How to Boot Jetson Nano From USB 3.0 (Natively) with Jetpack 4.5

If you have a Jetson Nano booting from a microSD card, you stand to gain both increased speed and a longer lifespan by switching out the microSD card for a USB 3.0 drive. In this guide, I’ll walk you through the process of wiping, partitioning, and flashing a USB drive and booting a Jetson Nano from it. Further, we won’t rely on hacks and workarounds like some other methods, since the ability to boot from USB is now built-in to Jetpack 4.5 and officially supported by Nvidia. The only issue is that Nvidia’s documentation is a bit verbose and doesn’t do enough to help users through the process. I took the time to read through the documentation and watch an Nvidia webinar so you don’t have to!

Quick Note: The original post overlooked a significant detail. In order for this process to work, you must flash the Nano with Jetpack 4.5 on the microSD card before you attempt to boot from USB. This is because the board will not allow boot from USB until the QSPI chip has been updated with new instructions, but that can only happen if you update to Jetpack 4.5 or later. The easiest and quickest way is to use Nvidia’s SDK Manager. You can follow this guide on Nvidia’s website to flash a microSD card with 4.5 using SDK Manager. The rest of this post depends on you having flashed a microSD with 4.5.

Requirements

I will assume you have the following components, all of which are necessary to complete the process:

  • A PC running Ubuntu 18.04 (16.xx and 20.xx were not tested, but they may still work)
  • A USB 3.0 flash drive (USB 2.0 is fine too, but you won’t be getting the best bang for your buck) with at least 16GB of space, preferably larger (I will use a 128GB drive in this guide)
  • A Jetson Nano powered via barrel jack connector (this won’t work if you use the mini-USB port to power the board, since we need to use the mini-USB for data transfer during the flashing process)
  • A jumper wire to put your Nano into recovery mode
  • You must flash a microSD card with Jetpack 4.5 or later and go through the system setup (user, password, locality, etc) in order to update the QSPI chip which allows later booting from USB.

Note: this process has only been tested and verified on Nano’s with SD card slots and not on Nano’s with built-in eMMC modules.

Step 1: Install Host Machine Dependencies

Run the following commands on your host machine

sudo apt-get update
sudo apt-get install qemu-user-static

Step 2: Setup USB Drive

  1. Run the following command twice, once before inserting the USB and once after inserting the USB. We run it twice to be 100% sure that we are wiping and writing to the correct device. In this example, the device we want to use is /dev/sdc, but it may be different on your host machine.
sudo lsblk -p -d | grep sd
>    /dev/sda       8:0    0 465.8G  0 disk
>    /dev/sdb       8:16   1    16M  1 disk

Insert the USB device…

sudo lsblk -p -d | grep sd
>    /dev/sda       8:0    0 465.8G  0 disk
>    /dev/sdb       8:16   1    16M  1 disk
>    /dev/sdc       8:32   1 114.6G  0 disk
  1. Create environment variables to make the following snippets easier to copy/paste. Note that the USB_SIZE variable below is not the full size of the disk. You can choose whatever size you want, as long as it’s at least 16GB, but I left some space for an additional partition incase I need it later. EXTREMELY IMPORTANT: make sure you change sdX to the correct value from above in the following commands. YOU CAN DESTROY YOUR HOST SYSTEM IF YOU DO NOT DO THIS CORRECTLY sdX must be changed to point to the USB drive you intend to install Jetpack on. In the case above, we are using sdc and sdc1, but you may need to use sdb or something else entirely.
export SDX=sdX
export SDX_PART=sdX1
export USB_SIZE=96GB
  1. We’re going to wipe the USB drive with the following commands. First, we need to make sure there are no existing partitions on the USB. If there are, we need to unmount them before proceeding.
sudo lsblk | grep sd

sda           8:0    0 465.8G  0 disk
├─sda1        8:1    0   512M  0 part /boot/efi
└─sda2        8:2    0 465.3G  0 part /
sdc           8:16   1 115.7G  0 disk
└─sdc1        8:17   1  89.4G  0 part /media/rob/0640288e...
  • Note that, in my case, there is an entry under sdc called sdc1, and it is mounted at location /media/rob/0640288e.... We need to unmount that partition before continuing.
# --------------------------------------------------------
# Only required if you have a mounted partition from above
# --------------------------------------------------------

sudo umount <location>

# --------------------------------------------------------
# Where <location> in my case is equal to /media/rob/0640288e...
# --------------------------------------------------------
  • Verify that the partition was successfully unmounted by running sudo lsblk | grep sd again. Once that is done, run the following command to wipe the USB Drive.
sudo dd if=/dev/zero of=/dev/${SDX} bs=1M count=16000 status=progress
  • This command reads from a constant stream of zero’s located at /dev/zero and writes that to the drive 1MB at a time. Note that we are only writing about 16GB of data to the drive. You can choose a larger count, but it could take a very long time to complete. 16GB should be sufficient to create a boot drive.
  1. Create a new GUID Partition Table (GPT)
