2023-10-12 06:08 PM
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:
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.
2023-10-12 09:45 PM
How is SAI clocked?
JW
2023-10-12 10:06 PM
"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.
2023-10-13 07:17 AM - edited 2023-10-13 07:20 AM
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.
2023-10-13 07:19 AM - edited 2023-10-13 07:21 AM
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.
2023-10-15 11:24 PM
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.
2023-10-16 12:26 AM
easy test , to see whats possible (with your clock settings! ) :
look in Cube, what it calculates for your different output frequencies ->
good clock chosen for 44.1 k ; now when choose 96k as desired output ->
15% too high - but better not possible with this clock setting
so you can optimize for one output frequency always, but for many frequencies will be some compromise.
2023-10-19 06:34 AM
Thank you so much. I will read the manual
2023-10-19 06:34 AM
Thank you so much!!