From cb5fef4486bedbc661d89c64669dc31c08334155 Mon Sep 17 00:00:00 2001 From: Alexandre Abadie Date: Thu, 2 Dec 2021 14:55:42 +0100 Subject: [PATCH] cpu/stm32: use HSI with I2C --- cpu/stm32/include/cpu_conf_stm32_common.h | 125 ---------------------- cpu/stm32/include/periph/cpu_i2c.h | 62 ++++++++--- cpu/stm32/periph/i2c_1.c | 30 +++++- 3 files changed, 75 insertions(+), 142 deletions(-) delete mode 100644 cpu/stm32/include/cpu_conf_stm32_common.h diff --git a/cpu/stm32/include/cpu_conf_stm32_common.h b/cpu/stm32/include/cpu_conf_stm32_common.h deleted file mode 100644 index bc0875d1dd..0000000000 --- a/cpu/stm32/include/cpu_conf_stm32_common.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2018 Inria - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_stm32 - * @{ - * - * @file - * @brief Shared CPU specific configuration for STM32 family - * - * @author Alexandre Abadie - */ - -#ifndef CPU_CONF_STM32_COMMON_H -#define CPU_CONF_STM32_COMMON_H - -#include "periph_cpu.h" - -#include "periph/i2c.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3) || \ - defined(CPU_FAM_STM32F7) || defined(CPU_FAM_STM32L0) || \ - defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32L4) || \ - defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32G4) || \ - defined(CPU_FAM_STM32G0) || defined(CPU_FAM_STM32L5) || \ - defined(CPU_FAM_STM32U5) || defined(CPU_FAM_STM32WL) - -/** - * @brief Timing register settings - * - * @ref i2c_timing_param_t - */ -static const i2c_timing_param_t timing_params[] = { -#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F7) || \ - defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB) || \ - defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32G0) || \ - defined(CPU_FAM_STM32L5) || defined(CPU_FAM_STM32U5) || \ - defined(CPU_FAM_STM32WL) - [ I2C_SPEED_NORMAL ] = { - .presc = 0xB, - .scll = 0x13, /* t_SCLL = 5.0us */ - .sclh = 0xF, /* t_SCLH = 4.0us */ - .sdadel = 0x2, /* t_SDADEL = 500ns */ - .scldel = 0x4, /* t_SCLDEL = 1250ns */ - }, - [ I2C_SPEED_FAST ] = { - .presc = 5, - .scll = 0x9, /* t_SCLL = 1250ns */ - .sclh = 0x3, /* t_SCLH = 500ns */ - .sdadel = 0x3, /* t_SDADEL = 375ns */ - .scldel = 0x3, /* t_SCLDEL = 500ns */ - }, - [ I2C_SPEED_FAST_PLUS ] = { - .presc = 5, - .scll = 0x3, /* t_SCLL = 500ns */ - .sclh = 0x1, /* t_SCLH = 250ns */ - .sdadel = 0x0, /* t_SDADEL = 0ns */ - .scldel = 0x1, /* t_SCLDEL = 250ns */ - } -#elif defined(CPU_FAM_STM32F3) - [ I2C_SPEED_NORMAL ] = { - .presc = 1, - .scll = 0x13, /* t_SCLL = 5.0us */ - .sclh = 0xF, /* t_SCLH = 4.0us */ - .sdadel = 0x2, /* t_SDADEL = 500ns */ - .scldel = 0x4, /* t_SCLDEL = 1250ns */ - }, - [ I2C_SPEED_FAST ] = { - .presc = 0, - .scll = 0x9, /* t_SCLL = 1250ns */ - .sclh = 0x3, /* t_SCLH = 500ns */ - .sdadel = 0x1, /* t_SDADEL = 125ns */ - .scldel = 0x3, /* t_SCLDEL = 500ns */ - }, - [ I2C_SPEED_FAST_PLUS ] = { - .presc = 0, - .scll = 0x6, /* t_SCLL = 875ns */ - .sclh = 0x3, /* t_SCLH = 500ns */ - .sdadel = 0x0, /* t_SDADEL = 0ns */ - .scldel = 0x1, /* t_SCLDEL = 250ns */ - } -#elif defined(CPU_FAM_STM32L0) - [ I2C_SPEED_NORMAL ] = { - .presc = 1, - .scll = 0x56, /* t_SCLL = 5.0us */ - .sclh = 0x3E, /* t_SCLH = 4.0us */ - .sdadel = 0x1, /* t_SDADEL = 500ns */ - .scldel = 0xA, /* t_SCLDEL = 1250ns */ - }, - [ I2C_SPEED_FAST ] = { - .presc = 0, - .scll = 0x2E, /* t_SCLL = 1250ns */ - .sclh = 0x11, /* t_SCLH = 500ns */ - .sdadel = 0x1, /* t_SDADEL = 125ns */ - .scldel = 0xB, /* t_SCLDEL = 500ns */ - }, - [ I2C_SPEED_FAST_PLUS ] = { - .presc = 0, - .scll = 0x6, /* t_SCLL = 875ns */ - .sclh = 0x3, /* t_SCLH = 500ns */ - .sdadel = 0x0, /* t_SDADEL = 0ns */ - .scldel = 0x1, /* t_SCLDEL = 250ns */ - } -#endif -}; - -#endif /* CPU_FAM_STM32F0 || CPU_FAM_STM32F3 || CPU_FAM_STM32F7 || - CPU_FAM_STM32L0 || CPU_FAM_STM32L4 || CPU_FAM_STM32WB || - CPU_FAM_STM32G4 || CPU_FAM_STM32G0 || CPU_FAM_STM32L5 */ - -#ifdef __cplusplus -} -#endif - -#endif /* CPU_CONF_STM32_COMMON_H */ -/** @} */ diff --git a/cpu/stm32/include/periph/cpu_i2c.h b/cpu/stm32/include/periph/cpu_i2c.h index 76e6c709bb..43db873389 100644 --- a/cpu/stm32/include/periph/cpu_i2c.h +++ b/cpu/stm32/include/periph/cpu_i2c.h @@ -88,7 +88,11 @@ typedef struct { #endif uint8_t bus; /**< APB bus */ uint32_t rcc_mask; /**< bit in clock enable register */ -#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3) +#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3) || \ + defined(CPU_FAM_STM32F7) || defined(CPU_FAM_STM32G0) || \ + defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32L4) || \ + defined(CPU_FAM_STM32L5) || defined(CPU_FAM_STM32WB) || \ + defined(CPU_FAM_STM32U5) || defined(CPU_FAM_STM32WL) uint32_t rcc_sw_mask; /**< bit to switch I2C clock */ #endif #if defined(CPU_FAM_STM32F1) || defined(CPU_FAM_STM32F2) || \ @@ -101,20 +105,12 @@ typedef struct { #if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3) || \ defined(CPU_FAM_STM32F7) || defined(CPU_FAM_STM32L0) || \ - defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB) || \ - defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32G0) || \ - defined(CPU_FAM_STM32L5) || defined(CPU_FAM_STM32U5) || \ + defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32L5) || \ + defined(CPU_FAM_STM32G0) || defined(CPU_FAM_STM32G4) || \ + defined(CPU_FAM_STM32U5) || defined(CPU_FAM_STM32WB) || \ defined(CPU_FAM_STM32WL) /** * @brief Structure for I2C timing register settings - * - * These parameters are valid for 48MHz (16MHz for L0) input clock. - * See reference manual of supported CPU for example of timing settings: - * - STM32F030/F070: see RM0360, section 22.4.10, p.560, table 76 - * - STM32F303: see RM0316, section 28.4.9, p.849, table 148 - * - STM32F72X: see RM0431, section 26.4.9, p.851, table 149 - * - STM32L0x2: see RM0376, section 27.4.10, p.686, table 117 - * - STM32L4X5/6: see RM0351, section 39.4.9, p.1297, table 234 */ typedef struct { uint8_t presc; /**< Timing prescaler value */ @@ -123,7 +119,47 @@ typedef struct { uint8_t sdadel; /**< Data hold time */ uint8_t scldel; /**< Data setup time */ } i2c_timing_param_t; -#endif + +/** + * @brief Timing register settings + * + * These parameters are valid for HSI16 input clock. + * See reference manual of supported CPU for example of timing settings: + * - STM32F030/F070: see RM0360, section 22.4.10, p.560, table 76 + * - STM32F303: see RM0316, section 28.4.9, p.849, table 148 + * - STM32F72X: see RM0431, section 26.4.9, p.851, table 149 + * - STM32L0x2: see RM0376, section 27.4.10, p.686, table 117 + * - STM32L4X5/6: see RM0351, section 39.4.9, p.1297, table 234 + * + * @ref i2c_timing_param_t + */ +static const i2c_timing_param_t timing_params[] = { + [ I2C_SPEED_NORMAL ] = { + .presc = 3, + .scll = 0x13, /* t_SCLL = 5.0us */ + .sclh = 0xF, /* t_SCLH = 4.0us */ + .sdadel = 0x2, /* t_SDADEL = 500ns */ + .scldel = 0x4, /* t_SCLDEL = 1250ns */ + }, + [ I2C_SPEED_FAST ] = { + .presc = 1, + .scll = 0x9, /* t_SCLL = 1250ns */ + .sclh = 0x3, /* t_SCLH = 500ns */ + .sdadel = 0x2, /* t_SDADEL = 250ns */ + .scldel = 0x3, /* t_SCLDEL = 500ns */ + }, + [ I2C_SPEED_FAST_PLUS ] = { + .presc = 0, + .scll = 0x4, /* t_SCLL = 312.5ns */ + .sclh = 0x2, /* t_SCLH = 187.5ns */ + .sdadel = 0x0, /* t_SDADEL = 0ns */ + .scldel = 0x2, /* t_SCLDEL = 187.5ns */ + } +}; +#endif /* CPU_FAM_STM32F0 || CPU_FAM_STM32F3 || CPU_FAM_STM32F7 || + CPU_FAM_STM32L0 || CPU_FAM_STM32L4 || CPU_FAM_STM32L5 || + CPU_FAM_STM32G0 || CPU_FAM_STM32G4 || CPU_FAM_STM32U5 || + CPU_FAM_STM32WB || CPU_FAM_STM32WL */ #ifdef __cplusplus } diff --git a/cpu/stm32/periph/i2c_1.c b/cpu/stm32/periph/i2c_1.c index d30cc27b3e..cbb2f3fd2b 100644 --- a/cpu/stm32/periph/i2c_1.c +++ b/cpu/stm32/periph/i2c_1.c @@ -41,7 +41,7 @@ #include "byteorder.h" #include "panic.h" -#include "cpu_conf_stm32_common.h" +#include "stmclk.h" #include "periph/i2c.h" #include "periph/gpio.h" @@ -59,6 +59,18 @@ #define CLEAR_FLAG (I2C_ICR_NACKCF | I2C_ICR_ARLOCF | I2C_ICR_BERRCF | I2C_ICR_ADDRCF) +#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3) +#define I2C_CLOCK_SRC_REG (RCC->CFGR3) +#elif defined(RCC_CCIPR_I2C1SEL) +#define I2C_CLOCK_SRC_REG (RCC->CCIPR) +#elif defined(RCC_CCIPR1_I2C1SEL) +#define I2C_CLOCK_SRC_REG (RCC->CCIPR1) +#elif defined(RCC_DCKCFGR2_I2C1SEL) +#define I2C_CLOCK_SRC_REG (RCC->DCKCFGR2) +#endif + +static uint32_t hsi_state; + /* static function definitions */ static inline void _i2c_init(I2C_TypeDef *i2c, uint32_t timing); static int _write(I2C_TypeDef *i2c, uint16_t addr, const void *data, @@ -87,9 +99,11 @@ void i2c_init(i2c_t dev) NVIC_SetPriority(i2c_config[dev].irqn, I2C_IRQ_PRIO); NVIC_EnableIRQ(i2c_config[dev].irqn); -#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3) - /* Set I2CSW bits to enable I2C clock source */ - RCC->CFGR3 |= i2c_config[dev].rcc_sw_mask; +#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3) || \ + defined(CPU_FAM_STM32F7) || defined(CPU_FAM_STM32L4) || \ + defined(CPU_FAM_STM32L5) || defined(CPU_FAM_STM32WB) + /* select I2C clock source */ + I2C_CLOCK_SRC_REG |= i2c_config[dev].rcc_sw_mask; #endif DEBUG("[i2c] init: configuring pins\n"); @@ -141,6 +155,11 @@ void i2c_acquire(i2c_t dev) assert(dev < I2C_NUMOF); mutex_lock(&locks[dev]); + hsi_state = (RCC->CR & RCC_CR_HSION); + if (!hsi_state) { + /* the internal RC oscillator (HSI) must be enabled */ + stmclk_enable_hsi(); + } periph_clk_en(i2c_config[dev].bus, i2c_config[dev].rcc_mask); @@ -158,6 +177,9 @@ void i2c_release(i2c_t dev) _wait_for_bus(i2c_config[dev].dev); periph_clk_dis(i2c_config[dev].bus, i2c_config[dev].rcc_mask); + if (!hsi_state) { + stmclk_disable_hsi(); + } mutex_unlock(&locks[dev]); }