天天看點

ESP 系列雜談(六):使用 ESP-IDF 程式設計時的記憶體使用情況查詢

1. 記憶體使用情況查詢

1. 記憶體使用情況查詢

以下介紹常用的記憶體使用情況查詢 API,如果想了解更多,請參考 堆記憶體配置設定。

1.1 esp_get_free_heap_size()

在正常編譯燒錄示例的基礎上加入了以下代碼來列印空閑堆記憶體:

你可以分别在需要檢測記憶體使用情況的 API 前後添加此 API,如剛進入 app_main() 函數時、完成 Wi-Fi 或 BLE 初始化時和 app_main() 函數結束時加上上述代碼來列印檢視空閑堆記憶體。比如使用以下代碼來檢測

wifi_init_sta()

的記憶體使用情況:

printf("before init wifi : free_heap_size = %d\n", esp_get_free_heap_size());
wifi_init_sta();
printf("after init wifi : free_heap_size = %d\n", esp_get_free_heap_size());
           

以下是對應 log:

before init wifi : free_heap_size = 270848
I (596) wifi:wifi driver task: 3ffc1d30, prio:23, stack:6656, core=0
I (596) system_api: Base MAC address is not set
I (596) system_api: read default base MAC address from EFUSE
I (626) wifi:wifi firmware version: 10db11f
I (626) wifi:wifi certification version: v7.0
I (626) wifi:config NVS flash: enabled
I (626) wifi:config nano formating: disabled
I (626) wifi:Init data frame dynamic rx buffer num: 32
I (636) wifi:Init management frame dynamic rx buffer num: 32
I (636) wifi:Init management short buffer num: 32
I (646) wifi:Init dynamic tx buffer num: 32
I (646) wifi:Init static rx buffer size: 1600
I (646) wifi:Init static rx buffer num: 10
I (656) wifi:Init dynamic rx buffer num: 32
I (766) phy: phy_version: 4182, f1ba940, Jun  4 2020, 19:40:07, 0, 0
I (766) wifi:mode : sta (30:ae:a4:80:01:c4)
I (766) wifi station: wifi_init_sta finished.
I (896) wifi:new:<6,0>, old:<1,0>, ap:<255,255>, sta:<6,0>, prof:13
I (896) wifi:state: init -> auth (b0)
I (896) wifi:state: auth -> assoc (0)
I (906) wifi:state: assoc -> run (10)
I (1226) wifi:connected with zztest, aid = 5, channel 6, BW20, bssid = 20:6b:e7:34:f5:36
I (1226) wifi:security: WPA2-PSK, phy: bgn, rssi: -21
I (1226) wifi:pm start, type: 1

I (1276) wifi:AP's beacon interval = 102400 us, DTIM period = 1
I (2586) esp_netif_handlers: sta ip: 192.168.1.100, mask: 255.255.255.0, gw: 192.168.1.1
I (2586) wifi station: got ip:192.168.1.100
I (2586) wifi station: connected to ap SSID:zztest password:espressif
after init wifi : free_heap_size = 232000
           

可以清楚的看到 log 首尾分别列印了空閑記憶體,如果不存在其他幹擾的情況下,它們的內插補點即為

wifi_init_sta()

使用的記憶體。

如何使用 esp-idf 建立與編譯示例請檢視 ESP-IDF 程式設計指南。

注:你也可以使用 esp_get_minimum_free_heap_size() 來檢測最小空閑記憶體。

1.2 heap_caps_print_heap_info()

