Skip to main content
Visitor II
November 20, 2025
Solved

HAL_DMA_XferCpltCallback not triggered after DMA transfer complete

  • November 20, 2025
  • 2 replies
  • 688 views

Post edited by ST moderator to be inline with the community rules for the code sharing. In next time please use </> button to paste your code. Please read this post: How to insert source code.

Hallo,

I am trying to measure the frequency of rectangular signals. the borad I am using is stm32f411-disco

I used the timer 2 channel 1 for input capture. at every capture the timer value will be sent to memery by uing DMA. The DMA seems working, because I printed the captured value periodically. the DMA-Buffer is two, and it is working in a circular mode.

I try to do some calculation in the interruption-function: "void HAL_DMA_XferCpltCallback(DMA_HandleTypeDef *hdma)" like this:

 
void HAL_DMA_XferCpltCallback(DMA_HandleTypeDef *hdma)

{

if (hdma->Instance == DMA1_Stream5) // MCU-abhängig!

{

uint32_t first = IC_Values[0];

uint32_t second = IC_Values[1];



if (second >= first)

diff = second - first;

else

diff = (0xFFFFFFFF - first + second);



/* Timer läuft mit 1 MHz → 1 µs pro Tick */

Frequency = 1e6f / diff;

}

}

 

But this interruption is not triggered.

so my question is, shouldn't this function be triggered after the DMA transfer complete?

 

complete script please see the attachment:

 

 

    This topic has been closed for replies.
    Best answer by TDK

    HAL only calls HAL_TIM_IC_CaptureCallback, not HAL_DMA_XferCpltCallback, at the end of this transfer. That is the intended behavior.

    You can hijack the DMA1_Stream5_IRQHandler handler if you want to process the TC flag.

    2 replies

    Super User
    November 20, 2025

    When HAL_TIM_IC_Start_DMA completes, the HAL_TIM_IC_CaptureCallback callback is called.

     

    xtxftzldAuthor
    Visitor II
    November 21, 2025

    Hi,

    the regular input capture call back: "HAL_TIM_IC_CaptureCallback" is working well. Normally I am also doing like this. But I read in the internet, that after the completion of DMA transfer there is also a callback, which I want to test:

    void HAL_DMA_XferCpltCallback(DMA_HandleTypeDef *hdma)

    But it turned out not working, although the DMA is working properly (the variables are really overwritten).

    TDKAnswer
    Super User
    November 21, 2025

    HAL only calls HAL_TIM_IC_CaptureCallback, not HAL_DMA_XferCpltCallback, at the end of this transfer. That is the intended behavior.

    You can hijack the DMA1_Stream5_IRQHandler handler if you want to process the TC flag.

    Technical Moderator
    November 20, 2025

    Hello @xtxftzld 

    Set a breakpoint in the DMA IRQ handler function to verify that the DMA interrupt handler is being triggered and also check the DMA status registers to see if the transfer complete flag is set as expected.

    xtxftzldAuthor
    Visitor II
    November 21, 2025

    Hello Saket, 

    thanks for your answer,

    I checked first as you said, the DMA_Stream5_IRQHandler by toggling the LED: 

    void DMA1_Stream5_IRQHandler(void)
    {
     /* USER CODE BEGIN DMA1_Stream5_IRQn 0 */
    	//HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_15);
    
     /* USER CODE END DMA1_Stream5_IRQn 0 */
     HAL_DMA_IRQHandler(&hdma_tim2_ch1);
     HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_15);
     /* USER CODE BEGIN DMA1_Stream5_IRQn 1 */
    
     /* USER CODE END DMA1_Stream5_IRQn 1 */
    }

     I gave a rectangular signal of 1 Hz on the PD15, and this IRQHandler is triggerd, since I see the LED blinking with also about 1 Hz.

    Secondly I checked the DMA status registers with:

    void CheckDMA1_Stream5_Status(void)
    {
     uint32_t status = DMA1->HISR;
    
     //printf("DMA1->HISR = 0x%08lX\n", status);
     snprintf(usb_buffer, sizeof(usb_buffer),"DMA1->HISR = 0x%08lX\n", status);
     CDC_Transmit_FS((uint8_t*)usb_buffer, strlen(usb_buffer));
    
     if (status & DMA_HISR_TCIF5){
     snprintf(usb_buffer, sizeof(usb_buffer),"TCIF5 = Transfer Complete\n");
     CDC_Transmit_FS((uint8_t*)usb_buffer, strlen(usb_buffer));
     }
     if (status & DMA_HISR_HTIF5){
     snprintf(usb_buffer, sizeof(usb_buffer),"HTIF5 = Half Transfer\n");
     CDC_Transmit_FS((uint8_t*)usb_buffer, strlen(usb_buffer));
     }
     if (status & DMA_HISR_TEIF5){
     snprintf(usb_buffer, sizeof(usb_buffer),"TEIF5 = Transfer Error\n");
     CDC_Transmit_FS((uint8_t*)usb_buffer, strlen(usb_buffer));
     }
     if (status & DMA_HISR_DMEIF5){
     snprintf(usb_buffer, sizeof(usb_buffer),"DMEIF5 = Direct Mode Error\n");
     CDC_Transmit_FS((uint8_t*)usb_buffer, strlen(usb_buffer));
     }
     if (status & DMA_HISR_FEIF5){
     snprintf(usb_buffer, sizeof(usb_buffer),"FEIF5 = FIFO Error\n");
     CDC_Transmit_FS((uint8_t*)usb_buffer, strlen(usb_buffer));
     }
    
    }

     Hier I just got the message in my serial monitor: "DMA1->HISR = 0x00000000"

    It seems DMA-Status is not changed at all, although the DMA_Stream5_IRQHandler is triggered.

     

    Technical Moderator
    November 21, 2025

    Hello @xtxftzld 

    Could you try with the config below please:

    // DMA handle declaration
    DMA_HandleTypeDef DmaHandle;
    
    
    static void TransferComplete(DMA_HandleTypeDef *DmaHandle);
    
    
    
    int main(void) {
    
     // Register the transfer complete callback
     HAL_DMA_RegisterCallback(&DmaHandle, HAL_DMA_XFER_CPLT_CB_ID, TransferComplete);
     
    
     while (1) {
     // Main loop code
     // You can check for transfer completion or handle other tasks
     }
    }
    
    
    // Callback function for transfer complete
    static void TransferComplete(DMA_HandleTypeDef *DmaHandle)
    {
     /* Transfer correct */
    }