參考:

問題:
1.ZYNQ Linux啟動流程:
BOOTROM→FSBL→Uboot→Kernel→RootFS
環境:
虛擬機ubuntu16.04
petalinux2018.3
vivado2018.3
開發板:小熊貓z7020
前言
使用ZYNQ大概率會用到Linux。這里就對linux移植的整個流程做一個記錄。
移植有兩種方式:
(1)使用petalinux工具鏈進行移植。虛擬機需要裝petalinux,自動化程度相對高。
(2)手動移植,需安裝SDK移植環境或者petalinux的環境,兩者貌似是一樣的。
實際上,rootfs是可以隨便用哪個的。比如,可以混搭手動移植的uboot\kernel,而使用petalinux的rootfs。或者使用petalinux的image.ub,而使用debian等三方rootfs。看需要使用。
手動移植可以更熟悉定制方面的內容,當然更為繁瑣。
- 建立BSP:
首先我們從建立底層硬件平台開始,其定義了底層的設備樹相關內容、PL端功能等。
這里使用了網口0、SD卡、UART1,根據原理圖分配管腳即可,網口和SD卡的管腳使用fast,設置好DDR信息。
(1)配置ZYNQ:

(2)正常綜合編譯生成bit導出BSP到文件夾。

(3)打開SDK查看一下是否導入成功。
- SD卡分區:本次移植u-boot、kernel、rootfs都在SD上。
分兩個區即可,BOOT分區和RootFS分區,前面的分區用於存儲u-boot和內核和PL端的bit,后一個分區用於存儲根文件系統。
(1)在ubuntu中安裝
gparted。使用圖形化界面簡化操作,可直接在命令行中打開。

(2)切換到sd卡,可根據容量確認。

右鍵刪除分區。

新建BOOT分區:
最起始保留4MB空間,這里分512M,文件格式fat32,標簽設置為BOOT。

剩下的全部分為RootFS分區。

至此,分區完成。
下述會講述petalinux的移植方式和手動移植的方式。
一、petalinux移植
對於初學者,自然,petalinux是一種更為簡便的方式,敲幾個命令即可得到控制台的歡喜,而手動移植的坑還蠻多的。
(1)導出前述bsp到虛擬機:

(2)隨便哪個位置新建個目錄,並把sdk文件夾放入。
這里新建個demo_linux文件夾。

(3)
source下petalinux的環境(可放在bashrc中自動source,避免手動敲)。路徑根據petalinux的安裝路徑進行選擇。
source /home/kingstacker/petalinux2018.3/settings.sh

(4)
新建一個petalinux項目:這里新建了個demo1_linux工程,路徑下會自動新建demo1_linux文件夾,模板使用zynq,zynq7系列應該都是這個。
petalinux-create -t project -n demo1_linux --template zynq
(5)
cd到這個工程下面:
cd demo1_linux/
(6)
導入上層的SDK文件夾內容:會自動彈出配置窗口。
petalinux-config --get-hw-description=/home/kingstacker/demo_linux/project_1.sdk
(7)
配置使用哪個串口進行打印。這里我使用的是PS端的串口1,波特率115200,跟ZYNQ配置時保持一致即可。
在Subsystem AUTO Hardware Settings選項下的Serial Settings設置。

(8)
設置bootargs,用於打印信息的串口指定,指定內核啟動位置。注意:我這里使用了自動生成頭,不使用自動的沒得實驗成功。
在DTG Setting選項卡下第三行修改如下:
鍵入bootargs:我這里使用了PS端的uart1(在設備樹中被alias到了serial0),內核要從SD卡的第二個分區啟動,分區格式為ext4。
console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait

在Image Packaging Configuration中設置根文件系統類型,這里為SD卡。

切換到save保存主項配置,然后按兩次ESC退出。

根據需要配置u-boot\kernel\rootfs內容,這里不配置使用默認,直接運行build即可。
petalinux-config -c u-boot
petalinux-config -c kernel
petalinux-config -c rootfs
(9)編譯工程,打把游戲回來再看:
petalinux-build

(10)切換到
image目錄下的linux目錄,執行語句生成BOOT.BIN文件。

petalinux-package --boot --format BIN --fsbl zynq_fsbl.elf --fpga system.bit --u-boot

(11)
復制BOOT.BIN和image.ub文件到SD卡的BOOT分區。
我這里BOOT路徑如下:

cp BOOT.BIN /media/kingstacker/BOOT/
cp image.ub /media/kingstacker/BOOT/

(12)
解壓文件系統到SD卡的RootFS分區。
sudo tar xvf rootfs.tar.gz -C /media/kingstacker/RootFS/

至此,完成了所有內容,把SD卡放到板子上,切換板子啟動模式為SD卡啟動,連接CRT顯示串口打印信息。
其他:
QEMU仿真:對於petalinux編譯的系統,其提供了仿真工具,在上板之前就可以知道Uboot和Kernel是否可以啟動。
(1)在工程目錄下執行下述打包命令:
petalinux-package --prebuilt
(2)進行第三階段仿真:
petalinux-boot --qemu --prebuilt 3

