ICM20948 设备树完整指南

ICM20948 设备树完整指南

目录

  1. 方案概述
  2. 设备树基础知识
  3. 准备工作
  4. 详细实施步骤
  5. 验证与测试
  6. 问题排查
  7. 方案对比

方案概述

将ICM20948传感器信息添加到Linux设备树(Device Tree)中,使其成为系统硬件描述的一部分。

方案优势

优势 说明
✅ 系统集成 设备在系统启动时自动识别
✅ 标准化 符合Linux设备模型规范
✅ 内核驱动 可以使用内核提供的IIO驱动
✅ 自动配置 无需手动指定I2C设备路径
✅ 电源管理 支持系统电源管理功能

方案B的劣势

劣势 说明
⚠️ 复杂度高 需要了解设备树和内核编译
⚠️ 编译耗时 需要重新编译内核/设备树
⚠️ 需要烧录 需要更新开发板上的设备树
⚠️ 风险较高 错误配置可能导致系统无法启动

设备树基础知识

什么是设备树(Device Tree)?

设备树是一种描述硬件配置的数据结构,用于告诉Linux内核系统中有哪些硬件设备以及如何配置它们。

设备树文件类型

文件类型 扩展名 说明
设备树源文件 .dts 人类可读的文本格式
设备树包含文件 .dtsi 可被其他dts文件包含的公共部分
设备树二进制文件 .dtb 编译后的二进制格式,内核使用

设备树节点结构

dts 复制代码
node_name@address {
    compatible = "manufacturer,device-model";
    reg = <address>;
    property1 = <value>;
    property2 = "string-value";
    status = "okay";
};

ICM20948 相关的设备树属性

属性 说明 示例
compatible 设备兼容性字符串 "invensense,icm20948"
reg I2C设备地址 <0x68><0x69>(默认0x68)
interrupt-parent 中断控制器 <&gpio0>
interrupts 中断配置 <RK_PA0 IRQ_TYPE_EDGE_RISING>
status 设备状态 "okay""disabled"

准备工作

1. 备份重要文件

bash 复制代码
# 在SDK目录下备份设备树文件
cd ~/atk_dlrv1126b_linux6.1_sdk/kernel
cp arch/arm64/boot/dts/rockchip/rv1126b-alientek.dtsi \
   arch/arm64/boot/dts/rockchip/rv1126b-alientek.dtsi.backup

2. 确认硬件连接信息

在开始之前,确认以下信息:

bash 复制代码
# 在开发板上执行
# 1. 确认ICM20948连接的I2C总线
i2cdetect -y 2

# 2. 确认I2C地址(应该是0x68或0x69)
# 从i2cdetect输出中查看

# 3. 确认是否有中断引脚连接(可选)
# 查看硬件原理图

硬件信息:

  • I2C总线:i2c2
  • I2C地址:0x68
  • 中断引脚:(如果没有需求,可以不配置)

3. 设置编译环境

bash 复制代码
# 进入SDK内核目录
cd ~/atk_dlrv1126b_linux6.1_sdk/kernel

# 加载交叉编译环境
cross_comp

详细实施步骤

步骤1:修改设备树文件

1.1 打开设备树文件
bash 复制代码
cd ~/atk_dlrv1126b_linux6.1_sdk/kernel
vi arch/arm64/boot/dts/rockchip/rv1126b-alientek.dtsi
1.2 找到i2c2节点

在文件中找到 &i2c2 节点:

dts 复制代码
&i2c2 {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&i2c2m0_pins>;

    at8563: rtc@51 {
        compatible = "nxp,pcf8563";
        reg = <0x51>;
        pinctrl-names = "default";
        pinctrl-0 = <&at8563_int>;
        interrupt-parent = <&gpio0>;
        interrupts = <RK_PB1 IRQ_TYPE_LEVEL_LOW>;
        #clock-cells = <0>;
    };
};
1.3 添加ICM20948节点

at8563 节点后面添加ICM20948节点:

方案1:基本配置(无中断)

dts 复制代码
&i2c2 {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&i2c2m0_pins>;

    at8563: rtc@51 {
        compatible = "nxp,pcf8563";
        reg = <0x51>;
        pinctrl-names = "default";
        pinctrl-0 = <&at8563_int>;
        interrupt-parent = <&gpio0>;
        interrupts = <RK_PB1 IRQ_TYPE_LEVEL_LOW>;
        #clock-cells = <0>;
    };

    icm20948: imu@68 {
        compatible = "invensense,icm20948";
        reg = <0x68>;
        status = "okay";
    };
};

方案2:完整配置(带中断)

如果您的硬件连接了ICM20948的INT引脚到GPIO,可以使用完整配置:

dts 复制代码
&i2c2 {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&i2c2m0_pins>;

    at8563: rtc@51 {
        compatible = "nxp,pcf8563";
        reg = <0x51>;
        pinctrl-names = "default";
        pinctrl-0 = <&at8563_int>;
        interrupt-parent = <&gpio0>;
        interrupts = <RK_PB1 IRQ_TYPE_LEVEL_LOW>;
        #clock-cells = <0>;
    };

    icm20948: imu@68 {
        compatible = "invensense,icm20948";
        reg = <0x68>;
        interrupt-parent = <&gpio0>;
        interrupts = <RK_PA0 IRQ_TYPE_EDGE_RISING>;
        status = "okay";
    };
};

注意:

  • RK_PA0 需要根据实际连接的GPIO引脚修改
  • 如果没有连接中断引脚,使用方案1即可
1.4 保存文件
bash 复制代码
# 在vi中保存并退出
:wq

步骤2:编译设备树

2.1 编译内核
bash 复制代码
# 编译kernel
cd ~/atk_dlrv1126b_linux6.1_sdk
./build.sh kernel
# 编译kernel后的输出文件为boot.img
2.2 检查编译结果
bash 复制代码
# 查看生成的img文件
ls -la ./rockdev

# 找到生成的img文件
/home/alientek/atk_dlrv1126b_linux6.1_sdk/output/firmware/boot.img

步骤3:部署设备树到开发板

  1. 将开发板连接至虚拟机,可正常adb shell

  2. 在[SDK]/rockdev文件夹下查看输出软链接文件:

    复制代码
    alientek@alientek:~/atk_dlrv1126b_linux6.1_sdk$ ls ./rockdev
    boot.img  MiniLoaderAll.bin  misc.img  parameter.txt  recovery.img  rootfs.img  uboot.img  update.img  userdata.img
  3. adb shell登录开发板并执行reboot loader重启进入到 Loader 模式。

  4. 设备名称为fuzhou rockchip usb download gadget,使其连接到虚拟机。

    注意到 Loader 的模式下是不能用 adb shell 登录开发版的,同时串口也失效了。

  5. 在 SDK 路径下执行指令:sudo ./rkflash.sh uboot。【更换为对应的映像文件】

  6. 等待烧写完毕,烧写完毕后,拨动开发板上的电源开关重启开发板。

步骤4:验证设备树加载

4.1 检查设备树节点
bash 复制代码
# 重启后,在开发板上执行

# 1. 查看设备树中的ICM20948节点
ls /sys/firmware/devicetree/base/i2c@ff410000/imu@68/

# 2. 查看compatible属性
cat /sys/firmware/devicetree/base/i2c@ff410000/imu@68/compatible
# 应该输出:invensense,icm20948

# 3. 查看reg属性
cat /sys/firmware/devicetree/base/i2c@ff410000/imu@68/reg | hexdump -C
# 应该显示:00 00 00 68(即地址0x68)
4.2 检查内核日志
bash 复制代码
# 查看内核启动日志中关于ICM20948的信息
dmesg | grep -i icm
dmesg | grep -i imu
dmesg | grep -i "i2c.*68"

