cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_DMA_XferCpltCallback not triggered after DMA transfer complete

xtxftzld
Associate

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:

 

 

1 ACCEPTED SOLUTION

Accepted Solutions

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.

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

13 REPLIES 13
TDK
Super User

When HAL_TIM_IC_Start_DMA completes, the HAL_TIM_IC_CaptureCallback callback is called.

 

If you feel a post has answered your question, please click "Accept as Solution".
Saket_Om
ST Employee

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.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om

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

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.

 

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 */
}

 

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om

Hi,

I just put your script manually (without touching the CubeMX) in my main.c with a LED-Toggleing in "TransferComplete":

static void TransferComplete(DMA_HandleTypeDef *DmaHandle)
{
  /* Transfer correct */
	HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_12);
}

 I finish the declartion and registered the function as you did. I uploaded the program, the function you offered is not triggered.

I checked the Variables IC_Values[0], where I stored the DMA values. The DMA is running in circular mode. 

Hello @xtxftzld 

Could you please check which flag triggers the DMA interrupt? You can set a breakpoint at HAL_DMA_IRQHandler() and step through the code to identify the specific flag.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om

xtxftzld_0-1763719384565.png

Hi,

in debugging modus, it arrives "/* Transfer complete callback */", which means the transfer complete call back should be triggered, right? but after this point, the program dose not go back to main.c:

xtxftzld_1-1763719953250.png

after this the program runs into: 

xtxftzld_2-1763719994678.png

then it comes back to my breakpont I set:

xtxftzld_3-1763720037287.png

and so on.

the programm never enter the main.c again, strange.

@xtxftzld 

Could you please share your code ?

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om