2017-07-18 09:34 AM
Hi,
I'm trying to use the STM32F746 I2S2 with DMA (to transmit data), but my datas are send in the wrong byte order.
My I2S configuration is : slave TX 32bits @ 192KHz
The DMA send data from a 32bits array in memory to the I2S peripheral.
My 32bits array is filled with the value 0x12345678.
Problem is, on the reception side I receive the value : 0x56781234.
Apparently the I2S peripheral only handle 16bits values. So when DMA send 32bits values, the I2S start sending the lower part of it (0x5678) before the higher part (0x1234).
I tried different configuration for the DMA (normal/circular, FIFO enable/disable, different word length) but nothing worked.
Do you have any idea if it's possible to send the data in the correct order ?
Thank you.
Here are my I2S and DMA configs :
hi2s2.Instance = SPI2;
hi2s2.Init.Mode = I2S_MODE_SLAVE_TX; hi2s2.Init.Standard = I2S_STANDARD_PHILIPS; hi2s2.Init.DataFormat = I2S_DATAFORMAT_32B; hi2s2.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE; hi2s2.Init.AudioFreq = I2S_AUDIOFREQ_192K; hi2s2.Init.CPOL = I2S_CPOL_LOW; hi2s2.Init.ClockSource = I2S_CLOCK_PLL;hdma_spi2_tx.Instance = DMA1_Stream4;
hdma_spi2_tx.Init.Channel = DMA_CHANNEL_0; hdma_spi2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_spi2_tx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_spi2_tx.Init.MemInc = DMA_MINC_ENABLE; hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; hdma_spi2_tx.Init.Mode = DMA_CIRCULAR; hdma_spi2_tx.Init.Priority = DMA_PRIORITY_LOW; hdma_spi2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;#issue #endian #endianness #byte-order #i2s #stm32f7 #dma2017-07-18 11:21 AM
It's a small endian machine, SPI can control the MSB/LSB issues, but will will likely have to manage the creation of your data in a form that gets it to the end-point in the form you want.
There should be some byte/word swapping instructions, here you'd do a 16-bit rotate.
2017-07-18 12:47 PM
Apparently the I2S peripheral only handle 16bits values.
Yes, but it's clearly written in the I2S chapter of the RM. There's even an example given, showing the ordering of halfwords in 32-bit transfer.
So when DMA send 32bits values, the I2S start sending the lower part of it (0x5678) before the higher part (0x1234).
No. If you'd really use DMA to use a word-wide transfer, the upper 16-bit would get thrown away entirely. But that's probably not what you want either.
DMA in STM32 can't reorder the halfwords.
As Clive said above, you have to prepare the data to respect this ordering. ARMs have barrel shift ever since, so it's only one extra instruction per word.
OTOH, the 'F746 has SAI, check it out.
JW
2017-07-19 02:02 AM
Ok, so if I understand my only option is to reorder the samples manually before sending them.
Apparently the I2S peripheral only handle 16bits values.
Yes, but it's clearly written in the I2S chapter of the RM. There's even an example given, showing the ordering of halfwords in 32-bit transfer.
In the RM example they are transmitting the 24bits word 0x8EAA33. They start transmitting the higher part 0x8EAA before the lower part 0x3300 (which is correct, no half word swapping).
2017-07-19 04:30 AM
They start transmitting the higher part 0x8EAA before the lower part 0x3300 (which is correct, no half word swapping).
But that IS the half word swapping, given the processor is little-endian, as Clive pointed out.
Draw yourself a diagram how those halfwords are stored in the memory.
JW