Merge branch 'master' of https://github.com/embassy-rs/embassy into embassy-rp/dma

This commit is contained in:
Mathias 2022-08-23 13:24:52 +02:00
commit 36cf719a18
163 changed files with 923 additions and 455 deletions

View File

@ -69,4 +69,4 @@ jobs:
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Test - name: Test
run: cd embassy-util && cargo test run: cd embassy-sync && cargo test

View File

@ -18,7 +18,7 @@
"rust-analyzer.linkedProjects": [ "rust-analyzer.linkedProjects": [
// Declare for the target you wish to develop // Declare for the target you wish to develop
//"embassy-executor/Cargo.toml", //"embassy-executor/Cargo.toml",
//"embassy-util/Cargo.toml", //"embassy-sync/Cargo.toml",
"examples/nrf/Cargo.toml", "examples/nrf/Cargo.toml",
// "examples/rp/Cargo.toml", // "examples/rp/Cargo.toml",
// "examples/std/Cargo.toml", // "examples/std/Cargo.toml",

View File

@ -14,7 +14,7 @@ target = "thumbv7em-none-eabi"
[dependencies] [dependencies]
defmt = { version = "0.3", optional = true } defmt = { version = "0.3", optional = true }
log = { version = "0.4", optional = true } log = { version = "0.4", optional = true }
embassy-util = { version = "0.1.0", path = "../../embassy-util" } embassy-sync = { version = "0.1.0", path = "../../embassy-sync" }
embedded-storage = "0.3.0" embedded-storage = "0.3.0"
embedded-storage-async = "0.3.0" embedded-storage-async = "0.3.0"

View File

@ -15,7 +15,7 @@ target = "thumbv7em-none-eabi"
[dependencies] [dependencies]
defmt = { version = "0.3", optional = true } defmt = { version = "0.3", optional = true }
embassy-util = { path = "../../embassy-util" } embassy-sync = { path = "../../embassy-sync" }
embassy-nrf = { path = "../../embassy-nrf", default-features = false, features = ["nightly"] } embassy-nrf = { path = "../../embassy-nrf", default-features = false, features = ["nightly"] }
embassy-boot = { path = "../boot", default-features = false } embassy-boot = { path = "../boot", default-features = false }
cortex-m = { version = "0.7.6" } cortex-m = { version = "0.7.6" }

View File

@ -17,7 +17,7 @@ defmt = { version = "0.3", optional = true }
defmt-rtt = { version = "0.3", optional = true } defmt-rtt = { version = "0.3", optional = true }
log = { version = "0.4", optional = true } log = { version = "0.4", optional = true }
embassy-util = { path = "../../embassy-util" } embassy-sync = { path = "../../embassy-sync" }
embassy-stm32 = { path = "../../embassy-stm32", default-features = false, features = ["nightly"] } embassy-stm32 = { path = "../../embassy-stm32", default-features = false, features = ["nightly"] }
embassy-boot = { path = "../boot", default-features = false } embassy-boot = { path = "../boot", default-features = false }
cortex-m = { version = "0.7.6" } cortex-m = { version = "0.7.6" }

View File

@ -35,7 +35,7 @@ prio-bits-8 = []
defmt = { version = "0.3", optional = true } defmt = { version = "0.3", optional = true }
log = { version = "0.4.14", optional = true } log = { version = "0.4.14", optional = true }
embassy-util = { version = "0.1.0", path = "../embassy-util" } embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
embassy-executor = { version = "0.1.0", path = "../embassy-executor"} embassy-executor = { version = "0.1.0", path = "../embassy-executor"}
embassy-macros = { version = "0.1.0", path = "../embassy-macros"} embassy-macros = { version = "0.1.0", path = "../embassy-macros"}
embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common"} embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common"}

View File

@ -71,7 +71,7 @@ impl<I: Interrupt> InterruptExecutor<I> {
/// Executor instance in a place where it'll live forever and grants you mutable /// Executor instance in a place where it'll live forever and grants you mutable
/// access. There's a few ways to do this: /// access. There's a few ways to do this:
/// ///
/// - a [Forever](embassy_util::Forever) (safe) /// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe)
/// - a `static mut` (unsafe) /// - a `static mut` (unsafe)
/// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe) /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe)
pub fn start(&'static mut self) -> SendSpawner { pub fn start(&'static mut self) -> SendSpawner {

View File

@ -16,7 +16,7 @@ std = []
nightly = ["embedded-hal-async", "embedded-storage-async"] nightly = ["embedded-hal-async", "embedded-storage-async"]
[dependencies] [dependencies]
embassy-util = { version = "0.1.0", path = "../embassy-util" } embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.8" } embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.8" }
embedded-hal-async = { version = "0.1.0-alpha.1", optional = true } embedded-hal-async = { version = "0.1.0-alpha.1", optional = true }

View File

@ -4,15 +4,15 @@
//! //!
//! ```rust //! ```rust
//! use embassy_embedded_hal::shared_bus::i2c::I2cDevice; //! use embassy_embedded_hal::shared_bus::i2c::I2cDevice;
//! use embassy_util::mutex::Mutex; //! use embassy_sync::mutex::Mutex;
//! use embassy_util::blocking_mutex::raw::ThreadModeRawMutex; //! use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
//! //!
//! static I2C_BUS: Forever<Mutex::<ThreadModeRawMutex, Twim<TWISPI0>>> = Forever::new(); //! static I2C_BUS: StaticCell<Mutex::<ThreadModeRawMutex, Twim<TWISPI0>>> = StaticCell::new();
//! let config = twim::Config::default(); //! let config = twim::Config::default();
//! let irq = interrupt::take!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); //! let irq = interrupt::take!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
//! let i2c = Twim::new(p.TWISPI0, irq, p.P0_03, p.P0_04, config); //! let i2c = Twim::new(p.TWISPI0, irq, p.P0_03, p.P0_04, config);
//! let i2c_bus = Mutex::<ThreadModeRawMutex, _>::new(i2c); //! let i2c_bus = Mutex::<ThreadModeRawMutex, _>::new(i2c);
//! let i2c_bus = I2C_BUS.put(i2c_bus); //! let i2c_bus = I2C_BUS.init(i2c_bus);
//! //!
//! // Device 1, using embedded-hal-async compatible driver for QMC5883L compass //! // Device 1, using embedded-hal-async compatible driver for QMC5883L compass
//! let i2c_dev1 = I2cDevice::new(i2c_bus); //! let i2c_dev1 = I2cDevice::new(i2c_bus);
@ -24,8 +24,8 @@
//! ``` //! ```
use core::future::Future; use core::future::Future;
use embassy_util::blocking_mutex::raw::RawMutex; use embassy_sync::blocking_mutex::raw::RawMutex;
use embassy_util::mutex::Mutex; use embassy_sync::mutex::Mutex;
use embedded_hal_async::i2c; use embedded_hal_async::i2c;
use crate::shared_bus::I2cDeviceError; use crate::shared_bus::I2cDeviceError;

View File

@ -4,16 +4,16 @@
//! //!
//! ```rust //! ```rust
//! use embassy_embedded_hal::shared_bus::spi::SpiDevice; //! use embassy_embedded_hal::shared_bus::spi::SpiDevice;
//! use embassy_util::mutex::Mutex; //! use embassy_sync::mutex::Mutex;
//! use embassy_util::blocking_mutex::raw::ThreadModeRawMutex; //! use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
//! //!
//! static SPI_BUS: Forever<Mutex<ThreadModeRawMutex, spim::Spim<SPI3>>> = Forever::new(); //! static SPI_BUS: StaticCell<Mutex<ThreadModeRawMutex, spim::Spim<SPI3>>> = StaticCell::new();
//! let mut config = spim::Config::default(); //! let mut config = spim::Config::default();
//! config.frequency = spim::Frequency::M32; //! config.frequency = spim::Frequency::M32;
//! let irq = interrupt::take!(SPIM3); //! let irq = interrupt::take!(SPIM3);
//! let spi = spim::Spim::new_txonly(p.SPI3, irq, p.P0_15, p.P0_18, config); //! let spi = spim::Spim::new_txonly(p.SPI3, irq, p.P0_15, p.P0_18, config);
//! let spi_bus = Mutex::<ThreadModeRawMutex, _>::new(spi); //! let spi_bus = Mutex::<ThreadModeRawMutex, _>::new(spi);
//! let spi_bus = SPI_BUS.put(spi_bus); //! let spi_bus = SPI_BUS.init(spi_bus);
//! //!
//! // Device 1, using embedded-hal-async compatible driver for ST7735 LCD display //! // Device 1, using embedded-hal-async compatible driver for ST7735 LCD display
//! let cs_pin1 = Output::new(p.P0_24, Level::Low, OutputDrive::Standard); //! let cs_pin1 = Output::new(p.P0_24, Level::Low, OutputDrive::Standard);
@ -27,8 +27,8 @@
//! ``` //! ```
use core::future::Future; use core::future::Future;
use embassy_util::blocking_mutex::raw::RawMutex; use embassy_sync::blocking_mutex::raw::RawMutex;
use embassy_util::mutex::Mutex; use embassy_sync::mutex::Mutex;
use embedded_hal_1::digital::blocking::OutputPin; use embedded_hal_1::digital::blocking::OutputPin;
use embedded_hal_1::spi::ErrorType; use embedded_hal_1::spi::ErrorType;
use embedded_hal_async::spi; use embedded_hal_async::spi;

View File

@ -4,13 +4,13 @@
//! //!
//! ```rust //! ```rust
//! use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice; //! use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice;
//! use embassy_util::blocking_mutex::{NoopMutex, raw::NoopRawMutex}; //! use embassy_sync::blocking_mutex::{NoopMutex, raw::NoopRawMutex};
//! //!
//! static I2C_BUS: Forever<NoopMutex<RefCell<Twim<TWISPI0>>>> = Forever::new(); //! static I2C_BUS: StaticCell<NoopMutex<RefCell<Twim<TWISPI0>>>> = StaticCell::new();
//! let irq = interrupt::take!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); //! let irq = interrupt::take!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
//! let i2c = Twim::new(p.TWISPI0, irq, p.P0_03, p.P0_04, Config::default()); //! let i2c = Twim::new(p.TWISPI0, irq, p.P0_03, p.P0_04, Config::default());
//! let i2c_bus = NoopMutex::new(RefCell::new(i2c)); //! let i2c_bus = NoopMutex::new(RefCell::new(i2c));
//! let i2c_bus = I2C_BUS.put(i2c_bus); //! let i2c_bus = I2C_BUS.init(i2c_bus);
//! //!
//! let i2c_dev1 = I2cDevice::new(i2c_bus); //! let i2c_dev1 = I2cDevice::new(i2c_bus);
//! let mpu = Mpu6050::new(i2c_dev1); //! let mpu = Mpu6050::new(i2c_dev1);
@ -18,8 +18,8 @@
use core::cell::RefCell; use core::cell::RefCell;
use embassy_util::blocking_mutex::raw::RawMutex; use embassy_sync::blocking_mutex::raw::RawMutex;
use embassy_util::blocking_mutex::Mutex; use embassy_sync::blocking_mutex::Mutex;
use embedded_hal_1::i2c::blocking::{I2c, Operation}; use embedded_hal_1::i2c::blocking::{I2c, Operation};
use embedded_hal_1::i2c::ErrorType; use embedded_hal_1::i2c::ErrorType;

View File

@ -4,13 +4,13 @@
//! //!
//! ```rust //! ```rust
//! use embassy_embedded_hal::shared_bus::blocking::spi::SpiDevice; //! use embassy_embedded_hal::shared_bus::blocking::spi::SpiDevice;
//! use embassy_util::blocking_mutex::{NoopMutex, raw::NoopRawMutex}; //! use embassy_sync::blocking_mutex::{NoopMutex, raw::NoopRawMutex};
//! //!
//! static SPI_BUS: Forever<NoopMutex<RefCell<Spim<SPI3>>>> = Forever::new(); //! static SPI_BUS: StaticCell<NoopMutex<RefCell<Spim<SPI3>>>> = StaticCell::new();
//! let irq = interrupt::take!(SPIM3); //! let irq = interrupt::take!(SPIM3);
//! let spi = Spim::new_txonly(p.SPI3, irq, p.P0_15, p.P0_18, Config::default()); //! let spi = Spim::new_txonly(p.SPI3, irq, p.P0_15, p.P0_18, Config::default());
//! let spi_bus = NoopMutex::new(RefCell::new(spi)); //! let spi_bus = NoopMutex::new(RefCell::new(spi));
//! let spi_bus = SPI_BUS.put(spi_bus); //! let spi_bus = SPI_BUS.init(spi_bus);
//! //!
//! // Device 1, using embedded-hal compatible driver for ST7735 LCD display //! // Device 1, using embedded-hal compatible driver for ST7735 LCD display
//! let cs_pin1 = Output::new(p.P0_24, Level::Low, OutputDrive::Standard); //! let cs_pin1 = Output::new(p.P0_24, Level::Low, OutputDrive::Standard);
@ -20,8 +20,8 @@
use core::cell::RefCell; use core::cell::RefCell;
use embassy_util::blocking_mutex::raw::RawMutex; use embassy_sync::blocking_mutex::raw::RawMutex;
use embassy_util::blocking_mutex::Mutex; use embassy_sync::blocking_mutex::Mutex;
use embedded_hal_1::digital::blocking::OutputPin; use embedded_hal_1::digital::blocking::OutputPin;
use embedded_hal_1::spi; use embedded_hal_1::spi;
use embedded_hal_1::spi::blocking::SpiBusFlush; use embedded_hal_1::spi::blocking::SpiBusFlush;

View File

@ -30,9 +30,13 @@ nightly = []
integrated-timers = ["dep:embassy-time"] integrated-timers = ["dep:embassy-time"]
# Trace interrupt invocations with rtos-trace.
rtos-trace-interrupt = ["rtos-trace"]
[dependencies] [dependencies]
defmt = { version = "0.3", optional = true } defmt = { version = "0.3", optional = true }
log = { version = "0.4.14", optional = true } log = { version = "0.4.14", optional = true }
rtos-trace = { version = "0.1.2", optional = true }
futures-util = { version = "0.3.17", default-features = false } futures-util = { version = "0.3.17", default-features = false }
embassy-macros = { version = "0.1.0", path = "../embassy-macros"} embassy-macros = { version = "0.1.0", path = "../embassy-macros"}
@ -40,6 +44,7 @@ embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true}
atomic-polyfill = "1.0.1" atomic-polyfill = "1.0.1"
critical-section = "1.1" critical-section = "1.1"
cfg-if = "1.0.0" cfg-if = "1.0.0"
static_cell = "1.0"
# WASM dependencies # WASM dependencies
wasm-bindgen = { version = "0.2.76", features = ["nightly"], optional = true } wasm-bindgen = { version = "0.2.76", features = ["nightly"], optional = true }

View File

@ -41,7 +41,7 @@ impl Executor {
/// Executor instance in a place where it'll live forever and grants you mutable /// Executor instance in a place where it'll live forever and grants you mutable
/// access. There's a few ways to do this: /// access. There's a few ways to do this:
/// ///
/// - a [Forever](crate::util::Forever) (safe) /// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe)
/// - a `static mut` (unsafe) /// - a `static mut` (unsafe)
/// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe) /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe)
/// ///

View File

@ -43,7 +43,7 @@ impl Executor {
/// Executor instance in a place where it'll live forever and grants you mutable /// Executor instance in a place where it'll live forever and grants you mutable
/// access. There's a few ways to do this: /// access. There's a few ways to do this:
/// ///
/// - a [Forever](crate::util::Forever) (safe) /// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe)
/// - a `static mut` (unsafe) /// - a `static mut` (unsafe)
/// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe) /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe)
/// ///

View File

@ -40,7 +40,7 @@ impl Executor {
/// Executor instance in a place where it'll live forever and grants you mutable /// Executor instance in a place where it'll live forever and grants you mutable
/// access. There's a few ways to do this: /// access. There's a few ways to do this:
/// ///
/// - a [Forever](crate::util::Forever) (safe) /// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe)
/// - a `static mut` (unsafe) /// - a `static mut` (unsafe)
/// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe) /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe)
/// ///

View File

@ -59,7 +59,7 @@ impl Executor {
/// Executor instance in a place where it'll live forever and grants you mutable /// Executor instance in a place where it'll live forever and grants you mutable
/// access. There's a few ways to do this: /// access. There's a few ways to do this:
/// ///
/// - a [Forever](crate::util::Forever) (safe) /// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe)
/// - a `static mut` (unsafe) /// - a `static mut` (unsafe)
/// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe) /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe)
pub fn start(&'static mut self, init: impl FnOnce(Spawner)) { pub fn start(&'static mut self, init: impl FnOnce(Spawner)) {

View File

@ -43,7 +43,7 @@ impl Executor {
/// Executor instance in a place where it'll live forever and grants you mutable /// Executor instance in a place where it'll live forever and grants you mutable
/// access. There's a few ways to do this: /// access. There's a few ways to do this:
/// ///
/// - a [Forever](crate::util::Forever) (safe) /// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe)
/// - a `static mut` (unsafe) /// - a `static mut` (unsafe)
/// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe) /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe)
/// ///

View File

@ -38,7 +38,38 @@ cfg_if::cfg_if! {
} }
} }
#[doc(hidden)]
/// Implementation details for embassy macros. DO NOT USE.
pub mod export {
#[cfg(feature = "rtos-trace")]
pub use rtos_trace::trace;
/// Expands the given block of code when `embassy-executor` is compiled with
/// the `rtos-trace-interrupt` feature.
#[doc(hidden)]
#[macro_export]
#[cfg(feature = "rtos-trace-interrupt")]
macro_rules! rtos_trace_interrupt {
($($tt:tt)*) => { $($tt)* };
}
/// Does not expand the given block of code when `embassy-executor` is
/// compiled without the `rtos-trace-interrupt` feature.
#[doc(hidden)]
#[macro_export]
#[cfg(not(feature = "rtos-trace-interrupt"))]
macro_rules! rtos_trace_interrupt {
($($tt:tt)*) => {};
}
}
pub mod raw; pub mod raw;
mod spawner; mod spawner;
pub use spawner::*; pub use spawner::*;
/// Do not use. Used for macros and HALs only. Not covered by semver guarantees.
#[doc(hidden)]
pub mod _export {
pub use static_cell::StaticCell;
}

View File

@ -5,7 +5,7 @@
//! ## WARNING: here be dragons! //! ## WARNING: here be dragons!
//! //!
//! Using this module requires respecting subtle safety contracts. If you can, prefer using the safe //! Using this module requires respecting subtle safety contracts. If you can, prefer using the safe
//! executor wrappers in [`executor`](crate::executor) and the [`embassy_executor::task`](embassy_macros::task) macro, which are fully safe. //! [executor wrappers](crate::Executor) and the [`embassy_executor::task`](embassy_macros::task) macro, which are fully safe.
mod run_queue; mod run_queue;
#[cfg(feature = "integrated-timers")] #[cfg(feature = "integrated-timers")]
@ -26,6 +26,8 @@ use critical_section::CriticalSection;
use embassy_time::driver::{self, AlarmHandle}; use embassy_time::driver::{self, AlarmHandle};
#[cfg(feature = "integrated-timers")] #[cfg(feature = "integrated-timers")]
use embassy_time::Instant; use embassy_time::Instant;
#[cfg(feature = "rtos-trace")]
use rtos_trace::trace;
use self::run_queue::{RunQueue, RunQueueItem}; use self::run_queue::{RunQueue, RunQueueItem};
use self::util::UninitCell; use self::util::UninitCell;
@ -247,7 +249,7 @@ impl<F: Future + 'static, const N: usize> TaskPool<F, N> {
/// ///
/// This is the core of the Embassy executor. It is low-level, requiring manual /// This is the core of the Embassy executor. It is low-level, requiring manual
/// handling of wakeups and task polling. If you can, prefer using one of the /// handling of wakeups and task polling. If you can, prefer using one of the
/// higher level executors in [`crate::executor`]. /// [higher level executors](crate::Executor).
/// ///
/// The raw executor leaves it up to you to handle wakeups and scheduling: /// The raw executor leaves it up to you to handle wakeups and scheduling:
/// ///
@ -306,6 +308,9 @@ impl Executor {
/// - `task` must NOT be already enqueued (in this executor or another one). /// - `task` must NOT be already enqueued (in this executor or another one).
#[inline(always)] #[inline(always)]
unsafe fn enqueue(&self, cs: CriticalSection, task: NonNull<TaskHeader>) { unsafe fn enqueue(&self, cs: CriticalSection, task: NonNull<TaskHeader>) {
#[cfg(feature = "rtos-trace")]
trace::task_ready_begin(task.as_ptr() as u32);
if self.run_queue.enqueue(cs, task) { if self.run_queue.enqueue(cs, task) {
(self.signal_fn)(self.signal_ctx) (self.signal_fn)(self.signal_ctx)
} }
@ -323,6 +328,9 @@ impl Executor {
pub(super) unsafe fn spawn(&'static self, task: NonNull<TaskHeader>) { pub(super) unsafe fn spawn(&'static self, task: NonNull<TaskHeader>) {
task.as_ref().executor.set(self); task.as_ref().executor.set(self);
#[cfg(feature = "rtos-trace")]
trace::task_new(task.as_ptr() as u32);
critical_section::with(|cs| { critical_section::with(|cs| {
self.enqueue(cs, task); self.enqueue(cs, task);
}) })
@ -365,9 +373,15 @@ impl Executor {
return; return;
} }
#[cfg(feature = "rtos-trace")]
trace::task_exec_begin(p.as_ptr() as u32);
// Run the task // Run the task
task.poll_fn.read()(p as _); task.poll_fn.read()(p as _);
#[cfg(feature = "rtos-trace")]
trace::task_exec_end();
// Enqueue or update into timer_queue // Enqueue or update into timer_queue
#[cfg(feature = "integrated-timers")] #[cfg(feature = "integrated-timers")]
self.timer_queue.update(p); self.timer_queue.update(p);
@ -381,6 +395,9 @@ impl Executor {
let next_expiration = self.timer_queue.next_expiration(); let next_expiration = self.timer_queue.next_expiration();
driver::set_alarm(self.alarm, next_expiration.as_ticks()); driver::set_alarm(self.alarm, next_expiration.as_ticks());
} }
#[cfg(feature = "rtos-trace")]
trace::system_idle();
} }
/// Get a spawner that spawns tasks in this executor. /// 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) {
let expires_at = task.expires_at.get(); let expires_at = task.expires_at.get();
task.expires_at.set(expires_at.min(at)); task.expires_at.set(expires_at.min(at));
} }
#[cfg(feature = "rtos-trace")]
impl rtos_trace::RtosTraceOSCallbacks for Executor {
fn task_list() {
// We don't know what tasks exist, so we can't send them.
}
#[cfg(feature = "integrated-timers")]
fn time() -> u64 {
Instant::now().as_micros()
}
#[cfg(not(feature = "integrated-timers"))]
fn time() -> u64 {
0
}
}
#[cfg(feature = "rtos-trace")]
rtos_trace::global_os_callbacks! {Executor}

View File

@ -0,0 +1,14 @@
[package]
name = "embassy-futures"
version = "0.1.0"
edition = "2021"
[package.metadata.embassy_docs]
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-futures-v$VERSION/embassy-futures/src/"
src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-futures/src/"
features = ["nightly"]
target = "thumbv7em-none-eabi"
[dependencies]
defmt = { version = "0.3", optional = true }
log = { version = "0.4.14", optional = true }

View File

@ -0,0 +1,12 @@
#![no_std]
#![doc = include_str!("../../README.md")]
#![warn(missing_docs)]
// This mod MUST go first, so that the others see its macros.
pub(crate) mod fmt;
mod select;
mod yield_now;
pub use select::*;
pub use yield_now::*;

View File

@ -25,7 +25,7 @@ defmt = { version = "0.3", optional = true }
log = { version = "0.4.14", optional = true } log = { version = "0.4.14", optional = true }
embassy-time = { version = "0.1.0", path = "../embassy-time" } embassy-time = { version = "0.1.0", path = "../embassy-time" }
embassy-util = { version = "0.1.0", path = "../embassy-util" } embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", default-features = false, optional = true } embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", default-features = false, optional = true }
embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.8" } embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.8" }
embedded-hal-async = { version = "0.1.0-alpha.1" } embedded-hal-async = { version = "0.1.0-alpha.1" }

View File

@ -12,7 +12,7 @@ use embassy_stm32::subghz::{
Status, SubGhz, TcxoMode, TcxoTrim, Timeout, TxParams, Status, SubGhz, TcxoMode, TcxoTrim, Timeout, TxParams,
}; };
use embassy_stm32::Peripheral; use embassy_stm32::Peripheral;
use embassy_util::channel::signal::Signal; use embassy_sync::signal::Signal;
use lorawan_device::async_device::radio::{Bandwidth, PhyRxTx, RfConfig, RxQuality, SpreadingFactor, TxConfig}; use lorawan_device::async_device::radio::{Bandwidth, PhyRxTx, RfConfig, RxQuality, SpreadingFactor, TxConfig};
use lorawan_device::async_device::Timings; use lorawan_device::async_device::Timings;

