Linux 内核层和 用户层 配置 GPIO 引脚

 Linux BSP 开发的基础就是和GPIO打交道, 下面总结下这几天对某家开发板的GPIO控制的知识。

  公司的开发板用的是 DTB  模式 ,首先,进入 dts,dtsi文件查看关于GPIO 的模块。

复制代码

soc {
                .
                .
                .
        gpio0: gpio@****addr {
            compatible = "**********";
            reg = <0 0x****addr 0 0x50>;
            interrupts = <SPI 4 IRQ_TYPE_LEVEL_HIGH>;
            #gpio-cells = <2>;
            gpio-controller;
            gpio-ranges = <&pfc 0 0 16>;
            #interrupt-cells = <2>;
            interrupt-controller;
            clocks = <&cpg CPG_MOD 912>;
            power-domains = <*****>;
        };
               .
               .
               .

};

复制代码

  可以看到 GPIO 节点 挂在 SOC node 下 ,手上这块开发板 把GPIO分成了8个 bank  :  gpio0 - gpio7

    reg =<0 地址 0 长度> 

         #gpio-cells  =<2> 表示 要用2个cell描述一个 GPIO引脚 

    如 I2C中定义 :  pwd-gpios  = <&gpio6 7 GPIO_ACTIVE_HIGH>;

    表示 bank 6 的gpio  用 2个cell 描述  :7,GPIO_ACTIVE_HIGH (7表示bank 6 下的第七个引脚一般是 GP 6_07表示  ;GPIO_ACTIVE_HIGH则为高电平有效)     

    gpio-controller;  interrupt-controller; 表示 bank 0 下的引脚 既可以作为中断引脚 ,也可以作为 通用的GPIO引脚 

         gpio-ranges = <&pfc 0 0 16>;  表示 bank 0下有16个 GPIO引脚 

 

   GPIO 使用 pinctrl 方式来驱动 ,pin control subsystem 会 :

    1. 枚举所有可用的pin 脚   ,于是每个引脚就有的唯一的 ID (num) ,这个ID 很关键,对于以后的操作。

    

复制代码

enum {
    PINMUX_RESERVED = 0,

    PINMUX_DATA_BEGIN,
    GP_ALL(DATA), /* add GP_0_1_DATA  ,GP_0_1_DATA..... */
    PINMUX_DATA_END,

#define F_(x, y)

.....
}

复制代码

    2.管理 这些Pin脚的, 由于pin 可以复用 比如 SPI 和GPIO 复用一个pin脚 如:  GP2_08 / MISO,于是引申出 pin group 和 pin functon 两个概念:

    i2c2_pins: i2c2 {
        groups = "i2c2_a";
        function = "i2c2";
    };

    在dts 中如上所示 ,其中 i2c2_a 在 pinctl 源码中 如下所示,i2c的两根引脚使用 GP5_0 ,GP5_4. 

static const unsigned int i2c2_a_pins[] = {
    /* SDA, SCL */
    GP_PIN(5, 0),GP_PIN(5, 4),
};

    function 如下 : 

复制代码

