草庐IT

Linux内核gpio

小田BSP 2023-10-17 原文

本文基于RockPI 4A单板Linux 4.4内核介绍RK3399 Linux GPIO功能。

一、GPIO介绍

GPIO(General Purpose Input/Output Port):通用输入输出端口。

除作为一般的输入/输出功能外,还可以配置为中断和模拟PWM、I2C等接口功能。

RK3399 GPIO属性如下:

1、一共有5组GPIO(GPIO0~4),每组GPIO为一个Bank,共32个引脚。每个Bank包括4个Group (GPIOA(0~7) ~ D(0~7))。不是所有Bank都有GPIOA~D的编号,RK3399共122个GPIO引脚。

2、所有GPIO都可被配置为CA55或CA53的中断功能,且GPIO0GPIO1可用于系统低功耗唤醒模式。

3、在上电复位后,所有GPIO默认输入状态。

4、软件可配置GPIO驱动强度。

RK3399引脚在系统中显示如下:

root@linaro-alip:/sys/kernel/debug/pinctrl/pinctrl# cat pins
registered pins: 160
## GPIO 0_*包括的GPIO
pin 0 (gpio0-0)
pin 1 (gpio0-1)
pin 2 (gpio0-2)
pin 3 (gpio0-3)
pin 4 (gpio0-4)
pin 5 (gpio0-5)
pin 6 (gpio0-6)
pin 7 (gpio0-7)
pin 8 (gpio0-8)
pin 9 (gpio0-9)
pin 10 (gpio0-10)
...
pin 31 (gpio0-31)
...
## GPIO 2_*包括的GPIO
pin 64 (gpio2-0)
pin 65 (gpio2-1)
pin 66 (gpio2-2)
pin 67 (gpio2-3)
pin 68 (gpio2-4)
pin 69 (gpio2-5)
pin 70 (gpio2-6)
pin 71 (gpio2-7)  ## GPIO2_A7
pin 72 (gpio2-8)
pin 73 (gpio2-9)
pin 74 (gpio2-10)
...
pin 95 (gpio2-31)
...
## GPIO 4_*包括的GPIO
pin 128 (gpio4-0)
...
pin 159 (gpio4-31)

RK3399 GPIO引脚号计算方式:

pins = 32*bank + 8*group + x
bank: 0 ~ 4,对应GPIO 0~4
group: 0 ~ 3,对应GPIO A~D

例:

GPIO2_A7 = 32*2 + 8*0 + 7 = 71

二、GPIO配置

ROCKPI 4A单板WIFI 模块电源(GPIO0_B2)为例,介绍DTSGPIO配置。

image.png

配置文件:arch/arm64/boot/dts/rockchip/rockpi-4-linux.dtsi,内容如下:

    sdio_pwrseq: sdio-pwrseq {
        compatible = "mmc-pwrseq-simple";
        clocks = <&rk808 1>;
        clock-names = "ext_clock";
        ## 1、配置GPIO0_B2_d的pinmux功能
        pinctrl-names = "default";
        pinctrl-0 = <&wifi_enable_h>;

        /*
         * On the module itself this is one of these (depending
         * on the actual card populated):
         * - SDIO_RESET_L_WL_REG_ON
         * - PDN (power down when low)
         */
        ## 2、配置GPIO0_B2_d默认输出低电平
        reset-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; 
    };
    ## 3、配置GPIO0_B2_d(WIFI_REG_ON_H)为GPIO功能
    sdio-pwrseq {
        wifi_enable_h: wifi-enable-h {
            rockchip,pins =
                <0 10 RK_FUNC_GPIO &pcfg_pull_none>;
        };
    };

在系统启动后,可以查看GPIO,命令如下:

root@linaro-alip:/sys/kernel/debug# cat gpio
GPIOs 0-31, platform/pinctrl, gpio0:
 gpio-4   (                    |bt_default_wake_host) out hi
 gpio-9   (                    |bt_default_reset    ) out hi
 gpio-10  (                    |reset               ) out lo    ## 该引脚就是GPIO0_B2_d

GPIOs 32-63, platform/pinctrl, gpio1:
 gpio-35  (                    |vcc5v0_otg          ) out hi
 gpio-46  (                    |vsel                ) out lo
 gpio-49  (                    |vsel                ) out lo

GPIOs 64-95, platform/pinctrl, gpio2:
 gpio-83  (                    |bt_default_rts      ) out lo
 gpio-90  (                    |vcc3v3_pcie         ) out hi
 gpio-91  (                    |bt_default_wake     ) out hi

