Skip to content

Commit 817796e

Browse files
committed
drivers: i2c_stm32_v2: Refactor end of master transfer
The stm32_i2c_master_mode_end function can be replaced with a simple irq disable and giving to the device sync semaphore Signed-off-by: Erik Andersson <erian747@gmail.com>
1 parent 9248492 commit 817796e

File tree

1 file changed

+61
-83
lines changed

1 file changed

+61
-83
lines changed

drivers/i2c/i2c_ll_stm32_v2.c

Lines changed: 61 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -232,32 +232,6 @@ static void i2c_stm32_disable_transfer_interrupts(const struct device *dev)
232232
}
233233
}
234234

235-
static void i2c_stm32_master_mode_end(const struct device *dev)
236-
{
237-
const struct i2c_stm32_config *cfg = dev->config;
238-
struct i2c_stm32_data *data = dev->data;
239-
I2C_TypeDef *i2c = cfg->i2c;
240-
241-
i2c_stm32_disable_transfer_interrupts(dev);
242-
243-
if (LL_I2C_IsEnabledReloadMode(i2c)) {
244-
LL_I2C_DisableReloadMode(i2c);
245-
}
246-
247-
#if defined(CONFIG_I2C_TARGET)
248-
data->master_active = false;
249-
if (!data->slave_attached && !data->smbalert_active) {
250-
LL_I2C_Disable(i2c);
251-
}
252-
#else
253-
if (!data->smbalert_active) {
254-
LL_I2C_Disable(i2c);
255-
}
256-
#endif
257-
258-
k_sem_give(&data->device_sync_sem);
259-
}
260-
261235
#if defined(CONFIG_I2C_TARGET)
262236
static void i2c_stm32_slave_event(const struct device *dev)
263237
{
@@ -655,17 +629,74 @@ int i2c_stm32_error(const struct device *dev)
655629

656630
return 0;
657631
end:
658-
i2c_stm32_master_mode_end(dev);
632+
i2c_stm32_disable_transfer_interrupts(dev);
633+
/* Wakeup thread */
634+
k_sem_give(&data->device_sync_sem);
659635
return -EIO;
660636
}
661637

638+
static int stm32_i2c_irq_msg_finish(const struct device *dev, struct i2c_msg *msg)
639+
{
640+
struct i2c_stm32_data *data = dev->data;
641+
const struct i2c_stm32_config *cfg = dev->config;
642+
bool keep_enabled = (msg->flags & I2C_MSG_STOP) == 0U;
643+
int ret;
644+
645+
/* Wait for IRQ to complete or timeout
646+
* Timeout scales with one millisecond for each byte to
647+
* transfer so that slave can do some clock stretching
648+
*/
649+
ret = k_sem_take(&data->device_sync_sem, K_MSEC(msg->len + 10U));
650+
651+
#ifdef CONFIG_I2C_STM32_V2_DMA
652+
/* Stop DMA and invalidate cache if needed */
653+
dma_finish(dev, msg);
654+
#endif
655+
/* Check for transfer errors or timeout */
656+
if (data->current.is_nack || data->current.is_arlo || (ret != 0)) {
657+
658+
if (data->current.is_arlo) {
659+
LOG_DBG("ARLO");
660+
}
661+
662+
if (data->current.is_nack) {
663+
LOG_DBG("NACK");
664+
}
665+
666+
if (data->current.is_err) {
667+
LOG_DBG("ERR %d", data->current.is_err);
668+
}
669+
670+
if (ret != 0) {
671+
LOG_DBG("TIMEOUT");
672+
}
673+
ret = -EIO;
674+
}
675+
676+
#if defined(CONFIG_I2C_TARGET)
677+
if (!keep_enabled || (ret != 0)) {
678+
data->master_active = false;
679+
}
680+
/* Don't disable I2C if a slave is attached */
681+
keep_enabled |= data->slave_attached;
682+
#endif
683+
/* Don't disable I2C if SMBus Alert is active */
684+
keep_enabled |= data->smbalert_active;
685+
686+
/* If I2C no longer need to be enabled or on error */
687+
if (!keep_enabled || (ret != 0)) {
688+
LL_I2C_Disable(cfg->i2c);
689+
}
690+
691+
return ret;
692+
}
693+
662694
static int stm32_i2c_irq_xfer(const struct device *dev, struct i2c_msg *msg,
663695
uint8_t *next_msg_flags, uint16_t slave)
664696
{
665697
const struct i2c_stm32_config *cfg = dev->config;
666698
struct i2c_stm32_data *data = dev->data;
667699
I2C_TypeDef *regs = cfg->i2c;
668-
bool is_timeout = false;
669700

670701
data->current.len = msg->len;
671702
data->current.buf = msg->buf;
@@ -781,61 +812,8 @@ static int stm32_i2c_irq_xfer(const struct device *dev, struct i2c_msg *msg,
781812
/* Enable interrupts */
782813
LL_I2C_WriteReg(regs, CR1, cr1);
783814

784-
/* Wait for IRQ to complete or timeout
785-
* Timeout scales with one millisecond for each byte to
786-
* transfer so that slave can do some clock stretching
787-
*/
788-
if (k_sem_take(&data->device_sync_sem, K_MSEC(msg->len + 10U)) != 0U) {
789-
is_timeout = true;
790-
}
791-
792-
#ifdef CONFIG_I2C_STM32_V2_DMA
793-
/* Stop DMA and invalidate cache if needed */
794-
dma_finish(dev, msg);
795-
#endif
796-
/* Check for transfer errors or timeout */
797-
if (data->current.is_nack || data->current.is_arlo || is_timeout) {
798-
LL_I2C_Disable(regs);
799-
goto error;
800-
}
801-
802-
if ((msg->flags & I2C_MSG_STOP) != 0U) {
803-
/* Disable I2C if this was the last message and SMBus alert is not active */
804-
#if defined(CONFIG_I2C_TARGET)
805-
data->master_active = false;
806-
if (!data->slave_attached && !data->smbalert_active) {
807-
LL_I2C_Disable(regs);
808-
}
809-
#else
810-
if (!data->smbalert_active) {
811-
LL_I2C_Disable(regs);
812-
}
813-
#endif
814-
}
815-
816-
return 0;
817-
818-
error:
819-
if (data->current.is_arlo) {
820-
LOG_DBG("ARLO");
821-
data->current.is_arlo = 0U;
822-
}
823-
824-
if (data->current.is_nack) {
825-
LOG_DBG("NACK");
826-
data->current.is_nack = 0U;
827-
}
828-
829-
if (data->current.is_err) {
830-
LOG_DBG("ERR %d", data->current.is_err);
831-
data->current.is_err = 0U;
832-
}
833-
834-
if (is_timeout) {
835-
LOG_DBG("TIMEOUT");
836-
}
837-
838-
return -EIO;
815+
/* Wait for transfer to finish */
816+
return stm32_i2c_irq_msg_finish(dev, msg);
839817
}
840818

841819
#else /* !CONFIG_I2C_STM32_INTERRUPT */

0 commit comments

Comments
 (0)