1 /******************************************************************************
\r
2 * @file system_LPC11Uxx.c
\r
3 * @purpose CMSIS Cortex-M3 Device Peripheral Access Layer Source File
\r
4 * for the NXP LPC13xx Device Series
\r
6 * @date 24. November 2010
\r
9 * Copyright (C) 2009-2010 ARM Limited. All rights reserved.
\r
12 * ARM Limited (ARM) is supplying this software for use with Cortex-M
\r
13 * processor based microcontrollers. This file can be freely distributed
\r
14 * within development tools that are supporting such ARM based processors.
\r
17 * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
\r
18 * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
\r
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
\r
20 * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
\r
21 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
\r
23 ******************************************************************************/
\r
27 #include "LPC11Uxx.h"
\r
30 //-------- <<< Use Configuration Wizard in Context Menu >>> ------------------
\r
33 /*--------------------- Clock Configuration ----------------------------------
\r
35 // <e> Clock Configuration
\r
36 // <h> System Oscillator Control Register (SYSOSCCTRL)
\r
37 // <o1.0> BYPASS: System Oscillator Bypass Enable
\r
38 // <i> If enabled then PLL input (sys_osc_clk) is fed
\r
39 // <i> directly from XTALIN and XTALOUT pins.
\r
40 // <o1.9> FREQRANGE: System Oscillator Frequency Range
\r
41 // <i> Determines frequency range for Low-power oscillator.
\r
46 // <h> Watchdog Oscillator Control Register (WDTOSCCTRL)
\r
47 // <o2.0..4> DIVSEL: Select Divider for Fclkana
\r
48 // <i> wdt_osc_clk = Fclkana/ (2 � (1 + DIVSEL))
\r
50 // <o2.5..8> FREQSEL: Select Watchdog Oscillator Analog Output Frequency (Fclkana)
\r
69 // <h> System PLL Control Register (SYSPLLCTRL)
\r
70 // <i> F_clkout = M * F_clkin = F_CCO / (2 * P)
\r
71 // <i> F_clkin must be in the range of 10 MHz to 25 MHz
\r
72 // <i> F_CCO must be in the range of 156 MHz to 320 MHz
\r
73 // <o3.0..4> MSEL: Feedback Divider Selection
\r
76 // <o3.5..6> PSEL: Post Divider Selection
\r
83 // <h> System PLL Clock Source Select Register (SYSPLLCLKSEL)
\r
84 // <o4.0..1> SEL: System PLL Clock Source
\r
85 // <0=> IRC Oscillator
\r
86 // <1=> System Oscillator
\r
91 // <h> Main Clock Source Select Register (MAINCLKSEL)
\r
92 // <o5.0..1> SEL: Clock Source for Main Clock
\r
93 // <0=> IRC Oscillator
\r
94 // <1=> Input Clock to System PLL
\r
95 // <2=> WDT Oscillator
\r
96 // <3=> System PLL Clock Out
\r
99 // <h> System AHB Clock Divider Register (SYSAHBCLKDIV)
\r
100 // <o6.0..7> DIV: System AHB Clock Divider
\r
101 // <i> Divides main clock to provide system clock to core, memories, and peripherals.
\r
102 // <i> 0 = is disabled
\r
106 // <h> USB PLL Control Register (USBPLLCTRL)
\r
107 // <i> F_clkout = M * F_clkin = F_CCO / (2 * P)
\r
108 // <i> F_clkin must be in the range of 10 MHz to 25 MHz
\r
109 // <i> F_CCO must be in the range of 156 MHz to 320 MHz
\r
110 // <o7.0..4> MSEL: Feedback Divider Selection
\r
111 // <i> M = MSEL + 1
\r
113 // <o7.5..6> PSEL: Post Divider Selection
\r
120 // <h> USB PLL Clock Source Select Register (USBPLLCLKSEL)
\r
121 // <o8.0..1> SEL: USB PLL Clock Source
\r
122 // <i> USB PLL clock source must be switched to System Oscillator for correct USB operation
\r
123 // <0=> IRC Oscillator
\r
124 // <1=> System Oscillator
\r
129 // <h> USB Clock Source Select Register (USBCLKSEL)
\r
130 // <o9.0..1> SEL: System PLL Clock Source
\r
131 // <0=> USB PLL out
\r
137 // <h> USB Clock Divider Register (USBCLKDIV)
\r
138 // <o10.0..7> DIV: USB Clock Divider
\r
139 // <i> Divides USB clock to 48 MHz.
\r
140 // <i> 0 = is disabled
\r
145 #define CLOCK_SETUP 1
\r
146 #define SYSOSCCTRL_Val 0x00000000 // Reset: 0x000
\r
147 #define WDTOSCCTRL_Val 0x00000000 // Reset: 0x000
\r
148 #define SYSPLLCTRL_Val 0x00000023 // Reset: 0x000
\r
149 #define SYSPLLCLKSEL_Val 0x00000001 // Reset: 0x000
\r
150 #define MAINCLKSEL_Val 0x00000003 // Reset: 0x000
\r
151 #define SYSAHBCLKDIV_Val 0x00000001 // Reset: 0x001
\r
152 #define USBPLLCTRL_Val 0x00000023 // Reset: 0x000
\r
153 #define USBPLLCLKSEL_Val 0x00000001 // Reset: 0x000
\r
154 #define USBCLKSEL_Val 0x00000000 // Reset: 0x000
\r
155 #define USBCLKDIV_Val 0x00000000 // Reset: 0x001
\r
157 #define PDRUNCFGUSEMASK 0x0000E800
\r
158 #define PDRUNCFGMASKTMP 0x000005FF
\r
161 //-------- <<< end of configuration section >>> ------------------------------
\r
164 /*----------------------------------------------------------------------------
\r
165 Check the register settings
\r
166 *----------------------------------------------------------------------------*/
\r
167 #define CHECK_RANGE(val, min, max) ((val < min) || (val > max))
\r
168 #define CHECK_RSVD(val, mask) (val & mask)
\r
170 /* Clock Configuration -------------------------------------------------------*/
\r
171 #if (CHECK_RSVD((SYSOSCCTRL_Val), ~0x00000003))
\r
172 #error "SYSOSCCTRL: Invalid values of reserved bits!"
\r
175 #if (CHECK_RSVD((WDTOSCCTRL_Val), ~0x000001FF))
\r
176 #error "WDTOSCCTRL: Invalid values of reserved bits!"
\r
179 #if (CHECK_RANGE((SYSPLLCLKSEL_Val), 0, 2))
\r
180 #error "SYSPLLCLKSEL: Value out of range!"
\r
183 #if (CHECK_RSVD((SYSPLLCTRL_Val), ~0x000001FF))
\r
184 #error "SYSPLLCTRL: Invalid values of reserved bits!"
\r
187 #if (CHECK_RSVD((MAINCLKSEL_Val), ~0x00000003))
\r
188 #error "MAINCLKSEL: Invalid values of reserved bits!"
\r
191 #if (CHECK_RANGE((SYSAHBCLKDIV_Val), 0, 255))
\r
192 #error "SYSAHBCLKDIV: Value out of range!"
\r
195 #if (CHECK_RANGE((USBPLLCLKSEL_Val), 0, 1))
\r
196 #error "USBPLLCLKSEL: Value out of range!"
\r
199 #if (CHECK_RSVD((USBPLLCTRL_Val), ~0x000001FF))
\r
200 #error "USBPLLCTRL: Invalid values of reserved bits!"
\r
203 #if (CHECK_RANGE((USBCLKSEL_Val), 0, 1))
\r
204 #error "USBCLKSEL: Value out of range!"
\r
207 #if (CHECK_RANGE((USBCLKDIV_Val), 0, 255))
\r
208 #error "USBCLKDIV: Value out of range!"
\r
212 /*----------------------------------------------------------------------------
\r
214 *----------------------------------------------------------------------------*/
\r
216 /*----------------------------------------------------------------------------
\r
218 *----------------------------------------------------------------------------*/
\r
219 #define __XTAL (12000000UL) /* Oscillator frequency */
\r
220 #define __SYS_OSC_CLK ( __XTAL) /* Main oscillator frequency */
\r
221 #define __IRC_OSC_CLK (12000000UL) /* Internal RC oscillator frequency */
\r
224 #define __FREQSEL ((WDTOSCCTRL_Val >> 5) & 0x0F)
\r
225 #define __DIVSEL (((WDTOSCCTRL_Val & 0x1F) << 1) + 2)
\r
227 #if (CLOCK_SETUP) /* Clock Setup */
\r
228 #if (__FREQSEL == 0)
\r
229 #define __WDT_OSC_CLK ( 0) /* undefined */
\r
230 #elif (__FREQSEL == 1)
\r
231 #define __WDT_OSC_CLK ( 500000 / __DIVSEL)
\r
232 #elif (__FREQSEL == 2)
\r
233 #define __WDT_OSC_CLK ( 800000 / __DIVSEL)
\r
234 #elif (__FREQSEL == 3)
\r
235 #define __WDT_OSC_CLK (1100000 / __DIVSEL)
\r
236 #elif (__FREQSEL == 4)
\r
237 #define __WDT_OSC_CLK (1400000 / __DIVSEL)
\r
238 #elif (__FREQSEL == 5)
\r
239 #define __WDT_OSC_CLK (1600000 / __DIVSEL)
\r
240 #elif (__FREQSEL == 6)
\r
241 #define __WDT_OSC_CLK (1800000 / __DIVSEL)
\r
242 #elif (__FREQSEL == 7)
\r
243 #define __WDT_OSC_CLK (2000000 / __DIVSEL)
\r
244 #elif (__FREQSEL == 8)
\r
245 #define __WDT_OSC_CLK (2200000 / __DIVSEL)
\r
246 #elif (__FREQSEL == 9)
\r
247 #define __WDT_OSC_CLK (2400000 / __DIVSEL)
\r
248 #elif (__FREQSEL == 10)
\r
249 #define __WDT_OSC_CLK (2600000 / __DIVSEL)
\r
250 #elif (__FREQSEL == 11)
\r
251 #define __WDT_OSC_CLK (2700000 / __DIVSEL)
\r
252 #elif (__FREQSEL == 12)
\r
253 #define __WDT_OSC_CLK (2900000 / __DIVSEL)
\r
254 #elif (__FREQSEL == 13)
\r
255 #define __WDT_OSC_CLK (3100000 / __DIVSEL)
\r
256 #elif (__FREQSEL == 14)
\r
257 #define __WDT_OSC_CLK (3200000 / __DIVSEL)
\r
259 #define __WDT_OSC_CLK (3400000 / __DIVSEL)
\r
262 /* sys_pllclkin calculation */
\r
263 #if ((SYSPLLCLKSEL_Val & 0x03) == 0)
\r
264 #define __SYS_PLLCLKIN (__IRC_OSC_CLK)
\r
265 #elif ((SYSPLLCLKSEL_Val & 0x03) == 1)
\r
266 #define __SYS_PLLCLKIN (__SYS_OSC_CLK)
\r
268 #define __SYS_PLLCLKIN (0)
\r
271 #define __SYS_PLLCLKOUT (__SYS_PLLCLKIN * ((SYSPLLCTRL_Val & 0x01F) + 1))
\r
273 /* main clock calculation */
\r
274 #if ((MAINCLKSEL_Val & 0x03) == 0)
\r
275 #define __MAIN_CLOCK (__IRC_OSC_CLK)
\r
276 #elif ((MAINCLKSEL_Val & 0x03) == 1)
\r
277 #define __MAIN_CLOCK (__SYS_PLLCLKIN)
\r
278 #elif ((MAINCLKSEL_Val & 0x03) == 2)
\r
279 #if (__FREQSEL == 0)
\r
280 #error "MAINCLKSEL: WDT Oscillator selected but FREQSEL is undefined!"
\r
282 #define __MAIN_CLOCK (__WDT_OSC_CLK)
\r
284 #elif ((MAINCLKSEL_Val & 0x03) == 3)
\r
285 #define __MAIN_CLOCK (__SYS_PLLCLKOUT)
\r
287 #define __MAIN_CLOCK (0)
\r
290 #define __SYSTEM_CLOCK (__MAIN_CLOCK / SYSAHBCLKDIV_Val)
\r
293 #define __SYSTEM_CLOCK (__IRC_OSC_CLK)
\r
294 #endif // CLOCK_SETUP
\r
297 /*----------------------------------------------------------------------------
\r
298 Clock Variable definitions
\r
299 *----------------------------------------------------------------------------*/
\r
300 uint32_t SystemCoreClock = __SYSTEM_CLOCK;/*!< System Clock Frequency (Core Clock)*/
\r
303 /*----------------------------------------------------------------------------
\r
305 *----------------------------------------------------------------------------*/
\r
306 void SystemCoreClockUpdate (void) /* Get Core Clock Frequency */
\r
308 uint32_t wdt_osc = 0;
\r
310 /* Determine clock frequency according to clock register values */
\r
311 switch ((LPC_SYSCON->WDTOSCCTRL >> 5) & 0x0F) {
\r
312 case 0: wdt_osc = 0; break;
\r
313 case 1: wdt_osc = 500000; break;
\r
314 case 2: wdt_osc = 800000; break;
\r
315 case 3: wdt_osc = 1100000; break;
\r
316 case 4: wdt_osc = 1400000; break;
\r
317 case 5: wdt_osc = 1600000; break;
\r
318 case 6: wdt_osc = 1800000; break;
\r
319 case 7: wdt_osc = 2000000; break;
\r
320 case 8: wdt_osc = 2200000; break;
\r
321 case 9: wdt_osc = 2400000; break;
\r
322 case 10: wdt_osc = 2600000; break;
\r
323 case 11: wdt_osc = 2700000; break;
\r
324 case 12: wdt_osc = 2900000; break;
\r
325 case 13: wdt_osc = 3100000; break;
\r
326 case 14: wdt_osc = 3200000; break;
\r
327 case 15: wdt_osc = 3400000; break;
\r
329 wdt_osc /= ((LPC_SYSCON->WDTOSCCTRL & 0x1F) << 1) + 2;
\r
331 switch (LPC_SYSCON->MAINCLKSEL & 0x03) {
\r
332 case 0: /* Internal RC oscillator */
\r
333 SystemCoreClock = __IRC_OSC_CLK;
\r
335 case 1: /* Input Clock to System PLL */
\r
336 switch (LPC_SYSCON->SYSPLLCLKSEL & 0x03) {
\r
337 case 0: /* Internal RC oscillator */
\r
338 SystemCoreClock = __IRC_OSC_CLK;
\r
340 case 1: /* System oscillator */
\r
341 SystemCoreClock = __SYS_OSC_CLK;
\r
343 case 2: /* Reserved */
\r
344 case 3: /* Reserved */
\r
345 SystemCoreClock = 0;
\r
349 case 2: /* WDT Oscillator */
\r
350 SystemCoreClock = wdt_osc;
\r
352 case 3: /* System PLL Clock Out */
\r
353 switch (LPC_SYSCON->SYSPLLCLKSEL & 0x03) {
\r
354 case 0: /* Internal RC oscillator */
\r
355 if (LPC_SYSCON->SYSPLLCTRL & 0x180) {
\r
356 SystemCoreClock = __IRC_OSC_CLK;
\r
358 SystemCoreClock = __IRC_OSC_CLK * ((LPC_SYSCON->SYSPLLCTRL & 0x01F) + 1);
\r
361 case 1: /* System oscillator */
\r
362 if (LPC_SYSCON->SYSPLLCTRL & 0x180) {
\r
363 SystemCoreClock = __SYS_OSC_CLK;
\r
365 SystemCoreClock = __SYS_OSC_CLK * ((LPC_SYSCON->SYSPLLCTRL & 0x01F) + 1);
\r
368 case 2: /* Reserved */
\r
369 case 3: /* Reserved */
\r
370 SystemCoreClock = 0;
\r
376 SystemCoreClock /= LPC_SYSCON->SYSAHBCLKDIV;
\r
380 __STATIC_INLINE void SYSCTL_PowerDown(uint32_t powerdownmask)
\r
384 pdrun = LPC_SYSCON->PDRUNCFG & PDRUNCFGMASKTMP;
\r
385 pdrun |= (powerdownmask & PDRUNCFGMASKTMP);
\r
386 LPC_SYSCON->PDRUNCFG = (pdrun | PDRUNCFGUSEMASK);
\r
389 __STATIC_INLINE void SYSCTL_PowerUp(uint32_t powerupmask)
\r
393 pdrun = LPC_SYSCON->PDRUNCFG & PDRUNCFGMASKTMP;
\r
394 pdrun &= ~(powerupmask & PDRUNCFGMASKTMP);
\r
396 LPC_SYSCON->PDRUNCFG = (pdrun | PDRUNCFGUSEMASK);
\r
399 __STATIC_INLINE void FLASH_SetFLASHAccess(uint32_t clks)
\r
401 uint32_t tmp = LPC_FLASHCTRL->FLASHCFG & (~(0x3));
\r
403 /* Don't alter upper bits */
\r
404 LPC_FLASHCTRL->FLASHCFG = tmp | clks;
\r
408 * Initialize the system
\r
413 * @brief Setup the microcontroller system.
\r
414 * Initialize the System.
\r
416 void SystemInit (void) {
\r
417 volatile uint32_t i;
\r
419 #if (CLOCK_SETUP) /* Clock Setup */
\r
421 #if ((SYSPLLCLKSEL_Val & 0x03) == 1)
\r
422 //LPC_SYSCON->PDRUNCFG &= ~(1 << 5); /* Power-up System Osc */
\r
423 SYSCTL_PowerUp ((1 << 5));
\r
424 //LPC_SYSCON->SYSOSCCTRL = SYSOSCCTRL_Val;
\r
425 for (i = 0; i < 0x100; i++) __NOP();
\r
428 LPC_SYSCON->SYSPLLCLKSEL = SYSPLLCLKSEL_Val; /* Select PLL Input */
\r
429 LPC_SYSCON->SYSPLLCLKUEN = 0x00; /* Toggle Update Register */
\r
430 LPC_SYSCON->SYSPLLCLKUEN = 0x01;
\r
431 //while (!(LPC_SYSCON->SYSPLLCLKUEN & 0x01)); /* Wait Until Updated */
\r
433 #if ((MAINCLKSEL_Val & 0x03) == 3) /* Main Clock is PLL Out */
\r
434 SYSCTL_PowerDown (1 << 7);
\r
435 LPC_SYSCON->SYSPLLCTRL = SYSPLLCTRL_Val;
\r
436 //LPC_SYSCON->PDRUNCFG &= ~(1 << 7); /* Power-up SYSPLL */
\r
437 SYSCTL_PowerUp ((1 << 7));
\r
438 while (!(LPC_SYSCON->SYSPLLSTAT & 0x01)); /* Wait Until PLL Locked */
\r
441 #if (((MAINCLKSEL_Val & 0x03) == 2) )
\r
442 SYSCTL_PowerDown (1 << 6);
\r
443 LPC_SYSCON->WDTOSCCTRL = WDTOSCCTRL_Val;
\r
444 //LPC_SYSCON->PDRUNCFG &= ~(1 << 6); /* Power-up WDT Clock */
\r
445 SYSCTL_PowerUp ((1 << 6));
\r
446 for (i = 0; i < 200; i++) __NOP();
\r
449 LPC_SYSCON->SYSAHBCLKDIV = SYSAHBCLKDIV_Val;
\r
451 FLASH_SetFLASHAccess (FLASHCFG_50MHZ_CPU);
\r
453 LPC_SYSCON->MAINCLKSEL = MAINCLKSEL_Val; /* Select PLL Clock Output */
\r
454 LPC_SYSCON->MAINCLKUEN = 0x00; /* Toggle Update Register */
\r
455 LPC_SYSCON->MAINCLKUEN = 0x01;
\r
456 //while (!(LPC_SYSCON->MAINCLKUEN & 0x01)); /* Wait Until Updated */
\r
458 #if ((USBCLKSEL_Val & 0x003) == 0) /* USB clock is USB PLL out */
\r
459 //SYSCTL_PowerDown (1 << 8);
\r
460 LPC_SYSCON->USBPLLCLKSEL = USBPLLCLKSEL_Val; /* Select PLL Input */
\r
461 LPC_SYSCON->USBPLLCLKUEN = 0x00; /* Toggle Update Register */
\r
462 LPC_SYSCON->USBPLLCLKUEN = 0x01;
\r
463 //while (!(LPC_SYSCON->USBPLLCLKUEN & 0x01)); /* Wait Until Updated */
\r
464 LPC_SYSCON->USBPLLCTRL = USBPLLCTRL_Val;
\r
465 SYSCTL_PowerUp (1 << 8);
\r
466 while (!(LPC_SYSCON->USBPLLSTAT & 0x01)); /* Wait Until PLL Locked */
\r
467 //LPC_SYSCON->USBCLKSEL = 0x00; /* Select USB PLL */
\r
469 #if ((USBCLKDIV_Val & 0x1FF) != 0) /* USB clock is used */
\r
470 SYSCTL_PowerDown (1 << 10);
\r
471 LPC_SYSCON->USBCLKSEL = USBCLKSEL_Val; /* Select USB Clock */
\r
472 LPC_SYSCON->USBCLKDIV = USBCLKDIV_Val; /* Set USB clock divider */
\r
473 //LPC_SYSCON->PDRUNCFG &= ~(1 << 10); /* Power-up USB PHY */
\r
474 SYSCTL_PowerUp (1 << 10);
\r
479 #else /* USB clock is not used */
\r
480 LPC_SYSCON->PDRUNCFG |= (1 << 10); /* Power-down USB PHY */
\r
481 LPC_SYSCON->PDRUNCFG |= (1 << 8); /* Power-down USB PLL */
\r
486 /* System clock to the IOCON needs to be enabled or
\r
487 most of the I/O related peripherals won't work. */
\r
488 LPC_SYSCON->SYSAHBCLKCTRL |= (1<<16);
\r
490 LPC_IOCON->PIO0_3 = 1; // USB_VBUS
\r
491 LPC_IOCON->PIO0_6 = 1; // USB_CONNECT
\r
493 LPC_SYSCON->SYSAHBCLKCTRL |= 1 << 26;
\r