2023-10-09 07: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
2023-10-09 08:02 AM
Did you stop DMA?
I'm doing that on a F767 this way:
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.
2023-10-09 09: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.
2023-10-09 12:19 PM
I'm using HAL only for start / stop DMA
And, like everything in HAL, that is also broken...
2023-10-09 10:24 PM
Thanks for that hint, I'll get back to this.