rockchip sensors da215s适配

RK3568  da215s适配 ,增加一个新的 sensor 驱动需做一些适配工作。
SOC:RK3568
KERNEL:Android 12
二、 Android sensors 架构
三、 Sensors hal kernel driver 的通信框图
四、 Rockchip sensors hal 介绍
代码路径: hardware/rockchip/sensor/st ,支持最新的 SENSORS_DEVICE_API
_VERSION_1_3 android sensors hal API 接口。其实现的接口包括:
get_sensors_list - 返回所有传感器的列表
activate - 启动或停止传感器
batch - 设置传感器的参数,如采样率和最大报告延迟
setDelay - 仅用于 1.0 版本的 HAL ,设置指定传感器的采样率
flush - 刷写指定传感器的 FIFO ,并在完成后报告刷写完成事件
poll - 返回可用的传感器事件
其中 flush 接口并没有真正实现,因为要具体到硬件的 fifo 支持,由于我们支持的
sensor 型 号 多 , 无 法 做 到 统 一 接 口 实 现 , 所 以 这 里 只 是 绕 过 , 直 接 返 回
META_DATA_FLUSH_COMPLETE 类型数据
五、 Rockchip sensors kernel driver 介绍
代码路径: kernel/drivers/input/sensors ,其中 sensor-dev.c 是核心代码,整合
了不同类型的 sensor ,包括 accel, gyro, lsensor, psensor, compass
六、新增一个 sensor 驱动流程
这里以增加一个最常用的 gsensor 为例,其他类型的 sensor 类似。
Android hal 不需要任何修改, hal 的是按 +-4G Gsensor 量程, adc 14bit 来配
置的,也就是 4 G 对应的数值是 16384*4 ;所以 driver 层增加 gsensor 驱动,上报数值需
要根据量程和 adc 的精度来适配
具体步骤如下,以 da215s acc 为例:
sensor-dev.h  中添加 sensor_id,其中gsensor_da215s_id 的 ”gs_da215s ”字段与 dts 中的 compatible
字段对应。
kernel-5.10\include\linux\sensor-dev.h
6.2 增加 gsensor chip 驱动
driver/input/sensors/accel/目录下增加相应驱动
实现 gsensor_mpu6500_ops 实例:
struct sensor_operate gsensor_da215s_ops= {
.name = "gs_da215s",            //与 gsensor_da215s_id 中定义的名称一致
.type = SENSOR_TYPE_ACCEL,      //sensor 类型是 gsensor
.id_i2c = ACCEL_ID_DA215S,      // 定 义 在 include/linux/sensor-dev.h 中
.read_reg = ACC_X_LSB,          //读取 gsensor 数据的起始 寄存器地址
.read_len = 6,                  //需要读取的 gsensor 数据的字节数
.id_reg = DA215S_CHIP_ID,       //芯片唯一 ID 寄存器
.id_data = DA215S_CHIPID_DATA,  //芯片 ID 值
.precision = DA215S_PRECISION,  //采样 gsensor 数据的adc 位数
.ctrl_reg = DA215S_MODE_BW,     //用于使能 gsensor 的寄 存器地址
.int_status_reg = INT_MAP1,     //中断状态寄存器地址
.range =  {-DA215S_DATA_RANGE, DA215S_DATA_RANGE}, //量程,这里表示上报的量 程为+-1G
.trig =  IRQF_TRIGGER_LOW | IRQF_ONESHOT,  // 中断类型
.active = sensor_active,        //用于开关 gsensor
.init = sensor_init,            //用于初始化 gsensor
.report = sensor_report_value,  //用于上报gsensor数据
};

static const struct i2c_device_id gsensor_da215s_id[] = {
    {"gs_da215s", ACCEL_ID_DA215S},
    {}
};
  //注册 sensor 驱动到 sensor-dev.c  devid 为gsensor_da215s_id地址
static const struct i2c_device_id gsensor_da215s_id[] = {
	{"gs_da215s", ACCEL_ID_DA215S},
	{}
};

static int gsensor_da215s_probe(struct i2c_client *client, const struct i2c_device_id *devid) 
{
    //注册 sensor 驱动到 sensor-dev.c  devid 为gsensor_da215s_id地址

	return sensor_register_device(client, NULL, devid, &gsensor_da215s_ops);
}

static int gsensor_da215s_remove(struct i2c_client *client)
{
	return sensor_unregister_device(client, NULL, &gsensor_da215s_ops);
}

//i2c_driver
static struct i2c_driver gsensor_da215s_driver = {
	.probe = gsensor_da215s_probe,
	.remove = gsensor_da215s_remove,
	.shutdown = sensor_shutdown,
	.id_table = gsensor_da215s_id,
	.driver = {
		.name = "gsensor_da215s",
	#ifdef CONFIG_PM
		.pm = &sensor_pm_ops,
	#endif
	},
};

