/
clock.c
141 lines (112 loc) · 2.49 KB
/
clock.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/* ___DISCLAIMER___ */
/* clock.c: PLL, CCLK, PCLK controls */
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include "config.h"
#include "clock.h"
#include "bits.h"
#include "uart.h"
void clock_disconnect() {
disconnectPLL0();
disablePLL0();
}
void clock_init() {
/* set flash access time to 5 clks (80<f<=100MHz) */
setFlashAccessTime(5);
/* setup PLL0 for 96MHz
First, disable and disconnect PLL0.
*/
clock_disconnect();
/* PLL is disabled and disconnected. setup PCLK NOW as it cannot be changed
reliably with PLL0 connected.
see:
http://ics.nxp.com/support/documents/microcontrollers/pdf/errata.lpc1754.pdf
*/
/* continue with PLL0 setup:
enable the xtal oscillator and wait for it to become stable
set the oscillator as clk source for PLL0
set PLL0 multiplier+predivider
enable PLL0
set CCLK divider
wait for PLL0 to lock
connect PLL0
done
*/
enableMainOsc();
setClkSrc(CLKSRC_MAINOSC);
setPLL0MultPrediv(CONFIG_CLK_MULT, CONFIG_CLK_PREDIV);
enablePLL0();
setCCLKDiv(CONFIG_CLK_CCLKDIV);
connectPLL0();
/* configure PLL1 for USB operation */
disconnectPLL1();
disablePLL1();
LPC_SC->PLL1CFG = 0x23;
enablePLL1();
connectPLL1();
}
void setFlashAccessTime(uint8_t clocks) {
LPC_SC->FLASHCFG=FLASHTIM(clocks);
}
void setPLL0MultPrediv(uint16_t mult, uint8_t prediv) {
LPC_SC->PLL0CFG=PLL_MULT(mult) | PLL_PREDIV(prediv);
PLL0feed();
}
void enablePLL0() {
LPC_SC->PLL0CON |= PLLE0;
PLL0feed();
}
void disablePLL0() {
LPC_SC->PLL0CON &= ~PLLE0;
PLL0feed();
}
void connectPLL0() {
while(!(LPC_SC->PLL0STAT & PLOCK0));
LPC_SC->PLL0CON |= PLLC0;
PLL0feed();
}
void disconnectPLL0() {
LPC_SC->PLL0CON &= ~PLLC0;
PLL0feed();
}
void setPLL1MultPrediv(uint16_t mult, uint8_t prediv) {
LPC_SC->PLL1CFG=PLL_MULT(mult) | PLL_PREDIV(prediv);
PLL1feed();
}
void enablePLL1() {
LPC_SC->PLL1CON |= PLLE1;
PLL1feed();
}
void disablePLL1() {
LPC_SC->PLL1CON &= ~PLLE1;
PLL1feed();
}
void connectPLL1() {
while(!(LPC_SC->PLL1STAT & PLOCK1));
LPC_SC->PLL1CON |= PLLC1;
PLL1feed();
}
void disconnectPLL1() {
LPC_SC->PLL1CON &= ~PLLC1;
PLL1feed();
}
void setCCLKDiv(uint8_t div) {
LPC_SC->CCLKCFG=CCLK_DIV(div);
}
void enableMainOsc() {
LPC_SC->SCS=OSCEN;
while(!(LPC_SC->SCS&OSCSTAT));
}
void disableMainOsc() {
LPC_SC->SCS=0;
}
void PLL0feed() {
LPC_SC->PLL0FEED=0xaa;
LPC_SC->PLL0FEED=0x55;
}
void PLL1feed() {
LPC_SC->PLL1FEED=0xaa;
LPC_SC->PLL1FEED=0x55;
}
void setClkSrc(uint8_t src) {
LPC_SC->CLKSRCSEL=src;
}