system_LPC13Uxx.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. /******************************************************************************
  2. * @file system_LPC13Uxx.c
  3. * @purpose CMSIS Cortex-M3 Device Peripheral Access Layer Source File
  4. * for the NXP LPC13xx Device Series
  5. * @version V1.10
  6. * @date 24. November 2010
  7. *
  8. * @note
  9. * Copyright (C) 2009-2010 ARM Limited. All rights reserved.
  10. *
  11. * @par
  12. * ARM Limited (ARM) is supplying this software for use with Cortex-M
  13. * processor based microcontrollers. This file can be freely distributed
  14. * within development tools that are supporting such ARM based processors.
  15. *
  16. * @par
  17. * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
  18. * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
  19. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
  20. * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
  21. * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
  22. *
  23. ******************************************************************************/
  24. #include <stdint.h>
  25. #include "LPC13Uxx.h"
  26. /*
  27. //-------- <<< Use Configuration Wizard in Context Menu >>> ------------------
  28. */
  29. /*--------------------- Clock Configuration ----------------------------------
  30. //
  31. // <e> Clock Configuration
  32. // <h> System Oscillator Control Register (SYSOSCCTRL)
  33. // <o1.0> BYPASS: System Oscillator Bypass Enable
  34. // <i> If enabled then PLL input (sys_osc_clk) is fed
  35. // <i> directly from XTALIN and XTALOUT pins.
  36. // <o1.9> FREQRANGE: System Oscillator Frequency Range
  37. // <i> Determines frequency range for Low-power oscillator.
  38. // <0=> 1 - 20 MHz
  39. // <1=> 15 - 25 MHz
  40. // </h>
  41. //
  42. // <h> Watchdog Oscillator Control Register (WDTOSCCTRL)
  43. // <o2.0..4> DIVSEL: Select Divider for Fclkana
  44. // <i> wdt_osc_clk = Fclkana/ (2 × (1 + DIVSEL))
  45. // <0-31>
  46. // <o2.5..8> FREQSEL: Select Watchdog Oscillator Analog Output Frequency (Fclkana)
  47. // <0=> Undefined
  48. // <1=> 0.5 MHz
  49. // <2=> 0.8 MHz
  50. // <3=> 1.1 MHz
  51. // <4=> 1.4 MHz
  52. // <5=> 1.6 MHz
  53. // <6=> 1.8 MHz
  54. // <7=> 2.0 MHz
  55. // <8=> 2.2 MHz
  56. // <9=> 2.4 MHz
  57. // <10=> 2.6 MHz
  58. // <11=> 2.7 MHz
  59. // <12=> 2.9 MHz
  60. // <13=> 3.1 MHz
  61. // <14=> 3.2 MHz
  62. // <15=> 3.4 MHz
  63. // </h>
  64. //
  65. // <h> System PLL Control Register (SYSPLLCTRL)
  66. // <i> F_clkout = M * F_clkin = F_CCO / (2 * P)
  67. // <i> F_clkin must be in the range of 10 MHz to 25 MHz
  68. // <i> F_CCO must be in the range of 156 MHz to 320 MHz
  69. // <o3.0..4> MSEL: Feedback Divider Selection
  70. // <i> M = MSEL + 1
  71. // <0-31>
  72. // <o3.5..6> PSEL: Post Divider Selection
  73. // <0=> P = 1
  74. // <1=> P = 2
  75. // <2=> P = 4
  76. // <3=> P = 8
  77. // </h>
  78. //
  79. // <h> System PLL Clock Source Select Register (SYSPLLCLKSEL)
  80. // <o4.0..1> SEL: System PLL Clock Source
  81. // <0=> IRC Oscillator
  82. // <1=> System Oscillator
  83. // <2=> Reserved
  84. // <3=> Reserved
  85. // </h>
  86. //
  87. // <h> Main Clock Source Select Register (MAINCLKSEL)
  88. // <o5.0..1> SEL: Clock Source for Main Clock
  89. // <0=> IRC Oscillator
  90. // <1=> Input Clock to System PLL
  91. // <2=> WDT Oscillator
  92. // <3=> System PLL Clock Out
  93. // </h>
  94. //
  95. // <h> System AHB Clock Divider Register (SYSAHBCLKDIV)
  96. // <o6.0..7> DIV: System AHB Clock Divider
  97. // <i> Divides main clock to provide system clock to core, memories, and peripherals.
  98. // <i> 0 = is disabled
  99. // <0-255>
  100. // </h>
  101. //
  102. // <h> USB PLL Control Register (USBPLLCTRL)
  103. // <i> F_clkout = M * F_clkin = F_CCO / (2 * P)
  104. // <i> F_clkin must be in the range of 10 MHz to 25 MHz
  105. // <i> F_CCO must be in the range of 156 MHz to 320 MHz
  106. // <o7.0..4> MSEL: Feedback Divider Selection
  107. // <i> M = MSEL + 1
  108. // <0-31>
  109. // <o7.5..6> PSEL: Post Divider Selection
  110. // <0=> P = 1
  111. // <1=> P = 2
  112. // <2=> P = 4
  113. // <3=> P = 8
  114. // </h>
  115. //
  116. // <h> USB PLL Clock Source Select Register (USBPLLCLKSEL)
  117. // <o8.0..1> SEL: USB PLL Clock Source
  118. // <i> USB PLL clock source must be switched to System Oscillator for correct USB operation
  119. // <0=> IRC Oscillator
  120. // <1=> System Oscillator
  121. // <2=> Reserved
  122. // <3=> Reserved
  123. // </h>
  124. //
  125. // <h> USB Clock Source Select Register (USBCLKSEL)
  126. // <o9.0..1> SEL: System PLL Clock Source
  127. // <0=> USB PLL out
  128. // <1=> Main clock
  129. // <2=> Reserved
  130. // <3=> Reserved
  131. // </h>
  132. //
  133. // <h> USB Clock Divider Register (USBCLKDIV)
  134. // <o10.0..7> DIV: USB Clock Divider
  135. // <i> Divides USB clock to 48 MHz.
  136. // <i> 0 = is disabled
  137. // <0-255>
  138. // </h>
  139. // </e>
  140. */
  141. #define CLOCK_SETUP 1
  142. #define SYSOSCCTRL_Val 0x00000000 // Reset: 0x000
  143. #define WDTOSCCTRL_Val 0x00000000 // Reset: 0x000
  144. #define SYSPLLCTRL_Val 0x00000025 // Reset: 0x000
  145. #define SYSPLLCLKSEL_Val 0x00000001 // Reset: 0x000
  146. #define MAINCLKSEL_Val 0x00000003 // Reset: 0x000
  147. #define SYSAHBCLKDIV_Val 0x00000001 // Reset: 0x001
  148. #define USBPLLCTRL_Val 0x00000023 // Reset: 0x000
  149. #define USBPLLCLKSEL_Val 0x00000001 // Reset: 0x000
  150. #define USBCLKSEL_Val 0x00000000 // Reset: 0x000
  151. #define USBCLKDIV_Val 0x00000001 // Reset: 0x001
  152. /*
  153. //-------- <<< end of configuration section >>> ------------------------------
  154. */
  155. /*----------------------------------------------------------------------------
  156. Check the register settings
  157. *----------------------------------------------------------------------------*/
  158. #define CHECK_RANGE(val, min, max) ((val < min) || (val > max))
  159. #define CHECK_RSVD(val, mask) (val & mask)
  160. /* Clock Configuration -------------------------------------------------------*/
  161. #if (CHECK_RSVD((SYSOSCCTRL_Val), ~0x00000003))
  162. #error "SYSOSCCTRL: Invalid values of reserved bits!"
  163. #endif
  164. #if (CHECK_RSVD((WDTOSCCTRL_Val), ~0x000001FF))
  165. #error "WDTOSCCTRL: Invalid values of reserved bits!"
  166. #endif
  167. #if (CHECK_RANGE((SYSPLLCLKSEL_Val), 0, 2))
  168. #error "SYSPLLCLKSEL: Value out of range!"
  169. #endif
  170. #if (CHECK_RSVD((SYSPLLCTRL_Val), ~0x000001FF))
  171. #error "SYSPLLCTRL: Invalid values of reserved bits!"
  172. #endif
  173. #if (CHECK_RSVD((MAINCLKSEL_Val), ~0x00000003))
  174. #error "MAINCLKSEL: Invalid values of reserved bits!"
  175. #endif
  176. #if (CHECK_RANGE((SYSAHBCLKDIV_Val), 0, 255))
  177. #error "SYSAHBCLKDIV: Value out of range!"
  178. #endif
  179. #if (CHECK_RANGE((USBPLLCLKSEL_Val), 0, 1))
  180. #error "USBPLLCLKSEL: Value out of range!"
  181. #endif
  182. #if (CHECK_RSVD((USBPLLCTRL_Val), ~0x000001FF))
  183. #error "USBPLLCTRL: Invalid values of reserved bits!"
  184. #endif
  185. #if (CHECK_RANGE((USBCLKSEL_Val), 0, 1))
  186. #error "USBCLKSEL: Value out of range!"
  187. #endif
  188. #if (CHECK_RANGE((USBCLKDIV_Val), 0, 255))
  189. #error "USBCLKDIV: Value out of range!"
  190. #endif
  191. /*----------------------------------------------------------------------------
  192. DEFINES
  193. *----------------------------------------------------------------------------*/
  194. /*----------------------------------------------------------------------------
  195. Define clocks
  196. *----------------------------------------------------------------------------*/
  197. #define __XTAL (12000000UL) /* Oscillator frequency */
  198. #define __SYS_OSC_CLK ( __XTAL) /* Main oscillator frequency */
  199. #define __IRC_OSC_CLK (12000000UL) /* Internal RC oscillator frequency */
  200. #define __FREQSEL ((WDTOSCCTRL_Val >> 5) & 0x0F)
  201. #define __DIVSEL (((WDTOSCCTRL_Val & 0x1F) << 1) + 2)
  202. #if (CLOCK_SETUP) /* Clock Setup */
  203. #if (__FREQSEL == 0)
  204. #define __WDT_OSC_CLK ( 0) /* undefined */
  205. #elif (__FREQSEL == 1)
  206. #define __WDT_OSC_CLK ( 500000 / __DIVSEL)
  207. #elif (__FREQSEL == 2)
  208. #define __WDT_OSC_CLK ( 800000 / __DIVSEL)
  209. #elif (__FREQSEL == 3)
  210. #define __WDT_OSC_CLK (1100000 / __DIVSEL)
  211. #elif (__FREQSEL == 4)
  212. #define __WDT_OSC_CLK (1400000 / __DIVSEL)
  213. #elif (__FREQSEL == 5)
  214. #define __WDT_OSC_CLK (1600000 / __DIVSEL)
  215. #elif (__FREQSEL == 6)
  216. #define __WDT_OSC_CLK (1800000 / __DIVSEL)
  217. #elif (__FREQSEL == 7)
  218. #define __WDT_OSC_CLK (2000000 / __DIVSEL)
  219. #elif (__FREQSEL == 8)
  220. #define __WDT_OSC_CLK (2200000 / __DIVSEL)
  221. #elif (__FREQSEL == 9)
  222. #define __WDT_OSC_CLK (2400000 / __DIVSEL)
  223. #elif (__FREQSEL == 10)
  224. #define __WDT_OSC_CLK (2600000 / __DIVSEL)
  225. #elif (__FREQSEL == 11)
  226. #define __WDT_OSC_CLK (2700000 / __DIVSEL)
  227. #elif (__FREQSEL == 12)
  228. #define __WDT_OSC_CLK (2900000 / __DIVSEL)
  229. #elif (__FREQSEL == 13)
  230. #define __WDT_OSC_CLK (3100000 / __DIVSEL)
  231. #elif (__FREQSEL == 14)
  232. #define __WDT_OSC_CLK (3200000 / __DIVSEL)
  233. #else
  234. #define __WDT_OSC_CLK (3400000 / __DIVSEL)
  235. #endif
  236. /* sys_pllclkin calculation */
  237. #if ((SYSPLLCLKSEL_Val & 0x03) == 0)
  238. #define __SYS_PLLCLKIN (__IRC_OSC_CLK)
  239. #elif ((SYSPLLCLKSEL_Val & 0x03) == 1)
  240. #define __SYS_PLLCLKIN (__SYS_OSC_CLK)
  241. #else
  242. #define __SYS_PLLCLKIN (0)
  243. #endif
  244. #define __SYS_PLLCLKOUT (__SYS_PLLCLKIN * ((SYSPLLCTRL_Val & 0x01F) + 1))
  245. /* main clock calculation */
  246. #if ((MAINCLKSEL_Val & 0x03) == 0)
  247. #define __MAIN_CLOCK (__IRC_OSC_CLK)
  248. #elif ((MAINCLKSEL_Val & 0x03) == 1)
  249. #define __MAIN_CLOCK (__SYS_PLLCLKIN)
  250. #elif ((MAINCLKSEL_Val & 0x03) == 2)
  251. #if (__FREQSEL == 0)
  252. #error "MAINCLKSEL: WDT Oscillator selected but FREQSEL is undefined!"
  253. #else
  254. #define __MAIN_CLOCK (__WDT_OSC_CLK)
  255. #endif
  256. #elif ((MAINCLKSEL_Val & 0x03) == 3)
  257. #define __MAIN_CLOCK (__SYS_PLLCLKOUT)
  258. #else
  259. #define __MAIN_CLOCK (0)
  260. #endif
  261. #define __SYSTEM_CLOCK (__MAIN_CLOCK / SYSAHBCLKDIV_Val)
  262. #else
  263. #define __SYSTEM_CLOCK (__IRC_OSC_CLK)
  264. #endif // CLOCK_SETUP
  265. /*----------------------------------------------------------------------------
  266. Clock Variable definitions
  267. *----------------------------------------------------------------------------*/
  268. uint32_t SystemCoreClock = __SYSTEM_CLOCK;/*!< System Clock Frequency (Core Clock)*/
  269. /*----------------------------------------------------------------------------
  270. Clock functions
  271. *----------------------------------------------------------------------------*/
  272. void SystemCoreClockUpdate (void) /* Get Core Clock Frequency */
  273. {
  274. uint32_t wdt_osc = 0;
  275. /* Determine clock frequency according to clock register values */
  276. switch ((LPC_SYSCON->WDTOSCCTRL >> 5) & 0x0F) {
  277. case 0: wdt_osc = 0; break;
  278. case 1: wdt_osc = 500000; break;
  279. case 2: wdt_osc = 800000; break;
  280. case 3: wdt_osc = 1100000; break;
  281. case 4: wdt_osc = 1400000; break;
  282. case 5: wdt_osc = 1600000; break;
  283. case 6: wdt_osc = 1800000; break;
  284. case 7: wdt_osc = 2000000; break;
  285. case 8: wdt_osc = 2200000; break;
  286. case 9: wdt_osc = 2400000; break;
  287. case 10: wdt_osc = 2600000; break;
  288. case 11: wdt_osc = 2700000; break;
  289. case 12: wdt_osc = 2900000; break;
  290. case 13: wdt_osc = 3100000; break;
  291. case 14: wdt_osc = 3200000; break;
  292. case 15: wdt_osc = 3400000; break;
  293. }
  294. wdt_osc /= ((LPC_SYSCON->WDTOSCCTRL & 0x1F) << 1) + 2;
  295. switch (LPC_SYSCON->MAINCLKSEL & 0x03) {
  296. case 0: /* Internal RC oscillator */
  297. SystemCoreClock = __IRC_OSC_CLK;
  298. break;
  299. case 1: /* Input Clock to System PLL */
  300. switch (LPC_SYSCON->SYSPLLCLKSEL & 0x03) {
  301. case 0: /* Internal RC oscillator */
  302. SystemCoreClock = __IRC_OSC_CLK;
  303. break;
  304. case 1: /* System oscillator */
  305. SystemCoreClock = __SYS_OSC_CLK;
  306. break;
  307. case 2: /* Reserved */
  308. case 3: /* Reserved */
  309. SystemCoreClock = 0;
  310. break;
  311. }
  312. break;
  313. case 2: /* WDT Oscillator */
  314. SystemCoreClock = wdt_osc;
  315. break;
  316. case 3: /* System PLL Clock Out */
  317. switch (LPC_SYSCON->SYSPLLCLKSEL & 0x03) {
  318. case 0: /* Internal RC oscillator */
  319. if (LPC_SYSCON->SYSPLLCTRL & 0x180) {
  320. SystemCoreClock = __IRC_OSC_CLK;
  321. } else {
  322. SystemCoreClock = __IRC_OSC_CLK * ((LPC_SYSCON->SYSPLLCTRL & 0x01F) + 1);
  323. }
  324. break;
  325. case 1: /* System oscillator */
  326. if (LPC_SYSCON->SYSPLLCTRL & 0x180) {
  327. SystemCoreClock = __SYS_OSC_CLK;
  328. } else {
  329. SystemCoreClock = __SYS_OSC_CLK * ((LPC_SYSCON->SYSPLLCTRL & 0x01F) + 1);
  330. }
  331. break;
  332. case 2: /* Reserved */
  333. case 3: /* Reserved */
  334. SystemCoreClock = 0;
  335. break;
  336. }
  337. break;
  338. }
  339. SystemCoreClock /= LPC_SYSCON->SYSAHBCLKDIV;
  340. }
  341. /**
  342. * Initialize the system
  343. *
  344. * @param none
  345. * @return none
  346. *
  347. * @brief Setup the microcontroller system.
  348. * Initialize the System.
  349. */
  350. void SystemInit (void) {
  351. volatile uint32_t i;
  352. #if (CLOCK_SETUP) /* Clock Setup */
  353. #if ((SYSPLLCLKSEL_Val & 0x03) == 1)
  354. LPC_SYSCON->PDRUNCFG &= ~(1 << 5); /* Power-up System Osc */
  355. LPC_SYSCON->SYSOSCCTRL = SYSOSCCTRL_Val;
  356. for (i = 0; i < 200; i++) __NOP();
  357. #endif
  358. LPC_SYSCON->SYSPLLCLKSEL = SYSPLLCLKSEL_Val; /* Select PLL Input */
  359. #if ((MAINCLKSEL_Val & 0x03) == 3) /* Main Clock is PLL Out */
  360. LPC_SYSCON->SYSPLLCTRL = SYSPLLCTRL_Val;
  361. LPC_SYSCON->PDRUNCFG &= ~(1 << 7); /* Power-up SYSPLL */
  362. while (!(LPC_SYSCON->SYSPLLSTAT & 0x01)); /* Wait Until PLL Locked */
  363. #endif
  364. #if (((MAINCLKSEL_Val & 0x03) == 2) )
  365. LPC_SYSCON->WDTOSCCTRL = WDTOSCCTRL_Val;
  366. LPC_SYSCON->PDRUNCFG &= ~(1 << 6); /* Power-up WDT Clock */
  367. for (i = 0; i < 200; i++) __NOP();
  368. #endif
  369. LPC_SYSCON->MAINCLKSEL = MAINCLKSEL_Val; /* Select PLL Clock Output */
  370. LPC_SYSCON->SYSAHBCLKDIV = SYSAHBCLKDIV_Val;
  371. #if ((USBCLKDIV_Val & 0x1FF) != 0) /* USB clock is used */
  372. LPC_SYSCON->PDRUNCFG &= ~(1 << 10); /* Power-up USB PHY */
  373. /* Regardless USB PLL is used as USB clock or not, USB PLL needs to be configured. */
  374. LPC_SYSCON->PDRUNCFG &= ~(1 << 8); /* Power-up USB PLL */
  375. LPC_SYSCON->USBPLLCLKSEL = USBPLLCLKSEL_Val; /* Select PLL Input */
  376. LPC_SYSCON->USBPLLCTRL = USBPLLCTRL_Val;
  377. while (!(LPC_SYSCON->USBPLLSTAT & 0x01)); /* Wait Until PLL Locked */
  378. LPC_SYSCON->USBCLKSEL = USBCLKSEL_Val; /* Select USB Clock */
  379. LPC_SYSCON->USBCLKDIV = USBCLKDIV_Val; /* Set USB clock divider */
  380. #else /* USB clock is not used */
  381. LPC_SYSCON->PDRUNCFG |= (1 << 10); /* Power-down USB PHY */
  382. LPC_SYSCON->PDRUNCFG |= (1 << 8); /* Power-down USB PLL */
  383. #endif
  384. #endif
  385. /* System clock to the IOCON needs to be enabled or
  386. most of the I/O related peripherals won't work. */
  387. LPC_SYSCON->SYSAHBCLKCTRL |= (1<<16);
  388. }