1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-18 12:52:44 +01:00

cpu/stm32: use HSI with I2C

This commit is contained in:
Alexandre Abadie 2021-12-02 14:55:42 +01:00
parent 20ffa92ba3
commit cb5fef4486
No known key found for this signature in database
GPG Key ID: 1C919A403CAE1405
3 changed files with 75 additions and 142 deletions

View File

@ -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 <alexandre.abadie@inria.fr>
*/
#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 */
/** @} */

View File

@ -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
}

View File

@ -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]);
}