当前位置: 首页 > news >正文

linux dts overlay

设备树 Overlay(Device Tree Overlays, DTO),它在嵌入式Linux系统(尤其是基于ARM的设备,比如树莓派、NanoPi等)中非常常见。它主要用于动态修改设备树,以适配硬件的变化或扩展外设支持。


1. 设备树 (Device Tree) 基础

  • 设备树是Linux内核用来描述硬件的一个数据结构(通常是 .dts 源文件,编译成 .dtb 二进制文件)。
  • 它告诉内核“硬件是什么”,“有什么设备”,以及“设备如何连接”的信息。
  • 这样,内核就不需要硬编码特定硬件,增强了移植性。

2. 设备树 Overlay(DTO)是什么?

  • Overlay 就是对设备树的“增量补丁”,它定义了一段额外的设备树节点,能够在运行时或者启动时“叠加”到主设备树上。
  • 目的:实现设备树的动态扩展,比如给板子添加新的外设(GPIO扩展板、摄像头模块、触摸屏等),而不用修改主设备树文件。
  • Overlay通常是一个独立的 .dtbo 文件(编译后的Overlay),由主设备树加载时或内核模块加载时合并。

3. 使用场景

典型场景:

  • 外设模块动态添加
    比如你的主板没有集成摄像头,需要外接摄像头模块,就可以用Overlay来描述摄像头设备节点和相关GPIO、中断配置。

  • GPIO复用和引脚配置
    一块板子多个设备共用引脚,Overlay能配置引脚复用,打开或关闭某些设备接口。

  • 设备树不方便修改的环境
    有些固件或内核只能加载固定的主设备树,Overlay给了动态配置的能力。


