sleep.c
Go to the documentation of this file.
1 
33 /*
34  * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
35  */
36 
37 #include <compiler.h>
38 #include "sleep.h"
39 
40 /* SAM3,SAM4,SAMG,SAMV,SAMS and SAME series */
41 #if (SAM3S || SAM3N || SAM3XA || SAM3U || SAM4S || SAM4E || SAM4N || SAM4C || \
42  SAM4CM || SAMG || SAM4CP || SAMV71 || SAMV70 || SAMS70 || SAME70)
43 # include "pmc.h"
44 # include "board.h"
45 
46 /* Checking board configuration of main clock xtal statup time */
47 #if !defined(BOARD_OSC_STARTUP_US)
48 # warning The board main clock xtal statup time has not been defined. Using default settings.
49 # define BOARD_OSC_STARTUP_US (15625UL)
50 #endif
51 
52 #if !defined(EFC0)
53 # define EFC0 EFC
54 #endif
55 
59 __always_inline static void pmc_save_clock_settings(
60  uint32_t *p_osc_setting,
61  uint32_t *p_pll0_setting,
62  uint32_t *p_pll1_setting,
63  uint32_t *p_mck_setting,
64  uint32_t *p_fmr_setting,
65 #if defined(EFC1)
66  uint32_t *p_fmr_setting1,
67 #endif
68  const bool disable_xtal)
69 {
70  uint32_t mor = PMC->CKGR_MOR;
71  uint32_t mckr = PMC->PMC_MCKR;
72  uint32_t fmr = EFC0->EEFC_FMR;
73 # if defined(EFC1)
74  uint32_t fmr1 = EFC1->EEFC_FMR;
75 # endif
76 
77  if (p_osc_setting) {
78  *p_osc_setting = mor;
79  }
80  if (p_pll0_setting) {
81  *p_pll0_setting = PMC->CKGR_PLLAR;
82  }
83  if (p_pll1_setting) {
84 #if (SAM3S || SAM4S || SAM4C || SAM4CM || SAM4CP)
85  *p_pll1_setting = PMC->CKGR_PLLBR;
86 #elif (SAM3U || SAM3XA)
87  *p_pll1_setting = PMC->CKGR_UCKR;
88 #else
89  *p_pll1_setting = 0;
90 #endif
91  }
92  if (p_mck_setting) {
93  *p_mck_setting = mckr;
94  }
95  if (p_fmr_setting) {
96  *p_fmr_setting = fmr;
97  }
98 #if defined(EFC1)
99  if (p_fmr_setting1) {
100  *p_fmr_setting1 = fmr1;
101  }
102 #endif
103 
104  /* Enable FAST RC */
105  PMC->CKGR_MOR = CKGR_MOR_KEY_PASSWD | mor | CKGR_MOR_MOSCRCEN;
106  /* if MCK source is PLL, switch to mainck */
107  if ((mckr & PMC_MCKR_CSS_Msk) > PMC_MCKR_CSS_MAIN_CLK) {
108  /* MCK -> MAINCK */
109  mckr = (mckr & (~PMC_MCKR_CSS_Msk)) | PMC_MCKR_CSS_MAIN_CLK;
110  PMC->PMC_MCKR = mckr;
111  while(!(PMC->PMC_SR & PMC_SR_MCKRDY));
112  }
113  /* MCK prescale -> 1 */
114  if (mckr & PMC_MCKR_PRES_Msk) {
115  mckr = (mckr & (~PMC_MCKR_PRES_Msk));
116  PMC->PMC_MCKR = mckr;
117  while(!(PMC->PMC_SR & PMC_SR_MCKRDY));
118  }
119  /* Disable PLLs */
121 #if (SAM3S || SAM4S || SAM4C || SAM4CM || SAM4CP)
122  pmc_disable_pllbck();
123 #elif (SAM3U || SAM3XA)
124  pmc_disable_upll_clock();
125 #endif
126 
127  /* Prepare for entering WAIT mode */
128  /* Wait fast RC ready */
129  while (!(PMC->PMC_SR & PMC_SR_MOSCRCS));
130 
131  /* Switch mainck to FAST RC */
132 #if SAMG
133 
138  EFC0->EEFC_FMR = (fmr & (~EEFC_FMR_FWS_Msk)) | EEFC_FMR_FWS(1);
139 
140  PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCSEL) | CKGR_MOR_MOSCRCF_24_MHz |
142 #else
143  PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCSEL) |
145 #endif
146  while (!(PMC->PMC_SR & PMC_SR_MOSCSELS));
147 
148 #if (!SAMG)
149  /* FWS update */
150  EFC0->EEFC_FMR = fmr & (~EEFC_FMR_FWS_Msk);
151 #if defined(EFC1)
152  EFC1->EEFC_FMR = fmr1 & (~EEFC_FMR_FWS_Msk);
153 #endif
154 #endif
155 
156  /* Disable XTALs */
157  if (disable_xtal) {
158  PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) |
160  }
161 }
162 
166 __always_inline static void pmc_restore_clock_setting(
167  const uint32_t osc_setting,
168  const uint32_t pll0_setting,
169  const uint32_t pll1_setting,
170  const uint32_t mck_setting,
171  const uint32_t fmr_setting
172 #if defined(EFC1)
173  , const uint32_t fmr_setting1
174 #endif
175  )
176 {
177  uint32_t mckr;
178  uint32_t pll_sr = 0;
179 
180  /* Switch mainck to external xtal */
181  if (CKGR_MOR_MOSCXTBY == (osc_setting & CKGR_MOR_MOSCXTBY)) {
182  /* Bypass mode */
183  PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) |
184  CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTBY |
186  PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCEN &
189  } else if (CKGR_MOR_MOSCXTEN == (osc_setting & CKGR_MOR_MOSCXTEN)) {
190  /* Enable External XTAL */
191  if (!(PMC->CKGR_MOR & CKGR_MOR_MOSCXTEN)) {
192  PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTBY) |
193  CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTEN;
194  /* Wait the Xtal to stabilize */
195  while (!(PMC->PMC_SR & PMC_SR_MOSCXTS));
196  }
197  /* Select External XTAL */
198  if (!(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL)) {
200  while (!(PMC->PMC_SR & PMC_SR_MOSCSELS));
201  }
202  /* Disable Fast RC */
203  PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCEN &
206  }
207 
208  if (pll0_setting & CKGR_PLLAR_MULA_Msk) {
209 #if (SAM4C || SAM4CM || SAMG || SAM4CP)
210  PMC->CKGR_PLLAR = pll0_setting;
211 #else
212  PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | pll0_setting;
213 #endif
214  pll_sr |= PMC_SR_LOCKA;
215  }
216 #if (SAM3S || SAM4S || SAM4C || SAM4CM || SAM4CP)
217  if (pll1_setting & CKGR_PLLBR_MULB_Msk) {
218  PMC->CKGR_PLLBR = pll1_setting;
219  pll_sr |= PMC_SR_LOCKB;
220  }
221 #elif (SAM3U || SAM3XA)
222  if (pll1_setting & CKGR_UCKR_UPLLEN) {
223  PMC->CKGR_UCKR = pll1_setting;
224  pll_sr |= PMC_SR_LOCKU;
225  }
226 #else
227  UNUSED(pll1_setting);
228 #endif
229  /* Wait MCK source ready */
230  switch(mck_setting & PMC_MCKR_CSS_Msk) {
232  while (!(PMC->PMC_SR & PMC_SR_LOCKA));
233  break;
234 #if (SAM3S || SAM4S || SAM4C || SAM4CM || SAM4CP)
235  case PMC_MCKR_CSS_PLLB_CLK:
236  while (!(PMC->PMC_SR & PMC_SR_LOCKB));
237  break;
238 #elif (SAM3U || SAM3XA)
240  while (!(PMC->PMC_SR & PMC_SR_LOCKU));
241  break;
242 #endif
243  }
244 
245  /* Switch to faster clock */
246  mckr = PMC->PMC_MCKR;
247 
248  /* Set PRES */
249  PMC->PMC_MCKR = (mckr & ~PMC_MCKR_PRES_Msk)
250  | (mck_setting & PMC_MCKR_PRES_Msk);
251  while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
252 
253  /* Restore flash wait states */
254  EFC0->EEFC_FMR = fmr_setting;
255 #if defined(EFC1)
256  EFC1->EEFC_FMR = fmr_setting1;
257 #endif
258 
259  /* Set CSS and others */
260  PMC->PMC_MCKR = mck_setting;
261  while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
262 
263  /* Waiting all restored PLLs ready */
264  while (!(PMC->PMC_SR & pll_sr));
265 }
266 
268 static volatile bool b_is_sleep_clock_used = false;
270 static pmc_callback_wakeup_clocks_restored_t callback_clocks_restored = NULL;
271 
272 void pmc_sleep(int sleep_mode)
273 {
274  switch (sleep_mode) {
275  case SAM_PM_SMODE_SLEEP_WFI:
276  case SAM_PM_SMODE_SLEEP_WFE:
277 #if (SAM4S || SAM4E || SAM4N || SAM4C || SAM4CM || SAM4CP || SAMG || SAMV71 || SAMV70 || SAMS70 || SAME70)
278  SCB->SCR &= (uint32_t)~SCR_SLEEPDEEP;
279  cpu_irq_enable();
280  __DSB();
281  __WFI();
282  break;
283 #else
284  PMC->PMC_FSMR &= (uint32_t)~PMC_FSMR_LPM;
285  SCB->SCR &= (uint32_t)~SCR_SLEEPDEEP;
286  cpu_irq_enable();
287  if (sleep_mode == SAM_PM_SMODE_SLEEP_WFI) {
288  __DSB();
289  __WFI();
290  } else {
291  __DSB();
292  __WFE();
293  }
294  break;
295 #endif
296 
297  case SAM_PM_SMODE_WAIT_FAST:
298  case SAM_PM_SMODE_WAIT: {
299  uint32_t mor, pllr0, pllr1, mckr;
300  uint32_t fmr;
301 #if defined(EFC1)
302  uint32_t fmr1;
303 #endif
304 #if (SAM4S || SAM4E || SAM4N || SAM4C || SAM4CM || SAM4CP || SAMG || SAMV71 || SAMV70 || SAMS70 || SAME70)
305  (sleep_mode == SAM_PM_SMODE_WAIT_FAST) ?
306  pmc_set_flash_in_wait_mode(PMC_FSMR_FLPM_FLASH_STANDBY) :
307  pmc_set_flash_in_wait_mode(PMC_FSMR_FLPM_FLASH_DEEP_POWERDOWN);
308 #endif
309  cpu_irq_disable();
310  b_is_sleep_clock_used = true;
311 
312 #if (SAM4C || SAM4CM || SAM4CP)
313  /* Backup the sub-system 1 status and stop sub-system 1 */
314  uint32_t cpclk_backup = PMC->PMC_SCSR &
315  (PMC_SCSR_CPCK | PMC_SCSR_CPBMCK);
316  PMC->PMC_SCDR = cpclk_backup | PMC_SCDR_CPKEY_PASSWD;
317 #endif
318  pmc_save_clock_settings(&mor, &pllr0, &pllr1, &mckr, &fmr,
319 #if defined(EFC1)
320  &fmr1,
321 #endif
322  (sleep_mode == SAM_PM_SMODE_WAIT));
323 
324  /* Enter wait mode */
325  cpu_irq_enable();
326 
328 
329  cpu_irq_disable();
330  pmc_restore_clock_setting(mor, pllr0, pllr1, mckr, fmr
331 #if defined(EFC1)
332  , fmr1
333 #endif
334  );
335 
336 #if (SAM4C || SAM4CM || SAM4CP)
337  /* Restore the sub-system 1 */
338  PMC->PMC_SCER = cpclk_backup | PMC_SCER_CPKEY_PASSWD;
339 #endif
340  b_is_sleep_clock_used = false;
341  if (callback_clocks_restored) {
342  callback_clocks_restored();
343  callback_clocks_restored = NULL;
344  }
345  cpu_irq_enable();
346 
347  break;
348  }
349 #if (!(SAMG51 || SAMG53 || SAMG54))
350  case SAM_PM_SMODE_BACKUP:
351  SCB->SCR |= SCR_SLEEPDEEP;
352 #if (SAM4S || SAM4E || SAM4N || SAM4C || SAM4CM || SAM4CP || SAMG55 || SAMV71 || SAMV70 || SAMS70 || SAME70)
354  cpu_irq_enable();
355  __WFI() ;
356 #else
357  cpu_irq_enable();
358  __WFE() ;
359 #endif
360  break;
361 #endif
362  }
363 }
364 
365 bool pmc_is_wakeup_clocks_restored(void)
366 {
367  return !b_is_sleep_clock_used;
368 }
369 
370 void pmc_wait_wakeup_clocks_restore(
371  pmc_callback_wakeup_clocks_restored_t callback)
372 {
373  if (b_is_sleep_clock_used) {
374  cpu_irq_disable();
375  callback_clocks_restored = callback;
376  } else if (callback) {
377  callback();
378  }
379 }
380 
381 #endif
#define cpu_irq_disable()
Disable interrupts globally.
#define CKGR_MOR_MOSCSEL
(CKGR_MOR) Main Oscillator Selection
#define CKGR_MOR_MOSCXTBY
(CKGR_MOR) Main Crystal Oscillator Bypass
#define PMC
(PMC ) Base Address
Definition: same70j19.h:524
#define CKGR_MOR_MOSCRCF_Msk
(CKGR_MOR) Main On-Chip RC Oscillator Frequency Selection
#define UNUSED(v)
Marking v as a unused parameter or value.
Definition: compiler.h:86
#define CKGR_PLLAR_MULA_Msk
(CKGR_PLLAR) PLLA Multiplier
#define PMC_FSMR_FLPM_FLASH_DEEP_POWERDOWN
(PMC_FSMR) Flash is in Deep-power-down mode when system enters Wait Mode
#define PMC_FSMR_FLPM_FLASH_STANDBY
(PMC_FSMR) Flash is in Standby Mode when system enters Wait Mode
#define CKGR_MOR_MOSCRCEN
(CKGR_MOR) Main On-Chip RC Oscillator Enable
void pmc_enable_waitmode(void)
Enable Wait Mode. Enter condition: WFE + (SLEEPDEEP bit = 0) + (LPM bit = 1)
Definition: pmc.c:1433
#define CKGR_UCKR_UPLLEN
(CKGR_UCKR) UTMI PLL Enable
#define PMC_SR_MOSCXTS
(PMC_SR) Main Crystal Oscillator Status
#define NULL
Definition: nm_bsp.h:52
#define PMC_SR_MOSCRCS
(PMC_SR) Main On-Chip RC Oscillator Status
Commonly used includes, types and macros.
#define PMC_FSMR_LPM
(PMC_FSMR) Low-power Mode
#define SCB
Definition: core_cm7.h:1599
#define EEFC_FMR_FWS(value)
#define PMC_MCKR_CSS_MAIN_CLK
(PMC_MCKR) Main Clock is selected
#define CKGR_PLLAR_ONE
(CKGR_PLLAR) Must Be Set to 1
#define CKGR_MOR_MOSCXTEN
(CKGR_MOR) Main Crystal Oscillator Enable
#define PMC_SR_LOCKA
(PMC_SR) PLLA Lock Status
#define PMC_SR_MOSCSELS
(PMC_SR) Main Oscillator Selection Status
#define PMC_SR_MCKRDY
(PMC_SR) Master Clock Status
#define PMC_MCKR_CSS_PLLA_CLK
(PMC_MCKR) PLLA Clock is selected
#define SUPC
(SUPC ) Base Address
Definition: same70j19.h:533
#define PMC_SR_LOCKU
(PMC_SR) UTMI PLL Lock Status
#define PMC_MCKR_PRES_Msk
(PMC_MCKR) Processor Clock Prescaler
#define PMC_MCKR_CSS_UPLL_CLK
(PMC_MCKR) Divided UPLL Clock is selected
#define SUPC_CR_KEY_PASSWD
#define SUPC_CR_VROFF_STOP_VREG
(SUPC_CR) If KEY is correct, VROFF asserts the vddcore_nreset and stops the voltage regulator...
#define EEFC_FMR_FWS_Msk
(EEFC_FMR) Flash Wait State
Standard board header file.
#define PMC_MCKR_CSS_Msk
(PMC_MCKR) Master Clock Source Selection
void pmc_disable_pllack(void)
Disable PLLA clock.
Definition: pmc.c:576
#define cpu_irq_enable()
Enable interrupts globally.
#define CKGR_MOR_KEY_PASSWD
Sleep mode access.


inertial_sense_ros
Author(s):
autogenerated on Sat Sep 19 2020 03:19:05