From 583b7e9b40b483828e7881f26c599e6bd7bc1211 Mon Sep 17 00:00:00 2001 From: Rogerio Goncalves Date: Tue, 29 Oct 2024 00:37:28 +0000 Subject: [PATCH] stm32: allow 400Khz in stm32f0_i2c.c (#6694) (#408) * stm32: allow 400Khz in stm32f0_i2c.c (#6694) Signed-off-by: Timofey Titovets * 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 commit hash: 8b7cc439529d727944589b751bd3a00305976bd0 --------- Signed-off-by: Timofey Titovets Co-authored-by: Timofey Titovets --- docs/Config_Reference.md | 5 +++-- src/stm32/stm32f0_i2c.c | 25 ++++++++++++++++++++----- src/stm32/stm32g4.c | 4 ++-- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/docs/Config_Reference.md b/docs/Config_Reference.md index eb99819c5..70fc9d804 100644 --- a/docs/Config_Reference.md +++ b/docs/Config_Reference.md @@ -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. ``` diff --git a/src/stm32/stm32f0_i2c.c b/src/stm32/stm32f0_i2c.c index 1382cd869..b83ceb0fc 100644 --- a/src/stm32/stm32f0_i2c.c +++ b/src/stm32/stm32f0_i2c.c @@ -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; } diff --git a/src/stm32/stm32g4.c b/src/stm32/stm32g4.c index 5255cb19a..6d6d1c0d3 100644 --- a/src/stm32/stm32g4.c +++ b/src/stm32/stm32g4.c @@ -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 @@ -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) ;