cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F7 I2S DMA byte order issue

cbardou
Associate II
Posted on July 18, 2017 at 18:34

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 #dma
4 REPLIES 4
Posted on July 18, 2017 at 20:21

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.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on July 18, 2017 at 21:47

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

cbardou
Associate II
Posted on July 19, 2017 at 11:02

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).

Posted on July 19, 2017 at 13:30

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