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

How to clear completely an interrupt??

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



Joined: 06 Sep 2007
Posts: 4

View user's profile Send private message

How to clear completely an interrupt??
PostPosted: Sat Sep 29, 2007 2:29 am     Reply with quote

Hi all!
Can I clear an interrupt in its isr using clear_interrupts(..)? Please show me really function of clear_interrupts(Timer2). Thank u very much!
Ttelmah
Guest







PostPosted: Sat Sep 29, 2007 3:15 am     Reply with quote

First understand what is happening. An 'interrupt', is a simple 'bit' in memory (in the case of timer2, called 'symbolically' TMR2IF). The 'timer2 interrupt flag'. Whenever the timer reaches it's terminal count, the timer resets the count to '0', and (for most interrupts), sets the interrupt flag. In the case of 'timer2', the signal here, feeds into yet anothe counter, allowing you to elect to actually set the interrupt flag only on every second, third, fourth etc., loop.
Now there is hardware in the chip, which has a number of logic gates combining various signals. For this timer, the three signals are:
TMR2IE 'interrupt enable'
TMR2IF 'interrupt flag'
GIE 'global interrupt enable'
If all three are 'set', then the hardware automatically clears the GIE bit, and issues a 'call' to address 8 (On a '18' chip, assuming interrupt priorities are not used). GIE is disabled, to prevent interrupts 'interrupting' the handler code.
At address 8, there is a program, known as the 'global interrupt dispatcher'.This saves _all_ the internal hardware registers (including things like table addresses for accessing arrays etc.), then for every interrupt with a dispatcher present, checks (in the order the interrupt handlers were defined, or in the order set in the #priority statement, if one is present), for the interrupt flag being set. If it is set, it also checks that the corresponding enable is set. If both are 'true', it jumps to the #INT_TIMER2 routine. Now, in the routine, you perform what you want. Then when the routine returns, the code _automatically clears the interrupt flag_. It returns to the 'global interrupt dispatcher', which restores all the saved registers (hopefully putting things back as they were before the interrupt handler was called). The final thing it does, is to 'return' to the location where the interrupt occured, using a 'special' return instruction, which re-enables GIE.

Now, you never need to use the clear_interrupt routine, unless you want to change this default handling. All the 'clear interrupt' routine does, is clear the 'flag' bit. The compiler already does this for you.

The reasons to use this routine, are various. The first, would be if you are 'enabling' an interrupt, which may have already triggered in the past, and you don't want the handler called for this 'old' probably 'spurious' trigger. Hence you would setup the timer, clear the interrupt, and then enable the interrupt, to avoid this 'extra' call.
The second reason, would be if you have perhaps an external interrupt 'event', where two interrupt may occur very quickly after one another. With these, you can clear the interrupt right at the 'start' of your handler, and then at the end of the handler, loop if the flag has become set a second time, to give much faster handling. Downside, is that if this happens too often, the code can get stuck in the handler... Also, for this, you would disable the default 'clear' at the exit of the handler routine. This is done by defining this with the 'NOCLEAR' directive.
The third occasion when the clear interrupt would be used, is if you, again for speed, elect not to use the default 'int_global' routine, and then have to save the registers needed, and reset the flag yourself.
The fourth use, would be if you don't actually 'interrupt'. Note that the flag becomes 'set', when the counter reaches a value. It doesn't depend on either of the interrupt 'enable' bits concerned. Hence, if you wanted to 'synchronise' a loop in your code, to the timer, you could simply sit reading the 'flag' bit with the interrupts disabled. Once the bit becomes set, you can move on, clear the bit, and execute your main code. This potentially gives faster responses than using the hardware interrupt handler (since there is no need to save lots of registers), while still giving execution 'connected' to the hardware event. Several of the internal routines use this approach. For example, the 'getc' routine, for a hardware UART, will check the received data interrupt flag is set, before trying to read a character.

At heart, unless you have one of these more complex reasons to use this instruction, there is no need ever to use the 'clear interrupt' handler.

Best Wishes
mfeinstein



Joined: 05 Jul 2012
Posts: 35

View user's profile Send private message

PostPosted: Thu Sep 06, 2012 7:35 pm     Reply with quote

Ttelmah, I am dealing with the case you specified as:

"The first, would be if you are 'enabling' an interrupt, which may have already triggered in the past, and you don't want the handler called for this 'old' probably 'spurious' trigger. Hence you would setup the timer, clear the interrupt, and then enable the interrupt, to avoid this 'extra' call. "

But since I am dealing with 4 interrupts in my code, is there a way to clear them all at the same time? I saw there is a GLOBAL input, but I am not sure if it will clear the interrupt bit, or the GIE or other Global bit...
Thanks!
Ttelmah



Joined: 11 Mar 2010
Posts: 19482

View user's profile Send private message

PostPosted: Fri Sep 07, 2012 1:01 am     Reply with quote

No,
Seriouosly, just do four calls to clear_interrupt.
The GLOBAL bit is a separate thing (as already said). The clear_interrupt instruction, codes as a single bit_clear instruction. To clear multiple interrupts you could (potentially) if all the bits were in one register, read the register, then use '&' to turn off all the bits, and write the value back. However this takes as many instructions as the separate clear instructions (actually the break even point, should be for three bits), so there is no point in getting involved in this complexity, especially since in most cases the bits are likely to be in multiple registers.
A comment though. remember you must clear the hardware event, _before_ you can clear the flag(s). So (for example), INT_RDA, cannot be cleared, until you read the character from the UART receive buffer. Similarly INT_RB, cannot be cleared, until you perform a read from Port B, to clear the input latch. INT_SSP, requires you to read the character waiting in the SSP buffer, etc. etc..

Best Wishes
mfeinstein



Joined: 05 Jul 2012
Posts: 35

View user's profile Send private message

PostPosted: Fri Sep 07, 2012 2:00 am     Reply with quote

Ttelmah, so I am assuming that a call like clear_interrupt(INT_TIMER0|INT_TIMER1|INT_TIMER2); wouldn't be valid also right?
When you say that "you must clear the hardware event" it's also valid for timers interrupts? I didnt know you had to service the interrupt always, I thought you could just clear the flag to ignore it...
Best Regards!
Ttelmah



Joined: 11 Mar 2010
Posts: 19482

View user's profile Send private message

PostPosted: Fri Sep 07, 2012 2:49 am     Reply with quote

CCS functions that accept the values 'ored' together, usually say so.
In fact if you try or'ing some combinations, you'll trigger a compiler error.
Seriously, on what hardware events need clearing _read the data sheet_.
jeremiah



Joined: 20 Jul 2010
Posts: 1343

View user's profile Send private message

PostPosted: Fri Sep 07, 2012 6:32 am     Reply with quote

Just as an example of that, if you have a chip that has a port B interrupt that you enable, you manually have to read the port in addition to clearing the flag or the hardware will just trigger another interrupt as soon as the flag clears. I don't recall any timers needing anything other than clearing the flag, so those should be safe, but definitely reference the data sheet for specific interrupts.
mfeinstein



Joined: 05 Jul 2012
Posts: 35

View user's profile Send private message

PostPosted: Fri Sep 07, 2012 1:02 pm     Reply with quote

Ok! Thanks guys!
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