embeddedartistry / arduino-printf

Add printf support to the Arduino SDK
MIT License
91 stars 15 forks source link

Arduino Uno not working with snprintf and %E or %G #24

Closed im-skylar closed 2 years ago

im-skylar commented 2 years ago

Hi there, I've been trying to use snprintf with the %G format specifier and depending on the float I inputted this resulted in the Arduino getting hung up and not sending anything over serial (for example when using 2.4455345e12 as input float), it writing 00000000000000000000 or infe-249 with %e format specifier.

I am using the Arduino IDE on Artix Linux and an Arduino Uno Rev. 3

As test sketch i used

#include <LibPrintf.h>

void setup() {
  Serial.begin(9600);
  delay(500);
}

void loop() {
  char buf[21] {0};
  snprintf(buf, 21, "% 18G", 2.4455345);
  Serial.println(buf);
  delay(50);
}

and in my platform.local.txt I have

compiler.cpp.extra_flags=-DPRINTF_PREVENT_DEFAULT_AVR_SETTINGS -DPRINTF_DISABLE_SUPPORT_LONG_LONG
compiler.c.extra_flags=-DPRINTF_PREVENT_DEFAULT_AVR_SETTINGS -DPRINTF_DISABLE_SUPPORT_LONG_LONG
Build Output ``` /usr/share/arduino/arduino-builder -dump-prefs -logger=machine -hardware /usr/share/arduino/hardware -hardware /home/skylar/.arduino15/packages -tools /usr/share/arduino/tools-builder -tools /home/skylar/.arduino15/packages -libraries /home/skylar/documents/programming/Arduino/libraries -fqbn=arduino:avr:uno -vid-pid=2341_0043 -ide-version=10817 -build-path /tmp/arduino_build_624533 -warnings=all -build-cache /tmp/arduino_cache_997480 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.arduinoOTA.path=/home/skylar/.arduino15/packages/arduino/tools/arduinoOTA/1.3.0 -prefs=runtime.tools.arduinoOTA-1.3.0.path=/home/skylar/.arduino15/packages/arduino/tools/arduinoOTA/1.3.0 -prefs=runtime.tools.avr-gcc.path=/home/skylar/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7 -prefs=runtime.tools.avr-gcc-7.3.0-atmel3.6.1-arduino7.path=/home/skylar/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7 -prefs=runtime.tools.avrdude.path=/home/skylar/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17 -prefs=runtime.tools.avrdude-6.3.0-arduino17.path=/home/skylar/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17 -verbose /home/skylar/documents/programming/Arduino/Printf_Test/Printf_Test.ino /usr/share/arduino/arduino-builder -compile -logger=machine -hardware /usr/share/arduino/hardware -hardware /home/skylar/.arduino15/packages -tools /usr/share/arduino/tools-builder -tools /home/skylar/.arduino15/packages -libraries /home/skylar/documents/programming/Arduino/libraries -fqbn=arduino:avr:uno -vid-pid=2341_0043 -ide-version=10817 -build-path /tmp/arduino_build_624533 -warnings=all -build-cache /tmp/arduino_cache_997480 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.arduinoOTA.path=/home/skylar/.arduino15/packages/arduino/tools/arduinoOTA/1.3.0 -prefs=runtime.tools.arduinoOTA-1.3.0.path=/home/skylar/.arduino15/packages/arduino/tools/arduinoOTA/1.3.0 -prefs=runtime.tools.avr-gcc.path=/home/skylar/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7 -prefs=runtime.tools.avr-gcc-7.3.0-atmel3.6.1-arduino7.path=/home/skylar/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7 -prefs=runtime.tools.avrdude.path=/home/skylar/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17 -prefs=runtime.tools.avrdude-6.3.0-arduino17.path=/home/skylar/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17 -verbose /home/skylar/documents/programming/Arduino/Printf_Test/Printf_Test.ino Using board 'uno' from platform in folder: /home/skylar/.arduino15/packages/arduino/hardware/avr/1.8.4 Using core 'arduino' from platform in folder: /home/skylar/.arduino15/packages/arduino/hardware/avr/1.8.4 Detecting libraries used... /home/skylar/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10817 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR -DPRINTF_PREVENT_DEFAULT_AVR_SETTINGS -DPRINTF_DISABLE_SUPPORT_LONG_LONG -I/home/skylar/.arduino15/packages/arduino/hardware/avr/1.8.4/cores/arduino -I/home/skylar/.arduino15/packages/arduino/hardware/avr/1.8.4/variants/standard /tmp/arduino_build_624533/sketch/Printf_Test.ino.cpp -o /dev/null Alternatives for LibPrintf.h: [LibPrintf@1.1.3] ResolveLibrary(LibPrintf.h) -> candidates: [LibPrintf@1.1.3] /home/skylar/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10817 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR -DPRINTF_PREVENT_DEFAULT_AVR_SETTINGS -DPRINTF_DISABLE_SUPPORT_LONG_LONG -I/home/skylar/.arduino15/packages/arduino/hardware/avr/1.8.4/cores/arduino -I/home/skylar/.arduino15/packages/arduino/hardware/avr/1.8.4/variants/standard -I/home/skylar/documents/programming/Arduino/libraries/LibPrintf/src /tmp/arduino_build_624533/sketch/Printf_Test.ino.cpp -o /dev/null Using cached library dependencies for file: /home/skylar/documents/programming/Arduino/libraries/LibPrintf/src/LibPrintf.cpp Generating function prototypes... /home/skylar/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10817 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR -DPRINTF_PREVENT_DEFAULT_AVR_SETTINGS -DPRINTF_DISABLE_SUPPORT_LONG_LONG -I/home/skylar/.arduino15/packages/arduino/hardware/avr/1.8.4/cores/arduino -I/home/skylar/.arduino15/packages/arduino/hardware/avr/1.8.4/variants/standard -I/home/skylar/documents/programming/Arduino/libraries/LibPrintf/src /tmp/arduino_build_624533/sketch/Printf_Test.ino.cpp -o /tmp/arduino_build_624533/preproc/ctags_target_for_gcc_minus_e.cpp /usr/bin/arduino-ctags -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives /tmp/arduino_build_624533/preproc/ctags_target_for_gcc_minus_e.cpp Compiling sketch... /home/skylar/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-g++ -c -g -Os -Wall -Wextra -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10817 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR -DPRINTF_PREVENT_DEFAULT_AVR_SETTINGS -DPRINTF_DISABLE_SUPPORT_LONG_LONG -I/home/skylar/.arduino15/packages/arduino/hardware/avr/1.8.4/cores/arduino -I/home/skylar/.arduino15/packages/arduino/hardware/avr/1.8.4/variants/standard -I/home/skylar/documents/programming/Arduino/libraries/LibPrintf/src /tmp/arduino_build_624533/sketch/Printf_Test.ino.cpp -o /tmp/arduino_build_624533/sketch/Printf_Test.ino.cpp.o Compiling libraries... Compiling library "LibPrintf" Using previously compiled file: /tmp/arduino_build_624533/libraries/LibPrintf/LibPrintf.cpp.o Compiling core... Using precompiled core: /tmp/arduino_cache_997480/core/core_arduino_avr_uno_26f9e2aa5e5a8259cb599b0504c5f6ad.a Linking everything together... /home/skylar/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-gcc -Wall -Wextra -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections -mmcu=atmega328p -o /tmp/arduino_build_624533/Printf_Test.ino.elf /tmp/arduino_build_624533/sketch/Printf_Test.ino.cpp.o /tmp/arduino_build_624533/libraries/LibPrintf/LibPrintf.cpp.o /tmp/arduino_build_624533/../arduino_cache_997480/core/core_arduino_avr_uno_26f9e2aa5e5a8259cb599b0504c5f6ad.a -L/tmp/arduino_build_624533 -lm /home/skylar/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-objcopy -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 /tmp/arduino_build_624533/Printf_Test.ino.elf /tmp/arduino_build_624533/Printf_Test.ino.eep /home/skylar/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-objcopy -O ihex -R .eeprom /tmp/arduino_build_624533/Printf_Test.ino.elf /tmp/arduino_build_624533/Printf_Test.ino.hex Using library LibPrintf at version 1.1.3 in folder: /home/skylar/documents/programming/Arduino/libraries/LibPrintf /home/skylar/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/bin/avr-size -A /tmp/arduino_build_624533/Printf_Test.ino.elf Sketch uses 8160 bytes (25%) of program storage space. Maximum is 32256 bytes. Global variables use 248 bytes (12%) of dynamic memory, leaving 1800 bytes for local variables. Maximum is 2048 bytes. ```
phillipjohnston commented 2 years ago

