Guidance on LOKI Project Toplevel Design - stfc-aeg/loki GitHub Wiki

LOKI - Guidance on Top-level Project Architecture

Contents:

Introduction

Note

Looking for how to start your application repository?

New applications should make use of the application template repository- see its README.

Typical Application Repository Architecture

%%{ init : { "theme" : "default" }}%%
flowchart LR
    subgraph Toolchain Flow
        direction LR
        
        subgraph lokicore["LOKI Core Repository"]
            subgraph lokihwsw["LOKI Repository HW & SW"]
                subgraph Vivado
                    hardwarebuild["Hardware Build"] --> fileXSA
                end

                subgraph Vitis
                    fileXSA["design_???.xsa<br>Hardware File"]
                    fileXSA --> buildFSBL["Build FSBL"] --> fileFSBL["fsbl.elf"<br>First Stage Bootloader]
                    fileXSA --> buildPMUFW["Build PMUFW"] --> filePMUFW["pmufw.elf"<br>Power Management Firmware]
                end
            end

            subgraph PetaLinux["LOKI PetaLinux OS Build"]
                fileXSA --> xsaImport
                filePMUFW --> pmufwImport["Copy PMUFW"]
                fileFSBL --> fsblImport["Copy FSBL"]
                xsaImport --> filesystembit["system.bit<br>Bitstream"]
                xsaImport["Import Hardware Design"] --> kernelBuild["Kernel Build"] --> fileKernelImg["Kernel Image"]
                xsaImport --> softwareBuild["Software Build"] --> fileRootFS["RootFS"]
                xsaImport --> dtBuild["Device Tree Build"] --> fileDTB["system.dtb<br>Device Tree"]
                xsaImport --> ubootBuild["UBoot Build"] --> fileubootelf["u-boot.elf<br>U-Boot Binary"]
                ubootBuild --> filebootscr  

                subgraph Packaging
                    fsblImport --> fileBOOTBIN
                    pmufwImport --> fileBOOTBIN
                    filesystembit --> fileBOOTBIN
                    filebl31 --> fileBOOTBIN
                    fileDTB --> fileBOOTBIN
                    fileubootelf --> fileBOOTBIN

                    fileKernelImg --> fileimageub
                    fileRootFS --> fileimageub
                    fileDTB --> fileimageub

                    subgraph finalimage
                        fileBOOTBIN["BOOT.BIN<br>Combined Bootloader"]
                        fileimageub["image.ub<br>Boot Image"]
                        filebootscr["boot.scr<br>U-Boot Script"]
                    end
                end
            end
        end

        subgraph apprepo["Application Repository"]

            appyoctolayer["Application<br>Yocto Layer"]
            appyoctolayer -->|App Software Mods| softwareBuild
            appyoctolayer -->|App Pin Names & Device Tree Modifications| dtBuild

            appconstraints["Application<br>Constraints"] --> hardwarebuild

            subgraph outoftreeHardware["Optional External HW/SW"]
                outoftreeXSA["Alternative XSA"] -.-> xsaImport
                outoftreeFSBL["Alternative FSBL"] -.-> fsblImport
                outoftreePMUFW["Alternative PMUFW"] -.-> pmufwImport
            end
        end
    end


    classDef process fill:#829cfa,stroke:#333,stroke-width:2px;
    classDef file fill:#fad4c0,stroke:#333,stroke-width:1px;
    classDef fileHWSW fill:#fad4c0,stroke:red,stroke-width:2px;
    classDef optional fill:#b6c5fa,stroke:#333,stroke-width:2px,stroke-dasharray: 5 5;
    classDef apprepo fill:#b6c5fa,stroke:#333,stroke-width:2px;
    classDef lokirepo fill:#b6c5fa,stroke:#333,stroke-width:2px;
    classDef lokireposubpart fill:#f96,stroke:#333,stroke-width:2px;
    
    class apprepo apprepo
    class PetaLinux,lokihwsw lokirepo
    class Vivado,Vitis,Packaging lokireposubpart
    class outoftreeHardware optional
    class filebl31,fileBOOTBIN,filebootscr,fileDTB,fileimageub,fileKernelImg,fileRootFS,filesystembit,fileubootelf file
    class fileFSBL,filePMUFW,fileXSA,outoftreeFSBL,outoftreeXSA,outoftreePMUFW fileHWSW
    class hardwarebuild,xsaImport,buildFSBL,buildPMUFW,fsblImport,pmufwImport,dtBuild,kernelBuild,ubootBuild,softwareBuild process
Loading

The LOKI Submodule

Repository Contents:

  • share, config.mk, Makefile.in, configure.ac: Automatic configuration of the project based on hardware selection, application-specific configuration and application hardware/software layers.
  • design: The firmware and low-level software design project, used for linking the software processing system to package pins, and including application-specific hardware designs.
  • os: The PetaLinux Embedded Linux project, used for building the final system image and providing configuration and all software dependencies for odin-control based detector systems.
  • loki-recovery, MakefileRecovery: Serves as a base and example application configuration, which builds an image with some self-test capability.

