PDA

View Full Version : Context saving in assembly - 16F72 giving problem



financecatalyst
- 3rd August 2012, 13:54
Hi, I am trying to learn about context saving in assembly language. I have 16F72 with me for which I am trying to write an ISR in assembly. I am having a little trouble in understanding the variable declaration part. What I have written upto now is this:

wsave var byte $40 SYSTEM ' safe for W in all banks
ssave var byte BANK0 SYSTEM ' save STATUS
fsave var byte BANK0 SYSTEM ' save FSR

ISR:
asm
movwf wsave ; Save WREG
swapf STATUS, W
clrf STATUS ; Point to bank 0
movwf ssave ; Save STATUS
movf FSR,w
movf fsave ; save FSR

; my code here

EndInt ; restore the machine state and return from interrupts
movf fsave,w
movwf FSR ; restore FSR
swapf ssave,w
movwf STATUS ; restore Status
swapf wsave,f
swapf wsave,w ; restore WREG
retfie
endasm


The above is an unreliable code which is causing problem in operation of the PIC. The problem is that the the PIC hangs up after sometime.

It is running fine without interrupts so it is surely the interrupts causing the problem. I was reading the datasheet and it says W_Temp should be saved in BANK0 & 1. How do you save the same variable in two banks? I also thought that since $40 location can be addressed from all banks, it was ok to just save W-Temp in that location so it can be accessed by all banks, but surely I am wrong here.

So can someone please explain this concept to me so I can correct the above code as well. Thanks

financecatalyst
- 3rd August 2012, 15:14
Anyone there?

mackrackit
- 3rd August 2012, 16:00
Anyone there?
Nope, no one here.

financecatalyst
- 3rd August 2012, 16:28
:rolleyes: Great!!

Darrel Taylor
- 3rd August 2012, 16:48
Somebody's home, but that doesn't mean the lights are on.

I notice that you aren't saving PCLATH.
It would depend on what's in your ISR whether you need to save it or not, but you didn't include that part.

$40 is fine for the wsave variable in all banks.

Make sure the interrupt flag is cleared before exiting the ISR.

financecatalyst
- 3rd August 2012, 17:18
Thanks Darrel, here is my complete code:

ISR:
asm
movwf wsave ; Save WREG
swapf STATUS, W
clrf STATUS ; Point to bank 0
movwf ssave ; Save STATUS
movf FSR,w
movf fsave ; save FSR

BTFSS INTCON,TMR0IF
GOTO EndInt

bcf INTCON, TMR0IF ; clear the interrupt
incf _i
movlw 3
bcf STATUS,Z
XORWF _i,w
BTFSS STATUS,Z
Goto EndInt

clrf _i

bcf STATUS,Z
MOVLW 0
addwf PORTA,w
BTFSS STATUS,Z
clrf PORTA

BCF STATUS,Z
MOVLW 0
addwf PORTC,w
BTFSS STATUS,Z
clrf PORTC

EndInt ; restore the machine state and return from interrupts
movf fsave,w
movwf FSR ; restore FSR
swapf ssave,w
movwf STATUS ; restore Status
swapf wsave,f
swapf wsave,w ; restore WREG
retfie
endasm

My PIC just hangs. The oscillator pins get weird constant voltage levels, one ground, one at 4.7/4.8 volts. The code is just clearing PORTA/C after certain interval.

I would also take this opportunity to ask you one question which I have heard before as well but never understood completely which is -> WHY should I save PCLATH? The datasheet says
During an interrupt, only the return PC value is saved on the stack. Typically, users may wish to save key registers during an interrupt (i.e, W, STATUS registers)...
and it also provides few lines about context saving.

Darrel Taylor
- 3rd August 2012, 20:30
Good question!

It's one of those things that was in the book since forever and I never questioned it. Just went on using it.
But now that you ask, and I look for the correct answer ... I can't see where it's needed on a chip with 2K or less.

GOTO and CALL statements encode 11 bits of the address into the opcode, and 11 bits covers the full 2K.
There's no reason for it to use the upper 2 bits, and therefore you shouldn't need to save PCLATH.

I'll ask Jeff (he's out of town right now) and see if he had a reason for it.

Since your ISR doesn't use the FSR, you don't need to save/restore it either.

But back to your problem ...
If the oscillator stops running, it sounds like a sleep instruction was executed.
Do you have any SLEEP's in your code.

Or maybe the MCLR pin is being pulled low somehow. Check the voltage on MCLR when the problem happens.

Possibly a brownout condition, check VDD voltage when the problem happens.