在使用vivado开发microblaze的时候,需要用到中断功能。芯片平台是xc7z020clg-400-1。所以我添加了一个axi interrupt controllor模块和两个axi gpio模块。其中一个gpio由于接收key按键输入。另外一个用于发送led显示。其block design所示。
生成比特流导出硬件。最后在vitis写c语言代码。
#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
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(){
//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,KEY_DEV_ID,(Xil_ExceptionHandler)GpioHandler,&KEY_Gpio );
//使能中断
XGpio_InterruptEnable(&KEY_Gpio, 1);
//使能全局中断
XGpio_InterruptGlobalEnable(&KEY_Gpio);
//在中断控制器上启用中断向量
XIntc_Enable(&Intc,KEY_DEV_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) //根据有效中断数点亮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); //使能中断
}
最后会显示:make:***[makefile:38:test.elf] Error 1
想问一下这个是什么问题。
在console窗口没有任何的提示
补充:这个问题主要由于初始化和配置中断控制器那几行代码引起的。在注释掉这些配置代码后就没有该问题了。
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,KEY_DEV_ID,(Xil_ExceptionHandler)GpioHandler,&KEY_Gpio );
//使能中断
XGpio_InterruptEnable(&KEY_Gpio, 1);
//使能全局中断
XGpio_InterruptGlobalEnable(&KEY_Gpio);
//在中断控制器上启用中断向量
XIntc_Enable(&Intc,KEY_DEV_ID);
XIntc_Start(&Intc, XIN_REAL_MODE);
根据提供的代码,可能的原因是编译出错,导致无法生成可执行文件test.elf。建议检查以下几点:
确认Vivado工程中的IP核及其连接是否正确。特别是AXI Interrupt Controller模块的连接是否正确,是否已连接到MicroBlaze的中断控制器。
确认代码中使用的XPAR_AXI_GPIO_1_DEVICE_ID和XPAR_AXI_GPIO_0_DEVICE_ID是否与Vivado中生成的硬件系统中的GPIO IP核对应,可以在生成的硬件系统中查看这些IP核的实例ID。
确认Vitis编译器是否正确配置。可以检查Vitis项目的设置,确保已选择正确的硬件平台、编译器和库。
确认是否已正确安装驱动程序和设备支持文件。可以检查Vivado安装目录下的driver文件夹和Vitis安装目录下的platforms文件夹,确保安装了相关的驱动和设备支持文件。
如果以上几点都没有问题,可以尝试重新生成Vivado的比特流和Vitis的可执行文件。如果仍然出现问题,可以查看Vitis的编译输出日志,以了解详细的错误信息,或者尝试在代码中添加调试信息来确定问题所在。
错误行:XGpio_Initialize(&LED_Gpio, LED_DEV_ID); 建议检查XPAR_AXI_GPIO_0_DEVICE_ID是否正确定义为LED GPIO的设备ID。 错误行:XGpio_Initialize(&KEY_Gpio, KEY_DEV_ID); 建议检查XPAR_AXI_GPIO_1_DEVICE_ID是否正确定义为按键GPIO的设备ID。 错误行:XIntc_Connect(&Intc,KEY_DEV_ID,(Xil_ExceptionHandler)GpioHandler,&KEY_Gpio ); 建议检查KEY_DEV_ID是否正确,确保与你在Vivado中定义的AXI GPIO的设备ID匹配。 错误行:Xil_ExceptionRegisterHandler(EXCEPTION_ID, (Xil_ExceptionHandler)XIntc_InterruptHandler,&Intc); 建议检查EXCEPTION_ID是否正确定义为中断异常ID。确保与你在Vivado中定义的中断控制器的ID匹配。 错误行:Xil_ExceptionEnable(); 这个函数在Vitis中是无效的,因为它与MicroBlaze处理器相关,而不适用于Zynq平台。你可以尝试删除此行,因为之前已经通过XIntc_Start()函数启用了中断。
在生成自定义IP时,删掉文件选项卡里的drivers和bd文件即可。
按照下面的方法检查一下
检查 Vivado 工具版本和编译器版本是否与所使用的 SDK 版本兼容。建议将 Vivado 工具,SDK 和编译器保持同一版本,或根据官方文档中的版本兼容性列表来安排版本搭配。
检查是否正确地配置了 AXI 中断控制器和 GPIO 模块。需要确保各个模块之间正确地连接,且中断管脚设置正确。
检查编译错误信息,查看是否有 undefined reference 和 missing symbol 的错误。这些错误通常与库链接不完整有关,需要添加缺失的库或在链接时添加 "-l" 参数确保库链接成功。
检查 SDK 的 BSP(Board Support Package)是否正确配置,包括需要使用的驱动程序是否正确添加和编译。在 SDK 软件开发环境中,需要手动添加引脚规划文件和驱动程序,并在 SDK 编译、构建工程时选择需要的 BSP。
检查工程文件夹权限,如果权限不足,会导致编译过程中无法创建文件或更新文件。
发生这个错误的原因有可能是,存储大小不够,比如ram不足,解决方法就是BSP工程-选择popertise-选择NIOS II BSP popertise,取消support C++,勾选Reduced device dirvers和small C library。另外,检查下你的配置以及中断控制器设置是否正确。你可选择调试或者一行一行注解代码的方式来定位
估计中断配置这里有问题,一行一行的进行注释调试试下~
该回答引用ChatGPT4与博主@晓码自在合作编写:
根据你描述的问题,很可能是在配置和初始化中断控制器和GPIO模块时出现了问题,导致编译失败。
可能的原因有:
解决思路:
c
XGpio_Initialize(&KEY_Gpio, ...); //初始化GPIO
XGpio_SetDataDirection(...); //设置GPIO方向
XIntc_Initialize(&Intc, ...); //初始化中断控制器
XIntc_Connect(&Intc, ...); //注册中断处理函数
XGpio_InterruptEnable(&KEY_Gpio, ...); //使能GPIO中断
XIntc_Enable(&Intc, ...); //使能中断控制器中断
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(...); //注册异常处理函数
Xil_ExceptionEnable();