]> begriffs open source - cmsis-freertos/blob - Demo/CORTEX_M4F_M0_LPC43xx_Keil/system/system_LPC43xx.c
Initial commit
[cmsis-freertos] / Demo / CORTEX_M4F_M0_LPC43xx_Keil / system / system_LPC43xx.c
1 /***********************************************************************
2  * $Id: system_LPC43xx.c 8389 2011-10-19 13:53:14Z nxp28536 $
3  *
4  * Project: LPC43xx Common
5  *
6  * Description:
7  *     CMSIS Cortex-M4 Device Peripheral Access Layer Source File
8  *     for the NXP LPC43xx Device Series 
9  *
10  ***********************************************************************
11  * Software that is described herein is for illustrative purposes only
12  * which provides customers with programming information regarding the
13  * products. This software is supplied "AS IS" without any warranties.
14  * NXP Semiconductors assumes no responsibility or liability for the
15  * use of the software, conveys no license or title under any patent,
16  * copyright, or mask work right to the product. NXP Semiconductors
17  * reserves the right to make changes in the software without
18  * notification. NXP Semiconductors also make no representation or
19  * warranty that such application will be suitable for the specified
20  * use without further testing or modification.
21  **********************************************************************/
22
23 #include <stdint.h>
24 #if defined CORE_M4
25 #include "LPC43xx.h"   
26 #endif
27
28 #ifdef CORE_M0
29 #include "LPC43xx_M0.h"                
30 #endif
31
32 #include "scu.h" 
33 #include "type.h"
34 #include "config.h"
35
36
37 /*--------------------- Clock Configuration ----------------------------------*/
38 //#define OTP
39 #define FLASH_SETUP         0
40 #define FLASHCFG_Val        0x0000303A
41
42 /*----------------------------------------------------------------------------
43   Check the register settings
44  *----------------------------------------------------------------------------*/
45 #define CHECK_RANGE(val, min, max)                ((val < min) || (val > max))
46 #define CHECK_RSVD(val, mask)                     (val & mask)
47
48 /* Clock Configuration -------------------------------------------------------*/
49 #if (CHECK_RSVD((SCS_Val),       ~0x00000030))
50    #error "SCS: Invalid values of reserved bits!"
51 #endif
52
53 #if (CHECK_RANGE((CLKSRCSEL_Val), 0, 2))
54    #error "CLKSRCSEL: Value out of range!"
55 #endif
56
57 #if (CHECK_RSVD((PLL0CFG_Val),   ~0x00FF7FFF))
58    #error "PLL0CFG: Invalid values of reserved bits!"
59 #endif
60
61 #if (CHECK_RSVD((PLL1CFG_Val),   ~0x0000007F))
62    #error "PLL1CFG: Invalid values of reserved bits!"
63 #endif
64
65 #if ((CCLKCFG_Val != 0) && (((CCLKCFG_Val - 1) % 2)))
66    #error "CCLKCFG: CCLKSEL field does not contain only odd values or 0!"
67 #endif
68
69 #if (CHECK_RSVD((USBCLKCFG_Val), ~0x0000000F))
70    #error "USBCLKCFG: Invalid values of reserved bits!"
71 #endif
72
73 #if (CHECK_RSVD((PCLKSEL0_Val),   0x000C0C00))
74    #error "PCLKSEL0: Invalid values of reserved bits!"
75 #endif
76
77 #if (CHECK_RSVD((PCLKSEL1_Val),   0x03000300))
78    #error "PCLKSEL1: Invalid values of reserved bits!"
79 #endif
80
81 #if (CHECK_RSVD((PCONP_Val),      0x10100821))
82    #error "PCONP: Invalid values of reserved bits!"
83 #endif
84
85 #if (CHECK_RSVD((CLKOUTCFG_Val), ~0x000001FF))
86    #error "CLKOUTCFG: Invalid values of reserved bits!"
87 #endif
88
89 /* Flash Accelerator Configuration -------------------------------------------*/
90 #if (CHECK_RSVD((FLASHCFG_Val), ~0x0000F07F))
91    #error "FLASHCFG: Invalid values of reserved bits!"
92 #endif
93
94
95 /*----------------------------------------------------------------------------
96   DEFINES
97  *----------------------------------------------------------------------------*/
98 uint32_t XtalFrequency = 0;                             
99 uint32_t PL160M_0Frequency = 0; 
100 uint32_t PL160M_1Frequency = 0; 
101 uint32_t PL160M_2Frequency = 0; 
102 uint32_t PL550Frequency = 0; 
103 uint32_t PL550FracFrequency = 0; //New in Falcon
104 uint32_t IDIVAFrequency = 0;
105 uint32_t IDIVBFrequency = 0;
106 uint32_t IDIVCFrequency = 0;
107 uint32_t IDIVDFrequency = 0;
108 uint32_t IDIVEFrequency = 0;
109 uint32_t USB1Frequency = 0;
110 uint32_t M4Frequency = 0;
111 uint32_t SPIFIFrequency = 0;
112 uint32_t SPIFrequency = 0;
113 uint32_t EnetRxFrequency = 0;
114 uint32_t EnetTxFrequency = 0;
115 uint32_t EXTFrequency = 0;
116 uint32_t VPB1Frequency = 0;
117 uint32_t VPB3Frequency = 0;
118 uint32_t LCDFrequency = 0;
119 uint32_t SCIFrequency = 0;
120 uint32_t VADCFrequency = 0;     
121 uint32_t SDIOFrequency = 0;
122 uint32_t SSP0Frequency = 0;
123 uint32_t SSP1Frequency = 0;
124 uint32_t UART0Frequency = 0;
125 uint32_t UART1Frequency = 0;
126 uint32_t UART2Frequency = 0;
127 uint32_t UART3Frequency = 0;
128 uint32_t OUTFrequency = 0;
129 uint32_t AOTESTFrequency = 0;
130 uint32_t ISOFrequency = 0;
131 uint32_t BSRFrequency = 0;
132 uint32_t CLK_TESTFrequency = 0;
133 uint32_t APLLFrequency = 0;   
134 uint32_t SPARE0Frequency = 0; 
135 uint32_t SPARE1Frequency = 0; 
136
137 /**
138  * Initialize the system
139  *
140  * @param  none
141  * @return none
142  *
143  * @brief  Setup the microcontroller system.
144  *         
145  */
146 void SystemInit(void)
147 {
148         // M4 runs on IRC by default
149         M4Frequency = IRC_OSC; 
150         XtalFrequency = XTAL_FREQ;
151         EXTFrequency = EXT_FREQ;
152 }
153
154 /**
155  * Set Clock
156  *
157  * @param  target PLL, source clock, division
158  * @return none
159  *
160  * @brief  Setup a clock 
161  */
162 void SetClock(CLKBASE_Type target_clk, CLKSRC_Type src_clk, CLKDIV_Type div)
163 {
164         volatile uint32_t target_clk_adr;
165         volatile uint8_t auto_block=TRUE;
166         uint32_t src_freq;
167
168         EnableSourceClk(src_clk);
169
170         switch(div)
171         {
172                 case(DIV1):                                             // Divide by 1 == no division
173                         break;
174                 case(DIV2):     
175                         LPC_CGU->IDIVA_CTRL = (src_clk<<24) | (1<<2) | AUTO_BLOCK;      
176                         IDIVAFrequency = GetClockFrequency(src_clk)/2;
177                         src_clk = SRC_IDIV_0;           // Set new src_clk for target_clk
178                         break;
179                 case(DIV4):     
180                         LPC_CGU->IDIVB_CTRL = (src_clk<<24) | (3<<2) |AUTO_BLOCK;               
181                         IDIVBFrequency = GetClockFrequency(src_clk)/4;
182                         src_clk = SRC_IDIV_1;           // Set new src_clk for target_clk
183                         break;
184                 case(DIV8):     
185                         LPC_CGU->IDIVC_CTRL = (src_clk<<24) | (7<<2) |AUTO_BLOCK;               
186                         IDIVCFrequency = GetClockFrequency(src_clk)/8;
187                         src_clk = SRC_IDIV_2;           // Set new src_clk for target_clk
188                         break;
189                 case(DIV16):    
190                         LPC_CGU->IDIVD_CTRL = (src_clk<<24) | (15<<2) |AUTO_BLOCK;              
191                         IDIVDFrequency = GetClockFrequency(src_clk)/16;
192                         src_clk = SRC_IDIV_3;           // Set new src_clk for target_clk
193                         break;
194                 case(DIV256):
195                         LPC_CGU->IDIVE_CTRL = (src_clk<<24) | (255<<2) |AUTO_BLOCK;     // MAX 128? IDIV bit 2:9 = 7 bits = 127 max
196                         IDIVEFrequency = GetClockFrequency(src_clk)/256;
197                         src_clk = SRC_IDIV_4;           // Set new src_clk for target_clk
198                         break;
199                 default:
200                         break;
201         }
202
203         src_freq = GetClockFrequency(src_clk);
204
205         switch(target_clk)
206         {
207                 case(BASE_OUT_CLK):
208                 {
209                         LPC_SCU->SFSCLK_0 = 1;                                  // function 1; CGU clk out, diable pull down, disable pull-up
210                         auto_block = FALSE;
211                         break;
212                 }
213                 case(XTAL):
214                 {
215                         XtalFrequency = (uint32_t) src_clk;             // convert target clock directly to frequency
216                         break;
217                 }
218                 case(ENET_RX):
219                 {
220                         EnetRxFrequency = (uint32_t) src_clk;   // convert target clock directly to frequency
221                         break;
222                 }
223                 case(ENET_TX):
224                 {
225                         EnetTxFrequency = (uint32_t) src_clk;   // convert target clock directly to frequency
226                         break;
227                 }
228                 case(BASE_USB1_CLK):
229                 {
230                         USB1Frequency = src_freq;
231                         break;
232                 }
233                 case(BASE_M4_CLK):
234                 {
235                         M4Frequency = src_freq;
236                         break;
237                 }
238                 case(BASE_SPIFI_CLK):
239                 {
240                         SPIFIFrequency = src_freq;
241                         break;
242                 }
243                 case(BASE_SPI_CLK):
244                 {
245                         SPIFrequency = src_freq;
246                         break;
247                 }
248                 case(BASE_PHY_RX_CLK):
249                 {
250                         EnetRxFrequency = src_freq;
251                         break;
252                 }
253                 case(BASE_PHY_TX_CLK):
254                 {
255                         EnetTxFrequency = src_freq;
256                         break;
257                 }
258                 case(BASE_VPB1_CLK):
259                 {
260                         VPB1Frequency = src_freq;
261                         break;
262                 }
263                 case(BASE_VPB3_CLK):
264                 {
265                         VPB3Frequency = src_freq;
266                         break;
267                 }
268                 case(BASE_LCD_CLK):
269                 {
270                         LCDFrequency = src_freq;
271                         break;
272                 }
273                 case (BASE_VADC_CLK) :
274                 {
275                         VADCFrequency = src_freq;
276                         break;
277                 }
278                 case(BASE_SDIO_CLK):
279                 {
280                         SDIOFrequency = src_freq;
281                         break;
282                 }
283                 case(BASE_SSP0_CLK):
284                 {
285                         SSP0Frequency = src_freq;
286                         break;
287                 }
288                 case(BASE_SSP1_CLK):
289                 {
290                         SSP1Frequency = src_freq;
291                         break;
292                 }
293                 case(BASE_UART0_CLK):
294                 {
295                         UART0Frequency = src_freq;
296                         break;
297                 }
298                 case(BASE_UART1_CLK):
299                 {
300                         UART1Frequency = src_freq;
301                         break;
302                 }
303                 case(BASE_UART2_CLK):
304                 {
305                         UART2Frequency = src_freq;
306                         break;
307                 }
308                 case(BASE_UART3_CLK):
309                 {
310                         UART3Frequency = src_freq;
311                         break;
312                 }
313                 case(BASE_AOTEST_CLK):
314                 {
315                         AOTESTFrequency = src_freq;
316                         break;
317                 }
318                 case(BASE_ISO_TCK):
319                 {
320                         ISOFrequency = src_freq;
321                         break;
322                 }
323                 case(BASE_BSR_TCK):
324                 {
325                         BSRFrequency = src_freq;
326                         break;
327                 }
328                 case(BASE_CLK_TEST):
329                 {
330                         CLK_TESTFrequency = src_freq;
331                         break;
332                 }
333                 case(BASE_APLL_CLK): //New in Falcon
334                 {
335                         APLLFrequency = src_freq;
336                         break;
337                 }
338                 case(BASE_SPARE0_CLK): //New in Falcon
339                 {
340                         SPARE0Frequency = src_freq;
341                         break;
342                 }
343                 case(BASE_SPARE1_CLK): //New in Falcon
344                 {
345                         SPARE1Frequency = src_freq;
346                         break;
347                 }
348                 default:
349                         break;
350         }
351
352         if(target_clk<200)
353         {
354                 target_clk_adr = (uint32_t) &LPC_CGU->IDIVA_CTRL + (target_clk-2)*4;    
355                 *(uint32_t *)target_clk_adr = (src_clk<<24) | (auto_block<<11); 
356         }
357 }
358
359 /**
360  * Get Clock Frequency
361  *
362  * @param  source clock
363  * @return frequency
364  *
365  * @brief  returns the current frequency of a base clock
366  */
367 uint32_t GetClockFrequency(CLKSRC_Type src_clk)
368 {
369         switch(src_clk)
370         {
371                 case(SRC_OSC32K):
372                         return RTC_CLK;
373                 case(SRC_IRC):
374                         return IRC_OSC;
375                 case(SRC_ENET_RX_CLK):
376                         return EnetRxFrequency;
377                 case(SRC_ENET_TX_CLK):
378                         return EnetTxFrequency;
379                 case(SRC_EXT_TCK):
380                         return EXTFrequency;
381                 case(SRC_XTAL):
382                         return XtalFrequency;
383                 case(SRC_PL550M_0):
384                         return PL550Frequency;
385                 case(SRC_PL550M_FRAC): //New in Falcon
386                         return PL550FracFrequency;
387                 case(SRC_PL160M_0):
388                         return PL160M_0Frequency;
389                 case(SRC_PL160M_1):
390                         return PL160M_1Frequency;
391                 case(SRC_PL160M_2):
392                         return PL160M_2Frequency;
393                 case(SRC_IDIV_0):
394                         return IDIVAFrequency;
395                 case(SRC_IDIV_1):
396                         return IDIVBFrequency;
397                 case(SRC_IDIV_2):
398                         return IDIVCFrequency;
399                 case(SRC_IDIV_3):
400                         return IDIVDFrequency;
401                 case(SRC_IDIV_4):
402                         return IDIVEFrequency;
403                 default:
404                 return 0;
405         }
406 }
407
408 /**
409  * Set PL160M
410  *
411  * @param  source clock, desired frequency 
412  * @return none
413  *
414  * @brief       Setup the PL160M PLL 
415  *                      If frequency equals 0 then disable PLL
416  *                      Integer mode only (fbsel=1, direct=0)                           
417  *                      Fclkout = M * Fclkin/N 
418  *                      Fcc0 = 2 * P * Fclkout = 2 * P * M * Fclkin/N 
419  *                      msel+1 = feedback-divider value M       (1 to 2^15)     
420  *                      nsel+1 = pre-divider value N            (1 to 2^8)      
421  *                      psel+1 = post-divider value P(x2)       (1 to 2^5)      
422  */
423 void SetPL160M(CLKSRC_Type src_clk, uint32_t mult) 
424 {
425         uint32_t msel=0, nsel=0, psel=0, pval=1;        
426
427 //      EnableSourceClk(src_clk);
428
429         if(mult==0)
430         {
431                 LPC_CGU->PLL1_CTRL |= PD_ENABLE;        // Power down PLL
432                 DisableSourceClk(src_clk);
433         }
434         else
435         {
436                 EnableSourceClk(src_clk);
437                          
438                 switch(src_clk)
439                 {
440                         case(SRC_OSC32K):
441                                 PL160M_0Frequency = mult * RTC_CLK;
442                                 break;
443                         case(SRC_IRC):
444                                 PL160M_0Frequency = mult * IRC_OSC;
445                                 break;
446                         case(SRC_ENET_RX_CLK):
447                                 PL160M_0Frequency = mult * EnetRxFrequency;
448                                 break;
449                         case(SRC_ENET_TX_CLK):
450                                 PL160M_0Frequency = mult * EnetTxFrequency;
451                                 break;
452                         case(SRC_EXT_TCK):
453                                 PL160M_0Frequency = mult * EXTFrequency;
454                                 break;
455                         case(SRC_XTAL):
456                                 PL160M_0Frequency = mult * XtalFrequency;
457                                 break;
458                         default:
459                                 PL160M_0Frequency = mult * IRC_OSC;
460                                 break;
461                 }
462         
463                 // CCO must be in range of 156 - 320 MHz
464                 // Increase P if FCCO is too low. 
465                 msel = mult-1;
466                 //psel is encoded such that 0=1, 1=2, 2=4, 3=8
467                 while(2*(pval)*PL160M_0Frequency < 156000000) {
468                         psel++; 
469                         pval*=2;
470                 }
471 //              if(2*(pval)*PL160M_0Frequency > 320000000) {
472 //                      THIS IS OUT OF RANGE!!!
473 //                      HOW DO WE ASSERT IN SAMPLE CODE?
474 //                      __breakpoint(0);
475 //              }
476                 LPC_CGU->PLL1_CTRL = (src_clk<<24) | (msel<<16) | (nsel<<12) | (psel<<8) | FBSEL;
477                 while((LPC_CGU->PLL1_STAT&1) == 0x0);           // Wait for PLL lock
478         }
479 }
480
481 /**
482  * Set PLL USB (PL550M)
483  *
484  * @param  enable
485  * @return none
486  *
487  * @brief       Setup the USB PLL to 480 MHz 
488  *                      If enable equals 0 then disable PLL
489  *                      Only clock sources IRC and XTAL are valid
490  *                      Mode1a only: Normal operating mode without post- and pre-divider                                
491  *                      Fclkout = 2 * M * Fclkin
492  *                      msel+1 = feedback-divider value M       (1 to 2^15)     
493  */
494 void SetPLLUSB(CLKSRC_Type src_clk, uint8_t enable)
495 {
496         if(!enable)
497         {
498                 LPC_CGU->PLL0USB_CTRL |= PD_ENABLE;     // Power down PLL
499         }
500         else
501         {
502                 // Setup PLL550 to generate 480MHz from 12 MHz crystal
503                 LPC_CGU->PLL0USB_CTRL |= PD_ENABLE;     // Power down PLL
504                                                         //      P                       N
505                 LPC_CGU->PLL0USB_NP_DIV = (98<<0) | (514<<12);
506                                                         //      SELP    SELI    SELR    MDEC     
507                 LPC_CGU->PLL0USB_MDIV = (0xB<<17)|(0x10<<22)|(0<<28)|(0x7FFA<<0);                                       
508                 LPC_CGU->PLL0USB_CTRL =(SRC_XTAL<<24) | (0x3<<2) | CLKEN;  
509                 
510                 // Set the USB0 clock source to PLL550 (480MHz)
511                 LPC_CGU->BASE_USB0_CLK = (0<<0) | (1<<11) | (SRC_PL550M_0<<24); 
512                         
513                 while((LPC_CGU->PLL0USB_STAT&1) == 0x0);        // Wait for PLL lock 
514         }
515
516         PL550Frequency = 480000000UL;
517 }
518
519 /**
520  * Enable source clock pheripheral
521  *
522  * @param  clock source
523  * @return none
524  *
525  * @brief       Enable clock specific peripherals
526  */
527 void EnableSourceClk(CLKSRC_Type src_clk)
528 {
529         uint32_t i=0;
530         const uint32_t PlainEnable = (0x2 << 3);        /* no pull up, no pull down (plain) */
531
532
533         if(src_clk == SRC_OSC32K)
534         {
535                 LPC_CREG->CREG0 &= ~((1<<3)|(1<<2));            // Active mode of 32 KHz osc and release reset
536                 LPC_CREG->CREG0 |= (1<<1)|(1<<0);                       // Enable 32 kHz & 1 kHz on osc32k
537         }
538         if(src_clk == SRC_ENET_RX_CLK)scu_pinmux(0xC ,0 , PlainEnable, FUNC3);  // enet_rx_clk on PC_0 func 3
539         if(src_clk == SRC_ENET_TX_CLK)scu_pinmux(0x1 ,19, PlainEnable, FUNC0);  // enet_tx_clk on P1_19 func 0
540         if(src_clk == SRC_XTAL && (LPC_CGU->XTAL_OSC_CTRL&0x1))
541         {
542                 LPC_CGU->XTAL_OSC_CTRL &= ~(1<<0);                                                              // Enable Xo50M
543                 for(i=0;i<0xFFFF;i++);
544         }
545 }
546
547 /**
548  * Disable source clock pheripheral
549  *
550  * @param  clock source
551  * @return none
552  *
553  * @brief       Disable clock specific peripherals
554  */
555 void DisableSourceClk(CLKSRC_Type src_clk)
556 {
557         uint32_t i=0;
558         const uint32_t PlainEnable = (0x2 << 3);        /* no pull up, no pull down (plain) */
559
560         if(src_clk == SRC_OSC32K)
561         {
562                 LPC_CREG->CREG0 &= ~((1<<1)|(1<<0));    // Disable 32 kHz & 1 kHz on osc32k
563                 LPC_CREG->CREG0 |= ((1<<3)|(1<<2));             // osc32k in power down and in reset mode
564         }
565         if(src_clk == SRC_ENET_RX_CLK)scu_pinmux(0xC ,0 , PlainEnable, FUNC0);  // nc on PC_0 func 0
566         if(src_clk == SRC_ENET_TX_CLK)scu_pinmux(0x1 ,19, PlainEnable, FUNC2);  // nc on P1_19 func 2
567         if(src_clk == SRC_XTAL)
568         {
569                 LPC_CGU->XTAL_OSC_CTRL = (1<<0);                // Disable Xo50M
570                 for(i=0;i<0xFFFF;i++);
571         }
572 }