PDA

View Full Version : 9 times out of 10, my program awakes fine (IOC interrupt related), but....



HankMcSpank
- 9th October 2011, 19:08
This is a tricky one that I can't get to the bottom of....I'm at a loss now and throw myself open to the forum for help!

Ok, here's what I'm doing, I'm putting a PIC to sleep, just before doing so, I enable IOC DT interrupts....



IOCAF = 0 'clear the interrupt flag
@ INT_ENABLE IOC_INT ' enable IOC interrupts
PAUSE 50 'wait a little
@ sleep ' put the PIC to sleep


Ok, so far so good, my PIC goes to sleep

So now when a switch gets pressed. the PIC gets woken up by an IOC Interrupt - I have a fair splattering of debug lines in the interrupt routine - I can see the program enter the IOC Interrupt routine (debug line at the top of the routine) & exit (another debug line at the end of the routine) - again so far so good.

Now from my weak understanding of waking from sleep, I believe the program picks up from the line of code immediately after the @sleep line (above), so here's what follows the @sleep line in my program...



@ sleep ' put the PIC to sleep (ie same entry as above, shown here to show the flow of things)

'here's what follows & should be where the PIC picks up...

pause 5
TrisA.0 = 0 ' make the nominated debug pin an output
debug "awake",13,10

So when all is working well, with the PIC being asleep, after a switch is pressed (to wake up the PIC), I should see my IOC interrupt 'entry' debug line, my IOC interrupt 'exit' debug line & then the word "awake" (ie the line of code immediately following the @sleep command)

So what's the problem?

Well as my thread title suggests...it's not robust - if I press the switch to wake the PIC ....about 7-10 times it wakes up fine on the trot, but then a problem occurs & my program appears to go nowhere(!) - the last thing debug line I see on my screen is my IOC interrupt 'exit' debug entry.....and nothing else after that (in other words I don't see the debug line "awake" onscreen)

I have no idea where my code is (ie where the code is at!)....any ideas how to debug this one?

I'd appreciate a bit of input as I'm worn out!!!

HankMcSpank
- 9th October 2011, 23:30
Hmm, it seems I'm a danger to myself - knowing full well that the next post on this thread would be along the lines of "Hank, post your code up"...i stripped my humumgous bloaty code back to something that could would be easy on the eye ....and you know what comes next....yep, the stripped back code worked 100% of the time!

So it transpires (to me at least) that I apparently can't use Gosubs whilst in DT's interrupt routines (or at least gosubs that go outside the DT interrupt routine) ....or maybe I should rephrase that - I can use Gosubs in DT interrupts, but I get very erratic results!

What I learned today....

1. Probably best not to use Gosubs when in a DT interrupt routine.

2. If you do...everything will compile...and 80% of the time it'll work - it's that pesky 20% that's the issue (& that lost me a whole day trying to debug!)

Now I know all you old hands, muttering "tsk.....n00bs" - but hey, at least I owned up!

cncmachineguy
- 10th October 2011, 00:12
Hank, while I am no old hand, may I remind you there are things we can do- but shouldn't. Like bungee jump or sir jump. I guess this also includes gosubs. Btw, for he benefit of those reading, it's not limited to gosubing from DT_int, it's any interrupt.

Thanks for sharing Hank, we all learn from others mishaps.

HankMcSpank
- 10th October 2011, 01:37
Thanks bert :-)

Ok, I've removed all the gosubs from the interrupt routine, but I'm still getting erratic results...I kinda know what's not causing my PIC to go to sleep , but the workaround is ugly.

I think I'm hitting diffs with nested gosubs. Imagine this scenario (this is just high evel *not* my actual code - just to get my problem across)...



loop1:
if pattern = 2 then goto loop2
IF sleep_flag = 1 THEN GOTO SLEEP_ROUTINE
pause 10
gosub decrease duty
gosub select_LED1
pause 10
gosub increase_duty
goto loop1:
'
loop2:
if pattern = 1 then goto loop1
IF sleep_flag = 1 THEN GOTO SLEEP_ROUTINE
pause 10
gosub decrease duty
gosub select_LED2
pause 10
gosub increase_duty
goto loop2
'
SLEEP_ROUTINE:
debug "PIC off to sleep",13,10
pause 200
@sleep

' program continues here afteran IOC interrupt....
pause 100
debug "PIC awake",13,10

IOC_Int:
@ INT_DISABLE IOC_INT

if sleep_flag = 1 then ' if we wake from asleep, this flag will be set still need to clear it & retun to the main program
sleep_flag = 0
goto INTERRUPT_END
endif

LOOP3:
IF SW1 = 0 THEN
COUNT3 = COUNT3+1
IF COUNT3 >300 THEN 'if Sw1 held for 300mS then set sleep_flag
SLEEP_FLAG =1
goto INTERRUPT_END
ENDIF
pause 1
GOTO LOOP3
ENDIF

if pattern <2 then pattern=pattern+1 'cycle between pattern1 & pattern 2
else
pattern=1
endif

INTERRUPT_END:
COUNT3 =0
while sw1=0
wend
PAUSE 180
IOCAF = 0 'CLEAR THE INTERRUPT FLAG
@ INT_ENABLE IOC_INT
'**************
@ INT_RETURN


It seems the interrupt routine (or program!) doesn't like the highlighted Gosubs in the loop1 & loop2 - if I remove the gosubs & instead locate the actual code contents of the gosubs in each loop - then everything is dandy (i.e. the PIC always goes to sleep & awakes fine) , but if I have gosubs in those two main loops - it looks like the interrupt routine (or some other aspect of my program) doesn't return to the main two loops & then trap the sleep_flag being hit! (the problem here is that by not using gosubs I run out of program space *very* quickly!)

What am I missing here?

HenrikOlsson
- 10th October 2011, 07:10
Hi,
First, I don't understand why you shouldn't (can't) be able to use GOSUB inside or outside of a DT-INTS ISR as long as you RETURN (as you should with ANY GOSUB), anyone care to elaborate on the reason you say you should never do that? Yes, the stack is limited, so you need to makes sure it doesn't overflow if you happen to get an interrupt when you're already into x nested GOSUBS but as far as I can see it should work.

Hank, I'm not syaing I have a solution for you but is seems to me that your program can "fall thru" into the ISR by itself. It wakes up, DT-Ints trips and jumps to the ISR, the ISR runs and the then it returns to where it woke up, which is right before the ISR so the ISR runs again. It hits the @INT_RETURN (by the way, there seems to be a missing underscore in your code?) and it returns to "somewhere". I think you need a Goto Loop1 or whatever right after the DEBUG satement - but I just had a quick look at it so I may be missing something.

/Henrik.

mackrackit
- 10th October 2011, 07:20
Golden rule for interrupts.
Once in get out as quick as possible.
My guess is GOSUB a time or two will violate the golden rule.

Yes, seeing the whole code could help :friendly_wink:

HankMcSpank
- 10th October 2011, 09:35
Golden rule for interrupts.
Once in get out as quick as possible.
My guess is GOSUB a time or two will violate the golden rule.

Yes, seeing the whole code could help :friendly_wink:

I no longer have Gosubs in my interrupt - I removed them.

The problem seems to be the Gosub in the main body of code - when I leave them in, the IOC interrupt routine or my program hangs once in every 8-10 switch presses.
(not sure which yet...when it hangs, the last debug line I see is that from inside in the interrupt routine!)

I'm presently trimming my bloaty program right down (most of it is just visual 'white noise' lol!)...once i've slimmed it down but can still replicate the problem I'm experiencing, then I'll post up the code....at least then you'll have a chance of picking through it!

Henrik - re the missing underscore - that was just a rough high level example of my approach - not my code (& it was *very* late UK time!)

HenrikOlsson
- 10th October 2011, 16:57
Hank,
Yes, that would be nice, please post the with which you are actually having problems... ;-)
But if it's like the code you DID post I still think though that there's a missing Goto Main or Goto Loop1 or whatever as per my previous post.

And, regarding the GOSUBs, there's really nothing preventing you from having a PAUSE 10000 in the ISR, it'll work. That "golden rule" is there to allow any software timings etc in the main loop to stay as accurate as possible. I still don't understand why using a GOSUB in the ISR would cause problem but that discussion is moot since that, for sure, is no longer the cause of the problem in this case.

/Henrik.

Acetronics2
- 10th October 2011, 18:11
Hi, Hank

as far as I can understand what you try to do ... ( :panda: ) I do not see any GIE bit cancelling before entering sleep ... nor the traditionnal "@NOP" placed right after the " @Sleep " ...

Regards

Alain

HankMcSpank
- 11th October 2011, 00:50
Well I think I'm finally there - the solution?

A combination of things....

the main one being a very bouncy tactile switch (China's litle way of making me lose two days!) - I was using a 100nf cap across it, but that wasn't sufficient - in the end it took a 1uf to stop whacky results. (I've a theory that when the interrupt routine was exiting with IOC interrupts then being ren-eabled - every now & then the switch would still be bouncing, which would cause unanticipated results)

poor coding - no surprises there (& which is why I'm reticent to post my code from the outset!)

A few more splatterings of wend (to wait for the switch to be released - particularly important when you're interrupting on change!)

I think the gosubs I thought was causing me an issue *might* be a misnomer - but for now, I'm leaving them out!

I'm still not 100% confident - but hey, you can only press a switch so many times to test, restest & restest again! (so for now I'm calling it fixed and scurrying out the side door!)

mackrackit
- 11th October 2011, 07:01
poor coding - no surprises there (& which is why I'm reticent to post my code from the outset!)
Poor coding has never stopped me from posting code :drunk: