As explained in Installing U-Boot to the NXP i.MX RT1170 EVK board, you have to install U-Boot to the QSPI Flash of the NXP i.MX RT1170 EVK board in order to run Linux (uClinux). U-Boot runs as the primary firmware from the QSPI Flash on each power-on / reset.
U-Boot is probably the most popular firmware monitor for Linux. It is developed and maintained by DENX Software Engineering (www.denx.de). If you need detailed information on any aspects of U‑Boot operation, DENX publishes extensive U‑Boot user documentation at their web site.
On the i.MX RT1170 microcontrollers, U‑Boot is started from the QSPI NOR Flash by the built-in i.MX ROM bootloader. Boot mode is specified with the states of the BOOT_MODE and BOOT_CFG pins, which are configured with the SW1 and SW2 switches on the NXP i.MX RT1170 EVK board.
When the BOOT_MODE pins select the internal boot and the BOOT_CFG pins select the QSPI Flash as a source boot, then the i.MX RT1170 ROM bootloader searches for a bootable firmware image of the special format at offset 0x400 of the QSPI Flash. There are two header prepended to the generic u-boot.bin U-Boot image to make is bootable from the QSPI Flash on the i.MX RT family:
- First is the FlexSPI Configuration Block, which must be located at offset 0x400 of the QSPI Flash. It contains parameters required for i.MX RT's FlexSPI controller to properly map the specific Flash devices such as read command sequence, quad or octal Flash mode etc.
- Second is the Image Vector Table (IVT), which must be located at offset 0x1000 of the QSPI Flash. It contains information necessary for the ROM bootloader to relocate and pass control to U‑Boot correctly.
The U-Boot u-boot.flexspi image consists of the generic u-boot.bin and two headers described above. It is ready to install to offset 0 of the QSPI Flash on the NXP i.MX RT1170 EVK board.
As soon as the NXP i.MX RT1170 EVK board is powered on or reset, the i.MX RT1170 proceeds to boot the U‑Boot firmware from the QSPI Flash as follows:
- The i.MX ROM bootloader initializes the FlexSPI controller to map the QPSI Flash to the i.MX RT1170 processor's address space (similarly as a regular NOR Flash) accordingly to parameters from the FlexSPI Configuration Block.
- The i.MX ROM bootloader passes control to U-Boot (IVT is configured is such a way so relocation is not required, U-Boot is started directly from the address where the QSPI Flash is mapped).
- U-Boot initializes SDRAM, relocates itself to the end of SDRAM and continues to execute from there. Volatile data (stack, variables, dynamic pool) are maintained in the external SDRAM memory as well. The U-Boot environment variables are stored in the QSPI Flash.
The following output must be printed out to the serial console during booting the U-Boot image:
U-Boot 2017.09-rc1-imxrt-2.5.3 (Mar 31 2021 - 21:21:46 +0300)
CPU: i.MX RT117x at 996MHz
Model: NXP i.MXRT1174 EVK
DRAM: 64 MiB
MMC: FSL_SDHC: 0
SF: Detected is25wp128a with page size 256 Bytes, erase size 64 KiB, total 16 MiB
In: [email protected]
Out: [email protected]
Err: [email protected]
Net: eth0: [email protected]
Hit any key to stop autoboot: 0
If you hit any key on the serial console before the number of seconds defined by the U-Boot bootdelay variable has elapsed, you will enter the U-Boot interactive command monitor. From the command monitor you can run U‑Boot commands to examine memory, load an image from Ethernet, boot Linux from a loaded image or perform any other action supported by U-Boot.
U-Boot makes use of the so-called environment variables to define various aspects of the target functionality. On the NXP i.MX RT1170 EVK board, the U-Boot environment is stored in the QPSI Flash (there is a special region allocate by U-Boot at offset 0x50000 of the QSPI Flash to store the environment) and is persistent across power or reset cycles. Parameters defined by the U-Boot environment variables include: target IP address, target MAC address, location in RAM where a Linux bootable image will be loaded, and many others.
To manipulate the U-Boot environment the following commands are used:
- printenv <var> - print the value of the variable <var>. Without arguments, prints all environment variables:
=> printenv
addip=setenv bootargs ${bootargs}
ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:eth0:off
baudrate=115200
bootargs=console=ttyLP0,115200 consoleblank=0 ignore_loglevel
bootcmd=run sfboot
bootdelay=0
ethaddr=aa:bb:cc:dd:ee:f0
ethprime=FEC
fdt_addr_r=0x81000000
image=rootfs.uImage
image_sf_addr=0x30080000
ini=mxrt117x-evk.ini
ipaddr=172.17.44.111
kernel_sf_offset=0x80000
kernel_sf_size=0xa00000
loadaddr=0x80007fc0
netboot=tftp ${tftpdir}${image} && run addip; bootm ${loadaddr}
netmask=255.255.0.0
serverip=172.17.0.1
sf_kernel_update=tftp ${tftpdir}${image} && sf erase ${kernel_sf_offset} ${kernel_sf_size} && sf write ${loadaddr} ${kernel_sf_offset} ${filesize}
sf_uboot_update=tftp ${tftpdir}${uboot} && sf erase ${uboot_sf_offset} ${uboot_sf_size} && sf write ${loadaddr} ${uboot_sf_offset} ${filesize}
sfboot=run addip && bootm ${image_sf_addr}
tftpdir=imxrt117x/
uboot=u-boot.flexspi
uboot_sf_offset=0x0
uboot_sf_size=0x50000
Environment size: 1001/65531 bytes
=>
- setenv <var><val> - set the variable <var> to the value <val>:
=> setenv image my.rootfs.uImage
=>
- saveenv - save the up-to-date U-Boot environment, possibly updated using setenv commands, into the QSPI Flash. Running saveenv makes sure that any updates you have made to the U-Boot environment are persistent across power cycles and resets.
=> saveenv
Saving Environment to SPI Flash...
SF: Detected is25wp128a with page size 256 Bytes, erase size 64 KiB, total 16 MiB
Erasing SPI flash...Writing to SPI flash...done
Valid environment: 2
=>