Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ARM FVP (FVP_BaseR_AEMv8R)

Run nano-ros on Arm’s Base_RevC AEMv8-R Fast Models — the Cortex-A SMP profile under Zephyr 3.7 (board id fvp_baser_aemv8r/fvp_aemv8r_aarch64/smp). The FVP is the canonical local proxy for the safety-island reference platforms that follow the same hwv2 Zephyr shape; pair this chapter with the Zephyr (west module) starter for the build half.

Status. The run half — invoking FVP_BaseR_AEMv8R and piping UART 0–3 to stdout — is landed.

The two standalone talker lanes were retired: their runners had been deleted, so they built images nothing booted. What remains is the part with consumers — the board-crate import surface and the workspace Entry. FVP support is intended to grow back from those. See the archived FVP runtime roadmap.

Verified where? The run half is maintainer-run: a maintainer boots the image by hand (the recipe is in the contributor lanes linked below), and no installed probe track replays this chapter. fvp-aemv8r-smp’s status and the date of its last boot are on its evidence page; a probe track follows an automated run, not the other way round. Read the output below as what a maintainer last saw, not as a gate.

When to use

  • You need to exercise a Cortex-A SMP Zephyr image on a developer laptop without dedicated silicon.
  • You’re bringing up a new hwv2 safety-island target — the FVP is the closest in-tree reference for board.cmake + SMP boot + Cyclone DDS shape.
  • You’re validating stock-Cyclone-DDS RMW interop locally before promoting to a hardware bench.

The FVP is not a replacement for QEMU on Cortex-M (mps2-an385, mps3-an547); those targets are covered by FreeRTOS (QEMU) and the Zephyr starter. The FVP is also not the same surface as Corellium’s AVH cloud FVP — AVH packages firmware as .coreimg and provisions via a remote API; local FVP loads a raw ELF via -a cluster0.cpu*=<elf>. AVH is out of scope for this chapter.

Prereqs

  • A working Zephyr 3.7 workspace — run nros setup zephyr once if you haven’t (see the Zephyr starter).

  • The Arm Base_RevC AEMv8R Fast Models binary. nano-ros fetches it:

    nros setup --tool arm-fvp
    

    nros setup board fvp-aemv8r-smp does it as one of its steps, so most people never run the line above directly. It is a pinned Arm CDN permalink with a checked SHA256 ([tool.arm-fvp] in nros-sdk-index.toml), installed to ~/.nros/sdk/arm-fvp/<version>.

    x86_64 Linux only — Arm publishes no other host build of this model. On another architecture you can still build the image; you cannot run it here.

    Until 2026-09-06 this page said the model was license-gated and that fetching it was your responsibility. It is not: the permalink answers 200 with no authentication, which is how autoware-safety-island had been downloading it in CI the whole time. The mistaken policy cost every reader of this page a manual install.

After installing, export one of the discovery env vars:

# Preferred — Zephyr's canonical name; takes highest priority.
export ARMFVP_BIN_PATH=/opt/Arm/FastModels/Base_RevC_AEMv8R/models/Linux64_GCC-9.3

# Alternative — directory layout from the gated installer; the
# resolver scans `models/Linux64_GCC-*/` underneath it.
export ARM_FVP_DIR=/opt/Arm/FastModels/Base_RevC_AEMv8R

If neither is set, FVP_BaseR_AEMv8R is discovered via PATH as a last-ditch fallback.

Installer surface

For a model you extracted yourself, rather than the one nros setup --tool arm-fvp fetched, run the discovery script:

ARM_FVP_DIR=/path/to/extracted/fvp \
    scripts/installers/arm-fvp-installer.sh

The installer locates FVP_BaseR_AEMv8R under $ARM_FVP_DIR, symlinks the containing directory to ~/.nros/sdks/arm-fvp/current/ (atomic via ln -sfn), and prints the export ARMFVP_BIN_PATH=… line for your shell rc. Run scripts/installers/arm-fvp-installer.sh --print-env later to re-emit the export. It downloads nothing: nros setup --tool arm-fvp is the fetch.

Doctor check

nano-ros checks that the model resolves via ARMFVP_BIN_PATH, ARM_FVP_DIR, PATH, or the SDK store (where nros setup --tool arm-fvp installs it), and warns — never hard-fails — when it can’t. A warning rather than an error because a contributor who is not working on the FVP should not be blocked by its absence; nros setup --tool arm-fvp is the fix when they are.

Changing this in the tree: see Internals → per-platform lanes.

Build

The FVP is a Zephyr board, fvp-aemv8r-smp, so an image names it in its bringup’s system.toml and nros build hands it to west like any Zephyr image (the Zephyr chapter has the workspace flow). The worked example is examples/workspaces/realtime-cpp’s [image.fvp], a Cyclone DDS image:

[image.fvp]
board = "fvp-aemv8r-smp"
rmw = "cyclonedds"

The build generates the messages from your ROS 2 install, so the first one runs in a shell that has sourced it; it records the prefix, so later builds need no sourced shell:

nros setup zephyr --rmw cyclonedds     # the Zephyr workspace + SDK
nros setup fvp-aemv8r-smp              # the model (x86_64 Linux only)
source /opt/ros/humble/setup.bash
nros build demo_bringup:fvp

The model must be resolvable when the build configures: Zephyr caches the FVP_BaseR_AEMv8R path then, so an image configured before the model was installed (or before ARMFVP_BIN_PATH was set) has to be reconfigured (nros build demo_bringup:fvp -- --pristine). nros build says so in the note it prints after the build.

Run on the FVP

nros build ends by printing Zephyr’s run target for the image’s build directory; it invokes FVP_BaseR_AEMv8R with the board’s cluster and UART settings and pipes the UARTs to your terminal:

west build -d build/zephyr-cyclonedds/demo_bringup__fvp_west -t run

Not replayed. No probe track builds or boots the FVP image yet, so this line is unmeasured on the installed track (tracking issue).

The model is a free download, not licence-gated (see Prereqs); what keeps it off a CI lane is cost and its x86_64-only host build. It runs until you stop it (Ctrl-C).

Expected output

The Zephyr 3.7 boot banner appears on UART0 first, followed by the talker. The exact line counts depend on CONFIG_BOOT_BANNER and your locator config, but the markers to look for are:

*** Booting Zephyr OS build v3.7.0 ***
[00:00:00.xxx,000] <inf> nros: session up (domain 0)
Publishing: 'Hello World: 1'
Publishing: 'Hello World: 2'
...

For the cpp/cyclonedds recipe, the same banner is followed by Cyclone DDS reader-match logs and std_msgs/String publish lines. Verify ROS 2 interop by running a sibling listener in another terminal:

# stock ROS 2 — reads the FVP's Cyclone DDS publisher
ros2 topic echo /chatter std_msgs/msg/String

The same std_msgs/String payload (Hello World: N) + byte-equal CDR framing must appear on both sides — that’s the stock-RMW interop contract (byte-compatible with rmw_cyclonedds_cpp).

Cross-references