cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7A3 STM32H7A3ZIT6Q DMA Not starting

Marius CO
Associate III

The code works fine on STM32G474 and I can get 1Msampe/second.

I redid the same project on STM32H7A3ZIT6Q with the changes indicated

https://community.st.com/s/article/FAQ-DMA-is-not-working-on-STM32H7-devices

I went to the option having a dma section. The link above linker is different. Mine is down below.

It does not start. I d not get the callbacks.

Then I used this project

https://github.com/moggiozzi/stm32h7_adc_dma

Is the same I have no ADC DMA callbacks called.

The DMA1_Stream0_IRQHandler is not called

The ADC_IRQHandler is called and fails here

if (hadc->Init.Overrun == ADC_OVR_DATA_PRESERVED)
    {
      overrun_error = 1UL;
    }

 Tweaking the

sConfig.SamplingTime = ADC_SAMPLETIME_64CYCLES_5; //ADC_SAMPLETIME_1CYCLE_5; up to 65C5 did not help.

Thank you

my ld file looks like:
 
MEMORY
{
  ITCMRAM (xrw)  : ORIGIN = 0x00000000, LENGTH = 64K
  FLASH (rx)     : ORIGIN = 0x08000000, LENGTH = 2048K
  DTCMRAM1 (xrw) : ORIGIN = 0x20000000, LENGTH = 64K
  DTCMRAM2 (xrw) : ORIGIN = 0x20010000, LENGTH = 64K
  RAM (xrw)      : ORIGIN = 0x24000000, LENGTH = 1024K
  RAM_CD (xrw)   : ORIGIN = 0x30000000, LENGTH = 128K
  RAM_SRD (xrw)  : ORIGIN = 0x38000000, LENGTH = 32K
}
...
  .data :
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */
    *(.RamFunc)        /* .RamFunc sections */
    *(.RamFunc*)       /* .RamFunc* sections */
 
    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */
  } >RAM AT> FLASH
 
	/* dma buffer */
	 .ram_d1 ORIGIN(DTCMRAM1) (NOLOAD):
	  {
	    *(.adc_dma_buf)
	  } >DTCMRAM1 
 

Then in my main I have

//////////////////////////////////////////////////////////
#define ADC_BUF_SIZE 	((1024 + 0x1f) & ~0x1f)
// adc_buf[ADC_BUF_SIZE];
static __attribute__((section(".adc_dma_buf"))) \
		__attribute__((aligned(0x20)))  \
		uint32_t adc_buf[ADC_BUF_SIZE];
 
//////////////////////////////////////////////////////////
/* omiytted for clarity */
 
////////////////////////////////////////////////////////// the callbacks
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc)
{
	Half=1;
}
 
// Called when buffer is completely filled
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
	Half=2;
}
 
 
////////////////////////////////////////////////// then main
int main(void)
{
  /* USER CODE BEGIN 1 */
	int Togle = 0;
	int Count = 0;
	int ret = 0;
	uint32_t tnow;
 
  /* USER CODE END 1 */
 
  /* Enable I-Cache---------------------------------------------------------*/
  SCB_EnableICache();
 
 
  /* Enable D-Cache---------------------------------------------------------*/
  SCB_EnableDCache();
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
	//__HAL_RCC_DMAMUX1_CLK_ENABLE(); // mco from other example
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  MX_UART5_Init();
  /* USER CODE BEGIN 2 */
	printf("Starting AD\r\n");
	memset(&adc_buf[0], 0xff, sizeof(adc_buf));
	SCB_InvalidateDCache_by_Addr((uint32_t*)&adc_buf[0], sizeof(adc_buf));
 
	HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buf, ADC_BUF_SIZE);
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	while (1)
	{
		if(Half==1)
		{
			Half=0;
		}
		else if(Half==2)
		{
			Half=0;
			Bytes += (ADC_BUF_SIZE);
		}
		tnow = HAL_GetTick();
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
		if(tnow-Now>1000)
		{
			char rec[1];
			Now=tnow;
 
			if(Count++%3==0)
				HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, Togle=!Togle);
			rec[0]=0;
			if(HAL_OK==HAL_UART_Receive(&huart5,rec,sizeof(rec),1000))
			{
				if(atoi(rec)!=0)
				{
					HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, 1);
				}
				else
				{
					HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, 0);
				}
			}
			printf("PIN=%s,USB=%d: %d=SPS at[0]=%d  at[1023]=%d  \r\n",
					rec,ret, Bytes,
					adc_buf[0], adc_buf[ADC_BUF_SIZE-2]);
			Bytes=0;
		}
	}
  /* USER CODE END 3 */
}
 
/////////////////////
 
 
 

Then the ADC and DMA settings

