Microblaze实现串口、GPIO中断

介绍

使用microblaze软核搭建处理器,实现中断
image
其中microblaze_0为microbalze内核,外接128Kb的local memory、利用JTAG调试的mdm内核、中断管理器axi_intc以及uatr外设和GPIO外设。

GPIO中断的实现利用vio IP核实现,16位的VIO接到GPIO作为输入来模拟按键输入。

UART中断外接串口调试助手或者直接利用SDK terminal实现。

concat IP核将多个中断源合成一条总线提供给中断管理器。

实验结果

jtag调试段循环输出hello word
image
ILA抓取的GPIO_o实现0000——FFFF的转换

GPIO_t为0xffff,说明16个gpio全为输入,至于GPIO_o为什么会实现数据转换,这是因为此时的信号还没有经过三态门的转换,在进过三态门转换后16个gpio全为输入
image

利用vio改变GPIO的输入,使GPIO控制器产生中断,这时候程序进入GPIO的中断处理函数,在调试端打印“gpio interrupt”.
imageimage利用串口调试助手,输入一段16进制的数字,会看到相同数字的返回值,这是调用中断返回的值,串口调试助手发送了3个8bit的数值,产生了四个中断,其中前三个中断为接收中断,最后一个为发送中断imageimage

c程序

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xparameters.h"
#include "xgpio.h"
#include "xuartlite.h"
#include "xuartlite_l.h"
#include "xintc.h"
#include "xil_io.h"
#include "sleep.h"

#define GPIO_EXAMPLE_DEVICE_ID  XPAR_GPIO_0_DEVICE_ID
#define UART_DEVICE_ID XPAR_UARTLITE_0_DEVICE_ID     //串口器件ID
#define INTC_DEVICE_ID   XPAR_INTC_0_DEVICE_ID      //中断控制器ID
#define AXI_GPIO_INTR_ID XPAR_INTC_0_GPIO_0_VEC_ID  //AXI GPIO中断ID
#define UART_INTR_ID   XPAR_INTC_0_UARTLITE_0_VEC_ID //串口中断ID
#define EXCEPTION_ID     XIL_EXCEPTION_ID_INT       //中断异常ID


#define RX_NOEMPTY XUL_SR_RX_FIFO_VALID_DATA // 接收 FIFO 非空

static XGpio Gpio; /* The Instance of the GPIO Driver */
static XIntc    Intc;                              //中断控制器实例
static XUartLite Uart;      //串口实例

void GpioHandler(void *CallbackRef);
void uart_handler(void *CallbackRef);

int main()
{
    
    
    init_platform();

    print("Hello World\n\r");
//设备初始化
    XGpio_Initialize(&Gpio, GPIO_EXAMPLE_DEVICE_ID);
    XGpio_SetDataDirection(&Gpio, 1, 0xffff);
    XUartLite_Initialize(&Uart , UART_DEVICE_ID);
    //初始化中断控制器
    XIntc_Initialize(&Intc, INTC_DEVICE_ID);
//关联中断ID和中断服务函数
    //中断服务函数是需要我们自己编写的, 用于响应和处理 AXI GPIO 中断的函数
   XIntc_Connect(&Intc,AXI_GPIO_INTR_ID,(Xil_ExceptionHandler)GpioHandler,&Gpio );
   XIntc_Connect(&Intc, UART_INTR_ID,(XInterruptHandler)uart_handler,&Uart);
//外设中断 使能
   //使能GPIO中断
   XGpio_InterruptEnable(&Gpio, 1);
   //使能GPIO全局中断
   XGpio_InterruptGlobalEnable(&Gpio);
   //使能串口中断
   XUartLite_EnableInterrupt(&Uart);
//启用外设对应的中断向量
   XIntc_Enable(&Intc,AXI_GPIO_INTR_ID);
   XIntc_Enable(&Intc,UART_INTR_ID);
//启动中断控制器
   XIntc_Start(&Intc, XIN_REAL_MODE);
//设置并打开中断异常处理
   Xil_ExceptionInit();
   Xil_ExceptionRegisterHandler(EXCEPTION_ID,
           (Xil_ExceptionHandler)XIntc_InterruptHandler,&Intc);
   Xil_ExceptionEnable();


    for(;1;){
    
    

    	Xil_Out32(0x40000000 , 0xffff);
    	sleep(1);
    	Xil_Out32(0x40000000 , 0x0000);
    	sleep(1);
    	print("Hello\n\r");
    	xil_printf("word\n\r");
    	sleep(1);

    }

    cleanup_platform();
    return 0;
}

void GpioHandler(void *CallbackRef){
    
    
    XGpio *GpioPtr = (XGpio *)CallbackRef;
        print("gpio interrupt\n\r");
        XGpio_InterruptDisable(GpioPtr, 1);  //关闭中断
        XGpio_InterruptClear(GpioPtr, 1);    //清除中断
        XGpio_InterruptEnable(GpioPtr, 1);   //使能中断
}


void uart_handler(void *CallbackRef)//中断处理函数
{
    
    
    u8 Read_data;
    u32 isr_status;
    XUartLite *InstancePtr= (XUartLite *)CallbackRef;
    //读取状态寄存器
     isr_status = XUartLite_ReadReg(InstancePtr->RegBaseAddress ,
     XUL_STATUS_REG_OFFSET);
     if(isr_status & RX_NOEMPTY){
    
     //接收 FIFO 中有数据
     //读取数据
     Read_data=XUartLite_ReadReg(InstancePtr->RegBaseAddress ,
     XUL_RX_FIFO_OFFSET);
     //发送数据
     XUartLite_WriteReg(InstancePtr->RegBaseAddress ,
     XUL_TX_FIFO_OFFSET, Read_data);
     xil_printf("%x\n",Read_data);
     print("\n\r");
     }
     print("uart interrupt\n\r");
}

git_hub 工程源文件

注:实现上述中断程序,处理器的local memory不能为默认的8kb,修改为64kb,要不然内存过小无法运行程序。

猜你喜欢

转载自blog.csdn.net/QUACK_G/article/details/126286727