Expand description
§uFerris Board Support Package Crate
uFerris is a flexible Rust embedded learning kit that can accomodate several SeeedStudio Xiao controllers. uFerris is essentially a carrier board that can accomodate mutliple different controllers.
The uferris-bsp crate provides a generic Board Support Package for the uFerris carrier board. As such, uferris-bsp is architecture-agnostic and can support for several MCUs (ESP32, RP2040…etc.)
Controller support is provided via feature flags.
In summary, this crate is meant to provide a software abstraction to easily drive the uFerris board with any supported Xiao Controller.
§Crate Architechture
The uFerris BSP architechture follows the layered scheme shown in the figure below. The upper uFerris board logic layer is meant to provide a hardware agnositc uniform interface across all Xiao controllers.
The second adapter layer is introduced to create the mappings between the logic and the individual device HALs. The adapter layer also utilizes the embedded-hal traits where possible. In most cases the controller HALs provide implementations for embedded-hal traits.
§Currently Supported Xiaos:
- Xiao ESP32-C3
- Xiao ESP32-C5 (buzzer stubbed - no PWM driver in
esp-halyet) - Xiao ESP32-C6
- Xiao ESP32-S3
- Xiao nRF52840 (and nRF52840 Sense)
- Xiao nRF54L15 (and nRF54L15 Sense)
- Xiao RP2040
- Xiao RP2350
§async Support
The async feature enables the async board API. Uferris carries a
Mode type parameter that selects which set of methods it exposes:
Blocking, the default, is the API described above and is what every
existing program already gets, and Async is the same board with the I2C
and ADC operations turned into async fns plus Uferris::wait_for_sw5,
which suspends until button 5 is pressed instead of spinning on it.
The executor and the time driver are the application’s responsibility. The
BSP starts neither: it hands back a board whose methods are futures, and the
program decides what runs them and where its delays come from. A board opts
in by exposing an uferris_init_async alongside its blocking
uferris_init, and all eight supported Xiaos now have one.
The ESP boards differ in one respect, because their runtime does. esp-rtos
is started from two peripherals — TIMG0 and SW_INTERRUPT — that live in
the same esp_hal::Peripherals struct their uferris_init_async consumes
whole, and its thread mode executor cannot suspend a task before the
scheduler is running. Their init is therefore synchronous, and hands those
two peripherals back next to the board so that the application can start the
scheduler with them before its first .await. See any of the ESP board
modules for the details.
§Contributing to the uFerris BSP - Adding a New Xiao Board Support:
Adding support for a new Xiao board entails two parts:
- Device Feature Flag in
Cargo.toml: A feature flag that imports the new device HAL needs to be added. - Device Board Adapter: This entails adding a new board definition (adapter layer) under the crate
boards/folder.
Other files in the crate should remain unchanged. It is recommended to view the existing board implementations for guidance on creating an adapter layer.
§Feature Flags
⚠️ At least one Xiao device feature must be enabled when building the crate.
xiao-esp32c3— Xiao ESP32-C3 Device Supportxiao-esp32c5— Xiao ESP32-C5 Device Supportxiao-esp32c6— Xiao ESP32-C6 Device Supportxiao-esp32s3— Xiao ESP32-S3 Device Supportxiao-nrf52840— Xiao nRF52840 Device Supportxiao-nrf54l15— Xiao nRF54L15 Device Supportxiao-rp2040— Xiao RP2040 Device Supportxiao-rp2350— Xiao RP2350 Device Supportpower-board— uFerris Megalops Power Board Extension Supportasync—asyncSupport Feature Flag. Enables theasyncboard API — theUferris<.., Async>mode, whose I2C and ADC operations areasync fns. This is a pure code gate: the executor and the time driver are the application’s responsibility, the BSP starts neither. Every supported Xiao has anuferris_init_asyncnext to its blockinguferris_init.
§Usage
The abstractions in this crate are designed in a way where they are common for any Xiao device. The only difference is that the correct controller board needs to be chosen as a feature. The steps to use this crate include the following:
1- Import the board init function:
use uferris_bsp::uferris_init;2- Acquire the controller peripherals and pass them to initialize the board:
let mut uferris = uferris_init(peripherals);3- Use the board methods:
// Turn on LED 1 on the board
uferris.led1_on();If no device feature is enabled, only the generic board API is available —
uferris_init requires selecting your Xiao’s feature. This is what code
written against the board API alone, without a controller in the picture,
builds against.
Re-exports§
pub use components::io_expander::SwPos;pub use crate::components::io_expander::SevenSegDigit;pub use boards::xiao_esp32c3::uferris_init;pub use boards::xiao_esp32c3::uferris_init_async;
Modules§
Structs§
- Async
- The
asyncboard API: the I2C and ADC operations areasync fns. - Blocking
- The blocking board API: every method returns its result directly.
- Uferris
- The uFerris Board Driver.
Enums§
Traits§
- Mode
- Which flavour of the board API a
Uferrisexposes. - Power
Constraints