RZ/V2L is a versatile edge AI processor SOC that supports multiple ways to boot embedded Linux. Which boot method to use is an engineering decision that is typically based on the context in which the hardware is being used. This project covers general embedded Linux booting details, boot configuration trade-offs and considerations, and how to deploy and boot via eMMC, micro SD, or the network.
With increased focus on security, the process for booting embedded Linux has become more complex over the years. This project will touch on the key aspects relevant to RZBoard V2L (You may also find this project write-up generic enough to help with other embedded Linux devices). Thankfully, building embedded Linux for arm targets is well documented. Resources like the yocto project and arm trusted firmware documentation can also be helpful in this context.
In terms of engineering trade-offs, multiple factors can influence which boot configuration is favored. This blog touches on some key factors to consider when choosing eMMC, SD, or network boot configurations. Anecdotally, I've used all three boot configurations on embedded linux devices. As a hobbyist, I found myself often using SD cards (and replacing them as needed), but as a professional developer, I much preferred network boot for rapid iterative development, then deploying finalized images to eMMC for production.
Once clear on the benefits (and shortcomings) of the different booting methods, the later sections of this project covers how to use each configuration in practice.
Understanding Embedded Linux BootingA long-press of the power switch on RZBoard V2L, activates the event sequence shown below, that is typical for many embedded Linux devices.
The boot process involves: bootloader startup, launching the kernel, parsing the device tree binary (DTB) and loading root file-system (rootfs) into DDR memory. Specifically, RZBoard V2L uses U-Boot, and the kernel/dtb/rootfs components of the build are managed by the various yocto layers present in the build process - Read more here or here (src).
To summarize, the following table describes the role(s) and possible locations of the primary components of the RZBoard V2L boot process.
Now, review the boot mode comparison diagram below.
You can see the RZ/V2L Linux bootloader is common to all 3 boot configurations. To elaborate, 3 bootloader files: image writer, Bl2 image, and FIP image need to be flashed into RZBoard V2L before any of the listed 3 boot modes can be used. For SDcard and network boot: the bootloader image must be flashed into QSPI.For eMMC boot: the bootloader must be flashed into eMMC (this is simply done by specifying a parameter when using the RZ/V2L flash programming utility)
From the above observations, a key difference to note between these three boot configurations, is where the kernel, DTB, and rootfs are located. Next, I will cover some trade-offs and considerations of these three boot methods.
Trade-offs and ConsiderationsCore differences and practical trade-offs are discussed now, specifically for eMMC, micro SD, and network booting of RZBoard V2L. The detail provided however, is applicable also to many other embedded Linux platforms.
In summary: eMMC and SD cards have similar pros/cons derived from hardware specs, while network boot trade-offs are mostly determined by network capabilities.
So, when should you pick one boot configuration over the other? Here are some examples/use cases:
- eMMC is strong for embedded devices that require little maintenance- think self-checkout monitoring device.
- Micro SD card booting might be more applicable if you plan to replace or swap SD cards often - think trail cam.
- Network booting is very strong for development iteration & centralized maintenance, but maintaining the network comes with its own challenges. Think distributed camera system in a building/warehouse, or application development.
How do you use these methods in practice? Later sections of this project will cover the shared bootloader process and configuration-specific processes for eMMC, micro SD, and network booting.
The shared bootloader processCommon to eMMC, micro SD, and network booting, this section covers how to flash your RZBoard V2L with the three bootloader images:
Firstly, RZBoard hardware must be configured for SCIF download boot-mode.
Additionally, you will need the flash-writer utility to send the data over the USB-serial cable. To download the flash writer and its related dependencies, run the following:
$ mkdir ~/rz_qt5 && cd ~/rz_qt5
$ git clone https://github.com/Avnet/rzboard_flash_util.git
$ cd rzboard_flash_util
$ pip3 install -r requirements.txt
The flash-writer tool makes a few assumptions (README):
- The images to be flashed are located in the directory of the flash writer
rzboard_flash-util
(with the original names output by bitbake). This can also be bypassed with parameters (see README) - /dev/ttyUSB0 is used (check out the flash writer docs for overriding the default serial port)
Before running the flash-writer, you can verify your USB-Serial device is protected. I'm using a Prolific PL2303TA which shows up in lsusb
like:
$ lsusb
...
Bus 001 Device 007: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port
...
Gather the FilesCopy the bootloader files over to the target directory ~/rz_qt5/rzboard_flash_util
. These commands assume you built according to the RZBoard V2L QT project. Otherwise, just manually drag the 3 bootloader files into ~/rz_qt5/rzboard_flash_util
$ cd ~/rz_qt5/yocto_rzboard/build/
$ cp tmp/deploy/images/rzboard/Flash_Writer_SCIF_rzboard.mot ~/rz_qt5/rzboard_flash_util/
$ cp tmp/deploy/images/rzboard/bl2_bp-rzboard.srec ~/rz_qt5/rzboard_flash_util/
$ cp tmp/deploy/images/rzboard/fip-rzboard.srec ~/rz_qt5/rzboard_flash_util/
FlashingBefore flashing, you must know if you want a eMMC, micro SD, or network boot configuration! If you plan to use micro SD or network booting, make sure to include the --qspi
in your flash_rzboard.py
command; but, If you want an eMMC boot, simply use the --bootloader
parameter and eMMC flashing is assumed!
The next steps require power cycling, here is a reminder of where the power button is:
When performing a --bootloader
flash, follow the flash writer output. The general order of operations will be:
- Power down RZBoard, configure for SCIF download boot mode
- On build host, run
$ python flash_util.py --bootloader
from~/rz_qt5/rzboard_flash_util
(for eMMC) - Power up RZBoard (Still in SCIF download boot mode)
- Let the
flash_util.py
script flash the flash writer, Bl2, and FIP image. - Wait for the
Done flashing bootloader!
flash log - Power down your RZBoard, removing the BOOT2 flywire strapping J19-pin1 J1-pin2
- Power on your RZBoard
Because I just implemented the --qspi feature for the rzboard_flash_util, I'll showcase my usage of the utility in preparation for a micro SD boot.
$ python flash_rzboard.py --qspi --bootloader
Please power on board. Make sure boot2 is strapped.
Writing Flash Writer application.
Done writing Flash Writer application.
Clearing QSPI flash
Done clearing QSPI flash
Flashing bl2 image to QSPI
Done flashing bl2 image to QSPI
Flashing FIP image to QSPI
Done flashing FIP image to QSPI
Done flashing bootloader!
Running Serial Sessions with RZBoard V2LReady to boot your RzBoard and interact with it? Need to modify U-Boot parameters before launching? Here are the default serial port parameters for the debug serial port you're using to flash:
- Baud rate: 115200
- Data bits: 8
- Parity: None
- Stop bits: 1
This section will detail the final step of flashing the linux system image to eMMC, assuming you've already completed the steps of The shared bootloader process section above.
Gather the WIC FileThis section depends upon one image file:
Copy the system image file over to the target directory ~/rz_qt5/rzboard_flash_util
. These commands assume you built according to the RZBoard V2L QT project. Otherwise, just manually drag the system image file into ~/rz_qt5/rzboard_flash_util
$ cd ~/rz_qt5/yocto_rzboard/build/
$ cp tmp/deploy/images/rzboard/avnet-core-image-rzboard.wic ~/rz_qt5/rzboard_flash_util/
Lastly, flash the system image using --rootfs
flash writer parameter. For --full
or--rootfs
, flash_util.py
will try to automatically find your RZBoard IP address, unless you specify a static IP. For this demonstration, I preferred to use a static IP.
When performing a --rootfs
flash, follow the flash writer output. The general order of operations will be:
- Power down RZBoard, configure for SCIF download boot mode
- Exit SCIF download mode by removing the BOOT2 flywire strapping J19-pin1 J1-pin2. Leave BOOT1 and BOOT0 untouched.
- Give build host 192.168.1.X IP so it can share same subnet with RZBoard. Personally, I ran
$ ifconfig eno1 192.168.1.88
, as eno1 was the Ethernet port connected directly to your RzBoard. - On build host, run
$ python flash_util.py --rootfs --static_ip 192.168.1.99
from~/rz_qt5/rzboard_flash_util
- Wait for the
Power on Board. Make sure boot2 strap is NOT on
flash log - Power on your RZBoard
- Wait for the
Finished. Total time: X.Ys
log before rebooting your RZBoard
NOTE: Use your preferred parameters/method, but know your RZBoard V2L & build host must be on the same subnet. More information on the flashing utility can be found in the README
$ cd ~/rz_qt5/rzboard_flash_util/
$ python flash_rzboard.py --rootfs --static_ip 192.168.1.99
Power on board. Make sure boot2 strap is NOT on.
Waiting for device...
Setting static IP: 192.168.1.99
Putting device into fastboot mode
Device in fastboot mode
error: no response from target
< waiting for udp:192.168.1.99>
fastboot: verbose: Do flash rawimg /home/ljkeller/code/rzv2l/rzboard_flash_util/avnet-core-image-rzboard.wic
fastboot: verbose: target reported max-download-size of 117440512 bytes
Sending sparse 'rawimg' 1/27 (102256 KB) OKAY [ 11.173s]
Writing 'rawimg' OKAY [ 20.617s]
Sending sparse 'rawimg' 2/27 (114684 KB) OKAY [ 12.525s]
Writing 'rawimg' (bootloader) writing
OKAY [ 9.997s]
Sending sparse 'rawimg' 3/27 (114684 KB) OKAY [ 12.511s]
Writing 'rawimg' (bootloader) writing
OKAY [ 9.965s]
Sending sparse 'rawimg' 4/27 (114684 KB) OKAY [ 12.522s]
Writing 'rawimg' OKAY [ 10.126s]
Sending sparse 'rawimg' 5/27 (114684 KB) OKAY [ 12.532s]
Writing 'rawimg' (bootloader) writing
OKAY [ 9.935s]
Sending sparse 'rawimg' 6/27 (114684 KB) OKAY [ 13.524s]
Writing 'rawimg' (bootloader) writing
OKAY [ 10.106s]
Sending sparse 'rawimg' 7/27 (114684 KB) OKAY [ 12.520s]
Writing 'rawimg' OKAY [ 9.933s]
Sending sparse 'rawimg' 8/27 (114684 KB) OKAY [ 12.543s]
Writing 'rawimg' (bootloader) writing
OKAY [ 10.112s]
Sending sparse 'rawimg' 9/27 (114684 KB) OKAY [ 13.457s]
Writing 'rawimg' (bootloader) writing
OKAY [ 9.931s]
Sending sparse 'rawimg' 10/27 (114684 KB) OKAY [ 12.519s]
Writing 'rawimg' OKAY [ 9.924s]
Sending sparse 'rawimg' 11/27 (114684 KB) OKAY [ 12.536s]
Writing 'rawimg' (bootloader) writing
OKAY [ 10.106s]
Sending sparse 'rawimg' 12/27 (114684 KB) OKAY [ 13.537s]
Writing 'rawimg' (bootloader) writing
OKAY [ 9.940s]
Sending sparse 'rawimg' 13/27 (114684 KB) OKAY [ 12.527s]
Writing 'rawimg' OKAY [ 9.937s]
Sending sparse 'rawimg' 14/27 (114684 KB) OKAY [ 12.523s]
Writing 'rawimg' (bootloader) writing
OKAY [ 9.925s]
Sending sparse 'rawimg' 15/27 (114684 KB) OKAY [ 12.609s]
Writing 'rawimg' (bootloader) writing
OKAY [ 9.942s]
Sending sparse 'rawimg' 16/27 (114684 KB) OKAY [ 12.524s]
Writing 'rawimg' OKAY [ 15.702s]
Sending sparse 'rawimg' 17/27 (114684 KB) OKAY [ 12.527s]
Writing 'rawimg' (bootloader) writing
OKAY [ 9.972s]
Sending sparse 'rawimg' 18/27 (113788 KB) OKAY [ 12.409s]
Writing 'rawimg' (bootloader) writing
OKAY [ 15.134s]
Sending sparse 'rawimg' 19/27 (114684 KB) OKAY [ 12.531s]
Writing 'rawimg' OKAY [ 9.985s]
Sending sparse 'rawimg' 20/27 (114684 KB) OKAY [ 12.529s]
Writing 'rawimg' (bootloader) writing
OKAY [ 9.960s]
Sending sparse 'rawimg' 21/27 (113976 KB) OKAY [ 12.466s]
Writing 'rawimg' (bootloader) writing
OKAY [ 9.885s]
Sending sparse 'rawimg' 22/27 (114684 KB) OKAY [ 12.532s]
Writing 'rawimg' OKAY [ 9.975s]
Sending sparse 'rawimg' 23/27 (114684 KB) OKAY [ 12.525s]
Writing 'rawimg' (bootloader) writing
OKAY [ 9.932s]
Sending sparse 'rawimg' 24/27 (114684 KB) OKAY [ 12.515s]
Writing 'rawimg' (bootloader) writing
OKAY [ 9.948s]
Sending sparse 'rawimg' 25/27 (114684 KB) OKAY [ 12.514s]
Writing 'rawimg' OKAY [ 9.932s]
Sending sparse 'rawimg' 26/27 (114684 KB) OKAY [ 12.172s]
Writing 'rawimg' (bootloader) writing
OKAY [ 9.925s]
Sending sparse 'rawimg' 27/27 (104524 KB) OKAY [ 11.985s]
Writing 'rawimg' (bootloader) writing
(bootloader) writing
(bootloader) writing
OKAY [ 73.463s]
Finished. Total time: 693.934s
Once this process has complete, you should be ready to launch!
LaunchingUpon rebooting your rzboard, you should see the following U-Boot logs from your serial terminal connection.
...
Importing environment from mmc0 ...
switch to partitions #0, OK
mmc0(part 0) is current device
... (kernel launch, etc...)
Enjoy!
Micro SD Deployment & BootingThis section will detail the final step of flashing the Linux system image to micro-SD, assuming you've already completed the steps of The shared bootloader process section above.
Gather the WIC FileThis section depends upon one image file:
Booting from SD card requires a QSPI boot configuration with some extra steps. The procedure can be summarized as:
Here is an image depicting the BOOT configuration:
Follow steps 1 and 2 before continuing.
Writing to micro SDWriting to the micro SD is trivial thanks to Ubuntu's built-in disk image writer tool. Here are the steps with some visual aid.
Insert your micro SD card into your Ubuntu machine. Personally, I use a USB C hub for this.
Find your.wic file in the Ubuntu File explorer. Right click > Open With Disk Image Writer
Now, CAREFULLY select the micro SD inserted into your Ubuntu machine in the list of available disks.
Begin writing by clicking Start Restoring...
.
Confirm you want to write the SD card by clicking Restore
.
The disk writing process will now begin, and the image writer will notify you the process is complete. Once the process is complete, you should see how the micro SD is now partitioned:
The device tree and kernel are in the 500 MB FAT32 partition, while the rootfs is placed in the 4.1 GB Ext4 partition.
Make sure to Eject the micro SD in software before physically ejecting it. Next, insert the micro SD into your RZBoard before powering the board on.
Here is an example of the micro SD boot logs:
Look how easy the micro SD process is- go ahead and login!
Username: root
Password: avnet
Network Deployment & BootingThis section will detail the network boot process, assuming you've already completed the steps of The shared bootloader process section above.
Gather the.bin,.dtb, and.bz2 filesThis section depends upon three files:
After gathering these files, you are ready to setup your Ubuntu machine for network deployment.
Network Boot OverviewNetwork boot requires a custom QSPI boot configuration on the RzBoard with a NFS and TFTP server setup on an Ubuntu machine. The procedure can be summarized as:
Here is an image depicting the boot configuration:
Follow steps 1 and 2 before continuing.
Setup and Configuration of Ubuntu MachineFirst, you must download NFS and TFTP server dependencies; then create a directory to serve the kernel and DTB out of.
$ sudo apt-get update
$ sudo apt-get install tftp tftpd-hpa nfs-common nfs-kernel-server cu
$ sudo mkdir /tftpboot
Configure your TFTP serverConfigure your TFTP server for serving out of /tftpboot
on port 69. This requires sudo permissions. For example
sudo vi /etc/default/tftpd-hpa
Update the parameters to look like:
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/tftpboot"
TFTP_ADDRESS=":69"
TFTP_OPTIONS="--secure"
Start the TFTP server, then confirm it has started using the commands below:
$ sudo systemctl enable tftpd-hpa
$ sudo systemctl restart tftpd-hpa
$ sudo chmod 777 /tftpboot
$ sudo echo “Hello” > /tftpboot/hello.txt
$ sudo tftp localhost
> get hello.txt
If no error message is displayed, the TFTP server is successfully started. Enter q
to exit from the TFTP prompt
Note: If above command did not show the expected result, then you should restart the Ubuntu hostPC, and try this again
Locate RZBoard's Linux kernel Image file and DTB file, then move/copy these into the TFTP server folder at /tftpboot. The image file should be shortened to Image.bin, while the DTB file should be renamed to rzboard.dtb. Renaming these files will make our U-Boot configuration later easier.
For example, my most recent build files looked like this originally (at my build path /home/username/code/rzv2l/main/yocto_rzboard/build/tmp/deploy/images/rzboard
):
Image--5.10.145+gitAUTOINC+fe9d9833ad-r1-rzboard-20230915143205.bin
rzboard--5.10.145+gitAUTOINC+fe9d9833ad-r1-rzboard-20230915143205.dtb
ls /tftpboot
Image.bin rzboard.dtb
Configure your NFS serverStart the NFS server and create a directory for RZBoard's NFS service:
$ sudo /etc/init.d/nfs-kernel-server start
$ sudo mkdir /nfs/rzv2l -p
Modify the NFS server configuration, by adding the following line at end of the /etc/exports
file:
$ vi /etc/exports
…
/nfs/rzv2l *(rw,no_subtree_check,sync,no_root_squash)
Refresh the NFS server, then confirm the NFS server is successfully started by executing the following command. If the same result is shown, the NFS server is successfully started.
$ sudo exportfs -a
$ showmount -e localhost
Export list for localhost:
/nfs/rzv2l *
Note: If above command did not show the expected result, please restart the Ubuntu PC, and try it again.
Locate the large Linux file-system archive file. My most recent build output avnet-core-image-rzboard-20230919181523.rootfs.tar.bz2
for example, and rename the file to avnet-core-image-rzboard.rootfs.tar.bz2. Finally, execute the following command on the Ubuntu host PC (with NFS server already started) to extract the RZBoard file system into the NFS server folder:
$ sudo tar xfj <PATH_to_FILE>/avnet-core-image-rzboard.tar.bz2 -C /nfs/rzv2l
The rootfs should extract into the /nfs/rzv2l
directory as follows:
$ ls /nfs/rzv2l
bin boot dev etc home lib lib64 media mnt proc run sbin sys tmp usr var
Set a Static IP Address for Ubuntu PC's Ethernet InterfaceFor the Ethernet communication between host PC and RZBoard, the IP address of the Ubuntu PC must be static. Implement this using one of these two methods:
- Configure the DHCP server of your network router to reserve / always assign the same IP address (eg. 192.168.1.77) to the Ubuntu host PC
- Alternatively, disable the default network settings on the Ubuntu PC, then create a new network netplan.yaml file, specifying this static IP address. eg. Disable the network settings:
$ sudo mv /etc/netplan/01-network-manager-all.yaml /etc/netplan/01-network-manager-all.yaml.disabled
Create /etc/netplan/99-netcfg.yaml
and add the following line (the name enp0s3
may be different, depending on environment):
network:
version: 2
ethernets:
enp0s3:
addresses: [192.168.1.77/24]
gateway4: 192.168.1.1
nameservers:
addresses: [192.168.1.1]
search: []
optional: true
Restart the network:
$ sudo netplan apply
Setup a Custom U-Boot ConfigurationOpen a serial terminal like putty/screen/minicom and connect with the default settings in the Running Serial Sessions with RZBoard V2L section above. Power on your RZBoard V2L. Immediately following power-up of RZBoard, repeatedly press the ENTER key in your serial terminal to interrupt the U-Boot autoboot sequence.
At the u-boot console prompt, enter new u-boot environment settings as follows:
env default -a
setenv ipaddr 192.168.1.11
setenv serverip 192.168.1.77
setenv netmask 255.255.255.0
setenv ethaddr 02:11:22:33:44:55
setenv boot_tftp 'tftpboot 0x48080000 Image.bin; tftpboot 0x48000000 rzboard.dtb; booti 0x48080000 - 0x48000000'
setenv bootargs root=/dev/nfs rw nfsroot=${serverip}:/nfs/rzv2l,nfsvers=3 ip=${ipaddr}:${serverip}::${netmask}:rzv2l:eth0
setenv bootcmd run boot_tftp
saveenv
boot
Entering boot command at end of this list, restarts the bootloader sequence. You should notice some obvious, network-specific U-Boot logs at this point. Example:
After U-boot, log messages from successful loading of Linux should be displayed.
Now, changes to your Ubuntu files in /nfs/rzv2l will be be directly reflected on your RZBoard V2L!
Conclusion and How to Find RZBoard InfoHopefully this has proved helpful to better understand the specifics of booting from different media (and reasons for choosing these different boot methods)
If you don't yet have RZBoard hardware, checkout the product page at http://avnet.me/rzboard (besides links to technical documentation and reference designs, this includes a BUY button that gets you over to the purchase page that shows available warehouse inventory ready to ship)Checkout also the growing list of other RZBoard project blogs here on Hackster.io. For example, Run Machine Learning on the RZBoard is a good starting point for working with ML & the DRP-AI accelerator.
Comments
Please log in or sign up to comment.