Skip to content

Commit

Permalink
cpu/stm32: allow arbitrary I2C clocks
Browse files Browse the repository at this point in the history
This adds support for using arbitrary I2C clock speeds for the I2C
peripheral implemented in i2c_2.c. The other variant implemented in
i2c_1.c already supported this.

As a nice side effect the API now is the same on an ABI level and we
no longer need to different `i2c_clock_t`.
  • Loading branch information
maribu committed Mar 18, 2024
1 parent 4850881 commit 8a19639
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 51 deletions.
72 changes: 37 additions & 35 deletions cpu/stm32/include/periph/cpu_i2c.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,23 @@
#include <stdint.h>

#include "cpu.h"
#include "macros/units.h"
#include "periph/cpu_gpio.h"

#ifdef __cplusplus
extern "C" {
#endif

#ifdef DOXYGEN
/**
* @brief Which I2C peripheral variant is used
*
* If defined as `1` the variant implemented in `i2c_1.c` is used, if
* defined as `2` the variant implemented in `i2c_2.c` is used.
*/
#define STM32_I2C_VARIANT /* <1 or 2> */
#endif

/**
* @name Use the shared I2C functions
* @{
Expand All @@ -40,37 +51,43 @@ extern "C" {
#define PERIPH_I2C_NEED_WRITE_REG
/** Use read regs function from periph common */
#define PERIPH_I2C_NEED_READ_REGS
#if defined(CPU_FAM_STM32F1) || defined(CPU_FAM_STM32F2) || \
defined(CPU_FAM_STM32L1) || defined(CPU_FAM_STM32F4) || \
defined(CPU_FAM_STM32MP1)
#if STM32_I2C_VARIANT == 2

Check failure on line 54 in cpu/stm32/include/periph/cpu_i2c.h

View workflow job for this annotation

GitHub Actions / static-tests

preprocessing issue while doing constant expression evaluation: syntax error: input=' == 2'
/** Use write regs function from periph common */
#define PERIPH_I2C_NEED_WRITE_REGS
# define PERIPH_I2C_NEED_WRITE_REGS
#endif
/** @} */

#ifndef DOXYGEN
#ifdef I2C_CR1_ANFOFF
/* i2c_1.c is used */
# define STM32_I2C_VARIANT 1
#else
/* i2c_2.c is used */
# define STM32_I2C_VARIANT 2
#endif

/**
* @brief Default mapping of I2C bus speed values
* @{
*/
#define HAVE_I2C_SPEED_T
#if STM32_I2C_VARIANT == 1
/* i2c_1.c */
typedef enum {
#if defined(CPU_FAM_STM32F1) || defined(CPU_FAM_STM32F2) || \
defined(CPU_FAM_STM32F4) || defined(CPU_FAM_STM32L1) || \
defined(CPU_FAM_STM32MP1)
I2C_SPEED_LOW, /**< low speed mode: ~10kit/s */
#endif
I2C_SPEED_NORMAL, /**< normal mode: ~100kbit/s */
I2C_SPEED_FAST, /**< fast mode: ~400kbit/s */
#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_STM32WL) || defined(CPU_FAM_STM32C0)
I2C_SPEED_FAST_PLUS, /**< fast plus mode: ~1Mbit/s */
#endif
} i2c_speed_t;
#elif STM32_I2C_VARIANT == 2
/* i2c_2.c */
typedef enum {
I2C_SPEED_LOW = KHZ(1), /**< low speed mode: ~10kit/s */
I2C_SPEED_NORMAL = KHZ(100), /**< normal mode: ~100kbit/s */
I2C_SPEED_FAST = KHZ(400), /**< fast mode: ~400kbit/s */
I2C_SPEED_FAST_PLUS = MHZ(1), /**< fast plus mode: ~1Mbit/s */
} i2c_speed_t;
#endif /* STM32_I2C_VARIANT */
/** @} */
#endif /* ndef DOXYGEN */

Expand All @@ -96,20 +113,13 @@ typedef struct {
defined(CPU_FAM_STM32C0)
uint32_t rcc_sw_mask; /**< bit to switch I2C clock */
#endif
#if defined(CPU_FAM_STM32F1) || defined(CPU_FAM_STM32F2) || \
defined(CPU_FAM_STM32F4) || defined(CPU_FAM_STM32L1) || \
defined(CPU_FAM_STM32MP1)
#if STM32_I2C_VARIANT == 2

Check failure on line 116 in cpu/stm32/include/periph/cpu_i2c.h

View workflow job for this annotation

GitHub Actions / static-tests

preprocessing issue while doing constant expression evaluation: syntax error: input=' == 2'
uint32_t clk; /**< bus frequency as defined in board config */
#endif
uint8_t irqn; /**< I2C event interrupt number */
} i2c_conf_t;

#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3) || \
defined(CPU_FAM_STM32F7) || defined(CPU_FAM_STM32L0) || \
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) || defined(CPU_FAM_STM32C0)
#if STM32_I2C_VARIANT == 1

Check failure on line 122 in cpu/stm32/include/periph/cpu_i2c.h

View workflow job for this annotation

GitHub Actions / static-tests

preprocessing issue while doing constant expression evaluation: syntax error: input=' == 1'
/**
* @brief Structure for I2C timing register settings
*/
Expand Down Expand Up @@ -157,23 +167,15 @@ static const i2c_timing_param_t timing_params[] = {
.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 || CPU_FAM_STM32C0 */
#endif /* i2c_1.c */

#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3) || \
defined(CPU_FAM_STM32F7) || defined(CPU_FAM_STM32G0) || \
defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32L0) || \
defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32L5) || \
defined(CPU_FAM_STM32U5) || defined(CPU_FAM_STM32WB) || \
defined(CPU_FAM_STM32WL) || defined(CPU_FAM_STM32C0)
#if STM32_I2C_VARIANT == 1

Check failure on line 172 in cpu/stm32/include/periph/cpu_i2c.h

View workflow job for this annotation

GitHub Actions / static-tests

preprocessing issue while doing constant expression evaluation: syntax error: input=' == 1'
/**
* @brief The I2C implementation supports only a limited frame size.
* See i2c_1.c
*/
#define PERIPH_I2C_MAX_BYTES_PER_FRAME (256U)
#endif
#endif /* i2c_1.c */

#ifdef __cplusplus
}
Expand Down
18 changes: 2 additions & 16 deletions cpu/stm32/periph/i2c_2.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,22 +206,8 @@ static void _init(i2c_t dev)
I2C_TypeDef *i2c = i2c_config[dev].dev;

uint32_t ccr = 0;
/* read speed configuration */
switch (i2c_config[dev].speed) {
case I2C_SPEED_LOW:
/* 10Kbit/s */
ccr = i2c_config[dev].clk / 20000;
break;

case I2C_SPEED_NORMAL:
/* 100Kbit/s */
ccr = i2c_config[dev].clk / 200000;
break;

case I2C_SPEED_FAST:
ccr = i2c_config[dev].clk / 800000;
break;
}
/* apply speed configuration */
ccr = i2c_config[dev].clk / (i2c_config[dev].speed << 1);

/* make peripheral soft reset */
i2c->CR1 |= I2C_CR1_SWRST;
Expand Down

0 comments on commit 8a19639

Please sign in to comment.