0環境
Linux主機OS:Ubuntu14.04 64位,運行在VMware Workstation 10虛擬機
樹莓派版本:raspberry pi 2 B型.
樹莓派OS: Debian Jessie Raspbian Jessie
1樹莓派的啟動過程
樹莓派1,2,3的啟動過程大致相同,主要分為3個階段:ROM上的GPU bootloader啟動GPU,GPU啟動CPU,CPU直接啟動內核或通過u-boot啟動內核.
由於樹莓派涉及到GPU的東西不開源,移植u-boot到樹莓派並不是真正意義上的bootloader,但是鑒於u-boot廣泛的應用,還是很有學習的必要
樹莓派啟動過程:
HOW THE RASPBERRY PI BOOTS UP
樹莓派3啟動過程概述
RPi Software
2移植u-boot到Debian Jessie系統
最初想直接移植u-boot到Raspbian,嘗試了多次都失敗告終.google上u-boot啟動raspberry pi大都是基於Debian Jessie,所以先照葫蘆畫瓢試一把.
移植u-boot到樹莓派參考例程
(1)最全面的RPi u-boot例程RPi U-Boot
(2)基於RPi2的例程Booting a Raspberry Pi2, with u-boot and HYP enabled
(3)基於RPi2,提供現成文件的例程Raspberry Pi 2 – Debian Jessie and U-Boot
(4)基於mainline u-boot的例程How to compile mainline u-boot for Raspberry Pi ?
MicroSD卡燒寫鏡像:debian jessie下載地址
Ubuntu主機上u-boot使用Mainline版本,官網源碼 亞馬遜下載地址
Ubuntu主機上文件位置如下
家目錄(/root)下u-boot-2016.09文件夾是解壓後的u-boot
家目錄(/root)下script_u-boot文件夾是自己寫的環境配置,腳本
u-boot-2016.09文件夾如下,可以先讀讀README
script_u-boot文件夾內如下圖,從左到右是scr配置文件,環境配置文件,生成u-boot.bin文件,生成scr文件
env_gnueabihf_mkimage文件代碼如下
#添加樹莓派的交叉編譯工具鏈路徑(主機是64位)
export PATH=$PATH:/root/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin #指定編譯目標架構為arm,編譯器為PATH路徑中的交叉編譯器
export ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
樹莓派交叉編譯工具鏈地址https://github.com/raspberrypi/tools
樹莓派交叉編譯可以參考Linux主機上實現樹莓派的交叉編譯及文件傳輸,遠程登陸
在後續操作之前先source一下這個文件使配置生效,關閉終端或者重新登陸Ubuntu需要再次source
用echo查看變量,注意使用tab自動補全路徑
make_ubootbin文件代碼如下
#從腳本文件夾切換到u-boot文件夾下 cd /root/u-boot-2016.09 #配置適用於樹莓派2的u-boot make rpi_2_defconfig #編譯 make all
#返回腳本文件夾 cd /root/script_u-boot
切換路徑是因為執行這個腳本是在script_u-boot文件夾,而make命令執行Makefile是在u-boot-2016.09文件夾,最後切回路徑方便後續的source
這裡make rpi_2_defconfig是針對樹莓派2板,其它版本樹莓派的make config參考前文的移植u-boot到樹莓派參考例程(1)(4)
執行make_ubootbin無報錯
在u-boot-2016.09文件夾下生成了u-boot.bin
把debian jessie的SD卡通過讀卡器插到電腦,注意先選中虛擬機的Ubuntu系統,Ubuntu會自動讀取(mount)SD卡
rootfs(根文件系統)分區:
firmware(debian jessie下的啟動分區):
關於啟動分區config.txt bootcode.bin cmdline.txt start.elf kernel7.img等文件,參考前文的樹莓派啟動過程
至此可以把u-boot.bin拷到sd卡的firmware(對於debian jessie系統)
然後在config.txt添加
kernel=u-boot.bin
指定用u-boot.bin啟動內核kernel7,config.txt是內核的配置文件,類似電腦的BIOS配置
配置內核的方法:
一種方法是在u-boot階段手動輸入命令,而mainline版本的u-boot不支持usb輸入,嘗試過例程(1)中的Stephen Warren版本,也無法輸入(問題還有待調查)
另一種是把u-boot中輸入的命令寫到一個腳本文件,通過mkimage命令將這個腳本生成.scr鏡像,然後放到啟動分區,u-boot會自動讀取腳本來啟動內核,這樣更簡單更容易修改,但是不利於調試錯誤信息
用第一種方法可以拔出SD卡,在樹莓派上配置內核啟動,注意在u-boot階段只能通過HDMI外接顯示屏或者串口來查看輸出信息.關於串口可以參考RPi Serial Connection
用第二種方法是在Ubuntu主機上生成boot.scr鏡像,先寫一個配置文件:在script_u-boot文件夾下新建configure_scr_file,內容如下
#設置環境為樹莓派2 setenv machid 0x00000c42
#設置打印信息,允許HDMI,允許串口,設置根文件系統路徑和類型 setenv bootargs "earlyprintk console=tty0 console=ttyAMA0 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait noinitrd"
#保存環境配置 saveenv
#載入內核鏡像到MMC0的第一分區 fatload mmc 0:1 ${kernel_addr_r} kernel7.img
#啟動內核 bootz ${kernel_addr_r}
以上命令的語法都是u-boot軟件規定,關於命令的細節可以參考RPi U-Boot 官方文檔U-Bootdoc
然後新建一個腳本make_ubootscr生成scr鏡像,make_ubootscr內容如下
#生成boot.scr鏡像文件 mkimage -A arm -O linux -T script -C none -a 0x00000000 -e 0x00000000 -n "RPi2 Boot Script" -d /path/to/script /boot/firmware/boot.scr
/path/to/script是configure_scr_file的路徑,替換後如下
mkimage -A arm -O linux -T script -C none -a 0x00000000 -e 0x00000000 -n "RPi2 Boot Script" -d /root/script_u-boot/configure_scr_file /boot/firmware/boot.scr
source報錯,提示未安裝mkimage
命令找不到通常是未安裝軟件,或者沒添加路徑,mkimage應該是包含在u-boot軟件中的,由於之前用過樹莓派交叉編譯工具鏈的經驗,在u-boot-2016.09文件夾的tools文件夾找到了mkimage程序
更通用的是用find命令查找
find 查找路徑 -name 文件名
看來是沒有添加mkimage的路徑到環境變量,只需在env_gnueabihf_mkimage添加路徑然後source
env_gnueabihf_mkimage修改如下
export PATH=$PATH:/root/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin:/root/u-boot-2016.09/tools export ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
提示路徑不存在
這時就需要了解這條mkimage命令的具體含義了,參考mkimage - Generate image for U-Boot
/boot/firmware/boot.scr是生成boot.scr文件的路徑,如果在樹莓派上直接操作這個路徑就是啟動分區,但是我是在Ubuntu主機操作,SD卡是掛載到Ubuntu主機的路徑被改變了
查看塊設備可以用命令
lsblk
sdb就是SD卡,sdb1是firmware啟動分區,sdb2是rootfs文件系統分區
事實上插入SD卡時Ubuntu自動把SD卡mount到了主機的/media路徑,所以前面才能對u-boot.bin直接復制粘貼操作
但是想把SD卡的第一分區掛載到其它路徑,比如主機的/mnt文件夾下,應該
mount /dev/sdb1 /mnt
注意設備的實際路徑和掛載後路徑的區別,/dev/xxx才是實際的設備路徑
在debian jessie的樹莓派上查看SD卡路徑如下
這是因為debian jessie沒有自動掛載功能
可以把boot.scr直接生成到firmware下(先在Ubuntu插好SD卡)
mkimage -A arm -O linux -T script -C none -a 0x00000000 -e 0x00000000 -n "RPi2 Boot Script" -d /root/script_u-boot/configure_scr_file /media/boot/firmware/boot.scr
更推薦生成在其它目錄(比如u-boot-2016.09文件夾)再拷到SD卡,最終改為如下,-n是生成的文件名
mkimage -A arm -O linux -T script -C none -a 0x00000000 -e 0x00000000 -n boot.scr -d /root/script_u-boot/configure_scr_file /root/u-boot-2016.09/boot.scr
成功生成boot.scr
在把u-boot.bin boot.scr拷到SD卡的firmware以後,確認config.txt添加了kernel=u-boot.bin就可以拔出SD卡啟動樹莓派2了
啟動過程如下
進入登陸界面
登陸名(login):root
密碼(password):debian
登錄成功,至此在debian jessie上的u-boot移植完成
在主機上交叉編譯生成boot.bin,也可以不添加環境變量ARCH,CROSS_COMPILE,直接在make語句指定編譯器
make_ubootbin可以改為如下
cd /root/u-boot-2016.09 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- rpi_2_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j4 cd /root/script_u-boot
-j4是采用四核處理器四線程編譯,取決於主機CPU WIN7下查看CPU核心數
3移植u-boot到Raspbian Jessie系統
有了前面的嘗試,後面的就水到渠成了
如果直接把剛才生成的u-boot.bin boot.scr拷到raspbian,在config.txt添加kernel=u-boot.bin
啟動後停留在starting kernel...
信息顯示kernel7已經通過boot.scr讀取了,說明問題出在啟動內核之後的部分
對比一下debian jessie和raspbian jessie的分區,文件系統都一樣,就是啟動分區有差別
debian jessie的啟動分區
raspbian jessie的啟動分區
發現raspbian多了一個kernel.img,幾個.dtb文件,overlay裡面也是.dtb文件
參考RPi U-Boot後感覺需要加載dtb(Device Tree binary)
修改boot.scr的配置文件(configure_scr_file)的內容如下
setenv machid 0x00000c42 #添加變量fdtfile的值為bcm2709-rpi-2-b.dtb setenv fdtfile bcm2709-rpi-2-b.dtb setenv bootargs "earlyprintk console=tty0 console=ttyAMA0 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait noinitrd" saveenv fatload mmc 0:1 ${kernel_addr_r} kernel7.img #載入fdtfile的值 fatload mmc 0:1 ${fdt_addr_r} ${fdtfile} bootz ${kernel_addr_r} - ${fdt_addr_r}
這裡添加bcm2709-rpi-2-b.dtb是因為使用樹莓派2,如果是其它版本酌情修改
然後source生成boot.scr
source make_ubootbin
將新的boot.scr拷到boot分區,u-boot.bin和之前完全相同,config.txt添加kernel=u-boot.bin
主機上拔出SD卡,啟動樹莓派
自動登錄進入桌面
至此u-boot在raspbian jessie上移植完成。