Author Topic: Microcontroller ISRs  (Read 9650 times)

0 Members and 1 Guest are viewing this topic.

Offline ice595Topic starter

  • Regular Contributor
  • *
  • Posts: 98
  • Country: ca
Microcontroller ISRs
« on: October 16, 2016, 05:47:58 pm »
So I've heard that an interrupt service routine should be quick and not call another functions.
Im quite familiar with the PIC24H and PIC32 family of micros as I've worked with them for 2 semesters at school.
Lets say for example I want to update a LCD display every second, I would need to setup a timer interrupt to fire every second.
During the interrupt service routine, should I call a function to update the LCD?
As long as the interrupt flag bit is cleared before calling the function would allow other interrupts to fire right?
If not, what other options do I have?
 

Offline Towz

  • Contributor
  • Posts: 26
  • Country: pe
  • this avatar gallery is so awesome o.o
Re: Microcontroller ISRs
« Reply #1 on: October 16, 2016, 06:10:57 pm »
It would but it isn't good practice since if there are other interrupt sources it might mess up the lcd update (a fairly long process unless driving it directly). It seems better to do the lcd update via the main program and using the isr just to enable it. But with pic24/32 you have the option to use low and high priority interrupts if you really want to update the lcd with an isr.
 

Offline mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 13742
  • Country: gb
    • Mike's Electric Stuff
Re: Microcontroller ISRs
« Reply #2 on: October 16, 2016, 06:13:09 pm »
You only use interrupts for things that need attention fast.
1 sec display update does not come under that category.
Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 
The following users thanked this post: alexanderbrevig

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11238
  • Country: us
    • Personal site
Re: Microcontroller ISRs
« Reply #3 on: October 16, 2016, 06:25:20 pm »
During the interrupt service routine, should I call a function to update the LCD?
Set a flag in the ISR, check that flag in the main program. This way your display update routine can be interrupted by other things and your system will remain responsive.
Alex
 

Offline mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 13742
  • Country: gb
    • Mike's Electric Stuff
Re: Microcontroller ISRs
« Reply #4 on: October 16, 2016, 06:34:13 pm »
Unless you can set up a timer to set an interrupt flag every second, in which case you don't need an ISR at all - just test the flag in your main loop.


Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11238
  • Country: us
    • Personal site
Re: Microcontroller ISRs
« Reply #5 on: October 16, 2016, 06:37:24 pm »
Unless you can set up a timer to set an interrupt flag every second, in which case you don't need an ISR at all - just test the flag in your main loop.
Yes, for things that happen rarely, you can just poll the hardware flag.

I was thinking of a more complex case, where you may want to run the hardware timer a bit faster, and derive all software timers from that.
Alex
 

Offline ice595Topic starter

  • Regular Contributor
  • *
  • Posts: 98
  • Country: ca
Re: Microcontroller ISRs
« Reply #6 on: October 16, 2016, 07:36:56 pm »
but does clearing the hardware interrupt flag allow other interrupts of equal or lower priority to fire?
if not, then does it matter if the interrupt flag is cleared upon entering the ISR or cleared right before exiting the ISR?

void timerISR()
{
         clear timer interrupt flag here?
         ISR stuff here
         or clear timer interrupt flag here?
}
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11238
  • Country: us
    • Personal site
Re: Microcontroller ISRs
« Reply #7 on: October 16, 2016, 07:41:56 pm »
         ISR stuff here
There is no ISR stuff. Simplified code:

Code: [Select]
volatile bool timer_flag = false;

void timerISR()
{
  timer_flag = true;
  clear timer interrupt flag here
}

int main(void)
{
  // init everything
  while (1)
  {
    if (timer_flag)
    {
      // do display suff here
      timer_flag = false;
    }

    // all other stuff
  }
}

Or, as Mike suggested for a simple timer:

Code: [Select]
int main(void)
{
  // Init everything
  // Configure timer,  but don't enable timer interrupt

  while (1)
  {
    if (interrupt flag is set in the timer register)
    {
      // do display suff here
      // clear interrupt flag
    }

    // all other stuff
  }
}
« Last Edit: October 16, 2016, 07:43:40 pm by ataradov »
Alex
 

Offline ice595Topic starter

  • Regular Contributor
  • *
  • Posts: 98
  • Country: ca
Re: Microcontroller ISRs
« Reply #8 on: October 16, 2016, 07:53:54 pm »
         ISR stuff here
There is no ISR stuff. Simplified code:

Code: [Select]
volatile bool timer_flag = false;

void timerISR()
{
  timer_flag = true;
  clear timer interrupt flag here
}

int main(void)
{
  // init everything
  while (1)
  {
    if (timer_flag)
    {
      // do display suff here
      timer_flag = false;
    }

    // all other stuff
  }
}

