Possible bug in Cube Lib 1.6 with I2C / DMA
Options
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2016-11-17 9:22 AM
Posted on November 17, 2016 at 18:22
Hello
In stm32L1 Cube lib 1.6. In the interrupt handling of a transfer complete on i2c in slave mode with DMA, the HAL_DMA_IRQHandler(...) calls XferCpltCallback(...) which points to I2C_DMAXferCplt (...). This is the function:static void I2C_DMAXferCplt(DMA_HandleTypeDef* hdma) {
I2C_HandleTypeDef* hi2c = (I2C_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
if ((hi2c->State == HAL_I2C_STATE_BUSY_TX) || ((hi2c->State == HAL_I2C_STATE_BUSY_RX) && (hi2c->Mode == HAL_I2C_MODE_SLAVE))) {
/* Disable DMA Request */
CLEAR_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN);
hi2c->XferCount = 0U;
/* Enable EVT and ERR interrupt */
__HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR);
} else {
/* Disable Acknowledge */
CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK);
/* Generate Stop */
SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP);
/* Disable Last DMA */
CLEAR_BIT(hi2c->Instance->CR2, I2C_CR2_LAST);
/* Disable DMA Request */
CLEAR_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN);
hi2c->XferCount = 0U;
/* Check if Errors has been detected during transfer */
if (hi2c->ErrorCode != HAL_I2C_ERROR_NONE) {
HAL_I2C_ErrorCallback(hi2c);
} else {
hi2c->State = HAL_I2C_STATE_READY;
if (hi2c->Mode == HAL_I2C_MODE_MEM) {
hi2c->Mode = HAL_I2C_MODE_NONE;
HAL_I2C_MemRxCpltCallback(hi2c);
} else {
hi2c->Mode = HAL_I2C_MODE_NONE;
HAL_I2C_MasterRxCpltCallback(hi2c);
}
}
}
}
In the discussed context, hi2c->state is HAL_I2C_STATE_BUSY_TX .
What I think to be a bug is that, in this case, the hi2c->state is not modified by
the function while the transfer has completed.
Is suspect that the code should more look like this:
static void I2C_DMAXferCplt(DMA_HandleTypeDef* hdma) {
I2C_HandleTypeDef* hi2c = (I2C_HandleTypeDef*) ((DMA_HandleTypeDef*) hdma)->Parent;
if ((hi2c->State == HAL_I2C_STATE_BUSY_TX) || ((hi2c->State == HAL_I2C_STATE_BUSY_RX) && (hi2c->Mode == HAL_I2C_MODE_SLAVE))) {
/* Disable DMA Request */
CLEAR_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN);
hi2c->XferCount = 0U;
/* Enable EVT and ERR interrupt */
__HAL_I2C_ENABLE_IT(hi2c, I2C_IT_EVT | I2C_IT_ERR);
} else {
/* Disable Acknowledge */
CLEAR_BIT(hi2c->Instance->CR1, I2C_CR1_ACK);
/* Generate Stop */
SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP);
/* Disable Last DMA */
CLEAR_BIT(hi2c->Instance->CR2, I2C_CR2_LAST);
/* Disable DMA Request */
CLEAR_BIT(hi2c->Instance->CR2, I2C_CR2_DMAEN);
hi2c->XferCount = 0U;
}
/* Check if Errors has been detected during transfer */
if (hi2c->ErrorCode != HAL_I2C_ERROR_NONE) {
HAL_I2C_ErrorCallback(hi2c);
} else {
hi2c->State = HAL_I2C_STATE_READY;
if (hi2c->Mode == HAL_I2C_MODE_MEM) {
hi2c->Mode = HAL_I2C_MODE_NONE;
HAL_I2C_MemRxCpltCallback(hi2c);
} else {
hi2c->Mode = HAL_I2C_MODE_NONE;
HAL_I2C_MasterRxCpltCallback(hi2c);
}
}
}
What do you think about it?
Regards
Julien
#dma #stm32l1 #i2c
Labels:
- Labels:
-
DMA
-
I2C
-
STM32L1 Series
0 REPLIES 0
