OSPI and SD Card Boot Flow - Detailed Reference#

Detailed procedures, advanced usage, options, error handling, and verification steps for the OSPI and SD card boot flow. For a quick reference, see OSPI and SD Card Boot Flow.

Section 1: OSPI Programming#

Purpose: Automated OSPI Flash Programming

../../_images/ospi_section1.png

Note

Vivado Lab Edition is a lite version of Vivado and is sufficient to support hardware download operations.

Step 1: Validate Configuration (Dry Run)#

Before flashing the hardware, validate the configuration:

cd <path to versal_2ve/tools/ospi_sd_flash/>

./vek385-flash-ospi.exp \
  --vivado-dir <path to Vivado Lab 2025.2> \
  --boot-images /path/to/boot_images \
  --dry-run

The dry run validates:

  • Vivado Lab Edition installation path and settings64.sh availability

  • Boot images directory structure

  • OSPI image auto-detection

  • Serial port auto-detection (matches ID_MODEL=VEK385)

  • Serial port availability (not locked by minicom/screen)

Example output of the OSPI flash dry run:

  [INFO]  Auto-detected OSPI image: edf-ospi-versal2-vek385-sdt-full.bin
  [INFO]  OSPI image size: 0x4D0000 (4.8 MB)
  [INFO]  Auto-detected serial port: /dev/ttyUSB1

========================================================================
  VEK385 OSPI Flash Tool
  Automates UG1787 (Board Setup)
========================================================================

  Vivado:       <path to Vivado Lab 2025.2>
  Boot images:  <path to boot_images>
  BOOT.bin:     BOOT.bin
  OSPI image:   edf-ospi-versal2-vek385-sdt-full.bin
  Image size:   0x4D0000 (4.8 MB)
  Serial port:  /dev/ttyUSB1
  XSDB port:    3121
  Log file:     <path>/vek385-flash-ospi_<timestamp>.log
  Mode:         DRY RUN (no hardware operations)

========================================================================
  Dry run complete -- all paths and settings validated
========================================================================

  All prerequisites satisfied. Re-run without --dry-run to flash.

Note

The script automatically detects the serial port using udevadm by matching VEK385 USB interface 01. Override with --serial-port /dev/ttyUSBX if needed.

Step 2: Flash OSPI#

After validating the configuration, flash the OSPI:

./vek385-flash-ospi.exp \
  --vivado-dir <path to Vivado Lab 2025.2> \
  --boot-images /path/to/boot_images

Note

Alternatively, set the VIVADO_INSTALL_DIR environment variable:

export VIVADO_INSTALL_DIR=<path to Vivado Lab 2025.2>
./vek385-flash-ospi.exp --boot-images /path/to/boot_images

Example output after the OSPI flash completes successfully:

========================================================================
  OSPI programming complete!
========================================================================

  Log file: <path>/vek385-flash-ospi_<timestamp>.log

  Next steps:
    1. Prepare the SD card (Section 2) using vek385-flash-sdcard.sh
    2. Power OFF the board
    3. Set SW1 DIP switch to OSPI mode (0001 = ON, ON, ON, OFF)
    4. Power ON the board

What the Script Does#

The script performs the following operations:

  1. Opens serial port (auto-detected at 115200, 8N1)

  2. Launches XSDB through Vivado Lab Edition settings64.sh

  3. Connects to board via JTAG (connect, target -set)

  4. Resets device (dev reset – ensures clean state)

  5. Downloads bootloader to DDR via JTAG (dev p BOOT.bin)

  6. Waits for U-Boot prompt on serial console (versal2> or =>)

  7. Downloads OSPI image to DDR at address 0x20000000 (dow -data)

  8. Initializes SPI flash controller (sf probe 0 0 0)

  9. Erases OSPI flash with progress indicator (sf erase – displays ‘.’ every 5 seconds, ~2-5 minutes)

  10. Writes OSPI flash from DDR with size-aware operation (only writes actual file size, not full 256MB – significantly faster for smaller images)

  11. Verifies completion (checks for “Erased: OK” and “Written: OK” in U-Boot output)

  12. Cleans up XSDB and serial connections

Note

The script manages two independent communication channels:

  • XSDB (JTAG): Downloads files into board DDR memory

  • Serial console: Accesses U-Boot to execute flash commands

Both channels are orchestrated by the same expect process, eliminating the need for manually switching between terminal windows.

