cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 Is this BUG? I2S LOOP BACK TEST FAILS in 24Bit Mode. Crush DMA pointer etc. (source code attached)

KAJIK.1
Associate III

I wrote I2S Loop back test program. I2S2 as Master Transfer mode and I2S3 as Slave Receive mode. (Proto for ADC in and DAC out.)

It works OK when 16bit in 16bit frame. However, in 24 bit in 32bit frame, DMA pointer etc. are corrupted.

With step-by-step trace, I found crushing point in stmf4xx_hal_i2s.c.

Is this BUG or my program is wrong???

Many thanks in advance,

K.A.

Gist of the program is below and screen shot of IDE is attached.

int main(void) {
....
	HAL_I2S_Receive_DMA(&hi2s3, (uint16_t *) ADC_Data, (uint16_t) (BUF_LEN*2) * 4) ; // (16bit*2)*stereo*double buffer
 
  while (1)
  {
	  while ((&hi2s2)->State != HAL_I2S_STATE_READY)	;
      if (HAL_I2S_Transmit_DMA(&hi2s2, (uint16_t*) Out_buf, (uint16_t) (BUF_LEN*2) * 2) != HAL_OK) {
			Error_Handler();
      }
  }
}
 
/********** call back **********/
 
void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef * hi2s3) {
	ADC1_ptr = BUF_LEN*2 ;
}
 
void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef * hi2s3) {
	ADC1_ptr = 0 ;

1 ACCEPTED SOLUTION

Accepted Solutions

K.A.,

I don't use Cube so it's up to you to determine, what exactly the Size parameter in HAL_I2S_Receive_DMA() means.

Just a snippet to raise suspicion:

HAL_StatusTypeDef HAL_I2S_Receive_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size)

