A10/A20 Bootloader加載過程分析注:由于全志A10和A20在加載Bootloader過程方面基本一致,下面僅以A20敘述,但同時也適用于A10。另外在不需要區(qū)分Cubieboard1和Cubieboard2的情況下,統(tǒng)稱為Cubieboard;另現(xiàn)在市面上一般所說的SD卡即為Micro SD Card,也就是TF卡,為區(qū)別于一般傳統(tǒng)的SD卡,本文一般使用TF卡描述,但同于平時所說的SD卡。 A20的啟動過程大概可分為5步:Boot ROM,SPL,Uboot,Kernel,RootFileSystem。本文關注的是鏡像的加載和啟動過程,分析Boot ROM→SPL→Uboot→Kernel的啟動流程。 系統(tǒng)上電后,ARM處理器在復位時從地址0x000000開始執(zhí)行指令,把板上ROM或Flash映射到這一地址。A20將啟動設備選擇程序固化在CPU內部的一個32KB ROM中,默認的啟動時序為SD Card0,NAND FLASH,SD Card2,SPI NOR FLASH。另外通過外部的一個啟動選擇引腳可以使其跳轉到USB啟動模式。通常情況下,啟動選擇引腳狀態(tài)連接50K內部上拉電阻。在上電后,執(zhí)行存儲在Boot ROM中的啟動代碼,將自動檢測啟動選擇引腳狀態(tài)。只有當該引腳狀態(tài)為低電平時才選擇USB啟動模式。 在選擇啟動設備后將加載并執(zhí)行bootloader程序,CPU通過拷貝或映射bootloader程序到內存,然后執(zhí)行bootloader的第一條指令。通過閱讀官方的uboot燒寫方法,發(fā)現(xiàn)A20通過uboot引導系統(tǒng)之前先載入了uboot SPL。什么是SPL?通過查閱uboot的官網資料得知,SPL是一個迷你版的uboot,全拼為Second Program Loader。適用于SOC的內部SRAM<64K的情況,用它來加載完整的uboot程序到SDRAM,并通過完整uboot加載內核來啟動系統(tǒng)。其中SRAM一般指CPU內部的L1/L2或外部的L2高速緩存,這里即為Boot ROM,而SDRAM一般指內存。 SPL程序流程如下:
啟動設備選擇程序的流程圖: 搞清楚了上面的概念,可以知道Cubieboard出廠已經燒寫了NandFlash中的程序,即在啟動時使用的是NandFlash。現(xiàn)在根據全志A20上述步驟,我們嘗試用SD Card0(即Cubieboard上卡槽中的TF卡)來啟動系統(tǒng)。 環(huán)境準備本文所使用的主機環(huán)境為kubuntu 12.10,然而一般情況下,下面涉及到的命令對基于Debian的(X)ubuntu系列都應該適用。 為不引起混淆,我們作如下約定:
筆者的設定如下: WORK_DIR=/home/itviewer/src 下載必須的工具軟件apt-get install build-essential libncurses5-dev u-boot-tools qemu-user-static debootstrap git binfmt-support libusb-1.0-0-dev pkg-config apt-get install gcc-arm-linux-gnueabihf 下載源碼從 github 下載 SPL,U-BOOT,Linux 內核源碼。注意 linux-sunxi 超過 3.8G ,耗時最長。如果您曾經下載過這些代碼,記得分別用 git pull 更新后再進行后續(xù)操作,因為代碼倉庫每天都有變化。 cd $WORK_DIR git clone git://github.com/linux-sunxi/u-boot-sunxi.git git clone git://github.com/cubieboard2/linux-sunxi git clone git://github.com/linux-sunxi/sunxi-tools.git git clone git://github.com/linux-sunxi/sunxi-boards.git 編譯ubootcd $WORK_DIR/u-boot-sunxi make distclean CROSS_COMPILE=arm-linux-gnueabihf- make Cubieboard2 CROSS_COMPILE=arm-linux-gnueabihf- 得到 u-boot-sunxi-with-spl.bin(同時生成的還有其它幾個文件,這里我們只用該文件,注意上面Cubieboard2,最新代碼需要首字母大寫) 編譯kernelcd $WORK_DIR/linux-sunxi make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- cubieboard2_defconfig make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j4 uImage modules 得到內核文件 arch/arm/boot/uImage(還有其它內核模塊,這里暫時沒有用到) 生成 boot.scr和script.bin在將uboot和kernel燒寫到TF卡之前,我們需要先編譯生成兩個啟動參數(shù)文件:boot.scr和script.bin。 生成 boot.scrboot.scr是什么? 根據資料描述(https://github.com/linux-sunxi/u-boot-sunxi/wiki#bootscr-support),u-boot在啟動的時候會在第一個分區(qū)(FAT/extX格式)尋找/boot.scr或者/boot/boot.scr文件,boot.scr中可以包含用于載入script.bin,kernel,initrd(可選)以及設置內核啟動參數(shù)的uboot命令。 boot.scr如何生成? 在$WORK_DIR目錄新建 boot.cmd 文件,添加以下內容: setenv bootargs console=ttyS0,115200 noinitrd disp.screen0_output_mode=EDID:1280x1024p60 init=/init root=/dev/mmcblk0p2 rootfstype=ext4 rootwait panic=10 ${extra} fatload mmc 0 0x43000000 boot/script.bin fatload mmc 0 0x48000000 boot/uImage bootm 0x48000000 詳細解釋: 1.上述第一行設置uboot的bootargs啟動參數(shù),格式為 參數(shù)=值,不同參數(shù)使用空格分開,其中
更多的參數(shù)可以通過查看Linux內核源碼目錄下Documentation/kernel-parameters.txt文件了解 2.第二行和第三行為將script.bin和內核uImage加載到指定內存地址。fatload是U-Boot中裝載linux kernel 到內存的指令。 基本用法:fatload <interface> <dev[:part]> <addr> <filename> <bytes>
3.第四行bootm 用于將內核映像加載到指定的地址 保存文件后,執(zhí)行以下命令生成boot.scr: mkimage -C none -A arm -T script -d boot.cmd boot.scr 生成 script.binscript.bin是什么? script.bin是被全志SOC內核驅動或LiveSuit使用的針對特定目標板的二進制配置文件,包含如何設置基于A10/A20目標版的各種外設,端口,I/O針腳信息。 其對應的可讀文本文件格式為FEX,可以利用 Sunxi-tools在二進制和文本文件之間進行轉換。更多關于FEX配置的信息可以參考http:///Fex_Guide script.bin如何生成? 首先需要編譯sunxi-tools: cd $WORK_DIR/sunxi-tools make 得到fex2bin、bin2fex等文件,其中fex2bin能把 *.fex 文件生成 *.bin文件。反之bin2fex可以將得到的*.bin文件生成可讀的*.fex文件。 然后編譯生成script.bin: cd $WORK_DIR/sunxi-boards/sys_config/a20 $WORK_DIR/sunxi-tools/fex2bin cubieboard2.fex script.bin 燒寫uboot和kernel到TF卡上面羅嗦了這么多,其實就是為了將uboot和kernel燒寫到TF卡上并能夠啟動,OK,讓我們先從分區(qū)開始: A20 芯片上電啟動的時候,會讀取SD卡最前面的 1M 內容,從而得到 bootloader,所以我們需要把 u-boot 寫到SD卡的前1M區(qū)間。 其中詳細的SD卡布局如下:
接下來,我們開始使用fdisk進行分區(qū)(由于sfdisk對部分TF不兼容,故除非你真的知道怎么用sfdisk,否則不要使用): 將TF卡插到電腦上并確認設備名,為不至于混淆,我們使用sdX代替,您需要根據自己的情況修改,如sdb: card=/dev/sdX dd if=/dev/zero of=${card} bs=1M count=1 # 把SD卡前1M的區(qū)域填充為0,預留給 u-boot sfdisk -R ${card} # 重新讀取${card} fdisk ${card} #使用fdisk進行分區(qū) 具體分區(qū)步驟如下: 建立第一個分區(qū) root@kubuntu:~/src/u-boot-sunxi# fdisk ${card} Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel Building a new DOS disklabel with disk identifier 0x911332e8. Changes will remain in memory only, until you decide to write them. After that, of course, the previous content won't be recoverable. Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite) Command (m for help): n #鍵入n然后回車 Partition type: p primary (0 primary, 0 extended, 4 free) e extended Select (default p): #直接回車 Using default response p Partition number (1-4, default 1): #直接回車 Using default value 1 First sector (2048-15278079, default 2048): #直接回車 Using default value 2048 Last sector, +sectors or +size{K,M,G} (2048-15278079, default 15278079): +64M #鍵入+64M后回車,即分區(qū)大小為64M 建立第二個分區(qū) Command (m for help): n #鍵入n然后回車 Partition type: p primary (1 primary, 0 extended, 3 free) e extended Select (default p): #直接回車 Using default response p Partition number (1-4, default 2): #直接回車 Using default value 2 First sector (133120-15278079, default 133120): #直接回車 Using default value 133120 Last sector, +sectors or +size{K,M,G} (133120-15278079, default 15278079): #直接回車,即第二個分區(qū)使用全部剩余空間 Using default value 15278079 接下來指定分區(qū)類型: Command (m for help): t #鍵入t然后回車 Partition number (1-4): 1 #鍵入1然后回車,即指定第一個分區(qū) Hex code (type L to list codes): c #鍵入c然后回車,即指定第一個分區(qū)為vfat Changed system type of partition 1 to c (W95 FAT32 (LBA)) Command (m for help): w #鍵入w然后回車,保存分區(qū)表 The partition table has been altered! Calling ioctl() to re-read partition table. Syncing disks. 格式化分區(qū): mkfs.vfat ${card}1 mkfs.ext4 ${card}2 #需要稍等片刻 然后寫入bootloader: cd $WORK_DIR/u-boot-sunxi dd if=u-boot-sunxi-with-spl.bin of=$card bs=1024 seek=8 最后安裝內核 uImage,設置啟動參數(shù): mount ${card}1 /mnt mkdir /mnt/boot cp $WORK_DIR/linux-sunxi/arch/arm/boot/uImage /mnt/boot cp $WORK_DIR/sunxi-boards/sys_config/a20/script.bin /mnt/boot cp $WORK_DIR/boot.scr /mnt/ sync && umount /mnt 至此,啟動到linux內核的工作已經完成,接下來我們就可以觀看linux內核啟動過程、進行內核調試了。 打印串口調試信息通過查看串口輸出信息,可以方便我們判斷問題所在,進而找到解決問題的方法。 在linux和windows下有多種串口調試工具可供使用,這里僅給出兩篇參考文章: 這里附上筆者的串口輸出信息:http://mer./data/media/cutecom.txt 信息結尾由于無法掛載根文件系統(tǒng)、啟動init而等待10秒后重啟。 總結本文參考了眾多網絡內容,在后面列出了主要文章地址,在此一并感謝。 之所以寫這篇內容,是因為從本人入手cubieboard2以來,通過苦尋資料,在各種痛苦與錯誤的嘗試中不斷走上了”正道“,深知對于一個沒有嵌入式開發(fā)基礎或開發(fā)經驗的普通玩家而言,想把各種環(huán)節(jié)搞清楚是一件很難的事情,故通過大量引用、參考網絡內容加上自己的摸索,總結出該文,以期望對新的玩家能夠有所幫助;就嵌入式linux而言,整個 加電——啟動bootloader——啟動內核——加載rootfs流程對于新手會感到非常的模糊,而不知如何下手。本篇內容盡可能詳細的描述了利用cubieboard從加電到啟動linux內核的整個操作過程,為進一步學習如何構建一個可運行的linux系統(tǒng)打下了基礎。后面,將會在此基礎上繼續(xù)介紹如何進一步掛載跟文件系統(tǒng),啟動到shell甚至GUI圖形界面,從而構建一個完整、可用的linux系統(tǒng)。 參考 |
|
來自: dwlinux_gs > 《A20》