Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

i2c_ll_stm32: Add timeout to I2C read/write functions #21308

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 22 additions & 21 deletions drivers/i2c/i2c_ll_stm32.c
Original file line number Diff line number Diff line change
Expand Up @@ -289,27 +289,28 @@ static void i2c_stm32_irq_config_func_##name(struct device *dev) \

#endif /* CONFIG_I2C_STM32_INTERRUPT */

#define STM32_I2C_INIT(name) \
STM32_I2C_IRQ_HANDLER_DECL(name); \
\
static const struct i2c_stm32_config i2c_stm32_cfg_##name = { \
.i2c = (I2C_TypeDef *)DT_REG_ADDR(DT_NODELABEL(name)), \
.pclken = { \
.enr = DT_CLOCKS_CELL(DT_NODELABEL(name), bits), \
.bus = DT_CLOCKS_CELL(DT_NODELABEL(name), bus), \
}, \
STM32_I2C_IRQ_HANDLER_FUNCTION(name) \
.bitrate = DT_PROP(DT_NODELABEL(name), clock_frequency), \
}; \
\
static struct i2c_stm32_data i2c_stm32_dev_data_##name; \
\
DEVICE_AND_API_INIT(i2c_stm32_##name, DT_LABEL(DT_NODELABEL(name)), \
&i2c_stm32_init, &i2c_stm32_dev_data_##name, \
&i2c_stm32_cfg_##name, \
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
&api_funcs); \
\
#define STM32_I2C_INIT(name) \
STM32_I2C_IRQ_HANDLER_DECL(name); \
\
static const struct i2c_stm32_config i2c_stm32_cfg_##name = { \
.i2c = (I2C_TypeDef *)DT_REG_ADDR(DT_NODELABEL(name)), \
.pclken = { \
.enr = DT_CLOCKS_CELL(DT_NODELABEL(name), bits), \
.bus = DT_CLOCKS_CELL(DT_NODELABEL(name), bus), \
}, \
STM32_I2C_IRQ_HANDLER_FUNCTION(name) \
.bitrate = DT_PROP(DT_NODELABEL(name), clock_frequency), \
.timeout = DT_PROP_OR(DT_NODELABEL(name), timeout_ms, UINT32_MAX) \
}; \
\
static struct i2c_stm32_data i2c_stm32_dev_data_##name; \
\
DEVICE_AND_API_INIT(i2c_stm32_##name, DT_LABEL(DT_NODELABEL(name)), \
&i2c_stm32_init, &i2c_stm32_dev_data_##name, \
&i2c_stm32_cfg_##name, \
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
&api_funcs); \
\
STM32_I2C_IRQ_HANDLER(name)

/* I2C instances declaration */
Expand Down
1 change: 1 addition & 0 deletions drivers/i2c/i2c_ll_stm32.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ struct i2c_stm32_config {
struct stm32_pclken pclken;
I2C_TypeDef *i2c;
uint32_t bitrate;
uint32_t timeout;
};

