版本

3.13. sample_imu 使用说明

3.13.1. 概述

3.13.1.1. 功能简介

sample_imu 提供多个 IMU 数据采集示例,用户可通过 sample_imu 子目录了解不同数据通路的读取方法:

  • IIO 通路:通过 sysfs 读取 IIO 设备节点,支持交互式单帧/多帧采集,并将数据转换为 SI 单位输出。

  • Input 通路:通过 Linux Input 子系统读取驱动上报的 EV_MSC 事件,适合验证驱动连续上报链路与丢包情况。

3.13.1.2. sample_imu 架构说明

sample_imu 包含多个测试用例,各子目录描述如下:

目录 描述
sample_imu_iio 基于 IIO 接口读取 IMU 数据,支持 bmi08x、icm42688-gyro、icm42688-accel
sample_imu_input 基于 Linux Input 子系统读取驱动上报的 IMU 原始数据 ,已经适配 bmi08x 和 icm42688

3.13.2. sample_imu_iio

3.13.2.1. 功能概述

sample_imu_iio 是一个基于 IIO 接口的 IMU 命令行示例,主要实现了对惯性测量单元(IMU)数据的读取、处理和显示功能。通过该程序,用户可以方便地获取 IMU 传感器的加速度、陀螺仪数据(传感器具备磁力计时也可扩展),并进行相应的分析和应用。

程序内置支持的传感器驱动名称如下:

  • bmi08x

  • icm42688-gyro

  • icm42688-accel

未通过 -n 指定传感器时,程序会调用 get_default_imu_name() 自动探测系统中第一个可用的受支持 IIO 设备;若未探测到任何设备,程序会说明没有探测到设备,然后退出。

3.13.2.2. 软件架构说明

sample_imu_iio 采用分层设计:

  • 应用层:sample_imu.c 作为程序入口,负责解析命令行参数、初始化传感器、处理用户输入命令,以及读取和显示传感器数据。

  • 管理层:imu_manager.h 和 imu_manager.c 提供传感器管理接口,包括列出可用传感器、初始化传感器、读取数据、释放资源等。

  • 适配层:imu_interface.h 定义传感器驱动接口结构体,为具体传感器提供统一抽象。

  • 传感器抽象层:bmi08x.c、icm42688.c 等文件负责与底层 IIO 驱动交互,将硬件数据转换为上层可用的标准数据格式。

软件架构图:

software_architecture_diagram.png

3.13.2.3. 数据流说明

  1. 应用层通过 init_sensor() 在 /sys/bus/iio/devices/ 下查找并校验目标 IIO 设备。

  2. 传感器抽象层从 in_accel_*_raw、in_anglvel_*_raw 等节点读取原始值,并结合 scale 转换为物理量。

  3. 应用层通过 read_sensor_data() 获取一帧 ImuData,再调用 print_imu_data() 输出加速度(m/s²)、角速度(rad/s)和时间戳。

3.13.2.4. 代码位置及目录结构

  • 代码位置:app/samples/platform_samples/sample_imu/sample_imu_iio

  • 目录结构

sample_imu_iio
├── Makefile
├── bmi08x.c
├── icm42688.c
├── imu_interface.h
├── imu_manager.c
├── imu_manager.h
└── sample_imu.c

各文件说明:

  • Makefile:定义编译规则,编译产物为 sample_imu_iio。

  • sample_imu.c:程序入口,负责命令行解析与交互式读数。

  • imu_manager.c / imu_manager.h:传感器管理与 IIO 设备探测逻辑。

  • imu_interface.h:传感器驱动统一接口定义。

  • bmi08x.c:BMI08x 传感器抽象层实现。

  • icm42688.c:ICM42688 加速度计/陀螺仪抽象层实现。

如需新增其他 IMU 传感器,可参考 bmi08x.c 的实现方式,并结合 imu_interface.h 接口进行扩展。

3.13.2.5. 背景知识

