Outils pour utilisateurs

Outils du site


msp430-interruption

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

msp430-interruption [2012/11/23 11:25]
bjonnh [Qu'est-ce qu'il y a sous le capot]
msp430-interruption [2015/01/28 03:09]
Ligne 1: Ligne 1:
-====== Les interruptions sur MSP430 ====== 
-<​note>​ 
- 
-Auteur: Bjonnh 
- 
-Licence: Creative Commons BY SA 3.0 [[http://​creativecommons.org/​licenses/​by-sa/​3.0/​fr/​]] 
-</​note>​ 
- 
-===== Principe ===== 
-Une interruption est un dispositif permettant d'​interrompre,​ suite à un évènement,​ le fonctionnement d'un programme pour exécuter une fonction spécifique à cet évènement. C'est ce qui permet d'​éviter d'​avoir à faire ce qu'on appelle du "​polling",​ consistant à vérifier en boucle dans le programme si une valeur à changé, ralentissant d'​autant le code, évitant au microcontrolleur de se mettre en veille et présentant le risque de rater un évènement si le programme était en train de faire autre chose. 
- 
-Un endroit spécifique de la mémoire contient ce que l'on appelle un vecteur d'​interruption contenant l'​adresse de la fonction quoi doit être exécutée quand l'​interruption se présente. 
- 
-Il existe 3 types d'​interruptions sur les MSP430: 
-  * Reset 
-  * Interruption non masquable (NMI) 
-  * Interruption masquable 
- 
-Le reset est une interruption spéciale, qui a une priorité sur toutes les autres. Par défaut le reset pointe vers l'​adresse de départ du programme, mais il est possible de changer cela afin d'​effectuer une action avant le reset effectif. Ou d'​utiliser le bouton reset pour faire autre chose. 
- 
-Les NMI ne sont pas gérées par le même système d'​interruption que les autres. Elles sont toutes désactivées automatiquement après l'​exécution d'une d'​entre elles et doivent être explicitement réactivées par l'​utilisateur. Le vecteur d'​interruption est situé à l'​adresse 0xFFFC. 
-Il existe trois sources d'​interruptions : 
-  * Une impulsion sur la broche !RST/​NMI ​ (!RST signifie que l'​entrée est active sur niveau bas) si elle est configurée ainsi. Son bit d'​activation est NMIIE. 
-  * Un problème d'​oscillateur. Son bit d'​activation est OFIE 
-  * Un problème d'​accès à la mémoire flash. Son bit d'​activation est ACCVIE. 
- 
-Les interruptions masquables sont produites par les différents périphériques internes et externes du MSP430. Ce sont celles qui nous intéressent ici. 
- 
-Contrairement à d'​autres microcontrolleurs tels que les ATMEGA 328, les MSP430 disposent d'​interruptions programmables sur chaque broche de PORT1 et PORT2. Ils sont configurés par 3 registres, PxIFG, PxIE et PxIES (avec x étant le numéro de port). ​ 
- 
-===== Les différents vecteurs ===== 
-Les différents vecteurs sont définis à partir de l'​adresse 0xFFE0. Attention les pointeurs de fonction sont définis sur un mot (deux octets). 
-|Interruption|Nom en C|Décalage|Position réelle| 
-| Port 1                    | PORT1_VECTOR ​      | 0x0004 | 0xFFE4 | 
-| Port 2                    | PORT2_VECTOR ​      | 0x0006 | 0xFFE6 | 
-| Convertisseur A/D         | ADC10_VECTOR ​      | 0x000A | 0xFFEA | 
-| USCI A0/B0 Transmission ​  | USCIAB0TX_VECTOR ​  | 0x000C | 0xFFEC | 
-| USCI A0/B0 Réception ​     | USCIAB0RX_VECTOR ​  | 0x000E | 0xFFEE | 
-| Timer0)A CC1, TA0         | TIMER0_A1_VECTOR ​  | 0x0010 | 0xFFF0 | 
-| Timer0_A CC0              | TIMER0_A0_VECTOR ​  | 0x0012 | 0xFFF2 | 
-| Timer du Watchdog ​        | WDT_VECTOR ​        | 0x0014 | 0xFFF4 | 
-| Comparateur A             | COMPARATORA_VECTOR | 0x0016 | 0xFFF6 | 
-| Timer1_A CC1-4, TA1       | TIMER1_VECTOR ​     | 0x0018 | 0xFFF8 | 
-| Timer1_A CC0              | TIMER1_A0_VECTOR ​  | 0x001A | 0xFFFA | 
-| NMI                       | NMI_VECTOR ​        | 0x001C | 0xFFFC | 
-| Reset [Priorité maximale] | RESET_VECTOR ​      | 0x001E | 0xFFFE | 
- 
- 
-On n'a pas besoin de s'​embêter avec la position réelle, la macro « interrupt(VECTOR) » contenue dans //​legacymsp430.h//​ permet de faire le calcul automatiquement. 
-Ainsi, on définit une fonction pour une interruption sur le PORT1, par : 
-<code c> 
-interrupt (PORT1_VECTOR) Nomdelafonction(void) 
-{ 
-// Corps de la fonction 
-} 
-</​code>​ 
-===== Les registres concernés ===== 
-==== PxIFG ==== 
-Ce registre est un registre drapeau, le bit correspondant à l'​entrée du port ayant déclenché une interruption est mis à 1 par le moteur d'​interruptions. Il peut aussi servir à déclencher des interruptions logicielles,​ c'est à dire que c'est l'​utilisateur qui place un bit à 1 dans ce registre pour déclencher l'​interruption. 
- 
-<note important>​Attention,​ pensez à remettre le bit correspondant à votre évènement de ce registre à 0 durant la fonction d'​interruption,​ sinon elle ne sera plus jamais déclenchée.</​note>​ 
-<note important>​Attention,​ le fait de changer le mode (entrée/​sortie) de la broche peut déclencher une interruption,​ il peut être plus sage de la désactiver avant.</​note>​ 
-==== PxIES ==== 
-Ce registre contrôle sur quel front est déclenchée l'​interruption. Si le bit est à 0, c'est une transition bas vers haut qui déclenche, et inversement pour 1. 
- 
-<note important>​Changer ce registre peut conduire à déclencher une interruption ! 
-|PxIESx|PxINx|PxIFGx| 
-|0→1|0|Peut être| 
-|0→1|1|Non changé| 
-|1→0|0|Non changé| 
-|1→0|1|Peut être| 
-</​note>​ 
- 
-==== PxIE ==== 
-Ce registre sert à contrôler si l'on souhaite utiliser les interruptions sur la broche correspondante. 
- 
-===== Réalisation ===== 
- 
-<code c> 
-#include <​msp430g2553.h>​ 
-#include <​legacymsp430.h>​ // nécessaire pour les interruptions 
- 
- 
-interrupt (PORT1_VECTOR) Port_1(void) // Façon de coder une fonction d'​interruption sur le PORT1 
-{ 
-  volatile int i; 
-  for (i = 0; i < 0x60; i++); // Petite pause pour l'​anti-rebond 
-  while (! (P1IN & BIT3)); // On attend que l'​utilisateur lache le bouton 
-  P1OUT ^= BIT6; // On inverse la led verte 
-  P1IFG &= ~BIT3; // On efface le drapeau pour permettre à l'​interruption d'​arriver à nouveau 
-} 
- 
-int main(void) { 
-  volatile int i; 
- 
-  // Arrêt du Watchdog 
-  WDTCTL = WDTPW | WDTHOLD; 
- 
-  // P1.0 et P1.6 en tant que sorties 
-  P1DIR = BIT0 | BIT6; 
-  // P1.0=0 et P1.6=1 ​ 
-  P1OUT = BIT3; // Il est nécessaire de mettre le registre de l'​entrée à 1 
-  P1REN = BIT3; // Et de mettre la résistance de pull-down 
-  
-  // Règle l'​interruption sur P1.3 
-  P1IE |= BIT3; // On souhaite surveiller P1.3 
-  P1IES |= BIT3; // Sur un front descendant 
-  P1IFG &= ~BIT3; // Effacer le registre drapeau 
-  _BIS_SR(GIE);​ // Lancer le module des interruptions 
- 
-  for (;;) { // Boucle infinie 
-    // inversion de la led rouge 
-     P1OUT ^= BIT0; 
-    // pause pour le clignotement 
-    for (i = 0; i < 0x6000; i++); 
-  } 
-} 
-</​code>​ 
- 
-===== Qu'​est-ce qu'il y a sous le capot ===== 
-Reprenons la définition de fonction d'​interruption:​ 
-<code c> 
-interrupt (PORT1_VECTOR) Nomdelafonction(void) 
-{ 
-// Corps de la fonction 
-} 
-</​code>​ 
- 
-Le code précédent est en fait transformé par le préprocesseur en : 
-<code c> 
-void __attribute__((interrupt ((0x0004)))) Nomdelafonction(void) 
-{ 
-// Corps de la fonction 
-} 
-</​code>​ 
- 
-//​__attribute__//​ est une fonction spéciale de gcc servant à donner au compilateur des informations sur la fonction. On peut indiquer beaucoup de choses, mais dans ce cas précis, on lui indique que cette fonction doit être placée au vecteur d'​interruption ayant un offset de 0x0004. 
-<​note>​À vérifier: Le compilateur connaît la position des vecteurs d'​interruption grâce au fichier //​memory.x//​ correspondant à l'​architecture. C'est pourquoi il est important de spécifier l'​option -mmcu de gcc correspondant exactement au composant utilisé.</​note>​ 
- 
-Le code assembleur généré par gcc (option -S) devient alors  
-<code asm> 
-.global Port_1 
- .type Port_1,​@function 
-/​*********************** 
- * Interrupt Vector 2 Service Routine `Port_1' ​ 
- ​***********************/​ 
-Port_1: 
-.global __isr_2 
-__isr_2: 
- // Reste de la fonction 
-</​code>​ 
-Ceci indique au compilateur ​ que la fonction est située à l'​adresse //​__isr_2//​. 
- 
-Ce code une fois compilé donne quand on utilise //​msp430-objdump -d// une fonction située à l'​adresse 0xc04c et une section //.vector// située à partir de l'​adresse 0xffe0, contenant à l'​adresse 0xffe4 (celle du vecteur d'​interruption de PORT1 vu dans le tableau précédent) la fonction 0xc04c. 
- 
-C'est ici l'​avantage du format ELF, permettant d'​indiquer la position d'une section en mémoire sans avoir à définir l'​intégralité de la mémoire. 
- 
-Ainsi le fichier avec des fonctions vides (main et Port1) sans informations de debug et compilé avec -Os fait 492 octets, alors que si il avait fallu définir la mémoire entière, il aurait fait 64K (Je donnerai plus de détails sur cette histoire de mémoire dans un autre article, en particulier pour expliquer comment une petite bête avec 16K de mémoire contient des adresses qui s'​étendent sur 64K). 
- 
-Il est possible de voir les différentes sections d'un fichier ELF avec l'​outil readelf -a. Qui nous donne la taille de chacune de ces sections. Ainsi on voit que même si le fichier fait 492 octets, finalement, la majorité des données est constituée par les métadonnées de ELF et les sections spéciales telles que les vecteurs. On ne peut donc pas juger de la taille réelle d'un programme par sa taille sur le disque. 
- 
-====== _BIS_SR(GIE) ??? ====== 
-Cette fonction est une macro, remplacée par : 
-<code c> 
-__bis_status_register((0x0008));​ 
-</​code>​ 
-Elle sert en fait à mettre à 1 dans le registre SR (Status register) les bits correspondants à son argument. 
- 
-La fonction __bic_status_register (ou _BIC_SR) sert à mettre cette valeur à 0. 
- 
-Le bit 3 du registre SR (16 bits) est appellé GIE (Global Interrupt Enable) et sert à lancer le moteur d'​interruptions. 
-===== Sources ===== 
-[[http://​justinstech.org/​2010/​09/​msp430-coding-interrupts-for-mspgcc/​|Justin'​s Tech - msp430- coding interrupts for mspgcc]] 
-[[http://​dbindner.freeshell.org/​msp430/​demo.html]] 
-[[http://​www.ti.com/​litv/​pdf/​slau144i|MSP430x2xx Family User's Guide (Rev. I)]] 
- 
-et man gcc ;) 
  
msp430-interruption.txt · Dernière modification: 2015/01/28 03:09 (modification externe)