0
点赞
收藏
分享

微信扫一扫

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第九章 定时器中断实验​

定时器中断实验​

MPSOC中PS部分包含许多不同类型的定时器,包括全局定时器、TTC定时器、系统看门狗定时器等。定时器可以不受CPU的干预,自己独立运行,来完成计时、定时、中断以及计算来自MIO或EMIO引脚的信号脉冲宽度等。本章我们将向大家介绍TTC(三路定时器)以TTC(三路定时器)中断的使用方法。

本章包括以下几个部分:

  1. 简介
  2. 实验任务
  3. 硬件设计
  4. 软件设计
  5. 下载验证
  6. 在线调试


简介

PS有许多不同类型的定时器和计数器,包括APU MPCore AArch64定时器,三路定时器(TTC),系统看门狗定时器。APU MPCore AArch64定时器包括APU MPCore全局定时器和APU私有定时器。MPSOC有4个三路定时器,每个三路定时器中有3个相似的计数器,三路定时器可以计算来自MIO引脚或EMIO引脚信号脉冲宽度,并产生中断。PS中有3个系统看门狗定时器(SWDT),用于检测系统故障并从中恢复。

定时器的系统框图如9.1.1所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第九章 定时器中断实验​_#include


9.1.1 定时器系统框图

图中的几种定时器都有连接到中断控制器(Interrupt Controller),我们可以很方便的使用定时器来完成定时器中断的实验。本次实验是基于三路定时器(TTC)来完成定时器的中断实验。

三路定时器(TTC)的特性如下:

1、32位APB编程接口;

2可选的时钟输入

内部总线时钟(LPD_LSBUS_CLK);

内部时钟(来自PL);

外部时钟(来自MIO);

3、支持三个独立的32位定时器/计数器;

4、支持16位时钟预分频器;

5、三个系统中断,用于每路定时器;

6、计数器和可编程值相等时,产生中断;

7、递增和递减计数;

8、产生波形输出(例如PWM);

实验任务

本章的实验任务是通过定时器的中断,每1s控制一次PS LED灯的亮灭。

硬件设计

从实验任务我们可以画出如下的系统框图,DDR4中存放和运行程序、三路定时器(TTC)产生定时中断、UART打印信息、MIO驱动LED外设。虽然本实验可以不需要UART控制器,不过为了方便打印一些信息,此处我们加上UART。

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第九章 定时器中断实验​_引脚_02


9.3.1 系统框图

本次实验在《“Hello World”实验》的基础上修改而来,添加MIO和TTC单元。

打开《“Hello World”实验》工程,另存为名为“timer_intr_led”的工程。点击Open Block Design,在打开的Diagram窗口中双击Zynq Ultrascale+ MPSOC打开重定义窗口,分别添加MIO和TTC,然后点击“OK”,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第九章 定时器中断实验​_#include_03


9.3.2 添加MIO和TTC

嵌入式系统最终搭建的框图如下:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第九章 定时器中断实验​_快捷键_04


9.3.3 嵌入式系统框图界面

保存设计,然后右键点击design_1_wrapper选择Generate Output Products导出Hardware,并将导出的design_1_wrapper.xsa放到vitis文件夹,启动Vitis。


软件设计

启动Vitis开发环境后,新建一个名为“timer_intr_led”的应用工程,工程建好后如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第九章 定时器中断实验​_快捷键_05


9.4.1 新建工程

双击硬件平台工程下的platform.spr,在右侧出现的界面中点击板级支持包Board Support Package,然后可以看到外设驱动Peripheral Drivers,如图9.4.2所示,下拉可以看到三路定时器(TTC)的文档和示例,如图9.4.3所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第九章 定时器中断实验​_引脚_06


9.4.2 展开Peripheral Drivers


《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第九章 定时器中断实验​_#include_07


9.4.3导入TTC示例

如果我们点击Import Examples,会弹出下图所示的导入示例界面,关于TTC有4个示例,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第九章 定时器中断实验​_#include_08


9.4.4 导入示例

感兴趣的朋友可以参考下官方提供的TTC例程,其中xttcps_intr_example是TTC中断的示例。

这里我们不导入官方的例程,而是新建一个源文件。在timer_intr_led/src目录上右键,选择New-> File在弹出的对话框中File name一栏我们输入文件名“main.c”,然后点击“Finish”。

