cancel
Showing results for 
Search instead for 
Did you mean: 

SPI DMA data corruption

asecen89
Associate II
Posted on November 21, 2013 at 17:52

Hi,

I am using SPI2 with DMA1 on STM32F427 to communicate with an external processor. The problem is that when the data on MISO and MOSI pins (PB14 and PB15) are somehow corrupted i.e. the data comes out as shifted versions of the data sent and the amount of the shift always changes and same thing goes for also the receive part; received data is the shifted version of the data in the input pin. What might be the cause of this problem? Could some other functions of the pins be interfering my application?
4 REPLIES 4
Posted on November 21, 2013 at 17:58

There is no intrinsic framing, so figure if your clock is getting noise or being missed. Look at how you are driving it, how it is being terminated, the edges and the speed.

Try it slower. Make sure you have good common grounds.

Use a logic analyzer and understand why and when you are losing bit synchronization/framing.

Consider if you can use CS for bit/byte framing.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
asecen89
Associate II
Posted on November 22, 2013 at 09:01

Hi Clive,

I tried the same code using STM32F4 discovery board and configured SPI2 as master with DMA1. I observed the output data with scope and saw that the bits are still shifting. I think this shows that my problem is not related with hardware or noise. Do you think it could be software related; may be about burst sizes? I am also sending my code below.

 

SPI_InitTypeDef SPI_InitStructure;

GPIO_InitTypeDef GPIO_InitStructure;

DMA_InitTypeDef DMA_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);

GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_SPI2); // SCK

GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_SPI2); // MISO

GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_SPI2); // MOSI

//Configure the pins used for SPI

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;

GPIO_Init(GPIOB, &GPIO_InitStructure);

SPI_I2S_DeInit(SPI2);

SPI_StructInit(&SPI_InitStructure);

// SPI configuration

SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;

SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;

SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;

SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;

SPI_InitStructure.SPI_CRCPolynomial = 7;

SPI_Init(SPI2, &SPI_InitStructure);

SPI_Cmd(SPI2, ENABLE);

/*********************************************************************************************/

// DMA for Tx

DMA_DeInit(DMA1_Stream4);

DMA_StructInit(&DMA_InitStructure);

DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) & (SPI2->DR);

DMA_InitStructure.DMA_Channel = DMA_Channel_0;

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;

DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;

DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t) &Tx_Buffer_to_AP1;

DMA_InitStructure.DMA_BufferSize = 4096;

DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;

DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

DMA_DoubleBufferModeConfig (DMA1_Stream4 ,(uint32_t) &Tx_Buffer_to_AP2, DMA_Memory_0);

DMA_DoubleBufferModeCmd(DMA1_Stream4 , ENABLE);

DMA_InitStructure.DMA_Priority = DMA_Priority_High;

DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;

DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

DMA_Init(DMA1_Stream4 , &DMA_InitStructure);

/************************************************************************************/

// DMA for Rx

DMA_DeInit(DMA1_Stream3);

DMA_StructInit(&DMA_InitStructure);

DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) & (SPI2->DR);

DMA_InitStructure.DMA_Channel = DMA_Channel_0;

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory ;

DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) &Rx_Buffer_from_AP;

DMA_InitStructure.DMA_BufferSize = 4096;

DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;

DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

DMA_InitStructure.DMA_Priority = DMA_Priority_High;

DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;

DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

DMA_Init(DMA1_Stream3 , &DMA_InitStructure);

/***************************************************************************************/

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);

NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream3_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

DMA_ITConfig(DMA1_Stream3, DMA_IT_TC, ENABLE);

DMA_ITConfig(DMA1_Stream4, DMA_IT_TC, ENABLE);

SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);

SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Rx, ENABLE);
frankmeyer9
Associate II
Posted on November 22, 2013 at 10:24

SPI is not a ''standardized'' protocol, so you will need to check if the master and slave settings do match. One of those subtle items is the CLK pulse transition which triggers the read. If that doesn't match, you will have random effects.

I would re-check the datasheets.

Posted on November 22, 2013 at 16:41

I observed the output data with scope and saw that the bits are still shifting.

I'm having a hard time visualizing this, can you post a screen plot of the Clock and Data signals that illustrates this?

The code is missing some critical context, can you perhaps NOT use DoubleBuffer mode, and try using a single double sized buffer with HT/TC?
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..