YOGYUI

[ESP-IDF] ESP32 메모리 사용량 체크하기 본문

Hardware/Espressif

[ESP-IDF] ESP32 메모리 사용량 체크하기

요겨 2024. 1. 25. 23:58
반응형

 

EspressIf의 SoC인 ESP32 모듈의 정적(static) 및 동적 (dynamic) 메모리 사용량을 체크하는 방법을 알아보자

- EspressIf에서 제공하는 SDK인 ESP-IDF version 5.1.2 기준
- 본 글의 데모는 Ubuntu Linux 22.04.03 LTS 환경에서 구동

1. 개발 환경(idf.py) 준비

※ ESP-IDF의 설치가 이미 진행되었다고 가정 (install.sh)

터미널에서 export.sh 쉘 스크립트를 호출해준다

$ source ${esp-idf-path}/export.sh

 

아래 명령어로 ESP-IDF를 설치해둔 경로가 출력되면 개발 환경 준비 완료 

$ echo ${IDF_PATH}

 

2. Static 메모리 사용량 확인

ESP-IDF SDK의 파이썬 유틸리티 idf.pysize 명령어로 빌드된 펌웨어의 정적 메모리 (Static DRAM 및 IRAM)의 할당량 및 펌웨어 바이너리 파일의 크기를 쉽게 확인할 수 있다

$ cd ${your_idf_project_path}
$ idf.py size

 

ESP32는 320KB의 상당히 한정적인 메모리만 제공하기 때문에 규모가 큰 프로젝트를 진행할 때는 static 변수 사용에 있어서 주의해야 한다

위 예시는 진행중인 Matter 관련 프로젝트 중 하나의 소스코드 size 출력 결과인데, connectedhomeip SDK 자체가 메모리를 꽤나 많이 잡아먹는 녀석이다 보니 SRAM을 거의 다 사용하고 있는 것을 볼 수 있다 

왠만한건 전부 동적 메모리 영역으로 넘겨야 하는데, Heap 사이즈도 한계가 있다보니 결국 PSRAM을 장착한 모듈을 사용할 수 밖에 없는 슬픈 현실..

 

펌웨어가 구동 시 로드하는 모듈별로 사용량을 체크해 코드 최적화를 진행해야 한다면, idf.pysize-componets 명령어를 사용해보자

$ idf.py size-components

각 모듈(.a)별 DRAM, IRAM, Flash 바이너리 사이즈를 개별로 정리해주며, 바이너리 사이즈가 큰 것부터 내림차순으로 출력해준다

위 예시에서 알 수 있듯이, EspressIf의 Matter 개발용 SDK인 ESP-Matter를 사용한다면 상당히 많은 메모리 및 바이너리 사이즈를 libCHIP과 libesp_matter 모듈에 양보(?)해야되기 때문에 Flash Memory 사이즈 및 PSRAM 장착 등 이것저것 신경쓸 게 많아진다

 

소스코드 출력 바이너리별로 사용량 체크도 가능한데, idf.pysize-files 명령어를 사용하면 된다

$ idf.py size-files

.o 혹은 .obj 확장자 등 코드별 빌드 출력물에 대한 개별 분석이 가능하므로, 본인이 직접 작성한 코드의 사이즈를 체크하여 최적화할 수 있는 부분이 있는지 검토하는 작업이 필요할 수 있다

 

참고로 sdkconfig의 CONFIG_COMPILER_OPTIMIZATION_SIZE=y 설정은 필수이며, 이 외에도 메모리 및 플래시 사이즈 최적화를 위한 여러 configuration들이 있으니 ESP-IDF 공식 페이지를 꼭 참고하도록 하자 (글 최하단의 링크 참고) 

3. Heap 메모리 영역 할당량 확인

동적(dynamic) 메모리인 힙(heap) 메모리 영역의 사용량은 펌웨어를 구동하면서 확인해야 한다

ESP-IDF는 메모리 사용량 체크를 위해 상당히 편리한 함수를 제공하고 있는데, 함수들은 아래와 같으며 "esp_heap_caps.h" 헤더파일을 불러와 사용하면 된다

  • heap_caps_get_free_size() can be used to return the current free memory for different memory capabilities.
  • heap_caps_get_largest_free_block() can be used to return the largest free block in the heap, which is also the largest single allocation currently possible. Tracking this value and comparing it to the total free heap allows you to detect heap fragmentation.
  • heap_caps_get_minimum_free_size() can be used to track the heap "low watermark" since boot.
  • heap_caps_get_info() returns a multi_heap_info_t structure, which contains the information from the above functions, plus some additional heap-specific data (number of allocations, etc.).
  • heap_caps_print_heap_info() prints a summary of the information returned by heap_caps_get_info() to stdout.
  • heap_caps_dump() and heap_caps_dump_all() output detailed information about the structure of each block in the heap. Note that this can be a large amount of output.

[코드 구현 예시]

내가 ESP32 관련 코드를 작성하면서 무조건 구현해두는 구문은 아래와 같다

#include "esp_heap_caps.h"

void get_heap_size_info(size_t *total_size, size_t *free_size)
{
    *total_size = heap_caps_get_total_size(MALLOC_CAP_8BIT);
    *free_size = heap_caps_get_free_size(MALLOC_CAP_8BIT);
}

void print_heap_size_info() 
{
    size_t heap_total_size = 0;
    size_t heap_free_size = 0;
    get_heap_size_info(&heap_total_size, &heap_free_size);
    ESP_LOGI("logger", "Heap total size: %zu", heap_total_size);
    ESP_LOGI("logger", "Heap free size: %zu (%g%% used)", heap_free_size, float(heap_total_size - heap_free_size) / float(heap_total_size) * 100.f);
}

 

위 예시는 2MB PSRAM이 장착된 ESP32 모듈 (ESP32-WROOM-32E-N8R2)에서 호출한 결과로 힙 영역이 2353399바이트라 상당히 여유로운 것을 알 수 있다 

만약 Matter 관련 프로젝트를 진행하는데, 수십개의 Matter 엔드포인트(endpoint)가 붙어야하는 bridge 디바이스같은 경우 각 엔드포인트마다 FreeRTOS stack을 할당해야 하기 때문에 생각보다 많은 메모리가 필요하므로 나처럼 프로젝트 초창기부터 PSRAM 장착을 고려하는 것을 추천한다  

 

이 외에도 힙메모리 관련 디버깅을 위한 함수들이 더 존재하므로, 마찬가지로 아래 링크를 참고하기 바란다

 

끝~!

 

[Reference]

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/performance/ram-usage.html

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/heap_debug.html

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/performance/size.html#idf-py-size

반응형
Comments