ESP32 Guru Meditation Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled?
Hallo,
ich habe ein Problem mit meinem Code auf einem ESP32.
ich habe einen array von struct, welchen ich beschreiben möchte:
file_1.c
typedef struct{
uint8_t green;
uint8_t red;
uint8_t blue;
}ledStrip_ts;
... ... ...
static ledStrip_ts lightbar_as[100];
... ... ...
if (true == getPixelData_b(&graphicData_s.numOfCols_u32, &graphicData_s.numOfRows_u32, (uint8_t*)&lightbar_as[0]))... ... ...
file_2.c:
bool getPixelData_b(uint32_t* numOfCols_pu32, uint32_t* numOfRows_pu32, uint8_t* pixelData_pu8)
{
.... .... ....
bmpColorData_ps = bmpGetGraphicData_v(numOfCols_pu32, numOfRows_pu32);
ESP_LOGI(TAG, "%p numOfCols_pu32: %lu numOfRows_pu32: %lu", bmpColorData_ps, *numOfCols_pu32, *numOfRows_pu32);
... ... ...
uint32_t counter1 = 0;
uint32_t counter2 = 0;
uint32_t counter3 = 0;
uint32_t y = 0;
for(uint32_t x=0; x<(*numOfRows_pu32); x++)
{
for(y=0; y<(*numOfCols_pu32); y++)
{
pixelData_pu8[counter1++] = bmpColorData_ps[counter2].green;
pixelData_pu8[counter1++] = bmpColorData_ps[counter2].red;
pixelData_pu8[counter1++] = bmpColorData_ps[counter2].blue;
ESP_LOGI(TAG, "r: 0x%02X g: 0x%02X b: 0x%02X", pixelData_pu8[counter3+1], pixelData_pu8[counter3], pixelData_pu8[counter3+2]);
counter2++;
counter3+=3;
}
counter2 += (4 - (y%4)); // Compression = 0 (BI_RGB): Bilddaten sind unkomprimiert, bedeutet
// "Jede Bildzeile ist durch rechtsseitiges Auffüllen mit Nullen auf ein
// ganzzahliges Vielfaches von 4 Bytes ausgerichtet." (Wikipedia)
}
... ... ...
Laut Ausgabe (und das ist richtig, sind es 14x14 pixel.
105 Elemente werden geschrieben, dann bekomme ich den Error.
Doch eigentlich ist mein Buffer doch 100 Elemente * 3 Byte (uint8_t red, green, blue). Also 300 Byte.
Als Ausgabe bekomme ich dann:
I (1414) GRAPHIC: r: 0xFF g: 0xFF b: 0xFF
I (1414) GRAPHIC: r: 0xFF g: 0xFF b: 0xED
Guru Meditation Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled.
Core 0 register dump:
PC : 0x400d836e PS : 0x00060730 A0 : 0x800d7e4e A1 : 0x3ffbcf70
A2 : 0x3ffb2e38 A3 : 0x0000013b A4 : 0x3ffb2e3c A5 : 0x00000007
A6 : 0x00000077 A7 : 0x0000013b A8 : 0x0000013d A9 : 0x3ffb2f74
A10 : 0x00000165 A11 : 0x3ffb2f78 A12 : 0xc0ee0164 A13 : 0x00000586
A14 : 0x3f403a78 A15 : 0x000000ff SAR : 0x00000004 EXCCAUSE: 0x0000001c
EXCVADDR: 0xc0ee0164 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xfffffffd
Backtrace: 0x400d836b:0x3ffbcf70 0x400d7e4b:0x3ffbcfc0 0x400d7f3c:0x3ffbcff0 0x40088075:0x3ffbd020
--- 0x400d836e: getPixelData_b at C:/Projekte/ESP32/leuchtstab/main/graphic.c:101
--- 0x400014fd: strlen in ROM
--- 0x4000150d: strlen in ROM
--- 0x400d836b: getPixelData_b at C:/Projekte/ESP32/leuchtstab/main/graphic.c:101
--- 0x400d7e4b: lightbarExec_v at C:/Projekte/ESP32/leuchtstab/main/lightbar.c:116
--- 0x400d7f3c: lightbarTask_v at C:/Projekte/ESP32/leuchtstab/main/lightbar.c:184 (discriminator 1)
--- 0x40088075: vPortTaskWrapper at C:/Espressif/frameworks/esp-idf-v5.4/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:139
Wenn ich nur ein 3x2 pixel bild nehme, funktioniert es ohne probleme.
1 Antwort
Das casten von einen struct pointer auf uint8* ist undefined behaviour keine Ahnung was da der Compiler genau macht, vielleicht kommt da noch ein Padding in die Struct dazu usw. Das ist schlechter Code.
Aber prüf doch mal ob sizeof(lightbar_as) wirklich 300 ist.
Weiters prüfe mal ob counter1 nicht doch irgendwie über 300 geht. Der Fehler kann natürlich auch in den Teilen stecken die nicht gezeigt wurden.
Das macht dann Sinn dennoch solltest du so etwas wie den uint8_t* cast vermeiden.
Der Grund ist dass C und C++ keine Angabe darüber machen wie eine Struct genau im Speicher liegt.
So kann der C Kompiler die struct auch als rgbp in den Speicher legen wobei p ein als Padding bezeichnetes Byte ist. Das hat den Hintergrund dass die nächste Strukt im Array auf 32Bit Alligned ist was den Zugriff auf mancher Hardware schneller macht.
Wenn du den Pointer auf die Struct nun im Typ änderst hat der Compiler danach keine Information mehr darüber ob ein Padding vorliegt oder nicht.
Der Cast auf einen anderen Pointer Typ ist nur dann definiert wenn die Daten an irgendeinem Punkt wieder in die Struct geschrieben werden.
Also Byteweises kopieren der Daten zwischen structs des selben Typs ist erlaubt Interpretation oder Manipulation der Daten ist es nicht.
Genau aus diesem Grund ist auch Typepunning oft undefiniert.
Habe den "Denk"-Fehler gefunden.
Der Buffer war für eine komplette spalte des Bildes. Übergeben habe ich aber alle Pixel des Bildes (14x14 pixel)
14 x 14 x 3 farben/prixel = 588 > 300