Yocto Project Zephyr Build

This page describes how to configure and build Zephyr RTOS applications for Cortex-A and Cortex-R processors using Yocto Project. The flow primarily uses SDT, Lopper, and gen-machine-conf tools to parse an XSA and transform it into Zephyr board source files.

Introduction

The Yocto Project can build for a variety of targets: Linux, Zephyr, bare-metal, etc. Using multiconfig one can target a combination of these environments in one single configured build. Zephyr is a real-time operating system (RTOS) that is open-source and hosted by the Linux Foundation. It is a collaborative effort uniting developers and users in building a best-in-class small, scalable, real-time operating system (RTOS) optimized for resource-constrained devices, across multiple architectures. For more details see Zephyr Getting Started Guide

Yocto Zephyr Build Workflows

Yocto Zephyr Build Architecture

Yocto Zephyr build flows: setup the YP host environment, clone poky and the AMD layers (meta-zephyr and meta-AMD), source the build env, and add the AMD and Zephyr layers to bblayers.conf; Vivado Tools produce the XSA, which SDTGen and the gen-machine-conf tool turn into per-domain DTS files and Lopper assists (gen_domain_dts, baremetaldrvlist_xlnx, xlnx_overlay_pl_dt) that drive zephyr_soc / zephyr_board / generated config files; bitbake builds the <zephyr-app> recipe (inheriting amd-zephyr-sdt and requiring amd-zephyr-kernel-src.inc) and produces images for SD/eMMC/UFS, QEMU runqemu, QSPI/NAND/OSPI, and a JTAG boot tcl that can be loaded with XSDB.

Yocto Zephyr Build Architecture overview.

Lopper Transformation

This section describes how to transform SDT output files to an operating environment standard device tree. Lopper tool is used to prune a system device tree to an Zephyr operating environment standard device tree. Lopper Transformation can be done in two ways.

