4
\$\begingroup\$

I have coded a simple timing check for my STM32F4 Discovery board.

#define IT_PER_SEC 100

int main(void)
{
   if (SysTick_Config(SystemCoreClock / IT_PER_SEC)) 
   {          
      while (1){}; // error
   }

   initGPIO();

   for(;;)
   {
   }

   return 0;
}

void SysTick_Handler(void)
{
   static uint32_t csec  = 0;
   static uint32_t ctime = 0;

   ++csec;
   if(csec == IT_PER_SEC) // every second
   {
      // every second
      GPIO_ToggleBits(GPIOD, GPIO_Pin_12);
      csec = 0;

      // clock
      ++ctime;

      if((ctime % 10) == 0) // every 10 seconds
      {
         GPIO_ToggleBits(GPIOD, GPIO_Pin_13);
      }

      if((ctime % 60) == 0)     // every minute
      {
         GPIO_ToggleBits(GPIOD, GPIO_Pin_14);
      }

      if(ctime == 3600)         // every hour
      {
         GPIO_ToggleBits(GPIOD, GPIO_Pin_15);
         ctime = 0;
      }
   }
}

This seems to be working fine. I checked it with the stopwatch app on my android phone. But after an hour and something I noticed that the LED timing was about a second in advance and after two and a half hours I'm almost at two seconds.

I guess my app is not at fault here, or is it? The SysTick should be fine as well, I suppose. So it must be my code...

The schematics are the standard schematics of the STM32F4 Discovery board. They can be found in the user manual on page 32. There, one can find an 8 MHz crystal together with the two common 20 pF capacitors.

\$\endgroup\$
  • \$\begingroup\$ Could you upload or describe the part of the schematic that shows the oscillator (crytal, ceramic resonator, RC), and make sure what type of oscillator your chip is configured to use? There are already good answers coming in pointing towards this issue... \$\endgroup\$ – zebonaut Jan 19 '13 at 12:11
  • \$\begingroup\$ The schematics are the standard schematics of the STM32F4 Discovery board. They can be found in the user manual on page 32: \$\endgroup\$ – aLu Jan 19 '13 at 12:35
  • \$\begingroup\$ Don't take it as a given that the clock on your Android phone is reliable, or that some random app is choosing to use a reliable clock source within the phone. For example, a clock which gets corrected from the network should not be used for relative timing, and in some older android versions even clocks that were not supposed to be corrected were receiving correction adjustments. Back to the STM board, in addition to mentioned clock source errors, consider the possibility of missed interrupts. \$\endgroup\$ – Chris Stratton Jun 28 '13 at 16:16
4
\$\begingroup\$

Crystals are usually much better than 50ppm accuracy ... BUT ... crystals have two resonance modes - series resonance and parallel resonance (with an impedance plot, you will see the impedance rise towards infinity at parallel resonance and fall towards zero at series resonance).

Now the importance of this is that the two resonant modes are usually a few hundred PPM apart, and only one of them will be at the marked frequency!

If you just buy an "8 MHz" crystal without paying due attention to the fine print, you may get one cut to 8 MHz in the wrong mode; and your oscillator will be several hundred PPM off tune.

(The parallel resonance is also tunable over 50ppm or more, so it is usually specified at a given load capacitance).

You'd think most professional designers would pay more attention and select the correct crystal - and you'd usually be right - but I have even seen some high-priced digital audio equipment where this mistake was made!

Or perhaps component purchasing found a "good deal" or it was simply decided that for a budget evaluation board, price was more important than timing accuracy...

But anyway my guess is that the crystal is operating in the wrong mode to produce a 300ppm frequency error.

