Unable to reinitialize SAI peripheral
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-10-09 7:27 AM
Hi,
I'm working with self designed board (STM32F765 MCU) and currently able to initialize SAI2 peripheral to work with codec in DMA mode.
At some point in my code, I need to change the sample rate of my codec (through MCLK).
The sequence of operations is basically as follows:
//1. DeInit SAI
HAL_SAI_DeInit(&hsai_BlockB2); //Deinit SAI_MODEMASTER_TX block set at old AudioFrequency
HAL_SAI_DeInit(&hsai_BlockA2); //Deinit SAI_MODESLAVE_RX block
//2 Init SAI with new freq. SAI_AUDIO_FREQUENCY_96K
hsai_BlockA2.Instance = SAI2_Block_A;
hsai_BlockA2.Init.AudioMode = SAI_MODESLAVE_RX;
hsai_BlockA2.Init.Synchro = SAI_SYNCHRONOUS;
hsai_BlockA2.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
hsai_BlockA2.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
hsai_BlockA2.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
hsai_BlockA2.Init.MonoStereoMode = SAI_STEREOMODE;
hsai_BlockA2.Init.CompandingMode = SAI_NOCOMPANDING;
hsai_BlockA2.Init.TriState = SAI_OUTPUT_NOTRELEASED;
if (HAL_SAI_InitProtocol(&hsai_BlockA2, SAI_I2S_STANDARD, SAI_PROTOCOL_DATASIZE_16BIT, 2) != HAL_OK)
{
Error_Handler();
}
hsai_BlockB2.Instance = SAI2_Block_B;
hsai_BlockB2.Init.AudioMode = SAI_MODEMASTER_TX;
hsai_BlockB2.Init.Synchro = SAI_ASYNCHRONOUS;
hsai_BlockB2.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE;
hsai_BlockB2.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
hsai_BlockB2.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
hsai_BlockB2.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_96K;
hsai_BlockB2.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
hsai_BlockB2.Init.MonoStereoMode = SAI_STEREOMODE;
hsai_BlockB2.Init.CompandingMode = SAI_NOCOMPANDING;
hsai_BlockB2.Init.TriState = SAI_OUTPUT_NOTRELEASED;
if (HAL_SAI_InitProtocol(&hsai_BlockB2, SAI_I2S_STANDARD, SAI_PROTOCOL_DATASIZE_16BIT, 2) != HAL_OK)
{
Error_Handler();
}
//3 custom function that reinit codec
Codec_Init();
//4. restart DMA tx and rx
Default_Handler:
Infinite_Loop:
b Infinite_Loop
.size Default_Handler, .-Default_Handler
- Labels:
-
STM32Cube MCU Packages
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-10-09 8:02 AM
Did you stop DMA?
I'm doing that on a F767 this way:
- stop DMA (circular mode) with HAL_SAI_DMAStop(), that includes FIFO flush and SAI disable
- then I set the MCKDIV bits in CR1
- then restart DMA with HAL_SAI_Receive_DMA() (modified for DBM)
So no complete init / deinit. (I'm using HAL only for start / stop DMA)
/* clear and set sampling rate */
u32MckDivNew = some define depending on sampling rate for the divider...
SAI1_Block_A->CR1 &= ~SAI_xCR1_MCKDIV;
SAI1_Block_A->CR1 |= u32MckDivNew;
PS: I just see that probably the link between DMA and SAI is gone after your De-Init.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-10-09 9:03 AM
Hi LCE,
Thank you for your quick reply.
I tried first, as you suggested, to stop DMA with the function HAL_SAI_DMAStop(), but without success.
If I call HAL_SAI_DMAStop() at the same time as HAL_SAI_TxCpltCallback or HAL_SAI_RxCpltCallback, I get the following error: DMA_ERROR_NO_XFER.
If I make the call to HAL_SAI_DMAStop() somewhere else, I end up in the infinite loop of Default_Handler.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-10-09 12:19 PM
I'm using HAL only for start / stop DMA
And, like everything in HAL, that is also broken...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2023-10-09 10:24 PM
Thanks for that hint, I'll get back to this.
