大家好,欢迎来到IT知识分享网。
一、引言
中断是一种当满足要求的突发事件发生时通知处理器进行处理的信号。中断可以由硬件处理单元和外部设备产生,也可以由软件本身产生。
对硬件来说,中断信号是一个由某个处理单元产生的异步信号,用来引起处理器的注意。
对软件来说,中断还是一种异步事件,用来通知处理器需要改变代码的执行,不过轮询所产生的中断的过程是同步的。
二、AXI INTC
AXI Interrupt Controller,为中断控制器IP,能将外围的多个中断输入,集中到单个中断输出,再将中断传输给系统处理器。AXI 规范的从属接口访问用于检查,启用和确认中断的寄存器。
AXI INTC(中断控制器)具有以下特点:
- INTC可以通过 AXI4-Lite 接口访问,最高支持 32 个中断,中断控制器之间可以级联产生其他的中断信号并且支持快速中断模式。
- 中断控制器的每个输入或输出都可以配置为电平或边缘敏感。中断信号间的优先级由向量的位决定,最低有效位(LSB,在本例中为位 0)具有最高优先级。
- 中断控制器中包含中断使能寄存器,能够有选择地使能单个中断输入。该 IP 也可以配置软件中断功能,还能中断嵌套。
下图为 AXI INTC IP 核的顶层框图。 AXI INTC IP 核主要功能就是接收外部输入的中断信号,检测到中断后,输出一个中断请求信号,而且处理系统可以通过 AXI 接口对 AXI INTC IP 核进行配置。
下面简单介绍 AXI INTC IP 核的主要模块:
- Regs Block( Registers Block 即寄存器模块): 此模块包含控制寄存器和状态寄存器。它们都通过AXI4-Lite 从接口访问,每个寄存器均为四字节。
- Int Det(Interrupt Detection 即中断检测): 此模块用于检测中断输入。它可以配置每个中断输入为电平或边缘触发。
Irq Gen(Interrupt Generation 即中断生成)模块具有以下功能:
- 从中断控制器生成最终输出中断。
- 中断灵敏度由配置参数决定。
- 检查控制寄存器(MER 和 IER)中用于中断生成的启用条件。
- 在确认后重置中断。
- 在 IVR(中断向量) 寄存器中写入活动中断的向量地址,并为挂起的中断启用 IPR 寄存器。
三、按键中断
1、系统框图。
系统框图中,按键 KEY 作为 AXI GPIO 的输入, LED 作为 AXI GPIO 的输出。当 AXI GPIO 检测到按键状态发生变化时, AXI GPIO 就会产生一个中断信号传入中断控制器(AXI Interrupt Controller),中断控制器生成中断输出信号,传入 MicroBlaze 处理器, MicroBlaze 处理器通过接收到的中断信号控制 LED。中断控制器通过 AXI Interconnect 与 MicroBlaze 互联, MicroBlaze 可以通过 AXI 接口对中断控制器进行配置。
2、添加一个gpio模块。
注意,需要在左下角使能下gpio的中断。
3、添加INTC的IP模块。
Number of Peripheral Interrupts(Auto):外围中断设备数量。此选项允许选择外围中断输入的数量。在 IP Integrator 中,此值由连接中断信号的数量自动确定。
Enable Fast Interrupt Logic:使能快速中断逻辑。此选项使 AXI INTC 能够在快速中断模式下工作。在这种模式下,AXI INTC 使用 interrupt_address 信号提供中断向量地址,处理器通过 processor_ack 信号确认中断。当选择单信号中断输出时,不可用快速中断模式。。
Peripheral Interrupts Type:外部设备中断类型,该选项用于设置输入的中断信号。
Interrupts type – Edge or Level:中断类型-边缘或电平。此选项用于将输入中断设置为边缘或电平类型。0 表示电平类型, 1 表示边缘类型。
Level type – High or Low:电平类型-高电平或低电平。0 表示低电平,1 表示高电平。
Edge type – Rising or Falling:边缘类型-上升沿或下降沿。0 表示下降沿,1 表示上升沿。
需要注意的是 Interrupts type – Edge or Level、 Level type – High or Low 和 Edge type – Rising or Falling 的值通常由连接的中断信号自动确定,但在必要时也可以手动设置。因此本实验中我们没有对 AXI GPIO IP 核进行配置。
Processor Interrupt Type and Connection:处理器中断类型和连接。该目录用于设置中断控制器的输出信号。在该目录可以设置中断类型为电平或边缘类型,以及触发方式。 Interrupt Output Connection(中断输出连接)选项用于设置中断控制器输出的中断信号是单信号还是总线类型的信号。
将 AXI Interrupt Controller 的输出信号“interrupt”接口与 MicroBlaze 的“INTERRUPT”接口相连,将新添加的 AXI GPIO 的“ip2intc_irpt”接口与 AXI Interrupt Controller 的 intr[0:0]接口相连。
4、系统连接。
双击 AXI Interrupt Controller IP 核打开配置页面我们可以看到,AXI Interrupt Controller IP 核的中断输入已经设置为了高电平敏感,这是因为 AXI GPIO 产生的中断信号是一个高电平信号。
5、SDK进行代码解读。
#include "xparameters.h"
#include "xintc.h"
#include "xgpio.h"
#include "sleep.h"
#define KEY_DEV_ID XPAR_AXI_GPIO_1_DEVICE_ID //按键 AXI GPIO ID
#define LED_DEV_ID XPAR_AXI_GPIO_0_DEVICE_ID //LED AXI GPIO ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID //中断控制器ID
// 中断异常ID是一个适配所有处理器的宏定义
#define EXCEPTION_ID XIL_EXCEPTION_ID_INT //中断异常ID
// 中断源就是指连接按键的 AXI GPIO 输出到中断控制器的中断信号
#define AXI_GPIO_INTR_ID XPAR_INTC_0_GPIO_1_VEC_ID //AXI GPIO中断ID
static XIntc Intc; //中断控制器实例
static XGpio KEY_Gpio; //GPIO中断实例 按键
static XGpio LED_Gpio; //GPIO实例
int led_value; //LED值
int key_value; //按键值
int Intr_times = 0; //有效中断计数
int key_intr_flag = 0; //中断标志
void GpioHandler(void *CallbackRef);
// 在主函数部分可以分为器件初始化、设置输入输出、设置中断系统和中断异常处理四部分
int main(){
xil_printf("AXI GPIO INTERRUPT TEST!\r\n");
//AXI_GPIO器件初始化
XGpio_Initialize(&KEY_Gpio, KEY_DEV_ID);
XGpio_Initialize(&LED_Gpio, LED_DEV_ID);
//为指定的GPIO信道设置所有独立信号的输入/输出方向
XGpio_SetDataDirection(&LED_Gpio, 1, 0);
//设置LED初始值
XGpio_DiscreteWrite(&LED_Gpio, 1, 0x0f);
XGpio_SetDataDirection(&KEY_Gpio, 1, 1);
//初始化中断控制器
XIntc_Initialize(&Intc, INTC_DEVICE_ID);
//关联中断ID和中断服务函数
//中断服务函数是需要我们自己编写的, 用于响应和处理 AXI GPIO 中断的函数
XIntc_Connect(&Intc,AXI_GPIO_INTR_ID,(Xil_ExceptionHandler)GpioHandler,&KEY_Gpio );
//使能中断
XGpio_InterruptEnable(&KEY_Gpio, 1);
//使能全局中断
XGpio_InterruptGlobalEnable(&KEY_Gpio);
//在中断控制器上启用中断向量
XIntc_Enable(&Intc,AXI_GPIO_INTR_ID);
//启动中断控制器
XIntc_Start(&Intc, XIN_REAL_MODE);
//设置并打开中断异常处理
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(EXCEPTION_ID,
(Xil_ExceptionHandler)XIntc_InterruptHandler,&Intc);
Xil_ExceptionEnable();
/* 在 while 语句部分,当检测到中断标志信号 key_intr_flag 拉高后,读取按键对应通道的值(key_value), 当 key_value 为 0 时说明按键按下,此时中断计数 Intr_times 加 1;代码 55 到 62 行是根据 Intr_times 的值给 led_value 的赋值,由于开发板上只有四个 LED,所以我们将 Intr_times 的范围约束在 0 到 3 之间,如代码 66 行所示。当检测到按键按下时,就点亮 LED 灯并打印 Intr_times 的值,延迟 1 秒进行消抖,最后将中断 标志信号 key_intr_flag 清零,等待下次中断到来。 */
while(1){
if(key_intr_flag){
//检测中断标志信号有效
key_value = XGpio_DiscreteRead(&KEY_Gpio, 1); //读取按键值
if(key_value == 0){
//检测按键是否按下
if(Intr_times == 0) //根据有效中断数点亮LED
led_value = 0x01;
else if(Intr_times == 1)
led_value = 0x02;
else if(Intr_times == 2)
led_value = 0x04;
else
led_value = 0x08;
//按键按下后点亮对应LED灯
XGpio_DiscreteWrite(&LED_Gpio, 1, led_value);
xil_printf("i = %d\r\n",Intr_times); //打印当前的Intr_times
Intr_times = (Intr_times + 1)%4; //将计数值约束在0到3之间
//延迟1秒
sleep(1);
}
key_intr_flag = 0; //中断标志清零
}
}
return 0;
}
void GpioHandler(void *CallbackRef){
XGpio *GpioPtr = (XGpio *)CallbackRef;
key_intr_flag = 1; //接收到中断,标志信号拉高
XGpio_InterruptDisable(GpioPtr, 1); //关闭中断
XGpio_InterruptClear(GpioPtr, 1); //清除中断
XGpio_InterruptEnable(GpioPtr, 1); //使能中断
}
四、测试结果
1、串口打印。
2、每按一下按键,LED灯也会发生变化。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/14068.html