Custom board works well with short program but bootloops with bigger one

Newbie here, trying to move from Arduino IDE to VSC + PlatformIO and having a really hard time. I have been working with Arduino for about 5 years now, I am pretty decent at the hardware side of things but software has always been my weak point.
I make my own PCBs, and lately I’ve been using ESP32-S3. In Arduino IDE I use the “ESP32S3 Dev Module” board and all my PCB’s work just fine.

For PlatformIO, I’ve been having tons of problems. I use the ESP32-S3-WROOM-1-N4 module, and there does not seem to be a default board that works well with this basic module.
I found this post:

And I managed to create a new JSON file for a new board from the info on that post.
I then found the problem that the Arduino pins header file was missing, I added one on .platformio\packages\framework-arduinoespressif32\variants
Then I thought I had finally managed to fix it.
I uploaded a simple sketch, it worked and I could use the serial monitor.
But then I tried to port a bigger sketch from another project and it entered a boot loop as soon as I uploaded the code.
The error I get is this:

ELF file SHA256: 6360e88d7b7dd159

Build:Mar 27 2021
rst:0xc (RTC_SW_CPU_RST),boot:0x2b (SPI_FAST_FLASH_BOOT)
Saved PC:0x42035cca
mode:DIO, clock div:1
entry 0x403c98d0

assert failed: heap_caps_free heap_caps.c:381 (heap != NULL && "free() target pointer is outside heap areas")

Backtrace: 0x40377122:0x3fceb9c0 0x4037a5bd:0x3fceb9e0 0x4037ff19:0x3fceba00 0x403776d2:0x3fcebb30 0x4037ff49:0x3fcebb50 0x42009d11:0x3fcebb70 0x42009dfa:0x3fcebb90 0x420023c9:0x3fcebbb0 0x4200240e:0x3fcebbd0 0x420029a5:0x3fcebc20 0x4200b58a:0x3fcebc50

I am no expert, but since it says something about heap, I assume it is trying to use the wrong memory or something related with memory.

