Star Super
Star Super

Reputation: 9

How to abort a process on a microcontroller with an interrupt?

On a microcontroller not running any OS, when it has entered a routine and is busy executing some lengthy loops in there, how can I make the microcontroller abort prematurely from this routine (i.e. return to the calling routine) as a response to an interrupt (e.g. one that is generated when the user pressed a button)?

Is there any solution better than:

  1. polling the button or shared variables between the loops,
  2. manually modifying the return address in the stack,
  3. using an OS, and
  4. hardcoding POP and JUMP instructions in the ISR?

Many thanks!

Upvotes: 0

Views: 829

Answers (2)

DrRobotNinja
DrRobotNinja

Reputation: 1421

For a PIC or an AVR, all the OS's tend to play with the stack anyway, so I'd consider 2 - 4 to be the same option (except with an OS someone else has implemented and tested the stack manipulation.)

I'd recommend option 1, since it would be the most portable. A really quick way to do this in your code:

//Consider using static int if all the code is in one file
int WasButtonPressed;

//Change this to match your complier for interrupts
void __attribute__((__interrupt__,no_auto_psv)) _Interrupt
{
    //Rewrite this to use whatever button polling method
    if (PORTAbits.RA0) {
        WasButtonPressed = 1;
    }
}

//Testing to see if the interrupt fired and then get out of the function
#define HANDLE_BUTTON() { if (WasButtonPressed) return; }

Then you can pepper your loop with HANDLE_BUTTON(); calls.

Upvotes: 0

old_timer
old_timer

Reputation: 71536

If you want a lengthy function to be shortcut by an interrupt, and do it in a clean matter there really is only one way you need to build a clean return in the function. How you tell that function to return can be have the interrupt set a shared resource (a variable for example) and the foreground loop/function can return. Or you can have the foreground loop poll something (a gpio pin for example, timer, etc).

Normally what you would want to do is something different. You allow the foreground task to do low priority things, like updating a display or handling user input or something like that, and you dont force it to exit functions prematurely, instead in the isr you handle whatever it is that needs to be done as a priority.

That or you can make a mini-os if you will and have different threads, interrupts that catch hardware events that need to be handled leave that information and/or swap threads (save a copy of all the registers used by the currently running code, replace all the registers with the handler code and return to handler code). If the isr doesnt swap then a periodic timer will come along see the priority event and swap, then later the periodic timer will swap back when the priority handler is idling. Or the priority handler can call a function before it idles to cause a switch back to the foreground thread. Not complicated, more complicated than simple isrs yes, but still not very complicated.

Upvotes: 2

Related Questions