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.
I am using an STM32F072B-DISCOVERY board, with VisualGDB on Visual Studio Community 2015.
My initialization code includes the following function:
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();
}
The notes for RCC_SYSCLKConfig()
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.
SystemCoreClockUpdate()
is from the standard STM32 libraries (in file system_stm32f0xx.c) and recomputes values that are later used to set 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;
}
In the debugger, I can see where this is failing: tmp = RCC->CFGR & RCC_CFGR_SWS;
, causing the incorrect case to be selected.
This looks relative straightforward in the disassembler:
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]
The RCC CFGR register has a value of 0x0010800a. The RCC_CFGR_SWS
mask is 0x0000000c. The result of this should be tmp
assigned 0x08, selecting the PLL case, with SystemCoreClock
is set to 48000000.
1) If I set a breakpoint on or before this statement, and step through it functions correctly, with tmp
assigned 0x08, and the clocks are correctly set.
2) If I set the breakpoint on the switch
statement immediately afterwards, it usually* fails. tmp
is assigned 0x0010800a, as if the ands r3, r2
instruction were skipped! This causes the default
case to be executed, and SystemCoreClock is set to 8000000, despite the chip running at 48MHz; with the fast SysTick as a result.
3) if I comment out the RCC_SYSCLKConfig()
call, leaving the start-up HSI clock selected, tmp
is assigned 0x00 and everything works as expected, with the chip running at 8MHz, not the 48MHz that I want.
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)
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.
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?