2016-03-11 09:52 AM
I have found a strange behavior of STM32L Low consumption 1.0 uA (as stated in the datasheet) is reached in the first sleeping with the STOP mode after reset but in sleepings that follow the first and next wake-ups the uC further consumes 2.3 uA.
It cannot depend on the external circuitry but in my minimalistic code that isolates the problem I have switched all GPIOs in the Analog Mode for sure.#include <
stdbool.h
>
#include ''stm32l0xx_hal.h''
RTC_HandleTypeDef hrtc;
volatile bool rtcwake = false;
int wakeperiod = 5; // [s]
//--------------------------------------------------------------
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
__SYSCFG_CLK_ENABLE();
__PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE|RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
RCC_OscInitStruct.MSICalibrationValue = 0;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
__HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_LOW);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
//--------------------------------------------------------------
void MX_RTC_Init(void)
{
RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
hrtc.Instance = RTC;
hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
hrtc.Init.AsynchPrediv = 127;
hrtc.Init.SynchPrediv = 255;
hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
HAL_RTC_Init(&hrtc);
sTime.Hours = 0x0;
sTime.Minutes = 0x0;
sTime.Seconds = 0x0;
sTime.TimeFormat = RTC_HOURFORMAT_24;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET;
HAL_RTC_SetTime(&hrtc, &sTime, FORMAT_BIN);
sDate.WeekDay = RTC_WEEKDAY_MONDAY;
sDate.Month = RTC_MONTH_JANUARY;
sDate.Date = 0x1;
sDate.Year = 16;
HAL_RTC_SetDate(&hrtc, &sDate, FORMAT_BIN);
}
//--------------------------------------------------------------
void RTCClock_Config()
{
RCC_PeriphCLKInitTypeDef PeriphClkInit;
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC;
PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
__HAL_RCC_RTC_ENABLE();
HAL_NVIC_SetPriority(RTC_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(RTC_IRQn);
}
//--------------------------------------------------------------
void DisableAllGPIO()
{
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pin = GPIO_PIN_All;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
//--------------------------------------------------------------
int main(void)
{
HAL_Init();
SystemClock_Config();
RTCClock_Config(); // only once, at start
DisableAllGPIO();
MX_RTC_Init();
// Disable the Power Voltage Detector(PVD)
HAL_PWR_DisablePVD();
// Enable Ultra low power mode - disable internal voltage reference
HAL_PWREx_EnableUltraLowPower();
// Select MSI as system clock source after Wake Up from Stop mode
__HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_MSI);
HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, wakeperiod-1, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);
while (1)
{
HAL_Delay(1000);
HAL_SuspendTick();
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
// Waiting for wake-up *******************************
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF);
__HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG();
SystemClock_Config();
}
}
// stm32l0xx_it.c
#include <
stdbool.h
>
#include ''stm32l0xx_hal.h''
/* External variables --------------------------------------------------------*/
extern RTC_HandleTypeDef hrtc;
extern volatile bool rtcwake;
//--------------------------------------------------------------
void SysTick_Handler(void)
{
HAL_IncTick();
}
//--------------------------------------------------------------
void RTC_IRQHandler(void)
{
NVIC_ClearPendingIRQ(RTC_IRQn);
/* Get the pending status of the WAKEUPTIMER Interrupt */
if (__HAL_RTC_WAKEUPTIMER_GET_FLAG(&hrtc, RTC_FLAG_WUTF) != RESET)
{
/* Clear the WAKEUPTIMER interrupt pending bit */
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF);
rtcwake = true;
}
/* Clear the EXTI's line Flag for RTC WakeUpTimer */
__HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG();
}
Any opinion, please?
Ivan
2016-03-13 04:13 PM
Although I do not know why, clearing of another flag in the RTC interrupt handler is important:
void RTC_IRQHandler(void)
{
NVIC_ClearPendingIRQ(RTC_IRQn);
/* Get the pending status of the WAKEUPTIMER Interrupt */
if (__HAL_RTC_WAKEUPTIMER_GET_FLAG(&hrtc, RTC_FLAG_WUTF) != RESET)
{
/* Clear the WAKEUPTIMER interrupt pending bit */
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&hrtc, RTC_FLAG_WUTF);
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); // NECESSARY FOR LOW CONSUMPTION !!!
rtcwake = true;
}
/* Clear the EXTI's line Flag for RTC WakeUpTimer */
__HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG();
}