aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-executor/Cargo.toml9
-rw-r--r--embassy-executor/src/raw/mod.rs27
-rw-r--r--embassy-executor/src/raw/timer_queue.rs12
-rw-r--r--embassy-time-driver/CHANGELOG.md51
-rw-r--r--embassy-time-queue-driver/Cargo.toml25
-rw-r--r--embassy-time-queue-driver/README.md8
-rw-r--r--embassy-time-queue-driver/build.rs1
-rw-r--r--embassy-time-queue-driver/src/lib.rs (renamed from embassy-time/src/queue.rs)42
-rw-r--r--embassy-time/Cargo.toml1
-rw-r--r--embassy-time/src/driver_mock.rs4
-rw-r--r--embassy-time/src/driver_std.rs5
-rw-r--r--embassy-time/src/driver_wasm.rs5
-rw-r--r--embassy-time/src/instant.rs6
-rw-r--r--embassy-time/src/lib.rs5
-rw-r--r--embassy-time/src/queue_generic.rs10
-rw-r--r--embassy-time/src/timer.rs16
-rw-r--r--examples/std/src/bin/serial.rs1
17 files changed, 100 insertions, 128 deletions
diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml
index c71452398..da3c9a4fc 100644
--- a/embassy-executor/Cargo.toml
+++ b/embassy-executor/Cargo.toml
@@ -33,7 +33,8 @@ log = { version = "0.4.14", optional = true }
33rtos-trace = { version = "0.1.2", optional = true } 33rtos-trace = { version = "0.1.2", optional = true }
34 34
35embassy-executor-macros = { version = "0.4.0", path = "../embassy-executor-macros" } 35embassy-executor-macros = { version = "0.4.0", path = "../embassy-executor-macros" }
36embassy-time = { version = "0.2", path = "../embassy-time", optional = true} 36embassy-time-driver = { version = "0.1.0", path = "../embassy-time-driver", optional = true }
37embassy-time-queue-driver = { version = "0.1.0", path = "../embassy-time-queue-driver", optional = true }
37critical-section = "1.1" 38critical-section = "1.1"
38 39
39document-features = "0.2.7" 40document-features = "0.2.7"
@@ -63,8 +64,8 @@ nightly = ["embassy-executor-macros/nightly"]
63# See: https://github.com/embassy-rs/embassy/pull/1263 64# See: https://github.com/embassy-rs/embassy/pull/1263
64turbowakers = [] 65turbowakers = []
65 66
66## Use timers from `embassy-time` 67## Use the executor-integrated `embassy-time` timer queue.
67integrated-timers = ["dep:embassy-time"] 68integrated-timers = ["dep:embassy-time-driver", "dep:embassy-time-queue-driver"]
68 69
69#! ### Architecture 70#! ### Architecture
70_arch = [] # some arch was picked 71_arch = [] # some arch was picked
@@ -177,4 +178,4 @@ task-arena-size-1048576 = []
177 178
178# END AUTOGENERATED CONFIG FEATURES 179# END AUTOGENERATED CONFIG FEATURES
179 180
180#! </details> \ No newline at end of file 181#! </details>
diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs
index b16a1c7c3..3f00be4a8 100644
--- a/embassy-executor/src/raw/mod.rs
+++ b/embassy-executor/src/raw/mod.rs
@@ -30,9 +30,7 @@ use core::ptr::NonNull;
30use core::task::{Context, Poll}; 30use core::task::{Context, Poll};
31 31
32#[cfg(feature = "integrated-timers")] 32#[cfg(feature = "integrated-timers")]
33use embassy_time::driver::{self, AlarmHandle}; 33use embassy_time_driver::{self, AlarmHandle};
34#[cfg(feature = "integrated-timers")]
35use embassy_time::Instant;
36#[cfg(feature = "rtos-trace")] 34#[cfg(feature = "rtos-trace")]
37use rtos_trace::trace; 35use rtos_trace::trace;
38 36
@@ -50,7 +48,7 @@ pub(crate) struct TaskHeader {
50 poll_fn: SyncUnsafeCell<Option<unsafe fn(TaskRef)>>, 48 poll_fn: SyncUnsafeCell<Option<unsafe fn(TaskRef)>>,
51 49
52 #[cfg(feature = "integrated-timers")] 50 #[cfg(feature = "integrated-timers")]
53 pub(crate) expires_at: SyncUnsafeCell<Instant>, 51 pub(crate) expires_at: SyncUnsafeCell<u64>,
54 #[cfg(feature = "integrated-timers")] 52 #[cfg(feature = "integrated-timers")]
55 pub(crate) timer_queue_item: timer_queue::TimerQueueItem, 53 pub(crate) timer_queue_item: timer_queue::TimerQueueItem,
56} 54}
@@ -123,7 +121,7 @@ impl<F: Future + 'static> TaskStorage<F> {
123 poll_fn: SyncUnsafeCell::new(None), 121 poll_fn: SyncUnsafeCell::new(None),
124 122
125 #[cfg(feature = "integrated-timers")] 123 #[cfg(feature = "integrated-timers")]
126 expires_at: SyncUnsafeCell::new(Instant::from_ticks(0)), 124 expires_at: SyncUnsafeCell::new(0),
127 #[cfg(feature = "integrated-timers")] 125 #[cfg(feature = "integrated-timers")]
128 timer_queue_item: timer_queue::TimerQueueItem::new(), 126 timer_queue_item: timer_queue::TimerQueueItem::new(),
129 }, 127 },
@@ -164,7 +162,7 @@ impl<F: Future + 'static> TaskStorage<F> {
164 this.raw.state.despawn(); 162 this.raw.state.despawn();
165 163
166 #[cfg(feature = "integrated-timers")] 164 #[cfg(feature = "integrated-timers")]
167 this.raw.expires_at.set(Instant::MAX); 165 this.raw.expires_at.set(u64::MAX);
168 } 166 }
169 Poll::Pending => {} 167 Poll::Pending => {}
170 } 168 }
@@ -328,7 +326,7 @@ pub(crate) struct SyncExecutor {
328impl SyncExecutor { 326impl SyncExecutor {
329 pub(crate) fn new(pender: Pender) -> Self { 327 pub(crate) fn new(pender: Pender) -> Self {
330 #[cfg(feature = "integrated-timers")] 328 #[cfg(feature = "integrated-timers")]
331 let alarm = unsafe { unwrap!(driver::allocate_alarm()) }; 329 let alarm = unsafe { unwrap!(embassy_time_driver::allocate_alarm()) };
332 330
333 Self { 331 Self {
334 run_queue: RunQueue::new(), 332 run_queue: RunQueue::new(),
@@ -377,18 +375,19 @@ impl SyncExecutor {
377 /// Same as [`Executor::poll`], plus you must only call this on the thread this executor was created. 375 /// Same as [`Executor::poll`], plus you must only call this on the thread this executor was created.
378 pub(crate) unsafe fn poll(&'static self) { 376 pub(crate) unsafe fn poll(&'static self) {
379 #[cfg(feature = "integrated-timers")] 377 #[cfg(feature = "integrated-timers")]
380 driver::set_alarm_callback(self.alarm, Self::alarm_callback, self as *const _ as *mut ()); 378 embassy_time_driver::set_alarm_callback(self.alarm, Self::alarm_callback, self as *const _ as *mut ());
381 379
382 #[allow(clippy::never_loop)] 380 #[allow(clippy::never_loop)]
383 loop { 381 loop {
384 #[cfg(feature = "integrated-timers")] 382 #[cfg(feature = "integrated-timers")]
385 self.timer_queue.dequeue_expired(Instant::now(), wake_task_no_pend); 383 self.timer_queue
384 .dequeue_expired(embassy_time_driver::now(), wake_task_no_pend);
386 385
387 self.run_queue.dequeue_all(|p| { 386 self.run_queue.dequeue_all(|p| {
388 let task = p.header(); 387 let task = p.header();
389 388
390 #[cfg(feature = "integrated-timers")] 389 #[cfg(feature = "integrated-timers")]
391 task.expires_at.set(Instant::MAX); 390 task.expires_at.set(u64::MAX);
392 391
393 if !task.state.run_dequeue() { 392 if !task.state.run_dequeue() {
394 // If task is not running, ignore it. This can happen in the following scenario: 393 // If task is not running, ignore it. This can happen in the following scenario:
@@ -418,7 +417,7 @@ impl SyncExecutor {
418 // If this is already in the past, set_alarm might return false 417 // If this is already in the past, set_alarm might return false
419 // In that case do another poll loop iteration. 418 // In that case do another poll loop iteration.
420 let next_expiration = self.timer_queue.next_expiration(); 419 let next_expiration = self.timer_queue.next_expiration();
421 if driver::set_alarm(self.alarm, next_expiration.as_ticks()) { 420 if embassy_time_driver::set_alarm(self.alarm, next_expiration) {
422 break; 421 break;
423 } 422 }
424 } 423 }
@@ -568,8 +567,8 @@ pub fn wake_task_no_pend(task: TaskRef) {
568struct TimerQueue; 567struct TimerQueue;
569 568
570#[cfg(feature = "integrated-timers")] 569#[cfg(feature = "integrated-timers")]
571impl embassy_time::queue::TimerQueue for TimerQueue { 570impl embassy_time_queue_driver::TimerQueue for TimerQueue {
572 fn schedule_wake(&'static self, at: Instant, waker: &core::task::Waker) { 571 fn schedule_wake(&'static self, at: u64, waker: &core::task::Waker) {
573 let task = waker::task_from_waker(waker); 572 let task = waker::task_from_waker(waker);
574 let task = task.header(); 573 let task = task.header();
575 unsafe { 574 unsafe {
@@ -580,7 +579,7 @@ impl embassy_time::queue::TimerQueue for TimerQueue {
580} 579}
581 580
582#[cfg(feature = "integrated-timers")] 581#[cfg(feature = "integrated-timers")]
583embassy_time::timer_queue_impl!(static TIMER_QUEUE: TimerQueue = TimerQueue); 582embassy_time_queue_driver::timer_queue_impl!(static TIMER_QUEUE: TimerQueue = TimerQueue);
584 583
585#[cfg(feature = "rtos-trace")] 584#[cfg(feature = "rtos-trace")]
586impl rtos_trace::RtosTraceOSCallbacks for Executor { 585impl rtos_trace::RtosTraceOSCallbacks for Executor {
diff --git a/embassy-executor/src/raw/timer_queue.rs b/embassy-executor/src/raw/timer_queue.rs
index 59a3b43f5..94a5f340b 100644
--- a/embassy-executor/src/raw/timer_queue.rs
+++ b/embassy-executor/src/raw/timer_queue.rs
@@ -1,7 +1,5 @@
1use core::cmp::min; 1use core::cmp::min;
2 2
3use embassy_time::Instant;
4
5use super::TaskRef; 3use super::TaskRef;
6use crate::raw::util::SyncUnsafeCell; 4use crate::raw::util::SyncUnsafeCell;
7 5
@@ -30,7 +28,7 @@ impl TimerQueue {
30 28
31 pub(crate) unsafe fn update(&self, p: TaskRef) { 29 pub(crate) unsafe fn update(&self, p: TaskRef) {
32 let task = p.header(); 30 let task = p.header();
33 if task.expires_at.get() != Instant::MAX { 31 if task.expires_at.get() != u64::MAX {
34 if task.state.timer_enqueue() { 32 if task.state.timer_enqueue() {
35 task.timer_queue_item.next.set(self.head.get()); 33 task.timer_queue_item.next.set(self.head.get());
36 self.head.set(Some(p)); 34 self.head.set(Some(p));
@@ -38,18 +36,18 @@ impl TimerQueue {
38 } 36 }
39 } 37 }
40 38
41 pub(crate) unsafe fn next_expiration(&self) -> Instant { 39 pub(crate) unsafe fn next_expiration(&self) -> u64 {
42 let mut res = Instant::MAX; 40 let mut res = u64::MAX;
43 self.retain(|p| { 41 self.retain(|p| {
44 let task = p.header(); 42 let task = p.header();
45 let expires = task.expires_at.get(); 43 let expires = task.expires_at.get();
46 res = min(res, expires); 44 res = min(res, expires);
47 expires != Instant::MAX 45 expires != u64::MAX
48 }); 46 });
49 res 47 res
50 } 48 }
51 49
52 pub(crate) unsafe fn dequeue_expired(&self, now: Instant, on_task: impl Fn(TaskRef)) { 50 pub(crate) unsafe fn dequeue_expired(&self, now: u64, on_task: impl Fn(TaskRef)) {
53 self.retain(|p| { 51 self.retain(|p| {
54 let task = p.header(); 52 let task = p.header();
55 if task.expires_at.get() <= now { 53 if task.expires_at.get() <= now {
diff --git a/embassy-time-driver/CHANGELOG.md b/embassy-time-driver/CHANGELOG.md
deleted file mode 100644
index d8c0c7d08..000000000
--- a/embassy-time-driver/CHANGELOG.md
+++ /dev/null
@@ -1,51 +0,0 @@
1# Changelog
2
3All notable changes to this project will be documented in this file.
4
5The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
8## 0.2.0 - 2023-12-04
9
10- Added tick rates in multiples of 10 kHz
11- Remove nightly and unstable-traits features in preparation for 1.75.
12- Update heapless to 0.8.
13
14## 0.1.5 - 2023-10-16
15
16- Added `links` key to Cargo.toml, to prevent multiple copies of this crate in the same binary.
17 Needed because different copies might get different tick rates, causing
18 wrong delays if the time driver is using one copy and user code is using another.
19 This is especially common when mixing crates from crates.io and git.
20
21## 0.1.4 - 2023-10-12
22
23- Added more tick rates
24
25## 0.1.3 - 2023-08-28
26
27- Update `embedded-hal-async` to `1.0.0-rc.2`
28- Update `embedded-hal v1` to `1.0.0-rc.2`
29
30## 0.1.2 - 2023-07-05
31
32- Update `embedded-hal-async` to `0.2.0-alpha.2`.
33- Update `embedded-hal v1` to `1.0.0-alpha.11`. (Note: v0.2 support is kept unchanged).
34
35## 0.1.1 - 2023-04-13
36
37- Update `embedded-hal-async` to `0.2.0-alpha.1` (uses `async fn` in traits).
38- Update `embedded-hal v1` to `1.0.0-alpha.10`. (Note: v0.2 support is kept unchanged).
39- Remove dep on `embassy-sync`.
40- Fix reentrancy issues in the `std` time driver (#1177)
41- Add `Duration::from_hz()`.
42- impl `From` conversions to/from `core::time::Duration`.
43- Add `#[must_use]` to all futures.
44- Add inherent `async fn tick()` to `Ticker`, so you can use it directly without the `Stream` trait.
45- Add more tick rates.
46- impl `Default` for `Signal`
47- Remove unnecessary uses of `atomic-polyfill`
48
49## 0.1.0 - 2022-08-26
50
51- First release
diff --git a/embassy-time-queue-driver/Cargo.toml b/embassy-time-queue-driver/Cargo.toml
new file mode 100644
index 000000000..85ee1da1b
--- /dev/null
+++ b/embassy-time-queue-driver/Cargo.toml
@@ -0,0 +1,25 @@
1[package]
2name = "embassy-time-queue-driver"
3version = "0.1.0"
4edition = "2021"
5description = "Timer queue driver trait for embassy-time"
6repository = "https://github.com/embassy-rs/embassy"
7readme = "README.md"
8license = "MIT OR Apache-2.0"
9categories = [
10 "embedded",
11 "no-std",
12 "concurrency",
13 "asynchronous",
14]
15
16# Prevent multiple copies of this crate in the same binary.
17# Needed because different copies might get different tick rates, causing
18# wrong delays if the time driver is using one copy and user code is using another.
19# This is especially common when mixing crates from crates.io and git.
20links = "embassy-time-queue"
21
22[package.metadata.embassy_docs]
23src_base = "https://github.com/embassy-rs/embassy/blob/embassy-time-queue-driver-v$VERSION/embassy-time-queue-driver/src/"
24src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-time-queue-driver/src/"
25target = "x86_64-unknown-linux-gnu"
diff --git a/embassy-time-queue-driver/README.md b/embassy-time-queue-driver/README.md
new file mode 100644
index 000000000..8852b0358
--- /dev/null
+++ b/embassy-time-queue-driver/README.md
@@ -0,0 +1,8 @@
1# embassy-time-queue-driver
2
3This crate contains the driver trait used by the [`embassy-time`](https://crates.io/crates/embassy-time) timer queue.
4
5You should rarely need to use this crate directly. Only use it when implementing your own timer queue.
6
7There is two timer queue implementations, one in `embassy-time` enabled by the `generic-queue` feature, and
8another in `embassy-executor` enabled by the `integrated-timers` feature.
diff --git a/embassy-time-queue-driver/build.rs b/embassy-time-queue-driver/build.rs
new file mode 100644
index 000000000..f328e4d9d
--- /dev/null
+++ b/embassy-time-queue-driver/build.rs
@@ -0,0 +1 @@
fn main() {}
diff --git a/embassy-time/src/queue.rs b/embassy-time-queue-driver/src/lib.rs
index d65197c54..50736e8c7 100644
--- a/embassy-time/src/queue.rs
+++ b/embassy-time-queue-driver/src/lib.rs
@@ -1,20 +1,14 @@
1//! Timer queue implementation 1#![no_std]
2//! 2#![doc = include_str!("../README.md")]
3//! This module defines the interface a timer queue needs to implement to power the `embassy_time` module. 3#![warn(missing_docs)]
4//! 4
5//! # Implementing a timer queue 5//! ## Implementing a timer queue
6//! 6//!
7//! - Define a struct `MyTimerQueue` 7//! - Define a struct `MyTimerQueue`
8//! - Implement [`TimerQueue`] for it 8//! - Implement [`TimerQueue`] for it
9//! - Register it as the global timer queue with [`timer_queue_impl`](crate::timer_queue_impl). 9//! - Register it as the global timer queue with [`timer_queue_impl`](crate::timer_queue_impl).
10//! 10//!
11//! # Linkage details 11//! ## Example
12//!
13//! Check the documentation of the [`driver`](crate::driver) module for more information.
14//!
15//! Similarly to driver, if there is none or multiple timer queues in the crate tree, linking will fail.
16//!
17//! # Example
18//! 12//!
19//! ``` 13//! ```
20//! use core::task::Waker; 14//! use core::task::Waker;
@@ -25,23 +19,29 @@
25//! struct MyTimerQueue{}; // not public! 19//! struct MyTimerQueue{}; // not public!
26//! 20//!
27//! impl TimerQueue for MyTimerQueue { 21//! impl TimerQueue for MyTimerQueue {
28//! fn schedule_wake(&'static self, at: Instant, waker: &Waker) { 22//! fn schedule_wake(&'static self, at: u64, waker: &Waker) {
29//! todo!() 23//! todo!()
30//! } 24//! }
31//! } 25//! }
32//! ``` 26//!
33//! ```ignore 27//! embassy_time_queue_driver::timer_queue_impl!(static QUEUE: MyTimerQueue = MyTimerQueue{});
34//! embassy_time::timer_queue_impl!(static QUEUE: MyTimerQueue = MyTimerQueue{});
35//! ``` 28//! ```
36use core::task::Waker; 29use core::task::Waker;
37 30
38use crate::Instant;
39
40/// Timer queue 31/// Timer queue
41pub trait TimerQueue { 32pub trait TimerQueue {
42 /// Schedules a waker in the queue to be awoken at moment `at`. 33 /// Schedules a waker in the queue to be awoken at moment `at`.
43 /// If this moment is in the past, the waker might be awoken immediately. 34 /// If this moment is in the past, the waker might be awoken immediately.
44 fn schedule_wake(&'static self, at: Instant, waker: &Waker); 35 fn schedule_wake(&'static self, at: u64, waker: &Waker);
36}
37
38extern "Rust" {
39 fn _embassy_time_schedule_wake(at: u64, waker: &Waker);
40}
41
42/// Schedule the given waker to be woken at `at`.
43pub fn schedule_wake(at: u64, waker: &Waker) {
44 unsafe { _embassy_time_schedule_wake(at, waker) }
45} 45}
46 46
47/// Set the TimerQueue implementation. 47/// Set the TimerQueue implementation.
@@ -53,8 +53,8 @@ macro_rules! timer_queue_impl {
53 static $name: $t = $val; 53 static $name: $t = $val;
54 54
55 #[no_mangle] 55 #[no_mangle]
56 fn _embassy_time_schedule_wake(at: $crate::Instant, waker: &core::task::Waker) { 56 fn _embassy_time_schedule_wake(at: u64, waker: &core::task::Waker) {
57 <$t as $crate::queue::TimerQueue>::schedule_wake(&$name, at, waker); 57 <$t as $crate::TimerQueue>::schedule_wake(&$name, at, waker);
58 } 58 }
59 }; 59 };
60} 60}
diff --git a/embassy-time/Cargo.toml b/embassy-time/Cargo.toml
index 729a2bd4f..f27de8ab4 100644
--- a/embassy-time/Cargo.toml
+++ b/embassy-time/Cargo.toml
@@ -398,6 +398,7 @@ tick-hz-5_242_880_000 = ["embassy-time-driver/tick-hz-5_242_880_000"]
398 398
399[dependencies] 399[dependencies]
400embassy-time-driver = { version = "0.1.0", path = "../embassy-time-driver" } 400embassy-time-driver = { version = "0.1.0", path = "../embassy-time-driver" }
401embassy-time-queue-driver = { version = "0.1.0", path = "../embassy-time-queue-driver" }
401 402
402defmt = { version = "0.3", optional = true } 403defmt = { version = "0.3", optional = true }
403log = { version = "0.4.14", optional = true } 404log = { version = "0.4.14", optional = true }
diff --git a/embassy-time/src/driver_mock.rs b/embassy-time/src/driver_mock.rs
index 7abc2bd70..8587f9172 100644
--- a/embassy-time/src/driver_mock.rs
+++ b/embassy-time/src/driver_mock.rs
@@ -1,8 +1,8 @@
1use core::cell::RefCell; 1use core::cell::RefCell;
2 2
3use critical_section::Mutex as CsMutex; 3use critical_section::Mutex as CsMutex;
4use embassy_time_driver::{AlarmHandle, Driver};
4 5
5use crate::driver::{AlarmHandle, Driver};
6use crate::{Duration, Instant}; 6use crate::{Duration, Instant};
7 7
8/// A mock driver that can be manually advanced. 8/// A mock driver that can be manually advanced.
@@ -28,7 +28,7 @@ use crate::{Duration, Instant};
28/// ``` 28/// ```
29pub struct MockDriver(CsMutex<RefCell<InnerMockDriver>>); 29pub struct MockDriver(CsMutex<RefCell<InnerMockDriver>>);
30 30
31crate::driver::time_driver_impl!(static DRIVER: MockDriver = MockDriver::new()); 31embassy_time_driver::time_driver_impl!(static DRIVER: MockDriver = MockDriver::new());
32 32
33impl MockDriver { 33impl MockDriver {
34 /// Creates a new mock driver. 34 /// Creates a new mock driver.
diff --git a/embassy-time/src/driver_std.rs b/embassy-time/src/driver_std.rs
index 3b5524f9e..d182f8331 100644
--- a/embassy-time/src/driver_std.rs
+++ b/embassy-time/src/driver_std.rs
@@ -6,8 +6,7 @@ use std::time::{Duration as StdDuration, Instant as StdInstant};
6use std::{mem, ptr, thread}; 6use std::{mem, ptr, thread};
7 7
8use critical_section::Mutex as CsMutex; 8use critical_section::Mutex as CsMutex;
9 9use embassy_time_driver::{AlarmHandle, Driver};
10use crate::driver::{AlarmHandle, Driver};
11 10
12const ALARM_COUNT: usize = 4; 11const ALARM_COUNT: usize = 4;
13 12
@@ -45,7 +44,7 @@ struct TimeDriver {
45} 44}
46 45
47const ALARM_NEW: AlarmState = AlarmState::new(); 46const ALARM_NEW: AlarmState = AlarmState::new();
48crate::driver::time_driver_impl!(static DRIVER: TimeDriver = TimeDriver { 47embassy_time_driver::time_driver_impl!(static DRIVER: TimeDriver = TimeDriver {
49 alarm_count: AtomicU8::new(0), 48 alarm_count: AtomicU8::new(0),
50 49
51 once: Once::new(), 50 once: Once::new(),
diff --git a/embassy-time/src/driver_wasm.rs b/embassy-time/src/driver_wasm.rs
index d75856c26..ad884f060 100644
--- a/embassy-time/src/driver_wasm.rs
+++ b/embassy-time/src/driver_wasm.rs
@@ -4,11 +4,10 @@ use std::mem::MaybeUninit;
4use std::ptr; 4use std::ptr;
5use std::sync::{Mutex, Once}; 5use std::sync::{Mutex, Once};
6 6
7use embassy_time_driver::{AlarmHandle, Driver};
7use wasm_bindgen::prelude::*; 8use wasm_bindgen::prelude::*;
8use wasm_timer::Instant as StdInstant; 9use wasm_timer::Instant as StdInstant;
9 10
10use crate::driver::{AlarmHandle, Driver};
11
12const ALARM_COUNT: usize = 4; 11const ALARM_COUNT: usize = 4;
13 12
14struct AlarmState { 13struct AlarmState {
@@ -42,7 +41,7 @@ struct TimeDriver {
42} 41}
43 42
44const ALARM_NEW: AlarmState = AlarmState::new(); 43const ALARM_NEW: AlarmState = AlarmState::new();
45crate::driver::time_driver_impl!(static DRIVER: TimeDriver = TimeDriver { 44embassy_time_driver::time_driver_impl!(static DRIVER: TimeDriver = TimeDriver {
46 alarm_count: AtomicU8::new(0), 45 alarm_count: AtomicU8::new(0),
47 once: Once::new(), 46 once: Once::new(),
48 alarms: UninitCell::uninit(), 47 alarms: UninitCell::uninit(),
diff --git a/embassy-time/src/instant.rs b/embassy-time/src/instant.rs
index 5571cdd15..909f1b173 100644
--- a/embassy-time/src/instant.rs
+++ b/embassy-time/src/instant.rs
@@ -1,7 +1,7 @@
1use core::fmt; 1use core::fmt;
2use core::ops::{Add, AddAssign, Sub, SubAssign}; 2use core::ops::{Add, AddAssign, Sub, SubAssign};
3 3
4use super::{driver, Duration, GCD_1K, GCD_1M, TICK_HZ}; 4use super::{Duration, GCD_1K, GCD_1M, TICK_HZ};
5 5
6#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] 6#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
7#[cfg_attr(feature = "defmt", derive(defmt::Format))] 7#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -18,7 +18,9 @@ impl Instant {
18 18
19 /// Returns an Instant representing the current time. 19 /// Returns an Instant representing the current time.
20 pub fn now() -> Instant { 20 pub fn now() -> Instant {
21 Instant { ticks: driver::now() } 21 Instant {
22 ticks: embassy_time_driver::now(),
23 }
22 } 24 }
23 25
24 /// Create an Instant from a tick count since system boot. 26 /// Create an Instant from a tick count since system boot.
diff --git a/embassy-time/src/lib.rs b/embassy-time/src/lib.rs
index 3f8c09f1a..d27eb92f6 100644
--- a/embassy-time/src/lib.rs
+++ b/embassy-time/src/lib.rs
@@ -10,12 +10,9 @@
10// This mod MUST go first, so that the others see its macros. 10// This mod MUST go first, so that the others see its macros.
11pub(crate) mod fmt; 11pub(crate) mod fmt;
12 12
13pub use embassy_time_driver as driver;
14
15mod delay; 13mod delay;
16mod duration; 14mod duration;
17mod instant; 15mod instant;
18pub mod queue;
19mod timer; 16mod timer;
20 17
21#[cfg(feature = "mock-driver")] 18#[cfg(feature = "mock-driver")]
@@ -32,8 +29,8 @@ mod driver_wasm;
32mod queue_generic; 29mod queue_generic;
33 30
34pub use delay::{block_for, Delay}; 31pub use delay::{block_for, Delay};
35pub use driver::TICK_HZ;
36pub use duration::Duration; 32pub use duration::Duration;
33pub use embassy_time_driver::TICK_HZ;
37pub use instant::Instant; 34pub use instant::Instant;
38pub use timer::{with_timeout, Ticker, TimeoutError, Timer}; 35pub use timer::{with_timeout, Ticker, TimeoutError, Timer};
39 36
diff --git a/embassy-time/src/queue_generic.rs b/embassy-time/src/queue_generic.rs
index 829368ffc..cf7a986d5 100644
--- a/embassy-time/src/queue_generic.rs
+++ b/embassy-time/src/queue_generic.rs
@@ -3,10 +3,10 @@ use core::cmp::{min, Ordering};
3use core::task::Waker; 3use core::task::Waker;
4 4
5use critical_section::Mutex; 5use critical_section::Mutex;
6use embassy_time_driver::{allocate_alarm, set_alarm, set_alarm_callback, AlarmHandle};
7use embassy_time_queue_driver::TimerQueue;
6use heapless::Vec; 8use heapless::Vec;
7 9
8use crate::driver::{allocate_alarm, set_alarm, set_alarm_callback, AlarmHandle};
9use crate::queue::TimerQueue;
10use crate::Instant; 10use crate::Instant;
11 11
12#[cfg(feature = "generic-queue-8")] 12#[cfg(feature = "generic-queue-8")]
@@ -167,12 +167,12 @@ impl Queue {
167} 167}
168 168
169impl TimerQueue for Queue { 169impl TimerQueue for Queue {
170 fn schedule_wake(&'static self, at: Instant, waker: &Waker) { 170 fn schedule_wake(&'static self, at: u64, waker: &Waker) {
171 Queue::schedule_wake(self, at, waker); 171 Queue::schedule_wake(self, Instant::from_ticks(at), waker);
172 } 172 }
173} 173}
174 174
175crate::timer_queue_impl!(static QUEUE: Queue = Queue::new()); 175embassy_time_queue_driver::timer_queue_impl!(static QUEUE: Queue = Queue::new());
176 176
177#[cfg(test)] 177#[cfg(test)]
178#[cfg(feature = "mock-driver")] 178#[cfg(feature = "mock-driver")]
diff --git a/embassy-time/src/timer.rs b/embassy-time/src/timer.rs
index 2705ba03f..565a65cb8 100644
--- a/embassy-time/src/timer.rs
+++ b/embassy-time/src/timer.rs
@@ -1,6 +1,6 @@
1use core::future::{poll_fn, Future}; 1use core::future::{poll_fn, Future};
2use core::pin::Pin; 2use core::pin::Pin;
3use core::task::{Context, Poll, Waker}; 3use core::task::{Context, Poll};
4 4
5use futures_util::future::{select, Either}; 5use futures_util::future::{select, Either};
6use futures_util::stream::FusedStream; 6use futures_util::stream::FusedStream;
@@ -116,7 +116,7 @@ impl Future for Timer {
116 if self.yielded_once && self.expires_at <= Instant::now() { 116 if self.yielded_once && self.expires_at <= Instant::now() {
117 Poll::Ready(()) 117 Poll::Ready(())
118 } else { 118 } else {
119 schedule_wake(self.expires_at, cx.waker()); 119 embassy_time_queue_driver::schedule_wake(self.expires_at.as_ticks(), cx.waker());
120 self.yielded_once = true; 120 self.yielded_once = true;
121 Poll::Pending 121 Poll::Pending
122 } 122 }
@@ -185,7 +185,7 @@ impl Ticker {
185 self.expires_at += dur; 185 self.expires_at += dur;
186 Poll::Ready(()) 186 Poll::Ready(())
187 } else { 187 } else {
188 schedule_wake(self.expires_at, cx.waker()); 188 embassy_time_queue_driver::schedule_wake(self.expires_at.as_ticks(), cx.waker());
189 Poll::Pending 189 Poll::Pending
190 } 190 }
191 }) 191 })
@@ -202,7 +202,7 @@ impl Stream for Ticker {
202 self.expires_at += dur; 202 self.expires_at += dur;
203 Poll::Ready(Some(())) 203 Poll::Ready(Some(()))
204 } else { 204 } else {
205 schedule_wake(self.expires_at, cx.waker()); 205 embassy_time_queue_driver::schedule_wake(self.expires_at.as_ticks(), cx.waker());
206 Poll::Pending 206 Poll::Pending
207 } 207 }
208 } 208 }
@@ -214,11 +214,3 @@ impl FusedStream for Ticker {
214 false 214 false
215 } 215 }
216} 216}
217
218extern "Rust" {
219 fn _embassy_time_schedule_wake(at: Instant, waker: &Waker);
220}
221
222fn schedule_wake(at: Instant, waker: &Waker) {
223 unsafe { _embassy_time_schedule_wake(at, waker) }
224}
diff --git a/examples/std/src/bin/serial.rs b/examples/std/src/bin/serial.rs
index 435089aad..10c85511d 100644
--- a/examples/std/src/bin/serial.rs
+++ b/examples/std/src/bin/serial.rs
@@ -3,6 +3,7 @@ mod serial_port;
3 3
4use async_io::Async; 4use async_io::Async;
5use embassy_executor::Executor; 5use embassy_executor::Executor;
6use embassy_time as _;
6use embedded_io_async::Read; 7use embedded_io_async::Read;
7use log::*; 8use log::*;
8use nix::sys::termios; 9use nix::sys::termios;