Building and Booting Linux on the SCU200 MicroBlaze V Platform

Overview

The SCU200 platform runs Linux on a MicroBlaze V processor, the AMD RISC-V soft processor implemented in AMD programmable logic. AMD EDF v26.06.1 supports two board revisions, and each one is a separate Yocto machine in the same BSP layer. This page covers both:

  • mbv64-scu200-sdt – the base board revision.

  • mbv64-scu200-revb-sdt – the RevB board revision.

Neither machine is a build-time variant of the other. They have their own machine templates, their own PDI, their own DDR map, and their own deploy directory, and they share no artifacts.

Note

mbv64-scu200-revb-sdt places DDR at 0x100000000 instead of 0x80000000, sets RISCV_SBI_FW_TEXT_START to match, and ships its own scu200_revb_base.pdi. None of the base-machine load addresses carry over to RevB; use the values in Load Addresses on RevB.

The machine names follow the naming convention documented in gen-machine-conf Best Practices: mbv64 identifies the processor family, scu200 identifies the board, and the sdt element records that the machine configuration comes from an SDT description of the hardware design rather than from the XSCT / DTG flow. The names carry no load-methodology suffix. The revb element is the board-revision suffix described in the Artifact and Machine Naming Conventions section of Downloads and Release Notes: it is appended only when a hardware revision needs its own machine configuration, so the name without it refers to the default supported revision.

The four-stage boot chain, the JTAG procedure, and the TFTP procedure are the same on both machines. What differs is the machine name, the artifact names derived from it, and every DDR address:

Item

mbv64-scu200-sdt

mbv64-scu200-revb-sdt

PDI

system-dt/scu200_base.pdi

system-dt/scu200_revb_base.pdi

DDR base

0x80000000

0x100000000

RISCV_SBI_FW_TEXT_START

Set to match the 0x80000000 DDR base

Set to match the 0x100000000 DDR base

Deploy directory

tmp/deploy/images/mbv64-scu200-sdt/

tmp/deploy/images/mbv64-scu200-revb-sdt/

Ramdisk artifact

core-image-minimal-mbv64-scu200-sdt.rootfs.cpio.gz.u-boot

core-image-minimal-mbv64-scu200-revb-sdt.rootfs.cpio.gz.u-boot

Machine Configuration

The machine templates that gen-machine-conf consumes live side by side in the EDF BSP layer:

sources/meta-amd-adaptive-socs/meta-amd-adaptive-socs-bsp/conf/machineyaml/mbv64-scu200-sdt.yaml
sources/meta-amd-adaptive-socs/meta-amd-adaptive-socs-bsp/conf/machineyaml/mbv64-scu200-revb-sdt.yaml

Boot Sequence

The boot flow starts with U-Boot SPL running from BRAM in the programmable logic. The SPL loads U-Boot from flash, and U-Boot then loads the operating system from flash and boots it.

RISC-V defines several privilege modes. Two of them matter here: Machine mode and Supervisor mode. An RTOS typically runs in Machine mode, while Linux requires Supervisor mode, so the boot chain needs a component that switches the processor from Machine mode to Supervisor mode. OpenSBI provides that switch on RISC-V and serves a role similar to TF-A on Arm.

The boot chain has four stages, and both mbv64-scu200-sdt and mbv64-scu200-revb-sdt run the same one. Only the addresses the stages are loaded at differ:

Stage

Privilege Level

Role

U-Boot SPL

Machine mode

First software stage. Runs out of BRAM in the programmable logic and loads the next stages from flash, or from the FIT image the debugger places in DDR during a JTAG boot.

OpenSBI

Machine mode

Machine-mode initialization and the SBI runtime. Hands off to U-Boot in Supervisor mode.

U-Boot

Supervisor mode

Boot loader proper. Loads the kernel and boots Linux.

Linux

Supervisor mode

Calls back into OpenSBI through the SBI interface for the lifetime of the system.

Building the Yocto BSP

Set up the build environment first. The steps are the same as for every other EDF machine: fetch the layers with repo, source the environment script, and point the build at your local download and shared-state caches. See Setting Up the Yocto Environment. Neither SCU200 machine needs a setup step beyond that page.

