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

时间:2016-04-14 05:11:21

标签: stm32 cortex-m

我的项目已经开始遇到一个问题,其中SysTick率通常是,但并不总是设置得太快。我没有改变相关的代码,它似乎与温度有关。

我在Visual Studio Community 2015上使用STM32F072B-DISCOVERY板和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()状态的注释"如果选择了尚未就绪的时钟源,则在时钟源就绪时将进行切换。"检查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初始化受温度影响。一个多月我没有在这个项目上工作,我的工作空间现在季节性变暖了。我在芯片上放了一小杯自来水,稍微冷却了芯片。这是成功的,因为程序每次都正确运行!取下杯子并用手指加热芯片后,它再次失败。

系统时钟配置的这种改变是否会以某种方式影响计算的完整性?我是否应该采取一些不同的措施来确保正确设置时钟?

1 个答案:

答案 0 :(得分:1)

在开始之前,你是否放慢了速度?是的,我知道你之前没有使用更快的时钟,但也许它在乘以之前切换到1x的外部时钟。对闪存进行超频会导致奇怪的行为,虽然单步执行可能/应该仍然会导致一些奇怪的行为