4. Overlay 如何使用?

  • 制作Overlay文件

    1. 编写 .dts 文件,继承主设备树的内容,只写你想“覆盖/新增”的部分。
    2. 使用设备树编译器(dtc)编译成 .dtbo 文件。
  • 加载Overlay

    • 在启动时加载(很多板子在bootloader配置文件中支持Overlay加载,比如 config.txt 里的 dtoverlay=
    • 运行时加载(通过configfs接口,动态插入Overlay)

举例(树莓派):

# /boot/config.txt
dtoverlay=your-overlay-name

5. Overlay 和 Initramfs、systemd 对比

特性设备树 Overlayinitramfssystemd
作用动态修改硬件描述,加载新硬件节点早期用户空间临时根文件系统加载Linux启动初始化系统及服务管理
关注层面硬件抽象层系统启动早期阶段用户空间环境系统服务管理及并发启动
运行时机启动阶段或运行时内核设备树修改内核启动时挂载,用于系统启动内核启动后启动管理服务
主要功能硬件描述扩展、配置引脚、设备绑定提供最初的文件系统环境启动服务、管理依赖、日志、资源等
适用场景硬件变动、模块化硬件设计内核启动时根文件系统不可用场景系统服务启动和管理
是否直接涉及硬件
动态修改硬件描述能力支持,动态加载/卸载Overlay不支持不支持

6. 简单总结

  • 设备树 Overlay:专注于硬件描述和配置,特别适合动态加载硬件节点。
  • initramfs:内核启动的第一个用户空间,负责挂载根文件系统和初始化环境。
  • systemd:现代Linux系统的初始化和服务管理器,负责启动和维护系统服务。

7. 你实际使用设备树Overlay时要注意

  • 设备树版本兼容性
  • Overlay文件的正确编译
  • 确保Overlay描述的硬件节点匹配实际硬件
  • 确保bootloader或内核支持Overlay机制
  • 运行时加载Overlay需内核开启CONFIG_OF_OVERLAY支持

很好,你正在使用的是 NanoPi NEO Core 这类基于 Allwinner H3 SoC 的板子,跑的是 Armbian,这类系统通常是 Debian 或 Ubuntu 的轻量定制版本,广泛用于嵌入式设备和 DIY 项目。


✅ 背景确认

你的平台:

  • 硬件:NanoPi NEO Core(基于 Allwinner H3)
  • 系统:Armbian(可能基于 Debian/Ubuntu)
  • 用途:可能用于音频服务(你提到 Navidrome)或其他嵌入式用途
  • 需求:动态控制硬件(如 I2C、SPI、UART、GPIO、LED、外接模块等)

📌 在 Armbian 上使用设备树 Overlay(DTO)

Armbian 提供 标准化支持 DTO 的机制,适用于大多数基于 mainline kernel 的 Allwinner 平台。


📘 Armbian Overlay 使用方法

1. 查看当前启用的 Overlays

armbian-config

进入 → SystemHardware → 你可以通过界面启用常见的设备树 Overlays(I2C, SPI, UART, PWM, etc)

或手动查看:

cat /boot/armbianEnv.txt

你可能会看到类似:

overlays=spi-spidev i2c0 uart1
param_spidev_spi_bus=0

2. 启用已有 Overlay

编辑 /boot/armbianEnv.txt

sudo nano /boot/armbianEnv.txt

添加或修改:

overlays=spi-spidev i2c0 uart1

保存后重启:

sudo reboot

你可以用 dmesg | grep spils /dev/spidev* 来确认是否生效。


3. Overlay 文件存放位置

Armbian 默认加载 /boot/dtb/overlay/ 中的 .dtbo 文件。你也可以:

ls /boot/dtb/allwinner/overlay/

4. 自定义 Overlay 示例

举个例子:你要启用一个额外的 LED 灯连接到 GPIO PH7

创建文件:my-led-overlay.dts

/dts-v1/;
/plugin/;&{/} {fragment@0 {target-path = "/";__overlay__ {my_led: gpio-leds {compatible = "gpio-leds";status_led {label = "status_led";gpios = <&pio 7 7 GPIO_ACTIVE_HIGH>;  // PH7 = port 7, pin 7default-state = "on";};};};};
};

然后编译:

dtc -@ -I dts -O dtb -o my-led-overlay.dtbo my-led-overlay.dts

拷贝到 overlay 文件夹:

sudo cp my-led-overlay.dtbo /boot/dtb/allwinner/overlay/

修改 /boot/armbianEnv.txt 添加:

user_overlays=my-led-overlay

保存并重启:

sudo reboot

🧠 Overlay 与 systemd/initramfs 区别(再次归纳)

项目设备树 Overlay (DTO)initramfssystemd
含义动态叠加修改设备树(硬件配置)临时根文件系统(启动用)启动初始化系统管理器
使用时机启动时或运行时加载启动时使用内核启动后立即运行
作用层面硬件层(GPIO/I2C/UART等)用户空间临时运行环境管理服务、守护进程、挂载等
是否与硬件直接相关✅ 是❌ 否❌ 否

🧪 常用场景举例(在你设备上)

目标使用方式
启用 SPIoverlays=spi-spidev
启用 UARToverlays=uart1 uart2
自定义 LED GPIO自写 DTO + user_overlays
音频模块支持(I2S DAC)DTO + 手动加载驱动
外接 OLED 屏(I2C)overlays=i2c0 + dto 添加地址和驱动绑定

🔧 小贴士

  • dtc -I fs /proc/device-tree 可以查看当前设备树的实际内容
  • 确保 CONFIG_OF_OVERLAY=y 在内核中开启(Armbian默认是开的)
  • 你可以使用 fdtput 工具直接修改 .dtb 文件(高级用法)

如果你遇到的问题是:

  • DTO加载无效 ➜ 看 /boot/armbianEnv.txt 里拼写是否正确
  • 驱动不生效 ➜ 用 dmesglsmodmodinfo 等调试
  • 不知道引脚编号 ➜ 查找对应的 sunxi pin map(Allwinner特有)

你想在 NanoPi NEO Core(Armbian) 上通过 I2C 接 OLED 显示屏(SSD1306 控制器),下面是完整详解,包括:

  • ✅ 硬件连接
  • ✅ 内核模块/驱动配置
  • ✅ 设备树 Overlay 编写与使用
  • ✅ 软件层显示内容(Python 示例)

✅ 1. 硬件接线(基于 I2C)

OLED LabelNanoPi NEO PinNotes
VCC3.3V / 5VOLED 供电
GNDGND地线
SDAI2C0_SDA (Pin 3, GPIO PA11)数据线
SCLI2C0_SCL (Pin 5, GPIO PA12)时钟线

确认你接在了 I2C0(默认引出)的 SDA/SCL 上。


✅ 2. 启用 I2C0 接口(Armbian Overlay)

编辑 /boot/armbianEnv.txt

overlays=i2c0

保存后重启:

sudo reboot

确认 /dev/i2c-0 是否出现:

ls /dev/i2c*

还可以确认 OLED 是否连上(地址通常为 0x3c):

sudo apt install -y i2c-tools
sudo i2cdetect -y 0

看到类似:

     0 1 2 3 4 5 6 7 8 9 a b c d e f
00:          -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- 3c
...

✅ 3. 添加设备树 Overlay(挂载 SSD1306)

Armbian 自带的 overlay 目录通常 没有直接包含 SSD1306 的 overlay。所以我们需要自定义:

✏️ 创建文件 ssd1306-i2c.dts

/dts-v1/;
/plugin/;/ {compatible = "allwinner,sun8i-h3";fragment@0 {target-path = "/";__overlay__ {i2c@01c2ac00 {status = "okay";ssd1306: ssd1306@3c {compatible = "solomon,ssd1306fb-i2c";reg = <0x3c>;pinctrl-names = "default";reset-gpios = <0>; /* if no reset pin */width = <128>;height = <64>;page-offset = <0>;seg-remap;com-invdir;contrast = <127>;};};};};
};

说明:

  • 如果你接的是 128x32 OLED,请将 height = <32>
  • 若有 reset 引脚可设置为 <&pio X Y GPIO_ACTIVE_LOW>,比如 <&pio 0 6 0> 是 PA6。

🛠️ 编译 & 安装

dtc -@ -I dts -O dtb -o ssd1306-i2c.dtbo ssd1306-i2c.dts
sudo cp ssd1306-i2c.dtbo /boot/dtb/allwinner/overlay/

修改 /boot/armbianEnv.txt 添加:

user_overlays=ssd1306-i2c

然后重启:

sudo reboot

✅ 4. 驱动检查

确认驱动模块是否加载:

lsmod | grep ssd1306

如果没有:

sudo modprobe ssd1306

也可以添加到 /etc/modules 里让其开机加载:

echo ssd1306 | sudo tee -a /etc/modules

✅ 5. 显示内容(Python)

安装 Python 库

sudo apt install python3-pip
pip3 install luma.oled

示例 Python 脚本

from luma.core.interface.serial import i2c
from luma.oled.device import ssd1306
from PIL import ImageDraw, ImageFont, Imageserial = i2c(port=0, address=0x3C)
device = ssd1306(serial)draw = ImageDraw.Draw(Image.new("1", device.size))
font = ImageFont.load_default()
draw.text((0, 0), "Hello NanoPi!", font=font, fill=255)device.display(draw.im)

✅ 6. 常见问题排查

问题原因
/dev/i2c-0 不存在overlay 没启用 i2c0
i2cdetect 无响应或空线路错误 / 接线问题
OLED 无反应地址错误(0x3c vs 0x3d),接错线,驱动未加载
无法加载驱动没有开启内核模块 CONFIG_FB_SSD1306
Python 报错未装 luma.oled 或设备没有正确挂载

✅ 小结

你只需要:

  1. 确保 I2C 通了 → overlays=i2c0
  2. 加载自定义 Overlay → ssd1306@3c
  3. 加载驱动 → ssd1306fb(内核驱动或 Python 用户空间库)
  4. 选定显示方式 → 控制台 framebuffer 或 Python 图形库

很好!你想通过 framebuffer 控制 SSD1306 OLED(I2C 接口),这样你可以直接使用命令行工具、C 程序或 Shell 脚本将图像、文字显示到屏幕上,而不需要 Python 库。


🧩 目标实现:

让 SSD1306 显示屏出现在 /dev/fb1,通过 catfbidd 等 framebuffer 工具控制它显示内容。


✅ 1. 检查内核模块

确保内核已包含以下模块(Armbian 通常自带):

lsmod | grep ssd1306

如果没有,手动加载:

sudo modprobe ssd1306
sudo modprobe ssd1306fb

⚠️ 如果提示模块不存在,可能你需要启用模块支持并重新编译内核(我可指导你做)。


✅ 2. 设备树 Overlay(带 framebuffer 绑定)

使用下面的 .dts 文件创建 overlay,挂载 SSD1306,并启用 framebuffer 输出。

✏️ 文件:ssd1306-fb-i2c.dts

/dts-v1/;
/plugin/;/ {compatible = "allwinner,sun8i-h3";fragment@0 {target = <&i2c0>;__overlay__ {status = "okay";ssd1306fb: ssd1306fb@3c {compatible = "solomon,ssd1306fb-i2c";reg = <0x3c>;width = <128>;height = <64>;page-offset = <0>;seg-remap;com-invdir;contrast = <127>;rotate = <0>;};};};
};

✅ 3. 编译并启用 overlay

dtc -@ -I dts -O dtb -o ssd1306-fb-i2c.dtbo ssd1306-fb-i2c.dts
sudo cp ssd1306-fb-i2c.dtbo /boot/dtb/overlay/

编辑 /boot/armbianEnv.txt,添加:

user_overlays=ssd1306-fb-i2c

保存后重启:

sudo reboot

✅ 4. 验证 framebuffer

重启后检查:

ls /dev/fb*

你应该看到 /dev/fb1(主 framebuffer 通常是 fb0)

确认信息:

cat /sys/class/graphics/fb1/name

应返回:ssd1306fb

查看分辨率:

cat /sys/class/graphics/fb1/virtual_size

✅ 5. 使用 framebuffer 工具显示内容

🖼️ 显示图片(需安装 fbi 工具)

sudo apt install fbi
sudo fbi -d /dev/fb1 -T 1 --noverbose -a your-image.png

注意:

  • 图片必须为 单色位图(1bit bmp/png),大小 128×64。
  • 你也可以用 imagemagick 转图:
convert input.png -resize 128x64\! -monochrome out.bmp

🧪 输出简单图像(命令行写 framebuffer)

sudo bash -c 'dd if=/dev/zero of=/dev/fb1 bs=1024 count=1'

这会清空屏幕。

你可以写一个程序像素级控制 /dev/fb1,例如写字符、画图。


✅ 6. 示例:C 程序写 framebuffer

#include <fcntl.h>
#include <unistd.h>
#include <string.h>int main() {int fb = open("/dev/fb1", O_RDWR);if (fb < 0) return 1;// 简单填充图案char buffer[1024]; // 128 x 64 = 1024 bits = 128 bytes x 8 linesmemset(buffer, 0xAA, sizeof(buffer)); // 交错黑白条纹write(fb, buffer, sizeof(buffer));close(fb);return 0;
}

✅ 小结

步骤动作
1️⃣确保 OLED 连到 I2C(地址 0x3c)
2️⃣使用 ssd1306fb-i2c overlay
3️⃣检查 /dev/fb1 是否出现
4️⃣fbidd、程序操作 framebuffer 显示内容

相关文章:

  • [1-01-01].第27节:常用类 - 包装类
  • 大模型证书
  • 16.2 Docker多阶段构建实战:LanguageMentor镜像瘦身40%,支持500+并发1.2秒响应!
  • LLaMA-Factory 对 omnisql 进行 ppo dpo grpo nl2sql任务 实现难度 时间 全面对比
  • 系统学习 Android 的 进程管理、内存管理、音频管理
  • 虚拟机远程连接编译部署QT程序
  • canvas面试题200道
  • 霸王餐系统
  • 数据源简单配置应用
  • GO 语言学习 之 语句块
  • 第N5周:Pytorch文本分类入门
  • Windows11系统上安装WM虚拟机及Ubuntu 22.04系统
  • 地址簇与数据序列
  • SpringCloud系列(38)--SpringCloud Gateway实现动态路由
  • SYSCFG 时钟在 GD32F4 系列微控制器中的作用
  • 升级 PowerShell 7
  • elastic-ai.creator开源程序是设计、训练和生成专门针对 FPGA 优化的神经网络
  • 基于 Java+MySQL实现TCP聊天工具
  • MySQL 基线核查实录:标准化配置与命令验证全解析
  • (LeetCode 面试经典 150 题 ) 238. 除自身以外数组的乘积 (前缀和)