4. 嵌入式Linux系统构建与启动

在Zynq平台上跑通嵌入式Linux,核心工作可以概括为一句话:把“硬件描述、内核、根文件系统、启动介质”四件事对齐。PetaLinux正是Xilinx(AMD)提供的这套对齐工具链,它把Yocto的复杂性封装成petalinux-*命令,让开发者围绕一个工程目录完成从硬件导入到镜像烧写的全过程。本节以Zynq-7000/Zynq UltraScale+通用流程为主线,给出可复现的工程创建、设备树定制、内核配置、根文件系统制作,以及SD卡启动与网络启动两条启动路径。

一、PetaLinux工程创建与硬件导入

PetaLinux工程必须绑定一份硬件描述文件(XSA)。XSA由Vivado在导出硬件时生成,包含PS配置、时钟、DDR、外设IP地址以及可选的bitstream。工程创建的第一步是设置环境并新建工程:

source /opt/pkg/petalinux/2023.2/settings.sh
petalinux-create -t project --name zynq_net --template zynq
cd zynq_net
petalinux-config --get-hw-description=../hw/system.xsa

执行petalinux-config后会进入一个Kconfig菜单,其中Subsystem AUTO Hardware Settings会自动从XSA读取串口、以太网、SD控制器、QSPI等配置。这里需要重点确认三项:串口是否指向PS UART0/1、以太网PHY接口类型(MIO或EMIO、RGMII或GMII)、SD控制器是否使能。若硬件中使用了自定义IP或AXI外设,需在DTG Settings中确认设备树生成器能识别对应节点。配置完成后保存退出,工程目录下会生成project-spec/、components/、images/等结构。

二、设备树定制

PetaLinux的设备树分两层:system-user.dtsi是用户定制入口,位于project-spec/meta-user/recipes-bsp/device-tree/files/;底层由DTG根据XSA自动生成pl.dtsi和system-top.dts。定制原则是“只改用户层,不动自动生成层”。

典型定制包括:修改以太网PHY地址与复位GPIO、增加I2C从设备、配置GPIO按键与LED、为自定义AXI IP添加compatible与reg。例如为PS以太网增加PHY复位:

&gem0 {
    phy-handle = <&phy0>;
    phy0: ethernet-phy@1 {
        reg = <1>;
        reset-gpios = <&gpio0 47 GPIO_ACTIVE_LOW>;
    };
};

修改后执行petalinux-build -c device-tree单独编译设备树,产物为images/linux/system.dtb。若启动后/proc/device-tree下看不到新增节点,优先检查system-user.dtsi是否被正确包含,以及节点标签是否与底层一致。

三、内核配置与根文件系统

内核配置通过petalinux-config -c kernel进入。网络与数据传输系统通常需要确认:CONFIG_NETDEVICES、CONFIG_MACB(Zynq千兆网)、CONFIG_STMMAC_ETH(UltraScale+)、CONFIG_USB_GADGET、CONFIG_EXT4_FS、CONFIG_NFS_FS与CONFIG_ROOT_NFS。若使用网络启动,CONFIG_IP_PNP与CONFIG_IP_PNP_DHCP必须打开,否则内核无法通过DHCP获取IP。

根文件系统由petalinux-config -c rootfs配置,可选择petalinux-image-minimal或petalinux-image-full。最小系统约30~50MB,适合SD卡启动;完整系统包含Python、GCC、调试工具,适合开发阶段。若需加入自定义应用,可在project-spec/meta-user/recipes-apps/下新建recipe,再在rootfs菜单中勾选。构建命令为petalinux-build,最终镜像位于images/linux/,包括BOOT.BIN、image.ub、rootfs.ext4等。

Zynq 嵌入式 Linux 构建与启动数据流 Vivado 硬件导出 system.xsa(PS+DDR+IP) PetaLinux 工程 petalinux-create / config 设备树定制 system-user.dtsi 内核配置 MACB / NFS / IP_PNP 根文件系统 rootfs.ext4 / image.ub images/linux/ BOOT.BIN image.ub system.dtb rootfs.ext4 boot.scr 路径 A:SD 卡启动 FAT 分区 BOOT.BIN / image.ub EXT4 分区 rootfs.ext4 FSBL → U-Boot → Kernel → rootfs 启动模式:SD0(MIO[5:3]=001) 路径 B:网络启动(TFTP + NFS) TFTP 服务器 image.ub / system.dtb NFS 服务器 /nfsroot U-Boot: tftpboot → bootm → nfsroot 启动模式:QSPI/JTAG 加载 U-Boot 关键校验:串口打印 U-Boot 版本 → 内核解压 → 挂载 rootfs → 登录提示符

四、SD卡启动

SD卡启动是最常用的独立运行方式。将SD卡分为两个分区:第一个FAT32分区存放BOOT.BIN、image.ub、boot.scr;第二个EXT4分区存放rootfs.ext4解压后的根文件系统。BOOT.BIN由FSBL、bitstream(可选)和U-Boot打包而成,命令为:

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

将SD卡插入Zynq板,设置启动模式为SD0(MIO[5:3]=001),上电后串口应依次输出FSBL版本、U-Boot版本、内核解压信息,最后出现登录提示符。若卡在“Waiting for root device”,通常是rootfs分区未正确写入或bootargs中root=指向错误;若U-Boot找不到image.ub,检查FAT分区格式与文件名大小写。

五、网络启动

网络启动适合频繁迭代内核与根文件系统的开发阶段。主机端需搭建TFTP与NFS服务:TFTP根目录放置image.ub与system.dtb,NFS导出/nfsroot为根文件系统。U-Boot中设置:

setenv ipaddr 192.168.1.10
setenv serverip 192.168.1.100
setenv bootargs 'console=ttyPS0,115200 root=/dev/nfs rw nfsroot=192.168.1.100:/nfsroot ip=dhcp'
tftpboot 0x10000000 image.ub
bootm 0x10000000

内核需已编译CONFIG_ROOT_NFS与CONFIG_IP_PNP_DHCP。启动成功的标志是内核打印“IP-Config: Got DHCP answer”并挂载NFS根目录。若出现“NFS: mount failed”,检查主机/etc/exports是否包含/nfsroot *(rw,sync,no_root_squash),以及防火墙是否放行2049端口。网络启动的优点是改内核只需替换TFTP目录文件,无需反复烧写SD卡。

SD卡启动与网络启动并非互斥:可先用SD卡启动验证硬件与设备树,再切换到网络启动加速开发迭代,最终量产时回到SD卡或QSPI固化。

六、常见问题与判断依据

现象可能原因排查方法
串口无任何输出启动模式错误、BOOT.BIN未写入确认MIO[5:3]电平,重新打包BOOT.BIN
U-Boot找不到image.ubFAT分区未挂载或文件名不符U-Boot中执行fatls mmc 0:1
内核panic: no root devicerootfs分区或bootargs错误检查root=/dev/mmcblk0p2与分区实际编号
NFS挂载超时网络不通或exports未生效U-Boot中ping主机,主机执行exportfs -v