ESP Memory Usage Optimization
Introduction
Due to the hardware resource constraints of embedded chips, running complex application code may lead to insufficient memory. Most of the default configuration items in ESP-IDF prioritize performance, but in actual products, a good balance between performance and memory usage can be achieved through appropriate memory configuration.
Warning
Some memory optimization methods listed in this document may reduce system performance and stability. Sufficient performance and stability testing should be conducted after optimization to ensure the application meets its requirements.
Obtaining Current Free Memory
Before optimizing memory usage, it is necessary to know the current memory consumption. For static memory usage, you can use the idf.py size and idf.py size-components commands to gather statistics memory usage. For runtime memory consumption, xPortGetFreeHeapSize() and xPortGetMinimumEverFreeHeapSize() functions can be used to obtain the current free memory and the minimum heap memory remaining since system startup, respectively. For more granular memory allocation, you can enable the CONFIG_FREERTOS_USE_TRACE_FACILITY and CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS options and then use the vTaskList() function to get the high watermark for each task stack.
Available Optimization Options
Wi-Fi Memory Optimization
Wi-Fi performance is affected by many parameters, with trade-offs between them. Proper configuration can not only improve performance but also increase available memory and system stability. Configuration options vary significantly depending on the chip, so for Wi-Fi memory optimization and throughput, please refer to the relevant chip documentation under How to Improve Wi-Fi Performance.
LwIP Memory Optimization
Since RAM is allocated dynamically from the heap, most of lwIP’s RAM usage is also dynamically allocated. Therefore, changing lwIP settings to reduce RAM usage might not affect idle RAM usage but can reduce peak RAM consumption. For LwIP memory optimization, see LwIP Minimum RAM Usage.
Mbed TLS Memory Optimization
Mbed TLS is a C library used to implement cryptographic primitives, X.509 certificate handling, and SSL/TLS and DTLS protocols. When using the Mbed library for encryption and decryption, memory usage can be reduced by adjusting its configuration. For Mbed memory optimization, see Mbed Minimum RAM Usage.
BLE Memory Optimization
Compared to Bluedroid, NimBLE uses less memory and a smaller firmware size. Additionally, you can disable certain features and reduce buffer sizes to achieve optimal memory usage. For scenarios where BLE is only used for provisioning, try the following configurations:
Reduce maximum connections and related parameters:
CONFIG_BT_NIMBLE_MAX_CONNECTIONS=1
CONFIG_BT_NIMBLE_MAX_BONDS=2
CONFIG_BT_NIMBLE_MAX_CCCDS=2
CONFIG_BT_NIMBLE_WHITELIST_SIZE=2
If there are no high-speed requirements, reduce buffer sizes and counts:
CONFIG_BT_NIMBLE_MSYS_1_BLOCK_COUNT=12
CONFIG_BT_NIMBLE_MSYS_1_BLOCK_SIZE=100
CONFIG_BT_NIMBLE_MSYS_2_BLOCK_COUNT=4
CONFIG_BT_NIMBLE_TRANSPORT_ACL_FROM_LL_COUNT=12
CONFIG_BT_NIMBLE_TRANSPORT_EVT_COUNT=5
CONFIG_BT_NIMBLE_TRANSPORT_EVT_DISCARD_COUNT=3
Disable unnecessary features:
CONFIG_BT_NIMBLE_ROLE_CENTRAL=n
CONFIG_BT_NIMBLE_ROLE_OBSERVER=n
CONFIG_BT_NIMBLE_SECURITY_ENABLE=n
Other Configuration Optimizations
For performance and power-saving purposes, some functions are placed in IRAM by default. If needed, you can reconfigure these functions to be placed back into Flash:
CONFIG_SPI_SLAVE_ISR_IN_IRAM=n
CONFIG_ESP_WIFI_IRAM_OPT=n
CONFIG_ESP_WIFI_RX_IRAM_OPT=n
CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH=y
CONFIG_RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH=y
CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y
Reduce the length of some system queues:
CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=16
Enable nano format options:
NEWLIB_NANO_FORMAT=y
Disable unnecessary features:
CONFIG_WS_TRANSPORT=n
Reduce Task Stack Sizes
In the default ESP-IDF configuration, Task Stack sizes include a large margin to accommodate different chips and allow users to add application code. Reducing Task Stack sizes can free up memory for dynamic allocation.
Common Task Stack configuration items:
CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE
CONFIG_BT_LE_CONTROLLER_TASK_STACK_SIZE
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE
CONFIG_ESP_TIMER_TASK_STACK_SIZE
CONFIG_FREERTOS_IDLE_TASK_STACKSIZE
CONFIG_LWIP_TCPIP_TASK_STACK_SIZE
Optimization Example and Result Statistics
Testing the bleprph_wifi_coex example demonstrates the effect of memory optimization by comparing memory usage before and after Wi-Fi and BLE connections.
Hardware and Software Environment
Hardware: ESP32-C2
Software: ESP-IDF 11eaf41b37267ad7709c0899c284e3683d2f0b5e (tag: v5.2)
Configuration Changes
CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y
CONFIG_EXAMPLE_ESP_PING_COUNT=5
CONFIG_BT_ENABLED=y
CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_MAX_BONDS=2
CONFIG_BT_NIMBLE_MAX_CCCDS=2
CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=2048
CONFIG_BT_NIMBLE_ROLE_CENTRAL=n
CONFIG_BT_NIMBLE_ROLE_OBSERVER=n
CONFIG_BT_NIMBLE_SECURITY_ENABLE=n
CONFIG_BT_NIMBLE_MSYS_1_BLOCK_COUNT=12
CONFIG_BT_NIMBLE_MSYS_1_BLOCK_SIZE=100
CONFIG_BT_NIMBLE_MSYS_2_BLOCK_COUNT=4
CONFIG_BT_NIMBLE_TRANSPORT_ACL_FROM_LL_COUNT=12
CONFIG_BT_NIMBLE_TRANSPORT_EVT_COUNT=5
CONFIG_BT_NIMBLE_TRANSPORT_EVT_DISCARD_COUNT=3
CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT=n
CONFIG_BT_NIMBLE_WHITELIST_SIZE=2
CONFIG_BT_LE_CONTROLLER_TASK_STACK_SIZE=2048
CONFIG_ESP_COEX_SW_COEXIST_ENABLE=n
CONFIG_ESP_EVENT_POST_FROM_ISR=n
CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=n
CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH=y
CONFIG_RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH=y
CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=16
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=1536
CONFIG_ESP_TIMER_TASK_STACK_SIZE=2048
CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=3
CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=6
CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER_NUM=6
CONFIG_ESP_WIFI_AMPDU_TX_ENABLED=n
CONFIG_ESP_WIFI_AMPDU_RX_ENABLED=n
CONFIG_ESP_WIFI_IRAM_OPT=n
CONFIG_ESP_WIFI_RX_IRAM_OPT=n
CONFIG_ESP_WIFI_ENABLE_WPA3_SAE=n
CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n
CONFIG_ESP_WIFI_SLP_BEACON_LOST_OPT=y
CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM=0
CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT=n
CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=768
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y
CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y
CONFIG_LWIP_L2_TO_L3_COPY=y
CONFIG_LWIP_MAX_SOCKETS=8
CONFIG_LWIP_SO_LINGER=y
CONFIG_LWIP_SO_RCVBUF=y
CONFIG_LWIP_NETBUF_RECVINFO=y
CONFIG_LWIP_GARP_TMR_INTERVAL=30
CONFIG_LWIP_MLDV6_TMR_INTERVAL=30
CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=16
CONFIG_LWIP_DHCP_RESTORE_LAST_IP=y
CONFIG_LWIP_DHCPS=n
CONFIG_LWIP_IPV6_NUM_ADDRESSES=6
CONFIG_LWIP_IPV6_FORWARD=y
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=6144
CONFIG_LWIP_TCP_SACK_OUT=y
CONFIG_LWIP_MAX_UDP_PCBS=24
CONFIG_LWIP_UDP_RECVMBOX_SIZE=12
CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=2048
CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=6
CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=8
CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=6288
CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=2048
CONFIG_MBEDTLS_DYNAMIC_BUFFER=y
CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y
CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=n
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=n
CONFIG_NEWLIB_TIME_SYSCALL_USE_HRT=y
Optimization Results
The table below shows the system’s available memory before and after optimization. The results indicate that approximately 60 KB of memory can be saved through configuration optimization.
Available Memory |
Before Optimization |
After Optimization |
Difference |
---|---|---|---|
Current Available (bytes) |
33,232 |
95,040 |
61,808 |
Minimum Available (bytes) |
25,804 |
91,252 |
65,448 |