一、问题背景:Sensor节点存在,但真实硬件没有接入

在完成 GPU、蓝牙等模块排查后,由于蓝牙经过多次尝试都没有成功,所以我先开始验证 OpenHarmony Sensor 子系统。

理论上,系统启动后应该能够通过 SensorService 获取加速度计、陀螺仪等传感器数据。

首先检查 Sensor 相关设备节点:

hdc shell "ls -la /dev/hdf_sensor* /dev/cam_sensor*"

结果如下:

crw-rw---- 1 root root 235,0 /dev/cam_sensor0
crw-rw---- 1 root root 235,2 /dev/cam_sensor2

crwxrwxrwx 1 sensor_host sensor_host 234,8
/dev/hdf_sensor_manager_ap

从结果来看:

  1. cam_sensor0 存在

  2. cam_sensor2 存在

  3. hdf_sensor_manager_ap 存在

说明 HDF Sensor Framework 已经正常启动。

但继续查看日志时发现异常:

hdc shell "dmesg | grep sensor"

输出:

[Fail][E002106]
Failed to communicate with daemon

虽然设备节点已经创建,但 Sensor 数据链路似乎并未真正建立。

因此开始逐层分析 Sensor 架构。


二、第一轮诊断:确认 HDF 服务状态

首先检查 HDF 服务是否正常运行:

hdc shell "ps -A | grep -iE 'sensor|hdf'"

输出:

222 ? 00:00:00 hdf_devmgr
490 ? 00:00:00 sensor_host
514 ? 00:00:00 sensors

三个关键进程均存在:

hdf_devmgr
    ↓
负责驱动加载

sensor_host
    ↓
负责Sensor驱动运行

sensors
    ↓
SensorService

从服务层面看没有明显异常。

继续查看 SensorService 当前注册的传感器:

hdc shell "hidumper -s SensorService -a '-l'"

结果:

Total sensor:1

sensorType:ACCELEROMETER

sensorName:sensor_test

vendorName:default

maxRange:9999

这里立刻发现异常。

正常情况下应该看到:

mxc4005
bmi160
bmi270

等真实硬件名称。

而当前显示:

sensor_test
vendor=default

显然只是测试设备。

进一步观察:

maxRange = 9999

完全不像真实加速度计参数。

因此可以判断:

SensorService
    ↓
返回的是 Mock Sensor

问题已经初步定位。

三、顺藤摸瓜:真实硬件在哪里

既然 SensorService 返回的是 Mock Sensor,那么真实硬件是否工作?

Linux 下传感器通常挂载在 IIO 子系统。

查看 IIO 设备:

hdc shell "ls /sys/bus/iio/devices/"

结果:

iio:device0

查看设备名称:

hdc shell \
"cat /sys/bus/iio/devices/iio:device0/name"

结果:

mxc4005

终于发现真实硬件。

说明:

  1. 硬件存在          
  2. IIO驱动存在       
  3. SensorService接入 

继续验证传感器数据:

hdc shell \
"cat /sys/bus/iio/devices/iio:device0/in_accel_x_raw"

hdc shell \
"cat /sys/bus/iio/devices/iio:device0/in_accel_y_raw"

hdc shell \
"cat /sys/bus/iio/devices/iio:device0/in_accel_z_raw"

输出:

57
2
875

查看比例因子:

hdc shell \
"cat /sys/bus/iio/devices/iio:device0/in_accel_scale"

结果:

0.009582

计算得到:

875 × 0.009582

≈ 8.38m/s²

开发板平放时重力主要作用于 Z 轴,因此数据合理。

证明:

MXC4005硬件正常
MXC4005 IIO驱动正常

问题位于 HDF Sensor 层。


四、进一步定位:HDF驱动配置错误

查看硬件路径:

hdc shell \
"readlink -f /sys/bus/iio/devices/iio:device0"

结果:

/sys/devices/platform/soc/d4013800.i2c/
i2c-5/5-0015/iio:device0

继续查看设备树兼容字符串:

hdc shell \
"cat /sys/bus/iio/devices/iio:device0/of_node/compatible"

结果:

memsic,mxc4005

确认板载加速度计型号:

MXC4005

随后检查 defconfig:

grep HDF_SENSOR \
arch/riscv/configs/k1_defconfig

结果:

CONFIG_DRIVERS_HDF_SENSOR_ACCEL=y
CONFIG_DRIVERS_HDF_SENSOR_ACCEL_MXC6655XA=y

这里发现关键问题。

开发板实际硬件:

MXC4005

而系统启用的驱动:

MXC6655XA

因此驱动初始化后无法匹配设备。

最终只能退回默认 Mock Sensor。

五、 编写 MXC4005 HDF 驱动

为了接入真实硬件,需要新增 MXC4005 HDF 驱动。

项目源码中已经存在:

ls drivers/peripheral/sensor/chipset/accel/

结果:

accel_bmi160.c
accel_bmi270.c
accel_mxc6655xa.c

其中:

accel_mxc6655xa.c

与 MXC4005 同属 MEMSIC 系列。

因此直接以该驱动作为模板。

驱动核心思路如下:

MXC4005
    ↓
IIO
    ↓
sysfs
    ↓
HDF Driver
    ↓
SensorService

由于 IIO 驱动已经占用 I2C 设备,因此不能再次直接访问寄存器。

验证:

hdc shell \
"i2cget -y 5 0x15 0x0F"

结果:

Resource busy

因此驱动最终采用:

filp_open()
kernel_read()

读取:

/sys/bus/iio/devices/iio:device0/

中的数据文件。

驱动核心逻辑:

SysfsReadInt()
        ↓
ReadMxc4005Data()
        ↓
SensorReportEvent
        ↓
SensorService

完成了 IIO 与 HDF 的桥接。

六、 修改构建系统

新增驱动后,需要同步修改构建系统。

Kconfig

新增:

CONFIG_DRIVERS_HDF_SENSOR_ACCEL_MXC4005

Makefile

新增:

obj-$(CONFIG_DRIVERS_HDF_SENSOR_ACCEL_MXC4005) += \
$(SENSOR_ROOT_CHIPSET)/chipset/accel/accel_mxc4005.o

defconfig

替换:

CONFIG_DRIVERS_HDF_SENSOR_ACCEL_MXC6655XA=y

为:

CONFIG_DRIVERS_HDF_SENSOR_ACCEL_MXC4005=y

至此驱动已经接入 Kbuild 系统。

七、 编译过程:连续踩坑实录

真正开始编译时,问题远比写驱动复杂。

7.1:ninja局部编译失败

尝试:

cd out/musepaper2

ninja drivers/peripheral/sensor/hdi_service_3.0:libsensor_driver

直接报错:

multiple rules generate
dlp_manager.stamp

即使:

ninja -w dupbuild=warn

也会长时间卡死。

最终放弃 ninja 路线。

7.2:target-name 实际跑全量

尝试:

./build.sh \
--product-name musepaper2 \
--target-name drivers/peripheral/sensor/hdi_service_3.0:libsensor_driver

结果:

[32295/118367]

直接开始执行十余万条任务。

说明 target-name 并没有真正限制编译范围。

最终放弃 OHOS 构建系统。

7.3:交叉编译器找不到

make ARCH=riscv \
CROSS_COMPILE=riscv64-unknown-linux-gnu-

报错:

C compiler
'riscv64-unknown-linux-gnu-gcc'
not found

解决:

export PATH="$HOME/workspace/oh6_riscv/prebuilts/gcc/linux-x86/riscv64/spacemit-riscv-gcc/bin:$PATH"

7.4:PRODUCT_PATH未设置

继续编译:

PRODUCT_PATH=
*** PRODUCT_PATH is not set

解决:

export PRODUCT_PATH=vendor/spacemit/musepaper2

7.5:源码未同步到内核构建目录

编译时:

accel_mxc4005.o
No such file

原因是:

OHOS构建目录
≠
源码目录

需要手动同步:

cp accel_mxc4005.* \
out/kernel/OBJ/musepaper2/...

7.6:结构体不完整

报错:

invalid application of sizeof
to incomplete type

原因:

#include "accel_mxc4005.h"

遗漏。

补充头文件后解决。

7.7:头文件引用错误

最初引用:

#include "hdf_device_desc.h"

导致:

struct IDeviceIoService
未定义

参考 MXC6655XA 驱动后改为:

#include "sensor_accel_driver.h"
#include "sensor_config_parser.h"

解决。

7.8:RISC-V内核不支持浮点

链接时报错:

__mulsf3
__fixsfsi

原因:

x * SCALE

触发软浮点依赖。

最终改为直接返回原始整数值。

7.9:filp_open符号问题

编译模块时:

undefined symbol:
filp_open
kernel_read
filp_close

这些函数未 EXPORT_SYMBOL。

因此放弃 .ko 模块。

改为:

Built-in Driver (=y)

内置编译。

最终成功。

八、 内核编译与 Image.itb 打包

驱动编译通过后开始链接内核:

make ARCH=riscv \
CROSS_COMPILE=riscv64-unknown-linux-gnu- \
Image

随后生成 FIT 镜像:

make ARCH=riscv \
CROSS_COMPILE=riscv64-unknown-linux-gnu- \
Image.itb

验证驱动已打入镜像:

strings Image.itb | grep MXC4005

输出:

HDF_SENSOR_ACCEL_MXC4005
mxc4005 driver init ok

证明驱动已经进入镜像。

九、 部署验证与最终状态

部署阶段先后尝试:

替换 ext4 Image.itb
        ↓
     无效

修改 boot.img
        ↓
镜像截断

定位 U-Boot 裸偏移
        ↓
确认启动位置

最终确认:

驱动代码     
Kconfig       
Makefile      
defconfig    
内核编译      
Image.itb     

十、 本阶段总结

这次 Sensor 驱动开发最大的收获并不是写出几百行驱动代码,而是完整理解了 OpenHarmony Sensor 框架的工作方式。

通过逐层分析最终确认:

SensorService
        ↓
HDF Driver
        ↓
IIO Driver
        ↓
MXC4005 Hardware

驱动写好了,内核编好了,Image.itb 打包好了,文件里也能搜到 HDF_SENSOR_ACCEL_MXC4005 和 mxc4005 driver init ok 字符串。但部署到板子时撞上了和蓝牙一模一样的墙:板子有两个 eMMC(mmcblk0 槽A + mmcblk2 槽B),U-Boot 从槽A 的裸偏移 0x616000 读内核 Image.itb,而我们所有操作——TitanFlasher 烧录、dd 写裸偏移、ext4 里替换文件——全部作用在槽B。在 ext4 里替换的 Image.itb 文件 U-Boot 根本不读(它读的是裸偏移,不理文件系统);dd 到 boot.img 裸偏移时又把 256MB 镜像截断成了 45MB;最后需要 dd 到 mmcblk0p5 但因为是裸分区写操作被禁止了。驱动本身没问题,只差最后一步把 38MB 的新 Image.itb 怼进槽A 的裸偏移 0x616000。但尝试过还是无法解决。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