struct sh_pfc_function {
    const char *name;
    const char * const *groups;
    unsigned int nr_groups;
};
#define SH_PFC_FUNCTION(n = i2c2)                \
    {                        \
        .name = #n,                \
        .groups = n##_groups,            \
        .nr_groups = ARRAY_SIZE(n##_groups),    \
    }

复制代码

好了 ,基本概念就先写这么多  。

 

内核层配置 GPIO 

在 写内核驱动的时候 如果希望配置某个GPIO引脚 , 可以在dts中 添加:  pwd-gpios  = <&gpio0 7 GPIO_ACTIVE_HIGH>;

 在 driver 代码中 ,  需要包含 #include <linux/gpio.h>使用 : 

    gpio_id = of_get_named_gpio(your_driver->dev->of_node,"pwd-gpios", 0);

获取 GP0_07的 ID号 ,然后申请 一个GPIO 操作对象。

    if (gpio_is_valid(gpio_id))  //判断一个IO是否合法

      devm_gpio_request_one(&platform_device->dev, gpio_id,GPIOF_OUT_INIT_LOW, name);

设置GPIO的方向,如果是输出同时设置电平:
    /* set as input or output, returning 0 or negative errno */
    int gpio_direction_input(unsigned gpio);
    int gpio_direction_output(unsigned gpio, int value);

获取输入引脚的电平:
    /* GPIO INPUT: return zero or nonzero */
    int gpio_get_value(unsigned gpio);

设置输出: 
    void gpio_set_value(unsigned gpio, int value);

释放申请的GPIO对象 

        void gpio_free(unsigned gpio);

将GPIO映射为IRQ中断:
    /* map GPIO numbers to IRQ numbers */
    int gpio_to_irq(unsigned gpio);

    /* map IRQ numbers to GPIO numbers (avoid using this) */
    int irq_to_gpio(unsigned irq);

 设置GPIO IRQ中断类型:

    set_irq_type(gpio_to_irq( gpio), IRQ_TYPE_EDGE_FALLING);

用户层配置 GPIO 

需要确认  内核  menuconfig  中 Device Drivers -》  GPIO Support  设 y .

在 /sys/class/gpio  目录下如下所示 : 

root@salvator-x:/sys/class/gpio# ls
export         gpiochip361  gpiochip419  gpiochip453  gpiochip496
gpiochip357  gpiochip393  gpiochip437  gpiochip468  unexport

gpiochip 后面的数字 是每个bank 的基地址  也就是  GP0 对应 gpiochip468

那么  GP0_07 的 ID 就是  468 + 7 ;(可能不同的内核版本,或者 开发板不一样 )通过 :

root@salvator-x:/sys/class/gpio# echo 475 > export

会对应生成 gpio475 目录 

root@salvator-x:/sys/class/gpio/gpio475# ls
active_low  device  direction  edge  power  subsystem  uevent  value

通过 

root@salvator-x:/sys/class/gpio/gpio475# echo 1 >value 
root@salvator-x:/sys/class/gpio/gpio475# echo 0 >value
root@salvator-x:/sys/class/gpio/gpio475# echo "in" > direction 
root@salvator-x:/sys/class/gpio/gpio475# echo "out" > direction 

来控制输出输入  ,电平高低 。 

 

 

 

Linux内核 GPIO操作部分API

内核中关于GPIO的操作API主要集中在<linux/of_gpio.h>和<linux/gpio.h>中,前者主要是GPIO直接与设备树相关的操作,在Linux 设备树操作API中已经记录过,后者主要是针对GPIO本身的操作,常用的有下面几个。

//linux/gpio.h
/**
 * gpio_request_one - request a single GPIO with initial configuration
 * @gpio:       the GPIO number
 * @flags:      GPIO configuration as specified by GPIOF_*
 * @label:      a literal description string of this GPIO
 */
int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)

/* 判断gpio是否有效 */
bool gpio_is_valid(int number)

/**
 * 功能:设置指定gpio的工作模式为输入模式
 * @gpio - 编号(要找的是那个cell)
 * 失败:负数,绝对值错误码,成功:0
 */
int gpio_direction_input(unsigned gpio)

/**
 * 功能:设置指定gpio的工作模式为输出模式
 * gpio - 编号(要找的是那个cell)
 * 失败:负数,绝对值错误码,成功:0
 */
int gpio_direction_output(unsigned gpio, int value)

/* 设置GPIO的值 */
void gpio_set_value(unsigned gpio, int value)

/* 获取GPIO的值 */
int gpio_get_value(unsigned gpio)

/* 申请软中断到GPIO引脚 */
int gpio_to_irq(unsigned int gpio)

/* 释放GPIO */
gpio_free(unsigned gpio)
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值