00001 /***************************************************************************/ 00033 #include <stdint.h> 00034 #include "em_device.h" 00035 00036 /******************************************************************************* 00037 ****************************** DEFINES ************************************ 00038 ******************************************************************************/ 00039 00041 #define EFM32_LFRCO_FREQ (32768UL) 00042 #define EFM32_ULFRCO_FREQ (1000UL) 00043 00044 /******************************************************************************* 00045 ************************** LOCAL VARIABLES ******************************** 00046 ******************************************************************************/ 00047 00048 /* System oscillator frequencies. These frequencies are normally constant */ 00049 /* for a target, but they are made configurable in order to allow run-time */ 00050 /* handling of different boards. The crystal oscillator clocks can be set */ 00051 /* compile time to a non-default value by defining respective EFM32_nFXO_FREQ */ 00052 /* values according to board design. By defining the EFM32_nFXO_FREQ to 0, */ 00053 /* one indicates that the oscillator is not present, in order to save some */ 00054 /* SW footprint. */ 00055 00056 #ifndef EFM32_HFXO_FREQ 00057 #define EFM32_HFXO_FREQ (24000000UL) 00058 #define EFM32_HFRCO_MAX_FREQ (21000000UL) 00059 #endif 00060 /* Do not define variable if HF crystal oscillator not present */ 00061 #if (EFM32_HFXO_FREQ > 0) 00062 00064 static uint32_t SystemHFXOClock = EFM32_HFXO_FREQ; 00066 #endif 00067 00068 #ifndef EFM32_LFXO_FREQ 00069 #define EFM32_LFXO_FREQ (EFM32_LFRCO_FREQ) 00070 #endif 00071 /* Do not define variable if LF crystal oscillator not present */ 00072 #if (EFM32_LFXO_FREQ > 0) 00073 00075 static uint32_t SystemLFXOClock = EFM32_LFXO_FREQ; 00077 #endif 00078 00079 /******************************************************************************* 00080 ************************** GLOBAL VARIABLES ******************************* 00081 ******************************************************************************/ 00082 00090 uint32_t SystemCoreClock; 00091 00092 /******************************************************************************* 00093 ************************** GLOBAL FUNCTIONS ******************************* 00094 ******************************************************************************/ 00095 00096 /***************************************************************************/ 00113 uint32_t SystemCoreClockGet(void) 00114 { 00115 uint32_t ret; 00116 00117 ret = SystemHFClockGet(); 00118 ret >>= (CMU->HFCORECLKDIV & _CMU_HFCORECLKDIV_HFCORECLKDIV_MASK) >> 00119 _CMU_HFCORECLKDIV_HFCORECLKDIV_SHIFT; 00120 00121 /* Keep CMSIS variable up-to-date just in case */ 00122 SystemCoreClock = ret; 00123 00124 return ret; 00125 } 00126 00127 00128 /***************************************************************************/ 00138 uint32_t SystemMaxCoreClockGet(void) 00139 { 00140 return (EFM32_HFRCO_MAX_FREQ > EFM32_HFXO_FREQ ? \ 00141 EFM32_HFRCO_MAX_FREQ : EFM32_HFXO_FREQ); 00142 } 00143 00144 00145 /***************************************************************************/ 00155 uint32_t SystemHFClockGet(void) 00156 { 00157 uint32_t ret; 00158 00159 switch (CMU->STATUS & (CMU_STATUS_HFRCOSEL | CMU_STATUS_HFXOSEL 00160 | CMU_STATUS_LFRCOSEL | CMU_STATUS_LFXOSEL 00161 #if defined(CMU_STATUS_USHFRCODIV2SEL) 00162 | CMU_STATUS_USHFRCODIV2SEL 00163 #endif 00164 )) 00165 { 00166 case CMU_STATUS_LFXOSEL: 00167 #if (EFM32_LFXO_FREQ > 0) 00168 ret = SystemLFXOClock; 00169 #else 00170 /* We should not get here, since core should not be clocked. May */ 00171 /* be caused by a misconfiguration though. */ 00172 ret = 0; 00173 #endif 00174 break; 00175 00176 case CMU_STATUS_LFRCOSEL: 00177 ret = EFM32_LFRCO_FREQ; 00178 break; 00179 00180 case CMU_STATUS_HFXOSEL: 00181 #if (EFM32_HFXO_FREQ > 0) 00182 ret = SystemHFXOClock; 00183 #else 00184 /* We should not get here, since core should not be clocked. May */ 00185 /* be caused by a misconfiguration though. */ 00186 ret = 0; 00187 #endif 00188 break; 00189 00190 #if defined(CMU_STATUS_USHFRCODIV2SEL) 00191 case CMU_STATUS_USHFRCODIV2SEL: 00192 ret = 24000000; 00193 break; 00194 #endif 00195 00196 default: /* CMU_STATUS_HFRCOSEL */ 00197 switch (CMU->HFRCOCTRL & _CMU_HFRCOCTRL_BAND_MASK) 00198 { 00199 case CMU_HFRCOCTRL_BAND_21MHZ: 00200 ret = 21000000; 00201 break; 00202 00203 case CMU_HFRCOCTRL_BAND_14MHZ: 00204 ret = 14000000; 00205 break; 00206 00207 case CMU_HFRCOCTRL_BAND_11MHZ: 00208 ret = 11000000; 00209 break; 00210 00211 case CMU_HFRCOCTRL_BAND_7MHZ: 00212 ret = 6600000; 00213 break; 00214 00215 case CMU_HFRCOCTRL_BAND_1MHZ: 00216 ret = 1200000; 00217 break; 00218 00219 default: 00220 ret = 0; 00221 break; 00222 } 00223 break; 00224 } 00225 00226 return ret; 00227 } 00228 00229 00230 /**************************************************************************/ 00240 uint32_t SystemHFXOClockGet(void) 00241 { 00242 /* External crystal oscillator present? */ 00243 #if (EFM32_HFXO_FREQ > 0) 00244 return SystemHFXOClock; 00245 #else 00246 return 0; 00247 #endif 00248 } 00249 00250 00251 /**************************************************************************/ 00266 void SystemHFXOClockSet(uint32_t freq) 00267 { 00268 /* External crystal oscillator present? */ 00269 #if (EFM32_HFXO_FREQ > 0) 00270 SystemHFXOClock = freq; 00271 00272 /* Update core clock frequency if HFXO is used to clock core */ 00273 if (CMU->STATUS & CMU_STATUS_HFXOSEL) 00274 { 00275 /* The function will update the global variable */ 00276 SystemCoreClockGet(); 00277 } 00278 #else 00279 (void)freq; /* Unused parameter */ 00280 #endif 00281 } 00282 00283 00284 /**************************************************************************/ 00296 void SystemInit(void) 00297 { 00298 } 00299 00300 00301 /**************************************************************************/ 00311 uint32_t SystemLFRCOClockGet(void) 00312 { 00313 /* Currently we assume that this frequency is properly tuned during */ 00314 /* manufacturing and is not changed after reset. If future requirements */ 00315 /* for re-tuning by user, we can add support for that. */ 00316 return EFM32_LFRCO_FREQ; 00317 } 00318 00319 00320 /**************************************************************************/ 00330 uint32_t SystemULFRCOClockGet(void) 00331 { 00332 /* The ULFRCO frequency is not tuned, and can be very inaccurate */ 00333 return EFM32_ULFRCO_FREQ; 00334 } 00335 00336 00337 /**************************************************************************/ 00347 uint32_t SystemLFXOClockGet(void) 00348 { 00349 /* External crystal oscillator present? */ 00350 #if (EFM32_LFXO_FREQ > 0) 00351 return SystemLFXOClock; 00352 #else 00353 return 0; 00354 #endif 00355 } 00356 00357 00358 /**************************************************************************/ 00373 void SystemLFXOClockSet(uint32_t freq) 00374 { 00375 /* External crystal oscillator present? */ 00376 #if (EFM32_LFXO_FREQ > 0) 00377 SystemLFXOClock = freq; 00378 00379 /* Update core clock frequency if LFXO is used to clock core */ 00380 if (CMU->STATUS & CMU_STATUS_LFXOSEL) 00381 { 00382 /* The function will update the global variable */ 00383 SystemCoreClockGet(); 00384 } 00385 #else 00386 (void)freq; /* Unused parameter */ 00387 #endif 00388 }