GPIOs 96-127, platform/pinctrl, gpio3:
 gpio-111 (                    |mdio-reset          ) out hi
 gpio-124 (                    |?                   ) out lo
 gpio-125 (                    |?                   ) out lo

GPIOs 128-159, platform/pinctrl, gpio4:
 gpio-153 (                    |vcc5v0_host         ) out hi

注:

如果debugfs没有挂载,使用下面命令挂载

mount -t debugfs none /sys/kernel/debug

三、GPIO驱动

Linux内核GPIO主要实现文件:

drivers/gpio/gpiolib.c         ## 新版API,基于描述符(descriptor-based)
drivers/gpio/gpiolib-legacy.c  ## 旧API
include/linux/gpio.h

GPIO子系统有两套API

1、基于描述符(descriptor-based)

前缀为:gpiod_

参考:Documentation/gpio/consumer.txt

2、老版本接口(legacy)

前缀为:gpio_

参考:Documentation/gpio/gpio-legacy.txt

3、常用API

功能 新版本接口 老版本接口
获取GPIO gpiod_get() gpio_request()
释放GPIO gpiod_put() gpio_free()
GPIO方向 设置为输入:gpiod_direction_input()设置为输出:gpiod_direction_output()获取方向:gpiod_get_direction() 设置为输入:gpio_direction_input()设置为输出:gpio_direction_output()
GPIO值 获取输入值:gpiod_get_value()设置输出值:gpiod_set_value() 获取输入值:gpio_get_value()设置输出值:gpio_set_value()

GPIO还有很多接口,就不一一列举了。

RK3399 GPIO控制器驱动实现文件:drivers/pinctrl/pinctrl-rockchip.c,涉及主要函数:

static const struct gpio_chip rockchip_gpiolib_chip = {
        .request = gpiochip_generic_request,
        .free = gpiochip_generic_free,
        .set = rockchip_gpio_set,
        .get = rockchip_gpio_get,
        .get_direction  = rockchip_gpio_get_direction,
        .direction_input = rockchip_gpio_direction_input,
        .direction_output = rockchip_gpio_direction_output,
        .to_irq = rockchip_gpio_to_irq,
        .owner = THIS_MODULE,
};

所有GPIO子系统的API最终都会调到SOCGPIO控制器驱动函数。

四、GPIO调试

ROCKPi 4A单板有个40个引脚的扩展口,引用radxa图片,见下图。

image.png

GPIO2_A7为例,介绍GPIO的一般调试方法。

1、进入测试目录

root@linaro-alip:/sys/class/gpio# ls
export  gpiochip0  gpiochip128  gpiochip32  gpiochip64  gpiochip96  unexport

2、导出GPIO

在使用GPIO2_A7前,需要导出该引脚。方法:配置export后,会出现gpio71节点。

root@linaro-alip:/sys/class/gpio# echo 71 > export
root@linaro-alip:/sys/class/gpio# ls
export  gpiochip0    gpiochip32  gpiochip96
gpio71  gpiochip128  gpiochip64  unexport

测试时,注意不要使用在程序中已经申请过或配置为其它功能的GPIO引脚。

3、配置GPIO方向

设置GPIO2_A7的输入/输出方向。

root@linaro-alip:/sys/class/gpio# cd gpio71/
root@linaro-alip:/sys/class/gpio/gpio71# ls
active_low  device  direction  edge  power  subsystem  uevent  value
root@linaro-alip:/sys/class/gpio/gpio71# cat direction
in
root@linaro-alip:/sys/class/gpio/gpio71# echo out > direction
root@linaro-alip:/sys/class/gpio/gpio71# cat direction
out

in:表示输入。

out:表示输出。

active_low:用于中断配置中高电平或低电平有效。

edge:用于中断配置中上升沿或下降沿有效。

4、配置GPIO输出值

GPIO为输入时,通过value查询GPIO的输入电平(高或低电平)。

GPIO为输出时,通过value配置GPIO的输出电平(高或低电平)。

root@linaro-alip:/sys/class/gpio/gpio71# cat value
0
root@linaro-alip:/sys/class/gpio/gpio71# echo 1 > value
root@linaro-alip:/sys/class/gpio/gpio71# cat value
1
root@linaro-alip:/sys/class/gpio/gpio71# echo 0 > value
root@linaro-alip:/sys/class/gpio/gpio71# cat value
0

5、查看GPIO

查看已经导出的GPIO71

