AnsweredAssumed Answered

How do I reset an SPI module and associated DMA streams, without resetting the whole microcontroller?

Question asked by arnold_w on Apr 4, 2016
Latest reply on Apr 6, 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 everything works fine during normal operation. Now I would like to add error checking and recovery and my first test was to have my master transmit 1 bit too little. I am able to detect this condition in the slave (I only receive DMA stream transmit complete interrupts and no DMA stream receive complete interrupts when this condition occurs) but I am unable to reset my SPI bus and DMA controller. So my question is, how do I reset the SPI module and associated DMA streams completely, without having to reset the whole microcontroller? It is not sufficient to call shutDownSpi2 and setupSpi2moduleForTransfer in the code below.


static uint8_t receiveDMAbuffer[5];
static uint8_t transmitDMAbuffer[5];
static Bool_t Stream3TxRxCpltReceived;




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




#define RESET_SPI_CRC(__SPI_MODULE__) do{(__SPI_MODULE__)->CR1 &= (~SPI_CR1_CRCEN);\
                                         (__SPI_MODULE__)->CR1 |= SPI_CR1_CRCEN;} 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);


    __DMA1_CLK_ENABLE();
    DMA1_Stream3->NDTR = 5;                                // Configure DMA Stream data length
    DMA1_Stream3->PAR  = (uint32_t)&SPI2->DR;              // Configure DMA Stream source address
    DMA1_Stream3->M0AR = (uint32_t)receiveDMAbuffer;       // Configure DMA Stream destination address
    DMA1_Stream4->NDTR = 4;                                // Configure DMA Stream data length
    DMA1_Stream4->PAR = (uint32_t)&SPI2->DR;               // Configure DMA Stream destination address
    DMA1_Stream4->M0AR = (uint32_t)transmitDMAbuffer;      // Configure DMA Stream source address
}




static void shutDownSpi2(void)
{
    SPI2->CR1 &= ~SPI_CR1_SPE;                             // Disable the selected SPI peripheral
    HAL_NVIC_DisableIRQ(DMA1_Stream3_IRQn);
    HAL_NVIC_DisableIRQ(DMA1_Stream4_IRQn);


    DMA1_Stream3->CR &= ~DMA_SxCR_EN;                      // Disable the selected DMA Streamx
    DMA1_Stream3->CR   = 0;                                // Reset DMA Streamx control register
    DMA1_Stream3->M1AR = 0;                                // Reset DMA Streamx memory 1 address register
    DMA1_Stream3->FCR  = (uint32_t)0x00000021;             // Reset DMA Streamx FIFO control register


    DMA1_Stream4->CR &= ~DMA_SxCR_EN;                      // Disable the selected DMA Streamx
    DMA1_Stream4->CR   = 0;                                // Reset DMA Streamx control register
    DMA1_Stream4->M1AR = 0;                                // Reset DMA Streamx memory 1 address register
    DMA1_Stream4->FCR  = (uint32_t)0x00000021;             // Reset DMA Streamx FIFO control register


    __DMA_CLEAR_FLAG(DMA1_Stream3, __DMA_GET_DME_FLAG_INDEX(DMA1_Stream3));
    __DMA_CLEAR_FLAG(DMA1_Stream3, __DMA_GET_TC_FLAG_INDEX(DMA1_Stream3));
    __DMA_CLEAR_FLAG(DMA1_Stream3, __DMA_GET_TE_FLAG_INDEX(DMA1_Stream3));
    __DMA_CLEAR_FLAG(DMA1_Stream3, __DMA_GET_FE_FLAG_INDEX(DMA1_Stream3));
    __DMA_CLEAR_FLAG(DMA1_Stream3, __DMA_GET_HT_FLAG_INDEX(DMA1_Stream3));


    __DMA_CLEAR_FLAG(DMA1_Stream4, __DMA_GET_DME_FLAG_INDEX(DMA1_Stream4));
    __DMA_CLEAR_FLAG(DMA1_Stream4, __DMA_GET_TC_FLAG_INDEX(DMA1_Stream4));
    __DMA_CLEAR_FLAG(DMA1_Stream4, __DMA_GET_TE_FLAG_INDEX(DMA1_Stream4));
    __DMA_CLEAR_FLAG(DMA1_Stream4, __DMA_GET_FE_FLAG_INDEX(DMA1_Stream4));
    __DMA_CLEAR_FLAG(DMA1_Stream4, __DMA_GET_HT_FLAG_INDEX(DMA1_Stream4));


    __SPI_CLEAR_CRCERRFLAG(SPI2);
    __SPI_CLEAR_MODFFLAG(SPI2);
    __SPI_CLEAR_OVRFLAG(SPI2);
    __SPI_CLEAR_FREFLAG(SPI2);
}




