堆栈大小问题?

hyuan75
Posts: 18
Joined: Wed Jun 14, 2023 9:03 am

堆栈大小问题?

Postby hyuan75 » Sun Apr 28, 2024 9:52 am

ESP32 IDF 版本:v5.2.1
硬件开发板:ESP32-LyraTD-MSC , ESP32 v1.0

一个很简单的跟https服务器交互的简单应用,以官方的esp_http_client参考代码为样本进行简单改造:

app_main代码如下,创建task的堆栈为8192(8K),应该足够?

Code: Select all

void app_main(void)
{
    //Initialize NVS
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
      ESP_ERROR_CHECK(nvs_flash_erase());
      ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    if(ESP_OK!=connect_wifi()){
        ESP_LOGE(TALKTAG,"Connect to Wifi is fail, aborting...");
    } else{
       ESP_LOGI(TALKTAG, "Connected to Wifi, starting the application...");
       xTaskCreate(&app_task, "app_task", 8192, NULL, 5, NULL);
    }
}
Task的入口函数如下:

Code: Select all

static void app_task(void *pvparameters)
{
    talk_to_server();
    ESP_LOGI(TALKTAG, "Finish talking to server.");
    for (int countdown = 10; countdown >= 0; countdown--) {
        ESP_LOGI(TALKTAG, "%d...", countdown);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }    
    vTaskDelete(NULL);
}
主要调用函数talk_to_server的代码如下

Code: Select all

void talk_to_server(void)
{
    char local_response_buffer[MAX_HTTP_OUTPUT_BUFFER+1] = {0};
    esp_http_client_config_t config = {
        .url = SERVER_WEB_URL,
        .event_handler = _http_event_handler,
        .crt_bundle_attach = esp_crt_bundle_attach,
        .user_data = local_response_buffer,
        //.method = HTTP_METHOD_POST,
    };

    esp_http_client_handle_t client = esp_http_client_init(&config);

    ...
	//中间代码略
	
	...

    esp_http_client_cleanup(client);

}
如果MACRO(MAX_HTTP_OUTPUT_BUFFER)定义为1024,则会发生Stack overflow错误:

#define MAX_HTTP_OUTPUT_BUFFER 1024

***ERROR*** A stack overflow in task talk_to_server_task has been detected.


Backtrace: 0x40081796:0x3ffcdf00 0x40089091:0x3ffcdf20 0x40089f8a:0x3ffcdf40 0x4008b273:0x3ffcdfc0 0x4008a094:0x3ffcdfe0 0x4008a046:0x00000000 |<-CORRUPTED
0x40081796: panic_abort at C:/Users/hyuan/esp/esp-idf/components/esp_system/panic.c:472
0x40089091: esp_system_abort at C:/Users/hyuan/esp/esp-idf/components/esp_system/port/esp_system_chip.c:93
0x40089f8a: vApplicationStackOverflowHook at C:/Users/hyuan/esp/esp-idf/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:553
0x4008b273: vTaskSwitchContext at C:/Users/hyuan/esp/esp-idf/components/freertos/FreeRTOS-Kernel/tasks.c:3630 (discriminator 7)
0x4008a094: _frxt_dispatch at C:/Users/hyuan/esp/esp-idf/components/freertos/FreeRTOS-Kernel/portable/xtensa/portasm.S:451
0x4008a046: _frxt_int_exit at C:/Users/hyuan/esp/esp-idf/components/freertos/FreeRTOS-Kernel/portable/xtensa/portasm.S:246

如果减小MAX_HTTP_OUTPUT_BUFFER定义为512,则应用正常跑完,也能获得服务器的数据
#define MAX_HTTP_OUTPUT_BUFFER 512
如果进一步增加MAX_HTTP_OUTPUT_BUFFER到2048,则体现为HEAP被破坏,跑飞crash.

============================================================================
#define MAX_HTTP_OUTPUT_BUFFER 512 时编译后的内存占用信息及HEAP信息如下:

Total sizes:
Used static DRAM: 33852 bytes ( 146884 remain, 18.7% used)
.data size: 15348 bytes
.bss size: 18504 bytes
Used static IRAM: 91606 bytes ( 39466 remain, 69.9% used)
.text size: 90579 bytes
.vectors size: 1027 bytes
Used Flash size : 847223 bytes
.text: 623595 bytes
.rodata: 223372 bytes
Total image size: 954177 bytes (.bin may be padded larger)

I (492) cpu_start: ESP-IDF: v5.2.1
I (497) cpu_start: Min chip rev: v0.0
I (502) cpu_start: Max chip rev: v3.99
I (507) cpu_start: Chip rev: v1.0
I (512) heap_init: Initializing. RAM available for dynamic allocation:
I (519) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (525) heap_init: At 3FFB8440 len 00027BC0 (158 KiB): DRAM
I (531) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (537) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (544) heap_init: At 400965D8 len 00009A28 (38 KiB): IRAM
I (552) spi_flash: detected chip: generic
I (555) spi_flash: flash io: dio
I (560) main_task: Started on CPU0
I (570) main_task: Calling app_main()



#define KIMI_MAX_HTTP_OUTPUT_BUFFER 1024 时编译后的内存占用信息及HEAP信息如下:
Total sizes:
Used static DRAM: 33852 bytes ( 146884 remain, 18.7% used)
.data size: 15348 bytes
.bss size: 18504 bytes
Used static IRAM: 91606 bytes ( 39466 remain, 69.9% used)
.text size: 90579 bytes
.vectors size: 1027 bytes
Used Flash size : 847179 bytes
.text: 623551 bytes
.rodata: 223372 bytes
Total image size: 954133 bytes (.bin may be padded larger)

