cancel
Showing results for 
Search instead for 
Did you mean: 

F4 I2S CubeMX problem in HAL_I2S_DMAStop

eugene239955_st
Associate II
Posted on January 05, 2016 at 08:26

I would like to point the attention of ST to the problem they have in the CubeMX generated code.

In HAL_StatusTypeDef HAL_I2S_DMAStop(I2S_HandleTypeDef *hi2s) function the procedure described in 26.6.4 I2S master mode of RM0390 is NOT followed!

It is clearly stated that ''To switch off the I2S, by clearing I2SE, it is mandatory to wait for TXE = 1 and BSY = 0.''

It is not done so and in 24 and 32 bit mode the next start usually gets shifted by 16 bit because of incompleted sequence during stop!

Following should be added before the __HAL_I2S_DISABLE(hi2s):

while(__HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_TXE) != 1 || __HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_BSY) != 0);

Also the timeout should be added and some protection of course in production version.

This bug has costed me about a day to track down.

Update. The fully define function:

__weak HAL_StatusTypeDef HAL_I2S_DMAStop(I2S_HandleTypeDef *hi2s)

{

    /* Process Locked */

    __HAL_LOCK(hi2s);

    /* Disable the I2S Tx/Rx DMA requests */

    hi2s->Instance->CR2 &= ~SPI_CR2_TXDMAEN;

    hi2s->Instance->CR2 &= ~SPI_CR2_RXDMAEN;

    /* Abort the I2S DMA Stream tx */

    if(hi2s->hdmatx != NULL)

    {

        HAL_DMA_Abort(hi2s->hdmatx);

    }

    /* Abort the I2S DMA Stream rx */

    if(hi2s->hdmarx != NULL)

    {

        HAL_DMA_Abort(hi2s->hdmarx);

    }

    // To switch off the I2S, by clearing I2SE, it is mandatory to wait for TXE = 1 and BSY = 0.

    uint32_t tickstart = 0;

    tickstart = HAL_GetTick();

    while(__HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_TXE) != 1 || __HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_BSY) != 0)

    {

    

if((HAL_GetTick() - tickstart ) > HAL_TIMEOUT_I2S_ABORT)

{

/* Update error code */

    

hi2s->ErrorCode |= HAL_I2S_ERROR_TIMEOUT;

/* Process Unlocked */

__HAL_UNLOCK(hi2s);

/* Change the I2S state */

hi2s->State = HAL_I2S_STATE_TIMEOUT;

return HAL_TIMEOUT;

}

    }

    /* Disable I2S peripheral */

    __HAL_I2S_DISABLE(hi2s);

    hi2s->State = HAL_I2S_STATE_READY;

    /* Process Unlocked */

    __HAL_UNLOCK(hi2s);

    return HAL_OK;

}

In .h:

#define HAL_TIMEOUT_I2S_ABORT    ((uint32_t)1000)  /* 1s */

#define HAL_I2S_ERROR_TIMEOUT       ((uint32_t)0x00000040)    /*!< I2S transfer error          */

2 REPLIES 2
Walid FTITI_O
Senior II
Posted on January 06, 2016 at 11:58

Hi shamaev.eugene,

Thanks for highlighting this issue. It is reported internally

.

-

  

Hannibal -

Walid FTITI_O
Senior II
Posted on March 31, 2016 at 13:35

Hi  shamaev.eugene, 

Your feedback will be  implimented in a new release. Thanks for contibution.

-Hannibal-