Skip to main content
Visitor II
January 5, 2019
Question

[BUG] - HAL_I2SEx_TxRxCpltCallback never fire in DMA circular mode

  • January 5, 2019
  • 12 replies
  • 4129 views

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.

    This topic has been closed for replies.

    12 replies

    Visitor II
    January 5, 2019

    Is there an application workaround? Probably the "transfer complete" is seen at untrue for cyclical mode? As the behaviour changed between versions, there maybe a changelist somewhere to let programmers of the functional modification if it is confirmed so?

    leonardoAuthor
    Visitor II
    January 5, 2019

    This change does not make any sense! It does not matter if it is in a changelist, this is a BUG. If I use DMA in Circular mode and don't want to get an interrupt from transfer complete then I will not add HAL_I2SEx_TxRxCpltCallback(hi2s) into my code and problem solved, but if I do want to get an interrupt from transfer complete, then I need HAL library to call HAL_I2SEx_TxRxCpltCallback(hi2s) callback. It is so simple.

    Can somebody tell me in what circunstance the call to HAL_I2SEx_TxRxCpltCallback is a problem in circular mode???????? I think that the guy that update this code never use a I2S device...

    Please, solve it!!!!!!!

    Technical Moderator
    January 11, 2019

    Hello,

    We passed your request internally to add HAL_I2SEx_TxRxCpltCallback with DMA in circular mode.

    Kind Regards,

    Imen.

    leonardoAuthor
    Visitor II
    January 15, 2019

    Thank Imen.

    meanwhile, could you provide a workaround?

    Visitor II
    September 30, 2019

    Any update on this? Definitely appears to be a bug.

    Visitor II
    October 7, 2020

    This is still an active bug in V1.25.0 of the hal library for the stm32f4 as of writing. Really confusing and inconsistent with the non RxTx implementation of the hal library .

    All in all confusing however. Can we please get this fixed?

    Technical Moderator
    October 8, 2020

    Hello @Geekboy1011​ ,

    After check internally with our Development team, the fix will be available in next patch release of STM32CubeF4.

    Actually, I don’t have an exact date as we have released the last package on 20W34.

    I will keep you updated on this topic.

    Thanks

    Imen

    Visitor II
    October 8, 2020

    Thanks for the response! Glad to hear its getting fixed :)

    I look forward to the updates and will keep an eye for the realease when it gets here!

    Technical Moderator
    October 8, 2020

    You are welcome @Geekboy1011​ and thank you for your patience.

    Visitor II
    November 3, 2020

    Just following up, A patch was released on Oct 22, 1.25.2 It included a fix for i2c but no patch for this has been released to date.

    Is there any ETA on this patch being provided.

    Thanks again

    Visitor II
    November 20, 2020

    AFAIK no solution has been updated yet, This is what i came up with for the time being.

       

    	HAL_I2SEx_TransmitReceive_DMA(&hi2s2, (uint16_t*) &qbuff, (uint16_t*) &rbuff, BUFFER_SIZE *2);
    	hi2s2.hdmarx->XferCpltCallback = Custom_TxRxDMACplt;
    	hi2s2.hdmarx->XferHalfCpltCallback = Custom_TxRxDMAHalfCplt;
    	hi2s2.hdmatx->XferCpltCallback = Custom_TxRxDMACplt;
    	hi2s2.hdmatx->XferHalfCpltCallback = Custom_TxRxDMAHalfCplt;
     
    static void Custom_TxRxDMAHalfCplt(DMA_HandleTypeDef *hdma)
    {
     I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
     if (hi2s->hdmarx == hdma)
     {
    	 I2SEx_RxHalfCpltCallback(hi2s);
     }
     else if (hi2s->hdmatx == hdma){
    	 I2SEx_TxHalfCpltCallback(hi2s);
     }
    }
     
    void I2SEx_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s) {
    	
    }
     
    void I2SEx_TxCpltCallback(I2S_HandleTypeDef *hi2s) {
    	
    }
     
    void I2SEx_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s) {
    	return;
    }
     
    void I2SEx_RxCpltCallback(I2S_HandleTypeDef *hi2s) {
    		return;
    }
     

    In short just overwrite their call backs and implement our own, its a cludge but at least it should work even once the updates comeout and properly service these routines.