|
|
View previous topic :: View next topic |
Author |
Message |
arrow
Joined: 17 May 2005 Posts: 213
|
Priority of Interrupts, and setting priority? |
Posted: Fri Jul 08, 2005 9:13 am |
|
|
Hi
Is there a priority of interrupts?
If yes, then is there a way to set the priority?
If I have an INT_RB, and the subroutine is executing, and
an INT_TIMER2 is set, will INT_RB first finish or will it go straight to
INT_TIMER2?
I am trying to flash an LED using INT_TIMER2, but my main concern is that the INT_RB routine gets done.
Thank you in advance
arrow |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1636 Location: Perth, Australia
|
|
|
valemike Guest
|
Re: Priority of Interrupts, and setting priority? |
Posted: Fri Jul 08, 2005 1:12 pm |
|
|
arrow wrote: | Hi
Is there a priority of interrupts?
If yes, then is there a way to set the priority?
If I have an INT_RB, and the subroutine is executing, and
an INT_TIMER2 is set, will INT_RB first finish or will it go straight to
INT_TIMER2?
I am trying to flash an LED using INT_TIMER2, but my main concern is that the INT_RB routine gets done.
|
I took a shortcut in my isrs. I have TIMER1, TIMER3 and RB0 interrupt. I'm not sure how much an rb0 int is different from an rb int in the way they are cleared.
Anyways, from within my other two ISRs, just before i exit those isrs, i have the following code:
#int_ext
void rb0_isr(void)
{
....
}
#int_timer1
void tmr1_isr(void)
{
...
if (rb0 interrupt flag is set)
{
rb0_isr();
}
}
You can do this shortcut with rb0 interrupts because simply doing a dummy read on rb0 will clear that flag, and that is all you need to clear that interrupt. after you call rb0_isr(), the tmr1_isr() will exit and context restoration is implemented by the CCS compiler.
And to get priorities, you can use #priority, but this only specifies which interrupt to test first. Once you're in the isr, all the other isrs will have to wait. (unless you implement a fast isr)
What ive shown you though is how to avoid the time-consuming isr overhead of a pending rb0 int. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jul 08, 2005 3:14 pm |
|
|
Quote: | #int_ext
void rb0_isr(void)
{
....
}
#int_timer1
void tmr1_isr(void)
{
...
if (rb0 interrupt flag is set)
{
rb0_isr();
}
}
You can do this shortcut with rb0 interrupts because simply doing a dummy read on rb0 will clear that flag, and that is all you need to clear that interrupt. after you call rb0_isr(), the tmr1_isr() will exit and context restoration is implemented by the CCS compiler. |
Your code doesn't do what you think it's doing. In fact, it just sets
the INTF interrupt flag (which in fact is already set if the test is true),
and exits the Timer1 isr. The PIC still has to do a complete trip through
the interrupt dispatcher routine for each interrupt.
Here is a test program to show this. This was compiled with
PCM vs. 3.227.
Code: | #include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 4000000)
#byte INTCON = 0x0B
#bit INTF_BIT = INTCON.1
#int_ext
void rb0_isr(void)
{
char c;
c = 0x55;
}
//---------------------
#int_timer1
void tmr1_isr(void)
{
char k;
k = 0xAA;
if(INTF_BIT)
{
rb0_isr();
}
}
//======================
void main()
{
while(1);
} |
Here is part of the .LST file, with comments:
Quote: | .................... #int_ext
.................... void rb0_isr(void)
.................... {
.................... char c;
.................... c = 0x55;
003C: MOVLW 55
003D: MOVWF 2A
.................... }
....................
.................... //---------------------
003E: BCF 0B.1
003F: BCF 0A.3
0040: BCF 0A.4
0041: GOTO 023
.................... #int_timer1
.................... void tmr1_isr(void)
.................... {
.................... char k;
.................... k = 0xAA;
0042: MOVLW AA
0043: MOVWF 29
....................
.................... if(INTF_BIT)
0044: BTFSS 0B.1
0045: GOTO 047
.................... {
.................... rb0_isr();
0046: BSF 0B.1 <-- It just sets the INTF bit
.................... }
.................... }
....................
.................... //======================
0047: BCF 0C.0
0048: BCF 0A.3
0049: BCF 0A.4
004A: GOTO 023
|
|
|
|
valemike Guest
|
|
Posted: Fri Jul 08, 2005 4:09 pm |
|
|
PCM Prog, i made a mistake.
You're right, that sure looks like it's going thru the interrupt dispatcher twice. What i meant to write was:
Code: |
#int_ext
void int_rb0(void)
{
my_rb0_fxn();
}
|
Then from the timer1_isr, i do:
Code: |
#int_timer1
void tmr1_isr(void)
{
[timer 1 isr code goes here]
...
Before exiting the timer isr, do a check on the rb0 int flag
if (rb0 interrupt flag is TRUE)
{
my_rb0_fxn();
}
}
...
// notice that no #int_xxx preprocessor directive precedes this function
void my_rb0_fxn(void)
{
// There is at least one dummy read of rb0 here, which automatically clears the flag
}
|
I hope this is right, i've been doing this for a while now. If it doesn't do what I expect, then that means i'm just lucky enough not to be having multiple pending isrs at once. |
|
|
valemike Guest
|
|
Posted: Fri Jul 08, 2005 4:16 pm |
|
|
maybe i should have read your comment more closely, especially the assembly listing.
However, if you call the non_isr function called my_rb0_fxn(), i don't think that the intf bit will get set or cleared.
I looked at my disassembly listing, and it's strange that the intf does not get set immediately (this is PCH for the 18F458 by the way):
Code: |
.................... #int_ext
.................... void rb0_interrupt(void)
.................... {
.................... if (GLOBAL_door_type_value == DOOR_TYPE_BESAM_AMD)
*
03AE: MOVF 54,W
03B0: SUBLW 04
03B2: BNZ 03B8
.................... {
.................... besam_amd_isr();
03B4: BRA 0362
.................... }
.....etc. etc. etc.
|
|
|
|
valemike Guest
|
|
Posted: Fri Jul 08, 2005 4:22 pm |
|
|
Wait, forget my most recent post.
I think what i'm trying to say is that if i am in a timer1 isr, then check the rb0 interrupt flag, then i should call a function not defined as the #ext_isr itself, but rather a function that the rb0 isr calls.
Thus to accomplish this, i have to declare the #int_ext isr function, and then the actual meat of the isr is in another function.
I sure hope that works, and if it isn't, well i'm lucky to not be getting any negative side effects from doing it that way |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jul 08, 2005 4:48 pm |
|
|
I think it works OK, but it costs another stack level to call the function.
So with a PIC that has only 8 stack levels, I'd just make a duplicate copy
of the int_ext code and put it in the int_timer1 isr. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Fri Jul 08, 2005 4:51 pm |
|
|
Here is an example of something I did like what Mike was trying to do
Code: |
#INT_EXT
void Zero_Cross_ISR(void)
{
if (bit_test(Current_Stat.Byte, ZEROX_FAIL_BIT))
{
Need_To_Send_Stat = TRUE;
Current_Stat.Bits.Zerox_Fail = FALSE;
}
bit_clear(FLAGS, SAVE_EEPROM_DATA_BIT);
Power_Fail = FALSE; /* if we get here it means power is good */
setup_timer_1(T1_DISABLED);
/* first time through, we need to determine if using 50Hz or 60Hz */
switch (Zero_Cross_State)
{
/* Start the frequency test */
case START_TEST:
set_timer1(0);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
Zero_Cross_State = END_TEST;
break;
/* End the test and set Test_Time to the time between zero crosses */
case END_TEST:
if (TIMER_1_HIGH > NINE_MILISEC)
Hz60 = FALSE;
Zero_Cross_State = IDLE;
break;
/* Handle zero crosses */
default:
if (Hz60)
{
set_timer1(PHAZA_ZEROX_60HZ); /* setup for Phaz A zero cross */
Phaz_Keeper = 0;
}
else
{
set_timer1(PHAZA_ZEROX_50HZ); /* setup for Phaz A zero cross */
Phaz_Keeper = 2;
}
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
Zero_Cross_Count = 10;
bit_set(PIE1, TMR1IE);
bit_clear(PIR1, TMR1IF);
break;
}
/* Clear the flag bit since we are about to bypass the compilers clear */
bit_clear(INTCON, INTF);
/* Check the int's again */
#asm
BCF 0x0A,3 /* clear 2 MSB's of the PC */
BCF 0x0A,4
GOTO 0x18 /* go back to the start of then isr handler */
#endasm
}
|
|
|
|
|
|
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
|