NVIDIA Jetson Nano/Xavier NX 扩容教程

  • Post author:
  • Post category:其他


在售的 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

)挂载到真正的根目录。

  1. 那么在上述的两个阶段中,内核借助临时根文件系统装载功能模块的部分(第一阶段)我们是不需要进行修改的,所以即使 NVIDIA Jetson 已经实现扩容,它仍会需要使用 eMMC。
  2. 我们需要改造的是第二个阶段,将根文件系统挂载到外部存储器中,从而实现扩容。

扩容注意事项


  1. 通过外部存储设备进行扩容的主要原理是将 rootfs 设置为在外部存储设备上。

  2. 此扩容方法将会对 Linux 内核级别的系统文件进行修改,您可能会遇到一些不容易解决的问题。您在根据此教程完成扩容操作时应当使用的是新的 NVIDIA Jetson 以及新的存储设备,不要尝试在设备中存放使用有价值的文件。如果一切未按预期,您可能会需要重新格式化存储设备甚至是 NVIDIA Jetson。对于最后的保留方案,我们会提供通过串口的方式尽可能帮助您恢复备份,但一切数据的丢失责任需要您自行承担。

  3. 此扩容过程与网上其他早期的扩容方法相比,不需要重新编译内核,节省了大约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)的存储设备不能完成扩容操作。

扩容步骤


  • 第 1 步:安装 SSD

请按照“硬件使用说明”中的步骤为 NVIDIA Jetson 安装好 SSD。


  • 第 2 步:准备 SSD

使用快捷键

Ctrl+F

或点击左上角的 Ubuntu 图标搜索 Disks,打开 Ubuntu 18.04 自带的 Disks 工具。

在左侧选择你的 SSD,然后在右上角的菜单栏下选择“Format Disk”。

将你的 SSD 格式化成 GPT 格式。此时会弹出窗口让你确认并输入用户密码。

然后,我们点击中间的“+”,添加盘符。

点击“Next”。

请给你的 SSD 起一个名字,并在类型中选择第四代扩展文件系统(Ext4),最后点击“Create”即可。此时我们已经按照扩容的要求完成了 SSD 的前期准备。


  • 第 3 步:将根目录构建到 SSD 上

使用 git 命令将我们需要使用的脚本文件下载到 NVIDIA Jetson 上。

$ git clone https://github.com/limengdu/rootOnNVMe.git
$ cd rootOnNVMe/

然后执行如下命令,将 eMMC 中根目录的文件构建到 SSD 中,这个步骤的等待时间视您所使用的根目录大小所决定。

$ ./copy-rootfs-ssd.sh

  • 第 4 步:配置环境,完成扩容

执行如下命令,完成 rootfs 的配置。

$ ./setup-service.sh

重新启动 NVIDIA Jetson,会发现 eMMC 已经变成了外部存储设备显示在主界面上,查看系统占用空间也发现变少了,扩容成功。

⚠️ 注意:

  1. 脚本文件中默认的 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)的存储设备不能完成扩容操作。

扩容步骤


  • 第 1 步:


    准备必要的文件

使用 git 命令下载我们需要用于 NVIDIA Jetson 的脚本文件。

$ git clone https://github.com/limengdu/bootFromUSB.git
$ cd bootFromUSB

  • 第 2 步:准备 USB 存储设备

将 USB 存储设备连接到 NVIDIA Jetson。使用快捷键

Ctrl+F

或点击左上角的 Ubuntu 图标搜索 Disks,打开 Ubuntu 18.04 自带的 Disks 工具。

在左侧选择你的 USB 存储设备,然后在右上角的菜单栏下选择“Format Disk”。

将你的 USB 存储设备格式化成 GPT 格式。此时会弹出窗口让你确认并输入用户密码。

然后,我们点击中间的“+”,添加盘符。

点击“Next”。

请给你的 USB 存储设备起一个名字,并在类型中选择第四代扩展文件系统(Ext4),最后点击“Create”即可。此时我们已经按照扩容的要求完成了 USB 存储设备的前期准备。


  • 第 3 步:挂载 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

  • 第 4 步:复制系统到 USB 存储设备中


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 存储的文件大小。


  • 第 5 步:备份及查询 USB 设备的 UUID

为了保证万无一失,我们需要查询一下 USB 设备的 UUID。

$ ./partUUID.sh

这个命令默认的操作路径为 sda1(/dev/sda1) ,但是您也可以确定其他 USB 设备的 UUID。规定 /dev/ 使用 -d 标志。例如:

$ ./diskUUID.sh -d sdb1

⚠️ 注意:

如果返回的 UUID 在格式和长度上不同于上面的示例,那么设备很可能没有格式化为 Ext4,请从第 2 步重新开始!


  • 第 6 步:


    修改引导配置以完成扩容

我们需要首先对引导配置文件进行备份。

$ 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

📢 小提示

  1. NVIDIA Jetson 和 UART 转 USB 模块的 VCC 接口不需要连接。
  2. 连接好线之后 NVIDIA Jetson 暂不需要通电,请先放在一旁准备好。
  3. 请拔掉扩容的外部存储器。

  • 第 2 步:在 Ubuntu 主机上安装并启动 minicom

如果您的 Ubuntu 主机尚未安装 minicom,您可以通过如下命令将 minicom 安装到您的电脑上。

$ sudo apt-get install minicom

等待安装完成后,输入命令启动 minicom。

$ sudo minicom


  • 第 3 步:准备配置 minicom

在 minicom 菜单栏中,我们打开串口并配置好串口,以便能够通过 minicom 获得 NVIDIA Jetson 的启动信息。在菜单栏中按下键盘 “

o

” 键进入配置界面。通过键盘上下方向键控制光标移动到 “

Serial port setup

”。


  • 第 4 步:将

    NVIDIA Jetson

    连接到 Ubuntu 主机

此刻,我们新建一个命令行窗口,并在窗口中输入命令监控新设备的接入。

$ dmesg --follow

此时我们将 NVIDIA Jetson 上电,然后将连接好 NVIDIA Jetson 的 UART 转 USB 模块通过 USB 接口连接到 Ubuntu 主机。此时命令行窗口会展示新接入的设备名称,我们需要找到以 “

tty

” 开头的片段,把它记下来。


  • 第 5 步:U-boot 操作

回到 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



版权声明:本文为weixin_44571647原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。