cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H743 nucleo board, using the 3 ADC at once on polling mode; doesn´t work!

mst0mst
Associate II

Greetings,

I am working on a project where a STM32H743 nucleo board and use of 16 ADC inputs are involved.

Obviously, these analog inputs are used once a time; read the value via polling mechanism and configure the next input... configure the ADC channel, start the ADC, read the value via polling and configure the next input... 16 times each 1 ms, as a Real-Time behaviour.

The problem I found is that I can´t start any of the 3 ADCs, it stuck at this line at

stm32h7xx_hal_adc.h (I think that I configure the clocks or another sort of things incorrectly) :

while(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_RDY) == 0UL)

This line is in the function:

HAL_StatusTypeDef ADC_Enable(ADC_HandleTypeDef *hadc)

That is being called by:

HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef *hadc)

Thanks in advance for the help, the source code is provided below

My function files are:

MAIN.C

#include "main.h"
#include "hwdrvlib.h" 
#include "test.h"
 
volatile unsigned int systick_count = 0;
static volatile int systick_active = 1;
 
/** 
 * @brief The application entry point.
 * @retval int
 */
int main(void)
{
#ifdef CPU_CACHE
 /* Enable I-Cache---------------------------------------------------------*/
 SCB_EnableICache();
 /* Enable D-Cache---------------------------------------------------------*/
 SCB_EnableDCache();
#endif 
 /* MCU Configuration--------------------------------------------------------*/
 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 HAL_Init(); 
 /* Configure the system clock */ 
 SystemClock_Config(); //Located on hwdrvlid.h y hwdrvlib.c
 /* SysTick is 0 at start */
 
 tick = (uint8_t)0;
 /* Initialize */
 
ADC_Init(); /* Initialize ADC peripherals and GPIO ADC inputs as analog */
                  //Located on hwdrvlid.h y hwdrvlib.c
 
 /* Sample Time: 0.001 */
 while (...) {  /* Some comparison deleted for readability */
   RT_Task(); //Located on Function file
 }                                   //End of while 
}   

hwdrvlib.c (The file that contains configuration functions)

ADC_HandleTypeDef hadc1 __attribute__((section(".ramd2")));
ADC_HandleTypeDef hadc2 __attribute__((section(".ramd2")));
ADC_HandleTypeDef hadc3 __attribute__((section(".ramd2")));
void ADC_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct; 
  /* ADC Clock Enable */
  __HAL_RCC_ADC12_CLK_ENABLE();
  __HAL_RCC_ADC3_CLK_ENABLE(); 
  /* ADC Periph interface clock configuration */
  __HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_CLKP);//or PLL2 
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOF_CLK_ENABLE();
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
 
  /* ADCs GPIO as analog input */
  /* System ADC Input number 1  PF9 */
  /*##-2- Configure peripheral GPIO ##########################################*/
  /* ADC Channel GPIO pin configuration */
  GPIO_InitStruct.Pin = GPIO_PIN_9;
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
 
 /* Initialization of 16 analog inputs, hidden for readability */
 
  /* System ADC Input number 16  PA3 */
  /*##-2- Configure peripheral GPIO ##########################################*/
  /* ADC Channel GPIO pin configuration */
  GPIO_InitStruct.Pin = GPIO_PIN_3;
  GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
  /* ADC1 Config */
  hadc1.Instance = ADC1;
  if (HAL_ADC_DeInit(&hadc1) != HAL_OK) {
    /* ADC1 de-initialization Error */
    Error_Handler();
  }
 
  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 = DISABLE;
  hadc1.Init.NbrOfConversion = 1;      /* Vector Support */
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.NbrOfDiscConversion = 1;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
  hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
  hadc1.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
  hadc1.Init.OversamplingMode = DISABLE;
  if (HAL_ADC_Init(&hadc1) != HAL_OK) {
    Error_Handler();
  } 
 /* The same for ADC2 and ADC3 using hadc2 and hadc3 */
}
 
 
void ADC_Input_Select(ADC_HandleTypeDef *hadc,uint32_t Channel)
{
  static ADC_ChannelConfTypeDef sConfig = { 0 };
 
  /* Configure Regular Channel */
  sConfig.Channel = Channel;
  sConfig.Rank = ADC_REGULAR_RANK_1;
  sConfig.SamplingTime = ADC_SAMPLETIME_387CYCLES_5;
  sConfig.SingleDiff = ADC_SINGLE_ENDED;
  sConfig.OffsetNumber = ADC_OFFSET_NONE;
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(hadc, &sConfig) != HAL_OK) {
    Error_Handler();
  }
}

