2021-05-12 14:32:11
Linux下使用交叉編譯移植U-Boot到樹莓派
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廣泛的應用,還是很有學習的必要
樹莓派啟動過程:
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上移植完成。
本文永久更新連結地址:http://www.linuxidc.com/Linux/2016-09/135470.htm
相關文章