Adresses de base des registres GPIO
Sur le BCM2837, les registres GPIO sont mappés en mémoire à partir de l’adresse de base :0x3F000000 (contre 0x20000000 sur le BCM2835).
Les registres GPIO occupent une plage de 0x3F200000 à 0x3F2000B4.
Note :
- Sur le Pi 4 (BCM2711), l’adresse de base devient
0xFE000000.- Toujours vérifier le modèle avec
cat /proc/cpuinfo.
Structure des registres GPIO clés
Chaque registre fait 32 bits (4 octets). Voici les principaux :
| Offset | Registre | Description |
| 0x00 | GPFSEL0 à GPFSEL5 | Configuration des broches (entrée/sortie/fonction alternative). |
| 0x1C | GPSET0 / GPSET1 | Mettre une broche à 1 (activation). |
| 0x28 | GPCLR0 / GPCLR1 | Mettre une broche à 0 (désactivation). |
| 0x34 | GPLEV0 / GPLEV1 | Lire l’état actuel d’une broche (niveau haut/bas). |
| 0x40 | GPEDS0 / GPEDS1 | Détection d’événement (front montant/descendant). |
| 0x7E | GPPUD | Configuration des résistances de pull-up/pull-down. |
| 0x94 | GPPUDCLK0/GPPUDCLK1 | 0x94 GPPUDCLK0/GPPUDCLK1 Activation du pull-up/pull-down pour une broche spécifique. |
Détail des registres de fonction (GPFSEL)
Chaque registre GPFSEL0 à GPFSEL5 contrôle 10 broches (3 bits par broche) :
- 000 : Entrée.
- 001 : Sortie.
- 010 à 111 : Fonction alternative (UART, SPI, I2C, etc.).
Exemple : Configurer la GPIO17 (broche 11 du header) en sortie :
- La GPIO17 est gérée par
GPFSEL1(offset0x04). - Bits 21-23 dans
GPFSEL1doivent être001.
// En C (accès direct mémoire) :
volatile unsigned int* gpio = (unsigned int*)0x3F200000;
*(gpio + 1) |= (1 << 21); // GPFSEL1[21:23] = 001
Activation/désactivation des broches (GPSET/GPCLR)
- GPSET0 (offset
0x1C) : Écrire1pour activer une broche. - GPCLR0 (offset
0x28) : Écrire1pour désactiver une broche.
Exemple : Allumer la GPIO17 :
*(gpio + 7) = (1 << 17); // GPSET0[17] = 1
Éteindre la GPIO17 :
*(gpio + 10) = (1 << 17); // GPCLR0[17] = 1
Lecture d’une broche (GPLEV)
Pour lire l’état de la GPIO17 :
int state = (*(gpio + 13) >> 17) & 1; // GPLEV0[17]
Pull-up/pull-down (GPPUD et GPPUDCLK)
Écrire la configuration dans GPPUD (offset 0x94) :
0x00: Désactiver.0x01: Pull-down.0x02: Pull-up.
Activer la configuration pour une broche via GPPUDCLK0 (offset 0x98).
*(gpio + 37) = 0x02; // GPPUD = pull-up
delay(150); // Attendre 150 cycles
*(gpio + 38) = (1 << 17); // GPPUDCLK0[17] = 1
delay(150);
*(gpio + 37) = 0x00; // Réinitialiser GPPUD
*(gpio + 38) = 0x00; // Réinitialiser GPPUDCLK0
Mapping des broches (Header 40 broches)
| Broche | GPIO | Fonction alternative |
|---|---|---|
| 11 | GPIO17 | Générique (sortie LED). |
| 12 | GPIO18 | PWM0. |
| 19 | GPIO10 | SPI0_MOSI. |
| 23 | GPIO11 | SPI0_SCLK. |
Exemple complet en C (sans librairie)
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
// Adresses pour Raspberry Pi (à ajuster selon modèle)
#define GPIO_BASE 0xFE200000 // RPi 4 (BCM2711)
// #define GPIO_BASE 0x3F200000 // RPi 2/3
#define PAGE_SIZE 4096
#define BLOCK_SIZE 4096
// Registres GPIO
#define GPFSEL0 0x00 // Fonction Select 0
#define GPSET0 0x1C // Set Output
#define GPCLR0 0x28 // Clear Output
volatile unsigned int *gpio;
void init_gpio() {
int fd = open("/dev/gpiomem", O_RDWR | O_SYNC);
if (fd < 0) {
perror("Échec de l'ouverture de /dev/gpiomem");
exit(1);
}
gpio = (volatile unsigned int *)mmap(
NULL,
BLOCK_SIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED,
fd,
GPIO_BASE
);
close(fd);
if (gpio == MAP_FAILED) {
perror("Échec du mmap");
exit(1);
}
}
void set_gpio_output(int pin) {
int reg = pin / 10;
int shift = (pin % 10) * 3;
gpio[reg] = (gpio[reg] & ~(7 << shift)) | (1 << shift);
}
int main() {
int led_pin = 17; // GPIO17 (broche physique 11)
init_gpio();
set_gpio_output(led_pin);
while (1) {
gpio[GPSET0 / 4] = 1 << led_pin; // Allume
sleep(1);
gpio[GPCLR0 / 4] = 1 << led_pin; // Éteint
sleep(1);
}
munmap((void *)gpio, BLOCK_SIZE);
return 0;
}
Précautions
- Accès root requis : Utiliser
/dev/memou/dev/gpiomem. - Voltage : Les GPIO sont en 3,3 V (ne pas connecter du 5 V directement).
- Synchronisation : Toujours vérifier les offsets et adresses pour le BCM2837.
