Skip to content

Add Xilinx Zynq-7000 (ZC702) wolfBoot port#770

Draft
dgarske wants to merge 1 commit intowolfSSL:masterfrom
dgarske:zynq7000
Draft

Add Xilinx Zynq-7000 (ZC702) wolfBoot port#770
dgarske wants to merge 1 commit intowolfSSL:masterfrom
dgarske:zynq7000

Conversation

@dgarske
Copy link
Copy Markdown
Member

@dgarske dgarske commented May 2, 2026

Summary

Adds a wolfBoot port for the Xilinx Zynq-7000 SoC (Cortex-A9, ARMv7-A 32-bit),
verified end-to-end on the ZC702 Evaluation Kit. This is a distinct port from
the existing ZynqMP/zynq target -- different CPU architecture (A9 vs A53),
different QSPI controller (XQspiPs vs GQSPI), and different boot model.

The port is FSBL-loaded: Xilinx FSBL (from prebuilt artifacts) brings up DDR,
clocks, and MIO, then hands off to wolfBoot at DDR 0x04000000. wolfBoot
verifies an ECC256/SHA256-signed image staged at DDR 0x10000000 and chain-
loads it.

This PR brings up the JTAG-loaded development path (wolfBoot loaded over
Platform Cable II + xsdb on top of FSBL). Cold-boot from QSPI flash via a
bundled BOOT.BIN, Linux/U-Boot payload handoff, and SD-card boot will
follow in subsequent PRs.

