System ticks - Embedded.com

System ticks

Many deeply embedded systems can benefit from using a general system tick timer. In the last article, “Soft timers in object-oriented C” (Embedded.com, January 2013), we introduced a notion of a hard timer that generates an update count once per system interval. This interval can be a millisecond, 10 milliseconds, or even a second.

This time I'll discuss the system tick timer, using the ARM M3 Cortex microprocessor as the example. Even though we shall use the ARM SYSTICK timer and the ARM M3 Cortex as the example, the code I present here can be readily repurposed for use with any general purpose timer or microprocessor core.

First steps for the SYSTICK timer
The SYSTICK timer is part of the ARM Cortex SCS (System Control Space). As many of you who work with the ARM processors know, there are a lot of peripheral flavors for the ARM Cortex silicon. However, you can be assured that the SYSTICK timer will always be present on any ARM Cortex implementation. It's for this reason that I've chosen to use the ARM Cortex SYSTICK timer as an example of the system tick timer.

For those of you using an RTOS (real-time operating system), your OS package may already exploit the SYSTICK timer. If you're in this category, you'll need to use one of the dedicated hardware timers to implement your version of the SYSTICK timer service instead.

The ARM Cortex SYSTICK timer uses either the HCLK (ARM system clock) or the HCLK/8 as the main clock source. This selection can be done by programming the SYSTICK Control and Status register (address = 0xE000E010) in the ARM Cortex SCS. More information on how to program the ARM SYSTICK timer can be found here.

Design process
The firmware design process for the system tick subsystem can be readily generalized for any subsystem or project. I'm including this process here because I've found that this process to be very effective in getting me to think when I'm staring at a blank screen.

In my travels as an embedded systems engineer, I've found that there are really only two design styles currently in widespread use:

  1. Copy an existing system, or subsystem and make modifications until you get a desired result. I call this the copy-modify design process .
  2. Create an approach with top-down design documents, get everything to work on paper, then start implementation of the highest-risk elements as part of the design prototype. I call this style the create-prototype-modify process .

In general, I've found that a lot of engineers favor the copy-modify approach. The advantage of this approach is that you can really get a decent result extremely fast. This is one of the reasons why all of those prototyping boards and developers kits are very popular. These systems leverage our affinity for the copy-modify process.

The more formal approach, which is the top down, getting everything on paper is useful if you're heading into extreme, uncharted territory. Many times, we're confronted with some technology that we're unfamiliar with, or are just heading into really unknown areas. In this case, it's extremely helpful to make sure we get a lot of the big issues worked out ahead of time. The danger of using this method is one can get really bogged down with the details.

The process I favor is a mix of both approaches. In general, I map out what I wish to do using a document editor such as Microsoft Word. Many times (especially when on a deadline), I'll just start the top-down by generating some thoughts in a C header file.

Patterns or recurring themes
So, let's start with the top down. In all embedded systems and subsystems, there are really three things that define the system:

1. Setup and initialization
2. Process
3. Interface

Setup and Initialization: Every subsystem requires a setup and initialization sequence of steps or sub-process. In general, the type of setup that is required consists of two separate steps, done in the following order:

  1. Instantiation: Instance the objects or variables of interest and initialize all of the fields that are required by that object.
  2. Setup: Take any of the instances we've created and bind them to the hardware and other processes within the system.

Process: This is where all of the action for the system or subsystem takes place. In general, the process is that thing that uses a set of variables, functions, and other services to fulfill a specific role within the system. The types of process actions can include, but may not be limited to:

  1. Update: Here the process may capture some readings and update some local database
  2. Control: Here, the process may use the readings and affect some type of control algorithm.
  3. Teardown: In some cases, a process needs to terminate. We include a teardown process just for the case where this is needed. Not all processes require a termination sub-process.
  4. Signaling: This may be the set of routines which will communicate information to the outside world via some protocol, LEDS or maybe some alarm mechanism.

Interface: The interface represents the method where other sections of the code can get or set variables from the subsystem or system. The interface can include any of the following:

  1. Function interfaces: A set of functions that will allow other processes or sub-processes to interact with the new module.
  2. Variable interfaces: A set of global variables that allow one to capture information in real time for use in other processes. One needs to use this one with discretion and be very careful.

