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 引脚说明

引脚编号引脚名称类型功能描述备注
1VCC电源供电(+3.3V/5V)不可反接
2GND地线接地必须连接
3SDAI/OI²C 数据线开漏输出
4SDLI/OI²C 数据线开漏输出
5RST复位低电平复位可选(软复位)
6CAOI/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来验证。
在这里插入图片描述
在这里插入图片描述

posted @ 2026-01-09 12:39  clnchanpin  阅读(55)  评论(0)    收藏  举报