Both machines are built with the reduced-footprint EDF distribution, amd-edf-small, described in amd-edf-small.

Then select the distro and the machine on the bitbake command line. For the base board:

$ DISTRO=amd-edf-small MACHINE=mbv64-scu200-sdt bitbake sdt-artifacts core-image-minimal

For RevB:

$ DISTRO=amd-edf-small MACHINE=mbv64-scu200-revb-sdt bitbake sdt-artifacts core-image-minimal

Alternatively, set both variables in conf/local.conf of the build directory to make the selection persistent across invocations:

DISTRO = "amd-edf-small"
MACHINE = "mbv64-scu200-revb-sdt"

The build writes the boot artifacts consumed by the JTAG procedure below to the machine-specific deploy directory:

tmp/deploy/images/mbv64-scu200-sdt/
tmp/deploy/images/mbv64-scu200-revb-sdt/

The JTAG boot needs three artifacts from the deploy directory of the machine that was built:

  • system-dt/scu200_base.pdi, or system-dt/scu200_revb_base.pdi on RevB – the PDI holding the MicroBlaze V design. The machine configuration pins the file name through PDI_PATH, and the sdt-artifacts recipe deploys the SDT bundle that contains it into the system-dt/ subdirectory of the deploy directory.

  • u-boot-spl.bin – the BRAM first stage.

  • u-boot.itb – the U-Boot FIT image carrying OpenSBI and U-Boot.

The kernel Image and the .cpio.gz.u-boot ramdisk used by the TFTP procedure are written to the same directory.

Note

The build also deploys the U-Boot artifacts under names carrying the machine name – for RevB, u-boot-fitImage-mbv64-scu200-revb-sdt.itb and u-boot-spl.bin-mbv64-scu200-revb-sdt. The short names above are symlinks to the current build, so either name can be passed to dow.

Booting the Board Over JTAG

JTAG boot loads the hardware design and the boot artifacts straight from the build host into the target, so no flash device has to be programmed. This makes it the practical choice during bring-up and while iterating on a build.

The procedure below is written for mbv64-scu200-sdt and uses the base-machine PDI and load addresses. On RevB the steps are the same, but the PDI, the artifact names, and every DDR address change – see Load Addresses on RevB.

  1. Connect the JTAG cable between the build host and the board, and attach a terminal to the board serial console so that the boot output is visible.

  2. Start XSDB and connect to the hardware server:

    $ xsdb
    xsdb% connect
    
  3. Configure the programmable logic with the PDI that contains the MicroBlaze V design. Until the design is loaded, the target has no processor for the debugger to attach to.

    xsdb% dev p system-dt/scu200_base.pdi
    

    dev p is the abbreviated form of device program. The path is relative to the deploy directory listed above.

  4. Select the MicroBlaze V core. It appears in the target list as Hart #0, a child of the RISC-V at USER2 node:

    xsdb% targets -set -nocase -filter {name =~ "Hart #0" && parent =~ "*USER2*"}
    

    The parent term is required: Hart #0 is not unique in the target tree, so a filter on name alone can select a different hart. Matching the parent against *USER2* pins the selection to the MicroBlaze V core in the programmable logic, and -nocase makes the match case-insensitive.

    Both nodes appear in the targets listing only after the PDI has been programmed, so on a target that still holds no design the filter matches nothing. Re-run targets (abbreviated ta) after dev p to refresh the listing; the core can also be selected by the target number targets prints for it.

  5. Download the U-Boot FIT image to its load address in DDR, then the SPL binary to BRAM at 0x0:

    xsdb% dow -data u-boot.itb 0x80200000
    xsdb% dow -data u-boot-spl.bin 0x0
    

    Load the FIT image first: the SPL starts looking for it as soon as the core runs.

  6. Release the core:

    xsdb% con
    

The console then shows the U-Boot SPL output, the OpenSBI banner, and finally the mbv64> U-Boot prompt. From that prompt, load the kernel and the root filesystem as described below.

Load Addresses on RevB

RevB maps DDR at 0x100000000, so none of the base-machine addresses work on RevB. The RevB addresses keep the same offsets from the DDR base:

Load Address

mbv64-scu200-sdt

mbv64-scu200-revb-sdt

DDR base

0x80000000

