Jetson Xavier NX 系统迁移实战:从EMMC到NVMe SSD的完整避坑指南
如果你正在使用EMMC版本的Jetson Xavier NX,并且已经感受到了存储空间的局促和读写速度的瓶颈,那么将系统迁移到NVMe固态硬盘上,无疑是释放这台边缘计算设备全部潜力的关键一步。我最初接触这个项目时,也以为只是简单的数据拷贝,但实际操作中遇到了各种意想不到的“坑”——从引导配置失败到分区表错误,再到那个令人头疼的“Fail to verify Stage2 signature SHA2”报错。经过多次尝试和总结,我梳理出了一套相对稳定、可复现的完整迁移流程。这篇文章就是为你准备的,无论你是嵌入式开发者、AI算法工程师,还是热衷于边缘计算的爱好者,都能从中找到从备份、迁移到优化启动的每一个细节。我们将避开那些官方文档语焉不详的部分,专注于实战中真正会遇到的问题和解决方案。
1. 迁移前的深度准备与环境搭建
在动手之前,充分的准备工作能避免后续80%的麻烦。系统迁移不仅仅是数据的搬运,更涉及到引导加载程序、分区表、内核参数等一系列底层配置的调整。你需要理解,Jetson Xavier NX的启动流程是:上电 → BootROM → QSPI-NOR中的引导加载程序 → 从EMMC或NVMe加载内核与设备树 → 挂载根文件系统。我们的目标,就是让引导加载程序能够正确找到并加载位于NVMe SSD上的内核与根文件系统。
硬件清单与检查点:
- Jetson Xavier NX开发套件(EMMC版本):确保设备能正常启动进入Ubuntu系统。
- M.2 NVMe固态硬盘(SSD):建议容量不小于256GB,品牌选择上,三星、西数、铠侠的兼容性都不错。我手头用的是一块512GB的SN750。
- USB转M.2 NVMe硬盘盒:这是连接Ubuntu主机和SSD的桥梁,务必确认其支持NVMe协议。有些便宜的硬盘盒只支持SATA协议,会导致识别失败。
- Ubuntu主机(实体机或虚拟机):版本建议18.04或20.04 LTS,这是NVIDIA SDK Manager和工具链兼容性最好的环境。我的工作环境是Ubuntu 20.04.6 LTS。
- Micro-USB数据线:必须是能传输数据的数据线,而非仅能充电的线缆。
- 跳线帽或杜邦线:用于短接FC REC和GND引脚,强制设备进入恢复模式(Recovery Mode)。
在开始之前,先在Jetson Xavier NX上执行几个关键命令,记录下至关重要的原始信息。打开终端,输入:
sudo fdisk -l /dev/mmcblk0你会看到类似下面的输出,重点记录分区起始扇区(Start)和扇区总数(Sectors),特别是根分区(通常是最大的那个Ext4分区)的信息。这些数据在后续配置引导时至关重要。
Device Boot Start End Sectors Size Id Type /dev/mmcblk0p1 * 2048 2099199 2097152 1G c W95 FAT32 (LBA) /dev/mmcblk0p2 2099200 312770559 310671360 148G 83 Linux同时,检查NVMe SSD是否已被系统识别:
ls /dev/nvme*如果能看到/dev/nvme0和/dev/nvme0n1,说明SSD已被内核识别。接下来,在Ubuntu主机上,我们需要安装几个核心工具。
Ubuntu主机软件环境配置:
首先更新软件包列表并安装必要的工具:
sudo apt update sudo apt install -y gparted nvme-cli qemu-user-staticgparted是图形化的分区编辑器,比命令行更直观;nvme-cli用于管理NVMe设备;qemu-user-static则是在x86主机上运行ARM架构程序(如Jetson的系统镜像处理工具)的关键。
注意:整个操作流程中,请确保你的Ubuntu主机有足够的磁盘空间。一个完整的系统镜像备份(raw格式)可能高达EMMC的物理容量(如32GB),而处理过程中的中间文件还会占用额外空间。建议预留至少2倍于EMMC容量的空闲空间。
2. 系统备份:创建完整的EMMC磁盘镜像
备份是迁移的保险绳。这里我推荐使用dd命令进行块设备级别的完整备份,虽然它备份的是整个设备(包括未使用空间),导致镜像文件较大,但其优点是能100%还原分区表、引导扇区和所有数据,兼容性最好。另一种基于文件系统的备份(如rsync)虽然节省空间,但在处理特殊的引导分区和恢复模式配置时容易出问题。
第一步:进入恢复模式并连接主机
- 在Jetson Xavier NX关机状态下,找到核心板底部的“FC REC”和“GND”引脚,用跳线帽短接。
- 先使用Micro-USB数据线连接Jetson的Micro-USB口和Ubuntu主机的USB口。
- 最后再给Jetson Xavier NX上电。此时设备不会正常启动,而是进入恢复模式。
- 在Ubuntu主机上执行
lsusb,如果看到NVIDIA Corp.相关的设备,说明连接成功。
第二步:使用NVIDIA官方工具准备基础系统
从NVIDIA开发者网站下载对应版本的Jetson Linux(BSP)和根文件系统样本。以R32.6.1版本为例(请根据你的JetPack版本选择对应版本):
# 假设下载的压缩包在 ~/Downloads 目录 cd ~/Downloads tar xf Jetson_Linux_R32.6.1_aarch64.tbz2 cd Linux_for_Tegra sudo tar xf ../Tegra_Linux_Sample-Root-Filesystem_R32.6.1_aarch64.tbz2 -C ./rootfs/接下来应用二进制文件,这一步会为根文件系统安装GPU驱动、CUDA等核心组件:
sudo ./apply_binaries.sh看到Success提示即表示完成。现在,我们需要修改NVMe的刷机配置文件,使其适配我们的SSD。编辑文件./tools/kernel_flash/flash_l4t_nvme.xml:
sudo vim ./tools/kernel_flash/flash_l4t_nvme.xml找到与分区相关的部分,关键是要修改partition标签中的size属性,将其调整为你的NVMe SSD容量(以扇区数为单位)。你可以通过sudo fdisk -l /dev/nvme0n1查看SSD的总扇区数。例如,一个500GB的SSD,其size值可能需要设置为976773168(这是示例,请以实际fdisk输出为准)。更稳妥的做法是,参考之前从EMMC的fdisk -l输出中记录的根分区扇区数,确保新分区不小于原分区。
第三步:执行备份与镜像生成
现在,将装有EMMC系统(即Jetson原系统)的NVMe SSD通过硬盘盒连接到Ubuntu主机。使用gparted或lsblk确认设备标识符,例如/dev/sdb或/dev/nvme0n1。请务必确认设备号,误操作会导致数据丢失。
假设SSD在主机上被识别为/dev/sdb,并且其第一个分区(通常是EXT4格式的根文件系统分区)为/dev/sdb1。我们使用dd命令进行备份:
sudo dd if=/dev/sdb1 of=~/nx_rootfs_backup.raw bs=1M status=progress这个命令会将整个分区逐比特复制到主目录下的nx_rootfs_backup.raw文件。bs=1M设置块大小,status=progress显示进度。这个过程耗时较长,取决于EMMC容量和数据量。
备份完成后,我们需要将这个raw文件转换为NVIDIA刷机工具能识别的稀疏镜像(sparse image)格式,以节省空间:
cd ~/Downloads/Linux_for_Tegra/bootloader sudo mv system.img system.img.bak # 备份原始空镜像 sudo cp ~/nx_rootfs_backup.raw . sudo ./mksparse --fillpattern=0 nx_rootfs_backup.raw system.imgmksparse工具会将连续的零填充块进行压缩,最终生成的system.img文件会比原始的raw文件小很多。
3. 系统烧录与NVMe启动配置
备份完成后,接下来就是将准备好的系统镜像烧录到新的NVMe SSD,并配置设备从SSD启动。这一步的细微差别是成败的关键。
第一步:替换刷机包中的系统镜像
将上一步生成的system.img复制到刷机包中专门为外部设备(如NVMe)准备镜像的目录:
cd ~/Downloads/Linux_for_Tegra sudo cp ./bootloader/system.img ./tools/kernel_flash/images/external/确保external目录下的system.img就是我们刚刚创建的那个。
第二步:执行刷机命令
保持Jetson Xavier NX处于恢复模式并连接主机。在Linux_for_Tegra目录下执行刷机命令。这里有一个关键点:我们使用--flash-only参数,因为之前已经运行过--no-flash来生成刷机所需的内核和初始化内存盘(initrd)文件。
sudo ./tools/kernel_flash/l4t_initrd_flash.sh --flash-only \ --external-device nvme0n1p1 \ -c ./tools/kernel_flash/flash_l4t_nvme.xml \ -S 120GiB \ --showlogs \ jetson-xavier-nx-devkit-emmc \ nvme0n1p1对命令参数的解释:
--external-device nvme0n1p1: 指定外部设备为NVMe的第一个分区。-c .../flash_l4t_nvme.xml: 指定配置文件。-S 120GiB: 为系统分区分配120GB的空间(请根据你的SSD容量调整,必须小于SSD总容量)。--showlogs: 显示详细日志,便于排查问题。jetson-xavier-nx-devkit-emmc: 目标设备型号。nvme0n1p1: 刷入的目标分区。
执行后,终端会输出大量日志。整个过程包括擦除SSD、创建分区、写入引导加载程序、内核、设备树和系统镜像。请保持设备连接稳定,切勿中断。看到*** Success ***的提示,即表示刷机完成。
第三步:配置从NVMe SSD启动
刷机完成后,移除Jetson Xavier NX上的短接跳线帽,正常上电启动。此时系统应该仍然从EMMC启动。我们需要进入系统,修改引导配置。
首先,检查NVMe SSD是否被正确识别并挂载。在Jetson的终端中:
lsblk -f你应该能看到/dev/nvme0n1p1分区,并且文件系统类型为ext4。如果未挂载,手动挂载它:
sudo mkdir -p /mnt/ssd sudo mount /dev/nvme0n1p1 /mnt/ssd接下来,修改引导加载程序配置文件/boot/extlinux/extlinux.conf。这个文件决定了启动时加载哪个内核和根文件系统。
sudo cp /boot/extlinux/extlinux.conf /boot/extlinux/extlinux.conf.backup sudo vim /boot/extlinux/extlinux.conf你会看到类似以下内容:
TIMEOUT 30 DEFAULT primary MENU TITLE L4T boot options LABEL primary MENU LABEL primary kernel LINUX /boot/Image INITRD /boot/initrd APPEND ${cbootargs} root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 console=ttyS0,115200n8 console=tty0我们需要做两件事:
- 修改现有的
LABEL primary条目,将其root=参数从/dev/mmcblk0p1改为/dev/nvme0n1p1。 - 强烈建议:复制一份修改前的配置,创建一个新的启动标签(例如
LABEL emmc_boot),作为备用启动项。这样如果NVMe启动失败,还可以通过串口调试(UART)选择从EMMC启动。
修改后的配置文件示例:
TIMEOUT 30 DEFAULT ssd_boot MENU TITLE L4T boot options LABEL ssd_boot MENU LABEL NVMe SSD Boot LINUX /boot/Image INITRD /boot/initrd APPEND ${cbootargs} root=/dev/nvme0n1p1 rw rootwait rootfstype=ext4 console=ttyS0,115200n8 console=tty0 LABEL emmc_boot MENU LABEL EMMC Boot (Fallback) LINUX /boot/Image INITRD /boot/initrd APPEND ${cbootargs} root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 console=ttyS0,115200n8 console=tty0保存并退出。最后,更新初始化内存盘,以确保内核模块能正确识别NVMe设备:
sudo update-initramfs -u -k all重启设备:
sudo reboot如果一切顺利,系统将从NVMe SSD启动。你可以通过以下命令验证:
df -h /如果显示的挂载点是/dev/nvme0n1p1,那么恭喜你,迁移成功了!同时,检查一下存储空间,应该能看到SSD的全部容量。
4. 疑难排查与性能调优
即使按照步骤操作,迁移过程也可能遇到问题。下面是我遇到过以及社区常见的一些“坑”及其解决方案。
问题一:刷机过程卡住或报错 “Fail to verify Stage2 signature SHA2”
这是最常见的问题之一。通常与刷机环境或镜像文件有关。
- 原因与解决:
USB连接或电源不稳定:尝试更换USB端口(最好使用主机背面的USB 3.0端口),使用更短、质量更好的数据线,并确保Jetson供电充足。
刷机包版本不匹配或损坏:确保下载的Jetson Linux BSP和根文件系统样本版本完全一致,并且完整下载。可以重新解压到一个新目录,从头执行
apply_binaries.sh和--no-flash步骤。签名验证失败:这个错误通常意味着刷机包中的某些文件(如内核、设备树)与当前设备或配置不匹配。可以尝试以下命令序列,重新准备刷机环境:
cd ~/Downloads/Linux_for_Tegra sudo ./apply_binaries.sh sudo ./tools/kernel_flash/l4t_initrd_flash.sh --no-flash jetson-xavier-nx-devkit-qspi internal sudo ./tools/kernel_flash/l4t_initrd_flash.sh --no-flash --external-device nvme0n1p1 -c ./tools/kernel_flash/flash_l4t_nvme.xml -S 120GiB --showlogs jetson-xavier-nx-devkit-emmc nvme0n1p1然后,再重新执行
--flash-only的刷机命令。
问题二:系统无法从NVMe启动,卡在启动界面或回退到EMMC
- 排查步骤:
- 检查extlinux.conf:确认
root=参数路径完全正确,是/dev/nvme0n1p1而不是/dev/nvme0。 - 检查文件系统:在从EMMC启动的系统里,检查SSD分区的文件系统是否完好。可以运行
sudo fsck.ext4 -f /dev/nvme0n1p1进行修复。 - 检查内核模块:确保NVMe驱动已加载。
lsmod | grep nvme应该能看到nvme和nvme_core模块。如果没有,尝试sudo modprobe nvme。 - 使用串口调试:这是最强大的调试手段。通过USB转TTL串口线连接Jetson的调试串口(J21 Header),在电脑上使用串口终端(如PuTTY、minicom)查看完整的启动日志。在启动瞬间,根据提示按空格键可以进入引导菜单,手动选择我们配置的
ssd_boot条目,并观察错误信息。
- 检查extlinux.conf:确认
问题三:迁移后性能提升不明显
系统成功从SSD启动只是第一步,要充分发挥NVMe的性能,还需要进行一些优化。
- 优化建议:
- 文件系统挂载选项:编辑
/etc/fstab文件,找到NVMe根分区的挂载行,添加noatime,discard选项。noatime可以减少不必要的写入,discard启用TRIM功能,有助于维持SSD长期性能。/dev/nvme0n1p1 / ext4 defaults,noatime,discard 0 1 - Swappiness调整:Jetson Xavier NX内存较大,可以减少交换分区(swap)的使用,避免不必要的SSD写入。编辑
/etc/sysctl.conf,添加或修改:
然后执行vm.swappiness=10sudo sysctl -p生效。 - 启用IO调度器:对于NVMe这类高速设备,使用
none或noop调度器可能比默认的mq-deadline或kyber更高效。可以创建一个udev规则:
重启后生效。echo 'ACTION=="add|change", KERNEL=="nvme[0-9]n[0-9]", ATTR{queue/scheduler}="none"' | sudo tee /etc/udev/rules.d/60-ssd-scheduler.rules
- 文件系统挂载选项:编辑
问题四:EMMC空间如何再利用
系统迁移到SSD后,原来的EMMC就空闲出来了。你可以选择将其格式化为一个额外的数据盘。但务必谨慎操作,确保当前系统确实是从SSD启动的。
- 首先,确认根文件系统不在EMMC上 (
df -h /)。 - 卸载EMMC上的所有分区(如果已自动挂载):
sudo umount /dev/mmcblk0p* - 使用
gparted或fdisk对/dev/mmcblk0进行重新分区和格式化。例如,可以创建一个单独的ext4分区用于存储数据集、模型或日志。
整个迁移过程,从准备到优化,虽然步骤不少,但每一步都有其明确的目的。最深刻的体会是,备份和验证环节再怎么仔细都不为过。尤其是在修改引导配置前,一定要备份原始文件。那个备用启动项(emmc_boot)在我第一次配置错误时救了我一命,让我能通过串口切换回EMMC启动进行修复。现在,我的Jetson Xavier NX在NVMe SSD上运行得飞快,编译大型ROS工作空间或加载深度学习模型的速度提升非常明显,EMMC则变成了一个高速的本地数据仓库,这套组合让这台小设备的实用性大大增强。