米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验

软件版本:VIVADO2017.4

操作系统:WIN10 64bit

硬件平台:适用米联客 ZYNQ系列开发板

米联客(MSXBO)论坛:www.osrc.cn答疑解惑专栏开通,欢迎大家给我提问!!

7.1 概述

本课节对ZYNQ的中断进行了介绍,并通过PL端按键输入中断信号,PS端进行处理,讲解了外部中断使用。

7.2 ZYNQ 中断介绍

7.2.1 ZYNQ中断框图

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第1张图片

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第2张图片

      上图为ZYNQ中断分布框图。可以看到部分PL到PS部分的中断,经过中断控制分配器(ICD),同时进入CPU1 和CPU0。查询下面表格,可以看到PL到PS部分一共有20个中断可以使用。4个快速中断(PPI),即IRQF2P[19:16];16个共享中断(SPI),即IRQF2P[7:0]、IRQF2P[15:8]。这16个中断可以任意定义,本课涉及使用。

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第3张图片

7.2.2 ZYNQ CPU软件中断 (SGI)

ZYNQ共有两个CPU,每个 CPU具备各自的16个软件中断。

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第4张图片

7.2.3 ZYNQ CPU 私有端口中断

私有中断不能修改。这里有2个PL到CPU的快速中断nFIQ

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第5张图片

7.2.4 ZYNQ PS和PL共享中断

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第6张图片

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第7张图片

共享中断就是PL的中断可以发送给PS处理。上图中,黄色区域是16个PL的中断,它们可以设置为高电平或者低电平触发。

7.3 搭建BD工程

Step1:新建一个名为为Miz_sys的工程。

Step2:创建一个BD文件,并命名为system,添加并且配置好ZYNQ IP。读者需要根据自己的硬件类型配置好输入时钟频率、内存型号、串口,连接时钟等。新手不清楚这些内容个,请参考“CH01 HelloWold/DDR/网口测试及固化”这一节课。

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第8张图片

7e7687a5b0d8e7a521d1a7c0f66f6659fad.jpg

 

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第9张图片

Step4:单击添加IP按钮,添加两个逻辑门(vector)和一个连接(concat)IP。

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第10张图片

e2b9d9ee7bd45e9b2e627747dbc453d1042.jpg

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第11张图片

Step6:如图所示,完成整体电路。

SW1(端口) 连接Op1(util_vector_logic_0);

SW2(端口) 连接Op1(util_vector_logic_1);

Res(util_vector_logic_0) 连接In0(xconcat_0);

Res(util_vector_logic_1) 连接In1(xconcat_0);

dout(xconcat_0) 连接 IRQ_F2P(ZYNQ7);

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第12张图片

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第13张图片

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第14张图片

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第15张图片

Step5:单击窗口上的运行按钮,运行程序。

7.6 实验结果

分别按下SW1和SW2按钮,系统运行结果如下图所示:

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第16张图片

7.7 程序分析

分析1

语句IntcInitFunction(INTC_DEVICE_ID);

含义:中断初始化

具体分析

                输入参数

       IntcInitFunction函数输入参数:INTC_DEVICE_ID。选中这个参数跟踪(按F3),找到定义,即“#define INTC_DEVICE_ID          XPAR_PS7_SCUGIC_0_DEVICE_ID”。这个参数是系统中断设备ID基地址的宏定义,即中断的基地址。

        定义

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第17张图片

1、程序开始定义需要用到的指针和变量。

         XScuGic_Config *IntcConfig;

         int status;

2、查找设备配置的程序,参数为设备ID。查看中断向量是否存在。当执行完下面的程序,系统会对中断做一些初始化,如果初始化成功,会返回一个XST_SUCCESS的标志。当未检测到返回到这个初始化成功的标志时,系统会返回一个XST_FAILURE标志。

      IntcConfig = XScuGic_LookupConfig(DeviceId);

      status = XScuGic_CfgInitialize(&INTCInst, IntcConfig, IntcConfig->CpuBaseAddress);

      if(status != XST_SUCCESS) return XST_FAILURE;

3、接下来是一个中断注册函数Xil_ExceptionRegisterHandler,查看其函数定义。“注册特定异常的处理程序。处理器遇到指定的异常时会调用此处理程序”。

         u32 Exception_id:异常源ID,范围:0~XIL_EXCEPTION_ID_LAST(更多相关信息,请参阅xil_exception.h)。这里可以理解为中断类型。

         Xil_ExceptionHandler Handler:处理异常的处理程序。

        void *Data:被调用时,传递给Handler的数据引用。

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第18张图片

从上面可以看出这个函数是把中断句柄和中断参数放到数组中,选中函数按下F3查看。

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第19张图片

数组类型为XExc_VectorTableEntry,这个结构体定义如下图所示:

3b013bc67a4eb812c2c5674c2dd8f561988.jpg

