ESP32S3 printf, fprintf to stdout and LOG output with missing characters

问题描述 投票:0回答:0

我正在使用 fprintf() 将某些传感器的测量值记录到文件或标准输出中。当记录到一个文件时,一切都按预期工作,但是当记录到标准输出时,字符被遗漏了。这是一个输出示例:

2023-03-09 20:58:11, 2, 25.0, 300, 2512, 448                                                              2023-03-09 20:59:26, 2, 25.0, 300, 2508, 4481, 25.0, 300, 2023-03-09 20:58:11, 0, 25.0, 300, 3380, 532                                       
2023-03-09 20:59:31, 2, 25.0, 300, 2508, 448023-03-09 20:59:26, 0, 25.0, 300, 3376, 531
2023-03-09 20:59:31, 1, 25.0, 300, 2543, 449.
2023-03-09 20:59:31, 0, 25.0, 300, 3376, 531.

仅添加缺少的换行符,如下所示:

2023-03-09 20:58:11, 2, 25.0, 300, 2512, 448                                                                2023-03-09 20:59:26, 2, 25.0, 300, 2508, 448
                     1, 25.0, 300, 
2023-03-09 20:58:11, 0, 25.0, 300, 3380, 532
2023-03-09 20:59:31, 2, 25.0, 300, 2508, 448
 023-03-09 20:59:26, 0, 25.0, 300, 3376, 531
2023-03-09 20:59:31, 1, 25.0, 300, 2543, 449
2023-03-09 20:59:31, 0, 25.0, 300, 3376, 531

该程序使用基于 esp-idf 控制台组件的命令行界面。

  • 处理器:ESP32S3
  • Esp-idf: V4.4
  • 主机:MAC OS BigSur
  • 集成开发环境:VSCode
  • 控制台输出通道:USB Serial/JTAG Controller

到目前为止我已经尝试过:

  • 输出到 ESP-IDF 监视器
  • 输出到屏幕串口终端
  • 其他 mac 终端程序,如 serial.app 等
  • 修改任务优先级,包括控制台任务
  • 更改波特率
  • 将 UART ISR 函数放入 RAM
  • printf 和变体而不是 fprintf

除了 REPL 和传感器任务之外,没有其他进程以任何方式使用串口。有没有人对日志或打印输出有类似的问题?我一直在到处寻找,但这似乎不是一个普遍的问题。

根据@romkey的建议,我写了一个最小的例子来重现

#include <stdio.h>
#include <string.h>
#include <time.h>
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

static char *rndstr(char *str, size_t size)
{
    const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQURSTUVWXYZ         ";
    if (size) {
        --size;
        for (size_t n = 0; n < size; n++) {
            int key = rand() % (int) (sizeof charset - 1);
            str[n] = charset[key];
        }
        str[size] = '\0';
    }
    return str;
}

static void print_task(void *arg)
{
    static char some_str[50]; 

    srand(time(NULL));

    while(1)
    {
        for(int i = 0; i < 4; i++) {
            rndstr(some_str, sizeof(some_str));
            fprintf(stdout, "*%s*\n", some_str);
        }
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

static void print_task_start(void)
{
    TaskHandle_t print_task_handle;

    // APP_CPU_NUM: doesn´t work
    // PRO_CPU_NUM: works
    // tskNO_AFFINITY: works except for the first print
    // xTaskCreate(): works
    xTaskCreatePinnedToCore(
        print_task, 
        "print_task", 
        4096, 
        NULL,
        5, 
        &print_task_handle,
        APP_CPU_NUM
    );
    configASSERT(print_task_handle);
}


void app_main(void)
{
    print_task_start();
    while(1)
    {
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

它似乎与命令行界面无关,而是与打印任务运行的 CPU 内核有关。

使用 xTaskCreatePinnedToCore() 时

  • APP_CPU_NUM:不工作
  • PRO_CPU_NUM:有效
  • tskNO_AFFINITY:除了第一次打印外都有效

使用 xTaskCreate() 时有效

console printf esp32 esp-idf
© www.soinside.com 2019 - 2024. All rights reserved.