Arm_rms_q15 not found when porting an Arduino Nano 33 Sense project to PlatformIO

I’m trying to port a TinyML project from the Arduino IDE to PlatformIO. This project uses the Arduino Nano 33 Sense board.

I can compile the code successfully in the Arduino IDE by installing the Arduino mbed enabled boards:

image

If I try to recreate this in PlatformIO using the nano33ble board, I get a compiler error:

undefined reference to `arm_rms_q15'

This is similar to what is discussed around this sample on the Arduino forums, and the ‘fix’ is to change the Arduino board in the board manager as there are multiple options that match that board.

So my question is - what is the right board setup to use to make this compile? My platformio.ini is:

[env:nano33ble]
platform = nordicnrf52
board = nano33ble
framework = arduino

That is a really strange phenomenon. You can see by a search in the repo (and by grep-ing through all the binary files) that the Arduino mbed core only provides the header for the arm_math.h functions, but not the implementation.

They are expected to be in the toolchain, in a file called libarm_cortexM4l_math.a, that then must be linked in the project. So if it works in some version of the Arduino IDE board package, then the version that works in has just the right toolchain that has this file.

But, as already discussed and solved in the topic Project using arm_math.h on nRF52 results in Linker Error - #6 by maxgerhardt, the same fix can be applied – we download the file, put it in our project and link against it.

grafik

[env:nano33ble]
platform = nordicnrf52
board = nano33ble
framework = arduino
build_flags = -L. -larm_cortexM4l_math

with a bit of test code in src\main.cpp

#include <Arduino.h>
#include <arm_math.h>

void setup() {
  Serial.begin(115200);
  float numbers_float[3] = {
    1.0f, 2.0f, 3.0f
  };
  q15_t numbers_q15[3];
  arm_float_to_q15(numbers_float, numbers_q15, 3);
  q15_t rms_result_q15 = 0;
  arm_rms_q15(numbers_q15, 3, &rms_result_q15);
  float rms_result_float = 0.0f;
  arm_q15_to_float(&rms_result_q15, &rms_result_float, 1);
  Serial.println("RMS result: " + String(rms_result_float, 5));
}

void loop() {
}

and build …

Linking .pio\build\nano33ble\firmware.elf
Checking size .pio\build\nano33ble\firmware.elf
Building .pio\build\nano33ble\firmware.bin
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [==        ]  16.6% (used 43496 bytes from 262144 bytes)
Flash: [=         ]   8.1% (used 80084 bytes from 983040 bytes)
=================== [SUCCESS] Took 6.87 seconds ===================

For a systematic fix one would have to look if it compiles in the very latest Arduino IDE version (and board support package version), and if yes, what toolchain they are using exactly, and add the missing files. But this works as a workaround and gets the very-lasted version of the ARM library straight from the ARM CMSIS source :slight_smile:

1 Like

Thanks @maxgerhardt - adding that library and the linker flag and it all works perfectly.

It works using the latest Arduino IDE - literally a fresh install when I compiled the code. I’m afraid I don’t know the internals of Arduino or PlatformIO or how the boards/libraries work, so I’m not sure where to start validating and suggesting a fix.

Okay then we might have a mismatch between the toolchain that Arduino IDE uses and what PlatformIO uses. I’ll look into that.

Seems I have another error with the same code. Now when I load up what was a working project and compile, it can’t find arm_math.h.

Nothing has changed in my code, my PIO is updated to the latest everything, so looks like there was an update that removes this header file.

This is consistent with what people say at Nano33BLESensorExample_MicrophoneRMS.ino does not compile with ArduinoCore-mbed · Issue #6 · DaleGia/Nano33BLESensor · GitHub. Probably an update in the framework / arduino core caused this.

With PlatformIO, you can always revert back to an earlier version. See documentation and available releases. You can e.g. try platform = nordicnrf52@7.1.0 in the platformio.ini to get to the 1.3.2 core version that is reported to work.

If you want the project to work with the latest core version, I’d advise to copy the header file, and all header files it depends on, directly in the include/ folder of the project. The original sources for arm_math.h come from the CMSIS DSP extension, available at https://github.com/ARM-software/CMSIS_5/tree/develop/CMSIS/DSP/Include (<-- this is the development version, there are also previous releases).

Thanks @maxgerhardt. I guess it makes sense to remove the header if the library is not shipped with it.

I’ll change my lab I’ve written to use the header from the GitHub repo.

Appreciate your guidance!

Hi Max.
Wouldn’t libarm_cortexM0l_math.a be more appropriate for arduino nano 33?
I am a bit new to this. Is the M0 referring to the ARM® Cortex®-M0+ processor, like the one on the nano 33?

https://store.arduino.cc/usa/nano-33-iot#:~:text=Arm®%20Cortex®-M0%2032-bit%20SAMD21

This thread is about the nano33ble board, aka “Arduino Nano 33 BLE” board, which has a Nordic nRF52840 microcontroller, which is a Cortex-M4(F) based MCU.

You are linking to the “Arduino Nano 33 IoT” board with a Atmel SAMD21G18 (Cortex®-M0+ based) microcontroller. If you are working with that board and you are encountering that “undefined reference to 'arm_rms_q15'” error, yes, you need to link in the library that is compiled for a Cortex M0+, aka libarm_cortexM0l_math.a.

1 Like