Question:
Arduino digitalWrite, précautions pour la manipulation directe du port?
Paul
2016-06-06 00:53:00 UTC
view on stackexchange narkive permalink

Je suis tombé sur cette pièce dans digitalWrite . Je ne sais pas pourquoi la suppression des interruptions et la configuration / réinitialisation de SREG sont nécessaires ici.

Quelqu'un peut-il éclairer ce sujet?

  uint8_t oldSREG = SREG; cli (); if (val == LOW) {* out & = ~ bit;} else {* out | = bit;} SREG = oldSREG;  

Je suppose qu'ils ne veulent pas qu'une interruption modifie éventuellement l'un des bits du registre de sortie pendant qu'il exécute * out = * out & ~ bit ?

Et qu'est-ce que le SREG aurait à voir avec cela? Le code pourrait-il affecter SREG et pourquoi cela importerait-il?

Quand la vitesse compte, j'utilise souvent la manipulation directe du port, j'aimerais avoir une idée s'il est nécessaire pour moi d'inclure ces "précautions".

Si vous voulez faire ce type de protection contre les interruptions vous-même, regardez simplement en utilisant `ATOMIC_BLOCK` de` #include `http://www.nongnu.org/avr-libc/user-manual/group__util__atomic .html
@BrettAM yup, j'ai compris celui-là aussi (voir le dernier commentaire sur la réponse de Majenko). Bien que cela semble plus sophistiqué (et plus logique), cela ne fera pas de différence à l'exécution?
Deux réponses:
Majenko
2016-06-06 01:05:19 UTC
view on stackexchange narkive permalink

Je suppose qu'ils ne veulent pas qu'une interruption modifie éventuellement l'un des bits du registre de sortie pendant qu'il s'exécute * out = * out & ~ bit?

Correct . C'est ce qu'on appelle une section critique .

Et qu'est-ce que le SREG aurait à voir avec cela? Le code pourrait-il affecter SREG et pourquoi cela importerait-il?

SREG est l'endroit où le drapeau indiquant si les interruptions sont activées ou non est stocké. Fondamentalement, il s'agit de stocker l'état actuel, de désactiver les interruptions, puis de restaurer l'état actuel.

Le résultat est:

  • Si les interruptions sont activées pour commencer, elles sont désactivées, puis réactivé.
  • Si les interruptions sont désactivées au départ, elles sont à nouveau désactivées, et elles restent désactivées.

C'est une façon de restaurer l'état précédent sans devoir vérifier quel était l'état et définir ou effacer en conséquence.

Ah! Au début, cela n'avait pas de sens, je pensais qu'ils auraient pu utiliser «cli ()» et «sei ()». Depuis que je pensais à un "scénario d'interruptions toujours en cours". Ce qui est amusant, c'est que lorsque les interruptions sont désactivées, vous voulez qu'elles soient également désactivées après ce morceau de code. Et quand c'était allumé (:
Que se passe-t-il quand on n'utilise pas la désactivation d'interruption sur cette partie critique? Cela peut provoquer un mauvais état de sortie lorsque cette broche est également modifiée au cours d'une interruption?
Il se peut que la broche que vous souhaitez modifier dans votre ISR (parfois) ne soit pas modifiée. Ou il se peut que la broche que vous souhaitez modifier en dehors de l'ISR ne soit (parfois) pas modifiée. Ils n'ont pas besoin d'être la même broche - juste dans le même registre.
Tout ce qui fait une lecture-modification-écriture qui peut également se produire dans un contexte différent (c'est-à-dire, dans une interruption) doit être protégé afin qu'un RMW ne se produise pas à mi-chemin de l'autre RMW.
Ah, compris, l'interruption peut éditer une épingle dans le même registre, juste après la lecture et avant l'écriture. Après cela, il écrit, donc l'effet de l'interruption est annulé
Oui. Spot sur. Les seules fois où vous n'avez pas besoin d'une section critique sont pour les opérations * atomic * - c'est-à-dire les choses qui ne peuvent pas être interrompues car il ne s'agit que d'un "code d'opération" de machine. Remarque Je n'utilise pas d '"instructions d'assemblage" là-bas, car certains assembleurs utilisent des instructions de macro qui sont assemblées en plusieurs op-codes et ne sont donc pas atomiques.
J'ai en effet entendu parler de Atomic Blick http://www.nongnu.org/avr-libc/user-manual/group__util__atomic.html et des cycles de lecture-modification-écriture. Je ne sais pas directement qu'il a été appliqué dans cette situation (:
Edgar Bonet
2016-06-06 01:10:48 UTC
view on stackexchange narkive permalink

Je ne réponds qu'à la dernière question, car le reste a été traité par Majenko.

J'utilise souvent la manipulation directe du port, j'aimerais avoir une idée s'il est nécessaire pour moi d'inclure ces "précautions".

Si vous utilisez des valeurs constantes , comme PORTB | = _BV (2); ou autre, il y a pas besoin, car cela se compile en une seule instruction CPU. Même si vous écrivez des choses qui prennent plusieurs instructions, comme PORTB | = _BV (2) | _BV (3); , vous savez probablement si vous modifiez le même registre dans un gestionnaire d'interruption ou non. Sinon, pas besoin de section critique non plus. Les auteurs du cœur Arduino ne peuvent faire aucune hypothèse.

Bon. Je devrais vérifier le nombre d'instructions que certains d'entre eux prennent. Au lieu de `PORTB | = _BV (2) | _BV (3); `vous pouvez utiliser` PORTB | = 0b00000110` donc c'est à nouveau une instruction ?. Mais bon, cela dépendra du compilateur et des paramètres si cela fait quelque chose de différent.
Non, ce n'est pas une instruction - c'est une lecture-modification-écriture. Il compile en `dans r24, 0x05; ori r24 0x06; out 0x05, r24; `- i, .e, lisez le port dans le registre 24, OU la nouvelle valeur avec lui, puis écrivez la nouvelle valeur combinée sur le port. La seule raison pour laquelle l'autre méthode pour un seul bit est une seule instruction est à cause de l'instruction SBI, (définir le bit dans le registre d'E / S), telle que `sbi 0x05, 1;` for `PORTB | = 0b0000010;`
Utiliser deux `| =` séparés serait deux instructions atomiques qui conviendraient: `PORTB | = 0b00000010; PORTB | = 0b00000100; `=` sbi 0x05,1; sbi 0x05, 2; `- c'est moins efficace cependant - chaque` sbi` est composé de 2 horloges, mais `in`,` out` et `ori` sont une horloge chacun, donc 4 horloges contre 3 horloges.


Ce Q&R a été automatiquement traduit de la langue anglaise.Le contenu original est disponible sur stackexchange, que nous remercions pour la licence cc by-sa 3.0 sous laquelle il est distribué.
Loading...