sensor调试总结

架构介绍

高通平台目前使用的是SSC和SEE架构。SSC架构用于一些老平台,如MSM8953、SDM660、QCM2150等,新平台使用的都是SEE架构。从下图来看,新架构更简洁,SEE充当了core层的重要角色,负责传送request,接收event。

SEE架构优点:

统一的事件驱动框架,适用于驱动程序和算法;

在SEE上运行的任何算法都必须签名;

简单且对称的API(传感器和服务);

简单的接口来初始化/启用/激活/停用/采样传感器;

驱动程序对如何处理客户端请求有改进的控制;

可以轻松扩展以添加新的/自定义驱动程序功能;

直接在驱动程序API中更好地进行测试;

支持异步COM总线传输;

sensor移植

驱动的集成及配置

本文主要介绍在SEE架构下点亮一个sensor,下面以添加地磁AK09918C为例进行详细介绍。

如果BP侧ADSP下已有驱动,则只需要修改AP侧对应的json文件中的配置即可;如果没有相关曲中,就需要手动添加相关驱动和编译选项,再修改AP侧配置。

sensor驱动的添加路径为:

adsp_proc/ssc/sensors/ak0991x

sensor型号的配置路径为:

adsp_proc/ssc/chipset/nicobar/por.py

把要添加的sensor型号添加到系统原生的代码中,型号是驱动代码下面build/目录,有一个sns_ak0991x.scons,这个就是驱动编译相关文件,取前面sns_ak0991x就是sensor型号,其他sensor同理。型号添加如下:

--- a/adsp_proc/ssc/chipset/nicobar/por.py
+++ b/adsp_proc/ssc/chipset/nicobar/por.py
@@ -31,7 +31,7 @@ def generate(env):
-    include_sensor_vendor_libs.extend(['lsm6dso', 'sns_stk3x1x', 'sns_mmc36xx', 'sns_stk3x3x', 'sns_icm4x6xx'])
+    include_sensor_vendor_libs.extend(['lsm6dso', 'sns_stk3x1x', 'sns_mmc36xx', 'sns_stk3x3x', 'sns_icm4x6xx', 'sns_ak0991x'])
     env.Replace(SSC_INCLUDE_SENS_VEND_LIBS=include_sensor_vendor_libs)
     env.Replace(SSC_EXCLUDE_LIBS=exclude_libs)

以上这些修改部分完成之后,就可以进行编译验证,想要确定编译是否生效:

驱动build目录下会生成sensor_img文件,内含lib库文件以及sensor驱动对应的.o文件;

查看sns_static_sensors.c文件中是否有添加的sensor型号,如果有说明参加编译了,文件路径如下:

adsp_proc/ssc/framework/src/sns_static_sensors.c

sensor驱动部分最终打包到NON_HLOS.bin镜像中,验证时可单独替换。

adb root

adb reboot bootloader

fastboot flash modem NON_HLOS.bin

json文件的修改及配置

sensor的json文件包含相关属性配置,具体添加路径为:

vendor/qcom/proprietary/sensors-see/registry/config/trinket/

路径由vendor/qcom/proprietary/sensors-see/registry/Android.mk中的TARGET_BOARD_PLATFORM决定。

sensor的json文件一般厂商会提供,需根据原理图确认相关参数取值,主要参数说明如下:

配置项

作用

备注

hw_platform

平台名称

cat /sys/devices/soc0/hw_platform

soc_id

平台ID

cat /sys/devices/soc0/soc_id

is_dri

数据上报方式

0:Polling  轮询方式

1:DRI  中断方式

hw_id

Sensor ID

区分同型号的多个sensor

res_idx

分辨率

选择默认分辨率和范围

sync_stream

同步数据流

是否支持同步数据流,比如S4S

bus_type

连接方式

0:I2C

1:SPI

2:UART

3:I3C

bus_instance

总线控制器

连接总线对应的QPU端口

slave_config

I2C地址

具体Sensor的I2C地址

min_bus_speed_khz

总线时钟频率

最小总线时钟频率

max_bus_speed_khz

总线时钟频率

最大总线时钟频率

dri_irq_num

中断号

具体sensor使用的GPIO号

irq_pull_type

中断上/下拉方式

0:No Pull

1:Pull Down

2:Keeper

3:Pull Up

irq_is_chip_pin

是否用作中断

1:MSM GPIO用作中断

irq_trigger_type

中断触发方式

0:Rising edge

1:Falling edge

2:Rising & Falling edge

3:Level triggered: High

4:Level triggered: Low

num_rail

power rails个数

Sensor的供电LDO个数(VDD和VDDIO)

rail_on_state

供电状态

1:Low Power mode

2:Normal Power mode

vddio_rail

电源轨

/pmic/client/sensor_vddio(默认)

json文件可以直接push到设备内部,然后重启,实现快速更新,具体步骤如下:

adb shell “rm -rf /vendor/etc/sensors/config/nicobar_ak991x_0.json” //删除之前的注册表文件

adb shell “rm -rf /mnt/vendor/persist/sensors/registry/registry/*” //删除已生成的sensor注册文件

adb push nicobar_ak991x_0.json /vendor/etc/sensors/config //push新的json文件到设备

ls –l /mnt/vendor/persist/sensors/registry/registry //重启设备后查看更新后的json文件是否注册成功

供电配置介绍

sensor通常有两路供电1.8V和2.8V,1.8V给I2C总线供电,2.8V给器件供电。

LDO供电

LDO供电配置路径:

adsp_proc/core/settings/pmic/pm/config/adsp/nicobar/pm_config_pam.c

如图,需要根据实际的LDO编号进行增加和修改,此时先查看原生代码配置,在使用过程中主要依赖于PMIC_NPA_CLIENT_NODE_SENSOR_VDDIO所在的数组,若实际设计与原生不一致,就需要修改或增减。

修改sensor供电为长供电,以L12A为例,修改如下:

--- a/rpm_proc/core/pmic/pm/config/sdm_nicobar/pm_config_target.c
+++ b/rpm_proc/core/pmic/pm/config/sdm_nicobar/pm_config_target.c
@@ -57,7 +57,7 @@ pm_rpm_ldo_rail_info_type ldo_rail_a[] =
-    {0,  24, 0, PM_ACCESS_ALLOWED,   PM_NONE,      PM_NPA_VREG_MODE_LPM, PM_NPA_BYPASS_DISALLOWED, PM_DROOP_DETECT_DIS,   1800, 1996, 0, PM_SETTLING_ERR_EN,   PM_SETTLING_EN,  0}, // LDO12 LDO510_LVP300  camera
+    {0,  24, 0, PM_ACCESS_ALLOWED,   PM_ALWAYS_ON, PM_NPA_VREG_MODE_LPM, PM_NPA_BYPASS_DISALLOWED, PM_DROOP_DETECT_DIS,   1800, 1996, 0, PM_SETTLING_ERR_EN,   PM_SETTLING_EN,  0}, // LDO12 LDO510_LVP300  camera

使用外挂的PM8008芯片的LDO6供电,修改如下:

--- a/kernel/msm-4.14/arch/arm64/boot/dts/qcom/sc138-evk/trinket-camera-sensor-idp.dtsi
+++ b/kernel/msm-4.14/arch/arm64/boot/dts/qcom/sc138-evk/trinket-camera-sensor-idp.dtsi
@@ -271,6 +271,7 @@
 		cam_vio-supply = <&L12A>;
 		cam_vana-supply = <&L4P>;
 		cam_vdig-supply = <&L1P>;
+		light_sensor_vdd = <&L6P>;
 		cam_clk-supply = <&camss_top_gdsc>;
--- a/kernel/msm-4.14/arch/arm64/boot/dts/qcom/sc138-evk/trinket.dtsi
+++ b/kernel/msm-4.14/arch/arm64/boot/dts/qcom/sc138-evk/trinket.dtsi
@@ -3141,6 +3141,9 @@
 &L6P {
 	regulator-min-microvolt = <3000000>;
 	regulator-max-microvolt = <3000000>;
+	regulator-always-on;
+        regulator-state-mem {
+            regulator-off-in-suspend;  };
 };
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c
@@ -1426,6 +1426,7 @@ static int32_t msm_sensor_driver_parse(struct msm_sensor_ctrl_t *s_ctrl)
 static int32_t msm_sensor_driver_platform_probe(struct platform_device *pdev)
 {
 	int32_t rc = 0;
+	struct regulator *sensor_vdd;
 	struct msm_sensor_ctrl_t *s_ctrl = NULL;
 
 	/* Create sensor control structure */
