Countdown timers (and counters) are used in many applications to generate an interrupt if some event does not occur within a specified time. One example is a watchdog timer, that, if firmware does not poke it in time, it will generate an interrupt. Another use is to watch for when regular pulses stop occurring.
To initiate the countdown, firmware writes the starting timer value to hardware. Exactly what that starting value should be depends on the particular application. However, in some cases the engineers do not know what a good value should be, especially if there is some variability in the event timing. This forces engineers to be generous with the starting value to allow for the longest possible period between events. But being generous could impact system performance.
When engineers use trial and error to determine the timer starting value, all they know after each test is that either the event occurred or it didn’t (that is, the timer reached zero). But if the event occurred first, there is no indication as to how close the timer was to zero. Was the starting count value too close for comfort? Or was it set so large that it could impact system performance?
Debug hooks added to the hardware will help engineers analyze the performance of countdown timers. One hook is to make the countdown timer stop when the event occurs and leave its value untouched. Firmware can then read this value and know how far the count got before the event occurred.
For example, suppose a starting timeout is set for 10ms and the firmware is written to collect lots of samples during the course of normal operation. If that collection of samples indicates that a good event always occurs in less than 2ms, then the starting value could be set to 3ms to enable firmware to detect and respond sooner to bad cases.
- Best Practice: Design each countdown timer (counter) to retain its count when an event occurs and allow firmware to read it, until firmware writes a new value or the counting is started again.
In some implementations, a countdown timer is used to make sure an event keeps occurring on a regular basis. As long as the event keeps occurring, the timer will reload the starting value and count down again. When the event stops occurring, then the timer will eventually count down to zero and generate an interrupt. In this case, firmware cannot read the timer register to get the ending value because it keeps reloading and is always counting down, making it difficult to analyze how close the starting value is.
This can be solved by adding a separate register that is loaded with the value of the timer register at the time the event occurs. Even though this timer value may change for every occurrence of the event, the value that it holds is what the timer reached when the event last occurred. Firmware could then sample the register several times to see what typical values are.
- Best Practice: Save a copy of the timer (counter) register value to a separate register each time an event occurs.
While this discussion focused on countdown timers and counters, these same techniques can be used with countup timers and counters. These are simple, non-intrusive, and light-weight additions to the design of the block, but they provide powerful data collection capabilities that help firmware engineers make informed decisions about the initial timer values to choose.
Counting down until the next issue…