Exceptions in interrupt handlers

The official pyboard running MicroPython.
This is the reference design and main target board for MicroPython.
You can buy one at the store.
Target audience: Users with a pyboard.
Post Reply
Jim.S
Posts: 84
Joined: Fri Dec 18, 2015 7:36 pm

Exceptions in interrupt handlers

Post by Jim.S » Sat Jul 30, 2016 4:47 pm

I am experimenting with exceptions, and trying to handle exceptions in interrupt service routines (ISR). It is my impression (based on the wiki) that the try except block has to be in the ISR. (.."If an ISR raises an exception it will not propagate to the main loop. The interrupt will be disabled unless the exception is handled by the ISR code.")

If I test the code shown below I don't get the exception I am expecting, I get a MemoryError instead of MyException.

Is it possible to use exceptions in ISRs? if so is there some trick way of handling them.

(the additional lines in the code are to allow me to (A) test it on a PC and also (B) demonstrate on the pyboard that it is the exception in the callback causing the problem and not the print statement)
>>> Uncaught exception in ExtInt interrupt handler line 3
Traceback (most recent call last):
File "main.py", line 10, in f
File "main.py", line 8, in f
MemoryError: memory allocation failed, heap is locked

Code: Select all

class MyException(Exception):
    def __init__(self):
        pass

def f():
    try:
        raise MyException()
    except MyException as e:
        print('my exception function f')

def g():
    print('function g')

try:
    import pyb
    import micropython
    micropython.alloc_emergency_exception_buf(100)
    sw=pyb.Switch()
    sw.callback(f)
except ImportError:
    print('pyb not available simlate instead')
    f()
    g()

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Exceptions in interrupt handlers

Post by dhylands » Sat Jul 30, 2016 6:14 pm

The issue that you're running into is that you're not allowed to allocate memory during an ISR. This code:

Code: Select all

raise MyException()
tries to allocate a new exception object, which will fail during an ISR.

You'd need to allocate the exception object outside the ISR, and then you'd be able to raise it from inside the ISR.

The C code which throws the MemoryError has to preallocate the MemoryError exception for exactly that reason.

Jim.S
Posts: 84
Joined: Fri Dec 18, 2015 7:36 pm

Re: Exceptions in interrupt handlers

Post by Jim.S » Sat Jul 30, 2016 8:10 pm

Thanks, I understand now.. If I declare an instance of MyException outside the ISR it works as intended

Code: Select all

class MyException(Exception):
    def __init__(self):
        pass

MyE=MyException()

    
def f():
    try:
        #raise MyException()
        raise MyE
    except MyException as e:
        print('my exception function f')

try:
    import pyb
    import micropython
    micropython.alloc_emergency_exception_buf(100)
    sw=pyb.Switch()
    sw.callback(f)
except ImportError:
    print('pyb not available simlate instead')
    f()

Post Reply