InstrFetchProhibited Error using DFRobot_DF2301Q library
Opened this issue · 6 comments
I am new to the DFRobot SEN0539 module and I am 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 and try to execute its e-ink-display driver code with it.
See minimum code-example at the very bottom of this entry...
#include <GxEPD2_BW.h> // https://github.com/ZinggJM/GxEPD2/tree/master
As soon as I add the above include-statement, together with the most simple e-ink-driving code, then I get a memory crash errror InstrFetchProhibited
.
Important: As I said, the DFRobot code alone works. And also, the GxEPD2 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. DFRobot_DF2301Q and GxEPD2) 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:
- Is this a RAM or FLASH issue ?
- 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 ?
- 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 GxEPD2 forum - since it is unclear where the error really originates... So I did : https://forum.arduino.cc/t/instrfetchprohibited-error-using-gxepd2-in-combination-with-another-library/1279812
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);
}
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 :) )
Can somebody please explain why this #pragma pack(1)
line of code is there ? And what does it exactly do ?
And why did it cause a crash on the ESP32 S3 board ?
Hello,
#progma pack() is a function for structure alignment, because the alignment of structures may be different in different compilers, and space may be wasted if alignment rules are not specified.
For example, in this sUartMst_t structure under the #progma pack(1) , if you don't do structure alignment, all the variables in the structure will occupy the variable with the largest number of bytes in the structure.
That is, if you remove #pragma pack(1), the structure will occupy 16 * 6=96 bytes.
If #pragma pack(1) is used, the current compiler will force the structure to be aligned to 1 byte. That means sUartMst_t will occupy 16 * 2+8 * 4=64 bytes.
But the problem with the current version of the code is that it doesn't end the byte alignment process. #progma pack() should be used in pairs. One #pragma pack() must be added at the end of the structure for the command to cancel the custom structure alignment, if not, it may lead to problems in the whole program, because it will affect the way other structures are aligned.
It should be used like this:
#pragma pack(1)
struct example
{
char a;
double b;
};
#pragma pack()
I fixed this bug in my branch, but unfortunately I don't have your e-ink-display to test it with.
You can use my branch to test it and I will raise a PR if the problem is fixed.
@YeezB, thank you very much for the detailed explanation. I only have time to test your branch by the end of the upcoming week. I'll let you know....
Many thanks, so far for your support.
Hello,
can I ask if my code work?
It did for me. thanks man