下面介紹下,我在以往手機觸摸屏調試中碰到的關于如何優化觸摸屏響應速度的分析思路,給沒有接觸過這方面的初學者一個方向。
觸摸屏的響應速度分為幾個階段去優化:
1階段1: 從手指觸發到觸摸屏電容表面》觸摸屏信号處理》控制輸出觸摸屏中斷信号;
2階段2:平台側響應來自觸摸屏器件的IRQ信号,進而退出CPU idle;
3階段3:IRQ控制器總入口》進入到觸摸屏驅動注冊到平台IRQ的入口函數内,接着執行觸摸屏中斷函數内的工作隊列,進而調用I2C平台端的控制器和觸摸屏通信,完成input事件的上報。
舉例:RK平台:
分析方法:
抓取ftrace:
<idle>-0 [000] d.h2 439.249389: irq_handler_entry: irq=303 name=GSL3673
<idle>-0 [000] d.h5 439.249406: clk_disable: pclk_gpio7
<idle>-0 [000] d.h3 439.249424: workqueue_queue_work: work struct=c48ddc18 function=gsl3673_ts_worker workqueue=c49dda00 req_cpu=4 cpu=4294967295
<idle>-0 [000] d.h3 439.249430: workqueue_activate_work: work struct c48ddc18
<idle>-0 [000] dnh2 439.249473: irq_handler_exit: irq=303 ret=handled
kworker/u8:3-169 [000] ...1 439.249586: workqueue_execute_start: work struct c48ddc18: function gsl3673_ts_worker
kworker/u8:3-169 [000] d..3 439.249607: clk_enable: pclk_i2c4
kworker/u8:3-169 [000] d.h1 439.249637: irq_handler_entry: irq=36 name=ff160000.i2c
kworker/u8:3-169 [000] d.h1 439.249652: irq_handler_exit: irq=36 ret=handled
<idle>-0 [000] d.h2 439.249713: irq_handler_entry: irq=36 name=ff160000.i2c
<idle>-0 [000] d.h2 439.249727: irq_handler_exit: irq=36 ret=handled
<idle>-0 [000] d.h2 439.249743: irq_handler_entry: irq=36 name=ff160000.i2c
<idle>-0 [000] dnh2 439.249782: irq_handler_exit: irq=36 ret=handled
kworker/u8:3-169 [000] d..3 439.249866: clk_disable: pclk_i2c4
kworker/u8:3-169 [000] d..3 439.249889: clk_enable: pclk_i2c4
kworker/u8:3-169 [000] d.h1 439.249917: irq_handler_entry: irq=36 name=ff160000.i2c
kworker/u8:3-169 [000] d.h1 439.249937: irq_handler_exit: irq=36 ret=handled
<idle>-0 [000] d.h2 439.250766: irq_handler_entry: irq=36 name=ff160000.i2c
<idle>-0 [000] d.h2 439.250791: irq_handler_exit: irq=36 ret=handled
<idle>-0 [000] d.h2 439.251091: irq_handler_entry: irq=36 name=ff160000.i2c
<idle>-0 [000] d.h2 439.251107: irq_handler_exit: irq=36 ret=handled
<idle>-0 [000] d.h2 439.251134: irq_handler_entry: irq=36 name=ff160000.i2c
<idle>-0 [000] dnh2 439.251178: irq_handler_exit: irq=36 ret=handled
kworker/u8:3-169 [000] d..3 439.251256: clk_disable: pclk_i2c4
kworker/u8:3-169 [000] d..4 439.251383: clk_enable: pclk_gpio7
kworker/u8:3-169 [000] ...1 439.251402: workqueue_execute_end: work struct c48ddc18
分析:
其中:
1
<idle>-0 [000] d.h2 439.249389: irq_handler_entry: irq=303 name=GSL3673
idle程序響應,觸摸屏的IRQ入口開始的時間點是439.249389
2
<idle>-0 [000] dnh2 439.249473: irq_handler_exit: irq=303 ret=handled
觸摸屏的IRQ入口開始的結束點是439.249473
3
IRQ函數内排程了工作隊列和綁定的一個work,線程号是169,ps 可以看到kworker
工作隊列上work執行開始的時間點是:
kworker/u8:3-169 [000] ...1 439.249586: workqueue_execute_start: work struct c48ddc18: function gsl3673_ts_worker
工作隊列上work執結束的時間點是:
kworker/u8:3-169 [000] ...1 439.251402: workqueue_execute_end: work struct c48ddc18
4
I2C4控制器的耗時,不分析。
是以階段3耗時:439.251402-439.249389=2.1ms;
通過谷歌浏覽器分析:
平均間隔1.76MS,這裡是工作隊列的執行時間而已。
示波器測試:
整個過程可以使用示波器來追蹤,如何追蹤呢?
階段1:
觸摸屏表面單體放置硬币,探頭,快速點選測試觸摸屏,對比觸摸屏單體内部信号觸發的波形,以及測試觸摸屏IRQ的輸出時間,可以計算出平均時延。
階段2,階段3,都可以在代碼入口和出口,加入GPIO翻轉方式去擷取波形時間。
總結:
通過ftrace來分析觸摸屏的階段3的耗時latency,舉一反三,可以加入日志去計算CPU IDLE的耗時。
也可以在驅動代碼中加入
trace_printk(" trace func is enter %s",__func__);
去追蹤是哪裡導緻耗時過長。
經驗舉例:
我就碰到一種情況,就是高通平台坑很多,為了達到省點的目的,經常CPU idle的時候關閉一些系統電源,導緻退出CPU idle都需要一定ms時間,接着才能進入到IRQ入口;也就階段2就耗費9MS左右。
然後階段3,在首次啟動的時候也同樣存在I2C控制器和外設互動的時候latency耗時過長;