cancel
Showing results for 
Search instead for 
Did you mean: 

SPI DMA Rx transfer error

intcd31
Associate II
Posted on September 18, 2014 at 02:05

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.
11 REPLIES 11
intcd31
Associate II
Posted on September 18, 2014 at 17:16

JW, thank you for this. I got stuck on this for a while. Never thought about this.

How can I make sure the parameters I declared NOT using CCM?