Can I have the full tutorial for deploying to C library?

I am trying to do some simple model on the device first
like multiplying a number by 2

but i don’t understand how to use the whole thing(the zip file with C++ source file and brunch of header file) on C

my goal is to deploy a audio classifier on a cortex m3 device
which is not in the list of device that edge impulse stated
i may collect my data and train the model outside edge impulse

i have put the edge-impulse-sdk ,tflite-model,model-parameters into my project
but seems it can’t find/use the run_classifier function
return L6218E: Undefined symbol run_classifier

Somebody help

I would start here:

how do i start with C++ standalone example on a C project?
i can’t even figure out how to use this right now…

Oh, sorry. The C version is here.

1 Like

but i got error when i try to run the code on my device

i am fresh to this
please some guide :pray:

1 Like

Looks like the compiler cannot find run_classifier(). Check this.

1 Like

yes i have defined them in the compiler
in c standalone example , it do not seems to add any run_classifier included header file?
maybe i am misunderstood the page?

i saw conditions with C linkage but it comes with __cplusplus too.
my compiler and project is not C++.
if i define the __cplusplus too, it would pop up like few hundreds syntax error relate to c++

1 Like


  1. Which compiler are you using?
  2. Does it fail during compilation (producing main.o) ?
  3. or during linking with producing edge-impulse-standalone ?

In main.c we forward declare run_classifier so if it fails to produce main.o I would look at your compiler arguments/flags.

The definition of run_classifier is in Can you confirm whether building was successful.

If it the shared library was built successfully, then the last step is to link the application with the shared If this failed. I’d check whether you have the right linker flags to find the shared

  1. Keil
  2. I want to deploy the whole thing into my project. so i am not producing the standalone-c main
    and i just copy the standalone-c main code to my project and put those file in my project
  3. i can’t see any file? how to produce it ? maybe i just need that to run my code?


i found i can build in the standalone-c folder
i am trying to look if my simple regression is work or not
i put 5 values in the feature , seems there is one output only when i execute the .exe
maybe i put too many feature in that ? how to rebuild the whole thing?

the seems cannot be directly use on my project
when i build my project there are errors in the


If I understand correctly you’ve built the library in the C example standalone repo that @MMarcial referenced and tried to use this library in your own keil project?
If so, then this is not going to work. You have to build and link libedgeimpulse using the same compiler you use in your Keil environment.

Take a look at this example of using GNU Toolchain and GNU Make:

Change the flags, compiler, linker and archiver accordingly for your toolchain, target and host.

Can you share what output logs?
To rebuild with GNU make it’s make clean followed by a make.

1 Like

i don’t understand how to build and link the libedgeimpulse in my project
do you have detail steps for this?

the second problem is solve . the standalone example works now

Thank you


You mention you’re using Arm Keil toolchain, so I assume and base on here that your compiler (CC) is armclang, linker is armlink and archiver (AR) is armar.

To build a static libedgeimpulse.a for your target and toolchain try and using this repo.

  1. Go to C/static/ directory
  2. Edit Makefile’s # Target Specific section with target specific flags and load the right porting layer for your target. Don’t see your target in the edge_impulse_sdk/porting/*? Then take a look at our Porting Guide.
  3. In a console run: make clean
  4. In a console run: CC=armclang CXX=armclang AR=armar make

Note you may need to add target specific flags. More info here and here.

Once you have built the static library using arm keil toolchain you can then link against this to create your final applicaiton. This can be done with the compiler or with linker.

1 Like

Hi @rjames

thanks for your help

but i don’t know if i need to add some target specific flags
is there a instruction for adding flags to corresponding device?
my device is cortex m3 and using ARM architecture v7-M
the line would be CFLAGS += -march=armv7-m ?
and the origin CFLAGS += -DTF_LITE_DISABLE_X86_NEON=1 should be removed?

i tried to make the lib by adding mbed porting
it seems looking for .o files
is it necessary ? cause i just want to get the lib file for my device to work with

or do i need to make a new project on keil to compile a library ? but how about the Makefile?


Yes you can buid the library alone with make build/ Note that you are currently building a shared library for x86 and not a static library for Cortex-M3. Meaning you won’t be able to use the library on the Cortex-M3. Please take a look building static edgeimpulse library for C application repo. In this case to build only the library, use make build/libedgeimpulse.a

You need to specify Cortex-m3 target flags see below flags passed to GNU Arm Toolchain.

CFLAGS += -march=armv7-m
CFLAGS += -mcpu=cortex-m3
CFLAGS += -mthumb 

