This is an automated email from the ASF dual-hosted git repository.

kasjer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git


The following commit(s) were added to refs/heads/master by this push:
     new a762010af mcu/stm32: Use I2C kernel clock for timing calculation
a762010af is described below

commit a762010afd70dab0d09f0c198d4375cfba8ca48e
Author: Jerzy Kasenberg <[email protected]>
AuthorDate: Sun Oct 18 15:43:13 2026 +0200

    mcu/stm32: Use I2C kernel clock for timing calculation
    
    When hic_timingr is not specified, I2C timing was computed from
    PCLK1. On many devices I2C has its own kernel clock that can come
    from different source (SYSCLK, HSI, PCLK3 on STM32H5, PCLK4 on
    STM32H7 I2C4) so computed timing could be wrong.
    
    This adds stm32_i2c_get_clock_freq() that returns frequency of the
    clock for given I2C instance using HAL_RCCEx_GetPeriphCLKFreq() where
    RCC provides it and falls back to PCLK1 otherwise.
    
    If neither hic_timingr nor hic_speed is set, 100kHz is used.
    
    get_pclk field is removed from STM32H5 I2C configuration together
    with its use in nucleo-h563zi and blackpill401cc BSPs, the
    STM32_I2Cx_GET_CLOCK_FREQ macros it referred to were never defined.
    
    Assisted-by: Claude:claude-opus-5-5
    Signed-off-by: Jerzy Kasenberg <[email protected]>
---
 hw/bsp/blackpill401cc/src/hal_bsp.c                |  3 --
 hw/bsp/nucleo-h563zi/src/hal_bsp.c                 |  4 ---
 .../stm32_common/include/stm32_common/stm32_hal.h  | 10 ++++++
 hw/mcu/stm/stm32_common/src/hal_i2c.c              | 42 +++++++++++++++++++++-
 .../stm32h5xx/include/mcu/stm32h5xx_mynewt_hal.h   |  1 -
 5 files changed, 51 insertions(+), 9 deletions(-)

