Les interruptions dans AVR peuvent être réalisées par des compteurs, des interfaces de communication, le convertisseur analogique-numérique, le comparateur, des broches d'entrée-sortie spéciales et plusieurs autres fonctions, selon le contrôleur. Chaque interruption peut être activée ou désactivée par l'unité qui la réalise. Bien que l'interruption puisse être activée ou désactivée, il y a un champ de 1 bit (le signal d'interruption) dans l'unité correspondante du contrôleur, qui est marqué comme vrai quand la condition interrompant est accomplie. Si le signal d'interruption prend la valeur vrai et que l'interruption est activée, le contrôleur commence à exécuter le code indiqué pour l'interruption.
Chaque interruption dans le micro-contrôleur AVR est liée à un événement spécifique. Chaque événement a un bit signal dans le registre de statut, qui marque l'apparition de l'événement. Les événements sont aussi liés pour interrompre des registres de masque et les bits correspondants. Si le bit événement interruption est laissé unmasked et un événement arrive, le processeur met en pause l'exécution du programme actif pendant quelques cycles et commence à exécuter le programme d'interruption. Après que le programme d'interruption a été exécuté, le processeur reprend l'exécution du programme principal.
Exemple
Pour utiliser des interruptions avec la librairie LibC de l'AVR, il faut ajouter la fonction interrupt.h
. La partie de code qui doit être exécuté pendant l'interruption se trouve après le mot clé “ISR”. Le texte entre parenthèses après “ISR” est le nom de l'interruption. Exemple en langage C:
#include <avr/interrupt.h> ISR(XXX_vect) { // Do something }
Globalement on utilise les interruptions pour contrôler le registre SREG. L'option pour permettre ou interrompre toutes les interruptions est là pour aider à protéger les données. Puisque l'interruption perturbent l'exécution du programme principal, quelques données utilisées selon le programme principal peuvent être dérangées ou corrompues dans le processus. Les situations comme cela peuvent être évitées en rejetant simplement toute interruption avant de traiter avec de telles données délicates. Rejeter une interruption est assez facile, cela peut être réalisé en changeant simplement un registre (SREG). Après l'exécution la partie critique du programme, l'interruption peut facilement être admise de nouveau et toute interruption dont on aurait besoin pourrait alors être exécutée.
Exemple
Supposons que nous utilisons une variable de 16 bits dans le programme, cette variable peut à la fois être modifiée par le programme principal ou par l'interruption. La valeur de la variable et ensuite affectée à une seconde variable:
#include <avr/interrupt.h> // Global 16-bit variables x and y unsigned short x, y; // A random interrupt that changes the value of x ISR(XXX_vect) { x = 0x3333; } int main() { // Give a value to x x = 0x1111; // Allow interrupts globally sei(); // Give the value of x to y y = x; }
Le programme en lui-même est assez simple - dans un premier temps on affecte la valeur 0x1111 à la variable x, puis cette valeur est affectée à la variable y. Si l'interruption est exécutée entre ces deux opérations, la valeur de x change et prend la valeur de 0x3333. Logiquement, la variable y pourrait avoir deux valeurs possibles à la fin du programme, mais avec un AVR 8 bits il existe une troisième option. Tout cela parce que l'architecture en 8 bits nécessite 2 cycles pour affecter une donnée de 16 bits et par conséquent une interruption mal tombée pourrait corrompre l'intégrité de la valeur de la variable. En conséquence, on peut obtenir les valeurs de 0x1111 ou de 0x3333, mais on peut aussi à la fin du programme obtenir la valeur de 0x3311. Pour éviter d'avoir cette troisième valeur, toutes les interruptions doivent être temporairement désactivées afin de réaliser les opérations qui nécessitent plus d'un cycle.
Dans l'exemple suivant, la valeur de la variable x est affectée à la variable y en utilisant la méthode de sauvegarde de donnée:
// Disallow interrupts globally cli(); // Give the value of x to y y = x; // Re-allow all interrupts again sei();