1.. zephyr:code-sample:: llext-edk 2 :name: Linkable loadable extensions EDK 3 :relevant-api: llext_apis 4 5 Enable linkable loadable extension development outside the Zephyr tree using 6 LLEXT EDK (Extension Development Kit). 7 8Overview 9******** 10 11This sample demonstrates how to use the Zephyr LLEXT EDK (Extension Development 12Kit). It is composed of one Zephyr application, which provides APIs for the 13extensions that it loads. The provided API is a simple publish/subscribe system, 14based on :ref:`Zbus <zbus>`, which extensions use to communicate with each other. 15 16The application is composed of a subscriber thread, which listens for events 17published and republishes them via Zbus to the extensions that are 18subscribers. There are four extensions, which are loaded by the application and 19run in different contexts. Extensions ``ext1``, ``ext2`` and ``ext3`` run in 20userspace, each demonstrating different application and Zephyr API usage, such as 21semaphores, spawning threads to listen for events or simply publishing or 22subscribing to events. Extension ``kext1`` runs in a kernel thread, albeit similar 23to ``ext3``. 24 25The application also creates different memory domains for each extension, thus 26providing some level of isolation - although the kernel one still has access 27to all of Zephyr kernel. 28 29Note that the kernel extension is only available when the EDK is built with 30the :kconfig:option:`CONFIG_LLEXT_EDK_USERSPACE_ONLY` option disabled. 31 32 33The application is built using the Zephyr build system. The EDK is built using 34the Zephyr build system as well, via ``llext-edk`` target. The EDK is then 35extracted and the extensions are built using CMake. 36 37Finally, the way the application loads the extensions is by including them 38during build time, which is not really practical. This sample is about the EDK 39providing the ability to build extensions independently from the application. 40One could build the extensions in different directories, not related to the 41Zephyr application - even on different machines, using only the EDK. At the 42limit, one could even imagine a scenario where the extensions are built by 43different teams, using the EDK provided by the application developer. 44 45Building the EDK 46**************** 47 48To build the EDK, use the ``llext-edk`` target. For example: 49 50.. zephyr-app-commands:: 51 :zephyr-app: samples/subsys/llext/edk/app 52 :board: qemu_cortex_r5 53 :goals: build llext-edk 54 :west-args: -p=always 55 :compact: 56 57Copy the EDK to some place and extract it: 58 59.. code-block:: console 60 61 mkdir /tmp/edk 62 cp build/zephyr/llext-edk.tar.xz /tmp/edk 63 cd /tmp/edk 64 tar -xf llext-edk.tar.xz 65 66Then set ``LLEXT_EDK_INSTALL_DIR`` to the extracted directory: 67 68.. code-block:: console 69 70 export LLEXT_EDK_INSTALL_DIR=/tmp/edk/llext-edk 71 72This variable is used by the extensions to find the EDK. 73 74Building the extensions 75*********************** 76 77The :envvar:`ZEPHYR_SDK_INSTALL_DIR` environment variable is used by the 78extensions to find the Zephyr SDK, so you need to ensure it's properly set: 79 80.. code-block:: console 81 82 export ZEPHYR_SDK_INSTALL_DIR=</path/to/zephyr-sdk> 83 84To build the extensions, in the ``ext1``, ``ext2``, ``ext3`` and ``kext1`` 85directories: 86 87.. code-block:: console 88 89 cmake -B build 90 make -C build 91 92Alternatively, you can set the ``LLEXT_EDK_INSTALL_DIR`` directly in the 93CMake invocation: 94 95.. code-block:: console 96 97 cmake -B build -DLLEXT_EDK_INSTALL_DIR=/tmp/edk/llext-edk 98 make -C build 99 100Building the application 101************************ 102 103Now, build the application, including the extensions, and run it: 104 105.. zephyr-app-commands:: 106 :zephyr-app: samples/subsys/llext/edk/app 107 :board: qemu_cortex_r5 108 :goals: build run 109 :west-args: -p=always 110 :compact: 111 112You should see something like: 113 114.. code-block:: console 115 116 [app]Subscriber thread [0x20b28] started. 117 [app]Loading extension [kext1]. 118 [app]Thread 0x20840 created to run extension [kext1], at privileged mode. 119 [k-ext1]Waiting sem 120 [app]Thread [0x222a0] registered event [0x223c0] 121 [k-ext1]Waiting event 122 [app]Loading extension [ext1]. 123 [app]Thread 0x20a30 created to run extension [ext1], at userspace. 124 [app]Thread [0x20a30] registered event [0x26060] 125 [ext1]Waiting event 126 [app]Loading extension [ext2]. 127 [app]Thread 0x20938 created to run extension [ext2], at userspace. 128 [ext2]Publishing tick 129 [app][subscriber_thread]Got channel tick_chan 130 [ext1]Got event, reading channel 131 [ext1]Read val: 0 132 [ext1]Waiting event 133 [k-ext1]Got event, giving sem 134 [k-ext1]Got sem, reading channel 135 [k-ext1]Read val: 0 136 [k-ext1]Waiting sem 137 (...) 138