system_LPC54114_cm4.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. /*
  2. ** ###################################################################
  3. ** Processors: LPC54114J256BD64_cm4
  4. ** LPC54114J256UK49_cm4
  5. **
  6. ** Compilers: Keil ARM C/C++ Compiler
  7. ** GNU C Compiler
  8. ** IAR ANSI C/C++ Compiler for ARM
  9. ** MCUXpresso Compiler
  10. **
  11. ** Reference manual: LPC5411x User manual Rev. 1.1 25 May 2016
  12. ** Version: rev. 1.0, 2016-04-29
  13. ** Build: b161227
  14. **
  15. ** Abstract:
  16. ** Provides a system configuration function and a global variable that
  17. ** contains the system frequency. It configures the device and initializes
  18. ** the oscillator (PLL) that is part of the microcontroller device.
  19. **
  20. ** The Clear BSD License
  21. ** Copyright (c) 2016 Freescale Semiconductor, Inc.
  22. ** Copyright 2016 - 2017 NXP
  23. ** All rights reserved.
  24. **
  25. ** Redistribution and use in source and binary forms, with or without modification,
  26. ** are permitted (subject to the limitations in the disclaimer below) provided
  27. ** that the following conditions are met:
  28. **
  29. ** o Redistributions of source code must retain the above copyright notice, this list
  30. ** of conditions and the following disclaimer.
  31. **
  32. ** o Redistributions in binary form must reproduce the above copyright notice, this
  33. ** list of conditions and the following disclaimer in the documentation and/or
  34. ** other materials provided with the distribution.
  35. **
  36. ** o Neither the name of the copyright holder nor the names of its
  37. ** contributors may be used to endorse or promote products derived from this
  38. ** software without specific prior written permission.
  39. **
  40. ** NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
  41. ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  42. ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  43. ** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  44. ** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  45. ** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  46. ** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  47. ** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  48. ** ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  49. ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  50. ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  51. **
  52. ** http: www.nxp.com
  53. ** mail: support@nxp.com
  54. **
  55. ** Revisions:
  56. ** - rev. 1.0 (2016-04-29)
  57. ** Initial version.
  58. **
  59. ** ###################################################################
  60. */
  61. /*!
  62. * @file LPC54114_cm4
  63. * @version 1.0
  64. * @date 2016-04-29
  65. * @brief Device specific configuration file for LPC54114_cm4 (implementation
  66. * file)
  67. *
  68. * Provides a system configuration function and a global variable that contains
  69. * the system frequency. It configures the device and initializes the oscillator
  70. * (PLL) that is part of the microcontroller device.
  71. */
  72. #include <stdint.h>
  73. #include "fsl_device_registers.h"
  74. #define NVALMAX (0x100)
  75. #define PVALMAX (0x20)
  76. #define MVALMAX (0x8000)
  77. #define PLL_SSCG0_MDEC_VAL_P (0) /* MDEC is in bits 16 downto 0 */
  78. #define PLL_SSCG0_MDEC_VAL_M (0x1FFFFUL << PLL_SSCG0_MDEC_VAL_P) /* NDEC is in bits 9 downto 0 */
  79. #define PLL_NDEC_VAL_P (0) /* NDEC is in bits 9:0 */
  80. #define PLL_NDEC_VAL_M (0x3FFUL << PLL_NDEC_VAL_P)
  81. #define PLL_PDEC_VAL_P (0) /* PDEC is in bits 6:0 */
  82. #define PLL_PDEC_VAL_M (0x3FFUL << PLL_PDEC_VAL_P)
  83. extern void *__Vectors;
  84. /* ----------------------------------------------------------------------------
  85. -- Core clock
  86. ---------------------------------------------------------------------------- */
  87. uint32_t SystemCoreClock = DEFAULT_SYSTEM_CLOCK;
  88. static const uint8_t wdtFreqLookup[32] = {0, 8, 12, 15, 18, 20, 24, 26, 28, 30, 32, 34, 36, 38, 40, 41, 42, 44, 45, 46,
  89. 48, 49, 50, 52, 53, 54, 56, 57, 58, 59, 60, 61};
  90. static uint32_t GetWdtOscFreq(void)
  91. {
  92. uint8_t freq_sel, div_sel;
  93. div_sel = ((SYSCON->WDTOSCCTRL & SYSCON_WDTOSCCTRL_DIVSEL_MASK) + 1) << 1;
  94. freq_sel = wdtFreqLookup[((SYSCON->WDTOSCCTRL & SYSCON_WDTOSCCTRL_FREQSEL_MASK) >> SYSCON_WDTOSCCTRL_FREQSEL_SHIFT)];
  95. return ((uint32_t) freq_sel * 50000U)/((uint32_t)div_sel);
  96. }
  97. /* Find decoded N value for raw NDEC value */
  98. static uint32_t pllDecodeN(uint32_t NDEC)
  99. {
  100. uint32_t n, x, i;
  101. /* Find NDec */
  102. switch (NDEC)
  103. {
  104. case 0xFFF:
  105. n = 0;
  106. break;
  107. case 0x302:
  108. n = 1;
  109. break;
  110. case 0x202:
  111. n = 2;
  112. break;
  113. default:
  114. x = 0x080;
  115. n = 0xFFFFFFFF;
  116. for (i = NVALMAX; ((i >= 3) && (n == 0xFFFFFFFF)); i--)
  117. {
  118. x = (((x ^ (x >> 2) ^ (x >> 3) ^ (x >> 4)) & 1) << 7) | ((x >> 1) & 0x7F);
  119. if ((x & (PLL_NDEC_VAL_M >> PLL_NDEC_VAL_P)) == NDEC)
  120. {
  121. /* Decoded value of NDEC */
  122. n = i;
  123. }
  124. }
  125. break;
  126. }
  127. return n;
  128. }
  129. /* Find decoded P value for raw PDEC value */
  130. static uint32_t pllDecodeP(uint32_t PDEC)
  131. {
  132. uint32_t p, x, i;
  133. /* Find PDec */
  134. switch (PDEC)
  135. {
  136. case 0xFF:
  137. p = 0;
  138. break;
  139. case 0x62:
  140. p = 1;
  141. break;
  142. case 0x42:
  143. p = 2;
  144. break;
  145. default:
  146. x = 0x10;
  147. p = 0xFFFFFFFF;
  148. for (i = PVALMAX; ((i >= 3) && (p == 0xFFFFFFFF)); i--)
  149. {
  150. x = (((x ^ (x >> 2)) & 1) << 4) | ((x >> 1) & 0xF);
  151. if ((x & (PLL_PDEC_VAL_M >> PLL_PDEC_VAL_P)) == PDEC)
  152. {
  153. /* Decoded value of PDEC */
  154. p = i;
  155. }
  156. }
  157. break;
  158. }
  159. return p;
  160. }
  161. /* Find decoded M value for raw MDEC value */
  162. static uint32_t pllDecodeM(uint32_t MDEC)
  163. {
  164. uint32_t m, i, x;
  165. /* Find MDec */
  166. switch (MDEC)
  167. {
  168. case 0xFFFFF:
  169. m = 0;
  170. break;
  171. case 0x18003:
  172. m = 1;
  173. break;
  174. case 0x10003:
  175. m = 2;
  176. break;
  177. default:
  178. x = 0x04000;
  179. m = 0xFFFFFFFF;
  180. for (i = MVALMAX; ((i >= 3) && (m == 0xFFFFFFFF)); i--)
  181. {
  182. x = (((x ^ (x >> 1)) & 1) << 14) | ((x >> 1) & 0x3FFF);
  183. if ((x & (PLL_SSCG0_MDEC_VAL_M >> PLL_SSCG0_MDEC_VAL_P)) == MDEC)
  184. {
  185. /* Decoded value of MDEC */
  186. m = i;
  187. }
  188. }
  189. break;
  190. }
  191. return m;
  192. }
  193. /* Get predivider (N) from PLL NDEC setting */
  194. static uint32_t findPllPreDiv(uint32_t ctrlReg, uint32_t nDecReg)
  195. {
  196. uint32_t preDiv = 1;
  197. /* Direct input is not used? */
  198. if ((ctrlReg & SYSCON_SYSPLLCTRL_DIRECTI_MASK) == 0)
  199. {
  200. /* Decode NDEC value to get (N) pre divider */
  201. preDiv = pllDecodeN(nDecReg & 0x3FF);
  202. if (preDiv == 0)
  203. {
  204. preDiv = 1;
  205. }
  206. }
  207. /* Adjusted by 1, directi is used to bypass */
  208. return preDiv;
  209. }
  210. /* Get postdivider (P) from PLL PDEC setting */
  211. static uint32_t findPllPostDiv(uint32_t ctrlReg, uint32_t pDecReg)
  212. {
  213. uint32_t postDiv = 1;
  214. /* Direct input is not used? */
  215. if ((ctrlReg & SYSCON_SYSPLLCTRL_DIRECTO_MASK) == 0)
  216. {
  217. /* Decode PDEC value to get (P) post divider */
  218. postDiv = 2 * pllDecodeP(pDecReg & 0x7F);
  219. if (postDiv == 0)
  220. {
  221. postDiv = 2;
  222. }
  223. }
  224. /* Adjusted by 1, directo is used to bypass */
  225. return postDiv;
  226. }
  227. /* Get multiplier (M) from PLL MDEC and BYPASS_FBDIV2 settings */
  228. static uint32_t findPllMMult(uint32_t ctrlReg, uint32_t mDecReg)
  229. {
  230. uint32_t mMult = 1;
  231. /* Decode MDEC value to get (M) multiplier */
  232. mMult = pllDecodeM(mDecReg & 0x1FFFF);
  233. /* Extra multiply by 2 needed? */
  234. if ((ctrlReg & SYSCON_SYSPLLCTRL_BYPASSCCODIV2_MASK) == 0)
  235. {
  236. mMult = mMult << 1;
  237. }
  238. if (mMult == 0)
  239. {
  240. mMult = 1;
  241. }
  242. return mMult;
  243. }
  244. /* ----------------------------------------------------------------------------
  245. -- SystemInit()
  246. ---------------------------------------------------------------------------- */
  247. void SystemInit(void)
  248. {
  249. #if ((__FPU_PRESENT == 1) && (__FPU_USED == 1)) || (defined(__VFP_FP__) && !defined(__SOFTFP__))
  250. SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); /* set CP10, CP11 Full Access */
  251. #endif /* ((__FPU_PRESENT == 1) && (__FPU_USED == 1)) */
  252. SCB->VTOR = (uint32_t)&__Vectors;
  253. /* Optionally enable RAM banks that may be off by default at reset */
  254. #if !defined(DONT_ENABLE_DISABLED_RAMBANKS)
  255. SYSCON->AHBCLKCTRLSET[0] = SYSCON_AHBCLKCTRL_SRAM2_MASK;
  256. #endif
  257. SystemInitHook();
  258. }
  259. /* ----------------------------------------------------------------------------
  260. -- SystemCoreClockUpdate()
  261. ---------------------------------------------------------------------------- */
  262. void SystemCoreClockUpdate(void)
  263. {
  264. uint32_t clkRate = 0;
  265. uint32_t prediv, postdiv;
  266. uint64_t workRate;
  267. switch (SYSCON->MAINCLKSELB & SYSCON_MAINCLKSELB_SEL_MASK)
  268. {
  269. case 0x00: /* MAINCLKSELA clock (main_clk_a)*/
  270. switch (SYSCON->MAINCLKSELA & SYSCON_MAINCLKSELA_SEL_MASK)
  271. {
  272. case 0x00: /* FRO 12 MHz (fro_12m) */
  273. clkRate = CLK_FRO_12MHZ;
  274. break;
  275. case 0x01: /* CLKIN (clk_in) */
  276. clkRate = CLK_CLK_IN;
  277. break;
  278. case 0x02: /* Watchdog oscillator (wdt_clk) */
  279. clkRate = GetWdtOscFreq();
  280. break;
  281. default: /* = 0x03 = FRO 96 or 48 MHz (fro_hf) */
  282. if (SYSCON->FROCTRL & SYSCON_FROCTRL_SEL_MASK)
  283. {
  284. clkRate = CLK_FRO_96MHZ;
  285. }
  286. else
  287. {
  288. clkRate = CLK_FRO_48MHZ;
  289. }
  290. break;
  291. }
  292. break;
  293. case 0x02: /* System PLL clock (pll_clk)*/
  294. switch (SYSCON->SYSPLLCLKSEL & SYSCON_SYSPLLCLKSEL_SEL_MASK)
  295. {
  296. case 0x00: /* FRO 12 MHz (fro_12m) */
  297. clkRate = CLK_FRO_12MHZ;
  298. break;
  299. case 0x01: /* CLKIN (clk_in) */
  300. clkRate = CLK_CLK_IN;
  301. break;
  302. case 0x02: /* Watchdog oscillator (wdt_clk) */
  303. clkRate = GetWdtOscFreq();
  304. break;
  305. case 0x03: /* RTC oscillator 32 kHz output (32k_clk) */
  306. clkRate = CLK_RTC_32K_CLK;
  307. break;
  308. default:
  309. break;
  310. }
  311. if ((SYSCON->SYSPLLCTRL & SYSCON_SYSPLLCTRL_BYPASS_MASK) == 0)
  312. {
  313. /* PLL is not in bypass mode, get pre-divider, post-divider, and M divider */
  314. prediv = findPllPreDiv(SYSCON->SYSPLLCTRL, SYSCON->SYSPLLNDEC);
  315. postdiv = findPllPostDiv(SYSCON->SYSPLLCTRL, SYSCON->SYSPLLPDEC);
  316. /* Adjust input clock */
  317. clkRate = clkRate / prediv;
  318. /* If using the SS, use the multiplier */
  319. if (SYSCON->SYSPLLSSCTRL1 & SYSCON_SYSPLLSSCTRL1_PD_MASK)
  320. {
  321. /* MDEC used for rate */
  322. workRate = (uint64_t)clkRate * (uint64_t)findPllMMult(SYSCON->SYSPLLCTRL, SYSCON->SYSPLLSSCTRL0);
  323. }
  324. else
  325. {
  326. /* SS multipler used for rate */
  327. workRate = 0;
  328. /* Adjust by fractional */
  329. workRate = workRate + ((clkRate * (uint64_t)((SYSCON->SYSPLLSSCTRL1 & 0x7FF) >> 0)) / 0x800);
  330. }
  331. clkRate = workRate / ((uint64_t)postdiv);
  332. }
  333. break;
  334. case 0x03: /* RTC oscillator 32 kHz output (32k_clk) */
  335. clkRate = CLK_RTC_32K_CLK;
  336. break;
  337. default:
  338. break;
  339. }
  340. SystemCoreClock = clkRate / ((SYSCON->AHBCLKDIV & 0xFF) + 1);
  341. }
  342. /* ----------------------------------------------------------------------------
  343. -- SystemInitHook()
  344. ---------------------------------------------------------------------------- */
  345. __attribute__ ((weak)) void SystemInitHook (void) {
  346. /* Void implementation of the weak function. */
  347. }