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 :

OffsetRegistreDescription
0x00 GPFSEL0 à GPFSEL5Configuration des broches (entrée/sortie/fonction alternative).
0x1CGPSET0 / GPSET1Mettre une broche à 1 (activation).
0x28GPCLR0 / GPCLR1Mettre une broche à 0 (désactivation).
0x34GPLEV0 / GPLEV1 Lire l’état actuel d’une broche (niveau haut/bas).
0x40GPEDS0 / GPEDS1Détection d’événement (front montant/descendant).
0x7EGPPUDConfiguration des résistances de pull-up/pull-down.
0x94GPPUDCLK0/GPPUDCLK10x94 GPPUDCLK0/GPPUDCLK1 Activation du pull-up/pull-down pour une broche spécifique.
offset pour accéder aux registres internes

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 (offset 0x04).
  • Bits 21-23 dans GPFSEL1 doivent être 001.
// 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) : Écrire 1 pour activer une broche.
  • GPCLR0 (offset 0x28) : Écrire 1 pour 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)

BrocheGPIOFonction alternative
11GPIO17Générique (sortie LED).
12GPIO18PWM0.
19GPIO10SPI0_MOSI.
23GPIO11SPI0_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/mem ou /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.