-
Notifications
You must be signed in to change notification settings - Fork 6.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Shows a simple application which loads extensions and some simple extensions. While everything is inside Zephyr tree, everything can actually be build from different directories (even machines), as long as the EDK is generated from the application and used by the extensions. More information is available at sample's README. This sample is build only for twister, as it requires a few steps to be properly run, namely build the EDK, install it somewhere, build the extensions using the EDK and finally build the application with the extensions. Signed-off-by: Ederson de Souza <ederson.desouza@intel.com>
- Loading branch information
1 parent
d6d136b
commit 48953b0
Showing
19 changed files
with
964 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
.. zephyr:code-sample:: llext-edk | ||
:name: Linkable loadable extensions EDK | ||
|
||
About | ||
***** | ||
|
||
This sample demonstrates how to use the Zephyr LLEXT EDK (Extension Development | ||
Kit). It is composed of one Zephyr application, which provides APIs for the | ||
extensions that it loads. The API provided is a simple publish/subscribe system, | ||
based on Zbus, which extensions use to communicate with each other. | ||
|
||
The application is composed of a subscriber thread, which listens for events | ||
published and republishes then via Zbus to the extensions that are | ||
subscribers. There are four extensions, which are loaded by the application and | ||
run in different contexts. Extensions ``ext1``, ``ext2`` and ``ext3`` run in | ||
userspace, each demonstrating different application and Zephyr API usage, such as | ||
semaphores, spawning threads to listen for events or simply publishing or | ||
subscribing to events. Extension ``kext1`` runs in a kernel thread, albeit similar | ||
to ``ext3``. | ||
|
||
The application also creates different memory domains for each extension, thus | ||
providing some level of isolation - although the kernel one still has access | ||
to all of Zephyr kernel. | ||
|
||
Note that the kernel extension is only available when the EDK is built with | ||
``CONFIG_LLEXT_EDK_USERSPACE_ONLY=n``. | ||
|
||
The application is built using the Zephyr build system. The EDK is built using | ||
the Zephyr build system as well, via ``llext-edk`` target. The EDK is then | ||
extracted and the extensions are built using CMake. | ||
|
||
Finally, the way the application loads the extensions is by including them | ||
during build time, which is not really practical. This sample is about the EDK | ||
providing the ability to build extensions independently from the application. | ||
One could build the extensions in different directories, not related to the | ||
Zephyr application - even on different machines, using only the EDK. At the | ||
limit, one could even imagine a scenario where the extensions are built by | ||
different teams, using the EDK provided by the application developer. | ||
|
||
Building the EDK | ||
**************** | ||
|
||
To build the EDK, use the ``llext-edk`` target. For example: | ||
|
||
.. zephyr-app-commands:: | ||
:zephyr-app: samples/subsys/llext/edk/app | ||
:board: qemu_cortex_r5 | ||
:goals: build llext-edk | ||
:west-args: -p=always | ||
:gen-args: -DSDK_BUILD=1 | ||
:compact: | ||
|
||
Note that the ``SDK_BUILD`` option is necessary to build the EDK initially, | ||
as it prevents the application from trying to load the extensions before | ||
they are built. | ||
|
||
Copy the EDK to some place and extract it: | ||
|
||
.. code-block:: console | ||
mkdir /tmp/edk | ||
cp build/zephyr/llext-edk.tar.xz /tmp/edk | ||
cd /tmp/edk | ||
tar -xf llext-edk.tar.xz | ||
Then set ``LLEXT_EDK_INSTALL_DIR`` to the extracted directory: | ||
|
||
.. code-block:: console | ||
export LLEXT_EDK_INSTALL_DIR=/tmp/edk/llext-edk | ||
This variable is used by the extensions to find the EDK. | ||
|
||
Building the extensions | ||
*********************** | ||
|
||
First, ensure the Zephyr SDK location is available at the environment variable | ||
``ZEPHYR_SDK_INSTALL_DIR``: | ||
|
||
.. code-block:: console | ||
export ZEPHYR_SDK_INSTALL_DIR=</path/to/zephyr-sdk> | ||
As the ``ZEPHYR_SDK_INSTALL_DIR`` is used by the extensions to find the Zephyr SDK. | ||
|
||
To build the extensions, in the ``ext1``, ``ext2``, ``ext3`` and ``kext1`` | ||
directories: | ||
|
||
.. code-block:: console | ||
cmake -B build | ||
make -C build | ||
Building the application | ||
************************ | ||
|
||
Now, build the application, including the extensions, and run it: | ||
|
||
.. zephyr-app-commands:: | ||
:zephyr-app: samples/subsys/llext/edk/app | ||
:board: qemu_cortex_r5 | ||
:goals: build run | ||
:west-args: -p=always | ||
:compact: | ||
|
||
You should see something like: | ||
|
||
.. code-block:: console | ||
[app]Subscriber thread [0x20b28] started. | ||
[app]Loading extension [kext1]. | ||
[app]Thread 0x20840 created to run extension [kext1], at privileged mode. | ||
[k-ext1]Waiting sem | ||
[app]Thread [0x222a0] registered event [0x223c0] | ||
[k-ext1]Waiting event | ||
[app]Loading extension [ext1]. | ||
[app]Thread 0x20a30 created to run extension [ext1], at userspace. | ||
[app]Thread [0x20a30] registered event [0x26060] | ||
[ext1]Waiting event | ||
[app]Loading extension [ext2]. | ||
[app]Thread 0x20938 created to run extension [ext2], at userspace. | ||
[ext2]Publishing tick | ||
[app][subscriber_thread]Got channel tick_chan | ||
[ext1]Got event, reading channel | ||
[ext1]Read val: 0 | ||
[ext1]Waiting event | ||
[k-ext1]Got event, giving sem | ||
[k-ext1]Got sem, reading channel | ||
[k-ext1]Read val: 0 | ||
[k-ext1]Waiting sem | ||
(...) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
cmake_minimum_required(VERSION 3.13.1) | ||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) | ||
|
||
project(app LANGUAGES C) | ||
|
||
target_sources(app PRIVATE src/main.c src/pubsub.c) | ||
zephyr_include_directories(include) | ||
|
||
option(SDK_BUILD "Build without including extension" OFF) | ||
|
||
if (SDK_BUILD) | ||
add_definitions(-DSDK_BUILD) | ||
endif() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
/* | ||
* Copyright (c) 2024 Intel Corporation | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#ifndef _TEST_EDK_H_ | ||
#define _TEST_EDK_H_ | ||
#include <zephyr/kernel.h> | ||
#include <zephyr/toolchain.h> | ||
|
||
#include <stddef.h> | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
enum Channels { | ||
CHAN_TICK = 1, | ||
CHAN_LAST | ||
}; | ||
|
||
struct channel_tick_data { | ||
unsigned long l; | ||
}; | ||
|
||
__syscall int publish(enum Channels channel, void *data, | ||
size_t data_len); | ||
__syscall int receive(enum Channels channel, void *data, | ||
size_t data_len); | ||
__syscall int register_subscriber(enum Channels channel, | ||
struct k_event *evt); | ||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#include <syscalls/app_api.h> | ||
#endif /* _TEST_EDK_H_ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
CONFIG_APPLICATION_DEFINED_SYSCALL=y | ||
CONFIG_USERSPACE=y | ||
CONFIG_LLEXT=y | ||
CONFIG_LLEXT_LOG_LEVEL_WRN=y | ||
|
||
CONFIG_LOG=y | ||
CONFIG_LOG_MODE_IMMEDIATE=y | ||
|
||
CONFIG_MAIN_STACK_SIZE=4096 | ||
|
||
CONFIG_DYNAMIC_OBJECTS=y | ||
CONFIG_DYNAMIC_THREAD=y | ||
CONFIG_DYNAMIC_THREAD_ALLOC=y | ||
CONFIG_DYNAMIC_THREAD_PREFER_ALLOC=y | ||
CONFIG_ZBUS=y | ||
CONFIG_ZBUS_CHANNEL_NAME=y | ||
|
||
CONFIG_LLEXT_HEAP_SIZE=32 | ||
|
||
# Comment/remove to enable kext1. | ||
#CONFIG_LLEXT_EDK_USERSPACE_ONLY=y | ||
|
||
CONFIG_EVENTS=y | ||
#CONFIG_HEAP_MEM_POOL_SIZE=8192 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
common: | ||
tags: llext edk | ||
arch_allow: | ||
- arm | ||
filter: CONFIG_ARCH_HAS_USERSPACE | ||
sample: | ||
description: EDK sample application | ||
name: EDK sample application | ||
tests: | ||
sample.edk.app: | ||
build_only: true | ||
extra_args: SDK_BUILD=1 | ||
tags: edk llext |
Oops, something went wrong.