[ESP32] Program size is greater than maximum

So I’m concerned about the amount of memory my program is taking up on my ESP32. There are probably a myriad of ways I could optimize the code.

Output is a really long list of compilations and dependencies:

CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32dev.html
PLATFORM: Espressif 32 (54.3.20) > Espressif ESP32 Dev Module
HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash
DEBUG: Current (cmsis-dap) External (cmsis-dap, esp-bridge, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
PACKAGES: 
 - framework-arduinoespressif32 @ 3.2.0 
 - framework-arduinoespressif32-libs @ 5.4.0+sha.2f7dcd862a
 - tool-esptoolpy @ 4.8.9
 - tool-mklittlefs @ 3.2.0
 - tool-riscv32-esp-elf-gdb @ 14.2.0+20240403
 - tool-xtensa-esp-elf-gdb @ 14.2.0+20240403
 - toolchain-xtensa-esp-elf @ 14.2.0+20241119
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 47 compatible libraries
Scanning dependencies...
Dependency Graph
|-- ArduinoJson @ 7.4.1
|-- NTPClient @ 3.2.1
|-- esp32wifi
|-- FS @ 3.2.0
|-- LittleFS @ 3.2.0
|-- littlefs_funcs
|-- SD @ 3.2.0
|-- sensor_read_json
|-- SPI @ 3.2.0
|-- write_read_json
|-- BluetoothSerial @ 3.2.0
|-- Preferences @ 3.2.0
|-- WiFi @ 3.2.0
Building in release mode
Compiling .pio\build\esp32dev\src\main.cpp.o
Building .pio\build\esp32dev\bootloader.bin
Generating partitions .pio\build\esp32dev\partitions.bin
Compiling .pio\build\esp32dev\libf37\NTPClient\NTPClient.cpp.o
Compiling .pio\build\esp32dev\libb51\Network\NetworkClient.cpp.o
Compiling .pio\build\esp32dev\libb51\Network\NetworkEvents.cpp.o
Compiling .pio\build\esp32dev\libb51\Network\NetworkInterface.cpp.o
Compiling .pio\build\esp32dev\libb51\Network\NetworkManager.cpp.o
Compiling .pio\build\esp32dev\libb51\Network\NetworkServer.cpp.o
esptool.py v4.8.9
Creating esp32 image...
Merged 2 ELF sections
Successfully created esp32 image.
Compiling .pio\build\esp32dev\libb51\Network\NetworkUdp.cpp.o
Archiving .pio\build\esp32dev\libf37\libNTPClient.a
Compiling .pio\build\esp32dev\lib0bb\WiFi\AP.cpp.o
Compiling .pio\build\esp32dev\lib0bb\WiFi\STA.cpp.o
Compiling .pio\build\esp32dev\lib0bb\WiFi\WiFi.cpp.o
Compiling .pio\build\esp32dev\lib0bb\WiFi\WiFiAP.cpp.o
Compiling .pio\build\esp32dev\lib0bb\WiFi\WiFiGeneric.cpp.o
Compiling .pio\build\esp32dev\lib0bb\WiFi\WiFiMulti.cpp.o
Archiving .pio\build\esp32dev\libb51\libNetwork.a
Compiling .pio\build\esp32dev\lib0bb\WiFi\WiFiSTA.cpp.o
Compiling .pio\build\esp32dev\lib0bb\WiFi\WiFiScan.cpp.o
Compiling .pio\build\esp32dev\libd69\esp32wifi\ESP32WifiShowNetworks.cpp.o
Compiling .pio\build\esp32dev\lib888\FS\FS.cpp.o
Compiling .pio\build\esp32dev\lib888\FS\vfs_api.cpp.o
Compiling .pio\build\esp32dev\lib486\LittleFS\LittleFS.cpp.o
Compiling .pio\build\esp32dev\libc7e\littlefs_funcs\littlefs_funcs.cpp.o
Compiling .pio\build\esp32dev\libdd3\SPI\SPI.cpp.o
Compiling .pio\build\esp32dev\lib4a2\SD\SD.cpp.o
Archiving .pio\build\esp32dev\lib0bb\libWiFi.a
Compiling .pio\build\esp32dev\lib4a2\SD\sd_diskio.cpp.o
Archiving .pio\build\esp32dev\libd69\libesp32wifi.a
Compiling .pio\build\esp32dev\lib4a2\SD\sd_diskio_crc.c.o
Archiving .pio\build\esp32dev\lib486\libLittleFS.a
Archiving .pio\build\esp32dev\libdd3\libSPI.a
Compiling .pio\build\esp32dev\libc1a\sensor_read_json\sensor_read.cpp.o
Compiling .pio\build\esp32dev\libddc\write_read_json\write_read_json.cpp.o
Archiving .pio\build\esp32dev\lib888\libFS.a
Compiling .pio\build\esp32dev\lib62b\BluetoothSerial\BTAddress.cpp.o
Compiling .pio\build\esp32dev\lib62b\BluetoothSerial\BTAdvertisedDeviceSet.cpp.o
Compiling .pio\build\esp32dev\lib62b\BluetoothSerial\BTScanResultsSet.cpp.o
Compiling .pio\build\esp32dev\lib62b\BluetoothSerial\BluetoothSerial.cpp.o
Archiving .pio\build\esp32dev\libc7e\liblittlefs_funcs.a
Compiling .pio\build\esp32dev\libdd9\Preferences\Preferences.cpp.o
Archiving .pio\build\esp32dev\lib4a2\libSD.a
Compiling .pio\build\esp32dev\FrameworkArduino\ColorFormat.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\Esp.cpp.o
Archiving .pio\build\esp32dev\libc1a\libsensor_read_json.a
Compiling .pio\build\esp32dev\FrameworkArduino\FirmwareMSC.cpp.o
Compiling .pio\build\esp32dev\FrameworkArduino\FunctionalInterrupt.cpp.o
Compiling .pio\build\esp32dev\FrameworkArduino\HEXBuilder.cpp.o
Compiling .pio\build\esp32dev\FrameworkArduino\HWCDC.cpp.o
Compiling .pio\build\esp32dev\FrameworkArduino\HardwareSerial.cpp.o
Compiling .pio\build\esp32dev\FrameworkArduino\IPAddress.cpp.o
Archiving .pio\build\esp32dev\libdd9\libPreferences.a
Compiling .pio\build\esp32dev\FrameworkArduino\MD5Builder.cpp.o
Archiving .pio\build\esp32dev\lib62b\libBluetoothSerial.a
Archiving .pio\build\esp32dev\libddc\libwrite_read_json.a
Compiling .pio\build\esp32dev\FrameworkArduino\MacAddress.cpp.o
Compiling .pio\build\esp32dev\FrameworkArduino\Print.cpp.o
Compiling .pio\build\esp32dev\FrameworkArduino\SHA1Builder.cpp.o
Compiling .pio\build\esp32dev\FrameworkArduino\Stream.cpp.o
Compiling .pio\build\esp32dev\FrameworkArduino\StreamString.cpp.o
Compiling .pio\build\esp32dev\FrameworkArduino\Tone.cpp.o
Compiling .pio\build\esp32dev\FrameworkArduino\USB.cpp.o
Compiling .pio\build\esp32dev\FrameworkArduino\USBCDC.cpp.o
Compiling .pio\build\esp32dev\FrameworkArduino\USBMSC.cpp.o
Compiling .pio\build\esp32dev\FrameworkArduino\WMath.cpp.o
Compiling .pio\build\esp32dev\FrameworkArduino\WString.cpp.o
Compiling .pio\build\esp32dev\FrameworkArduino\base64.cpp.o
Compiling .pio\build\esp32dev\FrameworkArduino\cbuf.cpp.o
Compiling .pio\build\esp32dev\FrameworkArduino\chip-debug-report.cpp.o
Compiling .pio\build\esp32dev\FrameworkArduino\esp32-hal-adc.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\esp32-hal-bt.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\esp32-hal-cpu.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\esp32-hal-dac.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\esp32-hal-gpio.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\esp32-hal-i2c-ng.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\esp32-hal-i2c-slave.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\esp32-hal-i2c.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\esp32-hal-ledc.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\esp32-hal-matrix.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\esp32-hal-misc.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\esp32-hal-periman.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\esp32-hal-psram.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\esp32-hal-rgb-led.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\esp32-hal-rmt.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\esp32-hal-sigmadelta.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\esp32-hal-spi.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\esp32-hal-time.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\esp32-hal-timer.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\esp32-hal-tinyusb.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\esp32-hal-touch-ng.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\esp32-hal-touch.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\esp32-hal-uart.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\firmware_msc_fat.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\freertos_stats.cpp.o
Compiling .pio\build\esp32dev\FrameworkArduino\libb64\cdecode.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\libb64\cencode.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\main.cpp.o
Compiling .pio\build\esp32dev\FrameworkArduino\stdlib_noniso.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\wiring_pulse.c.o
Compiling .pio\build\esp32dev\FrameworkArduino\wiring_shift.c.o
Archiving .pio\build\esp32dev\libFrameworkArduino.a
Linking .pio\build\esp32dev\firmware.elf
Retrieving maximum program size .pio\build\esp32dev\firmware.elf
Checking size .pio\build\esp32dev\firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [==        ]  18.6% (used 61092 bytes from 327680 bytes)
Flash: [===Error: The program size (1710954 bytes) is greater than maximum allowed (1310720 bytes)
==*** [checkprogsize] Explicit exit, status 1
=====]  130.5% (used 1710954 bytes from 1310720 bytes)

I didn’t expect the program to be this intensive and I’m not even halfway done writing the code.

Any tips? Are there tools that can help optimize or remove unused packages? Or perhaps it could be the partitions - how can I check the current partition size and possibly adjust them to allow for more room for my program?

I am using the devkit in this box (it has pre-soldered pins so it works much better for SD capabilities & whatnot).
Amazon.com: LAFVIN Basic Starter Kit for ESP32 ESP-32S WiFi I OT Development Board with Tutorial Compatible with Arduino IDE : Electronics
I believe it’s 4 MB flash but i can’t quite verify…

Also when I calculate size I get the following:

Calculating size .pio\build\esp32dev\firmware.elf
   text    data     bss     dec     hex filename
1487089  247100   34329 1768518  1afc46 .pio\build\esp32dev\firmware.elf
1 Like

No reason to be concerned. Using the Bluetooth or builtin BLE stacks in a project increase the size drastically. You could optimize your project using BLE instead of BluetoothSerial and use the NimBLE-Arduino BLE stack.

But for your project I think you should simply choose another partition table layout.

The ESP32 DevKit is using the default.csv partition layout which offers two OTA partitions with a size of 1310720 Bytes (0x140000) and a data partition with 1441792 bytes (0x160000).

If you need the OTA feature you can simply switch to the min_spiffs.csv which reduces the data partition to 131072 bytes (0x20000) and increase the OTA partitions to 1966080 bytes (0x1E0000).

If you don’t need OTA, choose the huge_app.csv layout which gives you 3145728 bytes (0x300000) for your App partition and 917504 bytes (0xE0000) for the data partition.

To change the partition layout in your project use board.built_partitions in the platformio.ini, e.g:

board.build_partitions = min_spiffs.csv
board.build_partitions = huge_app.csv

If none of the existing partition layouts fit your needs you can create your own custom layout. For this create a custom.csv file in the root directory of your project (at same level as the platformio.ini file) and set board.build_partitions = custom.csv in your platformio.ini.

1 Like

Thanks for your reply as always. :slight_smile:

I asked Copilot for help on cutting out unnecessary or redundant libraries and reducing the code.

I was also able to get the SD card working (I took your advice and used a different ESP32 that had the pins pre-soldered, then stretched over two breadboards). So if I wanted to use that SD card for OTA purposes, could I use it to save space on the memory?

That’s not possible due to the nature how OTA update works.
For OTA updates you always need at least two app partitions (OTA0 and OTA1).
One of the partition is marked as active. If an update is performed, the data will be written into the inactive partition. When the update process has finished and all checks have been passed the active partition will be marked as inactive and the formerly inactive partition will be marked as active. Then the ESP resets and boots from the partition which is marked as active.

Since you’re using an SD card, you can remove the SPIFFS partition from the partitions layout and use the extra space for your OTA partitions. Keep in mind that partitions of type app have to be placed at offsets aligned to 0x10000 (64 KB)

2 Likes