View File

@ -19,7 +19,13 @@ pub fn run(name: syn::Ident) -> Result<TokenStream, TokenStream> {
let func = HANDLER.func.load(interrupt::_export::atomic::Ordering::Relaxed); let func = HANDLER.func.load(interrupt::_export::atomic::Ordering::Relaxed);
let ctx = HANDLER.ctx.load(interrupt::_export::atomic::Ordering::Relaxed); let ctx = HANDLER.ctx.load(interrupt::_export::atomic::Ordering::Relaxed);
let func: fn(*mut ()) = ::core::mem::transmute(func); let func: fn(*mut ()) = ::core::mem::transmute(func);
func(ctx) ::embassy_executor::rtos_trace_interrupt! {
::embassy_executor::export::trace::isr_enter();
}
func(ctx);
::embassy_executor::rtos_trace_interrupt! {
::embassy_executor::export::trace::isr_exit();
}
} }
static TAKEN: interrupt::_export::atomic::AtomicBool = interrupt::_export::atomic::AtomicBool::new(false); static TAKEN: interrupt::_export::atomic::AtomicBool = interrupt::_export::atomic::AtomicBool::new(false);

View File

@ -34,8 +34,8 @@ pub fn run(args: syn::AttributeArgs, f: syn::ItemFn) -> Result<TokenStream, Toke
let main = quote! { let main = quote! {
#[wasm_bindgen::prelude::wasm_bindgen(start)] #[wasm_bindgen::prelude::wasm_bindgen(start)]
pub fn main() -> Result<(), wasm_bindgen::JsValue> { pub fn main() -> Result<(), wasm_bindgen::JsValue> {
static EXECUTOR: ::embassy_util::Forever<::embassy_executor::Executor> = ::embassy_util::Forever::new(); static EXECUTOR: ::embassy_executor::_export::StaticCell<::embassy_executor::Executor> = ::embassy_executor::_export::StaticCell::new();
let executor = EXECUTOR.put(::embassy_executor::Executor::new()); let executor = EXECUTOR.init(::embassy_executor::Executor::new());
executor.start(|spawner| { executor.start(|spawner| {
spawner.spawn(__embassy_main(spawner)).unwrap(); spawner.spawn(__embassy_main(spawner)).unwrap();

View File

@ -38,7 +38,7 @@ defmt = { version = "0.3", optional = true }
log = { version = "0.4.14", optional = true } log = { version = "0.4.14", optional = true }
embassy-time = { version = "0.1.0", path = "../embassy-time" } embassy-time = { version = "0.1.0", path = "../embassy-time" }
embassy-util = { version = "0.1.0", path = "../embassy-util" } embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
embedded-io = { version = "0.3.0", features = [ "async" ] } embedded-io = { version = "0.3.0", features = [ "async" ] }
managed = { version = "0.8.0", default-features = false, features = [ "map" ] } managed = { version = "0.8.0", default-features = false, features = [ "map" ] }

View File

@ -2,8 +2,8 @@ use core::cell::UnsafeCell;
use core::future::Future; use core::future::Future;
use core::task::{Context, Poll}; use core::task::{Context, Poll};
use embassy_sync::waitqueue::WakerRegistration;
use embassy_time::{Instant, Timer}; use embassy_time::{Instant, Timer};
use embassy_util::waitqueue::WakerRegistration;
use futures::future::poll_fn; use futures::future::poll_fn;
use futures::pin_mut; use futures::pin_mut;
use heapless::Vec; use heapless::Vec;

View File

@ -18,7 +18,7 @@ flavors = [
time = ["dep:embassy-time"] time = ["dep:embassy-time"]
defmt = ["dep:defmt", "embassy-executor/defmt", "embassy-util/defmt", "embassy-usb?/defmt", "embedded-io?/defmt", "embassy-embedded-hal/defmt"] defmt = ["dep:defmt", "embassy-executor/defmt", "embassy-sync/defmt", "embassy-usb?/defmt", "embedded-io?/defmt", "embassy-embedded-hal/defmt"]
# Enable nightly-only features # Enable nightly-only features
nightly = ["embedded-hal-1", "embedded-hal-async", "embassy-usb", "embedded-storage-async", "dep:embedded-io", "embassy-embedded-hal/nightly"] nightly = ["embedded-hal-1", "embedded-hal-async", "embassy-usb", "embedded-storage-async", "dep:embedded-io", "embassy-embedded-hal/nightly"]
@ -66,7 +66,7 @@ _gpio-p1 = []
[dependencies] [dependencies]
embassy-executor = { version = "0.1.0", path = "../embassy-executor", optional = true } embassy-executor = { version = "0.1.0", path = "../embassy-executor", optional = true }
embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true } embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true }
embassy-util = { version = "0.1.0", path = "../embassy-util" } embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-3"]} embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-3"]}
embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" } embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" }
embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" }

View File

@ -21,7 +21,7 @@ use core::task::Poll;
use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage}; use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage};
use embassy_hal_common::ring_buffer::RingBuffer; use embassy_hal_common::ring_buffer::RingBuffer;
use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_util::waitqueue::WakerRegistration; use embassy_sync::waitqueue::WakerRegistration;
use futures::future::poll_fn; use futures::future::poll_fn;
// Re-export SVD variants to allow user to directly set values // Re-export SVD variants to allow user to directly set values
pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
@ -45,8 +45,10 @@ enum TxState {
Transmitting(usize), Transmitting(usize),
} }
/// A type for storing the state of the UARTE peripheral that can be stored in a static.
pub struct State<'d, U: UarteInstance, T: TimerInstance>(StateStorage<StateInner<'d, U, T>>); pub struct State<'d, U: UarteInstance, T: TimerInstance>(StateStorage<StateInner<'d, U, T>>);
impl<'d, U: UarteInstance, T: TimerInstance> State<'d, U, T> { impl<'d, U: UarteInstance, T: TimerInstance> State<'d, U, T> {
/// Create an instance for storing UARTE peripheral state.
pub fn new() -> Self { pub fn new() -> Self {
Self(StateStorage::new()) Self(StateStorage::new())
} }
@ -75,6 +77,12 @@ pub struct BufferedUarte<'d, U: UarteInstance, T: TimerInstance> {
impl<'d, U: UarteInstance, T: TimerInstance> Unpin for BufferedUarte<'d, U, T> {} impl<'d, U: UarteInstance, T: TimerInstance> Unpin for BufferedUarte<'d, U, T> {}
impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> { impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
/// Create a new instance of a BufferedUarte.
///
/// See the [module documentation](crate::buffered_uarte) for more details about the intended use.
///
/// 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
/// can return early if there is no data to receive.
pub fn new( pub fn new(
state: &'d mut State<'d, U, T>, state: &'d mut State<'d, U, T>,
peri: impl Peripheral<P = U> + 'd, peri: impl Peripheral<P = U> + 'd,
@ -178,6 +186,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
} }
} }
/// Adjust the baud rate to the provided value.
pub fn set_baudrate(&mut self, baudrate: Baudrate) { pub fn set_baudrate(&mut self, baudrate: Baudrate) {
self.inner.with(|state| { self.inner.with(|state| {
let r = U::regs(); let r = U::regs();

View File

@ -1,3 +1,4 @@
//! General purpose input/output for nRF.
#![macro_use] #![macro_use]
use core::convert::Infallible; use core::convert::Infallible;
@ -26,8 +27,11 @@ pub enum Port {
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Pull { pub enum Pull {
/// No pull.
None, None,
/// Internal pull-up resistor.
Up, Up,
/// Internal pull-down resistor.
Down, Down,
} }
@ -37,6 +41,7 @@ pub struct Input<'d, T: Pin> {
} }
impl<'d, T: Pin> Input<'d, T> { impl<'d, T: Pin> Input<'d, T> {
/// Create GPIO input driver for a [Pin] with the provided [Pull] configuration.
#[inline] #[inline]
pub fn new(pin: impl Peripheral<P = T> + 'd, pull: Pull) -> Self { pub fn new(pin: impl Peripheral<P = T> + 'd, pull: Pull) -> Self {
let mut pin = Flex::new(pin); let mut pin = Flex::new(pin);
@ -45,11 +50,13 @@ impl<'d, T: Pin> Input<'d, T> {
Self { pin } Self { pin }
} }
/// Test if current pin level is high.
#[inline] #[inline]
pub fn is_high(&self) -> bool { pub fn is_high(&self) -> bool {
self.pin.is_high() self.pin.is_high()
} }
/// Test if current pin level is low.
#[inline] #[inline]
pub fn is_low(&self) -> bool { pub fn is_low(&self) -> bool {
self.pin.is_low() self.pin.is_low()
@ -66,7 +73,9 @@ impl<'d, T: Pin> Input<'d, T> {
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Level { pub enum Level {
/// Logical low.
Low, Low,
/// Logical high.
High, High,
} }
@ -88,6 +97,7 @@ impl Into<bool> for Level {
} }
} }
/// Drive strength settings for an output pin.
// These numbers match DRIVE_A exactly so hopefully the compiler will unify them. // These numbers match DRIVE_A exactly so hopefully the compiler will unify them.
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
@ -117,6 +127,7 @@ pub struct Output<'d, T: Pin> {
} }
impl<'d, T: Pin> Output<'d, T> { impl<'d, T: Pin> Output<'d, T> {
/// Create GPIO output driver for a [Pin] with the provided [Level] and [OutputDriver] configuration.
#[inline] #[inline]
pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level, drive: OutputDrive) -> Self { pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level, drive: OutputDrive) -> Self {
let mut pin = Flex::new(pin); let mut pin = Flex::new(pin);
@ -264,11 +275,13 @@ impl<'d, T: Pin> Flex<'d, T> {
self.pin.conf().reset(); self.pin.conf().reset();
} }
/// Test if current pin level is high.
#[inline] #[inline]
pub fn is_high(&self) -> bool { pub fn is_high(&self) -> bool {
!self.is_low() !self.is_low()
} }
/// Test if current pin level is low.
#[inline] #[inline]
pub fn is_low(&self) -> bool { pub fn is_low(&self) -> bool {
self.pin.block().in_.read().bits() & (1 << self.pin.pin()) == 0 self.pin.block().in_.read().bits() & (1 << self.pin.pin()) == 0
@ -374,6 +387,7 @@ pub(crate) mod sealed {
} }
} }
/// Interface for a Pin that can be configured by an [Input] or [Output] driver, or converted to an [AnyPin].
pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'static { pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'static {
/// Number of the pin within the port (0..31) /// Number of the pin within the port (0..31)
#[inline] #[inline]
@ -392,6 +406,7 @@ pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'stat
} }
} }
/// Peripheral port register value
#[inline] #[inline]
fn psel_bits(&self) -> u32 { fn psel_bits(&self) -> u32 {
self.pin_port() as u32 self.pin_port() as u32
@ -406,12 +421,16 @@ pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'stat
} }
} }
// Type-erased GPIO pin /// Type-erased GPIO pin
pub struct AnyPin { pub struct AnyPin {
pin_port: u8, pin_port: u8,
} }
impl AnyPin { impl AnyPin {
/// Create an [AnyPin] for a specific pin.
///
/// # Safety
/// - `pin_port` should not in use by another driver.
#[inline] #[inline]
pub unsafe fn steal(pin_port: u8) -> Self { pub unsafe fn steal(pin_port: u8) -> Self {
Self { pin_port } Self { pin_port }

View File

@ -3,7 +3,7 @@ use core::future::Future;
use core::task::{Context, Poll}; use core::task::{Context, Poll};
use embassy_hal_common::{impl_peripheral, Peripheral, PeripheralRef}; use embassy_hal_common::{impl_peripheral, Peripheral, PeripheralRef};
use embassy_util::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use futures::future::poll_fn; use futures::future::poll_fn;
use crate::gpio::sealed::Pin as _; use crate::gpio::sealed::Pin as _;

View File

@ -1,4 +1,4 @@
//! Nvmcerature sensor interface. //! Non-Volatile Memory Controller (NVMC) module.
use core::{ptr, slice}; use core::{ptr, slice};
@ -10,13 +10,19 @@ use embedded_storage::nor_flash::{
use crate::peripherals::NVMC; use crate::peripherals::NVMC;
use crate::{pac, Peripheral}; use crate::{pac, Peripheral};
/// Erase size of NVMC flash in bytes.
pub const PAGE_SIZE: usize = 4096; pub const PAGE_SIZE: usize = 4096;
/// Size of NVMC flash in bytes.
pub const FLASH_SIZE: usize = crate::chip::FLASH_SIZE; pub const FLASH_SIZE: usize = crate::chip::FLASH_SIZE;
/// Error type for NVMC operations.
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error { pub enum Error {
/// Opration using a location not in flash.
OutOfBounds, OutOfBounds,
/// Unaligned operation or using unaligned buffers.
Unaligned, Unaligned,
} }
@ -29,11 +35,13 @@ impl NorFlashError for Error {
} }
} }
/// Non-Volatile Memory Controller (NVMC) that implements the `embedded-storage` traits.
pub struct Nvmc<'d> { pub struct Nvmc<'d> {
_p: PeripheralRef<'d, NVMC>, _p: PeripheralRef<'d, NVMC>,
} }
impl<'d> Nvmc<'d> { impl<'d> Nvmc<'d> {
/// Create Nvmc driver.
pub fn new(_p: impl Peripheral<P = NVMC> + 'd) -> Self { pub fn new(_p: impl Peripheral<P = NVMC> + 'd) -> Self {
into_ref!(_p); into_ref!(_p);
Self { _p } Self { _p }

View File

@ -26,6 +26,7 @@ mod dppi;
#[cfg(feature = "_ppi")] #[cfg(feature = "_ppi")]
mod ppi; mod ppi;
/// An instance of the Programmable peripheral interconnect on nRF devices.
pub struct Ppi<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> { pub struct Ppi<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> {
ch: PeripheralRef<'d, C>, ch: PeripheralRef<'d, C>,
#[cfg(feature = "_dppi")] #[cfg(feature = "_dppi")]
@ -48,6 +49,7 @@ impl Task {
Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) }) Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) })
} }
/// Address off subscription register for this task.
pub fn subscribe_reg(&self) -> *mut u32 { pub fn subscribe_reg(&self) -> *mut u32 {
unsafe { self.0.as_ptr().add(REGISTER_DPPI_CONFIG_OFFSET) } unsafe { self.0.as_ptr().add(REGISTER_DPPI_CONFIG_OFFSET) }
} }
@ -69,6 +71,7 @@ impl Event {
Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) }) Self(unsafe { NonNull::new_unchecked(reg as *const _ as *mut _) })
} }
/// Address of publish register for this event.
pub fn publish_reg(&self) -> *mut u32 { pub fn publish_reg(&self) -> *mut u32 {
unsafe { self.0.as_ptr().add(REGISTER_DPPI_CONFIG_OFFSET) } unsafe { self.0.as_ptr().add(REGISTER_DPPI_CONFIG_OFFSET) }
} }
@ -87,21 +90,29 @@ pub(crate) mod sealed {
pub trait Group {} pub trait Group {}
} }
/// Interface for PPI channels.
pub trait Channel: sealed::Channel + Peripheral<P = Self> + Sized { pub trait Channel: sealed::Channel + Peripheral<P = Self> + Sized {
/// Returns the number of the channel /// Returns the number of the channel
fn number(&self) -> usize; fn number(&self) -> usize;
} }
/// Interface for PPI channels that can be configured.
pub trait ConfigurableChannel: Channel + Into<AnyConfigurableChannel> { pub trait ConfigurableChannel: Channel + Into<AnyConfigurableChannel> {
/// Convert into a type erased configurable channel.
fn degrade(self) -> AnyConfigurableChannel; fn degrade(self) -> AnyConfigurableChannel;
} }
/// Interface for PPI channels that cannot be configured.
pub trait StaticChannel: Channel + Into<AnyStaticChannel> { pub trait StaticChannel: Channel + Into<AnyStaticChannel> {
/// Convert into a type erased static channel.
fn degrade(self) -> AnyStaticChannel; fn degrade(self) -> AnyStaticChannel;
} }
/// Interface for a group of PPI channels.
pub trait Group: sealed::Group + Sized { pub trait Group: sealed::Group + Sized {
/// Returns the number of the group.
fn number(&self) -> usize; fn number(&self) -> usize;
/// Convert into a type erased group.
fn degrade(self) -> AnyGroup { fn degrade(self) -> AnyGroup {
AnyGroup { AnyGroup {
number: self.number() as u8, number: self.number() as u8,
@ -196,6 +207,7 @@ macro_rules! impl_ppi_channel {
// ====================== // ======================
// groups // groups
/// A type erased PPI group.
pub struct AnyGroup { pub struct AnyGroup {
number: u8, number: u8,
} }

View File

@ -20,6 +20,7 @@ fn regs() -> &'static pac::ppi::RegisterBlock {
#[cfg(not(feature = "nrf51"))] // Not for nrf51 because of the fork task #[cfg(not(feature = "nrf51"))] // Not for nrf51 because of the fork task
impl<'d, C: StaticChannel> Ppi<'d, C, 0, 1> { impl<'d, C: StaticChannel> Ppi<'d, C, 0, 1> {
/// Configure PPI channel to trigger `task`.
pub fn new_zero_to_one(ch: impl Peripheral<P = C> + 'd, task: Task) -> Self { pub fn new_zero_to_one(ch: impl Peripheral<P = C> + 'd, task: Task) -> Self {
into_ref!(ch); into_ref!(ch);
@ -32,6 +33,7 @@ impl<'d, C: StaticChannel> Ppi<'d, C, 0, 1> {
} }
impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> { impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> {
/// Configure PPI channel to trigger `task` on `event`.
pub fn new_one_to_one(ch: impl Peripheral<P = C> + 'd, event: Event, task: Task) -> Self { pub fn new_one_to_one(ch: impl Peripheral<P = C> + 'd, event: Event, task: Task) -> Self {
into_ref!(ch); into_ref!(ch);
@ -46,6 +48,7 @@ impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> {
#[cfg(not(feature = "nrf51"))] // Not for nrf51 because of the fork task #[cfg(not(feature = "nrf51"))] // Not for nrf51 because of the fork task
impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 2> { impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 2> {
/// Configure PPI channel to trigger `task1` and `task2` on `event`.
pub fn new_one_to_two(ch: impl Peripheral<P = C> + 'd, event: Event, task1: Task, task2: Task) -> Self { pub fn new_one_to_two(ch: impl Peripheral<P = C> + 'd, event: Event, task1: Task, task2: Task) -> Self {
into_ref!(ch); into_ref!(ch);

View File

@ -3,7 +3,7 @@
use core::task::Poll; use core::task::Poll;
use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_util::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use futures::future::poll_fn; use futures::future::poll_fn;
use crate::gpio::sealed::Pin as _; use crate::gpio::sealed::Pin as _;

View File

@ -526,7 +526,7 @@ cfg_if::cfg_if! {
} }
pub(crate) mod sealed { pub(crate) mod sealed {
use embassy_util::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use super::*; use super::*;

View File

@ -4,7 +4,7 @@ use core::task::Poll;
use embassy_hal_common::drop::OnDrop; use embassy_hal_common::drop::OnDrop;
use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_util::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use futures::future::poll_fn; use futures::future::poll_fn;
use crate::interrupt::InterruptExt; use crate::interrupt::InterruptExt;

View File

@ -4,7 +4,7 @@ use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll; use core::task::Poll;
use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef};
use embassy_util::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use futures::future::poll_fn; use futures::future::poll_fn;
use pac::{saadc, SAADC}; use pac::{saadc, SAADC};
use saadc::ch::config::{GAIN_A, REFSEL_A, RESP_A, TACQ_A}; use saadc::ch::config::{GAIN_A, REFSEL_A, RESP_A, TACQ_A};

View File

@ -363,7 +363,7 @@ impl<'d, T: Instance> Drop for Spim<'d, T> {
} }
pub(crate) mod sealed { pub(crate) mod sealed {
use embassy_util::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use super::*; use super::*;

View File

@ -4,7 +4,7 @@ use core::task::Poll;
use embassy_hal_common::drop::OnDrop; use embassy_hal_common::drop::OnDrop;
use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_util::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use fixed::types::I30F2; use fixed::types::I30F2;
use futures::future::poll_fn; use futures::future::poll_fn;

View File

@ -3,9 +3,9 @@ use core::sync::atomic::{compiler_fence, AtomicU32, AtomicU8, Ordering};
use core::{mem, ptr}; use core::{mem, ptr};
use critical_section::CriticalSection; use critical_section::CriticalSection;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::blocking_mutex::CriticalSectionMutex as Mutex;
use embassy_time::driver::{AlarmHandle, Driver}; use embassy_time::driver::{AlarmHandle, Driver};
use embassy_util::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_util::blocking_mutex::CriticalSectionMutex as Mutex;
use crate::interrupt::{Interrupt, InterruptExt}; use crate::interrupt::{Interrupt, InterruptExt};
use crate::{interrupt, pac}; use crate::{interrupt, pac};

View File

@ -5,7 +5,7 @@ use core::task::Poll;
use embassy_hal_common::drop::OnDrop; use embassy_hal_common::drop::OnDrop;
use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_util::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use futures::future::poll_fn; use futures::future::poll_fn;
use crate::interrupt::{Interrupt, InterruptExt}; use crate::interrupt::{Interrupt, InterruptExt};
@ -40,8 +40,8 @@ macro_rules! impl_timer {
fn regs() -> &'static pac::timer0::RegisterBlock { fn regs() -> &'static pac::timer0::RegisterBlock {
unsafe { &*(pac::$pac_type::ptr() as *const pac::timer0::RegisterBlock) } unsafe { &*(pac::$pac_type::ptr() as *const pac::timer0::RegisterBlock) }
} }
fn waker(n: usize) -> &'static ::embassy_util::waitqueue::AtomicWaker { fn waker(n: usize) -> &'static ::embassy_sync::waitqueue::AtomicWaker {
use ::embassy_util::waitqueue::AtomicWaker; use ::embassy_sync::waitqueue::AtomicWaker;
const NEW_AW: AtomicWaker = AtomicWaker::new(); const NEW_AW: AtomicWaker = AtomicWaker::new();
static WAKERS: [AtomicWaker; $ccs] = [NEW_AW; $ccs]; static WAKERS: [AtomicWaker; $ccs] = [NEW_AW; $ccs];
&WAKERS[n] &WAKERS[n]

View File

@ -13,9 +13,9 @@ use core::task::Poll;
use embassy_embedded_hal::SetConfig; use embassy_embedded_hal::SetConfig;
use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_sync::waitqueue::AtomicWaker;
#[cfg(feature = "time")] #[cfg(feature = "time")]
use embassy_time::{Duration, Instant}; use embassy_time::{Duration, Instant};
use embassy_util::waitqueue::AtomicWaker;
use futures::future::poll_fn; use futures::future::poll_fn;
use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};

View File

@ -932,7 +932,7 @@ impl<'d, U: Instance, T: TimerInstance> UarteRxWithIdle<'d, U, T> {
pub(crate) mod sealed { pub(crate) mod sealed {
use core::sync::atomic::AtomicU8; use core::sync::atomic::AtomicU8;
use embassy_util::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use super::*; use super::*;

View File

@ -7,10 +7,10 @@ use core::task::Poll;
use cortex_m::peripheral::NVIC; use cortex_m::peripheral::NVIC;
use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_sync::waitqueue::AtomicWaker;
pub use embassy_usb; pub use embassy_usb;
use embassy_usb::driver::{self, EndpointError, Event, Unsupported}; use embassy_usb::driver::{self, EndpointError, Event, Unsupported};
use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection}; use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection};
use embassy_util::waitqueue::AtomicWaker;
use futures::future::poll_fn; use futures::future::poll_fn;
use futures::Future; use futures::Future;
use pac::usbd::RegisterBlock; use pac::usbd::RegisterBlock;

View File

@ -27,10 +27,10 @@ nightly = ["embassy-executor/nightly", "embedded-hal-1", "embedded-hal-async", "
unstable-traits = ["embedded-hal-1"] unstable-traits = ["embedded-hal-1"]
[dependencies] [dependencies]
embassy-util = { version = "0.1.0", path = "../embassy-util" } embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
embassy-executor = { version = "0.1.0", path = "../embassy-executor" } embassy-executor = { version = "0.1.0", path = "../embassy-executor" }
embassy-time = { version = "0.1.0", path = "../embassy-time", features = [ "tick-1mhz" ] } embassy-time = { version = "0.1.0", path = "../embassy-time", features = [ "tick-1mhz" ] }
embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-3"]} embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-2"]}
embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" } embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" }
embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" }
atomic-polyfill = "1.0.1" atomic-polyfill = "1.0.1"

View File

@ -5,7 +5,7 @@ use core::task::{Context, Poll};
use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; use embassy_cortex_m::interrupt::{Interrupt, InterruptExt};
use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef};
use embassy_util::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use crate::pac::common::{Reg, RW}; use crate::pac::common::{Reg, RW};
use crate::pac::SIO; use crate::pac::SIO;
@ -189,7 +189,7 @@ impl<'d, T: Pin> InputFuture<'d, T> {
unsafe { unsafe {
let irq = interrupt::IO_IRQ_BANK0::steal(); let irq = interrupt::IO_IRQ_BANK0::steal();
irq.disable(); irq.disable();
irq.set_priority(interrupt::Priority::P6); irq.set_priority(interrupt::Priority::P3);
// Each INTR register is divided into 8 groups, one group for each // Each INTR register is divided into 8 groups, one group for each
// pin, and each group consists of LEVEL_LOW, LEVEL_HIGH, EDGE_LOW, // pin, and each group consists of LEVEL_LOW, LEVEL_HIGH, EDGE_LOW,

View File

@ -2,9 +2,9 @@ use core::cell::Cell;
use atomic_polyfill::{AtomicU8, Ordering}; use atomic_polyfill::{AtomicU8, Ordering};
use critical_section::CriticalSection; use critical_section::CriticalSection;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::blocking_mutex::Mutex;
use embassy_time::driver::{AlarmHandle, Driver}; use embassy_time::driver::{AlarmHandle, Driver};
use embassy_util::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_util::blocking_mutex::Mutex;
use crate::interrupt::{Interrupt, InterruptExt}; use crate::interrupt::{Interrupt, InterruptExt};
use crate::{interrupt, pac}; use crate::{interrupt, pac};

View File

@ -31,7 +31,7 @@ flavors = [
] ]
[dependencies] [dependencies]
embassy-util = { version = "0.1.0", path = "../embassy-util" } embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
embassy-executor = { version = "0.1.0", path = "../embassy-executor" } embassy-executor = { version = "0.1.0", path = "../embassy-executor" }
embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true } embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true }
embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-4"]} embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-4"]}
@ -72,7 +72,7 @@ quote = "1.0.15"
stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", default-features = false, features = ["metadata"]} stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", default-features = false, features = ["metadata"]}
[features] [features]
defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-util/defmt", "embassy-executor/defmt", "embassy-embedded-hal/defmt", "embedded-io?/defmt", "embassy-usb?/defmt"] defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-sync/defmt", "embassy-executor/defmt", "embassy-embedded-hal/defmt", "embedded-io?/defmt", "embassy-usb?/defmt"]
sdmmc-rs = ["embedded-sdmmc"] sdmmc-rs = ["embedded-sdmmc"]
net = ["embassy-net" ] net = ["embassy-net" ]
memory-x = ["stm32-metapac/memory-x"] memory-x = ["stm32-metapac/memory-x"]

View File

@ -244,11 +244,11 @@ fn main() {
(("usart", "CTS"), quote!(crate::usart::CtsPin)), (("usart", "CTS"), quote!(crate::usart::CtsPin)),
(("usart", "RTS"), quote!(crate::usart::RtsPin)), (("usart", "RTS"), quote!(crate::usart::RtsPin)),
(("usart", "CK"), quote!(crate::usart::CkPin)), (("usart", "CK"), quote!(crate::usart::CkPin)),
(("usart", "TX"), quote!(crate::usart::TxPin)), (("lpuart", "TX"), quote!(crate::usart::TxPin)),
(("usart", "RX"), quote!(crate::usart::RxPin)), (("lpuart", "RX"), quote!(crate::usart::RxPin)),
(("usart", "CTS"), quote!(crate::usart::CtsPin)), (("lpuart", "CTS"), quote!(crate::usart::CtsPin)),
(("usart", "RTS"), quote!(crate::usart::RtsPin)), (("lpuart", "RTS"), quote!(crate::usart::RtsPin)),
(("usart", "CK"), quote!(crate::usart::CkPin)), (("lpuart", "CK"), quote!(crate::usart::CkPin)),
(("spi", "SCK"), quote!(crate::spi::SckPin)), (("spi", "SCK"), quote!(crate::spi::SckPin)),
(("spi", "MOSI"), quote!(crate::spi::MosiPin)), (("spi", "MOSI"), quote!(crate::spi::MosiPin)),
(("spi", "MISO"), quote!(crate::spi::MisoPin)), (("spi", "MISO"), quote!(crate::spi::MisoPin)),
@ -497,6 +497,8 @@ fn main() {
// (kind, signal) => trait // (kind, signal) => trait
(("usart", "RX"), quote!(crate::usart::RxDma)), (("usart", "RX"), quote!(crate::usart::RxDma)),
(("usart", "TX"), quote!(crate::usart::TxDma)), (("usart", "TX"), quote!(crate::usart::TxDma)),
(("lpuart", "RX"), quote!(crate::usart::RxDma)),
(("lpuart", "TX"), quote!(crate::usart::TxDma)),
(("spi", "RX"), quote!(crate::spi::RxDma)), (("spi", "RX"), quote!(crate::spi::RxDma)),
(("spi", "TX"), quote!(crate::spi::TxDma)), (("spi", "TX"), quote!(crate::spi::TxDma)),
(("i2c", "RX"), quote!(crate::i2c::RxDma)), (("i2c", "RX"), quote!(crate::i2c::RxDma)),

View File

@ -1,7 +1,7 @@
use core::task::Poll; use core::task::Poll;
use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_util::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use futures::future::poll_fn; use futures::future::poll_fn;
use crate::gpio::sealed::AFType; use crate::gpio::sealed::AFType;

View File

@ -3,7 +3,7 @@
use core::sync::atomic::{fence, Ordering}; use core::sync::atomic::{fence, Ordering};
use core::task::Waker; use core::task::Waker;
use embassy_util::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use super::{TransferOptions, Word, WordSize}; use super::{TransferOptions, Word, WordSize};
use crate::_generated::BDMA_CHANNEL_COUNT; use crate::_generated::BDMA_CHANNEL_COUNT;

View File

@ -1,7 +1,7 @@
use core::sync::atomic::{fence, Ordering}; use core::sync::atomic::{fence, Ordering};
use core::task::Waker; use core::task::Waker;
use embassy_util::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use super::{Burst, FlowControl, Request, TransferOptions, Word, WordSize}; use super::{Burst, FlowControl, Request, TransferOptions, Word, WordSize};
use crate::_generated::DMA_CHANNEL_COUNT; use crate::_generated::DMA_CHANNEL_COUNT;

View File

@ -1,7 +1,7 @@
use core::sync::atomic::{fence, Ordering}; use core::sync::atomic::{fence, Ordering};
use core::task::Waker; use core::task::Waker;
use embassy_util::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use super::{Request, TransferOptions, Word, WordSize}; use super::{Request, TransferOptions, Word, WordSize};
use crate::_generated::GPDMA_CHANNEL_COUNT; use crate::_generated::GPDMA_CHANNEL_COUNT;

View File

@ -7,7 +7,7 @@ use core::task::Waker;
use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage}; use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage};
use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_net::{Device, DeviceCapabilities, LinkState, PacketBuf, MTU}; use embassy_net::{Device, DeviceCapabilities, LinkState, PacketBuf, MTU};
use embassy_util::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use crate::gpio::sealed::{AFType, Pin as __GpioPin}; use crate::gpio::sealed::{AFType, Pin as __GpioPin};
use crate::gpio::{AnyPin, Speed}; use crate::gpio::{AnyPin, Speed};

View File

@ -5,7 +5,7 @@ use core::task::Waker;
use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage}; use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage};
use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_net::{Device, DeviceCapabilities, LinkState, PacketBuf, MTU}; use embassy_net::{Device, DeviceCapabilities, LinkState, PacketBuf, MTU};
use embassy_util::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use crate::gpio::sealed::{AFType, Pin as _}; use crate::gpio::sealed::{AFType, Pin as _};
use crate::gpio::{AnyPin, Speed}; use crate::gpio::{AnyPin, Speed};

View File

@ -4,7 +4,7 @@ use core::pin::Pin;
use core::task::{Context, Poll}; use core::task::{Context, Poll};
use embassy_hal_common::impl_peripheral; use embassy_hal_common::impl_peripheral;
use embassy_util::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use crate::gpio::{AnyPin, Input, Pin as GpioPin}; use crate::gpio::{AnyPin, Input, Pin as GpioPin};
use crate::pac::exti::regs::Lines; use crate::pac::exti::regs::Lines;

View File

@ -5,7 +5,7 @@ use atomic_polyfill::{AtomicUsize, Ordering};
use embassy_embedded_hal::SetConfig; use embassy_embedded_hal::SetConfig;
use embassy_hal_common::drop::OnDrop; use embassy_hal_common::drop::OnDrop;
use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_util::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use futures::future::poll_fn; use futures::future::poll_fn;
use crate::dma::NoDma; use crate::dma::NoDma;

View File

@ -3,7 +3,7 @@
use core::task::Poll; use core::task::Poll;
use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_util::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use futures::future::poll_fn; use futures::future::poll_fn;
use rand_core::{CryptoRng, RngCore}; use rand_core::{CryptoRng, RngCore};

View File

@ -5,7 +5,7 @@ use core::task::Poll;
use embassy_hal_common::drop::OnDrop; use embassy_hal_common::drop::OnDrop;
use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_util::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use futures::future::poll_fn; use futures::future::poll_fn;
use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR}; use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR};
@ -1514,8 +1514,8 @@ foreach_peripheral!(
INNER INNER
} }
fn state() -> &'static ::embassy_util::waitqueue::AtomicWaker { fn state() -> &'static ::embassy_sync::waitqueue::AtomicWaker {
static WAKER: ::embassy_util::waitqueue::AtomicWaker = ::embassy_util::waitqueue::AtomicWaker::new(); static WAKER: ::embassy_sync::waitqueue::AtomicWaker = ::embassy_sync::waitqueue::AtomicWaker::new();
&WAKER &WAKER
} }
} }

View File

@ -4,10 +4,10 @@ use core::sync::atomic::{compiler_fence, Ordering};
use core::{mem, ptr}; use core::{mem, ptr};
use atomic_polyfill::{AtomicU32, AtomicU8}; use atomic_polyfill::{AtomicU32, AtomicU8};
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::blocking_mutex::Mutex;
use embassy_time::driver::{AlarmHandle, Driver}; use embassy_time::driver::{AlarmHandle, Driver};
use embassy_time::TICKS_PER_SECOND; use embassy_time::TICKS_PER_SECOND;
use embassy_util::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_util::blocking_mutex::Mutex;
use stm32_metapac::timer::regs; use stm32_metapac::timer::regs;
use crate::interrupt::{CriticalSection, InterruptExt}; use crate::interrupt::{CriticalSection, InterruptExt};

View File

@ -4,19 +4,19 @@ use core::task::Poll;
use atomic_polyfill::{compiler_fence, Ordering}; use atomic_polyfill::{compiler_fence, Ordering};
use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage}; use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage};
use embassy_hal_common::ring_buffer::RingBuffer; use embassy_hal_common::ring_buffer::RingBuffer;
use embassy_util::waitqueue::WakerRegistration; use embassy_sync::waitqueue::WakerRegistration;
use futures::future::poll_fn; use futures::future::poll_fn;
use super::*; use super::*;
pub struct State<'d, T: Instance>(StateStorage<StateInner<'d, T>>); pub struct State<'d, T: BasicInstance>(StateStorage<StateInner<'d, T>>);
impl<'d, T: Instance> State<'d, T> { impl<'d, T: BasicInstance> State<'d, T> {
pub fn new() -> Self { pub fn new() -> Self {
Self(StateStorage::new()) Self(StateStorage::new())
} }
} }
struct StateInner<'d, T: Instance> { struct StateInner<'d, T: BasicInstance> {
phantom: PhantomData<&'d mut T>, phantom: PhantomData<&'d mut T>,
rx_waker: WakerRegistration, rx_waker: WakerRegistration,
@ -26,16 +26,16 @@ struct StateInner<'d, T: Instance> {
tx: RingBuffer<'d>, tx: RingBuffer<'d>,
} }
unsafe impl<'d, T: Instance> Send for StateInner<'d, T> {} unsafe impl<'d, T: BasicInstance> Send for StateInner<'d, T> {}
unsafe impl<'d, T: Instance> Sync for StateInner<'d, T> {} unsafe impl<'d, T: BasicInstance> Sync for StateInner<'d, T> {}
pub struct BufferedUart<'d, T: Instance> { pub struct BufferedUart<'d, T: BasicInstance> {
inner: PeripheralMutex<'d, StateInner<'d, T>>, inner: PeripheralMutex<'d, StateInner<'d, T>>,
} }
impl<'d, T: Instance> Unpin for BufferedUart<'d, T> {} impl<'d, T: BasicInstance> Unpin for BufferedUart<'d, T> {}
impl<'d, T: Instance> BufferedUart<'d, T> { impl<'d, T: BasicInstance> BufferedUart<'d, T> {
pub fn new( pub fn new(
state: &'d mut State<'d, T>, state: &'d mut State<'d, T>,
_uart: Uart<'d, T, NoDma, NoDma>, _uart: Uart<'d, T, NoDma, NoDma>,
@ -66,7 +66,7 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
} }
} }
impl<'d, T: Instance> StateInner<'d, T> impl<'d, T: BasicInstance> StateInner<'d, T>
where where
Self: 'd, Self: 'd,
{ {
@ -135,7 +135,7 @@ where
} }
} }
impl<'d, T: Instance> PeripheralState for StateInner<'d, T> impl<'d, T: BasicInstance> PeripheralState for StateInner<'d, T>
where where
Self: 'd, Self: 'd,
{ {
@ -152,11 +152,11 @@ impl embedded_io::Error for Error {
} }
} }
impl<'d, T: Instance> embedded_io::Io for BufferedUart<'d, T> { impl<'d, T: BasicInstance> embedded_io::Io for BufferedUart<'d, T> {
type Error = Error; type Error = Error;
} }
impl<'d, T: Instance> embedded_io::asynch::Read for BufferedUart<'d, T> { impl<'d, T: BasicInstance> embedded_io::asynch::Read for BufferedUart<'d, T> {
type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>> type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>>
where where
Self: 'a; Self: 'a;
@ -194,7 +194,7 @@ impl<'d, T: Instance> embedded_io::asynch::Read for BufferedUart<'d, T> {
} }
} }
impl<'d, T: Instance> embedded_io::asynch::BufRead for BufferedUart<'d, T> { impl<'d, T: BasicInstance> embedded_io::asynch::BufRead for BufferedUart<'d, T> {
type FillBufFuture<'a> = impl Future<Output = Result<&'a [u8], Self::Error>> type FillBufFuture<'a> = impl Future<Output = Result<&'a [u8], Self::Error>>
where where
Self: 'a; Self: 'a;
@ -231,7 +231,7 @@ impl<'d, T: Instance> embedded_io::asynch::BufRead for BufferedUart<'d, T> {
} }
} }
impl<'d, T: Instance> embedded_io::asynch::Write for BufferedUart<'d, T> { impl<'d, T: BasicInstance> embedded_io::asynch::Write for BufferedUart<'d, T> {
type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>> type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>>
where where
Self: 'a; Self: 'a;

View File

@ -6,9 +6,10 @@ use embassy_hal_common::{into_ref, PeripheralRef};
use crate::dma::NoDma; use crate::dma::NoDma;
use crate::gpio::sealed::AFType; use crate::gpio::sealed::AFType;
use crate::interrupt::Interrupt; #[cfg(any(lpuart_v1, lpuart_v2))]
use crate::pac::usart::{regs, vals}; use crate::pac::lpuart::{regs, vals, Lpuart as Regs};
use crate::rcc::RccPeripheral; #[cfg(not(any(lpuart_v1, lpuart_v2)))]
use crate::pac::usart::{regs, vals, Usart as Regs};
use crate::{peripherals, Peripheral}; use crate::{peripherals, Peripheral};
#[derive(Clone, Copy, PartialEq, Eq, Debug)] #[derive(Clone, Copy, PartialEq, Eq, Debug)]
@ -71,22 +72,23 @@ pub enum Error {
Parity, Parity,
} }
pub struct Uart<'d, T: Instance, TxDma = NoDma, RxDma = NoDma> { pub struct Uart<'d, T: BasicInstance, TxDma = NoDma, RxDma = NoDma> {
phantom: PhantomData<&'d mut T>,
tx: UartTx<'d, T, TxDma>, tx: UartTx<'d, T, TxDma>,
rx: UartRx<'d, T, RxDma>, rx: UartRx<'d, T, RxDma>,
} }
pub struct UartTx<'d, T: Instance, TxDma = NoDma> { pub struct UartTx<'d, T: BasicInstance, TxDma = NoDma> {
phantom: PhantomData<&'d mut T>, phantom: PhantomData<&'d mut T>,
tx_dma: PeripheralRef<'d, TxDma>, tx_dma: PeripheralRef<'d, TxDma>,
} }
pub struct UartRx<'d, T: Instance, RxDma = NoDma> { pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> {
phantom: PhantomData<&'d mut T>, phantom: PhantomData<&'d mut T>,
rx_dma: PeripheralRef<'d, RxDma>, rx_dma: PeripheralRef<'d, RxDma>,
} }
impl<'d, T: Instance, TxDma> UartTx<'d, T, TxDma> { impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
fn new(tx_dma: PeripheralRef<'d, TxDma>) -> Self { fn new(tx_dma: PeripheralRef<'d, TxDma>) -> Self {
Self { Self {
tx_dma, tx_dma,
@ -132,7 +134,7 @@ impl<'d, T: Instance, TxDma> UartTx<'d, T, TxDma> {
} }
} }
impl<'d, T: Instance, RxDma> UartRx<'d, T, RxDma> { impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
fn new(rx_dma: PeripheralRef<'d, RxDma>) -> Self { fn new(rx_dma: PeripheralRef<'d, RxDma>) -> Self {
Self { Self {
rx_dma, rx_dma,
@ -187,7 +189,7 @@ impl<'d, T: Instance, RxDma> UartRx<'d, T, RxDma> {
} }
} }
impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
pub fn new( pub fn new(
_inner: impl Peripheral<P = T> + 'd, _inner: impl Peripheral<P = T> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
@ -203,7 +205,7 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
let pclk_freq = T::frequency(); let pclk_freq = T::frequency();
// TODO: better calculation, including error checking and OVER8 if possible. // TODO: better calculation, including error checking and OVER8 if possible.
let div = (pclk_freq.0 + (config.baudrate / 2)) / config.baudrate; let div = (pclk_freq.0 + (config.baudrate / 2)) / config.baudrate * T::MULTIPLIER;
let r = T::regs(); let r = T::regs();
@ -235,6 +237,7 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
Self { Self {
tx: UartTx::new(tx_dma), tx: UartTx::new(tx_dma),
rx: UartRx::new(rx_dma), rx: UartRx::new(rx_dma),
phantom: PhantomData {},
} }
} }
@ -275,7 +278,7 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
mod eh02 { mod eh02 {
use super::*; use super::*;
impl<'d, T: Instance, RxDma> embedded_hal_02::serial::Read<u8> for UartRx<'d, T, RxDma> { impl<'d, T: BasicInstance, RxDma> embedded_hal_02::serial::Read<u8> for UartRx<'d, T, RxDma> {
type Error = Error; type Error = Error;
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
let r = T::regs(); let r = T::regs();
@ -302,7 +305,7 @@ mod eh02 {
} }
} }
impl<'d, T: Instance, TxDma> embedded_hal_02::blocking::serial::Write<u8> for UartTx<'d, T, TxDma> { impl<'d, T: BasicInstance, TxDma> embedded_hal_02::blocking::serial::Write<u8> for UartTx<'d, T, TxDma> {
type Error = Error; type Error = Error;
fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
self.blocking_write(buffer) self.blocking_write(buffer)
@ -312,14 +315,14 @@ mod eh02 {
} }
} }
impl<'d, T: Instance, TxDma, RxDma> embedded_hal_02::serial::Read<u8> for Uart<'d, T, TxDma, RxDma> { impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_02::serial::Read<u8> for Uart<'d, T, TxDma, RxDma> {
type Error = Error; type Error = Error;
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
embedded_hal_02::serial::Read::read(&mut self.rx) embedded_hal_02::serial::Read::read(&mut self.rx)
} }
} }
impl<'d, T: Instance, TxDma, RxDma> embedded_hal_02::blocking::serial::Write<u8> for Uart<'d, T, TxDma, RxDma> { impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_02::blocking::serial::Write<u8> for Uart<'d, T, TxDma, RxDma> {
type Error = Error; type Error = Error;
fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
self.blocking_write(buffer) self.blocking_write(buffer)
@ -345,15 +348,15 @@ mod eh1 {
} }
} }
impl<'d, T: Instance, TxDma, RxDma> embedded_hal_1::serial::ErrorType for Uart<'d, T, TxDma, RxDma> { impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_1::serial::ErrorType for Uart<'d, T, TxDma, RxDma> {
type Error = Error; type Error = Error;
} }
impl<'d, T: Instance, TxDma> embedded_hal_1::serial::ErrorType for UartTx<'d, T, TxDma> { impl<'d, T: BasicInstance, TxDma> embedded_hal_1::serial::ErrorType for UartTx<'d, T, TxDma> {
type Error = Error; type Error = Error;
} }
impl<'d, T: Instance, RxDma> embedded_hal_1::serial::ErrorType for UartRx<'d, T, RxDma> { impl<'d, T: BasicInstance, RxDma> embedded_hal_1::serial::ErrorType for UartRx<'d, T, RxDma> {
type Error = Error; type Error = Error;
} }
} }
@ -362,7 +365,7 @@ cfg_if::cfg_if! {
if #[cfg(all(feature = "unstable-traits", feature = "nightly", feature = "_todo_embedded_hal_serial"))] { if #[cfg(all(feature = "unstable-traits", feature = "nightly", feature = "_todo_embedded_hal_serial"))] {
use core::future::Future; use core::future::Future;
impl<'d, T: Instance, TxDma> embedded_hal_async::serial::Write for UartTx<'d, T, TxDma> impl<'d, T: BasicInstance, TxDma> embedded_hal_async::serial::Write for UartTx<'d, T, TxDma>
where where
TxDma: crate::usart::TxDma<T>, TxDma: crate::usart::TxDma<T>,
{ {
@ -379,7 +382,7 @@ cfg_if::cfg_if! {
} }
} }
impl<'d, T: Instance, RxDma> embedded_hal_async::serial::Read for UartRx<'d, T, RxDma> impl<'d, T: BasicInstance, RxDma> embedded_hal_async::serial::Read for UartRx<'d, T, RxDma>
where where
RxDma: crate::usart::RxDma<T>, RxDma: crate::usart::RxDma<T>,
{ {
@ -390,7 +393,7 @@ cfg_if::cfg_if! {
} }
} }
impl<'d, T: Instance, TxDma, RxDma> embedded_hal_async::serial::Write for Uart<'d, T, TxDma, RxDma> impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_async::serial::Write for Uart<'d, T, TxDma, RxDma>
where where
TxDma: crate::usart::TxDma<T>, TxDma: crate::usart::TxDma<T>,
{ {
@ -407,7 +410,7 @@ cfg_if::cfg_if! {
} }
} }
impl<'d, T: Instance, TxDma, RxDma> embedded_hal_async::serial::Read for Uart<'d, T, TxDma, RxDma> impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_async::serial::Read for Uart<'d, T, TxDma, RxDma>
where where
RxDma: crate::usart::RxDma<T>, RxDma: crate::usart::RxDma<T>,
{ {
@ -442,60 +445,90 @@ fn sr(r: crate::pac::usart::Usart) -> crate::pac::common::Reg<regs::Sr, crate::p
#[cfg(usart_v1)] #[cfg(usart_v1)]
#[allow(unused)] #[allow(unused)]
unsafe fn clear_interrupt_flags(_r: crate::pac::usart::Usart, _sr: regs::Sr) { unsafe fn clear_interrupt_flags(_r: Regs, _sr: regs::Sr) {
// On v1 the flags are cleared implicitly by reads and writes to DR. // On v1 the flags are cleared implicitly by reads and writes to DR.
} }
#[cfg(usart_v2)] #[cfg(usart_v2)]
fn tdr(r: crate::pac::usart::Usart) -> *mut u8 { fn tdr(r: Regs) -> *mut u8 {
r.tdr().ptr() as _ r.tdr().ptr() as _
} }
#[cfg(usart_v2)] #[cfg(usart_v2)]
fn rdr(r: crate::pac::usart::Usart) -> *mut u8 { fn rdr(r: Regs) -> *mut u8 {
r.rdr().ptr() as _ r.rdr().ptr() as _
} }
#[cfg(usart_v2)] #[cfg(usart_v2)]
fn sr(r: crate::pac::usart::Usart) -> crate::pac::common::Reg<regs::Ixr, crate::pac::common::R> { fn sr(r: Regs) -> crate::pac::common::Reg<regs::Isr, crate::pac::common::R> {
r.isr() r.isr()
} }
#[cfg(usart_v2)] #[cfg(usart_v2)]
#[allow(unused)] #[allow(unused)]
unsafe fn clear_interrupt_flags(r: crate::pac::usart::Usart, sr: regs::Ixr) { unsafe fn clear_interrupt_flags(r: Regs, sr: regs::Isr) {
r.icr().write(|w| *w = sr); r.icr().write(|w| *w = regs::Icr(sr.0));
} }
pub(crate) mod sealed { pub(crate) mod sealed {
pub trait Instance { use super::*;
fn regs() -> crate::pac::usart::Usart;
pub trait BasicInstance: crate::rcc::RccPeripheral {
const MULTIPLIER: u32;
type Interrupt: crate::interrupt::Interrupt;
fn regs() -> Regs;
}
pub trait FullInstance: BasicInstance {
fn regs_uart() -> crate::pac::usart::Usart;
} }
} }
pub trait Instance: sealed::Instance + RccPeripheral { pub trait BasicInstance: sealed::BasicInstance {}
type Interrupt: Interrupt;
pub trait FullInstance: sealed::FullInstance {}
pin_trait!(RxPin, BasicInstance);
pin_trait!(TxPin, BasicInstance);
pin_trait!(CtsPin, BasicInstance);
pin_trait!(RtsPin, BasicInstance);
pin_trait!(CkPin, BasicInstance);
dma_trait!(TxDma, BasicInstance);
dma_trait!(RxDma, BasicInstance);
macro_rules! impl_lpuart {
($inst:ident, $irq:ident, $mul:expr) => {
impl sealed::BasicInstance for crate::peripherals::$inst {
const MULTIPLIER: u32 = $mul;
type Interrupt = crate::interrupt::$irq;
fn regs() -> Regs {
Regs(crate::pac::$inst.0)
}
} }
pin_trait!(RxPin, Instance); impl BasicInstance for peripherals::$inst {}
pin_trait!(TxPin, Instance); };
pin_trait!(CtsPin, Instance); }
pin_trait!(RtsPin, Instance);
pin_trait!(CkPin, Instance);
dma_trait!(TxDma, Instance);
dma_trait!(RxDma, Instance);
foreach_interrupt!( foreach_interrupt!(
($inst:ident, lpuart, $block:ident, $signal_name:ident, $irq:ident) => {
impl_lpuart!($inst, $irq, 255);
};
($inst:ident, usart, $block:ident, $signal_name:ident, $irq:ident) => { ($inst:ident, usart, $block:ident, $signal_name:ident, $irq:ident) => {
impl sealed::Instance for peripherals::$inst { impl_lpuart!($inst, $irq, 1);
fn regs() -> crate::pac::usart::Usart {
impl sealed::FullInstance for peripherals::$inst {
fn regs_uart() -> crate::pac::usart::Usart {
crate::pac::$inst crate::pac::$inst
} }
} }
impl Instance for peripherals::$inst { impl FullInstance for peripherals::$inst {
type Interrupt = crate::interrupt::$irq;
} }
}; };
); );

View File

@ -6,10 +6,10 @@ use core::task::Poll;
use atomic_polyfill::{AtomicBool, AtomicU8}; use atomic_polyfill::{AtomicBool, AtomicU8};
use embassy_hal_common::into_ref; use embassy_hal_common::into_ref;
use embassy_sync::waitqueue::AtomicWaker;
use embassy_time::{block_for, Duration}; use embassy_time::{block_for, Duration};
use embassy_usb::driver::{self, EndpointAllocError, EndpointError, Event, Unsupported}; use embassy_usb::driver::{self, EndpointAllocError, EndpointError, Event, Unsupported};
use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection}; use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection};
use embassy_util::waitqueue::AtomicWaker;
use futures::future::poll_fn; use futures::future::poll_fn;
use futures::Future; use futures::Future;
use pac::common::{Reg, RW}; use pac::common::{Reg, RW};

