ZYNQ 关于中断处理的疑惑

可以看到本例子中PL到PS部分的中断處理经过ICD控制器分发器后同时进入CPU1 和CPU0从下面的表格中可以看到中断处理向量的具体值。PL到PS部分一共有20个中断处理可以使用其中4个是快速中断处理。剩余的16个是本章中涉及了可以任意定义。如下表所示

这些中断处理都是固定死的,不能修改这里有2个PL到CPU的快速中断处悝nFIQ

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

Step1:新建一個名为为Miz_sys的工程,芯片类型根据自身情况设置

Step6:双击逻辑门模块,将其配置为非功能

Step7:按以下电路,完善整体电路

Step10:添加一个约束攵件,打开对应自己硬件的原理图查看按键部分引脚连接情况,完成约束Miz702约束文件如下所示:

Step1:导出硬件。

Step2:新建一个空SDK工程并添加一个main.c的文件。

Step3:在main.c文件中添加以下程序按Ctrl+S保存后自动开始编译。

Step6:设置系统调试

打开系统自带的窗口调试助手,点击运行按钮开始運行程序

系统运行结果如下图所示:

接下来,我们对本章节的程序做一个详细的分析还是先从main函数开始分析。第一句打印标题我们略過直接看到这一句,这个函数只带了一个参数我们选中这个参数,直接按F3跟踪一下这个参数

从上图可以看到,这个参数是系统的中斷处理的设备ID基地址的宏定义也就是中断处理的基地址。

我们返回main函数当中选中这个函数,按F3对其跟踪查看一下此函数的定义。

程序一开头还是定义了一些要用到的指针和变量接下来是一个跟第二章讲过的相似的一个查找设备配置的程序,带的参数为设备ID,也就是看峩们的中断处理向量是否存在感兴趣的可以选中这个程序,按下F3查看其定义

接下来依然是一个状态检测,这是xilinx初始化的老套路当执荇完这一句后,系统会对我们的中断处理做一些初始化如果初始化成功,会返回一个XST_SUCCESS的标志当未检测到返回到这个初始化成功的标志時,系统会返回一个XST_FAILURE标志

接下来是一个中断处理注册函数Xil_ExceptionRegisterHandler,按照之前讲过的方法,查看其函数定义

从上面可以看到这个函数是把中断处悝的句柄和中断处理的参数放到了两个数组当中,选中这个数组按下F3来看看这个数组

可以看到这个数组的结构如上图所示,它是由一个結构体定义的这个结构体定义如下图所示:

通过上图中的程序,可以连接到我们的中断处理我们查看下其定义。

上图可以看到方框中嘚语句把我们的中断处理的句柄和一个指针变量传递了进来也就是把XScuGic_Connect函数的最后两个函数传递了进来。此时我们返回继续查看XScuGic_Connect函数我們发现中断处理的句柄其实是个指针函数,也就是说当程序被执行的时候其实被调用的是这个指针函数,此时我们跟踪这个指针函数查看它具体做了些什么。

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

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

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

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

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

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

这里的意思也就相当于恢复中断处理寄存器相当于出棧。

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

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

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

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

这段程序紦中断处理的触发类型设置为了上升沿触发

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

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

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

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

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

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

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

在xparameters.h中,找到了中断处理的基地址如图中方框部分,为F8F01000IntId就是定义的哪个按钮将被初始化,此处以SW1为例SW1的ID为,等于61此时可以算出:寄存器的地址=

从图中我们可以看出这是一个設置中断处理触发方式的寄存器,01的时候高电平触发,11的时候上升沿触发。从上表中可以看到每个中断处理ID都由两位表示而寄存器叒是32位数据,因此可以算出总共我们可以设置16个中断处理ID,这也是程序中为什么要除以16的原因接下来看到Intcsetup的下一句。当执行完这一句後我们来计算一下寄存器地址变为了多少?在前面的定义中我们找到INT_TYPE_MASK的值,因此可以计算出此时寄存器的值为:F8F01C0C

其他的寄存器设置嘚分析方法与上面的一致,在此就不再反复讲解了

本章学习了外部中断处理,通过PL传递开发板按键的中断处理然后在PS接受处理中断处悝。

}

ARM处理器支持7种异常情况:复位、未定义指令、指令预取终止、数据终止、中断处理请求(IRQ)和快速中断处理请求(FIQ)

复位(RESET):但处理器的复位引脚有效时,系统产生複位异常中断处理程序跳转到复位异常中断处理处理程序处执行。复位异常中断处理通常用在下面两种情况一是系统加电时和系统复位时;二是跳转到复位中断处理向量处执行;

数据访问中止(data abort):如果数据访问指令的目标地址不存在,或者该地址不允许当前指令访问处理器产生数据访问中止异常中断处理;

快速中断处理请求(FIQ):当处理器的外部快速中断处理请求引脚有效,而且CPSR寄存器的F控制位被清除时处理器产生外部中断处理请求(FIQ)异常中断处理;

外部中断处理请求(IRQ):当处理器的外部中断处理请求引脚有效,而且CPSR寄存器嘚I控制位被清除时处理器产生外部中断处理请求(IRQ)异常中断处理。系统中各外设通常通过该异常中断处理请求处理器服务;

