Bug report : serial print for float/double broken in latest version

Hi there, I believe this is new bug report (i.e. I’ve checked everything I can and can’t find any error on my side).

I have a piece of code (printing to serial) that was working fine up until yesterday, before I updated PIO. Now, it’s completely broken and prints garbage and crashes the application. The same code works properly in the Arduino IDE.

The problem is float and double numbers fail with Serial.print() and appear to display some random memory address as a string. Here is the code I tested:

void setup(void)
{
    Serial.begin(115200);
    delay(1000);

    Serial.println("int:");
    int i = 0;
    Serial.println(i);

    Serial.println("float:");
    float f = 0.F;
    Serial.println(f);

    Serial.println("double:");
    double d = 0.;
    Serial.println(d);
}

Here is the output after compiling and uploading with PIO extension (under VSCode):

int:
0
float:
␀������������������������������������������������������������������������U␀ �U␀ �9␀ ␀␀␀␀����␇␡␂␀␆␡␂␀␀␀␀g␀ 0␀␀␀␀␀␀␀o|␂g␀ ␀␀␀␀␀␀␀␀␀␀␀␀�5␀ 0␀␀␀␁␀␀g␀ ␀␀␀␀�z␂g␀
␀␀␀␀␀␀␀o|␂g␀ ␀␀␀␀␀␀␀␀␀␀␀␀�5␀
double:
␀���������������������������������������������������������������������������������������␁␀␀g␀ ␀␀␀␀Uz␂g␀ 0␀␀␀␀␀␀␀C|␂g␀ ␀␀␀␀␀␀␀␀␀␀␀␀�5␀ 0␀␀␀␁␀␀g␀ ␀␀␀␀Uz␂g␀
␀␀␀␀␀␀␀C|␂g␀ ␀␀␀␀␀␀␀␀␀␀␀␀�5␀
␀␀␀�5␀ ␁␀␀␀'�␂␀���������w␂␀ww␂␀'�␂␀%�␂␀�t␂␀␀␀�5␀ ��␂␀�5␀ �5␀ ]v␂␀�T␀ �5␀ ␔�␂␀�b␂␀BNO055␀␀␀␀␀␀␁␀␀␀7␀␀␀␃␀␀␀␀␀␀␀␀␀␀␀
␁�������������������������������������������������������������BNO055␀␀␀␀␀␀␁␀␀␀7␀␀␀␃␀␀␀␀␀␀␀␀␀␀␀
�#<␀␀␀␀␀␀␀␀����������������g�␂␀����␕�␂␀��������\␀␀␀�����T␀ +␗␀␀ 6␀  6␀ �U␀ ␘6␀ ␄␀␀␀�3�+|*���U␀ ␀␀␀␀␁␀␀␀�=␀ loop␀�l␀␁␀␀␀����␁␀␀␀␀␀␀␀␀␀␀␀␀␀_'�␀␀␀HV␀ �V␀ HV␀ �V␀ ␀␀␀␀␐V␀ ����␐V␀ ␐V␀ ␁␀␀␀$V␀ �����f␀ �f␀ ␀␀␀␀␔␀␀␀␄␀␀␀��␀␃ˋ��␀4�)�␡�H␅b��s{b�␛␌����{5.1�!ͪ�G0%␑
␡�Y�␌�#␑m��P    7���%�E�␘��}�␖␜���7���P���7�/;<M�{␐␀␀����������������������������������������������������������������������������������������������������������������������������������������������������������������������������
�������.....

And here is the output after compiling and uploading with Arduino extension (under VSCode):

int:
0
float:
0.00
double:
0.00

After the PIO uploaded code tries to print a double or float and instead prints garbage, the program will randomly crash as well.

Board: I’m using Adafruit nFR52 Feather, using BSP 10.1. Prior to upgrade, I was using BSP 9.3 but the PIO upgrade also upgraded the BSP (I have all auto updates enabled). I’m not sure if the cause is the BSP or something in PIO itself or perhaps a specific compiler flag, but this code was working fine before updating.

Any ideas what may be causing this? And is there a way to disable all compiler optimizations?

Thanks

I had a similar problem with a Teensy board. Turns out that printf() doesn’t always include support for floating point (to save space).

See [Solved] Float to string fails for the fix for that platform, not sure if it’ll help on the nFR52.

1 Like

I’m afraid I won’t be able to reproduce this, because I don’t have a Feather. I would like to clarify a few things though:

Is this the Adafruit Feather nRF52840 Express or Adafruit Bluefruit nRF52832 Feather ? They hey have different definitions in platformio.ini

; Adafruit Feather nRF52840 Express
[env:adafruit_feather_nrf52840]
platform = nordicnrf52
board = adafruit_feather_nrf52840
framework = arduino

;Adafruit Bluefruit nRF52832 Feather
[env:adafruit_feather_nrf52832]
platform = nordicnrf52
board = adafruit_feather_nrf52832
framework = arduino

Also, I’m confused as to where you’re getting the BSP version from… as the current platformio version is 3.3.0 …

Hi there,
the board is a Feather nRF52832, however, it doesn’t appear to make a difference as several nRF52 boards seem to have the same problem. For the BSP version, in PlatformIO it’s sort of hidden but you can find it if you know where to look:

c_cpp_properties.json:
    "defines": [
        "ARDUINO_BSP_VERSION=\"0.9.3\"",

.platformio/packages/framework-arduinoadafruitnrf52/
    platform.txt:
        version=0.9.3
    library.properties:
        version=0.9.3

I copied Adafruit’s 0.10.1 BSP to the folder (PIO installs 0.9.3 by default) and changed the c_cpp_properties.json file, but somehow it keeps switching back to 0.9.3 every time I compile… I guess there is another setting somewhere that specifies the version number but I can’t seem to find it.

Anyway, after a lot of debugging and research on this issue I can say the BSP and compiler versions are not the issue. I eventually found a post on the Nordic forums that explains what’s going on, and it’s related to what blackketter mentioned: seems that PlatformIO is not passing the correct compiling/linking options to support sprintf for floats and doubles for Nordic chips. There are 2 conflicting flags that need to be specified:
compiler flag:

-mfloat-abi=hard   (** must be combined with linker flag below)
-mfloat-abi=softfp (** must be combined with linker flag below)
-mfloat-abi=soft   (can be specified alone)

linker flag:

-u _printf_float   (not needed for float-abi=soft)

So, here’s where I think the problem is. Both PIO and Arduino set -mfloat-abi=hard by default, and this requires the -u _printf_float flag to be passed to the linker. The code works in Arduino and I can see -u _printf_float on the command line to the linker in verbose mode. However, in verbose mode in PIO, the only difference I can see is that the linker arg is “-u _printf_float” not simply -u _printf_float, and perhaps that causes the arg to be interpreted as a single string and ignored.

Also, I wanted to try setting -mfloat-abi=soft to get around the linker issue, however I can’t seem to make this work. The -mfloat-abi=hard flag is hardcoded in 3 places:

boards.txt:
    Generic_nRF52832.build.float_flags=-mfloat-abi-soft -mfpu=fpv4-sp-d16

platform.txt:
    build.float_flags=-mfloat-abi=soft -mfpu=fpv4-sp-d16 -u _printf_float

c_cpp_properties.json:
    "compilerPath": "${home}/.platformio/packages/toolchain-gccarmnoneeabi/bin/arm-none-eabi-gcc.exe -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16"

Changing all of them to =soft results in PIO ignoring all the changes and it adds =hard to the compiler args anyway. Using build_flags= didn’t work either since the flag is already set and I couldn’t remove it. Is there another source of the compiler flags that can be customized?

Is it not unsettable by adding it to build_unflags = ..?

Yes, I had tried unflags and thought it didn’t work, but after further examination I did see it in the compile string. So, a slight update:
using -mfloat-abi=soft doesn’t work and throws compiler/linker errors because that mode is not compatible with the BSP base packages. Using -mfloat-abi=softfp at least compiles, but completely crashes the program upon executing an FPU instruction. So, only option is to use -mfloat-abi=hard and fix the linker issue, it seems. I’m not sure were the compiler/linker script gets ` “-u _printf_float” ’ from and because of the quotes I can’t seem to get build_unflags to remove it.

The build script is here builder-framework-arduino-nrf5/nrf5.py at master · platformio/builder-framework-arduino-nrf5 · GitHub

Thanks, I’ll try to investigate further to see where it’s going wrong.

I was going to start by logging all the commands run by Arduino to recreate a make file, then do the same with PIO and compare the 2. Obviously something very minor is different that’s causing this to break, but so far I haven’t been able to find it.

1 Like

Ok, so, note to PIO team: I’ve confirmed this bug and the solution:

With the argument "-u _printf_float" with quotes is passed to the compiler/linker, the argument is ignored and the linker produces code that will crash.

However, with the argument passed as -u _printf_float without quotes, the linker produces code that works and successfully executes floating point operations.

The bug looks to be in the PIO build script somewhere (but I don’t know python well enough to figure out where). The platform.txt file for the Adafruit nRF52 board package specifies all the compiler options, with -u _printf_float included in build.float_flags. There are no quotes specified in the flag and somehow PIO seems to be adding the quotes when it detects the -u parameter with a space. The Ardunio extension uses the exact same board package and doesn’t add the quotes when calling the compiler/linker.

I tried to fix this with setting build_flags and build_unflags, but there is no combination of settings that appears to replace the arg without quotes, since the quotes get added back in automatically because of the space. I also tried replacing the argument in the ASFLAGS/CFLAGS env variables via a pre-compile extra script, but the -u _printf_float flag does not contain any quotes inside the env variable, so it must be the script that’s adding it.

Also, it seems only the Adafruit board requires this flag to be set correctly, the nRF52 DK board does not.

Is this something that can be easily fixed? For now, my only work around is to manually link the elf file and build the hex/zip package and upload it.

I think I misunderstood your question originally - yes I’m using the Nordic nRF52 package 3.3.0, but that Nordic nRF52 package includes version 0.9.3 of the Adafruit Bluefruit package. As a side note, can this be updated to include 0.10.1 of the Adafruit Bluefruit package? Not that it makes any difference for this reported case.

1 Like

I found a simple work-around for this issue:
in builder-framework-arduino-nrf5/adafruit.py at master · platformio/builder-framework-arduino-nrf5 · GitHub
changing:

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

to:

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

completely fixes the issue. Can I post this as an issue on github?

1 Like

Thanks! Fixed in

1 Like