一篇文章讲明白Linux下控制GPIO的三种方法

简介: 一篇文章讲明白Linux下控制GPIO的三种方法

1. 应用空间控制gpio

1.1简介

在/sys/class/gpio/下有个export文件,向export文件写入要操作的GPIO号,使得该GPIO的操作接口从内核空间暴露到用户空间,GPIO的操作接口包括direction和value等,direction控制GPIO输入或者输出模式,而value可控制GPIO的状态或者读取状态。

/sys/class/gpio/目录下各个文件说明:

/sys/class/gpio/export文件用于通知系统需要导出控制的GPIO引脚编号;

/sys/class/gpio/unexport 用于通知系统取消导出;

/sys/class/gpio/gpioX/direction文件,可以写入in(设置输入方向)或out(设置输出方向);

/sys/class/gpio/gpioX/value文件是可以读写GPIO状态;

/sys/class/gpio/gpiochipX目录保存系统中GPIO寄存器的信息,包括每个寄存器控制引脚的起始编号,寄存器名称,引脚总数;其中X表示具体的引脚编号。

1.2操作gpio

比如我要操作GPIO8_A6作为高电平输出有效, 那么有以下三个操作:

1. 2.1 换算对应的gpio number

可以通过/sys/kernel/debug/gpio查询信息:

root@rk3288:/sys/kernel/debug # cat gpio

//snip

GPIOs 184-215, //代码效果参考:http://www.zidongmutanji.com/zsjx/506317.html

platform/ff770000.pinctrl, gpio6:

gpio-193 (? ) in hi

gpio-194 (? ) in hi

GPIOs 216-247, platform/ff770000.pinctrl, gpio7:

gpio-218 (enable ) out hi

gpio-219 (lcd_en ) in hi

gpio-220 (lcd_cs ) in hi

gpio-221 (gslX680 wake pin ) out hi

gpio-222 (gslX680 irq pin ) out lo

gpio-223 (headset_gpio ) in hi

gpio-233 (? ) in hi

gpio-234 (? ) in hi

GPIOs 248-279, platform/ff770000.pinctrl, gpio8:

GPIOs 280-311, platform/ff770000.pinctrl, gpio15:

可以看到gpio8是以nubmer为248开始, 那么GPIO8_A6就是 248 + 6 = 254,接下来就可以导出gpio了。

root@rk3288:/sys/class/gpio # echo 254 > export

root@rk3288:/sys/class/gpio # ls

export

gpio254

1.2.2 设置成输出

root@rk3288:/sys/class/gpio/gpio254 # echo out > direction

root@rk3288:/sys/class/gpio/gpio254 # cat direction

out

1.2.3 输出高电平

root@rk3288:/sys/class/gpio/gpio254 # echo 1 > value

root@rk3288:/sys/class/gpio/gpio254 # cat //代码效果参考:http://www.zidongmutanji.com/bxxx/195682.html

value

1.3 总结

这种方式一般不采用,为了gpio使用的安全性,一般是不将gpio的使用权暴露给应用层的,即sys/class/下没有gpio节点。

2. 内核空间控制gpio

在内核空间控制gpio有两种方法,第一种是通过调用gpiolib的接口来控制gpio;第二种是通过ioremap来控制gpio。

2.1 gpiolib控制gpio

2.1.1 gpiolib简介

Linux Kernel 中对 GPIO 资源进行了抽象,抽象出一个叫做 Gpiolib 的东西。

中间层是 Gpiolib,用于管理系统中的 GPIO。Gpiolib 汇总了 GPIO 的通用操作,根据 GPIO 的特性,Gpiolib 对上(其他 Drivers)提供的一套统一通用的操作 GPIO 的软件接口,屏蔽了不同芯片的具体实现。对下,Gpiolib 提供了针对不同芯片操作的一套 framework,针对不同芯片,只需要实现 Specific Chip Driver ,然后使用 Gpiolib 提供的注册函数,将其挂接到 Gpiolib 上,这样就完成了这一套东西。

2.1.2 Gpiolib 为其他驱动提供的 APIs

int gpio_request(unsigned gpio, const char label);

/向内核申请 gpio,要使用 GPIO 首先应该向内核进行申请,返回 0,代表申请成功,

可以进行后续操作/

void gpio_free(unsigned gpio);

/对应 gpio_request,是使用完gpio以后把gpio释放掉/

int gpio_direction_input(unsigned gpio);

/设置 GPIO 为输入/

int gpio_direction_output(unsigned gpio, int value);

/设置 GPIO 为输出/

int gpio_get_value(unsigned gpio);

/读取 GPIO 的值/

int gpio_set_value(unsigned gpio);

/设置 GPIO 的值/

2.1.3 操作gpio

功能和1.2一样。

#define GPIO8_A6 254

ret = gpio_request(GPIO8_A6 , "gpio8_a6");

if (!ret) {

printk("request for gpio8_a6 failed:%d\n", ret);

return 0;

}

gpio_direction_output(GPIO8_A6 ,1);//设置GPIO8_A6为输出功能且输出高电平

2.2 ioremap控制gpio

这种方法会降低程序的可读性,不建议使用。

linux内核空间访问的地址为虚拟地址(3~4GB),故在内核空间操作某个寄存器时,需先通过ioremap函数将物理地址映射成虚拟地址。

