AnsweredAssumed Answered

Unable to get SPI slave working with DMA controller with CRC enabled

Question asked by arnold_w on Mar 31, 2016
Latest reply on Apr 4, 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. My transmission size is 5 bytes and 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. I've been playing mostly with the DMA_RECEIVE_BUFFER_SIZE and the hdma_spi2_rx.Init.Mode. 

If I use DMA_RECEIVE_BUFFER_SIZE = 5 and DMA_NORMAL then the CRC is ignored, that is, my slave doesn't send a CRC and it doesn't generate a CRC error interrupt in case the received CRC is truly wrong. In addition, every other transmission generates an Overrun interrupt and I don't get the SPI_DMATransmitReceiveCplt interrupt. 

If I use DMA_RECEIVE_BUFFER_SIZE = 5 and DMA_CIRCULAR then the CRC is ignored, that is, my slave doesn't send a CRC and it doesn't generate a CRC error interrupt in case the received CRC is truly wrong. However, I don't get any Overrun interrupts and each transmission generates a SPI_DMATransmitReceiveCplt interrupt. 

If I use DMA_RECEIVE_BUFFER_SIZE = 4 and DMA_NORMAL then the CRC is working properly, but every other transmission generates an Overrun interrupt and I don't get the SPI_DMATransmitReceiveCplt interrupt.

If I use DMA_RECEIVE_BUFFER_SIZE = 4 and DMA_CIRCULAR then the CRC overwrites the first byte in the receive buffer and it makes sense because the buffer is circular and 5 bytes are received into a 4 byte buffer. Besides this, everything is working perfectly, it detects CRC errors and everything looks perfect on the logic analyzer.

Anybody know what I should change to make it work properly?

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];
 
 
#define __DMA_GET_DME_FLAG_INDEX(__DMA_STREAM__)\
(((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream0))? DMA_FLAG_DMEIF0_4 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream0))? DMA_FLAG_DMEIF0_4 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream4))? DMA_FLAG_DMEIF0_4 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream4))? DMA_FLAG_DMEIF0_4 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream1))? DMA_FLAG_DMEIF1_5 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream1))? DMA_FLAG_DMEIF1_5 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream5))? DMA_FLAG_DMEIF1_5 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream5))? DMA_FLAG_DMEIF1_5 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream2))? DMA_FLAG_DMEIF2_6 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream2))? DMA_FLAG_DMEIF2_6 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream6))? DMA_FLAG_DMEIF2_6 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream6))? DMA_FLAG_DMEIF2_6 :\
   DMA_FLAG_DMEIF3_7)
 
#define __DMA_GET_TC_FLAG_INDEX(__DMA_STREAM__) \
(((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream0))? DMA_FLAG_TCIF0_4 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream0))? DMA_FLAG_TCIF0_4 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream4))? DMA_FLAG_TCIF0_4 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream4))? DMA_FLAG_TCIF0_4 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream1))? DMA_FLAG_TCIF1_5 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream1))? DMA_FLAG_TCIF1_5 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream5))? DMA_FLAG_TCIF1_5 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream5))? DMA_FLAG_TCIF1_5 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream2))? DMA_FLAG_TCIF2_6 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream2))? DMA_FLAG_TCIF2_6 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream6))? DMA_FLAG_TCIF2_6 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream6))? DMA_FLAG_TCIF2_6 :\
   DMA_FLAG_TCIF3_7)
 
#define __DMA_GET_TE_FLAG_INDEX(__DMA_STREAM__)\
(((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream0))? DMA_FLAG_TEIF0_4 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream0))? DMA_FLAG_TEIF0_4 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream4))? DMA_FLAG_TEIF0_4 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream4))? DMA_FLAG_TEIF0_4 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream1))? DMA_FLAG_TEIF1_5 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream1))? DMA_FLAG_TEIF1_5 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream5))? DMA_FLAG_TEIF1_5 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream5))? DMA_FLAG_TEIF1_5 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream2))? DMA_FLAG_TEIF2_6 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream2))? DMA_FLAG_TEIF2_6 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream6))? DMA_FLAG_TEIF2_6 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream6))? DMA_FLAG_TEIF2_6 :\
   DMA_FLAG_TEIF3_7)
 
