aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorQuentin Smith <[email protected]>2022-08-23 23:01:51 -0400
committerQuentin Smith <[email protected]>2022-08-23 23:01:51 -0400
commit2900ab79e7afa0ca3e0d800f8a91c3253a333db1 (patch)
treea5066235f8b1ac6c2520105db2e5c48630bc006d
parent14eae9ca06f63a69ccc29d5fd9e1dec3848a3e98 (diff)
parent529535194d4b5d58b31fd6a7541176105e3c63f7 (diff)
Merge remote-tracking branch 'origin/master' into nrf-pdm
-rw-r--r--.github/workflows/rust.yml2
-rw-r--r--.vscode/settings.json2
-rw-r--r--embassy-boot/boot/Cargo.toml2
-rw-r--r--embassy-boot/nrf/Cargo.toml2
-rw-r--r--embassy-boot/stm32/Cargo.toml2
-rw-r--r--embassy-cortex-m/Cargo.toml2
-rw-r--r--embassy-cortex-m/src/executor.rs2
-rw-r--r--embassy-embedded-hal/Cargo.toml2
-rw-r--r--embassy-embedded-hal/src/shared_bus/asynch/i2c.rs12
-rw-r--r--embassy-embedded-hal/src/shared_bus/asynch/spi.rs12
-rw-r--r--embassy-embedded-hal/src/shared_bus/blocking/i2c.rs10
-rw-r--r--embassy-embedded-hal/src/shared_bus/blocking/spi.rs10
-rw-r--r--embassy-executor/Cargo.toml9
-rw-r--r--embassy-executor/src/arch/cortex_m.rs2
-rw-r--r--embassy-executor/src/arch/riscv32.rs2
-rw-r--r--embassy-executor/src/arch/std.rs2
-rw-r--r--embassy-executor/src/arch/wasm.rs2
-rw-r--r--embassy-executor/src/arch/xtensa.rs2
-rw-r--r--embassy-executor/src/lib.rs31
-rw-r--r--embassy-executor/src/raw/mod.rs39
-rw-r--r--embassy-futures/Cargo.toml14
-rw-r--r--embassy-futures/README.md9
-rw-r--r--embassy-futures/src/fmt.rs (renamed from embassy-util/src/fmt.rs)0
-rw-r--r--embassy-futures/src/lib.rs12
-rw-r--r--embassy-futures/src/select.rs (renamed from embassy-util/src/select.rs)0
-rw-r--r--embassy-futures/src/yield_now.rs (renamed from embassy-util/src/yield_now.rs)0
-rw-r--r--embassy-lora/Cargo.toml2
-rw-r--r--embassy-lora/src/stm32wl/mod.rs2
-rw-r--r--embassy-macros/src/macros/cortex_m_interrupt_take.rs8
-rw-r--r--embassy-macros/src/macros/main.rs4
-rw-r--r--embassy-net/Cargo.toml2
-rw-r--r--embassy-net/src/stack.rs2
-rw-r--r--embassy-nrf/Cargo.toml4
-rw-r--r--embassy-nrf/src/buffered_uarte.rs11
-rw-r--r--embassy-nrf/src/gpio.rs21
-rw-r--r--embassy-nrf/src/gpiote.rs2
-rw-r--r--embassy-nrf/src/nvmc.rs10
-rw-r--r--embassy-nrf/src/ppi/mod.rs47
-rw-r--r--embassy-nrf/src/ppi/ppi.rs3
-rw-r--r--embassy-nrf/src/qdec.rs2
-rw-r--r--embassy-nrf/src/qspi.rs2
-rw-r--r--embassy-nrf/src/rng.rs2
-rw-r--r--embassy-nrf/src/saadc.rs2
-rw-r--r--embassy-nrf/src/spim.rs2
-rw-r--r--embassy-nrf/src/temp.rs2
-rw-r--r--embassy-nrf/src/time_driver.rs4
-rw-r--r--embassy-nrf/src/timer.rs6
-rw-r--r--embassy-nrf/src/twim.rs2
-rw-r--r--embassy-nrf/src/uarte.rs2
-rw-r--r--embassy-nrf/src/usb.rs2
-rw-r--r--embassy-rp/Cargo.toml4
-rw-r--r--embassy-rp/src/gpio.rs4
-rw-r--r--embassy-rp/src/timer.rs4
-rw-r--r--embassy-stm32/Cargo.toml4
-rw-r--r--embassy-stm32/src/dcmi.rs2
-rw-r--r--embassy-stm32/src/dma/bdma.rs2
-rw-r--r--embassy-stm32/src/dma/dma.rs2
-rw-r--r--embassy-stm32/src/dma/gpdma.rs2
-rw-r--r--embassy-stm32/src/eth/v1/mod.rs2
-rw-r--r--embassy-stm32/src/eth/v2/mod.rs2
-rw-r--r--embassy-stm32/src/exti.rs2
-rw-r--r--embassy-stm32/src/i2c/v2.rs2
-rw-r--r--embassy-stm32/src/rng.rs2
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs6
-rw-r--r--embassy-stm32/src/time_driver.rs4
-rw-r--r--embassy-stm32/src/usart/buffered.rs2
-rw-r--r--embassy-stm32/src/usb/usb.rs2
-rw-r--r--embassy-sync/Cargo.toml (renamed from embassy-util/Cargo.toml)7
-rw-r--r--embassy-sync/README.md12
-rw-r--r--embassy-sync/build.rs (renamed from embassy-util/build.rs)0
-rw-r--r--embassy-sync/src/blocking_mutex/mod.rs (renamed from embassy-util/src/blocking_mutex/mod.rs)0
-rw-r--r--embassy-sync/src/blocking_mutex/raw.rs (renamed from embassy-util/src/blocking_mutex/raw.rs)0
-rw-r--r--embassy-sync/src/channel.rs (renamed from embassy-util/src/channel/mpmc.rs)14
-rw-r--r--embassy-sync/src/fmt.rs228
-rw-r--r--embassy-sync/src/lib.rs (renamed from embassy-util/src/lib.rs)12
-rw-r--r--embassy-sync/src/mutex.rs (renamed from embassy-util/src/mutex.rs)0
-rw-r--r--embassy-sync/src/pipe.rs (renamed from embassy-util/src/pipe.rs)10
-rw-r--r--embassy-sync/src/pubsub/mod.rs (renamed from embassy-util/src/channel/pubsub/mod.rs)6
-rw-r--r--embassy-sync/src/pubsub/publisher.rs (renamed from embassy-util/src/channel/pubsub/publisher.rs)0
-rw-r--r--embassy-sync/src/pubsub/subscriber.rs (renamed from embassy-util/src/channel/pubsub/subscriber.rs)0
-rw-r--r--embassy-sync/src/ring_buffer.rs (renamed from embassy-util/src/ring_buffer.rs)0
-rw-r--r--embassy-sync/src/signal.rs (renamed from embassy-util/src/channel/signal.rs)6
-rw-r--r--embassy-sync/src/waitqueue/mod.rs (renamed from embassy-util/src/waitqueue/mod.rs)0
-rw-r--r--embassy-sync/src/waitqueue/multi_waker.rs (renamed from embassy-util/src/waitqueue/multi_waker.rs)0
-rw-r--r--embassy-sync/src/waitqueue/waker.rs (renamed from embassy-util/src/waitqueue/waker.rs)0
-rw-r--r--embassy-time/Cargo.toml2
-rw-r--r--embassy-time/README.md43
-rw-r--r--embassy-time/src/driver.rs2
-rw-r--r--embassy-time/src/lib.rs43
-rw-r--r--embassy-usb-hid/Cargo.toml2
-rw-r--r--embassy-usb-ncm/Cargo.toml2
-rw-r--r--embassy-usb-serial/Cargo.toml2
-rw-r--r--embassy-usb-serial/src/lib.rs2
-rw-r--r--embassy-usb/Cargo.toml2
-rw-r--r--embassy-usb/src/builder.rs2
-rw-r--r--embassy-usb/src/control.rs3
-rw-r--r--embassy-usb/src/driver.rs6
-rw-r--r--embassy-usb/src/lib.rs2
-rw-r--r--embassy-util/src/channel/mod.rs5
-rw-r--r--embassy-util/src/forever.rs95
-rw-r--r--examples/boot/application/nrf/Cargo.toml2
-rw-r--r--examples/boot/application/stm32f3/Cargo.toml2
-rw-r--r--examples/boot/application/stm32f7/Cargo.toml2
-rw-r--r--examples/boot/application/stm32h7/Cargo.toml2
-rw-r--r--examples/boot/application/stm32l0/Cargo.toml2
-rw-r--r--examples/boot/application/stm32l1/Cargo.toml2
-rw-r--r--examples/boot/application/stm32l4/Cargo.toml2
-rw-r--r--examples/boot/application/stm32wl/Cargo.toml2
-rw-r--r--examples/nrf-rtos-trace/.cargo/config.toml9
-rw-r--r--examples/nrf-rtos-trace/Cargo.toml35
-rw-r--r--examples/nrf-rtos-trace/build.rs36
-rw-r--r--examples/nrf-rtos-trace/memory.x7
-rw-r--r--examples/nrf-rtos-trace/src/bin/rtos_trace.rs69
-rw-r--r--examples/nrf/Cargo.toml4
-rw-r--r--examples/nrf/src/bin/channel.rs4
-rw-r--r--examples/nrf/src/bin/channel_sender_receiver.rs10
-rw-r--r--examples/nrf/src/bin/multiprio.rs14
-rw-r--r--examples/nrf/src/bin/mutex.rs4
-rw-r--r--examples/nrf/src/bin/pubsub.rs4
-rw-r--r--examples/nrf/src/bin/raw_spawn.rs6
-rw-r--r--examples/nrf/src/bin/uart_split.rs4
-rw-r--r--examples/nrf/src/bin/usb_ethernet.rs18
-rw-r--r--examples/nrf/src/bin/usb_hid_keyboard.rs4
-rw-r--r--examples/nrf/src/bin/usb_serial_multitask.rs6
-rw-r--r--examples/rp/Cargo.toml2
-rw-r--r--examples/std/Cargo.toml3
-rw-r--r--examples/std/src/bin/net.rs16
-rw-r--r--examples/std/src/bin/net_udp.rs16
-rw-r--r--examples/std/src/bin/serial.rs6
-rw-r--r--examples/stm32f0/Cargo.toml2
-rw-r--r--examples/stm32f1/Cargo.toml2
-rw-r--r--examples/stm32f2/Cargo.toml2
-rw-r--r--examples/stm32f3/Cargo.toml3
-rw-r--r--examples/stm32f3/src/bin/button_events.rs4
-rw-r--r--examples/stm32f3/src/bin/multiprio.rs14
-rw-r--r--examples/stm32f4/Cargo.toml3
-rw-r--r--examples/stm32f4/src/bin/multiprio.rs14
-rw-r--r--examples/stm32f7/Cargo.toml3
-rw-r--r--examples/stm32f7/src/bin/eth.rs14
-rw-r--r--examples/stm32g0/Cargo.toml2
-rw-r--r--examples/stm32g4/Cargo.toml2
-rw-r--r--examples/stm32h7/Cargo.toml3
-rw-r--r--examples/stm32h7/src/bin/eth.rs14
-rw-r--r--examples/stm32h7/src/bin/eth_client.rs14
-rw-r--r--examples/stm32h7/src/bin/signal.rs2
-rw-r--r--examples/stm32h7/src/bin/spi.rs6
-rw-r--r--examples/stm32h7/src/bin/spi_dma.rs6
-rw-r--r--examples/stm32h7/src/bin/usart.rs6
-rw-r--r--examples/stm32h7/src/bin/usart_dma.rs6
-rw-r--r--examples/stm32h7/src/bin/usart_split.rs4
-rw-r--r--examples/stm32l0/Cargo.toml3
-rw-r--r--examples/stm32l0/src/bin/raw_spawn.rs6
-rw-r--r--examples/stm32l1/Cargo.toml2
-rw-r--r--examples/stm32l4/Cargo.toml2
-rw-r--r--examples/stm32l5/Cargo.toml3
-rw-r--r--examples/stm32l5/src/bin/usb_ethernet.rs18
-rw-r--r--examples/stm32u5/Cargo.toml2
-rw-r--r--examples/stm32wb/Cargo.toml2
-rw-r--r--examples/stm32wl/Cargo.toml2
-rw-r--r--examples/stm32wl/src/bin/subghz.rs2
-rw-r--r--examples/wasm/Cargo.toml4
-rw-r--r--examples/wasm/README.md2
-rw-r--r--tests/rp/Cargo.toml2
-rw-r--r--tests/stm32/Cargo.toml2
164 files changed, 923 insertions, 434 deletions
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index d76e5ced4..d2e8e316b 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -69,4 +69,4 @@ jobs:
69 steps: 69 steps:
70 - uses: actions/checkout@v2 70 - uses: actions/checkout@v2
71 - name: Test 71 - name: Test
72 run: cd embassy-util && cargo test 72 run: cd embassy-sync && cargo test
diff --git a/.vscode/settings.json b/.vscode/settings.json
index d6ce75c99..5e9e51799 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -18,7 +18,7 @@
18 "rust-analyzer.linkedProjects": [ 18 "rust-analyzer.linkedProjects": [
19 // Declare for the target you wish to develop 19 // Declare for the target you wish to develop
20 //"embassy-executor/Cargo.toml", 20 //"embassy-executor/Cargo.toml",
21 //"embassy-util/Cargo.toml", 21 //"embassy-sync/Cargo.toml",
22 "examples/nrf/Cargo.toml", 22 "examples/nrf/Cargo.toml",
23 // "examples/rp/Cargo.toml", 23 // "examples/rp/Cargo.toml",
24 // "examples/std/Cargo.toml", 24 // "examples/std/Cargo.toml",
diff --git a/embassy-boot/boot/Cargo.toml b/embassy-boot/boot/Cargo.toml
index 9c2e72be5..a42f88688 100644
--- a/embassy-boot/boot/Cargo.toml
+++ b/embassy-boot/boot/Cargo.toml
@@ -14,7 +14,7 @@ target = "thumbv7em-none-eabi"
14[dependencies] 14[dependencies]
15defmt = { version = "0.3", optional = true } 15defmt = { version = "0.3", optional = true }
16log = { version = "0.4", optional = true } 16log = { version = "0.4", optional = true }
17embassy-util = { version = "0.1.0", path = "../../embassy-util" } 17embassy-sync = { version = "0.1.0", path = "../../embassy-sync" }
18embedded-storage = "0.3.0" 18embedded-storage = "0.3.0"
19embedded-storage-async = "0.3.0" 19embedded-storage-async = "0.3.0"
20 20
diff --git a/embassy-boot/nrf/Cargo.toml b/embassy-boot/nrf/Cargo.toml
index b06e8102c..234393e7c 100644
--- a/embassy-boot/nrf/Cargo.toml
+++ b/embassy-boot/nrf/Cargo.toml
@@ -15,7 +15,7 @@ target = "thumbv7em-none-eabi"
15[dependencies] 15[dependencies]
16defmt = { version = "0.3", optional = true } 16defmt = { version = "0.3", optional = true }
17 17
18embassy-util = { path = "../../embassy-util" } 18embassy-sync = { path = "../../embassy-sync" }
19embassy-nrf = { path = "../../embassy-nrf", default-features = false, features = ["nightly"] } 19embassy-nrf = { path = "../../embassy-nrf", default-features = false, features = ["nightly"] }
20embassy-boot = { path = "../boot", default-features = false } 20embassy-boot = { path = "../boot", default-features = false }
21cortex-m = { version = "0.7.6" } 21cortex-m = { version = "0.7.6" }
diff --git a/embassy-boot/stm32/Cargo.toml b/embassy-boot/stm32/Cargo.toml
index d8f492531..ad4657e0d 100644
--- a/embassy-boot/stm32/Cargo.toml
+++ b/embassy-boot/stm32/Cargo.toml
@@ -17,7 +17,7 @@ defmt = { version = "0.3", optional = true }
17defmt-rtt = { version = "0.3", optional = true } 17defmt-rtt = { version = "0.3", optional = true }
18log = { version = "0.4", optional = true } 18log = { version = "0.4", optional = true }
19 19
20embassy-util = { path = "../../embassy-util" } 20embassy-sync = { path = "../../embassy-sync" }
21embassy-stm32 = { path = "../../embassy-stm32", default-features = false, features = ["nightly"] } 21embassy-stm32 = { path = "../../embassy-stm32", default-features = false, features = ["nightly"] }
22embassy-boot = { path = "../boot", default-features = false } 22embassy-boot = { path = "../boot", default-features = false }
23cortex-m = { version = "0.7.6" } 23cortex-m = { version = "0.7.6" }
diff --git a/embassy-cortex-m/Cargo.toml b/embassy-cortex-m/Cargo.toml
index 1f16da31b..7efced669 100644
--- a/embassy-cortex-m/Cargo.toml
+++ b/embassy-cortex-m/Cargo.toml
@@ -35,7 +35,7 @@ prio-bits-8 = []
35defmt = { version = "0.3", optional = true } 35defmt = { version = "0.3", optional = true }
36log = { version = "0.4.14", optional = true } 36log = { version = "0.4.14", optional = true }
37 37
38embassy-util = { version = "0.1.0", path = "../embassy-util" } 38embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
39embassy-executor = { version = "0.1.0", path = "../embassy-executor"} 39embassy-executor = { version = "0.1.0", path = "../embassy-executor"}
40embassy-macros = { version = "0.1.0", path = "../embassy-macros"} 40embassy-macros = { version = "0.1.0", path = "../embassy-macros"}
41embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common"} 41embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common"}
diff --git a/embassy-cortex-m/src/executor.rs b/embassy-cortex-m/src/executor.rs
index 80c452f84..0d1745d8a 100644
--- a/embassy-cortex-m/src/executor.rs
+++ b/embassy-cortex-m/src/executor.rs
@@ -71,7 +71,7 @@ impl<I: Interrupt> InterruptExecutor<I> {
71 /// Executor instance in a place where it'll live forever and grants you mutable 71 /// Executor instance in a place where it'll live forever and grants you mutable
72 /// access. There's a few ways to do this: 72 /// access. There's a few ways to do this:
73 /// 73 ///
74 /// - a [Forever](embassy_util::Forever) (safe) 74 /// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe)
75 /// - a `static mut` (unsafe) 75 /// - a `static mut` (unsafe)
76 /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe) 76 /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe)
77 pub fn start(&'static mut self) -> SendSpawner { 77 pub fn start(&'static mut self) -> SendSpawner {
diff --git a/embassy-embedded-hal/Cargo.toml b/embassy-embedded-hal/Cargo.toml
index 866666871..462680720 100644
--- a/embassy-embedded-hal/Cargo.toml
+++ b/embassy-embedded-hal/Cargo.toml
@@ -16,7 +16,7 @@ std = []
16nightly = ["embedded-hal-async", "embedded-storage-async"] 16nightly = ["embedded-hal-async", "embedded-storage-async"]
17 17
18[dependencies] 18[dependencies]
19embassy-util = { version = "0.1.0", path = "../embassy-util" } 19embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
20embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } 20embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
21embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.8" } 21embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.8" }
22embedded-hal-async = { version = "0.1.0-alpha.1", optional = true } 22embedded-hal-async = { version = "0.1.0-alpha.1", optional = true }
diff --git a/embassy-embedded-hal/src/shared_bus/asynch/i2c.rs b/embassy-embedded-hal/src/shared_bus/asynch/i2c.rs
index bd023fb6a..0bc6afd98 100644
--- a/embassy-embedded-hal/src/shared_bus/asynch/i2c.rs
+++ b/embassy-embedded-hal/src/shared_bus/asynch/i2c.rs
@@ -4,15 +4,15 @@
4//! 4//!
5//! ```rust 5//! ```rust
6//! use embassy_embedded_hal::shared_bus::i2c::I2cDevice; 6//! use embassy_embedded_hal::shared_bus::i2c::I2cDevice;
7//! use embassy_util::mutex::Mutex; 7//! use embassy_sync::mutex::Mutex;
8//! use embassy_util::blocking_mutex::raw::ThreadModeRawMutex; 8//! use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
9//! 9//!
10//! static I2C_BUS: Forever<Mutex::<ThreadModeRawMutex, Twim<TWISPI0>>> = Forever::new(); 10//! static I2C_BUS: StaticCell<Mutex::<ThreadModeRawMutex, Twim<TWISPI0>>> = StaticCell::new();
11//! let config = twim::Config::default(); 11//! let config = twim::Config::default();
12//! let irq = interrupt::take!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); 12//! let irq = interrupt::take!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
13//! let i2c = Twim::new(p.TWISPI0, irq, p.P0_03, p.P0_04, config); 13//! let i2c = Twim::new(p.TWISPI0, irq, p.P0_03, p.P0_04, config);
14//! let i2c_bus = Mutex::<ThreadModeRawMutex, _>::new(i2c); 14//! let i2c_bus = Mutex::<ThreadModeRawMutex, _>::new(i2c);
15//! let i2c_bus = I2C_BUS.put(i2c_bus); 15//! let i2c_bus = I2C_BUS.init(i2c_bus);
16//! 16//!
17//! // Device 1, using embedded-hal-async compatible driver for QMC5883L compass 17//! // Device 1, using embedded-hal-async compatible driver for QMC5883L compass
18//! let i2c_dev1 = I2cDevice::new(i2c_bus); 18//! let i2c_dev1 = I2cDevice::new(i2c_bus);
@@ -24,8 +24,8 @@
24//! ``` 24//! ```
25use core::future::Future; 25use core::future::Future;
26 26
27use embassy_util::blocking_mutex::raw::RawMutex; 27use embassy_sync::blocking_mutex::raw::RawMutex;
28use embassy_util::mutex::Mutex; 28use embassy_sync::mutex::Mutex;
29use embedded_hal_async::i2c; 29use embedded_hal_async::i2c;
30 30
31use crate::shared_bus::I2cDeviceError; 31use crate::shared_bus::I2cDeviceError;
diff --git a/embassy-embedded-hal/src/shared_bus/asynch/spi.rs b/embassy-embedded-hal/src/shared_bus/asynch/spi.rs
index caa37f6f3..c95b59ef0 100644
--- a/embassy-embedded-hal/src/shared_bus/asynch/spi.rs
+++ b/embassy-embedded-hal/src/shared_bus/asynch/spi.rs
@@ -4,16 +4,16 @@
4//! 4//!
5//! ```rust 5//! ```rust
6//! use embassy_embedded_hal::shared_bus::spi::SpiDevice; 6//! use embassy_embedded_hal::shared_bus::spi::SpiDevice;
7//! use embassy_util::mutex::Mutex; 7//! use embassy_sync::mutex::Mutex;
8//! use embassy_util::blocking_mutex::raw::ThreadModeRawMutex; 8//! use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
9//! 9//!
10//! static SPI_BUS: Forever<Mutex<ThreadModeRawMutex, spim::Spim<SPI3>>> = Forever::new(); 10//! static SPI_BUS: StaticCell<Mutex<ThreadModeRawMutex, spim::Spim<SPI3>>> = StaticCell::new();
11//! let mut config = spim::Config::default(); 11//! let mut config = spim::Config::default();
12//! config.frequency = spim::Frequency::M32; 12//! config.frequency = spim::Frequency::M32;
13//! let irq = interrupt::take!(SPIM3); 13//! let irq = interrupt::take!(SPIM3);
14//! let spi = spim::Spim::new_txonly(p.SPI3, irq, p.P0_15, p.P0_18, config); 14//! let spi = spim::Spim::new_txonly(p.SPI3, irq, p.P0_15, p.P0_18, config);
15//! let spi_bus = Mutex::<ThreadModeRawMutex, _>::new(spi); 15//! let spi_bus = Mutex::<ThreadModeRawMutex, _>::new(spi);
16//! let spi_bus = SPI_BUS.put(spi_bus); 16//! let spi_bus = SPI_BUS.init(spi_bus);
17//! 17//!
18//! // Device 1, using embedded-hal-async compatible driver for ST7735 LCD display 18//! // Device 1, using embedded-hal-async compatible driver for ST7735 LCD display
19//! let cs_pin1 = Output::new(p.P0_24, Level::Low, OutputDrive::Standard); 19//! let cs_pin1 = Output::new(p.P0_24, Level::Low, OutputDrive::Standard);
@@ -27,8 +27,8 @@
27//! ``` 27//! ```
28use core::future::Future; 28use core::future::Future;
29 29
30use embassy_util::blocking_mutex::raw::RawMutex; 30use embassy_sync::blocking_mutex::raw::RawMutex;
31use embassy_util::mutex::Mutex; 31use embassy_sync::mutex::Mutex;
32use embedded_hal_1::digital::blocking::OutputPin; 32use embedded_hal_1::digital::blocking::OutputPin;
33use embedded_hal_1::spi::ErrorType; 33use embedded_hal_1::spi::ErrorType;
34use embedded_hal_async::spi; 34use embedded_hal_async::spi;
diff --git a/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs b/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs
index 1fc343d15..a611e2d27 100644
--- a/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs
+++ b/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs
@@ -4,13 +4,13 @@
4//! 4//!
5//! ```rust 5//! ```rust
6//! use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice; 6//! use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
7//! use embassy_util::blocking_mutex::{NoopMutex, raw::NoopRawMutex}; 7//! use embassy_sync::blocking_mutex::{NoopMutex, raw::NoopRawMutex};
8//! 8//!
9//! static I2C_BUS: Forever<NoopMutex<RefCell<Twim<TWISPI0>>>> = Forever::new(); 9//! static I2C_BUS: StaticCell<NoopMutex<RefCell<Twim<TWISPI0>>>> = StaticCell::new();
10//! let irq = interrupt::take!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); 10//! let irq = interrupt::take!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
11//! let i2c = Twim::new(p.TWISPI0, irq, p.P0_03, p.P0_04, Config::default()); 11//! let i2c = Twim::new(p.TWISPI0, irq, p.P0_03, p.P0_04, Config::default());
12//! let i2c_bus = NoopMutex::new(RefCell::new(i2c)); 12//! let i2c_bus = NoopMutex::new(RefCell::new(i2c));
13//! let i2c_bus = I2C_BUS.put(i2c_bus); 13//! let i2c_bus = I2C_BUS.init(i2c_bus);
14//! 14//!
15//! let i2c_dev1 = I2cDevice::new(i2c_bus); 15//! let i2c_dev1 = I2cDevice::new(i2c_bus);
16//! let mpu = Mpu6050::new(i2c_dev1); 16//! let mpu = Mpu6050::new(i2c_dev1);
@@ -18,8 +18,8 @@
18 18
19use core::cell::RefCell; 19use core::cell::RefCell;
20 20
21use embassy_util::blocking_mutex::raw::RawMutex; 21use embassy_sync::blocking_mutex::raw::RawMutex;
22use embassy_util::blocking_mutex::Mutex; 22use embassy_sync::blocking_mutex::Mutex;
23use embedded_hal_1::i2c::blocking::{I2c, Operation}; 23use embedded_hal_1::i2c::blocking::{I2c, Operation};
24use embedded_hal_1::i2c::ErrorType; 24use embedded_hal_1::i2c::ErrorType;
25 25
diff --git a/embassy-embedded-hal/src/shared_bus/blocking/spi.rs b/embassy-embedded-hal/src/shared_bus/blocking/spi.rs
index a61326594..23845d887 100644
--- a/embassy-embedded-hal/src/shared_bus/blocking/spi.rs
+++ b/embassy-embedded-hal/src/shared_bus/blocking/spi.rs
@@ -4,13 +4,13 @@
4//! 4//!
5//! ```rust 5//! ```rust
6//! use embassy_embedded_hal::shared_bus::blocking::spi::SpiDevice; 6//! use embassy_embedded_hal::shared_bus::blocking::spi::SpiDevice;
7//! use embassy_util::blocking_mutex::{NoopMutex, raw::NoopRawMutex}; 7//! use embassy_sync::blocking_mutex::{NoopMutex, raw::NoopRawMutex};
8//! 8//!
9//! static SPI_BUS: Forever<NoopMutex<RefCell<Spim<SPI3>>>> = Forever::new(); 9//! static SPI_BUS: StaticCell<NoopMutex<RefCell<Spim<SPI3>>>> = StaticCell::new();
10//! let irq = interrupt::take!(SPIM3); 10//! let irq = interrupt::take!(SPIM3);
11//! let spi = Spim::new_txonly(p.SPI3, irq, p.P0_15, p.P0_18, Config::default()); 11//! let spi = Spim::new_txonly(p.SPI3, irq, p.P0_15, p.P0_18, Config::default());
12//! let spi_bus = NoopMutex::new(RefCell::new(spi)); 12//! let spi_bus = NoopMutex::new(RefCell::new(spi));
13//! let spi_bus = SPI_BUS.put(spi_bus); 13//! let spi_bus = SPI_BUS.init(spi_bus);
14//! 14//!
15//! // Device 1, using embedded-hal compatible driver for ST7735 LCD display 15//! // Device 1, using embedded-hal compatible driver for ST7735 LCD display
16//! let cs_pin1 = Output::new(p.P0_24, Level::Low, OutputDrive::Standard); 16//! let cs_pin1 = Output::new(p.P0_24, Level::Low, OutputDrive::Standard);
@@ -20,8 +20,8 @@
20 20
21use core::cell::RefCell; 21use core::cell::RefCell;
22 22
23use embassy_util::blocking_mutex::raw::RawMutex; 23use embassy_sync::blocking_mutex::raw::RawMutex;
24use embassy_util::blocking_mutex::Mutex; 24use embassy_sync::blocking_mutex::Mutex;
25use embedded_hal_1::digital::blocking::OutputPin; 25use embedded_hal_1::digital::blocking::OutputPin;
26use embedded_hal_1::spi; 26use embedded_hal_1::spi;
27use embedded_hal_1::spi::blocking::SpiBusFlush; 27use embedded_hal_1::spi::blocking::SpiBusFlush;
diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml
index 25c3f0abd..1a611720c 100644
--- a/embassy-executor/Cargo.toml
+++ b/embassy-executor/Cargo.toml
@@ -30,9 +30,13 @@ nightly = []
30 30
31integrated-timers = ["dep:embassy-time"] 31integrated-timers = ["dep:embassy-time"]
32 32
33# Trace interrupt invocations with rtos-trace.
34rtos-trace-interrupt = ["rtos-trace"]
35
33[dependencies] 36[dependencies]
34defmt = { version = "0.3", optional = true } 37defmt = { version = "0.3", optional = true }
35log = { version = "0.4.14", optional = true } 38log = { version = "0.4.14", optional = true }
39rtos-trace = { version = "0.1.2", optional = true }
36 40
37futures-util = { version = "0.3.17", default-features = false } 41futures-util = { version = "0.3.17", default-features = false }
38embassy-macros = { version = "0.1.0", path = "../embassy-macros"} 42embassy-macros = { version = "0.1.0", path = "../embassy-macros"}
@@ -40,7 +44,8 @@ embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true}
40atomic-polyfill = "1.0.1" 44atomic-polyfill = "1.0.1"
41critical-section = "1.1" 45critical-section = "1.1"
42cfg-if = "1.0.0" 46cfg-if = "1.0.0"
47static_cell = "1.0"
43 48
44# WASM dependencies 49# WASM dependencies
45wasm-bindgen = { version = "0.2.76", features = ["nightly"], optional = true } 50wasm-bindgen = { version = "0.2.82", optional = true }
46js-sys = { version = "0.3", optional = true } \ No newline at end of file 51js-sys = { version = "0.3", optional = true }
diff --git a/embassy-executor/src/arch/cortex_m.rs b/embassy-executor/src/arch/cortex_m.rs
index d6e758dfb..4b27a264e 100644
--- a/embassy-executor/src/arch/cortex_m.rs
+++ b/embassy-executor/src/arch/cortex_m.rs
@@ -41,7 +41,7 @@ impl Executor {
41 /// Executor instance in a place where it'll live forever and grants you mutable 41 /// Executor instance in a place where it'll live forever and grants you mutable
42 /// access. There's a few ways to do this: 42 /// access. There's a few ways to do this:
43 /// 43 ///
44 /// - a [Forever](crate::util::Forever) (safe) 44 /// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe)
45 /// - a `static mut` (unsafe) 45 /// - a `static mut` (unsafe)
46 /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe) 46 /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe)
47 /// 47 ///
diff --git a/embassy-executor/src/arch/riscv32.rs b/embassy-executor/src/arch/riscv32.rs
index 7a7d5698c..2a4b006da 100644
--- a/embassy-executor/src/arch/riscv32.rs
+++ b/embassy-executor/src/arch/riscv32.rs
@@ -43,7 +43,7 @@ impl Executor {
43 /// Executor instance in a place where it'll live forever and grants you mutable 43 /// Executor instance in a place where it'll live forever and grants you mutable
44 /// access. There's a few ways to do this: 44 /// access. There's a few ways to do this:
45 /// 45 ///
46 /// - a [Forever](crate::util::Forever) (safe) 46 /// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe)
47 /// - a `static mut` (unsafe) 47 /// - a `static mut` (unsafe)
48 /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe) 48 /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe)
49 /// 49 ///
diff --git a/embassy-executor/src/arch/std.rs b/embassy-executor/src/arch/std.rs
index b93ab8a79..701f0eb18 100644
--- a/embassy-executor/src/arch/std.rs
+++ b/embassy-executor/src/arch/std.rs
@@ -40,7 +40,7 @@ impl Executor {
40 /// Executor instance in a place where it'll live forever and grants you mutable 40 /// Executor instance in a place where it'll live forever and grants you mutable
41 /// access. There's a few ways to do this: 41 /// access. There's a few ways to do this:
42 /// 42 ///
43 /// - a [Forever](crate::util::Forever) (safe) 43 /// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe)
44 /// - a `static mut` (unsafe) 44 /// - a `static mut` (unsafe)
45 /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe) 45 /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe)
46 /// 46 ///
diff --git a/embassy-executor/src/arch/wasm.rs b/embassy-executor/src/arch/wasm.rs
index 9d5aa31ed..98091cfbb 100644
--- a/embassy-executor/src/arch/wasm.rs
+++ b/embassy-executor/src/arch/wasm.rs
@@ -59,7 +59,7 @@ impl Executor {
59 /// Executor instance in a place where it'll live forever and grants you mutable 59 /// Executor instance in a place where it'll live forever and grants you mutable
60 /// access. There's a few ways to do this: 60 /// access. There's a few ways to do this:
61 /// 61 ///
62 /// - a [Forever](crate::util::Forever) (safe) 62 /// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe)
63 /// - a `static mut` (unsafe) 63 /// - a `static mut` (unsafe)
64 /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe) 64 /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe)
65 pub fn start(&'static mut self, init: impl FnOnce(Spawner)) { 65 pub fn start(&'static mut self, init: impl FnOnce(Spawner)) {
diff --git a/embassy-executor/src/arch/xtensa.rs b/embassy-executor/src/arch/xtensa.rs
index 20bd7b8a5..f908aaa70 100644
--- a/embassy-executor/src/arch/xtensa.rs
+++ b/embassy-executor/src/arch/xtensa.rs
@@ -43,7 +43,7 @@ impl Executor {
43 /// Executor instance in a place where it'll live forever and grants you mutable 43 /// Executor instance in a place where it'll live forever and grants you mutable
44 /// access. There's a few ways to do this: 44 /// access. There's a few ways to do this:
45 /// 45 ///
46 /// - a [Forever](crate::util::Forever) (safe) 46 /// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe)
47 /// - a `static mut` (unsafe) 47 /// - a `static mut` (unsafe)
48 /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe) 48 /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe)
49 /// 49 ///
diff --git a/embassy-executor/src/lib.rs b/embassy-executor/src/lib.rs
index 9328a7378..e4cbd04b9 100644
--- a/embassy-executor/src/lib.rs
+++ b/embassy-executor/src/lib.rs
@@ -38,7 +38,38 @@ cfg_if::cfg_if! {
38 } 38 }
39} 39}
40 40
41#[doc(hidden)]
42/// Implementation details for embassy macros. DO NOT USE.
43pub mod export {
44 #[cfg(feature = "rtos-trace")]
45 pub use rtos_trace::trace;
46
47 /// Expands the given block of code when `embassy-executor` is compiled with
48 /// the `rtos-trace-interrupt` feature.
49 #[doc(hidden)]
50 #[macro_export]
51 #[cfg(feature = "rtos-trace-interrupt")]
52 macro_rules! rtos_trace_interrupt {
53 ($($tt:tt)*) => { $($tt)* };
54 }
55
56 /// Does not expand the given block of code when `embassy-executor` is
57 /// compiled without the `rtos-trace-interrupt` feature.
58 #[doc(hidden)]
59 #[macro_export]
60 #[cfg(not(feature = "rtos-trace-interrupt"))]
61 macro_rules! rtos_trace_interrupt {
62 ($($tt:tt)*) => {};
63 }
64}
65
41pub mod raw; 66pub mod raw;
42 67
43mod spawner; 68mod spawner;
44pub use spawner::*; 69pub use spawner::*;
70
71/// Do not use. Used for macros and HALs only. Not covered by semver guarantees.
72#[doc(hidden)]
73pub mod _export {
74 pub use static_cell::StaticCell;
75}
diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs
index afe67decb..e1258ebb5 100644
--- a/embassy-executor/src/raw/mod.rs
+++ b/embassy-executor/src/raw/mod.rs
@@ -5,7 +5,7 @@
5//! ## WARNING: here be dragons! 5//! ## WARNING: here be dragons!
6//! 6//!
7//! Using this module requires respecting subtle safety contracts. If you can, prefer using the safe 7//! Using this module requires respecting subtle safety contracts. If you can, prefer using the safe
8//! executor wrappers in [`executor`](crate::executor) and the [`embassy_executor::task`](embassy_macros::task) macro, which are fully safe. 8//! [executor wrappers](crate::Executor) and the [`embassy_executor::task`](embassy_macros::task) macro, which are fully safe.
9 9
10mod run_queue; 10mod run_queue;
11#[cfg(feature = "integrated-timers")] 11#[cfg(feature = "integrated-timers")]
@@ -26,6 +26,8 @@ use critical_section::CriticalSection;
26use embassy_time::driver::{self, AlarmHandle}; 26use embassy_time::driver::{self, AlarmHandle};
27#[cfg(feature = "integrated-timers")] 27#[cfg(feature = "integrated-timers")]
28use embassy_time::Instant; 28use embassy_time::Instant;
29#[cfg(feature = "rtos-trace")]
30use rtos_trace::trace;
29 31
30use self::run_queue::{RunQueue, RunQueueItem}; 32use self::run_queue::{RunQueue, RunQueueItem};
31use self::util::UninitCell; 33use self::util::UninitCell;
@@ -247,7 +249,7 @@ impl<F: Future + 'static, const N: usize> TaskPool<F, N> {
247/// 249///
248/// This is the core of the Embassy executor. It is low-level, requiring manual 250/// This is the core of the Embassy executor. It is low-level, requiring manual
249/// handling of wakeups and task polling. If you can, prefer using one of the 251/// handling of wakeups and task polling. If you can, prefer using one of the
250/// higher level executors in [`crate::executor`]. 252/// [higher level executors](crate::Executor).
251/// 253///
252/// The raw executor leaves it up to you to handle wakeups and scheduling: 254/// The raw executor leaves it up to you to handle wakeups and scheduling:
253/// 255///
@@ -306,6 +308,9 @@ impl Executor {
306 /// - `task` must NOT be already enqueued (in this executor or another one). 308 /// - `task` must NOT be already enqueued (in this executor or another one).
307 #[inline(always)] 309 #[inline(always)]
308 unsafe fn enqueue(&self, cs: CriticalSection, task: NonNull<TaskHeader>) { 310 unsafe fn enqueue(&self, cs: CriticalSection, task: NonNull<TaskHeader>) {
311 #[cfg(feature = "rtos-trace")]
312 trace::task_ready_begin(task.as_ptr() as u32);
313
309 if self.run_queue.enqueue(cs, task) { 314 if self.run_queue.enqueue(cs, task) {
310 (self.signal_fn)(self.signal_ctx) 315 (self.signal_fn)(self.signal_ctx)
311 } 316 }
@@ -323,6 +328,9 @@ impl Executor {
323 pub(super) unsafe fn spawn(&'static self, task: NonNull<TaskHeader>) { 328 pub(super) unsafe fn spawn(&'static self, task: NonNull<TaskHeader>) {
324 task.as_ref().executor.set(self); 329 task.as_ref().executor.set(self);
325 330
331 #[cfg(feature = "rtos-trace")]
332 trace::task_new(task.as_ptr() as u32);
333
326 critical_section::with(|cs| { 334 critical_section::with(|cs| {
327 self.enqueue(cs, task); 335 self.enqueue(cs, task);
328 }) 336 })
@@ -365,9 +373,15 @@ impl Executor {
365 return; 373 return;
366 } 374 }
367 375
376 #[cfg(feature = "rtos-trace")]
377 trace::task_exec_begin(p.as_ptr() as u32);
378
368 // Run the task 379 // Run the task
369 task.poll_fn.read()(p as _); 380 task.poll_fn.read()(p as _);
370 381
382 #[cfg(feature = "rtos-trace")]
383 trace::task_exec_end();
384
371 // Enqueue or update into timer_queue 385 // Enqueue or update into timer_queue
372 #[cfg(feature = "integrated-timers")] 386 #[cfg(feature = "integrated-timers")]
373 self.timer_queue.update(p); 387 self.timer_queue.update(p);
@@ -381,6 +395,9 @@ impl Executor {
381 let next_expiration = self.timer_queue.next_expiration(); 395 let next_expiration = self.timer_queue.next_expiration();
382 driver::set_alarm(self.alarm, next_expiration.as_ticks()); 396 driver::set_alarm(self.alarm, next_expiration.as_ticks());
383 } 397 }
398
399 #[cfg(feature = "rtos-trace")]
400 trace::system_idle();
384 } 401 }
385 402
386 /// Get a spawner that spawns tasks in this executor. 403 /// Get a spawner that spawns tasks in this executor.
@@ -426,3 +443,21 @@ unsafe fn _embassy_time_schedule_wake(at: Instant, waker: &core::task::Waker) {
426 let expires_at = task.expires_at.get(); 443 let expires_at = task.expires_at.get();
427 task.expires_at.set(expires_at.min(at)); 444 task.expires_at.set(expires_at.min(at));
428} 445}
446
447#[cfg(feature = "rtos-trace")]
448impl rtos_trace::RtosTraceOSCallbacks for Executor {
449 fn task_list() {
450 // We don't know what tasks exist, so we can't send them.
451 }
452 #[cfg(feature = "integrated-timers")]
453 fn time() -> u64 {
454 Instant::now().as_micros()
455 }
456 #[cfg(not(feature = "integrated-timers"))]
457 fn time() -> u64 {
458 0
459 }
460}
461
462#[cfg(feature = "rtos-trace")]
463rtos_trace::global_os_callbacks! {Executor}
diff --git a/embassy-futures/Cargo.toml b/embassy-futures/Cargo.toml
new file mode 100644
index 000000000..e564f5a96
--- /dev/null
+++ b/embassy-futures/Cargo.toml
@@ -0,0 +1,14 @@
1[package]
2name = "embassy-futures"
3version = "0.1.0"
4edition = "2021"
5
6[package.metadata.embassy_docs]
7src_base = "https://github.com/embassy-rs/embassy/blob/embassy-futures-v$VERSION/embassy-futures/src/"
8src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-futures/src/"
9features = ["nightly"]
10target = "thumbv7em-none-eabi"
11
12[dependencies]
13defmt = { version = "0.3", optional = true }
14log = { version = "0.4.14", optional = true }
diff --git a/embassy-futures/README.md b/embassy-futures/README.md
new file mode 100644
index 000000000..971f4c835
--- /dev/null
+++ b/embassy-futures/README.md
@@ -0,0 +1,9 @@
1# embassy-futures
2
3Utilities for working with futures:
4
5- [`select`](select::select) - waiting for one out of two futures to complete.
6- [`select3`](select::select3) - waiting for one out of three futures to complete.
7- [`select4`](select::select4) - waiting for one out of four futures to complete.
8- [`select_all`](select::select_all) - waiting for one future in a list of futures to complete.
9- [`yield_now`](yield_now::yield_now) - yielding the current task.
diff --git a/embassy-util/src/fmt.rs b/embassy-futures/src/fmt.rs
index f8bb0a035..f8bb0a035 100644
--- a/embassy-util/src/fmt.rs
+++ b/embassy-futures/src/fmt.rs
diff --git a/embassy-futures/src/lib.rs b/embassy-futures/src/lib.rs
new file mode 100644
index 000000000..45bea2529
--- /dev/null
+++ b/embassy-futures/src/lib.rs
@@ -0,0 +1,12 @@
1#![no_std]
2#![doc = include_str!("../README.md")]
3#![warn(missing_docs)]
4
5// This mod MUST go first, so that the others see its macros.
6pub(crate) mod fmt;
7
8mod select;
9mod yield_now;
10
11pub use select::*;
12pub use yield_now::*;
diff --git a/embassy-util/src/select.rs b/embassy-futures/src/select.rs
index 8cecb7fa0..8cecb7fa0 100644
--- a/embassy-util/src/select.rs
+++ b/embassy-futures/src/select.rs
diff --git a/embassy-util/src/yield_now.rs b/embassy-futures/src/yield_now.rs
index 1ebecb916..1ebecb916 100644
--- a/embassy-util/src/yield_now.rs
+++ b/embassy-futures/src/yield_now.rs
diff --git a/embassy-lora/Cargo.toml b/embassy-lora/Cargo.toml
index c7435ab3e..9d5e7aed2 100644
--- a/embassy-lora/Cargo.toml
+++ b/embassy-lora/Cargo.toml
@@ -25,7 +25,7 @@ defmt = { version = "0.3", optional = true }
25log = { version = "0.4.14", optional = true } 25log = { version = "0.4.14", optional = true }
26 26
27embassy-time = { version = "0.1.0", path = "../embassy-time" } 27embassy-time = { version = "0.1.0", path = "../embassy-time" }
28embassy-util = { version = "0.1.0", path = "../embassy-util" } 28embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
29embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", default-features = false, optional = true } 29embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", default-features = false, optional = true }
30embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.8" } 30embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.8" }
31embedded-hal-async = { version = "0.1.0-alpha.1" } 31embedded-hal-async = { version = "0.1.0-alpha.1" }
diff --git a/embassy-lora/src/stm32wl/mod.rs b/embassy-lora/src/stm32wl/mod.rs
index 4a4c5cfb7..7822d0153 100644
--- a/embassy-lora/src/stm32wl/mod.rs
+++ b/embassy-lora/src/stm32wl/mod.rs
@@ -12,7 +12,7 @@ use embassy_stm32::subghz::{
12 Status, SubGhz, TcxoMode, TcxoTrim, Timeout, TxParams, 12 Status, SubGhz, TcxoMode, TcxoTrim, Timeout, TxParams,
13}; 13};
14use embassy_stm32::Peripheral; 14use embassy_stm32::Peripheral;
15use embassy_util::channel::signal::Signal; 15use embassy_sync::signal::Signal;
16use lorawan_device::async_device::radio::{Bandwidth, PhyRxTx, RfConfig, RxQuality, SpreadingFactor, TxConfig}; 16use lorawan_device::async_device::radio::{Bandwidth, PhyRxTx, RfConfig, RxQuality, SpreadingFactor, TxConfig};
17use lorawan_device::async_device::Timings; 17use lorawan_device::async_device::Timings;
18 18
diff --git a/embassy-macros/src/macros/cortex_m_interrupt_take.rs b/embassy-macros/src/macros/cortex_m_interrupt_take.rs
index 9e40a56f1..f6e41bcb4 100644
--- a/embassy-macros/src/macros/cortex_m_interrupt_take.rs
+++ b/embassy-macros/src/macros/cortex_m_interrupt_take.rs
@@ -19,7 +19,13 @@ pub fn run(name: syn::Ident) -> Result<TokenStream, TokenStream> {
19 let func = HANDLER.func.load(interrupt::_export::atomic::Ordering::Relaxed); 19 let func = HANDLER.func.load(interrupt::_export::atomic::Ordering::Relaxed);
20 let ctx = HANDLER.ctx.load(interrupt::_export::atomic::Ordering::Relaxed); 20 let ctx = HANDLER.ctx.load(interrupt::_export::atomic::Ordering::Relaxed);
21 let func: fn(*mut ()) = ::core::mem::transmute(func); 21 let func: fn(*mut ()) = ::core::mem::transmute(func);
22 func(ctx) 22 ::embassy_executor::rtos_trace_interrupt! {
23 ::embassy_executor::export::trace::isr_enter();
24 }
25 func(ctx);
26 ::embassy_executor::rtos_trace_interrupt! {
27 ::embassy_executor::export::trace::isr_exit();
28 }
23 } 29 }
24 30
25 static TAKEN: interrupt::_export::atomic::AtomicBool = interrupt::_export::atomic::AtomicBool::new(false); 31 static TAKEN: interrupt::_export::atomic::AtomicBool = interrupt::_export::atomic::AtomicBool::new(false);
diff --git a/embassy-macros/src/macros/main.rs b/embassy-macros/src/macros/main.rs
index 52987d7d2..afe9bd3e2 100644
--- a/embassy-macros/src/macros/main.rs
+++ b/embassy-macros/src/macros/main.rs
@@ -34,8 +34,8 @@ pub fn run(args: syn::AttributeArgs, f: syn::ItemFn) -> Result<TokenStream, Toke
34 let main = quote! { 34 let main = quote! {
35 #[wasm_bindgen::prelude::wasm_bindgen(start)] 35 #[wasm_bindgen::prelude::wasm_bindgen(start)]
36 pub fn main() -> Result<(), wasm_bindgen::JsValue> { 36 pub fn main() -> Result<(), wasm_bindgen::JsValue> {
37 static EXECUTOR: ::embassy_util::Forever<::embassy_executor::Executor> = ::embassy_util::Forever::new(); 37 static EXECUTOR: ::embassy_executor::_export::StaticCell<::embassy_executor::Executor> = ::embassy_executor::_export::StaticCell::new();
38 let executor = EXECUTOR.put(::embassy_executor::Executor::new()); 38 let executor = EXECUTOR.init(::embassy_executor::Executor::new());
39 39
40 executor.start(|spawner| { 40 executor.start(|spawner| {
41 spawner.spawn(__embassy_main(spawner)).unwrap(); 41 spawner.spawn(__embassy_main(spawner)).unwrap();
diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml
index 9f9bb2261..2143f36d3 100644
--- a/embassy-net/Cargo.toml
+++ b/embassy-net/Cargo.toml
@@ -38,7 +38,7 @@ defmt = { version = "0.3", optional = true }
38log = { version = "0.4.14", optional = true } 38log = { version = "0.4.14", optional = true }
39 39
40embassy-time = { version = "0.1.0", path = "../embassy-time" } 40embassy-time = { version = "0.1.0", path = "../embassy-time" }
41embassy-util = { version = "0.1.0", path = "../embassy-util" } 41embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
42embedded-io = { version = "0.3.0", features = [ "async" ] } 42embedded-io = { version = "0.3.0", features = [ "async" ] }
43 43
44managed = { version = "0.8.0", default-features = false, features = [ "map" ] } 44managed = { version = "0.8.0", default-features = false, features = [ "map" ] }
diff --git a/embassy-net/src/stack.rs b/embassy-net/src/stack.rs
index 4b6a7ae2a..8d2dd4bca 100644
--- a/embassy-net/src/stack.rs
+++ b/embassy-net/src/stack.rs
@@ -2,8 +2,8 @@ use core::cell::UnsafeCell;
2use core::future::Future; 2use core::future::Future;
3use core::task::{Context, Poll}; 3use core::task::{Context, Poll};
4 4
5use embassy_sync::waitqueue::WakerRegistration;
5use embassy_time::{Instant, Timer}; 6use embassy_time::{Instant, Timer};
6use embassy_util::waitqueue::WakerRegistration;
7use futures::future::poll_fn; 7use futures::future::poll_fn;
8use futures::pin_mut; 8use futures::pin_mut;
9use heapless::Vec; 9use heapless::Vec;
diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml
index 0ef7f5bbd..186c73a58 100644
--- a/embassy-nrf/Cargo.toml
+++ b/embassy-nrf/Cargo.toml
@@ -18,7 +18,7 @@ flavors = [
18 18
19time = ["dep:embassy-time"] 19time = ["dep:embassy-time"]
20 20
21defmt = ["dep:defmt", "embassy-executor/defmt", "embassy-util/defmt", "embassy-usb?/defmt", "embedded-io?/defmt", "embassy-embedded-hal/defmt"] 21defmt = ["dep:defmt", "embassy-executor/defmt", "embassy-sync/defmt", "embassy-usb?/defmt", "embedded-io?/defmt", "embassy-embedded-hal/defmt"]
22 22
23# Enable nightly-only features 23# Enable nightly-only features
24nightly = ["embedded-hal-1", "embedded-hal-async", "embassy-usb", "embedded-storage-async", "dep:embedded-io", "embassy-embedded-hal/nightly"] 24nightly = ["embedded-hal-1", "embedded-hal-async", "embassy-usb", "embedded-storage-async", "dep:embedded-io", "embassy-embedded-hal/nightly"]
@@ -66,7 +66,7 @@ _gpio-p1 = []
66[dependencies] 66[dependencies]
67embassy-executor = { version = "0.1.0", path = "../embassy-executor", optional = true } 67embassy-executor = { version = "0.1.0", path = "../embassy-executor", optional = true }
68embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true } 68embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true }
69embassy-util = { version = "0.1.0", path = "../embassy-util" } 69embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
70embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-3"]} 70embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-3"]}
71embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" } 71embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" }
72embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } 72embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" }
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs
index 21ff1d73b..62af544ae 100644
--- a/embassy-nrf/src/buffered_uarte.rs
+++ b/embassy-nrf/src/buffered_uarte.rs
@@ -21,7 +21,7 @@ use core::task::Poll;
21use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage}; 21use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage};
22use embassy_hal_common::ring_buffer::RingBuffer; 22use embassy_hal_common::ring_buffer::RingBuffer;
23use embassy_hal_common::{into_ref, PeripheralRef}; 23use embassy_hal_common::{into_ref, PeripheralRef};
24use embassy_util::waitqueue::WakerRegistration; 24use embassy_sync::waitqueue::WakerRegistration;
25use futures::future::poll_fn; 25use futures::future::poll_fn;
26// Re-export SVD variants to allow user to directly set values 26// Re-export SVD variants to allow user to directly set values
27pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; 27pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
@@ -45,8 +45,10 @@ enum TxState {
45 Transmitting(usize), 45 Transmitting(usize),
46} 46}
47 47
48/// A type for storing the state of the UARTE peripheral that can be stored in a static.
48pub struct State<'d, U: UarteInstance, T: TimerInstance>(StateStorage<StateInner<'d, U, T>>); 49pub struct State<'d, U: UarteInstance, T: TimerInstance>(StateStorage<StateInner<'d, U, T>>);
49impl<'d, U: UarteInstance, T: TimerInstance> State<'d, U, T> { 50impl<'d, U: UarteInstance, T: TimerInstance> State<'d, U, T> {
51 /// Create an instance for storing UARTE peripheral state.
50 pub fn new() -> Self { 52 pub fn new() -> Self {
51 Self(StateStorage::new()) 53 Self(StateStorage::new())
52 } 54 }
@@ -75,6 +77,12 @@ pub struct BufferedUarte<'d, U: UarteInstance, T: TimerInstance> {
75impl<'d, U: UarteInstance, T: TimerInstance> Unpin for BufferedUarte<'d, U, T> {} 77impl<'d, U: UarteInstance, T: TimerInstance> Unpin for BufferedUarte<'d, U, T> {}
76 78
77impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { 79impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
80 /// Create a new instance of a BufferedUarte.
81 ///
82 /// See the [module documentation](crate::buffered_uarte) for more details about the intended use.
83 ///
84 /// The BufferedUarte uses the provided state to store the buffers and peripheral state. The timer and ppi channels are used to 'emulate' idle line detection so that read operations
85 /// can return early if there is no data to receive.
78 pub fn new( 86 pub fn new(
79 state: &'d mut State<'d, U, T>, 87 state: &'d mut State<'d, U, T>,
80 peri: impl Peripheral<P = U> + 'd, 88 peri: impl Peripheral<P = U> + 'd,
@@ -178,6 +186,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
178 } 186 }
179 } 187 }
180 188
189 /// Adjust the baud rate to the provided value.
181 pub fn set_baudrate(&mut self, baudrate: Baudrate) { 190 pub fn set_baudrate(&mut self, baudrate: Baudrate) {
182 self.inner.with(|state| { 191 self.inner.with(|state| {
183 let r = U::regs(); 192 let r = U::regs();
diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs
index a61ff6aa5..924629908 100644
--- a/embassy-nrf/src/gpio.rs
+++ b/embassy-nrf/src/gpio.rs
@@ -1,3 +1,4 @@
1//! General purpose input/output for nRF.
1#![macro_use] 2#![macro_use]
2 3
3use core::convert::Infallible; 4use core::convert::Infallible;
@@ -26,8 +27,11 @@ pub enum Port {
26#[derive(Debug, Eq, PartialEq)] 27#[derive(Debug, Eq, PartialEq)]
27#[cfg_attr(feature = "defmt", derive(defmt::Format))] 28#[cfg_attr(feature = "defmt", derive(defmt::Format))]
28pub enum Pull { 29pub enum Pull {
30 /// No pull.
29 None, 31 None,
32 /// Internal pull-up resistor.
30 Up, 33 Up,
34 /// Internal pull-down resistor.
31 Down, 35 Down,
32} 36}
33 37
@@ -37,6 +41,7 @@ pub struct Input<'d, T: Pin> {
37} 41}
38 42
39impl<'d, T: Pin> Input<'d, T> { 43impl<'d, T: Pin> Input<'d, T> {
44 /// Create GPIO input driver for a [Pin] with the provided [Pull] configuration.
40 #[inline] 45 #[inline]
41 pub fn new(pin: impl Peripheral<P = T> + 'd, pull: Pull) -> Self { 46 pub fn new(pin: impl Peripheral<P = T> + 'd, pull: Pull) -> Self {
42 let mut pin = Flex::new(pin); 47 let mut pin = Flex::new(pin);
@@ -45,11 +50,13 @@ impl<'d, T: Pin> Input<'d, T> {
45 Self { pin } 50 Self { pin }
46 } 51 }
47 52
53 /// Test if current pin level is high.
48 #[inline] 54 #[inline]
49 pub fn is_high(&self) -> bool { 55 pub fn is_high(&self) -> bool {
50 self.pin.is_high() 56 self.pin.is_high()
51 } 57 }
52 58
59 /// Test if current pin level is low.
53 #[inline] 60 #[inline]
54 pub fn is_low(&self) -> bool { 61 pub fn is_low(&self) -> bool {
55 self.pin.is_low() 62 self.pin.is_low()
@@ -66,7 +73,9 @@ impl<'d, T: Pin> Input<'d, T> {
66#[derive(Debug, Eq, PartialEq)] 73#[derive(Debug, Eq, PartialEq)]
67#[cfg_attr(feature = "defmt", derive(defmt::Format))] 74#[cfg_attr(feature = "defmt", derive(defmt::Format))]
68pub enum Level { 75pub enum Level {
76 /// Logical low.
69 Low, 77 Low,
78 /// Logical high.
70 High, 79 High,
71} 80}
72 81
@@ -88,6 +97,7 @@ impl Into<bool> for Level {
88 } 97 }
89} 98}
90 99
100/// Drive strength settings for an output pin.
91// These numbers match DRIVE_A exactly so hopefully the compiler will unify them. 101// These numbers match DRIVE_A exactly so hopefully the compiler will unify them.
92#[derive(Clone, Copy, Debug, PartialEq)] 102#[derive(Clone, Copy, Debug, PartialEq)]
93#[cfg_attr(feature = "defmt", derive(defmt::Format))] 103#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -117,6 +127,7 @@ pub struct Output<'d, T: Pin> {
117} 127}
118 128
119impl<'d, T: Pin> Output<'d, T> { 129impl<'d, T: Pin> Output<'d, T> {
130 /// Create GPIO output driver for a [Pin] with the provided [Level] and [OutputDriver] configuration.
120 #[inline] 131 #[inline]
121 pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level, drive: OutputDrive) -> Self { 132 pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level, drive: OutputDrive) -> Self {
122 let mut pin = Flex::new(pin); 133 let mut pin = Flex::new(pin);
@@ -264,11 +275,13 @@ impl<'d, T: Pin> Flex<'d, T> {
264 self.pin.conf().reset(); 275 self.pin.conf().reset();
265 } 276 }
266 277
278 /// Test if current pin level is high.
267 #[inline] 279 #[inline]
268 pub fn is_high(&self) -> bool { 280 pub fn is_high(&self) -> bool {
269 !self.is_low() 281 !self.is_low()
270 } 282 }
271 283
284 /// Test if current pin level is low.
272 #[inline] 285 #[inline]
273 pub fn is_low(&self) -> bool { 286 pub fn is_low(&self) -> bool {
274 self.pin.block().in_.read().bits() & (1 << self.pin.pin()) == 0 287 self.pin.block().in_.read().bits() & (1 << self.pin.pin()) == 0
@@ -374,6 +387,7 @@ pub(crate) mod sealed {
374 } 387 }
375} 388}
376 389
390/// Interface for a Pin that can be configured by an [Input] or [Output] driver, or converted to an [AnyPin].
377pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'static { 391pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'static {
378 /// Number of the pin within the port (0..31) 392 /// Number of the pin within the port (0..31)
379 #[inline] 393 #[inline]
@@ -392,6 +406,7 @@ pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'stat
392 } 406 }
393 } 407 }
394 408
409 /// Peripheral port register value
395 #[inline] 410 #[inline]
396 fn psel_bits(&self) -> u32 { 411 fn psel_bits(&self) -> u32 {
397 self.pin_port() as u32 412 self.pin_port() as u32
@@ -406,12 +421,16 @@ pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'stat
406 } 421 }
407} 422}
408 423
409// Type-erased GPIO pin 424/// Type-erased GPIO pin
410pub struct AnyPin { 425pub struct AnyPin {
411 pin_port: u8, 426 pin_port: u8,
412} 427}
413 428
414impl AnyPin { 429impl AnyPin {
430 /// Create an [AnyPin] for a specific pin.
431 ///
432 /// # Safety
433 /// - `pin_port` should not in use by another driver.
415 #[inline] 434 #[inline]
416 pub unsafe fn steal(pin_port: u8) -> Self { 435 pub unsafe fn steal(pin_port: u8) -> Self {
417 Self { pin_port } 436 Self { pin_port }
diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs
index cf49b0db0..b52035705 100644
--- a/embassy-nrf/src/gpiote.rs
+++ b/embassy-nrf/src/gpiote.rs
@@ -3,7 +3,7 @@ use core::future::Future;
3use core::task::{Context, Poll}; 3use core::task::{Context, Poll};
4 4
5use embassy_hal_common::{impl_peripheral, Peripheral, PeripheralRef}; 5use embassy_hal_common::{impl_peripheral, Peripheral, PeripheralRef};
6use embassy_util::waitqueue::AtomicWaker; 6use embassy_sync::waitqueue::AtomicWaker;
7use futures::future::poll_fn; 7use futures::future::poll_fn;
8 8
9use crate::gpio::sealed::Pin as _; 9use crate::gpio::sealed::Pin as _;
diff --git a/embassy-nrf/src/nvmc.rs b/embassy-nrf/src/nvmc.rs
index cd6100339..6f66f7a78 100644
--- a/embassy-nrf/src/nvmc.rs
+++ b/embassy-nrf/src/nvmc.rs
@@ -1,4 +1,4 @@
1//! Nvmcerature sensor interface. 1//! Non-Volatile Memory Controller (NVMC) module.
2 2
3use core::{ptr, slice}; 3use core::{ptr, slice};
4 4
@@ -10,13 +10,19 @@ use embedded_storage::nor_flash::{
10use crate::peripherals::NVMC; 10use crate::peripherals::NVMC;
11use crate::{pac, Peripheral}; 11use crate::{pac, Peripheral};
12 12
13/// Erase size of NVMC flash in bytes.
13pub const PAGE_SIZE: usize = 4096; 14pub const PAGE_SIZE: usize = 4096;
15
16/// Size of NVMC flash in bytes.
14pub const FLASH_SIZE: usize = crate::chip::FLASH_SIZE; 17pub const FLASH_SIZE: usize = crate::chip::FLASH_SIZE;
15 18
19/// Error type for NVMC operations.
16#[derive(Debug, Copy, Clone, PartialEq, Eq)] 20#[derive(Debug, Copy, Clone, PartialEq, Eq)]
17#[cfg_attr(feature = "defmt", derive(defmt::Format))] 21#[cfg_attr(feature = "defmt", derive(defmt::Format))]
18pub enum Error { 22pub enum Error {
23 /// Opration using a location not in flash.
19 OutOfBounds, 24 OutOfBounds,
25 /// Unaligned operation or using unaligned buffers.
20 Unaligned, 26 Unaligned,
21} 27}
22 28
@@ -29,11 +35,13 @@ impl NorFlashError for Error {
29 } 35 }
30} 36}
31 37
38/// Non-Volatile Memory Controller (NVMC) that implements the `embedded-storage` traits.
32pub struct Nvmc<'d> { 39pub struct Nvmc<'d> {
33 _p: PeripheralRef<'d, NVMC>, 40 _p: PeripheralRef<'d, NVMC>,
34} 41}
35 42
36impl<'d> Nvmc<'d> { 43impl<'d> Nvmc<'d> {
44 /// Create Nvmc driver.
37 pub fn new(_p: impl Peripheral<P = NVMC> + 'd) -> Self { 45 pub fn new(_p: impl Peripheral<P = NVMC> + 'd) -> Self {
38 into_ref!(_p); 46 into_ref!(_p);
39 Self { _p } 47 Self { _p }
diff --git a/embassy-nrf/src/ppi/mod.rs b/embassy-nrf/src/ppi/mod.rs
index 23ab011bc..8f5ed14cd 100644
--- a/embassy-nrf/src/ppi/mod.rs
+++ b/embassy-nrf/src/ppi/mod.rs
@@ -26,6 +26,7 @@ mod dppi;
26#[cfg(feature = "_ppi")] 26#[cfg(feature = "_ppi")]
27mod ppi; 27mod ppi;
28 28
29/// An instance of the Programmable peripheral interconnect on nRF devices.
29pub struct Ppi<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> { 30pub struct Ppi<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> {
30 ch: PeripheralRef<'d, C>, 31 ch: PeripheralRef<'d, C>,
31 #[cfg(feature = "_dppi")] 32 #[cfg(feature = "_dppi")]
@@ -34,20 +35,32 @@ pub struct Ppi<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize
34 tasks: [Task; TASK_COUNT], 35 tasks: [Task; TASK_COUNT],
35} 36}
36 37
38#[cfg(feature = "_dppi")]
37const REGISTER_DPPI_CONFIG_OFFSET: usize = 0x80 / core::mem::size_of::<u32>(); 39const REGISTER_DPPI_CONFIG_OFFSET: usize = 0x80 / core::mem::size_of::<u32>();
38 40
39/// Represents a task that a peripheral can do. 41/// Represents a task that a peripheral can do.
40/// When a task is subscribed to a PPI channel it will run when the channel is triggered by
41/// a published event.
42/// 42///
43/// The pointer is to a task register 43/// When a task is subscribed to a PPI channel, it will run when the channel is triggered by
44/// a published event.
44#[derive(PartialEq, Eq, Clone, Copy)] 45#[derive(PartialEq, Eq, Clone, Copy)]
45pub struct Task(pub NonNull<u32>); 46pub struct Task(NonNull<u32>);
47
46impl Task { 48impl Task {
49 /// Create a new `Task` from a task register pointer
50 ///
51 /// # Safety
52 ///
53 /// `ptr` must be a pointer to a valid `TASKS_*` register from an nRF peripheral.
54 pub unsafe fn new_unchecked(ptr: NonNull<u32>) -> Self {
55 Self(ptr)
56 }
57
47 pub(crate) fn from_reg<T>(reg: &T) -> Self { 58 pub(crate) fn from_reg<T>(reg: &T) -> Self {
48 Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) }) 59 Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) })
49 } 60 }
50 61
62 /// Address of subscription register for this task.
63 #[cfg(feature = "_dppi")]
51 pub fn subscribe_reg(&self) -> *mut u32 { 64 pub fn subscribe_reg(&self) -> *mut u32 {
52 unsafe { self.0.as_ptr().add(REGISTER_DPPI_CONFIG_OFFSET) } 65 unsafe { self.0.as_ptr().add(REGISTER_DPPI_CONFIG_OFFSET) }
53 } 66 }
@@ -59,16 +72,27 @@ impl Task {
59unsafe impl Send for Task {} 72unsafe impl Send for Task {}
60 73
61/// Represents an event that a peripheral can publish. 74/// Represents an event that a peripheral can publish.
62/// An event can be set to publish on a PPI channel when the event happens.
63/// 75///
64/// The pointer is to an event register 76/// An event can be set to publish on a PPI channel when the event happens.
65#[derive(PartialEq, Eq, Clone, Copy)] 77#[derive(PartialEq, Eq, Clone, Copy)]
66pub struct Event(pub NonNull<u32>); 78pub struct Event(NonNull<u32>);
79
67impl Event { 80impl Event {
81 /// Create a new `Event` from an event register pointer
82 ///
83 /// # Safety
84 ///
85 /// `ptr` must be a pointer to a valid `EVENTS_*` register from an nRF peripheral.
86 pub unsafe fn new_unchecked(ptr: NonNull<u32>) -> Self {
87 Self(ptr)
88 }
89
68 pub(crate) fn from_reg<T>(reg: &T) -> Self { 90 pub(crate) fn from_reg<T>(reg: &T) -> Self {
69 Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) }) 91 Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) })
70 } 92 }
71 93
94 /// Address of publish register for this event.
95 #[cfg(feature = "_dppi")]
72 pub fn publish_reg(&self) -> *mut u32 { 96 pub fn publish_reg(&self) -> *mut u32 {
73 unsafe { self.0.as_ptr().add(REGISTER_DPPI_CONFIG_OFFSET) } 97 unsafe { self.0.as_ptr().add(REGISTER_DPPI_CONFIG_OFFSET) }
74 } 98 }
@@ -87,21 +111,29 @@ pub(crate) mod sealed {
87 pub trait Group {} 111 pub trait Group {}
88} 112}
89 113
114/// Interface for PPI channels.
90pub trait Channel: sealed::Channel + Peripheral<P = Self> + Sized { 115pub trait Channel: sealed::Channel + Peripheral<P = Self> + Sized {
91 /// Returns the number of the channel 116 /// Returns the number of the channel
92 fn number(&self) -> usize; 117 fn number(&self) -> usize;
93} 118}
94 119
120/// Interface for PPI channels that can be configured.
95pub trait ConfigurableChannel: Channel + Into<AnyConfigurableChannel> { 121pub trait ConfigurableChannel: Channel + Into<AnyConfigurableChannel> {
122 /// Convert into a type erased configurable channel.
96 fn degrade(self) -> AnyConfigurableChannel; 123 fn degrade(self) -> AnyConfigurableChannel;
97} 124}
98 125
126/// Interface for PPI channels that cannot be configured.
99pub trait StaticChannel: Channel + Into<AnyStaticChannel> { 127pub trait StaticChannel: Channel + Into<AnyStaticChannel> {
128 /// Convert into a type erased static channel.
100 fn degrade(self) -> AnyStaticChannel; 129 fn degrade(self) -> AnyStaticChannel;
101} 130}
102 131
132/// Interface for a group of PPI channels.
103pub trait Group: sealed::Group + Sized { 133pub trait Group: sealed::Group + Sized {
134 /// Returns the number of the group.
104 fn number(&self) -> usize; 135 fn number(&self) -> usize;
136 /// Convert into a type erased group.
105 fn degrade(self) -> AnyGroup { 137 fn degrade(self) -> AnyGroup {
106 AnyGroup { 138 AnyGroup {
107 number: self.number() as u8, 139 number: self.number() as u8,
@@ -196,6 +228,7 @@ macro_rules! impl_ppi_channel {
196// ====================== 228// ======================
197// groups 229// groups
198 230
231/// A type erased PPI group.
199pub struct AnyGroup { 232pub struct AnyGroup {
200 number: u8, 233 number: u8,
201} 234}
diff --git a/embassy-nrf/src/ppi/ppi.rs b/embassy-nrf/src/ppi/ppi.rs
index 450a290a2..19abc4e18 100644
--- a/embassy-nrf/src/ppi/ppi.rs
+++ b/embassy-nrf/src/ppi/ppi.rs
@@ -20,6 +20,7 @@ fn regs() -> &'static pac::ppi::RegisterBlock {
20 20
21#[cfg(not(feature = "nrf51"))] // Not for nrf51 because of the fork task 21#[cfg(not(feature = "nrf51"))] // Not for nrf51 because of the fork task
22impl<'d, C: StaticChannel> Ppi<'d, C, 0, 1> { 22impl<'d, C: StaticChannel> Ppi<'d, C, 0, 1> {
23 /// Configure PPI channel to trigger `task`.
23 pub fn new_zero_to_one(ch: impl Peripheral<P = C> + 'd, task: Task) -> Self { 24 pub fn new_zero_to_one(ch: impl Peripheral<P = C> + 'd, task: Task) -> Self {
24 into_ref!(ch); 25 into_ref!(ch);
25 26
@@ -32,6 +33,7 @@ impl<'d, C: StaticChannel> Ppi<'d, C, 0, 1> {
32} 33}
33 34
34impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> { 35impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> {
36 /// Configure PPI channel to trigger `task` on `event`.
35 pub fn new_one_to_one(ch: impl Peripheral<P = C> + 'd, event: Event, task: Task) -> Self { 37 pub fn new_one_to_one(ch: impl Peripheral<P = C> + 'd, event: Event, task: Task) -> Self {
36 into_ref!(ch); 38 into_ref!(ch);
37 39
@@ -46,6 +48,7 @@ impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> {
46 48
47#[cfg(not(feature = "nrf51"))] // Not for nrf51 because of the fork task 49#[cfg(not(feature = "nrf51"))] // Not for nrf51 because of the fork task
48impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 2> { 50impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 2> {
51 /// Configure PPI channel to trigger `task1` and `task2` on `event`.
49 pub fn new_one_to_two(ch: impl Peripheral<P = C> + 'd, event: Event, task1: Task, task2: Task) -> Self { 52 pub fn new_one_to_two(ch: impl Peripheral<P = C> + 'd, event: Event, task1: Task, task2: Task) -> Self {
50 into_ref!(ch); 53 into_ref!(ch);
51 54
diff --git a/embassy-nrf/src/qdec.rs b/embassy-nrf/src/qdec.rs
index 83f2916b9..762e09715 100644
--- a/embassy-nrf/src/qdec.rs
+++ b/embassy-nrf/src/qdec.rs
@@ -3,7 +3,7 @@
3use core::task::Poll; 3use core::task::Poll;
4 4
5use embassy_hal_common::{into_ref, PeripheralRef}; 5use embassy_hal_common::{into_ref, PeripheralRef};
6use embassy_util::waitqueue::AtomicWaker; 6use embassy_sync::waitqueue::AtomicWaker;
7use futures::future::poll_fn; 7use futures::future::poll_fn;
8 8
9use crate::gpio::sealed::Pin as _; 9use crate::gpio::sealed::Pin as _;
diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs
index 6d7ebb4b1..c97cb1656 100644
--- a/embassy-nrf/src/qspi.rs
+++ b/embassy-nrf/src/qspi.rs
@@ -526,7 +526,7 @@ cfg_if::cfg_if! {
526} 526}
527 527
528pub(crate) mod sealed { 528pub(crate) mod sealed {
529 use embassy_util::waitqueue::AtomicWaker; 529 use embassy_sync::waitqueue::AtomicWaker;
530 530
531 use super::*; 531 use super::*;
532 532
diff --git a/embassy-nrf/src/rng.rs b/embassy-nrf/src/rng.rs
index 7aad561b6..42da51d0f 100644
--- a/embassy-nrf/src/rng.rs
+++ b/embassy-nrf/src/rng.rs
@@ -4,7 +4,7 @@ use core::task::Poll;
4 4
5use embassy_hal_common::drop::OnDrop; 5use embassy_hal_common::drop::OnDrop;
6use embassy_hal_common::{into_ref, PeripheralRef}; 6use embassy_hal_common::{into_ref, PeripheralRef};
7use embassy_util::waitqueue::AtomicWaker; 7use embassy_sync::waitqueue::AtomicWaker;
8use futures::future::poll_fn; 8use futures::future::poll_fn;
9 9
10use crate::interrupt::InterruptExt; 10use crate::interrupt::InterruptExt;
diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs
index f2ef46d8d..7dc66349e 100644
--- a/embassy-nrf/src/saadc.rs
+++ b/embassy-nrf/src/saadc.rs
@@ -4,7 +4,7 @@ use core::sync::atomic::{compiler_fence, Ordering};
4use core::task::Poll; 4use core::task::Poll;
5 5
6use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; 6use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef};
7use embassy_util::waitqueue::AtomicWaker; 7use embassy_sync::waitqueue::AtomicWaker;
8use futures::future::poll_fn; 8use futures::future::poll_fn;
9use pac::{saadc, SAADC}; 9use pac::{saadc, SAADC};
10use saadc::ch::config::{GAIN_A, REFSEL_A, RESP_A, TACQ_A}; 10use saadc::ch::config::{GAIN_A, REFSEL_A, RESP_A, TACQ_A};
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs
index 57c0c14c7..be2fc02fc 100644
--- a/embassy-nrf/src/spim.rs
+++ b/embassy-nrf/src/spim.rs
@@ -363,7 +363,7 @@ impl<'d, T: Instance> Drop for Spim<'d, T> {
363} 363}
364 364
365pub(crate) mod sealed { 365pub(crate) mod sealed {
366 use embassy_util::waitqueue::AtomicWaker; 366 use embassy_sync::waitqueue::AtomicWaker;
367 367
368 use super::*; 368 use super::*;
369 369
diff --git a/embassy-nrf/src/temp.rs b/embassy-nrf/src/temp.rs
index 1491e4268..d520fd686 100644
--- a/embassy-nrf/src/temp.rs
+++ b/embassy-nrf/src/temp.rs
@@ -4,7 +4,7 @@ use core::task::Poll;
4 4
5use embassy_hal_common::drop::OnDrop; 5use embassy_hal_common::drop::OnDrop;
6use embassy_hal_common::{into_ref, PeripheralRef}; 6use embassy_hal_common::{into_ref, PeripheralRef};
7use embassy_util::waitqueue::AtomicWaker; 7use embassy_sync::waitqueue::AtomicWaker;
8use fixed::types::I30F2; 8use fixed::types::I30F2;
9use futures::future::poll_fn; 9use futures::future::poll_fn;
10 10
diff --git a/embassy-nrf/src/time_driver.rs b/embassy-nrf/src/time_driver.rs
index b961d65a0..c32a44637 100644
--- a/embassy-nrf/src/time_driver.rs
+++ b/embassy-nrf/src/time_driver.rs
@@ -3,9 +3,9 @@ use core::sync::atomic::{compiler_fence, AtomicU32, AtomicU8, Ordering};
3use core::{mem, ptr}; 3use core::{mem, ptr};
4 4
5use critical_section::CriticalSection; 5use critical_section::CriticalSection;
6use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
7use embassy_sync::blocking_mutex::CriticalSectionMutex as Mutex;
6use embassy_time::driver::{AlarmHandle, Driver}; 8use embassy_time::driver::{AlarmHandle, Driver};
7use embassy_util::blocking_mutex::raw::CriticalSectionRawMutex;
8use embassy_util::blocking_mutex::CriticalSectionMutex as Mutex;
9 9
10use crate::interrupt::{Interrupt, InterruptExt}; 10use crate::interrupt::{Interrupt, InterruptExt};
11use crate::{interrupt, pac}; 11use crate::{interrupt, pac};
diff --git a/embassy-nrf/src/timer.rs b/embassy-nrf/src/timer.rs
index b3b613db2..3de5a8962 100644
--- a/embassy-nrf/src/timer.rs
+++ b/embassy-nrf/src/timer.rs
@@ -5,7 +5,7 @@ use core::task::Poll;
5 5
6use embassy_hal_common::drop::OnDrop; 6use embassy_hal_common::drop::OnDrop;
7use embassy_hal_common::{into_ref, PeripheralRef}; 7use embassy_hal_common::{into_ref, PeripheralRef};
8use embassy_util::waitqueue::AtomicWaker; 8use embassy_sync::waitqueue::AtomicWaker;
9use futures::future::poll_fn; 9use futures::future::poll_fn;
10 10
11use crate::interrupt::{Interrupt, InterruptExt}; 11use crate::interrupt::{Interrupt, InterruptExt};
@@ -40,8 +40,8 @@ macro_rules! impl_timer {
40 fn regs() -> &'static pac::timer0::RegisterBlock { 40 fn regs() -> &'static pac::timer0::RegisterBlock {
41 unsafe { &*(pac::$pac_type::ptr() as *const pac::timer0::RegisterBlock) } 41 unsafe { &*(pac::$pac_type::ptr() as *const pac::timer0::RegisterBlock) }
42 } 42 }
43 fn waker(n: usize) -> &'static ::embassy_util::waitqueue::AtomicWaker { 43 fn waker(n: usize) -> &'static ::embassy_sync::waitqueue::AtomicWaker {
44 use ::embassy_util::waitqueue::AtomicWaker; 44 use ::embassy_sync::waitqueue::AtomicWaker;
45 const NEW_AW: AtomicWaker = AtomicWaker::new(); 45 const NEW_AW: AtomicWaker = AtomicWaker::new();
46 static WAKERS: [AtomicWaker; $ccs] = [NEW_AW; $ccs]; 46 static WAKERS: [AtomicWaker; $ccs] = [NEW_AW; $ccs];
47 &WAKERS[n] 47 &WAKERS[n]
diff --git a/embassy-nrf/src/twim.rs b/embassy-nrf/src/twim.rs
index 9587d1f40..850f6d0fa 100644
--- a/embassy-nrf/src/twim.rs
+++ b/embassy-nrf/src/twim.rs
@@ -13,9 +13,9 @@ use core::task::Poll;
13 13
14use embassy_embedded_hal::SetConfig; 14use embassy_embedded_hal::SetConfig;
15use embassy_hal_common::{into_ref, PeripheralRef}; 15use embassy_hal_common::{into_ref, PeripheralRef};
16use embassy_sync::waitqueue::AtomicWaker;
16#[cfg(feature = "time")] 17#[cfg(feature = "time")]
17use embassy_time::{Duration, Instant}; 18use embassy_time::{Duration, Instant};
18use embassy_util::waitqueue::AtomicWaker;
19use futures::future::poll_fn; 19use futures::future::poll_fn;
20 20
21use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; 21use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs
index 0d24cf65f..4347ea558 100644
--- a/embassy-nrf/src/uarte.rs
+++ b/embassy-nrf/src/uarte.rs
@@ -932,7 +932,7 @@ impl<'d, U: Instance, T: TimerInstance> UarteRxWithIdle<'d, U, T> {
932pub(crate) mod sealed { 932pub(crate) mod sealed {
933 use core::sync::atomic::AtomicU8; 933 use core::sync::atomic::AtomicU8;
934 934
935 use embassy_util::waitqueue::AtomicWaker; 935 use embassy_sync::waitqueue::AtomicWaker;
936 936
937 use super::*; 937 use super::*;
938 938
diff --git a/embassy-nrf/src/usb.rs b/embassy-nrf/src/usb.rs
index 509ee313e..688326e9c 100644
--- a/embassy-nrf/src/usb.rs
+++ b/embassy-nrf/src/usb.rs
@@ -7,10 +7,10 @@ use core::task::Poll;
7 7
8use cortex_m::peripheral::NVIC; 8use cortex_m::peripheral::NVIC;
9use embassy_hal_common::{into_ref, PeripheralRef}; 9use embassy_hal_common::{into_ref, PeripheralRef};
10use embassy_sync::waitqueue::AtomicWaker;
10pub use embassy_usb; 11pub use embassy_usb;
11use embassy_usb::driver::{self, EndpointError, Event, Unsupported}; 12use embassy_usb::driver::{self, EndpointError, Event, Unsupported};
12use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection}; 13use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection};
13use embassy_util::waitqueue::AtomicWaker;
14use futures::future::poll_fn; 14use futures::future::poll_fn;
15use futures::Future; 15use futures::Future;
16use pac::usbd::RegisterBlock; 16use pac::usbd::RegisterBlock;
diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml
index af7c8ee6e..cfd95b7b4 100644
--- a/embassy-rp/Cargo.toml
+++ b/embassy-rp/Cargo.toml
@@ -27,10 +27,10 @@ nightly = ["embassy-executor/nightly", "embedded-hal-1", "embedded-hal-async", "
27unstable-traits = ["embedded-hal-1"] 27unstable-traits = ["embedded-hal-1"]
28 28
29[dependencies] 29[dependencies]
30embassy-util = { version = "0.1.0", path = "../embassy-util" } 30embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
31embassy-executor = { version = "0.1.0", path = "../embassy-executor" } 31embassy-executor = { version = "0.1.0", path = "../embassy-executor" }
32embassy-time = { version = "0.1.0", path = "../embassy-time", features = [ "tick-1mhz" ] } 32embassy-time = { version = "0.1.0", path = "../embassy-time", features = [ "tick-1mhz" ] }
33embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-3"]} 33embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-2"]}
34embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" } 34embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" }
35embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } 35embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" }
36atomic-polyfill = "1.0.1" 36atomic-polyfill = "1.0.1"
diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs
index f9fa8378b..428855c7f 100644
--- a/embassy-rp/src/gpio.rs
+++ b/embassy-rp/src/gpio.rs
@@ -5,7 +5,7 @@ use core::task::{Context, Poll};
5 5
6use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; 6use embassy_cortex_m::interrupt::{Interrupt, InterruptExt};
7use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; 7use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef};
8use embassy_util::waitqueue::AtomicWaker; 8use embassy_sync::waitqueue::AtomicWaker;
9 9
10use crate::pac::common::{Reg, RW}; 10use crate::pac::common::{Reg, RW};
11use crate::pac::SIO; 11use crate::pac::SIO;
@@ -189,7 +189,7 @@ impl<'d, T: Pin> InputFuture<'d, T> {
189 unsafe { 189 unsafe {
190 let irq = interrupt::IO_IRQ_BANK0::steal(); 190 let irq = interrupt::IO_IRQ_BANK0::steal();
191 irq.disable(); 191 irq.disable();
192 irq.set_priority(interrupt::Priority::P6); 192 irq.set_priority(interrupt::Priority::P3);
193 193
194 // Each INTR register is divided into 8 groups, one group for each 194 // Each INTR register is divided into 8 groups, one group for each
195 // pin, and each group consists of LEVEL_LOW, LEVEL_HIGH, EDGE_LOW, 195 // pin, and each group consists of LEVEL_LOW, LEVEL_HIGH, EDGE_LOW,
diff --git a/embassy-rp/src/timer.rs b/embassy-rp/src/timer.rs
index 5bc1f66c8..5215c0c0f 100644
--- a/embassy-rp/src/timer.rs
+++ b/embassy-rp/src/timer.rs
@@ -2,9 +2,9 @@ use core::cell::Cell;
2 2
3use atomic_polyfill::{AtomicU8, Ordering}; 3use atomic_polyfill::{AtomicU8, Ordering};
4use critical_section::CriticalSection; 4use critical_section::CriticalSection;
5use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
6use embassy_sync::blocking_mutex::Mutex;
5use embassy_time::driver::{AlarmHandle, Driver}; 7use embassy_time::driver::{AlarmHandle, Driver};
6use embassy_util::blocking_mutex::raw::CriticalSectionRawMutex;
7use embassy_util::blocking_mutex::Mutex;
8 8
9use crate::interrupt::{Interrupt, InterruptExt}; 9use crate::interrupt::{Interrupt, InterruptExt};
10use crate::{interrupt, pac}; 10use crate::{interrupt, pac};
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index c47ea0bca..7a8e5c59b 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -31,7 +31,7 @@ flavors = [
31] 31]
32 32
33[dependencies] 33[dependencies]
34embassy-util = { version = "0.1.0", path = "../embassy-util" } 34embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
35embassy-executor = { version = "0.1.0", path = "../embassy-executor" } 35embassy-executor = { version = "0.1.0", path = "../embassy-executor" }
36embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true } 36embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true }
37embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-4"]} 37embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-4"]}
@@ -72,7 +72,7 @@ quote = "1.0.15"
72stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", default-features = false, features = ["metadata"]} 72stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", default-features = false, features = ["metadata"]}
73 73
74[features] 74[features]
75defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-util/defmt", "embassy-executor/defmt", "embassy-embedded-hal/defmt", "embedded-io?/defmt", "embassy-usb?/defmt"] 75defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-sync/defmt", "embassy-executor/defmt", "embassy-embedded-hal/defmt", "embedded-io?/defmt", "embassy-usb?/defmt"]
76sdmmc-rs = ["embedded-sdmmc"] 76sdmmc-rs = ["embedded-sdmmc"]
77net = ["embassy-net" ] 77net = ["embassy-net" ]
78memory-x = ["stm32-metapac/memory-x"] 78memory-x = ["stm32-metapac/memory-x"]
diff --git a/embassy-stm32/src/dcmi.rs b/embassy-stm32/src/dcmi.rs
index bbb9a12cb..fb9dc9d08 100644
--- a/embassy-stm32/src/dcmi.rs
+++ b/embassy-stm32/src/dcmi.rs
@@ -1,7 +1,7 @@
1use core::task::Poll; 1use core::task::Poll;
2 2
3use embassy_hal_common::{into_ref, PeripheralRef}; 3use embassy_hal_common::{into_ref, PeripheralRef};
4use embassy_util::waitqueue::AtomicWaker; 4use embassy_sync::waitqueue::AtomicWaker;
5use futures::future::poll_fn; 5use futures::future::poll_fn;
6 6
7use crate::gpio::sealed::AFType; 7use crate::gpio::sealed::AFType;
diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs
index bd2cd5b57..674255ddc 100644
--- a/embassy-stm32/src/dma/bdma.rs
+++ b/embassy-stm32/src/dma/bdma.rs
@@ -3,7 +3,7 @@
3use core::sync::atomic::{fence, Ordering}; 3use core::sync::atomic::{fence, Ordering};
4use core::task::Waker; 4use core::task::Waker;
5 5
6use embassy_util::waitqueue::AtomicWaker; 6use embassy_sync::waitqueue::AtomicWaker;
7 7
8use super::{TransferOptions, Word, WordSize}; 8use super::{TransferOptions, Word, WordSize};
9use crate::_generated::BDMA_CHANNEL_COUNT; 9use crate::_generated::BDMA_CHANNEL_COUNT;
diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs
index 0c66005c7..a45b8780b 100644
--- a/embassy-stm32/src/dma/dma.rs
+++ b/embassy-stm32/src/dma/dma.rs
@@ -1,7 +1,7 @@
1use core::sync::atomic::{fence, Ordering}; 1use core::sync::atomic::{fence, Ordering};
2use core::task::Waker; 2use core::task::Waker;
3 3
4use embassy_util::waitqueue::AtomicWaker; 4use embassy_sync::waitqueue::AtomicWaker;
5 5
6use super::{Burst, FlowControl, Request, TransferOptions, Word, WordSize}; 6use super::{Burst, FlowControl, Request, TransferOptions, Word, WordSize};
7use crate::_generated::DMA_CHANNEL_COUNT; 7use crate::_generated::DMA_CHANNEL_COUNT;
diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs
index 1aea6c65d..bde8c3ef3 100644
--- a/embassy-stm32/src/dma/gpdma.rs
+++ b/embassy-stm32/src/dma/gpdma.rs
@@ -1,7 +1,7 @@
1use core::sync::atomic::{fence, Ordering}; 1use core::sync::atomic::{fence, Ordering};
2use core::task::Waker; 2use core::task::Waker;
3 3
4use embassy_util::waitqueue::AtomicWaker; 4use embassy_sync::waitqueue::AtomicWaker;
5 5
6use super::{Request, TransferOptions, Word, WordSize}; 6use super::{Request, TransferOptions, Word, WordSize};
7use crate::_generated::GPDMA_CHANNEL_COUNT; 7use crate::_generated::GPDMA_CHANNEL_COUNT;
diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs
index 37593914f..1ab0438ad 100644
--- a/embassy-stm32/src/eth/v1/mod.rs
+++ b/embassy-stm32/src/eth/v1/mod.rs
@@ -7,7 +7,7 @@ use core::task::Waker;
7use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage}; 7use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage};
8use embassy_hal_common::{into_ref, PeripheralRef}; 8use embassy_hal_common::{into_ref, PeripheralRef};
9use embassy_net::{Device, DeviceCapabilities, LinkState, PacketBuf, MTU}; 9use embassy_net::{Device, DeviceCapabilities, LinkState, PacketBuf, MTU};
10use embassy_util::waitqueue::AtomicWaker; 10use embassy_sync::waitqueue::AtomicWaker;
11 11
12use crate::gpio::sealed::{AFType, Pin as __GpioPin}; 12use crate::gpio::sealed::{AFType, Pin as __GpioPin};
13use crate::gpio::{AnyPin, Speed}; 13use crate::gpio::{AnyPin, Speed};
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs
index 1bc1fb72e..d67c3c5e4 100644
--- a/embassy-stm32/src/eth/v2/mod.rs
+++ b/embassy-stm32/src/eth/v2/mod.rs
@@ -5,7 +5,7 @@ use core::task::Waker;
5use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage}; 5use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage};
6use embassy_hal_common::{into_ref, PeripheralRef}; 6use embassy_hal_common::{into_ref, PeripheralRef};
7use embassy_net::{Device, DeviceCapabilities, LinkState, PacketBuf, MTU}; 7use embassy_net::{Device, DeviceCapabilities, LinkState, PacketBuf, MTU};
8use embassy_util::waitqueue::AtomicWaker; 8use embassy_sync::waitqueue::AtomicWaker;
9 9
10use crate::gpio::sealed::{AFType, Pin as _}; 10use crate::gpio::sealed::{AFType, Pin as _};
11use crate::gpio::{AnyPin, Speed}; 11use crate::gpio::{AnyPin, Speed};
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs
index ecb180bbe..935149b13 100644
--- a/embassy-stm32/src/exti.rs
+++ b/embassy-stm32/src/exti.rs
@@ -4,7 +4,7 @@ use core::pin::Pin;
4use core::task::{Context, Poll}; 4use core::task::{Context, Poll};
5 5
6use embassy_hal_common::impl_peripheral; 6use embassy_hal_common::impl_peripheral;
7use embassy_util::waitqueue::AtomicWaker; 7use embassy_sync::waitqueue::AtomicWaker;
8 8
9use crate::gpio::{AnyPin, Input, Pin as GpioPin}; 9use crate::gpio::{AnyPin, Input, Pin as GpioPin};
10use crate::pac::exti::regs::Lines; 10use crate::pac::exti::regs::Lines;
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index b4303d3d4..07a3105da 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -5,7 +5,7 @@ use atomic_polyfill::{AtomicUsize, Ordering};
5use embassy_embedded_hal::SetConfig; 5use embassy_embedded_hal::SetConfig;
6use embassy_hal_common::drop::OnDrop; 6use embassy_hal_common::drop::OnDrop;
7use embassy_hal_common::{into_ref, PeripheralRef}; 7use embassy_hal_common::{into_ref, PeripheralRef};
8use embassy_util::waitqueue::AtomicWaker; 8use embassy_sync::waitqueue::AtomicWaker;
9use futures::future::poll_fn; 9use futures::future::poll_fn;
10 10
11use crate::dma::NoDma; 11use crate::dma::NoDma;
diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs
index 81e28f355..520f2ab9a 100644
--- a/embassy-stm32/src/rng.rs
+++ b/embassy-stm32/src/rng.rs
@@ -3,7 +3,7 @@
3use core::task::Poll; 3use core::task::Poll;
4 4
5use embassy_hal_common::{into_ref, PeripheralRef}; 5use embassy_hal_common::{into_ref, PeripheralRef};
6use embassy_util::waitqueue::AtomicWaker; 6use embassy_sync::waitqueue::AtomicWaker;
7use futures::future::poll_fn; 7use futures::future::poll_fn;
8use rand_core::{CryptoRng, RngCore}; 8use rand_core::{CryptoRng, RngCore};
9 9
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index 3ad31ec87..67758c492 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -5,7 +5,7 @@ use core::task::Poll;
5 5
6use embassy_hal_common::drop::OnDrop; 6use embassy_hal_common::drop::OnDrop;
7use embassy_hal_common::{into_ref, PeripheralRef}; 7use embassy_hal_common::{into_ref, PeripheralRef};
8use embassy_util::waitqueue::AtomicWaker; 8use embassy_sync::waitqueue::AtomicWaker;
9use futures::future::poll_fn; 9use futures::future::poll_fn;
10use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR}; 10use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR};
11 11
@@ -1514,8 +1514,8 @@ foreach_peripheral!(
1514 INNER 1514 INNER
1515 } 1515 }
1516 1516
1517 fn state() -> &'static ::embassy_util::waitqueue::AtomicWaker { 1517 fn state() -> &'static ::embassy_sync::waitqueue::AtomicWaker {
1518 static WAKER: ::embassy_util::waitqueue::AtomicWaker = ::embassy_util::waitqueue::AtomicWaker::new(); 1518 static WAKER: ::embassy_sync::waitqueue::AtomicWaker = ::embassy_sync::waitqueue::AtomicWaker::new();
1519 &WAKER 1519 &WAKER
1520 } 1520 }
1521 } 1521 }
diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs
index 7f4723162..6989a43d3 100644
--- a/embassy-stm32/src/time_driver.rs
+++ b/embassy-stm32/src/time_driver.rs
@@ -4,10 +4,10 @@ use core::sync::atomic::{compiler_fence, Ordering};
4use core::{mem, ptr}; 4use core::{mem, ptr};
5 5
6use atomic_polyfill::{AtomicU32, AtomicU8}; 6use atomic_polyfill::{AtomicU32, AtomicU8};
7use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
8use embassy_sync::blocking_mutex::Mutex;
7use embassy_time::driver::{AlarmHandle, Driver}; 9use embassy_time::driver::{AlarmHandle, Driver};
8use embassy_time::TICKS_PER_SECOND; 10use embassy_time::TICKS_PER_SECOND;
9use embassy_util::blocking_mutex::raw::CriticalSectionRawMutex;
10use embassy_util::blocking_mutex::Mutex;
11use stm32_metapac::timer::regs; 11use stm32_metapac::timer::regs;
12 12
13use crate::interrupt::{CriticalSection, InterruptExt}; 13use crate::interrupt::{CriticalSection, InterruptExt};
diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs
index ec2231e43..a7fa43894 100644
--- a/embassy-stm32/src/usart/buffered.rs
+++ b/embassy-stm32/src/usart/buffered.rs
@@ -4,7 +4,7 @@ use core::task::Poll;
4use atomic_polyfill::{compiler_fence, Ordering}; 4use atomic_polyfill::{compiler_fence, Ordering};
5use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage}; 5use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage};
6use embassy_hal_common::ring_buffer::RingBuffer; 6use embassy_hal_common::ring_buffer::RingBuffer;
7use embassy_util::waitqueue::WakerRegistration; 7use embassy_sync::waitqueue::WakerRegistration;
8use futures::future::poll_fn; 8use futures::future::poll_fn;
9 9
10use super::*; 10use super::*;
diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs
index 3861e42d0..db965824a 100644
--- a/embassy-stm32/src/usb/usb.rs
+++ b/embassy-stm32/src/usb/usb.rs
@@ -6,10 +6,10 @@ use core::task::Poll;
6 6
7use atomic_polyfill::{AtomicBool, AtomicU8}; 7use atomic_polyfill::{AtomicBool, AtomicU8};
8use embassy_hal_common::into_ref; 8use embassy_hal_common::into_ref;
9use embassy_sync::waitqueue::AtomicWaker;
9use embassy_time::{block_for, Duration}; 10use embassy_time::{block_for, Duration};
10use embassy_usb::driver::{self, EndpointAllocError, EndpointError, Event, Unsupported}; 11use embassy_usb::driver::{self, EndpointAllocError, EndpointError, Event, Unsupported};
11use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection}; 12use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection};
12use embassy_util::waitqueue::AtomicWaker;
13use futures::future::poll_fn; 13use futures::future::poll_fn;
14use futures::Future; 14use futures::Future;
15use pac::common::{Reg, RW}; 15use pac::common::{Reg, RW};
diff --git a/embassy-util/Cargo.toml b/embassy-sync/Cargo.toml
index d4708d735..0d14bba55 100644
--- a/embassy-util/Cargo.toml
+++ b/embassy-sync/Cargo.toml
@@ -1,11 +1,11 @@
1[package] 1[package]
2name = "embassy-util" 2name = "embassy-sync"
3version = "0.1.0" 3version = "0.1.0"
4edition = "2021" 4edition = "2021"
5 5
6[package.metadata.embassy_docs] 6[package.metadata.embassy_docs]
7src_base = "https://github.com/embassy-rs/embassy/blob/embassy-util-v$VERSION/embassy-util/src/" 7src_base = "https://github.com/embassy-rs/embassy/blob/embassy-sync-v$VERSION/embassy-sync/src/"
8src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-util/src/" 8src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-sync/src/"
9features = ["nightly"] 9features = ["nightly"]
10target = "thumbv7em-none-eabi" 10target = "thumbv7em-none-eabi"
11 11
@@ -31,3 +31,4 @@ futures-util = { version = "0.3.17", features = [ "channel" ] }
31 31
32# Enable critical-section implementation for std, for tests 32# Enable critical-section implementation for std, for tests
33critical-section = { version = "1.1", features = ["std"] } 33critical-section = { version = "1.1", features = ["std"] }
34static_cell = "1.0"
diff --git a/embassy-sync/README.md b/embassy-sync/README.md
new file mode 100644
index 000000000..106295c0d
--- /dev/null
+++ b/embassy-sync/README.md
@@ -0,0 +1,12 @@
1# embassy-sync
2
3Synchronization primitives and data structures with an async API:
4
5- [`Channel`](channel::Channel) - A Multiple Producer Multiple Consumer (MPMC) channel. Each message is only received by a single consumer.
6- [`PubSubChannel`](pubsub::PubSubChannel) - A broadcast channel (publish-subscribe) channel. Each message is received by all consumers.
7- [`Signal`](signal::Signal) - Signalling latest value to a single consumer.
8- [`Mutex`](mutex::Mutex) - A Mutex for synchronizing state between asynchronous tasks.
9- [`Pipe`](pipe::Pipe) - Byte stream implementing `embedded_io` traits.
10- [`WakerRegistration`](waitqueue::WakerRegistration) - Utility to register and wake a `Waker`.
11- [`AtomicWaker`](waitqueue::AtomicWaker) - A variant of `WakerRegistration` accessible using a non-mut API.
12- [`MultiWakerRegistration`](waitqueue::MultiWakerRegistration) - Utility registering and waking multiple `Waker`'s.
diff --git a/embassy-util/build.rs b/embassy-sync/build.rs
index 6fe82b44f..6fe82b44f 100644
--- a/embassy-util/build.rs
+++ b/embassy-sync/build.rs
diff --git a/embassy-util/src/blocking_mutex/mod.rs b/embassy-sync/src/blocking_mutex/mod.rs
index 8a4a4c642..8a4a4c642 100644
--- a/embassy-util/src/blocking_mutex/mod.rs
+++ b/embassy-sync/src/blocking_mutex/mod.rs
diff --git a/embassy-util/src/blocking_mutex/raw.rs b/embassy-sync/src/blocking_mutex/raw.rs
index 15796f1b2..15796f1b2 100644
--- a/embassy-util/src/blocking_mutex/raw.rs
+++ b/embassy-sync/src/blocking_mutex/raw.rs
diff --git a/embassy-util/src/channel/mpmc.rs b/embassy-sync/src/channel.rs
index 535f77e6f..76f42d0e7 100644
--- a/embassy-util/src/channel/mpmc.rs
+++ b/embassy-sync/src/channel.rs
@@ -373,8 +373,8 @@ where
373 /// Establish a new bounded channel. For example, to create one with a NoopMutex: 373 /// Establish a new bounded channel. For example, to create one with a NoopMutex:
374 /// 374 ///
375 /// ``` 375 /// ```
376 /// use embassy_util::channel::mpmc::Channel; 376 /// use embassy_sync::channel::Channel;
377 /// use embassy_util::blocking_mutex::raw::NoopRawMutex; 377 /// use embassy_sync::blocking_mutex::raw::NoopRawMutex;
378 /// 378 ///
379 /// // Declare a bounded channel of 3 u32s. 379 /// // Declare a bounded channel of 3 u32s.
380 /// let mut channel = Channel::<NoopRawMutex, u32, 3>::new(); 380 /// let mut channel = Channel::<NoopRawMutex, u32, 3>::new();
@@ -471,10 +471,10 @@ mod tests {
471 use futures_executor::ThreadPool; 471 use futures_executor::ThreadPool;
472 use futures_timer::Delay; 472 use futures_timer::Delay;
473 use futures_util::task::SpawnExt; 473 use futures_util::task::SpawnExt;
474 use static_cell::StaticCell;
474 475
475 use super::*; 476 use super::*;
476 use crate::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex}; 477 use crate::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex};
477 use crate::Forever;
478 478
479 fn capacity<T, const N: usize>(c: &ChannelState<T, N>) -> usize { 479 fn capacity<T, const N: usize>(c: &ChannelState<T, N>) -> usize {
480 c.queue.capacity() - c.queue.len() 480 c.queue.capacity() - c.queue.len()
@@ -549,8 +549,8 @@ mod tests {
549 async fn receiver_receives_given_try_send_async() { 549 async fn receiver_receives_given_try_send_async() {
550 let executor = ThreadPool::new().unwrap(); 550 let executor = ThreadPool::new().unwrap();
551 551
552 static CHANNEL: Forever<Channel<CriticalSectionRawMutex, u32, 3>> = Forever::new(); 552 static CHANNEL: StaticCell<Channel<CriticalSectionRawMutex, u32, 3>> = StaticCell::new();
553 let c = &*CHANNEL.put(Channel::new()); 553 let c = &*CHANNEL.init(Channel::new());
554 let c2 = c; 554 let c2 = c;
555 assert!(executor 555 assert!(executor
556 .spawn(async move { 556 .spawn(async move {
@@ -571,8 +571,8 @@ mod tests {
571 async fn senders_sends_wait_until_capacity() { 571 async fn senders_sends_wait_until_capacity() {
572 let executor = ThreadPool::new().unwrap(); 572 let executor = ThreadPool::new().unwrap();
573 573
574 static CHANNEL: Forever<Channel<CriticalSectionRawMutex, u32, 1>> = Forever::new(); 574 static CHANNEL: StaticCell<Channel<CriticalSectionRawMutex, u32, 1>> = StaticCell::new();
575 let c = &*CHANNEL.put(Channel::new()); 575 let c = &*CHANNEL.init(Channel::new());
576 assert!(c.try_send(1).is_ok()); 576 assert!(c.try_send(1).is_ok());
577 577
578 let c2 = c; 578 let c2 = c;
diff --git a/embassy-sync/src/fmt.rs b/embassy-sync/src/fmt.rs
new file mode 100644
index 000000000..f8bb0a035
--- /dev/null
+++ b/embassy-sync/src/fmt.rs
@@ -0,0 +1,228 @@
1#![macro_use]
2#![allow(unused_macros)]
3
4#[cfg(all(feature = "defmt", feature = "log"))]
5compile_error!("You may not enable both `defmt` and `log` features.");
6
7macro_rules! assert {
8 ($($x:tt)*) => {
9 {
10 #[cfg(not(feature = "defmt"))]
11 ::core::assert!($($x)*);
12 #[cfg(feature = "defmt")]
13 ::defmt::assert!($($x)*);
14 }
15 };
16}
17
18macro_rules! assert_eq {
19 ($($x:tt)*) => {
20 {
21 #[cfg(not(feature = "defmt"))]
22 ::core::assert_eq!($($x)*);
23 #[cfg(feature = "defmt")]
24 ::defmt::assert_eq!($($x)*);
25 }
26 };
27}
28
29macro_rules! assert_ne {
30 ($($x:tt)*) => {
31 {
32 #[cfg(not(feature = "defmt"))]
33 ::core::assert_ne!($($x)*);
34 #[cfg(feature = "defmt")]
35 ::defmt::assert_ne!($($x)*);
36 }
37 };
38}
39
40macro_rules! debug_assert {
41 ($($x:tt)*) => {
42 {
43 #[cfg(not(feature = "defmt"))]
44 ::core::debug_assert!($($x)*);
45 #[cfg(feature = "defmt")]
46 ::defmt::debug_assert!($($x)*);
47 }
48 };
49}
50
51macro_rules! debug_assert_eq {
52 ($($x:tt)*) => {
53 {
54 #[cfg(not(feature = "defmt"))]
55 ::core::debug_assert_eq!($($x)*);
56 #[cfg(feature = "defmt")]
57 ::defmt::debug_assert_eq!($($x)*);
58 }
59 };
60}
61
62macro_rules! debug_assert_ne {
63 ($($x:tt)*) => {
64 {
65 #[cfg(not(feature = "defmt"))]
66 ::core::debug_assert_ne!($($x)*);
67 #[cfg(feature = "defmt")]
68 ::defmt::debug_assert_ne!($($x)*);
69 }
70 };
71}
72
73macro_rules! todo {
74 ($($x:tt)*) => {
75 {
76 #[cfg(not(feature = "defmt"))]
77 ::core::todo!($($x)*);
78 #[cfg(feature = "defmt")]
79 ::defmt::todo!($($x)*);
80 }
81 };
82}
83
84macro_rules! unreachable {
85 ($($x:tt)*) => {
86 {
87 #[cfg(not(feature = "defmt"))]
88 ::core::unreachable!($($x)*);
89 #[cfg(feature = "defmt")]
90 ::defmt::unreachable!($($x)*);
91 }
92 };
93}
94
95macro_rules! panic {
96 ($($x:tt)*) => {
97 {
98 #[cfg(not(feature = "defmt"))]
99 ::core::panic!($($x)*);
100 #[cfg(feature = "defmt")]
101 ::defmt::panic!($($x)*);
102 }
103 };
104}
105
106macro_rules! trace {
107 ($s:literal $(, $x:expr)* $(,)?) => {
108 {
109 #[cfg(feature = "log")]
110 ::log::trace!($s $(, $x)*);
111 #[cfg(feature = "defmt")]
112 ::defmt::trace!($s $(, $x)*);
113 #[cfg(not(any(feature = "log", feature="defmt")))]
114 let _ = ($( & $x ),*);
115 }
116 };
117}
118
119macro_rules! debug {
120 ($s:literal $(, $x:expr)* $(,)?) => {
121 {
122 #[cfg(feature = "log")]
123 ::log::debug!($s $(, $x)*);
124 #[cfg(feature = "defmt")]
125 ::defmt::debug!($s $(, $x)*);
126 #[cfg(not(any(feature = "log", feature="defmt")))]
127 let _ = ($( & $x ),*);
128 }
129 };
130}
131
132macro_rules! info {
133 ($s:literal $(, $x:expr)* $(,)?) => {
134 {
135 #[cfg(feature = "log")]
136 ::log::info!($s $(, $x)*);
137 #[cfg(feature = "defmt")]
138 ::defmt::info!($s $(, $x)*);
139 #[cfg(not(any(feature = "log", feature="defmt")))]
140 let _ = ($( & $x ),*);
141 }
142 };
143}
144
145macro_rules! warn {
146 ($s:literal $(, $x:expr)* $(,)?) => {
147 {
148 #[cfg(feature = "log")]
149 ::log::warn!($s $(, $x)*);
150 #[cfg(feature = "defmt")]
151 ::defmt::warn!($s $(, $x)*);
152 #[cfg(not(any(feature = "log", feature="defmt")))]
153 let _ = ($( & $x ),*);
154 }
155 };
156}
157
158macro_rules! error {
159 ($s:literal $(, $x:expr)* $(,)?) => {
160 {
161 #[cfg(feature = "log")]
162 ::log::error!($s $(, $x)*);
163 #[cfg(feature = "defmt")]
164 ::defmt::error!($s $(, $x)*);
165 #[cfg(not(any(feature = "log", feature="defmt")))]
166 let _ = ($( & $x ),*);
167 }
168 };
169}
170
171#[cfg(feature = "defmt")]
172macro_rules! unwrap {
173 ($($x:tt)*) => {
174 ::defmt::unwrap!($($x)*)
175 };
176}
177
178#[cfg(not(feature = "defmt"))]
179macro_rules! unwrap {
180 ($arg:expr) => {
181 match $crate::fmt::Try::into_result($arg) {
182 ::core::result::Result::Ok(t) => t,
183 ::core::result::Result::Err(e) => {
184 ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e);
185 }
186 }
187 };
188 ($arg:expr, $($msg:expr),+ $(,)? ) => {
189 match $crate::fmt::Try::into_result($arg) {
190 ::core::result::Result::Ok(t) => t,
191 ::core::result::Result::Err(e) => {
192 ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e);
193 }
194 }
195 }
196}
197
198#[cfg(feature = "defmt-timestamp-uptime")]
199defmt::timestamp! {"{=u64:us}", crate::time::Instant::now().as_micros() }
200
201#[derive(Debug, Copy, Clone, Eq, PartialEq)]
202pub struct NoneError;
203
204pub trait Try {
205 type Ok;
206 type Error;
207 fn into_result(self) -> Result<Self::Ok, Self::Error>;
208}
209
210impl<T> Try for Option<T> {
211 type Ok = T;
212 type Error = NoneError;
213
214 #[inline]
215 fn into_result(self) -> Result<T, NoneError> {
216 self.ok_or(NoneError)
217 }
218}
219
220impl<T, E> Try for Result<T, E> {
221 type Ok = T;
222 type Error = E;
223
224 #[inline]
225 fn into_result(self) -> Self {
226 self
227 }
228}
diff --git a/embassy-util/src/lib.rs b/embassy-sync/src/lib.rs
index 110c72811..25150e8aa 100644
--- a/embassy-util/src/lib.rs
+++ b/embassy-sync/src/lib.rs
@@ -1,7 +1,7 @@
1#![cfg_attr(not(any(feature = "std", feature = "wasm")), no_std)] 1#![cfg_attr(not(any(feature = "std", feature = "wasm")), no_std)]
2#![cfg_attr(feature = "nightly", feature(generic_associated_types, type_alias_impl_trait))] 2#![cfg_attr(feature = "nightly", feature(generic_associated_types, type_alias_impl_trait))]
3#![allow(clippy::new_without_default)] 3#![allow(clippy::new_without_default)]
4#![doc = include_str!("../../README.md")] 4#![doc = include_str!("../README.md")]
5#![warn(missing_docs)] 5#![warn(missing_docs)]
6 6
7// This mod MUST go first, so that the others see its macros. 7// This mod MUST go first, so that the others see its macros.
@@ -14,12 +14,6 @@ pub mod blocking_mutex;
14pub mod channel; 14pub mod channel;
15pub mod mutex; 15pub mod mutex;
16pub mod pipe; 16pub mod pipe;
17pub mod pubsub;
18pub mod signal;
17pub mod waitqueue; 19pub mod waitqueue;
18
19mod forever;
20mod select;
21mod yield_now;
22
23pub use forever::*;
24pub use select::*;
25pub use yield_now::*;
diff --git a/embassy-util/src/mutex.rs b/embassy-sync/src/mutex.rs
index 75a6e8dd3..75a6e8dd3 100644
--- a/embassy-util/src/mutex.rs
+++ b/embassy-sync/src/mutex.rs
diff --git a/embassy-util/src/pipe.rs b/embassy-sync/src/pipe.rs
index 9c20aeeff..7d64b648e 100644
--- a/embassy-util/src/pipe.rs
+++ b/embassy-sync/src/pipe.rs
@@ -241,8 +241,8 @@ where
241 /// Establish a new bounded pipe. For example, to create one with a NoopMutex: 241 /// Establish a new bounded pipe. For example, to create one with a NoopMutex:
242 /// 242 ///
243 /// ``` 243 /// ```
244 /// use embassy_util::pipe::Pipe; 244 /// use embassy_sync::pipe::Pipe;
245 /// use embassy_util::blocking_mutex::raw::NoopRawMutex; 245 /// use embassy_sync::blocking_mutex::raw::NoopRawMutex;
246 /// 246 ///
247 /// // Declare a bounded pipe, with a buffer of 256 bytes. 247 /// // Declare a bounded pipe, with a buffer of 256 bytes.
248 /// let mut pipe = Pipe::<NoopRawMutex, 256>::new(); 248 /// let mut pipe = Pipe::<NoopRawMutex, 256>::new();
@@ -461,10 +461,10 @@ mod io_impls {
461mod tests { 461mod tests {
462 use futures_executor::ThreadPool; 462 use futures_executor::ThreadPool;
463 use futures_util::task::SpawnExt; 463 use futures_util::task::SpawnExt;
464 use static_cell::StaticCell;
464 465
465 use super::*; 466 use super::*;
466 use crate::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex}; 467 use crate::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex};
467 use crate::Forever;
468 468
469 fn capacity<const N: usize>(c: &PipeState<N>) -> usize { 469 fn capacity<const N: usize>(c: &PipeState<N>) -> usize {
470 N - c.buffer.len() 470 N - c.buffer.len()
@@ -528,8 +528,8 @@ mod tests {
528 async fn receiver_receives_given_try_write_async() { 528 async fn receiver_receives_given_try_write_async() {
529 let executor = ThreadPool::new().unwrap(); 529 let executor = ThreadPool::new().unwrap();
530 530
531 static CHANNEL: Forever<Pipe<CriticalSectionRawMutex, 3>> = Forever::new(); 531 static CHANNEL: StaticCell<Pipe<CriticalSectionRawMutex, 3>> = StaticCell::new();
532 let c = &*CHANNEL.put(Pipe::new()); 532 let c = &*CHANNEL.init(Pipe::new());
533 let c2 = c; 533 let c2 = c;
534 let f = async move { 534 let f = async move {
535 assert_eq!(c2.try_write(&[42]), Ok(1)); 535 assert_eq!(c2.try_write(&[42]), Ok(1));
diff --git a/embassy-util/src/channel/pubsub/mod.rs b/embassy-sync/src/pubsub/mod.rs
index ecc8fbd8f..62a9e4763 100644
--- a/embassy-util/src/channel/pubsub/mod.rs
+++ b/embassy-sync/src/pubsub/mod.rs
@@ -33,9 +33,9 @@ pub use subscriber::{DynSubscriber, Subscriber};
33/// ## Example 33/// ## Example
34/// 34///
35/// ``` 35/// ```
36/// # use embassy_util::blocking_mutex::raw::NoopRawMutex; 36/// # use embassy_sync::blocking_mutex::raw::NoopRawMutex;
37/// # use embassy_util::channel::pubsub::WaitResult; 37/// # use embassy_sync::pubsub::WaitResult;
38/// # use embassy_util::channel::pubsub::PubSubChannel; 38/// # use embassy_sync::pubsub::PubSubChannel;
39/// # use futures_executor::block_on; 39/// # use futures_executor::block_on;
40/// # let test = async { 40/// # let test = async {
41/// // Create the channel. This can be static as well 41/// // Create the channel. This can be static as well
diff --git a/embassy-util/src/channel/pubsub/publisher.rs b/embassy-sync/src/pubsub/publisher.rs
index 705797f60..705797f60 100644
--- a/embassy-util/src/channel/pubsub/publisher.rs
+++ b/embassy-sync/src/pubsub/publisher.rs
diff --git a/embassy-util/src/channel/pubsub/subscriber.rs b/embassy-sync/src/pubsub/subscriber.rs
index b9a2cbe18..b9a2cbe18 100644
--- a/embassy-util/src/channel/pubsub/subscriber.rs
+++ b/embassy-sync/src/pubsub/subscriber.rs
diff --git a/embassy-util/src/ring_buffer.rs b/embassy-sync/src/ring_buffer.rs
index 521084024..521084024 100644
--- a/embassy-util/src/ring_buffer.rs
+++ b/embassy-sync/src/ring_buffer.rs
diff --git a/embassy-util/src/channel/signal.rs b/embassy-sync/src/signal.rs
index 05889f5a4..f6ebeb9b9 100644
--- a/embassy-util/src/channel/signal.rs
+++ b/embassy-sync/src/signal.rs
@@ -6,7 +6,7 @@ use core::task::{Context, Poll, Waker};
6 6
7/// Single-slot signaling primitive. 7/// Single-slot signaling primitive.
8/// 8///
9/// This is similar to a [`Channel`](crate::channel::mpmc::Channel) with a buffer size of 1, except 9/// This is similar to a [`Channel`](crate::channel::Channel) with a buffer size of 1, except
10/// "sending" to it (calling [`Signal::signal`]) when full will overwrite the previous value instead 10/// "sending" to it (calling [`Signal::signal`]) when full will overwrite the previous value instead
11/// of waiting for the receiver to pop the previous value. 11/// of waiting for the receiver to pop the previous value.
12/// 12///
@@ -14,12 +14,12 @@ use core::task::{Context, Poll, Waker};
14/// the latest data, and therefore it's fine to "lose" messages. This is often the case for "state" 14/// the latest data, and therefore it's fine to "lose" messages. This is often the case for "state"
15/// updates. 15/// updates.
16/// 16///
17/// For more advanced use cases, you might want to use [`Channel`](crate::channel::mpmc::Channel) instead. 17/// For more advanced use cases, you might want to use [`Channel`](crate::channel::Channel) instead.
18/// 18///
19/// Signals are generally declared as `static`s and then borrowed as required. 19/// Signals are generally declared as `static`s and then borrowed as required.
20/// 20///
21/// ``` 21/// ```
22/// use embassy_util::channel::signal::Signal; 22/// use embassy_sync::signal::Signal;
23/// 23///
24/// enum SomeCommand { 24/// enum SomeCommand {
25/// On, 25/// On,
diff --git a/embassy-util/src/waitqueue/mod.rs b/embassy-sync/src/waitqueue/mod.rs
index 6661a6b61..6661a6b61 100644
--- a/embassy-util/src/waitqueue/mod.rs
+++ b/embassy-sync/src/waitqueue/mod.rs
diff --git a/embassy-util/src/waitqueue/multi_waker.rs b/embassy-sync/src/waitqueue/multi_waker.rs
index 325d2cb3a..325d2cb3a 100644
--- a/embassy-util/src/waitqueue/multi_waker.rs
+++ b/embassy-sync/src/waitqueue/multi_waker.rs
diff --git a/embassy-util/src/waitqueue/waker.rs b/embassy-sync/src/waitqueue/waker.rs
index 64e300eb8..64e300eb8 100644
--- a/embassy-util/src/waitqueue/waker.rs
+++ b/embassy-sync/src/waitqueue/waker.rs
diff --git a/embassy-time/Cargo.toml b/embassy-time/Cargo.toml
index 161c101fe..f0f622aba 100644
--- a/embassy-time/Cargo.toml
+++ b/embassy-time/Cargo.toml
@@ -49,6 +49,6 @@ critical-section = "1.1"
49cfg-if = "1.0.0" 49cfg-if = "1.0.0"
50 50
51# WASM dependencies 51# WASM dependencies
52wasm-bindgen = { version = "0.2.76", features = ["nightly"], optional = true } 52wasm-bindgen = { version = "0.2.81", optional = true }
53js-sys = { version = "0.3", optional = true } 53js-sys = { version = "0.3", optional = true }
54wasm-timer = { version = "0.2.5", optional = true } \ No newline at end of file 54wasm-timer = { version = "0.2.5", optional = true } \ No newline at end of file
diff --git a/embassy-time/README.md b/embassy-time/README.md
new file mode 100644
index 000000000..2be80ff9c
--- /dev/null
+++ b/embassy-time/README.md
@@ -0,0 +1,43 @@
1# embassy-time
2
3Timekeeping, delays and timeouts.
4
5Timekeeping is done with elapsed time since system boot. Time is represented in
6ticks, where the tick rate is defined by the current driver, usually to match
7the tick rate of the hardware.
8
9Tick counts are 64 bits. At the highest supported tick rate of 1Mhz this supports
10representing time spans of up to ~584558 years, which is big enough for all practical
11purposes and allows not having to worry about overflows.
12
13[`Instant`] represents a given instant of time (relative to system boot), and [`Duration`]
14represents the duration of a span of time. They implement the math operations you'd expect,
15like addition and substraction.
16
17# Delays and timeouts
18
19[`Timer`] allows performing async delays. [`Ticker`] allows periodic delays without drifting over time.
20
21An implementation of the `embedded-hal` delay traits is provided by [`Delay`], for compatibility
22with libraries from the ecosystem.
23
24# Wall-clock time
25
26The `time` module deals exclusively with a monotonically increasing tick count.
27Therefore it has no direct support for wall-clock time ("real life" datetimes
28like `2021-08-24 13:33:21`).
29
30If persistence across reboots is not needed, support can be built on top of
31`embassy_time` by storing the offset between "seconds elapsed since boot"
32and "seconds since unix epoch".
33
34# Time driver
35
36The `time` module is backed by a global "time driver" specified at build time.
37Only one driver can be active in a program.
38
39All methods and structs transparently call into the active driver. This makes it
40possible for libraries to use `embassy_time` in a driver-agnostic way without
41requiring generic parameters.
42
43For more details, check the [`driver`] module.
diff --git a/embassy-time/src/driver.rs b/embassy-time/src/driver.rs
index 216b27408..79ae14b91 100644
--- a/embassy-time/src/driver.rs
+++ b/embassy-time/src/driver.rs
@@ -6,7 +6,7 @@
6//! 6//!
7//! - Define a struct `MyDriver` 7//! - Define a struct `MyDriver`
8//! - Implement [`Driver`] for it 8//! - Implement [`Driver`] for it
9//! - Register it as the global driver with [`time_driver_impl`]. 9//! - Register it as the global driver with [`time_driver_impl`](crate::time_driver_impl).
10//! - Enable the Cargo features `embassy-executor/time` and one of `embassy-time/tick-*` corresponding to the 10//! - Enable the Cargo features `embassy-executor/time` and one of `embassy-time/tick-*` corresponding to the
11//! tick rate of your driver. 11//! tick rate of your driver.
12//! 12//!
diff --git a/embassy-time/src/lib.rs b/embassy-time/src/lib.rs
index a6454d55e..a6c5d78cc 100644
--- a/embassy-time/src/lib.rs
+++ b/embassy-time/src/lib.rs
@@ -1,50 +1,9 @@
1#![cfg_attr(not(any(feature = "std", feature = "wasm")), no_std)] 1#![cfg_attr(not(any(feature = "std", feature = "wasm")), no_std)]
2#![cfg_attr(feature = "nightly", feature(generic_associated_types, type_alias_impl_trait))] 2#![cfg_attr(feature = "nightly", feature(generic_associated_types, type_alias_impl_trait))]
3#![doc = include_str!("../README.md")]
3#![allow(clippy::new_without_default)] 4#![allow(clippy::new_without_default)]
4#![warn(missing_docs)] 5#![warn(missing_docs)]
5 6
6//! Timekeeping, delays and timeouts.
7//!
8//! Timekeeping is done with elapsed time since system boot. Time is represented in
9//! ticks, where the tick rate is defined by the current driver, usually to match
10//! the tick rate of the hardware.
11//!
12//! Tick counts are 64 bits. At the highest supported tick rate of 1Mhz this supports
13//! representing time spans of up to ~584558 years, which is big enough for all practical
14//! purposes and allows not having to worry about overflows.
15//!
16//! [`Instant`] represents a given instant of time (relative to system boot), and [`Duration`]
17//! represents the duration of a span of time. They implement the math operations you'd expect,
18//! like addition and substraction.
19//!
20//! # Delays and timeouts
21//!
22//! [`Timer`] allows performing async delays. [`Ticker`] allows periodic delays without drifting over time.
23//!
24//! An implementation of the `embedded-hal` delay traits is provided by [`Delay`], for compatibility
25//! with libraries from the ecosystem.
26//!
27//! # Wall-clock time
28//!
29//! The `time` module deals exclusively with a monotonically increasing tick count.
30//! Therefore it has no direct support for wall-clock time ("real life" datetimes
31//! like `2021-08-24 13:33:21`).
32//!
33//! If persistence across reboots is not needed, support can be built on top of
34//! `embassy_time` by storing the offset between "seconds elapsed since boot"
35//! and "seconds since unix epoch".
36//!
37//! # Time driver
38//!
39//! The `time` module is backed by a global "time driver" specified at build time.
40//! Only one driver can be active in a program.
41//!
42//! All methods and structs transparently call into the active driver. This makes it
43//! possible for libraries to use `embassy_time` in a driver-agnostic way without
44//! requiring generic parameters.
45//!
46//! For more details, check the [`driver`] module.
47
48// This mod MUST go first, so that the others see its macros. 7// This mod MUST go first, so that the others see its macros.
49pub(crate) mod fmt; 8pub(crate) mod fmt;
50 9
diff --git a/embassy-usb-hid/Cargo.toml b/embassy-usb-hid/Cargo.toml
index 5e9cfebf7..730351485 100644
--- a/embassy-usb-hid/Cargo.toml
+++ b/embassy-usb-hid/Cargo.toml
@@ -14,7 +14,7 @@ default = ["usbd-hid"]
14usbd-hid = ["dep:usbd-hid", "ssmarshal"] 14usbd-hid = ["dep:usbd-hid", "ssmarshal"]
15 15
16[dependencies] 16[dependencies]
17embassy-util = { version = "0.1.0", path = "../embassy-util" } 17embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
18embassy-usb = { version = "0.1.0", path = "../embassy-usb" } 18embassy-usb = { version = "0.1.0", path = "../embassy-usb" }
19 19
20defmt = { version = "0.3", optional = true } 20defmt = { version = "0.3", optional = true }
diff --git a/embassy-usb-ncm/Cargo.toml b/embassy-usb-ncm/Cargo.toml
index 47c1f36bd..15d3db96f 100644
--- a/embassy-usb-ncm/Cargo.toml
+++ b/embassy-usb-ncm/Cargo.toml
@@ -10,7 +10,7 @@ features = ["defmt"]
10target = "thumbv7em-none-eabi" 10target = "thumbv7em-none-eabi"
11 11
12[dependencies] 12[dependencies]
13embassy-util = { version = "0.1.0", path = "../embassy-util" } 13embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
14embassy-usb = { version = "0.1.0", path = "../embassy-usb" } 14embassy-usb = { version = "0.1.0", path = "../embassy-usb" }
15 15
16defmt = { version = "0.3", optional = true } 16defmt = { version = "0.3", optional = true }
diff --git a/embassy-usb-serial/Cargo.toml b/embassy-usb-serial/Cargo.toml
index 633610471..9788588e9 100644
--- a/embassy-usb-serial/Cargo.toml
+++ b/embassy-usb-serial/Cargo.toml
@@ -10,7 +10,7 @@ features = ["defmt"]
10target = "thumbv7em-none-eabi" 10target = "thumbv7em-none-eabi"
11 11
12[dependencies] 12[dependencies]
13embassy-util = { version = "0.1.0", path = "../embassy-util" } 13embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
14embassy-usb = { version = "0.1.0", path = "../embassy-usb" } 14embassy-usb = { version = "0.1.0", path = "../embassy-usb" }
15 15
16defmt = { version = "0.3", optional = true } 16defmt = { version = "0.3", optional = true }
diff --git a/embassy-usb-serial/src/lib.rs b/embassy-usb-serial/src/lib.rs
index e561be9df..f3de2ec1b 100644
--- a/embassy-usb-serial/src/lib.rs
+++ b/embassy-usb-serial/src/lib.rs
@@ -9,11 +9,11 @@ use core::cell::Cell;
9use core::mem::{self, MaybeUninit}; 9use core::mem::{self, MaybeUninit};
10use core::sync::atomic::{AtomicBool, Ordering}; 10use core::sync::atomic::{AtomicBool, Ordering};
11 11
12use embassy_sync::blocking_mutex::CriticalSectionMutex;
12use embassy_usb::control::{self, ControlHandler, InResponse, OutResponse, Request}; 13use embassy_usb::control::{self, ControlHandler, InResponse, OutResponse, Request};
13use embassy_usb::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; 14use embassy_usb::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut};
14use embassy_usb::types::*; 15use embassy_usb::types::*;
15use embassy_usb::Builder; 16use embassy_usb::Builder;
16use embassy_util::blocking_mutex::CriticalSectionMutex;
17 17
18/// This should be used as `device_class` when building the `UsbDevice`. 18/// This should be used as `device_class` when building the `UsbDevice`.
19pub const USB_CLASS_CDC: u8 = 0x02; 19pub const USB_CLASS_CDC: u8 = 0x02;
diff --git a/embassy-usb/Cargo.toml b/embassy-usb/Cargo.toml
index 6adbd399b..8cad4d314 100644
--- a/embassy-usb/Cargo.toml
+++ b/embassy-usb/Cargo.toml
@@ -10,7 +10,7 @@ features = ["defmt"]
10target = "thumbv7em-none-eabi" 10target = "thumbv7em-none-eabi"
11 11
12[dependencies] 12[dependencies]
13embassy-util = { version = "0.1.0", path = "../embassy-util" } 13embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
14 14
15defmt = { version = "0.3", optional = true } 15defmt = { version = "0.3", optional = true }
16log = { version = "0.4.14", optional = true } 16log = { version = "0.4.14", optional = true }
diff --git a/embassy-usb/src/builder.rs b/embassy-usb/src/builder.rs
index 1ca24cc08..6be88bc76 100644
--- a/embassy-usb/src/builder.rs
+++ b/embassy-usb/src/builder.rs
@@ -10,6 +10,7 @@ use crate::{Interface, STRING_INDEX_CUSTOM_START};
10#[derive(Debug, Copy, Clone)] 10#[derive(Debug, Copy, Clone)]
11#[cfg_attr(feature = "defmt", derive(defmt::Format))] 11#[cfg_attr(feature = "defmt", derive(defmt::Format))]
12#[non_exhaustive] 12#[non_exhaustive]
13/// Configuration used when creating [UsbDevice].
13pub struct Config<'a> { 14pub struct Config<'a> {
14 pub(crate) vendor_id: u16, 15 pub(crate) vendor_id: u16,
15 pub(crate) product_id: u16, 16 pub(crate) product_id: u16,
@@ -96,6 +97,7 @@ pub struct Config<'a> {
96} 97}
97 98
98impl<'a> Config<'a> { 99impl<'a> Config<'a> {
100 /// Create default configuration with the provided vid and pid values.
99 pub fn new(vid: u16, pid: u16) -> Self { 101 pub fn new(vid: u16, pid: u16) -> Self {
100 Self { 102 Self {
101 device_class: 0x00, 103 device_class: 0x00,
diff --git a/embassy-usb/src/control.rs b/embassy-usb/src/control.rs
index 12e5303c3..3e5749a01 100644
--- a/embassy-usb/src/control.rs
+++ b/embassy-usb/src/control.rs
@@ -1,3 +1,4 @@
1//! USB control data types.
1use core::mem; 2use core::mem;
2 3
3use super::types::*; 4use super::types::*;
@@ -8,7 +9,7 @@ use super::types::*;
8#[cfg_attr(feature = "defmt", derive(defmt::Format))] 9#[cfg_attr(feature = "defmt", derive(defmt::Format))]
9pub enum RequestType { 10pub enum RequestType {
10 /// Request is a USB standard request. Usually handled by 11 /// Request is a USB standard request. Usually handled by
11 /// [`UsbDevice`](crate::device::UsbDevice). 12 /// [`UsbDevice`](crate::UsbDevice).
12 Standard = 0, 13 Standard = 0,
13 /// Request is intended for a USB class. 14 /// Request is intended for a USB class.
14 Class = 1, 15 Class = 1,
diff --git a/embassy-usb/src/driver.rs b/embassy-usb/src/driver.rs
index 2a84ff9e7..7888f1639 100644
--- a/embassy-usb/src/driver.rs
+++ b/embassy-usb/src/driver.rs
@@ -12,7 +12,7 @@ pub trait Driver<'a> {
12 12
13 /// Allocates an endpoint and specified endpoint parameters. This method is called by the device 13 /// Allocates an endpoint and specified endpoint parameters. This method is called by the device
14 /// and class implementations to allocate endpoints, and can only be called before 14 /// and class implementations to allocate endpoints, and can only be called before
15 /// [`start`](UsbBus::start) is called. 15 /// [`start`](Self::start) is called.
16 /// 16 ///
17 /// # Arguments 17 /// # Arguments
18 /// 18 ///
@@ -95,7 +95,7 @@ pub trait Bus {
95 /// 95 ///
96 /// # Errors 96 /// # Errors
97 /// 97 ///
98 /// * [`Unsupported`](crate::UsbError::Unsupported) - This UsbBus implementation doesn't support 98 /// * [`Unsupported`](crate::driver::Unsupported) - This UsbBus implementation doesn't support
99 /// simulating a disconnect or it has not been enabled at creation time. 99 /// simulating a disconnect or it has not been enabled at creation time.
100 fn force_reset(&mut self) -> Result<(), Unsupported> { 100 fn force_reset(&mut self) -> Result<(), Unsupported> {
101 Err(Unsupported) 101 Err(Unsupported)
@@ -105,7 +105,7 @@ pub trait Bus {
105 /// 105 ///
106 /// # Errors 106 /// # Errors
107 /// 107 ///
108 /// * [`Unsupported`](crate::UsbError::Unsupported) - This UsbBus implementation doesn't support 108 /// * [`Unsupported`](crate::driver::Unsupported) - This UsbBus implementation doesn't support
109 /// remote wakeup or it has not been enabled at creation time. 109 /// remote wakeup or it has not been enabled at creation time.
110 fn remote_wakeup(&mut self) -> Self::RemoteWakeupFuture<'_>; 110 fn remote_wakeup(&mut self) -> Self::RemoteWakeupFuture<'_>;
111} 111}
diff --git a/embassy-usb/src/lib.rs b/embassy-usb/src/lib.rs
index 3f6e13472..5a3f8ba88 100644
--- a/embassy-usb/src/lib.rs
+++ b/embassy-usb/src/lib.rs
@@ -12,7 +12,7 @@ mod descriptor_reader;
12pub mod driver; 12pub mod driver;
13pub mod types; 13pub mod types;
14 14
15use embassy_util::{select, Either}; 15use embassy_futures::{select, Either};
16use heapless::Vec; 16use heapless::Vec;
17 17
18pub use self::builder::{Builder, Config}; 18pub use self::builder::{Builder, Config};
diff --git a/embassy-util/src/channel/mod.rs b/embassy-util/src/channel/mod.rs
deleted file mode 100644
index 5df1f5c5c..000000000
--- a/embassy-util/src/channel/mod.rs
+++ /dev/null
@@ -1,5 +0,0 @@
1//! Async channels
2
3pub mod mpmc;
4pub mod pubsub;
5pub mod signal;
diff --git a/embassy-util/src/forever.rs b/embassy-util/src/forever.rs
deleted file mode 100644
index 4f3698211..000000000
--- a/embassy-util/src/forever.rs
+++ /dev/null
@@ -1,95 +0,0 @@
1use core::cell::UnsafeCell;
2use core::mem::MaybeUninit;
3
4use atomic_polyfill::{AtomicBool, Ordering};
5
6/// Type with static lifetime that may be written to once at runtime.
7///
8/// This may be used to initialize static objects at runtime, typically in the init routine.
9/// This is useful for objects such as Embassy's RTC, which cannot be initialized in a const
10/// context.
11///
12/// Note: IF a global mutable variable is desired, use a CriticalSectionMutex or ThreadModeMutex instead.
13///
14/// ```
15/// use embassy_util::Forever;
16/// // Using an integer for the sake of keeping this example self-contained,
17/// // see https://github.com/embassy-rs/embassy/wiki/Getting-Started for a more "proper" example.
18/// static SOME_INT: Forever<u32> =Forever::new();
19///
20/// // put returns a mutable pointer to the object stored in the forever, which may then be passed
21/// // around.
22/// let mut x = SOME_INT.put(42);
23/// assert_eq!(*x, 42);
24/// ```
25pub struct Forever<T> {
26 used: AtomicBool,
27 t: UnsafeCell<MaybeUninit<T>>,
28}
29
30unsafe impl<T> Send for Forever<T> {}
31unsafe impl<T> Sync for Forever<T> {}
32
33impl<T> Forever<T> {
34 /// Create a new `Forever`.
35 #[inline(always)]
36 pub const fn new() -> Self {
37 Self {
38 used: AtomicBool::new(false),
39 t: UnsafeCell::new(MaybeUninit::uninit()),
40 }
41 }
42
43 /// Store a value in this `Forever`, returning a mutable reference to it.
44 ///
45 /// Using this method, the compiler usually constructs `val` in the stack and then moves
46 /// it into the `Forever`. If `T` is big, this is likely to cause stack overflows.
47 /// Considering using [`Signal::put_with`] instead, which will construct it in-place inside the `Forever`.
48 ///
49 /// # Panics
50 ///
51 /// Panics if this `Forever` already has a value stored in it.
52 #[inline(always)]
53 #[allow(clippy::mut_from_ref)]
54 pub fn put(&'static self, val: T) -> &'static mut T {
55 self.put_with(|| val)
56 }
57
58 /// Store the closure return value in this `Forever`, returning a mutable reference to it.
59 ///
60 /// The advantage over [`Forever::put`] is that this method allows the closure to construct
61 /// the `T` value in-place directly inside the `Forever`, saving stack space.
62 ///
63 /// # Panics
64 ///
65 /// Panics if this `Forever` already has a value stored in it.
66 #[inline(always)]
67 #[allow(clippy::mut_from_ref)]
68 pub fn put_with(&'static self, val: impl FnOnce() -> T) -> &'static mut T {
69 if self
70 .used
71 .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
72 .is_err()
73 {
74 panic!("Forever.put() called multiple times");
75 }
76
77 let p: &'static mut MaybeUninit<T> = unsafe { &mut *self.t.get() };
78 p.write(val())
79 }
80
81 /// Unsafely get a mutable reference to the contents of this Forever.
82 ///
83 /// # Safety
84 ///
85 /// This is undefined behavior if:
86 ///
87 /// - The `Forever` has not been initialized yet (with `put' or `put_with`), or
88 /// - A reference to the contents (mutable or not) already exists.
89 #[inline(always)]
90 #[allow(clippy::mut_from_ref)]
91 pub unsafe fn steal(&self) -> &mut T {
92 let p: &mut MaybeUninit<T> = &mut *self.t.get();
93 p.assume_init_mut()
94 }
95}
diff --git a/examples/boot/application/nrf/Cargo.toml b/examples/boot/application/nrf/Cargo.toml
index ef9346639..b9ff92578 100644
--- a/examples/boot/application/nrf/Cargo.toml
+++ b/examples/boot/application/nrf/Cargo.toml
@@ -4,7 +4,7 @@ name = "embassy-boot-nrf-examples"
4version = "0.1.0" 4version = "0.1.0"
5 5
6[dependencies] 6[dependencies]
7embassy-util = { version = "0.1.0", path = "../../../../embassy-util" } 7embassy-sync = { version = "0.1.0", path = "../../../../embassy-sync" }
8embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["nightly", "integrated-timers"] } 8embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["nightly", "integrated-timers"] }
9embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly"] } 9embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly"] }
10embassy-nrf = { version = "0.1.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", "nightly", "nrf52840"] } 10embassy-nrf = { version = "0.1.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", "nightly", "nrf52840"] }
diff --git a/examples/boot/application/stm32f3/Cargo.toml b/examples/boot/application/stm32f3/Cargo.toml
index 27eafa653..f143d1e8d 100644
--- a/examples/boot/application/stm32f3/Cargo.toml
+++ b/examples/boot/application/stm32f3/Cargo.toml
@@ -4,7 +4,7 @@ name = "embassy-boot-stm32f3-examples"
4version = "0.1.0" 4version = "0.1.0"
5 5
6[dependencies] 6[dependencies]
7embassy-util = { version = "0.1.0", path = "../../../../embassy-util", features = ["defmt"] } 7embassy-sync = { version = "0.1.0", path = "../../../../embassy-sync", features = ["defmt"] }
8embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["nightly", "integrated-timers"] } 8embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["nightly", "integrated-timers"] }
9embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-32768hz"] } 9embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-32768hz"] }
10embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32f303re", "time-driver-any", "exti"] } 10embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32f303re", "time-driver-any", "exti"] }
diff --git a/examples/boot/application/stm32f7/Cargo.toml b/examples/boot/application/stm32f7/Cargo.toml
index 7de0b82d7..29c87eee1 100644
--- a/examples/boot/application/stm32f7/Cargo.toml
+++ b/examples/boot/application/stm32f7/Cargo.toml
@@ -4,7 +4,7 @@ name = "embassy-boot-stm32f7-examples"
4version = "0.1.0" 4version = "0.1.0"
5 5
6[dependencies] 6[dependencies]
7embassy-util = { version = "0.1.0", path = "../../../../embassy-util", features = ["defmt"] } 7embassy-sync = { version = "0.1.0", path = "../../../../embassy-sync", features = ["defmt"] }
8embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["nightly", "integrated-timers"] } 8embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["nightly", "integrated-timers"] }
9embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-32768hz"] } 9embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-32768hz"] }
10embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32f767zi", "time-driver-any", "exti"] } 10embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32f767zi", "time-driver-any", "exti"] }
diff --git a/examples/boot/application/stm32h7/Cargo.toml b/examples/boot/application/stm32h7/Cargo.toml
index 65d34c70b..5669527fe 100644
--- a/examples/boot/application/stm32h7/Cargo.toml
+++ b/examples/boot/application/stm32h7/Cargo.toml
@@ -4,7 +4,7 @@ name = "embassy-boot-stm32h7-examples"
4version = "0.1.0" 4version = "0.1.0"
5 5
6[dependencies] 6[dependencies]
7embassy-util = { version = "0.1.0", path = "../../../../embassy-util", features = ["defmt"] } 7embassy-sync = { version = "0.1.0", path = "../../../../embassy-sync", features = ["defmt"] }
8embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["nightly", "integrated-timers"] } 8embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["nightly", "integrated-timers"] }
9embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-32768hz"] } 9embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-32768hz"] }
10embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32h743zi", "time-driver-any", "exti"] } 10embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32h743zi", "time-driver-any", "exti"] }
diff --git a/examples/boot/application/stm32l0/Cargo.toml b/examples/boot/application/stm32l0/Cargo.toml
index 8f37869e3..48624d5ec 100644
--- a/examples/boot/application/stm32l0/Cargo.toml
+++ b/examples/boot/application/stm32l0/Cargo.toml
@@ -4,7 +4,7 @@ name = "embassy-boot-stm32l0-examples"
4version = "0.1.0" 4version = "0.1.0"
5 5
6[dependencies] 6[dependencies]
7embassy-util = { version = "0.1.0", path = "../../../../embassy-util", features = ["defmt"] } 7embassy-sync = { version = "0.1.0", path = "../../../../embassy-sync", features = ["defmt"] }
8embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["nightly", "integrated-timers"] } 8embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["nightly", "integrated-timers"] }
9embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-32768hz"] } 9embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-32768hz"] }
10embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l072cz", "time-driver-any", "exti", "memory-x"] } 10embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l072cz", "time-driver-any", "exti", "memory-x"] }
diff --git a/examples/boot/application/stm32l1/Cargo.toml b/examples/boot/application/stm32l1/Cargo.toml
index 6abf1986d..00b638ca5 100644
--- a/examples/boot/application/stm32l1/Cargo.toml
+++ b/examples/boot/application/stm32l1/Cargo.toml
@@ -4,7 +4,7 @@ name = "embassy-boot-stm32l1-examples"
4version = "0.1.0" 4version = "0.1.0"
5 5
6[dependencies] 6[dependencies]
7embassy-util = { version = "0.1.0", path = "../../../../embassy-util", features = ["defmt"] } 7embassy-sync = { version = "0.1.0", path = "../../../../embassy-sync", features = ["defmt"] }
8embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["nightly", "integrated-timers"] } 8embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["nightly", "integrated-timers"] }
9embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-32768hz"] } 9embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-32768hz"] }
10embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l151cb-a", "time-driver-any", "exti"] } 10embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l151cb-a", "time-driver-any", "exti"] }
diff --git a/examples/boot/application/stm32l4/Cargo.toml b/examples/boot/application/stm32l4/Cargo.toml
index 6f2d12ff1..51ba730d5 100644
--- a/examples/boot/application/stm32l4/Cargo.toml
+++ b/examples/boot/application/stm32l4/Cargo.toml
@@ -4,7 +4,7 @@ name = "embassy-boot-stm32l4-examples"
4version = "0.1.0" 4version = "0.1.0"
5 5
6[dependencies] 6[dependencies]
7embassy-util = { version = "0.1.0", path = "../../../../embassy-util", features = ["defmt"] } 7embassy-sync = { version = "0.1.0", path = "../../../../embassy-sync", features = ["defmt"] }
8embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["nightly", "integrated-timers"] } 8embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["nightly", "integrated-timers"] }
9embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-32768hz"] } 9embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-32768hz"] }
10embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l475vg", "time-driver-any", "exti"] } 10embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l475vg", "time-driver-any", "exti"] }
diff --git a/examples/boot/application/stm32wl/Cargo.toml b/examples/boot/application/stm32wl/Cargo.toml
index be97d4ebb..182acf694 100644
--- a/examples/boot/application/stm32wl/Cargo.toml
+++ b/examples/boot/application/stm32wl/Cargo.toml
@@ -4,7 +4,7 @@ name = "embassy-boot-stm32wl-examples"
4version = "0.1.0" 4version = "0.1.0"
5 5
6[dependencies] 6[dependencies]
7embassy-util = { version = "0.1.0", path = "../../../../embassy-util", features = ["defmt"] } 7embassy-sync = { version = "0.1.0", path = "../../../../embassy-sync", features = ["defmt"] }
8embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["nightly", "integrated-timers"] } 8embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["nightly", "integrated-timers"] }
9embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-32768hz"] } 9embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-32768hz"] }
10embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32wl55jc-cm4", "time-driver-any", "exti"] } 10embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32wl55jc-cm4", "time-driver-any", "exti"] }
diff --git a/examples/nrf-rtos-trace/.cargo/config.toml b/examples/nrf-rtos-trace/.cargo/config.toml
new file mode 100644
index 000000000..8ca28df39
--- /dev/null
+++ b/examples/nrf-rtos-trace/.cargo/config.toml
@@ -0,0 +1,9 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2# replace nRF82840_xxAA with your chip as listed in `probe-run --list-chips`
3runner = "probe-run --chip nRF52840_xxAA"
4
5[build]
6target = "thumbv7em-none-eabi"
7
8[env]
9DEFMT_LOG = "trace"
diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml
new file mode 100644
index 000000000..87c9f33f5
--- /dev/null
+++ b/examples/nrf-rtos-trace/Cargo.toml
@@ -0,0 +1,35 @@
1[package]
2edition = "2021"
3name = "embassy-nrf-rtos-trace-examples"
4version = "0.1.0"
5
6[features]
7default = ["log", "nightly"]
8nightly = ["embassy-executor/nightly", "embassy-nrf/nightly", "embassy-nrf/unstable-traits"]
9log = [
10 "dep:log",
11 "embassy-sync/log",
12 "embassy-executor/log",
13 "embassy-time/log",
14 "embassy-nrf/log",
15]
16
17[dependencies]
18embassy-sync = { version = "0.1.0", path = "../../embassy-sync" }
19embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features=["rtos-trace", "rtos-trace-interrupt", "integrated-timers"] }
20embassy-time = { version = "0.1.0", path = "../../embassy-time" }
21embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] }
22
23cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
24cortex-m-rt = "0.7.0"
25panic-probe = { version = "0.3" }
26futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
27rand = { version = "0.8.4", default-features = false }
28serde = { version = "1.0.136", default-features = false }
29rtos-trace = "0.1.3"
30systemview-target = { version = "0.1.2", features = ["callbacks-app", "callbacks-os", "log", "cortex-m"] }
31log = { version = "0.4.17", optional = true }
32
33[[bin]]
34name = "rtos_trace"
35required-features = ["nightly"]
diff --git a/examples/nrf-rtos-trace/build.rs b/examples/nrf-rtos-trace/build.rs
new file mode 100644
index 000000000..36cdb65a8
--- /dev/null
+++ b/examples/nrf-rtos-trace/build.rs
@@ -0,0 +1,36 @@
1//! This build script copies the `memory.x` file from the crate root into
2//! a directory where the linker can always find it at build time.
3//! For many projects this is optional, as the linker always searches the
4//! project root directory -- wherever `Cargo.toml` is. However, if you
5//! are using a workspace or have a more complicated build setup, this
6//! build script becomes required. Additionally, by requesting that
7//! Cargo re-run the build script whenever `memory.x` is changed,
8//! updating `memory.x` ensures a rebuild of the application with the
9//! new memory settings.
10
11use std::env;
12use std::fs::File;
13use std::io::Write;
14use std::path::PathBuf;
15
16fn main() {
17 // Put `memory.x` in our output directory and ensure it's
18 // on the linker search path.
19 let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
20 File::create(out.join("memory.x"))
21 .unwrap()
22 .write_all(include_bytes!("memory.x"))
23 .unwrap();
24 println!("cargo:rustc-link-search={}", out.display());
25
26 // By default, Cargo will re-run a build script whenever
27 // any file in the project changes. By specifying `memory.x`
28 // here, we ensure the build script is only re-run when
29 // `memory.x` is changed.
30 println!("cargo:rerun-if-changed=memory.x");
31
32 println!("cargo:rustc-link-arg-bins=--nmagic");
33 println!("cargo:rustc-link-arg-bins=-Tlink.x");
34 #[cfg(feature = "defmt")]
35 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
36}
diff --git a/examples/nrf-rtos-trace/memory.x b/examples/nrf-rtos-trace/memory.x
new file mode 100644
index 000000000..9b04edec0
--- /dev/null
+++ b/examples/nrf-rtos-trace/memory.x
@@ -0,0 +1,7 @@
1MEMORY
2{
3 /* NOTE 1 K = 1 KiBi = 1024 bytes */
4 /* These values correspond to the NRF52840 with Softdevices S140 7.0.1 */
5 FLASH : ORIGIN = 0x00000000, LENGTH = 1024K
6 RAM : ORIGIN = 0x20000000, LENGTH = 256K
7}
diff --git a/examples/nrf-rtos-trace/src/bin/rtos_trace.rs b/examples/nrf-rtos-trace/src/bin/rtos_trace.rs
new file mode 100644
index 000000000..7d1ad87c8
--- /dev/null
+++ b/examples/nrf-rtos-trace/src/bin/rtos_trace.rs
@@ -0,0 +1,69 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use core::task::Poll;
6
7use embassy_executor::Spawner;
8use embassy_time::{Duration, Instant, Timer};
9#[cfg(feature = "log")]
10use log::*;
11use panic_probe as _;
12// N.B. systemview_target cannot be used at the same time as defmt_rtt.
13use rtos_trace;
14use systemview_target::SystemView;
15
16static LOGGER: systemview_target::SystemView = systemview_target::SystemView::new();
17rtos_trace::global_trace! {SystemView}
18
19struct TraceInfo();
20
21impl rtos_trace::RtosTraceApplicationCallbacks for TraceInfo {
22 fn system_description() {}
23 fn sysclock() -> u32 {
24 64000000
25 }
26}
27rtos_trace::global_application_callbacks! {TraceInfo}
28
29#[embassy_executor::task]
30async fn run1() {
31 loop {
32 #[cfg(feature = "log")]
33 info!("DING DONG");
34 #[cfg(not(feature = "log"))]
35 rtos_trace::trace::marker(13);
36 Timer::after(Duration::from_ticks(16000)).await;
37 }
38}
39
40#[embassy_executor::task]
41async fn run2() {
42 loop {
43 Timer::at(Instant::from_ticks(0)).await;
44 }
45}
46
47#[embassy_executor::task]
48async fn run3() {
49 futures::future::poll_fn(|cx| {
50 cx.waker().wake_by_ref();
51 Poll::<()>::Pending
52 })
53 .await;
54}
55
56#[embassy_executor::main]
57async fn main(spawner: Spawner) {
58 let _p = embassy_nrf::init(Default::default());
59 LOGGER.init();
60 #[cfg(feature = "log")]
61 {
62 ::log::set_logger(&LOGGER).ok();
63 ::log::set_max_level(::log::LevelFilter::Trace);
64 }
65
66 spawner.spawn(run1()).unwrap();
67 spawner.spawn(run2()).unwrap();
68 spawner.spawn(run3()).unwrap();
69}
diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml
index 876dcf734..8309dda08 100644
--- a/examples/nrf/Cargo.toml
+++ b/examples/nrf/Cargo.toml
@@ -8,7 +8,8 @@ default = ["nightly"]
8nightly = ["embassy-executor/nightly", "embassy-nrf/nightly", "embassy-nrf/unstable-traits", "embassy-usb", "embassy-usb-serial", "embassy-usb-hid", "embassy-usb-ncm", "embedded-io/async", "embassy-net"] 8nightly = ["embassy-executor/nightly", "embassy-nrf/nightly", "embassy-nrf/unstable-traits", "embassy-usb", "embassy-usb-serial", "embassy-usb-hid", "embassy-usb-ncm", "embedded-io/async", "embassy-net"]
9 9
10[dependencies] 10[dependencies]
11embassy-util = { version = "0.1.0", path = "../../embassy-util", features = ["defmt"] } 11embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
12embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
12embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } 13embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
13embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 14embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
14embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } 15embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] }
@@ -22,6 +23,7 @@ embedded-io = "0.3.0"
22defmt = "0.3" 23defmt = "0.3"
23defmt-rtt = "0.3" 24defmt-rtt = "0.3"
24 25
26static_cell = "1.0"
25cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } 27cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
26cortex-m-rt = "0.7.0" 28cortex-m-rt = "0.7.0"
27panic-probe = { version = "0.3", features = ["print-defmt"] } 29panic-probe = { version = "0.3", features = ["print-defmt"] }
diff --git a/examples/nrf/src/bin/channel.rs b/examples/nrf/src/bin/channel.rs
index 195200988..d782a79e7 100644
--- a/examples/nrf/src/bin/channel.rs
+++ b/examples/nrf/src/bin/channel.rs
@@ -5,9 +5,9 @@
5use defmt::unwrap; 5use defmt::unwrap;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::gpio::{Level, Output, OutputDrive}; 7use embassy_nrf::gpio::{Level, Output, OutputDrive};
8use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
9use embassy_sync::channel::Channel;
8use embassy_time::{Duration, Timer}; 10use embassy_time::{Duration, Timer};
9use embassy_util::blocking_mutex::raw::ThreadModeRawMutex;
10use embassy_util::channel::mpmc::Channel;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13enum LedState { 13enum LedState {
diff --git a/examples/nrf/src/bin/channel_sender_receiver.rs b/examples/nrf/src/bin/channel_sender_receiver.rs
index c9c458aec..fcccdaed5 100644
--- a/examples/nrf/src/bin/channel_sender_receiver.rs
+++ b/examples/nrf/src/bin/channel_sender_receiver.rs
@@ -5,10 +5,10 @@
5use defmt::unwrap; 5use defmt::unwrap;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::gpio::{AnyPin, Level, Output, OutputDrive, Pin}; 7use embassy_nrf::gpio::{AnyPin, Level, Output, OutputDrive, Pin};
8use embassy_sync::blocking_mutex::raw::NoopRawMutex;
9use embassy_sync::channel::{Channel, Receiver, Sender};
8use embassy_time::{Duration, Timer}; 10use embassy_time::{Duration, Timer};
9use embassy_util::blocking_mutex::raw::NoopRawMutex; 11use static_cell::StaticCell;
10use embassy_util::channel::mpmc::{Channel, Receiver, Sender};
11use embassy_util::Forever;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14enum LedState { 14enum LedState {
@@ -16,7 +16,7 @@ enum LedState {
16 Off, 16 Off,
17} 17}
18 18
19static CHANNEL: Forever<Channel<NoopRawMutex, LedState, 1>> = Forever::new(); 19static CHANNEL: StaticCell<Channel<NoopRawMutex, LedState, 1>> = StaticCell::new();
20 20
21#[embassy_executor::task] 21#[embassy_executor::task]
22async fn send_task(sender: Sender<'static, NoopRawMutex, LedState, 1>) { 22async fn send_task(sender: Sender<'static, NoopRawMutex, LedState, 1>) {
@@ -43,7 +43,7 @@ async fn recv_task(led: AnyPin, receiver: Receiver<'static, NoopRawMutex, LedSta
43#[embassy_executor::main] 43#[embassy_executor::main]
44async fn main(spawner: Spawner) { 44async fn main(spawner: Spawner) {
45 let p = embassy_nrf::init(Default::default()); 45 let p = embassy_nrf::init(Default::default());
46 let channel = CHANNEL.put(Channel::new()); 46 let channel = CHANNEL.init(Channel::new());
47 47
48 unwrap!(spawner.spawn(send_task(channel.sender()))); 48 unwrap!(spawner.spawn(send_task(channel.sender())));
49 unwrap!(spawner.spawn(recv_task(p.P0_13.degrade(), channel.receiver()))); 49 unwrap!(spawner.spawn(recv_task(p.P0_13.degrade(), channel.receiver())));
diff --git a/examples/nrf/src/bin/multiprio.rs b/examples/nrf/src/bin/multiprio.rs
index b653689a7..25806ae48 100644
--- a/examples/nrf/src/bin/multiprio.rs
+++ b/examples/nrf/src/bin/multiprio.rs
@@ -63,7 +63,7 @@ use embassy_nrf::executor::{Executor, InterruptExecutor};
63use embassy_nrf::interrupt; 63use embassy_nrf::interrupt;
64use embassy_nrf::interrupt::InterruptExt; 64use embassy_nrf::interrupt::InterruptExt;
65use embassy_time::{Duration, Instant, Timer}; 65use embassy_time::{Duration, Instant, Timer};
66use embassy_util::Forever; 66use static_cell::StaticCell;
67use {defmt_rtt as _, panic_probe as _}; 67use {defmt_rtt as _, panic_probe as _};
68 68
69#[embassy_executor::task] 69#[embassy_executor::task]
@@ -108,9 +108,9 @@ async fn run_low() {
108 } 108 }
109} 109}
110 110
111static EXECUTOR_HIGH: Forever<InterruptExecutor<interrupt::SWI1_EGU1>> = Forever::new(); 111static EXECUTOR_HIGH: StaticCell<InterruptExecutor<interrupt::SWI1_EGU1>> = StaticCell::new();
112static EXECUTOR_MED: Forever<InterruptExecutor<interrupt::SWI0_EGU0>> = Forever::new(); 112static EXECUTOR_MED: StaticCell<InterruptExecutor<interrupt::SWI0_EGU0>> = StaticCell::new();
113static EXECUTOR_LOW: Forever<Executor> = Forever::new(); 113static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new();
114 114
115#[entry] 115#[entry]
116fn main() -> ! { 116fn main() -> ! {
@@ -121,19 +121,19 @@ fn main() -> ! {
121 // High-priority executor: SWI1_EGU1, priority level 6 121 // High-priority executor: SWI1_EGU1, priority level 6
122 let irq = interrupt::take!(SWI1_EGU1); 122 let irq = interrupt::take!(SWI1_EGU1);
123 irq.set_priority(interrupt::Priority::P6); 123 irq.set_priority(interrupt::Priority::P6);
124 let executor = EXECUTOR_HIGH.put(InterruptExecutor::new(irq)); 124 let executor = EXECUTOR_HIGH.init(InterruptExecutor::new(irq));
125 let spawner = executor.start(); 125 let spawner = executor.start();
126 unwrap!(spawner.spawn(run_high())); 126 unwrap!(spawner.spawn(run_high()));
127 127
128 // Medium-priority executor: SWI0_EGU0, priority level 7 128 // Medium-priority executor: SWI0_EGU0, priority level 7
129 let irq = interrupt::take!(SWI0_EGU0); 129 let irq = interrupt::take!(SWI0_EGU0);
130 irq.set_priority(interrupt::Priority::P7); 130 irq.set_priority(interrupt::Priority::P7);
131 let executor = EXECUTOR_MED.put(InterruptExecutor::new(irq)); 131 let executor = EXECUTOR_MED.init(InterruptExecutor::new(irq));
132 let spawner = executor.start(); 132 let spawner = executor.start();
133 unwrap!(spawner.spawn(run_med())); 133 unwrap!(spawner.spawn(run_med()));
134 134
135 // Low priority executor: runs in thread mode, using WFE/SEV 135 // Low priority executor: runs in thread mode, using WFE/SEV
136 let executor = EXECUTOR_LOW.put(Executor::new()); 136 let executor = EXECUTOR_LOW.init(Executor::new());
137 executor.run(|spawner| { 137 executor.run(|spawner| {
138 unwrap!(spawner.spawn(run_low())); 138 unwrap!(spawner.spawn(run_low()));
139 }); 139 });
diff --git a/examples/nrf/src/bin/mutex.rs b/examples/nrf/src/bin/mutex.rs
index 876297883..c402c6ba1 100644
--- a/examples/nrf/src/bin/mutex.rs
+++ b/examples/nrf/src/bin/mutex.rs
@@ -4,9 +4,9 @@
4 4
5use defmt::{info, unwrap}; 5use defmt::{info, unwrap};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
8use embassy_sync::mutex::Mutex;
7use embassy_time::{Duration, Timer}; 9use embassy_time::{Duration, Timer};
8use embassy_util::blocking_mutex::raw::ThreadModeRawMutex;
9use embassy_util::mutex::Mutex;
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12static MUTEX: Mutex<ThreadModeRawMutex, u32> = Mutex::new(0); 12static MUTEX: Mutex<ThreadModeRawMutex, u32> = Mutex::new(0);
diff --git a/examples/nrf/src/bin/pubsub.rs b/examples/nrf/src/bin/pubsub.rs
index 1d90217f2..688e6d075 100644
--- a/examples/nrf/src/bin/pubsub.rs
+++ b/examples/nrf/src/bin/pubsub.rs
@@ -4,9 +4,9 @@
4 4
5use defmt::unwrap; 5use defmt::unwrap;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
8use embassy_sync::pubsub::{DynSubscriber, PubSubChannel, Subscriber};
7use embassy_time::{Duration, Timer}; 9use embassy_time::{Duration, Timer};
8use embassy_util::blocking_mutex::raw::ThreadModeRawMutex;
9use embassy_util::channel::pubsub::{DynSubscriber, PubSubChannel, Subscriber};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12/// Create the message bus. It has a queue of 4, supports 3 subscribers and 1 publisher 12/// Create the message bus. It has a queue of 4, supports 3 subscribers and 1 publisher
diff --git a/examples/nrf/src/bin/raw_spawn.rs b/examples/nrf/src/bin/raw_spawn.rs
index 415579be7..1b067f5e4 100644
--- a/examples/nrf/src/bin/raw_spawn.rs
+++ b/examples/nrf/src/bin/raw_spawn.rs
@@ -8,7 +8,7 @@ use defmt::{info, unwrap};
8use embassy_executor::raw::TaskStorage; 8use embassy_executor::raw::TaskStorage;
9use embassy_executor::Executor; 9use embassy_executor::Executor;
10use embassy_time::{Duration, Timer}; 10use embassy_time::{Duration, Timer};
11use embassy_util::Forever; 11use static_cell::StaticCell;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14async fn run1() { 14async fn run1() {
@@ -25,14 +25,14 @@ async fn run2() {
25 } 25 }
26} 26}
27 27
28static EXECUTOR: Forever<Executor> = Forever::new(); 28static EXECUTOR: StaticCell<Executor> = StaticCell::new();
29 29
30#[entry] 30#[entry]
31fn main() -> ! { 31fn main() -> ! {
32 info!("Hello World!"); 32 info!("Hello World!");
33 33
34 let _p = embassy_nrf::init(Default::default()); 34 let _p = embassy_nrf::init(Default::default());
35 let executor = EXECUTOR.put(Executor::new()); 35 let executor = EXECUTOR.init(Executor::new());
36 36
37 let run1_task = TaskStorage::new(); 37 let run1_task = TaskStorage::new();
38 let run2_task = TaskStorage::new(); 38 let run2_task = TaskStorage::new();
diff --git a/examples/nrf/src/bin/uart_split.rs b/examples/nrf/src/bin/uart_split.rs
index dab8e475d..1adaf53fd 100644
--- a/examples/nrf/src/bin/uart_split.rs
+++ b/examples/nrf/src/bin/uart_split.rs
@@ -7,8 +7,8 @@ use embassy_executor::Spawner;
7use embassy_nrf::peripherals::UARTE0; 7use embassy_nrf::peripherals::UARTE0;
8use embassy_nrf::uarte::UarteRx; 8use embassy_nrf::uarte::UarteRx;
9use embassy_nrf::{interrupt, uarte}; 9use embassy_nrf::{interrupt, uarte};
10use embassy_util::blocking_mutex::raw::ThreadModeRawMutex; 10use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
11use embassy_util::channel::mpmc::Channel; 11use embassy_sync::channel::Channel;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14static CHANNEL: Channel<ThreadModeRawMutex, [u8; 8], 1> = Channel::new(); 14static CHANNEL: Channel<ThreadModeRawMutex, [u8; 8], 1> = Channel::new();
diff --git a/examples/nrf/src/bin/usb_ethernet.rs b/examples/nrf/src/bin/usb_ethernet.rs
index f0a870317..ca6c7e0d1 100644
--- a/examples/nrf/src/bin/usb_ethernet.rs
+++ b/examples/nrf/src/bin/usb_ethernet.rs
@@ -14,21 +14,21 @@ use embassy_net::{PacketBox, PacketBoxExt, PacketBuf, Stack, StackResources};
14use embassy_nrf::rng::Rng; 14use embassy_nrf::rng::Rng;
15use embassy_nrf::usb::{Driver, PowerUsb}; 15use embassy_nrf::usb::{Driver, PowerUsb};
16use embassy_nrf::{interrupt, pac, peripherals}; 16use embassy_nrf::{interrupt, pac, peripherals};
17use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
18use embassy_sync::channel::Channel;
17use embassy_usb::{Builder, Config, UsbDevice}; 19use embassy_usb::{Builder, Config, UsbDevice};
18use embassy_usb_ncm::{CdcNcmClass, Receiver, Sender, State}; 20use embassy_usb_ncm::{CdcNcmClass, Receiver, Sender, State};
19use embassy_util::blocking_mutex::raw::ThreadModeRawMutex;
20use embassy_util::channel::mpmc::Channel;
21use embassy_util::Forever;
22use embedded_io::asynch::{Read, Write}; 21use embedded_io::asynch::{Read, Write};
22use static_cell::StaticCell;
23use {defmt_rtt as _, panic_probe as _}; 23use {defmt_rtt as _, panic_probe as _};
24 24
25type MyDriver = Driver<'static, peripherals::USBD, PowerUsb>; 25type MyDriver = Driver<'static, peripherals::USBD, PowerUsb>;
26 26
27macro_rules! forever { 27macro_rules! singleton {
28 ($val:expr) => {{ 28 ($val:expr) => {{
29 type T = impl Sized; 29 type T = impl Sized;
30 static FOREVER: Forever<T> = Forever::new(); 30 static STATIC_CELL: StaticCell<T> = StaticCell::new();
31 FOREVER.put_with(move || $val) 31 STATIC_CELL.init_with(move || $val)
32 }}; 32 }};
33} 33}
34 34
@@ -116,7 +116,7 @@ async fn main(spawner: Spawner) {
116 control_buf: [u8; 128], 116 control_buf: [u8; 128],
117 serial_state: State<'static>, 117 serial_state: State<'static>,
118 } 118 }
119 let res: &mut Resources = forever!(Resources { 119 let res: &mut Resources = singleton!(Resources {
120 device_descriptor: [0; 256], 120 device_descriptor: [0; 256],
121 config_descriptor: [0; 256], 121 config_descriptor: [0; 256],
122 bos_descriptor: [0; 256], 122 bos_descriptor: [0; 256],
@@ -174,10 +174,10 @@ async fn main(spawner: Spawner) {
174 174
175 // Init network stack 175 // Init network stack
176 let device = Device { mac_addr: our_mac_addr }; 176 let device = Device { mac_addr: our_mac_addr };
177 let stack = &*forever!(Stack::new( 177 let stack = &*singleton!(Stack::new(
178 device, 178 device,
179 config, 179 config,
180 forever!(StackResources::<1, 2, 8>::new()), 180 singleton!(StackResources::<1, 2, 8>::new()),
181 seed 181 seed
182 )); 182 ));
183 183
diff --git a/examples/nrf/src/bin/usb_hid_keyboard.rs b/examples/nrf/src/bin/usb_hid_keyboard.rs
index cf0078eec..ba2159c72 100644
--- a/examples/nrf/src/bin/usb_hid_keyboard.rs
+++ b/examples/nrf/src/bin/usb_hid_keyboard.rs
@@ -8,14 +8,14 @@ use core::sync::atomic::{AtomicBool, Ordering};
8 8
9use defmt::*; 9use defmt::*;
10use embassy_executor::Spawner; 10use embassy_executor::Spawner;
11use embassy_futures::{select, Either};
11use embassy_nrf::gpio::{Input, Pin, Pull}; 12use embassy_nrf::gpio::{Input, Pin, Pull};
12use embassy_nrf::usb::{Driver, PowerUsb}; 13use embassy_nrf::usb::{Driver, PowerUsb};
13use embassy_nrf::{interrupt, pac}; 14use embassy_nrf::{interrupt, pac};
15use embassy_sync::signal::Signal;
14use embassy_usb::control::OutResponse; 16use embassy_usb::control::OutResponse;
15use embassy_usb::{Builder, Config, DeviceStateHandler}; 17use embassy_usb::{Builder, Config, DeviceStateHandler};
16use embassy_usb_hid::{HidReaderWriter, ReportId, RequestHandler, State}; 18use embassy_usb_hid::{HidReaderWriter, ReportId, RequestHandler, State};
17use embassy_util::channel::signal::Signal;
18use embassy_util::{select, Either};
19use futures::future::join; 19use futures::future::join;
20use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; 20use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor};
21use {defmt_rtt as _, panic_probe as _}; 21use {defmt_rtt as _, panic_probe as _};
diff --git a/examples/nrf/src/bin/usb_serial_multitask.rs b/examples/nrf/src/bin/usb_serial_multitask.rs
index 4c1a93087..d62d7e520 100644
--- a/examples/nrf/src/bin/usb_serial_multitask.rs
+++ b/examples/nrf/src/bin/usb_serial_multitask.rs
@@ -12,7 +12,7 @@ use embassy_nrf::{interrupt, pac, peripherals};
12use embassy_usb::driver::EndpointError; 12use embassy_usb::driver::EndpointError;
13use embassy_usb::{Builder, Config, UsbDevice}; 13use embassy_usb::{Builder, Config, UsbDevice};
14use embassy_usb_serial::{CdcAcmClass, State}; 14use embassy_usb_serial::{CdcAcmClass, State};
15use embassy_util::Forever; 15use static_cell::StaticCell;
16use {defmt_rtt as _, panic_probe as _}; 16use {defmt_rtt as _, panic_probe as _};
17 17
18type MyDriver = Driver<'static, peripherals::USBD, PowerUsb>; 18type MyDriver = Driver<'static, peripherals::USBD, PowerUsb>;
@@ -67,8 +67,8 @@ async fn main(spawner: Spawner) {
67 control_buf: [u8; 64], 67 control_buf: [u8; 64],
68 serial_state: State<'static>, 68 serial_state: State<'static>,
69 } 69 }
70 static RESOURCES: Forever<Resources> = Forever::new(); 70 static RESOURCES: StaticCell<Resources> = StaticCell::new();
71 let res = RESOURCES.put(Resources { 71 let res = RESOURCES.init(Resources {
72 device_descriptor: [0; 256], 72 device_descriptor: [0; 256],
73 config_descriptor: [0; 256], 73 config_descriptor: [0; 256],
74 bos_descriptor: [0; 256], 74 bos_descriptor: [0; 256],
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml
index c2dcf429a..d804a660b 100644
--- a/examples/rp/Cargo.toml
+++ b/examples/rp/Cargo.toml
@@ -5,7 +5,7 @@ version = "0.1.0"
5 5
6 6
7[dependencies] 7[dependencies]
8embassy-util = { version = "0.1.0", path = "../../embassy-util", features = ["defmt"] } 8embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
9embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } 9embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
10embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 10embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
11embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac"] } 11embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac"] }
diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml
index b7009017c..c7cec6b19 100644
--- a/examples/std/Cargo.toml
+++ b/examples/std/Cargo.toml
@@ -4,7 +4,7 @@ name = "embassy-std-examples"
4version = "0.1.0" 4version = "0.1.0"
5 5
6[dependencies] 6[dependencies]
7embassy-util = { version = "0.1.0", path = "../../embassy-util", features = ["log"] } 7embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["log"] }
8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["log", "std", "nightly", "integrated-timers"] } 8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["log", "std", "nightly", "integrated-timers"] }
9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["log", "std", "nightly"] } 9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["log", "std", "nightly"] }
10embassy-net = { version = "0.1.0", path = "../../embassy-net", features=[ "std", "log", "medium-ethernet", "tcp", "udp", "dhcpv4", "pool-16"] } 10embassy-net = { version = "0.1.0", path = "../../embassy-net", features=[ "std", "log", "medium-ethernet", "tcp", "udp", "dhcpv4", "pool-16"] }
@@ -20,3 +20,4 @@ libc = "0.2.101"
20clap = { version = "3.0.0-beta.5", features = ["derive"] } 20clap = { version = "3.0.0-beta.5", features = ["derive"] }
21rand_core = { version = "0.6.3", features = ["std"] } 21rand_core = { version = "0.6.3", features = ["std"] }
22heapless = { version = "0.7.5", default-features = false } 22heapless = { version = "0.7.5", default-features = false }
23static_cell = "1.0"
diff --git a/examples/std/src/bin/net.rs b/examples/std/src/bin/net.rs
index 528609260..9b1450b72 100644
--- a/examples/std/src/bin/net.rs
+++ b/examples/std/src/bin/net.rs
@@ -4,22 +4,22 @@ use clap::Parser;
4use embassy_executor::{Executor, Spawner}; 4use embassy_executor::{Executor, Spawner};
5use embassy_net::tcp::TcpSocket; 5use embassy_net::tcp::TcpSocket;
6use embassy_net::{ConfigStrategy, Ipv4Address, Ipv4Cidr, Stack, StackResources}; 6use embassy_net::{ConfigStrategy, Ipv4Address, Ipv4Cidr, Stack, StackResources};
7use embassy_util::Forever;
8use embedded_io::asynch::Write; 7use embedded_io::asynch::Write;
9use heapless::Vec; 8use heapless::Vec;
10use log::*; 9use log::*;
11use rand_core::{OsRng, RngCore}; 10use rand_core::{OsRng, RngCore};
11use static_cell::StaticCell;
12 12
13#[path = "../tuntap.rs"] 13#[path = "../tuntap.rs"]
14mod tuntap; 14mod tuntap;
15 15
16use crate::tuntap::TunTapDevice; 16use crate::tuntap::TunTapDevice;
17 17
18macro_rules! forever { 18macro_rules! singleton {
19 ($val:expr) => {{ 19 ($val:expr) => {{
20 type T = impl Sized; 20 type T = impl Sized;
21 static FOREVER: Forever<T> = Forever::new(); 21 static STATIC_CELL: StaticCell<T> = StaticCell::new();
22 FOREVER.put_with(move || $val) 22 STATIC_CELL.init_with(move || $val)
23 }}; 23 }};
24} 24}
25 25
@@ -63,10 +63,10 @@ async fn main_task(spawner: Spawner) {
63 let seed = u64::from_le_bytes(seed); 63 let seed = u64::from_le_bytes(seed);
64 64
65 // Init network stack 65 // Init network stack
66 let stack = &*forever!(Stack::new( 66 let stack = &*singleton!(Stack::new(
67 device, 67 device,
68 config, 68 config,
69 forever!(StackResources::<1, 2, 8>::new()), 69 singleton!(StackResources::<1, 2, 8>::new()),
70 seed 70 seed
71 )); 71 ));
72 72
@@ -97,7 +97,7 @@ async fn main_task(spawner: Spawner) {
97 } 97 }
98} 98}
99 99
100static EXECUTOR: Forever<Executor> = Forever::new(); 100static EXECUTOR: StaticCell<Executor> = StaticCell::new();
101 101
102fn main() { 102fn main() {
103 env_logger::builder() 103 env_logger::builder()
@@ -106,7 +106,7 @@ fn main() {
106 .format_timestamp_nanos() 106 .format_timestamp_nanos()
107 .init(); 107 .init();
108 108
109 let executor = EXECUTOR.put(Executor::new()); 109 let executor = EXECUTOR.init(Executor::new());
110 executor.run(|spawner| { 110 executor.run(|spawner| {
111 spawner.spawn(main_task(spawner)).unwrap(); 111 spawner.spawn(main_task(spawner)).unwrap();
112 }); 112 });
diff --git a/examples/std/src/bin/net_udp.rs b/examples/std/src/bin/net_udp.rs
index 07e11c385..392a97f0d 100644
--- a/examples/std/src/bin/net_udp.rs
+++ b/examples/std/src/bin/net_udp.rs
@@ -4,21 +4,21 @@ use clap::Parser;
4use embassy_executor::{Executor, Spawner}; 4use embassy_executor::{Executor, Spawner};
5use embassy_net::udp::UdpSocket; 5use embassy_net::udp::UdpSocket;
6use embassy_net::{ConfigStrategy, Ipv4Address, Ipv4Cidr, PacketMetadata, Stack, StackResources}; 6use embassy_net::{ConfigStrategy, Ipv4Address, Ipv4Cidr, PacketMetadata, Stack, StackResources};
7use embassy_util::Forever;
8use heapless::Vec; 7use heapless::Vec;
9use log::*; 8use log::*;
10use rand_core::{OsRng, RngCore}; 9use rand_core::{OsRng, RngCore};
10use static_cell::StaticCell;
11 11
12#[path = "../tuntap.rs"] 12#[path = "../tuntap.rs"]
13mod tuntap; 13mod tuntap;
14 14
15use crate::tuntap::TunTapDevice; 15use crate::tuntap::TunTapDevice;
16 16
17macro_rules! forever { 17macro_rules! singleton {
18 ($val:expr) => {{ 18 ($val:expr) => {{
19 type T = impl Sized; 19 type T = impl Sized;
20 static FOREVER: Forever<T> = Forever::new(); 20 static STATIC_CELL: StaticCell<T> = StaticCell::new();
21 FOREVER.put_with(move || $val) 21 STATIC_CELL.init_with(move || $val)
22 }}; 22 }};
23} 23}
24 24
@@ -62,10 +62,10 @@ async fn main_task(spawner: Spawner) {
62 let seed = u64::from_le_bytes(seed); 62 let seed = u64::from_le_bytes(seed);
63 63
64 // Init network stack 64 // Init network stack
65 let stack = &*forever!(Stack::new( 65 let stack = &*singleton!(Stack::new(
66 device, 66 device,
67 config, 67 config,
68 forever!(StackResources::<1, 2, 8>::new()), 68 singleton!(StackResources::<1, 2, 8>::new()),
69 seed 69 seed
70 )); 70 ));
71 71
@@ -93,7 +93,7 @@ async fn main_task(spawner: Spawner) {
93 } 93 }
94} 94}
95 95
96static EXECUTOR: Forever<Executor> = Forever::new(); 96static EXECUTOR: StaticCell<Executor> = StaticCell::new();
97 97
98fn main() { 98fn main() {
99 env_logger::builder() 99 env_logger::builder()
@@ -102,7 +102,7 @@ fn main() {
102 .format_timestamp_nanos() 102 .format_timestamp_nanos()
103 .init(); 103 .init();
104 104
105 let executor = EXECUTOR.put(Executor::new()); 105 let executor = EXECUTOR.init(Executor::new());
106 executor.run(|spawner| { 106 executor.run(|spawner| {
107 spawner.spawn(main_task(spawner)).unwrap(); 107 spawner.spawn(main_task(spawner)).unwrap();
108 }); 108 });
diff --git a/examples/std/src/bin/serial.rs b/examples/std/src/bin/serial.rs
index 35cba4cee..85ee54f70 100644
--- a/examples/std/src/bin/serial.rs
+++ b/examples/std/src/bin/serial.rs
@@ -5,10 +5,10 @@ mod serial_port;
5 5
6use async_io::Async; 6use async_io::Async;
7use embassy_executor::Executor; 7use embassy_executor::Executor;
8use embassy_util::Forever;
9use embedded_io::asynch::Read; 8use embedded_io::asynch::Read;
10use log::*; 9use log::*;
11use nix::sys::termios; 10use nix::sys::termios;
11use static_cell::StaticCell;
12 12
13use self::serial_port::SerialPort; 13use self::serial_port::SerialPort;
14 14
@@ -40,7 +40,7 @@ async fn run() {
40 } 40 }
41} 41}
42 42
43static EXECUTOR: Forever<Executor> = Forever::new(); 43static EXECUTOR: StaticCell<Executor> = StaticCell::new();
44 44
45fn main() { 45fn main() {
46 env_logger::builder() 46 env_logger::builder()
@@ -49,7 +49,7 @@ fn main() {
49 .format_timestamp_nanos() 49 .format_timestamp_nanos()
50 .init(); 50 .init();
51 51
52 let executor = EXECUTOR.put(Executor::new()); 52 let executor = EXECUTOR.init(Executor::new());
53 executor.run(|spawner| { 53 executor.run(|spawner| {
54 spawner.spawn(run()).unwrap(); 54 spawner.spawn(run()).unwrap();
55 }); 55 });
diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml
index 8476200d4..cd2995d2c 100644
--- a/examples/stm32f0/Cargo.toml
+++ b/examples/stm32f0/Cargo.toml
@@ -11,7 +11,7 @@ cortex-m-rt = "0.7.0"
11defmt = "0.3" 11defmt = "0.3"
12defmt-rtt = "0.3" 12defmt-rtt = "0.3"
13panic-probe = "0.3" 13panic-probe = "0.3"
14embassy-util = { version = "0.1.0", path = "../../embassy-util", features = ["defmt"] } 14embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
15embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } 15embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
16embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] } 16embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] }
17embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "memory-x", "stm32f030f4", "time-driver-any"] } 17embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "memory-x", "stm32f030f4", "time-driver-any"] }
diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml
index fbc96400c..8660e743d 100644
--- a/examples/stm32f1/Cargo.toml
+++ b/examples/stm32f1/Cargo.toml
@@ -4,7 +4,7 @@ name = "embassy-stm32f1-examples"
4version = "0.1.0" 4version = "0.1.0"
5 5
6[dependencies] 6[dependencies]
7embassy-util = { version = "0.1.0", path = "../../embassy-util", features = ["defmt"] } 7embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } 8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] } 9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] }
10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any"] } 10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any"] }
diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml
index 27894df50..b4bff4d85 100644
--- a/examples/stm32f2/Cargo.toml
+++ b/examples/stm32f2/Cargo.toml
@@ -4,7 +4,7 @@ name = "embassy-stm32f2-examples"
4version = "0.1.0" 4version = "0.1.0"
5 5
6[dependencies] 6[dependencies]
7embassy-util = { version = "0.1.0", path = "../../embassy-util", features = ["defmt"] } 7embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } 8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] } 9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] }
10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] } 10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] }
diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml
index b5ea28bb6..d152b145f 100644
--- a/examples/stm32f3/Cargo.toml
+++ b/examples/stm32f3/Cargo.toml
@@ -4,7 +4,7 @@ name = "embassy-stm32f3-examples"
4version = "0.1.0" 4version = "0.1.0"
5 5
6[dependencies] 6[dependencies]
7embassy-util = { version = "0.1.0", path = "../../embassy-util", features = ["defmt"] } 7embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } 8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] } 9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] }
10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-any", "exti"] } 10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-any", "exti"] }
@@ -23,3 +23,4 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa
23heapless = { version = "0.7.5", default-features = false } 23heapless = { version = "0.7.5", default-features = false }
24nb = "1.0.0" 24nb = "1.0.0"
25embedded-storage = "0.3.0" 25embedded-storage = "0.3.0"
26static_cell = "1.0"
diff --git a/examples/stm32f3/src/bin/button_events.rs b/examples/stm32f3/src/bin/button_events.rs
index 61fc6dcab..02c475f66 100644
--- a/examples/stm32f3/src/bin/button_events.rs
+++ b/examples/stm32f3/src/bin/button_events.rs
@@ -15,9 +15,9 @@ use embassy_executor::Spawner;
15use embassy_stm32::exti::ExtiInput; 15use embassy_stm32::exti::ExtiInput;
16use embassy_stm32::gpio::{AnyPin, Input, Level, Output, Pin, Pull, Speed}; 16use embassy_stm32::gpio::{AnyPin, Input, Level, Output, Pin, Pull, Speed};
17use embassy_stm32::peripherals::PA0; 17use embassy_stm32::peripherals::PA0;
18use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
19use embassy_sync::channel::Channel;
18use embassy_time::{with_timeout, Duration, Timer}; 20use embassy_time::{with_timeout, Duration, Timer};
19use embassy_util::blocking_mutex::raw::ThreadModeRawMutex;
20use embassy_util::channel::mpmc::Channel;
21use {defmt_rtt as _, panic_probe as _}; 21use {defmt_rtt as _, panic_probe as _};
22 22
23struct Leds<'a> { 23struct Leds<'a> {
diff --git a/examples/stm32f3/src/bin/multiprio.rs b/examples/stm32f3/src/bin/multiprio.rs
index e96c31249..9e8228a4b 100644
--- a/examples/stm32f3/src/bin/multiprio.rs
+++ b/examples/stm32f3/src/bin/multiprio.rs
@@ -63,7 +63,7 @@ use embassy_stm32::executor::{Executor, InterruptExecutor};
63use embassy_stm32::interrupt; 63use embassy_stm32::interrupt;
64use embassy_stm32::interrupt::InterruptExt; 64use embassy_stm32::interrupt::InterruptExt;
65use embassy_time::{Duration, Instant, Timer}; 65use embassy_time::{Duration, Instant, Timer};
66use embassy_util::Forever; 66use static_cell::StaticCell;
67use {defmt_rtt as _, panic_probe as _}; 67use {defmt_rtt as _, panic_probe as _};
68 68
69#[embassy_executor::task] 69#[embassy_executor::task]
@@ -108,9 +108,9 @@ async fn run_low() {
108 } 108 }
109} 109}
110 110
111static EXECUTOR_HIGH: Forever<InterruptExecutor<interrupt::UART4>> = Forever::new(); 111static EXECUTOR_HIGH: StaticCell<InterruptExecutor<interrupt::UART4>> = StaticCell::new();
112static EXECUTOR_MED: Forever<InterruptExecutor<interrupt::UART5>> = Forever::new(); 112static EXECUTOR_MED: StaticCell<InterruptExecutor<interrupt::UART5>> = StaticCell::new();
113static EXECUTOR_LOW: Forever<Executor> = Forever::new(); 113static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new();
114 114
115#[entry] 115#[entry]
116fn main() -> ! { 116fn main() -> ! {
@@ -121,19 +121,19 @@ fn main() -> ! {
121 // High-priority executor: SWI1_EGU1, priority level 6 121 // High-priority executor: SWI1_EGU1, priority level 6
122 let irq = interrupt::take!(UART4); 122 let irq = interrupt::take!(UART4);
123 irq.set_priority(interrupt::Priority::P6); 123 irq.set_priority(interrupt::Priority::P6);
124 let executor = EXECUTOR_HIGH.put(InterruptExecutor::new(irq)); 124 let executor = EXECUTOR_HIGH.init(InterruptExecutor::new(irq));
125 let spawner = executor.start(); 125 let spawner = executor.start();
126 unwrap!(spawner.spawn(run_high())); 126 unwrap!(spawner.spawn(run_high()));
127 127
128 // Medium-priority executor: SWI0_EGU0, priority level 7 128 // Medium-priority executor: SWI0_EGU0, priority level 7
129 let irq = interrupt::take!(UART5); 129 let irq = interrupt::take!(UART5);
130 irq.set_priority(interrupt::Priority::P7); 130 irq.set_priority(interrupt::Priority::P7);
131 let executor = EXECUTOR_MED.put(InterruptExecutor::new(irq)); 131 let executor = EXECUTOR_MED.init(InterruptExecutor::new(irq));
132 let spawner = executor.start(); 132 let spawner = executor.start();
133 unwrap!(spawner.spawn(run_med())); 133 unwrap!(spawner.spawn(run_med()));
134 134
135 // Low priority executor: runs in thread mode, using WFE/SEV 135 // Low priority executor: runs in thread mode, using WFE/SEV
136 let executor = EXECUTOR_LOW.put(Executor::new()); 136 let executor = EXECUTOR_LOW.init(Executor::new());
137 executor.run(|spawner| { 137 executor.run(|spawner| {
138 unwrap!(spawner.spawn(run_low())); 138 unwrap!(spawner.spawn(run_low()));
139 }); 139 });
diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml
index 04a217aff..9bfdda92d 100644
--- a/examples/stm32f4/Cargo.toml
+++ b/examples/stm32f4/Cargo.toml
@@ -5,7 +5,7 @@ version = "0.1.0"
5 5
6 6
7[dependencies] 7[dependencies]
8embassy-util = { version = "0.1.0", path = "../../embassy-util", features = ["defmt"] } 8embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
9embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } 9embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
10embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-32768hz"] } 10embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-32768hz"] }
11embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti"] } 11embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti"] }
@@ -23,6 +23,7 @@ heapless = { version = "0.7.5", default-features = false }
23nb = "1.0.0" 23nb = "1.0.0"
24embedded-storage = "0.3.0" 24embedded-storage = "0.3.0"
25micromath = "2.0.0" 25micromath = "2.0.0"
26static_cell = "1.0"
26 27
27usb-device = "0.2" 28usb-device = "0.2"
28usbd-serial = "0.1.1" 29usbd-serial = "0.1.1"
diff --git a/examples/stm32f4/src/bin/multiprio.rs b/examples/stm32f4/src/bin/multiprio.rs
index e96c31249..9e8228a4b 100644
--- a/examples/stm32f4/src/bin/multiprio.rs
+++ b/examples/stm32f4/src/bin/multiprio.rs
@@ -63,7 +63,7 @@ use embassy_stm32::executor::{Executor, InterruptExecutor};
63use embassy_stm32::interrupt; 63use embassy_stm32::interrupt;
64use embassy_stm32::interrupt::InterruptExt; 64use embassy_stm32::interrupt::InterruptExt;
65use embassy_time::{Duration, Instant, Timer}; 65use embassy_time::{Duration, Instant, Timer};
66use embassy_util::Forever; 66use static_cell::StaticCell;
67use {defmt_rtt as _, panic_probe as _}; 67use {defmt_rtt as _, panic_probe as _};
68 68
69#[embassy_executor::task] 69#[embassy_executor::task]
@@ -108,9 +108,9 @@ async fn run_low() {
108 } 108 }
109} 109}
110 110
111static EXECUTOR_HIGH: Forever<InterruptExecutor<interrupt::UART4>> = Forever::new(); 111static EXECUTOR_HIGH: StaticCell<InterruptExecutor<interrupt::UART4>> = StaticCell::new();
112static EXECUTOR_MED: Forever<InterruptExecutor<interrupt::UART5>> = Forever::new(); 112static EXECUTOR_MED: StaticCell<InterruptExecutor<interrupt::UART5>> = StaticCell::new();
113static EXECUTOR_LOW: Forever<Executor> = Forever::new(); 113static EXECUTOR_LOW: StaticCell<Executor> = StaticCell::new();
114 114
115#[entry] 115#[entry]
116fn main() -> ! { 116fn main() -> ! {
@@ -121,19 +121,19 @@ fn main() -> ! {
121 // High-priority executor: SWI1_EGU1, priority level 6 121 // High-priority executor: SWI1_EGU1, priority level 6
122 let irq = interrupt::take!(UART4); 122 let irq = interrupt::take!(UART4);
123 irq.set_priority(interrupt::Priority::P6); 123 irq.set_priority(interrupt::Priority::P6);
124 let executor = EXECUTOR_HIGH.put(InterruptExecutor::new(irq)); 124 let executor = EXECUTOR_HIGH.init(InterruptExecutor::new(irq));
125 let spawner = executor.start(); 125 let spawner = executor.start();
126 unwrap!(spawner.spawn(run_high())); 126 unwrap!(spawner.spawn(run_high()));
127 127
128 // Medium-priority executor: SWI0_EGU0, priority level 7 128 // Medium-priority executor: SWI0_EGU0, priority level 7
129 let irq = interrupt::take!(UART5); 129 let irq = interrupt::take!(UART5);
130 irq.set_priority(interrupt::Priority::P7); 130 irq.set_priority(interrupt::Priority::P7);
131 let executor = EXECUTOR_MED.put(InterruptExecutor::new(irq)); 131 let executor = EXECUTOR_MED.init(InterruptExecutor::new(irq));
132 let spawner = executor.start(); 132 let spawner = executor.start();
133 unwrap!(spawner.spawn(run_med())); 133 unwrap!(spawner.spawn(run_med()));
134 134
135 // Low priority executor: runs in thread mode, using WFE/SEV 135 // Low priority executor: runs in thread mode, using WFE/SEV
136 let executor = EXECUTOR_LOW.put(Executor::new()); 136 let executor = EXECUTOR_LOW.init(Executor::new());
137 executor.run(|spawner| { 137 executor.run(|spawner| {
138 unwrap!(spawner.spawn(run_low())); 138 unwrap!(spawner.spawn(run_low()));
139 }); 139 });
diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml
index 29d6da4d8..a446fe3fb 100644
--- a/examples/stm32f7/Cargo.toml
+++ b/examples/stm32f7/Cargo.toml
@@ -4,7 +4,7 @@ name = "embassy-stm32f7-examples"
4version = "0.1.0" 4version = "0.1.0"
5 5
6[dependencies] 6[dependencies]
7embassy-util = { version = "0.1.0", path = "../../embassy-util", features = ["defmt"] } 7embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } 8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] } 9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] }
10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "net", "stm32f767zi", "unstable-pac", "time-driver-any", "exti"] } 10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "net", "stm32f767zi", "unstable-pac", "time-driver-any", "exti"] }
@@ -24,3 +24,4 @@ nb = "1.0.0"
24rand_core = "0.6.3" 24rand_core = "0.6.3"
25critical-section = "1.1" 25critical-section = "1.1"
26embedded-storage = "0.3.0" 26embedded-storage = "0.3.0"
27static_cell = "1.0"
diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs
index bdffabcb3..5202edf62 100644
--- a/examples/stm32f7/src/bin/eth.rs
+++ b/examples/stm32f7/src/bin/eth.rs
@@ -13,16 +13,16 @@ use embassy_stm32::rng::Rng;
13use embassy_stm32::time::mhz; 13use embassy_stm32::time::mhz;
14use embassy_stm32::{interrupt, Config}; 14use embassy_stm32::{interrupt, Config};
15use embassy_time::{Duration, Timer}; 15use embassy_time::{Duration, Timer};
16use embassy_util::Forever;
17use embedded_io::asynch::Write; 16use embedded_io::asynch::Write;
18use rand_core::RngCore; 17use rand_core::RngCore;
18use static_cell::StaticCell;
19use {defmt_rtt as _, panic_probe as _}; 19use {defmt_rtt as _, panic_probe as _};
20 20
21macro_rules! forever { 21macro_rules! singleton {
22 ($val:expr) => {{ 22 ($val:expr) => {{
23 type T = impl Sized; 23 type T = impl Sized;
24 static FOREVER: Forever<T> = Forever::new(); 24 static STATIC_CELL: StaticCell<T> = StaticCell::new();
25 FOREVER.put_with(move || $val) 25 STATIC_CELL.init_with(move || $val)
26 }}; 26 }};
27} 27}
28 28
@@ -52,7 +52,7 @@ async fn main(spawner: Spawner) -> ! {
52 52
53 let device = unsafe { 53 let device = unsafe {
54 Ethernet::new( 54 Ethernet::new(
55 forever!(State::new()), 55 singleton!(State::new()),
56 p.ETH, 56 p.ETH,
57 eth_int, 57 eth_int,
58 p.PA1, 58 p.PA1,
@@ -78,10 +78,10 @@ async fn main(spawner: Spawner) -> ! {
78 //}); 78 //});
79 79
80 // Init network stack 80 // Init network stack
81 let stack = &*forever!(Stack::new( 81 let stack = &*singleton!(Stack::new(
82 device, 82 device,
83 config, 83 config,
84 forever!(StackResources::<1, 2, 8>::new()), 84 singleton!(StackResources::<1, 2, 8>::new()),
85 seed 85 seed
86 )); 86 ));
87 87
diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml
index 5c80d43eb..30f2b86f8 100644
--- a/examples/stm32g0/Cargo.toml
+++ b/examples/stm32g0/Cargo.toml
@@ -4,7 +4,7 @@ name = "embassy-stm32g0-examples"
4version = "0.1.0" 4version = "0.1.0"
5 5
6[dependencies] 6[dependencies]
7embassy-util = { version = "0.1.0", path = "../../embassy-util", features = ["defmt"] } 7embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } 8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] } 9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] }
10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g071rb", "memory-x", "unstable-pac", "exti"] } 10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g071rb", "memory-x", "unstable-pac", "exti"] }
diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml
index 74c645cf5..f81df0b70 100644
--- a/examples/stm32g4/Cargo.toml
+++ b/examples/stm32g4/Cargo.toml
@@ -4,7 +4,7 @@ name = "embassy-stm32g4-examples"
4version = "0.1.0" 4version = "0.1.0"
5 5
6[dependencies] 6[dependencies]
7embassy-util = { version = "0.1.0", path = "../../embassy-util", features = ["defmt"] } 7embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } 8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] } 9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] }
10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] } 10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] }
diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml
index a416796ea..0f76f3226 100644
--- a/examples/stm32h7/Cargo.toml
+++ b/examples/stm32h7/Cargo.toml
@@ -4,7 +4,7 @@ name = "embassy-stm32h7-examples"
4version = "0.1.0" 4version = "0.1.0"
5 5
6[dependencies] 6[dependencies]
7embassy-util = { version = "0.1.0", path = "../../embassy-util", features = ["defmt"] } 7embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } 8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-32768hz"] } 9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-32768hz"] }
10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h743bi", "net", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] } 10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h743bi", "net", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] }
@@ -28,6 +28,7 @@ critical-section = "1.1"
28micromath = "2.0.0" 28micromath = "2.0.0"
29stm32-fmc = "0.2.4" 29stm32-fmc = "0.2.4"
30embedded-storage = "0.3.0" 30embedded-storage = "0.3.0"
31static_cell = "1.0"
31 32
32# cargo build/run 33# cargo build/run
33[profile.dev] 34[profile.dev]
diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs
index 83210bcb5..4ccc0b5ef 100644
--- a/examples/stm32h7/src/bin/eth.rs
+++ b/examples/stm32h7/src/bin/eth.rs
@@ -13,16 +13,16 @@ use embassy_stm32::rng::Rng;
13use embassy_stm32::time::mhz; 13use embassy_stm32::time::mhz;
14use embassy_stm32::{interrupt, Config}; 14use embassy_stm32::{interrupt, Config};
15use embassy_time::{Duration, Timer}; 15use embassy_time::{Duration, Timer};
16use embassy_util::Forever;
17use embedded_io::asynch::Write; 16use embedded_io::asynch::Write;
18use rand_core::RngCore; 17use rand_core::RngCore;
18use static_cell::StaticCell;
19use {defmt_rtt as _, panic_probe as _}; 19use {defmt_rtt as _, panic_probe as _};
20 20
21macro_rules! forever { 21macro_rules! singleton {
22 ($val:expr) => {{ 22 ($val:expr) => {{
23 type T = impl Sized; 23 type T = impl Sized;
24 static FOREVER: Forever<T> = Forever::new(); 24 static STATIC_CELL: StaticCell<T> = StaticCell::new();
25 FOREVER.put_with(move || $val) 25 STATIC_CELL.init_with(move || $val)
26 }}; 26 }};
27} 27}
28 28
@@ -53,7 +53,7 @@ async fn main(spawner: Spawner) -> ! {
53 53
54 let device = unsafe { 54 let device = unsafe {
55 Ethernet::new( 55 Ethernet::new(
56 forever!(State::new()), 56 singleton!(State::new()),
57 p.ETH, 57 p.ETH,
58 eth_int, 58 eth_int,
59 p.PA1, 59 p.PA1,
@@ -79,10 +79,10 @@ async fn main(spawner: Spawner) -> ! {
79 //}); 79 //});
80 80
81 // Init network stack 81 // Init network stack
82 let stack = &*forever!(Stack::new( 82 let stack = &*singleton!(Stack::new(
83 device, 83 device,
84 config, 84 config,
85 forever!(StackResources::<1, 2, 8>::new()), 85 singleton!(StackResources::<1, 2, 8>::new()),
86 seed 86 seed
87 )); 87 ));
88 88
diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs
index 99946f504..64fd84141 100644
--- a/examples/stm32h7/src/bin/eth_client.rs
+++ b/examples/stm32h7/src/bin/eth_client.rs
@@ -13,17 +13,17 @@ use embassy_stm32::rng::Rng;
13use embassy_stm32::time::mhz; 13use embassy_stm32::time::mhz;
14use embassy_stm32::{interrupt, Config}; 14use embassy_stm32::{interrupt, Config};
15use embassy_time::{Duration, Timer}; 15use embassy_time::{Duration, Timer};
16use embassy_util::Forever;
17use embedded_io::asynch::Write; 16use embedded_io::asynch::Write;
18use embedded_nal_async::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpConnect}; 17use embedded_nal_async::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpConnect};
19use rand_core::RngCore; 18use rand_core::RngCore;
19use static_cell::StaticCell;
20use {defmt_rtt as _, panic_probe as _}; 20use {defmt_rtt as _, panic_probe as _};
21 21
22macro_rules! forever { 22macro_rules! singleton {
23 ($val:expr) => {{ 23 ($val:expr) => {{
24 type T = impl Sized; 24 type T = impl Sized;
25 static FOREVER: Forever<T> = Forever::new(); 25 static STATIC_CELL: StaticCell<T> = StaticCell::new();
26 FOREVER.put_with(move || $val) 26 STATIC_CELL.init_with(move || $val)
27 }}; 27 }};
28} 28}
29 29
@@ -54,7 +54,7 @@ async fn main(spawner: Spawner) -> ! {
54 54
55 let device = unsafe { 55 let device = unsafe {
56 Ethernet::new( 56 Ethernet::new(
57 forever!(State::new()), 57 singleton!(State::new()),
58 p.ETH, 58 p.ETH,
59 eth_int, 59 eth_int,
60 p.PA1, 60 p.PA1,
@@ -80,10 +80,10 @@ async fn main(spawner: Spawner) -> ! {
80 //}); 80 //});
81 81
82 // Init network stack 82 // Init network stack
83 let stack = &*forever!(Stack::new( 83 let stack = &*singleton!(Stack::new(
84 device, 84 device,
85 config, 85 config,
86 forever!(StackResources::<1, 2, 8>::new()), 86 singleton!(StackResources::<1, 2, 8>::new()),
87 seed 87 seed
88 )); 88 ));
89 89
diff --git a/examples/stm32h7/src/bin/signal.rs b/examples/stm32h7/src/bin/signal.rs
index be2ac268e..cc3e4e3ca 100644
--- a/examples/stm32h7/src/bin/signal.rs
+++ b/examples/stm32h7/src/bin/signal.rs
@@ -4,8 +4,8 @@
4 4
5use defmt::{info, unwrap}; 5use defmt::{info, unwrap};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_sync::signal::Signal;
7use embassy_time::{Duration, Timer}; 8use embassy_time::{Duration, Timer};
8use embassy_util::channel::signal::Signal;
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11static SIGNAL: Signal<u32> = Signal::new(); 11static SIGNAL: Signal<u32> = Signal::new();
diff --git a/examples/stm32h7/src/bin/spi.rs b/examples/stm32h7/src/bin/spi.rs
index c28f937a8..1f407f002 100644
--- a/examples/stm32h7/src/bin/spi.rs
+++ b/examples/stm32h7/src/bin/spi.rs
@@ -12,8 +12,8 @@ use embassy_stm32::dma::NoDma;
12use embassy_stm32::peripherals::SPI3; 12use embassy_stm32::peripherals::SPI3;
13use embassy_stm32::time::mhz; 13use embassy_stm32::time::mhz;
14use embassy_stm32::{spi, Config}; 14use embassy_stm32::{spi, Config};
15use embassy_util::Forever;
16use heapless::String; 15use heapless::String;
16use static_cell::StaticCell;
17use {defmt_rtt as _, panic_probe as _}; 17use {defmt_rtt as _, panic_probe as _};
18 18
19#[embassy_executor::task] 19#[embassy_executor::task]
@@ -31,7 +31,7 @@ async fn main_task(mut spi: spi::Spi<'static, SPI3, NoDma, NoDma>) {
31 } 31 }
32} 32}
33 33
34static EXECUTOR: Forever<Executor> = Forever::new(); 34static EXECUTOR: StaticCell<Executor> = StaticCell::new();
35 35
36#[entry] 36#[entry]
37fn main() -> ! { 37fn main() -> ! {
@@ -54,7 +54,7 @@ fn main() -> ! {
54 spi::Config::default(), 54 spi::Config::default(),
55 ); 55 );
56 56
57 let executor = EXECUTOR.put(Executor::new()); 57 let executor = EXECUTOR.init(Executor::new());
58 58
59 executor.run(|spawner| { 59 executor.run(|spawner| {
60 unwrap!(spawner.spawn(main_task(spi))); 60 unwrap!(spawner.spawn(main_task(spi)));
diff --git a/examples/stm32h7/src/bin/spi_dma.rs b/examples/stm32h7/src/bin/spi_dma.rs
index 6c78c194f..53004fc9b 100644
--- a/examples/stm32h7/src/bin/spi_dma.rs
+++ b/examples/stm32h7/src/bin/spi_dma.rs
@@ -11,8 +11,8 @@ use embassy_executor::Executor;
11use embassy_stm32::peripherals::{DMA1_CH3, DMA1_CH4, SPI3}; 11use embassy_stm32::peripherals::{DMA1_CH3, DMA1_CH4, SPI3};
12use embassy_stm32::time::mhz; 12use embassy_stm32::time::mhz;
13use embassy_stm32::{spi, Config}; 13use embassy_stm32::{spi, Config};
14use embassy_util::Forever;
15use heapless::String; 14use heapless::String;
15use static_cell::StaticCell;
16use {defmt_rtt as _, panic_probe as _}; 16use {defmt_rtt as _, panic_probe as _};
17 17
18#[embassy_executor::task] 18#[embassy_executor::task]
@@ -27,7 +27,7 @@ async fn main_task(mut spi: spi::Spi<'static, SPI3, DMA1_CH3, DMA1_CH4>) {
27 } 27 }
28} 28}
29 29
30static EXECUTOR: Forever<Executor> = Forever::new(); 30static EXECUTOR: StaticCell<Executor> = StaticCell::new();
31 31
32#[entry] 32#[entry]
33fn main() -> ! { 33fn main() -> ! {
@@ -50,7 +50,7 @@ fn main() -> ! {
50 spi::Config::default(), 50 spi::Config::default(),
51 ); 51 );
52 52
53 let executor = EXECUTOR.put(Executor::new()); 53 let executor = EXECUTOR.init(Executor::new());
54 54
55 executor.run(|spawner| { 55 executor.run(|spawner| {
56 unwrap!(spawner.spawn(main_task(spi))); 56 unwrap!(spawner.spawn(main_task(spi)));
diff --git a/examples/stm32h7/src/bin/usart.rs b/examples/stm32h7/src/bin/usart.rs
index 1384d54c6..87c2b1253 100644
--- a/examples/stm32h7/src/bin/usart.rs
+++ b/examples/stm32h7/src/bin/usart.rs
@@ -7,7 +7,7 @@ use defmt::*;
7use embassy_executor::Executor; 7use embassy_executor::Executor;
8use embassy_stm32::dma::NoDma; 8use embassy_stm32::dma::NoDma;
9use embassy_stm32::usart::{Config, Uart}; 9use embassy_stm32::usart::{Config, Uart};
10use embassy_util::Forever; 10use static_cell::StaticCell;
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13#[embassy_executor::task] 13#[embassy_executor::task]
@@ -27,13 +27,13 @@ async fn main_task() {
27 } 27 }
28} 28}
29 29
30static EXECUTOR: Forever<Executor> = Forever::new(); 30static EXECUTOR: StaticCell<Executor> = StaticCell::new();
31 31
32#[entry] 32#[entry]
33fn main() -> ! { 33fn main() -> ! {
34 info!("Hello World!"); 34 info!("Hello World!");
35 35
36 let executor = EXECUTOR.put(Executor::new()); 36 let executor = EXECUTOR.init(Executor::new());
37 37
38 executor.run(|spawner| { 38 executor.run(|spawner| {
39 unwrap!(spawner.spawn(main_task())); 39 unwrap!(spawner.spawn(main_task()));
diff --git a/examples/stm32h7/src/bin/usart_dma.rs b/examples/stm32h7/src/bin/usart_dma.rs
index f8d58bb84..3adffcbeb 100644
--- a/examples/stm32h7/src/bin/usart_dma.rs
+++ b/examples/stm32h7/src/bin/usart_dma.rs
@@ -9,8 +9,8 @@ use defmt::*;
9use embassy_executor::Executor; 9use embassy_executor::Executor;
10use embassy_stm32::dma::NoDma; 10use embassy_stm32::dma::NoDma;
11use embassy_stm32::usart::{Config, Uart}; 11use embassy_stm32::usart::{Config, Uart};
12use embassy_util::Forever;
13use heapless::String; 12use heapless::String;
13use static_cell::StaticCell;
14use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
15 15
16#[embassy_executor::task] 16#[embassy_executor::task]
@@ -30,13 +30,13 @@ async fn main_task() {
30 } 30 }
31} 31}
32 32
33static EXECUTOR: Forever<Executor> = Forever::new(); 33static EXECUTOR: StaticCell<Executor> = StaticCell::new();
34 34
35#[entry] 35#[entry]
36fn main() -> ! { 36fn main() -> ! {
37 info!("Hello World!"); 37 info!("Hello World!");
38 38
39 let executor = EXECUTOR.put(Executor::new()); 39 let executor = EXECUTOR.init(Executor::new());
40 40
41 executor.run(|spawner| { 41 executor.run(|spawner| {
42 unwrap!(spawner.spawn(main_task())); 42 unwrap!(spawner.spawn(main_task()));
diff --git a/examples/stm32h7/src/bin/usart_split.rs b/examples/stm32h7/src/bin/usart_split.rs
index 64080ec45..df2b600f8 100644
--- a/examples/stm32h7/src/bin/usart_split.rs
+++ b/examples/stm32h7/src/bin/usart_split.rs
@@ -7,8 +7,8 @@ use embassy_executor::Spawner;
7use embassy_stm32::dma::NoDma; 7use embassy_stm32::dma::NoDma;
8use embassy_stm32::peripherals::{DMA1_CH1, UART7}; 8use embassy_stm32::peripherals::{DMA1_CH1, UART7};
9use embassy_stm32::usart::{Config, Uart, UartRx}; 9use embassy_stm32::usart::{Config, Uart, UartRx};
10use embassy_util::blocking_mutex::raw::ThreadModeRawMutex; 10use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
11use embassy_util::channel::mpmc::Channel; 11use embassy_sync::channel::Channel;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14#[embassy_executor::task] 14#[embassy_executor::task]
diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml
index fdb716d15..11751a21d 100644
--- a/examples/stm32l0/Cargo.toml
+++ b/examples/stm32l0/Cargo.toml
@@ -8,7 +8,7 @@ default = ["nightly"]
8nightly = ["embassy-stm32/nightly", "embassy-lora", "lorawan-device", "lorawan", "embedded-io/async"] 8nightly = ["embassy-stm32/nightly", "embassy-lora", "lorawan-device", "lorawan", "embedded-io/async"]
9 9
10[dependencies] 10[dependencies]
11embassy-util = { version = "0.1.0", path = "../../embassy-util", features = ["defmt"] } 11embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
12embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } 12embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
13embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] } 13embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] }
14embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "time-driver-any", "exti", "unstable-traits", "memory-x"] } 14embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "time-driver-any", "exti", "unstable-traits", "memory-x"] }
@@ -29,3 +29,4 @@ panic-probe = { version = "0.3", features = ["print-defmt"] }
29futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 29futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
30heapless = { version = "0.7.5", default-features = false } 30heapless = { version = "0.7.5", default-features = false }
31embedded-hal = "0.2.6" 31embedded-hal = "0.2.6"
32static_cell = "1.0"
diff --git a/examples/stm32l0/src/bin/raw_spawn.rs b/examples/stm32l0/src/bin/raw_spawn.rs
index bd87e62a4..edc17304a 100644
--- a/examples/stm32l0/src/bin/raw_spawn.rs
+++ b/examples/stm32l0/src/bin/raw_spawn.rs
@@ -8,7 +8,7 @@ use defmt::*;
8use embassy_executor::raw::TaskStorage; 8use embassy_executor::raw::TaskStorage;
9use embassy_executor::Executor; 9use embassy_executor::Executor;
10use embassy_time::{Duration, Timer}; 10use embassy_time::{Duration, Timer};
11use embassy_util::Forever; 11use static_cell::StaticCell;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14async fn run1() { 14async fn run1() {
@@ -25,14 +25,14 @@ async fn run2() {
25 } 25 }
26} 26}
27 27
28static EXECUTOR: Forever<Executor> = Forever::new(); 28static EXECUTOR: StaticCell<Executor> = StaticCell::new();
29 29
30#[entry] 30#[entry]
31fn main() -> ! { 31fn main() -> ! {
32 info!("Hello World!"); 32 info!("Hello World!");
33 33
34 let _p = embassy_stm32::init(Default::default()); 34 let _p = embassy_stm32::init(Default::default());
35 let executor = EXECUTOR.put(Executor::new()); 35 let executor = EXECUTOR.init(Executor::new());
36 36
37 let run1_task = TaskStorage::new(); 37 let run1_task = TaskStorage::new();
38 let run2_task = TaskStorage::new(); 38 let run2_task = TaskStorage::new();
diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml
index 43f844b67..18b35b305 100644
--- a/examples/stm32l1/Cargo.toml
+++ b/examples/stm32l1/Cargo.toml
@@ -4,7 +4,7 @@ name = "embassy-stm32l1-examples"
4version = "0.1.0" 4version = "0.1.0"
5 5
6[dependencies] 6[dependencies]
7embassy-util = { version = "0.1.0", path = "../../embassy-util", features = ["defmt"] } 7embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } 8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] } 9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] }
10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] } 10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] }
diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml
index eaffa253e..cb7238e4c 100644
--- a/examples/stm32l4/Cargo.toml
+++ b/examples/stm32l4/Cargo.toml
@@ -6,7 +6,7 @@ version = "0.1.0"
6[features] 6[features]
7 7
8[dependencies] 8[dependencies]
9embassy-util = { version = "0.1.0", path = "../../embassy-util", features = ["defmt"] } 9embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
10embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } 10embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
11embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] } 11embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] }
12embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } 12embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" }
diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml
index 4d96d31fc..624c73c26 100644
--- a/examples/stm32l5/Cargo.toml
+++ b/examples/stm32l5/Cargo.toml
@@ -6,7 +6,7 @@ version = "0.1.0"
6[features] 6[features]
7 7
8[dependencies] 8[dependencies]
9embassy-util = { version = "0.1.0", path = "../../embassy-util", features = ["defmt"] } 9embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
10embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } 10embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
11embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] } 11embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] }
12embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "unstable-traits", "memory-x"] } 12embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "unstable-traits", "memory-x"] }
@@ -28,3 +28,4 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa
28heapless = { version = "0.7.5", default-features = false } 28heapless = { version = "0.7.5", default-features = false }
29rand_core = { version = "0.6.3", default-features = false } 29rand_core = { version = "0.6.3", default-features = false }
30embedded-io = { version = "0.3.0", features = ["async"] } 30embedded-io = { version = "0.3.0", features = ["async"] }
31static_cell = "1.0"
diff --git a/examples/stm32l5/src/bin/usb_ethernet.rs b/examples/stm32l5/src/bin/usb_ethernet.rs
index 7c53d03cc..3286f5c4d 100644
--- a/examples/stm32l5/src/bin/usb_ethernet.rs
+++ b/examples/stm32l5/src/bin/usb_ethernet.rs
@@ -15,22 +15,22 @@ use embassy_stm32::rng::Rng;
15use embassy_stm32::time::Hertz; 15use embassy_stm32::time::Hertz;
16use embassy_stm32::usb::Driver; 16use embassy_stm32::usb::Driver;
17use embassy_stm32::{interrupt, Config}; 17use embassy_stm32::{interrupt, Config};
18use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
19use embassy_sync::channel::Channel;
18use embassy_usb::{Builder, UsbDevice}; 20use embassy_usb::{Builder, UsbDevice};
19use embassy_usb_ncm::{CdcNcmClass, Receiver, Sender, State}; 21use embassy_usb_ncm::{CdcNcmClass, Receiver, Sender, State};
20use embassy_util::blocking_mutex::raw::ThreadModeRawMutex;
21use embassy_util::channel::mpmc::Channel;
22use embassy_util::Forever;
23use embedded_io::asynch::{Read, Write}; 22use embedded_io::asynch::{Read, Write};
24use rand_core::RngCore; 23use rand_core::RngCore;
24use static_cell::StaticCell;
25use {defmt_rtt as _, panic_probe as _}; 25use {defmt_rtt as _, panic_probe as _};
26 26
27type MyDriver = Driver<'static, embassy_stm32::peripherals::USB>; 27type MyDriver = Driver<'static, embassy_stm32::peripherals::USB>;
28 28
29macro_rules! forever { 29macro_rules! singleton {
30 ($val:expr) => {{ 30 ($val:expr) => {{
31 type T = impl Sized; 31 type T = impl Sized;
32 static FOREVER: Forever<T> = Forever::new(); 32 static STATIC_CELL: StaticCell<T> = StaticCell::new();
33 FOREVER.put_with(move || $val) 33 STATIC_CELL.init_with(move || $val)
34 }}; 34 }};
35} 35}
36 36
@@ -115,7 +115,7 @@ async fn main(spawner: Spawner) {
115 control_buf: [u8; 128], 115 control_buf: [u8; 128],
116 serial_state: State<'static>, 116 serial_state: State<'static>,
117 } 117 }
118 let res: &mut Resources = forever!(Resources { 118 let res: &mut Resources = singleton!(Resources {
119 device_descriptor: [0; 256], 119 device_descriptor: [0; 256],
120 config_descriptor: [0; 256], 120 config_descriptor: [0; 256],
121 bos_descriptor: [0; 256], 121 bos_descriptor: [0; 256],
@@ -171,10 +171,10 @@ async fn main(spawner: Spawner) {
171 171
172 // Init network stack 172 // Init network stack
173 let device = Device { mac_addr: our_mac_addr }; 173 let device = Device { mac_addr: our_mac_addr };
174 let stack = &*forever!(Stack::new( 174 let stack = &*singleton!(Stack::new(
175 device, 175 device,
176 config, 176 config,
177 forever!(StackResources::<1, 2, 8>::new()), 177 singleton!(StackResources::<1, 2, 8>::new()),
178 seed 178 seed
179 )); 179 ));
180 180
diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml
index 48833664a..ff0ec9f42 100644
--- a/examples/stm32u5/Cargo.toml
+++ b/examples/stm32u5/Cargo.toml
@@ -4,7 +4,7 @@ name = "embassy-stm32u5-examples"
4version = "0.1.0" 4version = "0.1.0"
5 5
6[dependencies] 6[dependencies]
7embassy-util = { version = "0.1.0", path = "../../embassy-util", features = ["defmt"] } 7embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } 8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] } 9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] }
10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32u585ai", "time-driver-any", "memory-x" ] } 10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32u585ai", "time-driver-any", "memory-x" ] }
diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml
index b46300764..3b10da0ad 100644
--- a/examples/stm32wb/Cargo.toml
+++ b/examples/stm32wb/Cargo.toml
@@ -4,7 +4,7 @@ name = "embassy-stm32wb-examples"
4version = "0.1.0" 4version = "0.1.0"
5 5
6[dependencies] 6[dependencies]
7embassy-util = { version = "0.1.0", path = "../../embassy-util", features = ["defmt"] } 7embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } 8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] } 9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] }
10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55cc", "time-driver-any", "exti"] } 10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55cc", "time-driver-any", "exti"] }
diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml
index ae33478af..5f6679f4b 100644
--- a/examples/stm32wl/Cargo.toml
+++ b/examples/stm32wl/Cargo.toml
@@ -4,7 +4,7 @@ name = "embassy-stm32wl-examples"
4version = "0.1.0" 4version = "0.1.0"
5 5
6[dependencies] 6[dependencies]
7embassy-util = { version = "0.1.0", path = "../../embassy-util", features = ["defmt"] } 7embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } 8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] } 9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-32768hz"] }
10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "subghz", "unstable-pac", "exti"] } 10embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "subghz", "unstable-pac", "exti"] }
diff --git a/examples/stm32wl/src/bin/subghz.rs b/examples/stm32wl/src/bin/subghz.rs
index d16e3f5e4..c5e9bb597 100644
--- a/examples/stm32wl/src/bin/subghz.rs
+++ b/examples/stm32wl/src/bin/subghz.rs
@@ -13,7 +13,7 @@ use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed};
13use embassy_stm32::interrupt; 13use embassy_stm32::interrupt;
14use embassy_stm32::interrupt::{Interrupt, InterruptExt}; 14use embassy_stm32::interrupt::{Interrupt, InterruptExt};
15use embassy_stm32::subghz::*; 15use embassy_stm32::subghz::*;
16use embassy_util::channel::signal::Signal; 16use embassy_sync::signal::Signal;
17use {defmt_rtt as _, panic_probe as _}; 17use {defmt_rtt as _, panic_probe as _};
18 18
19const PING_DATA: &str = "PING"; 19const PING_DATA: &str = "PING";
diff --git a/examples/wasm/Cargo.toml b/examples/wasm/Cargo.toml
index c7f980366..ea61fb921 100644
--- a/examples/wasm/Cargo.toml
+++ b/examples/wasm/Cargo.toml
@@ -7,7 +7,7 @@ version = "0.1.0"
7crate-type = ["cdylib"] 7crate-type = ["cdylib"]
8 8
9[dependencies] 9[dependencies]
10embassy-util = { version = "0.1.0", path = "../../embassy-util", features = ["log"] } 10embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["log"] }
11embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["log", "wasm", "nightly", "integrated-timers"] } 11embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["log", "wasm", "nightly", "integrated-timers"] }
12embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["log", "wasm", "nightly"] } 12embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["log", "wasm", "nightly"] }
13 13
@@ -15,4 +15,4 @@ wasm-logger = "0.2.0"
15wasm-bindgen = "0.2" 15wasm-bindgen = "0.2"
16web-sys = { version = "0.3", features = ["Document", "Element", "HtmlElement", "Node", "Window" ] } 16web-sys = { version = "0.3", features = ["Document", "Element", "HtmlElement", "Node", "Window" ] }
17log = "0.4.11" 17log = "0.4.11"
18critical-section = "1.1" 18critical-section = { version = "1.1", features = ["std"] }
diff --git a/examples/wasm/README.md b/examples/wasm/README.md
index 4bed4a797..b7fee2dc8 100644
--- a/examples/wasm/README.md
+++ b/examples/wasm/README.md
@@ -3,7 +3,7 @@
3Examples use a CLI tool named `wasm-pack` to build this example: 3Examples use a CLI tool named `wasm-pack` to build this example:
4 4
5``` 5```
6cargo install wasm-pack 6cargo install wasm-pack --version 0.9.1
7``` 7```
8 8
9## Building 9## Building
diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml
index 8740cc488..4d6877ccd 100644
--- a/tests/rp/Cargo.toml
+++ b/tests/rp/Cargo.toml
@@ -4,7 +4,7 @@ name = "embassy-rp-tests"
4version = "0.1.0" 4version = "0.1.0"
5 5
6[dependencies] 6[dependencies]
7embassy-util = { version = "0.1.0", path = "../../embassy-util", features = ["defmt"] } 7embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } 8embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt"] } 9embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt"] }
10embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["nightly", "defmt", "unstable-pac", "unstable-traits"] } 10embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["nightly", "defmt", "unstable-pac", "unstable-traits"] }
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml
index 1d12995a2..f1441d00c 100644
--- a/tests/stm32/Cargo.toml
+++ b/tests/stm32/Cargo.toml
@@ -13,7 +13,7 @@ stm32wb55rg = ["embassy-stm32/stm32wb55rg"] # Nucleo
13stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board 13stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board
14 14
15[dependencies] 15[dependencies]
16embassy-util = { version = "0.1.0", path = "../../embassy-util", features = ["defmt"] } 16embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
17embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } 17embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
18embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "tick-32768hz"] } 18embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "tick-32768hz"] }
19embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "memory-x", "time-driver-tim2"] } 19embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "memory-x", "time-driver-tim2"] }