cancel
Showing results for 
Search instead for 
Did you mean: 

Peripheral to Mem BDMA on H750

VN.2
Associate III

Hi, I am looking to read 16bits which are split between port A and B on an interrupt hooked up to exti0. I *seem* to have the dma working and see the expected data at DMA completion (interrupt). However the DMA controller does not react to the interrupt quick enough and Im trying to compensate by triggering a little earlier and having the dma controller read a few more instances from A/B ->IDR. What I am stuck at is how I can get the data to output to an array of 32 words in a ringbuffer fashion. It seems circular mode limits itself to 4 words total. Which is not enough to grab the data I want.

I also couldnt understand when DMA continues in circular mode while in the completion interrupt. Do I need to temporarily suspend DMA while in that interrupt to read the data or does DMA continue on clearing the pending bit?

Should I be using a separate DMA channel to take Data out of sram and put it in a stack allocated array?

Thanks!

1 ACCEPTED SOLUTION

Accepted Solutions
VN.2
Associate III

Thanks Tesla DeLorean for the helpful input. I realize I should have put up some signal form just to explain what I was after.

Summarizing my issue and solution:

  1. I was struggling to understand how the looping (of circular mode) was being handled through the HAL API. The most important part I missed is that the HAL_DMA_Start_IT(Channel, Output, Input, **DATALENGTH**); is talking about the size of the output location, which is directly stuffed into the DMA NDTR register.
  2. The circular mode being triggered off an EXTI interrupt means that "PeriphDataAlignment" will be read "dmamux_ReqGenParams.RequestNumber" times per interrupt. What I missed here is again related to point 1, datalength (aka NDTR) controls the warp around point of the DMA output. Which I initially thought to be controlled by "dmamux_ReqGenParams.RequestNumber".

Fixes:

  1. Changed the datalength to be 2, as I want the completion interrupt only when 2 values have been read. I don't need the halfway interrupt.
  2. Set request to back to 1. Because each edge just needs to trigger 1 read.
  3. Went back to a single buffer, as I have ample time to use the values in sram.

Here is the currently working init and a picture that explains the data collected for portA

