AnsweredAssumed Answered

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

Question asked by arnold_w on Mar 23, 2016
Latest reply on Mar 31, 2016 by arnold_w
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]);
    }
}

Outcomes