cancel
Showing results for 
Search instead for 
Did you mean: 

Issue with HAL_Init, my board, or my code?

JayDev
Senior II

Hello! I'm using an STM32L4R5ZI board and was running some low power code to put the board in Standby and the board was getting stuck in the clock init section. I would restart the board, it would run HAL_Init (where I assume it would reset the state of the board for reprogramming) and it would appear to still be in low power mode (sitting at around 600 uA when trying to run the clock section rather than the expected 10+ mA) and get stuck (sitting around 2.3 mA). Unplugging the USB and plugging it back in would put it in the same state (stuck at 2.3 mA).

I assume it's down to 1 of 3 things:

1) There's something wrong with my code and I put it in a weird state it doesn't know how to get out of

2) My expectations are wrong and this behaviour could be expected, based on my code

3) There's something wrong with my board

4) HAL_Init is not performing as expected (though I'm not sure why this would be)

I am running STM32CubeIde V1.8.0 and I'm running the L4 framework V1.17.2. I'm kind of at a loss to know how to proceed from here because I don't really know what's wrong at this point. Any help you can give me would be appreciated!

Below is my code:

Main:

int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* 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_Delay(5000);  // Added in case it's putting it in sleep mode when trying to program
 
/* I did try this code at one point, not sure if any of this could've broken something */
//	/* Enable Power Clock */
//	__HAL_RCC_PWR_CLK_ENABLE();
//
//	/* Enable backup domain for LSE/RTC control */
//	HAL_PWR_EnableBkUpAccess();
//
//	/* Swith off LSE clock (to make sure RTC is off) */
//	LSE_OFF_Config();
//
//	/* Configure the main internal regulator output voltage (Range1 by default)*/
//	HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
//
//	/* Disable Power Clock */
//	__HAL_RCC_PWR_CLK_DISABLE();
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_LPUART1_UART_Init();
  MX_USART3_UART_Init();
  MX_USB_OTG_FS_PCD_Init();
  /* USER CODE BEGIN 2 */
 
  buf_len = sprintf(UART_Buffer, "\n\r Start of user code \n\r");
  HAL_UART_Transmit(&hlpuart1, (uint8_t *)UART_Buffer, buf_len, 100);
 
  test_standby(); 			// 0.65 mA -> Down to 0.6 mA after updated clock setting
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

Here's my sleep code:

void test_standby(void)
{
	buf_len = sprintf(UART_Buffer, "\n\r Executing test (STANDBY) \n\rr");
	HAL_UART_Transmit(&hlpuart1, (uint8_t *)UART_Buffer, buf_len, 100);
 
	buf_len = sprintf(UART_Buffer, "Please measure current then use Reset button to select another test \n\r");
	HAL_UART_Transmit(&hlpuart1, (uint8_t *)UART_Buffer, buf_len, 100);
 
	/* Set all GPIO in analog state to reduce power consumption */
	GPIO_AnalogState_Config();
 
	/* Enable Power Clock */
	__HAL_RCC_PWR_CLK_ENABLE();
 
	/* Request to enter STANDBY mode */
	HAL_PWR_EnterSTANDBYMode();
}
 
void GPIO_AnalogState_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
 
  /* Set all GPIO in analog state to reduce power consumption, */
 
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOD_CLK_ENABLE();
    __HAL_RCC_GPIOE_CLK_ENABLE();
    __HAL_RCC_GPIOF_CLK_ENABLE();
    __HAL_RCC_GPIOG_CLK_ENABLE();
    __HAL_RCC_GPIOH_CLK_ENABLE();
 
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Pin = GPIO_PIN_All;
 
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
    HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
 
    __HAL_RCC_GPIOA_CLK_DISABLE();
    __HAL_RCC_GPIOB_CLK_DISABLE();
    __HAL_RCC_GPIOC_CLK_DISABLE();
    __HAL_RCC_GPIOD_CLK_DISABLE();
    __HAL_RCC_GPIOE_CLK_DISABLE();
    __HAL_RCC_GPIOF_CLK_DISABLE();
    __HAL_RCC_GPIOG_CLK_DISABLE();
    __HAL_RCC_GPIOH_CLK_DISABLE();
 
}

Here's the clock code (as well as where it's getting stuck):

void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
 
  /** Configure the main internal regulator output voltage
  */
  if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48|RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 2;
  RCC_OscInitStruct.PLL.PLLN = 30;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 
/* It's getting stuck on this line below */
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {
    Error_Handler();
  }
}

Any idea what might be happening? History tells me I screwed something up somewhere.

4 REPLIES 4

Make sure Error_Handler() does something useful.

I'd recommend using a version that reports file/line as this will allow you to quickly identify the source of the error.

At a minimum you should flag this type of critical failure with an LED, UART output or something better than a while() loop.

Use GPIO check points, or post codes to see progress, and get some detail out of the MCU about the state it finds itself in.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Ok, I think I might've discovered the issue. It's an interesting one and not one I expected. When i was in Standby mode, I was measuring about 650 uA (definitely not as low as I'd like or as advertised but it is also powering a bit of extra circuitry like a level shifter. Not sure if that explains the difference alone, I'll have to take another look).

Anyway, it seems to work just fine with the ammeter in "mA" mode but not in "uA" mode. My guess is the uA range has more resistance and could be causing a larger voltage drop and the Vsupply to the microcontroller (or other circuitry perhaps) has dropped too low to properly initialize the chip.

Thanks for the advice! In my case, it didn't appear to even be getting to the Error Handler, it was lost somewhere else in code (I might still go back and see what was happening for future reference).

Piranha
Chief II

When entering low-power mode, set DBGMCU_CR to zero and disconnect the debugger physically.

There is no point in configuring the GPIOx registers before going into standby or shutdown modes because those will be reset immediately anyway and will not have an impact in those modes.

You can run the MCU in ammeter's mA mode and only switch it to uA mode while the MCU is in standby mode and consumes tiny amount of current.

Yeah, you're are correct that that analog mode doesn't appear to make any difference (which makes sense).

I did confirm the problem was the Vsupply drop. Looks like in uA mode, it was dropping as low as 2.1V (whereas I think it might've dropped to 3.1V in mA mode). So at least that makes sense.

It looks like it was losing connection with the board at the following line in stm32l4_hal_rcc.c (where it was hitting 2.1V):

MODIFY_REG(RCC->CFGR, RCC_CFGR_SW, RCC_ClkInitStruct->SYSCLKSource);

One other thing I ran into that was odd was I'm disconnecting the USB and plugging it back into the computer and when it goes to low power mode, it's now dropping to 500 - 800 nA rather than the 600 uA I had before (which, to be fair, was more in line with what I was expecting to see). If it was in debug mode and that was drawing extra current, that would make sense to me but I was putting it in "run" mode from within STM32CubeIDE.

Any idea what might be happening? Does this mean even "Run" mode is pulling some additional current (or maybe even the level translator that VDD/VDD_MCU is connected to) is enabled when running through CubeIDE?

I'm sure there's probably a good explanation but thought I'd see if you had any insight on this one. Thanks!