pyb.Switch() Memory Error External Interrupt

C programming, build, interpreter/VM.
Target audience: MicroPython Developers.
Post Reply
mosi
Posts: 28
Joined: Tue Oct 07, 2014 12:07 am

pyb.Switch() Memory Error External Interrupt

Post by mosi » Tue Oct 07, 2014 12:19 am

Any idea where I might start searching for an error in this code?

Code: Select all

sw = pyb.Switch()

def BTN_callback():
   pyb.udelay(4000)
   pyb.LED(1).toggle
 
sw.callback(BTN_callback)

Code: Select all

>>> Uncaught exception in ExtInt interrupt handler line 0
MemoryError: 
sw.callback(lambda:

does work, however, what if one wants to implement a more complicated button behavior?

Like:
button_callback:
1. wait
2. dim led with pwm in a sinusiodal wave
3. if button press longer than x, start pwm on second led ...

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

Re: pyb.Switch() Memory Error External Interrupt

Post by dhylands » Tue Oct 07, 2014 6:07 am

Interrupt handlers aren't allowed to allocate any memory, which unfortunately means that even reporting an error is problematic.

The first thing I do is to add the call:

Code: Select all

import micropython
micropython.alloc_emergency_exception_buf(100)
into your code and hopefully get better error reporting.

As a general rule, you also shouldn't put delays in your interrupt handlers.

pyb.delay requires the SysTick interrupt to work, so it may not work in your interrupt handler. The pyb.udelay doesn't require interrupts to work (at least not on the stmhal port), but while you're delaying, other lower-priority interrupts will be delayed as well.

I tried adding those lines, and I still see the same thing, which is not what I was expecting. So I think you've uncovered a bug.

The bug in your routine is the line: pyb.Led(1).toggle which has 2 potential issues. I thought the first issue would be that pyb.Led(1) allocates a LED object, but it turns out that internally the LED module pre-allocates all of the LED objects. The second issue is that you're missing the parenthesis to call toggle().

If you rewrite your routine:

Code: Select all

import pyb
import micropython
micropython.alloc_emergency_exception_buf(200)

sw = pyb.Switch()

def BTN_callback():
    pyb.LED(1).toggle()
 
sw.callback(BTN_callback)
I'll take a look into why no error is reported when the parenthesis are removed. I suspect that what's happening is that because pyb.LED(1).toggle is a function object and that the code is trying to allocate some memory to store that function object; which would be what's causing the MemoryError, but I would have expcected some traceback information.

fma
Posts: 164
Joined: Wed Jan 01, 2014 5:38 pm
Location: France

Re: pyb.Switch() Memory Error External Interrupt

Post by fma » Tue Oct 07, 2014 6:15 am

Maybe pyb.Led(1) creates a new reference to the existing Led object, so it does allocate memory?
Frédéric

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

Re: pyb.Switch() Memory Error External Interrupt

Post by dhylands » Tue Oct 07, 2014 6:32 am

The code as I posted it woks, which tells me that pyb.LED(1) doesn't allocate any memory.

I don't see any allocations in the C code.

I tried to change it to:

led = pyb.LED(1)

and if I use led.toggle() then it works properly, but if I use: led.toggle I get a memory error with no backtrace.
Similarly, using pyb.LED(1).toggle() works fine and pyb.LED(1).toggle gives a memory error with no backtrace.

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

Re: pyb.Switch() Memory Error External Interrupt

Post by dhylands » Tue Oct 07, 2014 6:42 am

It only seems to be a problem when the parenthesis are removed from a bound function.

mosi
Posts: 28
Joined: Tue Oct 07, 2014 12:07 am

Re: pyb.Switch() Memory Error External Interrupt

Post by mosi » Tue Oct 07, 2014 11:28 am

Thank you,
great answer, I will try not to code at 3am again.

Will dig deeper into interrupt handling and callbacks.

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

Re: pyb.Switch() Memory Error External Interrupt

Post by dhylands » Tue Oct 07, 2014 2:48 pm

I found the problem with the traceback not being reported and filed a PR:
https://github.com/micropython/micropython/pull/894

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

Re: pyb.Switch() Memory Error External Interrupt

Post by dhylands » Thu Oct 09, 2014 3:59 pm

And that PR has now been merged into the source.

Post Reply