PDA

View Full Version : PIC with Automatic Context Saving



Dick Ivers
- 9th March 2011, 20:56
As a matter of curiosity I recently tested a 16F1828 device. This is one of the newer PICs having interrupt capability with automatic context saving. In this case, the new device replaced a 16F690, a 20 pin chip with the same pinout. The original PBP program (too long to include here) incorporates a DT_INT utility to service a change on porta.1 interrupt. The actual functioning circuit works well and as expected.

With the 16F1828 software I removed all the DT_INT stuff, and rewrote the program in PBP to include a DEFINE INTHAND pointing to a short ASM handler routine. Didn't do much else ... the new device took care of context saving. With this in place the circuit again worked well. The difference was that the new program complied with 625 fewer program words. This may be of interest in situations where you are tight on code space.

Ioannis
- 18th March 2011, 07:38
Why not post he new code for members to have it as a reference?

Ioannis

Acetronics2
- 18th March 2011, 09:15
Hi, Ioannis

That looks like simply using asm interrupts as stated in the 9.3 Chapter of the Manual ... :rolleyes:

as it is a 4k memory device ... PBP will include the context saving stubb by itself ... like for the elder devices ...

nothing exceptionnal here ... :rolleyes:

Alain

Dick Ivers
- 18th March 2011, 17:46
delete --------

Bruce
- 18th March 2011, 21:23
Does PBP automatically insert a context saving stub for enhanced 14-bit core types, and does chapter 9.3 apply to these..:eek:

I thought the post was pretty helpful, but do agree it would be more helpful to show how he structured his .asm int handler.

Acetronics2
- 19th March 2011, 11:57
Hi, Bruce

I had read the relevant chapter of the Databook ... ;)





8.5 Automatic Context Saving
Upon entering an interrupt, the return PC address is
saved on the stack. Additionally, the following registers
are automatically saved in the Shadow registers:
• W register
• STATUS register (except for TO and PD)
• BSR register
• FSR registers
• PCLATH register
Upon exiting the Interrupt Service Routine, these registers
are automatically restored. Any modifications to
these registers during the ISR will be lost. If modifications
to any of these registers are desired, the corresponding
Shadow register should be modified and the
value will be restored when exiting the ISR. The
Shadow registers are available in Bank 31 and are
readable and writable. Depending on the user’s application,
other registers may also need to be saved



Was not so clear from me ... I do agree !!!

just meant : it is like for other 4K devices, No need to care about asm Context saving ...

But the really interesting point is, RESTORING is done by itself ... a contrario than elder devices ... ;)

Ok ... no need to reserve RAM nor ...

... :)

Alain

Dick Ivers
- 19th March 2011, 12:10
'************************************************* ***************
'* Name : Test RDT Interrupt for one-time use
'* Author : Dick Ivers
'* Notice : Copyright (c) 2011
'* : All Rights Reserved
'* Date : 1/30/2011
'* Version : 1.0
'* Notes : 112 words
'* Device : 16F1828
'************************************************* ***************
'set configurat1on
@ __config _CONFIG1, _FOSC_HS & _MCLRE_ON & _CLKOUTEN_OFF & _WDTE_ON
@ __config _CONFIG2, _PLLEN_OFF & _LVP_OFF

'set registers
ANSELA = 0 'all digital inputs
ANSELB = 0 'all digital inputs
ANSELC = 0 'all digital inputs
OPTION_REG.7 = 0 'global pullups enabled
CM1CON0.7 = 0 'comparator1 off
CM2CON0.7 = 0 'comparator2 off
TRISA = %110 'set porta pin 0 as output
TRISB = %11111111 'set all portb pins as inputs
TRISC = %11000000 'set portc pins 0,1,2,3,4,5 as output
WPUA = %110 'porta pins 1,2 pullups enabled
WPUB = %11110000 'portb pin pullups enabled

INTCON = %10001000 'global int enabled, IOCI enabled, IOCI flag bit 0 clr
IOCAF.1 = 0 'flag bit for porta int pin 1 cleared
IOCAN = %00000010 'porta pin 1 enabled for negative change


DEFINE OSC 16 '16 Mhz oscillator
DEFINE INTHAND RDT

portc.3 = 1 'turn off beeper

'declare variables
LED VAR PORTC.5
j var byte

LED = 0 'flash red LED for 0.5 sec to check circuit function
pause 500
LED = 1

pause 2000 'delay 2 seconds

Main:
gosub beep 'play beep for 1/8 second
PAUSE 1000 '1 second delay
GOTO Main

ASM
RDT
BCF IOCAF,IOCAF1 ;clear IOCA negative change interrupt flag
BCF INTCON,3 ;disable interrupt on change by clearing INTCON bit 3
BCF PORTC,5 ;turn on led solid
RETFIE ;return to main
ENDASM

beep: for j =1 to 240 'buzzer sound for 1/8 second
portc.3 = 0 'buzzer on
pauseus 180 '2.73 khz half period
portc.3 = 1 'buzzer off
pauseus 180 '2.73 khz half period
next
return

halt: END

HankMcSpank
- 24th August 2011, 20:17
Forgive me for digging up an old thread, but this really interests me.

I've also a stash of 16f1828s and the auto context register saving intrigues/appeals to me ... my ultimate goal is getting in/out of a timer based interrupt as fast as possible - ie miniscule overhead (the interrupt rate will be happening at about 50khz)....the thought of learning assembly is quite a hurdle, but this seems like this could be a way of easing myself into it...ie my main code can be picbasic with the interrupt being a little bit of assembly.

But I'm lost!

How do I set up an interupt, so that when say timer1 overflows it jumps to an assembly type interrupt in my code (all my interrupts to date have been using DT's most excellent interupt routine, but if I'm understanding correctly that way adds some overhead which could be avoided with these new type PICs?)...in the example above it wasn't clear to me how that ASM part was called/found by the PIC/program.

mister_e
- 24th August 2011, 20:24
You define your interrupt type on the top, you may have many interrupt source, but once in the ISR you need to test them.

Once an interrupt is fired, it will jump the the ISR label specified by the DEFINE INTHAND line. Here RDT

HankMcSpank
- 24th August 2011, 20:29
Thanks, funny now you mention it, it's there I just didn't leap out at me...


DEFINE INTHAND RDT


but there's no colon after the nominated handle/label at the top of the subroutine?



ASM
RDT
BCF IOCAF,IOCAF1 ;clear IOCA negative change interrupt flag
BCF INTCON,3 ;disable interrupt on change by clearing INTCON bit 3
BCF PORTC,5 ;turn on led solid
RETFIE ;return to main
ENDASM


also, I'm figuring it must be necessary to have that 'ASM' entered immediately above?

thanks again looking forward to having a a dabble :)

Darrel Taylor
- 24th August 2011, 20:33
DT_INTS-14 uses the auto context saving in the 16F1's.

Since you already know how to use them, try them first.
There are still a few instruction cycles that can be saved by doing it manually, but you probably won't need to.
Just use an ASM type INT_Handler. They do not have to save PBP system variables.

50Khz should be no problem.

mister_e
- 24th August 2011, 20:38
never mind, Thanks Darrel

HankMcSpank
- 24th August 2011, 20:46
Thanks Darrel.

my fixation is that I want to generate sine waves to very high resolution (DDS) - and all the stuff that abounds on the net seems to be assembly....they all typically generate a fixed timebase by way of an interupt & then in the interupt add a number to an accumulator, do a look up from the result then get out asap. I agree that 50khz is not that onerous...but this is just the first step to total world domination (Mwuahahahaha.) & the interrupt rate will inevitably crank up.

Towards helping me understand this area, (actually I'm just curious) when you say there are still a few cycles that can be saved by going the way I asked about ....do you have a ballpark figure for the auto context saving and your (still excellent!) auto context embracing routine?

Darrel Taylor
- 24th August 2011, 23:20
Well, if you're only going to be using 1 interupt source, it will be better without DT_INTS since you don't need to test for which interrupt was triggered.

I just did a quick test with an incrementing variable and a SIN lookup with an 1827 running at 32Mhz.

With DT_INTS ... max = 140Khz
Without ... max = 220Khz

With 2 interrupt sources the difference is not as pronounced since it has to check which one triggered and jump over the handler that wasn't. DT_INTS always does that.

The PWM will have to be running much faster than the interrupts or it will be changing dutycycles before a single cycle has completed. Could be trickey.

HankMcSpank
- 24th August 2011, 23:32
Cool (& thanks) ....as it goes I will need two interrupts, one to generate the timebase, plus one UART interrupt, so I can feed in required frequency changes externally.

I will really only need up to 18khz(ish), so your quoted 140khz max is well above what I need....so I'll stick with DT_INTS! :)

As an aside, for anyone who holds an interest in DDS for PIC, the best I've found to date is this chap's site....

http://www.g4jnt.com/pics.htm (specifically, this http://www.g4jnt.com/PIC_DDS.pdf and his accompanying zip file http://www.g4jnt.com/PIC_DDS.zip which has his assembly source code for a 16f628 DDS ....it'll probably a while before I get to try my DDS exploits, becuase I'm still trying to wrap my head around how he made a pseudo 32 bit accumulator on a 16f628 by lobbing together four 8 bit registers & then making them dance)

I can feel a serious amount of plagiarism coming on though!

Dick Ivers
- 25th August 2011, 13:32
Hank, Please note from the first post that an advantage of interrupts without DT_INTS is a major saving in code space. My sample program compiled with 625 fewer program words when using the 16F1828 vs. a 16F690.

HankMcSpank
- 25th August 2011, 14:09
Hi Dick....thanks point noted. As it goes, while saving space is always welcome the 16f1828 has a reasonable amount - plus, my intended program is going to be very small.

While I've got you ear....do I just use the syntax exactly as per your example, ie.....



ASM
RDT
BCF IOCAF,IOCAF1 ;clear IOCA negative change interrupt flag
BCF INTCON,3 ;disable interrupt on change by clearing INTCON bit 3
BCF PORTC,5 ;turn on led solid
RETFIE ;return to main
ENDASM



ie headed up by an ASM label with no colon, then on the following line the label as defined by the DEFINE INTHAND command?

Any idea how two interrupts are catered for? (yes, I know DTS_INT handles multiple interrupts already, but just wondering how to do it manually)

Darrel Taylor
- 25th August 2011, 14:18
Hank, Please note from the first post that an advantage of interrupts without DT_INTS is a major saving in code space. My sample program compiled with 625 fewer program words when using the 16F1828 vs. a 16F690.

The test program I ran in post #14 compiled to 133 words without DT-INTS, and 153 words with DT_INTS.
I don't think the code savings was due to not using DT_INTS.

That's using an ASM type INT_Handler. If using a PBP type handler, it goes up to 285 words.
But that's not a good comparison, because if you want to do PBP type interrupts without DT_INTS the program will get huge from all the checks placed between every line of code.

Bruce
- 25th August 2011, 14:27
FYI: BCF IOCAF,IOCAF1 in your int handler is probably not doing what you think. IOCAF is in bank 7 on the 16F1828, and PBP resets the bank to 1 when you use ASM. It's up to you to make sure you're in the correct register bank in your .asm routines.

Dick Ivers
- 25th August 2011, 17:18
Bruce, Thanks for the info re. IOCAF bank switching in the handler. Actually, I don't think I need that line of code anyway. As stated in the header, the test program is for one-time use only. The circuit works correctly as is.

Hank, With two interrupt sources you would first go to the handler identified after DEFINE INTHAND. Once there, set up a test to determine which interrupt occurred by polling the interrupt flags. Then carry out the appropriate interrupt action. I have never done this, so maybe Bruce or Darrel could help with a better explanation.

mister_e
- 25th August 2011, 18:08
Hint: BTFSS or BTFSC, or BIT?GOTO

;************************************************* ***************
;* BIT?GOTO : Macro - Bit test and Long Goto *
;* *
;* Input : Cstate = constant desired state for goto *
;* Regin = register *
;* Bitin = bit *
;* Label *
;* Output : None *
;* *
;* Notes : Preserves C, Z, handles page boundaries, resets bank.*
;************************************************* ***************

Dick Ivers
- 29th August 2011, 16:16
16F1828 now working with two interrupt sources.
BTFSS works well as a source selection tool ... thanks Steve.
Automatic context saving feature of the chip working.
End of story.