InstrFetchProhibited Error using GxEPD2 in combination with another library

I am using the E-ink display GxEPD2_420_GDEY042T81 and driving it by an ESP32S3-WROOM-1U-8N8R.

Therefore I have 8MB of RAM and 8MB of Flash available.

Everything works as expected - until the moment where I include another library into my code.

See minimum code-example at the very bottom of this entry...

#include "DFRobot_DF2301Q.h"  // https://github.com/DFRobot/DFRobot_DF2301Q

As soon as I add the above include-statement, then I get a memory crash errror InstrFetchProhibited.

Important: As I said, the GxEPD2 code alone works. And also, the DFRobot_DF2301Q example as a standalone-code works fine. ONLY in combination, these two libraries do crash.

Here the error message (i.e. the processor keeps crashing again and again no longer being capable of booting the code properly).

The error log sais:

ELF file SHA256: ed7694204b47b38f

Rebooting...
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0xc (RTC_SW_CPU_RST),boot:0x9 (SPI_FAST_FLASH_BOOT)
Saved PC:0x42051082
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce3808,len:0x44c
load:0x403c9700,len:0xbe4
load:0x403cc700,len:0x2a68
entry 0x403c98d4

Guru Meditation Error: Core  1 panic'ed (InstrFetchProhibited). Exception was unhandled.

Core  1 register dump:
PC      : 0xffffff00  PS      : 0x00060230  A0      : 0x82005792  A1      : 0x3fcebb10  
A2      : 0x3fc96dd2  A3      : 0x3c0603fc  A4      : 0x00233bc6  A5      : 0x00000001  
A6      : 0x0000012c  A7      : 0x00000000  A8      : 0x82005502  A9      : 0x3fcebaf0  
A10     : 0xffffffff  A11     : 0x00000001  A12     : 0xffffffff  A13     : 0x3fcf5520  
A14     : 0x00000001  A15     : 0x3fce9dc0  SAR     : 0x00000006  EXCCAUSE: 0x00000014  
EXCVADDR: 0xffffff00  LBEG    : 0x42007a70  LEND    : 0x42007ad3  LCOUNT  : 0x00000002  

Backtrace: 0x7ffffefd:0x3fcebb10 0x4200578f:0x3fcebb30 0x4200588c:0x3fcebb50 0x420059c5:0x3fcebb70 0x42005aea:0x3fcebbc0 0x42002f61:0x3fcebc00 0x4200360d:0x3fcebc30 0x4200877a:0x3fcebc50

Now it is pretty clear that the two libraries (i.e. GxEPD2 and DFRobot_DF2301Q) are spilling memory of the ESP32S3 type at choice.

When I investigate more closely, I get the above crash inside the while loop of my GxEPD2 code:

    display.setRotation(0);
    display.setFullWindow();
    display.firstPage();
    do {
        display.fillScreen(GxEPD_WHITE);
    } while (display.nextPage());

Now my questions:

  1. Is this a RAM or FLASH issue ?
  2. could I prevent the error when using the ESP32S3-WROOM-1U N16R8 that has 16MB of Flash and 8MB of PSRAM ? Unfortunately, there are no models having more RAM. Could the double Flash work ?
  3. What else could I do to prevent the InstrFetchProhibited error from happening ?

Thank you for any support on this. I am aware that I could ask this same question also in the DFRobot forum - since it is unclear where the error really originates... So I did: InstrFetchProhibited Error using DFRobot_DF2301Q library · Issue #12 · DFRobot/DFRobot_DF2301Q · GitHub

Here the minimum code-example that reproduces the memory issue nicely:

Pleae note: As soon as I uncomment the do-while loop, then I get the error! The question is WHY ?

#include "DFRobot_DF2301Q.h"
#include <GxEPD2_BW.h>

#define EPD_WIDTH     400
#define EPD_HEIGHT    300
#define EPD_ARRAY     EPD_WIDTH*EPD_HEIGHT/8

#define CS_SS_PIN     SS    // 10 (CS SS)
#define HSPI_COPI     MOSI  // 11 (MOSI)
#define HSPI_SCLK     SCK   // 12 (SCK)

#define BUSY_PIN      A5       // 6   (BUSY)
#define RST_PIN       A6       // 7   (RST RES)
#define DC_PIN        A14      // 15  (DC)

