|
| 1 | +--- |
| 2 | +title: "Optimizing RAM Usage on ESP32-C2" |
| 3 | +date: 2025-11-28 |
| 4 | +summary: ESP32-C2 has 256 KB of physical RAM, but with default configurations, only 24 KB remains free in typical Wi-Fi + BLE scenarios. This article explores comprehensive memory optimization strategies that can free up over 100 KB of RAM, making complex applications viable on this cost-effective chip. |
| 5 | +authors: |
| 6 | + - zheng-zhong |
| 7 | + - he-xin-lin |
| 8 | +tags: ["ESP32-C2", "Memory Optimization", "Performance", "ESP-IDF"] |
| 9 | +--- |
| 10 | + |
| 11 | +## Overview |
| 12 | + |
| 13 | +{{< alert >}} |
| 14 | +This article is largely based on the [ESP Memory Usage Optimization](https://docs.espressif.com/projects/esp-techpedia/en/latest/esp-friends/advanced-development/performance/reduce-ram-usage.html#memory-usage-comparison) document. If differences appear in the future due to updates, please consider the document as the most accurate source. |
| 15 | +{{< /alert >}} |
| 16 | + |
| 17 | +The ESP32-C2 chip provides 256 KB of available physical RAM, making it an excellent cost-effective solution for IoT applications. However, when testing with default ESP-IDF configuration, running the [BLE + Wi-Fi coexistence example](https://github.com/espressif/esp-idf/tree/v5.5-beta1/examples/bluetooth/nimble/bleprph_wifi_coex) leaves only 24 KB of free memory—which is insufficient for developing complex applications. |
| 18 | + |
| 19 | +The root cause of this issue is that ESP32-C2's default configuration prioritizes performance, compiling many core components into IRAM to improve execution speed. For cost-sensitive applications that primarily require simple control operations, the memory usage can be significantly optimized. With deep optimization, it's possible to free up more than 100 KB of additional memory. |
| 20 | + |
| 21 | +This article documents RAM optimization for ESP32-C2 based on ESP-IDF v5.5, explaining the impact of each optimization and how to enable them. |
| 22 | + |
| 23 | +{{< alert >}} |
| 24 | +Some optimization methods listed in this article may reduce system performance and stability. After implementing RAM optimizations, thorough performance and stability testing should be conducted to ensure the application meets all requirements. |
| 25 | +{{< /alert >}} |
| 26 | + |
| 27 | +## ESP32-C2 Memory Map Overview |
| 28 | + |
| 29 | +ESP32-C2 features 256 KB of on-chip RAM, which is separate from the ROM used for boot and system code—ROM is not counted within these 256 KB. The memory map for ESP32-C2 closely resembles those of other ESP chips: RAM is allocated for data, stack, heap, and code execution, while certain regions are reserved by the system and peripherals. |
| 30 | + |
| 31 | +Even though not specifically about ESP32-C2, the article [ESP32 Memory Map 101](https://developer.espressif.com/blog/2024/08/esp32-memory-map-101/) provides a useful primer on how memory is typically organized on ESP chips. The overall memory region concepts (dedicated areas for instruction and data, reserved and shared buffers, etc.) are similar across the ESP family, even if exact sizes or addresses differ. |
| 32 | + |
| 33 | +## Checking Current Free Memory |
| 34 | + |
| 35 | +Before optimizing memory, it's essential to understand the current memory usage. To analyze memory consumption for static memory, you can compile your application and then use the commands `idf.py size` and `idf.py size-components`. |
| 36 | + |
| 37 | +For runtime memory usage, the functions `esp_get_free_heap_size()` and `esp_get_minimum_free_heap_size()` can retrieve the current free heap memory and the minimum free heap size since system startup, respectively. For more details, refer to the [ESP-IDF Heap Memory Documentation](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c2/api-reference/system/heap_debug.html). |
| 38 | + |
| 39 | +## ESP32-C2 Memory Test Results |
| 40 | + |
| 41 | +The following data shows the amount of free memory on the ESP32-C2 using ESP-IDF tag v5.5-beta1, tested with default configuration (after `idf.py set-target esp32c2`) versus various optimization configurations. |
| 42 | + |
| 43 | +### Test Scenario Descriptions |
| 44 | + |
| 45 | +- **Wi-Fi station**: Following the [Wi-Fi station example](https://github.com/espressif/esp-idf/tree/release/v5.5/examples/wifi/getting_started/station). Print free memory after the device successfully obtains an IP address (GOT_IP event). |
| 46 | +- **WiFi station + 1TLS(MQTTS)**: Using the [mqtt/ssl example](https://github.com/espressif/esp-idf/tree/v5.5-beta1/examples/protocols/mqtt/ssl) and print free memory after the MQTT_EVENT_DATA event is triggered. |
| 47 | +- **bleprph_wifi_coex**: Following the [BLE + Wi-Fi coexistence example](https://github.com/espressif/esp-idf/tree/v5.5-beta1/examples/bluetooth/nimble/bleprph_wifi_coex), after the WiFi GOT_IP event is triggered, initialize nimble and enable BLE advertising, then print free memory. |
| 48 | +- **bleprph_wifi_coex + mbedtls + power_save**: Based on [`bleprph_wifi_coex`](https://github.com/espressif/esp-idf/tree/v5.5-beta1/examples/bluetooth/nimble/bleprph_wifi_coex), integrate [https_mbedtls](https://github.com/espressif/esp-idf/tree/v5.5-beta1/examples/protocols/https_mbedtls) and [power_save](https://github.com/espressif/esp-idf/tree/v5.5-beta1/examples/wifi/power_save) functionality, then print free memory after connecting to the HTTPS server. For the demo implementation and optimization configuration files, refer to [this repository](https://github.com/Jacques-Zhao/ble_wifi_mbetlds_mem_opt_demo). |
| 49 | + |
| 50 | +### Default Configuration Memory Usage Comparison |
| 51 | + |
| 52 | +| Test Senario | Default Config (KB free) | Optimized Config (KB free) | |
| 53 | +| -------------------------------------------- | ------------------------ | -------------------------- | |
| 54 | +| WiFi station | 95 | 169 | |
| 55 | +| WiFi station + 1TLS(MQTTS) | 55 | 152 | |
| 56 | +| bleprph_wifi_coex | 24 | 125 | |
| 57 | +| bleprph_wifi_coex + mbedtls + power_save | Insufficient | 115 | |
| 58 | + |
| 59 | +{{< alert >}} |
| 60 | +This data focuses on ESP32-C2 memory optimization processes and results. For more comprehensive memory usage statistics across different chips and scenarios, refer to the [ESP Memory Usage Optimization](https://docs.espressif.com/projects/esp-techpedia/en/latest/esp-friends/advanced-development/performance/reduce-ram-usage.html#memory-usage-comparison) documentation. |
| 61 | +{{< /alert >}} |
| 62 | + |
| 63 | +## Optimization Strategies |
| 64 | + |
| 65 | +The optimization strategies in this article are based on a custom test case combining `bleprph_wifi_coex + mbedtls + power_save`, which includes common scenarios: Wi-Fi + BLE + HTTPS + power save auto-sleep. For the demo implementation and optimization configuration files, refer to [this repository](https://github.com/Jacques-Zhao/ble_wifi_mbetlds_mem_opt_demo). Without any optimizations, this scenario triggers a reset due to insufficient runtime memory. |
| 66 | + |
| 67 | +### Optimization Approach Comparison |
| 68 | + |
| 69 | +| Optimization Approach | v5.4.1 (bytes) | v5.5 (bytes) | Description | |
| 70 | +| --------------------- | -------------- | ------------ | ------------------------------------------------------------------------ | |
| 71 | +| No optimization | Insufficient | Insufficient | Default configuration after `idf.py set-target esp32c2` | |
| 72 | +| Basic optimization | 62,840 | 60,212 | Follows the ESP Memory Usage Optimization guide (see below) | |
| 73 | +| Advanced optimization | 91,976 | 90,576 | On top of basic optimization | |
| 74 | +| Deep optimization | | 118,096 | On top of advanced optimization, suitable for v5.5.x and newer | |
| 75 | + |
| 76 | +## No optimization |
| 77 | + |
| 78 | +Default configuration after `idf.py set-target esp32c2`, ensuring only basic functionality (e.g., enabling Bluetooth, PM), with no memory-specific optimizations. See the [default configuration file](https://github.com/Jacques-Zhao/ble_wifi_mbetlds_mem_opt_demo/blob/main/sdkconfig.defaults). |
| 79 | + |
| 80 | +## Basic Optimization |
| 81 | + |
| 82 | +Follows [ESP Memory Usage Optimization](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/performance/ram-usage.html) guide, involving IRAM heap memory optimization. |
| 83 | + |
| 84 | +Key optimization items include: |
| 85 | + |
| 86 | +- Moving FreeRTOS functions from IRAM to flash |
| 87 | +- Moving Wi-Fi functions from IRAM to flash |
| 88 | +- Reducing Wi-Fi static buffers |
| 89 | +- Optimizing lwIP memory usage |
| 90 | +- Optimizing mbedTLS configuration |
| 91 | + |
| 92 | +Through these optimization configurations (see [sdkconfig.defaults.opt.1](https://github.com/Jacques-Zhao/ble_wifi_mbetlds_mem_opt_demo/blob/main/sdkconfig.defaults.opt.1)), available memory can be increased to 62 KB after all functions are executed. |
| 93 | + |
| 94 | +## Advanced Optimization |
| 95 | + |
| 96 | +Based on basic optimization, further deep optimization. This represents the "final optimization" result for v5.4.x and earlier versions. |
| 97 | + |
| 98 | +Advanced optimization mainly includes: |
| 99 | + |
| 100 | +1. **Enable CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY** |
| 101 | + After enabling [`CONFIG_SPI_FLASH_AUTO_SUSPEND`](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c2/api-reference/kconfig-reference.html#config-spi-flash-auto-suspend), enabling [`CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY`](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c2/api-reference/kconfig-reference.html#config-bt-ctrl-run-in-flash-only) places all Bluetooth controller code in flash, freeing approximately 20 KB of memory. |
| 102 | + |
| 103 | +2. **Enable Compiler Optimization Options** |
| 104 | + - [`CONFIG_COMPILER_OPTIMIZATION_SIZE`](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c2/api-reference/kconfig-reference.html#config-compiler-optimization) |
| 105 | + - [`CONFIG_COMPILER_SAVE_RESTORE_LIBCALLS`](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c2/api-reference/kconfig-reference.html#config-compiler-save-restore-libcalls) |
| 106 | + These compiler optimizations can free approximately 8 KB of additional memory. |
| 107 | + |
| 108 | +For the complete advanced optimization configuration file, refer to [sdkconfig.defaults.opt.2](https://github.com/Jacques-Zhao/ble_wifi_mbetlds_mem_opt_demo/blob/main/sdkconfig.defaults.opt.2). With all the above configurations enabled (basic + advanced optimization), available memory increases to 90 KB. |
| 109 | + |
| 110 | +## Deep Optimization |
| 111 | + |
| 112 | +Continues optimization beyond advanced optimization, but only effective on ESP-IDF v5.5 and later. |
| 113 | + |
| 114 | +This optimization leverages new features (such as flash suspend) in ESP-IDF v5.5 to place more code in flash, thereby freeing IRAM and minimizing memory usage, especially when [`CONFIG_SPI_FLASH_AUTO_SUSPEND`](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c2/api-reference/kconfig-reference.html#config-spi-flash-auto-suspend) is enabled. For a detailed list of all such configurations, refer to [sdkconfig.flash_auto_suspend_iram_reduction](https://github.com/espressif/esp-idf/blob/release/v5.5/tools/test_apps/configs/sdkconfig.flash_auto_suspend_iram_reduction). |
| 115 | + |
| 116 | +For the complete deep optimization configuration file, refer to [sdkconfig.defaults.opt.3](https://github.com/Jacques-Zhao/ble_wifi_mbetlds_mem_opt_demo/blob/main/sdkconfig.defaults.opt.3). |
| 117 | + |
| 118 | +With all these configurations enabled on ESP-IDF v5.5 can save an additional 20 KB of memory compared to v5.4.2. |
| 119 | + |
| 120 | +With v5.5, available memory after connecting to an HTTPS server can reach 118 KB, with IRAM `.text` section occupying only 10,050 bytes. |
| 121 | + |
| 122 | +In contrast, with v5.4.2 using the same configuration, available memory after connecting to an HTTPS server is 95 KB, with IRAM `.text` section occupying 31,206 bytes. |
| 123 | + |
| 124 | +### IRAM Text Section Comparison |
| 125 | + |
| 126 | +IRAM `.text` section memory consumption data obtained using the `idf.py size` command: |
| 127 | + |
| 128 | +| Optimization Approach | v5.4.1 (bytes) | v5.5 (bytes) | |
| 129 | +| --------------------- | -------------- | ------------ | |
| 130 | +| No optimization | 93,592 | 100,616 | |
| 131 | +| Basic optimization | 56,384 | 60,088 | |
| 132 | +| Advanced optimization | 36,130 | 35,912 | |
| 133 | +| v5.5 deep optimization| N/A | 9,742 | |
| 134 | + |
| 135 | +The significant reduction in IRAM usage (from ~36 KB to ~10 KB) demonstrates the effectiveness of v5.5's deep optimization features. |
0 commit comments