0x100000000

U-Boot FIT image

0x80200000

0x100200000

Kernel Image

0x90000000

0x110000000

Ramdisk

0x92e00000

0x112e00000

RISCV_SBI_FW_TEXT_START in the RevB machine template records where OpenSBI links and runs, and it anchors the FIT image load address in the table above. At the U-Boot prompt, bdinfo reports the DDR start address and size on the running board.

With those values, the XSDB sequence is the one given above, with the RevB PDI, the RevB artifact names, and the RevB addresses substituted:

xsdb% dev p system-dt/scu200_revb_base.pdi
xsdb% targets -set -nocase -filter {name =~ "Hart #0" && parent =~ "*USER2*"}
xsdb% dow -data u-boot-fitImage-mbv64-scu200-revb-sdt.itb 0x100200000
xsdb% dow -data u-boot-spl.bin-mbv64-scu200-revb-sdt 0x0
xsdb% con

Note

Loading a RevB build onto the base board, or a base-machine build onto a RevB board, gives no console output at all: the SPL looks for the FIT image at an address the board does not implement. Confirm the deploy directory in the file paths before blaming the cable or the design.

Loading Linux and the Root Filesystem Over TFTP

The JTAG procedure stops at the U-Boot prompt; it brings up no kernel on its own. During bring-up, the quickest way to get from that prompt into Linux is to pull the kernel and a ramdisk root filesystem from the build host over TFTP and boot them out of DDR, so no flash device has to be programmed.

Copy the two artifacts from the deploy directory of the machine that was built into the serve directory of a TFTP server reachable from the board:

  • Image – the RISC-V kernel image.

  • core-image-minimal-mbv64-scu200-sdt.rootfs.cpio.gz.u-boot, or core-image-minimal-mbv64-scu200-revb-sdt.rootfs.cpio.gz.u-boot on RevB – the ramdisk root filesystem with a U-Boot header. The build also writes a build-stamped copy of this file next to it; the unversioned name above is a symlink to the current build.

Then, at the U-Boot prompt, bring up the network interface, transfer both files into DDR, and boot. The transfer below is from a base-board session:

mbv64> dhcp
DHCP client bound to address 192.0.2.11 (1012 ms)
mbv64> tftpboot 0x90000000 Image
Using ethernet@40c00000 device
TFTP from server 192.0.2.1; our IP address is 192.0.2.11
Filename 'Image'.
Load address: 0x90000000
Loading: ##################################################  28.4 MiB
         783.2 KiB/s
done
Bytes transferred = 29765120 (1c62e00 hex)
mbv64> tftpboot 0x92e00000 core-image-minimal-mbv64-scu200-sdt.rootfs.cpio.gz.u-boot
Using ethernet@40c00000 device
TFTP from server 192.0.2.1; our IP address is 192.0.2.11
Filename 'core-image-minimal-mbv64-scu200-sdt.rootfs.cpio.gz.u-boot'.
Load address: 0x92e00000
Loading: ##################################################  44 MiB
         784.2 KiB/s
done
Bytes transferred = 46188810 (2c0c90a hex)
mbv64> booti 0x90000000 0x92e00000 $fdtcontroladdr

The three booti arguments are the kernel load address, the ramdisk load address, and the device tree address. $fdtcontroladdr is the address of the control device tree U-Boot is already running with, so no separate device tree has to be transferred.

On RevB the commands are the same, with the RevB ramdisk file name and the RevB DDR window from Load Addresses on RevB:

mbv64> dhcp
mbv64> tftpboot 0x110000000 Image
mbv64> tftpboot 0x112e00000 core-image-minimal-mbv64-scu200-revb-sdt.rootfs.cpio.gz.u-boot
mbv64> booti 0x110000000 0x112e00000 $fdtcontroladdr

Note

The ramdisk load address has to leave room for the kernel: the 0x90000000 / 0x92e00000 pair above leaves a 46 MiB gap, which holds the 28.4 MiB Image shown in the transfer log. The RevB pair, 0x110000000 / 0x112e00000, leaves the same gap. Move the ramdisk address up if the kernel grows past it.

Linux boots from the ramdisk in DDR, so nothing is persisted across a reset. Reload both images after every board reset.