Mbed library to manage low-power modes on STM32 devices

Committer:
biagiomkr
Date:
Fri Apr 12 17:36:38 2019 +0000
Revision:
0:f37bc13b9bbf
First release of STM32_LowPower Mbed library.; Added source code:; - STM32_LowPower.cpp; - STM32_LowPower.h

Who changed what in which revision?

UserRevisionLine numberNew contents of line
biagiomkr 0:f37bc13b9bbf 1 /**
biagiomkr 0:f37bc13b9bbf 2 ******************************************************************************
biagiomkr 0:f37bc13b9bbf 3 * @file STM32_LowPower.cpp
biagiomkr 0:f37bc13b9bbf 4 * @author Biagio Montaruli, STM32duino team (STMicroelectronics)
biagiomkr 0:f37bc13b9bbf 5 * @version V1.0.0
biagiomkr 0:f37bc13b9bbf 6 * @date 12-April-2019
biagiomkr 0:f37bc13b9bbf 7 * @brief Mbed Library to manage Low Power modes on STM32 boards
biagiomkr 0:f37bc13b9bbf 8 *
biagiomkr 0:f37bc13b9bbf 9 ******************************************************************************
biagiomkr 0:f37bc13b9bbf 10 * @attention
biagiomkr 0:f37bc13b9bbf 11 *
biagiomkr 0:f37bc13b9bbf 12 * <h2><center>&copy; COPYRIGHT(c) 2019 STMicroelectronics</center></h2>
biagiomkr 0:f37bc13b9bbf 13 * <h2><center>&copy; COPYRIGHT(c) 2019 Biagio Montaruli</center></h2>
biagiomkr 0:f37bc13b9bbf 14 *
biagiomkr 0:f37bc13b9bbf 15 * Redistribution and use in source and binary forms, with or without modification,
biagiomkr 0:f37bc13b9bbf 16 * are permitted provided that the following conditions are met:
biagiomkr 0:f37bc13b9bbf 17 * 1. Redistributions of source code must retain the above copyright notice,
biagiomkr 0:f37bc13b9bbf 18 * this list of conditions and the following disclaimer.
biagiomkr 0:f37bc13b9bbf 19 * 2. Redistributions in binary form must reproduce the above copyright notice,
biagiomkr 0:f37bc13b9bbf 20 * this list of conditions and the following disclaimer in the documentation
biagiomkr 0:f37bc13b9bbf 21 * and/or other materials provided with the distribution.
biagiomkr 0:f37bc13b9bbf 22 * 3. Neither the name of STMicroelectronics nor the names of its contributors
biagiomkr 0:f37bc13b9bbf 23 * may be used to endorse or promote products derived from this software
biagiomkr 0:f37bc13b9bbf 24 * without specific prior written permission.
biagiomkr 0:f37bc13b9bbf 25 *
biagiomkr 0:f37bc13b9bbf 26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
biagiomkr 0:f37bc13b9bbf 27 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
biagiomkr 0:f37bc13b9bbf 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
biagiomkr 0:f37bc13b9bbf 29 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
biagiomkr 0:f37bc13b9bbf 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
biagiomkr 0:f37bc13b9bbf 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
biagiomkr 0:f37bc13b9bbf 32 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
biagiomkr 0:f37bc13b9bbf 33 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
biagiomkr 0:f37bc13b9bbf 34 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
biagiomkr 0:f37bc13b9bbf 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
biagiomkr 0:f37bc13b9bbf 36 *
biagiomkr 0:f37bc13b9bbf 37 ******************************************************************************
biagiomkr 0:f37bc13b9bbf 38 */
biagiomkr 0:f37bc13b9bbf 39
biagiomkr 0:f37bc13b9bbf 40 #include "STM32_LowPower.h"
biagiomkr 0:f37bc13b9bbf 41 #include "rtc_api_hal.h"
biagiomkr 0:f37bc13b9bbf 42
biagiomkr 0:f37bc13b9bbf 43 STM32_LowPower LowPower;
biagiomkr 0:f37bc13b9bbf 44
biagiomkr 0:f37bc13b9bbf 45 static RTC_HandleTypeDef RtcHandle;
biagiomkr 0:f37bc13b9bbf 46 static voidFuncPtr RTCUserCallback = NULL;
biagiomkr 0:f37bc13b9bbf 47 static void *callbackUserData = NULL;
biagiomkr 0:f37bc13b9bbf 48
biagiomkr 0:f37bc13b9bbf 49 void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
biagiomkr 0:f37bc13b9bbf 50 {
biagiomkr 0:f37bc13b9bbf 51 UNUSED(hrtc);
biagiomkr 0:f37bc13b9bbf 52
biagiomkr 0:f37bc13b9bbf 53 if (RTCUserCallback != NULL) {
biagiomkr 0:f37bc13b9bbf 54 RTCUserCallback(callbackUserData);
biagiomkr 0:f37bc13b9bbf 55 }
biagiomkr 0:f37bc13b9bbf 56 }
biagiomkr 0:f37bc13b9bbf 57
biagiomkr 0:f37bc13b9bbf 58 void RTC_IRQHandler(void)
biagiomkr 0:f37bc13b9bbf 59 {
biagiomkr 0:f37bc13b9bbf 60 HAL_RTCEx_WakeUpTimerIRQHandler(&RtcHandle);
biagiomkr 0:f37bc13b9bbf 61 }
biagiomkr 0:f37bc13b9bbf 62
biagiomkr 0:f37bc13b9bbf 63 #ifdef STM32G0xx
biagiomkr 0:f37bc13b9bbf 64 #define PWR_FLAG_WU PWR_FLAG_WUF
biagiomkr 0:f37bc13b9bbf 65 #endif
biagiomkr 0:f37bc13b9bbf 66
biagiomkr 0:f37bc13b9bbf 67 STM32_LowPower::STM32_LowPower()
biagiomkr 0:f37bc13b9bbf 68 {
biagiomkr 0:f37bc13b9bbf 69 _configured = false;
biagiomkr 0:f37bc13b9bbf 70 _rtc_wakeup = false;
biagiomkr 0:f37bc13b9bbf 71 _timer = 0;
biagiomkr 0:f37bc13b9bbf 72 }
biagiomkr 0:f37bc13b9bbf 73
biagiomkr 0:f37bc13b9bbf 74 /**
biagiomkr 0:f37bc13b9bbf 75 * @brief Initializes the low power mode
biagiomkr 0:f37bc13b9bbf 76 * @param None
biagiomkr 0:f37bc13b9bbf 77 * @retval None
biagiomkr 0:f37bc13b9bbf 78 */
biagiomkr 0:f37bc13b9bbf 79 void STM32_LowPower::init(void)
biagiomkr 0:f37bc13b9bbf 80 {
biagiomkr 0:f37bc13b9bbf 81 debug(DEBUG, "Starting STM32_LowPower::init()\n");
biagiomkr 0:f37bc13b9bbf 82 /* Initialize Low Power mode using STM32 HAL */
biagiomkr 0:f37bc13b9bbf 83 #if !defined(STM32H7xx) && !defined(STM32WBxx)
biagiomkr 0:f37bc13b9bbf 84 /* Enable Power Clock */
biagiomkr 0:f37bc13b9bbf 85 __HAL_RCC_PWR_CLK_ENABLE();
biagiomkr 0:f37bc13b9bbf 86 debug(DEBUG, "STM32_LowPower::init() -> __HAL_RCC_PWR_CLK_ENABLE()\n");
biagiomkr 0:f37bc13b9bbf 87 #endif
biagiomkr 0:f37bc13b9bbf 88 /* Allow access to Backup domain */
biagiomkr 0:f37bc13b9bbf 89 HAL_PWR_EnableBkUpAccess();
biagiomkr 0:f37bc13b9bbf 90 debug(DEBUG, "STM32_LowPower::init() -> HAL_PWR_EnableBkUpAccess()\n");
biagiomkr 0:f37bc13b9bbf 91
biagiomkr 0:f37bc13b9bbf 92 #ifdef __HAL_RCC_WAKEUPSTOP_CLK_CONFIG
biagiomkr 0:f37bc13b9bbf 93 /* Ensure that HSI is wake-up system clock */
biagiomkr 0:f37bc13b9bbf 94 __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI);
biagiomkr 0:f37bc13b9bbf 95 debug(DEBUG, "STM32_LowPower::init() -> __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI)\n");
biagiomkr 0:f37bc13b9bbf 96 #endif
biagiomkr 0:f37bc13b9bbf 97 /* Check if the system was resumed from StandBy mode */
biagiomkr 0:f37bc13b9bbf 98 if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB) != RESET) {
biagiomkr 0:f37bc13b9bbf 99 /* Clear Standby flag */
biagiomkr 0:f37bc13b9bbf 100 __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
biagiomkr 0:f37bc13b9bbf 101 debug(DEBUG, "STM32_LowPower::init() -> __HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB)\n");
biagiomkr 0:f37bc13b9bbf 102 }
biagiomkr 0:f37bc13b9bbf 103
biagiomkr 0:f37bc13b9bbf 104 /* Clear all related wakeup flags */
biagiomkr 0:f37bc13b9bbf 105 __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
biagiomkr 0:f37bc13b9bbf 106 debug(DEBUG, "STM32_LowPower::init() -> __HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU)\n");
biagiomkr 0:f37bc13b9bbf 107
biagiomkr 0:f37bc13b9bbf 108 /* start RTC */
biagiomkr 0:f37bc13b9bbf 109 set_time(0);
biagiomkr 0:f37bc13b9bbf 110
biagiomkr 0:f37bc13b9bbf 111 _configured = true;
biagiomkr 0:f37bc13b9bbf 112 debug(DEBUG, "Exiting STM32_LowPower::init()...\n");
biagiomkr 0:f37bc13b9bbf 113 }
biagiomkr 0:f37bc13b9bbf 114
biagiomkr 0:f37bc13b9bbf 115 /**
biagiomkr 0:f37bc13b9bbf 116 * @brief Enable the STM32 sleep mode.
biagiomkr 0:f37bc13b9bbf 117 * Exit this mode on interrupt using the attachInterruptWakeup() method
biagiomkr 0:f37bc13b9bbf 118 * or in timer_s seconds.
biagiomkr 0:f37bc13b9bbf 119 * @param reg: type of power regulator.
biagiomkr 0:f37bc13b9bbf 120 * @param timer_s: optional delay before leaving the sleep mode (default: 0).
biagiomkr 0:f37bc13b9bbf 121 * @retval None
biagiomkr 0:f37bc13b9bbf 122 */
biagiomkr 0:f37bc13b9bbf 123 void STM32_LowPower::sleep(STM32_RegulatorType reg, uint32_t timer_s)
biagiomkr 0:f37bc13b9bbf 124 {
biagiomkr 0:f37bc13b9bbf 125 debug(DEBUG, "Starting STM32_LowPower::sleep()...\n");
biagiomkr 0:f37bc13b9bbf 126
biagiomkr 0:f37bc13b9bbf 127 uint32_t regulator;
biagiomkr 0:f37bc13b9bbf 128
biagiomkr 0:f37bc13b9bbf 129 /* Enable STM32 Sleep Mode: regulator in main mode */
biagiomkr 0:f37bc13b9bbf 130 if (reg == STM32_MAIN_REGULATOR) {
biagiomkr 0:f37bc13b9bbf 131 regulator = PWR_MAINREGULATOR_ON;
biagiomkr 0:f37bc13b9bbf 132 debug(DEBUG, "STM32_LowPower::sleep() -> regulator: PWR_MAINREGULATOR_ON\n");
biagiomkr 0:f37bc13b9bbf 133 }
biagiomkr 0:f37bc13b9bbf 134 /* Enable STM32 Low-power Sleep Mode: regulator in low-power mode */
biagiomkr 0:f37bc13b9bbf 135 else if (reg == STM32_LOWPOWER_REGULATOR) {
biagiomkr 0:f37bc13b9bbf 136 regulator = PWR_LOWPOWERREGULATOR_ON;
biagiomkr 0:f37bc13b9bbf 137 debug(DEBUG, "STM32_LowPower::sleep() -> regulator: PWR_LOWPOWERREGULATOR_ON\n");
biagiomkr 0:f37bc13b9bbf 138 } else {
biagiomkr 0:f37bc13b9bbf 139 regulator = PWR_MAINREGULATOR_ON;
biagiomkr 0:f37bc13b9bbf 140 }
biagiomkr 0:f37bc13b9bbf 141
biagiomkr 0:f37bc13b9bbf 142 if (timer_s > 0) {
biagiomkr 0:f37bc13b9bbf 143 programRtcWakeUp(timer_s);
biagiomkr 0:f37bc13b9bbf 144 debug(DEBUG, "STM32_LowPower::sleep() -> programRtcWakeUp(timer_s)\n");
biagiomkr 0:f37bc13b9bbf 145 }
biagiomkr 0:f37bc13b9bbf 146 else if (_rtc_wakeup && (_timer > 0)) {
biagiomkr 0:f37bc13b9bbf 147 programRtcWakeUp(_timer);
biagiomkr 0:f37bc13b9bbf 148 debug(DEBUG, "STM32_LowPower::sleep() -> programRtcWakeUp(_timer)\n");
biagiomkr 0:f37bc13b9bbf 149 }
biagiomkr 0:f37bc13b9bbf 150
biagiomkr 0:f37bc13b9bbf 151 /*
biagiomkr 0:f37bc13b9bbf 152 * Suspend Tick increment to prevent wakeup by Systick interrupt.
biagiomkr 0:f37bc13b9bbf 153 * Otherwise the Systick interrupt will wake up the device within
biagiomkr 0:f37bc13b9bbf 154 * 1ms (HAL time base)
biagiomkr 0:f37bc13b9bbf 155 */
biagiomkr 0:f37bc13b9bbf 156 HAL_SuspendTick();
biagiomkr 0:f37bc13b9bbf 157 debug(DEBUG, "STM32_LowPower::sleep() -> HAL_SuspendTick()\n");
biagiomkr 0:f37bc13b9bbf 158
biagiomkr 0:f37bc13b9bbf 159 /* Enter Sleep Mode */
biagiomkr 0:f37bc13b9bbf 160 debug(DEBUG, "STM32_LowPower::sleep() -> HAL_PWR_EnterSLEEPMode()\n");
biagiomkr 0:f37bc13b9bbf 161 HAL_PWR_EnterSLEEPMode(regulator, PWR_SLEEPENTRY_WFI);
biagiomkr 0:f37bc13b9bbf 162
biagiomkr 0:f37bc13b9bbf 163 /* Resume Tick interrupt if disabled before switching into Sleep mode */
biagiomkr 0:f37bc13b9bbf 164 HAL_ResumeTick();
biagiomkr 0:f37bc13b9bbf 165 debug(DEBUG, "STM32_LowPower::sleep() -> HAL_ResumeTick()\n");
biagiomkr 0:f37bc13b9bbf 166
biagiomkr 0:f37bc13b9bbf 167 if ((timer_s > 0) || _rtc_wakeup) {
biagiomkr 0:f37bc13b9bbf 168 rtc_deactivate_wake_up_timer();
biagiomkr 0:f37bc13b9bbf 169 }
biagiomkr 0:f37bc13b9bbf 170
biagiomkr 0:f37bc13b9bbf 171 debug(DEBUG, "Exiting STM32_LowPower::sleep()...\n");
biagiomkr 0:f37bc13b9bbf 172 }
biagiomkr 0:f37bc13b9bbf 173
biagiomkr 0:f37bc13b9bbf 174 /**
biagiomkr 0:f37bc13b9bbf 175 * @brief Enable the STM32 stop mode.
biagiomkr 0:f37bc13b9bbf 176 * Exit this mode on interrupt using the attachInterruptWakeup() method
biagiomkr 0:f37bc13b9bbf 177 * or in timer_s seconds.
biagiomkr 0:f37bc13b9bbf 178 * @param reg: type of power regulator.
biagiomkr 0:f37bc13b9bbf 179 * @param timer_s: optional delay before leaving the stop mode (default: 0).
biagiomkr 0:f37bc13b9bbf 180 * @retval None
biagiomkr 0:f37bc13b9bbf 181 */
biagiomkr 0:f37bc13b9bbf 182 void STM32_LowPower::stop(STM32_RegulatorType reg, uint32_t timer_s)
biagiomkr 0:f37bc13b9bbf 183 {
biagiomkr 0:f37bc13b9bbf 184 debug(DEBUG, "Starting STM32_LowPower::stop()\n");
biagiomkr 0:f37bc13b9bbf 185
biagiomkr 0:f37bc13b9bbf 186 __disable_irq();
biagiomkr 0:f37bc13b9bbf 187 debug(DEBUG, "STM32_LowPower::stop() -> __disable_irq()\n");
biagiomkr 0:f37bc13b9bbf 188
biagiomkr 0:f37bc13b9bbf 189 uint32_t regulator;
biagiomkr 0:f37bc13b9bbf 190 /* Use regulator in main mode */
biagiomkr 0:f37bc13b9bbf 191 if (reg == STM32_MAIN_REGULATOR) {
biagiomkr 0:f37bc13b9bbf 192 regulator = PWR_MAINREGULATOR_ON;
biagiomkr 0:f37bc13b9bbf 193 debug(DEBUG, "STM32_LowPower::stop() -> regulator: PWR_MAINREGULATOR_ON\n");
biagiomkr 0:f37bc13b9bbf 194 }
biagiomkr 0:f37bc13b9bbf 195 /* Use regulator in low-power mode */
biagiomkr 0:f37bc13b9bbf 196 else if (reg == STM32_LOWPOWER_REGULATOR) {
biagiomkr 0:f37bc13b9bbf 197 regulator = PWR_LOWPOWERREGULATOR_ON;
biagiomkr 0:f37bc13b9bbf 198 debug(DEBUG, "STM32_LowPower::stop() -> regulator: PWR_LOWPOWERREGULATOR_ON\n");
biagiomkr 0:f37bc13b9bbf 199 } else {
biagiomkr 0:f37bc13b9bbf 200 regulator = PWR_LOWPOWERREGULATOR_ON;
biagiomkr 0:f37bc13b9bbf 201 }
biagiomkr 0:f37bc13b9bbf 202
biagiomkr 0:f37bc13b9bbf 203 if (timer_s > 0) {
biagiomkr 0:f37bc13b9bbf 204 programRtcWakeUp(timer_s);
biagiomkr 0:f37bc13b9bbf 205 debug(DEBUG, "STM32_LowPower::stop() -> programRtcWakeUp(timer_s)\n");
biagiomkr 0:f37bc13b9bbf 206 }
biagiomkr 0:f37bc13b9bbf 207 else if (_rtc_wakeup && (_timer > 0)) {
biagiomkr 0:f37bc13b9bbf 208 programRtcWakeUp(_timer);
biagiomkr 0:f37bc13b9bbf 209 debug(DEBUG, "STM32_LowPower::stop() -> programRtcWakeUp(_timer)\n");
biagiomkr 0:f37bc13b9bbf 210 }
biagiomkr 0:f37bc13b9bbf 211
biagiomkr 0:f37bc13b9bbf 212 #if defined(STM32L0xx) || defined(STM32L1xx)
biagiomkr 0:f37bc13b9bbf 213 /* Enable Ultra low power mode */
biagiomkr 0:f37bc13b9bbf 214 HAL_PWREx_EnableUltraLowPower();
biagiomkr 0:f37bc13b9bbf 215 debug(DEBUG, "STM32_LowPower::stop() -> HAL_PWREx_EnableUltraLowPower()\n");
biagiomkr 0:f37bc13b9bbf 216
biagiomkr 0:f37bc13b9bbf 217 /* Enable the fast wake up from Ultra low power mode */
biagiomkr 0:f37bc13b9bbf 218 HAL_PWREx_EnableFastWakeUp();
biagiomkr 0:f37bc13b9bbf 219 debug(DEBUG, "STM32_LowPower::stop() -> HAL_PWREx_EnableFastWakeUp()\n");
biagiomkr 0:f37bc13b9bbf 220 #endif
biagiomkr 0:f37bc13b9bbf 221 #ifdef __HAL_RCC_WAKEUPSTOP_CLK_CONFIG
biagiomkr 0:f37bc13b9bbf 222 /* Select HSI as system clock source after Wake Up from Stop mode */
biagiomkr 0:f37bc13b9bbf 223 __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI);
biagiomkr 0:f37bc13b9bbf 224 debug(DEBUG, "STM32_LowPower::stop() -> __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI)\n");
biagiomkr 0:f37bc13b9bbf 225 #endif
biagiomkr 0:f37bc13b9bbf 226
biagiomkr 0:f37bc13b9bbf 227 /* Enter Stop mode */
biagiomkr 0:f37bc13b9bbf 228 debug(DEBUG, "STM32_LowPower::stop() -> HAL_PWR_EnterSTOPMode()\n");
biagiomkr 0:f37bc13b9bbf 229 HAL_Delay(20);
biagiomkr 0:f37bc13b9bbf 230 HAL_PWR_EnterSTOPMode(regulator, PWR_STOPENTRY_WFI);
biagiomkr 0:f37bc13b9bbf 231
biagiomkr 0:f37bc13b9bbf 232 /* Exit Stop mode reset clocks */
biagiomkr 0:f37bc13b9bbf 233 SetSysClock();
biagiomkr 0:f37bc13b9bbf 234
biagiomkr 0:f37bc13b9bbf 235 __enable_irq();
biagiomkr 0:f37bc13b9bbf 236 debug(DEBUG, "STM32_LowPower::stop() -> __enable_irq()\n");
biagiomkr 0:f37bc13b9bbf 237
biagiomkr 0:f37bc13b9bbf 238 HAL_Delay(100);
biagiomkr 0:f37bc13b9bbf 239 debug(DEBUG, "STM32_LowPower::stop() -> SetSysClock()\n");
biagiomkr 0:f37bc13b9bbf 240
biagiomkr 0:f37bc13b9bbf 241 if ((timer_s > 0) || _rtc_wakeup) {
biagiomkr 0:f37bc13b9bbf 242 rtc_deactivate_wake_up_timer();
biagiomkr 0:f37bc13b9bbf 243 }
biagiomkr 0:f37bc13b9bbf 244
biagiomkr 0:f37bc13b9bbf 245 debug(DEBUG, "Exiting STM32_LowPower::stop()...\n");
biagiomkr 0:f37bc13b9bbf 246 }
biagiomkr 0:f37bc13b9bbf 247
biagiomkr 0:f37bc13b9bbf 248 /**
biagiomkr 0:f37bc13b9bbf 249 * @brief Enable the STM32 shutdown or standby mode.
biagiomkr 0:f37bc13b9bbf 250 * Exit this mode on interrupt using the attachInterruptWakeup() method
biagiomkr 0:f37bc13b9bbf 251 * or in timer_s seconds.
biagiomkr 0:f37bc13b9bbf 252 * @param timer_s: optional delay before leaving the standby mode (default: 0).
biagiomkr 0:f37bc13b9bbf 253 * @retval None
biagiomkr 0:f37bc13b9bbf 254 */
biagiomkr 0:f37bc13b9bbf 255 void STM32_LowPower::standby(uint32_t timer_s)
biagiomkr 0:f37bc13b9bbf 256 {
biagiomkr 0:f37bc13b9bbf 257 __disable_irq();
biagiomkr 0:f37bc13b9bbf 258 debug(DEBUG, "STM32_LowPower::standby() -> __disable_irq()\n");
biagiomkr 0:f37bc13b9bbf 259
biagiomkr 0:f37bc13b9bbf 260 debug(DEBUG, "Starting STM32_LowPower::standby()...\n");
biagiomkr 0:f37bc13b9bbf 261 if (timer_s > 0) {
biagiomkr 0:f37bc13b9bbf 262 programRtcWakeUp(timer_s);
biagiomkr 0:f37bc13b9bbf 263 debug(DEBUG, "STM32_LowPower::standby() -> programRtcWakeUp(timer_s)\n");
biagiomkr 0:f37bc13b9bbf 264 }
biagiomkr 0:f37bc13b9bbf 265 else if (_rtc_wakeup && (_timer > 0)) {
biagiomkr 0:f37bc13b9bbf 266 programRtcWakeUp(_timer);
biagiomkr 0:f37bc13b9bbf 267 debug(DEBUG, "STM32_LowPower::standby() -> programRtcWakeUp(_timer)\n");
biagiomkr 0:f37bc13b9bbf 268 }
biagiomkr 0:f37bc13b9bbf 269
biagiomkr 0:f37bc13b9bbf 270 #if defined(STM32L0xx) || defined(STM32L1xx)
biagiomkr 0:f37bc13b9bbf 271 /* Enable Ultra low power mode */
biagiomkr 0:f37bc13b9bbf 272 HAL_PWREx_EnableUltraLowPower();
biagiomkr 0:f37bc13b9bbf 273 debug(DEBUG, "STM32_LowPower::standby() -> HAL_PWREx_EnableUltraLowPower()\n");
biagiomkr 0:f37bc13b9bbf 274
biagiomkr 0:f37bc13b9bbf 275 /* Enable the fast wake up from Ultra low power mode */
biagiomkr 0:f37bc13b9bbf 276 HAL_PWREx_EnableFastWakeUp();
biagiomkr 0:f37bc13b9bbf 277 debug(DEBUG, "STM32_LowPower::standby() -> HAL_PWREx_EnableFastWakeUp()\n");
biagiomkr 0:f37bc13b9bbf 278 #endif
biagiomkr 0:f37bc13b9bbf 279 debug(DEBUG, "STM32_LowPower::standby() -> HAL_PWR_EnterSTANDBYMode()\n");
biagiomkr 0:f37bc13b9bbf 280 HAL_PWR_EnterSTANDBYMode();
biagiomkr 0:f37bc13b9bbf 281 }
biagiomkr 0:f37bc13b9bbf 282
biagiomkr 0:f37bc13b9bbf 283 /**
biagiomkr 0:f37bc13b9bbf 284 * @brief Enable GPIO pin in interrupt mode. If the pin is a wakeup pin, it is
biagiomkr 0:f37bc13b9bbf 285 * configured as wakeup source.
biagiomkr 0:f37bc13b9bbf 286 * @param pin: pin name (PX_Y, where X = GPIO port and Y = GPIO number)
biagiomkr 0:f37bc13b9bbf 287 * @param callback: pointer to callback function.
biagiomkr 0:f37bc13b9bbf 288 * @param mode: interrupt mode (IT_MODE_RISING, IT_MODE_FALLING, IT_MODE_RISING_FALLING)
biagiomkr 0:f37bc13b9bbf 289 * @retval None
biagiomkr 0:f37bc13b9bbf 290 */
biagiomkr 0:f37bc13b9bbf 291 void STM32_LowPower::attachInterruptWakeup(PinName pin, voidFuncPtrVoid callback,
biagiomkr 0:f37bc13b9bbf 292 Interrupt_Mode mode)
biagiomkr 0:f37bc13b9bbf 293 {
biagiomkr 0:f37bc13b9bbf 294 debug(DEBUG, "Starting STM32_LowPower::attachInterruptWakeup()...\n");
biagiomkr 0:f37bc13b9bbf 295 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> pin: %u\n", pin);
biagiomkr 0:f37bc13b9bbf 296 _wakeupPin = new InterruptIn(pin);
biagiomkr 0:f37bc13b9bbf 297
biagiomkr 0:f37bc13b9bbf 298 switch (mode) {
biagiomkr 0:f37bc13b9bbf 299 case IT_MODE_RISING :
biagiomkr 0:f37bc13b9bbf 300 _wakeupPin->rise(callback);
biagiomkr 0:f37bc13b9bbf 301 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wakeupPin->rise(callback)\n");
biagiomkr 0:f37bc13b9bbf 302 break;
biagiomkr 0:f37bc13b9bbf 303 case IT_MODE_FALLING :
biagiomkr 0:f37bc13b9bbf 304 _wakeupPin->fall(callback);
biagiomkr 0:f37bc13b9bbf 305 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wakeupPin->fall(callback)\n");
biagiomkr 0:f37bc13b9bbf 306 break;
biagiomkr 0:f37bc13b9bbf 307 case IT_MODE_RISING_FALLING :
biagiomkr 0:f37bc13b9bbf 308 default:
biagiomkr 0:f37bc13b9bbf 309 _wakeupPin->rise(callback);
biagiomkr 0:f37bc13b9bbf 310 _wakeupPin->fall(callback);
biagiomkr 0:f37bc13b9bbf 311 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wakeupPin->rise & fall\n");
biagiomkr 0:f37bc13b9bbf 312 break;
biagiomkr 0:f37bc13b9bbf 313 }
biagiomkr 0:f37bc13b9bbf 314
biagiomkr 0:f37bc13b9bbf 315 /* If Gpio is a Wake up pin activate it in order to wake up the STM32 MCU */
biagiomkr 0:f37bc13b9bbf 316 #if !defined(PWR_WAKEUP_PIN1_HIGH)
biagiomkr 0:f37bc13b9bbf 317 UNUSED(mode);
biagiomkr 0:f37bc13b9bbf 318 #endif
biagiomkr 0:f37bc13b9bbf 319 uint32_t wkup_pin;
biagiomkr 0:f37bc13b9bbf 320 if (pin != NC) {
biagiomkr 0:f37bc13b9bbf 321 switch (pin) {
biagiomkr 0:f37bc13b9bbf 322 #ifdef PWR_WAKEUP_PIN1
biagiomkr 0:f37bc13b9bbf 323
biagiomkr 0:f37bc13b9bbf 324 #if defined(TARGET_DISCO_F100RB) || defined(TARGET_DISCO_F407VG) || \
biagiomkr 0:f37bc13b9bbf 325 defined(TARGET_DISCO_F401VC) || defined(TARGET_DISCO_F429ZI) || \
biagiomkr 0:f37bc13b9bbf 326 defined(TARGET_NUCLEO_F103RB) || defined(TARGET_NUCLEO_F207ZG) || \
biagiomkr 0:f37bc13b9bbf 327 defined(TARGET_NUCLEO_F401RE) || defined(TARGET_NUCLEO_F411RE) || \
biagiomkr 0:f37bc13b9bbf 328 defined(TARGET_NUCLEO_F429ZI) || defined(TARGET_NUCLEO_F439ZI) || \
biagiomkr 0:f37bc13b9bbf 329 defined(TARGET_NUCLEO_F469NI) || defined(TARGET_MTB_STM_S2LP)
biagiomkr 0:f37bc13b9bbf 330 case SYS_WKUP :
biagiomkr 0:f37bc13b9bbf 331 #else
biagiomkr 0:f37bc13b9bbf 332 case SYS_WKUP1 :
biagiomkr 0:f37bc13b9bbf 333 #endif
biagiomkr 0:f37bc13b9bbf 334 wkup_pin = PWR_WAKEUP_PIN1;
biagiomkr 0:f37bc13b9bbf 335 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN1.\n");
biagiomkr 0:f37bc13b9bbf 336 #ifdef PWR_WAKEUP_PIN1_HIGH
biagiomkr 0:f37bc13b9bbf 337 if (mode != IT_MODE_RISING) {
biagiomkr 0:f37bc13b9bbf 338 wkup_pin = PWR_WAKEUP_PIN1_LOW;
biagiomkr 0:f37bc13b9bbf 339 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN1_LOW.\n");
biagiomkr 0:f37bc13b9bbf 340 }
biagiomkr 0:f37bc13b9bbf 341 #endif
biagiomkr 0:f37bc13b9bbf 342 break;
biagiomkr 0:f37bc13b9bbf 343 #endif /* PWR_WAKEUP_PIN1 */
biagiomkr 0:f37bc13b9bbf 344 #ifdef PWR_WAKEUP_PIN2
biagiomkr 0:f37bc13b9bbf 345 case SYS_WKUP2 :
biagiomkr 0:f37bc13b9bbf 346 wkup_pin = PWR_WAKEUP_PIN2;
biagiomkr 0:f37bc13b9bbf 347 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN2.\n");
biagiomkr 0:f37bc13b9bbf 348 #ifdef PWR_WAKEUP_PIN2_HIGH
biagiomkr 0:f37bc13b9bbf 349 if (mode != IT_MODE_RISING) {
biagiomkr 0:f37bc13b9bbf 350 wkup_pin = PWR_WAKEUP_PIN2_LOW;
biagiomkr 0:f37bc13b9bbf 351 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN2_LOW\n");
biagiomkr 0:f37bc13b9bbf 352 }
biagiomkr 0:f37bc13b9bbf 353 #endif
biagiomkr 0:f37bc13b9bbf 354 break;
biagiomkr 0:f37bc13b9bbf 355 #endif /* PWR_WAKEUP_PIN2 */
biagiomkr 0:f37bc13b9bbf 356 #ifdef PWR_WAKEUP_PIN3
biagiomkr 0:f37bc13b9bbf 357 case SYS_WKUP3 :
biagiomkr 0:f37bc13b9bbf 358 wkup_pin = PWR_WAKEUP_PIN3;
biagiomkr 0:f37bc13b9bbf 359 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN3\n");
biagiomkr 0:f37bc13b9bbf 360 #ifdef PWR_WAKEUP_PIN3_HIGH
biagiomkr 0:f37bc13b9bbf 361 if (mode != IT_MODE_RISING) {
biagiomkr 0:f37bc13b9bbf 362 wkup_pin = PWR_WAKEUP_PIN3_LOW;
biagiomkr 0:f37bc13b9bbf 363 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN3_LOW\n");
biagiomkr 0:f37bc13b9bbf 364 }
biagiomkr 0:f37bc13b9bbf 365 #endif
biagiomkr 0:f37bc13b9bbf 366 break;
biagiomkr 0:f37bc13b9bbf 367 #endif /* PWR_WAKEUP_PIN3 */
biagiomkr 0:f37bc13b9bbf 368 #ifdef PWR_WAKEUP_PIN4
biagiomkr 0:f37bc13b9bbf 369 case SYS_WKUP4 :
biagiomkr 0:f37bc13b9bbf 370 wkup_pin = PWR_WAKEUP_PIN4;
biagiomkr 0:f37bc13b9bbf 371 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN4\n");
biagiomkr 0:f37bc13b9bbf 372 #ifdef PWR_WAKEUP_PIN4_HIGH
biagiomkr 0:f37bc13b9bbf 373 if (mode != IT_MODE_RISING) {
biagiomkr 0:f37bc13b9bbf 374 wkup_pin = PWR_WAKEUP_PIN4_LOW;
biagiomkr 0:f37bc13b9bbf 375 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN4_LOW\n");
biagiomkr 0:f37bc13b9bbf 376 }
biagiomkr 0:f37bc13b9bbf 377 #endif
biagiomkr 0:f37bc13b9bbf 378 break;
biagiomkr 0:f37bc13b9bbf 379 #endif /* PWR_WAKEUP_PIN4 */
biagiomkr 0:f37bc13b9bbf 380 #ifdef PWR_WAKEUP_PIN5
biagiomkr 0:f37bc13b9bbf 381 case SYS_WKUP5 :
biagiomkr 0:f37bc13b9bbf 382 wkup_pin = PWR_WAKEUP_PIN5;
biagiomkr 0:f37bc13b9bbf 383 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN5\n");
biagiomkr 0:f37bc13b9bbf 384 #ifdef PWR_WAKEUP_PIN5_HIGH
biagiomkr 0:f37bc13b9bbf 385 if (mode != IT_MODE_RISING) {
biagiomkr 0:f37bc13b9bbf 386 wkup_pin = PWR_WAKEUP_PIN5_LOW;
biagiomkr 0:f37bc13b9bbf 387 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN5_LOW\n");
biagiomkr 0:f37bc13b9bbf 388 }
biagiomkr 0:f37bc13b9bbf 389 #endif
biagiomkr 0:f37bc13b9bbf 390 break;
biagiomkr 0:f37bc13b9bbf 391 #endif /* PWR_WAKEUP_PIN5 */
biagiomkr 0:f37bc13b9bbf 392 #ifdef PWR_WAKEUP_PIN6
biagiomkr 0:f37bc13b9bbf 393 case SYS_WKUP6 :
biagiomkr 0:f37bc13b9bbf 394 wkup_pin = PWR_WAKEUP_PIN6;
biagiomkr 0:f37bc13b9bbf 395 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN6\n");
biagiomkr 0:f37bc13b9bbf 396 #ifdef PWR_WAKEUP_PIN6_HIGH
biagiomkr 0:f37bc13b9bbf 397 if (mode != IT_MODE_RISING) {
biagiomkr 0:f37bc13b9bbf 398 wkup_pin = PWR_WAKEUP_PIN6_LOW;
biagiomkr 0:f37bc13b9bbf 399 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN6_LOW\n");
biagiomkr 0:f37bc13b9bbf 400 }
biagiomkr 0:f37bc13b9bbf 401 #endif
biagiomkr 0:f37bc13b9bbf 402 break;
biagiomkr 0:f37bc13b9bbf 403 #endif /* PWR_WAKEUP_PIN6 */
biagiomkr 0:f37bc13b9bbf 404 #ifdef PWR_WAKEUP_PIN7
biagiomkr 0:f37bc13b9bbf 405 case SYS_WKUP7 :
biagiomkr 0:f37bc13b9bbf 406 wkup_pin = PWR_WAKEUP_PIN7;
biagiomkr 0:f37bc13b9bbf 407 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN7\n");
biagiomkr 0:f37bc13b9bbf 408 break;
biagiomkr 0:f37bc13b9bbf 409 #endif /* PWR_WAKEUP_PIN7 */
biagiomkr 0:f37bc13b9bbf 410 #ifdef PWR_WAKEUP_PIN8
biagiomkr 0:f37bc13b9bbf 411 case SYS_WKUP8 :
biagiomkr 0:f37bc13b9bbf 412 wkup_pin = PWR_WAKEUP_PIN8;
biagiomkr 0:f37bc13b9bbf 413 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN7\n");
biagiomkr 0:f37bc13b9bbf 414 break;
biagiomkr 0:f37bc13b9bbf 415 #endif /* PWR_WAKEUP_PIN8 */
biagiomkr 0:f37bc13b9bbf 416 default :
biagiomkr 0:f37bc13b9bbf 417 wkup_pin = PWR_WAKEUP_PIN1;
biagiomkr 0:f37bc13b9bbf 418 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN1 (default case)\n");
biagiomkr 0:f37bc13b9bbf 419 #ifdef PWR_WAKEUP_PIN1_HIGH
biagiomkr 0:f37bc13b9bbf 420 if (mode != IT_MODE_RISING) {
biagiomkr 0:f37bc13b9bbf 421 wkup_pin = PWR_WAKEUP_PIN1_LOW;
biagiomkr 0:f37bc13b9bbf 422 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> wkup_pin = PWR_WAKEUP_PIN1_LOW (default case)\n");
biagiomkr 0:f37bc13b9bbf 423 }
biagiomkr 0:f37bc13b9bbf 424 #endif
biagiomkr 0:f37bc13b9bbf 425 break;
biagiomkr 0:f37bc13b9bbf 426 }
biagiomkr 0:f37bc13b9bbf 427
biagiomkr 0:f37bc13b9bbf 428 HAL_PWR_EnableWakeUpPin(wkup_pin);
biagiomkr 0:f37bc13b9bbf 429 debug(DEBUG, "STM32_LowPower::attachInterruptWakeup() -> HAL_PWR_EnableWakeUpPin()\n");
biagiomkr 0:f37bc13b9bbf 430 debug(DEBUG, "Exiting STM32_LowPower::attachInterruptWakeup()...\n");
biagiomkr 0:f37bc13b9bbf 431 }
biagiomkr 0:f37bc13b9bbf 432 }
biagiomkr 0:f37bc13b9bbf 433
biagiomkr 0:f37bc13b9bbf 434 /**
biagiomkr 0:f37bc13b9bbf 435 * @brief Configure the RTC WakeUp Interrupt.
biagiomkr 0:f37bc13b9bbf 436 * @param millis: time (in seconds) to generate a RTC WakeUp event.
biagiomkr 0:f37bc13b9bbf 437 * @retval None
biagiomkr 0:f37bc13b9bbf 438 */
biagiomkr 0:f37bc13b9bbf 439 void STM32_LowPower::programRtcWakeUp(uint32_t timer_s)
biagiomkr 0:f37bc13b9bbf 440 {
biagiomkr 0:f37bc13b9bbf 441 uint32_t rtc_clock;
biagiomkr 0:f37bc13b9bbf 442
biagiomkr 0:f37bc13b9bbf 443 core_util_critical_section_enter();
biagiomkr 0:f37bc13b9bbf 444 debug(DEBUG, "STM32_LowPower::programRtcWakeUp() -> core_util_critical_section_enter()\n");
biagiomkr 0:f37bc13b9bbf 445
biagiomkr 0:f37bc13b9bbf 446 rtc_clock = RTC_WAKEUPCLOCK_CK_SPRE_16BITS;
biagiomkr 0:f37bc13b9bbf 447
biagiomkr 0:f37bc13b9bbf 448 /* Clear wakeup flag, just in case. */
biagiomkr 0:f37bc13b9bbf 449 SET_BIT(PWR->CR, PWR_CR_CWUF);
biagiomkr 0:f37bc13b9bbf 450
biagiomkr 0:f37bc13b9bbf 451 /* HAL_RTCEx_SetWakeUpTimer_IT will assert that timer_s is 0xFFFF at max */
biagiomkr 0:f37bc13b9bbf 452 if (timer_s > 0xFFFF) {
biagiomkr 0:f37bc13b9bbf 453 timer_s -= 0x10000;
biagiomkr 0:f37bc13b9bbf 454 rtc_clock = RTC_WAKEUPCLOCK_CK_SPRE_17BITS;
biagiomkr 0:f37bc13b9bbf 455 }
biagiomkr 0:f37bc13b9bbf 456
biagiomkr 0:f37bc13b9bbf 457 RtcHandle.Instance = RTC;
biagiomkr 0:f37bc13b9bbf 458
biagiomkr 0:f37bc13b9bbf 459 HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, timer_s, rtc_clock);
biagiomkr 0:f37bc13b9bbf 460 debug(DEBUG, "STM32_LowPower::programRtcWakeUp() -> HAL_RTCEx_SetWakeUpTimer_IT()\n");
biagiomkr 0:f37bc13b9bbf 461
biagiomkr 0:f37bc13b9bbf 462 NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)RTC_IRQHandler);
biagiomkr 0:f37bc13b9bbf 463 NVIC_EnableIRQ(RTC_WKUP_IRQn);
biagiomkr 0:f37bc13b9bbf 464
biagiomkr 0:f37bc13b9bbf 465 core_util_critical_section_exit();
biagiomkr 0:f37bc13b9bbf 466 debug(DEBUG, "STM32_LowPower::programRtcWakeUp() -> core_util_critical_section_exit()\n");
biagiomkr 0:f37bc13b9bbf 467 }
biagiomkr 0:f37bc13b9bbf 468
biagiomkr 0:f37bc13b9bbf 469 /**
biagiomkr 0:f37bc13b9bbf 470 * @brief Attach a callback to a RTC WakeUp event.
biagiomkr 0:f37bc13b9bbf 471 * @param callback: callback function called when leaving the low power mode.
biagiomkr 0:f37bc13b9bbf 472 * @param data: optional pointer to callback data parameters (default NULL).
biagiomkr 0:f37bc13b9bbf 473 * @retval None
biagiomkr 0:f37bc13b9bbf 474 */
biagiomkr 0:f37bc13b9bbf 475 void STM32_LowPower::enableWakeupFromRTC(voidFuncPtr callback, void *data,
biagiomkr 0:f37bc13b9bbf 476 uint32_t timer_s)
biagiomkr 0:f37bc13b9bbf 477 {
biagiomkr 0:f37bc13b9bbf 478 _rtc_wakeup = true;
biagiomkr 0:f37bc13b9bbf 479 if (timer_s > 0) {
biagiomkr 0:f37bc13b9bbf 480 _timer = timer_s;
biagiomkr 0:f37bc13b9bbf 481 }
biagiomkr 0:f37bc13b9bbf 482 RTCUserCallback = callback;
biagiomkr 0:f37bc13b9bbf 483 callbackUserData = data;
biagiomkr 0:f37bc13b9bbf 484 }