I have seen printf using printf-stdarg.c however, I’m still not sure if it is applicable to my project.
I am using FreeRTOS SMP with RP2040/Pico; and I use the default printf
there (pico-sdk), to print to the USB serial port the RP2040 app creates.
Eventually, my code grew, so it now often does a isr_hardfault
(or other deadlocks) when there is a lot of printing, and typically a gdb backtrace will reveal that at least one of the cores has been running a printf related function at time of hardfault/deadlock.
Then, I noticed https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/main/include/task.h :
An alternative, tiny, third party, and limited * functionality implementation of sprintf() is provided in many of the * FreeRTOS/Demo sub-directories in a file called printf-stdarg.c (note * printf-stdarg.c does not provide a full snprintf() implementation!).
Well, that’s great - I’d really like to try a tiny sprintf() :)
However, I cannot really tell - can I?
The thing is - the pico-sdk already defines a printf
, that defaults to printing to the USB serial port. So, I’d have to somehow override it.
Then, looking at where this file is found in GitHub - FreeRTOS/FreeRTOS: 'Classic' FreeRTOS distribution. Started as Git clone of FreeRTOS SourceForge SVN repo. Submodules the kernel., and which projects have a related Makefile for gcc (since that is how I build by FreeRTOS + pico-sdk code):
$ find FreeRTOS -name '*stdarg.c' | while read f; do ls -la "$f" ; find $(dirname "$f")/ -name Makefile -exec printf " %s\n" {} \; ; done
-rw-r--r-- 1 user None 6.8K Jul 8 09:26 FreeRTOS/FreeRTOS/Demo/ColdFire_MCF52221_CodeWarrior/sources/printf-stdarg.c
-rw-r--r-- 1 user None 6.8K Jul 8 09:26 FreeRTOS/FreeRTOS/Demo/ColdFire_MCF52259_CodeWarrior/printf-stdarg.c
-rw-r--r-- 1 user None 7.6K Jul 8 09:25 FreeRTOS/FreeRTOS/Demo/CORTEX_A9_Cyclone_V_SoC_DK/printf-stdarg.c
-rw-r--r-- 1 user None 6.8K Jul 8 09:25 FreeRTOS/FreeRTOS/Demo/CORTEX_AT91SAM3U256_IAR/printf-stdarg.c
-rw-r--r-- 1 user None 7.3K Jul 8 09:25 FreeRTOS/FreeRTOS/Demo/CORTEX_LM3S6965_GCC_QEMU/LocalDemoFiles/printf-stdarg.c
-rw-r--r-- 1 user None 6.8K Jul 8 09:25 FreeRTOS/FreeRTOS/Demo/CORTEX_M0+_Atmel_SAMD20_XPlained/RTOuseremo/src/printf-stdarg.c
-rw-r--r-- 1 user None 7.6K Jul 8 09:25 FreeRTOS/FreeRTOS/Demo/CORTEX_M4F_MSP432_LaunchPad_IAR_CCS_Keil/system/CCS/printf-stdarg.c
-rw-r--r-- 1 user None 7.6K Jul 8 09:26 FreeRTOS/FreeRTOS/Demo/CORTEX_M4_SimpleLink_CC3220SF_CCS/printf-stdarg.c
-rw-r--r-- 1 user None 7.4K Jul 8 09:26 FreeRTOS/FreeRTOS/Demo/CORTEX_MPS2_QEMU_IAR_GCC/build/gcc/printf-stdarg.c
FreeRTOS/FreeRTOS/Demo/CORTEX_MPS2_QEMU_IAR_GCC/build/gcc/Makefile
-rw-r--r-- 1 user None 6.4K Jul 8 09:26 FreeRTOS/FreeRTOS/Demo/CORTEX_STM32F103_Primer_GCC/printf-stdarg.c
-rw-r--r-- 1 user None 6.6K Jul 8 09:26 FreeRTOS/FreeRTOS/Demo/IA32_flat_GCC_Galileo_Gen_2/Support_Files/printf-stdarg.c
-rw-r--r-- 1 user None 8.5K Jul 8 09:27 FreeRTOS/FreeRTOS/Demo/lwIP_AVR32_UC3/printf-stdarg.c
FreeRTOS/FreeRTOS/Demo/lwIP_AVR32_UC3/AT32UC3A/GCC/Makefile
-rw-r--r-- 1 user None 6.7K Jul 8 09:26 FreeRTOS/FreeRTOS/Demo/MB91460_Softune/SRC/utility/printf-stdarg.c
-rw-r--r-- 1 user None 6.7K Jul 8 09:26 FreeRTOS/FreeRTOS/Demo/MB96340_Softune/FreeRTOS_96348hs_SK16FX100PMC/Src/utility/printf_stdarg.c
-rw-r--r-- 1 user None 6.7K Jul 8 09:26 FreeRTOS/FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/RTOuseremo/src/printf-stdarg.c
-rw-r--r-- 1 user None 6.8K Jul 8 09:26 FreeRTOS/FreeRTOS/Demo/MSP430X_MSP430F5438_CCS/Demo_Source/printf-stdarg.c
-rw-r--r-- 1 user None 7.6K Jul 8 09:26 FreeRTOS/FreeRTOS/Demo/MSP430X_MSP430FR5969_LaunchPad_IAR_CCS/printf-stdarg.c
-rw-r--r-- 1 user None 6.7K Jul 8 09:26 FreeRTOS/FreeRTOS/Demo/PIC32MX_MPLAB/printf-stdarg.c
FreeRTOS/FreeRTOS/Demo/PIC32MX_MPLAB/RTOuseremo.X/Makefile
-rw-r--r-- 1 user None 7.4K Jul 8 09:26 FreeRTOS/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/printf-stdarg.c
FreeRTOS/FreeRTOS/Demo/RISC-V_RV32_QEMU_VIRT_GCC/build/gcc/Makefile
-rw-r--r-- 1 user None 6.8K Jul 8 09:26 FreeRTOS/FreeRTOS/Demo/RX100-RSK_GCC_e2studio/RTOuseremo/printf-stdarg.c
-rw-r--r-- 1 user None 18K Jul 8 09:25 FreeRTOS/FreeRTOS-Plus/Demo/AWS/Device_Shadow_Windows_Simulator/Common/printf-stdarg.c
-rw-r--r-- 1 user None 14K Jul 8 09:25 FreeRTOS/FreeRTOS-Plus/Demo/FreeRTOS_Plus_TCP_Minimal_Windows_Simulator/printf-stdarg.c
… I can see that:
- None of these hits are in the directory
./FreeRTOS/Demo/ThirdParty/Community-Supported/CORTEX_M0+_RP2040
, which would be the one for the MCU I use - All
printf-stdargs.c
files that otherwise exist have file sizes that differ, so they’re likely platform specific - Only the demo projects for CORTEX_MPS2_QEMU_IAR_GCC, lwIP_AVR32_UC3, AT32UC3A, PIC32MX_MPLAB, and RISC-V_RV32_QEMU_VIRT_GCC also have a Makefile
I looked briefly at the Makefile - config.mk - of lwIP_AVR32_UC3, and all I could see was that printf-stdargs.c
was added last to the list of source files to be compiled, and I did not notice any special linker switches.
So I tried the same - added a printf-stdargs.c
to my RP2040 FreeRTOS project, with the contents:
#include "stddef.h"
int printf( char *apBuf, size_t aMaxLen, const char *apFmt, ... )
{
return 0;
}
… and rebuilt; it went fine, but trying to look in the result with readelf:
$ arm-none-eabi-readelf -s my_program.elf | grep 'stdarg'
$
… no filename containing stdarg
is listed among the source files recorded in the .elf binary.
Then again, if I look into the symbols of the binary .elf:
$ arm-none-eabi-nm -a my_program.elf | grep 'printf'
1000e01c T __wrap_printf
1000ce5c T __wrap_snprintf
1000dfd8 T __wrap_vprintf
1000c838 t _vsnprintf
00000000 a printf.c
1000ce84 T vfctprintf
… there is no actual symbol printf
– there is only __wrap_printf
; and if I read the nm
output correctly (i.e. listed .c.
files are followed by symbols defined in them), then __wrap_printf
comes from __call_atexit.c
, and I cannot tell where that comes from.
So, my questions are:
- Can I use a
printf-stdarg.c
approach to override (s)printf for RP2040, or not?- If not, how could I have judged that from existing examples? (e.g. maybe those platforms where there is a demo with
printf-stdarg.c
, do not provide a default stdio/printf like pico-sdk does, and that is why they can use this approach?) - If yes, what is the approach: is it “just” add the source file “last” in the list of source files to be sure it is compiled (well, probably not, judging from my results above) - or does one also have to do additional steps (maybe change linking order of object files; or add some additional code in my
main.c
; or add special linker flags)? If there is a need for additional steps - what are those?- And if yes, what would be the best project to look at, for an example of everything that would have to be changed in a
printf-stdarg.c
, so I can use it on RP2040? (my guess is CORTEX_M0+_Atmel_SAMD20_XPlained, since the RP2040 is also Cortex M0+, but IDK)
- And if yes, what would be the best project to look at, for an example of everything that would have to be changed in a
- If not, how could I have judged that from existing examples? (e.g. maybe those platforms where there is a demo with