姓名:鄧皓軒? 學(xué)號(hào):19020100151? 學(xué)院:丁香2號(hào)書院
轉(zhuǎn)自:https://yngzmiao.blog.csdn.net/article/details/90243257
【嵌牛導(dǎo)讀】嵌入式Linux系統(tǒng)移植
【嵌牛鼻子】介紹嵌入式Linux系統(tǒng)移植的要點(diǎn)
【嵌牛提問】怎樣進(jìn)行嵌入式Linux系統(tǒng)移植
BootLoader
BootLoader的概念
BootLoader就是在操作系統(tǒng)內(nèi)核運(yùn)行之前運(yùn)行的一段小程序。通過這段小程序,可以初始化硬件設(shè)備、建立內(nèi)存空間的映射圖,從而將系統(tǒng)的軟硬件環(huán)境帶到一個(gè)合適的狀態(tài),以便為最終調(diào)用操作系統(tǒng)內(nèi)核準(zhǔn)備好正確的環(huán)境,這就是所謂的引導(dǎo)加載程序(Boot Loader)。
在Flash存儲(chǔ)中存放文件的分布圖如下所示:

歸根結(jié)底,BootLoader的任務(wù)是引導(dǎo)操作系統(tǒng),所謂引導(dǎo)操作系統(tǒng),就是啟動(dòng)內(nèi)核,把內(nèi)核加載到內(nèi)存RAM中去運(yùn)行。
本文中,BootLoader的起始地址為0x20000000,內(nèi)核(uImage)的起始地址為0x20008000,根文件系統(tǒng)(initrd.img.gz)的起始地址為0x21000000。
BootLoader的分類
通常,BootLoader是嚴(yán)重地依賴于硬件而實(shí)現(xiàn)的,特別是在嵌入式中。因此,在嵌入式里建立一個(gè)通用的BootLoader幾乎是不可能的。因此,BootLoader的種類繁多,
可以看出,不同的bootloader具有不同的使用范圍。
其中最令人矚目的就是有一個(gè)叫U-Boot的BootLoader,是一個(gè)比較通用的引導(dǎo)程序,而且同時(shí)支持X86、ARM和PowerPC等多種處理器架構(gòu)。
U-Boot
U-Boot,全稱 Universal Boot Loader,是遵循GPL條款的開放源碼項(xiàng)目,是由德國DENX小組開發(fā)的用于多種嵌入式CPU的BootLoader程序,對于Linux的開發(fā),德國的u-boot做出了巨大的貢獻(xiàn),而且是開源的。
U-Boot具有以下特點(diǎn):
開放源碼;
支持多種嵌入式操作系統(tǒng)內(nèi)核,如Linux、NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS;
支持多個(gè)處理器系列,如PowerPC、ARM、x86、MIPS、XScale;
較高的可靠性和穩(wěn)定性;
高度靈活的功能設(shè)置,適合U-Boot調(diào)試、操作系統(tǒng)不同引導(dǎo)要求、產(chǎn)品發(fā)布等;
豐富的設(shè)備驅(qū)動(dòng)源碼,如串口、以太網(wǎng)、SDRAM、FLASH、LCD、NVRAM、EEPROM、RTC、鍵盤等;
較為豐富的開發(fā)調(diào)試文檔與強(qiáng)大的網(wǎng)絡(luò)技術(shù)支持;
其實(shí),把u-boot可以理解為是一個(gè)小型的操作系統(tǒng)。
U-Boot的常用命令
U-Boot的文件通過SD卡或者USB線可直接燒寫到Flash中,然后就可以進(jìn)行U-Boot的命令的執(zhí)行了。
U-Boot的基本命令
print:打印U-Boot中的環(huán)境變量(打印格式:變量名=變量值)
setenv:設(shè)置U-Boot中的環(huán)境變量,重啟后無效(設(shè)置格式:setenv 變量名 變量值;當(dāng)變量值為空的時(shí)候,表示刪除該環(huán)境變量)
saveenv:保存U-Boot中的環(huán)境變量,重啟后有效
md:內(nèi)存顯示,顯示特定內(nèi)存地址的內(nèi)容(設(shè)置格式:md 內(nèi)存地址,如20008000)
U-Boot網(wǎng)絡(luò)層相關(guān)命令
一般而言,將文件(例如:內(nèi)核)從主板傳輸?shù)侥繕?biāo)板采用TFTP協(xié)議,這就涉及到U-Boot的網(wǎng)絡(luò)層設(shè)置。而U-Boot的網(wǎng)絡(luò)層的設(shè)置與環(huán)境變量ipaddr有關(guān):
setenv ipaddr 192.168.10.3
saveenv
需要注意的是,該ip地址需要和虛擬機(jī)的網(wǎng)卡地址在同一網(wǎng)段,即需要Ping通(U-Boot為了精簡,Ping協(xié)議并不完全,必須由目標(biāo)板去Ping主機(jī)虛擬機(jī))。這樣才能完成目標(biāo)板與主板虛擬機(jī)的網(wǎng)絡(luò)層的通暢。
Ping通之后,就可以通過TFTP進(jìn)行文件傳輸了。由于U-Boot內(nèi)有TFTP的客戶端,因此服務(wù)器端有兩種可能:
主板:下載TFTPD軟件,設(shè)置目錄并選擇網(wǎng)卡
主板虛擬機(jī):下載服務(wù)器端軟件,命令如下:
sudo apt-get install tftpd-hpa //32位
sudo apt-get install tftpd openbsc-xinetd //64位
然后TFTP的目錄配置文件在/etc/inetd.conf中,比如:
sudo vi /etc/inetd.conf
...
tftp dgram udp wait noboby /usr/sbin/tcpd /usr/sbin/in.tftpd [目錄]
...
sudo /etc/init.d/tftpd-hpa/restart //重啟服務(wù)
目標(biāo)板進(jìn)行TFTP需要知曉服務(wù)器端的ip地址、端口號(hào)、傳輸?shù)降膬?nèi)存地址和需要傳輸?shù)膬?nèi)容。服務(wù)器端的ip地址在環(huán)境變量serverip,端口號(hào)是TFTP規(guī)定好的(69號(hào)端口),剩下的兩個(gè)參數(shù)就是tftp命令需要指定的:
tftp 20008000 hello.c
這段命令的意思為,從環(huán)境變量serverip的服務(wù)器端將hello.c文件通過TFTP協(xié)議傳輸?shù)侥繕?biāo)板內(nèi)存地址為20008000的內(nèi)存中。
U-Boot Flash相關(guān)命令
當(dāng)調(diào)試完程序后,最終需要將其寫入NandFlash中,否則程序仍在內(nèi)存中,一旦重啟就會(huì)消失。這就需要用到nand命令了。其一般格式為:
nand erase [NandFlash內(nèi)部地址] [擦除大小]
nand [write/read] [內(nèi)存地址] [NandFlash內(nèi)部地址] [搬移大小]
通常,在使用write之前都需要先進(jìn)行erase命令。例如:
nand erase 500000 1024 //擦除Flash5M地址1字節(jié)的內(nèi)容
nand write 20008000 500000 1024 //將內(nèi)存20008000以后1字節(jié)的內(nèi)容寫入Flash5M地址
nand read 20008000 500000 1024 //將Flash5M地址以后1字節(jié)的內(nèi)容讀取到內(nèi)存20008000
這樣就能保證,目標(biāo)板重啟之后數(shù)據(jù)也不會(huì)丟失了。
U-Boot啟動(dòng)內(nèi)核命令
bootm命令用于啟動(dòng)一個(gè)操作系統(tǒng)映像。它會(huì)從內(nèi)核映像文件(uImage)的頭部取得一些信息,這些信息包括:映像文件的基于的cpu架構(gòu)、其操作系統(tǒng)類型、映像的類型、壓縮方式、映像文件在內(nèi)存中的加載地址、映像文件運(yùn)行的入口地址、映像文件名等。
緊接著bootm命令將映像加載到指定的地址,如果需要的話,還會(huì)解壓映像并傳遞必要有參數(shù)給內(nèi)核,最后跳到入口地址進(jìn)入內(nèi)核。
U-Boot啟動(dòng)內(nèi)核,需要滿足一定的條件:
啟動(dòng)參數(shù) bootargs
根文件系統(tǒng)
啟動(dòng)參數(shù)bootargs,一般包括以下三項(xiàng):
root=:啟動(dòng)的根文件系統(tǒng)的位置相關(guān)信息
init=:內(nèi)核啟動(dòng)后的第一個(gè)可執(zhí)行文件,即init進(jìn)程
console=:內(nèi)核啟動(dòng)后,作為控制臺(tái)的設(shè)備
根文件系統(tǒng)一般有兩種方式:Ramdisk、NFS。
Ramdisk:顧名思義內(nèi)存磁盤,即將根文件系統(tǒng)放在內(nèi)存中。本質(zhì)上,RamDisk并非一個(gè)實(shí)際的文件系統(tǒng),而是一種將實(shí)際的文件系統(tǒng)裝入內(nèi)存的機(jī)制,并且可以作為根文件系統(tǒng)。實(shí)際上它使用的文件系統(tǒng)是ext2。
此時(shí)的配置需要指定root的位置在RAM,同時(shí)還需要指定RAM中的具體位置和大小,啟動(dòng)參數(shù)為:
setenv bootargs root=/dev/ram initrd=0x21000000,8M init=/linuxrc console=ttySAC0,115200
saveenv
確定完啟動(dòng)參數(shù)之后,就可以傳輸文件,并進(jìn)行內(nèi)核啟動(dòng)了,使用bootm命令:
tftp 20008000 uImage
tftp 21000000 initrd.img.gz
bootm 20008000
NFS:顧名思義網(wǎng)絡(luò)文件系統(tǒng)。即允許網(wǎng)絡(luò)中的計(jì)算機(jī)之間通過TCP/IP網(wǎng)絡(luò)共享資源。在NFS的應(yīng)用中,本地NFS的客戶端應(yīng)用可以透明地讀寫位于遠(yuǎn)端NFS服務(wù)器上的文件,就像訪問本地文件一樣。這種方式,對于調(diào)試就非常方便。
簡單一點(diǎn)說,就是將根文件系統(tǒng)放在主板的虛擬機(jī)上,目標(biāo)板通過NFS來進(jìn)行訪問。那么,顯而易見,主板的虛擬機(jī)需要安裝NFS的服務(wù)器端。
sudo apt-cache search nfs- //記不得名稱了可以用此命令搜索
sudo apt-get install nfs-kernel-server
安裝完成后,需要進(jìn)行NFS的配置,配置文件在/etc/exports中:
sudo vi /etc/exports
...
[目錄] *(rw,sync,no_subtree_check)
...
sudo /etc/init.d/nfs-kernel-server restart //重啟服務(wù)
需要注意的是,根文件系統(tǒng)的后綴為.gz,是一個(gè)壓縮包。當(dāng)通過TFTP傳輸給目標(biāo)板之后,目標(biāo)板會(huì)自動(dòng)對其進(jìn)行解壓操作,形成相應(yīng)的文件夾。然而,如果采用NFS的方式,服務(wù)器端需要自身解壓完,留給目標(biāo)板進(jìn)行訪問:
gunzip initrd.img.gz //解壓為initrd.img,相當(dāng)于一個(gè)ios文件
mount -t ext2 init.img [掛載目錄] //掛載initrd.img
服務(wù)器端配置完成后,目標(biāo)板的配置需要指定root的位置在NFS,同時(shí)還需要指定NFS中的具體ip、端口和目錄絕對地址,端口號(hào)是NFS規(guī)定好的。
除此之外,U-Boot一旦啟動(dòng)內(nèi)核之后,它就喪失了對目標(biāo)板的主動(dòng)權(quán),此時(shí)它的環(huán)境變量ipaddr也喪失作用了。這個(gè)時(shí)候,目標(biāo)板就是屬于無ip的狀態(tài),自然NFS就無法連接上了。因此,還需要設(shè)置ip參數(shù)。啟動(dòng)參數(shù)為:
setenv bootargs root=/dev/nfs nfsroot=192.168.10.110:/home/rocky/work/rootfs ip=192.168.10.120 init=/linuxrc console=ttySAC0,115200
saveenv
確定完啟動(dòng)參數(shù)之后,就可以傳輸文件,并進(jìn)行內(nèi)核啟動(dòng)了,使用bootm命令:
tftp 20008000 uImage
bootm 20008000
采用NFS方式的好處就是,可以在主板虛擬機(jī)上寫一個(gè)程序,并運(yùn)用交叉編譯器進(jìn)行編譯,編譯完成后,自動(dòng)就會(huì)同步到目標(biāo)板上。這個(gè)時(shí)候,就可以直接在目標(biāo)板上運(yùn)行編譯完的程序。即主板虛擬機(jī)編譯,目標(biāo)板運(yùn)行!
U-Boot自動(dòng)啟動(dòng)內(nèi)核命令
可以看出,上面的兩種啟動(dòng)內(nèi)核的方式都不能做到一上電就自動(dòng)啟動(dòng)內(nèi)核的作用。其實(shí)這都和U-Boot的環(huán)境變量有關(guān):bootdelay、bootcmd。前者為啟動(dòng)后倒計(jì)時(shí),后者為倒計(jì)時(shí)后自動(dòng)執(zhí)行的命令。
就可以將內(nèi)核、根文件系統(tǒng)都nand到Flash中,倒計(jì)時(shí)后從Flash中讀取并啟動(dòng)內(nèi)核:
setenv bootdelay 2
setenv bootcmd nand read 20008000 100000 200000;nand read 21000000 5600000 400000;bootm 20008000