嵌入式功耗问题调试日志

  1. mh公司功耗要求:整机(包括所有外设)在飞行模式灭屏下,待机电流在5ma以内  
      
    一、功耗问题一般调试办法 - 【逐个去掉】  
        1. 外接精确电源(实验室有),电脑端有一个连接电源的软件(龙旗电流检测工具),可以查看实时电流与平均电流  
        2. 切换为飞行模式 - 排查modem的影响  
            10ma 以上 -> 查看mtklog中的kernel_log看是否有休眠"suspend"  
            10ma 以下 -> 逐个去掉外设: lcm/tp/camera/fingerprint/sensor/小板(直接拔除), 看哪里漏电  
          
    二、常见外设功耗:  
            注:除了tp带手势,其他均为询问FAE得知,均未验证  
            lcm                 : uA级  
            tp                  : uA级  
            tp 带手势唤醒        : 1mA  
            camera              : uA级  
            sensor              : uA级  
            fingerprint         : uA级  
            省晶体(节省gps晶体)也会导致电流较大 - 约1mA  
            每增大1G RAM 电流会增大: 约1mA  
      
    三、如何确实中断唤醒源:  
        (1)打开irq-mt-eic.c中的EINT_DEBUG宏,重新抓取kernel log       // 实测80_c_m.git 不报错,7.0都报错  
        (2)在log中w“ake up by EINT”之后,查找EINT_STA的值  
               EINT_STA的值是中断状态寄存器,每个bit对应一个EINT channel,  
               所以EINT_STA的值就是0x1<<index(index即EINT channel)  
               eg:比如EINT_STA=0x200,对应的EINT channel就是9  
        (3)查看cust_eint.h,跟据EINT channel确定是哪个模块  
       
        至于log中“wake up by EINT (0x20)(0x4)”的0x20指的是EINT wakesrc的index,是WAKE_SRC_EINT这个宏的值  
              
          
    四、常见外设功耗不符合要求原因及解决办法:  
        lcm :  
            案例一:  lcm没有完全休眠:  
            原因: lcm驱动中使用SET_RESET_PIN(0)在休眠时对reset进行拉低,实际上LCM的reset并未拉低,拉低后又会被拉高。  
                  而很多显示屏在休眠下去时是要将LCM的reset的拉低,显示屏的待机电流才能正常的uA级别。  
            解决: 改用这种方式将reset拉低:  
                android5.1: (不支持dts)  
                    由老的 SET_RESET_PIN()  改为 lcd_rst_en()  
                    驱动中:  
                     #include <mach/mt_gpio.h>        // mt_set_gpio_mode()函数包含  
                     static void lcd_rst_en(int enabled){  
                        if(1 == enabled){  
                            mt_set_gpio_mode(GPIO_LCM_RST, GPIO_MODE_00);  
      
                            mt_set_gpio_dir(GPIO_LCM_RST, GPIO_DIR_OUT);  
                            mt_set_gpio_out(GPIO_LCM_RST, GPIO_OUT_ONE);  
                        }else{  
                            mt_set_gpio_mode(GPIO_LCM_RST, GPIO_MODE_00);  
      
                            mt_set_gpio_dir(GPIO_LCM_RST, GPIO_DIR_OUT);  
                            mt_set_gpio_out(GPIO_LCM_RST, GPIO_OUT_ZERO);  
                        }  
                    }  
                     static void lcm_init(void)  
                    {  
                        lcd_rst_en(1);//SET_RESET_PIN(1);  
                        MDELAY(2);  
                        lcd_rst_en(0);//SET_RESET_PIN(0);  
                        MDELAY(2);  
                        lcd_rst_en(1);//SET_RESET_PIN(1);  
                        MDELAY(120);  
      
                        push_table(lcm_initialization_setting, sizeof(lcm_initialization_setting) / sizeof(struct LCM_setting_table), 1);  
                    }  
                    static void lcm_suspend(void)  
                    {  
                        push_table(lcm_sleep_in_setting, sizeof(lcm_sleep_in_setting) / sizeof(struct LCM_setting_table), 1);  
                        MDELAY(10);  
                        lcd_rst_en(0);      // 新增这一句  
                    }  
                    static unsigned int lcm_compare_id(void)  
                    {  
                        ...  
                        lcd_rst_en(1);  
                        MDELAY(25);  
                        lcd_rst_en(0);  
                        MDELAY(25);  
                        lcd_rst_en(1);  
                        MDELAY(50);  
                        ...  
                        read_reg_v2(0xbf, buffer, 5);  
                        ...  
                        return (0x3350 == id)?1:0;  
                    }  
                       
                android6/7:  
                    1.修改dts: 添加reset引脚的配置,方便驱动中使用  
                        /* DISPSYS GPIO standardization */  
                        &pio {  
                            ...  
                            mtkfb_pins_lcm_reset0: lcm_rst_out0_gpio {  
                                pins_cmd_dat {  
                                    pins = <PINMUX_GPIO70__FUNC_LCM_RST>;  
                                    slew-rate = <1>;  
                                    output-low;  
                                };  
                            };  
                            mtkfb_pins_lcm_reset1: lcm_rst_out1_gpio {  
                                pins_cmd_dat {  
                                    pins = <PINMUX_GPIO70__FUNC_LCM_RST>;  
                                    slew-rate = <1>;  
                                    output-high;  
                                };  
                            };  
                            ...  
                        }  
                              
                        &mtkfb {  
                            ...  
                            pinctrl-3 = <&mtkfb_pins_lcm_reset0>;  
                            pinctrl-4 = <&mtkfb_pins_lcm_reset1>;  
                        }  
                      
                    2.驱动中: (kernel中才能用dts)  
                        #include "disp_dts_gpio.h"  // mt_lcm_rst_set_gpio()函数包含  
                        static void lcm_init(void)  
                        {  
                            mt_lcm_rst_set_gpio(1);  
                            MDELAY(10);  
                            mt_lcm_rst_set_gpio(0);  
                            MDELAY(10);  
                            mt_lcm_rst_set_gpio(1);  
                            MDELAY(200);  
      
                            push_table(lcm_initialization_setting,  
                                      sizeof(lcm_initialization_setting) /  
                                      sizeof(struct LCM_setting_table), 1);  
                        }  
                        static void lcm_suspend(void)  
                        {  
                            push_table(lcm_sleep_in_setting, sizeof(lcm_sleep_in_setting) / sizeof(struct LCM_setting_table), 1);  
                            MDELAY(10);  
                            mt_lcm_rst_set_gpio(0);  
                        }  
                        static unsigned int lcm_compare_id(void)  
                        {  
                            ...  
                            mt_lcm_rst_set_gpio(1);  
                            MDELAY(25);  
                            mt_lcm_rst_set_gpio(0);  
                            MDELAY(25);  
                            mt_lcm_rst_set_gpio(1);  
                            MDELAY(50);  
                            ...  
                            read_reg_v2(0xbf, buffer, 5);  
                            ...  
                            return (0x3350 == id)?1:0;  
                        }  
      
        tp  :  
            案例一: 固件原因  
                原因: 固件  
                解决: 安排FAE来优化固件  
                示例: v618_p300项目,tp电流为1.5mA  
                      ->FAE优化下发参数之后,约为1mA  
              
        camera:   
        案例一 : 待机电流过大(18ma) - 后副摄没有休眠 - 掉电时序  
            现象  : 整机待机电流正常(7ma),摄像头打开再关闭灭屏后整机待机电流过大(18ma)  
            平台  : androidN,MTK6737  
            排查过程: 1. 一个有后副摄,一个没有后副摄对照,发现无后副摄的机器电流正常  
                    
                  2. 引出后副摄的RST 与PDN脚,用万用表测量打开载关闭灭屏之后的电平 - 低   
                    
                  3. 对照gc0310的芯片手册 - PDN脚为高时休眠  
                       
                  4. 掉电时序中将PDN脚拉高  
                    -   mtkcam_gpio_set(pinSetIdx, CAMPDN, pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_ON]);    // 拉低 前面进行翻转  
                    +   mtkcam_gpio_set(pinSetIdx, CAMPDN, pinSet[pinSetIdx][IDX_PS_CMPDN + IDX_PS_OFF]);   // 拉高  
                    
                  5. 改掉电时序之后还是一样电流大,怀疑没跑到,修改的代码中添加log -> log没打印  
                     询问姜工后,修改alps\kernel-3.18\drivers\misc\mediatek\imgsensor\src\mt6735m\kd_sensorlist.c:  
                     在kd_MultiSensorClose()函数中,打开后副摄掉电时序:  
                       
                    -   #ifdef CONFIG_KST_DUAL_CAM_YUV0  
                    +   #if ((defined CONFIG_KST_DUAL_CAM_YUV0) || (defined CONFIG_KST_BOARD_V666))  
                      
                  6. log还是没打印,修改掉电时序中: (均打印得知:后副摄 pinSetIdx == 2)  
                    -   if((pinSetIdx == 0)&&(currSensorName && (0 == strcmp(SENSOR_DRVNAME_GC0310_MIPI_YUV, currSensorName))))  
                    +   if((pinSetIdx == 2)&&(currSensorName && (0 == strcmp(SENSOR_DRVNAME_GC0310_MIPI_YUV, currSensorName))))  
                    
        处理方案: 修改掉电时序  
      
        sensor:   
            案例一: 待机电流过大(6.6ma) - gsensor 中断脚漏电  
                原因: 原理图中gsensor的中断脚接了10k的上拉电阻,上拉到PMU1.8v 高电平, 而dws中没有配置GPIO60为中断模式,  
                处理: 1. 配置dws中的pin脚模式 与中断的触发方式  
                    dws配置pin脚:  
                            EintMode|Def.Mode   M0|M1|M2|M3|M4|M5|M6|M7|InPull En|InPull SelHigh|Def.Dir|In|Out|OutHigh|VarName1  
                -   GPIO60          0:GPIO80    1  0  0  1  1  0  1  0  1         0              OUT     0  1   0         
                +   GPIO60  1       0:GPIO80                            1         1              IN                     GPIO_GSE_1_EINT_PIN   
                  
                    dws配置EINT:  
                            EINTVar|Debounce Time(ms)|Polarity|Sensitive_Level|Debounce En    
                -   EINT60  NC      0  
                +   EINT60  GSE_1   0                   High    Level           Disable  
                      
                      2. 或者在硬件中去掉上拉电阻,也就是将gsensor的中断脚NC掉  
                        
                      ==> 配置dws后 功耗正常(小于5ma)  
                        
            案例二: 待机电流过大(8ma)去掉gsensor后5ma  
                原因: gsensor(qma6981)的第10脚只能悬空或接1.8v,而实际接到了2.8v  
                处理: 1. 查看log,休眠与唤醒函数都正常跑到了  
                      
                      2. 对比相同mtk6737 android7.0的其他项目。不同主板的gsensor 6981功耗正常。==>对比电路原理图  
                        发现qma6981的第10脚接的电压不一样,正常主板接的是1.8v,问题主板接到2.8v。  
                      
                      3. 咨询fae后得知:[此芯片的Pin10 为VDDIO 电压域1.8v,当接入2.8V电压时会产生电压差导致待机电流偏大4-5mA,且无法通过软件改善] ,第10脚只能悬空或接1.8v  
                        
                      4. 尝试将正常主板的第10脚接到2.8v,功耗就变大了3个ma(正常主板原理图上做了1.8v/2.8v兼容,将接到1.8v的电阻挪到接2.8v的位置即可)  
                        
                      ==> 硬件改版(问题主板没做1.8v/2.8v兼容) or 更换gsensor为3433(3433 芯片内部兼容1.8v/2.8v)  
                        
                      5. 也就是说3433与6981并不完全pin对pin  
                        
            案例三 : gsensor兼容(3433 & 6981)导致功耗大(70ma)  
                平台: androidN,MTK6737  
                步骤: 1. 休眠时候打log: adb shell dmesg > e:gsensor_3433_6981.log  
                        log显示由于设备(2-004c - mc3433)休眠失败,导致系统休眠失败,重新唤醒,  
                        系统一直处于: 休眠->休眠失败->唤醒 ->休眠的循环中  
                        [  207.629520]  (1)[1066:system_server]qma6981_suspend 2894 : liuzhigou 20171018 qma6981_suspend start   
                        [  207.635164]  (1)[1066:system_server]qma6981_suspend 2914 : liuzhigou 20171018 qma6981_suspend end   
                        [  207.635254]  (1)[1066:system_server]liuzhigou 20171018 mc3xxx_suspend start   
                        [  207.635291]  (1)[1066:system_server]dpm_run_callback(): i2c_device_pm_suspend+0x0/0x38 returns -22  
                        [  207.635324]  (1)[1066:system_server]PM: Device 2-004c failed to suspend: error -22  
                        [  207.635352]  (1)[1066:system_server][name:suspend&]PM: Some devices failed to suspend, or early wake event detected  
          
                      2. 在mc3433的休眠函数中,添加打印log:  
                        static int mc3xxx_suspend(struct i2c_client *client, pm_message_t msg)  
                        {  
                            struct mc3xxx_i2c_data *obj = i2c_get_clientdata(client);  
                            int err = 0;  
                            if(msg.event == PM_EVENT_SUSPEND)   {  
                                if(obj == NULL) {  
                        +               GSE_ERR("liuzhigou 20171025 %s obj == NULL\n",__FUNCTION__);  
                                        return -EINVAL;  
                                    }  
                                  
                        [  116.917907]  (0)[1150:system_server]liuzhigou 20171018 mc3xxx_suspend start   
                        [  116.917926]  (0)[1150:system_server]liuzhigou 20171018 mc3xxx_suspend msg.event == PM_EVENT_SUSPEND   
                        [  116.917943]  (0)[1150:system_server]liuzhigou 20171018 mc3xxx_suspend obj == NULL   
                        [  116.917974]  (0)[1150:system_server]dpm_run_callback(): i2c_device_pm_suspend+0x0/0x38 returns -22  
                        [  116.917996]  (0)[1150:system_server]PM: Device 2-004c failed to suspend: error -22  
                        [  116.918016]  (0)[1150:system_server]PM: Some devices failed to suspend, or early wake event detected  
                            根据log,obj为空指针,出错判断后返回错误值  
                    
                      3. 根据标志位添加出错判断,如果没加载3433就直接return 0(成功),终止3433的休眠函数  
                        static int mc3xxx_suspend(struct i2c_client *client, pm_message_t msg)  
                        {  
                            struct mc3xxx_i2c_data *obj = i2c_get_clientdata(client);  
                            int err = 0;  
                            if(msg.event == PM_EVENT_SUSPEND)   {  
                                if(obj == NULL) {  
                            +       if (MC3XXX_INIT_FAIL == s_nInitFlag){  
                            +           GSE_ERR("liuzhigou 20171025 %s obj == NULL MC3XXX_INIT_FAIL == s_nInitFlag \n",__FUNCTION__);  
                            +           return 0;  
                            +       }  
                            +       else{  
                            +           GSE_ERR("liuzhigou 20171025 %s obj == NULL MC3XXX_INIT_FAIL != s_nInitFlag \n",__FUNCTION__);  
                                        return -EINVAL;  
                                    }  
                                }  
                                  
        总结  :   此log为正常状态: 0x4000为pmu中断  
                    [  147.732936] -(0)[1066:system_server][name:mt_spm_internal&][SPM] wake up byEINT, timer_out = 18724959, r13 = 0x10001000, debug_flag = 0x9f  
                    [  147.732936] -(0)[1066:system_server][name:mt_spm_internal&][SPM] r12 = 0x20, raw_sta = 0x20, idle_sta = 0x9fa, event_reg = 0x90100000, isr = 0x0  
                    [  147.732936] -(0)[1066:system_server][name:mt_spm_sleep&][SPM] suspend dormant state = 0, md32_flag = 0x0, md32_flag2 = 0  
                    [  147.732936] -(0)[1066:system_server][name:mt_spm_sleep&][SPM] log_wakesta_index = 5  
                    [  147.732936] -(0)[1066:system_server][name:irq_mt_eic&]EINT_STA:  
                    [  147.732936] -(0)[1066:system_server][name:irq_mt_eic&]EINT Module - index:192,EINT_STA = 0x4000  
                    [  147.732936] -(0)[1066:system_server][name:irq_mt_eic&]EINT 206 is pending  
                    [  147.732936] -(0)[1066:system_server][name:irq_mt_eic&]  
                    [  147.732988] -(0)[1066:system_server][name:ccci&][ccci1/mcd]Resume cldma pdn register ...11  
                    [  147.733070] -(0)[1066:system_server][name:irq_mt_eic&]EINT Module - expires:4294952066, jiffies:4294952065, deb_in_jiffies:1,   
                    [  147.733091] -(0)[1066:system_server][name:irq_mt_eic&]deb:1000, in mt_eint_set_timer_event  
                    [  147.733270]  (0)[1066:system_server][name:cpu&]Enabling non-boot CPUs ...  
                    [  147.733571] -(1)[0:swapper/1]CPU1: Booted secondary processor  
              
        fingerprint:  
            案例一: 指纹功耗约为2mA,不符合要求  
                原因: 没有休眠,指纹的休眠需要hal层下发休眠命令  
                处理: 添加相关hal层代码  
                实例: v618_p300项目(去掉上层mmi修改的测功耗版本),指纹电流为2mA  
                      ->由于指纹没有收到休眠命令导致,添加上层mmi修改之后正常  
                    
        充电IC:  
            案例一: 每隔30s左右会有一次大电流脉冲,导致平均功耗十几个毫安  
                现象: 30s一次大电流脉冲  
                原因: 1. mtklog中显示wake up by PCM_TIMER提示,但还是定位不到问题,只好git回退,  
                      2. 通过git版本回退发现:对alps\kernel-3.18\drivers\power\mediatek\battery_meter.c中的获取电池电压  
                      函数battery_meter_get_battery_voltage()做了【读取20次,求平均值的操作】  
                      导致,30s一次大电流脉冲  
                处理: 去掉读取20次操作,还原为mtk默认即只读一次  
                存疑: 添加log得知,本函数每隔10s被调用一次,为何脉冲是是30s一次?  
                log:  [cat /proc/kmsg | grep "20170713"]  
                     [489.332438] 20170713 battery_meter_get_battery_voltage()  
                     [489.503921] 20170713 battery_meter_get_battery_voltage()  
                     [499.331495] 20170713 battery_meter_get_battery_voltage()  
                     [499.503337] 20170713 battery_meter_get_battery_voltage()  
                     [509.331463] 20170713 battery_meter_get_battery_voltage()  
                     [509.502923] 20170713 battery_meter_get_battery_voltage()  
              
        主板功耗:  
            案例一: 双卡实网待机电流过大(标准需要小于12ma,实测约15ma)  
            原因: 谷歌服务  
            处理: 1. 测试的时候关闭:这种方式只能【关闭部分】谷歌服务  
                    setting -> apps -> google play servicer 点击disable关闭  
                      
                    这样测出来的电流是15ma  
                      
                  2. 编译的时候在update\alps\system_conf.sh 【彻底关闭】(微掌客制化)  
                    BUILD_GMS=no  
                      
                    这样测出来的电流是11.5ma(合格)  
              
            注意: 1. 双卡待机,数据只能开一卡,联通卡(CU)网络待机功耗较大,以移动卡(CMCC)网络待机为准  
                  2. 切换:setting -> sim cards ->cellular data 点击选择sim卡 :CMCC 移动 / CU 联通  
                  3. 打开数据:下滑菜单 打开 :CMCC/CU -> cellular data 打开  
              
              


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值