cancel
Showing results for 
Search instead for 
Did you mean: 

HAL DMA ADC Interrupt stuck in IRQ Handler

rajpaged
Associate II
Posted on July 18, 2014 at 02:12

I'm having an issue where, if I enable the DMA IRQ, my application gets stuck on one of the error check statements within the HAL_DMA_IRQHandler

I'm trying to run conversions on four ADC1 channels, each going into memory using the DMA, and then repeating the process. Each time the transfer is complete, I want to run some code in the DMA interrupt.

The ADC seems to be converting correctly, and DMA seems to be moving the data where I want in memory.The problem occors when I enable the DMA interrupt using:

HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0);

 

HAL_NVIC_SetPriority(DMA2_Stream4_IRQn, 0, 3);

 

HAL_NVIC_EnableIRQ(DMA2_Stream4_IRQn);

 

If I understand correctly, the correct way of starting the ADC with DMA is using:

HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&rawADC, 4);

 

where hadc1 is my ADC_HandleTypeDef, rawADC is my buffer and 4 is the number of conversions.

Am I correct in that HAL_ADC_ConvCpltCallback() is also the same callback for ADC DMA end of transfer?

This is my ADC and DMA config:------------------------

 

__ADC1_CLK_ENABLE();

 

  

 

GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3;

 

GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;

 

GPIO_InitStruct.Pull = GPIO_NOPULL;

 

HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

 

 

/* Peripheral DMA init*/

 

hdma_adc1.Instance = DMA2_Stream4;

 

hdma_adc1.Init.Channel = DMA_CHANNEL_0;

 

hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;

 

hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;

 

hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;

 

hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;

 

hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;

 

hdma_adc1.Init.Mode = DMA_CIRCULAR;

 

hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;

 

hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

 

HAL_DMA_Init(&hdma_adc1);

 

 

__HAL_LINKDMA(hadc,DMA_Handle,hdma_adc1);

 

 

HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0);

 

HAL_NVIC_SetPriority(ADC_IRQn, 0, 3);

 

HAL_NVIC_EnableIRQ(ADC_IRQn);

 

 

 

__DMA2_CLK_ENABLE();

 

HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0);

 

HAL_NVIC_SetPriority(DMA2_Stream4_IRQn, 0, 3);

 

HAL_NVIC_EnableIRQ(DMA2_Stream4_IRQn); /* Something goes wrong when enable this line */

 

 

 

/* Configure ADC1 */

 

ADC_ChannelConfTypeDef sConfig;

 

 

hadc1.Instance = ADC1;

 

hadc1.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2;

 

hadc1.Init.Resolution = ADC_RESOLUTION12b;

 

hadc1.Init.ScanConvMode = DISABLE;

 

hadc1.Init.ContinuousConvMode = ENABLE;

 

hadc1.Init.DiscontinuousConvMode = DISABLE;

 

hadc1.Init.NbrOfDiscConversion = 1;

 

hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;

 

hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;

 

hadc1.Init.NbrOfConversion = 4;

 

hadc1.Init.DMAContinuousRequests = ENABLE;

 

hadc1.Init.EOCSelection = EOC_SEQ_CONV;

 

HAL_ADC_Init(&hadc1);

 

 

 

/* Configure channel sample order*/

 

sConfig.Channel = ADC_CHANNEL_13;

 

sConfig.Rank = 4;

 

sConfig.SamplingTime = ADCSAMPLES;

 

HAL_ADC_ConfigChannel(&hadc1, &sConfig);

 

 

 

sConfig.Channel = ADC_CHANNEL_10;

 

sConfig.Rank = 1;

 

HAL_ADC_ConfigChannel(&hadc1, &sConfig);

 

 

 

sConfig.Channel = ADC_CHANNEL_11;

 

sConfig.Rank = 2;

 

HAL_ADC_ConfigChannel(&hadc1, &sConfig);

 

 

 

sConfig.Channel = ADC_CHANNEL_12;

 

sConfig.Rank = 3;

 

HAL_ADC_ConfigChannel(&hadc1, &sConfig);

 

 

HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&rawADC, 4);

1 REPLY 1
Posted on September 01, 2014 at 17:30

Hello

I have not the complete overview of your program, but I suspect two main hypothesis:

1. Overhead in IRQhandler

Considering IT occurring after each 4 ADC conversions in your example (IT by DMA end of transfer), you must select sampling time and ADC clock with sufficient duration to not create an overhead situation in IRQHandler.

If constant ADCSAMPLES is set to ADC_SAMPLETIME_3CYCLES, CPU may be saturated by DMA interruptions.

Can you try to set ''sConfig.SamplingTime = ADC_SAMPLETIME_84CYCLES;'' for example ?

2. DMA issueADC1 maybe affected to wrong DMA IRQhandler or DMA stream overtaken by another request.

ADC1 has 2 possible DMA streams:

- DMA2 Channel0 Stream0

- DMA2 Channel0 Stream4

2.1 Can you check that all items referring to DMA are well aligned ?

In your example your correctly use:

- hdma_adc1.Instance = DMA2_Stream4;

- hdma_adc1.Init.Channel = DMA_CHANNEL_0;

- HAL_NVIC_SetPriority(DMA2_Stream4_IRQn, 0, 3);

HAL_NVIC_EnableIRQ(DMA2_Stream4_IRQn);

Therefore, in stm32f4xx_it.c, DMA IRQhandler should be:

void DMA2_Stream4_IRQHandler(void)
{
HAL_DMA_IRQHandler(AdcHandle.DMA_Handle);
}

2.2 Can you set a breakpoint into ''void DMA2_Stream4_IRQHandler(void)'' to check if the program is stuck in looping into this IRQhandler ?

2.3 If the program appears to be stuck at line ''HAL_NVIC_EnableIRQ(DMA2_Stream4_IRQn);'', maybe DMA2_Stream4_IRQn is used by another IP ?

Can you try to replace DMA2 Channel0 Stream4 by DMA2 Channel0 Stream0 ?

About your question ''Am I correct in that HAL_ADC_ConvCpltCallback() is also the same callback for ADC DMA end of transfer?''

Yes, this is correct: function ''HAL_ADC_ConvCpltCallback()'' is used for ADC conversion without DMA (polling or IT) and with DMA.

You can find attached a working example. Hope that may help you.

Best regards

________________

Attachments :

Example_ADC_DMA2Channel0_Stream4_STM32F4-Discovery.zip : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I1Cy&d=%2Fa%2F0X0000000bjs%2Fzm_Vf7LxXsLUYfgva.pgyUHoVvxSBJKrwPhoTaIFgI8&asPdf=false