TP01
TP01
TP01
1 Objectif
1. Manipuler les API destinées aux GPIO,
2. Gérer les interruptions,
3. Configurer le NVIC.
2 Principe
Une interruption matérielle (en anglais Interrupt ReQuest ou IRQ) est une interruption déclenchée par
un périphérique d'entrée-sortie d'un microprocesseur ou d'un microcontrôleur.
Les interruptions matérielles sont utilisées en informatique lorsqu’il est nécessaire de réagir en temps
réel à un événement asynchrone, ou bien, de manière plus générale, afin d’économiser le temps
d’exécution lié à une boucle de consultation (polling loop).
1. Une interruption peut être activée d’une manière asynchrone au déroulement du programme
principal. Ici symbolisée par un éclair jaune sur la figure,
2. Après sauvegarde de contexte le processeur passe en mode exception et exécute la fonction
qui correspond à l’exception activée (une interruption est une exception). Le processeur
récupère l’adresse de la fonction « handler » à partir du « vector table » qui contient les
adresses des fonctions qui gèrent toutes les exceptions software et matérielles.
3. Une fois l’interruption est servie, il y a restauration de contexte,
4. Retour au programme principal.
Le processeur Cortex ARM contient un composant nommé « Nested Vectored Interrupt Controller
(NVIC) ». Il supporte jusqu’à 240 interruptions. Il offre 255 niveaux de priorités programmables de
0 à 255 avec 255 la priorité la plus faible. Les priorités sont hiérarchisées en deux groupes. Un
premier groupe de priorité de 0 à 15. De la même manière chacun de ces groupes contient un
sous-groupe de priorité de 0 à 15. Le NVIC est sensible aux niveaux de tensions et aux différents
fronts, montant ou descendant.
Le travail demandé dans ce TP permettra de tester une solution avec polling pour commander une
diode LED avec un bouton utilisateur puis avec une solution basée sur une interruption hardware.
Dans la troisième partie le NVIC sera programmé pour donner deux priorités différentes au bouton
utilisateur et au « system tick handler » responsable d’incrémenter le « system tick counter »
chaque 1 ms.
3 Création d’un projet
1. Suivre les mêmes étapes du TP initiation aux GPIO pour créer un projet,
2. Sélectionner sous le menu « Project » -> « Manage » -> « Run-Time Environment »,
sélectionner « LED API » et « Button API » et il est important de préciser la board « STM32F4-
Discovery » (voir figure suivante).
Cliquer sur « Resolve » et cocher « Classic » sous « STM32Cube Framework (API) » puis sur
« OK ».
3. Suivre les mêmes étapes du TP initiation aux GPIO pour ajouter les dossiers « sources » et
« headers », ajouter les fichiers « main.c » , « main.h », «stm32f4xx_it.c » et «stm32f4xx_it.h »
4. Cliquer sur l’icône « options for target » , ensuite sur l’onglet « Debug » afin de
configurer les options de la carte cible sur laquelle le programme sera exécuté. Cette fenêtre
fait apparaître deux options de test : par simulation (à gauche), ou par émulation (à droite), en
utilisant la carte STM32F407VG. Selectionner l’option émulation (à droite), cocher le bouton
« use » et sélectionner « ST-Link Debugger ».
Cliquer sur le bouton « Settings » et vérifier, sous l’onglet « Debug », que le port utilisé et de type
« SW », sinon le changer.
Cliquer sur l’onglet « Flash Download » de la même fenêtre, et vérifier que la taille de la mémoire Flash
de la cible est de 1 M on Chip.
Cliquer sur l’onglet C/C++ et ajouter le macro « HSE_VALUE=8000000 » qui indique la fréquence du
Crystal installé sur la carte à la fonction « SystemClock_Config(); » qui se trouve par défaut dans le
« Template » du « main.c »
Cliquer sur « OK » pour valider les options de configuration du Debugger choisies.
Re-cliquer sur l’icône « options for target » , ensuite sur l’onglet « Debug ». Cliquer sur « Settings »
puis « Trace » changer la fréquence « Core Clock » à 168MHz et cocher la case « Trace Enable » puis
sur « OK ».
1. Au niveau de la ligne 109 du fichier « main.c » ajouter l’appel des fonction suivantes :
« Buttons_Initialize() » et « LED_Initialize() ». Ceci permettra ensuite l’utilisation des LEDs et
du Bouton utilisateur de la carte d’évaluation.
2. A l’aide d’une boucle infinie dans le fichier « main.c » tester la valeur du bouton utilisateur
puis inverser l’état de la LED0. Identifier dans le fichier « Buttons_F4Discovery.c » la fonction
qui retourne la valeur du bouton utilisateur.
Remarquer qu’avec cette solution le processeur est entièrement dédié à la lecture de l’état de la
pine relative au bouton utilisateur. Ceci est un gaspillage des cycles processeur et c’est pour cela
on se propose d’utiliser une solution avec interruption dans la partie 2.
3. Choisir le bon paramètre pour configurer la pine PA0 en mode interruption sur front montant.
En changeant le mode «GPIO_MODE_INPUT » par « GPIO_MODE_IT_RISING » définis dans le
fichier « stm32F4ww_hal_gpio.h ».
4. Ouvrir le fichier « stm32F4xx_it.c » , lire attentivement le commentaire qui se trouve à la ligne
176. Puis aller sur le fichier indiqué par le commentaire et ajouter une fonction vide avec la
signature adéquate pour gérer l’interruption du bouton PA0. Noter bien que les interruptions
générées par les GPIO sont considérées comme des interruptions Externes et que toutes les
pines du même index sont connectées à la même ligne d’interruption.
5. Ouvrir l’onglet « {}function » trouver la fonction du driver HAL qui gère les interruptions des
GPIOs et faire appel à cette fonction dans le corps de celle créée au point 4.
10. Complier et charger le programme dans la carte. Appuyer sur le bouton Reset (bouton noir).
Vérifier que la LED1 (Led orangée ) clignote et que le bouton utilisateur (bouton bleu)
permet de changer l’état de la LED0 (Led verte).
11. Ajouter une temporisation de 5ms dans la fonction « void HAL_GPIO_EXTI_Callback(uint16_t
GPIO_Pin); ». re-exécuter le programme. Appuyer sur le bouton et constater.
12. En effet, le programme arrête de tourner car les priorités de l’interruption du bouton
utilisateur et de l’interruption qui incrémente le compteur « system tick » (voir la fonction
« SysTick_Handler » à la ligne 170 du fichier « stm32F4xx_it.c ») n’ont pas été modifiées pour
donner la priorité à l’incrémentation du temps par rapport au bouton utilisateur.
Ajouter les deux lignes suivantes juste après l’activation de l’interruption du bouton
utilisateur :
HAL_NVIC_SetPriority(EXTI0_IRQn,15,15);
HAL_NVIC_SetPriority(SysTick_IRQn, 14 ,0);
En effet, ceci permet de donner une priorité supérieure à l’incrémentation du temps par
rapport à l’interruption du bouton.
13. Re-exécuter le programme et vérifier que le programme continue à tourner malgré l’appel de
la fonction « HAL_Delay() » dans la fonction call-back.
Les boutons poussoirs peuvent engendrer des rebondissements électriques à l’entrée de la pine (voir
figure suivante)
Pour éviter ce problème on va ajouter un filtre de temps pour ne considérer que les impulsions dont
la durée est supérieure à 20ms.
6. Exécuter le programme en appuyant sur la touche F5. Vérifier que la LED1 (Led orangée )
clignote et que le bouton utilisateur (bouton bleu) permet de changer l’état de la LED0 (Led
verte) si la durée de l’impulsion est supérieure à 20ms. La durée de l’impulsion peut être
observée sur le « logic Analyzer ».