Comment fonctionne la pile d'appels pendant une interruption sur AVR?

8

(Spécifique à l'Arduino Uno ...)

Qu'arrive-t-il à la pile lorsqu'une interruption se produit sur un microcontrôleur AVR et que j'appelle une fonction? Le compilateur insère-t-il le code? Est-ce qu'il cache la pile quelque part, puis réinitialise le pointeur de la pile? A-t-il une pile secondaire pour les interruptions uniquement?

Si je comprends bien, le vecteur de l'interruption est une commande GOTO directe dans l'assemblage. De plus, je ne pense pas que le microcontrôleur gâcherait automatiquement la pile, donc il est probablement laissé seul. Cependant, cela n'explique toujours pas comment les fonctions fonctionnent pendant un ISR.

Pingouin anonyme
la source
La réponse ci-dessous est excellente, veuillez noter que le compilateur ne peut pas interrompre les appels en ligne car ... Ce sont des appels interrompus: D
Vladimir Cravero
1
@VladimirCravero Je voulais dire en ligne les fonctions appelées dans l'interruption (si j'appelle foo () dans l'ISR le fait-il en ligne donc ce n'est pas vraiment un appel de fonction?)
Pingouin anonyme
Donc, la réponse ci-dessous ne répond pas à votre question, n'est-ce pas? l'homme des cavernes explique ce qui se passe lorsqu'une interruption se produit, mais pas ce qui se passe lorsqu'une fonction est appelée dans un contexte interrompu. la réponse à ce dernier serait: rien de spécial, la fonction est appelée et c'est tout. la magie se produit lorsque l'interruption est déclenchée, ce qui se passe après (avant l'iret) est juste du code normal, généralement non interruptible.
Vladimir Cravero
@VladimirCravero oui (indirectement). Je parlais de la façon dont la pile a été modifiée pour un ISR, pensant qu'elle devait être modifiée pour utiliser les fonctions en premier lieu. Je vais deviner que les fonctions fonctionnent exactement de la même manière après la configuration de l'ISR.
Anonymous Penguin
eh bien, vous l'avez compris. après le saut vers le vecteur d'interruption, tout va bien et vous pouvez vous déplacer où vous voulez.
Vladimir Cravero

Réponses:

16

L'AVR est une architecture RISC, donc il a une gestion matérielle assez basique des interruptions. La plupart des processeurs jouent avec la pile pendant les interruptions, bien qu'il y en ait quelques-uns, notamment ARM et PowerPC, qui utilisent des méthodes différentes.

En tout cas, c'est ce que fait l'AVR pour les interruptions:

Lorsqu'une interruption se produit, le matériel du processeur effectue ces étapes, qui ne sont pas simplement un simple GOTO:

  1. Terminez l'instruction en cours.
  2. Désactivez l'indicateur d'interruption globale.
  3. Poussez l'adresse de l'instruction suivante sur la pile.
  4. Copiez l'adresse dans le vecteur d'interruption correct (en fonction de l'interruption survenue) dans le compteur de programme.

Maintenant, à ce stade, le matériel a fait tout ce qu'il va faire. Le logiciel doit être écrit correctement pour ne pas casser les choses. En règle générale, les étapes suivantes vont dans ce sens.

  1. Poussez le registre d'état sur la pile. (Cela doit être fait avant de le changer).

  2. Poussez tous les registres CPU qui seront (ou peuvent être) modifiés sur la pile. Les registres qui doivent être sauvegardés de cette manière sont définis par le modèle de programmation. Le modèle de programmation est défini par le compilateur.

Maintenant, le code d'interruption de travail peut être exécuté. Pour répondre au cas de la question d'appeler une fonction, il fait juste ce qu'il fait toujours, pousse la valeur de retour sur la pile, puis la fait revenir quand c'est fait. Cela n'affecte aucune de ces valeurs précédentes que nous avons enregistrées sur la pile jusqu'à présent.

  1. Exécutez le code de travail ISR.

Maintenant, nous avons terminé et voulons revenir de l'interruption. Nous devons d'abord faire le nettoyage du logiciel.

  1. Pop les registres CPU que nous avons poussés à l'étape 6.
  2. Remettez la valeur de statut enregistrée dans le registre de statut. Après cela, nous devons faire attention à ne pas exécuter d'instructions qui pourraient changer le registre d'état.
  3. Exécutez l'instruction RTI. Le matériel effectue ces étapes pour cette instruction:

    une. Activez l'indicateur d'interruption globale. (Notez qu'au moins une instruction doit être exécutée avant que la prochaine interruption ne soit honorée. Cela empêche les interruptions importantes de bloquer complètement le travail en arrière-plan.)

    b. Insérez l'adresse de retour enregistrée dans le PC.

Nous revenons maintenant au code normal.

Notez qu'il y a certains points où nous devons être très prudents, en particulier autour du registre d'état et de la sauvegarde des registres qui pourraient être modifiés. Heureusement, si vous utilisez un compilateur C, tout cela est géré sous les couvertures.

Vous devez également surveiller la profondeur de votre pile. À tout moment lorsque les interruptions sont activées, un ISR pourrait utiliser plus de la pile qu'il n'est évident en regardant le code local. Bien sûr, cela ne se produit vraiment que si vous poussez votre mémoire à ses limites.

Voici un lien décrivant ce processus si vous souhaitez une référence.

Homme des cavernes
la source
Quel est le but des étapes 5/6? Il me semble stupide de ne pas modifier directement les registres, même si je suppose que jouer avec certains registres pendant les interruptions pourrait créer des résultats désagréables.
Pingouin anonyme
1
Les étapes 5 et 6 enregistrent l'état actuel (avant interruption) du système, afin qu'il puisse être restauré (étapes 8 et 9) une fois l'interruption terminée, pour permettre au programme principal de continuer comme s'il n'avait pas été interrompu.
Peter Bennett
1
Ceci est un excellent résumé.
Connor Wolf
3
Il convient également de noter que si vous savez vraiment vraiment ce que vous faites, vous pouvez désactiver la sauvegarde automatique de l'état et d'autres registres, avec un indicateur GCC ( ISR_NAKED). Cela peut vous permettre de sauter les étapes 5, 6, 8, 9, dans un contexte où vous avez vraiment besoin de ces cycles. L'inconvénient est que vous devez être absolument certain que vous préserverez les registres pertinents ou que vous pourrez les remplacer sans danger.
Connor Wolf
2
C'est intéressant à savoir, mais je ferais de la programmation d'assemblage avant d'utiliser cet indicateur. Si dangereux ...
homme des cavernes