GPIO使用参考

Version 1.0


1. 概述


1.1. 概述

GPIO 采用标准的LINUX框架,能够使用统一的接口来操作gpio。


1.2. GPIO NUM与PAD对应表

请查看硬件线路图上GPIO 的PAD name,查找这个表格,对应的num 就是要操作的GPIO的num。

例如:硬件线路图上的一个GPIO 是PAD_PM_SPI_DO,如果要操作这个GPIO,对应的num =17。

开放使用的GPIO列表,请查看硬件资料的SSD26x_4L HW Checklist.xlsx的GPIO List页面里面的表格,举例如下:

表1-1


2. 内核使用GPIO


2.1. 申请为gpio端口

  • 目的

    创建端口为GPIO。

  • 语法

    int gpio_request(unsigned gpio, const char *label)
    
  • 参数

    参数名称 描述
    gpio Gpio num
    label 具体名称
  • 返回值

    返回值 描述
    0 成功。
    Other 失败。

2.2. 设为输入

  • 目的

    标记gpio为输入。

  • 语法

    int gpio_direction_input(unsigned gpio);
    
  • 参数

    参数名称 描述
    gpio Gpio num
  • 返回值

    返回值 描述
    0 成功。
    Other 失败。

2.3. 设为输出

  • 目的

    标记gpio为输出。

  • 语法

    int gpio_direction_output(unsigned gpio, int value);
    
  • 参数

    参数名称 描述
    gpio Gpio num
    value 输出值
  • 返回值

    返回值 描述
    0 成功。
    Other 失败。

2.4. 获取输入电平

  • 目的

    获取输入引脚的电平。

  • 语法

    int gpio_get_value(unsigned gpio);
    
  • 参数

    参数名称 描述
    gpio Gpio num
  • 返回值

    返回值 描述
    Int 电平值

2.5. 设置输出电平

  • 目的

    设定输出引脚的电平。

  • 语法

    void gpio_set_value(unsigned gpio, int value);
    
  • 参数

    参数名称 描述
    gpio Gpio num
    value 输出值
  • 返回值

    返回值 描述
    0 成功。
    Other 失败。

2.6. 注册gpio中断

内核下注册gpio中断可参考Kernel/drivers/sstar/gpio/test/gpio_irq_test.c

函数介绍如下:

函数名 描述
gpio_request 申请使用gpio
gpio_direction_input 配置gpio为输入
gpio_to_irq 获取中断号
request_irq 注册中断函数
irq_set_irq_type 修改触发跳变沿类型
gpio_test_isr 中断服务函数
free_irq 释放中断
gpio_free 释放gpio

SSD26x不支持双边沿触发,可以在中断服务函数中切触发跳变沿类型,参考示例:

static unsigned int irq_num;
bool LedStatus = 0;

/* 中断服务函数*/
static irqreturn_t irq_callback(int irq, void *dev_id){
if(0 == LedStatus){
    LedStatus = 1;
    irq_set_irq_type(irq_num, IRQF_TRIGGER_FALLING);
} else {
    LedStatus = 0;
    irq_set_irq_type(irq_num, IRQF_TRIGGER_RISING);
}

/***应用code***/

return IRQ_HANDLED;
}

测试方法:

kernel下编译生成gpio_irq.ko,使用insmod加载模块,默认捕捉下降沿跳变,中断服务函数处理中断事件。


3. 用户空间使用GPIO

用户空间访问gpio,即通过sysfs接口访问gpio

下面是/sys/class/gpio目录下的三种文件: 

--export/unexport文件

--gpioN指代具体的gpio引脚

--gpio_chipN指代gpio控制器

必须知道以上接口没有标准device文件和它们的链接。


3.1. export/unexport文件接口

/sys/class/gpio/export,该接口只能写不能读。

用户程序通过写入gpio的编号来向内核申请将某个gpio的控制权导出到用户空间,前提是没有内核代码申请这个gpio端口,如用户申请编号为12的GPIO的命令:

echo 12 > export

上述操作会为12号gpio创建一个节点gpio12,此时/sys/class/gpio目录下边生成一个gpio12的目录,如下图所示:

/sys/class/gpio/unexport和导出的效果相反,比如移除gpio12这个节点操作命令:

