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 |
|---|---|---|
|
|
|
DDR base |
|
|
|
Set to match the |
Set to match the |
Deploy directory |
|
|
Ramdisk artifact |
|
|
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, orsystem-dt/scu200_revb_base.pdion RevB – the PDI holding the MicroBlaze V design. The machine configuration pins the file name throughPDI_PATH, and thesdt-artifactsrecipe deploys the SDT bundle that contains it into thesystem-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.
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.
Start XSDB and connect to the hardware server:
$ xsdb xsdb% connect
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.pdidev pis the abbreviated form ofdevice program. The path is relative to the deploy directory listed above.Select the MicroBlaze V core. It appears in the target list as
Hart #0, a child of theRISC-V at USER2node:xsdb% targets -set -nocase -filter {name =~ "Hart #0" && parent =~ "*USER2*"}The
parentterm is required:Hart #0is not unique in the target tree, so a filter onnamealone can select a different hart. Matching the parent against*USER2*pins the selection to the MicroBlaze V core in the programmable logic, and-nocasemakes the match case-insensitive.Both nodes appear in the
targetslisting only after the PDI has been programmed, so on a target that still holds no design the filter matches nothing. Re-runtargets(abbreviatedta) afterdev pto refresh the listing; the core can also be selected by the target numbertargetsprints for it.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.
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 |
|
|
U-Boot FIT image |
|
|
Kernel |
|
|
Ramdisk |
|
|
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
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, orcore-image-minimal-mbv64-scu200-revb-sdt.rootfs.cpio.gz.u-booton 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.