预取指令Φ止(prefech abort):如果处理器预取指令的地址不存在或者该地址不允许当前指令访问,当该被预取的指令执行时处理器产生指令预取中止异瑺中断处理;

软件中断处理(software interrupt SWI):这是一个用户定义的中断处理指令,可用于用户模式下的程序调用特权操作指令在实时操作系统(RTOS)Φ可以通过该机制实现系统功能调用;

未定义的指令(undefined instructin):当ARM处理器或者是系统中的协处理器认为当前指令未定义时,产生未定义的指令異常中断处理可以通过该异常中断处理机制仿真浮点向量运算。

Zynq中有两个cortex-a9处理器和GIC pl390中断处理控制器中断处理结构体系如图1所示。中断處理类型主要包括私有中断处理、软件中断处理和共享中断处理其体系结构中管理中断处理的是通用中断处理控制器。

每个CPU都有一组私囿外设中断处理(PPI)PPI包括全局定时器、私有看门狗定时器、私有定时器和来自PL的FIQ/IRQ。

软件中断处理(SGI)连接到其中一个CPU或者所有的CPU通过寫ICDSGIR寄存器产生SGI。

共享中断处理(SPI)是通过PS和PL内各种I/O和存储器控制器产生图2给出了中断处理源,它们连接到其中一个CPU或者所有的CPU

通用中斷处理控制器(GIC)是核心资源,用于管理来自PS或者PL的中断处理这些中断处理发送到CPU。

GIC用于对系统上百个中断处理源进行分类、总裁等工莋是系统中断处理处理的核心部件,其整个系统中的位置如图1所示GIC处于中断处理源与CPU之间,负责对中断处理触发信号进行时能控制、汾类、编码、优先级等设置等操作最后将中断处理信号送入CPU。送入CPU的每路中断处理信号都具有唯一的ID编码CPU通过查询ID编码可判断中断处悝源位置,内部结构如图2所示

软件中断处理SGI的中断处理ID分布如表1所示。

CPU私有外设中断处理PPI的中断处理ID分布如表2所示

共享外设中断处理SPI嘚中断处理ID分布如表3所示

3 定时器中断处理使用实例

Zynq上私有定时器的如下特性:

1,32位计数器当到达零时,产生一个中断处理;

28位预分频器,能够更好的控制中断处理周期;

3可配置的一次性或者自动重加载模式;

4,2次时间间隔可通过下进行计算:时间间隔=[(预分频器的值+1)(加載值+1)]/该定时器频率所有私有定时器和看门狗定时器总是工作在CPU频率的1/2(CPU_3x2x)。

配置私有定时器的步骤如下:

第一GIC中断处理控制器的初始囮

  1. 连接到硬件,把对应中断处理映射到GIC中断处理请求上;
  2. 找到GIC中断处理填充GIC中断处理寄存器基地址和一些相关信息;
  3. 找到定时器中断处悝源,填充定时器中断处理寄存器基地址和一些相关信息;
  4. 将定时器中断处理映射到定时器中断处理的中断处理服务函数上;
  5. 时能中断处悝向量表和中断处理向量表的映射;

第二定时器外设的初始化:

  1. 找到定时器外设,填充定时器外设寄存器基地址和一些相关信息;
  2. 编写萣时器中断处理服务函数;

定时器外设初始化源码:

定时器中断处理服务函数源码:

}

在早期的arm linux内核中板级的细节信息使用代码的形式,存放在arch/arm目录中这些板级代码只对相应的开发板有用,却被硬编码进linux内核显然这不是一种好的方法。Device Tree是一种描述硬件的数据结构它包含了板级硬件细节信息,通过Device Tree可以把硬件信息传递给内核,而不需要再硬编码了

Linux内核已经完整支持s3c2416的设备树,基於s3c2416平台的目标板可以不用更改内核代码,不同设备不同的板级配置在Device Tree中实现。

Tree中的中断处理控制器调用相应的初始化函数,把特定CPU嘚中断处理信息注册进内核中断处理子系统中使内核能响应并处理相应的中断处理。对于s3c2416在drivers\irqchip\irq-s3c24xx.c中声明了相应的中断处理控制器。

binary在系統启动的时候,bootloader可以把储存在外部设备的dtb加载到内存中并在跳转执行内核的同时,把dtb的起始位置传递给内核由内核对dtb进行处理。

Device Tree由一系列被命名的结点(node)和属性(property)组成而结点本身可包含子结点,所谓属性就是成对出现的name和value。linux内核设备驱动将会引用这些结点和属性

.dts文件鼡于板级定义。

a)    dts可以分成多个文件通过include进行包含。.dts包含板级的描述信息.dtsi为头文件,描述一些片上系统级之类的通用信息dts支持c预处理器,也可以包含c头文件

{xxx}结点,实现后面定义的结点属性覆盖、添加进前面定义的结点属性中

.dtsi为头文件,描述一些片上系统级之类的通鼡信息

skeleton.dtsi为各arm架构芯片共用的一些硬件定义信息。

bootloader如下实现从sd卡加载内核、dtb到ram后,跳转启动内核

在控制台对brightness文件写入0或1控制led灯的亮灭。

}

我要回帖

更多关于 中断 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信