【【FPGA中断的介绍附上 上个MicroBlaze 代码的解析】】

2023-12-02 04:12

本文主要是介绍【【FPGA中断的介绍附上 上个MicroBlaze 代码的解析】】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

FPGA中断的介绍附上 上个MicroBlaze 代码的解析

我们 先附带上上一节 Micro Blaze 的 blockdesign 结构 和 代码
本次实验参考自 正点原子达芬奇开发板 Micro Blaze 开发
在这里插入图片描述

我们 可以看出 我们圈画了一个中断控制器IP 还有一个是我们构建的软核 micro blaze 和挂载的BRAM 用来当作原本内核的 DDR 存储

我之前用的是 带硬核的 zynq 开发 ARM cpu 为设计 提供了很大的帮助

我们可以 利用 强大的FPGA端 构建出假的CPU 俗称 软核
好的 了解 这个之后 我们先了解一下 中断的基本概念和使用
1.中断 — 是 打断CPU 正常执行顺序的事件
2.中断处理函数 – CPU被动调用,当有紧急的事情发生的时候,会调用
3.中断源 – 产生中断的设备

设备要产生中断 就必须有一根中断请求线,并且将其连接到中断控制器上
中断控制器就是我们在blockdesign 中 添加的 那个 IP核
在这里插入图片描述

根据输入的中断请求 给CPU内核一个中断信号,通过CPU某某设备产生了中断。外部硬件在通过INTR发送中断请求 同时读取了这个由外部硬件提供的编号

接下来我们附上代码

#include "xparameters.h"#include "xintc.h"#include "xgpio.h"#include "sleep.h"#define KEY_DEV_ID XPAR_AXI_GPIO_0_DEVICE_ID //按键 AXI GPIO ID#define LED_DEV_ID    XPAR_AXI_GPIO_1_DEVICE_ID //LED AXI GPIO ID#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID //中断控制器 ID#define EXCEPTION_ID     XIL_EXCEPTION_ID_INT //中断异常 ID
#define AXI_GPIO_INTR_ID    XPAR_INTC_0_GPIO_0_VEC_ID //AXI GPIO 中断 IDstatic 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 和中断服务函数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(1){if(key_intr_flag){ //检测中断标志信号有效key_value = XGpio_DiscreteRead(&KEY_Gpio, 1); //读取按键值if(key_value == 0){ //检测按键是否按下if(Intr_times == 0) //根据有效中断数点亮 LEDled_value = 0x01;else if(Intr_times == 1)led_value = 0x02;else if(Intr_times == 2)led_value = 0x04;elseled_value = 0x08;//按键按下后点亮对应 LED 灯XGpio_DiscreteWrite(&LED_Gpio, 1, led_value);xil_printf("i = %d\r\n",Intr_times); //打印当前的 Intr_timesIntr_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); //使能中断
}

我们接下来 对代码进行解析

#include "xparameters.h"
#include "xintc.h"
#include "xgpio.h"
#include "sleep.h"

一开始的是文件的头文件

#define KEY_DEV_ID XPAR_AXI_GPIO_0_DEVICE_ID //按键 AXI GPIO ID
#define LED_DEV_ID    XPAR_AXI_GPIO_1_DEVICE_ID //LED AXI GPIO ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID //中断控制器 ID
#define EXCEPTION_ID     XIL_EXCEPTION_ID_INT //中断异常 ID
#define AXI_GPIO_INTR_ID    XPAR_INTC_0_GPIO_0_VEC_ID //AXI GPIO 中断 ID

包括按键和 LED 对应的 AXI GPIO的 ID,中断控制器 ID,中断源 ID 以及中断异常 ID
中断源就是指连接按键的 AXI GPIO 输出到中断控制器的中断信号。中断异常 ID(XIL_EXCEPTION_ID_INT)是一个适配所有处理器的宏定义,但在不同处理器中它对应的的值也不同,我们将其宏定义为 EXCEPTION_ID

中断控制器 就是中断控制器
中断异常ID 不同的中断会有不同的ID 我们读取ID 才知道 处理的是什么中断
接下来的是 在 器件初始化、设置输入输出、设置中断系统和中断异常处理四部分。

器件初始化 :

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

有GPIO的初始化 还有设置GPIO的 输入输出方向 还有 GPIO的LED 初始化都亮

//初始化中断控制器
XIntc_Initialize(&Intc, INTC_DEVICE_ID);
//关联中断 ID 和中断服务函数
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);

下面是对中断系统的描述
1.//初始化中断控制器

XIntc_Initialize(&Intc, INTC_DEVICE_ID);

先初始化中断控制器 就是图上的那个 我们定义了叫 INIC_DEVICE

2.//关联中断 ID 和中断服务函数

XIntc_Connect(&Intc,AXI_GPIO_INTR_ID,(Xil_ExceptionHandler)GpioHandler,&KEY_Gpio );

我们可以在这里面看到 (Xil_ExceptionHandler)GpioHandler
这个GPIOHandler是我们自己写的中断服务函数
关联中断源与 中断服务函数 就可以帮助我们确定 何时触发中断

//使能中断
XGpio_InterruptEnable(&KEY_Gpio, 1);

//使能全局中断
XGpio_InterruptGlobalEnable(&KEY_Gpio);
使能 AXI GPIO 通道中断和 AXI GPIO全局中断,只有全局中断使能后 XGpio_InterruptEnable 启用的中断才会被传递。

 //在中断控制器上启用中断向量
XIntc_Enable(&Intc,AXI_GPIO_INTR_ID);
//启动中断控制器
XIntc_Start(&Intc, XIN_REAL_MODE);

