刚入行驱动时最先接触调试的外设模块便是sensor,一直都是零零散散的记录,这次终于下定决心对自己所学做一个系统的总结。
sensor作为一款常用的外设,虽不起眼但是很多功能确实离不开它。比如我们手机上常用的步数记录,就要用到重力加速度传感器和陀螺仪,手机亮度自动调节离不开光感传感器,其它的诸如红外传感器、温湿度传感器、气压传感器等等在各种场景下发挥着不可或缺的作用。单论调试来说,基础的调试移植并不复杂,新人也很容易上手;如果要去调试效果就需要研读代码,对代码流程有一定的了解;再深一层,想弄清楚sensor的架构各部分代码是如何跑起来的,就需要花时间阅读相关文档,同时结合代码去逐步理解架构。不过专门深入搞sensor的不多,毕竟还没指甲盖大个料,几块钱,没钱途呀。调调屏去哪儿都能干,调调camera调的好进个大厂实现财富自由不是梦。
言归正传,下面就来介绍高通平台sensor相关的一些基础知识。
架构篇
目前市面常见平台模块使用的是SSC和SEE架构。前者用于一些老的平台诸如MSM8953、SDM660、QCM2150等等,新一点平台使用的都是SEE架构。直观来看,会觉得SEE架构使用起来更方便,尤其是移植的时候不用去改很多东西,因为他把SSC架构里的很多东西都封装了起来你可以直接使用,而不必再去逐个修改。就好比造一辆车,SSC架构需要从最小的零件开始拼起,而SEE架构则相当于把各个部件都组装好,你直接装配就行。当然方便的同时也有隐患,就是出问题的时候你更难排查,毕竟不是你自己从最底层一点点拼出来的, ·出了问题你当然不知道去哪儿找原因啦。从两者架构图中就能看出一二。
左边是SSC右边是SEE,可以明显的看到SEE架构要简洁了许多。当然光看这框图可没用,想要真正理解两种架构之间的具体区别,那得花时间打磨咯,咱目前还达不到这个水平哈哈哈。
移植篇
移植算是sensor调试最基本的工作了,即如何让sensor跑起来。这里主要介绍SEE架构的移植调试。
SEE架构移植
SEE架构下点亮一个sensor驱动,如果BP侧ADSP/SLPI下面已有驱动,则只需要修改AP侧对应的json文件中的配置即可;如果没有相关驱动,就需要手动添加相关驱动和编译选项,再修改AP侧配置。
这里以6490平台为例,后续有些平台位置换到了slpi里,但是换汤不换药。
(1)sensor驱动代码相关路径,根据平台不同有所差异。
adsp_proc\ssc_drivers
(2)sensor编译选项相关代码路径
adsp_proc/ssc/chipset/kodiak/por.py
(3)AP侧json文件路径
vendor\qcom\proprietary\sensors-see\registry\config\lahaina
(4)AP测hal层相关代码路径
vendor\qcom\proprietary\sensors-see\sensors-hal-2.0\sensors
依据高通文档说明,描述如何移植添加一个新的sensor驱动,以添加一个重力加速度传感器BMI160为例,并添加修改对应json文件。直接上代码
添加编译选项,让新加的sensor驱动参与编译
把我们要添加的sensor型号添加到系统原生的代码里,不知道型号怎么写可以参考BMI160驱动代码下面build/目录,有一个sns_bmi16x.scons,这个就是驱动的编译相关文件,取前面sns_bmi16x就是sensor型号,其他sensor同理。有些童鞋可能有疑问了,不是添加bmi160么,怎么又变成bmi16x了?啊哈,盲生你发现了华点。这是因为sensor同一系列有时候会有好多型号,这些配置基本都是类似的,因此厂商在集成驱动代码的时候就把它们集成在一套里面啦。
if 'SSC_TARGET_X86' not in env['CPPDEFINES']:
#POR sensors list
include_sensor_vendor_libs.extend(['lsm6dst', #ACCEL/GYRO/MD/TEMP
'sns_ak0991x', #MAGNETOMETER
'sns_ltr556',
'sns_bmi16x',
'sns_tmd3702', #ALS/PROX
'sns_lps22hx', #PRESSURE
'sns_sx932x', #CAPACITIVE
'sns_bu52053nvx']) #HALL
添加驱动代码
sensor驱动代码一般由对应厂商提供,把驱动代码放在adsp_proc\ssc_drivers目录下即可。
修改I2C协议相关
该平台sensor使用的是i2c协议,需要在对应文件下修改协议为i2c。i2c对应的gpio为gpio161和gpio162,gpio161为数据lane,gpio162为时钟lane。从下图中看到两个gpio对应QUP_IO_0和QUP_IO_1,因此在对应文件中修改se0和se1协议为i2c。(实际使用时根据需求修改为i2c、i3c、spi)
adsp_proc/core/settings/buses/qup_fw/config/kodiak/fw_devcfg.c
// #elif defined BUS_PRESIL_CONFIG //same as MTP
// RUMI // offset, protocol, mode, load_fw, dfs_mode
se_cfg se0_cfg_rumi = { 0x80000, SE_PROTOCOL_I2C, GSI, TRUE, TRUE };
se_cfg se1_cfg_rumi = { 0x84000, SE_PROTOCOL_I2C, GSI, TRUE, TRUE };
se_cfg se2_cfg_rumi = { 0x88000, SE_PROTOCOL_I2C, GSI, TRUE, TRUE };
//se_cfg se3_cfg_rumi = { 0x8C000, SE_PROTOCOL_I2C, GSI, TRUE, TRUE };
//se_cfg se4_cfg_rumi = { 0x90000, SE_PROTOCOL_I2C, GSI, TRUE, TRUE };
//se_cfg se5_cfg_rumi = { 0x94000, SE_PROTOCOL_UART, FIFO, FALSE, FALSE };
se_cfg se6_cfg_rumi = { 0x98000, SE_PROTOCOL_UART, FIFO, FALSE,FALSE };
//se_cfg se7_cfg_rumi = { 0x9C000, SE_PROTOCOL_UART, FIFO, FALSE,FALSE };
// #else
// MTP /// offset, protocol, mode, load_fw, dfs_mode
se_cfg se0_cfg = { 0x80000, SE_PROTOCOL_I2C, GSI, TRUE, TRUE };
se_cfg se1_cfg = { 0x84000, SE_PROTOCOL_I2C, GSI, TRUE, TRUE };
se_cfg se2_cfg = { 0x88000, SE_PROTOCOL_I2C, GSI, TRUE, TRUE };
se_cfg se3_cfg = { 0x8C000, SE_PROTOCOL_I2C, GSI, FALSE, TRUE };
se_cfg se4_cfg = { 0x90000, SE_PROTOCOL_SPI, GSI, TRUE, TRUE };
se_cfg se5_cfg = { 0x94000, SE_PROTOCOL_UART, FIFO, TRUE,FALSE };
se_cfg se6_cfg = { 0x98000, SE_PROTOCOL_UART, FIFO, TRUE,FALSE };
//se_cfg se7_cfg = { 0x9C000, SE_PROTOCOL_UART, FIFO, TRUE,FALSE };
TZ中释放gpio权限
总线gpio相关的权限,i2c、spi、uart等都在TZ中管理。查看平台总线gpio对应哪一组se可以参考高通文档QCM6490/QCS6490 Linux Android Peripheral (UART, SPI, I2C, I3C) Technical Overview
每个平台都有类似的对应文档,可以在高通文档网站获取。(注意:修改总线权限相关容易导致死机,请谨慎修改)
本平台总线gpio对应关系表,图中LPI_QUP是专门给sensor用的,因为sensor需要用到LPIgpio,这里不做详细讲述,后面会说到。可以看到我们用的是se1,文件内默认的协议即为i2c,因此不需要做修改。
trustzone_images/core/settings/buses/qup_accesscontrol/qupv3/config/kodiak/QUPAC_Access.c
const uint32 ssc_qupv3_perms_size_default = sizeof(ssc_qupv3_perms_default)/sizeof(ssc_qupv3_perms_default[0]);
const QUPv3_se_security_permissions_type qupv3_perms_rumi[] =
{
/* PeriphID, ProtocolID, Mode, NsOwner, bAllowFifo, bLoad, bModExcl */
{ QUPV3_0_SE0, QUPV3_PROTOCOL_I3C, QUPV3_MODE_FIFO, AC_HLOS, TRUE, TRUE, FALSE }, // camera
{ QUPV3_0_SE1, QUPV3_PROTOCOL_I2C, QUPV3_MODE_FIFO, AC_HLOS, TRUE, TRUE, FALSE }, // APPS I2C 给sensor i2c使用
{ QUPV3_0_SE2, QUPV3_PROTOCOL_I2C, QUPV3_MODE_FIFO, AC_HLOS, TRUE, TRUE, FALSE }, // I2C
{ QUPV3_0_SE3, QUPV3_PROTOCOL_SPI, QUPV3_MODE_FIFO, AC_HLOS, TRUE, TRUE, FALSE }, // Broadcast SPI
/*QUPV3_0_SE4*/
{ QUPV3_0_SE5, QUPV3_PROTOCOL_UART_2W, QUPV3_MODE_FIFO, AC_HLOS, TRUE, FALSE, FALSE }, // Debug UART
/* QUPV3_0_SE6, QUPV3_PROTOCOL_SPI */
{ QUPV3_0_SE7, QUPV3_PROTOCOL_UART_4W, QUPV3_MODE_FIFO, AC_MSS_MSA, TRUE, FALSE, FALSE }, // UART (MODEM standalone)
{ QUPV3_1_SE0, QUPV3_PROTOCOL_SPI, QUPV3_MODE_FIFO, AC_HLOS, TRUE, TRUE, FALSE },
trustzone_images/core/settings/buses/qup_accesscontrol/qupv3/config/kodiak/QUPAC_Access_RFCOMM.c
const uint32 ssc_qupv3_perms_size_default = sizeof(ssc_qupv3_perms_default)/sizeof(ssc_qupv3_perms_default[0]);
const QUPv3_se_security_permissions_type qupv3_perms_rumi[] =
{
/* PeriphID, ProtocolID, Mode, NsOwner, bAllowFifo, bLoad, bModExcl */
{ QUPV3_0_SE0, QUPV3_PROTOCOL_I3C, QUPV3_MODE_FIFO, AC_HLOS, TRUE, TRUE, FALSE }, // camera
{ QUPV3_0_SE1, QUPV3_PROTOCOL_I2C, QUPV3_MODE_FIFO, AC_HLOS, TRUE, TRUE, FALSE }, // APPS I2C
{ QUPV3_0_SE2, QUPV3_PROTOCOL_I2C, QUPV3_MODE_FIFO, AC_HLOS, TRUE, TRUE, FALSE }, // I2C
{ QUPV3_0_SE3, QUPV3_PROTOCOL_SPI, QUPV3_MODE_FIFO, AC_HLOS, TRUE, TRUE, FALSE }, // Broadcast SPI
/*QUPV3_0_SE4*/
{ QUPV3_0_SE5, QUPV3_PROTOCOL_UART_2W, QUPV3_MODE_FIFO, AC_HLOS, TRUE, FALSE, FALSE }, // Debug UART
以上这些修改部分完成之后,就可以进行编译验证,想要确定编译是否生效可以查看
adsp_proc/ssc/framework/build/sensor_img/qdsp6/kodiak.adsp.prod/sns_static_sensors.c
adsp_proc/ssc/framework/build/sensor_img/qdsp6/kodiak.adsp.prod/sns_static_drivers.c
看这两个文件内是否有你添加的sensor型号,如果有就是参与编译了,如果没有,说明你添加的驱动没有参与编译需要重新检查。sensor驱动部分最终打包到NON_HLOS.bin镜像中,TZ修改打包到devcfg.mbn中,验证时可以单独替换比较方便。
adb root
adb reboot bootloader
fastboot flash modem NON_HLOS.bin
fastboot flash devcfg devcfg.mbn
AP部分文件修改
vendor/qcom/proprietary/sensors-see/registry/config/lahaina/lahaina_qrd_bmi160_0.json
vendor/qcom/proprietary/sensors-see/sensors-hal-2.0/sensors/orientation.cpp
该目录下原本并没有bmi160对应的json文件,需要我们自己添加,可以复制高通原生重力加速度传感器的json文件来用,另目录下有很多同料但是名称不同的json文件,可以根据平台设备树来确认我们需要的,比如调试项目使用的QRD,那么我们就选带qrd的文件。hal层的修改是为了把g-sensor的数据通过算法转换为方向数据。
相关属性含义在文件内注释
{
"config":
{
"hw_platform": ["QRD"], // cat /sys/devices/soc0/hw_platform获取
"soc_id": ["497"] //cat /sys/devices/soc0/soc_id 获取
},
"bmi160_0":{
"owner": "sns_bmi160",
".accel":{
"owner": "sns_bmi160",
".config":{
"owner": "sns_bmi160",
"is_dri":{ "type": "int", "ver": "0",
"data": "1"
},//配置中断模式或者轮训模式(“0”轮训模式,“1”中断模式)
"hw_id":{ "type": "int", "ver": "0",
"data": "0"
},//用来区分同一硬件多个传感器
"res_idx":{ "type": "int", "ver": "0",
"data": "2"
},
"sync_stream":{ "type": "int", "ver": "0",
"data": "0"
}
}
},
".gyro":{
"owner": "sns_bmi160",
".config":{
"owner": "sns_bmi160",
"is_dri":{ "type": "int", "ver": "0",
"data": "1"
},
"hw_id":{ "type": "int", "ver": "0",
"data": "0"
},
"res_idx":{ "type": "int", "ver": "0",
"data": "4"
},
"sync_stream":{ "type": "int", "ver": "0",
"data": "0"
}
}
},
".md":{
"owner": "sns_bmi160",
".config":{
"owner": "sns_bmi160",
"is_dri":{ "type": "int", "ver": "0",
"data": "1"
},
"hw_id":{ "type": "int", "ver": "0",
"data": "0"
},
"res_idx":{ "type": "int", "ver": "0",
"data": "0"
},
"sync_stream":{ "type": "int", "ver": "0",
"data": "0"
}
}
},
".temp":{
"owner": "sns_bmi160",
".config":{
"owner": "sns_bmi160",
"is_dri":{ "type": "int", "ver": "0",
"data": "0"
},
"hw_id":{ "type": "int", "ver": "0",
"data": "0"
},
"res_idx":{ "type": "int", "ver": "0",
"data": "2"
},
"sync_stream":{ "type": "int", "ver": "0",
"data": "0"
}
}
}
},
"bmi160_0_platform":{
"owner": "sns_bmi160",
".config":{
"owner": "sns_bmi160",
"bus_type":{ "type": "int", "ver": "0",
"data": "0"
},//I2C 写 0、 SPI 写 1、 I3C 写 3
"bus_instance":{ "type": "int", "ver": "0",
"data": "2"
},//bus_instance: = QUP 数 + 1
"slave_config":{ "type": "int", "ver": "0",
"data": "104"
},//I2C 地址,参考规格书
"min_bus_speed_khz":{ "type": "int", "ver": "0",
"data": "400"
},//最小 COM 总线时钟速度,默认配置 400khz
"max_bus_speed_khz":{ "type": "int", "ver": "0",
"data": "400"
},//最大 COM 总线时钟速度,默认配置 400khz
"reg_addr_type":{ "type": "int", "ver": "0",
"data": "0"
},//寄存器地址类型( 寄存器地址位数,“ 0” 8 bit “ 1” 16 bit “ 2” 32bit)
"dri_irq_num":{ "type": "int", "ver": "0",
"data": "102"
},//中断引脚
"irq_pull_type":{ "type": "int", "ver": "0",
"data": "2"
},//配置中断引脚内部电平类型
"irq_is_chip_pin":{ "type": "int", "ver": "0",
"data": "1"
},//配置 MSM_GPIO 由于中断模式
"irq_drive_strength":{ "type": "int", "ver": "0",
"data": "0"
},//配置 MSM_GPIO 由于中断模式
"irq_trigger_type":{ "type": "int", "ver": "0",
"data": "0"
},//中断触发类型,这里我们配置为低电平触发
"num_rail":{ "type": "int", "ver": "0",
"data": "2"
},//中断触发类型,这里我们配置为低电平触发
"rail_on_state":{ "type": "int", "ver": "0",
"data": "2"
},//低功耗供电模式 LPM 还是常规供电模式 NPM
"vddio_rail":{ "type": "str", "ver": "0",
"data": "/pmic/client/sensor_vddio"
},
"vdd_rail":{ "type": "str", "ver": "0",
"data": "/pmic/client/sensor_vdd"
},
"rigid_body_type":{ "type": "int", "ver": "0",
"data": "0"
}
},
".orient":{
"owner": "sns_bmi160",
"x":{ "type": "str", "ver": "0",
"data": "+y"
},
"y":{ "type": "str", "ver": "0",
"data": "-x"
},
"z":{ "type": "str", "ver": "0",
"data": "+z"
}
},
".gyro":{
"owner": "sns_bmi160",
".fac_cal":{
"owner": "sns_bmi160",
".corr_mat":{
"owner": "sns_bmi160",
"0_0":{ "type": "flt", "ver": "0",
"data": "1.0"
},
"0_1":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"0_2":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"1_0":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"1_1":{ "type": "flt", "ver": "0",
"data": "1.0"
},
"1_2":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"2_0":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"2_1":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"2_2":{ "type": "flt", "ver": "0",
"data": "1.0"
}
},
".bias":{
"owner": "sns_bmi160",
"x":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"y":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"z":{ "type": "flt", "ver": "0",
"data": "0.0"
}
}
}
},
".accel":{
"owner": "sns_bmi160",
".fac_cal":{
"owner": "sns_bmi160",
".corr_mat":{
"owner": "sns_bmi160",
"0_0":{ "type": "flt", "ver": "0",
"data": "1.0"
},
"0_1":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"0_2":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"1_0":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"1_1":{ "type": "flt", "ver": "0",
"data": "1.0"
},
"1_2":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"2_0":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"2_1":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"2_2":{ "type": "flt", "ver": "0",
"data": "1.0"
}
},
".bias":{
"owner": "sns_bmi160",
"x":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"y":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"z":{ "type": "flt", "ver": "0",
"data": "0.0"
}
}
}
},
".temp":{
"owner": "sns_bmi160",
".fac_cal":
{
"owner": "sns_bmi160",
".scale":{
"owner": "sns_bmi160",
"x":{ "type": "flt", "ver": "0",
"data": "1.0"
}
},
".bias":{
"owner": "sns_bmi160",
"x":{ "type": "flt", "ver": "0",
"data": "0.0"
}
}
}
},
".md":{
"owner": "sns_bmi160",
".config":{
"owner": "sns_bmi160",
"thresh":{ "type": "flt", "ver": "0",
"data": "0.156"
},
"disable":{ "type": "int", "ver": "0",
"data": "0"
},
"win":{ "type": "flt", "ver": "0",
"data": "0.02"
}
}
},
".placement":{
"owner": "sns_bmi160",
"0":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"1":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"2":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"3":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"4":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"5":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"6":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"7":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"8":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"9":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"10":{ "type": "flt", "ver": "0",
"data": "0.0"
},
"11":{ "type": "flt", "ver": "0",
"data": "0.0"
}
}
}
}
根据硬件设计配置完成后,可以直接把json文件push到设备的/vendor/etc/sensors/config/下面验证。
adb root
adb remount
adb push xxx vendor/etc/sensors/config/
adb shell
rm -rf mnt/vendor/persist/sensors/registry/registry/* (这步操作是删除由json文件生成的配置文件防止干扰验证)
adb reboot
修改都替换到设备之后,可以装个apk看下效果。
手头没有调试设备的话可以用自己的手机试一下哦,打开手机设置--关于手机--点击7此版本号,提示您已进入开发者模式--返回上一级,进入系统--点击开发人员选项--把调试下面相关的权限打开,然后就可以连上PC上的adb操作啦,如下就已经把app装到手机里啦。
(Ps:对普通用户来说开发者选项也没有什么用处啦,可能就一个阳光下阅读能力提升有点用,这个功能打开的话在太阳下面显示状况会好不少,但是因为太耗电了,所以一般都藏起来啦)
apk打开之后就是这个样子,这些也是一般移动设备常用的传感器类型。
Debug篇
获取ADSP端sensor初始化log
因为sensor在开机过程中加载的时候,diag口还未识别因此无法抓到初始化log,因此可以重启ADSP子系统让sensor重新加载一编来抓取log。子系统要通过cat节点确认是否是adsp,这里只是示例。这也是最常用的debug手段,通过初始化log追踪定位问题发生位置。
adb root
adb shell "cat /sys/bus/msm_subsys/devices/subsys<N>/name"
adb shell "echo 'related' > /sys/bus/msm_subsys/devices/subsys<N>/restart_level
然后再QXDM工具上输入send_data 75 37 03 48 00
ADSP |
send_data 75 37 03 48 00 |
SLPI |
send_data 75 37 03 64 00 |
工具里可以把不需要的信息列隐藏掉,这样log起来更方便一点。
调试问题篇
这部分主要介绍一些移植调试过程中可能遇到的一些问题以及应对方法
编译环境
该问题在sm4350平台调试中遇到,调试过程中一直出现G-sensor导致死机问题,尝试过替换同平台项目的persist镜像,json文件,生成文件,甚至升级基线都试过还是无法解决死机问题,最后高通方面建议我们查看下是否是编译环境有问题。通过查看4350平台sensor文档,编译ADSP之前需要更新nanopb工具包作为基础,编译服务器需要ubuntu版本16以上,更新之后重新编译ADSP不再死机,最后解决方案是把nanopb压缩工具包一并提交上去,并修改编译脚本在编译ADSP之前先升级工具。
下载后放入指定位置,执行指令打印如图信息表示成功,即可继续编译ADSP
python ssc_api/build/config_nanopb_dependency.py -f nanopb-0.3.9.5-linux-x86
2. 供电问题
在移植初期常常会遇到供电问题,通常sensor都是由两路供电1.8V和2.8V,如果用万用表量不到供电,可以尝试下先把电常供。
查找给sensor供电的LDO代码路径
adsp_proc\core\settings\pmic\pm\config\adsp\kodiak\pm_config_pam.c
修改sensor供电为常供代码路径(或者在rpm下)
aop_proc\core\pmic\pm\config\kodiak\pm_config_target.c
{.AccessAllowed = PM_ACCESS_ALLOWED, .RsrcCategory = VRM_RSRC_REGULATOR, .AlwaysOn = PM_ON, .MinMode = PM_NPM_MODE_VAL, .SafetyHR = 32, .MinVoltage = 1800, .MaxVoltage = 2000, .EnableFixedTime = 300, .EnableStepperWarmUpTime = 0, .VoltFixedUpTime = 0, .VoltFixedDownTime = 0, .VoltStepperExtraUpTime = 0, .VoltStepperExtraDownTime = 0, .VoltDischargeTime = 0, .ModeFixedTime = 20, .VregReadyEn = PM_SETTLING_EN, .VregReadyErrEn = PM_SETTLING_ERR_EN, .VregWdogTimer = VRM_8X_SETTLING_TIMER, .AopHandling = 0, .VoltSeqType = VRM_GENERIC_SEQ, .EnableSeqType = VRM_GENERIC_SEQ, .ModeSeqType = VRM_GENERIC_SEQ, .DrvOwnMask = PM_DRV_AUD|PM_DRV_HLOS, .Reserved = 0}, //LDO8 Sensors
其中.AlwaysOn = PM_ON,属性就表示该LDO长供,如果改为PM_OFF就是关闭掉长供,其它的属性尽量不要驱动,比如电压上下限.MinVoltage = 1800, .MaxVoltage = 2000,有时候修改会导致死机。
长供电可以解决大部分供电问题,但是如果长供电之后还是不行,就要看下原理图是不是该LDO还受其他地方的控制,列举两种可能的情况:
供电脚由gpio控制
如果是普通的gpio可以在lk阶段把gpio拉高即可正常供电,如果是在pmi芯片上,就比较复杂一些,这两种状况下如何控制gpio会在后面其他帖子专门列出。
LDO供电默认没有打开
这种情况比较少见,只在660平台上某项目见到过,默认LDO未启用,需要在xbl中打开
a/boot_images/QcomPkg/Library/PmicLib/target/sdm660_pm660_pm660l/system/src/pm_sbl_boot_oem.c
+++ b/boot_images/QcomPkg/Library/PmicLib/target/sdm660_pm660_pm660l/system/src/pm_sbl_boot_oem.c
@@ -214,6 +214,8 @@ pm_driver_post_init (void)
//SW WA to Enable LDO2B (SDCARD LDO), This should go in OTP.
err_flag |= pm_ldo_sw_enable(PM_DEVICE_1,PM_LDO_2,PM_ON);
+ //SW WA to Enable LDO3B (SENSOR LDO), This should go in OTP.
+ err_flag |= pm_ldo_sw_enable(PM_DEVICE_1,PM_LDO_3,PM_ON);
//Configure MISC.VSET_LB to stable solution(0x02)
/* This should have been handled in SBL config, but SBL config has the best power optimised solution as default,
3.中断脚选择不合适
此问题出现于某平台光距传感器上。供电与I2c都正常,apk显示sensor也是点亮的,但是手覆盖上去亮度值和距离值都不会变化。查阅PIN定义表格并询问高通,高通告知是中断脚选用有问题,sensor的中断脚需要是LPI gpio,也就是带有唤醒功能,普通的gpio就会出现功能异常的现象,这种问题较少出现,出现一般就需要硬件改版。文章来源:https://www.toymoban.com/news/detail-408417.html
小结
sensor作为驱动调试中常见的外设之一,看起来没有其它外设那么复杂,但是个中流程等等还是值得我们去研读代码、深度探究。后面调试过程中遇到的问题和心得也会继续汇总分享出来,文章写得有问题的地方还望大家多多指正,欢迎一起讨论~文章来源地址https://www.toymoban.com/news/detail-408417.html
到了这里,关于高通平台sensor学习的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!