PDA

View Full Version : Interrupts in Assembler



ozarkshermit
- 28th April 2010, 20:05
I'm trying to understand saving W in various sized PICS (more or less code space). See page 187 of the PBP manual.

Let's say I have a 16F870 - - the first two examples would apply there

Let's say I have a 16F876A - - then all four examples would apply.

Must all four saves then be used ?

Now see page 188

the example shows :

myint movwf wsave ; <= 2K only

It does not seem to require wsave Var Byte $a0 System

I am probably not doing a very good job explaning my question - -
How many "wsaves" must be used , and what about when exiting the interrupt?
Only one swapf wsave,W is used.

Now, if more than one wsave is used, what swapf needs to be used?
Is the W register saved in all the variables, wsave, wsave1, wsave2, wsave3, but only restored using wsave?
The answer is probably simple, but I cannot get my hands around it.

YES, I KNOW, I should simply use DT's instant interrupts and not be concerned about it - - I just want to understand this.
I'm familar using interrupts in pure assembly, but am totally confused here. I've searched (and read through DT's code as well, but have not found an answer.)

Any explination would be greatly appreciated.

Ken

Darrel Taylor
- 29th April 2010, 03:47
Use of DT_INTS is not mandatory.
But understanding how interrupts work will make you appreciate them more when you do use them.
Hopefully this will help. :)
---------------------------------

When you get an interrupt, the processor could be in any bank, it depends on what it's doing when the interrupt happens.

The W and STATUS register must be saved before anything else is done, because doing anything else will change the w or STATUS register.
So the W reg has to be saved in whatever bank is currently selected.
And each bank (that has GP RAM) must have a location to save W (wsave1-3).

The addresses of the wsave vars are chosen to be in the exact same place in each bank (shown in red).
So that no matter which bank is selected, wsave points to the correct location.

http://www.pbpgroup.com/files/wsave.GIF

When the registers are being restored, the STATUS register is always restored before the W register.
And since STATUS controls the BANK, it's always left pointing to the same bank it was in before W was saved to begin with and always restores the correct wsave?.

Many 16F's also have "Access RAM", usually at address $70, but some are at a different address.
Access RAM is common between all the banks. If you assign wsave to Access RAM then you don't need wsave1-3.
If the chip has Access RAM, it's best to use that for wsave.

If the PIC has more than 2K of program space, then the flash memory is divided into "Pages".
Since the interrupt handler in your PBP program could end up in any Page, PBP must set PCLATH to the correct page before doing a GOTO to the handler.

As before, doing anything else before saving the W register will change the W register. So PBP has to do the context saving before it can jump to your handler.
That's why you only need to save context if the chip has 2k or less.

If the chip has more than 2K and you try to save context again ... you'll be saving registers that have already been changed, and PBP will crash when the wrong thing gets restored.

In either instance, you always have to restore context.
Whether it was saved by you, or by PBP.

HTH,

ozarkshermit
- 29th April 2010, 12:48
Thank you Darrel.

As usual, you are the man with the gracious and complete answer.

I understood the need for saving / restoring the various registers when entering / exiting an interrupt, but was totally confused about the various locations.

I've copied your answer and pasted it in my PBP tips folder.

Thanks again

Ken

aberco
- 22nd October 2010, 18:45
Thanks for this nice wrap-up of interrupt handling. I think I may have a related problem using DT_INTS18: In my main program I use INT0, TMR1, and USBINT, but as I was adding function and the code grew INT0 and then TMR1 stopped working. The interrupt is called but I think the handler is not running properly (or as you said, does crash when it has to go back to the main program).

As far as I understand, Page locations in RAM should be dealt within DT_INTS, but should the program reside in specific page of the code memory in order for everything to work?

I remember seeing a piece of code to trigger an error if interrupt handler is not located in the appropriate memory bank but cannot find it back... could that be useful for debug?

Darrel Taylor
- 22nd October 2010, 18:55
The post above is refering to 14-bit cores (12F/16F).
18F's are completely different. There are no "Pages" in program memory.

Make sure you have the handler's "Type" set to "PBP" for anything you've written.

aberco
- 26th October 2010, 21:59
I did use the PBP type for each interrupt. The USB interrupt is working fine, the INT0 is working only once and the TMR1 int does not work anymore. It started to malfunction after adding more code that is unrelated to the interrupt function. Even if I bypass everything using a GOTO to enter directly in the operating mode that use the timer interrupt it does not work (the idle loop is running but the interrupt is never triggered).

I'm a bit clueless on this :(

aberco
- 26th October 2010, 23:51
Now that is impressive... I've been on this for a week, and I don't know how I managed to remove the "blinking led" line that goes with my interrupt code!!! no wonder why it was not blinking...

Well everything does work perfectly now, TMR1 and also INT0 (fixed a little glitch on slope detection so it can work as expected).

Your interrupt code is doing wonders, I really enjoy using it :)

Darrel Taylor
- 27th October 2010, 00:27
http://www.pbpgroup.com/files/ROFL.gif

Whew, had me worried there for a bit.
Glad you got it working.