RK3568 Android14 电子罗盘AK09911C调试 - 教程
一,AK09911C介绍
1.AK09911C 简介
AKM09911 是旭化成微电子(AKM)推出的一款三轴电子罗盘(磁力计)传感器,采用磁阻效应技术(AMR),具有高精度、低功耗等特点,适用于智能手机、可穿戴设备、无人机等需要地磁检测的应用场景。
2.AK09911C 主要特性
- 测量范围:±49.152 Gauss(可通过软件配置调整)。
- 分辨率:16位输出,支持0.15μT/LSB的高精度检测。
- 低功耗:典型工作电流为100μA(单次测量模式),待机电流为1μA。
- 接口:支持I²C通信(默认地址0x0C)。
- 工作电压:1.7V~3.6V,兼容低电压设备。
- 内置自检功能:支持硬件和软件自检,确保数据可靠性。
- 温度补偿:集成温度传感器,可自动校正环境温度影响。
3.AKM09911 引脚说明
| 引脚编号 | 引脚名称 | 类型 | 功能描述 | 备注 |
|---|---|---|---|---|
| 1 | VCC | 电源 | 供电(+3.3V/5V) | 不可反接 |
| 2 | GND | 地线 | 接地 | 必须连接 |
| 3 | SDA | I/O | I²C 数据线 | 开漏输出 |
| 4 | SDL | I/O | I²C 数据线 | 开漏输出 |
| 5 | RST | 复位 | 低电平复位 | 可选(软复位) |
| 6 | CAO | I/O | 地址选用 | 可选 |
4.AK09911C 原理图
二、驱动配置
1.DTS配置
我的AK09911C电子罗盘接在i2c1上,大家可以根据实际情况进行修改。
配置文件路径:kernel-6.1/arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi
&i2c1 {
status = "okay";
ak09911:ak09911@c {
compatible = "asahi-kasei,ak09911";
status = "okay";
reg = <0x0c>;#默认为0c
#采用软件方式复位
//pinctrl-names = "default";
//pinctrl-0 = <&sensor_rst_l>;
//reset-gpio = <&gpio0 RK_PB6 GPIO_ACTIVE_LOW>;
type = <SENSOR_TYPE_COMPASS>;#电子罗盘
irq_enable = <0>;
poll_delay_ms = <30>; #30ms上报一次
layout = <4>;
};
};
2.内核配置
配置文件路径:kernel-6.1/arch/arm64/configs/rockchip_defconfig
CONFIG_COMPASS_AK09911=y
打开ak09911配置后编译内核,烧写到板卡,出现驱动死锁问题,sensor-dev.c的锁跟ak09911.c的锁冲突,修改如下:
diff --git a/kernel-6.1/drivers/input/sensors/compass/ak09911.c b/kernel-6.1/drivers/input/sensors/compass/ak09911.c
index d8ff643..95bb48d 100644
--- a/kernel-6.1/drivers/input/sensors/compass/ak09911.c
+++ b/kernel-6.1/drivers/input/sensors/compass/ak09911.c
static int compass_dev_open(struct inode *inode, struct file *file)
{
+ struct sensor_private_data *sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
+ atomic_inc(&sensor->flags.open_flag);
return 0;
}
static int compass_dev_release(struct inode *inode, struct file *file)
{
+ struct sensor_private_data *sensor = (struct sensor_private_data *)i2c_get_clientdata(this_client);
+ atomic_dec(&sensor->flags.open_flag);
return 0;
}
diff --git a/kernel-6.1/drivers/input/sensors/sensor-dev.c b/kernel-6.1/drivers/input/sensors/sensor-dev.c
index 1759090..a66903b 100644
--- a/kernel-6.1/drivers/input/sensors/sensor-dev.c
+++ b/kernel-6.1/drivers/input/sensors/sensor-dev.c
@@ -894,13 +894,18 @@ error:
static int compass_dev_open(struct inode *inode, struct file *file)
{
struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_COMPASS];
- int flag = 0;
-
- flag = atomic_read(&sensor->flags.open_flag);
- if (!flag) {
- atomic_set(&sensor->flags.open_flag, 1);
- wake_up(&sensor->flags.open_wq);
- }
+ if (!sensor) return -ENODEV;
+ // struct i2c_client *client = sensor->client;
+ // int flag = 0;
+
+ // flag = atomic_read(&sensor->flags.open_flag);
+ // if (!flag) {
+ // atomic_set(&sensor->flags.open_flag, 1);
+ // wake_up(&sensor->flags.open_wq);
+ // }
+ atomic_inc(&sensor->flags.open_flag);
+ //dev_err(&client->dev," open_flag=%d", atomic_read(&sensor->flags.open_flag));
+ wake_up_interruptible(&sensor->flags.open_wq); // 新增:唤醒等待队列
return 0;
}
@@ -908,14 +913,12 @@ static int compass_dev_open(struct inode *inode, struct file *file)
static int compass_dev_release(struct inode *inode, struct file *file)
{
struct sensor_private_data *sensor = g_sensor[SENSOR_TYPE_COMPASS];
- int flag = 0;
-
- flag = atomic_read(&sensor->flags.open_flag);
- if (flag) {
- atomic_set(&sensor->flags.open_flag, 0);
- wake_up(&sensor->flags.open_wq);
- }
+ if (!sensor) return -ENODEV;
+ // struct i2c_client *client = sensor->client;
+ atomic_dec(&sensor->flags.open_flag);
+ //dev_err(&client->dev,"open_flag=%d", atomic_read(&sensor->flags.open_flag));
+ wake_up_interruptible(&sensor->flags.open_wq); // 新增:唤醒等待队列
return 0;
}
@@ -987,13 +990,17 @@ static long compass_dev_ioctl(struct file *file,
case ECS_IOCTL_APP_SET_AFLAG:
case ECS_IOCTL_APP_SET_MVFLAG:
if (copy_from_user(&flag, argp, sizeof(flag)))
+ {
return -EFAULT;
+ }
if (flag < 0 || flag > 1)
return -EINVAL;
break;
case ECS_IOCTL_APP_SET_DELAY:
if (copy_from_user(&flag, argp, sizeof(flag)))
+ {
return -EFAULT;
+ }
break;
default:
break;
@@ -1014,6 +1021,15 @@ static long compass_dev_ioctl(struct file *file,
break;
case ECS_IOCTL_APP_SET_MVFLAG:
atomic_set(&sensor->flags.mv_flag, flag);
+ // mutex_lock(&sensor->operation_mutex);
+ // if (flag) {
+ // if (sensor->status_cur == SENSOR_OFF)
+ // sensor_enable(sensor, SENSOR_ON);
+ // } else {
+ // if (sensor->status_cur == SENSOR_ON)
+ // sensor_enable(sensor, SENSOR_OFF);
+ // }
+ // mutex_unlock(&sensor->operation_mutex);
break;
case ECS_IOCTL_APP_GET_MVFLAG:
再次编译后,查看日志,ak09911c设备成功注册:
rk3568_t:/ # dmesg| grep 9911
[ 2.439788] [AK09911] compass_akm09911_probe: start (client addr=0x0c, name=ak09911)
[ 2.439797] compass_akm09911 1-000c: sensor_register_device: akm09911, id = 42
[ 2.439819] i2c i2c-1: sensor_probe: ak09911,00000000222b1ebb
[ 2.440326] compass_akm09911 1-000c: sensor_chip_init:ak09911:devid=0x5,ops=0x00000000ee3205d2
[ 2.440344] [AK09911] sensor_init: start (client addr=0x0c)
[ 2.440684] [AK09911] sensor_init: initial state set to SENSOR_OFF
[ 2.440811] [AK09911] sensor_init: misc device 'akm_dev' registered, minor=124
[ 2.441372] [AK09911] sensor_init: WIA1=0x48, WIA2=0x05 (expected WIA2=0x05)
[ 2.442022] [AK09911] sensor_init: init completed successfully
[ 2.442280] compass_akm09911 1-000c: sensor_irq_init:use polling,delay=30 ms
[ 2.442409] compass_akm09911 1-000c: sensor_misc_device_register:miscdevice: compass
[ 2.442426] compass_akm09911 1-000c: sensor_probe:initialized ok,sensor name:akm09911,type:3,id=42
[ 2.442439] [AK09911] compass_akm09911_probe: probe completed successfully
[ 11.492653] [AK09911] compass_dev_ioctl: GET_INFO copied 2 bytes (WIA1/WIA2)
[ 11.492675] [AK09911] compass_dev_ioctl: GET_CONF copied 3 bytes (fuse data)
[ 11.493369] [AK09911] compass_dev_ioctl: unknown cmd=0x00006303 before arg check
[ 11.493413] [AK09911] compass_akm_reset: start (client addr=0x0c)
[ 11.493778] [AK09911] compass_akm_reset: fallback to measure mode completed
[ 11.493905] [AK09911] compass_dev_ioctl: RESET completed successfully
[ 11.493941] [AK09911] compass_akm_set_mode: sensor status changed to SENSOR_ON
[ 11.494342] [AK09911] compass_akm_set_mode: set to single measurement mode
[ 11.494357] [AK09911] compass_dev_ioctl: SET_MODE updated to 0x01
三、HAL层配置
1、hal配置
开启hal层sensor配置,让Android系统支持COMPASS传感器,文件路径:device/rockchip/rk356x/BoardConfig.mk。
BOARD_COMPASS_SENSOR_SUPPORT := true
在开启AK09911C支持之前先看一下配置文件,文件路径hardware/rockchip/sensor/st/Android.mk
######### AKM daemon #################################################
ifeq ($(strip $(BOARD_SENSOR_COMPASS_AK8963)), true)
include $(LOCAL_PATH)/akm8963/Android.mk
else ifeq ($(strip $(BOARD_SENSOR_COMPASS_AK09911)), true)
include $(LOCAL_PATH)/akm09911/Android.mk
else ifeq ($(strip $(BOARD_SENSOR_COMPASS_AK8975)), true)
include $(LOCAL_PATH)/akm8975/Android.mk
else ifeq ($(strip $(BOARD_SENSOR_COMPASS_AK8963-64)), true)
include $(LOCAL_PATH)/akm8963-64/Android.mk
endif # ifeq ($(strip $(BOARD_SENSOR_COMPASS_AK8963)), true)
从上面可以看到compass传感器是可以支持多种型号的,由于BOARD_SENSOR_COMPASS_AK09911编译报错,没继续跟进是什么问题。发现AK8963的hal源码也有AK09911,从而选择了使用AK8963-64编译。在BoardConfig.mk加上。
BOARD_SENSOR_COMPASS_AK8963-64 := true
紧接着再修改一下AK8963源码支持AK09911,文件路径:hardware/rockchip/sensor/st/akm8963-64/Android.mk
diff --git a/hardware/rockchip/sensor/st/akm8963-64/Android.mk b/hardware/rockchip/sensor/st/akm8963-64/Android.mk
index 8fbfca2..2fbe039 100755
--- a/hardware/rockchip/sensor/st/akm8963-64/Android.mk
+++ b/hardware/rockchip/sensor/st/akm8963-64/Android.mk
@@ -1,7 +1,7 @@
ifeq (${TARGET_ARCH},arm64)
ifneq ($(TARGET_SIMULATOR),true)
-BOARD_SENSOR_COMPASS_AK09911 := false
+BOARD_SENSOR_COMPASS_AK09911 := true
LOCAL_PATH:= $(call my-dir)
@@ -78,8 +78,8 @@ endif
endif
LOCAL_CFLAGS += -Wall -Wextra
#需要日志的话可以开启调试
-#LOCAL_CFLAGS += -DENABLE_AKMDEBUG=1
-#LOCAL_CFLAGS += -DAKM_LOG_ENABLE
LOCAL_MODULE_TAGS := optional
LOCAL_FORCE_STATIC_EXECUTABLE := false
2.SELlinux配置
diff --git a/device/rockchip/common/rootdir/init.rk30board.rc b/device/rockchip/common/rootdir/init.rk30board.rc
index 62cffb1..828189e2 100755
--- a/device/rockchip/common/rootdir/init.rk30board.rc
+++ b/device/rockchip/common/rootdir/init.rk30board.rc
@@ -15,6 +15,7 @@ on post-fs-data
mkdir /data/vendor/logs 0755 root shell
mkdir /data/vendor/audio 0755 audioserver audioserver
mkdir /data/vendor/camera 0755 cameraserver cameraserver
+ mkdir /data/vendor/akmd 0755 system system
on init
# set temperature control policy as normal mode
以上就配置完了,使用Sensor sense 测试APP来验证。

浙公网安备 33010602011771号