问题重现:
在设备中设置alarm闹铃,然后选择震动和闹铃和屏幕最低亮度。确保进入vddmin后,当闹铃响的时候,会crash
OCP:
过电流保护OCP(英文名称:over current protection)
预定当被测电流增大超过允许值时执行相应保护动作(如使断路器跳闸)的一种措施保护。
log等级:
cat /proc/sys/kernel/printk
4 4 1 7
第一个参数表示console的loglevel,第二个参数表示prink的loglevel(只是表示不加参数,printk的默认loglevel),如果设置console的loglevel为8,则printk都会打印在console,否则0/1/2/3打在console。
echo 8 > /proc/sys/kernel/printk设置console的loglevel
分析:
在每次crash后,重启后抓取log,查看关机原因:
[ 0.722600] qcom,qpnp-power-on qpnp-power-on-2: PMIC@SID0 Power-on reason: Triggered from KPD (power key press) and 'cold' boot
[ 0.722638] qcom,qpnp-power-on qpnp-power-on-2: PMIC@SID0: Power-off reason: Triggered from GP_FAULT0
从中看到Power-off reason: Triggered from GP_FAULT0
GP_FAULT0这个错误代表OCP错误
注意要抓取整份的log,如果不能用串口抓取整份log,可以用以下命令抓取尽量多的log:
adb wait-for-device & adb root & adb shell dmesg > ./dmesg3.txt —快速抓取log
这个时候就需要分析,在crash之前是什么原因导致的。一般OCP的问题,可以追踪crash之前最近的一次LDO使用情况,这样可以快速定位问题:
需要在kernel/drivers/regulator/core.c下加log,查看最后一个LDO的使用情况:
在这个函数里面一些函数的调用情况:
int regulator_enable(struct regulator *regulator) -----> Request that the regulator be enabled with the regulator output at the predefined voltage or current value.
每个LDO开启的时候,都会调用regulator_enable然后调用_regulator_enable(rdev);
然后在调用static void drms_uA_update(struct regulator_dev *rdev)
在static void drms_uA_update(struct regulator_dev *rdev)函数中
/* Calculate the new optimum regulator operating mode based on the new total
* consumer load. All locks held by caller */
static void drms_uA_update(struct regulator_dev *rdev)
{
struct regulator *sibling;
int current_uA = 0, output_uV, input_uV, err;
unsigned int regulator_curr_mode, mode;
err = regulator_check_drms(rdev);
/* get output voltage */
output_uV = _regulator_get_voltage(rdev); //得到需要的输出电压
printk("xhlin %s: output voltage: %d\n",__func__,output_uV);
/* get input voltage */
input_uV = 0; //得到输入电压,不明白什么是输入电压,回来要看?
if (rdev->supply)input_uV = regulator_get_voltage(rdev->supply);
if (input_uV <= 0)input_uV = rdev->constraints->input_uV;
if (input_uV <= 0)return;
printk("xhlin %s: input voltage: %d\n",__func__,input_uV);
/* calc total requested load */------------------计算每个LDO所需要的全部电流,就是把每个consumer的电流全部加起来,注意这些电流都软件写死的,不是瞬时电流
list_for_each_entry(sibling, &rdev->consumer_list, list)
{
printk("xhlin %s: rdev name %s, current_uA %d, sib_ua_load %d\n",__func__, rdev->desc->name, current_uA, sibling->uA_load);
current_uA += sibling->uA_load;
}
/* now get the optimum mode for our new total regulator load */
mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, output_uV, current_uA);--------------------------根据以上的数据确定mode,注意有LPM和NPM两种模式
/* check the new mode is allowed */
err = regulator_mode_constrain(rdev, &mode);
//重要,这个就是加log的重点:得到OPC之前的LDO是什么状态,是哪一个LDO
printk("xhlin %s: rdev name %s, current_uA %d, mode %d\n",__func__, rdev->desc->name, current_uA, mode);
/* return if the same mode is requested */
if (rdev->desc->ops->get_mode) {
regulator_curr_mode = rdev->desc->ops->get_mode(rdev);
printk("xhlin %s: -------regulator_curr_mode = %d-----------1--------------\n",__func__,regulator_curr_mode);
if (regulator_curr_mode == mode)
{
printk("xhlin %s: -------regulator_curr_mode = %d-----------2--------------\n",__func__,regulator_curr_mode);
return;}
} else
return;
if (err == 0)
rdev->desc->ops->set_mode(rdev, mode);
}
当出现Suspending console(s) (use no_console_suspend to debug)后,表明已经进入vdd min模式了
以下在响铃之后,出现的一段log,之后就crash
注意要加上echo 8 > /proc/sys/kernel/printk ,显示全部的log打印
[ 110.800881] CPU1: Booted secondary processor
[ 110.810993] xhlin drms_uA_update: output voltage: 1800000
[ 110.815515] xhlin drms_uA_update: input voltage: 1800000
[ 110.820766] xhlin drms_uA_update: rdev name pm660_l11, current_uA 0, sib_ua_load 5000 ---- 第一个consumer为5ma,后面会分析它从哪里来
[ 110.828744] xhlin drms_uA_update: rdev name pm660_l11, current_uA 5000, sib_ua_load 100 ---- 第二个consumer为0.1ma
[ 110.836586] xhlin drms_uA_update: rdev name pm660_l11, current_uA 5100, sib_ua_load 0 ---- 第三个consumer为0ma,说明不需要用到电流,跟硬件对应吗?
[ 110.844596] xhlin drms_uA_update: rdev name pm660_l11, current_uA 5100, mode 4,err=0 ---- 进入的mode 为4 ,这个应该对应LPM,低功耗模式?
[ 110.852124] xhlin drms_uA_update: -------regulator_curr_mode = 4-----------1--------------
[ 110.860441] xhlin drms_uA_update: -------regulator_curr_mode = 4-----------2--------------
根据最后出现的LDO为:pm660_l11,可以判断LDO11引起了OCP问题。
通过检查硬件原理图,发现LDO11被以下三个部件使用:SPKR,SNS和DISP,分别为音频的喇叭,sensor和显示部分,因为闹铃只用到喇叭和显示器,所以sensor的电流应该为0
通过查找dts发现:
msm_digital_codec: msm-dig-codec@771c000 {
compatible = "qcom,msm-digital-codec";
reg = <0x0771c000 0x0>;
cdc-vdd-digital-supply = <&pm660_l11>;
qcom,cdc-vdd-digital-voltage = <1800000 1800000>;
qcom,cdc-vdd-digital-current = <5000>;
qcom,cdc-on-demand-supplies = "cdc-vdd-digital";
qcom,subsys-name = "modem";
};
其中qcom,cdc-vdd-digital-current = <5000>;这就有问题了,分析如下:
每个LDO在enable的时候系统会给他们选择mode,有LPM,和NPM模式,分别代表低功耗和正常模式
当每个LDO所有consumer加起来的电流<LPM规定的某个值,即为LPM模式,否则为NPM模式。 --------------- 注意电流值是dts里面配置的,而不是实际电流
当处于LPM模式下的设备,此时的实际电流大于 这个LDO所有consumer加起来的电流(加起来的电流是设备树的电流,而不是实际电流),或者大于LPM模式下的阈值电流 ------------------- 就会发生OCP
如果consumer的电流>LPM规定的某个值,就会进入NPM模式,这个是正常模式,就不会产生OCP,
所以现在需要增加所有consumer的电流和,这样才符合实际电流,---------- 大于LPM模式的阈值 --------------- 不会进入LPM模式 ----------------- 电流高一点的时候不会产生OCP现象
所以把音频的喇叭电流增加,通过log可以发现主要consumer来源于此:
qcom,cdc-vdd-digital-current = <5000>; -------------- <10000>
更改后的log如下:
[ 108.034455] xhlin drms_uA_update: output voltage: 1800000
[ 108.038821] xhlin drms_uA_update: input voltage: 1800000
[ 108.044198] xhlin drms_uA_update: rdev name pm660_l11, current_uA 0, sib_ua_load 10000
[ 108.052081] xhlin drms_uA_update: rdev name pm660_l11, current_uA 10000, sib_ua_load 100
[ 108.060132] xhlin drms_uA_update: rdev name pm660_l11, current_uA 10100, sib_ua_load 0
[ 108.068005] xhlin drms_uA_update: rdev name pm660_l11, current_uA 10100, mode 2,err=0
[ 108.075861] xhlin drms_uA_update: -------regulator_curr_mode = 2-----------1--------------
[ 108.080439] CPU2: Booted secondary processor
[ 108.088345] xhlin drms_uA_update: -------regulator_curr_mode = 2-----------2--------------
从中可以看到有两个地方更改了,
第一current_uA 10000,依据:qcom,cdc-vdd-digital-current = <5000>; -------------- <10000>
第二mode 2,依据:进入了NPM模式
问题:LPM模式的阈值电流在哪里设置,一共有多少模式,在npm模式下实际电流大于consumer的电流会发生ocp吗
在平常模式下:
[ 295.169003] xhlin drms_uA_update: rdev name pm660_l11, current_uA 105000, mode 2 -----
现在不妨换换思路,瞧点文学东西
如果你喜欢,聊历史,思哲学,品诗集,赏国学。
那就关注公众号:二校五叔
这个是博主的文学公众号啦