【調(diào)試筆記】韋東山:在100ASK_IMX6ULL板子上支持其他型號(hào)的屏幕

作者:韋東山
目錄
1. 我擔(dān)心這有點(diǎn)尷尬
2. 移植思路
3. 移植LCD驅(qū)動(dòng)
3.1 確定LCD參數(shù)
3.2 修改設(shè)備樹
3.3 完善驅(qū)動(dòng)
4. 移植觸摸屏驅(qū)動(dòng)
4.1 確定觸摸屏型號(hào)
4.2 在設(shè)備樹中指定觸摸IC信息
4.3 重新配置內(nèi)核添加驅(qū)動(dòng)
4.4 調(diào)試:找出問(wèn)題
4.5 解決方法
4.6 其他情況
4.7 gt9xx芯片固件更新
100ask_imx6ull預(yù)售購(gòu)買鏈接&產(chǎn)品介紹:
http://100ask.taobao.com?(點(diǎn)開店鋪首頁(yè)的第一張海報(bào)即可進(jìn)入購(gòu)買頁(yè)面)
很多學(xué)員有過(guò)STM32的學(xué)習(xí)經(jīng)驗(yàn),他們手上的開發(fā)板很多,LCD也很多。
一個(gè)LCD還挺貴的,他們問(wèn),100ask_imx6ull開發(fā)板能否兼容其他廠家的LCD?最近我們一直在調(diào)試這個(gè)問(wèn)題。所以就有了本文。
1. 我擔(dān)心這有點(diǎn)尷尬
同一款芯片的開發(fā)板,基本上都是源自廠家的公板。
如果有人跟你說(shuō):我們的程序在別家的板子上無(wú)法運(yùn)行,這是有可能的,因?yàn)檫€沒(méi)移植。
但是如果有人跟你說(shuō):我們的學(xué)習(xí)資料,只適合我們的板子。
那只有2個(gè)原因:資料太差,你不適合學(xué)習(xí)這行。
如果相同芯片的板子都無(wú)法移植,工作時(shí)一定是使用其他芯片的,到時(shí)你怎么辦啊?
很多學(xué)員有過(guò)STM32的學(xué)習(xí)經(jīng)驗(yàn),他們手上的開發(fā)板很多,LCD也很多。
一個(gè)LCD還挺貴的,他們買Linux開發(fā)板時(shí),問(wèn)我:
a. 能不能在100ASK_IMX6ULL上使用手上的LCD?
這當(dāng)然能,做一個(gè)轉(zhuǎn)接板就可以了,幾元錢就可以做出來(lái)。
各家的LCD引腳順序都不一樣,所以別家的LCD不能直接接到100ASK_IMX6ULL開發(fā)板,需要轉(zhuǎn)接板。
大部分單片機(jī)學(xué)員都是使用正點(diǎn)原子、野火的板子,有他們的屏。
針對(duì)這兩家的屏,我們做了轉(zhuǎn)接板,如下:

