Arduino Nano 33 BLE TensorFlow lite - Undefined References

Hi,

I’m hoping to get some assistance on a Arduino project, using Platform IO for the Arduino Nano 33 BLE Sense.

Platform IO has enabled me to build, upload and test simple projects, however now I’m trying to step it up a notch, by introducing the TensorFlow Lite library. Its a simple Platform-IO port of the micro_speech project for TensorFlow 2.2.0, which is not currently supported in the Arduino IDE.

My code base can be found here.

I’m getting a tonne of Undefined References when linking the local TensorFlow lite library into the code base, and I’m wondering if there is a Platform IO concept I’m missing.

Currently there is a closed TensorFlow issue, regarding Undefined references when targeting an ARM64.

I’m really loving the idea that I can debug my code using Platform IO and don’t want to give up using this tool set, but I can’t get my head around why this code is failing.

Any ideas?

An excerpt of a verbose build on Ubuntu 20.04 x86_64 is here:

...
rm-none-eabi-g++ -o .pio/build/nano33ble/firmware.elf -T linker_script.ld -DMBED_APP_SIZE=0xf0000 -DMBED_APP_START=0x10000 -DMBED_BOOT_STACK_SIZE=2048 -Wl,--gc-sections -Wl,--wrap,_calloc_r -Wl,--wrap,_free_r -Wl,--wrap,_malloc_r -Wl,--wrap,_memalign_r -Wl,--wrap,_realloc_r -Wl,--wrap,atexit -Wl,--wrap,exit -Wl,--wrap,main -Wl,-n -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -mthumb --specs=nano.specs --specs=nosys.specs -Wl,--as-needed .pio/build/nano33ble/src/audio_provider.cpp.o .pio/build/nano33ble/src/command_responder.cpp.o .pio/build/nano33ble/src/feature_provider.cpp.o .pio/build/nano33ble/src/main.cpp.o .pio/build/nano33ble/src/recognize_commands.cpp.o -L.pio/build/nano33ble -L/home/ian/.platformio/packages/framework-arduino-nrf52-mbedos/variants/ARDUINO_NANO33BLE -L/home/ian/.platformio/packages/framework-arduino-nrf52-mbedos/variants/ARDUINO_NANO33BLE/libs -Wl,--start-group -Wl,--whole-archive .pio/build/nano33ble/libe06/libPDM.a .pio/build/nano33ble/lib5e8/libtensorflow.a .pio/build/nano33ble/lib082/libmicro_features.a .pio/build/nano33ble/libFrameworkArduinoVariant.a .pio/build/nano33ble/libFrameworkArduino.a -lmbed -lcc_310_core -lcc_310_ext -lcc_310_trng -Wl,--no-whole-archive -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys -Wl,--end-group
/home/ian/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/8.2.1/../../../../arm-none-eabi/bin/ld: .pio/build/nano33ble/src/command_responder.cpp.o: in function `RespondToCommand(tflite::ErrorReporter*, long, char const*, unsigned char, bool)':
/home/ian/Documents/PlatformIO/Projects/Nano33Take01/src/command_responder.cpp:48: undefined reference to `tflite::ErrorReporter::Report(char const*, ...)'
/home/ian/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/8.2.1/../../../../arm-none-eabi/bin/ld: .pio/build/nano33ble/src/feature_provider.cpp.o: in function `FeatureProvider::PopulateFeatureData(tflite::ErrorReporter*, long, long, int*)':
/home/ian/Documents/PlatformIO/Projects/Nano33Take01/src/feature_provider.cpp:102: undefined reference to `tflite::ErrorReporter::Report(char const*, ...)'
/home/ian/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/8.2.1/../../../../arm-none-eabi/bin/ld: .pio/build/nano33ble/src/main.cpp.o: in function `tflite::MicroMutableOpResolver<4u>::GetOpDataParser(tflite::BuiltinOperator) const':
/home/ian/Documents/PlatformIO/Projects/Nano33Take01/lib/tensorflow/tensorflow/lite/micro/micro_mutable_op_resolver.h:62: undefined reference to `tflite::ParseOpData(tflite::Operator const*, tflite::BuiltinOperator, tflite::ErrorReporter*, tflite::BuiltinDataAllocator*, void**)'
/home/ian/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/8.2.1/../../../../arm-none-eabi/bin/ld: .pio/build/nano33ble/src/main.cpp.o: in function `tflite::MicroMutableOpResolver<4u>::AddCustom(char const*, TfLiteRegistration*)':
/home/ian/Documents/PlatformIO/Projects/Nano33Take01/lib/tensorflow/tensorflow/lite/micro/micro_mutable_op_resolver.h:98: undefined reference to `tflite::ErrorReporter::Report(char const*, ...)'
/home/ian/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/8.2.1/../../../../arm-none-eabi/bin/ld: /home/ian/Documents/PlatformIO/Projects/Nano33Take01/lib/tensorflow/tensorflow/lite/micro/micro_mutable_op_resolver.h:108: undefined reference to `tflite::ErrorReporter::Report(char const*, ...)'
/home/ian/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/8.2.1/../../../../arm-none-eabi/bin/ld: .pio/build/nano33ble/src/main.cpp.o: in function `tflite::MicroMutableOpResolver<4u>::AddBuiltin(tflite::BuiltinOperator, TfLiteRegistration*)':
...

Well the github page tells you how to do it for the normal Arduino IDE: https://github.com/tensorflow/tensorflow/tree/master/tensorflow/lite/micro/examples/micro_speech#deploy-to-arduino

From there we download the library (e.g. mirrored on ArduBadge), add in the lib/ folder, and add the most recent demo files.

Your code there also seems to differ from what’s in the Github repo at the moment. E.g., you have a main.cpp where you #include "tensorflow/lite/micro/kernels/micro_ops.h" but the Github does #include "tensorflow/lite/experimental/micro/kernels/micro_ops.h" – you seem to be using a different version or codebase here?

Also note how the library.properties states the inclusion of the precompiled library:

ldflags=-lm -ltensorflowlite

That’s where your undefined references are implemented, in Arduino_TensorFlowLite\src\cortex-m4\libtensorflowlite.a. An ugly way would be by adding

build_flags = -L lib/Arduino_TensorFlowLite/src/cortex-m4 -ltensorflowlite

to the platformio.ini, so let’s create a PlatformIO library.json description which is more portable.

So if we copy the Arduino library code, copy the microspeech example and create a library.json that passes these two extra linker flags, we get a perfectly compilable example.

See GitHub - maxgerhardt/pio-nano33ble-microspeech-example: The TensorflowLite microspeech example compilable for a Arduino Nano 33 BLE board..

And of course, completion in an IDE works now too :slight_smile:

2 Likes

Thanks for it Max. Tried to put together the TensorflowLiteMicro from the repo but it have many files in to be builded with Makefile, etc. Just downloading the packaged version from Arduino is much simpler…

I am trying to build this for Nicla Sense ME. No luck yet.