cancel
Showing results for 
Search instead for 
Did you mean: 

DMA interrupt not triggering after init

Klassic
Associate III

After setting configuration registers in HAL_DMA_Start_IT, DMA fails to fire back interrupt, HAL_DMA_IRQHandler(). The TransferComplete call back routine is not called but only once after reset since HAL_DMA_IRQHandler() is called only once after initialization. Flags CC1DE and CC1IE are set after initialization and never change there after. I am trying to read a parallel ADC through GPIO using DMA with interrupt and timer input capture. I am using STM32L496ZG ucontroller and used CUBEMX to generate code.

Also, I am using Timer2 with input capture mode to request DMA transfer. And using MCO to generate 2 MHz to feed to PA0 for timer2 ch1.

I searched the forum and checked almost everything. I used latest  CUBEMX 6.11.1 version.

Your help is greatly appreciated.
Thanks

Here is my initzn part;

 

 

 

 HAL_Init();
  /* Configure the system clock */
  SystemClock_Config();

  /* Initialize all configured peripherals */
  MX_DMA_Init();
  MX_GPIO_Init();
  MX_TIM2_Init();
  MX_USART2_UART_Init();
	if(DWT_Delay_Init())
	HAL_UART_Transmit(&huart2, (uint8_t *)"\r\nClkTick started", 17, HAL_MAX_DELAY);
	else
	HAL_UART_Transmit(&huart2, (uint8_t *)"\r\nClkTicks fail to start", 4, HAL_MAX_DELAY);

  /* USER CODE BEGIN 2 */
  if (HAL_DMA_Start_IT(htim2.hdma[TIM_DMA_ID_CC1], &GPIOE->IDR, (uint32_t)&aDST_Buffer, BUFFER_SIZE) != HAL_OK)
  {
    /* Transfer Error */
    Error_Handler();
  }

  // Attach DMA callback functions
  htim2.hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = HalfTransferComplete;
  htim2.hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TransferComplete;
  htim2.hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TransferError;

  // Enable timer to trigger DMA transfer - CC1DE bit
  __HAL_TIM_ENABLE_DMA(&htim2, TIM_DMA_CC1);
  // Enable timer input capture
  HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  }

 

 

Klassic_0-1718361144991.png           DMA Req setting: >Mode: Normal. 

 

 

 

And this is the data transfer callback routines:

 

 

 

static void HalfTransferComplete(DMA_HandleTypeDef *hdma_tim2_ch1) {
    int position = 0;
    LastITHalfComplete = 1;
    /*Copy the first part of the received buffer */
    for (int i = 0; i < HALF_BUFFER_SIZE; i++) {
        aFull_Buffer[FullDataIndex] = aDST_Buffer[i+position];
        FullDataIndex++;
        //HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_1);
    }
}
static void TransferComplete(DMA_HandleTypeDef *hdma_tim2_ch1)
{
    int position = HALF_BUFFER_SIZE;
    LastITHalfComplete = 0;

    /* Copy the second part of the received buffer */
    for (int i = 0; i < HALF_BUFFER_SIZE; i++) {
    aFull_Buffer[FullDataIndex] = aDST_Buffer[i+position];
        FullDataIndex++;
        HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0);
    }
    transferComplete = 1;
}

static void TransferError(DMA_HandleTypeDef *hdma_tim2_ch1) {
    HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_14);
}

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
Klassic
Associate III

Seems like HAL libraries have still loop holes to be fixed. Jan, you are right.

I used LL library for Timer1 along with DMA and it worked. I can see the change in GPIO inputs during debug.

Klassic_0-1725030496578.png

Thanks for supporting me.

 

View solution in original post

15 REPLIES 15
SofLit
ST Employee

Hello,

As you need to transfer data from GPIO IDR to a memory, how did you configure the DMA? Peripheral to Memory? If yes this that's not the correct config.

You need to consider the GPIO register as a memory location so you need to configure it as Memory to Memory.

You can also refer to this application note AN4666.

Read also this post: https://community.st.com/t5/stm32-mcus-products/stm32f429-read-from-pin-to-dma/m-p/683278

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.

Thanks SofLit, 

As you know there's no Mem to Mem option available in recent cubeMx. Only Periph to Mem Or Mem to Periph. I read somewhere that Periph to Mem is same as Mem to Mem. plz correct me.

According to AN4666 doc, DMA1Ch5 was selected using Tim2Ch1. And I did the same.

For timer in Inp capture, I am using falling edge to trigger DMA.

 

Thanks

 

Hello,

How?

SofLit_0-1718368740655.png

 

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.

I was checking here.

Klassic_0-1718370760388.png

Ok. But if I did be selecting DMA MEM to MEM directly without timer, then how to connect it to timer pulse trigger? I mean, what condition will trigger a DMA request? Which channel to choose along with DMA2?

 

Thanks 

 

Is the DMA set to Circular? If not, how do you start it again?

JW

Hi jan,

Sorry for late reply. I was working to put changes suggested by SofLit and DMA setting to circular, but could not succeed. DMA is set to normal.

Also, I could not accommodate MEM to MEM DMA change, as I could not connect interrupt trigger by timer with DMA.

  Still struggling to get it work.

Thanks

Klassic
Associate III

Hi  @SofLit

   Tried DMA in MEM to MEM mode and triggered it thru software. And chose DMA2 for it. Still the DMA transfer happens only once during start up.
 Also, the mode is set to Normal instead of circular , since, according to RM, it cannot be set to Circular in Mem to MEM mode.

 

 

1. DMA M2M mode is not triggered by the usual requests from peripherals. Immediately after enabling it performs the number of transfers set in DMA Stream's NDTR, and ends. That's all.

2. Contrary to what @SofLit said above, P2M *is* the correct mode, if you want to trigger individual transfers from the timer. However, in 'F4, only DMA2 can access the AHB bus where GPIO is located, and only TIM1 and TIM8 can trigger DMA2 streams. [EDIT] Sorry, this is irrelevant to this thread, as the 'L496 is used here, I mis-read the STM32 model.[/EDIT]

3. Cube may or may not get into your way when setting up this, as Cube/CubeMX inevitably caters only for a fraction of actions what the hardware allows, whatever Cube's authors deemed "usual", and this sounds to be "not usual". Disclaimer: I don't use Cube.

JW

 

Thats true @waclawek.jan .
After compiling configuration register functions (HAL_DMA_Start_IT() ), the CNDTR is becoming zero as soon as Enable Bit in DMA_CCRx register is set during Mem to Mem transfer mode. After that, no dma transfer takes place.

The compiler never reaches HAL_DMA_IRQHandler routine.

And the program hangs around Default_Handler routine infinitely.

According to @KnarfB , If an IRQ handler is not defined in the code, a default implementation is used in the interrupt vector table, the DefaultHandler.

Can you elaborate this ?
only TIM1 and TIM8 can trigger DMA2 streams.

How to make TIM1 to trigger DMA2 transfer?


Thanks Jan for supportive effort.