Manual Transformation

  • Run the lopper commands manually to transform SDT to standard operating specific environment dt files.

    • Clone lopper repo:

      $ git clone https://github.com/Xilinx/lopper -b <version_branch>
      $ export LOPPER_REPO_PATH=$PWD/lopper
      $ export LOPPER_DTC_FLAGS="-b 0 -@"
      
    • VERSAL-2VE-2VM Cortex-A78 Processor (Example: VEK385 Cortex-A78 Core1)

      $ mkdir -p lopper-outputs/vek385-cortexa78-1/
      $ export SDT_VEK385_OUTPUT_DIR=<path-to>/versal-2ve-2vm-vek385-sdt-seg/
      $ export LOPPER_VEK385_OUTPUT_DIR=$PWD/lopper-outputs/vek385-cortexa78-1/
      $ export CONFIG_DTFILE=versal2_apu.dts
      $ ${LOPPER_REPO_PATH}/lopper.py -f --enhanced -O ${LOPPER_VEK385_OUTPUT_DIR} ${SDT_VEK385_OUTPUT_DIR}/system-top.dts system-domain.dts -- gen_domain_dts cortexa78_1
      $ ls -la ${LOPPER_VEK385_OUTPUT_DIR}
      total 232
      drwxr-xr-x 2 santraju boulder   4096 Aug 22 17:13 .
      drwxr-xr-x 7 santraju boulder   4096 Aug 22 16:36 ..
      -rw-r--r-- 1 santraju boulder 227402 Aug 22 17:13 system-domain.dts
      $
      $ ${LOPPER_REPO_PATH}/lopper.py -f --enhanced -O ${LOPPER_VEK385_OUTPUT_DIR} -i ${LOPPER_REPO_PATH}/lopper/lops/lop-a78-imux.dts ${LOPPER_VEK385_OUTPUT_DIR}/system-domain.dts system-imux.dts
      $ ls -la ${LOPPER_VEK385_OUTPUT_DIR}
      total 452
      drwxr-xr-x 2 santraju boulder   4096 Aug 22 17:13 .
      drwxr-xr-x 7 santraju boulder   4096 Aug 22 16:36 ..
      -rw-r--r-- 1 santraju boulder 227402 Aug 22 17:13 system-domain.dts
      -rw-r--r-- 1 santraju boulder 222828 Aug 22 17:13 system-imux.dts
      $
      $ ${LOPPER_REPO_PATH}/lopper.py -f --enhanced -O ${LOPPER_VEK385_OUTPUT_DIR} ${LOPPER_VEK385_OUTPUT_DIR}/system-imux.dts ${CONFIG_DTFILE} -- gen_domain_dts cortexa78_1 zephyr_dt
      $ ls -la ${LOPPER_VEK385_OUTPUT_DIR}
      total 404
      drwxr-xr-x 2 santraju boulder   4096 Aug 11 18:33 .
      drwxr-xr-x 7 santraju boulder   4096 Aug 22 16:36 ..
      -rw-r--r-- 1 santraju boulder 191943 Aug 11 15:40 system-domain.dts
      -rw-r--r-- 1 santraju boulder 187968 Aug 11 15:40 system-imux.dts
      -rw-r--r-- 1 santraju boulder  21079 Aug 11 15:44 versal2_rpu.dts
      $
      
    • VERSAL-2VE-2VM Cortex-R52 Processor (Example: VEK385 Cortex-R52 Core0)

      $ mkdir -p lopper-outputs/vek385-cortexr52-0/
      $ export SDT_VEK385_OUTPUT_DIR=<path-to>/versal-2ve-2vm-vek385-sdt-seg/
      $ export LOPPER_VEK385_OUTPUT_DIR=$PWD/lopper-outputs/vek385-cortexr52-0/
      $ export CONFIG_DTFILE=versal2_rpu.dts
      $ ${LOPPER_REPO_PATH}/lopper.py -f --enhanced -O ${LOPPER_VEK385_OUTPUT_DIR} ${SDT_VEK385_OUTPUT_DIR}/system-top.dts system-domain.dts -- gen_domain_dts cortexr52_0
      $ ls -la ${LOPPER_VEK385_OUTPUT_DIR}
      total 176
      drwxr-xr-x 2 santraju boulder   4096 Jun 17 15:07 .
      drwxr-xr-x 4 santraju boulder   4096 Jun  9 13:53 ..
      -rw-r--r-- 1 santraju boulder 171372 Jun 17 15:07 system-domain.dts
      $
      $ ${LOPPER_REPO_PATH}/lopper.py -f --enhanced -O ${LOPPER_VEK385_OUTPUT_DIR} -i ${LOPPER_REPO_PATH}/lopper/lops/lop-r52-imux.dts ${LOPPER_VEK385_OUTPUT_DIR}/system-domain.dts system-imux.dts
      $ ls -la ${LOPPER_VEK385_OUTPUT_DIR}
      total 340
      drwxr-xr-x 2 santraju boulder   4096 Jun 17 15:07 .
      drwxr-xr-x 4 santraju boulder   4096 Jun  9 13:53 ..
      -rw-r--r-- 1 santraju boulder 171372 Jun 17 15:07 system-domain.dts
      -rw-r--r-- 1 santraju boulder 167642 Jun 17 15:07 system-imux.dts
      $
      $ ${LOPPER_REPO_PATH}/lopper.py -f --enhanced -O ${LOPPER_VEK385_OUTPUT_DIR} ${LOPPER_VEK385_OUTPUT_DIR}/system-imux.dts ${CONFIG_DTFILE} -- gen_domain_dts cortexr52_0 zephyr_dt
      $ ls -la ${LOPPER_VEK385_OUTPUT_DIR}
      total 348
      drwxr-xr-x 2 santraju boulder   4096 Jun 17 15:08 .
      drwxr-xr-x 4 santraju boulder   4096 Jun  9 13:53 ..
      -rw-r--r-- 1 santraju boulder 171372 Jun 17 15:07 system-domain.dts
      -rw-r--r-- 1 santraju boulder 167642 Jun 17 15:07 system-imux.dts
      -rw-r--r-- 1 santraju boulder   6911 Jun 17 15:08 versal2_rpu.dts
      $
      

gen-machine-conf

  • The gen-machine-conf tool automates the Yocto Project flow that transforms an SDT into standard operating-system-specific generated device tree, machine, and multiconfig files.

Yocto AMD Zephyr Meta-Layers

Building AMD Zephyr using Yocto requires the following layers.

  1. meta-zephyr

    1. meta-zephyr-core

      1. Core layer provides meta data information for the following.

        1. zephyr, zephyr-sample, and zephyr-qemu bbclass

        2. qemu zephyr wrapper scripts

        3. zephyr-kernel source recipes

        4. zephyr-<apps> recipes

        5. zephyr-sdk generation recipes

    2. meta-zephyr-bsp

      1. Core layer provides meta data for pre-defined machine files for different SoC’s, Community Boards, Vendor Boards, and QEMU emulation platform.

  2. meta-amd-zephyr

    1. amd-zephyr-sdt bbclass

      1. This class use lopper transformed files such as <board>.dts, Kconfig and Kconfig.defconfig file path is set in machine/multiconfig files are copied and replace with <zephyr-repo>/boards/amd/<boards>/<board>.dts , <zephyr-repo>/soc/xlnx/<arch>/Kconfig and <zephy-repo>/soc/xlnx/<arch>/Kconfig.defconfig file during bitbake do_configure tasks.

    2. zephyr-kernel and apps bbappends to build demo application using AMD Zephyr.

