AnsweredAssumed Answered

What/Wher is my mistake what is STM32F4 I2S DMA Dobule Buffer mode transfer

Question asked by park.hyeon_cheol on Jul 3, 2015
Latest reply on Jul 6, 2015 by park.hyeon_cheol
Hi, there

I am just new one of STM32 world, and thank you for you have interesting my problem.

My problem is I just want large data(Over 10KB) from Memroy to I2S using DMA Double Buffer Mode. but STM32 can not hanle large data at at one DMA command after I divided data by 4.

And I change interrupt handler for each DMA tansfger complete, when is data(1/4) transfer complete I chage start address of DMA transfer.
 
buf problem is If I use JTAG and set break point in DMA handler it's (looks like) work. but standalone mode is not work.

please let me know where is my fault or mistakte.

Thank you

Hyeon-Cheol Park

//----------------------------------------------------------------
uint32_t uDMA_Buffer_Length, uDMA_Buffer, uAF_Address;

//-------------------------------------------------------------------------------------------------
void Init_I2S(uint32_t AF_base, uint32_t AF_length){

 GPIO_InitTypeDef  GPIO_InitStructure;
 I2S_InitTypeDef I2S_InitStructure;
 NVIC_InitTypeDef  NVIC_InitStructure;

 /*
 PLL
 */
 RCC_I2SCLKConfig(RCC_I2S2CLKSource_PLLI2S);     
 RCC_PLLI2SCmd(ENABLE);                          
 while(!RCC_GetFlagStatus(RCC_FLAG_PLLI2SRDY));
 prints("PLLI2S locked...\r\n");

 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC, ENABLE);
 RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);

 /*
 I2S GPIO Initialize
 */
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15 |GPIO_Pin_13 | GPIO_Pin_12;
 GPIO_Init(GPIOB, &GPIO_InitStructure);
 GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_SPI2);
 GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI2);
 GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2);

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
 GPIO_Init(GPIOC, &GPIO_InitStructure);
 GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_SPI2);

 /*
 DMA1 Stream-4 Channel-0
 */
 uDMA_Buffer_Length = AF_length / 4;        //STM32F407 DMA can not handle data size over 1KB(My guess)
 uDMA_Buffer = AF_base;
 uAF_Address = uDMA_Buffer;

 DMA_DeInit(DMA1_Stream4);     //DMA1/Ch0/Stream3 for SPI2_RX
 DMA_I2S_InitStructure.DMA_Channel = DMA_Channel_0;
 DMA_I2S_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI2->DR;
 DMA_I2S_InitStructure.DMA_Memory0BaseAddr = uDMA_Buffer;                 //DMA Buffer1;
 DMA_I2S_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
 DMA_I2S_InitStructure.DMA_BufferSize = uDMA_Buffer_Length;
 DMA_I2S_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
 DMA_I2S_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
 DMA_I2S_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
 DMA_I2S_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
 DMA_I2S_InitStructure.DMA_Mode = DMA_Mode_Circular;
 DMA_I2S_InitStructure.DMA_Priority = DMA_Priority_High;
 DMA_I2S_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
 DMA_I2S_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
 DMA_I2S_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
 DMA_I2S_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
 DMA_Init(DMA1_Stream4, &DMA_I2S_InitStructure);
 DMA_ITConfig(DMA1_Stream4, DMA_IT_TC, ENABLE);
 DMA_DoubleBufferModeConfig(DMA1_Stream4, (uint32_t) (uDMA_Buffer + uDMA_Buffer_Length), DMA_Memory_0);
 DMA_DoubleBufferModeCmd(DMA1_Stream4, ENABLE);

 /*
 I2S DMA Interrupt Initialize
 */
 NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream4_IRQn;
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
 NVIC_Init(&NVIC_InitStructure);

 /*
 I2S Initialize
 */
 SPI_I2S_DeInit(SPI2);
 I2S_InitStructure.I2S_Mode= I2S_Mode_MasterTx;
 I2S_InitStructure.I2S_Standard = I2S_Standard_MSB;
 //I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;
 I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16bextended;
 I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Enable;
 I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_96k;
 I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;
 I2S_Init(SPI2, &I2S_InitStructure);

 SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE); 
 DMA_Cmd(DMA1_Stream4, ENABLE);
 I2S_Cmd(SPI2, ENABLE);
}

