STM32 ADC DMA Multi-Channel Readin using FreeRTOS and Timer 2

Hey guys!
I’m trying to get an ADC reeading of 3 channels to work, i think i set up everything correctly but when i read my buffer, the data does not seem correct, not it works according to the Timer 2 timing of 1 second.

ADC config:
12 bits
Scan conversion enabled
Continuous conversion enabled
DMA Continuous requests enabled
Number of conversions = 3
The ranks are correct with cycles of 15
External trigger conversion source is set to Timer 2 Trigger Out Event

DMA:
ADC1
DMA2 Stream0
Peripheral to Memory
Low
Half Word
Circular

NVIC:
DMA2 stream0 global interrupt enabled by default

Timer:
64MHz cpu clock
PSC = 64k → 1kHz
ARR = 1k → 1s count

This is my Task 1:

void StartTask1(void const * argument)
{
  /* USER CODE BEGIN StartTask1 */
	HAL_ADC_Start_DMA(&hadc1, (uint32_t*) adcBuffer, ADC_CHANNEL_LENGTH);
	HAL_TIM_Base_Start(&htim2);
	//HAL_TIM_Base_Start_DMA(&htim8, (uint32_t*) adcBuffer, ADC_CHANNEL_LENGTH);

  /* Infinite loop */
  for(;;)
  {
	  HAL_GPIO_TogglePin(green_led_GPIO_Port, green_led_Pin);
	  // Check if DMA buffer is ready for processing
    osDelay(500);
  }
  /* USER CODE END StartTask1 */
}

The LED is just to test if the freeRTOS is working with the DMA (it may stop scheduling).
This is my buffer with a lenght of 100:

volatile uint16_t adcBuffer[ADC_CHANNEL_LENGTH]; 

And this is my CpltCallback:

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{

	// Custom logic for ADC1 conversion completion
	adcThermistorValue = adcBuffer[0];
	adcAccelXValue = adcBuffer[1];
	adcAccelYValue = adcBuffer[2];
	dmaDataReadyFlag = 1;  // Set a flag to indicate that data is ready

}

Any ideas why this is not reading correctly, nor counting time correctly and reading with 1s intervals.

Are you able to get it working without FreeRTOS i.e. in a bare metal environment. If no, then it is likely not related to FreeRTOS and you should reach out to ST.

As aggarg says, the configuration of the ADC/DMA will have nothing to do with FreeRTOS, except how to signal the “done” event, so if the issue isn’t there, it is a STM issue, not a FreeRTOS one.

I resolved the issue (on a baremetal implementation), basically to use the Timer as an Event source, you need to disable the Continuous Conversion on the ADC. It worked for me on my NUCLEO-F767ZI.
But thanks for the response anyway.

Glad that you resolved it. Does it work with FreeRTOS also or are you still facing problem with that?

1 Like

Yes, i just did the same implementation there and it works. Probably i will have problems if i have faster readings with the freeRTOS scheduler, but i can just increase the size of the ADC DMA buffer.
As i said before, if you have Continuous connversion mode it will operate at the clock prescaler frequency. Deactivate that and it will read when the timer generates an event.

Thank you for sharing your solution!