embassy-rs/embassy · error

Invalid GPIO port index

Error message

Invalid GPIO port index {}

What it means

Panic in InputFuture::poll: the future's waker registry (GPIO_WAKERS) is sized for the number of GPIO ports the chip actually has. When polling, the pin's port index is checked against the table length; a port value at or beyond that length cannot have a registered waker, so interrupt-driven waiting is impossible and the code panics rather than silently never waking. The faulting input is a pin constructed with an out-of-range port number — a pin model/peripheral mismatch or an invalid port passed into GPIO configuration.

Solutions

  1. Use only pin definitions from the generated embassy-imxrt peripherals model for the actual chip variant
  2. Check that the Cargo feature/board model matches the physical chip so GPIO_WAKERS covers all real ports
  3. Fix code that fabricates pins with hand-written port numbers instead of using the peripherals struct
  4. Validate port index at pin-construction time so invalid pins fail early, not during poll
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at embassy-imxrt/src/gpio.rs:446 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10). Data as JSON: /api/errors/7ca608aea210f37e. Report an issue: GitHub.

Appendix: source

Thrown at embassy-imxrt/src/gpio.rs:446

            // Enable pin interrupt on GPIO INT A
            pin.block()
                .intena(pin.port())
                .modify(|r, w| unsafe { w.int_en().bits(r.int_en().bits() | (1 << pin.pin())) });
        });

        Self { pin: pin.into() }
    }
}

impl Future for InputFuture<'_> {
    type Output = ();

    fn poll(self: FuturePin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        // We need to register/re-register the waker for each poll because any
        // calls to wake will deregister the waker.
        if self.pin.port() >= GPIO_WAKERS.len() {
            panic!("Invalid GPIO port index {}", self.pin.port());
        }

        let port_waker = GPIO_WAKERS[self.pin.port()];
        if port_waker.is_none() {
            panic!("Waker not present for GPIO port {}", self.pin.port());
        }

        let waker = port_waker.unwrap().get_waker(self.pin.pin());
        if waker.is_none() {
            panic!(
                "Waker not present for GPIO pin {}, port {}",
                self.pin.pin(),
                self.pin.port()
            );
        }
        waker.unwrap().register(cx.waker());

        // Double check that the pin interrut has been disabled by IRQ handler

View on GitHub (pinned to 463a07b963)