可能的输出:

  • 如果有内核驱动:会看到驱动加载信息
  • 如果没有内核驱动:可能看不到相关信息(这是正常的,Linux不支持该驱动)

验证与测试

方法1:使用用户空间程序(方案A)

即使添加了设备树节点,仍然可以使用之前的用户空间程序:

bash 复制代码
cd /root/icm
LD_LIBRARY_PATH=/root/icm ./simple_gyro_test

应该仍然正常工作!

方法2:检查IIO子系统(如果有内核驱动)

bash 复制代码
# 查看IIO设备
ls /sys/bus/iio/devices/

# 如果ICM20948有内核驱动,会看到类似:
# iio:device0

# 查看设备属性
cat /sys/bus/iio/devices/iio:device0/name
# 应该输出:icm20948

# 读取陀螺仪数据
cat /sys/bus/iio/devices/iio:device0/in_anglvel_x_raw
cat /sys/bus/iio/devices/iio:device0/in_anglvel_y_raw
cat /sys/bus/iio/devices/iio:device0/in_anglvel_z_raw

注意: Linux 6.1内核可能没有ICM20948的IIO驱动,这种情况下不会看到IIO设备。

方法3:使用i2cdetect验证

bash 复制代码
# 检查I2C设备是否仍然可见
i2cdetect -y 2

预期结果:

  • 地址0x68处应该显示 68UU
  • UU 表示设备被内核驱动占用(如果有驱动)
  • 68 表示设备存在但未被驱动占用

问题排查

问题1:编译设备树失败

错误信息:

复制代码
Error: xxx.dtsi:123: syntax error

解决方法:

  1. 检查设备树语法,特别是:

    • 大括号是否匹配
    • 分号是否缺失
    • 属性值格式是否正确
  2. 使用dtc工具检查语法:

bash 复制代码
dtc -I dts -O dtb arch/arm64/boot/dts/rockchip/rv1126b-alientek.dtsi

问题2:系统无法启动

症状: 替换dtb后系统无法启动或卡在启动画面

解决方法:

  1. 恢复备份的dtb文件:
bash 复制代码
# 通过串口或恢复模式进入系统
cp /boot/rv1126b-alientek.dtb.backup /boot/rv1126b-alientek.dtb
sync
reboot
  1. 检查设备树配置是否有错误

  2. 从简单配置开始,逐步添加属性

问题3:设备树节点不存在

症状: /sys/firmware/devicetree/base/ 下找不到ICM20948节点

可能原因:

  1. dtb文件没有正确替换
  2. 设备树编译时没有包含修改
  3. 节点路径不正确

解决方法:

bash 复制代码
# 1. 确认dtb文件时间戳
ls -l /boot/rv1126b-alientek.dtb

# 2. 反编译当前使用的dtb查看内容
dtc -I dtb -O dts /boot/rv1126b-alientek.dtb > /tmp/current.dts
grep -A 10 icm20948 /tmp/current.dts

# 3. 如果没有找到,说明dtb没有正确更新

问题4:用户空间程序无法访问设备

症状: 添加设备树后,simple_gyro_test 报错 "Failed to detect ICM-20948"

可能原因:

  • 设备被内核驱动占用(i2cdetect显示UU)

解决方法:

bash 复制代码
# 1. 检查是否有驱动占用
i2cdetect -y 2

# 2. 如果显示UU,卸载内核驱动
lsmod | grep icm
rmmod icm20948  # 如果有的话

# 3. 或者在设备树中禁用该节点
# 修改 status = "disabled";

问题5:找不到IIO设备

症状: /sys/bus/iio/devices/ 目录为空

原因: Linux 6.1内核可能没有编译ICM20948的IIO驱动

解决方法:

  1. 检查内核配置:
bash 复制代码
cd ~/atk_dlrv1126b_linux6.1_sdk/kernel
grep ICM20948 .config
  1. 如果没有驱动,有两个选择:
    • 继续使用用户空间方案(方案A)
    • 编译并加载ICM20948内核驱动(高级)

