UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

Implementing the Zynq SoC's Private Timer: Adam Taylor’s MicroZed Chronicles Part 15

by Xilinx Employee ‎01-13-2014 12:59 PM - edited ‎05-26-2015 04:31 PM (17,442 Views)

In the last blog we looked at Zynq timers. In this new instalment, we will start looking at how we can use these resources starting with the private timer. Like most of the Zynq peripherals, the private timer has a number of predefined functions and macros to help the engineer use the resource efficiently. These are contained within

 

#include "xscutimer.h"

 

Xscutimer.h contains functions (macros) that:

 

  • Initialize the timer
  • Run a timer self test
  • Start and stop the timer
  • Manage the timer (restart, check if expired, load the timer, enable/disable auto loading)
  • Set the pre-scaler
  • Get the pre-scaler value
  • Setup, enable, disable, clear, and manage timer interrupts

 

The timer itself is controlled via four registers in the Zynq All Programmable SoC:

 

  • Private Timer Load Register – used in auto reload mode. This register contains the value to be reloaded into the Private Timer Counter Register when auto reload is enabled.

 

  • Private Timer Counter Register – This register is the actual counter itself. When the value in this register reaches zero, an interrupt event flag is set (when enabled).

 

  • Private Timer Control Register – This control register enables or disables the timer, auto reload mode, and interrupt generation. It also contains the timer pre-scaler.

 

  • Private Timer Interrupt Status Register – This register contains the Private timer interrupt status event flag

 

 

The timer device ID and timer interrupt ID, which are needed to set up the timer, are contained within XParameters.h.

 

The example in this blog post uses the push-button interrupt, which we have developed previously. See “Using the MicroZed Button for Input: Adam Taylor’s MicroZed Chronicles Part 11”  and “MicroZed Timers, Clocks and Watchdogs: Adam Taylor’s MicroZed Chronicles Part 14.”

 

In this example, the timer will be loaded and will start running when the button is pressed. (Note: the timer will not be run in auto-reload mode). The timer will generate an interrupt when the preset timer countdown value reaches zero. The resulting interrupt triggers output of a message out over STDOUT and the interrupt will then be cleared to await the next button press.

 

This example always loads the same value into the counter. Hence the declarations at the top of the file where the timer count value is declared

 

#define TIMER_LOAD_VALUE      0xFFFFFFFF

 

The next step is to configure and initialize the private timer, perform a self-test, and load the timer count value into the timer:

 

     //timer initialization

     TMRConfigPtr = XScuTimer_LookupConfig(TIMER_DEVICE_ID);

     XScuTimer_CfgInitialize(&Timer, TMRConfigPtr,TMRConfigPtr->BaseAddr);

     XScuTimer_SelfTest(&Timer);

     //load the timer

     XScuTimer_LoadTimer(&Timer, TIMER_LOAD_VALUE);

 

We also need to update the interrupt setup subroutine to connect the timer interrupts to the GIC (General Interrupt controller) and enable the timer interrupt:

 

      //set up the timer interrupt

      XScuGic_Connect(GicInstancePtr, TimerIntrId,

                                    (Xil_ExceptionHandler)TimerIntrHandler,

                                    (void *)TimerInstancePtr);

      //enable the interrupt for the Timer at GIC

      XScuGic_Enable(GicInstancePtr, TimerIntrId);

      //enable interrupt on the timer

      XScuTimer_EnableInterrupt(TimerInstancePtr);

 

Where TimerIntrHandler is the name of the function to be called when the interrupt occurs.

 

Next, the timer interrupt must be enabled on the GIC and within the timer itself. The timer interrupt service routine is very simple. It just clears the pending interrupt and writes out a message over the STDOUT:

 

static void TimerIntrHandler(void *CallBackRef)

{

 

      XScuTimer *TimerInstancePtr = (XScuTimer *) CallBackRef;

      XScuTimer_ClearInterruptStatus(TimerInstancePtr);

      printf("****Timer Event!!!!!!!!!!!!!****\n\r");

     

}

 

The final step is to modify the GPIO interrupt service routine to start the timer each time the button is pushed:

 

      //load timer

      XScuTimer_LoadTimer(&Timer, TIMER_LOAD_VALUE);

      //start timer

      XScuTimer_Start(&Timer);

 

To do this, we first load the timer value into the timer and then call the timer start function, before again clearing the push button interrupt and resume processing.

 

To reduce the number of messages being output over STDOUT, the reading of XADC within the main loop of this program has been removed in this example. Here’s what the output from this program now looks like:

 

Output window for Part 15.jpg 

 

 

Downloadable sample code is attached to this blog post.

 

 

In the next blog we will look at using the private watchdog.

 

 

Please see the previous entries in this MicroZed series by Adam Taylor:

 

MicroZed Timers, Clocks and Watchdogs: Adam Taylor’s MicroZed Chronicles Part 14

 

More About MicroZed Interrupts: Adam Taylor’s MicroZed Chronicles Part 13

 

MicroZed Interrupts: Adam Taylor’s MicroZed Chronicles Part 12

 

Using the MicroZed Button for Input: Adam Taylor’s MicroZed Chronicles Part 11

 

Driving the Zynq SoC's GPIO: Adam Taylor’s MicroZed Chronicles Part 10

 

Meet the Zynq MIO: Adam Taylor’s MicroZed Chronicles Part 9

 

MicroZed XADC Software: Adam Taylor’s MicroZed Chronicles Part 8

 

Getting the XADC Running on the MicroZed: Adam Taylor’s MicroZed Chronicles Part 7

 

A Boot Loader for MicroZed. Adam Taylor’s MicroZed Chronicles, Part 6 

 

Figuring out the MicroZed Boot Loader – Adam Taylor’s MicroZed Chronicles, Part 5

 

Running your programs on the MicroZed – Adam Taylor’s MicroZed Chronicles, Part 4

 

Zynq and MicroZed say “Hello World”-- Adam Taylor’s MicroZed Chronicles, Part 3

 

Adam Taylor’s MicroZed Chronicles: Setting the SW Scene

 

Bringing up the Avnet MicroZed with Vivado

 

Labels
About the Author
  • Be sure to join the Xilinx LinkedIn group to get an update for every new Xcell Daily post! ******************** Steve Leibson is the Director of Strategic Marketing and Business Planning at Xilinx. He started as a system design engineer at HP in the early days of desktop computing, then switched to EDA at Cadnetix, and subsequently became a technical editor for EDN Magazine. He's served as Editor in Chief of EDN Magazine, Embedded Developers Journal, and Microprocessor Report. He has extensive experience in computing, microprocessors, microcontrollers, embedded systems design, design IP, EDA, and programmable logic.