void Reload_I2S(uint32_t AF_base, uint32_t AF_length)
{
 
     //I2S_Cmd(SPI2, DISABLE); 
     //SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, DISABLE);
     //DMA_Cmd(DMA1_Stream4, DISABLE);

     uDMA_Buffer_Length = AF_length
     uDMA_Buffer = AF_base;
     uAF_Address = uDMA_Buffer;

     //DMA_DeInit(DMA1_Stream4);     //DMA1/Ch0/Stream3 for SPI2_RX
     DMA_I2S_InitStructure.DMA_Channel = DMA_Channel_0;
     DMA_I2S_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI2->DR;
     DMA_I2S_InitStructure.DMA_Memory0BaseAddr = uDMA_Buffer;
     DMA_I2S_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
     //DMA_I2S_InitStructure.DMA_BufferSize = AF_length;
     DMA_I2S_InitStructure.DMA_BufferSize = uDMA_Buffer_Length;
     DMA_I2S_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
     DMA_I2S_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
     DMA_I2S_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
     DMA_I2S_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
     DMA_I2S_InitStructure.DMA_Mode = DMA_Mode_Circular;
     DMA_I2S_InitStructure.DMA_Priority = DMA_Priority_High;
     DMA_I2S_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
     DMA_I2S_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
     DMA_I2S_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
     DMA_I2S_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
     DMA_Init(DMA1_Stream4, &DMA_I2S_InitStructure);
     DMA_ITConfig(DMA1_Stream4, DMA_IT_TC, ENABLE); 

     //DMA_DoubleBufferModeConfig(DMA1_Stream4, (uint32_t) AF_base, DMA_Memory_0);
     DMA_DoubleBufferModeConfig(DMA1_Stream4, (uint32_t) (uDMA_Buffer + uDMA_Buffer_Length), DMA_Memory_0);
     DMA_DoubleBufferModeCmd(DMA1_Stream4, ENABLE);

     SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);  
     DMA_Cmd(DMA1_Stream4, ENABLE);
     I2S_Cmd(SPI2, ENABLE);

}

extern  uint16_t        uCAB, uFSEL;

