1 /*****************************************************************************
2  * Copyright (c) 2022, Nations Technologies Inc.
3  *
4  * All rights reserved.
5  * ****************************************************************************
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * - Redistributions of source code must retain the above copyright notice,
11  * this list of conditions and the disclaimer below.
12  *
13  * Nations' name may not be used to endorse or promote products derived from
14  * this software without specific prior written permission.
15  *
16  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY NATIONS "AS IS" AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
19  * DISCLAIMED. IN NO EVENT SHALL NATIONS BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
22  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
25  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  * ****************************************************************************/
27 
28 /**
29  * @file n32l40x_pwr.c
30  * @author Nations
31  * @version v1.2.0
32  *
33  * @copyright Copyright (c) 2022, Nations Technologies Inc. All rights reserved.
34  */
35 #include "n32l40x_pwr.h"
36 
37 /** @addtogroup n32l40x_StdPeriph_Driver
38  * @{
39  */
40 
41 /** @addtogroup PWR
42  * @brief PWR driver modules
43  * @{
44  */
45 
46 /** @addtogroup PWR_Private_TypesDefinitions
47  * @{
48  */
49 
50 /**
51  * @}
52  */
53 
54 /** @addtogroup PWR_Private_Defines
55  * @{
56  */
57 
58 /* --------- PWR registers bit address in the alias region ---------- */
59 #define PWR_OFFSET (PWR_BASE - PERIPH_BASE)
60 
61 /* --- CTRL Register ---*/
62 
63 /* Alias word address of DBKP bit */
64 #define CTRL_OFFSET  (PWR_OFFSET + 0x00)
65 #define DBKP_BITN    0x08
66 #define CTRL_DBKP_BB (PERIPH_BB_BASE + (CTRL_OFFSET * 32) + (DBKP_BITN * 4))
67 
68 /* Alias word address of PVDEN bit */
69 #define PVDEN_BITN    0x04
70 #define CTRL_PVDEN_BB (PERIPH_BB_BASE + (CTRL_OFFSET * 32) + (PVDEN_BITN * 4))
71 
72 /* --- CTRLSTS Register ---*/
73 
74 /* Alias word address of WKUPEN bit */
75 #define CTRLSTS_OFFSET    (PWR_OFFSET + 0x04)
76 #define WKUPEN_BITN       0x08
77 #define CTRLSTS_WKUPEN_BB (PERIPH_BB_BASE + (CTRLSTS_OFFSET * 32) + (WKUPEN_BITN * 4))
78 
79 /* ------------------ PWR registers bit mask ------------------------ */
80 
81 
82 void SetSysClock_MSI(void);
83 /**
84  * @}
85  */
86 
87 /** @addtogroup PWR_Private_Macros
88  * @{
89  */
90 
91 /**
92  * @}
93  */
94 
95 /** @addtogroup PWR_Private_Variables
96  * @{
97  */
98 
99 /**
100  * @}
101  */
102 
103 /** @addtogroup PWR_Private_FunctionPrototypes
104  * @{
105  */
106 
107 /**
108  * @}
109  */
110 
111 /** @addtogroup PWR_Private_Functions
112  * @{
113  */
114 
115 /**
116  * @brief  Deinitializes the PWR peripheral registers to their default reset values.
117  */
PWR_DeInit(void)118 void PWR_DeInit(void)
119 {
120     RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_PWR, ENABLE);
121     RCC_EnableAPB1PeriphReset(RCC_APB1_PERIPH_PWR, DISABLE);
122 }
123 
124 /**
125  * @brief  Enables or disables access to the RTC and backup registers.
126  * @param Cmd new state of the access to the RTC and backup registers.
127  *   This parameter can be: ENABLE or DISABLE.
128  */
PWR_BackupAccessEnable(FunctionalState Cmd)129 void PWR_BackupAccessEnable(FunctionalState Cmd)
130 {
131     /* Check the parameters */
132     assert_param(IS_FUNCTIONAL_STATE(Cmd));
133     *(__IO uint32_t*)CTRL_DBKP_BB = (uint32_t)Cmd;
134 }
135 /**
136  * @brief  MR voltage selection.
137  * @param voltage value: 1.0V and 1.1V.
138  *   This parameter can be: MR_1V0 or MR_1V1.
139  */
PWR_MRconfig(uint8_t voltage)140 void PWR_MRconfig(uint8_t voltage)
141 {
142   uint32_t tmpreg = 0;
143 
144   tmpreg = PWR->CTRL1;
145   /* Clear MRSEL bits */
146   tmpreg &= (~PWR_CTRL1_MRSELMASK);
147   /* Set voltage*/
148   tmpreg |= (uint32_t)(voltage << 9);
149   PWR->CTRL1 = tmpreg;
150 }
151 /**
152  * @brief  Get MR voltage value.
153  * @param voltage value: 1.0V and 1.1V.
154  * @return The value of voltage.
155  */
GetMrVoltage(void)156 uint8_t GetMrVoltage(void)
157 {
158   uint8_t tmp = 0;
159 
160   tmp = (uint8_t)((PWR->CTRL1 >> 9) & 0x03);//2bits
161   return tmp ;
162 }
163 /**
164  * @brief  Enables or disables the Power Voltage Detector(PVD).
165  * @param Cmd new state of the PVD.
166  *   This parameter can be: ENABLE or DISABLE.
167  */
PWR_PvdEnable(FunctionalState Cmd)168 void PWR_PvdEnable(FunctionalState Cmd)
169 {
170     /* Check the parameters */
171     assert_param(IS_FUNCTIONAL_STATE(Cmd));
172     //*(__IO uint32_t*)CTRL_PVDEN_BB = (uint32_t)Cmd; //Can not enable the PVD bit
173     PWR->CTRL2 |= Cmd;
174 
175 }
176 
177 /**
178   * @brief  Configures the voltage threshold detected by the Power Voltage Detector(PVD).
179   * @param  PWR_PVDLevel: specifies the PVD detection level
180   *   This parameter can be one of the following values:
181   *     @arg PWR_CTRL2_PLS1: PVD detection level set to 2.1V
182   *     @arg PWR_CTRL2_PLS2: PVD detection level set to 2.25V
183   *     @arg PWR_CTRL2_PLS3: PVD detection level set to 2.4V
184   *     @arg PWR_CTRL2_PLS4: PVD detection level set to 2.55V
185   *     @arg PWR_CTRL2_PLS5: PVD detection level set to 2.7V
186   *     @arg PWR_CTRL2_PLS6: PVD detection level set to 2.85V
187   *     @arg PWR_CTRL2_PLS7: PVD detection level set to 2.95V
188   *     @arg PWR_CTRL2_PLS8: external input analog voltage PVD_IN (compared internally to VREFINT)
189   * @retval None
190   */
PWR_PVDLevelConfig(uint32_t PWR_PVDLevel)191 void PWR_PVDLevelConfig(uint32_t PWR_PVDLevel)
192 {
193     uint32_t tmpregister = 0;
194     /* Check the parameters */
195     assert_param(IS_PWR_PVD_LEVEL(PWR_PVDLevel));
196     tmpregister = PWR->CTRL2;
197     /* Clear PLS[7:5] bits */
198     tmpregister &= (~PWR_CTRL2_PLSMASK);
199     /* Set PRS[7:5] bits according to PWR_PVDLevel value */
200     tmpregister |= PWR_PVDLevel;
201     /* Store the new value */
202     PWR->CTRL2 = tmpregister;
203 }
204 
205 /**
206  * @brief  Enables or disables the WakeUp Pin functionality.
207  * @param Pin: which PIN  select to wakeup.
208  *   This parameter can be one of the following values:
209  *     @arg WAKEUP_PIN0
210  *     @arg WAKEUP_PIN1
211  *     @arg WAKEUP_PIN2
212  * @param Cmd new state of the WakeUp Pin functionality.
213  *   This parameter can be: ENABLE or DISABLE.
214  */
PWR_WakeUpPinEnable(WAKEUP_PINX WKUP_Pin,FunctionalState Cmd)215 void PWR_WakeUpPinEnable(WAKEUP_PINX WKUP_Pin,FunctionalState Cmd)
216 {
217     uint32_t Temp = 0;
218     Temp = PWR->CTRL3;
219     if (ENABLE==Cmd)
220     {
221        Temp &= (~(PWR_CTRL3_WKUP0EN|PWR_CTRL3_WKUP1EN|PWR_CTRL3_WKUP2EN));
222        Temp |= (WKUP_Pin);
223        PWR->CTRL3 = Temp;
224     }
225     else
226     {
227        Temp &= (~(WKUP_Pin));
228        PWR->CTRL3 = Temp;
229     }
230 }
231 
232 /**
233   * @brief  Enters SLEEP mode.
234   * @param  SLEEPONEXIT: specifies the SLEEPONEXIT state in SLEEP mode.
235   *   This parameter can be one of the following values:
236   *     @arg 0: SLEEP mode with SLEEPONEXIT disable
237   *     @arg 1: SLEEP mode with SLEEPONEXIT enable
238   * @param  PWR_STOPEntry: specifies if SLEEP mode in entered with WFI or WFE instruction.
239   *   This parameter can be one of the following values:
240   *     @arg PWR_SLEEPEntry_WFI: enter SLEEP mode with WFI instruction
241   *     @arg PWR_SLEEPEntry_WFE: enter SLEEP mode with WFE instruction
242   * @retval None
243   */
PWR_EnterSLEEPMode(uint8_t SLEEPONEXIT,uint8_t PWR_SLEEPEntry)244 void PWR_EnterSLEEPMode(uint8_t SLEEPONEXIT, uint8_t PWR_SLEEPEntry)
245 {
246   /* Check the parameters */
247   assert_param(IS_PWR_SLEEP_ENTRY(PWR_SLEEPEntry));
248 
249   /* CLEAR SLEEPDEEP bit of Cortex System Control Register */
250   SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP);
251 
252     /* Select SLEEPONEXIT mode entry --------------------------------------------------*/
253   if (SLEEPONEXIT == 1)
254   {
255     /* the MCU enters Sleep mode as soon as it exits the lowest priority ISR */
256     SCB->SCR |= SCB_SCR_SLEEPONEXIT;
257   }
258   else if (SLEEPONEXIT == 0)
259   {
260     /* Sleep-now */
261     SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPONEXIT);
262   }
263 
264   /* Select SLEEP mode entry --------------------------------------------------*/
265   if (PWR_SLEEPEntry == PWR_SLEEPENTRY_WFI)
266   {
267     /* Request Wait For Interrupt */
268     __WFI();
269   }
270   else
271   {
272     /* Request Wait For Event */
273     __SEV();
274     __WFE();
275     __WFE();
276   }
277 }
278 
279 
280 
281 /**
282  * @brief  Enters STOP2 mode.
283  * @param PWR_STOPEntry specifies if STOP2 mode in entered with WFI or WFE instruction.
284  *   This parameter can be one of the following values:
285  *     @arg PWR_STOPENTRY_WFI enter STOP2 mode with WFI instruction
286  *     @arg PWR_STOPENTRY_WFE enter STOP2 mode with WFE instruction
287  * @param RetentionMode: PWR_CTRL3_RAM1RET or PWR_CTRL3_RAM2RET
288  */
PWR_EnterSTOP2Mode(uint8_t PWR_STOPEntry,uint32_t RetentionMode)289 void PWR_EnterSTOP2Mode(uint8_t PWR_STOPEntry,uint32_t RetentionMode)
290 {
291   uint32_t tmpreg = 0;
292   /* Check the parameters */
293   assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry));
294   /* Wait MR Voltage Adjust Complete */
295   while ((PWR->STS2 &0X2) != 2);
296   tmpreg = PWR->CTRL3;
297   /* Clear SRAMRET bits */
298   tmpreg &= (~PWR_CTRL3_RAMRETMASK);
299   /* Set SRAM1/2 select */
300   tmpreg |= RetentionMode;
301   PWR->CTRL3 = tmpreg;
302   /* Select the regulator state in STOP2 mode ---------------------------------*/
303   tmpreg = PWR->CTRL1;
304   /* Clear LPMS bits */
305   tmpreg &= (~PWR_CTRL1_LPMSELMASK);
306   /* Set stop2 mode select */
307   tmpreg |= PWR_CTRL1_STOP2;
308   /* Store the new value */
309   PWR->CTRL1 = tmpreg;
310   /* Set SLEEPDEEP bit of Cortex System Control Register */
311   SCB->SCR |= SCB_SCR_SLEEPDEEP;
312 
313   /* Select STOP mode entry --------------------------------------------------*/
314   if (PWR_STOPEntry ==  PWR_STOPENTRY_WFI)
315   {
316     /* Request Wait For Interrupt */
317     __WFI();
318   }
319   else
320   {
321     /* Request Wait For Event */
322     __SEV();
323     __WFE();
324     __WFE();
325   }
326 
327   /* Reset SLEEPDEEP bit of Cortex System Control Register */
328   SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP);
329 }
330 
331 
332 /**
333   * @brief  Enters Low power run mode.
334   * @param
335   *     @arg
336   *     @arg
337   * @retval None
338   */
PWR_EnterLowPowerRunMode(void)339 void PWR_EnterLowPowerRunMode(void)
340 {
341     uint32_t tmpreg = 0;
342 
343     SetSysClock_MSI();
344     FLASH_SetLatency(FLASH_LATENCY_2);    //Configure the Flash read latency to be grater than 2, so LVE/SE timing requirement is guaranteed
345     //config FLASH enter the low power voltage mode
346     FLASH->AC |= FLASH_AC_LVMEN;
347     while ((FLASH->AC & FLASH_AC_LVMF) != FLASH_AC_LVMF);
348     FLASH_SetLatency(FLASH_LATENCY_0);    //Configure the latency of Flash read cycle to proper value which depends on the Flash read access time.
349 
350     _SetLprunSramVoltage(0);
351     _SetBandGapMode(0);
352     _SetPvdBorMode(0);
353     /* Select the regulator state in LPRUN mode ---------------------------------*/
354     tmpreg = PWR->CTRL1;
355     /* Clear LPMS bits */
356     tmpreg &= (~PWR_CTRL1_LPMSELMASK);
357     /* Set lpr to run the main power domain*/
358     tmpreg |= PWR_CTRL1_LPREN;
359     /* Store the new value */
360     PWR->CTRL1 = tmpreg;
361     while ((PWR->STS2 &PWR_STS2_LPRUNF) != 0);//LPRCNT flag ready
362 }
363 
364 /**
365   * @brief  Enters Low power run mode.
366   * @param
367   *     @arg
368   *     @arg
369   * @retval None
370   */
PWR_ExitLowPowerRunMode(void)371 void PWR_ExitLowPowerRunMode(void)
372 {
373     PWR->CTRL1 &= ~PWR_CTRL1_LPREN;
374     _SetLprunswitch(3);
375     while ((PWR->STS2 &PWR_STS2_MRF) != PWR_STS2_MRF);
376     while ((PWR->STS2 &PWR_STS2_LPRUNF) != PWR_STS2_LPRUNF);
377     FLASH_SetLatency(FLASH_LATENCY_2);    //Configure the Flash read latency to be grater than 2, so LVE/SE timing requirement is guaranteed
378     FLASH->AC &= ~FLASH_AC_LVMEN;                  //clear LVMREQ
379     while ((FLASH->AC &FLASH_AC_LVMF) != 0);   //wait LVE is deasserted by polling the LVMVLD bit
380 
381     FLASH_SetLatency(FLASH_LATENCY_0);    //Configure the latency of Flash read cycle to proper value which depends on the Flash read access time.
382     _SetLprunswitch(2);
383     while ((PWR->STS2 &0X2) != 0)           // wait MF to be 0 first
384     {
385     }
386     while ((PWR->STS2 &0X2) != 2)           // wait MF to be 1 then
387     {
388     }
389 }
390 
391 /**
392   * @brief  Enters LP_SLEEP mode.
393   * @param  SLEEPONEXIT: specifies the SLEEPONEXIT state in SLEEP mode.
394   *   This parameter can be one of the following values:
395   *     @arg 0: SLEEP mode with SLEEPONEXIT disable
396   *     @arg 1: SLEEP mode with SLEEPONEXIT enable
397   * @param  PWR_STOPEntry: specifies if SLEEP mode in entered with WFI or WFE instruction.
398   *   This parameter can be one of the following values:
399   *     @arg PWR_SLEEPEntry_WFI: enter SLEEP mode with WFI instruction
400   *     @arg PWR_SLEEPEntry_WFE: enter SLEEP mode with WFE instruction
401   * @retval None
402   */
PWR_EnterLowPowerSleepMode(uint8_t SLEEPONEXIT,uint8_t PWR_SLEEPEntry)403 void PWR_EnterLowPowerSleepMode(uint8_t SLEEPONEXIT, uint8_t PWR_SLEEPEntry)
404 {
405   PWR_EnterLowPowerRunMode();
406   PWR_EnterSLEEPMode(SLEEPONEXIT, PWR_SLEEPEntry);
407 }
408 
409  /**
410   * @brief  Enters STANDBY mode.
411   * @param  PWR_STANDBYEntry: specifies if STANDBY mode in entered with WFI or WFE instruction.
412   *   This parameter can be one of the following values:
413   *     @arg PWR_STANDBYEntry_WFI: enter STANDBY mode with WFI instruction
414   *     @arg PWR_CTRL3_RAM2RET: SRAM2 whether to retention
415   * @retval None
416   */
PWR_EnterSTANDBYMode(uint8_t PWR_STANDBYEntry,uint32_t Sam2Ret)417 void PWR_EnterSTANDBYMode(uint8_t PWR_STANDBYEntry,uint32_t Sam2Ret)
418 {
419     uint32_t tmpreg;
420     /* Clear Wake-up flag */
421     PWR->STSCLR |= PWR_STSCLR_CLRWKUP0;
422     PWR->STSCLR |= PWR_STSCLR_CLRWKUP1;
423     PWR->STSCLR |= PWR_STSCLR_CLRWKUP2;
424     tmpreg = PWR->CTRL3;
425     /* Clear SRAMRET bits */
426     tmpreg &= (~PWR_CTRL3_RAMRETMASK);
427     /* Set SRAM1/2 select */
428     tmpreg |= Sam2Ret;
429     PWR->CTRL3 = tmpreg;
430 
431     tmpreg = PWR->CTRL1;
432     /* Clear LPMS bits */
433     tmpreg &= (~PWR_CTRL1_LPMSELMASK);
434     /* Select STANDBY mode */
435     tmpreg |= PWR_CTRL1_STANDBY;
436     PWR->CTRL1 = tmpreg;
437     /* Set SLEEPDEEP bit of Cortex System Control Register */
438     SCB->SCR |= SCB_SCR_SLEEPDEEP;
439 /* This option is used to ensure that store operations are completed */
440 #if defined ( __CC_ARM   )
441   __force_stores();
442 #endif
443  /* Select STANDBY mode entry --------------------------------------------------*/
444   if (PWR_STANDBYEntry == PWR_STOPENTRY_WFI)
445   {
446     /* Request Wait For Interrupt */
447     __WFI();
448   }
449   else
450   {
451     /* Request Wait For Event */
452     __SEV();
453     __WFE();
454     __WFE();
455   }
456 }
457 
458 
459 
460 /**
461   * @brief  Checks whether the specified PWR flag is set or not.
462   * @param  PWR_FLAG: specifies the flag to check.
463   *   This parameter can be one of the following values:
464   *     @arg PWR_WKUP0_FLAG/PWR_WKUP1_FLAG/PWR_WKUP2_FLAG: Wake Up flag
465   *     @arg PWR_STBY_FLAG: StandBy flag
466   *     @arg PWR_LPRUN_FLAG: low power work flag
467   *     @arg PWR_MR_FLAG: MR work statue flag
468   *     @arg PWR_PVDO_FLAG: PVD output flag
469   * @retval The new state of PWR_FLAG (SET or RESET).
470   */
PWR_GetFlagStatus(uint8_t STS,uint32_t PWR_FLAG)471 FlagStatus PWR_GetFlagStatus(uint8_t STS,uint32_t PWR_FLAG)
472 {
473   FlagStatus bitstatus = RESET;
474   /* Check the parameters */
475   assert_param(IS_PWR_GET_FLAG(PWR_FLAG));
476   if (STS == 1)
477     {
478         if ((PWR->STS1 & PWR_FLAG) != (uint32_t)RESET)
479         {
480             bitstatus = SET;
481         }
482         else
483         {
484             bitstatus = RESET;
485         }
486 
487     }
488     else
489     {
490         if ((PWR->STS2 & PWR_FLAG) != (uint32_t)RESET)
491         {
492             bitstatus = SET;
493         }
494         else
495         {
496             bitstatus = RESET;
497         }
498 
499     }
500 
501   /* Return the flag status */
502   return bitstatus;
503 }
504 
505 /**
506  * @brief  Clears the PWR's pending flags.
507  * @param PWR_FLAG specifies the flag to clear.
508  *   This parameter can be one of the following values:
509   *     @arg PWR_WKUP1_FLAG/PWR_WKUP2_FLAG/PWR_WKUP3_FLAG: Wake Up flag
510   *     @arg PWR_STBY_FLAG: StandBy flag
511  */
PWR_ClearFlag(uint32_t PWR_FLAG)512 void PWR_ClearFlag(uint32_t PWR_FLAG)
513 {
514     /* Check the parameters */
515     assert_param(IS_PWR_CLEAR_FLAG(PWR_FLAG));
516 
517     PWR->STSCLR |=  PWR_FLAG ;
518 }
519 
520 
521 /**
522  * @brief  set system clock with MSI.
523  * @param void.
524  */
525 
SetSysClock_MSI(void)526 void SetSysClock_MSI(void)
527 {
528      RCC_DeInit();
529 
530     if (RESET == RCC_GetFlagStatus(RCC_CTRLSTS_FLAG_MSIRD))
531     {
532         /* Enable MSI and Config Clock */
533         RCC_ConfigMsi(RCC_MSI_ENABLE, RCC_MSI_RANGE_4M);
534         /* Waits for MSI start-up */
535         while (SUCCESS != RCC_WaitMsiStable());
536     }
537 
538     /* Enable Prefetch Buffer */
539     FLASH_PrefetchBufSet(FLASH_PrefetchBuf_EN);
540 
541     /* Select MSI as system clock source */
542     RCC_ConfigSysclk(RCC_SYSCLK_SRC_MSI);
543 
544     /* Wait till MSI is used as system clock source */
545     while (RCC_GetSysclkSrc() != 0x00)
546     {
547     }
548 
549     /* Flash 0 wait state */
550     //FLASH_SetLatency(FLASH_LATENCY_0);
551 
552     /* HCLK = SYSCLK */
553     RCC_ConfigHclk(RCC_SYSCLK_DIV1);
554 
555     /* PCLK2 = HCLK */
556     RCC_ConfigPclk2(RCC_HCLK_DIV1);
557 
558     /* PCLK1 = HCLK */
559     RCC_ConfigPclk1(RCC_HCLK_DIV1);
560 }
561 
562 /**
563  * @}
564  */
565 
566 /**
567  * @}
568  */
569 
570 /**
571  * @}
572  */
573