Android 亮屏速度分析

640?wx_fmt=png


640?wx_fmt=jpeg

640?wx_fmt=png

前面聊的

最近在调试项目的亮屏速度,我们希望在按下power键后到亮屏这个时间能达到500MS以内,在Rockchip 3399和3288上面的时间都不能达到要求,因此引发了一系列的调试之路。

计算按下power键到亮屏的时间

Android 唤醒时间统计
刚开始的时候,我只在android阶段统计时间,也能看到时间的差异,但是不是最准确的,我统计的时间日志如下

01-18 09:13:40.992 683 772 D SurfaceControlExcessive delay in setPowerMode(): 743ms
01-18 09:13:45.304 683 772 D SurfaceControlExcessive delay in setPowerMode(): 757ms
01-18 09:13:49.559 683 772 D SurfaceControlExcessive delay in setPowerMode(): 725ms
01-18 09:18:27.461 683 772 D SurfaceControlExcessive delay in setPowerMode(): 741ms
01-18 09:18:32.766 683 772 D SurfaceControlExcessive delay in setPowerMode(): 743ms
01-18 09:18:35.861 683 772 D SurfaceControlExcessive delay in setPowerMode(): 745ms
01-18 09:18:38.345 683 772 D SurfaceControlExcessive delay in setPowerMode(): 733ms

Kernel从Power到亮屏的时间统计
后来同事中的精英古总在他的代码上加入了从按下Power键到亮屏的时间,直接通过printk打印,代码如下

diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
old mode 100644
new mode 100755
index 17c3b94..2b39662
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -504,6 +504,7 @@ static int panel_simple_enable(struct drm_panel *panel)
        }

        p->enabled = true;
+       printk("%s exit\n", __func__);

        return 0;
 }
diff --git a/drivers/input/keyboard/rk_keys.c b/drivers/input/keyboard/rk_keys.c
old mode 100644
new mode 100755
index fed5ced..537b599
--- a/drivers/input/keyboard/rk_keys.c
+++ b/drivers/input/keyboard/rk_keys.c
@@ -134,6 +134,10 @@ static void keys_timer(unsigned long _data)
                key_dbg(pdata, "%skey[%s]: report event[%d] state[%d]\n",
                        button->type == TYPE_ADC ? "adc" : "gpio",
                        button->desc, button->code, button->state);
+               if(strcmp(button->desc, "power") == 0)
+               printk("%skey[%s]: report event[%d] state[%d]\n",
+                       button->type == TYPE_ADC ? "adc" : "gpio",
+                       button->desc, button->code, button->state);
                input_event(input, EV_KEY, button->code, button->state);
                input_sync(input);
        }

统计每个驱动的resume函数调用时间

上面的时间对我们调试非常有用,然后就需要细分到每个驱动的resume函数执行的时间,用的方法是我之前写过的,大概统计了下TP,LCD,sensor的resume时间,发现TP和LCD占用的时间非常多,然后跟同事一起看了下,同事把TP resume里面的代码用工作队列实现后速度明显有了提升。
然后有很长一段时间不知道干嘛,想打印其他每个驱动的resume时间,一直没找到方法,后面看到一个代码,非常有用。
kernel/drivers/base/power/main.c

static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)                                                       
{                
    ktime_t calltime;
    u64 usecs64;
    int usecs;

    calltime = ktime_get();
    usecs64 = ktime_to_ns(ktime_sub(calltime, starttime));
    do_div(usecs64, NSEC_PER_USEC);
    usecs = usecs64;
    if (usecs == 0)
        usecs = 1
    pr_info("PM: %s%s%s of devices complete after %ld.%03ld msecs\n",
        info ?: "", info ? " " : "", pm_verb(state.event),
        usecs / USEC_PER_MSEC, usecs % USEC_PER_MSEC);
}   

这个函数用来打印resume的函数消耗的时间,但是如何去触发打印这个函数呢?

  • 一定保证设备进入深度睡眠,串口也进入深度睡眠,没有任何打印后。

  • 执行以下命令

echo N > /sys/module/printk/parameters/console_suspend
//使控制台在suspend最后才关闭,这样可以打印出休眠过程完整信息
echo 1 > /sys/power/pm_print_times
//使能调试变量

打印的LOG类似下面的

[ 37.031413] bcmsdh_sdmmc_resume Exit
[ 37.082174] PMresume of devices complete after 78.589 msecs
[ 37.085277] [BT_RFKILL]: ** disable irq
[ 37.087645] Restarting tasks ... 

修改Lcd配置减小resume时间

古总在调试过程中展现了非常厉害的功底,第一步就是修改了LCD的参数,让亮屏时间加快。修改如下

--- a/arch/arm/boot/dts/rk3288-pad.dts
+++ b/arch/arm/boot/dts/rk3288-pad.dts
@@ -169,10 +169,10 @@
                dsi,lanes = <4>;

                prepare-delay-ms = <20>;
-               init-delay-ms = <20>;
-               enable-delay-ms = <100>;
-               disable-delay-ms = <20>;
-               unprepare-delay-ms = <20>;
+               //init-delay-ms = <20>;
+               enable-delay-ms = <1>;
+               disable-delay-ms = <1>;
+               unprepare-delay-ms = <1>;
                panel-init-sequence = [
                        15 32 02 8F A5
                        15 01 02 83 00

修改DRM 超时时间减小唤醒时间

这是最关键的,DRM框架非常复杂,RK也是从开源的DRM移植过来使用,在DRM部分有个时间超时导致问题,最终跟RK拿到最新的patch让唤醒时间直接加速500MS.
我们在日志下发现问题,并给询问了RK,最终发现这部分代码没有更新到最新的部分。

hi rk:
为什么亮屏的时候有时候会打印这句VOP等待超时?请问下这是什么意思。
[ 1211.293492] rockchip-vop ff930000.vop: wait win close timeout
[ 1211.293514] rockchip-vop ff930000.vop: [drm:vop_crtc_enable] Update mode to 1200*1920, close all win
有时候却不会打印。

[ 1216.423283] rockchip-vop ff930000.vop: [drm:vop_crtc_enable] Update mode to 12001920, close all win [ 1223.899741] rockchip-vop ff930000.vop: [drm:vop_crtc_enable] Update mode to 12001920, close all win
[ 1234.386252] rockchip-vop ff930000.vop: [drm:vop_crtc_enable] Update mode to 1200*1920, close all win

patch代码如下

--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -139,6 +139,9 @@
 #define to_vop_win(x) container_of(x, struct vop_win, base)
 #define to_vop_plane_state(x) container_of(x, struct vop_plane_state, base)

+/*add by VENDOR_PATCH for seep up the drm vop driver at 2018/1/18 for RK Defect #191554, VENDOR_PATCH PAD100-193*/
+#define VENDOR_PATCH
+
 struct vop_zpos {
        int win_id;
        int zpos;
@@ -868,9 +871,15 @@ static void vop_disable_all_planes(struct vop *vop)

        vop_disable_allwin(vop)
;
        vop_cfg_done(vop);
+#ifdef VENDOR_PATCH
        ret = readx_poll_timeout_atomic(vop_is_allwin_disabled,
                                        vop, active, active,
+                                       0100 * 1000);
+#else
+       ret = readx_poll_timeout_atomic(vop_is_allwin_disabled,
+                               vop, active, active,
                                        0500 * 1000);
+#endif
        if (ret)
                dev_err(vop->dev, "wait win close timeout\n");
 }
@@ -2215,20 +2224,36 @@ static size_t vop_crtc_bandwidth(struct drm_crtc *crtc,
        u16 htotal = adjusted_mode->crtc_htotal;
        u16 vdisplay = adjusted_mode->crtc_vdisplay;
        int clock = adjusted_mode->crtc_clock;
+#ifndef VENDOR_PATCH
        struct vop *vop = to_vop(crtc
)
;
        const struct vop_data *vop_data = vop->data;
+#endif
        struct vop_plane_state *vop_plane_state;
        struct drm_plane_state *pstate;
        struct vop_bandwidth *pbandwidth;
        struct drm_plane *plane;
        u64 bandwidth;
        int i, cnt = 0;
+#ifdef VENDOR_PATCH
+       int plane_num = 0;
+#endif

        if (!htotal || !vdisplay)
                return 0;

+#ifndef VENDOR_PATCH
        pbandwidth = kmalloc_array(vop_data->win_size, sizeof(*pbandwidth),
                                   GFP_KERNEL);
+#else
+       for_each_plane_in_state(state, plane, pstate, i) {
+               if (pstate->crtc != crtc || !pstate->fb)
+                       continue;
+               plane_num++;
+       }
+       pbandwidth = kmalloc_array(plane_num, sizeof(*pbandwidth),
+                                  GFP_KERNEL);
+#endif
+
        if (!pbandwidth)
                return -ENOMEM;

@@ -2421,7 +2446,10 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
        rockchip_set_system_status(sys_status)
;
        mutex_lock(&vop->vop_lock);
        vop_initial(crtc);
-
+#ifdef VENDOR_PATCH
+       vop_disable_allwin(vop);
+       VOP_CTRL_SET(vop, standby, 0);
+#endif
        VOP_CTRL_SET(vop, dclk_pol, 1);
        val = (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) ?
                   0 : BIT(HSYNC_POSITIVE);
@@ -2549,8 +2577,9 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
        /*
         * enable vop, all the register would take effect when vop exit standby
         */

+#ifndef VENDOR_PATCH
        VOP_CTRL_SET(vop, standby, 0)
;
-
+#endif
        enable_irq(vop->irq);
        drm_crtc_vblank_on(crtc);
        mutex_unlock(&vop->vop_lock);


修改QOS相关代码

QOS为Quality Of Service(服务质量)的简称,对PM QoS而言,表示Linux kernel电源管理相关的服务质量。那到底什么是服务质量呢?

我们知道,Linux PM的主要功能,是节省功耗,但同时,会付出一定的性能代价,例如延迟(latency)增加、吞吐量(throughput)下降。可以把PM当作一种服务,把它对性能的影响,类比为服务的质量(QoS)。对性能的影响越大,QoS越低,反之越高。

我们可以这么认为,我们在某个时候需要增加代码的执行速度,就通过这个去控制CPU的运行策略,这样确保代码可以快速执行。

不过这个方法没有使用到,如果对某个resume时间不是十分满意,可以尝试这个方法。

休眠唤醒流程图

从网上拷贝了个休眠唤醒的流程图,如果以后有问题需要分析的话,可以跟进这个流程去排查。

640?wx_fmt=jpeg

参考

https://www.spinics.net/lists/linux-pm/msg24063.html
http://eeepage.info/pm-failed-suspend-wakeup_event/
https://blog.csdn.net/qq_695538007/article/details/41208135
https://blog.csdn.net/jacobywu/article/details/24735521


640?wx_fmt=png

当你看到这里的时候,说明你已经阅读完上面的内容,不管怎样,感谢您有心或者无意的关注和支持,

觉得不错,请帮忙转发点好看,您的每一次支持,我都将铭记于心

公众号接入了AI功能,随意回复任意消息哦(比如笑话,天气

想获取学习资料,请点击状态栏公众号福利按钮



640?wx_fmt=jpeg




本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/468847.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

container_of实例

1 前面说的 container_of 在linux内核代码里面使用非常多&#xff0c;对于喜欢linux编程的同学来说&#xff0c;对这个函数要非常清楚他的使用方法&#xff0c;而且还要知道他的原理&#xff0c;这对以后看内核代码&#xff0c;写内核驱动的帮助都非常大&#xff0c;当然&…

Git 分布式版本控制工具 03Git常用命令:Git全局设置+本地与远程仓库操作获取Git仓库+标签操作+忽略名单+工作区、暂存区、版本库+分支操作+暂时保存

Git常用命令目录4 Git常用命令4.1 Git全局设置4.2 获取Git仓库4.2.1 在本地初始化Git仓库4.2.2 从远程仓库克隆4.3 常见的概念&#xff1a;工作区、暂存区、版本库4.4 常见的概念&#xff1a;Git工作区中文件的状态4.5 本地仓库操作4.5.1 git status4.5.2 git add4.5.3 git res…

matlab dir函数_MATLAB自动管理文件

MATLAB自动管理文件1. MATLAB中路径设置(1)cd:用于切换当前工作目录示例&#xff1a;将当前工作目录切换到D:\Documents\MATLAB\Matlab test\study下。代码:cd (D:\Documents\MATLAB\Matlab test\study)(2)path:用于对搜索路径的操作示例&#xff1a;先查看当前所有的文件路径&…

Git 分布式版本控制工具 04Gitcode案例:多人协作开发流程+创建仓库+拉取操作+克隆仓库+拉取远程仓库中最新的版本+修改拉取的本地代码

文章目录5. Gitcode5.1 多人协作开发流程5.2 创建仓库5.3 拉取操作5.3.1 克隆仓库5.3.2 拉取远程仓库中最新的版本5.4 修改拉取的本地代码5.5 解决冲突5.6 跨团队协作5. Gitcode 在版本控制系统中&#xff0c;大约90%的操作都是在本地仓库中进行的&#xff1a;暂存&#xff0c…

rabbitmq如何保证消息不被重复消费_如何保证消息不被重复消费

一. 重复消息为什么会出现消息重复&#xff1f;消息重复的原因有两个&#xff1a;1.生产时消息重复&#xff0c;2.消费时消息重复。1.1 生产时消息重复由于生产者发送消息给MQ&#xff0c;在MQ确认的时候出现了网络波动&#xff0c;生产者没有收到确认&#xff0c;实际上MQ已经…

Git 分布式版本控制工具 06在IDEA中使用Git:获取Git仓库+本地仓库操作+远程仓库操作+创建/查看/切换/推送/合并分支操作

在IDEA中使用Git7. 在IDEA中使用Git7.1 在IDEA中配置Git7.2 获取Git仓库7.2.1 本地初始化仓库7.2.2 从远程仓库克隆7.3 Git忽略文件7.4 本地仓库操作7.4.1 将文件加入暂存区7.4.2 将暂存区文件提交到版本库7.4.3 查看日志7.5 远程仓库操作7.5.1 查看远程仓库7.5.2 添加远程仓库…

linux 内核宏container_of剖析

1、前面说的我在好几年前读linux 驱动代码的时候看到这个宏&#xff0c;百度了好久&#xff0c;知道怎么用了&#xff0c;但是对实现过程和原理还是一知半解。container_of宏 在linux内核代码里面使用次数非常非常多&#xff0c;对于喜欢linux编程的同学来说&#xff0c;了解其…

目录树 删除 数据结构_数据结构:B树和B+树的插入、删除图文详解

B树1.1B树的定义B树也称B-树,它是一颗多路平衡查找树。我们描述一颗B树时需要指定它的阶数&#xff0c;阶数表示了一个结点最多有多少个孩子结点&#xff0c;一般用字母m表示阶数。当m取2时&#xff0c;就是我们常见的二叉搜索树。一颗m阶的B树定义如下&#xff1a;1)每个结点最…

MMdetection框架速成系列 第01部分:学习路线图与步骤+优先学习的两个目标检测模型代码+loss计算流程+遇到问题如何求助+Anaconda3下的安装教程(mmdet+mmdet3d)

mmdetection 学习目录1 mmdetection 学习建议1.1 mmdetection 学习的第一件事1.2 mmdetection学习路线图1.2.1 优先看的两个库1.2.2 阅读代码1.2.3 代码学习步骤1.2.4 建议优先学习的两个目标检测模型代码1.2.5 loss计算流程的攻坚克难1.3 遇到问题如何求助2 Anaconda3下的安装…

机器人循迹小车资料

前言 我记得在大学的时候&#xff0c;参加电子比赛&#xff0c;我们有一个题目是平衡小车项目&#xff0c;那个对基础要求还是比较高的&#xff0c;总结了一些平衡车机器的资料&#xff0c;希望对大家有帮助。 正文 关注公众号&#xff0c;回复【机器人资料】获取

单片机实现环形队列_稀疏数组和队列(二)

队列的介绍队列以一种先入先出(FIFO)的线性表&#xff0c;还有一种先入后出的线性表(FILO)叫做栈。教科书上有明确的定义与描述。类似于现实中排队时的队列(队尾进&#xff0c;队头出)&#xff0c;队列只在线性表两端进行操作&#xff0c;插入元素的一端称为表尾&#xff0c;删…

漫画-Linux中断子系统综述

1、中断引发的面试教训2、什么是中断&#xff1f;中断&#xff1a; &#xff08;英语&#xff1a;Interrupt&#xff09;指当出现需要时&#xff0c;CPU暂时停止当前程序的执行转而执行处理新情况的程序和执行过程。即在程序运行过程中&#xff0c;系统出现了一个必须由CPU立即…

SQL强化(二) 在Oracle 中写代码

一 : 关于查询中的转换 -- 字符串转换 一 : decode 函数 转换 SELECT DECODE ( PROTYPE.PRO_TYPE_DATE, L, 长, m, 短, 默认值 )FROM PROTYPE -- 字符串转换 二 : case 转换 SELECT T1.PRO_TYPE_ID, T1.PRO_TYPE_NAME, CASE T1.PRO_TYPE_DATEWHEN S THEN 短WHEN L THEN 长EL…

vue 非es6 写法怎么按须加载_Vue源码必学指南:flow(语法检查)以及rollup(模板打包)...

点击上方蓝色字关注我们~一、前言虽然 Vue3 已经公开了代码,但是Vue3.0还处于开发阶段&#xff0c;直接上手使用Typescript是不合适的 , 对于前端的老手是不错的选择, 但是如果没有研究源码经验的开发者还是建议使用完善, 成熟的源码进行入手. 而 Vue 2.x 中使用的 flow 是一个…

漫画|创业到底有多难?

我有一群同事&#xff0c;我们一起经历了一个产品从无到有的过程&#xff0c;从开始的斗志满满到最后跟老板的不欢而散&#xff0c;其中的辛酸苦楚也许只能我们自己能体味&#xff0c;在这过程中&#xff0c;我们共同经历过的事情&#xff0c;有快乐的&#xff0c;悲伤的&#…

生成step文件_利用opencv给彦女王生成一副蒙太奇画像

大家好呀&#xff0c;前两天烈阳天道1上映了&#xff0c;不知道大家看没看呢&#xff0c;里面还有一小段彦穿越虫洞与猴哥相遇的画面&#xff0c;彦女王啊啊啊~~所以我去网上爬了二百来张我大学的风景画&#xff0c;然后找了以前存的彦女王的图片&#xff0c;生成了一幅蒙太奇画…

浪漫情人节|C语言画心型

1.前言新年第一天上班&#xff0c;先祝大家新年快乐&#xff0c;巧的是&#xff0c;今天刚好又是情人节&#xff0c;所以想了下用C实现画心形符号~过年的时候&#xff0c;跟我表哥去接新娘&#xff0c;实地看了下&#xff0c;如果一个汉字内心没有点浪漫的细胞&#xff0c;很难…

CS190.1x Scalable Machine Learning

这门课是CS100.1x的后续课&#xff0c;看课程名字就知道这门课主要讲机器学习。难度也会比上一门课大一点。如果你对这门课感兴趣&#xff0c;可以看看我这篇博客&#xff0c;如果对PySpark感兴趣&#xff0c;可以看我分析作业的博客。 Course Software Setup 这门课的环境配置…

./4.sh: No such file or directory

sh push到目标板后提示出错 #!/bin/bash echo "ladjfaosdjfoia"头bin/bash 我们要看&#xff0c;sh在哪里 130|rk3399_idpad:/data # which sh /system/bin/sh rk3399_idpad:/data # 所以上面的代码应该写成 #!/system/bin/sh echo "ladjfaosdjfoia"修…

Spring总结四:IOC和DI 注解方式

首先我们要了解注解和xml配置的区别&#xff1a; 作用一样&#xff0c;但是注解写在Bean的上方来代替我们之前在xml文件中所做的bean配置&#xff0c;也就是说我们使用了注解的方式&#xff0c;就不用再xml里面进行配置了&#xff0c;相对来说注解方式更为简便。 IOC获取对象注…