新建源文件之后,在左侧timer_intr_led/src目录下可以看到main.c文件,同时在主页面已经打开了该文件的文本编辑框。我们在新建的main.c文件中输入以下代码:

1 #include <stdio.h>​
2 #include <stdlib.h>​
3 #include "xparameters.h"​
4 #include "xstatus.h"​
5 #include "xil_exception.h"​
6 #include "xttcps.h"​
7 #include "xscugic.h"​
8 #include "xil_printf.h"​
9 #include "xgpiops.h"​
10 ​
11 /************************** Constant Definitions *****************************/​
12 #define NUM_DEVICES 12U​
13 #define TTC_TICK_DEVICE_ID XPAR_XTTCPS_1_DEVICE_ID​
14 #define TTC_TICK_INTR_ID XPAR_XTTCPS_1_INTR​
15 #define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID​
16 ​
17 #define GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID //宏定义 GPIO_PS ID​
18 ​
19 #define MIO_LED 38 //连接 PS_LED1 到 MIO38​
20 #define MIO_LED2 39 //连接 PS_LED2 到 MIO39​
21 ​
22 /**************************** Type Definitions *******************************/​
23 typedef struct {​
24 u32 OutputHz;​
25 XInterval Interval;​
26 u8 Prescaler;​
27 u16 Options;​
28 } TmrCntrSetup;​
29 ​
30 /************************** Function Prototypes ******************************/​
31 static int SetupTicker(void);​
32 static int IniTimer(int DeviceID);​
33 static int SetupInterruptSystem(u16 IntcDeviceID, XScuGic *IntcInstancePtr);​
34 static void TickHandler(void *CallBackRef, u32 StatusEvent);​
35 ​
36 /************************** Variable Definitions *****************************/​
37 ​
38 static XTtcPs TtcPsInst[NUM_DEVICES]; /* Number of available timer counters */​
39 ​
40 XScuGic InterruptController; //中断控制器实例​
41 XGpioPs Gpio; //GPIO设备的驱动程序实例​
42 ​
43 //MIO初始化​
44 int mio_init(XGpioPs *mio_ptr)​
45 {​
46 XGpioPs_Config *mio_cfg_ptr;​
47 ​
48 mio_cfg_ptr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);​
49 if (NULL == mio_cfg_ptr)​
50 return XST_FAILURE;​
51 ​
52 XGpioPs_CfgInitialize(mio_ptr, mio_cfg_ptr,​
53 mio_cfg_ptr->BaseAddr);​
54 ​
55 //设置指定引脚的方向: 0 输入, 1 输出​
56 XGpioPs_SetDirectionPin(mio_ptr, MIO_LED, 1);​
57 ​
58 //使能指定引脚输出: 0 禁止输出使能, 1 使能输出​
59 XGpioPs_SetOutputEnablePin(mio_ptr, MIO_LED, 1);​
60 ​
61 //向指定引脚写入数据: 0 或 1​
62 XGpioPs_WritePin(mio_ptr, MIO_LED, 0);​
63 ​
64 return XST_SUCCESS;​
65 }​
66 ​
67 //中断处理函数​
68 u32 ttc_InterruptHandler(XTtcPs *InstancePtr)​
69 {​
70 u32 XTtcPsStatusReg;​
71 ​
72 XTtcPsStatusReg = XTtcPs_GetInterruptStatus(InstancePtr);​
73 ​
74 //LED状态,用于控制LED灯状态翻转​
75 static int led_state = 0;​
76 if(led_state == 0){​
77 led_state = 1;​
78 }​
79 else{​
80 led_state = 0;​
81 }​
82 ​
83 //向指定引脚写入数据: 0 或 1​
84 XGpioPs_WritePin(&Gpio, MIO_LED,led_state);​
85 ​
86 return XST_SUCCESS;​
87 }​
88 ​
89 int main(void)​
90 {​
91 int Status;​
92 ​
93 //MIO初始化​
94 mio_init(&Gpio);​
95 ​
96 Status = SetupInterruptSystem(INTC_DEVICE_ID, &InterruptController);​
97 if (Status != XST_SUCCESS) {​
98 xil_printf("TTC Interrupt Example Test Failed\r\n");​
99 return XST_FAILURE;​
100 }​
101 ​
102 SetupTicker();​
103 ​
104 xil_printf("Successfully ran TTC Interrupt Test\r\n");​
105 ​
106 return XST_SUCCESS;​
107 }​
108 ​
109 int SetupTicker(void)​
110 {​
111 int Status;​
112 XTtcPs *TtcPsTick;​
113 ​
114 Status = IniTimer(TTC_TICK_DEVICE_ID);​
115 if(Status != XST_SUCCESS) {​
116 return Status;​
117 }​
118 ​
119 TtcPsTick = &(TtcPsInst[TTC_TICK_DEVICE_ID]);​
120 ​
121 Status = XScuGic_Connect(&InterruptController, TTC_TICK_INTR_ID,​
122 (Xil_ExceptionHandler)ttc_InterruptHandler, (void *)TtcPsTick);​
123 if (Status != XST_SUCCESS) {​
124 return XST_FAILURE;​
125 }​
126 ​
127 XTtcPs_SetStatusHandler(&(TtcPsInst[TTC_TICK_DEVICE_ID]), &(TtcPsInst[TTC_TICK_DEVICE_ID]),​
128 (XTtcPs_StatusHandler)TickHandler);​
129 ​
130 //使能定时计数器中断​
131 XScuGic_Enable(&InterruptController, TTC_TICK_INTR_ID);​
132 ​
133 XTtcPs_EnableInterrupts(TtcPsTick, XTTCPS_IXR_INTERVAL_MASK);​
134 ​
135 XTtcPs_Start(TtcPsTick);​
136 ​
137 return Status;​
138 }​
139 ​
140 //配置TTC​
141 int IniTimer(int DeviceID)​
142 {​
143 //int Status;​
144 XTtcPs_Config *Config;​
145 XTtcPs *Timer;​
146 ​
147 Timer = &(TtcPsInst[DeviceID]);​
148 ​
149 //查找配置​
150 Config = XTtcPs_LookupConfig(DeviceID);​
151 ​
152 //初始化ttc​
153 XTtcPs_CfgInitialize(Timer, Config, Config->BaseAddress);​
154 ​
155 XTtcPs_SetOptions (Timer, 0x24); //设置Option​
156 ​
157 //设置Interval​
158 XTtcPs_SetInterval (Timer, 50000000); //每隔500ms产生中断,led灯间隔1s亮灭一次​
159 ​
160 //设置Prescaler​
161 XTtcPs_SetPrescaler (Timer, 0); //不分频,默认输入100Mhz​
162 ​
163 return XST_SUCCESS;​
164 }​
165 ​
166 static int SetupInterruptSystem(u16 IntcDeviceID, XScuGic *IntcInstancePtr)​
167 {​
168 int Status;​
169 XScuGic_Config *IntcConfig;​
170 ​
171 IntcConfig = XScuGic_LookupConfig(IntcDeviceID);​
172 if (NULL == IntcConfig) {​
173 return XST_FAILURE;​
174 }​
175 ​
176 Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,​
177 IntcConfig->CpuBaseAddress);​
178 if (Status != XST_SUCCESS) {​
179 return XST_FAILURE;​
180 }​
181 ​
182 Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,​
183 (Xil_ExceptionHandler) XScuGic_InterruptHandler,​
184 IntcInstancePtr);​
185 ​
186 Xil_ExceptionEnable();​
187 ​
188 return XST_SUCCESS;​
189 }​
190 ​
191 static void TickHandler(void *CallBackRef, u32 StatusEvent)​
192 {​
193 ​
194 }

