Low-level GPIO library for Raspberry Pi 4 (BCM2711) using /dev/mem + mmap
Project description
bcmio
Biblioteca Python low-level para controle de GPIO do Raspberry Pi 4 Model B (BCM2711) usando
acesso direto a registradores via mmap e /dev/mem (MMIO).
Aviso: acessar
/dev/memnormalmente requer root (sudo). Use com cuidado: MMIO incorreto pode travar o sistema.
Objetivos
- Performance: escrita/leitura direto em registradores (
GPSET/GPCLR/GPLEV) - Arquitetura modular: separar low-level (MMIO/registradores) e high-level (abstrações)
- API familiar (inspirada em RPi.GPIO/pigpio/gpiozero), mas sem dependências dessas bibliotecas
- Código tipado, com docstrings, pronto para evoluir para PWM/SPI/I2C/UART/interrupts/DMA
Arquitetura (módulos)
bcmio/memory.py: abertura de/dev/mem,mmap, leitura/escrita 32-bitbcmio/constants.py: offsets e constantes (GPIO modes, pulls, endereços base)bcmio/gpio.py: acesso aos registradores GPIO (FSEL, SET/CLR, LEV, PULL)bcmio/pin.py: classePin(alto nível) para um pino individualbcmio/exceptions.py: exceções customizadasbcmio/utils.py: helpers (validação, bit operations)bcmio/pwm.py,bcmio/interrupts.py: placeholders para evolução
Como mmap funciona (visão geral)
- Abrimos
/dev/mem(arquivo especial que expõe memória física do SoC). - Fazemos
mmapde uma página (ou mais) a partir do endereço físico dos periféricos GPIO. - A partir do ponteiro mapeado, fazemos leituras/escritas de 32 bits em offsets específicos.
No Linux, isso é MMIO (Memory Mapped I/O): escrever em um registrador mapeado altera o hardware.
Endereços base (BCM2711)
O datasheet usa endereços no barramento (bus) como 0x7E200000 para o bloco GPIO. No Raspberry Pi 4,
o endereço físico tipicamente é 0xFE200000 (peripheral base 0xFE000000 + GPIO offset 0x200000).
Esta biblioteca:
- expõe ambos em
bcmio.constants(GPIO_BASE_BUS,GPIO_BASE_PHYS_DEFAULT) - por padrão usa o físico (
0xFE200000) - permite sobrescrever o endereço base via
GPIO.open(base_phys=...)
Registradores GPIO usados (BCM2711)
Offsets relativos ao base do GPIO (bloco GPIO):
GPFSEL0..5(Function Select): 3 bits por pino para definirIN,OUT, ou função alternativaGPSET0..1(Set): escrever1no bit seta o pino em nível alto (atômico)GPCLR0..1(Clear): escrever1no bit seta o pino em nível baixo (atômico)GPLEV0..1(Level): lê o nível atual do pinoGPIO_PUP_PDN_CNTRL_REG0..3: 2 bits por pino para pull-up/pull-down/no-pull (BCM2711)
Uso
API estilo “módulo” (GPIO)
from bcmio import GPIO
GPIO.safe_shutdown_enable() # opcional: cleanup automático em SIGINT/SIGTERM/exit
GPIO.open() # inicializa /dev/mem + mmap
GPIO.setup(17, GPIO.OUT, pull=GPIO.PULL_NONE)
GPIO.write(17, GPIO.HIGH)
value = GPIO.read(17)
GPIO.cleanup()
Context manager (shutdown seguro)
from bcmio import GPIO
GPIO.safe_shutdown_enable()
with GPIO() as gpio:
gpio.setup(17, gpio.OUT)
gpio.write(17, gpio.HIGH)
API orientada a objeto (Pin)
from bcmio import Pin
led = Pin(17, mode=Pin.OUT)
led.high()
led.low()
led.toggle()
led.close()
Exemplos
Veja exemplos/:
exemplos/blink.pyexemplos/blink_safe.pyexemplos/button_read.pyexemplos/button_safe.pyexemplos/toggle.pyexemplos/read_digital.py
Também há uma pasta examples/ (API high-level e eventos):
examples/blink.pyexamples/button.pyexamples/pwm_led.pyexamples/interrupt_button.pyexamples/servo_control.pyexamples/safe_shutdown.py
Testes
Os testes em testes/ não acessam /dev/mem. Eles usam um backend fake de memória para validar:
- cálculo de offsets e bitfields de
GPFSEL GPSET/GPCLRe leitura emGPLEV- configuração de pull em
GPIO_PUP_PDN_CNTRL_REGx
Rodar:
python -m pip install -e ".[dev]"
pytest -q
Segurança e boas práticas
- Use
sudoapenas quando necessário. - Prefira isolar e revisar o endereço base antes de usar em produção.
- Em produção, considere um modo “safe” ou
/dev/gpiomem(não implementado aqui por requisito). - Se estiver usando PWM/eventos, evite apertar Ctrl+C repetidamente;
GPIO.safe_shutdown_enable()já executacleanup().
Safety limit (GPIO 0–27)
Por padrão, bcmio bloqueia pinos acima de GPIO27 para reduzir riscos em hardware real. Se você
precisar acessar GPIOs além disso, ajuste a validação no seu código (API para override planejada).
Backends
GPIO.set_backend("mmio"): usa/dev/mem+mmap(default)GPIO.set_backend("mock"): registradores em memória (testes/CI)
Eventos por hardware (edge detect)
Para um sistema event-driven sem polling de GPLEV, use:
from bcmio import GPIO
GPIO.safe_shutdown_enable()
GPIO.open()
GPIO.setup(27, GPIO.IN, pull=GPIO.PULL_UP)
def cb(pin: int) -> None:
print("edge event on", pin)
GPIO.add_event_detect(27, GPIO.FALLING, cb) # GPEDS/GPFEN/GPREN
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bcmio-1.1.1.tar.gz.
File metadata
- Download URL: bcmio-1.1.1.tar.gz
- Upload date:
- Size: 21.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
22950c3eae61376dbdadf3aefe4bf13344c9f8470a548b09e88e20483d963279
|
|
| MD5 |
03a1a6d7cdb1b4b8afe30cbefeac63c0
|
|
| BLAKE2b-256 |
89dce86a7e5b1502f6c6de7ae89273c1f796148994995dde6354daebc12362c7
|
File details
Details for the file bcmio-1.1.1-py3-none-any.whl.
File metadata
- Download URL: bcmio-1.1.1-py3-none-any.whl
- Upload date:
- Size: 23.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
833e50b4163f28d5f8953a178d230dfd5948e4555ce84dafc9ac7b1598ec0547
|
|
| MD5 |
d14f8d0700f56afd90d2c0d0273f3b41
|
|
| BLAKE2b-256 |
1dc65bbeebc266500bc9d32ad2b91088e7180f837d453de5f201dc2efe78f0be
|