pico-sdk
pico-sdk copied to clipboard
Inconsistent ordering of output to STDOUT
I have found that mixing different methods of writing to stdout results in inconsistent ordering of the output.
The following simple program illustrates this:
// Test sequencing of STDOUT
#include <pico.h>
#include <pico/time.h>
#include <pico/stdio.h>
#include <pico/stdio_usb.h>
#include <stdio.h>
int main (int argc, const char **argv)
{
stdio_init_all();
while ( ! stdio_usb_connected() ) sleep_ms(1000);
char a = 'A';
char b = 'B';
fwrite (&a, 1, 1, stdout); // Output the character 'A'
printf ("%c", b); // Output the character 'B'
fflush (stdout);
printf ("\n");
}
Clearly the expected output is AB. However, in practice the output is BA.
The CMakeLists.txt file I am using is:
cmake_minimum_required(VERSION 3.12)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
project(sio_test C CXX ASM)
pico_sdk_init()
add_executable(${PROJECT_NAME} main.c)
target_link_libraries(${PROJECT_NAME}
pico_stdlib
pico_time
pico_stdio
pico_stdio_usb
)
pico_enable_stdio_usb(${PROJECT_NAME} 1)
pico_add_extra_outputs(${PROJECT_NAME})
A slightly refined example with the same result
// Test sequencing of STDOUT
#include <pico.h>
#include <pico/time.h>
#include <pico/stdio.h>
#include <pico/stdio_usb.h>
#include <stdio.h>
int main (int argc, const char **argv)
{
stdio_init_all();
while ( ! stdio_usb_connected() ) sleep_ms(1000);
char a = 'A';
char b = 'B';
fprintf (stdout, "%c", a); // Output the character 'A'
printf ("%c", b); // Output the character 'B'
fflush (stdout);
printf ("\n");
}
This is because we try to reduce code size by preventing the HUGE amount of FILE handling code used by fprintf and friends from being pulled in just for a simple printf. This means that printf does not go thru the C-library, whereas fprintf does, and the latter is what is buffering.
You can fix your problem, by moving the fflush(stdout) after the fprintf, but also we will be adding
PICO_STDIO_SHORT_CIRCUIT_CLIB_FUNCS define in the next release, which you can set to 0 to for output from printf to go thru the c-library
You can set PICO_STDIO_SHORT_CIRCUIT_CLIB_FUNCS=1 in your target_compile_options if you want to mix printf and fprintf(stdout). The reason we don't do that by default is that otherwise you pull in all the C library FILE handling code