Introduction to Timers
In ZYNQ embedded systems, timer resources are abundant. Each Cortex-A9 processor has its own independent 32-bit private timer and a 32-bit watchdog timer, while both CPUs share a single 64-bit Global Timer Counter (GTC).
System Block Diagram

Global Timer (GTC)
The Global Timer is a 64-bit incrementing counter with an automatic increment feature. The Global Timer is memory-mapped to the same address space as the dedicated timers. The Global Timer is only accessed during a reset in a secure state. All Cortex-A9 processors can access this Global Timer. Each Cortex-A9 processor has a 64-bit comparator, which is used to generate a private interrupt when the Global Timer reaches the comparator value.
GTC Clock
- The clock for the Global Timer GTC is half of the CPU clock frequency (CPU_6x4x), which is CPU_3x2x.
GTC Register Table


GTC Driver Example
- gtc.c driver source file:
/**
* Copyright (c) 2022-2023, HelloAlpha
*
* Change Logs:
* Date Author Notes
*/
#include "gt.h"
#include "stdio.h"
void GtStart(void)
{
/* Start the Global Timer */
GT_WR_REG(GT_CTRL_REG, AUTO_INC_BIT | IRQ_ENABLE_BIT
| COMP_ENABLE_BIT | TMR_ENABLE_BIT);
}
/* Global Timer initialization and interrupt configuration */
int GtIntrInit(XScuGic *GtInstancePtr,
uint64_t Value, void(* CallBack)(void *))
{
int Status;
/* Stop the Global Timer */
GT_WR_REG(GT_CTRL_REG, 0);
/* Clear the lower 32 bits of the counter */
GT_WR_REG(GT_CNT_REG0, 0);
/* Clear the upper 32 bits of the counter */
GT_WR_REG(GT_CNT_REG1, 0);
/* Clear the interrupt status */
GT_WR_REG(GT_INTR_STAT_REG, 1);
/* Load the lower 32 bits of the comparator */
GT_WR_REG(COMP_VAL_REG0, (uint32_t)Value);
/* Load the upper 32 bits of the comparator */
GT_WR_REG(COMP_VAL_REG1, 0);
/* Load the increment register value */
GT_WR_REG(AUTO_INC_REG, (uint32_t)(Value >> 32));
/* Bind the Global Timer interrupt service function */
Status = XScuGic_Connect(GtInstancePtr, GT_INTR,
(Xil_ExceptionHandler)CallBack, 0);
if (Status != XST_SUCCESS)
{
return Status;
}
/* Map the 27th Global Timer interrupt to CPU1 */
XScuGic_InterruptMaptoCpu(GtInstancePtr, 1, GT_INTR);
/* Enable the Global Timer interrupt (27th) */
XScuGic_Enable(GtInstancePtr, GT_INTR);
return Status;
}
/* Reset the counter */
void gt_tic(void)
{
*((volatile int*)(GT_CTRL_REG)) = 0x00;
*((volatile int*)(GT_CNT_REG0)) = 0x00000000;
*((volatile int*)(GT_CNT_REG1)) = 0x00000000;
*((volatile int*)(GT_CTRL_REG)) = 0x01;
}
/** Read the counter and output the current time in ms
* Can be used with gt_tic as follows:
* {
* gt_tic();
* function_to_get_running_time();
* gt_toc();
* }
*/
double gt_toc(void)
{
*((volatile int*)(GT_CTRL_REG)) = 0x00;
long long cnt = *((volatile int*)(GT_CNT_REG1));
double elapsed_time = cnt << 32;
cnt = *((volatile int*)(GT_CNT_REG0));
elapsed_time += cnt;
elapsed_time /= CLK_3x2x;
elapsed_time *= 1000;
printf("Elapsed time is %f ms.\r\n",elapsed_time);
return elapsed_time;
}
/* Get the current time (in seconds) */
float get_time_s(void)
{
XTime tCur = 0;
XTime_GetTime(&tCur);
return (tCur / (float) COUNTS_PER_SECOND);
}
- gtc.h driver header file:
/**
* Copyright (c) 2022-2023, HelloAlpha
*
* Change Logs:
* Date Author Notes
*/
#ifndef __GTC_H__
#define __GTC_H__
#include "xtime_l.h"
#include "xscugic.h"
#include "xil_io.h"
/* Timer Registers */
#define GT_BASEADDR GLOBAL_TMR_BASEADDR
#define GT_CNT_REG0 GT_BASEADDR + GTIMER_COUNTER_LOWER_OFFSET
#define GT_CNT_REG1 GT_BASEADDR + GTIMER_COUNTER_UPPER_OFFSET
#define GT_CTRL_REG GT_BASEADDR + GTIMER_CONTROL_OFFSET
/* Interrupt Registers */
#define GT_INTR XPAR_GLOBAL_TMR_INTR
/* Interrupt Status Register */
#define GT_INTR_STAT_REG GT_BASEADDR + 0x0CU
/* Comparators */
#define COMP_VAL_REG0 GT_BASEADDR + 0x10U
#define COMP_VAL_REG1 GT_BASEADDR + 0x14U
/* Auto Increment Register */
#define AUTO_INC_REG GT_BASEADDR + 0x18U
#define AUTO_INC_BIT 0x08
#define IRQ_ENABLE_BIT 0x04
#define COMP_ENABLE_BIT 0x02
#define TMR_ENABLE_BIT 0x01
#define CLK_3x2x 333333333
#define GT_WR_REG Xil_Out32
void GtStart(void);
int GtIntrInit(XScuGic *GtInstancePtr,
uint64_t Value, void(* CallBack)(void *));
void gt_tic(void);
double gt_toc(void);
float get_time_s(void);
#endif
Reference: UG585; Summary of online resources.
The End

Share, bookmark, like, and follow!
