code

Jon Wilder

Joined Oct 25, 2011
23
RETURN is used for subroutines. RETFIE is used to return from interrupts (RETurn From IntErrupt).

When an interrupt source on a PIC generates an interrupt, the GIE bit in INTCON gets cleared by hardware, which disables all unmasked interrupts. The instruction counter then jumps to the interrupt vector address in program ROM and executes the interrupt handler code that resides there.

Upon executing an RETFIE instruction at the end of the interrupt handler, the GIE bit gets set, which re-enables all unmasked interrupts. If you use RETURN instead of RETFIE, it will still return from the interrupt, but interrupts will not get re-enabled.
 

MaxHeadRoom

Joined Jul 18, 2013
28,698
OK I know it is a legacy thread,
Although many decry the use of using return instead of retfie (RetFromInterupt&Enable) in an interrupt but I was reading over the Picmicro AN566 and the program for multiple IOC routines, and they use it in a couple of places, the one thing I can see is that the stored registers at the start of the ISR are not restored.
Would it be more prudent to turn off the GIE immediately on return, if this is needed? Or would the INT creep in?
Max..
 

JohnInTX

Joined Jun 26, 2012
4,787
GIE is cleared automatically when the interrupt occurs to prevent multiple interrupts on non-reentrant context saving code. You can use calls and returns within the interrupt routine but have to use RETFIE at the end to make re-enabling interrupts and the return an atomic operation. If you enabled interrupts before the return, you risk problems with the context save/restore as well as using another stack level. You could return from interrupt without re-enabling if you wanted that but it’s not common. In 16f1xxx, the auto context save must be restored using RETFIE.

Haven’t seen the A/N, napping with granddaughter but can take a look later.

EDIT: looked at it. They’re looking to see which pin caused the interrupt by testing flag bits and CALLing inline the individual handlers. CALLs are used so that the whole chain of events is processed for each IOC. Simple RETURNS are used for these because the overall interrupt service is not complete. At the end of testing all the bits, context is restored and RETFIE is used to exit the service routine in the normal manner.

EDIT2: the code in Example 4 has a serious bug. At CK_RB4, if that flag is it will GOTO RB4_CHG and flow into the exit routine using RETFIE. If not set, it erroneously flows into RB7_CHG where it will RETURN to the interrupted code without re-enabling GIE or restoring context.

There are other problems inherent with the approach shown as well if you’re interested.
 
Last edited:

MaxHeadRoom

Joined Jul 18, 2013
28,698
EDIT2: the code in Example 4 has a serious bug. At CK_RB4, if that flag is it will GOTO RB4_CHG and flow into the exit routine using RETFIE. If not set, it erroneously flows into RB7_CHG where it will RETURN to the interrupted code without re-enabling GIE or restoring context.
That's what I was referring to in my comment, i.e. the resulting effect of a normal Return used in a ISR ?
Max.
 

JohnInTX

