cancel
Showing results for 
Search instead for 
Did you mean: 

ADC1 + ADC5 with DMA and HRTIMER trigger dont work together on STM32G474

KoRba88
Associate III

Hi

I've configured two ADC 1 and ADC5 in independend mode with DMA and triggered by master compare from HRTIMER.

I have two problems

First. When I have started two ADCs by HAL_ADC_Start_DMA one by one

my code freeze on debug after this, but when I set the one GPIO to toggle in HAL_ADC_ConvCpltCallback I see that converters are working

even they dont work when I use two diffrent compare registers in HRTIMER with two diffrent values to trigger them out of phase

With one ADC at once code works perfectly and I can debug code normally

Second issue is that i see that GPIO toggle (BSRR used) in HAL_ADC_ConvCpltCallback is not in sync with HRTIMER edges and it varies from cycle to cycle. (blue is PWM from HRTIMER, yellow is GPIO toggle after ADC callback)

0693W000001sTc6QAE.png

10 REPLIES 10
TDK
Guru

It looks like the period between triggers is around a little under 5us. So you're generating the HAL_ADC_ConvCpltCallback for each conversion at a rate of 200kHz. It's possible the CPU just can't keep up.

Slow the triggers down by a factor of 10 and try again.

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

But I need to sample in this range of frequencies.

Im building solar microinverter, two stage DCDC LLC 70-240 khz type and DCAC 50khz.

I have

PV current on ADC1 and PV voltage on ADC5

Grid voltage on ADC 2 and Grid current on ADC3

MPPT and grid synchronisation PLL algorithm demand synchrononous sampling of the ADC1 & ADC5 and ADC2 & ADC3

Since DMA handle sampling at the same time this is not a problem. Only how to get this data from DMA without CPU overload and since getting sampled data timming is not critical I think it shoud be possible. Anybody have Idea how to achieve this ?

Have you slowed down the timers as TDK said?

JW

I'm not saying the CPU isn't able to achieve what you want. I'm suggesting lowering the frequency temporarily (1) to rule out the possibility that the interrupt routine is completely occupying the cpu and (2) to provide more information on when HAL_ADC_ConvCpltCallback gets called in relation to when it's triggered.

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

Yes At 10khz even four ADCs can work simultaneously.

I have created this code to measure lag between ADC1 and ADC2 callback (Gpio toggle in ADC1 and ADC2). The lag is 2us = 500Khz so 240khz shoudnt be a problem but I have measured that approx 150khz is max when callbacks are not overlaping.

I can set for the LLC stage the postscaler to the ADC to lower the ADC sampling but it not solve the whole problem beacuse ADC from LLC Timer (since LLC stage is frequency variable) could overlap with DCAC (50khz fixed switching) stage timer i.e when LLC=100, 150, 200 khz and so on.

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
 
{
 
	if(hadc->Instance == ADC1){
 
		//pinADC1_TABLE = &ADC1_TABLE[0];
 
		GPIOF->BSRR = (1<<4);
		GPIOF->BRR = (1<<4);
	}
 
	if(hadc->Instance == ADC2){
 
		//pinADC2_TABLE = &ADC2_TABLE[0];
 
		GPIOF->BSRR = (1<<3);
		GPIOF->BRR = (1<<3);
	}
 
	if(hadc->Instance == ADC3){
 
		//pinADC3_TABLE = &ADC3_TABLE[0];
	}
 
	if(hadc->Instance == ADC5){
 
		//pinADC5_TABLE = &ADC5_TABLE[0];
	}
 
}

That IMO doesn't tell you, what's the duration of the ISR.

JW

Ofcourse but insteed of this Im thinking about leaving only one ISR, i.e from DMA from ADC2orADC3 with fixed DCAC 50khz timer, so I will get notification when ADC2&ADC3 data avaliable (since PLL grid synchro is time critical and since ADC2&ADC3 data shoud arrive at the same time), and for the ADC1&ADC5 (which I use only for MPPT when the speed is not critical) i will be polling the buffer and only checking if the corresponding DMA chanell is not actualy writing the data.

But Im not sure if the CubeMX allow to use ADC+DMA without interrups ?

>But Im not sure if the CubeMX allow to use

Then don't use CubeMX.

Cube's inefficient code is probably a factor making your ISR slower than necessary, anyway.

JW

So I do. I started with removing HAL DMA IRQ call handler and checking the latency/frequency in the DMAx_Channelx_IRQHandlers

First im observing that i.e DMA1_Channel1_IRQHandler is entering every 170ns ! Why so frequent? I checked the all interrupt cases (half compete, full transfer complete and transfer error) and nothing is called so frequent. There is no transfer error, and transfer complete are ocour normally with ADC timer trigger frequency.

void DMA1_Channel1_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Channel1_IRQn 0 */
	
	  if (DMA1->ISR & DMA_ISR_TCIF1)
	  {
	  DMA1->IFCR |= DMA_IFCR_CTCIF1;
	  GPIOF->BSRR = (1<<4);
	  GPIOF->BRR = (1<<4);
	  }
 
	  if (DMA1->ISR & DMA_ISR_HTIF1)
	  {
	  DMA1->IFCR |= DMA_IFCR_CHTIF1;
	  GPIOF->BSRR = (1<<3);
	  GPIOF->BRR = (1<<3);
	  }
	  
	  if (DMA1->ISR & DMA_ISR_TEIF1)
	  {
	  DMA1->IFCR |= DMA_IFCR_CTEIF1;
	  GPIOF->BSRR = (1<<2);
	  GPIOF->BRR = (1<<2);
	  }
 
  /* USER CODE END DMA1_Channel1_IRQn 0 */
 
  /* USER CODE BEGIN DMA1_Channel1_IRQn 1 */
 
  /* USER CODE END DMA1_Channel1_IRQn 1 */
}