Invalid data when using DMA for SPI with STM32

I am using DMA to manage some SPI transmissions with external flash. The selected first and last data are invalid. I can live with the last invalid byte (but would still like to know why), but not the first.

Here's the DMA initialization

// Deinitialize DMA Streams 
DMA_DeInit(DMA_TX_STREAM);
DMA_DeInit(DMA_RX_STREAM);

// Initialize buffer size
DMA_InitStructure.DMA_BufferSize = *nbData;
// Rest of Init
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable ;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single ;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

DMA_InitStructure.DMA_PeripheralBaseAddr = (Uint32)&(SPIx->DR);
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;

// Configure Tx DMA 
DMA_InitStructure.DMA_Channel = DMA_TX_CHANNEL;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_Memory0BaseAddr = (Uint32) data;
DMA_Init(DMA_TX_STREAM, &DMA_InitStructure);

// Configure Rx DMA 
DMA_InitStructure.DMA_Channel = DMA_RX_CHANNEL;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) data;
DMA_Init(DMA_RX_STREAM, &DMA_InitStructure);

DMA_ITConfig(DMA_RX_STREAM, DMA_IT_TC, ENABLE);

// Enable the DMA Stream IRQ Channel
NVIC_InitStructure.NVIC_IRQChannel = DMA_RX_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

// Enable DMA Streams
DMA_Cmd(DMA_RX_STREAM, ENABLE);
DMA_Cmd(DMA_TX_STREAM, ENABLE);

// Enable DMA SPI request
SPI_I2S_DMACmd(SPIx, SPI_I2S_DMAReq_Rx, ENABLE);
SPI_I2S_DMACmd(SPIx, SPI_I2S_DMAReq_Tx, ENABLE);

      

I tried pushing SPI transfer to something in SPIx-> DR before starting DMA transfer but with no success

while(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData(SPIx, (Uint16)0x00);

      

Why is this happening and how could you fix it?

EDIT: used here are used

#define SPIx                            SPI2
#define DMA_RX_STREAM                   DMA1_Stream3
#define DMA_RX_CHANNEL                  DMA_Channel_0
#define DMA_RX_IRQ                      DMA1_Stream3_IRQn
#define DMA_IT_TCIF_RX                  DMA_IT_TCIF3
#define DMA_TX_STREAM                   DMA1_Stream4
#define DMA_TX_CHANNEL                  DMA_Channel_0
#define DMA_TX_IRQ                      DMA1_Stream4_IRQn
#define DMA_IT_TCIF_TX                  DMA_IT_TCIF4

      

EDIT 2: The first and last bytes are counted as 0 instead of 0xff. Here's the beginning and end of the show.

Start

End

To clarify, I use normal SPI instructions to send the read command, and then I configure the DMA for a specific data length and start transfer (the section where SCLK is continuous). The flash is empty (tested) which means everything is at 0xFF. The data buffer just gets 0 in the first and last bytes ...

+3


source to share


1 answer


I suspect you turned on SS too late to start while SPI is already starting to transmit. And turn it off too early for the end of the frame while still the bit is shifted.



First, enable SPI, then start DMA. Wait until DMA is complete to complete (SPI !BUSY

will not work if DMA is too slow to support SPI continuously).

+2


source







All Articles