Wenn das Programm irgendwo landet, wo es nicht hingehört, dann überschreibst du dir mit irgendwas deine Stack-Inhalte. Der Stack wächst zu weit nach unten und liegt im normalen Datenbereich. Wenn du dann Variablen schreibst, überschreibst du die Rücksprungadresse.
Ausserdem werden beim Sprung in eine Unterroutine/ISR Daten überbügelt. Auch möglich, daß eine rekursiver IRQ das Problem auslöst, zB wenn in einer Timer-ISR wieder dieser Timer-IRQ ausgelöst wird und man in der ISR ein cli stehen hat.
Weitere Fehlerquelle kann ein falsch initialisierter/übergelaufener Pointer sein, über den du auf den Stackbereich geschrieben hast.
Unkontrollierte Sprünge können auch auftreten, wenn die Versorgungsspannung zu niedrig ist.