Entrée-sorties
@loop ldr r0, 0x9234 % lecture de l'état des boutons
cmp r0, #1 % bouton 0 enfoncé ?
beq on % brancher vers l'allumage
cmp r0, #2 % bouton 1 enfoncé ?
beq off % brancher vers l'extinction
b loop % boucler
@on mov r0, #1 % allumage = mettre la bascule de la LED à 1
b output % brancher vers l'écriture
@off mov r0, #0 % extinction = mettre la bascule de la LED à 0
@output str r0, 0xABCD % écriture dans la bascule de la LED
b loop % boucler
- Le processeur passe son temps à scruter les entrées
- Il peut rater un appui sur un bouton
Interruptions
Scrutation (polling)
- Consultation périodique des entrées
- Prendrait plus de 100% du temps avec quelques périphériques
Exemple
- vous attendez un appel téléphonique
- votre portable est en mode silencieux
- vous devez regarder l'écran assez souvent
- vous risquez quand-même de rater l'appel
Interruptions
Avec interruptions
- vous attendez un appel téléphonique
- votre portable vibre ou sonne
- vous pouvez faire autre chose en attendant l'appel
- vous ne risquez pas de rater l'appel
Sur un ordinateur
- lors d'une demande d'interruption :
- l'exécution du programme est interrompue
- le processeur saute à une adresse particulière
pour traiter l'interruption
Interruptions
Conditions
- le traitement de l'interruption doit être transparent
pour le programme interrompu
- il faut sauvegarder le compteur ordinal
- ainsi que le registre d'état
- et les registres modifiés par le traitement de l'interruption
Exemple
cmp r1, r2 % SR <- N et Z en fonction de r1-r2
beq ok
- si une interruption survient entre ces instructions :
- si le SR est modifié, le branchement ne sera pas correct
- si r1 ou r2 sont modifiés, le programme n'aura pas
le bon comportement
Interruptions
Détection
- une interruption est provoquée par
le changement d'état d'un périphérique
- passage d'un signal de 0 à 1 ou vice-versa
- si le périphérique est configuré pour
générer une demande d'interruption
- il rend actif un signal d'entrée du processeur (patte IRQ)
Traitement
- à la fin de l'exécution de chaque instruction,
le processeur vérifie le signal IRQ
- s'il est actif et que les interruptions sont autorisées
- il sauvegarde le PC et le SR
- il charge le PC avec une adresse prédéterminée
(vecteur d'interruption)
Interruptions
Dans la pratique
- il est rare de travailler sur un processeur nu
- on utilise généralement un système d'exploitation
- ou un moniteur qui fournit des services :
- pour activer ou désactiver les interruptions
- pour configurer la génération d'une demande d'interruption
quand un signal change de niveau (ligne d'interruption)
- pour indiquer le code qui traitera cette interruption
- le système se charge de sauvegarder tout ce qui doit l'être
Avec MicroPython
- on dispose de 22 lignes d'interruptions
- 16 proviennent des pattes d'entrées-sorties
- 6 sont liées à des sources internes à la carte
Interruptions
Exemple avec MicroPython
import pyb
def traitement(l):
print("Interruption sur ", l)
ligne = pyb.ExtInt(
pyb.Pin("X17"), # bouton USR
pyb.ExtInt.IRQ_FALLING, # front descendant
pyb.Pin.PULL_UP, # signal haut par défaut
traitement # fonction à appeler
)
pyb.enable_irq(True) # interruptions autorisées
À chaque passage à 0 de la patte X17, la fonction traitement
sera appelée et affichera un message
Timers
- un timer est un périphérique muni d'un compteur
qui est décrémenté à chaque impulsion d'une horloge
- lorsque le compteur atteint 0,
il génère une demande d'interruption
- en chargeant le compteur avec une valeur initiale adéquate,
on peut être interrompu lorsqu'un certain délai expire
Timers
Avec MicroPython
import pyb
def clignote(t):
pyb.LED(1).toggle()
timer = pyb.Timer(4, freq=1, callback=clignote)
- la LED 1 (rouge) de la carte s'allumera et s'éteindra chaque seconde
- MicroPython se charge de calculer la valeur initiale du compteur
pour obtenir la fréquence voulue
- il se charge également d'activer la génération d'interruptions pour le
timer et d'enregistrer notre fonction pour traiter cette interruption
À faire en BE !