The quick read : use only simple globals in ESP32 Interrupts do not use objects!
The longer read below…
As part of my sound module (to be used first in the Frogger build) I have to use interrupts as a necessity. In addition I like to work in OOP when I can, I enjoy the style of that type of coding (although for quick small stuff it’s always usually procedural – horses for courses). So having wrote my first part of the module – a WAV player (see here) and all went well with nothing unusual happening beyond the annoying way you can’t use floats inside the interrupt without adding some code to handle swapping in and out the Floating Point Unit (see this thread) I proceeded to expand the code for more functionality.
After expanding the code with the first bit of extra functionality I then started to get core panic warnings and register dumps, unknown exceptions as the code ran. And they were a bit weird. I could add a debugging “Serial.println()” statement in other parts of the code, not even in the interrupt routine and it would change behaviour, crashing differently or just not working in a different way.
One thing I was getting sometimes was a “Load Prohibited” error in the dump from the ESP32. This seemed to suggest accessing an invalid memory location (one that has been de-refrenced or something similar). But as I was using the “volatile” keyword how could this be? Although as mentioned core panic reasons sometimes changed as I added bits of what looked like harmless debug code. My original code was something like this.
volatile MyClass MyObject();
and the compiler is happy until I started using this object or passing it as part of my normal none interrupt code, then the compiler wasn’t happy, can’t remember the message but basically was forbidding me using this object in what I considered a normal way unless I removed the “volatile” keyword. Which I did and then I added it to all the variables within this object. The problem was it would sometimes fail differently as I added in really simple debug code, it would not always give a memory violation and this is why I ended up going round in circles.
The Solution
I had to remove using a global object within the interrupt routine replacing the object within the routine with normal basic global variable types marked with the volatile keyword. Instantly the module came to life with just a minor issue of normal incorrect code.
The lesson
Do not use objects within the interrupt routine for an ESP32! This may change in the future if I can successfully mark an object with the volatile keyword but at time of writing the compiler seems to baulk at this in places where the object is used or passed so you cannot use this. Annoyingly it will sometimes work with objects but it is touch and go, so use only simple globals in ESP32 Interrupts.