Pinctrl和GPIO子系统

目录

  1. 1. Pinctrl子系统
    1. 1.1. 示例代码
    2. 1.2. 1. 主要功能
      1. 1.2.1. Pin Controller 概念
      2. 1.2.2. Client Device 概念
    3. 1.3. 2. 关键组件
    4. 1.4. 3. 使用示例
    5. 1.5. 4. API 接口
    6. 1.6. 5. 适用场景
    7. 1.7. 6. 总结
  2. 2. GPIO子系统
    1. 2.1. GPIO 控制器在设备树中的定义
    2. 2.2. 在设备节点中引用 GPIO 引脚
    3. 2.3. 在驱动代码中调用 GPIO 子系统
    4. 2.4. 在sysfs中访问GPIO的方式

Pinctrl 子系统<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>负责管理引脚的复用与配置<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>它允许将引脚配置为不同的功能<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>>如 GPIO<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>I2C<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>UART 等<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>并设置引脚的电气特性<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>>如上拉<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>下拉等<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg><h-char class=bd bd-beg>
GPIO 子系统<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg> 主要负责对通用输入输出引脚的管理<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>它提供 API 来配置引脚为输入或输出<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>并控制引脚的电平状态<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
层次结构<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg> Pinctrl 子系统位于 GPIO 子系统之上<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>Pinctrl 负责引脚的初步配置和复用<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>而 GPIO 子系统则利用这些配置来实现输入输出操作<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>两者有密切的关系<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>先配置Pinctrl<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>在配置GPIO<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

  • 引脚配置<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>首先<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>通过 Pinctrl 子系统配置引脚的功能<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>例如<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>将某个引脚设置为 GPIO 功能<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
  • 状态管理<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>然后<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>GPIO 子系统使用这些配置来管理引脚的电平状态<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>>读取或设置引脚电平<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg><h-char class=bd bd-beg>

Pinctrl子系统

pinctrl 子系统是 Linux 内核中用于管理 GPIO<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>>通用输入输出<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>引脚和其他引脚控制功能的一个重要组件<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>它的主要作用是提供一个统一的接口来配置和控制各种硬件引脚的功能<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>例如输入<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>输出<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>复用等<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>以下是对 pinctrl 子系统的详细介绍<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

在有pinctrl之前<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>一般直接操作硬件寄存器以配置 GPIO 引脚的方式通常涉及到访问特定的内存地址<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>在Imx6u平台上<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>展示如何在 Linux 驱动中直接访问寄存器来设置 GPIO 引脚的模式和状态<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

示例代码

