cancel
Showing results for 
Search instead for 
Did you mean: 

Switching Between Internal and External Audio Clock Sources and back again

CherrySnacker
Associate II

I’m implementing an audio clock source switching mechanism where the system runs on the internal audio clock if no external clock is detected. As soon as an external clock becomes available, it switches to use that external clock source.

This works initially, but when the external clock is lost for any reason and the system switches back to the internal clock — then later detects the external clock again and switches back — I notice that data is still being received through the SAIs, but the clock is no longer synchronized with the external clock source. It seems to continue running from the internal clock instead.

Is what I’m trying to do here actually possible?

 void SwitchAudioMode(eAudioClockSelection::Enum ClockSelection)
    {
        if (gAudioMode == ClockSelection)
        {
            return;
        }
        else
        {
            gAudioMode = ClockSelection;
        }

        HAL_SAI_Abort(&hsai_BlockA1);
        HAL_SAI_Abort(&hsai_BlockA3);
        HAL_SAI_Abort(&hsai_BlockB3);

        HAL_SAI_DMAStop(&hsai_BlockA1);
        HAL_SAI_DMAStop(&hsai_BlockA3);
        HAL_SAI_DMAStop(&hsai_BlockB3);

        HAL_SAI_DeInit(&hsai_BlockA1);
        HAL_SAI_DeInit(&hsai_BlockA3);
        HAL_SAI_DeInit(&hsai_BlockB3);

        __HAL_RCC_SAI3_FORCE_RESET();
        __HAL_RCC_SAI3_RELEASE_RESET();
        __HAL_RCC_SAI1_FORCE_RESET();
        __HAL_RCC_SAI1_RELEASE_RESET();

        // Use Clock from A2B
        if (ClockSelection == eAudioClockSelection::External)
        {
            __HAL_RCC_SAI23_CONFIG(RCC_SAI23CLKSOURCE_PIN);
        }
        else
        {
            while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLL3RDY) == RESET);
            __HAL_RCC_SAI23_CONFIG(RCC_SAI23CLKSOURCE_PLL3);
        }
        HAL_SAI_Init(&hsai_BlockB3);
        HAL_SAI_Init(&hsai_BlockA3);
        HAL_SAI_Init(&hsai_BlockA1);

        // Start DMA for SAI1_A (RX from A2B_1 aka HUD)
        HAL_SAI_Receive_DMA(&hsai_BlockA1, (uint8_t *)&mRxHeadUnitA2B1Buffer[0], 2 * cNoOfBlockSamples * NUMBER_OF_A2B_DOWNSTREAM_CHANNELS);
        // Start DMA for SAI3_A (TX to AMP)
        HAL_SAI_Transmit_DMA(&hsai_BlockA3, (uint8_t *)&mTxTDM1Buffer[0], 2 * cNoOfBlockSamples * NUMBER_OF_TDM_CHANNELS);
        // Start DMA for SAI3_B (TX to AMP)
        HAL_SAI_Transmit_DMA(&hsai_BlockB3, (uint8_t *)&mTxTDM2Buffer[0], 2 * cNoOfBlockSamples * NUMBER_OF_TDM_CHANNELS);
    }
3 REPLIES 3
AScha.3
Super User

Hi,

 what is it for ? Because 3 SAI , 6 ch , but may lose clock connection ??

+

basically it should work to switch clk source, but i would stop DMA at first , to switching action.

If you feel a post has answered your question, please click "Accept as Solution".

There is an external clock when the connection via A2B (Automotive Audio Bus) is established, but it is not controlled by the ECU and may lose the clock signal. Basically, the ECU switches from the internal clock source to the external one when the A2B connection is established, and switches back when the A2B connection is lost. I want to ensure that the switching between clock sources is implemented correctly, as it seems to me that it is not working properly.

CherrySnacker
Associate II

When doing some additional tests here, it seems that there is an error (possibly on the DMA side), which only recovers when the STM32H750VB is power-cycled. When I simulate the clock loss behavior, I can see that the ECU switches back to the internal clock, but for some reason, the DMA transfer callback is no longer being called, which stops the audio loop.

If I re-download my application while debugging with Ozone, the issue still remains, and the DMA continues to show problems. I would expect that running the main initialization code would somehow resolve it, but that is not the case. Only a power cycle restores normal DMA operation.

The initial code works correctly when the ECU is power-cycled, but it encounters DMA issues if a clock loss occurs.

I cannot find any documentation showing a workaround or guidance on handling a DMA issue like this?