]>
git.gir.st - tmk_keyboard.git/blob - tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC15XX/system_LPC15xx.c
1 /**************************************************************************//**
2 * @file system_LPC15xx.c
3 * @brief CMSIS Cortex-M3 Device System Source File for
4 * NXP LPC15xx Device Series
9 * Copyright (C) 2013 ARM Limited. All rights reserved.
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.
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.
23 ******************************************************************************/
30 //-------- <<< Use Configuration Wizard in Context Menu >>> ------------------
33 /*- SystemCoreClock Configuration -------------------------------------------*/
34 // <e0> SystemCoreClock Configuration
37 // <h> System Oscillator Control (SYSOSCCTRL)
38 // <o.0> BYPASS: System Oscillator Bypass Enable
39 // <i> If enabled then PLL input (sys_osc_clk) is fed
40 // <i> directly from XTALIN and XTALOUT pins.
41 // <o.1> FREQRANGE: System Oscillator Frequency Range
42 // <i> Determines frequency range for Low-power oscillator.
46 #define SYSOSCCTRL_Val 0x00000000 // Reset value: 0x000
48 // <o.0..1> System PLL Clock Source Select (SYSPLLCLKSEL)
49 // <0=> IRC Oscillator
50 // <1=> Crystal Oscillator (SYSOSC)
51 #define SYSPLLCLKSEL_Val 0x00000001 // Reset value: 0x000
53 // <e> Clock Configuration (Manual)
54 #define CLOCK_SETUP_REG 1
56 // <o.0..1> Main Clock Source Select A (MAINCLKSELA)
57 // <0=> IRC Oscillator
58 // <1=> System Oscillator
60 #define MAINCLKSELA_Val 0x00000001 // Reset value: 0x000
62 // <o.0..1> Main Clock Source Select B (MAINCLKSELB)
64 // <1=> System PLL Input
65 // <2=> System PLL Output
66 // <3=> RTC Oscillator
67 #define MAINCLKSELB_Val 0x00000002 // Reset value: 0x000
69 // <h> System PLL Setting (SYSPLLCTRL)
70 // <i> F_clkout = M * F_clkin = F_CCO / (2 * P)
71 // <i> F_clkin must be in the range of 10 MHz to 25 MHz
72 // <i> F_CCO must be in the range of 156 MHz to 320 MHz
73 // <o.0..5> MSEL: Feedback Divider Selection
76 // <o.5..7> PSEL: Post Divider Selection
77 // <i> Post divider ratio P. Division ratio is 2 * P
83 #define SYSPLLCTRL_Val 0x00000005 // Reset value: 0x000
85 // <o.0..7> System AHB Clock Divider (SYSAHBCLKDIV.DIV)
86 // <i> Divides main clock to provide system clock to core, memories, and peripherals.
87 // <i> 0 = is disabled
89 #define SYSAHBCLKDIV_Val 0x00000001 // Reset value: 0x001
92 // <e> Clock Configuration (via ROM PLL API)
93 #define CLOCK_SETUP_API 0
95 // <o> PLL API Mode Select
97 // <1=> Less than or equal
98 // <2=> Greater than or equal
99 // <3=> As close as possible
100 #define PLL_API_MODE_Val 0
102 // <o> CPU Frequency [Hz] <1000000-72000000:1000>
103 #define PLL_API_FREQ_Val 72000000
106 // <e> USB Clock Configuration
107 #define USB_CLOCK_SETUP 0
108 // <h> USB PLL Control (USBPLLCTRL)
109 // <i> F_clkout = M * F_clkin = F_CCO / (2 * P)
110 // <i> F_clkin must be in the range of 10 MHz to 25 MHz
111 // <i> F_CCO must be in the range of 156 MHz to 320 MHz
112 // <o.0..5> MSEL: Feedback Divider Selection
115 // <o.7..6> PSEL: Post Divider Selection
116 // <i> Post divider ratio P. Division ratio is 2 * P
122 #define USBPLLCTRL_Val 0x00000023 // Reset value: 0x000
124 // <o.0..1> USB PLL Clock Source Select (USBPLLCLKSEL.SEL)
125 // <0=> IRC Oscillator
126 // <1=> System Oscillator
127 #define USBPLLCLKSEL_Val 0x00000001 // Reset value: 0x000
129 // <o.0..1> USB Clock Source Select (USBCLKSEL.SEL)
130 // <0=> IRC Oscillator
131 // <1=> System Oscillator
134 #define USBCLKSEL_Val 0x00000002 // Reset value: 0x000
136 // <o.0..7> USB Clock Divider (USBCLKDIV.DIV)
137 // <i> Divides USB clock to 48 MHz.
138 // <i> 0 = is disabled
140 #define USBCLKDIV_Val 0x00000001 // Reset Value: 0x001
143 // <e> SCT Clock Configuration
144 #define SCT_CLOCK_SETUP 1
145 // <h> SCT PLL Control (SCTPLLCTRL)
146 // <i> F_clkout = M * F_clkin = F_CCO / (2 * P)
147 // <i> F_clkin must be in the range of 10 MHz to 25 MHz
148 // <i> F_CCO must be in the range of 156 MHz to 320 MHz
149 // <o.0..5> MSEL: Feedback Divider Selection
152 // <o.7..6> PSEL: Post Divider Selection
153 // <i> Post divider ratio P. Division ratio is 2 * P
159 #define SCTPLLCTRL_Val 0x00000005 // Reset value: 0x000
161 // <o.0..1> SCT PLL Clock Source Select (SCTPLLCLKSEL.SEL)
162 // <0=> IRC Oscillator
163 // <1=> System Oscillator
164 #define SCTPLLCLKSEL_Val 0x00000001 // Reset value: 0x000
169 // <o0>System Oscillator (XTAL) Frequency [Hz] <1000000-25000000>
170 // <i> XTAL frequency must be in the range of 1 MHz to 25 MHz
172 #define XTAL_CLK_Val 12000000
175 //-------- <<< end of configuration section >>> ------------------------------
178 /*----------------------------------------------------------------------------
180 *----------------------------------------------------------------------------*/
181 #define __XTAL_CLK ( XTAL_CLK_Val) /* Oscillator freq */
182 #define __SYS_OSC_CLK ( __XTAL_CLK) /* System oscillator freq */
183 #define __IRC_OSC_CLK ( 12000000UL) /* Internal RC oscillator freq */
184 #define __RTC_OSC_CLK ( 32768UL) /* RTC oscillator freq */
185 #define __WDT_OSC_CLK ( 503000UL) /* WDT oscillator freq */
187 /*----------------------------------------------------------------------------
188 Check the register settings
189 *----------------------------------------------------------------------------*/
190 #define CHECK_RANGE(val, min, max) ((val < min) || (val > max))
191 #define CHECK_RSVD(val, mask) (val & mask)
193 #if (CHECK_RANGE((SYSOSCCTRL_Val), 0, 1))
194 #error "SYSOSCCTRL: Invalid values of reserved bits!"
197 #if (CHECK_RANGE((SYSPLLCLKSEL_Val), 0, 3))
198 #error "SYSPLLCLKSEL: Value out of range!"
201 #if (CHECK_RSVD((SYSPLLCTRL_Val), ~0x000000FF))
202 #error "SYSPLLCTRL: Invalid values of reserved bits!"
205 #if (CHECK_RANGE((MAINCLKSELA_Val), 0, 2))
206 #error "MAINCLKSELA: Invalid values of reserved bits!"
209 #if (CHECK_RSVD((MAINCLKSELB_Val), ~0x00000003))
210 #error "MAINCLKSELB: Invalid values of reserved bits!"
213 #if (CHECK_RANGE((SYSAHBCLKDIV_Val), 0, 255))
214 #error "SYSAHBCLKDIV: Value out of range!"
217 #if ( CLOCK_SETUP_REG == CLOCK_SETUP_API )
218 #error "You must select either manual or API based Clock Configuration!"
221 #if (CHECK_RANGE((USBPLLCLKSEL_Val), 0, 1))
222 #error "USBPLLCLKSEL: Value out of range!"
225 #if (CHECK_RSVD((USBPLLCTRL_Val), ~0x00000FF))
226 #error "USBPLLCTRL: Invalid values of reserved bits!"
229 #if (CHECK_RANGE((USBCLKSEL_Val), 0, 3))
230 #error "USBCLKSEL: Value out of range!"
233 #if (CHECK_RANGE((USBCLKDIV_Val), 0, 255))
234 #error "USBCLKDIV: Value out of range!"
237 #if (CHECK_RANGE((SCTPLLCLKSEL_Val), 0, 1))
238 #error "SCTPLLCLKSEL: Value out of range!"
241 #if (CHECK_RSVD((SCTPLLCTRL_Val), ~0x00000FF))
242 #error "SCTPLLCTRL: Invalid values of reserved bits!"
245 #if (CHECK_RANGE(XTAL_CLK_Val, 1000000, 25000000))
246 #error "XTAL frequency is out of bounds"
249 #if (CHECK_RANGE(PLL_API_MODE_Val, 0, 3))
250 #error "PLL API Mode Select not valid"
253 #if (CHECK_RANGE(PLL_API_FREQ_Val, 1000000, 72000000))
254 #error "CPU Frequency (API mode) not valid"
259 /*----------------------------------------------------------------------------
260 Calculate system core clock
261 *----------------------------------------------------------------------------*/
262 #if (CLOCK_SETUP) /* Clock Setup */
264 /* sys_pllclkin calculation */
265 #if ((SYSPLLCLKSEL_Val & 0x03) == 0)
266 #define __SYS_PLLCLKIN (__IRC_OSC_CLK)
267 #elif ((SYSPLLCLKSEL_Val & 0x03) == 1)
268 #define __SYS_PLLCLKIN (__SYS_OSC_CLK)
273 #if (CLOCK_SETUP_REG == 1) /* Clock Setup via Register */
275 #if ((MAINCLKSELA_Val & 0x03) == 0)
276 #define __MAINA_CLOCK (__IRC_OSC_CLK)
277 #elif ((MAINCLKSELA_Val & 0x03) == 1)
278 #define __MAINA_CLOCK (__SYS_OSC_CLK)
279 #elif ((MAINCLKSELA_Val & 0x03) == 2)
280 #define __MAINA_CLOCK (__WDT_OSC_CLK)
285 #define __SYS_PLLCLKOUT (__SYS_PLLCLKIN * ((SYSPLLCTRL_Val & 0x01F) + 1))
287 /* main clock calculation */
288 #if ((MAINCLKSELB_Val & 0x03) == 0)
289 #define __MAINB_CLOCK (__MAINA_CLOCK)
290 #elif ((MAINCLKSELB_Val & 0x03) == 1)
291 #define __MAINB_CLOCK (__SYS_PLLCLKIN)
292 #elif ((MAINCLKSELB_Val & 0x03) == 2)
293 #define __MAINB_CLOCK (__SYS_PLLCLKOUT)
294 #elif ((MAINCLKSELB_Val & 0x03) == 3)
295 #define __MAINB_CLOCK (__RTC_OSC_CLK)
300 #define __SYSTEM_CLOCK (__MAINB_CLOCK / SYSAHBCLKDIV_Val)
301 #endif /* Clock Setup via Register */
303 #if (CLOCK_SETUP_API == 1) /* Clock Setup via ROM API */
304 #define __SYSTEM_CLOCK (PLL_API_FREQ_Val)
305 #endif /* Clock Setup via PLL API */
308 #define __SYSTEM_CLOCK (__IRC_OSC_CLK)
309 #endif /* CLOCK_SETUP */
313 #if ((CLOCK_SETUP == 1) && (CLOCK_SETUP_API == 1)) /* PLL Setup via PLL API */
314 #include "power_api.h"
316 typedef struct _ROM
{
317 const unsigned p_dev0
;
318 const unsigned p_dev1
;
319 const unsigned p_dev2
;
320 const PWRD
* pPWRD
; /* ROM Power Management API */
321 const unsigned p_dev4
;
322 const unsigned p_dev5
;
323 const unsigned p_dev6
;
324 const unsigned p_dev7
;
327 /*----------------------------------------------------------------------------
329 *----------------------------------------------------------------------------*/
330 static void setPLL(const uint32_t pllMode
, const uint32_t pllInFreq
, const uint32_t reqCpuFreq
)
332 uint32_t cmd
[5], res
[5];
333 ROM
** rom
= (ROM
**) 0x03000200; /* pointer to power API calls */
335 cmd
[0] = pllInFreq
; /* PLL's input freq in KHz */
336 cmd
[1] = reqCpuFreq
; /* requested CPU freq in KHz */
338 cmd
[3] = 0; /* no timeout for PLL to lock */
340 /* Execute API call */
341 (*rom
)->pPWRD
->set_pll(cmd
, res
); /* call API function */
342 if ((res
[0] != PLL_CMD_SUCCESS
)){ /* in case of an error ... */
343 while(1); /* ... stay here */
351 /*----------------------------------------------------------------------------
352 Clock Variable definitions
353 *----------------------------------------------------------------------------*/
354 uint32_t SystemCoreClock
= __SYSTEM_CLOCK
; /* System Clock Frequency */
357 /*----------------------------------------------------------------------------
359 *----------------------------------------------------------------------------*/
360 void SystemCoreClockUpdate (void) /* Get Core Clock Frequency */
362 /* Determine clock frequency according to clock register values */
363 switch (LPC_SYSCON
->MAINCLKSELB
& 0x03) {
364 case 0: /* MAINCLKSELA clock sel */
365 switch (LPC_SYSCON
->MAINCLKSELA
& 0x03) {
366 case 0: /* Internal RC oscillator */
367 SystemCoreClock
= __IRC_OSC_CLK
;
369 case 1: /* System oscillator */
370 SystemCoreClock
= __SYS_OSC_CLK
;
372 case 2: /* Watchdog oscillator */
373 SystemCoreClock
= __WDT_OSC_CLK
;
375 case 3: /* Reserved */
380 case 1: /* Input Clock to System PLL */
381 switch (LPC_SYSCON
->SYSPLLCLKSEL
& 0x03) {
382 case 0: /* Internal RC oscillator */
383 SystemCoreClock
= __IRC_OSC_CLK
;
385 case 1: /* System oscillator */
386 SystemCoreClock
= __SYS_OSC_CLK
;
388 case 2: /* Reserved */
389 case 3: /* Reserved */
394 case 2: /* System PLL Clock Out */
395 switch (LPC_SYSCON
->SYSPLLCLKSEL
& 0x03) {
396 case 0: /* Internal RC oscillator */
397 SystemCoreClock
= __IRC_OSC_CLK
* ((LPC_SYSCON
->SYSPLLCTRL
& 0x01F) + 1);
399 case 1: /* System oscillator */
400 SystemCoreClock
= __SYS_OSC_CLK
* ((LPC_SYSCON
->SYSPLLCTRL
& 0x01F) + 1);
402 case 2: /* Reserved */
403 case 3: /* Reserved */
408 case 3: /* WDT Oscillator */
409 SystemCoreClock
= __WDT_OSC_CLK
;
413 SystemCoreClock
/= LPC_SYSCON
->SYSAHBCLKDIV
;
418 * Initialize the system
423 * @brief Setup the microcontroller system.
425 void SystemInit (void) {
430 #if (CLOCK_SETUP) /* Clock Setup */
432 #if ((SYSPLLCLKSEL_Val & 0x03) == 1)
433 LPC_SYSCON
->SYSOSCCTRL
= SYSOSCCTRL_Val
;
434 LPC_SYSCON
->PDRUNCFG
&= ~(1 << 21); /* Power-up sysosc */
435 for (i
= 0; i
< 200; i
++) __NOP(); /* Wait for osc to stabilize */
438 LPC_SYSCON
->SYSPLLCLKSEL
= SYSPLLCLKSEL_Val
; /* Select PLL Input */
440 #if (CLOCK_SETUP_REG == 1) /* Clock Setup via Register */
442 #if (((MAINCLKSELA_Val & 0x03) == 1) )
443 LPC_SYSCON
->SYSOSCCTRL
= SYSOSCCTRL_Val
;
444 LPC_SYSCON
->PDRUNCFG
&= ~(1 << 21); /* Power-up sysosc */
445 for (i
= 0; i
< 200; i
++) __NOP(); /* Wait for osc to stabilize */
448 #if (((MAINCLKSELA_Val & 0x03) == 2) )
449 LPC_SYSCON
->PDRUNCFG
&= ~(1 << 20); /* Power-up WDT Clock */
450 for (i
= 0; i
< 200; i
++) __NOP(); /* Wait for osc to stabilize */
453 #if ((MAINCLKSELB_Val & 0x03) == 3)
454 LPC_SYSCON
->RTCOSCCTRL
= (1 << 0); /* Enable 32 kHz output */
455 for (i
= 0; i
< 200; i
++) __NOP(); /* Wait for osc to stabilize */
458 LPC_SYSCON
->MAINCLKSELA
= MAINCLKSELA_Val
; /* select MAINCLKA clock */
460 #if ((MAINCLKSELB_Val & 0x03) == 2) /* Main Clock is PLL Out */
461 LPC_SYSCON
->SYSPLLCTRL
= SYSPLLCTRL_Val
;
462 LPC_SYSCON
->PDRUNCFG
&= ~(1 << 22); /* Power-up SYSPLL */
463 while (!(LPC_SYSCON
->SYSPLLSTAT
& 0x01)); /* Wait Until PLL Locked */
466 LPC_SYSCON
->MAINCLKSELB
= MAINCLKSELB_Val
; /* select Main clock */
468 LPC_SYSCON
->SYSAHBCLKDIV
= SYSAHBCLKDIV_Val
;
469 #endif /* Clock Setup via Register */
471 #if (CLOCK_SETUP_API == 1) /* Clock Setup via PLL API */
472 // LPC_SYSCON->SYSPLLCLKSEL = 0x00; /* Use IRC */
474 LPC_SYSCON
->MAINCLKSELB
= (1 << 2); /* Select System PLL output */
476 LPC_SYSCON
->SYSAHBCLKDIV
= 1;
478 setPLL(PLL_API_MODE_Val
, __SYS_PLLCLKIN
/ 1000, PLL_API_FREQ_Val
/ 1000);
479 #endif /* Clock Setup via PLL API */
481 #if (USB_CLOCK_SETUP == 1) /* USB clock is used */
482 LPC_SYSCON
->PDRUNCFG
&= ~(1 << 9); /* Power-up USB PHY */
484 #if ((USBCLKSEL_Val & 0x003) == 2) /* USB clock is USB PLL out */
485 LPC_SYSCON
->PDRUNCFG
&= ~(1 << 23); /* Power-up USB PLL */
486 LPC_SYSCON
->USBPLLCLKSEL
= USBPLLCLKSEL_Val
; /* Select PLL Input */
488 LPC_SYSCON
->USBPLLCTRL
= USBPLLCTRL_Val
;
489 while (!(LPC_SYSCON
->USBPLLSTAT
& 0x01)); /* Wait Until PLL Locked */
491 LPC_SYSCON
->USBCLKSEL
= 0x02; /* Select USB PLL */
494 LPC_SYSCON
->USBCLKSEL
= USBCLKSEL_Val
; /* Select USB Clock */
495 LPC_SYSCON
->USBCLKDIV
= USBCLKDIV_Val
; /* Set USB clock divider */
497 #else /* USB clock is not used */
498 LPC_SYSCON
->PDRUNCFG
|= (1 << 9); /* Power-down USB PHY */
499 LPC_SYSCON
->PDRUNCFG
|= (1 << 23); /* Power-down USB PLL */
502 #if (SCT_CLOCK_SETUP == 1) /* SCT clock is used */
503 LPC_SYSCON
->PDRUNCFG
&= ~(1 << 24); /* Power-up SCT PLL */
504 LPC_SYSCON
->SCTPLLCLKSEL
= SCTPLLCLKSEL_Val
; /* Select PLL Input */
506 LPC_SYSCON
->SCTPLLCTRL
= SCTPLLCTRL_Val
;
507 while (!(LPC_SYSCON
->SCTPLLSTAT
& 0x01)); /* Wait Until PLL Locked */
508 #else /* SCT clock is not used */
509 LPC_SYSCON
->PDRUNCFG
|= (1 << 24); /* Power-down SCT PLL */
512 #endif /* Clock Setup */
515 LPC_SYSCON
->SYSAHBCLKCTRL0
|= (1UL << 12); /* enable clock for SWM */