Zephyr Integration
Zephyr + HeliaAOT + NS-CMSIS-NN (Customer Integration Guide)
This guide assumes you are working in a west workspace created by west init, and that the workspace contains:
- zephyr/ (Zephyr repo)
- modules/ (external Zephyr modules)
- app/ (your application source)
Below is the expected workspace layout; details on how to create each part follow later in this guide.
<ws>/
├── zephyr/
│ ├── west.yml # NOTE: in this environment, west.yml lives inside zephyr/
│ └── ... # Zephyr source tree
├── modules/
│ ├── ns-cmsis-nn/ # NS-CMSIS-NN Zephyr module (checked out or copied)
│ └── helia_aot_nn/ # HeliaAOT generated Zephyr module (checked out or copied)
└── app/
└── helia_aot_app/
├── CMakeLists.txt
├── prj.conf
├── VERSION # optional
└── src/
└── main.c
It also assumes known-good versions: - Zephyr: 4.3 - Zephyr SDK: zephyr-sdk-0.17.4
1) Install prerequisites (quick expectations)
- Install Zephyr and Python dependencies per Zephyr Getting Started.
- Install Zephyr SDK per Zephyr Getting Started.
(Exact host dependency install steps are intentionally omitted here to avoid duplicating upstream Zephyr documentation.)
For official guidance, see:
2) Create or enter a west workspace
- Create or enter an existing west workspace (
west init/west update). - Confirm
zephyr/exists at the workspace root. - Run
west updateafter editingzephyr/west.yml.
3) Generate the HeliaAOT Zephyr module
Run HeliaAOT convert on your model:
helia-aot convert \
--model.path model.tflite \
--module.path ./out \
--module.name helia_aot_nn \
--module.type zephyr
Expected output layout
This command produces:
out/helia_aot_nn/
├── includes-api/
├── src/
├── zephyr/
│ ├── CMakeLists.txt
│ ├── Kconfig
│ └── module.yml
├── LICENSE
└── README.md
Place the module into the workspace
Copy (or move) the generated module into modules/:
4) Add NS-CMSIS-NN to the workspace
You have two supported integration styles: west-managed (recommended for reproducibility) or app-local (useful for quick experiments). Pick one and stay consistent. HeliaAOT-generated models rely on CMSIS-NN kernels provided by ns-cmsis-nn (rather than Tensorflow), which must be available at build time.
Add NS-CMSIS-NN as a project entry in zephyr/west.yml (in this environment, the manifest is under zephyr/).
Example snippet:
remotes:
- name: ambiqai
url-base: git@github.com:AmbiqAI
projects:
- name: ns-cmsis-nn
remote: ambiqai
repo-path: ns-cmsis-nn
path: modules/ns-cmsis-nn
revision: main
Notes:
- If an ambiqai remote already exists, reuse it or rename this one to avoid collisions.
- Prefer pinning revision to a tag or commit SHA instead of main for reproducibility.
Then from <ws>:
This produces:
5) Choose how Zephyr discovers modules: west vs ZEPHYR_EXTRA_MODULES
Zephyr can discover modules in two common ways:
If modules are included as projects: in the manifest, they’re fetched/pinned by west. This is ideal when you want:
- reproducible builds
- clean CI
- a single place to pin known-good revisions
Note: HeliaAOT modules are generated artifacts, so they typically are not fetched from a remote by west. For HeliaAOT-generated modules, follow step 5B (use ZEPHYR_EXTRA_MODULES).
If you want your app to explicitly point to module paths (including locally copied/generated modules), you can set:
ZEPHYR_EXTRA_MODULESin your appCMakeLists.txt
This is convenient for:
- app-local “bring your own module” development
- quickly switching between module variants without editing a manifest
Tradeoff: more manual path management; reproducibility depends on your own process.
6) Create the application
<ws>/app/helia_aot_app/CMakeLists.txt
Below is a pragmatic pattern that works whether modules are west-fetched or copied locally into <ws>/modules.
cmake_minimum_required(VERSION 3.20.0)
# If you are NOT relying on west/module discovery, explicitly list module paths here.
# If modules are already discovered via west manifest, you can remove this block.
list(APPEND ZEPHYR_EXTRA_MODULES
${CMAKE_CURRENT_SOURCE_DIR}/../../modules/ns-cmsis-nn
${CMAKE_CURRENT_SOURCE_DIR}/../../modules/helia_aot_nn
)
# IMPORTANT: must appear before find_package(Zephyr)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(helia_aot_app)
target_sources(app PRIVATE src/main.c)
<ws>/app/helia_aot_app/prj.conf
This file is necessarily board/model dependent. Keep it minimal and add only what you need.
... # Existing configurations
# Enable FPU support
CONFIG_FPU=y
# If multiple threads/ISRs may use MVE/FP:
# CONFIG_FPU_SHARING=y
# Enable printing via UART
CONFIG_PRINTK=y
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y
# Enable NS-CMSIS-NN
CONFIG_NS_CMSIS_NN=y
# Enable all kernels
CONFIG_NS_CMSIS_NN_ALL=y
# -OR- selectively add kernels
# CONFIG_NS_CMSIS_NN_ACTIVATION=y
# CONFIG_NS_CMSIS_NN_BASICMATH=y
# CONFIG_NS_CMSIS_NN_CONCATENATION=y
# CONFIG_NS_CMSIS_NN_CONVOLUTION=y
# CONFIG_NS_CMSIS_NN_FULLYCONNECTED=y
# CONFIG_NS_CMSIS_NN_LSTM=y
# CONFIG_NS_CMSIS_NN_NNSUPPORT=y
# CONFIG_NS_CMSIS_NN_PAD=y
# CONFIG_NS_CMSIS_NN_POOLING=y
# CONFIG_NS_CMSIS_NN_QUANTIZATION=y
# CONFIG_NS_CMSIS_NN_RESHAPE=y
# CONFIG_NS_CMSIS_NN_SOFTMAX=y
# CONFIG_NS_CMSIS_NN_STRIDED_SLICE=y
# CONFIG_NS_CMSIS_NN_SVD=y
# CONFIG_NS_CMSIS_NN_TRANSPOSE=y
# Enable HELIA_AOT_NN module
CONFIG_HELIA_AOT_NN=y
# ^ Notice we use uppercase with hyphens replaced by underscores
<ws>/app/helia_aot_app/src/main.c
Use the generated API from includes-api/ (made available through the module build).
#include "aot_model.h"
#include "aot_common.h"
#include <zephyr/sys/printk.h>
static aot_model_context_t aot_model_ctx;
int main(void)
{
int32_t status = aot_model_init(&aot_model_ctx);
if (status != 0) {
printk("aot_model_init failed: %ld\n", (long)status);
return 0;
}
// TODO: Fill inputs
// Example conceptually:
// memcpy(aot_model_ctx.inputs[0].data, my_input, aot_model_ctx.inputs[0].nbytes);
status = aot_model_run(&aot_model_ctx);
if (status != 0) {
printk("aot_model_run failed: %ld\n", (long)status);
return 0;
}
// TODO: Read outputs
printk("HeliaAOT inference complete\n");
while(1);
}
7) Build
Example:
8) Flash
Note: To view application output, ensure console support is enabled inprj.conf, then connect to the board's console using a serial terminal. For example, on macOS:
9) Common integration checkpoints
-
Confirm both modules are physically present:
-
<ws>/modules/ns-cmsis-nn <ws>/modules/helia_aot_nn-
Confirm HeliaAOT module metadata exists:
-
<ws>/modules/helia_aot_nn/zephyr/module.yml -
If the module is not discovered:
-
ensure
ZEPHYR_EXTRA_MODULESpaths are correct or - ensure the module is included/discoverable via west/module mechanism