instrucción AVR SEI

12

La instrucción AVR SEI ( enlace ) espera a que finalice la siguiente instrucción antes de habilitar las interrupciones.

Si uso otra instrucción para establecer el indicador I en SREG, ¿esto también esperará 1 instrucción?

En otras palabras: ¿es la espera una función de la instrucción SEI o el registro de estado?

Si es una característica de la instrucción SEI, ¿en qué punto se establece realmente el indicador, en el ciclo que ejecuta SEI o con la siguiente instrucción?

    
pregunta jayjay

4 respuestas

6

¡Resultados empíricos!

Mientras que las otras respuestas son reflexivas y están bien razonadas, todas están incompletas o son solo una conjetura. Cuando la documentación es ambigua, debemos experimentar y probar cada caso.

Esta pregunta merece una respuesta concluyente, ¡así que saquemos un AVR y comencemos a configurar algunos bits!

Procedimiento

Para probar, hice un pequeño programa Arduino (ATMEGA328P) que ...

  1. configurar un ISR que nunca devolvería ( while (1) )
  2. asignó el ISR a una fuente que podría desencadenar en el software ( INT0 bajando)
  3. interrupciones inhabilitadas
  4. habilitó y desencadenó la interrupción por lo que estaría pendiente

Utilicé un banco de pruebas que encendería un LED en la instrucción única después de que se habilitaran las interrupciones. Al probar diferentes formas de habilitar interrupciones en el banco de pruebas y verificar el LED, podría decir si la instrucción después de la instrucción de habilitación se ejecutó o no.

Si el LED no se encendió, entonces sé que el ISR se ejecutó (y se bloqueó) inmediatamente después de que se habilitaran las interrupciones.

Si el LED se encendió, entonces sé que se permitió que se ejecutara la siguiente instrucción antes de llamar al ISR.

Resultados

SEI instrucción (caso base)

Código:

sei

Resultado: Llevado en. Siguiendo las instrucciones ejecutadas.

OUT instrucción

Código:

in  r16,0x3f   // Get SREG
ori r16,128    // Set I bit 
out 0x3f,r16   // Save back to SREG

Resultado:

LED encendido. Siguiendo las instrucciones ejecutadas.

ST instrucción

Código:

   clr r29        // Clear Y high byte
   ldi r28,0x5f   // Set Y low byte to point to SREG
   ld r16, Y      // Get SREG
   ori r16,128    // Set I bit 
   st Y,r16       // Put SREG

Resultado:

LED encendido. Siguiendo las instrucciones ejecutadas.

Conclusión!

P: ¿La espera es una característica de la instrucción SEI o del registro de estado?

A: Parece que cambiar el I bit en SREG es de 0 a 1 permitirá que la siguiente instrucción se ejecute a continuación, incluso si hay una interrupción pendiente, independientemente de qué instrucción sea utilizado para establecer el bit.

Notas

Esto realmente se convirtió en una pregunta muy interesante con muchas complicaciones. Si te interesan los detalles, echa un vistazo ...

enlace

    
respondido por el bigjosh
4

De acuerdo con la documentación, entiendo que realizar la instrucción sei no es diferente de escribir directamente un 1 en el bit I del SREG. La ventaja de la instrucción es que no necesita cargar primero un valor de 1<<I en un registro de trabajo para cambiar el SREG, por lo que ahorra tiempo.

Para elaborar, utilizando sei :

sei ; One cycle

Establecer el bit usando sbi (solo funcionaría si SREG estuviera en los 32 bytes más bajos del mapa de registro, pero parece que en la mayoría, si no en todo, no lo está).

sbi SREG,7 ; Two cycles

Escribiendo a bit directamente en SREG:

in  r24,SREG ;
ori r24,0x80 ;
out SREG,r24 ; Three cycles

El bit I se debe establecer en SREG tan pronto como se complete la instrucción sei (o sbi o out ). Sin embargo, las interrupciones pendientes no se manejarán hasta que se complete la instrucción next . El bit se establecerá, pero se requiere un ciclo adicional para que las interrupciones se habiliten. Debido a que una interrupción no se puede manejar a mitad de la instrucción, y algunas instrucciones toman más de un ciclo para ejecutarse, especifican el tiempo que toma habilitarse como una sola instrucción. Este debería ser el caso para todas las versiones del código, es decir, cada uno de los anteriores causará el retraso de una instrucción.

Después de un poco de búsqueda, encontré este hilo en el foro de Arduino en el que se realizan varias pruebas diferentes. Se realizaron para verificar el comportamiento. Parece estar de acuerdo con lo que dije anteriormente.

Además, de acuerdo con ese hilo, si el indicador I ya está establecido, entonces no hay respuesta retrasada de una interrupción causada por sei , lo que implica que la respuesta retardada no es causada por la instrucción en sí, sino en el hardware interno controlado por el indicador I , por lo que cualquier operación que cambie el indicador en SREG, ya sea sei o out o sts tendrá exactamente el mismo comportamiento.

    
respondido por el Tom Carpenter
1

En mi humilde opinión, escribir en SREG aún se puede probar con una instrucción de retardo 1 (pseudocódigo):

ISR() { PORTA = 0; while(1); }
main() 
{
    cli();
    DDRA = 0xff;
    configure_isr_for_level_interrupt_that_will_trigger_immediately();
    SREG = 0xff;
    cli();
    PORTA = 0xff;
    while(1);
}

Lamentablemente, no tengo tiempo para hacerlo :(

    
respondido por el Vorac
0

Eso no es lo que dice. La documentación dice

  

La instrucción que sigue a SEI se ejecutará antes de cualquier interrupción pendiente.

no es que espere la siguiente instrucción. Leí esto ya que el indicador se establece de inmediato, pero aunque está activado, no se manejarán las interrupciones hasta que se haya ejecutado la siguiente instrucción.

    
respondido por el patthoyts

Lea otras preguntas en las etiquetas