2025-01-20 12:10 AM
Hello,
I'm working on a low-power application using the STM32L073 microcontroller and aiming to achieve a current consumption of around 3.5 µA in Stop mode. Here are the steps I've followed so far:
Power Connections: I'm powering the microcontroller directly via VDD with a voltage of 3.3V.
Nucleo Board Configuration: I have removed the JP5 connection on my Nucleo-L073 board along with the CN2 jumper connections.
Despite my efforts, the current consumption I'm observing ranges between 260 µA to 280 µA, which is significantly higher than my target.
Here are the crucial parts of the code I've used to measure the current consumption:
#include "main.h"
// Function prototypes
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
void HW_EnterStopMode(void);
void Error_Handler(void); // Function prototype for Error_Handler
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
// Main loop
while (1) {
// Enter Stop mode
HW_EnterStopMode();
}
}
void HW_EnterStopMode(void) {
// Suspend SysTick to prevent waking up from interrupts
HAL_SuspendTick();
// Clear the wake-up flag
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
// Enter Stop mode with low power regulator ON and wait for interrupt
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
// After waking up, reconfigure the system clock
SystemClock_Config();
// Resume SysTick
HAL_ResumeTick();
}
static void MX_GPIO_Init(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
// Enable GPIO clock
__HAL_RCC_GPIOB_CLK_ENABLE();
// Configure GPIO pin for external interrupt (e.g., button)
GPIO_InitStruct.Pin = GPIO_PIN_1; // Change as needed for your setup
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
// Enable and set EXTI line 0 and 1 Interrupt to the lowest priority
HAL_NVIC_SetPriority(EXTI0_1_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(EXTI0_1_IRQn);
}
// Interrupt handler for external interrupt
void EXTI0_1_IRQHandler(void) {
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1); // Clear the interrupt flag
}
void SystemClock_Config(void) {
// Set the system clock to use MSI or HSI at a low frequency (e.g., 100 kHz)
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6; // 100 kHz
RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
Error_Handler(); // Call Error_Handler on failure
}
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) {
Error_Handler(); // Call Error_Handler on failure
}
}
// Error handler function definition
void Error_Handler(void) {
/* USER CODE BEGIN Error_Handler_Debug */
// User can add their own implementation to report the HAL error return state.
__disable_irq(); // Disable all interrupts
while (1) {
// Stay in this loop if an error occurs.
// You can add a mechanism to blink an LED or send a message here.
}
/* USER CODE END Error_Handler_Debug */
}
Am I missing something in my setup or code? Any insights on how to achieve single-digit µA consumption for my application would be greatly appreciated. Thank you!
Hope that helps! Do you want me to assist further on optimizing your code or setup?
2025-01-20 02:01 AM - edited 2025-01-30 05:53 AM
You need to look very carefully at the schematics to identify all possible paths for current leakage.
eg, CN2 disconnects the SWD lines from the ST-Link - but not the reset line.
There may be a connection to the ST-Link for measuring the target voltage.
Probably the easiest way with this Nucleo board is to break off the ST-Link part completely:
Adventures in low-power measurement with ST boards:
#SleepCurrentConsumption #CurrentConsumption #LowPower
2025-01-20 05:24 AM
Hello Andrew,
I have looked into the schematics and observed USART, MCO, NRST, SWO pins connected over solder bridges to the ST Link where CN2 separates out the required programming pins. So I take off the SBs then you think I will be able to achieve the required current consumption? Thanks for the support.
2025-01-21 02:38 AM - edited 2025-01-21 02:39 AM
I have taken OFF the SBs going to ST-LINK and now observed that the power consumption is 0.44 u amps. NRST is the culprit is what I see but this current feels very low is it correct? The code I have used is this
/**
******************************************************************************
* @file PWR/PWR_STOP/Src/main.c
* @author MCD Application Team
* @brief This sample code shows how to use STM32L0xx PWR HAL API to enter
* and exit the stop mode with an EXTI.
******************************************************************************
* @attention
*
* Copyright (c) 2016 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/** @addtogroup STM32L0xx_HAL_Examples
* @{
*/
/** @addtogroup PWR_STOP
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void SystemPower_Config(void);
/* Private functions ---------------------------------------------------------*/
/**
* @brief Main program
* None
* @retval None
*/
int main(void)
{
/* STM32L0xx HAL library initialization:
- Configure the Flash prefetch, Flash preread and Buffer caches
- Systick timer is configured by default as source of time base, but user
can eventually implement his proper time base source (a general purpose
timer for example or other time source), keeping in mind that Time base
duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
handled in milliseconds basis.
- Low Level Initialization
*/
HAL_Init();
/* Configure the system clock to 2 MHz */
SystemClock_Config();
/* Configure the system Power */
SystemPower_Config();
while (1)
{
/* Insert 5 second delay */
HAL_Delay(5000);
/* User push-button (lines 4 to 15) will be used to wakeup the system from STOP mode */
BSP_PB_Init(BUTTON_KEY, BUTTON_MODE_EXTI);
/* Enable Power Control clock */
__HAL_RCC_PWR_CLK_ENABLE();
/* Enter Stop Mode */
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
/* Configures system clock after wake-up from STOP */
SystemClock_Config();
}
}
/**
* @brief System Clock Configuration
* The system Clock is configured as follow :
* System Clock source = MSI
* SYSCLK(Hz) = 2000000
* HCLK(Hz) = 2000000
* AHB Prescaler = 1
* APB1 Prescaler = 1
* APB2 Prescaler = 1
* Flash Latency(WS) = 0
* Main regulator output voltage = Scale3 mode
* @retval None
*/
void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
/* Enable MSI Oscillator */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_5;
RCC_OscInitStruct.MSICalibrationValue=0x00;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct)!= HAL_OK)
{
/* Initialization Error */
while(1);
}
/* Select MSI as system clock source and configure the HCLK, PCLK1 and PCLK2
clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0)!= HAL_OK)
{
/* Initialization Error */
while(1);
}
/* Enable Power Control clock */
__HAL_RCC_PWR_CLK_ENABLE();
/* 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_SCALE3);
}
/**
* @brief System Power Configuration
* The system Power is configured as follow :
* + Regulator in LP mode
* + VREFINT OFF, with fast wakeup enabled
* + MSI as SysClk after Wake Up
* + No IWDG
* + Wakeup using EXTI Line (User push-button PC.13)
* None
* @retval None
*/
static void SystemPower_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable Power Control clock */
__HAL_RCC_PWR_CLK_ENABLE();
/* Enable Ultra low power mode */
HAL_PWREx_EnableUltraLowPower();
/* Enable the fast wake up from Ultra low power mode */
HAL_PWREx_EnableFastWakeUp();
/* Select MSI as system clock source after Wake Up from Stop mode */
__HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_MSI);
/* Enable GPIOs clock */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
/* Configure all GPIO port pins in Analog Input mode (floating input trigger OFF) */
/* Note: Debug using ST-Link is not possible during the execution of this */
/* example because communication between ST-link and the device */
/* under test is done through UART. All GPIO pins are disabled (set */
/* to analog input mode) including UART I/O pins. */
GPIO_InitStructure.Pin = GPIO_PIN_All;
GPIO_InitStructure.Mode = GPIO_MODE_ANALOG;
GPIO_InitStructure.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
HAL_GPIO_Init(GPIOB, &GPIO_InitStructure);
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
HAL_GPIO_Init(GPIOD, &GPIO_InitStructure);
HAL_GPIO_Init(GPIOH, &GPIO_InitStructure);
HAL_GPIO_Init(GPIOE, &GPIO_InitStructure);
/* Disable GPIOs clock */
__HAL_RCC_GPIOA_CLK_DISABLE();
__HAL_RCC_GPIOB_CLK_DISABLE();
__HAL_RCC_GPIOC_CLK_DISABLE();
__HAL_RCC_GPIOD_CLK_DISABLE();
__HAL_RCC_GPIOH_CLK_DISABLE();
__HAL_RCC_GPIOE_CLK_DISABLE();
}
/**
* @brief GPIO EXTI callback
* None
* @retval None
*/
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
/* Clear Wake Up Flag */
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
}
/**
* @brief SYSTICK callback
* None
* @retval None
*/
void HAL_SYSTICK_Callback(void)
{
HAL_IncTick();
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* file: pointer to the source file name
* line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif
/**
* @}
*/
/**
* @}
*/
which was an example code from CubeMX for STOP mode for EWARM. I am worried if everything is correct. Thanks and regards.
2025-01-21 02:59 AM
@PSaga.1 wrote:now observed that the power consumption is 0.44 u amps ... but this current feels very low is it correct? .
LOL - don't often get people complaining that their sleep current is too low !
Anyhow, what does the Datasheet say?
2025-01-24 02:16 AM
Hello @PSaga.1,
Normally, using an STM32L073, the typical power consumption is 0.43µA as per the datasheet:
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.