Production line programming of Jetson Nano Production Nano

We have developed a custom carrier board for the Jetson Nano production module.

I am now trying to find an efficient method for flashing the Nano in a production line environment. Using the SDK Manager does not lend itself to high volume production. We are using Ubuntu Linux and then adding proprietary files to that.
What I would like to do is pull an image off of my reference build module and then flash that image repeatedly onto new units as they are assembled in a production line.
Any pointers or links? I cannot find anything helpful on the NVidia website.

Normally SDKM installs the “driver package”, which is what the content is at “~/nvidia/nvidia_sdk/JetPack...version.../Linux_for_Tegra/”. This is what performs the actual flash, and SDKM is just a front end for downloading and other utilities (the driver package is available for separate download).

The actual image which is generated is a nearly exact match to whatever is at “Linux_for_Tegra/rootfs/”. Normally SDKM would unpack the sample rootfs there, and run the “” script to copy NVIDIA’s drivers in to what would otherwise be a purely Ubuntu rootfs (this is when you can call it “L4T” instead of “Ubuntu”, but it is still Ubuntu).

The actual flash, if performed on command line via the “Linux_for_Tegra/” script “”, uses arguments passed to slightly modify some of the the “rootfs/boot/” content. Then the actual binary image is created, and it becomes “Linux_for_Tegra/bootloader/system.img”. If you replace that system.img with your image, and use the “-r” option to flash, then a new image is not created, and the old system.img is used again without modification.

If you have a rootfs image, and place it as “Linux_for_Tegra/bootloader/system.img”, then it will flash your image every time, as many times as you want.

Keep in mind the following: When generating a system.img there is both a “raw” format and a “sparse” format. “Raw” is just an exact partition right down to the last byte. “Sparse” cuts size by not adding filesystem space which is empty. Both can be used for flash if they are at “bootloader/system.img”, and the result will be the same, but raw will take longer than sparse. However, raw can be loopback mounted, manipulated, edited, so on. If you use dd to copy a root partition, then this is essentially what the raw format system.img is (and can be used to flash, but you’d have to be careful since using dd on a running filesystem which changes during copy might not always do what you expect).

If your image is not the default size, then you’d want to specify size. You can’t find that from a sparse image, but if you have a raw image, then the size, if evenly divisible twice by 1024, is the size in MiB. If the size of the raw partition is evenly divisible by 1024 three times, then this is the size in GiB. To illustrate, if your raw partition is 15288238080 bytes, then this can be divided by 1024 twice and evenly results in “14580 MiB”. The option “-S 14580MiB” would specify this.

If you were to flash an eMMC version of a Nano with defaults on command line from “Linux_for_Tegra/”, then you might use a command like this:
sudo ./ jetson-nano-emmc mmcblk0p1

To modify this to reuse the “Linux_for_Tegra/bootloader/system.img”, and not generate a new image for the rootfs, use “-r”:
sudo ./ -r jetson-nano-emmc mmcblk0p1

To reuse the image and make sure a 14580 MiB size is configured:
sudo ./ -r -S 14580MiB jetson-nano-emmc mmcblk0p1

You can clone a rootfs partition. This guarantees it won’t change during copy since the Jetson is in recovery mode, and is the best way to get a matching rootfs. Do beware that a clone which was created from one L4T release version will be unlikely to be compatible with that of a different L4T release. Also, you would want to avoid telling it to “only” flash rootfs, you’d want it to flash all content, with your clone becoming the rootfs. That other content is tiny and fast and if it does not match, then it will fail at least part of boot.

A clone could have something in it you do not want, e.g., it will preserve any code for setting up by a specific ethernet MAC address, and obviously the second Jetson will have a new MAC, and so that would fail to run as expected. Account names and passwords would also be preserved, and you might not want that. There are some interesting ways to edit under QEMU from the host PC using a loopback device over the raw image:

You should also see the “Linux_for_Tegra/README_Massflash.txt” file.

1 Like

Thank you for your response. That is a great help.

I seem to be having trouble getting some jetson-nano-emmc modules to go into ‘forced-recovery’ mode. I am powering up with pins 9-10 shorted and then removing the jumper, yet no device is showing up in /dev. Is there something else I am supposed to be doing?

It seems that I was removing the ‘force recovery’ jumper.

I now have a kernel, rootfs, and proprietary apps loaded and working.

However, now I am having trouble pulling the kernel and rootfs off of the Nano module. These would be the images I want to deploy in a production environment.

I have read README_Massflash.txt and scanned the source for and still do not understand how to use these tools to accomplish that.

Any help would be greatly appreciated.

The forced recovery button is like a “shift key” to the power button. If the jumper is in place while either starting power or resetting power, then you are done and can remove the recovery mode jumper.

What do you mean by pulling the kernel and rootfs off of the Nano? Do you mean you want to clone? Clone (on even semi-recent releases) should be:
sudo ./ -r -k APP -G my_backup.img jetson-nano-emmc mmcblk0p1
(which produces both “my_backup.img” and “my_backup.img.raw”)

I can’t help with massflash, I have not personally used this. However, it would be an extension of the single unit flash.