cancel
Showing results for 
Search instead for 
Did you mean: 

Issue with SAI Protocol Data Transmission at Higher Frequencies on STM32L476RG

kmkoo
Associate III

Hello STM32 Community,

I am encountering an issue with the SAI (Serial Audio Interface) protocol on my STM32L476RG board and am hopeful that someone with a similar experience might offer some guidance.

Issue Description:

While attempting to transmit data using the SAI protocol, the board is not adhering to the designated transmission frequencies above 32kHz. Specifically:

  • At 32kHz and below, data transmission occurs as expected.
  • At 48kHz, 96kHz, and 192kHz, data is transmitted at an unexpected 64kHz instead.

Steps Taken:

I have explored various configurations and settings without success in isolating the issue.

Your insights into why this misalignment in transmission frequency might be occurring and potential resolution strategies would be greatly appreciated. Thank you in advance for your time and assistance.

8 REPLIES 8

How is SAI clocked?

JW

LCE
Principal

"32 kHz works, the higher sampling rates run with 64 kHz"

=> that sounds very much like you don't control the clocks to the SAI correctly, as @waclawek.jan already pointed out.

So please show us the input clock to the SAI peripheral and all clock relevant registers:

CR1 (MCKDIV, NODIV), FRCR (FSOFF, FSALL), SLOTR

My guess is that either the clock input to the SAI is not fitting for 48/96 kHz, or that MCKDIV / NODIV settings are wrong.

My SAI channel is set as the following code.

static void MX_SAI1_Init(void)

{

hsai_BlockA1.Instance = SAI1_Block_A;

hsai_BlockA1.Init.Protocol = SAI_FREE_PROTOCOL;

hsai_BlockA1.Init.AudioMode = SAI_MODEMASTER_TX;

hsai_BlockA1.Init.DataSize = SAI_DATASIZE_32;

hsai_BlockA1.Init.FirstBit = SAI_FIRSTBIT_MSB;

hsai_BlockA1.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;

hsai_BlockA1.Init.Synchro = SAI_ASYNCHRONOUS;

hsai_BlockA1.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;

hsai_BlockA1.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;

hsai_BlockA1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;

hsai_BlockA1.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_48K;

hsai_BlockA1.Init.SynchroExt = SAI_SYNCEXT_DISABLE;

hsai_BlockA1.Init.MonoStereoMode = SAI_STEREOMODE;

hsai_BlockA1.Init.CompandingMode = SAI_NOCOMPANDING;

hsai_BlockA1.Init.TriState = SAI_OUTPUT_NOTRELEASED;

hsai_BlockA1.FrameInit.FrameLength = 32;

hsai_BlockA1.FrameInit.ActiveFrameLength = 1;

hsai_BlockA1.FrameInit.FSDefinition = SAI_FS_STARTFRAME;

hsai_BlockA1.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;

hsai_BlockA1.FrameInit.FSOffset = SAI_FS_FIRSTBIT;

hsai_BlockA1.SlotInit.FirstBitOffset = 0;

hsai_BlockA1.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;

hsai_BlockA1.SlotInit.SlotNumber = 1;

hsai_BlockA1.SlotInit.SlotActive = 0x0000FFFF;

if (HAL_SAI_Init(&hsai_BlockA1) != HAL_OK)

{

Error_Handler();

}

}

And my clock configuration is as follows.

void SystemClock_Config(void)

{

if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)

{

Error_Handler();

}

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;

RCC_OscInitStruct.HSIState = RCC_HSI_ON;

RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;

RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;

RCC_OscInitStruct.PLL.PLLM = 1;

RCC_OscInitStruct.PLL.PLLN = 10;

RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;

RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;

RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;

if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)

{

Error_Handler();

}

 

/** Initializes the CPU, AHB and APB buses clocks

*/

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK

|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

 

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)

{

Error_Handler();

}

}

