[BUG] - HAL_I2SEx_TxRxCpltCallback never fire in DMA circular mode
I was usig stm32f4 hal version 1.11 and in that version there was this code:
void I2S_DMATxCplt(DMA_HandleTypeDef *hdma)
{
I2S_HandleTypeDef* hi2s = (I2S_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0U)
{
if(hi2s->Init.FullDuplexMode != I2S_FULLDUPLEXMODE_ENABLE)
{
hi2s->Instance->CR2 &= (uint32_t)(~SPI_CR2_TXDMAEN);
}
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\
defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) ||\
defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F411xE) || defined(STM32F469xx) ||\
defined(STM32F479xx)
/* FullDuplexMode feature enabled */
else
{
if(((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_TX) || ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_SLAVE_TX))
{
/* Disable Tx DMA Request for the I2S Master*/
hi2s->Instance->CR2 &= (uint32_t)(~SPI_CR2_TXDMAEN);
}
else
{
/* Disable Tx DMA Request for the I2SEx Slave */
I2SxEXT(hi2s->Instance)->CR2 &= (uint32_t)(~SPI_CR2_TXDMAEN);
}
}
#endif /* STM32F40xxx || STM32F41xxx || STM32F42xxx || STM32F43xxx || STM32F401xx || STM32F411xx ||\
STM32F469xx || STM32F479xx */
hi2s->TxXferCount = 0U;
if(hi2s->State == HAL_I2S_STATE_BUSY_TX_RX)
{
if(hi2s->RxXferCount == 0U)
{
hi2s->State = HAL_I2S_STATE_READY;
}
}
else
{
hi2s->State = HAL_I2S_STATE_READY;
}
}
HAL_I2S_TxCpltCallback(hi2s);
}as you can see HAL_I2S_TxCpltCallback(hi2s) is called at the end of the function, no matter if DMA was in circular mode or not. That is the expected behavior for that callback!!!!
In current stm32f4 hal library we have:
/**
* @brief DMA I2S transmit receive process complete callback
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
* the configuration information for the specified DMA module.
* @retval None
*/
static void I2SEx_TxRxDMACplt(DMA_HandleTypeDef *hdma)
{
I2S_HandleTypeDef* hi2s = (I2S_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent;
/* if DMA is not configured in DMA_CIRCULAR mode */
if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0U)
{
if (hi2s->hdmarx == hdma)
{
/* Disable Rx DMA Request */
if (((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_TX) ||\
((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_SLAVE_TX))
{
CLEAR_BIT(I2SxEXT(hi2s->Instance)->CR2,SPI_CR2_RXDMAEN);
}
else
{
CLEAR_BIT(hi2s->Instance->CR2,SPI_CR2_RXDMAEN);
}
hi2s->RxXferCount = 0U;
if (hi2s->TxXferCount == 0U)
{
hi2s->State = HAL_I2S_STATE_READY;
HAL_I2SEx_TxRxCpltCallback(hi2s);
}
}
if (hi2s->hdmatx == hdma)
{
/* Disable Tx DMA Request */
if (((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_TX) ||\
((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_SLAVE_TX))
{
CLEAR_BIT(hi2s->Instance->CR2,SPI_CR2_TXDMAEN);
}
else
{
CLEAR_BIT(I2SxEXT(hi2s->Instance)->CR2,SPI_CR2_TXDMAEN);
}
hi2s->TxXferCount = 0U;
if (hi2s->RxXferCount == 0U)
{
hi2s->State = HAL_I2S_STATE_READY;
HAL_I2SEx_TxRxCpltCallback(hi2s);
}
}
}
}this time the call to HAL_I2SEx_TxRxCpltCallback(hi2s) function is inside the circular mode enabled check and therefore it never fire in circular mode.
