软件版本:VIVADO2021.1
操作系统:WIN10 64bit
硬件平台:适用 XILINX A7/K7/Z7/ZU/KU 系列 FPGA
实验平台:米联客-MLK-H3-CZ08-7100开发板
板卡获取平台:https://milianke.tmall.com/
登录“米联客”FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!
目录
1概述
看门狗是芯片内部的一个具有定时计数的功能模块,当启用看门狗功能后,系统软件必须定时“喂狗”,CPU程序跑飞异常后,就不能“喂狗”这样看门狗定时器就会产生超时,超时后一般会复位整个系统。
本文实验介绍ZYNQ自带的私有看门狗定时器的使用:
实验目的:
1:了解私有看门狗定时器的概念
2:了解私有看门狗定时器的功能寄存器
3:使用SDK自带代码测试门狗定时器的定时器工作模式和门狗模式。
2系统框图
3中断资源概述
PS的CPU0和CPU1各有1个私有定时器。上图中,红色部分为PS的私有中断资源,本文中demo就是以CPU0的定时器中断使用作为演示方案。CPU0的定时器中断经过中断控制派发器派发给CPU0。CPU0的私有看门狗定时器IRQ ID=30。
4定时器资源介绍
Zynq的PS的CPU0和CPU1各包含1个私有定时器以及一个私有看门狗定时器并且共享一个全局定时器。另外Zynq的PS还有TTC0以及TTC1定制控制器。每个TTC定时器里面包含三个定时器/计数器。本文所讲解的是CPU0的私有看门狗定时器中断的使用。
看门狗需要不停的“喂狗”,在这里就是不停的读预加载寄存器再写入预加载寄存器。如果不能及时喂狗,那么看门狗就会超时,并且产生一个复位输出。
本方案中只对CPU0的私有看门狗定时器进行说明。
Zynq的私有定时器和看门狗定时器具有以下共同的特性:
1-定时计数器位宽为32位,当达到0时产生中断
2-参考时钟为CPU时钟的1/2,比如CPU是666.6666M 那么定时器的参考时钟为333.3333M
3-有一个8bit预分频器,可以对参考时钟进一步分频
4-有一个可配置的预加载寄存器
5-可配置为单次模式或者自动重载模式
看门狗定时器多了以下功能:
1-当看门狗没有及时“喂狗”导致的系统复位输出
2-看门狗定时器可以设置为定时器模式或者看门狗模式
5私有定看门狗时器的寄存器
在UG585中没有关于私有看门狗定时器的详细说明,我们通过SDK代码的理解补充了这部分说明。私有看门狗定时器的基地址为0xF8F00620。CPU的私有看门狗定时器一共有6个寄存器:
XSCUWDT_LOAD寄存器XSCUWDT_LOAD_OFFSET(0x00U)
Field Name | Bits | Type | Reset Value | Description |
XSCUWDT_LOAD | 31:0 | 至少 可写 | 0x0 | 私有看门狗定时器的预加载值 |
XSCUWDT_COUNTER寄存器XSCUWDT_COUNTER_OFFSET (0x04U)
Field Name | Bits | Type | Reset Value | Description |
XSCUWDT_COUNTER | 31:0 | 至少 可读 | 0x0 | 私有看门狗定时器的计数器 |
XSCUWDT_CONTROL寄存器XSCUWDT_CONTROL_OFFSET (0x08U)
Field Name | Bits | Type | Reset Value | Description |
XSCUWDT_CONTROL | 31:0 | R/W | 0x0 | 私有看门狗定时器的控制寄存器 15~8bit:预分频设置 3bit:当为看门狗模式,设置1为看门狗 2bit:当为定时器模式,设置1为中断使能 1bit:当为1自动重载使能 0bit:当为1表示看门狗使能 |
XSCUWDT _ISR寄存器XSCUWDT _ISR_OFFSET (0x0CU)
Field Name | Bits | Type | Reset Value | Description |
XSCUWDT_ISR | 31:0 | R/W | 0x0 | 私有看门狗定时器的中断寄存器 0bit:当为1的时候表示发生中断 |
XSCUWDT_RST_STS寄存器XSCUWDT_RST_STS_OFFSET (0x10U)
Field Name | Bits | Type | Reset Value | Description |
XSCUWDT_RST_STS | 31:0 | R/W | 0x0 | 私有看门狗定时器的复位状态寄存器 0bit:当为1代表定时器超时并且发送一个复位 |
XSCUWDT_DISABLE寄存器XSCUWDT_DISABLE_OFFSET (0x14U)
Field Name | Bits | Type | Reset Value | Description |
XSCUWDT_DISABLE | 31:0 | R/W | 0x0 | 第一次写入0x12345678U 第二次写入0x87654321U 会设置控制寄存器的bit-3为0,这样设置为定时器模式 |
6搭建SOC系统工程
详细的搭建过程这里不再重复,对于初学读者如果还不清楚如何创建SOC工程的,请学习“01Vitis Soc开发入门”这篇文章。
6.1SOC系统工程
直接使用已经搭建好的“01Vitis Soc开发入门”这篇文章中的工程。
6.2编译并导出平台文件
以下步骤简写,有不清楚的看第一篇文章。
1:单击Block文件à右键àGenerate the Output ProductsàGlobalàGenerate。
2:单击Block文件à右键à Create a HDL wrapper(生成HDL顶层文件)àLet vivado manager wrapper and auto-update(自动更新)。
3:添加配套工程路径下uisrc/04_pin/fpga_pin.xdc约束文件
4:生成Bit文件。
5:导出到硬件: FileàExport HardwareàInclude bitstream
6:导出完成后,对应工程路径的soc_hw路径下有硬件平台文件:system_wrapper.xsa的文件。根据硬件平台文件system_wrapper.xsa来创建需要Platform平台。
7搭建Vitis-sdk工程
创建soc_base sdk platform和APP工程的过程不再重复,如果不清楚请参考本章节第一个demo。
7.1创建SDK Platform工程
右击soc_base编译,编译的时间可能会有点长
7.2创建APP工程
利用SDK自带的程序对看门狗定时器2种工作模式测试。
xscuwdt_intr_example是SDK库函数自带的函数,采用的是看门狗定时器的定时器模式
xscuwdt_polled_example是SDK库函数自带的函数,采用的是看门狗定时器的看门狗模式
8程序分析
函数的分析办法可以参考“PS私有定时器实验”中的程序分析,我们这里只对重点函数相关的寄存器说明。
8.1定时器模式
在定时器模式下,看门狗定时器的功能和定时器的使用非常类似,这里对SDK自带的demo进行部分修改
int ScuWdtIntrExample(XScuGic *IntcInstancePtr, XScuWdt * WdtInstancePtr,u16 WdtDeviceId, u16 WdtIntrId)
{
int Status;
u32 Timebase = 0;
u32 ExpiredTimeDelta = 0;
XScuWdt_Config *ConfigPtr;
/*
* Initialize the ScuWdt driver.
*/
ConfigPtr = XScuWdt_LookupConfig(WdtDeviceId);
/*
* This is where the virtual address would be used, this example
* uses physical address.
*/
Status = XScuWdt_CfgInitialize(WdtInstancePtr, ConfigPtr,ConfigPtr->BaseAddr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
XScuWdt_SetTimerMode(WdtInstancePtr); //设置看门狗定时器的工作模式为定时器模式
XScuWdt_LoadWdt(WdtInstancePtr, TIMER_LOAD_VALUE); //设置看门狗定时器的预加载值
XScuWdt_EnableAutoReload(WdtInstancePtr); //使能自动重载模式
Status = WdtSetupIntrSystem(IntcInstancePtr, WdtInstancePtr, WdtIntrId); //设置看门狗定时器的中断函数
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
XScuWdt_Start(WdtInstancePtr); //启动看门狗定时器
while (1)
{
}
return XST_SUCCESS;
}
之后每次定时中断产生后串口打印输出
static void WdtIntrHandler(void *CallBackRef)
{
/*
* WDT timed out and interrupt occurred, let main test loop know.
*/
XScuWdt *WdtInstancePtr = CallBackRef;
timer_counter++;
printf("timer_counter = %u\n",timer_counter);
XScuWdt_WriteReg(WdtInstancePtr->Config.BaseAddr,
XSCUWDT_ISR_OFFSET,
XSCUWDT_ISR_EVENT_FLAG_MASK);
}
1:XScuWdt_SetTimerMode()函数
通过写入XSCUWDT_DISABLE寄存器会设控制寄存器XSCUWDT_CONTROL的bit-3为0这样看门狗工作于定时器模式,就是一个定时器。
2:XScuWdt_LoadWdt()函数
给看门狗预加载寄存器XSCUWDT_LOAD初值
3:WdtSetupIntrSystem()函数
4:XScuWdt_Start()函数
启动定时器
5:XScuWdt_RestartWdt()函数
重新加载预加载寄存器,会更新计数器为预加载值,可以防止看门狗复位信号输出
8.2看门狗模式
看门狗需要不停的“喂狗”,在这里就是不停的读预加载寄存器再写入预加载寄存器。如果不能及时喂狗,那么看门狗就会超时,并且产生一个复位输出,复位系统。由于while循环中不停的喂狗,所以这个程序正常运行期间不会产生看门狗超时,但是如果用TF卡启动,程序运行 结束后,会产生看门狗超时后导致的系统复位,这样会看到看程序不停的启动,停止。
int ScuWdtPolledExample(XScuWdt * WdtInstancePtr, u16 DeviceId)
{
int Status;
XScuWdt_Config *ConfigPtr;
int Count = 0;
/*
* Initialize the SCU Private Wdt driver so that it is ready to use.
*/
ConfigPtr = XScuWdt_LookupConfig(DeviceId);
/*
* This is where the virtual address would be used, this example
* uses physical address.
*/
Status = XScuWdt_CfgInitialize(WdtInstancePtr, ConfigPtr,
ConfigPtr->BaseAddr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
XScuWdt_SetWdMode(WdtInstancePtr); //设置为看门狗模式
/*
* Load the watchdog counter register.
*/
XScuWdt_LoadWdt(WdtInstancePtr, WDT_LOAD_VALUE); //设置预加载值寄存器
XScuWdt_Start(WdtInstancePtr); //启动看门狗
while (Count < 20) {
sleep(1);
Count++;
XScuWdt_RestartWdt(WdtInstancePtr); //需要不停的喂狗
}
return XST_SUCCESS;
}
9方案演示
9.1硬件准备
实验需要用到 JTAG 下载器、USB 转串口外设,另外需要把核心板上的 2P 模式开关设置到 JTAG 模式,即ON ON(注意新版本的 MLK_H3_CZ08-7100-MZ7100FC),支持 JTAG 模式,对于老版本的核心板,JTAG 调试的时候 一定要拔掉 TF 卡,并且设置模式开关为 OFF OFF)
9.2实验结果
当运行定时器模式,程序运行后每1S会中断并输出中断次数
由于开发板不支持SD卡启动,因此看门狗实验暂时无法实现。
标签:定时器,FPGA,CZ08,私有,H3,寄存器,看门狗,XSCUWDT,XScuWdt From: https://blog.csdn.net/u011570052/article/details/142363990