|
|
View previous topic :: View next topic |
Author |
Message |
future
Joined: 14 May 2004 Posts: 330
|
Fast interrupt dispatcher |
Posted: Wed Jun 02, 2004 10:36 am |
|
|
Does anyone have an example of low priority and high priority interrupts working together?
My code has a 100uS TIMER0 interrupt and I want a fast EXT and RDA interrupts. EXT is just a VarA=VarB and RDA is a buffer[index++]=rcreg and code to build a linear buffer.
The problem is the lack of knowloedge to write a fast interrupt dispatcher. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed Jun 02, 2004 1:03 pm |
|
|
Which processor and compiler version are you intending to use?
Two problems in v3.188 were promised to be fixed in 3.191, but the problems are not mentioned in the list of changes and I haven't tested any of the newer compiler versions yet.
I can recommend you to read http://www.ccsinfo.com/forum/viewtopic.php?t=19286 |
|
|
Guest
|
|
Posted: Wed Jun 02, 2004 1:13 pm |
|
|
PIC18F452 and 3.187, clock at 40mhz |
|
|
future
Joined: 14 May 2004 Posts: 330
|
|
Posted: Wed Jun 02, 2004 1:21 pm |
|
|
This guest thing should be disabled ;)
The code is already working, but only EXT is a fast interrupt.
I think it is bad to pass through almost 150 instructions just to receive a byte. |
|
|
Gerrit
Joined: 15 Sep 2003 Posts: 58
|
|
Posted: Wed Jun 02, 2004 2:47 pm |
|
|
If you alrady have an 100 us interupt just check for rda buffer and read as nessesery.
If you handle two interupts in fast int you also have to check what int it
was so why no check for char received.
You can handle +- 100 kBit serial stream.
Gerrit |
|
|
future
Joined: 14 May 2004 Posts: 330
|
|
Posted: Wed Jun 02, 2004 3:15 pm |
|
|
A question comes to my mind.
If I set global int and do not enable interrupt for RDA, the receive interrupt flag is set to 1 when a byte is received? |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Wed Jun 02, 2004 3:52 pm |
|
|
V3.187 is a good version for fiddling with the fast interrupts, and I guess you have read the PIC18F452 errata sheets by now?
Implementing one fast interrupt in the CCS compiler is relatively easy as you have already figured out, but implementing multiple fast interrupts requires some tweaking.
This is how I did it:
1) The Status, Wreg and BSR registers are automatically saved in a Fast interrupt, but the other registers you will have to save yourself. This is a good reason for writing your interrupt handler in assembly because a new compiler version might use different registers.... If you do want to mix C and assembly (like I did) then double check your code for using the scratch registers on address 1 to 4. I forgot to save one register and this caused all kind of strange problems.
2) For the first Fast interrupt (int_ext in my example) you have to do nothing, the priority is automatically set by the compiler and the interrupt is cleared on exit. But for the other interrupt you will have to code these two actions yourself, this requires a bit working around the compiler.
Code: |
#define intcon 0xFF2
#define intcon2 0xFF1
// etc
int8 save_fsr0l;
int8 save_fsr0h;
int8 save_scratch3;
void init()
{
// Setup timer2
Setup_Timer_2(T2_DIV_BY_1, EXTSER_BIT_TIME - 1, 1);
IPR1bits.TMR2IP = 1; // Make this a high priority interrupt
// The CCS compiler has no method for
// specifying multiple High Priority interrupts.
// enable_interrupts(INT_TIMER2); // Do not enable, or compiler
// will add a low priority handler
// Setup RS-232 receive pin (Ext0)
ext_int_edge(0, H_TO_L); // Interrupt on fallling edge
enable_interrupts(INT_EXT);
}
#INT_EXT FAST
void fast_isr()
{
// Save registers
#ASM
movff FSR0L, save_fsr0l
movff FSR0H, save_fsr0h
movff 3, save_scratch3 // used by some C-code I'm calling
// Determine which interrupt source is active
btfss intcon,intf ; external interrupt?
goto intovfl ; no, go
bcf intcon,intf ; yes. Clear external interrupt flag
; note: not required, compiler adds code at exit
; Do some more stuff here.
intovfl:
btfss pir1,t2if ; timer overflow?
goto int_exit ; no, go exit
bcf pir1,t2if ; clear timer interrupt
; note: This clear is required, compiler will not do it.
; Do some more stuff here.
int_exit:
// Restore registers
movff save_fsr0l, FSR0L
movff save_fsr0h, FSR0H
movff save_scratch3, 3
#ENDASM
}
|
|
|
|
Ttelmah Guest
|
Re: Fast interrupt dispatcher |
Posted: Thu Jun 03, 2004 2:17 am |
|
|
future wrote: | Does anyone have an example of low priority and high priority interrupts working together?
My code has a 100uS TIMER0 interrupt and I want a fast EXT and RDA interrupts. EXT is just a VarA=VarB and RDA is a buffer[index++]=rcreg and code to build a linear buffer.
The problem is the lack of knowloedge to write a fast interrupt dispatcher. |
As others have said, I'd probably handle the RDA interrupt another way. The 'fastest' response, to INT EXT, would be to just code this using FAST, then simply copy the bytes (which only needs affect the W reg, and the BSR), and use the RETFIE 1 ability to restore these registers. The 'key' problem at each level, is how many registers have to be saved. Using an array in the RDA handler, implies that several of the table pointer registers, and a couple of scratch registers have to be saved. You can look through the assembler listing of each routine you intend to use in each interrupt, and get a list of the registers that are used. You may also consider reducing the interrupt overhead on the low priority interrupt by taking advantage of this information (especially given that your system is going to be spending a large percentage of it's time in the 100uSec timer interrupt). So (for instance), if you know that this is the only low priority interrupt in use, and hence that if the handler is called, this interrupt must have happened, you can remove the code to check which interrupt has occurred, and that the interrupt is enabled. In answer to another question you have raised, yes the RDA interrupt flag is set even if the interrupt is disabled. So if you code a int_global handler to only save the registers needed by the RDA, and timer tick routines, then do the timer handling (given that this is the only low priority interrupt), clear the timer interrupt flag, check if RDA is set, save the data, and clear this flag if so, restore the registers, and exit, I'd expect to be able to reduce the overhead by perhaps 30-40% on the low priority interrupt, giving a fairly effective result.
I have posted in the past example 'int_global' code for this type of approach.
Big caveat, are you sure that you have late enough chips, that you are not going to be affected by the asynchronous fast interrupt errata?...
Best Wishes |
|
|
future
Joined: 14 May 2004 Posts: 330
|
|
Posted: Thu Jun 03, 2004 4:15 am |
|
|
This is a good question, the chip is a PIC18F452-I/P 0412262. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|