方案对比

方案A vs 方案B 详细对比

对比项 方案A(用户空间) 方案B(设备树)
实施难度 ⭐ 简单 ⭐⭐⭐⭐ 复杂
所需时间 10分钟 1-2小时
需要重启 ❌ 不需要 ✅ 需要
风险等级 中等
系统集成 手动 自动
灵活性 中等
适用场景 快速原型、测试 产品化、长期使用
维护成本 中等

何时使用方案A?

推荐使用方案A的情况:

  • 快速验证硬件功能
  • 原型开发阶段
  • 不想修改系统配置
  • 需要灵活调整参数
  • 只需要基本的数据读取功能

何时使用方案B?

推荐使用方案B的情况:

  • 产品化阶段
  • 需要系统自动识别设备
  • 想使用内核IIO驱动
  • 需要电源管理功能
  • 长期稳定运行

混合方案

您可以同时使用两种方案:

  1. 添加设备树节点(方案B)
  2. 在设备树中设置 status = "disabled"
  3. 继续使用用户空间程序(方案A)

这样既保持了系统的规范性,又保留了灵活性。


高级主题

1. 添加内核驱动支持

如果您想使用内核IIO驱动,需要:

bash 复制代码
# 1. 检查内核配置
cd ~/atk_dlrv1126b_linux6.1_sdk/kernel
make menuconfig

# 2. 启用IIO子系统和ICM20948驱动
# Device Drivers -->
#   Industrial I/O support -->
#     Inertial measurement units -->
#       <M> Invensense ICM20948 I2C driver

# 3. 编译内核模块
make modules

# 4. 安装模块到开发板
make modules_install INSTALL_MOD_PATH=/path/to/rootfs

2. 自定义设备树属性

您可以添加自定义属性来配置传感器:

dts 复制代码
icm20948: imu@68 {
    compatible = "invensense,icm20948";
    reg = <0x68>;

    /* 自定义属性 */
    invensense,gyro-range = <250>;  /* 陀螺仪量程:250 dps */
    invensense,accel-range = <2>;   /* 加速度计量程:2g */
    invensense,sample-rate = <100>; /* 采样率:100Hz */

    status = "okay";
};

文档版本: 1.0
最后更新: 2026-02-10
适用平台: RV1126B + Linux 6.1.141

相关推荐
不做无法实现的梦~10 小时前
ros2实现路径规划---nav2部分
linux·stm32·嵌入式硬件·机器人·自动驾驶
LeoZY_21 小时前
CH347/339W开源项目:集SPI、I2C、JTAG、SWD、UART、GPIO多功能为一体(3)
stm32·单片机·嵌入式硬件·mcu·开源
Hello_Embed21 小时前
libmodbus STM32 板载串口实验(双串口主从通信)
笔记·stm32·单片机·学习·modbus
良许Linux1 天前
嵌入式处理器架构
stm32·单片机·程序员·嵌入式·编程
wotaifuzao1 天前
为什么 if/else 是嵌入式系统的慢性毒药?
stm32·重构·freertos·状态机·架构设计·事件驱动·表驱动
LeoZY_1 天前
开源项目精选: lazygit —— 告别繁琐命令,终端里玩转可视化Git
git·stm32·单片机·mcu·开源·远程工作·gitcode
youcans_1 天前
【STM32-MBD】(17)基于 ADC 同步采样的 PWM 闭环控制链路
stm32·单片机·嵌入式硬件·matlab·电机控制·foc
what丶k1 天前
深入浅出 STM32 中断系统:原理、配置与实战优化
stm32·单片机·嵌入式硬件
Zeku1 天前
RTSP音视频传输软件流程文档
stm32·音视频·freertos·linux驱动开发·linux应用开发
Bin Watson1 天前
STM32 HRTIM 学习心得(2):控制输出 PWM/SPWM/带死区的互补SPWM
stm32·单片机·嵌入式硬件