Error: <object> uses VFP register arguments, <firmware.elf> does not

Trying to develop applications on a STM32L476RG NUCLEO with the ARM CMSIS DSP library on PlatformIO throws the following error during the linking stage:

error: ext_libs/libarm_cortexM4lf_math.a(arm_biquad_cascade_df1_init_f32.o) uses VFP register arguments, .pio/build/nucleo_l476rg/firmware.elf does not

My .ini-file looks like this:

[env:nucleo_l476rg]
platform = ststm32
board = nucleo_l476rg
framework = stm32cube

build_flags =
    -L ext_libs
    -larm_cortexM4lf_math

Introducing flags like -mfloat-abi=softfp or -mfloat-abi=hard just causes more of these mismatch errors to appear. I know for a fact that it can work: using the STM Cube IDE i can upload just fine, but via PlatformIO and a raspberry Pi as host it doesn’t seem to work. Is there a type of flag i can add? Would be surprising if an ARM library doesn’t compile on an ARM device which targets an ARM microcontroler, right?

Well first of all, PlatformIO’s STM32Cube builder script adds the CMSIS-DSP folder in the library path:

but does not add the linking flag -l.. to it.

A minimal working example is

[env:nucleo_l476rg]
platform = ststm32
board = nucleo_l476rg
framework = stm32cube
build_flags = -larm_cortexM4l_math
#include "stm32l4xx_hal.h"
#include <arm_math.h>

int main(void)
{
  HAL_Init();

  float32_t cosOutput;
  float32_t cosSquareOutput;
  while(1) {
     cosOutput = arm_cos_f32(1.2345f);
     arm_mult_f32(&cosOutput, &cosOutput, &cosSquareOutput, 1);
  }
}


void SysTick_Handler(void)
{
  HAL_IncTick();
}

void NMI_Handler(void)
{
}

void HardFault_Handler(void)
{
  while (1) {}
}


void MemManage_Handler(void)
{
  while (1) {}
}

void BusFault_Handler(void)
{
  while (1) {}
}

void UsageFault_Handler(void)
{
  while (1) {}
}

void SVC_Handler(void)
{
}


void DebugMon_Handler(void)
{
}

void PendSV_Handler(void)
{
}

Notice how I link with libarm_cortexM4l_math instead of libarm_cortexM4lf_math. The first one requires hardfloat, the second one softfloat. The builder script does not setup any flags for the FPU (source), so by default you will have softfloat.

Your project does

so it tries to link with the Hardfloat version of the lib and one from an external source (this is wring since board_build.stm32cube.custom_dsp_library =yes is not set in your `platformio.ini). So you get the error

accordingly.

To link with the hardfloat library, you need to the compiler as well as linker flags. This can be done via a script.

[env:nucleo_l476rg]
platform = ststm32
board = nucleo_l476rg
framework = stm32cube
; add hardfloat compiler flags
extra_scripts = pre:add_hardfloat.py
; link against better hardfloat lib
build_flags =
  -larm_cortexM4lf_math

with add_hardfloat.py on the same directory level as the platformio.ini

Import("env")
flags = [
   "-mfloat-abi=hard",
   "-mfpu=fpv4-sp-d16"
]
env.Append(CCFLAGS=flags, LINKFLAGS=flags)

And same code as above, gives

RAM:   [          ]   0.0% (used 44 bytes from 98304 bytes)
Flash: [          ]   0.3% (used 3084 bytes from 1048576 bytes)
===============[SUCCESS] Took 2.73 seconds ===============

If you wish to use your external CMSIS-DSP library, use

[env:nucleo_l476rg]
platform = ststm32
board = nucleo_l476rg
framework = stm32cube
; don't add builtin DSP lib to linkerpath
board_build.stm32cube.custom_dsp_library =yes
; add hardfloat compiler flags
extra_scripts = pre:add_hardfloat.py
; link against better hardfloat lib
build_flags =
  -Lext_libs
  -larm_cortexM4lf_math
3 Likes

An issue about this is open at Make FPU and CMSIS-DSP configuration easier · Issue #591 · platformio/platform-ststm32 · GitHub.

First of all, thank you for your swift and comprehensive service which holds this forum together. I see you in tons of threads and you always provide great insight to ignorant people like me. Your suggestion worked right away and I’m now able to develop and debug STM32 DSP applications remotely from a raspberry pi. Good stuff!

I came across your script-suggestion here but was initially confused, since the code does not look like python an pylance doesn’t like it either:

Import: Any
"Import" is not definedPylancereportUndefinedVariable

But that’s just a minor thing.
I wish i was aware of the fact that the ARM DSP lib is already added, that would have saved me some time.

Technically it is mentioned in the documentation page for STM32Cube STM32Cube — PlatformIO latest documentation, but the given example platformio.ini would lead you to the linking errors shown in the issue. The devs should take care of this now.

An extra_script is executed by PlatformIO through the SCons engine and with a lot of runtime-injected functions, like Import(). Static code analyzers can impossibly recognize this situation when just given the .py file. Errors like these should be ignored in Python editors / IDEs.

Thank you very much :slight_smile:

I have the same issue with an STM32H7, and while I did include the flags for hard and fpv5_d16, that only got me through FreeRTOS compiling. Now when I got to link I have this issue.

I believe I understand the fix… but not the cause. For some reason it seems that STM32 projects just aren’t going to be linked correctly without setting the build_flags in the CCFLAGS AND LINKFLAGS sections? When I set them with build_flags that was effecting cc I think. Is there any way to set the LINKFLAGS to use floating point without the python script? That seems too cryptic for most people to figure out.

I’m fine with the python if I have to. But @maxgerhardt if you could help me understand the issue, it would help the next time I see something like this. Why would the linker flags not be accessible via the .ini?