cancel
Showing results for 
Search instead for 
Did you mean: 

Switching Between Internal and External Audio Clock Sources and back again

CherrySnacker
Associate

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);
    }
2 REPLIES 2
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.