Joined Jun 26, 2012
4,787
That's what I was referring to in my comment, i.e. the resulting effect of a normal Return used in a ISR ?
Max.
I guess the simple answer is ignore that example. It’s a bug and shouldn’t be done like that. The interrupt uses exactly the same mechanism as any subroutine except the CALL instruction is jammed in by the hardware with a fixed target address (the interrupt vector at (0004h). When invoked, the return address is pushed on the stack and the PC is set to 0004h where you have to have the service routine. Within the service you can have calls and returns as you would with any other subroutine. When you return from the ‘hardware call’ at the end of the interrupt service, it works the same as any other subroutine return I.e. pops the return address off the stack and into the program counter to resume execution there.

The only thing that sets the interrupt apart is that when the hardware interrupt ‘calls’ the service routine, it also disables further interrupts. You use RETFIE to return from t;he interrupt call and re-enable interrupts. If you just use RETURN at tne end of the service routine, the code will execute exactly the same but with interrupts still disabled - preventing further interrupts until they are manually re-enabled. That won’t work since you don’t know where in the code an interrupt will occur so you can’t know where to re-enable them - hence the need for RETFIE.

Note that there is nothing special about the stack operation between interrupts and normal calls. Interrupt and calls push the stack and return and retfie pop the stack. The only difference is the additional manipulation of GIE by the hardware interrupt and RETFIE.

Hope that answers your question. If not, ask away.
 
Last edited:

MaxHeadRoom

Joined Jul 18, 2013
28,698
Thanks, I am implementing a couple of IOC inputs on a 12F628 , they are each a different format one is a momentary P.B. switch, the other a ON/OFF 2 position.
I found one of the Gooligum tutorials deals with this so I should be able to work it out OK! Hopefully :oops:
Max.
 

John P

Joined Oct 14, 2008
2,026
...
Note that there is nothing special about the stack operation between interrupts and normal calls. Interrupt and calls push the stack and return and retfie pop the stack. The only difference is the additional manipulation of GIE by the hardware interrupt and RETFIE.
That's processor dependent. The "enhanced midrange" PIC processors automatically save various registers when an interrupt call happens, where a function call wouldn't save anything, and then RETFIE restores them, and again, a RETURN wouldn't do that. The items saved are:
• W register
• STATUS register (except for TO and PD)
• BSR register
• FSR registers
• PCLATH register

They go to "shadow registers", not to the stack. The shadow registers are like any other registers, accessible via software if you ever wanted to do it, and the data sheet says "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."
 

JohnInTX

Joined Jun 26, 2012
4,787
One thing I am not completely clear on is all the IOC ISR routines open with:
move GPIO, W ; Clear mismatch condition.
??
Max.
IOC works by keeping a copy of the last PORTB value read in an internal register (D flip flops). The N-bit wide output of that register (previous port value) is compared to the current port value on each Q1 cycle (using a digital comparator). When pin(s) on the input of the port change the digital comparator outputs a flag (the mis-match flag) which is latched. Setting mis-match flag also sets the RBIF flip-flop. Note that the mis-match flag is driven by latched data and will be true even if the raw pins return to the original value - or change to something different. The only way to clear the mis-match condition is to read the PORT again. This causes the port input latch AND the compare latch to once again have the same value (the new port pin values) and that clears the mis-match. Only then can you clear RBIF. If you clear RBIF without reading the port, it will be immediately set again. Fig 5-12 in the datasheet shows the compare mechanism and extra latch for RB4. It's the same for the other IOC pins.

So the proper procedure is to read the port to clear the mismatch, then clear RBIF. The comparison latches will once again agree with the current pin values and all is hunky-dory.

Or IS it?

IOC can be problematic when used like you are trying. Note that between getting the mis-match and RBIF interrupt processed, anything can happen on the port including returning the pins to the original value so you can miss things. If you use IOC, you can't poll the port for other uses for fear of clearing mis-matches that you haven't processed. The note at the end of 5.2 and the following paragraph kind of tell you what Microchip thinks the limitations are.


Curious as to why you are using IOC for switch sensing. A far better way IMHO is to set up a periodic timer interrupt, poll and debounce the switches and post results. As for IOC, the only thing I'm comfortable using it for is wake on keypress and quadrature encoder input. Just my .02
 

JohnInTX

Joined Jun 26, 2012
4,787
That's processor dependent. The "enhanced midrange" PIC processors automatically save various registers when an interrupt call happens, where a function call wouldn't save anything, and then RETFIE restores them, and again, a RETURN wouldn't do that. The items saved are:
• W register
• STATUS register (except for TO and PD)
• BSR register
• FSR registers
• PCLATH register

They go to "shadow registers", not to the stack. The shadow registers are like any other registers, accessible via software if you ever wanted to do it, and the data sheet says "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."
I did mention that in #7 but not to that level of detail, thanks.
 

MaxHeadRoom

Joined Jul 18, 2013
28,698
I have been using it successfully so far with just the momentary P.B. now adding a ON/OFF maintained with interrupt.
The PGM includes a analogue in and PWM out.
12F683 6 I/O only.
Max.
 

jpanhalt

Joined Jan 18, 2008
11,087
MaxHeadRoom said:
One thing I am not completely clear on is all the IOC ISR routines open with:
move GPIO, W ; Clear mismatch condition.
??
Max.
I saw that comment this morning, and it didn't register (no pun) with me what you meant. I think that instruction, assuming you mean MOVF, would be a horrible first instruction for saving context. MOVF GPIO,W can affect STATUS,2. The datasheet recommends:
Code:
MOVWF W_TEMP ;Copy W to TEMP register
SWAPF STATUS,W ;Swap status to be saved into W
;Swaps are used because they do not affect the status bits
MOVWF STATUS_TEMP ;Save status to bank zero STATUS_TEMP register
SWAPF and MOVWF do not affect STATUS bits. MOVWF does not need a destination.
 

MaxHeadRoom

Joined Jul 18, 2013
28,698
Sorry I did miss-type.
The AN566 shows movf PORTB, F ; read PORTB to itself to end missmatch condition.
The Gooligum example = movf GPIO, W ;read GPIO to clear any IOC mismatch condition.
The AN566 is for the older 16cxxx family.
The Gooligum is for the 12F683 etc.
Max.
 

jpanhalt

Joined Jan 18, 2008
11,087
Googligum is still wrong for the first step in the ISR, unless you don't care about the zero bit of Status or WREG. I usually do. Does Googligum give any example of an IOC mismatch and GPIO? If it is due to some very rapidly changing input that has changed AFTER the interrupt or during the latency, I don't see how doing that is necessary to do first thing. GIE is disabled. (There is come ancient stuff regarding three (4?) chips of the 16C series where a GIE might get skipped, but that does not apply to the 12F chips.)

Most of the PIC datasheets I have read also point out the possibility of fast input changes changing IF's during the course of the ISR, and so they give a sequence of instructions to test for that.

EDIT: I have found Googligum to be pretty reliable. Is there some chance of misunderstanding? Is it, per chance, referring to enhanced mid-range devices, like the 12F1840?
 
Last edited:

MaxHeadRoom

Joined Jul 18, 2013
28,698
EDIT: I have found Googligum to be pretty reliable. Is there some chance of misunderstanding? Is it, per chance, referring to enhanced mid-range devices, like the 12F1840?
The IC's refered to in Gooligum is the 12F629/12F683
The 16Cxxx was re the Picmicro AN566 app notes.
Max.
 

jpanhalt

Joined Jan 18, 2008
11,087
Hi Max,

The three chips affected by the GIE problem were the 16C71, 16C73, and 16C74. Chips in that series with a suffix are not affected. MCC even points out the problem in its datasheets for the affected chips. I think it is extremely unlikely Googligum was thinking of those chips. Moreover, try to buy one today. I did a few years ago just to test (a non-windowed 16C71), and they were expensive.
 
Top