Other flags you may want to consider:

CXXFLAGS += -fno-rtti
LDFLAGS += -specs=nano.specs -specs=nosys.specs

You need to specify equivalent (if not the same) flags for armclang.

They’re more flags that may need to be provided, not too mention linker flags and linker files. etc.
Which evaluation/development kit or board are you using? I’d suggest to re-use flags, linker files, etc. used in their examples provided (or their IDE).

1 Like

Hi @rjames ,

i am using a custom board of this series of chip

it maybe kind of complicated for me.

so i have another board of stm32
maybe i should start with this as a practice first?
i am not meaning to use the inbuilded edge impulse option of stm32 software
i want to build a library and be used by the corresponding devices

the optimization and speed of mcu may not be enough to run the model , but i want to figure out how to do in the first place
thank you

1 Like


Yes that’s a better approach.
Please report when you have results or findings


i have no much knowledge in Makefile.
i have tried to add some flags and words but it seems not working

C:\Users\uveuv\Downloads\example-standalone-inferencing-with-library-master\C\static>make -j 4
cc -mcpu=cortex-m4 -mthumb -Wall -g -Wno-strict-aliasing -DEIDSP_SIGNAL_C_FN_POINTER=1 -DEI_C_LINKAGE=1 -I. -Os -DNDEBUG -g -c edge-impulse-sdk/CMSIS/DSP/Source/BasicMathFunctions/arm_xor_u8.c -o edge-impulse-sdk/CMSIS/DSP/Source/BasicMathFunctions/arm_xor_u8.o
process_begin: CreateProcess(NULL, cc -mcpu=cortex-m4 -mthumb -Wall -g -Wno-strict-aliasing -DEIDSP_SIGNAL_C_FN_POINTER=1 -DEI_C_LINKAGE=1 -I. -Os -DNDEBUG -g -c edge-impulse-sdk/CMSIS/DSP/Source/BasicMathFunctions/arm_xor_u8.c -o edge-impulse-sdk/CMSIS/DSP/Source/BasicMathFunctions/arm_xor_u8.o, ...) failed.
make (e=2): 系統找不到指定的檔案。
make: *** [Makefile:91: edge-impulse-sdk/CMSIS/DSP/Source/BasicMathFunctions/arm_xor_u8.o] Error 2

Can you just show an example for building such a library?

my so far added some words Makefile is this

NAME = edge-impulse-standalone

CC ?= gcc
CXX ?= g++
AR ?=ar

CFLAGS += -mcpu=cortex-m4
CFLAGS += -mthumb
CFLAGS += -Wall -g -Wno-strict-aliasing
CFLAGS += -g
CXXFLAGS += -std=c++11

LDFLAGS += -mcpu=cortex-m4
LDFLAGS += -Wl,--gc-sections
LDFLAGS += -lm -lstdc++

