1 /***********************************************************************
\r
2 * $Id: system_LPC43xx.c 8389 2011-10-19 13:53:14Z nxp28536 $
\r
4 * Project: LPC43xx Common
\r
7 * CMSIS Cortex-M4 Device Peripheral Access Layer Source File
\r
8 * for the NXP LPC43xx Device Series
\r
10 ***********************************************************************
\r
11 * Software that is described herein is for illustrative purposes only
\r
12 * which provides customers with programming information regarding the
\r
13 * products. This software is supplied "AS IS" without any warranties.
\r
14 * NXP Semiconductors assumes no responsibility or liability for the
\r
15 * use of the software, conveys no license or title under any patent,
\r
16 * copyright, or mask work right to the product. NXP Semiconductors
\r
17 * reserves the right to make changes in the software without
\r
18 * notification. NXP Semiconductors also make no representation or
\r
19 * warranty that such application will be suitable for the specified
\r
20 * use without further testing or modification.
\r
21 **********************************************************************/
\r
25 #include "LPC43xx.h" /* LPC18xx definitions */
\r
29 #include "LPC43xx_M0.h" /* LPC18xx definitions */
\r
37 /*--------------------- Clock Configuration ----------------------------------*/
\r
39 #define FLASH_SETUP 0
\r
40 #define FLASHCFG_Val 0x0000303A
\r
42 /*----------------------------------------------------------------------------
\r
43 Check the register settings
\r
44 *----------------------------------------------------------------------------*/
\r
45 #define CHECK_RANGE(val, min, max) ((val < min) || (val > max))
\r
46 #define CHECK_RSVD(val, mask) (val & mask)
\r
48 /* Clock Configuration -------------------------------------------------------*/
\r
49 #if (CHECK_RSVD((SCS_Val), ~0x00000030))
\r
50 #error "SCS: Invalid values of reserved bits!"
\r
53 #if (CHECK_RANGE((CLKSRCSEL_Val), 0, 2))
\r
54 #error "CLKSRCSEL: Value out of range!"
\r
57 #if (CHECK_RSVD((PLL0CFG_Val), ~0x00FF7FFF))
\r
58 #error "PLL0CFG: Invalid values of reserved bits!"
\r
61 #if (CHECK_RSVD((PLL1CFG_Val), ~0x0000007F))
\r
62 #error "PLL1CFG: Invalid values of reserved bits!"
\r
65 #if ((CCLKCFG_Val != 0) && (((CCLKCFG_Val - 1) % 2)))
\r
66 #error "CCLKCFG: CCLKSEL field does not contain only odd values or 0!"
\r
69 #if (CHECK_RSVD((USBCLKCFG_Val), ~0x0000000F))
\r
70 #error "USBCLKCFG: Invalid values of reserved bits!"
\r
73 #if (CHECK_RSVD((PCLKSEL0_Val), 0x000C0C00))
\r
74 #error "PCLKSEL0: Invalid values of reserved bits!"
\r
77 #if (CHECK_RSVD((PCLKSEL1_Val), 0x03000300))
\r
78 #error "PCLKSEL1: Invalid values of reserved bits!"
\r
81 #if (CHECK_RSVD((PCONP_Val), 0x10100821))
\r
82 #error "PCONP: Invalid values of reserved bits!"
\r
85 #if (CHECK_RSVD((CLKOUTCFG_Val), ~0x000001FF))
\r
86 #error "CLKOUTCFG: Invalid values of reserved bits!"
\r
89 /* Flash Accelerator Configuration -------------------------------------------*/
\r
90 #if (CHECK_RSVD((FLASHCFG_Val), ~0x0000F07F))
\r
91 #error "FLASHCFG: Invalid values of reserved bits!"
\r
95 /*----------------------------------------------------------------------------
\r
97 *----------------------------------------------------------------------------*/
\r
98 uint32_t XtalFrequency = 0;
\r
99 uint32_t PL160M_0Frequency = 0;
\r
100 uint32_t PL160M_1Frequency = 0;
\r
101 uint32_t PL160M_2Frequency = 0;
\r
102 uint32_t PL550Frequency = 0;
\r
103 uint32_t PL550FracFrequency = 0; //New in Falcon
\r
104 uint32_t IDIVAFrequency = 0;
\r
105 uint32_t IDIVBFrequency = 0;
\r
106 uint32_t IDIVCFrequency = 0;
\r
107 uint32_t IDIVDFrequency = 0;
\r
108 uint32_t IDIVEFrequency = 0;
\r
109 uint32_t USB1Frequency = 0;
\r
110 uint32_t M4Frequency = 0;
\r
111 uint32_t SPIFIFrequency = 0;
\r
112 uint32_t SPIFrequency = 0;
\r
113 uint32_t EnetRxFrequency = 0;
\r
114 uint32_t EnetTxFrequency = 0;
\r
115 uint32_t EXTFrequency = 0;
\r
116 uint32_t VPB1Frequency = 0;
\r
117 uint32_t VPB3Frequency = 0;
\r
118 uint32_t LCDFrequency = 0;
\r
119 uint32_t SCIFrequency = 0;
\r
120 uint32_t VADCFrequency = 0;
\r
121 uint32_t SDIOFrequency = 0;
\r
122 uint32_t SSP0Frequency = 0;
\r
123 uint32_t SSP1Frequency = 0;
\r
124 uint32_t UART0Frequency = 0;
\r
125 uint32_t UART1Frequency = 0;
\r
126 uint32_t UART2Frequency = 0;
\r
127 uint32_t UART3Frequency = 0;
\r
128 uint32_t OUTFrequency = 0;
\r
129 uint32_t AOTESTFrequency = 0;
\r
130 uint32_t ISOFrequency = 0;
\r
131 uint32_t BSRFrequency = 0;
\r
132 uint32_t CLK_TESTFrequency = 0;
\r
133 uint32_t APLLFrequency = 0;
\r
134 uint32_t SPARE0Frequency = 0;
\r
135 uint32_t SPARE1Frequency = 0;
\r
138 * Initialize the system
\r
143 * @brief Setup the microcontroller system.
\r
146 void SystemInit(void)
\r
149 // Set IRC trim if OTP is not programmed.
\r
150 if( *(uint32_t *)LPC_OTP_CTRL_BASE == 0x00FF ||
\r
151 *(uint32_t *)(LPC_OTP_CTRL_BASE+4) == 0x0000)
\r
153 LPC_CREG->IRCTRM = IRC_TRIM_VAL;
\r
156 LPC_CREG->IRCTRM = IRC_TRIM_VAL;
\r
159 // Set all GPIO as input.
\r
160 LPC_GPIO0->DIR = 0x0000;
\r
161 LPC_GPIO1->DIR = 0x0000;
\r
162 LPC_GPIO2->DIR = 0x0000;
\r
163 LPC_GPIO3->DIR = 0x0000;
\r
164 LPC_GPIO4->DIR = 0x0000;
\r
165 LPC_GPIO5->DIR = 0x0000;
\r
166 LPC_GPIO6->DIR = 0x0000;
\r
167 LPC_GPIO7->DIR = 0x0000;
\r
169 // M4 runs on IRC by default
\r
170 M4Frequency = IRC_OSC;
\r
171 XtalFrequency = XTAL_FREQ;
\r
172 EXTFrequency = EXT_FREQ;
\r
178 * @param target PLL, source clock, division
\r
181 * @brief Setup a clock
\r
183 void SetClock(CLKBASE_Type target_clk, CLKSRC_Type src_clk, CLKDIV_Type div)
\r
185 volatile uint32_t target_clk_adr;
\r
186 volatile uint8_t auto_block=TRUE;
\r
189 EnableSourceClk(src_clk);
\r
193 case(DIV1): // Divide by 1 == no division
\r
196 LPC_CGU->IDIVA_CTRL = (src_clk<<24) | (1<<2) | AUTO_BLOCK;
\r
197 IDIVAFrequency = GetClockFrequency(src_clk)/2;
\r
198 src_clk = SRC_IDIV_0; // Set new src_clk for target_clk
\r
201 LPC_CGU->IDIVB_CTRL = (src_clk<<24) | (3<<2) |AUTO_BLOCK;
\r
202 IDIVBFrequency = GetClockFrequency(src_clk)/4;
\r
203 src_clk = SRC_IDIV_1; // Set new src_clk for target_clk
\r
206 LPC_CGU->IDIVC_CTRL = (src_clk<<24) | (7<<2) |AUTO_BLOCK;
\r
207 IDIVCFrequency = GetClockFrequency(src_clk)/8;
\r
208 src_clk = SRC_IDIV_2; // Set new src_clk for target_clk
\r
211 LPC_CGU->IDIVD_CTRL = (src_clk<<24) | (15<<2) |AUTO_BLOCK;
\r
212 IDIVDFrequency = GetClockFrequency(src_clk)/16;
\r
213 src_clk = SRC_IDIV_3; // Set new src_clk for target_clk
\r
216 LPC_CGU->IDIVE_CTRL = (src_clk<<24) | (255<<2) |AUTO_BLOCK; // MAX 128? IDIV bit 2:9 = 7 bits = 127 max
\r
217 IDIVEFrequency = GetClockFrequency(src_clk)/256;
\r
218 src_clk = SRC_IDIV_4; // Set new src_clk for target_clk
\r
224 src_freq = GetClockFrequency(src_clk);
\r
228 case(BASE_OUT_CLK):
\r
230 LPC_SCU->SFSCLK_0 = 1; // function 1; CGU clk out, diable pull down, disable pull-up
\r
231 auto_block = FALSE;
\r
236 XtalFrequency = (uint32_t) src_clk; // convert target clock directly to frequency
\r
241 EnetRxFrequency = (uint32_t) src_clk; // convert target clock directly to frequency
\r
246 EnetTxFrequency = (uint32_t) src_clk; // convert target clock directly to frequency
\r
249 case(BASE_USB1_CLK):
\r
251 USB1Frequency = src_freq;
\r
256 M4Frequency = src_freq;
\r
259 case(BASE_SPIFI_CLK):
\r
261 SPIFIFrequency = src_freq;
\r
264 case(BASE_SPI_CLK):
\r
266 SPIFrequency = src_freq;
\r
269 case(BASE_PHY_RX_CLK):
\r
271 EnetRxFrequency = src_freq;
\r
274 case(BASE_PHY_TX_CLK):
\r
276 EnetTxFrequency = src_freq;
\r
279 case(BASE_VPB1_CLK):
\r
281 VPB1Frequency = src_freq;
\r
284 case(BASE_VPB3_CLK):
\r
286 VPB3Frequency = src_freq;
\r
289 case(BASE_LCD_CLK):
\r
291 LCDFrequency = src_freq;
\r
294 case (BASE_VADC_CLK) :
\r
296 VADCFrequency = src_freq;
\r
299 case(BASE_SDIO_CLK):
\r
301 SDIOFrequency = src_freq;
\r
304 case(BASE_SSP0_CLK):
\r
306 SSP0Frequency = src_freq;
\r
309 case(BASE_SSP1_CLK):
\r
311 SSP1Frequency = src_freq;
\r
314 case(BASE_UART0_CLK):
\r
316 UART0Frequency = src_freq;
\r
319 case(BASE_UART1_CLK):
\r
321 UART1Frequency = src_freq;
\r
324 case(BASE_UART2_CLK):
\r
326 UART2Frequency = src_freq;
\r
329 case(BASE_UART3_CLK):
\r
331 UART3Frequency = src_freq;
\r
334 case(BASE_AOTEST_CLK):
\r
336 AOTESTFrequency = src_freq;
\r
339 case(BASE_ISO_TCK):
\r
341 ISOFrequency = src_freq;
\r
344 case(BASE_BSR_TCK):
\r
346 BSRFrequency = src_freq;
\r
349 case(BASE_CLK_TEST):
\r
351 CLK_TESTFrequency = src_freq;
\r
354 case(BASE_APLL_CLK): //New in Falcon
\r
356 APLLFrequency = src_freq;
\r
359 case(BASE_SPARE0_CLK): //New in Falcon
\r
361 SPARE0Frequency = src_freq;
\r
364 case(BASE_SPARE1_CLK): //New in Falcon
\r
366 SPARE1Frequency = src_freq;
\r
375 target_clk_adr = (uint32_t) &LPC_CGU->IDIVA_CTRL + (target_clk-2)*4;
\r
376 *(uint32_t *)target_clk_adr = (src_clk<<24) | (auto_block<<11);
\r
381 * Get Clock Frequency
\r
383 * @param source clock
\r
384 * @return frequency
\r
386 * @brief returns the current frequency of a base clock
\r
388 uint32_t GetClockFrequency(CLKSRC_Type src_clk)
\r
396 case(SRC_ENET_RX_CLK):
\r
397 return EnetRxFrequency;
\r
398 case(SRC_ENET_TX_CLK):
\r
399 return EnetTxFrequency;
\r
401 return EXTFrequency;
\r
403 return XtalFrequency;
\r
404 case(SRC_PL550M_0):
\r
405 return PL550Frequency;
\r
406 case(SRC_PL550M_FRAC): //New in Falcon
\r
407 return PL550FracFrequency;
\r
408 case(SRC_PL160M_0):
\r
409 return PL160M_0Frequency;
\r
410 case(SRC_PL160M_1):
\r
411 return PL160M_1Frequency;
\r
412 case(SRC_PL160M_2):
\r
413 return PL160M_2Frequency;
\r
415 return IDIVAFrequency;
\r
417 return IDIVBFrequency;
\r
419 return IDIVCFrequency;
\r
421 return IDIVDFrequency;
\r
423 return IDIVEFrequency;
\r
432 * @param source clock, desired frequency
\r
435 * @brief Setup the PL160M PLL
\r
436 * If frequency equals 0 then disable PLL
\r
437 * Integer mode only (fbsel=1, direct=0)
\r
438 * Fclkout = M * Fclkin/N
\r
439 * Fcc0 = 2 * P * Fclkout = 2 * P * M * Fclkin/N
\r
440 * msel+1 = feedback-divider value M (1 to 2^15)
\r
441 * nsel+1 = pre-divider value N (1 to 2^8)
\r
442 * psel+1 = post-divider value P(x2) (1 to 2^5)
\r
444 void SetPL160M(CLKSRC_Type src_clk, uint32_t mult)
\r
446 uint32_t msel=0, nsel=0, psel=0, pval=1;
\r
448 // EnableSourceClk(src_clk);
\r
452 LPC_CGU->PLL1_CTRL |= PD_ENABLE; // Power down PLL
\r
453 DisableSourceClk(src_clk);
\r
457 EnableSourceClk(src_clk);
\r
462 PL160M_0Frequency = mult * RTC_CLK;
\r
465 PL160M_0Frequency = mult * IRC_OSC;
\r
467 case(SRC_ENET_RX_CLK):
\r
468 PL160M_0Frequency = mult * EnetRxFrequency;
\r
470 case(SRC_ENET_TX_CLK):
\r
471 PL160M_0Frequency = mult * EnetTxFrequency;
\r
474 PL160M_0Frequency = mult * EXTFrequency;
\r
477 PL160M_0Frequency = mult * XtalFrequency;
\r
480 PL160M_0Frequency = mult * IRC_OSC;
\r
484 // CCO must be in range of 156 - 320 MHz
\r
485 // Increase P if FCCO is too low.
\r
487 //psel is encoded such that 0=1, 1=2, 2=4, 3=8
\r
488 while(2*(pval)*PL160M_0Frequency < 156000000) {
\r
492 // if(2*(pval)*PL160M_0Frequency > 320000000) {
\r
493 // THIS IS OUT OF RANGE!!!
\r
494 // HOW DO WE ASSERT IN SAMPLE CODE?
\r
495 // __breakpoint(0);
\r
497 LPC_CGU->PLL1_CTRL = (src_clk<<24) | (msel<<16) | (nsel<<12) | (psel<<8) | FBSEL;
\r
498 while((LPC_CGU->PLL1_STAT&1) == 0x0); // Wait for PLL lock
\r
503 * Set PLL USB (PL550M)
\r
508 * @brief Setup the USB PLL to 480 MHz
\r
509 * If enable equals 0 then disable PLL
\r
510 * Only clock sources IRC and XTAL are valid
\r
511 * Mode1a only: Normal operating mode without post- and pre-divider
\r
512 * Fclkout = 2 * M * Fclkin
\r
513 * msel+1 = feedback-divider value M (1 to 2^15)
\r
515 void SetPLLUSB(CLKSRC_Type src_clk, uint8_t enable)
\r
519 LPC_CGU->PLL0USB_CTRL |= PD_ENABLE; // Power down PLL
\r
523 // Setup PLL550 to generate 480MHz from 12 MHz crystal
\r
524 LPC_CGU->PLL0USB_CTRL |= PD_ENABLE; // Power down PLL
\r
526 LPC_CGU->PLL0USB_NP_DIV = (98<<0) | (514<<12);
\r
527 // SELP SELI SELR MDEC
\r
528 LPC_CGU->PLL0USB_MDIV = (0xB<<17)|(0x10<<22)|(0<<28)|(0x7FFA<<0);
\r
529 LPC_CGU->PLL0USB_CTRL =(SRC_XTAL<<24) | (0x3<<2) | CLKEN;
\r
531 // Set the USB0 clock source to PLL550 (480MHz)
\r
532 LPC_CGU->BASE_USB0_CLK = (0<<0) | (1<<11) | (SRC_PL550M_0<<24);
\r
534 while((LPC_CGU->PLL0USB_STAT&1) == 0x0); // Wait for PLL lock
\r
537 PL550Frequency = 480000000UL;
\r
541 * Enable source clock pheripheral
\r
543 * @param clock source
\r
546 * @brief Enable clock specific peripherals
\r
548 void EnableSourceClk(CLKSRC_Type src_clk)
\r
552 if(src_clk == SRC_OSC32K)
\r
554 LPC_CREG->CREG0 &= ~((1<<3)|(1<<2)); // Active mode of 32 KHz osc and release reset
\r
555 LPC_CREG->CREG0 |= (1<<1)|(1<<0); // Enable 32 kHz & 1 kHz on osc32k
\r
557 if(src_clk == SRC_ENET_RX_CLK)scu_pinmux(0xC ,0 , PLAIN_ENABLE, FUNC3); // enet_rx_clk on PC_0 func 3
\r
558 if(src_clk == SRC_ENET_TX_CLK)scu_pinmux(0x1 ,19, PLAIN_ENABLE, FUNC0); // enet_tx_clk on P1_19 func 0
\r
559 if(src_clk == SRC_XTAL && (LPC_CGU->XTAL_OSC_CTRL&0x1))
\r
561 LPC_CGU->XTAL_OSC_CTRL &= ~(1<<0); // Enable Xo50M
\r
562 for(i=0;i<0xFFFF;i++);
\r
567 * Disable source clock pheripheral
\r
569 * @param clock source
\r
572 * @brief Disable clock specific peripherals
\r
574 void DisableSourceClk(CLKSRC_Type src_clk)
\r
578 if(src_clk == SRC_OSC32K)
\r
580 LPC_CREG->CREG0 &= ~((1<<1)|(1<<0)); // Disable 32 kHz & 1 kHz on osc32k
\r
581 LPC_CREG->CREG0 |= ((1<<3)|(1<<2)); // osc32k in power down and in reset mode
\r
583 if(src_clk == SRC_ENET_RX_CLK)scu_pinmux(0xC ,0 , PLAIN_ENABLE, FUNC0); // nc on PC_0 func 0
\r
584 if(src_clk == SRC_ENET_TX_CLK)scu_pinmux(0x1 ,19, PLAIN_ENABLE, FUNC2); // nc on P1_19 func 2
\r
585 if(src_clk == SRC_XTAL)
\r
587 LPC_CGU->XTAL_OSC_CTRL = (1<<0); // Disable Xo50M
\r
588 for(i=0;i<0xFFFF;i++);
\r