Note:本次使用pynq z2 board作为硬件环境
一. Zynq 定时器概述
在zynq7000中,定时器一共分为4个部分, 参考手册:Ug585
- 每颗arm A9含有一个私有定时器以及一个看门狗定时器
- 系统含有一个全局看门狗定时器
- 系统含有一个全局定时器
- 系统含有两个TTC模块,每个模块含有三路定时器
从TTC的框架图来看, 每个TTC模块含有三个定时器
- 每个定时器可以为CPU时钟或者外部时钟输入
- 每个定时器可以输出方波, 并且可以产生中断, 中断号在图中以及给出
- 使用CPU时钟时候可以先将时钟进行分频再输入进入计数器
二. vivado配置
- block design添加zynq7进行配置
1.1 取消reset信号,不使用PL
1.2 取消PSPL AXI接口
1.3 设置BANK电压,需要查看自己原理图, 勾选Timer0, 根据自己原理图查看MIO是否被占用, 本次勾选EMIO就行
1.4 配置PS输入时钟, 取消勾选FCLK, 不使用PL
1.5 配置DDR, 根据自己原理图选择
1.6 配置好以后就这样
以上设置好以后进行布线, generate output products, creat HDL wrapper
然后直接export handware, 因为没使用PL, 因此不需要generate bitstream
然后launch SDK
三. SDK编写
-
新建工程
-
输入改成名称后选择hello world 模板即可
-
进行宏定义
#define GicDeviceId XPAR_SCUGIC_SINGLE_DEVICE_ID
#define TTC00DeviceId XPAR_XTTCPS_0_DEVICE_ID
#define TTC00IntId XPS_TTC0_0_INT_ID
#define TTC01DeviceId XPAR_XTTCPS_1_DEVICE_ID
#define TTC01IntId XPS_TTC0_1_INT_ID
#define TTC0Freq 1
#define TTC1Freq 2
#define TTC_Option XTTCPS_OPTION_INTERVAL_MODE | XTTCPS_OPTION_WAVE_DISABLE
#define TTC_Mask XTTCPS_IXR_INTERVAL_MASK
- 定义一些必要的函数以及变量
XScuGic GicInst;
XTtcPs ttc0Inst;
XTtcPs ttc1Inst;
// 方便传递函数参数
typedef void (*TTC_Handler)(void *);
// 初始化中断系统
static void SysInterruptSetup(u16 DeviceId, XScuGic* GicInstancePtr);
// 初始化ttc及中断
static void TTC_Int_Init(u16 ttcDeviceId, XTtcPs* ttcInstancePtr, u16 ttcIntId, u32 Freq, TTC_Handler handlerFunc);
// 定义中断回调函数
static void TTC0_Handle(void *Callbackref);
static void TTC1_Handle(void *Callbackref);
// 中断flag
u8 flag_ttc0;
u8 flag_ttc1;
对TTC进行初始化
- 在main函数中对函数进行调用
int main()
{
init_platform();
SysInterruptSetup(GicDeviceId, &GicInst);
TTC_Int_Init(TTC00DeviceId, &ttc0Inst, TTC00IntId, TTC0Freq, TTC0_Handle);
TTC_Int_Init(TTC01DeviceId, &ttc1Inst, TTC01IntId, TTC1Freq, TTC1_Handle);
while(1){
if(flag_ttc0){
flag_ttc0 = 0;
print("ttc0000000 has been detected!!! \r\n");
}
if(flag_ttc1){
flag_ttc1 = 0;
print("ttc1111111 has been detected!!! \r\n");
}
}
cleanup_platform();
return 0;
}
- 最后,ttc0一秒打印一次, ttc1一秒打印两次
源码地址: click here