View File

@ -1,11 +1,11 @@
[package] [package]
name = "embassy-util" name = "embassy-sync"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
[package.metadata.embassy_docs] [package.metadata.embassy_docs]
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-util-v$VERSION/embassy-util/src/" src_base = "https://github.com/embassy-rs/embassy/blob/embassy-sync-v$VERSION/embassy-sync/src/"
src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-util/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-sync/src/"
features = ["nightly"] features = ["nightly"]
target = "thumbv7em-none-eabi" target = "thumbv7em-none-eabi"
@ -31,3 +31,4 @@ futures-util = { version = "0.3.17", features = [ "channel" ] }
# Enable critical-section implementation for std, for tests # Enable critical-section implementation for std, for tests
critical-section = { version = "1.1", features = ["std"] } critical-section = { version = "1.1", features = ["std"] }
static_cell = "1.0"

View File

@ -373,8 +373,8 @@ where
/// Establish a new bounded channel. For example, to create one with a NoopMutex: /// Establish a new bounded channel. For example, to create one with a NoopMutex:
/// ///
/// ``` /// ```
/// use embassy_util::channel::mpmc::Channel; /// use embassy_sync::channel::Channel;
/// use embassy_util::blocking_mutex::raw::NoopRawMutex; /// use embassy_sync::blocking_mutex::raw::NoopRawMutex;
/// ///
/// // Declare a bounded channel of 3 u32s. /// // Declare a bounded channel of 3 u32s.
/// let mut channel = Channel::<NoopRawMutex, u32, 3>::new(); /// let mut channel = Channel::<NoopRawMutex, u32, 3>::new();
@ -471,10 +471,10 @@ mod tests {
use futures_executor::ThreadPool; use futures_executor::ThreadPool;
use futures_timer::Delay; use futures_timer::Delay;
use futures_util::task::SpawnExt; use futures_util::task::SpawnExt;
use static_cell::StaticCell;
use super::*; use super::*;
use crate::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex}; use crate::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex};
use crate::Forever;
fn capacity<T, const N: usize>(c: &ChannelState<T, N>) -> usize { fn capacity<T, const N: usize>(c: &ChannelState<T, N>) -> usize {
c.queue.capacity() - c.queue.len() c.queue.capacity() - c.queue.len()
@ -549,8 +549,8 @@ mod tests {
async fn receiver_receives_given_try_send_async() { async fn receiver_receives_given_try_send_async() {
let executor = ThreadPool::new().unwrap(); let executor = ThreadPool::new().unwrap();
static CHANNEL: Forever<Channel<CriticalSectionRawMutex, u32, 3>> = Forever::new(); static CHANNEL: StaticCell<Channel<CriticalSectionRawMutex, u32, 3>> = StaticCell::new();
let c = &*CHANNEL.put(Channel::new()); let c = &*CHANNEL.init(Channel::new());
let c2 = c; let c2 = c;
assert!(executor assert!(executor
.spawn(async move { .spawn(async move {
@ -571,8 +571,8 @@ mod tests {
async fn senders_sends_wait_until_capacity() { async fn senders_sends_wait_until_capacity() {
let executor = ThreadPool::new().unwrap(); let executor = ThreadPool::new().unwrap();
static CHANNEL: Forever<Channel<CriticalSectionRawMutex, u32, 1>> = Forever::new(); static CHANNEL: StaticCell<Channel<CriticalSectionRawMutex, u32, 1>> = StaticCell::new();
let c = &*CHANNEL.put(Channel::new()); let c = &*CHANNEL.init(Channel::new());
assert!(c.try_send(1).is_ok()); assert!(c.try_send(1).is_ok());
let c2 = c; let c2 = c;

228
embassy-sync/src/fmt.rs Normal file
View File

@ -0,0 +1,228 @@
#![macro_use]
#![allow(unused_macros)]
#[cfg(all(feature = "defmt", feature = "log"))]
compile_error!("You may not enable both `defmt` and `log` features.");
macro_rules! assert {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::assert!($($x)*);
#[cfg(feature = "defmt")]
::defmt::assert!($($x)*);
}
};
}
macro_rules! assert_eq {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::assert_eq!($($x)*);
#[cfg(feature = "defmt")]
::defmt::assert_eq!($($x)*);
}
};
}
macro_rules! assert_ne {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::assert_ne!($($x)*);
#[cfg(feature = "defmt")]
::defmt::assert_ne!($($x)*);
}
};
}
macro_rules! debug_assert {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::debug_assert!($($x)*);
#[cfg(feature = "defmt")]
::defmt::debug_assert!($($x)*);
}
};
}
macro_rules! debug_assert_eq {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::debug_assert_eq!($($x)*);
#[cfg(feature = "defmt")]
::defmt::debug_assert_eq!($($x)*);
}
};
}
macro_rules! debug_assert_ne {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::debug_assert_ne!($($x)*);
#[cfg(feature = "defmt")]
::defmt::debug_assert_ne!($($x)*);
}
};
}
macro_rules! todo {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::todo!($($x)*);
#[cfg(feature = "defmt")]
::defmt::todo!($($x)*);
}
};
}
macro_rules! unreachable {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::unreachable!($($x)*);
#[cfg(feature = "defmt")]
::defmt::unreachable!($($x)*);
}
};
}
macro_rules! panic {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::panic!($($x)*);
#[cfg(feature = "defmt")]
::defmt::panic!($($x)*);
}
};
}
macro_rules! trace {
($s:literal $(, $x:expr)* $(,)?) => {
{
#[cfg(feature = "log")]
::log::trace!($s $(, $x)*);
#[cfg(feature = "defmt")]
::defmt::trace!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt")))]
let _ = ($( & $x ),*);
}
};
}
macro_rules! debug {
($s:literal $(, $x:expr)* $(,)?) => {
{
#[cfg(feature = "log")]
::log::debug!($s $(, $x)*);
#[cfg(feature = "defmt")]
::defmt::debug!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt")))]
let _ = ($( & $x ),*);
}
};
}
macro_rules! info {
($s:literal $(, $x:expr)* $(,)?) => {
{
#[cfg(feature = "log")]
::log::info!($s $(, $x)*);
#[cfg(feature = "defmt")]
::defmt::info!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt")))]
let _ = ($( & $x ),*);
}
};
}
macro_rules! warn {
($s:literal $(, $x:expr)* $(,)?) => {
{
#[cfg(feature = "log")]
::log::warn!($s $(, $x)*);
#[cfg(feature = "defmt")]
::defmt::warn!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt")))]
let _ = ($( & $x ),*);
}
};
}
macro_rules! error {
($s:literal $(, $x:expr)* $(,)?) => {
{
#[cfg(feature = "log")]
::log::error!($s $(, $x)*);
#[cfg(feature = "defmt")]
::defmt::error!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt")))]
let _ = ($( & $x ),*);
}
};
}
#[cfg(feature = "defmt")]
macro_rules! unwrap {
($($x:tt)*) => {
::defmt::unwrap!($($x)*)
};
}
#[cfg(not(feature = "defmt"))]
macro_rules! unwrap {
($arg:expr) => {
match $crate::fmt::Try::into_result($arg) {
::core::result::Result::Ok(t) => t,
::core::result::Result::Err(e) => {
::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e);
}
}
};
($arg:expr, $($msg:expr),+ $(,)? ) => {
match $crate::fmt::Try::into_result($arg) {
::core::result::Result::Ok(t) => t,
::core::result::Result::Err(e) => {
::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e);
}
}
}
}
#[cfg(feature = "defmt-timestamp-uptime")]
defmt::timestamp! {"{=u64:us}", crate::time::Instant::now().as_micros() }
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct NoneError;
pub trait Try {
type Ok;
type Error;
fn into_result(self) -> Result<Self::Ok, Self::Error>;
}
impl<T> Try for Option<T> {
type Ok = T;
type Error = NoneError;
#[inline]
fn into_result(self) -> Result<T, NoneError> {
self.ok_or(NoneError)
}
}
impl<T, E> Try for Result<T, E> {
type Ok = T;
type Error = E;
#[inline]
fn into_result(self) -> Self {
self
}
}

