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