使用"gpiolib"实现框架的平台可选择配置一个GPIO的sysfs用户接口,这不同于debugfs接口,因为它提供GPIO方向和值的控制,而不仅是显示gpio状态摘要,另外,它可再没有调试支持的产品级系统中使用。
为系统提供合适的硬件文档,比如,用户空间可知道GPIO23控制Flash的写保护引脚,用来保护bootloader分区。系统升级处理可能需要临时接触此保护,寿险需要导入一个GPIO,再改变它的输出状态,然后在重新使能写保护前升级代码。一般情况下,GPIO23不会被触及,内核也不需要知道它。
根据合适的硬件文档,一些系统用户空间GPIO可用来确定标准内核不知道的系统配置数据。在某些任务中,简单的用户控件GPIO驱动可能是系统真正需要的。
请注意,标准内核驱动已经有通用的“LED和按键”的GPIO任务:leds-gpio和gpio_keys,使用这些来替代直接访问GPIO,因为它们和内核框架更好的配合,这比你用户控件代码更好。
1. GPIO在Sysfs中的路径
在/sys/class/gpio中有三类入口:
(1) 用来获取GPIO用户控件控制的控制接口
控制接口是只写的,有export和unexport。
1) Export文件
用户空间可通过写具体的GPIO编号给此文件来请求内核导出此GPIO的控制,比如echo 19 > export,如果内核没有申请GPIO19,将会创建gpio19节点
2) Unexport文件
“unexport”可恢复内核导出gpio节点,比如echo 19 > unexport,将删除创建的gpio19节点。
(2) GPIO本身
GPIO信号有类似于/sys/class/gpio/gpio42/(对于GPIO42来说)和有下面的读/写属性:
1) Direction
读取的值为“in”或“out”,此值通常被写入,写入“out”时默认输出低电平。
2) Value
读取的值为0(低电平)或1(高电平),如果GPIO配置为输出,此值允许写,任何非零值多当做高电平。
如果引脚可配置为中断模式和如果已经配置为中断模式(看”edge”的描述),你可以轮询poll(2)此文件和再中断触发时返回。如果你使用轮询select(2),设置exceptfds中的文件描述符,在轮询poll(2)返回后,要么通过lseek(2)读取此sysfs文件最开始的地方,要么关闭此文件并重新打开它来读取数据。
3) Edge
“edge”读取的值为“none”,“rising”,“falling”或是”both”,写这些值到此文件可以选择边沿触发模式,这样,在“value”文件上的轮询操作会返回。
4) Active_low
读取的值为0(false)或是1(true),用于决定value中的值是否进行翻转。当值为“0”时,value中的“0”表示低电平,“1”表示高电平;当值为“1”时,value中的“1”表示低电平,“0”表示高电平。
(3) GPIO控制器(“gpiochip实例”)
这里有17个gpiochipN,通过到arch/arm/boot/dts/qcom目录下的字符串“gpio-controller”可以查找出来。
GPIO控制有类似于/sys/class/gpio/gpiochip42/(对于从GPIO42开始实现控制的控制器)和有下面只读属性。
/sys/class/gpio/gpiochipN/
1) Base:文件,只读
和N相同,此芯片管理的第一个GPIO编号。
2) Label:文件,只读
设备信息,用于诊断(并不总是唯一的)
这里的1000000和modalias的值表示地址对应于msm8937-pinctrl.dtsi下面的内容:
&soc {
tlmm:pinctrl@1000000 {
compatible= "qcom,msm8937-pinctrl";
…
3) Ngpio:文件,只读
此芯片管理的GPIO总数(N到N+ngpio-1)
4) Device:目录,指chip。
Driver表示对应的驱动,怎么知道对应哪个驱动呢?发现一个方法:
Gpio:是gpiochipN的符号链接
进入drivers目录下执行su命令,就显示对应的驱动,比如这是msm8937-pinctrl
5) Power:目录,设备供电方面的相关信息
6) Subsystem:目录,符号链接,指向父目录
7) Uevent:文件,读写,内核与udev(自动设备发现程序)之间的通信接口
大多数情况下,板级文档应注明每个GPIO的使用目的,但是那些编号并不总是固定的,比如子板卡的GPIO依赖于所使用的的主板或是堆叠架构中其他板而有所不同,在这种情况下,你可能需要使用gpiochip节点(尽可能结合电路图)来确认给定信号所用的GPIO编号。
2. 从内核代码中导出
内核代码可显示管理那些已通过gpio_request()申请的GPIO的导出
/* export the GPIO to userspace */导出GPIO到用户空间
intgpiod_export(struct gpio_desc *desc, bool direction_may_change);
/*reverse gpio_export() */gpio_expor()的逆操作,取消GPIO的导出
voidgpiod_unexport(struct gpio_desc *desc);
/*create a sysfs link to an exported GPIO node */创建一个sysfs连接到一个已导出的GPIO节点。
intgpiod_export_link(struct device *dev, const char *name,
struct gpio_desc *desc);
/*change the polarity of a GPIO node in sysfs */
intgpiod_sysfs_set_active_low(struct gpio_desc *desc, int value);
在一个内核驱动申请一个GPIO后,它通过gpiod_export()使它在sysfs接口可见(如gpio19).该驱动能控制信号方向是否可修改,这有助于驱动防止用户空间代码意外破坏重要的系统状态。
此显示导出有助于调试(可更容易做一些实验),也可以体用一个始终存在的接口,与文档配合作为板级支持包的一部分。
在GPIO被导出之后,gpiod_export_link()允许在sysfs文件系统的任何地方创建一个到该GPIO sysfs节点的符号链接。这样驱动就可以通过一个描述性名字,在sysfs中他们所拥有的设备下提供一个接口(到该GPIO sysfs节点的)。
Drivers can usegpiod_sysfs_set_active_low() to hide GPIO line polarity
differences between boards from user space.Polarity change can be done both
before and after gpiod_export(), andpreviously enabled poll(2) support for
either rising or falling edge will bereconfigured to follow this setting.
参考:
内核自带文档
\Documentation\gpio\sysfs.txt
Linux下用文件IO的方式操作GPIO(/sys/class/gpio)
http://blog.sina.com.cn/s/blog_7880d3350102w2um.html
linux gpio 控制 基于sysfs
http://gofly.blog.51cto.com/4344767/1685747
Documentation/gpio.txt 的中文翻译
http://blog.csdn.net/viewsky11/article/details/53192767