Or, as Mike suggested for a simple timer:

Code: [Select]
int main(void)
{
  // Init everything
  // Configure timer,  but don't enable timer interrupt

  while (1)
  {
    if (interrupt flag is set in the timer register)
    {
      // do display suff here
      // clear interrupt flag
    }

    // all other stuff
  }
}

yeah but isn't polling bad though? (like constantly asking "are we there yet?" during a long car ride)

what I ideally want is for the timer to update the LCD every second, but still allow interrupts to fire during the LCD update process. I guess I could set other interrupts to higher priority ::)
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11238
  • Country: us
    • Personal site
Re: Microcontroller ISRs
« Reply #9 on: October 16, 2016, 07:56:41 pm »
yeah but isn't polling bad though? (like constantly asking "are we there yet?" during a long car ride)
That depends. Are you doing anything important while you wait? Or are you just sitting in the same loop? For most practical cases polling works just fine.

what I ideally want is for the timer to update the LCD every second, but still allow interrupts to fire during the LCD update process. I guess I could set other interrupts to higher priority ::)
You will run into all sorts of problems doing this, but see for yourself.
Alex
 

Offline Kleinstein

  • Super Contributor
  • ***
  • Posts: 14181
  • Country: de
Re: Microcontroller ISRs
« Reply #10 on: October 16, 2016, 08:28:55 pm »
It really depends on the context. If there is nothing critical going one on can very well do a lot of things in the ISR. In the extreme case the main program is only sending the µC back into sleep mode and everything else is done in an ISR. For some µCs function calls inside an ISR cause extra overhead, e.g for saving a few extra registers. So in time critical cases one should avoid it, but if not time- (or stack-) critical a few 10 cycles are not that bad.

Only the so often heard part of only setting a flag in the ISR is usually bad, as the hardware usually can do that without an ISR as well.

Allowing nested interrupts when something not that important in an ISR can very well be a good solution, if one can make sure the same type of interrupt is not called again before the code is finished and one has enough stack space. µCs with internal buffer (e.g. some PIC18) might also need extra attention.

Handling slow IO parts like the LCD output can have more difficulties, not to access the same hardware twice at the same time (e.g. ISR and main program). Also waiting for the response is not that nice inside an ISR.
 

Offline ice595Topic starter

  • Regular Contributor
  • *
  • Posts: 98
  • Country: ca
Re: Microcontroller ISRs
« Reply #11 on: October 16, 2016, 08:51:51 pm »
I still remember my final project for my microcontrollers course last year.
We had to make a temperature logger with a 3x4 keypad and a 128x64 SPI LCD, and mine was the lowest in power consumption.  ;D
What I did was setup a change notification interrupt to the pins connected to the keypad, so every time a key is pressed the ISR would do a keypad scan to determine which key was pressed and update the statemachine accordingly (e.g read temperature, save it, display saved data, dump data to uart). so it called the state machine function which called many many other functions :palm:
Once the state machine is updated, it would go back to sleep and wait for further interrupts to wake it up again.

and everyone else did an infinite loop scanning their keypad to constantly check for keypresses
 

Online ataradov

  • Super Contributor
  • ***
  • Posts: 11238
  • Country: us
    • Personal site
Re: Microcontroller ISRs
« Reply #12 on: October 16, 2016, 08:55:11 pm »
Code: [Select]
int main(void)
{
  // Init everything
  // Configure timer,  but don't enable timer interrupt

  while (1)
  {
    if (interrupt flag is set in the timer register)
    {
      // do display suff here
      // clear interrupt flag
    }

    // all other stuff

    wfi(); //  make the thing low power (for ARM in this case, but similar thing goes for all other MCUs)
  }
}

Still  no need for actual ISRs.
Alex
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9889
  • Country: us
Re: Microcontroller ISRs
« Reply #13 on: October 16, 2016, 09:10:38 pm »
I like the idea of setting a flag in the interrupt handler.  That concept flows nicely into setting a semaphore in an RTOS where, whenever it gets around to it, the RTOS will dispatch the code to do whatever is required of the interrupt.  All priority stuff is handled by the RTOS.  Sometimes there is more to it than setting a semaphore.  We might grab a value in the interrupt handler and stuff it in a queue.  But it's still fast!  Get in and get out!

There is certainly nothing wrong with polling the timer in the super loop; it's a pretty fast operation.  What you don't want to poll (and hang) for is something like an incoming character, something that might not happen for a long time, if ever.  So, there is a difference between testing and moving on versus testing and hang until.

Early games were written in a super loop, in effect, simulating threads without multiple cores.  There was a loop counter that wrapped around modulo <something>.  The counter value was used to determine what part of the game to update using a large switch statement.  That way, there was no need to hang and the game could be responsive without the graphics routine hogging the compute cycles.


 

