|
|
View previous topic :: View next topic |
Author |
Message |
valemike Guest
|
ISR and Sleep |
Posted: Sun Aug 29, 2004 12:48 pm |
|
|
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
|
|
Posted: Sun Aug 29, 2004 1:32 pm |
|
|
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
|
|
Posted: Tue Aug 31, 2004 7:50 am |
|
|
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. |
|
|
|
|
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
|