To download the full code listings in this article, click here. First steps for the SYSTICK timer
So, now that we have defined some approaches on how to make our system tick timer counter. How do we get started? In general, the method of choice for me is to first create the header file. This file helps me to focus on what I wish for the timer to do and what various interfaces I'll be creating for the timer. Listing 1 shows an example of the header file I created for the SYSTICK timer module.

#ifndef __SYSTICK_H    #define __SYSTICK_H/****************************************************************************//*    FILE: sysTick.h                                                       *//*                                                                          *//*    These files contain the interfaces for the ARM SYSTICK system         *//*    peripheral.                                                           *//*                                                                          *//*      BY:   Ken Wada                                                      *//*            27-January-2013                                               *//*                                                                          *//****************************************************************************/    #ifdef  __cplusplus      extern  "C" {    #endif      void  MySysTick_Configuration         (const unsigned long FsysTick);      long  sysTick_capture                 (void);      unsigned long SysTick_GetReload       (void);      unsigned long SysTick_GetUpCountValue (void);    #ifdef  __cplusplus      }    #endif#endif

Listing 1: The SYSTICK system timer header file.

In this listing, I've included three interfaces and an initialization function. The initialization function, MySysTick_Configuration (const unsigned long FsysTick) will setup the sysTick timer interrupt and any globals that are required by the interrupt service. The sysTick_capture() , SysTick_GetReload() , and SysTick_GetUpCountValue() are the generic interfaces that allow one to get the various systick counts and control settings.

Initialization: Listing 2 shows the implementation of the SYSTICK timer initialization. In this case, only the interrupt service is initialized. I have chosen to use the ANSI C initialization for the counter variables. If you have a compiler or toolkit that does not support this type of initialization, it's a good idea to include the variable initialization here.

#define   __MYSYSTICK_CONFIGURATION_C/****************************************************************************//*    FILE: MySysTick_Configuration.c                                       *//*                                                                          *//*    These files contain the methods and attributes for using ARM Cortex   *//*    sysTick interface.                                                    *//*                                                                          *//*    BY:   Ken Wada                                                        *//*          27-January-2013                                                 *//****************************************************************************/#include  "stm32f10x_lib.h"#include  "sysTick.h"/****************************************************************************//* Function Name  : MySysTick_Configuration                                 *//* Description    : Configures sysTick to interrupt at FsysTick frequency   *//* Input          : unsigned long FsysTick = timer interrupt frequency in Herz    *//* Output         : None                                                    *//* Return         : None                                                    *//****************************************************************************/void MySysTick_Configuration (const unsigned long FsysTick){    RCC_ClocksTypeDef rcc;    /* Select AHB clock(HCLK) as SysTick clock source */    SysTick_CLKSourceConfig (SysTick_CLKSource_HCLK);    /* Set SysTick Priority to 3 */    NVIC_SystemHandlerPriorityConfig(SystemHandler_SysTick, 3, 0);    RCC_GetClocksFreq (&rcc);    SysTick_SetReload (rcc.HCLK_Frequency / FsysTick);    /* Enable the SysTick Interrupt */    SysTick_ITConfig(ENABLE);    //enable systick counter    SysTick_CounterCmd(SysTick_Counter_Enable);}

Listing 2: The SYSTICK timer initialization for the ARM Cortex processor.

Interfaces: Listing 3 shows the interfaces for the SYSTICK timer service. Here, we show how to “abstract” the systick timer into a set of function calls. Of course, we could have easily accessed the SYSTICK object directly using the ST-micro access calls. However, what if we do another project that uses the NXP ARM Cortex processor and not the ST-micro? In this way, we can get away with using this library and simply redefine the interface. This allows us to retain the “investment” in the other modules that require the use of the SYSTICK interface with a different silicon implementation.

