Understanding Timers in Embedded Systems
Timers are fundamental components in embedded systems, used to measure time intervals, generate delays, and trigger events at specific times. In this blog, we’ll cover the basics of timers, the different types available in AMD’s Zynq-7000 SoC, and their practical applications.
What is a Timer?
A timer is a hardware device that counts clock pulses. By counting these pulses, timers can measure time intervals or generate specific events after a set period. Timers are essential for tasks that require precise timing, such as:
Generating periodic interrupts for task scheduling
Measuring time intervals between events
Creating delays in software execution
Types of Timers in Zynq-7000
The Zynq-7000 SoC includes several types of timers, each designed for specific purposes. Let’s explore these timers and their uses:
CPU 32-bit Timer (SCUTIMER)
Clock Source: Half the CPU frequency
Description: A private timer for each CPU core. It can be used for timing operations specific to the CPU, such as generating delays or measuring execution time.
Use Case: Scheduling periodic tasks, generating software delays.
CPU 32-bit Watchdog Timer (SCUWDT)
Clock Source: Half the CPU frequency
Description: A watchdog timer for each CPU core that helps in system recovery. If the timer is not reset within a specified period, it triggers a CPU reset.
Use Case: Detecting and recovering from software faults.
Shared 64-bit Global Timer (GT)
Clock Source: Half the CPU frequency
Description: A shared timer with a 64-bit comparator for each CPU. It generates interrupts for each CPU independently.
Use Case: Synchronizing tasks between multiple CPUs, generating periodic events.
System Watchdog Timer (WDT)
Clock Source: CPU clock or external source
Description: A system-wide watchdog timer that can reset the entire system if not serviced within a set interval.
Use Case: Ensuring system stability by resetting the system in case of software malfunctions.
Triple Timer Counter (TTC)
Clock Source: CPU clock or external source from MIO/EMIO
Description: Each TTC module contains three independent timers. These timers can be used for various functions like delay generation, event counting, and PWM signal generation.
Use Case: Creating precise delays, measuring time intervals, generating PWM signals.
Practical Applications of Timers
Timers are used in a wide range of applications in embedded systems:
Generating Periodic Interrupts: Timers can generate interrupts at regular intervals, allowing the CPU to perform periodic tasks such as updating a display, sampling sensors, or toggling LEDs.
Creating Delays: Timers can be used to create delays in software execution. For example, a delay function can be implemented using a timer to pause the execution of code for a specified time.
Measuring Time Intervals: Timers can measure the time between events. For instance, measuring the duration between button presses or the time taken for a sensor to respond.
Watchdog Timers for System Stability: Watchdog timers ensure that the system remains stable by resetting the CPU or the entire system if the software fails to operate correctly.
Setting Up Timer Interrupts in FPGA
To illustrate the concept, we will use a simple example with an ARM Cortex-A9 processor on an FPGA platform, such as the Xilinx Zynq-7000 series.
Step-by-Step Guide
1. Define the CPU Frequency
First, we need to know the CPU frequency of our FPGA. For this example, let’s assume the CPU frequency is 633,333,333 Hz (633.33 MHz).
2. Calculating the Timer Frequency
The timer frequency is half of the CPU frequency for Zynq :
Timer Frequency = (CPU Frequency/2)=(633,333,333 Hz/2)=316,666,666.5 Hz.
Calculate the Load Value
The load value determines how long the timer will count before triggering an interrupt.
For a 1-second interval, the load value is:
Load Value = (Time in Seconds × Timer Frequency) −1
So, what we end up with is as below:
Load Value = (1×316,666,666.5) −1= 316,666,665
Counting Down
When the timer is loaded with 316,666,665, it takes exactly:
Time = (Load Value+1)/ Timer Frequency = (316,666,665+1)/ 316,666,666.5
≈1 second
This step is crucial because it shows how the timer counts down from the load value to zero, which results in one second passing before the timer triggers an interrupt.
Implementing an Interrupt example in Vitis
Step 1. Click Tools-Launch Vitis IDE.
Step 2. With the previous Hello World experiments, we only built the Platform project.
Step 3. Fill in the platform project name and clickNext.
Step 4. Click “Create a new platform hardware (XSA), the software has provided some board hardware platforms
Step 5. Select design_1_wrapper.xsa and click on open.
Step 6. Click on “Finish” .
Step 7. Click to open platform.spr, and click on BSP.
Step 8. Find the timer driver and click on Import Examples.
Step 9. Select on “ xscuwdt_intr_example” and click on “OK”.
Step 10. Click on “xscutimer_intr_example.c “
Step 11. We learned that the clock frequency of the timer is half of the CPU frequency. First, modify the maximum value of the counter to half of the CPU frequency, which is the clock frequency value of the counter. This will ensure that there is one interrupt per second.
Step 12. Modification count3 Change to30 in “xscutimer_intr_example.c “
Step 13. Add printing information and save the file.
Step 14. Build Project.
Step 15. Run as Launch Hardware
Step 16. Open PuTTY serial terminal.