diff --git a/EdgeImpulse.EI-SDK.pdsc b/EdgeImpulse.EI-SDK.pdsc
index 10bbafc..56d4fec 100644
--- a/EdgeImpulse.EI-SDK.pdsc
+++ b/EdgeImpulse.EI-SDK.pdsc
@@ -5,13 +5,16 @@
EI-SDK
LICENSE-apache-2.0.txt
Edge Impulse SDK
- https://github.com/edgeimpulse/edge-impulse-sdk-pack/releases/download/v1.54.8/
+ https://github.com/edgeimpulse/edge-impulse-sdk-pack/releases/download/v1.55.4/
hello@edgeimpulse.com
https://github.com/edgeimpulse/edge-impulse-sdk-pack.git
-
+
EI-SDK
+
+ EI-SDK
+
EI-SDK
@@ -98,9 +101,6 @@
EI-SDK
-
-
- EI-SDK
@@ -146,12 +146,13 @@
-
+
Edge Impulse SDK
+
@@ -335,6 +336,8 @@
+
+
@@ -348,6 +351,7 @@
+
@@ -389,6 +393,7 @@
+
@@ -624,6 +629,7 @@
+
@@ -661,6 +667,7 @@
+
diff --git a/EdgeImpulse.pidx b/EdgeImpulse.pidx
index 3481163..b8e5c56 100644
--- a/EdgeImpulse.pidx
+++ b/EdgeImpulse.pidx
@@ -2,8 +2,8 @@
EdgeImpulse
https://raw.githubusercontent.com/edgeimpulse/edge-impulse-sdk-pack/main/
- 2024-07-30 10:53:15
+ 2024-08-05 16:39:10
-
+
diff --git a/edgeimpulse/edge-impulse-sdk/classifier/ei_model_types.h b/edgeimpulse/edge-impulse-sdk/classifier/ei_model_types.h
index e181cd8..39754ed 100644
--- a/edgeimpulse/edge-impulse-sdk/classifier/ei_model_types.h
+++ b/edgeimpulse/edge-impulse-sdk/classifier/ei_model_types.h
@@ -42,6 +42,7 @@
#define EI_CLASSIFIER_SYNTIANT 10
#define EI_CLASSIFIER_ONNX_TIDL 11
#define EI_CLASSIFIER_MEMRYX 12
+#define EI_CLASSIFIER_ETHOS_LINUX 13
#define EI_CLASSIFIER_SENSOR_UNKNOWN -1
#define EI_CLASSIFIER_SENSOR_MICROPHONE 1
@@ -149,6 +150,21 @@ typedef struct {
size_t arena_size;
} ei_config_tflite_graph_t;
+typedef struct {
+ uint16_t implementation_version;
+ uint8_t input_datatype;
+ bool input_quantized;
+ float input_scale;
+ float input_zeropoint;
+ uint8_t output_datatype;
+ bool output_quantized;
+ float output_scale;
+ float output_zeropoint;
+ const unsigned char *model;
+ size_t model_size;
+ size_t arena_size;
+} ei_config_ethos_graph_t;
+
typedef struct {
uint16_t implementation_version;
TfLiteStatus (*model_init)(void*(*alloc_fnc)(size_t, size_t));
diff --git a/edgeimpulse/edge-impulse-sdk/classifier/ei_run_classifier.h b/edgeimpulse/edge-impulse-sdk/classifier/ei_run_classifier.h
index d9b0e6f..9921e44 100644
--- a/edgeimpulse/edge-impulse-sdk/classifier/ei_run_classifier.h
+++ b/edgeimpulse/edge-impulse-sdk/classifier/ei_run_classifier.h
@@ -58,6 +58,8 @@
#include "edge-impulse-sdk/classifier/inferencing_engines/onnx_tidl.h"
#elif EI_CLASSIFIER_INFERENCING_ENGINE == EI_CLASSIFIER_MEMRYX
#include "edge-impulse-sdk/classifier/inferencing_engines/memryx.h"
+#elif EI_CLASSIFIER_INFERENCING_ENGINE == EI_CLASSIFIER_ETHOS_LINUX
+#include "edge-impulse-sdk/classifier/inferencing_engines/ethos_linux.h"
#elif EI_CLASSIFIER_INFERENCING_ENGINE == EI_CLASSIFIER_NONE
// noop
#else
diff --git a/edgeimpulse/edge-impulse-sdk/classifier/ei_run_dsp.h b/edgeimpulse/edge-impulse-sdk/classifier/ei_run_dsp.h
index e46612c..00d789e 100644
--- a/edgeimpulse/edge-impulse-sdk/classifier/ei_run_dsp.h
+++ b/edgeimpulse/edge-impulse-sdk/classifier/ei_run_dsp.h
@@ -26,8 +26,16 @@
#include "model-parameters/model_metadata.h"
#if EI_CLASSIFIER_HR_ENABLED
+#if EI_CLASSIFIER_HR_LIB
+// Forward declare only the part of the class we need to link later
+class hr_class {
+public:
+ static DspHandle* create(void* config, float frequency);
+};
+#else
#include "edge-impulse-sdk/dsp/ei_hr.hpp"
#endif
+#endif
#if defined(__cplusplus) && EI_C_LINKAGE == 1
extern "C" {
diff --git a/edgeimpulse/edge-impulse-sdk/classifier/inferencing_engines/ethos_linux.h b/edgeimpulse/edge-impulse-sdk/classifier/inferencing_engines/ethos_linux.h
new file mode 100644
index 0000000..3f162fe
--- /dev/null
+++ b/edgeimpulse/edge-impulse-sdk/classifier/inferencing_engines/ethos_linux.h
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2024 EdgeImpulse Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an "AS
+ * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#ifndef _EI_CLASSIFIER_INFERENCING_ENGINE_ETHOS_LINUX_H_
+#define _EI_CLASSIFIER_INFERENCING_ENGINE_ETHOS_LINUX_H_
+
+#if (EI_CLASSIFIER_INFERENCING_ENGINE == EI_CLASSIFIER_ETHOS_LINUX)
+// check if the model is quantized on the build stage to fail quickly
+#if EI_CLASSIFIER_QUANTIZATION_ENABLED == 0
+#error "Ethos does not support float32 models"
+#endif
+
+#include "model-parameters/model_metadata.h"
+#include
+#include "edge-impulse-sdk/classifier/ei_fill_result_struct.h"
+#include "edge-impulse-sdk/classifier/ei_model_types.h"
+#include "edge-impulse-sdk/porting/ethos-u-driver-stack-imx/driver_library/include/ethosu.hpp"
+#include "edge-impulse-sdk/porting/ethos-u-driver-stack-imx/kernel_driver/include/uapi/ethosu.h"
+
+std::shared_ptr network;
+// by default Device uses /dev/ethosu0
+static EthosU::Device device;
+static bool init_done = false;
+
+bool init_ethos(const uint8_t *model_arr, size_t model_arr_size, bool debug)
+{
+ int ret;
+ try {
+ // eioctl thros exception if ioctl returns negative value
+ ret = device.ioctl(ETHOSU_IOCTL_PING);
+ }
+ catch (EthosU::Exception &e) {
+ ei_printf("ERR: EthosU device not found: %s\n", e.what());
+ return false;
+ }
+
+ try {
+ // eioctl thros exception if ioctl returns negative value
+ ret = device.ioctl(ETHOSU_IOCTL_VERSION_REQ);
+ }
+ catch (EthosU::Exception &e) {
+ ei_printf("ERR: EthosU version request failed: %s\n", e.what());
+ return false;
+ }
+
+ if (debug) {
+ try {
+ EthosU::Capabilities capabilities = device.capabilities();
+ }
+ catch (EthosU::Exception &e) {
+ ei_printf("ERR: EthosU capabilities request failed: %s\n", e.what());
+ return false;
+ }
+
+ // std::cout << "Capabilities:" << std::endl
+ // << "\tversion_status:" << unsigned(capabilities.hwId.versionStatus) << std::endl
+ // << "\tversion:" << capabilities.hwId.version << std::endl
+ // << "\tproduct:" << capabilities.hwId.product << std::endl
+ // << "\tarchitecture:" << capabilities.hwId.architecture << std::endl
+ // << "\tdriver:" << capabilities.driver << std::endl
+ // << "\tmacs_per_cc:" << unsigned(capabilities.hwCfg.macsPerClockCycle) << std::endl
+ // << "\tcmd_stream_version:" << unsigned(capabilities.hwCfg.cmdStreamVersion) << std::endl
+ // << "\tcustom_dma:" << std::boolalpha << capabilities.hwCfg.customDma << std::endl;
+ }
+
+ std::shared_ptr modelBuffer = std::make_shared(device, model_arr_size);
+ // TODO: not sure why we need to do that, but Buffer constructor calls mmap
+ // while resize calls ioct ETHOSU_IOCTL_BUFFER_SET on the ethos device
+ modelBuffer->resize(model_arr_size);
+ std::copy(model_arr, model_arr + model_arr_size, modelBuffer->data());
+
+ // std::shared_ptr networkBuffer = allocAndFill(device, "lamp-plant-int8_vela.tflite");
+ network = std::make_shared(device, modelBuffer);
+
+ if(network->getIfmDims().size() > 1) {
+ ei_printf("ERR: Only single input models are supported\n");
+ return false;
+ }
+
+ init_done = true;
+
+ return true;
+}
+
+EI_IMPULSE_ERROR run_nn_inference(
+ const ei_impulse_t *impulse,
+ ei_feature_t *fmatrix,
+ uint32_t learn_block_index,
+ uint32_t* input_block_ids,
+ uint32_t input_block_ids_size,
+ ei_impulse_result_t *result,
+ void *config_ptr,
+ bool debug)
+{
+ ei_learning_block_config_tflite_graph_t *block_config = (ei_learning_block_config_tflite_graph_t*)config_ptr;
+ ei_config_ethos_graph_t *io_details = ((ei_config_ethos_graph_t*)block_config->graph_config);
+ std::vector> ifm;
+ std::vector> ofm;
+ ei::matrix_t* matrix;
+
+
+ if (!init_done) {
+ if(!init_ethos(io_details->model, io_details->model_size, debug)) {
+ return EI_IMPULSE_DEVICE_INIT_ERROR;
+ }
+ }
+
+ // so far only single input models are supported
+ // get the size of the first input tensor
+ auto ifmSize = network->getIfmDims()[0];
+ // create a buffer for the input tensor
+ std::shared_ptr buffer = std::make_shared(device, ifmSize);
+ // resize the buffer to the size of the input tensor
+ // TODO: not sure if we need to call it, but the reference code does
+ buffer->resize(ifmSize);
+ // // inputType is an enum TensorType
+ // auto inputType = network->getIfmTypes()[0];
+ // // inputShape is a vecor of dims
+ // auto inputShape = network->getIfmShapes()[0];
+
+ // get the matrix with input features
+ for (size_t i = 0; i < input_block_ids_size; i++) {
+#if EI_CLASSIFIER_SINGLE_FEATURE_INPUT == 0
+ uint16_t cur_mtx = input_block_ids[i];
+ matrix = NULL;
+
+ if (!find_mtx_by_idx(fmatrix, &matrix, cur_mtx, impulse->dsp_blocks_size + impulse->learning_blocks_size)) {
+ ei_printf("ERR: Cannot find matrix with id %zu\n", cur_mtx);
+ return EI_IMPULSE_INVALID_SIZE;
+ }
+#else
+ matrix = fmatrix[0].matrix;
+#endif
+ }
+
+ if(ifmSize != matrix->rows * matrix->cols) {
+ ei_printf("ERR: Input size mismatch\n");
+ return EI_IMPULSE_INVALID_SIZE;
+ }
+
+ // copy rescale the input features to int8 and copy to input buffer
+ for (size_t i = 0; i < ifmSize; i++) {
+ buffer->data()[i] = (int8_t)((matrix->buffer[i] / io_details->input_scale) + io_details->input_zeropoint);
+ }
+
+ // put the data into the input tensor
+ ifm.push_back(buffer);
+
+ // create a buffer for the output tensor
+ auto ofmSize = network->getOfmDims()[0];
+ ofm.push_back(std::make_shared(device, ofmSize));
+
+ // get start time of the inference
+ uint64_t ctx_start_us = ei_read_timer_us();
+
+ // start inference
+ EthosU::Inference inference(network, ifm.begin(), ifm.end(), ofm.begin(), ofm.end());
+
+ // wait in 1 second (wait gets nanoseconds)
+ if (inference.wait(1000 * 1000 * 1000)) {
+ return EI_IMPULSE_INFERENCE_ERROR;
+ }
+
+ // get end time of the inference
+ uint64_t ctx_end_us = ei_read_timer_us();
+
+ // check if inference ended successfully
+ if (inference.status() != EthosU::InferenceStatus::OK) {
+ return EI_IMPULSE_INFERENCE_ERROR;
+ }
+
+ // calculate inference time
+ result->timing.classification_us = ctx_end_us - ctx_start_us;
+ result->timing.classification = (int)(result->timing.classification_us / 1000);
+
+ // get output data from the output tensor
+ auto data = inference.getOfmBuffers()[0]->data();
+
+ EI_IMPULSE_ERROR fill_res = EI_IMPULSE_OK;
+
+ if(block_config->object_detection) {
+ switch (block_config->object_detection_last_layer) {
+ case EI_CLASSIFIER_LAST_LAYER_FOMO: {
+ fill_res = fill_result_struct_i8_fomo(
+ impulse,
+ block_config,
+ result,
+ (int8_t*)data,
+ io_details->output_zeropoint,
+ io_details->output_scale,
+ impulse->fomo_output_size,
+ impulse->fomo_output_size);
+ break;
+ }
+ case EI_CLASSIFIER_LAST_LAYER_SSD: {
+ ei_printf("ERR: MobileNet SSD models are not supported by Ethos\n");
+ return EI_IMPULSE_LAST_LAYER_NOT_SUPPORTED;
+ }
+ case EI_CLASSIFIER_LAST_LAYER_YOLOV5:
+ case EI_CLASSIFIER_LAST_LAYER_YOLOV5_V5_DRPAI: {
+ int version = block_config->object_detection_last_layer == EI_CLASSIFIER_LAST_LAYER_YOLOV5_V5_DRPAI ?
+ 5 : 6;
+
+ if (network->getOfmTypes()[0] == EthosU::TensorType_INT8) {
+ fill_res = fill_result_struct_quantized_yolov5(
+ impulse,
+ block_config,
+ result,
+ version,
+ (int8_t*)data,
+ io_details->output_zeropoint,
+ io_details->output_scale,
+ impulse->tflite_output_features_count,
+ debug);
+ }
+ else if (network->getOfmTypes()[0] == EthosU::TensorType_UINT8) {
+ fill_res = fill_result_struct_quantized_yolov5(
+ impulse,
+ block_config,
+ result,
+ version,
+ (uint8_t*)data,
+ io_details->output_zeropoint,
+ io_details->output_scale,
+ impulse->tflite_output_features_count,
+ debug);
+ }
+ else {
+ ei_printf("ERR: Invalid output type (%d) for YOLOv5 last layer\n", network->getOfmTypes()[0]);
+ return EI_IMPULSE_LAST_LAYER_NOT_SUPPORTED;
+ }
+ break;
+ }
+ case EI_CLASSIFIER_LAST_LAYER_YOLOX:
+ case EI_CLASSIFIER_LAST_LAYER_YOLOV7:
+ default: {
+ ei_printf("ERR: Object Detection layer (%d) not supported\n", block_config->object_detection_last_layer);
+ return EI_IMPULSE_LAST_LAYER_NOT_SUPPORTED;
+ }
+ }
+ }
+ else {
+ fill_res = fill_result_struct_i8(impulse, result, (int8_t*)data, io_details->output_zeropoint, io_details->output_scale, debug);
+ }
+
+ return fill_res;
+}
+
+#endif // (EI_CLASSIFIER_INFERENCING_ENGINE == EI_CLASSIFIER_ETHOS_LINUX)
+#endif // _EI_CLASSIFIER_INFERENCING_ENGINE_ETHOS_LINUX_H_
diff --git a/edgeimpulse/edge-impulse-sdk/dsp/returntypes.h b/edgeimpulse/edge-impulse-sdk/dsp/returntypes.h
index a7e7191..d7906ac 100644
--- a/edgeimpulse/edge-impulse-sdk/dsp/returntypes.h
+++ b/edgeimpulse/edge-impulse-sdk/dsp/returntypes.h
@@ -41,6 +41,8 @@ typedef enum {
EI_IMPULSE_INVALID_SIZE = -24, /**
+#include
+
+// Redirect TFLite DebugLog to ei_printf
+#if defined(__cplusplus) && EI_C_LINKAGE == 1
+extern "C"
+#endif // defined(__cplusplus) && EI_C_LINKAGE == 1
+void DebugLog(const char* s) {
+ ei_printf("%s", s);
+}
+
+#endif
diff --git a/edgeimpulse/edge-impulse-sdk/porting/clib/ei_classifier_porting.cpp b/edgeimpulse/edge-impulse-sdk/porting/clib/ei_classifier_porting.cpp
new file mode 100644
index 0000000..0ff802b
--- /dev/null
+++ b/edgeimpulse/edge-impulse-sdk/porting/clib/ei_classifier_porting.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2022 EdgeImpulse Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an "AS
+ * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "edge-impulse-sdk/porting/ei_classifier_porting.h"
+#if EI_PORTING_CLIB == 1
+#include
+#include
+
+__attribute__((weak)) EI_IMPULSE_ERROR ei_run_impulse_check_canceled() {
+ return EI_IMPULSE_OK;
+}
+
+/**
+ * Cancelable sleep, can be triggered with signal from other thread
+ */
+__attribute__((weak)) EI_IMPULSE_ERROR ei_sleep(int32_t time_ms) {
+ return EI_IMPULSE_OK;
+}
+
+uint64_t ei_read_timer_ms() {
+ return ei_read_timer_us() / 1000;
+}
+
+uint64_t ei_read_timer_us() {
+ return 0;
+}
+
+__attribute__((weak)) void ei_printf(const char *format, ...) {
+ va_list myargs;
+ va_start(myargs, format);
+ vprintf(format, myargs);
+ va_end(myargs);
+}
+
+__attribute__((weak)) void ei_printf_float(float f) {
+ ei_printf("%f", f);
+}
+
+__attribute__((weak)) void ei_putchar(char data)
+{
+ putchar(data);
+}
+
+__attribute__((weak)) char ei_getchar(void)
+{
+ return getchar();
+}
+
+__attribute__((weak)) void *ei_malloc(size_t size) {
+ return malloc(size);
+}
+
+__attribute__((weak)) void *ei_calloc(size_t nitems, size_t size) {
+ return calloc(nitems, size);
+}
+
+__attribute__((weak)) void ei_free(void *ptr) {
+ free(ptr);
+}
+
+#if defined(__cplusplus) && EI_C_LINKAGE == 1
+extern "C"
+#endif
+__attribute__((weak)) void DebugLog(const char* s) {
+ ei_printf("%s", s);
+}
+
+#endif // EI_PORTING_CLIB == 1
diff --git a/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/LICENSE-GPL-2.0.txt b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/LICENSE-GPL-2.0.txt
new file mode 100644
index 0000000..d159169
--- /dev/null
+++ b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/LICENSE-GPL-2.0.txt
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ , 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/LICENSE.txt b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/LICENSE.txt
new file mode 100644
index 0000000..8dada3e
--- /dev/null
+++ b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/LICENSE.txt
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/Linux-syscall-note b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/Linux-syscall-note
new file mode 100644
index 0000000..adbe756
--- /dev/null
+++ b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/Linux-syscall-note
@@ -0,0 +1,24 @@
+SPDX-Exception-Identifier: Linux-syscall-note
+SPDX-URL: https://spdx.org/licenses/Linux-syscall-note.html
+SPDX-Licenses: GPL-2.0, GPL-2.0+, GPL-1.0+, LGPL-2.0, LGPL-2.0+, LGPL-2.1, LGPL-2.1+, GPL-2.0-only, GPL-2.0-or-later
+Usage-Guide:
+ This exception is used together with one of the above SPDX-Licenses
+ to mark user space API (uapi) header files so they can be included
+ into non GPL compliant user space application code.
+ To use this exception add it with the keyword WITH to one of the
+ identifiers in the SPDX-Licenses tag:
+ SPDX-License-Identifier: WITH Linux-syscall-note
+License-Text:
+
+ NOTE! This copyright does *not* cover user programs that use kernel
+ services by normal system calls - this is merely considered normal use
+ of the kernel, and does *not* fall under the heading of "derived work".
+ Also note that the GPL below is copyrighted by the Free Software
+ Foundation, but the instance of code that it refers to (the Linux
+ kernel) is copyrighted by me and others who actually wrote it.
+
+ Also note that the only valid version of the GPL as far as the kernel
+ is concerned is _this_ particular version of the license (ie v2, not
+ v2.2 or v3.x or whatever), unless explicitly otherwise stated.
+
+ Linus Torvalds
diff --git a/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/README.md b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/README.md
new file mode 100644
index 0000000..d062431
--- /dev/null
+++ b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/README.md
@@ -0,0 +1,23 @@
+# Linux driver stack for Arm(R) Ethos(TM)-U
+
+The driver was imported from [The Ethos-U Driver Stack iMX](https://github.com/nxp-imx/ethos-u-driver-stack-imx/tree/2acb7e2626fe3ff8764019e385829105a6e210bb)
+
+The [most recent version](https://github.com/nxp-imx/ethos-u-driver-stack-imx/tree/lf-6.6.3_1.0.0)
+
+# Licenses
+
+The kernel drivers are provided under a GPL v2 license. All other software
+componantes are provided under an Apache 2.0 license.
+
+Please see [LICENSE-APACHE-2.0.txt](LICENSE-APACHE-2.0.txt),
+[LICENSE-GPL-2.0.txt](LICENSE-GPL-2.0.txt) and [Linux-syscall-note](Linux-syscall-note)
+for more information.
+
+# Security
+
+Please see [Security](SECURITY.md).
+
+# Trademark notice
+
+Arm, Cortex and Ethos are registered trademarks of Arm Limited (or its
+subsidiaries) in the US and/or elsewhere.
diff --git a/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/SCR.txt b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/SCR.txt
new file mode 100644
index 0000000..4f2e390
--- /dev/null
+++ b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/SCR.txt
@@ -0,0 +1,39 @@
+NXP Software Content Register
+
+Package: ethos-u-driver-stack-imx.git
+Outgoing License: Apache-2.0
+License File: LICENSE.txt
+Type of Content: source
+Description and comments: ethos-u-driver-stack is the user space driver library for ethos-u NPU on iMX93 platform
+Release Location: https://github.com/nxp-imx/ethos-u-driver-stack-imx
+Origin: NXP (BSD-3-Clause)
+ ARM Limited ethos-u-linux-driver-stack v23.08 (Apache-2.0) - https://git.mlplatform.org/ml/ethos-u/ethos-u-linux-driver-stack.git
+
+
+--------------------------------------------
+Included kernel header file
+--------------------------------------------
+Component: kernel_driver inteface header file
+Outgoing License: GPL-2.0-only WITH Linux-syscall-note
+License File: LICENSE-GPL-2.0.txt and Linux-syscall-note
+Package Category: Ethos-u Linux kernel driver header file
+Type of Content: header file
+Description and comments: Linux kernel driver header file, the driver stack will include this header
+ file to use linux kernel syscall.
+Origin: ARM ethos-u-linux-driver-stack v23.08 (Apache-2.0) - https://git.mlplatform.org/ml/ethos-u/ethos-u-linux-driver-stack.git
+File location: kernel_driver/include/ethos-u.h
+
+--------------------------------------------
+Auto generated header file by flatbuffers
+--------------------------------------------
+Component: flatbuffers header file
+Outgoing License: Apache-2.0
+License File: LICENSE.txt
+Package Category: Auto generated header file by flatbuffers
+Type of Content: header file
+Description and comments: FlatBuffers is a cross platform serialization library architected for maximum memory efficiency
+Origin: Google flatbuffers 1.12.0 (Apache-2.0) - https://github.com/google/flatbuffers
+File location: driver_library/src/autogen/tflite_schema.hpp
+
+
+
diff --git a/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/SECURITY.md b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/SECURITY.md
new file mode 100644
index 0000000..29c6ce4
--- /dev/null
+++ b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/SECURITY.md
@@ -0,0 +1,85 @@
+# Security
+
+If you believe you have identified a security related issue or vulnerability,
+then we encourage you to responsibly disclose it to us as soon as possible.
+
+## Reporting vulnerabilities
+
+Arm takes security issues seriously and welcomes feedback from researchers and
+the security community in order to improve the security of its products and
+services. We operate a coordinated disclosure policy for disclosing
+vulnerabilities and other security issues.
+
+Security issues can be complex and one single timescale doesn't fit all
+circumstances. We will make best endeavours to inform you when we expect
+security notifications and fixes to be available and facilitate coordinated
+disclosure when notifications and patches/mitigations are available.
+
+### Report
+
+For all security issues, contact Arm by email at
+[arm-security@arm.com](mailto:arm-security@arm.com). In the body of the email
+include as much information as possible about the issue or vulnerability and any
+additional contact details.
+
+### Secure submission using PGP
+
+We support and encourage secure submission of vulnerability reports using PGP,
+using the key below. If you would like replies to be encrypted, please provide
+your own public key through a secure mechanism.
+
+~~~none
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+mQINBFr7/RMBEACjHR5QZL/z1t2aLCRNXLE4KJiQmCo7edU5Be+7MTjIJDzZNu68
+lNEUYRoLexeayif8eC4T19bUsSbGpxHiYsFFjV8ewLXDyDJRRuaBGPfQ5rn/mE6X
+Nvu+9Pputr+mB1R3CXcvrNkhmzPkK7zVM15oeyBMhogqPssuT4OeMduQdip8smfK
+xTMk91RrJTLb+G3eE1tf+81kXBYvzp2e24Sn0/VeYe0IWnBobjVBZk3TmcYxDvz5
+Y47fU9V6cNj3Zq4VYrgxuLoFCA2VtetyiFQm5IYa3Bt3SWcAwihr8nbR2HoNdWyA
+u8wJYYVzSq3hvT5l/IjTHxEcY+6RBq8poDSsftzvX386u9hmw7sJQFlTw6/pUjdr
+gbsZ2ZzRBzKtU17ercpn4kU6VgVP3WRB5HiTFFkEpZuqAznOYaHbMq4dfd/g7Quq
+C0VTbWiJnhku2i+g4BdHHRDtIF6U3aVQAfbrDb1LjVTa65p5ULOeY3HRAWtMNtu/
+Cj8cD98JDanzXtcnisds8vMQ8LZ6iMFChEnF8K4V0eLw9Ju6CMNiFYY7SEBndD/H
+M4KcU4li7mROSbJcshgEbe1SYkxdMuI9eY4DNYxl3VjxoPUGzeqXo/ADFKE9bHsi
+GTyEoij4ku0HspLVKnYHXn/LqHGwEcwjF8zphS+w5cn/e01akYwz5EVSQwARAQAB
+tB1Bcm0gU3VwcG9ydCA8c3VwcG9ydEBhcm0uY29tPokCTgQTAQgAOBYhBN9zqDwZ
+RL/vF0ihcdfNKdz4bBRiBQJa+/0TAhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheA
+AAoJENfNKdz4bBRibK0P/jLlJR/QYypcjb+8BnHT9tCDgcV2KFYXS15VpbSNviN9
+Xs/UOnSadoGUMGCXDyb1PRNn98yUn7JlNR9rtsqPRmkpbo5cuw46ehgxjVlfcHnk
+CttaE8Davx6zo0fyrBib2+oVVW8usi9+uRK4vhhPUicO3oXwzldsVFz+RbpubZxc
+Bg/CZ+dQ2jMKOv1zDtInOG6OBnbQZRAeiWXgGhcIoPZ4zBQOi8nr0+bLcfvMeZi2
+uz6uKnylpXwZbl4ijcG8MKV/ei+7du+SzA9NY0WOT2g3FXDREWUhjKs8bmEZgIx4
+QgvDNpxAUThF+TqQ7zrsA8nT8POvDD0MhN/Z+A3QdPTdcaZFaXzIdxbDg+0FKmzu
+OgtQBH4C01RWrkmZlhO5w7/Qjt0vLlhfyQIL9BW/HeEPtjnH2Hnq8xYnZhlVqJEh
+FJU7F9sMvyiJiKviobFTd6AmpVkhxhcJ3k2L2C03imTsmUwAoejQCXwiYcOhyQ2t
+Z9Nk8YIZTEw2urGFi4HSQPwPq2j/2j7ABJ4rlzJvO6vs5ppGkumvzIIP9JnpVXbp
+wcbK6Ev6KdkX4s14Mzd6Hsd8LpL8t5nHhxUey6G0xKe2eSlHVm5Mlfhoete9UmIZ
+dzIOZkgTgWXlYXRIxwGQ2Pss7pURtofykvLklq4jcobQuHxurl9cteodETfbWk/J
+uQINBFr7/RMBEADWZG8eqt5D22g3T7ehnH/T3fuTX8LPUBnODMWGAEUY8uv64To8
+46odvrXFgWBgCf0sROEyJchc3SGLyR9S4lJsVJRde3QLN3WZkHlB4pSn4IQHFyQd
+wsLQi+S9uggHMPlQ6MNvc5n0P3k5bT9fLUmtJWJ3QVjW7k963ZXpzf1zbQJqs30w
+rlqGUZllfRoYQTfcYxFEaUFhwRJ//skNImWH8Vz+PTnqg2zRtFn3usrBV4GpNvsM
+6jy+YEsSvUa7IY8k4wpPzEhIfqDjGbZxFSQ1H1G+mLUL+DD7oGffej/ZoC86TIdM
+p6ew1rGhJdQBLh9nx+1ADOLWjNo2R0h60u7VR5q/K6V4fwWmeGFipPXZCD92I+nR
+t/cjznwNyD/6J9YrBMF7mbGrS1TyfLaLt4tpdcBnsgqDTodd5OmG65mroXsg/lNO
+7YZdecLZ34krfaLrWTtKkqULXbppB+uQvbVj8p8ONRImn6bZ+iAhnNaH9wJ06ico
+b1F0imJ2SJWnFr6PzPRr0gPStLgu9wrRKheaORwF/H/HxSyPZxNVxFqu81q518A/
+plhub9INQLaxHf/TTjXpqZCcfdNTYUAW8rwbQfW9doSIT4lHY8bJXktb6BsVjkFj
+PzDeYpXeOoTWetQqsEuTdg/F+qg041QBLtNj9Lr3Vy3StgMciRUIP8m0XwARAQAB
+iQI2BBgBCAAgFiEE33OoPBlEv+8XSKFx180p3PhsFGIFAlr7/RMCGwwACgkQ180p
+3PhsFGLWMA//V/XKrnI2YBh/SptUrgg7knPXva45bb7tGSH1fJg8f/wqycOSFFCY
+ES45boA5jlQ3z8uw6BYCz5KeOucGhxAMw+x5EDdxZ33ksY5zqXB35WaMXzEwGYYb
+E113/yhOsTbzu4bBKABSXbJO98MdAWvWpyCpp2MHIR3S9+ycM7/FMZ5xi3czZNRg
+9+WZP+7W4qWhJptQ0kBh5C3N/tiltju5WQ2Y7XIn+5dMOJdtseFS7CNerxXZGAtH
+nfRxaD/4ENdbWOwaVJiVW7+ioUJz09OWgy0gLYSDW+hciDnW1QAaJLpdAbniGZ0S
+JsTmaZla8JnUKqZPgbFfA2OcnH9H+DWc0pHv17c5tJzTMP7rgirgGRX/U2LOzmFZ
+1UxjQj5nn3Oa5frXbIAzb8xKiR0VDaquCM/3sti1AesYiS0Gw0Sqnw8qpFypgFXN
+CKVgYXppIT+TmbDbNJDOB2UycxeI4vbiBwU8fI4qSpW12WsGdAJt/rx3UsyhZ+02
+4aSqDHzhJmtDPQ6lnaKe1fUkC90tgp8loVGmriWQx82jAQMqATVjIklTpE4vm00f
+ocQIWOKEE90mKNEoV6rNbfl5QevmapTVdV/pmrRBzhbsa1uAUS4HZdH0Nf/OXEyv
+yYCr2gCFPymkkRYhPr2w5EgbWyzLaBIwqjyIbXaveuB3DYi2Lhbf64I=
+=EaN7
+-----END PGP PUBLIC KEY BLOCK-----
+~~~
+
+For more information visit
+
\ No newline at end of file
diff --git a/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/driver_library/include/ethosu.hpp b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/driver_library/include/ethosu.hpp
new file mode 100644
index 0000000..c361db4
--- /dev/null
+++ b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/driver_library/include/ethosu.hpp
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) 2020-2022 Arm Limited.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+#define DEFAULT_ARENA_SIZE_OF_MB 16
+#define ETHOSU_PMU_EVENT_MAX 4
+
+/*
+ *The following undef are necessary to avoid clash with macros in GNU C Library
+ * if removed the following warning/error are produced:
+ *
+ * In the GNU C Library, "major" ("minor") is defined
+ * by . For historical compatibility, it is
+ * currently defined by as well, but we plan to
+ * remove this soon. To use "major" ("minor"), include
+ * directly. If you did not intend to use a system-defined macro
+ * "major" ("minor"), you should undefine it after including .
+ */
+#undef major
+#undef minor
+
+namespace EthosU {
+
+class Exception : public std::exception {
+public:
+ Exception(const char *msg);
+ virtual ~Exception() throw();
+ virtual const char *what() const throw();
+
+private:
+ std::string msg;
+};
+
+/**
+ * Sematic Version : major.minor.patch
+ */
+class SemanticVersion {
+public:
+ SemanticVersion(uint32_t _major = 0, uint32_t _minor = 0, uint32_t _patch = 0) :
+ major(_major), minor(_minor), patch(_patch){};
+
+ bool operator==(const SemanticVersion &other);
+ bool operator<(const SemanticVersion &other);
+ bool operator<=(const SemanticVersion &other);
+ bool operator!=(const SemanticVersion &other);
+ bool operator>(const SemanticVersion &other);
+ bool operator>=(const SemanticVersion &other);
+
+ uint32_t major;
+ uint32_t minor;
+ uint32_t patch;
+};
+
+std::ostream &operator<<(std::ostream &out, const SemanticVersion &v);
+
+/*
+ * Hardware Identifier
+ * @versionStatus: Version status
+ * @version: Version revision
+ * @product: Product revision
+ * @architecture: Architecture revison
+ */
+struct HardwareId {
+public:
+ HardwareId(uint32_t _versionStatus,
+ const SemanticVersion &_version,
+ const SemanticVersion &_product,
+ const SemanticVersion &_architecture) :
+ versionStatus(_versionStatus),
+ version(_version), product(_product), architecture(_architecture) {}
+
+ uint32_t versionStatus;
+ SemanticVersion version;
+ SemanticVersion product;
+ SemanticVersion architecture;
+};
+
+/*
+ * Hardware Configuration
+ * @macsPerClockCycle: MACs per clock cycle
+ * @cmdStreamVersion: NPU command stream version
+ * @customDma: Custom DMA enabled
+ */
+struct HardwareConfiguration {
+public:
+ HardwareConfiguration(uint32_t _macsPerClockCycle, uint32_t _cmdStreamVersion, bool _customDma) :
+ macsPerClockCycle(_macsPerClockCycle), cmdStreamVersion(_cmdStreamVersion), customDma(_customDma) {}
+
+ uint32_t macsPerClockCycle;
+ uint32_t cmdStreamVersion;
+ bool customDma;
+};
+
+/**
+ * Device capabilities
+ * @hwId: Hardware
+ * @driver: Driver revision
+ * @hwCfg Hardware configuration
+ */
+class Capabilities {
+public:
+ Capabilities(const HardwareId &_hwId, const HardwareConfiguration &_hwCfg, const SemanticVersion &_driver) :
+ hwId(_hwId), hwCfg(_hwCfg), driver(_driver) {}
+
+ HardwareId hwId;
+ HardwareConfiguration hwCfg;
+ SemanticVersion driver;
+};
+
+class Device {
+public:
+ Device(const char *device = "/dev/ethosu0");
+ virtual ~Device() noexcept(false);
+
+ int ioctl(unsigned long cmd, void *data = nullptr) const;
+ Capabilities capabilities() const;
+
+private:
+ int fd;
+};
+
+class Buffer {
+public:
+ Buffer(const Device &device, const size_t capacity);
+ virtual ~Buffer() noexcept(false);
+
+ size_t capacity() const;
+ void clear() const;
+ char *data() const;
+ void resize(size_t size, size_t offset = 0) const;
+ size_t offset() const;
+ size_t size() const;
+
+ int getFd() const;
+
+private:
+ int fd;
+ char *dataPtr;
+ const size_t dataCapacity;
+};
+
+class Network {
+public:
+ Network(const Device &device, std::shared_ptr &buffer);
+ Network(const Device &device, const unsigned index);
+ virtual ~Network() noexcept(false);
+
+ int ioctl(unsigned long cmd, void *data = nullptr);
+ std::shared_ptr getBuffer();
+ const std::vector &getIfmDims() const;
+ size_t getIfmSize() const;
+ const std::vector &getOfmDims() const;
+ size_t getOfmSize() const;
+
+ size_t getInputCount() const;
+ size_t getOutputCount() const;
+ int32_t getInputDataOffset(int index);
+ int32_t getOutputDataOffset(int index);
+ const std::vector> &getIfmShapes() const;
+ const std::vector> &getOfmShapes() const;
+ const std::vector &getIfmTypes() const;
+ const std::vector &getOfmTypes() const;
+ const Device &getDevice() const;
+ bool isVelaModel() const;
+
+private:
+ void collectNetworkInfo();
+
+ int fd;
+ std::shared_ptr buffer;
+ std::vector ifmDims;
+ std::vector ofmDims;
+ std::vector ifmDataOffset;
+ std::vector ofmDataOffset;
+ std::vector> ifmShapes;
+ std::vector> ofmShapes;
+ std::vector ifmTypes;
+ std::vector ofmTypes;
+ const Device &device;
+ bool _isVelaModel;
+};
+
+enum class InferenceStatus {
+ OK,
+ ERROR,
+ RUNNING,
+ REJECTED,
+ ABORTED,
+ ABORTING,
+};
+
+std::ostream &operator<<(std::ostream &out, const InferenceStatus &v);
+
+class Inference {
+public:
+ template
+ Inference(const std::shared_ptr &network,
+ const T &ifmBegin,
+ const T &ifmEnd,
+ const T &ofmBegin,
+ const T &ofmEnd) :
+ network(network) {
+ std::copy(ifmBegin, ifmEnd, std::back_inserter(ifmBuffers));
+ std::copy(ofmBegin, ofmEnd, std::back_inserter(ofmBuffers));
+ std::vector counterConfigs = initializeCounterConfig();
+
+ // Init tensor arena buffer
+ size_t arena_buffer_size = DEFAULT_ARENA_SIZE_OF_MB << 20;
+ arenaBuffer = std::make_shared(network->getDevice(), arena_buffer_size);
+ arenaBuffer->resize(arena_buffer_size);
+
+ create(counterConfigs, false);
+ }
+ template
+ Inference(const std::shared_ptr &network,
+ const T &ifmBegin,
+ const T &ifmEnd,
+ const T &ofmBegin,
+ const T &ofmEnd,
+ const U &counters,
+ bool enableCycleCounter) :
+ network(network) {
+ std::copy(ifmBegin, ifmEnd, std::back_inserter(ifmBuffers));
+ std::copy(ofmBegin, ofmEnd, std::back_inserter(ofmBuffers));
+ std::vector counterConfigs = initializeCounterConfig();
+
+ if (counters.size() > counterConfigs.size())
+ throw EthosU::Exception("PMU Counters argument to large.");
+
+ // Init tensor arena buffer
+ size_t arena_buffer_size = DEFAULT_ARENA_SIZE_OF_MB << 20;
+ arenaBuffer = std::make_shared(network->getDevice(), arena_buffer_size);
+ arenaBuffer->resize(arena_buffer_size);
+
+ std::copy(counters.begin(), counters.end(), counterConfigs.begin());
+ create(counterConfigs, enableCycleCounter);
+ }
+
+ template
+ Inference(const std::shared_ptr &network,
+ const T &arenaBuffer,
+ const U &counters,
+ bool enableCycleCounter) :
+ network(network), arenaBuffer(arenaBuffer) {
+
+ std::vector counterConfigs = initializeCounterConfig();
+
+ if (counters.size() > counterConfigs.size())
+ throw EthosU::Exception("PMU Counters argument to large.");
+
+ std::copy(counters.begin(), counters.end(), counterConfigs.begin());
+ create(counterConfigs, enableCycleCounter);
+ }
+
+
+ virtual ~Inference() noexcept(false);
+
+ bool wait(int64_t timeoutNanos = -1) const;
+ const std::vector getPmuCounters() const;
+ uint64_t getCycleCounter() const;
+ bool cancel() const;
+ InferenceStatus status() const;
+ int getFd() const;
+ const std::shared_ptr getNetwork() const;
+ std::vector> &getIfmBuffers();
+ std::vector> &getOfmBuffers();
+
+ static uint32_t getMaxPmuEventCounters();
+
+ char* getInputData(int index = 0);
+ char* getOutputData(int index = 0);
+
+private:
+ void create(std::vector &counterConfigs, bool enableCycleCounter);
+ std::vector initializeCounterConfig();
+
+ int fd;
+ const std::shared_ptr network;
+ std::vector> ifmBuffers;
+ std::vector> ofmBuffers;
+ std::shared_ptr arenaBuffer;
+};
+
+struct TensorInfo{
+ int type;
+ std::vector shape;
+};
+
+//Define tflite::TensorType here
+enum TensorType{
+ TensorType_FLOAT32 = 0,
+ TensorType_FLOAT16 = 1,
+ TensorType_INT32 = 2,
+ TensorType_UINT8 = 3,
+ TensorType_INT64 = 4,
+ TensorType_STRING = 5,
+ TensorType_BOOL = 6,
+ TensorType_INT16 = 7,
+ TensorType_COMPLEX64 = 8,
+ TensorType_INT8 = 9,
+ TensorType_FLOAT64 = 10,
+ TensorType_MIN = TensorType_FLOAT32,
+ TensorType_MAX = TensorType_FLOAT64
+
+};
+
+class Interpreter {
+public:
+ Interpreter(const char *model, const char *device = "/dev/ethosu0",
+ int64_t arenaSizeOfMB = DEFAULT_ARENA_SIZE_OF_MB);
+ Interpreter(const std::string &model) : Interpreter(model.c_str()) {}
+
+ void SetPmuCycleCounters(std::vector counters, bool enableCycleCounter = true);
+ std::vector GetPmuCounters();
+ uint64_t GetCycleCounter();
+
+ void Invoke(int64_t timeoutNanos = 60000000000);
+
+ template
+ T* typed_input_buffer(int index) {
+ int32_t offset = network->getInputDataOffset(index);
+ return (T*)(arenaBuffer->data() + offset);
+ }
+
+ template
+ T* typed_output_buffer(int index) {
+ int32_t offset = network->getOutputDataOffset(index);
+ return (T*)(arenaBuffer->data() + offset);
+ }
+
+ std::vector GetInputInfo();
+ std::vector GetOutputInfo();
+
+private:
+ Device device;
+ std::shared_ptr networkBuffer;
+ std::shared_ptr arenaBuffer;
+ std::shared_ptr network;
+ std::shared_ptr inference;
+
+ int64_t arenaSizeOfMB;
+ std::vector pmuCounters;
+ bool enableCycleCounter;
+};
+
+} // namespace EthosU
diff --git a/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/driver_library/src/ethosu.cpp b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/driver_library/src/ethosu.cpp
new file mode 100644
index 0000000..0393a05
--- /dev/null
+++ b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/driver_library/src/ethosu.cpp
@@ -0,0 +1,732 @@
+/*
+ * Copyright (c) 2020-2022 Arm Limited.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef EI_ETHOS_LINUX
+#include "../include/ethosu.hpp"
+#include "../../kernel_driver/include/uapi/ethosu.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace std;
+
+namespace {
+
+enum class Severity { Error, Warning, Info, Debug };
+
+class Log {
+public:
+ Log(const Severity _severity = Severity::Error) : severity(_severity) {}
+
+ ~Log() = default;
+
+ template
+ const Log &operator<<(const T &d) const {
+ if (level >= severity) {
+ cout << d;
+ }
+
+ return *this;
+ }
+
+ const Log &operator<<(ostream &(*manip)(ostream &)) const {
+ if (level >= severity) {
+ manip(cout);
+ }
+
+ return *this;
+ }
+
+private:
+ static Severity getLogLevel() {
+ if (const char *e = getenv("ETHOSU_LOG_LEVEL")) {
+ const string env(e);
+
+ if (env == "Error") {
+ return Severity::Error;
+ } else if (env == "Warning") {
+ return Severity::Warning;
+ } else if (env == "Info") {
+ return Severity::Info;
+ } else if (env == "Debug") {
+ return Severity::Debug;
+ } else {
+ cerr << "Unsupported log level '" << env << "'" << endl;
+ }
+ }
+
+ return Severity::Warning;
+ }
+
+ static const Severity level;
+ const Severity severity;
+};
+
+const Severity Log::level = Log::getLogLevel();
+
+} // namespace
+
+namespace EthosU {
+__attribute__((weak)) int eioctl(int fd, unsigned long cmd, void *data = nullptr) {
+ int ret = ::ioctl(fd, cmd, data);
+ if (ret < 0) {
+ throw EthosU::Exception("IOCTL failed");
+ }
+
+ Log(Severity::Debug) << "ioctl. fd=" << fd << ", cmd=" << setw(8) << setfill('0') << hex << cmd << ", ret=" << ret
+ << endl;
+
+ return ret;
+}
+
+__attribute__((weak)) int eopen(const char *pathname, int flags) {
+ int fd = ::open(pathname, flags);
+ if (fd < 0) {
+ throw Exception("Failed to open device");
+ }
+
+ Log(Severity::Debug) << "open. fd=" << fd << ", path='" << pathname << "', flags=" << flags << endl;
+
+ return fd;
+}
+
+__attribute__((weak)) int
+eppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmo_p, const sigset_t *sigmask) {
+ int result = ::ppoll(fds, nfds, tmo_p, sigmask);
+ if (result < 0) {
+ throw Exception("Failed to wait for ppoll event or signal");
+ }
+
+ return result;
+}
+
+__attribute__((weak)) int eclose(int fd) {
+ Log(Severity::Debug) << "close. fd=" << fd << endl;
+
+ int result = ::close(fd);
+ if (result < 0) {
+ throw Exception("Failed to close file");
+ }
+
+ return result;
+}
+__attribute((weak)) void *emmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) {
+ void *ptr = ::mmap(addr, length, prot, flags, fd, offset);
+ if (ptr == MAP_FAILED) {
+ throw Exception("Failed to mmap file");
+ }
+
+ Log(Severity::Debug) << "map. fd=" << fd << ", addr=" << setfill('0') << addr << ", length=" << dec << length
+ << ", ptr=" << hex << ptr << endl;
+
+ return ptr;
+}
+
+__attribute__((weak)) int emunmap(void *addr, size_t length) {
+ Log(Severity::Debug) << "unmap. addr=" << setfill('0') << addr << ", length=" << dec << length << endl;
+
+ int result = ::munmap(addr, length);
+ if (result < 0) {
+ throw Exception("Failed to munmap file");
+ }
+
+ return result;
+}
+
+} // namespace EthosU
+
+namespace EthosU {
+
+/****************************************************************************
+ * Exception
+ ****************************************************************************/
+
+Exception::Exception(const char *msg) : msg(msg) {}
+
+Exception::~Exception() throw() {}
+
+const char *Exception::what() const throw() {
+ return msg.c_str();
+}
+
+/****************************************************************************
+ * Semantic Version
+ ****************************************************************************/
+
+bool SemanticVersion::operator==(const SemanticVersion &other) {
+ return other.major == major && other.minor == minor && other.patch == patch;
+}
+
+bool SemanticVersion::operator<(const SemanticVersion &other) {
+ if (other.major > major)
+ return true;
+ if (other.minor > minor)
+ return true;
+ return other.patch > patch;
+}
+
+bool SemanticVersion::operator<=(const SemanticVersion &other) {
+ return *this < other || *this == other;
+}
+
+bool SemanticVersion::operator!=(const SemanticVersion &other) {
+ return !(*this == other);
+}
+
+bool SemanticVersion::operator>(const SemanticVersion &other) {
+ return !(*this <= other);
+}
+
+bool SemanticVersion::operator>=(const SemanticVersion &other) {
+ return !(*this < other);
+}
+
+ostream &operator<<(ostream &out, const SemanticVersion &v) {
+ return out << "{ major=" << unsigned(v.major) << ", minor=" << unsigned(v.minor) << ", patch=" << unsigned(v.patch)
+ << " }";
+}
+
+/****************************************************************************
+ * Device
+ ****************************************************************************/
+Device::Device(const char *device) {
+ fd = eopen(device, O_RDWR | O_NONBLOCK);
+ Log(Severity::Info) << "Device(\"" << device << "\"). this=" << this << ", fd=" << fd << endl;
+}
+
+Device::~Device() noexcept(false) {
+ eclose(fd);
+ Log(Severity::Info) << "~Device(). this=" << this << endl;
+}
+
+int Device::ioctl(unsigned long cmd, void *data) const {
+ return eioctl(fd, cmd, data);
+}
+
+Capabilities Device::capabilities() const {
+ ethosu_uapi_device_capabilities uapi;
+ (void)eioctl(fd, ETHOSU_IOCTL_CAPABILITIES_REQ, static_cast(&uapi));
+
+ Capabilities capabilities(
+ HardwareId(uapi.hw_id.version_status,
+ SemanticVersion(uapi.hw_id.version_major, uapi.hw_id.version_minor),
+ SemanticVersion(uapi.hw_id.product_major),
+ SemanticVersion(uapi.hw_id.arch_major_rev, uapi.hw_id.arch_minor_rev, uapi.hw_id.arch_patch_rev)),
+ HardwareConfiguration(uapi.hw_cfg.macs_per_cc, uapi.hw_cfg.cmd_stream_version, bool(uapi.hw_cfg.custom_dma)),
+ SemanticVersion(uapi.driver_major_rev, uapi.driver_minor_rev, uapi.driver_patch_rev));
+ return capabilities;
+}
+
+/****************************************************************************
+ * Buffer
+ ****************************************************************************/
+
+Buffer::Buffer(const Device &device, const size_t capacity) : fd(-1), dataPtr(nullptr), dataCapacity(capacity) {
+ ethosu_uapi_buffer_create uapi = {static_cast(dataCapacity)};
+ fd = device.ioctl(ETHOSU_IOCTL_BUFFER_CREATE, static_cast(&uapi));
+
+ void *d;
+ try {
+ d = emmap(nullptr, dataCapacity, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ } catch (std::exception &e) {
+ try {
+ eclose(fd);
+ } catch (...) { std::throw_with_nested(e); }
+ throw;
+ }
+
+ dataPtr = reinterpret_cast(d);
+
+ Log(Severity::Info) << "Buffer(" << &device << ", " << dec << capacity << "), this=" << this << ", fd=" << fd
+ << ", dataPtr=" << static_cast(dataPtr) << endl;
+}
+
+Buffer::~Buffer() noexcept(false) {
+ try {
+ emunmap(dataPtr, dataCapacity);
+ } catch (std::exception &e) {
+ try {
+ eclose(fd);
+ } catch (...) { std::throw_with_nested(e); }
+ throw;
+ }
+
+ eclose(fd);
+
+ Log(Severity::Info) << "~Buffer(). this=" << this << endl;
+}
+
+size_t Buffer::capacity() const {
+ return dataCapacity;
+}
+
+void Buffer::clear() const {
+ resize(0, 0);
+}
+
+char *Buffer::data() const {
+ return dataPtr + offset();
+}
+
+void Buffer::resize(size_t size, size_t offset) const {
+ ethosu_uapi_buffer uapi;
+ uapi.offset = offset;
+ uapi.size = size;
+ eioctl(fd, ETHOSU_IOCTL_BUFFER_SET, static_cast(&uapi));
+}
+
+size_t Buffer::offset() const {
+ ethosu_uapi_buffer uapi;
+ eioctl(fd, ETHOSU_IOCTL_BUFFER_GET, static_cast(&uapi));
+ return uapi.offset;
+}
+
+size_t Buffer::size() const {
+ ethosu_uapi_buffer uapi;
+ eioctl(fd, ETHOSU_IOCTL_BUFFER_GET, static_cast(&uapi));
+ return uapi.size;
+}
+
+int Buffer::getFd() const {
+ return fd;
+}
+
+/****************************************************************************
+ * Network
+ ****************************************************************************/
+
+Network::Network(const Device &device, shared_ptr &buffer) : device(device), fd(-1), buffer(buffer) {
+ // Create buffer handle
+ ethosu_uapi_network_create uapi;
+ uapi.type = ETHOSU_UAPI_NETWORK_BUFFER;
+ uapi.fd = buffer->getFd();
+ fd = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, static_cast(&uapi));
+ try {
+ collectNetworkInfo();
+ } catch (std::exception &e) {
+ try {
+ eclose(fd);
+ } catch (...) { std::throw_with_nested(e); }
+ throw;
+ }
+
+ Log(Severity::Info) << "Network(" << &device << ", " << &*buffer << "), this=" << this << ", fd=" << fd << endl;
+}
+
+Network::Network(const Device &device, const unsigned index) : device(device), fd(-1) {
+ // Create buffer handle
+ ethosu_uapi_network_create uapi;
+ uapi.type = ETHOSU_UAPI_NETWORK_INDEX;
+ uapi.index = index;
+ fd = device.ioctl(ETHOSU_IOCTL_NETWORK_CREATE, static_cast(&uapi));
+ try {
+ collectNetworkInfo();
+ } catch (std::exception &e) {
+ try {
+ eclose(fd);
+ } catch (...) { std::throw_with_nested(e); }
+ throw;
+ }
+
+ Log(Severity::Info) << "Network(" << &device << ", " << index << "), this=" << this << ", fd=" << fd << endl;
+}
+
+void Network::collectNetworkInfo() {
+ ethosu_uapi_network_info info;
+ ioctl(ETHOSU_IOCTL_NETWORK_INFO, static_cast(&info));
+
+ _isVelaModel = info.is_vela;
+
+ for (uint32_t i = 0; i < info.ifm_count; i++) {
+ ifmDims.push_back(info.ifm_size[i]);
+ ifmTypes.push_back(info.ifm_types[i]);
+ ifmDataOffset.push_back(info.ifm_offset[i]);
+
+ std::vector shape;
+ for (uint32_t j = 0; j < info.ifm_dims[i]; j++) {
+ shape.push_back(info.ifm_shapes[i][j]);
+ }
+ ifmShapes.push_back(shape);
+ }
+
+ for (uint32_t i = 0; i < info.ofm_count; i++) {
+ ofmDims.push_back(info.ofm_size[i]);
+ ofmTypes.push_back(info.ofm_types[i]);
+ ofmDataOffset.push_back(info.ofm_offset[i]);
+
+ std::vector shape;
+ for (uint32_t j = 0; j < info.ofm_dims[i]; j++) {
+ shape.push_back(info.ofm_shapes[i][j]);
+ }
+ ofmShapes.push_back(shape);
+ }
+}
+
+Network::~Network() noexcept(false) {
+ eclose(fd);
+ Log(Severity::Info) << "~Network(). this=" << this << endl;
+}
+
+int Network::ioctl(unsigned long cmd, void *data) {
+ return eioctl(fd, cmd, data);
+}
+
+shared_ptr Network::getBuffer() {
+ return buffer;
+}
+
+const std::vector &Network::getIfmDims() const {
+ return ifmDims;
+}
+
+size_t Network::getIfmSize() const {
+ size_t size = 0;
+
+ for (auto s : ifmDims) {
+ size += s;
+ }
+
+ return size;
+}
+
+const std::vector &Network::getOfmDims() const {
+ return ofmDims;
+}
+
+size_t Network::getOfmSize() const {
+ size_t size = 0;
+
+ for (auto s : ofmDims) {
+ size += s;
+ }
+
+ return size;
+}
+
+size_t Network::getInputCount() const {
+ return ifmTypes.size();
+}
+
+size_t Network::getOutputCount() const {
+ return ofmTypes.size();
+}
+
+int32_t Network::getInputDataOffset(int index){
+ if (index >= ifmDataOffset.size()){
+ throw Exception("Invalid input index or non vela model");
+ }
+ return ifmDataOffset[index];
+}
+
+int32_t Network::getOutputDataOffset(int index){
+ if (index >= ofmDataOffset.size()){
+ throw Exception("Invalid output index or non vela model");
+ }
+ return ofmDataOffset[index];
+}
+
+const std::vector> &Network::getIfmShapes() const {
+ return ifmShapes;
+}
+
+const std::vector> &Network::getOfmShapes() const {
+ return ofmShapes;
+}
+
+const std::vector &Network::getIfmTypes() const {
+ return ifmTypes;
+}
+
+const std::vector &Network::getOfmTypes() const {
+ return ofmTypes;
+}
+
+const Device &Network::getDevice() const {
+ return device;
+}
+
+bool Network::isVelaModel() const {
+ return _isVelaModel;
+}
+
+/****************************************************************************
+ * Inference
+ ****************************************************************************/
+
+ostream &operator<<(ostream &out, const InferenceStatus &status) {
+ switch (status) {
+ case InferenceStatus::OK:
+ return out << "ok";
+ case InferenceStatus::ERROR:
+ return out << "error";
+ case InferenceStatus::RUNNING:
+ return out << "running";
+ case InferenceStatus::REJECTED:
+ return out << "rejected";
+ case InferenceStatus::ABORTED:
+ return out << "aborted";
+ case InferenceStatus::ABORTING:
+ return out << "aborting";
+ }
+ throw Exception("Unknown inference status");
+}
+
+Inference::~Inference() noexcept(false) {
+ eclose(fd);
+ Log(Severity::Info) << "~Inference(). this=" << this << endl;
+}
+
+void Inference::create(std::vector &counterConfigs, bool cycleCounterEnable = false) {
+ ethosu_uapi_inference_create uapi;
+
+ if (ifmBuffers.size() > ETHOSU_FD_MAX) {
+ throw Exception("IFM buffer overflow");
+ }
+
+ if (ofmBuffers.size() > ETHOSU_FD_MAX) {
+ throw Exception("OFM buffer overflow");
+ }
+
+ if (counterConfigs.size() != ETHOSU_PMU_EVENT_MAX) {
+ throw Exception("Wrong size of counter configurations");
+ }
+
+ uapi.ifm_count = 0;
+ uapi.ifm_fd[uapi.ifm_count++] = arenaBuffer->getFd();
+ for (auto it : ifmBuffers) {
+ uapi.ifm_fd[uapi.ifm_count++] = it->getFd();
+ }
+
+ uapi.ofm_count = 0;
+ for (auto it : ofmBuffers) {
+ uapi.ofm_fd[uapi.ofm_count++] = it->getFd();
+ }
+
+ for (int i = 0; i < ETHOSU_PMU_EVENT_MAX; i++) {
+ uapi.pmu_config.events[i] = counterConfigs[i];
+ }
+
+ uapi.pmu_config.cycle_count = cycleCounterEnable;
+
+ fd = network->ioctl(ETHOSU_IOCTL_INFERENCE_CREATE, static_cast(&uapi));
+
+ Log(Severity::Info) << "Inference(" << &*network << "), this=" << this << ", fd=" << fd << endl;
+}
+
+std::vector Inference::initializeCounterConfig() {
+ return std::vector(ETHOSU_PMU_EVENT_MAX, 0);
+}
+
+uint32_t Inference::getMaxPmuEventCounters() {
+ return ETHOSU_PMU_EVENT_MAX;
+}
+
+bool Inference::wait(int64_t timeoutNanos) const {
+ struct pollfd pfd;
+ pfd.fd = fd;
+ pfd.events = POLLIN | POLLERR;
+ pfd.revents = 0;
+
+ // if timeout negative wait forever
+ if (timeoutNanos < 0) {
+ return eppoll(&pfd, 1, NULL, NULL);
+ }
+
+ struct timespec tmo_p;
+ int64_t nanosec = 1000000000;
+ tmo_p.tv_sec = timeoutNanos / nanosec;
+ tmo_p.tv_nsec = timeoutNanos % nanosec;
+
+ return eppoll(&pfd, 1, &tmo_p, NULL) == 0;
+}
+
+bool Inference::cancel() const {
+ ethosu_uapi_cancel_inference_status uapi;
+ eioctl(fd, ETHOSU_IOCTL_INFERENCE_CANCEL, static_cast(&uapi));
+ return uapi.status == ETHOSU_UAPI_STATUS_OK;
+}
+
+InferenceStatus Inference::status() const {
+ ethosu_uapi_result_status uapi;
+
+ eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast(&uapi));
+
+ switch (uapi.status) {
+ case ETHOSU_UAPI_STATUS_OK:
+ return InferenceStatus::OK;
+ case ETHOSU_UAPI_STATUS_ERROR:
+ return InferenceStatus::ERROR;
+ case ETHOSU_UAPI_STATUS_RUNNING:
+ return InferenceStatus::RUNNING;
+ case ETHOSU_UAPI_STATUS_REJECTED:
+ return InferenceStatus::REJECTED;
+ case ETHOSU_UAPI_STATUS_ABORTED:
+ return InferenceStatus::ABORTED;
+ case ETHOSU_UAPI_STATUS_ABORTING:
+ return InferenceStatus::ABORTING;
+ }
+
+ throw Exception("Unknown inference status");
+}
+
+const std::vector Inference::getPmuCounters() const {
+ ethosu_uapi_result_status uapi;
+ std::vector counterValues = std::vector(ETHOSU_PMU_EVENT_MAX, 0);
+
+ eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast(&uapi));
+
+ for (int i = 0; i < ETHOSU_PMU_EVENT_MAX; i++) {
+ if (uapi.pmu_config.events[i]) {
+ counterValues.at(i) = uapi.pmu_count.events[i];
+ }
+ }
+
+ return counterValues;
+}
+
+uint64_t Inference::getCycleCounter() const {
+ ethosu_uapi_result_status uapi;
+
+ eioctl(fd, ETHOSU_IOCTL_INFERENCE_STATUS, static_cast(&uapi));
+
+ return uapi.pmu_count.cycle_count;
+}
+
+int Inference::getFd() const {
+ return fd;
+}
+
+const shared_ptr Inference::getNetwork() const {
+ return network;
+}
+
+vector> &Inference::getIfmBuffers() {
+ return ifmBuffers;
+}
+
+vector> &Inference::getOfmBuffers() {
+ return ofmBuffers;
+}
+
+/****************************************************************************
+ * Interpreter
+ ****************************************************************************/
+Interpreter::Interpreter(const char *model, const char *_device, int64_t _arenaSizeOfMB):
+ device(_device), arenaSizeOfMB(_arenaSizeOfMB){
+ //Send capabilities request
+ Capabilities capabilities = device.capabilities();
+
+ cout << "Capabilities:" << endl
+ << "\tversion_status:" << unsigned(capabilities.hwId.versionStatus) << endl
+ << "\tversion:" << capabilities.hwId.version << endl
+ << "\tproduct:" << capabilities.hwId.product << endl
+ << "\tarchitecture:" << capabilities.hwId.architecture << endl
+ << "\tdriver:" << capabilities.driver << endl
+ << "\tmacs_per_cc:" << unsigned(capabilities.hwCfg.macsPerClockCycle) << endl
+ << "\tcmd_stream_version:" << unsigned(capabilities.hwCfg.cmdStreamVersion) << endl
+ << "\tcustom_dma:" << std::boolalpha << capabilities.hwCfg.customDma << endl;
+
+ // Init network
+ ifstream stream(model, ios::binary);
+ if (!stream.is_open()) {
+ throw Exception("Failed to open model file");
+ }
+
+ stream.seekg(0, ios_base::end);
+ size_t size = stream.tellg();
+ stream.seekg(0, ios_base::beg);
+
+ networkBuffer = make_shared(device, size);
+ networkBuffer->resize(size);
+ stream.read(networkBuffer->data(), size);
+ network = make_shared(device, networkBuffer);
+ if (!network->isVelaModel()) {
+ throw Exception("Only support models compiled by vela.");
+ }
+
+ // Init tensor arena buffer
+ size_t arena_buffer_size = arenaSizeOfMB << 20;
+ arenaBuffer = make_shared(device, arena_buffer_size);
+ arenaBuffer->resize(arena_buffer_size);
+}
+
+void Interpreter::SetPmuCycleCounters(vector counters, bool cycleCounter) {
+ if (counters.size() != ETHOSU_PMU_EVENT_MAX){
+ throw Exception("PMU event count is invalid.");
+ }
+
+ pmuCounters = counters;
+ enableCycleCounter = cycleCounter;
+}
+
+void Interpreter::Invoke(int64_t timeoutNanos) {
+ inference = make_shared(network, arenaBuffer,
+ pmuCounters, enableCycleCounter);
+ inference->wait(timeoutNanos);
+
+ if (inference->status() != InferenceStatus::OK) {
+ throw Exception("Failed to invoke.");
+ }
+}
+
+std::vector Interpreter::GetPmuCounters() {
+ return inference->getPmuCounters();
+}
+
+uint64_t Interpreter::GetCycleCounter() {
+ return inference->getCycleCounter();
+}
+
+std::vector Interpreter::GetInputInfo() {
+ std::vector ret;
+ auto types = network->getIfmTypes();
+ auto shapes = network->getIfmShapes();
+
+ for (int i = 0; i < network->getInputCount(); i ++) {
+ ret.push_back(TensorInfo{types[i], shapes[i]});
+ }
+
+ return ret;
+}
+
+std::vector Interpreter::GetOutputInfo(){
+ std::vector ret;
+ auto types = network->getOfmTypes();
+ auto shapes = network->getOfmShapes();
+
+ for (int i = 0; i < network->getOutputCount(); i ++) {
+ ret.push_back(TensorInfo{types[i], shapes[i]});
+ }
+
+ return ret;
+}
+
+} // namespace EthosU
+
+#endif // EI_ETHOS_LINUX
diff --git a/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/kernel_driver/include/uapi/ethosu.h b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/kernel_driver/include/uapi/ethosu.h
new file mode 100644
index 0000000..ae3efbc
--- /dev/null
+++ b/edgeimpulse/edge-impulse-sdk/porting/ethos-u-driver-stack-imx/kernel_driver/include/uapi/ethosu.h
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2020-2023 Arm Limited.
+ *
+ * This program is free software and is provided to you under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation, and any use by you of this program is subject to the terms
+ * of such GNU licence.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
+ *
+ * SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note
+ */
+
+#ifndef ETHOSU_H
+#define ETHOSU_H
+
+/****************************************************************************
+ * Includes
+ ****************************************************************************/
+
+#include
+#include
+#include
+
+#ifdef __cplusplus
+namespace EthosU {
+#endif
+
+/****************************************************************************
+ * Defines
+ ****************************************************************************/
+
+#define ETHOSU_IOCTL_BASE 0x01
+#define ETHOSU_IO(nr) _IO(ETHOSU_IOCTL_BASE, nr)
+#define ETHOSU_IOR(nr, type) _IOR(ETHOSU_IOCTL_BASE, nr, type)
+#define ETHOSU_IOW(nr, type) _IOW(ETHOSU_IOCTL_BASE, nr, type)
+#define ETHOSU_IOWR(nr, type) _IOWR(ETHOSU_IOCTL_BASE, nr, type)
+
+#define ETHOSU_IOCTL_PING ETHOSU_IO(0x00)
+#define ETHOSU_IOCTL_VERSION_REQ ETHOSU_IO(0x01)
+#define ETHOSU_IOCTL_CAPABILITIES_REQ ETHOSU_IOR(0x02, \
+ struct ethosu_uapi_device_capabilities)
+#define ETHOSU_IOCTL_BUFFER_CREATE ETHOSU_IOR(0x10, \
+ struct ethosu_uapi_buffer_create)
+#define ETHOSU_IOCTL_BUFFER_SET ETHOSU_IOR(0x11, \
+ struct ethosu_uapi_buffer)
+#define ETHOSU_IOCTL_BUFFER_GET ETHOSU_IOW(0x12, \
+ struct ethosu_uapi_buffer)
+#define ETHOSU_IOCTL_NETWORK_CREATE ETHOSU_IOR(0x20, \
+ struct ethosu_uapi_network_create)
+#define ETHOSU_IOCTL_NETWORK_INFO ETHOSU_IOR(0x21, \
+ struct ethosu_uapi_network_info)
+#define ETHOSU_IOCTL_INFERENCE_CREATE ETHOSU_IOR(0x30, \
+ struct ethosu_uapi_inference_create)
+#define ETHOSU_IOCTL_INFERENCE_STATUS ETHOSU_IOR(0x31, \
+ struct ethosu_uapi_result_status)
+#define ETHOSU_IOCTL_INFERENCE_CANCEL ETHOSU_IOR(0x32, \
+ struct ethosu_uapi_cancel_inference_status)
+
+/* Maximum number of IFM/OFM file descriptors per network */
+#define ETHOSU_FD_MAX 16
+/* Maximum number of dimensions for input and output */
+#define ETHOSU_DIM_MAX 8
+
+/* Maximum number of PMUs available */
+#define ETHOSU_PMU_EVENT_MAX 4
+
+/****************************************************************************
+ * Types
+ ****************************************************************************/
+
+/**
+ * enum ethosu_uapi_status - Status
+ */
+enum ethosu_uapi_status {
+ ETHOSU_UAPI_STATUS_OK,
+ ETHOSU_UAPI_STATUS_ERROR,
+ ETHOSU_UAPI_STATUS_RUNNING,
+ ETHOSU_UAPI_STATUS_REJECTED,
+ ETHOSU_UAPI_STATUS_ABORTED,
+ ETHOSU_UAPI_STATUS_ABORTING,
+};
+
+/**
+ * struct ethosu_uapi_buffer_create - Create buffer request
+ * @capacity: Maximum capacity of the buffer
+ */
+struct ethosu_uapi_buffer_create {
+ __u32 capacity;
+};
+
+/**
+ * struct ethosu_uapi_buffer - Buffer descriptor
+ * @offset: Offset to where the data starts
+ * @size: Size of the data
+ *
+ * 'offset + size' must not exceed the capacity of the buffer.
+ */
+struct ethosu_uapi_buffer {
+ __u32 offset;
+ __u32 size;
+};
+
+/**
+ * enum ethosu_uapi_network_create - Network buffer type.
+ * @ETHOSU_UAPI_NETWORK_BUFFER: Network is stored in a buffer handle.
+ * @ETHOSU_UAPI_NETWORK_INDEX: Network is built into firmware and referenced by
+ * index.
+ */
+enum ethosu_uapi_network_type {
+ ETHOSU_UAPI_NETWORK_BUFFER = 1,
+ ETHOSU_UAPI_NETWORK_INDEX
+};
+
+/**
+ * struct ethosu_uapi_network_create - Create network request
+ * @type: Buffer type. See @ethosu_uapi_network_type.
+ * @fd: Buffer file descriptor
+ * @index: Buffer index compiled into firmware binary.
+ */
+struct ethosu_uapi_network_create {
+ uint32_t type;
+ union {
+ __u32 fd;
+ __u32 index;
+ };
+};
+
+/**
+ * struct ethosu_uapi_network_info - Network info
+ * @desc: Network description
+ * @ifm_count: Number of IFM buffers
+ * @ifm_size: IFM buffer sizes
+ * @ifm_types: IFM data types
+ * @ifm_offset: IFM data offset in arena
+ * @ifm_dims: IFM buffer dimensions
+ * @ifm_shapes: IFM buffer shapes
+ * @ofm_count: Number of OFM buffers
+ * @ofm_size: OFM buffer sizes
+ * @ofm_offset: OFM data offset in arena
+ * @ofm_dims: OFM buffer dimensions
+ * @ofm_shapes: OFM buffer shapes
+ */
+struct ethosu_uapi_network_info {
+ char desc[32];
+ __u32 is_vela;
+ __u32 ifm_count;
+ __u32 ifm_size[ETHOSU_FD_MAX];
+ __u32 ifm_types[ETHOSU_FD_MAX];
+ __u32 ifm_offset[ETHOSU_FD_MAX];
+ __u32 ifm_dims[ETHOSU_FD_MAX];
+ __u32 ifm_shapes[ETHOSU_FD_MAX][ETHOSU_DIM_MAX];
+ __u32 ofm_count;
+ __u32 ofm_size[ETHOSU_FD_MAX];
+ __u32 ofm_types[ETHOSU_FD_MAX];
+ __u32 ofm_offset[ETHOSU_FD_MAX];
+ __u32 ofm_dims[ETHOSU_FD_MAX];
+ __u32 ofm_shapes[ETHOSU_FD_MAX][ETHOSU_DIM_MAX];
+};
+
+/**
+ * struct ethosu_uapi_pmu_config - Configure performance counters
+ * @events: Array of counters to configure, set to non-zero for
+ * each counter to enable corresponding event.
+ * @cycle_count: Set to enable the cycle counter.
+ */
+struct ethosu_uapi_pmu_config {
+ __u32 events[ETHOSU_PMU_EVENT_MAX];
+ __u32 cycle_count;
+};
+
+/**
+ * struct ethosu_uapi_pmu_counts - Status of performance counters
+ * @events: Count for respective configured events.
+ * @cycle_count: Count for cycle counter.
+ */
+struct ethosu_uapi_pmu_counts {
+ __u32 events[ETHOSU_PMU_EVENT_MAX];
+ __u64 cycle_count;
+};
+
+/**
+ * struct ethosu_uapi_device_hw_id - Device hardware identification
+ * @version_status: Version status
+ * @version_minor: Version minor
+ * @version_major: Version major
+ * @product_major: Product major
+ * @arch_patch_rev: Architecture version patch
+ * @arch_minor_rev: Architecture version minor
+ * @arch_major_rev: Architecture version major
+ */
+struct ethosu_uapi_device_hw_id {
+ __u32 version_status;
+ __u32 version_minor;
+ __u32 version_major;
+ __u32 product_major;
+ __u32 arch_patch_rev;
+ __u32 arch_minor_rev;
+ __u32 arch_major_rev;
+};
+
+/**
+ * struct ethosu_uapi_device_hw_cfg - Device hardware configuration
+ * @macs_per_cc: MACs per clock cycle
+ * @cmd_stream_version: NPU command stream version
+ * @custom_dma: Custom DMA enabled
+ */
+struct ethosu_uapi_device_hw_cfg {
+ __u32 macs_per_cc;
+ __u32 cmd_stream_version;
+ __u32 custom_dma;
+};
+
+/**
+ * struct ethosu_uapi_device_capabilities - Device capabilities
+ * @hw_id: Hardware identification
+ * @hw_cfg: Hardware configuration
+ * @driver_patch_rev: Driver version patch
+ * @driver_minor_rev: Driver version minor
+ * @driver_major_rev: Driver version major
+ */
+struct ethosu_uapi_device_capabilities {
+ struct ethosu_uapi_device_hw_id hw_id;
+ struct ethosu_uapi_device_hw_cfg hw_cfg;
+ __u32 driver_patch_rev;
+ __u32 driver_minor_rev;
+ __u32 driver_major_rev;
+};
+
+/**
+ * enum ethosu_uapi_inference_type - Inference type
+ */
+enum ethosu_uapi_inference_type {
+ ETHOSU_UAPI_INFERENCE_MODEL = 0,
+ ETHOSU_UAPI_INFERENCE_OP
+};
+
+/**
+ * struct ethosu_uapi_inference_create - Create network request
+ * @ifm_count: Number of IFM file descriptors
+ * @ifm_fd: IFM buffer file descriptors
+ * @ofm_count: Number of OFM file descriptors
+ * @ofm_fd: OFM buffer file descriptors
+ */
+struct ethosu_uapi_inference_create {
+ __u32 ifm_count;
+ __u32 ifm_fd[ETHOSU_FD_MAX];
+ __u32 ofm_count;
+ __u32 ofm_fd[ETHOSU_FD_MAX];
+ enum ethosu_uapi_inference_type inference_type;
+ struct ethosu_uapi_pmu_config pmu_config;
+};
+
+/**
+ * struct ethosu_uapi_result_status - Status of inference
+ * @status Status of run inference.
+ * @pmu_config Configured performance counters.
+ * @pmu_count Perfomance counters values, when status is
+ * ETHOSU_UAPI_STATUS_OK.
+ */
+struct ethosu_uapi_result_status {
+ enum ethosu_uapi_status status;
+ struct ethosu_uapi_pmu_config pmu_config;
+ struct ethosu_uapi_pmu_counts pmu_count;
+};
+
+/**
+ * struct ethosu_uapi_cancel_status - Status of inference cancellation.
+ * @status OK if inference cancellation was performed, ERROR otherwise.
+ */
+struct ethosu_uapi_cancel_inference_status {
+ enum ethosu_uapi_status status;
+};
+
+#ifdef __cplusplus
+} /* namespace EthosU */
+#endif
+#endif
diff --git a/edgeimpulse/edge-impulse-sdk/porting/himax-we2/ethosu_driver.c b/edgeimpulse/edge-impulse-sdk/porting/himax-we2/ethosu_driver.c
new file mode 100644
index 0000000..322f0c6
--- /dev/null
+++ b/edgeimpulse/edge-impulse-sdk/porting/himax-we2/ethosu_driver.c
@@ -0,0 +1,16 @@
+#include "../ei_classifier_porting.h"
+#if EI_PORTING_HIMAX_WE2 == 1
+#include "WE2_core.h"
+
+// Impelements weak functions from edge-impulse-sdk/porting/ethos-core-driver/src/ethosu_driver.c
+void ethosu_flush_dcache(uint32_t *p, size_t bytes)
+{
+ hx_CleanDCache_by_Addr((volatile void *)p, bytes);
+}
+
+void ethosu_invalidate_dcache(uint32_t *p, size_t bytes)
+{
+ hx_InvalidateDCache_by_Addr((volatile void *)p, bytes);
+}
+
+#endif // #if EI_PORTING_HIMAX_WE2 == 1
\ No newline at end of file