View File

@ -14,12 +14,6 @@ pub mod blocking_mutex;
pub mod channel; pub mod channel;
pub mod mutex; pub mod mutex;
pub mod pipe; pub mod pipe;
pub mod pubsub;
pub mod signal;
pub mod waitqueue; pub mod waitqueue;
mod forever;
mod select;
mod yield_now;
pub use forever::*;
pub use select::*;
pub use yield_now::*;

View File

@ -241,8 +241,8 @@ where
/// Establish a new bounded pipe. For example, to create one with a NoopMutex: /// Establish a new bounded pipe. For example, to create one with a NoopMutex:
/// ///
/// ``` /// ```
/// use embassy_util::pipe::Pipe; /// use embassy_sync::pipe::Pipe;
/// use embassy_util::blocking_mutex::raw::NoopRawMutex; /// use embassy_sync::blocking_mutex::raw::NoopRawMutex;
/// ///
/// // Declare a bounded pipe, with a buffer of 256 bytes. /// // Declare a bounded pipe, with a buffer of 256 bytes.
/// let mut pipe = Pipe::<NoopRawMutex, 256>::new(); /// let mut pipe = Pipe::<NoopRawMutex, 256>::new();
@ -461,10 +461,10 @@ mod io_impls {
mod tests { mod tests {
use futures_executor::ThreadPool; use futures_executor::ThreadPool;
use futures_util::task::SpawnExt; use futures_util::task::SpawnExt;
use static_cell::StaticCell;
use super::*; use super::*;
use crate::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex}; use crate::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex};
use crate::Forever;
fn capacity<const N: usize>(c: &PipeState<N>) -> usize { fn capacity<const N: usize>(c: &PipeState<N>) -> usize {
N - c.buffer.len() N - c.buffer.len()
@ -528,8 +528,8 @@ mod tests {
async fn receiver_receives_given_try_write_async() { async fn receiver_receives_given_try_write_async() {
let executor = ThreadPool::new().unwrap(); let executor = ThreadPool::new().unwrap();
static CHANNEL: Forever<Pipe<CriticalSectionRawMutex, 3>> = Forever::new(); static CHANNEL: StaticCell<Pipe<CriticalSectionRawMutex, 3>> = StaticCell::new();
let c = &*CHANNEL.put(Pipe::new()); let c = &*CHANNEL.init(Pipe::new());
let c2 = c; let c2 = c;
let f = async move { let f = async move {
assert_eq!(c2.try_write(&[42]), Ok(1)); assert_eq!(c2.try_write(&[42]), Ok(1));

View File

@ -33,9 +33,9 @@ pub use subscriber::{DynSubscriber, Subscriber};
/// ## Example /// ## Example
/// ///
/// ``` /// ```
/// # use embassy_util::blocking_mutex::raw::NoopRawMutex; /// # use embassy_sync::blocking_mutex::raw::NoopRawMutex;
/// # use embassy_util::channel::pubsub::WaitResult; /// # use embassy_sync::pubsub::WaitResult;
/// # use embassy_util::channel::pubsub::PubSubChannel; /// # use embassy_sync::pubsub::PubSubChannel;
/// # use futures_executor::block_on; /// # use futures_executor::block_on;
/// # let test = async { /// # let test = async {
/// // Create the channel. This can be static as well /// // Create the channel. This can be static as well

View File

@ -19,7 +19,7 @@ use core::task::{Context, Poll, Waker};
/// Signals are generally declared as `static`s and then borrowed as required. /// Signals are generally declared as `static`s and then borrowed as required.
/// ///
/// ``` /// ```
/// use embassy_util::channel::signal::Signal; /// use embassy_sync::signal::Signal;
/// ///
/// enum SomeCommand { /// enum SomeCommand {
/// On, /// On,

View File

@ -6,7 +6,7 @@
//! //!
//! - Define a struct `MyDriver` //! - Define a struct `MyDriver`
//! - Implement [`Driver`] for it //! - Implement [`Driver`] for it
//! - Register it as the global driver with [`time_driver_impl`]. //! - Register it as the global driver with [`time_driver_impl`](crate::time_driver_impl).
//! - Enable the Cargo features `embassy-executor/time` and one of `embassy-time/tick-*` corresponding to the //! - Enable the Cargo features `embassy-executor/time` and one of `embassy-time/tick-*` corresponding to the
//! tick rate of your driver. //! tick rate of your driver.
//! //!

View File

@ -14,7 +14,7 @@ default = ["usbd-hid"]
usbd-hid = ["dep:usbd-hid", "ssmarshal"] usbd-hid = ["dep:usbd-hid", "ssmarshal"]
[dependencies] [dependencies]
embassy-util = { version = "0.1.0", path = "../embassy-util" } embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
embassy-usb = { version = "0.1.0", path = "../embassy-usb" } embassy-usb = { version = "0.1.0", path = "../embassy-usb" }
defmt = { version = "0.3", optional = true } defmt = { version = "0.3", optional = true }

View File

@ -10,7 +10,7 @@ features = ["defmt"]
target = "thumbv7em-none-eabi" target = "thumbv7em-none-eabi"
[dependencies] [dependencies]
embassy-util = { version = "0.1.0", path = "../embassy-util" } embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
embassy-usb = { version = "0.1.0", path = "../embassy-usb" } embassy-usb = { version = "0.1.0", path = "../embassy-usb" }
defmt = { version = "0.3", optional = true } defmt = { version = "0.3", optional = true }

View File

@ -10,7 +10,7 @@ features = ["defmt"]
target = "thumbv7em-none-eabi" target = "thumbv7em-none-eabi"
[dependencies] [dependencies]
embassy-util = { version = "0.1.0", path = "../embassy-util" } embassy-sync = { version = "0.1.0", path = "../embassy-sync" }
embassy-usb = { version = "0.1.0", path = "../embassy-usb" } embassy-usb = { version = "0.1.0", path = "../embassy-usb" }
defmt = { version = "0.3", optional = true } defmt = { version = "0.3", optional = true }

View File

@ -9,11 +9,11 @@ use core::cell::Cell;
use core::mem::{self, MaybeUninit}; use core::mem::{self, MaybeUninit};
use core::sync::atomic::{AtomicBool, Ordering}; use core::sync::atomic::{AtomicBool, Ordering};
use embassy_sync::blocking_mutex::CriticalSectionMutex;
use embassy_usb::control::{self, ControlHandler, InResponse, OutResponse, Request}; use embassy_usb::control::{self, ControlHandler, InResponse, OutResponse, Request};
use embassy_usb::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut}; use embassy_usb::driver::{Driver, Endpoint, EndpointError, EndpointIn, EndpointOut};
use embassy_usb::types::*; use embassy_usb::types::*;
use embassy_usb::Builder; use embassy_usb::Builder;
use embassy_util::blocking_mutex::CriticalSectionMutex;
/// This should be used as `device_class` when building the `UsbDevice`. /// This should be used as `device_class` when building the `UsbDevice`.
pub const USB_CLASS_CDC: u8 = 0x02; pub const USB_CLASS_CDC: u8 = 0x02;

View File

@ -10,7 +10,7 @@ features = ["defmt"]
target = "thumbv7em-none-eabi" target = "thumbv7em-none-eabi"
[dependencies] [dependencies]
embassy-util = { version = "0.1.0", path = "../embassy-util" } embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
defmt = { version = "0.3", optional = true } defmt = { version = "0.3", optional = true }
log = { version = "0.4.14", optional = true } log = { version = "0.4.14", optional = true }

View File

@ -10,6 +10,7 @@ use crate::{Interface, STRING_INDEX_CUSTOM_START};
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive] #[non_exhaustive]
/// Configuration used when creating [UsbDevice].
pub struct Config<'a> { pub struct Config<'a> {
pub(crate) vendor_id: u16, pub(crate) vendor_id: u16,
pub(crate) product_id: u16, pub(crate) product_id: u16,
@ -96,6 +97,7 @@ pub struct Config<'a> {
} }
impl<'a> Config<'a> { impl<'a> Config<'a> {
/// Create default configuration with the provided vid and pid values.
pub fn new(vid: u16, pid: u16) -> Self { pub fn new(vid: u16, pid: u16) -> Self {
Self { Self {
device_class: 0x00, device_class: 0x00,

View File

@ -1,3 +1,4 @@
//! USB control data types.
use core::mem; use core::mem;
use super::types::*; use super::types::*;
@ -8,7 +9,7 @@ use super::types::*;
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum RequestType { pub enum RequestType {
/// Request is a USB standard request. Usually handled by /// Request is a USB standard request. Usually handled by
/// [`UsbDevice`](crate::device::UsbDevice). /// [`UsbDevice`](crate::UsbDevice).
Standard = 0, Standard = 0,
/// Request is intended for a USB class. /// Request is intended for a USB class.
Class = 1, Class = 1,

View File

@ -12,7 +12,7 @@ pub trait Driver<'a> {
/// Allocates an endpoint and specified endpoint parameters. This method is called by the device /// Allocates an endpoint and specified endpoint parameters. This method is called by the device
/// and class implementations to allocate endpoints, and can only be called before /// and class implementations to allocate endpoints, and can only be called before
/// [`start`](UsbBus::start) is called. /// [`start`](Self::start) is called.
/// ///
/// # Arguments /// # Arguments
/// ///
@ -95,7 +95,7 @@ pub trait Bus {
/// ///
/// # Errors /// # Errors
/// ///
/// * [`Unsupported`](crate::UsbError::Unsupported) - This UsbBus implementation doesn't support /// * [`Unsupported`](crate::driver::Unsupported) - This UsbBus implementation doesn't support
/// simulating a disconnect or it has not been enabled at creation time. /// simulating a disconnect or it has not been enabled at creation time.
fn force_reset(&mut self) -> Result<(), Unsupported> { fn force_reset(&mut self) -> Result<(), Unsupported> {
Err(Unsupported) Err(Unsupported)
@ -105,7 +105,7 @@ pub trait Bus {
/// ///
/// # Errors /// # Errors
/// ///
/// * [`Unsupported`](crate::UsbError::Unsupported) - This UsbBus implementation doesn't support /// * [`Unsupported`](crate::driver::Unsupported) - This UsbBus implementation doesn't support
/// remote wakeup or it has not been enabled at creation time. /// remote wakeup or it has not been enabled at creation time.
fn remote_wakeup(&mut self) -> Self::RemoteWakeupFuture<'_>; fn remote_wakeup(&mut self) -> Self::RemoteWakeupFuture<'_>;
} }

View File

@ -12,7 +12,7 @@ mod descriptor_reader;
pub mod driver; pub mod driver;
pub mod types; pub mod types;
use embassy_util::{select, Either}; use embassy_futures::{select, Either};
use heapless::Vec; use heapless::Vec;
pub use self::builder::{Builder, Config}; pub use self::builder::{Builder, Config};

View File

@ -1,5 +0,0 @@
//! Async channels
pub mod mpmc;
pub mod pubsub;
pub mod signal;

View File

@ -1,95 +0,0 @@
use core::cell::UnsafeCell;
use core::mem::MaybeUninit;
use atomic_polyfill::{AtomicBool, Ordering};
/// Type with static lifetime that may be written to once at runtime.
///
/// This may be used to initialize static objects at runtime, typically in the init routine.
/// This is useful for objects such as Embassy's RTC, which cannot be initialized in a const
/// context.
///
/// Note: IF a global mutable variable is desired, use a CriticalSectionMutex or ThreadModeMutex instead.
///
/// ```
/// use embassy_util::Forever;
/// // Using an integer for the sake of keeping this example self-contained,
/// // see https://github.com/embassy-rs/embassy/wiki/Getting-Started for a more "proper" example.
/// static SOME_INT: Forever<u32> =Forever::new();
///
/// // put returns a mutable pointer to the object stored in the forever, which may then be passed
/// // around.
/// let mut x = SOME_INT.put(42);
/// assert_eq!(*x, 42);
/// ```
pub struct Forever<T> {
used: AtomicBool,
t: UnsafeCell<MaybeUninit<T>>,
}
unsafe impl<T> Send for Forever<T> {}
unsafe impl<T> Sync for Forever<T> {}
impl<T> Forever<T> {
/// Create a new `Forever`.
#[inline(always)]
pub const fn new() -> Self {
Self {
used: AtomicBool::new(false),
t: UnsafeCell::new(MaybeUninit::uninit()),
}
}
/// Store a value in this `Forever`, returning a mutable reference to it.
///
/// Using this method, the compiler usually constructs `val` in the stack and then moves
/// it into the `Forever`. If `T` is big, this is likely to cause stack overflows.
/// Considering using [`Signal::put_with`] instead, which will construct it in-place inside the `Forever`.
///
/// # Panics
///
/// Panics if this `Forever` already has a value stored in it.
#[inline(always)]
#[allow(clippy::mut_from_ref)]
pub fn put(&'static self, val: T) -> &'static mut T {
self.put_with(|| val)
}
/// Store the closure return value in this `Forever`, returning a mutable reference to it.
///
/// The advantage over [`Forever::put`] is that this method allows the closure to construct
/// the `T` value in-place directly inside the `Forever`, saving stack space.
///
/// # Panics
///
/// Panics if this `Forever` already has a value stored in it.
#[inline(always)]
#[allow(clippy::mut_from_ref)]
pub fn put_with(&'static self, val: impl FnOnce() -> T) -> &'static mut T {
if self
.used
.compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
.is_err()
{
panic!("Forever.put() called multiple times");
}
let p: &'static mut MaybeUninit<T> = unsafe { &mut *self.t.get() };
p.write(val())
}
/// Unsafely get a mutable reference to the contents of this Forever.
///
/// # Safety
///
/// This is undefined behavior if:
///
/// - The `Forever` has not been initialized yet (with `put' or `put_with`), or
/// - A reference to the contents (mutable or not) already exists.
#[inline(always)]
#[allow(clippy::mut_from_ref)]
pub unsafe fn steal(&self) -> &mut T {
let p: &mut MaybeUninit<T> = &mut *self.t.get();
p.assume_init_mut()
}
}

View File

@ -4,7 +4,7 @@ name = "embassy-boot-nrf-examples"
version = "0.1.0" version = "0.1.0"
[dependencies] [dependencies]
embassy-util = { version = "0.1.0", path = "../../../../embassy-util" } embassy-sync = { version = "0.1.0", path = "../../../../embassy-sync" }
embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["nightly", "integrated-timers"] } embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["nightly", "integrated-timers"] }
embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly"] } embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly"] }
embassy-nrf = { version = "0.1.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", "nightly", "nrf52840"] } embassy-nrf = { version = "0.1.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", "nightly", "nrf52840"] }

View File

@ -4,7 +4,7 @@ name = "embassy-boot-stm32f3-examples"
version = "0.1.0" version = "0.1.0"
[dependencies] [dependencies]
embassy-util = { version = "0.1.0", path = "../../../../embassy-util", features = ["defmt"] } embassy-sync = { version = "0.1.0", path = "../../../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["nightly", "integrated-timers"] } embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["nightly", "integrated-timers"] }
embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-32768hz"] } embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-32768hz"] }
embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32f303re", "time-driver-any", "exti"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32f303re", "time-driver-any", "exti"] }

View File

@ -4,7 +4,7 @@ name = "embassy-boot-stm32f7-examples"
version = "0.1.0" version = "0.1.0"
[dependencies] [dependencies]
embassy-util = { version = "0.1.0", path = "../../../../embassy-util", features = ["defmt"] } embassy-sync = { version = "0.1.0", path = "../../../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["nightly", "integrated-timers"] } embassy-executor = { version = "0.1.0", path = "../../../../embassy-executor", features = ["nightly", "integrated-timers"] }
embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-32768hz"] } embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-32768hz"] }
embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32f767zi", "time-driver-any", "exti"] } embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32f767zi", "time-driver-any", "exti"] }

Some files were not shown because too many files have changed in this diff Show More