Zynq 7000使用NAND Flash启动UBIFS文件系统全攻略(基于PetaLinux 2017.4)
前言
在Zynq 7000的嵌入式开发中,NAND Flash由于容量大、价格便宜,常被用作主要的存储介质。但NAND Flash存在坏块问题,如果直接使用传统的ext4或jffs2文件系统,容易导致数据损坏。UBIFS(Unsorted Block Image File System) 专为裸NAND设计,自带坏块管理和磨损均衡,是NAND Flash的最佳搭档。
本文将手把手教你,如何在 PetaLinux 2017.4 环境下,配置Zynq 7000从NAND Flash启动,并挂载UBIFS根文件系统。新手小白只要跟着步骤一步步复制粘贴,也能轻松搞定!
🛠️ 准备工作
- 硬件基础:带有NAND Flash的Zynq 7000开发板。
- Vivado工程 :已经在Zynq IP核中开启了SMC(NAND Flash控制器),并导出了硬件描述文件(
.hdf)。 - 软件环境:Ubuntu虚拟机,已成功安装 PetaLinux 2017.4。
第一步:创建并初始化PetaLinux工程
首先,把Vivado导出的 xxx.hdf 文件拷贝到Ubuntu中。打开终端,依次执行以下命令:
bash
# 1. 设置PetaLinux环境变量(根据你的实际安装路径修改)
source /opt/pkg/petalinux/2017.4/settings.sh
# 2. 创建PetaLinux工程(假设工程名为zynq_nand_ubifs)
petalinux-create --type project --template zynq --name zynq_nand_ubifs
# 3. 进入工程目录
cd zynq_nand_ubifs
# 4. 导入硬件描述文件(注意把/path/to/hdf替换为你hdf文件所在的目录)
petalinux-config --get-hw-description=/path/to/hdf
执行完最后一步后,会弹出一个蓝底灰字的配置菜单。
第二步:系统级配置(划分NAND分区)
在刚弹出的 petalinux-config 菜单中,我们需要配置Flash分区和根文件系统类型。
1. 配置Flash分区
按照以下路径进入:
Subsystem AUTO Hardware Settings -> Flash Settings
- 确保当前的Flash选中的是你的NAND。
- 重点来了!进入
Advanced Flash Auto Partitioning,我们需要给NAND划分分区。建议划分如下:boot(存放BOOT.BIN):大小0x00800000(8MB)bootenv(存放U-Boot环境变量):大小0x00100000(1MB)kernel(存放image.ub):大小0x00A00000(10MB)rootfs(存放UBIFS文件系统):剩下的所有空间(比如填0x1F0E0000,根据你的NAND总大小计算)
💡 新手避坑指南 :请务必记住这里名为
rootfs的分区名称,后面的配置要用到!
2. 设置根文件系统类型为UBIFS
退回主菜单,按照以下路径进入:
Image Packaging Configuration -> Root filesystem type
- 将其修改为 other。因为没有UBIFS

接下来修改petalinuxbsp.conf文件

上图中的后两个是关于nand falsh的参数具体说明如下,其中-s项对于不支持子页的flash应填写与页大小相同的数值。

继续在 Image Packaging Configuration 菜单下找到:
Device node of SD device(或者Bootargs配置),我们需要修改内核启动参数(Bootargs)。
- 取消勾选
generate boot args automatically。 - 在
user set kernel bootargs中输入以下内容(一字不差地复制):
text
console=ttyPS0,115200 earlyprintk root=ubi0:rootfs ubi.mtd=rootfs rootfstype=ubifs rw rootwait
(解释:ubi.mtd=rootfs表示在名为rootfs的MTD分区寻找UBI;root=ubi0:rootfs表示挂载UBI里面的rootfs卷)
配置完成后,连续按 Exit 退出并保存(Save)。

第三步:内核配置(开启UBI和UBIFS支持)
终端输入以下命令打开内核配置:
bash
petalinux-config -c kernel
在内核菜单中,按 / 键可以搜索,我们需要确保开启以下几项功能(输入 Y 选中,变成 [*] 或 <*>):
1. 开启MTD的UBI支持:
Device Drivers --->
Memory Technology Device (MTD) support --->
Enable UBI - Unsorted block images ---> 选中(设为 *)

2. 开启UBIFS文件系统支持:
File systems --->
Miscellaneous filesystems --->
UBIFS file system support ---> 选中(设为 *)
保存并退出。

