2026山东大学软件学院创新项目实训(七)
一、问题背景: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
从结果来看:
-
cam_sensor0 存在
-
cam_sensor2 存在
-
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
终于发现真实硬件。
说明:
- 硬件存在
- IIO驱动存在
- 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。但尝试过还是无法解决。
更多推荐

所有评论(0)