TP99 : La tour de Hanoi en assembleur + Interruptions
Les interruptions
Pour implémenter les interactions avec le bouton, vous avez probablement lu son état dans une boucle et effectué une action lorsque cet état changeait. Cette méthode appelée “polling” est simple, mais elle est aussi limitée. Si un système doit faire plusieurs tâches et gérer plusieurs entrées, le “polling” devient vite contraignant et de plus, nous perdons beaucoup de temps à demander constamment l’état du bouton.
Une autre manière de réagir à la pression d’un bouton est d’utiliser les interruptions. Comme son nom l’indique, une interruption permet d’interrompre le programme principal pour exécuter une routine d’interruption liée à l’évènement qui a levé l’interruption. Cet évènement peut être la pression d’un bouton, mais ça peut aussi être une minuterie (timer) ou l’arrivée d’un caractère sur un port série (UART). Commençons par traiter la pression d’un bouton.
Pour configurer les interruptions produites par un bouton (externe au microcontrôleur) nous utilisons les modules exti (external interrupt)
et nvic (nested vectored interrupt controller). Dans votre programme, importez ces modules en plus de rcc :
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/stm32/exti.h>
#include <libopencm3/stm32/rcc.h>
Pour configurer le système, vous devez enclencher l’horloge de sysconfig :
rcc_periph_clock_enable(RCC_SYSCFG);
Il faut ensuite configurer les interruptions externes. Une restriction de notre microcontrôleur c’est qu’il ne peut avoir
qu’une seule interruption par numéro de pin du GPIO. Vous pouvez par exemple définir une interruption pour le port PG0
(GPIO G / pin 0) et une autre pour le port PF14 (GPIO F / pin 14), ou vous pouvez définir une interruption pour le port PG0
et une autre pour le port PG1, mais vous ne pouvez pas définir une interruption pour le port PA0
et une autre pour le port PG0 car ils utilisent tous les deux la pin 0.
Etudiez le chapitre 10.2 (page 231) du “Reference manual” (RM0402)
pour plus d’information concernant le module exti.
Configurez les modules exti et nvic avec les lignes suivantes en remplaçant <n> par le numéro de la pin et <x> par le port du GPIO :
exti_set_trigger(EXTI<n>, EXTI_TRIGGER_RISING);
exti_enable_request(EXTI<n>);
exti_select_source(EXTI<n>, GPIO<x>);
nvic_enable_irq(NVIC_EXTI<n>_IRQ);
Implémentez maintenant la procédure exti<n>_isr :
void exti<n>_isr(void)
{
exti_reset_request(EXTI<n>);
// Your code here
}
Cette procédure avec ce nom précis sera automatiquement appelée lorsque vous presserez le bouton.
La première ligne de cette procédure est exti_reset_request(EXTI<n>); et permet de quittancer le
traitement de l’interruption. Si vous ne le faites pas, le microcontrôleur ne saura pas que vous avez
réagi à l’évènement et continuera d’interrompre le programme.
Info
Nous avons vu que le système EXTI impose des limites sur l’affectation des pins aux
interruptions. Si une telle limit ne vous permet pas de réaliser votre projet, vous pouvez
alors utiliser la technique de polling périodique que nous avons vu dans un TP précédent.