I am away from my hardware at this moment, but I will look into it when I return home. I would need to check the underlying printf library to see what might be going on there (since you did set the appropriate build definitions). I have a task in another project to switch that to a more recently updated fork as well.

eyalroz commented 2 years ago

@im-skylar : That would be issue embeddedartistry/libc#159 ; and the fork would be the stand-alone, self-contained, embedded-friendly printf library, of which I am the effective maintainer.

Here's your example, adapted for use of the library and for Linux (without the C standard library):

#include <printf/printf.h>
#include <unistd.h>

// If you didn't use link-time optimization when compiling the library,
// you'll need to uncomment the following line:
// 
//     void putchar_(char character) { };
// 
// even though the function is not actually used. 

int main() {
  char buf[21] = { 0 };
  int written_len = snprintf_(buf, 21, "% 18G", 2.4455345);
  if (written_len > 0) {
    write(0, buf, written_len);
  }
}

This prints: 2.44553.

phillipjohnston commented 2 years ago

Changes are ready to go to integrate the new library, but is blocked because printf("string with no args") does not output anything. Adding a variable to the printf causes everything to work as expected. No warnings are shown in the Arduino IDE...

https://github.com/eyalroz/printf/issues/99

phillipjohnston commented 2 years ago

Hm, ok, I resolved that problem for libc but now I have no theory on Arduino.

phillipjohnston commented 2 years ago

Well, this is fun. GCC is replacing printf("string with no args"); with puts("string with no args"); even with no optimizations enabled, which is apparently not implemented in a usable way for us in Arduino land and results in a) no output or b) an infinitely rebooting application, depending on whether it's my lucky day or not.

phillipjohnston commented 2 years ago

I suspect the mpaland approach to the definitions resulted in printf_ being used as the actual name instead of printf w/ the Aliasing option, which avoided the optimization in the past. One workaround is to supply a puts that forwards to printf (what I will do for now, though I suspect that might be undefined behavior). The other workaround is to NOT alias the standard library using the preprocessor option, but instead have LibPrintf.h provide macros like: #define printf printf_ to recreate the old behavior and work with the non-aliased names.

phillipjohnston commented 2 years ago

New library has landed with #25, making the release now, should be available the library manager whenever it sees the new version.