static void setupSpi2moduleForTransfer(void)
{
    uint32_t tmp;
    Stream3TxRxCpltReceived = FALSE;
    shutDownSpi2();
    __DMA1_CLK_ENABLE();
    __SPI2_CLK_ENABLE();


    tmp = DMA1_Stream3->CR;                                // Get the CR register value


    // Clear CHSEL, MBURST, PBURST, PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR, CT and DBM bits
    tmp &= ((uint32_t)~(DMA_SxCR_CHSEL | DMA_SxCR_MBURST | DMA_SxCR_PBURST | DMA_SxCR_PL    |
                        DMA_SxCR_MSIZE | DMA_SxCR_PSIZE  | DMA_SxCR_MINC   | DMA_SxCR_PINC  |
                        DMA_SxCR_CIRC  | DMA_SxCR_DIR    | DMA_SxCR_CT     | DMA_SxCR_DBM));


    // Prepare the DMA Stream configuration
    tmp |=  DMA_CHANNEL_0       | DMA_PERIPH_TO_MEMORY | DMA_PINC_DISABLE | DMA_MINC_ENABLE |
            DMA_PDATAALIGN_BYTE | DMA_MDATAALIGN_BYTE  | DMA_CIRCULAR     | DMA_PRIORITY_LOW;


    DMA1_Stream3->CR = tmp;                                // Write to DMA Stream CR register
    tmp = DMA1_Stream3->FCR;                               // Get the FCR register value
    tmp &= (uint32_t)~(DMA_SxFCR_DMDIS | DMA_SxFCR_FTH);   // Clear Direct mode and FIFO threshold bits
    tmp |= DMA_FIFOMODE_DISABLE;                           // Prepare the DMA Stream FIFO configuration
    DMA1_Stream3->FCR = tmp;                               // Write to DMA Stream FCR




    tmp = DMA1_Stream4->CR;                                // Get the CR register value


    // Clear CHSEL, MBURST, PBURST, PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR, CT and DBM bits
    tmp &= ((uint32_t)~(DMA_SxCR_CHSEL | DMA_SxCR_MBURST | DMA_SxCR_PBURST | DMA_SxCR_PL    |
                        DMA_SxCR_MSIZE | DMA_SxCR_PSIZE  | DMA_SxCR_MINC   | DMA_SxCR_PINC  |
                        DMA_SxCR_CIRC  |  DMA_SxCR_DIR   | DMA_SxCR_CT     | DMA_SxCR_DBM));


    // Prepare the DMA Stream configuration
    tmp |=  DMA_CHANNEL_0       | DMA_MEMORY_TO_PERIPH | DMA_PINC_DISABLE | DMA_MINC_ENABLE  |
            DMA_PDATAALIGN_BYTE | DMA_MDATAALIGN_BYTE  | DMA_NORMAL       | DMA_PRIORITY_LOW;


    DMA1_Stream4->CR = tmp;                                // Write to DMA Stream CR register
    tmp = DMA1_Stream4->FCR;                               // Get the FCR register value
    tmp &= (uint32_t)~(DMA_SxFCR_DMDIS | DMA_SxFCR_FTH);   // Clear Direct mode and FIFO threshold bits
    tmp |= DMA_FIFOMODE_DISABLE;                           // Prepare the DMA Stream FIFO configuration
    DMA1_Stream4->FCR = tmp;                               // Write to DMA Stream FCR


    //----------------------- SPIx CR1 & CR2 Configuration ---------------------
    // Configure : SPI Mode, Communication Mode, Data size, Clock polarity and phase, NSS management,
    // Communication speed, First bit and CRC calculation state
    SPI2->CR1 = (SPI_MODE_SLAVE  | SPI_DIRECTION_2LINES               | SPI_DATASIZE_8BIT |  SPI_POLARITY_HIGH  |
                 SPI_PHASE_2EDGE | (SPI_NSS_HARD_INPUT & SPI_CR1_SSM) | SPI_FIRSTBIT_MSB  |  SPI_CRCCALCULATION_ENABLED);


    // Configure : NSS management
    SPI2->CR2 = (((SPI_NSS_HARD_INPUT >> 16) & SPI_CR2_SSOE) | SPI_TIMODE_DISABLED);
    SPI2->CRCPR = 7;                                       // Configure : CRC Polynomial


    // Activate the SPI mode (Make sure that I2SMOD bit in I2SCFGR register is reset)
    SPI2->I2SCFGR &= (uint32_t)(~SPI_I2SCFGR_I2SMOD);


    RESET_SPI_CRC(SPI2);                                   // Reset CRC Calculation
    DMA1_Stream3->CR &= (uint32_t)(~DMA_SxCR_DBM);         // Clear DBM bit
    DMA1_Stream4->CR &= (uint32_t)(~DMA_SxCR_DBM);         // Clear DBM bit


    HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
    HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn);
    __DMA_ENABLE_IT(DMA1_Stream3, DMA_IT_TC);              // Enable the transfer complete interrupt
    __DMA_ENABLE_IT(DMA1_Stream3, DMA_IT_TE);              // Enable the transfer Error interrupt
    __DMA_ENABLE_IT(DMA1_Stream3, DMA_IT_FE);              // Enable the FIFO Error interrupt
    __DMA_ENABLE_IT(DMA1_Stream3, DMA_IT_DME);             // Enable the direct mode Error interrupt
    __DMA_ENABLE_IT(DMA1_Stream4, DMA_IT_TC);              // Enable the transfer complete interrupt
    __DMA_ENABLE_IT(DMA1_Stream4, DMA_IT_TE);              // Enable the transfer Error interrupt
    __DMA_ENABLE_IT(DMA1_Stream4, DMA_IT_FE);              // Enable the FIFO Error interrupt
    __DMA_ENABLE_IT(DMA1_Stream4, DMA_IT_DME);             // Enable the direct mode Error interrupt


    HAL_NVIC_EnableIRQ(SPI2_IRQn);                         // Enable SPI bus interrupts
    SPI2->CR2 |= SPI_CR2_ERRIE;


    DMA1_Stream3->CR |= DMA_SxCR_EN;                       // Enable the Peripheral
    DMA1_Stream4->CR |= DMA_SxCR_EN;                       // Enable the Peripheral
    SPI2->CR1 |= SPI_CR1_SPE;                              // Enable SPI peripheral
    SPI2->CR2 |= SPI_CR2_RXDMAEN;                          // Enable Rx DMA Request
    SPI2->CR2 |= SPI_CR2_TXDMAEN;                          // Enable Tx DMA Request
}




void prepareTransferSpi2(uint8_t* bytesToTransmit)
{
    uint16_t i;
    for (i = 0; i < 4; i++)
    {
        transmitDMAbuffer[i] = bytesToTransmit[i];
    }
    setupSpi2moduleForTransfer();
}




void DMA1_Stream3_IRQHandler(void)
{
    UART4_TransmitNullTerminatedString((uint8_t*)"\r\nDMA1_Stream3_IRQHandler beginning");


    // 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
            Stream3TxRxCpltReceived = TRUE;
            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 < 4; i++)
            {
                UART4_TransmitNullTerminatedString((uint8_t*) "\r\n0x");
                UART4_TransmitHexNumberAsASCII((uint32_t)receiveDMAbuffer[i]);
            }
        }
    }
    UART4_TransmitNullTerminatedString((uint8_t*)"\r\nDMA1_Stream3_IRQHandler end");
}




void DMA1_Stream4_IRQHandler(void)
{
    UART4_TransmitNullTerminatedString((uint8_t*)"\r\nDMA1_Stream4_IRQHandler beginning");
    // Transfer Error Interrupt management
    if(__DMA_GET_FLAG(DMA1_Stream4, __DMA_GET_TE_FLAG_INDEX(DMA1_Stream4)) != RESET)
    {
        if(__DMA_GET_IT_SOURCE(DMA1_Stream4, DMA_IT_TE) != RESET)
        {
            __DMA_DISABLE_IT(DMA1_Stream4, DMA_IT_TE);                             // Disable the transfer error interrupt
            __DMA_CLEAR_FLAG(DMA1_Stream4, __DMA_GET_TE_FLAG_INDEX(DMA1_Stream4)); // 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_Stream4, __DMA_GET_FE_FLAG_INDEX(DMA1_Stream4)) != RESET)
    {
        if(__DMA_GET_IT_SOURCE(DMA1_Stream4, DMA_IT_FE) != RESET)
        {
            __DMA_DISABLE_IT(DMA1_Stream4, DMA_IT_FE);                              // Disable the FIFO Error interrupt
            __DMA_CLEAR_FLAG(DMA1_Stream4, __DMA_GET_FE_FLAG_INDEX(DMA1_Stream4));  // 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_Stream4, __DMA_GET_DME_FLAG_INDEX(DMA1_Stream4)) != RESET)
    {
        if(__DMA_GET_IT_SOURCE(DMA1_Stream4, DMA_IT_DME) != RESET)
        {
            __DMA_DISABLE_IT(DMA1_Stream4, DMA_IT_DME);                              // Disable the direct mode Error interrupt
            __DMA_CLEAR_FLAG(DMA1_Stream4, __DMA_GET_DME_FLAG_INDEX(DMA1_Stream4));  // 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_Stream4, __DMA_GET_HT_FLAG_INDEX(DMA1_Stream4)) != RESET)
    {
        if(__DMA_GET_IT_SOURCE(DMA1_Stream4, DMA_IT_HT) != RESET)
        {
            /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
            if((DMA1_Stream4->CR & DMA_SxCR_CIRC) == 0)
            {
                /* Disable the half transfer interrupt */
                __DMA_DISABLE_IT(DMA1_Stream4, DMA_IT_HT);
            }
            /* Clear the half transfer complete flag */
            __DMA_CLEAR_FLAG(DMA1_Stream4, __DMA_GET_HT_FLAG_INDEX(DMA1_Stream4));
        }


        // Half transfer callback
        UART4_TransmitNullTerminatedString((uint8_t*)"\r\nSPI_DMATransmitReceiveHalfCplt");
        UART4_WaitForTransmitToFinish();
    }




    // Transfer Complete Interrupt management
    if(__DMA_GET_FLAG(DMA1_Stream4, __DMA_GET_TC_FLAG_INDEX(DMA1_Stream4)) != RESET)
    {
        if(__DMA_GET_IT_SOURCE(DMA1_Stream4, DMA_IT_TC) != RESET)
        {
            // Disable the transfer complete interrupt if the DMA mode is not CIRCULAR
            if((DMA1_Stream4->CR & DMA_SxCR_CIRC) == 0)
            {


              __DMA_DISABLE_IT(DMA1_Stream4, DMA_IT_TC);   // Disable the transfer complete interrupt
            }
            __DMA_CLEAR_FLAG(DMA1_Stream4, __DMA_GET_TC_FLAG_INDEX(DMA1_Stream4));  // Clear the transfer complete flag


            // Transfer complete callback
            if (!Stream3TxRxCpltReceived)
            {
                UART4_TransmitNullTerminatedString((uint8_t*)"\r\nSPI_DMATransmitReceiveCplt, ERROR!!!!");
                UART4_WaitForTransmitToFinish();
            }
            else
            {
                UART4_TransmitNullTerminatedString((uint8_t*)"\r\nSPI_DMATransmitReceiveCplt, everything ok");
                UART4_WaitForTransmitToFinish();
            }
        }
    }
    UART4_TransmitNullTerminatedString((uint8_t*)"\r\nDMA1_Stream4_IRQHandler end");
}




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