Biagio Montaruli / STM32_LowPower
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers STM32_LowPower.cpp Source File

STM32_LowPower.cpp

Go to the documentation of this file.
00001 /**
00002 ******************************************************************************
00003 * @file    STM32_LowPower.cpp
00004 * @author  Biagio Montaruli, STM32duino team (STMicroelectronics)
00005 * @version V1.0.0
00006 * @date    12-April-2019
00007 * @brief   Mbed Library to manage Low Power modes on STM32 boards
00008 *
00009 ******************************************************************************
00010 * @attention
00011 *
00012 * <h2><center>&copy; COPYRIGHT(c) 2019 STMicroelectronics</center></h2>
00013 * <h2><center>&copy; COPYRIGHT(c) 2019 Biagio Montaruli</center></h2>
00014 *
00015 * Redistribution and use in source and binary forms, with or without modification,
00016 * are permitted provided that the following conditions are met:
00017 *   1. Redistributions of source code must retain the above copyright notice,
00018 *      this list of conditions and the following disclaimer.
00019 *   2. Redistributions in binary form must reproduce the above copyright notice,
00020 *      this list of conditions and the following disclaimer in the documentation
00021 *      and/or other materials provided with the distribution.
00022 *   3. Neither the name of STMicroelectronics nor the names of its contributors
00023 *      may be used to endorse or promote products derived from this software
00024 *      without specific prior written permission.
00025 *
00026 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00027 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00029 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00030 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00031 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00032 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00033 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00034 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00035 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 *
00037 ******************************************************************************
00038 */
00039 
00040 #include "STM32_LowPower.h"
00041 #include "rtc_api_hal.h"
00042 
00043 STM32_LowPower LowPower;
00044 
00045 static RTC_HandleTypeDef RtcHandle;
00046 static voidFuncPtr RTCUserCallback = NULL;
00047 static void *callbackUserData = NULL;
00048 
00049 void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
00050 {
00051     UNUSED(hrtc);
00052 
00053     if (RTCUserCallback != NULL) {
00054         RTCUserCallback(callbackUserData);
00055     }
00056 }
00057 
00058 void RTC_IRQHandler(void)
00059 {
00060     HAL_RTCEx_WakeUpTimerIRQHandler(&RtcHandle);
00061 }
00062 
00063 #ifdef STM32G0xx
00064 #define PWR_FLAG_WU PWR_FLAG_WUF
00065 #endif
00066 
00067 STM32_LowPower::STM32_LowPower()
00068 {
00069     _configured = false;
00070     _rtc_wakeup = false;
00071     _timer = 0;
00072 }
00073 
00074 /**
00075   * @brief  Initializes the low power mode
00076   * @param  None
00077   * @retval None
00078   */
00079 void STM32_LowPower::init(void)
00080 {
00081     debug(DEBUG, "Starting STM32_LowPower::init()\n");
00082     /* Initialize Low Power mode using STM32 HAL */
00083 #if !defined(STM32H7xx) && !defined(STM32WBxx)
00084     /* Enable Power Clock */
00085     __HAL_RCC_PWR_CLK_ENABLE();
00086     debug(DEBUG, "STM32_LowPower::init() -> __HAL_RCC_PWR_CLK_ENABLE()\n");
00087 #endif
00088     /* Allow access to Backup domain */
00089     HAL_PWR_EnableBkUpAccess();
00090     debug(DEBUG, "STM32_LowPower::init() -> HAL_PWR_EnableBkUpAccess()\n");
00091 
00092 #ifdef __HAL_RCC_WAKEUPSTOP_CLK_CONFIG
00093     /* Ensure that HSI is wake-up system clock */
00094     __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI);
00095     debug(DEBUG, "STM32_LowPower::init() -> __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI)\n");
00096 #endif
00097     /* Check if the system was resumed from StandBy mode */
00098     if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB) != RESET) {
00099         /* Clear Standby flag */
00100         __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
00101         debug(DEBUG, "STM32_LowPower::init() -> __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB)\n");
00102     }
00103 
00104     /* Clear all related wakeup flags */
00105     __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
00106     debug(DEBUG, "STM32_LowPower::init() -> __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU)\n");
00107     
00108     /* start RTC */
00109     set_time(0);
00110 
00111     _configured = true;
00112     debug(DEBUG, "Exiting STM32_LowPower::init()...\n");
00113 }
00114 
00115 /**
00116   * @brief  Enable the STM32 sleep mode.
00117   *         Exit this mode on interrupt using the attachInterruptWakeup() method
00118   *         or in timer_s seconds.
00119   * @param  reg: type of power regulator.
00120   * @param  timer_s: optional delay before leaving the sleep mode (default: 0).
00121   * @retval None
00122   */
00123 void STM32_LowPower::sleep(STM32_RegulatorType reg, uint32_t timer_s)
00124 {
00125     debug(DEBUG, "Starting STM32_LowPower::sleep()...\n");
00126     
00127     uint32_t regulator;
00128 
00129     /* Enable STM32 Sleep Mode: regulator in main mode */
00130     if (reg == STM32_MAIN_REGULATOR) {
00131         regulator = PWR_MAINREGULATOR_ON;
00132         debug(DEBUG, "STM32_LowPower::sleep() -> regulator: PWR_MAINREGULATOR_ON\n");
00133     }
00134     /* Enable STM32 Low-power Sleep Mode: regulator in low-power mode */
00135     else if (reg == STM32_LOWPOWER_REGULATOR) {
00136         regulator = PWR_LOWPOWERREGULATOR_ON;
00137         debug(DEBUG, "STM32_LowPower::sleep() -> regulator: PWR_LOWPOWERREGULATOR_ON\n");
00138     } else {
00139         regulator = PWR_MAINREGULATOR_ON;
00140     }
00141 
00142     if (timer_s > 0) {
00143         programRtcWakeUp(timer_s);
00144         debug(DEBUG, "STM32_LowPower::sleep() -> programRtcWakeUp(timer_s)\n");
00145     }
00146     else if (_rtc_wakeup && (_timer > 0)) {
00147         programRtcWakeUp(_timer);
00148         debug(DEBUG, "STM32_LowPower::sleep() -> programRtcWakeUp(_timer)\n");
00149     }
00150 
00151     /*
00152      * Suspend Tick increment to prevent wakeup by Systick interrupt.
00153      * Otherwise the Systick interrupt will wake up the device within
00154      * 1ms (HAL time base)
00155      */
00156     HAL_SuspendTick();
00157     debug(DEBUG, "STM32_LowPower::sleep() -> HAL_SuspendTick()\n");
00158 
00159     /* Enter Sleep Mode */
00160     debug(DEBUG, "STM32_LowPower::sleep() -> HAL_PWR_EnterSLEEPMode()\n");
00161     HAL_PWR_EnterSLEEPMode(regulator, PWR_SLEEPENTRY_WFI);
00162 
00163     /* Resume Tick interrupt if disabled before switching into Sleep mode */
00164     HAL_ResumeTick();
00165     debug(DEBUG, "STM32_LowPower::sleep() -> HAL_ResumeTick()\n");
00166     
00167     if ((timer_s > 0) || _rtc_wakeup) {
00168         rtc_deactivate_wake_up_timer();
00169     }
00170     
00171     debug(DEBUG, "Exiting STM32_LowPower::sleep()...\n");
00172 }
00173 
00174 /**
00175   * @brief  Enable the STM32 stop mode.
00176   *         Exit this mode on interrupt using the attachInterruptWakeup() method
00177   *         or in timer_s seconds.
00178   * @param  reg: type of power regulator.
00179   * @param  timer_s: optional delay before leaving the stop mode (default: 0).
00180   * @retval None
00181   */
00182 void STM32_LowPower::stop(STM32_RegulatorType reg, uint32_t timer_s)
00183 {
00184     debug(DEBUG, "Starting STM32_LowPower::stop()\n");
00185 
00186     __disable_irq();
00187     debug(DEBUG, "STM32_LowPower::stop() -> __disable_irq()\n");
00188 
00189     uint32_t regulator;
00190     /* Use regulator in main mode */
00191     if (reg == STM32_MAIN_REGULATOR) {
00192         regulator = PWR_MAINREGULATOR_ON;
00193         debug(DEBUG, "STM32_LowPower::stop() -> regulator: PWR_MAINREGULATOR_ON\n");
00194     }
00195     /* Use regulator in low-power mode */
00196     else if (reg == STM32_LOWPOWER_REGULATOR) {
00197         regulator = PWR_LOWPOWERREGULATOR_ON;
00198         debug(DEBUG, "STM32_LowPower::stop() -> regulator: PWR_LOWPOWERREGULATOR_ON\n");
00199     } else {
00200         regulator = PWR_LOWPOWERREGULATOR_ON;
00201     }
00202     
00203     if (timer_s > 0) {
00204         programRtcWakeUp(timer_s);
00205         debug(DEBUG, "STM32_LowPower::stop() -> programRtcWakeUp(timer_s)\n");
00206     }
00207     else if (_rtc_wakeup && (_timer > 0)) {
00208         programRtcWakeUp(_timer);
00209         debug(DEBUG, "STM32_LowPower::stop() -> programRtcWakeUp(_timer)\n");
00210     }
00211 
00212 #if defined(STM32L0xx) || defined(STM32L1xx)
00213     /* Enable Ultra low power mode */
00214     HAL_PWREx_EnableUltraLowPower();
00215     debug(DEBUG, "STM32_LowPower::stop() -> HAL_PWREx_EnableUltraLowPower()\n");
00216 
00217     /* Enable the fast wake up from Ultra low power mode */
00218     HAL_PWREx_EnableFastWakeUp();
00219     debug(DEBUG, "STM32_LowPower::stop() -> HAL_PWREx_EnableFastWakeUp()\n");
00220 #endif
00221 #ifdef __HAL_RCC_WAKEUPSTOP_CLK_CONFIG
00222     /* Select HSI as system clock source after Wake Up from Stop mode */
00223     __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI);
00224     debug(DEBUG, "STM32_LowPower::stop() -> __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI)\n");
00225 #endif
00226 
00227     /* Enter Stop mode */
00228     debug(DEBUG, "STM32_LowPower::stop() -> HAL_PWR_EnterSTOPMode()\n");
00229     HAL_Delay(20);
00230     HAL_PWR_EnterSTOPMode(regulator, PWR_STOPENTRY_WFI);
00231 
00232     /* Exit Stop mode reset clocks */
00233     SetSysClock();
00234 
00235     __enable_irq();
00236     debug(DEBUG, "STM32_LowPower::stop() -> __enable_irq()\n");
00237     
00238     HAL_Delay(100);
00239     debug(DEBUG, "STM32_LowPower::stop() -> SetSysClock()\n");
00240     
00241     if ((timer_s > 0) || _rtc_wakeup) {
00242         rtc_deactivate_wake_up_timer();
00243     }
00244     
00245     debug(DEBUG, "Exiting STM32_LowPower::stop()...\n");
00246 }
00247 
00248 /**
00249   * @brief  Enable the STM32 shutdown or standby mode.
00250   *         Exit this mode on interrupt using the attachInterruptWakeup() method
00251   *         or in timer_s seconds.
00252   * @param  timer_s: optional delay before leaving the standby mode (default: 0).
00253   * @retval None
00254   */
00255 void STM32_LowPower::standby(uint32_t timer_s)
00256 {
00257     __disable_irq();
00258     debug(DEBUG, "STM32_LowPower::standby() -> __disable_irq()\n");
00259     
00260     debug(DEBUG, "Starting STM32_LowPower::standby()...\n");
00261     if (timer_s > 0) {
00262         programRtcWakeUp(timer_s);
00263         debug(DEBUG, "STM32_LowPower::standby() -> programRtcWakeUp(timer_s)\n");
00264     }
00265     else if (_rtc_wakeup && (_timer > 0)) {
00266         programRtcWakeUp(_timer);
00267         debug(DEBUG, "STM32_LowPower::standby() -> programRtcWakeUp(_timer)\n");
00268     }
00269 
00270 #if defined(STM32L0xx) || defined(STM32L1xx)
00271     /* Enable Ultra low power mode */
00272     HAL_PWREx_EnableUltraLowPower();
00273     debug(DEBUG, "STM32_LowPower::standby() -> HAL_PWREx_EnableUltraLowPower()\n");
00274 
00275     /* Enable the fast wake up from Ultra low power mode */
00276     HAL_PWREx_EnableFastWakeUp();
00277     debug(DEBUG, "STM32_LowPower::standby() -> HAL_PWREx_EnableFastWakeUp()\n");
00278 #endif
00279     debug(DEBUG, "STM32_LowPower::standby() -> HAL_PWR_EnterSTANDBYMode()\n");
00280     HAL_PWR_EnterSTANDBYMode();
00281 }
00282 
00283 /**
00284   * @brief  Enable GPIO pin in interrupt mode. If the pin is a wakeup pin, it is
00285   *         configured as wakeup source.
00286   * @param  pin:  pin name (PX_Y, where X = GPIO port and Y = GPIO number)
00287   * @param  callback: pointer to callback function.
00288   * @param  mode: interrupt mode (IT_MODE_RISING, IT_MODE_FALLING, IT_MODE_RISING_FALLING)
00289   * @retval None
00290   */
00291 void STM32_LowPower::attachInterruptWakeup(PinName pin, voidFuncPtrVoid callback,
00292                                            Interrupt_Mode mode)
00293 {
00294     debug(DEBUG, "Starting STM32_LowPower::attachInterruptWakeup()...\n");
00295     debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> pin: %u\n", pin);
00296     _wakeupPin = new InterruptIn(pin);
00297 
00298     switch (mode) {
00299         case IT_MODE_RISING :
00300             _wakeupPin->rise(callback);
00301             debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wakeupPin->rise(callback)\n");
00302             break;
00303         case IT_MODE_FALLING :
00304             _wakeupPin->fall(callback);
00305             debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wakeupPin->fall(callback)\n");
00306             break;
00307         case IT_MODE_RISING_FALLING :
00308         default:
00309             _wakeupPin->rise(callback);
00310             _wakeupPin->fall(callback);
00311             debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wakeupPin->rise & fall\n");
00312             break;
00313     }
00314 
00315     /* If Gpio is a Wake up pin activate it in order to wake up the STM32 MCU */
00316 #if !defined(PWR_WAKEUP_PIN1_HIGH)
00317     UNUSED(mode);
00318 #endif
00319     uint32_t wkup_pin;
00320     if (pin != NC) {
00321         switch (pin) {
00322 #ifdef PWR_WAKEUP_PIN1
00323 
00324 #if defined(TARGET_DISCO_F100RB)  || defined(TARGET_DISCO_F407VG)  || \
00325     defined(TARGET_DISCO_F401VC)  || defined(TARGET_DISCO_F429ZI)  || \
00326     defined(TARGET_NUCLEO_F103RB) || defined(TARGET_NUCLEO_F207ZG) || \
00327     defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE) || \
00328     defined(TARGET_NUCLEO_F429ZI) || defined(TARGET_NUCLEO_F439ZI) || \
00329     defined(TARGET_NUCLEO_F469NI) || defined(TARGET_MTB_STM_S2LP)
00330             case SYS_WKUP :
00331 #else
00332             case SYS_WKUP1 :
00333 #endif
00334                 wkup_pin = PWR_WAKEUP_PIN1;
00335                 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN1.\n");
00336 #ifdef PWR_WAKEUP_PIN1_HIGH
00337                 if (mode != IT_MODE_RISING) {
00338                     wkup_pin = PWR_WAKEUP_PIN1_LOW;
00339                     debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN1_LOW.\n");
00340                 }
00341 #endif
00342                 break;
00343 #endif /* PWR_WAKEUP_PIN1 */
00344 #ifdef PWR_WAKEUP_PIN2
00345             case SYS_WKUP2 :
00346                 wkup_pin = PWR_WAKEUP_PIN2;
00347                 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN2.\n");
00348 #ifdef PWR_WAKEUP_PIN2_HIGH
00349                 if (mode != IT_MODE_RISING) {
00350                     wkup_pin = PWR_WAKEUP_PIN2_LOW;
00351                     debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN2_LOW\n");
00352                 }
00353 #endif
00354                 break;
00355 #endif /* PWR_WAKEUP_PIN2 */
00356 #ifdef PWR_WAKEUP_PIN3
00357             case SYS_WKUP3 :
00358                 wkup_pin = PWR_WAKEUP_PIN3;
00359                 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN3\n");
00360 #ifdef PWR_WAKEUP_PIN3_HIGH
00361                 if (mode != IT_MODE_RISING) {
00362                     wkup_pin = PWR_WAKEUP_PIN3_LOW;
00363                     debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN3_LOW\n");
00364                 }
00365 #endif
00366                 break;
00367 #endif /* PWR_WAKEUP_PIN3 */
00368 #ifdef PWR_WAKEUP_PIN4
00369             case SYS_WKUP4 :
00370                 wkup_pin = PWR_WAKEUP_PIN4;
00371                 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN4\n");
00372 #ifdef PWR_WAKEUP_PIN4_HIGH
00373                 if (mode != IT_MODE_RISING) {
00374                     wkup_pin = PWR_WAKEUP_PIN4_LOW;
00375                     debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN4_LOW\n");
00376                 }
00377 #endif
00378                 break;
00379 #endif /* PWR_WAKEUP_PIN4 */
00380 #ifdef PWR_WAKEUP_PIN5
00381             case SYS_WKUP5 :
00382                 wkup_pin = PWR_WAKEUP_PIN5;
00383                 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN5\n");
00384 #ifdef PWR_WAKEUP_PIN5_HIGH
00385                 if (mode != IT_MODE_RISING) {
00386                     wkup_pin = PWR_WAKEUP_PIN5_LOW;
00387                     debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN5_LOW\n");
00388                 }
00389 #endif
00390                 break;
00391 #endif /* PWR_WAKEUP_PIN5 */
00392 #ifdef PWR_WAKEUP_PIN6
00393             case SYS_WKUP6 :
00394                 wkup_pin = PWR_WAKEUP_PIN6;
00395                 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN6\n");
00396 #ifdef PWR_WAKEUP_PIN6_HIGH
00397                 if (mode != IT_MODE_RISING) {
00398                     wkup_pin = PWR_WAKEUP_PIN6_LOW;
00399                     debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN6_LOW\n");
00400                 }
00401 #endif
00402                 break;
00403 #endif /* PWR_WAKEUP_PIN6 */
00404 #ifdef PWR_WAKEUP_PIN7
00405             case SYS_WKUP7 :
00406                 wkup_pin = PWR_WAKEUP_PIN7;
00407                 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN7\n");
00408                 break;
00409 #endif /* PWR_WAKEUP_PIN7 */
00410 #ifdef PWR_WAKEUP_PIN8
00411             case SYS_WKUP8 :
00412                 wkup_pin = PWR_WAKEUP_PIN8;
00413                 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN7\n");
00414                 break;
00415 #endif /* PWR_WAKEUP_PIN8 */
00416             default :
00417                 wkup_pin = PWR_WAKEUP_PIN1;
00418                 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN1 (default case)\n");
00419 #ifdef PWR_WAKEUP_PIN1_HIGH
00420                 if (mode != IT_MODE_RISING) {
00421                     wkup_pin = PWR_WAKEUP_PIN1_LOW;
00422                     debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN1_LOW (default case)\n");
00423                 }
00424 #endif
00425                 break;
00426         }
00427 
00428         HAL_PWR_EnableWakeUpPin(wkup_pin);
00429         debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> HAL_PWR_EnableWakeUpPin()\n");
00430         debug(DEBUG, "Exiting STM32_LowPower::attachInterruptWakeup()...\n");
00431     }
00432 }
00433 
00434 /**
00435   * @brief  Configure the RTC WakeUp Interrupt.
00436   * @param  millis: time (in seconds) to generate a RTC WakeUp event.
00437   * @retval None
00438   */
00439 void STM32_LowPower::programRtcWakeUp(uint32_t timer_s)
00440 {
00441     uint32_t rtc_clock;
00442     
00443     core_util_critical_section_enter();
00444     debug(DEBUG, "STM32_LowPower::programRtcWakeUp() -> core_util_critical_section_enter()\n");
00445     
00446     rtc_clock = RTC_WAKEUPCLOCK_CK_SPRE_16BITS;
00447     
00448     /* Clear wakeup flag, just in case. */
00449     SET_BIT(PWR->CR, PWR_CR_CWUF);
00450 
00451     /* HAL_RTCEx_SetWakeUpTimer_IT will assert that timer_s is 0xFFFF at max */
00452     if (timer_s > 0xFFFF) {
00453         timer_s -= 0x10000;
00454         rtc_clock = RTC_WAKEUPCLOCK_CK_SPRE_17BITS;
00455     }
00456 
00457     RtcHandle.Instance = RTC;
00458 
00459     HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, timer_s, rtc_clock);
00460     debug(DEBUG, "STM32_LowPower::programRtcWakeUp() -> HAL_RTCEx_SetWakeUpTimer_IT()\n");
00461     
00462     NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler);
00463     NVIC_EnableIRQ(RTC_WKUP_IRQn);
00464     
00465     core_util_critical_section_exit();
00466     debug(DEBUG, "STM32_LowPower::programRtcWakeUp() -> core_util_critical_section_exit()\n");
00467 }
00468 
00469 /**
00470   * @brief  Attach a callback to a RTC WakeUp event.
00471   * @param  callback: callback function called when leaving the low power mode.
00472   * @param  data: optional pointer to callback data parameters (default NULL).
00473   * @retval None
00474   */
00475 void STM32_LowPower::enableWakeupFromRTC(voidFuncPtr callback, void *data,
00476                                          uint32_t timer_s)
00477 {
00478     _rtc_wakeup = true;
00479     if (timer_s > 0) {
00480         _timer = timer_s;
00481     }
00482     RTCUserCallback = callback;
00483     callbackUserData = data;
00484 }