一、概述

1.设计目标

  • 1.u-boot可以正常运行,并正确引导Linux内核启动。其中Linux内核文件、设备树文件、PL部分描述文件通过TFTP服务加载,根文件系统通过NFS服务挂载。
  • 2.使用一个MIO GPIO、一个EMIO GPIO、一个AXI GPIO共三个GPIO驱动三个LED灯显示系统运行状态。
  • 3.通过USB接口可以进行U盘文件读取。
  • 4.可以正常读取SD卡、EMMC中文件。

2.设计内容

  • 1.系统硬件描述文件hdf。
  • 1.系统启动文件BOOT.BIN,内包括zynq引导程序FSBL,Linux引导程序u-boot。
  • 2.Linux内核文件zImage。
  • 3.设备树文件system.dtb。
  • 4.PL部分比特流文件system.bit。
  • 5.根文件系统。

二、硬件平台搭建

根据设计目标与开发板设计搭建zynq硬件平台,需要开启外设SPI Flash、SD0、SD1、UART1、Ethernet0、USB0、MIO、EMIO,其中EMIO只需1位即可,此外还需添加AXI GPIO,同样开启1位。硬件设计如下图所示:
在这里插入图片描述
编译工程到处hdf文件design_1_wrapper.hdf。其中到处hdf文件时需要包含bit文件。

三、由hdf文件得到bit文件、设备树文件、FSBL

1.在系统用户目录下创建“work”文件夹作为工程目录,在work目录下创建“hdf”文件夹,将design_1_wrapper.hdf文件保存到此文件夹内。下载Xilinx device-tree,解压到“~/work/device-tree”目录下并重命名为device-tree。下载Xilinx embeddedsw解压到“~/work/embeddedsw”并重命名为embeddedsw,如下图所示:
在这里插入图片描述
2.在work目录下新建一个名为hsi.tcl的tcl脚本,内容入下:

hsi::open_hw_design ./hdf/design_1_wrapper.hdf
hsi::set_repo_path ./device-tree/device-tree
hsi::create_sw_design device-tree -os device_tree -proc ps7_cortexa9_0
hsi::generate_target -dir ./device-tree
hsi::set_repo_path ./embeddedsw/embeddedsw
hsi::generate_app -hw design_1_wrapper -os standalone -proc ps7_cortexa9_0 -app zynq_fsbl -compile -sw fsbl -dir ./embeddedsw

然后运行如下命令:

#建立一个软链接文件 gmake,链接到 make
sudo ln -s /usr/bin/make /usr/bin/gmake
#执行tcl命令
xsct hsi.tcl

程序会根据hdf文件得到bit文件、设备树文件、zynq引导程序,如下图所示。将bit文件复制到TFTP服务目录下并更名为system.bit。
在这里插入图片描述
3.将system-top.dts修改为如下内容:

/*
 * CAUTION: This file is automatically generated by Xilinx.
 * Version:  
 * Today is: Mon Jan 10 19:24:27 2022
 */


/dts-v1/;
#include "zynq-7000.dtsi"
#include "pl.dtsi"
#include "pcw.dtsi"

#define GPIO_ACTIVE_LOW 1
#define GPIO_ACTIVE_HIGH 0

/ {
	chosen {
		bootargs = "earlycon";
		stdout-path = "serial0:115200n8";
	};
	aliases {
		ethernet0 = &gem0;
		serial0 = &uart1;
		spi0 = &qspi;
	};
	memory {
		device_type = "memory";
		reg = <0x0 0x40000000>;
	};
	usb_phy0: phy0@e0002000 {
 		compatible = "ulpi-phy";
 		#phy-cells = <0>;
 		reg = <0xe0002000 0x1000>;
 		view-port = <0x0170>;
		drv-vbus;
	};
	user-leds {
		compatible = "gpio-leds";
		gpio-led1 {
			label = "led1";
			gpios = <&axi_gpio_0 0 0 GPIO_ACTIVE_HIGH>;
			linux,default-trigger = "heartbeat";
			default-state = "on";
		};
		gpio-led2 {
			label = "led2";
			gpios = <&gpio0 54 GPIO_ACTIVE_HIGH>;
			linux,default-trigger = "heartbeat";
			default-state = "on";
		};
		gpio-led3 {
			label = "led3";
			gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
			linux,default-trigger = "heartbeat";
			default-state = "on";
		};
	};
};

