ARM processors provide several different timer modes that allow developers to configure timers for different use cases. The timer mode determines how the timer counts, triggers interrupts, and more. The main timer modes in ARM are:
- Free-Running Mode
- Periodic Mode
- One-Shot Mode
Free-Running Mode
In free-running mode, the timer continuously counts up or down from an initial value at a fixed rate. The counter automatically resets to the initial value when it reaches the maximum or minimum value. Interrupts can be triggered when the counter reaches a preset value. Free-running mode is useful for measuring time durations in applications that need accurate timekeeping.
To configure a timer in free-running mode:
- Load the initial counter value into the timer load register.
- Program the timer interval into the timer prescale register to set the tick rate.
- Set the appropriate mode control bits in the timer control register to enable free-running mode.
- Enable the timer by setting the enable bit in the timer control register.
- The counter will now start incrementing or decrementing at each tick based on the prescale value.
- Optional: Program the match register value(s) if interrupts are needed when the counter reaches a certain value.
In this mode, the timer keeps running indefinitely once enabled. The counter value can be read to determine elapsed time. Interrupts provide a way to trigger events after certain time durations.
Periodic Mode
In periodic mode, the timer counts from an initial value to a specified terminal value, then reloads the initial value and repeats the count. This creates a periodic timer that triggers an interrupt and restarts at regular intervals. Periodic mode is useful for generating periodic interrupts at a fixed frequency.
To configure periodic mode:
- Load the start counter value into the timer load register.
- Load the end counter value into the timer match register.
- Configure the control register to enable periodic mode.
- Enable the timer and interrupt generation on match.
When the counter reaches the match value, it will reset to the initial load value and continue counting. This results in a periodic timer with a frequency determined by the count range and tick rate.
Periodic mode is commonly used to generate interrupts at regular intervals for time-based tasks like reading sensors, blinking LEDs, data refresh rates, motor control pulses, and other repetitive actions.
One-Shot Mode
In one-shot mode, the timer counts from an initial value to a terminal value then stops. An interrupt can be triggered when the terminal value is reached. One-shot mode is useful for creating delay timers and time-based triggers.
To configure a one-shot timer:
- Load the start counter value into the timer load register.
- Load the end counter value into the timer match register.
- Configure the control register for one-shot mode.
- Enable the timer and interrupt on match.
When the counter reaches the match value, it will stop counting and trigger the interrupt. The timer will not restart until it is reconfigured and enabled again.
One-shot mode can generate delays, timeouts, pulse widths, and other non-repeating time-based events. The timer expires once and remains in its terminal state until reset.
Choosing a Timer Mode
Here are some guidelines for selecting a timer mode for different use cases:
- Use free-running mode when you need an always-on counter for elapsed time measurement.
- Use periodic mode when you need something to happen at regular intervals, like blinking an LED.
- Use one-shot mode when you need a single timeout or delay, like waiting for sensor data.
- Avoid free-running mode if you don’t need continuous timekeeping. It uses more power.
- Prefer periodic mode over repetitive one-shot modes for periodic events.
- Use one-shot for simple delays rather than busy-wait loops.
The mode can typically be changed dynamically at runtime if requirements change. Most timers allow free-running, periodic, and one-shot modes to be intermixed on the same timer peripheral.
Timer Features
ARM timers offer many configurable features including:
- Clock source – Timer can use internal clocks or external signal.
- Clock prescaling – Adjusts the timer tick speed.
- Count direction – Supports up or down counting.
- Auto-reload – Timer restarts automatically in periodic mode.
- Preload – Next load value can be preloaded for seamless transitions.
- Interrupts – Flexible interrupt generation on match, capture, overflow, etc.
- Dead timer – Stops counting when the processor halts.
- Nested interrupts – Allows interrupting active ISRs.
These features allow the timer peripheral to be customized for many different use cases. The timer can act as a simple counter, periodic interrupt source, PWM driver, real-time clock, event timestamp, and more.
Using Timers Efficiently
Here are some tips for using timers efficiently in ARM Cortex-M devices:
- Pick the simplest timer mode that meets requirements to save power.
- Use lower-frequency clock sources like internal RC oscillators when possible.
- Prefer the periodic interrupt mode over software polling.
- Use prescaling to reduce the tick frequency if a slower rate is acceptable.
- Combine timers sharing a clock source into a single prescaled counter whenever possible.
- Use autoreload and preload features to avoid reconfiguring the timers.
- Prioritize interrupt handling to minimize jitter.
- Use timestamps and deltas rather than absolute times to simplify software.
Following these best practices will help reduce timer power consumption, lower interrupt overhead, and improve the responsiveness of time-critical operations.
Conclusion
The timer peripheral is one of the most versatile components in ARM Cortex-M microcontrollers. The free-running, periodic, and one-shot modes provide flexible options for timekeeping, timeouts, pulse generation, interrupts, and other core timing functions. Timers can be optimized for low power operation and customized via clock sources, prescalers, autoreload, and interrupt capabilities. Using the right timer features and efficient software design allows building responsive and robust time-based applications on ARM.