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

ISR and Sleep

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







ISR and Sleep
PostPosted: Sun Aug 29, 2004 12:48 pm     Reply with quote

If i have the following code in my isr:

Code:

#int_ext
void my_isr(void)
{
    flag = 1;
}


and somewhere in my code, i have:

Code:

while (1)
{
.....
    sleep();
    if (flag)
   {
       do_something();
       flag = 0;
   }
   else
   {
       //Why is flag not set????
   }
}


Well I have a mechanical switch connected to my RB0 pin, H_to_L edge interrupt enabled. If i hit the switch, sleep() wakes up, 'flag' gets set in the isr, then my "if (flag)" statement us guaranteed to always be true after a wakeup from sleep, right??

Many times, the PIC wake up, and the if-statment fails, so the else-statement runs instead.

Am I not guaranteed then that the ISR will not run immediately upon a wakeup?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun Aug 29, 2004 1:32 pm     Reply with quote

From section 12.13 of the 16F877 data sheet:
Power-down Mode (SLEEP):
"When the SLEEP instruction is being executed, the next instruction
(PC + 1) is pre-fetched." (This is the key point).
"If the GIE bit is set (enabled), the device executes the instruction
after the SLEEP instruction and then branches to the interrupt
address (0004h)." (When you pressed your switch, the GIE bit got set)
"In cases where the execution of the instruction following SLEEP is not
desirable, the user should have a NOP after the SLEEP instruction".

So, looking at the .LST file for your code, you see that the assembly
language instruction that updates the Z flag based on the value of 'flag'
is being pre-fetched and executed before 'flag' is actually updated in
your isr. The solution is to put a NOP after the Sleep() function.
You can use inline assembly for this, or define a macro and make the
nop look like a function call:

#define nop() #asm nop #endasm

sleep();
nop();

.................... while (1)
.................... {
.................... sleep();
*
0012: SLEEP
.................... if (flag)
.................... {
0013: MOVF flag,F // This instruction is pre-fetched !
0014: BTFSC STATUS.2
0015: GOTO 018
.................... flag = 0;
0016: CLRF flag
.................... }
.................... else
.................... {
MikeValencia



Joined: 04 Aug 2004
Posts: 238
Location: Chicago

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

PostPosted: Tue Aug 31, 2004 7:50 am     Reply with quote

Thanks PCM. You saved me a lot of time scratching my head.

What would happen would be, at the first wakeup from sleep, my else{} stuff would run, then at the next interrupt, the if{} stuff would run. It would happen every other interrupt. That's exactly the effect of what you described.

It should work fine now.
By the way, I don't think i need to use inline assembly to get a NOP. delay_cycles() should do the trick, i think.
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