int InitializeDmaChannels(void)
{
    HAL_DMA_MuxRequestGeneratorConfigTypeDef dmamux_ReqGenParams  = {0};
 
    /*##-2- Configure the DMA ##################################################*/
    /* Enable BDMA clock */
    __HAL_RCC_BDMA_CLK_ENABLE();
 
    { // Channel 0 init.
        /* Configure the DMA handler for Transmission process     */
        /* DMA mode is set to circular for an infinite DMA transfer */
        DMA_Handle_Channel0.Instance                 = BDMA_Channel0;
        DMA_Handle_Channel0.Init.Request             = BDMA_REQUEST_GENERATOR0;
        DMA_Handle_Channel0.Init.Direction           = DMA_PERIPH_TO_MEMORY;
        DMA_Handle_Channel0.Init.PeriphInc           = DMA_PINC_DISABLE;
        DMA_Handle_Channel0.Init.MemInc              = DMA_MINC_ENABLE;
        DMA_Handle_Channel0.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        DMA_Handle_Channel0.Init.MemDataAlignment    = DMA_PDATAALIGN_WORD;
        DMA_Handle_Channel0.Init.Mode                = DMA_CIRCULAR;
        DMA_Handle_Channel0.Init.Priority            = DMA_PRIORITY_VERY_HIGH;
        DMA_Handle_Channel0.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
        DMA_Handle_Channel0.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_HALFFULL;
        DMA_Handle_Channel0.Init.MemBurst            = DMA_MBURST_SINGLE;
        DMA_Handle_Channel0.Init.PeriphBurst         = DMA_PBURST_SINGLE;
 
        /* Initialize the DMA with for Transmission process */
        HAL_StatusTypeDef dmares = HAL_OK;
        dmares = HAL_DMA_Init(&DMA_Handle_Channel0);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
        /* Select Callbacks functions called after Transfer complete and Transfer error */
        dmares = HAL_DMA_RegisterCallback(&DMA_Handle_Channel0, HAL_DMA_XFER_CPLT_CB_ID, NULL);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
        dmares = HAL_DMA_RegisterCallback(&DMA_Handle_Channel0, HAL_DMA_XFER_ERROR_CB_ID, HAL_TransferError);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
                /* NVIC configuration for DMA transfer complete interrupt*/
        HAL_NVIC_SetPriority(BDMA_Channel0_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(BDMA_Channel0_IRQn);
 
        /*##-3- Configure and enable the DMAMUX Request generator  ####################*/
        dmamux_ReqGenParams.SignalID  = HAL_DMAMUX2_REQ_GEN_EXTI0;
        dmamux_ReqGenParams.Polarity  = HAL_DMAMUX_REQ_GEN_RISING_FALLING;
        dmamux_ReqGenParams.RequestNumber = 1;                          /* 1 requests on each edge of the external request signal  */
 
        dmares = HAL_DMAEx_ConfigMuxRequestGenerator(&DMA_Handle_Channel0, &dmamux_ReqGenParams);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
        /* NVIC configuration for DMAMUX request generator overrun errors*/
        HAL_NVIC_SetPriority(DMAMUX2_OVR_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(DMAMUX2_OVR_IRQn);
 
        dmares = HAL_DMAEx_EnableMuxRequestGenerator (&DMA_Handle_Channel0);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
        dmares = HAL_DMA_Start_IT(&DMA_Handle_Channel0, (uint32_t)&(GPIOB->IDR), (uint32_t)(PortBBuffer), 2);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
    }
 
    { // Channel 1 init.
        /* Configure the DMA handler for Transmission process     */
        /* DMA mode is set to circular for an infinite DMA transfer */
        DMA_Handle_Channel1.Instance                 = BDMA_Channel1;
        DMA_Handle_Channel1.Init.Request             = BDMA_REQUEST_GENERATOR0;
        DMA_Handle_Channel1.Init.Direction           = DMA_PERIPH_TO_MEMORY;
        DMA_Handle_Channel1.Init.PeriphInc           = DMA_PINC_DISABLE;
        DMA_Handle_Channel1.Init.MemInc              = DMA_MINC_ENABLE;
        DMA_Handle_Channel1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
        DMA_Handle_Channel1.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
        DMA_Handle_Channel1.Init.Mode                = DMA_CIRCULAR;
        DMA_Handle_Channel1.Init.Priority            = DMA_PRIORITY_VERY_HIGH;
        DMA_Handle_Channel1.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
        DMA_Handle_Channel1.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_HALFFULL;
        DMA_Handle_Channel1.Init.MemBurst            = DMA_MBURST_SINGLE;
        DMA_Handle_Channel1.Init.PeriphBurst         = DMA_PBURST_SINGLE;
 
        /* Initialize the DMA with for Transmission process */
        HAL_StatusTypeDef dmares = HAL_OK;
        dmares = HAL_DMA_Init(&DMA_Handle_Channel1);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
        /* Select Callbacks functions called after Transfer complete and Transfer error */
        dmares = HAL_DMA_RegisterCallback(&DMA_Handle_Channel1, HAL_DMA_XFER_CPLT_CB_ID, NULL);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
        dmares = HAL_DMA_RegisterCallback(&DMA_Handle_Channel1, HAL_DMA_XFER_ERROR_CB_ID, HAL_TransferError);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
        /* NVIC configuration for DMA transfer complete interrupt*/
        HAL_NVIC_SetPriority(BDMA_Channel1_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(BDMA_Channel1_IRQn);
 
        /*##-3- Configure and enable the DMAMUX Request generator  ####################*/
        dmamux_ReqGenParams.SignalID  = HAL_DMAMUX2_REQ_GEN_EXTI0;
        dmamux_ReqGenParams.Polarity  = HAL_DMAMUX_REQ_GEN_RISING_FALLING;
        dmamux_ReqGenParams.RequestNumber = 1;
 
        dmares = HAL_DMAEx_ConfigMuxRequestGenerator(&DMA_Handle_Channel1, &dmamux_ReqGenParams);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
        /* NVIC configuration for DMAMUX request generator overrun errors*/
        HAL_NVIC_SetPriority(DMAMUX2_OVR_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(DMAMUX2_OVR_IRQn);
 
        dmares = HAL_DMAEx_EnableMuxRequestGenerator (&DMA_Handle_Channel1);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
        volatile uint32_t dmares1 = HAL_DMA_Start_IT(&DMA_Handle_Channel1, (uint32_t)&(GPIOA->IDR), (uint32_t)(PortABuffer), 2);
        if (dmares1 != HAL_OK) {
            Error_Handler();
        }
    }
 
    return 0;
}

0693W00000SuJZEQA3.png

View solution in original post

5 REPLIES 5

DMA should be viable over quite significant buffer sizes

In circular mode DMA continues, but be agile, it's not going to wait for you.

Pick a size such that the interrupt can do it's work and leave within the time it takes to fill one half of the ping-pong buffer arrangement, and have the HT and TC IRQ handle the inactive portion of the buffer.

On CM7 make sure you properly manage cache coherency, the DMA units looks/changes actual memory, not stuff you have in the cache or floating in the write buffers.

Don't use the stack for DMA buffers, the memory is transitory, the DMA is less so

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
a

I am doing CleanInvalidate Dcache on the sram address that I am attempting to read. I've added the below testcode to illustrate the setup and the interrupts.

I'm only seeing PortABuffer being filled with 4 words, even if I set dmamux_ReqGenParams.RequestNumber to 32. This is done by inspecting PortABuffer through GDB "x PortABuffer[4]".PortABuffer[0] to PortABuffer[3] show reasonable data PortABuffer[4] is complete garbage.

Since you say circular continues, should it continue even if no subsequent trigger occurs, or does it wait for the trigger always, or should I be using normal mode instead?

I swapped the stack vars with some logging to ram. I understand stack is transient but was more concerned with the fact that the cm7 was moving those.

int8_t *ram = (int8_t *)0xC0000000;
BYTE *Sram4Buffer = (BYTE*)0x38000000;
uint32_t *PortABuffer = (uint32_t*)Sram4Buffer;
uint32_t *PortBBuffer = (uint32_t*)(Sram4Buffer + (32*4));
int InitializeDmaChannels(void)
{
    HAL_DMA_MuxRequestGeneratorConfigTypeDef dmamux_ReqGenParams  = {0};
 
    /*##-2- Configure the DMA ##################################################*/
    /* Enable BDMA clock */
    __HAL_RCC_BDMA_CLK_ENABLE();
 
    { // Channel 0 init.
        /* Configure the DMA handler for Transmission process     */
        /* DMA mode is set to circular for an infinite DMA transfer */
        DMA_Handle_Channel0.Instance                 = BDMA_Channel0;
        DMA_Handle_Channel0.Init.Request             = BDMA_REQUEST_GENERATOR0;
        DMA_Handle_Channel0.Init.Direction           = DMA_PERIPH_TO_MEMORY;
        DMA_Handle_Channel0.Init.PeriphInc           = DMA_PINC_DISABLE;
        DMA_Handle_Channel0.Init.MemInc              = DMA_MINC_ENABLE;
        DMA_Handle_Channel0.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
        DMA_Handle_Channel0.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
        DMA_Handle_Channel0.Init.Mode                = DMA_CIRCULAR;
        DMA_Handle_Channel0.Init.Priority            = DMA_PRIORITY_VERY_HIGH;
        DMA_Handle_Channel0.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
        DMA_Handle_Channel0.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_HALFFULL;
        DMA_Handle_Channel0.Init.MemBurst            = DMA_MBURST_SINGLE;
        DMA_Handle_Channel0.Init.PeriphBurst         = DMA_PBURST_SINGLE;
 
        /* Initialize the DMA with for Transmission process */
        HAL_StatusTypeDef dmares = HAL_OK;
        dmares = HAL_DMA_Init(&DMA_Handle_Channel0);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
        /* Select Callbacks functions called after Transfer complete and Transfer error */
        dmares = HAL_DMA_RegisterCallback(&DMA_Handle_Channel0, HAL_DMA_XFER_CPLT_CB_ID, NULL);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
        dmares = HAL_DMA_RegisterCallback(&DMA_Handle_Channel0, HAL_DMA_XFER_ERROR_CB_ID, HAL_TransferError);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
                /* NVIC configuration for DMA transfer complete interrupt*/
        HAL_NVIC_SetPriority(BDMA_Channel0_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(BDMA_Channel0_IRQn);
 
        /*##-3- Configure and enable the DMAMUX Request generator  ####################*/
        dmamux_ReqGenParams.SignalID  = HAL_DMAMUX2_REQ_GEN_EXTI0;
        dmamux_ReqGenParams.Polarity  = HAL_DMAMUX_REQ_GEN_RISING;
        dmamux_ReqGenParams.RequestNumber = 4; // Setting this to 32 still only seems to return 4 WORDs.
 
        dmares = HAL_DMAEx_ConfigMuxRequestGenerator(&DMA_Handle_Channel0, &dmamux_ReqGenParams);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
        /* NVIC configuration for DMAMUX request generator overrun errors*/
        HAL_NVIC_SetPriority(DMAMUX2_OVR_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(DMAMUX2_OVR_IRQn);
 
        dmares = HAL_DMAEx_EnableMuxRequestGenerator (&DMA_Handle_Channel0);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
        //dmares = HAL_DMA_Start_IT(&DMA_Handle_Channel0, (uint32_t)&(GPIOB->IDR), (uint32_t)(Sram4Buffer), 4);
        //dmares = HAL_DMA_Start_IT(&DMA_Handle_Channel0, (uint32_t)(Sram4Buffer + 8), (uint32_t)&(GPIOA->ODR), 8);
        dmares = HAL_DMAEx_MultiBufferStart_IT(&DMA_Handle_Channel0, (uint32_t)&(GPIOA->IDR), (uint32_t)PortABuffer, (uint32_t)(PortABuffer+128), 4);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
    }
 
    { // Channel 1 init.
        DMA_Handle_Channel1.Instance                 = BDMA_Channel1;
        DMA_Handle_Channel1.Init.Request             = BDMA_REQUEST_GENERATOR0;
        DMA_Handle_Channel1.Init.Direction           = DMA_PERIPH_TO_MEMORY;
        DMA_Handle_Channel1.Init.PeriphInc           = DMA_PINC_DISABLE;
        DMA_Handle_Channel1.Init.MemInc              = DMA_MINC_ENABLE;
        DMA_Handle_Channel1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
        DMA_Handle_Channel1.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
        DMA_Handle_Channel1.Init.Mode                = DMA_CIRCULAR;
        DMA_Handle_Channel1.Init.Priority            = DMA_PRIORITY_VERY_HIGH;
        DMA_Handle_Channel1.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
        DMA_Handle_Channel1.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_HALFFULL;
        DMA_Handle_Channel1.Init.MemBurst            = DMA_MBURST_SINGLE;
        DMA_Handle_Channel1.Init.PeriphBurst         = DMA_PBURST_SINGLE;
 
        /* Initialize the DMA with for Transmission process */
        HAL_StatusTypeDef dmares = HAL_OK;
        dmares = HAL_DMA_Init(&DMA_Handle_Channel1);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
        dmares = HAL_DMA_RegisterCallback(&DMA_Handle_Channel1, HAL_DMA_XFER_CPLT_CB_ID, NULL);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
        dmares = HAL_DMA_RegisterCallback(&DMA_Handle_Channel1, HAL_DMA_XFER_ERROR_CB_ID, HAL_TransferError);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
        /* NVIC configuration for DMA transfer complete interrupt*/
        HAL_NVIC_SetPriority(BDMA_Channel1_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(BDMA_Channel1_IRQn);
 
        /*##-3- Configure and enable the DMAMUX Request generator  ####################*/
        dmamux_ReqGenParams.SignalID  = HAL_DMAMUX2_REQ_GEN_EXTI0;
        dmamux_ReqGenParams.Polarity  = HAL_DMAMUX_REQ_GEN_RISING;
        dmamux_ReqGenParams.RequestNumber = 4; // Setting this to 32 still only seems to return 4 WORDs.
 
        dmares = HAL_DMAEx_ConfigMuxRequestGenerator(&DMA_Handle_Channel1, &dmamux_ReqGenParams);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
        /* NVIC configuration for DMAMUX request generator overrun errors*/
        HAL_NVIC_SetPriority(DMAMUX2_OVR_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(DMAMUX2_OVR_IRQn);
 
        dmares = HAL_DMAEx_EnableMuxRequestGenerator (&DMA_Handle_Channel1);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
        //volatile uint32_t dmares1 = HAL_DMA_Start_IT(&DMA_Handle_Channel1, (uint32_t)&(GPIOA->IDR), (uint32_t)(PortBBuffer), 4);
        volatile uint32_t dmares1 = HAL_DMAEx_MultiBufferStart_IT(&DMA_Handle_Channel1, (uint32_t)&(GPIOB->IDR), (uint32_t)PortBBuffer, (uint32_t)(PortBBuffer+128), 4);
        if (dmares1 != HAL_OK) {
            Error_Handler();
        }
    }
 
    return 0;
}
 
extern "C" void BDMA_Channel0_IRQHandler(void)
{
    ((BDMA_Base_Registers *)(DMA_Handle_Channel0.StreamBaseAddress))->IFCR = (2 << 0);
    SCB_CleanInvalidateDCache_by_Addr((uint32_t*)PortABuffer + ((DMACount & 1)*128), 32);
    ((uint32_t*)ram)[DMACount * 2] = *((uint32_t*)(PortABuffer + ((DMACount & 1)*128)));
    DMACount += 1;
}
 
extern "C" void BDMA_Channel1_IRQHandler(void)
{
    ((BDMA_Base_Registers *)(DMA_Handle_Channel0.StreamBaseAddress))->IFCR = (2 << 4);
    SCB_CleanInvalidateDCache_by_Addr((uint32_t*)PortBBuffer + ((DMACount1 & 1)*128), 32);
    ((uint32_t*)ram)[DMACount1 * 2 + 1] = *((uint32_t*)(PortBBuffer + ((DMACount1 & 1)*128)));
    DMACount1 += 1;
}

Your interrupts should explicitly handle the HT and TC cases.

You should clear the appropriate interrupt source, or the global one.

The buffers should be large enough that you have actual time to manage things.

There is not good reason why the buffers can't be 4KB deep, with HT/TC as each 2KB is filled.

If the DMA is stopping or failing look at the error / status thrown.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
VN.2
Associate III

Do HT TC happen if FIFO is disabled? I don't want FIFO's because that adds latency.

The way I also understood the spec for BDMA is that for whole words the max Fifo depth is 4.

0693W00000SuE5TQAV.png

VN.2
Associate III

Thanks Tesla DeLorean for the helpful input. I realize I should have put up some signal form just to explain what I was after.

Summarizing my issue and solution:

  1. I was struggling to understand how the looping (of circular mode) was being handled through the HAL API. The most important part I missed is that the HAL_DMA_Start_IT(Channel, Output, Input, **DATALENGTH**); is talking about the size of the output location, which is directly stuffed into the DMA NDTR register.
  2. The circular mode being triggered off an EXTI interrupt means that "PeriphDataAlignment" will be read "dmamux_ReqGenParams.RequestNumber" times per interrupt. What I missed here is again related to point 1, datalength (aka NDTR) controls the warp around point of the DMA output. Which I initially thought to be controlled by "dmamux_ReqGenParams.RequestNumber".

Fixes:

  1. Changed the datalength to be 2, as I want the completion interrupt only when 2 values have been read. I don't need the halfway interrupt.
  2. Set request to back to 1. Because each edge just needs to trigger 1 read.
  3. Went back to a single buffer, as I have ample time to use the values in sram.

Here is the currently working init and a picture that explains the data collected for portA

int InitializeDmaChannels(void)
{
    HAL_DMA_MuxRequestGeneratorConfigTypeDef dmamux_ReqGenParams  = {0};
 
    /*##-2- Configure the DMA ##################################################*/
    /* Enable BDMA clock */
    __HAL_RCC_BDMA_CLK_ENABLE();
 
    { // Channel 0 init.
        /* Configure the DMA handler for Transmission process     */
        /* DMA mode is set to circular for an infinite DMA transfer */
        DMA_Handle_Channel0.Instance                 = BDMA_Channel0;
        DMA_Handle_Channel0.Init.Request             = BDMA_REQUEST_GENERATOR0;
        DMA_Handle_Channel0.Init.Direction           = DMA_PERIPH_TO_MEMORY;
        DMA_Handle_Channel0.Init.PeriphInc           = DMA_PINC_DISABLE;
        DMA_Handle_Channel0.Init.MemInc              = DMA_MINC_ENABLE;
        DMA_Handle_Channel0.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
        DMA_Handle_Channel0.Init.MemDataAlignment    = DMA_PDATAALIGN_WORD;
        DMA_Handle_Channel0.Init.Mode                = DMA_CIRCULAR;
        DMA_Handle_Channel0.Init.Priority            = DMA_PRIORITY_VERY_HIGH;
        DMA_Handle_Channel0.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
        DMA_Handle_Channel0.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_HALFFULL;
        DMA_Handle_Channel0.Init.MemBurst            = DMA_MBURST_SINGLE;
        DMA_Handle_Channel0.Init.PeriphBurst         = DMA_PBURST_SINGLE;
 
        /* Initialize the DMA with for Transmission process */
        HAL_StatusTypeDef dmares = HAL_OK;
        dmares = HAL_DMA_Init(&DMA_Handle_Channel0);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
        /* Select Callbacks functions called after Transfer complete and Transfer error */
        dmares = HAL_DMA_RegisterCallback(&DMA_Handle_Channel0, HAL_DMA_XFER_CPLT_CB_ID, NULL);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
        dmares = HAL_DMA_RegisterCallback(&DMA_Handle_Channel0, HAL_DMA_XFER_ERROR_CB_ID, HAL_TransferError);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
                /* NVIC configuration for DMA transfer complete interrupt*/
        HAL_NVIC_SetPriority(BDMA_Channel0_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(BDMA_Channel0_IRQn);
 
        /*##-3- Configure and enable the DMAMUX Request generator  ####################*/
        dmamux_ReqGenParams.SignalID  = HAL_DMAMUX2_REQ_GEN_EXTI0;
        dmamux_ReqGenParams.Polarity  = HAL_DMAMUX_REQ_GEN_RISING_FALLING;
        dmamux_ReqGenParams.RequestNumber = 1;                          /* 1 requests on each edge of the external request signal  */
 
        dmares = HAL_DMAEx_ConfigMuxRequestGenerator(&DMA_Handle_Channel0, &dmamux_ReqGenParams);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
        /* NVIC configuration for DMAMUX request generator overrun errors*/
        HAL_NVIC_SetPriority(DMAMUX2_OVR_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(DMAMUX2_OVR_IRQn);
 
        dmares = HAL_DMAEx_EnableMuxRequestGenerator (&DMA_Handle_Channel0);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
        dmares = HAL_DMA_Start_IT(&DMA_Handle_Channel0, (uint32_t)&(GPIOB->IDR), (uint32_t)(PortBBuffer), 2);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
    }
 
    { // Channel 1 init.
        /* Configure the DMA handler for Transmission process     */
        /* DMA mode is set to circular for an infinite DMA transfer */
        DMA_Handle_Channel1.Instance                 = BDMA_Channel1;
        DMA_Handle_Channel1.Init.Request             = BDMA_REQUEST_GENERATOR0;
        DMA_Handle_Channel1.Init.Direction           = DMA_PERIPH_TO_MEMORY;
        DMA_Handle_Channel1.Init.PeriphInc           = DMA_PINC_DISABLE;
        DMA_Handle_Channel1.Init.MemInc              = DMA_MINC_ENABLE;
        DMA_Handle_Channel1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
        DMA_Handle_Channel1.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
        DMA_Handle_Channel1.Init.Mode                = DMA_CIRCULAR;
        DMA_Handle_Channel1.Init.Priority            = DMA_PRIORITY_VERY_HIGH;
        DMA_Handle_Channel1.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
        DMA_Handle_Channel1.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_HALFFULL;
        DMA_Handle_Channel1.Init.MemBurst            = DMA_MBURST_SINGLE;
        DMA_Handle_Channel1.Init.PeriphBurst         = DMA_PBURST_SINGLE;
 
        /* Initialize the DMA with for Transmission process */
        HAL_StatusTypeDef dmares = HAL_OK;
        dmares = HAL_DMA_Init(&DMA_Handle_Channel1);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
        /* Select Callbacks functions called after Transfer complete and Transfer error */
        dmares = HAL_DMA_RegisterCallback(&DMA_Handle_Channel1, HAL_DMA_XFER_CPLT_CB_ID, NULL);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
        dmares = HAL_DMA_RegisterCallback(&DMA_Handle_Channel1, HAL_DMA_XFER_ERROR_CB_ID, HAL_TransferError);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
        /* NVIC configuration for DMA transfer complete interrupt*/
        HAL_NVIC_SetPriority(BDMA_Channel1_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(BDMA_Channel1_IRQn);
 
        /*##-3- Configure and enable the DMAMUX Request generator  ####################*/
        dmamux_ReqGenParams.SignalID  = HAL_DMAMUX2_REQ_GEN_EXTI0;
        dmamux_ReqGenParams.Polarity  = HAL_DMAMUX_REQ_GEN_RISING_FALLING;
        dmamux_ReqGenParams.RequestNumber = 1;
 
        dmares = HAL_DMAEx_ConfigMuxRequestGenerator(&DMA_Handle_Channel1, &dmamux_ReqGenParams);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
        /* NVIC configuration for DMAMUX request generator overrun errors*/
        HAL_NVIC_SetPriority(DMAMUX2_OVR_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(DMAMUX2_OVR_IRQn);
 
        dmares = HAL_DMAEx_EnableMuxRequestGenerator (&DMA_Handle_Channel1);
        if (dmares != HAL_OK) {
            Error_Handler();
        }
 
        volatile uint32_t dmares1 = HAL_DMA_Start_IT(&DMA_Handle_Channel1, (uint32_t)&(GPIOA->IDR), (uint32_t)(PortABuffer), 2);
        if (dmares1 != HAL_OK) {
            Error_Handler();
        }
    }
 
    return 0;
}

0693W00000SuJZEQA3.png