2016-12-12 03:28 PM
So I'm running a program on an STM32L073 that puts the device into stop mode to minimise power consumption.
After flashing the device (via ST-LinkV2) it starts up and enters stop mode where it is consuming around 135 uA
After a soft reset (reset button or program) when the device enters stop mode again it consumes the same current.
However if the power is re-cycled upon entering stop mode it consumes around 5 uA
After a soft reset it consumes the same.
So I'd appreciate views on what could be running, or how to identify what could be running, in stop mode after flashing. As I'd like to switch that off!
Pretty sure that it is actually entering stop mode in the former case as putting it into sleep mode the consumption is significantly higher than 135 uA.
(maybe something to do with RTC and backup domains,which survive normal flashing, but can't think what would cause that level of consumption). Thanks, Ron
Solved! Go to Solution.
2016-12-20 07:18 AM
Hi Ron
Have you tried the example from STM32CubeL0 FW package?(STM32Cube\Repository\STM32Cube_FW_L0_V1.7.0\Projects\STM32L073RZ-Nucleo\Examples\PWR\PWR_STOP)
What consumption do you have with this example?
One thing which is removed after power-on reset is debug support in low power modes. In this case it is not enough to just comment the corresponding lines in the code.
Also be sure to check 'Reset and run', 'Reset after download' or similar option in your IDE.
2016-12-13 03:57 AM
Hi
Segal.Ron
,As mentionned in the datasheet device you expect the following :
– 0.43 μA Stop mode (16 wakeup lines)
– 0.86 μA Stop mode + RTC + 20 KB RAM retention)To reproduce the same power consumption value measured, you should apply the same conditions described in the '6.3.4 supply current characteristics' part.
I presume the you missed to configureAll I/O pins in analog input mode before entering the low power mode.
you would follow this recommandation.
If the answer is correct, press correct.
-Walid F-
2016-12-13 12:51 PM
Hi Walid
Maybe I didn't explain the situation very well. The entire board is running at 5 uA in stop mode with RTC and RAM, including the power supply, a LoRa radio and a few other parts besides (LPTIM is also running to count pulses during stop mode) . So I'm reasonably happy with that. (It's not possible to isolate measurement of mcu consumption on the board) The GPIO configuration is probably ok (I'm aware of low power mode requirements in that regard). However the 5 uA current is only achieved after an initial power down reset (disconnect and reconnect the power supply). It's a different story when the board restarts after flashing (via SWD) without a power recycle. In that case the board is consuming around 135 uA in stop mode. So am looking for ideas on how to track that down and/or resolve. The issue seems unlikely to be directly related to pin consumption as the configuration in that regard is of course the same after starting via any reset mode. Thanks, Ron.
2016-12-14 03:24 AM
Hi Ron,
You would share the main code of the application ( the part which commande the state machine of power cycle / reset/ wakeup ..and the low power mode configuration ..) to be able to help you on the subject.
-WAlid F-
2016-12-14 07:07 PM
Hi Walid,
Thanks for getting back gain and for assistance, which is very much appreciated. The code is quite spread out but I'll try to provide apparently relevant pieces. You're correct, it is based on the STM / Semtech cubemx lorawan example, which implements a state machine in (middleware) lora.c. The state machine is implemented as a switch statement in an endless while loop. This initialises the lorawan stack and radio, joins the network, transmits/receives data, then goes into state 'Sleep'. What happens in state 'Sleep' is defined in main.c. So in the regular program path (i.e. when there are no network exceptions) I check first that the LoraWAN MAC layer is idle, set the RTC to wake-up the mcu after a period and then enter deep sleep, as follows:
(apologies the code indentation is lost)
else if ( GetMacStatus( ) == 0 ) { // Ensure internal MAC status is idle before sleeping resetResendCount(); deepSleep(deepsleep_minutes);Here's the deepsleep function:
/**
* @brief Sets the device in low power, stop mode * @param uint16_t minutestosleep * @retval None */void deepSleep (uint16_t minutestosleep) { PRINTF ('DeepSleep ..zzz.\r\n');TimerStop( &WatchdogDelayTimer );
//HW_RTC_SetAlarm(minutestosleep * 60 * 1000); // Set Wakeup Alarm
HW_RTC_SetAlarm(minutestosleep * 60 * 100); // Set Wakeup Alarm
do { wakeforcount = false; LowPower_Handler(); } while (wakeforcount); // Go back to sleep if wake was a count interrupt ENABLE_IRQ();TimerStart(&WatchdogDelayTimer);
PRINTF ('Wakeup ..!!\r\n');
}
The do/while loop puts the mcu back to sleep after it is temporarily woken by an LPTIM interrupt, which then stores a pulse count total into an RTC backup register before going back to sleep.
Lowpower_Handler() is as follows:
void LowPower_Handler( void )
{ // DBG_GPIO_RST(GPIOB, GPIO_PIN_15); // DBG_GPIO_RST(GPIOB, GPIO_PIN_14); if ( LowPower_State == 0 ) { DBG_PRINTF('dz\n');HW_EnterStopMode( );
/* mcu dependent. to be implemented by user*/ HW_ExitStopMode(); // DBG_GPIO_SET(GPIOB, GPIO_PIN_15); // HW_RTC_setMcuWakeUpTime( ); // Commented out as not required with RTC Alarm } else { DBG_PRINTF('z\n'); HW_EnterSleepMode( ); // Note sleep mode is > 2mA// DBG_GPIO_SET(GPIOB, GPIO_PIN_14);
} }and HW_EnterStopeMode() is:
void HW_EnterStopMode( void)
{ BACKUP_PRIMASK();DISABLE_IRQ( );
HW_DeInit( );
/*clear wake up flag*/ SET_BIT(PWR->CR, PWR_CR_CWUF); RESTORE_PRIMASK( );/* Enter Stop Mode */
HAL_PWR_EnterSTOPMode ( PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI );}
HW_DeInit() is also pretty important for low power and to avoid immediately waking:
void HW_DeInit( void )
{Radio.Sleep( ); // force the radio to sleep before de-initialising pins
Radio.IoDeInit( );HW_SPI_DeInit( );
//HW_LPTIM_DeInit( );
HW_AdcDeInit();
vcom_DeInit( );
HW_BatGpioDeInit ( );
McuInitialized = false;}LPTIM must continue to run as it counts pulses from an external source during deep sleep. HW_BatGpioDeInit configures pins that control battery voltage sensing..
Two other functions that may be relevant are SystemClock_Config and SystemPower_Config as follows:
void SystemClock_Config( void ){ RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_OscInitTypeDef RCC_OscInitStruct = {0};RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; // added
// Enable HSE Oscillator and Activate PLL with HSE as source
//RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSE; // changed RCC_OscInitStruct.HSEState = RCC_HSE_OFF; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; // (16MHz) RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; //RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_6; //RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_3; // HSI Clock is 16MHz with 16MHz input and these parameters RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_3; RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_3;if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{ Error_Handler(); }// Set Voltage scale1 as MCU will run at 32MHz
__HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); // Poll VOSF bit of in PWR_CSR. Wait until it is reset to 0 while (__HAL_PWR_GET_FLAG(PWR_FLAG_VOS) != RESET) {};// Select PLL 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_PLLCLK; 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_1) != HAL_OK) //if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { Error_Handler(); }// Added
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2|RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_LPTIM1; PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1; PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE; PeriphClkInit.LptimClockSelection = RCC_LPTIM1CLKSOURCE_LSE; HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);// SysTick_IRQn interrupt configuration
HAL_NVIC_SetPriority(SysTick_IRQn, 0x0, 0);}
SystemPower_Config is used as part of initialisation:
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();/* 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();}Note that if I set it into sleep mode rather than stop mode in the deepSleep() function for testing purposes, current consumption is over 2mA.
So not sure if the above is of any help at all with diagnosis. Please let me know you require anything else. Am prepared to try almost anything to resolve! Cheers, Ron.
2016-12-20 07:18 AM
Hi Ron
Have you tried the example from STM32CubeL0 FW package?(STM32Cube\Repository\STM32Cube_FW_L0_V1.7.0\Projects\STM32L073RZ-Nucleo\Examples\PWR\PWR_STOP)
What consumption do you have with this example?
One thing which is removed after power-on reset is debug support in low power modes. In this case it is not enough to just comment the corresponding lines in the code.
Also be sure to check 'Reset and run', 'Reset after download' or similar option in your IDE.
2016-12-20 11:32 AM
Hi Jaroslav, thanks, your point about debug support in low power modes is exactly what I was hoping for. So I implemented a debug de-initialisation function that has solved the problem! As follows:
/**
* @brief This function Deinitializes Debug * @param None * @retval None */void HW_debug_DeInit(void) { /* sw interface off*/ GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.Mode = GPIO_MODE_ANALOG; GPIO_InitStructure.Pull = GPIO_NOPULL; GPIO_InitStructure.Pin = (GPIO_PIN_13 | GPIO_PIN_14); HAL_GPIO_Init(GPIOA, &GPIO_InitStructure); __HAL_RCC_DBGMCU_CLK_ENABLE( ); HAL_DBGMCU_DisableDBGSleepMode( ); HAL_DBGMCU_DisableDBGStopMode( ); HAL_DBGMCU_DisableDBGStandbyMode( ); __HAL_RCC_DBGMCU_CLK_DISABLE( );}It is now possible to flash the device whilst retaining RTC backup register contents, which is very useful for the particular application.
The goal now is to possibly reduce the board's stop mode current even further and also run time power consumption. Longer delays in the radio stack in particular I think could benefit from a sleep based approach.
In any case, thanks again for taking the time to help. Best wishes, Ron.