Error Handling#

The script includes comprehensive error detection:

A timestamped log file is created in the current directory: vek385-flash-ospi_<timestamp>.log

Step 3: Switch to OSPI Boot Mode#

After OSPI programming completes successfully:

  1. Power OFF the board

  2. Set SW1 DIP switch to OSPI boot mode (0001 = ON, ON, ON, OFF)

  3. Power ON the board

The board now boots independently from OSPI flash – JTAG is no longer required.

Section 2: SD Card Setup#

Purpose: Automated SD Card Preparation

../../_images/ospi_section2.png

Prerequisites#

  • SD card (minimum 32GB) inserted into host machine card reader

  • SD card physically removed from the VEK385 board

  • Scripts directory with automation tools

Note

The SD card script must be run as root (sudo) because it writes directly to block devices.

Step 1: Validate Configuration (Dry Run)#

Before writing to the SD card, validate the configuration:

cd <path to versal_2ve/tools/ospi_sd_flash/>

sudo ./vek385-flash-sdcard.sh \
  --boot-images /path/to/boot_images \
  --dry-run

The dry run validates:

  • Running as root (sudo)

  • Boot images directory structure

  • Root filesystem image auto-detection (*.wic.xz)

  • Block map file auto-detection (*.wic.bmap)

  • bmaptool installation

Example output of the SD card flash dry run:

========================================================================
  VEK385 SD Card Flash Tool
  Automates UG1787 (SD Card Setup)
========================================================================

  Boot images:   <path to boot_images>
  Rootfs image:  rootfs.wic.xz
  Bmap file:     rootfs.wic.bmap (found)
  SD device:     /dev/sdb
  Device size:   59GB
  Device model:  Micro SD
  Log file:      <path>/vek385-flash-sdcard_<timestamp>.log
  Mode:          DRY RUN (no hardware operations)

    NAME    MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
    sdb       8:16   1 59.6G  0 disk
    |-sdb1    8:17   1    1G  0 part
    |-sdb2    8:18   1    1G  0 part
    `-sdb3    8:19   1 57.4G  0 part

========================================================================
  Dry run complete -- all paths and settings validated
========================================================================

  All prerequisites satisfied. Re-run without --dry-run to flash.

Step 2: Flash SD Card#

Flash the root filesystem and copy all overlays:

sudo ./vek385-flash-sdcard.sh \
  --boot-images /path/to/boot_images

The script will:

  1. Auto-detect SD card (USB readers, built-in slots, mmcblk devices)

  2. Display device information (size, model, partitions)

  3. Request user confirmation before destructive operation

  4. Perform safety checks (size < 128GB, not mounted as /)

  5. Unmount existing partitions and kill holding processes

  6. Flash root filesystem using bmaptool (sparse write, ~2-3 minutes)

  7. Mount rootfs partition

  8. Copy overlay files from boot_images (PL/AIE configuration)

  9. Install setup scripts (setup_overlay.sh, runtime_env.sh)

  10. Install systemd service and create enable symlink

  11. Extract environment variables to /etc/profile.d/vek385-runtime.sh

  12. Sync, unmount, eject

Note

Override auto-detection with --sd-device /dev/sdX if multiple candidates are found.

Example output after the SD card flash completes successfully:

========================================================================
  Finalizing SD card
========================================================================
  [INFO]  Syncing...
  [INFO]  Unmounting /mnt/vek385-sd...
  [INFO]  Ejecting /dev/sdb...
  [INFO]  SD card ejected.

========================================================================
  SD card is ready!
========================================================================

  Log file: <path>/vek385-flash-sdcard_<timestamp>.log

  Next steps:
    1. Insert the SD card into the VEK385 board
    2. Ensure SW1 DIP is set to OSPI mode (0001 = ON, ON, ON, OFF)
    3. Power on the board

Optional: Copy Compiled Models#

To copy pre-compiled AI/ML models to the SD card:

sudo ./vek385-flash-sdcard.sh \
  --boot-images /path/to/boot_images \
  --models-dir /path/to/compiled_models

Models are copied to /home/models/ on the rootfs partition.

Note

Before the first boot, the rootfs partition on the SD card has only about 3.1 GB of free space available. Attempting to copy models larger than 3.1 GB at this stage fails with a “no space left on device” error.

On the first boot, the rootfs auto-resize service expands the partition to consume the full SD card capacity. It is therefore recommended to copy compiled models to the SD card after the first boot, once the rootfs has been expanded.

What the Script Does#

The script performs the following operations:

Resulting SD Card Partition Layout#

After flashing, the SD card contains:

/dev/sdc1    1 GB   FAT32   /efi          # EFI boot partition (kernel, bootloader)
/dev/sdc2    1 GB   ext4    /root/storage # Storage partition
/dev/sdc3    6 GB   ext4    /             # Root filesystem (expands on first boot)

Note

The actual partition device names (for example, /dev/sdc1, /dev/sdb1, /dev/mmcblk0p1) and partition sizes you see might differ depending on your host system, the SD card device assignment, and the SD card capacity. The layout shown above is representative; verify the device name on your system before performing any operations on the SD card.

Rootfs Contents:
/overlay/
  setup_overlay.sh                        # Installed by SD flash script
  runtime_env.sh                          # Installed by SD flash script
  x_plus_ml.pdi                           # Copied from boot_images/overlay/
  x_plus_ml.dtbo                          # Copied from boot_images/overlay/
  image_processing.cfg                    # Copied from boot_images/overlay/
  x_plus_ml.xclbin                        # Copied from boot_images/overlay/

/etc/ufs_config/
  configure_ufs.sh                        # UFS configuration script (optional)
  ufsconfig_64gb                          # UFS 64GB configuration descriptor

/etc/systemd/system/
  vek385-setup.service                    # Installed by SD flash script

/etc/systemd/system/multi-user.target.wants/
  vek385-setup.service -> ...             # Enable symlink (auto-runs on boot)

/etc/profile.d/
  vek385-runtime.sh                       # Environment variables (auto-sourced on login)

/home/models/                             # Optional: compiled AI models
  <model_cache_directories>

Special Options#

Skip Re-Flash (Update Only)

If the SD card is already flashed and you only need to update overlays or models:

sudo ./vek385-flash-sdcard.sh \
  --boot-images /path/to/boot_images \
  --skip-flash

This skips the bmaptool operation and jumps directly to mounting and copying files (much faster).

Non-Interactive Mode

For automated/scripted workflows, skip all confirmation prompts:

sudo ./vek385-flash-sdcard.sh \
  --boot-images /path/to/boot_images \
  --yes

Error Handling#

Scenario

Behavior

Not running as root

Exits immediately with sudo hint

bmaptool not installed

Exits with apt install hint

Device > 128GB

Refuses to flash (safety check)

Device mounted as /

Refuses to flash (system disk protection)

User declines confirmation

Exits gracefully

bmaptool copy fails

Exits with error code and log reference

No ext4 partition found

Warning, falls back to last partition

Mount fails

Exits with error message

Device busy during eject

Warning with manual removal instructions

Ctrl-C during execution

Cleanup trap unmounts and removes mount point

A timestamped log file is created in the current directory: vek385-flash-sdcard_<timestamp>.log

Section 3: Board Boot#

Purpose: Automatic System Configuration

../../_images/ospi_section3.png

Step 1: Boot the Board#

  1. Insert the prepared SD card into the VEK385 board

  2. Verify SW1 DIP switch is set to OSPI mode (0001 = ON, ON, ON, OFF)

  3. Power ON the board

The board boots from OSPI (bootloader) and SD card (root filesystem).

Note

The automated setup requires no manual intervention after boot. The systemd service vek385-setup.service runs automatically during boot sequence and consolidates overlay programming, runtime environment setup, and optional UFS flash enablement.

Important

Optional UFS Flash Support: VEK385 boards include UFS (Universal Flash Storage) that ships in a disabled state. The vek385-setup.service includes an optional UFS enablement step that, on first boot, configures the UFS device with 64GB capacity and requires a reboot to activate. On subsequent boots, the service detects that UFS is already enabled and skips reconfiguration. If you do not need UFS, ignore the reboot notice and continue using the SD Card boot flow.

For background on UFS and the workflows it enables (booting from UFS, programming UFS via the System Boot Image Recovery Tool), see OSPI + UFS Boot Flow.

Step 2: Verify Configuration#

After logging in, verify the automatic configuration succeeded:

Check Service Status#

systemctl status vek385-setup.service

Expected output:

● vek385-setup.service - VEK385 board setup (overlay, runtime, UFS)
     Loaded: loaded (/etc/systemd/system/vek385-setup.service; enabled; preset: enabled)
     Active: active (exited) since Fri 2026-05-01 00:03:45 UTC; 1min ago
    Process: 683 ExecStart=/overlay/setup_overlay.sh (code=exited, status=0/SUCCESS)
    Process: 749 ExecStart=/overlay/runtime_env.sh (code=exited, status=0/SUCCESS)
    Process: 759 ExecStart=/etc/ufs_config/configure_ufs.sh (code=exited, status=0/SUCCESS)
   Main PID: 759 (code=exited, status=0/SUCCESS)

Verify Kernel Module#

The amdxdna kernel module is loaded automatically by the system. Verify it is loaded:

lsmod | grep amdxdna

Expected output:

amdxdna               123456  0

Note

The module loading is handled automatically by the Linux system (via udev rules or kernel auto-loading), not by the runtime_env.sh script.

Verify Environment Variables#

echo $LD_LIBRARY_PATH

Expected output:

/usr/lib/python3.12/site-packages/onnxruntime/capi/:/usr/lib/python3.12/site-packages/flexmlrt/lib/:/usr/lib/python3.12/site-packages/voe/lib/
true
1

Manual Re-run (If Needed)#

If the service fails or the overlay needs re-programming:

# Re-run via systemd
sudo systemctl restart vek385-setup.service

# Or run scripts directly
cd /overlay
sudo ./setup_overlay.sh
source ./runtime_env.sh

# Re-run UFS configuration (if needed)
sudo /etc/ufs_config/configure_ufs.sh

Note

When running runtime_env.sh manually, source is required to set environment variables in your current shell. When systemd runs it on boot, environment variables are installed to /etc/profile.d/vek385-runtime.sh and apply to all user login shells automatically.

Troubleshooting#

OSPI Flash Issues#

Symptom

Resolution

“Serial port locked” error

Kill minicom/screen: fuser -k /dev/ttyUSB1

“No targets found” (XSDB)

Check USB cable, verify SW1=JTAG (0000)

U-Boot prompt timeout

Check DIP switch, verify board powered on

“sf probe” fails

Hardware issue – flash not detected by U-Boot

“sf erase” timeout

256MB erase takes 2-5 minutes – wait longer

OSPI flash script hangs

Press Ctrl-C, check log file for details

SD Card Flash Issues#

Symptom

Resolution

“Not running as root” error

Prefix command with sudo

Multiple SD cards detected

Script shows numbered list – choose correct one

“Device is too large” (>128GB)

Verify correct device – SD cards are <128GB

“Device busy” during flash

Script runs fuser -k automatically

bmaptool fails

Check log file, verify .bmap file exists

SD card won’t eject

Manual removal safe after sync completes

Boot Configuration Issues#

Additional Options#

Logging#

Both scripts create timestamped log files in the current directory:

vek385-flash-ospi_20260418_143022.log
vek385-flash-sdcard_20260418_144530.log

Override log file path:

./vek385-flash-ospi.exp --boot-images /path --log-file /tmp/ospi.log
sudo ./vek385-flash-sdcard.sh --boot-images /path --log-file /tmp/sd.log

Advanced OSPI Options#

# Override auto-detected serial port
./vek385-flash-ospi.exp \
  --vivado-dir <path to Vivado Lab 2025.2> \
  --boot-images /path/to/boot_images \
  --serial-port /dev/ttyUSB3

# Use custom OSPI image filename
./vek385-flash-ospi.exp \
  --vivado-dir <path to Vivado Lab 2025.2> \
  --boot-images /path/to/boot_images \
  --ospi-image custom-ospi-image.bin

Advanced SD Card Options#

# Explicit device selection
sudo ./vek385-flash-sdcard.sh \
  --boot-images /path/to/boot_images \
  --sd-device /dev/sdc

# Custom rootfs image
sudo ./vek385-flash-sdcard.sh \
  --boot-images /path/to/boot_images \
  --rootfs-image custom-rootfs.wic.xz

Summary#

The scripts cover the complete board bring-up flow. For users who need to troubleshoot or understand the underlying process, the equivalent step-by-step manual procedure is documented in the appendix: OSPI and SD Card Boot Flow - Manual Steps Reference.

UFS flash activation is optional and not needed for standard AI/ML inference workflows. It is only required if you plan to use the Image Recovery Tool or need additional persistent storage. For details, see OSPI + UFS Boot Flow.