我目前正在尝试使用C++编写STM32F401微控制器的引导装载程序。我已经删除了所有使用-nostartfiles
的启动文件,并自己编写了所有启动代码。我目前面临的主要问题是从25MHz的外部晶体源设置系统时钟,以使系统达到大约84MHz。我已使用STM32CubeIDE确认尝试配置的时钟设置确实是有效值。
我的主要问题是无法设置PLL就绪位以继续执行我的程序。我更改了HSE配置和PLL配置的操作顺序,但没有效果。每个外设都被构造为一个类,其中新的操作符被覆盖以返回存储器中的确切地址。RCC::EnableExternalSystemClock()
函数是我在boot_main()
条目中调用的第一个函数。下面是我现在拥有的当前时钟配置代码的一些片段:
RCC.cpp
/**
* @brief Sets the system clock to the specified TARGET_SYSTEM_CLOCK through
* the external oscillator.
*
*/
void RCC::EnableExternalSystemClock() {
size_t timeout = 0;
// Enable HSE
this->CR.bits.HSEON = 1;
while (this->CR.bits.HSERDY != 0b1 || timeout < this->HSE_TIMEOUT) {
timeout++;
}
// Enable power controller
this->APB1ENR.bits.PWREN = 1;
// Configure voltage regulator scaling
PWR &power = *new PWR();
power.SetRegulatorScale(PWR::Scale::DIV2);
// Enable flash prefetch & caches
FLASH &flash = *new FLASH();
flash.EnablePrefetchCache();
// Calculate actual system clock
constexpr auto pll_clocks =
RCC::CalculatePLLClocks(RCC::HSE_CRYSTAL_FREQ_HZ, RCC::TARGET_SYSTEM_CLOCK);
constexpr auto sys_clock = RCC::CalculateSysClock(RCC::HSE_CRYSTAL_FREQ_HZ, pll_clocks.pll_m,
pll_clocks.pll_n, pll_clocks.pll_p);
// Set APB scalers
constexpr auto lsapb2_prescaler = RCC::CalculateLSAPB2Prescaler(sys_clock);
this->CFGR.bits.HPRE = 0b000;
this->CFGR.bits.PPRE1 = lsapb2_prescaler; // calculates as 0x04
this->CFGR.bits.PPRE2 = 0b000;
// Enable system config click
this->APB2ENR.bits.SYSCFGEN = 1;
// Disable PLL
this->CR.bits.PLLON = 0;
while (this->CR.bits.PLLRDY != 0) {
// Do nothing
}
// Set PLL scalers
this->PLLCFGR.bits.PLLM = pll_clocks.pll_m; // calculates as 13
this->PLLCFGR.bits.PLLN = pll_clocks.pll_n; // calclulates as 87
this->PLLCFGR.bits.PLLP = pll_clocks.pll_p; // calculates as 0x00
this->PLLCFGR.bits.PLLQ = 4;
// Set PLL source
this->PLLCFGR.bits.PLLSRC = 1;
// Enable PLL
this->CR.bits.PLLON = 1;
while (this->CR.bits.PLLRDY == 0) { // currently stuck here
// Do nothing
}
// Set clock source
this->CFGR.bits.SW = 0b10;
while (this->CFGR.bits.SWS != 0b10) {
// Do nothing
}
}
FLASH.hpp
void FLASH::EnablePrefetchCache() {
this->ACR.bits.DCEN = 1;
this->ACR.bits.ICEN = 1;
this->ACR.bits.PRFTEN = 1;
constexpr int sys_clock = RCC::GetSystemClock(RCC::HSE_CRYSTAL_FREQ_HZ);
constexpr uint8_t latency = FLASH::CalculateFlashLatency(TARGET_SYSTEM_VOLTAGE, sys_clock);
this->ACR.bits.LATENCY = latency;
}
RCC.hpp文件可以在here中找到。
以下是STM32CubeIDE中预期系统时钟配置的示意图:
我错过了什么让系统时钟设置正确?
1条答案
按热度按时间n1bvdmb61#
您违反了PLLM和PLLN配置。参考手册RM0368. RCC部分,PLL配置寄存器(第105页):
阅读注意部分。基本上,它说PLLM时钟分频后输出必须在1 MHz-2 MHz范围内。
接下来是PLLN:
提出一个系数组合本身就是一个小数学问题。我建议的解决方案是:
此外,如果您要将MCU推到最大,则可能需要在PWR外设中启用过驱动/过驱动开关。您只需要设置缩放比例。