2 * @brief LPC43xx System Initialization
5 * Copyright(C) NXP Semiconductors, 2012
9 * Software that is described herein is for illustrative purposes only
10 * which provides customers with programming information regarding the
11 * LPC products. This software is supplied "AS IS" without any warranties of
12 * any kind, and NXP Semiconductors and its licensor disclaim any and
13 * all warranties, express or implied, including all implied warranties of
14 * merchantability, fitness for a particular purpose and non-infringement of
15 * intellectual property rights. NXP Semiconductors assumes no responsibility
16 * or liability for the use of the software, conveys no license or rights under any
17 * patent, copyright, mask work right, or any other intellectual property rights in
18 * or to any products. NXP Semiconductors reserves the right to make changes
19 * in the software without notification. NXP Semiconductors also makes no
20 * representation or warranty that such application will be suitable for the
21 * specified use without further testing or modification.
24 * Permission to use, copy, modify, and distribute this software and its
25 * documentation is hereby granted, under NXP Semiconductors' and its
26 * licensor's relevant copyrights in the software, without fee, provided that it
27 * is used in conjunction with NXP Semiconductors microcontrollers. This
28 * copyright, permission, and disclaimer notice must appear in all copies of
31 * Modified by Micromint USA <support@micromint.com>
35 #define COUNT_OF(a) (sizeof(a)/sizeof(a[0]))
39 uint32_t SystemCoreClock
= MAX_CLOCK_FREQ
;
41 uint32_t SystemCoreClock
= CRYSTAL_MAIN_FREQ_IN
;
45 /* SCU pin definitions for pin muxing */
47 __IO
uint32_t *reg
; /* SCU register address */
48 uint16_t mode
; /* SCU pin mode and function */
51 /* Pins to initialize before clocks are configured */
52 static const PINMUX_GRP_T pre_clock_mux
[] = {
54 {SCU_REG(0x3, 3), (SCU_PINIO_FAST
| 0x3)}, /* P3_3 SPIFI CLK */
55 {SCU_REG(0x3, 4), (SCU_PINIO_FAST
| 0x3)}, /* P3_4 SPIFI D3 */
56 {SCU_REG(0x3, 5), (SCU_PINIO_FAST
| 0x3)}, /* P3_5 SPIFI D2 */
57 {SCU_REG(0x3, 6), (SCU_PINIO_FAST
| 0x3)}, /* P3_6 SPIFI D1 */
58 {SCU_REG(0x3, 7), (SCU_PINIO_FAST
| 0x3)}, /* P3_7 SPIFI D0 */
59 {SCU_REG(0x3, 8), (SCU_PINIO_FAST
| 0x3)} /* P3_8 SPIFI CS/SSEL */
62 /* Pins to initialize after clocks are configured */
63 static const PINMUX_GRP_T post_clock_mux
[] = {
65 {SCU_REG(0x1, 1), (SCU_PINIO_FAST
| 0x0)}, /* P1_1 BOOT0 */
66 {SCU_REG(0x1, 2), (SCU_PINIO_FAST
| 0x0)}, /* P1_2 BOOT1 */
67 {SCU_REG(0x2, 8), (SCU_PINIO_FAST
| 0x0)}, /* P2_8 BOOT2 */
68 {SCU_REG(0x2, 9), (SCU_PINIO_FAST
| 0x0)}, /* P2_9 BOOT3 */
69 /* Micromint Bambino 200/210 */
70 {SCU_REG(0x6, 11), (SCU_PINIO_FAST
| 0x0)}, /* P6_11 LED1 */
71 {SCU_REG(0x2, 5), (SCU_PINIO_FAST
| 0x0)}, /* P2_5 LED2 */
72 {SCU_REG(0x2, 7), (SCU_PINIO_FAST
| 0x0)}, /* P2_7 BTN1 */
73 /* Micromint Bambino 210 */
74 {SCU_REG(0x6, 1), (SCU_PINIO_FAST
| 0x0)}, /* P6_1 LED3 */
75 {SCU_REG(0x6, 2), (SCU_PINIO_FAST
| 0x0)}, /* P6_2 LED4 */
79 /* Structure for initial base clock states */
80 struct CLK_BASE_STATES
{
81 CGU_BASE_CLK_T clk
; /* Base clock */
82 CGU_CLKIN_T clkin
; /* Base clock source */
83 uint8_t powerdn
; /* Set to 1 if base clock is initially powered down */
86 /* Initial base clock states are mostly on */
87 static const struct CLK_BASE_STATES clock_states
[] = {
88 {CLK_BASE_SAFE
, CLKIN_IRC
, 0},
89 {CLK_BASE_APB1
, CLKIN_MAINPLL
, 0},
90 {CLK_BASE_APB3
, CLKIN_MAINPLL
, 0},
91 {CLK_BASE_USB0
, CLKIN_USBPLL
, 1},
92 {CLK_BASE_PERIPH
, CLKIN_MAINPLL
, 0},
93 {CLK_BASE_SPI
, CLKIN_MAINPLL
, 0},
94 {CLK_BASE_PHY_TX
, CLKIN_ENET_TX
, 0},
96 {CLK_BASE_PHY_RX
, CLKIN_ENET_TX
, 0},
98 {CLK_BASE_PHY_RX
, CLKIN_ENET_RX
, 0},
100 {CLK_BASE_SDIO
, CLKIN_MAINPLL
, 0},
101 {CLK_BASE_SSP0
, CLKIN_IDIVC
, 0},
102 {CLK_BASE_SSP1
, CLKIN_IDIVC
, 0},
103 {CLK_BASE_UART0
, CLKIN_MAINPLL
, 0},
104 {CLK_BASE_UART1
, CLKIN_MAINPLL
, 0},
105 {CLK_BASE_UART2
, CLKIN_MAINPLL
, 0},
106 {CLK_BASE_UART3
, CLKIN_MAINPLL
, 0},
107 {CLK_BASE_OUT
, CLKINPUT_PD
, 0},
108 {CLK_BASE_APLL
, CLKINPUT_PD
, 0},
109 {CLK_BASE_CGU_OUT0
, CLKINPUT_PD
, 0},
110 {CLK_BASE_CGU_OUT1
, CLKINPUT_PD
, 0},
112 /* Clocks derived from dividers */
113 {CLK_BASE_LCD
, CLKIN_IDIVC
, 0},
114 {CLK_BASE_USB1
, CLKIN_IDIVD
, 1}
116 #endif /* defined(CLOCK_SETUP) */
118 /* Local functions */
119 static uint32_t SystemGetMainPLLHz(void);
120 static void SystemSetupClock(void);
121 static void SystemSetupPins(const PINMUX_GRP_T
*mux
, uint32_t n
);
122 static void SystemSetupMemory(void);
123 static void WaitUs(uint32_t us
);
125 #endif /* !defined(CORE_M0) */
128 * SystemInit() - Initialize the system
130 void SystemInit(void)
132 #if !defined(CORE_M0)
134 /* Initialize vector table in flash */
135 #if defined(__ARMCC_VERSION)
136 extern void *__Vectors
;
138 SCB
->VTOR
= (unsigned int) &__Vectors
;
139 #elif defined(__IAR_SYSTEMS_ICC__)
140 extern void *__vector_table
;
142 SCB
->VTOR
= (unsigned int) &__vector_table
;
143 #elif defined(TOOLCHAIN_GCC_ARM)
144 extern void *__isr_vector
;
146 SCB
->VTOR
= (unsigned int) &__isr_vector
;
147 #else /* defined(__GNUC__) and others */
148 extern void *g_pfnVectors
;
150 SCB
->VTOR
= (unsigned int) &g_pfnVectors
;
153 #if defined(__FPU_PRESENT) && __FPU_PRESENT == 1
154 /* Initialize floating point */
158 SystemSetupPins(pre_clock_mux
, COUNT_OF(pre_clock_mux
)); /* Configure pins */
159 SystemSetupClock(); /* Configure processor and peripheral clocks */
160 SystemSetupPins(post_clock_mux
, COUNT_OF(post_clock_mux
)); /* Configure pins */
161 SystemSetupMemory(); /* Configure external memory */
162 #endif /* !defined(CORE_M0) */
164 SystemCoreClockUpdate(); /* Update SystemCoreClock variable */
168 * SystemCoreClockUpdate() - Update SystemCoreClock variable
170 void SystemCoreClockUpdate(void)
172 uint32_t reg
, div
, rate
;
174 /* Get main PLL rate */
175 rate
= SystemGetMainPLLHz();
177 /* Get clock divider */
178 reg
= LPC_CCU1
->CLKCCU
[CLK_MX_MXCORE
].CFG
;
179 if (((reg
>> 5) & 0x7) == 0) {
187 SystemCoreClock
= rate
;
190 /* Returns the frequency of the main PLL */
191 uint32_t SystemGetMainPLLHz(void)
193 uint32_t PLLReg
= LPC_CGU
->PLL1_CTRL
;
194 uint32_t freq
= CRYSTAL_MAIN_FREQ_IN
;
195 uint32_t msel
, nsel
, psel
, direct
, fbsel
;
197 const uint8_t ptab
[] = {1, 2, 4, 8};
199 msel
= (PLLReg
>> 16) & 0xFF;
200 nsel
= (PLLReg
>> 12) & 0x3;
201 psel
= (PLLReg
>> 8) & 0x3;
202 direct
= (PLLReg
>> 7) & 0x1;
203 fbsel
= (PLLReg
>> 6) & 0x1;
209 if (direct
|| fbsel
) {
210 return m
* (freq
/ n
);
213 return (m
/ (2 * p
)) * (freq
/ n
);
216 #if !defined(CORE_M0)
218 * SystemSetupClock() - Set processor and peripheral clocks
220 * Clock Frequency Source
221 * CLK_BASE_MX 204 MHz CLKIN_MAINPLL (CLKIN_PLL1)
222 * CLK_BASE_SPIFI 102 MHz CLKIN_IDIVE
223 * CLK_BASE_USB0 480 MHz CLKIN_USBPLL (Disabled) (CLKIN_PLL0USB)
224 * CLK_BASE_USB1 60 MHz CLKIN_IDIVE (Disabled)
225 * 120 MHz CLKIN_IDIVD (Disabled)
231 void SystemSetupClock(void)
236 /* Switch main clock to Internal RC (IRC) while setting up PLL1 */
237 LPC_CGU
->BASE_CLK
[CLK_BASE_MX
] = (1 << 11) | (CLKIN_IRC
<< 24);
238 /* Set prescaler/divider on SSP1 assuming 204 MHz clock */
239 LPC_SSP1
->CR1
&= ~(1 << 1);
240 LPC_SSP1
->CPSR
= 0x0002;
241 LPC_SSP1
->CR0
= 0x00006507;
242 LPC_SSP1
->CR1
|= (1 << 1);
244 /* Enable the oscillator and wait 100 us */
245 LPC_CGU
->XTAL_OSC_CTRL
= 0;
249 /* Setup SPIFI control register and no-opcode mode */
250 LPC_SPIFI
->CTRL
= (0x100 << 0) | (1 << 16) | (1 << 29) | (1 << 30);
251 LPC_SPIFI
->IDATA
= 0xA5;
252 /* Switch IDIVE clock to IRC and connect to SPIFI clock */
253 LPC_CGU
->IDIV_CTRL
[CLK_IDIV_E
] = ((1 << 11) | (CLKIN_IRC
<< 24));
254 LPC_CGU
->BASE_CLK
[CLK_BASE_SPIFI
] = ((1 << 11) | (CLKIN_IDIVE
<< 24));
255 #endif /* SPIFI_INIT */
257 /* Configure PLL1 (MAINPLL) for main clock */
258 LPC_CGU
->PLL1_CTRL
|= 1; /* Power down PLL1 */
260 /* Change PLL1 to 108 Mhz (msel=9, 12 MHz*9=108 MHz) */
261 LPC_CGU
->PLL1_CTRL
= (1 << 7) | (0 << 8) | (1 << 11) | (0 << 12) | (8 << 16)
262 | (CLKIN_MAINPLL
<< 24);
263 while (!(LPC_CGU
->PLL1_STAT
& 1)); /* Wait for PLL1 to lock */
266 /* Change PLL1 to 204 Mhz (msel=17, 12 MHz*17=204 MHz) */
267 LPC_CGU
->PLL1_CTRL
= (1 << 7) | (0 << 8) | (1 << 11) | (0 << 12) | (16 << 16)
268 | (CLKIN_MAINPLL
<< 24);
269 while (!(LPC_CGU
->PLL1_STAT
& 1)); /* Wait for PLL1 to lock */
271 /* Connect main clock to PLL1 */
272 LPC_CGU
->BASE_CLK
[CLK_BASE_MX
] = (1 << 11) | (CLKIN_MAINPLL
<< 24);
274 /* Set USB PLL dividers for 480 MHz (for USB0) */
275 LPC_CGU
->PLL
[CGU_USB_PLL
].PLL_MDIV
= 0x06167FFA;
276 LPC_CGU
->PLL
[CGU_USB_PLL
].PLL_NP_DIV
= 0x00302062;
277 LPC_CGU
->PLL
[CGU_USB_PLL
].PLL_CTRL
= 0x0000081D | (CLKIN_CRYSTAL
<< 24);
279 /* Set IDIVE clock to PLL1/2 = 102 MHz */
280 LPC_CGU
->IDIV_CTRL
[CLK_IDIV_E
] = (1 << 2) | (1 << 11) | (CLKIN_MAINPLL
<< 24); /* PLL1/2 */
282 /* Set IDIVD clock to ((USBPLL/4) / 2) = 60 MHz (for USB1) */
283 LPC_CGU
->IDIV_CTRL
[CLK_IDIV_A
] = (3 << 2) | (1 << 11) | (CLKIN_USBPLL
<< 24); /* USBPLL/4 */
284 LPC_CGU
->IDIV_CTRL
[CLK_IDIV_D
] = (1 << 2) | (1 << 11) | (CLKIN_IDIVA
<< 24); /* IDIVA/2 */
286 /* Configure remaining integer dividers */
287 LPC_CGU
->IDIV_CTRL
[CLK_IDIV_B
] = (0 << 2) | (1 << 11) | (CLKIN_IRC
<< 24); /* IRC */
288 LPC_CGU
->IDIV_CTRL
[CLK_IDIV_C
] = (1 << 2) | (1 << 11) | (CLKIN_MAINPLL
<< 24); /* PLL1/2 */
290 /* Connect base clocks */
291 for (i
= 0; i
< COUNT_OF(clock_states
); i
++) {
292 LPC_CGU
->BASE_CLK
[clock_states
[i
].clk
] =
293 ( clock_states
[i
].powerdn
<< 0)
294 | (1 << 11) | (clock_states
[i
].clkin
<< 24);
296 #endif /* CLOCK_SETUP */
297 /* Reset peripherals */
298 LPC_RGU
->RESET_CTRL0
= 0x105F0000;
299 LPC_RGU
->RESET_CTRL1
= 0x01DFF7FF;
303 * SystemSetupPins() - Configure MCU pins
305 void SystemSetupPins(const PINMUX_GRP_T
*mux
, uint32_t n
)
309 for (i
= 0; i
< n
; i
++) {
310 *(mux
[i
].reg
) = mux
[i
].mode
;
315 * SystemSetupMemory() - Configure external memory
317 void SystemSetupMemory(void)
320 /* None required for boards without external memory */
321 #endif /* MEMORY_SETUP */
324 #if defined(__FPU_PRESENT) && __FPU_PRESENT == 1
326 * fpuInit() - Early initialization of the FPU
331 * from ARM TRM manual:
332 * ; CPACR is located at address 0xE000ED88
333 * LDR.W R0, =0xE000ED88
336 * ; Set bits 20-23 to enable CP10 and CP11 coprocessors
337 * ORR R1, R1, #(0xF << 20)
338 * ; Write back the modified value to the CPACR
342 volatile uint32_t *regCpacr
= (uint32_t *) LPC_CPACR
;
343 volatile uint32_t *regMvfr0
= (uint32_t *) SCB_MVFR0
;
344 volatile uint32_t *regMvfr1
= (uint32_t *) SCB_MVFR1
;
345 volatile uint32_t Cpacr
;
346 volatile uint32_t Mvfr0
;
347 volatile uint32_t Mvfr1
;
353 vfpPresent
= ((SCB_MVFR0_RESET
== Mvfr0
) && (SCB_MVFR1_RESET
== Mvfr1
));
357 Cpacr
|= (0xF << 20);
358 *regCpacr
= Cpacr
; /* enable CP10 and CP11 for full access */
361 #endif /* defined(__FPU_PRESENT) && __FPU_PRESENT == 1 */
363 /* Approximate delay function */
364 #define CPU_NANOSEC(x) (((uint64_t) (x) * SystemCoreClock) / 1000000000)
366 static void WaitUs(uint32_t us
)
368 volatile uint32_t cyc
= us
* CPU_NANOSEC(1000) / 4;
373 #endif /* !defined(CORE_M0) */