I (492) cpu_start: ESP-IDF: v5.2.1
I (497) cpu_start: Min chip rev: v0.0
I (502) cpu_start: Max chip rev: v3.99
I (507) cpu_start: Chip rev: v1.0
I (512) heap_init: Initializing. RAM available for dynamic allocation:
I (519) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (525) heap_init: At 3FFB8440 len 00027BC0 (158 KiB): DRAM
I (531) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (537) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (544) heap_init: At 400965D8 len 00009A28 (38 KiB): IRAM
I (551) spi_flash: detected chip: generic
I (554) spi_flash: flash io: dio
I (559) main_task: Started on CPU0
I (569) main_task: Calling app_main()


============================================================================

应该是函数talk_to_server中定义的局部变量local_response_buffer大小会影响内存分布导致要么Stack overflow, 要么heap被破坏:
void talk_to_server(void)
{
char local_response_buffer[MAX_HTTP_OUTPUT_BUFFER+1] = {0};
.....
}

请教一下这种情况应该如何调整配置?
Last edited by hyuan75 on Mon Apr 29, 2024 4:14 am, edited 1 time in total.

hyuan75
Posts: 18
Joined: Wed Jun 14, 2023 9:03 am

Re: 堆栈大小问题?

Postby hyuan75 » Sun Apr 28, 2024 11:43 am

进一步的验证表明似乎跟内存的分配有关系:如果分配过大的尺寸,会破坏其他模块的已分配内存,请参考以下代码改动和验证:

改动talk_to_server函数里局部变量的内存分配方式,从堆栈内分配(定义函数局部数组)变为从堆内分配(用malloc函数申请,并打印malloc前后全局堆大小):

Code: Select all


#define MAX_HTTP_OUTPUT_BUFFER 512*4

void talk_to_server(void)
{
    char *local_response_buffer = NULL;
    int heapleft = heap_caps_get_free_size(MALLOC_CAP_8BIT);
    ESP_LOGI(TALKTAG, "free heap before malloc :\n%d ", heapleft);
    local_response_buffer = malloc(MAX_HTTP_OUTPUT_BUFFER+ 1);
    heapleft = heap_caps_get_free_size(MALLOC_CAP_8BIT);
    ESP_LOGI(TALKTAG, "free heap after malloc :\n%d ", heapleft);
    if (NULL != local_response_buffer)
    {
   	 esp_http_client_config_t config = {
       		 .url = SERVER_WEB_URL,
       		 .event_handler = _http_event_handler,
     		 .crt_bundle_attach = esp_crt_bundle_attach,
    		 .user_data = local_response_buffer,
	        //.method = HTTP_METHOD_POST,
  		  };

  	  esp_http_client_handle_t client = esp_http_client_init(&config);

    	  ...
	 //中间代码略
	
	  ...

    	 esp_http_client_cleanup(client);
    }

}
从malloc前后打印的free heap大小可以看出,heap大小应该是足够的(分配前后都有100K以上的剩余DRAM/Heap):

I (1879) Talk: free heap before malloc :
195024
I (1889) Talk: free heap after malloc :
192968

I (1919) main_task: Returned froGuru Meditation Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled.

Core 0 register dump:
PC : 0x40108c46 PS : 0x00060130 A0 : 0x8010a7e8 A1 : 0x3ffc02e0
0x40108c46: ieee80211_send_setup at ??:?

A2 : 0x00000001 A3 : 0x3ffd1208 A4 : 0x3ffb7fbc A5 : 0x00000010
A6 : 0x00000005 A7 : 0x00000005 A8 : 0x3ffb7fbc A9 : 0x3ffc02d0
A10 : 0x00000048 A11 : 0x00000003 A12 : 0x00000018 A13 : 0x00000000
A14 : 0x00000001 A15 : 0x00000000 SAR : 0x00000011 EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000001 LBEG : 0x4000c46c LEND : 0x4000c477 LCOUNT : 0x00000000
0x4000c46c: memset in ROM
0x4000c477: memset in ROM



Backtrace: 0x40108c43:0x3ffc02e0 0x4010a7e5:0x3ffc0310 0x4010a828:0x3ffc0350 0x40116c16:0x3ffc0370 0x4011719f:0x3ffc0390 0x40117c6f:0x3ffc03b0 0x401191d5:0x3ffc03d0 0x40164599:0x3ffc03f0 0x40092216:0x3ffc0410 0x40089b9d:0x3ffc0440
0x40108c43: ieee80211_send_setup at ??:?
0x4010a7e5: ieee80211_encap_null_data at ??:?
0x4010a828: ieee80211_pm_tx_null_process at ??:?
0x40116c16: pm_send_nullfunc at ??:?
0x4011719f: pm_go_to_sleep at ??:?
0x40117c6f: pm_active_timeout_process at ??:?
0x401191d5: dbg_lmac_ps_statis_reset at ??:?
0x40164599: pp_timer_do_process at ??:?
0x40092216: ppTask at ??:?
0x40089b9d: vPortTaskWrapper at C:/Users/hyuan/esp/esp-idf/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:134





ELF file SHA256: 4a040b880

CPU halted.

那么一定是内存存在践踏了,请问哪位大侠可以给点提示,是我哪里没有配置好吗?ESP32刚入手,还请多多指点。

Who is online

Users browsing this forum: No registered users and 184 guests