on 2021-11-16 02:12 AM
The STM32’s integrated RTC (Real-Time Clock) peripheral can be used to periodically wake it up from one of the various Low Power modes. It is very common for battery powered applications to have a power scheme where the application will run for a short period of time and then enter a low power mode to save power and extend battery life. The RTC can be used to wake up the STM32 from a low power mode, even in the lowest power mode like Standby.
In this article we will see how to configure the RTC peripheral of the STM32 to wake up the STM32 periodically from a low power mode like STOP2 mode which is one of the lowest power modes of the STM3L4.
In main, execution loops on turning the LED on for 1 second, entering STOP 2 mode and then the RTC waking up the STM32 after 10 seconds. When the RTC wakes up the device, execution goes to the RTC ISR to clear some RTC fags and then goes back to main to continue code execution.
/* USER CODE BEGIN WHILE */ while (1) { HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET); HAL_Delay(1000); HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET); HAL_SuspendTick(); HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 0x500B, RTC_WAKEUPCLOCK_RTCCLK_DIV16); /* Enter STOP 2 mode */ HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI); HAL_RTCEx_DeactivateWakeUpTimer(&hrtc); SystemClock_Config(); HAL_ResumeTick(); /* USER CODE END WHILE */
Thanks, nice article. ICNR, the calculation of the WakeUpCounter results exactly in 0x5000 (20480 dec) time. It is easier (for me) to calculate as follows:
The XTAL 'counts' 32768 per second. We divide by 16 i.e. 2048 oszillations (counts) per second. 10 sec: Multiplied with 10 is 20480 or 0x5000.
This is a useful article. But, when implementing this on my design, it does not work 100% :
If other code (in the main loop while(1)) uses critical sections (to achieve thread safety from ISR), the MCU does not stay asleep, but wakes up immediately..
If you have no other code disabling/enabling interrupts, then the MCU goes into sleep without problems.
See this question : STM32WLE immediately exist Stop2 when using UTILS_ENTER_CRITICAL_SECTION()
Hi, the above problem was due to a certain function disabling the interrupts, and then the WFI does not stop the MCU.
After correcting this, the above example works perfect. Thank you
Hi Laura,
Nice example does it also apply to the stm32wle5J?
And is it possible to use a time based wakeup and a external interrupt wakeup as well?
Thanks for your time.
Greetings Dom
Ok I tried it out of the blue and it generates an error. It says:
09:29:23 **** Incremental Build of configuration Debug for project Seeed-LoRa-E5 ****
make -j16 all
arm-none-eabi-gcc "../Core/Src/main.c" -mcpu=cortex-m4 -std=gnu11 -g3 -DDEBUG -DCORE_CM4 -DUSE_HAL_DRIVER -DSTM32WLE5xx -c -I../Core/Inc -I"C:/Users/Dominik/Downloads/Seeed-LoRa-E5-master/Drivers/BSP/STM32WLxx_Nucleo" -I../Drivers/STM32WLxx_HAL_Driver/Inc -I../Drivers/STM32WLxx_HAL_Driver/Inc/Legacy -I../Drivers/CMSIS/Device/ST/STM32WLxx/Include -I../Drivers/CMSIS/Include -I../LoRaWAN/App -I../LoRaWAN/Target -I../Utilities/trace/adv_trace -I../Utilities/misc -I../Utilities/sequencer -I../Utilities/timer -I../Utilities/lpm/tiny_lpm -I../Middlewares/Third_Party/LoRaWAN/LmHandler/Packages -I../Middlewares/Third_Party/SubGHz_Phy -I../Middlewares/Third_Party/SubGHz_Phy/stm32_radio_driver -I../Middlewares/Third_Party/LoRaWAN/Crypto -I../Middlewares/Third_Party/LoRaWAN/Mac/Region -I../Middlewares/Third_Party/LoRaWAN/Mac -I../Middlewares/Third_Party/LoRaWAN/LmHandler -I../Middlewares/Third_Party/LoRaWAN/Utilities -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -fcyclomatic-complexity -MMD -MP -MF"Core/Src/main.d" -MT"Core/Src/main.o" --specs=nano.specs -mfloat-abi=soft -mthumb -o "Core/Src/main.o"
../Core/Src/main.c: In function 'main':
../Core/Src/main.c:106:34: error: 'hrtc' undeclared (first use in this function)
106 | HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 0x500B, RTC_WAKEUPCLOCK_RTCCLK_DIV16);
| ^~~~
../Core/Src/main.c:106:34: note: each undeclared identifier is reported only once for each function it appears in
../Core/Src/main.c:106:5: error: too few arguments to function 'HAL_RTCEx_SetWakeUpTimer_IT'
106 | HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 0x500B, RTC_WAKEUPCLOCK_RTCCLK_DIV16);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../Drivers/STM32WLxx_HAL_Driver/Inc/stm32wlxx_hal_rtc.h:738,
from ../Core/Inc/stm32wlxx_hal_conf.h:281,
from ../Drivers/STM32WLxx_HAL_Driver/Inc/stm32wlxx_hal.h:29,
from ../Core/Inc/main.h:30,
from ../Core/Src/main.c:20:
../Drivers/STM32WLxx_HAL_Driver/Inc/stm32wlxx_hal_rtc_ex.h:1141:19: note: declared here
1141 | HAL_StatusTypeDef HAL_RTCEx_SetWakeUpTimer_IT(RTC_HandleTypeDef *hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock, uint32_t WakeUpAutoClr);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
make: *** [Core/Src/subdir.mk:76: Core/Src/main.o] Error 1
"make -j16 all" terminated with exit code 2. Build might be incomplete.
09:29:23 Build Failed. 3 errors, 0 warnings. (took 486ms)
I´m not sure it is undeclared?
Greetings Dom
hrtc is a 'handle' to the RTC object. It is declared in main.c
if you want to use it in other source code files, you have to add
extern RTC_HandleTypeDef hrtc;
and for the RTC_HandleTypeDef to be a known type, you have to include eg. main.h
Hmm I added the code like so:
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
extern RTC_HandleTypeDef hrtc;
/* USER CODE END Includes */
After that there is an error about too few arguments within the call:
HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 0x500B, RTC_WAKEUPCLOCK_RTCCLK_DIV16);
Which I do understand because when following the expression via (Ctrl- right click) I do see that there should be:
HAL_StatusTypeDef HAL_RTCEx_SetWakeUpTimer_IT(RTC_HandleTypeDef *hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock, uint32_t WakeUpAutoClr)
four I guess. But it is not autogenerated be Cube MX?
Regards Dom