【i.MX6ULL】驅(qū)動開發(fā)11——LCD驅(qū)動實踐

1 知識點
1.1 Framebuffer
Framebuffer直譯即幀緩沖,簡稱 fb,它是Linux將系統(tǒng)中所有跟顯示有關(guān)的硬件以及軟件集合起來,將底層的LCD虛擬抽象出一 個/dev/fbX設(shè)備,應(yīng)用程序可以通過操作/dev/fbX來實現(xiàn)對屏幕的顯示控制。
NXP官方Linux內(nèi)核已默認(rèn)開啟了LCD驅(qū)動,在dev/目錄下可以看到fb0這樣一個設(shè)備

Framebuffer在內(nèi)核中的表現(xiàn)就是fb_info結(jié)構(gòu)體:

完整的結(jié)構(gòu)體定義如下:
注意結(jié)構(gòu)體中的fb_fops這一項,/dev/fb0 是個字符設(shè)備,fb_fops就是它的文件操作結(jié)構(gòu)體,它的file_operations操作集在drivers/video/fbdev/core/fbmem.c 文件中:

可以看到有熟悉的open、release等函數(shù)接口。
因此,LCD驅(qū)動的重點就是初始化fb_info里面的各個成員。
fb_info結(jié)構(gòu)體的成員變量很多,需要重點關(guān)注的是這幾個:
var:當(dāng)前的可變參數(shù)
fix:當(dāng)前的固定參數(shù)
fbops:幀緩沖操作函數(shù)集
screen_base:虛擬內(nèi)存基地址(屏幕顯存)
screen_size:虛擬內(nèi)存大小(屏幕顯存大小)
pseudo_palette:偽16位調(diào)色板
初始化完成fb_info后,通過register_framebuffer函數(shù)向內(nèi)核注冊剛剛初始化的fb_info。
1.2 LCD驅(qū)動文件mxsfb介紹
LCD的驅(qū)動文件為mxsfb.c,這是一種platform驅(qū)動框架,驅(qū)動和設(shè)備匹配之后,mxsfb_probe函數(shù)就會執(zhí)行。
LCD的初始化通過mxsfb_probe函數(shù)來實現(xiàn),該函數(shù)的主要功能有:
申請fb_info
初始化fb_info結(jié)構(gòu)體中的各個成員變量
初始化eLCDIF控制器
使用register_framebuffer函數(shù)向Linux內(nèi)核注冊初始化好的fb_info
該函數(shù)位于:/drivers/video/fbdev/mxsfb.c中

該函數(shù)的實現(xiàn)如下:
其中,register_framebuffer函數(shù)的原型如下:

函數(shù)參數(shù)和返回值含義:
fb_info:需上報的fb_info
返回值:0-成功,負(fù)值-失敗
1.3 LCD 驅(qū)動程序編寫
6ULL的eLCDIF接口驅(qū)動程序 NXP 已經(jīng)編 寫好了,因此 LCD 驅(qū)動部分我們不需要去修改。我們需要做的就是按照所使用的 LCD 來修改設(shè)備樹。
1.3.1 查看設(shè)備樹
1.3 先來看一下NXP官方編寫的Linux下的 LCD 驅(qū)動。打開 imx6ull.dtsi,然后找到 lcdif節(jié)點內(nèi)容:

其中021c8000 這個地址,可以從參考手冊中找到對應(yīng)的介紹:

1.3.2 屏幕IO配置
打開 imx6ull-myboard.dts 文件,在 iomuxc 節(jié)點中找到如下內(nèi)容:

具體為:
這里有3個節(jié)點:
子節(jié)點pinctrl_lcdif_dat ,為 RGB LCD 的 24根數(shù)據(jù)線配置項
子節(jié)點 pinctrl_lcdif_ctrl ,為RGB LCD 的 4根控制線配置項,包括 CLK、ENABLE、VSYNC 和 HSYNC
子節(jié)點 pinctrl_pwm1 ,為RGB LCD 的背光亮度配置項
1.3.3 屏幕參數(shù)配置
在imx6ull-myboard.dts 文件中找到lcdif 節(jié)點,根據(jù)自己使用的LCD,修改為對應(yīng)的參數(shù)。
下面是NXP官方板子的參數(shù):

我用的野火7寸屏(GT911,800x480),其參數(shù)為:

修改后的lcdif 節(jié)點如下:
1.3.4 屏幕背光配置
通過PWM信號來控制LCD屏幕背光的亮度
LCD 背光要用到PWM1,因此也要設(shè)置 PWM1 節(jié)點,在imx6ull.dtsi 文件中找到如下內(nèi)容:

