cancel
Showing results for 
Search instead for 
Did you mean: 

Strange problem with SAI full-duplex slave in I2S mode

tomasz radomski
Associate II
Posted on November 21, 2017 at 12:55

The original post was too long to process during our migration. Please click on the attachment to read the original post.
8 REPLIES 8
tomasz radomski
Associate II
Posted on November 21, 2017 at 13:09

HI, 

i forgot to add HAL_SAI_MspInit instead  of HAL_I2S_MspInit

Here it is:

void HAL_SAI_MspInit(SAI_HandleTypeDef* hsai)// dane do i z KODEKA AUDIO

{

GPIO_InitTypeDef GPIO_InitStruct;

/* SAI1 */

if(hsai->Instance==SAI1_Block_A)//Receive data

{

/* Peripheral clock enable */

if (SAI1_client == 0)

{

__HAL_RCC_SAI1_CLK_ENABLE();

}

SAI1_client ++;

/**SAI1_A_Block_A GPIO Configuration

PE4 ------> SAI1_FS_A

PE2 ------> SAI1_MCLK_A

PE5 ------> SAI1_SCK_A

PE6 ------> SAI1_SD_A

*/

GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_2|GPIO_PIN_5|GPIO_PIN_6;

GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

GPIO_InitStruct.Pull = GPIO_NOPULL;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;

GPIO_InitStruct.Alternate = GPIO_AF6_SAI1;

HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

/* Peripheral DMA init*/

__HAL_RCC_DMA2_CLK_ENABLE();

hdma_sai1_a.Instance = DMA2_Stream1;

hdma_sai1_a.Init.Channel = DMA_CHANNEL_0;

hdma_sai1_a.Init.Direction = DMA_PERIPH_TO_MEMORY;

hdma_sai1_a.Init.PeriphInc = DMA_PINC_DISABLE;

hdma_sai1_a.Init.MemInc = DMA_MINC_ENABLE;

hdma_sai1_a.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;

hdma_sai1_a.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;

hdma_sai1_a.Init.Mode = DMA_CIRCULAR;

hdma_sai1_a.Init.Priority = DMA_PRIORITY_VERY_HIGH;

hdma_sai1_a.Init.FIFOMode = DMA_FIFOMODE_DISABLE;//DMA_FIFOMODE_DISABLE;

hdma_sai1_a.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;

hdma_sai1_a.Init.MemBurst = DMA_MBURST_SINGLE;

hdma_sai1_a.Init.PeriphBurst = DMA_PBURST_SINGLE;

if (HAL_DMA_Init(&hdma_sai1_a) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

/* Several peripheral DMA handle pointers point to the same DMA handle.

Be aware that there is only one channel to perform all the requested DMAs. */

__HAL_LINKDMA(hsai,hdmarx,hdma_sai1_a);

//__HAL_LINKDMA(hsai,hdmatx,hdma_sai1_a);

/* DMA interrupt init */

/* DMA2_Stream1_IRQn interrupt configuration */

HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 0, 0);

HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);

}

if(hsai->Instance==SAI1_Block_B)

