Skip to main content

Memory and limits

A board has much less memory than a PC, and some things work differently from Windows. Here are the figures the VM and the IDE give, and what changes in your program.

Internal RAM and PSRAM​

A board has two memories for your program:

  • The internal RAM, the one the chip carries.
  • The PSRAM, a separate, larger memory chip. Not every board has it, and the profile doesn't say.

The ESP32 and ESP32-S3 VMs work with PSRAM and without it. The ESP32-P4 and ESP32-S31 VMs need it: it is where they keep the screen frames.

WhatWhere it goes
What your program creates: strings, lists, maps, objects…The system decides by its size: small blocks to the internal RAM, and large ones to the PSRAM if there is one. The boundary is 4 KB on the ESP32 and the ESP32-S3, and 16 KB on the ESP32-P4 and the ESP32-S31.
Images: bitmaps, sprites and backgroundsTo the PSRAM if there is one; if not, to the internal RAM. Each pixel takes 2 bytes: a 320 × 240 image takes 153,600 bytes.
The screen's double buffer, on the ESP32 and the ESP32-S3To the internal RAM, and if it doesn't fit, to the PSRAM. One byte per pixel of the view: 76,800 bytes for 320 × 240.
The screen frames, on the ESP32-P4 and the ESP32-S31Two, the size of the panel, in the PSRAM. Two bytes per pixel: 1,036,800 bytes each on a 720 × 720 panel.
Samples and music of 4 KB or moreTo the PSRAM if there is one; if not, to the internal RAM.

To see how much memory you use, use memUse() and memFree(), from the standard library:

WindowsESP32 / ESP32-S3ESP32-P4ESP32-S31
memUse()What the VM has allocated for your programSameSameSame
memFree()Always 0The free internal RAM, without the PSRAMAll the free memory, PSRAM includedAll the free memory, PSRAM included

On the board, the garbage collector kicks in more often than on Windows: its growth factor is 1.2, and on Windows, 1.7 (see GC).

If memory runs out, the VM collects the garbage and tries again, three times. If that fails, it writes "Fallo en ReallocAlloc Null" on the serial monitor, with the bytes it was asking for, and closes.

Program and file size​

The board's flash is split by a partition table that the IDE makes every time it writes to the board. The VM goes in a fixed place, and the file memory (LittleFS), where the program and its resources go, takes from the end of the VM to the end of the flash. The IDE reads the flash size from the board (see Flash the firmware and run).

Board flashFiles on the ESP32 and the ESP32-S3Files on the ESP32-P4 and the ESP32-S31
4 MB2,624 KB960 KB
8 MB6,720 KB5,056 KB
16 MB14,912 KB13,248 KB
32 MB31,296 KB29,632 KB

The VM's space is 1,408 KB on the ESP32 and the ESP32-S3, and 3,072 KB on the ESP32-P4 and the ESP32-S31; before it, in the first 64 KB of the flash, go the bootloader, the partition table and two small system partitions (nvs and phy_init). The figures come from JARU IDE's partition templates, in Compiler\ESP32\<chip>\partitions_template.csv.

The file memory holds everything in the project's Build/flash folder: the compiled program, the boot.cfg and the resources (see The file memory).

Check Storage, on the Storage page of ESP32 Tools (LittleFS Storage Check group), tells you whether it fits. It reads the flash size from the board, adds up what is in Build/flash, counting each file in whole 4 KB blocks, and shows it in a bar:

MessageWhat it means
"OK. Used Space: … KB / Total: … KB (…%)"It fits.
"WARNING: Low storage space…"It fits, but takes up more than 90%.
"ERROR: Capacity exceeded…", with how much is overIt doesn't fit.

It is an estimate: it doesn't write anything. If the files really don't fit, Run stops at step 1, before writing anything: the Output says "File system is full." and "DEPLOYMENT FAILED: Error during LittleFS build.".

Close the serial monitor before Check Storage

Check Storage reads the board through its port, and doesn't move the serial monitor aside: if it is open on that port, it can't read the board. Close it first with Close Serial.

File paths​

On the board, paths are written as in the file memory, not as on Windows:

  • With /, never with \. On Windows both work; on the board, a path like Images\background.bmp doesn't find the file.
  • With the upper and lower case of its name. Windows doesn't tell them apart, and the board's file memory does: if the file is called Images/Background.bmp, "images/background.bmp" works on Windows and not on the board.

The flash: and sd: units and the open modes, which also change on the board, are in File.

What the board does not have​

  • readLine(). On the board it waits for a line from the serial port, and in 0.9.7 nothing reaches it: the IDE's serial monitor doesn't send what you type. The program keeps waiting forever. It happens to the examples that ask for input, such as CheckPrime, Factorial_ForLoop, FibonacciGenerator and Palindromes. On Windows it works.
  • Keys. On the board, Input.map only accepts GPIO, except on the ESP32-S31, which reads a USB keyboard (see Buttons, pins and gamepad). There is no key to quit: a program with an endless loop never ends.
  • The window. Window Scale and closing the window to end the program are Windows things.
  • MQTT.intStats and MQTT.resetIntStats. They only exist on Windows.
  • The debugger. Debug always runs on the Windows VM, and Stop doesn't stop a program on the board (see Run on the board).

What only works on the board​

These modules talk to the board's hardware. On Windows you can use them, but they don't do the same:

ModuleOn Windows
GPIOThe pins are those of the GPIO simulator.
LEDThe strip shows on the WS2812 Strip card of the GPIO simulator.
I2CWriting succeeds, and reading gives 0.
PowerPower.sleep() waits the time of Power.wakeOnTimer the first time it sleeps after that call, and 100 ms otherwise; Power.wakeReason() always returns Power.WAKE_TIMER.
Display.backlightDoes nothing.
Power.sleep() on the Waveshare 2.8 and the JaruCade

After the first Power.sleep(), these boards lose their USB: the serial monitor gets nothing more, and the IDE can't write to them until you start them in download mode (see Supported boards).

All the known issues of JARU, together, are in Known issues.

What looks different from Windows​

Colors​

WindowsESP32 / ESP32-S3ESP32-P4ESP32-S31
With double buffer (Display.mode(2), the default)16.7 million colors (24 bits)256 colors (8 bits)65,536 colors (16 bits)65,536 colors (16 bits)

On the ESP32 and the ESP32-S3, the double buffer stores each pixel in one byte: 3 bits of red, 3 of green and 2 of blue. There are 8 shades of red, 8 of green and 4 of blue, so:

  • two similar colors look the same;
  • a gradient looks stepped;
  • draw.getPixel returns the color as it ended up in the frame, not the one you asked for.

Images and sprites are loaded with 65,536 colors, but when drawn into the double buffer they also go down to 256. With direct mode, Display.mode(1), drawing uses 65,536 colors, but you see each thing being drawn (see Display). For a game, pick colors that stay distinct with 256.

Text​

draw.text doesn't use the same lettering on Windows as on the board:

  • On Windows, text always comes out in the same lettering, 13 pixels high, whatever draw.font says.
  • On the board, draw.font picks one of the screen's fonts:
draw.fontFont on the board
0, 1 (the default), 3 and 5The small one, 6 × 8 pixels
216 pixels high
426 pixels
648 pixels, for clocks
748 pixels, seven-segment
875 pixels

With the default one, text on the board is a little over half its size on Windows. If your game places text by eye on Windows, check on the board that it doesn't overlap or spill out: the width of each letter changes too.