我正试图配置我的Yocto Linux发行版来设置两个板上I2C GPIO扩展器,并记录如何以编程方式访问它们(即从C用户应用程序)。GPIO扩展器均为NXP PCA9557, GPIO -pca953x.c内核驱动支持。
我知道如何将这个驱动程序编译成内核(使用CONFIG_GPIO_PCA953X
配置选项)并加载它(使用modprobe
)。我也明白我可以在设备树中实例化这两个I2C设备(这是一个嵌入式设备,因此GPIO扩展器是静态和不变的):
gpio@20 {
compatible = "nxp,pca9557";
reg = <0x1a>;
gpio-controller;
#gpio-cells = <2>;
};
我缺乏的信息是如何使用gpio-pca953x驱动程序与这些实例化的设备?我需要将这些设备与特定的驱动程序关联吗?在用C编写的用户应用程序中,我使用什么api来访问它们?一旦我正确配置它们,它们是否就像普通的gpio一样?
我非常乐意阅读有关如何做到这一点的任何相关文档,无论冗长与否。我只是一个Linux设备驱动程序的初学者,不知道从哪里开始,尽管谷歌了很多。
正常工作时,驱动应在/dev
中提供一个gpiochipX
器件。这可以用于ioctl调用。
libgpiod
库为与这些设备交互提供了一个友好的API。
在Yocto中安装libgpiod
包。它附带了一些方便的命令行工具用于调试。
-
gpiodetect -列出系统中存在的所有gpiochip,它们的名称,标签和GPIO线数
-
gpioinfo -列出指定gpiochip的所有行,它们的名称,消费者,方向、活动状态和附加标志
-
gpioget -读取指定GPIO线的值
-
gpioset -设置指定GPIO线路的值,可能保留线路导出并等待超时,用户输入或信号
-
gpiofind -查找给定行名的gpiochip名称和行偏移
-
gpiomon -等待GPIO上的事件,指定要观察的事件。在退出事件之前要处理多少事件应该报告到控制台
如果你没有这个文件,那么驱动程序没有启动。查看dmesg
是否有线索。
# dmesg | grep pca953x
[ 0.208762] pca953x 1-0020: using AI
您还可以检查pca芯片是否可以在i2c上访问。列出i2c总线并找出pca9557在哪个总线上。
# i2cdetect -l
i2c-0 21a0000.i2c
i2c-1 21a4000.i2c
i2c-2 21a8000.i2c
假设pca芯片在i2c-1总线上。检测总线上的设备
# i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- UU -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
表中应该包含
UU
在1a地址如果pca953x驱动正在运行,1a
在1a地址,如果驱动程序不运行,但芯片是正常的,可以通过i2c控制,--
在1a地址,如果芯片关闭或其i2c地址实际上不是1a
。
有几种方法可以从用户空间控制GPIO,但是您试图控制的是什么?Linux可以使用GPIO作为LED, key, interrupt等。
sysfs是"老"吗?控制gpio的方法。它是有效的,而且还在维护中。实际上,您在/sys目录中编写节点。在c中,写文件是一个简单的过程。如果你愿意,你可以先在Shell中测试写文件。
$ echo 7 > /sys/class/gpio/export
$ echo "out" > /sys/class/gpio/gpio7/direction
$ echo 1 > /sys/class/gpio/gpio7/value #turn on
$ echo 0 > /sys/class/gpio/gpio7/value #turn off
有一种访问GPIO的新方法。您可以打开/dev/chip并进行一些IOCTL调用。包含#include <linux/gpio.h>
然后
GPIO_GET_LINEHANDLE_IOCTL
,查看当前状态GPIOHANDLE_GET_LINE_VALUES_IOCTL
然后读取GPIOHANDLE_SET_LINE_VALUES_IOCTL
写入
您可以使用使用相同接口的Shell程序来测试它。
$ gpiodetect
$ gpioinfo
$ gpioset
我从来没有这样做过,但是这里有一个示例工具可以这样做。在5.9之后的内核中,你也可以使用#include "gpio-utils.h"
。