米联客 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中断框图

2d06cb5b3084f9439c067ca5ecd957faab3.jpg

5bf8c6a411f99ec25f1a8766b24cde10516.jpg

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

15001ded9d4e6ac707333654b88ccdf5e5a.jpg

7.2.2 ZYNQ CPU软件中断 (SGI)

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

3c62fae71ca5959bc3eca76a151129a1c67.jpg

7.2.3 ZYNQ CPU 私有端口中断

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

bae13c5c0ba33cd9210bfabdfd28d5e8dff.jpg

7.2.4 ZYNQ PS和PL共享中断

4697667e53d0069a18c02b1c6aa1409ec5f.jpg

610137e50476253ba72099db14cb4f151b5.jpg

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

7.3 搭建BD工程

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

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

7a09b80c369f99fe6ebce2b041df3f2bc84.jpg

7e7687a5b0d8e7a521d1a7c0f66f6659fad.jpg

 

5b5623cf1b17a84fe0f712f12a3665e6163.jpg

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

1b603942c4ba9c436cd733d45b7461ab854.jpg

e2b9d9ee7bd45e9b2e627747dbc453d1042.jpg

2e37da4bceaea9cc4465ecb942d0545bf13.jpg

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);

dfc22cf68f2666a21cdaab44d0a7253d08f.jpg

9c6a4eda4e175557cef136b3415328b8ac6.jpg

f6b15e6c9ce2d9e79e60ecbb5278ec85e24.jpg

09581a442005100b24b97ead3b0acdd7f71.jpg

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

7.6 实验结果

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

536b0c26a160974736232c1f40e00769929.jpg

7.7 程序分析

分析1

语句IntcInitFunction(INTC_DEVICE_ID);

含义:中断初始化

具体分析

                输入参数

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

        定义

ccd2cf56b1547975c41baadb4dfb909b4d2.jpg

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的数据引用。

ac51229791bb383b80752b85191f1ea5cec.jpg

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

be39cf5b048c6081d282cea0e76c3add8ab.jpg

数组类型为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;

96494a2372c55c3de394f5ad6a0c45c7b9a.jpg

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

37f3463767dde334279daf7e75ada50743b.jpg

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

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

68234fcd1dddc07591c740104bef14bd918.jpg

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

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

7d11a2d89921800c7b6e3a3615f25112650.jpg

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

5c8325e8c86ca9d0bd838f60828d1c053ec.jpg

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

2882ca16b163d1f55e5e009c82bd8ecf4cf.jpg

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

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

a4a02594460cf18db8cf875a2182dcb002d.jpg

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

c33760bfa0ecac3561bb484a4de202f1f0e.jpg

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

5、

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

f8bc8842b0656b594835210ec49f14ba1c0.jpg

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

4a0a56c20326b1ec0e9a9cd7c1405a62533.jpg

这段程序使能了中断。

6、

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

621cacf741ffbe2c0505a86b3cf3ab15405.jpg

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

f811244bdcbd55358ecd895408862e6b81a.jpg

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

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

77912bc3124455272e1996f3f0259de4c18.jpg

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

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

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

8a496cebeb50274b5f6d7255f97d14d8160.jpg

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

096c3116f77f195fbad93a57e1e32b02f2f.jpg

51590dcce3a8a0a9eb28bd770f9c8ab6666.jpg

a5757585cbe0afb6f44333b6b22977d9baf.jpg

9f1a6c642ad268678f6fa172784d1867679.jpg

 

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值