I also attached clock configuration images in IDE. Let me know if any additional information is needed. Thank you so much in advance.

kmkoo
Associate III

Hi, as I replied to waclawek.jan, my code is as follows.

static void MX_SAI1_Init(void)

{

hsai_BlockA1.Instance = SAI1_Block_A;

hsai_BlockA1.Init.Protocol = SAI_FREE_PROTOCOL;

hsai_BlockA1.Init.AudioMode = SAI_MODEMASTER_TX;

hsai_BlockA1.Init.DataSize = SAI_DATASIZE_32;

hsai_BlockA1.Init.FirstBit = SAI_FIRSTBIT_MSB;

hsai_BlockA1.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;

hsai_BlockA1.Init.Synchro = SAI_ASYNCHRONOUS;

hsai_BlockA1.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;

hsai_BlockA1.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;

hsai_BlockA1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_EMPTY;

hsai_BlockA1.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_48K;

hsai_BlockA1.Init.SynchroExt = SAI_SYNCEXT_DISABLE;

hsai_BlockA1.Init.MonoStereoMode = SAI_STEREOMODE;

hsai_BlockA1.Init.CompandingMode = SAI_NOCOMPANDING;

hsai_BlockA1.Init.TriState = SAI_OUTPUT_NOTRELEASED;

hsai_BlockA1.FrameInit.FrameLength = 32;

hsai_BlockA1.FrameInit.ActiveFrameLength = 1;

hsai_BlockA1.FrameInit.FSDefinition = SAI_FS_STARTFRAME;

hsai_BlockA1.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;

hsai_BlockA1.FrameInit.FSOffset = SAI_FS_FIRSTBIT;

hsai_BlockA1.SlotInit.FirstBitOffset = 0;

hsai_BlockA1.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;

hsai_BlockA1.SlotInit.SlotNumber = 1;

hsai_BlockA1.SlotInit.SlotActive = 0x0000FFFF;

if (HAL_SAI_Init(&hsai_BlockA1) != HAL_OK)

{

Error_Handler();

}

}

And my clock configuration is as follows.

void SystemClock_Config(void)

{

if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)

{

Error_Handler();

}

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;

RCC_OscInitStruct.HSIState = RCC_HSI_ON;

RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;

RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;

RCC_OscInitStruct.PLL.PLLM = 1;

RCC_OscInitStruct.PLL.PLLN = 10;

RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;

RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;

RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;

if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)

{

Error_Handler();

}

 

/** Initializes the CPU, AHB and APB buses clocks

*/

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK

|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

 

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)

{

Error_Handler();

}

}

I also attached clock configuration images in IDE. Let me know if any additional information is needed. Thank you so much in advance.

LCE
Principal

1. Please don't post the same things twice. Even if you reply person X, then person Y can see the reply.

2. Instead of some pictures, the value of the SAI input clock would have been enough.

3. I don't care for CubeMX settings, I asked for register contents.

Now do the following:

- read and understand chapter 43.3.8 of the ref manual RM0351

- check the register settings

- do some math as shown in the ref manual concerning the clocks

Or simply start your CubeMX again, and start setting the SAI to the highest sampling rate you need, then probably it will show that you need to change the input clock settings to the SAI. But that way you will not get any more understanding of the SAI than before.

That said, for 192 kHz you need  256 x 192 kHz = 49.152 MHz.

BTW, audio quality will be terrible with the jittery HSI.

AScha.3
Chief II

easy test , to see whats possible (with your clock settings! ) :

look in Cube, what it calculates for your different output frequencies ->

AScha3_0-1697440691181.png

good clock chosen for 44.1 k ; now when choose 96k as desired output ->

AScha3_1-1697440826469.png

15% too high - but better not possible with this clock setting

AScha3_2-1697440961233.png

so you can optimize for one output frequency always, but for many frequencies will be some compromise.

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

Thank you so much. I will read the manual

Thank you so much!!