| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
clock_17xx_40xx.c
Go to the documentation of this file.
1 /*
2 * @brief LPC17xx/40xx System and Control driver
3 *
4 * @note
5 * Copyright(C) NXP Semiconductors, 2012
6 * All rights reserved.
7 *
8 * @par
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.
22 *
23 * @par
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
29 * this code.
30 */
31
32 #include "chip.h"
33
34 /*****************************************************************************
35 * Private types/enumerations/variables
36 ****************************************************************************/
37
38 /*****************************************************************************
39 * Public types/enumerations/variables
40 ****************************************************************************/
41
42 /*****************************************************************************
43 * Private functions
44 ****************************************************************************/
45
46 /*****************************************************************************
47 * Public functions
48 ****************************************************************************/
49
50 /* Enables or connects a PLL */
51 void Chip_Clock_EnablePLL(CHIP_SYSCTL_PLL_T pllNum, uint32_t flags) {
52 uint32_t temp;
53
54 temp = LPC_SYSCTL->PLL[pllNum].PLLCON;
55 temp |= flags;
56 LPC_SYSCTL->PLL[pllNum].PLLCON = temp;
57 Chip_Clock_FeedPLL(pllNum);
58 }
59
60 /* Disables or disconnects a PLL */
61 void Chip_Clock_DisablePLL(CHIP_SYSCTL_PLL_T pllNum, uint32_t flags) {
62 uint32_t temp;
63
64 temp = LPC_SYSCTL->PLL[pllNum].PLLCON;
65 temp &= ~flags;
66 LPC_SYSCTL->PLL[pllNum].PLLCON = temp;
67 Chip_Clock_FeedPLL(pllNum);
68 }
69
70 /* Sets up a PLL */
71 void Chip_Clock_SetupPLL(CHIP_SYSCTL_PLL_T pllNum, uint32_t msel, uint32_t psel) {
72 uint32_t pllcfg;
73
74 #if defined(CHIP_LPC175X_6X)
75 /* PLL0 and PLL1 are slightly different */
76 if (pllNum == SYSCTL_MAIN_PLL) {
77 pllcfg = (msel) | (psel << 16);
78 }
79 else {
80 pllcfg = (msel) | (psel << 5);
81 }
82
83 #else
84 pllcfg = (msel) | (psel << 5);
85 #endif
86
87 LPC_SYSCTL->PLL[pllNum].PLLCFG = pllcfg;
88 Chip_Clock_FeedPLL(pllNum);
89 }
90
91 /* Enables power and clocking for a peripheral */
92 void Chip_Clock_EnablePeriphClock(CHIP_SYSCTL_CLOCK_T clk) {
93 uint32_t bs = (uint32_t) clk;
94
95 #if defined(CHIP_LPC407X_8X)
96 if (bs >= 32) {
97 LPC_SYSCTL->PCONP1 |= (1 << (bs - 32));
98 }
99 else {
100 LPC_SYSCTL->PCONP |= (1 << bs);
101 }
102 #else
103 LPC_SYSCTL->PCONP |= (1 << bs);
104 #endif
105 }
106
107 /* Disables power and clocking for a peripheral */
108 void Chip_Clock_DisablePeriphClock(CHIP_SYSCTL_CLOCK_T clk) {
109 uint32_t bs = (uint32_t) clk;
110
111 #if defined(CHIP_LPC407X_8X)
112 if (bs >= 32) {
113 LPC_SYSCTL->PCONP1 &= ~(1 << (bs - 32));
114 }
115 else {
116 LPC_SYSCTL->PCONP |= ~(1 << bs);
117 }
118 #else
119 LPC_SYSCTL->PCONP |= ~(1 << bs);
120 #endif
121 }
122
123 /* Returns power enables state for a peripheral */
124 bool Chip_Clock_IsPeripheralClockEnabled(CHIP_SYSCTL_CLOCK_T clk)
125 {
126 uint32_t bs = (uint32_t) clk;
127
128 #if defined(CHIP_LPC407X_8X)
129 if (bs >= 32) {
130 bs = LPC_SYSCTL->PCONP1 & (1 << (bs - 32));
131 }
132 else {
133 bs = LPC_SYSCTL->PCONP & (1 << bs);
134 }
135 #else
136 bs = LPC_SYSCTL->PCONP & (1 << bs);
137 #endif
138
139 return (bool) (bs != 0);
140 }
141
142 /* Sets the current CPU clock source */
143 void Chip_Clock_SetCPUClockSource(CHIP_SYSCTL_CCLKSRC_T src)
144 {
145 #if defined(CHIP_LPC175X_6X)
146 /* LPC175x/6x CPU clock source is based on PLL connect status */
147 if (src == SYSCTL_CCLKSRC_MAINPLL) {
148 /* Connect PLL0 */
149 Chip_Clock_EnablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_CONNECT);
150 }
151 else {
152 Chip_Clock_DisablePLL(SYSCTL_MAIN_PLL, SYSCTL_PLL_CONNECT);
153 }
154 #else
155 /* LPC177x/8x and 407x/8x CPU clock source is based on CCLKSEL */
156 if (src == SYSCTL_CCLKSRC_MAINPLL) {
157 /* Connect PLL0 */
158 LPC_SYSCTL->CCLKSEL |= (1 << 8);
159 }
160 else {
161 LPC_SYSCTL->CCLKSEL &= ~(1 << 8);
162 }
163 #endif
164 }
165
166 /* Returns the current CPU clock source */
167 CHIP_SYSCTL_CCLKSRC_T Chip_Clock_GetCPUClockSource(void)
168 {
169 CHIP_SYSCTL_CCLKSRC_T src;
170 #if defined(CHIP_LPC175X_6X)
171 /* LPC175x/6x CPU clock source is based on PLL connect status */
172 if (Chip_Clock_IsMainPLLConnected()) {
173 src = SYSCTL_CCLKSRC_MAINPLL;
174 }
175 else {
176 src = SYSCTL_CCLKSRC_SYSCLK;
177 }
178 #else
179 /* LPC177x/8x and 407x/8x CPU clock source is based on CCLKSEL */
180 if (LPC_SYSCTL->CCLKSEL & (1 << 8)) {
181 src = SYSCTL_CCLKSRC_MAINPLL;
182 }
183 else {
184 src = SYSCTL_CCLKSRC_SYSCLK;
185 }
186 #endif
187
188 return src;
189 }
190
191 /* Selects the CPU clock divider */
192 void Chip_Clock_SetCPUClockDiv(uint32_t div)
193 {
194 #if defined(CHIP_LPC175X_6X)
195 LPC_SYSCTL->CCLKSEL = div;
196 #else
197 uint32_t temp;
198
199 /* Save state of CPU clock source bit */
200 temp = LPC_SYSCTL->CCLKSEL & (1 << 8);
201 LPC_SYSCTL->CCLKSEL = temp | div;
202 #endif
203 }
204
205 /* Gets the CPU clock divider */
206 uint32_t Chip_Clock_GetCPUClockDiv(void)
207 {
208 #if defined(CHIP_LPC175X_6X)
209 return (LPC_SYSCTL->CCLKSEL & 0xFF) + 1;
210 #else
211 return LPC_SYSCTL->CCLKSEL & 0x1F;
212 #endif
213 }
214
215 #if !defined(CHIP_LPC175X_6X)
216 /* Selects the USB clock divider source */
217 void Chip_Clock_SetUSBClockSource(CHIP_SYSCTL_USBCLKSRC_T src)
218 {
219 uint32_t temp;
220
221 /* Mask out current source, but keep divider */
222 temp = LPC_SYSCTL->USBCLKSEL & ~(0x3 << 8);
223 LPC_SYSCTL->USBCLKSEL = temp | (((uint32_t) src) << 8);
224 }
225
226 #endif
227
228 /* Sets the USB clock divider */
229 void Chip_Clock_SetUSBClockDiv(uint32_t div)
230 {
231 uint32_t temp;
232
233 /* Mask out current divider */
234 #if defined(CHIP_LPC175X_6X)
235 temp = LPC_SYSCTL->USBCLKSEL & ~(0xF);
236 #else
237 temp = LPC_SYSCTL->USBCLKSEL & ~(0x1F);
238 #endif
239 LPC_SYSCTL->USBCLKSEL = temp | div;
240 }
241
242 /* Gets the USB clock divider */
243 uint32_t Chip_Clock_GetUSBClockDiv(void)
244 {
245 #if defined(CHIP_LPC175X_6X)
246 return (LPC_SYSCTL->USBCLKSEL & 0xF) + 1;
247 #else
248 return (LPC_SYSCTL->USBCLKSEL & 0x1F) + 1;
249 #endif
250 }
251
252 #if defined(CHIP_LPC175X_6X)
253 /* Selects a clock divider for a peripheral */
254 void Chip_Clock_SetPCLKDiv(CHIP_SYSCTL_PCLK_T clk, CHIP_SYSCTL_CLKDIV_T div)
255 {
256 uint32_t temp, bitIndex, regIndex = (uint32_t) clk;
257
258 /* Get register array index and clock index into the register */
259 bitIndex = ((regIndex % 16) * 2);
260 regIndex = regIndex / 16;
261
262 /* Mask and update register */
263 temp = LPC_SYSCTL->PCLKSEL[regIndex] & ~(0x3 << bitIndex);
264 temp |= (((uint32_t) div) << bitIndex);
265 LPC_SYSCTL->PCLKSEL[regIndex] = temp;
266 }
267
268 /* Gets a clock divider for a peripheral */
269 uint32_t Chip_Clock_GetPLCKDiv(CHIP_SYSCTL_PCLK_T clk)
270 {
271 uint32_t div = 1, bitIndex, regIndex = ((uint32_t) clk) * 2;
272
273 /* Get register array index and clock index into the register */
274 bitIndex = regIndex % 32;
275 regIndex = regIndex / 32;
276
277 /* Mask and update register */
278 div = LPC_SYSCTL->PCLKSEL[regIndex];
279 div = (div >> bitIndex) & 0x3;
280 if (div == SYSCTL_CLKDIV_4) {
281 div = 4;
282 }
283 else if (div == SYSCTL_CLKDIV_1) {
284 div = 1;
285 }
286 else if (div == SYSCTL_CLKDIV_2) {
287 div = 2;
288 }
289 else {
290 /* Special case for CAN clock divider */
291 if ((clk == SYSCTL_PCLK_CAN1) || (clk == SYSCTL_PCLK_CAN2) || (clk == SYSCTL_PCLK_ACF)) {
292 div = 6;
293 }
294 else {
295 div = 8;
296 }
297 }
298
299 return div;
300 }
301
302 #endif
303
304 /* Selects a source clock and divider rate for the CLKOUT pin */
305 void Chip_Clock_SetCLKOUTSource(CHIP_SYSCTL_CLKOUTSRC_T src,
306 uint32_t div)
307 {
308 uint32_t temp;
309
310 temp = LPC_SYSCTL->CLKOUTCFG & ~0x1FF;
311 temp |= ((uint32_t) src) | (div - 1);
312 LPC_SYSCTL->CLKOUTCFG = temp;
313 }
314
315 /* Returns the current SYSCLK clock rate */
316 uint32_t Chip_Clock_GetSYSCLKRate(void)
317 {
318 /* Determine clock input rate to SYSCLK based on input selection */
319 switch (Chip_Clock_GetMainPllSource()) {
320 case (uint32_t) SYSCTL_PLLCLKSRC_IRC:
321 return Chip_Clock_GetIntOscRate();
322
323 case (uint32_t) SYSCTL_PLLCLKSRC_MAINOSC:
324 return Chip_Clock_GetMainOscRate();
325
326 #if defined(CHIP_LPC175X_6X)
327 case (uint32_t) SYSCTL_PLLCLKSRC_RTC:
328 return Chip_Clock_GetRTCOscRate();
329 #endif
330 }
331 return 0;
332 }
333
334 /* Returns the main pll output clock rate */
335 uint32_t Chip_Clock_GetMainPllOutClockRate(void)
336 {
337 uint32_t clkhr = 0;
338
339 #if defined(CHIP_LPC175X_6X)
340 /* Only valid if enabled */
341 if (Chip_Clock_IsMainPLLEnabled()) {
342 uint32_t msel, nsel;
343
344 /* PLL0 rate is (FIN * 2 * MSEL) / NSEL, get MSEL and NSEL */
345 msel = 1 + (LPC_SYSCTL->PLL[SYSCTL_MAIN_PLL].PLLCFG & 0x7FFF);
346 nsel = 1 + ((LPC_SYSCTL->PLL[SYSCTL_MAIN_PLL].PLLCFG >> 16) & 0xFF);
347 clkhr = (Chip_Clock_GetMainPllInClockRate() * 2 * msel) / nsel;
348 }
349 #else
350 if (Chip_Clock_IsMainPLLEnabled()) {
351 uint32_t msel;
352
353 /* PLL0 rate is (FIN * MSEL) */
354 msel = 1 + (LPC_SYSCTL->PLL[SYSCTL_MAIN_PLL].PLLCFG & 0x1F);
355 clkhr = (Chip_Clock_GetMainPllInClockRate() * msel);
356 }
357 #endif
358
359 return (uint32_t) clkhr;
360
361 }
362
363 /* Get USB output clock rate */
364 uint32_t Chip_Clock_GetUSBPllOutClockRate(void)
365 {
366 uint32_t clkhr = 0;
367
368 /* Only valid if enabled */
369 if (Chip_Clock_IsUSBPLLEnabled()) {
370 uint32_t msel;
371
372 /* PLL1 input clock (FIN) is always main oscillator */
373 /* PLL1 rate is (FIN * MSEL) */
374 msel = 1 + (LPC_SYSCTL->PLL[SYSCTL_USB_PLL].PLLCFG & 0x1F);
375 clkhr = (Chip_Clock_GetUSBPllInClockRate() * msel);
376 }
377
378 return (uint32_t) clkhr;
379
380 }
381
382 /* Get the main clock rate */
383 /* On 175x/6x devices, this is the input clock to the CPU divider.
384 Additionally, on 177x/8x and 407x/8x devices, this is also the
385 input clock to the peripheral divider. */
386 uint32_t Chip_Clock_GetMainClockRate(void)
387 {
388 switch (Chip_Clock_GetCPUClockSource()) {
389 case SYSCTL_CCLKSRC_MAINPLL:
390 return Chip_Clock_GetMainPllOutClockRate();
391
392 case SYSCTL_CCLKSRC_SYSCLK:
393 return Chip_Clock_GetSYSCLKRate();
394
395 default:
396 return 0;
397 }
398 }
399
400 /* Get CCLK rate */
401 uint32_t Chip_Clock_GetSystemClockRate(void)
402 {
403 return Chip_Clock_GetMainClockRate() / Chip_Clock_GetCPUClockDiv();
404 }
405
406 /* Returns the USB clock (USB_CLK) rate */
407 uint32_t Chip_Clock_GetUSBClockRate(void)
408 {
409 uint32_t div, clkrate;
410 #if defined(CHIP_LPC175X_6X)
411 /* The USB clock rate is derived from PLL1 or PLL0 */
412 if (Chip_Clock_IsUSBPLLConnected()) {
413 /* Use PLL1 clock for USB source with divider of 1 */
414 clkrate = Chip_Clock_GetUSBPllOutClockRate();
415 div = 1;
416 }
417 else {
418 clkrate = Chip_Clock_GetMainClockRate();
419 div = Chip_Clock_GetUSBClockDiv();
420 }
421
422 #else
423 /* Get clock from source drving USB */
424 switch (Chip_Clock_GetUSBClockSource()) {
425 case SYSCTL_USBCLKSRC_SYSCLK:
426 default:
427 clkrate = Chip_Clock_GetSYSCLKRate();
428 break;
429
430 case SYSCTL_USBCLKSRC_MAINPLL:
431 clkrate = Chip_Clock_GetMainPllOutClockRate();
432 break;
433
434 case SYSCTL_USBCLKSRC_USBPLL:
435 clkrate = Chip_Clock_GetUSBPllOutClockRate();
436 break;
437 }
438
439 div = Chip_Clock_GetUSBClockDiv();
440 #endif
441
442 return clkrate / div;
443 }
444
445 #if !defined(CHIP_LPC175X_6X)
446 /* Selects the SPIFI clock divider source */
447 void Chip_Clock_SetSPIFIClockSource(CHIP_SYSCTL_SPIFICLKSRC_T src)
448 {
449 uint32_t temp;
450
451 /* Mask out current source, but keep divider */
452 temp = LPC_SYSCTL->SPIFICLKSEL & ~(0x3 << 8);
453 LPC_SYSCTL->SPIFICLKSEL = temp | (((uint32_t) src) << 8);
454 }
455
456 /* Sets the SPIFI clock divider */
457 void Chip_Clock_SetSPIFIClockDiv(uint32_t div)
458 {
459 uint32_t temp;
460
461 /* Mask out current divider */
462 temp = LPC_SYSCTL->SPIFICLKSEL & ~(0x1F);
463 LPC_SYSCTL->SPIFICLKSEL = temp | div;
464 }
465
466 /* Returns the SPIFI clock rate */
467 uint32_t Chip_Clock_GetSPIFIClockRate(void)
468 {
469 uint32_t div, clkrate;
470
471 /* Get clock from source drving USB */
472 switch (Chip_Clock_GetSPIFIClockSource()) {
473 case SYSCTL_SPIFICLKSRC_SYSCLK:
474 default:
475 clkrate = Chip_Clock_GetSYSCLKRate();
476 break;
477
478 case SYSCTL_SPIFICLKSRC_MAINPLL:
479 clkrate = Chip_Clock_GetMainPllOutClockRate();
480 break;
481
482 case SYSCTL_SPIFICLKSRC_USBPLL:
483 clkrate = Chip_Clock_GetUSBPllOutClockRate();
484 break;
485 }
486
487 div = Chip_Clock_GetSPIFIClockDiv();
488
489 return clkrate / div;
490 }
491
492 #endif
493
494 #if defined(CHIP_LPC175X_6X)
495 /* Returns the clock rate for a peripheral */
496 uint32_t Chip_Clock_GetPeripheralClockRate(CHIP_SYSCTL_PCLK_T clk) {
497 /* 175x/6x clock is derived from CPU clock with CPU divider */
498 return Chip_Clock_GetSystemClockRate() / Chip_Clock_GetPLCKDiv(clk);
499 }
500
501 #else
502 /* Returns the clock rate for all peripherals */
503 uint32_t Chip_Clock_GetPeripheralClockRate(void)
504 {
505 uint32_t clkrate = 0, div;
506
507 /* Get divider, a divider of 0 means the clock is disabled */
508 div = Chip_Clock_GetPCLKDiv();
509 if(div != 0) {
510 /* Derived from periperhal clock input and peripheral clock divider */
511 clkrate = Chip_Clock_GetMainClockRate() / div;
512 }
513
514 return clkrate;
515 }
516
517 #endif