root@linaro-alip:/sys/kernel/debug# cat gpio
GPIOs 0-31, platform/pinctrl, gpio0:
 gpio-4   (                    |bt_default_wake_host) out hi
 gpio-9   (                    |bt_default_reset    ) out hi
 gpio-10  (                    |reset               ) out lo

GPIOs 32-63, platform/pinctrl, gpio1:
 gpio-35  (                    |vcc5v0_otg          ) out hi
 gpio-46  (                    |vsel                ) out lo
 gpio-49  (                    |vsel                ) out lo

GPIOs 64-95, platform/pinctrl, gpio2:
 gpio-71  (                    |sysfs               ) in  hi   ## GPIO71
 gpio-83  (                    |bt_default_rts      ) out lo
 gpio-90  (                    |vcc3v3_pcie         ) out hi
 gpio-91  (                    |bt_default_wake     ) out hi

GPIOs 96-127, platform/pinctrl, gpio3:
 gpio-111 (                    |mdio-reset          ) out hi
 gpio-124 (                    |?                   ) out lo
 gpio-125 (                    |?                   ) out lo

GPIOs 128-159, platform/pinctrl, gpio4:
 gpio-153 (                    |vcc5v0_host         ) out hi

6、取消导出

使用完GPIO2_A7后,需要进行释放。方法:配置unexport后,gpio71节点会消失。

root@linaro-alip:/sys/class/gpio/gpio71# cd ..
root@linaro-alip:/sys/class/gpio# ls
export  gpiochip0    gpiochip32  gpiochip96
gpio71  gpiochip128  gpiochip64  unexport
root@linaro-alip:/sys/class/gpio# echo 71 > unexport
root@linaro-alip:/sys/class/gpio# ls
export  gpiochip0  gpiochip128  gpiochip32  gpiochip64  gpiochip96  unexport

注:转载请标注出处。

