diff --git a/drivers/i2c/i2c_ll_stm32.c b/drivers/i2c/i2c_ll_stm32.c index da69256579d..6e10d73f6ec 100644 --- a/drivers/i2c/i2c_ll_stm32.c +++ b/drivers/i2c/i2c_ll_stm32.c @@ -61,24 +61,47 @@ static int i2c_stm32_transfer(struct device *dev, struct i2c_msg *msg, LL_I2C_Enable(i2c); current = msg; + /* + * Set I2C_MSG_RESTART flag on first message in order to send start + * condition + */ + current->flags |= I2C_MSG_RESTART; while (num_msgs > 0) { - unsigned int flags = 0; + u8_t *next_msg_flags = NULL; - if (current->len > 255) - return -EINVAL; - - /* do NOT issue the i2c stop condition at the end of transfer */ if (num_msgs > 1) { next = current + 1; + next_msg_flags = &(next->flags); + + /* + * Stop or restart condition between messages + * of different directions is required + */ if (OPERATION(current) != OPERATION(next)) { - flags = I2C_MSG_RESTART; + if (!(next->flags & I2C_MSG_RESTART)) { + ret = -EINVAL; + break; + } } } + if (current->len > 255) { + ret = -EINVAL; + break; + } + + /* Stop condition is required for the last message */ + if ((num_msgs == 1) && !(current->flags & I2C_MSG_STOP)) { + ret = -EINVAL; + break; + } + if ((current->flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) { - ret = stm32_i2c_msg_write(dev, current, flags, slave); + ret = stm32_i2c_msg_write(dev, current, next_msg_flags, + slave); } else { - ret = stm32_i2c_msg_read(dev, current, flags, slave); + ret = stm32_i2c_msg_read(dev, current, next_msg_flags, + slave); } if (ret < 0) { diff --git a/drivers/i2c/i2c_ll_stm32.h b/drivers/i2c/i2c_ll_stm32.h index 9e75f2f3350..d0e744092de 100644 --- a/drivers/i2c/i2c_ll_stm32.h +++ b/drivers/i2c/i2c_ll_stm32.h @@ -42,9 +42,9 @@ struct i2c_stm32_data { } current; }; -s32_t stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg, u32_t flg, +s32_t stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg, u8_t *flg, u16_t sadr); -s32_t stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg, u32_t flg, +s32_t stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg, u8_t *flg, u16_t sadr); s32_t stm32_i2c_configure_timing(struct device *dev, u32_t clk); diff --git a/drivers/i2c/i2c_ll_stm32_v1.c b/drivers/i2c/i2c_ll_stm32_v1.c index e964f4cf91f..ace1e413977 100644 --- a/drivers/i2c/i2c_ll_stm32_v1.c +++ b/drivers/i2c/i2c_ll_stm32_v1.c @@ -90,7 +90,7 @@ static inline void handle_txe(I2C_TypeDef *i2c, struct i2c_stm32_data *data) LL_I2C_TransmitData8(i2c, *data->current.buf); data->current.buf++; } else { - if ((data->current.flags & I2C_MSG_RESTART) == 0) { + if (data->current.flags & I2C_MSG_STOP) { LL_I2C_GenerateStopCondition(i2c); } if (LL_I2C_IsActiveFlag_BTF(i2c)) { @@ -107,7 +107,7 @@ static inline void handle_rxne(I2C_TypeDef *i2c, struct i2c_stm32_data *data) switch (data->current.len) { case 1: /* Single byte reception */ - if ((data->current.flags & I2C_MSG_RESTART) == 0) { + if (data->current.flags & I2C_MSG_STOP) { LL_I2C_GenerateStopCondition(i2c); } LL_I2C_DisableIT_BUF(i2c); @@ -146,7 +146,7 @@ static inline void handle_btf(I2C_TypeDef *i2c, struct i2c_stm32_data *data) * Stop condition must be generated before reading the * last two bytes. */ - if ((data->current.flags & I2C_MSG_RESTART) == 0) { + if (data->current.flags & I2C_MSG_STOP) { LL_I2C_GenerateStopCondition(i2c); } @@ -209,16 +209,18 @@ void stm32_i2c_error_isr(void *arg) } s32_t stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg, - u32_t flags, u16_t saddr) + u8_t *next_msg_flags, u16_t saddr) { const struct i2c_stm32_config *cfg = DEV_CFG(dev); struct i2c_stm32_data *data = DEV_DATA(dev); I2C_TypeDef *i2c = cfg->i2c; s32_t ret = 0; + ARG_UNUSED(next_msg_flags); + data->current.len = msg->len; data->current.buf = msg->buf; - data->current.flags = flags; + data->current.flags = msg->flags; data->current.is_restart = 0; data->current.is_write = 1; data->current.is_nack = 0; @@ -228,7 +230,9 @@ s32_t stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg, LL_I2C_EnableIT_EVT(i2c); LL_I2C_EnableIT_ERR(i2c); LL_I2C_AcknowledgeNextData(i2c, LL_I2C_ACK); - LL_I2C_GenerateStartCondition(i2c); + if (msg->flags & I2C_MSG_RESTART) { + LL_I2C_GenerateStartCondition(i2c); + } LL_I2C_EnableIT_BUF(i2c); k_sem_take(&data->device_sync_sem, K_FOREVER); @@ -255,16 +259,18 @@ s32_t stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg, } s32_t stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg, - u32_t flags, u16_t saddr) + u8_t *next_msg_flags, u16_t saddr) { const struct i2c_stm32_config *cfg = DEV_CFG(dev); struct i2c_stm32_data *data = DEV_DATA(dev); I2C_TypeDef *i2c = cfg->i2c; s32_t ret = 0; + ARG_UNUSED(next_msg_flags); + data->current.len = msg->len; data->current.buf = msg->buf; - data->current.flags = flags; + data->current.flags = msg->flags; data->current.is_restart = 0; data->current.is_write = 0; data->current.is_err = 0; @@ -294,7 +300,7 @@ s32_t stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg, #else s32_t stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg, - u32_t flags, u16_t saddr) + u8_t *next_msg_flags, u16_t saddr) { const struct i2c_stm32_config *cfg = DEV_CFG(dev); struct i2c_stm32_data *data = DEV_DATA(dev); @@ -302,31 +308,37 @@ s32_t stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg, u32_t len = msg->len; u8_t *buf = msg->buf; + ARG_UNUSED(next_msg_flags); + LL_I2C_AcknowledgeNextData(i2c, LL_I2C_ACK); - LL_I2C_GenerateStartCondition(i2c); - while (!LL_I2C_IsActiveFlag_SB(i2c)) { - ; - } - if (I2C_ADDR_10_BITS & data->dev_config) { - u8_t slave = (((saddr & 0x0300) >> 7) & 0xFF); - u8_t header = slave | HEADER; - - LL_I2C_TransmitData8(i2c, header); - while (!LL_I2C_IsActiveFlag_ADD10(i2c)) { + if (msg->flags & I2C_MSG_RESTART) { + LL_I2C_GenerateStartCondition(i2c); + while (!LL_I2C_IsActiveFlag_SB(i2c)) { ; } - slave = data->slave_address & 0xFF; - LL_I2C_TransmitData8(i2c, slave); - } else { - u8_t slave = (saddr << 1) & 0xFF; - LL_I2C_TransmitData8(i2c, slave | I2C_REQUEST_WRITE); + if (I2C_ADDR_10_BITS & data->dev_config) { + u8_t slave = (((saddr & 0x0300) >> 7) & 0xFF); + u8_t header = slave | HEADER; + + LL_I2C_TransmitData8(i2c, header); + while (!LL_I2C_IsActiveFlag_ADD10(i2c)) { + ; + } + slave = data->slave_address & 0xFF; + LL_I2C_TransmitData8(i2c, slave); + } else { + u8_t slave = (saddr << 1) & 0xFF; + + LL_I2C_TransmitData8(i2c, slave | I2C_REQUEST_WRITE); + } + while (!LL_I2C_IsActiveFlag_ADDR(i2c)) { + ; + } + LL_I2C_ClearFlag_ADDR(i2c); } - while (!LL_I2C_IsActiveFlag_ADDR(i2c)) { - ; - } - LL_I2C_ClearFlag_ADDR(i2c); + while (len) { while (1) { if (LL_I2C_IsActiveFlag_TXE(i2c)) { @@ -343,10 +355,12 @@ s32_t stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg, buf++; len--; } + while (!LL_I2C_IsActiveFlag_BTF(i2c)) { ; } - if ((flags & I2C_MSG_RESTART) == 0) { + + if (msg->flags & I2C_MSG_STOP) { LL_I2C_GenerateStopCondition(i2c); } @@ -354,7 +368,7 @@ s32_t stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg, } s32_t stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg, - u32_t flags, u16_t saddr) + u8_t *next_msg_flags, u16_t saddr) { const struct i2c_stm32_config *cfg = DEV_CFG(dev); struct i2c_stm32_data *data = DEV_DATA(dev); @@ -362,57 +376,65 @@ s32_t stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg, u32_t len = msg->len; u8_t *buf = msg->buf; + ARG_UNUSED(next_msg_flags); + LL_I2C_AcknowledgeNextData(i2c, LL_I2C_ACK); - LL_I2C_GenerateStartCondition(i2c); - while (!LL_I2C_IsActiveFlag_SB(i2c)) { - ; - } - if (I2C_ADDR_10_BITS & data->dev_config) { - u8_t slave = (((saddr & 0x0300) >> 7) & 0xFF); - u8_t header = slave | HEADER; - - LL_I2C_TransmitData8(i2c, header); - while (!LL_I2C_IsActiveFlag_ADD10(i2c)) { - ; - } - slave = saddr & 0xFF; - LL_I2C_TransmitData8(i2c, slave); - while (!LL_I2C_IsActiveFlag_ADDR(i2c)) { - ; - } - LL_I2C_ClearFlag_ADDR(i2c); + if (msg->flags & I2C_MSG_RESTART) { LL_I2C_GenerateStartCondition(i2c); while (!LL_I2C_IsActiveFlag_SB(i2c)) { ; } - header |= I2C_REQUEST_READ; - LL_I2C_TransmitData8(i2c, header); - } else { - u8_t slave = ((saddr) << 1) & 0xFF; - LL_I2C_TransmitData8(i2c, slave | I2C_REQUEST_READ); + if (I2C_ADDR_10_BITS & data->dev_config) { + u8_t slave = (((saddr & 0x0300) >> 7) & 0xFF); + u8_t header = slave | HEADER; + + LL_I2C_TransmitData8(i2c, header); + while (!LL_I2C_IsActiveFlag_ADD10(i2c)) { + ; + } + slave = saddr & 0xFF; + LL_I2C_TransmitData8(i2c, slave); + while (!LL_I2C_IsActiveFlag_ADDR(i2c)) { + ; + } + LL_I2C_ClearFlag_ADDR(i2c); + LL_I2C_GenerateStartCondition(i2c); + while (!LL_I2C_IsActiveFlag_SB(i2c)) { + ; + } + header |= I2C_REQUEST_READ; + LL_I2C_TransmitData8(i2c, header); + } else { + u8_t slave = ((saddr) << 1) & 0xFF; + + LL_I2C_TransmitData8(i2c, slave | I2C_REQUEST_READ); + } + + while (!LL_I2C_IsActiveFlag_ADDR(i2c)) { + ; + } + + if (len == 1) { + /* Single byte reception: enable NACK and set STOP */ + LL_I2C_AcknowledgeNextData(i2c, LL_I2C_NACK); + } else if (len == 2) { + /* 2-byte reception: enable NACK and set POS */ + LL_I2C_AcknowledgeNextData(i2c, LL_I2C_NACK); + LL_I2C_EnableBitPOS(i2c); + } + + LL_I2C_ClearFlag_ADDR(i2c); } - while (!LL_I2C_IsActiveFlag_ADDR(i2c)) { - ; - } - if (len == 1) { - /* Single byte reception: enable NACK and set STOP */ - LL_I2C_AcknowledgeNextData(i2c, LL_I2C_NACK); - } else if (len == 2) { - /* 2-byte reception: enable NACK and set POS */ - LL_I2C_AcknowledgeNextData(i2c, LL_I2C_NACK); - LL_I2C_EnableBitPOS(i2c); - } - LL_I2C_ClearFlag_ADDR(i2c); while (len) { while (!LL_I2C_IsActiveFlag_RXNE(i2c)) { ; } switch (len) { case 1: - if ((flags & I2C_MSG_RESTART) == 0) { + if (msg->flags & I2C_MSG_STOP) { LL_I2C_GenerateStopCondition(i2c); } len--; @@ -427,7 +449,7 @@ s32_t stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg, * Stop condition must be generated before reading the * last two bytes. */ - if ((data->current.flags & I2C_MSG_RESTART) == 0) { + if (msg->flags & I2C_MSG_STOP) { LL_I2C_GenerateStopCondition(i2c); } diff --git a/drivers/i2c/i2c_ll_stm32_v2.c b/drivers/i2c/i2c_ll_stm32_v2.c index e6406d96734..b87d89102ca 100644 --- a/drivers/i2c/i2c_ll_stm32_v2.c +++ b/drivers/i2c/i2c_ll_stm32_v2.c @@ -21,48 +21,56 @@ #include static inline void msg_init(struct device *dev, struct i2c_msg *msg, - unsigned int flags, u16_t slave, uint32_t transfer) + u8_t *next_msg_flags, u16_t slave, + uint32_t transfer) { const struct i2c_stm32_config *cfg = DEV_CFG(dev); struct i2c_stm32_data *data = DEV_DATA(dev); I2C_TypeDef *i2c = cfg->i2c; - unsigned int len = msg->len; - if (I2C_ADDR_10_BITS & data->dev_config) { - LL_I2C_SetMasterAddressingMode(i2c, - LL_I2C_ADDRESSING_MODE_10BIT); - LL_I2C_SetSlaveAddr(i2c, (uint32_t) slave); + if (LL_I2C_IsEnabledReloadMode(i2c)) { + LL_I2C_SetTransferSize(i2c, msg->len); } else { - LL_I2C_SetMasterAddressingMode(i2c, - LL_I2C_ADDRESSING_MODE_7BIT); - LL_I2C_SetSlaveAddr(i2c, (uint32_t) slave << 1); + if (I2C_ADDR_10_BITS & data->dev_config) { + LL_I2C_SetMasterAddressingMode(i2c, + LL_I2C_ADDRESSING_MODE_10BIT); + LL_I2C_SetSlaveAddr(i2c, (uint32_t) slave); + } else { + LL_I2C_SetMasterAddressingMode(i2c, + LL_I2C_ADDRESSING_MODE_7BIT); + LL_I2C_SetSlaveAddr(i2c, (uint32_t) slave << 1); + } + + if (!(msg->flags & I2C_MSG_STOP) && next_msg_flags && + !(*next_msg_flags & I2C_MSG_RESTART)) { + LL_I2C_EnableReloadMode(i2c); + } else { + LL_I2C_DisableReloadMode(i2c); + } + LL_I2C_DisableAutoEndMode(i2c); + LL_I2C_SetTransferRequest(i2c, transfer); + LL_I2C_SetTransferSize(i2c, msg->len); + LL_I2C_GenerateStartCondition(i2c); } - - LL_I2C_SetTransferRequest(i2c, transfer); - LL_I2C_SetTransferSize(i2c, len); - - LL_I2C_DisableAutoEndMode(i2c); - LL_I2C_DisableReloadMode(i2c); - LL_I2C_GenerateStartCondition(i2c); } -static inline void msg_done(struct device *dev, unsigned int flags) +static inline void msg_done(struct device *dev, unsigned int current_msg_flags) { const struct i2c_stm32_config *cfg = DEV_CFG(dev); I2C_TypeDef *i2c = cfg->i2c; /* Wait for transfer to complete */ - while (!LL_I2C_IsActiveFlag_TC(i2c)) { + while (!LL_I2C_IsActiveFlag_TC(i2c) && !LL_I2C_IsActiveFlag_TCR(i2c)) { ; } - /* Issue stop condition if necessary */ - if ((flags & I2C_MSG_RESTART) == 0) { + if (current_msg_flags & I2C_MSG_STOP) { LL_I2C_GenerateStopCondition(i2c); while (!LL_I2C_IsActiveFlag_STOP(i2c)) { ; } LL_I2C_ClearFlag_STOP(i2c); + LL_I2C_DisableReloadMode(i2c); } } @@ -91,9 +99,9 @@ void stm32_i2c_event_isr(void *arg) data->current.buf++; data->current.len--; - if (!data->current.len) + if (!data->current.len) { k_sem_give(&data->device_sync_sem); - + } return; error: data->current.is_err = 1; @@ -117,7 +125,7 @@ void stm32_i2c_error_isr(void *arg) } int stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg, - unsigned int flags, uint16_t slave) + u8_t *next_msg_flags, uint16_t slave) { const struct i2c_stm32_config *cfg = DEV_CFG(dev); struct i2c_stm32_data *data = DEV_DATA(dev); @@ -129,7 +137,7 @@ int stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg, data->current.is_nack = 0; data->current.is_err = 0; - msg_init(dev, msg, flags, slave, LL_I2C_REQUEST_WRITE); + msg_init(dev, msg, next_msg_flags, slave, LL_I2C_REQUEST_WRITE); LL_I2C_EnableIT_TX(i2c); LL_I2C_EnableIT_NACK(i2c); @@ -138,7 +146,7 @@ int stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg, goto error; } - msg_done(dev, flags); + msg_done(dev, msg->flags); LL_I2C_DisableIT_TX(i2c); LL_I2C_DisableIT_NACK(i2c); @@ -162,7 +170,7 @@ error: } int stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg, - unsigned int flags, uint16_t slave) + u8_t *next_msg_flags, uint16_t slave) { const struct i2c_stm32_config *cfg = DEV_CFG(dev); struct i2c_stm32_data *data = DEV_DATA(dev); @@ -173,7 +181,7 @@ int stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg, data->current.is_write = 0; data->current.is_err = 0; - msg_init(dev, msg, flags, slave, LL_I2C_REQUEST_READ); + msg_init(dev, msg, next_msg_flags, slave, LL_I2C_REQUEST_READ); LL_I2C_EnableIT_RX(i2c); k_sem_take(&data->device_sync_sem, K_FOREVER); @@ -181,7 +189,7 @@ int stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg, goto error; } - msg_done(dev, flags); + msg_done(dev, msg->flags); LL_I2C_DisableIT_RX(i2c); return 0; @@ -195,15 +203,16 @@ error: #else /* !CONFIG_I2C_STM32_INTERRUPT */ int stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg, - unsigned int flags, uint16_t slave) + u8_t *next_msg_flags, uint16_t slave) { const struct i2c_stm32_config *cfg = DEV_CFG(dev); I2C_TypeDef *i2c = cfg->i2c; - unsigned int len = msg->len; + unsigned int len = 0; u8_t *buf = msg->buf; - msg_init(dev, msg, flags, slave, LL_I2C_REQUEST_WRITE); + msg_init(dev, msg, next_msg_flags, slave, LL_I2C_REQUEST_WRITE); + len = msg->len; while (len) { while (1) { if (LL_I2C_IsActiveFlag_TXIS(i2c)) { @@ -220,7 +229,7 @@ int stm32_i2c_msg_write(struct device *dev, struct i2c_msg *msg, len--; } - msg_done(dev, flags); + msg_done(dev, msg->flags); return 0; error: @@ -231,15 +240,16 @@ error: } int stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg, - unsigned int flags, uint16_t slave) + u8_t *next_msg_flags, uint16_t slave) { const struct i2c_stm32_config *cfg = DEV_CFG(dev); I2C_TypeDef *i2c = cfg->i2c; - unsigned int len = msg->len; + unsigned int len = 0; u8_t *buf = msg->buf; - msg_init(dev, msg, flags, slave, LL_I2C_REQUEST_READ); + msg_init(dev, msg, next_msg_flags, slave, LL_I2C_REQUEST_READ); + len = msg->len; while (len) { while (!LL_I2C_IsActiveFlag_RXNE(i2c)) { ; @@ -250,7 +260,7 @@ int stm32_i2c_msg_read(struct device *dev, struct i2c_msg *msg, len--; } - msg_done(dev, flags); + msg_done(dev, msg->flags); return 0; }