定时器简介
在 ZYNQ 嵌入式系统中,定时器的资源是非常丰富的,每个 Cortex-A9 处理器都有各自独立的 32 位私有定时器和 32 位看门狗定时器,这两个 CPU 同时共享一个 64 位的全局定时器(GT)。
系统框图
私有定时器
特点
- 32 位计数器,当计数器递减至 0 时产生中断
- 8 位预分频计数器,可以更好的控制中断周期
- 可以配置单次定时或者自动重载模式
- 通过配置起始计数值来设置定时时间
时钟
- 私有定时器时钟为 CPU 频率(CPU_3x2x)的一半,如 ARM 的工作时钟频率为 666.666Mhz,则私有定时器的时钟频率为 333.333Mhz。
寄存器表
驱动示例
- timer.c
/** * Copyright (c) 2022-2023,HelloAlpha * * Change Logs: * Date Author Notes */ #include "timer.h" int TimerInit(XScuTimer *TimerInstancePtr, uint16_t TimerDeviceId, uint32_t TimerLoadValue) { int Status; XScuTimer_Config *ConfigPtr; ConfigPtr = XScuTimer_LookupConfig(TimerDeviceId); Status = XScuTimer_CfgInitialize(TimerInstancePtr, ConfigPtr, ConfigPtr->BaseAddr); if (Status != XST_SUCCESS) { return XST_FAILURE; } Status = XScuTimer_SelfTest(TimerInstancePtr); if (Status != XST_SUCCESS) { return XST_FAILURE; } XScuTimer_EnableAutoReload(TimerInstancePtr); XScuTimer_LoadTimer(TimerInstancePtr, TimerLoadValue); return Status; } int TimerIntrInit(XScuGic *IntcInstancePtr, XScuTimer *TimerInstancePtr, uint32_t TimerIntrId, void(* CallBack)(void *)) { int Status; XScuGic_Config *IntcConfig; IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID); if (NULL == IntcConfig) { return XST_FAILURE; } Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig, IntcConfig->CpuBaseAddress); if (Status != XST_SUCCESS) { return XST_FAILURE; } Xil_ExceptionInit(); Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, IntcInstancePtr); Xil_ExceptionEnable(); Status = XScuGic_Connect(IntcInstancePtr, TimerIntrId, (Xil_ExceptionHandler)CallBack, (void *)TimerInstancePtr); if (Status != XST_SUCCESS) { return Status; } XScuGic_Enable(IntcInstancePtr, TimerIntrId); XScuTimer_EnableInterrupt(TimerInstancePtr); return XST_SUCCESS; }
- timer.h
/** * Copyright (c) 2022-2023,HelloAlpha * * Change Logs: * Date Author Notes */ #ifndef __TIMER_H__ #define __TIMER_H__ #include "xscutimer.h" #include "xscugic.h" /* CPU时钟频率 */ #ifndef CPU_CLK_FREQ_HZ #define CPU_CLK_FREQ_HZ XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ #endif /* 私有定时器的时钟频率 = CPU时钟频率/2 = 333MHz */ #define TIMER_HZ CPU_CLK_FREQ_HZ/2 #ifndef INTC_DEVICE_ID #define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID #endif #define TIMER_DEVICE_ID XPAR_XSCUTIMER_0_DEVICE_ID #define TIMER_IRPT_INTR XPAR_SCUTIMER_INTR /* * Function declaration */ int TimerInit(XScuTimer *TimerInstancePtr, uint16_t TimerDeviceId, uint32_t TimerLoadValue); int TimerIntrInit(XScuGic *IntcInstancePtr, XScuTimer *TimerInstancePtr, uint32_t TimerIntrId, void(* CallBack)(void *)); #endif
应用示例
- app_timer.c
/** * Copyright (c) 2022-2023,HelloAlpha * * Change Logs: * Date Author Notes */ #include "app_timer.h" #define USING_ULOG #include "ulog.h" extern XScuGic IntcInstPtr; /** * @brief 定时器中断处理,中断时间 50ms */ void TimerIntrHandler(void *CallBackRef) { XScuTimer *TimerInstancePtr = (XScuTimer *) CallBackRef; struct timer_flag *_timer_flag = &g_timer_flag; static uint16_t count = 0; /* 标志位触发 */ // XScuTimer_IsExpired(TimerInstancePtr); ULOG("--- timer handle --- \r\n"); count++; if(count == 101) { count = 0; } ULOG("count: %d\r\n", count); _timer_flag->timer_flag_50ms = 1; if(count % 10 == 0) { _timer_flag->timer_flag_500ms = 1; ULOG("--- 500 MS --- \r\n"); } if(count % 20 == 0) { _timer_flag->timer_flag_1s = 1; ULOG("--- 1 S --- \r\n"); } XScuTimer_ClearInterruptStatus(TimerInstancePtr); /* 关闭自动重装载值 关闭中断 */ // XScuTimer_DisableAutoReload(TimerInstancePtr); } int app_timer_init(void) { int Status; Status = TimerInit(&Timer, TIMER_DEVICE_ID, TIMER_LOAD_VALUE); if (Status != XST_SUCCESS) { return XST_FAILURE; } Status = TimerIntrInit(&IntcInstPtr, &Timer, TIMER_IRPT_INTR, TimerIntrHandler); if (Status != XST_SUCCESS) { return XST_FAILURE; } XScuTimer_Start(&Timer); return Status; }
- app_timer.h
/** * Copyright (c) 2022-2023,HelloAlpha * * Change Logs: * Date Author Notes */ #ifndef __APP_TIMER_H__ #define __APP_TIMER_H__ #include "timer.h" /* CPU时钟频率 */ #ifndef CPU_CLK_FREQ_HZ #define CPU_CLK_FREQ_HZ XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ #endif /* 私有定时器的时钟频率 = CPU时钟频率/2 = 333MHz */ #define TIMER_HZ CPU_CLK_FREQ_HZ/2 /* * 精确计算 装载值 = 定时时间(单位:秒)* 333333333 * 0.5s 166,666,666.5 0x9EF21AA * 0.1s 333,333,33.3 0x1FCA055 * 0.05s 16,666,666,65 0xFE502A */ #define TIMER_LOAD_VALUE 0xFE502A XScuTimer Timer; struct timer_flag { char timer_flag_50ms; char timer_flag_500ms; char timer_flag_1s; }; typedef struct timer_flag timer_flag_t; timer_flag_t g_timer_flag; int app_timer_init(void); #endif
测试平台:黑金 AC7Z035B
芯片型号:XC7Z035-2FFG676
参考来源:UG585