Page 1 of 1
pyb.Switch() Memory Error External Interrupt
Posted: Tue Oct 07, 2014 12:19 am
by mosi
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 ...
Re: pyb.Switch() Memory Error External Interrupt
Posted: Tue Oct 07, 2014 6:07 am
by dhylands
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.
Re: pyb.Switch() Memory Error External Interrupt
Posted: Tue Oct 07, 2014 6:15 am
by fma
Maybe pyb.Led(1) creates a new reference to the existing Led object, so it does allocate memory?
Re: pyb.Switch() Memory Error External Interrupt
Posted: Tue Oct 07, 2014 6:32 am
by dhylands
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.
Re: pyb.Switch() Memory Error External Interrupt
Posted: Tue Oct 07, 2014 6:42 am
by dhylands
It only seems to be a problem when the parenthesis are removed from a bound function.
Re: pyb.Switch() Memory Error External Interrupt
Posted: Tue Oct 07, 2014 11:28 am
by mosi
Thank you,
great answer, I will try not to code at 3am again.
Will dig deeper into interrupt handling and callbacks.
Re: pyb.Switch() Memory Error External Interrupt
Posted: Tue Oct 07, 2014 2:48 pm
by dhylands
I found the problem with the traceback not being reported and filed a PR:
https://github.com/micropython/micropython/pull/894
Re: pyb.Switch() Memory Error External Interrupt
Posted: Thu Oct 09, 2014 3:59 pm
by dhylands
And that PR has now been merged into the source.