mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-27 09:40:07 +01:00
Use the high-speed external oscillator
This is required to feed the USB controller an accurate 48 MHz clock. Change-Id: If3b4490c931c18e1b917b3569ece1adec870477a
This commit is contained in:
@@ -201,12 +201,26 @@ void initClocks() {
|
||||
FLASH.ACR()->setDCEN(true);
|
||||
FLASH.ACR()->setICEN(true);
|
||||
|
||||
/* We're using the high-speed internal oscillator as a clock source. It runs
|
||||
* at a fixed 16 MHz frequency, but by piping it through the PLL we can derive
|
||||
* faster oscillations. Combining default values and a PLLQ of 4 can provide
|
||||
* us with a 96 MHz frequency for SYSCLK. */
|
||||
/* After reset, the device is using the high-speed internal oscillator (HSI)
|
||||
* as a clock source, which runs at a fixed 16 MHz frequency. The HSI is not
|
||||
* accurate enough for reliable USB operation, so we need to use the external
|
||||
* high-speed oscillator (HSE). */
|
||||
|
||||
// Enable the HSE and wait for it to be ready
|
||||
RCC.CR()->setHSEON(true);
|
||||
while(!RCC.CR()->getHSERDY()) {
|
||||
}
|
||||
|
||||
/* Given the crystal used on our device, the HSE will oscillate at 25 MHz. By
|
||||
* piping it through a phase-locked loop (PLL) we can derive other frequencies
|
||||
* for use in different parts of the system. Combining the default PLL values
|
||||
* with a PLLM of 25 and a PLLQ of 4 yields both a 96 MHz frequency for SYSCLK
|
||||
* and the required 48 MHz USB clock. */
|
||||
|
||||
// Configure the PLL ratios and use HSE as a PLL input
|
||||
RCC.PLLCFGR()->setPLLM(25);
|
||||
RCC.PLLCFGR()->setPLLQ(4);
|
||||
RCC.PLLCFGR()->setPLLSRC(RCC::PLLCFGR::PLLSRC::HSI);
|
||||
RCC.PLLCFGR()->setPLLSRC(RCC::PLLCFGR::PLLSRC::HSE);
|
||||
// 96 MHz is too fast for APB1. Divide it by two to reach 48 MHz
|
||||
RCC.CFGR()->setPPRE1(RCC::CFGR::AHBRatio::DivideBy2);
|
||||
|
||||
@@ -215,11 +229,14 @@ void initClocks() {
|
||||
while(!RCC.CR()->getPLLRDY()) {
|
||||
}
|
||||
|
||||
// Last but not least, use the PLL output as a SYSCLK source
|
||||
// Use the PLL output as a SYSCLK source
|
||||
RCC.CFGR()->setSW(RCC::CFGR::SW::PLL);
|
||||
while (RCC.CFGR()->getSWS() != RCC::CFGR::SW::PLL) {
|
||||
}
|
||||
|
||||
// Now that we don't need use it anymore, turn the HSI off
|
||||
RCC.CR()->setHSION(false);
|
||||
|
||||
// Peripheral clocks
|
||||
|
||||
// AHB1 bus
|
||||
|
||||
@@ -7,8 +7,11 @@ class RCC {
|
||||
public:
|
||||
class CR : public Register32 {
|
||||
public:
|
||||
REGS_BOOL_FIELD(PLLRDY, 25);
|
||||
REGS_BOOL_FIELD(HSION, 0);
|
||||
REGS_BOOL_FIELD(HSEON, 16);
|
||||
REGS_BOOL_FIELD(HSERDY, 17);
|
||||
REGS_BOOL_FIELD(PLLON, 24);
|
||||
REGS_BOOL_FIELD(PLLRDY, 25);
|
||||
};
|
||||
|
||||
class PLLCFGR : public Register32 {
|
||||
|
||||
Reference in New Issue
Block a user