2025-09-18 9:43 AM - last edited on 2025-09-25 6:42 AM by Saket_Om
Post edited by ST moderator to be inline with the community rules especially with the code sharing. In next time please use </> button to paste your code. Please read this post: How to insert source code
Hi,
On checking, I noticed a mismatch between the expected sampling frequency (44.1 kHz) and the actual frequency (46.875 kHz). Could this be the cause of the noise? Any suggestions on what might be going wrong?
For reference, I’m using SAI1_A with circular linked-list channel 12 of GPDMA1. The configuration details for SAI and GPDMA are provided below.
GPDMA Configuration:
handle_GPDMA1_Channel12.Instance = GPDMA1_Channel12;
handle_GPDMA1_Channel12.InitLinkedList.Priority = DMA_HIGH_PRIORITY;
handle_GPDMA1_Channel12.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
handle_GPDMA1_Channel12.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;
handle_GPDMA1_Channel12.InitLinkedList.TransferEventMode = DMA_TCEM_LAST_LL_ITEM_TRANSFER;
handle_GPDMA1_Channel12.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
SAI Configuration:
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_16;
hsai_BlockA1.Init.FirstBit = SAI_FIRSTBIT_MSB;
hsai_BlockA1.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
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_1QF;
hsai_BlockA1.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_44K;
hsai_BlockA1.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
hsai_BlockA1.Init.MckOutput = SAI_MCK_OUTPUT_DISABLE;
hsai_BlockA1.Init.MonoStereoMode = SAI_STEREOMODE;
hsai_BlockA1.Init.CompandingMode = SAI_NOCOMPANDING;
hsai_BlockA1.Init.TriState = SAI_OUTPUT_NOTRELEASED;
hsai_BlockA1.Init.PdmInit.Activation = DISABLE;
hsai_BlockA1.Init.PdmInit.MicPairsNbr = 1;
hsai_BlockA1.Init.PdmInit.ClockEnable = SAI_PDM_CLOCK1_ENABLE;
hsai_BlockA1.FrameInit.FrameLength = 32;
hsai_BlockA1.FrameInit.ActiveFrameLength = 16;
hsai_BlockA1.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
hsai_BlockA1.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
hsai_BlockA1.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
hsai_BlockA1.SlotInit.FirstBitOffset = 0;
hsai_BlockA1.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
hsai_BlockA1.SlotInit.SlotNumber = 2;
hsai_BlockA1.SlotInit.SlotActive = 0x00000003;
LinkList configuration:
pNodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
pNodeConfig.Init.Request = GPDMA1_REQUEST_SAI1_A;
pNodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
pNodeConfig.Init.Direction = DMA_MEMORY_TO_PERIPH;
pNodeConfig.Init.SrcInc = DMA_SINC_INCREMENTED;
pNodeConfig.Init.DestInc = DMA_DINC_FIXED;
pNodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_HALFWORD;
pNodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_BYTE;
pNodeConfig.Init.SrcBurstLength = 1;
pNodeConfig.Init.DestBurstLength = 1;
pNodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;
pNodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
pNodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
pNodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
pNodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
pNodeConfig.SrcAddress = 0;
pNodeConfig.DstAddress = 0;
pNodeConfig.DataSize = 0;
Thanks,
Jinal
2025-11-03 7:37 AM
Hi @LCE ,
Thanks for response.
The data read from flash and stored in the buffer matches the original WAV file data — we’ve verified this.
We also confirmed using a logic analyzer that the same data from the WAV file is being transmitted correctly on the I²S data line.
Additionally, a sine wave generated through code was played, which seems to be functioning correctly; however, this cannot be conclusively confirmed.
Now, how can we confirm whether the issue is related to the SAI peripheral, DMA, or something else?
Thanks,
Jinal
2025-11-03 8:05 AM
> Additionally, a sine wave generated through code was played,
> which seems to be functioning correctly;
> however, this cannot be conclusively confirmed.
Why not?
> Now, how can we confirm whether the issue is related to the SAI peripheral, DMA, or something else?
As I said, make the sine output work.
I would do it this way:
If that doesn't give a good sine at the amp's / DAC's output, then your SAI setup is at least part of the problem.
If that output is good, then your flash reading (maybe your sample "re-building" from bytes to 16/24/32 bits is bad?) and / or DMA setup and / or re-starting is the issue. Or maybe even the original file / waveform / amplitude?
It's important to not just do stuff, but to do it methodically. Step by step, only one change at a time, peripheral after peripheral, ... :D
2025-11-03 11:08 PM
Hi @LCE ,
Thanks for your response.
We observed an anomaly in the clock and FSYNC signals. Specifically, the first clock pulse appears wider (duty cycle: 36.36%, frequency: 2.182 MHz, width: 3.429 MHz), while the subsequent clock pulses (duty: 50%, frequency: 3 MHz, width: 6 MHz) behave as expected.
Additionally, we noticed that the FSYNC signal begins in the middle of a clock cycle.
Could you please review this behavior and suggest possible causes?
If this could be contributing to the noisy audio issue, please advise how we can resolve it.
Please refer to the attached images for the observed issue with the FSYNC and clock signals.
Thanks,
Jinal
2025-11-03 11:26 PM
Do you still have 2 SAI slots active? Not good for mono amp.
Also check if you have any uneven clock dividers.
2025-11-03 11:34 PM - edited 2025-11-04 3:59 AM
Hi,
Thanks for quick response,
We are transmitting stereo audio data, which is why the stereo mode is configured.
Kindly review our SAI and clock configuration as well.
Also, we have also tried to restart the SAI and start the SAI before playing audio but observed that CLK is not stopping and FSYNC getting delayed as per given delay.
__HAL_SAI_DISABLE(&hsai_BlockA1);
HAL_Delay(1);
__HAL_SAI_ENABLE(&hsai_BlockA1);
HAL_Delay(1);
Clock Configuration
< PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LTDC|RCC_PERIPHCLK_DSI
|RCC_PERIPHCLK_OSPI|RCC_PERIPHCLK_SAI1;
PeriphClkInit.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLL2;
PeriphClkInit.OspiClockSelection = RCC_OSPICLKSOURCE_PLL2;
PeriphClkInit.DsiClockSelection = RCC_DSICLKSOURCE_PLL3;
PeriphClkInit.LtdcClockSelection = RCC_LTDCCLKSOURCE_PLL3;
PeriphClkInit.PLL3.PLL3Source = RCC_PLLSOURCE_HSE;
PeriphClkInit.PLL3.PLL3M = 4;
PeriphClkInit.PLL3.PLL3N = 125;
PeriphClkInit.PLL3.PLL3P = 8;
PeriphClkInit.PLL3.PLL3Q = 2;
PeriphClkInit.PLL3.PLL3R = 24;
PeriphClkInit.PLL3.PLL3RGE = RCC_PLLVCIRANGE_0;
PeriphClkInit.PLL3.PLL3FRACN = 0;
PeriphClkInit.PLL3.PLL3ClockOut = RCC_PLL3_DIVP|RCC_PLL3_DIVR;
PeriphClkInit.PLL2.PLL2Source = RCC_PLLSOURCE_HSE;
PeriphClkInit.PLL2.PLL2M = 4;
PeriphClkInit.PLL2.PLL2N = 45;
PeriphClkInit.PLL2.PLL2P = 15;
PeriphClkInit.PLL2.PLL2Q = 2;
PeriphClkInit.PLL2.PLL2R = 1;
PeriphClkInit.PLL2.PLL2RGE = RCC_PLLVCIRANGE_0;
PeriphClkInit.PLL2.PLL2FRACN = 0;
PeriphClkInit.PLL2.PLL2ClockOut = RCC_PLL2_DIVP|RCC_PLL2_DIVQ;/>
SAI Configuration
<hsai_BlockA1.Instance = SAI1_Block_A;
hsai_BlockA1.Init.AudioMode = SAI_MODEMASTER_TX;
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.MckOutput = SAI_MCK_OUTPUT_DISABLE;
hsai_BlockA1.Init.MonoStereoMode = SAI_STEREOMODE;
hsai_BlockA1.Init.CompandingMode = SAI_NOCOMPANDING;
hsai_BlockA1.Init.TriState = SAI_OUTPUT_NOTRELEASED;
if (HAL_SAI_InitProtocol(&hsai_BlockA1, SAI_I2S_STANDARD, SAI_PROTOCOL_DATASIZE_16BIT, 4) != HAL_OK)/>
Thanks,
Jinal
2025-11-04 3:54 AM
Please edit your post and make it readable.
Use the </> button to post source code.
TAS2110:
oh my, a TDM device with a few registers, not the easiest way to start...
Are you sure that all registers are set correctly? For example, by default it wants to have 32 bit samples.
2025-11-04 4:09 AM
Start looking at the SAI registers, learn to understand the direct register settings, CubeMx & HAL are not perfect.
In the H733 the SAI only needs 3 to 4 registers for setup: CR1, (CR2,) FRCR, SLOTR.
The below example is for master RX, and as said above for a H733:
/* CR1: most important settings here
* DMA and SAI enable are set when started
* SAI_xCR1_MCKEN = 0 MCLK is OFF, we use extra I2S for MCLK cause we need OSR 128 at 200 kHz
* SAI_xCR1_OSR = 0 x256 oversampling
* SAI_xCR1_NODIV = 0 use SAI_xCR1_MCKDIV for sampling rate settings
* SAI_xCR1_SYNCEN = 00 async mode, SAI_1_A is master
* SAI_xCR1_CKSTR = 1 I2S: sample on SCK rising
* SAI_xCR1_LSBFIRST = 0 MSB first
* SAI_xCR1_DS = 111 32 bit data size
* SAI_xCR1_PRTCFG = 00 free protocol
* SAI_xCR1_MODE = 01 master receiver
*/
SAI1_Block_A->CR1 = ( SAI_CR1_MCKDIV_SR_200K | SAI_xCR1_CKSTR |
SAI_CR1_DS_XBIT | SAI_CR1_MODE_MSTR_RCV );
#if( 1 )
/* CR2 - unused: compander, FIFO flush and threshold EMPTY, tristate */
SAI1_Block_A->CR2 = 0;
#else
/* CR2 - unused: compander, FIFO flush and threshold HALF FULL, tristate */
SAI1_Block_A->CR2 = SAI_xCR2_FTH_1;
#endif
/* FRCR: frame configuration -> FS = LRCK */
SAI1_Block_A->FRCR = ( SAI_xFRCR_FSPOL | /* FS active high */
SAI_xFRCR_FSDEF | /* FS is start of frame AND channel side ID -> LeftRightCK */
SAI_FRCR_FSALL_32 | /* frame length active in bit clocks = 32 (-1) */
SAI_FRCR_FRL_64 ); /* frame length in bit clocks = 64 (-1) */
/* SLOTR: slot configuration -> SCLK / LRCK */
SAI1_Block_A->SLOTR = ( SAI_SLOTR_SLOTEN_12 | /* slots 1 & 2 active */
SAI_SLOTR_NBSLOT_2 | /* number of slots in frame = 2 (-1) */
SAI_SLOTR_SLOTSZ_32 ); /* slot size = bits per channel */