Skip to content

Commit

Permalink
stm32: allow 400Khz in stm32f0_i2c.c (#6694) (#408)
Browse files Browse the repository at this point in the history
* stm32: allow 400Khz in stm32f0_i2c.c (#6694)

Signed-off-by: Timofey Titovets <nefelim4ag@gmail.com>

* stm32: Reduce peripheral clock speed on stm32g4 chips

A 170mhz (or 150mhz) peripheral clock is too fast for some peripherals.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>

commit hash: 8b7cc439529d727944589b751bd3a00305976bd0

---------

Signed-off-by: Timofey Titovets <nefelim4ag@gmail.com>
Co-authored-by: Timofey Titovets <nefelim4ag@gmail.com>
  • Loading branch information
rogerlz and nefelim4ag authored Oct 29, 2024
1 parent d0eff55 commit 583b7e9
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 9 deletions.
5 changes: 3 additions & 2 deletions docs/Config_Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -5875,8 +5875,9 @@ Most Klipper micro-controller implementations only support an
micro-controller supports a 400000 speed (_fast mode_, 400kbit/s), but it must be
[set in the operating system](RPi_microcontroller.md#optional-enabling-i2c)
and the `i2c_speed` parameter is otherwise ignored. The Klipper
"RP2040" micro-controller and ATmega AVR family support a rate of 400000
via the `i2c_speed` parameter. All other Klipper micro-controllers use a
"RP2040" micro-controller and ATmega AVR family and some STM32
(F0, G0, G4, L4, F7, H7) support a rate of 400000 via the `i2c_speed` parameter.
All other Klipper micro-controllers use a
100000 rate and ignore the `i2c_speed` parameter.

```
Expand Down
25 changes: 20 additions & 5 deletions src/stm32/stm32f0_i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,26 @@ i2c_setup(uint32_t bus, uint32_t rate, uint8_t addr)
gpio_peripheral(ii->sda_pin, ii->function | GPIO_OPEN_DRAIN, 1);

// Set 100Khz frequency and enable
i2c->TIMINGR = ((0xB << I2C_TIMINGR_PRESC_Pos)
| (0x13 << I2C_TIMINGR_SCLL_Pos)
| (0xF << I2C_TIMINGR_SCLH_Pos)
| (0x2 << I2C_TIMINGR_SDADEL_Pos)
| (0x4 << I2C_TIMINGR_SCLDEL_Pos));
uint32_t nom_i2c_clock = 8000000; // 8mhz internal clock = 125ns ticks
uint32_t scll = 40; // 40 * 125ns = 5us
uint32_t sclh = 32; // 32 * 125ns = 4us
uint32_t sdadel = 4; // 4 * 125ns = 500ns
uint32_t scldel = 10; // 10 * 125ns = 1250ns
// Clamp the rate to 400Khz
if (rate >= 400000) {
scll = 10; // 10 * 125ns = 1250ns
sclh = 4; // 4 * 125 = 500ns
sdadel = 3; // 3 * 125 = 375ns
scldel = 4; // 4 * 125 = 500ns
}

uint32_t pclk = get_pclock_frequency((uint32_t)i2c);
uint32_t presc = DIV_ROUND_UP(pclk, nom_i2c_clock);
i2c->TIMINGR = (((presc - 1) << I2C_TIMINGR_PRESC_Pos)
| ((scll - 1) << I2C_TIMINGR_SCLL_Pos)
| ((sclh - 1) << I2C_TIMINGR_SCLH_Pos)
| (sdadel << I2C_TIMINGR_SDADEL_Pos)
| ((scldel - 1) << I2C_TIMINGR_SCLDEL_Pos));
i2c->CR1 = I2C_CR1_PE;
}

Expand Down
4 changes: 2 additions & 2 deletions src/stm32/stm32g4.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#include "internal.h" // enable_pclock
#include "sched.h" // sched_main

#define FREQ_PERIPH_DIV 1
#define FREQ_PERIPH_DIV 2
#define FREQ_PERIPH (CONFIG_CLOCK_FREQ / FREQ_PERIPH_DIV)

// Map a peripheral address to its enable bits
Expand Down Expand Up @@ -142,7 +142,7 @@ clock_setup(void)
RCC->PLLCFGR |= RCC_PLLCFGR_PLLREN;

// Switch system clock to PLL
RCC->CFGR = RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE1_DIV1 | RCC_CFGR_PPRE2_DIV1
RCC->CFGR = RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE1_DIV2 | RCC_CFGR_PPRE2_DIV2
| RCC_CFGR_SW_PLL;
while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_PLL)
;
Expand Down

0 comments on commit 583b7e9

Please sign in to comment.