适用于用户空间的 GPIO Sysfs 接口¶
警告
此 API 已被GPIO 字符设备用户空间 API废弃,且 ABI 文档已移至ABI 文件 obsolete/sysfs-gpio。
新的开发应使用GPIO 字符设备用户空间 API,并鼓励现有开发尽快迁移,因为此 API 将来会被移除。
此接口在迁移期间将继续维护,但新功能只会添加到新的 API 中。
废弃的 sysfs ABI¶
使用“gpiolib”实现者框架的平台可以选择配置一个 sysfs 用户接口来访问 GPIO。这与 debugfs 接口不同,因为它提供对 GPIO 方向和值的控制,而不仅仅是显示 GPIO 状态摘要。此外,它可以在没有调试支持的生产系统上存在。
如果系统有适当的硬件文档,用户空间例如可以知道 GPIO #23 控制用于保护闪存中引导加载器段的写保护线。系统升级过程可能需要暂时移除该保护,首先导入一个 GPIO,然后改变其输出状态,接着更新代码,最后重新启用写保护。在正常使用中,GPIO #23 永远不会被触及,内核也无需了解它。
同样,根据适当的硬件文档,在某些系统上,用户空间 GPIO 可以用于确定标准内核无法了解的系统配置数据。对于某些任务,简单的用户空间 GPIO 驱动程序可能就是系统真正所需的全部。
Sysfs 中的路径¶
/sys/class/gpio 中有三种条目:
用于获取用户空间对 GPIO 控制的接口;
GPIO 本身;以及
GPIO 控制器(“gpio_chip”实例)。
这些是除了包括“device”符号链接在内的标准文件之外的。
控制接口是只写(write-only)的
/sys/class/gpio/
- “export”...
用户空间可以通过将 GPIO 号写入此文件来请求内核将 GPIO 的控制权导出到用户空间。
示例:“echo 19 > export”将为 GPIO #19 创建一个“gpio19”节点,如果内核代码尚未请求此节点。
- “unexport”...
撤销导出到用户空间的效果。
示例:“echo 19 > unexport”将移除使用“export”文件导出的“gpio19”节点。
GPIO 信号的路径类似于 /sys/class/gpio/gpio42/(对于 GPIO #42),并具有以下读/写属性:
/sys/class/gpio/gpioN/
- “direction”...
读取时为“in”或“out”。此值通常可以写入。写入“out”时,默认将值初始化为低电平。为确保无毛刺操作,可以写入“low”和“high”值,以将 GPIO 配置为具有该初始值的输出。
请注意,如果内核不支持更改 GPIO 的方向,或者它是由未明确允许用户空间重新配置此 GPIO 方向的内核代码导出的,则此属性将不存在。
- “value”...
读取时为 0(非激活)或 1(激活)。如果 GPIO 配置为输出,则可以写入此值;任何非零值都被视为激活。
如果引脚可以配置为中断生成输入,并且已配置为生成中断(参见“edge”的描述),则可以对此文件进行 poll(2) 操作,当中断触发时 poll(2) 将返回。如果使用 poll(2),请设置事件 POLLPRI 和 POLLERR。如果使用 select(2),请在 exceptfds 中设置文件描述符。poll(2) 返回后,使用 pread(2) 读取偏移量为零的值。或者,可以 lseek(2) 到 sysfs 文件的开头并读取新值,或者关闭文件并重新打开以读取值。
- “edge”...
读取时为“none”、“rising”、“falling”或“both”。写入这些字符串以选择在“value”文件上进行 poll(2) 操作时将使其返回的信号边沿。
此文件仅在引脚可以配置为中断生成输入引脚时存在。
- “active_low”...
读取时为 0(假)或 1(真)。写入任何非零值以反转值属性,无论是读取还是写入。现有和后续的 poll(2) 通过 edge 属性对“上升”和“下降”边沿的支持配置将遵循此设置。
GPIO 控制器的路径类似于 /sys/class/gpio/gpiochip42/(用于实现从 #42 开始的 GPIO 的控制器),并具有以下只读属性:
/sys/class/gpio/gpiochipN/
- “base”...
与 N 相同,此芯片管理的第一个 GPIO
- “label”...
用于诊断(不总是唯一的)
- “ngpio”...
此芯片管理多少个 GPIO(N 到 N + ngpio - 1)
在大多数情况下,板级文档应该涵盖 GPIO 的用途。然而,这些编号并不总是稳定的;子卡上的 GPIO 可能会因所使用的基板或堆栈中的其他卡而异。在这种情况下,您可能需要使用 gpiochip 节点(可能结合原理图)来确定给定信号应使用的正确 GPIO 编号。
从内核代码导出¶
内核代码可以显式管理已使用 gpio_request() 请求的 GPIO 的导出。
/* export the GPIO to userspace */
int gpiod_export(struct gpio_desc *desc, bool direction_may_change);
/* reverse gpiod_export() */
void gpiod_unexport(struct gpio_desc *desc);
/* create a sysfs link to an exported GPIO node */
int gpiod_export_link(struct device *dev, const char *name,
struct gpio_desc *desc);
在内核驱动程序请求一个 GPIO 后,它只能通过gpiod_export()
在 sysfs 接口中可用。驱动程序可以控制信号方向是否可以改变。这有助于驱动程序防止用户空间代码意外破坏重要的系统状态。
这种显式导出有助于调试(通过使某些实验更容易),或者可以提供一个始终存在的接口,适合作为板级支持包的一部分进行文档化。
GPIO 导出后,gpiod_export_link()
允许从 sysfs 中的其他位置创建指向 GPIO sysfs 节点的符号链接。驱动程序可以使用此功能在 sysfs 中其自己的设备下提供带有描述性名称的接口。