将系统时钟切换到 PLL 时,STM32F411CEU6 程序暂停

问题描述 投票:0回答:1

我试图通过在不使用 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 中运行良好,因此不是硬件问题。 时钟图: enter image description here 这是包含整个项目的 github 存储库

我试图找到有类似问题的人,但没有发现有人有这个确切的问题。每个人的系统时钟似乎都毫无问题地切换到 PLL。

embedded stm32 stm32f4
1个回答
0
投票

我没有像这样使用过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 写入。

© www.soinside.com 2019 - 2024. All rights reserved.