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:
- Copy an existing system, or subsystem and make modifications until you get a desired result. I call this the copy-modify design process.
- 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:
- Instantiation: Instance the objects or variables of interest and initialize all of the fields that are required by that object.
- 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:
- Update: Here the process may capture some readings and update some local database
- Control: Here, the process may use the readings and affect some type of control algorithm.
- 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.
- 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:
- Function interfaces: A set of functions that will allow other processes or sub-processes to interact with the new module.
- 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.


Loading comments... Write a comment