0% ont trouvé ce document utile (0 vote)
67 vues48 pages

Cours 2

Ce document décrit trois méthodes pour gérer les entrées sur les microcontrôleurs: la scrutation, les interruptions et le DMA. Il explique ensuite comment configurer les interruptions matérielles provenant des GPIOs sur les microcontrôleurs STM32 via l'EXTI et le NVIC.

Transféré par

fotsoarole
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
67 vues48 pages

Cours 2

Ce document décrit trois méthodes pour gérer les entrées sur les microcontrôleurs: la scrutation, les interruptions et le DMA. Il explique ensuite comment configurer les interruptions matérielles provenant des GPIOs sur les microcontrôleurs STM32 via l'EXTI et le NVIC.

Transféré par

fotsoarole
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Aspects avancés sur la gestion des E/S

+
Ecriture des pilotes des périphériques

CHIRAZ TRABELSI

[email protected]

SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2


Lecture des entrées

• Trois principales méthodes pour prendre en compte le changement d’état des entrées (exemple appui sur un
bouton)

1) La scrutation (polling)
• Scruter l’état de l’Entrée
• Exemple sur Ordinateur: Pour savoir si l’utilisateur a tapé un caractère, le processeur surveille le
registre d’état du clavier
• Exemple sur Arduino: un programme qui allume la LED quand le bouton est relâché et l’éteint
quand le bouton est appuyé
Scrutation de l’état
du bouton dans une
boucle

2
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Lecture des entrées

• Inconvénients de la scrutation

• Le temps de scrutation peut avoir un impact non négligeable sur le temps d’exécution du
programme qui fait d’autres tâches non liées au changement de l’entrée

• Si les autres tâches durent assez longtemps et que le signal à observer change très vite,
on peut rater des changements de valeurs

• Solution: on laisse le programme faire ses tâches normalement et on ne l’interrompt que


lorsque l’entrée a changé d’état  utilisation des interruptions

3
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Lecture des entrées
• Trois principales méthodes pour prendre en compte le
changement d’état des entrées (exemple appui sur un bouton)
2) Les interruptions
• L’Entrée génère une interruption
• Le contrôleur d’interruption met le processeur au courant de
l’interruption
• Le processeur interrompt ce qu’il était en train d’exécuter
• S’il y a une routine d’interruption (Interrupt Service Routine -
ISR), le processeur l’exécute
• A la fin de l’exécution de l’ISR, le processeur reprend ce instruction1
qu’il était en train d’exécuter ISR:
int main(){ instruction2 Gestionnaire _clavier
Instruction1;
Instruction2; instruction3 printf(« interruption… »);
Instruction3;
Instruction4;
Instruction5;
Arrivée d’une instruction4 lire ….
Instruction6; interruption
Instruction7;
....
printf(«caractere ….);
}
//ISR exécutée quand un bouton est appuyé instruction5 return
int gestionnaire_clavier()
{printf (“interruption clavier”); instruction6
char c= Lire(registre des donnees du clavier);
printf(“caractere lu=%c\n”,c);} instruction7 4
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Lecture des entrées
• Trois principales méthodes pour prendre en compte le changement d’état des entrées
3) Le DMA (Direct Memory Access)
• Ce mode de communication permet de transférer les données de l’Entrée directement à la mémoire
sans passer par le processeur
• L’objectif est d’accélérer le programme en libérant le processeur de cette tâche
• Exemple:
• Le processeur veut récupérer les images de la caméra (en streaming) et y appliquer un traitement
(filtrage, tracking d’objets, etc.)
• 1ère solution: sans DMA
• Le processeur doit envoyer des commandes à la caméra, récupérer les images et les stocker
dans la mémoire

Transfert de Transfert de
Caméra données CPU données Mémoire

5
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Lecture des entrées
• Trois principales méthodes pour prendre en compte le changement d’état des entrées
3) Le DMA (Direct Memory Access)

• 2ème solution: avec DMA


