日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

排查一个触摸屏驱动问题

發布時間:2023/12/20 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 排查一个触摸屏驱动问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

今天跟同事看一個TP驅動,上電后日志都正常,但是觸摸沒反應,然后開始排查。

上電后可以正常讀到芯片的chip ID,那說明I2C是通訊正常的,也可以說明觸摸芯片的供電也是正常的。

基于這個,我搬來示波器,測量中斷引腳的信號,發現兩個現象

1、從休眠到喚醒狀態后,中斷腳有波形,而且波形上看不出異常。

2、中斷處理函數沒有跑進去

—— 觸摸屏的dts文件編寫如下

?文件:arch/arm/boot/dts/inxxx.dtscap_touch@14?{compatible?=?"mediatek,cap_touch";reg?=?<0x14>;interrupt-parent?=?<&pio>;interrupts?=?<100?IRQ_TYPE_EDGE_FALLING>;int-gpio?=?<&pio?100?0>;rst-gpio?=?<&pio?101?0>;};

compatible 是和驅動里面的name 匹配上的。

reg 是I2C芯片的 地址。

interrupt-parent 對應的是平臺的中斷控制器,里面應用的 pio對應的是mt8167.dtsi文件里面的中斷控制器dts描述

interrupts 的第一個參數對應的是中斷號,第二個參數對應的是中斷的觸發方式。

int-gpio 里面引用的 pio 也是用到了 pio里面的gpio口控制器,第二個參數對應的是gpio 編號,第三個對應的是gpio口的電平。

rst-gpio 和上面同理。

看內核文檔對gpiodts的描述

?文件:Documentation/devicetree/binding/pinctrl/pinctrl-mt65xx.txtEg:?<&pio?6?0><[phandle?of?the?gpio?controller?node][line?number?within?the?gpio?controller][flags]>Values?for?gpio?specifier:-?Line?number:?is?a?value?between?0?to?202.-?Flags:??bit?field?of?flags,?as?defined?in?<dt-bindings/gpio/gpio.h>.?Only?the?following?flags?are?supported:?0?-?GPIO_ACTIVE_HIGH?1?-?GPIO_ACTIVE_LOW

看看&pio這個里面都是一些什么東西