i2C内核驱动加载:
module_i2c_driver(gsensor_da215s_driver);

6.3 修改 gsensor range 和上报数据转化
不同厂家的 gsensor 在量程和精度上都会有差异,为了兼容不同厂家的 gsensor 芯片,
同时做到不修改 android hal 层代码,只修改驱动,来达到简化客户开发的目的,我们必
须把不同量程,不同精度的 gsensor 转换成统一标准的数据上报给 hal 层代码。
上节提到, HAL 层是以量程为 +-4G adc 14bit 的标准来上报的 gsensor 数据,以
此标准不同的 gsensor 需要做适配。举例如下:
1 )da215s+- 4G 14bit adc
da215s的 adc 位数是 14bit 的,初始化的时候设置的量程是 +-4G ,那么寄存器读
出来的数值范围为:+-16384*4 ,并且与上层 hal 层匹配,所以只要把寄存器读出来的值直
接上报即可;

#define DA215S_PRECISION    14
#define DA215S_DATA_RANGE    (16384*4)

static struct sensor_operate gsensor_da215s_ops = {
    .name        = "gs_da215s",
    .type        = SENSOR_TYPE_ACCEL,
    .id_i2c        = ACCEL_ID_DA215S,
    .read_reg    = ACC_X_LSB,
    .read_len    = 6,
    .id_reg        = DA215S_CHIP_ID,
    .id_data    = DA215S_CHIPID_DATA,
    .precision    = DA215S_PRECISION,
    .ctrl_reg    = DA215S_MODE_BW,
    .int_status_reg    = INT_MAP1,
    .range          = {-DA215S_DATA_RANGE, DA215S_DATA_RANGE},
    .trig        = IRQF_TRIGGER_LOW | IRQF_ONESHOT,
    .active        = sensor_active,
    .init        = sensor_init,
    .report        = sensor_report_value,
    .suspend        = sensor_suspend,
    .resume         = sensor_resume,
};

2 )如果 gsensor 的量程和 adc 精度不是 +-2G 16bit 的话,则需要做相应的转化,
假设量程为 +-XG adc Ybit 的,其转化关系如下:
#define XXX_RANGE  16384*X
#define XXX_PRECISION Y
#define XXX_BOUNDARY
(0x1 << (XXX_PRECISION - 1))
#define XXX_GRAVITY_STEP (XXX_RANGE / XXX_BOUNDARY)
struct sensor_operate gsensor_xxx_ops = {
.name = "xxx_acc",
.type = SENSOR_TYPE_ACCEL,
.id_i2c = ACCEL_ID_XXX,
.read_reg = XXX_ACCEL_XOUT_H,
.read_len = 6,
.id_reg = XXX_WHOAMI,
.id_data = XXX_DEVICE_ID,
.precision = Y,
.ctrl_reg = XXX_PWR_MGMT_2,
.int_status_reg = XXX_INT_STATUS,
.range = {-16384*X, +16384*X},
.trig = (IRQF_TRIGGER_LOW |
IRQF_ONESHOT),
.active = sensor_active,
.init = sensor_init,
.report = sensor_report_value,
};
上报值转化:
report_data = read_data* XXX_GRAVITY_STEP; //read_data 为实际寄存器
读出来的值, report_data 为转换后可以上报给 hal 层的值
6.4 修改 gsensor layout 方向
      Android 系统对坐标轴的定义如下:
Sensor chip 的坐标系定义:
每一颗 sensor 都有自己的坐标系定义,所以需要根据 layout 方向,把 sensor 的坐
标系转换成 android 设备的坐标系,这个可以通过一个矩阵来做转换;
如下矩阵表示:
X = x*0 + y*1 + z*0 = y
Y = x*1 + y*0 + z*0 = x
Z = x*0 + y*0 + z*-1 = -z
Sensor-dev.c 定义了 layout 值,对应不同的矩阵,具体可以查看 sensor-dev.c
码查询,所以,适配方向可以通过修改 dts 里面的 layout 值来选择对应的转换矩阵,达到
方向的变化,以适配 android 的要求。
6.5 dts 中其他值的意义
	gs_da215s: gs_da215s@26 {
        status = "okay"; 
        compatible = "gs_da215s";// 与 sensor-dev.c 中的sensor_id 定义匹配
        reg = <0x26>;//i2c 地址
        irq-gpio = <&gpio1 RK_PA4 IRQ_TYPE_EDGE_RISING>;//中断脚,中断类型
        irq_enable = <0>;//是否使用中断模式,如果要过cts 
		                 // 或者 vts 建议使用轮询,sensor-dev.c 
		                 //的轮询模式已经可以满足 cts 测试要求,如果
                          //使用中断模式,需要 gsensor chip driver 做好采样率的配置;
        poll_delay_ms = <30>;//轮询间隔,最新代码这个值没有意义
        type = <SENSOR_TYPE_ACCEL>;//传感器类型,不能搞错
        layout = <4>;
	};
