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 support@ccsinfo.com

Interrupt handling

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







Interrupt handling
PostPosted: Fri Dec 07, 2007 9:47 am     Reply with quote

Hi all!

After reading the CCS PICC manual I could not find a definitive answer to the following questions:
Let's say I have:
enable_interrupts(INT_TIMER0);
this will activate TIMER0. Then I use:
disable_interrupts(INT_TIMER0);
as far as I understand this will prevent the interrupt from firing but the interrupt flag will still be set if the TIMER0 overflows. Is this correct?
If so when I enter next:
enable_interrupts(INT_TIMER0);
the Timer0 interrupt should fire immediately because the flag is already set. To prevent this I should use:
clear_interrupt(INT_TIMER0);
before reenabling the interrupt. Is this correct?

Thanks for any help!

Regards,
Zer0flag
Ken Johnson



Joined: 23 Mar 2006
Posts: 197
Location: Lewisburg, WV

View user's profile Send private message

PostPosted: Fri Dec 07, 2007 10:13 am     Reply with quote

I believe you are correct, except for the possible meaning of this phrase:

Quote:

enable_interrupts(INT_TIMER0);
this will activate TIMER0.


You also need setup_timer0() to *activate* timer0, before it can overflow and cause an interrupt when enabled (also enable global interrupts).

Ken
Zer0flag
Guest







PostPosted: Fri Dec 07, 2007 10:47 am     Reply with quote

Thank you for your comment. You are correct. I'm sorry, I wanted to say: "will enable the Timer0 interrupt".

Ken Johnson wrote:
I believe you are correct, except for the possible meaning of this phrase:

Quote:

enable_interrupts(INT_TIMER0);
this will activate TIMER0.


You also need setup_timer0() to *activate* timer0, before it can overflow and cause an interrupt when enabled (also enable global interrupts).

Ken
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Fri Dec 07, 2007 11:06 am     Reply with quote

Actually, you really don't need the setup_timer0() statement to enable the timer. If I read the spec. sheet properly for the 18FXX2 PIC's the MCU resets with 0xFF in T0CON which will turn on the timer. Setup_timer0() is used to configure things the way you want them to be. As long as you enable the interrupts, the timer will, most likely, run at a default configuration.

Now, as far as needing to clear the interrupt before you enable it, on many PIC's it is possible to turn on/off the timer which will keep the interrupt flag from being set. I have used this in many applications. This can be used to conserve power, keep the timer from using unnesessary cpu time or many other uses.

Now, I'm not sure about this but if you use the clear_interrupt() command the interrupt is cleared but I believe the register will still have whatever value it has incremented to which could fire the interrupt right after it is cleared, if the register is close to turning over. This could cause you unexpected headaches if you don't clean things up so this doesn't happen.

Ronald
Zer0flag
Guest







PostPosted: Fri Dec 07, 2007 3:28 pm     Reply with quote

rnielsen wrote:

Now, as far as needing to clear the interrupt before you enable it, on many PIC's it is possible to turn on/off the timer which will keep the interrupt flag from being set. I have used this in many applications. This can be used to conserve power, keep the timer from using unnesessary cpu time or many other uses.


You mean you can stop the timer from incrementing? How do you do that? Is there any CCS function for that or is it only possible through direct register manipulation?

Quote:

Now, I'm not sure about this but if you use the clear_interrupt() command the interrupt is cleared but I believe the register will still have whatever value it has incremented to which could fire the interrupt right after it is cleared, if the register is close to turning over. This could cause you unexpected headaches if you don't clean things up so this doesn't happen.
Ronald


You are right, from my experience a timer keeps running and overflowing, running and overflowing forever, even if interrupts are disabled. But to keep things right I would just use set_timer0(0); before reenabling the interrupt. This way I make sure that the interrupt starts incrementing from 0 and then I would enable interrupts.

Some more info on my problem: All I want for my application is to make sure that I won't miss any timer interrupts if I disable them for a short time and then reenable them. This will probably work ok if the interrupt flag is set on timer overflow even when interrupts are disabled at that time - that way the ISR just won't execute until I reenable the timer interrupt but then it will execute immediately if I understand things right. I am doing this because when I am manipulating non-atomic variables of 16 bit or 32 bit in my main() function I have to make sure that a timer ISRs won't interrupt this manipulation in the middle of the assembler instructions. I have to make sure that this does not happen because I evaluate these variables in the ISR later. Some books are discribing this as "the data-sharing problem" between main code and ISRs. Unfortunately I could not find much PIC-specific info on that topic :(
Ken Johnson



Joined: 23 Mar 2006
Posts: 197
Location: Lewisburg, WV

View user's profile Send private message

PostPosted: Sat Dec 08, 2007 10:03 am     Reply with quote

You are correct again - disable interrupts when manipulating non-atomic variables shared by an isr.

I usually (but not always) disable ALL interrupts (global) when doing this. If you disable only timer0 interrupts, but several other interrupts could occur, you can end up with timer0 interrupt disabled longer than just the time to copy the non-atomic variables - this may not be important, but think about it.

Note also that I said "copy" the non-atomic variable. For example, if timer0 increments a 16- or 32-bit counter, don't use the counter itself in your main-loop code. Rather, make a copy of it first (disable ints, copy, enable ints), then use the copy. The copy operation is pretty quick, whereas add/compare or other operations probably take longer.

You're on the right track - go for it Smile

Ken
Zer0flag
Guest







PostPosted: Mon Dec 10, 2007 3:53 am     Reply with quote

Many thanks for the hints Ken!
Ttelmah
Guest







PostPosted: Mon Dec 10, 2007 4:13 am     Reply with quote

Ken's aproach is the best one.
Copying a value, takes just a few instructions. Disabling the global interrupt, prevents the interrupt handler(s) from being called, but the flags will in either case, still be set. So as soon as you re-enable the interrupts, any events that have happened in the meantime, will be responded to.
There is a caveat though. If (for instance), you disable the interrupt inside a routine, which is itself called from another routine, which has already disabled interrupts, and then you re-enable the interrupts, you can end up enabling the interrupts, when you really want them still disabled. This is why in some of the example code, and some of the internal CCS code, you will find routtines like:
Code:

#bit GIE= (set this to suit the processor involved)
int1 ints_were_on=FALSE;

while (GIE) {
   ints_were_on=TRUE
   disable_interrupts(GLOBAL);
} //This as written, also handles an erratum, on some chips.
//Copy the values here

if (ints_were_on) enable_interrupts(GLOBAL);


This only disables the interrupts, and re-enables them after the code, if they were enabled in the first place, and also handles the erratum, where if an interrupt occurs inside the disable instruction itself, the interrupt can get turned back on...

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