Exercise: Explore the uFerris BSP

~15-20 min

Your Task

Step 1: Read the Source

Open the uFerris BSP crate source code. Don't use it yet — just read it.

Answer these questions:

  1. How does the BSP map pin numbers to named functions?
  2. What configuration choices has the BSP author made? (Drive strength? Pull resistors? I2C speed?)
  3. Can you find the Create → Configure → Control pattern inside the BSP code?
The BSP calls `Output::new()`, which calls into the HAL, which writes to PAC registers, which toggle actual hardware. Every layer you've learned is present — the BSP just wraps them up.

Step 2: Refactor Your Code

Take one of your earlier exercises — blinky or I2C scan — and refactor it to use the BSP:

Before (raw HAL):

#![allow(unused)]
fn main() {
let mut led = Output::new(
    peripherals.GPIO5,
    Level::Low,
    OutputConfig::default()
);
}

After (BSP):

#![allow(unused)]
fn main() {
let mut led = board.led();
}

How much simpler is the code? What did you lose (if anything)?

Step 3: Look Beyond

What other convenience functions does the BSP provide? Can you find:

  • I2C setup?
  • Button input?
  • Sensor initialization?

Try using one you haven't tried before.

Reflection

You've now seen every layer of the embedded Rust stack:

LayerWhat You Did
HALConfigured GPIO pins, I2C buses manually
embedded-halUsed traits that make driver crates portable
Driver cratesRead sensor data with hardware-agnostic drivers
BSPUsed board-specific convenience functions

And for every layer, the same pattern: Create → Configure → Control.

You know how to read the docs for any of them. You know how to adapt examples. You know where to look when you need something new.

That's the skill that lasts.