Page 1 of 1

ESP32-C3: Executing code from RTC_FAST_MEM causes “Illegal Instruction” (works fine under GDB)

Posted: Tue Oct 14, 2025 11:39 am
by bssmr32
Hello everyone,

I'm experimenting with the idea of having self-modifying or dynamically loaded code in my ESP-IDF project and have encountered some behavior I can’t explain.

I have a regular ESP-IDF project compiled and running on an ESP32-C3.
After flashing the normal firmware, I modify the firmware image in flash by adding an additional code segment that should be loaded at 0x50001000.

After a reboot, the bootloader indeed detects and loads my new segment:

Code: Select all

I (222) esp_image: segment 6: paddr=002d89a0 vaddr=50001000 size=001e4h (   484) load
When I read memory at address 0x50001000 via the D-Bus, my code appears correctly in RAM as expected.
However, when I try to execute it by jumping to 0x50001000, I get an Illegal Instruction exception:

Code: Select all

Guru Meditation Error: Core  0 panic'ed (Illegal instruction). Exception was unhandled.

Core  0 register dump:
MEPC    : 0x50001000  RA      : 0x42088722  SP      : 0x3fca2d40  GP      : 0x3fc8ca00
TP      : 0x3fca3360  T0      : 0x42085e36  T1      : 0x40387f60  T2      : 0xffffffff
S0/FP   : 0x00000004  S1      : 0x50001000  A0      : 0x3fca5274  A1      : 0x3fca52b0
A2      : 0x00000000  A3      : 0x00000000  A4      : 0x00000002  A5      : 0x3fcb6b5c
A6      : 0x3fcc5574  A7      : 0x3fca2c24  S2      : 0x3fcabeec  S3      : 0x00000000
S4      : 0x00000001  S5      : 0x00000016  S6      : 0x00000d79  S7      : 0x00000001
S8      : 0x00000001  S9      : 0x00000d79  S10     : 0x00000d79  S11     : 0x3c1df000
T3      : 0xffffffff  T4      : 0x00000000  T5      : 0x0ccccccc  T6      : 0x00000019
MSTATUS : 0x00001881  MTVEC   : 0x40380001  MCAUSE  : 0x00000002  MTVAL   : 0x00000000
MHARTID : 0x00000000
Here’s the strange part:
If I connect GDB via OpenOCD (USB/JTAG) and then perform the exact same jump to 0x50001000, the code executes perfectly—no exception, no issue. This happens without any breakpoints or stepping; just having GDB attached makes it work.

This behavior is fully reproducible:

Without GDB → Illegal Instruction

With GDB attached → works flawlessly

Does anyone have an idea why executing from 0x50001000 only works when GDB is connected?

Any insights or pointers would be greatly appreciated.