GPIO中断
1、中断ID:
2、中断设备初始化:
首先来看已经封装好的两个设备的结构体:
在SDK中,对于每一个外设,如gpio、spi、timer、intc、tft等等,都提供了三种层次的驱动函数,无论在哪一种层次上编程都应该能实现期望的功能。
- 最低层次是,只提供了读写寄存器的函数,函数参数需要外设地址、寄存器偏移地址、掩码等。当然也提供了寄存器偏移的宏变量,与gpio的数据手册中的寄存器描述是一致的。
- 低层次的,是提供了读写不同寄存器的方式,需要用到的函数参数为外设地址,掩码。此时相对于1,是把偏移地址给隐藏起来了,通过函数的字面意思就可以理解到函数的含义,一般只需提供基地址。
- 高层次的,被封装成结构体的形式,用户定义好一个结构体变量,对它使用相应的初始化函数之后。再要进行程序编写,完全不需要用到外设地址、或者寄存器偏移等等。相关函数比较多。,一般采用的是第三种,如图所示的两个结构体,更加方便好理解。
将要用的中断实例通过设备中断号初始化绑定到终端控制器上
3、设置中断函数和绑定GPIO:
设置中断类型
由图可以看出XScuGic_SetPriorityTriggerType()后两位参数0xA0, 0x3分别代表优先级和触发方式。
Xil_ExceptionRegisterHandler是Xilinx提供的通用异常处理程序,中断触发之后统一由XScuGic_ExceptionHandler先处理,然后在HandlerTable中查找相应的处理函数,最后由XScuGic_Connect()将函数地址绑到IntrTd,即连接到我们自己定义的中断处理函数,函数名即入口地址。
允许GPIO设备中断:
下面是GPIO独立按键的一个简单实现demo:
/************************** Constant Definitions
*****************************/
#ifndef TESTAPP_GEN
/*
* The following constants map to the XPAR parameters created in the
* xparameters.h file. They are defined here such that a user can easily
* change all the needed parameters in one place.
*/
#define BTN_DEVICE_ID XPAR_GPIO_BTN_DEVICE_ID
#define LEDS_DEVICE_ID XPAR_GPIO_LEDS_DEVICE_ID
#define GPIO_CHANNEL1 1
#define INTC_GPIO_INTERRUPT_ID XPAR_FABRIC_GPIO_BTN_IP2INTC_IRPT_INTR
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
/*
* The following constants define the positions of the buttons and LEDs
each
* channel of the GPIO
*/
#define LEDS_ALL_ON 0x00
#define LEDS_ALL_OFF 0xFF
#define SEG7_ALL_ON 0x00FFFF
#define SEG7_ALL_OFF 0xFF0000
#define GPIO_ALL_LEDS 0xFFFF
#define GPIO_ALL_BUTTONS 0xFFFF
/*
* The following constants define the GPIO channel that is used for the
buttons
* and the LEDs. They allow the channels to be reversed easily.
*/
#define LEDS_CHANNEL 1 /* Channel 1 of the GPIO Device */
#define SEG7_CHANNEL 2 /* Channel 2 of the GPIO Device */
#define BUTTON_INTERRUPT XGPIO_IR_CH1_MASK /* Channel 1 Interrupt Mask */
/*
* The following constant determines which buttons must be pressed at the
same
* time to cause interrupt processing to stop and start
*/
#define INTERRUPT_CONTROL_VALUE 0x7
/*
* The following constant is used to wait after an LED is turned on to make
* sure that it is visible to the human eye. This constant might need to
be
* tuned for faster or slower processor speeds.
*/
#define LED_DELAY 1000000
#endif /* TESTAPP_GEN */
#define INTR_DELAY 0x00FFFFFF
#define INTR_MASK 0xF
#define INTC_DEVICE_IDXPAR_SCUGIC_SINGLE_DEVICE_ID
#define INTC XScuGic
#define INTC_HANDLER XScuGic_InterruptHandler
/************************** Function Prototypes
******************************/
void GpioHandler(void *CallBackRef);
int GpioIntrInitialize();
int GpioSetupIntrSystem(INTC *IntcInstancePtr, XGpio *InstancePtr,
u16 DeviceId, u16 IntrId, u16 IntrMask);
void GpioDisableIntr(INTC *IntcInstancePtr, XGpio *InstancePtr,
u16 IntrId, u16 IntrMask);
/************************** Variable Definitions
*****************************/
/*
* The following are declared globally so they are zeroed and so they are
* easily accessible from a debugger
*/
XGpio Gpio_BTN,Gpio_LEDS; /* The Instance of the GPIO Driver */
INTC Intc; /* The Instance of the Interrupt Controller Driver */
static u16 GlobalIntrMask; /* GPIO channel mask that is needed by
* the Interrupt Handler */
static volatile u32 IntrFlag; /* Interrupt Handler Flag */
/**************************************************************************
**/
/**
* This function is the main function of the GPIO example. It is
responsible
* for initializing the GPIO device, setting up interrupts and providing a
* foreground loop such that interrupt can occur in the background.
*
* @param None.
*
* @return
* - XST_SUCCESS to indicate success.
* - XST_FAILURE to indicate failure.
*
* @note None.
*
***************************************************************************
**/
#ifndef TESTAPP_GEN
int main(void)
{
int Status;
//u32 DataRead;
print(" Press button to Generate Interrupt\r\n");
Status = GpioIntrInitialize();
return XST_SUCCESS;
}
#endif
/**************************************************************************
****/
/**
*
* This is the entry function from the TestAppGen tool generated application
* which tests the interrupts when enabled in the GPIO
*
* @param IntcInstancePtr is a reference to the Interrupt Controller
* driver Instance
* @param InstancePtr is a reference to the GPIO driver Instance
* @param DeviceId is the XPAR_<GPIO_instance>_DEVICE_ID value from
* xparameters.h
* @param IntrId is XPAR_<INTC_instance>_<GPIO_instance>_IP2INTC_IRPT_INTR
* value from xparameters.h
* @param IntrMask is the GPIO channel mask
* @param DataRead is the pointer where the data read from GPIO Input is
* returned
*
* @return
* - XST_SUCCESS if the Test is successful
* - XST_FAILURE if the test is not successful
*
* @note None.
*
***************************************************************************
***/
int GpioIntrInitialize()
{
int Status;
u32 delay;
/* Initialize the GPIO driver. If an error occurs then exit */
Status = XGpio_Initialize(&Gpio_BTN, BTN_DEVICE_ID);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
Status = XGpio_Initialize(&Gpio_LEDS, LEDS_DEVICE_ID);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
XGpio_SetDataDirection(&Gpio_BTN, LEDS_CHANNEL, 0X0F); //set all BUTTON
pins as input
XGpio_SetDataDirection(&Gpio_LEDS, LEDS_CHANNEL, 0); //set all LEDS
pins as output
XGpio_SetDataDirection(&Gpio_LEDS, SEG7_CHANNEL, 0); //set all SEVEN
SEGMENGT LEDS pins as output
XGpio_DiscreteWrite(&Gpio_LEDS, LEDS_CHANNEL, LEDS_ALL_OFF);//set all
LEDS off
XGpio_DiscreteWrite(&Gpio_LEDS, SEG7_CHANNEL, SEG7_ALL_OFF);//set all
seven segment leds off
Status = GpioSetupIntrSystem(&Intc, &Gpio_BTN, BTN_DEVICE_ID,
INTC_GPIO_INTERRUPT_ID, INTR_MASK);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
IntrFlag = 0;
delay = 0;
while(1){
switch(IntrFlag&0xF)
{
case 0xE:
XGpio_DiscreteWrite(&Gpio_LEDS, LEDS_CHANNEL, 0xFC);
XGpio_DiscreteWrite(&Gpio_LEDS, SEG7_CHANNEL, 0x000606);
break;
case 0xD:
XGpio_DiscreteWrite(&Gpio_LEDS, LEDS_CHANNEL, 0xF3);
XGpio_DiscreteWrite(&Gpio_LEDS, SEG7_CHANNEL, 0x005B5B);
break;
case 0xB:
XGpio_DiscreteWrite(&Gpio_LEDS, LEDS_CHANNEL, 0xCF);
XGpio_DiscreteWrite(&Gpio_LEDS, SEG7_CHANNEL, 0x004F4F);
break;
case 0x7:
XGpio_DiscreteWrite(&Gpio_LEDS, LEDS_CHANNEL, 0x3F);
XGpio_DiscreteWrite(&Gpio_LEDS, SEG7_CHANNEL, 0x006666);
break;
default:
//XGpio_DiscreteWrite(&Gpio_LEDS, LEDS_CHANNEL, LEDS_ALL_OFF);
//XGpio_DiscreteWrite(&Gpio_LEDS, SEG7_CHANNEL, SEG7_ALL_OFF);
break;
}
}
GpioDisableIntr(&Intc, &Gpio_BTN, INTC_GPIO_INTERRUPT_ID, INTR_MASK);
return Status;
}
/**************************************************************************
****/
/**
*
* This function performs the GPIO set up for Interrupts
*
* @param IntcInstancePtr is a reference to the Interrupt Controller
* driver Instance
* @param InstancePtr is a reference to the GPIO driver Instance
* @param DeviceId is the XPAR_<GPIO_instance>_DEVICE_ID value from
* xparameters.h
* @param IntrId is XPAR_<INTC_instance>_<GPIO_instance>_IP2INTC_IRPT_INTR
* value from xparameters.h
* @param IntrMask is the GPIO channel mask
*
* @return XST_SUCCESS if the Test is successful, otherwise XST_FAILURE
*
* @note None.
*
***************************************************************************
***/
int GpioSetupIntrSystem(INTC *IntcInstancePtr, XGpio *InstancePtr,
u16 DeviceId, u16 IntrId, u16 IntrMask)
{
int Result;
GlobalIntrMask = IntrMask;
XScuGic_Config *IntcConfig;
/*
* Initialize the interrupt controller driver so that it is ready to
* use.
*/
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
if (NULL == IntcConfig) {
return XST_FAILURE;
}
Result = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,
IntcConfig->CpuBaseAddress);
if (Result != XST_SUCCESS) {
return XST_FAILURE;
}
XScuGic_SetPriorityTriggerType(IntcInstancePtr, IntrId,
0xA0, 0x3);
/*
* Connect the interrupt handler that will be called when an
* interrupt occurs for the device.
*/
Result = XScuGic_Connect(IntcInstancePtr, IntrId,
(Xil_ExceptionHandler)GpioHandler, InstancePtr);
if (Result != XST_SUCCESS) {
return Result;
}
/* Enable the interrupt for the GPIO device.*/
XScuGic_Enable(IntcInstancePtr, IntrId);
/*
* Enable the GPIO channel interrupts so that push button can be
* detected and enable interrupts for the GPIO device
*/
XGpio_InterruptEnable(InstancePtr, IntrMask);
XGpio_InterruptGlobalEnable(InstancePtr);
/*
* Initialize the exception table and register the interrupt
* controller handler with the exception table
*/
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)INTC_HANDLER, IntcInstancePtr);
/* Enable non-critical exceptions */
Xil_ExceptionEnable();
return XST_SUCCESS;
}
/**************************************************************************
****/
/**
*
* This is the interrupt handler routine for the GPIO for this example.
*
* @param CallbackRef is the Callback reference for the handler.
*
* @return None.
*
* @note None.
*
***************************************************************************
***/
void GpioHandler(void *CallbackRef)
{
XGpio *GpioPtr = (XGpio *)CallbackRef;
IntrFlag = XGpio_DiscreteRead(&Gpio_BTN, LEDS_CHANNEL);
/* Clear the Interrupt */
XGpio_InterruptClear(GpioPtr, GlobalIntrMask);
}
/**************************************************************************
****/
/**
*
* This function disables the interrupts for the GPIO
*
* @param IntcInstancePtr is a pointer to the Interrupt Controller
* driver Instance
* @param InstancePtr is a pointer to the GPIO driver Instance
* @param IntrId is XPAR_<INTC_instance>_<GPIO_instance>_VEC
* value from xparameters.h
* @param IntrMask is the GPIO channel mask
*
* @return None
*
* @note None.
*
***************************************************************************
***/
void GpioDisableIntr(INTC *IntcInstancePtr, XGpio *InstancePtr,
u16 IntrId, u16 IntrMask)
{
XGpio_InterruptDisable(InstancePtr, IntrMask);
/* Disconnect the interrupt */
XScuGic_Disable(IntcInstancePtr, IntrId);
XScuGic_Disconnect(IntcInstancePtr, IntrId);
return;
}