\$\endgroup\$
  • \$\begingroup\$ +1 for a good guess at the problem, I may dig my Discovery board out later and run some tests on the crystal. It is indeed common for designers to just plonk any old crystal in without regard to drive level, loading, temperature, etc. \$\endgroup\$ – Oli Glaser Jan 20 '13 at 10:52
  • \$\begingroup\$ I'm not quite sure what I'm supposed to check/do now \$\endgroup\$ – aLu Jan 20 '13 at 19:18
  • \$\begingroup\$ Fix it somehow. Possibly : (1) use an external 8 MHz oscillator, (2) find a crystal cut to suit the oscillator (as it's running too fast, I suspect you need one tuned at series resonance) (3) use the current crystal in the correct resonator topology (my guess is, parallel resonance, i.e. with the crystal as the vertical element in a "T" network) or (4) apply a software correction, i.e. fiddle the division ratio. In approx increasing order of difficulty... \$\endgroup\$ – Brian Drummond Jan 20 '13 at 22:03
  • \$\begingroup\$ ALternatively; there appear to be 2 crystal oscillators on the board, and instructions in the user guide for selecting either one (or the 32768Hz osc). Maybe one of the other oscillators is on tune? \$\endgroup\$ – Brian Drummond Jan 20 '13 at 22:13
3
\$\begingroup\$

Systick derives from the processor clock, which in turn probably derives from an xtal (or from the internal RC oscillator?).

1 second error in 1 hour is 1 : 3600, or 277 ppm. A run-of-the-mill xtal is guaranteed to be accurate to 50 ppm, so this is unlikely to be caused by just the xtal inaccuray.

Are you sure your chip runs on the xtal? The LPC chips with which I am familiar run by default on their internal RC oscillator, which is far less accurate than an xtal.

Another culprit could be a wrong initialization, are you sure that is done correctly?

Side note: for accurate tiemkeeping 32 kHz crystals seem to be more popular, but I don't see one on a photo of an STM32F4 Discovery board. There is an empty place marked X3, maybe that is meant for such an xtal.

\$\endgroup\$
  • \$\begingroup\$ 1:86400 would be 1 second in a whole day. For one hour this would count to 278ppm. \$\endgroup\$ – aLu Jan 19 '13 at 12:13
  • \$\begingroup\$ Drat, miscalculation. I'll update my answer! \$\endgroup\$ – Wouter van Ooijen Jan 19 '13 at 12:49
  • \$\begingroup\$ I see your point. Although I don't know what could be going wrong there. Initialization is done automatically (system_stm32f4xx.c) and everything seems fine there (HSE Frequency(Hz) 8000000, SYSCLK(Hz) 168000000). \$\endgroup\$ – aLu Jan 19 '13 at 13:35
  • 1
    \$\begingroup\$ Just as an aside, I don't think 32kHz crystals are necessarily more accurate, but real-time clocks running at this low frequency use much less power and can be operated from coin cells. \$\endgroup\$ – Joe Hass Jan 19 '13 at 14:40
  • \$\begingroup\$ As another aside, one of the major technological advances of the 18th century was the invention of a clock which could keep time over a period of weeks, in varying temperature conditions, with accuracy comparable to a modern non-temperature-compensated crystal. Electronics are not necessary for good timekeeping (though they do make relatively-good timekeeping to be done cheaply!) \$\endgroup\$ – supercat Jan 20 '13 at 17:42
2
\$\begingroup\$

In the datasheet of the STM32F4 I found this, maybe it is your answer :

SysTick calibration value register

The SysTick calibration value is fixed to 18750, which gives a reference time base of 1 ms with the SysTick clock set to 18.75 MHz (HCLK/8, with HCLK set to 150 MHz).

\$\endgroup\$
  • 2
    \$\begingroup\$ I guess I'm not seeing how this answers the question - how does this explain the apparent error? \$\endgroup\$ – Chris Stratton Jun 28 '13 at 16:10
1
\$\begingroup\$

It sounds like your uC is running from the HSI oscillator - I have a Discovery F4 and I seem to recall having a little difficulty getting it to run from the external oscillator at first.

One easy way to test is to probe the output pin of the external oscillator to see if it's running.

If you have a look in your peripheral library documentation, under CMSIS, you will see the SystemInit and SetSysClock functions. IIRC, on reset the normal behaviour is to use the HSI unless defined otherwise. Make sure you have the STD_PERIPH_DRIVER defined, and check your system_stm32f4xx.c file to make sure the correct oscillator is selected. Make sure your HSE_VALUE is defined (and set to the right value) also.

Basically have a browse around the CMSIS system setup files, and the documentation in the library - I forget off the top of my head exactly what you need to set (I'm half asleep here, and very soon to be the other half...), but it's all in there somewhere (the code comments will guide you on how to set for the correct oscillator) for example, in the system_stm32f4xx file you have this comment at the top:

* 5. This file configures the system clock as follows:
  *=============================================================================
  *=============================================================================
  *        Supported STM32F4xx device revision    | Rev A
  *-----------------------------------------------------------------------------
  *        System Clock source                    | PLL (HSE)
  *-----------------------------------------------------------------------------
  *        SYSCLK(Hz)                             | 168000000
  *-----------------------------------------------------------------------------
  *        HCLK(Hz)                               | 168000000
  *-----------------------------------------------------------------------------
  *        AHB Prescaler                          | 1
  *-----------------------------------------------------------------------------
  *        APB1 Prescaler                         | 4
  *-----------------------------------------------------------------------------
  *        APB2 Prescaler                         | 2
  *-----------------------------------------------------------------------------
  *        HSE Frequency(Hz)                      | 25000000
  *-----------------------------------------------------------------------------
  *        PLL_M                                  | 25
  *-----------------------------------------------------------------------------
  *        PLL_N                                  | 336
  *-----------------------------------------------------------------------------
  *        PLL_P                                  | 2
  *-----------------------------------------------------------------------------
  *        PLL_Q                                  | 7
  *-----------------------------------------------------------------------------
  *        PLLI2S_N                               | NA
  *-----------------------------------------------------------------------------
  *        PLLI2S_R                               | NA
  *-----------------------------------------------------------------------------
  *        I2S input clock                        | NA
  *-----------------------------------------------------------------------------
  *        VDD(V)                                 | 3.3
  *-----------------------------------------------------------------------------
  *        High Performance mode                  | Enabled
  *-----------------------------------------------------------------------------
  *        Flash Latency(WS)                      | 5
  *-----------------------------------------------------------------------------
  *        Prefetch Buffer                        | OFF
  *-----------------------------------------------------------------------------
  *        Instruction cache                      | ON
  *-----------------------------------------------------------------------------
  *        Data cache                             | ON
  *-----------------------------------------------------------------------------
  *        Require 48MHz for USB OTG FS,          | Enabled
  *        SDIO and RNG clock                     |
  *----------------------------------------------------------------------------- 
\$\endgroup\$
  • \$\begingroup\$ The first seven values are identical to mine. My HSE Frequency is set to 8000000, which should be okay for the Discovery board, I guess. Then again, I'm in no way an expert in this.. \$\endgroup\$ – aLu Jan 19 '13 at 22:49
1
\$\begingroup\$

There are a couple of ways of calibrating the HSI clock to be more realistic use mains 50Hz or RTC. The ST appnote is here.

Basically count to a second both using Systick and RTC and divide in hardware using the HSITRIM bits.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.