title: STM32F0 System Clock PLL configuration and/or temperature causing error?
body: <p>My project has started experiencing a problem in which the SysTick rate is usually, but not always set too fast. I have not changed the code that is relevant, and it seems to be temperature-related.</p>
  
  <p>I am using an STM32F072B-DISCOVERY board, with VisualGDB on Visual Studio Community 2015.</p>
  
  <p>My initialization code includes the following function:</p>
  
  <pre><code>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();
  }
  </code></pre>
  
  <p>The notes for <code>RCC_SYSCLKConfig()</code> state "If a clock source which is not yet ready is selected, the switch will occur when the clock source will be ready." Checking the PLLRDY RCC flag should identify this condition so the clock change occurs immediately, so that the clock is set immediately.</p>
  
  <p><code>SystemCoreClockUpdate()</code> is from the standard STM32 libraries (in file system_stm32f0xx.c) and recomputes values that are later used to set SysTick:</p>
  
  <pre><code>void SystemCoreClockUpdate (void)
  {
    uint32_t tmp = 0, pllmull = 0, pllsource = 0, prediv1factor = 0;
  
    /* Get SYSCLK source -------------------------------------------------------*/
    tmp = RCC-&gt;CFGR &amp; 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-&gt;CFGR &amp; RCC_CFGR_PLLMULL;
        pllsource = RCC-&gt;CFGR &amp; RCC_CFGR_PLLSRC;
        pllmull = ( pllmull &gt;&gt; 18) + 2;
  
        if (pllsource == 0x00)
        {
          /* HSI oscillator clock divided by 2 selected as PLL clock entry */
          SystemCoreClock = (HSI_VALUE &gt;&gt; 1) * pllmull;
        }
        else
        {
          prediv1factor = (RCC-&gt;CFGR2 &amp; 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-&gt;CFGR &amp; RCC_CFGR_HPRE) &gt;&gt; 4)];
    /* HCLK clock frequency */
    SystemCoreClock &gt;&gt;= tmp;  
  }
  </code></pre>
  
  <p>In the debugger, I can see where this is failing: <code>tmp = RCC-&gt;CFGR &amp; RCC_CFGR_SWS;</code>, causing the incorrect case to be selected.</p>
  
  <p>This looks relative straightforward in the disassembler:</p>
  
  <pre><code>   237:   tmp = RCC-&gt;CFGR &amp; RCC_CFGR_SWS;
  0x08003262 2A 4B                ldr r3, [pc, #168]  ; (0x800330c SystemCoreClockUpdate+192&gt;) 
  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] 
  </code></pre>
  
  <p>The RCC CFGR register has a value of 0x0010800a. The <code>RCC_CFGR_SWS</code> mask is 0x0000000c. The result of this <em>should</em> be <code>tmp</code> assigned 0x08, selecting the PLL case, with <code>SystemCoreClock</code> is set to 48000000.</p>
  
  <p>1) If I set a breakpoint on or before this statement, and step through it functions correctly, with <code>tmp</code> assigned 0x08, and the clocks are correctly set.</p>
  
  <p>2) If I set the breakpoint on the <code>switch</code> statement immediately afterwards, it usually* fails. <code>tmp</code> is assigned 0x0010800a, as if the <code>ands r3, r2</code> instruction were skipped! This causes the <code>default</code> case to be executed, and SystemCoreClock is set to 8000000, despite the chip running at 48MHz; with the fast SysTick as a result.</p>
  
  <p>3) if I comment out the <code>RCC_SYSCLKConfig()</code> call, leaving the start-up HSI clock selected, <code>tmp</code> is assigned 0x00 and everything works as expected, with the chip running at 8MHz, not the 48MHz that I want.</p>
  
  <p>4) If I leave it unplugged for a few minutes, it will work OK on the first power-up, but fail on warm resets (including debugging), or if unplugged for short durations (~15 seconds)</p>
  
  <p>5) I suspected that the PLL Initialization is affected by temperature. I haven't working on the project in over a month and my workspace is now seasonally warmer. I cooled the chip down slightly by putting a small cup of tap water on the chip. This was successful in that the program ran correctly every time! After removing the cup and warming the chip with my finger, it again failed.</p>
  
  <p>Can such a change to the System Clock configuration somehow affect the integrity of computation? Is there something different that I should be doing to ensure the clock is set up properly?</p>