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

  1. Reassign program pin bases so every pin group lies entirely in pins <32 or entirely in pins >=16
  2. If the program genuinely needs pins across the boundary, split the functionality or change wiring
  3. If gpio_base was latched by an earlier set_config, recreate the PIO/SM config or reset so the correct base is applied first
  4. 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

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


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)