可以看到在等待文件系統,則表示成功。
也可以單獨仿真uboot、kernel:
petalinux-boot --qemu --u-boot
petalinux-boot --qemu --kernel

還有一些高級用法這里不表。
二、手動移植linux:
(1)獲取u-boot\kernel、device tree。
- 下載xilinx的u-boot、kernel:
git clone https://github.com/Xilinx/u-boot-xlnx.git
git clone https://github.com/Xilinx/linux-xlnx.git
git checkout 檢出想使用的版本,git tag查看所有可用的版本。
u-boot 2018.3貌似沒得zynq_zc702_defconfig這個配置文件,可檢出到2018.1拷貝一份。
確保含有device tree文件,沒有就要下載並導入到SDK的倉庫中:
git clone https://github.com/Xilinx/device-tree-xlnx
(2)設備樹編譯:
- 工程導入SDK生成設備樹:就是新建個設備樹工程。
- 設備樹信息導入linux中生成dtb文件:
導入bsp信息:

右鍵命令行中運行:
首先source下SDK的settings.sh環境,source petalinux的sh文件也是一樣的:

歸集dts文件到一個文件中:
cpp -nostdinc -I include -I arch -undef -x assembler-with-cpp system-top.dts system-top.dts.preprocessed
編譯設備樹,生成dtb:
dtc -I dts -O dtb -i . -o devicetree.dtb system-top.dts.preprocessed
可以看到文件夾下生成了dtb文件:

(3)編譯uboot:2018.3沒得zc702,所以這里檢出了2018.1的版本。
這里可以使用zc702的defconfig文件,其在xil_source/u-boot-xlnx/configs路徑下。
CONFIG_ARM=y
CONFIG_SYS_CONFIG_NAME="zynq_zc70x"
CONFIG_ARCH_ZYNQ=y
CONFIG_SYS_TEXT_BASE=0x4000000
CONFIG_SYS_MALLOC_F_LEN=0x800
CONFIG_IDENT_STRING=" Xilinx Zynq ZC702"
CONFIG_SPL_STACK_R_ADDR=0x200000
CONFIG_DEFAULT_DEVICE_TREE="zynq-zc702"
CONFIG_DEBUG_UART=y
CONFIG_DISTRO_DEFAULTS=y
CONFIG_FIT=y
CONFIG_FIT_SIGNATURE=y
CONFIG_FIT_VERBOSE=y
CONFIG_BOOTCOMMAND="run $modeboot || run distro_bootcmd"
# CONFIG_DISPLAY_CPUINFO is not set
CONFIG_SPL=y
CONFIG_SPL_STACK_R=y
CONFIG_SPL_OS_BOOT=y
CONFIG_SYS_PROMPT="Zynq> "
CONFIG_CMD_THOR_DOWNLOAD=y
CONFIG_CMD_EEPROM=y
CONFIG_CMD_MEMTEST=y
CONFIG_CMD_DFU=y
# CONFIG_CMD_FLASH is not set
CONFIG_CMD_FPGA_LOADBP=y
CONFIG_CMD_FPGA_LOADFS=y
CONFIG_CMD_FPGA_LOADMK=y
CONFIG_CMD_FPGA_LOADP=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_I2C=y
CONFIG_CMD_MMC=y
CONFIG_CMD_SF=y
CONFIG_CMD_USB=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_CMD_TFTPPUT=y
CONFIG_CMD_CACHE=y
CONFIG_CMD_EXT4_WRITE=y
CONFIG_OF_EMBED=y
#CONFIG_ENV_IS_IN_SPI_FLASH=y
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_DM_SEQ_ALIAS=y
CONFIG_DFU_MMC=y
CONFIG_DFU_RAM=y
CONFIG_FPGA_XILINX=y
CONFIG_DM_GPIO=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_ZYNQ=y
CONFIG_SPI_FLASH=y
CONFIG_SPI_FLASH_BAR=y
CONFIG_SF_DUAL_FLASH=y
CONFIG_SPI_FLASH_ISSI=y
CONFIG_SPI_FLASH_MACRONIX=y
CONFIG_SPI_FLASH_SPANSION=y
CONFIG_SPI_FLASH_STMICRO=y
CONFIG_SPI_FLASH_WINBOND=y
CONFIG_PHY_MARVELL=y
CONFIG_PHY_REALTEK=y
CONFIG_PHY_XILINX=y
CONFIG_ZYNQ_GEM=y
CONFIG_DEBUG_UART_ZYNQ=y
CONFIG_DEBUG_UART_BASE=0xe0001000
CONFIG_DEBUG_UART_CLOCK=50000000
CONFIG_ZYNQ_SERIAL=y
CONFIG_ZYNQ_QSPI=y
CONFIG_USB=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_ULPI_VIEWPORT=y
CONFIG_USB_ULPI=y
CONFIG_USB_STORAGE=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_MANUFACTURER="Xilinx"
CONFIG_USB_GADGET_VENDOR_NUM=0x03fd
CONFIG_USB_GADGET_PRODUCT_NUM=0x0300
CONFIG_CI_UDC=y
CONFIG_USB_GADGET_DOWNLOAD=y
因為沒有用到flash則並修改下述:關掉
不然啟動時候會卡死在SPI flash初始化部分

清除中間編譯:
make distclean
使用配置文件:
make CROSS_COMPILE=arm-linux-gnueabihf- zynq_zc702_defconfig
通過下述指令可在界面中uboot進行進一步修改配置:改defconfig文件也可以
make CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
工具編譯:
make CROSS_COMPILE=arm-linux-gnueabihf- tools
編譯u-boot:
make CROSS_COMPILE=arm-linux-gnueabihf-
最后把編譯生成的
u-boot
后綴改成
.elf。
(4)生成FSBL文件並合成BOOT.BIN:
- 在SDK中先生新建fsbl工程成FSBL,在src的h文件中添加debug屬性,可以在控制台中打印FSBL階段的啟動信息:
#define FSBL_DEBUG_INFO

SDK中合成BOOT.BIN文件:uboot.elf、fsbl.elf、bit。
復制BOOT.BIN到SD卡的BOOT分區。上電確認BOOT.BIN是否可以正常啟動。


(5)內核編譯:
切換到linux-xlnx目錄。
注意:錯誤的解決:
解決 "mkimage" command not found - U-Boot images will not be built
sudo apt-get install u-boot-tools
或者#export PATH=${YOUR_UBOOT_DIR}/tools:$PATH //編譯內核如果要生成uImage,則需要用到mkimage工具,該工具在u-boot/tools下有提供
或者直接復制mkimage到/bin目錄即可,生成uimage會用到。
清除老的編譯文件:
#make distclean
配置:
#make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- xilinx_mz7x_defconfig
根據需要對內核進行圖形化界面的配置:暫時默認就好
#make ARCH=arm menuconfig
編譯工具:
#make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- prepare scripts
編譯內核生成uimage:
#make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- UIMAGE_LOADADDR=0x8000 uImage
(6)定制文件系統:
- 文件系統:
這里文件系統使用debian,也可用別的,無所謂。
安裝arm環境和debootstrap:
sudo apt-get install binfmt-support qemu qemu-user-static debootstrap
debian提取:
sudo debootstrap --arch=armhf --foreign stretch rootfs http://cdn.debian.net/debian
拷貝到bin路徑:
cp /usr/bin/qemu-arm-static {{剛剛rootfs目錄}}/usr/bin
在rootfs文件夾的上層執行:
DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C chroot rootfs debootstrap/debootstrap --second-stage
進入rootfs:
chroot rootfs
添加源到list:
echo deb http://ftp.cn.debian.org/debian/ stretch main > /etc/apt/sources.list
更新:
apt-get update
按需安裝相關包:
apt-get install vim sudo net-tools
debian9啟動后網口默認沒有自動掛載,開發者可以指定rc.local(注意給權限777)文件中自動執行腳本,使用腳本配置網口,腳本注意給權限chmod +x xx.sh。
而debian9默認不帶rc.local。解決方法:
https://www.cnblogs.com/flymeng/p/7901062.html
比如我這里新建/etc/rc.local文件:放入了sh_boot.sh文件。
#!/bin/sh -e
#
#rc.local
#sh in there
/home/sh_boot.sh
#sh end
exit 0
EOF
給權限:chmod 777 /etc/rc.local
在home路徑放入sh文件,即可。(注意別放在普通用戶文件夾下,否則無法上電就執行了)配置網口0使用,根據需要修改。
echo "Welcome to use,powerd by kingstacker"
echo "config the eth......."
ifconfig eth0 192.168.0.110 netmask 255.255.255.0 up
echo "config finish."
給權限:chmod 777 /home/sh_boot.sh
命令行執行exit 退出。
- 打包rootfs備份:
文件夾壓縮:
切換到rootfs路徑,執行:
tar -zcvf debian9_rootfs.tar.gz ./
文件夾解壓到SD卡的rootfs:
tar zxvf debian9_rootfs.tar.gz -C /media/kingstacker/RootFS
debian9 rootfs文件堅果雲分享:
https://www.jianguoyun.com/p/DdhhnukQ15CBCBjvgrcD
普通用戶登錄及密碼:kingstacker
su登錄密碼:123123
(7)復制相關文件到SD卡的BOOT分區,並添加uEnv.txt文件:
- SD卡BOOT分區內容如下:bin文件、設備樹、txt、內核鏡像。

uEnv.txt:其指定了內核傳參。表示uart速率115200,使用ttyPS0。根目錄為SD卡的第二個分區。
bootargs=console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait
load_image=fatload mmc 0 ${kernel_load_address} ${kernel_image} && fatload mmc 0 ${devicetree_load_address} ${devicetree_image}
uenvcmd=echo Copying Linux from SD to RAM... && mmcinfo && run load_image && bootm ${kernel_load_address} - ${devicetree_load_address}
而S
D卡的RootFS分區存儲了根文件系統:

至此,移植結束,插到板子上,享受勞動成果吧。

以上。