#define __SYSTICK_INTERFACE_C/****************************************************************************//*    FILE: sysTick_interface.c                                             *//*                                                                          *//*    These files contain the methods and attributes for using ARM Cortex   *//*    sysTick interface.                                                    *//*                                                                          *//*    BY:   Ken Wada                                                        *//*          27-January-2013                                                 *//****************************************************************************/#include  "stm32f10x_systick.h"#include  "tm32f10x_lib.h"#include  "sysTick.h"/****************************************************************************//*                            CODE STARTS HERE                              *//****************************************************************************/long sysTick_capture (void){    return ((long)SysTick->VAL);}unsigned long SysTick_GetReload (void){    return (SysTick->LOAD & 0x00FFFFFF);}unsigned long SysTick_GetUpCountValue (void){    unsigned long my_value  = (SysTick->VAL  & 0x00FFFFFF);    return (((SysTick->LOAD & 0x00FFFFFF) + 1) - my_value);}

Listing 3: A set of interfaces for the SYSTICK timer service

Process: In the SYSTICK handler, the process is the interrupt service. Listing 4 shows the code to implement the core SYSTICK interrupt service routine. In our case, the SysTickHandler() function is defined as a global in an assembly file. In this case, the file defines all of the interrupt vectors for the ARM Cortex processor. The process updates three global variables. These variables are:

1. SysTick_1ms , this counter updates once per millisecond
2. SysTick_10ms , this counter updates or counts once per 10 milliseconds
3. SysTick_1sec , this counter is the 1 second global system uptime clock.

Notice that there is no interrupt keyword being used here. This is because the ARM Cortex has hardware that does the context-switch, which in turn saves the processor state upon entry into the service. The hardware also restores the context when the service returns.

#define  __SYSTICKHANDLER_C/****************************************************************************//*    SysTickHandler.c                                                      *//*                                                                          *//*    This is the actual interrupt service routine for the ARM Cortex       *//*    sysTick timer service. The toolchain has predefined the function      *//*    void SysTickHandler (void); in the global namespace as an interrupt   *//*    vector.                                                               *//*                                                                          *//*    BY:   Ken Wada                                                        *//*          27-January-2013                                                 *//*                                                                          *//****************************************************************************/volatile unsigned long  SysTick_1ms;volatile unsigned long  SysTick_10ms;volatile unsigned long  SysTick_1sec;#define _TIC_10     10#define _TIC_100    100/****************************************************************************//*                            CODE STARTS HERE                              *//****************************************************************************/void SysTickHandler(void){    static int _prescaler_10ms  = _TIC_10;    static int _prescaler_sec   = _TIC_100;    ++SysTick_1ms;    --_prescaler_10ms;    if (_prescaler_10ms<=0)    {      _prescaler_10ms = _TIC_10;      ++SysTick_10ms;      --_prescaler_sec;	  if(_prescaler_sec<=0)	  {        _prescaler_sec  = _TIC_100;		  ++SysTick_1sec;	  }    }}

Listing 4: The SYSTICK interrupt service routine.
Examples
Soft timer: In the last article, one of the interfaces I mentioned is the interface to acquire a system clock tick counter for the soft timer. Listing 5 shows the code modified to use the SYSTICK timer service counter. In this example, I use the 1 millisecond update counter. Also, I've commented out the code I showed you in the last article so you can see how the new interface works.

#define __SYSRETRIEVE_CLOCK_C/****************************************************************************//*    FILE: sysRetrieveClock.c                                              *//*                                                                          *//*    A general purpose C/C++ timer object                                  *//*                                                                          *//*    BY:   Ken Wada                                                        *//*          Aurora Networks Inc.                                            *//*          12-January-2010                                                 *//*                                                                          *//****************************************************************************/#include  "hgptimer.h"//extern volatile unsigned long my_system_tick;extern volatile unsigned long  SysTick_1ms;/****************************************************************************//*                            CODE STARTS HERE                              *//****************************************************************************/unsigned long sysRetrieveClock (void){//    return (my_system_tick);    return (SysTick_1ms);}

Listing 5: An example of how to use the 1 millisecond counter.

One can also get a micro-seconds elapsed count using the SYSTICK interface. Doing this requires one of the interface functions I mentioned earlier in this article. The interface function is:

Retrieving the elapsed microseconds: Many times, a small amount of delay is required in order to synchronize some other process. Usually this can be anything from a small amount of delay required to allow an analog-to-digital converter (ADC) reading to settle or to add some latency to a bit-bang interface. Many times, this delay is implemented via some code as follows:

void sw_delay (int count){    while (count>0)    {      --count;    }}

