i.MX6ULL嵌入式Linux開(kāi)發(fā)2-uboot移植實(shí)踐

上篇文章,我們介紹了如何使用NXP原廠的uboot進(jìn)行編譯和燒寫,將uboot運(yùn)行在自己的開(kāi)發(fā)板上。NXP原廠的uboot,直接燒錄到我的開(kāi)發(fā)板中,LCD的驅(qū)動(dòng)是不正常的,需要進(jìn)行修改。本篇我們就來(lái)繼續(xù)研究uboot,使得uboot能匹配我們自己的開(kāi)發(fā)板。
修改uboot以匹配開(kāi)發(fā)板的方式有兩種,一種是在NXP原廠開(kāi)發(fā)板i.MX 6ULL EVK的文件上進(jìn)行修改,另一種仿造NXP的開(kāi)發(fā)板文件,添加自己的開(kāi)發(fā)板文件。
為了能更多的了解uboot,我們使用代碼改動(dòng)較大的第二種方式進(jìn)行uboot的移植。
在修改uboot之前,先來(lái)看一下uboot的源碼結(jié)構(gòu)。
1 uboot源碼結(jié)構(gòu)分析
uboot的源碼如下,這里是源碼編譯后的結(jié)果,包含編譯后的文件。

這里文件的含義如下:

2 uboot移植實(shí)踐
2.1 添加開(kāi)發(fā)板配置文件
首先是創(chuàng)建自己開(kāi)發(fā)板的配置文件,該文件可參考原廠開(kāi)發(fā)板的配置文件,在configs
文件夾下,將原來(lái)的默認(rèn)配置文件mx6ull_14x14_evk_emmc_defconfig
復(fù)制一份,并重命名為mx6ull_myboard_defconfig
,該文件即用于作為自己開(kāi)發(fā)板的配置文件。
然后進(jìn)行內(nèi)容修改,將原始內(nèi)容:
修改為:

2.2 添加開(kāi)發(fā)板對(duì)應(yīng)的頭文件
在目錄 include/configs
下添加自己開(kāi)發(fā)板對(duì)應(yīng)的頭文件,復(fù)制mx6ullevk.h
,并重命名為mx6ull_myboard.h
,將文件中的
修改為:

該文件里面有很多宏定義,這些宏定義基本用于配置uboot,如果我們自己要想使能或者禁止uboot的某些功能,那就要在這里面修改。
在ubuntu中,可以安裝VS Code軟件來(lái)輔助查看代碼,在ubuntu中安裝vscode,需要先下載deb格式的安裝包,然后使用類似如下的指令即可進(jìn)行安裝:
sudo dpkg -i code_1.58.0-1625728071_amd64.deb安裝完之后,我們可以將圖標(biāo)添加到ubuntu桌面上,ubuntu安裝的所有軟件圖標(biāo)都在目錄
/usr/share/applications
中,找到 Visual Studio Code 的圖標(biāo),然后點(diǎn)擊鼠標(biāo)右鍵,選擇復(fù)制到->桌面即可。
2.3 添加開(kāi)發(fā)板對(duì)應(yīng)的板級(jí)文件夾
uboot中每個(gè)板子都有一個(gè)對(duì)應(yīng)的文件夾來(lái)存放板級(jí)文件(如開(kāi)發(fā)板上外設(shè)驅(qū)動(dòng)文件等)。NXP的I.MX系列芯片的所有板級(jí)文件夾都存放在 board/freescale/
目錄下,在這個(gè)目錄下有個(gè)名為mx6ullevk
的文件夾,原廠開(kāi)發(fā)板的板級(jí)文件夾。
復(fù)制 mx6ullevk,將其重命名為mx6ull_myboard
,進(jìn)入mx6ull_myboard
目錄中, 將其中的mx6ullevk.c
文件重命名為mx6ull_myboard.c
。
2.3.1 修改Makefile文件
首先是修改 board/freescale/mx6ull_myboard 目錄下的Makefile
文件
將原始內(nèi)容:
其中的依賴項(xiàng)修改為:

這樣才會(huì)編譯mx6ull_myboard.c
這個(gè)文件。
2.3.2 修改imximage.cfg文件
然后修改 board/freescale/mx6ull_myboard 目錄下的imximage.cfg
文件
將imximage.cfg
中的下面一句:
改為:

2.3.3 修改Kconfig文件
接著修改 board/freescale/mx6ull_myboard 目錄下的Kconfig
文件
將原始內(nèi)容:
修改為:

2.3.4 修改MAINTAINERS文件
再接著修改 board/freescale/mx6ull_myboard 目錄下的MAINTAINERS
文件
將原始內(nèi)容:
修改為:

2.3.5 重命名板子的c文件
將 board/freescale/mx6ull_myboard 目錄下原來(lái)的mx6ullevk.c
重命名為mx6ull_myboard.c

2.4 修改U-Boot圖形界面配置文件
最后修改arch/arm/cpu/armv7/mx6/
目錄下的Kconfig
文件
注意這里的Kconfig和
board/freescale/mx6ull_myboard
目錄下的Kconfig是不一樣的。
在207行插入一些內(nèi)容:

然后,在最后一行的endif
的前一行添加如下內(nèi)容:

2.5 創(chuàng)建編譯腳本
在uboot-imx-rel_imx_4.1.15_2.1.0_ga目錄下新建一個(gè)名為build_myboard.sh
的 shell 腳本,寫入如下內(nèi)容:
至此,以上完成的工作,相當(dāng)于將NXP原廠開(kāi)發(fā)板相關(guān)的配置文件,重新復(fù)制了一份,并對(duì)板子名稱修改為了自己板子的名字。
此時(shí)執(zhí)行./build_myboard.sh
,等待編譯完成后輸入如下命令:
如果有很多文件都引用了這個(gè)頭文件, 那就說(shuō)明新板子添加成功:

將uboot進(jìn)行編譯并運(yùn)行,實(shí)際的效果應(yīng)該和原廠uboot的效果一樣(LCD無(wú)法顯示)。

總結(jié)一下剛才都有哪些修改:
右端灰色的為原廠開(kāi)發(fā)板的相關(guān)文件,黃色的為模仿原廠文件,新添加并修改的自己開(kāi)發(fā)板的文件。

