Error with Arduino Library on Adafruit nRF Board

I followed the instructions on getting an Edge Impulse Arduino Library to run on an generic ARM Arduino. I am trying to get it to work on the Adafruit Bluefruit Sense.

With the Static Buffer example it compiles fine if I don’t fill out the feature array, however if I fill it in, I get:
sketch/nano_ble33_sense_accelerometer.ino.cpp.o: In function (anonymous namespace)::extract_spectral_analysis_features(ei::ei_signal_t*, ei::ei_matrix*, void*)': /Users/lberndt/Library/Arduino15/packages/arduino/tools/arm-none-eabi-gcc/7-2017q4/arm-none-eabi/include/c++/7.2.1/bits/std_function.h:705: undefined reference to std::__throw_bad_function_call()’
collect2: error: ld returned 1 exit status
exit status 1
Error compiling for board Adafruit Feather Bluefruit Sense.

I will compile if I fill in a just a few floats in the feature array and runs on the board, but will print out a message on serial about the feature array not being long enough, so that seems good.
I am using Arduino studio 1.8.12 on a OS X 10.15.4

Hi @Robotastic, if you have a features array that is not the right size it’ll compile everything out (as the assert fails and the linker is smart!). Could you let me know the Arduino core path for this board? I’ll try it out. Looking a little bit at the typical cases for this error message are old GCC versions but 7 should be fine…

Thanks - I am using the Adafruit core for the nRF52 series. The local path is here:
~/Library/Arduino15/packages/adafruit/hardware/nrf52/0.20.1
The repo is here: https://github.com/adafruit/Adafruit_nRF52_Arduino
You can add the Adafruit board repo with this: https://www.adafruit.com/package_adafruit_index.json
And then install ‘Adafruit nRF52 by Adafruit’ from the board manager.

I just tried compiling for an Adafruit board with an M4 ARM SAMD51 and it compiled fine.

It also complaining about Serial.write() with the nRF52 Core, I changed it to Serial.println() to get past it:

/Users/lberndt/Documents/Arduino/libraries/ei-robotastic-project-1-arduino-1/examples/static_buffer/static_buffer.ino: In function ‘void ei_printf(const char*, …)’:
static_buffer:122:31: error: invalid conversion from ‘char*’ to ‘uint8_t {aka unsigned char}’ [-fpermissive]
Serial.write(print_buf);
^
In file included from /Users/lberndt/Library/Arduino15/packages/adafruit/hardware/nrf52/0.20.1/cores/nRF5/TinyUSB/Adafruit_TinyUSB_ArduinoCore/Adafruit_TinyUSB_Core.h:36:0,
from /Users/lberndt/Library/Arduino15/packages/adafruit/hardware/nrf52/0.20.1/cores/nRF5/Arduino.h:71,
from sketch/static_buffer.ino.cpp:1:
/Users/lberndt/Library/Arduino15/packages/adafruit/hardware/nrf52/0.20.1/cores/nRF5/TinyUSB/Adafruit_TinyUSB_ArduinoCore/Adafruit_USBD_CDC.h:48:17: note: initializing argument 1 of ‘virtual size_t Adafruit_USBD_CDC::write(uint8_t)’
virtual size_t write(uint8_t);
^~~~~
exit status 1
invalid conversion from ‘char*’ to ‘uint8_t {aka unsigned char}’ [-fpermissive]

Thanks @Robotastic, I’ll get someone to take a look at this in our next patch round.

1 Like

Adafruit recently updated their Board Package for the nRF52 boards ( https://github.com/adafruit/Adafruit_nRF52_Arduino/releases ). With the update it almost compiles fine.

During linking it complains about the following:
/Users/lberndt/Library/Arduino15/packages/adafruit/tools/arm-none-eabi-gcc/9-2019q4/bin/…/lib/gcc/arm-none-eabi/9.2.1/…/…/…/…/arm-none-eabi/bin/ld: sketch/wash-watcher-bluefruit.ino.cpp.o: in function `std::vector<ei::spectral::processing::freq_peak_t, std::allocatorei::spectral::processing::freq_peak_t >::_M_check_len(unsigned int, char const*) const’:

/Users/lberndt/Library/Arduino15/packages/adafruit/tools/arm-none-eabi-gcc/9-2019q4/arm-none-eabi/include/c++/9.2.1/bits/stl_vector.h:1756: undefined reference to `std::__throw_length_error(char const*)'
/Users/lberndt/Library/Arduino15/packages/adafruit/tools/arm-none-eabi-gcc/9-2019q4/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld: sketch/wash-watcher-bluefruit.ino.cpp.o: in function `std::function<int (unsigned int, unsigned int, float*)>::operator()(unsigned int, unsigned int, float*) const':
/Users/lberndt/Library/Arduino15/packages/adafruit/tools/arm-none-eabi-gcc/9-2019q4/arm-none-eabi/include/c++/9.2.1/bits/std_function.h:687: undefined reference to `std::__throw_bad_function_call()'
collect2: error: ld returned 1 exit status
exit status 1
Error compiling for board Adafruit Feather Bluefruit Sense.

Adding in the following fixed that:

namespace std {void __throw_bad_function_call() { while(1); }; }
namespace std {void __throw_length_error(char const*) { while(1); }; }

It has a different accelerometer so you have to change the included library:

#include <Arduino_LSM6DS3.h>

I also removed the architecture definition from library.properties since it works with more than mbed.

I will give an audio example a try.

@Robotastic, thanks a lot for reporting! I’m wondering why __throw_bad_function_call wouldn’t be present with this GCC version… It’s there on GCC7 with the Arduino Nano 33 BLE Sense. Any chance that this port uses newlib-nano maybe?

edit: Running tests now with these functions defined, let’s see if there’s any targets that will fail compilation. If not, we can land it in the SDK.

It does look like they are using newlib-nano: https://github.com/adafruit/Adafruit_nRF52_Arduino/issues/34
I couldn’t track down exactly where it is being included in the board package.

It looks like they are using GCC v9:

Using built-in specs.

COLLECT_GCC=./arm-none-eabi-gcc

COLLECT_LTO_WRAPPER=/Users/lberndt/Library/Arduino15/packages/adafruit/tools/arm-none-eabi-gcc/9-2019q4/bin/../lib/gcc/arm-none-eabi/9.2.1/lto-wrapper

Target: arm-none-eabi

Configured with: /tmp/jenkins-GCC-9-pipeline-100_20191030_1572397548/src/gcc/configure --target=arm-none-eabi --prefix=/tmp/jenkins-GCC-9-pipeline-100_20191030_1572397548/install-native --libexecdir=/tmp/jenkins-GCC-9-pipeline-100_20191030_1572397548/install-native/lib --infodir=/tmp/jenkins-GCC-9-pipeline-100_20191030_1572397548/install-native/share/doc/gcc-arm-none-eabi/info --mandir=/tmp/jenkins-GCC-9-pipeline-100_20191030_1572397548/install-native/share/doc/gcc-arm-none-eabi/man --htmldir=/tmp/jenkins-GCC-9-pipeline-100_20191030_1572397548/install-native/share/doc/gcc-arm-none-eabi/html --pdfdir=/tmp/jenkins-GCC-9-pipeline-100_20191030_1572397548/install-native/share/doc/gcc-arm-none-eabi/pdf --enable-languages=c,c++ --enable-plugins --disable-decimal-float --disable-libffi --disable-libgomp --disable-libmudflap --disable-libquadmath --disable-libssp --disable-libstdcxx-pch --disable-nls --disable-shared --disable-threads --disable-tls --with-gnu-as --with-gnu-ld --with-newlib --with-headers=yes --with-python-dir=share/gcc-arm-none-eabi --with-sysroot=/tmp/jenkins-GCC-9-pipeline-100_20191030_1572397548/install-native/arm-none-eabi --build=x86_64-apple-darwin10 --host=x86_64-apple-darwin10 --with-gmp=/tmp/jenkins-GCC-9-pipeline-100_20191030_1572397548/build-native/host-libs/usr --with-mpfr=/tmp/jenkins-GCC-9-pipeline-100_20191030_1572397548/build-native/host-libs/usr --with-mpc=/tmp/jenkins-GCC-9-pipeline-100_20191030_1572397548/build-native/host-libs/usr --with-isl=/tmp/jenkins-GCC-9-pipeline-100_20191030_1572397548/build-native/host-libs/usr --with-libelf=/tmp/jenkins-GCC-9-pipeline-100_20191030_1572397548/build-native/host-libs/usr --with-host-libstdcxx='-static-libgcc -Wl,-lstdc++ -lm' --with-pkgversion='GNU Tools for Arm Embedded Processors 9-2019-q4-major' --with-multilib-list=rmprofile

Thread model: single

gcc version 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599] (GNU Tools for Arm Embedded Processors 9-2019-q4-major)

I also got an audio inference example working. I had to change around the microphone_audio_signal_get_data because arm_q15_to_float is not defined. EIDSP_USE_CMSIS_DSP does not get set to true. I think the board package includes support for CMSIS - so I might try messing around with the definitions in config.hpp

/**
 * Get raw audio signal data
 */
static int microphone_audio_signal_get_data(size_t offset, size_t length, float *out_ptr)
{
    //arm_q15_to_float(&inference.buffer[offset], out_ptr, length);

    int16_t *input = &inference.buffer[offset];
    for (size_t ix = 0; ix < length; ix++) {
            out_ptr[ix] = (float)(input[ix]);
    }
    return 0;
}

@Robotastic you can use the numpy::int16_to_float function there. It uses CMSIS-DSP if available and software implementation when not. Will actually fix in our Arduino examples.

Cool! that is where I borrowed the code from. I didn’t figure out the namespace to call it, so I was lazy and just copied the code.