这篇博文重点介绍了使用共享外设中断 GPIO 中断。为了正确实现这个中断结构,我们需要编写两个函数:
- 中断服务程序(ISR-Interrupt service routine)——定义了中断发生时发生的动作。
- 中断设置——配置中断。该例程设置并启用 GPIO 中断。它对系统内的所有中断都是通用的,以帮助代码重用。
虽然,中断很复杂,但是,值得庆幸的是,独立板支持包 (BSP) 包含许多功能,可以大大简化这项任务。将在以下头文件中找到这些函数:
- Xparameters.h – 定义处理器设备 ID
- XGPIOS.h – GPIO 配置和使用的驱动程序
- Xscugic.h – GIC(通用中断控制器)配置和使用的驱动程序
- Xil_exception.h – ARM Cortex-A9 处理器的异常函数
当我们编写代码时,我们需要知道我们希望使用的片上设备的硬件 ID 参数。对于此示例,这些设备是 GIC 和 GPIO。这些参数主要在 BSP 头文件 xparameters.h 中提供,中断 ID 除外,它由 xparameters_ps.h 提供。无需在源代码中声明此头文件;它包含在 xparameters.h 文件中。
#define GPIO_DEVICE_ID XPAR_XGPIOPS_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define GPIO_INTERRUPT_ID XPS_GPIO_INT_ID
要设置中断,我们需要两个静态全局变量和上面定义的中断
static XScuGic Intc; // Interrupt Controller Driver
static XGpioPs Gpio; //GPIO Device
Xil_exception.h 和 Xscugic.h 文件中提供了执行此操作所需的函数。在将 GPIO 配置为中断源时,我们可以使用 xgpiops.h 中提供的函数来配置整个 I/O bank 或单个引脚。例如:
void XGpioPs_IntrEnable(XGpioPs *InstancePtr, u8 Bank, u32 Mask);
void XGpioPs_IntrEnablePin(XGpioPs *InstancePtr, int Pin);
我们还需要正确配置中断:边沿触发或电平触发,哪个边沿或电平?我们使用这个函数配置中断:
void XGpioPs_SetIntrTypePin(XGpioPs *InstancePtr, int Pin, u8 IrqType);
其中 IrqType 由 xgpiops.h 文件中的五个定义之一定义:
#define XGPIOPS_IRQ_TYPE_EDGE_RISING 0 /**< Interrupt on Rising edge */
#define XGPIOPS_IRQ_TYPE_EDGE_FALLING 1 /**< Interrupt Falling edge */
#define XGPIOPS_IRQ_TYPE_EDGE_BOTH 2 /**< Interrupt on both edges */
#define XGPIOPS_IRQ_TYPE_LEVEL_HIGH 3 /**< Interrupt on high level */
#define XGPIOPS_IRQ_TYPE_LEVEL_LOW 4 /**< Interrupt on low level */
请注意,我们可以将边沿触发中断配置为上升沿或下降沿中断,或者我们可以在上升沿和下降沿都触发中断。
如果决定启用整个 I/O bank,需要知道哪个 bank 与希望用于中断的一个或多个引脚相关联。Zynq SoC 最多支持 118 个 GPIO 引脚。对于本示例中的配置,所有 MIO(54 个引脚)与 EMIO(64 个引脚)一起用作 GPIO,分为四个组,每个组包含 32 个引脚。
中断设置函数还将定义 ISR,它会在中断发生时被调用。我们使用这个函数:
XGpioPs_SetCallbackHandler(Gpio, (void *)Gpio, IntrHandler);
写了中断设置代码后,下一步将是编写在发生中断时将调用的实际 ISR。ISR 可以根据应用程序的需要而简单或复杂。对于此示例,ISR 将执行与之前轮询 I/O 示例中相同的任务:每次按下按钮时,它将切换 LED 的打开和关闭状态。ISR 还将在运行时向控制台打印一条消息。
代码链接:
❝
https://gitee.com/openfpga/zy...
原文:OpenFPGA
作者:碎碎思
相关文章推荐
更多FPGA技术干货请关注FPGA 的逻辑技术专栏。