← All articles

Bringing up a custom Zynq UltraScale+ board: U-Boot to a login prompt

The ZynqMP boot chain stage by stage, with what each stage prints and what to check when it does not.

IronKernel ·

Zynq UltraScale+ bring-up on a custom board follows the order the chip boots. The ZynqMP boot sequence passes through the CSU BootROM, the first stage boot loader (FSBL), the PMU firmware, Trusted Firmware-A, U-Boot and the Linux kernel before a login prompt appears on the serial console. Bringing the stages up one at a time, in that order, tells you which stage a failure belongs to. This guide walks the stages and what to check at each. It assumes the board already has sound reset, power and clocks; a processor held in reset or running from a bad clock fails every check below in the same way.

The ZynqMP boot sequence

StageWhat it does
CSU BootROMReads the boot mode pins, finds the boot image on the selected device, and loads the next stages
PMU firmwareRuns on the platform management unit and handles power, reset and clock control for the rest of the chip
FSBLInitialises the processing system, including clocks, pins and DDR, loads the FPGA bitstream, then loads TF-A and U-Boot
TF-ATrusted Firmware-A, the secure monitor that stays resident under U-Boot and Linux
U-BootBrings up the console and loads the kernel, device tree and root file system
LinuxProbes drivers, mounts the root file system and starts init, which prints the login prompt

Boot mode pins and BOOT.BIN

Pins on the device select the boot device, such as JTAG, QSPI flash, an SD card or eMMC. Check the strap settings on your board against AMD's documentation for the device, and measure them: a strap in the wrong place sends the BootROM to an empty device.

The boot image, BOOT.BIN, holds the FSBL, the PMU firmware, the bitstream, TF-A and U-Boot. AMD's Bootgen tool builds it from a file that lists each part and the processor it runs on. PetaLinux and the meta-xilinx Yocto layers write that file and run Bootgen for you; the Yocto vs PetaLinux vs Buildroot comparison covers which build to use.

First boot over JTAG

Bring up a new board in JTAG boot mode before anything is in flash. JTAG boot separates two questions: whether the processing system runs, and whether the boot device works. If U-Boot runs over JTAG and not from the boot device, the fault is in the boot device, its pin configuration or the image on it.

The JTAG sequence follows the boot chain: the PMU firmware, then the FSBL, then TF-A, U-Boot and the device tree. The FSBL has to finish initialising DDR before anything can be loaded into it. The AMD tools script this sequence.

If the debugger cannot see the device at all, look at the JTAG chain, the resets and the reference clock before looking at software.

PS DDR configuration from the XSA

The DDR settings come from the processing system configuration in Vivado: memory type, speed, bus width, ECC and the timing parameters of the part. They travel in the exported XSA, and the FSBL built from it applies them. A wrong value shows up as a boot that stops during processing system initialisation, or as a board that boots and then crashes or corrupts data once code runs from DDR.

Compare every DDR setting in Vivado with the memory data sheet and the schematic, then run a memory test before trusting the memory. Rebuild the FSBL every time the XSA changes, or the board runs the old settings.

Serial console

The console is one of the processing system UARTs, on the pins chosen in Vivado. The FSBL, TF-A, U-Boot and Linux each write to the console as they start, so the last output before a stop marks the stage that failed. If nothing appears, check the boot mode pins, the boot image on the boot device, and the UART pins and baud rate.

Device tree for a custom ZynqMP board

The device tree generated from the XSA describes what Vivado knows: which processing system peripherals are enabled and the IP in the programmable logic. It does not know what else is on the board. That goes in a hand-written device tree file:

  • Ethernet PHY addresses and interface modes.
  • I2C devices and multiplexers, and flash partitions.
  • SD card detect, write protect and signalling voltage.

Start from the device tree of the AMD evaluation board closest to your design, and change only what your schematic changes. U-Boot needs a device tree too. If U-Boot and Linux use different trees, a peripheral that works in U-Boot can still fail in Linux.

From U-Boot to a login prompt

U-Boot loads the kernel, the device tree and a root file system or ramdisk, and starts the kernel with a command line that names the console and the root device. The kernel mounts the root file system, and init starts a login on the console. The usual failures at this stage:

  • Output stops as the kernel starts: the console named on the kernel command line or in the device tree is the wrong UART, or the kernel and device tree were loaded on top of each other.
  • The kernel cannot mount the root file system: the wrong root device, a storage driver or file system missing from the kernel, or a partition that was never written.
  • The kernel boots and no login prompt appears: init starts the login on a different terminal from the console.

With a login prompt on the UART, the remaining bring-up items are the peripherals: Ethernet passing traffic, then storage, then the logic in the programmable fabric. Our board bring-up package covers this boot chain on Zynq UltraScale+ and the other AMD SoCs, ending with UART and Ethernet working.

Further reading

Bringing up a Zynq UltraScale+ board?

Our Bring-Up-Blitz package gets bootloader, kernel, UART and Ethernet running on your board, at a fixed price.