Instruction AVR SEI

13

L'instruction AVR SEI ( http://www.atmel.com/webdoc/avrassembler/avrassembler.wb_SEI.html ) attend la fin de l'instruction suivante avant d'activer les interruptions.

Si j'utilise une autre instruction pour définir le drapeau I dans SREG, cela attendra-t-il également 1 instruction?

En d'autres termes: l'attente est-elle une caractéristique de l'instruction SEI ou du registre d'état?

S'il s'agit d'une caractéristique de l'instruction SEI, à quel moment le drapeau est-il réellement défini, dans le cycle qui exécute SEI ou avec l'instruction suivante?

Jay Jay
la source
C'est une excellente question, mais cela ne devrait pas être trop difficile à tester et à en être sûr.
Vorac
1
@Vorac Pouvez-vous me donner un exemple de la façon dont cela pourrait être testé? Ce serait ma réponse acceptée à coup sûr.
jayjay
1
Il peut s'agir d'une caractéristique d'une implémentation de l'architecture AVR, et où les interruptions peuvent être gérées. IIRC, l'architecture AVR a utilisé un pipeline en 3 étapes. Ainsi, la prochaine instruction peut être déjà «en vol» (c'est-à-dire à l'étape 1 du pipeline ou plus) avant que le changement de drapeau I puisse être utilisé pour vérifier les interruptions. Je n'ai pas cherché depuis longtemps, mais je ne pense pas que les concepteurs de l'architecture AVR se seraient trop contraints. Ainsi, tester l'interruption pour une instruction à l'étape 1 du pipeline, et pas avant l'instruction suivante (à l'étape 2) leur donne une certaine flexibilité.
gbulmer

Réponses:

8

Résultats empiriques!

Bien que les autres réponses soient réfléchies et bien motivées, elles sont toutes incomplètes ou simplement des conjectures. Lorsque la documentation est ambiguë, nous devons expérimenter et tester chaque cas.

Cette question mérite une réponse concluante, alors sortons un AVR et commençons à régler quelques bits!

Procédure

Pour tester, j'ai fait un petit programme Arduino (ATMEGA328P) qui serait ...

  1. configurer un ISR qui ne retournerait jamais ( while (1))
  2. assigné l'ISR à une source que je pouvais déclencher dans le logiciel ( INT0en baisse)
  3. interruptions désactivées
  4. activé et déclenché l'interruption de sorte qu'il serait en attente

J'ai utilisé un banc d'essai qui allumait une LED dans l'instruction unique après l'activation des interruptions. En essayant différentes façons d'activer les interruptions dans le banc d'essai et de vérifier la LED, je pourrais dire si l'instruction après l'exécution de l'instruction d'activation a été exécutée ou non.

Si la LED ne s'est pas allumée, je sais que l'ISR a été exécuté (et verrouillé) immédiatement après l'activation des interruptions.

Si la LED s'est allumée, je sais que l'instruction suivante a été autorisée à s'exécuter avant l'appel de l'ISR.

Résultats

SEI instruction (cas de base)

Code:

sei

Résultat: LED allumée. Instruction suivante exécutée.

OUT instruction

Code:

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

Résultat:

Conduit sur. Instruction suivante exécutée.

ST instruction

Code:

   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

Résultat:

Conduit sur. Instruction suivante exécutée.

Conclusion!

Q: L'attente est-elle une caractéristique de l'instruction SEI ou du registre d'état?

R: Il semble que changer le Ibit en SREGsoit de a 0à a 1permettra à l'instruction suivante de s'exécuter ensuite même s'il y a une interruption en attente, quelle que soit l'instruction utilisée pour régler le bit.

Remarques

Cela s'est en fait transformé en une question très intéressante avec beaucoup de complications. Si vous êtes intéressé par les détails, consultez ...

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

bigjosh
la source
2
Lorsque la spécification est ambiguë, il y a un problème avec "Résultats empiriques". Tout simplement parce que le matériel spécifique que vous avez testé fonctionne d'une manière spécifique, ne signifie pas que d'autres pièces fonctionneront de cette façon. Atmel est libre de modifier l'implémentation à condition de ne pas modifier la spécification. Donc, "Là où la documentation est ambiguë, ...", il n'en reste pas moins qu'après expérience et test, elle est toujours ambiguë.
gbulmer
@ bulbul Je suis d'accord à 100%. Celui qui utilise des fonctionnalités non documentées dans la production est forcément triste. Encore une question empirique intéressante (et une réponse), et probablement acceptable de dépendre d'un projet personnel unique.
bigjosh
Oui, vous avez fait une enquête fascinante.
gbulmer
4

D'après ma documentation, l'exécution de l' seiinstruction n'est pas différente de l'écriture directe d'un 1 sur le bit I du SREG. L'avantage de l'instruction est que vous n'avez pas besoin de charger d'abord une valeur de 1<<Idans un registre de travail pour changer le SREG, ce qui permet de gagner du temps.

Pour élaborer, en utilisant sei:

sei ; One cycle

Définir le bit en utilisant sbi(ne fonctionnerait que si SREG était dans les 32 octets inférieurs de la mappe de registre, mais il semble que sur la plupart sinon la totalité, il ne l'est pas.)

sbi SREG,7 ; Two cycles

J'écris directement dans SREG:

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

Le Ibit doit être positionné dans SREG dès que l' seiinstruction (ou sbiou out) se termine. Cependant, toutes les interruptions en attente ne seront traitées qu'après la fin de l' instruction suivante - le bit sera activé, mais il faudra un cycle supplémentaire pour que les interruptions soient activées. Étant donné qu'une interruption ne peut pas être gérée à mi-instruction et que certaines instructions prennent plus d'un cycle à exécuter, elles spécifient le temps nécessaire pour devenir activé en tant qu'une instruction. Cela devrait être le cas pour toutes les versions du code - c'est-à-dire que chacune des réponses ci-dessus entraînera le retard d'une instruction.


Après un peu de recherche, j'ai trouvé ce fil sur le forum Arduino dans lequel plusieurs tests différents ont été effectués pour vérifier le comportement. Il semble être d'accord avec ce que j'ai dit ci-dessus.

En outre, selon ce thread, si l' Iindicateur est déjà défini, il n'y a pas de réponse retardée d'une interruption causée par seice qui implique que la réponse retardée n'est pas causée par l'instruction elle-même, mais plutôt par le matériel interne contrôlé par l' Iindicateur - donc toute opération qui change le drapeau dans SREG, que ce seisoit outou ou stsaura exactement le même comportement.

Tom Carpenter
la source
Il n'y a donc aucun aspect de retarder l'opération, spécifique à SEI mais pas à OUT, qui permette à l'instruction suivante de se terminer?
Brian Drummond
Dans le cas de votre deuxième exemple, quand une interruption en attente est-elle gérée? Y a-t-il un retard de cycle comme dans le premier?
jayjay
@jayjay voir ma mise à jour.
Tom Carpenter
1
Notez que SBIcela ne peut pas être utilisé pour définir le Ibit, SREGdonc tout code qui fait cela n'a probablement pas été testé dans la vie réelle car il ne s'assemblera même pas. SBIne peut fonctionner que sur les 32 registres inférieurs et SREG est à l'emplacement 63.
bigjosh
@bigjosh l'exemple SBI était celui auquel j'ai pensé plus tard - outétait celui que j'utilisais à l'origine. Je pensais avoir rencontré un AVR (peut-être un ATTiny) qui a le SREG dans les 32 registres inférieurs, mais je l'imagine peut-être.
Tom Carpenter
1

À mon humble avis, l'écriture dans SREG retarde encore 1 instruction peut être testée comme ceci (pseudocode):

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);
}

Malheureusement, je n'ai pas le temps de le faire :(

Vorac
la source
0

Ce n'est pas ce qu'il dit. La documentation dit

L'instruction suivant SEI sera exécutée avant toute interruption en attente.

pas qu'il attend la prochaine instruction. J'ai lu ceci car l'indicateur est défini immédiatement mais même s'il est activé, aucune interruption ne sera gérée jusqu'à ce que la prochaine instruction ait été exécutée.

patthoyts
la source
Tout cela est vrai, mais ma question est: ce comportement est-il spécifique à SEI?
jayjay
@jayjay Je soupçonne que cela est dû à la longueur du pipeline d'instructions
crasic