It is discussed here https://github.com/espressif/esp-idf/issues/3497 and more here maximum ram usable is 96000 · Issue #1163 · espressif/arduino-esp32 · GitHub
Overall, while the ESP32s have much RAM, it is not necessarily freely usable. For global vars the limit seems to be somewhere near 100kB. This makes the ESP32 much less useful than it seemed.
First of all, thank you for tracking down those references and reporting back here...
Heap can be used only by malloc().
Note that your particular problem from the original post can be "adequately" solved my using malloc() to get your buffer, rather than statically allocating it. (although there are frequently reasons to avoid malloc(), it seems like this situation would warrant an exception!)
`dram0_0_seg' overflowed by 88 bytes
Overflowed by 88 bytes? what is it that overflows, and what function tells me that?
dram0_0_seg overflowed, just like it says in the error message. Since it is happening at link time, there isn't a function to tell you about it, just the linker error message.
Global variables use 122604 bytes (37%) of dynamic memory, leaving 205076 bytes for local variables. Maximum is 327680 bytes.
This "normal compile" message seems very misleading, if in fact the limit for the memory it's talking about is only about 120k, rather than the ~300k theoretically available on the chip. Might it be worth submitting a bug report...
Now, since my first guess was right, I might as well keep on guessing! I don't know what "technical issue" prevents the ESP32 from having all of the RAM accessible to the compiler. Sometimes RAM in a chip is not contiguous (one block at 0x10000000, another at 0x2000 0000, neither 16MB long), and this can make things more difficult for a compiler, and prevent single data elements from being longer than a memory segment, but I thought that gcc would handle that sort of thing better than it is doing here.
I still don't know any function which lets me determine what RAM I have left for global vars. Any help is much appreciated.
dram0_0_seg will be a variable defined by the tools in something called a "linker script" that is invoked by the link command issued by the IDE with the -T switch. In this case:
.../packages/esp32/tools/xtensa-esp32-elf-gcc/1.22.0-80-g6c4433a-5.2.0/bin/xtensa-esp32-elf-gcc" -nostdlib "-L/Applications/Arduino-1.8.9 copy.app/Contents/Java/portable/packages/esp32/hardware/esp32/1.0.2/tools/sdk/lib" "-L/Applications/Arduino-1.8.9 copy.app/Contents/Java/portable/packages/esp32/hardware/esp32/1.0.2/tools/sdk/ld" [color=teal][b]-T esp32_out.ld[/b][/color] -T esp32.common.ld -T esp32.rom.ld -T esp32.peripherals.ld -T esp32.rom.spiram_incompatible_fns.ld -u ld_include_panic_highint_hdl ...
(Oh wow - there are multiple -T switches. I didn't even know you could do that!)
A linker script describes the memory layout of a physical chip, and how the "logical" sections that the compiler generates should be fit into that memory.
The esp32_out.ld is the linker script that describes the RAM. It's pretty obscure stuff, but there are comments. It says (among other things):
/* Shared data RAM, excluding memory reserved for ROM bss/data/stack.
Enabling Bluetooth & Trace Memory features in menuconfig will decrease
the amount of RAM available.
Note: Length of this section *should* be 0x50000, and this extra DRAM is available
in heap at runtime. However due to static ROM memory usage at this 176KB mark, the
additional static memory temporarily cannot be used.
*/
dram0_0_seg (RW) : org = 0x3FFB0000 + 0xdb5c,
len = 0x2c200 - 0xdb5c
I guess ... The ROM functions use a chunk of the RAM in the middle? (probably left over from earlier chips with less total RAM? malloc() and etc may get info about the actual RAM usage by the ROM at runtime, which could be what permits it to be used at all.)
THAT "len" (124580 bytes) seems to match up with the limits you are seeing.
There are some additional tools that will help you look at memory usage of your sketch, they live off in the ESP32 tools directory ( ...packages/esp32/tools/xtensa-esp32-elf-gcc/1.22.0-80-g6c4433a-5.2.0/bin/ )
(You'll also need to find the actual location where the IDE has put the sketch binaries.)
size (xtensa-esp32-elf-size) - reports size of the various sections:
.../packages/esp32/tools/xtensa-esp32-elf-gcc/1.22.0-80-g6c4433a-5.2.0/bin/xtensa-esp32-elf-size /tmp/NewArduBuild/test_esp32_heap.ino.elf
text data bss dec hex filename
150840 51428 114040 316308 4d394 /tmp/NewArduBuild/test_esp32_heap.ino.elf
nm (xtensa-esp32-elf-nm) - reports on symbols in the file, especially useful in the form:
xtensa-esp32-elf-nm -SC --size-sort mysketch.elf
4008a0ac 00000490 T rtc_init
400d7400 00000498 T nvs::Page::mLoadEntryTable()
400d7af0 00000544 T nvs::PageManager::load(unsigned int, unsigned int)
3ffdae24 00000800 b s_stub_min_stack
3f401810 00000820 D rtc_gpio_desc
400e1df4 00000ba2 T _dtoa_r
400e3004 00001ffa T _svfiprintf_r
400dc338 000020fe T _vfiprintf_r
400d8d6c 000030de T _svfprintf_r
400de970 000031e2 T _vfprintf_r
3ffbfcf0 0001aa2c B BigBuffer
(The "T", "B", "D" labels indicate whether the object is in text (code), BSS, or Data sections.)