Skip to content

Commit d4afe8d

Browse files
committed
changed pll setup to use crystal frequency as input instead of final frequency
1 parent f190ac0 commit d4afe8d

File tree

11 files changed

+103
-50
lines changed

11 files changed

+103
-50
lines changed

targets/chip/lpc1752/startup.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ void __attribute__((__constructor__(101))) __target_startup() {
2020

2121
// setup the clock to 96Mhz (in this example we are using a 12Mhz
2222
// oscillator)
23-
// (((15 + 1) * 2 * 12Mhz) / (0 + 1) = 384Mhz) / (3 + 1) = 96Mhz
24-
clock::set_main<clock::source::main, 96'000'000, 15, 0, 3>();
25-
// clock::set_main<clock::source::internal, 96'000'000, 47, 0, 3>();
23+
// ((16 * 2 * 12Mhz) / 1 = 384Mhz) / 4 = 96Mhz
24+
clock::set_main<clock::source::main, 12'000'000, 16, 1, 4>();
25+
// clock::set_main<clock::source::internal, 12'000'000, 48, 1, 4>();
2626

2727
// setup the irq handler before main is called. This
2828
// moves the vector table to ram so it can be changed

targets/chip/lpc1756/startup.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ void __attribute__((__constructor__(101))) __target_startup() {
2020

2121
// setup the clock to 96Mhz (in this example we are using a 12Mhz
2222
// oscillator)
23-
// (((15 + 1) * 2 * 12Mhz) / (0 + 1) = 384Mhz) / (3 + 1) = 96Mhz
24-
clock::set_main<clock::source::main, 96'000'000, 15, 0, 3>();
25-
// clock::set_main<clock::source::internal, 96'000'000, 47, 0, 3>();
23+
// ((16 * 2 * 12Mhz) / 1 = 384Mhz) / 4 = 96Mhz
24+
clock::set_main<clock::source::main, 12'000'000, 16, 1, 4>();
25+
// clock::set_main<clock::source::internal, 12'000'000, 48, 1, 4>();
2626

2727
// setup the irq handler before main is called. This
2828
// moves the vector table to ram so it can be changed

targets/chip/lpc1759/startup.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ void __attribute__((__constructor__(101))) __target_startup() {
1818
// setup the flash wait state to 4 + 1 CPU clocks
1919
target::io::system::flash::setup<4>();
2020

21-
// setup the clock to 120Mhz (in this example we are using a 12Mhz
21+
// setup the clock to 96Mhz (in this example we are using a 12Mhz
2222
// oscillator)
23-
// (((19 + 1) * 2 * 12Mhz) / (0 + 1) = 480Mhz) / (3 + 1) = 120Mhz
24-
clock::set_main<clock::source::main, 120'000'000, 19, 0, 3>();
25-
// clock::set_main<clock::source::internal, 96'000'000, 47, 0, 3>();
23+
// ((16 * 2 * 12Mhz) / 1 = 384Mhz) / 4 = 96Mhz
24+
clock::set_main<clock::source::main, 12'000'000, 16, 1, 4>();
25+
// clock::set_main<clock::source::internal, 12'000'000, 48, 1, 4>();
2626

2727
// setup the irq handler before main is called. This
2828
// moves the vector table to ram so it can be changed

targets/chip/lpc1788/startup.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ void __attribute__((__constructor__(101))) __target_startup() {
2222

2323
// setup the clock to 120Mhz (in this example we are using a 12Mhz
2424
// oscillator). FCCO needs to be in range 156 - 320Mhz
25-
// (((9 + 1) * 2 * 12Mhz) / (0 + 1) = 240Mhz) / (1 + 1) = 120Mhz
25+
// ((10 * 2 * 12Mhz) / 1 = 240Mhz) / 2 = 120Mhz
2626
clock::set_main<
27-
clock::source::main, 120'000'000, 9, clock::pre_divider::div_1, 1
27+
clock::source::main, 12'000'000, 10, clock::pre_divider::div_1, 2
2828
>();
2929

3030
// set the global peripheral clock divider to 1. All the

targets/chip/lpc802/io/system.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ namespace klib::lpc802::io::system {
3030

3131
public:
3232
template <clock_source Clock>
33-
static void set() {
33+
static void set_main() {
3434
// check if we have a valid clock
3535
static_assert(
3636
Clock == clock_source::mhz_9 ||
@@ -65,7 +65,7 @@ namespace klib::lpc802::io::system {
6565
}
6666

6767
template <uint32_t Trim, uint32_t ClockFreq>
68-
static void set() {
68+
static void set_main() {
6969
// check if the trim value will lock up the cpu
7070
static_assert(
7171
Trim <= (klib::exp2(18) - 1),

targets/chip/lpc802/startup.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ void __attribute__((__constructor__(101))) __target_startup() {
1414
namespace target = klib::lpc802;
1515

1616
// change the clock frequency to 15Mhz
17-
target::io::system::clock::set<target::io::system::clock::clock_source::mhz_15>();
17+
target::io::system::clock::set_main<target::io::system::clock::clock_source::mhz_15>();
1818

1919
// setup the irq handler before main is called. This
2020
// moves the vector table to ram so it can be changed

targets/chip/tmpm373/startup.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ void __attribute__((__constructor__(101))) __target_startup() {
2323
wdt::disable();
2424

2525
// enable the PLL using the internal oscillator
26-
target::io::system::clock::setup<
26+
target::io::system::clock::set_main<
2727
10'000'000,
2828
target::io::system::clock::source::internal
2929
>();

targets/core/atmel/atsam4s/system.hpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -369,16 +369,19 @@ namespace klib::core::atsam4s::io::system {
369369
*
370370
* @tparam Source
371371
* @tparam Pll
372-
* @tparam OscillatorFreq
372+
* @tparam Freq
373373
* @tparam Multiplier
374374
* @tparam Div
375375
*/
376376
template <
377-
source Source, pll Pll, uint32_t OscillatorFreq = 0,
377+
source Source, pll Pll, uint32_t Freq = 0,
378378
uint16_t Multiplier = 0, uint32_t Div = 0,
379379
prescaler Prescaler = prescaler::div_1
380380
>
381381
static void set_main() {
382+
// make sure the input is valid
383+
static_assert(Freq > 0, "Invalid frequency");
384+
382385
// disable the write protect on the PMC
383386
target::io::power_control::write_protect<false>();
384387

@@ -397,6 +400,10 @@ namespace klib::core::atsam4s::io::system {
397400

398401
// check if we need to configure a pll
399402
if constexpr (Pll != pll::none) {
403+
// make sure the pll inputs are valid
404+
static_assert(Multiplier > 0, "Invalid multiplier");
405+
static_assert(Div > 0, "Invalid divider");
406+
400407
// make sure the user did not enable a pll. slow clock is not
401408
// supported as a pll input
402409
static_assert(
@@ -416,11 +423,11 @@ namespace klib::core::atsam4s::io::system {
416423
>();
417424

418425
// notify klib what freqency we are running
419-
klib::io::clock::set(((OscillatorFreq * Multiplier) / Div) / get_divider<Prescaler>());
426+
klib::io::clock::set(((Freq * Multiplier) / Div) / get_divider<Prescaler>());
420427
}
421428
else {
422429
// notify klib what freqency we are running
423-
klib::io::clock::set(OscillatorFreq / get_divider<Prescaler>());
430+
klib::io::clock::set(Freq / get_divider<Prescaler>());
424431
}
425432

426433
// enable the write protect again

targets/core/nxp/lpc175x/system.hpp

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,23 @@ namespace klib::core::lpc175x::io::system {
212212

213213
template <source Source, uint32_t Freq, uint16_t Multiplier, uint8_t PreDivider, uint32_t Div>
214214
static void set_main() {
215+
// make sure the input is valid
216+
static_assert(Freq > 0, "Invalid frequency");
217+
static_assert(Multiplier > 0, "Invalid multiplier");
218+
static_assert(Div > 0 && Div <= 256, "Invalid divider");
219+
static_assert(PreDivider > 0, "Invalid pre-divider");
220+
221+
// calculate the fcco frequency using the oscilator and multiplier
222+
constexpr static uint32_t partial_freq = (Freq * 2 * Multiplier) / klib::exp2(static_cast<uint32_t>(PreDivider));
223+
224+
static_assert(
225+
(Multiplier == 1) || (partial_freq >= 156'000'000 && partial_freq <= 320'000'000),
226+
"Invalid Fcco output. PLL frequency needs to be between 156 and 320mhz"
227+
);
228+
229+
// calculate the final frequency
230+
constexpr static uint32_t freq = (partial_freq / Div);
231+
215232
// disconnect the main pll if it is connected.
216233
if (is_connected<pll::main>()) {
217234
// disconnect the pll
@@ -224,37 +241,46 @@ namespace klib::core::lpc175x::io::system {
224241
enable<pll::main, false>();
225242
}
226243

227-
// enable the crystal if it is not enabled
228-
if (!crystal::is_enabled()) {
229-
// enable the crystal
230-
crystal::enable<true>();
244+
// check if we need the crystal
245+
if constexpr (Source == source::main) {
246+
// enable the crystal if it is not enabled
247+
if (!crystal::is_enabled()) {
248+
// enable the crystal
249+
crystal::enable<true>();
250+
}
231251
}
232252

233253
// set the clock divider to 0
234254
SYSCON->CCLKCFG = 0;
235255

236-
// set the clock source for PLL0 to the oscillator
256+
// set the clock source for the system clock
237257
SYSCON->CLKSRCSEL = static_cast<uint32_t>(Source);
238258

239-
// setup the pll
240-
setup<pll::main>(Multiplier, PreDivider);
259+
// check if we need to setup the pll
260+
if constexpr (Multiplier > 1) {
261+
// setup the pll
262+
setup<pll::main>((Multiplier - 1), (PreDivider - 1));
241263

242-
// enable the pll after configuring it
243-
enable<pll::main, true>();
264+
// enable the pll after configuring it
265+
enable<pll::main, true>();
266+
267+
// wait until the pll is locked
268+
while (!is_locked<pll::main>()) {
269+
// do nothing
270+
}
271+
}
244272

245273
// setup the divider to get the correct cpu frequency
246-
SYSCON->CCLKCFG = Div;
274+
SYSCON->CCLKCFG = (Div - 1);
247275

248-
// wait until the pll is locked
249-
while (!is_locked<pll::main>()) {
250-
// do nothing
276+
// check if we need to connect the pll
277+
if constexpr (Multiplier > 1) {
278+
// connect the pll
279+
connect<pll::main, true>();
251280
}
252281

253-
// connect the pll
254-
connect<pll::main, true>();
255-
256282
// notify klib what freqency we are running
257-
klib::io::clock::set(Freq);
283+
klib::io::clock::set(freq);
258284
}
259285

260286
template <uint32_t ExtCrystalFreq, uint8_t PreDivider = 0x1>

targets/core/nxp/lpc178x/system.hpp

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,24 @@ namespace klib::core::lpc178x::io::system {
132132

133133
template <
134134
source Source, uint32_t Freq,
135-
uint16_t Multiplier, pre_divider PreDivider,
136-
uint8_t Div
135+
uint16_t Multiplier = 1, pre_divider PreDivider = pre_divider::div_1,
136+
uint8_t Div = 1
137137
>
138138
static void set_main() {
139+
// calculate the fcco frequency using the oscilator and multiplier
140+
constexpr static uint32_t partial_freq = (Freq * 2 * Multiplier) / klib::exp2(static_cast<uint32_t>(PreDivider));
141+
142+
// make sure the pll inputs are valid
143+
static_assert(Multiplier > 0, "Invalid multiplier");
144+
static_assert(Div > 0, "Invalid divider");
145+
static_assert(
146+
(Multiplier == 1) || (partial_freq >= 156'000'000 && partial_freq <= 320'000'000),
147+
"Invalid Fcco output. PLL frequency needs to be between 156 and 320mhz"
148+
);
149+
150+
// calculate the final frequency
151+
constexpr static uint32_t freq = (partial_freq / Div);
152+
139153
// enable the crystal if we are changing to that
140154
if constexpr (Source == source::main) {
141155
crystal::enable<true>();
@@ -148,10 +162,10 @@ namespace klib::core::lpc178x::io::system {
148162

149163
// enable/disable the boost based on the frequency
150164
// (> 100 Mhz = on)
151-
SYSCON->PBOOST = (Freq > 100'000'000) ? 0b11 : 0b00;
165+
SYSCON->PBOOST = (freq > 100'000'000) ? 0b11 : 0b00;
152166

153167
// check if we need to enable the pll
154-
if constexpr (Multiplier) {
168+
if constexpr (Multiplier > 1) {
155169
// disconnect the main pll if it is connected.
156170
if (SYSCON->CCLKSEL & (0x1 << 8)) {
157171
SYSCON->CCLKSEL &= ~(0x1 << 8);
@@ -173,7 +187,7 @@ namespace klib::core::lpc178x::io::system {
173187
SYSCON->CLKSRCSEL = static_cast<uint32_t>(Source);
174188

175189
// setup the main pll
176-
setup<pll::main>(Multiplier, PreDivider);
190+
setup<pll::main>((Multiplier - 1), PreDivider);
177191

178192
// enable the pll
179193
enable<pll::main, true>();
@@ -189,20 +203,26 @@ namespace klib::core::lpc178x::io::system {
189203
}
190204

191205
// setup the cpu clock divider
192-
SYSCON->CCLKSEL = Div & 0x1f | ((Multiplier > 0) << 8);
206+
SYSCON->CCLKSEL = (Div - 1) & 0x1f | ((Multiplier > 1) << 8);
193207

194208
// notify klib what freqency we are running
195-
klib::io::clock::set(Freq);
209+
klib::io::clock::set(freq);
196210
}
197211

198212
template <
199213
uint32_t Freq, uint16_t Multiplier,
200214
pre_divider PreDivider
201215
>
202216
static void set_usb() {
203-
static_assert((Freq % 48'000'000) == 0, "Pll frequency needs to be 48, 96 or 144Mhz");
204-
static_assert(Freq <= 144'000'000, "Maximum USB pll frequency supported is 144Mhz");
205-
static_assert(Freq >= 48'000'000, "Minumim USB pll frequency supported is 48Mhz");
217+
static_assert((48'000'000 % Freq) == 0, "Invalid crystal frequency");
218+
219+
// calculate the frequency
220+
constexpr static uint32_t freq = ((Freq * Multiplier) / klib::exp2(static_cast<uint32_t>(PreDivider)));
221+
222+
static_assert((freq % 48'000'000) == 0, "Pll frequency needs to be 48, 96 or 144Mhz");
223+
static_assert(freq <= 144'000'000, "Maximum USB pll frequency supported is 144Mhz");
224+
static_assert(freq >= 48'000'000, "Minumim USB pll frequency supported is 48Mhz");
225+
static_assert(Multiplier > 0, "Invalid multiplier");
206226

207227
// check if the crystal is stable and enabled
208228
if (!crystal::status()) {
@@ -221,7 +241,7 @@ namespace klib::core::lpc178x::io::system {
221241
}
222242

223243
// setup the second pll
224-
setup<pll::alternate>(Multiplier, PreDivider);
244+
setup<pll::alternate>(Multiplier - 1, PreDivider);
225245

226246
// enable the pll
227247
enable<pll::alternate, true>();
@@ -233,7 +253,7 @@ namespace klib::core::lpc178x::io::system {
233253

234254
// setup the correct divider for the usb and
235255
// change to the alternate pll
236-
SYSCON->USBCLKSEL = (Freq / 48'000'000) | (0x2 << 8);
256+
SYSCON->USBCLKSEL = (freq / 48'000'000) | (0x2 << 8);
237257
}
238258
};
239259

0 commit comments

Comments
 (0)