i2c master: add i2c fallback support

This commit is contained in:
Dimitris Mantzouranis 2023-05-29 20:36:51 +03:00
parent 20cefe254d
commit a2e6cb94c6
2 changed files with 55 additions and 1 deletions

View File

@ -117,6 +117,31 @@ See [this page](https://www.playembedded.org/blog/stm32-i2c-chibios/#8_I2Cv2_I2C
|`I2C1_TIMINGR_SCLH` |`38U` |
|`I2C1_TIMINGR_SCLL` |`129U` |
### I2C Fallback :id=arm-configuration-i2cfallback
ChibiOS provides a software solution through the I2C Fallback driver for cases where hardware I2C is not available.
To enable it, modify your board's `halconf.h` to enable the first I2C Fallback driver( assuming selected I2C peripheral is `I2CD1`).
```c
#define SW_I2C_USE_I2C1
```
By default, the delay required for I2C communication is calculated automatically with a target frequency of 100kHz, through the ChibiOS OSAL layer. If you wish to override this behavior, further modify your board's `halconf.h`
```c
#define SW_I2C_USE_OSAL_DELAY FALSE
```
and provide the following function in your board's files
```c
void i2c_sw_delay(void) {
// custom delay goes here
}
```
The I2C Fallback configuration structure is as follows
|`config.h` Override |Default |
|-----------------------|--------|
|`I2C_CLOCK_FREQUENCY` |`100000`|
|`SW_I2C_USE_OSAL_DELAY`|`TRUE` |
Note that `I2C_CLOCK_FREQUENCY` is target I2C speed in `Hz` and is only respected if `SW_I2C_USE_OSAL_DELAY` is `TRUE`.
## API :id=api
### `void i2c_init(void)` :id=api-i2c-init

View File

@ -90,10 +90,39 @@
# endif
#endif
#ifdef SW_I2C_USE_I2C1
# ifndef I2C1_SCL_PAL_MODE
# define I2C1_SCL_PAL_MODE PAL_MODE_ALTERNATE_OPENDRAIN
# endif
# ifndef I2C1_SDA_PAL_MODE
# define I2C1_SDA_PAL_MODE PAL_MODE_ALTERNATE_OPENDRAIN
# endif
# ifndef I2C_CLOCK_FREQUENCY
# define I2C_CLOCK_FREQUENCY 100000
# endif
# ifndef SW_I2C_DELAY
# define SW_I2C_DELAY ceil((CH_CFG_ST_FREQUENCY / I2C_CLOCK_FREQUENCY) / 2)
# endif
# ifndef SW_I2C_USE_OSAL_DELAY
# define SW_I2C_USE_OSAL_DELAY TRUE
# endif
# if (SW_I2C_USE_OSAL_DELAY == FALSE)
__attribute__((weak)) void i2c_sw_delay(void) {}
# endif
#endif
static uint8_t i2c_address;
static const I2CConfig i2cconfig = {
#if defined(USE_I2CV1_CONTRIB)
#if defined(SW_I2C_USE_I2C1)
0,
I2C1_SCL_PIN,
I2C1_SDA_PIN,
# if (SW_I2C_USE_OSAL_DELAY == FALSE)
&i2c_sw_delay,
# else
SW_I2C_DELAY,
# endif
#elif defined(USE_I2CV1_CONTRIB)
I2C1_CLOCK_SPEED,
#elif defined(USE_I2CV1)
I2C1_OPMODE,