9轴传感器MPU9250调试

MPU9250实际上是mpu6500+ak8963的贴合芯片,内部的AK8963是负责三轴磁力传感器采样的芯片 ,它通过I2C总线与MPU6500连接在一起。ak8963的寄存器读取可以通过特定的i2c直通模式:

驱动代码,也是用mpu6500和ak8963对应的驱动即可。 gsensor、陀螺仪、地磁传感器对应驱动如下:

drivers/input/sensors/accel/mpu6500_acc.c
drivers/input/sensors/gyro/mpu6500_gyro.c

drivers/input/sensors/compass/ak8963.c.c

 

调试步骤:

  1.开启支持地磁传感器和编译AK8963的hardware:

device/rockchip/rk356x
diff --git a/BoardConfig.mk b/BoardConfig.mk
index 4601141..46b500f 100644
--- a/BoardConfig.mk
+++ b/BoardConfig.mk
@@ -54,6 +54,7 @@ endif
 BOARD_SENSOR_ST := true
 BOARD_SENSOR_MPU_VR := false
 BOARD_SENSOR_MPU_PAD := false
+BOARD_SENSOR_COMPASS_AK8963-64 := true
 
 BOARD_USES_GENERIC_INVENSENSE := false
 
@@ -68,7 +69,7 @@ BOARD_NFC_SUPPORT := false
 BOARD_HAS_GPS := true
 
 BOARD_GRAVITY_SENSOR_SUPPORT := true
-BOARD_COMPASS_SENSOR_SUPPORT := false
+BOARD_COMPASS_SENSOR_SUPPORT := true
 BOARD_GYROSCOPE_SENSOR_SUPPORT := true
 BOARD_PROXIMITY_SENSOR_SUPPORT := false
 BOARD_LIGHT_SENSOR_SUPPORT := false
BOARD_SENSOR_COMPASS_AK8963-64这个宏对应的编译代码为:
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

 

 2.dts设备添加:

@@ -306,6 +306,36 @@
                type = <SENSOR_TYPE_GYROSCOPE>;
                //layout = <5>;
        };
+
+       mpu6500_acc: mpu_acc@68 {
+               compatible = "mpu6500_acc";
+               status = "okay";
+               reg = <0x68>;
+               irq-gpio = <&gpio3 RK_PA3 IRQ_TYPE_EDGE_RISING>;
+               irq_enable = <0>;
+               poll_delay_ms = <30>;
+               type = <SENSOR_TYPE_ACCEL>;
+               layout = <9>;
+       };
+
+       mpu6500_gyro: mpu_gyro@68 {
+               compatible = "mpu6500_gyro";
+               status = "okay";
+               reg = <0x68>;
+               irq_enable = <0>;
+               poll_delay_ms = <30>;
+               type = <SENSOR_TYPE_GYROSCOPE>;
+               layout = <9>;
+       };
+
+       akm8963_mag: akm_mag@c {
+               status = "okay";
+               compatible = "ak8963";
+               reg = <0x0c>;
+               type = <SENSOR_TYPE_COMPASS>;
+               poll_delay_ms = <30>;
+               layout = <3>;
+       };

 

3.驱动修改:

  直通模式需要MPU6500初始化的时候设置一下0x37这个寄存器Bit1写1即可开启,然后就会有0x0c的地址出来,这个就是ak8963的地址,相当于一条总线挂2个单独的设备。

#define MPU6500_INT_PIN_CFG        0x37
/*------------------------------
    MPU6500_INT_PIN_CFG
--------------------------------*/
#define BIT_BYPASS_EN           0x2

 

diff --git a/drivers/input/sensors/accel/mpu6500_acc.c b/drivers/input/sensors/accel/mpu6500_acc.c
index 6fc2058e0f9f..3dee84f6b44e 100644
--- a/drivers/input/sensors/accel/mpu6500_acc.c
+++ b/drivers/input/sensors/accel/mpu6500_acc.c
@@ -86,7 +86,7 @@ static int sensor_active(struct i2c_client *client, int enable, int rate)
        int result = 0;
        int status = 0;
        u8 pwrm1 = 0;
-
+       
        sensor->ops->ctrl_data = sensor_read_reg(client, sensor->ops->ctrl_reg);
        pwrm1 = sensor_read_reg(client, MPU6500_PWR_MGMT_1);
 