@@ -1463,6 +1464,14 @@ static int32_t msm_sensor_driver_platform_probe(struct platform_device *pdev)
 
 	/* Fill device in power info */
 	s_ctrl->sensordata->power_info.dev = &pdev->dev;
+
+	sensor_vdd = regulator_get(&pdev->dev, "light_sensor_vdd");
+	if(!sensor_vdd){
+		pr_err("sensor_vdd get failed\n");
+	}
+	regulator_set_voltage(sensor_vdd, 3000000, 3000000);
+	regulator_enable(sensor_vdd);
+
 	return rc;

gpio供电

sensor的供电如果由普通的gpio控制,可以在abl阶段把gpio拉高即可,修改如下:

--- a/bootable/bootloader/edk2/QcomModulePkg/Application/LinuxLoader/LinuxLoader.inf
+++ b/bootable/bootloader/edk2/QcomModulePkg/Application/LinuxLoader/LinuxLoader.inf
@@ -110,6 +110,7 @@
 	gEfiResetReasonProtocolGuid
 	gQcomRngProtocolGuid
 	gQcomDisplayUtilsProtocolGuid
+	gEfiTLMMProtocolGuid
 
--- a/bootable/bootloader/edk2/QcomModulePkg/Library/BootLib/UpdateCmdLine.c
+++ b/bootable/bootloader/edk2/QcomModulePkg/Library/BootLib/UpdateCmdLine.c
@@ -40,6 +40,7 @@
#include <Protocol/Print2.h>
+#include <Protocol/EFITlmm.h>
 
 #include "AutoGen.h"
 #include <DeviceInfo.h>
@@ -81,6 +82,39 @@ STATIC CONST CHAR8 *AndroidBootFstabSuffix =
 STATIC CHAR8 *FstabSuffixEmmc = "emmc";
 STATIC CHAR8 *FstabSuffixDefault = "default";
 