我们在上面绑定了中断源与 需要接下来处理的中断服务函数 然后开动小脑筋想一下 还缺什么
当然缺的是 把中断源绑定到 中断控制器上 通过XIntc_Enable(&Intc,AXI_GPIO_INTR_ID); 绑定之后 再启用中断控制器

5.下面的是中断异常处理 关联中断异常处理函数和中断异常 ID

Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(EXCEPTION_ID,(Xil_ExceptionHandler)XIntc_InterruptHandler,&Intc);
Xil_ExceptionEnable();

MicroBlaze 支持多种异常情况,每种异常也都有自己的 ID标识,其中 XIL_EXCEPTION_ID_INT 用于标识中断请求(IRQ)异常,在代码第 9 行将其宏定义为EXCEPTION_ID,其对应的值为 0。代码第 49 行就是使能处理器的异常处理。

先初始化中断异常处理
然后 关联中断异常处理函数和中断ID — 还有一个是(Xil_ExceptionHandler)XIntc_InterruptHandler 关联之后就知道我们选择我们出现的是什么样子的中断
最后 Xil_ExceptionEnable(); 使能处理器异常处理

下面一部分的while 循环 是用来调配中断接受后的操作

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; //中断标志清零
}
}

最后一段是自己写的 中断服务函数

void GpioHandler(void *CallbackRef){
XGpio *GpioPtr = (XGpio *)CallbackRef;
key_intr_flag = 1; //接收到中断,标志信号拉高
XGpio_InterruptDisable(GpioPtr, 1); //关闭中断
XGpio_InterruptClear(GpioPtr, 1); //清除中断
XGpio_InterruptEnable(GpioPtr, 1); //使能中断
}

当系统接收到中断信号时就将中断标志信号 key_intr_flag 拉高,
然后用 XGpio_InterruptDisable 函数关闭中断,
再调用 XGpio_InterruptClear(GpioPtr, 1)函数清除 AXI GPIO通道 1 的中断状态寄存器,
最后再使能 AXI GPIO 中断以等待下一次中断触发。

这篇关于【【FPGA中断的介绍附上 上个MicroBlaze 代码的解析】】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/443906

相关文章

使用Jackson进行JSON生成与解析的新手指南

《使用Jackson进行JSON生成与解析的新手指南》这篇文章主要为大家详细介绍了如何使用Jackson进行JSON生成与解析处理,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 核心依赖2. 基础用法2.1 对象转 jsON(序列化)2.2 JSON 转对象(反序列化)3.

Springboot @Autowired和@Resource的区别解析

《Springboot@Autowired和@Resource的区别解析》@Resource是JDK提供的注解,只是Spring在实现上提供了这个注解的功能支持,本文给大家介绍Springboot@... 目录【一】定义【1】@Autowired【2】@Resource【二】区别【1】包含的属性不同【2】@

springboot循环依赖问题案例代码及解决办法

《springboot循环依赖问题案例代码及解决办法》在SpringBoot中,如果两个或多个Bean之间存在循环依赖(即BeanA依赖BeanB,而BeanB又依赖BeanA),会导致Spring的... 目录1. 什么是循环依赖?2. 循环依赖的场景案例3. 解决循环依赖的常见方法方法 1:使用 @La

使用C#代码在PDF文档中添加、删除和替换图片

《使用C#代码在PDF文档中添加、删除和替换图片》在当今数字化文档处理场景中,动态操作PDF文档中的图像已成为企业级应用开发的核心需求之一,本文将介绍如何在.NET平台使用C#代码在PDF文档中添加、... 目录引言用C#添加图片到PDF文档用C#删除PDF文档中的图片用C#替换PDF文档中的图片引言在当

C#使用SQLite进行大数据量高效处理的代码示例

《C#使用SQLite进行大数据量高效处理的代码示例》在软件开发中,高效处理大数据量是一个常见且具有挑战性的任务,SQLite因其零配置、嵌入式、跨平台的特性,成为许多开发者的首选数据库,本文将深入探... 目录前言准备工作数据实体核心技术批量插入:从乌龟到猎豹的蜕变分页查询:加载百万数据异步处理:拒绝界面

用js控制视频播放进度基本示例代码

《用js控制视频播放进度基本示例代码》写前端的时候,很多的时候是需要支持要网页视频播放的功能,下面这篇文章主要给大家介绍了关于用js控制视频播放进度的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言html部分:JavaScript部分:注意:总结前言在javascript中控制视频播放

SpringCloud动态配置注解@RefreshScope与@Component的深度解析

《SpringCloud动态配置注解@RefreshScope与@Component的深度解析》在现代微服务架构中,动态配置管理是一个关键需求,本文将为大家介绍SpringCloud中相关的注解@Re... 目录引言1. @RefreshScope 的作用与原理1.1 什么是 @RefreshScope1.

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

Spring Boot 3.4.3 基于 Spring WebFlux 实现 SSE 功能(代码示例)

《SpringBoot3.4.3基于SpringWebFlux实现SSE功能(代码示例)》SpringBoot3.4.3结合SpringWebFlux实现SSE功能,为实时数据推送提供... 目录1. SSE 简介1.1 什么是 SSE?1.2 SSE 的优点1.3 适用场景2. Spring WebFlu

java之Objects.nonNull用法代码解读

《java之Objects.nonNull用法代码解读》:本文主要介绍java之Objects.nonNull用法代码,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录Java之Objects.nonwww.chinasem.cnNull用法代码Objects.nonN