{

 uint32_t *tmp = NULL;

 uint32_t tmp1 = 0U;

 if((pData == NULL) || (Size == 0U))

 {

   return HAL_ERROR;

 }

 if(hi2s->State == HAL_I2S_STATE_READY)

 {

   hi2s->pRxBuffPtr = pData;

   tmp1 = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN);

   if((tmp1 == I2S_DATAFORMAT_24B) || (tmp1 == I2S_DATAFORMAT_32B))

   {

     hi2s->RxXferSize = (Size << 1U);

     hi2s->RxXferCount = (Size << 1U);

   }

   else

   {

     hi2s->RxXferSize = Size;

     hi2s->RxXferCount = Size;

   }

JW

View solution in original post

8 REPLIES 8

Do you define a large enough buffer in memory?

Note, that in Cube/HAL functions with DMA, you specify (probably - read the Cube/HAL manual or follow its code - I don't use Cube) number of *transfers* rather than bytes.

JW

KAJIK.1
Associate III

Dear Jan,

Thank you very much for your reply.

As I attached the source code, I defined required buffer size. (I hope.)

Please check below.

K.A.

#define BUF_LEN  96       //  1msec data for 96kHz sampling
 
/***  I use 24bit data in 32bit frame, and I2S transfers 16bit data by DMA ***/
 
// Input Buffer
uint16_t ADC_Data [(BUF_LEN*2)*2*2] ;  // (16bit*2) * stereo * double buffer ==> 1536byte
 
// Output Buffer
uint16_t Out_buf[(BUF_LEN*2)*2] ; // (16bit*2)*stereo ==>768 byte
 
// I2S Receive
HAL_I2S_Receive_DMA(&hi2s3, (uint16_t *) ADC_Data, (uint16_t) (BUF_LEN*2) * 4) ; // transfer size => 768
 
// IS2 Transmit
HAL_I2S_Transmit_DMA(&hi2s2, (uint16_t*) Out_buf, (uint16_t) (BUF_LEN*2) * 2) ;  // transfer size => 384

K.A.,

I don't use Cube so it's up to you to determine, what exactly the Size parameter in HAL_I2S_Receive_DMA() means.

Just a snippet to raise suspicion:

HAL_StatusTypeDef HAL_I2S_Receive_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size)

{

 uint32_t *tmp = NULL;

 uint32_t tmp1 = 0U;

 if((pData == NULL) || (Size == 0U))

 {

   return HAL_ERROR;

 }

 if(hi2s->State == HAL_I2S_STATE_READY)

 {

   hi2s->pRxBuffPtr = pData;

   tmp1 = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN);

   if((tmp1 == I2S_DATAFORMAT_24B) || (tmp1 == I2S_DATAFORMAT_32B))

   {

     hi2s->RxXferSize = (Size << 1U);

     hi2s->RxXferCount = (Size << 1U);

   }

   else

   {

     hi2s->RxXferSize = Size;

     hi2s->RxXferCount = Size;

   }

JW

TDK
Guru

Seems like your buffers are half as big as they need to be when using 24- or 32-bit frames. Easy enough to test.

If you feel a post has answered your question, please click "Accept as Solution".
KAJIK.1
Associate III

Dear Jan and TDK,

Thank you very much for your kind reply.

Jan's comment remind me that I saw the same code somewhere in HAL source.

TDK's comment forced me to re-read HAL manual.

Code excerpt from stm32f4xx_hal_i2s.c (below) answer both of above. ("@note" is exactly the same comment as in HAL manual.)

* @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S

* configuration phase, the Size parameter means the number of 16-bit data length

* in the transaction and 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.

I read this if transfer data size were 100byte, Size parameter will be 50. Either in 16bit data frame or in 24/32bit data frame.

However, the same code Jan kindly mentioned is shown in line 40 and after;

if ((tmpreg_cfgr == I2S_DATAFORMAT_24B) || (tmpreg_cfgr == I2S_DATAFORMAT_32B))

{

hi2s->RxXferSize = (Size << 1U);

hi2s->RxXferCount = (Size << 1U);

}

That means Size parameter for 24/32bit data frame shall be 25 instead of 50 in the above.

(Then, I think "@note" should be "32-bit data length".)

I checked the program after changing the transfer size.

Thanks to your kind reply, it works with out crush!!!

  1. // I2S Receive
  2. HAL_I2S_Receive_DMA(&hi2s3, (uint16_t *) ADC_Data, (uint16_t) BUF_LEN * 2 * 2) ; // transfer size => 768 384
  3.  
  4. // IS2 Transmit
  5. HAL_I2S_Transmit_DMA(&hi2s2, (uint16_t*) Out_buf, (uint16_t) BUF_LEN * 2 ) ; // transfer size => 384 192

However, all received data was 0xFFFF. (Input data (content of Out_buf) is sin wave.)

{In 16bit loopback, there also some data error in received data. Therefore, this will not the problem of software I suppose.}

Anyway, many thanks to both of you!!!

K.A.

/**
  * @brief  Receive an amount of data in non-blocking mode with DMA
  * @param  hi2s pointer to a I2S_HandleTypeDef structure that contains
  *         the configuration information for I2S module
  * @param  pData a 16-bit pointer to the Receive data buffer.
  * @param  Size number of data sample to be sent:
  * @note   When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
  *         configuration phase, the Size parameter means the number of 16-bit data length
  *         in the transaction and 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.
  * @note   The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
  *         between Master and Slave(example: audio streaming).
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_I2S_Receive_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size)
{
  uint32_t tmpreg_cfgr;
 
  if ((pData == NULL) || (Size == 0U))
  {
    return  HAL_ERROR;
  }
 
  /* Process Locked */
  __HAL_LOCK(hi2s);
 
  if (hi2s->State != HAL_I2S_STATE_READY)
  {
    __HAL_UNLOCK(hi2s);
    return HAL_BUSY;
  }
 
  /* Set state and reset error code */
  hi2s->State = HAL_I2S_STATE_BUSY_RX;
  hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
  hi2s->pRxBuffPtr = pData;
 
  tmpreg_cfgr = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN);
 
  if ((tmpreg_cfgr == I2S_DATAFORMAT_24B) || (tmpreg_cfgr == I2S_DATAFORMAT_32B))
  {
    hi2s->RxXferSize = (Size << 1U);
    hi2s->RxXferCount = (Size << 1U);
  }
  else
  {
    hi2s->RxXferSize = Size;
    hi2s->RxXferCount = Size;
  }

> However, all received data was 0xFFFF.

Observe the data using oscilloscope/LA. Check for bad solder joints.

JW

KAJIK.1
Associate III

Dear Jan,

Thank you very much for your reply. Your comment is very encouraging.😊

Unfortunately, I do not have Oscillo or Logic analyzer. But my test bed is very simple.

0693W000004HBbhQAG.jpg Therefore, I need check the received data.

In 16bit in 16bit data frame case, I thought loopback data (received data) is OK, but it was NOT.

Received data is unexpectedly SHIFTED. (see red part) [PDF attached]

And In 24bit in 32bit data frame, received data was DISASTROUS!!!

If you (and anyone!) have any idea what is wrong, please enlighten me.

Many many thanks in advance.

K.A.

KAJIK.1
Associate III

One Correction.

I checked Device configuration again, and found an error in 24bit mode. (Assignment of SCK for I2S3 was not correct.)

However, received data was same as 16bit mode, that is, received data was SHIFTED. [please see PDF]

Please help!!!

K.A.