CSOURCES =  $(wildcard edge-impulse-sdk/CMSIS/DSP/Source/BasicMathFunctions/*.c) \
			$(wildcard edge-impulse-sdk/CMSIS/DSP/Source/FastMathFunctions/*.c) \
			$(wildcard edge-impulse-sdk/CMSIS/DSP/Source/StatisticsFunctions/*.c) \
			$(wildcard edge-impulse-sdk/CMSIS/DSP/Source/TransformFunctions/*fft*.c) \
			$(wildcard edge-impulse-sdk/CMSIS/DSP/Source/CommonTables/*.c) \
			$(wildcard edge-impulse-sdk/CMSIS/DSP/Source/TransformFunctions/*bit*.c)  \
			$(wildcard edge-impulse-sdk/CMSIS/DSP/Source/MatrixFunctions/*.c)
CXXSOURCES = $(wildcard tflite-model/*.cpp) \
			 $(wildcard edge-impulse-sdk/dsp/kissfft/*.cpp) \
			 $(wildcard edge-impulse-sdk/dsp/dct/*.cpp) \
			 $(wildcard ./edge-impulse-sdk/dsp/memory.cpp) \
			 $(wildcard ./edge-impulse-sdk/classifier/*.cpp)\
			 $(wildcard edge-impulse-sdk/porting/mbed/*.cpp)
CCSOURCES = $(wildcard edge-impulse-sdk/tensorflow/lite/kernels/*.cc) \
			$(wildcard edge-impulse-sdk/tensorflow/lite/kernels/internal/*.cc) \
			$(wildcard edge-impulse-sdk/tensorflow/lite/micro/kernels/*.cc) \
			$(wildcard edge-impulse-sdk/tensorflow/lite/micro/*.cc) \
			$(wildcard edge-impulse-sdk/tensorflow/lite/micro/memory_planner/*.cc) \
			$(wildcard edge-impulse-sdk/tensorflow/lite/core/api/*.cc)
APP_CSOURCES = $(wildcard source/*.c)

ifeq (${CMSIS_NN},1)
CFLAGS += -Wno-unknown-attributes
CFLAGS += -Iedge-impulse-sdk/CMSIS/NN/Include/
CFLAGS += -Iedge-impulse-sdk/CMSIS/DSP/PrivateInclude/
CSOURCES += $(wildcard edge-impulse-sdk/CMSIS/NN/Source/ActivationFunctions/*.c) \
$(wildcard edge-impulse-sdk/CMSIS/NN/Source/BasicMathFunctions/*.c) \
$(wildcard edge-impulse-sdk/CMSIS/NN/Source/ConcatenationFunctions/*.c) \
$(wildcard edge-impulse-sdk/CMSIS/NN/Source/ConvolutionFunctions/*.c) \
$(wildcard edge-impulse-sdk/CMSIS/NN/Source/FullyConnectedFunctions/*.c) \
$(wildcard edge-impulse-sdk/CMSIS/NN/Source/NNSupportFunctions/*.c) \
$(wildcard edge-impulse-sdk/CMSIS/NN/Source/PoolingFunctions/*.c) \
$(wildcard edge-impulse-sdk/CMSIS/NN/Source/ReshapeFunctions/*.c) \
$(wildcard edge-impulse-sdk/CMSIS/NN/Source/SoftmaxFunctions/*.c)

# end Target specific

COBJECTS := $(patsubst %.c,%.o,$(CSOURCES))
CXXOBJECTS := $(patsubst %.cpp,%.o,$(CXXSOURCES))
CCOBJECTS := $(patsubst,%.o,$(CCSOURCES))
APP_COBJECTS = $(patsubst %.c,%.o,$(APP_CSOURCES))
# Host specific
ifeq ($(OS),Windows_NT)
	MKDIR_BUILD = if not exist build mkdir build
	MKDIR_BUILD = mkdir -p build
#end host specific

# Target specific

all: app

.PHONY: app clean

$(COBJECTS) : %.o : %.c
$(CXXOBJECTS) : %.o : %.cpp
$(CCOBJECTS) : %.o :
$(APP_COBJECTS) : %.o : %.c

%.o: %.c
	$(CC) $(CFLAGS) -c $^ -o $@

	$(CXX) $(CFLAGS) $(CXXFLAGS) -c $^ -o $@

%.o: %.cpp
	$(CXX) $(CFLAGS) $(CXXFLAGS) -c $^ -o $@

build/libedgeimpulse.a: $(COBJECTS) $(CXXOBJECTS) $(CCOBJECTS)
	$(AR) rcs build/libedgeimpulse.a $(COBJECTS) $(CXXOBJECTS) $(CCOBJECTS)

app: $(APP_COBJECTS) build/libedgeimpulse.a
	$(CXX) $(APP_COBJECTS) build/libedgeimpulse.a -o build/$(NAME) $(LDFLAGS)

ifeq ($(OS),Windows_NT)
	del /Q $(subst /,\,$(patsubst %.c,%.o,$(CSOURCES))) >nul 2>&1 || exit 0
	del /Q $(subst /,\,$(patsubst %.cpp,%.o,$(CXXSOURCES))) >nul 2>&1 || exit 0
	del /Q $(subst /,\,$(patsubst,%.o,$(CCSOURCES))) >nul 2>&1 || exit 0
	del /Q $(subst /,\,$(patsubst %.c,%.o,$(APP_COBJECTS))) >nul 2>&1 || exit 0
	del /Q build\libedgeimpulse.a >nul 2>&1 || exit 0
	rm -f $(COBJECTS)
	rm -f $(CCOBJECTS)
	rm -f $(CXXOBJECTS)
	rm -f $(APP_COBJECTS)
	rm -f build/libedgeimpulse.a

Hi @uveuvenouve

Which terminal are you using on Windows?

Your error seems to suggest a issue with PATH. Take a look at answer from Ricardo Alejos at windows - Makefile error make (e=2): The system cannot find the file specified - Stack Overflow.
Can you try adding <git-installation-directory>/usr/bin to you’re PATH environmental variable.

Hi @rjames

i think it just can’t find arm_xor_u8.o
but i don’t know why
maybe it didn’t compile out the arm_xor_u8.o
i expect it should compile like standalone example cause the makefile seems the same besides of some other flag added