AnsweredAssumed Answered

I2S Full Duplex DMA on STM32F4xx

Question asked by tardy.vincent on Jan 10, 2014
Latest reply on Jul 3, 2014 by maggie.roxas

Hello,

I am facing to an issue about I2S interface of the STM32F405 microcontroller when I use DMA process with I2D3 in Full Duplex.

My hardware setup is :
The microcontroller is connected through I2S3 peripheral to the PCM interface of a Bluetooth Controller.
I2S3_SD (Tx mode) is connected to the PCM_IN of the Bluetooth Controller
I2S3ext_SD (Rx mode) is connected to the PCM_OUT of the Bluetooth Controller
The audio format is :
- PCM format
- audio sample 16 bits
- short Frame sync
- I2S3 in Tx Master
- I2S3 Interrupt on DMA_IT_TC

My problem is, when the ISR of the DMA corresponding to the Stream of I2S3ext_EXT_RX occurs, the buffer notified in the ‘DMA_Memory0BaseAddr’ field is always filled with zeros.

My code is the following :

Defines:

#define DMA_I2S_TX_STREAM           DMA1_Stream7
#define DMA_I2S_TX_CHNL             DMA_Channel_0
#define DMA_I2S_TX_IRQ_STREAM       DMA1_Stream7_IRQn
#define DMA_I2S_TX_IT_TC            DMA_IT_TCIF7
#define DMA_I2S_TX_DR_ADDR         ((SPI_TypeDef *)SPI3) + 0x0C

#define DMA_I2S_RX_STREAM           DMA1_Stream0
#define DMA_I2S_RX_CHNL             DMA_Channel_3
#define DMA_I2S_RX_IRQ_STREAM       DMA1_Stream0_IRQn
#define DMA_I2S_RX_IT_TC            DMA_IT_TCIF0
#define DMA_I2S_RX_DR_ADDR         ((SPI_TypeDef *)I2S3ext) + 0x0C 


Initialization:

GPIO_Configuration();
I2S_Configuration();
DMA_Configuration();


GPIO Configuration:

GPIO_InitTypeDef GPIO_InitStructure;
 
 /* Enable clock */
 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1 | RCC_AHB1Periph_GPIOA | \
                        RCC_AHB1Periph_GPIOB , ENABLE);

 RCC_I2SCLKConfig(RCC_I2S2CLKSource_PLLI2S);
 RCC_APB1PeriphClockCmd (RCC_APB1Periph_SPI3, ENABLE);
 
 /* I2S GPIO Configuration --------------------------------------------------*/
  /* Connect I2S pins to Alternate functions */ 
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_SPI3);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource15, GPIO_AF_SPI3);
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_SPI3);
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_SPI3);
 
 
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
 GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
 
 /* I2S SYNC pin configuration */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* I2S CK pin configuration */
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_3;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
 
  /* I2S SD pin configuration */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

  /* I2S Extended SD pin configuration */
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_4;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

I2S Configuration:

I2S_InitTypeDef I2S_InitStructure;
 NVIC_InitTypeDef NVIC_InitStructure;
 
 /* Deinitialize I2S  peripheral */
 SPI_I2S_DeInit(SPI3);
 
 /* I2S  peripheral configuration */
  I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx;
 I2S_InitStructure.I2S_Standard = I2S_Standard_PCMShort;
 I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;
 I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Disable;
 I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_8k;
 I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;
 I2S_Init(SPI3, &I2S_InitStructure);
 
 /* Configure the I2Sx_ext (the second instance) in Slave Transmitter Mode */
  I2S_FullDuplexConfig(I2S3ext, &I2S_InitStructure);

 /*Hook up I2S3 to DMA buffers*/
 SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx , ENABLE);
 SPI_I2S_DMACmd(I2S3ext, SPI_I2S_DMAReq_Rx, ENABLE);
 

 I2S_Cmd(SPI3, ENABLE);
 I2S_Cmd(I2S3ext, ENABLE);

 /* Configure I2S interrupt Channel */
 NVIC_InitStructure.NVIC_IRQChannel = DMA_I2S_TX_IRQ_STREAM;
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
 NVIC_Init(&NVIC_InitStructure);
 
 NVIC_InitStructure.NVIC_IRQChannel = DMA_I2S_RX_IRQ_STREAM;
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
 NVIC_Init(&NVIC_InitStructure);