#define __DMA_GET_FE_FLAG_INDEX(__DMA_STREAM__)\
(((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream0))? DMA_FLAG_FEIF0_4 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream0))? DMA_FLAG_FEIF0_4 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream4))? DMA_FLAG_FEIF0_4 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream4))? DMA_FLAG_FEIF0_4 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream1))? DMA_FLAG_FEIF1_5 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream1))? DMA_FLAG_FEIF1_5 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream5))? DMA_FLAG_FEIF1_5 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream5))? DMA_FLAG_FEIF1_5 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream2))? DMA_FLAG_FEIF2_6 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream2))? DMA_FLAG_FEIF2_6 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream6))? DMA_FLAG_FEIF2_6 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream6))? DMA_FLAG_FEIF2_6 :\
   DMA_FLAG_FEIF3_7)
 
#define __DMA_GET_HT_FLAG_INDEX(__DMA_STREAM__)\
(((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream0))? DMA_FLAG_HTIF0_4 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream0))? DMA_FLAG_HTIF0_4 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream4))? DMA_FLAG_HTIF0_4 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream4))? DMA_FLAG_HTIF0_4 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream1))? DMA_FLAG_HTIF1_5 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream1))? DMA_FLAG_HTIF1_5 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream5))? DMA_FLAG_HTIF1_5 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream5))? DMA_FLAG_HTIF1_5 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream2))? DMA_FLAG_HTIF2_6 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream2))? DMA_FLAG_HTIF2_6 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA1_Stream6))? DMA_FLAG_HTIF2_6 :\
 ((uint32_t)(__DMA_STREAM__) == ((uint32_t)DMA2_Stream6))? DMA_FLAG_HTIF2_6 :\
   DMA_FLAG_HTIF3_7)
 
#define __DMA_CLEAR_FLAG(__DMA_STREAM__, __FLAG__) \
(((uint32_t)(__DMA_STREAM__) > (uint32_t)DMA2_Stream3)? (DMA2->HIFCR = (__FLAG__)) :\
 ((uint32_t)(__DMA_STREAM__) > (uint32_t)DMA1_Stream7)? (DMA2->LIFCR = (__FLAG__)) :\
 ((uint32_t)(__DMA_STREAM__) > (uint32_t)DMA1_Stream3)? (DMA1->HIFCR = (__FLAG__)) : (DMA1->LIFCR = (__FLAG__)))
 
#define __DMA_ENABLE_IT(__DMA_STREAM__, __INTERRUPT__)   (((__INTERRUPT__) != DMA_IT_FE)? \
((__DMA_STREAM__)->CR |= (__INTERRUPT__)) : ((__DMA_STREAM__)->FCR |= (__INTERRUPT__)))
 
#define __DMA_GET_FLAG(__DMA_STREAM__, __FLAG__)\
(((uint32_t)(__DMA_STREAM__) > (uint32_t)DMA2_Stream3)? (DMA2->HISR & (__FLAG__)) :\
 ((uint32_t)(__DMA_STREAM__) > (uint32_t)DMA1_Stream7)? (DMA2->LISR & (__FLAG__)) :\
 ((uint32_t)(__DMA_STREAM__) > (uint32_t)DMA1_Stream3)? (DMA1->HISR & (__FLAG__)) : (DMA1->LISR & (__FLAG__)))
 
#define __DMA_DISABLE_IT(__DMA_STREAM__, __INTERRUPT__)  (((__INTERRUPT__) != DMA_IT_FE)? \
((__DMA_STREAM__)->CR &= ~(__INTERRUPT__)) : ((__DMA_STREAM__)->FCR &= ~(__INTERRUPT__)))
 
#define __DMA_GET_IT_SOURCE(__DMA_STREAM__, __INTERRUPT__)  (((__INTERRUPT__) != DMA_IT_FE)? \
                                                        ((__DMA_STREAM__)->CR & (__INTERRUPT__)) : \
                                                        ((__DMA_STREAM__)->FCR & (__INTERRUPT__)))
 
#define __SPI_GET_FLAG(__SPI_MODULE__, __FLAG__) ((((__SPI_MODULE__)->SR) & (__FLAG__)) == (__FLAG__))
#define __SPI_GET_IT_SOURCE(__SPI_MODULE__, __INTERRUPT__) ((((__SPI_MODULE__)->CR2 & (__INTERRUPT__)) == (__INTERRUPT__)) ? 1 : 0)
#define __SPI_CLEAR_CRCERRFLAG(__SPI_MODULE__) ((__SPI_MODULE__)->SR = ~(SPI_FLAG_CRCERR))
 
