一、概述
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
然后运行如下命令:
sudo ln -s /usr/bin/make /usr/bin/gmake
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/;
/ {
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";
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 {
flash0: flash@0 {
compatible = "n25q512a","micron,m25p80";
reg = <0x0>;
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
|