Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

GPIO

GPIO (General Purpose Input/Output) driver for BCM2711.

Overview

The BCM2711 provides 58 GPIO pins (GPIO 0-57) for general-purpose digital I/O. Each pin can be configured as input, output, or one of six alternate functions (for hardware peripherals like UART, SPI, I2C, etc.).

Key Features:

  • 58 GPIO pins (BCM2711 specific - BCM2835 had 54)
  • Configurable as input, output, or 6 alternate functions
  • Built-in pull-up/pull-down resistors (BCM2711 uses new register mechanism)
  • 3.3V logic levels (NOT 5V tolerant!)
  • Fast digital I/O for bit-banging protocols

Hardware Reference

Register Map

All offsets are from GPIO_BASE = 0xFE200000.

Function Select Registers (GPFSEL0-5)

Control pin modes (input, output, alternate functions).

RegisterOffsetControls PinsDescription
GPFSEL00x00GPIO 0-9Function select for pins 0-9
GPFSEL10x04GPIO 10-19Function select for pins 10-19
GPFSEL20x08GPIO 20-29Function select for pins 20-29
GPFSEL30x0CGPIO 30-39Function select for pins 30-39
GPFSEL40x10GPIO 40-49Function select for pins 40-49
GPFSEL50x14GPIO 50-57Function select for pins 50-57

Format: Each pin uses 3 bits (10 pins per 32-bit register).

Function Codes:

  • 000 (0) - Input
  • 001 (1) - Output
  • 100 (4) - Alternate Function 0
  • 101 (5) - Alternate Function 1
  • 110 (6) - Alternate Function 2
  • 111 (7) - Alternate Function 3
  • 011 (3) - Alternate Function 4
  • 010 (2) - Alternate Function 5

Output Set Registers (GPSET0-1)

Set pins HIGH (write-only, reads return 0).

RegisterOffsetControls PinsDescription
GPSET00x1CGPIO 0-31Write 1 to bit N to set GPIO N high
GPSET10x20GPIO 32-57Write 1 to bit (N-32) to set GPIO N high

Usage: Writing 1 to a bit sets the corresponding pin HIGH. Writing 0 has no effect.

Output Clear Registers (GPCLR0-1)

Set pins LOW (write-only, reads return 0).

RegisterOffsetControls PinsDescription
GPCLR00x28GPIO 0-31Write 1 to bit N to set GPIO N low
GPCLR10x2CGPIO 32-57Write 1 to bit (N-32) to set GPIO N low

Usage: Writing 1 to a bit sets the corresponding pin LOW. Writing 0 has no effect.

Pin Level Registers (GPLEV0-1)

Read current pin state (read-only).

RegisterOffsetControls PinsDescription
GPLEV00x34GPIO 0-31Read bit N to get GPIO N level
GPLEV10x38GPIO 32-57Read bit (N-32) to get GPIO N level

Usage: Returns actual pin voltage level (0 = low, 1 = high) regardless of pin mode.

Pull-up/down Control Registers (BCM2711 Only!)

IMPORTANT: BCM2711 uses a completely different mechanism than BCM2835/BCM2836/BCM2837!

The old GPPUD and GPPUDCLK registers are not connected on BCM2711. Use these instead:

RegisterOffsetControls PinsDescription
GPIO_PUP_PDN_CNTRL_REG00xE4GPIO 0-15Pull control for pins 0-15
GPIO_PUP_PDN_CNTRL_REG10xE8GPIO 16-31Pull control for pins 16-31
GPIO_PUP_PDN_CNTRL_REG20xECGPIO 32-47Pull control for pins 32-47
GPIO_PUP_PDN_CNTRL_REG30xF0GPIO 48-57Pull control for pins 48-57

Format: Each pin uses 2 bits (16 pins per register).

Pull Codes:

  • 00 (0) - No pull resistor
  • 01 (1) - Pull-up resistor enabled
  • 10 (2) - Pull-down resistor enabled
  • 11 (3) - Reserved

Example: To enable pull-up on GPIO 5 (in REG0, bits 10-11):

#![allow(unused)]
fn main() {
let reg = gpio.read(GPIO_PUP_PDN_CNTRL_REG0);
gpio.write(GPIO_PUP_PDN_CNTRL_REG0, (reg & !(0x3 << 10)) | (0x1 << 10));
}

Reset State

At power-on/reset:

  • All pins configured as INPUT (GPFSEL = 0x0)
  • All pins have PULL-DOWN enabled (GPIO_PUP_PDN_CNTRL = 0x2 for each pin)
  • Except: Pins used by firmware (UART, I2C) may be configured differently

Common GPIO Pins

On Raspberry Pi 4, common GPIO usage:

GPIOAlt FuncCommon Use
14ALT0UART0 TXD (console)
15ALT0UART0 RXD (console)
2ALT0I2C1 SDA (HAT EEPROM)
3ALT0I2C1 SCL (HAT EEPROM)
42-Activity LED (active low)
18ALT5PWM0 (audio, servo control)

Warning: Avoid GPIOs 0-8 (used for SD card boot), and GPIOs 14-15 if using serial console.

Electrical Characteristics

  • Logic Levels: 3.3V (HIGH = 3.3V, LOW = 0V)
  • Absolute Maximum: 3.6V (do NOT connect 5V signals directly!)
  • Pull Resistors: ~50-60kΩ (exact value varies)
  • Drive Strength: Configurable, default ~8mA
  • Maximum Current: 16mA per pin, 50mA total for all GPIO

Usage Pattern

Typical sequence for GPIO operations:

1. Configure as Output:

#![allow(unused)]
fn main() {
// Set GPIO 42 (Activity LED) as output
gpio.set_function(42, Function::Output);
gpio.set_pull(42, Pull::None);  // LEDs don't need pull resistors
}

2. Set Output HIGH/LOW:

#![allow(unused)]
fn main() {
gpio.set(42);    // Turn LED on
gpio.clear(42);  // Turn LED off
}

3. Configure as Input:

#![allow(unused)]
fn main() {
// Set GPIO 17 (button) as input with pull-up
gpio.set_function(17, Function::Input);
gpio.set_pull(17, Pull::Up);  // Button to ground, pull-up holds high
}

4. Read Input:

#![allow(unused)]
fn main() {
let pressed = !gpio.read(17);  // Active low (button pulls to ground)
}

Implementation Notes

Function Select Calculation:

  • Register index: pin / 10
  • Bit offset: (pin % 10) * 3
  • Mask: 0b111 << bit_offset

Output Set/Clear Calculation:

  • Register index: pin / 32
  • Bit offset: pin % 32
  • Mask: 1 << bit_offset

Pull Control Calculation (BCM2711):

  • Register index: pin / 16
  • Bit offset: (pin % 16) * 2
  • Mask: 0b11 << bit_offset

References