Introduction
When using U-Boot, the boot procedure, commands, and associated parameters are configured in the U-Boot environment.
The default contents for the U-Boot environments in Zynq-7000 devices is defined this file:
./include/configs/zynq-common.h
In the Zynq-7000 boards which mount a QSPI FLASH memory, as the SPEC7 is, when the U-Boot environment is modified and saved by using the saveenv
command, the resulting values are writen and then recovered at start up to/from a predefined QSPI section.
In this wiki page we will explain the rationale regarding the introduced SPEC7 U-Boot environment modifications from default behavior and how we can easily export and transplant a customized U-Boot environment from one board to other.
Environment location in QSPI
The environment location in QSPI is defined by the following variables:
CONFIG_ENV_IS_IN_SPI_FLASH
CONFIG_ENV_SECT_SIZE
CONFIG_ENV_SIZE
CONFIG_ENV_OFFSET
The meaning for each of them is:
-
CONFIG_ENV_IS_IN_SPI_FLASH
: boolean value that specify if the environment resides in QSPI. -
CONFIG_ENV_SECT_SIZE
: size of the sector containing the environment. -
CONFIG_ENV_SIZE
: specify to use only a part of the flash sector for the environment. This saves memory for the RAM copy of the environment. -
CONFIG_ENV_OFFSET
: Offset of environment data (variable area) to the beginning of flash memory.
Default environment location for Zynq-7000
For the most of Zynq-7000 boards, the resulting U-Boot config file contains the following environment location values:
CONFIG_ENV_IS_IN_SPI_FLASH=y
CONFIG_ENV_SECT_SIZE=0x20000
CONFIG_ENV_SIZE=0x20000
CONFIG_ENV_OFFSET=0xE0000
The CONFIG_ENV_IS_IN_SPI_FLASH
value is defined in the associated defconfig file for each Zynq-7000 board, while the other parameters' default values for ARCH_ZYNQ
are defined at env/Kconfig
:
config ENV_OFFSET
hex "Environment Offset"
depends on !ENV_IS_IN_UBI
depends on !ENV_IS_NOWHERE
default 0x3f8000 if ARCH_ROCKCHIP
default 0x88000 if ARCH_SUNXI
default 0xE0000 if ARCH_ZYNQ
default 0x1E00000 if ARCH_ZYNQMP
default 0x7F40000 if ARCH_VERSAL
help
Offset from the start of the device (or partition)
config ENV_SIZE
hex "Environment Size"
default 0x40000 if ENV_IS_IN_SPI_FLASH && ARCH_ZYNQMP
default 0x20000 if ARCH_SUNXI || ARCH_ZYNQ
default 0x8000 if ARCH_ROCKCHIP || ARCH_ZYNQMP || ARCH_VERSAL
help
Size of the environment storage area
config ENV_SECT_SIZE
hex "Environment Sector-Size"
depends on !ENV_IS_NOWHERE && (ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_VERSAL)
default 0x40000 if ARCH_ZYNQMP || ARCH_VERSAL
default 0x20000 if ARCH_ZYNQ
help
Size of the sector containing the environment.
Saving the environment corrupts the boot image
Sometimes, when the saveenv
command is run in u-boot, the zynq board cannot boot again. This is because the command has saved environment the data to the boot image or other critical contents defined in FLASH.
In particular, for Zynq-7000 boards, the default environment location values are thought for boot images that doesn't include a bitstream to be loaded by the FSBL:
- The
0x20000
size defines a 128 KiB environment - The
0xE0000
offset defines that the enviroment is stored at the end of the first 1 MiB in QSPI. - The maximum size for FSBL is 192 KiB because it resides in the OCM, and that is the max size available (see UG585, page 150).
- The combined FSBL + U-Boot footprint in QSPI must be below 896 KiB.
In this way, as soon as you add a bitstream partition after the FSBL in the boot image, the saved U-Boot environment will be colliding with the bitstream. Indeed, even if you don't add a bitstream partition, if the FSBL + U-Boot combination is too big in size, the U-Boot environment will potentially overwrite the U-Boot binary.
Modified environment location for SPEC7
If the SPEC7 is working in PCIe slave mode, we need to introuduce a gateware to be quickly loaded in the Programmable Logic by the FSBL. In this way, we must move the environment location in QSPI to a location where the potential collisions are avoided.
As the maximum size for the SPEC7 bitstream is about 12,61 MiB, we move the environment to the end of the first 16 MiB in QSPI and keep the other parameters unchanged.
In order to do this, we have added the following variable to the SPEC7 defconfig file:
CONFIG_ENV_OFFSET=0xFE0000
By doing this, the resulting U-Boot config file for SPEC7 contains the following values:
CONFIG_ENV_IS_IN_SPI_FLASH=y
CONFIG_ENV_SECT_SIZE=0x20000
CONFIG_ENV_SIZE=0x20000
CONFIG_ENV_OFFSET=0xFE0000
Managing the environment in QSPI
Once we have fixed the environment location in QSPI for the SPEC7, there are several actions that allow us to configure the environment for our specific purposes and then reuse it in multiple deployed boards.
Edit the QSPI environment
We can modify the environment by using the setenv
and editenv
commands and then sabe it to the QSPI by using saveenv
:
SPEC7> editenv bootcmd
edit: echo Break into command shell
SPEC7> saveenv
Saving Environment to SPI Flash... Erasing SPI flash...Writing to SPI flash...done
OK
Clean the QSPI environment
In order to clean the SPEC7 environment and go back to the default values, we need to activate the FLASH and then erase the QSPI section of size 0x20000
starting at offset 0xFE0000
:
SPEC7> sf probe
SPEC7> sf erase 0xFE0000 0x20000
Content size in the QSPI environment
We can check the used and total size of the environment by reading the report at the end of printenv
command:
SPEC7> printenv
...
Environment size: 8928/131068 bytes
Export the QSPI environment
Once we have modifidied and saved the U-Boot environment to match our needs, we can export the contents into a binary blob that can be later reused in different boards.
First, we activate the FLASH and move the saved u-Boot environment from QSPI to DDR. In the following example, we move the environment QSPI section of size 0x20000
starting at offset 0xFE0000
to the DDR address at 0x100000
:
SPEC7> sf probe 0 0 0
SPEC7> sf read 0x100000 0xFE0000 0x20000
device 0 offset 0xfe0000, size 0x20000
SF: 131072 bytes @ 0xfe0000 Read: OK
Then, we can save the copied environment of size 0x20000
from the DDR address at 0x100000
to an external media, e.g. microSD:
SPEC7> fatwrite mmc 0:1 0x100000 environment.bin 0x20000
131072 bytes written
And check that the file has been saved:
SPEC7> fatls mmc 0:1
131072 environment.bin
1 file(s), 0 dir(s)
NOTE: we are using .bin
extension in order to be able of using this file later in the FLASH programming file if required, as only .bin
and .mcs
extensions are supported (of course, we could simply change the extension by hand).
Import the QSPI environment
Once we have a copy of the desired u-Boot environment in an external file, we can write it to a different SPEC7 board so that the edited values are easily reused.
We can use the JTAG to transfer the saved and exported environment binary blob by:
- Using Vitis Program Flash in a already working board and programming the blob at the proper offset, i.e.
0xFE0000
- Including the binary blob as a boot image data partition located at offset
0xFE0000
Alternatively, we can load the binary blob from USB, SD, TFTP or Kermit to DDR and then copy from DDR to QSPI a block of size 0x20000
at offset 0xFE0000
. As an example, once we have the environment.bin
contents in the DDR, e.g. at address 0x100000
, we can activate the FLASH and write to it by just:
SPEC7> sf probe 0 0 0
SPEC7> sf write 0x100000 0xFE0000 0x20000