| Crates.io | aimdb-embassy-adapter |
| lib.rs | aimdb-embassy-adapter |
| version | 0.4.0 |
| created_at | 2025-11-06 22:06:55.187327+00 |
| updated_at | 2025-12-25 20:48:14.576961+00 |
| description | Embassy async runtime adapter for AimDB embedded targets |
| homepage | https://aimdb.dev |
| repository | https://github.com/aimdb-dev/aimdb |
| max_upload_size | |
| id | 1920806 |
| size | 93,574 |
Embassy async runtime adapter for AimDB - embedded no_std environments.
aimdb-embassy-adapter provides Embassy-specific extensions for AimDB, enabling the database to run on embedded systems using the Embassy async runtime and embedded-hal peripheral abstractions.
Key Features:
Add to your Cargo.toml:
[dependencies]
aimdb-core = { version = "0.1", default-features = false }
aimdb-embassy-adapter = { version = "0.1", default-features = false, features = ["embassy-task-pool-16"] }
embassy-executor = { version = "0.6", features = ["arch-cortex-m", "executor-thread"] }
embassy-time = "0.3"
#![no_std]
#![no_main]
use aimdb_core::AimDbBuilder;
use aimdb_embassy_adapter::{EmbassyAdapter, EmbassyRecordRegistrarExt};
use embassy_executor::Spawner;
use defmt_rtt as _;
use panic_probe as _;
#[derive(Clone, Debug)]
struct SensorReading {
value: f32,
timestamp: u32,
}
#[embassy_executor::main]
async fn main(spawner: Spawner) {
// Create adapter with spawner for task management
let adapter = EmbassyAdapter::new_with_spawner(spawner.clone());
// Build database with Embassy runtime
let mut builder = AimDbBuilder::new().runtime(adapter);
builder.configure::<SensorReading>(|reg| {
// Configure buffer using Embassy extension trait
reg.buffer(aimdb_core::buffer::BufferCfg::SingleLatest);
});
let db = builder.build().unwrap();
// Use database...
defmt::info!("Database initialized");
}
The Embassy adapter uses a static task pool for dynamic spawning. Configure the pool size via feature flags:
| Feature Flag | Pool Size | Use Case |
|---|---|---|
embassy-task-pool-8 |
8 tasks | Default, small systems |
embassy-task-pool-16 |
16 tasks | Medium complexity |
embassy-task-pool-32 |
32 tasks | Complex applications |
Important: Only enable one task pool feature at a time.
[dependencies]
aimdb-embassy-adapter = {
version = "0.1",
default-features = false,
features = ["embassy-runtime", "embassy-task-pool-16"]
}
If you exceed the pool size, you'll get an ExecutorError::SpawnFailed error.
Embassy uses the standard buffer configuration API:
use aimdb_core::buffer::BufferCfg;
// SPMC Ring buffer
reg.buffer(BufferCfg::SpmcRing { capacity: 8 });
// Single latest value
reg.buffer(BufferCfg::SingleLatest);
// Mailbox (single slot)
reg.buffer(BufferCfg::Mailbox);
The adapter implements all required executor traits:
impl RuntimeAdapter for EmbassyAdapter {
fn runtime_name() -> &'static str {
"embassy"
}
}
impl TimeOps for EmbassyAdapter {
type Instant = embassy_time::Instant;
type Duration = embassy_time::Duration;
fn now(&self) -> Self::Instant {
embassy_time::Instant::now()
}
fn millis(&self, ms: u64) -> Self::Duration {
embassy_time::Duration::from_millis(ms)
}
fn sleep(&self, duration: Self::Duration) -> impl Future<Output = ()> + Send {
embassy_time::Timer::after(duration)
}
// ... other methods
}
impl Logger for EmbassyAdapter {
fn info(&self, message: &str) {
defmt::info!("{}", message);
}
fn debug(&self, message: &str) {
defmt::debug!("{}", message);
}
// ... warn, error via defmt
}
impl Spawn for EmbassyAdapter {
type SpawnToken = ();
fn spawn<F>(&self, future: F) -> ExecutorResult<Self::SpawnToken>
where
F: Future<Output = ()> + Send + 'static,
{
// Uses static task pool
// Returns () (no handle like Tokio's JoinHandle)
}
}
[features]
embassy-runtime = [] # Enable Embassy support
embassy-task-pool-8 = [] # 8-task pool (default)
embassy-task-pool-16 = [] # 16-task pool
embassy-task-pool-32 = [] # 32-task pool
defmt = ["dep:defmt"] # Embedded logging
Embassy time integration:
use aimdb_embassy_adapter::EmbassyAdapter;
use embassy_time::Duration;
let adapter = EmbassyAdapter::new().unwrap();
// Get current instant
let now = adapter.now();
// Create duration
let delay = adapter.millis(1000);
// Sleep for duration
adapter.sleep(delay).await;
Efficient embedded logging:
// In your main.rs or lib.rs
use defmt_rtt as _; // Transport
use panic_probe as _; // Panic handler
// Adapter automatically uses defmt
let db = AimDb::build_with(adapter, |builder| {
// Logs appear via defmt
builder.configure::<Data>(|reg| {
// ...
})
})?;
View logs with probe-rs:
probe-rs run --chip STM32F411RETx
Tested on:
Embassy-specific errors:
use aimdb_executor::{ExecutorError, ExecutorResult};
use embassy_executor::Spawner;
let adapter = EmbassyAdapter::new_with_spawner(spawner);
// Task pool exhausted
match adapter.spawn(future) {
Ok(_) => { /* success */ },
Err(ExecutorError::SpawnFailed { message }) => {
defmt::error!("Task pool full: {}", message);
// Increase pool size via feature flag
},
Err(ExecutorError::RuntimeUnavailable { message }) => {
defmt::error!("No spawner: {}", message);
// Use EmbassyAdapter::new_with_spawner()
},
_ => {}
}
Embassy environments are memory-constrained:
heapless collections#[embassy_executor::task] for spawned tasksdefmt instead of format!Optimized for embedded:
#![no_std]
#![no_main]
use aimdb_core::AimDbBuilder;
use aimdb_embassy_adapter::{EmbassyAdapter, EmbassyRecordRegistrarExt};
use embassy_executor::Spawner;
use defmt_rtt as _;
use panic_probe as _;
#[derive(Clone, Debug)]
struct Temperature {
celsius: f32,
sensor_id: &'static str,
}
#[embassy_executor::main]
async fn main(spawner: Spawner) {
defmt::info!("Starting AimDB on Embassy");
// Initialize hardware
let p = embassy_stm32::init(Default::default());
// Create adapter with spawner
let adapter = EmbassyAdapter::new_with_spawner(spawner.clone());
// Build database
let mut builder = AimDbBuilder::new().runtime(adapter);
builder.configure::<Temperature>(|reg| {
reg.buffer(aimdb_core::buffer::BufferCfg::SingleLatest);
});
let db = builder.build().unwrap();
// Start producer/consumer tasks
// (implementation depends on your use case)
defmt::info!("Database ready");
}
# Test compilation for embedded target
cargo build -p aimdb-embassy-adapter \
--target thumbv7em-none-eabihf \
--no-default-features \
--features embassy-task-pool-16
Use probe-rs or cargo-embed:
cargo embed --chip STM32F411RETx --release
See repository examples:
examples/embassy-mqtt-connector-demo - Embassy with MQTT on RP2040| Feature | Embassy Adapter | Tokio Adapter |
|---|---|---|
| Environment | no_std | std |
| Target | Embedded MCUs | Servers, desktop |
| Threading | No | Yes |
| Heap allocation | Limited/None | Unlimited |
| Logging | defmt | tracing |
| Task spawn | Static pool | Dynamic |
| SpawnToken type | () |
JoinHandle |
| Instant type | embassy Instant | tokio Instant |
| Duration type | embassy Duration | tokio Duration |
Generate API docs:
cargo doc -p aimdb-embassy-adapter --open
See LICENSE file.