sudo parted /dev/${SDX} mklabel gpt

> Warning: The existing disk label on /dev/sdc will be destroyed and all data on this disk will be lost. Do you want to continue?
Yes/No? yes
  • Note: If you get an error like the following…
> Error: Partition(s) 1 on /dev/sdc have been written, but we have been unable to inform the kernel of the change, probably because it/they are in use.  
> As a result, the old partition(s) will remain in use.  You should reboot now before making further changes.
Ignore/Cancel? cancel
  • Type cancel + Enter. This error means that the USB device is mounted and you must unmount it before continuing. See steps above.
  1. Create a new partition on the USB drive and mount it.
sudo parted /dev/${SDX} mkpart APP 0GB ${USB_SIZE}
sudo mkfs.ext4 /dev/${SDX_PART}
sudo mount /dev/${SDX_PART} /mnt
  • The USB Drive should now be ready for writing. Next, we prepare the the files that will be written to USB.

Step 3: Download and Prepare BSP and rootfs

cd ~/
wget https://developer.nvidia.com/embedded/L4T/r32_Release_v5.0/T210/Tegra210_Linux_R32.5.0_aarch64.tbz2
wget https://developer.nvidia.com/embedded/L4T/r32_Release_v5.0/T210/Tegra_Linux_Sample-Root-Filesystem_R32.5.0_aarch64.tbz2

Step 4: Setup Environment Variables

export L4T_RELEASE_PACKAGE=Tegra210_Linux_R32.5.0_aarch64.tbz2
export SAMPLE_FS_PACKAGE=Tegra_Linux_Sample-Root-Filesystem_R32.5.0_aarch64.tbz2
export BOARD=jetson-nano-devkit

Step 5: Extract and Apply

tar xf ${L4T_RELEASE_PACKAGE}
cd Linux_for_Tegra/rootfs/
sudo tar xpf ../../${SAMPLE_FS_PACKAGE}
cd ~/Linux_for_Tegra
sudo ./apply_binaries.sh

Note: The final line should say “Success!” is everything worked properly.

Step 6: Patch l4t-payload-updater

cd ~/Linux_for_Tegra/rootfs/usr/sbin
sudo rm l4t_payload_updater_t210
sudo wget https://developer.nvidia.com/l4t-payload-updater-t210 -O l4t_payload_updater_t210
sudo chmod +x l4t_payload_updater_t210

Step 7: Recovery Mode and Connect

  1. Power down the Nano
  2. Put the Nano into “recovery” mode.
    • For revision B01, place a jumper wire across pins 9 and 10 of the button header (J50, underneath the heatsink module)
    • For revision A02, place a jumper wire across pins 3 and 4 of the button header (J40, near camera header)
    • Correct configuration for revision B01 is shown in the image below.
  3. Connect the mini-USB cable from the Nano to your host machine.
  4. Apply power to turn the Nano on.
  5. After 3 seconds, disconnect the jumper wires.
  6. Verify that the Nano is in recovery mode by executing lsusb on your host. You should see something like Bus 001 Device 011: ID 0955:7f21 NVidia Corp.

Step 8: Mount, Copy, Unmount

  • Note: We are not changing sda1 to ${SDX_PART} in the following code. You must keep it as sda1.
cd ~/Linux_for_Tegra
sudo BOOTDEV=sda1 ./flash.sh --no-flash ${BOARD} sda1
sudo mkdir tmp_system
sudo mount bootloader/system.img.raw ./tmp_system/
sudo rsync -axHAWX --numeric-ids --info=progress2 --exclude=/proc ./tmp_system/ /mnt
sudo umount /mnt
sudo umount ./tmp_system

Step 9: Jetson Nano Peripheral Setup

1) Power down the Jetson Nano. Make sure the jumper wires for recovery mode are removed.
2) Remove the USB Drive from your host machine.
3) Remove the SD Card (if any) from the Jetson Nano. This is an important step since, if an SD Card is present, the Nano will always boot from SD rather than USB.
4) Remove the mini-USB connection between your host machine and the Jetson Nano.
5) Insert the USB Drive into the Jetson Nano.
6) Ensure that any USB accessories (mouse, keyboard) and HDMI are plugged in before turning the power back on.

Step 10: Power On and Complete System Setup

  • After the SD Card has been removed and the USB + peripherals have been inserted, apply power to the Jetson Nano. If everything worked correctly, you will briefly see some system dialog followed by the typical system setup process. Complete this process and the device will reboot. Next, we will want to install system libraries, SDK’s, and dependencies. I will be writing a guide on how to easily install these components using Nvidia’s SDK Manager as soon as possible. Check back soon!

