]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M4_ATSAM4S_Atmel_Studio/src/asf/sam/drivers/pmc/sleep.h
Add FreeRTOS-Plus directory.
[freertos] / FreeRTOS / Demo / CORTEX_M4_ATSAM4S_Atmel_Studio / src / asf / sam / drivers / pmc / sleep.h
1 /**\r
2  * \file\r
3  *\r
4  * \brief Sleep mode access\r
5  *\r
6  * Copyright (c) 2012 Atmel Corporation. All rights reserved.\r
7  *\r
8  * \asf_license_start\r
9  *\r
10  * Redistribution and use in source and binary forms, with or without\r
11  * modification, are permitted provided that the following conditions are met:\r
12  *\r
13  * 1. Redistributions of source code must retain the above copyright notice,\r
14  *    this list of conditions and the following disclaimer.\r
15  *\r
16  * 2. Redistributions in binary form must reproduce the above copyright notice,\r
17  *    this list of conditions and the following disclaimer in the documentation\r
18  *    and/or other materials provided with the distribution.\r
19  *\r
20  * 3. The name of Atmel may not be used to endorse or promote products derived\r
21  *    from this software without specific prior written permission.\r
22  *\r
23  * 4. This software may only be redistributed and used in connection with an\r
24  *    Atmel microcontroller product.\r
25  *\r
26  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
27  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
28  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
29  * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
30  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\r
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\r
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\r
34  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
35  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
36  * POSSIBILITY OF SUCH DAMAGE.\r
37  *\r
38  * \asf_license_stop\r
39  *\r
40  */\r
41 \r
42 #ifndef SLEEP_H\r
43 #define SLEEP_H\r
44 \r
45 #ifdef __cplusplus\r
46 extern "C" {\r
47 #endif\r
48 \r
49 #include <compiler.h>\r
50 \r
51 /**\r
52  * \defgroup sleep_group Power Manager (PM)\r
53  *\r
54  * This is a stub on the SAM Power Manager Control (PMC) for the sleepmgr service.\r
55  *\r
56  * \note To minimize the code overhead, these functions do not feature\r
57  * interrupt-protected access since they are likely to be called inside\r
58  * interrupt handlers or in applications where such protection is not\r
59  * necessary. If such protection is needed, it must be ensured by the calling\r
60  * code.\r
61  *\r
62  * @{\r
63  */\r
64 \r
65 #if defined(__DOXYGEN__)\r
66 /**\r
67  * \brief Sets the MCU in the specified sleep mode\r
68  * \param sleep_mode Sleep mode to set.\r
69  */\r
70 #endif\r
71 \r
72 #if (SAM3S || SAM3N || SAM3XA || SAM3U || SAM4S) // SAM3 and SAM4 series\r
73 # include "pmc.h"\r
74 \r
75 # define  SAM_PM_SMODE_ACTIVE     0\r
76 # define  SAM_PM_SMODE_SLEEP_WFE  1\r
77 # define  SAM_PM_SMODE_SLEEP_WFI  2\r
78 # define  SAM_PM_SMODE_WAIT       3\r
79 # define  SAM_PM_SMODE_BACKUP     4\r
80 \r
81 /* (SCR) Sleep deep bit */\r
82 #define SCR_SLEEPDEEP   (0x1 <<  2)\r
83 \r
84 /**\r
85  * Save clock settings and shutdown PLLs\r
86  */\r
87 static inline void pmc_save_clock_settings(\r
88                 uint32_t *p_osc_setting,\r
89                 uint32_t *p_pll0_setting,\r
90                 uint32_t *p_pll1_setting,\r
91                 uint32_t *p_mck_setting)\r
92 {\r
93         if (p_osc_setting) {\r
94                 *p_osc_setting = PMC->CKGR_MOR;\r
95         }\r
96         if (p_pll0_setting) {\r
97                 *p_pll0_setting = PMC->CKGR_PLLAR;\r
98         }\r
99         if (p_pll1_setting) {\r
100 #if SAM3S||SAM4S\r
101                 *p_pll1_setting = PMC->CKGR_PLLBR;\r
102 #elif SAM3U||SAM3XA\r
103                 *p_pll1_setting = PMC->CKGR_UCKR;\r
104 #else\r
105                 *p_pll1_setting = 0;\r
106 #endif\r
107         }\r
108         if (p_mck_setting) {\r
109                 *p_mck_setting  = PMC->PMC_MCKR;\r
110         }\r
111 \r
112         // Switch MCK to Main clock (internal or external 12MHz) for fast wakeup\r
113         // If MAIN_CLK is already the source, just skip\r
114         if ((PMC->PMC_MCKR & PMC_MCKR_CSS_Msk) == PMC_MCKR_CSS_MAIN_CLK) {\r
115                 return;\r
116         }\r
117         // If we have to enable the MAIN_CLK\r
118         if ((PMC->PMC_SR & PMC_SR_MOSCXTS) == 0) {\r
119                 // Intend to use internal RC as source of MAIN_CLK\r
120                 pmc_osc_enable_fastrc(CKGR_MOR_MOSCRCF_12_MHz);\r
121                 pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_12_MHz);\r
122         }\r
123         pmc_switch_mck_to_mainck(PMC_MCKR_PRES_CLK_1);\r
124 }\r
125 \r
126 /**\r
127  * Restore clock settings\r
128  */\r
129 static inline void pmc_restore_clock_setting(\r
130                 uint32_t osc_setting,\r
131                 uint32_t pll0_setting,\r
132                 uint32_t pll1_setting,\r
133                 uint32_t mck_setting)\r
134 {\r
135         uint32_t mckr;\r
136         if ((pll0_setting & CKGR_PLLAR_MULA_Msk) &&\r
137                 pll0_setting != PMC->CKGR_PLLAR) {\r
138                 PMC->CKGR_PLLAR = 0;\r
139                 PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | pll0_setting;\r
140                 while (!(PMC->PMC_SR & PMC_SR_LOCKA));\r
141         }\r
142 #if SAM3S||SAM4S\r
143         if ((pll1_setting & CKGR_PLLBR_MULB_Msk) &&\r
144                 pll1_setting != PMC->CKGR_PLLBR) {\r
145                 PMC->CKGR_PLLBR = 0;\r
146                 PMC->CKGR_PLLBR = pll1_setting ;\r
147                 while (!(PMC->PMC_SR & PMC_SR_LOCKB));\r
148         }\r
149 #elif SAM3U||SAM3XA\r
150         if ((pll1_setting & CKGR_UCKR_UPLLEN) &&\r
151                 pll1_setting != PMC->CKGR_UCKR) {\r
152                 PMC->CKGR_UCKR = 0;\r
153                 PMC->CKGR_UCKR = pll1_setting;\r
154                 while (!(PMC->PMC_SR & PMC_SR_LOCKU));\r
155         }\r
156 #endif\r
157         /* Switch to faster clock */\r
158         mckr = PMC->PMC_MCKR;\r
159         // Set PRES\r
160         PMC->PMC_MCKR = (mckr & ~PMC_MCKR_PRES_Msk)\r
161                 | (mck_setting & PMC_MCKR_PRES_Msk);\r
162         while (!(PMC->PMC_SR & PMC_SR_MCKRDY));\r
163         // Set CSS and others\r
164         PMC->PMC_MCKR = mck_setting;\r
165         while (!(PMC->PMC_SR & PMC_SR_MCKRDY));\r
166         /* Shutdown fastrc */\r
167         if (0 == (osc_setting & CKGR_MOR_MOSCRCEN)) {\r
168                 pmc_osc_disable_fastrc();\r
169         }\r
170 }\r
171 \r
172 static inline void pmc_sleep(int sleep_mode)\r
173 {\r
174         switch (sleep_mode) {\r
175         case SAM_PM_SMODE_SLEEP_WFI:\r
176         case SAM_PM_SMODE_SLEEP_WFE:\r
177                 PMC->PMC_FSMR &= (uint32_t)~PMC_FSMR_LPM;\r
178                 SCB->SCR &= (uint32_t)~SCR_SLEEPDEEP;\r
179                 cpu_irq_enable();\r
180                 if (sleep_mode == SAM_PM_SMODE_SLEEP_WFI)\r
181                         __WFI();\r
182                 else\r
183                         __WFE();\r
184                 break;\r
185 \r
186         case SAM_PM_SMODE_WAIT: {\r
187                 uint32_t mor, pllr0, pllr1, mckr;\r
188                 pmc_save_clock_settings(&mor, &pllr0, &pllr1, &mckr);\r
189 \r
190                 PMC->PMC_FSMR |= PMC_FSMR_LPM;\r
191                 SCB->SCR &= (uint32_t)~SCR_SLEEPDEEP ;\r
192                 cpu_irq_enable();\r
193                 __WFE();\r
194 \r
195                 cpu_irq_disable();\r
196                 pmc_restore_clock_setting(mor, pllr0, pllr1, mckr);\r
197                 cpu_irq_enable();\r
198                 break;\r
199         }\r
200 \r
201         case SAM_PM_SMODE_BACKUP:\r
202                 SCB->SCR |= SCR_SLEEPDEEP ;\r
203                 cpu_irq_enable();\r
204                 __WFE() ;\r
205                 break;\r
206         }\r
207 }\r
208 \r
209 #endif\r
210 \r
211 //! @}\r
212 \r
213 #ifdef __cplusplus\r
214 }\r
215 #endif\r
216 \r
217 #endif /* SLEEP_H */\r