2025-07-22 2:52 PM
Hello,
I'm slowly losing my sanity so I figure I'd make a post here. I set up SAI4 to interface with BDMA, hoping to retrieve data from the onboard MEMS microphone and store it in a buffer in RAM_D3. Ideally I'd like for that data to be processed by the CPU, but I can't even get the buffer to fill up.
The following code produces the output below:
audio_buffer[0] = 5;
audio_buffer[1] = 6;
audio_buffer[2] = 7;
audio_buffer[3] = 8;
// ...
// Inside main loop:
printf("SAI State: %d \r\n", HAL_SAI_GetState(&hsai_BlockA4));
printf("SAI Error: %lu \r\n", HAL_SAI_GetError(&hsai_BlockA4));
printf("SAI Buffer Address: 0x%08lx\r\n", SAI4_Block_A->DR);
printf("DMA State: %d \r\n", HAL_DMA_GetState(&hdma_sai4_a));
printf("DMA Error: %lu \r\n", HAL_DMA_GetError(&hdma_sai4_a));
printf("Pointer location: %p \r\n", audio_buffer);
printf("Audio Buffer Data:\r\n");
for (int i = 0; i < 10; i++) {
printf("[%d]: %d\r\n", i, audio_buffer[i]);
}
As you can see, SAI4 is in HAL_SAI_STATE_BUSY_RX and BDMA is in HAL_DMA_STATE_BUSY. However, audio_buffer is not being filled. It's worth mentioning that there doesn't even seem to be zeroes coming into the buffer, as the values I set manually are never changed.
Does anyone know what may be causing this? I'll drop my CubeMX configuration, in case it is useful:
Thanks in advance :(
Solved! Go to Solution.
2025-07-24 12:24 PM
More info: HAL_SAI_Receive_DMA() triggers all FIFO callbacks but fills the buffer with zeroes. DCache is disabled. HAL_SAI_Receive_IT() triggers the full callback once and then gives a transfer error, does not even touch the buffer.
2025-07-24 1:43 PM
Getting a 63.3kHz signal from the clock on PE2, absolutely nothing on the PC1 data pin. I'm convinced the mic is defective.
2025-07-24 11:00 PM
> Getting a 63.3kHz signal ...
Does that frequency make sense? Just curious, I would have assumed it should be higher.
2025-07-25 10:15 AM - edited 2025-07-25 10:15 AM
I'm not entirely sure. I am admittedly a little confused on the SAI clocks. When I wrote this reply I had the mux on CubeMX configured to send a 4.096 MHz to SAI4, since I thought that met the specs for 16kHz audio with oversampling on and no internal clock divider. Then I switched it to 50 MHz since I read that CubeMX automatically adjusts the prescalers (therefore, higher frequency = better?). Neither of them work.
2025-07-25 11:11 AM
The SAI needs typ. Fs x 2048 as clock; so for 44k1 stereo I2S mode audio i use 90.333MHz sai clk.
For PDM mode - i dont know, but with 16 or 32 bit /sample it should be same.
2025-07-25 11:47 AM
I found a way to mux ~32.768 MHz (i.e. 16,000 * 2048) to the SAI4. With master clock division and oversampling disabled, I still get all zeroes. This is 16 bits per sample. If I probe the clock pin, I see 128kHz, which doesn't feel right either.
Thank you for the reply, I'll keep chipping away at this. The clock is a new lead. I'm just so lost on how to configure it properly (it looks like a lot of registers and formulas)
2025-07-25 1:59 PM
The SAI working fine - if you set it correct.
So read a bit....and you know, you dont get pcm data, but just a bit density pattern from the mic ?
PDM (Pulse Density Modulation) bitstream , read ->
The STM32 also provides software libraries, like X-CUBE-MEMSMIC1, to simplify development ->
https://github.com/STMicroelectronics/x-cube-memsmic1
Just look for examples, to see, how to set the SAI parameters. (yours wrong now....probably :)
2025-07-25 2:30 PM
I followed the first link you provided step-by-step and it's still all zeroes! I probed the CLK line and now it's 22kHz (the tutorial said to mux 2.048MHz to SAI4). I don't understand the math behind the clocking whatsoever.
2025-07-25 9:14 PM
I did eventually find the solution. To my original problem: I forgot to enable the active slot. It was that simple. Just go to CubeMX > SAI4 > Configuration > Active Slot and enable one or all of them.
To the zeroes problem: It was the peripheral clocks. I found this answer by JW which gave me an idea of what clock frequency I should aim for. From there I just messed around with the clock dividers until I got something very close, and now am getting a proper signal on PE2. Notably, it seems like there's something weird about the way the HAL calculates MCKDIV, so I just set the audio frequency to the one that's dependent on MCKDIV and the kernel clock and just calculated it myself with some help from the aforementioned post.
Thanks to everyone for your help!