在代码的19行定义了MIO_LED为38,即PS_LED连接到MIO的38号引脚上。然后在代码的第44行至第65行对MIO进行初始化,并将MIO38设置为输出。

代码的第68行至第87行定义了中断处理函数。在函数中首先定义一个led_state变量,并赋初始值0,每当中断发生时,对led_state的值进行翻转,并将翻转后的值写到MIO38引脚。

在程序的main函数中,首先对GPIO进行初始化,然后在程序的第96行调用中断函数。中断函数在代码的第166行至第189行。在中断函数的第171行,根据器件ID查找GIC的配置,然后在代码的第176行对GIC进行初始化。在代码的第182行至第186行,设置并使能中断异常。

main函数中第102行调用了SetupTicker函数,该函数主要完成TTC中断的配置以及定时器的配置。第114行的SetupTicker函数中调用了IniTimer定时器配置函数。TTC使用系统输入的100Mhz时钟,这里不对系统时钟进行分频,所以分频系数设置为0,如代码的第161行所示。

由于实验任务是led灯间隔1s亮灭一次,所以每隔500ms改变一次led灯的状态。时钟周期是10ns,因此可以计算出定时器Interval的值是50_000_000 (500_000_000/10),如代码第158行所示。

下载验证

首先我们将下载器与开发板上的JTAG接口连接,下载器另外一端与电脑连接。然后使用USB连接线将USB_UART接口(开发板右上角PS PORT)与电脑连接,用于串口通信。最后连接开发板的电源,给开发板上电。