Example Yocto AMD Zephyr Machine file

VEK385 Cortex-A78 Core 1

  • Machine file:

    # conf/machine/versal-2ve-2vm-apu.conf
    #@TYPE: Machine
    #@NAME: versal-2ve-2vm-apu
    #@DESCRIPTION: Machine for stock Zephyr BOARD versal2_apu
    # Include tune-cortexa72-cortexa53.inc
    require conf/machine/include/arm/armv8a/tune-cortexa72-cortexa53.inc
    # This machine file demonstrates building the stock Zephyr amd versal2_apu board using
    # meta-amd-zephyr layer.
    DEFAULTTUNE = "cortexa72-cortexa53"
    DISTRO = "amd-zephyr"
    TMPDIR = "${TOPDIR}/tmp-versal-2ve-2vm-apu"
    # Zephyr RTOS settings
    ZEPHYR_BOARD = "versal2_apu"
    ARCH:versal-2ve-2vm-apu = "arm"
    
  • Multiconfig Machine file

    # conf/multiconfig/versal-2ve-2vm-vek385-sdt-seg-cortexa78-1-zephyr.conf
    #@TYPE: Machine
    #@NAME: versal-2ve-2vm-vek385-sdt-seg-cortexa78-1-zephyr
    #@DESCRIPTION: Multiconfig Machine for SDT Zephyr BOARD versal2_apu
    DEFAULTTUNE = "cortexa72-cortexa53"
    DISTRO = "amd-zephyr"
    TMPDIR .= "-${BB_CURRENT_MC}"
    # Zephyr RTOS settings
    ZEPHYR_BOARD = "versal2_apu"
    ARCH:versal-2ve-2vm-apu = "arm"
    CONFIG_DTFILE = "${CONFIG_DTFILE_DIR}/versal-2ve-2vm-vek385-sdt-seg-cortexa78-1-zephyr.dts"
    

Because we are not generating versal-2ve-2vm-vek385-sdt-seg-cortexa78-1-zephyr multiconfig by default, first run a pre-step before building.

  1. Copy versal-2ve-2vm-vek385-sdt-seg-cortexa78-1-zephyr.dts to meta-amd-adaptive-socs/meta-amd-adaptive-socs-bsp/conf/dts directory.

  2. Add versal-2ve-2vm-vek385-sdt-seg-cortexa78-1-zephyr to BBMULITICONFIGin meta-amd-adaptive-socs/meta-amd-adaptive-socs-bsp/conf/versal-2ve-2vm-vek385-sdt-seg.conf machine file. Example:

    BBMULTICONFIG += "versal-2ve-2vm-vek385-sdt-seg-cortexr52-0-zephyr versal-2ve-2vm-vek385-sdt-seg-cortexr52-1-baremetal versal-2ve-2vm-vek385-sdt-seg-microblaze-pmc versal-2ve-2vm-vek385-sdt-seg-cortexa78-1-zephyr"

VEK385 Cortex-R52 Core 0

  • Machine file:

    # conf/machine/versal-2ve-2vm-rpu.conf
    #@TYPE: Machine
    #@NAME: versal-2ve-2vm-rpu
    #@DESCRIPTION: Machine for stock Zephyr BOARD versal2_rpu
    # Include tune-cortexr52
    require conf/machine/include/arm/armv8r/tune-cortexr52.inc
    # This machine file demonstrates building the stock Zephyr amd versal2_rpu board using
    # meta-amd-zephyr layer.
    DEFAULTTUNE = "cortexr52"
    # GLIBC will not work with Cortex-R.
    TCLIBC = "newlib"
    DISTRO = "amd-zephyr"
    TMPDIR = "${TOPDIR}/tmp-versal-2ve-2vm-rpu"
    # Zephyr RTOS settings
    ZEPHYR_BOARD = "versal2_rpu"
    ARCH:versal-2ve-2vm-rpu = "arm"
    
  • Multiconfig Machine file

    # meta-amd-adaptive-socs/meta-amd-adaptive-socs-bsp/conf/multiconfig/versal-2ve-2vm-vek385-sdt-seg-cortexr52-0-zephyr.conf
    #@TYPE: Machine
    #@NAME: versal-2ve-2vm-vek385-sdt-seg-cortexr52-0-zephyr
    #@DESCRIPTION: Multiconfig Machine for SDT Zephyr BOARD versal2_rpu
    DEFAULTTUNE = "cortexr52"
    # GLIBC will not work with Cortex-R.
    TCLIBC = "newlib"
    DISTRO = "amd-zephyr"
    TMPDIR .= "-${BB_CURRENT_MC}"
    # Zephyr RTOS settings
    ZEPHYR_BOARD = "versal2_rpu"
    ARCH:versal-2ve-2vm-rpu = "arm"
    CONFIG_DTFILE = "${CONFIG_DTFILE_DIR}/versal-2ve-2vm-vek385-sdt-seg-cortexr52-0-zephyr.dts"
    