@@ -175,6 +175,11 @@ static int sensor_init(struct i2c_client *client)
        }
        msleep(10);
 
+       res = sensor_write_reg(client, MPU6500_INT_PIN_CFG, BIT_BYPASS_EN);
+       if (res)
+               pr_err("%s:wmc---wmc---t-pass1 mode\n", __func__);
+       read_data = sensor_read_reg(client, MPU6500_INT_PIN_CFG);
+
        res = sensor->ops->active(client, 0, sensor->pdata->poll_delay_ms);

设置完0x37寄存器的时候,发现差不多开机起来才有对应的0x0c地址出来(i2ctool工具检测),这个时候如果正常加载ak8963,会失败(原因是0x0c的地址还没有出来)。试过把ak8963编译成模块的方式,开机完成后在脚本里启动.ko驱动,驱动可以加载成功,但是没有数据上报。原因应该是驱动一定要在HAL层启动之前初始化,要不然可能没有生成/dev/compass这个文件节点,HAL层会出错。

仔细看开机log:

[   19.676846] gsensor_mpu6500 5-0068: set sensor poll time to 66ms
[   19.677119] sensor_active-------hfksdhfkskg.......enable:1
[   19.761173] gsensor_mpu6500 5-0068: sensor on: starting poll sensor data 62ms

发现有一个hal对底层ioclt的动作,追踪代码流程:

drivers/input/sensors/sensor-dev.c
gsensor_dev_ioctl
    -->GSENSOR_IOCTL_APP_SET_RATE
        -->sensor_reset_rate

static int sensor_reset_rate(struct i2c_client *client, int rate)
{
    .......

    if (sensor->status_cur == SENSOR_ON) {
        if (!sensor->pdata->irq_enable) {
            sensor->stop_work = 1;
            cancel_delayed_work_sync(&sensor->delaywork);
        }
        sensor->ops->active(client, SENSOR_OFF, rate);
        result = sensor->ops->active(client, SENSOR_ON, rate);
        if (!sensor->pdata->irq_enable) {
            sensor->stop_work = 0;
            schedule_delayed_work(&sensor->delaywork, msecs_to_jiffies(sensor->pdata->poll_delay_ms));
        }
    }

    .......
}
sensor->ops->active实际调用了
static int sensor_active(struct i2c_client *client, int enable, int rate)
{
。。。。

    if (!enable) {
        status = BIT_ACCEL_STBY;
        sensor->ops->ctrl_data |= status;
        if ((sensor->ops->ctrl_data &  BIT_GYRO_STBY) == BIT_GYRO_STBY) {
            pwrm1 |= MPU6500_PWRM1_SLEEP;
        }
    } else {
        status = ~BIT_ACCEL_STBY;
        sensor->ops->ctrl_data &= status;
        pwrm1 &= ~MPU6500_PWRM1_SLEEP;

        mpu6500_set_rate(client, rate);
    }
。。。。
}
传入的enable参数要为1的时候,6500设置的寄存器的功能才有效。正常开机完成的时候,ioctl对底层会设置1。这也是为什么开机初阶段为什么命明设置了0x37的寄存器,
但是要等开机才有0x0c地址出来的原因。
于是要想办法不等开机起来,直接在开机初始化的时候就设置enble为1即可解决该问题。
在sensor_init里面,刚好有对sensor_active的设置:
diff --git a/drivers/input/sensors/accel/mpu6500_acc.c b/drivers/input/sensors/accel/mpu6500_acc.c
index 6fc2058e0f9f..8dea829f49cc 100644
--- a/drivers/input/sensors/accel/mpu6500_acc.c
+++ b/drivers/input/sensors/accel/mpu6500_acc.c
@@ -175,7 +175,12 @@ static int sensor_init(struct i2c_client *client)
        }-       res = sensor->ops->active(client, 0, sensor->pdata->poll_delay_ms);
+       res = sensor->ops->active(client, 1, sensor->pdata->poll_delay_ms);
        if (res) {
                dev_err(&client->dev, "%s:line=%d,error\n", __func__, __LINE__);

 

4.apk测试

 9轴对应的数据都有了。

 

参考:https://www.cnblogs.com/leptonation/p/5225889.html

https://kerndev.blog.csdn.net/article/details/103959385

posted @ 2024-04-24 12:00  M-kobe  阅读(138)  评论(0编辑  收藏  举报