1.為什么要有uboot 1.1、計算機系統的主要部件 (1)計算機系統就是以CPU為核心來(lái)運行的系統。典型的計算機系統有:PC機(臺式機+筆記本)、嵌入式設備(手機、平板電腦、游戲機)、單片機(家用電器像電飯鍋、空調) (2)計算機系統的組成部件非常多,不同的計算機系統組成部件也不同。但是所有的計算機系統運行時(shí)需要的主要核心部件都是3個(gè)東西: CPU + 外部存儲器(Flash/硬盤(pán)) + 內部存儲器(DDR SDRAM/SDRAM/SRAM) 1.2、PC機的啟動(dòng)過(guò)程 (1)部署:典型的PC機的BIOS程序部署在PC機主板上(隨主板出廠(chǎng)時(shí)已經(jīng)預制了),操作系統部署在硬盤(pán)上,內存在掉電時(shí)無(wú)作用,CPU在掉電時(shí)不工作。 (2)啟動(dòng)過(guò)程:PC上電后先執行BIOS程序(實(shí)際上PC的BIOS就是NorFlash),BIOS程序負責初始化DDR內存,負責初始化硬盤(pán),然后從硬盤(pán)上將OS鏡像讀取到DDR中,然后跳轉到DDR中去執行OS直到啟動(dòng)(OS啟動(dòng)后BIOS就無(wú)用了) 1.3、典型嵌入式linux系統啟動(dòng)過(guò)程 (1)典型嵌入式系統的部署:uboot程序部署在Flash(能作為啟動(dòng)設備的Flash)上、OS部署在FLash(嵌入式系統中用Flash代替了硬盤(pán))上、內存在掉電時(shí)無(wú)作用,CPU在掉電時(shí)不工作。 (2)啟動(dòng)過(guò)程:嵌入式系統上電后先執行uboot、然后uboot負責初始化DDR,初始化Flash,然后將OS從Flash中讀取到DDR中,然后啟動(dòng)OS(OS啟動(dòng)后uboot就無(wú)用了) 總結:嵌入式系統和PC機的啟動(dòng)過(guò)程幾乎沒(méi)有兩樣,只是BIOS成了uboot,硬盤(pán)成了Flash。 1.4、android系統啟動(dòng)過(guò)程 (1)Android系統的啟動(dòng)和Linux系統(前面講的典型的嵌入式系統啟動(dòng))幾乎一樣。幾乎一樣意思就是前面完全一樣,只是在內核啟動(dòng)后加載根文件系統后不同了。 (2)可以認為啟動(dòng)分為2個(gè)階段:第一個(gè)階段是uboot到OS啟動(dòng);第二個(gè)階段是OS啟動(dòng)后到rootfs加載到命令行執行;現在我們主要研究第一個(gè)階段,android的啟動(dòng)和linux的差別在第二階段。 1.5、總結:uboot到底是干嘛的 (1)uboot主要作用是用來(lái)啟動(dòng)操作系統內核。 (2)uboot還要負責部署整個(gè)計算機系統。 (3)uboot中還有操作Flash等板子上硬盤(pán)的驅動(dòng)。 (4)uboot還得提供一個(gè)命令行界面供人來(lái)操作。 2.為什么是uboot 2.1、uboot從哪里來(lái)的? (1)uboot是SourceForge上的開(kāi)源項目 (2)uboot項目的作者:一個(gè)德國人最早發(fā)起的項目 (3)uboot就是由一個(gè)人發(fā)起,然后由整個(gè)網(wǎng)絡(luò )上所有感興趣的人共同維護發(fā)展而來(lái)的一個(gè)bootloader。 2.2、uboot的發(fā)展歷程 (1)自己使用的小開(kāi)源項目。 (2)被更多人認可使用 (3)被SoC廠(chǎng)商默認支持。 總結:uboot經(jīng)過(guò)多年發(fā)展,已經(jīng)成為事實(shí)上的業(yè)內bootloader標準,F在大部分的嵌入式設備都會(huì )默認使用uboot來(lái)做為bootloader。 2.3、uboot的版本號問(wèn)題 (1)早期的uboot的版本號類(lèi)似于這樣:uboot1.3.4。后來(lái)版本號便成了類(lèi)似于uboot-2010.06。 (2)uboot的核心部分幾乎沒(méi)怎么變化,越新的版本支持的開(kāi)發(fā)板越多而已,對于一個(gè)老版本的芯片來(lái)說(shuō),新舊版本的uboot并沒(méi)有差異。 2.4、uboot的可移植性的正確理解 (1)uboot就是universal bootloader(通用的啟動(dòng)代碼),通用的意思就是在各種地方都可以用。所以說(shuō)uboot具有可移植性。 (2)uboot具有可移植性并不是說(shuō)uboot在哪個(gè)開(kāi)發(fā)板都可以隨便用,而是說(shuō)uboot具有在源代碼級別的移植能力,可以針對多個(gè)開(kāi)發(fā)板進(jìn)行移植,移植后就可以在這個(gè)開(kāi)發(fā)板上使用了。 3.uboot必須解決哪些問(wèn)題 3.1、自身可開(kāi)機直接啟動(dòng) (1)一般的SoC都支持多種啟動(dòng)方式,譬如SD卡啟動(dòng)、NorFlash啟動(dòng)、NandFlash啟動(dòng)等·····uboot要能夠開(kāi)機啟動(dòng),必須根據具體的SoC的啟動(dòng)設計來(lái)設計uboot。 (2)uboot必須進(jìn)行和硬件相對應的代碼級別的更改和移植,才能夠保證可以從相應的啟動(dòng)介質(zhì)啟動(dòng)。uboot中第一階段的start.S文件中具體處理了這一塊。 3.2、能夠引導操作系統內核啟動(dòng)并給內核傳參 (1)uboot的終極目標就是啟動(dòng)內核。 (2)linux內核在設計的時(shí)候,設計為可以被傳參。也就是說(shuō)我們可以在uboot中事先給linux內核準備一些啟動(dòng)參數放在內存中特定位置然后傳給內核,內核啟動(dòng)后會(huì )到這個(gè)特定位置去取uboot傳給他的參數,然后在內核中解析這些參數,這些參數將被用來(lái)指導linux內核的啟動(dòng)過(guò)程。 3.3、能提供系統部署功能 (1)uboot必須能夠被人借助而完成整個(gè)系統(包括uboot、kernel、rootfs等的鏡像)在Flash上的燒錄下載工作。 (2)裸機教程中刷機(ARM裸機第三部分)就是利用uboot中的fastboot功能將各種鏡像燒錄到iNand中,然后從iNand啟動(dòng)。 3.4能進(jìn)行soc級和板級硬件管理 (1)uboot中實(shí)現了一部分硬件的控制能力(uboot中初始化了一部分硬件),因為uboot為了完成一些任務(wù)必須讓這些硬件工作。譬如uboot要實(shí)現刷機必須能驅動(dòng)iNand,譬如uboot要在刷機時(shí)LCD上顯示進(jìn)度條就必須能驅動(dòng)LCD,譬如uboot能夠通過(guò)串口提供操作界面就必須驅動(dòng)串口。譬如uboot要實(shí)現網(wǎng)絡(luò )功能就必須驅動(dòng)網(wǎng)卡芯片。 (2)SoC級(譬如串口)就是SoC內部外設,板級就是SoC外面開(kāi)發(fā)板上面的硬件(譬如網(wǎng)卡、iNand) 3.5、uboot的“生命周期” (1)uboot的生命周期就是指:uboot什么時(shí)候開(kāi)始運行,什么時(shí)候結束運行。 (2)uboot本質(zhì)上是一個(gè)裸機程序(不是操作系統),一旦uboot開(kāi)始SoC就會(huì )單純運行uboot(意思就是uboot運行的時(shí)候別的程序是不可能同時(shí)運行的),一旦uboot結束運行則無(wú)法再回到uboot(所以uboot啟動(dòng)了內核后uboot自己本身就死了,要想再次看到uboot界面只能重啟系統。重啟并不是復活了剛才的uboot,重啟只是uboot的另一生) (3)uboot的入口和出口。uboot的入口就是開(kāi)機自動(dòng)啟動(dòng),uboot的唯一出口就是啟動(dòng)內核。uboot還可以執行很多別的任務(wù)(譬如燒錄系統),但是其他任務(wù)執行完后都可以回到uboot的命令行繼續執行uboot命令,而啟動(dòng)內核命令一旦執行就回不來(lái)了。 總結:一切都是為了啟動(dòng)內核 4.uboot的工作方式 4.1、從裸機程序鏡像uboot.bin說(shuō)起 (1)uboot的本質(zhì)就是一個(gè)裸機程序,和我們裸機全集中寫(xiě)的那些裸機程序xx.bin并沒(méi)有本質(zhì)區別。如果非說(shuō)要有區別,那就是:我們寫(xiě)的大部分小于16KB,而uboot大于16KB(一般uboot在180k-400k之間) (2)uboot本身是一個(gè)開(kāi)源項目,由若干個(gè).c文件和.h文件組成,配置編譯之后會(huì )生成一個(gè)uboot.bin,這就是uboot這個(gè)裸機程序的鏡像文件。然后這個(gè)鏡像文件被合理的燒錄到啟動(dòng)介質(zhì)中拿給SoC去啟動(dòng)。也就是說(shuō)uboot在沒(méi)有運行時(shí)表現為uboot.bin,一般躺在啟動(dòng)介質(zhì)中。 (3)uboot運行時(shí)會(huì )被加載到內存中然后一條指令一條指令的拿給CPU去運行。 4.2、uboot的命令式shell界面 (1)普通的裸機程序運行起來(lái)就直接執行了,執行時(shí)效果和代碼有關(guān)。 (2)有些程序需要和人進(jìn)行交互,于是乎程序中就實(shí)現了一個(gè)shell(shell就是提供人機交互的一個(gè)界面,回想ARM裸機全集第十六部分),uboot就實(shí)現了一個(gè)shell。 注意:shell并不是操作系統,和操作系統一點(diǎn)關(guān)系都沒(méi)有。linux中打開(kāi)一個(gè)終端后就得到了一個(gè)shell,可以輸入命令回車(chē)執行。uboot中的shell工作方式和linux中的終端shell非常像(其實(shí)幾乎是一樣的,只是命令集不一樣。譬如linux中可以ls,uboot中ls就不識別) 4.3、掌握uboot使用的2個(gè)關(guān)鍵點(diǎn):命令和環(huán)境變量 (1)uboot啟動(dòng)后大部分時(shí)間和工作都是在shell下完成的(譬如uboot要部署系統要在shell下輸命令、要設置環(huán)境變量也得在命令行地下,要啟動(dòng)內核也要在命令行底下敲命令) (2)命令就是uboot的shell中可以識別的各種命令。uboot中有幾十個(gè)命令,其中有一些常用另一些不常用(我們還可以自己給uboot添加命令),后面會(huì )用幾節課時(shí)間來(lái)依次學(xué)習uboot中常用命令。 (3)uboot的環(huán)境變量和操作系統的環(huán)境變量工作原理和方式幾乎完全相同。uboot在設計時(shí)借助了操作系統的設計理念(命令行工作方式借鑒了linux終端命令行,環(huán)境變量借鑒了操作系統的環(huán)境變量,uboot的驅動(dòng)管理幾乎完全照抄了linux的驅動(dòng)框架)。 (4)環(huán)境變量可以被認為是系統的全局變量,環(huán)境變量名都是系統內置的(認識就認識,不認識就不認識,這部分是系統自帶的默認的環(huán)境變量,譬如PATH;但是也有一部分環(huán)境變量是自己添加的,自己添加的系統就不認識但是我們自己認識)。系統或者我們自己的程序在運行時(shí)可以通過(guò)讀取環(huán)境變量來(lái)指導程序的運行。這樣設計的好處就是靈活,譬如我們要讓一個(gè)程序更改運行方法,不用去重新修改程序代碼再重新編譯運行,而只要修改相應的環(huán)境變量就可以了。 (5)環(huán)境變量就是運行時(shí)的配置屬性。 5.uboot的常用命令1 5.1、類(lèi)似linux終端的行緩沖命令行 (1)行緩沖的意思就是:當我們向終端命令行輸入命令的時(shí)候,這些命令沒(méi)有立即被系統識別,而是被緩沖到一個(gè)緩存區(也就是系統認為我們還沒(méi)有輸入完),當我們按下回車(chē)鍵(換行)后系統就認為我們輸入完了,然后將緩沖區中所有剛才輸入的作為命令拿去分析處理。 (2)linux終端設計有3種緩沖機制:無(wú)緩沖、行緩沖、全緩沖 (3)有些命令有簡(jiǎn)化的別名,譬如printenv命令可以簡(jiǎn)化為print,譬如setenv可以簡(jiǎn)化為set (4)有些命令會(huì )帶參數(注意格式是固定的),uboot的每個(gè)命令都有事先規定好的各種格式。有些命令就是不帶參數的,譬如printenv/print命令;有些命令帶可選的參數(可以帶也可以不帶,當然帶不帶參數的執行結果是不同的);有些命令帶必須的參數(譬如setenv/set命令) (5)采用“help+命令名”來(lái)查詢(xún)命令的詳細信息,只輸入help時(shí),則打印出命令列表。 5.2、命令中的特殊符號(譬如單引號) (1)uboot的有些命令帶的參數非常長(cháng),為了告訴uboot這個(gè)非常長(cháng)而且中間有好多個(gè)空格的東西是給他的一整個(gè)參數,所以用單引號將這個(gè)很長(cháng)且中間有空格隔開(kāi)的參數引起來(lái)。 (2)別的符號也許也有,而且有特定的意義。當碰到uboot的命令行有特殊符號時(shí)要注意不是弄錯了,而是可能有特別的含義。 5.3、有些命令是一個(gè)命令族(譬如movi) (1)命令族意思就是好多個(gè)命令開(kāi)頭都是用同一個(gè)命令關(guān)鍵字的,但是后面的參數不一樣,這些命令的功能和作用也不同。這就叫一個(gè)命令族。 (2)同一個(gè)命令族中所有的命令都有極大的關(guān)聯(lián),譬如movi開(kāi)頭的命令族都和moviNand(EMMC、iNand)操作有關(guān)。 5.4、第一個(gè)命令:printenv/print (1)print命令不用帶參數,作用是打印出系統中所有的環(huán)境變量。 (2)環(huán)境變量就好像程序的全局變量一樣。程序中任何地方都可以根據需要去調用或者更改環(huán)境變量(一般都是調用),環(huán)境變量和全局變量不同之處在于:全局變量的生命周期是在程序的一次運行當中,開(kāi)始運行時(shí)誕生程序結束時(shí)死亡,下次運行程序時(shí)從頭開(kāi)始;但是環(huán)境變量被存儲在Flash的另一塊專(zhuān)門(mén)區域(Flash上有一個(gè)環(huán)境變量分區),一旦我們在程序中保存了該環(huán)境變量,那么下次開(kāi)機時(shí)該環(huán)境變量的值將維持上一次更改保存后的值。 6.uboot的常用命令2 1、設置(添加/更改)環(huán)境變量:setenv/set 用法:set name value 2、保存環(huán)境變量的更改:saveenv/save saveenv/save命令不帶參數,直接執行,作用是將內存中的環(huán)境變量的值同步保存到Flash中環(huán)境變量的分區。注意:環(huán)境變量的保存是整體的覆蓋保存,也就是說(shuō)內存中所有的環(huán)境變量都會(huì )整體的將Flash中環(huán)境變量分區中原來(lái)的內容整體覆蓋。 總結:徹底更改一個(gè)環(huán)境變量的值,需要2步: 第一步:set命令來(lái)更改內存中的環(huán)境變量 第二步:用save命令將其同步到Flash中環(huán)境變量的分區。 有時(shí)候我們只是想測試下這個(gè)環(huán)境變量,不希望影響到下一次開(kāi)機,那就只set不save,這樣set后當前本次運行的uboot已經(jīng)起效果了,只不過(guò)沒(méi)save下一次開(kāi)機還是會(huì )恢復到原來(lái)的狀況。 3、網(wǎng)絡(luò )測試指令:ping (1)命令用法: ping ip地址 注意:ping是測試開(kāi)發(fā)板和主機之間的網(wǎng)絡(luò )鏈接,注意以下步驟: 1)首先要插上網(wǎng)線(xiàn)。 2)先試圖ping通主機windows。注意Windows中有線(xiàn)網(wǎng)卡的地址設置(設置本地連接)。設置主機windows的本地連接IPv4地址為192.168.1.10 3)第三步確認開(kāi)發(fā)板中uboot里幾個(gè)網(wǎng)絡(luò )相關(guān)的環(huán)境變量的值對不對。最重要的是ipaddr(這個(gè)環(huán)境變量表示當前開(kāi)發(fā)板的IP地址),這個(gè)地址必須和主機windows的IP地址在同一個(gè)網(wǎng)段。 網(wǎng)段的概念:一個(gè)IP地址分為2部分,一部分是網(wǎng)段地址,另一部分是網(wǎng)段內的主機地址(由子網(wǎng)掩碼來(lái)區分哪一部分是網(wǎng)段地址,哪一部分是IP地址)。在子網(wǎng)掩碼是255.255.255.0的情況下,192.168.1.10這個(gè)IP地址的前三部分(192.168.1.)屬于網(wǎng)段地址,第4部分(10)屬于主機地址。 7.開(kāi)發(fā)板和主機的ping通 上節課最后的結果是:uboot中的ipaddr和主機windows本地連接地址已經(jīng)設置到一個(gè)網(wǎng)段,但是實(shí)際還ping不通。 還發(fā)現了這樣的現象:1、我把2個(gè)的網(wǎng)段都從192.168.1.x改到192.168.0.x時(shí)會(huì )ping通一次,第二次開(kāi)始就ping不通了;2、有同學(xué)說(shuō)ping不通可能是因為uboot中g(shù)atewayip沒(méi)設置,我就實(shí)際測試設置網(wǎng)管為同網(wǎng)段.1,再次測試結論是第一次ping通了,第二次開(kāi)始又不通了。 7.1、開(kāi)發(fā)板運行linux下和主機Windows的ping通 (1)先將開(kāi)發(fā)板刷機成linux+QT鏡像(刷機見(jiàn)裸機教程第三部分),然后啟動(dòng)進(jìn)入linux命令行終端下。 (2)在linux下使用ifconfig命令將開(kāi)發(fā)板中linux系統的IP地址設置為和主機windows同一網(wǎng)段(為了上課方便,以后就固定:主機windows地址192.168.1.10,開(kāi)發(fā)板uboot或linux的地址為192.168.1.20,虛擬機ubuntu地址為192.168.1.141) (3)此時(shí)開(kāi)發(fā)板端ping windows通的。 (4)windows中ping開(kāi)發(fā)板也是通的。 說(shuō)明:首先開(kāi)發(fā)板和主機的網(wǎng)絡(luò )部分硬件都是好的,網(wǎng)絡(luò )連接也是好的,主機windows中的網(wǎng)絡(luò )軟件設置是好的。 7.2、開(kāi)發(fā)板運行linux下和虛擬機ubuntu的ping通 (1)在linux基礎課中講過(guò):虛擬機的網(wǎng)卡設置可以選擇好幾種方式,常用的就是NAT和橋接(bridged)。 (2)虛擬機要和開(kāi)發(fā)板進(jìn)行網(wǎng)絡(luò )通信,只能通過(guò)橋接方式連接。 (3)虛擬機要想被開(kāi)發(fā)板ping通,設置步驟如下: 第一步:虛擬機設置成橋接方式。 第二步:虛擬機的菜單中有個(gè)“虛擬網(wǎng)絡(luò )編輯器”,這里面要設置為橋接到有線(xiàn)網(wǎng)卡。(默認是自動(dòng)的,自動(dòng)的一般會(huì )影響ping通。因為電腦現在一般都有2個(gè)網(wǎng)卡:一個(gè)有線(xiàn)的一個(gè)無(wú)線(xiàn)的。如果選了自動(dòng),那么虛擬機會(huì )自動(dòng)橋接到無(wú)線(xiàn)網(wǎng)卡上,但是我們卻是通過(guò)有線(xiàn)網(wǎng)卡來(lái)連接開(kāi)發(fā)板的,自然ping不通) 第三步:在虛擬機ubuntu中設置IP地址為192.168.1.141(可以通過(guò)/etc/network/interfaces文件來(lái)設置靜態(tài)的然后重啟;也可以直接命令行ifconfig去設置) (4)此時(shí)開(kāi)發(fā)板ping虛擬機ubuntu應該就通了。 (5)此時(shí)虛擬機ubuntu中ping開(kāi)發(fā)板也是通的。 7.3、開(kāi)發(fā)板運行uboot下和主機Windows的ping通 (1)剛才開(kāi)發(fā)板運行linux時(shí)和主機windows、虛擬機ubuntu都ping通了,說(shuō)明硬件和連接和主機設置沒(méi)錯。 (2)此時(shí)開(kāi)發(fā)板重啟進(jìn)入uboot,設置好ipaddr、gatewayip,然后去ping windows發(fā)現還是不通。 懷疑uboot本身網(wǎng)絡(luò )驅動(dòng)有問(wèn)題。 (3)然后同樣情況下嘗試去ping通虛擬機ubuntu,理論分析應該也不通,但是實(shí)際發(fā)現是通的。 7.4、開(kāi)發(fā)板運行uboot下和虛擬機ubuntu的ping通 uboot和虛擬機ubuntu互相ping通(前提是虛擬機ubuntu設置為橋接,且橋接到有線(xiàn)網(wǎng)卡,且ip地址設置正確的情況下) 結論:開(kāi)發(fā)板中運行的uboot有點(diǎn)小bug,ping windows就不通,ping虛擬機ubuntu就通。 8.uboot常用命令3 8.1、tftp下載指令:tftp (1)uboot本身主要目標是啟動(dòng)內核,為了完成啟動(dòng)內核必須要能夠部署內核,uboot為了部署內核就需要將內核鏡像從主機中下載過(guò)來(lái)然后燒錄到本地flash中。uboot如何從主機(windows或者虛擬機ubuntu)下載鏡像到開(kāi)發(fā)板上?有很多種方式,主流方式是:fastboot和tftp。 fastboot的方式是通過(guò)USB線(xiàn)進(jìn)行數據傳輸。 tftp的方式是通過(guò)有線(xiàn)網(wǎng)絡(luò )的。典型的方式就是通過(guò)網(wǎng)絡(luò ),fastboot是近些年才新發(fā)展的。 (2)tftp方式下載時(shí)實(shí)際上uboot扮演的是tftp客戶(hù)端程序角色,主機windows或虛擬機ubuntu中必須有一個(gè)tftp服務(wù)器,然后將要下載的鏡像文件放在服務(wù)器的下載目錄中,然后開(kāi)發(fā)板中使用uboot的tftp命令去下載即可。 (3)有些人習慣在windows中搭建tftp服務(wù)器,一般是用一些軟件來(lái)搭建(譬如tftpd32,使用起來(lái)比較簡(jiǎn)單);有些人習慣在linux下搭建tftp服務(wù)器,可以參考網(wǎng)盤(pán)中的虛擬機下載目錄下的一個(gè)教程《嵌入式開(kāi)發(fā)環(huán)境搭建-基于14.04.pdf》,這里面有ubuntu中搭建tftp服務(wù)器的教程,也可以自己上網(wǎng)搜索教程嘗試。(如果你直接就用我的虛擬機,那就已經(jīng)搭建好了,不用再搭建了;如果是自己新裝的那就參考文檔搭建;如果你的版本和我的不一樣那搭建過(guò)程可能不一樣) (4)我的虛擬機搭建的時(shí)候設置的tftp下載目錄是/tftpboot,將要被下載的鏡像復制到這個(gè)目錄下。 (5)檢查開(kāi)發(fā)板uboot的環(huán)境變量,注意serverip必須設置為虛擬機ubuntu的ip地址。(serverip這個(gè)環(huán)境變量的意義就是主機tftp服務(wù)器的ip地址) (6)然后在開(kāi)發(fā)板的uboot下先ping通虛擬機ubuntu,然后再?lài)L試下載:tftp 0x30000000 zImage-qt(意思是將服務(wù)器上名為zImage-qt的文件下載到開(kāi)發(fā)板內存的0x30000000地址處。) (7)鏡像下載到開(kāi)發(fā)板的DDR中后,uboot就可以用movi指令進(jìn)行鏡像的燒寫(xiě)了。 注意: 如果你是用的windows下的tftp服務(wù)器,那uboot的serverip就要設置為和windwos下tftp服務(wù)器的ip地址一樣(windows下的tftp服務(wù)器軟件設置的時(shí)候就有個(gè)步驟是讓你設置服務(wù)器的ip地址,這個(gè)ip地址和主機windows必須在一個(gè)網(wǎng)段)。 9.uboot的常用命令4 9.1、SD卡/iNand操作指令movi (1)開(kāi)發(fā)板如果用SD卡/EMMC/iNand等作為Flash,則在uboot中操作flash的指令為movi(或mmc) (2)movi指令是一個(gè)命令集,有很多子命令,具體用法可以help movi查看。 (3)movi的指令都是movi read和movi write一組的,movi read用來(lái)讀取iNand到DDR上,movi write用來(lái)將DDR中的內容寫(xiě)入iNand中。理解這些指令時(shí)一定要注意涉及到的2個(gè)硬件:iNand和DDR內存。 (4)movi read {u-boot | kernel} {addr} 這個(gè)命令使用了一種通用型的描述方法來(lái)描述:movi 和read外面沒(méi)有任何標記說(shuō)明每一次使用這個(gè)指令都是必選的;一對大括號{}括起來(lái)的部分必選1個(gè);大括號中的豎線(xiàn)表是多選一;中括號[]表示可選參數 (5)指令有多種用法,譬如 movi read u-boot 0x30000000,意思就是把iNand中的u-boot分區讀出到DDR的0x30000000起始的位置處。(uboot代碼中將iNand分成了很多個(gè)分區,每個(gè)分區有地址范圍和分區名,uboot程序操作中可以使用直接地址來(lái)操作iNand分區,也可以使用分區名來(lái)操作分區。);注意這里的0x30000000也可以直接寫(xiě)作30000000,意思是一樣的(uboot的命令行中所有數字都被默認當作十六進(jìn)制處理,不管你加不加0x都一樣)。 9.2、NandFlash操作指令nand 理解方法和操作方法完全類(lèi)似于movi指令 9.3、內存操作指令:mm、mw、md (1)DDR中是沒(méi)有分區的(只聽(tīng)說(shuō)過(guò)對硬盤(pán)、Flash進(jìn)行分區,沒(méi)聽(tīng)說(shuō)過(guò)對內存進(jìn)行分區····),但是內存使用時(shí)要注意,千萬(wàn)不能越界踩到別人了。因為uboot是一個(gè)裸機程序,不像操作系統會(huì )由系統整體管理所有內存,系統負責分配和管理,系統會(huì )保證內存不會(huì )隨便越界。然后裸機程序中uboot并不管理所有內存,內存是散的隨便用的,所以如果程序員(使用uboot的人)自己不注意就可能出現自己把自己的數據給覆蓋了。(所以你思考下我們?yōu)槭裁窗製boot放在23E00000地址處) (2)md就是memory display,用來(lái)顯示內存中的內容。 (3)mw就是memory write,將內容寫(xiě)到內存中 (4)mm就是memory modify,修改內存中的某一塊,說(shuō)白了還是寫(xiě)內存(如果需要批量的逐個(gè)單元的修改內存,用mm最合適) 9.4、啟動(dòng)內核指令:bootm、go (1)uboot的終極目標就是啟動(dòng)內核,啟動(dòng)內核在uboot中表現為一個(gè)指令,uboot命令行中調用這個(gè)指令就會(huì )啟動(dòng)內核(不管成功與否,所以這個(gè)指令是一條死路)。 (2)差別:bootm啟動(dòng)內核同時(shí)給內核傳參,而Go命令啟動(dòng)內核不傳參。bootm其實(shí)才是正宗的啟動(dòng)內核的命令,一般情況下都用這個(gè);go命令本來(lái)不是專(zhuān)為啟動(dòng)內核設計的,go命令內部其實(shí)就是一個(gè)函數指針指向一個(gè)內存地址然后直接調用那個(gè)函數,go命令的實(shí)質(zhì)就是PC直接跳轉到一個(gè)內存地址去運行而已。go命令可以用來(lái)在uboot中執行任何的裸機程序(有一種調試裸機程序的方法就是事先啟動(dòng)uboot,然后在uboot中去下載裸機程序,用go命令去執行裸機程序) 10.uboot的常用環(huán)境變量1 10.1、環(huán)境變量如何參與程序運行 (1)環(huán)境變量有2份,一份在Flash中,另一份在DDR中。uboot開(kāi)機時(shí)一次性從Flash中讀取全部環(huán)境變量到DDR中作為環(huán)境變量的初始化值,然后使用過(guò)程中都是用DDR中這一份,用戶(hù)可以用saveenv指令將DDR中的環(huán)境變量重新寫(xiě)入Flash中去更新Flash中環(huán)境變量。下次開(kāi)機時(shí)又會(huì )從Flash中再讀一次。 (2)環(huán)境變量在uboot中是用字符串表示的,也就是說(shuō)uboot是按照字符匹配的方式來(lái)區分各個(gè)環(huán)境變量的。因此用的時(shí)候一定要注意不要打錯字了。 1、自動(dòng)運行倒數時(shí)間:bootdelay 2、網(wǎng)絡(luò )設置:ipaddr serverip (1)ipaddr是開(kāi)發(fā)板的本地IP地址 (2)serverip是開(kāi)發(fā)板通過(guò)tftp指令去tftp服務(wù)器下載東西時(shí),tftp服務(wù)器的IP地址。 (3)gatewayip是開(kāi)發(fā)板的本地網(wǎng)關(guān)地址 (4)netmask是子網(wǎng)掩碼 (5)ethaddr是開(kāi)發(fā)板的本地網(wǎng)卡的MAC地址。 11.uboot的常用環(huán)境變量2 11.1、自動(dòng)運行命令設置:bootcmd (1)uboot啟動(dòng)后會(huì )開(kāi)機自動(dòng)倒數bootdelay秒,如果沒(méi)有人按下回車(chē)打斷啟動(dòng),則uboot會(huì )自動(dòng)執行啟動(dòng)命令來(lái)啟動(dòng)內核。 (2)uboot開(kāi)機自動(dòng)啟動(dòng)時(shí)實(shí)際就是在內部執行了bootcmd這個(gè)環(huán)境變量的值所對應的命令集:bootcmd=movi read kernel 30008000; bootm 30008000 意思是:將iNand的kernel分區讀取到DDR內存的0x30008000地址處,然后使用bootm啟動(dòng)命令從內存0x30008000處去啟動(dòng)內核。 (3)set bootcmd printenv,然后saveenv;然后重啟則會(huì )看到啟動(dòng)倒數后自動(dòng)執行printenv命令打印出環(huán)境變量。這個(gè)小實(shí)驗說(shuō)明開(kāi)機自動(dòng)執行了bootcmd。 (4)設置bootcmd環(huán)境變量:set bootcmd 'movi read kernel 30008000; bootm 30008000' 11.2、uboot給kernel傳參:bootargs (1)linux內核啟動(dòng)時(shí)可以接收uboot給他傳遞的啟動(dòng)參數,這些啟動(dòng)參數是uboot和內核約定好的形式、內容,linux內核在這些啟動(dòng)參數的指導下完成啟動(dòng)過(guò)程。這樣的設計是為了靈活,為了內核在不重新編譯的情況下可以用不同的方式啟動(dòng)。 (2)我們要做的事情就是:在uboot的環(huán)境變量中設置bootargs,然后bootm命令啟動(dòng)內核時(shí)會(huì )自動(dòng)將bootargs傳給內核。 (3)環(huán)境變量bootargs=console=ttySAC2,115200 root=/dev/mmcblk0p2 rw init=/linuxrc rootfstype=ext3 意義解釋?zhuān)?br /> console=ttySAC2,115200 控制臺使用串口2,波特率115200. root=/dev/mmcblk0p2 rw 根文件系統在SD卡端口0設備(iNand)第2分區,根文件系統是可讀可寫(xiě)的 init=/linuxrc linux的進(jìn)程1(init進(jìn)程)的路徑 rootfstype=ext3 根文件系統的類(lèi)型是ext3 (4)內核傳參非常重要。在內核移植的時(shí)候,新手經(jīng)常因為忘記給內核傳參,或者給內核傳遞的參數不對,造成內核啟動(dòng)不起來(lái)。 11.3、新建、更改、刪除一個(gè)環(huán)境變量的方法 (1)新建一個(gè)環(huán)境變量,使用set var value (2)更改一個(gè)環(huán)境變量,使用set var value (3)刪除一個(gè)環(huán)境變量,使用set var 注意:修改完成環(huán)境變量后一定要保存,否則下次開(kāi)機更改就又沒(méi)了。 12.uboot中對Flash和DDR的管理 12.1、uboot階段Flash的分區 (1)所謂分區,就是說(shuō)對Flash進(jìn)行分塊管理。 (2)PC機等產(chǎn)品中,因為大家都是在操作系統下使用硬盤(pán)的,整個(gè)硬盤(pán)由操作系統統一管理,操作系統會(huì )使用文件系統幫我們管理硬盤(pán)空間。(管理保證了文件之間不會(huì )互相堆疊),于是乎使用者不用自己太過(guò)在意分區問(wèn)題。 (3)在uboot中是沒(méi)有操作系統的,因此我們對Flash(相當于硬盤(pán))的管理必須事先使用分區界定(實(shí)際上在uboot中和kernel中都有個(gè)分區表,分區表就是我們在做系統移植時(shí)對Flash的整體管理分配方法)。有了這個(gè)界定后,我們在部署系統時(shí)按照分區界定方法來(lái)部署,uboot和kernel的軟件中也是按照這個(gè)分區界定來(lái)工作,就不會(huì )錯。 (4)分區方法不是一定的,不是固定的,是可以變動(dòng)的。但是在一個(gè)移植中必須事先設計好定死,一般在設計系統移植時(shí)就會(huì )定好,定的標準是: uboot:uboot必須從Flash起始地址開(kāi)始存放(也許是扇區0,也許是扇區1,也許是其他,取決于SoC的啟動(dòng)設計),uboot分區的大小必須保證uboot肯定能放下,一般設計為512KB或者1MB(因為一般uboot肯定不足512KB,給再大其實(shí)也可以工作,但是浪費); 環(huán)境變量:環(huán)境變量分區一般緊貼著(zhù)uboot來(lái)存放,大小為32KB或者更多一點(diǎn)。 kernel:kernel可以緊貼環(huán)境變量存放,大小一般為3MB或5MB或其他。 rootfs:······ 剩下的就是自由分區,一般kernel啟動(dòng)后將自由分區掛載到rootfs下使用 總結:一般規律如下: (1)各分區彼此相連,前面一個(gè)分區的結尾就是后一個(gè)分區的開(kāi)頭。 (2)整個(gè)flash充分利用,從開(kāi)頭到結尾。 (3)uboot必須在Flash開(kāi)頭,其他分區相對位置是可變的。 (4)各分區的大小由系統移植工程師自己來(lái)定,一般定為合適大。ú荒芴,太小了容易溢出;不能太大,太大了浪費空間) (5)分區在系統移植前確定好,在uboot中和kernel中使用同一個(gè)分區表。將來(lái)在系統部署時(shí)和系統代碼中的分區方法也必須一樣。 12.2、uboot階段DDR的分區 (1)DDR的分區和Flash的分區不同,主要是因為Flash是掉電存在的,而DDR是掉電消失,因此可以說(shuō)DDR是每次系統運行時(shí)才開(kāi)始部署使用的。 (2)內存的分區主要是在linux內核啟動(dòng)起來(lái)之前,linux內核啟動(dòng)后內核的內存管理模塊會(huì )接管整個(gè)內存空間,那時(shí)候就不用我們來(lái)管了。 (3)注意內存分區關(guān)鍵就在于內存中哪一塊用來(lái)干什么必須分配好,以避免各個(gè)不同功能使用了同一塊內存造成的互相踩踏。譬如說(shuō)我們tftp 0x23E00000 zImage去下載zImage到內存的0x23E00000處就會(huì )出錯,因為這個(gè)內存處實(shí)際是uboot的鏡像所在。這樣下載會(huì )導致下載的zImage把內存中的uboot給沖掉。 嵌入式技術(shù)學(xué)習,聯(lián)系宋老師企鵝號:3524-6590-88 Tel/WX:173--1795--1908 以下課程可免費試聽(tīng)C語(yǔ)言、電子、PCB、STM32、Linux、FPGA、JAVA、安卓等。 想學(xué)習的你和我聯(lián)系預約就可以免費聽(tīng)課了。 ![]() |