struct i2c_stm32_data {
Expand Down
41 changes: 19 additions & 22 deletions drivers/i2c/i2c_ll_stm32_v1.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@ LOG_MODULE_REGISTER(i2c_ll_stm32_v1);

#include "i2c-priv.h"

#define STM32_I2C_TRANSFER_TIMEOUT_MSEC 500

#define STM32_I2C_TIMEOUT_USEC 1000
#define I2C_REQUEST_WRITE 0x00
#define I2C_REQUEST_READ 0x01
#define HEADER 0xF0
Expand Down Expand Up @@ -620,8 +617,7 @@ int32_t stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg,
stm32_i2c_enable_transfer_interrupts(dev);
LL_I2C_EnableIT_TX(i2c);

if (k_sem_take(&data->device_sync_sem,
K_MSEC(STM32_I2C_TRANSFER_TIMEOUT_MSEC)) != 0) {
if (k_sem_take(&data->device_sync_sem, K_USEC(cfg->timeout)) != 0) {
LOG_DBG("%s: WRITE timeout", __func__);
stm32_i2c_reset(dev);
return -EIO;
Expand All @@ -642,8 +638,7 @@ int32_t stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg,
stm32_i2c_enable_transfer_interrupts(dev);
LL_I2C_EnableIT_RX(i2c);

if (k_sem_take(&data->device_sync_sem,
K_MSEC(STM32_I2C_TRANSFER_TIMEOUT_MSEC)) != 0) {
if (k_sem_take(&data->device_sync_sem, K_USEC(cfg->timeout)) != 0) {
LOG_DBG("%s: READ timeout", __func__);
stm32_i2c_reset(dev);
return -EIO;
Expand Down Expand Up @@ -693,7 +688,7 @@ static inline int check_errors(struct device *dev, const char *funcname)
return -EIO;
}

static int stm32_i2c_wait_timeout(uint16_t *timeout)
static int stm32_i2c_wait_timeout(uint32_t *timeout)
{
if (*timeout == 0) {
return 1;
Expand All @@ -711,13 +706,14 @@ int32_t stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg,
struct i2c_stm32_data *data = DEV_DATA(dev);
I2C_TypeDef *i2c = cfg->i2c;
uint32_t len = msg->len;
uint16_t timeout;
const uint32_t timeout_us = cfg->timeout;
uint32_t timeout;
uint8_t *buf = msg->buf;

msg_init(dev, msg, next_msg_flags, saddr, I2C_REQUEST_WRITE);

if (msg->flags & I2C_MSG_RESTART) {
timeout = STM32_I2C_TIMEOUT_USEC;
timeout = timeout_us;
while (!LL_I2C_IsActiveFlag_SB(i2c)) {
if (stm32_i2c_wait_timeout(&timeout)) {
LL_I2C_GenerateStopCondition(i2c);
Expand All @@ -731,7 +727,7 @@ int32_t stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg,
uint8_t header = slave | HEADER;

LL_I2C_TransmitData8(i2c, header);
timeout = STM32_I2C_TIMEOUT_USEC;
timeout = timeout_us;
while (!LL_I2C_IsActiveFlag_ADD10(i2c)) {
if (stm32_i2c_wait_timeout(&timeout)) {
LL_I2C_GenerateStopCondition(i2c);
Expand All @@ -748,7 +744,7 @@ int32_t stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg,
LL_I2C_TransmitData8(i2c, slave | I2C_REQUEST_WRITE);
}

timeout = STM32_I2C_TIMEOUT_USEC;
timeout = timeout_us;
while (!LL_I2C_IsActiveFlag_ADDR(i2c)) {
if (LL_I2C_IsActiveFlag_AF(i2c) || stm32_i2c_wait_timeout(&timeout)) {
LL_I2C_ClearFlag_AF(i2c);
Expand All @@ -761,7 +757,7 @@ int32_t stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg,
}

while (len) {
timeout = STM32_I2C_TIMEOUT_USEC;
timeout = timeout_us;
while (1) {
if (LL_I2C_IsActiveFlag_TXE(i2c)) {
break;
Expand All @@ -778,7 +774,7 @@ int32_t stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg,
len--;
}

timeout = STM32_I2C_TIMEOUT_USEC;
timeout = timeout_us;
while (!LL_I2C_IsActiveFlag_BTF(i2c)) {
if (stm32_i2c_wait_timeout(&timeout)) {
LL_I2C_GenerateStopCondition(i2c);
Expand All @@ -803,13 +799,14 @@ int32_t stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg,
struct i2c_stm32_data *data = DEV_DATA(dev);
I2C_TypeDef *i2c = cfg->i2c;
uint32_t len = msg->len;
uint16_t timeout;
const uint32_t timeout_us = cfg->timeout;
uint32_t timeout;
uint8_t *buf = msg->buf;

msg_init(dev, msg, next_msg_flags, saddr, I2C_REQUEST_READ);

if (msg->flags & I2C_MSG_RESTART) {
timeout = STM32_I2C_TIMEOUT_USEC;
timeout = timeout_us;
while (!LL_I2C_IsActiveFlag_SB(i2c)) {
if (stm32_i2c_wait_timeout(&timeout)) {
LL_I2C_GenerateStopCondition(i2c);
Expand All @@ -823,7 +820,7 @@ int32_t stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg,
uint8_t header = slave | HEADER;

LL_I2C_TransmitData8(i2c, header);
timeout = STM32_I2C_TIMEOUT_USEC;
timeout = timeout_us;
while (!LL_I2C_IsActiveFlag_ADD10(i2c)) {
if (stm32_i2c_wait_timeout(&timeout)) {
LL_I2C_GenerateStopCondition(i2c);
Expand All @@ -834,7 +831,7 @@ int32_t stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg,

slave = saddr & 0xFF;
LL_I2C_TransmitData8(i2c, slave);
timeout = STM32_I2C_TIMEOUT_USEC;
timeout = timeout_us;
while (!LL_I2C_IsActiveFlag_ADDR(i2c)) {
if (stm32_i2c_wait_timeout(&timeout)) {
LL_I2C_GenerateStopCondition(i2c);
Expand All @@ -845,7 +842,7 @@ int32_t stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg,

LL_I2C_ClearFlag_ADDR(i2c);
stm32_i2c_generate_start_condition(i2c);
timeout = STM32_I2C_TIMEOUT_USEC;
timeout = timeout_us;
while (!LL_I2C_IsActiveFlag_SB(i2c)) {
if (stm32_i2c_wait_timeout(&timeout)) {
LL_I2C_GenerateStopCondition(i2c);
Expand All @@ -862,7 +859,7 @@ int32_t stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg,
LL_I2C_TransmitData8(i2c, slave | I2C_REQUEST_READ);
}

timeout = STM32_I2C_TIMEOUT_USEC;
timeout = timeout_us;
while (!LL_I2C_IsActiveFlag_ADDR(i2c)) {
if (LL_I2C_IsActiveFlag_AF(i2c) || stm32_i2c_wait_timeout(&timeout)) {
LL_I2C_ClearFlag_AF(i2c);
Expand All @@ -886,7 +883,7 @@ int32_t stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg,
}

while (len) {
timeout = STM32_I2C_TIMEOUT_USEC;
timeout = timeout_us;
while (!LL_I2C_IsActiveFlag_RXNE(i2c)) {
if (stm32_i2c_wait_timeout(&timeout)) {
LL_I2C_GenerateStopCondition(i2c);
Expand All @@ -895,7 +892,7 @@ int32_t stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg,
}
}

timeout = STM32_I2C_TIMEOUT_USEC;
timeout = timeout_us;
switch (len) {
case 1:
if (msg->flags & I2C_MSG_STOP) {
Expand Down
Loading