Update embassy, embedded-test (#3945)

This commit is contained in:
Dániel Buga 2025-09-05 15:51:26 +02:00 committed by GitHub
parent 67e0b65ee4
commit 91e0cea412
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 144 additions and 105 deletions

View File

@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Updates for embassy-executor 0.9, embassy-time 0.5 (#3945)
### Fixed

View File

@ -26,15 +26,16 @@ static_cell = "2.1.0"
# Unstable dependencies that are not (strictly) part of the public API
document-features = "0.2.11"
embassy-sync = { version = "0.7" }
embassy-time-driver = { version = "0.2.0", features = [ "tick-hz-1_000_000" ] }
embassy-time-queue-utils = { version = "0.1.0", features = ["_generic-queue"] }
embassy-sync = { version = "0.7.0" }
embassy-time-driver = { version = "0.2.1", features = [ "tick-hz-1_000_000" ] }
embassy-time-queue-utils = { version = "0.3.0", features = ["_generic-queue"] }
esp-config = { version = "0.5.0", path = "../esp-config" }
esp-sync = { version = "0.0.0", path = "../esp-sync" }
macros = { version = "0.19.0", features = ["embassy"], package = "esp-hal-procmacros", path = "../esp-hal-procmacros" }
# Optional dependencies that enable ecosystem support.
embassy-executor = { version = "0.7.0", features = ["timer-item-payload-size-4"], optional = true }
embassy-executor = { version = "0.9.0", optional = true }
embassy-executor-timer-queue = { version = "0.1.0", features = ["timer-item-size-6-words"] }
# Logging interfaces, they are mutually exclusive so they need to be behind separate features.
defmt = { version = "1.0.1", optional = true }

View File

@ -292,7 +292,7 @@ impl EmbassyTimer {
// time. In this case the interrupt handler will pend a wake-up when we exit the
// critical section.
//
// This is correct behavior. See https://docs.rs/embassy-time-driver/0.1.0/embassy_time_driver/trait.Driver.html#tymethod.set_alarm
// This is correct behavior. See https://docs.rs/embassy-time-driver/0.2.1/embassy_time_driver/trait.Driver.html#tymethod.set_alarm
// (... the driver should return true and arrange to call the alarm callback as
// soon as possible, but not synchronously.)
@ -321,7 +321,9 @@ impl Driver for EmbassyTimer {
// If we have multiple queues, we have integrated timers and our own timer queue
// implementation.
use embassy_executor::raw::Executor as RawExecutor;
use portable_atomic::{AtomicPtr, Ordering};
use portable_atomic::Ordering;
use crate::timer_queue::queue_impl::QueueItem;
let task = embassy_executor::raw::task_from_waker(waker);
@ -329,10 +331,7 @@ impl Driver for EmbassyTimer {
// so the executor is guaranteed to be set to a non-null value.
let mut executor = task.executor().unwrap_unchecked() as *const RawExecutor;
let owner = task
.timer_queue_item()
.payload
.as_ref::<AtomicPtr<RawExecutor>>();
let owner = &task.timer_queue_item().as_mut::<QueueItem>().owner;
// Try to take ownership over the timer item.
let owner = owner.compare_exchange(

View File

@ -94,18 +94,47 @@ impl TimerQueue {
}
#[cfg(integrated_timers)]
mod queue_impl {
use core::{cell::Cell, cmp::min, ptr, task::Waker};
pub(crate) mod queue_impl {
use core::{
cell::Cell,
cmp::min,
ptr::{self, NonNull},
task::Waker,
};
use embassy_executor::raw::TaskRef;
use embassy_executor::raw::Executor as RawExecutor;
use embassy_executor_timer_queue::TimerQueueItem;
use portable_atomic::{AtomicPtr, Ordering};
/// An item in the timer queue.
#[derive(Default)]
pub(crate) struct QueueItem {
/// The next item in the queue.
///
/// If this field contains `Some`, the item is in the queue. The last item in the queue has
/// a value of `Some(dangling_pointer)`
pub next: Cell<Option<NonNull<QueueItem>>>,
/// The time at which this item expires.
pub expires_at: u64,
/// The registered waker. If Some, the item is enqueued in the timer queue.
pub waker: Option<Waker>,
pub owner: AtomicPtr<RawExecutor>,
}
unsafe impl Sync for QueueItem {}
/// Copy of the embassy integrated timer queue, that clears the owner upon
/// dequeueing.
pub(super) struct RawQueue {
head: Cell<Option<TaskRef>>,
head: Cell<Option<NonNull<QueueItem>>>,
}
unsafe impl Send for RawQueue {}
unsafe impl Sync for RawQueue {}
impl RawQueue {
/// Creates a new timer queue.
pub const fn new() -> Self {
@ -119,25 +148,43 @@ mod queue_impl {
/// If this function returns `true`, the called should find the next
/// expiration time and set a new alarm for that time.
pub fn schedule_wake(&mut self, at: u64, waker: &Waker) -> bool {
let task = embassy_executor::raw::task_from_waker(waker);
let item = task.timer_queue_item();
if item.next.get().is_none() {
// If not in the queue, add it and update.
let prev = self.head.replace(Some(task));
item.next.set(if prev.is_none() {
Some(unsafe { TaskRef::dangling() })
} else {
prev
});
item.expires_at.set(at);
true
} else if at <= item.expires_at.get() {
// If expiration is sooner than previously set, update.
item.expires_at.set(at);
true
} else {
// Task does not need to be updated.
false
let item = unsafe {
// Safety: the `&mut self`, along with the Safety note of the Queue, are sufficient
// to ensure that this function creates the only mutable reference
// to the queue item.
TimerQueueItem::from_embassy_waker(waker)
};
let item = unsafe { item.as_mut::<QueueItem>() };
match item.waker.as_ref() {
Some(_) if at <= item.expires_at => {
// If expiration is sooner than previously set, update.
item.expires_at = at;
// The waker is always stored in its own queue item, so we don't need to update
// it.
// Trigger a queue update in case this item can be immediately dequeued.
true
}
Some(_) => {
// Queue item does not need to be updated, the task will be scheduled to be
// woken before the new expiration.
false
}
None => {
// If not in the queue, add it and update.
let mut item_ptr = NonNull::from(item);
let prev = self.head.replace(Some(item_ptr));
let item = unsafe { item_ptr.as_mut() };
item.expires_at = at;
item.waker = Some(waker.clone());
item.next.set(prev);
// The default implementation doesn't care about the
// opaque payload, leave it unchanged.
true
}
}
}
@ -149,45 +196,36 @@ mod queue_impl {
pub fn next_expiration(&mut self, now: u64) -> u64 {
let mut next_expiration = u64::MAX;
self.retain(|p| {
let item = p.timer_queue_item();
let expires = item.expires_at.get();
if expires <= now {
self.retain(|item| {
if item.expires_at <= now {
// Timer expired, process task.
embassy_executor::raw::wake_task(p);
if let Some(waker) = item.waker.take() {
waker.wake();
}
false
} else {
// Timer didn't yet expire, or never expires.
next_expiration = min(next_expiration, expires);
expires != u64::MAX
next_expiration = min(next_expiration, item.expires_at);
item.expires_at != u64::MAX
}
});
next_expiration
}
fn retain(&self, mut f: impl FnMut(TaskRef) -> bool) {
fn retain(&self, mut f: impl FnMut(&mut QueueItem) -> bool) {
let mut prev = &self.head;
while let Some(p) = prev.get() {
if unsafe { p == TaskRef::dangling() } {
// prev was the last item, stop
break;
}
let item = p.timer_queue_item();
if f(p) {
while let Some(mut p) = prev.get() {
let item = unsafe { p.as_mut() };
if f(item) {
// Skip to next
prev = &item.next;
} else {
// Remove it
prev.set(item.next.get());
// Clear owner
unsafe {
// SAFETY: our payload is an AtomicPtr.
item.payload
.as_ref::<AtomicPtr<()>>()
.store(ptr::null_mut(), Ordering::Relaxed);
}
item.owner.store(ptr::null_mut(), Ordering::Relaxed);
item.next.set(None);
}
}

View File

@ -5,8 +5,8 @@ edition = "2024"
publish = false
[dependencies]
embassy-executor = { version = "0.7.0", features = ["task-arena-size-20480"] }
embassy-time = "0.4.0"
embassy-executor = "0.9.0"
embassy-time = "0.5.0"
esp-backtrace = { path = "../../../esp-backtrace", features = [
"panic-handler",
"println",

View File

@ -5,9 +5,9 @@ edition = "2024"
publish = false
[dependencies]
embassy-executor = { version = "0.7.0", features = ["task-arena-size-20480"] }
embassy-executor = "0.9.0"
embassy-sync = "0.7.0"
embassy-time = "0.4.0"
embassy-time = "0.5.0"
esp-backtrace = { path = "../../../esp-backtrace", features = [
"panic-handler",
"println",

View File

@ -5,9 +5,9 @@ edition = "2024"
publish = false
[dependencies]
embassy-executor = { version = "0.7.0", features = ["task-arena-size-20480"] }
embassy-executor = "0.9.0"
embassy-sync = "0.7.0"
embassy-time = "0.4.0"
embassy-time = "0.5.0"
esp-backtrace = { path = "../../../esp-backtrace", features = [
"panic-handler",
"println",

View File

@ -6,8 +6,8 @@ publish = false
[dependencies]
cfg-if = "1.0.0"
embassy-executor = { version = "0.7.0", features = ["task-arena-size-20480"] }
embassy-time = "0.4.0"
embassy-executor = "0.9.0"
embassy-time = "0.5.0"
esp-backtrace = { path = "../../../esp-backtrace", features = [
"panic-handler",
"println",

View File

@ -6,8 +6,8 @@ publish = false
[dependencies]
cfg-if = "1.0.1"
embassy-executor = { version = "0.7.0", features = ["task-arena-size-20480"] }
embassy-time = "0.4.0"
embassy-executor = "0.9.0"
embassy-time = "0.5.0"
esp-backtrace = { path = "../../../esp-backtrace", features = [
"panic-handler",
"println",

View File

@ -6,8 +6,8 @@ publish = false
[dependencies]
cfg-if = "1.0.1"
embassy-executor = { version = "0.7.0", features = ["task-arena-size-20480"] }
embassy-time = "0.4.0"
embassy-executor = "0.9.0"
embassy-time = "0.5.0"
esp-backtrace = { path = "../../../esp-backtrace", features = [
"panic-handler",
"println",

View File

@ -6,7 +6,7 @@ publish = false
[dependencies]
cfg-if = "1.0.1"
embassy-executor = { version = "0.7.0", features = ["task-arena-size-20480"] }
embassy-executor = "0.9.0"
embassy-sync = "0.7.0"
embedded-io-async = "0.6.1"
esp-backtrace = { path = "../../../esp-backtrace", features = [

View File

@ -6,8 +6,8 @@ publish = false
[dependencies]
cfg-if = "1.0.0"
embassy-executor = { version = "0.7.0", features = ["task-arena-size-20480"] }
embassy-time = "0.4.0"
embassy-executor = "0.9.0"
embassy-time = "0.5.0"
embedded-hal-async = "1.0.0"
esp-backtrace = { path = "../../../esp-backtrace", features = [
"panic-handler",

View File

@ -5,7 +5,7 @@ edition = "2024"
publish = false
[dependencies]
embassy-executor = { version = "0.7.0", features = ["task-arena-size-20480"] }
embassy-executor = "0.9.0"
embassy-futures = "0.1.1"
embassy-usb = { version = "0.5.0", default-features = false }
esp-backtrace = { path = "../../../esp-backtrace", features = [

View File

@ -5,7 +5,7 @@ edition = "2024"
publish = false
[dependencies]
embassy-executor = { version = "0.7.0", features = ["task-arena-size-20480"] }
embassy-executor = "0.9.0"
embassy-sync = "0.7.0"
embedded-io-async = "0.6.1"
esp-backtrace = { path = "../../../esp-backtrace", features = [

View File

@ -6,10 +6,10 @@ publish = false
[dependencies]
bt-hci = "0.4.0"
embassy-executor = { version = "0.7.0", features = ["task-arena-size-20480"] }
embassy-executor = "0.9.0"
embassy-futures = "0.1.1"
embassy-sync = "0.7.2"
embassy-time = "0.4.0"
embassy-time = "0.5.0"
esp-alloc = { path = "../../../esp-alloc" }
esp-backtrace = { path = "../../../esp-backtrace", features = [
"panic-handler",
@ -27,7 +27,7 @@ esp-radio = { path = "../../../esp-radio", features = [
] }
heapless = "0.9.1"
log = "0.4.27"
trouble-host = { git = "https://github.com/embassy-rs/trouble", rev = "366ee88", features = [
trouble-host = { git = "https://github.com/embassy-rs/trouble", rev = "39c5c99", features = [
"default-packet-pool-mtu-255",
"derive",
"scan",

View File

@ -6,9 +6,9 @@ publish = false
[dependencies]
bt-hci = "0.4.0"
embassy-executor = { version = "0.7.0", features = ["task-arena-size-20480"] }
embassy-executor = "0.9.0"
embassy-futures = "0.1.1"
embassy-time = "0.4.0"
embassy-time = "0.5.0"
esp-alloc = { path = "../../../esp-alloc" }
esp-backtrace = { path = "../../../esp-backtrace", features = [
"panic-handler",
@ -26,7 +26,7 @@ esp-radio = { path = "../../../esp-radio", features = [
] }
heapless = "0.9.1"
log = "0.4.27"
trouble-host = { git = "https://github.com/embassy-rs/trouble", rev = "366ee88", features = [
trouble-host = { git = "https://github.com/embassy-rs/trouble", rev = "39c5c99", features = [
"default-packet-pool-mtu-255",
"derive",
"scan",

View File

@ -6,9 +6,9 @@ publish = false
[dependencies]
cfg-if = "1.0.0"
embassy-executor = { version = "0.7.0", features = ["task-arena-size-20480"] }
embassy-executor = "0.9.0"
embassy-futures = "0.1.1"
embassy-time = "0.4.0"
embassy-time = "0.5.0"
esp-alloc = { path = "../../../esp-alloc" }
esp-backtrace = { path = "../../../esp-backtrace", features = [
"panic-handler",

View File

@ -6,9 +6,9 @@ publish = false
[dependencies]
cfg-if = "1.0.0"
embassy-executor = { version = "0.7.0", features = ["task-arena-size-20480"] }
embassy-executor = "0.9.0"
embassy-sync = "0.6.2"
embassy-time = "0.4.0"
embassy-time = "0.5.0"
esp-alloc = { path = "../../../esp-alloc" }
esp-backtrace = { path = "../../../esp-backtrace", features = [
"panic-handler",

View File

@ -8,15 +8,15 @@ publish = false
cfg-if = "1.0.0"
edge-dhcp = "0.5.0"
edge-nal = "0.5.0"
edge-nal-embassy = "0.5.0"
embassy-executor = { version = "0.7.0", features = ["task-arena-size-20480"] }
embassy-net = { version = "0.6.0", features = [
edge-nal-embassy = "0.6.0"
embassy-executor = "0.9.0"
embassy-net = { version = "0.7.0", features = [
"dhcpv4",
"medium-ethernet",
"tcp",
"udp",
] }
embassy-time = "0.4.0"
embassy-time = "0.5.0"
embedded-io-async = "0.6.1"
esp-alloc = { path = "../../../esp-alloc" }
esp-backtrace = { path = "../../../esp-backtrace", features = [

View File

@ -6,15 +6,15 @@ publish = false
[dependencies]
cfg-if = "1.0.0"
embassy-executor = { version = "0.7.0", features = ["task-arena-size-20480"] }
embassy-executor = "0.9.0"
embassy-futures = "0.1.1"
embassy-net = { version = "0.6.0", features = [
embassy-net = { version = "0.7.0", features = [
"dhcpv4",
"medium-ethernet",
"tcp",
"udp",
] }
embassy-time = "0.4.0"
embassy-time = "0.5.0"
embedded-io-async = "0.6.1"
esp-alloc = { path = "../../../esp-alloc" }
esp-backtrace = { path = "../../../esp-backtrace", features = [

View File

@ -6,14 +6,14 @@ publish = false
[dependencies]
cfg-if = "1.0.0"
embassy-executor = { version = "0.7.0", features = ["task-arena-size-20480"] }
embassy-net = { version = "0.6.0", features = [
embassy-executor = "0.9.0"
embassy-net = { version = "0.7.0", features = [
"dhcpv4",
"medium-ethernet",
"tcp",
"udp",
] }
embassy-time = "0.4.0"
embassy-time = "0.5.0"
embedded-io-async = "0.6.1"
esp-alloc = { path = "../../../esp-alloc" }
esp-backtrace = { path = "../../../esp-backtrace", features = [

View File

@ -6,14 +6,14 @@ publish = false
[dependencies]
cfg-if = "1.0.0"
embassy-executor = { version = "0.7.0", features = ["task-arena-size-10240"] }
embassy-executor = "0.9.0"
embassy-net = { version = "0.7.0", features = [
"dhcpv4",
"medium-ethernet",
"udp",
"dns",
] }
embassy-time = "0.4.0"
embassy-time = "0.5.0"
embedded-io-async = "0.6.1"
esp-alloc = { path = "../../../esp-alloc" }
esp-backtrace = { path = "../../../esp-backtrace", features = [

View File

@ -218,11 +218,11 @@ cfg-if = "1.0.0"
critical-section = "1.1.3"
defmt = "1.0.1"
defmt-rtt = { version = "1.0.0", optional = true }
embassy-executor = "0.7.0"
embassy-executor = { version = "0.9.0", default-features = false }
embassy-futures = "0.1.1"
embedded-storage = "0.3.1"
embassy-sync = "0.6.0"
embassy-time = "0.4.0"
embassy-time = "0.5.0"
embedded-hal = "1.0.0"
embedded-io = "0.6.1"
embedded-io-async = "0.6.1"
@ -244,9 +244,9 @@ semihosting = { version = "0.1", features= ["stdio", "panic-handler"] }
crypto-bigint = { version = "0.5.5", default-features = false }
digest = { version = "0.10.7", default-features = false }
elliptic-curve = { version = "0.13.8", default-features = false, features = ["sec1"] }
embassy-executor = { version = "0.7.0", default-features = false }
embassy-executor = { version = "0.9.0", default-features = false }
# Add the `embedded-test/defmt` feature for more verbose testing
embedded-test = { version = "0.6.2", default-features = false, features = ["embassy", "external-executor", "semihosting"] }
embedded-test = { version = "0.7.0-alpha.3", default-features = false, features = ["embassy", "external-executor", "semihosting"] }
hex-literal = "1.0.0"
nb = "1.1.0"
p192 = { version = "0.13.0", default-features = false, features = ["arithmetic"] }

View File

@ -13,7 +13,7 @@
#![no_std]
#![no_main]
use embassy_executor::Spawner;
use embassy_executor::SendSpawner;
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, signal::Signal};
#[cfg(aes_dma)]
use esp_hal::aes::dma::AesDmaBackend;
@ -564,7 +564,7 @@ mod tests {
let signal = mk_static!(Signal<CriticalSectionRawMutex, ()>, Signal::new());
// Start task before we'd start the AES operation
let spawner = Spawner::for_current_executor().await;
let spawner = SendSpawner::for_current_executor().await;
spawner.must_spawn(aes_task(signal));
signal.wait().await;

View File

@ -230,7 +230,7 @@ mod test {
let spawner_int = executor.start(Priority::Priority3);
spawner_int.must_spawn(test_interrupt_executor_invoker());
let spawner = embassy_executor::Spawner::for_current_executor().await;
let spawner = embassy_executor::SendSpawner::for_current_executor().await;
spawner.must_spawn(e_task30ms());
// The test ends once the interrupt executor's task has finished

View File

@ -130,7 +130,7 @@ mod tests {
#[test]
async fn test_i2s_loopback_async(ctx: Context) {
let spawner = embassy_executor::Spawner::for_current_executor().await;
let spawner = unsafe { embassy_executor::Spawner::for_current_executor().await };
let (rx_buffer, rx_descriptors, tx_buffer, tx_descriptors) =
esp_hal::dma_circular_buffers!(BUFFER_SIZE, BUFFER_SIZE);

View File

@ -8,10 +8,10 @@ publish = false
[dependencies]
blocking-network-stack = { git = "https://github.com/bjoernQ/blocking-network-stack.git", rev = "b3ecefc", optional = true }
cfg-if = "1.0.0"
embassy-executor = { version = "0.7.0", features = ["task-arena-size-12288"] }
embassy-time = "0.4.0"
embassy-executor = "0.9.0"
embassy-time = "0.5.0"
embassy-futures = "0.1.1"
embassy-net = { version = "0.6.0", features = [ "tcp", "udp", "dhcpv4", "medium-ethernet"] }
embassy-net = { version = "0.7.0", features = [ "tcp", "udp", "dhcpv4", "medium-ethernet"] }
embassy-sync = "0.6.1"
embedded-graphics = "0.8.1"
embedded-hal-async = "1.0.0"