有关Linux内核gpio的更多相关文章

  1. ruby - 为什么 Object 在 Ruby 中既包含内核又继承它? - 2

    在Ruby(1.8.X)中为什么Object既继承了内核又包含了内核?仅仅继承还不够吗?irb(main):006:0>Object.ancestors=>[Object,Kernel]irb(main):005:0>Object.included_modules=>[Kernel]irb(main):011:0>Object.superclass=>nil请注意,在Ruby1.9中情况类似(但更简洁):irb(main):001:0>Object.ancestors=>[Object,Kernel,BasicObject]irb(main):002:0>Object.included

  2. 【Linux操作系统】——网络配置与SSH远程 - 2

    Linux操作系统——网络配置与SSH远程安装完VMware与系统后,需要进行网络配置。第一个目标为进行SSH连接,可以从本机到VMware进行文件传送,首先需要进行网络配置。1.下载远程软件首先需要先下载安装一款远程软件:FinalShell或者xhell7FinalShellxhell7FinalShell下载:Windows下载http://www.hostbuf.com/downloads/finalshell_install.exemacOS下载http://www.hostbuf.com/downloads/finalshell_install.pkg2.配置CentOS网络安装好

  3. Linux磁盘分区中物理卷(PV)、卷组(VG)、逻辑卷(LV)创建和(LVM)管理 - 2

    文章目录一基础定义二创建逻辑卷2-1准备物理设备2-2创建物理卷2-3创建卷组2-4创建逻辑卷2-5创建文件系统并挂载文件三扩展卷组和缩减卷组3-1准备物理设备3-2创建物理卷3-3扩展卷组3-4查看卷组的详细信息以验证3-5缩减卷组四扩展逻辑卷4-1检查卷组是否有可用的空间4-2扩展逻辑卷4-3扩展文件系统五删除逻辑卷5-1备份数据5-2卸载文件系统5-3删除逻辑卷5-4删除卷组5-5删除物理卷六LVM逻辑卷缩容6-1缩容注意事项6-2标准缩容步骤一基础定义LVM,LogicalVolumeManger,逻辑卷管理,Linux磁盘分区管理的一种机制,建立在硬盘和分区上的一个逻辑层,提高磁盘分

  4. ruby - 如何在 Ruby 中获取 linux 系统信息 - 2

    如何在Ruby中获取linux系统(这必须适用于Fedora、Ubuntu等)的软件/硬件信息? 最佳答案 Chef背后的优秀人才,拥有一颗名为Ohai的优秀gemhttps://github.com/opscode/ohai以散列形式返回系统信息,例如操作系统、内核、规范、fqdn、磁盘、空间、内存、用户、接口(interface)、sshkey等。它非常完整,非常好。它还会安装命令行二进制文件(也称为ohai)。 关于ruby-如何在Ruby中获取linux系统信息,我们在Stack

  5. ruby - rbenv:在 Linux Mint 上找不到 gem 命令 - 2

    我在LinuxMint17.2上。我最近使用apt-getpurgeruby​​删除了ruby​​。然后我安装了rbenv然后rbenvinstall2.3.0所以现在,~/.rbenv/versions/2.3.0/bin/ruby存在。但是现在,我无法执行geminstallrubocop。我明白了:$geminstallrubocoprbenv:gem:commandnotfoundThe`gem'commandexistsintheseRubyversions:2.3.0但是我可以~/.rbenv/versions/2.3.0/bin/geminstallrubocop。但是,

  6. ruby - 在 Linux 上编译 Ruby 1.9.2 所需的先决条件? - 2

    我是Ruby和RoR的新手。我有一个带有Ubuntu镜像的干净Linode实例,我想从源代码编译Ruby而不是使用apt-get。我已经在谷歌上搜索了执行此操作的说明,但经过一些尝试后,当我尝试运行一些教程示例时,我不断收到有关缺少zlib和其他一些包的错误。任何人都可以给我详细的说明(或链接),教我如何在从源代码编译Ruby之前安装必要的必备包吗?我的目的是编译Ruby的最新稳定版本,然后安装Rubygems和Rails。提前感谢您的帮助!!! 最佳答案 Thisblogpost涵盖从源代码编译ruby​​所需的包和安装过程;它引

  7. ruby - 为什么会存在 Ruby 模块内核? - 2

    在Ruby中的面向对象设计一书中,SandiMetz说模块的主要用途是用它们实现鸭子类型,并将它们包含在每个需要的类中。为什么RubyKernel是包含在Object中的模块?据我所知,它没有在其他任何地方使用。使用模块有什么意义? 最佳答案 理想情况下,Methodsinspirit(适用于任何对象),即使用接收器的方法,应在Object上定义上课,而Procedures(全局提供),即忽略接收者的方法,应该收集在Kernel中模块。Kernel#puts,例如不对其接收者做任何事情;它不调用它的私有(private)方法,它不访

  8. 驱动开发:内核无痕隐藏自身分析 - 2

    在笔者前面有一篇文章《驱动开发:断链隐藏驱动程序自身》通过摘除驱动的链表实现了断链隐藏自身的目的,但此方法恢复时会触发PG会蓝屏,偶然间在网上找到了一个作者介绍的一种方法,觉得有必要详细分析一下他是如何实现的进程隐藏的,总体来说作者的思路是最终寻找到MiProcessLoaderEntry的入口地址,该函数的作用是将驱动信息加入链表和移除链表,运用这个函数即可动态处理驱动的添加和移除问题。MiProcessLoaderEntry(pDriverObject->DriverSection,1)添加MiProcessLoaderEntry(pDriverObject->DriverSection,

  9. Linux网络编程必备的POSIX API的细节 - 2

    目录POSIXAPI大集合五元组三次握手的过程,内核协议栈分析listen函数DDOS攻击,洪水攻击DDOS攻击的应对措施数据发送 怎么保证顺序?如何保证包地顺序到达(序号+确认应答机制+重传)TCP断开连接的过程问题1.大量的CLOSE_WAIT+FIN_WAIT2是为啥?time_wait状态存在的原因?POSIXAPI大集合五元组(sip,sport,dip,dport,protocol)三次握手的过程,内核协议栈分析内核协议栈中是有内核数据结构的.  我们send/write数据,都是先发送到内核协议栈中,然后由内核协议栈封装发送到物理介质中传输到对端的对端的接收过程也是经有内核协议栈

  10. Linux export 命令及如何删除export设置的环境变量 - 2

    背景:Linuxexport命令用于设置或显示环境变量。在shell中执行程序时,shell会提供一组环境变量。export可新增,修改或删除环境变量,供后续执行的程序使用。export的效力仅限于该次登陆操作。语法:export[-fnp][变量名称]=[变量设置值]参数说明:-f 代表[变量名称]中为函数名称。-n 删除指定的变量。变量实际上并未删除,只是不会输出到后续指令的执行环境中。-p 列出所有的shell赋予程序的环境变量。实例:列出当前所有的环境变量#export-p//列出当前的环境变量值定义环境变量赋值#exportMYENV=7//定义环境变量并赋值添加环境变量:默认保存在

随机推荐