Instrucción AVR SEI

13

La instrucción AVR SEI ( http://www.atmel.com/webdoc/avrassembler/avrassembler.wb_SEI.html ) espera a que finalice la siguiente instrucción antes de habilitar las interrupciones.

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

En otras palabras: ¿Es la espera una característica de la instrucción SEI o del 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?

Jay Jay
fuente
Esta es una gran pregunta, pero no debería ser demasiado difícil de probar y estar seguro.
Vorac
1
@Vorac ¿Puede darme un ejemplo de cómo se podría probar esto? Esa sería mi respuesta aceptada con seguridad.
jayjay
1
Puede ser una característica de una implementación de la arquitectura AVR, y donde se pueden manejar las interrupciones. IIRC, la arquitectura AVR utilizó una tubería de 3 etapas. Por lo tanto, la siguiente instrucción puede estar ya 'en vuelo' (es decir, en la etapa de canalización uno o más) antes de que el cambio de bandera I pueda usarse para verificar las interrupciones. No he buscado durante mucho tiempo, pero no creo que los diseñadores de la arquitectura AVR se hayan limitado demasiado. Entonces, probar la interrupción para una instrucción en la etapa 1 de la tubería, y no antes de la siguiente instrucción (en la etapa 2) les da cierta flexibilidad.
Gbulmer

Respuestas:

8

¡Resultados empíricos!

Si bien las otras respuestas son reflexivas y bien razonadas, todas son incompletas o solo conjeturas. 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 volvería ( while (1))
  2. asigné el ISR a una fuente que podría activar en el software ( INT0bajando)
  3. interrupciones deshabilitadas
  4. habilitó y activó la interrupción por lo que estaría pendiente

Utilicé un banco de pruebas que encendía un LED en la única instrucción después de que se habilitaran las interrupciones. Al probar diferentes formas de habilitar las 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 bloqueó) inmediatamente después de que se habilitaran las interrupciones.

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

Resultados

SEI instrucción (caso base)

Código:

sei

Resultado: LED encendido. Siguiendo 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:

Llevado en. Siguiendo 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:

Llevado en. Siguiendo instrucciones ejecutadas.

¡Conclusión!

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

R: Parece que cambiar el Ibit en SREGde a 0a 1permitirá que la siguiente instrucción se ejecute a continuación, incluso si hay una interrupción pendiente, independientemente de qué instrucción se use para establecer el bit.

Notas

Esto en realidad se convirtió en una pregunta muy interesante con muchas complicaciones. Si está interesado en los detalles, consulte ...

http://wp.josh.com/2016/01/05/different-ways-to-set-i-bit-in-avr-sreg-besides-sei/

bigjosh
fuente
2
Cuando la especificación es ambigua, hay un problema con los "resultados empíricos". Simplemente porque la pieza específica de hardware que probó funciona de una manera específica, no significa que otras partes funcionarán de esa manera. Atmel tiene la libertad de cambiar la implementación siempre que no cambie la especificación. Entonces, "Donde la documentación es ambigua, ..." sigue siendo exactamente eso, después de experimentar y probar, todavía es ambigua.
Gbulmer
@gbulmer Estoy de acuerdo al 100%. El que usa características indocumentadas en la producción está triste. Todavía es una pregunta empírica interesante (y respuesta), y probablemente está bien depender de un proyecto personal único.
bigjosh
Sí, hiciste una investigación fascinante.
Gbulmer
4

Tengo entendido por la documentación que realizar la seiinstrucción 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 1<<Ien un registro de trabajo para cambiar el SREG, por lo que ahorra tiempo.

Para elaborar, usando sei:

sei ; One cycle

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

sbi SREG,7 ; Two cycles

Escribiendo a I bit directamente en SREG:

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

El Ibit debe fijarse en SREG tan pronto como la seiinstrucción (o sbio out) completa. Sin embargo, cualquier interrupción pendiente no se manejará hasta después de que se complete la siguiente instrucción: el bit se establecerá, pero se necesita un ciclo adicional para que las interrupciones se habiliten. Debido a que una interrupción no puede manejarse a mitad de la instrucción, y algunas instrucciones tardan más de un ciclo en ejecutarse, especifican el tiempo que lleva habilitarse como una instrucción. Este debería ser el caso para todas las versiones del código, es decir, cada una de las anteriores provocará el retraso de una instrucción.


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

Además, de acuerdo con ese hilo, si el Iindicador ya está configurado, entonces no hay respuesta retrasada de una interrupción causada por lo seique implica que la respuesta retrasada no es causada por la instrucción en sí, sino en el hardware interno controlado por elI indicador. por lo que cualquier operación que cambia la bandera en SREG, ya sea seio outo ststendrá exactamente el mismo comportamiento.

Tom Carpenter
fuente
Entonces, ¿no hay ningún aspecto de retrasar la operación, específico de SEI pero no OUT, que permita que se complete la siguiente instrucción?
Brian Drummond el
En el caso de su segundo ejemplo, ¿cuándo se maneja una interrupción pendiente? ¿Hay un retraso de ciclo como en el primero?
Jayjay
@jayjay ver mi actualización.
Tom Carpenter el
1
Tenga en cuenta que SBIno se puede usar para configurar el Ibit, por SREGlo que cualquier código que lo haga probablemente no se probó en la vida real porque ni siquiera se ensamblará. SBIsolo puede operar en los 32 registros inferiores y SREG está en la ranura 63.
bigjosh
@bigjosh, el ejemplo de SBI fue uno en el que pensé más tarde, outfue el que estaba usando originalmente. Pensé que había encontrado un AVR (podría ser un ATTiny) que tiene el SREG en los 32 registros inferiores, pero puedo estar imaginándolo.
Tom Carpenter el
1

En mi humilde opinión, escribir en SREG todavía demora 1 instrucción que se puede probar de esta manera (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 :(

Vorac
fuente
0

Eso no es lo que dice. Las documentaciones dicen

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

No es que espere la próxima instrucción. Leí esto ya que el indicador se establece de inmediato, pero aunque esté habilitado, no se manejarán interrupciones hasta que se ejecute la siguiente instrucción.

patthoyts
fuente
Todo esto es cierto, pero mi pregunta es: ¿Es este comportamiento específico de SEI?
Jayjay
@jayjay Sospecho que esto se debe a la longitud de la tubería de instrucción
crasic el