GPIO使用参考

Version 0.2


1. 概述

请查看硬件线路图上GPIO 的PAD name,参考hw/HW Doc/SSR920 HW Checklist.xlsx,对应的num 就是需要操作的GPIO的 num。

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


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 失败。

3. 用户空间使用GPIO

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

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

  • --export/unexport文件

  • --gpioN指代具体的gpio引脚

  • --gpio_chipN指代gpio控制器

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

图3-1


3.1. export/unexport文件接口

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

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

echo 12 > export

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

图3-2

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

echo 12 > unexport

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

图3-3


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-4


3.3. 示例

用户空间代码操作参考。

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <linux/kd.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <string.h>
#include <errno.h>

#include "mi_sys.h"

#define GPIO_DEV "/sys/class/gpio"
#define SSTAR_GPIO_IN 0
#define SSTAR_GPIO_OUT 1

/* API call reference
    SStar_Gpio_Export(10);
    SStar_Gpio_SetDirection(10, SSTAR_GPIO_OUT);
    SStar_Gpio_SetValue(10, 0/1);
*/

// export gpio port
MI_S32 SStar_Gpio_Export(MI_S32 s32Gpio)
{
    MI_S32 s32Ret = -1;
    MI_S32 s32Fd = -1;

    char as8GpioDev[128];

    memset(as8GpioDev, 0, sizeof(as8GpioDev));
    sprintf(as8GpioDev, "%s/export", GPIO_DEV);

    s32Fd = open(as8GpioDev, O_WRONLY);

    if (s32Fd < 0)
        printf("failed to export gpio %d\n", s32Gpio);
    else
    {
        char as8GpioPort[10];
        memset(as8GpioPort, 0, sizeof(as8GpioPort));
        sprintf(as8GpioPort, "%d", s32Gpio);
        write(s32Fd, as8GpioPort, strlen(as8GpioPort));
        printf("export gpio port: %d\n", s32Gpio);
        close(s32Fd);
        s32Ret = MI_SUCCESS;
    }

    return s32Ret;
}

// set gpio direction: 0 in, others out
MI_S32 SStar_Gpio_SetDirection(MI_S32 s32Gpio, MI_S32 s32Direction)
{
    MI_S32 s32Ret  = -1;
    const char *ps8Direction = NULL;
    MI_S32 s32Fd = -1;

    char as8GpioDev[128];

    memset(as8GpioDev, 0, sizeof(as8GpioDev));
    sprintf(as8GpioDev, "%s/gpio%d/direction", GPIO_DEV, s32Gpio);

    s32Fd = open(as8GpioDev, O_RDWR);

    if (s32Fd < 0)
        printf("failed to set gpio%d direction\n", s32Gpio);
    else
    {
        if (SSTAR_GPIO_IN == s32Direction)
            ps8Direction = "in";
        else if (SSTAR_GPIO_OUT == s32Direction)
            ps8Direction = "out";
        else
        {
            printf("Unkown gpio direction %d\n", s32Direction);
        }
        write(s32Fd, ps8Direction, strlen(ps8Direction));
        printf("set gpio%d direction: %s\n", s32Gpio, ps8Direction);
        close(s32Fd);
        s32Ret = 0;
    }

    return s32Ret;
}

// get gpio direction
MI_S32 SStar_Gpio_GetDirection(MI_S32 s32Gpio, MI_S8 *ps8Direction, MI_S32 s32Len)
{
    MI_S32 s32Ret  = -1;
    MI_S32 s32Fd = -1;

    char as8GpioDev[128];

    memset(as8GpioDev, 0, sizeof(as8GpioDev));
    sprintf(as8GpioDev, "%s/gpio%d/direction", GPIO_DEV, s32Gpio);

    s32Fd = open(as8GpioDev, O_RDWR);

    if (s32Fd < 0)
        printf("failed to read gpio%d direction\n", s32Gpio);
    else
    {
        memset(ps8Direction, 0, s32Len);
        read(s32Fd, ps8Direction, s32Len);
        printf("get gpio%d direction: %s\n", s32Gpio, ps8Direction);
        close(s32Fd);
        s32Ret = MI_SUCCESS;
    }

    return s32Ret;
}

// set gpio value: 0 low, 1 high
MI_S32 SStar_Gpio_SetValue(MI_S32 s32Gpio, MI_S8 s8Value)
{
    MI_S32 s32Ret  = -1;
    MI_S32 s32Fd = -1;

    char as8GpioDev[128];

    memset(as8GpioDev, 0, sizeof(as8GpioDev));
    sprintf(as8GpioDev, "%s/gpio%d/value", GPIO_DEV, s32Gpio);

    s32Fd = open(as8GpioDev, O_RDWR);

    if (s32Fd < 0)
        printf("failed to set gpio%d value\n", s32Gpio);
    else
    {
        if (0 == s8Value)
        {
            write(s32Fd, (const void*)"0", 1);
        }
        else if (1 == s8Value)
        {
            write(s32Fd, (const void*)"1", 1);
        }
        else
        {
            printf("error:set gpio value fail (%d)\n", s8Value);
        }
        close(s32Fd);
        s32Ret = MI_SUCCESS;
    }

    return s32Ret;
}

// get gpio value
int SStar_Gpio_GetValue(MI_S32 s32Gpio)
{
    int value = -1;
    MI_S32 s32Fd = -1;

    char as8GpioDev[128];
    char as8[2];

    memset(as8, 0, sizeof(as8));
    memset(as8GpioDev, 0, sizeof(as8GpioDev));
    sprintf(as8GpioDev, "%s/gpio%d/value", GPIO_DEV, s32Gpio);

    s32Fd = open(as8GpioDev, O_RDWR);
    if (s32Fd < 0)
        printf("failed to read gpio%d value\n", s32Gpio);
    else
    {
        read(s32Fd, as8, 1);
        value = atoi(as8);
        close(s32Fd);
    }

    return value;
}

4. UBOOT使用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)
note: gpio# ref to drivers\mstar\gpio\mercury6\gpio.h

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