aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias <[email protected]>2022-10-27 07:12:34 +0200
committerMathias <[email protected]>2022-10-27 07:12:34 +0200
commitc871fe0848e50c8682b8a8d9fe8da31ca9185592 (patch)
treee24f9edc23385080968d4b427aed3eddb4bd2f21
parent3c6c382465131c6f76567f976198b77e327df4b2 (diff)
parent61560e740dea1b4c7ca036dafd66c834a1ff92e2 (diff)
Rebase on master
-rw-r--r--embassy-embedded-hal/Cargo.toml2
-rw-r--r--embassy-executor/src/raw/mod.rs91
-rw-r--r--embassy-lora/Cargo.toml2
-rw-r--r--embassy-net/Cargo.toml2
-rw-r--r--embassy-net/src/tcp.rs18
-rw-r--r--embassy-nrf/Cargo.toml24
-rw-r--r--embassy-nrf/src/buffered_uarte.rs16
-rw-r--r--embassy-nrf/src/chips/nrf52805.rs4
-rw-r--r--embassy-nrf/src/chips/nrf52810.rs16
-rw-r--r--embassy-nrf/src/chips/nrf52811.rs16
-rw-r--r--embassy-nrf/src/chips/nrf52832.rs16
-rw-r--r--embassy-nrf/src/chips/nrf52833.rs16
-rw-r--r--embassy-nrf/src/chips/nrf52840.rs16
-rw-r--r--embassy-nrf/src/chips/nrf5340_app.rs16
-rw-r--r--embassy-nrf/src/chips/nrf9160.rs16
-rw-r--r--embassy-nrf/src/time_driver.rs19
-rw-r--r--embassy-nrf/src/usb.rs14
-rw-r--r--embassy-rp/Cargo.toml4
-rw-r--r--embassy-rp/src/timer.rs15
-rw-r--r--embassy-rp/src/uart/buffered.rs16
-rw-r--r--embassy-stm32/Cargo.toml9
-rw-r--r--embassy-stm32/src/adc/f1.rs21
-rw-r--r--embassy-stm32/src/adc/v2.rs23
-rw-r--r--embassy-stm32/src/adc/v3.rs39
-rw-r--r--embassy-stm32/src/adc/v4.rs14
-rw-r--r--embassy-stm32/src/i2c/mod.rs5
-rw-r--r--embassy-stm32/src/i2c/timeout.rs142
-rw-r--r--embassy-stm32/src/i2c/v1.rs123
-rw-r--r--embassy-stm32/src/i2c/v2.rs221
-rw-r--r--embassy-stm32/src/lib.rs2
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs12
-rw-r--r--embassy-stm32/src/subghz/timeout.rs1
-rw-r--r--embassy-stm32/src/subghz/tx_params.rs1
-rw-r--r--embassy-stm32/src/time_driver.rs14
-rw-r--r--embassy-stm32/src/usart/buffered.rs50
-rw-r--r--embassy-stm32/src/usart/mod.rs429
-rw-r--r--embassy-sync/Cargo.toml5
-rw-r--r--embassy-sync/src/pipe.rs18
-rw-r--r--embassy-time/Cargo.toml39
-rw-r--r--embassy-time/src/driver.rs13
-rw-r--r--embassy-time/src/driver_std.rs4
-rw-r--r--embassy-time/src/driver_wasm.rs14
-rw-r--r--embassy-time/src/lib.rs5
-rw-r--r--embassy-time/src/queue.rs58
-rw-r--r--embassy-time/src/queue_generic.rs449
-rw-r--r--examples/nrf/Cargo.toml2
-rw-r--r--examples/rp/Cargo.toml4
-rw-r--r--examples/std/Cargo.toml2
-rw-r--r--examples/stm32f1/src/bin/adc.rs14
-rw-r--r--examples/stm32f3/src/bin/usart_dma.rs4
-rw-r--r--examples/stm32f4/Cargo.toml2
-rw-r--r--examples/stm32f4/src/bin/adc.rs31
-rw-r--r--examples/stm32f4/src/bin/i2c.rs45
-rw-r--r--examples/stm32f4/src/bin/usart.rs4
-rw-r--r--examples/stm32f4/src/bin/usart_buffered.rs15
-rw-r--r--examples/stm32f4/src/bin/usart_dma.rs4
-rw-r--r--examples/stm32f7/Cargo.toml2
-rw-r--r--examples/stm32f7/src/bin/adc.rs12
-rw-r--r--examples/stm32f7/src/bin/usart_dma.rs4
-rw-r--r--examples/stm32h7/Cargo.toml4
-rw-r--r--examples/stm32h7/src/bin/i2c.rs44
-rw-r--r--examples/stm32h7/src/bin/usart.rs4
-rw-r--r--examples/stm32h7/src/bin/usart_dma.rs4
-rw-r--r--examples/stm32h7/src/bin/usart_split.rs4
-rw-r--r--examples/stm32l0/Cargo.toml2
-rw-r--r--examples/stm32l0/src/bin/usart_dma.rs4
-rw-r--r--examples/stm32l0/src/bin/usart_irq.rs12
-rw-r--r--examples/stm32l4/Cargo.toml2
-rw-r--r--examples/stm32l4/src/bin/usart.rs4
-rw-r--r--examples/stm32l4/src/bin/usart_dma.rs4
-rw-r--r--examples/stm32l5/Cargo.toml2
-rw-r--r--rust-toolchain.toml2
-rw-r--r--tests/rp/Cargo.toml4
-rw-r--r--tests/stm32/Cargo.toml2
-rw-r--r--tests/stm32/src/bin/usart.rs17
-rw-r--r--tests/stm32/src/bin/usart_dma.rs48
76 files changed, 1894 insertions, 464 deletions
diff --git a/embassy-embedded-hal/Cargo.toml b/embassy-embedded-hal/Cargo.toml
index d0be6d195..85ee856a6 100644
--- a/embassy-embedded-hal/Cargo.toml
+++ b/embassy-embedded-hal/Cargo.toml
@@ -20,7 +20,7 @@ nightly = ["embedded-hal-async", "embedded-storage-async"]
20embassy-sync = { version = "0.1.0", path = "../embassy-sync" } 20embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
21embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } 21embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
22embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9" } 22embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9" }
23embedded-hal-async = { version = "=0.1.0-alpha.2", optional = true } 23embedded-hal-async = { version = "=0.1.0-alpha.3", optional = true }
24embedded-storage = "0.3.0" 24embedded-storage = "0.3.0"
25embedded-storage-async = { version = "0.3.0", optional = true } 25embedded-storage-async = { version = "0.3.0", optional = true }
26nb = "1.0.0" 26nb = "1.0.0"
diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs
index e1258ebb5..181dabe8e 100644
--- a/embassy-executor/src/raw/mod.rs
+++ b/embassy-executor/src/raw/mod.rs
@@ -354,46 +354,54 @@ impl Executor {
354 /// somehow schedule for `poll()` to be called later, at a time you know for sure there's 354 /// somehow schedule for `poll()` to be called later, at a time you know for sure there's
355 /// no `poll()` already running. 355 /// no `poll()` already running.
356 pub unsafe fn poll(&'static self) { 356 pub unsafe fn poll(&'static self) {
357 #[cfg(feature = "integrated-timers")] 357 loop {
358 self.timer_queue.dequeue_expired(Instant::now(), |task| wake_task(task)); 358 #[cfg(feature = "integrated-timers")]
359 self.timer_queue.dequeue_expired(Instant::now(), |task| wake_task(task));
359 360
360 self.run_queue.dequeue_all(|p| { 361 self.run_queue.dequeue_all(|p| {
361 let task = p.as_ref(); 362 let task = p.as_ref();
362 363
363 #[cfg(feature = "integrated-timers")] 364 #[cfg(feature = "integrated-timers")]
364 task.expires_at.set(Instant::MAX); 365 task.expires_at.set(Instant::MAX);
365
366 let state = task.state.fetch_and(!STATE_RUN_QUEUED, Ordering::AcqRel);
367 if state & STATE_SPAWNED == 0 {
368 // If task is not running, ignore it. This can happen in the following scenario:
369 // - Task gets dequeued, poll starts
370 // - While task is being polled, it gets woken. It gets placed in the queue.
371 // - Task poll finishes, returning done=true
372 // - RUNNING bit is cleared, but the task is already in the queue.
373 return;
374 }
375 366
376 #[cfg(feature = "rtos-trace")] 367 let state = task.state.fetch_and(!STATE_RUN_QUEUED, Ordering::AcqRel);
377 trace::task_exec_begin(p.as_ptr() as u32); 368 if state & STATE_SPAWNED == 0 {
369 // If task is not running, ignore it. This can happen in the following scenario:
370 // - Task gets dequeued, poll starts
371 // - While task is being polled, it gets woken. It gets placed in the queue.
372 // - Task poll finishes, returning done=true
373 // - RUNNING bit is cleared, but the task is already in the queue.
374 return;
375 }
378 376
379 // Run the task 377 #[cfg(feature = "rtos-trace")]
380 task.poll_fn.read()(p as _); 378 trace::task_exec_begin(p.as_ptr() as u32);
381 379
382 #[cfg(feature = "rtos-trace")] 380 // Run the task
383 trace::task_exec_end(); 381 task.poll_fn.read()(p as _);
382
383 #[cfg(feature = "rtos-trace")]
384 trace::task_exec_end();
385
386 // Enqueue or update into timer_queue
387 #[cfg(feature = "integrated-timers")]
388 self.timer_queue.update(p);
389 });
384 390
385 // Enqueue or update into timer_queue
386 #[cfg(feature = "integrated-timers")] 391 #[cfg(feature = "integrated-timers")]
387 self.timer_queue.update(p); 392 {
388 }); 393 // If this is already in the past, set_alarm might return false
394 // In that case do another poll loop iteration.
395 let next_expiration = self.timer_queue.next_expiration();
396 if driver::set_alarm(self.alarm, next_expiration.as_ticks()) {
397 break;
398 }
399 }
389 400
390 #[cfg(feature = "integrated-timers")] 401 #[cfg(not(feature = "integrated-timers"))]
391 { 402 {
392 // If this is already in the past, set_alarm will immediately trigger the alarm. 403 break;
393 // This will cause `signal_fn` to be called, which will cause `poll()` to be called again, 404 }
394 // so we immediately do another poll loop iteration.
395 let next_expiration = self.timer_queue.next_expiration();
396 driver::set_alarm(self.alarm, next_expiration.as_ticks());
397 } 405 }
398 406
399 #[cfg(feature = "rtos-trace")] 407 #[cfg(feature = "rtos-trace")]
@@ -436,14 +444,21 @@ pub unsafe fn wake_task(task: NonNull<TaskHeader>) {
436} 444}
437 445
438#[cfg(feature = "integrated-timers")] 446#[cfg(feature = "integrated-timers")]
439#[no_mangle] 447struct TimerQueue;
440unsafe fn _embassy_time_schedule_wake(at: Instant, waker: &core::task::Waker) { 448
441 let task = waker::task_from_waker(waker); 449#[cfg(feature = "integrated-timers")]
442 let task = task.as_ref(); 450impl embassy_time::queue::TimerQueue for TimerQueue {
443 let expires_at = task.expires_at.get(); 451 fn schedule_wake(&'static self, at: Instant, waker: &core::task::Waker) {
444 task.expires_at.set(expires_at.min(at)); 452 let task = waker::task_from_waker(waker);
453 let task = unsafe { task.as_ref() };
454 let expires_at = task.expires_at.get();
455 task.expires_at.set(expires_at.min(at));
456 }
445} 457}
446 458
459#[cfg(feature = "integrated-timers")]
460embassy_time::timer_queue_impl!(static TIMER_QUEUE: TimerQueue = TimerQueue);
461
447#[cfg(feature = "rtos-trace")] 462#[cfg(feature = "rtos-trace")]
448impl rtos_trace::RtosTraceOSCallbacks for Executor { 463impl rtos_trace::RtosTraceOSCallbacks for Executor {
449 fn task_list() { 464 fn task_list() {
diff --git a/embassy-lora/Cargo.toml b/embassy-lora/Cargo.toml
index ea2c3fe67..dc2004172 100644
--- a/embassy-lora/Cargo.toml
+++ b/embassy-lora/Cargo.toml
@@ -32,7 +32,7 @@ embassy-time = { version = "0.1.0", path = "../embassy-time" }
32embassy-sync = { version = "0.1.0", path = "../embassy-sync" } 32embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
33embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", default-features = false, optional = true } 33embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", default-features = false, optional = true }
34embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9" } 34embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9" }
35embedded-hal-async = { version = "=0.1.0-alpha.2" } 35embedded-hal-async = { version = "=0.1.0-alpha.3" }
36embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common", default-features = false } 36embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common", default-features = false }
37futures = { version = "0.3.17", default-features = false, features = [ "async-await" ] } 37futures = { version = "0.3.17", default-features = false, features = [ "async-await" ] }
38embedded-hal = { version = "0.2", features = ["unproven"] } 38embedded-hal = { version = "0.2", features = ["unproven"] }
diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml
index 967ef26a7..76217075a 100644
--- a/embassy-net/Cargo.toml
+++ b/embassy-net/Cargo.toml
@@ -42,7 +42,7 @@ log = { version = "0.4.14", optional = true }
42 42
43embassy-time = { version = "0.1.0", path = "../embassy-time" } 43embassy-time = { version = "0.1.0", path = "../embassy-time" }
44embassy-sync = { version = "0.1.0", path = "../embassy-sync" } 44embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
45embedded-io = { version = "0.3.0", optional = true } 45embedded-io = { version = "0.3.1", optional = true }
46 46
47managed = { version = "0.8.0", default-features = false, features = [ "map" ] } 47managed = { version = "0.8.0", default-features = false, features = [ "map" ] }
48heapless = { version = "0.7.5", default-features = false } 48heapless = { version = "0.7.5", default-features = false }
diff --git a/embassy-net/src/tcp.rs b/embassy-net/src/tcp.rs
index f8fff3e2d..f3bd2361c 100644
--- a/embassy-net/src/tcp.rs
+++ b/embassy-net/src/tcp.rs
@@ -292,7 +292,7 @@ mod embedded_io_impls {
292 } 292 }
293 293
294 impl<'d> embedded_io::asynch::Read for TcpSocket<'d> { 294 impl<'d> embedded_io::asynch::Read for TcpSocket<'d> {
295 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 295 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
296 where 296 where
297 Self: 'a; 297 Self: 'a;
298 298
@@ -302,7 +302,7 @@ mod embedded_io_impls {
302 } 302 }
303 303
304 impl<'d> embedded_io::asynch::Write for TcpSocket<'d> { 304 impl<'d> embedded_io::asynch::Write for TcpSocket<'d> {
305 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 305 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
306 where 306 where
307 Self: 'a; 307 Self: 'a;
308 308
@@ -310,7 +310,7 @@ mod embedded_io_impls {
310 self.io.write(buf) 310 self.io.write(buf)
311 } 311 }
312 312
313 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> 313 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a
314 where 314 where
315 Self: 'a; 315 Self: 'a;
316 316
@@ -324,7 +324,7 @@ mod embedded_io_impls {
324 } 324 }
325 325
326 impl<'d> embedded_io::asynch::Read for TcpReader<'d> { 326 impl<'d> embedded_io::asynch::Read for TcpReader<'d> {
327 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 327 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
328 where 328 where
329 Self: 'a; 329 Self: 'a;
330 330
@@ -338,7 +338,7 @@ mod embedded_io_impls {
338 } 338 }
339 339
340 impl<'d> embedded_io::asynch::Write for TcpWriter<'d> { 340 impl<'d> embedded_io::asynch::Write for TcpWriter<'d> {
341 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 341 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
342 where 342 where
343 Self: 'a; 343 Self: 'a;
344 344
@@ -346,7 +346,7 @@ mod embedded_io_impls {
346 self.io.write(buf) 346 self.io.write(buf)
347 } 347 }
348 348
349 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> 349 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a
350 where 350 where
351 Self: 'a; 351 Self: 'a;
352 352
@@ -445,7 +445,7 @@ pub mod client {
445 impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize> embedded_io::asynch::Read 445 impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize> embedded_io::asynch::Read
446 for TcpConnection<'d, N, TX_SZ, RX_SZ> 446 for TcpConnection<'d, N, TX_SZ, RX_SZ>
447 { 447 {
448 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 448 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
449 where 449 where
450 Self: 'a; 450 Self: 'a;
451 451
@@ -457,7 +457,7 @@ pub mod client {
457 impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize> embedded_io::asynch::Write 457 impl<'d, const N: usize, const TX_SZ: usize, const RX_SZ: usize> embedded_io::asynch::Write
458 for TcpConnection<'d, N, TX_SZ, RX_SZ> 458 for TcpConnection<'d, N, TX_SZ, RX_SZ>
459 { 459 {
460 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 460 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
461 where 461 where
462 Self: 'a; 462 Self: 'a;
463 463
@@ -465,7 +465,7 @@ pub mod client {
465 self.socket.write(buf) 465 self.socket.write(buf)
466 } 466 }
467 467
468 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> 468 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a
469 where 469 where
470 Self: 'a; 470 Self: 'a;
471 471
diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml
index 5459bc90c..67b6bec40 100644
--- a/embassy-nrf/Cargo.toml
+++ b/embassy-nrf/Cargo.toml
@@ -75,8 +75,8 @@ embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optiona
75 75
76embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } 76embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
77embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9", optional = true} 77embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9", optional = true}
78embedded-hal-async = { version = "=0.1.0-alpha.2", optional = true} 78embedded-hal-async = { version = "=0.1.0-alpha.3", optional = true}
79embedded-io = { version = "0.3.0", features = ["async"], optional = true } 79embedded-io = { version = "0.3.1", features = ["async"], optional = true }
80 80
81defmt = { version = "0.3", optional = true } 81defmt = { version = "0.3", optional = true }
82log = { version = "0.4.14", optional = true } 82log = { version = "0.4.14", optional = true }
@@ -90,13 +90,13 @@ embedded-storage = "0.3.0"
90embedded-storage-async = { version = "0.3.0", optional = true } 90embedded-storage-async = { version = "0.3.0", optional = true }
91cfg-if = "1.0.0" 91cfg-if = "1.0.0"
92 92
93nrf52805-pac = { version = "0.11.0", optional = true, features = [ "rt" ] } 93nrf52805-pac = { version = "0.12.0", optional = true, features = [ "rt" ] }
94nrf52810-pac = { version = "0.11.0", optional = true, features = [ "rt" ] } 94nrf52810-pac = { version = "0.12.0", optional = true, features = [ "rt" ] }
95nrf52811-pac = { version = "0.11.0", optional = true, features = [ "rt" ] } 95nrf52811-pac = { version = "0.12.0", optional = true, features = [ "rt" ] }
96nrf52820-pac = { version = "0.11.0", optional = true, features = [ "rt" ] } 96nrf52820-pac = { version = "0.12.0", optional = true, features = [ "rt" ] }
97nrf52832-pac = { version = "0.11.0", optional = true, features = [ "rt" ] } 97nrf52832-pac = { version = "0.12.0", optional = true, features = [ "rt" ] }
98nrf52833-pac = { version = "0.11.0", optional = true, features = [ "rt" ] } 98nrf52833-pac = { version = "0.12.0", optional = true, features = [ "rt" ] }
99nrf52840-pac = { version = "0.11.0", optional = true, features = [ "rt" ] } 99nrf52840-pac = { version = "0.12.0", optional = true, features = [ "rt" ] }
100nrf5340-app-pac = { version = "0.11.0", optional = true, features = [ "rt" ] } 100nrf5340-app-pac = { version = "0.12.0", optional = true, features = [ "rt" ] }
101nrf5340-net-pac = { version = "0.11.0", optional = true, features = [ "rt" ] } 101nrf5340-net-pac = { version = "0.12.0", optional = true, features = [ "rt" ] }
102nrf9160-pac = { version = "0.11.0", optional = true, features = [ "rt" ] } 102nrf9160-pac = { version = "0.12.0", optional = true, features = [ "rt" ] }
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs
index 6e85a159f..9c8fe65f4 100644
--- a/embassy-nrf/src/buffered_uarte.rs
+++ b/embassy-nrf/src/buffered_uarte.rs
@@ -341,7 +341,7 @@ impl<'u, 'd, U: UarteInstance, T: TimerInstance> embedded_io::Io for BufferedUar
341} 341}
342 342
343impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Read for BufferedUarte<'d, U, T> { 343impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Read for BufferedUarte<'d, U, T> {
344 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 344 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
345 where 345 where
346 Self: 'a; 346 Self: 'a;
347 347
@@ -351,7 +351,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Read for Buffe
351} 351}
352 352
353impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Read for BufferedUarteRx<'u, 'd, U, T> { 353impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Read for BufferedUarteRx<'u, 'd, U, T> {
354 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 354 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
355 where 355 where
356 Self: 'a; 356 Self: 'a;
357 357
@@ -361,7 +361,7 @@ impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Read f
361} 361}
362 362
363impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::BufRead for BufferedUarte<'d, U, T> { 363impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::BufRead for BufferedUarte<'d, U, T> {
364 type FillBufFuture<'a> = impl Future<Output = Result<&'a [u8], Self::Error>> 364 type FillBufFuture<'a> = impl Future<Output = Result<&'a [u8], Self::Error>> + 'a
365 where 365 where
366 Self: 'a; 366 Self: 'a;
367 367
@@ -375,7 +375,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::BufRead for Bu
375} 375}
376 376
377impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io::asynch::BufRead for BufferedUarteRx<'u, 'd, U, T> { 377impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io::asynch::BufRead for BufferedUarteRx<'u, 'd, U, T> {
378 type FillBufFuture<'a> = impl Future<Output = Result<&'a [u8], Self::Error>> 378 type FillBufFuture<'a> = impl Future<Output = Result<&'a [u8], Self::Error>> + 'a
379 where 379 where
380 Self: 'a; 380 Self: 'a;
381 381
@@ -389,7 +389,7 @@ impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io::asynch::BufRea
389} 389}
390 390
391impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Write for BufferedUarte<'d, U, T> { 391impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Write for BufferedUarte<'d, U, T> {
392 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 392 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
393 where 393 where
394 Self: 'a; 394 Self: 'a;
395 395
@@ -397,7 +397,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Write for Buff
397 self.inner_write(buf) 397 self.inner_write(buf)
398 } 398 }
399 399
400 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> 400 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a
401 where 401 where
402 Self: 'a; 402 Self: 'a;
403 403
@@ -407,7 +407,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Write for Buff
407} 407}
408 408
409impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Write for BufferedUarteTx<'u, 'd, U, T> { 409impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Write for BufferedUarteTx<'u, 'd, U, T> {
410 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 410 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
411 where 411 where
412 Self: 'a; 412 Self: 'a;
413 413
@@ -415,7 +415,7 @@ impl<'u, 'd: 'u, U: UarteInstance, T: TimerInstance> embedded_io::asynch::Write
415 self.inner.inner_write(buf) 415 self.inner.inner_write(buf)
416 } 416 }
417 417
418 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> 418 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a
419 where 419 where
420 Self: 'a; 420 Self: 'a;
421 421
diff --git a/embassy-nrf/src/chips/nrf52805.rs b/embassy-nrf/src/chips/nrf52805.rs
index d078fa0ad..dec31a84c 100644
--- a/embassy-nrf/src/chips/nrf52805.rs
+++ b/embassy-nrf/src/chips/nrf52805.rs
@@ -193,8 +193,8 @@ impl_ppi_channel!(PPI_CH29, 29 => static);
193impl_ppi_channel!(PPI_CH30, 30 => static); 193impl_ppi_channel!(PPI_CH30, 30 => static);
194impl_ppi_channel!(PPI_CH31, 31 => static); 194impl_ppi_channel!(PPI_CH31, 31 => static);
195 195
196impl_saadc_input!(P0_04, ANALOGINPUT2); 196impl_saadc_input!(P0_04, ANALOG_INPUT2);
197impl_saadc_input!(P0_05, ANALOGINPUT3); 197impl_saadc_input!(P0_05, ANALOG_INPUT3);
198 198
199pub mod irqs { 199pub mod irqs {
200 use embassy_cortex_m::interrupt::_export::declare; 200 use embassy_cortex_m::interrupt::_export::declare;
diff --git a/embassy-nrf/src/chips/nrf52810.rs b/embassy-nrf/src/chips/nrf52810.rs
index 3e500098c..e57a4a383 100644
--- a/embassy-nrf/src/chips/nrf52810.rs
+++ b/embassy-nrf/src/chips/nrf52810.rs
@@ -211,14 +211,14 @@ impl_ppi_channel!(PPI_CH29, 29 => static);
211impl_ppi_channel!(PPI_CH30, 30 => static); 211impl_ppi_channel!(PPI_CH30, 30 => static);
212impl_ppi_channel!(PPI_CH31, 31 => static); 212impl_ppi_channel!(PPI_CH31, 31 => static);
213 213
214impl_saadc_input!(P0_02, ANALOGINPUT0); 214impl_saadc_input!(P0_02, ANALOG_INPUT0);
215impl_saadc_input!(P0_03, ANALOGINPUT1); 215impl_saadc_input!(P0_03, ANALOG_INPUT1);
216impl_saadc_input!(P0_04, ANALOGINPUT2); 216impl_saadc_input!(P0_04, ANALOG_INPUT2);
217impl_saadc_input!(P0_05, ANALOGINPUT3); 217impl_saadc_input!(P0_05, ANALOG_INPUT3);
218impl_saadc_input!(P0_28, ANALOGINPUT4); 218impl_saadc_input!(P0_28, ANALOG_INPUT4);
219impl_saadc_input!(P0_29, ANALOGINPUT5); 219impl_saadc_input!(P0_29, ANALOG_INPUT5);
220impl_saadc_input!(P0_30, ANALOGINPUT6); 220impl_saadc_input!(P0_30, ANALOG_INPUT6);
221impl_saadc_input!(P0_31, ANALOGINPUT7); 221impl_saadc_input!(P0_31, ANALOG_INPUT7);
222 222
223pub mod irqs { 223pub mod irqs {
224 use embassy_cortex_m::interrupt::_export::declare; 224 use embassy_cortex_m::interrupt::_export::declare;
diff --git a/embassy-nrf/src/chips/nrf52811.rs b/embassy-nrf/src/chips/nrf52811.rs
index 25c7c0d91..918404cf1 100644
--- a/embassy-nrf/src/chips/nrf52811.rs
+++ b/embassy-nrf/src/chips/nrf52811.rs
@@ -212,14 +212,14 @@ impl_ppi_channel!(PPI_CH29, 29 => static);
212impl_ppi_channel!(PPI_CH30, 30 => static); 212impl_ppi_channel!(PPI_CH30, 30 => static);
213impl_ppi_channel!(PPI_CH31, 31 => static); 213impl_ppi_channel!(PPI_CH31, 31 => static);
214 214
215impl_saadc_input!(P0_02, ANALOGINPUT0); 215impl_saadc_input!(P0_02, ANALOG_INPUT0);
216impl_saadc_input!(P0_03, ANALOGINPUT1); 216impl_saadc_input!(P0_03, ANALOG_INPUT1);
217impl_saadc_input!(P0_04, ANALOGINPUT2); 217impl_saadc_input!(P0_04, ANALOG_INPUT2);
218impl_saadc_input!(P0_05, ANALOGINPUT3); 218impl_saadc_input!(P0_05, ANALOG_INPUT3);
219impl_saadc_input!(P0_28, ANALOGINPUT4); 219impl_saadc_input!(P0_28, ANALOG_INPUT4);
220impl_saadc_input!(P0_29, ANALOGINPUT5); 220impl_saadc_input!(P0_29, ANALOG_INPUT5);
221impl_saadc_input!(P0_30, ANALOGINPUT6); 221impl_saadc_input!(P0_30, ANALOG_INPUT6);
222impl_saadc_input!(P0_31, ANALOGINPUT7); 222impl_saadc_input!(P0_31, ANALOG_INPUT7);
223 223
224pub mod irqs { 224pub mod irqs {
225 use embassy_cortex_m::interrupt::_export::declare; 225 use embassy_cortex_m::interrupt::_export::declare;
diff --git a/embassy-nrf/src/chips/nrf52832.rs b/embassy-nrf/src/chips/nrf52832.rs
index 18b8eda67..81e66c193 100644
--- a/embassy-nrf/src/chips/nrf52832.rs
+++ b/embassy-nrf/src/chips/nrf52832.rs
@@ -225,14 +225,14 @@ impl_ppi_channel!(PPI_CH29, 29 => static);
225impl_ppi_channel!(PPI_CH30, 30 => static); 225impl_ppi_channel!(PPI_CH30, 30 => static);
226impl_ppi_channel!(PPI_CH31, 31 => static); 226impl_ppi_channel!(PPI_CH31, 31 => static);
227 227
228impl_saadc_input!(P0_02, ANALOGINPUT0); 228impl_saadc_input!(P0_02, ANALOG_INPUT0);
229impl_saadc_input!(P0_03, ANALOGINPUT1); 229impl_saadc_input!(P0_03, ANALOG_INPUT1);
230impl_saadc_input!(P0_04, ANALOGINPUT2); 230impl_saadc_input!(P0_04, ANALOG_INPUT2);
231impl_saadc_input!(P0_05, ANALOGINPUT3); 231impl_saadc_input!(P0_05, ANALOG_INPUT3);
232impl_saadc_input!(P0_28, ANALOGINPUT4); 232impl_saadc_input!(P0_28, ANALOG_INPUT4);
233impl_saadc_input!(P0_29, ANALOGINPUT5); 233impl_saadc_input!(P0_29, ANALOG_INPUT5);
234impl_saadc_input!(P0_30, ANALOGINPUT6); 234impl_saadc_input!(P0_30, ANALOG_INPUT6);
235impl_saadc_input!(P0_31, ANALOGINPUT7); 235impl_saadc_input!(P0_31, ANALOG_INPUT7);
236 236
237pub mod irqs { 237pub mod irqs {
238 use embassy_cortex_m::interrupt::_export::declare; 238 use embassy_cortex_m::interrupt::_export::declare;
diff --git a/embassy-nrf/src/chips/nrf52833.rs b/embassy-nrf/src/chips/nrf52833.rs
index 3b33907d2..92499e3c9 100644
--- a/embassy-nrf/src/chips/nrf52833.rs
+++ b/embassy-nrf/src/chips/nrf52833.rs
@@ -271,14 +271,14 @@ impl_ppi_channel!(PPI_CH29, 29 => static);
271impl_ppi_channel!(PPI_CH30, 30 => static); 271impl_ppi_channel!(PPI_CH30, 30 => static);
272impl_ppi_channel!(PPI_CH31, 31 => static); 272impl_ppi_channel!(PPI_CH31, 31 => static);
273 273
274impl_saadc_input!(P0_02, ANALOGINPUT0); 274impl_saadc_input!(P0_02, ANALOG_INPUT0);
275impl_saadc_input!(P0_03, ANALOGINPUT1); 275impl_saadc_input!(P0_03, ANALOG_INPUT1);
276impl_saadc_input!(P0_04, ANALOGINPUT2); 276impl_saadc_input!(P0_04, ANALOG_INPUT2);
277impl_saadc_input!(P0_05, ANALOGINPUT3); 277impl_saadc_input!(P0_05, ANALOG_INPUT3);
278impl_saadc_input!(P0_28, ANALOGINPUT4); 278impl_saadc_input!(P0_28, ANALOG_INPUT4);
279impl_saadc_input!(P0_29, ANALOGINPUT5); 279impl_saadc_input!(P0_29, ANALOG_INPUT5);
280impl_saadc_input!(P0_30, ANALOGINPUT6); 280impl_saadc_input!(P0_30, ANALOG_INPUT6);
281impl_saadc_input!(P0_31, ANALOGINPUT7); 281impl_saadc_input!(P0_31, ANALOG_INPUT7);
282 282
283pub mod irqs { 283pub mod irqs {
284 use embassy_cortex_m::interrupt::_export::declare; 284 use embassy_cortex_m::interrupt::_export::declare;
diff --git a/embassy-nrf/src/chips/nrf52840.rs b/embassy-nrf/src/chips/nrf52840.rs
index ae59f8b25..4beadfba8 100644
--- a/embassy-nrf/src/chips/nrf52840.rs
+++ b/embassy-nrf/src/chips/nrf52840.rs
@@ -276,14 +276,14 @@ impl_ppi_channel!(PPI_CH29, 29 => static);
276impl_ppi_channel!(PPI_CH30, 30 => static); 276impl_ppi_channel!(PPI_CH30, 30 => static);
277impl_ppi_channel!(PPI_CH31, 31 => static); 277impl_ppi_channel!(PPI_CH31, 31 => static);
278 278
279impl_saadc_input!(P0_02, ANALOGINPUT0); 279impl_saadc_input!(P0_02, ANALOG_INPUT0);
280impl_saadc_input!(P0_03, ANALOGINPUT1); 280impl_saadc_input!(P0_03, ANALOG_INPUT1);
281impl_saadc_input!(P0_04, ANALOGINPUT2); 281impl_saadc_input!(P0_04, ANALOG_INPUT2);
282impl_saadc_input!(P0_05, ANALOGINPUT3); 282impl_saadc_input!(P0_05, ANALOG_INPUT3);
283impl_saadc_input!(P0_28, ANALOGINPUT4); 283impl_saadc_input!(P0_28, ANALOG_INPUT4);
284impl_saadc_input!(P0_29, ANALOGINPUT5); 284impl_saadc_input!(P0_29, ANALOG_INPUT5);
285impl_saadc_input!(P0_30, ANALOGINPUT6); 285impl_saadc_input!(P0_30, ANALOG_INPUT6);
286impl_saadc_input!(P0_31, ANALOGINPUT7); 286impl_saadc_input!(P0_31, ANALOG_INPUT7);
287 287
288pub mod irqs { 288pub mod irqs {
289 use embassy_cortex_m::interrupt::_export::declare; 289 use embassy_cortex_m::interrupt::_export::declare;
diff --git a/embassy-nrf/src/chips/nrf5340_app.rs b/embassy-nrf/src/chips/nrf5340_app.rs
index edf800ef3..7845d4a8e 100644
--- a/embassy-nrf/src/chips/nrf5340_app.rs
+++ b/embassy-nrf/src/chips/nrf5340_app.rs
@@ -458,14 +458,14 @@ impl_ppi_channel!(PPI_CH29, 29 => configurable);
458impl_ppi_channel!(PPI_CH30, 30 => configurable); 458impl_ppi_channel!(PPI_CH30, 30 => configurable);
459impl_ppi_channel!(PPI_CH31, 31 => configurable); 459impl_ppi_channel!(PPI_CH31, 31 => configurable);
460 460
461impl_saadc_input!(P0_13, ANALOGINPUT0); 461impl_saadc_input!(P0_13, ANALOG_INPUT0);
462impl_saadc_input!(P0_14, ANALOGINPUT1); 462impl_saadc_input!(P0_14, ANALOG_INPUT1);
463impl_saadc_input!(P0_15, ANALOGINPUT2); 463impl_saadc_input!(P0_15, ANALOG_INPUT2);
464impl_saadc_input!(P0_16, ANALOGINPUT3); 464impl_saadc_input!(P0_16, ANALOG_INPUT3);
465impl_saadc_input!(P0_17, ANALOGINPUT4); 465impl_saadc_input!(P0_17, ANALOG_INPUT4);
466impl_saadc_input!(P0_18, ANALOGINPUT5); 466impl_saadc_input!(P0_18, ANALOG_INPUT5);
467impl_saadc_input!(P0_19, ANALOGINPUT6); 467impl_saadc_input!(P0_19, ANALOG_INPUT6);
468impl_saadc_input!(P0_20, ANALOGINPUT7); 468impl_saadc_input!(P0_20, ANALOG_INPUT7);
469 469
470pub mod irqs { 470pub mod irqs {
471 use embassy_cortex_m::interrupt::_export::declare; 471 use embassy_cortex_m::interrupt::_export::declare;
diff --git a/embassy-nrf/src/chips/nrf9160.rs b/embassy-nrf/src/chips/nrf9160.rs
index f8ed11e03..b5a53ed80 100644
--- a/embassy-nrf/src/chips/nrf9160.rs
+++ b/embassy-nrf/src/chips/nrf9160.rs
@@ -339,14 +339,14 @@ impl_ppi_channel!(PPI_CH13, 13 => configurable);
339impl_ppi_channel!(PPI_CH14, 14 => configurable); 339impl_ppi_channel!(PPI_CH14, 14 => configurable);
340impl_ppi_channel!(PPI_CH15, 15 => configurable); 340impl_ppi_channel!(PPI_CH15, 15 => configurable);
341 341
342impl_saadc_input!(P0_13, ANALOGINPUT0); 342impl_saadc_input!(P0_13, ANALOG_INPUT0);
343impl_saadc_input!(P0_14, ANALOGINPUT1); 343impl_saadc_input!(P0_14, ANALOG_INPUT1);
344impl_saadc_input!(P0_15, ANALOGINPUT2); 344impl_saadc_input!(P0_15, ANALOG_INPUT2);
345impl_saadc_input!(P0_16, ANALOGINPUT3); 345impl_saadc_input!(P0_16, ANALOG_INPUT3);
346impl_saadc_input!(P0_17, ANALOGINPUT4); 346impl_saadc_input!(P0_17, ANALOG_INPUT4);
347impl_saadc_input!(P0_18, ANALOGINPUT5); 347impl_saadc_input!(P0_18, ANALOG_INPUT5);
348impl_saadc_input!(P0_19, ANALOGINPUT6); 348impl_saadc_input!(P0_19, ANALOG_INPUT6);
349impl_saadc_input!(P0_20, ANALOGINPUT7); 349impl_saadc_input!(P0_20, ANALOG_INPUT7);
350 350
351pub mod irqs { 351pub mod irqs {
352 use embassy_cortex_m::interrupt::_export::declare; 352 use embassy_cortex_m::interrupt::_export::declare;
diff --git a/embassy-nrf/src/time_driver.rs b/embassy-nrf/src/time_driver.rs
index c32a44637..bc2c8a3c1 100644
--- a/embassy-nrf/src/time_driver.rs
+++ b/embassy-nrf/src/time_driver.rs
@@ -243,21 +243,24 @@ impl Driver for RtcDriver {
243 }) 243 })
244 } 244 }
245 245
246 fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) { 246 fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) -> bool {
247 critical_section::with(|cs| { 247 critical_section::with(|cs| {
248 let n = alarm.id() as _; 248 let n = alarm.id() as _;
249 let alarm = self.get_alarm(cs, alarm); 249 let alarm = self.get_alarm(cs, alarm);
250 alarm.timestamp.set(timestamp); 250 alarm.timestamp.set(timestamp);
251 251
252 let t = self.now(); 252 let r = rtc();
253 253
254 // If alarm timestamp has passed, trigger it instantly. 254 let t = self.now();
255 if timestamp <= t { 255 if timestamp <= t {
256 self.trigger_alarm(n, cs); 256 // If alarm timestamp has passed the alarm will not fire.
257 return; 257 // Disarm the alarm and return `false` to indicate that.
258 } 258 r.intenclr.write(|w| unsafe { w.bits(compare_n(n)) });
259 259
260 let r = rtc(); 260 alarm.timestamp.set(u64::MAX);
261
262 return false;
263 }
261 264
262 // If it hasn't triggered yet, setup it in the compare channel. 265 // If it hasn't triggered yet, setup it in the compare channel.
263 266
@@ -287,6 +290,8 @@ impl Driver for RtcDriver {
287 // It will be setup later by `next_period`. 290 // It will be setup later by `next_period`.
288 r.intenclr.write(|w| unsafe { w.bits(compare_n(n)) }); 291 r.intenclr.write(|w| unsafe { w.bits(compare_n(n)) });
289 } 292 }
293
294 true
290 }) 295 })
291 } 296 }
292} 297}
diff --git a/embassy-nrf/src/usb.rs b/embassy-nrf/src/usb.rs
index 00da5c9dd..eb1472fa5 100644
--- a/embassy-nrf/src/usb.rs
+++ b/embassy-nrf/src/usb.rs
@@ -313,7 +313,7 @@ impl<'d, T: Instance, P: UsbSupply> driver::Bus for Bus<'d, T, P> {
313 } 313 }
314 }) 314 })
315 .await; 315 .await;
316 regs.eventcause.write(|w| w.ready().set_bit()); // Write 1 to clear. 316 regs.eventcause.write(|w| w.ready().clear_bit_by_one());
317 317
318 errata::post_enable(); 318 errata::post_enable();
319 319
@@ -367,24 +367,24 @@ impl<'d, T: Instance, P: UsbSupply> driver::Bus for Bus<'d, T, P> {
367 let r = regs.eventcause.read(); 367 let r = regs.eventcause.read();
368 368
369 if r.isooutcrc().bit() { 369 if r.isooutcrc().bit() {
370 regs.eventcause.write(|w| w.isooutcrc().set_bit()); 370 regs.eventcause.write(|w| w.isooutcrc().detected());
371 trace!("USB event: isooutcrc"); 371 trace!("USB event: isooutcrc");
372 } 372 }
373 if r.usbwuallowed().bit() { 373 if r.usbwuallowed().bit() {
374 regs.eventcause.write(|w| w.usbwuallowed().set_bit()); 374 regs.eventcause.write(|w| w.usbwuallowed().allowed());
375 trace!("USB event: usbwuallowed"); 375 trace!("USB event: usbwuallowed");
376 } 376 }
377 if r.suspend().bit() { 377 if r.suspend().bit() {
378 regs.eventcause.write(|w| w.suspend().set_bit()); 378 regs.eventcause.write(|w| w.suspend().detected());
379 regs.lowpower.write(|w| w.lowpower().low_power()); 379 regs.lowpower.write(|w| w.lowpower().low_power());
380 return Poll::Ready(Event::Suspend); 380 return Poll::Ready(Event::Suspend);
381 } 381 }
382 if r.resume().bit() { 382 if r.resume().bit() {
383 regs.eventcause.write(|w| w.resume().set_bit()); 383 regs.eventcause.write(|w| w.resume().detected());
384 return Poll::Ready(Event::Resume); 384 return Poll::Ready(Event::Resume);
385 } 385 }
386 if r.ready().bit() { 386 if r.ready().bit() {
387 regs.eventcause.write(|w| w.ready().set_bit()); 387 regs.eventcause.write(|w| w.ready().ready());
388 trace!("USB event: ready"); 388 trace!("USB event: ready");
389 } 389 }
390 390
@@ -512,7 +512,7 @@ impl<'d, T: Instance, P: UsbSupply> driver::Bus for Bus<'d, T, P> {
512 } else if r.resume().bit() { 512 } else if r.resume().bit() {
513 Poll::Ready(()) 513 Poll::Ready(())
514 } else if r.usbwuallowed().bit() { 514 } else if r.usbwuallowed().bit() {
515 regs.eventcause.write(|w| w.usbwuallowed().set_bit()); 515 regs.eventcause.write(|w| w.usbwuallowed().allowed());
516 516
517 regs.dpdmvalue.write(|w| w.state().resume()); 517 regs.dpdmvalue.write(|w| w.state().resume());
518 regs.tasks_dpdmdrive.write(|w| w.tasks_dpdmdrive().set_bit()); 518 regs.tasks_dpdmdrive.write(|w| w.tasks_dpdmdrive().set_bit());
diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml
index 2f9c9b9af..04b0c13ce 100644
--- a/embassy-rp/Cargo.toml
+++ b/embassy-rp/Cargo.toml
@@ -53,13 +53,13 @@ cortex-m = "0.7.6"
53critical-section = "1.1" 53critical-section = "1.1"
54futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 54futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
55chrono = { version = "0.4", default-features = false, optional = true } 55chrono = { version = "0.4", default-features = false, optional = true }
56embedded-io = { version = "0.3.1", features = ["async"], optional = true }
56embedded-storage = { version = "0.3" } 57embedded-storage = { version = "0.3" }
57embedded-io = { version = "0.3.0", features = ["async"], optional = true }
58 58
59rp2040-pac2 = { git = "https://github.com/embassy-rs/rp2040-pac2", rev="017e3c9007b2d3b6965f0d85b5bf8ce3fa6d7364", features = ["rt"] } 59rp2040-pac2 = { git = "https://github.com/embassy-rs/rp2040-pac2", rev="017e3c9007b2d3b6965f0d85b5bf8ce3fa6d7364", features = ["rt"] }
60#rp2040-pac2 = { path = "../../rp2040-pac2", features = ["rt"] } 60#rp2040-pac2 = { path = "../../rp2040-pac2", features = ["rt"] }
61 61
62embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } 62embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
63embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9", optional = true} 63embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9", optional = true}
64embedded-hal-async = { version = "=0.1.0-alpha.2", optional = true} 64embedded-hal-async = { version = "=0.1.0-alpha.3", optional = true}
65embedded-hal-nb = { version = "=1.0.0-alpha.1", optional = true} 65embedded-hal-nb = { version = "=1.0.0-alpha.1", optional = true}
diff --git a/embassy-rp/src/timer.rs b/embassy-rp/src/timer.rs
index 5215c0c0f..80efd779f 100644
--- a/embassy-rp/src/timer.rs
+++ b/embassy-rp/src/timer.rs
@@ -68,7 +68,7 @@ impl Driver for TimerDriver {
68 }) 68 })
69 } 69 }
70 70
71 fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) { 71 fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) -> bool {
72 let n = alarm.id() as usize; 72 let n = alarm.id() as usize;
73 critical_section::with(|cs| { 73 critical_section::with(|cs| {
74 let alarm = &self.alarms.borrow(cs)[n]; 74 let alarm = &self.alarms.borrow(cs)[n];
@@ -81,11 +81,16 @@ impl Driver for TimerDriver {
81 unsafe { pac::TIMER.alarm(n).write_value(timestamp as u32) }; 81 unsafe { pac::TIMER.alarm(n).write_value(timestamp as u32) };
82 82
83 let now = self.now(); 83 let now = self.now();
84
85 // If alarm timestamp has passed, trigger it instantly.
86 // This disarms it.
87 if timestamp <= now { 84 if timestamp <= now {
88 self.trigger_alarm(n, cs); 85 // If alarm timestamp has passed the alarm will not fire.
86 // Disarm the alarm and return `false` to indicate that.
87 unsafe { pac::TIMER.armed().write(|w| w.set_armed(1 << n)) }
88
89 alarm.timestamp.set(u64::MAX);
90
91 false
92 } else {
93 true
89 } 94 }
90 }) 95 })
91 } 96 }
diff --git a/embassy-rp/src/uart/buffered.rs b/embassy-rp/src/uart/buffered.rs
index 87e16f0eb..4f0a55532 100644
--- a/embassy-rp/src/uart/buffered.rs
+++ b/embassy-rp/src/uart/buffered.rs
@@ -355,7 +355,7 @@ impl<'d, T: Instance> embedded_io::Io for BufferedUartTx<'d, T> {
355} 355}
356 356
357impl<'d, T: Instance + 'd> embedded_io::asynch::Read for BufferedUart<'d, T> { 357impl<'d, T: Instance + 'd> embedded_io::asynch::Read for BufferedUart<'d, T> {
358 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 358 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
359 where 359 where
360 Self: 'a; 360 Self: 'a;
361 361
@@ -376,7 +376,7 @@ impl<'d, T: Instance + 'd> embedded_io::asynch::Read for BufferedUart<'d, T> {
376} 376}
377 377
378impl<'d, T: Instance + 'd> embedded_io::asynch::Read for BufferedUartRx<'d, T> { 378impl<'d, T: Instance + 'd> embedded_io::asynch::Read for BufferedUartRx<'d, T> {
379 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 379 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
380 where 380 where
381 Self: 'a; 381 Self: 'a;
382 382
@@ -397,7 +397,7 @@ impl<'d, T: Instance + 'd> embedded_io::asynch::Read for BufferedUartRx<'d, T> {
397} 397}
398 398
399impl<'d, T: Instance + 'd> embedded_io::asynch::BufRead for BufferedUart<'d, T> { 399impl<'d, T: Instance + 'd> embedded_io::asynch::BufRead for BufferedUart<'d, T> {
400 type FillBufFuture<'a> = impl Future<Output = Result<&'a [u8], Self::Error>> 400 type FillBufFuture<'a> = impl Future<Output = Result<&'a [u8], Self::Error>> + 'a
401 where 401 where
402 Self: 'a; 402 Self: 'a;
403 403
@@ -419,7 +419,7 @@ impl<'d, T: Instance + 'd> embedded_io::asynch::BufRead for BufferedUart<'d, T>
419} 419}
420 420
421impl<'d, T: Instance + 'd> embedded_io::asynch::BufRead for BufferedUartRx<'d, T> { 421impl<'d, T: Instance + 'd> embedded_io::asynch::BufRead for BufferedUartRx<'d, T> {
422 type FillBufFuture<'a> = impl Future<Output = Result<&'a [u8], Self::Error>> 422 type FillBufFuture<'a> = impl Future<Output = Result<&'a [u8], Self::Error>> + 'a
423 where 423 where
424 Self: 'a; 424 Self: 'a;
425 425
@@ -441,7 +441,7 @@ impl<'d, T: Instance + 'd> embedded_io::asynch::BufRead for BufferedUartRx<'d, T
441} 441}
442 442
443impl<'d, T: Instance + 'd> embedded_io::asynch::Write for BufferedUart<'d, T> { 443impl<'d, T: Instance + 'd> embedded_io::asynch::Write for BufferedUart<'d, T> {
444 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 444 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
445 where 445 where
446 Self: 'a; 446 Self: 'a;
447 447
@@ -455,7 +455,7 @@ impl<'d, T: Instance + 'd> embedded_io::asynch::Write for BufferedUart<'d, T> {
455 }) 455 })
456 } 456 }
457 457
458 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> 458 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a
459 where 459 where
460 Self: 'a; 460 Self: 'a;
461 461
@@ -465,7 +465,7 @@ impl<'d, T: Instance + 'd> embedded_io::asynch::Write for BufferedUart<'d, T> {
465} 465}
466 466
467impl<'d, T: Instance + 'd> embedded_io::asynch::Write for BufferedUartTx<'d, T> { 467impl<'d, T: Instance + 'd> embedded_io::asynch::Write for BufferedUartTx<'d, T> {
468 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 468 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
469 where 469 where
470 Self: 'a; 470 Self: 'a;
471 471
@@ -479,7 +479,7 @@ impl<'d, T: Instance + 'd> embedded_io::asynch::Write for BufferedUartTx<'d, T>
479 }) 479 })
480 } 480 }
481 481
482 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> 482 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a
483 where 483 where
484 Self: 'a; 484 Self: 'a;
485 485
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 9194ae788..6b00518a6 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -44,7 +44,7 @@ embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optiona
44 44
45embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } 45embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
46embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9", optional = true} 46embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9", optional = true}
47embedded-hal-async = { version = "=0.1.0-alpha.2", optional = true} 47embedded-hal-async = { version = "=0.1.0-alpha.3", optional = true}
48embedded-hal-nb = { version = "=1.0.0-alpha.1", optional = true} 48embedded-hal-nb = { version = "=1.0.0-alpha.1", optional = true}
49 49
50embedded-storage = "0.3.0" 50embedded-storage = "0.3.0"
@@ -67,7 +67,7 @@ nb = "1.0.0"
67stm32-fmc = "0.2.4" 67stm32-fmc = "0.2.4"
68seq-macro = "0.3.0" 68seq-macro = "0.3.0"
69cfg-if = "1.0.0" 69cfg-if = "1.0.0"
70embedded-io = { version = "0.3.0", features = ["async"], optional = true } 70embedded-io = { version = "0.3.1", features = ["async"], optional = true }
71 71
72[build-dependencies] 72[build-dependencies]
73proc-macro2 = "1.0.36" 73proc-macro2 = "1.0.36"
@@ -82,9 +82,12 @@ memory-x = ["stm32-metapac/memory-x"]
82subghz = [] 82subghz = []
83exti = [] 83exti = []
84 84
85# Enables additional driver features that depend on embassy-time
86time = ["dep:embassy-time"]
87
85# Features starting with `_` are for internal use only. They're not intended 88# Features starting with `_` are for internal use only. They're not intended
86# to be enabled by other crates, and are not covered by semver guarantees. 89# to be enabled by other crates, and are not covered by semver guarantees.
87_time-driver = ["dep:embassy-time"] 90_time-driver = ["time"]
88time-driver-any = ["_time-driver"] 91time-driver-any = ["_time-driver"]
89time-driver-tim2 = ["_time-driver"] 92time-driver-tim2 = ["_time-driver"]
90time-driver-tim3 = ["_time-driver"] 93time-driver-tim3 = ["_time-driver"]
diff --git a/embassy-stm32/src/adc/f1.rs b/embassy-stm32/src/adc/f1.rs
index 50d4f9bf9..c5b317ce9 100644
--- a/embassy-stm32/src/adc/f1.rs
+++ b/embassy-stm32/src/adc/f1.rs
@@ -86,7 +86,6 @@ pub use sample_time::SampleTime;
86 86
87pub struct Adc<'d, T: Instance> { 87pub struct Adc<'d, T: Instance> {
88 sample_time: SampleTime, 88 sample_time: SampleTime,
89 calibrated_vdda: u32,
90 phantom: PhantomData<&'d mut T>, 89 phantom: PhantomData<&'d mut T>,
91} 90}
92 91
@@ -122,7 +121,6 @@ impl<'d, T: Instance> Adc<'d, T> {
122 121
123 Self { 122 Self {
124 sample_time: Default::default(), 123 sample_time: Default::default(),
125 calibrated_vdda: VDDA_CALIB_MV,
126 phantom: PhantomData, 124 phantom: PhantomData,
127 } 125 }
128 } 126 }
@@ -162,29 +160,10 @@ impl<'d, T: Instance> Adc<'d, T> {
162 Temperature {} 160 Temperature {}
163 } 161 }
164 162
165 /// Calculates the system VDDA by sampling the internal VREF channel and comparing
166 /// to the expected value. If the chip's VDDA is not stable, run this before each ADC
167 /// conversion.
168 pub fn calibrate(&mut self, vref: &mut Vref) -> u32 {
169 let old_sample_time = self.sample_time;
170 self.sample_time = SampleTime::Cycles239_5;
171
172 let vref_samp = self.read(vref);
173 self.sample_time = old_sample_time;
174
175 self.calibrated_vdda = (ADC_MAX * VREF_INT) / u32::from(vref_samp);
176 self.calibrated_vdda
177 }
178
179 pub fn set_sample_time(&mut self, sample_time: SampleTime) { 163 pub fn set_sample_time(&mut self, sample_time: SampleTime) {
180 self.sample_time = sample_time; 164 self.sample_time = sample_time;
181 } 165 }
182 166
183 /// Convert a measurement to millivolts
184 pub fn to_millivolts(&self, sample: u16) -> u16 {
185 ((u32::from(sample) * self.calibrated_vdda) / ADC_MAX) as u16
186 }
187
188 /// Perform a single conversion. 167 /// Perform a single conversion.
189 fn convert(&mut self) -> u16 { 168 fn convert(&mut self) -> u16 {
190 unsafe { 169 unsafe {
diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs
index 4fe4ad1f0..53419c7f2 100644
--- a/embassy-stm32/src/adc/v2.rs
+++ b/embassy-stm32/src/adc/v2.rs
@@ -80,15 +80,6 @@ impl super::sealed::InternalChannel<ADC1> for Temperature {
80} 80}
81 81
82impl Temperature { 82impl Temperature {
83 /// Converts temperature sensor reading in millivolts to degrees celcius
84 pub fn to_celcius(sample_mv: u16) -> f32 {
85 // From 6.3.22 Temperature sensor characteristics
86 const V25: i32 = 760; // mV
87 const AVG_SLOPE: f32 = 2.5; // mV/C
88
89 (sample_mv as i32 - V25) as f32 / AVG_SLOPE + 25.0
90 }
91
92 /// Time needed for temperature sensor readings to stabilize 83 /// Time needed for temperature sensor readings to stabilize
93 pub fn start_time_us() -> u32 { 84 pub fn start_time_us() -> u32 {
94 10 85 10
@@ -172,7 +163,6 @@ impl Prescaler {
172 163
173pub struct Adc<'d, T: Instance> { 164pub struct Adc<'d, T: Instance> {
174 sample_time: SampleTime, 165 sample_time: SampleTime,
175 vref_mv: u32,
176 resolution: Resolution, 166 resolution: Resolution,
177 phantom: PhantomData<&'d mut T>, 167 phantom: PhantomData<&'d mut T>,
178} 168}
@@ -200,7 +190,6 @@ where
200 Self { 190 Self {
201 sample_time: Default::default(), 191 sample_time: Default::default(),
202 resolution: Resolution::default(), 192 resolution: Resolution::default(),
203 vref_mv: VREF_DEFAULT_MV,
204 phantom: PhantomData, 193 phantom: PhantomData,
205 } 194 }
206 } 195 }
@@ -213,18 +202,6 @@ where
213 self.resolution = resolution; 202 self.resolution = resolution;
214 } 203 }
215 204
216 /// Set VREF value in millivolts. This value is used for [to_millivolts()] sample conversion.
217 ///
218 /// Use this if you have a known precise VREF (VDDA) pin reference voltage.
219 pub fn set_vref_mv(&mut self, vref_mv: u32) {
220 self.vref_mv = vref_mv;
221 }
222
223 /// Convert a measurement to millivolts
224 pub fn to_millivolts(&self, sample: u16) -> u16 {
225 ((u32::from(sample) * self.vref_mv) / self.resolution.to_max_count()) as u16
226 }
227
228 /// Enables internal voltage reference and returns [VrefInt], which can be used in 205 /// Enables internal voltage reference and returns [VrefInt], which can be used in
229 /// [Adc::read_internal()] to perform conversion. 206 /// [Adc::read_internal()] to perform conversion.
230 pub fn enable_vrefint(&self) -> VrefInt { 207 pub fn enable_vrefint(&self) -> VrefInt {
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs
index 0f1090888..816feeac7 100644
--- a/embassy-stm32/src/adc/v3.rs
+++ b/embassy-stm32/src/adc/v3.rs
@@ -205,7 +205,6 @@ pub use sample_time::SampleTime;
205 205
206pub struct Adc<'d, T: Instance> { 206pub struct Adc<'d, T: Instance> {
207 sample_time: SampleTime, 207 sample_time: SampleTime,
208 vref_mv: u32,
209 resolution: Resolution, 208 resolution: Resolution,
210 phantom: PhantomData<&'d mut T>, 209 phantom: PhantomData<&'d mut T>,
211} 210}
@@ -244,7 +243,6 @@ impl<'d, T: Instance> Adc<'d, T> {
244 Self { 243 Self {
245 sample_time: Default::default(), 244 sample_time: Default::default(),
246 resolution: Resolution::default(), 245 resolution: Resolution::default(),
247 vref_mv: VREF_DEFAULT_MV,
248 phantom: PhantomData, 246 phantom: PhantomData,
249 } 247 }
250 } 248 }
@@ -285,31 +283,6 @@ impl<'d, T: Instance> Adc<'d, T> {
285 Vbat {} 283 Vbat {}
286 } 284 }
287 285
288 /// Calculates the system VDDA by sampling the internal VREFINT channel and comparing
289 /// the result with the value stored at the factory. If the chip's VDDA is not stable, run
290 /// this before each ADC conversion.
291 #[cfg(not(stm32g0))] // TODO is this supposed to be public?
292 #[allow(unused)] // TODO is this supposed to be public?
293 fn calibrate(&mut self, vrefint: &mut VrefInt) {
294 #[cfg(stm32l5)]
295 let vrefint_cal: u32 = todo!();
296 #[cfg(not(stm32l5))]
297 let vrefint_cal = unsafe { crate::pac::VREFINTCAL.data().read().value() };
298 let old_sample_time = self.sample_time;
299
300 // "Table 24. Embedded internal voltage reference" states that the sample time needs to be
301 // at a minimum 4 us. With 640.5 ADC cycles we have a minimum of 8 us at 80 MHz, leaving
302 // some headroom.
303 self.sample_time = SampleTime::Cycles640_5;
304
305 // This can't actually fail, it's just in a result to satisfy hal trait
306 let vrefint_samp = self.read(vrefint);
307
308 self.sample_time = old_sample_time;
309
310 self.vref_mv = (VREF_CALIB_MV * u32::from(vrefint_cal)) / u32::from(vrefint_samp);
311 }
312
313 pub fn set_sample_time(&mut self, sample_time: SampleTime) { 286 pub fn set_sample_time(&mut self, sample_time: SampleTime) {
314 self.sample_time = sample_time; 287 self.sample_time = sample_time;
315 } 288 }
@@ -318,18 +291,6 @@ impl<'d, T: Instance> Adc<'d, T> {
318 self.resolution = resolution; 291 self.resolution = resolution;
319 } 292 }
320 293
321 /// Set VREF value in millivolts. This value is used for [to_millivolts()] sample conversion.
322 ///
323 /// Use this if you have a known precise VREF (VDDA) pin reference voltage.
324 pub fn set_vref_mv(&mut self, vref_mv: u32) {
325 self.vref_mv = vref_mv;
326 }
327
328 /// Convert a measurement to millivolts
329 pub fn to_millivolts(&self, sample: u16) -> u16 {
330 ((u32::from(sample) * self.vref_mv) / self.resolution.to_max_count()) as u16
331 }
332
333 /* 294 /*
334 /// Convert a raw sample from the `Temperature` to deg C 295 /// Convert a raw sample from the `Temperature` to deg C
335 pub fn to_degrees_centigrade(sample: u16) -> f32 { 296 pub fn to_degrees_centigrade(sample: u16) -> f32 {
diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs
index eda2b2a72..2b8f10533 100644
--- a/embassy-stm32/src/adc/v4.rs
+++ b/embassy-stm32/src/adc/v4.rs
@@ -314,7 +314,6 @@ impl Prescaler {
314 314
315pub struct Adc<'d, T: Instance> { 315pub struct Adc<'d, T: Instance> {
316 sample_time: SampleTime, 316 sample_time: SampleTime,
317 vref_mv: u32,
318 resolution: Resolution, 317 resolution: Resolution,
319 phantom: PhantomData<&'d mut T>, 318 phantom: PhantomData<&'d mut T>,
320} 319}
@@ -352,7 +351,6 @@ impl<'d, T: Instance + crate::rcc::RccPeripheral> Adc<'d, T> {
352 351
353 let mut s = Self { 352 let mut s = Self {
354 sample_time: Default::default(), 353 sample_time: Default::default(),
355 vref_mv: VREF_DEFAULT_MV,
356 resolution: Resolution::default(), 354 resolution: Resolution::default(),
357 phantom: PhantomData, 355 phantom: PhantomData,
358 }; 356 };
@@ -459,18 +457,6 @@ impl<'d, T: Instance + crate::rcc::RccPeripheral> Adc<'d, T> {
459 self.resolution = resolution; 457 self.resolution = resolution;
460 } 458 }
461 459
462 /// Set VREF value in millivolts. This value is used for [to_millivolts()] sample conversion.
463 ///
464 /// Use this if you have a known precise VREF (VDDA) pin reference voltage.
465 pub fn set_vref_mv(&mut self, vref_mv: u32) {
466 self.vref_mv = vref_mv;
467 }
468
469 /// Convert a measurement to millivolts
470 pub fn to_millivolts(&self, sample: u16) -> u16 {
471 ((u32::from(sample) * self.vref_mv) / self.resolution.to_max_count()) as u16
472 }
473
474 /// Perform a single conversion. 460 /// Perform a single conversion.
475 fn convert(&mut self) -> u16 { 461 fn convert(&mut self) -> u16 {
476 unsafe { 462 unsafe {
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs
index 9d314f411..f898fcc8b 100644
--- a/embassy-stm32/src/i2c/mod.rs
+++ b/embassy-stm32/src/i2c/mod.rs
@@ -7,6 +7,11 @@ use crate::interrupt::Interrupt;
7mod _version; 7mod _version;
8pub use _version::*; 8pub use _version::*;
9 9
10#[cfg(feature = "time")]
11mod timeout;
12#[cfg(feature = "time")]
13pub use timeout::*;
14
10use crate::peripherals; 15use crate::peripherals;
11 16
12#[derive(Debug)] 17#[derive(Debug)]
diff --git a/embassy-stm32/src/i2c/timeout.rs b/embassy-stm32/src/i2c/timeout.rs
new file mode 100644
index 000000000..4fca1ca2b
--- /dev/null
+++ b/embassy-stm32/src/i2c/timeout.rs
@@ -0,0 +1,142 @@
1use embassy_time::{Duration, Instant};
2
3use super::{Error, I2c, Instance};
4
5/// An I2C wrapper, which provides `embassy-time` based timeouts for all `embedded-hal` trait methods.
6///
7/// This is useful for recovering from a shorted bus or a device stuck in a clock stretching state.
8/// A regular [I2c] would freeze until condition is removed.
9pub struct TimeoutI2c<'d, T: Instance, TXDMA, RXDMA> {
10 i2c: &'d mut I2c<'d, T, TXDMA, RXDMA>,
11 timeout: Duration,
12}
13
14fn timeout_fn(timeout: Duration) -> impl Fn() -> Result<(), Error> {
15 let deadline = Instant::now() + timeout;
16 move || {
17 if Instant::now() > deadline {
18 Err(Error::Timeout)
19 } else {
20 Ok(())
21 }
22 }
23}
24
25impl<'d, T: Instance, TXDMA, RXDMA> TimeoutI2c<'d, T, TXDMA, RXDMA> {
26 pub fn new(i2c: &'d mut I2c<'d, T, TXDMA, RXDMA>, timeout: Duration) -> Self {
27 Self { i2c, timeout }
28 }
29
30 /// Blocking read with a custom timeout
31 pub fn blocking_read_timeout(&mut self, addr: u8, buffer: &mut [u8], timeout: Duration) -> Result<(), Error> {
32 self.i2c.blocking_read_timeout(addr, buffer, timeout_fn(timeout))
33 }
34
35 /// Blocking read with default timeout, provided in [`TimeoutI2c::new()`]
36 pub fn blocking_read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> {
37 self.blocking_read_timeout(addr, buffer, self.timeout)
38 }
39
40 /// Blocking write with a custom timeout
41 pub fn blocking_write_timeout(&mut self, addr: u8, bytes: &[u8], timeout: Duration) -> Result<(), Error> {
42 self.i2c.blocking_write_timeout(addr, bytes, timeout_fn(timeout))
43 }
44
45 /// Blocking write with default timeout, provided in [`TimeoutI2c::new()`]
46 pub fn blocking_write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
47 self.blocking_write_timeout(addr, bytes, self.timeout)
48 }
49
50 /// Blocking write-read with a custom timeout
51 pub fn blocking_write_read_timeout(
52 &mut self,
53 addr: u8,
54 bytes: &[u8],
55 buffer: &mut [u8],
56 timeout: Duration,
57 ) -> Result<(), Error> {
58 self.i2c
59 .blocking_write_read_timeout(addr, bytes, buffer, timeout_fn(timeout))
60 }
61
62 /// Blocking write-read with default timeout, provided in [`TimeoutI2c::new()`]
63 pub fn blocking_write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> {
64 self.blocking_write_read_timeout(addr, bytes, buffer, self.timeout)
65 }
66}
67
68impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Read for TimeoutI2c<'d, T, TXDMA, RXDMA> {
69 type Error = Error;
70
71 fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
72 self.blocking_read(addr, buffer)
73 }
74}
75
76impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Write for TimeoutI2c<'d, T, TXDMA, RXDMA> {
77 type Error = Error;
78
79 fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> {
80 self.blocking_write(addr, bytes)
81 }
82}
83
84impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::WriteRead for TimeoutI2c<'d, T, TXDMA, RXDMA> {
85 type Error = Error;
86
87 fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> {
88 self.blocking_write_read(addr, bytes, buffer)
89 }
90}
91
92#[cfg(feature = "unstable-traits")]
93mod eh1 {
94 use super::*;
95
96 impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::ErrorType for TimeoutI2c<'d, T, TXDMA, RXDMA> {
97 type Error = Error;
98 }
99
100 impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::I2c for TimeoutI2c<'d, T, TXDMA, RXDMA> {
101 fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
102 self.blocking_read(address, buffer)
103 }
104
105 fn write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Self::Error> {
106 self.blocking_write(address, buffer)
107 }
108
109 fn write_iter<B>(&mut self, _address: u8, _bytes: B) -> Result<(), Self::Error>
110 where
111 B: IntoIterator<Item = u8>,
112 {
113 todo!();
114 }
115
116 fn write_iter_read<B>(&mut self, _address: u8, _bytes: B, _buffer: &mut [u8]) -> Result<(), Self::Error>
117 where
118 B: IntoIterator<Item = u8>,
119 {
120 todo!();
121 }
122
123 fn write_read(&mut self, address: u8, wr_buffer: &[u8], rd_buffer: &mut [u8]) -> Result<(), Self::Error> {
124 self.blocking_write_read(address, wr_buffer, rd_buffer)
125 }
126
127 fn transaction<'a>(
128 &mut self,
129 _address: u8,
130 _operations: &mut [embedded_hal_1::i2c::Operation<'a>],
131 ) -> Result<(), Self::Error> {
132 todo!();
133 }
134
135 fn transaction_iter<'a, O>(&mut self, _address: u8, _operations: O) -> Result<(), Self::Error>
136 where
137 O: IntoIterator<Item = embedded_hal_1::i2c::Operation<'a>>,
138 {
139 todo!();
140 }
141 }
142}
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs
index f39a37df6..f140e2b0d 100644
--- a/embassy-stm32/src/i2c/v1.rs
+++ b/embassy-stm32/src/i2c/v1.rs
@@ -1,8 +1,9 @@
1use core::marker::PhantomData; 1use core::marker::PhantomData;
2 2
3use embassy_embedded_hal::SetConfig; 3use embassy_embedded_hal::SetConfig;
4use embassy_hal_common::into_ref; 4use embassy_hal_common::{into_ref, PeripheralRef};
5 5
6use crate::dma::NoDma;
6use crate::gpio::sealed::AFType; 7use crate::gpio::sealed::AFType;
7use crate::gpio::Pull; 8use crate::gpio::Pull;
8use crate::i2c::{Error, Instance, SclPin, SdaPin}; 9use crate::i2c::{Error, Instance, SclPin, SdaPin};
@@ -34,19 +35,26 @@ impl State {
34 } 35 }
35} 36}
36 37
37pub struct I2c<'d, T: Instance> { 38pub struct I2c<'d, T: Instance, TXDMA = NoDma, RXDMA = NoDma> {
38 phantom: PhantomData<&'d mut T>, 39 phantom: PhantomData<&'d mut T>,
40 #[allow(dead_code)]
41 tx_dma: PeripheralRef<'d, TXDMA>,
42 #[allow(dead_code)]
43 rx_dma: PeripheralRef<'d, RXDMA>,
39} 44}
40 45
41impl<'d, T: Instance> I2c<'d, T> { 46impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
42 pub fn new( 47 pub fn new(
43 _peri: impl Peripheral<P = T> + 'd, 48 _peri: impl Peripheral<P = T> + 'd,
44 scl: impl Peripheral<P = impl SclPin<T>> + 'd, 49 scl: impl Peripheral<P = impl SclPin<T>> + 'd,
45 sda: impl Peripheral<P = impl SdaPin<T>> + 'd, 50 sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
51 _irq: impl Peripheral<P = T::Interrupt> + 'd,
52 tx_dma: impl Peripheral<P = TXDMA> + 'd,
53 rx_dma: impl Peripheral<P = RXDMA> + 'd,
46 freq: Hertz, 54 freq: Hertz,
47 config: Config, 55 config: Config,
48 ) -> Self { 56 ) -> Self {
49 into_ref!(scl, sda); 57 into_ref!(scl, sda, tx_dma, rx_dma);
50 58
51 T::enable(); 59 T::enable();
52 T::reset(); 60 T::reset();
@@ -99,7 +107,11 @@ impl<'d, T: Instance> I2c<'d, T> {
99 }); 107 });
100 } 108 }
101 109
102 Self { phantom: PhantomData } 110 Self {
111 phantom: PhantomData,
112 tx_dma,
113 rx_dma,
114 }
103 } 115 }
104 116
105 unsafe fn check_and_clear_error_flags(&self) -> Result<i2c::regs::Sr1, Error> { 117 unsafe fn check_and_clear_error_flags(&self) -> Result<i2c::regs::Sr1, Error> {
@@ -141,7 +153,12 @@ impl<'d, T: Instance> I2c<'d, T> {
141 Ok(sr1) 153 Ok(sr1)
142 } 154 }
143 155
144 unsafe fn write_bytes(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { 156 unsafe fn write_bytes(
157 &mut self,
158 addr: u8,
159 bytes: &[u8],
160 check_timeout: impl Fn() -> Result<(), Error>,
161 ) -> Result<(), Error> {
145 // Send a START condition 162 // Send a START condition
146 163
147 T::regs().cr1().modify(|reg| { 164 T::regs().cr1().modify(|reg| {
@@ -149,7 +166,9 @@ impl<'d, T: Instance> I2c<'d, T> {
149 }); 166 });
150 167
151 // Wait until START condition was generated 168 // Wait until START condition was generated
152 while !self.check_and_clear_error_flags()?.start() {} 169 while !self.check_and_clear_error_flags()?.start() {
170 check_timeout()?;
171 }
153 172
154 // Also wait until signalled we're master and everything is waiting for us 173 // Also wait until signalled we're master and everything is waiting for us
155 while { 174 while {
@@ -157,7 +176,9 @@ impl<'d, T: Instance> I2c<'d, T> {
157 176
158 let sr2 = T::regs().sr2().read(); 177 let sr2 = T::regs().sr2().read();
159 !sr2.msl() && !sr2.busy() 178 !sr2.msl() && !sr2.busy()
160 } {} 179 } {
180 check_timeout()?;
181 }
161 182
162 // Set up current address, we're trying to talk to 183 // Set up current address, we're trying to talk to
163 T::regs().dr().write(|reg| reg.set_dr(addr << 1)); 184 T::regs().dr().write(|reg| reg.set_dr(addr << 1));
@@ -165,26 +186,30 @@ impl<'d, T: Instance> I2c<'d, T> {
165 // Wait until address was sent 186 // Wait until address was sent
166 // Wait for the address to be acknowledged 187 // Wait for the address to be acknowledged
167 // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set. 188 // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set.
168 while !self.check_and_clear_error_flags()?.addr() {} 189 while !self.check_and_clear_error_flags()?.addr() {
190 check_timeout()?;
191 }
169 192
170 // Clear condition by reading SR2 193 // Clear condition by reading SR2
171 let _ = T::regs().sr2().read(); 194 let _ = T::regs().sr2().read();
172 195
173 // Send bytes 196 // Send bytes
174 for c in bytes { 197 for c in bytes {
175 self.send_byte(*c)?; 198 self.send_byte(*c, &check_timeout)?;
176 } 199 }
177 200
178 // Fallthrough is success 201 // Fallthrough is success
179 Ok(()) 202 Ok(())
180 } 203 }
181 204
182 unsafe fn send_byte(&self, byte: u8) -> Result<(), Error> { 205 unsafe fn send_byte(&self, byte: u8, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
183 // Wait until we're ready for sending 206 // Wait until we're ready for sending
184 while { 207 while {
185 // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set. 208 // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set.
186 !self.check_and_clear_error_flags()?.txe() 209 !self.check_and_clear_error_flags()?.txe()
187 } {} 210 } {
211 check_timeout()?;
212 }
188 213
189 // Push out a byte of data 214 // Push out a byte of data
190 T::regs().dr().write(|reg| reg.set_dr(byte)); 215 T::regs().dr().write(|reg| reg.set_dr(byte));
@@ -193,24 +218,33 @@ impl<'d, T: Instance> I2c<'d, T> {
193 while { 218 while {
194 // Check for any potential error conditions. 219 // Check for any potential error conditions.
195 !self.check_and_clear_error_flags()?.btf() 220 !self.check_and_clear_error_flags()?.btf()
196 } {} 221 } {
222 check_timeout()?;
223 }
197 224
198 Ok(()) 225 Ok(())
199 } 226 }
200 227
201 unsafe fn recv_byte(&self) -> Result<u8, Error> { 228 unsafe fn recv_byte(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<u8, Error> {
202 while { 229 while {
203 // Check for any potential error conditions. 230 // Check for any potential error conditions.
204 self.check_and_clear_error_flags()?; 231 self.check_and_clear_error_flags()?;
205 232
206 !T::regs().sr1().read().rxne() 233 !T::regs().sr1().read().rxne()
207 } {} 234 } {
235 check_timeout()?;
236 }
208 237
209 let value = T::regs().dr().read().dr(); 238 let value = T::regs().dr().read().dr();
210 Ok(value) 239 Ok(value)
211 } 240 }
212 241
213 pub fn blocking_read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> { 242 pub fn blocking_read_timeout(
243 &mut self,
244 addr: u8,
245 buffer: &mut [u8],
246 check_timeout: impl Fn() -> Result<(), Error>,
247 ) -> Result<(), Error> {
214 if let Some((last, buffer)) = buffer.split_last_mut() { 248 if let Some((last, buffer)) = buffer.split_last_mut() {
215 // Send a START condition and set ACK bit 249 // Send a START condition and set ACK bit
216 unsafe { 250 unsafe {
@@ -221,27 +255,33 @@ impl<'d, T: Instance> I2c<'d, T> {
221 } 255 }
222 256
223 // Wait until START condition was generated 257 // Wait until START condition was generated
224 while unsafe { !T::regs().sr1().read().start() } {} 258 while unsafe { !self.check_and_clear_error_flags()?.start() } {
259 check_timeout()?;
260 }
225 261
226 // Also wait until signalled we're master and everything is waiting for us 262 // Also wait until signalled we're master and everything is waiting for us
227 while { 263 while {
228 let sr2 = unsafe { T::regs().sr2().read() }; 264 let sr2 = unsafe { T::regs().sr2().read() };
229 !sr2.msl() && !sr2.busy() 265 !sr2.msl() && !sr2.busy()
230 } {} 266 } {
267 check_timeout()?;
268 }
231 269
232 // Set up current address, we're trying to talk to 270 // Set up current address, we're trying to talk to
233 unsafe { T::regs().dr().write(|reg| reg.set_dr((addr << 1) + 1)) } 271 unsafe { T::regs().dr().write(|reg| reg.set_dr((addr << 1) + 1)) }
234 272
235 // Wait until address was sent 273 // Wait until address was sent
236 // Wait for the address to be acknowledged 274 // Wait for the address to be acknowledged
237 while unsafe { !self.check_and_clear_error_flags()?.addr() } {} 275 while unsafe { !self.check_and_clear_error_flags()?.addr() } {
276 check_timeout()?;
277 }
238 278
239 // Clear condition by reading SR2 279 // Clear condition by reading SR2
240 let _ = unsafe { T::regs().sr2().read() }; 280 let _ = unsafe { T::regs().sr2().read() };
241 281
242 // Receive bytes into buffer 282 // Receive bytes into buffer
243 for c in buffer { 283 for c in buffer {
244 *c = unsafe { self.recv_byte()? }; 284 *c = unsafe { self.recv_byte(&check_timeout)? };
245 } 285 }
246 286
247 // Prepare to send NACK then STOP after next byte 287 // Prepare to send NACK then STOP after next byte
@@ -253,10 +293,12 @@ impl<'d, T: Instance> I2c<'d, T> {
253 } 293 }
254 294
255 // Receive last byte 295 // Receive last byte
256 *last = unsafe { self.recv_byte()? }; 296 *last = unsafe { self.recv_byte(&check_timeout)? };
257 297
258 // Wait for the STOP to be sent. 298 // Wait for the STOP to be sent.
259 while unsafe { T::regs().cr1().read().stop() } {} 299 while unsafe { T::regs().cr1().read().stop() } {
300 check_timeout()?;
301 }
260 302
261 // Fallthrough is success 303 // Fallthrough is success
262 Ok(()) 304 Ok(())
@@ -265,25 +307,50 @@ impl<'d, T: Instance> I2c<'d, T> {
265 } 307 }
266 } 308 }
267 309
268 pub fn blocking_write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { 310 pub fn blocking_read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> {
311 self.blocking_read_timeout(addr, buffer, || Ok(()))
312 }
313
314 pub fn blocking_write_timeout(
315 &mut self,
316 addr: u8,
317 bytes: &[u8],
318 check_timeout: impl Fn() -> Result<(), Error>,
319 ) -> Result<(), Error> {
269 unsafe { 320 unsafe {
270 self.write_bytes(addr, bytes)?; 321 self.write_bytes(addr, bytes, &check_timeout)?;
271 // Send a STOP condition 322 // Send a STOP condition
272 T::regs().cr1().modify(|reg| reg.set_stop(true)); 323 T::regs().cr1().modify(|reg| reg.set_stop(true));
273 // Wait for STOP condition to transmit. 324 // Wait for STOP condition to transmit.
274 while T::regs().cr1().read().stop() {} 325 while T::regs().cr1().read().stop() {
326 check_timeout()?;
327 }
275 }; 328 };
276 329
277 // Fallthrough is success 330 // Fallthrough is success
278 Ok(()) 331 Ok(())
279 } 332 }
280 333
281 pub fn blocking_write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> { 334 pub fn blocking_write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
282 unsafe { self.write_bytes(addr, bytes)? }; 335 self.blocking_write_timeout(addr, bytes, || Ok(()))
283 self.blocking_read(addr, buffer)?; 336 }
337
338 pub fn blocking_write_read_timeout(
339 &mut self,
340 addr: u8,
341 bytes: &[u8],
342 buffer: &mut [u8],
343 check_timeout: impl Fn() -> Result<(), Error>,
344 ) -> Result<(), Error> {
345 unsafe { self.write_bytes(addr, bytes, &check_timeout)? };
346 self.blocking_read_timeout(addr, buffer, &check_timeout)?;
284 347
285 Ok(()) 348 Ok(())
286 } 349 }
350
351 pub fn blocking_write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> {
352 self.blocking_write_read_timeout(addr, bytes, buffer, || Ok(()))
353 }
287} 354}
288 355
289impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Read for I2c<'d, T> { 356impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Read for I2c<'d, T> {
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 89b52da98..aa4e6bb08 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -147,14 +147,23 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
147 } 147 }
148 } 148 }
149 149
150 unsafe fn master_read(address: u8, length: usize, stop: Stop, reload: bool, restart: bool) { 150 unsafe fn master_read(
151 address: u8,
152 length: usize,
153 stop: Stop,
154 reload: bool,
155 restart: bool,
156 check_timeout: impl Fn() -> Result<(), Error>,
157 ) -> Result<(), Error> {
151 assert!(length < 256); 158 assert!(length < 256);
152 159
153 if !restart { 160 if !restart {
154 // Wait for any previous address sequence to end 161 // Wait for any previous address sequence to end
155 // automatically. This could be up to 50% of a bus 162 // automatically. This could be up to 50% of a bus
156 // cycle (ie. up to 0.5/freq) 163 // cycle (ie. up to 0.5/freq)
157 while T::regs().cr2().read().start() {} 164 while T::regs().cr2().read().start() {
165 check_timeout()?;
166 }
158 } 167 }
159 168
160 // Set START and prepare to receive bytes into 169 // Set START and prepare to receive bytes into
@@ -176,15 +185,25 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
176 w.set_autoend(stop.autoend()); 185 w.set_autoend(stop.autoend());
177 w.set_reload(reload); 186 w.set_reload(reload);
178 }); 187 });
188
189 Ok(())
179 } 190 }
180 191
181 unsafe fn master_write(address: u8, length: usize, stop: Stop, reload: bool) { 192 unsafe fn master_write(
193 address: u8,
194 length: usize,
195 stop: Stop,
196 reload: bool,
197 check_timeout: impl Fn() -> Result<(), Error>,
198 ) -> Result<(), Error> {
182 assert!(length < 256); 199 assert!(length < 256);
183 200
184 // Wait for any previous address sequence to end 201 // Wait for any previous address sequence to end
185 // automatically. This could be up to 50% of a bus 202 // automatically. This could be up to 50% of a bus
186 // cycle (ie. up to 0.5/freq) 203 // cycle (ie. up to 0.5/freq)
187 while T::regs().cr2().read().start() {} 204 while T::regs().cr2().read().start() {
205 check_timeout()?;
206 }
188 207
189 let reload = if reload { 208 let reload = if reload {
190 i2c::vals::Reload::NOTCOMPLETED 209 i2c::vals::Reload::NOTCOMPLETED
@@ -204,12 +223,20 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
204 w.set_autoend(stop.autoend()); 223 w.set_autoend(stop.autoend());
205 w.set_reload(reload); 224 w.set_reload(reload);
206 }); 225 });
226
227 Ok(())
207 } 228 }
208 229
209 unsafe fn master_continue(length: usize, reload: bool) { 230 unsafe fn master_continue(
231 length: usize,
232 reload: bool,
233 check_timeout: impl Fn() -> Result<(), Error>,
234 ) -> Result<(), Error> {
210 assert!(length < 256 && length > 0); 235 assert!(length < 256 && length > 0);
211 236
212 while !T::regs().isr().read().tcr() {} 237 while !T::regs().isr().read().tcr() {
238 check_timeout()?;
239 }
213 240
214 let reload = if reload { 241 let reload = if reload {
215 i2c::vals::Reload::NOTCOMPLETED 242 i2c::vals::Reload::NOTCOMPLETED
@@ -221,6 +248,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
221 w.set_nbytes(length as u8); 248 w.set_nbytes(length as u8);
222 w.set_reload(reload); 249 w.set_reload(reload);
223 }); 250 });
251
252 Ok(())
224 } 253 }
225 254
226 fn flush_txdr(&self) { 255 fn flush_txdr(&self) {
@@ -243,7 +272,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
243 //} 272 //}
244 } 273 }
245 274
246 fn wait_txe(&self) -> Result<(), Error> { 275 fn wait_txe(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
247 loop { 276 loop {
248 unsafe { 277 unsafe {
249 let isr = T::regs().isr().read(); 278 let isr = T::regs().isr().read();
@@ -261,10 +290,12 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
261 return Err(Error::Nack); 290 return Err(Error::Nack);
262 } 291 }
263 } 292 }
293
294 check_timeout()?;
264 } 295 }
265 } 296 }
266 297
267 fn wait_rxne(&self) -> Result<(), Error> { 298 fn wait_rxne(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
268 loop { 299 loop {
269 unsafe { 300 unsafe {
270 let isr = T::regs().isr().read(); 301 let isr = T::regs().isr().read();
@@ -282,10 +313,12 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
282 return Err(Error::Nack); 313 return Err(Error::Nack);
283 } 314 }
284 } 315 }
316
317 check_timeout()?;
285 } 318 }
286 } 319 }
287 320
288 fn wait_tc(&self) -> Result<(), Error> { 321 fn wait_tc(&self, check_timeout: impl Fn() -> Result<(), Error>) -> Result<(), Error> {
289 loop { 322 loop {
290 unsafe { 323 unsafe {
291 let isr = T::regs().isr().read(); 324 let isr = T::regs().isr().read();
@@ -303,10 +336,18 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
303 return Err(Error::Nack); 336 return Err(Error::Nack);
304 } 337 }
305 } 338 }
339
340 check_timeout()?;
306 } 341 }
307 } 342 }
308 343
309 fn read_internal(&mut self, address: u8, buffer: &mut [u8], restart: bool) -> Result<(), Error> { 344 fn read_internal(
345 &mut self,
346 address: u8,
347 buffer: &mut [u8],
348 restart: bool,
349 check_timeout: impl Fn() -> Result<(), Error>,
350 ) -> Result<(), Error> {
310 let completed_chunks = buffer.len() / 255; 351 let completed_chunks = buffer.len() / 255;
311 let total_chunks = if completed_chunks * 255 == buffer.len() { 352 let total_chunks = if completed_chunks * 255 == buffer.len() {
312 completed_chunks 353 completed_chunks
@@ -322,20 +363,21 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
322 Stop::Automatic, 363 Stop::Automatic,
323 last_chunk_idx != 0, 364 last_chunk_idx != 0,
324 restart, 365 restart,
325 ); 366 &check_timeout,
367 )?;
326 } 368 }
327 369
328 for (number, chunk) in buffer.chunks_mut(255).enumerate() { 370 for (number, chunk) in buffer.chunks_mut(255).enumerate() {
329 if number != 0 { 371 if number != 0 {
330 // NOTE(unsafe) We have &mut self 372 // NOTE(unsafe) We have &mut self
331 unsafe { 373 unsafe {
332 Self::master_continue(chunk.len(), number != last_chunk_idx); 374 Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?;
333 } 375 }
334 } 376 }
335 377
336 for byte in chunk { 378 for byte in chunk {
337 // Wait until we have received something 379 // Wait until we have received something
338 self.wait_rxne()?; 380 self.wait_rxne(&check_timeout)?;
339 381
340 unsafe { 382 unsafe {
341 *byte = T::regs().rxdr().read().rxdata(); 383 *byte = T::regs().rxdr().read().rxdata();
@@ -345,7 +387,13 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
345 Ok(()) 387 Ok(())
346 } 388 }
347 389
348 fn write_internal(&mut self, address: u8, bytes: &[u8], send_stop: bool) -> Result<(), Error> { 390 fn write_internal(
391 &mut self,
392 address: u8,
393 bytes: &[u8],
394 send_stop: bool,
395 check_timeout: impl Fn() -> Result<(), Error>,
396 ) -> Result<(), Error> {
349 let completed_chunks = bytes.len() / 255; 397 let completed_chunks = bytes.len() / 255;
350 let total_chunks = if completed_chunks * 255 == bytes.len() { 398 let total_chunks = if completed_chunks * 255 == bytes.len() {
351 completed_chunks 399 completed_chunks
@@ -359,14 +407,20 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
359 // ST SAD+W 407 // ST SAD+W
360 // NOTE(unsafe) We have &mut self 408 // NOTE(unsafe) We have &mut self
361 unsafe { 409 unsafe {
362 Self::master_write(address, bytes.len().min(255), Stop::Software, last_chunk_idx != 0); 410 Self::master_write(
411 address,
412 bytes.len().min(255),
413 Stop::Software,
414 last_chunk_idx != 0,
415 &check_timeout,
416 )?;
363 } 417 }
364 418
365 for (number, chunk) in bytes.chunks(255).enumerate() { 419 for (number, chunk) in bytes.chunks(255).enumerate() {
366 if number != 0 { 420 if number != 0 {
367 // NOTE(unsafe) We have &mut self 421 // NOTE(unsafe) We have &mut self
368 unsafe { 422 unsafe {
369 Self::master_continue(chunk.len(), number != last_chunk_idx); 423 Self::master_continue(chunk.len(), number != last_chunk_idx, &check_timeout)?;
370 } 424 }
371 } 425 }
372 426
@@ -374,7 +428,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
374 // Wait until we are allowed to send data 428 // Wait until we are allowed to send data
375 // (START has been ACKed or last byte when 429 // (START has been ACKed or last byte when
376 // through) 430 // through)
377 self.wait_txe()?; 431 self.wait_txe(&check_timeout)?;
378 432
379 unsafe { 433 unsafe {
380 T::regs().txdr().write(|w| w.set_txdata(*byte)); 434 T::regs().txdr().write(|w| w.set_txdata(*byte));
@@ -382,7 +436,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
382 } 436 }
383 } 437 }
384 // Wait until the write finishes 438 // Wait until the write finishes
385 self.wait_tc()?; 439 self.wait_tc(&check_timeout)?;
386 440
387 if send_stop { 441 if send_stop {
388 self.master_stop(); 442 self.master_stop();
@@ -396,6 +450,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
396 bytes: &[u8], 450 bytes: &[u8],
397 first_slice: bool, 451 first_slice: bool,
398 last_slice: bool, 452 last_slice: bool,
453 check_timeout: impl Fn() -> Result<(), Error>,
399 ) -> Result<(), Error> 454 ) -> Result<(), Error>
400 where 455 where
401 TXDMA: crate::i2c::TxDma<T>, 456 TXDMA: crate::i2c::TxDma<T>,
@@ -447,11 +502,12 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
447 total_len.min(255), 502 total_len.min(255),
448 Stop::Software, 503 Stop::Software,
449 (total_chunks != 1) || !last_slice, 504 (total_chunks != 1) || !last_slice,
450 ); 505 &check_timeout,
506 )?;
451 } 507 }
452 } else { 508 } else {
453 unsafe { 509 unsafe {
454 Self::master_continue(total_len.min(255), (total_chunks != 1) || !last_slice); 510 Self::master_continue(total_len.min(255), (total_chunks != 1) || !last_slice, &check_timeout)?;
455 T::regs().cr1().modify(|w| w.set_tcie(true)); 511 T::regs().cr1().modify(|w| w.set_tcie(true));
456 } 512 }
457 } 513 }
@@ -461,32 +517,40 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
461 let chunks_transferred = state.chunks_transferred.load(Ordering::Relaxed); 517 let chunks_transferred = state.chunks_transferred.load(Ordering::Relaxed);
462 518
463 if chunks_transferred == total_chunks { 519 if chunks_transferred == total_chunks {
464 return Poll::Ready(()); 520 return Poll::Ready(Ok(()));
465 } else if chunks_transferred != 0 { 521 } else if chunks_transferred != 0 {
466 remaining_len = remaining_len.saturating_sub(255); 522 remaining_len = remaining_len.saturating_sub(255);
467 let last_piece = (chunks_transferred + 1 == total_chunks) && last_slice; 523 let last_piece = (chunks_transferred + 1 == total_chunks) && last_slice;
468 524
469 // NOTE(unsafe) self.tx_dma does not fiddle with the i2c registers 525 // NOTE(unsafe) self.tx_dma does not fiddle with the i2c registers
470 unsafe { 526 unsafe {
471 Self::master_continue(remaining_len.min(255), !last_piece); 527 if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) {
528 return Poll::Ready(Err(e));
529 }
472 T::regs().cr1().modify(|w| w.set_tcie(true)); 530 T::regs().cr1().modify(|w| w.set_tcie(true));
473 } 531 }
474 } 532 }
475 Poll::Pending 533 Poll::Pending
476 }) 534 })
477 .await; 535 .await?;
478 536
479 dma_transfer.await; 537 dma_transfer.await;
480 538
481 if last_slice { 539 if last_slice {
482 // This should be done already 540 // This should be done already
483 self.wait_tc()?; 541 self.wait_tc(&check_timeout)?;
484 self.master_stop(); 542 self.master_stop();
485 } 543 }
486 Ok(()) 544 Ok(())
487 } 545 }
488 546
489 async fn read_dma_internal(&mut self, address: u8, buffer: &mut [u8], restart: bool) -> Result<(), Error> 547 async fn read_dma_internal(
548 &mut self,
549 address: u8,
550 buffer: &mut [u8],
551 restart: bool,
552 check_timeout: impl Fn() -> Result<(), Error>,
553 ) -> Result<(), Error>
490 where 554 where
491 RXDMA: crate::i2c::RxDma<T>, 555 RXDMA: crate::i2c::RxDma<T>,
492 { 556 {
@@ -527,7 +591,14 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
527 591
528 // NOTE(unsafe) self.rx_dma does not fiddle with the i2c registers 592 // NOTE(unsafe) self.rx_dma does not fiddle with the i2c registers
529 unsafe { 593 unsafe {
530 Self::master_read(address, total_len.min(255), Stop::Software, total_chunks != 1, restart); 594 Self::master_read(
595 address,
596 total_len.min(255),
597 Stop::Software,
598 total_chunks != 1,
599 restart,
600 &check_timeout,
601 )?;
531 } 602 }
532 603
533 poll_fn(|cx| { 604 poll_fn(|cx| {
@@ -535,25 +606,27 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
535 let chunks_transferred = state.chunks_transferred.load(Ordering::Relaxed); 606 let chunks_transferred = state.chunks_transferred.load(Ordering::Relaxed);
536 607
537 if chunks_transferred == total_chunks { 608 if chunks_transferred == total_chunks {
538 return Poll::Ready(()); 609 return Poll::Ready(Ok(()));
539 } else if chunks_transferred != 0 { 610 } else if chunks_transferred != 0 {
540 remaining_len = remaining_len.saturating_sub(255); 611 remaining_len = remaining_len.saturating_sub(255);
541 let last_piece = chunks_transferred + 1 == total_chunks; 612 let last_piece = chunks_transferred + 1 == total_chunks;
542 613
543 // NOTE(unsafe) self.rx_dma does not fiddle with the i2c registers 614 // NOTE(unsafe) self.rx_dma does not fiddle with the i2c registers
544 unsafe { 615 unsafe {
545 Self::master_continue(remaining_len.min(255), !last_piece); 616 if let Err(e) = Self::master_continue(remaining_len.min(255), !last_piece, &check_timeout) {
617 return Poll::Ready(Err(e));
618 }
546 T::regs().cr1().modify(|w| w.set_tcie(true)); 619 T::regs().cr1().modify(|w| w.set_tcie(true));
547 } 620 }
548 } 621 }
549 Poll::Pending 622 Poll::Pending
550 }) 623 })
551 .await; 624 .await?;
552 625
553 dma_transfer.await; 626 dma_transfer.await;
554 627
555 // This should be done already 628 // This should be done already
556 self.wait_tc()?; 629 self.wait_tc(&check_timeout)?;
557 self.master_stop(); 630 self.master_stop();
558 Ok(()) 631 Ok(())
559 } 632 }
@@ -566,9 +639,9 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
566 TXDMA: crate::i2c::TxDma<T>, 639 TXDMA: crate::i2c::TxDma<T>,
567 { 640 {
568 if bytes.is_empty() { 641 if bytes.is_empty() {
569 self.write_internal(address, bytes, true) 642 self.write_internal(address, bytes, true, || Ok(()))
570 } else { 643 } else {
571 self.write_dma_internal(address, bytes, true, true).await 644 self.write_dma_internal(address, bytes, true, true, || Ok(())).await
572 } 645 }
573 } 646 }
574 647
@@ -587,7 +660,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
587 let next = iter.next(); 660 let next = iter.next();
588 let is_last = next.is_none(); 661 let is_last = next.is_none();
589 662
590 self.write_dma_internal(address, c, first, is_last).await?; 663 self.write_dma_internal(address, c, first, is_last, || Ok(())).await?;
591 first = false; 664 first = false;
592 current = next; 665 current = next;
593 } 666 }
@@ -599,9 +672,9 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
599 RXDMA: crate::i2c::RxDma<T>, 672 RXDMA: crate::i2c::RxDma<T>,
600 { 673 {
601 if buffer.is_empty() { 674 if buffer.is_empty() {
602 self.read_internal(address, buffer, false) 675 self.read_internal(address, buffer, false, || Ok(()))
603 } else { 676 } else {
604 self.read_dma_internal(address, buffer, false).await 677 self.read_dma_internal(address, buffer, false, || Ok(())).await
605 } 678 }
606 } 679 }
607 680
@@ -611,15 +684,15 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
611 RXDMA: super::RxDma<T>, 684 RXDMA: super::RxDma<T>,
612 { 685 {
613 if bytes.is_empty() { 686 if bytes.is_empty() {
614 self.write_internal(address, bytes, false)?; 687 self.write_internal(address, bytes, false, || Ok(()))?;
615 } else { 688 } else {
616 self.write_dma_internal(address, bytes, true, true).await?; 689 self.write_dma_internal(address, bytes, true, true, || Ok(())).await?;
617 } 690 }
618 691
619 if buffer.is_empty() { 692 if buffer.is_empty() {
620 self.read_internal(address, buffer, true)?; 693 self.read_internal(address, buffer, true, || Ok(()))?;
621 } else { 694 } else {
622 self.read_dma_internal(address, buffer, true).await?; 695 self.read_dma_internal(address, buffer, true, || Ok(())).await?;
623 } 696 }
624 697
625 Ok(()) 698 Ok(())
@@ -628,22 +701,55 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
628 // ========================= 701 // =========================
629 // Blocking public API 702 // Blocking public API
630 703
631 pub fn blocking_read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> { 704 pub fn blocking_read_timeout(
632 self.read_internal(address, buffer, false) 705 &mut self,
706 address: u8,
707 buffer: &mut [u8],
708 check_timeout: impl Fn() -> Result<(), Error>,
709 ) -> Result<(), Error> {
710 self.read_internal(address, buffer, false, &check_timeout)
633 // Automatic Stop 711 // Automatic Stop
634 } 712 }
635 713
714 pub fn blocking_read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> {
715 self.blocking_read_timeout(address, buffer, || Ok(()))
716 }
717
718 pub fn blocking_write_timeout(
719 &mut self,
720 address: u8,
721 bytes: &[u8],
722 check_timeout: impl Fn() -> Result<(), Error>,
723 ) -> Result<(), Error> {
724 self.write_internal(address, bytes, true, &check_timeout)
725 }
726
636 pub fn blocking_write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Error> { 727 pub fn blocking_write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Error> {
637 self.write_internal(address, bytes, true) 728 self.blocking_write_timeout(address, bytes, || Ok(()))
638 } 729 }
639 730
640 pub fn blocking_write_read(&mut self, address: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> { 731 pub fn blocking_write_read_timeout(
641 self.write_internal(address, bytes, false)?; 732 &mut self,
642 self.read_internal(address, buffer, true) 733 address: u8,
734 bytes: &[u8],
735 buffer: &mut [u8],
736 check_timeout: impl Fn() -> Result<(), Error>,
737 ) -> Result<(), Error> {
738 self.write_internal(address, bytes, false, &check_timeout)?;
739 self.read_internal(address, buffer, true, &check_timeout)
643 // Automatic Stop 740 // Automatic Stop
644 } 741 }
645 742
646 pub fn blocking_write_vectored(&mut self, address: u8, bytes: &[&[u8]]) -> Result<(), Error> { 743 pub fn blocking_write_read(&mut self, address: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> {
744 self.blocking_write_read_timeout(address, bytes, buffer, || Ok(()))
745 }
746
747 pub fn blocking_write_vectored_timeout(
748 &mut self,
749 address: u8,
750 bytes: &[&[u8]],
751 check_timeout: impl Fn() -> Result<(), Error>,
752 ) -> Result<(), Error> {
647 if bytes.is_empty() { 753 if bytes.is_empty() {
648 return Err(Error::ZeroLengthTransfer); 754 return Err(Error::ZeroLengthTransfer);
649 } 755 }
@@ -657,7 +763,8 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
657 first_length.min(255), 763 first_length.min(255),
658 Stop::Software, 764 Stop::Software,
659 (first_length > 255) || (last_slice_index != 0), 765 (first_length > 255) || (last_slice_index != 0),
660 ); 766 &check_timeout,
767 )?;
661 } 768 }
662 769
663 for (idx, slice) in bytes.iter().enumerate() { 770 for (idx, slice) in bytes.iter().enumerate() {
@@ -673,7 +780,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
673 if idx != 0 { 780 if idx != 0 {
674 // NOTE(unsafe) We have &mut self 781 // NOTE(unsafe) We have &mut self
675 unsafe { 782 unsafe {
676 Self::master_continue(slice_len.min(255), (idx != last_slice_index) || (slice_len > 255)); 783 Self::master_continue(
784 slice_len.min(255),
785 (idx != last_slice_index) || (slice_len > 255),
786 &check_timeout,
787 )?;
677 } 788 }
678 } 789 }
679 790
@@ -681,7 +792,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
681 if number != 0 { 792 if number != 0 {
682 // NOTE(unsafe) We have &mut self 793 // NOTE(unsafe) We have &mut self
683 unsafe { 794 unsafe {
684 Self::master_continue(chunk.len(), (number != last_chunk_idx) || (idx != last_slice_index)); 795 Self::master_continue(
796 chunk.len(),
797 (number != last_chunk_idx) || (idx != last_slice_index),
798 &check_timeout,
799 )?;
685 } 800 }
686 } 801 }
687 802
@@ -689,7 +804,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
689 // Wait until we are allowed to send data 804 // Wait until we are allowed to send data
690 // (START has been ACKed or last byte when 805 // (START has been ACKed or last byte when
691 // through) 806 // through)
692 self.wait_txe()?; 807 self.wait_txe(&check_timeout)?;
693 808
694 // Put byte on the wire 809 // Put byte on the wire
695 //self.i2c.txdr.write(|w| w.txdata().bits(*byte)); 810 //self.i2c.txdr.write(|w| w.txdata().bits(*byte));
@@ -700,11 +815,15 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
700 } 815 }
701 } 816 }
702 // Wait until the write finishes 817 // Wait until the write finishes
703 self.wait_tc()?; 818 self.wait_tc(&check_timeout)?;
704 self.master_stop(); 819 self.master_stop();
705 820
706 Ok(()) 821 Ok(())
707 } 822 }
823
824 pub fn blocking_write_vectored(&mut self, address: u8, bytes: &[&[u8]]) -> Result<(), Error> {
825 self.blocking_write_vectored_timeout(address, bytes, || Ok(()))
826 }
708} 827}
709 828
710mod eh02 { 829mod eh02 {
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 0392e8086..bcf2feee8 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -52,7 +52,7 @@ pub mod sdmmc;
52pub mod spi; 52pub mod spi;
53#[cfg(usart)] 53#[cfg(usart)]
54pub mod usart; 54pub mod usart;
55#[cfg(usb)] 55#[cfg(all(usb, feature = "time"))]
56pub mod usb; 56pub mod usb;
57#[cfg(any(otgfs, otghs))] 57#[cfg(any(otgfs, otghs))]
58pub mod usb_otg; 58pub mod usb_otg;
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index a8bc6385f..c91f3c8bf 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -1534,14 +1534,14 @@ mod sdmmc_rs {
1534 1534
1535 impl<'d, T: Instance, P: Pins<T>> BlockDevice for Sdmmc<'d, T, P> { 1535 impl<'d, T: Instance, P: Pins<T>> BlockDevice for Sdmmc<'d, T, P> {
1536 type Error = Error; 1536 type Error = Error;
1537 type ReadFuture<'a> 1537
1538 type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a
1538 where 1539 where
1539 Self: 'a, 1540 Self: 'a;
1540 = impl Future<Output = Result<(), Self::Error>> + 'a; 1541
1541 type WriteFuture<'a> 1542 type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a
1542 where 1543 where
1543 Self: 'a, 1544 Self: 'a;
1544 = impl Future<Output = Result<(), Self::Error>> + 'a;
1545 1545
1546 fn read<'a>( 1546 fn read<'a>(
1547 &'a mut self, 1547 &'a mut self,
diff --git a/embassy-stm32/src/subghz/timeout.rs b/embassy-stm32/src/subghz/timeout.rs
index 28b3b0c21..0ae49dd90 100644
--- a/embassy-stm32/src/subghz/timeout.rs
+++ b/embassy-stm32/src/subghz/timeout.rs
@@ -439,6 +439,7 @@ impl From<Timeout> for [u8; 3] {
439 } 439 }
440} 440}
441 441
442#[cfg(feature = "time")]
442impl From<Timeout> for embassy_time::Duration { 443impl From<Timeout> for embassy_time::Duration {
443 fn from(to: Timeout) -> Self { 444 fn from(to: Timeout) -> Self {
444 embassy_time::Duration::from_micros(to.as_micros().into()) 445 embassy_time::Duration::from_micros(to.as_micros().into())
diff --git a/embassy-stm32/src/subghz/tx_params.rs b/embassy-stm32/src/subghz/tx_params.rs
index cede6f2c1..03bdb1ea8 100644
--- a/embassy-stm32/src/subghz/tx_params.rs
+++ b/embassy-stm32/src/subghz/tx_params.rs
@@ -44,6 +44,7 @@ impl From<RampTime> for core::time::Duration {
44 } 44 }
45} 45}
46 46
47#[cfg(feature = "time")]
47impl From<RampTime> for embassy_time::Duration { 48impl From<RampTime> for embassy_time::Duration {
48 fn from(rt: RampTime) -> Self { 49 fn from(rt: RampTime) -> Self {
49 match rt { 50 match rt {
diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs
index ed3225c51..8e84570a4 100644
--- a/embassy-stm32/src/time_driver.rs
+++ b/embassy-stm32/src/time_driver.rs
@@ -292,19 +292,23 @@ impl Driver for RtcDriver {
292 }) 292 })
293 } 293 }
294 294
295 fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) { 295 fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) -> bool {
296 critical_section::with(|cs| { 296 critical_section::with(|cs| {
297 let r = T::regs_gp16(); 297 let r = T::regs_gp16();
298 298
299 let n = alarm.id() as _; 299 let n = alarm.id() as usize;
300 let alarm = self.get_alarm(cs, alarm); 300 let alarm = self.get_alarm(cs, alarm);
301 alarm.timestamp.set(timestamp); 301 alarm.timestamp.set(timestamp);
302 302
303 let t = self.now(); 303 let t = self.now();
304 if timestamp <= t { 304 if timestamp <= t {
305 // If alarm timestamp has passed the alarm will not fire.
306 // Disarm the alarm and return `false` to indicate that.
305 unsafe { r.dier().modify(|w| w.set_ccie(n + 1, false)) }; 307 unsafe { r.dier().modify(|w| w.set_ccie(n + 1, false)) };
306 self.trigger_alarm(n, cs); 308
307 return; 309 alarm.timestamp.set(u64::MAX);
310
311 return false;
308 } 312 }
309 313
310 let safe_timestamp = timestamp.max(t + 3); 314 let safe_timestamp = timestamp.max(t + 3);
@@ -317,6 +321,8 @@ impl Driver for RtcDriver {
317 let diff = timestamp - t; 321 let diff = timestamp - t;
318 // NOTE(unsafe) We're in a critical section 322 // NOTE(unsafe) We're in a critical section
319 unsafe { r.dier().modify(|w| w.set_ccie(n + 1, diff < 0xc000)) }; 323 unsafe { r.dier().modify(|w| w.set_ccie(n + 1, diff < 0xc000)) };
324
325 true
320 }) 326 })
321 } 327 }
322} 328}
diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs
index 2a711bc06..3be0677bd 100644
--- a/embassy-stm32/src/usart/buffered.rs
+++ b/embassy-stm32/src/usart/buffered.rs
@@ -46,16 +46,44 @@ impl<'d, T: BasicInstance> Unpin for BufferedUart<'d, T> {}
46impl<'d, T: BasicInstance> BufferedUart<'d, T> { 46impl<'d, T: BasicInstance> BufferedUart<'d, T> {
47 pub fn new( 47 pub fn new(
48 state: &'d mut State<'d, T>, 48 state: &'d mut State<'d, T>,
49 _uart: Uart<'d, T, NoDma, NoDma>, 49 _peri: impl Peripheral<P = T> + 'd,
50 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
51 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
50 irq: impl Peripheral<P = T::Interrupt> + 'd, 52 irq: impl Peripheral<P = T::Interrupt> + 'd,
51 tx_buffer: &'d mut [u8], 53 tx_buffer: &'d mut [u8],
52 rx_buffer: &'d mut [u8], 54 rx_buffer: &'d mut [u8],
55 config: Config,
53 ) -> BufferedUart<'d, T> { 56 ) -> BufferedUart<'d, T> {
54 into_ref!(irq); 57 into_ref!(_peri, rx, tx, irq);
58
59 T::enable();
60 T::reset();
55 61
56 let r = T::regs(); 62 let r = T::regs();
63
64 configure(r, &config, T::frequency(), T::MULTIPLIER);
65
57 unsafe { 66 unsafe {
58 r.cr1().modify(|w| { 67 rx.set_as_af(rx.af_num(), AFType::Input);
68 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
69
70 r.cr2().write(|_w| {});
71 r.cr3().write(|_w| {});
72 r.cr1().write(|w| {
73 w.set_ue(true);
74 w.set_te(true);
75 w.set_re(true);
76 w.set_m0(if config.parity != Parity::ParityNone {
77 vals::M0::BIT9
78 } else {
79 vals::M0::BIT8
80 });
81 w.set_pce(config.parity != Parity::ParityNone);
82 w.set_ps(match config.parity {
83 Parity::ParityOdd => vals::Ps::ODD,
84 Parity::ParityEven => vals::Ps::EVEN,
85 _ => vals::Ps::EVEN,
86 });
59 w.set_rxneie(true); 87 w.set_rxneie(true);
60 w.set_idleie(true); 88 w.set_idleie(true);
61 }); 89 });
@@ -283,7 +311,7 @@ impl<'u, 'd, T: BasicInstance> embedded_io::Io for BufferedUartTx<'u, 'd, T> {
283} 311}
284 312
285impl<'d, T: BasicInstance> embedded_io::asynch::Read for BufferedUart<'d, T> { 313impl<'d, T: BasicInstance> embedded_io::asynch::Read for BufferedUart<'d, T> {
286 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 314 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
287 where 315 where
288 Self: 'a; 316 Self: 'a;
289 317
@@ -293,7 +321,7 @@ impl<'d, T: BasicInstance> embedded_io::asynch::Read for BufferedUart<'d, T> {
293} 321}
294 322
295impl<'u, 'd, T: BasicInstance> embedded_io::asynch::Read for BufferedUartRx<'u, 'd, T> { 323impl<'u, 'd, T: BasicInstance> embedded_io::asynch::Read for BufferedUartRx<'u, 'd, T> {
296 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 324 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
297 where 325 where
298 Self: 'a; 326 Self: 'a;
299 327
@@ -303,7 +331,7 @@ impl<'u, 'd, T: BasicInstance> embedded_io::asynch::Read for BufferedUartRx<'u,
303} 331}
304 332
305impl<'d, T: BasicInstance> embedded_io::asynch::BufRead for BufferedUart<'d, T> { 333impl<'d, T: BasicInstance> embedded_io::asynch::BufRead for BufferedUart<'d, T> {
306 type FillBufFuture<'a> = impl Future<Output = Result<&'a [u8], Self::Error>> 334 type FillBufFuture<'a> = impl Future<Output = Result<&'a [u8], Self::Error>> + 'a
307 where 335 where
308 Self: 'a; 336 Self: 'a;
309 337
@@ -317,7 +345,7 @@ impl<'d, T: BasicInstance> embedded_io::asynch::BufRead for BufferedUart<'d, T>
317} 345}
318 346
319impl<'u, 'd, T: BasicInstance> embedded_io::asynch::BufRead for BufferedUartRx<'u, 'd, T> { 347impl<'u, 'd, T: BasicInstance> embedded_io::asynch::BufRead for BufferedUartRx<'u, 'd, T> {
320 type FillBufFuture<'a> = impl Future<Output = Result<&'a [u8], Self::Error>> 348 type FillBufFuture<'a> = impl Future<Output = Result<&'a [u8], Self::Error>> + 'a
321 where 349 where
322 Self: 'a; 350 Self: 'a;
323 351
@@ -331,7 +359,7 @@ impl<'u, 'd, T: BasicInstance> embedded_io::asynch::BufRead for BufferedUartRx<'
331} 359}
332 360
333impl<'d, T: BasicInstance> embedded_io::asynch::Write for BufferedUart<'d, T> { 361impl<'d, T: BasicInstance> embedded_io::asynch::Write for BufferedUart<'d, T> {
334 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 362 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
335 where 363 where
336 Self: 'a; 364 Self: 'a;
337 365
@@ -339,7 +367,7 @@ impl<'d, T: BasicInstance> embedded_io::asynch::Write for BufferedUart<'d, T> {
339 self.inner_write(buf) 367 self.inner_write(buf)
340 } 368 }
341 369
342 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> 370 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a
343 where 371 where
344 Self: 'a; 372 Self: 'a;
345 373
@@ -349,7 +377,7 @@ impl<'d, T: BasicInstance> embedded_io::asynch::Write for BufferedUart<'d, T> {
349} 377}
350 378
351impl<'u, 'd, T: BasicInstance> embedded_io::asynch::Write for BufferedUartTx<'u, 'd, T> { 379impl<'u, 'd, T: BasicInstance> embedded_io::asynch::Write for BufferedUartTx<'u, 'd, T> {
352 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 380 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
353 where 381 where
354 Self: 'a; 382 Self: 'a;
355 383
@@ -357,7 +385,7 @@ impl<'u, 'd, T: BasicInstance> embedded_io::asynch::Write for BufferedUartTx<'u,
357 self.inner.inner_write(buf) 385 self.inner.inner_write(buf)
358 } 386 }
359 387
360 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> 388 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a
361 where 389 where
362 Self: 'a; 390 Self: 'a;
363 391
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index a152a0c15..dee466b21 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -1,7 +1,11 @@
1#![macro_use] 1#![macro_use]
2 2
3use core::future::poll_fn;
3use core::marker::PhantomData; 4use core::marker::PhantomData;
5use core::task::Poll;
4 6
7use atomic_polyfill::{compiler_fence, Ordering};
8use embassy_cortex_m::interrupt::InterruptExt;
5use embassy_hal_common::{into_ref, PeripheralRef}; 9use embassy_hal_common::{into_ref, PeripheralRef};
6 10
7use crate::dma::NoDma; 11use crate::dma::NoDma;
@@ -10,6 +14,7 @@ use crate::gpio::sealed::AFType;
10use crate::pac::lpuart::{regs, vals, Lpuart as Regs}; 14use crate::pac::lpuart::{regs, vals, Lpuart as Regs};
11#[cfg(not(any(lpuart_v1, lpuart_v2)))] 15#[cfg(not(any(lpuart_v1, lpuart_v2)))]
12use crate::pac::usart::{regs, vals, Usart as Regs}; 16use crate::pac::usart::{regs, vals, Usart as Regs};
17use crate::time::Hertz;
13use crate::{peripherals, Peripheral}; 18use crate::{peripherals, Peripheral};
14 19
15#[derive(Clone, Copy, PartialEq, Eq, Debug)] 20#[derive(Clone, Copy, PartialEq, Eq, Debug)]
@@ -44,6 +49,10 @@ pub struct Config {
44 pub data_bits: DataBits, 49 pub data_bits: DataBits,
45 pub stop_bits: StopBits, 50 pub stop_bits: StopBits,
46 pub parity: Parity, 51 pub parity: Parity,
52 /// if true, on read-like method, if there is a latent error pending,
53 /// read will abort, the error reported and cleared
54 /// if false, the error is ignored and cleared
55 pub detect_previous_overrun: bool,
47} 56}
48 57
49impl Default for Config { 58impl Default for Config {
@@ -53,6 +62,8 @@ impl Default for Config {
53 data_bits: DataBits::DataBits8, 62 data_bits: DataBits::DataBits8,
54 stop_bits: StopBits::STOP1, 63 stop_bits: StopBits::STOP1,
55 parity: Parity::ParityNone, 64 parity: Parity::ParityNone,
65 // historical behavior
66 detect_previous_overrun: false,
56 } 67 }
57 } 68 }
58} 69}
@@ -70,10 +81,11 @@ pub enum Error {
70 Overrun, 81 Overrun,
71 /// Parity check error 82 /// Parity check error
72 Parity, 83 Parity,
84 /// Buffer too large for DMA
85 BufferTooLong,
73} 86}
74 87
75pub struct Uart<'d, T: BasicInstance, TxDma = NoDma, RxDma = NoDma> { 88pub struct Uart<'d, T: BasicInstance, TxDma = NoDma, RxDma = NoDma> {
76 phantom: PhantomData<&'d mut T>,
77 tx: UartTx<'d, T, TxDma>, 89 tx: UartTx<'d, T, TxDma>,
78 rx: UartRx<'d, T, RxDma>, 90 rx: UartRx<'d, T, RxDma>,
79} 91}
@@ -84,8 +96,9 @@ pub struct UartTx<'d, T: BasicInstance, TxDma = NoDma> {
84} 96}
85 97
86pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> { 98pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> {
87 phantom: PhantomData<&'d mut T>, 99 _peri: PeripheralRef<'d, T>,
88 rx_dma: PeripheralRef<'d, RxDma>, 100 rx_dma: PeripheralRef<'d, RxDma>,
101 detect_previous_overrun: bool,
89} 102}
90 103
91impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { 104impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
@@ -135,10 +148,112 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
135} 148}
136 149
137impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { 150impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
138 fn new(rx_dma: PeripheralRef<'d, RxDma>) -> Self { 151 /// usefull if you only want Uart Rx. It saves 1 pin and consumes a little less power
152 pub fn new(
153 peri: impl Peripheral<P = T> + 'd,
154 irq: impl Peripheral<P = T::Interrupt> + 'd,
155 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
156 rx_dma: impl Peripheral<P = RxDma> + 'd,
157 config: Config,
158 ) -> Self {
159 into_ref!(peri, irq, rx, rx_dma);
160
161 T::enable();
162 T::reset();
163
164 let r = T::regs();
165
166 configure(r, &config, T::frequency(), T::MULTIPLIER);
167
168 unsafe {
169 rx.set_as_af(rx.af_num(), AFType::Input);
170
171 r.cr2().write(|_w| {});
172 r.cr3().write(|w| {
173 // enable Error Interrupt: (Frame error, Noise error, Overrun error)
174 w.set_eie(true);
175 });
176 r.cr1().write(|w| {
177 // enable uart
178 w.set_ue(true);
179 // enable receiver
180 w.set_re(true);
181 // configure word size
182 w.set_m0(if config.parity != Parity::ParityNone {
183 vals::M0::BIT9
184 } else {
185 vals::M0::BIT8
186 });
187 // configure parity
188 w.set_pce(config.parity != Parity::ParityNone);
189 w.set_ps(match config.parity {
190 Parity::ParityOdd => vals::Ps::ODD,
191 Parity::ParityEven => vals::Ps::EVEN,
192 _ => vals::Ps::EVEN,
193 });
194 });
195 }
196
197 irq.set_handler(Self::on_interrupt);
198 irq.unpend();
199 irq.enable();
200
201 // create state once!
202 let _s = T::state();
203
139 Self { 204 Self {
205 _peri: peri,
140 rx_dma, 206 rx_dma,
141 phantom: PhantomData, 207 detect_previous_overrun: config.detect_previous_overrun,
208 }
209 }
210
211 fn on_interrupt(_: *mut ()) {
212 let r = T::regs();
213 let s = T::state();
214
215 let (sr, cr1, cr3) = unsafe { (sr(r).read(), r.cr1().read(), r.cr3().read()) };
216
217 let has_errors = (sr.pe() && cr1.peie()) || ((sr.fe() || sr.ne() || sr.ore()) && cr3.eie());
218
219 if has_errors {
220 // clear all interrupts and DMA Rx Request
221 unsafe {
222 r.cr1().modify(|w| {
223 // disable RXNE interrupt
224 w.set_rxneie(false);
225 // disable parity interrupt
226 w.set_peie(false);
227 // disable idle line interrupt
228 w.set_idleie(false);
229 });
230 r.cr3().modify(|w| {
231 // disable Error Interrupt: (Frame error, Noise error, Overrun error)
232 w.set_eie(false);
233 // disable DMA Rx Request
234 w.set_dmar(false);
235 });
236 }
237
238 compiler_fence(Ordering::SeqCst);
239
240 s.rx_waker.wake();
241 } else if cr1.idleie() && sr.idle() {
242 // IDLE detected: no more data will come
243 unsafe {
244 r.cr1().modify(|w| {
245 // disable idle line detection
246 w.set_idleie(false);
247 });
248
249 r.cr3().modify(|w| {
250 // disable DMA Rx Request
251 w.set_dmar(false);
252 });
253 }
254 compiler_fence(Ordering::SeqCst);
255
256 s.rx_waker.wake();
142 } 257 }
143 } 258 }
144 259
@@ -146,17 +261,8 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
146 where 261 where
147 RxDma: crate::usart::RxDma<T>, 262 RxDma: crate::usart::RxDma<T>,
148 { 263 {
149 let ch = &mut self.rx_dma; 264 self.inner_read(buffer, false).await?;
150 let request = ch.request(); 265
151 unsafe {
152 T::regs().cr3().modify(|reg| {
153 reg.set_dmar(true);
154 });
155 }
156 // If we don't assign future to a variable, the data register pointer
157 // is held across an await and makes the future non-Send.
158 let transfer = crate::dma::read(ch, request, rdr(T::regs()), buffer);
159 transfer.await;
160 Ok(()) 266 Ok(())
161 } 267 }
162 268
@@ -211,35 +317,259 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
211 } 317 }
212 Ok(()) 318 Ok(())
213 } 319 }
320
321 pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error>
322 where
323 RxDma: crate::usart::RxDma<T>,
324 {
325 self.inner_read(buffer, true).await
326 }
327
328 async fn inner_read(&mut self, buffer: &mut [u8], enable_idle_line_detection: bool) -> Result<usize, Error>
329 where
330 RxDma: crate::usart::RxDma<T>,
331 {
332 if buffer.is_empty() {
333 return Ok(0);
334 } else if buffer.len() > 0xFFFF {
335 return Err(Error::BufferTooLong);
336 }
337
338 let r = T::regs();
339
340 let buffer_len = buffer.len();
341
342 let ch = &mut self.rx_dma;
343 let request = ch.request();
344
345 // SAFETY: The only way we might have a problem is using split rx and tx
346 // here we only modify or read Rx related flags, interrupts and DMA channel
347 unsafe {
348 // Start USART DMA
349 // will not do anything yet because DMAR is not yet set
350 ch.start_read(request, rdr(r), buffer, Default::default());
351
352 // clear ORE flag just before enabling DMA Rx Request: can be mandatory for the second transfer
353 if !self.detect_previous_overrun {
354 let sr = sr(r).read();
355 // This read also clears the error and idle interrupt flags on v1.
356 rdr(r).read_volatile();
357 clear_interrupt_flags(r, sr);
358 }
359
360 r.cr1().modify(|w| {
361 // disable RXNE interrupt
362 w.set_rxneie(false);
363 // enable parity interrupt if not ParityNone
364 w.set_peie(w.pce());
365 });
366
367 r.cr3().modify(|w| {
368 // enable Error Interrupt: (Frame error, Noise error, Overrun error)
369 w.set_eie(true);
370 // enable DMA Rx Request
371 w.set_dmar(true);
372 });
373
374 compiler_fence(Ordering::SeqCst);
375
376 // In case of errors already pending when reception started, interrupts may have already been raised
377 // and lead to reception abortion (Overrun error for instance). In such a case, all interrupts
378 // have been disabled in interrupt handler and DMA Rx Request has been disabled.
379
380 let cr3 = r.cr3().read();
381
382 if !cr3.dmar() {
383 // something went wrong
384 // because the only way to get this flag cleared is to have an interrupt
385
386 // abort DMA transfer
387 ch.request_stop();
388 while ch.is_running() {}
389
390 let sr = sr(r).read();
391 // This read also clears the error and idle interrupt flags on v1.
392 rdr(r).read_volatile();
393 clear_interrupt_flags(r, sr);
394
395 if sr.pe() {
396 return Err(Error::Parity);
397 }
398 if sr.fe() {
399 return Err(Error::Framing);
400 }
401 if sr.ne() {
402 return Err(Error::Noise);
403 }
404 if sr.ore() {
405 return Err(Error::Overrun);
406 }
407
408 unreachable!();
409 }
410
411 // clear idle flag
412 if enable_idle_line_detection {
413 let sr = sr(r).read();
414 // This read also clears the error and idle interrupt flags on v1.
415 rdr(r).read_volatile();
416 clear_interrupt_flags(r, sr);
417
418 // enable idle interrupt
419 r.cr1().modify(|w| {
420 w.set_idleie(true);
421 });
422 }
423 }
424
425 compiler_fence(Ordering::SeqCst);
426
427 let res = poll_fn(move |cx| {
428 let s = T::state();
429
430 ch.set_waker(cx.waker());
431 s.rx_waker.register(cx.waker());
432
433 // SAFETY: read only and we only use Rx related flags
434 let sr = unsafe { sr(r).read() };
435
436 // SAFETY: only clears Rx related flags
437 unsafe {
438 // This read also clears the error and idle interrupt flags on v1.
439 rdr(r).read_volatile();
440 clear_interrupt_flags(r, sr);
441 }
442
443 compiler_fence(Ordering::SeqCst);
444
445 let has_errors = sr.pe() || sr.fe() || sr.ne() || sr.ore();
446
447 if has_errors {
448 // all Rx interrupts and Rx DMA Request have already been cleared in interrupt handler
449
450 // stop dma transfer
451 ch.request_stop();
452 while ch.is_running() {}
453
454 if sr.pe() {
455 return Poll::Ready(Err(Error::Parity));
456 }
457 if sr.fe() {
458 return Poll::Ready(Err(Error::Framing));
459 }
460 if sr.ne() {
461 return Poll::Ready(Err(Error::Noise));
462 }
463 if sr.ore() {
464 return Poll::Ready(Err(Error::Overrun));
465 }
466 }
467
468 if sr.idle() {
469 // Idle line
470
471 // stop dma transfer
472 ch.request_stop();
473 while ch.is_running() {}
474
475 let n = buffer_len - (ch.remaining_transfers() as usize);
476
477 return Poll::Ready(Ok(n));
478 } else if !ch.is_running() {
479 // DMA complete
480 return Poll::Ready(Ok(buffer_len));
481 }
482
483 Poll::Pending
484 })
485 .await;
486
487 // clear all interrupts and DMA Rx Request
488 // SAFETY: only clears Rx related flags
489 unsafe {
490 r.cr1().modify(|w| {
491 // disable RXNE interrupt
492 w.set_rxneie(false);
493 // disable parity interrupt
494 w.set_peie(false);
495 // disable idle line interrupt
496 w.set_idleie(false);
497 });
498 r.cr3().modify(|w| {
499 // disable Error Interrupt: (Frame error, Noise error, Overrun error)
500 w.set_eie(false);
501 // disable DMA Rx Request
502 w.set_dmar(false);
503 });
504 }
505
506 res
507 }
214} 508}
215 509
216impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { 510impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
217 pub fn new( 511 pub fn new(
218 _inner: impl Peripheral<P = T> + 'd, 512 peri: impl Peripheral<P = T> + 'd,
219 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 513 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
220 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 514 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
515 irq: impl Peripheral<P = T::Interrupt> + 'd,
221 tx_dma: impl Peripheral<P = TxDma> + 'd, 516 tx_dma: impl Peripheral<P = TxDma> + 'd,
222 rx_dma: impl Peripheral<P = RxDma> + 'd, 517 rx_dma: impl Peripheral<P = RxDma> + 'd,
223 config: Config, 518 config: Config,
224 ) -> Self { 519 ) -> Self {
225 into_ref!(_inner, rx, tx, tx_dma, rx_dma); 520 T::enable();
521 T::reset();
522
523 Self::new_inner(peri, rx, tx, irq, tx_dma, rx_dma, config)
524 }
525
526 pub fn new_with_rtscts(
527 peri: impl Peripheral<P = T> + 'd,
528 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
529 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
530 irq: impl Peripheral<P = T::Interrupt> + 'd,
531 rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
532 cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
533 tx_dma: impl Peripheral<P = TxDma> + 'd,
534 rx_dma: impl Peripheral<P = RxDma> + 'd,
535 config: Config,
536 ) -> Self {
537 into_ref!(cts, rts);
226 538
227 T::enable(); 539 T::enable();
228 T::reset(); 540 T::reset();
229 let pclk_freq = T::frequency();
230 541
231 // TODO: better calculation, including error checking and OVER8 if possible. 542 unsafe {
232 let div = (pclk_freq.0 + (config.baudrate / 2)) / config.baudrate * T::MULTIPLIER; 543 rts.set_as_af(rts.af_num(), AFType::OutputPushPull);
544 cts.set_as_af(cts.af_num(), AFType::Input);
545 T::regs().cr3().write(|w| {
546 w.set_rtse(true);
547 w.set_ctse(true);
548 });
549 }
550 Self::new_inner(peri, rx, tx, irq, tx_dma, rx_dma, config)
551 }
552
553 fn new_inner(
554 peri: impl Peripheral<P = T> + 'd,
555 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
556 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
557 irq: impl Peripheral<P = T::Interrupt> + 'd,
558 tx_dma: impl Peripheral<P = TxDma> + 'd,
559 rx_dma: impl Peripheral<P = RxDma> + 'd,
560 config: Config,
561 ) -> Self {
562 into_ref!(peri, rx, tx, irq, tx_dma, rx_dma);
233 563
234 let r = T::regs(); 564 let r = T::regs();
235 565
566 configure(r, &config, T::frequency(), T::MULTIPLIER);
567
236 unsafe { 568 unsafe {
237 rx.set_as_af(rx.af_num(), AFType::Input); 569 rx.set_as_af(rx.af_num(), AFType::Input);
238 tx.set_as_af(tx.af_num(), AFType::OutputPushPull); 570 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
239 571
240 r.cr2().write(|_w| {}); 572 r.cr2().write(|_w| {});
241 r.cr3().write(|_w| {});
242 r.brr().write_value(regs::Brr(div));
243 r.cr1().write(|w| { 573 r.cr1().write(|w| {
244 w.set_ue(true); 574 w.set_ue(true);
245 w.set_te(true); 575 w.set_te(true);
@@ -258,10 +588,20 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
258 }); 588 });
259 } 589 }
260 590
591 irq.set_handler(UartRx::<T, RxDma>::on_interrupt);
592 irq.unpend();
593 irq.enable();
594
595 // create state once!
596 let _s = T::state();
597
261 Self { 598 Self {
262 tx: UartTx::new(tx_dma), 599 tx: UartTx::new(tx_dma),
263 rx: UartRx::new(rx_dma), 600 rx: UartRx {
264 phantom: PhantomData {}, 601 _peri: peri,
602 rx_dma,
603 detect_previous_overrun: config.detect_previous_overrun,
604 },
265 } 605 }
266 } 606 }
267 607
@@ -295,6 +635,13 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
295 self.rx.blocking_read(buffer) 635 self.rx.blocking_read(buffer)
296 } 636 }
297 637
638 pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error>
639 where
640 RxDma: crate::usart::RxDma<T>,
641 {
642 self.rx.read_until_idle(buffer).await
643 }
644
298 /// Split the Uart into a transmitter and receiver, which is 645 /// Split the Uart into a transmitter and receiver, which is
299 /// particuarly useful when having two tasks correlating to 646 /// particuarly useful when having two tasks correlating to
300 /// transmitting and receiving. 647 /// transmitting and receiving.
@@ -303,6 +650,15 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
303 } 650 }
304} 651}
305 652
653fn configure(r: Regs, config: &Config, pclk_freq: Hertz, multiplier: u32) {
654 // TODO: better calculation, including error checking and OVER8 if possible.
655 let div = (pclk_freq.0 + (config.baudrate / 2)) / config.baudrate * multiplier;
656
657 unsafe {
658 r.brr().write_value(regs::Brr(div));
659 }
660}
661
306mod eh02 { 662mod eh02 {
307 use super::*; 663 use super::*;
308 664
@@ -352,6 +708,7 @@ mod eh1 {
352 Self::Noise => embedded_hal_1::serial::ErrorKind::Noise, 708 Self::Noise => embedded_hal_1::serial::ErrorKind::Noise,
353 Self::Overrun => embedded_hal_1::serial::ErrorKind::Overrun, 709 Self::Overrun => embedded_hal_1::serial::ErrorKind::Overrun,
354 Self::Parity => embedded_hal_1::serial::ErrorKind::Parity, 710 Self::Parity => embedded_hal_1::serial::ErrorKind::Parity,
711 Self::BufferTooLong => embedded_hal_1::serial::ErrorKind::Other,
355 } 712 }
356 } 713 }
357 } 714 }
@@ -536,13 +893,30 @@ unsafe fn clear_interrupt_flags(r: Regs, sr: regs::Isr) {
536} 893}
537 894
538pub(crate) mod sealed { 895pub(crate) mod sealed {
896 use embassy_sync::waitqueue::AtomicWaker;
897
539 use super::*; 898 use super::*;
540 899
900 pub struct State {
901 pub rx_waker: AtomicWaker,
902 pub tx_waker: AtomicWaker,
903 }
904
905 impl State {
906 pub const fn new() -> Self {
907 Self {
908 rx_waker: AtomicWaker::new(),
909 tx_waker: AtomicWaker::new(),
910 }
911 }
912 }
913
541 pub trait BasicInstance: crate::rcc::RccPeripheral { 914 pub trait BasicInstance: crate::rcc::RccPeripheral {
542 const MULTIPLIER: u32; 915 const MULTIPLIER: u32;
543 type Interrupt: crate::interrupt::Interrupt; 916 type Interrupt: crate::interrupt::Interrupt;
544 917
545 fn regs() -> Regs; 918 fn regs() -> Regs;
919 fn state() -> &'static State;
546 } 920 }
547 921
548 pub trait FullInstance: BasicInstance { 922 pub trait FullInstance: BasicInstance {
@@ -550,7 +924,7 @@ pub(crate) mod sealed {
550 } 924 }
551} 925}
552 926
553pub trait BasicInstance: sealed::BasicInstance {} 927pub trait BasicInstance: Peripheral<P = Self> + sealed::BasicInstance + 'static + Send {}
554 928
555pub trait FullInstance: sealed::FullInstance {} 929pub trait FullInstance: sealed::FullInstance {}
556 930
@@ -572,6 +946,11 @@ macro_rules! impl_lpuart {
572 fn regs() -> Regs { 946 fn regs() -> Regs {
573 Regs(crate::pac::$inst.0) 947 Regs(crate::pac::$inst.0)
574 } 948 }
949
950 fn state() -> &'static crate::usart::sealed::State {
951 static STATE: crate::usart::sealed::State = crate::usart::sealed::State::new();
952 &STATE
953 }
575 } 954 }
576 955
577 impl BasicInstance for peripherals::$inst {} 956 impl BasicInstance for peripherals::$inst {}
diff --git a/embassy-sync/Cargo.toml b/embassy-sync/Cargo.toml
index 584d5ba9f..b7fe1643c 100644
--- a/embassy-sync/Cargo.toml
+++ b/embassy-sync/Cargo.toml
@@ -19,6 +19,9 @@ src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-sync/
19features = ["nightly"] 19features = ["nightly"]
20target = "thumbv7em-none-eabi" 20target = "thumbv7em-none-eabi"
21 21
22[package.metadata.docs.rs]
23features = ["nightly"]
24
22[features] 25[features]
23nightly = ["embedded-io/async"] 26nightly = ["embedded-io/async"]
24std = [] 27std = []
@@ -32,7 +35,7 @@ atomic-polyfill = "1.0.1"
32critical-section = "1.1" 35critical-section = "1.1"
33heapless = "0.7.5" 36heapless = "0.7.5"
34cfg-if = "1.0.0" 37cfg-if = "1.0.0"
35embedded-io = "0.3.0" 38embedded-io = "0.3.1"
36 39
37[dev-dependencies] 40[dev-dependencies]
38futures-executor = { version = "0.3.17", features = [ "thread-pool" ] } 41futures-executor = { version = "0.3.17", features = [ "thread-pool" ] }
diff --git a/embassy-sync/src/pipe.rs b/embassy-sync/src/pipe.rs
index 7d64b648e..cd577f34f 100644
--- a/embassy-sync/src/pipe.rs
+++ b/embassy-sync/src/pipe.rs
@@ -361,7 +361,7 @@ mod io_impls {
361 } 361 }
362 362
363 impl<M: RawMutex, const N: usize> embedded_io::asynch::Read for Pipe<M, N> { 363 impl<M: RawMutex, const N: usize> embedded_io::asynch::Read for Pipe<M, N> {
364 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 364 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
365 where 365 where
366 Self: 'a; 366 Self: 'a;
367 367
@@ -371,7 +371,7 @@ mod io_impls {
371 } 371 }
372 372
373 impl<M: RawMutex, const N: usize> embedded_io::asynch::Write for Pipe<M, N> { 373 impl<M: RawMutex, const N: usize> embedded_io::asynch::Write for Pipe<M, N> {
374 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 374 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
375 where 375 where
376 Self: 'a; 376 Self: 'a;
377 377
@@ -379,7 +379,7 @@ mod io_impls {
379 Pipe::write(self, buf).map(Ok) 379 Pipe::write(self, buf).map(Ok)
380 } 380 }
381 381
382 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> 382 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a
383 where 383 where
384 Self: 'a; 384 Self: 'a;
385 385
@@ -393,7 +393,7 @@ mod io_impls {
393 } 393 }
394 394
395 impl<M: RawMutex, const N: usize> embedded_io::asynch::Read for &Pipe<M, N> { 395 impl<M: RawMutex, const N: usize> embedded_io::asynch::Read for &Pipe<M, N> {
396 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 396 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
397 where 397 where
398 Self: 'a; 398 Self: 'a;
399 399
@@ -403,7 +403,7 @@ mod io_impls {
403 } 403 }
404 404
405 impl<M: RawMutex, const N: usize> embedded_io::asynch::Write for &Pipe<M, N> { 405 impl<M: RawMutex, const N: usize> embedded_io::asynch::Write for &Pipe<M, N> {
406 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 406 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
407 where 407 where
408 Self: 'a; 408 Self: 'a;
409 409
@@ -411,7 +411,7 @@ mod io_impls {
411 Pipe::write(self, buf).map(Ok) 411 Pipe::write(self, buf).map(Ok)
412 } 412 }
413 413
414 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> 414 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a
415 where 415 where
416 Self: 'a; 416 Self: 'a;
417 417
@@ -425,7 +425,7 @@ mod io_impls {
425 } 425 }
426 426
427 impl<M: RawMutex, const N: usize> embedded_io::asynch::Read for Reader<'_, M, N> { 427 impl<M: RawMutex, const N: usize> embedded_io::asynch::Read for Reader<'_, M, N> {
428 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 428 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
429 where 429 where
430 Self: 'a; 430 Self: 'a;
431 431
@@ -439,7 +439,7 @@ mod io_impls {
439 } 439 }
440 440
441 impl<M: RawMutex, const N: usize> embedded_io::asynch::Write for Writer<'_, M, N> { 441 impl<M: RawMutex, const N: usize> embedded_io::asynch::Write for Writer<'_, M, N> {
442 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> 442 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> + 'a
443 where 443 where
444 Self: 'a; 444 Self: 'a;
445 445
@@ -447,7 +447,7 @@ mod io_impls {
447 Writer::write(self, buf).map(Ok) 447 Writer::write(self, buf).map(Ok)
448 } 448 }
449 449
450 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> 450 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a
451 where 451 where
452 Self: 'a; 452 Self: 'a;
453 453
diff --git a/embassy-time/Cargo.toml b/embassy-time/Cargo.toml
index c51a71d01..9487003cc 100644
--- a/embassy-time/Cargo.toml
+++ b/embassy-time/Cargo.toml
@@ -2,8 +2,16 @@
2name = "embassy-time" 2name = "embassy-time"
3version = "0.1.0" 3version = "0.1.0"
4edition = "2021" 4edition = "2021"
5description = "Instant and Duration for embedded no-std systems, with async timer support"
6repository = "https://github.com/embassy-rs/embassy"
7readme = "README.md"
5license = "MIT OR Apache-2.0" 8license = "MIT OR Apache-2.0"
6 9categories = [
10 "embedded",
11 "no-std",
12 "concurrency",
13 "asynchronous",
14]
7 15
8[package.metadata.embassy_docs] 16[package.metadata.embassy_docs]
9src_base = "https://github.com/embassy-rs/embassy/blob/embassy-time-v$VERSION/embassy-time/src/" 17src_base = "https://github.com/embassy-rs/embassy/blob/embassy-time-v$VERSION/embassy-time/src/"
@@ -11,6 +19,9 @@ src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-time/
11features = ["nightly", "defmt", "unstable-traits", "std"] 19features = ["nightly", "defmt", "unstable-traits", "std"]
12target = "x86_64-unknown-linux-gnu" 20target = "x86_64-unknown-linux-gnu"
13 21
22[package.metadata.docs.rs]
23features = ["nightly", "defmt", "unstable-traits", "std"]
24
14[features] 25[features]
15std = ["tick-hz-1_000_000"] 26std = ["tick-hz-1_000_000"]
16wasm = ["dep:wasm-bindgen", "dep:js-sys", "dep:wasm-timer", "tick-hz-1_000_000"] 27wasm = ["dep:wasm-bindgen", "dep:js-sys", "dep:wasm-timer", "tick-hz-1_000_000"]
@@ -26,6 +37,22 @@ unstable-traits = ["embedded-hal-1"]
26# To use this you must have a time driver provided. 37# To use this you must have a time driver provided.
27defmt-timestamp-uptime = ["defmt"] 38defmt-timestamp-uptime = ["defmt"]
28 39
40# Create a global, generic queue that can be used with any executor
41# To use this you must have a time driver provided.
42generic-queue = []
43
44# Set the number of timers for the generic queue.
45#
46# At most 1 `generic-queue-*` feature can be enabled. If none is enabled, a default of 64 timers is used.
47#
48# When using embassy-time from libraries, you should *not* enable any `generic-queue-*` feature, to allow the
49# end user to pick.
50generic-queue-8 = ["generic-queue"]
51generic-queue-16 = ["generic-queue"]
52generic-queue-32 = ["generic-queue"]
53generic-queue-64 = ["generic-queue"]
54generic-queue-128 = ["generic-queue"]
55
29# Set the `embassy_time` tick rate. 56# Set the `embassy_time` tick rate.
30# 57#
31# At most 1 `tick-*` feature can be enabled. If none is enabled, a default of 1MHz is used. 58# At most 1 `tick-*` feature can be enabled. If none is enabled, a default of 1MHz is used.
@@ -107,15 +134,21 @@ log = { version = "0.4.14", optional = true }
107 134
108embedded-hal-02 = { package = "embedded-hal", version = "0.2.6" } 135embedded-hal-02 = { package = "embedded-hal", version = "0.2.6" }
109embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9", optional = true} 136embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9", optional = true}
110embedded-hal-async = { version = "=0.1.0-alpha.2", optional = true} 137embedded-hal-async = { version = "=0.1.0-alpha.3", optional = true}
111 138
112futures-util = { version = "0.3.17", default-features = false } 139futures-util = { version = "0.3.17", default-features = false }
113embassy-macros = { version = "0.1.0", path = "../embassy-macros"} 140embassy-sync = { version = "0.1", path = "../embassy-sync" }
114atomic-polyfill = "1.0.1" 141atomic-polyfill = "1.0.1"
115critical-section = "1.1" 142critical-section = "1.1"
116cfg-if = "1.0.0" 143cfg-if = "1.0.0"
144heapless = "0.7"
117 145
118# WASM dependencies 146# WASM dependencies
119wasm-bindgen = { version = "0.2.81", optional = true } 147wasm-bindgen = { version = "0.2.81", optional = true }
120js-sys = { version = "0.3", optional = true } 148js-sys = { version = "0.3", optional = true }
121wasm-timer = { version = "0.2.5", optional = true } 149wasm-timer = { version = "0.2.5", optional = true }
150
151[dev-dependencies]
152serial_test = "0.9"
153critical-section = { version = "1.1", features = ["std"] }
154
diff --git a/embassy-time/src/driver.rs b/embassy-time/src/driver.rs
index 79ae14b91..5c2ad3b23 100644
--- a/embassy-time/src/driver.rs
+++ b/embassy-time/src/driver.rs
@@ -105,20 +105,21 @@ pub trait Driver: Send + Sync + 'static {
105 /// Sets an alarm at the given timestamp. When the current timestamp reaches the alarm 105 /// Sets an alarm at the given timestamp. When the current timestamp reaches the alarm
106 /// timestamp, the provided callback function will be called. 106 /// timestamp, the provided callback function will be called.
107 /// 107 ///
108 /// If `timestamp` is already in the past, the alarm callback must be immediately fired. 108 /// The `Driver` implementation should guarantee that the alarm callback is never called synchronously from `set_alarm`.
109 /// In this case, it is allowed (but not mandatory) to call the alarm callback synchronously from `set_alarm`. 109 /// Rather - if `timestamp` is already in the past - `false` should be returned and alarm should not be set,
110 /// or alternatively, the driver should return `true` and arrange to call the alarm callback as soon as possible, but not synchronously.
110 /// 111 ///
111 /// When callback is called, it is guaranteed that now() will return a value greater or equal than timestamp. 112 /// When callback is called, it is guaranteed that now() will return a value greater or equal than timestamp.
112 /// 113 ///
113 /// Only one alarm can be active at a time for each AlarmHandle. This overwrites any previously-set alarm if any. 114 /// Only one alarm can be active at a time for each AlarmHandle. This overwrites any previously-set alarm if any.
114 fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64); 115 fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) -> bool;
115} 116}
116 117
117extern "Rust" { 118extern "Rust" {
118 fn _embassy_time_now() -> u64; 119 fn _embassy_time_now() -> u64;
119 fn _embassy_time_allocate_alarm() -> Option<AlarmHandle>; 120 fn _embassy_time_allocate_alarm() -> Option<AlarmHandle>;
120 fn _embassy_time_set_alarm_callback(alarm: AlarmHandle, callback: fn(*mut ()), ctx: *mut ()); 121 fn _embassy_time_set_alarm_callback(alarm: AlarmHandle, callback: fn(*mut ()), ctx: *mut ());
121 fn _embassy_time_set_alarm(alarm: AlarmHandle, timestamp: u64); 122 fn _embassy_time_set_alarm(alarm: AlarmHandle, timestamp: u64) -> bool;
122} 123}
123 124
124/// See [`Driver::now`] 125/// See [`Driver::now`]
@@ -139,7 +140,7 @@ pub fn set_alarm_callback(alarm: AlarmHandle, callback: fn(*mut ()), ctx: *mut (
139} 140}
140 141
141/// See [`Driver::set_alarm`] 142/// See [`Driver::set_alarm`]
142pub fn set_alarm(alarm: AlarmHandle, timestamp: u64) { 143pub fn set_alarm(alarm: AlarmHandle, timestamp: u64) -> bool {
143 unsafe { _embassy_time_set_alarm(alarm, timestamp) } 144 unsafe { _embassy_time_set_alarm(alarm, timestamp) }
144} 145}
145 146
@@ -167,7 +168,7 @@ macro_rules! time_driver_impl {
167 } 168 }
168 169
169 #[no_mangle] 170 #[no_mangle]
170 fn _embassy_time_set_alarm(alarm: $crate::driver::AlarmHandle, timestamp: u64) { 171 fn _embassy_time_set_alarm(alarm: $crate::driver::AlarmHandle, timestamp: u64) -> bool {
171 <$t as $crate::driver::Driver>::set_alarm(&$name, alarm, timestamp) 172 <$t as $crate::driver::Driver>::set_alarm(&$name, alarm, timestamp)
172 } 173 }
173 }; 174 };
diff --git a/embassy-time/src/driver_std.rs b/embassy-time/src/driver_std.rs
index 2ddb2e604..fc7fd1979 100644
--- a/embassy-time/src/driver_std.rs
+++ b/embassy-time/src/driver_std.rs
@@ -127,12 +127,14 @@ impl Driver for TimeDriver {
127 alarm.ctx = ctx; 127 alarm.ctx = ctx;
128 } 128 }
129 129
130 fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) { 130 fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) -> bool {
131 self.init(); 131 self.init();
132 let mut alarms = unsafe { self.alarms.as_ref() }.lock().unwrap(); 132 let mut alarms = unsafe { self.alarms.as_ref() }.lock().unwrap();
133 let alarm = &mut alarms[alarm.id() as usize]; 133 let alarm = &mut alarms[alarm.id() as usize];
134 alarm.timestamp = timestamp; 134 alarm.timestamp = timestamp;
135 unsafe { self.signaler.as_ref() }.signal(); 135 unsafe { self.signaler.as_ref() }.signal();
136
137 true
136 } 138 }
137} 139}
138 140
diff --git a/embassy-time/src/driver_wasm.rs b/embassy-time/src/driver_wasm.rs
index e4497e6a2..63d049897 100644
--- a/embassy-time/src/driver_wasm.rs
+++ b/embassy-time/src/driver_wasm.rs
@@ -90,15 +90,23 @@ impl Driver for TimeDriver {
90 })); 90 }));
91 } 91 }
92 92
93 fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) { 93 fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) -> bool {
94 self.init(); 94 self.init();
95 let mut alarms = unsafe { self.alarms.as_ref() }.lock().unwrap(); 95 let mut alarms = unsafe { self.alarms.as_ref() }.lock().unwrap();
96 let alarm = &mut alarms[alarm.id() as usize]; 96 let alarm = &mut alarms[alarm.id() as usize];
97 let timeout = (timestamp - self.now()) as u32;
98 if let Some(token) = alarm.token { 97 if let Some(token) = alarm.token {
99 clearTimeout(token); 98 clearTimeout(token);
100 } 99 }
101 alarm.token = Some(setTimeout(alarm.closure.as_ref().unwrap(), timeout / 1000)); 100
101 let now = self.now();
102 if timestamp <= now {
103 false
104 } else {
105 let timeout = (timestamp - now) as u32;
106 alarm.token = Some(setTimeout(alarm.closure.as_ref().unwrap(), timeout / 1000));
107
108 true
109 }
102 } 110 }
103} 111}
104 112
diff --git a/embassy-time/src/lib.rs b/embassy-time/src/lib.rs
index 4edc883fe..586aa28de 100644
--- a/embassy-time/src/lib.rs
+++ b/embassy-time/src/lib.rs
@@ -1,4 +1,4 @@
1#![cfg_attr(not(any(feature = "std", feature = "wasm")), no_std)] 1#![cfg_attr(not(any(feature = "std", feature = "wasm", test)), no_std)]
2#![cfg_attr(feature = "nightly", feature(type_alias_impl_trait))] 2#![cfg_attr(feature = "nightly", feature(type_alias_impl_trait))]
3#![doc = include_str!("../README.md")] 3#![doc = include_str!("../README.md")]
4#![allow(clippy::new_without_default)] 4#![allow(clippy::new_without_default)]
@@ -11,6 +11,7 @@ mod delay;
11pub mod driver; 11pub mod driver;
12mod duration; 12mod duration;
13mod instant; 13mod instant;
14pub mod queue;
14mod tick; 15mod tick;
15mod timer; 16mod timer;
16 17
@@ -18,6 +19,8 @@ mod timer;
18mod driver_std; 19mod driver_std;
19#[cfg(feature = "wasm")] 20#[cfg(feature = "wasm")]
20mod driver_wasm; 21mod driver_wasm;
22#[cfg(feature = "generic-queue")]
23mod queue_generic;
21 24
22pub use delay::{block_for, Delay}; 25pub use delay::{block_for, Delay};
23pub use duration::Duration; 26pub use duration::Duration;
diff --git a/embassy-time/src/queue.rs b/embassy-time/src/queue.rs
new file mode 100644
index 000000000..c6f8b440a
--- /dev/null
+++ b/embassy-time/src/queue.rs
@@ -0,0 +1,58 @@
1//! Timer queue implementation
2//!
3//! This module defines the interface a timer queue needs to implement to power the `embassy_time` module.
4//!
5//! # Implementing a timer queue
6//!
7//! - Define a struct `MyTimerQueue`
8//! - Implement [`TimerQueue`] for it
9//! - Register it as the global timer queue with [`timer_queue_impl`](crate::timer_queue_impl).
10//!
11//! # Linkage details
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//!
19//! ```
20//! use core::task::Waker;
21//!
22//! use embassy_time::Instant;
23//! use embassy_time::queue::{TimerQueue};
24//!
25//! struct MyTimerQueue{}; // not public!
26//! embassy_time::timer_queue_impl!(static QUEUE: MyTimerQueue = MyTimerQueue{});
27//!
28//! impl TimerQueue for MyTimerQueue {
29//! fn schedule_wake(&'static self, at: Instant, waker: &Waker) {
30//! todo!()
31//! }
32//! }
33//! ```
34use core::task::Waker;
35
36use crate::Instant;
37
38/// Timer queue
39pub trait TimerQueue {
40 /// Schedules a waker in the queue to be awoken at moment `at`.
41 /// If this moment is in the past, the waker might be awoken immediately.
42 fn schedule_wake(&'static self, at: Instant, waker: &Waker);
43}
44
45/// Set the TimerQueue implementation.
46///
47/// See the module documentation for an example.
48#[macro_export]
49macro_rules! timer_queue_impl {
50 (static $name:ident: $t: ty = $val:expr) => {
51 static $name: $t = $val;
52
53 #[no_mangle]
54 fn _embassy_time_schedule_wake(at: $crate::Instant, waker: &core::task::Waker) {
55 <$t as $crate::queue::TimerQueue>::schedule_wake(&$name, at, waker);
56 }
57 };
58}
diff --git a/embassy-time/src/queue_generic.rs b/embassy-time/src/queue_generic.rs
new file mode 100644
index 000000000..20ae7e6cc
--- /dev/null
+++ b/embassy-time/src/queue_generic.rs
@@ -0,0 +1,449 @@
1use core::cell::RefCell;
2use core::cmp::{min, Ordering};
3use core::task::Waker;
4
5use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
6use embassy_sync::blocking_mutex::Mutex;
7use heapless::Vec;
8
9use crate::driver::{allocate_alarm, set_alarm, set_alarm_callback, AlarmHandle};
10use crate::queue::TimerQueue;
11use crate::Instant;
12
13#[cfg(feature = "generic-queue-8")]
14const QUEUE_SIZE: usize = 8;
15#[cfg(feature = "generic-queue-16")]
16const QUEUE_SIZE: usize = 16;
17#[cfg(feature = "generic-queue-32")]
18const QUEUE_SIZE: usize = 32;
19#[cfg(feature = "generic-queue-64")]
20const QUEUE_SIZE: usize = 32;
21#[cfg(feature = "generic-queue-128")]
22const QUEUE_SIZE: usize = 128;
23#[cfg(not(any(
24 feature = "generic-queue-8",
25 feature = "generic-queue-16",
26 feature = "generic-queue-32",
27 feature = "generic-queue-64",
28 feature = "generic-queue-128"
29)))]
30const QUEUE_SIZE: usize = 64;
31
32#[derive(Debug)]
33struct Timer {
34 at: Instant,
35 waker: Waker,
36}
37
38impl PartialEq for Timer {
39 fn eq(&self, other: &Self) -> bool {
40 self.at == other.at
41 }
42}
43
44impl Eq for Timer {}
45
46impl PartialOrd for Timer {
47 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
48 self.at.partial_cmp(&other.at)
49 }
50}
51
52impl Ord for Timer {
53 fn cmp(&self, other: &Self) -> Ordering {
54 self.at.cmp(&other.at)
55 }
56}
57
58struct InnerQueue {
59 queue: Vec<Timer, QUEUE_SIZE>,
60 alarm: AlarmHandle,
61}
62
63impl InnerQueue {
64 fn schedule_wake(&mut self, at: Instant, waker: &Waker) {
65 self.queue
66 .iter_mut()
67 .find(|timer| timer.waker.will_wake(waker))
68 .map(|mut timer| {
69 timer.at = min(timer.at, at);
70 })
71 .unwrap_or_else(|| {
72 let mut timer = Timer {
73 waker: waker.clone(),
74 at,
75 };
76
77 loop {
78 match self.queue.push(timer) {
79 Ok(()) => break,
80 Err(e) => timer = e,
81 }
82
83 self.queue.pop().unwrap().waker.wake();
84 }
85 });
86
87 // Don't wait for the alarm callback to trigger and directly
88 // dispatch all timers that are already due
89 //
90 // Then update the alarm if necessary
91 self.dispatch();
92 }
93
94 fn dispatch(&mut self) {
95 loop {
96 let now = Instant::now();
97
98 let mut next_alarm = Instant::MAX;
99
100 let mut i = 0;
101 while i < self.queue.len() {
102 let timer = &self.queue[i];
103 if timer.at <= now {
104 let timer = self.queue.swap_remove(i);
105 timer.waker.wake();
106 } else {
107 next_alarm = min(next_alarm, timer.at);
108 i += 1;
109 }
110 }
111
112 if self.update_alarm(next_alarm) {
113 break;
114 }
115 }
116 }
117
118 fn update_alarm(&mut self, next_alarm: Instant) -> bool {
119 if next_alarm == Instant::MAX {
120 true
121 } else {
122 set_alarm(self.alarm, next_alarm.as_ticks())
123 }
124 }
125
126 fn handle_alarm(&mut self) {
127 self.dispatch();
128 }
129}
130
131struct Queue {
132 inner: Mutex<CriticalSectionRawMutex, RefCell<Option<InnerQueue>>>,
133}
134
135impl Queue {
136 const fn new() -> Self {
137 Self {
138 inner: Mutex::new(RefCell::new(None)),
139 }
140 }
141
142 fn schedule_wake(&'static self, at: Instant, waker: &Waker) {
143 self.inner.lock(|inner| {
144 let mut inner = inner.borrow_mut();
145
146 if inner.is_none() {}
147
148 inner
149 .get_or_insert_with(|| {
150 let handle = unsafe { allocate_alarm() }.unwrap();
151 set_alarm_callback(handle, Self::handle_alarm_callback, self as *const _ as _);
152 InnerQueue {
153 queue: Vec::new(),
154 alarm: handle,
155 }
156 })
157 .schedule_wake(at, waker)
158 });
159 }
160
161 fn handle_alarm(&self) {
162 self.inner
163 .lock(|inner| inner.borrow_mut().as_mut().unwrap().handle_alarm());
164 }
165
166 fn handle_alarm_callback(ctx: *mut ()) {
167 unsafe { (ctx as *const Self).as_ref().unwrap() }.handle_alarm();
168 }
169}
170
171impl TimerQueue for Queue {
172 fn schedule_wake(&'static self, at: Instant, waker: &Waker) {
173 Queue::schedule_wake(self, at, waker);
174 }
175}
176
177crate::timer_queue_impl!(static QUEUE: Queue = Queue::new());
178
179#[cfg(test)]
180mod tests {
181 use core::cell::Cell;
182 use core::task::{RawWaker, RawWakerVTable, Waker};
183 use std::rc::Rc;
184 use std::sync::Mutex;
185
186 use serial_test::serial;
187
188 use super::InnerQueue;
189 use crate::driver::{AlarmHandle, Driver};
190 use crate::queue_generic::QUEUE;
191 use crate::Instant;
192
193 struct InnerTestDriver {
194 now: u64,
195 alarm: u64,
196 callback: fn(*mut ()),
197 ctx: *mut (),
198 }
199
200 impl InnerTestDriver {
201 const fn new() -> Self {
202 Self {
203 now: 0,
204 alarm: u64::MAX,
205 callback: Self::noop,
206 ctx: core::ptr::null_mut(),
207 }
208 }
209
210 fn noop(_ctx: *mut ()) {}
211 }
212
213 unsafe impl Send for InnerTestDriver {}
214
215 struct TestDriver(Mutex<InnerTestDriver>);
216
217 impl TestDriver {
218 const fn new() -> Self {
219 Self(Mutex::new(InnerTestDriver::new()))
220 }
221
222 fn reset(&self) {
223 *self.0.lock().unwrap() = InnerTestDriver::new();
224 }
225
226 fn set_now(&self, now: u64) {
227 let notify = {
228 let mut inner = self.0.lock().unwrap();
229
230 if inner.now < now {
231 inner.now = now;
232
233 if inner.alarm <= now {
234 inner.alarm = u64::MAX;
235
236 Some((inner.callback, inner.ctx))
237 } else {
238 None
239 }
240 } else {
241 panic!("Going back in time?");
242 }
243 };
244
245 if let Some((callback, ctx)) = notify {
246 (callback)(ctx);
247 }
248 }
249 }
250
251 impl Driver for TestDriver {
252 fn now(&self) -> u64 {
253 self.0.lock().unwrap().now
254 }
255
256 unsafe fn allocate_alarm(&self) -> Option<AlarmHandle> {
257 Some(AlarmHandle::new(0))
258 }
259
260 fn set_alarm_callback(&self, _alarm: AlarmHandle, callback: fn(*mut ()), ctx: *mut ()) {
261 let mut inner = self.0.lock().unwrap();
262
263 inner.callback = callback;
264 inner.ctx = ctx;
265 }
266
267 fn set_alarm(&self, _alarm: AlarmHandle, timestamp: u64) -> bool {
268 let mut inner = self.0.lock().unwrap();
269
270 if timestamp <= inner.now {
271 false
272 } else {
273 inner.alarm = timestamp;
274 true
275 }
276 }
277 }
278
279 struct TestWaker {
280 pub awoken: Rc<Cell<bool>>,
281 pub waker: Waker,
282 }
283
284 impl TestWaker {
285 fn new() -> Self {
286 let flag = Rc::new(Cell::new(false));
287
288 const VTABLE: RawWakerVTable = RawWakerVTable::new(
289 |data: *const ()| {
290 unsafe {
291 Rc::increment_strong_count(data as *const Cell<bool>);
292 }
293
294 RawWaker::new(data as _, &VTABLE)
295 },
296 |data: *const ()| unsafe {
297 let data = data as *const Cell<bool>;
298 data.as_ref().unwrap().set(true);
299 Rc::decrement_strong_count(data);
300 },
301 |data: *const ()| unsafe {
302 (data as *const Cell<bool>).as_ref().unwrap().set(true);
303 },
304 |data: *const ()| unsafe {
305 Rc::decrement_strong_count(data);
306 },
307 );
308
309 let raw = RawWaker::new(Rc::into_raw(flag.clone()) as _, &VTABLE);
310
311 Self {
312 awoken: flag.clone(),
313 waker: unsafe { Waker::from_raw(raw) },
314 }
315 }
316 }
317
318 crate::time_driver_impl!(static DRIVER: TestDriver = TestDriver::new());
319
320 fn setup() {
321 DRIVER.reset();
322
323 QUEUE.inner.lock(|inner| {
324 *inner.borrow_mut() = InnerQueue::new();
325 });
326 }
327
328 fn queue_len() -> usize {
329 QUEUE.inner.lock(|inner| inner.borrow().queue.iter().count())
330 }
331
332 #[test]
333 #[serial]
334 fn test_schedule() {
335 setup();
336
337 assert_eq!(queue_len(), 0);
338
339 let waker = TestWaker::new();
340
341 QUEUE.schedule_wake(Instant::from_secs(1), &waker.waker);
342
343 assert!(!waker.awoken.get());
344 assert_eq!(queue_len(), 1);
345 }
346
347 #[test]
348 #[serial]
349 fn test_schedule_same() {
350 setup();
351
352 let waker = TestWaker::new();
353
354 QUEUE.schedule_wake(Instant::from_secs(1), &waker.waker);
355
356 assert_eq!(queue_len(), 1);
357
358 QUEUE.schedule_wake(Instant::from_secs(1), &waker.waker);
359
360 assert_eq!(queue_len(), 1);
361
362 QUEUE.schedule_wake(Instant::from_secs(100), &waker.waker);
363
364 assert_eq!(queue_len(), 1);
365
366 let waker2 = TestWaker::new();
367
368 QUEUE.schedule_wake(Instant::from_secs(100), &waker2.waker);
369
370 assert_eq!(queue_len(), 2);
371 }
372
373 #[test]
374 #[serial]
375 fn test_trigger() {
376 setup();
377
378 let waker = TestWaker::new();
379
380 QUEUE.schedule_wake(Instant::from_secs(100), &waker.waker);
381
382 assert!(!waker.awoken.get());
383
384 DRIVER.set_now(Instant::from_secs(99).as_ticks());
385
386 assert!(!waker.awoken.get());
387
388 assert_eq!(queue_len(), 1);
389
390 DRIVER.set_now(Instant::from_secs(100).as_ticks());
391
392 assert!(waker.awoken.get());
393
394 assert_eq!(queue_len(), 0);
395 }
396
397 #[test]
398 #[serial]
399 fn test_immediate_trigger() {
400 setup();
401
402 let waker = TestWaker::new();
403
404 QUEUE.schedule_wake(Instant::from_secs(100), &waker.waker);
405
406 DRIVER.set_now(Instant::from_secs(50).as_ticks());
407
408 let waker2 = TestWaker::new();
409
410 QUEUE.schedule_wake(Instant::from_secs(40), &waker2.waker);
411
412 assert!(!waker.awoken.get());
413 assert!(waker2.awoken.get());
414 assert_eq!(queue_len(), 1);
415 }
416
417 #[test]
418 #[serial]
419 fn test_queue_overflow() {
420 setup();
421
422 for i in 1..super::QUEUE_SIZE {
423 let waker = TestWaker::new();
424
425 QUEUE.schedule_wake(Instant::from_secs(310), &waker.waker);
426
427 assert_eq!(queue_len(), i);
428 assert!(!waker.awoken.get());
429 }
430
431 let first_waker = TestWaker::new();
432
433 QUEUE.schedule_wake(Instant::from_secs(300), &first_waker.waker);
434
435 assert_eq!(queue_len(), super::QUEUE_SIZE);
436 assert!(!first_waker.awoken.get());
437
438 let second_waker = TestWaker::new();
439
440 QUEUE.schedule_wake(Instant::from_secs(305), &second_waker.waker);
441
442 assert_eq!(queue_len(), super::QUEUE_SIZE);
443 assert!(first_waker.awoken.get());
444
445 QUEUE.schedule_wake(Instant::from_secs(320), &TestWaker::new().waker);
446 assert_eq!(queue_len(), super::QUEUE_SIZE);
447 assert!(second_waker.awoken.get());
448 }
449}
diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml
index 6949042e2..c633f82f5 100644
--- a/examples/nrf/Cargo.toml
+++ b/examples/nrf/Cargo.toml
@@ -17,7 +17,7 @@ embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["de
17embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } 17embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] }
18embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "pool-16"], optional = true } 18embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "pool-16"], optional = true }
19embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"], optional = true } 19embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"], optional = true }
20embedded-io = "0.3.0" 20embedded-io = "0.3.1"
21embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx126x", "time", "defmt"], optional = true } 21embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx126x", "time", "defmt"], optional = true }
22 22
23lorawan-device = { version = "0.8.0", default-features = false, features = ["async"], optional = true } 23lorawan-device = { version = "0.8.0", default-features = false, features = ["async"], optional = true }
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml
index 38355bbf8..31f688305 100644
--- a/examples/rp/Cargo.toml
+++ b/examples/rp/Cargo.toml
@@ -28,8 +28,8 @@ display-interface = "0.4.1"
28byte-slice-cast = { version = "1.2.0", default-features = false } 28byte-slice-cast = { version = "1.2.0", default-features = false }
29 29
30embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9" } 30embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9" }
31embedded-hal-async = { version = "0.1.0-alpha.1" } 31embedded-hal-async = { version = "0.1.0-alpha.3" }
32embedded-io = { version = "0.3.0", features = ["async", "defmt"] } 32embedded-io = { version = "0.3.1", features = ["async", "defmt"] }
33embedded-storage = { version = "0.3" } 33embedded-storage = { version = "0.3" }
34static_cell = "1.0.0" 34static_cell = "1.0.0"
35 35
diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml
index b9bd1e718..790258382 100644
--- a/examples/std/Cargo.toml
+++ b/examples/std/Cargo.toml
@@ -9,7 +9,7 @@ embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["lo
9embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["log", "std", "nightly", "integrated-timers"] } 9embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["log", "std", "nightly", "integrated-timers"] }
10embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["log", "std", "nightly"] } 10embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["log", "std", "nightly"] }
11embassy-net = { version = "0.1.0", path = "../../embassy-net", features=[ "std", "nightly", "log", "medium-ethernet", "tcp", "udp", "dhcpv4", "pool-16"] } 11embassy-net = { version = "0.1.0", path = "../../embassy-net", features=[ "std", "nightly", "log", "medium-ethernet", "tcp", "udp", "dhcpv4", "pool-16"] }
12embedded-io = { version = "0.3.0", features = ["async", "std", "futures"] } 12embedded-io = { version = "0.3.1", features = ["async", "std", "futures"] }
13critical-section = { version = "1.1", features = ["std"] } 13critical-section = { version = "1.1", features = ["std"] }
14 14
15async-io = "1.6.0" 15async-io = "1.6.0"
diff --git a/examples/stm32f1/src/bin/adc.rs b/examples/stm32f1/src/bin/adc.rs
index 2d6b4a0e9..ed59e2799 100644
--- a/examples/stm32f1/src/bin/adc.rs
+++ b/examples/stm32f1/src/bin/adc.rs
@@ -16,11 +16,19 @@ async fn main(_spawner: Spawner) {
16 let mut adc = Adc::new(p.ADC1, &mut Delay); 16 let mut adc = Adc::new(p.ADC1, &mut Delay);
17 let mut pin = p.PB1; 17 let mut pin = p.PB1;
18 18
19 let mut vref = adc.enable_vref(&mut Delay); 19 let mut vrefint = adc.enable_vref(&mut Delay);
20 adc.calibrate(&mut vref); 20 let vrefint_sample = adc.read(&mut vrefint);
21 let convert_to_millivolts = |sample| {
22 // From http://www.st.com/resource/en/datasheet/CD00161566.pdf
23 // 5.3.4 Embedded reference voltage
24 const VREFINT_MV: u32 = 1200; // mV
25
26 (u32::from(sample) * VREFINT_MV / u32::from(vrefint_sample)) as u16
27 };
28
21 loop { 29 loop {
22 let v = adc.read(&mut pin); 30 let v = adc.read(&mut pin);
23 info!("--> {} - {} mV", v, adc.to_millivolts(v)); 31 info!("--> {} - {} mV", v, convert_to_millivolts(v));
24 Timer::after(Duration::from_millis(100)).await; 32 Timer::after(Duration::from_millis(100)).await;
25 } 33 }
26} 34}
diff --git a/examples/stm32f3/src/bin/usart_dma.rs b/examples/stm32f3/src/bin/usart_dma.rs
index 3bc5a287f..47121acf1 100644
--- a/examples/stm32f3/src/bin/usart_dma.rs
+++ b/examples/stm32f3/src/bin/usart_dma.rs
@@ -7,6 +7,7 @@ use core::fmt::Write;
7use defmt::*; 7use defmt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::dma::NoDma; 9use embassy_stm32::dma::NoDma;
10use embassy_stm32::interrupt;
10use embassy_stm32::usart::{Config, Uart}; 11use embassy_stm32::usart::{Config, Uart};
11use heapless::String; 12use heapless::String;
12use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
@@ -17,7 +18,8 @@ async fn main(_spawner: Spawner) {
17 info!("Hello World!"); 18 info!("Hello World!");
18 19
19 let config = Config::default(); 20 let config = Config::default();
20 let mut usart = Uart::new(p.USART1, p.PE1, p.PE0, p.DMA1_CH4, NoDma, config); 21 let irq = interrupt::take!(USART1);
22 let mut usart = Uart::new(p.USART1, p.PE1, p.PE0, irq, p.DMA1_CH4, NoDma, config);
21 23
22 for n in 0u32.. { 24 for n in 0u32.. {
23 let mut s: String<128> = String::new(); 25 let mut s: String<128> = String::new();
diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml
index 6d4f09fba..b05457eaa 100644
--- a/examples/stm32f4/Cargo.toml
+++ b/examples/stm32f4/Cargo.toml
@@ -17,7 +17,7 @@ defmt-rtt = "0.3"
17cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } 17cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
18cortex-m-rt = "0.7.0" 18cortex-m-rt = "0.7.0"
19embedded-hal = "0.2.6" 19embedded-hal = "0.2.6"
20embedded-io = "0.3.0" 20embedded-io = "0.3.1"
21panic-probe = { version = "0.3", features = ["print-defmt"] } 21panic-probe = { version = "0.3", features = ["print-defmt"] }
22futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 22futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
23heapless = { version = "0.7.5", default-features = false } 23heapless = { version = "0.7.5", default-features = false }
diff --git a/examples/stm32f4/src/bin/adc.rs b/examples/stm32f4/src/bin/adc.rs
index 1d030f7dc..1c9a0b35d 100644
--- a/examples/stm32f4/src/bin/adc.rs
+++ b/examples/stm32f4/src/bin/adc.rs
@@ -24,19 +24,44 @@ async fn main(_spawner: Spawner) {
24 // Startup delay can be combined to the maximum of either 24 // Startup delay can be combined to the maximum of either
25 delay.delay_us(Temperature::start_time_us().max(VrefInt::start_time_us())); 25 delay.delay_us(Temperature::start_time_us().max(VrefInt::start_time_us()));
26 26
27 let vrefint_sample = adc.read_internal(&mut vrefint);
28
29 let convert_to_millivolts = |sample| {
30 // From http://www.st.com/resource/en/datasheet/DM00071990.pdf
31 // 6.3.24 Reference voltage
32 const VREFINT_MV: u32 = 1210; // mV
33
34 (u32::from(sample) * VREFINT_MV / u32::from(vrefint_sample)) as u16
35 };
36
37 let convert_to_celcius = |sample| {
38 // From http://www.st.com/resource/en/datasheet/DM00071990.pdf
39 // 6.3.22 Temperature sensor characteristics
40 const V25: i32 = 760; // mV
41 const AVG_SLOPE: f32 = 2.5; // mV/C
42
43 let sample_mv = convert_to_millivolts(sample) as i32;
44
45 (sample_mv - V25) as f32 / AVG_SLOPE + 25.0
46 };
47
48 info!("VrefInt: {}", vrefint_sample);
49 const MAX_ADC_SAMPLE: u16 = (1 << 12) - 1;
50 info!("VCCA: {} mV", convert_to_millivolts(MAX_ADC_SAMPLE));
51
27 loop { 52 loop {
28 // Read pin 53 // Read pin
29 let v = adc.read(&mut pin); 54 let v = adc.read(&mut pin);
30 info!("PC1: {} ({} mV)", v, adc.to_millivolts(v)); 55 info!("PC1: {} ({} mV)", v, convert_to_millivolts(v));
31 56
32 // Read internal temperature 57 // Read internal temperature
33 let v = adc.read_internal(&mut temp); 58 let v = adc.read_internal(&mut temp);
34 let celcius = Temperature::to_celcius(adc.to_millivolts(v)); 59 let celcius = convert_to_celcius(v);
35 info!("Internal temp: {} ({} C)", v, celcius); 60 info!("Internal temp: {} ({} C)", v, celcius);
36 61
37 // Read internal voltage reference 62 // Read internal voltage reference
38 let v = adc.read_internal(&mut vrefint); 63 let v = adc.read_internal(&mut vrefint);
39 info!("VrefInt: {} ({} mV)", v, adc.to_millivolts(v)); 64 info!("VrefInt: {}", v);
40 65
41 Timer::after(Duration::from_millis(100)).await; 66 Timer::after(Duration::from_millis(100)).await;
42 } 67 }
diff --git a/examples/stm32f4/src/bin/i2c.rs b/examples/stm32f4/src/bin/i2c.rs
new file mode 100644
index 000000000..6e51c211d
--- /dev/null
+++ b/examples/stm32f4/src/bin/i2c.rs
@@ -0,0 +1,45 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::*;
6use embassy_executor::Spawner;
7use embassy_stm32::dma::NoDma;
8use embassy_stm32::i2c::{Error, I2c, TimeoutI2c};
9use embassy_stm32::interrupt;
10use embassy_stm32::time::Hertz;
11use embassy_time::Duration;
12use {defmt_rtt as _, panic_probe as _};
13
14const ADDRESS: u8 = 0x5F;
15const WHOAMI: u8 = 0x0F;
16
17#[embassy_executor::main]
18async fn main(_spawner: Spawner) -> ! {
19 info!("Hello world!");
20 let p = embassy_stm32::init(Default::default());
21
22 let irq = interrupt::take!(I2C2_EV);
23 let mut i2c = I2c::new(
24 p.I2C2,
25 p.PB10,
26 p.PB11,
27 irq,
28 NoDma,
29 NoDma,
30 Hertz(100_000),
31 Default::default(),
32 );
33
34 // I2C bus can freeze if SCL line is shorted or due to a broken device that clock stretches for too long.
35 // TimeoutI2c allows recovering from such errors by throwing `Error::Timeout` after a given delay.
36 let mut timeout_i2c = TimeoutI2c::new(&mut i2c, Duration::from_millis(1000));
37
38 let mut data = [0u8; 1];
39
40 match timeout_i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data) {
41 Ok(()) => info!("Whoami: {}", data[0]),
42 Err(Error::Timeout) => error!("Operation timed out"),
43 Err(e) => error!("I2c Error: {:?}", e),
44 }
45}
diff --git a/examples/stm32f4/src/bin/usart.rs b/examples/stm32f4/src/bin/usart.rs
index 90ad882b8..8f41bb6c4 100644
--- a/examples/stm32f4/src/bin/usart.rs
+++ b/examples/stm32f4/src/bin/usart.rs
@@ -5,6 +5,7 @@
5use cortex_m_rt::entry; 5use cortex_m_rt::entry;
6use defmt::*; 6use defmt::*;
7use embassy_stm32::dma::NoDma; 7use embassy_stm32::dma::NoDma;
8use embassy_stm32::interrupt;
8use embassy_stm32::usart::{Config, Uart}; 9use embassy_stm32::usart::{Config, Uart};
9use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
10 11
@@ -15,7 +16,8 @@ fn main() -> ! {
15 let p = embassy_stm32::init(Default::default()); 16 let p = embassy_stm32::init(Default::default());
16 17
17 let config = Config::default(); 18 let config = Config::default();
18 let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, NoDma, NoDma, config); 19 let irq = interrupt::take!(USART3);
20 let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, irq, NoDma, NoDma, config);
19 21
20 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n")); 22 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
21 info!("wrote Hello, starting echo"); 23 info!("wrote Hello, starting echo");
diff --git a/examples/stm32f4/src/bin/usart_buffered.rs b/examples/stm32f4/src/bin/usart_buffered.rs
index 7bcecbd26..dd171fe13 100644
--- a/examples/stm32f4/src/bin/usart_buffered.rs
+++ b/examples/stm32f4/src/bin/usart_buffered.rs
@@ -4,9 +4,8 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::dma::NoDma;
8use embassy_stm32::interrupt; 7use embassy_stm32::interrupt;
9use embassy_stm32::usart::{BufferedUart, Config, State, Uart}; 8use embassy_stm32::usart::{BufferedUart, Config, State};
10use embedded_io::asynch::BufRead; 9use embedded_io::asynch::BufRead;
11use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
12 11
@@ -16,13 +15,21 @@ async fn main(_spawner: Spawner) {
16 info!("Hello World!"); 15 info!("Hello World!");
17 16
18 let config = Config::default(); 17 let config = Config::default();
19 let usart = Uart::new(p.USART3, p.PD9, p.PD8, NoDma, NoDma, config);
20 18
21 let mut state = State::new(); 19 let mut state = State::new();
22 let irq = interrupt::take!(USART3); 20 let irq = interrupt::take!(USART3);
23 let mut tx_buf = [0u8; 32]; 21 let mut tx_buf = [0u8; 32];
24 let mut rx_buf = [0u8; 32]; 22 let mut rx_buf = [0u8; 32];
25 let mut buf_usart = BufferedUart::new(&mut state, usart, irq, &mut tx_buf, &mut rx_buf); 23 let mut buf_usart = BufferedUart::new(
24 &mut state,
25 p.USART3,
26 p.PD9,
27 p.PD8,
28 irq,
29 &mut tx_buf,
30 &mut rx_buf,
31 config,
32 );
26 33
27 loop { 34 loop {
28 let buf = buf_usart.fill_buf().await.unwrap(); 35 let buf = buf_usart.fill_buf().await.unwrap();
diff --git a/examples/stm32f4/src/bin/usart_dma.rs b/examples/stm32f4/src/bin/usart_dma.rs
index bb41b8b4f..78baeaa0d 100644
--- a/examples/stm32f4/src/bin/usart_dma.rs
+++ b/examples/stm32f4/src/bin/usart_dma.rs
@@ -7,6 +7,7 @@ use core::fmt::Write;
7use defmt::*; 7use defmt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::dma::NoDma; 9use embassy_stm32::dma::NoDma;
10use embassy_stm32::interrupt;
10use embassy_stm32::usart::{Config, Uart}; 11use embassy_stm32::usart::{Config, Uart};
11use heapless::String; 12use heapless::String;
12use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
@@ -17,7 +18,8 @@ async fn main(_spawner: Spawner) {
17 info!("Hello World!"); 18 info!("Hello World!");
18 19
19 let config = Config::default(); 20 let config = Config::default();
20 let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, p.DMA1_CH3, NoDma, config); 21 let irq = interrupt::take!(USART3);
22 let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, irq, p.DMA1_CH3, NoDma, config);
21 23
22 for n in 0u32.. { 24 for n in 0u32.. {
23 let mut s: String<128> = String::new(); 25 let mut s: String<128> = String::new();
diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml
index dad92c0fc..b14afd2fe 100644
--- a/examples/stm32f7/Cargo.toml
+++ b/examples/stm32f7/Cargo.toml
@@ -10,7 +10,7 @@ embassy-executor = { version = "0.1.0", path = "../../embassy-executor", feature
10embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 10embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "net", "stm32f767zi", "unstable-pac", "time-driver-any", "exti"] } 11embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "net", "stm32f767zi", "unstable-pac", "time-driver-any", "exti"] }
12embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "pool-16"] } 12embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "pool-16"] }
13embedded-io = { version = "0.3.0", features = ["async"] } 13embedded-io = { version = "0.3.1", features = ["async"] }
14 14
15defmt = "0.3" 15defmt = "0.3"
16defmt-rtt = "0.3" 16defmt-rtt = "0.3"
diff --git a/examples/stm32f7/src/bin/adc.rs b/examples/stm32f7/src/bin/adc.rs
index 80fad8c41..70b3b2a75 100644
--- a/examples/stm32f7/src/bin/adc.rs
+++ b/examples/stm32f7/src/bin/adc.rs
@@ -16,9 +16,19 @@ async fn main(_spawner: Spawner) {
16 let mut adc = Adc::new(p.ADC1, &mut Delay); 16 let mut adc = Adc::new(p.ADC1, &mut Delay);
17 let mut pin = p.PA3; 17 let mut pin = p.PA3;
18 18
19 let mut vrefint = adc.enable_vrefint();
20 let vrefint_sample = adc.read_internal(&mut vrefint);
21 let convert_to_millivolts = |sample| {
22 // From http://www.st.com/resource/en/datasheet/DM00273119.pdf
23 // 6.3.27 Reference voltage
24 const VREFINT_MV: u32 = 1210; // mV
25
26 (u32::from(sample) * VREFINT_MV / u32::from(vrefint_sample)) as u16
27 };
28
19 loop { 29 loop {
20 let v = adc.read(&mut pin); 30 let v = adc.read(&mut pin);
21 info!("--> {} - {} mV", v, adc.to_millivolts(v)); 31 info!("--> {} - {} mV", v, convert_to_millivolts(v));
22 Timer::after(Duration::from_millis(100)).await; 32 Timer::after(Duration::from_millis(100)).await;
23 } 33 }
24} 34}
diff --git a/examples/stm32f7/src/bin/usart_dma.rs b/examples/stm32f7/src/bin/usart_dma.rs
index 07270479c..4827c52ae 100644
--- a/examples/stm32f7/src/bin/usart_dma.rs
+++ b/examples/stm32f7/src/bin/usart_dma.rs
@@ -7,6 +7,7 @@ use core::fmt::Write;
7use defmt::*; 7use defmt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::dma::NoDma; 9use embassy_stm32::dma::NoDma;
10use embassy_stm32::interrupt;
10use embassy_stm32::usart::{Config, Uart}; 11use embassy_stm32::usart::{Config, Uart};
11use heapless::String; 12use heapless::String;
12use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
@@ -15,7 +16,8 @@ use {defmt_rtt as _, panic_probe as _};
15async fn main(_spawner: Spawner) { 16async fn main(_spawner: Spawner) {
16 let p = embassy_stm32::init(Default::default()); 17 let p = embassy_stm32::init(Default::default());
17 let config = Config::default(); 18 let config = Config::default();
18 let mut usart = Uart::new(p.UART7, p.PA8, p.PA15, p.DMA1_CH1, NoDma, config); 19 let irq = interrupt::take!(UART7);
20 let mut usart = Uart::new(p.UART7, p.PA8, p.PA15, irq, p.DMA1_CH1, NoDma, config);
19 21
20 for n in 0u32.. { 22 for n in 0u32.. {
21 let mut s: String<128> = String::new(); 23 let mut s: String<128> = String::new();
diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml
index 1a05b9ecb..0dccff6e8 100644
--- a/examples/stm32h7/Cargo.toml
+++ b/examples/stm32h7/Cargo.toml
@@ -10,7 +10,7 @@ embassy-executor = { version = "0.1.0", path = "../../embassy-executor", feature
10embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } 10embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h743bi", "net", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] } 11embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h743bi", "net", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] }
12embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "pool-16", "unstable-traits"] } 12embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "pool-16", "unstable-traits"] }
13embedded-io = { version = "0.3.0", features = ["async"] } 13embedded-io = { version = "0.3.1", features = ["async"] }
14 14
15defmt = "0.3" 15defmt = "0.3"
16defmt-rtt = "0.3" 16defmt-rtt = "0.3"
@@ -19,7 +19,7 @@ cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
19cortex-m-rt = "0.7.0" 19cortex-m-rt = "0.7.0"
20embedded-hal = "0.2.6" 20embedded-hal = "0.2.6"
21embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9" } 21embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9" }
22embedded-hal-async = { version = "=0.1.0-alpha.2" } 22embedded-hal-async = { version = "=0.1.0-alpha.3" }
23embedded-nal-async = "0.2.0" 23embedded-nal-async = "0.2.0"
24panic-probe = { version = "0.3", features = ["print-defmt"] } 24panic-probe = { version = "0.3", features = ["print-defmt"] }
25futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 25futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
diff --git a/examples/stm32h7/src/bin/i2c.rs b/examples/stm32h7/src/bin/i2c.rs
new file mode 100644
index 000000000..d44319ae6
--- /dev/null
+++ b/examples/stm32h7/src/bin/i2c.rs
@@ -0,0 +1,44 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::*;
6use embassy_executor::Spawner;
7use embassy_stm32::i2c::{Error, I2c, TimeoutI2c};
8use embassy_stm32::interrupt;
9use embassy_stm32::time::Hertz;
10use embassy_time::Duration;
11use {defmt_rtt as _, panic_probe as _};
12
13const ADDRESS: u8 = 0x5F;
14const WHOAMI: u8 = 0x0F;
15
16#[embassy_executor::main]
17async fn main(_spawner: Spawner) -> ! {
18 info!("Hello world!");
19 let p = embassy_stm32::init(Default::default());
20
21 let irq = interrupt::take!(I2C2_EV);
22 let mut i2c = I2c::new(
23 p.I2C2,
24 p.PB10,
25 p.PB11,
26 irq,
27 p.DMA1_CH4,
28 p.DMA1_CH5,
29 Hertz(100_000),
30 Default::default(),
31 );
32
33 // I2C bus can freeze if SCL line is shorted or due to a broken device that clock stretches for too long.
34 // TimeoutI2c allows recovering from such errors by throwing `Error::Timeout` after a given delay.
35 let mut timeout_i2c = TimeoutI2c::new(&mut i2c, Duration::from_millis(1000));
36
37 let mut data = [0u8; 1];
38
39 match timeout_i2c.blocking_write_read(ADDRESS, &[WHOAMI], &mut data) {
40 Ok(()) => info!("Whoami: {}", data[0]),
41 Err(Error::Timeout) => error!("Operation timed out"),
42 Err(e) => error!("I2c Error: {:?}", e),
43 }
44}
diff --git a/examples/stm32h7/src/bin/usart.rs b/examples/stm32h7/src/bin/usart.rs
index 87c2b1253..405f18ec7 100644
--- a/examples/stm32h7/src/bin/usart.rs
+++ b/examples/stm32h7/src/bin/usart.rs
@@ -6,6 +6,7 @@ use cortex_m_rt::entry;
6use defmt::*; 6use defmt::*;
7use embassy_executor::Executor; 7use embassy_executor::Executor;
8use embassy_stm32::dma::NoDma; 8use embassy_stm32::dma::NoDma;
9use embassy_stm32::interrupt;
9use embassy_stm32::usart::{Config, Uart}; 10use embassy_stm32::usart::{Config, Uart};
10use static_cell::StaticCell; 11use static_cell::StaticCell;
11use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
@@ -15,7 +16,8 @@ async fn main_task() {
15 let p = embassy_stm32::init(Default::default()); 16 let p = embassy_stm32::init(Default::default());
16 17
17 let config = Config::default(); 18 let config = Config::default();
18 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, NoDma, NoDma, config); 19 let irq = interrupt::take!(UART7);
20 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, irq, NoDma, NoDma, config);
19 21
20 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n")); 22 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
21 info!("wrote Hello, starting echo"); 23 info!("wrote Hello, starting echo");
diff --git a/examples/stm32h7/src/bin/usart_dma.rs b/examples/stm32h7/src/bin/usart_dma.rs
index 3adffcbeb..6e3491e55 100644
--- a/examples/stm32h7/src/bin/usart_dma.rs
+++ b/examples/stm32h7/src/bin/usart_dma.rs
@@ -8,6 +8,7 @@ use cortex_m_rt::entry;
8use defmt::*; 8use defmt::*;
9use embassy_executor::Executor; 9use embassy_executor::Executor;
10use embassy_stm32::dma::NoDma; 10use embassy_stm32::dma::NoDma;
11use embassy_stm32::interrupt;
11use embassy_stm32::usart::{Config, Uart}; 12use embassy_stm32::usart::{Config, Uart};
12use heapless::String; 13use heapless::String;
13use static_cell::StaticCell; 14use static_cell::StaticCell;
@@ -18,7 +19,8 @@ async fn main_task() {
18 let p = embassy_stm32::init(Default::default()); 19 let p = embassy_stm32::init(Default::default());
19 20
20 let config = Config::default(); 21 let config = Config::default();
21 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, p.DMA1_CH0, NoDma, config); 22 let irq = interrupt::take!(UART7);
23 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, irq, p.DMA1_CH0, NoDma, config);
22 24
23 for n in 0u32.. { 25 for n in 0u32.. {
24 let mut s: String<128> = String::new(); 26 let mut s: String<128> = String::new();
diff --git a/examples/stm32h7/src/bin/usart_split.rs b/examples/stm32h7/src/bin/usart_split.rs
index df2b600f8..f97176ecb 100644
--- a/examples/stm32h7/src/bin/usart_split.rs
+++ b/examples/stm32h7/src/bin/usart_split.rs
@@ -5,6 +5,7 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::dma::NoDma; 7use embassy_stm32::dma::NoDma;
8use embassy_stm32::interrupt;
8use embassy_stm32::peripherals::{DMA1_CH1, UART7}; 9use embassy_stm32::peripherals::{DMA1_CH1, UART7};
9use embassy_stm32::usart::{Config, Uart, UartRx}; 10use embassy_stm32::usart::{Config, Uart, UartRx};
10use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; 11use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
@@ -31,7 +32,8 @@ async fn main(spawner: Spawner) -> ! {
31 info!("Hello World!"); 32 info!("Hello World!");
32 33
33 let config = Config::default(); 34 let config = Config::default();
34 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, p.DMA1_CH0, p.DMA1_CH1, config); 35 let irq = interrupt::take!(UART7);
36 let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, irq, p.DMA1_CH0, p.DMA1_CH1, config);
35 unwrap!(usart.blocking_write(b"Type 8 chars to echo!\r\n")); 37 unwrap!(usart.blocking_write(b"Type 8 chars to echo!\r\n"));
36 38
37 let (mut tx, rx) = usart.split(); 39 let (mut tx, rx) = usart.split();
diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml
index 7e1120f48..8b00773be 100644
--- a/examples/stm32l0/Cargo.toml
+++ b/examples/stm32l0/Cargo.toml
@@ -22,7 +22,7 @@ defmt = "0.3"
22defmt-rtt = "0.3" 22defmt-rtt = "0.3"
23 23
24embedded-storage = "0.3.0" 24embedded-storage = "0.3.0"
25embedded-io = "0.3.0" 25embedded-io = "0.3.1"
26 26
27cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } 27cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
28cortex-m-rt = "0.7.0" 28cortex-m-rt = "0.7.0"
diff --git a/examples/stm32l0/src/bin/usart_dma.rs b/examples/stm32l0/src/bin/usart_dma.rs
index 66657d0f0..c307f857a 100644
--- a/examples/stm32l0/src/bin/usart_dma.rs
+++ b/examples/stm32l0/src/bin/usart_dma.rs
@@ -4,13 +4,15 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::interrupt;
7use embassy_stm32::usart::{Config, Uart}; 8use embassy_stm32::usart::{Config, Uart};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
10#[embassy_executor::main] 11#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 12async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 13 let p = embassy_stm32::init(Default::default());
13 let mut usart = Uart::new(p.USART1, p.PB7, p.PB6, p.DMA1_CH2, p.DMA1_CH3, Config::default()); 14 let irq = interrupt::take!(USART1);
15 let mut usart = Uart::new(p.USART1, p.PB7, p.PB6, irq, p.DMA1_CH2, p.DMA1_CH3, Config::default());
14 16
15 usart.write(b"Hello Embassy World!\r\n").await.unwrap(); 17 usart.write(b"Hello Embassy World!\r\n").await.unwrap();
16 info!("wrote Hello, starting echo"); 18 info!("wrote Hello, starting echo");
diff --git a/examples/stm32l0/src/bin/usart_irq.rs b/examples/stm32l0/src/bin/usart_irq.rs
index 0e2237388..8e84cd092 100644
--- a/examples/stm32l0/src/bin/usart_irq.rs
+++ b/examples/stm32l0/src/bin/usart_irq.rs
@@ -4,9 +4,8 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::dma::NoDma;
8use embassy_stm32::interrupt; 7use embassy_stm32::interrupt;
9use embassy_stm32::usart::{BufferedUart, Config, State, Uart}; 8use embassy_stm32::usart::{BufferedUart, Config, State};
10use embedded_io::asynch::{Read, Write}; 9use embedded_io::asynch::{Read, Write};
11use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
12 11
@@ -21,15 +20,18 @@ async fn main(_spawner: Spawner) {
21 let mut config = Config::default(); 20 let mut config = Config::default();
22 config.baudrate = 9600; 21 config.baudrate = 9600;
23 22
24 let usart = Uart::new(p.USART2, p.PA3, p.PA2, NoDma, NoDma, config);
25 let mut state = State::new(); 23 let mut state = State::new();
24 let irq = interrupt::take!(USART2);
26 let mut usart = unsafe { 25 let mut usart = unsafe {
27 BufferedUart::new( 26 BufferedUart::new(
28 &mut state, 27 &mut state,
29 usart, 28 p.USART2,
30 interrupt::take!(USART2), 29 p.PA3,
30 p.PA2,
31 irq,
31 &mut TX_BUFFER, 32 &mut TX_BUFFER,
32 &mut RX_BUFFER, 33 &mut RX_BUFFER,
34 config,
33 ) 35 )
34 }; 36 };
35 37
diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml
index 657605ebe..83d456b26 100644
--- a/examples/stm32l4/Cargo.toml
+++ b/examples/stm32l4/Cargo.toml
@@ -20,7 +20,7 @@ cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
20cortex-m-rt = "0.7.0" 20cortex-m-rt = "0.7.0"
21embedded-hal = "0.2.6" 21embedded-hal = "0.2.6"
22embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9" } 22embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9" }
23embedded-hal-async = { version = "=0.1.0-alpha.2" } 23embedded-hal-async = { version = "=0.1.0-alpha.3" }
24panic-probe = { version = "0.3", features = ["print-defmt"] } 24panic-probe = { version = "0.3", features = ["print-defmt"] }
25futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 25futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
26heapless = { version = "0.7.5", default-features = false } 26heapless = { version = "0.7.5", default-features = false }
diff --git a/examples/stm32l4/src/bin/usart.rs b/examples/stm32l4/src/bin/usart.rs
index 4a4b46c53..7d874d9d7 100644
--- a/examples/stm32l4/src/bin/usart.rs
+++ b/examples/stm32l4/src/bin/usart.rs
@@ -4,6 +4,7 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_stm32::dma::NoDma; 6use embassy_stm32::dma::NoDma;
7use embassy_stm32::interrupt;
7use embassy_stm32::usart::{Config, Uart}; 8use embassy_stm32::usart::{Config, Uart};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
@@ -14,7 +15,8 @@ fn main() -> ! {
14 let p = embassy_stm32::init(Default::default()); 15 let p = embassy_stm32::init(Default::default());
15 16
16 let config = Config::default(); 17 let config = Config::default();
17 let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, NoDma, NoDma, config); 18 let irq = interrupt::take!(UART4);
19 let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, irq, NoDma, NoDma, config);
18 20
19 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n")); 21 unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
20 info!("wrote Hello, starting echo"); 22 info!("wrote Hello, starting echo");
diff --git a/examples/stm32l4/src/bin/usart_dma.rs b/examples/stm32l4/src/bin/usart_dma.rs
index 728906897..452bede30 100644
--- a/examples/stm32l4/src/bin/usart_dma.rs
+++ b/examples/stm32l4/src/bin/usart_dma.rs
@@ -7,6 +7,7 @@ use core::fmt::Write;
7use defmt::*; 7use defmt::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::dma::NoDma; 9use embassy_stm32::dma::NoDma;
10use embassy_stm32::interrupt;
10use embassy_stm32::usart::{Config, Uart}; 11use embassy_stm32::usart::{Config, Uart};
11use heapless::String; 12use heapless::String;
12use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
@@ -17,7 +18,8 @@ async fn main(_spawner: Spawner) {
17 info!("Hello World!"); 18 info!("Hello World!");
18 19
19 let config = Config::default(); 20 let config = Config::default();
20 let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, p.DMA1_CH3, NoDma, config); 21 let irq = interrupt::take!(UART4);
22 let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, irq, p.DMA1_CH3, NoDma, config);
21 23
22 for n in 0u32.. { 24 for n in 0u32.. {
23 let mut s: String<128> = String::new(); 25 let mut s: String<128> = String::new();
diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml
index 63eac3ed2..848723f8b 100644
--- a/examples/stm32l5/Cargo.toml
+++ b/examples/stm32l5/Cargo.toml
@@ -26,5 +26,5 @@ embedded-hal = "0.2.6"
26futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 26futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
27heapless = { version = "0.7.5", default-features = false } 27heapless = { version = "0.7.5", default-features = false }
28rand_core = { version = "0.6.3", default-features = false } 28rand_core = { version = "0.6.3", default-features = false }
29embedded-io = { version = "0.3.0", features = ["async"] } 29embedded-io = { version = "0.3.1", features = ["async"] }
30static_cell = "1.0" 30static_cell = "1.0"
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
index 1ec19e58b..c05aac3fc 100644
--- a/rust-toolchain.toml
+++ b/rust-toolchain.toml
@@ -1,7 +1,7 @@
1# Before upgrading check that everything is available on all tier1 targets here: 1# Before upgrading check that everything is available on all tier1 targets here:
2# https://rust-lang.github.io/rustup-components-history 2# https://rust-lang.github.io/rustup-components-history
3[toolchain] 3[toolchain]
4channel = "nightly-2022-09-22" 4channel = "nightly-2022-10-25"
5components = [ "rust-src", "rustfmt" ] 5components = [ "rust-src", "rustfmt" ]
6targets = [ 6targets = [
7 "thumbv7em-none-eabi", 7 "thumbv7em-none-eabi",
diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml
index 48c88e85b..069b7fb8c 100644
--- a/tests/rp/Cargo.toml
+++ b/tests/rp/Cargo.toml
@@ -18,10 +18,10 @@ cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
18cortex-m-rt = "0.7.0" 18cortex-m-rt = "0.7.0"
19embedded-hal = "0.2.6" 19embedded-hal = "0.2.6"
20embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9" } 20embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9" }
21embedded-hal-async = { version = "=0.1.0-alpha.2" } 21embedded-hal-async = { version = "=0.1.0-alpha.3" }
22panic-probe = { version = "0.3.0", features = ["print-defmt"] } 22panic-probe = { version = "0.3.0", features = ["print-defmt"] }
23futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 23futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
24embedded-io = { version = "0.3.0", features = ["async"] } 24embedded-io = { version = "0.3.1", features = ["async"] }
25embedded-storage = { version = "0.3" } 25embedded-storage = { version = "0.3" }
26 26
27[profile.dev] 27[profile.dev]
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml
index bebbf557e..602c1fb57 100644
--- a/tests/stm32/Cargo.toml
+++ b/tests/stm32/Cargo.toml
@@ -26,7 +26,7 @@ cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
26cortex-m-rt = "0.7.0" 26cortex-m-rt = "0.7.0"
27embedded-hal = "0.2.6" 27embedded-hal = "0.2.6"
28embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9" } 28embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.9" }
29embedded-hal-async = { version = "=0.1.0-alpha.2" } 29embedded-hal-async = { version = "=0.1.0-alpha.3" }
30panic-probe = { version = "0.3.0", features = ["print-defmt"] } 30panic-probe = { version = "0.3.0", features = ["print-defmt"] }
31 31
32[profile.dev] 32[profile.dev]
diff --git a/tests/stm32/src/bin/usart.rs b/tests/stm32/src/bin/usart.rs
index 7673bfe6d..af55867f2 100644
--- a/tests/stm32/src/bin/usart.rs
+++ b/tests/stm32/src/bin/usart.rs
@@ -7,6 +7,7 @@ mod example_common;
7use defmt::assert_eq; 7use defmt::assert_eq;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::dma::NoDma; 9use embassy_stm32::dma::NoDma;
10use embassy_stm32::interrupt;
10use embassy_stm32::usart::{Config, Uart}; 11use embassy_stm32::usart::{Config, Uart};
11use example_common::*; 12use example_common::*;
12 13
@@ -18,22 +19,22 @@ async fn main(_spawner: Spawner) {
18 // Arduino pins D0 and D1 19 // Arduino pins D0 and D1
19 // They're connected together with a 1K resistor. 20 // They're connected together with a 1K resistor.
20 #[cfg(feature = "stm32f103c8")] 21 #[cfg(feature = "stm32f103c8")]
21 let (tx, rx, usart) = (p.PA9, p.PA10, p.USART1); 22 let (tx, rx, usart, irq) = (p.PA9, p.PA10, p.USART1, interrupt::take!(USART1));
22 #[cfg(feature = "stm32g491re")] 23 #[cfg(feature = "stm32g491re")]
23 let (tx, rx, usart) = (p.PC4, p.PC5, p.USART1); 24 let (tx, rx, usart, irq) = (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1));
24 #[cfg(feature = "stm32g071rb")] 25 #[cfg(feature = "stm32g071rb")]
25 let (tx, rx, usart) = (p.PC4, p.PC5, p.USART1); 26 let (tx, rx, usart, irq) = (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1));
26 #[cfg(feature = "stm32f429zi")] 27 #[cfg(feature = "stm32f429zi")]
27 let (tx, rx, usart) = (p.PG14, p.PG9, p.USART6); 28 let (tx, rx, usart, irq) = (p.PG14, p.PG9, p.USART6, interrupt::take!(USART6));
28 #[cfg(feature = "stm32wb55rg")] 29 #[cfg(feature = "stm32wb55rg")]
29 let (tx, rx, usart) = (p.PA2, p.PA3, p.LPUART1); 30 let (tx, rx, usart, irq) = (p.PA2, p.PA3, p.LPUART1, interrupt::take!(LPUART1));
30 #[cfg(feature = "stm32h755zi")] 31 #[cfg(feature = "stm32h755zi")]
31 let (tx, rx, usart) = (p.PB6, p.PB7, p.USART1); 32 let (tx, rx, usart, irq) = (p.PB6, p.PB7, p.USART1, interrupt::take!(USART1));
32 #[cfg(feature = "stm32u585ai")] 33 #[cfg(feature = "stm32u585ai")]
33 let (tx, rx, usart) = (p.PD8, p.PD9, p.USART3); 34 let (tx, rx, usart, irq) = (p.PD8, p.PD9, p.USART3, interrupt::take!(USART3));
34 35
35 let config = Config::default(); 36 let config = Config::default();
36 let mut usart = Uart::new(usart, rx, tx, NoDma, NoDma, config); 37 let mut usart = Uart::new(usart, rx, tx, irq, NoDma, NoDma, config);
37 38
38 // We can't send too many bytes, they have to fit in the FIFO. 39 // We can't send too many bytes, they have to fit in the FIFO.
39 // This is because we aren't sending+receiving at the same time. 40 // This is because we aren't sending+receiving at the same time.
diff --git a/tests/stm32/src/bin/usart_dma.rs b/tests/stm32/src/bin/usart_dma.rs
index e0389446f..d12605a9a 100644
--- a/tests/stm32/src/bin/usart_dma.rs
+++ b/tests/stm32/src/bin/usart_dma.rs
@@ -6,6 +6,7 @@
6mod example_common; 6mod example_common;
7use defmt::assert_eq; 7use defmt::assert_eq;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::interrupt;
9use embassy_stm32::usart::{Config, Uart}; 10use embassy_stm32::usart::{Config, Uart};
10use example_common::*; 11use example_common::*;
11 12
@@ -17,22 +18,53 @@ async fn main(_spawner: Spawner) {
17 // Arduino pins D0 and D1 18 // Arduino pins D0 and D1
18 // They're connected together with a 1K resistor. 19 // They're connected together with a 1K resistor.
19 #[cfg(feature = "stm32f103c8")] 20 #[cfg(feature = "stm32f103c8")]
20 let (tx, rx, usart, tx_dma, rx_dma) = (p.PA9, p.PA10, p.USART1, p.DMA1_CH4, p.DMA1_CH5); 21 let (tx, rx, usart, irq, tx_dma, rx_dma) = (
22 p.PA9,
23 p.PA10,
24 p.USART1,
25 interrupt::take!(USART1),
26 p.DMA1_CH4,
27 p.DMA1_CH5,
28 );
21 #[cfg(feature = "stm32g491re")] 29 #[cfg(feature = "stm32g491re")]
22 let (tx, rx, usart, tx_dma, rx_dma) = (p.PC4, p.PC5, p.USART1, p.DMA1_CH1, p.DMA1_CH2); 30 let (tx, rx, usart, irq, tx_dma, rx_dma) =
31 (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1), p.DMA1_CH1, p.DMA1_CH2);
23 #[cfg(feature = "stm32g071rb")] 32 #[cfg(feature = "stm32g071rb")]
24 let (tx, rx, usart, tx_dma, rx_dma) = (p.PC4, p.PC5, p.USART1, p.DMA1_CH1, p.DMA1_CH2); 33 let (tx, rx, usart, irq, tx_dma, rx_dma) =
34 (p.PC4, p.PC5, p.USART1, interrupt::take!(USART1), p.DMA1_CH1, p.DMA1_CH2);
25 #[cfg(feature = "stm32f429zi")] 35 #[cfg(feature = "stm32f429zi")]
26 let (tx, rx, usart, tx_dma, rx_dma) = (p.PG14, p.PG9, p.USART6, p.DMA2_CH6, p.DMA2_CH1); 36 let (tx, rx, usart, irq, tx_dma, rx_dma) = (
37 p.PG14,
38 p.PG9,
39 p.USART6,
40 interrupt::take!(USART6),
41 p.DMA2_CH6,
42 p.DMA2_CH1,
43 );
27 #[cfg(feature = "stm32wb55rg")] 44 #[cfg(feature = "stm32wb55rg")]
28 let (tx, rx, usart, tx_dma, rx_dma) = (p.PA2, p.PA3, p.LPUART1, p.DMA1_CH1, p.DMA1_CH2); 45 let (tx, rx, usart, irq, tx_dma, rx_dma) = (
46 p.PA2,
47 p.PA3,
48 p.LPUART1,
49 interrupt::take!(LPUART1),
50 p.DMA1_CH1,
51 p.DMA1_CH2,
52 );
29 #[cfg(feature = "stm32h755zi")] 53 #[cfg(feature = "stm32h755zi")]
30 let (tx, rx, usart, tx_dma, rx_dma) = (p.PB6, p.PB7, p.USART1, p.DMA1_CH0, p.DMA1_CH1); 54 let (tx, rx, usart, irq, tx_dma, rx_dma) =
55 (p.PB6, p.PB7, p.USART1, interrupt::take!(USART1), p.DMA1_CH0, p.DMA1_CH1);
31 #[cfg(feature = "stm32u585ai")] 56 #[cfg(feature = "stm32u585ai")]
32 let (tx, rx, usart, tx_dma, rx_dma) = (p.PD8, p.PD9, p.USART3, p.GPDMA1_CH0, p.GPDMA1_CH1); 57 let (tx, rx, usart, irq, tx_dma, rx_dma) = (
58 p.PD8,
59 p.PD9,
60 p.USART3,
61 interrupt::take!(USART3),
62 p.GPDMA1_CH0,
63 p.GPDMA1_CH1,
64 );
33 65
34 let config = Config::default(); 66 let config = Config::default();
35 let mut usart = Uart::new(usart, rx, tx, tx_dma, rx_dma, config); 67 let mut usart = Uart::new(usart, rx, tx, irq, tx_dma, rx_dma, config);
36 68
37 // We can't send too many bytes, they have to fit in the FIFO. 69 // We can't send too many bytes, they have to fit in the FIFO.
38 // This is because we aren't sending+receiving at the same time. 70 // This is because we aren't sending+receiving at the same time.