embassy-rs/embassy · error
All pins must either be <32 or >=16, in
Error message
All pins must either be <32 or >=16, in:{:?}-{:?}, side:{:?}-{:?}, set:{:?}-{:?}, out:{:?}-{:?}, bypass:{:#x} What it means
When applying a PIO config on RP235x with GPIOBASE routing, all pins referenced by the program (in, side-set, set, out, and the input-sync bypass mask plus jmp pin) must be addressable: either all <32 (base 0) or all >=16 (base 16), and the base must be consistent with any latched gpio_base. If the config mixes banks or conflicts with a latched base, `set_config` panics with this detailed dump.
Solutions
- Reassign program pin bases so every pin group lies entirely in pins <32 or entirely in pins >=16
- If the program genuinely needs pins across the boundary, split the functionality or change wiring
- If gpio_base was latched by an earlier set_config, recreate the PIO/SM config or reset so the correct base is applied first
- Check the bypass mask in the message: it must fit within the single chosen 32-pin window
Example fix
// before let mut c = Config::default(); c.set_set_pins(&[pin_28, pin_30]); // straddles? both >=16 ok, but in pins <16 would fail // after let mut c = Config::default(); c.set_set_pins(&[pin_16, pin_18]); // keep all used pins in one bank (>=16)
Defensive patterns
Strategy: validation
Validate before calling
fn all_pins_one_bank(bases: &[Option<u8>]) -> bool {
let pins: Vec<_> = bases.iter().flatten().copied().collect();
pins.iter().all(|&p| p < 32) || pins.iter().all(|&p| p >= 16)
} Prevention
- Assign all program pin groups (in/side/set/out/jmp) to a single pin bank on RP235x
- Avoid re-latching configs with conflicting gpio_base; rebuild the config from scratch
- Check the bypass mask fits the chosen bank before set_config
When it happens
Trigger: Calling `StateMachine::set_config` (which latches the config) with a Config whose in/sideset/set/out base ranges or jmp_pin straddle the 16/32 boundary, or whose bypass mask requires a different GPIOBASE than the one already latched.
Common situations: RP235x programs that use e.g. in_base 12 with out_base 20; reconfiguring a state machine after the GPIOBASE was latched to the other bank; porting RP2040 code using pins 12..20 to RP235x.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- pin is outside the PIO's GPIOBASE window .. ; use…
- Error configuring i2c
- Failed to load PIO program
- Invalid PIO_NO: , expected one of 0,1,2
- Invalid PIO_NO: , expected one of 0,1
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/72115fd326eac712.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-rp/src/pio/mod.rs:872
low_ok &= pin < 32;
high_ok &= pin >= 16;
}
}
let mut bypass = config.input_sync_bypass_mask;
while bypass != 0 {
let pin = bypass.trailing_zeros() as u8;
low_ok &= pin < 32;
high_ok &= pin >= 16;
bypass &= bypass - 1;
}
if let Some(jmp_pin) = config.exec.jmp_pin {
low_ok &= jmp_pin < 32;
high_ok &= jmp_pin >= 16;
}
if (!low_ok && !high_ok) || (!high_ok && gpio_base_latched) {
panic!(
"All pins must either be <32 or >=16, in:{:?}-{:?}, side:{:?}-{:?}, set:{:?}-{:?}, out:{:?}-{:?}, bypass:{:#x}",
config.pins.in_base,
config.pins.in_base + config.in_count - 1,
config.pins.sideset_base,
config.pins.sideset_base + config.pins.sideset_count - 1,
config.pins.set_base,
config.pins.set_base + config.pins.set_count - 1,
config.pins.out_base,
config.pins.out_base + config.pins.out_count - 1,
config.input_sync_bypass_mask,
)
}
let shift = if low_ok && !gpio_base_latched { 0 } else { 16 };
if !gpio_base_latched && shift == 16 {
// GPIO_Base set for the first time, update all SMs
for i in 0..4 {
if i != SM {View on GitHub (pinned to 463a07b963)