printf为什么在while循环中能工作,但在树莓派pico之前不能?

huangapple go评论62阅读模式
英文:

Why does printf work in the while loop, but not before on a raspberry pi pico?

问题

我已经在Raspberry Pi 4上为Raspberry Pi Pico安装了C/C++ SDK。然后,我通过USB成功编译并执行了hello world示例。我使用minicom监视输出,到目前为止一切都正常。

但是,在while循环之前添加printf语句时,没有任何效果。

以下是SDK示例及我的一行添加内容:

#include <stdio.h>
#include "pico/stdlib.h"

int main() {
    stdio_init_all();

    printf("Let's start\n"); // <-- 这是我的添加部分

    while (true) {
        printf("Hello, world!\n");
        sleep_ms(1000);
    }
    return 0;
}

我在minicom中每秒看到Hello World!,但没有Let's start。可能的原因是什么,我该如何解决?

英文:

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 &lt;stdio.h&gt;
#include &quot;pico/stdlib.h&quot;

int main() {
    stdio_init_all();

    printf( &quot;Let&#39;s start\n&quot; ); // &lt;-- This is my addition

    while (true) {
        printf(&quot;Hello, world!\n&quot;);
        sleep_ms(1000);
    }
    return 0;
}

I do see Hello World! in minicom once a second as desired, but no Let&#39;s start. What could be the reason and how can I overcome this?

UPDATE: Answers to some questions in the comments:

  • I have also tried to add fflush(stdout); after the first printf. It didn't help
  • Usually, I connect minicom before I start the application. I restart the application several times with or without the debugger and it makes no difference. Minicom does not 'drop' between restarts. It seems the connection to the USB port is stable whatever I do. It shows the "hello world" part even if I launch minicom after the application on the pico has started
  • Adding a numeric identifier to see if some of the 'hello world' drops: I did this in a more complicated app with timers and various interrupts. They work just fine and they all get called after the while loop starts
  • I have also added a sleep_ms(1000) before the printf. This didn't help either

答案1

得分: 1

USB初始化可能还没有完成,导致在stdio_init_all()返回时丢失了最初的打印输出。

在包含pico头文件之前,定义PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS来等待一定的时间。否则,pico/stdio_usb.h会将其定义为0

#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(); // 现在应该等待最多5秒

    printf("开始。\n");

    for(unsigned co = 0;; ++co) {
        printf("你好,世界!%u\n", co); // Aconcagua的建议。你看到“0”了吗?
        sleep_ms(1000);
    }
    return 0;
}

如果5秒不够长,请尝试无限等待,并且使用stdio_usb_init()明确初始化USB,根据文档,“如果你不希望在连接建立之前丢弃任何初始标准输出,这是有用的”

#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(); // 明确初始化USB

    printf("开始。\n");

    for(unsigned co = 0;; ++co) {
        printf("你好,世界! 初始化:%d  id:%u\n", (int)result, co);
        sleep_ms(1000);
    }
    return 0;
}

有些USB驱动程序在连接建立后仍然会直接丢失I/O,因此pico库还有一个“post connect”延迟的define。默认设置为50 (ms),但你可以增加它:

// 这也需要在包含任何pico头文件之前完成:
#ifndef PICO_STDIO_USB_POST_CONNECT_WAIT_DELAY_MS
#define PICO_STDIO_USB_POST_CONNECT_WAIT_DELAY_MS (1500)
#endif

如果同时定义PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS (-1)PICO_STDIO_USB_POST_CONNECT_WAIT_DELAY_MS (1500)没有帮助,那么在stdio_usb_init返回后,你将别无选择,只能手动睡眠:

_Bool result = stdio_usb_init();
sleep_ms(PICO_STDIO_USB_POST_CONNECT_WAIT_DELAY_MS);

注:PICO_STDIO_USB_POST_CONNECT_WAIT_DELAY_MS在以下提交中被添加:

commit 13be546dc393e6ae8154e127f2b5cc8f5ee8fd95
Author: Graham Sanderson <graham.sanderson@raspberrypi.com>
Date:   Fri Oct 8 09:01:30 2021 -0500

并且需要重新编译pico sdk。连接建立后库中实际发生的事情只是:

sleep_ms(PICO_STDIO_USB_POST_CONNECT_WAIT_DELAY_MS);
英文:

The 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 &quot;pico/stdio_usb.h&quot;:
#ifndef PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS
#define PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS (5000)
#endif

#include &lt;stdio.h&gt;
#include &quot;pico/stdlib.h&quot;

int main(void) {
    _Bool result = stdio_init_all(); // should now wait for up to 5 seconds

    printf( &quot;Let&#39;s start.\n&quot; );

    for(unsigned co = 0;; ++co) {
        printf(&quot;Hello, world! %u\n&quot;, co); // Aconcagua&#39;s suggestion. Do you see &quot;0&quot;?
        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 &lt;stdio.h&gt;
#include &quot;pico/stdlib.h&quot;

int main(void) {
    _Bool result = stdio_usb_init(); // init USB explicitly

    printf( &quot;Let&#39;s start.\n&quot; );

    for(unsigned co = 0;; ++co) {
        printf(&quot;Hello, world!  Init: %d  id: %u\n&quot;, (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 &lt;graham.sanderson@raspberrypi.com&gt;
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);

huangapple
  • 本文由 发表于 2023年4月13日 18:40:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76004473.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定