-
Notifications
You must be signed in to change notification settings - Fork 0
Yocto Layer for Odin Control
The Yocto recipe layer is a directory that specifies how the application-specific code should be baked into the Linux image. This 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.
A good example of how this can work is in the BabyD repository.
Contents:
- Creating the Yocto Layer
- Creating a Recipe For an Odin-Control Instance
- Troubleshooting
- Create the parent directories from your project root. The name
meta-<project>is just a convention, but the other directories and files must have the same names to overlay properly.
mkdir meta-<project>
cd meta-<project>mkdir conf
touch conf/layer.conf- Edit the main config file.
layer.confdescribes the contents of this layer as well as how it overlays. These settings should work fine, but remember to replace "" with whatever your project's name is.
# layer.conf
# We have a conf and classes directory, add to BBPATH
BBPATH .= ":${LAYERDIR}"
# We have recipes-* directories, add to BBFILES
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
${LAYERDIR}/recipes-*/*/*.bbappend"
BBFILE_COLLECTIONS += "<project>"
BBFILE_PATTERN_<project> = "^${LAYERDIR}/"
BBFILE_PRIORITY_<project> = "9"
LAYERVERSION_<project> = "1"
LAYERSERIES_COMPAT_<project> = "zeus" # For 2020 tools
LAYERSERIES_COMPAT_<project> = "langdale" # For 2023 tools-
Create an odin-detector recipe instance (see Creating a Recipe for an Odin-Control Instance), by convention called
<project>-detector. -
Add the recipe name to the
layer.confso that it will always be brought into the Linux image without being a dependency.
IMAGE_INSTALL_APPENDS = " <project>-detector" # For 2020 tools
IMAGE_INSTALL:append = " <project>-detector" # For 2023 toolsWarning
DO NOT try and include these lines in any file aside from layer.conf, no matter what is already present. This leads to confusion due to the way that some petalinux-specific files are overridden between layers.
- Update your repository environment file to include the location of the new user layer (see Repository Configuration Files for more information). In
repo.env:
yocto_user_layer_0=$(shell pwd)/meta-<project>Note that you may have to clean and re-build the entire project for this to take effect.
An instance of odin-control is the combination of odin-control adapter(s), configuration file(s), sequences for odin-sequencer (optional), and any other supporting files. To make this easier - and to standardise installation locations - a base recipe from which application-specific recipes can be derived has been created. This means that everything to do with automatically starting the process, system outputs and static resource target locations are all handled. Additionally, it includes the the odin-control software, dependencies, and supporting code (odin-devices and odin-sequencer) in the image.
This guide assumes that you have already created an odin-control adapter for your project, and that it is present in the repository's /control directory, or is in another known repository.
Note
Throughout this documentation, ensure that <project> is always replaced with the exact same project/detector name
The recipe must be created inside a subdirectory recipes-apps in the user layer. This step takes place assuming the user is CD'ed into /meta-<project>/
mkdir recipes-apps
mkdir recipes-apps/detector
cd recipes-apps/detectorCreate a directory for any files that the recipe will need to import later (if applicable):
mkdir filesCreate the recipe files themselves (update name to match your project):
touch <project>-adapter.bb
touch <project>.bbIf your control code is in the current repository, create a relative symlink to it (if your control code is in a repository, skip this step).
This way, the logic for moving the control software into the image is kept in the Yocto layer, and the control software is in the toplevel with no required knowledge of how this is done, making it easier to work in in isolation.
ln -s ../../../../control files/controlThere are two types of recipe files that need to be created, adapter recipe(s) and an application recipe.
An adapter recipe uses <project>-adapter.bb as its naming convention. This recipe is used to install an adapter as a python package that the application recipe will later depend on.
An application recipe uses <project>.bb as its naming convention. This recipe is used to install any UIs, or config files that are required.
Note
These are generic templates and may not be entirely applicable for your scenario. Please ensure all placeholders are replaced with the revelvant information
You can create this initially by using this template:
SUMMARY = "A recipe for the <project> adapter"
RDEPENDS_${PN} += "odin-control (= 1.6.0)"
SRC_URI = "file://control/* \
"
inherit setuptools3
do_configure_prepend() {
cd ${WORKDIR}/<directory_with_setup.py>
}
do_compile_prepend() {
cd ${WORKDIR}/<directory_with_setup.py>
}
do_install_prepend() {
cd ${WORKDIR}/<directory_with_setup.py>
}
# This has to be in the format expected in Yocto's license list...
LICENSE = "CLOSED"Warning
For 2023 tools, _prepend becomes :prepend, _append becomes :append, and _${PN} becomes :${PN}
You can initially create this file using this template:
inherit odin-control-instance
SUMMARY = "A recipe for the <project> application"
RDEPENDS_${PN} += "<adapter-recipe-name>"
S = "${WORKDIR}"
REACT_UI_TAG = "v0.0.0"
# React UI will end up here
REACT_SOURCE_PATH = "<project>-${REACT_UI_TAG}"
REACT_SOURCE_URL = "<react_UI_download_URL>"
# Repo will be cloned into here
REPO_CLONED_BASE = "git"
# Pull specific commit from repository
SRCREV = "<commit_hash>"
PV = "0.0+git${SRCPV}"
SRC_URI = "git://<github repo URL> \
file://<project>-config.conf \
"
# Checksum specifically for the react UI
SRC_URI[react-build-zip.sha256sum] = "<checksum>"
# This has to be in the format expected in Yocto's license list...
LICENSE = "CLOSED"
# Relative repository locations of standard resources
REPO_STATIC_PATH = '${REACT_SOURCE_PATH}'
REPO_SEQUENCES_PATH = 'control/sequences/'
REPO_CONFIG_PATH = 'control/config/config.cfg'
FILES_${PN} += "${base_prefix}/opt/loki-detector/instances/${PN}/*"Warning
For 2023 tools, _prepend becomes :prepend, _append becomes :append, and _${PN} becomes :${PN}
Note
If using remote complied React resources, REPO_STATIC_PATH must be the same as REACT_SOURCE_PATH
-
Your code will need to be staged by the recipe in
SRC_URI, but this will depend on where it is stored- If (typical) your control code is in the current application repository, specify the local location (this also works with symlink directories). E.g.
SRC_URI = "file://control/* \ "
-
If your control code resides in a different repository, you will have to specify it with a
git://URL, as well as a specific tag or commit hash inSRCREV(you cannot simply specify a branch assuming it will pull the latest commit). Note that this is quite different depending on tool version.- For 2020 tools:
SRC_URI = "git://github.com/stfc-aeg/mercury-detector.git;branch=use-loki-carrier \ " # Pull specific commit from mercury-detector repository SRCREV = "91b2edb93f2a899b4fa2394eaa3444ca7810459c" PV = "0.0+git${SRCPV}"
- For 2023 tools (more complicated due to it not liking hanging references):
# To build to a tag, update the tag here as well as the commit hash below. # You can fetch the git hash with git ls-remote https://github.com/<repository> refs/tags/<tag> GIT_TAG = "1.6.0" GIT_HASH = "a5a399d21818405c262a1f09cdfe32a944e5f084" PV = "${GIT_TAG}+git${SRCPV}" # AUTOREV will just pull latest version # SRCREV must now be the git hash of the target tag since Yocto does not like hanging references. SRCREV = "${GIT_HASH}" SRC_URI = "git://github.com/odin-detector/odin-control.git;protocol=http;branch=master" SRC_URI[md5sum] = "1af5b49ffe84b3360b23086c7bb06a15"
Some other settings:
- The
RDEPENDSis used to specify any runtime dependencies you need along with your recipe- Suggested often-used dependencies are
python3-matplotlibandpython3-numpy. These were originally always build into the core, but are now only built if the application requires them. You can also add them tolayer.confif they are not specific to the recipe.
- Suggested often-used dependencies are
-
SUMMARYshould be updated for your project ` This example is using a react-based UI, which has already been compiled and made available as a build artifact from a separate repository. This is the recommended way of producing a UI. See below. -
REPO_STATIC_PATHis used to point the base recipe to static resources from this repository/codebase, if there are any (see UI options below) -
REPO_SEQUENCES_PATHis used to point the base recipe toodin-sequencersequences that should be baked into the image -
REPO_CONFIG_PATHis used to point the base recipe to theodin-controlconfig file for starting the server
Note
A UI is optional
Add the target repository location so that it will grab a certain tag's build outputs, assuming that the repository has been set up with automation to build tagged versions:
# The react UI tag is a separate repository, used to download pre-built static assets
# This will only accept tags that have been built (releases)
REACT_UI_TAG = "v0.0.4"
REACT_SOURCE_PATH = "babyd-ui-${REACT_UI_TAG}"
REACT_SOURCE_URL = "https://github.com/owner/repo/releases/${REACT_UI_TAG}/build.zipREACT_UI_SOURCE_URL is the URL of the compiled resources that will be downloaded and unzipped into the directory specified in REACT_SOURCE_PATH.
There is a base directory in the LOKI image that is used for including general purpose files and folders. The destination locations are relative to this directory.
To add a files from a local directory (files in the Yocto layer):
# Add the files to the source for the recipe
SRC_URI += " file://control/*"
# Install the target directory into the image
copy_resource_protected 'control/clkgen' 'clkgen'To add a directory from a cloned source after creating the destination directory:
do_install_append() {
# Add a directory to the image for the clock configs at the same relative place
loki_mkdir 'carrier' # Must create parent
copy_resource_protected '${MERCURY_REPO_CLONED_BASE}/control/test/carrier/clk_config' 'carrier/clk_config'
}#TODO there are helpers to build things into the image in known locations, explain them.
Check that this is still a requirement; it is only used while
odin-sequenceris not available as part ofodin-reactand must therefore be included separately. WARNING: This is hacky.
Essentially this boils down to three steps:
- Install the sequencer UI as a static page, using the instructions above
- Move the sequencer's
index.htmlto a page with a different name post-install, to clear the way for the React UI:
do_install_prepend() {
# Rename the original UI index.html to prevent conflict. This means the sequencer
# can be accessed at <IP>:8888/original.html
# TEMPORARY UNTIL SEQUENCER IS INCLUDED IN REACT UI
mv '<sequencer_dir_path>/index.html' '<sequencer_dir_path>/original.html'
}- Copy of the React resources manually, hoping that none of the filenames conflict with filenames of the sequencer UI already added to the same location:
do_install_append() {
# Directly copy the resources into the default working static location.
# This is an untidy way of doing things, and relies on a lack of conflicts
# (apart from the manually handled index.html), but means the two 'separate'
# UI's can be used a the same time.
# A better future solution would be to integrate the sequencer UI into react.
# TEMPORARY UNTIL SEQUENCER IS INCLUDED IN REACT UI
copy_resource_protected '<sequencer_dir_path>/.' ${LOKI_STATIC_DESTINATION}
}There is a default recipe config file located at loki/os/petalinux-custom/project-spec/meta-user/recipes-apps/loki/files/config-default.conf (relative to your top level directory for the detector repository). This config file contains options such as log file locations and a toggle for auto starting instances of Odin control, along with many other options.
To override these default configurations for your application, follow these steps:
- Create a file named
<project>-config.confinside thefilesdirectory you created. - Assign the desired options a new value (any options that are not changed will still use the default)
- Add the following to
<project>.bb:
do_install_append() {
install -d ${D}${base_prefix}/etc/conf.d/loki-config
install -m 0644 '${WORKDIR}/<project>-config.conf' '${D}${base_prefix}/etc/conf.d/loki-config/<project>-config.conf'
}
FILES_${PN} += "${base_prefix}/etc/conf.d/loki-config/*"
By default, all installed instances of odin-control are automatically started on boot. To disable this for an instance of odin-control, add conf_AUTO_START=false to the relevant files/<project>-config.conf file.
Generally if all else fails (and your issue is not mentioned below), a make clean && make should sort most issues out.
Sometimes the PetaLinux tools just get in a state where things are broken and can't easily be recovered.
To save time, try this first in the PetaLinux directory only (cd loki/os/petalinux-custom; make clean && make) before doing the same in the root directory (since the latter will also rebuild the hardware).
In addition, ensure that you are not using the same Yocto cache location (in machine.env) for more than one of the Yocto builds, as they will interfere with each other at some point (traditionally later on, once you've forgotten about this).
This is not really a specific error in itself, but to find out more to aid in debugging, you should attempt to build the recipe on its own. This may allow you to spot errors that were masked during the build process (sometimes errors occur and the PetaLinux build just carriers on anyway...).
- Make sure you have the correct PetaLinux tools activated (
module load xilinx/2020-1; petalinux_env) - Change directory to the PetaLinux root (
cd loki/os/petalinux-custom/) - Build just your recipe's name (e.g.
petalinux-build -c <projectname>-detector)
This should build properly by itself, or otherwise print out errors with more information.
If you get the following error, it may not exactly be what it suggests:
'PATCHTOOL = "git" set for source tree that is not a git repository.
This is actually returned by the patch.bbclass when
This is usually because the GitHub repository that the recipe is trying to download the release from is private. In order for releases to be downloaded the repo must be set to public.
If this is not the solution, please ensure that the URL being used is correct.