4、连接interrupt和handler,即连接中断到中断处理函数。

       查看XScuGic_Connect定义。注释中描述其功能:“使中断源的Int_Id与识别中断时要运行的关联处理程序之间建立连接”。 XScuGic_Connect函数的最后两个函数,把中断的句柄和一个指针变量传递了进来。

           // Connect SW1~SW2 interrupt to handler

           status = XScuGic_Connect(&INTCInst, SW1_INT_ID, (Xil_ExceptionHandler)SW_intr_Handler, (void *)1);           

           if(status != XST_SUCCESS) return XST_FAILURE;

 

           status = XScuGic_Connect(&INTCInst, SW2_INT_ID,

           (Xil_ExceptionHandler)SW_intr_Handler, (void *)2);

           if(status != XST_SUCCESS) return XST_FAILURE;

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第20张图片

此时返回查看XScuGic_Connect函数,发现中断句柄是一个指针函数,当程序被执行时,被调用的是这个指针函数,此时跟踪这个指针函数,查看其具体内容。

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第21张图片

通过程序开头xilinx给出的这个程序的注释可以知道:这个函数是基本的中断驱动函数。它必须连接到中断源,以便在中断控制器的中断激活时被调用。 它将解决哪些中断是活动的和启用的,并调用适当的中断处理程序。它使用中断类型信息来确定何时响应中断。首先处理最高优先级的中断。此函数假定中断向量表已预先初始化。它不会在调用中断处理程序之前验证表中的条目是否有效。

上面讲到的这个中断向量表其实也就是下图所示的部分。

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第22张图片

这部分在刚才已经进行了讲解了,此时我们就可以清楚的知道这就是一个中断向量表了。

回到基本的中断驱动函数的分析,看到下面的一段程序:

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第23张图片

通过注释我们知道了这个程序是读取int_ack寄存器以识别最高优先级的中断ID,并确保其有效。 读取Int_Ack将清除GIC中的中断。然后看看读出来的中断ID是否大于最大的中断值。查看下这个最大的中断值。

5c8325e8c86ca9d0bd838f60828d1c053ec.jpg

从上图中圈出的地方可以看到,当使用ZYNQ的时候,最大有95个中断可以供我们使用。当读出来的这个中断值大于95U的话,就直接跳转到异常处理程序部分:

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第24张图片

这里的意思也就相当于恢复中断寄存器,相当于出栈。

当读出来的中断值是正常的话,就会查找这个中断的中断向量表,如果这个向量表不是非空的话,就开始处理这个中断,也就是开始执行之前的连接中断的函数。此部分程序如下:

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第25张图片

上图中的Tableptr指向的CallBackRef其实就是我们连接中断函数定义的无符号的数字,如下图所示。

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第26张图片

为了验证我们的猜想,我们可以把这里的数字改成其他的值进行验证。

5、

回到主程序当中,接着看到这段函数:

f8bc8842b0656b594835210ec49f14ba1c0.jpg

这段程序把中断的触发类型设置为了上升沿触发。

4a0a56c20326b1ec0e9a9cd7c1405a62533.jpg

这段程序使能了中断。

6、

整段程序下来,那么主要是执行了哪个函数呢?通过上面的分析,我们可以判定其实是下面这个函数:

621cacf741ffbe2c0505a86b3cf3ab15405.jpg

这个函数的方框部分其实是个指针函数,我们可以跟踪看一下其定义。

f811244bdcbd55358ecd895408862e6b81a.jpg

       一开始,它将传递进来的指针传递给了sw_id,然后会打印哪个按钮初始化,其实也就是哪个中断被触发了。

       接下来,我们再对中断的一些寄存器做一些分析。在中断设置里的一些寄存器是比较重要的,我们就来分析一下中断设置里的寄存器。

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第27张图片

将鼠标停留在图上圈出的函数上,SDK会跳出关于这个函数的信息,在跳出的窗口中左边是我们圈出的这个函数的定义,右边则是在执行过程中实际运行的程序。我们拷贝出右边这个函数来分析一下:

       ((Xil_In32((((InstancePtr)->Config->DistBaseAddress)) + ((0x00000C00 + (intId/16)*4)))))

       红色部分是一个指针,它调用了config里的一个基地址DisBaseAddress,后半部分我们可以断定这是一个寄存器地址,因为这个函数就是一个读取中断寄存器的函数。此时,我们跟踪一下这个函数。

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第28张图片

       此时,我们就知道了第一个参数是一个指向要处理的中断的指针,第二个是寄存器偏移。我们就来计算一下这个寄存器偏移。首先我们来看看中断的基地址是多少(也就是红色部分指向的基地址)。

096c3116f77f195fbad93a57e1e32b02f2f.jpg

51590dcce3a8a0a9eb28bd770f9c8ab6666.jpg

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第29张图片

米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验_第30张图片

 

转载于:https://my.oschina.net/msxbo/blog/3098561

你可能感兴趣的:(米联客 ZYNQ/SOC精品教程 S02-CH07 PL中断请求实验)