假设我们有一个简单的硬件平台<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>其 GPIO 寄存器映射如下<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

  • GPIO 控制寄存器<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>>用于设置引脚模式<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
  • GPIO 数据寄存器<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>>用于读写引脚状态<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"highlight c"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"code"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"meta"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">#"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">include "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"><linux/module.h>
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"meta"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">#"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">include "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"><linux/kernel.h>
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"meta"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">#"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">include "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"><linux/init.h>
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"meta"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">#"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">include "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"><linux/io.h>
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"meta"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">#"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">define GPIO_BASE_ADDR 0x3F200000 "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 假设的 GPIO 基址
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"meta"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">#"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">define GPIO_SET_OFFSET 0x1C "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 设置 GPIO 引脚高电平的偏移量
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"meta"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">#"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">define GPIO_CLR_OFFSET 0x28 "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 清除 GPIO 引脚高电平的偏移量
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"meta"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">#"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">define GPIO_DIR_OFFSET 0x00 "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// GPIO 方向寄存器偏移量
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"meta"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">#"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">define GPIO_PIN 17 "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 假设我们操作 GPIO 17
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">static "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">void __iomem *gpio_base;
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">static "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">int __init "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"title function_"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">gpio_init"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"params"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">("bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">void) {
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 映射 GPIO 控制寄存器
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> gpio_base = ioremap(GPIO_BASE_ADDR, "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"number"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">0x1000);
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">if (!gpio_base) {
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> printk(KERN_ERR "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"Failed to map GPIO base address\n");
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">return -ENOMEM;
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> }
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 设置 GPIO_PIN 为输出
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">unsigned "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">int *gpio_dir = gpio_base + GPIO_DIR_OFFSET;
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> *gpio_dir |= ("bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"number"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">1 << GPIO_PIN); "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 将 GPIO_PIN 设置为输出模式
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 设置 GPIO_PIN 为高电平
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">unsigned "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">int *gpio_set = gpio_base + GPIO_SET_OFFSET;
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> *gpio_set = ("bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"number"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">1 << GPIO_PIN);
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> printk(KERN_INFO "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"GPIO %d is set to high\n", GPIO_PIN);
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">return "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"number"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">0;
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">}
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">static "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">void __exit "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"title function_"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">gpio_exit"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"params"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">("bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">void) {
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 清除 GPIO_PIN 的高电平
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">unsigned "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">int *gpio_clr = gpio_base + GPIO_CLR_OFFSET;
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> *gpio_clr = ("bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"number"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">1 << GPIO_PIN);
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 解除映射
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> iounmap(gpio_base);
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> printk(KERN_INFO "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"GPIO %d is set to low\n", GPIO_PIN);
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">}
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">module_init(gpio_init);
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">module_exit(gpio_exit);
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">MODULE_LICENSE("bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"GPL");
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">MODULE_AUTHOR("bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"Example Author");
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">MODULE_DESCRIPTION("bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"Direct GPIO Access Example");
  • 映射寄存器<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

    • 使用 ioremap() 函数将 GPIO 基地址映射到内核虚拟地址空间<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
  • 设置 GPIO 方向<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

    • 通过对 GPIO 方向寄存器进行位操作<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>将指定的 GPIO 引脚设置为输出模式<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
  • 设置引脚状态<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

    • 通过操作 GPIO 设置寄存器<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>将引脚设为高电平<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>通过 GPIO 清除寄存器可以将引脚设为低电平<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
  • 模块初始化与退出<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

    • 在模块初始化时配置 GPIO 引脚<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>并在模块卸载时清除引脚状态并解除映射<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

导致问题<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

  • 硬件依赖性<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>直接寄存器访问依赖于特定硬件平台的寄存器映射<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>具有很强的硬件依赖性<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>不易移植<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
  • 安全性<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>直接操作硬件寄存器时<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>必须确保不会引起冲突或不安全的状态<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
  • 错误处理<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>实际代码中应包含更多的错误处理逻辑<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>以确保健壮性<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

1. 主要功能

  • 引脚配置<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>允许用户设置每个引脚的模式<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>>如输入<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>输出<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>复用功能等<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg><h-char class=bd bd-beg>
  • 引脚状态管理<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>可以读写引脚的电平状态<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
  • 引脚复用<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>支持将同一引脚配置为不同的功能<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>以适应不同的硬件需求<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

在设备树<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>>Device Tree<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>中<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>Pin Controller 节点的格式并没有统一的标准<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>这意味着不同的芯片制造商可能会采用不同的方式来定义这些节点<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>尽管所有芯片都具备类似的功能概念<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>如引脚复用和配置<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>但具体的实现和描述方式各不相同<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

Pin Controller 概念

Pin Controller 是一个软件抽象概念<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>主要用于管理和配置芯片上的引脚功能<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>它并不是在芯片手册中可以直接找到的硬件模块<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>而是通过软件来实现引脚的复用和配置<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

  • 引脚复用<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>类似于 IOMUX<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>Pin Controller 允许将同一引脚配置为多种功能<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>>例如 GPIO<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>I2C<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>UART 等<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg><h-char class=bd bd-beg>
  • 引脚配置<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>除了复用功能外<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>Pin Controller 还可以配置引脚的电气特性<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>例如上下拉电阻<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>驱动强度等<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

