Acces direct aux registres GPIO

publication: 12 juillet 2021 / mis à jour 10 mai 2024

Read this page in english

 

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:

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