cancel
Showing results for 
Search instead for 
Did you mean: 

The DMA length parameter defect of the HAL_I2S_Receive_DMA().

Takemasa
Associate III

Hi.

The HAL_I2S_Receive_DMA() has defect around its size parameter.

The UM1905 explain the size parameter as following :

when a 24-bit data frame or a 32-bit data

frame is selected the Size parameter means the number of

16-bit data length

That mean, regardless of the data size, the buffer size to the DMA have to be measured by the count of the int16_t. On the other word, the length by int32_t have to be multiplied by 2.

I saw several example on the internet which follows this specification.

But, this description is incorrect. The HAL_I2S_Receive_DMA() interprets its size parameter as number of the int32_t type in the buffer, when the data type of I2S is 32 or 24bit.

This behavior can be confirmed by reading stm32f7xx_hal_i2s.c. As you can see the attached screenshot, this APi is compensating size parameter when the data is 24 or 32bit. So, the behavior and documentation doesn't match.

I have two request.

  1. Which documentation or source code is right?
  2. Please fix the wrong one.

As I checked, this problem was observed on Nucleo F722, F446 and G431.

The firmware of the F722 is the STM32Cube FW_F7 V1.15.0

1 REPLY 1
Georgy Moshkin
Senior II

I recommend using pre-filled buffer in such cases. E.g., we can initialize buffer filled with 1 2 3 4 5... and output it back using UART to see what values are actually being overwritten. To set right length for I2S DMA transfers, we need to know several parameters:

1. Data Width of DMA configuration (Byte, Half Word or Word)
2. I2S data configuration (16 or 24/32-bit data)
3. Array type (uint8_t, uint16_t or uint32_t)

E.g.,

assume that DMA data width is set to Word, I2S data type is set to 24/32-bit, and array type is uint32_t:

 

 

 

#define ARRAY_SIZE 10
uint32_t i2sBuffer[ARRAY_SIZE]={0x11111111, 0x22222222, 0x33333333, 0x44444444,
0x55555555, 0x66666666, 0x77777777, 0x88888888,
0x99999999,0xAAAAAAAA};

// let's test it:
HAL_I2S_Receive_DMA(&hi2s1, (uint16_t *)&i2sBuffer[0], 4);
// this will fill 8 elements of i2sBuffer array (all except 0x99999999 and 0xAAAAAAAA)
// thus, we can't pass ARRAY_SIZE (10), because it will write 20 elements
HAL_I2S_Receive_DMA(&hi2s1, (uint16_t *)&i2sBuffer[0], ARRAY_SIZE/2);
// because dma data width is Word (32-bit), but this function assumes 16-bit data.

 

 

 

HAL_I2S_Receive_DMA will multiply ARRAY_SIZE by 2, and will receive 10 32-bit elements

now, if DMA Data Width is set to Half Word, this will be correct:

 

 

 

HAL_I2S_Receive_DMA(&hi2s1, (uint16_t *)&i2sBuffer[0], ARRAY_SIZE);

 

 

 

 

HAL_I2S_Receive_DMA will multiply ARRAY_SIZE by 2, and will receive 20 16-bit elements (which is 10 32-bit elements)
 

Source: I2S data size (thundertronics.com)

Note that SPI/I2S data register (SPI_DR) is 16-bit. I've checked my I2S projects and I always configured I2S DMA as half word/half word (16-bit/16-bit) despite using 32-bit I2S ADC and 32-bit arrays. From my understanding, I2S provides data in 16-bit halves, thus we should use 16-bit data width regardless of connected chip format for correct operation.