Offline mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 13742
  • Country: gb
    • Mike's Electric Stuff
Re: Microcontroller ISRs
« Reply #14 on: October 16, 2016, 09:39:23 pm »
I still remember my final project for my microcontrollers course last year.
We had to make a temperature logger with a 3x4 keypad and a 128x64 SPI LCD, and mine was the lowest in power consumption.  ;D
What I did was setup a change notification interrupt to the pins connected to the keypad, so every time a key is pressed the ISR would do a keypad scan to determine which key was pressed and update the statemachine accordingly (e.g read temperature, save it, display saved data, dump data to uart). so it called the state machine function which called many many other functions :palm:
Once the state machine is updated, it would go back to sleep and wait for further interrupts to wake it up again.

and everyone else did an infinite loop scanning their keypad to constantly check for keypresses
All they would have needed to do was put a sleep instruction in their loop and it would have worked just as well. In fact if you're squeezing every nanojoule, it would have been more efficient as you wouldn't have the ISR context save overhead.

The only normal reason to use an interrupt is when you need a guaranteed response time substantially faster than you can guarantee with your main program loop.
You should generally only do the absolute minimum in the int code, as long ISRs will degrade the worst-case performance of other interrupts or your main code.
Another good reason to minimise interrupt code is it can be a lot harder to debug problems in ( or caused by) interrupt routines. 

There are always some special cases where you might do things differently, but in general you should only use ints where they are needed, and then only to the minimum extent to which they are needed.

 
Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 

Offline langwadt

  • Super Contributor
  • ***
  • Posts: 4414
  • Country: dk
Re: Microcontroller ISRs
« Reply #15 on: October 16, 2016, 10:47:21 pm »
you can do other trickery, like  triggering a low priority interrupt or manually adding a stack frame in the interrupt so rti will return to a different function before returning to main. 

sometimes such tricks can be necessary when an interrupt is shared and the cpu (e.g cortex) doesn't
support reentrant interrupts
 

Offline mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 13742
  • Country: gb
    • Mike's Electric Stuff
Re: Microcontroller ISRs
« Reply #16 on: October 16, 2016, 11:41:23 pm »
you can do other trickery, like  triggering a low priority interrupt or manually adding a stack frame in the interrupt so rti will return to a different function before returning to main. 

sometimes such tricks can be necessary when an interrupt is shared and the cpu (e.g cortex) doesn't
support reentrant interrupts
If you need re-entrant interrupts you're probably doing it wrong.
Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Microcontroller ISRs
« Reply #17 on: October 17, 2016, 12:12:14 am »
Quote
During the interrupt service routine, should I call a function to update the LCD?

what you were told is generally true. that means it is not always true, especially for a more complex chip like pic24/32. and you may want to see how frequently other tasks in your code run before making a decision here.

as to clear the flag, you generally want to clear the flag at the beginning of the isr so not to miss an interrupt event.
================================
https://dannyelectronics.wordpress.com/
 

Offline langwadt

  • Super Contributor
  • ***
  • Posts: 4414
  • Country: dk
Re: Microcontroller ISRs
« Reply #18 on: October 17, 2016, 08:25:19 am »
you can do other trickery, like  triggering a low priority interrupt or manually adding a stack frame in the interrupt so rti will return to a different function before returning to main. 

sometimes such tricks can be necessary when an interrupt is shared and the cpu (e.g cortex) doesn't
support reentrant interrupts
If you need re-entrant interrupts you're probably doing it wrong.

calling it re-entrant might be the wrong term, more like software nesting, as and example a timer timer with a single interrupt
but four compares

or an arm7 that only has one interrupt

 

Offline ice595Topic starter

  • Regular Contributor
  • *
  • Posts: 98
  • Country: ca
Re: Microcontroller ISRs
« Reply #19 on: October 17, 2016, 10:38:14 am »
as to clear the flag, you generally want to clear the flag at the beginning of the isr so not to miss an interrupt event.

so as soon as the hardware interrupt flag bit is cleared, other interrupts of same or lower priority can interrupt the current ISR even though it didn't fully exit the current ISR function right?
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: Microcontroller ISRs
« Reply #20 on: October 17, 2016, 11:13:01 am »
Whether interiors can be nested is a hardware question, and not a primary driver here.

Think of two tightly timed events being served by the isr.

The first event fires and the execution jumps to the isr. Let's say that the isr clears the flag on the way out. While the isr is serving the first event, the 2nd event arrives and the flag remain set. On the exit, the flag is set.

As far as the isr is concerned, only one event took place.

If instead, you clear the flag right away, the 2nd event will set the flag again. Upon exiting the first isr, the execution will jump right back to it. Ie. Both events are served. And no event is missed.
================================
https://dannyelectronics.wordpress.com/
 

Offline mikeselectricstuff

  • Super Contributor
  • ***
  • Posts: 13742
  • Country: gb
    • Mike's Electric Stuff
Re: Microcontroller ISRs
« Reply #21 on: October 17, 2016, 12:30:04 pm »
Whether interiors can be nested is a hardware question, and not a primary driver here.

Think of two tightly timed events being served by the isr.

The first event fires and the execution jumps to the isr. Let's say that the isr clears the flag on the way out. While the isr is serving the first event, the 2nd event arrives and the flag remain set. On the exit, the flag is set.

As far as the isr is concerned, only one event took place.

If instead, you clear the flag right away, the 2nd event will set the flag again. Upon exiting the first isr, the execution will jump right back to it. Ie. Both events are served. And no event is missed.
If you're expecting this to happen, a better approach is to do
while (interrupt_flag)
 {
    <clear interrupt_flag>
    <do interrupt stuff>
 }

That way, you don't have the interriupt entry/exit overhead for the second interrupt
Youtube channel:Taking wierd stuff apart. Very apart.
Mike's Electric Stuff: High voltage, vintage electronics etc.
Day Job: Mostly LEDs
 

Offline langwadt

  • Super Contributor
  • ***
  • Posts: 4414
  • Country: dk
Re: Microcontroller ISRs
« Reply #22 on: October 17, 2016, 02:26:50 pm »
Whether interiors can be nested is a hardware question, and not a primary driver here.

Think of two tightly timed events being served by the isr.

The first event fires and the execution jumps to the isr. Let's say that the isr clears the flag on the way out. While the isr is serving the first event, the 2nd event arrives and the flag remain set. On the exit, the flag is set.

As far as the isr is concerned, only one event took place.

If instead, you clear the flag right away, the 2nd event will set the flag again. Upon exiting the first isr, the execution will jump right back to it. Ie. Both events are served. And no event is missed.
If you're expecting this to happen, a better approach is to do
while (interrupt_flag)
 {
    <clear interrupt_flag>
    <do interrupt stuff>
 }

That way, you don't have the interriupt entry/exit overhead for the second interrupt

with cortex-m it doesn't make much difference, it does tail chaining so it skips the restore-store when an interrupt is pending
on the return from interrupt

 

Offline KL27x

  • Super Contributor
  • ***
  • Posts: 4099
  • Country: us
Re: Microcontroller ISRs
« Reply #23 on: October 18, 2016, 01:45:18 am »
Quote
but does clearing the hardware interrupt flag allow other interrupts of equal or lower priority to fire?
No.... Another interrupt flag may be set in the interim. But not until you exit ISR can another equal/lower ISR flag be acted upon by its own ISR. Hence, while any piece of ISR is being executed, there will be latency in response to a flag being set of equal or lower priority.

You can write the code, right in your own ISR, to poll for a "higher (by your definition)" interrupt flag, and to abandon current ISR.

Quote
if not, then does it matter if the interrupt flag is cleared upon entering the ISR or cleared right before exiting the ISR?
It might matter. In case you want this ISR subroutine to immediately repeat if the condition is retriggered while ISR is still executing or not.
The main reason to do it up front, though, IMO, is so you don't have to cover it multiple times, in case of multiple branches in the ISR.

Your needs may be unique. You can certainly write good code that doesn't follow the "short ISR" rule. It depends what you need the micro to do. As long as you understand it, you can achieve your result anyway you want.

If your code may get more complicated later, it might be nice to use timer interrupt set for 10ms, rather than simply set timer for 1 second and check the timer generated flag in main code loop. In ISR, you can increment multiple counters. In this way you can use a single timer for multiple events. When the "LCD timer counter" reaches 100, set your own flag. This can stretch your peripherals and reduce time spent looking at datasheet. Or you could set it so that some order of 2 will equal 1 second. And let the counter freely increment. Everytime bit X change state, set that user flag. Evertime bit Y changes state, you might have something else periodically firing at a different rate, which is some order of 2 different in period, etc. Now you got multiple concurrent timers out of a single post scaler.
« Last Edit: October 18, 2016, 02:29:35 am by KL27x »
 

Offline viperidae

  • Frequent Contributor
  • **
  • Posts: 306
  • Country: nz
Re: Microcontroller ISRs
« Reply #24 on: October 18, 2016, 08:27:16 am »
If you call a long running function from an isr then no other isr will run. The isr isn't over until the retfie instruction is called.

The only exception to this is high priority interrupts can interrupt a low priority one.

That's how it works for pic24.

Pic32 is similar
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf