uferris-bsp 0.2.0

A Board Support Package for the uFerris Learner Board
Documentation
<p align="center">
  <img src="https://i.imgur.com/gAPf1TI.png" width="50" alt="uFerris logo"/>
  <br/>
</p>

<h1 align="center">µFerris Board Support Package</h1>

<p align="center">
  <strong>A flexible, hardware-agnostic BSP crate for the µFerris Xiao carrier board</strong>
</p>

<p align="center">
  <img src="https://i.imgur.com/KcvXhPw.png" width="250" alt="µFerris board photo"/>
</p>

<br/>


<div align="center">

[![crates.io](https://img.shields.io/crates/v/uferris-bsp.svg)](https://crates.io/crates/uferris-bsp)
[![docs.rs](https://docs.rs/uferris-bsp/badge.svg)](https://docs.rs/uferris-bsp)

</div>

**µFerris** is a Rust embedded learning/experimentation kit that can accept various **[Seeed Studio Xiao](seeedstudio.com/xiao-series-page)** controllers.

The `uferris-bsp` crate provides a **generic Board Support Package** that aims to be mostly MCU-agnostic, allowing the same high-level board API to work across different supported Xiao controllers (ESP32-C3, RP2040, etc.).

Controller-specific support is enabled via **feature flags**.

µFerris is an open-source hardware project. The hardware source is available on the **[uferris-hw](https://github.com/uFerris-rs/uferris-hw)** repo. µFerris can also be acquired from **[The Embedded Rustacean Store](http://shop.theembeddedrustacean.com/)**.

## Architecture Overview

The crate adopts the following layered approach:

<p align="center">
  <img src="https://i.imgur.com/SD77pGl.png" width="520" alt="µFerris BSP architecture diagram"/>
</p>

The architechture adds two layers on top of existing community crates:
- **µFerris Board Logic Layer**: This layer implments the hardware-agnostic µFerris board API. 
- **µFerris Board Adapter Layer**: This layer maps the generic logic to concrete MCU HALs (uses `embedded-hal` traits where possible).

## `async` Support

This BSP supports `async` operation. This is enabled by activating the `async` feature flag which enables the `async` BSP API. The different modes are handled by using mode type parameters: `Uferris<.., Blocking>`, and `Uferris<.., Async>`, built against the `embedded-hal` and `embedded-hal-async` traits, respectively. 

The runtime, such as embassy, is provided by the application, not the BSP. The crate starts no executor and installs no time driver. The BSP initialization hands back a board handle whose methods are futures, and the program brings its own executor (`embassy-executor`) and its own delay (`embassy-time`).

Note that not all board functions might have async methods or support. However, the blocking functions would still be available in `async` mode.

## Support Status

| Controller       | Feature flag          | Support Status | `async` Support |
|------------------|-----------------------|:----------------:|:-----------------:|
| [Xiao ESP32-C3]https://www.seeedstudio.com/Seeed-XIAO-ESP32C3-p-5431.html?utm_source=blog&utm_medium=TER&utm_campaign=uFerris    | `xiao-esp32c3`        |||
| [Xiao ESP32-C5]https://www.seeedstudio.com/Seeed-Studio-XIAO-ESP32C5-p-6609.html?utm_source=blog&utm_medium=TER&utm_campaign=uFerris     | `xiao-esp32c5`       |||
| [Xiao ESP32-C6]https://www.seeedstudio.com/Seeed-Studio-XIAO-ESP32C6-p-5884.html?utm_source=blog&utm_medium=TER&utm_campaign=uFerris     | `xiao-esp32c6`       |||
| [Xiao ESP32-S3]https://www.seeedstudio.com/XIAO-ESP32S3-p-5627.html?utm_source=blog&utm_medium=TER&utm_campaign=uFerris     | `xiao-esp32s3`       |||
| [Xiao ESP32-S3 Sense]https://www.seeedstudio.com/XIAO-ESP32S3-Sense-p-5639.html?utm_source=blog&utm_medium=TER&utm_campaign=uFerris | `xiao-esp32s3`     |||
| [Xiao nRF52840]https://www.seeedstudio.com/Seeed-XIAO-BLE-nRF52840-p-5201.html?utm_source=blog&utm_medium=TER&utm_campaign=uFerris    | `xiao-nrf52840`       |||
| [Xiao nRF52840 Sense]https://www.seeedstudio.com/Seeed-XIAO-BLE-Sense-nRF52840-p-5253.html?utm_source=blog&utm_medium=TER&utm_campaign=uFerris | `xiao-nrf52840`    |||
| [Xiao nRF54L15]https://www.seeedstudio.com/XIAO-nRF54L15-p-6493.html?utm_source=blog&utm_medium=TER&utm_campaign=uFerris    | `xiao-nrf54l15`       |||
| [Xiao nRF54L15 Sense]https://www.seeedstudio.com/XIAO-nRF54L15-Sense-p-6494.html?utm_source=blog&utm_medium=TER&utm_campaign=uFerris | `xiao-nrf54l15`    |||
| [Xiao RP2350]https://www.seeedstudio.com/Seeed-XIAO-RP2350-p-5944.html?utm_source=blog&utm_medium=TER&utm_campaign=uFerris      | `xiao-rp2350`         |||
| [Xiao RP2040]https://www.seeedstudio.com/XIAO-RP2040-v1-0-p-5026.html?utm_source=blog&utm_medium=TER&utm_campaign=uFerris      | `xiao-rp2040`         |||
| [Xiao SAMD21]https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html?utm_source=blog&utm_medium=TER&utm_campaign=uFerris      | -                     |||
| [Xiao RA4M1]https://www.seeedstudio.com/Seeed-XIAO-RA4M1-p-5943.html?utm_source=blog&utm_medium=TER&utm_campaign=uFerris       | -                     |||
| Xiao MG24        | -                     |||
| Xiao MG24 Sense  | -                     |||


## Adding Support for a New Xiao Controller

Adding support for a new Xiao board entails two parts:
1. **Adding a Device Feature Flag in `Cargo.toml`**: A feature flag that imports the new device HAL needs to be added.
2. **Adding a Device Board Adapter**: This entails adding a new board definition (adapter layer) under the crate `boards/` folder.

The rest of the crate files should not need to change.

## Feature Flags

Available Cargo features:

- `xiao-esp32c3` — Xiao ESP32-C3 Device Support
- `xiao-esp32c5` — Xiao ESP32-C5 Device Support
- `xiao-nrf52840` — Xiao nRF52840 Device Support
- `xiao-nrf54l15` — Xiao nRF54L15 Device Support
- `xiao-rp2040` — Xiao RP2040 Device Support
- `xiao-rp2350` — Xiao RP2350 Device Support
- `powerboard` — µFerris Megalops Power Board Extension Support
- `async``async` Support Feature Flag (enables the `Uferris<.., Async>` board API; the executor and time driver are the application's)

## Quick Start / Usage
Generally, you need to:

- Enable the correct feature flags in your `Cargo.toml`
- Pass the correct HAL peripherals struct to `uferris_init()`

Everything else should stay the same regardless of which Xiao is mounted. A simple example is presented below.


```rust
#![no_std]
#![no_main]

use uferris_bsp::uferris_init;

#[entry]
fn main() -> ! {
    // 1. Get your HAL peripherals (depends on MCU)
    let peripherals = your_hal::take().unwrap();

    // 2. Initialize the µFerris board abstraction
    let mut uferris = uferris_init(peripherals);

    // 3. Use the board API
    uferris.led1_on();

    loop {}
}
```

## Examples
Each supported board has a self-contained example project under [`examples/`](examples/).
Each board directory is a self-contained Cargo project with its own target, toolchain, and runner configuration.
See each board's README for the full list of examples it supports.

The demos themselves are written once, in [`examples/uferris-demos/`](examples/uferris-demos/): every board runs the same code against the generic board API.
A board's `src/bin/*.rs` only brings the controller up, opens whatever console it has, and hands both to the shared demo.

| Board | Examples |
| ----- | -------- |
| Xiao ESP32-C3 | [`examples/xiao-esp32-c3/`]examples/xiao-esp32-c3/ |
| Xiao ESP32-C5 | [`examples/xiao-esp32-c5/`]examples/xiao-esp32-c5/ |
| Xiao ESP32-C6 | [`examples/xiao-esp32-c6/`]examples/xiao-esp32-c6/ |
| Xiao ESP32-S3 | [`examples/xiao-esp32-s3/`]examples/xiao-esp32-s3/ |
| Xiao nRF52840 | [`examples/xiao-nrf52840/`]examples/xiao-nrf52840/ |
| Xiao nRF54L15 | [`examples/xiao-nrf54l15/`]examples/xiao-nrf54l15/ |
| Xiao RP2040 | [`examples/xiao-rp2040/`]examples/xiao-rp2040/ |
| Xiao RP2350 | [`examples/xiao-rp2350/`]examples/xiao-rp2350/ |


## Running Examples

Run any example with:

```
cd examples/<board>
cargo run --bin <example>
```

For example, to run `blinky.rs` on a Xiao ESP32-C3:

```bash
cd examples/xiao-esp32-c3
cargo run --bin blinky
```

Use `cargo build --bin <example>` if you only want to compile without flashing.

## AI use

This project accepts AI-assisted contributions under conditions. Before opening a
pull request, read [AI_POLICY.md](AI_POLICY.md). To summarize, AI as a tool is
fine, but you must understand and be able to explain everything you submit; a
human must be the interface for all contributions; disclosure is required in the
PR template, and every change must state how it was verified. Autonomous agent
submissions will be closed.

## License

Licensed under either of

- Apache License, Version 2.0 ([LICENSE-APACHE]LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT]LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

---

Made with 🦀