diff --git a/hw/bsp/blackpill401cc/src/hal_bsp.c 
b/hw/bsp/blackpill401cc/src/hal_bsp.c
index ec6e51a6f..adbed9b33 100644
--- a/hw/bsp/blackpill401cc/src/hal_bsp.c
+++ b/hw/bsp/blackpill401cc/src/hal_bsp.c
@@ -118,7 +118,6 @@ const struct stm32_hal_i2c_cfg os_bsp_i2c0_cfg = {
     .hic_i2c = I2C1,
     .hic_rcc_reg = &RCC->APB1ENR,
     .hic_rcc_dev = RCC_APB1ENR_I2C1EN,
-    .get_pclk = STM32_I2C1_GET_CLOCK_FREQ,
     .hic_pin_sda = MYNEWT_VAL(I2C_0_PIN_SDA),
     .hic_pin_scl = MYNEWT_VAL(I2C_0_PIN_SCL),
     .hic_pin_af = GPIO_AF4_I2C1,
@@ -132,7 +131,6 @@ const struct stm32_hal_i2c_cfg os_bsp_i2c1_cfg = {
     .hic_i2c = I2C2,
     .hic_rcc_reg = &RCC->APB1ENR,
     .hic_rcc_dev = RCC_APB1ENR_I2C2EN,
-    .get_pclk = STM32_I2C2_GET_CLOCK_FREQ,
     .hic_pin_sda = MYNEWT_VAL(I2C_1_PIN_SDA),
     .hic_pin_scl = MYNEWT_VAL(I2C_1_PIN_SCL),
     .hic_pin_af = GPIO_AF4_I2C2,
@@ -146,7 +144,6 @@ const struct stm32_hal_i2c_cfg os_bsp_i2c2_cfg = {
     .hic_i2c = I2C3,
     .hic_rcc_reg = &RCC->APB1ENR,
     .hic_rcc_dev = RCC_APB1ENR_I2C3EN,
-    .get_pclk = STM32_I2C3_GET_CLOCK_FREQ,
     .hic_pin_sda = MYNEWT_VAL(I2C_2_PIN_SDA),
     .hic_pin_scl = MYNEWT_VAL(I2C_2_PIN_SCL),
     .hic_pin_af = GPIO_AF4_I2C3,
diff --git a/hw/bsp/nucleo-h563zi/src/hal_bsp.c 
b/hw/bsp/nucleo-h563zi/src/hal_bsp.c
index a9ab39881..a5fbc7435 100644
--- a/hw/bsp/nucleo-h563zi/src/hal_bsp.c
+++ b/hw/bsp/nucleo-h563zi/src/hal_bsp.c
@@ -114,7 +114,6 @@ const struct stm32_hal_i2c_cfg os_bsp_i2c0_cfg = {
     .hic_i2c = I2C1,
     .hic_rcc_reg = &RCC->APB1LENR,
     .hic_rcc_dev = RCC_APB1LENR_I2C1EN,
-    .get_pclk = STM32_I2C1_GET_CLOCK_FREQ,
     .hic_pin_sda = MYNEWT_VAL(I2C_0_PIN_SDA),
     .hic_pin_scl = MYNEWT_VAL(I2C_0_PIN_SCL),
     .hic_pin_af = GPIO_AF4_I2C1,
@@ -128,7 +127,6 @@ const struct stm32_hal_i2c_cfg os_bsp_i2c1_cfg = {
     .hic_i2c = I2C2,
     .hic_rcc_reg = &RCC->APB1LENR,
     .hic_rcc_dev = RCC_APB1LENR_I2C2EN,
-    .get_pclk = STM32_I2C2_GET_CLOCK_FREQ,
     .hic_pin_sda = MYNEWT_VAL(I2C_1_PIN_SDA),
     .hic_pin_scl = MYNEWT_VAL(I2C_1_PIN_SCL),
     .hic_pin_af = GPIO_AF4_I2C2,
@@ -142,7 +140,6 @@ const struct stm32_hal_i2c_cfg os_bsp_i2c2_cfg = {
     .hic_i2c = I2C3,
     .hic_rcc_reg = &RCC->APB1LENR,
     .hic_rcc_dev = RCC_APB1LENR_I2C3EN,
-    .get_pclk = STM32_I2C3_GET_CLOCK_FREQ,
     .hic_pin_sda = MYNEWT_VAL(I2C_2_PIN_SDA),
     .hic_pin_scl = MYNEWT_VAL(I2C_2_PIN_SCL),
     .hic_pin_af = GPIO_AF4_I2C3,
@@ -156,7 +153,6 @@ const struct stm32_hal_i2c_cfg os_bsp_i2c3_cfg = {
     .hic_i2c = I2C4,
     .hic_rcc_reg = &RCC->APB4ENR,
     .hic_rcc_dev = RCC_APB4ENR_I2C4EN,
-    .get_pclk = STM32_I2C4_GET_CLOCK_FREQ,
     .hic_pin_sda = MYNEWT_VAL(I2C_3_PIN_SDA),
     .hic_pin_scl = MYNEWT_VAL(I2C_3_PIN_SCL),
     .hic_pin_af = GPIO_AF4_I2C4,
diff --git a/hw/mcu/stm/stm32_common/include/stm32_common/stm32_hal.h 
b/hw/mcu/stm/stm32_common/include/stm32_common/stm32_hal.h
index 38b0b49de..cc51dfffe 100644
--- a/hw/mcu/stm/stm32_common/include/stm32_common/stm32_hal.h
+++ b/hw/mcu/stm/stm32_common/include/stm32_common/stm32_hal.h
@@ -41,6 +41,16 @@ extern "C" {
                  ((uint8_t)(MYNEWT_VAL(PWM_2) != 0)))
 
 uint32_t stm32_hal_timer_get_freq(void *timx);
+
+/**
+ * Get frequency of the clock that drives given I2C peripheral
+ *
+ * @param i2c I2C peripheral instance (I2C1, I2C2, ...)
+ *
+ * @return I2C kernel clock frequency in Hz
+ */
+uint32_t stm32_i2c_get_clock_freq(const I2C_TypeDef *i2c);
+
 void stm32_periph_create(void);
 
 int hal_gpio_init_stm(int pin, const GPIO_InitTypeDef *cfg);
diff --git a/hw/mcu/stm/stm32_common/src/hal_i2c.c 
b/hw/mcu/stm/stm32_common/src/hal_i2c.c
index 740e4956c..352a28dc9 100644
--- a/hw/mcu/stm/stm32_common/src/hal_i2c.c
+++ b/hw/mcu/stm/stm32_common/src/hal_i2c.c
@@ -100,6 +100,44 @@ i2c_reset(I2C_HandleTypeDef *hi2c)
 }
 #endif
 
+/*
+ * Returns frequency of the kernel clock of given I2C peripheral.
+ * On devices where I2C clock source is selectable in RCC, frequency is
+ * reported by HAL_RCCEx_GetPeriphCLKFreq(); if HAL does not report
+ * frequency for given instance, PCLK1 is assumed.
+ */
+uint32_t
+stm32_i2c_get_clock_freq(const I2C_TypeDef *i2c)
+{
+    uint32_t freq = 0;
+
+#if defined(I2C1) && defined(RCC_PERIPHCLK_I2C1)
+    if (i2c == I2C1) {
+        freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2C1);
+    }
+#endif
+#if defined(I2C2) && defined(RCC_PERIPHCLK_I2C2)
+    if (i2c == I2C2) {
+        freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2C2);
+    }
+#endif
+#if defined(I2C3) && defined(RCC_PERIPHCLK_I2C3)
+    if (i2c == I2C3) {
+        freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2C3);
+    }
+#endif
+#if defined(I2C4) && defined(RCC_PERIPHCLK_I2C4)
+    if (i2c == I2C4) {
+        freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2C4);
+    }
+#endif
+    if (freq == 0) {
+        freq = HAL_RCC_GetPCLK1Freq();
+    }
+
+    return freq;
+}
+
 #if !MYNEWT_VAL(STM32_HAL_I2C_HAS_CLOCKSPEED)
 #ifndef __LL_I2C_CONVERT_TIMINGS
 /* This is copy of macro from STM HAL for HALs that don't have it */
@@ -188,7 +226,9 @@ hal_i2c_init(uint8_t i2c_num, void *usercfg)
     if (cfg->hic_timingr) {
         init->Timing = cfg->hic_timingr;
     } else {
-        init->Timing = hal_i2c_timing(cfg->hic_speed, HAL_RCC_GetPCLK1Freq());
+        /* Standard mode if speed was not specified */
+        init->Timing = hal_i2c_timing(cfg->hic_speed ? cfg->hic_speed : 100000,
+                                      stm32_i2c_get_clock_freq(cfg->hic_i2c));
     }
 #else
     init->ClockSpeed = cfg->hic_speed;
diff --git a/hw/mcu/stm/stm32h5xx/include/mcu/stm32h5xx_mynewt_hal.h 
b/hw/mcu/stm/stm32h5xx/include/mcu/stm32h5xx_mynewt_hal.h
index 823eeca2a..11a04ae33 100644
--- a/hw/mcu/stm/stm32h5xx/include/mcu/stm32h5xx_mynewt_hal.h
+++ b/hw/mcu/stm/stm32h5xx/include/mcu/stm32h5xx_mynewt_hal.h
@@ -48,7 +48,6 @@ struct stm32_hal_i2c_cfg {
     I2C_TypeDef *hic_i2c;
     volatile uint32_t *hic_rcc_reg; /* RCC register to modify */
     uint32_t hic_rcc_dev;           /* RCC device ID */
-    uint32_t (*get_pclk)(void);
     uint8_t hic_pin_sda;
     uint8_t hic_pin_scl;
     uint8_t hic_pin_af;

Reply via email to