heap_caps_print_heap_info()` 能列印具有給定功能的所有記憶體的清單。在正常編譯燒錄示例的基礎上加入了以下代碼來列印給定功能的所有記憶體的清單:

printf("heap_caps metadata test\n");
heap_caps_print_heap_info(MALLOC_CAP_8BIT);
heap_caps_print_heap_info(MALLOC_CAP_32BIT);
           

你可以在需要檢測給定功能的記憶體使用情況的地方使用此 API。比如在 station 示例裡的 app_main 函數最後加上上述三行後,log 如下:

heap_caps metadata test
Heap summary for capabilities 0x00000004:
  At 0x3ffae6e0 len 6432 free 0 allocated 6292 min_free 0
    largest_free_block 0 alloc_blocks 27 free_blocks 0 total_blocks 27
  At 0x3ffb9308 len 158968 free 103012 allocated 55256 min_free 100064
    largest_free_block 102720 alloc_blocks 159 free_blocks 8 total_blocks 167
  At 0x3ffe0440 len 15072 free 15036 allocated 0 min_free 15036
    largest_free_block 15036 alloc_blocks 0 free_blocks 1 total_blocks 1
  At 0x3ffe4350 len 113840 free 113804 allocated 0 min_free 113804
    largest_free_block 113804 alloc_blocks 0 free_blocks 1 total_blocks 1
  Totals:
    free 231852 allocated 61548 min_free 228904 largest_free_block 113804
Heap summary for capabilities 0x00000002:
  At 0x3ffae6e0 len 6432 free 0 allocated 6292 min_free 0
    largest_free_block 0 alloc_blocks 27 free_blocks 0 total_blocks 27
  At 0x3ffb9308 len 158968 free 103012 allocated 55256 min_free 100064
    largest_free_block 102720 alloc_blocks 159 free_blocks 8 total_blocks 167
  At 0x3ffe0440 len 15072 free 15036 allocated 0 min_free 15036
    largest_free_block 15036 alloc_blocks 0 free_blocks 1 total_blocks 1
  At 0x3ffe4350 len 113840 free 113804 allocated 0 min_free 113804
    largest_free_block 113804 alloc_blocks 0 free_blocks 1 total_blocks 1
  At 0x40095d54 len 41644 free 41608 allocated 0 min_free 41600
    largest_free_block 41608 alloc_blocks 0 free_blocks 1 total_blocks 1
  Totals:
    free 273460 allocated 61548 min_free 270504 largest_free_block 113804
           

可以看到此 API 清楚的列印了具有給定功能的所有記憶體的清單。

注:你也可以使用 heap_caps_get_minimum_free_size() 來獲得具有給定功能的所有區域的最小總可用記憶體。

1.3 檢查是否有較大的全局變量

使用

make size-components

檢視生成的固件記憶體使用情況, 檢視你的子產品中是否存在較大的全局變量

total sizes:
 DRAM .data size:   13272 bytes
 DRAM .bss  size:   34024 bytes
Used static DRAM:   47296 bytes (  77284 available, 38.0% used)
Used static IRAM:   96352 bytes (  34720 available, 73.5% used)
      Flash code: 1101719 bytes
    Flash rodata:  267772 bytes
Total image size:~1479115 bytes (.bin may be padded larger)
Per-archive contributions to ELF file:
            Archive File DRAM .data & .bss   IRAM Flash code & rodata   Total
                 libbt.a        325   2338    460     155773    53596  212492
               libmesh.a        186   3636      0     161096    38471  203389
           libnet80211.a        924   8906   3782     111740    13750  139102
            libmbedtls.a        100    268     30     108099    19263  127760
               liblwip.a         19   4172      0      89540    16876  110607
                  libc.a          0     20      0      85809     6516   92345
...
...
           
  1. DRAM: 連結器将非常量靜态資料和未初始化資料放入 0x3FFB0000 — 0x3FFF0000 這 256kB 的區域。注意,如果使用藍牙堆棧,此區域會減少 64kB(通過将起始位址移至 0x3FFC0000 )。如果使用了記憶體跟蹤的功能,該區域的長度還要減少 16kB 或者 32kB。放置靜态資料後,留在此區域中的剩餘空間都用作運作時堆。常量資料也可以放在 DRAM 中,需要使用 DRAM_ATTR 宏來聲明。
    • bss: 未初始化的全局變量。
    • data: 已初始化的全局變量。
  2. IRAM: ESP-IDF 将内部 SRAM0 區域(在技術參考手冊中有定義)的一部分配置設定為指令 RAM。除了開始的 64kB 用作 PRO CPU 和 APP CPU 的高速緩存外,剩餘記憶體區域(從 0x40080000 至 0x400A0000 )被用來存儲應用程式中部分需要在RAM中運作的代碼。
注: 記憶體布局說明

1.4 vTaskList()

同時你可以使用 FreeRTOS 列印系統目前的任務清單,任務狀态優先級,使用率等資訊。使用示例如下:

void app_main()
{
    xTaskCreate(test_task, "test_task", 4096, NULL, 6, NULL);
    static char InfoBuffer[512] = {0}; 
    while (1) {
        vTaskList((char *) &InfoBuffer);
		printf("任務名      任務狀态 優先級   剩餘棧 任務序号\r\n");
		printf("\r\n%s\r\n", InfoBuffer);
        vTaskDelay(2000 / portTICK_PERIOD_MS); 
    }
}
           

對應 log 列印如下:

任務名      任務狀态    優先級   剩餘棧 任務序号

main            R       1       2996    2
IDLE0           R       0       1232    3
test_task       B       6       3460    5
Tmr Svc         B       1       2684    4
esp_timer       B       22      3632    1
           

這樣就可以檢視每個 task 的相關資訊了。

繼續閱讀