AXI GPIO 同意通道混合輸入輸出中斷控制
#KEY
set_property IOSTANDARD LVCMOS18 [get_ports {AXI_GPIO_KEY_tri_io[0]}]
set_property PACKAGE_PIN J13 [get_ports {AXI_GPIO_KEY_tri_io[0]}]
set_property IOSTANDARD LVCMOS18 [get_ports {AXI_GPIO_KEY_tri_io[1]}]
set_property PACKAGE_PIN H13 [get_ports {AXI_GPIO_KEY_tri_io[1]}]#LED
set_property IOSTANDARD LVCMOS18 [get_ports {AXI_GPIO_KEY_tri_io[2]}]
set_property PACKAGE_PIN U21 [get_ports {AXI_GPIO_KEY_tri_io[2]}]
set_property IOSTANDARD LVCMOS18 [get_ports {AXI_GPIO_KEY_tri_io[3]}]
set_property PACKAGE_PIN Y25 [get_ports {AXI_GPIO_KEY_tri_io[3]}]
main.c
#include <stdio.h>
#include "xil_printf.h"
#include "axi_gpio.h"
#include "axi_intr.h"
#include "sleep.h"u8 led1_flag = 0;
u8 led2_flag = 0;int main(){printf("AXI_GPIO_S\r\n");axi_gpio_config();intr_config();
// LED_ON;while(1){out_axi_gpio(2,led1_flag);out_axi_gpio(3,led2_flag);printf("%lx %d %d\r\n",read_axi_reg(),led1_flag,led2_flag);sleep(1);AXI_GPIO_INTR(1);}return 0;
}
axi_gpio.c
#include <stdio.h> // 標準輸入輸出函數,用于調試信息輸出
#include "xparameters.h" // 硬件系統參數定義,包含基地址和設備ID等
#include "axi_gpio.h" // AXI GPIO寄存器定義,提供底層硬件訪問XGpio AXI_Gpio ;#define GPIO_CHANNEL1 1 //AXI GPIO 通道號#define AXI_GPIO_ID XPAR_GPIO_0_DEVICE_ID //AXI GPIO 器件ID//axi gpio 初始化
void axi_gpio_config(void){XGpio_Initialize(&AXI_Gpio, AXI_GPIO_ID); //初始化AXI GPIOXGpio_SetDataDirection(&AXI_Gpio,GPIO_CHANNEL1,0x000000003); //設置對應通道為0011輸出輸入LED_OFF;
}//讀取通道當前狀態
u32 read_axi_reg(void){return XGpio_DiscreteRead(&AXI_Gpio,GPIO_CHANNEL1);
}//輸出函數
//bit_pos:要修改的數據位
//value:要修改的數據
void out_axi_gpio(u32 bit_pos,u8 value){u32 out_data;out_data = modify_bit(read_axi_reg(),bit_pos,value);XGpio_DiscreteWrite(&AXI_Gpio,GPIO_CHANNEL1,out_data);
}/*** @brief 修改數據的特定位* @param data 要修改的原始數據* @param bit_pos 要修改的位位置(0-31,0表示最低位)* @param value 要設置的值(0或1)* @return 修改后的數據** @details 此函數通過創建掩碼來修改數據的特定位,不影響其他位的值* 使用示例:modify_bit(0x00000000, 3, 1) 返回 0x00000008(設置第3位為1)*/
u32 modify_bit(u32 data, u32 bit_pos, u8 value) {// 創建指定位的掩碼:將1左移bit_pos位// 例如:bit_pos=3 -> mask = 0b00001000 (0x08)u32 mask = 1U << bit_pos;if (value) {// 設置特定位為1:使用OR操作將指定位設為1data |= mask;} else {// 設置特定位為0:使用AND操作與掩碼的反碼,清除指定位data &= ~mask;}return data;
}/*** 獲取32位數據中特定位的值* @param data 原始數據* @param bit_pos 位位置(0-31,0表示最低位)* @return 指定位的值(0或1)*/
u32 get_bit(u32 data, u32 bit_pos) {// 確保位位置在有效范圍內(0-31)if(bit_pos > 31) return 0;// 將數據右移,使目標位移動到最低位,然后與1進行與操作return (data >> bit_pos) & 1;
}
axi_gpio.h
#include <stdio.h>
#include "xparameters.h"
#include "xgpio.h"extern XGpio AXI_Gpio ;#define GPIO_CHANNEL1 1 //AXI GPIO 通道號#define LED_ON XGpio_DiscreteWrite(&AXI_Gpio,GPIO_CHANNEL1,0X0000000F) //控制IO輸出1
#define LED_OFF XGpio_DiscreteWrite(&AXI_Gpio,GPIO_CHANNEL1,0X00000003) //控制IO輸出0void axi_gpio_config(void);
u32 read_axi_reg(void);
u32 modify_bit(u32 data, u32 bit_pos, u8 value);
void out_axi_gpio(u32 bit_pos,u8 value);
u32 get_bit(u32 data, u32 bit_pos);
axi_intr.c
#include <stdio.h>
#include "xparameters.h"
#include "xgpio.h"
#include "xil_exception.h"
#include "xscugic.h"
#include "axi_intr.h"
#include "axi_gpio.h"extern XGpio AXI_Gpio ;XScuGic Intc ;#define AXI_GPIO_ID XPAR_GPIO_0_DEVICE_ID //AXI GPIO 器件ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID //中斷控制器 器件ID#define AXI_GPIO_INT_ID XPAR_FABRIC_AXI_GPIO_0_IP2INTC_IRPT_INTR //AXI GPIO 中斷ID#define GPIO_CHANNEL1 1 //AXI GPIO 通道號extern u8 led1_flag;
extern u8 led2_flag;void intr_config(void){XGpio_Initialize(&AXI_Gpio, AXI_GPIO_ID); //初始化AXI GPIOXGpio_SetDataDirection(&AXI_Gpio,GPIO_CHANNEL1,0x00000003); //設置對應通道為輸入SetupInterruptSystem(&Intc,&AXI_Gpio,AXI_GPIO_INT_ID); //設置中斷系統
}void SetupInterruptSystem(XScuGic *GicInstancePtr, XGpio *AXI_Gpio,u16 AXI_GpioIntrId)
{XScuGic_Config *IntcConfig;//查找GIC配置信息,進行初始化IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);XScuGic_CfgInitialize(GicInstancePtr, IntcConfig,IntcConfig->CpuBaseAddress);/*********************************************************************************************************************///初始化ARM處理器異常句柄Xil_ExceptionInit();//給IRQ異常注冊處理程序Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,GicInstancePtr);//使能處理器中斷Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);
/*********************************************************************************************************************///關聯IQC異常處理函數XScuGic_Connect(GicInstancePtr,AXI_GpioIntrId,(Xil_ExceptionHandler)IntrHandler,(void *)AXI_Gpio);//使能GIC控制器對應ID中斷XScuGic_Enable(GicInstancePtr, AXI_GpioIntrId);//設置優先級0xA0 觸發類型 0x3邊沿觸發(上升沿或下降沿)XScuGic_SetPriorityTriggerType(GicInstancePtr, AXI_GpioIntrId,0xA0, 0x3);//打開AXI GPIO IP中斷使能 通道使能XGpio_InterruptGlobalEnable(AXI_Gpio);XGpio_InterruptEnable(AXI_Gpio,0x00000003);
}void IntrHandler(void){printf("from intr\r\n");//關閉AXI GPIO1中斷使能AXI_GPIO_INTR(0);
// //判斷AXI KEYif(get_bit(read_axi_reg(),0) == 0){led1_flag = !led1_flag;}if(get_bit(read_axi_reg(),1) == 0){led2_flag = !led2_flag;}
// else;//清楚中斷線XGpio_InterruptClear(&AXI_Gpio,GPIO_CHANNEL1);
}
axi_intr.h
#include <stdio.h>
#include "xparameters.h"
#include "xgpio.h"
#include "xil_exception.h"
#include "xscugic.h"void intr_config(void);
void IntrHandler(void);
void SetupInterruptSystem(XScuGic *GicInstancePtr, XGpio *AXI_Gpio,u16 AXI_GpioIntrId);extern XScuGic Intc ;
extern XGpio AXI_Gpio ;#define AXI_GPIO_INTR(a) if(a)\XGpio_InterruptEnable(&AXI_Gpio,0x00000003);\else XGpio_InterruptDisable(&AXI_Gpio,0x00000000);
實現AXI GPIO[1:0]做輸入,中斷控制AXI GPIO[3:2]做輸出。