{

/* Peripheral clock enable */

if (SAI1_client == 0)

{

__HAL_RCC_SAI1_CLK_ENABLE();

}

SAI1_client ++;

/**SAI1_B_Block_B GPIO Configuration

PE3 ------> SAI1_SD_B

*/

GPIO_InitStruct.Pin = GPIO_PIN_3;

GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

GPIO_InitStruct.Pull = GPIO_NOPULL;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;

GPIO_InitStruct.Alternate = GPIO_AF6_SAI1;

HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

/* Peripheral DMA init*/

hdma_sai1_b.Instance = DMA2_Stream4;

hdma_sai1_b.Init.Channel = DMA_CHANNEL_1;

hdma_sai1_b.Init.Direction = DMA_MEMORY_TO_PERIPH;

hdma_sai1_b.Init.PeriphInc = DMA_PINC_DISABLE;

hdma_sai1_b.Init.MemInc = DMA_MINC_ENABLE;

hdma_sai1_b.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;

hdma_sai1_b.Init.MemDataAlignment = DMA_PDATAALIGN_HALFWORD;

hdma_sai1_b.Init.Mode = DMA_CIRCULAR;

hdma_sai1_b.Init.Priority = DMA_PRIORITY_VERY_HIGH;

hdma_sai1_b.Init.FIFOMode = DMA_FIFOMODE_DISABLE;//DMA_FIFOMODE_DISABLE;

hdma_sai1_b.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;

hdma_sai1_b.Init.MemBurst = DMA_MBURST_SINGLE;

hdma_sai1_b.Init.PeriphBurst = DMA_PBURST_SINGLE;

/* Deinitialize the Stream for new transfer */

HAL_DMA_DeInit(&hdma_sai1_b);

if (HAL_DMA_Init(&hdma_sai1_b) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

/* Several peripheral DMA handle pointers point to the same DMA handle.

Be aware that there is only one stream to perform all the requested DMAs. */

// __HAL_LINKDMA(hsai,hdmarx,hdma_sai1_b);

__HAL_LINKDMA(hsai,hdmatx,hdma_sai1_b);

/* DMA2_Stream4_IRQn interrupt configuration */

HAL_NVIC_SetPriority(DMA2_Stream4_IRQn, 0, 0);

HAL_NVIC_EnableIRQ(DMA2_Stream4_IRQn);

}

}

BR

Tom

tomasz radomski
Associate II
Posted on November 21, 2017 at 14:01

Yes i use the same buffer but for dsp mode it is not a problem. Voice is clear.

I also  tried tu use different buffers and do not use dma and there is still the same problem.

Tom

Posted on November 21, 2017 at 13:21

Hello,

I will test your code using a nucleo board. Did you try our HAL example from our librairy ?

What is the sysclk frequency vs I2S peripheral ?

Regards,

Simon

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

176034CGIL3
Posted on November 21, 2017 at 13:38

Ok thank you,

How do you manage the DMA memory it seems you are using the same buffer audio_GSM_buffer1...

I will try to come back to you asap.

Regards,

Simon

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Simon V.
ST Employee
Posted on November 23, 2017 at 09:17

Hi,

From my understanding, using your configuration you can loop back SAI using DSP mode (bit pulse mode for frame signal) but you are facing data integrity issue using the standard I2S format where frame signal polarity is aligned with I2S channels.

Your app is : Mic --> AudioCODEC --> STM32 I2S RX 

 --> STM32 I2S TX --> AudioCodec --> headset. 

Did you try to split the path and testing separetly RX path and TX path for example using a stored sinus wave for TX ?

Regards,

Simon

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Posted on November 23, 2017 at 09:45

Hi, 

The audio path is:

mic->codec->mcu(SAI) ->codec->speaker

It does not work in SAI A and B (ful-duplex in i2s mode). In DSP mode it is ok. Codec initialization is correct. I do not have time to search for the solution so i changed interface to I2s between  codec and a MCU and it works ok now.

Also i use another i2s to send/receive data to GSM modem LE910.

I2s in my app is in slave mode so i had to take into account errata which says:

'In slave mode, the WS signal level is used only to start the communication. If the I2S (in slave mode) is enabled while the master is already sending the clock and the WS signal level is low (for I2S protocol) or is high (for the LSB or MSB-justified mode), the slave starts communicating data immediately. In this case, the master and slave will be desynchronized throughout the whole communication.'

And that is true, in my app signals where unsinchronized (90% of cases). When i enable i2s when WS signal is high it is perfect.

Thank You for your help. I leave SAI in I2s mode problem. 

BR

Tom

Posted on November 23, 2017 at 15:54

Ok,

Great you succeeded to solve your application issue.

It is a good habit to read the errata document. 

 Feel free if you have any other question.

Kind regards,

Simon

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.