14 votos

Instrucción AVR SEI

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

Si utilizo otra instrucción para fijar la bandera I en el SREG, ¿también esperará 1 instrucción?

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

Si es una característica de la instrucción SEI, entonces ¿en qué momento se activa realmente la bandera, en el ciclo que ejecuta la SEI o con la siguiente instrucción?

0 votos

Esta es una gran pregunta, pero no debería ser demasiado difícil de probar y estar seguro.

1 votos

@Vorac ¿Puedes darme un ejemplo de cómo se podría probar esto? Esa sería mi respuesta aceptada con seguridad.

1 votos

Puede ser una característica de una implementación de la arquitectura AVR, y donde las interrupciones pueden ser manejadas. Según recuerdo, la arquitectura AVR utilizaba un pipeline de 3 etapas. Así que la siguiente instrucción puede estar ya "en vuelo" (es decir, en la primera etapa del pipeline, o más allá) antes de que el cambio de la bandera I pueda ser utilizado para comprobar las interrupciones. No he mirado durante mucho tiempo, pero no creo que los diseñadores de la arquitectura AVR se hayan limitado demasiado. Así que, comprobando la interrupción para una instrucción en la etapa 1 del pipeline, y no antes de la siguiente instrucción (en la etapa 2) les da cierta flexibilidad.

9voto

chews Puntos 1507

Resultados empíricos

Aunque las demás respuestas son reflexivas y están bien razonadas, todas son incompletas o sólo conjeturas. Cuando la documentación es ambigua, hay que experimentar y probar cada caso.

Esta pregunta merece una respuesta concluyente, así que saquemos un AVR y empecemos a configurar algunos bits.

Procedimiento

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

  1. configurar un ISR que nunca regrese ( while (1) )
  2. asignó el ISR a una fuente que podía activar en el software ( INT0 bajando)
  3. interrupciones desactivadas
  4. activó y disparó la interrupción para que quedara pendiente

Utilicé un banco de pruebas que encendía un LED en la única instrucción después de habilitar las interrupciones. Probando diferentes formas de habilitar las interrupciones en el banco de pruebas y comprobando el LED, podía saber si la instrucción posterior a la habilitación se ejecutaba 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 la siguiente instrucción pudo ejecutarse antes de llamar al ISR.

Resultados

SEI instrucción (caso base)

Código:

sei

Resultado: LED encendido. Se ejecuta la siguiente instrucción.

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. Se ejecuta la siguiente instrucción.

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. Se ejecuta la siguiente instrucción.

¡Conclusión!

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

R: Parece que el cambio de la I bit en SREG es de un 0 a un 1 permitirá que la siguiente instrucción se ejecute incluso si hay una interrupción pendiente, independientemente de la instrucción que se utilice para establecer el bit.

Notas

Esto 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/

3 votos

Cuando la especificación es ambigua, hay un problema con los "resultados empíricos". El simple hecho de que la pieza específica de hardware que se ha probado funcione de una manera específica, no significa que otras piezas vayan a funcionar de esa manera. Atmel es libre de cambiar la implementación siempre que no cambie la especificación. Así que, "Cuando la documentación es ambigua, ..." sigue siendo exactamente eso, después de experimentar y probar, sigue siendo ambigua.

0 votos

@gbulmer Estoy 100% de acuerdo. El que usa características no documentadas en producción, seguro que está triste. Aún así es una pregunta empírica interesante (y su respuesta), y probablemente esté bien depender de un proyecto personal puntual.

1 votos

Sí, has hecho una investigación fascinante.

4voto

Tom Carpenter Puntos 7192

Tengo entendido que, según la documentación, la realización de la sei no es diferente de escribir directamente un 1 en el bit I del SREG. La ventaja de la instrucción es que no es necesario cargar primero un valor de 1<<I en un registro de trabajo para cambiar el SREG, así se ahorra tiempo.

Para más detalles, el uso de sei :

sei ; One cycle

Ajuste del bit mediante sbi (sólo funcionaría si SREG estuviera en los 32 bytes inferiores del mapa de registros, pero parece que en la mayoría, si no en todos, no lo está).

sbi SREG,7 ; Two cycles

Escribir en el bit I directamente en el SREG:

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

El I debe activarse en el SREG tan pronto como el sei instrucción (o sbi o out ) completa. Sin embargo, cualquier interrupción pendiente no será manejada hasta después de que el siguiente el bit se activará, pero las interrupciones tardarán un ciclo más en activarse. Debido a que una interrupción no puede ser manejada a mitad de la instrucción, y algunas instrucciones toman más de un ciclo para ejecutarse, especifican el tiempo que toma para 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 causará el retraso de una instrucción.


Después de buscar un poco, encontré este hilo en el foro de Arduino en el que se realizaron diferentes pruebas para comprobar el comportamiento. Parece que coincide con lo que he dicho más arriba.

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

0 votos

Entonces, ¿no hay ningún aspecto de retraso de la operación, específico de SEI pero no de OUT, que permita completar la siguiente instrucción?

0 votos

En el caso de tu segundo ejemplo, ¿cuándo se gestiona una interrupción pendiente? ¿Hay un retardo de ciclo como en el primero?

0 votos

@jayjay ver mi actualización.

1voto

KC Baltz Puntos 655

IMHO la escritura a SREG todavía retrasa 1 instrucción puede ser probada así (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 me falta tiempo para hacerlo :(

0voto

Simplexion Puntos 41

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

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

no que espere la siguiente instrucción. Yo leo esto como que la bandera se activa inmediatamente pero aunque esté habilitada, no se manejarán las interrupciones hasta que se haya ejecutado la siguiente instrucción.

0 votos

Todo esto es cierto, pero mi pregunta es: ¿este comportamiento es específico de SEI?

0 votos

@jayjay Sospecho que esto se debe a la longitud del pipeline de instrucciones

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X