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

jerzy 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 c801bb603 mcu/stm32: Calculate I2C timing register
c801bb603 is described below

commit c801bb6038620205ef9d933e875b54a146126254
Author: Jerzy Kasenberg <[email protected]>
AuthorDate: Wed Nov 22 14:34:45 2023 +0100

    mcu/stm32: Calculate I2C timing register
    
    STM32 F1,F4,L1 do have ClockSpeed filed in I2C initialization API,
    so it easy to specify requested clock speed for I2C.
    For all other devices ST HAL does not provide such field and
    expect that TIMINGR register value is precomputed.
    This value is specified in each BSP and is likely incorrect
    for some of them.
    
    This change introduces hic_speed to MCUs that has timing register and
    function that computes timing register base on requested speed and system
    clock.
    
    If timing register is specified in settings it is still being used to
    to configure I2C. If timing register setting is 0 hic_speed is used.
    
    Signed-off-by: Jerzy Kasenberg <[email protected]>
---
 hw/mcu/stm/stm32_common/src/hal_i2c.c              | 74 +++++++++++++++++++++-
 .../stm32f0xx/include/mcu/stm32f0xx_mynewt_hal.h   |  1 +
 .../stm32f3xx/include/mcu/stm32f3xx_mynewt_hal.h   |  1 +
 .../stm32f7xx/include/mcu/stm32f7xx_mynewt_hal.h   |  1 +
 .../stm32h7xx/include/mcu/stm32h7xx_mynewt_hal.h   |  1 +
 .../stm32l0xx/include/mcu/stm32l0xx_mynewt_hal.h   |  1 +
 .../stm32l4xx/include/mcu/stm32l4xx_mynewt_hal.h   |  1 +
 .../stm32u5xx/include/mcu/stm32u5xx_mynewt_hal.h   |  1 +
 .../stm32wbxx/include/mcu/stm32wbxx_mynewt_hal.h   |  1 +
 9 files changed, 81 insertions(+), 1 deletion(-)

diff --git a/hw/mcu/stm/stm32_common/src/hal_i2c.c 
b/hw/mcu/stm/stm32_common/src/hal_i2c.c
index cacf29c39..59d1bf1d1 100644
--- a/hw/mcu/stm/stm32_common/src/hal_i2c.c
+++ b/hw/mcu/stm/stm32_common/src/hal_i2c.c
@@ -98,6 +98,73 @@ i2c_reset(I2C_HandleTypeDef *hi2c)
 }
 #endif
 
