2023-04-05 06:42 PM - edited 2023-11-20 08:52 AM
Hi everyone,
I am trying to get the SAI1 periperhal configured in I2S Standard mode going on the STM32H753ZI. During my testing sessions I found that my master clock is so far off it doesnt make sense.
Based on the figure 652 within the TRM, it shows that the MCLK_x is produced by having NOMCK = 0 and just having the sai_x_ker_ck divided by MCKDIV,
in which case should have been 98.304MHz/4 = 24.576MHz, but somehow getting 5MHz???
Current Configuration:
Things I have done thus far:
Picture of register of both SAI1 Block A and B
SAI 1 Block A reg:
SAI 1 Block B Reg:
Picture of SAI 1 Block A MCLK
2023-04-05 10:49 PM
At first glance the register settings look correct.
Have you checked the other clocks? Do you get the 6.144 MHz for SCLK ?
Have you checked the GPIO for MCLK, concerning the correct alternate function ?
As a workaround - mostly because I need other OSR ratios than 256/512 - I use another I2S peripheral as MCLK source.
2023-04-06 12:50 AM
Looks like I got it working-ish, It seems every other frequency works besides using the sample rate of 96kHz? Is there any particular reason for that?
2023-04-06 12:50 AM
Even using 96kHz with Over sampling on works. Just not 96kHz with over sampling off
2023-04-06 01:07 AM
I don't really understand your posts above...
So which clocks are actually how they are supposed to be?
You should have, at fs = 96 kHz:
LRCK = word clock = sampling rate fs = 96 kHz
SCLK = bit clock = 64 * fs = 6.144 MHz
and then your "problem child":
MCLK = (OSR + 1) * fs = 24.576 MHz or 49.152 MHz
Concerning the GPIO, have you checked the alternate function, and the speed setting?
Or maybe another peripheral sets up that GPIO after SAI init and takes over?
2023-04-06 10:32 AM
Sorry about the confusion,
The clock I am using for the SAI kernel is PLL2_P_CLK. Its set at 98.304MHz and its working correctly.
What I was trying to say was I have tried another sampling frequency of 48kHz, and 192kHz and they all output the correct clocks (FS, MCLK, and SCLK) its just whenever I have the sample frequency as 96kHz things go wonky. When I say sampling frequencyof (x)kHz I meant changing the MCKDIV and using the diagram above to get FS as the desired sample frequency. So the reply above me is what I am not getting however if I use another other frequencies I get the correct clocks.
Theres no other periperhal enabled as SAI is the only thing enable within my system right now
Concerns for the GPIO is that everything is set correctly all GPIO are set to max speed and the alt function are correct, as mentioned changing the FS to 48 or 192kHz works, I have audio being outputted right now, its just for 96kHz not working
2023-04-13 12:02 AM
@CLeo.1 Have you solved that problem? If yes, how?
If not: what are the exact register settings at 96 kHz, the peripheral clock, what do the output clocks do ?
2023-04-13 07:38 AM
The problem has not been solve.
The register settings is listed in the original question. The periperhal clock is using PLL2_P_CLK.
The output clocks are just shown in accurate, as shown in the original question, MCLK is completly wrong and the FS clock is shown also as 25MHz
2023-04-13 09:53 PM
Okay. Really strange. Especially the case that with OSR set it works.
Maybe you're not turning off the peripheral before changing the clock settings?
Do you use CubeMX / HAL for setup?
If yes, try using direct register settings, that gives you better control anyway.
It's not that many settings for I2S.
For inspiration, here's my SAI1 init, but for a H723/H735 (slightly different registers), with SAI1A as RX master and SAI1B as synced RX slave:
void SAI1_Init(void)
{
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* SAI 1 A, SYNC master, I2S INput --> ADC */
/* creates SCLK, LRCK */
/* DMA stuff simpler with SAI handle */
hSai_1_A.Instance = SAI1_Block_A;
/* Initialize the SAI state for DMA */
hSai_1_A.State = HAL_SAI_STATE_READY;
/* GPIO and DMA init */
SaiDmaGpio_Init(&hSai_1_A);
/* SAI register init */
/* CR2 - unused: compander, FIFO, tristate */
hSai_1_A.Instance->CR2 = 0;
/* 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
*/
hSai_1_A.Instance->CR1 = ( SAI_CR1_MCKDIV_SR_200K | SAI_xCR1_CKSTR |
SAI_CR1_DS_XBIT | SAI_CR1_MODE_MSTR_RCV );
/* FRCR: frame configuration -> FS = LRCK */
hSai_1_A.Instance->FRCR = 0;
hSai_1_A.Instance->FRCR |= SAI_xFRCR_FSPOL; /* FS active high */
hSai_1_A.Instance->FRCR |= SAI_xFRCR_FSDEF; /* FS is start of frame AND channel side ID -> LeftRightCK */
hSai_1_A.Instance->FRCR |= SAI_FRCR_FSALL_32; /* frame length active in bit clocks = 32 (-1) */
hSai_1_A.Instance->FRCR |= SAI_FRCR_FRL_64; /* frame length in bit clocks = 64 (-1) */
/* SLOTR: slot configuration -> SCLK / LRCK */
hSai_1_A.Instance->SLOTR = 0;
hSai_1_A.Instance->SLOTR |= SAI_SLOTR_SLOTEN_ALL; /* all slots active */
hSai_1_A.Instance->SLOTR |= SAI_SLOTR_NBSLOT_2; /* number of slots in frame = 2 (-1) */
hSai_1_A.Instance->SLOTR |= SAI_SLOTR_SLOTSZ_32; /* slot size = bits per channel */
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* SAI 1 B, sync slave, I2S INput --> ADC */
/* SCLK, LRCK from master SAI_1_A */
/* DMA stuff simpler with SAI handle */
hSai_1_B.Instance = SAI1_Block_B;
/* Initialize the SAI state */
hSai_1_B.State = HAL_SAI_STATE_READY;
/* GPIO and DMA init */
SaiDmaGpio_Init(&hSai_1_B);
/* SAI register init */
/* CR2 - unused: compander, FIFO, tristate */
hSai_1_B.Instance->CR2 = 0;
/* CR1: most important settings here
* DMA and SAI enable are set when started
* SAI_xCR1_OSR = 0 x256 oversampling
* SAI_xCR1_NODIV = 0 use SAI_xCR1_MCKDIV for sampling rate settings
* SAI_xCR1_SYNCEN = 01 sync mode same block, 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 = 11 slave receiver
*/
hSai_1_B.Instance->CR1 = ( SAI_CR1_SYNCEN_SYNC_INT | SAI_xCR1_CKSTR |
SAI_CR1_DS_XBIT | SAI_CR1_MODE_SLAVE_RCV );
/* FRCR: frame configuration -> FS = LRCK */
hSai_1_B.Instance->FRCR = hSai_1_A.Instance->FRCR; /* copy from sync master */
/* SLOTR: slot configuration -> SCLK / LRCK */
hSai_1_B.Instance->SLOTR = hSai_1_A.Instance->SLOTR; /* copy from sync master */
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* GCR:
* - for both blocks of SAI
* - SYNC configuration to other SAIs / blocks
* - SAI1:
* - output: A is master
* - input: none
*/
SAI1->GCR = SAI_GCR_SYNCOUT_A;
/* calculate audio sampling rate */
u32SaiSamplingRate = SaiGetSamplingRate(&hSai_1_A);
}
2023-04-14 07:37 AM
I to find it very bizzare as well.
The periperhal is not enable when doing the configuration and clock selection (Double checked in code). Enabled only after everything is set.
I use HAL just for the initiation as theres no LL variant of it, however the registers setup all looks correct and worked on the math myself for the MCLK and all the other output clock based on the clock generation diagram, it should theoretical be fine.