espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.61k stars 7.27k forks source link

一路串口的接收数据任务内,调用打印日志的API,概率很大的系统重启 (IDFGH-3458) #5419

Closed iot1688 closed 4 years ago

iot1688 commented 4 years ago

Environment

Problem Description

采用 GPIO17做TX , GPIO16做RX,建一路串口,然后在该路串口的接收数据任务内,调用打印日志的API,系统会重启

Expected Behavior

Actual Behavior

Steps to reproduce

  1. 建立了串口接收数据任务后
  2. 在电脑上通过串口助手,发送串口数据,发个几十遍就能复现到

// If possible, attach a picture of your setup/wiring here.

Code to reproduce this issue

//串口初始化
void ct_uart_init(uint32_t uart0,uint32_t uart1, uint32_t uart2)
{
    uart_config_t uart2_config;
    uart2_config.baud_rate = uart2;
    uart2_config.data_bits = UART_DATA_8_BITS;  
    uart2_config.parity = UART_PARITY_DISABLE;
    uart2_config.stop_bits = UART_STOP_BITS_1;  
    uart2_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE;
    uart_param_config(UART_NUM_2, &uart2_config);
    //IO  TX:GPIO17  RX:GPIO16
    uart_set_pin(UART_NUM_2, TXD2_PIN, RXD2_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

    uart_driver_install(UART_NUM_2, RX2_BUF_SIZE, TX2_BUF_SIZE, 0, NULL, 0);
    ct_uart_createTask();
}
void ct_uart_createTask(void)
{
    xTaskCreate(uart2_rx_task, "uart2_rx_task", RX2_BUF_SIZE*2, NULL, 10, &pvCreatedTaskUart2);
}
void uart2_rx_task()
{
    uint8_t* data = (uint8_t*) malloc(RX2_BUF_SIZE+1);
    if(NULL != data)
    {
        while (1) 
        {
            memset(data, 0, RX2_BUF_SIZE+1);
            int rxBytes = uart_read_bytes(UART_NUM_2, data, RX2_BUF_SIZE, 10 / portTICK_RATE_MS);
            if (rxBytes > 0) {
                data[rxBytes] = 0;
                //uart_write_bytes(UART_NUM_2, (char *)data, rxBytes);
                ESP_LOGI(GATTS_TAG,"%s\n",data);//加上这句,串口助手多发几十遍数据就会系统重启
            }
        }
        free(data);
        vTaskDelete(pvCreatedTaskUart2);  
    }
}

// If your code is longer than 30 lines, GIST is preferred.

Debug Logs

Debug log goes here, should contain the backtrace, as well as the reset source if it is a crash.
Please copy the plain text here for us to search the error log. Or attach the complete logs but leave the main part here if the log is *too* long.

日志:esp32 [0ERROR A stack overflow in task uart2_rx_task has been detected

Other items if possible

koobest commented 4 years ago

Hi @iot1688

The log tells that the RX task stack overflowed 日志:esp32 [0ERROR A stack overflow in task uart2_rx_task has been detected

Can you try to increase the task stack size?

iot1688 commented 4 years ago

@koobest 你好,试过,但是问题依然存在。 但是,你注意看,实际并没有占掉什么内存,开了2K的空间,1K的数据缓存,实际串口助手发的数据就是“12345”这么简短的,一样说这路串口任务堆栈溢出。如果把这句输入日志的API注销掉,没有任何问题(挂机验证了1个多小时)

iot1688 commented 4 years ago

@koobest ct_uart.h源码

ifndef CT_UART_H

define CT_UART_H

//三路串口
//uart0 默认用来输出调试日志 GPIO3 U0RXD; GPIO1 UORXD

//UART1 SD_DATA_2 GPIO9 U1RXD;SD_DATA_3 GPIO10 U1TXD;

define RX1_BUF_SIZE (1024)

define TX1_BUF_SIZE (512)

define TXD1_PIN (GPIO_NUM_5)

define RXD1_PIN (GPIO_NUM_4)

//UART2 用来与单片机数据交互 GPIO16 U2RXD; GPIO17 U2TXD

define RX2_BUF_SIZE (1024)

define TX2_BUF_SIZE (1024)

define TXD2_PIN (GPIO_NUM_17)

define RXD2_PIN (GPIO_NUM_16)

TaskHandle_t pvCreatedTaskUart2 = NULL;

void ct_uart_init(uint32_t uart0,uint32_t uart1, uint32_t uart2); void ct_uart_createTask(void); void ct_uart2_write_data(char *data,size_t datalen); void uart2_rx_task(void);

endif

ct_uart.c源码

include

include "esp_system.h"

include "esp_spi_flash.h"

include "esp_wifi.h"

include "esp_event_loop.h"

include "esp_log.h"

include "esp_err.h"

include "nvs_flash.h"

include "freertos/FreeRTOS.h"

include "freertos/task.h"

include "driver/ledc.h"

include

include "freertos/FreeRTOS.h"

include "freertos/task.h"

include "driver/uart.h"

include "driver/gpio.h"

include "string.h"

include "ct_uart.h"

define GATTS_TAG "CT_UART"

//串口初始化 void ct_uart_init(uint32_t uart0,uint32_t uart1, uint32_t uart2) { //串口配置结构体 uart_config_t uart2_config;

uart2_config.baud_rate = uart2;         
uart2_config.data_bits = UART_DATA_8_BITS;          
uart2_config.parity = UART_PARITY_DISABLE;          
uart2_config.stop_bits = UART_STOP_BITS_1;          
uart2_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE;  
uart_param_config(UART_NUM_2, &uart2_config);       

uart_set_pin(UART_NUM_2, TXD2_PIN, RXD2_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

uart_driver_install(UART_NUM_2, RX2_BUF_SIZE, TX2_BUF_SIZE, 0, NULL, 0);

ct_uart_createTask();

}

void ct_uart2_write_data(char *data,size_t datalen) { uart_write_bytes(UART_NUM_2, data, datalen); }

void ct_uart_createTask(void) { xTaskCreate(uart2_rx_task, "uart2_rx_task", RX2_BUF_SIZE*2, NULL, 10, &pvCreatedTaskUart2); }

void ct_uart_deleteTask(TaskHandle_t pvCreatedTask) { if(NULL != pvCreatedTask) { vTaskDelete(pvCreatedTask);
} }

void uart2_rx_task() { uint8_t data = (uint8_t) malloc(RX2_BUF_SIZE+1); if(NULL != data) { while (1) { memset(data, 0, RX2_BUF_SIZE+1); int rxBytes = uart_read_bytes(UART_NUM_2, data, RX2_BUF_SIZE, 10 / portTICK_RATE_MS);

        if (rxBytes > 0) {
            data[rxBytes] = 0;

            //uart_write_bytes(UART_NUM_2, (char *)data, rxBytes);
            ESP_LOGI(GATTS_TAG,"%s\n",data);
        }
    }
    free(data);
    vTaskDelete(pvCreatedTaskUart2);  
}

}

koobest commented 4 years ago

2K 栈空间小了一点, 是否可以增大到 4K 进行测试?

iot1688 commented 4 years ago

@koobest
你好,暂时还没去拿电脑试,理论上加大队列空间,会缓解这种问题,想问下,输出日志API会暂用空间吗?占用了后,不会立马释放吗?怎么会导致这个任务堆栈内存溢出呢?

koobest commented 4 years ago

@iot1688 是的, 日志输出的函数会暂用栈内存空间, 但是会释放, 但是释放之前已经导致了栈溢出.

iot1688 commented 4 years ago

@koobest 现在加大到一定的空间后,暂时没有发现问题。TKS

liying016 commented 9 months ago

你好 请问控制台输出乱码一个菱形问号怎么办呀 请问有遇到过吗