+#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 */
+#define __LL_I2C_CONVERT_TIMINGS(__PRESCALER__, __SETUP_TIME__, __HOLD_TIME__, 
__SCLH_PERIOD__, __SCLL_PERIOD__) \
+    ((((uint32_t)(__PRESCALER__) << I2C_TIMINGR_PRESC_Pos) & 
I2C_TIMINGR_PRESC) | \
+     (((uint32_t)(__SETUP_TIME__) << I2C_TIMINGR_SCLDEL_Pos) & 
I2C_TIMINGR_SCLDEL) | \
+     (((uint32_t)(__HOLD_TIME__) << I2C_TIMINGR_SDADEL_Pos) & 
I2C_TIMINGR_SDADEL) | \
+     (((uint32_t)(__SCLH_PERIOD__) << I2C_TIMINGR_SCLH_Pos) & 
I2C_TIMINGR_SCLH) | \
+     (((uint32_t)(__SCLL_PERIOD__) << I2C_TIMINGR_SCLL_Pos) & 
I2C_TIMINGR_SCLL))
+#endif
+
+static uint32_t
+hal_i2c_timing(uint32_t i2c_speed, uint32_t clock)
+{
+    uint32_t i2c_hold_time_min, i2c_setup_time_min;
+    uint32_t i2c_h_min_time, i2c_l_min_time;
+    uint32_t presc;
+    uint32_t timing = 0U;
+
+    /* Timings from I2S specification for standard/fast/fast+ */
+    if (i2c_speed < 400000) {
+        i2c_h_min_time = 4000U;
+        i2c_l_min_time = 4700U;
+        i2c_hold_time_min = 500U;
+        i2c_setup_time_min = 1250U;
+    } else if (i2c_speed < 1000000) {
+        i2c_h_min_time = 600U;
+        i2c_l_min_time = 1300U;
+        i2c_hold_time_min = 375U;
+        i2c_setup_time_min = 500U;
+    } else {
+        i2c_h_min_time = 260U;
+        i2c_l_min_time = 500U;
+        i2c_hold_time_min = 130U;
+        i2c_setup_time_min = 50U;
+    }
+    uint32_t clock_khz = clock / 1000;
+    presc = ((i2c_h_min_time * clock_khz / 1000) + 255999) / 256000;
+    uint32_t presc_max = ((i2c_l_min_time * clock_khz / 1000) + 255999) / 
256000;
+    presc = max(presc, presc_max);
+    presc_max = ((i2c_hold_time_min * clock_khz / 1000) + 14999) / 15000;
+    presc = max(presc, presc_max);
+    presc_max = ((i2c_setup_time_min * clock_khz / 1000) + 15999) / 16000;
+    presc = max(presc, presc_max);
+
+    if (presc <= 16) {
+        uint32_t t_presc = clock / presc;
+        uint32_t ns_presc = 1000000000 / t_presc;
+        uint32_t sclh = (i2c_h_min_time + ns_presc - 1) / ns_presc;
+        uint32_t scll = (i2c_l_min_time + ns_presc - 1) / ns_presc;
+        uint32_t sdadel = (i2c_hold_time_min + ns_presc - 1) / ns_presc;
+        uint32_t scldel = (i2c_setup_time_min + ns_presc - 1) / ns_presc;
+
+        uint32_t scl_h_l = (t_presc / i2c_speed) - 5;
+        if (scl_h_l > sclh + scll) {
+            uint32_t scl_h_l_fill = scl_h_l - (sclh + scll);
+            scll += scl_h_l_fill / 2;
+            sclh += (scl_h_l_fill + 1) / 2;
+        }
+        timing = __LL_I2C_CONVERT_TIMINGS(presc - 1,
+                                          scldel - 1, sdadel, sclh - 1, scll - 
1);
+    }
+
+    return timing;
+}
+#endif
+
 int
 hal_i2c_init(uint8_t i2c_num, void *usercfg)
 {
@@ -116,7 +183,11 @@ hal_i2c_init(uint8_t i2c_num, void *usercfg)
     init = &dev->hid_handle.Init;
     dev->hid_handle.Instance = cfg->hic_i2c;
 #if !MYNEWT_VAL(STM32_HAL_I2C_HAS_CLOCKSPEED)
-    init->Timing = cfg->hic_timingr;
+    if (cfg->hic_timingr) {
+        init->Timing = cfg->hic_timingr;
+    } else {
+        init->Timing = hal_i2c_timing(cfg->hic_speed, HAL_RCC_GetPCLK1Freq());
+    }
 #else
     init->ClockSpeed = cfg->hic_speed;
 #endif
@@ -258,3 +329,4 @@ hal_i2c_master_probe(uint8_t i2c_num, uint8_t address, 
uint32_t timo)
 
     return rc;
 }
+
diff --git a/hw/mcu/stm/stm32f0xx/include/mcu/stm32f0xx_mynewt_hal.h 
b/hw/mcu/stm/stm32f0xx/include/mcu/stm32f0xx_mynewt_hal.h
index b120b67c5..de8931cde 100644
--- a/hw/mcu/stm/stm32f0xx/include/mcu/stm32f0xx_mynewt_hal.h
+++ b/hw/mcu/stm/stm32f0xx/include/mcu/stm32f0xx_mynewt_hal.h
@@ -56,6 +56,7 @@ struct stm32_hal_i2c_cfg {
     uint8_t hic_pin_af;
     uint8_t hic_10bit;
     uint32_t hic_timingr;               /* TIMINGR register */
+    uint32_t hic_speed;                 /* Requested speed (used when 
hic_timingr is 0) */
 };
 
 #ifdef __cplusplus
diff --git a/hw/mcu/stm/stm32f3xx/include/mcu/stm32f3xx_mynewt_hal.h 
b/hw/mcu/stm/stm32f3xx/include/mcu/stm32f3xx_mynewt_hal.h
index 104b3c31d..868efca6f 100644
--- a/hw/mcu/stm/stm32f3xx/include/mcu/stm32f3xx_mynewt_hal.h
+++ b/hw/mcu/stm/stm32f3xx/include/mcu/stm32f3xx_mynewt_hal.h
@@ -56,6 +56,7 @@ struct stm32_hal_i2c_cfg {
     uint8_t hic_pin_af;
     uint8_t hic_10bit;
     uint32_t hic_timingr;               /* TIMINGR register */
+    uint32_t hic_speed;                 /* Requested speed (used when 
hic_timingr is 0) */
 };
 
 #ifdef __cplusplus
diff --git a/hw/mcu/stm/stm32f7xx/include/mcu/stm32f7xx_mynewt_hal.h 
b/hw/mcu/stm/stm32f7xx/include/mcu/stm32f7xx_mynewt_hal.h
index 0cd772151..a9f2321ea 100644
--- a/hw/mcu/stm/stm32f7xx/include/mcu/stm32f7xx_mynewt_hal.h
+++ b/hw/mcu/stm/stm32f7xx/include/mcu/stm32f7xx_mynewt_hal.h
@@ -57,6 +57,7 @@ struct stm32_hal_i2c_cfg {
     uint8_t hic_pin_af;
     uint8_t hic_10bit;
     uint32_t hic_timingr;               /* TIMINGR register */
+    uint32_t hic_speed;                 /* Requested speed (used when 
hic_timingr is 0) */
 };
 
 #ifdef __cplusplus
