gpiod Driver¶
jumpstarter-driver-gpiod provides functionality for interacting with
gpiod GPIO pins for digital input/output operations.
This requires the /dev/gpiochip[0..N] device available on the system, and you can use the gpioinfo gpiod tool to list the available GPIO lines.
Installation¶
$ pip3 install --extra-index-url https://pkg.jumpstarter.dev/simple jumpstarter-driver-gpiod
Hardware Requirements¶
gpiod with GPIO access
Python
gpiodlibrary installedAppropriate permissions to access
/dev/gpiochip0
Configuration¶
The gpiod driver provides three main driver types:
DigitalOutput Configuration¶
Example configuration for digital output:
export:
led_output:
type: jumpstarter_driver_gpiod.driver.DigitalOutput
config:
device: "/dev/gpiochip0"
line: 18
drive: "push_pull"
active_low: false
bias: "pull_up"
initial_value: "inactive"
DigitalInput Configuration¶
Example configuration for digital input:
export:
button_input:
type: jumpstarter_driver_gpiod.driver.DigitalInput
config:
line: 17
active_low: false
bias: "pull_up"
PowerSwitch Configuration¶
Example configuration for one channel of a GPIO relay HAT:
export:
power:
type: jumpstarter_driver_gpiod.driver.PowerSwitch
config:
line: 26
drive: push_pull # or open_drain / open_source, as the board needs
active_low: true # most relay HATs energize the coil on a LOW input
initial_value: preserve # an exporter restart leaves the relay where it is
Set active_low to match the board, so that on means “relay energized”. Use one
PowerSwitch per channel.
PowerSwitch speaks the same PowerInterface as the other relay drivers
(j power on|off|cycle|status). read raises NotImplementedError, because a
GPIO-switched contact has no voltage or current to measure; use status for the
switch state. See Power relays for what survives a restart and
what doesn’t.
Config parameters¶
Parameter |
Description |
Type |
Required |
Default |
Driver Types |
|---|---|---|---|---|---|
device |
The GPIO device to use (can be integer or string like “/dev/gpiochip0”) |
str |
no |
“/dev/gpiochip0” |
All |
line |
The GPIO line number to use |
int |
yes |
All |
|
drive |
The drive mode for the GPIO line. Options: “push_pull”, “open_drain”, “open_source”. Unset means “push_pull” |
str |
no |
null |
DigitalOutput, PowerSwitch |
active_low |
Whether the pin is active low (True) or active high (False) |
bool |
no |
False |
All |
bias |
The bias configuration for the GPIO line. Options: “as_is”, “pull_up”, “pull_down”, “disabled” |
str |
no |
null |
All |
initial_value |
The initial value for output pins. Options: “active”, “inactive”, “on”, “off”, “preserve”, True, False. “preserve” claims the line without changing its level, see below |
str/bool |
no |
“inactive” |
DigitalOutput, PowerSwitch |
Usage¶
Digital Output Examples¶
Basic LED control:
# Turn LED on
led_output.on()
# Turn LED off
led_output.off()
# Read current state
state = led_output.read()
print(f"LED state: {state}")
Digital Input Examples¶
Button input with edge detection:
# Read current input state
state = button_input.read()
print(f"Button state: {state}")
# Wait for button press (active state)
button_input.wait_for_active(timeout=10.0)
# Wait for button release (inactive state)
button_input.wait_for_inactive(timeout=10.0)
# Wait for rising edge (button press)
button_input.wait_for_edge("rising", timeout=10.0)
# Wait for falling edge (button release)
button_input.wait_for_edge("falling", timeout=10.0)
Power Switch Examples¶
Power control for devices:
# Turn power on
power_switch.on()
# Turn power off
power_switch.off()
# Read current power state: "on", "off", or "unknown" (the level last commanded, see Status)
state = power_switch.status()
print(f"Power state: {state}")
Pin Configuration Details¶
Drive Modes¶
drive sets how the pin drives each level. It applies to DigitalOutput and
PowerSwitch.
push_pull (default): drives both HIGH and LOW. Use it when the pin alone sets the input it is wired to, as with most relay HATs.
open_drain: drives LOW, and lets go of the line (high impedance) for HIGH. Use it when a pull-up on the far side sets the HIGH level: a reset or power button line on a DUT, a line at a different voltage than the Pi’s 3.3 V, or a line other devices can also pull LOW.
open_source: the mirror image: drives HIGH, and lets go for LOW, which a pull-down on the far side then sets.
With open_drain or open_source, the released level comes from the pull (on
the board, or from bias), not from the pin.
For example, a power control line driven open-drain. With active_low: false,
on releases the line (the pull-up takes it HIGH) and off pulls it LOW:
export:
power:
type: jumpstarter_driver_gpiod.driver.DigitalOutput
config:
line: 23
drive: open_drain
initial_value: "on"
Bias Configuration¶
bias enables the SoC’s internal pull resistor on the pin. It applies to all
driver types.
as_is (default): leave the bias as it is already configured
pull_up: internal pull-up resistor
pull_down: internal pull-down resistor
disabled: no pull resistor
On an input, the pull sets the level when nothing drives the line (a button
wired to ground needs pull_up). On an open_drain or open_source output, it
can supply the released level when the far side has no pull of its own. Internal
pulls are weak (tens of kΩ on a Raspberry Pi), so use an external resistor for
long wires or fast edges.
Active Low vs Active High¶
active_low: false (default): Pin is active when HIGH
active_low: true: Pin is active when LOW
Initial Values¶
For output pins, you can set the initial state:
“inactive” or “off” or False: Start inactive
“active” or “on” or True: Start active
“preserve”: Keep whatever level the line is already at
active_low is applied first, so “active” means the pin is LOW when active_low
is set. Any value other than preserve drives the line every time the exporter
starts.
Status¶
status returns on, off, or unknown: the level this driver last commanded,
not a measurement.
on/off: the level last driven (byon(),off(), or the initial request), withactive_lowapplied.unknown: the last write raised. The nexton()oroff()that succeeds makes the state known again.
status does not read the line back. Reading an output line can return either its
output or its input buffer, depending on the controller, so a readback can differ
from what was driven without meaning anything is wrong. A shorted pin or dead pad
therefore still reports the commanded level. read on DigitalOutputClient gives
the raw pin read when you want it.
Power relays¶
A GPIO relay HAT has one input per channel, and a pull resistor on the board holds
each input at its de-energized level whenever nothing drives it. PowerSwitch
drives one channel. What the relay does across restarts is set by the board and the
host, not by this driver:
Event |
Relay |
|
|---|---|---|
Exporter restart, with |
Unchanged |
The level it was left at |
Exporter restart, with any other |
Driven to that value |
That value |
Host reboot |
De-energizes for the whole boot |
The level found at start |
Host power loss |
De-energizes |
The level found at start |
Exporter restart. When the exporter exits, cleanly or by crashing, the kernel releases the line, and it keeps its level on typical SoC controllers (verified on a Raspberry Pi 4, including after SIGKILL, with no glitch on the line).
preservereads that level back and keeps driving it, so the relay doesn’t move. The kernel doesn’t guarantee this for every controller, so check yours if it matters.Host reboot. A reboot resets the SoC, which returns every GPIO to an input. The board’s pull then de-energizes the relay until something claims the line again, and the previous level is gone. No software setting prevents this: on a Raspberry Pi,
gpio=inconfig.txtonly takes effect after the reset, so the relay drops and then re-energizes, andcmdline.txtruns later still. After a reboot,preservefinds the de-energized level and reports it.
So wire each load for the state you want during a reboot. The relay is de-energized at reset, during boot, and with the host off:
For a load that should stay powered through a host reboot (a DUT’s supply), wire it through the relay’s NC (normally closed) contact.
onthen means de-energize the relay, so invertactive_lowfrom what NO wiring would use: on a board that energizes on LOW, setactive_low: false. The load is then powered at reset and during boot, andoffenergizes the relay to cut it.For a load that should be off unless commanded (ignition, a button press), wire it through the NO (normally open) contact.
If the load must keep either state through a host reboot, use a latching relay. A standard relay can’t do this.
Neither status nor anything else in this driver can tell whether a relay
actually switched: a missing jumper, a lost coil supply, or a welded contact all
still report the driven level. Only a feedback line wired back to the host can
confirm it.
API Reference¶
DigitalOutputClient¶
- class jumpstarter_driver_gpiod.client.DigitalOutputClient¶
A client for handling digital output operations on GPIO pins.
- off()¶
Turn gpio off.
- on()¶
Turn gpio on.
- read()¶
Read gpio state.
- status() str | None¶
Return the power state reported by the driver, e.g. “on”, “off” or “unknown”.
Optional for power drivers: returns None when the driver cannot report its state, so callers can tell “no status” apart from a real state.
PowerSwitch uses the standard jumpstarter_driver_power.client.PowerClient
(on, off, cycle, status).
DigitalInputClient¶
- class jumpstarter_driver_gpiod.client.DigitalInputClient¶
A client for handling digital input operations on GPIO pins.
Timeout conditions for input operations