下面進(jìn)行LCD驅(qū)動(dòng)的修改。
3 LCD驅(qū)動(dòng)的修改
一般uboot中修改驅(qū)動(dòng)都是在對(duì)應(yīng)板子c文件和h文件,即board/freescale/mx6ull_myboard/mx6ull_myboard.c
和 include/configs/mx6ull_myboard.h
這兩個(gè)文件。
?一般修改 LCD 驅(qū)動(dòng)重點(diǎn)注意以下幾點(diǎn):
LCD 所使用的 GPIO,查看 uboot 中 LCD 的 IO 配置是否正確
LCD 背光引腳 GPIO 的配置
LCD 配置參數(shù)是否正確
正點(diǎn)原子以及野火的I.MX6ULL開(kāi)發(fā)板的LCD原理圖和NXP官方的開(kāi)發(fā)板一致,也就是LCD的IO和背光IO都是一樣的, 所以IO部分就不用修改了,只需修改之后的LCD參數(shù)。
3.1 修改c文件配置
打開(kāi)文件 mx6ull_myboard.c
,需要修改下面這段內(nèi)容:
先來(lái)分析一下這段代碼,該代碼定義了一個(gè)變量displays
,類型為display_info_t
,這個(gè)結(jié)構(gòu)體是LCD信息結(jié)構(gòu)體,其中包括了LCD的分辨率,像素格式,LCD的各個(gè)參數(shù)等。
display_info_t
定義在文件 ?arch/arm/include/asm/imx-common/video.h ?中,定義如下:
這里的pixfmt
是像素格式,也就是一個(gè)像素點(diǎn)是多少位,如果是RGB565的話就是16位,如果是RGB888的話就是24位,一般使用 RGB888。
結(jié)構(gòu)體display_info_t
還有個(gè)mode
成員變量,此成員變量也是個(gè)結(jié)構(gòu)體,為fb_videomode
,定義在文件 include/linux/fb.h
中,定義如下:
結(jié)構(gòu)體b_videomode
里面的成員變量為L(zhǎng)CD的參數(shù),這些成員變量函數(shù)如下:
name
:LCD 名字,要和環(huán)境變量中的 panel 相等xres 、yres
:LCD X 軸和 Y 軸像素?cái)?shù)量pixclock
:像素時(shí)鐘,每個(gè)像素時(shí)鐘周期的長(zhǎng)度,單位為皮秒left_margin
:HBP(horizontal back porch),水平同步后肩right_margin
:HFP(horizontal front porch),水平同步前肩upper_margin
:VBP(vertical back porch),垂直同步后肩lower_margin
:VFP(vertical front porch),垂直同步前肩hsync_len
:HSPW(horizontal sync pulse width),行同步脈寬vsync_len
:VSPW(vertical sync pulse width),垂直同步脈寬vmode
:大多數(shù)使用 FB_VMODE_NONINTERLACED,也就是不使用隔行掃描。
野火的7寸RGB屏幕(GT911,800x480)的一些參數(shù)如下:
參數(shù)值width800height480HBP46HFP22VBP23VFP22HSW1VSW1
注意像素時(shí)鐘pixclock
的計(jì)算方法:以野火的 7 寸RGB屏為例,屏幕要求的像素時(shí)鐘為27.4MHz,因此:pixclock=(1/27400000)*10^12=36496
像素時(shí)鐘就是 RGB LCD 的時(shí)鐘信號(hào),以 GT911這款屏幕為例,顯示一幀圖像所需要的時(shí)鐘數(shù)就是: ? ? ?(VSPW+VBP+LINE+VFP) * (HSPW + HBP + HOZVAL + HFP) ?= (1 + 23 + 480+ 22) * (1+ 46+ 800+ 22) ? = 526* 869 = 457094。 ?顯示一幀圖像需要457094個(gè)時(shí)鐘數(shù), 那么顯示60幀就是: 457094* 60 = 27425640≈27.4M,所以像素時(shí)鐘就是27.4MHz
由以上的屏幕參數(shù),可以得出GT911屏幕的配置參數(shù)如下:
3.2 修改h文件配置
另外還要修改include/configs/
路徑下的mx6ull_myboard.h
,找到所有如下語(yǔ)句:
修改為:
修改完成以后重新編譯一遍 uboot 并燒寫到 SD 中啟動(dòng)。
3.3 編譯測(cè)試
將修改后的uboot編譯下載以后,LCD 驅(qū)動(dòng)一般就會(huì)工作正常了,LCD 上會(huì)顯示 NXP 的 logo。

但某些情況有可能還會(huì)遇到LCD 并沒(méi)有工作,還是黑屏,這是什么原因呢?
在 uboot 命令模式輸入“print
”來(lái)查看環(huán)境變量 panel 的值,會(huì)發(fā)現(xiàn)panel的值要是TFT43AB(或其他的,反正不是GT911):
這是因?yàn)橹坝袑h(huán)境變量保存到EMMC中,uboot啟動(dòng)以后會(huì)先從EMMC中讀取環(huán)境變量,如果EMMC中沒(méi)有環(huán)境變量的話才會(huì)使用 mx6ull_alientek_emmc.h 中的默認(rèn)環(huán)境變量。
如果EMMC中的環(huán)境變量panel不等于GT911,那么LCD顯示肯定不正常,我們只需要在uboot中修改panel的值為GT911即可,在uboot的命令模式下輸入如下命令:
上述命令修改環(huán)境變量panel為GT911并保存后,按下復(fù)位鍵重啟uboot,此時(shí) LCD 驅(qū)動(dòng)就工作正常了。
4 網(wǎng)絡(luò)測(cè)試
I.MX6ULL內(nèi)部有個(gè)以太網(wǎng)MAC外設(shè),也就是ENET,需要外接一個(gè)PHY芯片來(lái)實(shí)現(xiàn)網(wǎng)絡(luò)通信功能,也就是內(nèi)部MAC+外部PHY芯片的方案。 I.MX6ULL有兩個(gè)網(wǎng)絡(luò)接口ENET1和ENET2,野火的開(kāi)發(fā)板提供了這兩個(gè)網(wǎng)絡(luò)接口,其中ENET1和ENET2都使用是和原廠開(kāi)發(fā)板一樣的KSZ8081
作為PHY芯片。
因此,網(wǎng)絡(luò)驅(qū)動(dòng)部分的uboot不需要修改,下面就只是來(lái)測(cè)試一下網(wǎng)路功能。
4.1 連接網(wǎng)線并查看啟動(dòng)情況
首先將開(kāi)發(fā)板通過(guò)網(wǎng)線連接到局域網(wǎng)的路由器中(自己的電腦也要在同一個(gè)局域網(wǎng),這樣ubuntu虛擬機(jī)則也在同一個(gè)局域網(wǎng))。

然后啟動(dòng)uboot,串口查看相關(guān)的打印信息,如下圖,可以看到網(wǎng)絡(luò)端口的FEC1(注意是uboot程序中默認(rèn)設(shè)置的,不是因?yàn)榫W(wǎng)線插在了左邊就自動(dòng)識(shí)別FEC1),但是提示網(wǎng)絡(luò)地址未設(shè)置。

4.2 設(shè)置網(wǎng)絡(luò)參數(shù)
下面就來(lái)設(shè)置一下,首先是設(shè)置開(kāi)發(fā)板的IP,在設(shè)置之前,先借助Windows電腦的cmd的ping+ip
指令來(lái)測(cè)試某個(gè)IP是否被使用,如我的192.168.5.102
未被使用,就可以設(shè)為開(kāi)發(fā)板的IP。

除了設(shè)置開(kāi)發(fā)板的IP,還要設(shè)置一些其它的網(wǎng)絡(luò)參數(shù),具體如下:
開(kāi)發(fā)板的MAC地址是一個(gè)長(zhǎng)度為48位(6個(gè)字節(jié))的地址,每個(gè)字節(jié)間通過(guò)冒號(hào)間隔,理論上只要局域網(wǎng)內(nèi)各網(wǎng)絡(luò)設(shè)備不沖突,該地址可任意設(shè)置。
局域網(wǎng)的默認(rèn)網(wǎng)關(guān)和子網(wǎng)掩碼需要根據(jù)自己的實(shí)際情況設(shè)置(不知道是多少的,可以借助Windows電腦的cmd中的ipconfig
指令來(lái)查看)
服務(wù)器的地址就是ubuntu虛擬機(jī)的地址(可以通過(guò)linux的ifconfig
指令來(lái)查看)
4.3 測(cè)試另一個(gè)網(wǎng)口
打開(kāi) include/configs/mx6ull_alientek_emmc.h ,將CONFIG_FEC_ENET_DEV
修改為 0, 重新編譯uboot并燒寫到SD卡中。

將網(wǎng)線連接到開(kāi)發(fā)板右邊的網(wǎng)口上,按照之前的測(cè)試方法再次測(cè)試:

5 uboot啟動(dòng)Linux內(nèi)核測(cè)試
uboot的最終目的就是啟動(dòng)Linux內(nèi)核,所以需要通過(guò)啟動(dòng)Linux內(nèi)核來(lái)判斷uboot移植是否成功。
啟動(dòng)Linux內(nèi)核。我們測(cè)試兩種啟動(dòng)Linux內(nèi)核的方法:
從EMMC啟動(dòng)
從網(wǎng)絡(luò)啟動(dòng)
從EMMC啟動(dòng)也就是將編譯出來(lái)的Linux鏡像文件zImage和設(shè)備樹(shù)文件保存在EMMC中,uboot從EMMC中讀這兩個(gè)文件并啟動(dòng)。 由于我們板子的EMMC中可能還沒(méi)有l(wèi)inux鏡像文件和設(shè)備樹(shù)文件,所以先不測(cè)試這種方法。
從網(wǎng)絡(luò)啟動(dòng),是指將linux鏡像文件和根文件系統(tǒng)都放到Ubuntu下某個(gè)指定的文件夾中,然后通過(guò)nfs或者tftp等傳輸方式將系統(tǒng)文件(zImage和設(shè)備樹(shù)文件)從Ubuntu中直接下載到開(kāi)發(fā)板的內(nèi)存中,EMMC中則不需要有系統(tǒng)文件。這種方式的作用就是方便調(diào)試,免去將代碼固化到開(kāi)發(fā)板的過(guò)程。當(dāng)然,當(dāng)開(kāi)發(fā)板掉電,內(nèi)存的系統(tǒng)文件就沒(méi)了。
下面就來(lái)通過(guò)網(wǎng)絡(luò)調(diào)試的方法來(lái)測(cè)試uboot是否能正常啟動(dòng)Linux內(nèi)核。
在測(cè)試之前,先來(lái)介紹一下在ubuntu虛擬機(jī)上如何搭建tftp來(lái)傳輸文件。
5.1 tftp服務(wù)搭建
Ubuntu上搭建TFTP服務(wù)器,需要安裝tftp-hpa
和tftpd-hpa
,命令如下:
TFTP也需要一個(gè)文件夾來(lái)存放文件,在用戶目錄下新建一個(gè)目錄,示例命令如下:
最后配置 tftp, 安裝完成以后,新建文件/etc/xinetd.d/tftp
, 如果沒(méi)有/etc/xinetd.d 目錄的話自行創(chuàng)建,然后在里面輸入如下內(nèi)容:
完了以后啟動(dòng)tftp服務(wù),命令如下:
打開(kāi)/etc/default/tftpd-hpa
文件,將其修改為如下所示內(nèi)容:
TFTP_DIRECTORY
就是我們上面創(chuàng)建的tftp文件夾目錄,以后我們就將所有需要通過(guò)TFTP傳輸?shù)奈募挤诺竭@個(gè)文件夾里面,并且要給予這些文件相應(yīng)的權(quán)限。
最后輸入如下命令, 重啟 tftp 服務(wù)器:
至此,tftp服務(wù)器已經(jīng)搭建好了,可以先來(lái)測(cè)試一下功能是否正常。
5.2 tftp文件傳輸測(cè)試
測(cè)試tftp功能是否正常,主要分為兩步:
首先是將某個(gè)zImage鏡像文件拷貝到ubuntu虛擬機(jī)的tftpboot文件夾中,并且給予 zImage 相應(yīng)777的權(quán)限。
然后是通過(guò)開(kāi)發(fā)板uboot的串口交互指令將文件從ubuntu傳輸?shù)介_(kāi)發(fā)板的內(nèi)存。
uboot串口交互指令中的tftp命令格式如下:
loadAddress
是文件在DRAM中的存放地址,[[hostIPaddr:]bootfilename]
是要從Ubuntu中下載的文件。
tftp傳輸文件,不需要輸入文件在Ubuntu中的完整路徑,只需要輸入文件名即可。
比如我們現(xiàn)在將tftpboot文件夾里面的zImage文件下載到開(kāi)發(fā)板DRAM的0X80800000地址處,命令如下:
注:此次測(cè)試時(shí),我的ubuntu虛擬機(jī)(作為tftp服務(wù)器)的IP變了,所以我又重新設(shè)置了ubuntu的IP
5.3 測(cè)試從網(wǎng)絡(luò)啟動(dòng)Linux
設(shè)置環(huán)境變量
這兩個(gè)環(huán)境變量的具體含義先不展開(kāi)討論。
通過(guò)tftp將zImage和設(shè)備樹(shù)下載到板子的RAM中
就是通過(guò)網(wǎng)路的方式(tftp)將系統(tǒng)文件下載到板子的內(nèi)存中,這里使用的野火提供的yocto的zImage和dtb文件,將兩個(gè)文件輔助到ubuntu的tftp服務(wù)器目錄,依次輸入如下指令:
啟動(dòng)內(nèi)核
可以看到Starting kernel ...的字樣,表示內(nèi)核已經(jīng)啟動(dòng)。
再看看下板子,已經(jīng)有啟動(dòng)畫面了:

在過(guò)一會(huì)兒,會(huì)出現(xiàn)系統(tǒng)的圖形界面,只是現(xiàn)在還不能操作,觸摸沒(méi)反應(yīng)。
