AnsweredAssumed Answered

SPI DMA Rx transfer error

Question asked by chen.ken.005 on Sep 18, 2014
Latest reply on Sep 18, 2014 by chen.ken.005
I want to change polling SPI to DMA SPI. Now I get stuck and have looked up lots of material. None of them is working for me. 
The original polling SPI code works fine. I implemented the following code for the DMA. Something weird happened here. It seems there is no problem for TX  but the RX DMA gets transfer error. SxNDT register still 0x78. I don't know the reason.

1. Should the amount of RX data be the same as TX? But Rx doesn't receive anything.
2. The TX source is from external memory by FMC. Does it matter?

void SPI1_DMA_Configuration()
{
    DMA_InitTypeDef DMA_InitStructure;




    DMA_Cmd(DMA2_Stream3, DISABLE);
    DMA_Cmd(DMA2_Stream2, DISABLE);


    DMA_ClearITPendingBit(DMA2_Stream3,DMA_IT_TCIF3);
    DMA_ClearITPendingBit(DMA2_Stream2,DMA_IT_TCIF2);


    DMA_DeInit(DMA2_Stream3);
    while (DMA_GetCmdStatus (DMA2_Stream3) != DISABLE);
    DMA_StructInit(&DMA_InitStructure);
    // TX
    DMA_InitStructure.DMA_Channel = DMA_Channel_3;
    DMA_InitStructure.DMA_PeripheralBaseAddr = ((uint32_t)(&SPI1->DR));
    DMA_InitStructure.DMA_BufferSize = 10000;
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) HEADER_ADDR;
    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//DMA_PeripheralDataSize_HalfWord;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//DMA_MemoryDataSize_HalfWord;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
    DMA_Init(DMA2_Stream3, &DMA_InitStructure);


    // RX
    DMA_DeInit(DMA2_Stream2);
    while (DMA_GetCmdStatus (DMA2_Stream2) != DISABLE);
    DMA_StructInit(&DMA_InitStructure);


    DMA_InitStructure.DMA_Channel = DMA_Channel_3;
    DMA_InitStructure.DMA_PeripheralBaseAddr = ((uint32_t)(&SPI1->DR));
    DMA_InitStructure.DMA_BufferSize = 120;
    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) &SPIReceiveBuffer[0];
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//DMA_PeripheralDataSize_HalfWord;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//DMA_MemoryDataSize_HalfWord;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
    DMA_Init(DMA2_Stream2, &DMA_InitStructure);




    SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Tx, ENABLE);
    SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Rx, ENABLE);


    while(!SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE));                // wait for empty TX buffer


    DMA_Cmd(DMA2_Stream2, ENABLE);
    DMA_Cmd(DMA2_Stream3, ENABLE);
    
    while ( DMA_GetCmdStatus(DMA2_Stream3) != ENABLE );
    while ( DMA_GetCmdStatus(DMA2_Stream2) != ENABLE ); 


    SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, DISABLE);
    SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, DISABLE);
}

This is my first time to ask questions. Thank you for your help.

Outcomes