本文主要记录如何在 Rockchip RK3506 上接入并驱动 ADIS16505 IMU 模块。

Linux 有 IIO 子系统(工业输入输出),用于接入一些工业传感器,其中就包括 IMU。Analog ADIS16505 是一款使用较多的 MEMS IMU 模组,其驱动早已进入内核。

下面直接介绍相关适配工作,适配的 SOC 是 Rockchip RK3506,内核6.1,使用的模块是 ADIS16505-2。

参考资料:

1. 驱动适配

内核 CONFIG 修改:

1
2
3
+CONFIG_ADIS16475=m
+CONFIG_IIO_ADIS_LIB_BUFFER=y
+CONFIG_IIO_ADIS_LIB=y

然后编译出来 adis_lib.koadis16475.ko 拷贝到开发板,添加到 /lib/modules/$(uname -r)/kernel/drivers/iio/imu 下。

DTS 修改,在对应 spi 节点下添加 imu@0 节点(ADIS16505 最大只支持 2M 时钟,所以一般无法和其他外设共享 SPI 总线,建议单独一个 SPI 与之连接):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
+ imu@0 {
+            compatible = "adi,adis16505-2";
+            reset-gpios = <&gpio1 RK_PC7 GPIO_ACTIVE_LOW>;
+            reg = <0>;
+            spi-cpha;
+            spi-cpol;
+            spi-max-frequency = <2000000>;
+            interrupts = <RK_PB5 IRQ_TYPE_EDGE_RISING>;
+            interrupt-parent = <&gpio0>;
+            status = "okay";
+ };

pinctrl 配置复位和终端引脚:

1
2
3
4
5
6
7
8
9
+ &pinctrl {
+        adis16505 {
+                imu_pins: imu-pins {
+			             rockchip,pins =
+			             <1 RK_PC7 RK_FUNC_GPIO &pcfg_pull_none>,
+			             <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
+		         };
+        };
+}

编译,烧写 boot 镜像。

启动后,会自动加载 adis 内核模块驱动,检查 lsmod | grep adis 会输出。

2. 读取验证

数据检查,安装 apt install libiio-utils ,然后用 sudo iio_info 检查,一般输出如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
sudo iio_info
Library version: 0.23 (git tag: v0.23)
Compiled with backends: local xml ip usb
IIO context created with local backend.
Backend version: 0.23 (git tag: v0.23)
Backend description string: Linux rk3506-iot 6.1.99 #18 SMP PREEMPT Sun Sep 28 16:51:31 CST 2025 armv7l
IIO context has 2 attributes:
        local,kernel: 6.1.99
        uri: local:
IIO context has 2 devices:
        iio:device0: adis16505-2 (buffer capable)
                8 channels found:
                        anglvel_x:  (input, index: 0, format: be:S32/32>>0)
                        3 channel-specific attributes found:
                                attr  0: calibbias value: 0
                                attr  1: raw value: 822982
                                attr  2: scale value: 0.000000006
                        anglvel_y:  (input, index: 1, format: be:S32/32>>0)
                        3 channel-specific attributes found:
                                attr  0: calibbias value: 0
                                attr  1: raw value: 632205
                                attr  2: scale value: 0.000000006
                        anglvel_z:  (input, index: 2, format: be:S32/32>>0)
                        3 channel-specific attributes found:
                                attr  0: calibbias value: 0
                                attr  1: raw value: -574057
                                attr  2: scale value: 0.000000006
                        accel_x:  (input, index: 3, format: be:S32/32>>0)
                        3 channel-specific attributes found:
                                attr  0: calibbias value: 0
                                attr  1: raw value: -182676799
                                attr  2: scale value: 0.000000037
                        accel_y:  (input, index: 4, format: be:S32/32>>0)
                        3 channel-specific attributes found:
                                attr  0: calibbias value: 0
                                attr  1: raw value: 73639656
                                attr  2: scale value: 0.000000037
                        accel_z:  (input, index: 5, format: be:S32/32>>0)
                        3 channel-specific attributes found:
                                attr  0: calibbias value: 0
                                attr  1: raw value: -172736170
                                attr  2: scale value: 0.000000037
                        temp0:  (input, index: 6, format: be:S16/16>>0)
                        2 channel-specific attributes found:
                                attr  0: raw value: 307
                                attr  1: scale value: 100
                        timestamp:  (input, index: 7, format: le:S64/64>>0)
                4 device-specific attributes found:
                                attr  0: current_timestamp_clock value: monotonic

                                attr  1: filter_low_pass_3db_frequency value: 720
                                attr  2: sampling_frequency value: 400.000000
                                attr  3: waiting_for_supplier value: 0
                3 buffer-specific attributes found:
                                attr  0: data_available value: 0
                                attr  1: direction value: in
                                attr  2: watermark value: 1
                6 debug attributes found:
                                debug attr  0: firmware_date value: 08-19-2021
                                debug attr  1: firmware_revision value: 1.7
                                debug attr  2: flash_count value: 55
                                debug attr  3: product_id value: 16505
                                debug attr  4: serial_number value: 0x2aa7
                                debug attr  5: direct_reg_access value: 0x0
                Current trigger: trigger0(adis16505-2-dev0)
        trigger0: adis16505-2-dev0
                0 channels found:
                No trigger on this device

如果有 error 或问题,则需要检查 DTS 引脚与实际的接线,接线有问题会导致出现问题。

这里需要注意 anglvelaccelscale 字段,会跟手册的对不上,这个稍后解释。

读取实际数据,可以交叉编译内核 tools/iio/iio_generic_buffer 程序,使用 sudo iio_generic_buffer -n adis16505-2 -a -c -1 来连续可读所有数据,包括 时间戳:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
sudo iio_generic_buffer -n adis16505-2 -a -c -1
iio device number being used is 0
iio trigger number being used is 0
Enabling all channels
Enabling: in_accel_y_en
Enabling: in_temp0_en
Enabling: in_anglvel_z_en
Enabling: in_accel_x_en
Enabling: in_timestamp_en
Enabling: in_anglvel_y_en
Enabling: in_accel_z_en
Enabling: in_anglvel_x_en
/sys/bus/iio/devices/iio:device0 adis16505-2-dev0
0.003762 0.003326 -0.000192 -6.759874 2.724417 -6.391016 30600.000000 1759115389553132535 
0.001698 0.002608 -0.001356 -6.764592 2.726806 -6.392885 30600.000000 1759115389555627474 
0.000364 0.004624 -0.000209 -6.756444 2.718365 -6.381812 30600.000000 1759115389558121829 
-0.000038 0.003894 -0.000131 -6.760957 2.724637 -6.373475 30600.000000 1759115389560619101 
-0.000031 0.004665 -0.001059 -6.754562 2.714244 -6.378930 30800.000000 1759115389563114623 
0.001390 0.003611 -0.001513 -6.760931 2.723385 -6.377503 31000.000000 1759115389565610144 
0.002020 0.003198 -0.000661 -6.759657 2.719233 -6.383900 31000.000000 1759115389568120833 
0.002179 0.002808 -0.004133 -6.762529 2.723939 -6.387537 31000.000000 1759115389570598855 
0.001080 0.004518 -0.003293 -6.761709 2.727158 -6.387032 30700.000000 1759115389573096710 
0.000033 0.002241 -0.002442 -6.756791 2.720568 -6.381608 30700.000000 1759115389575591065 
0.000519 0.003776 -0.003139 -6.759673 2.720824 -6.381290 30700.000000 1759115389578086587 
0.000121 0.003285 -0.004375 -6.761266 2.715935 -6.379437 30600.000000 1759115389580582108 
-0.000275 0.003437 -0.003296 -6.761114 2.716521 -6.379723 30600.000000 1759115389583077047 
0.002979 0.004323 -0.002205 -6.760320 2.717569 -6.381045 30600.000000 1759115389585569360 
0.003052 0.003355 -0.003360 -6.764820 2.720145 -6.388940 30500.000000 1759115389588067799 
0.001705 0.003426 -0.002130 -6.761583 2.715266 -6.392511 30500.000000 1759115389590562446 
0.002971 0.003035 -0.003745 -6.760653 2.715627 -6.385410 30500.000000 1759115389593058259 
0.001787 0.003784 -0.002825 -6.763578 2.716290 -6.383574 30600.000000 1759115389595552614 
0.000679 0.003716 -0.004219 -6.761706 2.714494 -6.381908 30600.000000 1759115389598048428 
0.001852 0.001673 -0.002511 -6.764761 2.713016 -6.385989 30600.000000 1759115389600543949 
0.001230 0.003286 -0.003984 -6.759422 2.706651 -6.386874 30600.000000 1759115389603039471 
0.001944 0.003745 -0.001667 -6.764474 2.714547 -6.382912 30500.000000 1759115389605535285 

驱动默认使用 realtime,可以通过修改 /sys/bus/iio/devices/iio:deviceX/current_timestamp_clock 来修改时间戳,可选 monotonic 使用 MONO 时间,来避免系统时间调整导致的跳跃。

3. 注意事项

由于内核中不支持浮点数,所以内核驱动在 sysfs 中展示的浮点字段,都存在精度损失(内核打印浮点只保留1e-9的精度,无法满足这款IMU的比例系数),也就意味着,不能直接使用驱动提供的 sysfs 中的 scale 字段来求解物理值,而是直接使用芯片手册中的比例换算,在用户空间解算物理值,否则会有严重的精度丢失。针对 IIO 驱动,只使用 buffer 提供的原始值,和手册的比例系数进行换算,是最为稳妥的方式。

同时驱动在 /sys/kernel/debug/iio/iio\:deviceX/ 目录下提供一些额外信息:

1
2
ls  /sys/kernel/debug/iio/iio\:device1/
direct_reg_access  firmware_date      firmware_revision  flash_count        product_id         serial_number

这些字段可以通过参考资料2了解具体含义,比较有用的是 direct_reg_access 这个文件,可以通过它来实现直接的底层寄存器读写:

1
2
3
4
5
6
7
8
9
# 读取 0x60
echo 0x60 > direct_reg_access

cat 0x60
=> 0x2c1
# 写入 0x60
echo 0x60 0x2c1 > direct_reg_access
cat 0x60
=> 0x2c1

另外如频率设置、滤波设置等,可以参考参考治疗,直接修改 sysfs 下文件即可。