]> git.sur5r.net Git - freertos/blob
c2b611326f10b5e3448682683ece5ed6f840e8fc
[freertos] /
1 /***************************************************************************//**\r
2  * @file system_efm32pg1b.c\r
3  * @brief CMSIS Cortex-M3/M4 System Layer for EFM32 devices.\r
4  * @version 4.2.1\r
5  ******************************************************************************\r
6  * @section License\r
7  * <b>Copyright 2015 Silicon Laboratories, Inc. http://www.silabs.com</b>\r
8  ******************************************************************************\r
9  *\r
10  * Permission is granted to anyone to use this software for any purpose,\r
11  * including commercial applications, and to alter it and redistribute it\r
12  * freely, subject to the following restrictions:\r
13  *\r
14  * 1. The origin of this software must not be misrepresented; you must not\r
15  *    claim that you wrote the original software.@n\r
16  * 2. Altered source versions must be plainly marked as such, and must not be\r
17  *    misrepresented as being the original software.@n\r
18  * 3. This notice may not be removed or altered from any source distribution.\r
19  *\r
20  * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Laboratories, Inc.\r
21  * has no obligation to support this Software. Silicon Laboratories, Inc. is\r
22  * providing the Software "AS IS", with no express or implied warranties of any\r
23  * kind, including, but not limited to, any implied warranties of\r
24  * merchantability or fitness for any particular purpose or warranties against\r
25  * infringement of any proprietary rights of a third party.\r
26  *\r
27  * Silicon Laboratories, Inc. will not be liable for any consequential,\r
28  * incidental, or special damages, or any other relief, or for any claim by\r
29  * any third party, arising from your use of this Software.\r
30  *\r
31  *****************************************************************************/\r
32 \r
33 #include <stdint.h>\r
34 #include "em_device.h"\r
35 \r
36 /*******************************************************************************\r
37  ******************************   DEFINES   ************************************\r
38  ******************************************************************************/\r
39 \r
40 /** LFRCO frequency, tuned to below frequency during manufacturing. */\r
41 #define EFM32_LFRCO_FREQ  (32768UL)\r
42 #define EFM32_ULFRCO_FREQ (1000UL)\r
43 \r
44 /*******************************************************************************\r
45  **************************   LOCAL VARIABLES   ********************************\r
46  ******************************************************************************/\r
47 \r
48 /* System oscillator frequencies. These frequencies are normally constant */\r
49 /* for a target, but they are made configurable in order to allow run-time */\r
50 /* handling of different boards. The crystal oscillator clocks can be set */\r
51 /* compile time to a non-default value by defining respective EFM_nFXO_FREQ */\r
52 /* values according to board design. By defining the EFM_nFXO_FREQ to 0, */\r
53 /* one indicates that the oscillator is not present, in order to save some */\r
54 /* SW footprint. */\r
55 \r
56 #ifndef EFM32_HFRCO_MAX_FREQ\r
57 #define EFM32_HFRCO_MAX_FREQ            (38000000UL)\r
58 #endif\r
59 \r
60 #ifndef EFM32_HFXO_FREQ\r
61 #define EFM32_HFXO_FREQ                 (40000000UL)\r
62 #endif\r
63 \r
64 #ifndef EFM32_HFRCO_STARTUP_FREQ\r
65 #define EFM32_HFRCO_STARTUP_FREQ        (19000000UL)\r
66 #endif\r
67 \r
68 \r
69 /* Do not define variable if HF crystal oscillator not present */\r
70 #if (EFM32_HFXO_FREQ > 0UL)\r
71 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
72 /** System HFXO clock. */\r
73 static uint32_t SystemHFXOClock = EFM32_HFXO_FREQ;\r
74 /** @endcond (DO_NOT_INCLUDE_WITH_DOXYGEN) */\r
75 #endif\r
76 \r
77 #ifndef EFM32_LFXO_FREQ\r
78 #define EFM32_LFXO_FREQ (EFM32_LFRCO_FREQ)\r
79 #endif\r
80 /* Do not define variable if LF crystal oscillator not present */\r
81 #if (EFM32_LFXO_FREQ > 0UL)\r
82 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
83 /** System LFXO clock. */\r
84 static uint32_t SystemLFXOClock = 32768UL;\r
85 /** @endcond (DO_NOT_INCLUDE_WITH_DOXYGEN) */\r
86 #endif\r
87 \r
88 \r
89 /*******************************************************************************\r
90  **************************   GLOBAL VARIABLES   *******************************\r
91  ******************************************************************************/\r
92 \r
93 /**\r
94  * @brief\r
95  *   System System Clock Frequency (Core Clock).\r
96  *\r
97  * @details\r
98  *   Required CMSIS global variable that must be kept up-to-date.\r
99  */\r
100 uint32_t SystemCoreClock;\r
101 \r
102 \r
103 /**\r
104  * @brief\r
105  *   System HFRCO frequency\r
106  *\r
107  * @note\r
108  *   This is an EFM32 proprietary variable, not part of the CMSIS definition.\r
109  *\r
110  * @details\r
111  *   Frequency of the system HFRCO oscillator\r
112  */\r
113 uint32_t SystemHfrcoFreq = EFM32_HFRCO_STARTUP_FREQ;\r
114 \r
115 \r
116 /*******************************************************************************\r
117  **************************   GLOBAL FUNCTIONS   *******************************\r
118  ******************************************************************************/\r
119 \r
120 /***************************************************************************//**\r
121  * @brief\r
122  *   Get the current core clock frequency.\r
123  *\r
124  * @details\r
125  *   Calculate and get the current core clock frequency based on the current\r
126  *   configuration. Assuming that the SystemCoreClock global variable is\r
127  *   maintained, the core clock frequency is stored in that variable as well.\r
128  *   This function will however calculate the core clock based on actual HW\r
129  *   configuration. It will also update the SystemCoreClock global variable.\r
130  *\r
131  * @note\r
132  *   This is an EFM32 proprietary function, not part of the CMSIS definition.\r
133  *\r
134  * @return\r
135  *   The current core clock frequency in Hz.\r
136  ******************************************************************************/\r
137 uint32_t SystemCoreClockGet(void)\r
138 {\r
139   uint32_t ret;\r
140   uint32_t presc;\r
141 \r
142   ret   = SystemHFClockGet();\r
143   presc = (CMU->HFCOREPRESC & _CMU_HFCOREPRESC_PRESC_MASK) >>\r
144           _CMU_HFCOREPRESC_PRESC_SHIFT;\r
145   ret  /= (presc + 1);\r
146 \r
147   /* Keep CMSIS system clock variable up-to-date */\r
148   SystemCoreClock = ret;\r
149 \r
150   return ret;\r
151 }\r
152 \r
153 \r
154 /***************************************************************************//**\r
155  * @brief\r
156  *   Get the maximum core clock frequency.\r
157  *\r
158  * @note\r
159  *   This is an EFM32 proprietary function, not part of the CMSIS definition.\r
160  *\r
161  * @return\r
162  *   The maximum core clock frequency in Hz.\r
163  ******************************************************************************/\r
164 uint32_t SystemMaxCoreClockGet(void)\r
165 {\r
166   return (EFM32_HFRCO_MAX_FREQ > EFM32_HFXO_FREQ ? \\r
167           EFM32_HFRCO_MAX_FREQ : EFM32_HFXO_FREQ);\r
168 }\r
169 \r
170 \r
171 /***************************************************************************//**\r
172  * @brief\r
173  *   Get the current HFCLK frequency.\r
174  *\r
175  * @note\r
176  *   This is an EFM32 proprietary function, not part of the CMSIS definition.\r
177  *\r
178  * @return\r
179  *   The current HFCLK frequency in Hz.\r
180  ******************************************************************************/\r
181 uint32_t SystemHFClockGet(void)\r
182 {\r
183   uint32_t ret;\r
184 \r
185   switch (CMU->HFCLKSTATUS & _CMU_HFCLKSTATUS_SELECTED_MASK)\r
186   {\r
187     case CMU_HFCLKSTATUS_SELECTED_LFXO:\r
188 #if (EFM32_LFXO_FREQ > 0)\r
189       ret = SystemLFXOClock;\r
190 #else\r
191       /* We should not get here, since core should not be clocked. May */\r
192       /* be caused by a misconfiguration though. */\r
193       ret = 0;\r
194 #endif\r
195       break;\r
196 \r
197     case CMU_HFCLKSTATUS_SELECTED_LFRCO:\r
198       ret = EFM32_LFRCO_FREQ;\r
199       break;\r
200 \r
201     case CMU_HFCLKSTATUS_SELECTED_HFXO:\r
202 #if (EFM32_HFXO_FREQ > 0)\r
203       ret = SystemHFXOClock;\r
204 #else\r
205       /* We should not get here, since core should not be clocked. May */\r
206       /* be caused by a misconfiguration though. */\r
207       ret = 0;\r
208 #endif\r
209       break;\r
210 \r
211     default: /* CMU_HFCLKSTATUS_SELECTED_HFRCO */\r
212       ret = SystemHfrcoFreq;\r
213       break;\r
214   }\r
215 \r
216   return ret;\r
217 }\r
218 \r
219 \r
220 /**************************************************************************//**\r
221  * @brief\r
222  *   Get high frequency crystal oscillator clock frequency for target system.\r
223  *\r
224  * @note\r
225  *   This is an EFM32 proprietary function, not part of the CMSIS definition.\r
226  *\r
227  * @return\r
228  *   HFXO frequency in Hz.\r
229  *****************************************************************************/\r
230 uint32_t SystemHFXOClockGet(void)\r
231 {\r
232   /* External crystal oscillator present? */\r
233 #if (EFM32_HFXO_FREQ > 0)\r
234   return SystemHFXOClock;\r
235 #else\r
236   return 0;\r
237 #endif\r
238 }\r
239 \r
240 \r
241 /**************************************************************************//**\r
242  * @brief\r
243  *   Set high frequency crystal oscillator clock frequency for target system.\r
244  *\r
245  * @note\r
246  *   This function is mainly provided for being able to handle target systems\r
247  *   with different HF crystal oscillator frequencies run-time. If used, it\r
248  *   should probably only be used once during system startup.\r
249  *\r
250  * @note\r
251  *   This is an EFM32 proprietary function, not part of the CMSIS definition.\r
252  *\r
253  * @param[in] freq\r
254  *   HFXO frequency in Hz used for target.\r
255  *****************************************************************************/\r
256 void SystemHFXOClockSet(uint32_t freq)\r
257 {\r
258   /* External crystal oscillator present? */\r
259 #if (EFM32_HFXO_FREQ > 0)\r
260   SystemHFXOClock = freq;\r
261 \r
262   /* Update core clock frequency if HFXO is used to clock core */\r
263   if ((CMU->HFCLKSTATUS & _CMU_HFCLKSTATUS_SELECTED_MASK) == CMU_HFCLKSTATUS_SELECTED_HFXO)\r
264   {\r
265     /* The function will update the global variable */\r
266     SystemCoreClockGet();\r
267   }\r
268 #else\r
269   (void)freq; /* Unused parameter */\r
270 #endif\r
271 }\r
272 \r
273 \r
274 /**************************************************************************//**\r
275  * @brief\r
276  *   Initialize the system.\r
277  *\r
278  * @details\r
279  *   Do required generic HW system init.\r
280  *\r
281  * @note\r
282  *   This function is invoked during system init, before the main() routine\r
283  *   and any data has been initialized. For this reason, it cannot do any\r
284  *   initialization of variables etc.\r
285  *****************************************************************************/\r
286 void SystemInit(void)\r
287 {\r
288 #if (__FPU_PRESENT == 1)\r
289   /* Set floating point coprosessor access mode. */\r
290   SCB->CPACR |= ((3UL << 10 * 2) |      /* set CP10 Full Access */\r
291                  (3UL << 11 * 2));      /* set CP11 Full Access */\r
292 #endif\r
293 }\r
294 \r
295 \r
296 /**************************************************************************//**\r
297  * @brief\r
298  *   Get low frequency RC oscillator clock frequency for target system.\r
299  *\r
300  * @note\r
301  *   This is an EFM32 proprietary function, not part of the CMSIS definition.\r
302  *\r
303  * @return\r
304  *   LFRCO frequency in Hz.\r
305  *****************************************************************************/\r
306 uint32_t SystemLFRCOClockGet(void)\r
307 {\r
308   /* Currently we assume that this frequency is properly tuned during */\r
309   /* manufacturing and is not changed after reset. If future requirements */\r
310   /* for re-tuning by user, we can add support for that. */\r
311   return EFM32_LFRCO_FREQ;\r
312 }\r
313 \r
314 \r
315 /**************************************************************************//**\r
316  * @brief\r
317  *   Get ultra low frequency RC oscillator clock frequency for target system.\r
318  *\r
319  * @note\r
320  *   This is an EFM32 proprietary function, not part of the CMSIS definition.\r
321  *\r
322  * @return\r
323  *   ULFRCO frequency in Hz.\r
324  *****************************************************************************/\r
325 uint32_t SystemULFRCOClockGet(void)\r
326 {\r
327   /* The ULFRCO frequency is not tuned, and can be very inaccurate */\r
328   return EFM32_ULFRCO_FREQ;\r
329 }\r
330 \r
331 \r
332 /**************************************************************************//**\r
333  * @brief\r
334  *   Get low frequency crystal oscillator clock frequency for target system.\r
335  *\r
336  * @note\r
337  *   This is an EFM32 proprietary function, not part of the CMSIS definition.\r
338  *\r
339  * @return\r
340  *   LFXO frequency in Hz.\r
341  *****************************************************************************/\r
342 uint32_t SystemLFXOClockGet(void)\r
343 {\r
344   /* External crystal oscillator present? */\r
345 #if (EFM32_LFXO_FREQ > 0)\r
346   return SystemLFXOClock;\r
347 #else\r
348   return 0;\r
349 #endif\r
350 }\r
351 \r
352 \r
353 /**************************************************************************//**\r
354  * @brief\r
355  *   Set low frequency crystal oscillator clock frequency for target system.\r
356  *\r
357  * @note\r
358  *   This function is mainly provided for being able to handle target systems\r
359  *   with different HF crystal oscillator frequencies run-time. If used, it\r
360  *   should probably only be used once during system startup.\r
361  *\r
362  * @note\r
363  *   This is an EFM32 proprietary function, not part of the CMSIS definition.\r
364  *\r
365  * @param[in] freq\r
366  *   LFXO frequency in Hz used for target.\r
367  *****************************************************************************/\r
368 void SystemLFXOClockSet(uint32_t freq)\r
369 {\r
370   /* External crystal oscillator present? */\r
371 #if (EFM32_LFXO_FREQ > 0)\r
372   SystemLFXOClock = freq;\r
373 \r
374   /* Update core clock frequency if LFXO is used to clock core */\r
375   if ((CMU->HFCLKSTATUS & _CMU_HFCLKSTATUS_SELECTED_MASK) == CMU_HFCLKSTATUS_SELECTED_LFXO)\r
376   {\r
377     /* The function will update the global variable */\r
378     SystemCoreClockGet();\r
379   }\r
380 #else\r
381   (void)freq; /* Unused parameter */\r
382 #endif\r
383 }\r