AnsweredAssumed Answered

SPI RX Buffer via DMA Too Big

Question asked by Joshua on Feb 13, 2014
Latest reply on Feb 14, 2014 by Clive One
I've set up my DMA to transfer 106 half-words via the SPI to a memory buffer. I am quite confident that my buffer size is correct. However, when the transfer actually occurs, it is twice the size I expect (and is consequently stepping on some global variables). Because the transfer is all 0xFFs, I can't tell if I'm getting 212 half-words, 106 full-words, or two 106 half-word "packets" back-to-back and somehow the destination pointer is getting scrambled. If I look at the NDTR register for that stream in my IDE just before it transfers, it says I have 106 data items, leading me to believe the case is 106 full-words, but then again it also says the memory and peripheral data sizes are set to half-words so I don't know which to believe.

Any thoughts are appreciated. Sample DMA/SPI setup:

void SPI_Configuration()
{
   StopSPI();                                                                   //Stop DMA, SPI

   /***************************
   //     SPI1               //
   ***************************/
   SPI1_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
   SPI1_InitStructure.SPI_Mode = SPI_Mode_Master;
   SPI1_InitStructure.SPI_DataSize = SPI_DataSize_16b;
   SPI1_InitStructure.SPI_CPOL = SPI_CPOL_Low;
   SPI1_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
   SPI1_InitStructure.SPI_NSS = SPI_NSS_Soft;
   SPI1_InitStructure.SPI_BaudRatePrescaler = SPI1SCALER;
   SPI1_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
   SPI1_InitStructure.SPI_CRCPolynomial = 7;
   SPI_Init(SPI1, &SPI1_InitStructure);
  
   // Rx Channel
   DMA_DeInit(DMA2_Stream2);
   DMA_StructInit(&SPI1RX_DMA_InitStructure);
   SPI1RX_DMA_InitStructure.DMA_Channel = DMA_Channel_3;
   SPI1RX_DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&(SPI1->DR);
   SPI1RX_DMA_InitStructure.DMA_Memory0BaseAddr = (u32)&g_spi1_adc_data;
   SPI1RX_DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
   SPI1RX_DMA_InitStructure.DMA_BufferSize = g_chain1_buffer_size;
   SPI1RX_DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
   SPI1RX_DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
   SPI1RX_DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
   SPI1RX_DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
   SPI1RX_DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
   SPI1RX_DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
   DMA_Init(DMA2_Stream2, &SPI1RX_DMA_InitStructure);
   // Enable DMA Stream Transfer Complete interrupt
   DMA_ITConfig(DMA2_Stream2, DMA_IT_TC, ENABLE);
  
   // Tx Channel
   DMA_DeInit(DMA2_Stream3);
   DMA_StructInit(&SPI1TX_DMA_InitStructure);
   SPI1TX_DMA_InitStructure.DMA_Channel = DMA_Channel_3;
   SPI1TX_DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&(SPI1->DR);
   SPI1TX_DMA_InitStructure.DMA_Memory0BaseAddr = g_spi1_config_buf_base_ptr;
   SPI1TX_DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
   SPI1TX_DMA_InitStructure.DMA_BufferSize = g_chain1_buffer_size;
   SPI1TX_DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
   SPI1TX_DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
   SPI1TX_DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
   SPI1TX_DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
   SPI1TX_DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
   SPI1TX_DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;  
   DMA_Init(DMA2_Stream3, &SPI1TX_DMA_InitStructure);

   // Enable SPI1
   SPI_Cmd(SPI1, ENABLE);
 
   // Enable DMA request
   SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx, ENABLE);
}

Outcomes