Embedded

GPIO — General-Purpose I/O

The most basic building block: a pin that firmware can configure as an input or output, and read or drive directly. Everything from bit-banged protocols to chip-select lines for SPI ultimately rests on GPIO.

Quick reference
What it is
A pin firmware can configure as input or output and read/drive directly — the lowest-level building block of any digital hardware interface.
Mental model
A switch you control from code — push-pull can flip it fully both ways, open-drain can only pull it down and rely on a resistor to pull it back up.
Key numbers
A few tens of mA max source/sink current per pin; 3.3 V and 5 V are the common logic levels.
Reach for it when
Anything that isn't a dedicated peripheral — LEDs, buttons, chip-select lines, bit-banged protocols.

Pin modes

ModeBehavior
Input (floating)High-impedance; reads whatever voltage is externally applied — undefined if nothing drives it.
Input, pull-upInternal resistor weakly pulls the pin high when nothing else drives it.
Input, pull-downInternal resistor weakly pulls the pin low when nothing else drives it.
Output, push-pullActively drives both high and low — the default for most outputs.
Output, open-drainCan only pull low; needs an external (or internal) pull-up to reach high. Required for shared buses like I2C where multiple devices share a line.

Why open-drain matters

On a push-pull bus, two devices disagreeing about the line's state fight each other — one drives high, one drives low, and current flows between them (a short). Open-drain avoids this: every device can only pull low or release, so the "loudest" state that wins is always low, and nobody fights over who's allowed to drive high. This is exactly the property I2C depends on for both signaling and simple multi-master arbitration.

Electrical basics worth remembering

Linux userspace: the character-device GPIO API

Modern Linux exposes GPIO to userspace through /dev/gpiochipN character devices and the libgpiod library (the older sysfs /sys/class/gpio interface is deprecated). See Linux → Drivers for the driver-model context.

# command-line, via libgpiod tools
gpioget gpiochip0 17          # read line 17
gpioset gpiochip0 17=1        # drive line 17 high

Real-world applications

What I learned

A pin left floating (no pull-up/down, nothing driving it) doesn't read as a stable 0 or 1 — it reads noise, and can even oscillate rapidly enough to burn extra power through the input buffer. Always give an unused or momentarily-unconnected input pin a defined pull state.