#define SDA_PIN       GPIO_NUM_14
#define SCL_PIN       GPIO_NUM_21

GxEPD2_BW<GxEPD2_420_GDEY042T81, GxEPD2_420_GDEY042T81::HEIGHT> display(GxEPD2_420_GDEY042T81(CS_SS_PIN, DC_PIN, RST_PIN, BUSY_PIN)); // GDEY042T81, 400x300, SSD1683 (no inking)

DFRobot_DF2301Q_I2C asr;

void setup() {
    
  Serial.begin(115200);
  delay(2000);

  Wire.begin(SDA_PIN, SCL_PIN);

  // Init the sensor
  while (!(asr.begin())) {
    Serial.println("Communication with device failed, please check connection");
    delay(3000);
  }
  asr.setMuteMode(0);
  asr.setWakeTime(20);

  display.init(115200, false, 10, false);
  display.setTextColor(GxEPD_BLACK);
  display.setRotation(0);
  display.setFullWindow();
  display.firstPage();

  // ***********************************************************
  // UNCOMMENTING THIS DO-WHILE LOOP MAKES THE MEMORY-CRASH !
  // 
  //  do {
  //    display.fillScreen(GxEPD_WHITE);
  //  } while (display.nextPage());
  // 
  // ***********************************************************
  
}

void loop() {
  uint8_t CMDID = asr.getCMDID();
  switch (CMDID) {
    default:
      if (CMDID != 0) {
        Serial.print("CMDID = ");  //Printing command ID
        Serial.println(CMDID);
      }
  }
  delay(300);
}

Run the ESP32 Exception Decoder to get a better idea of where the exception is happening. Post the results.

Does it crash if you only make a single call to display.fillScreen() rather than multiple calls in a loop?

Also, which ESP32 Arduino Core are you using?

I am using ESP32S3 Dev Module and there I am using Core 1.

If I run the ESP32 Exception Decoder, I do not get much at all.
(i.e. since now used for the first time, I am not sure what I have to paste exactly. I did paste everything that was in the Serial-Monitor. But there was no stack results on this for some reason...)

Screenshot 2024-07-09 at 14.44.05

And yes, if I only make a single call to display.fillScreen() then I do not get the exception. However this is not what I am supposed to do with the GxEPD2 module. In fact, I reduced to the max the example. Normally, I have much more code inside the do...while loop.

The problem is created by the do...while loop. As soon as I introduce this loop (even an empty one), I get the crash.

What could be wrong with this do...while ??

Ah, doing the same on Adruino Core 0, I do get stack results:

I am going to investigate the suggested lines now....
...

There seems to be a problem with the display.nextPage() - but I don't see what could be wrong

What does that mean? The code you posted doesn't select the running core.

Don't post screenshots!!!!
Post the decoder results using Code Tags, just like posting source code.

Post a GitHub link to the GxEPD2_BW library.

How do I select the running Core inside code ?

I am selecting the Core 0 inside the Arduino IDE 1.8.19 (under Tools-->Arduino Runs on: Core0).

The Github Link to the GxEPD2 library is this one. I am using the GDEY042T81 display. But most examples for any kind of display are very similar for this library.

A clear example for the GDEY042T81 display can be found here

(of course by uncommenting the display-type needed in the corresponding .h file accordingly)

As you asked, here the decoder result with pure text using code-tags:

PC: 0x4037784c
EXCVADDR: 0xffffff00