echo 12 > unexport

上述操作将会移除gpio12这个节点,如下图所示:


3.2. /sys/class/gpio/gpioN

指代某个具体的gpio端口,里边有如下属性文件:

direction 表示gpio端口的方向,读取结果是in或out。也可以对该文件进行写操作,写入out 时该gpio设为输出同时电平默认为低。写入low或high时不仅可以设置为输出还可以设置指定的输出电平。 当然如果内核不支持或者内核代码不愿意,将不会存在这个属性,比如内核调用了gpio_export(N,0)就表示内核不愿意修改gpio端口方向属性 。

value 表示gpio引脚的电平,0表示低电平,1表示高电平;如果gpio被配置为输出,这个值是可写的,记住任何非零的值都将输出为高电平。如果某个引脚被配置为中断,则可以调用poll(2)函数监听该中断,中断触发后poll(2)函数就会返回。


3.3. 代码示例

非中断模式

提供用户空间通过sysfs接口操作gpio的sample code源文件gpio_main.c

写操作:

int ss_gpio_set_value(unsigned int gpio, unsigned int value)

传入要写的gpio的编号,输入参数1/0,控制高/低电平;

读操作:

int ss_gpio_get_value(unsigned int gpio, unsigned int *value)

传入要写的gpio的编号,获取当前电平状态。

编译sample code生成gpio_main可执行bin档:

# arm-linux-gnueabihf-gcc –o gpio_main gpio_main.c

在shell中运行下述命令测试gpio:

# ./gpio_main input
# ./gpio_main output 1

提供用户空间通过mmap直接访问寄存器操作gpio的sample code源文件gpio_mmap.c

使用此方式操作gpio,用户需要查看GPIO List,确认gpio的bank基地址以及偏移地址。以PAD_TX0_IO00为例:

如上表bank基地址为0x103E,偏移地址为0x43,BIT3使能gpio mode,BIT2配置gpio方向,BIT1控制输出电平,BIT0的值为输入电平状态。


4. BOOT使用GPIO


4.1. CMD:gpio -Config gpio port

Usage:

gpio (for 2nd parameter, you must type at least 3 characters)

gpio output <gpio#> <1/0> : ex: gpio output 69 1

gpio input/get <gpio#> : ex: gpio input 10 (gpio 10 set as input)

gpio toggle <gpio#> : ex: gpio tog 49 (toggle)

gpio state <gpio#> : ex: gpio sta 49 (get i/o status(direction) & pin status)

gpio list [num_of_pins] : ex: gpio list 10 (list GPIO1~GPIO10 status)

详见boot/ommon/MsSysUtility.c文件do_gpio函数实现。


4.2. API

4.2.1. 设为输入

  • 目的

    标记gpio为输入。

  • 语法

    void MDrv_GPIO_Pad_Odn(MS_GPIO_NUM u32IndexGPIO);
    
  • 参数

    参数名称 描述
    u32IndexGPIO Gpio num
  • 返回值

    返回值 描述
    void

4.2.2. 设为输出

  • 目的

    标记gpio为输出。

  • 语法

    void MDrv_GPIO_Pad_Oen(MS_GPIO_NUM u32IndexGPIO);
    
  • 参数

    参数名称 描述
    u32IndexGPIO Gpio num
  • 返回值

    返回值 描述
    Void

4.2.3. 获取输入电平

  • 目的

    获取输入引脚的电平。

  • 语法

     U8 MDrv_GPIO_Pad_Read(MS_GPIO_NUM u32IndexGPIO);
    
  • 参数

    参数名称 描述
    u32IndexGPIO Gpio num
  • 返回值

    返回值 描述
    unsigned char 电平值

4.2.4. 设置输出高电平

  • 目的

    设定该引脚为高电平。

  • 语法

    void MDrv_GPIO_Pull_High(MS_GPIO_NUM u32IndexGPIO);
    
  • 参数

    参数名称 描述
    gpio Gpio num

4.2.5. 设置输出低电平

  • 目的

    设定该引脚为低电平。

  • 语法

    void MDrv_GPIO_Pull_Low(MS_GPIO_NUM u32IndexGPIO);
    
  • 参数

    参数名称 描述
    gpio Gpio num