Guidance on LOKI Project Toplevel Design - stfc-aeg/loki GitHub Wiki
Contents:
- Introduction
- Typical Application Repository Architecture
- Creating an Application Project with LOKI as a Submodule
- Building the Recovery Image
Note
Looking for how to start your application repository?
New applications should make use of the application template repository- see its README.
%%{ 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
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.
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.
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.
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.
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.
Warning
This method is now out of date, but required in case of maintaining old projects. New projects should use the application template.
- Create your application directory / repository
git init- Add LOKI as a submodule
git submodule add [email protected]:stfc-aeg/loki.git- Create a basic application configuration using
loki-recoveryas 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 ./MakefileUpdate the Makefile to suit your application:
- Set
LOKI_DIRto the submodule location, most likely./loki/ - Set the
APPLICATION_DIRto your application's top-level directory. This is currently unused. - Set
LOKI_ENV_DIRto the location of your.envfiles, most likely./
-
Populate your application-specifics
- Add any constraints to the
constraintsdirectory 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.
- You must set CONSTRAINTS_SOURCE_DIR in your makefile so that they are automatically included. Otherwise, add
- 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
- Add the location to
- 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_DIRandSW_EXPORT_DIRin your Makefile. Otherwise, both should haveundefinelines as above for the constraints, after theexport.- 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.
- Add any constraints to the
-
Build the project
makeThe built files that you need will appear in loki/os/petalinux-custom/images/linux/.
See also Booting, Updating and Debugging.
The recovery image uses a standalone makefile -MakefileRecovery- that will build the project without being a submodule.
To build the image:
make -f MakefileRecoveryThe image outputs will be built to os/petalinux-custom/images/linux/.
To upload these files to a board, see Booting, Configuring and Updating Systems.