Linux Yocto环境下如何编程使用PCA9557型I2C GPIO扩展器开发C应用
驱动与设备树节点的自动匹配机制
- 驱动和静态设备的绑定完全靠内核设备模型的自动匹配流程完成,不需要手动执行绑定操作,只要满足两个核心条件就能正常关联:
- 设备树中的
gpio@xx节点必须直接作为对应I2C总线控制器的子节点存在(比如片上I2C0、I2C1节点的内部子节点),否则I2C总线枚举流程不会扫描到这个静态注册的硬件 - 节点上声明的
compatible = "nxp,pca9557"字符串,必须和gpio-pca953x驱动内置的设备匹配表中的字符串完全一致
- 设备树中的
- 匹配的完整流程:内核启动阶段,I2C总线会遍历所有注册的子节点,将每个节点的compatible属性和已加载的
gpio-pca953x驱动的匹配表做字符串比对,一旦命中匹配项,就会自动执行驱动的probe函数,完成PCA9557的硬件初始化、GPIO控制器注册全流程。 - 匹配失败的常规排查方向:
- 核对硬件设计的I2C地址,设备树中的
reg属性值必须和芯片地址引脚拉定的实际地址完全一致 - 通过
dmesg | grep pca953x查看内核启动日志,如果出现匹配失败、设备无响应的报错,优先核对compatible拼写、I2C总线挂载路径、设备地址这几个配置项是否匹配硬件实际设计。
- 核对硬件设计的I2C地址,设备树中的
扩展GPIO的访问统一性
正确完成驱动绑定后,PCA9557引出的所有GPIO引脚和SoC原生GPIO的访问逻辑完全一致,没有任何区别。gpio-pca953x驱动会将每片PCA9557的8个引脚作为独立的GPIO控制器注册到内核统一的GPIO子系统中,所有内核态、用户态的GPIO操作接口对扩展引脚和原生引脚是完全无差别的,不需要为扩展引脚编写特殊的访问适配逻辑。
针对板上的2颗扩展器,只需要在设备树中按照硬件实际连接的总线、地址添加对应的两个节点,驱动会自动为每颗设备生成独立的GPIO控制器实例,不需要额外修改驱动代码。
C用户态应用的访问实现
目前有两种成熟的用户态访问方式,生产环境优先推荐第一种:
标准方式:GPIO字符设备 + libgpiod
这是当前内核官方维护的GPIO用户态访问标准,替代了已经被标记为废弃的传统sysfs接口,从Linux 4.8版本开始正式引入。
- 前置准备:在Yocto镜像中集成
libgpiod软件包,即可获得对应的C语言API库和配套的测试命令行工具 - 核心C API使用逻辑:
- 通过GPIO控制器编号或名称打开对应扩展器的设备节点:
gpiod_chip_open_by_number/gpiod_chip_open_by_name - 锁定目标GPIO引脚,配置引脚的工作模式(输入/输出)、默认电平:
gpiod_line_request_input/gpiod_line_request_output - 读写引脚电平:
gpiod_line_get_value/gpiod_line_set_value - 操作完成后释放引脚锁、关闭设备句柄:
gpiod_line_release/gpiod_chip_close
- 通过GPIO控制器编号或名称打开对应扩展器的设备节点:
- 硬件连通性验证:编写应用前可直接使用libgpiod提供的命令行工具测试,比如通过
gpiodetect列出系统所有注册的GPIO控制器,通过gpioget/gpioset命令读写对应引脚电平,确认硬件连接和驱动配置正常后再进行应用开发。
兼容legacy代码:传统sysfs GPIO接口
这是Linux早期的GPIO用户态访问方式,目前已经在新内核中被标记为废弃,后续版本会逐步移除,但大量存量老代码依然在使用该方式:
- 访问逻辑:
- 先通过
/sys/class/gpio/目录下的gpiochip节点,确认每片扩展器的GPIO全局起始编号 - 将目标GPIO的全局编号写入
/sys/class/gpio/export文件,完成引脚的用户态导出 - 在自动生成的引脚目录下,通过写入
direction文件配置输入/输出模式,读写value文件完成电平操作
- 先通过
- 注意:该方式需要应用程序具备sysfs文件系统的读写权限,不适合在有权限隔离、实时性要求的生产环境中使用。
内容的提问来源于stack exchange,提问作者Brett Rushlow
相关产品推荐
相关产品推荐

