STM32F0 系统时钟 PLL 配置 and/or 温度导致错误?

STM32F0 System Clock PLL configuration and/or temperature causing error?

我的项目开始遇到 SysTick 速率通常但并不总是设置得太快的问题。相关的代码我没有改,好像是温度相关的。

我正在使用 STM32F072B-DISCOVERY 开发板,在 Visual Studio Community 2015 上使用 VisualGDB。

我的初始化代码包括以下函数:

void Setup_Init_Clocks()
{
    // Set up 48 MHz Core Clock using HSI (8Mhz) with PLL x 6
    RCC_PLLConfig(RCC_PLLSource_HSI, RCC_PLLMul_6);
    RCC_PLLCmd(ENABLE);

    // Wait for PLLRDY after enabling PLL.
    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) != SET)
    { }

    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);  // Select the PLL as clock source.
    SystemCoreClockUpdate();
}

RCC_SYSCLKConfig() 状态 "If a clock source which is not yet ready is selected, the switch will occur when the clock source will be ready." 的注释检查 PLLRDY RCC 标志应该可以识别这种情况,以便立即发生时钟变化,以便立即设置时钟。

SystemCoreClockUpdate() 来自标准 STM32 库(在文件 system_stm32f0xx.c 中)并重新计算稍后用于设置 SysTick 的值:

void SystemCoreClockUpdate (void)
{
  uint32_t tmp = 0, pllmull = 0, pllsource = 0, prediv1factor = 0;

  /* Get SYSCLK source -------------------------------------------------------*/
  tmp = RCC->CFGR & RCC_CFGR_SWS;

  switch (tmp)
  {
    case 0x00:  /* HSI used as system clock */
      SystemCoreClock = HSI_VALUE;
      break;
    case 0x04:  /* HSE used as system clock */
      SystemCoreClock = HSE_VALUE;
      break;
    case 0x08:  /* PLL used as system clock */
      /* Get PLL clock source and multiplication factor ----------------------*/
      pllmull = RCC->CFGR & RCC_CFGR_PLLMULL;
      pllsource = RCC->CFGR & RCC_CFGR_PLLSRC;
      pllmull = ( pllmull >> 18) + 2;

      if (pllsource == 0x00)
      {
        /* HSI oscillator clock divided by 2 selected as PLL clock entry */
        SystemCoreClock = (HSI_VALUE >> 1) * pllmull;
      }
      else
      {
        prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1;
        /* HSE oscillator clock selected as PREDIV1 clock entry */
        SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull; 
      }      
      break;
    default: /* HSI used as system clock */
      SystemCoreClock = HSI_VALUE;
      break;
  }
  /* Compute HCLK clock frequency ----------------*/
  /* Get HCLK prescaler */
  tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
  /* HCLK clock frequency */
  SystemCoreClock >>= tmp;  
}

在调试器中,我可以看到失败的地方:tmp = RCC->CFGR & RCC_CFGR_SWS;,导致选择了不正确的大小写。

这在反汇编程序中看起来相对简单:

   237:   tmp = RCC->CFGR & RCC_CFGR_SWS;
0x08003262 2A 4B                ldr r3, [pc, #168]  ; (0x800330c SystemCoreClockUpdate+192>) 
0x08003264 5B 68                ldr r3, [r3, #4] 
0x08003266 0C 22                movs r2, #12 
0x08003268 13 40                ands r3, r2 
0x0800326a FB 60                str r3, [r7, #12] 

RCC CFGR 寄存器的值为 0x0010800a。 RCC_CFGR_SWS 掩码是 0x0000000c。 的结果应该tmp分配0x08,选择PLL情况,SystemCoreClock设置为48000000。

1) 如果我在此语句上或之前设置一个断点,并且单步执行它会正常运行,tmp 分配 0x08,并且时钟设置正确。

2) 如果我随后立即在 switch 语句上设置断点,它通常*会失败。 tmp 被赋值为 0x0010800a,就好像 ands r3, r2 指令被跳过了一样!这导致 default 案例被执行,并且 SystemCoreClock 被设置为 8000000,尽管芯片 运行 在 48MHz;结果是快速的 SysTick。

3) 如果我注释掉 RCC_SYSCLKConfig() 调用,选择启动 HSI 时钟,tmp 被分配为 0x00,一切都按预期工作,芯片 运行在 8MHz,而不是我想要的 48MHz。

4) 如果我把它拔掉几分钟,它会在第一次通电时正常工作,但在热重置(包括调试)时会失败,或者如果拔掉插头的时间很短(~15 秒)

5) 我怀疑PLL Initialization受温度影响。我已经一个多月没有从事该项目了,我的工作区现在季节性变暖了。我通过在芯片上放一小杯自来水来稍微冷却芯片。这是成功的,因为程序 运行 每次都正确!取下杯子用手指加热芯片后,再次失败。

对系统时钟配置的这种更改会以某种方式影响计算的完整性吗?我应该做些什么来确保时钟设置正确?

你在开始之前有没有放慢闪光灯。是的,我知道你直到之后才使用更快的时钟,但也许它在倍增之前切换到 1x 的外部时钟。对闪存进行超频会导致奇怪的行为,尽管单步 may/should 仍然会导致一些奇怪的事情