• Le processeur lance une commande CPU
DMA au contrôleur DMA
• Le contrôleur DMA récupère les images Instruction Notification
de lancement de fin du
de la caméra et les stocke directement du DMA DMA
dans la mémoire sans « déranger le Caméra Contrôleur Mémoire
processeur » DMA
• Le processeur entre temps peut accéder à Transfert de Transfert de
données données
la mémoire pour appliquer des
traitements sur les images précédentes

• Avantage: accélérer l’exécution en


libérant le processeur de certains
transferts de données pour qu’il puisse
faire d’autres tâches
6
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Les interruptions sur les GPIOs

• Le NVIC (Nested vectored interrupt controller) gère les exceptions/interruptions


• Les exceptions ont deux types:
• Matérielles: asynchrones, appelées souvent interruptions, envoyées par le matériel au NVIC
• Exemples: débordement d’un timer, appui sur un bouton, etc.
• Logicielles: synchrones, appelées souvent exceptions, envoyées par le processeur au NVIC
• Exemples: division par zéro, appel d’un service de l’OS, évènement lors du debug, etc.
7
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Les interruptions sur les GPIOs

• Pour les interruptions provenant des entrées/sorties GPIO, il faut passer par l’EXTI
(Extended interrupt and event controller) qui offre 16 canaux (0 à 15) pour gérer les
interruptions sur les GPIOs

8
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Les interruptions sur les GPIOs

• Utilisation des interruptions


• Chaque interruption a son vecteur d’interruption (une adresse de l’instruction à exécuter si
l’interruption en question se produit)

Exemple: Si on appuie sur le bouton


Reset, c’est le code à l’adresse
0x0000 0004 qui sera exécuté

Source : RM0367 Reference manual -- Ultra-low-power STM32L0x3 advanced ARM®-based 32-bit MCUs 9
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Les interruptions sur les GPIOs
• Utilisation des interruptions

En plus des 16 interruptions de base du


microcontrôleur (en gris),
Il y a 39 autres canaux d’interruption gérés par le
NVIC (Nested vectored interrupt controller )

C’est le module NVIC qui permet de gérer des


interruptions provenant des boutons, des
timers, des communications série, etc.

Les vecteurs d’interruption pour les GPIOs

Source : RM0367 Reference manual -- Ultra-low-power STM32L0x3 advanced ARM®-based 32-bit MCUs 10
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Les interruptions sur les GPIOs

l’EXTI (Extended interrupt and event controller) gère


les interruptions sur les GPIOs par 3 vecteurs
d’interruptions
• Un vecteur pour les pins dont les numéros sont
entre 0 et 1(PA0, PA1, PB0, PB1, etc.)
• Un vecteur pour les pins dont les numéros sont
entre 3 et 2
• Un vecteur pour les pins dont les numéros sont
entre 4 et 15

 On ne peut pas configurer deux pins ayant le


même numéro (ex: PA0 et PB0) par interruption en
Source : RM0367 Reference manual -- Ultra-low-power STM32L0x3 advanced ARM®-based 32-bit MCUs
même temps
 en entrant dans un gestionnaire (handler), il faut
vérifier le numéro du canal source d’interruption

11
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Les temporisateurs matériels (Timers)
• Utilisation des interruptions
• Pour les projets sous STM32CubeIDE, les vecteurs d’interruptions sont disponibles dans le fichier
startup/startup_stm32l053r8tx.s

Exemple: pour une interruption générée par une


g_pfnVectors:
.word _estack GPIO géré par EXTI0_1, c’est la routine
.word Reset_Handler EXTI0_1_IRQHandler
………. qui sera utilisée
.word SysTick_Handler
……….
.word EXTI0_1_IRQHandler /* EXTI Line 0 and 1 */
.word EXTI2_3_IRQHandler /* EXTI Line 2 and 3 */
.word EXTI4_15_IRQHandler /* EXTI Line 4 to 15 */
…………
.word TIM2_IRQHandler /* TIM2 */
.word 0 /* Reserved */
.word TIM6_DAC_IRQHandler /* TIM6 and DAC */
.word 0 /* Reserved */
.word 0 /* Reserved */
.word TIM21_IRQHandler /* TIM21 */
.word 0 /* Reserved */
.word TIM22_IRQHandler /* TIM22 */
…………
12
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Les interruptions sur les GPIOs

