1). 簡介
本文簡單介紹ARM嵌入式裝置基于嵌入式Linux作業系統時候的啟動步驟和啟動方式, 差別與X86平台,ARM平台下并沒有一個标準的啟動步驟,不同ARM SoC都會使用各自定義的boot ROM來實作啟動過程,不過大體上面都包含有一些基本步驟。本文就基于Toradex ARM計算機子產品和配套載闆來介紹基于Freescale i.MX6 ARM嵌入式裝置的啟動步驟和方式。
2). 啟動步驟
a). 電源上電,系統Reset。
b). CPU内部boot ROM讀取, strapping GPIO數值鎖定。
c). 根據strapping GPIO值和SoC 内部fuse設定确定用于啟動的裝置。
d). 從啟動裝置起始位置讀取用于配置DDR RAM和定位boot loader的配置資訊。對于i.MX6平台,則使用'image vector table (IVT)' 和 'device configuration data (DCD)' ,如果從NAND裝置啟動,則還包括 'boot control blocks (BCB)'。
e). DDR RAM被boot ROM初始化。
f). boot loader從啟動裝置複制到RAM執行,至此系統控制交由boot loader.也是從這裡,一些定制代碼才可以在boot loader裡面開始執行。當然也有一些SoC是先将boot loader複制到SDRAM執行後再由boot loader來初始化DDR RAM。
Toradex ARM核心闆使用定制化的U-boot作為boot loader,下面就基于此來繼續boot loader加載後的啟動過程。
g). U-Boot從啟動裝置上面讀取環境變量,如果變量資料損壞或者不存在,則會提示'*** Warning - bad CRC, using default environment' ,然後加載預設初始設定.
h). U-Boot通過分析環境變量獲得kernel和rootfs存儲位置,以及所需的kernel command line
i). U-Boot 自動檢測系統RAM和eMMC/Nand Flash容量和參數
j). U-Boot 設定以太網口MAC位址,并配置好硬體準備加載Linux kernel
k). U-Boot 加載Linux kernel到RAM,至此系統控制權則轉移到kernel來處理
l). 系統Kernel初始化Linux,加載rootfs,最後啟動'init'來初始化Linux user space
3). 啟動方式
a). 預設方式, U-Boot, kernel和rootfs都位與子產品自帶的eMMC上,全部從eMMC啟動。通常情況下的基本模式
b). U-Boot位于eMMC,從eMMC啟動;而kernel和rootfs位于SD卡,從SD卡啟動。常用于切換不同的kernel和rootfs版本
c). U-Boot位于eMMC,從eMMC啟動;而kernel從TFTP加載,rootfs從NFS加載。常用于kernel和application開發調試階段
4). 不同啟動方式示範
這裡使用Toradex Apalis i.MX6Q 計算機子產品配合Apalis Eva 開發載闆來進行測試,平台基本的操作上手指南請見這裡。
軟體使用Toradex官方釋出的Linux V2.5beta3版本,請從這裡下載下傳。
a). 全部從eMMC啟動
子產品預設的U-Boot設定即為全部從eMMC啟動,開機上電即可
b). Kernel和rootfs從SD卡啟動
./ 準備SD卡:将SD卡(幾百MB容量以上,這裡使用8GB)分為2個分區,第一個分區為FAT32格式,一般幾十MB即可,這裡示範操作為1GB;另外一個分區為ext3格式,配置設定為剩下SD卡容量。
----------------------------------
$ sudo fdisk /dev/sdc
...
指令(輸入 m 擷取幫助): p
Disk /dev/sdc: 7744 MB, 7744782336 bytes
255 heads, 63 sectors/track, 941 cylinders, total 15126528 sectors
Units = 扇區 of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
裝置 啟動 起點 終點 塊數 Id 系統
/dev/sdc1 2048 2099199 1048576 c W95 FAT32 (LBA)
/dev/sdc2 2099200 15126527 6513664 83 Linux
$ sudo mkfs.vfat -F 32 -n boot /dev/sdc1
$ sudo mkfs.ext3 -L fs /dev/sdc2
./ 制作啟動SD卡
// 複制Linux image 壓縮包裡面的kernel和device tree檔案到FAT32分區
$ cd .../Apalis_iMX6_LinuxImageV2.5/apalis-imx6_bin
$ cp uImage--3.14.28+gitr0632def1c9981e3974f724025f39b2c1588d8ee6-V2.5b3-apalis-imx6-20151215145612.bin /media/username/boot/uImage
$ cp uImage--3.14.28+gitr0632def1c9981e3974f724025f39b2c1588d8ee6-V2.5b3-imx6q-apalis-eval-20151215145612.dtb /media/simon/boot/imx6q-apalis-eval.dtb
// 複制Linux image 壓縮包裡面的rootfs檔案夾内容到ext3分區
$ cd .../Apalis_iMX6_LinuxImageV2.5
$ sudo cp -Ppr rootfs/* /media/simon/fs/
./ 将SD卡插入Apalis Eva載闆8-bit SD卡插槽, 開機上電進入uboot
Apalis iMX6 # printenv
fdt_file=imx6q-apalis-eval.dtb //確定device tree檔案和上面FAT32分區裡面的命名一緻
Apalis iMX6 # run sdboot
./ 啟動後就可以進行正常的應用開發測試了.
c). TFTP/NFS加載kernel/file system啟動
./ 預設目标版系統和開發主機已經在同一區域網路内并通過網内DHCP伺服器自動取得IP位址,如果需要手動搭建DHCP伺服器,請參考這裡。
./ 配置TFTP Server
// 在Ubuntu 開發主機通過下面指令建立TFTP Server
$ sudo apt-get install tftpd-hpa
$ sudo vi /etc/default/tftpd-hpa
//預設tftp server配置,也可以更換目錄,不過需要修改目錄group為”nogroup”
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/var/lib/tftpboot"
TFTP_ADDRESS="[::]:69"
TFTP_OPTIONS="--secure"
$ sudo service tftpd-hpa start
//如已經啟動,重新加載配置,則可運作
$ sudo service tftpd-hpa force-reload
// 複制kernel和device tree檔案到TFTP Server檔案夾
$ sudo cp uImage--3.14.28+gitr0632def1c9981e3974f724025f39b2c1588d8ee6-V2.5b3-apalis-imx6-20151215145612.bin /var/lib/tftpboot/uImage
$ sudo cp uImage--3.14.28+gitr0632def1c9981e3974f724025f39b2c1588d8ee6-V2.5b3-imx6q-apalis-eval-20151215145612.dtb /var/lib/tftpboot/imx6q-apalis-eval.dtb
./ 配置NFS Server
// 在Ubuntu 開發主機通過下面指令建立NFS Server
$ sudo apt-get install nfs-kernel-server
$ sudo vi /etc/exports
//增加下面NFS配置, ‘10.20.1.111/24’為開發主機IP/Mask配置
/srv/nfs 10.20.1.111/24(no_root_squash,no_subtree_check,rw,fsid=root)
$ sudo service nfs-kernel-server restart
// 複制rootfs檔案到NFS Server檔案夾
$ sudo cp -Ppr rootfs/* /srv/nfs/
./ 配置Apalis i.MX6目标系統
//開機上電進入Uboot,修改如下參數
# setenv serverip ‘10.20.1.111’ //TFTP Server IP
# setenv nfsargs ‘ip=10.20.1.115:10.20.1.111:10.20.1.1:255.255.255.0::eth0:on root=/dev/nfs nfsroot=10.20.1.111:/srv/nfs rw netdevwait’
// ip = 目标闆IP:NFS Server IP:網關:Mask
// 啟動NFS boot
# run nfsboot