I have installed the C/C++ SDK for the Raspberry PI Pico on a Raspberry pi 4. Then I have compiled and executed the hello world example via USB successfully. I monitor the output using minicom and so far everything works fine.
However, when I add a printf before the while loop, it has no effect.
Here is the SDK Example with my 1 line addition:
#include <stdio.h>
#include "pico/stdlib.h"
int main() {
stdio_init_all();
printf( "Let's start\n" ); // <-- This is my addition
while (true) {
printf("Hello, world!\n");
sleep_ms(1000);
}
return 0;
}
I do see Hello World!
in minicom once a second as desired, but no Let's start
. What could be the reason and how can I overcome this?
UPDATE: Answers to some questions in the comments:
fflush(stdout);
after the first printf. It didn't helpsleep_ms(1000)
before the printf. This didn't help eitherThe most likely cause is that the USB initialization isn't done when stdio_init_all()
returns. The first print outs will then be lost.
Define PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS
to make it wait for a certain amout of time. You must define it before including the pico
headers, otherwise, pico/stdio_usb.h
will define it to 0
.
// this must be done before indirectly including "pico/stdio_usb.h":
#ifndef PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS
#define PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS (5000)
#endif
#include <stdio.h>
#include "pico/stdlib.h"
int main(void) {
_Bool result = stdio_init_all(); // should now wait for up to 5 seconds
printf( "Let's start.\n" );
for(unsigned co = 0;; ++co) {
printf("Hello, world! %u\n", co); // Aconcagua's suggestion. Do you see "0"?
sleep_ms(1000);
}
return 0;
}
If 5 seconds isn't enough, try waiting indefinitely and instead initialize USB explicitly with stdio_usb_init()
which, according to the documentation, "is useful if you don't want any initial stdout output to be discarded before the connection is established".
#ifndef PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS
#define PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS (-1)
#endif
#include <stdio.h>
#include "pico/stdlib.h"
int main(void) {
_Bool result = stdio_usb_init(); // init USB explicitly
printf( "Let's start.\n" );
for(unsigned co = 0;; ++co) {
printf("Hello, world! Init: %d id: %u\n", (int)result, co);
sleep_ms(1000);
}
return 0;
}
Some USB drivers seems to still loose I/O directly after the connection has been established, so the pico library has a define
for a "post connect" delay too. It's set to 50 (ms
) by default, but you could increase it:
// this also needs to be done before including any pico headers:
#ifndef PICO_STDIO_USB_POST_CONNECT_WAIT_DELAY_MS
#define PICO_STDIO_USB_POST_CONNECT_WAIT_DELAY_MS (1500)
#endif
If defining both PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS (-1)
and PICO_STDIO_USB_POST_CONNECT_WAIT_DELAY_MS (1500)
doesn't help, then you'll have no other option than to sleep manually after stdio_usb_init
returns:
_Bool result = stdio_usb_init();
sleep_ms(PICO_STDIO_USB_POST_CONNECT_WAIT_DELAY_MS);
Note: PICO_STDIO_USB_POST_CONNECT_WAIT_DELAY_MS
was added in
commit 13be546dc393e6ae8154e127f2b5cc8f5ee8fd95
Author: Graham Sanderson <graham.sanderson@raspberrypi.com>
Date: Fri Oct 8 09:01:30 2021 -0500
and requires that you recompile the pico sdk. What happens in the library when a connection is established is actually just:
sleep_ms(PICO_STDIO_USB_POST_CONNECT_WAIT_DELAY_MS);