Heap and interrupt handlers

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
User avatar
tuupola
Posts: 54
Joined: Sun Sep 17, 2017 12:10 am
Contact:

Heap and interrupt handlers

Post by tuupola » Sat Feb 17, 2018 1:53 pm

I am bit confused about heap and interrupt handlers. Documentation says in several places that ISR cannot allocate memory from heap. For example:
ISR’s cannot create instances of Python objects. This is because MicroPython needs to allocate memory for the object from a store of free memory block called the heap. This is not permitted in an interrupt handler because heap allocation is not re-entrant. In other words the interrupt might occur when the main program is part way through performing an allocation - to maintain the integrity of the heap the interpreter disallows memory allocations in ISR code.
I am however able to run the following code. Am I missing something obvious?

Code: Select all

from machine import Timer

class Hello:
    def __init__(self, name):
        self._name = name

    def greet(self):
        print("Hello " + self._name)

def timer_greet(timer):
    hello = Hello(name="world!")
    hello.greet()

timer_0 = Timer(0)
timer_0.init(period=2000, mode=Timer.PERIODIC, callback=timer_greet)

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Heap and interrupt handlers

Post by pythoncoder » Sun Feb 18, 2018 9:01 am

I adapted this to run on the Pyboard, where interrupts are true hardware interrupts:

Code: Select all

from pyb import Timer
import micropython
micropython.alloc_emergency_exception_buf(100)

class Hello:
    def __init__(self, name):
        self._name = name

    def greet(self):
        print("Hello " + self._name)

def timer_greet(timer):
    hello = Hello(name="world!")
    hello.greet()

timer_0 = Timer(1)
timer_0.init(freq=1, callback=timer_greet)
with the following outcome

Code: Select all

>>> uncaught exception in Timer(1) interrupt handler
Traceback (most recent call last):
  File "<stdin>", line 12, in timer_greet
MemoryError: memory allocation failed, heap is locked

>>> 
The general statement in the docs is correct. However on ESP* platforms interrupts aren't necessarily true hardware interrupts. My understanding is that, even though no error is thrown, it's still inadvisable to allocate memory in ISR's because garbage collection is not re-entrant. If an ISR interrupts GC, attempts to allocate RAM and that attempt fails due to heap fragmentation, a re-entrant GC will be triggered. The outcome of this is likely to be some later crash which will be hard to diagnose.
Peter Hinch
Index to my micropython libraries.

User avatar
tuupola
Posts: 54
Joined: Sun Sep 17, 2017 12:10 am
Contact:

Re: Heap and interrupt handlers

Post by tuupola » Sun Feb 18, 2018 5:41 pm

Makes sense, thanks. Guess I need to purchase some other boards than ESP32 for development to make sure code is portable.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Heap and interrupt handlers

Post by pythoncoder » Mon Feb 19, 2018 7:20 am

I thoroughly recommend getting a Pyboard as reference hardware.
Peter Hinch
Index to my micropython libraries.

Post Reply