I've been at this the whole day, and aware of the problem since yesterday.
I have an SVG parser and renderer that's very lightweight. The XML parser uses 2KB window to peephole parse the whole document. I don't even keep it on the stack. I've pruned the stack on the codepath that my troubleshooting/test SVG content is invoking to with in an inch of its life. I did so by hoisting local variables onto the heap and combining multiple parameters in function calls into single references to a struct containing many of the parameters.
It still crashes when I invoke parser. I've narrowed it down to a particular codepath that it gets to, I think.
The thing should be stack shallow, but I don't know how to measure the stack, at least on an ESP32, and the stack corruption clobbers any chance of a meaningful trace.
The thing is, it works fine on a PC.
And I can get it to limp on an ESP32 by moving the initialization to run at static initialization time. It reboots but then works. Go figure. That's not really acceptable for production, but I'm just putting it out there.
Attempts to call the parsing code from within any routine, even one I create on a thread with a ton of stack space cause the crash.
See "what have you tried."
Note the 32768 . That is the number of 32-bit machine *words* to allocate to the stack for that thread. That's 128KB. That's enough effing stack, so I'm thinking maybe that's not my problem.
But I can't really know, can I because I can't get MSVC++ on the PC (which is my alternate) to measure how much stack that codepath is using. And I certainly can't on the ESP32.
Does anyone have any ideas for next moves, or things I can investigate? It's not exactly a hard and fast programming question, and yet it is.
What I have tried:
TaskHandle_t handle;
xTaskCreatePinnedToCore(loop_task,"loop_task",32768,nullptr,24,&handle,1-xTaskGetAffinity(xTaskGetCurrentTaskHandle()));
Here's the loop task.
svg_image img2(doc,150,{128,128});
volatile int draw_state = 0;
#ifdef ARDUINO
static void loop_task(void* arg) {
img2.initialize(); gfx_result r=img2.draw(((srect16)img2.bounds()).center((srect16)panel_fb.bounds()).crop((srect16)panel_fb.bounds()),
[](const image_data& data, void* state){
if(data.is_fill) {
return draw::filled_rectangle(panel_fb,*data.fill.bounds,data.fill.color);
}
return draw::bitmap(panel_fb,data.bitmap.region->bounds().offset(data.bitmap.location),*data.bitmap.region,data.bitmap.region->bounds());
});
if(r!=gfx_result::success) {
printf("draw error: %d\n",(int)r);
}
draw_state = 1;
uint32_t time_ts = millis();
while(1) {
if(millis()>time_ts+150) {
time_ts = millis();
vTaskDelay(1);
}
}
}