Client Device 概念

Client Device<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>>客户设备<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>是指在 pinctrl 系统中<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>使用 Pin Controller 控制引脚的外设或模块<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>简而言之<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>Client Device 是依赖于 Pin Controller 提供的接口和功能的设备<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>Client Device 是使用 pinctrl 系统的设备<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>它通过 Pin Controller 配置和管理所需的引脚功能<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>以实现与主控芯片或其他设备的通信<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

在设备树<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>>Device Tree<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>中<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>Client Device 通常被定义为一个节点<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>该节点包含以下信息<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"highlight c"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"code"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">my_device: my_device@"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"number"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">0 {
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> compatible = "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"my_vendor,my_device";
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> pinctrl-names = "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"default";
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> pinctrl = <&pinctrl_0>; "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 引用 Pin Controller 配置
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 其他设备属性
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">};

在设备树中<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg><&pinctrl_0>; 是对 Pin Controller 配置的引用<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>它通常在设备树的某个部分定义<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>具体来说<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>pinctrl_0 是一个节点标签<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>>label<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg><h-char class=bd bd-beg>通常定义在 pinctrl 子系统部分<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>描述相关引脚的配置和功能<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"highlight c"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"code"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">&pinctrl {
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> pinctrl_0: pinctrl {
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> gpio1_pins: gpio1_pins {
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> fsl,pins = <MX6UL_PAD_GPIO1_IO16__GPIO1_IO16>;
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> };
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> gpio2_pins: gpio2_pins {
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> fsl,pins = <MX6UL_PAD_GPIO1_IO17__GPIO1_IO17>;
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> };
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 其他引脚配置
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> };
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">};

2. 关键组件

  • 设备树<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>pinctrl 使用设备树<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>>Device Tree<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>来描述硬件的引脚功能和配置<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>设备树中的节点定义了硬件平台的引脚布局和特性<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
  • pinctrl 驱动<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>每个硬件平台都有相应的 pinctrl 驱动<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>它实现了 pinctrl 子系统的接口<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>负责具体的硬件控制<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
  • GPIO 线路<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>pinctrl 提供的接口通常与 GPIO 线路紧密结合<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>允许用户在需要时直接控制 GPIO 引脚<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

驱动结构<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>每个硬件平台通常实现一个 pinctrl 驱动<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>负责解析设备树并配置引脚<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>引脚控制逻辑<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>驱动通过访问特定的寄存器来实现引脚的配置和状态管理<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

由BSP工程师完成<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>驱动程序使用特定的输入/输出操作函数<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>>如 readl 和 writel<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>来访问硬件寄存器<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>这些寄存器通常位于系统级芯片<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>>SoC<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>的地址空间中<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>负责控制引脚的功能和状态<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>驱动程序通过写入相应的寄存器值<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>配置引脚为特定的功能<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>例如将引脚设置为 GPIO<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>I2C 或 UART 等<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>驱动程序可以设置引脚为输入或输出模式<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>在输出模式下<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>驱动程序控制引脚的电平状态<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>在输入模式下<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>驱动程序读取引脚的电平状态<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

3. 使用示例

在设备树中<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>pinctrl 的定义通常如下<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"highlight dts"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"code"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"title class_"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">pinctrl "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"punctuation"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">{
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"symbol"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> pinctrl0: "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"title class_"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">pinctrl0 "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"punctuation"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">{
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"attr"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">pins "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"operator"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">= "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"gpio1", "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"gpio2""bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"punctuation"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">;
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"attr"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">function "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"operator"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">= "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"gpio""bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"punctuation"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">;
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"punctuation"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">};
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"punctuation"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">};

在 Linux 驱动中<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>使用 pinctrl API 进行引脚配置的一个简单示例<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"highlight c"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"code"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"class"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">struct "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"title"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">pinctrl *"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"title"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">pinctrl;
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"class"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">struct "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"title"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">pinctrl_state *"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"title"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">state;
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">pinctrl = devm_pinctrl_get(dev);
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">state = pinctrl_lookup_state(pinctrl, "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"pinctrl0");
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">pinctrl_select_state(pinctrl, state);

