1.GPIO中断源
相关参考文章:
RISC-V教学教案
在PLIC(PLIC简介点击这里),外部平台级中断源中,GPIO中断源一共有32个,中断ID为8-39。每组GPIO(目前有4组GPIO,分别为GPIO A,GPIO B,GPIO C,GPIO D)的前8bit可以设置为中断源。例如中断ID 16-23为GPIO B组bit 0-7,如图1和图2所示。
图1 中断源
图2 GPIO中断源
2.工程代码
2.1. platform.h
注意2.02/2.03版本FII RISC-V CPU的GPIO A组连接的是LED,GPIO B组和C组连接的是数码管,GPIO D组连接的是按键。在使用GPIO工程时,将GPIO A组连接由原来的LED改成拨码开关,注意除了修改相应的FPGA代码外,还需要添加相应的管脚分配。图3所示修改过的GPIO A组连线。图4为新添加的管脚分配(这里使用的是FII PRX100-D FPGA开发板,详细的硬件参考指南点击这里)。图5所示是地址图(详细地址图点击这里)上GPIO 寄存器的值和寄存器方向,软件工程中需要根据相应的地址对GPIO进行配置。
图3 GPIO A组连线
图4 拨码开关管脚分配
图5 GPIO 寄存器地址
//定义GPIO组偏移量 #define GPIO_A_GRP_IRQ_OFFSET (0) #define GPIO_B_GRP_IRQ_OFFSET (8) #define GPIO_C_GRP_IRQ_OFFSET (16) #define GPIO_D_GRP_IRQ_OFFSET (24) #define INT_GPIO_BASE 8 //中断ID 8-39是GPIO组 //GPIO D组的bit 0-2设置成中断源,对应的按键为menu,up,return #define BUT_D_0 (0) #define BUT_D_1 (1) #define BUT_D_2 (2) //三个按键对应的GPIO序号 #define BUTTON_0_OFFSET (GPIO_D_GRP_IRQ_OFFSET + BUT_D_0) #define BUTTON_1_OFFSET (GPIO_D_GRP_IRQ_OFFSET + BUT_D_1) #define BUTTON_2_OFFSET (GPIO_D_GRP_IRQ_OFFSET + BUT_D_2) //三个按键对应的中断ID #define INT_DEVICE_BUTTON_0 (INT_GPIO_BASE + BUTTON_0_OFFSET) #define INT_DEVICE_BUTTON_1 (INT_GPIO_BASE + BUTTON_1_OFFSET) #define INT_DEVICE_BUTTON_2 (INT_GPIO_BASE + BUTTON_2_OFFSET) //GPIO A组的bit 5-7设置成中断源,对应的拨码开关为SW5-7 #define SW_5 (5) #define SW_6 (6) #define SW_7 (7) //三个拨码开关对应的GPIO序号 #define SW_5_OFFSET (GPIO_A_GRP_IRQ_OFFSET + SW_5) #define SW_6_OFFSET (GPIO_A_GRP_IRQ_OFFSET + SW_6) #define SW_7_OFFSET (GPIO_A_GRP_IRQ_OFFSET + SW_7) //三个拨码开关对应的中断ID #define INT_DEVICE_SW_5 (INT_GPIO_BASE + SW_5_OFFSET) #define INT_DEVICE_SW_6 (INT_GPIO_BASE + SW_6_OFFSET) #define INT_DEVICE_SW_7 (INT_GPIO_BASE + SW_7_OFFSET)
2.2. fii_gpio.h
图6所示为GPIO中断相关的寄存器,摘自地址图(详细地址图点击这里)。寄存器的详细解释见图7。
图6 GPIO中断寄存器
图7 GPIO中断寄存器解释
#include "fii_types.h" #define GPIO_ADDR (0xF0000000) //定义GPIO地址区间相关参数 #define GPIO_VAL (0x00) //GPIO值相对偏移量 #define GPIO_DIR (0x04) //GPIO方向相对偏移量 //定义GPIO组别 #define GPIO_A (0x00) #define GPIO_B (0x08) #define GPIO_C (0x10) #define GPIO_D (0x18) //定义GPIO中断的偏移量 #define GPIO_IRQ_GRP (0x40) //定义GPIO中断相关的参数偏移量 #define GPIO_IRQ_ENA (0x00) //中断使能 #define GPIO_IRQ_MASK (0x04) //中断屏蔽 #define GPIO_IRQ_TRIGGER (0x08) //中断边沿/电平 #define GPIO_IRQ_TYPE (0x0C) //中断上/下边沿或是高/低电压选择 #define GPIO_IRQ_PENDING (0x10) //中断悬挂 #define GPIO_IRQ_CLR (0x14) //中断清除 //定义GPIO相关的宏 //定义GPIO管脚的方向 #define GPIO_SetBitDir(gpio_grp, gpio_bit, gpio_dir) ( \ (gpio_dir == 0) ? (GPIO_REG(gpio_grp + 4) &= ~(1UL << gpio_bit)) \ : (GPIO_REG(gpio_grp + 4) |= 1UL << gpio_bit ) ) //设置GPIO的比特位 #define GPIO_SetBit(gpio_grp, gpio_bit) ( GPIO_REG( gpio_grp) |= 1UL << gpio_bit ) //清除GPIO的比特位 #define GPIO_ClrBit(gpio_grp, gpio_bit) ( GPIO_REG( gpio_grp) &= ~(1UL << gpio_bit) ) //读取GPIO的比特位 #define GPIO_ReadBit(gpio_grp, gpio_bit) (( GPIO_REG(gpio_grp) >> gpio_bit ) & 0x01 ) // 再次给GPIO相关的宏取别名 #define CPUPIN_DIR(ba,pin,d) GPIO_SetBitDir(ba, pin, d) #define CPUPIN_SET(ba,pin) GPIO_SetBit(ba, pin) #define CPUPIN_CLR(ba,pin) GPIO_ClrBit(ba, pin) #define CPUPIN_GET(ba,pin) GPIO_ReadBit(ba, pin) //枚举+取别名,为之后GPIO中断的使用提供便利 typedef enum { GPIO_OUT = 0, GPIO_IN //默认为1 } E_GPIO_DIR; typedef enum { GPIO_IRQ_DIS = 0, GPIO_IRQ_EN //默认为1 } E_GPIO_IRQ_SW; typedef enum { IRQ_LEVEL = 0, IRQ_EDGE //默认为1 } E_IRQ_TRIGGER; typedef enum { IRQ_NEG_LOW = 0, IRQ_POS_HIGH //默认为1 } E_IRQ_TYPE; //声明GPIO相关的函数,设置GPIO中断类型,比如引发中断的是边沿或者电平 void GPIO_IRQ_register( u32_t gpio_pin, E_GPIO_IRQ_SW gpio_sw, E_IRQ_TRIGGER gpio_trigger, E_IRQ_TYPE gpio_type);