我們提供的內(nèi)核、設(shè)備樹,并不能直接支持其他廠家的LCD,可以聯(lián)系我們,我們來(lái)調(diào)試。
下面的文檔是示例,教你們?cè)趺醋约阂浦病?/p>
b. 能不能移植這些LCD驅(qū)動(dòng)?
這很簡(jiǎn)單,半小時(shí)就可以搞定。
c. 能不能寫成文檔?
這有點(diǎn)尷尬。
咱也不藏頭藏尾了,有話直接說(shuō)。
去年9月份左右,我們專心錄視頻,想法很美好。
我們只錄視頻,同時(shí)支持各家IMX6ULL開發(fā)板,大家一起把生態(tài)做好。
所以你可以看到我們的視頻/文檔支持野火的IMX6ULL、支持正點(diǎn)原子的IMX6ULL。
但是后來(lái)發(fā)現(xiàn)不行啊,我錄收費(fèi)視頻,他們也錄視頻還免費(fèi)。
雖然我自信有10幾年功力,但是也擋不住免費(fèi)啊。
這樣下去我得沒(méi)飯吃,所以我們也做了開發(fā)板,還0利潤(rùn)。
這就有很大的競(jìng)爭(zhēng)關(guān)系了。
所以,我們的視頻、文檔是否繼續(xù)支持同行的板子?
看似難以決定,想清楚后就不難了。
我們會(huì)繼續(xù)支持各家的板子,不能因?yàn)闀?huì)給同行帶來(lái)好處就廢棄承諾。
我們的裸板+同行的LCD,這是避免浪費(fèi)的好事,不能因?yàn)闀?huì)給我們引流而避諱。
2. 移植思路
LCD除了顯示之外,它的表面通常還貼有一個(gè)觸摸屏。
所以我們移植的是2個(gè)設(shè)備的驅(qū)動(dòng):LCD、觸摸屏。
LCD驅(qū)動(dòng)在內(nèi)核中已經(jīng)有了,并且很完善,我們只需要修改設(shè)備樹就可以:修改時(shí)序等LCD參數(shù),修改背光引腳等板子參數(shù)。
觸摸屏的驅(qū)動(dòng)在內(nèi)核中一般也有了,各廠家用的觸摸屏IC可能不同。需要配置內(nèi)核把它加進(jìn)去,同時(shí)修改設(shè)備樹:指定觸摸IC的信息(比如I2C地址),指定中斷引腳。
如果能拿到這塊LCD在別的板子上的內(nèi)核源碼,就可以參考它的LCD參數(shù)、觸摸IC信息。
再結(jié)合你用的開發(fā)板,把涉及的GPIO找出來(lái)寫入設(shè)備樹。
簡(jiǎn)單吧?
開工!
3. 移植LCD驅(qū)動(dòng)
注意:100ASK_IMX6ULL不能直接連接其他廠家的屏,需要轉(zhuǎn)接板。
IMX6ULL跟LCD的連接框圖如下:

IMX6ULL內(nèi)部有LCD控制器,肯定是廠家對(duì)這個(gè)LCD控制器最熟悉了,所以他們?yōu)榱速u芯片,一般都會(huì)在內(nèi)核中做好LCD控制器的驅(qū)動(dòng)程序。
而IMX6ULL可以接各種LCD,這些LCD參數(shù)各有不同。LCD控制器的驅(qū)動(dòng)程序會(huì)去設(shè)備樹中獲得這些參數(shù),并根據(jù)這些參數(shù)來(lái)設(shè)置LCD控制器。
所以,我們要做的事情從理論上講很簡(jiǎn)單:根據(jù)LCD參數(shù)修改設(shè)備樹。
但是,誰(shuí)說(shuō)廠家的驅(qū)動(dòng)就沒(méi)有BUG,就完美無(wú)缺了?
我們要做的事有3項(xiàng):確定LCD參數(shù),修改設(shè)備樹,完善驅(qū)動(dòng)。
3.1 確定LCD參數(shù)
如果還保留有LCD的芯片手冊(cè),這是最好的??上遗龅降拇蠖鄬W(xué)員早已經(jīng)忘記這些資料在哪了。
野火的屏在板子背后直接寫明分辨率是多少,這比較簡(jiǎn)單直接。
正點(diǎn)原子的屏在背后畫有一個(gè)表格,如下:

上圖例子中,M2、M1接地,M0接電源,所以M2M1M0為001;對(duì)比表格可知它的分辨率為800x480。
如果是從零開發(fā),我們還需要找到芯片手冊(cè)確定LCD的詳細(xì)時(shí)序。
我們沒(méi)有LCD的手冊(cè),即使有也懶得看。
直接看廠家的源碼不就行了?直接點(diǎn),直接看它的設(shè)備樹不就行了?
找到LCD廠家的IMX6ULL內(nèi)核源碼,執(zhí)行以下命令:
$ cd arch/arm/boot/dts/
$ ls *imx6ull*.dts
結(jié)果如下:

可以找到2個(gè)設(shè)備樹文件,我們只關(guān)心里面的LCD信息,打開任意一個(gè)看看:

3.2 修改設(shè)備樹
100ASK_IMX6ULL用的內(nèi)核版本是4.9.88,版本高一點(diǎn),但是IMX6ULL設(shè)備樹的寫法完全一樣。
設(shè)備樹文件是arch/arm/boot/dts/100ask_imx6ull-14x14.dts,替換下圖紅框部分:

修改好設(shè)備樹后,就可以編譯了。
為方便你們操作,下面貼出編譯命令,假設(shè)你已經(jīng)位于我們提供的內(nèi)核源碼目錄中:
$ export ?ARCH=arm $ export ?CROSS_COMPILE=arm-linux-gnueabihf- $ export PATH=$PATH:/home/book/100ask_imx6ull-sdk/ToolChain/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin $ make ?dtbs
新編譯好的設(shè)備樹文件為:arch/arm/boot/dts/100ask_imx6ull-14x14.dtb。
怎么更新設(shè)備樹?請(qǐng)看我們的開發(fā)板使用手冊(cè)。
更新設(shè)備樹后,重啟板子觀察效果。
3.3 完善驅(qū)動(dòng)
使用新的設(shè)備樹啟動(dòng)板子后,你會(huì)發(fā)現(xiàn)一個(gè)神奇的現(xiàn)象:LCD有時(shí)候有顯示,有時(shí)候沒(méi)有,不斷地冷啟動(dòng)偶爾會(huì)有顯示。
如果你經(jīng)驗(yàn)豐富,可以判斷這是復(fù)位問(wèn)題。
為驗(yàn)證是否復(fù)位問(wèn)題,我們可以執(zhí)行命令手工發(fā)出復(fù)位信號(hào),先確定LCD復(fù)位引腳是哪個(gè)GPIO:

從上圖可以確定LCD的復(fù)位引腳用到GPIO3_IO04,那我們可以使用GPIO子系統(tǒng)來(lái)驗(yàn)證。
執(zhí)行某些命令讓GPIO輸出低電平,再輸出高電平,這樣就可以復(fù)位LCD了。
3.3.1 使用GPIO子系統(tǒng)復(fù)位LCD
GPIO3_IO04在GPIO子系統(tǒng)中編號(hào)為:(3-1)*32+4=68,它是第68號(hào)GPIO。
板子進(jìn)入Linux后,執(zhí)行以下命令:
$ fb-test // LCD上應(yīng)該顯示紅綠藍(lán)色塊
$ echo 68 > /sys/class/gpio/export // 導(dǎo)出68號(hào)GPIO
$ echo out > /sys/class/gpio/gpio68/direction // 設(shè)置為輸出引腳
$ echo 0 > /sys/class/gpio/gpio68/value // 讓它輸出0
$ echo 1 > /sys/class/gpio/gpio68/value // 讓它輸出1
$ echo 68 > /sys/class/gpio/unexport // unexport
你會(huì)發(fā)現(xiàn)一旦執(zhí)行上述命令,LCD立刻就有顯示了。
所以,LCD驅(qū)動(dòng)不完善,應(yīng)該加上復(fù)位信號(hào)。
3.3.2 修改設(shè)備樹:指定復(fù)位引腳
設(shè)備樹文件為:arch/arm/boot/dts/100ask_imx6ull-14x14.dts
如下圖修改:

把添加的代碼寫出來(lái):
reset-gpios = <&gpio3 4 GPIO_ACTIVE_LOW>; /* 100ask */
3.3.3 修改驅(qū)動(dòng):復(fù)位LCD
LCD驅(qū)動(dòng)程序是哪個(gè)?
在Linux內(nèi)核源碼目錄下執(zhí)行命令:
$ ls drivers/video/fbdev/*.o
drivers/video/fbdev/built-in.o drivers/video/fbdev/mx3fb.o drivers/video/fbdev/mxsfb.o
發(fā)現(xiàn)有2個(gè).o文件:mx3fb.o、mxsfb.o。我們是imx6ull,應(yīng)該是后者。
我們?cè)趍xsfb.c中mxsfb_probe函數(shù)的后面添加復(fù)位代碼,如下圖修改:

為了方便讀者復(fù)制代碼,我把添加的代碼寫出來(lái)(在mxsfb.c中mxsfb_probe函數(shù)的后面添加復(fù)位代碼,):
/* 100ask */
printk("100ask, %s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
rst_gpio = of_get_named_gpio(pdev->dev.of_node, "reset-gpios", 0);
if (gpio_is_valid(rst_gpio)) {
ret = gpio_request(rst_gpio, "lcdif_rst");
if (ret < 0) {
dev_err(&pdev->dev,
"Failed to request GPIO:%d, ERRNO:%d\n",
(s32)rst_gpio, ret);
} else {
gpio_direction_output(rst_gpio, 0);
msleep(2);
gpio_direction_output(rst_gpio, 1);
dev_info(&pdev->dev, "Success seset LCDIF\n");
}
}
修改完后,重新編譯得到zImage和100ask_imx6ull-14x14.dtb,更新開發(fā)板,重啟,完美!
4. 移植觸摸屏驅(qū)動(dòng)
4.1 確定觸摸屏型號(hào)
還是那句話,如果有觸摸屏數(shù)據(jù)手冊(cè),看手冊(cè)就好了。
如果沒(méi)有手冊(cè),怎么辦?
觸摸屏的主控芯片一般都是I2C接口的,那么我們可以把屏接到板子上,用i2cdetect檢測(cè)出I2C設(shè)備的地址,根據(jù)地址就可以知道它的型號(hào)。
注意:100ASK_IMX6ULL不能直接連接其他廠家的屏,需要轉(zhuǎn)接板。
接上屏幕后,啟動(dòng)開發(fā)板進(jìn)入Linux,執(zhí)行如下命令:
[root@imx6ull:~]# i2cdetect -y 1
命令解析:“-y”表示 Disable interactive mode,簡(jiǎn)單地說(shuō)就是“別讓我確認(rèn)了,趕緊執(zhí)行”;“1”表示I2C總線1(從0開始)。
結(jié)果如下:

上圖中,
“--”表示沒(méi)有這個(gè)地址對(duì)應(yīng)的I2C設(shè)備;
“UU”表示這個(gè)地址的I2C設(shè)備已經(jīng)有驅(qū)動(dòng)在使用占用它了,那這個(gè)I2C設(shè)備肯定是存在的;
其他數(shù)值表示該地址對(duì)應(yīng)的I2C設(shè)備是存在的,并且還沒(méi)有驅(qū)動(dòng)程序跟它匹配。
根據(jù)上圖,我們可以知道0x38就是觸摸屏設(shè)備,為什么!為什么不是0x60?你可以把屏幕取下,再重新執(zhí)行命令,就可以看到“38”消失了。
根據(jù)0x38,我們得找到對(duì)應(yīng)的芯片型號(hào),怎么找?去內(nèi)核設(shè)備樹目錄里找。
$ cd arch/arm/boot/dts/
$ grep "@38" * -nR
可以得到很多結(jié)果,比如:

地址為0x38的I2C芯片有不少,比如HDMI PHY,還有ft5306、ft5x06。你在百度搜一下“ft5306”,它確實(shí)就是觸摸屏芯片。所以這款觸摸屏的主控芯片就是ft5x06。x表示某些數(shù)字,可能有多個(gè)型號(hào),我們暫時(shí)沒(méi)不用去細(xì)分。
4.2 在設(shè)備樹中指定觸摸IC信息
IMX6ULL跟觸摸IC的連接圖如下:

所以,我們要確定的信息是:
a. 它接在哪個(gè)I2C控制器上?
b. 它的I2C地址是?
c. 復(fù)位引腳使用哪個(gè)GPIO?低電平有效還是高電平有效?
d. 中斷引腳使用哪個(gè)GPIO?低電平有效還是高電平有效?
不知道怎么寫?沒(méi)關(guān)系,參考!
a. 對(duì)于ft5x06,設(shè)備樹節(jié)點(diǎn)中有哪些內(nèi)容?
b. 那些內(nèi)容怎么適配100ASM_IMX6ULL板子?即怎么改成100ASK_IMX6ULL所用的GPIO引腳
前面說(shuō)過(guò),根據(jù)I2C設(shè)備的地址0x38,執(zhí)行如下命令:
$ cd arch/arm/boot/dts/
$ grep "@38" * -nR
我們可以得到很多結(jié)果,打開跟imx6ull最相近的imx6ul-tx6ul.dtsi,可以看到如下代碼:

我們把這個(gè)結(jié)點(diǎn)的內(nèi)容先復(fù)制下來(lái),粘貼到哪里去?
100ASK_IMX6ULL也配有觸摸屏,我們用的型號(hào)是gt9xx,把這個(gè)結(jié)點(diǎn)放到gt9xx結(jié)點(diǎn)相同位置去就可以了,如下圖所示:

100ASK_IMX6ULL接標(biāo)配的LCD時(shí),觸摸IC是gt9xx,用的引腳假設(shè)是 AAA;
那么同一個(gè)底板接上另一塊LCD時(shí),雖然觸摸IC型號(hào)不同,但是它仍然用的是同一個(gè)引腳AAA。
所以,新加的節(jié)點(diǎn),其內(nèi)容可以參考gt9xx節(jié)點(diǎn)的內(nèi)容。
下圖就是改好的樣子:

重新編譯設(shè)備樹,更新到板子上,發(fā)現(xiàn)觸摸屏還是不能用。
這還得往內(nèi)核里加驅(qū)動(dòng)。
4.3 重新配置內(nèi)核添加驅(qū)動(dòng)
這設(shè)備節(jié)點(diǎn)對(duì)應(yīng)哪個(gè)驅(qū)動(dòng)啊?它有這個(gè)屬性:
compatible = "edt,edt-ft5x06"
在內(nèi)核drivers/input/touchscreen目錄下搜搜"edt,edt-ft5x06":
$ cd drivers/input/touchscreen/
$ grep "edt,edt-ft5x06" * -nr
什么都沒(méi)搜到,再搜“edt-ft5x06”:
$ grep "edt-ft5x06" * -nr
edt-ft5x06.c:1071: { .name = "edt-ft5x06", .driver_data = (long)&edt_ft5x06_data },
Kconfig:667: module will be called edt-ft5x06.
Makefile:31:obj-$(CONFIG_TOUCHSCREEN_EDT_FT5X06) += edt-ft5x06.o
顯然,驅(qū)動(dòng)程序是edt-ft5x06.c,內(nèi)核配置項(xiàng)是CONFIG_TOUCHSCREEN_EDT_FT5X06。
我們需要配置內(nèi)核,把CONFIG_TOUCHSCREEN_EDT_FT5X06配置為y。
在內(nèi)核目錄下執(zhí)行“make menuconfig”,然后搜“CONFIG_TOUCHSCREEN_EDT_FT5X06”:

在菜單里找到它,把它配置為y,如下圖:

重新編譯內(nèi)核zImage,更新到板子上,啟動(dòng)。
發(fā)現(xiàn)觸摸屏有反應(yīng),但是點(diǎn)不準(zhǔn),還得調(diào)試。
4.4 調(diào)試:找出問(wèn)題
Tslib是觸摸屏的庫(kù),自帶有很多工具:
a. ts_print_raw :打印觸摸屏原始數(shù)據(jù)
b. ts_print :打印經(jīng)過(guò)較準(zhǔn)的數(shù)據(jù)
c. ts_test_mt:測(cè)試電容屏,點(diǎn)擊觸摸屏,同時(shí)就會(huì)在LCD上顯示觸點(diǎn)位置。
我們先把系統(tǒng)自帶的QT系統(tǒng)去掉,在開發(fā)板執(zhí)行:
# mv /etc/init.d/S07hmi /root/
# reboot
然后設(shè)置環(huán)境變量,執(zhí)行ts_test_mt:
export TSLIB_TSDEVICE=/dev/input/event1
export TSLIB_CONFFILE=/etc/ts.conf
export TSLIB_CALIBFILE=/etc/pointercal
export TSLIB_PLUGINDIR=/usr/lib/ts
ts_test_mt
可以在LCD屏幕上看到提示,你點(diǎn)擊某個(gè)位置,正常的話在該位置就會(huì)顯示一個(gè)標(biāo)號(hào)。
我們發(fā)現(xiàn)有意思的現(xiàn)象:從左往右點(diǎn),標(biāo)號(hào)從上邊移動(dòng)到下邊;從上往下點(diǎn),標(biāo)號(hào)從左邊移動(dòng)到右邊。
猜測(cè):XY坐標(biāo)對(duì)調(diào)了。
再試一下,執(zhí)行 ts_print_raw,然后從左往右點(diǎn),現(xiàn)象如下:

從左往右點(diǎn),x坐標(biāo)應(yīng)該發(fā)生變化,y坐標(biāo)保持不變;但是從上圖看來(lái),這是相反的。
所以,確實(shí)是xy坐標(biāo)對(duì)調(diào)了。
4.5 解決方法
可以從應(yīng)用層面(比如修改設(shè)備樹)解決,也可以從驅(qū)動(dòng)層面(比如修改配置文件/etc/ts.conf)解決,二種方法任選其一,不要同時(shí)做。
4.5.1 修改/etc/ts.conf
如下圖加上xyswap就可以了:

4.5.2 修改設(shè)備樹
有時(shí)候我們并不愿意、不能修改應(yīng)用層的東西,那可以修改設(shè)備樹:

4.6 其他情況
100ASK_IMX6ULL標(biāo)配的屏,帶的觸摸IC是gt9xx;但是我們發(fā)現(xiàn)別家的LCD即使同樣使用gt9xx,但是它的xy值是反轉(zhuǎn)的。
什么意思呢?
你從左往右點(diǎn),正常來(lái)說(shuō)x值是從小變大,但是有些屏是從大變小。
你從上往下點(diǎn),正常來(lái)說(shuō)y值是從小變大,但是有些屏是從大變小。
這時(shí)候,你同樣可以修改設(shè)備樹,或是修改/etc/ts.conf。
怎么修改設(shè)備樹?
參考內(nèi)核文檔:Documentation/devicetree/bindings/input/touchscreen,該目錄下有很多I2C觸摸芯片的設(shè)備樹說(shuō)明,比如有g(shù)oodix.txt,對(duì)應(yīng)gt9xx芯片;有edt-ft5x06.txt。
要讓x反轉(zhuǎn),或是y反轉(zhuǎn),在設(shè)備節(jié)點(diǎn)中加入這樣的屬性值就可以:
touchscreen-inverted-x = <1>;
touchscreen-inverted-y = <1>;
有時(shí)為了測(cè)試方便,就是想臨時(shí)改一下/etc/ts.conf,怎么做?
這個(gè)文件本身是有些注釋的,可以參考:
“x0=1024”的意思就是:x坐標(biāo),0表示1024;
“y0=600”的意思是:y坐標(biāo),0表示600。
4.7 gt9xx芯片固件更新
gt9xx芯片功能強(qiáng)大,可以寫入配置信息讓它支持不同分辨率的觸摸屏。
但是出廠的觸摸屏IC一般都已經(jīng)寫好配置信息了,我們不應(yīng)該讓驅(qū)動(dòng)程序去修改這些配置信息。
可以在設(shè)備樹中加上這一句,禁止驅(qū)動(dòng)去修改配置信息:
goodix,driver-send-cfg = <0>;
這是我們調(diào)試過(guò)程中碰到的一個(gè)坑。

我是韋東山,希望我的分享能給你帶來(lái)幫助,歡迎訂閱我的付費(fèi)視頻:http://100ask.taobao.com