2026-01-17 5:54 PM
Hi,
I want to get synchronized samples from 4 microphones connected via I2S2 and I2S3. First I set one as master and other as slave and just connect Clock and Word Select, but I have only 0 values on slave interface. Is it possible to do it this way? Or there is another better one?
I am using STM32H533
Solved! Go to Solution.
2026-01-18 5:53 AM - edited 2026-01-18 5:55 AM
>I had similar problem and after long time searching i found: it was on the wrong pin tx <--> rx swapped.
The rx was on the tx pin...thats what i tried to explain. (Dont ask me why...)
Look in rm of your chip, registers of the I2C : is there a swap bit ? (swap rx - tx ) .
from H743 :
2026-01-17 6:23 PM - edited 2026-01-17 6:31 PM
I connected oscilloscope to both master and slave interfaces and both seems to be working fine (there is data that changes when I make noise). Unfortunately the problem is in GPDMA configuration and I cannot find it.
2026-01-18 5:01 AM
Hi,
> Is it possible to do it this way?
Yes, perfect. I do same to sync 3 I2S streams , just for output to dacs, but for input is same connection, clk+ws from master -> slave(s) .
+ for DMA:
You have to setup two dma channels, circular mode , check data size is correct for I2S and memory.
Enable callbacks in Cube -> project manager -> advanced : callbacks for SAI / I2S (whatever you use).
In half/full callbacks then ...use/copy the data.
2026-01-18 5:12 AM - edited 2026-01-18 5:35 AM
Thank you for your reply.
I have two dma channels configured as below:
/* I2S2 DMA Init */
/* GPDMA1_REQUEST_SPI2_RX Init */
NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
NodeConfig.Init.Request = GPDMA1_REQUEST_SPI2_RX;
NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;
NodeConfig.Init.SrcInc = DMA_SINC_FIXED;
NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;
NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD;
NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
NodeConfig.Init.SrcBurstLength = 1;
NodeConfig.Init.DestBurstLength = 1;
NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT1;
NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
NodeConfig.Init.Mode = DMA_NORMAL;
NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
if (HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel0) != HAL_OK)
{
Error_Handler();
}
if (HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel0, NULL, &Node_GPDMA1_Channel0) != HAL_OK)
{
Error_Handler();
}
if (HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel0) != HAL_OK)
{
Error_Handler();
}
handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;
handle_GPDMA1_Channel0.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;
handle_GPDMA1_Channel0.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
handle_GPDMA1_Channel0.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;
handle_GPDMA1_Channel0.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
handle_GPDMA1_Channel0.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
if (HAL_DMAEx_List_Init(&handle_GPDMA1_Channel0) != HAL_OK)
{
Error_Handler();
}
if (HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel0, &List_GPDMA1_Channel0) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(i2sHandle, hdmarx, handle_GPDMA1_Channel0);
if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0, DMA_CHANNEL_NPRIV) != HAL_OK)
{
Error_Handler();
}
/* I2S3 DMA Init */
/* GPDMA1_REQUEST_SPI3_RX Init */
NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
NodeConfig.Init.Request = GPDMA1_REQUEST_SPI3_RX;
NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;
NodeConfig.Init.SrcInc = DMA_SINC_FIXED;
NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;
NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD;
NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
NodeConfig.Init.SrcBurstLength = 1;
NodeConfig.Init.DestBurstLength = 1;
NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT1;
NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
NodeConfig.Init.Mode = DMA_NORMAL;
NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
if (HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel1) != HAL_OK)
{
Error_Handler();
}
if (HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel1, NULL, &Node_GPDMA1_Channel1) != HAL_OK)
{
Error_Handler();
}
if (HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel1) != HAL_OK)
{
Error_Handler();
}
handle_GPDMA1_Channel1.Instance = GPDMA1_Channel1;
handle_GPDMA1_Channel1.InitLinkedList.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;
handle_GPDMA1_Channel1.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
handle_GPDMA1_Channel1.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;
handle_GPDMA1_Channel1.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
handle_GPDMA1_Channel1.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
if (HAL_DMAEx_List_Init(&handle_GPDMA1_Channel1) != HAL_OK)
{
Error_Handler();
}
if (HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel1, &List_GPDMA1_Channel1) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(i2sHandle, hdmarx, handle_GPDMA1_Channel1);
if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel1, DMA_CHANNEL_NPRIV) != HAL_OK)
{
Error_Handler();
}I enabled I2S callback as you said, but it didn't help :(
Maybe there is something wrong with this DMA configuration? When I swap master/receive in cubemx always it is the slave which does not work (it produces callbacks, but reads only 0s).
EDIT: I use 4 x IC43434 microphones
EDIT2: Here are two screenshots from oscilloscope:
1. Shows clock signal on master vs on slave (probes were connected on two ends of cable that connets I2S2 and I2S3 clocks)
ch1 (yellow) - slave clock
ch4 (blue) - master clock
2. Shows data from microphones
ch1 (yellow) clock
ch2 (turqoise) ws
ch3 (pink) i2s3 (slave) data
ch4 (blue) i2s2 (master) data
If I can provide you with more information, let me know.
2026-01-18 5:38 AM
>the slave which does not work (it produces callbacks, but reads only 0s).
Are you sure to read the pin with the data ?
I had similar problem and after long time searching i found: it was on the wrong pin tx <--> rx swapped.
+
Try the SAI , set to I2S mode; the SAI worked in all my tests perfect (the I2S not...but didnt test on H533).
2026-01-18 5:47 AM - edited 2026-01-18 5:52 AM
>Are you sure to read the pin with the data ?
Yes, I double checked:
/**I2S2 GPIO Configuration
PC2 ------> I2S2_SDI
PB1 ------> I2S2_WS
PB2 ------> I2S2_CK
*/
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF6_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/**I2S3 GPIO Configuration
PA4 ------> I2S3_WS
PB0 ------> I2S3_SDI
PC10 ------> I2S3_CK
*/
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF6_SPI3;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI3;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF6_SPI3;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
Also, after swapping master / slave roles in CubeMX, there is data on new master (previous slave), but there is no data on new slave (previous master). So I checked that I2S2 and I2S3 works while in master mode but none of them works as slave.
EDIT:
>Try the SAI , set to I2S mode; the SAI worked in all my tests perfect (the I2S not...but didnt test on H533).
I am new to SAI, but unfortunately, I cannot find any proof that there is any on H533RE.
2026-01-18 5:53 AM - edited 2026-01-18 5:55 AM
>I had similar problem and after long time searching i found: it was on the wrong pin tx <--> rx swapped.
The rx was on the tx pin...thats what i tried to explain. (Dont ask me why...)
Look in rm of your chip, registers of the I2C : is there a swap bit ? (swap rx - tx ) .
from H743 :
2026-01-18 9:04 AM
It worked, thank you very much!
I wonder why did Cube configure it differently?
For future generations, here you have functions that helped mi resolve the issue:
2026-01-18 9:52 AM
>I wonder why did Cube configure it differently?
that was my > (Dont ask me why...)
Maybe someone of the ingenious HAL designers was thinking: if its a slave now, so tx/rx has to be swapped.
Might be useful, to avoid swapping the wires if changing from master to slave ---
BUT: it should be a setting in Cube, that can be set or not set - not a hidden setting !
Dont ask me, how many hours i needed to find this sh.. quirk.