ryankurte / efm32-base

Base project for Silicon Labs EFM32 microcontrollers
89 stars 33 forks source link

float/double format strings (sprintf) print blank output. #29

Closed ewheelerinc closed 3 years ago

ewheelerinc commented 3 years ago

Hello Ryan,

I'm trying to print a simple %f in sprintf, but %f is yielding an empty string for %f: sprintf(s, "test: %f", 1.234); This line sets s to "test: " but %f is unpopulated.

Thinking it was a problem with printf, I found a function that uses math functions like log10(), pow(), and exp() from here: https://stackoverflow.com/a/7097567/14055985

but then I got linker errors:

CMakeFiles/space-ham.dir/main.c.obj: In function `dtoa':
/home/zeke/src/space-ham/main.c:104: undefined reference to `log10'
/home/zeke/src/space-ham/main.c:114: undefined reference to `pow'
/home/zeke/src/space-ham/main.c:125: undefined reference to `pow'
/home/zeke/src/space-ham/main.c:129: undefined reference to `floor'

I know I need to add "-lm" to the linker line so I updated my CMAKE_EXE_LINKER_FLAGS as follows (note the -lm at the end): set(CMAKE_EXE_LINKER_FLAGS "${COMMON_DEFINITIONS} -Xlinker -T${LINKER_SCRIPT} -Wl,-Map=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}.map -Wl,--gc-sections -Wl,-v -lm") but that didn't change the undefined reference problem. Where should I add the -lm ?

If I copy/paste the super-long GCC command line generated by cmake that is displayed to the screen upon error, and add -lm to the output, then I get this:

opt/gcc-arm-none-eabi-7-2018-q2-update/bin/../lib/gcc/arm-none-eabi/7.3.1/../../../../arm-none-eabi/lib/thumb/v8-m.main/fpv5-sp/hard/libm.a(lib_a-w_log10.o): 
In function `log10':
w_log10.c:(.text.log10+0xbe): undefined reference to `__errno'
w_log10.c:(.text.log10+0xc8): undefined reference to `__errno'
w_log10.c:(.text.log10+0xda): undefined reference to `__errno'

While I will eventually need math functions, the current issue is just getting sprintf() to format strings with floats. Is there a way to fix this without switching to some external 3rd-party stdio/stdlib/math library?

Thanks for your help!

-Eric

ryankurte commented 3 years ago

hmm, you -should- be able to sprintf floats but sometimes it requires the right configuration for newlib nano, you might try adding -u _printf_float as a linker argument (not sure if you'll need to use -Wl,-u _printf_float or the bare form) here.

Where should I add the -lm

on embedded devices the order of symbol inclusion can be important, the right place to add it is here, and you might need to add both m and c (or newlib, it's been a long time since i've had to fix this). it's also worth checking (from the verbose output) that --specs=nosys.specs is set. fingers crossed one of both of those helps!

ewheelerinc commented 3 years ago

It worked! I added just m and the "bare" form of -u _printf_float (the -Wl form said "no such file or directory"). Now math functions and %f are working.

Thanks so much for your help!

ewheelerinc commented 3 years ago

Also just found this KB article at silabs:

https://www.silabs.com/community/mcu/32-bit/knowledge-base.entry.html/2014/11/19/floating_point_print-7R9j