惯性测量单元(IMU)是一种用于测量物体加速度、角速度和磁场等物理量的设备,通常由加速度计、陀螺仪和磁力计组成。通过对这些物理量的测量和分析,可以获取物体的姿态、运动状态等信息。需要注意的是,并非所有 IMU 都同时具备三种传感器,行业中也存在单独售卖加速度计、陀螺仪、磁力计,或六轴、九轴等不同配置的 IMU 产品。

3.13.2.6. API 流程说明

sample_imu_iio 主要基于 kernel 标准 IIO 接口构建。结合程序函数,整体流程如下:

  1. 列出可用传感器:调用 list_available_sensors(),遍历程序内置支持的传感器驱动列表并打印名称。

  2. 初始化传感器:调用 init_sensor(),传入传感器类型后查找并校验对应 IIO 设备,再调用具体驱动初始化函数。

  3. 读取传感器数据:调用 read_sensor_data(),由传感器抽象层读取一帧数据并填充到 ImuData。

  4. 释放传感器资源:调用 release_sensor(),释放驱动上下文与句柄。

api_process

3.13.2.7. 编译部署

编译

  • 进入 sample_imu_iio 目录,执行 make 编译

  • 输出成果物是该源码目录下的 sample_imu_iio

  • 详细程序编译方式请查阅 编译方法 章节

硬件环境搭建

可以参考如下连接方式(使用的传感器是 BMI08x):

40pin_connect

确认硬件连接正确之后,还需要确认相应的驱动配置是否已打开。(因为该传感器非板载设备,所以下文配置在 SDK 中默认可能为关闭状态,使用前请检查实际代码中是否已打开。)

首先检查 dts,EVB 板子使用的是 x5-evb.dtsi 文件,检查对应的 i2c5 节点是否有配置;如果没有,可以参考如下配置:

&i2c5 {
	status = "okay";
    ......
	bmi08a@19 {
		compatible = "bmi08xa";
		reg = <0x19>;
		interrupt-parent = <&ls_gpio1_porta>;
		interrupts = <4 IRQ_TYPE_EDGE_RISING>;
		status = "okay";
	};

	bmi08g@69 {
		compatible = "bmi08xg";
		reg = <0x69>;
		interrupt-parent = <&ls_gpio1_porta>;
		interrupts = <6 IRQ_TYPE_EDGE_RISING>;
		status = "okay";
	};
};

该 IMU 也支持 SPI 接口,如果要使用,也可以参考设备树配置:

&spi1 {
	/*When dual chip select is used, the number of SPI chip selects must be set to 2.*/
	/*num-cs = <2>;*/
	status = "okay";
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_spi1 &pinctrl_spi1_ssn1>;
	dma-names = "tx", "rx";
	dmas = <&axi_dmac 23>, <&axi_dmac 22>;

	bmi08g@0 {
		compatible = "bmi088_gyro";
		reg = <0>;
		spi-max-frequency = <5000000>;
		interrupt-parent = <&dsp_gpio_porta>;
		interrupts = <12 IRQ_TYPE_EDGE_RISING>;
		gyro-irq-gpio = <&dsp_gpio_porta 12 GPIO_ACTIVE_HIGH>;
		status = "okay";
	};

	bmi08a@1 {
		compatible = "bmi08a";
		reg = <1>;
		spi-max-frequency = <5000000>;
		interrupt-parent = <&ls_gpio0_porta>;
		interrupts = <2 IRQ_TYPE_EDGE_RISING>;
		accel-irq-gpio = <&ls_gpio0_porta 2 GPIO_ACTIVE_HIGH>;
		status = "okay";
	};
};

注意:I2C 与 SPI 只能选择一个接口使用,未使用的接口可在设备树中设置为 disabled。

然后检查对应 defconfig(比如 EVB 默认使用 hobot_x5_soc_defconfig)是否已开启:

CONFIG_BMI08X_SUPPORT_I2C_BUS=m
CONFIG_BMI08X_SUPPORT_SPI_BUS=m