pio:?pinctrl@10005000?{compatible?=?"mediatek,mt8167-pinctrl";reg?=?<0?0x1000b000?0?0x1000>;mediatek,pctl-regmap?=?<&syscfg_pctl_a>;pins-are-numbered;gpio-controller;#gpio-cells?=?<2>;interrupt-controller;#interrupt-cells?=?<2>;interrupts?=?<GIC_SPI?134?IRQ_TYPE_LEVEL_HIGH>; };

—— 看看注冊上的中斷的編號

xxxx:/?#?cat?proc/interruptsCPU018:??????19578???????GIC??27?Edge??????arch_timer20:??????????0??MT_SYSIRQ?132?Level?????mtk_timer21:?????????12??MT_SYSIRQ??84?Level?????mtk-uart30:??????????0??MT_SYSIRQ?128?Level?????SPM31:??????????0??MT_SYSIRQ?129?Level?????SPM32:??????????0??MT_SYSIRQ?130?Level?????SPM33:??????????0??MT_SYSIRQ?131?Level?????SPM34:??????????0??MT_SYSIRQ?221?Edge??????ATF_irq39:??????????0??MT_SYSIRQ?194?Level?????BTCVSD_ISR_Handle40:??????????0??MT_SYSIRQ?198?Edge??????mtk-wdt42:??????????0??MT_SYSIRQ?204?Level?????mt-pmic-pwrap43:??????????0??MT_SYSIRQ?149?Edge??????mtk-kpd45:??????????0??MT_SYSIRQ?121?Level?????10203000.m4u46:??????????0??MT_SYSIRQ?218?Level?????CIRQ47:??????????0??MT_SYSIRQ?114?Level?????TEE?IRQ49:???????2942??MT_SYSIRQ?125?Level?????mtk_cmdq50:??????????0??MT_SYSIRQ?126?Level?????TEE?IRQ53:??????????0??MT_SYSIRQ??76?Level?????mt-pwm54:?????????30??MT_SYSIRQ??80?Level?????i2c-mt65xx55:?????????16??MT_SYSIRQ??81?Level?????i2c-mt65xx56:?????????64??MT_SYSIRQ??82?Level?????i2c-mt65xx57:??????????0??MT_SYSIRQ??77?Level?????mt8167-thermal58:?????????16??MT_SYSIRQ??83?Level?????ptp62:??????20967??MT_SYSIRQ??72?Level?????musb-hdrc63:??????????0??MT_SYSIRQ?120?Level?????Afe_ISR_Handle64:???????2950??MT_SYSIRQ?185?Level?????pvrsrvkm65:?????113181??MT_SYSIRQ??78?Level?????11120000.mmc67:??????????0??MT_SYSIRQ?210?Level?????musbfsh-hdrc.074:????????347??MT_SYSIRQ?160?Level?????DISPSYS75:??????12980??MT_SYSIRQ?162?Level?????DISPSYS76:??????????0??MT_SYSIRQ?163?Level?????DISPSYS80:??????????0??MT_SYSIRQ?167?Level?????DISPSYS83:??????????0??MT_SYSIRQ?171?Level?????DISPSYS85:???????1466??MT_SYSIRQ?153?Level?????DISPSYS88:??????????0??MT_SYSIRQ?180?Level?????ISP 123:??????????0??mtk-eint??28?Level?????mt6397-pmic 136:??????????0??mtk-eint??41?Level?????USB_IDDIG 195:??????????6??mtk-eint?100?Edge??????mtk-tpd 264:??????????0??mt6397-irq???6?Edge??????mt6397-thr_l 265:??????????0??mt6397-irq???7?Edge??????mt6397-thr_h 266:??????????0??mt6397-irq???5?Edge??????mtk-pmic-keys 267:??????????0??mt6397-irq??17?Edge??????mtk-pmic-keys 268:??????????0??mt6397-irq??18?Edge??????mtk-pmic-keys 269:??????????0??mt6397-irq??19?Edge??????mtk-pmic-keys 270:??????????0??mt6397-irq??20?Edge??????mt6397-rtc IPI0:??????????0??CPU?wakeup?interrupts IPI1:??????????0??Timer?broadcast?interrupts IPI2:??????31856??Rescheduling?interrupts IPI3:?????????35??Function?call?interrupts IPI4:????????121??Single?function?call?interrupts IPI5:??????????0??CPU?stop?interrupts IPI6:??????????0??IRQ?work?interrupts IPI7:??????????0??completion?interrupts Err:??????????0

#看看驅動文件如何駕馭這些dts配置

先使用函數獲取dts里面的內容

??tpd_rst_gpio?=?of_get_named_gpio(dev->of_node,?"rst-gpio",?0);tpd_int_gpio?=?of_get_named_gpio(dev->of_node,?"int-gpio",?0);

然后就是申請

static?int?gtp_get_gpio_res(void) { #if?defined(CONFIG_OF)?&&?!defined(CONFIG_GTP_USE_PINCTRL)int?ret;/*?configure?the?gpio?pins?*/ret?=?gpio_request_one(tpd_rst_gpio,?GPIOF_OUT_INIT_LOW,"touchp_reset");if?(ret?<?0)?{GTP_ERROR("Unable?to?request?gpio?reset_pin\n");return?-1;}ret?=?gpio_request_one(tpd_int_gpio,?GPIOF_IN,"tpd_int");if?(ret?<?0)?{GTP_ERROR("Unable?to?request?gpio?int_pin\n");gpio_free(tpd_rst_gpio);return?-1;} #endifreturn?0; }

然后去看中斷注冊函數的時候,會有點奇怪

static?int?tpd_irq_registration(void) {struct?device_node?*node?=?NULL;unsigned?long?irqf_val?=?0;int?ret?=?0;//?node?=?of_find_compatible_node(NULL,?NULL,?"mediatek,cap_touch");//0704node?=?of_find_matching_node(NULL,?touch_of_match);if?(node)?{ //??touch_irq?=?gpio_to_irq(tpd_int_gpio);touch_irq?=?irq_of_parse_and_map(node,?0);GTP_ERROR("######?touch_irq?=?%d\n",(int)touch_irq);irqf_val?=?!int_type???IRQF_TRIGGER_RISING?:?IRQF_TRIGGER_FALLING;irq_enabled?=?true;?//ret?=?request_irq(touch_irq,?(irq_handler_t)?tpd_interrupt_handler,irqf_val,?TPD_DEVICE,?NULL);?//jason?test?hereGTP_ERROR("######?ret?=?%d\n",(int)ret);if?(ret?<?0)GTP_ERROR("tpd?request_irq?IRQ?LINE?NOT?AVAILABLE!."); }

// touch_irq = gpio_to_irq(tpd_int_gpio); 這行代碼被注釋掉了,也就是不用 gpio_to_irq來使用中斷了。

目前的驅動使用了 irq_of_parse_and_map 函數來解析dts內容給驅動使用。

使用 irq_of_parse_and_map 的原因還是為了讓驅動工程師少干活,dts 已經把中斷的信息給描述清楚了,包括上面說的 interrupts 和 interrupt-parent 屬性,這個函數會解析這兩個屬性,并實現對應的映射關系。

—— 看看內核代碼對這個函數的解釋

/***?irq_of_parse_and_map?-?Parse?and?map?an?interrupt?into?linux?virq?space*?@dev:?Device?node?of?the?device?whose?interrupt?is?to?be?mapped*?@index:?Index?of?the?interrupt?to?map**?This?function?is?a?wrapper?that?chains?of_irq_parse_one()?and*?irq_create_of_mapping()?to?make?things?easier?to?callers*/ unsigned?int?irq_of_parse_and_map(struct?device_node?*dev,?int?index) {struct?of_phandle_args?oirq;if?(of_irq_parse_one(dev,?index,?&oirq))return?0;return?irq_create_of_mapping(&oirq); } EXPORT_SYMBOL_GPL(irq_of_parse_and_map);

上面的英文的意思是,這個函數是解析并映射中斷到 linux virq 空間,dev對應的就是device指針,index 就是需要映射的中斷的索引。

該函數是 of_irq_parse_one() 和 irq_create_of_mapping() 的封裝,封裝的作用是為了碼農寫代碼更容易一些。

我們再看看

touch_irq?=?irq_of_parse_and_map(node,?0);

后邊的這個 0表示的是偏移索引,如果我們在dts里面這樣寫的話,就可以使用索引來選擇我們的配置

interrupts?=?<0?0?4>,?<0?1?4>;

我們在 proc/interrupts下看到的編號「195」就是這里出來的

195:?????????69??????????0??????????0??????????0??mtk-eint?100?Edge??????mtk-tpd

#所以為什么中斷函數沒有進去?

檢查了一輪發現是因為dts描述里面的?interrupts?屬性沒有寫對,interrupts?的第一個參數需要和gpio口編號對應起來,但是我們沿用上個項目的代碼,應該修改了這個gpio口,我們軟件沒有及時修改過來。

當然了,知道問題后就很快解決了。

觸摸后可以看到觸摸屏可以正常報點是一件非常開心的事情。

#驅動獲取dts中斷的方式

這部分韋東山老師總結的非常好的,我建議大家看看這篇文章

在Linux驅動中獲取dts描述的中斷

針對不同的設備,獲取的方式不同,比較常見的是在dts里面把中斷描述成一個gpio口,然后在驅動中先獲取gpio口,然后再轉換成中斷。

#總結

這部分屬于炒舊飯,觸摸屏驅動是比較常見的外設,調試的難度也不是很大,正常的調試順序是

— 先搞定供電
—?再搞定I2C、I2C一般需要上拉,還有I2C的速率,I2C的電平。

— 再看看地址,我們Linux 里面一般是 7bit 地址,需要注意,地址也會跟硬件設計相關。

— 上面都正常了,就可以去排查中斷的問題了,有的GPIO可能默認沒有中斷,也需要軟件配置。

—?然后就觀察軟件是否能進入中斷處理函數,有的驅動是支持輪詢的,但是代碼位置都差不多。

這樣都正常后就可以開機測試觸摸是否正常了。

推薦閱讀:

專輯|Linux文章匯總

專輯|程序人生

專輯|C語言

我的知識小密圈


嵌入式Linux

微信掃描二維碼,關注我的公眾號?

總結

以上是生活随笔為你收集整理的排查一个触摸屏驱动问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。