這個節(jié)點信息不用修改,使用默認(rèn)的配置即可。如果要修改的話,也不要修改這里,可以通過imx6ull-myboard.dts文件中進行修改。
imx6ull-myboard.dts中的pwm1節(jié)點:
imx6ull-myboard.dts中的backlight節(jié)點:
2 實驗測試
2.1使能Linux logo顯示
uboot啟動的時候,LCD左上角上會顯示NXP的圖標(biāo),而Linux內(nèi)核啟動的時候,LCD左上角上會顯示一個小企鵝。因此,可以通過小企鵝logo的顯示來驗證LCD 驅(qū)動是否正常。
默認(rèn)情況下是已經(jīng)開啟logo顯示的,可以再確認(rèn)一下。
在Linux內(nèi)核源碼目錄,輸入以下指令打開內(nèi)核的圖形化配置:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
Linux內(nèi)核配置界面:

然后按下路徑找到對應(yīng)的配置項:
最終到達這個界面:

這三個選項分別對應(yīng)黑白、16 位、24 位色彩格式的 logo。
2.2 編譯設(shè)備樹
修改設(shè)備樹中的lcdif節(jié)點后(主要是修改屏幕的參數(shù)),在Linux內(nèi)核源碼目錄執(zhí)行下面的命令,重新編譯設(shè)備樹并拷貝到網(wǎng)絡(luò)啟動位置。
然后重啟開發(fā)板,就可以在Linux內(nèi)核驅(qū)動的時候看到屏幕上的企鵝圖標(biāo)了:

2.3 設(shè)置LCD作為終端控制臺
之前一直使用串口來顯示板子的啟動和調(diào)試信息,實際上可以設(shè)置 LCD 作為終端進行同步顯示:
2.3.1 設(shè)置uboot的bootargs
重啟開發(fā)板,在倒計時時按回充進入ubout,可以先看下之前的bootargs配置:

只需要在原來的基礎(chǔ)上再添加console=tty1
即可:
然后重啟開發(fā)板,在Linux內(nèi)核驅(qū)動的時候就可以在屏幕上看到輸出信息了:

對比一下串口輸出的信息,可以看出屏幕輸出到Freeing unused kernel memory: 400K (8090e000 - 80972000)
這句后就沒有了,沒有出現(xiàn)按下回車鍵繼續(xù)的提示,也沒有顯示開啟自啟動的hello word測試程序的打印,這是因為某些設(shè)置還未完成。

2.3.2 修改/etc/inittab文件
該修改用于設(shè)置屏幕作為終端進行交互。
打開根文件系統(tǒng)中的/etc/inittab 文件,加入下面這一行:

保存后重啟板子,并在板子的USB接口插上鍵盤,就可以通過鍵盤和板子交互了:

現(xiàn)在通過板子插入鍵盤,也可以在屏幕上操作板子了。
注意,之前設(shè)置的開機啟動的hello word程序的打印沒有出現(xiàn)在屏幕上,是因為printf的輸入沒有設(shè)置的LCD中,我們可以通過將輸出指向 /dev/tty1 來實現(xiàn)LCD屏幕的打印,比如測試屏幕輸出hello linux:

2.4 其它問題
2.4.1 自動熄屏的問題
當(dāng)沒有操作LCD屏幕一段時間后,屏幕會自動黑屏,這時可以通過接入鍵盤按下回車鍵進行喚醒(也可以通過板子的ON/OFF按鍵進行喚醒,因為該按鍵也被賦予了回車鍵的功能)。
這個時間是在Linux源碼的 drivers/tty/vt/vt.c中設(shè)置的,默認(rèn)是10分鐘(10*60秒)。

如果想讓屏幕一直亮著,可以將改值設(shè)為0,并重新編輯Linux內(nèi)核得到zImage,然后用新的zImage啟動開發(fā)板。
如果不想修改zImage,另外一種方式可以創(chuàng)建一個開機啟動的應(yīng)用程序來控制屏幕不熄滅, lcd_always_on.c
的內(nèi)容為:
在ubuntu中編譯該程序,然后將可執(zhí)行程序拷貝到板子的根文件系統(tǒng)中:

然后,/etc/init.d/rcS中設(shè)置該程序開機自啟動即可。

保存后,重啟開發(fā)板,屏幕就不會自動熄屏了。
2.4.2 屏幕亮度調(diào)節(jié)
屏幕的亮度也是可以調(diào)節(jié)的,設(shè)備樹中背光節(jié)點設(shè)置了8 個等級,可以在 0~7范圍內(nèi)進行亮度調(diào)節(jié),進入下面的目錄,可以查看當(dāng)前屏幕的亮度:
通過下面的指令可以實時修改屏幕的亮度,比如修改亮度為1:

總結(jié)
本篇介紹了LCD屏幕驅(qū)動相關(guān)知識并進行了實驗,因為NXP官方的板子和我這個板子的LCD引腳一樣,因此主要的修改就是將設(shè)備樹中的lcdif 節(jié)點的屏幕參數(shù)進行修改即可。
通過實驗,可以將企鵝logo顯示出來,并將板子的輸出信息定向到了LCD屏幕顯示,通過接入鍵盤可實現(xiàn)與Linux板子的交互。最后,還測試了屏幕熄屏和亮度調(diào)節(jié)功能。