Skip to content
heliaCORE
Getting started
HELIA HUB

Build and run your first kernel

Complete one integration guide first. This example uses the integer activation group and requires no floating-point support, model file, or scratch buffer. Keep the activation group enabled; if you filter source files by data type, include q7 for this function.

Input Operation Expected output
[-8, -1, 0, 3, 7] ReLU: clamp negative values to zero [0, 0, 0, 3, 7]

Save this as first_kernel.c and add it to your firmware’s source list. The inherited arm_relu_q7 API operates on signed 8-bit values in place: negative values become zero and nonnegative values remain unchanged.

first_kernel.c
#include "first_kernel.h"
#include <stdint.h>
#include "arm_nnfunctions.h"
int helia_first_kernel(void)
{
int8_t values[] = {-8, -1, 0, 3, 7};
const int8_t expected[] = {0, 0, 0, 3, 7};
const uint16_t count = sizeof(values) / sizeof(values[0]);
arm_relu_q7(values, count);
for (uint16_t i = 0; i < count; ++i)
{
if (values[i] != expected[i])
{
return 1;
}
}
return 0;
}

The function owns its input/output buffer on the stack. It returns 0 when all output elements match, or 1 on a mismatch. This is a kernel integration check, not an example of running a complete neural network.

Save the declaration beside it in first_kernel.h. The linkage guard lets both C and C++ applications call the C implementation:

first_kernel.h
#ifndef FIRST_KERNEL_H
#define FIRST_KERNEL_H
#ifdef __cplusplus
extern "C" {
#endif
int helia_first_kernel(void);
#ifdef __cplusplus
}
#endif
#endif

This example clamps stored signed values at integer zero. It is not a general affine-quantized activation with an arbitrary zero-point. See data types and quantization before applying activation kernels to model tensors.

For CMake or an NSX CMake application, use your existing firmware target:

Application CMakeLists.txt
target_sources(my_firmware PRIVATE first_kernel.c)

For Zephyr, add it to the application’s app target:

Zephyr application CMakeLists.txt
target_sources(app PRIVATE src/first_kernel.c)

For this Zephyr layout, place both files in src/. For CMSIS-Toolbox, add first_kernel.c to an existing project group’s files list; in an IDE, add it to the application’s source group. Keep the header beside your calling source or add its directory to the application’s include paths.

Include the header in your application:

#include "first_kernel.h"

Inside your existing entry point, after board initialization, call:

volatile int kernel_result = helia_first_kernel();

Build with your normal firmware command, flash using your board’s existing workflow, then inspect kernel_result in the debugger immediately after the call. It should be 0. You can also report the return value through your application’s logging facility. Building and linking alone do not verify the output; execute the call on the target.

Symptom Action
Header not found Check heliaCORE’s include path and the location of first_kernel.h.
Undefined helia_first_kernel Register first_kernel.c and use the shared header for C/C++ linkage.
Undefined arm_relu_q7 Check library linkage, the activation group, and the q7 source filter.
Fault or unexpected result Check CPU/FPU/ABI compatibility, then inspect input and output buffers in the debugger.

For a full model, use heliaAOT or heliaRT. For direct kernel development, continue with build configuration and the API reference, including each kernel’s tensor, quantization, and scratch-buffer requirements.