Dos funciones en la interrupción de prioridad alta

1

Estoy usando el PIC18F46k22 mcu y estoy usando dos funciones en mi rutina de interrupción de alta prioridad:

#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));   
}

¿Se pueden realizar dos rutinas en una interrupción de prioridad alta? ¿Habrá algún problema a largo plazo? Esto se debe a que estoy intentando averiguar por qué mi dispositivo siempre se cuelga después de ejecutarse unos días ...

    
pregunta maniac84

2 respuestas

1

Hay muchas tonterías aquí:

  1. Su rutina de interrupción es simplemente saltar a otra rutina en lugar de ejecutarse directamente. Es posible que deba hacer algo así si también está utilizando interrupciones de baja prioridad, pero este no parece ser el caso.

  2. ¿Qué ocurre con la configuración de GIE en 0 en la rutina de interrupción? Es necesario que en realidad lea la hoja de datos.

  3. Peor aún, está configurando GIE en 1 cerca del final de la segunda rutina de interrupción. Podría intentar explicar por qué no debería hacer eso, pero necesita leer la hoja de datos de todos modos, de modo que pueda descubrir por sí mismo por qué es una idea estúpida.

  4. Al ser demasiado inteligente a la mitad, como les gusta decir a los británicos, usted ha derrotado los medios del compilador para activar las interrupciones nuevamente al final de la rutina de servicio de interrupciones. Dicho de otra manera, ya no está ejecutando una instrucción RETFIE.

  5. Todo esto se podría haber hecho mucho más fácilmente en el ensamblador, y luego tal vez verías cómo el código de interrupción se confunde de la forma en que está ahora. A diferencia de los sistemas grandes con muchos niveles de abstracción, en los sistemas con recursos limitados que usan compiladores no se reduce la necesidad de entender realmente lo que está sucediendo en el nivel de instrucción de la máquina.

  6. El desorden con los detalles de la máquina, como las interrupciones, requiere absolutamente leer la hoja de datos .

respondido por el Olin Lathrop
0

No hay problemas para llamar a las funciones dentro de los ISR, ni asignar alta prioridad a múltiples periféricos, siempre y cuando no cree un conflicto mientras se les da servicio. Sin embargo, hay algunas cosas que debe tener en cuenta, como la latencia y el orden en el que las reparó. Las funciones de llamada dentro de los ISR agregan ciclos adicionales cuando se realiza el cambio de contexto (dentro y fuera), pero es algo que podría no afectar en absoluto a su aplicación si se pesa. En cuanto al orden, considere escribir arriba del if (flag) {} Encadenar los servicios de mayor prioridad o críticos, serán revisados primero. Hay algo extraño en su código y esa podría ser la razón por la que su MCU se cuelga, después de llamar a RC_ISR (); no está borrando el indicador PIR1bits.RC1IF. Está saliendo del ISR de alta prioridad con un indicador que forzará un reingreso.

    
respondido por el Guih

Lea otras preguntas en las etiquetas