• Pour travailler avec une interruption provenant d’un bouton, il faut:


1) Choisir la pin sur la quelle on veut travailler, exemple: PB12

2) Le contrôleur EXTI est configurable en agissant sur des registres du System configuration controller
(SYSCFG)
• Il faut activer l’horloge pour le SYSCFG
RCC->APB2ENR|=1; //active l’horloge pour SYSCFG (connecté sur le bus APB2)

Source : RM0367 Reference manual -- Ultra-low-power STM32L0x3 advanced ARM®-based 32-bit MCUs 13
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Les interruptions sur les GPIOs

• Pour travailler avec une interruption provenant d’un bouton, il faut:


3) Préciser le canal de l’interruption en agissant sur des registres du System configuration controller
(SYSCFG)
• Il faut configurer le registre EXTICRx (déterminer le registre à modifier parmi les 4 registres
disponibles) (exemple: pour PB12  il faut sélectionner EXTI12  registre EXTI4)
Source : RM0367 Reference manual -- Ultra-low-power STM32L0x3 advanced ARM®-based 32-bit MCUs

…….

//PB12 --> il faut configurer EXTICR4 (EXTICR[3]) avec la valeur 0001


SYSCFG->EXTICR[3]|=0b0001; 14
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Les interruptions sur les GPIOs

• Pour travailler avec une interruption provenant d’un bouton, il faut:


4) Dire que l’interruption ne sera pas masquée (sera traitée si elle se produit)
• Exemple: pour un bouton connecté à PB12
EXTI->IMR|=(1<<12); //activation d'EXTI12

Source : RM0367 Reference manual -- Ultra-low-power STM32L0x3 advanced ARM®-based 32-bit MCUs
15
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Les interruptions sur les GPIOs

• Pour travailler avec une interruption provenant d’un bouton, il faut:


5) Choisir le type d’évènement déclencheur de l’interruption
• Deux cas: front montant, front descendant
Exemple:
EXTI->RTSR|=(1<<12); /*activation de l'interruption sur front montant d'EXTI12*/

Source : RM0367 Reference manual -- Ultra-low-power STM32L0x3 advanced ARM®-based 32-bit MCUs
16
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Les interruptions sur les GPIOs

• Pour travailler avec une interruption provenant d’un bouton, il faut:

6) Attacher l’interruption à un vecteur du NVIC


• Exemple: pour PB12, il s’agit du vecteur EXTI[15:4]
NVIC_EnableIRQ(EXTI4_15_IRQn);

Source : RM0367 Reference manual -- Ultra-low-power STM32L0x3 advanced ARM®-based 32-bit MCUs
17
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Les interruptions sur les GPIOs

• Pour travailler avec une interruption provenant d’un bouton, il faut:

7) Ecrire le code qui sera exécuté si l’interruption se produit


void EXTI4_15_IRQHandler(){

//si l’interruption est produite par PB12


if ( EXTI->PR&(1<<12)){

GPIOA->ODR^=(1<<5);//exemple de traitement en cas


//d’interruption

//il ne faut pas oublier de réinitialiser le flag


EXTI->PR|=(1<<12);
}
}

• Si une interruption sur la pin PB12 se produit, la


position 12 du registre PR d’EXTI se met
automatiquement à 1

• Une fois l’interruption traitée, il faut remettre la


