Writing
Embedded Rust on XIAO BLE, Part 2: Digital Input With Pull-Ups
Read a button with Embassy, use a pull-up input, and drive the onboard LED from GPIO state.
Series Embedded Rust on XIAO BLE / Part 2 of 2
March 27, 2026 / 2 min read
- Embedded Rust
- Embassy
- GPIO
- Input
Article
This part follows Embassy Rust + XIAO BLE - 02 Digital Input and the matching crate, crates/02-digital-input.
Part 1 controlled output pins. Part 2 adds input: read a button and use that state to turn the onboard red LED on or off.
git clone https://github.com/sarmadgulzar/xiao-ble-embassy
cd xiao-ble-embassy
cargo run --bin digital-input
The LED side should look familiar. The red LED is still on P0_26, and it is still active low:
let mut onboard_red = Output::new(p.P0_26, Level::High, OutputDrive::Standard);
The new piece is the button input:
let button = Input::new(p.P0_03, Pull::Up);
Pull::Up matters because it gives the input a defined idle state. With a pull-up, the pin reads high when the button is not pressed. When the button is pressed, the pin is pulled low.
That is why the main loop checks for is_low():
if button.is_low() {
onboard_red.set_low();
} else {
onboard_red.set_high();
}
There are two inversions to keep in your head:
- the button is pressed when the input reads low
- the red LED turns on when the output is driven low
That can feel odd the first time, but it is normal hardware work. The Rust code is only one layer; the board schematic and pin wiring decide what "high" and "low" mean in the real circuit.
This example also shows why it is useful to keep firmware examples small. There is no debounce logic yet, no event stream, and no second async task. It is just a readable bridge from input state to output state.
Once it works, try one careful change:
- swap the red LED for the blue LED on
P0_06 - reverse the behavior so the LED is on when the button is not pressed
- add a tiny
Timer::after_millis(20).awaitdelay in the loop before experimenting with debounce
That last step is where the series starts moving from "make pins work" toward "design firmware behavior". The first habit is observing the pin state clearly.
Continue The Series
Embedded Rust Series
Embedded Rust on XIAO BLE
Part 2 of 2
A hands-on Embassy Rust series for the Seeed Studio XIAO BLE and nRF52840.
-
1
Embedded Rust on XIAO BLE, Part 1: Blinky With Embassy
Run the first Embassy firmware example, blink the onboard RGB LED, and understand the active-low pins.
2 min read
-
2
Embedded Rust on XIAO BLE, Part 2: Digital Input With Pull-Ups
Read a button with Embassy, use a pull-up input, and drive the onboard LED from GPIO state.
2 min read