DMA Configuration:

 /* DMA Channel (triggered by Rx event) Config */
DMA_DeInit(DMA_I2S_RX_STREAM);
DMA_I2S_RX_InitStructure.DMA_Channel = DMA_I2S_RX_CHNL;
DMA_I2S_RX_InitStructure.DMA_PeripheralBaseAddr = (u32)DMA_I2S_RX_DR_ADDR; 
DMA_I2S_RX_InitStructure.DMA_Memory0BaseAddr = (u32)&PCM_RxBuffer[0];
DMA_I2S_RX_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_I2S_RX_InitStructure.DMA_BufferSize = 32; 
DMA_I2S_RX_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_I2S_RX_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_I2S_RX_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_I2S_RX_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_I2S_RX_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_I2S_RX_InitStructure.DMA_Priority = DMA_Priority_Low;
DMA_I2S_RX_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;        
DMA_I2S_RX_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_I2S_RX_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_I2S_RX_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

/* DMA Channel (triggered by Tx event) Config */
/*Disable the specified DMA Channel*/
DMA_Cmd(DMA_I2S_TX_STREAM, DISABLE);
DMA_DeInit(DMA_I2S_TX_STREAM);
DMA_I2S_TX_InitStructure.DMA_Channel = DMA_I2S_TX_CHNL;
DMA_I2S_TX_InitStructure.DMA_PeripheralBaseAddr =  (u32)DMA_I2S_TX_DR_ADDR;
DMA_I2S_TX_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&PCM_TxBuffer[0]; 
DMA_I2S_TX_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_I2S_TX_InitStructure.DMA_BufferSize = 32; 
DMA_I2S_TX_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_I2S_TX_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_I2S_TX_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_I2S_TX_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_I2S_TX_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_I2S_TX_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_I2S_TX_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;        
DMA_I2S_TX_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_I2S_TX_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_I2S_TX_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; 
DMA_Init(DMA_I2S_TX_STREAM, &DMA_I2S_TX_InitStructure);

To start the DMA transfer I call :

/*Disable the specified DMA Channel*/
  DMA_Cmd(DMA_I2S_RX_STREAM, DISABLE);

  /* DMA Channel (triggered by Rx event) Config */
  DMA_DeInit(DMA_I2S_RX_STREAM);
  DMA_Init(DMA_I2S_RX_STREAM, &DMA_I2S_RX_InitStructure);
  /*Enable the specified DMA Channel interrupts*/
  DMA_ITConfig( DMA_I2S_RX_STREAM, DMA_IT_TC, ENABLE);
  /*Enable the specified DMA Channel*/
  DMA_Cmd(DMA_I2S_RX_STREAM, ENABLE);
 
 DMA_DeInit(DMA_I2S_TX_STREAM);
 /* DMA Channel (triggered by Tx event) Config */ 
  DMA_Init(DMA_I2S_TX_STREAM, &DMA_I2S_TX_InitStructure);
 /*Enable the specified DMA Channel interrupts*/
  DMA_ITConfig( DMA_I2S_TX_STREAM, DMA_IT_TC, ENABLE);
  /*Enable the specified DMA Channel*/
  DMA_Cmd(DMA_I2S_TX_STREAM, ENABLE);

In the ISR corresponding to the DMA Stream of the I2S3_EXT_RX, I check the PCM_RxBuffer[] buffer

/*void DMA1_Stream0_IRQHandler(void)
{

/* Test on DMA Channel Transfer Complete interrupt */
   if(DMA_GetITStatus(DMA_I2S_RX_STREAM, DMA_I2S_RX_IT_TC))
   {
     /* Clear DMA Channel Transfer Complete and Global interrupt pending bits */
     DMA_ClearITPendingBit(DMA_I2S_RX_STREAM,DMA_I2S_RX_IT_TC);
      /*Here I check the value in 'PCM_RxBuffer' */
   }

}

 

If I debug, I can oberve that the array PCM_RxBuffer is filled with zero value.

Could you please help me to fix this issue. I didn't find where is my mistake.

Thanks you,

Best regards,

Vincent

Outcomes