My board file is:

  "build": {
    "arduino": {
      "ldscript": "esp32s3_out.ld",
      "memory_type": "qio_qspi"
    "core": "esp32",
    "extra_flags": [
    "f_cpu": "240000000L",
    "f_flash": "80000000L",
    "flash_mode": "qio",
    "hwids": [
    "mcu": "esp32s3",
    "variant": "EZY_4MB"
  "connectivity": [
  "debug": {
    "openocd_target": "esp32s3.cfg"
  "frameworks": [
  "name": "EZY_4MB",
  "upload": {
    "flash_size": "4MB",
    "maximum_ram_size": 327680,
    "maximum_size": 4194304,
    "wait_for_upload_port": true,
    "require_upload_port": true,
    "speed": 460800
  "url": "",
  "vendor": "Espressif Systems"

and my platformio.ini:

platform = espressif32
board = EZY_4MB
board_build.mcu = esp32s3
framework = arduino
monitor_speed = 921600
;upload_protocol = jlink
debug_tool = esp-builtin
; esp-builtin or jlink
debug_speed = 40000
upload_port = COM26
build_flags = 
lib_deps = dfrobot/DFRobotDFPlayerMini@^1.0.6

Can you please point me in the right direction or point out any obvious errors?
Thanks in advance

Hi @x04n !

I am trying to reproduce the error.

Your EZY_4MB.json refers to "variant": "EZY_4MB".
Can you please provide these files as well?
Otherwise I get error messages:

* Looking for pins_arduino.h dependency? Check our library registry!
* CLI  > platformio lib search "header:pins_arduino.h"
* Web  >

 #include "pins_arduino.h"
compilation terminated.
1 Like

I was able to reproduce the error message.
You free memory with delete or free which is on the stack instead on the heap.

The following example illustrates the problem where a placement new is used to force the error.

#include "Arduino.h"

String stringOnStack;

void setup() {
  String* fakeHeapString = new (&stringOnStack) String; // placement new -> fakeHeapString points to stack instead to heap memory
  delete fakeHeapString; // kaboom: trying to free memory from stack

void loop() {}
1 Like

Here you can see a simulation: esp32-s3 crash on "target pointer is outside heap areas" - Wokwi ESP32, STM32, Arduino Simulator

1 Like

Thanks for the answer Sivar, I’ll take a look at this as soon as I can and I’ll let you know!

1 Like

Here is the content of pins_arduino.h for the variant EZY_4MB: (it’s a direct copy of the variant lolin_s3_2

#ifndef Pins_Arduino_h
#define Pins_Arduino_h

#include <stdint.h>
#include "soc/soc_caps.h"

#define USB_VID 0x303a
#define USB_PID 0x1001

#define NUM_DIGITAL_PINS        48
#define NUM_ANALOG_INPUTS       18

static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT+38;
#define BUILTIN_LED  LED_BUILTIN // backward compatibility

#define analogInputToDigitalPin(p)  (((p)<18)?(analogChannelToDigitalPin(p)):-1)
#define digitalPinToInterrupt(p)    (((p)<48)?(p):-1)
#define digitalPinHasPWM(p)         (p < 46)

static const uint8_t TX = 43;
static const uint8_t RX = 44;

static const uint8_t SDA = 42;
static const uint8_t SCL = 41;

static const uint8_t SS    = 10;
static const uint8_t MOSI  = 11;
static const uint8_t MISO  = 13;
static const uint8_t SCK   = 12;

static const uint8_t A0 = 1;
static const uint8_t A1 = 2;
static const uint8_t A2 = 3;
static const uint8_t A3 = 4;
static const uint8_t A4 = 5;
static const uint8_t A5 = 6;
static const uint8_t A6 = 7;
static const uint8_t A7 = 8;
static const uint8_t A8 = 9;
static const uint8_t A9 = 10;
static const uint8_t A10 = 11;
static const uint8_t A11 = 12;
static const uint8_t A12 = 13;
static const uint8_t A13 = 14;
static const uint8_t A14 = 15;
static const uint8_t A15 = 16;
static const uint8_t A16 = 17;
static const uint8_t A17 = 18;

static const uint8_t T1 = 1;
static const uint8_t T2 = 2;
static const uint8_t T3 = 3;
static const uint8_t T4 = 4;
static const uint8_t T5 = 5;
static const uint8_t T6 = 6;
static const uint8_t T7 = 7;
static const uint8_t T8 = 8;
static const uint8_t T9 = 9;
static const uint8_t T10 = 10;
static const uint8_t T11 = 11;
static const uint8_t T12 = 12;
static const uint8_t T13 = 13;
static const uint8_t T14 = 14;

#endif /* Pins_Arduino_h */

I am not using any of those functions (delete, free or new), I never have, honestly it’s the first time I hear about them.
The same code uploads and runs well with Arduino IDE, so I assumed it was a problem with my board definition.
Do I have to manually manage memory with PlatformIO?

This was just an example to show what happens when you try to free dynamic memory from the stack instead from the heap. It is exactly the same as the error message.

This does not have to be done by your code. It can also be triggered by a function of a library you are using. For example, if you pass a wrong parameter.

If the same code is running in the ArduinoIDE then the settings are certainly different.

There are no differences between the ArduinoIDE and PlatformIO.

1 Like

Then my assumption must be right, something about my board configuration Json must be wrong in some way.

I don’t think so .
Do you use the same Arduino-Core on ArduinoIDE and PlatformIO?

Maybe you are using Arduino 3.x alpha which is not yet available on PlatformIO?

I am using Arduino IDE 2.3.2

That wasn’t the question, what ESP32 core you are using with Arduino IDE?

1 Like


How to compare the ArduinoCore-Version


Click on Tools / Board / Boards Manager...

  1. Enter “Espressif
  2. Note the version



  1. Click on the PlatformIO Icon
  2. Click “Platforms”
  3. Enter “Espressif32
  4. Note the version
    4a. If multiple versions installed, please note them too.

The ArduinoCore Version for Espressf32 Platform can be obtained by checking the Release Notes here Releases · platformio/platform-espressif32 · GitHub

Espressif32 @ 6.5.0 = Arduino v2.0.14
Espressif32 @ 6.4.0 = Arduino v2.0.11
Espressif32 @ 6.3.0 = Arduino v2.0.9
Espressif32 @ 6.2.0 = Arduino v2.0.8
Espressif32 @ 6.1.0 = Arduino v2.0.7

1 Like

Thank you, in Arduino IDE I am using 2.0.14 and in PlatformIO 6.5 which according to your post is the same as 2.0.14.

Ok that rules out version differences :slight_smile:

Please post a screenshot of your board settings from the ArduinoIDE.

1 Like


I’m not sure about "memory_type": "qio_qspi".
The “qspi” part is used for PSRAM, which your board doesn’t have.

Remove this line from your boards.json and try again.

One thing you can do to help debug is decode the crash. There’s a nice website you can use where you input your elf file (located in your .pio folder) and then you paste in your backtrace addresses:

0x40377122:0x3fceb9c0 0x4037a5bd:0x3fceb9e0 0x4037ff19:0x3fceba00 0x403776d2:0x3fcebb30 0x4037ff49:0x3fcebb50 0x42009d11:0x3fcebb70 0x42009dfa:0x3fcebb90 0x420023c9:0x3fcebbb0 0x4200240e:0x3fcebbd0 0x420029a5:0x3fcebc20 0x4200b58a:0x3fcebc50

It will then provide a backtrace of where in your code that the crash happened. It’s not always crystal clear but many times it points you close enough to give you clues as to what is wrong.

There are other board definitions available for the ESP32-S3 that don’t have PSRAM, adafruit_feather_esp32s3_nopsram is one example and then you can use build_flags to override the pin definitions. I did this for one of my recent board designs:

build_flags = 
	-D ILI9488_DRIVER=1
	-D TFT_CS=10
	-D TFT_DC=18
	-D TFT_RST=39
	-D TFT_BL=38
	-D SPI_FREQUENCY=27000000