可以通过 menuconfig 开启,搜索位置参考如下截图:

boot_menuconfig_search

打开方式参考如下截图:

boot_menuconfig_config

最后编译整个镜像并刷机,检查 IMU 是否成功注册,可通过如下两种方式:

(1)通过 LOG 检查

root@buildroot:~# dmesg | grep BS
[    0.084965] CPU features: detected: Speculative Store Bypassing Safe (SSBS)
               [I]\x016<BS_LOG><bmi08_i2c_probe><187>client->name:bmi08xa / addr: 0x19
               [I]\x016<BS_LOG><bmi08_i2c_probe><187>client->name:bmi08xg / addr: 0x69
               [I]\x016<BS_LOG><sensor_init><1057>accel initilized
               [I]\x016<BS_LOG><sensor_init><1064>gyro initilized
               [I]\x016<BS_LOG><sensor_init><1065>sensor initilized
               [I]\x016<BS_LOG><sensor_init><1072>soft reset done
               [I]\x016<BS_LOG><sensor_init><1080>config stream loaded successfully
               [I]\x016<BS_LOG><sensor_init><1090>Accel power mode set to NORMAL
               [I]\x016<BS_LOG><sensor_init><1099>Gyro power mode set to NORMAL
               [I]\x016<BS_LOG><bmi08_probe><2216>Acc chip ID : 0x1e, Gyro chip ID : 0xf
               [I]\x016<BS_LOG><bmi08_request_irq><544>ACC IRQ requested for pin : 56
               [I]\x016<BS_LOG><bmi08_probe><2227>ACC IRQ requested
               [I]\x016<BS_LOG><bmi08_gyr_request_irq><563>GYR IRQ requested for pin : 57
               [I]\x016<BS_LOG><bmi08_probe><2234>GYR IRQ requested
               [I]\x016<BS_LOG><bmi08_probe><2236>sensor bmi088 probed successfully
[    4.687140] CAM_SUBSYS soc:cam:cam_sys@0: [FRT:D] camsys_probe(0)
root@buildroot:~#

可以看到 sensor ID 已正确读取:

[I]\x016<BS_LOG><bmi08_probe><2216>Acc chip ID : 0x1e, Gyro chip ID : 0xf

(2)通过 IIO 子系统检查 name 节点

root@buildroot:~# cd /sys/bus/iio/devices/iio\:device1/
root@buildroot:/sys/bus/iio/devices/iio:device1# cat name
bmi08x
root@buildroot:/sys/bus/iio/devices/iio:device1#

程序部署

把 sample_imu_iio 上传到开发板后,执行 chmod +x sample_imu_iio 赋予可执行权限。

板端默认部署路径:

/app/platform_samples/sample_imu/sample_imu_iio/sample_imu_iio

3.13.2.8. 运行

程序运行方法

直接执行程序可获得帮助信息:

./sample_imu_iio -h

不带参数运行时,程序会自动探测并使用系统中第一个可用的受支持 IMU:

./sample_imu_iio

也可通过 -n 显式指定传感器名称,例如:

./sample_imu_iio -n bmi08x
./sample_imu_iio -n icm42688-gyro

程序参数选项说明

Usage: sample_imu_iio [OPTIONS]
Options:
  -n <imu_name>         Specify IMU name (default: auto-detected)
  -h                    Show this help message
Supported sensors: bmi08x icm42688-gyro icm42688-accel

参数说明:

  • -n <imu_name>:指定 IMU 传感器名称。未指定时,程序自动探测第一个可用设备。

  • -h:显示帮助信息,并列出程序内置支持的传感器名称。

运行效果

程序运行后会显示命令菜单,用户可输入命令获取传感器数据:

root@buildroot:/app/platform_samples/sample_imu/sample_imu_iio# ./sample_imu_iio
No IMU specified, using detected default: bmi08x
Using IMU: bmi08x

=== Detected IIO Devices ===
  Device: iio:device1     | Name: bmi08x
  Device: iio:device0     | Name: 34190000.adc
