Menu Close

RISC-V GPIO 中断设计与应用 (1)

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所示。

 

IMG_256

图1 中断源

 

IMG_257

 

图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进行配置。

 

IMG_258

图3 GPIO A组连线

 

IMG_259

 

图4 拨码开关管脚分配

 

IMG_260

 

图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。

 

IMG_261

图6 GPIO中断寄存器

IMG_262

IMG_263

 

 

图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);
Posted in RISC-V, RISC-V, RISC-V 外设, RISC-V 教案, 应用开发, 开发板, 教材与教案, 文章

发表评论

相关链接