release/EM_CMSIS_P1_4.0.0/Device/SiliconLabs/EFM32G/Source/system_efm32g.c

Go to the documentation of this file.
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 #ifdef _EFM32_GIANT_FAMILY
00058 #define EFM32_HFXO_FREQ (48000000UL)
00059 #else
00060 #define EFM32_HFXO_FREQ (32000000UL)
00061 #endif
00062 #endif
00063 /* Do not define variable if HF crystal oscillator not present */
00064 #if (EFM32_HFXO_FREQ > 0)
00065 
00067 static uint32_t SystemHFXOClock = EFM32_HFXO_FREQ;
00069 #endif
00070 
00071 #ifndef EFM32_LFXO_FREQ 
00072 #define EFM32_LFXO_FREQ (EFM32_LFRCO_FREQ)
00073 #endif
00074 /* Do not define variable if LF crystal oscillator not present */
00075 #if (EFM32_LFXO_FREQ > 0)
00076 
00078 static uint32_t SystemLFXOClock = EFM32_LFXO_FREQ;
00080 #endif
00081 
00082 /* Inline function to get the chip's Production Revision. */
00083 __STATIC_INLINE uint8_t GetProdRev(void)
00084 {
00085   return ((DEVINFO->PART & _DEVINFO_PART_PROD_REV_MASK)
00086                          >> _DEVINFO_PART_PROD_REV_SHIFT);
00087 }
00088 
00089 /*******************************************************************************
00090  **************************   GLOBAL VARIABLES   *******************************
00091  ******************************************************************************/
00092 
00100 uint32_t SystemCoreClock;
00101 
00102 /*******************************************************************************
00103  **************************   GLOBAL FUNCTIONS   *******************************
00104  ******************************************************************************/
00105 
00106 /***************************************************************************/
00123 uint32_t SystemCoreClockGet(void)
00124 {
00125   uint32_t ret;
00126   
00127   ret = SystemHFClockGet();
00128 #if defined (_EFM32_GIANT_FAMILY)
00129   /* Leopard/Giant Gecko has an additional divider */
00130   ret =  ret / (1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK)>>_CMU_CTRL_HFCLKDIV_SHIFT));
00131 #endif
00132   ret >>= (CMU->HFCORECLKDIV & _CMU_HFCORECLKDIV_HFCORECLKDIV_MASK) >> 
00133           _CMU_HFCORECLKDIV_HFCORECLKDIV_SHIFT;
00134 
00135   /* Keep CMSIS variable up-to-date just in case */
00136   SystemCoreClock = ret;
00137 
00138   return ret;
00139 }
00140 
00141 
00142 /***************************************************************************/
00152 uint32_t SystemHFClockGet(void)
00153 {
00154   uint32_t ret;
00155   
00156   switch (CMU->STATUS & (CMU_STATUS_HFRCOSEL | CMU_STATUS_HFXOSEL |
00157                          CMU_STATUS_LFRCOSEL | CMU_STATUS_LFXOSEL))
00158   {
00159     case CMU_STATUS_LFXOSEL:
00160 #if (EFM32_LFXO_FREQ > 0)
00161       ret = SystemLFXOClock;
00162 #else
00163       /* We should not get here, since core should not be clocked. May */
00164       /* be caused by a misconfiguration though. */
00165       ret = 0;
00166 #endif
00167       break;
00168       
00169     case CMU_STATUS_LFRCOSEL:
00170       ret = EFM32_LFRCO_FREQ;
00171       break;
00172       
00173     case CMU_STATUS_HFXOSEL:
00174 #if (EFM32_HFXO_FREQ > 0)
00175       ret = SystemHFXOClock;
00176 #else
00177       /* We should not get here, since core should not be clocked. May */
00178       /* be caused by a misconfiguration though. */
00179       ret = 0;
00180 #endif
00181       break;
00182       
00183     default: /* CMU_STATUS_HFRCOSEL */
00184       switch (CMU->HFRCOCTRL & _CMU_HFRCOCTRL_BAND_MASK)
00185       {
00186       case CMU_HFRCOCTRL_BAND_28MHZ:
00187         ret = 28000000;
00188         break;
00189 
00190       case CMU_HFRCOCTRL_BAND_21MHZ:
00191         ret = 21000000;
00192         break;
00193 
00194       case CMU_HFRCOCTRL_BAND_14MHZ:
00195         ret = 14000000;
00196         break;
00197 
00198       case CMU_HFRCOCTRL_BAND_11MHZ:
00199         ret = 11000000;
00200         break;
00201 
00202       case CMU_HFRCOCTRL_BAND_7MHZ:
00203         if ( GetProdRev() >= 19 )
00204           ret = 6600000;
00205         else
00206           ret = 7000000;
00207         break;
00208 
00209       case CMU_HFRCOCTRL_BAND_1MHZ:
00210         if ( GetProdRev() >= 19 )
00211           ret = 1200000;
00212         else
00213           ret = 1000000;
00214         break;
00215 
00216       default:
00217         ret = 0;
00218         break;
00219       }
00220       break;
00221   }
00222 
00223   return ret;
00224 }
00225 
00226 
00227 /**************************************************************************/
00237 uint32_t SystemHFXOClockGet(void)
00238 {
00239   /* External crystal oscillator present? */
00240 #if (EFM32_HFXO_FREQ > 0)
00241   return SystemHFXOClock;
00242 #else
00243   return 0;
00244 #endif
00245 }
00246 
00247 
00248 /**************************************************************************/
00263 void SystemHFXOClockSet(uint32_t freq)
00264 {
00265   /* External crystal oscillator present? */
00266 #if (EFM32_HFXO_FREQ > 0)
00267   SystemHFXOClock = freq;
00268 
00269   /* Update core clock frequency if HFXO is used to clock core */
00270   if (CMU->STATUS & CMU_STATUS_HFXOSEL)
00271   {
00272     /* The function will update the global variable */
00273     SystemCoreClockGet();
00274   }
00275 #else
00276   (void)freq; /* Unused parameter */
00277 #endif
00278 }
00279 
00280 
00281 /**************************************************************************/
00293 void SystemInit(void)
00294 {
00295 }
00296 
00297 
00298 /**************************************************************************/
00308 uint32_t SystemLFRCOClockGet(void)
00309 {
00310   /* Currently we assume that this frequency is properly tuned during */
00311   /* manufacturing and is not changed after reset. If future requirements */
00312   /* for re-tuning by user, we can add support for that. */
00313   return EFM32_LFRCO_FREQ;
00314 }
00315 
00316 
00317 /**************************************************************************/
00327 uint32_t SystemULFRCOClockGet(void)
00328 {
00329   /* The ULFRCO frequency is not tuned, and can be very inaccurate */
00330   return EFM32_ULFRCO_FREQ;
00331 }
00332 
00333 
00334 /**************************************************************************/
00344 uint32_t SystemLFXOClockGet(void)
00345 {
00346   /* External crystal oscillator present? */
00347 #if (EFM32_LFXO_FREQ > 0)
00348   return SystemLFXOClock;
00349 #else
00350   return 0;
00351 #endif
00352 }
00353 
00354 
00355 /**************************************************************************/
00370 void SystemLFXOClockSet(uint32_t freq)
00371 {
00372   /* External crystal oscillator present? */
00373 #if (EFM32_LFXO_FREQ > 0)
00374   SystemLFXOClock = freq;
00375 
00376   /* Update core clock frequency if LFXO is used to clock core */
00377   if (CMU->STATUS & CMU_STATUS_LFXOSEL)
00378   {
00379     /* The function will update the global variable */
00380     SystemCoreClockGet();
00381   }
00382 #else
00383   (void)freq; /* Unused parameter */
00384 #endif
00385 }