xilinx 库函数有一个比较通用的初始化流程
1、定义外设结构体:
XGpioPs xgpio;
XScuGic intc;
2、定义外设配置指针:
XGpioPs_Config *gpioConfig;
XScuGic_Config *IntcConfig;
3、根据外设DEVICE_ID寻找配置:
gpio_Config = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
4、初始化外设
XGpioPs_CfgInitialize(&xgpio, gpioConfig, gpioConfig->BaseAddr);
XScuGic_CfgInitialize(&intc, IntcConfig, IntcConfig->CpuBaseAddress);
注意第三个参数和配置所在的内存位置有关,函数原型中是EffectiveAddr,即base address
5、调用各个外设的api
GPIO中断配置流程,分为GPIO控制器初始化和中断控制器(GIC)初始化,以及设置中断触发类型和绑定中断回调等
1、GPIO控制器初始化
#include "xparameters.h"
#include "xgpiops.h"
//定义GPIO设备ID
#define GPIOPS_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID
//定义按键和LED的MIO编号,看板子的原理图
#define PS_KEY1 50
#define PS_KEY2 51
#define PS_LED1 0
#define PS_LED2 13
//定义全局设备结构体变量
XGpioPs xgpio;
XGpioPs_Config *gpio_Config;
//根据器件 ID 查找配置信息
gpio_Config = XGpioPs_LookupConfig(GPIOPS_DEVICE_ID);
//初始化 GPIO driver
status = XGpioPs_CfgInitialize(&xgpio, gpio_Config, gpio_Config->BaseAddr);
//设置 KEY 所连接的 MIO 引脚的方向为输入,0为输入
XGpioPs_SetDirectionPin(&xgpio, PS_KEY1, 0);
XGpioPs_SetDirectionPin(&xgpio, PS_KEY2, 0);
//设置 LED 所连接的 MIO 引脚的方向为输出、使能输出并设置默认输出电平
XGpioPs_SetDirectionPin(&xgpio, PS_LED1, 1);
XGpioPs_SetDirectionPin(&xgpio, PS_LED2, 1);
//1为使能输出
XGpioPs_SetOutputEnablePin(&xgpio, PS_LED1, 1);
XGpioPs_SetOutputEnablePin(&xgpio, PS_LED2, 1);
//0为输出低电平
XGpioPs_WritePin(&xgpio, PS_LED1, 0x0);
XGpioPs_WritePin(&xgpio, PS_LED2, 0x0);
2、GIC控制器初始化
#include "xscugic.h"
#include "xil_exception.h"
//GIC控制器的设备ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
//MIO的中断号为52,参考UG585
#define GPIO_INTERRUPT_ID XPAR_XGPIOPS_0_INTR
//全局结构体定义
XScuGic intc;
//中断控制器配置信息指针
XScuGic_Config *IntcConfig;
//根据器件 ID 查找配置信息
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
//初始化 Gic driver
status = XScuGic_CfgInitialize(&intc, IntcConfig, IntcConfig->CpuBaseAddress);
3、使能中断异常,注册回调函数
//设置并使能中断异常
//XIL_EXCEPTION_ID_INT和XScuGic_InterruptHandler是库函数自带的
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler) XScuGic_InterruptHandler, &intc);
Xil_ExceptionEnable();
//为中断设置中断处理函数
//intr_handler是实际的回调函数,(void *) gpio是传递给回调函数的参数,用于获取中断源
status = XScuGic_Connect(&intc, GpioIntrId,
(Xil_ExceptionHandler) intr_handler, (void *) gpio);
4、设置GPIO中断触发类型
//使能来自于 Gpio 器件的中断
XScuGic_Enable(&intc, GpioIntrId);
//设置 KEY 按键的中断类型为下降沿中断
XGpioPs_SetIntrTypePin(&xgpio, PS_KEY1, XGPIOPS_IRQ_TYPE_EDGE_FALLING);
XGpioPs_SetIntrTypePin(&xgpio, PS_KEY2, XGPIOPS_IRQ_TYPE_EDGE_FALLING);
//使能按键 KEY 中断
XGpioPs_IntrEnablePin(&xgpio, PS_KEY1);
XGpioPs_IntrEnablePin(&xgpio, PS_KEY2);
/*库函数中定义了以下几种中断触发类型,具体可用哪些参考UG585****************************/
#define XGPIOPS_IRQ_TYPE_EDGE_RISING 0x00U /**< Interrupt on Rising edge */
#define XGPIOPS_IRQ_TYPE_EDGE_FALLING 0x01U /**< Interrupt Falling edge */
#define XGPIOPS_IRQ_TYPE_EDGE_BOTH 0x02U /**< Interrupt on both edges */
#define XGPIOPS_IRQ_TYPE_LEVEL_HIGH 0x03U /**< Interrupt on high level */
#define XGPIOPS_IRQ_TYPE_LEVEL_LOW 0x04U /**< Interrupt on low level */
/*********************************************************************************/
5、回调函数示例,实现功能为按下一次按键LED翻转一次
static void intr_handler(void *callback_ref)
{
XGpioPs *gpio = (XGpioPs *) callback_ref;
xil_printf("enter interrupt!\t");
//读取 KEY 按键引脚的中断状态,判断是否发生中断
if (XGpioPs_IntrGetStatusPin(gpio, PS_KEY1))
{
xil_printf("PS_KEY1 press!\r\n");
XGpioPs_WritePin(gpio, PS_LED1, ~XGpioPs_ReadPin(gpio, PS_LED1));
//禁用PS_KEY1的中断,防止无限进入中断
XGpioPs_IntrDisablePin(gpio, PS_KEY1);
//清除按键 KEY 中断
XGpioPs_IntrClearPin(gpio, PS_KEY1);
//使能按键 KEY 中断
XGpioPs_IntrEnablePin(gpio, PS_KEY1);
}
if (XGpioPs_IntrGetStatusPin(gpio, PS_KEY2))
{
xil_printf("PS_KEY2 press!\r\n");
XGpioPs_WritePin(gpio, PS_LED2, ~XGpioPs_ReadPin(gpio, PS_LED2));
XGpioPs_IntrDisablePin(gpio, PS_KEY2);//禁用PS_KEY2的中断,防止无限进入中断
XGpioPs_IntrClearPin(gpio, PS_KEY2); //清除按键 KEY 中断
XGpioPs_IntrEnablePin(gpio, PS_KEY2); //使能按键 KEY 中断
}
}