system_efm32gg.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  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. #include <stdint.h>
  34. #include "efm32.h"
  35. /*******************************************************************************
  36. ****************************** DEFINES ************************************
  37. ******************************************************************************/
  38. /** LFRCO frequency, tuned to below frequency during manufacturing. */
  39. #define EFM32_LFRCO_FREQ (32768UL)
  40. #define EFM32_ULFRCO_FREQ (1000UL)
  41. /*******************************************************************************
  42. ************************** LOCAL VARIABLES ********************************
  43. ******************************************************************************/
  44. /* System oscillator frequencies. These frequencies are normally constant */
  45. /* for a target, but they are made configurable in order to allow run-time */
  46. /* handling of different boards. The crystal oscillator clocks can be set */
  47. /* compile time to a non-default value by defining respective EFM32_nFXO_FREQ */
  48. /* values according to board design. By defining the EFM32_nFXO_FREQ to 0, */
  49. /* one indicates that the oscillator is not present, in order to save some */
  50. /* SW footprint. */
  51. #ifndef EFM32_HFXO_FREQ
  52. #ifdef _EFM32_GIANT_FAMILY
  53. #define EFM32_HFXO_FREQ (48000000UL)
  54. #else
  55. #define EFM32_HFXO_FREQ (32000000UL)
  56. #endif
  57. #endif
  58. /* Do not define variable if HF crystal oscillator not present */
  59. #if (EFM32_HFXO_FREQ > 0)
  60. /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
  61. /** System HFXO clock. */
  62. static uint32_t SystemHFXOClock = EFM32_HFXO_FREQ;
  63. /** @endcond (DO_NOT_INCLUDE_WITH_DOXYGEN) */
  64. #endif
  65. #ifndef EFM32_LFXO_FREQ
  66. #define EFM32_LFXO_FREQ (EFM32_LFRCO_FREQ)
  67. #endif
  68. /* Do not define variable if LF crystal oscillator not present */
  69. #if (EFM32_LFXO_FREQ > 0)
  70. /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
  71. /** System LFXO clock. */
  72. static uint32_t SystemLFXOClock = EFM32_LFXO_FREQ;
  73. /** @endcond (DO_NOT_INCLUDE_WITH_DOXYGEN) */
  74. #endif
  75. /*******************************************************************************
  76. ************************** GLOBAL VARIABLES *******************************
  77. ******************************************************************************/
  78. /**
  79. * @brief
  80. * System System Clock Frequency (Core Clock).
  81. *
  82. * @details
  83. * Required CMSIS global variable that must be kept up-to-date.
  84. */
  85. uint32_t SystemCoreClock;
  86. /*******************************************************************************
  87. ************************** GLOBAL FUNCTIONS *******************************
  88. ******************************************************************************/
  89. /***************************************************************************//**
  90. * @brief
  91. * Get the current core clock frequency.
  92. *
  93. * @details
  94. * Calculate and get the current core clock frequency based on the current
  95. * configuration. Assuming that the SystemCoreClock global variable is
  96. * maintained, the core clock frequency is stored in that variable as well.
  97. * This function will however calculate the core clock based on actual HW
  98. * configuration. It will also update the SystemCoreClock global variable.
  99. *
  100. * @note
  101. * This is an EFM32 proprietary function, not part of the CMSIS definition.
  102. *
  103. * @return
  104. * The current core clock frequency in Hz.
  105. ******************************************************************************/
  106. uint32_t SystemCoreClockGet(void)
  107. {
  108. uint32_t ret;
  109. ret = SystemHFClockGet();
  110. #if defined (_EFM32_GIANT_FAMILY)
  111. /* Leopard/Giant Gecko has an additional divider */
  112. ret = ret / (1 + ((CMU->CTRL & _CMU_CTRL_HFCLKDIV_MASK)>>_CMU_CTRL_HFCLKDIV_SHIFT));
  113. #endif
  114. ret >>= (CMU->HFCORECLKDIV & _CMU_HFCORECLKDIV_HFCORECLKDIV_MASK) >>
  115. _CMU_HFCORECLKDIV_HFCORECLKDIV_SHIFT;
  116. /* Keep CMSIS variable up-to-date just in case */
  117. SystemCoreClock = ret;
  118. return ret;
  119. }
  120. /***************************************************************************//**
  121. * @brief
  122. * Get the current HFCLK frequency.
  123. *
  124. * @note
  125. * This is an EFM32 proprietary function, not part of the CMSIS definition.
  126. *
  127. * @return
  128. * The current HFCLK frequency in Hz.
  129. ******************************************************************************/
  130. uint32_t SystemHFClockGet(void)
  131. {
  132. uint32_t ret;
  133. switch (CMU->STATUS & (CMU_STATUS_HFRCOSEL | CMU_STATUS_HFXOSEL |
  134. CMU_STATUS_LFRCOSEL | CMU_STATUS_LFXOSEL))
  135. {
  136. case CMU_STATUS_LFXOSEL:
  137. #if (EFM32_LFXO_FREQ > 0)
  138. ret = SystemLFXOClock;
  139. #else
  140. /* We should not get here, since core should not be clocked. May */
  141. /* be caused by a misconfiguration though. */
  142. ret = 0;
  143. #endif
  144. break;
  145. case CMU_STATUS_LFRCOSEL:
  146. ret = EFM32_LFRCO_FREQ;
  147. break;
  148. case CMU_STATUS_HFXOSEL:
  149. #if (EFM32_HFXO_FREQ > 0)
  150. ret = SystemHFXOClock;
  151. #else
  152. /* We should not get here, since core should not be clocked. May */
  153. /* be caused by a misconfiguration though. */
  154. ret = 0;
  155. #endif
  156. break;
  157. default: /* CMU_STATUS_HFRCOSEL */
  158. switch (CMU->HFRCOCTRL & _CMU_HFRCOCTRL_BAND_MASK)
  159. {
  160. case CMU_HFRCOCTRL_BAND_28MHZ:
  161. ret = 28000000;
  162. break;
  163. case CMU_HFRCOCTRL_BAND_21MHZ:
  164. ret = 21000000;
  165. break;
  166. case CMU_HFRCOCTRL_BAND_14MHZ:
  167. ret = 14000000;
  168. break;
  169. case CMU_HFRCOCTRL_BAND_11MHZ:
  170. ret = 11000000;
  171. break;
  172. case CMU_HFRCOCTRL_BAND_7MHZ:
  173. ret = 7000000;
  174. break;
  175. case CMU_HFRCOCTRL_BAND_1MHZ:
  176. ret = 1000000;
  177. break;
  178. default:
  179. ret = 0;
  180. break;
  181. }
  182. break;
  183. }
  184. return ret;
  185. }
  186. /**************************************************************************//**
  187. * @brief
  188. * Get high frequency crystal oscillator clock frequency for target system.
  189. *
  190. * @note
  191. * This is an EFM32 proprietary function, not part of the CMSIS definition.
  192. *
  193. * @return
  194. * HFXO frequency in Hz.
  195. *****************************************************************************/
  196. uint32_t SystemHFXOClockGet(void)
  197. {
  198. /* External crystal oscillator present? */
  199. #if (EFM32_HFXO_FREQ > 0)
  200. return SystemHFXOClock;
  201. #else
  202. return 0;
  203. #endif
  204. }
  205. /**************************************************************************//**
  206. * @brief
  207. * Set high frequency crystal oscillator clock frequency for target system.
  208. *
  209. * @note
  210. * This function is mainly provided for being able to handle target systems
  211. * with different HF crystal oscillator frequencies run-time. If used, it
  212. * should probably only be used once during system startup.
  213. *
  214. * @note
  215. * This is an EFM32 proprietary function, not part of the CMSIS definition.
  216. *
  217. * @param[in] freq
  218. * HFXO frequency in Hz used for target.
  219. *****************************************************************************/
  220. void SystemHFXOClockSet(uint32_t freq)
  221. {
  222. /* External crystal oscillator present? */
  223. #if (EFM32_HFXO_FREQ > 0)
  224. SystemHFXOClock = freq;
  225. /* Update core clock frequency if HFXO is used to clock core */
  226. if (CMU->STATUS & CMU_STATUS_HFXOSEL)
  227. {
  228. /* The function will update the global variable */
  229. SystemCoreClockGet();
  230. }
  231. #else
  232. (void)freq; /* Unused parameter */
  233. #endif
  234. }
  235. /**************************************************************************//**
  236. * @brief
  237. * Initialize the system.
  238. *
  239. * @details
  240. * Do required generic HW system init.
  241. *
  242. * @note
  243. * This function is invoked during system init, before the main() routine
  244. * and any data has been initialized. For this reason, it cannot do any
  245. * initialization of variables etc.
  246. *****************************************************************************/
  247. void SystemInit(void)
  248. {
  249. }
  250. /**************************************************************************//**
  251. * @brief
  252. * Get low frequency RC oscillator clock frequency for target system.
  253. *
  254. * @note
  255. * This is an EFM32 proprietary function, not part of the CMSIS definition.
  256. *
  257. * @return
  258. * LFRCO frequency in Hz.
  259. *****************************************************************************/
  260. uint32_t SystemLFRCOClockGet(void)
  261. {
  262. /* Currently we assume that this frequency is properly tuned during */
  263. /* manufacturing and is not changed after reset. If future requirements */
  264. /* for re-tuning by user, we can add support for that. */
  265. return EFM32_LFRCO_FREQ;
  266. }
  267. /**************************************************************************//**
  268. * @brief
  269. * Get ultra low frequency RC oscillator clock frequency for target system.
  270. *
  271. * @note
  272. * This is an EFM32 proprietary function, not part of the CMSIS definition.
  273. *
  274. * @return
  275. * ULFRCO frequency in Hz.
  276. *****************************************************************************/
  277. uint32_t SystemULFRCOClockGet(void)
  278. {
  279. /* The ULFRCO frequency is not tuned, and can be very inaccurate */
  280. return EFM32_ULFRCO_FREQ;
  281. }
  282. /**************************************************************************//**
  283. * @brief
  284. * Get low frequency crystal oscillator clock frequency for target system.
  285. *
  286. * @note
  287. * This is an EFM32 proprietary function, not part of the CMSIS definition.
  288. *
  289. * @return
  290. * LFXO frequency in Hz.
  291. *****************************************************************************/
  292. uint32_t SystemLFXOClockGet(void)
  293. {
  294. /* External crystal oscillator present? */
  295. #if (EFM32_LFXO_FREQ > 0)
  296. return SystemLFXOClock;
  297. #else
  298. return 0;
  299. #endif
  300. }
  301. /**************************************************************************//**
  302. * @brief
  303. * Set low frequency crystal oscillator clock frequency for target system.
  304. *
  305. * @note
  306. * This function is mainly provided for being able to handle target systems
  307. * with different HF crystal oscillator frequencies run-time. If used, it
  308. * should probably only be used once during system startup.
  309. *
  310. * @note
  311. * This is an EFM32 proprietary function, not part of the CMSIS definition.
  312. *
  313. * @param[in] freq
  314. * LFXO frequency in Hz used for target.
  315. *****************************************************************************/
  316. void SystemLFXOClockSet(uint32_t freq)
  317. {
  318. /* External crystal oscillator present? */
  319. #if (EFM32_LFXO_FREQ > 0)
  320. SystemLFXOClock = freq;
  321. /* Update core clock frequency if LFXO is used to clock core */
  322. if (CMU->STATUS & CMU_STATUS_LFXOSEL)
  323. {
  324. /* The function will update the global variable */
  325. SystemCoreClockGet();
  326. }
  327. #else
  328. (void)freq; /* Unused parameter */
  329. #endif
  330. }