4. API 接口

pinctrl 提供了一系列的 API<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>主要包括<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

  • pinctrl_get()<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>获取 pinctrl 句柄<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
  • pinctrl_lookup_state()<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>查找特定的引脚状态<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
  • pinctrl_select_state()<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>选择并应用指定的引脚状态<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

5. 适用场景

  • 嵌入式系统<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>广泛应用于嵌入式设备中<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>以控制各种外设<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
  • 开发板<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>如 Raspberry Pi<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>BeagleBone 等<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>用户需要对 GPIO 进行灵活控制<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
  • 自定义硬件<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>在需要对硬件引脚进行特定配置的场景中<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

6. 总结

pinctrl 子系统是 Linux 内核中用于引脚管理的重要组成部分<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>它通过统一的接口简化了 GPIO 和引脚控制的复杂性<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>了解和使用 pinctrl 可以帮助开发者更有效地管理硬件资源<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>提高开发效率<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

GPIO子系统

在早期的嵌入式系统中<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>直接通过寄存器操作 GPIO 引脚的方式存在许多问题<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>尤其是在不同硬件平台上的兼容性<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>每个板子的 GPIO 控制代码往往需要完全不同的实现<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>导致代码重复和维护困难<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

驱动代码可以使用 GPIO 子系统提供的标准函数来操作 GPIO 引脚<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>而不需要关心底层的寄存器操作<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>这些标准函数包括<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

  • 获取 GPIO<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>申请使用特定的 GPIO 引脚<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
  • 设置 GPIO 方向<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>配置 GPIO 引脚为输入或输出<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
  • 读取/设置 GPIO 值<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>读取引脚的电平状态或设置引脚的电平<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

通过这种方式<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>驱动代码将变得与具体板子无关<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>具有更好的可移植性和可重用性<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>无论在何种硬件平台上<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>只需确保设备树正确配置和 GPIO 子系统实现得当<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>驱动程序就可以正常工作<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