FUNCTION FILE (The function that contains the function to be executed, in order to read analog input data)

void RT_Task(void)
{
  /* ADC3-IN2  PF9 */
  ADC_Input_Select(&hadc3,ADC_CHANNEL_2);
  HAL_ADC_Start(&hadc3);
  if (HAL_ADC_PollForConversion(&hadc3,1000) != HAL_OK ) {
    /* ADC conversion fails */
    //Escribir aqui la salida de error
  } else {
    test2_B.VectorConcatenate[1] = HAL_ADC_GetValue(&hadc3) + 0;
  }
 
/* More ADC reading hidden for readability */
}

1 ACCEPTED SOLUTION

Accepted Solutions
mst0mst
Associate II

I found the solution.

The MCU has not finished to execute the Initialization() function when the first SysTick IRQ happens.

The Real-Time task is called inside the SysTick IRQ context, and the ADC is accesed without being initialized; due to this the execution stucks at this point.

I placed an initialization flag, that avoids execute the Real-Time task if the initialization function is not ended.

Also I need to call ADC boost enable function inside ADC_Init(), due to the high configured frequency for each ADC.

View solution in original post

2 REPLIES 2
mst0mst
Associate II

The clk configuration function:

/**
 * @brief System Clock Configuration
 * @retval None
 *
 *
 *
 * Configure 480 MHz CPU Clock, 240 MHz APB1 and APB2 Clock
 *                                          flash latency 4
 */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = { 0 };
 
  RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };
 
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = { 0 };
 
  /** Supply configuration update enable
   */
  HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
 
  /* The voltage scaling allows optimizing the power consumption when the device is
     clocked below the maximum system frequency, to update the voltage scaling value
     regarding system frequency refer to product datasheet.  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  while (!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {
  }
 
  __HAL_RCC_SYSCFG_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);
  while (!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {
  }
 
  __HAL_RCC_PLL_PLLSOURCE_CONFIG(RCC_PLLSOURCE_HSI);//HSE
 
  /* a 480 MHz config */
 
  /** Configure the main internal regulator output voltage
   */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);
  while (!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {
  }
 
  /** Initializes the CPU, AHB and APB busses clocks
   */
#ifdef USB_VCP_SETUP
 
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48 |
    RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 60;
  RCC_OscInitStruct.PLL.PLLP = 2;
  RCC_OscInitStruct.PLL.PLLQ = 2;
  RCC_OscInitStruct.PLL.PLLR = 2;
  RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
  RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
  RCC_OscInitStruct.PLL.PLLFRACN = 0;
 
#else
 
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 60;
  RCC_OscInitStruct.PLL.PLLP = 2;
  RCC_OscInitStruct.PLL.PLLQ = 2;
  RCC_OscInitStruct.PLL.PLLR = 2;
  RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
  RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
  RCC_OscInitStruct.PLL.PLLFRACN = 0;
 
#endif
 
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
    Error_Handler();
  }
 
  /* End of old 480 MHz config */
 
  /** Initializes the CPU, AHB and APB busses clocks
   */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
    |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
    |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
  RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) {
    Error_Handler();
  }
 
  /* USB CLK Initialization if needed */
#ifdef USB_VCP_SETUP
 
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;
  PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;//PLL
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) {
    Error_Handler();
  }
 
  /** Enable USB Voltage detector
   */
  HAL_PWREx_EnableUSBVoltageDetector();
 
#endif
    
}

mst0mst
Associate II

I found the solution.

The MCU has not finished to execute the Initialization() function when the first SysTick IRQ happens.

The Real-Time task is called inside the SysTick IRQ context, and the ADC is accesed without being initialized; due to this the execution stucks at this point.

I placed an initialization flag, that avoids execute the Real-Time task if the initialization function is not ended.

Also I need to call ADC boost enable function inside ADC_Init(), due to the high configured frequency for each ADC.