本文以XIlinx ZCU102 UltraScale+ MPSoC作为实例,总结在学习嵌入式开过程中对中断系统或机制的理解。
ZYNQ其中包含FPGA、 Arm处理器以及与之相关的外设,是一款非常强大的SoC系统芯片。由于在科研项目中需要基于ZCU102开发一套数据传输系统用于粒子物理实验探测器前端数据的处理和传输。常规的方法便是完全直接通过FPGA(Programmable Logic, PL)进行汇编语言实现数据的存储和高速传输,而本课题尝试采用Programmable Logic(PL)和Process System(PS)协同开发数据获取系统。作为从未接触过FPGA开发或者嵌入式协同设计的物理学方向的研究僧,自学并尝试该设计实属不易,作此文为了更好记录学习过程。在最后以DMA中断循环做实例介绍。
什么是中断?
中断是计算机发展中一个重要的技术,它的出现很大程度上解放了CPU,提高了CPU的执行效率。
在中断出现之前,CPU对IO采用的是轮询的方式进行服务,这使的CPU纠结在某一个IO上,一直在等待它的响应,如果它不响应,CPU就在原地一直的等下去。这样就导致了其他IO口也在等待CPU的服务,如果某个IO出现了important or emergency affairs,CPU也抽不出身去响应这个IO。为了解决这个纠结的问题就------>出现了中断
中断控制的主要优点是只有在IO接口需要服务时才去响应它,使得CPU很淡定的做它自己的事情,只有IO口有需求的时候才去响应它。同时中断中也设计了中断优先级,来处理一些很紧急的事件。在任何的嵌入式系统设计中都离不开中断机制的使用,一般意思为处理器在运行程序过程中,遇到外部信号的干预(中断信号),致使处理器停止当前的程序运行,转而运行由中断指定的程序(函数),中断服务函数执行完毕后再返回主程序中执行先前暂定的程序。
1.所谓中断,是指CPU在正常运行程序时,由于程序的预先安排或内外部事件,引起CPU中断正在运行的程序,而转到发生中断事件程序中。这些引起程序中断的事件称为中断源。
其实从 物理学的角度看,中断是一种电信号,由硬件设备产生,并直接送入中断控制器(如 8259A)的输入引脚上,然后再由中断控制器向处理器发送相应的信号。处理器一经检测到该信号,便中断自己当前正在处理的工作,转而去处理中断。此后, 处理器会通知 OS 已经产生中断。这样,OS 就可以对这个中断进行适当的处理。不同的设备对应的中断不同,而每个中断都通过一个唯一的数字标识,这些值通常被称为中断请求线。
2.那么 当产生一个中断时,CPU是如何识别的呢?为了使处理器能识别每种中断源,给它们进行了编号----->叫做中断向量。比如在ZCU102中xczu9eg芯片支持:私有中断(每个CPU连接5个私有中断,中断ID27—31), 软件中断(16个,中断号:0—15。通过CPU私有总线向ICDSGIR寄存器写中断号,并且制定CPU), 共享中断(接收来自如GPIO、DMA、定时器等模块的中断信号。中断号32-95)。
3.异常和中断的区别:
1>异常:是指CPU内部出现的中断,即在CPU执行特定指令时出现的非法情况。同时异常也称为同步中断,因此只有在一条指令执行后才会发出中断 ,不可能在指令执行期间发生异常。
- 产生的原因:
程序的错误产生的(eg:除数为0)
内核必须处理的异常条件产生的(eg:缺页)
- 异常又分为故障和陷阱,它们都不使用中断控制器,也不能被屏蔽
- X86处理处理器中大约有20中异常。Linux内核必须为每种异常提供一个专门的异常处理程序。
2>中断:也称为异步中断。因此它是由其他硬件设备依照 CPU 时钟信号随机产生,即意味着中断能在指令之间发生。
- 中断又分为外部可屏蔽中断(INTR)和外部非屏蔽中断(NMI)
所用I0设备产生的中断请求均引起可屏蔽中断
硬件故障引起的故障则产生非屏蔽中断。
在CPU执行一个异常处理程序时,就不再响应其他异常和中断请求服务.那么如果此时发生了一个异常,CPU不能去响应它,又不能把它的信息丢失该怎么办呢?
这是就用到了堆栈,把所有的信息压入栈。等当前异常处理后,才从堆栈中取出信息再响应刚才的异常。(当产生多个非屏蔽中断时,CPU的处理方法同上)
ARM和ZYNQ中断机制
-
Arm中断体系
ARM体系中,在存储地址的低位,固化了一个32字节的硬件中断向量表。异常中断发生时,程序计数器PC所指的位置不同,异常中断就不同。中断结束后,中断不同,返回地址也不同。但是,对于系统复位中断,不需要返回,因为整个应用系统就是从复位中断中开始的。ARM通常存在七种基本的中断处理(异常处理机制)。
数据访问终止:数据访问的地址不存在,或者当前地址不允许访问。
快速中断请求:外部引脚的快速中断请求,比外部中断请求等级高,但是一般外设的中断请求使用外部中断请求。
指令预取终止:预取指令的地址不存在,或者当前地址不允许访问。
未定义的指令:ARM或协处理器认为当前指令未定义。ARM基本中断流程如下图所示。从图中明显可以看出,在主程序中发生IRQ中断请求,程序跳转到中断向量表中查找IRQ中断对应的解析程序地址,也就是根据地址进入到中断服务函数(中断解析程序),执行服务函数之后将中断返回,并最终返回进入到主程序。
-
ZYNQ中断体系
ZYNQ芯片中包含有Programmable Logic和Processing System,因此其中包含丰富的中断系统,私有中断: 每个CPU连接着5个私有中断,中断ID分别为27-31.
软件中断:总共有16个,中断号:0—15。通过CPU私有总线向ICDSGIR寄存器写中断号,并且制定CPU。
共享中断:接收来自如GPIO、DMA、定时器等模块的中断信号。中断号32-95。
所有中断的关系如下图所示:
ZYNQ中断过程实现
中断系统的使用总是与相应的设备相联系的通用中断控制器(GIC)初始化和配置, 连接GIC、中断ID和回调函数, 使能中断, Arm中断异常处理。下面是DMA环通测试例子:
其中XAxiDma_Setup是最主要的函数,包括DMA设备配置信息;SetupInterruptInt是中断系统设置函数,包含XScuGic通用中断控制器的配置,连接DMA 中断和中断服务函数,Arm异常处理;CheckData是中断服务函数,每次主程序中断后,将执行此函数。
#include "xaxidma.h"
#include "xparameters.h"
#include "xil_printf.h"
#include "xscugic.h"
#define DMA_DEV_ID XPAR_AXIDMA_0_DEVICE_ID
#define INT_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define INTR_ID XPAR_FABRIC_AXI_DMA_0_S2MM_INTROUT_INTR
#define FIFO_DATABYTE 4
#define TEST_COUNT 80
#define MAX_PKT_LEN TEST_COUNT*FIFO_DATABYTE
#define TEST_START_VALUE 0xC
<