下面是一个使用 GPIO 子系统的简单示例<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"highlight c"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"code"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"meta"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">#"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">include "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"><linux/gpio.h>
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"meta"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">#"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">define LED_GPIO_PIN 17 "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 定义 LED 使用的 GPIO 引脚编号
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">void "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"title function_"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">led_control"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"params"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">("bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">int state) {
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 申请 GPIO 引脚
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> gpio_request(LED_GPIO_PIN, "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"led_gpio");
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 设置引脚方向为输出
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> gpio_direction_output(LED_GPIO_PIN, state);
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 控制 LED 状态
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> gpio_set_value(LED_GPIO_PIN, state);
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 释放 GPIO 引脚
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> gpio_free(LED_GPIO_PIN);
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">}

GPIO 控制器在设备树中的定义

在许多 ARM 芯片中<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>GPIO 引脚通常被分为多个组<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>每组包含若干个引脚<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>在使用 GPIO 子系统之前<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>必须确定要使用的 GPIO 组和具体引脚<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>以下是如何在设备树中定义和引用 GPIO 控制器的详细说明<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"highlight c"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"code"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">gpio1: gpio@"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"number"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">12340000 {
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> compatible = "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"vendor,gpio-controller"; "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 兼容的设备类型
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> reg = <"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"number"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">0x12340000 "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"number"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">0x1000>; "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 寄存器基地址及大小
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> interrupts = <GIC_SPI "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"number"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">32 "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"number"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">0>; "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 中断配置"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">GIC_SPI 表示中断类型"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">32 是中断号
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> gpio-cells = <"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"number"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">2>; "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// GPIO 单元数"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">第一个为引脚编号"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">第二个为属性"bd bd-beg">"bd-box"bd bd-beg">">如上下拉配置等"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> gpio-controller; "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 指示这是一个 GPIO 控制器
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> ngpios = <"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"number"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">32>; "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 可用的 GPIO 引脚数量
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 额外的属性"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">可以根据具体需要添加
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> vendor = "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"MyVendor"; "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 厂商信息
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> model = "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"MyGPIOController"; "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 控制器型号
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 可选的引脚配置
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> pinctrl-names = "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"default"; "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 引脚控制器配置名称
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> pinctrl"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"number"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">-0 = <&pinctrl_0>; "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 引用引脚控制器配置
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">};

在设备树中<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>GPIO 控制器节点的定义中<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>有两个关键属性需要关注<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

  1. gpio-controller
  • 意义<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>该属性标记该节点为一个 GPIO 控制器<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>表示它负责管理多个 GPIO 引脚<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
  • 作用<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>它让内核识别该节点为 GPIO 控制器<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>并允许其他设备节点引用其管理的 GPIO 引脚<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
  1. #gpio-cells = <2>
  • 意义<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>这个属性指定每个 GPIO 引脚的描述需要使用两个 32 位的数<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>>cell<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg><h-char class=bd bd-beg>
  • 具体含义<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
    • 第一个值<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>表示引脚的编号<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>>index<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg><h-char class=bd bd-beg>用于指定 GPIO 控制器下的具体引脚<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
    • 第二个值<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>可以是可选属性<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>例如设置引脚的上下拉电阻或其他特性<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

在设备节点中引用 GPIO 引脚

gpios 属性并不是将设备定义为 GPIO<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>而是指定该设备使用的 GPIO 引脚<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>具体来说<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>这一行代码指明了该设备将使用由 gpio1 控制器管理的第 0 号引脚<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"highlight c"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"code"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">my_device: my_device@"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"number"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">0 {
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> compatible = "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"goodix,gt9xx";
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> reg = <"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"number"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">0x5d>; "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 设备寄存器地址
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> status = "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"okay"; "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 状态
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> interrupt-parent = <&gpio1>; "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 中断父节点
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> pinctrl-names = "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"default"; "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 默认引脚控制
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> pinctrl"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"number"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">-0 = <&pinctrl_tsc_reset &pinctrl_touchscreen>; "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 引脚控制配置
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> name-gpios = <&gpio1 "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"number"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">0 GPIO_ACTIVE_HIGH>; "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">//// 引用 gpio1 控制器的第 0 号引脚"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">高电平有效
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> reset-gpios = <&gpio2 "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"number"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">2 GPIO_ACTIVE_LOW>; "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 复位 GPIO 低电平有效
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> irq-gpios = <&gpio1 "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"number"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">5 IRQ_TYPE_EDGE_FALLING>; "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 中断 GPIO"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">下降沿触发
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">};
  • gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>; 是一个重要的属性<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>定义了该设备使用的 GPIO 引脚<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
  • 上图中<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>可以使用 gpios 属性<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>也可以使用 name-gpios 属性<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

pinctrl 负责引脚的配置和初始化<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>gpio 则负责在运行时对这些引脚的实际使用<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>分开指定能够提供更大的灵活性和清晰性<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>使得设备在不同环境下的引脚配置和控制更加清晰和可管理<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

0 表示该引脚在 gpio1 控制器中的编号<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>GPIO_ACTIVE_HIGH 指定该 GPIO 引脚在高电平状态下有效<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>这意味着<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>当引脚电平为高时<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>设备的功能将被激活<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>以上dts定义指定了设备所使用的 GPIO 引脚及其状态<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>这是设备树中对设备与 GPIO 之间关系的描述<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>使得内核能够通过驱动程序正确控制该设备<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

效果<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

设备功能控制<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>通过此引用<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>驱动程序可以控制该引脚的状态<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>从而影响设备的行为<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>例如<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>如果这个设备是一个 LED<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>设置该引脚为高电平可能会使 LED 亮起<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

硬件抽象<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>这使得设备树能够抽象出硬件细节<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>驱动程序可以通过统一的接口与硬件进行交互<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>而不必关心具体的硬件实现<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

在驱动代码中调用 GPIO 子系统

在驱动程序中使用 GPIO 引脚时<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>可以通过 Linux GPIO 子系统提供的 API 来进行管理<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>以下是您提供的代码的详细解释<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>展示如何在驱动程序中使用 GPIO<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"highlight c"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"code"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"meta"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">#"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">include "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"><linux/gpio.h>
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"meta"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">#"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">define GPIO_PIN 0 "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 使用 gpio1 控制器中的第 0 号引脚
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">void "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"title function_"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">control_gpio"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"params"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">("bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">void) {
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 申请 GPIO 引脚
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> gpio_request(GPIO_PIN, "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"my_gpio");
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 设置引脚方向为输出
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> gpio_direction_output(GPIO_PIN, "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"number"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">1); "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 设置引脚为高电平
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 控制引脚状态
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> gpio_set_value(GPIO_PIN, "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"number"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">0); "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 设置引脚为低电平
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 释放 GPIO 引脚
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> gpio_free(GPIO_PIN);
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">}

在sysfs中访问GPIO的方式

在 Linux 的 sysfs 中<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>访问方法主要涉及如何通过文件系统接口与内核对象进行交互<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>sysfs 是一个虚拟文件系统<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>它提供了用户空间与内核空间之间的交互机制<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>尤其用于设备和驱动程序的信息暴露<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>以下是访问 sysfs 的一般方法和步骤<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

查看设备信息<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"highlight bash"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"code"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"built_in"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">ls /sys/class/ | grep <device_class>

读取属性<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"highlight bash"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"code"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"built_in"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">cat /sys/class/<device_class>/<device>/attribute_name

写入属性<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"highlight bash"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"code"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"built_in"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">echo <value> > /sys/class/<device_class>/<device>/attribute_name

在 C 程序中<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>可以使用标准文件操作函数来读取和写入 sysfs 文件<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>

"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"highlight c"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"code"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"meta"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">#"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">include "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"><stdio.h>
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"meta"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">#"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">include "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"><stdlib.h>
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">void "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"title function_"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">read_sysfs"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"params"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">("bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">const "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">char *path) {
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> FILE *file = fopen(path, "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"r");
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">if (file) {
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">char buffer["bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"number"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">256];
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> fgets(buffer, "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">sizeof(buffer), file);
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"built_in"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">printf("bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"Value: %s\n", buffer);
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> fclose(file);
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> } "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">else {
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> perror("bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"Failed to open file");
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> }
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">}
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">void "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"title function_"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">write_sysfs"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"params"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">("bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">const "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">char *path, "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">const "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">char *value) {
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> FILE *file = fopen(path, "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"w");
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">if (file) {
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"built_in"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">fprintf(file, "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"%s\n", value);
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> fclose(file);
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> } "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">else {
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> perror("bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"Failed to open file");
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> }
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">}
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">int "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"title function_"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">main"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"params"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">() {
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 示例"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">读取和写入 sysfs 属性
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">const "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"type"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">char *path = "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"/sys/class/<device_class>/<device>/attribute_name";
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> read_sysfs(path); "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 读取属性
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> write_sysfs(path, "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"string"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">"1"); "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"comment"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">// 写入属性
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"> "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"keyword"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">return "bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"number"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">0;
"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">"line"bd bd-beg">"bd-box"bd bd-beg">">"bd bd-beg">">}
  • 权限<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>访问 sysfs 中的某些文件可能需要特定的权限<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>特别是写入操作<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
  • 数据格式<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>确保读取和写入的数据格式正确<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>例如整数<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>布尔值等<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>
  • 设备状态<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>在对设备进行操作前<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>了解设备的当前状态<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>以避免不必要的错误<span class=<h-char class=bd bd-beg>bd-box<h-char class=bd bd-beg>><h-char class=bd bd-beg>