&gem0 {
	local-mac-address = [00 0a 35 00 00 00];
};
&qspi {
	#address-cells = <1>;
	#size-cells = <0>;
	flash0: flash@0 {
		compatible = "n25q512a","micron,m25p80";
		reg = <0x0>;
		#address-cells = <1>;
		#size-cells = <1>;
		spi-max-frequency = <50000000>;
		partition@0x00000000 {
			label = "boot";
			reg = <0x00000000 0x00500000>;
		};
		partition@0x00500000 {
			label = "bootenv";
			reg = <0x00500000 0x00020000>;
		};
		partition@0x00520000 {
			label = "kernel";
			reg = <0x00520000 0x00a80000>;
		};
		partition@0x00fa0000 {
			label = "spare";
			reg = <0x00fa0000 0x00000000>;
		};
	};
};
&usb0 {
	dr_mode = "otg";
	usb-phy = <&usb_phy0>;
};

四、编译u-boot

1.添加设备树

1.将前面生成修改后的设备树文件pcw.dtsi、pl.dtsi、system-top.dts以及 zynq-7000.dtsi四个文件拷贝到u-boot源码目录下的arch/arm/dts目录下。
2.在arch/arm/dts/Makefile文件中,找到dtb-$(CONFIG_ARCH_ZYNQ)这里,将system-top.dtb添加上去,如下图:
在这里插入图片描述

2.修改zynq-common.h和zynq_zc70x.h配置文件

1.在include/configs目录下,找到zynq-common.h与zynq_zc70x.h文件。
2.将zynq_zc70x.h中CONFIG_ZYNQ_I2C0和CONFIG_ZYNQ_EEPROM宏定义注释掉,如下图所示:
在这里插入图片描述
3.接下来修改zynq-common.h文件,打开该文件,修改CONFIG_CPU_FREQ_HZ(ARM主频),将频率由800000000修改为666666687。
在这里插入图片描述

修改CONFIG_SF_DEFAULT_SPEED(默认的QSPI速率),由30000000改为50000000,如下所示:
在这里插入图片描述
修改CONFIG_ENV_SIZE(环境变量大小),由(128 << 10)修改为0x20000:
在这里插入图片描述
修改CONFIG_ENV_OFFSET(环境变量存储位置偏移量),由0xE0000修改为0x500000:
在这里插入图片描述
需要注意CONFIG_ENV_SIZE和CONFIG_ENV_OFFSET这两个是u-boot环境变量存储有关的,与之前修改的设备树文件system-top.dts中对应:
在这里插入图片描述

3.u-boot配置

1.载u-boot源码目录下执行如下命令进行默认配置:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zynq_zc702_defconfig

2.执行如下命令进行图形化配置:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig

执行命令后进入如下界面:
在这里插入图片描述
3.进行如下配置:

SPL / TPL --->
	[ ] Enable SPL // 取消
Command line interface --->
	Memory commands --->
		[ ] eeprom - EEPROM subsystem // 取消
	Device access commands --->
		[ ] i2c // 取消
Device Tree Control --->
	(system-top) Default Device Tree for DT control // 将设备树设置为 system-top(也就是 system-top.dts)

4.编译

配置完成后执行如下命令,编译u-boot

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j10

编译完成后在源码目录下可得到u-boot文件,其为elf格式的镜像文件。

5.生成BOOT.BIN文件

在u-boot源码目录下执行如下命令:

mv u-boot u-boot.elf
petalinux-package --boot -p ~/petalinux/LGD-ZYNQ --fsbl ~/work/embeddedsw/executable.elf --u-boot ./u-boot.elf -o ./BOOT.BIN --force

其中,~/petalinux/LGD-ZYNQ为一个Petalinux工程目录,~/work/embeddedsw/executable.elf为FSBL文件目录。执行后源文件目录下即可找到BOOT.BIN文件,如下图所示:
在这里插入图片描述

五、编译kernel

1.添加设备树

1.将前面生成修改后的设备树文件pcw.dtsi、pl.dtsi、system-top.dts以及zynq-7000.dtsi四个文件直接拷贝到内核源码目录下的arch/arm/boot/dts目录中。同样我需要修改arch/arm/boot/dts目录下的Makefile文件,将设备树添加上去,如下:
2.在arch/arm/boot/dts/Makefile文件中,找到 dtb-$(CONFIG_ARCH_ZYNQ)这里,将system-top.dtb添加上去,如下图:
在这里插入图片描述

2.kernel配置

1.在Linux源码目录下执行如下命令进行默认配置:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- xilinx_zynq_defconfig

2.执行如下命令进行图形化配置:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig

执行命令后进入如下界面:
在这里插入图片描述
Xilinx官方的内核默认已经使能了U盘类设备的驱动,使用默认配置即可。

