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 打開
嵌入式功耗問題調試日誌
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.