static void MX_ADC1_Init(void)
{
 
  /* USER CODE BEGIN ADC1_Init 0 */
 
  /* USER CODE END ADC1_Init 0 */
 
  ADC_MultiModeTypeDef multimode = {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_DIV1;
  hadc1.Init.Resolution = ADC_RESOLUTION_16B;
  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.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
  hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
  hadc1.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
  hadc1.Init.OversamplingMode = DISABLE;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }
 
  /** Configure the ADC multi-mode
  */
  multimode.Mode = ADC_MODE_INDEPENDENT;
  if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
  {
    Error_Handler();
  }
 
  /** Configure Regular Channel
  */
  sConfig.Channel = ADC_CHANNEL_2;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  sConfig.OffsetSignedSaturation = DISABLE;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */
 
  /* USER CODE END ADC1_Init 2 */
 
}
 
static void MX_DMA_Init(void)
{
 
  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();
 
  /* DMA interrupt init */
  /* DMA1_Stream0_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
 
}
 
void HAL_MspInit(void)
{
  /* USER CODE BEGIN MspInit 0 */
 
  /* USER CODE END MspInit 0 */
 
  __HAL_RCC_SYSCFG_CLK_ENABLE();
 
  /* System interrupt init*/
 
  /* USER CODE BEGIN MspInit 1 */
 
  /* USER CODE END MspInit 1 */
}
 
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
  if(hadc->Instance==ADC1)
  {
  /* USER CODE BEGIN ADC1_MspInit 0 */
 
  /* USER CODE END ADC1_MspInit 0 */
 
  /** Initializes the peripherals clock
  */
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_ADC;
    PeriphClkInitStruct.PLL2.PLL2M = 32;
    PeriphClkInitStruct.PLL2.PLL2N = 129;
    PeriphClkInitStruct.PLL2.PLL2P = 2;
    PeriphClkInitStruct.PLL2.PLL2Q = 2;
    PeriphClkInitStruct.PLL2.PLL2R = 2;
    PeriphClkInitStruct.PLL2.PLL2RGE = RCC_PLL2VCIRANGE_1;
    PeriphClkInitStruct.PLL2.PLL2VCOSEL = RCC_PLL2VCOWIDE;
    PeriphClkInitStruct.PLL2.PLL2FRACN = 0;
    PeriphClkInitStruct.AdcClockSelection = RCC_ADCCLKSOURCE_PLL2;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    {
      Error_Handler();
    }
 
    /* Peripheral clock enable */
    __HAL_RCC_ADC12_CLK_ENABLE();
 
    __HAL_RCC_GPIOF_CLK_ENABLE();
    /**ADC1 GPIO Configuration
    PF11     ------> ADC1_INP2
    */
    GPIO_InitStruct.Pin = GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
 
    /* ADC1 DMA Init */
    /* ADC1 Init */
    hdma_adc1.Instance = DMA1_Stream0;
    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_WORD;
    hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_adc1.Init.Mode = DMA_NORMAL;
    hdma_adc1.Init.Priority = DMA_PRIORITY_LOW;
    hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
    {
      Error_Handler();
    }
 
    __HAL_LINKDMA(hadc,DMA_Handle,hdma_adc1);
 
    /* ADC1 interrupt Init */
    HAL_NVIC_SetPriority(ADC_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(ADC_IRQn);
  /* USER CODE BEGIN ADC1_MspInit 1 */
  /* USER CODE END ADC1_MspInit 1 */
  }
 
}
 

1 REPLY 1
Marius CO
Associate III

I think is something wrong with the adc buffer.

Either on stack either on __attribute__((section(".adc_dma_buf")))

did not work.

Anyone can help where to place it in ld file ?

If I change the DMA buffer to heap and disable

// SCB_EnableICache();

// SCB_EnableDCache();

adc_buf = (uint32_t*)malloc(4096*sizeof(uint32_t));

Works: I get 2 Mbps with ADC_CLOCK_ASYNC_DIV4,

Down is 1 second report printing in the loop. (/ second)

SPS are samples/second, one sample is 32 bit long.

GOTS are halfs+wholes completion calls.

math is good 977(callbacks) * 4096(buffer) /2(2 callbacks half and whole)=2000896(SPS)

The 64's/4096 values are 1 ADC reads from a gpio I toggle at index 0,1 Half/2+/-1 and

end-1 and end to check if the buffer is valid (just debug).

PIN=,USB=0: SPS=2000896 SND=1 GOTS=977   63 63    64  64  | 63 63   63 63
PIN=,USB=0: SPS=1998848 SND=1 GOTS=976   65 64    64  64  | 64 64   64 64
PIN=,USB=0: SPS=2000896 SND=1 GOTS=977   4095 4095    4095  4095  | 4095 4095   4095 4095
PIN=,USB=0: SPS=2000896 SND=1 GOTS=977   4095 4095    4095  4095  | 4095 4095   4095 4095