There are some issues with this type of delay, some of which are:

  1. The delay can vary from call to call based on interrupts and on some processors cache and pipeline variances.
  2. The count parameter needs to be varied based on the processor timing and system clock settings.

Now, wouldn't it be nice to have a method that can determine whether a certain number of microseconds have elapsed? Yes, this can be done using the SYSTICK service with its associated interfaces. How to do this is shown in Listing 6 . Notice, in this listing, there is a do-while loop. This is to allow a capture of the millisecond counter in conjunction of reading the microsecond's clock tick on the SYSTICK hardware. This method can be readily generalized to any timer resource that uses a hardware counter to count the ticks between interrupts.

#define __SYSRETRIEVE_USEC_C/****************************************************************************//*    FILE: sysRetrieve_usec.c                                              *//*                                                                          *//*    Read the ARM Cortex-M3 sysTick resource to obtain a 32-bit usec       *//*    count value                                                           *//*                                                                          *//*      BY:   Ken Wada                                                      *//*            27-January-2013                                               *//*                                                                          *//****************************************************************************/#include  "stm32f10x_lib.h"#include  "sysTick.h"#include  "gptimer.h"extern  volatile u32  SysTick_1ms;/****************************************************************************//*                            CODE STARTS HERE                              *//****************************************************************************/unsigned long sysRetrieve_usec (void){    unsigned long tics_per_usec;    unsigned long usec;    unsigned long my_upCountValue;    unsigned long my_msTIC;    RCC_ClocksTypeDef rcc;    do  {      my_msTIC        = SysTick_1ms;      my_upCountValue = SysTick_GetUpCountValue();    } while (my_msTIC != SysTick_1ms);    RCC_GetClocksFreq (&rcc);    tics_per_usec = rcc.HCLK_Frequency / 1000000;    usec  = (my_msTIC * 1000) + ( my_upCountValue / tics_per_usec);    return (usec);}

Listing 6: How to use the SYSTICK process and interface to capture the number of elapsed microseconds.

Keeping time
In this how to article, I talk briefly about how I design and develop a simple system tick timer interrupt service. Also, I briefly mention the various design methods I use on a typical project. The usual design methods include the copy-modify approach, which is very quick in prototyping. Also, I mention the top-down approach, which allows me to identify risks in the overall approach and to quickly pinpoint parts that I may wish to quickly prototype to help with mitigating the risks.

The three parts to systems and sub-systems architecture is also discussed and is shown using the SYSTICK service as the primary example of how this is implemented. The general approach here is to identify recurring themes and patterns and to build these into a set of functions and interfaces which will be used for the implementations of these patterns. Of course, much of what I present here can be readily ported to any processor and or timer architecture. I have not seen many systems that couldn't benefit from using a system tick timer.

Also, to those of you who already use a real-time operating system, the SYSTICK is already incorporated as a primary feature of the OS. Therefore, you'll need to port these ideas using another timer on your specific application.

So, how do you keep time in your application?

Ken Wada is president and owner of Aurium Technologies, an independent product design and consulting firm in California's Silicon Valley. Ken has over 25 years of experience architecting and designing high-tech products and systems, including the FASTRAK vehicle-sensing system for toll roads and bridges. His expertise includes industrial automation, biotechnology, and high-speed optical networks. Ken holds four patents. You may reach him at .

To download the full code listings in this article, click here.

4 thoughts on “System ticks

  1. “Hi Ken wada,nnThank you very much for your tutorial.nnI'm just newbie to ARM,nwhen I read your article , I don't understand some point, Please help me explain.nnFirst, at Listing2. SysTick_SetReload (rcc.HCLK_Frequency / FsysTick);n If HCLK_Fre

    Log in to Reply
  2. “Hello Toinhatminh;nYes, you are correct on both counts.nnAs to the reload; page 8-10 of the ARM Cortex M3 Technical Reference Manual states that the SYSTICK reload is a 24-bit field in a 32-bit register. The upper 8-bits are reserved.nnIn general, it

    Log in to Reply
  3. “You can download the ARM Cortex M3 technical reference manual here:nnhttp://infocenter.arm.com/help/topic/com.arm.doc.ddi0337e/DDI0337E_cortex_m3_r1p1_trm.pdfnnn”

    Log in to Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.