在售的 NVIDIA Jetson 内置 16 GB 的 eMMC,并已安装了 ubuntu 18.04 LTS
和 NVIDIA JetPack 4.6
,所以剩余的用户可用空间大约 2GB,这对将 NVIDIA Jetson 应用于一些项目的训练和部署是一个不小的阻碍。本教程会基于这样的处境,分别介绍不同型号 NVIDIA Jetson 的扩容过程,帮助开发者将系统转移到外部存储器设备而实现扩容的目的。
扩容的基本原理
装有系统的磁盘上面的第一个扇区被称为主引导记录(MBR),主引导记录存放了引导加载程序(BootLoader)、分区表以及固定标识“55AA”三个信息。在 Linux 的启动过程中,引导加载程序和内核(Kernel)会经历两个比较重要的阶段。
第一阶段:引导加载程序会初始化(initrd)一个临时根文件系统(ramfs)。临时根文件系统中有启动时必要的驱动(drivers)、文件系统(fs)、网络(net)等配置程序。之后,引导加载程序的控制权就会转交给内核,以便内核能够取出这些程序,将其移动到内存(RAM)中运行,加载各个功能模块。
第二阶段:内核借助临时根文件系统装载必要的功能模块之后,会释放该系统,并配置真正的根文件系统(rootfs)挂载到真正的根目录。
- 那么在上述的两个阶段中,内核借助临时根文件系统装载功能模块的部分(第一阶段)我们是不需要进行修改的,所以即使 NVIDIA Jetson 已经实现扩容,它仍会需要使用 eMMC。
- 我们需要改造的是第二个阶段,将根文件系统挂载到外部存储器中,从而实现扩容。
扩容注意事项
- 通过外部存储设备进行扩容的主要原理是将 rootfs 设置为在外部存储设备上。
- 此扩容方法将会对 Linux 内核级别的系统文件进行修改,您可能会遇到一些不容易解决的问题。您在根据此教程完成扩容操作时应当使用的是新的 NVIDIA Jetson 以及新的存储设备,不要尝试在设备中存放使用有价值的文件。如果一切未按预期,您可能会需要重新格式化存储设备甚至是 NVIDIA Jetson。对于最后的保留方案,我们会提供通过串口的方式尽可能帮助您恢复备份,但一切数据的丢失责任需要您自行承担。
- 此扩容过程与网上其他早期的扩容方法相比,不需要重新编译内核,节省了大约40分钟的安装时间。
通过载板上的 M.2 插槽和 SSD 扩容
SSD 又称为固态硬盘(Solid State Drives),常作为笔记本、台式机等的主要存储设备。它具有可靠性高、数据读写数率快等优势,这将会是 NVIDIA Jetson 扩容的最佳选择。此方法仅适用于 NVIDIA Jetson Xavier NX 系列。
软硬件要求
使用 SSD 进行扩容的方案需要尽量满足如下条件,这也是经过验证可以顺利完成扩容的基本要求。
| 软硬件要求 |
NVIDIA Jetson | JetPack 版本 4.4 ~ 4.6 载板需含有 M.2 M-Key 插槽 |
SSD | SSD 需为第四代扩展文件系统(Ext4) NVMe 协议的 M.2 M-Key 接口 推荐容量 ≤ 512 GB |
⚠️ 注意:
- 更新的 JetPack 版本是未经过扩容测试的,无法保证扩容的稳定性或成功性,请慎重按此教程进行扩容。
- SSD 需要注意接口需为 M.2 M-Key,否则无法与载板上的接口相匹配。
- 非第四代扩展文件系统(Ext4)的存储设备不能完成扩容操作。
扩容步骤
请按照“硬件使用说明”中的步骤为 NVIDIA Jetson 安装好 SSD。
使用快捷键 Ctrl+F 或点击左上角的 Ubuntu 图标搜索 Disks,打开 Ubuntu 18.04 自带的 Disks 工具。
在左侧选择你的 SSD,然后在右上角的菜单栏下选择“Format Disk”。
将你的 SSD 格式化成 GPT 格式。此时会弹出窗口让你确认并输入用户密码。
然后,我们点击中间的“+”,添加盘符。
点击“Next”。
请给你的 SSD 起一个名字,并在类型中选择第四代扩展文件系统(Ext4),最后点击“Create”即可。此时我们已经按照扩容的要求完成了 SSD 的前期准备。
使用 git 命令将我们需要使用的脚本文件下载到 NVIDIA Jetson 上。
$ git clone https://github.com/limengdu/rootOnNVMe.git
$ cd rootOnNVMe/
然后执行如下命令,将 eMMC 中根目录的文件构建到 SSD 中,这个步骤的等待时间视您所使用的根目录大小所决定。
$ ./copy-rootfs-ssd.sh
执行如下命令,完成 rootfs 的配置。
$ ./setup-service.sh
重新启动 NVIDIA Jetson,会发现 eMMC 已经变成了外部存储设备显示在主界面上,查看系统占用空间也发现变少了,扩容成功。
⚠️ 注意:
- 脚本文件中默认的 SSD 路径为 /dev/nvme0n1p1,这也是 NVIDIA Jetson 默认分配的路径。如果您通过命令
sudo fdisk -l
查询到您的 SSD 路径与此不一致,请更改 rootOnNVMe 中文件 copy-rootfs-ssd.sh、data/setssdroot.service 和 data/setssdroot.sh 中所有 /dev/nvme0n1p1 的路径为您 SSD 所在的路径。
2. 上述扩容操作不会删除 eMMC 中原来的根目录内容,如果您不想从 SSD 启动系统,您可以拆除 SSD,系统依旧可以从 eMMC 中完成启动。
通过 USB 存储设备进行扩容
USB 存储设备例如 U 盘、移动硬盘等,作为生活中常见的外部存储器,广泛应用在各个领域,USB 的扩容方式也同样适用于 NVIDIA Jetson。此方法对能够使用的设备没有限制。
相较于通过 SSD 的方法进行扩容,通过 USB 存储设备进行扩容最大的优势是 USB 设备具有高度的便捷性,且移除设备比较简单。但是,即使是高速的 USB 3.0 接口,数据传输的数率也远不及标准的 PCIe 总线,所以从稳定性、可靠性和数据传输速度来讲,通过 SSD 扩容的方法会更胜一筹。
软硬件要求
使用 USB 进行扩容的方案需要尽量满足如下条件,这也是经过验证可以顺利完成扩容的基本要求。
| 软硬件要求 |
NVIDIA Jetson | JetPack 版本 4.4 ~ 4.6 核心模组需为 Jetson Nano |
USB 存储设备 | USB 存储设备需为第四代扩展文件系统(Ext4) USB 存储设备供电电流 ≤ 0.5 A |
⚠️ 注意:
- 更新的 JetPack 版本是未经过扩容测试的,无法保证扩容的稳定性或成功性,请慎重按此教程进行扩容。
- 大容量 USB 存储设备需要确保 NVIDIA Jetson 能够正常为其供电以维持正常工作,不建议使用 512 GB 以上容量的 USB 存储设备。供电不足可能会导致 NVIDIA Jetson 断电关机。
- 非第四代扩展文件系统(Ext4)的存储设备不能完成扩容操作。
扩容步骤
使用 git 命令下载我们需要用于 NVIDIA Jetson 的脚本文件。
$ git clone https://github.com/limengdu/bootFromUSB.git
$ cd bootFromUSB
将 USB 存储设备连接到 NVIDIA Jetson。使用快捷键 Ctrl+F 或点击左上角的 Ubuntu 图标搜索 Disks,打开 Ubuntu 18.04 自带的 Disks 工具。
在左侧选择你的 USB 存储设备,然后在右上角的菜单栏下选择“Format Disk”。
将你的 USB 存储设备格式化成 GPT 格式。此时会弹出窗口让你确认并输入用户密码。
然后,我们点击中间的“+”,添加盘符。
点击“Next”。
请给你的 USB 存储设备起一个名字,并在类型中选择第四代扩展文件系统(Ext4),最后点击“Create”即可。此时我们已经按照扩容的要求完成了 USB 存储设备的前期准备。
按照第 2 步准备好的 USB 存储设备可以在 Disks 软件中看到显示的是未挂载的情况。
我们使用如下命令挂载该 USB 设备。
$ mkdir /media/USB/
$ sudo mount <USB Device Path> /media/USB/
其中,<USB Device Path>
指的是 USB 存储设备的路径,此参数可以在 Disks 软件的 Device 中看到,也可以通过命令sudo fdisk -l
查询得到。例如对于我的 USB 设备,我可以使用如下命令将 /dev/sda1 挂载到 /media/USB/ 中。
$ sudo mount /dev/sda1 /mnt
使用如下命令检查设备的挂载位置。
$ sudo findmnt -rno TARGET <USB Device Path>
对于我的 USB 设备,我需要使用的命令为:
$ sudo findmnt -rno TARGET /dev/sda1
copyRootToUSB.sh 脚本会将 eMMC 整个系统的内容复制到 USB 存储设备上。当然,USB 存储器的存储空间应当比 eMMC 的存储空间大。
使用的命令如下:
usage: ./copyRootToUSB.sh [OPTIONS]
-d | --directory Directory path to parent of kernel
-v | --volume_label Label of Volume to lookup
-p | --path Device Path to USB drive (e.g. /dev/sda1)
-h | --help This message
一般来讲,对于常规的扩容需求,我们在参数[OPTIONS]
中选择-p
即可,后面需要添加 USB 设备的路径(如 /dev/sda1),这我们在第 3 步中已经得到。例如对于我的 USB 设备,我需要使用的完整命令为:
$ ./copyRootToUSB.sh -p /dev/sda1
此命令执行时间的长短取决于你的 eMMC 存储的文件大小。
为了保证万无一失,我们需要查询一下 USB 设备的 UUID。
$ ./partUUID.sh
这个命令默认的操作路径为 sda1(/dev/sda1) ,但是您也可以确定其他 USB 设备的 UUID。规定 /dev/ 使用 -d 标志。例如:
$ ./diskUUID.sh -d sdb1
⚠️ 注意:
如果返回的 UUID 在格式和长度上不同于上面的示例,那么设备很可能没有格式化为 Ext4,请从第 2 步重新开始!
我们需要首先对引导配置文件进行备份。
$ sudo cp /boot/extlinux/extlinux.conf /boot/extlinux/extlinux.conf.bak
这一步的操作是 USB 设备扩容操作中最为重要也是最危险的一步。编辑 /boot/extlinux/extlinux.conf 文件和 /media/nvidia/boot/extlinux/extlinux.conf 文件,添加一个条目来指向新的 rootfs,指向的位置即为 USB 设备的路径,将它填入下方参数<path>
中。路径信息已在第 3 步获得。
LABEL primary
MENU LABEL primary kernel
LINUX /boot/Image
INITRD /boot/initrd
APPEND ${cbootargs} quiet root=<path> rw rootwait rootfstype=ext4 console=ttyS0,115200n8 console=tty0 fbcon=map:0 net.ifnames=0 sdhci_tegra.en_boot_part_access=1
对于我所使用的 USB 存储设备,修改完的 /boot/extlinux/extlinux.conf 和 /media/nvidia/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} quiet root=/dev/sda1 rw rootwait rootfstype=ext4 console=ttyS0,115200n8 console=tty0 fbcon=map:0 net.ifnames=0 sdhci_tegra.en_boot_part_access=1
# APPEND ${cbootargs} quiet root=/dev/mmcblk0p1 rw rootwait rootfstype=ext4 console=ttyS0,115200n8 console=tty0 fbcon=map:0 net.ifnames=0 sdhci_tegra.en_boot_part_access=1
# When testing a custom kernel, it is recommended that you create a backup of
# the original kernel and add a new entry to this file so that the device can
# fallback to the original kernel. To do this:
#
# 1, Make a backup of the original kernel
# sudo cp /boot/Image /boot/Image.backup
#
# 2, Copy your custom kernel into /boot/Image
#
# 3, Uncomment below menu setting lines for the original kernel
#
# 4, Reboot
# LABEL backup
# MENU LABEL backup kernel
# LINUX /boot/Image.backup
# INITRD /boot/initrd
# APPEND ${cbootargs}
保存好文件,重新启动 NVIDIA Jetson,系统根目录将切换到 USB 存储设备,扩容完成。
通过串口控制台恢复系统备份
当您由于误操作,或者其他原因导致系统无法正常启动(常见的情况是开机一直循环重复出现英伟达的图标),那么您在扩容所做的备份将会起到重要的作用。我们理解您此刻焦急的心情,但请您保持耐心,遵循如下步骤让 NVIDIA Jetson 进入串口控制台,我们将操作 U-boot 以恢复您的备份。
材料准备
准备材料 | 描述 |
| Ubuntu 主机 x1 |
| 无法进入系统的 NVIDIA Jetson x1 |
| UART 转 USB 模块 x1 |
| 母对母杜邦线 x3 |
进入串口控制台步骤
- 第 1 步:将 UART 转 USB 模块连接到 NVIDIA Jetson
按照如下表格的接线指示,连接 NVIDIA Jetson 到 UART 转 USB 模块。
|
NVIDIA Jetson | | UART 转 USB 模块 |
GND | --> | GND |
UART TXD | --> | RX |
UART RXD | --> | TX |
📢 小提示
- NVIDIA Jetson 和 UART 转 USB 模块的 VCC 接口不需要连接。
- 连接好线之后 NVIDIA Jetson 暂不需要通电,请先放在一旁准备好。
- 请拔掉扩容的外部存储器。
- 第 2 步:在 Ubuntu 主机上安装并启动 minicom
如果您的 Ubuntu 主机尚未安装 minicom,您可以通过如下命令将 minicom 安装到您的电脑上。
$ sudo apt-get install minicom
等待安装完成后,输入命令启动 minicom。
$ sudo minicom
在 minicom 菜单栏中,我们打开串口并配置好串口,以便能够通过 minicom 获得 NVIDIA Jetson 的启动信息。在菜单栏中按下键盘 “o” 键进入配置界面。通过键盘上下方向键控制光标移动到 “Serial port setup”。
- 第 4 步:将 NVIDIA Jetson 连接到 Ubuntu 主机
此刻,我们新建一个命令行窗口,并在窗口中输入命令监控新设备的接入。
$ dmesg --follow
此时我们将 NVIDIA Jetson 上电,然后将连接好 NVIDIA Jetson 的 UART 转 USB 模块通过 USB 接口连接到 Ubuntu 主机。此时命令行窗口会展示新接入的设备名称,我们需要找到以 “tty” 开头的片段,把它记下来。
回到 minicom,将在第 4 步获得的设备名称填入“Serial Device”中。同时检查波特率是否配置为 115200。
修改后,回车保存。选择 “Save setup as dfl” ,然后退出 minicom 界面。
重新输入命令sudo minicom
,进入 minicom 之后,我们就可以在窗口中看到 NVIDIA Jetson 的启动信息。
我们可以通过返回的信息排查 NVIDIA Jetson 启动失败的原因,并通过使用命令help
,来查看在 U-boot 系统下的所有可用命令。掌握这些命令的使用对解决问题是必要的,当然这也是困难的。
Tegra210 (P3450-0000) # help
? - alias for 'help'
base - print or set address offset
bdinfo - print Board Info structure
blkcache - block cache diagnostics and control
boot - boot default, i.e., run 'bootcmd'
bootd - boot default, i.e., run 'bootcmd'
bootefi - Boots an EFI payload from memory
bootelf - Boot from an ELF image in memory
booti - boot Linux kernel 'Image' format from memory
bootm - boot application image from memory
bootp - boot image via network using BOOTP/TFTP protocol
bootvx - Boot vxWorks from an ELF image
cmp - memory compare
coninfo - print console devices and information
cp - memory copy
crc32 - checksum calculation
dcache - enable or disable data cache
dfu - Device Firmware Upgrade
dhcp - boot image via network using DHCP/TFTP protocol
dm - Driver model low level access
echo - echo args to console
editenv - edit environment variable
enterrcm - reset Tegra and enter USB Recovery Mode
env - environment handling commands
exit - exit script
ext2load - load binary file from a Ext2 filesystem
ext2ls - list files in a directory (default /)
ext4load - load binary file from a Ext4 filesystem
ext4ls - list files in a directory (default /)
ext4size - determine a file's size
ext4write - create a file in the root directory
false - do nothing, unsuccessfully
fatinfo - print information about filesystem
fatload - load binary file from a dos filesystem
fatls - list files in a directory (default /)
fatmkdir - create a directory
fatrm - delete a file
fatsize - determine a file's size
fatwrite - write file into a dos filesystem
fdt - flattened device tree utility commands
fstype - Look up a filesystem type
go - start application at address 'addr'
gpio - query and control gpio pins
gzwrite - unzip and write memory to block device
help - print command description/usage
i2c - I2C sub-system
icache - enable or disable instruction cache
imxtract - extract a part of a multi-image
itest - return true/false on integer compare
ln - Create a symbolic link
load - load binary file from a filesystem
loadb - load binary file over serial line (kermit mode)
loads - load S-Record file over serial line
loadx - load binary file over serial line (xmodem mode)
loady - load binary file over serial line (ymodem mode)
loop - infinite loop on address range
ls - list files in a directory (default /)
lzmadec - lzma uncompress a memory region
md - memory display
mii - MII utility commands
mm - memory modify (auto-incrementing address)
mmc - MMC sub system
mmcinfo - display MMC info
mw - memory write (fill)
nm - memory modify (constant address)
nvme - NVM Express sub-system
part - disk partition related commands
pci - list and access PCI Configuration Space
ping - send ICMP ECHO_REQUEST to network host
printenv - print environment variables
pxe - commands to get and boot from pxe files
reset - Perform RESET of the CPU
run - run commands in an environment variable
save - save file to a filesystem
saveenv - save environment variables to persistent storage
setenv - set environment variables
sf - SPI flash sub-system
showvar - print local hushshell variables
size - determine a file's size
sleep - delay execution for some time
source - run script from memory
sspi - SPI utility command
sysboot - command to get and boot from syslinux files
test - minimal test like /bin/sh
tftpboot - boot image via network using TFTP protocol
true - do nothing, successfully
ums - Use the UMS [USB Mass Storage]
unzip - unzip a memory region
usb - USB sub-system
usbboot - boot from USB device
version - print monitor, compiler and linker version
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)