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:
Romain Goyet
2018-01-08 11:50:54 +01:00
committed by Léa Saviot
parent 704e02f765
commit d4d4cd359b
2 changed files with 27 additions and 7 deletions

View File

@@ -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

View File

@@ -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 {