cancel
Showing results for 
Search instead for 
Did you mean: 

CRC-value replaces the first byte in SPI slave DMA receive buffer

arnold_w
Senior
Posted on March 23, 2016 at 12:26

I'm working with the Discovery Development Board and I am trying to use the DMA-controller with my SPI-bus with CRC enabled. I have assigned SPI1 as my master and SPI2 as my slave and connected wires in between and I have verified using a logic analyzer that my master is working properly. My slave, on the other hand, is not working properly. The first received byte in each transmission is replaced with the CRC-value, for example:

MOSI (observed on logic analyzer): 0xFF; 0xFE, 0xFD, 0xFC, 0x96 Received in my software buffer:0x96,0xFE,0xFD,0xFC' MOSI (observed on logic analyzer):0xFA, 0xF9, 0xF8, 0xF7, 0xBE Received in my software buffer:0xBE,0xF9,0xF8,0xF7 Does anybody know what is wrong?

static SPI_HandleTypeDef hspi2;
static DMA_HandleTypeDef hdma_spi2_tx;
static DMA_HandleTypeDef hdma_spi2_rx;
#define DMA_RECEIVE_BUFFER_SIZE 4
static uint8_t receiveDMAbuffer[DMA_RECEIVE_BUFFER_SIZE + 1];
static uint8_t transmitDMAbuffer[DMA_RECEIVE_BUFFER_SIZE + 1];
void initSpi2(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/***************************************************
***************** SPI MISO ***********************
***************************************************/
GPIO_InitStructure.Pin = GPIO_PIN_2;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
/***************************************************
***************** SPI MOSI ***********************
***************************************************/
GPIO_InitStructure.Pin = GPIO_PIN_3;
GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
/***************************************************
***************** SPI CLK ************************
***************************************************/
GPIO_InitStructure.Pin = GPIO_PIN_10;
GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
/***************************************************
***************** SPI NSS ************************
***************************************************/
GPIO_InitStructure.Pin = GPIO_PIN_9;
GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
hdma_spi2_rx.Instance = DMA1_Stream3;
hdma_spi2_rx.Init.Channel = DMA_CHANNEL_0;
hdma_spi2_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi2_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi2_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi2_rx.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_spi2_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi2_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi2_rx.Init.Mode = DMA_CIRCULAR;
hdma_spi2_rx.Init.Priority = DMA_PRIORITY_LOW;
hdma_spi2_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_SLAVE;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;
hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi2.Init.NSS = SPI_NSS_HARD_INPUT;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLED;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_ENABLED;
hspi2.Init.CRCPolynomial = 7;
hdma_spi2_tx.Instance = DMA1_Stream4;
hdma_spi2_tx.Init.Channel = DMA_CHANNEL_0;
hdma_spi2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi2_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi2_tx.Init.MemBurst = DMA_MBURST_SINGLE;
hdma_spi2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi2_tx.Init.Mode = DMA_NORMAL;
hdma_spi2_tx.Init.Priority = DMA_PRIORITY_LOW;
hdma_spi2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
}
static void shutDownSpi2(void)
{
HAL_NVIC_DisableIRQ(DMA1_Stream3_IRQn);
HAL_NVIC_DisableIRQ(DMA1_Stream4_IRQn);
HAL_DMA_DeInit(&hdma_spi2_rx);
HAL_DMA_DeInit(&hdma_spi2_tx);
__HAL_SPI_DISABLE(&hspi2);
__DMA1_CLK_DISABLE();
__SPI2_CLK_DISABLE();
}
static HAL_StatusTypeDef setupSpi1moduleForTransfer(void)
{
HAL_StatusTypeDef status;
shutDownSpi2();
__DMA1_CLK_ENABLE();
__SPI2_CLK_ENABLE();
status = HAL_DMA_Init(&hdma_spi2_rx);
if (status != HAL_OK)
{
shutDownSpi2();
return status;
}
status = HAL_DMA_Init(&hdma_spi2_tx);
if (status != HAL_OK)
{
shutDownSpi2();
return status;
}
__HAL_LINKDMA(&hspi2, hdmarx, hdma_spi2_rx);
__HAL_LINKDMA(&hspi2, hdmatx, hdma_spi2_tx);
status = HAL_SPI_Init(&hspi2);
if (status != HAL_OK)
{
shutDownSpi2();
return status;
}
HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn);
status = HAL_SPI_TransmitReceive_DMA(&hspi2, transmitDMAbuffer, receiveDMAbuffer, DMA_RECEIVE_BUFFER_SIZE);
if (status != HAL_OK)
{
shutDownSpi2();
return status;
}
return HAL_OK;
}
HAL_StatusTypeDef prepareTransferSpi2(uint8_t* bytesToTransmit)
{
uint16_t i;
for (i = 0; i < DMA_RECEIVE_BUFFER_SIZE; i++)
{
transmitDMAbuffer[i] = bytesToTransmit[i];
}
return setupSpi1moduleForTransfer();
}
void DMA1_Stream3_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_spi2_rx);
}
void DMA1_Stream4_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_spi2_tx);
}
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
UART4_TransmitNullTerminatedString((uint8_t*)''\r\nHAL_SPI_TxRxCpltCallback'');
UART4_WaitForTransmitToFinish();
uint16_t i;
UART4_TransmitNullTerminatedString((uint8_t*) ''\r\nSlave received the following in the receive DMA buffer: '');
for (i = 0; i < DMA_RECEIVE_BUFFER_SIZE; i++)
{
UART4_TransmitNullTerminatedString((uint8_t*) ''\r\n0x'');
UART4_TransmitHexNumberAsASCII((uint32_t)receiveDMAbuffer[i]);
}
}

2 REPLIES 2
TDK
Guru
Posted on March 23, 2016 at 20:00

You're receiving 5 bytes into a 4 byte buffer in circular DMA mode.  The 5th byte is overwriting the first.

If you feel a post has answered your question, please click "Accept as Solution".
arnold_w
Senior
Posted on March 31, 2016 at 12:26

Yes, it makes sense that the buffer wraps around and puts the 5th byte (the CRC) at the first location. However, if I change the buffer size to 5 then the CRC is not taken into account (the slave never sends a CRC and it never issues a CRC interrupt when a bad CRC is received). I use DMA_NORMAL instead of DMA_CIRCULAR then every other transmission is incorrectly both received and transmitted and I get Overrun error in the SPI module. But I guess I should start a new thread with a different title.