Skip to main content
Associate III
January 3, 2026
Question

NUCLEO H7S3L8 ADC continous conv mode + DMA; DMA stays idle

  • January 3, 2026
  • 0 replies
  • 273 views

Hello,

I am looking for help debugging an issue with both ADCs running in continuous conversion mode with multiple channels, using DMA on an STM32H7 device.

Hardware / Tools

  • Board: NUCLEO-H7S3L8

  • MCU family: STM32H7RS

  • Peripherals: ADC1 and ADC2

  • Mode: Continuous conversion, multi-channel (scan mode)

  • Data transfer: DMA

Configuration Overview

  • Both ADCs are configured in continuous conversion mode

  • Each ADC scans multiple channels

  • DMA is used to transfer conversion results into memory buffers

  • DMA buffers are statically allocated and placed in DMA-accessible memory

  • D-Cache is enabled on the H7

Problem Description
Both ADCs are running and DMA transfers are occurring, but the sampled data in the buffer is always 0

In the SFR it shows that the ADC is working, but the DMA is idle/not set up correctly. Also the DMA buffers are in a non-cacheble region protercted by my MPU.

static void MPU_Config(void)
{
 MPU_Region_InitTypeDef MPU_InitStruct = {0};

 /* Disables the MPU */
 HAL_MPU_Disable();

 /* Disables all MPU regions */
 for(uint8_t i=0; i<__MPU_REGIONCOUNT; i++)
 {
 HAL_MPU_DisableRegion(i);
 }

 /** Initializes and configures the Region and the memory to be protected
 */
 MPU_InitStruct.Enable = MPU_REGION_ENABLE;
 MPU_InitStruct.Number = MPU_REGION_NUMBER0;
 MPU_InitStruct.BaseAddress = 0x0;
 MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
 MPU_InitStruct.SubRegionDisable = 0x87;
 MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
 MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
 MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
 MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
 MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
 MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;

 HAL_MPU_ConfigRegion(&MPU_InitStruct);

 /** Initializes and configures the Region and the memory to be protected
 */
 MPU_InitStruct.Enable = MPU_REGION_ENABLE;
 MPU_InitStruct.Number = MPU_REGION_NUMBER1;
 MPU_InitStruct.BaseAddress = 0x30000000;
 MPU_InitStruct.Size = MPU_REGION_SIZE_32KB;
 MPU_InitStruct.SubRegionDisable = 0x0;
 MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
 MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;

 MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; /* TEX = 000 */
 MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; /* C = 0 */
 MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; /* B = 0 */
 MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE; /* S = 1 */

 HAL_MPU_ConfigRegion(&MPU_InitStruct);

 /** Initializes and configures the Region and the memory to be protected
 */
 MPU_InitStruct.Number = MPU_REGION_NUMBER2;
 MPU_InitStruct.BaseAddress = 0x70000000;
 MPU_InitStruct.Size = MPU_REGION_SIZE_256MB;
 MPU_InitStruct.AccessPermission = MPU_REGION_PRIV_RO;
 MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
 MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;

 HAL_MPU_ConfigRegion(&MPU_InitStruct);
 /* Enables the MPU */
 HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

The DMA buffers themselves are located correctly, and there are no hard faults or DMA errors reported. The issue appears to be related to the interaction between:

  • Continuous conversion + scan mode

  • DMA buffer handling

What I Have Checked / Tried

  • Verified that DMA buffers are not located in Flash

  • Confirmed DMA streams are enabled and running

  • Checked ADC channel ranks and scan configuration

  • Ensured continuous mode is enabled only where intended

  • Tested with different buffer sizes

  • Reviewed reference manual sections on ADC + DMA operation

  • Reviewed cache configuration (D-Cache enabled)

Despite this, the DMA is misbehaiving, can someone help?

Best regards.

PS: I applied additionally the ADC config as well as 2 SFRs. Also this is how i start the DMA+ADC:

if (HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adc1_dma_buf, 7) != HAL_OK)
tb_fatal();

if (HAL_ADC_Start_DMA(&hadc2, (uint32_t *)adc2_dma_buf, 7) != HAL_OK)
tb_fatal();