diff --git a/hw/mcu/stm/stm32h7xx/include/mcu/stm32h7xx_mynewt_hal.h 
b/hw/mcu/stm/stm32h7xx/include/mcu/stm32h7xx_mynewt_hal.h
index dc17d6fe1..fd6f5ea1c 100644
--- a/hw/mcu/stm/stm32h7xx/include/mcu/stm32h7xx_mynewt_hal.h
+++ b/hw/mcu/stm/stm32h7xx/include/mcu/stm32h7xx_mynewt_hal.h
@@ -57,6 +57,7 @@ struct stm32_hal_i2c_cfg {
     uint8_t hic_pin_af;
     uint8_t hic_10bit;
     uint32_t hic_timingr;               /* TIMINGR register */
+    uint32_t hic_speed;                 /* Requested speed (used when 
hic_timingr is 0) */
 };
 
 #ifdef __cplusplus
diff --git a/hw/mcu/stm/stm32l0xx/include/mcu/stm32l0xx_mynewt_hal.h 
b/hw/mcu/stm/stm32l0xx/include/mcu/stm32l0xx_mynewt_hal.h
index 75a7bef2d..50f18b7d0 100644
--- a/hw/mcu/stm/stm32l0xx/include/mcu/stm32l0xx_mynewt_hal.h
+++ b/hw/mcu/stm/stm32l0xx/include/mcu/stm32l0xx_mynewt_hal.h
@@ -57,6 +57,7 @@ struct stm32_hal_i2c_cfg {
     uint8_t hic_pin_af;
     uint8_t hic_10bit;
     uint32_t hic_timingr;               /* TIMINGR register */
+    uint32_t hic_speed;                 /* Requested speed (used when 
hic_timingr is 0) */
 };
 
 #ifdef __cplusplus
diff --git a/hw/mcu/stm/stm32l4xx/include/mcu/stm32l4xx_mynewt_hal.h 
b/hw/mcu/stm/stm32l4xx/include/mcu/stm32l4xx_mynewt_hal.h
index 292dade41..6cec1fdc6 100644
--- a/hw/mcu/stm/stm32l4xx/include/mcu/stm32l4xx_mynewt_hal.h
+++ b/hw/mcu/stm/stm32l4xx/include/mcu/stm32l4xx_mynewt_hal.h
@@ -57,6 +57,7 @@ struct stm32_hal_i2c_cfg {
     uint8_t hic_pin_af;
     uint8_t hic_10bit;
     uint32_t hic_timingr;               /* TIMINGR register */
+    uint32_t hic_speed;                 /* Requested speed (used when 
hic_timingr is 0) */
 };
 
 #ifdef __cplusplus
diff --git a/hw/mcu/stm/stm32u5xx/include/mcu/stm32u5xx_mynewt_hal.h 
b/hw/mcu/stm/stm32u5xx/include/mcu/stm32u5xx_mynewt_hal.h
index 1709bf9fe..c403d44c4 100644
--- a/hw/mcu/stm/stm32u5xx/include/mcu/stm32u5xx_mynewt_hal.h
+++ b/hw/mcu/stm/stm32u5xx/include/mcu/stm32u5xx_mynewt_hal.h
@@ -57,6 +57,7 @@ struct stm32_hal_i2c_cfg {
     uint8_t hic_pin_af;
     uint8_t hic_10bit;
     uint32_t hic_timingr;               /* TIMINGR register */
+    uint32_t hic_speed;                 /* Requested speed (used when 
hic_timingr is 0) */
 };
 
 #ifdef __cplusplus
diff --git a/hw/mcu/stm/stm32wbxx/include/mcu/stm32wbxx_mynewt_hal.h 
b/hw/mcu/stm/stm32wbxx/include/mcu/stm32wbxx_mynewt_hal.h
index 71313f377..752265768 100644
--- a/hw/mcu/stm/stm32wbxx/include/mcu/stm32wbxx_mynewt_hal.h
+++ b/hw/mcu/stm/stm32wbxx/include/mcu/stm32wbxx_mynewt_hal.h
@@ -57,6 +57,7 @@ struct stm32_hal_i2c_cfg {
     uint8_t hic_pin_af;
     uint8_t hic_10bit;
     uint32_t hic_timingr;               /* TIMINGR register */
+    uint32_t hic_speed;                 /* Requested speed (used when 
hic_timingr is 0) */
 };
 
 #ifdef __cplusplus

Reply via email to