============================

Device validation passed at: /sys/bus/iio/devices/iio:device1
BMI08x: Initializing with params:

***************  Command Lists  ***************
 g    -- Get a single frame of imu data
 l    -- Get multiple frames of imu data
 q    -- Quit the program
 h    -- Print this help message
Enter command:

命令说明:

  • g:获取一帧 IMU 数据

  • l:获取多帧 IMU 数据,需输入帧数

  • q:退出程序

  • h:显示帮助信息

获取一帧数据示例:

Enter command: g
Data received (Frame 1):
  Accelerometer: [-117.836021, -118.283142, 9.569026] m/s²
  Gyroscope:     [0.006392, -69.885605, 0.049002] rad/s
  Timestamp:     00:01:38.917.929

获取多帧数据示例:

Enter command: l
Enter number of frames to read: 3
Data received (Frame 1):
  Accelerometer: [-117.870140, -118.261597, 9.597756] m/s²
  Gyroscope:     [0.019175, 0.010653, -69.857903] rad/s
  Timestamp:     00:01:50.861.640
Data received (Frame 2):
  Accelerometer: [-117.825249, -118.283142, 9.574412] m/s²
  Gyroscope:     [0.014914, -69.857903, -69.887733] rad/s
  Timestamp:     00:01:50.867.500
......

3.13.2.9. 常见问题

已经接上设备,但是没有识别到设备

  • 首先确认硬件连接是否正确,检查 IMU 与开发板之间的连线是否松动、短路或接错。可参考开发板使用指南中的 40PIN 连接说明。

  • 其次检查驱动是否已向 IIO 框架正常注册。sample_imu_iio 运行时会列举 IIO 下所有设备;若未发现期望设备,请检查驱动注册情况,具体可参考上文 硬件环境搭建。

  • 若需支持新的 IMU 型号,请先在 IIO 框架下完成驱动注册,再参考 bmi08x.c 在 sample_imu_iio 中扩展传感器抽象层。

3.13.3. sample_imu_input

3.13.3.1. 功能概述

sample_imu_input 演示如何通过 Linux Input 子系统读取驱动上报的 IMU 数据。与 sample_imu_iio 的 sysfs 轮询/读取方式不同,本示例通过读取 /dev/input/eventX 节点,解析驱动通过 EV_MSC 事件连续上报的六轴原始值、硬件时间戳和 IRQ 计数,并基于时间戳间隔进行丢包检测。

本示例特点如下:

  • 持续读取驱动上报事件,无交互式 g/l/q 菜单

  • 输出六轴原始 LSB 值与 64 位硬件时间戳(ns)

  • 当相邻帧时间戳间隔超过 3.5 ms 时,判定为可能丢包并打印告警

硬件连接、设备树与内核配置等前置条件,请参考 sample_imu_iio 硬件环境搭建 的介绍。IMU 基础概念可参考 背景知识。

3.13.3.2. 软件架构说明

sample_imu_input.c 从 main 入口启动,打开 /dev/input/eventX 设备后进入 read 循环;

每次读到 input_event 后解析 EV_MSC 字段,在 SYN_REPORT 时完成组帧,打印六轴数据和时间戳,

并根据相邻帧时间戳间隔做丢包检测。程序持续运行,按 Ctrl+C 退出

software_architecture_diagram.png

3.13.3.3. 数据流说明

  1. 内核 BMI088 驱动在每次采样完成后,通过 Input 子系统上报若干 EV_MSC 事件(code = BMI088_MSC_DATA)。

  2. 一帧数据以 SYN_REPORT 结束;应用层在收到 SYN_REPORT 时,将缓存的 9 个 MSC 字段组装为一帧 IMU 数据。

  3. 应用层打印 ACC/GYRO 原始值、时间戳和 IRQ 计数,并根据相邻时间戳差值统计丢包情况。

每帧 MSC 字段顺序如下:

索引 含义
0 ~ 2 加速度计 X/Y/Z 原始值
3 ~ 5 陀螺仪 X/Y/Z 原始值
6 ~ 7 硬件时间戳高/低 32 位
8 IRQ 计数

3.13.3.4. 代码位置及目录结构

  • 代码位置:app/samples/platform_samples/sample_imu/sample_imu_input

  • 目录结构

sample_imu_input
├── Makefile
├── sample_imu_input.c
└── sample_imu_input

3.13.3.5. API 流程说明

sample_imu_input 基于标准 Linux Input 接口实现,主要流程如下:

  1. open() 打开 /dev/input/eventX 设备节点。

  2. 循环 read() 读取 input_event 结构体。

  3. 对 EV_MSC 事件缓存字段,对 SYN_REPORT 事件完成组帧与打印。

  4. 根据相邻帧硬件时间戳差值判断是否丢包。

  5. 程序退出时 close() 设备并输出统计信息。

api_process

3.13.3.6. 编译部署

编译

  • 进入 sample_imu_input 目录,执行 make 编译

  • 输出成果物是该源码目录下的 sample_imu_input

  • 详细程序编译方式请查阅 编译方法 章节

程序部署

把 sample_imu_input 上传到开发板后,执行 chmod +x sample_imu_input 赋予可执行权限。

板端默认部署路径:

/app/platform_samples/sample_imu/sample_imu_input/sample_imu_input

驱动加载成功后,可通过如下命令确认 Input 设备节点:

cat /proc/bus/input/devices
ls -l /dev/input/event*

请根据实际设备名称选择正确的 event 节点;程序默认使用 /dev/input/event1。

3.13.3.7. 运行

程序运行方法

使用默认设备节点:

./sample_imu_input

指定 Input 设备路径:

./sample_imu_input /dev/input/event2

程序启动后持续读取并打印数据,按 Ctrl+C 退出。

程序参数选项说明

本程序不使用 getopt 风格参数,支持如下调用方式:

./sample_imu_input [input_device_path]
  • input_device_path(可选):Input 设备节点路径,默认 /dev/input/event1。

运行效果

========================================
BMI088 input reader (unified MSC code)
Device path: /dev/input/event1
Press Ctrl+C to exit
========================================

ACC(-117,-118,9) | GYRO(0,-69,0) | TS:9876543210 ns | Lost: 0 | EventCount: 9 | up_count: 128 | lower_count: -
ACC(-117,-118,9) | GYRO(0,-69,0) | TS:9879876543 ns | Lost: 0 | EventCount: 9 | up_count: 129 | lower_count: -
[ERROR] IMU data lost: last ts 0.009876s, current ts 0.009883s, diff 0.000007s
......

字段说明:

  • ACC(x,y,z) / GYRO(x,y,z):六轴原始 LSB 值

  • TS:由驱动上报高低 32 位组装的硬件时间戳(ns)

  • Lost:累计疑似丢包次数

  • EventCount:当前帧收到的 input 事件数量

  • up_count:驱动上报的 IRQ 计数

  • [ERROR] IMU data lost : 丢包的标志,丢包的时间间隔需要根据具体方案需求,对程序做修改。

3.13.3.8. 常见问题

打开 /dev/input/eventX 失败

  • 请先确认 IMU 驱动是否已成功加载,硬件连接与内核配置请参考 sample_imu_iio 硬件环境搭建。

  • 使用 cat /proc/bus/input/devices 确认 IMU 对应的 event 节点编号,并在启动命令中传入正确路径。

能打开设备但没有数据输出

  • 确认驱动是否已使能数据流上报;部分场景需先完成 IIO/Input 驱动的 probe 与中断配置。

  • 检查是否选错了 event 节点(系统中可能存在键盘、触摸板等其他 Input 设备)。

如何判断是否丢包

  • 程序默认以相邻帧硬件时间戳差值大于 3.5 ms 作为丢包判定阈值;出现丢包时会打印 [ERROR] IMU data lost 日志。