vitis编译代码出现makefile编译错误且无提示。

在使用vivado开发microblaze的时候,需要用到中断功能。芯片平台是xc7z020clg-400-1。所以我添加了一个axi interrupt controllor模块和两个axi gpio模块。其中一个gpio由于接收key按键输入。另外一个用于发送led显示。其block design所示。

img

生成比特流导出硬件。最后在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

img

想问一下这个是什么问题。

在console窗口没有任何的提示

img


img

补充:这个问题主要由于初始化和配置中断控制器那几行代码引起的。在注释掉这些配置代码后就没有该问题了。

    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文件即可。

按照下面的方法检查一下

  1. 检查 Vivado 工具版本和编译器版本是否与所使用的 SDK 版本兼容。建议将 Vivado 工具,SDK 和编译器保持同一版本,或根据官方文档中的版本兼容性列表来安排版本搭配。

  2. 检查是否正确地配置了 AXI 中断控制器和 GPIO 模块。需要确保各个模块之间正确地连接,且中断管脚设置正确。

  3. 检查编译错误信息,查看是否有 undefined reference 和 missing symbol 的错误。这些错误通常与库链接不完整有关,需要添加缺失的库或在链接时添加 "-l" 参数确保库链接成功。

  4. 检查 SDK 的 BSP(Board Support Package)是否正确配置,包括需要使用的驱动程序是否正确添加和编译。在 SDK 软件开发环境中,需要手动添加引脚规划文件和驱动程序,并在 SDK 编译、构建工程时选择需要的 BSP。

  5. 检查工程文件夹权限,如果权限不足,会导致编译过程中无法创建文件或更新文件。

发生这个错误的原因有可能是,存储大小不够,比如ram不足,解决方法就是BSP工程-选择popertise-选择NIOS II BSP popertise,取消support C++,勾选Reduced device dirvers和small C library。另外,检查下你的配置以及中断控制器设置是否正确。你可选择调试或者一行一行注解代码的方式来定位

估计中断配置这里有问题,一行一行的进行注释调试试下~

该回答引用ChatGPT4与博主@晓码自在合作编写:

根据你描述的问题,很可能是在配置和初始化中断控制器和GPIO模块时出现了问题,导致编译失败。

可能的原因有:

  1. 中断控制器或GPIO模块的ID配置错误。在使用XIntc_Initialize和XGpio_Initialize初始化时,需要传入正确的设备ID。如果ID错误,会导致初始化失败。
  2. 中断异常ID配置错误。在Xil_ExceptionRegisterHandler注册中断处理函数时,需要传入正确的中断异常ID。如果异常ID不正确,中断系统无法正常工作。
  3. 中断处理函数格式错误。中断处理函数需要符合Xil_ExceptionHandler格式要求,否则不能正确注册和调用。
  4. 中断未正确使能。需要通过XIntc_Enable和XGpio_InterruptEnable等函数使能中断,否则中断不会响应。
  5. 器件初始化的顺序错误。GPIO和中断控制器的初始化顺序会影响其正常工作,需要首先初始化GPIO,然后中断控制器,最后使能中断。

解决思路:

  1. Double check 你的中断控制器、GPIO模块ID和中断异常ID是否正确,与Vivado设计一致。
  2. 检查中断处理函数GpioHandler的格式和定义是否满足Xil_ExceptionHandler要求。
  3. 确认通过XIntc_Enable和XGpio_InterruptEnable已经正确使能了中断。
  4. 检查初始化的顺序,推荐的顺序是:
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();

  1. 你也可以尝试注释掉中断和GPIO相关的初始化代码,确认是否可以编译通过,然后逐步添加并编译,定位具体的问题代码。