PIC ISR: ¿comprueba cada fuente de interrupción o solo una?

2

Tengo curiosidad por saber si hay alguna ganancia en particular por usar una llamada en lugar de un goto cuando se verifica cada fuente de interrupción en un ISR. Mi código actual haría algo como esto:

.intr   CODE        4

    pagesel     $

    btfsc       INTCON, TMR0IF          ; Timer0
      goto      Timer0_Entry

    banksel     PIR1                    ; Bank #0
    btfsc       PIR1, SSP1IF
      goto      I2C_Entry               ; I2C Peripheral
...

pero eso es en una imagen mejorada de rango medio 16 donde se realiza el guardado de contexto por ti. Si estuviera en un PIC16F88, habría una victoria (menor) por evitar todo el tedioso contexto, salvo en una situación en la que estuvieran pendientes dos fuentes de interrupción simultáneas.

Al hacerlo con gotos, se crea implícitamente una lista de prioridades que puede detener otras fuentes. Si tuviera varias interrupciones de una fuente, esa fuente detendría las otras fuentes irq hasta que se detenga. Lo logré una vez al olvidar que el indicador de irq del puerto serie está activado de forma predeterminada.

Pero aparte de eso, ¿es solo una cuestión de gusto? El golpe que recibes (en una situación de irq múltiple) al hacer una devolución y luego regresar al ISR de inmediato no es particularmente grave.

    
pregunta carveone

1 respuesta

1

TL; DR: usa la menor cantidad de interrupciones que puedas y mantén su ISR corto. Descargar trabajo no crítico al bucle principal es una gran ayuda.

En un PIC, con su único vector de interrupción (doble para PIC18), a menudo hago esto:

void ISR()
{
    if(FLAG1_EN && FLAG1)
    {
        //ISR1
    }
    if(FLAG2_EN && FLAG2)
    {
        //ISR2
    }
    //etc.
}

Esto evita llamadas a funciones desde el ISR, lo que hace que mi compilador genere un montón de código adicional para guardar el contexto, incluso en un chip que lo hace (parte de) automáticamente.

Si es necesario, puedo ordenarlos por prioridad y regresar de cada uno sin verificar el resto de las banderas, para que las prioridades más altas sean consultadas con mayor frecuencia. O para guardar algo de latencia, puede retroceder y repetir el ISR, y solo regresar si no hay ninguno activo.

O, si algunos ISR son tareas periódicas que solo tienen que promediar a la frecuencia correcta, puede hacer que sus ISR simplemente establezcan una marca y se vayan. El bucle principal luego observa las banderas y realiza las actividades cuando se acerca a ellas. Esto hace que el ISR real sea muy corto y permite que una tarea de mayor prioridad interrumpa su actividad. De hecho, incluso puede utilizar el indicador de interrupción en el bucle principal y no habilitar la interrupción real para él.

En esta plataforma, nunca se le garantizará que una interrupción de prioridad súper alta será atendida con latencia constante, a menos que pueda convertirla en la única fuente de interrupción real. Siempre existe la posibilidad de que se posponga hasta que se termine una diferente. Hay formas de reducir esa posibilidad y la consecuencia de que suceda, pero nunca la elimines.

Dicho esto, Spehro tiene un buen punto acerca de las interrupciones que suelen suceder de una en una y, por lo general, no son un problema. A menos que pases todo tu tiempo en el ISR; entonces casi garantizas una colisión.

    
respondido por el AaronD

Lea otras preguntas en las etiquetas