第四步:文件系统配置(添加测试工具)
终端输入:
bash
petalinux-config -c rootfs
为了以后我们在板子上能手动操作NAND,我们需要把 mtd-utils 工具包编译进去。
路径:
Filesystem Packages --->
base --->
mtd-utils --->
进去后,把 mtd-utils 及其下的 mtd-utils-ubifs 都打上星号 [*]。
保存并退出。
第五步:设备树配置(关联NAND硬件)
虽然在第二步划分了分区,但最保险的做法是在设备树中再硬性声明一次。
打开文件 project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi。
将其修改为类似如下内容(根据你的NAND节点名称 smcc 调整):
dts
/include/ "system-conf.dtsi"
/ {
};
&smcc {
nand0: nand@0,0 {
compatible = "arm,pl353-nand-r2p1";
reg = <0 0 0x1000000>;
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "boot";
reg = <0x00000000 0x00500000>;
};
partition@1 {
label = "bootenv";
reg = <0x00500000 0x00020000>;
};
partition@2 {
label = "kernel";
reg = <0x00520000 0x00A00000>;
};
partition@3 {
label = "rootfs";
reg = <0x00F20000 0x1F0E0000>; /* 根据你的实际剩余容量修改 */
};
};
};
保存退出。
如nand flash有时序要求,可按下图方式增加nand时序。

第六步:编译生成
激动人心的时刻到了,终端输入:
bash
petalinux-build
(这个过程可能需要十几分钟到半小时,去喝杯咖啡吧~ ☕)
编译成功后,我们需要打包生成最终的 BOOT.BIN。终端输入:
bash
petalinux-package --boot --fsbl images/linux/zynq_fsbl.elf --fpga images/linux/system.bit --u-boot --force
此时,在 images/linux/ 目录下,我们拥有了烧写所需的三剑客:
BOOT.BIN(引导程序)image.ub(内核与设备树)rootfs.ubifs(UBIFS根文件系统镜像)
第七步:U-Boot烧写与启动(关键!)
由于是新板子,NAND里是空的。通常我们需要通过TFTP服务器,在U-Boot命令行下把这三个文件烧写到NAND中。(前提:开发板用网线连上电脑,电脑开启TFTP服务并将上述三个文件放入TFTP目录)。
在开发板串口终端中,上电狂按回车进入 U-Boot命令行:
1. 配置网络
bash
setenv ipaddr 192.168.1.100 # 开发板IP
setenv serverip 192.168.1.10 # 电脑Ubuntu IP
2. 烧写 BOOT.BIN
bash
tftp 0x100000 BOOT.BIN
nand erase 0x0 0x500000
nand write 0x100000 0x0 $filesize
3. 烧写 image.ub (Kernel)
bash
tftp 0x100000 image.ub
nand erase 0x520000 0xA00000
nand write 0x100000 0x520000 $filesize
4. 烧写 rootfs.ubifs
这是最特殊的一步!UBIFS不能用普通的nand write,必须按UBI格式写入。
bash
# 擦除rootfs所在分区 (对应分区起始地址 0xF20000)
nand erase 0xF20000 0x1F0E0000
# 格式化该MTD分区为UBI格式
ubi part rootfs
# 创建名为rootfs的UBI卷 (注意这里不要超出大小)
ubi create rootfs
# 将文件系统下载到内存
tftp 0x100000 rootfs.ubifs
# 将内存中的文件系统写入UBI卷
ubi write 0x100000 rootfs $filesize
5. 保存环境变量并重启
确保U-Boot的启动指令是正确的:
bash
# 设置U-Boot去NAND的kernel分区读取内核
setenv bootcmd 'nand read 0x3000000 0x520000 0xA00000; bootm 0x3000000'
saveenv
boot
🎉 成功启动
如果你在串口打印信息中看到了类似下面的字眼:
text
UBIFS (ubi0:0): UBIFS: mounted UBI device 0, volume 0, name "rootfs"
...
Welcome to PetaLinux!
zynq_nand_ubifs login:
恭喜你,大功告成! 你的Zynq 7000已经成功从NAND Flash启动了UBIFS系统,以后断电重启你的代码和文件都不会再丢失啦!
结语
配置NAND和UBIFS的过程中,最容易在分区大小计算 和U-Boot烧写命令上踩坑。新手一定要耐心对照设备树中的地址和U-Boot操作的地址,确保完全一致。