What's included

  • HAL (hal/zynq7000.c, hal/zynq7000.h, hal/zynq7000.ld)
    • XUartPs UART1 driver (115200 8N1, MIO48/49 console).
    • XQspiPs QSPI driver: I/O mode for short command ops (RDID/RDSR/WREN/SE/PP)
      using the TXD1/TXD2/TXD3 auto-start FIFOs, plus Linear/XIP mode for bulk
      reads via the memory-mapped 0xFC000000 window. This split mirrors the
      ZynqMP driver's PIO-vs-SDMA split for CMD17/CMD18.
    • ext_flash_read/write/erase wired to the QSPI driver; hal_flash_*
      no-ops (no internal flash).
    • hal_prepare_boot() cleans+invalidates L1 D-cache and disables MMU/caches
      before chain-load, leaving FSBL's flat mapping intact for handoff.
  • Cortex-A9 startup (src/boot_zynq7000_start.S)
    • Sets VBAR to 0x04000000, initializes per-mode stacks (IRQ/FIQ/ABT/UND/SVC),
      cleans+invalidates L1 D-cache by set/way, enables async aborts, and jumps
      to main. Inherits FSBL's MMU + caches (intentional -- ARMv7-A treats
      no-MMU memory as Strongly-Ordered, which traps unaligned access from the
      C runtime).
  • Build system (arch.mk, Makefile)
    • New CORTEX_A9 toolchain block: -mcpu=cortex-a9 -marm -mfpu=neon-vfpv3 -mfloat-abi=softfp.
    • TARGET=zynq7000 selects A9 + ARM 32-bit objects (boot_arm32.o +
      boot_zynq7000_start.o) and enables WOLFSSL_SP_ARM32_ASM /
      WOLFSSL_ARMASM / WOLFSSL_ARM_ARCH=7.
  • Config (config/examples/zynq7000.config)
    • ECC256 + SHA256, EXT_FLASH=1, NO_XIP=1,
      WOLFBOOT_LOAD_ADDRESS=0x10000000 (above the wolfBoot region so
      update_ram.c's dst > _end invariant holds).
    • 16 MB QSPI A/B layout: BOOT.BIN @ 0x000000, BOOT_A @ 0x100000
      (~6 MB), UPDATE_B @ 0x700000 (~6 MB), SWAP @ 0xD00000 (64 KB).
  • Test app (test-app/app_zynq7000.c, test-app/ARM-zynq7000.ld)
    • Minimal banner + heartbeat over UART1 to validate do_boot() handoff.
  • Tools (tools/scripts/zc702/)
    • jtag_load.tcl -- xsdb script that runs the prebuilt FSBL, stops at
      handoff, then loads wolfboot.elf and starts execution at
      0x04000000.
    • zc702_qspi.bif -- bootgen template bundling FSBL + wolfBoot for the
      cold-boot work in the next PR.
  • Docs (docs/Targets.md)
    • New "Xilinx Zynq-7000 (ZC702)" section: prerequisites
      (source /opt/Xilinx/2025.2/Vitis/settings64.sh, Platform Cable II
      driver install), build, JTAG bring-up flow, partition layout, DDR map,
      real cold-boot UART output, and TEST_EXT_FLASH selftest expected
      output.

Status

  • JTAG-loaded boot end-to-end: UART banner -> header load from QSPI ->
    image staged at DDR 0x10000000 -> ECC256/SHA256 verify -> do_boot ->
    test-app heartbeat.
  • TEST_EXT_FLASH=1 selftest passes: JEDEC 0x20bb18 (Micron N25Q128),
    sector erase + page program + 256-byte linear-mode read-back verifies
    clean.

Not in this PR (planned follow-ups)

  1. FSBL-bundled BOOT.BIN cold-boot from QSPI (no JTAG).
  2. Linux/U-Boot payload with DTB handoff in r2.
  3. Arasan SDHCI v2.0 driver + zc702_sdcard.config.
  4. A/B update path validation (UPDATE_B swap test).

@dgarske dgarske self-assigned this May 2, 2026
Copilot AI review requested due to automatic review settings May 2, 2026 01:53
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds an initial wolfBoot port for Xilinx Zynq-7000 on the ZC702 board, extending the codebase with a new ARMv7-A / Cortex-A9 target that boots via the Xilinx FSBL, verifies images from QSPI, and chain-loads a staged payload from DDR.

Changes:

  • Adds a new zynq7000 target across the HAL, startup code, linker scripts, and build system for FSBL-loaded Cortex-A9 boot.
  • Introduces a Zynq-7000 QSPI/UART HAL, RAM-boot configuration, and a minimal test application for bring-up validation.
  • Documents the target, JTAG workflow, QSPI layout, and adds helper scripts for XSDB/bootgen usage.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tools/scripts/zc702/zc702_qspi.bif Adds a bootgen BIF template for packaging FSBL + wolfBoot into BOOT.BIN.
tools/scripts/zc702/jtag_load.tcl Adds an XSDB script for JTAG bring-up by running FSBL and loading wolfboot.elf into DDR.
test-app/app_zynq7000.c Adds a minimal bare-metal ZC702 test app that prints a boot banner and heartbeat on UART1.
test-app/Makefile Wires the new target into test-app builds with the ARM32 startup object and target linker script.
test-app/ARM-zynq7000.ld Adds the linker script for the staged Zynq-7000 test application in DDR.
src/boot_zynq7000_start.S Adds Zynq-7000-specific ARMv7-A startup, vector setup, stack initialization, and early CPU state handling.
src/boot_arm32.c Adjusts ARM32 inline assembly immediate syntax used during chain-load handoff.
hal/zynq7000.ld Adds the wolfBoot linker script for execution from DDR at the FSBL handoff address.
hal/zynq7000.h Defines Zynq-7000 register maps and bitfields for UART, QSPI, and related peripherals.
hal/zynq7000.c Implements the new Zynq-7000 HAL, including UART, QSPI external flash access, and boot-preparation logic.
docs/Targets.md Documents the new ZC702 target, configuration, memory map, JTAG flow, and expected output.
config/examples/zynq7000.config Adds an example configuration for ECC256/SHA256 RAM-boot from external QSPI flash.
arch.mk Adds target selection and Cortex-A9-specific compiler/object settings for zynq7000.
Makefile Includes the new target in the default main build outputs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread hal/zynq7000.c
Comment on lines +394 to +402
const volatile uint8_t *xip =
(const volatile uint8_t *)(Z7_QSPI_LINEAR_BASE + address);
unsigned int i;
/* Sacrificial read: the first XIP byte after switching to linear
* mode is unreliable while the controller primes its read pipeline.
* Read one byte from the same address and discard it. */
(void)xip[0];
for (i = 0; i < len; i++)
data[i] = xip[i];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants