Keep getting MemoryError on ISR callback (asyncio)

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
mark_melvin
Posts: 10
Joined: Sat Dec 28, 2019 11:35 pm

Keep getting MemoryError on ISR callback (asyncio)

Post by mark_melvin » Wed Jan 27, 2021 1:23 am

Hi There,

I am trying to convert an app to asyncio and I am using this as a reference:

https://github.com/peterhinch/micropyth ... -irq_event

However, no matter what I do I am getting the following error:

Code: Select all

Uncaught exception in IRQ callback handler
MemoryError:
I'm hooking up an ISR to a UART and literally all I am doing is setting an asyncio IRQ_EVENT(). Is there anything I can do to help narrow down this error? I'm not allocating anything as you can see in my code below:

Code: Select all

class MyDevice:
    def __init__(self, uart ...):
        self.uart = uart

        # asyncio event set by the hard UART interrupt handler
        self.rx_event = IRQ_EVENT()
        self.uart.irq(self.on_serial_rx_data, machine.UART.IRQ_RXIDLE, True)

        asyncio.create_task(self.handle_serial_rx())

    def on_serial_rx_data(self, *args, **kwargs):
        '''
        Callback called as an ISR whenever there are characters waiting in the RX buffer.
        '''
        # Set the asyncio event and return ASAP
        self.rx_event.set()

    async def handle_serial_rx(self,):
        while True:
            await self.rx_event.wait()  # Wait for the next interrupt
            # Do stuff that does allocate memory...
I have a similar setup for a Timer, but I've disabled that and still get the error....

mark_melvin
Posts: 10
Joined: Sat Dec 28, 2019 11:35 pm

Re: Keep getting MemoryError on ISR callback (asyncio)

Post by mark_melvin » Wed Jan 27, 2021 1:36 am

Bah! Just figured it out. Apparently you can't use "*args, **kwargs" in your handler signature.

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

Re: Keep getting MemoryError on ISR callback (asyncio)

Post by pythoncoder » Wed Jan 27, 2021 6:24 am

The correct way to handle UARTs in uasyncio is to use the stream mechanism rather than interrupts.
Peter Hinch
Index to my micropython libraries.

mark_melvin
Posts: 10
Joined: Sat Dec 28, 2019 11:35 pm

Re: Keep getting MemoryError on ISR callback (asyncio)

Post by mark_melvin » Wed Jan 27, 2021 2:00 pm

Thanks, but no matter what I did I could not make that work without losing data. Interrupts seem to work much smoother for me.

mark_melvin
Posts: 10
Joined: Sat Dec 28, 2019 11:35 pm

Re: Keep getting MemoryError on ISR callback (asyncio)

Post by mark_melvin » Wed Jan 27, 2021 2:41 pm

Having said that, my code has changed quite a bit since trying it. I'll give it another shot.

Thanks for asyncio and all the awesome documentation, BTW. It is all fantastic stuff!

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

Re: Keep getting MemoryError on ISR callback (asyncio)

Post by pythoncoder » Wed Jan 27, 2021 5:35 pm

If you lose data you could try increasing the receive buffer size in the UART constructor.

That said, uasyncio's I/O handling is not as fast as it might be. @Damien is planning performance improvements.
Peter Hinch
Index to my micropython libraries.

mark_melvin
Posts: 10
Joined: Sat Dec 28, 2019 11:35 pm

Re: Keep getting MemoryError on ISR callback (asyncio)

Post by mark_melvin » Thu Jan 28, 2021 12:11 am

The other thing that seems to be missing is a `.readinto()` method. Given that most of the memory used in my app is serial traffic I have a pre-declared buffer that I am reading the data into. Allocating bytes for each call to StreamReader.read() is probably not going to fare well given micropython's GC strategy, no?

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

StreamReader.readinto()

Post by pythoncoder » Thu Jan 28, 2021 5:55 am

On the face of it a .readinto() method would make a lot of sense. The commonest stream devices are sockets and uarts, both of which support .readinto().

As someone who favours line oriented protocols I'd want a .readline_into() which would need to behave rationally if the buffer filled before a newline occurred.You could raise a feature request on GitHub.
Peter Hinch
Index to my micropython libraries.

Post Reply