Filling a Queue with Data from 4 Microphones from 2 different I2S Interfaces
Platform: STM32 Nucleo-H7A3ZI-Q
Goal: Read audio from four microphones in stereo mode (two mics per I²S interface) via DMA, then enqueue complete stereo frames for processing.
1. Hardware & DMA Setup
I2S1 handles Mic 1 (left) and Mic 2 (right).
I2S2 handles Mic 3 (left) and Mic 4 (right).
Each I2S interface uses DMA to fill its receive buffer (data_i2s[] and data_i2s_2[]).
2. Current Callback Code
void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s){
if(hi2s==&hi2s1){
if(x1Flag == 0){
valX1 = 0;
valX1 = sample_left = ((int32_t)data_i2s[0]) >> 8;
x1Flag = 1;
}else if(x2Flag == 0){
valX2 = 0;
valX2 = sample_right = ((int32_t)data_i2s[1]) >> 8;
x2Flag = 1;
/*if(x1Flag != 0 && x2Flag != 0){
enqueueData();
}*/
}
}else if (hi2s == &hi2s2){
if(y1Flag == 0){
valY1 = 0;
valY1 = sample_left_2 = ((int32_t)data_i2s_2[0]) >> 8;
y1Flag = 1;
}else if (y2Flag == 0){
valY2 = 0;
valY2 = sample_right_2 = ((int32_t)data_i2s_2[1]) >> 8;
y2Flag = 1;
/*if(y1Flag != 0 && y2Flag != 0){
enqueueData();
}*/
}
}
if(x1Flag != 0 && x2Flag != 0 && y1Flag != 0 && y2Flag != 0){
enqueueData();
}
}3. Observed Behavior
Often the callback only ever enters the hi2s1 branch and never the hi2s2 branch.
Other times, I see data from three mics but never from the fourth, so enqueueData() either never runs or runs with incomplete data.
4. What I’ve Already Checked
DMA handles are correctly linked to hi2s1 and hi2s2.
Interrupt priorities: I’ve ensured DMA and I2S IRQs don’t mask each other.
Buffer sizes: The receive arrays are distinct and large enough.
Flag reset: Flags are cleared immediately after calling enqueueData().
5. My Questions
How can I guarantee that both I²S interfaces complete their DMA transfer before enqueueData() fires?
Why might the hi2s2 branch be skipped or only partially served?
Is there a cleaner or more reliable pattern in FreeRTOS for gathering four DMA callbacks and pushing full stereo frames into a queue?
Thanks in advance for any suggestions!
