]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/tool/mbed/mbed-sdk/libraries/mbed/targets/cmsis/TARGET_NXP/TARGET_LPC13XX/system_LPC13Uxx.c
Merge commit '1fe4406f374291ab2e86e95a97341fd9c475fcb8'
[qmk_firmware.git] / tmk_core / tool / mbed / mbed-sdk / libraries / mbed / targets / cmsis / TARGET_NXP / TARGET_LPC13XX / system_LPC13Uxx.c
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
25
26 #include <stdint.h>
27 #include "LPC13Uxx.h"
28
29 /*
30 //-------- <<< Use Configuration Wizard in Context Menu >>> ------------------
31 */
32
33 /*--------------------- Clock Configuration ----------------------------------
34 //
35 // <e> Clock Configuration
36 //   <h> System Oscillator Control Register (SYSOSCCTRL)
37 //     <o1.0>      BYPASS: System Oscillator Bypass Enable
38 //                     <i> If enabled then PLL input (sys_osc_clk) is fed
39 //                     <i> directly from XTALIN and XTALOUT pins.
40 //     <o1.9>      FREQRANGE: System Oscillator Frequency Range
41 //                     <i> Determines frequency range for Low-power oscillator.
42 //                   <0=> 1 - 20 MHz
43 //                   <1=> 15 - 25 MHz
44 //   </h>
45 //
46 //   <h> Watchdog Oscillator Control Register (WDTOSCCTRL)
47 //     <o2.0..4>   DIVSEL: Select Divider for Fclkana
48 //                     <i> wdt_osc_clk = Fclkana/ (2 * (1 + DIVSEL))
49 //                   <0-31>
50 //     <o2.5..8>   FREQSEL: Select Watchdog Oscillator Analog Output Frequency (Fclkana)
51 //                   <0=> Undefined
52 //                   <1=> 0.5 MHz
53 //                   <2=> 0.8 MHz
54 //                   <3=> 1.1 MHz
55 //                   <4=> 1.4 MHz
56 //                   <5=> 1.6 MHz
57 //                   <6=> 1.8 MHz
58 //                   <7=> 2.0 MHz
59 //                   <8=> 2.2 MHz
60 //                   <9=> 2.4 MHz
61 //                   <10=> 2.6 MHz
62 //                   <11=> 2.7 MHz
63 //                   <12=> 2.9 MHz
64 //                   <13=> 3.1 MHz
65 //                   <14=> 3.2 MHz
66 //                   <15=> 3.4 MHz
67 //   </h>
68 //
69 //   <h> System PLL Control Register (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 //     <o3.0..4>   MSEL: Feedback Divider Selection
74 //                     <i> M = MSEL + 1
75 //                   <0-31>
76 //     <o3.5..6>   PSEL: Post Divider Selection
77 //                   <0=> P = 1
78 //                   <1=> P = 2
79 //                   <2=> P = 4
80 //                   <3=> P = 8
81 //   </h>
82 //
83 //   <h> System PLL Clock Source Select Register (SYSPLLCLKSEL)
84 //     <o4.0..1>   SEL: System PLL Clock Source
85 //                   <0=> IRC Oscillator
86 //                   <1=> System Oscillator
87 //                   <2=> Reserved
88 //                   <3=> Reserved
89 //   </h>
90 //
91 //   <h> Main Clock Source Select Register (MAINCLKSEL)
92 //     <o5.0..1>   SEL: Clock Source for Main Clock
93 //                   <0=> IRC Oscillator
94 //                   <1=> Input Clock to System PLL
95 //                   <2=> WDT Oscillator
96 //                   <3=> System PLL Clock Out
97 //   </h>
98 //
99 //   <h> System AHB Clock Divider Register (SYSAHBCLKDIV)
100 //     <o6.0..7>   DIV: System AHB Clock Divider
101 //                     <i> Divides main clock to provide system clock to core, memories, and peripherals.
102 //                     <i> 0 = is disabled
103 //                   <0-255>
104 //   </h>
105 //
106 //   <h> USB PLL Control Register (USBPLLCTRL)
107 //                   <i> F_clkout = M * F_clkin = F_CCO / (2 * P)
108 //                   <i> F_clkin must be in the range of  10 MHz to  25 MHz
109 //                   <i> F_CCO   must be in the range of 156 MHz to 320 MHz
110 //     <o7.0..4>   MSEL: Feedback Divider Selection
111 //                     <i> M = MSEL + 1
112 //                   <0-31>
113 //     <o7.5..6>   PSEL: Post Divider Selection
114 //                   <0=> P = 1
115 //                   <1=> P = 2
116 //                   <2=> P = 4
117 //                   <3=> P = 8
118 //   </h>
119 //
120 //   <h> USB PLL Clock Source Select Register (USBPLLCLKSEL)
121 //     <o8.0..1>   SEL: USB PLL Clock Source
122 //                     <i> USB PLL clock source must be switched to System Oscillator for correct USB operation
123 //                   <0=> IRC Oscillator
124 //                   <1=> System Oscillator
125 //                   <2=> Reserved
126 //                   <3=> Reserved
127 //   </h>
128 //
129 //   <h> USB Clock Source Select Register (USBCLKSEL)
130 //     <o9.0..1>   SEL: System PLL Clock Source
131 //                   <0=> USB PLL out
132 //                   <1=> Main clock
133 //                   <2=> Reserved
134 //                   <3=> Reserved
135 //   </h>
136 //
137 //   <h> USB Clock Divider Register (USBCLKDIV)
138 //     <o10.0..7>  DIV: USB Clock Divider
139 //                     <i> Divides USB clock to 48 MHz.
140 //                     <i> 0 = is disabled
141 //                   <0-255>
142 //   </h>
143 // </e>
144 */
145 #define CLOCK_SETUP           1
146 #define SYSOSCCTRL_Val        0x00000000              // Reset: 0x000
147 #define WDTOSCCTRL_Val        0x00000000              // Reset: 0x000
148 #define SYSPLLCTRL_Val        0x00000025              // Reset: 0x000
149 #define SYSPLLCLKSEL_Val      0x00000001              // Reset: 0x000
150 #define MAINCLKSEL_Val        0x00000003              // Reset: 0x000
151 #define SYSAHBCLKDIV_Val      0x00000001              // Reset: 0x001
152 #define USBPLLCTRL_Val        0x00000023              // Reset: 0x000
153 #define USBPLLCLKSEL_Val      0x00000001              // Reset: 0x000
154 #define USBCLKSEL_Val         0x00000000              // Reset: 0x000
155 #define USBCLKDIV_Val         0x00000001              // Reset: 0x001
156
157 /*
158 //-------- <<< end of configuration section >>> ------------------------------
159 */
160
161 /*----------------------------------------------------------------------------
162   Check the register settings
163  *----------------------------------------------------------------------------*/
164 #define CHECK_RANGE(val, min, max)                ((val < min) || (val > max))
165 #define CHECK_RSVD(val, mask)                     (val & mask)
166
167 /* Clock Configuration -------------------------------------------------------*/
168 #if (CHECK_RSVD((SYSOSCCTRL_Val),  ~0x00000003))
169    #error "SYSOSCCTRL: Invalid values of reserved bits!"
170 #endif
171
172 #if (CHECK_RSVD((WDTOSCCTRL_Val),  ~0x000001FF))
173    #error "WDTOSCCTRL: Invalid values of reserved bits!"
174 #endif
175
176 #if (CHECK_RANGE((SYSPLLCLKSEL_Val), 0, 2))
177    #error "SYSPLLCLKSEL: Value out of range!"
178 #endif
179
180 #if (CHECK_RSVD((SYSPLLCTRL_Val),  ~0x000001FF))
181    #error "SYSPLLCTRL: Invalid values of reserved bits!"
182 #endif
183
184 #if (CHECK_RSVD((MAINCLKSEL_Val),  ~0x00000003))
185    #error "MAINCLKSEL: Invalid values of reserved bits!"
186 #endif
187
188 #if (CHECK_RANGE((SYSAHBCLKDIV_Val), 0, 255))
189    #error "SYSAHBCLKDIV: Value out of range!"
190 #endif
191
192 #if (CHECK_RANGE((USBPLLCLKSEL_Val), 0, 1))
193    #error "USBPLLCLKSEL: Value out of range!"
194 #endif
195
196 #if (CHECK_RSVD((USBPLLCTRL_Val),  ~0x000001FF))
197    #error "USBPLLCTRL: Invalid values of reserved bits!"
198 #endif
199
200 #if (CHECK_RANGE((USBCLKSEL_Val), 0, 1))
201    #error "USBCLKSEL: Value out of range!"
202 #endif
203
204 #if (CHECK_RANGE((USBCLKDIV_Val), 0, 255))
205    #error "USBCLKDIV: Value out of range!"
206 #endif
207
208
209 /*----------------------------------------------------------------------------
210   DEFINES
211  *----------------------------------------------------------------------------*/
212     
213 /*----------------------------------------------------------------------------
214   Define clocks
215  *----------------------------------------------------------------------------*/
216 #define __XTAL            (12000000UL)    /* Oscillator frequency             */
217 #define __SYS_OSC_CLK     (    __XTAL)    /* Main oscillator frequency        */
218 #define __IRC_OSC_CLK     (12000000UL)    /* Internal RC oscillator frequency */
219
220
221 #define __FREQSEL   ((WDTOSCCTRL_Val >> 5) & 0x0F)
222 #define __DIVSEL   (((WDTOSCCTRL_Val & 0x1F) << 1) + 2)
223
224 #if (CLOCK_SETUP)                         /* Clock Setup              */
225   #if  (__FREQSEL ==  0)
226     #define __WDT_OSC_CLK        ( 0)                  /* undefined */
227   #elif (__FREQSEL ==  1)
228     #define __WDT_OSC_CLK        ( 500000 / __DIVSEL)
229   #elif (__FREQSEL ==  2)
230     #define __WDT_OSC_CLK        ( 800000 / __DIVSEL)
231   #elif (__FREQSEL ==  3)
232     #define __WDT_OSC_CLK        (1100000 / __DIVSEL)
233   #elif (__FREQSEL ==  4)
234     #define __WDT_OSC_CLK        (1400000 / __DIVSEL)
235   #elif (__FREQSEL ==  5)
236     #define __WDT_OSC_CLK        (1600000 / __DIVSEL)
237   #elif (__FREQSEL ==  6)
238     #define __WDT_OSC_CLK        (1800000 / __DIVSEL)
239   #elif (__FREQSEL ==  7)
240     #define __WDT_OSC_CLK        (2000000 / __DIVSEL)
241   #elif (__FREQSEL ==  8)
242     #define __WDT_OSC_CLK        (2200000 / __DIVSEL)
243   #elif (__FREQSEL ==  9)
244     #define __WDT_OSC_CLK        (2400000 / __DIVSEL)
245   #elif (__FREQSEL == 10)
246     #define __WDT_OSC_CLK        (2600000 / __DIVSEL)
247   #elif (__FREQSEL == 11)
248     #define __WDT_OSC_CLK        (2700000 / __DIVSEL)
249   #elif (__FREQSEL == 12)
250     #define __WDT_OSC_CLK        (2900000 / __DIVSEL)
251   #elif (__FREQSEL == 13)
252     #define __WDT_OSC_CLK        (3100000 / __DIVSEL)
253   #elif (__FREQSEL == 14)
254     #define __WDT_OSC_CLK        (3200000 / __DIVSEL)
255   #else
256     #define __WDT_OSC_CLK        (3400000 / __DIVSEL)
257   #endif
258
259   /* sys_pllclkin calculation */
260   #if   ((SYSPLLCLKSEL_Val & 0x03) == 0)
261     #define __SYS_PLLCLKIN           (__IRC_OSC_CLK)
262   #elif ((SYSPLLCLKSEL_Val & 0x03) == 1)
263     #define __SYS_PLLCLKIN           (__SYS_OSC_CLK)
264   #else
265     #define __SYS_PLLCLKIN           (0)
266   #endif
267
268   #define  __SYS_PLLCLKOUT         (__SYS_PLLCLKIN * ((SYSPLLCTRL_Val & 0x01F) + 1))
269
270   /* main clock calculation */
271   #if   ((MAINCLKSEL_Val & 0x03) == 0)
272     #define __MAIN_CLOCK             (__IRC_OSC_CLK)
273   #elif ((MAINCLKSEL_Val & 0x03) == 1)
274     #define __MAIN_CLOCK             (__SYS_PLLCLKIN)
275   #elif ((MAINCLKSEL_Val & 0x03) == 2)
276     #if (__FREQSEL ==  0)
277       #error "MAINCLKSEL: WDT Oscillator selected but FREQSEL is undefined!"
278     #else
279       #define __MAIN_CLOCK           (__WDT_OSC_CLK)
280     #endif
281   #elif ((MAINCLKSEL_Val & 0x03) == 3)
282     #define __MAIN_CLOCK             (__SYS_PLLCLKOUT)
283   #else
284     #define __MAIN_CLOCK             (0)
285   #endif
286
287   #define __SYSTEM_CLOCK             (__MAIN_CLOCK / SYSAHBCLKDIV_Val)         
288
289 #else
290   #define __SYSTEM_CLOCK             (__IRC_OSC_CLK)
291 #endif  // CLOCK_SETUP 
292
293
294 /*----------------------------------------------------------------------------
295   Clock Variable definitions
296  *----------------------------------------------------------------------------*/
297 uint32_t SystemCoreClock = __SYSTEM_CLOCK;/*!< System Clock Frequency (Core Clock)*/
298
299
300 /*----------------------------------------------------------------------------
301   Clock functions
302  *----------------------------------------------------------------------------*/
303 void SystemCoreClockUpdate (void)            /* Get Core Clock Frequency      */
304 {
305   uint32_t wdt_osc = 0;
306
307   /* Determine clock frequency according to clock register values             */
308   switch ((LPC_SYSCON->WDTOSCCTRL >> 5) & 0x0F) {
309     case 0:  wdt_osc =       0; break;
310     case 1:  wdt_osc =  500000; break;
311     case 2:  wdt_osc =  800000; break;
312     case 3:  wdt_osc = 1100000; break;
313     case 4:  wdt_osc = 1400000; break;
314     case 5:  wdt_osc = 1600000; break;
315     case 6:  wdt_osc = 1800000; break;
316     case 7:  wdt_osc = 2000000; break;
317     case 8:  wdt_osc = 2200000; break;
318     case 9:  wdt_osc = 2400000; break;
319     case 10: wdt_osc = 2600000; break;
320     case 11: wdt_osc = 2700000; break;
321     case 12: wdt_osc = 2900000; break;
322     case 13: wdt_osc = 3100000; break;
323     case 14: wdt_osc = 3200000; break;
324     case 15: wdt_osc = 3400000; break;
325   }
326   wdt_osc /= ((LPC_SYSCON->WDTOSCCTRL & 0x1F) << 1) + 2;
327  
328   switch (LPC_SYSCON->MAINCLKSEL & 0x03) {
329     case 0:                             /* Internal RC oscillator             */
330       SystemCoreClock = __IRC_OSC_CLK;
331       break;
332     case 1:                             /* Input Clock to System PLL          */
333       switch (LPC_SYSCON->SYSPLLCLKSEL & 0x03) {
334           case 0:                       /* Internal RC oscillator             */
335             SystemCoreClock = __IRC_OSC_CLK;
336             break;
337           case 1:                       /* System oscillator                  */
338             SystemCoreClock = __SYS_OSC_CLK;
339             break;
340           case 2:                       /* Reserved                           */
341           case 3:                       /* Reserved                           */
342             SystemCoreClock = 0;
343             break;
344       }
345       break;
346     case 2:                             /* WDT Oscillator                     */
347       SystemCoreClock = wdt_osc;
348       break;
349     case 3:                             /* System PLL Clock Out               */
350       switch (LPC_SYSCON->SYSPLLCLKSEL & 0x03) {
351           case 0:                       /* Internal RC oscillator             */
352             if (LPC_SYSCON->SYSPLLCTRL & 0x180) {
353               SystemCoreClock = __IRC_OSC_CLK;
354             } else {
355               SystemCoreClock = __IRC_OSC_CLK * ((LPC_SYSCON->SYSPLLCTRL & 0x01F) + 1);
356             }
357             break;
358           case 1:                       /* System oscillator                  */
359             if (LPC_SYSCON->SYSPLLCTRL & 0x180) {
360               SystemCoreClock = __SYS_OSC_CLK;
361             } else {
362               SystemCoreClock = __SYS_OSC_CLK * ((LPC_SYSCON->SYSPLLCTRL & 0x01F) + 1);
363             }
364             break;
365           case 2:                       /* Reserved                           */
366           case 3:                       /* Reserved                           */
367             SystemCoreClock = 0;
368             break;
369       }
370       break;
371   }
372
373   SystemCoreClock /= LPC_SYSCON->SYSAHBCLKDIV;  
374
375 }
376
377 /**
378  * Initialize the system
379  *
380  * @param  none
381  * @return none
382  *
383  * @brief  Setup the microcontroller system.
384  *         Initialize the System.
385  */
386 void SystemInit (void) {
387   volatile uint32_t i;
388
389 #if (CLOCK_SETUP)                                 /* Clock Setup              */
390
391 #if ((SYSPLLCLKSEL_Val & 0x03) == 1)
392   LPC_SYSCON->PDRUNCFG     &= ~(1 << 5);          /* Power-up System Osc      */
393   LPC_SYSCON->SYSOSCCTRL    = SYSOSCCTRL_Val;
394   for (i = 0; i < 200; i++) __NOP();
395 #endif
396
397   LPC_SYSCON->SYSPLLCLKSEL  = SYSPLLCLKSEL_Val;   /* Select PLL Input         */
398 #if ((MAINCLKSEL_Val & 0x03) == 3)                /* Main Clock is PLL Out    */
399   LPC_SYSCON->SYSPLLCTRL    = SYSPLLCTRL_Val;
400   LPC_SYSCON->PDRUNCFG     &= ~(1 << 7);          /* Power-up SYSPLL          */
401   while (!(LPC_SYSCON->SYSPLLSTAT & 0x01));           /* Wait Until PLL Locked    */
402 #endif
403
404 #if (((MAINCLKSEL_Val & 0x03) == 2) )
405   LPC_SYSCON->WDTOSCCTRL    = WDTOSCCTRL_Val;
406   LPC_SYSCON->PDRUNCFG     &= ~(1 << 6);          /* Power-up WDT Clock       */
407   for (i = 0; i < 200; i++) __NOP();
408 #endif
409
410   LPC_SYSCON->MAINCLKSEL    = MAINCLKSEL_Val;     /* Select PLL Clock Output  */
411
412   LPC_SYSCON->SYSAHBCLKDIV  = SYSAHBCLKDIV_Val;
413
414 #if ((USBCLKDIV_Val & 0x1FF) != 0)                /* USB clock is used        */
415   LPC_SYSCON->PDRUNCFG     &= ~(1 << 10);         /* Power-up USB PHY         */
416
417   /* Regardless USB PLL is used as USB clock or not, USB PLL needs to be configured. */
418   LPC_SYSCON->PDRUNCFG     &= ~(1 <<  8);         /* Power-up USB PLL         */
419   LPC_SYSCON->USBPLLCLKSEL  = USBPLLCLKSEL_Val;   /* Select PLL Input         */
420   LPC_SYSCON->USBPLLCTRL    = USBPLLCTRL_Val;
421   while (!(LPC_SYSCON->USBPLLSTAT   & 0x01));     /* Wait Until PLL Locked    */
422
423   LPC_SYSCON->USBCLKSEL     = USBCLKSEL_Val;      /* Select USB Clock         */
424   LPC_SYSCON->USBCLKDIV     = USBCLKDIV_Val;      /* Set USB clock divider    */
425
426 #else                                             /* USB clock is not used    */                        
427   LPC_SYSCON->PDRUNCFG     |=  (1 << 10);         /* Power-down USB PHY       */
428   LPC_SYSCON->PDRUNCFG     |=  (1 <<  8);         /* Power-down USB PLL       */
429 #endif
430
431 #endif
432
433   /* System clock to the IOCON needs to be enabled or
434   most of the I/O related peripherals won't work. */
435   LPC_SYSCON->SYSAHBCLKCTRL |= (1<<16);
436
437 }