Simple Interrupt Problem

Questions and discussion about The WiPy 1.0 board and CC3200 boards.
Target audience: Users with a WiPy 1.0 or CC3200 board.
Post Reply
KMcLoud
Posts: 7
Joined: Sun Oct 30, 2016 1:06 pm

Simple Interrupt Problem

Post by KMcLoud » Sun Oct 30, 2016 1:35 pm

I was working on a significantly more complex programs and having some problems that I traced back to the fact that the interrupt wasn't firing.

I've written a new, extremely simple program just to prove to myself that I can make interrupts work, and its not going so well.

it uses the user button on the expansion board to trigger interrupts to increment a counter (or at least that's the idea)

here's the contents of boot.py, there is no main.py:

[code]
import micropython
from machine import Pin

micropython.alloc_emergency_exception_buf(100)

int_counter =0

def int_handler():
global int_counter
int_counter+=1


button=Pin('GP17', mode=Pin.IN, pull=Pin.PULL_UP)
button.irq(trigger=Pin.IRQ_RISING|Pin.IRQ_FALLING, handler=int_handler)
[/code]

I know the pin setup is working because when I go to the repl and run button() I get a value that toggles as I press and release the button

I know the handler function works because when I manually run int_handler(), int_counter increments.

Further, I suspect the trigger is working because when I press the button for the first time, the heartbeat LED blinks very rapidly for a couple seconds. However it won't do that again unless the button.irq() method is re-called.

However, when I press the button, int_counter does not increment.

Any idea what's going on here? I'm stumped

KMcLoud
Posts: 7
Joined: Sun Oct 30, 2016 1:06 pm

Re: Simple Interrupt Problem

Post by KMcLoud » Sat Nov 05, 2016 10:23 am

FYI, in case anyone else runs into this.

One of the devs over on the Pycom forum straightened this out for me.

when a pin interrupt is triggered and it calls its callback, it passes the pin object as an argument to the callback function.

Apparently, the fact that this happens inside an interrupt prevents the normal error message from getting out even with EMERGENCY_EXCEPTION_BUF set

I didn't think the docs made this clear, so its definitely something to watch out for.

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

Re: Simple Interrupt Problem

Post by dhylands » Sun Nov 06, 2016 1:45 am

Not sure what you mean by "prevents the normal error message from getting out".

Interrupts aren't allowed to allocate memory, and that includes memory to create an exception object. There is a pre-allocated MemoryError object and by default that gets thrown for any and all exceptions inside an interrupt handler.

You can call:

Code: Select all

import micropython
micropython.alloc_emergency_exception_buf(100)
and that will preallocate an emergency buffer which is used to allocate an exception and traceback information for exceptions which occur inside interrupt handlers.

This page covers much more depth about writing interrupt handlers:
http://docs.micropython.org/en/latest/p ... rules.html

Exceptions from interrupt handlers never make it out to the main program, since they would essentially windup interrupting some random piece of code in the main thread.

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

Re: Simple Interrupt Problem

Post by pythoncoder » Sun Nov 06, 2016 8:52 am

A couple of general points. MicroPython callbacks including interrupt handlers generally take a single argument which is the object causing the callback. Secondly it's usually best to run user code from main.py rather than boot.py. Further it's easiest to create your own module which you can run from the REPL. Only when the module is fully debugged do you need to alter main.py to simply issue

Code: Select all

import mymodule
Having development code automatically run after a soft reset tends to be inconvenient.
Peter Hinch
Index to my micropython libraries.

KMcLoud
Posts: 7
Joined: Sun Oct 30, 2016 1:06 pm

Re: Simple Interrupt Problem

Post by KMcLoud » Sun Nov 06, 2016 2:33 pm

@pythoncoder
thanks for the tip!

@dhylands
Thanks for taking a look

I was running the exception buffer in the above code, I expected it to raise an exception within the main program, but now I see how that could be problematic.

all the docs page says about catching the exception is "Debugging is simplified if the following code is included in any program using interrupts."

so how would one catch an exception from within an interrupt?

I understand that the code in the handler should be simple enough for this not to be an issue, I'm generally just toggling boolean flags. However, in cases like this catching that exception would sure help with debugging.

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

Re: Simple Interrupt Problem

Post by pythoncoder » Sun Nov 06, 2016 5:13 pm

The emergency buffer ensures that an exception in an interrupt handler produces a readable error message for debugging purposes. I'm pretty sure there's no way to trap such an exception. The key with interrupt handlers is to make them a short and simple as possible and to handle any abnormal conditions in code in the handler itself - i.e. aim to ensure that it never throws an exception.
Peter Hinch
Index to my micropython libraries.

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

Re: Simple Interrupt Problem

Post by dhylands » Sun Nov 06, 2016 6:17 pm

You catch an exception in an interrupt handler the same way that you do in regular code, but using try/catch.

I normally don't bother, since I typically don't do things in interrupt handlers which would cause exceptions, except for typos and bad code :)

The C code that calls the interrupt callback essentially puts a try/catch around the call to the callback, and if an exception is fired it reports that the callback failed to catch the exception and prints out the exception object.

Post Reply