+#define SEN_VDD_2V8	27
+
+EFI_STATUS
+SetGpioStateProtocol (UINT32 GpioNum, UINT32 GpioState)
+{
+	EFI_STATUS Status = EFI_SUCCESS;
+	EFI_TLMM_PROTOCOL *TLMMProtocol = NULL;
+
+	Status = gBS->LocateProtocol (&gEfiTLMMProtocolGuid, NULL, (VOID **)&TLMMProtocol);
+	if (Status == EFI_NOT_FOUND) {
+		DEBUG ((EFI_D_VERBOSE, "TLMM Protocol is not available.\n"));
+		return EFI_SUCCESS;
+	} else if (EFI_ERROR (Status)) {
+		DEBUG ((EFI_D_ERROR, "Error finding TLMM protocol: %r\n", Status));
+		return Status;
+	}
+
+	if(TLMMProtocol){
+		Status = TLMMProtocol ->ConfigGpio( (UINT32) EFI_GPIO_CFG(GpioNum,0, GPIO_OUTPUT,GPIO_NO_PULL,GPIO_2MA),TLMM_GPIO_ENABLE);
+		if (Status != EFI_SUCCESS)
+		{
+			DEBUG ((EFI_D_ERROR, "ConfigGpio: Unable to Configure MSM GPIO %d!!\n", GpioNum));
+		}
+
+		if (EFI_SUCCESS != TLMMProtocol->GpioOut((UINT32)EFI_GPIO_CFG(GpioNum, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA), GpioState?GPIO_HIGH_VALUE:GPIO_LOW_VALUE))
+			DEBUG((EFI_D_ERROR, "pull up gpio SEN_VDD_2V8 Failed!\n"));
+		else
+			DEBUG((EFI_D_ERROR, "pull up gpio SEN_VDD_2V8 successfully!\n"));
+	}
+
+	return Status;
+}
+
 EFI_STATUS
 TargetPauseForBatteryCharge (BOOLEAN *BatteryStatus)
 {
@@ -583,6 +617,12 @@ UpdateCmdLine (CONST CHAR8 *CmdLine,
   UINT32 LEVerityCmdLineLen = 0;
   CHAR8 RootDevStr[BOOT_DEV_NAME_SIZE_MAX];
 
+  Status = SetGpioStateProtocol(SEN_VDD_2V8, 1);
+  if (Status != EFI_SUCCESS) {
+    DEBUG ((EFI_D_ERROR, "Error SetGpioStateProtocol num: %x\n", Status));
+    return Status;
+  }
+
   Status = BoardSerialNum (StrSerialNum, sizeof (StrSerialNum));
--- a/bootable/bootloader/edk2/QcomModulePkg/QcomModulePkg.dec
+++ b/bootable/bootloader/edk2/QcomModulePkg/QcomModulePkg.dec
@@ -95,6 +95,7 @@
   gEfiPlatformInfoProtocolGuid =        { 0x157a5c45, 0x21b2, 0x43c5, { 0xba, 0x7c, 0x82, 0x2f, 0xee, 0x5f, 0xe5, 0x99 } }
   # Sdcc Card Info
   gEfiMemCardInfoProtocolGuid =        { 0x85c1f7d2, 0xbce6, 0x4f31, { 0x8f, 0x4d, 0xd3, 0x7e, 0x03, 0xd0, 0x5e, 0xaa } }
+  gEfiTLMMProtocolGuid =                { 0xad9aec18, 0x7bf0, 0x4809, { 0x9e, 0x96, 0x30, 0x12, 0x30, 0x9f, 0x3d, 0xf7 } }

调试方法

QXDM简易操作

用QXDM接收sensor模块log:

View—Common—Filtered View:新增log查看窗口;

Tools—CFG File Generator:对新增窗口进行log信息筛选过滤;

设置Filtered View用于接收sensor log,Tools->CFG File Generator,如下图;

log抓取

sensor的调试原理是利用QXDM发送命令使adsp子系统重启,再用QXDM来接收过滤出sensor从初始化、注册到正常工作的全部log,具体操作步骤如下:

修改adsp子系统重启等级,需在cmd窗口执行,指令如下:

echo related > /sys/bus/msm_subsys/devices/subsys1/restart_level //修改adsp子系统restart_level

参考上面步骤使用QXDM抓log,usb连接上设备后,在QXDM中发送command,使adsp子系统重启,指令如下:

send_data 75 37 03 48 00

以上操作就可以使QXDM过滤出SNS从初始化到启动的全部log,使用CTRL+A、Alt+M打开搜索框,可搜索所加驱动信息。

调试成功判断

指令dumpsys sensorservice

可以检测sensor hal层中哪些sensor已经init成功。

QsensorTest APP获取

Android系统本身有内置QsensorTest 这一APP,通过此APP可以获取到可用sensor,能看到调试对应的sensor型号,即表明调试成功,点击对应型号可以让sensor开始运行,点击图中的“X”停止运行。

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
华为海思sensor调试是指对华为海思公司的传感器进行调试工作。传感器是一种能够感知和检测环境中各种物理量和信号的装置,它可以将感知到的信息转化为可识别和可利用的信号,为后续的数据处理和分析提供基础。 在进行华为海思sensor调试时,首先需要对传感器进行连接和配置。连接是指将传感器与调试工具或设备连接起来,以确保传感器能够与外部系统进行数据传输。配置则是指根据实际需求对传感器的参数进行设置,如采样率、灵敏度等,以使传感器能够按照预期工作。 接下来,进行传感器的校准工作。校准是通过对传感器进行精确的调整和校对,以消除误差和偏差,提高测量的准确性和精度。校准过程中需要使用标准参考信号或物理量进行比对和调整,以使传感器输出的测量值与实际值尽可能接近。 调试过程中还需要进行传感器的功能测试。功能测试是指对传感器的各项功能进行验证,如是否能够正常感知和检测目标物体或环境、是否能够正确输出测量值等。可以通过模拟测试场景或实际应用场景对传感器的功能进行测试,以确认其是否符合设计要求。 最后,对传感器进行性能评估。性能评估是通过对传感器进行多个指标的测试和分析,评估其在实际使用中的性能表现,如响应时间、信噪比、动态范围等。根据评估结果可以判断传感器是否能够满足实际应用需求,以及是否需要进一步优化和改进。 综上所述,华为海思sensor调试是一个对传感器进行连接、配置、校准、功能测试和性能评估的过程,旨在确保传感器能够准确、可靠地感知环境并输出准确的测量值,以满足实际应用的需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值