I'm using the PIC18F46k22 mcu and I'm using two function in my high priority interrupt routine:
#pragma code
#pragma code My_HiPrio_Int=0x0008
#pragma code
#pragma interrupt chk_isr
#pragma code
void My_HiPrio_Int(void)
{
_asm
GOTO chk_isr
_endasm
}
void chk_isr(void) /*Serial Interrupt*/
{
INTCONbits.GIE = 0;
if(INTCONbits.TMR0IF==1) //Timer routine
Timer0_ISR();
if(PIR1bits.RC1IF) //RS485 receiver
RC_ISR();
INTCONbits.GIE = 1;
}
void Timer0_ISR(void)
{
nTick0++;
if(pSet == 0) nTickSetPress++;
else nTickSetPress = 0;
if(pPlus == 0) nTickPlusPress++;
else nTickPlusPress = 0;
if(pMinus == 0) nTickMinusPress++;
else nTickMinusPress = 0;
if(pShift == 0) nTickShfPress++;
else nTickShfPress = 0;
if(pCountPlus == 0) nTickCount++;
else nTickCount = 0;
if(pReset == 0) nTickResetPress++;
else nTickResetPress = 0;
if(bCdlyStart == 1) nCdlyCount++;
if(nCdlyCount >= nTickCdly) bCdlyStart = 0;
if(bDisplayTime == 1) nDisplayTimeCount++;
if(bBlinkDigitFast == 1) nTickBlinkFast++;
TMR0H = TMR0HValue;
TMR0L = TMR0LValue;
INTCONbits.TMR0IF = 0;
}
void RC_ISR(void)
{
rxbuf485 = RCREG1;
if (rxbuf485 == 0)
{
return;
}
if (rxbuf485 == TOKEN)
{
b485RxToken = 1;
return;
}
if (b485RxComplete) return;
if (!b485SOH)
{
if (rxbuf485 != SOH) return;
b485SOH = 1;
n485RxDataPos = 0;
b485RxComplete = 0;
memset (RS485RXDATA, 0, sizeof(RS485RXDATA));
return;
}
else if (rxbuf485 == EOT)
{
b485SOH = 0;
b485RxComplete = 1;
return;
}
if (n485RxDataPos == 50)
n485RxDataPos = 50;
if (n485RxDataPos>=RS485RXSIZE)
n485RxDataPos--;
RS485RXDATA[n485RxDataPos++] = rxbuf485;
return;
}
void Timer0Init(void)
{
T0CON = 0x07;
TMR0H = TMR0HValue;
TMR0L = TMR0LValue;
T0CONbits.TMR0ON = 1;
INTCONbits.TMR0IE = 1;
nTick0 = 0;
nTickSetPress = 0;
nTickResetPress = 0;
nTickCdly = 0;
nTickBlinkFast = 0;
}
void RS485Init(void)
{
TRISCbits.TRISC7=1; // RX
TRISCbits.TRISC6=0; // TX
TXSTA1 = 0x00;
RCSTA1 = 0x90;
SPBRG1 = 30;
BAUDCON1 = 0x00;
PIE1bits.RC1IE = 1;
TRISCbits.TRISC3 = 0;
p485 = 0;
memset (RS485RXDATA, 0, sizeof(RS485RXDATA));
}
Can two routine be done in a high priority interrupt? Will there be any problem in long term? This is because I'm trying to find out why my device always hang after running a few days...
2 Answers 2
There is much silliness here:
- Your interrupt routine is just jumping into another routine instead of executing directly. You may need to do something like that if you are also using low priority interrupts, but this doesn't seem to be the case.
- What's with setting GIE to 0 in the interrupt routine? You need to actually read the datasheet.
- Even worse, you are setting GIE to 1 near the end of the second interrupt routine. I could try to explain why you shouldn't do that, but you need to read the datasheet anyway, so you can discover for yourself why this is a dumb idea.
- By being too clever by a half, as the British like to say, you have defeated the compiler's means of properly turning on interrupts again at the end of the interrupt service routine. Put another way, you are no longer running a RETFIE instruction.
- This whole thing could have been done much more easily in assembler, and then maybe you'd see how the interrupt code is messed up the way it is now. Unlike on large systems with many levels of abstraction, on small resource limited systems using a compiler doesn't alleviate the need to actually understand what is happening at the machine instruction level.
- Messing with machine details like interrupts absolutely requires reading the datasheet.
There's no trouble in calling functions within ISRs, neither assigning high priority to multiple peripherals as long as it doesn't create a conflict while servicing them. There are a couple of things to have in mind though, such as latency and the order in which you service them. Calling functions within ISRs add extra cycles when the context switch is performed (in and out), but its something that might not affect your application at all if weighed in. As for the order, consider writing up top the if(flag){} chain the higher priority or critical services, they will be checked first. There's something odd in your code and that might the the reason why your MCU hangs, after you call RC_ISR(); you are not clearing the PIR1bits.RC1IF flag. You are exiting the high priority ISR with a flag that will force a reentry.
-
\$\begingroup\$
There's no trouble in calling functions within ISRs
There might be problems if the function in question is also called outside the interrupt and if the compiler doesn't support reentrant functions \$\endgroup\$m.Alin– m.Alin2014年10月31日 14:24:07 +00:00Commented Oct 31, 2014 at 14:24
return
at the end of function, you can save an instruction there. I don't think calling two functions in ISR making it unresponsive but there could be some another reason for that! \$\endgroup\$