3.编译

执行如下命令,编译kernel

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage -j10

编译完成之后会在arch/arm/boot/目录下生成一个名为zImage的内核镜像文件,将其复制到TFTP服务目录下。

六、编译设备树

在Linux源码目录下执行如下命令,编译设备树。

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- system-top.dtb -j10

编译成功之后会在arch/arm/boot/dts目录下生成system-top.dtb文件,将其复制到TFTP服务目录下,并更名为system.dtb。

七、编译rootfs

根文件系统我们直接使用之前Petalinux编译生成的根文件系统即可,使用如下命令将rootfs.tar.gz解压缩至NFS服务目录下,及/home/lgd/nfs/linux目录。

sudo tar -xzf rootfs.tar.gz -C /home/lgd/nfs/linux

解压完毕之后结果如下图所示:
在这里插入图片描述

八、启动开发板

1.确认TFTP服务目录下存在system.bit、system.dtb、zImage文件:
在这里插入图片描述

2.将BOOT.BIN文件复制到SD卡中,插入开发板,连接好串口、网线,开启开发板电源,打印信息如下:
在这里插入图片描述
3.在u-boot启动倒计时之前,按回车键停止启动,进入到u-boot的命令行模式,因为现在不能直接启动,我们需要对u-boot环境变量进行修改,在u-boot命令行下执行下面这些命令设置环境变量:

dhcp
setenv serverip 192.168.137.15
setenv loadbit_addr 0x100000
setenv bitstream_image system.bit
setenv kernel_load_address 0x2080000
setenv kernel_image zImage
setenv devicetree_load_address 0x2000000
setenv devicetree_image system.dtb
setenv rootpath /home/lgd/nfs/linux
setenv bootargs root=/dev/nfs nfsroot=${serverip}:${rootpath}, tcp rw ip=${ipaddr}:${serverip}:${gatewayip}:${netmask} ::eth0:on console=ttyPS0,115200 earlyprintk

首先使用dhcp获取IP地址,然后设置所需环境变量。执行结果如下:
在这里插入图片描述
4.使用如下命令加载system.bit、zImage、system.dtb文件,并给PL加载bit文件:

tftpboot ${loadbit_addr} ${bitstream_image} && tftpboot ${kernel_load_address} ${kernel_image} && tftpboot ${devicetree_load_address} ${devicetree_image}
fpga loadb 0 ${loadbit_addr} ${bitstream_size}

执行结果如下:
在这里插入图片描述
在这里插入图片描述
5.使用如下命令启动Linux系统:

bootz ${kernel_load_address} - ${devicetree_load_address}

执行结果如下:
在这里插入图片描述
输入用户名“root”,密码“root”就可以登陆。

九、系统测试

1.LED测试

启动Linux系统后,可以观察到MIO GPIO、EMIO GPIO、AXI GPIO对应的三个LED灯闪烁。

2.SD卡测试

1.登陆系统之后执行df -h命令,如下图:
在这里插入图片描述
即可看到SD卡两个分区在系统中的目录,进入/run/media/mmcblk0p1目录:
在这里插入图片描述
可以看到之前复制到SD卡的BOOT.BIN文件。

3.EMMC测试

1.由于EMMC没有分区,所以系统不会自动挂载,需要先将EMMC进行设置,进入到/dev目录,可以找到EMMC对应的设备节点:
在这里插入图片描述
其中mmcblk0由上一节知道,其为SD卡,所以mmcblk1为EMMC对应的设备节点。
2.输入如下命令:

fdisk /dev/mmcblk1

按照下图步骤进行设置:
在这里插入图片描述

分区确认正确后输入“w”保存并退出,如下图:
在这里插入图片描述
设置成功后,查看/dev目录,mmcblk1p1即为EMMC的分区,如下图:
在这里插入图片描述

3.在/run/media目录下新建文件夹mmcblk1p1,输入如下命令将emmc格式化并挂载:

mkfs.vfat -F 32 -n emmc /dev/mmcblk1p1
mount /dev/mmcblk1p1 /run/media/mmcblk1p1

使用df -h查看,结果如下:
在这里插入图片描述
可见,EMMC已经成功挂载至系统。

4.USB U盘测试

1.将U 盘连接至开发板,会输出以下信息:
在这里插入图片描述
再次输入df -h命令,即可看到U盘已经挂载至系统,进入U盘目录,使用ls命令可查看U盘内文件,与将之连接至电脑时查看到的内容相同。
在这里插入图片描述

十、相关下载链接

device-tree xilinx-v2018.3
embeddedsw xilinx-v2018.3

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