我试图通过在不使用 HAL 的情况下调整 PLL 时钟来在 STM32F411CEU6 板 (96 MHZ) 上实现高时钟速度。我已将 PLL 时钟源设置为 HSE (25 MHz)。每当我的调试器到达此行时,我的代码就会停止:
setBits(RCC->CFGR, RCC_CFGR_SW, RCC_CFGR_SW_PLL);
halt((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
我不明白为什么。我已将闪存延迟设置为绝对最大值,希望它会有所帮助,因为当我将其设置为 3WS(>90 MHz,3.3V)时它不起作用。
实施:
inline void spin (volatile u32 pCount)
{
while (pCount--) asm("nop");
}
#define halt(cond) while (cond) { spin(1); }
#define setBits(x, msk, v) x = ((x) & ~((u32)(msk))) | (u32)(v)
#define clearBits(x, msk) x = ((x) & ~(u32)(msk))
void fhInit()
{
fhInitPower();
fhMspInit();
fhHseInit();
fhPllInit();
fhCpuClockInit();
systickInit();
}
void fhMspInit()
{
setBits(FLASH->ACR, FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_PRFTEN | FLASH_ACR_LATENCY, FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_PRFTEN | FLASH_ACR_LATENCY_7WS);
}
void fhHseInit()
{
setBits(RCC->CR, RCC_CR_HSEON, RCC_CR_HSEON);
halt(RCC->CR & RCC_CR_HSERDY == 0);
}
void fhPllDisable()
{
setBits(RCC->CR, RCC_CR_PLLON, 0);
halt(RCC->CR & RCC_CR_PLLRDY);
}
void fhPllEnable()
{
setBits(RCC->CR, RCC_CR_PLLON, 1);
halt(RCC->CR & RCC_CR_PLLRDY == 0);
}
void fhPllInit()
{
fhPllDisable();
auto m = 25;
auto n = 192;
auto p = 2;
auto q = 4;
auto pllReg = RCC_PLLCFGR_PLLSRC_HSE;
pllReg |= m << RCC_PLLCFGR_PLLM_Pos;
pllReg |= n << RCC_PLLCFGR_PLLN_Pos;
pllReg |= (p >> 1) - 1 << RCC_PLLCFGR_PLLP_Pos;
pllReg |= q << RCC_PLLCFGR_PLLQ_Pos;
setBits(RCC->PLLCFGR, RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM | RCC_PLLCFGR_PLLN | RCC_PLLCFGR_PLLP | RCC_PLLCFGR_PLLQ, pllReg);
fhPllEnable();
}
void fhInitPower()
{
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
setBits(PWR->CR, PWR_CR_VOS, 0b11 << PWR_CR_VOS_Pos);
}
void fhUpdateCoreClock()
{
u32 pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
u32 pllvco = (uint64_t)HSE_VALUE * (uint64_t)((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> RCC_PLLCFGR_PLLN_Pos) / (uint64_t)pllm;
u32 pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >> RCC_PLLCFGR_PLLP_Pos) + 1U) * 2U;
u32 sysCfkFreq = pllvco / pllp;
SystemCoreClock = sysCfkFreq >> AHBPrescTable[(RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos];
}
void fhCpuClockInit()
{
fhPllEnable();
setBits(RCC->CFGR, RCC_CFGR_PPRE1 | RCC_CFGR_PPRE2 | RCC_CFGR_HPRE, RCC_CFGR_PPRE2_DIV1 | RCC_CFGR_PPRE1_DIV2 | RCC_CFGR_HPRE_DIV1);
setBits(RCC->CFGR, RCC_CFGR_SW, RCC_CFGR_SW_PLL);
halt((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);
fhUpdateCoreClock();
}
使用 HAL 时,此时钟配置在 Cube IDE 中运行良好,因此不是硬件问题。 时钟图: 这是包含整个项目的 github 存储库
我试图找到有类似问题的人,但没有发现有人有这个确切的问题。每个人的系统时钟似乎都毫无问题地切换到 PLL。
我没有像这样使用过F411裸机,我通常让cube为我生成时钟配置,然后从那里开始。 (因为为什么要这样浪费时间?)
但我怀疑你不能一次性完全重写时钟复用。
setBits(RCC->CFGR, RCC_CFGR_PPRE1 | RCC_CFGR_PPRE2 | RCC_CFGR_HPRE, RCC_CFGR_PPRE2_DIV1 | RCC_CFGR_PPRE1_DIV2 | RCC_CFGR_HPRE_DIV1);
setBits(RCC->CFGR, RCC_CFGR_SW, RCC_CFGR_SW_PLL);
还需要担心一些同步问题,因为并非所有时钟多路复用器都会立即切换。
用户手册中有很多注意事项:
软件必须正确设置这些位,以免在此域上超过 100 MHz。 时钟在 1 到 16 个 AHB 周期后使用新的预分频器因子进行分频 PPRE2 写入。