用ioremap() 获取寄存器的地址:

unsigned int iomem *base_addr1; //iomem可选择,告诉你为虚拟地址

#define GPIO8_REGBASE (0x20A0000)

#define GPIO8_A6 ((volatile unsigned int )(base_addr1 + 6)) //指针unsigned int为4字节,指针加1,字节加4

base_addr1 = ioremap(GPIO8_REGBASE, 0x14)

通过 readl() 或者 writel() 函数直接操作映射后的地址:

GPIO8_A6 |= (1[8);

int temp;

temp = readl(GPIO8_A6);

temp |= (1[8);

writel(temp, GPIO8_A6);

使用完后,取消映射:

iounmap(base_addr1);

3. 查看GPIO全部信息

cat /sys/kernel/debug/pinctrl/pinctrl/pinmux-pins

Pinmux settings per pin

Format: pin (name): mux_owner gpio_owner hog?

pin 0 (gpio0-0): wireless-wlan (GPIO UNCLAIMED) function wireless-wlan group wifi-wake-host

pin 1 (gpio0-1): (MUX UNCLAIMED) (GPIO UNCLAIMED)

pin 2 (gpio0-2): (MUX UNCLAIMED) gpio0:2

pin 3 (gpio0-3): (MUX UNCLAIMED) (GPIO UNCLAIMED)

pin 4 (gpio0-4): (MUX UNCLAIMED) (GPIO UNCLAIMED)

pin 5 (gpio0-5): (MUX UNCLAIMED) gpio0:5

pin 6 (gpio0-6): (MUX UNCLAIMED) (GPIO UNCLAIMED)

pin 7 (gpio0-7): (MUX UNCLAIMED) gpio0:7

pin 8 (gpio0-8): (MUX UNCLAIMED) (GPIO UNCLAIMED)

pin 9 (gpio0-9): (MUX UNCLAIMED) (GPIO UNCLAIMED)

pin 10 (gpio0-10): (MUX UNCLAIMED) (GPIO UNCLAIMED)

pin 11 (gpio0-11): ff050000.i2c (GPIO UNCLAIMED) function i2c1 group i2c1-xfer

pin 12 (gpio0-12): ff050000.i2c (GPIO UNCLAIMED) function i2c1 <span class="hljs-keyword

相关文章
|
1月前
|
Linux Python
在Linux下升级到Python3的两种方法
在Linux下升级到Python3的两种方法
105 0
|
20天前
|
Linux
linux不同场景下修改文件名的五种方法
linux不同场景下修改文件名的五种方法
13 1
|
12天前
|
自然语言处理 安全 Shell
Linux 提权-SUID/SGID_1 本文通过 Google 翻译 SUID | SGID Part-1 – Linux Privilege Escalation 这篇文章所产生,本人仅是对机器翻译中部分表达别扭的字词进行了校正及个别注释补充。
接下来,让我们看看 SUID3NUM 在枚举 SUID 二进制文件方面的表现如何。 3.2、枚举 SUID 二进制文件 – SUID3NUM 我们将用来枚举 SUID 二进制文件的第二个工具是 SUID3NUM。这是一个很棒的工具,因为它是专门为枚举 SUID 二进制文件而创建的。但这还不是全部,它还提供了可用于提升权限的命令(命令从 GTFOBins 中提取)。 这还不是最好的部分,SUID3NUM 还具有内置的 autopwn 功能,可以通过 -e 开关激活! 在 OSCP 考试中也使用此工具,只要您不使用自动利用功能。 3.2.1、下载并执行 SUID3NUM 我们可以从 GitHubs
10 0
|
1月前
|
Linux Python
在 Linux 中查看目录文件数的方法
【6月更文挑战第7天】在 Linux 中查看目录文件数的方法包括:使用 `ls` 命令结合 `wc -l`,`find` 命令,`tree` 命令,以及编程方式(如 Python)。`ls` 和 `find` 命令通过管道传递给 `wc -l` 统计行数,而 `tree` 命令提供树状视图并显示文件数。编程方式则允许自定义实现,例如 Python 中的 `os.walk()`。注意权限、效率和场景适用性,选择合适的方法以提高 Linux 操作效率。
45 3
|
1月前
|
Linux API 芯片
Linux GPIO 和 Pinctrl 子系统的使用(十四)
Linux GPIO 和 Pinctrl 子系统的使用(十四)
16 1
|
20天前
|
机器学习/深度学习 固态存储 Linux
一篇文章讲明白Linux下的ping命令用法与实现
一篇文章讲明白Linux下的ping命令用法与实现
17 0
|
21天前
|
Java 编译器 Linux
程序技术好文:详解Linux安装GCC方法
程序技术好文:详解Linux安装GCC方法
30 0
|
21天前
|
Unix Linux 调度
一篇文章讲明白linux僵死进程
一篇文章讲明白linux僵死进程
12 0
|
22天前
|
Linux 芯片
一篇文章讲明白Linux内核态和用户态共享内存方式通信
一篇文章讲明白Linux内核态和用户态共享内存方式通信
11 0
|
1月前
|
Linux Shell
保姆级只需五步linux中安装aapt(64位)的方法
保姆级只需五步linux中安装aapt(64位)的方法