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 数据,支持 bmi08xicm42688-gyroicm42688-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.himu_manager.c 提供传感器管理接口,包括列出可用传感器、初始化传感器、读取数据、释放资源等。

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

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

软件架构图:

software_architecture_diagram.png

3.13.2.3. 数据流说明

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

  2. 传感器抽象in_accel_*_rawin_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.csample_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 日志。