banner
NEWS LETTER

嵌入式 Linux 进阶:设备树、驱动和应用层的关系

Scroll down

一、为什么需要设备树

在嵌入式 Linux 中,内核需要知道硬件板子上有什么设备、这些设备接在哪些总线上、使用哪些 GPIO、中断、时钟和寄存器地址。

这些硬件描述不适合全部写死在驱动代码里,所以 Linux 使用设备树描述硬件。

设备树的作用:

  • 描述硬件资源。
  • 把板级差异从驱动中分离出来。
  • 让同一个驱动适配不同板子。
  • 让内核启动时创建设备。

二、设备树文件

常见文件:

1
2
3
.dts   板级设备树
.dtsi 公共设备树片段
.dtb 编译后的二进制设备树

关系:

1
dts/dtsi -> dtc -> dtb

内核启动时,Bootloader 会把 dtb 传给内核。

三、设备树节点示例

示例:

1
2
3
4
5
6
7
8
9
leds {
compatible = "gpio-leds";

status_led {
label = "status";
gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
};

说明:

  • compatible:用于匹配驱动。
  • label:设备名称。
  • gpios:使用哪个 GPIO。
  • default-state:默认状态。

驱动根据 compatible 找到对应设备,然后读取节点里的资源。

四、compatible

compatible 是设备和驱动匹配的关键。

设备树:

1
2
3
my_device {
compatible = "demo,my-device";
};

驱动:

1
2
3
4
5
static const struct of_device_id my_of_match[] = {
{ .compatible = "demo,my-device" },
{ }
};
MODULE_DEVICE_TABLE(of, my_of_match);

如果字符串不一致,驱动就匹配不上设备。

五、status

常见写法:

1
2
status = "okay";
status = "disabled";

含义:

  • okay:启用设备。
  • disabled:禁用设备。

外设调不通时,先检查设备树节点是否真的启用。

六、设备节点和 sysfs

驱动加载后,用户层可能看到:

1
2
3
/dev/xxx
/sys/class/xxx
/sys/bus/...

不同驱动暴露的接口不同:

  • 字符设备通常在 /dev 下。
  • LED 可能在 /sys/class/leds
  • GPIO 可能通过 gpiod 访问。
  • I2C 设备可能在 /sys/bus/i2c/devices

查看设备:

1
2
3
ls /sys/bus/platform/devices
ls /sys/class/leds
ls /dev

七、字符设备驱动的基本概念

字符设备按字节流方式访问,用户层通过文件接口操作:

1
2
3
4
5
open
read
write
ioctl
close

驱动中对应:

1
2
3
4
5
6
7
8
static const struct file_operations fops = {
.owner = THIS_MODULE,
.open = my_open,
.read = my_read,
.write = my_write,
.unlocked_ioctl = my_ioctl,
.release = my_release,
};

应用层不需要知道底层寄存器,只需要操作 /dev/mydev

八、应用层、驱动、硬件的关系

可以这样理解:

1
应用层 -> /dev 或 /sys -> 驱动 -> 内核子系统 -> 硬件寄存器/总线

例如控制 LED:

1
echo 1 > /sys/class/leds/status/brightness

背后流程:

1
Shell 写 sysfs -> LED 子系统 -> GPIO 驱动 -> GPIO 控制器寄存器 -> 引脚电平变化

九、驱动调试常用命令

查看内核日志:

1
2
dmesg
dmesg -w

查看模块:

1
lsmod

加载模块:

1
insmod my_driver.ko

卸载模块:

1
rmmod my_driver

查看设备树:

1
ls /proc/device-tree

查看中断:

1
cat /proc/interrupts

查看 GPIO:

1
gpioinfo

十、常见问题

10.1 驱动没有 probe

可能原因:

  • compatible 不匹配。
  • 设备树节点没有启用。
  • 驱动没有编进内核或模块没加载。
  • 总线父节点未启用。

10.2 GPIO 控制无效

检查:

  • pinctrl 是否配置。
  • GPIO 编号是否正确。
  • 是否被其它驱动占用。
  • 电平极性是否反了。
  • 硬件是否需要额外使能。

10.3 I2C 设备找不到

检查:

  • I2C 控制器是否启用。
  • 地址是否正确。
  • 设备是否上电。
  • SDA/SCL 是否有上拉。
  • 是否有地址冲突。

十一、学习路线

建议路线:

  1. 看懂设备树基本语法。
  2. 修改 LED 或按键节点。
  3. 使用现成 GPIO/I2C/SPI 驱动。
  4. 写简单平台驱动。
  5. 写字符设备驱动。
  6. 理解 pinctrl、clock、reset、interrupt。
  7. 阅读内核子系统驱动。

十二、总结

设备树描述硬件,驱动管理硬件,应用层通过 /dev/sys 或标准 API 使用硬件。

嵌入式 Linux 进阶的关键是把这三层串起来:

1
设备树资源是否正确 -> 驱动是否匹配并 probe -> 用户层接口是否出现 -> 应用是否按正确协议访问

按这个顺序排查,比直接翻驱动源码更高效。

其他文章
目录导航 置顶
  1. 1. 一、为什么需要设备树
  2. 2. 二、设备树文件
  3. 3. 三、设备树节点示例
  4. 4. 四、compatible
  5. 5. 五、status
  6. 6. 六、设备节点和 sysfs
  7. 7. 七、字符设备驱动的基本概念
  8. 8. 八、应用层、驱动、硬件的关系
  9. 9. 九、驱动调试常用命令
  10. 10. 十、常见问题
    1. 10.1. 10.1 驱动没有 probe
    2. 10.2. 10.2 GPIO 控制无效
    3. 10.3. 10.3 I2C 设备找不到
  11. 11. 十一、学习路线
  12. 12. 十二、总结
请输入关键词进行搜索