CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

General Interrupt Questions...

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
SBS



Joined: 15 Aug 2005
Posts: 18

View user's profile Send private message

General Interrupt Questions...
PostPosted: Mon Nov 14, 2005 10:48 am     Reply with quote

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

View user's profile Send private message Send e-mail Yahoo Messenger

PostPosted: Mon Nov 14, 2005 11:06 am     Reply with quote

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







PostPosted: Mon Nov 14, 2005 11:22 am     Reply with quote

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
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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