position 12 du registre PR à 0, pour cela, il faut y Source : RM0367 Reference manual -- Ultra-low-power STM32L0x3 advanced ARM®-based 32-bit MCUs
écrire 1 (voir l’extrait d manuel à droite) 18
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Les interruptions sur les GPIOs
• Exemple: Changement de l’état d’une led par interruption
A chaque appui sur le bouton sur PB12, la led sur PA7 changera d’état
#include "STM32l053xx.h" /*configuration de PB12 comme entrée en pull-down*/
void EXTI4_15_IRQHandler(){ …..
//si l’interruption est produite par PB12 //enable clock for SYSCF
if ( EXTI->PR&(1<<12)){ RCC->APB2ENR|=RCC_APB2ENR_SYSCFGEN;
GPIOA->ODR^=(1<<7); /*activation de l'interruption externe sur PB12*/
//il ne faut pas oublier de réinitialiser le flag SYSCFG->EXTICR[3]|=0b0001;
EXTI->PR|=(1<<12);
} EXTI->IMR|=(1<<12); //activation d'EXTI12
} EXTI->RTSR|=(1<<12); /*activation de l'interruption
sur front montant d'EXTI12*/
int main(void)
{ /*Attacher l’interruption à un vecteur du NVIC*/
//configuration de la fréquence à 16MHz NVIC_EnableIRQ(EXTI4_15_IRQn);
….
/*configuration de PA7 comme sortie*/ while(1)
… {}

19
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Les priorités des interruptions

• Les valeurs de priorités les plus petites


correspondent aux priorités les plus hautes

• Certaines interruptions ont des priorités fixes.


C’est le cas du reset qui est l’interruption la plus
prioritaire.
Source : RM0367 Reference manual -- Ultra-low-power STM32L0x3 advanced ARM®-based 32-bit MCUs

20
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Les priorités des interruptions
• Changement de la priorité d’une interruption

NVIC_SetPriority(EXTI4_15_IRQn,0);

• Si on utilise le niveau de priorité 0 pour une


interruption, on lui donne la plus grande priorité
derrière les trois interruptions les plus prioritaires

Source : RM0367 Reference manual -- Ultra-low-power STM32L0x3 advanced ARM®-based 32-bit MCUs

21
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Les priorités des interruptions
• Gestion des interruptions en cours
• 1er cas: priorités différentes

NVIC_SetPriority(EXTI0_1_IRQn,1);
NVIC_SetPriority(EXTI2_3_IRQn,0);
• EXTI2_3_IRQn ayant la plus haute priorité, si
EXTI0_1_IRQn et EXTI2_3_IRQn se déclenchent au
même moment, c’est EXTI2_3_IRQn qui sera traitée en
premier

• Si le processeur était en train d’exécuter le code du


EXI0_1_IRQHandler() et que l’interruption
EXI2_3_IRQn se déclenche, il sera interrompu pour
exécuter le code du EXI2_3_IRQHandler() et sera
repris par la suite

22 32-bit MCUs
Source : RM0367 Reference manual -- Ultra-low-power STM32L0x3 advanced ARM®-based
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Les priorités des interruptions
• Gestion des interruptions en cours
• 2ème cas: même priorité

NVIC_SetPriority(EXTI0_1_IRQn,0);
NVIC_SetPriority(EXTI2_3_IRQn,0);
• Ayant la même priorité, si EXTI0_1_IRQn et
EXTI2_3_IRQn se déclenchent au même moment, c’est
l’interruption ayant le plus petit numéro
(EXTI0_1_IRQn) qui sera traitée en premier

• Si le processeur était en train d’exécuter le code du


EXTI2_3_IRQHandler() et que l’interruption
EXTI0_1_IRQn se déclenche, il ne sera pas interrompu
puisqu’il s’agit d’une interruption de la même priorité
(même si EXTI0_1 a un numéro plus petit).
L’interruption EXTI0_1_IRQn attend alors la fin du
EXTI2_3_IRQHandler() pour être traitée

23 32-bit MCUs
Source : RM0367 Reference manual -- Ultra-low-power STM32L0x3 advanced ARM®-based
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Limites de la gestion par interruption

• Gestion des flux des données


• Que faire si le CPU est déjà engagé avec le convertisseur analogique/numérique CAN qui fait des
conversions à partir d’un capteur analogique pour un certain laps de temps, et qu’entre temps, il reçoit
une interruption de l’UART (universal asynchronous receiver-transmitter, exemples: clavier, bluetooth,
etc.) lui indiquant qu’il vient de recevoir une donnée à traiter?

• Problème: il faut à la fois ne pas perdre les données envoyées par l’UART et traiter toutes les données
du CAN pour ce laps de temps.
Microcontrôleur

Capteur 1
analogique CAN CPU

NVIC
2 Mémoire
Clavier/Bluetooth UART

24
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Limites de la gestion par interruption

• Problème: il faut à la fois ne pas perdre les données envoyées par l’UART et traiter toutes les données du
CAN pour ce laps de temps.
• Solution1: augmenter la priorité de l’une des interruptions
 Risque: on perd des données venant de celui ayant la plus basse priorité

Microcontrôleur

Capteur 1
analogique CAN CPU

NVIC
2 Mémoire
Clavier/Bluetooth UART

25
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Limites de la gestion par interruption

• Problème: il faut à la fois ne pas perdre les données envoyées par l’UART et traiter toutes les données du
CAN pour ce laps de temps.
• Solution2: utiliser un DMA (Direct Access Memory)
 Avec le DMA, l’UART peut transférer ses données à la mémoire sans intervention du CPU. De
cette façon, le CPU peut continuer à gérer le CAN pour traiter par la suite les données de l’UART à
partir de la mémoire
Microcontrôleur

Capteur 1
analogique CAN CPU

NVIC
Mémoire
2
Clavier/Bluetooth UART DMA

26
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Le DMA (Direct Memory Access)

• Autre utilisation du DMA: accélération du traitement sur un stream de données

• Exemple:
• Le processeur veut récupérer les images de la caméra (en streaming) et y appliquer un traitement (filtrage,
tracking d’objets, etc.)

• Le CPU établit le lien entre le DMA et la caméra


CPU
• Le contrôleur DMA récupère les images de la caméra et
les stocke directement dans la mémoire sans « déranger Instruction
le processeur » de lancement
du DMA
• Le processeur entre temps peut accéder à la mémoire Caméra Contrôleur Mémoire
pour appliquer des traitements sur les images DMA
précédentes Transfert de Transfert de
données données

27
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Le DMA (Direct Memory Access)

• Sans le DMA
• Le CPU lit les données à partir des
registres du périphérique puis les stocke
dans la mémoire
• Avec le DMA
• Le contrôleur DMA lit les données à partir
des registres du périphérique puis les
stocke dans la mémoire sans
l’intervention du CPU

Source : RM0367 Reference manual -- Ultra-low-power STM32L0x3 advanced ARM®-based 32-bit MCUs

28
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Comparaison des modes de gestion des entrées sorties

• La gestion par interruption présente des avantages par rapport à la scrutation:


• Gain de temps en évitant de vérifier continuellement l’état du périphérique

• Inconvénients des interruptions


• Le temps nécessaire pour traiter les interruptions peut avoir un impact non négligeable sur la
performance si le nombre d’interruptions/ de périphériques augmente

• Avantage du DMA
• Libère le CPU de certaines tâches
• Evite que le CPU soit interrompu très souvent
• Plus de performance

• Inconvénients du DMA
• Un système plus complexe
• Plus de consommation d’énergie

29
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Les pilotes de périphériques

• Pour communiquer avec une E/S, le microprocesseur/microcontrôleur


passe par une interface/contrôleur d’E/S (sur la même puce que le CPU
pour un microcontrôleur)

• Composition d’un contrôleur


• 3 types de registres
• Données: les données échangées entre le bus et le
périphériques transitent par ces registres
• Etat: indique l’état du périphérique (réception d’une
donnée, la transmission a pris fin, etc.)
• Commande/contrôle: permettent au processeur de
configurer et de contrôler les périphériques (activer la
réception/transmission, configurer la vitesse de
transmission, etc.)
• Communication avec le processeur
• Du point de vue du processeur, un périphérique est un ensemble
de registres (données, état et contrôle) qu’il peut lire ou écrire
pour communiquer
• Le logiciel qui communique avec le contrôleur est appelé pilote
 le pilote est le logiciel qui communique avec les trois types de 30
registres SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Ecriture de pilote de périphérique

• Pour faciliter l’interfaçage avec un périphérique, l’écriture d’un pilote (driver) offre des avantages:
• Faciliter la réutilisation des fonctions écrites pour le périphérique  plus de productivité dans le
développement
• Cacher la complexité matérielle du périphérique  faciliter le travail des non-experts

• Exemple: Arduino offre des librairies pour gérer les composants de la carte et la communication avec
certains périphériques (afficheur LCD, servomoteur, etc.)

• L’idée ici est de développer nos propres drivers en se basant sur la documentation du microcontrôleur et
des périphériques pour offrir des librairies réutilisables pour différents projets et facilement extensibles

31
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Ecriture de pilote de périphérique

• Exemple de pilote pour une led:


• 1ère étape: collecte des informations nécessaires pour le fonctionnement
• GPIO
• Pin

32
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Ecriture de pilote de périphérique

• Exemple de pilote pour une led:


• 2ème étape: définition d’une structure qui regroupe ces informations:
1) Le numéro de la pin peut aller de 0 à 15 sur un GPIO (4 bits au maximum). Le plus petit type
disponible est uint8_t et peut être utilisé pour représenter le numéro de pin.