6.6 Android 中的 sensor 相关宏配置
BoardConfig.mk 中:
# Sensors
BOARD_SENSOR_ST := true //采用 RK 的 sensors Hal,也就是本文介绍的
BOARD_SENSOR_MPU_PAD := false //仅适用 MPU6500、mpu6050 等芯片
支持哪些类型的 sensor,如果没有,要配置成 false,否则 vts 和 cts 测试会失败:
BOARD_GRAVITY_SENSOR_SUPPORT := true
BOARD_COMPASS_SENSOR_SUPPORT := false
BOARD_GYROSCOPE_SENSOR_SUPPORT := false
BOARD_PROXIMITY_SENSOR_SUPPORT := false
BOARD_LIGHT_SENSOR_SUPPORT := true
BOARD_PRESSURE_SENSOR_SUPPORT := false
BOARD_TEMPERATURE_SENSOR_SUPPORT := false
七、 Gsensor gyro 的校准
Gsensor gyro 的校准可通过命令行方式, pcba 测试的时候也可以做校准,具体查
pcba 的配置。
命令行校准方法:保持机器水平静止放置,输入以下命令校准:
Gsensor: echo 1 > /sys/class/sensor_class/accel_calibration
GYRO : echo 1 > /sys/class/sensor_class/gyro_calibration
查看校准值:
cat /sys/class/sensor_class/accel_calibration
如果无法查看校准值,则说明校准失败,可以打印 kernel log 确定失败原因。
校准成功后,校准的值会保存到 nand emmc vendor storage 里面,不会被擦
除,开机自动生效
八、 Sensor 常见问题分析
这里以 gsensor 为例进行介绍,其他类型 sensor 可参考这里。
8.1 Gsensor 功能无法使用
8.1.1 getevent 查看 gsensor 无数据上报
排查思路:
1 )确认驱动是否注册上,可以通过 getevent 查看是否有名为 gsensor input 设备;
没有的话就要看为何没注册上,有可能是 dts 配置问题,驱动问题, i2c 同时失败,
chip id 不匹配等等可能的原因,查看 kernel log ,具体问题具体分析;如果有注
册上,往下。
2 )确认 android 层相关宏是否打开;
3 )确认 hal 层代码是否正常运行;开机打印 logcat ,搜索 sensor 字段查看相关 log
8.1.2 数据值不对
Getevent 有数据上报,屏幕不旋转或者旋转无规律;
除可通过 sensor apk 查看数值是否正确外,还可以通过命令的方式查看 android
上报的 gsensor 数据是否正确:
setprop sensor.debug.level 2
手动灭屏休眠,再唤醒后命令生效,通过 logcat –s SensorsHal 可以查看到 hal 上报
gsensor 数值;
静止水平放置时,理论正确的数值应该是有个轴的值为 +9.8 或者 -9.8 ,另外两个轴的
值为 0
如果数值不对,请确认上面章节介绍的数据上报转换是否正确。
8.2 方向不对
方向不对的话,通过修改 dts layout 值.
目前 RK sensor 驱动,采用轮询的方法,基本可以满足 android 采样率的要求,所
以如果不知道如何动态配置采样率的话,建议采用轮询方法,同时芯片初始化的时候就把采
样率配置成高采样率, 200Hz 就可以;另外, Sensor 芯片驱动中最好不要对数据做过滤,
如果有,可以去掉数据过滤直接上报再测试看看;还有一种情况是芯片本身的采样率实在上
不去,比较 low 的芯片;只能通过软件来绕,当 android 要求的采样率大于 sensor 的采
样率,意味着存在多次读取的数值一样的情况,同样数值在通过 input 上报的时候,会被
框架层丢弃,这样就达不到 android 的测试要求,此时我们可以人为修改数值,通过软件
骗过框架,如下:
/*
 *input dev will ignore report data if data value is the same with 
last_value,
 *sample rate will not enough by this way, so just avoid this case
 */
 if ((sensor->axis.x == axis.x) && (sensor->axis.y == axis.y) && 
(sensor->axis.z == axis.z)) {
 if (flag) {
 flag = 0;
 axis.x += 1;
 axis.y += 1;
 axis.z += 1;
 } else {
 flag = 1;
 axis.x -= 1;
 axis.y -= 1;
 axis.z -= 1;
 }
 }

  • 14
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hmbbPdx_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值