1 /**
2   ******************************************************************************
3   * @file    stm32c0xx_hal_pwr.c
4   * @author  MCD Application Team
5   * @brief   PWR HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the Power Controller (PWR) peripheral:
8   *           + Initialization/de-initialization functions
9   *           + Peripheral Control functions
10   *
11   ******************************************************************************
12   * @attention
13   *
14   * Copyright (c) 2022 STMicroelectronics.
15   * All rights reserved.
16   *
17   * This software is licensed under terms that can be found in the LICENSE file
18   * in the root directory of this software component.
19   * If no LICENSE file comes with this software, it is provided AS-IS.
20   *
21   ******************************************************************************
22   */
23 
24 /* Includes ------------------------------------------------------------------*/
25 #include "stm32c0xx_hal.h"
26 
27 /** @addtogroup STM32C0xx_HAL_Driver
28   * @{
29   */
30 
31 /** @addtogroup PWR
32   * @{
33   */
34 
35 #ifdef HAL_PWR_MODULE_ENABLED
36 
37 /* Private typedef -----------------------------------------------------------*/
38 /* Private define ------------------------------------------------------------*/
39 /** @defgroup PWR_Private_Defines PWR Private Defines
40   * @{
41   */
42 
43 /**
44   * @}
45   */
46 
47 /* Private macro -------------------------------------------------------------*/
48 /* Private variables ---------------------------------------------------------*/
49 /* Private function prototypes -----------------------------------------------*/
50 /* Exported functions --------------------------------------------------------*/
51 /** @addtogroup PWR_Exported_Functions  PWR Exported Functions
52   * @{
53   */
54 
55 /** @addtogroup PWR_Exported_Functions_Group1  Initialization and de-initialization functions
56   * @brief  Initialization and de-initialization functions
57   *
58 @verbatim
59  ===============================================================================
60               ##### Initialization and de-initialization functions #####
61  ===============================================================================
62     [..]
63 
64 @endverbatim
65   * @{
66   */
67 
68 /**
69   * @brief  Deinitialize the HAL PWR peripheral registers to their default reset
70             values.
71   * @retval None
72   */
HAL_PWR_DeInit(void)73 void HAL_PWR_DeInit(void)
74 {
75   __HAL_RCC_PWR_FORCE_RESET();
76   __HAL_RCC_PWR_RELEASE_RESET();
77 }
78 
79 /**
80   * @}
81   */
82 
83 /** @addtogroup PWR_Exported_Functions_Group2  Peripheral Control functions
84   *  @brief Low Power modes configuration functions
85   *
86 @verbatim
87 
88  ===============================================================================
89                  ##### Peripheral Control functions #####
90  ===============================================================================
91 
92     [..]
93 
94     *** WakeUp pin configuration ***
95     ================================
96     [..]
97       (+) WakeUp pins are used to wakeup the system from Standby mode or
98           Shutdown mode. WakeUp pins polarity can be set to configure event
99           detection on high level (rising edge) or low level (falling edge).
100 
101     *** Low Power mode configuration ***
102     =====================================
103     [..]
104       The devices feature 4 low-power modes:
105       (+) Sleep mode: Cortex-M0+ core stopped, peripherals kept running,
106           regulator is main mode.
107       (+) Stop 0 mode: all clocks are stopped except LSI and LSE, regulator is
108            main mode.
109       (+) Standby mode: all clocks are stopped except LSI and LSE, regulator is
110           disable.
111       (+) Shutdown mode: all clocks are stopped except LSE, regulator is
112           disable.
113 
114 
115    *** Sleep mode ***
116    =========================================
117     [..]
118       (+) Entry:
119           The Sleep is entered through HAL_PWR_EnterSLEEPMode() API specifying
120       the main regulator per default and if exit is interrupt or event
121           triggered.
122           (++) PWR_MAINREGULATOR_ON: Sleep mode (regulator in main mode).
123           (++) PWR_SLEEPENTRY_WFI: Core enters sleep mode with WFI instruction
124           (++) PWR_SLEEPENTRY_WFE: Core enters sleep mode with WFE instruction
125       (+) WFI Exit:
126         (++) Any interrupt enabled in nested vectored interrupt controller (NVIC)
127       (+) WFE Exit:
128         (++) Any wakeup event if cortex is configured with SEVONPEND = 0
129         (++) Interrupt even when disabled in NVIC if cortex is configured with
130              SEVONPEND = 1
131 
132    *** Stop 0 mode ***
133    =============================
134     [..]
135       (+) Entry:
136           The Stop modes are entered through the following APIs:
137           (++) HAL_PWR_EnterSTOPMode() with following settings:
138               (+++) PWR_MAINREGULATOR_ON to enter STOP0 mode.
139       (+) Exit (interrupt or event-triggered, specified when entering STOP mode):
140           (++) PWR_STOPENTRY_WFI: enter Stop mode with WFI instruction
141           (++) PWR_STOPENTRY_WFE: enter Stop mode with WFE instruction
142       (+) WFI Exit:
143           (++) Any EXTI line (internal or external) configured in interrupt mode
144                with corresponding interrupt enable in NVIC
145       (+) WFE Exit:
146           (++) Any EXTI line (internal or external) configured in event mode if
147                cortex is configured with SEVONPEND = 0
148           (++) Any EXTI line configured in interrupt mode (even if the
149                corresponding EXTI Interrupt vector is disabled in the NVIC) if
150                cortex is configured with SEVONPEND = 0. The interrupt source can
151                be external interrupts or peripherals with wakeup capability.
152 
153    *** Standby mode ***
154    ====================
155     [..]
156       (+) Entry:
157           (++) The Standby mode is entered through HAL_PWR_EnterSTANDBYMode() API, by
158                setting SLEEPDEEP in Cortex control register.
159       (+) Exit:
160           (++) WKUP pin edge detection, RTC event (alarm, timestamp),
161                LSE CSS detection, reset on NRST pin, IWDG reset & BOR reset.
162     [..] Exiting Standby generates a power reset: Cortex is reset and execute
163          Reset handler vector, all registers in the Vcore domain are set to
164          their reset value. Registers outside the VCORE domain (RTC, WKUP, IWDG,
165          and Standby/Shutdown modes control) are not impacted.
166 
167     *** Shutdown mode ***
168    ======================
169     [..]
170       In Shutdown mode,
171         voltage regulator is disabled, all clocks are off except LSE, RRS bit is
172         cleared. SRAM and registers contents are lost except for backup domain
173         registers.
174       (+) Entry:
175           (++) The Shutdown mode is entered through HAL_PWREx_EnterSHUTDOWNMode() API,
176                by setting SLEEPDEEP in Cortex control register.
177       (+) Exit:
178           (++) WKUP pin edge detection, RTC event (alarm, timestamp),
179                LSE CSS detection, reset on NRST pin.
180     [..] Exiting Shutdown generates a brown out reset: Cortex is reset and execute
181          Reset handler vector, all registers are set to their reset value but ones
182          in backup domain.
183 
184 @endverbatim
185   * @{
186   */
187 
188 
189 /**
190   * @brief  Enable the WakeUp PINx functionality.
191   * @param  WakeUpPinPolarity Specifies which Wake-Up pin to enable.
192   *         This parameter can be one of the following legacy values which set
193   *         the default polarity i.e. detection on high level (rising edge):
194   *           @arg @ref PWR_WAKEUP_PIN1, PWR_WAKEUP_PIN2, PWR_WAKEUP_PIN3,
195   *                PWR_WAKEUP_PIN4, PWR_WAKEUP_PIN6
196   *         or one of the following value where the user can explicitly specify
197   *         the enabled pin and the chosen polarity:
198   *           @arg @ref PWR_WAKEUP_PIN1_HIGH or PWR_WAKEUP_PIN1_LOW
199   *           @arg @ref PWR_WAKEUP_PIN2_HIGH or PWR_WAKEUP_PIN2_LOW
200   *           @arg @ref PWR_WAKEUP_PIN3_HIGH or PWR_WAKEUP_PIN3_LOW
201   *           @arg @ref PWR_WAKEUP_PIN4_HIGH or PWR_WAKEUP_PIN4_LOW
202   *           @arg @ref PWR_WAKEUP_PIN6_HIGH or PWR_WAKEUP_PIN6_LOW
203   * @note  PWR_WAKEUP_PINx and PWR_WAKEUP_PINx_HIGH are equivalent.
204   * @retval None
205   */
HAL_PWR_EnableWakeUpPin(uint32_t WakeUpPinPolarity)206 void HAL_PWR_EnableWakeUpPin(uint32_t WakeUpPinPolarity)
207 {
208   assert_param(IS_PWR_WAKEUP_PIN(WakeUpPinPolarity));
209 
210   /* Specifies the Wake-Up pin polarity for the event detection
211     (rising or falling edge) */
212   MODIFY_REG(PWR->CR4, (PWR_CR4_WP & WakeUpPinPolarity), (WakeUpPinPolarity >> PWR_WUP_POLARITY_SHIFT));
213 
214   /* Enable wake-up pin */
215   SET_BIT(PWR->CR3, (PWR_CR3_EWUP & WakeUpPinPolarity));
216 }
217 
218 
219 /**
220   * @brief  Disable the WakeUp PINx functionality.
221   * @param  WakeUpPinx Specifies the Power Wake-Up pin to disable.
222   *         This parameter can be one of the following values:
223   *           @arg @ref PWR_WAKEUP_PIN1, PWR_WAKEUP_PIN2, PWR_WAKEUP_PIN4,
224   *                PWR_WAKEUP_PIN6
225   * @retval None
226   */
HAL_PWR_DisableWakeUpPin(uint32_t WakeUpPinx)227 void HAL_PWR_DisableWakeUpPin(uint32_t WakeUpPinx)
228 {
229   assert_param(IS_PWR_WAKEUP_PIN(WakeUpPinx));
230 
231   CLEAR_BIT(PWR->CR3, (PWR_CR3_EWUP & WakeUpPinx));
232 }
233 
234 
235 /**
236   * @brief  Enter Sleep mode.
237   * @note   In Sleep mode, all I/O pins keep the same state as
238   *         in Run mode.
239   * @param  Regulator Specifies the regulator state in Sleep mode.
240   *         This parameter can be the following value:
241   *           @arg @ref PWR_MAINREGULATOR_ON Sleep mode (regulator in main mode)
242   * @param  SLEEPEntry Specifies if Sleep mode is entered with WFI or WFE
243   *         instruction. This parameter can be one of the following values:
244   *           @arg @ref PWR_SLEEPENTRY_WFI enter Sleep or Low-power Sleep
245   *                     mode with WFI instruction
246   *           @arg @ref PWR_SLEEPENTRY_WFE enter Sleep or Low-power Sleep
247   *                     mode with WFE instruction
248   * @note   When WFI entry is used, tick interrupt have to be disabled if not
249   *         desired as the interrupt wake up source.
250   * @retval None
251   */
HAL_PWR_EnterSLEEPMode(uint32_t Regulator,uint8_t SLEEPEntry)252 void HAL_PWR_EnterSLEEPMode(uint32_t Regulator, uint8_t SLEEPEntry)
253 {
254   /* Check the parameters */
255   assert_param(IS_PWR_REGULATOR(Regulator));
256   assert_param(IS_PWR_SLEEP_ENTRY(SLEEPEntry));
257 
258   /* Clear SLEEPDEEP bit of Cortex System Control Register */
259   CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
260 
261   /* Select SLEEP mode entry -------------------------------------------------*/
262   if (SLEEPEntry == PWR_SLEEPENTRY_WFI)
263   {
264     /* Request Wait For Interrupt */
265     __WFI();
266   }
267   else
268   {
269     /* Request Wait For Event */
270     __SEV();
271     __WFE();
272     __WFE();
273   }
274 }
275 
276 
277 /**
278   * @brief  Enter Stop mode
279   * @note   This API is named HAL_PWR_EnterSTOPMode to ensure compatibility with
280   *         legacy code running on devices where only "Stop mode" is mentioned
281   *         with main regulator ON.
282   * @note   In Stop mode, all I/O pins keep the same state as in Run mode.
283   * @note   All clocks in the VCORE domain are stopped; the HSI and the
284   *         HSE oscillators are disabled. Some peripherals with the wakeup
285   *         capability can switch on the HSI to receive a frame, and switch off
286   *         the HSI after receiving the frame if it is not a wakeup frame.
287   *         SRAM and register contents are preserved.
288   * @note   When exiting Stop 0 mode by issuing an interrupt or a
289   *         wakeup event, the HSI RC oscillator is selected as system clock
290   * @param  Regulator Specifies the regulator state in Stop mode
291   *         This parameter can be of the following value:
292   *            @arg @ref PWR_MAINREGULATOR_ON  Stop 0 mode (main regulator ON)
293   * @param  STOPEntry Specifies Stop 0 mode is entered with WFI or
294   *         WFE instruction. This parameter can be one of the following values:
295   *            @arg @ref PWR_STOPENTRY_WFI  Enter Stop 0 mode with WFI
296   *                                         instruction.
297   *            @arg @ref PWR_STOPENTRY_WFE  Enter Stop 0 mode with WFE
298   *                                         instruction.
299   * @retval None
300   */
HAL_PWR_EnterSTOPMode(uint32_t Regulator,uint8_t STOPEntry)301 void HAL_PWR_EnterSTOPMode(uint32_t Regulator, uint8_t STOPEntry)
302 {
303   /* Check the parameters */
304   assert_param(IS_PWR_REGULATOR(Regulator));
305   assert_param(IS_PWR_STOP_ENTRY(STOPEntry));
306 
307   MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_LOWPOWERMODE_STOP0);
308 
309   /* Set SLEEPDEEP bit of Cortex System Control Register */
310   SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
311 
312   /* Select Stop mode entry --------------------------------------------------*/
313   if (STOPEntry == PWR_STOPENTRY_WFI)
314   {
315     /* Request Wait For Interrupt */
316     __WFI();
317   }
318   else
319   {
320     /* Request Wait For Event */
321     __SEV();
322     __WFE();
323     __WFE();
324   }
325 
326   /* Reset SLEEPDEEP bit of Cortex System Control Register */
327   CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
328 }
329 
330 
331 /**
332   * @brief  Enter Standby mode.
333   * @note   In Standby mode,the HSI and the HSE oscillators are
334   *         switched off. SRAM and register contents are lost except
335   *         for registers in the Backup domain and Standby circuitry.
336   * @note   The I/Os can be configured either with a pull-up or pull-down or can
337   *         be kept in analog state.
338   *         HAL_PWREx_EnableGPIOPullUp() and HAL_PWREx_EnableGPIOPullDown()
339   *         respectively enable Pull Up and PullDown state.
340   *         HAL_PWREx_DisableGPIOPullUp() & HAL_PWREx_DisableGPIOPullDown()
341   *         disable the same. These states are effective in Standby mode only if
342   *         APC bit is set through HAL_PWREx_EnablePullUpPullDownConfig() API.
343   * @retval None
344   */
HAL_PWR_EnterSTANDBYMode(void)345 void HAL_PWR_EnterSTANDBYMode(void)
346 {
347   /* Set Stand-by mode */
348   MODIFY_REG(PWR->CR1, PWR_CR1_LPMS, PWR_LOWPOWERMODE_STANDBY);
349 
350   /* Set SLEEPDEEP bit of Cortex System Control Register */
351   SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
352 
353   /* Request Wait For Interrupt */
354   __WFI();
355 }
356 
357 
358 /**
359   * @brief  Enable Sleep-On-Exit Cortex feature
360   * @note   Set SLEEPONEXIT bit of SCR register. When this bit is set, the
361   *         processor enters SLEEP or DEEPSLEEP mode when an interruption
362   *         handling is over returning to thread mode. Setting this bit is
363   *         useful when the processor is expected to run only on interruptions
364   *         handling.
365   * @retval None
366   */
HAL_PWR_EnableSleepOnExit(void)367 void HAL_PWR_EnableSleepOnExit(void)
368 {
369   /* Set SLEEPONEXIT bit of Cortex System Control Register */
370   SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPONEXIT_Msk));
371 }
372 
373 
374 /**
375   * @brief  Disable Sleep-On-Exit Cortex feature
376   * @note   Clear SLEEPONEXIT bit of SCR register. When this bit is set, the
377   *         processor enters SLEEP or DEEPSLEEP mode when an interruption
378   *         handling is over.
379   * @retval None
380   */
HAL_PWR_DisableSleepOnExit(void)381 void HAL_PWR_DisableSleepOnExit(void)
382 {
383   /* Clear SLEEPONEXIT bit of Cortex System Control Register */
384   CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPONEXIT_Msk));
385 }
386 
387 
388 /**
389   * @brief  Enable Cortex Sev On Pending feature.
390   * @note   Set SEVONPEND bit of SCR register. When this bit is set, enabled
391   *         events and all interrupts, including disabled ones can wakeup
392   *         processor from WFE.
393   * @retval None
394   */
HAL_PWR_EnableSEVOnPend(void)395 void HAL_PWR_EnableSEVOnPend(void)
396 {
397   /* Set SEVONPEND bit of Cortex System Control Register */
398   SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SEVONPEND_Msk));
399 }
400 
401 
402 /**
403   * @brief  Disable Cortex Sev On Pending feature.
404   * @note   Clear SEVONPEND bit of SCR register. When this bit is clear, only
405   *         enable interrupts or events can wakeup processor from WFE
406   * @retval None
407   */
HAL_PWR_DisableSEVOnPend(void)408 void HAL_PWR_DisableSEVOnPend(void)
409 {
410   /* Clear SEVONPEND bit of Cortex System Control Register */
411   CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SEVONPEND_Msk));
412 }
413 
414 /**
415   * @}
416   */
417 
418 /**
419   * @}
420   */
421 
422 #endif /* HAL_PWR_MODULE_ENABLED */
423 /**
424   * @}
425   */
426 
427 /**
428   * @}
429   */
430