mercredi 25 juin 2014

LPC810, partie 7, les interruptions

Dans cet article je discute des interruptions sur les LPC81x. En fait le contrôleur d'interruption fait partie du coeur ARM Cortex M0+, donc son fonctionnement est le même sur tous les MCU qui utilise les CPU M0 et M0+.

Le contrôleur d'interruption

Dans le jargon de la compagnie ARM ce contrôleur s'appelle NVIC pour Nested Vector Interruptupt Controller. Comme son nom l'indique il s'agit d'un contrôleur multi-niveaux utilisant une table de vecteurs. Par multi-niveaux on entend qu'une interruption en cours peut-être interrompue par une autre interruption de priorité supérieure. Il y a 4 niveaux de priorités numérotées de 0 à 3. 0 étant la plus haute et 3 la plus basse.

Lorsqu'on crée un projet utilisant CMSIS_CORE_LPC8xx dans LPCXpresso, on retrouve dans le dossier src du projet un fichier appelé cr_startup_lpc8xx.c et à l'intérieur de celui-ci se trouve la déclaration de toutes les fonctions de gestions d'interruptions.

Comme on le voit il s'agit d'alias pour un gestionnaire par défaut qui contient une boucle while infinie. Donc si dans votre programme vous activez une interruption sans créer un gestionnaire pour celle-ci, lorsque cette interruption sera déclenchée votre programme va bloqué.

Pour créer un gestionnaire d'interruption il suffit de créer une fonction avec le nom du gestionnaire définie dans ce fichier. Par exemple le gestionnaire pour le périphérique MRT (Multi Rate Timer) s'appelle MRT_IRQHandler.

Utilisation d'une interruption

A titre d'exemple on va créer un projet MRT-multi-blink et utiliser le périphérique MRT pour faire clignoter 3 LEDs à des vitesses différentes l'une de l'autre. Ce projet va utiliser une interruption MRT_IRQHandler. Le MRT contient 4 minuteries et chacune d'elle peut-être programmée pour un délais différent. Chaque fois qu'un délais expire l'interruption est déclenchée. Le gestionnaire vérifie qu'elle canal du MRT a déclenché l'interruption et inverse l'état de la LED correspondante.

Créez un nouveau "C project" appelé "MRT-multi-blink" et utilisez la librairie CMSIS_CORE_LPC8xx. Copiez le code source suivant dans le fichier main.c.

Analyse du programme.

Ce programme utilise le signal d'horloge par défaut soit l'IRC sans PLL. Donc le CPU tourne à 12Mhz. Dans la fonction main on commence par désactiver les fonctions fixes ACMP_I1, ACMP_I2, CLKIN, SWCLK et SWDIO. Ces fonctions sont activées/désactivés par des bits dans le registre LPC_SYSCON->PINENABLE0. la macro m_disable_function simplifie cette configuration.

Par défaut les périphériques sur le bus AHB sont désactivés. On doit donc les activés dans le registre LPC_SYSCON->SYSAHBCLKCTRL. Ici on active le clock pour les GPIO et pour le MRT. Se sont les 2 périphériques que ce programme utilise.

À la ligne suivante on met les broches sur lesquelles les LEDs sont branchées en mode sortie en mettant les bits correspondants dans LPC_GPIO_PORT->DIR0 à la valeur 1. un bit à 0 dans ce registre correspond à une entrée.

Ensuite on configure les 3 canaux du MRT. Le registre STAT contient un bit indicateur d'interruption. Pour mettre ce bit à zéro il faut écrire un 1 dans le bit (ce n'est pas une erreur, mettre 1 pour réinitialiser). Le registre CTRL contient le bit d'activation/désactivation en position 0. et 2 bits de sélection du mode de fonctionnement en position 2:1. On active le canal en laissant le mode à zéro qui correspond au mode interruption répétitive. Dans ce mode une interruption est déclenchée lorsque le compteur arrive à zéro (le comptage est à rebours). La valeur initiale est rechargée automatiquement et le cycle recommence. On obtient donc une interruption à intervalle régulier.

Le compteur démarre au moment ou on inscris la valeur de l'intervalle désiré dans le registre INTVAL.

On programme ensuite la priorité d'interruption au plus bas niveau avec la fonction NVIC_SetPriority(). Finalement on active cette interruption avec la fonction NVIC_EnableIRQ().

Le gestionnaire d'interruption est très simple. On vérifie quels sont les canneaux qui ont l'indicateur d'interruption à 1 et pour ceux-ci, on inverse l'état de la sortie GPIO associé.

Pour en savoir plus sur l'interface de programmation des interruptions il faut lire le fichier d'entête core_cm0plus.h qui fait parti de la librairie CMSIS_CORE_LPC8xx.


Liens vers les articles précédents:

  1. Introduction au LPC810 (ARM M0+)
  2. LPC810, partie 2, anatomie
  3. LPC810, création d'un projet
  4. LPC810, partie 4, programmation
  5. LPC810, partie 5, module SCT et PWM
  6. LPC810, partie 6, system clock et PLL

Aucun commentaire:

Enregistrer un commentaire