Showing results for 
Search instead for 
Did you mean: 

DMA + ADC doesn't work


CubeIDE 1.1.0


Trying to make DMA transfer ADC results.

I'm putting code in main() after MX_..._Init() and before while(1) {}

HAL_ADC_Start_IT(&hadc1); works fine

HAL_DMA_Start_IT(&hdma_memtomem_dma1_channel2, (uint32_t) src, (uint32_t) dest, 40); works fine too


HAL_ADC_Start_DMA(&hadc1, dest, 10) doesn't work as it should

ADC is activated and keeps throwing Overrun_Error

But DMA doesn't transfer anything

static void MX_ADC1_Init(void)
  /* USER CODE BEGIN ADC1_Init 0 */
  /* USER CODE END ADC1_Init 0 */
  ADC_ChannelConfTypeDef sConfig = {0};
  /* USER CODE BEGIN ADC1_Init 1 */
  /* USER CODE END ADC1_Init 1 */
  /** Common config 
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV8;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.DMAContinuousRequests = ENABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.OversamplingMode = ENABLE;
  hadc1.Init.Oversampling.Ratio = ADC_OVERSAMPLING_RATIO_16;
  hadc1.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_NONE;
  hadc1.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
  hadc1.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_CONTINUED_MODE;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  /** Configure Regular Channel 
  sConfig.Channel = ADC_CHANNEL_5;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_2CYCLES_5;
  sConfig.SingleDiff = ADC_DIFFERENTIAL_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  /* USER CODE BEGIN ADC1_Init 2 */
  /* USER CODE END ADC1_Init 2 */
static void MX_DMA_Init(void) 
  /* DMA controller clock enable */
  /* Configure DMA request hdma_memtomem_dma1_channel2 on DMA1_Channel2 */
  hdma_memtomem_dma1_channel2.Instance = DMA1_Channel2;
  hdma_memtomem_dma1_channel2.Init.Request = DMA_REQUEST_MEM2MEM;
  hdma_memtomem_dma1_channel2.Init.Direction = DMA_MEMORY_TO_MEMORY;
  hdma_memtomem_dma1_channel2.Init.PeriphInc = DMA_PINC_ENABLE;
  hdma_memtomem_dma1_channel2.Init.MemInc = DMA_MINC_ENABLE;
  hdma_memtomem_dma1_channel2.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  hdma_memtomem_dma1_channel2.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
  hdma_memtomem_dma1_channel2.Init.Mode = DMA_NORMAL;
  hdma_memtomem_dma1_channel2.Init.Priority = DMA_PRIORITY_LOW;
  if (HAL_DMA_Init(&hdma_memtomem_dma1_channel2) != HAL_OK)
    Error_Handler( );
  /* DMA interrupt init */
  /* DMA1_Channel1_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 15, 0);
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  /* USER CODE BEGIN ADC1_MspInit 0 */
  /* USER CODE END ADC1_MspInit 0 */
    /* Peripheral clock enable */
    /**ADC1 GPIO Configuration    
    PA0     ------> ADC1_IN5
    PA1     ------> ADC1_IN6 
    GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    /* ADC1 DMA Init */
    /* ADC1 Init */
    hdma_adc1.Instance = DMA1_Channel1;
    hdma_adc1.Init.Request = DMA_REQUEST_ADC1;
    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_NORMAL;
    hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;
    if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
  /* USER CODE BEGIN ADC1_MspInit 1 */
  /* USER CODE END ADC1_MspInit 1 */

I've tried this confuguration on PNUCLEO-WB55 Dongle in far more complex code and it worked. Now I'm using custom board and just main() body. But I think the board should not matter as DMA is totally internal thing


Do you do the swap of the init manually in the program or do you do it in stmcubemx in the Advanced Settings of the Project manager?

@PDeff.1​ Yes, if you change it in code it will become wrong again when regenerating code. Fixed it permanently by this:

Opened *.ioc file in text editor and rearranged the 'ProjectManager.functionlistsort' to correct order.

Just change the rank of the function in the project manager to permanantly affect the project ioc file after rebuilt. No need to manually edit the file


Hi @PDeff.1​ & @EGoep​ ,

In order to permanently fix the issue while regenerating code, you can refer to the post MX_DMA_Init order in the main.c file generated by STM32CubeMX, How to fix?


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 for the tip, this bug is also present in stm32wb and stm32f2xx packages that i know of

we dont need to firmware by ourselves, lets talk

Dear @eg7963​ & @Javier Muñoz​ ,

A pinned post is published some time ago under STM32CubeMX topic in order to describe the permanent solution for this regression issue.

Please have a look to MX_DMA_Init order in the main.c file generated by STM32CubeMX, How to fix?.


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.