打开Vitis Terminal终端,设置连接串口。然后下载本次实验程序下载完成后,在下方的Terminal中可以看到应用程序打印的信息Successfully ran TTC Interrupt Test”,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第九章 定时器中断实验​_#include_09


9.5.1 程序打印结果

接下来观察开发板,可以看到PS_LED1每隔200ms亮灭一次,如9.5.2所示,本次实验在MPSOC开发板上面下载验证成功。

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第九章 定时器中断实验​_快捷键_10


9.5.2 开发板实验现象

在线调试

至此,定时器中断实验的讲解已经结束。最后,我们来教大家如何对代码进行调试。

在应用工程timer_intr_led上右击,选择“Debug As”,然后选择第一项“1 Launch on Hardware (System Debugger)”,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第九章 定时器中断实验​_快捷键_11


9.6.1 打开调试界面

进入下图所示的调试界面,程序首先从main函数开始运行,如程序第116行所示。

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第九章 定时器中断实验​_快捷键_12


9.6.2 开始调试界面

9.6.2标注为1的位置是用于调试的工具栏;标注为3的位置可以观察程序中变量的值;标注为2的位置即为我们所要调试的代码,图中高亮的代码行就是接下来将要执行的代码。

我们来详细看下用于调试的工具栏界面,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第九章 定时器中断实验​_#include_13


9.6.3 工具栏

9.6.3标注为1的图标表示程序继续运行(Resume,快捷键F8);标注为2的图标表示暂停(Suspend,只有程序在运行时才可以点击);标注为3的图标表示单步执行(Step Into,快捷键F5);标注为4的图标表示单步执行结束(Step Over,快捷键F6);标注为5的图标表示执行完并返回(Step Return,快捷键F7)。同时,也可以点击菜单栏的Run,找到调试按钮,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第九章 定时器中断实验​_快捷键_14


9.6.4点击Run界面

我们首先打开Vitis Serial Terminal窗口的界面并点击右上角“+”设置串口,以便于观察程序调试的结果,如下图所示。如果不小心把Terminal窗口关掉了,需要点击工具栏Window->Show view,然后在弹出的窗口中输入Terminal搜索并打开串口终端。

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第九章 定时器中断实验​_快捷键_15


9.6.5 窗口打印界面

接下来开始调试代码。点击Step Over图标或者按下快捷键F6来执行代码,执行MIO初始化函数mio_init()。接下来点击Step Info图标或者按下快捷键F5,跳转进入SetupInterruptSystem()函数,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第九章 定时器中断实验​_快捷键_16


9.6.6 跳转至SetupInterruptSystem()函数

接下来可以继续按F5单步执行。如果此时想迅速跳出SetupInterruptSystem()函数,可以直接点击Step Return或者按下快捷键F7,跳转结果如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第九章 定时器中断实验​_引脚_17


9.6.7 跳出函数

调试界面支持设置断点,直接双击行号前面蓝色区域的位置设置断点,再次双击可取消断点。如在第126行位置设置断点,双击第126行前面蓝色区域的位置,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第九章 定时器中断实验​_引脚_18


9.6.8 设置断点

接下来点击Resume图标或者按下快捷键F8,程序可执行至断点位置,如下图所示:

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第九章 定时器中断实验​_引脚_19


9.6.9 程序执行至断点处

再次双击第126行前面蓝色区域的位置可取消断点。此时继续点击Resume图标或者按下快捷键F8,程序会一直执行下去,此时可以看到串口打印信息“Successfully ran TTC Interrupt Test”,并且开发板上的PS_LED1每隔200毫秒亮灭一次。如果想要暂停程序的执行,点击Suspend图标即可。

如果要退出Debug界面,点击下图中的图标即可。

《DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南》第九章 定时器中断实验​_引脚_20


9.6.10 退出Debug界面


举报

相关推荐

0 条评论