void DMA1_Stream4_IRQHandler(void)
{
 static uint8_t        uSwap=1;  //STM32F407 DMA can not handle size over 2KB

 uint32_t        uTemp;          //just for compiler volatile warning

        if(DMA_GetITStatus(DMA1_Stream4, DMA_IT_TCIF4))      //Transfer complete event
 {
                //DMA_ClearFlag(DMA1_Stream4, DMA_IT_TCIF4 | DMA_IT_TEIF4);  //Clear pending interrupt
                DMA_ClearITPendingBit(DMA1_Stream4, DMA_IT_TCIF4 | DMA_IT_TEIF4);  //Clear pending interrupt
                if (uCAB == 6)  //temporally generate FCODE only, case of CAB is not on the track
                {
                       
                       switch (uSwap)
                       {
                                case 0:
                                {
                                        DMA_Cmd(DMA1_Stream4, DISABLE);
                                        DMA_I2S_InitStructure.DMA_Memory0BaseAddr = uDMA_Buffer;                 //DMA Buffer1
                                        DMA_I2S_InitStructure.DMA_BufferSize = uDMA_Buffer_Length;
                                        //DMA_Init(DMA1_Stream4, &DMA_I2S_InitStructure);
                                        DMA_ITConfig(DMA1_Stream4, DMA_IT_TC, ENABLE); 
                                        DMA_DoubleBufferModeConfig(DMA1_Stream4, (uDMA_Buffer + uDMA_Buffer_Length), DMA_Memory_0);
                                        DMA_Cmd(DMA1_Stream4, ENABLE);
                                        uSwap++;
                                        break;
                                }
                                case 1:
                                {
                                        DMA_Cmd(DMA1_Stream4, DISABLE);
                                        DMA_I2S_InitStructure.DMA_Memory0BaseAddr = (uint32_t) (uDMA_Buffer+(uDMA_Buffer_Length * 2));                 //DMA Buffer1
                                        DMA_I2S_InitStructure.DMA_BufferSize = uDMA_Buffer_Length;
                                        //DMA_Init(DMA1_Stream4, &DMA_I2S_InitStructure);
                                        DMA_ITConfig(DMA1_Stream4, DMA_IT_TC, ENABLE); 
                                        DMA_DoubleBufferModeConfig(DMA1_Stream4, (uint32_t) (uDMA_Buffer + (uDMA_Buffer_Length * 3)), DMA_Memory_0);
                                        DMA_Cmd(DMA1_Stream4, ENABLE);
                                        uSwap = 0;
                                        break;
                                }
                                default:
                                {
                                        uSwap = 0;
                                        break;
                                }
                         
                        }
                }
                else    //CAB is on the track
                {
                        switch (uSwap)
                        {
                                case 0:
                                {
                                        DMA_Cmd(DMA1_Stream4, DISABLE);
                                        DMA_I2S_InitStructure.DMA_Memory0BaseAddr = uDMA_Buffer;                 //DMA Buffer1
                                        DMA_I2S_InitStructure.DMA_BufferSize = uDMA_Buffer_Length;
                                        //DMA_Init(DMA1_Stream4, &DMA_I2S_InitStructure);
                                        //DMA_ITConfig(DMA1_Stream4, DMA_IT_TC, ENABLE); 
                                        DMA_DoubleBufferModeConfig(DMA1_Stream4, (uDMA_Buffer + uDMA_Buffer_Length), DMA_Memory_0);
                                        DMA_Cmd(DMA1_Stream4, ENABLE);
                                        uSwap++;
                                        break;
                                }
                                case 1:
                                {
                                        DMA_Cmd(DMA1_Stream4, DISABLE);
                                        DMA_I2S_InitStructure.DMA_Memory0BaseAddr = (uint32_t) (uDMA_Buffer+(uDMA_Buffer_Length * 2));                 //DMA Buffer1
                                        DMA_I2S_InitStructure.DMA_BufferSize = uDMA_Buffer_Length;
                                        //DMA_Init(DMA1_Stream4, &DMA_I2S_InitStructure);
                                        //DMA_ITConfig(DMA1_Stream4, DMA_IT_TC, ENABLE); 
                                        DMA_DoubleBufferModeConfig(DMA1_Stream4, (uint32_t) (uDMA_Buffer + (uDMA_Buffer_Length * 3)), DMA_Memory_0);
                                        DMA_Cmd(DMA1_Stream4, ENABLE);
                                        uSwap++;
                                        break;
                                }
                                case 2:
                                {
                                        DMA_Cmd(DMA1_Stream4, DISABLE);
                                        DMA_I2S_InitStructure.DMA_Memory0BaseAddr = (uint32_t) AF_Table_Zero;                 //DMA Buffer1
                                        DMA_I2S_InitStructure.DMA_BufferSize = uDMA_Buffer_Length;
                                        //DMA_Init(DMA1_Stream4, &DMA_I2S_InitStructure);
                                        //DMA_ITConfig(DMA1_Stream4, DMA_IT_TC, ENABLE); 
                                        DMA_DoubleBufferModeConfig(DMA1_Stream4, (uint32_t) (AF_Table_Zero + uDMA_Buffer_Length), DMA_Memory_0);
                                        DMA_Cmd(DMA1_Stream4, ENABLE);
                                        uSwap++;
                                        break;
                                }
                                case 3:
                                {
                                        DMA_Cmd(DMA1_Stream4, DISABLE);
                                        DMA_I2S_InitStructure.DMA_Memory0BaseAddr = (uint32_t) (AF_Table_Zero + (uDMA_Buffer_Length * 2));                 //DMA Buffer1
                                        DMA_I2S_InitStructure.DMA_BufferSize = uDMA_Buffer_Length;
                                        //DMA_Init(DMA1_Stream4, &DMA_I2S_InitStructure);
                                        //DMA_ITConfig(DMA1_Stream4, DMA_IT_TC, ENABLE); 
                                        DMA_DoubleBufferModeConfig(DMA1_Stream4, (uint32_t) (AF_Table_Zero + (uDMA_Buffer_Length * 3)), DMA_Memory_0);
                                        DMA_Cmd(DMA1_Stream4, ENABLE);
                                        uSwap=0;
                                        break;
                                }
                                default:
                                {
                                        uSwap = 0;
                                        break;
                                }
                         
                        }
                }
        }
}

Outcomes