2) Les GPIOs sont définis par des structures dans la librairie « stm32l053xx.h ». Pour le savoir, il suffit
de taper GPIOA dans le fichier main, cliquer dessus et appuyer sur F3. Cela renvoie vers la définition
suivante dans le fichier « stm32l053xx.h ».
#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
• En cherchant la définition de GPIO_TypeDef dans le même fichier, on trouve la structure suivante:
typedef struct
{
__IO uint32_t MODER;
__IO uint32_t OTYPER;
__IO uint32_t OSPEEDR;
__IO uint32_t PUPDR;
__IO uint32_t IDR;
__IO uint32_t ODR;
….}GPIO_TypeDef; 33
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Ecriture de pilote de périphérique

• Exemple de pilote pour une led:

• 2ème étape: définition d’une structure qui regroupe ces informations:


• On peut donc utiliser la structure LED_TypeDef suivante pour définir une Led:
Fichier « led.h »

#include "stm32l053xx.h"

typedef struct
{
GPIO_TypeDef * gpioPort;
uint8_t pin;

}LED_TypeDef;

34
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Ecriture de pilote de périphérique

• Exemple de pilote pour une led:


• 3ème étape: définition d’une fonction d’initialisation

Fichier « led.c »

void Led_init(LED_TypeDef *led, GPIO_TypeDef * port, uint8_t pn){

led->gpioPort=port;
led->pin=pn;

//Activation de l'horloge sur le port en question


//1-déterminer le numéro du port 0--> GPIOA, 1-->GPIOB, etc.
uint8_t nb_port;
nb_port=(uint32_t)((uint32_t *)port - IOPPERIPH_BASE)/ (uint32_t)0x400;
//2-activation de l'horloge du port GPIO en question
RCC->IOPENR|=1<<nb_port; Remarque: IOPPERIPH_BASE
est égal à 0x5000 0000 qui est
//configuration de la pin en sortie la première adresse dans
led->gpioPort->MODER&=~(0b11<<2*pn);
led->gpioPort->MODER|=(0b01<<2*pn); l’espace d’adressage dédié aux
} GPIOs
Chaque GPIO est adressable sur
une plage de 0x400
35
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Ecriture de pilote de périphérique