Application Constraints

Constraints are the method for -among other things- connecting internal programmable logic signals to named package pins. LOKI already contains definitions for connections to its own on-board devices and interfaces, so this will be for defining any application-specific connections. Constraints are specified in Xilinx .xdc files.

Note that if you have added application-specific GPIO connections, you might want to name them to make it easier to tell which is which when accessing them via your control software. This requires adding GPIO line name definitions as a modification to the device tree. See Device Tree Modification.

Control Layer

The control layer includes the python code and any related files for an odin-control adapter for the application. By convention, this is created in the ./control directory, which is where the setup.py is located. There are alternative options here: for example, the HEXITEC-MHz LOKI project builds its control instance from a separate repository completely.

Instances of adapters used to control LOKI systems should be derived from a base carrier class packaged with the LOKI core project. For more information on this, see Guidance on odin-control Adapter Creation.

Yocto Recipe Layer

The Yocto recipe layer is a directory that specifies how the application-specific code should be baked into the Linux image. The is combined with general layers for the hardware provided by the vendor, as well as additional layers for supporting the LOKI infrastructure. In a typical LOKI application repository, this layer is used to create recipe derived from an odin-control base recipe to install the custom adapter into the image such that resources end up in a predictable place, and everything is executed automatically.

For generic odin-control instances, you can follow the guide in this Wiki (Yocto Layer for Odin Control - this guide assumes control software is already present in the ./control directory, or elsewhere in some repository).

Note

For more advanced layer modification, you should have knowledge of working with Yocto in general, but a lot can be figured out by looking at other recipes in the LOKI project and OpenEmbedded for reference.

User Interface

The user interface for a control instance is either supplied alongside it in a static resources directory (therefore part of the application repository), or static resources provided from some other location.

Most typically in recent projects, the UI has been created using React, a component-based library for constructing JavaScript interfaces. In this case (and since the development tools are not installed in the LOKI system) the static resources will have to be pre-compiled and placed somewhere the build can access them. In several projects, this is achieved by having the user interface in a separate repository that uses GitHub CI/CD to automatically compile the static resources for pushed tags, then hosting them where the associated application Yocto recipe knows where to look. A good example of this is the BabyD UI Repo.

There is more information on how to build in these resources to Yocto recipes for odin-control in this wiki article.

Creating an Application Project with LOKI as a Submodule

Warning

This method is now out of date, but required in case of maintaining old projects. New projects should use the application template.

  1. Create your application directory / repository
git init
  1. Add LOKI as a submodule
git submodule add [email protected]:stfc-aeg/loki.git
  1. Create a basic application configuration using loki-recovery as a reference:

Copy the base configuration environment files to your top-level directory. The machine.env is used to define machine-specific settings, such as toolchain location and will not be comitted to the repo. The repo.env contains definitions that will be updated on the repo, such as the application name built into teh image.

cp ./loki/loki-recovery/machine.env ./
cp machine.env machine.env.example
cp ./loki/loki-recovery/repo.env ./

Create new blank constraints and Yocto layer directories (your choice of name for the Yocto layer).

mkdir constraints
mkdir meta-<whatever>

Update the repo.env Yocto layer location to match meta-<whatever>. If your application does not require a custom Yocto layer, just delete the line that defines yocto_user_layer_0.

Copy the Application makefile from recovery to be the default application directory makefile:

cp ./loki/MakefileRecovery ./Makefile

Update the Makefile to suit your application:

  • Set LOKI_DIR to the submodule location, most likely ./loki/
  • Set the APPLICATION_DIR to your application's top-level directory. This is currently unused.
  • Set LOKI_ENV_DIR to the location of your .env files, most likely ./
  1. Populate your application-specifics

    • Add any constraints to the constraints directory in a file with name `l.xdc. This prefix means they will override other definitions.
      • You must set CONSTRAINTS_SOURCE_DIR in your makefile so that they are automatically included. Otherwise, add undefine CONSTRAINTS_SOURCE_DIR.
    • If using one, define a Yocto layer in meta-<whatever>. See Odin Control Yocto Layer Creation for more information.
      • Add the location to repo.env
    • If you are using a pre-built (or externally built) XSA (HW), FSBL & PMUFW (SW), set the location they are exported to in variables HW_EXPORT_DIR and SW_EXPORT_DIR in your Makefile. Otherwise, both should have undefine lines as above for the constraints, after the export.
      • Note that if you are using pre-built files, any constraints you supply will not be picked up, as these are already part of the XSA compiled XSA hardware file.
  2. Build the project

make

The built files that you need will appear in loki/os/petalinux-custom/images/linux/. See also Booting, Updating and Debugging.

Building the recovery image

The recovery image uses a standalone makefile -MakefileRecovery- that will build the project without being a submodule.

To build the image:

make -f MakefileRecovery

The image outputs will be built to os/petalinux-custom/images/linux/. To upload these files to a board, see Booting, Configuring and Updating Systems.

⚠️ **GitHub.com Fallback** ⚠️