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等。
四、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卡。
六、常见问题与判断依据
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 串口无任何输出 | 启动模式错误、BOOT.BIN未写入 | 确认MIO[5:3]电平,重新打包BOOT.BIN |
| U-Boot找不到image.ub | FAT分区未挂载或文件名不符 | U-Boot中执行fatls mmc 0:1 |
| 内核panic: no root device | rootfs分区或bootargs错误 | 检查root=/dev/mmcblk0p2与分区实际编号 |
| NFS挂载超时 | 网络不通或exports未生效 | U-Boot中ping主机,主机执行exportfs -v |