--- /dev/null
+/***************************************************************************//**\r
+ * @file system_efm32gg.c\r
+ * @brief CMSIS Cortex-M3 System Layer for EFM32GG devices.\r
+ * @version 4.0.0\r
+ ******************************************************************************\r
+ * @section License\r
+ * <b>(C) Copyright 2015 Silicon Laboratories, Inc. http://www.silabs.com</b>\r
+ ******************************************************************************\r
+ *\r
+ * Permission is granted to anyone to use this software for any purpose,\r
+ * including commercial applications, and to alter it and redistribute it\r
+ * freely, subject to the following restrictions:\r
+ *\r
+ * 1. The origin of this software must not be misrepresented; you must not\r
+ * claim that you wrote the original software.@n\r
+ * 2. Altered source versions must be plainly marked as such, and must not be\r
+ * misrepresented as being the original software.@n\r
+ * 3. This notice may not be removed or altered from any source distribution.\r
+ *\r
+ * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Laboratories, Inc.\r
+ * has no obligation to support this Software. Silicon Laboratories, Inc. is\r
+ * providing the Software "AS IS", with no express or implied warranties of any\r
+ * kind, including, but not limited to, any implied warranties of\r
+ * merchantability or fitness for any particular purpose or warranties against\r
+ * infringement of any proprietary rights of a third party.\r
+ *\r
+ * Silicon Laboratories, Inc. will not be liable for any consequential,\r
+ * incidental, or special damages, or any other relief, or for any claim by\r
+ * any third party, arising from your use of this Software.\r
+ *\r
+ *****************************************************************************/\r
+\r
+#include <stdint.h>\r
+#include "em_device.h"\r
+\r
+/*******************************************************************************\r
+ ****************************** DEFINES ************************************\r
+ ******************************************************************************/\r
+\r
+/** LFRCO frequency, tuned to below frequency during manufacturing. */\r
+#define EFM32_LFRCO_FREQ (32768UL)\r
+#define EFM32_ULFRCO_FREQ (1000UL)\r
+\r
+/*******************************************************************************\r
+ ************************** LOCAL VARIABLES ********************************\r
+ ******************************************************************************/\r
+\r
+/* System oscillator frequencies. These frequencies are normally constant */\r
+/* for a target, but they are made configurable in order to allow run-time */\r
+/* handling of different boards. The crystal oscillator clocks can be set */\r
+/* compile time to a non-default value by defining respective EFM32_nFXO_FREQ */\r
+/* values according to board design. By defining the EFM32_nFXO_FREQ to 0, */\r
+/* one indicates that the oscillator is not present, in order to save some */\r
+/* SW footprint. */\r
+\r
+#ifndef EFM32_HFXO_FREQ\r
+#ifdef _EFM32_GIANT_FAMILY\r
+#define EFM32_HFXO_FREQ (48000000UL)\r
+#else\r
+#define EFM32_HFXO_FREQ (32000000UL)\r
+#endif\r
+#endif\r
+/* Do not define variable if HF crystal oscillator not present */\r
+#if (EFM32_HFXO_FREQ > 0)\r
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
+/** System HFXO clock. */ \r
+static uint32_t SystemHFXOClock = EFM32_HFXO_FREQ;\r
+/** @endcond (DO_NOT_INCLUDE_WITH_DOXYGEN) */\r
+#endif\r
+\r
+#ifndef EFM32_LFXO_FREQ \r
+#define EFM32_LFXO_FREQ (EFM32_LFRCO_FREQ)\r
+#endif\r
+/* Do not define variable if LF crystal oscillator not present */\r
+#if (EFM32_LFXO_FREQ > 0)\r
+/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */\r
+/** System LFXO clock. */ \r
+static uint32_t SystemLFXOClock = EFM32_LFXO_FREQ;\r
+/** @endcond (DO_NOT_INCLUDE_WITH_DOXYGEN) */\r
+#endif\r
+\r
+/* Inline function to get the chip's Production Revision. */\r
+__STATIC_INLINE uint8_t GetProdRev(void)\r
+{\r
+ return ((DEVINFO->PART & _DEVINFO_PART_PROD_REV_MASK)\r
+ >> _DEVINFO_PART_PROD_REV_SHIFT);\r
+}\r
+\r
+/*******************************************************************************\r
+ ************************** GLOBAL VARIABLES *******************************\r
+ ******************************************************************************/\r
+\r
+/**\r
+ * @brief\r
+ * System System Clock Frequency (Core Clock).\r
+ *\r
+ * @details\r
+ * Required CMSIS global variable that must be kept up-to-date.\r
+ */\r
+uint32_t SystemCoreClock;\r
+\r
+/*******************************************************************************\r
+ ************************** GLOBAL FUNCTIONS *******************************\r
+ ******************************************************************************/\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get the current core clock frequency.\r
+ *\r
+ * @details\r
+ * Calculate and get the current core clock frequency based on the current\r
+ * configuration. Assuming that the SystemCoreClock global variable is\r
+ * maintained, the core clock frequency is stored in that variable as well.\r
+ * This function will however calculate the core clock based on actual HW\r
+ * configuration. It will also update the SystemCoreClock global variable.\r
+ *\r
+ * @note\r
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.\r
+ *\r
+ * @return\r
+ * The current core clock frequency in Hz.\r
+ ******************************************************************************/\r
+uint32_t SystemCoreClockGet(void)\r
+{\r
+ uint32_t ret;\r
+ \r
+ ret = SystemHFClockGet();\r
+#if defined (_EFM32_GIANT_FAMILY)\r
+ /* Leopard/Giant Gecko has an additional divider */\r
+ ret = ret / (1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK)>>_CMU_CTRL_HFCLKDIV_SHIFT));\r
+#endif\r
+ ret >>= (CMU->HFCORECLKDIV & _CMU_HFCORECLKDIV_HFCORECLKDIV_MASK) >> \r
+ _CMU_HFCORECLKDIV_HFCORECLKDIV_SHIFT;\r
+\r
+ /* Keep CMSIS variable up-to-date just in case */\r
+ SystemCoreClock = ret;\r
+\r
+ return ret;\r
+}\r
+\r
+\r
+/***************************************************************************//**\r
+ * @brief\r
+ * Get the current HFCLK frequency.\r
+ *\r
+ * @note\r
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.\r
+ *\r
+ * @return\r
+ * The current HFCLK frequency in Hz.\r
+ ******************************************************************************/\r
+uint32_t SystemHFClockGet(void)\r
+{\r
+ uint32_t ret;\r
+ \r
+ switch (CMU->STATUS & (CMU_STATUS_HFRCOSEL | CMU_STATUS_HFXOSEL |\r
+ CMU_STATUS_LFRCOSEL | CMU_STATUS_LFXOSEL))\r
+ {\r
+ case CMU_STATUS_LFXOSEL:\r
+#if (EFM32_LFXO_FREQ > 0)\r
+ ret = SystemLFXOClock;\r
+#else\r
+ /* We should not get here, since core should not be clocked. May */\r
+ /* be caused by a misconfiguration though. */\r
+ ret = 0;\r
+#endif\r
+ break;\r
+ \r
+ case CMU_STATUS_LFRCOSEL:\r
+ ret = EFM32_LFRCO_FREQ;\r
+ break;\r
+ \r
+ case CMU_STATUS_HFXOSEL:\r
+#if (EFM32_HFXO_FREQ > 0)\r
+ ret = SystemHFXOClock;\r
+#else\r
+ /* We should not get here, since core should not be clocked. May */\r
+ /* be caused by a misconfiguration though. */\r
+ ret = 0;\r
+#endif\r
+ break;\r
+ \r
+ default: /* CMU_STATUS_HFRCOSEL */\r
+ switch (CMU->HFRCOCTRL & _CMU_HFRCOCTRL_BAND_MASK)\r
+ {\r
+ case CMU_HFRCOCTRL_BAND_28MHZ:\r
+ ret = 28000000;\r
+ break;\r
+\r
+ case CMU_HFRCOCTRL_BAND_21MHZ:\r
+ ret = 21000000;\r
+ break;\r
+\r
+ case CMU_HFRCOCTRL_BAND_14MHZ:\r
+ ret = 14000000;\r
+ break;\r
+\r
+ case CMU_HFRCOCTRL_BAND_11MHZ:\r
+ ret = 11000000;\r
+ break;\r
+\r
+ case CMU_HFRCOCTRL_BAND_7MHZ:\r
+ if ( GetProdRev() >= 19 )\r
+ ret = 6600000;\r
+ else\r
+ ret = 7000000;\r
+ break;\r
+\r
+ case CMU_HFRCOCTRL_BAND_1MHZ:\r
+ if ( GetProdRev() >= 19 )\r
+ ret = 1200000;\r
+ else\r
+ ret = 1000000;\r
+ break;\r
+\r
+ default:\r
+ ret = 0;\r
+ break;\r
+ }\r
+ break;\r
+ }\r
+\r
+ return ret;\r
+}\r
+\r
+\r
+/**************************************************************************//**\r
+ * @brief\r
+ * Get high frequency crystal oscillator clock frequency for target system.\r
+ *\r
+ * @note\r
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.\r
+ *\r
+ * @return\r
+ * HFXO frequency in Hz.\r
+ *****************************************************************************/\r
+uint32_t SystemHFXOClockGet(void)\r
+{\r
+ /* External crystal oscillator present? */\r
+#if (EFM32_HFXO_FREQ > 0)\r
+ return SystemHFXOClock;\r
+#else\r
+ return 0;\r
+#endif\r
+}\r
+\r
+\r
+/**************************************************************************//**\r
+ * @brief\r
+ * Set high frequency crystal oscillator clock frequency for target system.\r
+ *\r
+ * @note\r
+ * This function is mainly provided for being able to handle target systems\r
+ * with different HF crystal oscillator frequencies run-time. If used, it\r
+ * should probably only be used once during system startup.\r
+ *\r
+ * @note\r
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.\r
+ *\r
+ * @param[in] freq\r
+ * HFXO frequency in Hz used for target.\r
+ *****************************************************************************/\r
+void SystemHFXOClockSet(uint32_t freq)\r
+{\r
+ /* External crystal oscillator present? */\r
+#if (EFM32_HFXO_FREQ > 0)\r
+ SystemHFXOClock = freq;\r
+\r
+ /* Update core clock frequency if HFXO is used to clock core */\r
+ if (CMU->STATUS & CMU_STATUS_HFXOSEL)\r
+ {\r
+ /* The function will update the global variable */\r
+ SystemCoreClockGet();\r
+ }\r
+#else\r
+ (void)freq; /* Unused parameter */\r
+#endif\r
+}\r
+\r
+\r
+/**************************************************************************//**\r
+ * @brief\r
+ * Initialize the system.\r
+ *\r
+ * @details\r
+ * Do required generic HW system init.\r
+ *\r
+ * @note\r
+ * This function is invoked during system init, before the main() routine\r
+ * and any data has been initialized. For this reason, it cannot do any\r
+ * initialization of variables etc.\r
+ *****************************************************************************/\r
+void SystemInit(void)\r
+{\r
+}\r
+\r
+\r
+/**************************************************************************//**\r
+ * @brief\r
+ * Get low frequency RC oscillator clock frequency for target system.\r
+ *\r
+ * @note\r
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.\r
+ *\r
+ * @return\r
+ * LFRCO frequency in Hz.\r
+ *****************************************************************************/\r
+uint32_t SystemLFRCOClockGet(void)\r
+{\r
+ /* Currently we assume that this frequency is properly tuned during */\r
+ /* manufacturing and is not changed after reset. If future requirements */\r
+ /* for re-tuning by user, we can add support for that. */\r
+ return EFM32_LFRCO_FREQ;\r
+}\r
+\r
+\r
+/**************************************************************************//**\r
+ * @brief\r
+ * Get ultra low frequency RC oscillator clock frequency for target system.\r
+ *\r
+ * @note\r
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.\r
+ *\r
+ * @return\r
+ * ULFRCO frequency in Hz.\r
+ *****************************************************************************/\r
+uint32_t SystemULFRCOClockGet(void)\r
+{\r
+ /* The ULFRCO frequency is not tuned, and can be very inaccurate */\r
+ return EFM32_ULFRCO_FREQ;\r
+}\r
+\r
+\r
+/**************************************************************************//**\r
+ * @brief\r
+ * Get low frequency crystal oscillator clock frequency for target system.\r
+ *\r
+ * @note\r
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.\r
+ *\r
+ * @return\r
+ * LFXO frequency in Hz.\r
+ *****************************************************************************/\r
+uint32_t SystemLFXOClockGet(void)\r
+{\r
+ /* External crystal oscillator present? */\r
+#if (EFM32_LFXO_FREQ > 0)\r
+ return SystemLFXOClock;\r
+#else\r
+ return 0;\r
+#endif\r
+}\r
+\r
+\r
+/**************************************************************************//**\r
+ * @brief\r
+ * Set low frequency crystal oscillator clock frequency for target system.\r
+ *\r
+ * @note\r
+ * This function is mainly provided for being able to handle target systems\r
+ * with different HF crystal oscillator frequencies run-time. If used, it\r
+ * should probably only be used once during system startup.\r
+ *\r
+ * @note\r
+ * This is an EFM32 proprietary function, not part of the CMSIS definition.\r
+ *\r
+ * @param[in] freq\r
+ * LFXO frequency in Hz used for target.\r
+ *****************************************************************************/\r
+void SystemLFXOClockSet(uint32_t freq)\r
+{\r
+ /* External crystal oscillator present? */\r
+#if (EFM32_LFXO_FREQ > 0)\r
+ SystemLFXOClock = freq;\r
+\r
+ /* Update core clock frequency if LFXO is used to clock core */\r
+ if (CMU->STATUS & CMU_STATUS_LFXOSEL)\r
+ {\r
+ /* The function will update the global variable */\r
+ SystemCoreClockGet();\r
+ }\r
+#else\r
+ (void)freq; /* Unused parameter */\r
+#endif\r
+}\r