• Exemple de pilote pour une led:


• 4ème étape: définition des fonctions permettant de lire l’état ou les données à partir du périphérique

uint8_t Led_isOn(LED_TypeDef *led){


//retourner 1 si la led est On sinon 0
typedef struct //……….
{ }
GPIO_TypeDef * gpioPort;
uint8_t pin;
uint8_t Led_isOff(LED_TypeDef *led){
}LED_TypeDef; //retourner 1 si la led est Off sinon 0
//……….
}

36
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Ecriture de pilote de périphérique

• Exemple de pilote pour une led:


• 5ème étape: définition des fonctions permettant d’envoyer des commandes ou des données vers le
périphérique

void Led_turnOn(LED_TypeDef *led){


typedef struct //allumer la led
{ …..
GPIO_TypeDef * gpioPort; }
uint8_t pin;
void Led_turnOff(LED_TypeDef *led){
//éteindre la led
}LED_TypeDef;
…..
}
void Led_toggle(LED_TypeDef *led){
//inverser l’état de la led
……
}

37
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Ecriture de pilote de périphérique

• Exemple de pilote pour une led:


• Les fichiers du driver
Fichier « led.h » Fichier « led.c »

#include "stm32l053xx.h" #include "led.h"

typedef struct uint8_t Led_isOn(LED_TypeDef *led){


{ ….}
GPIO_TypeDef * gpioPort;
uint8_t pin; uint8_t Led_isOff(LED_TypeDef *led){
…..}
}LED_TypeDef;
void Led_turnOn(LED_TypeDef *led){
uint8_t Led_isOn(LED_TypeDef *led); ….}

uint8_t Led_isOff(LED_TypeDef *led); void Led_turnOff(LED_TypeDef *led){


…..}
void Led_turnOn(LED_TypeDef *led);
void Led_toggle(LED_TypeDef *led){
void Led_turnOff(LED_TypeDef *led); ….}

void Led_toggle(LED_TypeDef *led);


38
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Ecriture de pilote de périphérique

• Exemple de pilote pour une led:


• Test du pilote dans un main
#include "led.h" for(;;){
if(Led_isOn(&led)){
LED_TypeDef led; Led_turnOff(&led);
LL_mDelay(1000);
int main(void) }
{
//configuration de l'horloge du système en else if(Led_isOff(&led)){
16MHz Led_turnOn(&led);
….. LL_mDelay(1000);}
}
//configuration de la led sur la pin PA5 }
Led_init(&led, GPIOA,5);

39
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Ecriture de pilote de périphérique

• Exemple de pilote pour une led:


• Débogage

• En ajoutant « led » à l’onglet « Expressions », on a toutes les informations sur la led

40
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Ecriture de pilote de périphérique

• Exemple de pilote pour un bouton poussoir


• 1ère étape: collecte des informations nécessaires pour le fonctionnement
• GPIO
• Pin
• Résistance de tirage

• Pour la résistance de tirage, en cherchant dans le fichier « stm32l0xx_ll_gpio.h », on trouve les définitions suivantes:

• En suivant avec F3, on trouve que les valeurs binaires de ces trois constantes sont respectivement: 00, 01 et 10.
41
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Ecriture de pilote de périphérique

• Exemple de pilote pour un bouton poussoir

• 2ème étape: définition d’une structure qui regroupe ces informations:


Fichier « button.h »
#include "stm32l053xx.h“ • Le champ pull peut avoir l’une des valeurs suivantes (lors de l’appel
dans le main):
typedef struct • LL_GPIO_PULL_NO
{ • LL_GPIO_PULL_UP
GPIO_TypeDef * gpioPort;
• LL_GPIO_PULL_DOWN
uint8_t pin;
uint8_t pull;

}BUTTON_TypeDef;

42
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Ecriture de pilote de périphérique

• Exemple de pilote pour un bouton poussoir


• 3ème étape: définition d’une fonction d’initialisation
void Button_init(BUTTON_TypeDef *button, GPIO_TypeDef * port, uint8_t pn,uint8_t pl) {

button->gpioPort = port;
button->pin = pn;
button->pull = pl;

//Activation de l'horloge sur le port en question


//1-déterminer le numéro du port 0--> GPIOA, 1-->GPIOB, etc.
uint8_t nb_port;
nb_port = ((uint32_t) port - IOPPERIPH_BASE) / 0x400;
//2-activation de l'hologe
RCC->IOPENR |= 1 << nb_port;

//configuration de la pin en entrée


button->gpioPort->MODER &= ~(0b11 << 2 * pn);

//configuration du type de pull


button->gpioPort->PUPDR &= ~(0b11 << 2 * pn);
button->gpioPort->PUPDR |= (pl << 2 * pn);
}
43
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Ecriture de pilote de périphérique

• Exemple de pilote pour un bouton poussoir


• 4ème étape: définition des fonctions permettant de lire l’état ou les données à partir du périphérique

typedef struct uint8_t Button_State(BUTTON_TypeDef *button) {


{ //retourner 1 si le signal lu est 1 et 0 sinon
GPIO_TypeDef * //…..
gpioPort; }
uint8_t pin;
uint8_t pull;

}BUTTON_TypeDef;

44
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Ecriture de pilote de périphérique

• Exemple de pilote pour un bouton poussoir


• 5ème étape: définition des fonctions permettant d’envoyer des commandes ou des données vers le
périphérique

• Puisqu’il s’agit d’une entrée, on ne peut pas y écrire des données, cependant on peut changer sa
configuration (changement de la valeur du champ pin ou pull, par exemple)

45
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Ecriture de pilote de périphérique

• Exemple de pilote pour un bouton poussoir for (;;) {


• Test du pilote dans un main
//si bouton appuyé allumer led, sinon éteindre la led
#include "led.h" if (Button_State(&bouton) == 0)
#include "button.h" Led_turnOn(&led);

LED_TypeDef led; else Led_turnOff(&led);

BUTTON_TypeDef bouton; }
}
int main(void)
{
//configuration de l'horloge du système en 16MHz
….

//configuration de la led sur la pin PA5


Led_init(&led, GPIOA,5);

//configuration du bouton sur la pin PC13


Button_init(&bouton, GPIOC, 13, LL_GPIO_PULL_NO);

46
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Ecriture de pilote de périphérique
• Exemple de pilote pour un bouton poussoir case LL_EXTI_TRIGGER_FALLING:
//activation de l'interruption sur front descendant
• Utilisation du mode interruption dans FTSR
void Button_enableIRQ(BUTTON_TypeDef *button, uint8_t trigger) { //…..
break;
//activation de l'interruption externe case LL_EXTI_TRIGGER_RISING_FALLING:
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; //activation de l'interruption sur front montant
//….
/*chercher à quel registre EXTI de SYSCFG on doit accéder parmi //activation de l'interruption sur front descendant
les quatre disponibles*/ //….
//1-détermination du numéro d'EXTI break;}
uint8_t nb_EXTI = button->pin / 4; /*activer un vecteur d’interruption EXTI parmi les
//2-déterminer le numéro du port 0--> GPIOA, 1-->GPIOB, etc. trois vecteurs disponibles selon le numéro de pin*/
uint8_t nb_port; if (button->pin < 2) {
nb_port = ((uint32_t) button->gpioPort - IOPPERIPH_BASE) / 0x400; //activer les requêtes d’interruption EXTI0_1
//3-configuration du registre EXTI de SYSCFG NVIC_EnableIRQ(EXTI0_1_IRQn);
SYSCFG->EXTICR[nb_EXTI] &= ~(0b1111 << 4 * (button->pin % 4)); NVIC_SetPriority(EXTI0_1_IRQn, 0);
SYSCFG->EXTICR[nb_EXTI] |= (nb_port << 4 * (button->pin % 4)); }
else if (button->pin < 4) {
//activation d'EXTI dans IMR //activer les requêtes d’interruption EXTI2_3
//….. ……..
switch (trigger) { }
case LL_EXTI_TRIGGER_RISING: else {
//activation de l'interruption sur front montant dans RTSR //activer les requêtes d’interruption EXTI4_15
//….. ……
break; }}

47
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2
Ecriture de pilote de périphérique

• Exemple de pilote pour un bouton poussoir


• Test du mode interruption
#include "stm32l0xx_ll_exti.h“ //pour les interruptions int main(void)
#include "led.h" {
#include "button.h" //configuration de l'horloge du système en 16MHz

LED_TypeDef led;
BUTTON_TypeDef bouton; //configuration de la led sur la pin PA5
Led_init(&led, GPIOA,5);
/*puisqu’on utilise le bouton PC13 pour l’interruption,
le vecteur correspondant est EXTI4_15*/ //configuration du bouton sur la pin PC13
void EXTI4_15_IRQHandler() { Button_init(&bouton, GPIOC, 13, LL_GPIO_PULL_NO);
if ( EXTI->PR & (1 << bouton.pin)) {
//l’interruption se déclenche quand on relâche le bouton
Led_toggle(&led); Button_enableIRQ(&bouton,LL_EXTI_TRIGGER_RISING);

//effacer le flag correspodant à l’interruption en cours for (;;) {


EXTI->PR |= (1 << bouton.pin); }
}}
}

Attention: Le gestionnaire d’interruption ne peut pas être appelé dans le main comme les fonctions ordinaires. Il se
déclenche automatiquement à chaque fois que l’interruption concernée se produit.
48
SYS3046-Microcontrôleurs : périphériques et applications – 3A-S2

Vous aimerez peut-être aussi