Microblaze realizes serial port and GPIO interrupt

introduce

Use the microblaze soft core to build a processor and implement interrupts.
image
Microblaze_0 is the microbalze core, which is connected to a 128Kb local memory, an mdm core debugged by JTAG, an interrupt manager axi_intc, uatr peripherals, and GPIO peripherals.

The implementation of GPIO interrupt is realized by vio IP core, and the 16-bit VIO is connected to GPIO as input to simulate key input.

The UART interrupt can be realized by connecting an external serial port debugging assistant or directly using the SDK terminal.

The concat IP core synthesizes multiple interrupt sources into one bus and provides it to the interrupt manager.

Experimental results

The jtag debugging section loops out the hello word
image
GPIO_o captured by ILA to realize the conversion from 0000 to FFFF

GPIO_t is 0xffff, indicating that all 16 gpio are input. As for why GPIO_o realizes data conversion, this is because the signal at this time has not been converted by the tri-state gate, and all 16 gpio are input after the tri-state gate conversion.
image

Use vio to change the input of GPIO, so that the GPIO controller generates an interrupt. At this time, the program enters the GPIO interrupt processing function, and prints "gpio interrupt" on the debug terminal. Use the serial port debugging assistant to input a hexadecimal number, and you will see the
imageimagesame The return value of the number, which is the value returned by calling the interrupt, the serial port debugging assistant sent three 8bit values, and four interrupts were generated, the first three interrupts were receiving interrupts, and the last one was sending interruptsimageimage

c program

#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 project source file

Note: To implement the above interrupt program, the local memory of the processor cannot be the default 8kb, but be changed to 64kb, otherwise the memory is too small to run the program.

Guess you like

Origin blog.csdn.net/QUACK_G/article/details/126286727