Decoding stack results
0x42002b8f: GxEPD2_420_GDEY042T81::_PowerOn() at /Users/myfolder/Arduino/libraries/GxEPD2/src/gdey/GxEPD2_420_GDEY042T81.cpp line 323
0x42002c8c: GxEPD2_420_GDEY042T81::_Init_Part() at /Users/myfolder/Arduino/libraries/GxEPD2/src/gdey/GxEPD2_420_GDEY042T81.cpp line 368
0x42002dc5: GxEPD2_420_GDEY042T81::_writeImage(unsigned char, unsigned char const*, short, short, short, short, bool, bool, bool) at /Users/myfolder/Arduino/libraries/GxEPD2/src/gdey/GxEPD2_420_GDEY042T81.cpp line 87
0x42002eea: GxEPD2_420_GDEY042T81::writeImageForFullRefresh(unsigned char const*, short, short, short, short, bool, bool, bool) at /Users/myfolder/Arduino/libraries/GxEPD2/src/gdey/GxEPD2_420_GDEY042T81.cpp line 60
0x42001bed: GxEPD2_BW ::nextPage() at /Users/myfolder/Arduino/libraries/GxEPD2/src/GxEPD2_BW.h line 412
0x42002239: setup() at /Users/myfolder/Arduino/iKK/teddy_arduino/General_Arduino_Trials/DFRobot_SEN0539_Example_I2C_not_working/DFRobot_SEN0539_Example_I2C_not_working.ino line 64
0x4200591e: loopTask(void*) at /Users/myname/Library/Arduino15/packages/esp32/hardware/esp32/2.0.11/cores/esp32/main.cpp line 42

I realized that the DFRobot_DF2301Q library is compatible with ESP32 and ESP8266.

I am using ESP32 S3 - could that be the problem ? (i.e. that the DFRobot library is not yet 100% ready for the ESP32 S3, especially in combination this GxEPD library ??).

But the simple DFRobot example (without the GxEPD2 library-code) works perfectly well on the ESP32 S3 (UART and I2C examples, both work very well on the ESP32 S3). So I assume this is not the problem. Or could it be once I add the GxEPD library ?

Anyway, I am pretty clueless about this issue. Any help highly appreciated. Thank you.

The main question: why is the display.nextPage() crashing ?

You'll have even more problems with Core 0 as it's much more sensitive to user code screwing around if you're not careful. BTW, that's not what I mean by "Core". I meant:

The last function shown in the trace is GxEPD2_420_GDEY042T81::_PowerOn(). That code:

void GxEPD2_420_GDEY042T81::_PowerOn()
{
  if (!_power_is_on)
  {
    _writeCommand(0x22);
    _writeData(0xe0);
    _writeCommand(0x20);
    _waitWhileBusy("_PowerOn", power_on_time);
  }
  _power_is_on = true;
}

The trace doesn't show any of the subsequent function calls. The corruption may be happening on one of them.

Don't know.

Try it on an ESP32.

No - I can't try it on an ESP32 (since I don't have one here and moreover since my project is entirely based on an ESP32 S3). The ESP32 is out of question for this project (for other reasons).

Therefore I did not even install the ESP32 board as you asked.

But rather, I am working with this board. And I need a solution for this board:

The _PowerOn() function - hmm what could be wrong with it ?

Will try one more time. All ESP32-type boards (including ESP32 S3) are supported by the same ESP32 Arduino Board package. I was asking which version of that package you have installed. It's important because the most recent 3.x family of packages includes significant changes that can cause problems for existing code based on the 2.x packages.

If it were me, I'd buy an ESP32 and test it. That way you could say for sure (or not) that the problem is related to using ESP32 S3.

Start digging into the library source code to find out. Instrument it with print statements to see how far it gets and exactly which call is corrupted.

Ah I understand.

I indeed had the ESP32 v 2.11 installed. But now updated to be ESP32 v 3.02

But same thing. I don't think the two versions (v2.11 and v3.02) show a big difference concerning my issue. They both don't work for now....

I finally found a "solution" (...well not yet quite sure what I've found).

It turns out that the DFRobot's DFRobot_DF2301Q-library contains a line of code that was the root-cause of my code-crash:

Inside the file DFRobot_DF2301Q.h, on line 217, there is the faulty instruction:

#pragma pack(1)

If I put a comment on this line, then my code compiles without crash !

(I am using the I2C example right now - and I guess therefore none of the UART-code is used and most likely the comment-out of this #pragma pack(1) has no effect (other than making my code run super smooth :slight_smile: )

Screenshot 2024-07-09 at 17.37.39

I will ask in the DFRobot-Forum about this line of code and whether it is really necessary.
(see here)...

Obscure. I could see that causing unnecessary code expansion for the 32-bit processor because of non-aligned data fields, but not a crash. Makes me think there's still a problem with pointer mismanagement that changing the alignment ends up hiding. If that's the case, it may just continue to work for you. Or, it may start crashing again once you make another (seemingly unrelated) change. Only time will tell ....