定时器简介
在 ZYNQ 嵌入式系统中,定时器的资源是非常丰富的,每个 Cortex-A9 处理器都有各自独立的 32 位私有定时器和 32 位看门狗定时器,这两个 CPU 同时共享一个 64 位的全局定时器(GT)。
系统框图
全局定时器(GTC)
全局定时器是一个具有自动递增功能的 64 位递增计数器。全局定时器将内存映射到与专用定时器相同的地址空间中。全局定时器仅在安全状态下的重置时被访问。所有 Cortex-A9 处理器都可以访问这个全局定时器。每个 Cortex-A9 处理器都有一个 64 位的比较器,当全局计时器达到比较器值时,该比较器被用来产生一个私有中断。
时钟
- GTC 的时钟始终为 CPU 频率(CPU_3x2x)的 1/2。
寄存器表
驱动示例
- gtc.c
/** * Copyright (c) 2022-2023,HelloAlpha * * Change Logs: * Date Author Notes */ #include "gtc.h" #include "stdio.h" void GtStart(void) { /* 启动全局定时器 */ GT_WR_REG(GT_CTRL_REG, AUTO_INC_BIT | IRQ_ENABLE_BIT | COMP_ENABLE_BIT | TMR_ENABLE_BIT); } int GtIntrInit(XScuGic *GtInstancePtr, uint64_t Value, void(* CallBack)(void *)) { int Status; /* 停止全局定时器 */ GT_WR_REG(GT_CTRL_REG, 0); /* 清空计数器低 32 位 */ GT_WR_REG(GT_CNT_REG0, 0); /* 清空计数器高 32 位 */ GT_WR_REG(GT_CNT_REG1, 0); /* 清除中断标志位 */ GT_WR_REG(GT_INTR_STAT_REG, 1); /* 加载比较器低 32 位 */ GT_WR_REG(COMP_VAL_REG0, (uint32_t)Value); /* 加载比较器高 32 位 */ GT_WR_REG(COMP_VAL_REG1, 0); /* 加载递增寄存器数值 */ GT_WR_REG(AUTO_INC_REG, (uint32_t)(Value >> 32)); /* 绑定全局定时器中断服务函数 */ Status = XScuGic_Connect(GtInstancePtr, GT_INTR, (Xil_ExceptionHandler)CallBack, 0); if (Status != XST_SUCCESS) { return Status; } /* 将 27 号全局定时器中断映射到 CPU1 */ XScuGic_InterruptMaptoCpu(GtInstancePtr, 1, GT_INTR); /* 打开全局定时器中断(27号) */ XScuGic_Enable(GtInstancePtr, GT_INTR); return Status; } /* 清零计数器 */ 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; } /** 读取计数器 输出当前时间 单位:ms * 可配合 gt_tic 作如下使用: * { * 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; } /* 获取当前时间(单位:秒 second) */ float get_time_s(void) { XTime tCur = 0; XTime_GetTime(&tCur); return (tCur / (float) COUNTS_PER_SECOND); }
- gtc.h
/** * 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" /* 定时器寄存器 */ #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 /* 中断寄存器 */ #define GT_INTR XPAR_GLOBAL_TMR_INTR /* 中断状态寄存器 */ #define GT_INTR_STAT_REG GT_BASEADDR + 0x0CU /* 比较器 */ #define COMP_VAL_REG0 GT_BASEADDR + 0x10U #define COMP_VAL_REG1 GT_BASEADDR + 0x14U /* 自动递增寄存器 */ #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
测试平台:黑金 AX7Z035
芯片型号:XC7Z035-2FFG676
参考来源:UG585