PDA

View Full Version : Returning from Int on PortB change



sheryl
- 10th December 2008, 19:51
Hello.
My PBP ISR works great in PBP...but unfortunately, I have to conver it to asm. The code interrupts on a change on Portb. There are no other interrupts enabled. After the ISR, the code has to go to a new location and NOT RESUME to where it was.

By using the compiler manual or DT_INTS code (thanks DT), I think I might be able to piece together some of the asm code, but I don't know how to "retfie" to a different location. At the end of the ISR, the code needs to go to the "top" (RESUME top_label). How do I do that in ASM? Any suggestions are greatly appreciated!

disable
inthand:
tempb4=portb
intcon.0=0 ;reset RBIF
;@@@@@@@@@@@@@@@
;do some things
;like wait for portc=0
;@@@@@@@@@@@@@@@
tempb4=portb
intcon.0=0 ;reset RBIF
resume top_label ; go to new location - do not "return" to old place in code
enable

Sheryl

Darrel Taylor
- 11th December 2008, 02:02
Hi sheryl,

It depends on if you're using a 16F or an 18F.
For 16F's, the stack is circular, so you can just jump to the beginning of the program after resetting GIE. Any previous gosubs or interrupts will be forgotten, or more like Ignored.

PBP defines the "beginning" of the program as INIT, which makes it easy to do this, instead of retfie...

ASM
bsf INTCON, GIE ; re-enable interrupts
clrf PCLATH ; codepage 0
goto INIT ; start from the top
ENDASM


For 18F's, the stack is NOT circular, so you have to POP everthing off the stack before jumping to INIT. Otherwise, the stack will eventually overflow.
Or you could just reset everything.
@ reset (not the prefered method ... depending again?).

If you're using an 18F? I'll come up with some code.
<br>

Charles Linquis
- 11th December 2008, 02:09
Darrel,

I'm using an 18F, and I have come across several instances where such code would be useful. Please...

Bruce
- 11th December 2008, 16:52
Check out this app note: http://ww1.microchip.com/downloads/en/AppNotes/00818a.pdf
You can do some really cool stuff on the 18F.

sheryl
- 11th December 2008, 17:34
Thank you.
I am using the 18f4620....so...here's the followup ..how do I pop everything off the stack? since most of the code is in PBP, how do i know how deep the stack is?

Sincerely,
Sheryl

Darrel Taylor
- 11th December 2008, 18:09
Charles,

I'm pretty sure you're using DT_INTS with the 18F, so here's a macro that should do the same thing that RESUME LABEL does with ON Interrupt and 16F's.

I DO NOT recommend actually using it. It's just BAD programming practice. And it will cause more problems than it will alleviate. However, being the capable programmer that you are, you may be able to make some use of it.

It can be used in place of INT_RETURN.
With the format ... @ INT_RESUME _Label, IntsEnabled


@ INT_RESUME _Main, 1

The line above would "resume" at the Main: label, with interrupts enabled.
Changing IntsEnabled to 0, will leave the interrupts DISABLED. In case they need to be setup again from the new "Starting point".

All previous GOSUB's and Interrupts will be discarded, and the command that was interrupted will NOT be completed. Stopping a PBP command in the middle can cause unexpected results. In particular, the I2C and LCD commands, may be left in the incorrect state. Clearing the Flags register, will correct those two, but other problems can arise.

The label that is resumed to, MUST be a GOTO Loop, just like the Main loop. It CAN NOT be a subroutine with a RETURN at the end.

And since it is exiting the interrupt handler without the assistance of DT_INTS, you have to make sure the IF (interrupt flag) bits are cleared before resuming.

18F's ONLY

ASM
#define Reg(PBPreg, PBPbit) PBPreg ; Returns the register for a PBP BIT var

INT_RESUME macro Label, IntsEnabled
local PopLoop

PopLoop ; Remove everything from the stack
pop
movf STKPTR, W
bnz PopLoop

ifdef ReEnterHPused ; let Instant Interrupts know we are
if (ReEnterHPused == 1) ; done with the System variables
banksel Reg(_VarsSaved_H) ; that were saved during the
bcf _VarsSaved_H ; High Priority interrupt.
endif
endif
ifdef ReEnterLPused ; And, we're done with the variables
if (ReEnterLPused == 1) ; saved on a Low Priority INT.
banksel Reg(_VarsSaved_L)
bcf _VarsSaved_L
endif
endif

ifdef USE_LOWPRIORITY ; If Low Priority INTs are being used,
if (USE_LOWPRIORITY == 1)
if (IntsEnabled == 1) ; and the user specified IntsEnabled
bsf INTCON, GIEL ; then enable Low Priority Interrupts
else ; if not,
bcf INTCON, GIEL ; disable LP INTs
endif
endif
endif

if (IntsEnabled == 1) ; If the user specified IntsEnabled,
bsf INTCON, GIEH ; enable High Priority Interrupts
else ; if not,
bcf INTCON, GIEH ; disable HP INTs
endif

clrf BSR ; reset to Bank0
goto Label ; resume from the users Label
endm
ENDASM


HTH,