7 responses to “How to Boot Jetson Nano From USB 3.0 (Natively) with Jetpack 4.5”

  1. Hi Rob, thanks for your efforts..

    My go was successful and your commands have allowed me to use an SSD with at least a 5x speed increase over the old SD card 🙂

    Now the issue is ‘dpkg’ errors on the usual apt update / upgrade command. I’ve posted the error output below. My install is on a Jetson Nano 2Gb – with the following firmware >


    NVIDIA Jetson Nano (Developer Kit Version)
    L4T 32.5.1 [ JetPack UNKNOWN ]
    Ubuntu 18.04.5 LTS
    Kernel Version: 4.9.201-tegra

    I’ll also post this on the Nvidia forums too – but you may have already encountered this. hence my post here. Error output below…

    Cheers, Michael.

    _______

    Setting up nvidia-l4t-bootloader (32.5.1-20210219084526) …
    3448-300-0003–1–jetson-nano-devkit-sda1
    Starting bootloader post-install procedure.
    ERROR. Procedure for bootloader update FAILED.
    Cannot install package. Exiting…
    dpkg: error processing package nvidia-l4t-bootloader (–configure):
    installed nvidia-l4t-bootloader package post-installation script subprocess returned error exit status 1
    Setting up nvidia-l4t-xusb-firmware (32.5.1-20210219084526) …
    3448-300-0003–1–jetson-nano-devkit-sda1
    Starting xusb firmware post-install procedure.
    ERROR. Procedure for xusb firmware update FAILED.
    Cannot install package. Exiting…
    dpkg: error processing package nvidia-l4t-xusb-firmware (–configure):
    installed nvidia-l4t-xusb-firmware package post-installation script subprocess returned error exit status 1
    dpkg: dependency problems prevent configuration of nvidia-l4t-initrd:
    nvidia-l4t-initrd depends on nvidia-l4t-xusb-firmware (= 32.5.1-20210219084526); however:
    Package nvidia-l4t-xusb-firmware is not configured yet.

    dpkg: error processing package nvidia-l4t-initrd (–configure):
    dependency problems – leaving unconfigured
    Setting up nano (2.9.3-2) …
    No apport report written because the error message indicates its a followup error from a previous failure.
    update-alternatives: using /bin/nano to provide /usr/bin/editor (editor) in auto mode
    update-alternatives: warning: skip creation of /usr/share/man/man1/editor.1.gz because associated file /usr/share/man/man1/nano.1.gz (of link group editor) doesn’t exist
    update-alternatives: using /bin/nano to provide /usr/bin/pico (pico) in auto mode
    update-alternatives: warning: skip creation of /usr/share/man/man1/pico.1.gz because associated file /usr/share/man/man1/nano.1.gz (of link group pico) doesn’t exist
    Processing triggers for man-db (2.8.3-2ubuntu0.1) …
    Errors were encountered while processing:
    nvidia-l4t-bootloader
    nvidia-l4t-xusb-firmware
    nvidia-l4t-initrd
    E: Sub-process /usr/bin/dpkg returned an error code (1)

    Liked by 1 person

    • Hi Michael, happy to help! One thing I found with the Nano devices in general is that the `sudo apt-get upgrade` command tends to break things, unfortunately.

      I have indeed encountered this exact same issue and the only way I was able to fix it was by purging `nvidia-l4t-bootloader`, `nvidia-l4t-xusb-firmware`, and `nvidia-l4t-initrd`. I didn’t record my steps, unfortunately, but you should try `sudo apt-get purge nvidia-l4t-bootloader`, and so on. After purging all three of the specified packages, do a `sudo apt-get autoremove` and then reboot the device.

      You will also find this issue discussed briefly on the Nvidia forum here: https://forums.developer.nvidia.com/t/dist-uopgrade-fails-on-l4t-bootloader/121346, which may or may not help you find a fix!

      Like

  2. Thanks for this blog post. I can’t wait for part 2 (regarding step 10).

    I have two questions: 1) Is this reversible? I mean, will I be able to return to SD as root device? 2) The purpose of read only systems or overlay systems is to protect the SD from being damaged on sudden power loss during write cycles. Is there anything known about whether or not such a USB stick is not the same way problematic as an SD?

    Like

  3. Thanks for this tutorial. I have a a jetson-nano B01 with JP 4.5.1 latest. So QSPI firmware has been updated to boot from USB.

    I just want to know how I can do it without a host Ubuntu PC because I dont have access to one.
    It seems many of the steps can be done on Jetson Nano itself.

    Like

  4. Hi, nice post. Is there any chance to use HDD bigger than 2TB. I’m trying this with 4TB and got errors:
    GUID Partition Table Header signature is wrong: 0x0 != 0x5452415020494645
    find_valid_gpt: *** ERROR: Invalid Backup GPT ***
    GPT: first_usable_lba incorrect: 22 > 0
    find_valid_gpt: *** ERROR: Invalid GPT ***
    GUID Partition Table Header signature is wrong: 0x0 != 0x5452415020494645
    find_valid_gpt: *** ERROR: Invalid Backup GPT ***
    ** Invalid partition 1 *

    I thing it’s because of big drive..

    Like

Leave a comment