Mbed library to manage low-power modes on STM32 devices
Revision 0:f37bc13b9bbf, committed 2019-04-12
- Comitter:
- biagiomkr
- Date:
- Fri Apr 12 17:36:38 2019 +0000
- Commit message:
- First release of STM32_LowPower Mbed library.; Added source code:; - STM32_LowPower.cpp; - STM32_LowPower.h
Changed in this revision
STM32_LowPower.cpp | Show annotated file Show diff for this revision Revisions of this file |
STM32_LowPower.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/STM32_LowPower.cpp Fri Apr 12 17:36:38 2019 +0000 @@ -0,0 +1,484 @@ +/** +****************************************************************************** +* @file STM32_LowPower.cpp +* @author Biagio Montaruli, STM32duino team (STMicroelectronics) +* @version V1.0.0 +* @date 12-April-2019 +* @brief Mbed Library to manage Low Power modes on STM32 boards +* +****************************************************************************** +* @attention +* +* <h2><center>© COPYRIGHT(c) 2019 STMicroelectronics</center></h2> +* <h2><center>© COPYRIGHT(c) 2019 Biagio Montaruli</center></h2> +* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* 3. Neither the name of STMicroelectronics nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +*/ + +#include "STM32_LowPower.h" +#include "rtc_api_hal.h" + +STM32_LowPower LowPower; + +static RTC_HandleTypeDef RtcHandle; +static voidFuncPtr RTCUserCallback = NULL; +static void *callbackUserData = NULL; + +void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc) +{ + UNUSED(hrtc); + + if (RTCUserCallback != NULL) { + RTCUserCallback(callbackUserData); + } +} + +void RTC_IRQHandler(void) +{ + HAL_RTCEx_WakeUpTimerIRQHandler(&RtcHandle); +} + +#ifdef STM32G0xx +#define PWR_FLAG_WU PWR_FLAG_WUF +#endif + +STM32_LowPower::STM32_LowPower() +{ + _configured = false; + _rtc_wakeup = false; + _timer = 0; +} + +/** + * @brief Initializes the low power mode + * @param None + * @retval None + */ +void STM32_LowPower::init(void) +{ + debug(DEBUG, "Starting STM32_LowPower::init()\n"); + /* Initialize Low Power mode using STM32 HAL */ +#if !defined(STM32H7xx) && !defined(STM32WBxx) + /* Enable Power Clock */ + __HAL_RCC_PWR_CLK_ENABLE(); + debug(DEBUG, "STM32_LowPower::init() -> __HAL_RCC_PWR_CLK_ENABLE()\n"); +#endif + /* Allow access to Backup domain */ + HAL_PWR_EnableBkUpAccess(); + debug(DEBUG, "STM32_LowPower::init() -> HAL_PWR_EnableBkUpAccess()\n"); + +#ifdef __HAL_RCC_WAKEUPSTOP_CLK_CONFIG + /* Ensure that HSI is wake-up system clock */ + __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI); + debug(DEBUG, "STM32_LowPower::init() -> __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI)\n"); +#endif + /* Check if the system was resumed from StandBy mode */ + if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB) != RESET) { + /* Clear Standby flag */ + __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB); + debug(DEBUG, "STM32_LowPower::init() -> __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB)\n"); + } + + /* Clear all related wakeup flags */ + __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU); + debug(DEBUG, "STM32_LowPower::init() -> __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU)\n"); + + /* start RTC */ + set_time(0); + + _configured = true; + debug(DEBUG, "Exiting STM32_LowPower::init()...\n"); +} + +/** + * @brief Enable the STM32 sleep mode. + * Exit this mode on interrupt using the attachInterruptWakeup() method + * or in timer_s seconds. + * @param reg: type of power regulator. + * @param timer_s: optional delay before leaving the sleep mode (default: 0). + * @retval None + */ +void STM32_LowPower::sleep(STM32_RegulatorType reg, uint32_t timer_s) +{ + debug(DEBUG, "Starting STM32_LowPower::sleep()...\n"); + + uint32_t regulator; + + /* Enable STM32 Sleep Mode: regulator in main mode */ + if (reg == STM32_MAIN_REGULATOR) { + regulator = PWR_MAINREGULATOR_ON; + debug(DEBUG, "STM32_LowPower::sleep() -> regulator: PWR_MAINREGULATOR_ON\n"); + } + /* Enable STM32 Low-power Sleep Mode: regulator in low-power mode */ + else if (reg == STM32_LOWPOWER_REGULATOR) { + regulator = PWR_LOWPOWERREGULATOR_ON; + debug(DEBUG, "STM32_LowPower::sleep() -> regulator: PWR_LOWPOWERREGULATOR_ON\n"); + } else { + regulator = PWR_MAINREGULATOR_ON; + } + + if (timer_s > 0) { + programRtcWakeUp(timer_s); + debug(DEBUG, "STM32_LowPower::sleep() -> programRtcWakeUp(timer_s)\n"); + } + else if (_rtc_wakeup && (_timer > 0)) { + programRtcWakeUp(_timer); + debug(DEBUG, "STM32_LowPower::sleep() -> programRtcWakeUp(_timer)\n"); + } + + /* + * Suspend Tick increment to prevent wakeup by Systick interrupt. + * Otherwise the Systick interrupt will wake up the device within + * 1ms (HAL time base) + */ + HAL_SuspendTick(); + debug(DEBUG, "STM32_LowPower::sleep() -> HAL_SuspendTick()\n"); + + /* Enter Sleep Mode */ + debug(DEBUG, "STM32_LowPower::sleep() -> HAL_PWR_EnterSLEEPMode()\n"); + HAL_PWR_EnterSLEEPMode(regulator, PWR_SLEEPENTRY_WFI); + + /* Resume Tick interrupt if disabled before switching into Sleep mode */ + HAL_ResumeTick(); + debug(DEBUG, "STM32_LowPower::sleep() -> HAL_ResumeTick()\n"); + + if ((timer_s > 0) || _rtc_wakeup) { + rtc_deactivate_wake_up_timer(); + } + + debug(DEBUG, "Exiting STM32_LowPower::sleep()...\n"); +} + +/** + * @brief Enable the STM32 stop mode. + * Exit this mode on interrupt using the attachInterruptWakeup() method + * or in timer_s seconds. + * @param reg: type of power regulator. + * @param timer_s: optional delay before leaving the stop mode (default: 0). + * @retval None + */ +void STM32_LowPower::stop(STM32_RegulatorType reg, uint32_t timer_s) +{ + debug(DEBUG, "Starting STM32_LowPower::stop()\n"); + + __disable_irq(); + debug(DEBUG, "STM32_LowPower::stop() -> __disable_irq()\n"); + + uint32_t regulator; + /* Use regulator in main mode */ + if (reg == STM32_MAIN_REGULATOR) { + regulator = PWR_MAINREGULATOR_ON; + debug(DEBUG, "STM32_LowPower::stop() -> regulator: PWR_MAINREGULATOR_ON\n"); + } + /* Use regulator in low-power mode */ + else if (reg == STM32_LOWPOWER_REGULATOR) { + regulator = PWR_LOWPOWERREGULATOR_ON; + debug(DEBUG, "STM32_LowPower::stop() -> regulator: PWR_LOWPOWERREGULATOR_ON\n"); + } else { + regulator = PWR_LOWPOWERREGULATOR_ON; + } + + if (timer_s > 0) { + programRtcWakeUp(timer_s); + debug(DEBUG, "STM32_LowPower::stop() -> programRtcWakeUp(timer_s)\n"); + } + else if (_rtc_wakeup && (_timer > 0)) { + programRtcWakeUp(_timer); + debug(DEBUG, "STM32_LowPower::stop() -> programRtcWakeUp(_timer)\n"); + } + +#if defined(STM32L0xx) || defined(STM32L1xx) + /* Enable Ultra low power mode */ + HAL_PWREx_EnableUltraLowPower(); + debug(DEBUG, "STM32_LowPower::stop() -> HAL_PWREx_EnableUltraLowPower()\n"); + + /* Enable the fast wake up from Ultra low power mode */ + HAL_PWREx_EnableFastWakeUp(); + debug(DEBUG, "STM32_LowPower::stop() -> HAL_PWREx_EnableFastWakeUp()\n"); +#endif +#ifdef __HAL_RCC_WAKEUPSTOP_CLK_CONFIG + /* Select HSI as system clock source after Wake Up from Stop mode */ + __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI); + debug(DEBUG, "STM32_LowPower::stop() -> __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI)\n"); +#endif + + /* Enter Stop mode */ + debug(DEBUG, "STM32_LowPower::stop() -> HAL_PWR_EnterSTOPMode()\n"); + HAL_Delay(20); + HAL_PWR_EnterSTOPMode(regulator, PWR_STOPENTRY_WFI); + + /* Exit Stop mode reset clocks */ + SetSysClock(); + + __enable_irq(); + debug(DEBUG, "STM32_LowPower::stop() -> __enable_irq()\n"); + + HAL_Delay(100); + debug(DEBUG, "STM32_LowPower::stop() -> SetSysClock()\n"); + + if ((timer_s > 0) || _rtc_wakeup) { + rtc_deactivate_wake_up_timer(); + } + + debug(DEBUG, "Exiting STM32_LowPower::stop()...\n"); +} + +/** + * @brief Enable the STM32 shutdown or standby mode. + * Exit this mode on interrupt using the attachInterruptWakeup() method + * or in timer_s seconds. + * @param timer_s: optional delay before leaving the standby mode (default: 0). + * @retval None + */ +void STM32_LowPower::standby(uint32_t timer_s) +{ + __disable_irq(); + debug(DEBUG, "STM32_LowPower::standby() -> __disable_irq()\n"); + + debug(DEBUG, "Starting STM32_LowPower::standby()...\n"); + if (timer_s > 0) { + programRtcWakeUp(timer_s); + debug(DEBUG, "STM32_LowPower::standby() -> programRtcWakeUp(timer_s)\n"); + } + else if (_rtc_wakeup && (_timer > 0)) { + programRtcWakeUp(_timer); + debug(DEBUG, "STM32_LowPower::standby() -> programRtcWakeUp(_timer)\n"); + } + +#if defined(STM32L0xx) || defined(STM32L1xx) + /* Enable Ultra low power mode */ + HAL_PWREx_EnableUltraLowPower(); + debug(DEBUG, "STM32_LowPower::standby() -> HAL_PWREx_EnableUltraLowPower()\n"); + + /* Enable the fast wake up from Ultra low power mode */ + HAL_PWREx_EnableFastWakeUp(); + debug(DEBUG, "STM32_LowPower::standby() -> HAL_PWREx_EnableFastWakeUp()\n"); +#endif + debug(DEBUG, "STM32_LowPower::standby() -> HAL_PWR_EnterSTANDBYMode()\n"); + HAL_PWR_EnterSTANDBYMode(); +} + +/** + * @brief Enable GPIO pin in interrupt mode. If the pin is a wakeup pin, it is + * configured as wakeup source. + * @param pin: pin name (PX_Y, where X = GPIO port and Y = GPIO number) + * @param callback: pointer to callback function. + * @param mode: interrupt mode (IT_MODE_RISING, IT_MODE_FALLING, IT_MODE_RISING_FALLING) + * @retval None + */ +void STM32_LowPower::attachInterruptWakeup(PinName pin, voidFuncPtrVoid callback, + Interrupt_Mode mode) +{ + debug(DEBUG, "Starting STM32_LowPower::attachInterruptWakeup()...\n"); + debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> pin: %u\n", pin); + _wakeupPin = new InterruptIn(pin); + + switch (mode) { + case IT_MODE_RISING : + _wakeupPin->rise(callback); + debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wakeupPin->rise(callback)\n"); + break; + case IT_MODE_FALLING : + _wakeupPin->fall(callback); + debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wakeupPin->fall(callback)\n"); + break; + case IT_MODE_RISING_FALLING : + default: + _wakeupPin->rise(callback); + _wakeupPin->fall(callback); + debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wakeupPin->rise & fall\n"); + break; + } + + /* If Gpio is a Wake up pin activate it in order to wake up the STM32 MCU */ +#if !defined(PWR_WAKEUP_PIN1_HIGH) + UNUSED(mode); +#endif + uint32_t wkup_pin; + if (pin != NC) { + switch (pin) { +#ifdef PWR_WAKEUP_PIN1 + +#if defined(TARGET_DISCO_F100RB) || defined(TARGET_DISCO_F407VG) || \ + defined(TARGET_DISCO_F401VC) || defined(TARGET_DISCO_F429ZI) || \ + defined(TARGET_NUCLEO_F103RB) || defined(TARGET_NUCLEO_F207ZG) || \ + defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE) || \ + defined(TARGET_NUCLEO_F429ZI) || defined(TARGET_NUCLEO_F439ZI) || \ + defined(TARGET_NUCLEO_F469NI) || defined(TARGET_MTB_STM_S2LP) + case SYS_WKUP : +#else + case SYS_WKUP1 : +#endif + wkup_pin = PWR_WAKEUP_PIN1; + debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN1.\n"); +#ifdef PWR_WAKEUP_PIN1_HIGH + if (mode != IT_MODE_RISING) { + wkup_pin = PWR_WAKEUP_PIN1_LOW; + debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN1_LOW.\n"); + } +#endif + break; +#endif /* PWR_WAKEUP_PIN1 */ +#ifdef PWR_WAKEUP_PIN2 + case SYS_WKUP2 : + wkup_pin = PWR_WAKEUP_PIN2; + debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN2.\n"); +#ifdef PWR_WAKEUP_PIN2_HIGH + if (mode != IT_MODE_RISING) { + wkup_pin = PWR_WAKEUP_PIN2_LOW; + debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN2_LOW\n"); + } +#endif + break; +#endif /* PWR_WAKEUP_PIN2 */ +#ifdef PWR_WAKEUP_PIN3 + case SYS_WKUP3 : + wkup_pin = PWR_WAKEUP_PIN3; + debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN3\n"); +#ifdef PWR_WAKEUP_PIN3_HIGH + if (mode != IT_MODE_RISING) { + wkup_pin = PWR_WAKEUP_PIN3_LOW; + debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN3_LOW\n"); + } +#endif + break; +#endif /* PWR_WAKEUP_PIN3 */ +#ifdef PWR_WAKEUP_PIN4 + case SYS_WKUP4 : + wkup_pin = PWR_WAKEUP_PIN4; + debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN4\n"); +#ifdef PWR_WAKEUP_PIN4_HIGH + if (mode != IT_MODE_RISING) { + wkup_pin = PWR_WAKEUP_PIN4_LOW; + debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN4_LOW\n"); + } +#endif + break; +#endif /* PWR_WAKEUP_PIN4 */ +#ifdef PWR_WAKEUP_PIN5 + case SYS_WKUP5 : + wkup_pin = PWR_WAKEUP_PIN5; + debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN5\n"); +#ifdef PWR_WAKEUP_PIN5_HIGH + if (mode != IT_MODE_RISING) { + wkup_pin = PWR_WAKEUP_PIN5_LOW; + debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN5_LOW\n"); + } +#endif + break; +#endif /* PWR_WAKEUP_PIN5 */ +#ifdef PWR_WAKEUP_PIN6 + case SYS_WKUP6 : + wkup_pin = PWR_WAKEUP_PIN6; + debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN6\n"); +#ifdef PWR_WAKEUP_PIN6_HIGH + if (mode != IT_MODE_RISING) { + wkup_pin = PWR_WAKEUP_PIN6_LOW; + debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN6_LOW\n"); + } +#endif + break; +#endif /* PWR_WAKEUP_PIN6 */ +#ifdef PWR_WAKEUP_PIN7 + case SYS_WKUP7 : + wkup_pin = PWR_WAKEUP_PIN7; + debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN7\n"); + break; +#endif /* PWR_WAKEUP_PIN7 */ +#ifdef PWR_WAKEUP_PIN8 + case SYS_WKUP8 : + wkup_pin = PWR_WAKEUP_PIN8; + debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN7\n"); + break; +#endif /* PWR_WAKEUP_PIN8 */ + default : + wkup_pin = PWR_WAKEUP_PIN1; + debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN1 (default case)\n"); +#ifdef PWR_WAKEUP_PIN1_HIGH + if (mode != IT_MODE_RISING) { + wkup_pin = PWR_WAKEUP_PIN1_LOW; + debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN1_LOW (default case)\n"); + } +#endif + break; + } + + HAL_PWR_EnableWakeUpPin(wkup_pin); + debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> HAL_PWR_EnableWakeUpPin()\n"); + debug(DEBUG, "Exiting STM32_LowPower::attachInterruptWakeup()...\n"); + } +} + +/** + * @brief Configure the RTC WakeUp Interrupt. + * @param millis: time (in seconds) to generate a RTC WakeUp event. + * @retval None + */ +void STM32_LowPower::programRtcWakeUp(uint32_t timer_s) +{ + uint32_t rtc_clock; + + core_util_critical_section_enter(); + debug(DEBUG, "STM32_LowPower::programRtcWakeUp() -> core_util_critical_section_enter()\n"); + + rtc_clock = RTC_WAKEUPCLOCK_CK_SPRE_16BITS; + + /* Clear wakeup flag, just in case. */ + SET_BIT(PWR->CR, PWR_CR_CWUF); + + /* HAL_RTCEx_SetWakeUpTimer_IT will assert that timer_s is 0xFFFF at max */ + if (timer_s > 0xFFFF) { + timer_s -= 0x10000; + rtc_clock = RTC_WAKEUPCLOCK_CK_SPRE_17BITS; + } + + RtcHandle.Instance = RTC; + + HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, timer_s, rtc_clock); + debug(DEBUG, "STM32_LowPower::programRtcWakeUp() -> HAL_RTCEx_SetWakeUpTimer_IT()\n"); + + NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler); + NVIC_EnableIRQ(RTC_WKUP_IRQn); + + core_util_critical_section_exit(); + debug(DEBUG, "STM32_LowPower::programRtcWakeUp() -> core_util_critical_section_exit()\n"); +} + +/** + * @brief Attach a callback to a RTC WakeUp event. + * @param callback: callback function called when leaving the low power mode. + * @param data: optional pointer to callback data parameters (default NULL). + * @retval None + */ +void STM32_LowPower::enableWakeupFromRTC(voidFuncPtr callback, void *data, + uint32_t timer_s) +{ + _rtc_wakeup = true; + if (timer_s > 0) { + _timer = timer_s; + } + RTCUserCallback = callback; + callbackUserData = data; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/STM32_LowPower.h Fri Apr 12 17:36:38 2019 +0000 @@ -0,0 +1,95 @@ +/** +****************************************************************************** +* @file STM32_LowPower.h +* @author Biagio Montaruli, STM32duino team (STMicroelectronics) +* @version V1.0.0 +* @date 12-April-2019 +* @brief Mbed Library to manage Low Power modes on STM32 boards +* +****************************************************************************** +* @attention +* +* <h2><center>© COPYRIGHT(c) 2019 STMicroelectronics</center></h2> +* <h2><center>© COPYRIGHT(c) 2019 Biagio Montaruli</center></h2> +* +* Redistribution and use in source and binary forms, with or without modification, +* are permitted provided that the following conditions are met: +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* 3. Neither the name of STMicroelectronics nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +****************************************************************************** +*/ + +#ifndef _STM32_LOW_POWER_H_ +#define _STM32_LOW_POWER_H_ + +#include "mbed.h" + +#define DEBUG 0 + +/* Check if PWR HAL enable in mbed-os/targets/TARGET_STM/TARGET_STM32YZ/device/stm32yzxx_hal_conf.h */ +#ifndef HAL_PWR_MODULE_ENABLED +#error "PWR configuration is missing. Check flag HAL_PWR_MODULE_ENABLED in " \ + "mbed-os/targets/TARGET_STM/TARGET_STM32YZ/device/stm32yzxx_hal_conf.h" +#endif + +typedef void (*voidFuncPtrVoid)(void); +typedef void (*voidFuncPtr)(void *) ; + +typedef enum { + STM32_MAIN_REGULATOR = 0, + STM32_LOWPOWER_REGULATOR = 1 +} STM32_RegulatorType; + +typedef enum { + IT_MODE_RISING = 0, + IT_MODE_FALLING = 1, + IT_MODE_RISING_FALLING = 3 +} Interrupt_Mode; + +class STM32_LowPower +{ +public: + STM32_LowPower(); + + void init(void); + + void sleep(STM32_RegulatorType reg = STM32_MAIN_REGULATOR, uint32_t timer_s = 0); + + void stop(STM32_RegulatorType reg = STM32_MAIN_REGULATOR, uint32_t timer_s = 0); + + void standby(uint32_t timer_s = 0); + + void attachInterruptWakeup(PinName pin, voidFuncPtrVoid callback, + Interrupt_Mode mode); + void enableWakeupFromRTC(voidFuncPtr callback, void *data = NULL, uint32_t timer_s = 0); + +private: + bool _configured; /* Low Power mode initialization status */ + bool _rtc_wakeup; + uint32_t _timer; + InterruptIn *_wakeupPin; + + void programRtcWakeUp(uint32_t timer_s); +}; + +extern STM32_LowPower LowPower; + +#endif // _STM32_LOW_POWER_H_