|
|
View previous topic :: View next topic |
Author |
Message |
SBS
Joined: 15 Aug 2005 Posts: 18
|
General Interrupt Questions... |
Posted: Mon Nov 14, 2005 10:48 am |
|
|
Hi,
I have a few general questions about interrupts in PIC microcontrollers. I think I know the answers but I just want to make sure...
1) When I set up my interrupts for change on port B and timer 0, I make the following declarations (pseudocode):
enable interrupts RB;
enable interrupts Timer0;
enable interrupts GLOBAL
Do I really need the "GLOBAL" enable? Shouldn't enabling the separate interrupts be enough to turn them on?
2) If I have two interrupts enabled.... calling DISABLE_GLOBAL will turn both of them off. And then ENABLE_GLOBAL will turn both of them on, correct?
3) If I am in the code that is handling my timer0 interrupt, and I get a button press on port B. The timer0 interrupt doesn't get interrupted, right? You can't call an interrupt when in an interrupt? Or can you? Or is it that can't interrupt into an interrupt you are already in?
Thanks for your help,
Sal |
|
|
MikeValencia
Joined: 04 Aug 2004 Posts: 238 Location: Chicago
|
|
Posted: Mon Nov 14, 2005 11:06 am |
|
|
Quote: | 1) When I set up my interrupts for change on port B and timer 0, I make the following declarations (pseudocode):
enable interrupts RB;
enable interrupts Timer0;
enable interrupts GLOBAL
Do I really need the "GLOBAL" enable? Shouldn't enabling the separate interrupts be enough to turn them on?
|
Yup, you need the GLOBAL enable. Otherwise, those other interrupt bits will get set, but you'll never know.
Quote: |
2) If I have two interrupts enabled.... calling DISABLE_GLOBAL will turn both of them off. And then ENABLE_GLOBAL will turn both of them on, correct?
|
disable_global() will disable your ISR from getting called, but will not theoretically turn those two interrupts 'off'. In other words, those bits may still get set in the meantime, and the moment you call enable_interrupts(GLOBAL) again, those ISRs will run.
Quote: |
3) If I am in the code that is handling my timer0 interrupt, and I get a button press on port B. The timer0 interrupt doesn't get interrupted, right? You can't call an interrupt when in an interrupt? Or can you? Or is it that can't interrupt into an interrupt you are already in?
|
Right, it won't get interrupted, but the moment you finish off your current ISR, then you'll get interrupted all over again. This may be a waste of cpu cycles, but if your requirements aren't so tight, then you can get away with this. In my case, i would like to know if my rb0 interrupt is pending before i leave a current isr. so i do the following:
#int_timer0
tmr0_isr()
{
...
if (rb0 interrupt flag is set)
{
rb0_isr();
}
}
#int_ext
void external_interrupt_routine(void)
{
rb0_isr();
}
void rb0_isr();
{
...
// somewhere here, do a dummy read of PORTB.0, which automatically clears the interrupt flag.
}
Notice how i have a separate function for rb0_isr(). This gives the convenience of calling rb0_isr on the fly. |
|
|
Ttelmah Guest
|
|
Posted: Mon Nov 14, 2005 11:22 am |
|
|
The PIC has two control bits associated with each interrupt. The first controls whether the respective interrupt flag is operated, the second controls whether the hardware then responds to this. You can for example, 'enable' a specific interrupt, and leave the second (global) flag disabled. Then when the 'event' occurs, the interrupt flag will be set _but_ the hardware will not respond to this. You can then 'poll' the flag for the event, but without using an 'interrupt' as such.
Now the two flags, are also the basis for how the interrupt 'handler' works. When the hardware responds to an interrupt 'event' (an event is flagged, and the global interrupt is enabled), the _global_ flag is automatically disabled in the hardware. The software then decides which event handler to call. Only when the interrupt handler returns, is this flag automatically reset. If other interrupts occur inside the handler, their flags come on, but because the global flag is disabled, there is no hardware response. However when the interrupt handler _exits_, the global flag is automatically reset, and then if another interrupt flag is already 'made', the handler will be called, again with the global flag being disabled.
This has a number of implications. The first is that you must _never_ change the state of the 'global' flag inside an interrupt handler. If you enable this here, it can lead to a recursive interrupt event, which the hardware can't handle. Disabling the flag inside an interrupt handler, just won't work, since when the handler exits, the flag will be reset.
The next implication, is that if two events occur shortly after one another, so two interrupt flags are set when the global handler is called, the order with which the event handlers is called, depends on the order the software checks the bits, _not_ the time when the actual events took place. This is set by default, by the order the event handlers are declared in memory, but can be changed by the #priority instruction. Now if an event with a high priority keeps happening at short intervals, handlers for other events, may never get called (interrupt 'starvation').
The final thing is related to the way the PIC itself works. Because there is no 'software stack', to allow variables to be saved/retrieved on a FIFO basis, storage locations are hard coded for routines. Hence a routine must never interrupt itself. Hence if any subroutine is used inside an interrupt, and the same routine is used outside the interrupt, the compiler automatically adds protection for the outer call, by disabling the global interrupt when it is called, and re-enabling it when the code exits. This is fine (with the caveat, that it will slow the response to an interrupt event), provide you do not re-enable the global interrupt inside the routine, overriding this protection...
Best Wishes |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|