Acces direct aux registres GPIO
publication: 12 juillet 2021 / mis à jour 10 mai 2024
Appel à collaboration
Vous développez des montages, simples ou complexes avec ESP32 et ESP32forth.
Partagez-les ici sur ce site.
ESP32forth ne pourra se développer qu'avec la collaboration active de toutes les bonnes volontés.
Vos montages peuvent aider d'autres développeurs.
Les montages des autres développeurs peuvent vous aider.
Pour proposer un article ou un montage, cliquez ici
Accès direct aux registres
Dans certaines situations, il est bien plus intéressant d'avoir un accès direct aux registres GPIO sur la carte ESP32. Par exemple, pour gérer des séquences d'activation ou désactivation complexes.
L'accès à un registre GPIO s'effectue au moyen des mots L!
et UL@
.
Ces mots permettent en particulier un accès direct aux registres GPIO.
Le registre GPIO gérant les 32 premières entrées/sorties est à l'adresse hexadécimale 3ff44004:
$3ff44004 constant GPIO_OUT_REG 0 GPIO_OUT_REG L! \ turn LED on G2 off 4 GPIO_OUT_REG L! \ turn LED on G2 on
L'inconvénient, dans la séquence 4 GPIO_OUT_REG L!
, c'est quelle
n'active que le port G2. Si d'autres ports étaient actifs, ils seront désactivés.
La solution qui vient à l'esprit serait donc de lire l'état du registre à l'aide de
UL@
et d'effectuer des opérations logiques sur la valeur avant de la
réinjecter par L!
.
Il se trouve que la carte ESP32 dispose de registres dédiés qui effectuent ces opérations d'activation et désactivation sélectives sans passer par ces opérations logiques.
Définition des registres d'activation et désactivation
Les noms des registres sont extrait de la documentation ESP32 Technical Reference Manual (pdf):
hex 3ff44000 constant DR_REG_GPIO_BASE DR_REG_GPIO_BASE 04 + constant GPIO_OUT_REG DR_REG_GPIO_BASE 08 + constant GPIO_OUT_W1TS_REG DR_REG_GPIO_BASE 0c + constant GPIO_OUT_W1TC_REG DR_REG_GPIO_BASE 20 + constant GPIO_ENABLE_REG
Les deux registres qui nous intéressent sont GPIO_OUT_W1TS_REG
et GPIO_OUT_W1TC_REG
.
Leux noms ne diffèrent que d'une seule lettre: GPIO_OUT_W1TX_REG:
- S dans GPIO_OUT_W1TS_REG pour SET. Active sélectivement un ou plusieurs bits dans GPIO_OUT_REG.
- C dans GPIO_OUT_W1TC_REG pour CLEAR. Désactive sélectivement un ou plusieurs bits dans GPIO_OUT_REG:
Ainsi, avec GPIO_OUT_W1TS_REG
et GPIO_OUT_W1TC_REG
il n'est
plus nécessaire d'écrire directement dans GPIO_OUT_REG:
\ set Gx in LOW level : GxOFF ( mask --- ) GPIO_OUT_W1TC_REG L! ; \ set Gx in HIGH level : GxON ( mask --- ) GPIO_OUT_W1TS_REG L! ;
Nos deux mots GxOFF
et GxON
acceptent comme paramètre
un masque binaire de 32 bits.
Le mot GxON
va activer une sortie Gx sans altérer les autres sorties.
Le mot GxOFF
va désactiver une sortie Gx en utilisant le même masque binaire sans
altérer les autres sorties.
Définition des masques binaires
Pour mettre en pratique l'accès direct aux registres GPIO, on va reprendre l'exemple de gestion de feux tricolores de notre article Gérer un feu tricolore avec ESP32
On va redéfinir nos trois LEDs comme ceci:
binary \ masks are 32 bit length 00000000000000000000000000000100 constant ledGREEN \ green LED on G2 00000000001000000000000000000000 constant ledYELLOW \ yellow LED on G21 00000000000000100000000000000000 constant ledRED \ red LED on G17 decimal
On a défini chaque LED en indiquant sa position en binaire. Par exemple, pour la LED jaune connectée sur G21, ce sera le bit en position 21 (le comptage des bits commence à 0).
On peut aussi définir nos LEDs comme ceci:
1 2 lshift constant ledGREEN \ green LED on G2 1 21 lshift constant ledYELLOW \ yellow LED on G21 1 17 lshift constant ledRED \ red LED on G17
Mais avant d'agir sur les LEDs, il faut initialiser les ports GPIO en mode sortie.
Initialisation des sorties GPIO
Pour contrôler l'état d'une sortie Gx, il faut définir l'état de cette sortie
en agissant sur le contenu du registre GPIO_ENABLE_REG
. Cette
opération peut être exécutée en une seule fois en combinant les masques binaires
des sorties à activer:
\ init G2 G17 and G21 in output mode : GxInit ( -- ) ledGREEN ledYELLOW + ledRED + GPIO_ENABLE_REG L! ;
Pour créer un masque binaire unique, il suffit de faire la somme de tous les masques binaires des sorties à activer.
Gestion de feu tricolore allemand
En Allemagne, les feux tricolores routiers ont quatre cycles. La particularité de ces feux est d'allumer simultanément les feux rouge et jaune avant de repasser au feu vert.
Pour commencer, nous allons définir un mot qui va désactiver tous les feux:
\ set all LEDs off : allLEDSoff ( -- ) ledRED ledYELLOW ledGREEN + + GxOFF ;
Nous allons maintenant créer un tableau contenant les quatre cycles de ces feux routiers allemands:
\ german traffic lights cycle create dLightsCycle ( -- addr ) ledGREEN , ledYELLOW , ledRED , ledYELLOW ledRED + ,
Et pour finir, on va réécrire le mot Dtraffic
, prenant en compte
notre table dLightsCycle
:
\ german trafic light style : Dtraffic ( ---) GxInit begin 4 0 do allLEDSoff dLightsCycle i cell * + @ GxON 500 ms loop key? until allLEDSoff ;
On a donc vu dans cet article comment agir sur plusieurs sorties GPIO simulatément en agissant directement sur les registres GPIO.
Cependant, avec les cartes ESP32, il est déconseillé de gérer trop de LEDs simultanément. La carte ESP32 doit être réservée à la gestion des signaux vers des accessoires très peu gourmands en énergie. On évitera donc des montages du style 8 à 16 LEDs pour faire un effet de type chenillard par exemple...
Code complet disponible ici:
ESP32forth/regsDirectAccess.txt
Legal: site web personnel sans commerce / personal site without seling