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:
- uses: actions/checkout@v2
- name: Test
run: cd embassy-util && cargo test
run: cd embassy-sync && cargo test

View File

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

View File

@ -14,7 +14,7 @@ target = "thumbv7em-none-eabi"
[dependencies]
defmt = { version = "0.3", 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-async = "0.3.0"

View File

@ -15,7 +15,7 @@ target = "thumbv7em-none-eabi"
[dependencies]
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-boot = { path = "../boot", default-features = false }
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 }
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-boot = { path = "../boot", default-features = false }
cortex-m = { version = "0.7.6" }

View File

@ -35,7 +35,7 @@ prio-bits-8 = []
defmt = { version = "0.3", 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-macros = { version = "0.1.0", path = "../embassy-macros"}
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
/// 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 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 {

View File

@ -16,7 +16,7 @@ std = []
nightly = ["embedded-hal-async", "embedded-storage-async"]
[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-1 = { package = "embedded-hal", version = "1.0.0-alpha.8" }
embedded-hal-async = { version = "0.1.0-alpha.1", optional = true }

View File

@ -4,15 +4,15 @@
//!
//! ```rust
//! use embassy_embedded_hal::shared_bus::i2c::I2cDevice;
//! use embassy_util::mutex::Mutex;
//! use embassy_util::blocking_mutex::raw::ThreadModeRawMutex;
//! use embassy_sync::mutex::Mutex;
//! 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 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_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
//! let i2c_dev1 = I2cDevice::new(i2c_bus);
@ -24,8 +24,8 @@
//! ```
use core::future::Future;
use embassy_util::blocking_mutex::raw::RawMutex;
use embassy_util::mutex::Mutex;
use embassy_sync::blocking_mutex::raw::RawMutex;
use embassy_sync::mutex::Mutex;
use embedded_hal_async::i2c;
use crate::shared_bus::I2cDeviceError;

View File

@ -4,16 +4,16 @@
//!
//! ```rust
//! use embassy_embedded_hal::shared_bus::spi::SpiDevice;
//! use embassy_util::mutex::Mutex;
//! use embassy_util::blocking_mutex::raw::ThreadModeRawMutex;
//! use embassy_sync::mutex::Mutex;
//! 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();
//! config.frequency = spim::Frequency::M32;
//! let irq = interrupt::take!(SPIM3);
//! 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 = 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
//! let cs_pin1 = Output::new(p.P0_24, Level::Low, OutputDrive::Standard);
@ -27,8 +27,8 @@
//! ```
use core::future::Future;
use embassy_util::blocking_mutex::raw::RawMutex;
use embassy_util::mutex::Mutex;
use embassy_sync::blocking_mutex::raw::RawMutex;
use embassy_sync::mutex::Mutex;
use embedded_hal_1::digital::blocking::OutputPin;
use embedded_hal_1::spi::ErrorType;
use embedded_hal_async::spi;

View File

@ -4,13 +4,13 @@
//!
//! ```rust
//! 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 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 = I2C_BUS.put(i2c_bus);
//! let i2c_bus = I2C_BUS.init(i2c_bus);
//!
//! let i2c_dev1 = I2cDevice::new(i2c_bus);
//! let mpu = Mpu6050::new(i2c_dev1);
@ -18,8 +18,8 @@
use core::cell::RefCell;
use embassy_util::blocking_mutex::raw::RawMutex;
use embassy_util::blocking_mutex::Mutex;
use embassy_sync::blocking_mutex::raw::RawMutex;
use embassy_sync::blocking_mutex::Mutex;
use embedded_hal_1::i2c::blocking::{I2c, Operation};
use embedded_hal_1::i2c::ErrorType;

View File

@ -4,13 +4,13 @@
//!
//! ```rust
//! 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 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 = SPI_BUS.put(spi_bus);
//! let spi_bus = SPI_BUS.init(spi_bus);
//!
//! // Device 1, using embedded-hal compatible driver for ST7735 LCD display
//! let cs_pin1 = Output::new(p.P0_24, Level::Low, OutputDrive::Standard);
@ -20,8 +20,8 @@
use core::cell::RefCell;
use embassy_util::blocking_mutex::raw::RawMutex;
use embassy_util::blocking_mutex::Mutex;
use embassy_sync::blocking_mutex::raw::RawMutex;
use embassy_sync::blocking_mutex::Mutex;
use embedded_hal_1::digital::blocking::OutputPin;
use embedded_hal_1::spi;
use embedded_hal_1::spi::blocking::SpiBusFlush;

View File

@ -30,9 +30,13 @@ nightly = []
integrated-timers = ["dep:embassy-time"]
# Trace interrupt invocations with rtos-trace.
rtos-trace-interrupt = ["rtos-trace"]
[dependencies]
defmt = { version = "0.3", 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 }
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"
critical-section = "1.1"
cfg-if = "1.0.0"
static_cell = "1.0"
# WASM dependencies
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
/// 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 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
/// 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 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
/// 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 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
/// 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 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)) {

View File

@ -43,7 +43,7 @@ impl Executor {
/// Executor instance in a place where it'll live forever and grants you mutable
/// 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 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;
mod 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!
//!
//! 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;
#[cfg(feature = "integrated-timers")]
@ -26,6 +26,8 @@ use critical_section::CriticalSection;
use embassy_time::driver::{self, AlarmHandle};
#[cfg(feature = "integrated-timers")]
use embassy_time::Instant;
#[cfg(feature = "rtos-trace")]
use rtos_trace::trace;
use self::run_queue::{RunQueue, RunQueueItem};
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
/// 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:
///
@ -306,6 +308,9 @@ impl Executor {
/// - `task` must NOT be already enqueued (in this executor or another one).
#[inline(always)]
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) {
(self.signal_fn)(self.signal_ctx)
}
@ -323,6 +328,9 @@ impl Executor {
pub(super) unsafe fn spawn(&'static self, task: NonNull<TaskHeader>) {
task.as_ref().executor.set(self);
#[cfg(feature = "rtos-trace")]
trace::task_new(task.as_ptr() as u32);
critical_section::with(|cs| {
self.enqueue(cs, task);
})
@ -365,9 +373,15 @@ impl Executor {
return;
}
#[cfg(feature = "rtos-trace")]
trace::task_exec_begin(p.as_ptr() as u32);
// Run the task
task.poll_fn.read()(p as _);
#[cfg(feature = "rtos-trace")]
trace::task_exec_end();
// Enqueue or update into timer_queue
#[cfg(feature = "integrated-timers")]
self.timer_queue.update(p);
@ -381,6 +395,9 @@ impl Executor {
let next_expiration = self.timer_queue.next_expiration();
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.
@ -426,3 +443,21 @@ unsafe fn _embassy_time_schedule_wake(at: Instant, waker: &core::task::Waker) {
let expires_at = task.expires_at.get();
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 }
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 }
embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.8" }
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,
};
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::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 ctx = HANDLER.ctx.load(interrupt::_export::atomic::Ordering::Relaxed);
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);

View File

@ -34,8 +34,8 @@ pub fn run(args: syn::AttributeArgs, f: syn::ItemFn) -> Result<TokenStream, Toke
let main = quote! {
#[wasm_bindgen::prelude::wasm_bindgen(start)]
pub fn main() -> Result<(), wasm_bindgen::JsValue> {
static EXECUTOR: ::embassy_util::Forever<::embassy_executor::Executor> = ::embassy_util::Forever::new();
let executor = EXECUTOR.put(::embassy_executor::Executor::new());
static EXECUTOR: ::embassy_executor::_export::StaticCell<::embassy_executor::Executor> = ::embassy_executor::_export::StaticCell::new();
let executor = EXECUTOR.init(::embassy_executor::Executor::new());
executor.start(|spawner| {
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 }
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" ] }
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::task::{Context, Poll};
use embassy_sync::waitqueue::WakerRegistration;
use embassy_time::{Instant, Timer};
use embassy_util::waitqueue::WakerRegistration;
use futures::future::poll_fn;
use futures::pin_mut;
use heapless::Vec;

View File

@ -18,7 +18,7 @@ flavors = [
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
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]
embassy-executor = { version = "0.1.0", path = "../embassy-executor", 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-hal-common = {version = "0.1.0", path = "../embassy-hal-common" }
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_hal_common::ring_buffer::RingBuffer;
use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_util::waitqueue::WakerRegistration;
use embassy_sync::waitqueue::WakerRegistration;
use futures::future::poll_fn;
// 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};
@ -45,8 +45,10 @@ enum TxState {
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>>);
impl<'d, U: UarteInstance, T: TimerInstance> State<'d, U, T> {
/// Create an instance for storing UARTE peripheral state.
pub fn new() -> Self {
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> 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(
state: &'d mut State<'d, U, T>,
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) {
self.inner.with(|state| {
let r = U::regs();

View File

@ -1,3 +1,4 @@
//! General purpose input/output for nRF.
#![macro_use]
use core::convert::Infallible;
@ -26,8 +27,11 @@ pub enum Port {
#[derive(Debug, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Pull {
/// No pull.
None,
/// Internal pull-up resistor.
Up,
/// Internal pull-down resistor.
Down,
}
@ -37,6 +41,7 @@ pub struct Input<'d, T: Pin> {
}
impl<'d, T: Pin> Input<'d, T> {
/// Create GPIO input driver for a [Pin] with the provided [Pull] configuration.
#[inline]
pub fn new(pin: impl Peripheral<P = T> + 'd, pull: Pull) -> Self {
let mut pin = Flex::new(pin);
@ -45,11 +50,13 @@ impl<'d, T: Pin> Input<'d, T> {
Self { pin }
}
/// Test if current pin level is high.
#[inline]
pub fn is_high(&self) -> bool {
self.pin.is_high()
}
/// Test if current pin level is low.
#[inline]
pub fn is_low(&self) -> bool {
self.pin.is_low()
@ -66,7 +73,9 @@ impl<'d, T: Pin> Input<'d, T> {
#[derive(Debug, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Level {
/// Logical low.
Low,
/// Logical 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.
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@ -117,6 +127,7 @@ pub struct Output<'d, T: Pin> {
}
impl<'d, T: Pin> Output<'d, T> {
/// Create GPIO output driver for a [Pin] with the provided [Level] and [OutputDriver] configuration.
#[inline]
pub fn new(pin: impl Peripheral<P = T> + 'd, initial_output: Level, drive: OutputDrive) -> Self {
let mut pin = Flex::new(pin);
@ -264,11 +275,13 @@ impl<'d, T: Pin> Flex<'d, T> {
self.pin.conf().reset();
}
/// Test if current pin level is high.
#[inline]
pub fn is_high(&self) -> bool {
!self.is_low()
}
/// Test if current pin level is low.
#[inline]
pub fn is_low(&self) -> bool {
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 {
/// Number of the pin within the port (0..31)
#[inline]
@ -392,6 +406,7 @@ pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'stat
}
}
/// Peripheral port register value
#[inline]
fn psel_bits(&self) -> 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 {
pin_port: u8,
}
impl AnyPin {
/// Create an [AnyPin] for a specific pin.
///
/// # Safety
/// - `pin_port` should not in use by another driver.
#[inline]
pub unsafe fn steal(pin_port: u8) -> Self {
Self { pin_port }

View File

@ -3,7 +3,7 @@ use core::future::Future;
use core::task::{Context, Poll};
use embassy_hal_common::{impl_peripheral, Peripheral, PeripheralRef};
use embassy_util::waitqueue::AtomicWaker;
use embassy_sync::waitqueue::AtomicWaker;
use futures::future::poll_fn;
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};
@ -10,13 +10,19 @@ use embedded_storage::nor_flash::{
use crate::peripherals::NVMC;
use crate::{pac, Peripheral};
/// Erase size of NVMC flash in bytes.
pub const PAGE_SIZE: usize = 4096;
/// Size of NVMC flash in bytes.
pub const FLASH_SIZE: usize = crate::chip::FLASH_SIZE;
/// Error type for NVMC operations.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error {
/// Opration using a location not in flash.
OutOfBounds,
/// Unaligned operation or using unaligned buffers.
Unaligned,
}
@ -29,11 +35,13 @@ impl NorFlashError for Error {
}
}
/// Non-Volatile Memory Controller (NVMC) that implements the `embedded-storage` traits.
pub struct Nvmc<'d> {
_p: PeripheralRef<'d, NVMC>,
}
impl<'d> Nvmc<'d> {
/// Create Nvmc driver.
pub fn new(_p: impl Peripheral<P = NVMC> + 'd) -> Self {
into_ref!(_p);
Self { _p }

View File

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

View File

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

View File

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

View File

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

View File

@ -4,7 +4,7 @@ use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll;
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 pac::{saadc, SAADC};
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 {
use embassy_util::waitqueue::AtomicWaker;
use embassy_sync::waitqueue::AtomicWaker;
use super::*;

View File

@ -4,7 +4,7 @@ use core::task::Poll;
use embassy_hal_common::drop::OnDrop;
use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_util::waitqueue::AtomicWaker;
use embassy_sync::waitqueue::AtomicWaker;
use fixed::types::I30F2;
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 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_util::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_util::blocking_mutex::CriticalSectionMutex as Mutex;
use crate::interrupt::{Interrupt, InterruptExt};
use crate::{interrupt, pac};

View File

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

View File

@ -13,9 +13,9 @@ use core::task::Poll;
use embassy_embedded_hal::SetConfig;
use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_sync::waitqueue::AtomicWaker;
#[cfg(feature = "time")]
use embassy_time::{Duration, Instant};
use embassy_util::waitqueue::AtomicWaker;
use futures::future::poll_fn;
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 {
use core::sync::atomic::AtomicU8;
use embassy_util::waitqueue::AtomicWaker;
use embassy_sync::waitqueue::AtomicWaker;
use super::*;

View File

@ -7,10 +7,10 @@ use core::task::Poll;
use cortex_m::peripheral::NVIC;
use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_sync::waitqueue::AtomicWaker;
pub use embassy_usb;
use embassy_usb::driver::{self, EndpointError, Event, Unsupported};
use embassy_usb::types::{EndpointAddress, EndpointInfo, EndpointType, UsbDirection};
use embassy_util::waitqueue::AtomicWaker;
use futures::future::poll_fn;
use futures::Future;
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"]
[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-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-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" }
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_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::SIO;
@ -189,7 +189,7 @@ impl<'d, T: Pin> InputFuture<'d, T> {
unsafe {
let irq = interrupt::IO_IRQ_BANK0::steal();
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
// 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 critical_section::CriticalSection;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::blocking_mutex::Mutex;
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, pac};

View File

@ -31,7 +31,7 @@ flavors = [
]
[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-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"]}
@ -72,7 +72,7 @@ quote = "1.0.15"
stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", default-features = false, features = ["metadata"]}
[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"]
net = ["embassy-net" ]
memory-x = ["stm32-metapac/memory-x"]

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
use core::sync::atomic::{fence, Ordering};
use core::task::Waker;
use embassy_util::waitqueue::AtomicWaker;
use embassy_sync::waitqueue::AtomicWaker;
use super::{Request, TransferOptions, Word, WordSize};
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_hal_common::{into_ref, PeripheralRef};
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::{AnyPin, Speed};

View File

@ -5,7 +5,7 @@ use core::task::Waker;
use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage};
use embassy_hal_common::{into_ref, PeripheralRef};
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::{AnyPin, Speed};

View File

@ -4,7 +4,7 @@ use core::pin::Pin;
use core::task::{Context, Poll};
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::pac::exti::regs::Lines;

View File

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

View File

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

View File

@ -4,10 +4,10 @@ use core::sync::atomic::{compiler_fence, Ordering};
use core::{mem, ptr};
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::TICKS_PER_SECOND;
use embassy_util::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_util::blocking_mutex::Mutex;
use stm32_metapac::timer::regs;
use crate::interrupt::{CriticalSection, InterruptExt};

View File

@ -4,19 +4,19 @@ use core::task::Poll;
use atomic_polyfill::{compiler_fence, Ordering};
use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage};
use embassy_hal_common::ring_buffer::RingBuffer;
use embassy_util::waitqueue::WakerRegistration;
use embassy_sync::waitqueue::WakerRegistration;
use futures::future::poll_fn;
use super::*;
pub struct State<'d, T: Instance>(StateStorage<StateInner<'d, T>>);
impl<'d, T: Instance> State<'d, T> {
pub struct State<'d, T: BasicInstance>(StateStorage<StateInner<'d, T>>);
impl<'d, T: BasicInstance> State<'d, T> {
pub fn new() -> Self {
Self(StateStorage::new())
}
}
struct StateInner<'d, T: Instance> {
struct StateInner<'d, T: BasicInstance> {
phantom: PhantomData<&'d mut T>,
rx_waker: WakerRegistration,
@ -26,16 +26,16 @@ struct StateInner<'d, T: Instance> {
tx: RingBuffer<'d>,
}
unsafe impl<'d, T: Instance> Send for StateInner<'d, T> {}
unsafe impl<'d, T: Instance> Sync for StateInner<'d, T> {}
unsafe impl<'d, T: BasicInstance> Send 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>>,
}
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(
state: &'d mut State<'d, T>,
_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
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
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;
}
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>>
where
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>>
where
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>>
where
Self: 'a;

View File

@ -6,9 +6,10 @@ use embassy_hal_common::{into_ref, PeripheralRef};
use crate::dma::NoDma;
use crate::gpio::sealed::AFType;
use crate::interrupt::Interrupt;
use crate::pac::usart::{regs, vals};
use crate::rcc::RccPeripheral;
#[cfg(any(lpuart_v1, lpuart_v2))]
use crate::pac::lpuart::{regs, vals, Lpuart as Regs};
#[cfg(not(any(lpuart_v1, lpuart_v2)))]
use crate::pac::usart::{regs, vals, Usart as Regs};
use crate::{peripherals, Peripheral};
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
@ -71,22 +72,23 @@ pub enum Error {
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>,
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>,
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>,
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 {
Self {
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 {
Self {
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(
_inner: impl Peripheral<P = 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();
// 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();
@ -235,6 +237,7 @@ impl<'d, T: Instance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
Self {
tx: UartTx::new(tx_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 {
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;
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
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;
fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
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;
fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
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;
fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
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;
}
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;
}
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;
}
}
@ -362,7 +365,7 @@ cfg_if::cfg_if! {
if #[cfg(all(feature = "unstable-traits", feature = "nightly", feature = "_todo_embedded_hal_serial"))] {
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
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
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
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
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)]
#[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.
}
#[cfg(usart_v2)]
fn tdr(r: crate::pac::usart::Usart) -> *mut u8 {
fn tdr(r: Regs) -> *mut u8 {
r.tdr().ptr() as _
}
#[cfg(usart_v2)]
fn rdr(r: crate::pac::usart::Usart) -> *mut u8 {
fn rdr(r: Regs) -> *mut u8 {
r.rdr().ptr() as _
}
#[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()
}
#[cfg(usart_v2)]
#[allow(unused)]
unsafe fn clear_interrupt_flags(r: crate::pac::usart::Usart, sr: regs::Ixr) {
r.icr().write(|w| *w = sr);
unsafe fn clear_interrupt_flags(r: Regs, sr: regs::Isr) {
r.icr().write(|w| *w = regs::Icr(sr.0));
}
pub(crate) mod sealed {
pub trait Instance {
fn regs() -> crate::pac::usart::Usart;
use super::*;
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 {
type Interrupt: Interrupt;
pub trait BasicInstance: sealed::BasicInstance {}
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);
pin_trait!(TxPin, Instance);
pin_trait!(CtsPin, Instance);
pin_trait!(RtsPin, Instance);
pin_trait!(CkPin, Instance);
dma_trait!(TxDma, Instance);
dma_trait!(RxDma, Instance);
impl BasicInstance for peripherals::$inst {}
};
}
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) => {
impl sealed::Instance for peripherals::$inst {
fn regs() -> crate::pac::usart::Usart {
impl_lpuart!($inst, $irq, 1);
impl sealed::FullInstance for peripherals::$inst {
fn regs_uart() -> crate::pac::usart::Usart {
crate::pac::$inst
}
}
impl Instance for peripherals::$inst {
type Interrupt = crate::interrupt::$irq;
impl FullInstance for peripherals::$inst {
}
};
);

View File

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

View File

@ -1,11 +1,11 @@
[package]
name = "embassy-util"
name = "embassy-sync"
version = "0.1.0"
edition = "2021"
[package.metadata.embassy_docs]
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-util-v$VERSION/embassy-util/src/"
src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/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-sync/src/"
features = ["nightly"]
target = "thumbv7em-none-eabi"
@ -31,3 +31,4 @@ futures-util = { version = "0.3.17", features = [ "channel" ] }
# Enable critical-section implementation for std, for tests
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:
///
/// ```
/// use embassy_util::channel::mpmc::Channel;
/// use embassy_util::blocking_mutex::raw::NoopRawMutex;
/// use embassy_sync::channel::Channel;
/// use embassy_sync::blocking_mutex::raw::NoopRawMutex;
///
/// // Declare a bounded channel of 3 u32s.
/// let mut channel = Channel::<NoopRawMutex, u32, 3>::new();
@ -471,10 +471,10 @@ mod tests {
use futures_executor::ThreadPool;
use futures_timer::Delay;
use futures_util::task::SpawnExt;
use static_cell::StaticCell;
use super::*;
use crate::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex};
use crate::Forever;
fn capacity<T, const N: usize>(c: &ChannelState<T, N>) -> usize {
c.queue.capacity() - c.queue.len()
@ -549,8 +549,8 @@ mod tests {
async fn receiver_receives_given_try_send_async() {
let executor = ThreadPool::new().unwrap();
static CHANNEL: Forever<Channel<CriticalSectionRawMutex, u32, 3>> = Forever::new();
let c = &*CHANNEL.put(Channel::new());
static CHANNEL: StaticCell<Channel<CriticalSectionRawMutex, u32, 3>> = StaticCell::new();
let c = &*CHANNEL.init(Channel::new());
let c2 = c;
assert!(executor
.spawn(async move {
@ -571,8 +571,8 @@ mod tests {
async fn senders_sends_wait_until_capacity() {
let executor = ThreadPool::new().unwrap();
static CHANNEL: Forever<Channel<CriticalSectionRawMutex, u32, 1>> = Forever::new();
let c = &*CHANNEL.put(Channel::new());
static CHANNEL: StaticCell<Channel<CriticalSectionRawMutex, u32, 1>> = StaticCell::new();
let c = &*CHANNEL.init(Channel::new());
assert!(c.try_send(1).is_ok());
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 mutex;
pub mod pipe;
pub mod pubsub;
pub mod signal;
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:
///
/// ```
/// use embassy_util::pipe::Pipe;
/// use embassy_util::blocking_mutex::raw::NoopRawMutex;
/// use embassy_sync::pipe::Pipe;
/// use embassy_sync::blocking_mutex::raw::NoopRawMutex;
///
/// // Declare a bounded pipe, with a buffer of 256 bytes.
/// let mut pipe = Pipe::<NoopRawMutex, 256>::new();
@ -461,10 +461,10 @@ mod io_impls {
mod tests {
use futures_executor::ThreadPool;
use futures_util::task::SpawnExt;
use static_cell::StaticCell;
use super::*;
use crate::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex};
use crate::Forever;
fn capacity<const N: usize>(c: &PipeState<N>) -> usize {
N - c.buffer.len()
@ -528,8 +528,8 @@ mod tests {
async fn receiver_receives_given_try_write_async() {
let executor = ThreadPool::new().unwrap();
static CHANNEL: Forever<Pipe<CriticalSectionRawMutex, 3>> = Forever::new();
let c = &*CHANNEL.put(Pipe::new());
static CHANNEL: StaticCell<Pipe<CriticalSectionRawMutex, 3>> = StaticCell::new();
let c = &*CHANNEL.init(Pipe::new());
let c2 = c;
let f = async move {
assert_eq!(c2.try_write(&[42]), Ok(1));

View File

@ -33,9 +33,9 @@ pub use subscriber::{DynSubscriber, Subscriber};
/// ## Example
///
/// ```
/// # use embassy_util::blocking_mutex::raw::NoopRawMutex;
/// # use embassy_util::channel::pubsub::WaitResult;
/// # use embassy_util::channel::pubsub::PubSubChannel;
/// # use embassy_sync::blocking_mutex::raw::NoopRawMutex;
/// # use embassy_sync::pubsub::WaitResult;
/// # use embassy_sync::pubsub::PubSubChannel;
/// # use futures_executor::block_on;
/// # let test = async {
/// // 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.
///
/// ```
/// use embassy_util::channel::signal::Signal;
/// use embassy_sync::signal::Signal;
///
/// enum SomeCommand {
/// On,

View File

@ -6,7 +6,7 @@
//!
//! - Define a struct `MyDriver`
//! - 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
//! tick rate of your driver.
//!

View File

@ -14,7 +14,7 @@ default = ["usbd-hid"]
usbd-hid = ["dep:usbd-hid", "ssmarshal"]
[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" }
defmt = { version = "0.3", optional = true }

View File

@ -10,7 +10,7 @@ features = ["defmt"]
target = "thumbv7em-none-eabi"
[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" }
defmt = { version = "0.3", optional = true }

View File

@ -10,7 +10,7 @@ features = ["defmt"]
target = "thumbv7em-none-eabi"
[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" }
defmt = { version = "0.3", optional = true }

View File

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

View File

@ -10,7 +10,7 @@ features = ["defmt"]
target = "thumbv7em-none-eabi"
[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 }
log = { version = "0.4.14", optional = true }

View File

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

View File

@ -1,3 +1,4 @@
//! USB control data types.
use core::mem;
use super::types::*;
@ -8,7 +9,7 @@ use super::types::*;
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum RequestType {
/// Request is a USB standard request. Usually handled by
/// [`UsbDevice`](crate::device::UsbDevice).
/// [`UsbDevice`](crate::UsbDevice).
Standard = 0,
/// Request is intended for a USB class.
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
/// and class implementations to allocate endpoints, and can only be called before
/// [`start`](UsbBus::start) is called.
/// [`start`](Self::start) is called.
///
/// # Arguments
///
@ -95,7 +95,7 @@ pub trait Bus {
///
/// # 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.
fn force_reset(&mut self) -> Result<(), Unsupported> {
Err(Unsupported)
@ -105,7 +105,7 @@ pub trait Bus {
///
/// # 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.
fn remote_wakeup(&mut self) -> Self::RemoteWakeupFuture<'_>;
}

View File

@ -12,7 +12,7 @@ mod descriptor_reader;
pub mod driver;
pub mod types;
use embassy_util::{select, Either};
use embassy_futures::{select, Either};
use heapless::Vec;
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"
[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-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"] }

View File

@ -4,7 +4,7 @@ name = "embassy-boot-stm32f3-examples"
version = "0.1.0"
[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-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"] }

View File

@ -4,7 +4,7 @@ name = "embassy-boot-stm32f7-examples"
version = "0.1.0"
[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-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"] }

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