Yocto AMD Zephyr Recipe Template

Here is the example AMD Zephyr Recipe Template.

Note:

  • Recipe source(ZEPHYR_SRC_DIR) must be one of the following applications in https://github.com/Xilinx/zephyr-amd/tree/master/samples or it fails to build

  • Create a recipe

    $ touch meta-xilinx/meta-amd-zephyr/recipes-kernel/zephyr-kernel/<app-name>.bb
    
  • Add the following content to <app-name>.bb

    # Inheriting zephyr-sample is a must for all zephyr application recipes
    inherit zephyr-sample
    # Inheriting amd-zephyr-sdt will use the zephyr-amd repo instead of the upstream one.
    inherit amd-zephyr-sdt
    # To use SRC_URI_ZEPHYR pointing to zephyr-amd github tree instead of upstream
    # zephyr tree we need to add the amd-zephyr-kernel-src include file.
    require amd-zephyr-kernel-src.inc
    ZEPHYR_SRC_DIR = "${ZEPHYR_BASE}/samples/<app-name>"
    # Optional
    COMPATIBLE_MACHINE = "<machine-name>"
    # Additional CMake flags to be passed to zephyr cmake configuration phase.
    EXTRA_OECMAKE += ""
    

Building Zephyr Applications

Pre-requisites: Set up the build environment and Yocto Project pre-requisites by following Operating System Integration and Development AMD Versal device portfolio

VEK385 Cortex-A78 Core 1:

  • Without Multiconfig:

    $ MACHINE=versal-2ve-2vm-apu bitbake zephyr-helloworld
    
  • With Multiconfig:

    $ MACHINE=versal-2ve-2vm-vek385-sdt-seg bitbake mc:versal-2ve-2vm-vek385-sdt-seg-cortexa78-1-zephyr:zephyr-helloworld
    
  • After the images are built they are deployed in ${TMPDIR}-${BB_CURRENT_MC}/deploy/images/${MACHINE} directory. Here is an example.

    $ ls -la tmp-versal-2ve-2vm-vek385-sdt-seg-cortexa78-1-zephyr/deploy/images/versal-2ve-2vm-vek385-sdt-seg/
    total 4768
    drwxr-xr-x 2 santraju boulder    4096 Aug 22 19:49 .
    drwxr-xr-x 3 santraju boulder    4096 Aug 22 19:49 ..
    lrwxrwxrwx 2 santraju boulder      66 Aug 22 19:49 zephyr-helloworld.bin -> zephyr-helloworld-versal-2ve-2vm-vek385-sdt-seg-20250823014541.bin
    lrwxrwxrwx 2 santraju boulder      66 Aug 22 19:49 zephyr-helloworld.elf -> zephyr-helloworld-versal-2ve-2vm-vek385-sdt-seg-20250823014541.elf
    -rwxr-xr-x 2 santraju boulder 4304900 Aug 22 19:49 zephyr-helloworld-versal-2ve-2vm-vek385-sdt-seg-20250823014541.bin
    -rwxr-xr-x 2 santraju boulder  544104 Aug 22 19:49 zephyr-helloworld-versal-2ve-2vm-vek385-sdt-seg-20250823014541.elf
    lrwxrwxrwx 2 santraju boulder      66 Aug 22 19:49 zephyr-helloworld-versal-2ve-2vm-vek385-sdt-seg.bin -> zephyr-helloworld-versal-2ve-2vm-vek385-sdt-seg-20250823014541.bin
    lrwxrwxrwx 2 santraju boulder      66 Aug 22 19:49 zephyr-helloworld-versal-2ve-2vm-vek385-sdt-seg.elf -> zephyr-helloworld-versal-2ve-2vm-vek385-sdt-seg-20250823014541.elf
    $
    

