Se detectó que al menos uno de los vectores ISR no estaba inicializado

1

Este es el programa para hacer parpadear el LED rojo en el puerto P1.0 en MSP430 Launchpad

#include <msp430.h>
int main(void) {
    WDTCTL = WDTPW + WDTHOLD;       // Stop watchdog timer
    P1DIR |= 0x01;                  // Set P1.0 to output direction

    for(;;) {
        volatile unsigned int i;    // volatile to prevent optimization

        P1OUT ^= 0x01;              // Toggle P1.0 using exclusive-OR

        i = 4000;                   // SW Delay
        do i--;
        while(i != 0);
    }
}

Esto funcionaba bien, excepto muchas advertencias similares a las siguientes:

  

El vector de interrupción "COMPARATORA" no tiene un controlador de interrupción   rutina. lnk_msp430g2553.cmd / LEDBlinking line 88 C / C ++ Problem

Solo recibí ayuda del IDE: Se detectó que al menos uno de los vectores ISR no estaba inicializado.

Cuando agregué las siguientes líneas de código, las advertencias desaparecieron.

/* Initialize non-used ISR vectors with a trap function */

#pragma vector=PORT2_VECTOR
#pragma vector=PORT1_VECTOR
#pragma vector=TIMER1_A1_VECTOR
#pragma vector=TIMER1_A0_VECTOR
#pragma vector=TIMER0_A1_VECTOR
#pragma vector=TIMER0_A0_VECTOR
#pragma vector=ADC10_VECTOR
#pragma vector=USCIAB0TX_VECTOR
#pragma vector=WDT_VECTOR
#pragma vector=USCIAB0RX_VECTOR
#pragma vector=NMI_VECTOR
#pragma vector=COMPARATORA_VECTOR

__interrupt void ISR_trap(void)
{

}

pragma que conozco es una directiva de compilación que le dice que haga algo explícitamente. Pero lo que está sucediendo aquí no lo puedo entender. También la función ISR_trap (void) haciendo aquí? Cuando quité esta función, volví a ver esas advertencias.

    
pregunta gpuguy

2 respuestas

6

Así es como funciona una interrupción:

Cuando ocurre un evento determinado (el que dispara la interrupción correspondiente) el procesador detiene lo que está haciendo, guarda el punto de ejecución actual (el contador del programa) y comienza a ejecutar el controlador de interrupción. Por lo general, la última instrucción de un controlador de interrupciones es una instrucción especial que le dice al procesador que continúe la ejecución desde el punto en que se guardó antes de ingresar la interrupción.

Para ejecutar el controlador de interrupciones, el procesador necesita saber dónde está.

A menudo esto se hace así: cada interrupción tiene una dirección correspondiente en la memoria del programa y los procesadores comienzan a ejecutar las instrucciones desde allí, por lo general estas direcciones están al principio de la memoria del programa. Debido a que una instrucción generalmente no es suficiente para un controlador de interrupciones, la instrucción generalmente es un jmp para el controlador real. Esto crea un problema: si al inicio de la memoria del programa tiene un montón de jmp que van a los controladores de interrupción correspondientes, entonces la primera instrucción que ve el procesador después del encendido es un jmp para el primer controlador de interrupción y ejecutará eso En lugar del programa principal. Debido a esto, la primera instrucción en la memoria del programa suele ser un jmp al código del programa principal (puede pensar en un reinicio como un tipo especial de interrupción del que no regresa), y lo sigue el jmp a los manejadores de interrupciones.

Por lo tanto, el programa compilado en la memoria del programa se puede desarmar en algo como esto:

jmp main_program
jmp isr_1
jmp isr_2
...

isr_1:
...
reti

isr_2:
...
reti

main_program:
...

El código del ensamblador

somewhere:

es una etiqueta. No se convierte en código binario, pero el ensamblador recuerda la dirección en la que se colocó "algún lugar" y reemplaza cualquier mención de él en la lista del ensamblador con esa dirección. Así que cuando el ensamblador ve esto:

...
    jmp somewhere
...

...
somewhere:
    some_instrunction
....

