ESP8266 rtos中,串口日志打印和串口发送数据的问题?

为什么ESP8266 RTOS中,串口打印日志ESP_LOGI要比串口发送uart_write_bytes要优先?
比如在如下任务中:

static void uart_event_task(void *pvParameters)
{
    uart_event_t event;
    uint8_t *dtmp = (uint8_t *) malloc(RD_BUF_SIZE);

    for (;;) {
        // Waiting for UART event.
        if (xQueueReceive(uart0_queue, (void *)&event, (portTickType)portMAX_DELAY)) {
            bzero(dtmp, RD_BUF_SIZE);
            ESP_LOGI(TAG, "uart[%d] event:", EX_UART_NUM);

            switch (event.type) {
                // Event of UART receving data
                // We'd better handler data event fast, there would be much more data events than
                // other types of events. If we take too much time on data event, the queue might be full.
                case UART_DATA:
                    ESP_LOGI(TAG, "[UART DATA]: %d", event.size);
                   // uart_read_bytes(EX_UART_NUM_1, dtmp, event.size, portMAX_DELAY);

                    uart_read_bytes(EX_UART_NUM, dtmp, event.size, portMAX_DELAY);
                    ESP_LOGI(TAG, "[DATA EVT]:");
                    uart_write_bytes(EX_UART_NUM, (const char *) dtmp, event.size);
                    ESP_LOGI(TAG, "[DATA EVT1111111]:");

                    break;

                // Event of HW FIFO overflow detected
                case UART_FIFO_OVF:
                    ESP_LOGI(TAG, "hw fifo overflow");
                    // If fifo overflow happened, you should consider adding flow control for your application.
                    // The ISR has already reset the rx FIFO,
uart_flush_input(EX_UART_NUM);
                    xQueueReset(uart0_queue);
                    break;

                // Event of UART ring buffer full
                case UART_BUFFER_FULL:
                    ESP_LOGI(TAG, "ring buffer full");
                    // If buffer full happened, you should consider encreasing your buffer size
                    // As an example, we directly flush the rx buffer here in order to read more data.
                    uart_flush_input(EX_UART_NUM);
                    xQueueReset(uart0_queue);
                    break;

                case UART_PARITY_ERR:
                    ESP_LOGI(TAG, "uart parity error");
                    break;

                // Event of UART frame error
                case UART_FRAME_ERR:
                    ESP_LOGI(TAG, "uart frame error");
                    break;

                // Others
                default:
                    ESP_LOGI(TAG, "uart event type: %d", event.type);
                    break;
            }
        }
    }

    free(dtmp);
    dtmp = NULL;
    vTaskDelete(NULL);
}

当我发送如下数据时

img

发现日志打印都是先打印的,但是如果按照函数,日志信息的打印和我发送的数据应该是交叉的,为什么是把所有日志信息打印出来后,再打印我发送的数据呢?

这个问题可能是由于ESP_LOGI和uart_write_bytes的不同实现方式导致的。这两个函数可能在不同的优先级环境中运行,或者他们可能使用不同的缓冲机制。

ESP_LOGI函数可能立即将日志信息写入到输出设备(例如串口或文件),而uart_write_bytes可能将要发送的数据首先放入一个队列或缓冲区,然后由另一个线程或任务在适当的时候发送出去。因此,ESP_LOGI的日志输出可能会比uart_write_bytes的数据发送更早出现。

另外,ESP_LOGI可能会立即触发中断并直接将日志写入UART,而uart_write_bytes可能会等待DMA或其他硬件资源可用。

这只是可能的解释,实际的情况可能会因硬件、RTOS配置、驱动程序等因素而有所不同。如果你需要更详细的信息,可能需要查看ESP8266 RTOS和相关驱动程序的源代码,以了解这两个函数的具体实现方式。

  • 以下回答由chatgpt基于相关博客总结生成:

    根据ESP8266 RTOS中的文档,uart_write_bytes函数是用于向UART发送字节数据的函数。但是,如果在这个函数和日志输出函数之间发生了延迟,日志输出会比发送数据更快地打印出来。这是因为在RTOS中,日志输出的优先级比发送数据的优先级更高。

    如果希望日志信息和发送的数据能够交叉打印,可以使用RTOS提供的vTaskDelay函数来添加适当的延迟。通过添加适当的延迟,可以确保日志信息和发送数据交替打印,而不会出现优先级问题。具体步骤如下:

    1. 在发送数据之后,调用vTaskDelay函数来添加一些延迟。可以通过调整延迟的时间来确保日志信息和发送数据交替打印。
    2. 在添加延迟之后,执行日志输出函数。由于在前面添加了一些延迟,因此日志输出和发送数据将会交替打印。

    下面是参考代码:

    // 发送数据
    uart_write_bytes(uart_num, data, len);
    
    // 添加延迟
    vTaskDelay(pdMS_TO_TICKS(50));
    
    // 输出日志信息
    ESP_LOGI(TAG, "Data sent: %s", data);
    

    在这个例子中,我们添加了一个50毫秒的延迟,并在延迟之后输出了一条日志信息。这样,日志信息和发送数据就能够交替打印了。

    请注意,延迟的时间以及日志输出和发送数据的顺序可能会因系统和应用程序的特定需求而有所不同。因此,在实际应用程序中,需要根据具体情况调整延迟时间和代码顺序。