VEK385 Cortex-R52 Core 0:

  • Without Multiconfig:

    $ MACHINE=versal-2ve-2vm-rpu bitbake zephyr-helloworld
    
  • With Multiconfig:

    $ MACHINE=versal-2ve-2vm-vek385-sdt-seg bitbake mc:versal-2ve-2vm-vek385-sdt-seg-cortexr52-0-zephyr:zephyr-helloworld
    
  • After the images are built they are deployed in ${TMPDIR}-${BB_CURRENT_MC}/deploy/images/${MACHINE} directory. Here is an example.

    $ ls -la tmp-versal-2ve-2vm-vek385-sdt-seg-cortexr52-0-zephyr/deploy/images/versal-2ve-2vm-vek385-sdt-seg/
    total 520
    drwxr-xr-x 2 santraju boulder   4096 Aug 22 19:22 .
    drwxr-xr-x 3 santraju boulder   4096 Aug 22 19:22 ..
    lrwxrwxrwx 2 santraju boulder     66 Aug 22 19:22 zephyr-helloworld.bin -> zephyr-helloworld-versal-2ve-2vm-vek385-sdt-seg-20250823011055.bin
    lrwxrwxrwx 2 santraju boulder     66 Aug 22 19:22 zephyr-helloworld.elf -> zephyr-helloworld-versal-2ve-2vm-vek385-sdt-seg-20250823011055.elf
    -rwxr-xr-x 2 santraju boulder  45508 Aug 22 19:22 zephyr-helloworld-versal-2ve-2vm-vek385-sdt-seg-20250823011055.bin
    -rwxr-xr-x 2 santraju boulder 456148 Aug 22 19:22 zephyr-helloworld-versal-2ve-2vm-vek385-sdt-seg-20250823011055.elf
    lrwxrwxrwx 2 santraju boulder     66 Aug 22 19:22 zephyr-helloworld-versal-2ve-2vm-vek385-sdt-seg.bin -> zephyr-helloworld-versal-2ve-2vm-vek385-sdt-seg-20250823011055.bin
    lrwxrwxrwx 2 santraju boulder     66 Aug 22 19:22 zephyr-helloworld-versal-2ve-2vm-vek385-sdt-seg.elf -> zephyr-helloworld-versal-2ve-2vm-vek385-sdt-seg-20250823011055.elf
    $
    

XENVMGICV3:

  • Without Multiconfig:

    $ MACHINE=xenvmgicv3 bitbake zephyr-synchronization
    
  • After the images are built they are deployed in ${TMPDIR}/deploy/images/${MACHINE} directory. Here is an example.

    • Without Multiconfig:

      $ ls -la tmp/deploy/images/xenvmgicv3/
      total 1340
      drwxr-xr-x 2 santraju boulder    4096 Oct 14 08:44 .
      drwxr-xr-x 5 santraju boulder    4096 Oct 14 08:44 ..
      lrwxrwxrwx 2 santraju boulder      52 Oct 14 08:44 zephyr-synchronization.bin -> zephyr-synchronization-xenvmgicv3-20251014143550.bin
      lrwxrwxrwx 2 santraju boulder      52 Oct 14 08:44 zephyr-synchronization.elf -> zephyr-synchronization-xenvmgicv3-20251014143550.elf
      -rwxr-xr-x 2 santraju boulder  311300 Oct 14 08:44 zephyr-synchronization-xenvmgicv3-20251014143550.bin
      -rwxr-xr-x 2 santraju boulder 1046136 Oct 14 08:44 zephyr-synchronization-xenvmgicv3-20251014143550.elf
      lrwxrwxrwx 2 santraju boulder      52 Oct 14 08:44 zephyr-synchronization-xenvmgicv3.bin -> zephyr-synchronization-xenvmgicv3-20251014143550.bin
      lrwxrwxrwx 2 santraju boulder      52 Oct 14 08:44 zephyr-synchronization-xenvmgicv3.elf -> zephyr-synchronization-xenvmgicv3-20251014143550.elf
      $
      

Yocto Zephyr Limitations

  1. Doesn’t deploy following files.

    1. DTB (Only required for Zephyr QEMU boot).

  2. Zephyr Board Extension is not yet supported.

  3. Yocto Zephyr QEMU for AMD boards is not yet supported.