recuerda la dirección en la que se colocó "some_instrunction" y compila "jmp en algún lugar" del código binario "jmp_opcode address_of_some_instrunction".

Entonces, ¿qué tiene todo esto que ver con la advertencia del compilador que está recibiendo?

El compilador advierte que no ha asignado los controladores de interrupción para los eventos sobre los que está advirtiendo. Lo que el compilador hace con esto depende del compilador. Es posible que no genere una tabla de interrupciones (si las interrupciones no están habilitadas, esto no será un problema, si se producen, la interrupción saltará a algún lugar cerca del inicio de su programa, pero no del todo) (la posición exacta depende de la dirección de la interrupción)), puede colocar reti en lugar de jmps, por lo que si se activa la interrupción, regresa de inmediato, puede tener su propio controlador de interrupción de emergencia que detiene la ejecución del procesador.

¿Qué hace "#pragma vector = event" y "__interrupt void function_name ()"?

"__interrupt" le dice al compilador que la siguiente función es en realidad un controlador de interrupciones, por lo que no puede tener ningún argumento, en lugar de una instrucción ret, la función termina con un reti, y algunas sobre cosas como qué registros se guardan en la pila, etc.

"#pragma vector = event" le dice al compilador la interrupción de qué evento es la función siguiente y usar la dirección de esa función como un argumento para la instrucción jmp colocada en la dirección de la interrupción del "evento".

Por lo tanto, el código que escribió que detuvo las advertencias es un controlador para todos los eventos en las #pragmas escritas.

Cuando eliminó la función en sí misma, básicamente le dijo al compilador "la siguiente función es un controlador de interrupciones" pero no le dio una función. Así que el compilador todavía no tiene un controlador de interrupción. Colocar un #pragma como este (sin la función de la que está hablando) es peligroso, porque le gustaría comenzar a escribir otra cosa y que otra cosa se convertirá en un controlador de interrupciones. Aún más doloroso sería colocar tal #pragma en un archivo ".h" (¿o es el alcance de un #pragma solo un archivo?).

¿Son esas advertencias un problema?

Debe asegurarse de haber definido el controlador de interrupciones para todas las interrupciones que están habilitadas. Por lo general, hay un bit global_enable_interrupts que debe configurarse para que funcionen las interrupciones y un bit de habilitación por cada posible interrupción. Normalmente, el bit de habilitación de cada interrupción se encuentra en los registros de configuración del módulo periférico (uart, temporizador, etc.) que activa esa interrupción. Además, los bits de interrupt_triggered del módulo periférico generalmente se activan / desactivan incluso cuando las interrupciones están deshabilitadas (por ejemplo, uart tiene una interrupción byte_recieve, la interrupción está deshabilitada, pero el software puede verificar ese bit para ver si hay un byte se ha recibido, esto se puede utilizar para recibir bytes con sondeo).

Otra cosa que debes tener en cuenta es el NMI (interrupción no enmascarable), debes pensar qué pasará si / cuando se activa.

    
respondido por el user25093
1

Un microcontrolador generalmente tiene múltiples interrupciones, internas (como un temporizador interno) y externas (para presionar botones, recibir datos, etc.).

Un controlador de interrupción es el código que se ejecuta cuando se activa una determinada interrupción. Por ejemplo, conectaría un botón a una línea de interrupción externa y luego escribiría un controlador que alterna una salida cada vez que se presiona el botón.

Las advertencias simplemente le dicen que no ha definido los manejadores para todas las interrupciones disponibles y, por lo tanto, la uC no sabe qué hacer cuando suceden (y por lo tanto no hará nada). Es posible que esto no sea lo que desea, por lo que el compilador le informa al respecto.

Si desea que el compilador deje de quejarse, debe decirle explícitamente que no quiere que ocurra nada para esas interrupciones (y eso es lo que el ISR_trap vacío está haciendo allí). Los pragmas le dicen al compilador a qué interrupciones se aplica el controlador.

Tenga cuidado de no ignorar accidentalmente las interrupciones que necesite de esta manera.

    
respondido por el us2012

Lea otras preguntas en las etiquetas