1. 项目概述
在嵌入式Linux系统开发中,使用PetaLinux工具链为Zynq平台制作可启动的SD卡是一个常见但容易出错的过程。作为一名长期从事FPGA和嵌入式系统开发的工程师,我经常需要为不同项目准备启动介质。本文将详细介绍从分区格式化到文件部署的完整流程,分享我在实际项目中积累的经验技巧。
对于Zynq-7000或UltraScale+ MPSoC平台,SD卡启动需要三个核心文件:BOOT.BIN(包含FSBL、比特流和U-Boot)、image.ub(FIT格式的内核镜像)以及rootfs.tar.gz(根文件系统)。这三个文件的生成通常通过PetaLinux工具完成,而本文重点在于如何正确地将它们部署到SD卡。
2. 准备工作与SD卡分区
2.1 硬件与软件准备
在开始前,请确保准备好以下物品:
- 容量至少为8GB的Class 10 SD卡(实测SanDisk Extreme Pro兼容性最佳)
- USB读卡器(建议使用USB 3.0接口的知名品牌产品)
- 运行Ubuntu 18.04/20.04 LTS的PC或虚拟机
- 已生成的BOOT.BIN、image.ub和rootfs.tar.gz文件
重要提示:避免使用廉价或来路不明的SD卡,我在项目中曾遇到多起因SD卡质量问题导致的启动失败案例。建议准备两张同型号SD卡作为备份。
2.2 识别SD卡设备
将SD卡插入读卡器并连接到Ubuntu系统后,执行以下命令识别设备节点:
bash复制sudo fdisk -l
典型输出如下:
code复制Disk /dev/sdb: 14.9 GiB, 15931539456 bytes, 31116288 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
关键点说明:
/dev/sdX中的X通常是b/c/d等,取决于系统已有存储设备- 务必确认容量与你的SD卡一致,避免误操作其他磁盘
- 如果使用虚拟机,需确保USB设备已正确传递给虚拟机
2.3 分区方案设计
Zynq平台SD卡的标准分区方案如下表所示:
| 分区 | 大小 | 文件系统 | 内容 | 必要性 |
|---|---|---|---|---|
| boot | 100-200MB | FAT32 | BOOT.BIN, image.ub | 必需 |
| rootfs | 剩余空间 | ext4 | 根文件系统 | 必需 |
| persistent | 可选(1-2GB) | ext4 | 持久化数据 | 可选 |
实际操作中,我推荐使用以下分区参数:
- boot分区:200MB FAT32(考虑未来内核增大的可能)
- rootfs分区:剩余全部空间ext4(建议至少4GB)
- 起始扇区:2048(对齐到1MB边界,提升性能)
3. 详细分区操作流程
3.1 卸载现有分区
在操作前,必须先卸载所有已挂载的分区:
bash复制sudo umount /dev/sdb*
3.2 使用fdisk进行分区
执行以下命令进入分区工具:
bash复制sudo fdisk /dev/sdb
在fdisk交互界面中,按顺序执行以下操作:
-
删除现有分区(如有):
code复制Command (m for help): d Partition number (1,2, default 2): [按需输入] -
创建boot分区:
code复制Command (m for help): n Partition type: p (primary) Partition number: 1 First sector: 2048 Last sector: +200M -
设置boot分区类型:
code复制Command (m for help): t Selected partition 1 Hex code (type L to list all codes): c -
设置boot分区为可启动:
code复制Command (m for help): a Partition number (1,2, default 1): 1 -
创建rootfs分区:
code复制Command (m for help): n Partition type: p (primary) Partition number: 2 First sector: [默认] Last sector: [默认] -
写入分区表并退出:
code复制Command (m for help): w
3.3 格式化分区
创建文件系统并设置卷标:
bash复制sudo mkfs.vfat -F 32 -n boot /dev/sdb1
sudo mkfs.ext4 -L rootfs /dev/sdb2
格式化后建议检查文件系统:
bash复制sudo fsck.vfat -a /dev/sdb1
sudo fsck.ext4 -f /dev/sdb2
4. 文件部署与验证
4.1 挂载分区
创建挂载点并挂载分区:
bash复制mkdir -p /media/$USER/{boot,rootfs}
sudo mount /dev/sdb1 /media/$USER/boot
sudo mount /dev/sdb2 /media/$USER/rootfs
4.2 复制启动文件
将PetaLinux生成的镜像复制到boot分区:
bash复制cp BOOT.BIN image.ub /media/$USER/boot/
sync
经验之谈:在复制大文件后务必执行sync命令,确保数据完全写入。我曾遇到过因缓存未同步导致启动失败的情况。
4.3 部署根文件系统
解压根文件系统到rootfs分区:
bash复制sudo tar xvf rootfs.tar.gz -C /media/$USER/rootfs
对于需要自定义文件系统的情况,可以使用以下工作流:
bash复制sudo mount /dev/sdb2 /mnt
sudo tar xvf rootfs.tar.gz -C /mnt
# 在此进行文件系统修改
sync
sudo umount /mnt
4.4 文件系统权限修复
解压后可能需要修复文件权限:
bash复制sudo chown -R root:root /media/$USER/rootfs/*
sudo chmod -R go-w /media/$USER/rootfs/*
5. 常见问题与解决方案
5.1 启动失败排查表
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| U-Boot未启动 | BOOT.BIN损坏或位置错误 | 检查文件是否在FAT分区根目录 |
| 内核panic | 设备树不匹配 | 确认image.ub包含正确的DTB |
| 根文件系统挂载失败 | ext4分区损坏 | 重新格式化并部署rootfs |
| 串口无输出 | 波特率设置错误 | 确认使用115200波特率 |
5.2 性能优化技巧
- 分区对齐:确保分区起始于1MB边界(2048扇区),可提升读写性能
- ext4优化:格式化时添加
-E stride=512,stripe-width=512选项 - 预分配inode:对于大型根文件系统,使用
-N参数指定足够的inode数量 - 日志模式:对于频繁写入的场景,考虑使用ext4的
data=writeback选项
5.3 SD卡兼容性问题
不同品牌SD卡在Zynq平台上的表现差异较大。根据我的经验:
- 推荐品牌:SanDisk Extreme Pro、Samsung Pro Endurance
- 避免使用:廉价白牌卡、二手回收卡
- 容量选择:8-32GB为宜,过大容量可能引发兼容性问题
6. 高级应用场景
6.1 双启动配置
通过在boot分区放置多组镜像,可以实现双系统启动:
code复制/boot/
├── BOOT.BIN # 主系统
├── image.ub
├── BOOT_ALT.BIN # 备用系统
└── image_alt.ub
在U-Boot中通过环境变量切换启动项:
bash复制setenv bootalt 'fatload mmc 0 0x10000000 BOOT_ALT.BIN; bootm 0x10000000'
saveenv
6.2 持久化存储方案
创建第三个分区用于存储应用数据:
bash复制sudo mkfs.ext4 -L persist /dev/sdb3
在根文件系统中创建挂载点:
bash复制mkdir /mnt/persist
echo "/dev/mmcblk0p3 /mnt/persist ext4 defaults 0 2" >> /etc/fstab
6.3 自动化部署脚本
对于频繁部署的场景,可以创建自动化脚本:
bash复制#!/bin/bash
# deploy_sd.sh
DEVICE=$1
# 分区和格式化
parted -s $DEVICE mklabel msdos
parted -s $DEVICE mkpart primary fat32 1MiB 201MiB
parted -s $DEVICE set 1 boot on
parted -s $DEVICE mkpart primary ext4 201MiB 100%
mkfs.vfat -F 32 -n boot ${DEVICE}1
mkfs.ext4 -F -L rootfs ${DEVICE}2
# 文件复制
mount ${DEVICE}1 /mnt
cp BOOT.BIN image.ub /mnt
umount /mnt
mount ${DEVICE}2 /mnt
tar xvf rootfs.tar.gz -C /mnt
umount /mnt
使用方式:sudo ./deploy_sd.sh /dev/sdb
在实际项目开发中,我发现这套流程虽然看似简单,但细节决定成败。特别是在量产环境中,确保SD卡制作的一致性和可靠性至关重要。建议在关键项目中使用工业级SD卡,并在部署后进行全面验证。