#define __SPI_CLEAR_MODFFLAG(__SPI_MODULE__)            \
  do{                                                   \
    __IO uint32_t tmpreg;                               \
    tmpreg = (__SPI_MODULE__)->SR;                      \
    (__SPI_MODULE__)->CR1 &= (~SPI_CR1_SPE);            \
    UNUSED(tmpreg);                                     \
  } while(0)
 
#define __SPI_CLEAR_OVRFLAG(__SPI_MODULE__)       \
  do{                                             \
    __IO uint32_t tmpreg;                         \
    tmpreg = (__SPI_MODULE__)->DR;                \
    tmpreg = (__SPI_MODULE__)->SR;                \
    UNUSED(tmpreg);                               \
  } while(0)
 
 
#define __SPI_CLEAR_FREFLAG(__SPI_MODULE__)     \
  do{                                           \
  __IO uint32_t tmpreg;                         \
  tmpreg = (__SPI_MODULE__)->SR;                \
  UNUSED(tmpreg);                               \
  } while(0)
 
 
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);
    __SPI_CLEAR_CRCERRFLAG(SPI2);
    __SPI_CLEAR_MODFFLAG(SPI2);
    __SPI_CLEAR_OVRFLAG(SPI2);
    __SPI_CLEAR_FREFLAG(SPI2);
    __DMA1_CLK_DISABLE();
    __SPI2_CLK_DISABLE();
}
 
 
static HAL_StatusTypeDef setupSpi2moduleForTransfer(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);
 
    SPI2->CR1 |= SPI_CR1_SPE;                       // Enable SPI peripheral
    HAL_NVIC_EnableIRQ(SPI2_IRQn);                  // Enable SPI bus interrupts
    SPI2->CR2 |= SPI_CR2_ERRIE;
 
    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 setupSpi2moduleForTransfer();
}
 
 
void DMA1_Stream3_IRQHandler(void)
{
    // Transfer Error Interrupt management
    if(__DMA_GET_FLAG(DMA1_Stream3, __DMA_GET_TE_FLAG_INDEX(DMA1_Stream3)) != RESET)
    {
        if(__DMA_GET_IT_SOURCE(DMA1_Stream3, DMA_IT_TE) != RESET)
        {
            __DMA_DISABLE_IT(DMA1_Stream3, DMA_IT_TE);                             // Disable the transfer error interrupt
            __DMA_CLEAR_FLAG(DMA1_Stream3, __DMA_GET_TE_FLAG_INDEX(DMA1_Stream3)); // Clear the transfer error flag
 
            // Transfer error callback
            UART4_TransmitNullTerminatedString((uint8_t*)"\r\nSPI_DMAError 1");
            UART4_WaitForTransmitToFinish();
        }
    }
 
 
    // FIFO Error Interrupt management
    if(__DMA_GET_FLAG(DMA1_Stream3, __DMA_GET_FE_FLAG_INDEX(DMA1_Stream3)) != RESET)
    {
        if(__DMA_GET_IT_SOURCE(DMA1_Stream3, DMA_IT_FE) != RESET)
        {
            __DMA_DISABLE_IT(DMA1_Stream3, DMA_IT_FE);                              // Disable the FIFO Error interrupt
            __DMA_CLEAR_FLAG(DMA1_Stream3, __DMA_GET_FE_FLAG_INDEX(DMA1_Stream3));  // Clear the FIFO error flag
 
            // Transfer error callback
            UART4_TransmitNullTerminatedString((uint8_t*)"\r\nSPI_DMAError 2");
            UART4_WaitForTransmitToFinish();
        }
    }
 
 
    // Direct Mode Error Interrupt management
    if(__DMA_GET_FLAG(DMA1_Stream3, __DMA_GET_DME_FLAG_INDEX(DMA1_Stream3)) != RESET)
    {
        if(__DMA_GET_IT_SOURCE(DMA1_Stream3, DMA_IT_DME) != RESET)
        {
            __DMA_DISABLE_IT(DMA1_Stream3, DMA_IT_DME);                              // Disable the direct mode Error interrupt
            __DMA_CLEAR_FLAG(DMA1_Stream3, __DMA_GET_DME_FLAG_INDEX(DMA1_Stream3));  // Clear the direct mode error flag
 
            // Transfer error callback
            UART4_TransmitNullTerminatedString((uint8_t*)"\r\nSPI_DMAError 3");
            UART4_WaitForTransmitToFinish();
        }
    }
 
 
    // Half Transfer Complete Interrupt management
    if(__DMA_GET_FLAG(DMA1_Stream3, __DMA_GET_HT_FLAG_INDEX(DMA1_Stream3)) != RESET)
    {
      if(__DMA_GET_IT_SOURCE(DMA1_Stream3, DMA_IT_HT) != RESET)
      {
          /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
          if((DMA1_Stream3->CR & DMA_SxCR_CIRC) == 0)
          {
            /* Disable the half transfer interrupt */
            __DMA_DISABLE_IT(DMA1_Stream3, DMA_IT_HT);
          }
          /* Clear the half transfer complete flag */
          __DMA_CLEAR_FLAG(DMA1_Stream3, __DMA_GET_HT_FLAG_INDEX(DMA1_Stream3));
        }
 
          // Half transfer callback
        UART4_TransmitNullTerminatedString((uint8_t*)"\r\nSPI_DMATransmitReceiveHalfCplt");
        UART4_WaitForTransmitToFinish();
    }
 
 
    // Transfer Complete Interrupt management
    if(__DMA_GET_FLAG(DMA1_Stream3, __DMA_GET_TC_FLAG_INDEX(DMA1_Stream3)) != RESET)
    {
        if(__DMA_GET_IT_SOURCE(DMA1_Stream3, DMA_IT_TC) != RESET)
        {
            // Disable the transfer complete interrupt if the DMA mode is not CIRCULAR
            if((DMA1_Stream3->CR & DMA_SxCR_CIRC) == 0)
            {
 
                __DMA_DISABLE_IT(DMA1_Stream3, DMA_IT_TC);   // Disable the transfer complete interrupt
            }
            __DMA_CLEAR_FLAG(DMA1_Stream3, __DMA_GET_TC_FLAG_INDEX(DMA1_Stream3));  // Clear the transfer complete flag
 
            // Transfer complete callback
            UART4_TransmitNullTerminatedString((uint8_t*)"\r\nSPI_DMATransmitReceiveCplt");
            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]);
            }
        }
    }
}
 
 
void DMA1_Stream4_IRQHandler(void)
{
  UART4_TransmitNullTerminatedString((uint8_t*)"\r\nDMA1_Stream4_IRQHandler");
  HAL_DMA_IRQHandler(&hdma_spi2_tx);
}
 
 
void SPI2_IRQHandler(void)
{
    UART4_TransmitNullTerminatedString((uint8_t*)"\r\nSPI2_IRQHandler");
    UART4_WaitForTransmitToFinish();
 
    if (SPI2->SR & 1)
    {   // No need to clear interrupt flag
        UART4_TransmitNullTerminatedString((uint8_t*)"\r\nReceive buffer not empty flag is set");
    }
    if (SPI2->SR & 2)
    {   // No need to clear interrupt flag
        UART4_TransmitNullTerminatedString((uint8_t*)"\r\nTransmit Buffer Empty flag is set");
    }
    if (SPI2->SR & 0x10)
    {
        UART4_TransmitNullTerminatedString((uint8_t*)"\r\nCRCERR flag is set");
        __SPI_CLEAR_CRCERRFLAG(SPI2);   // Clear interrupt flag
    }
    if (SPI2->SR & 0x20)
    {
        UART4_TransmitNullTerminatedString((uint8_t*)"\r\nMode fault flag is set");
        __SPI_CLEAR_MODFFLAG(SPI2);
    }
    if (SPI2->SR & 0x40)
    {
        UART4_TransmitNullTerminatedString((uint8_t*)"\r\nOverrun flag is set");
        __SPI_CLEAR_OVRFLAG(SPI2); // Clear interrupt flag
    }
    if (SPI2->SR & 0x100)
    {
        UART4_TransmitNullTerminatedString((uint8_t*)"\r\nTI frame format error flag is set");
        __SPI_CLEAR_FREFLAG(SPI2); // Clear interrupt flag
    }
}

Outcomes