Merge #1321
1321: executor: add Pender, rework Cargo features. r=Dirbaio a=Dirbaio This introduces a `Pender` struct with enum cases for thread-mode, interrupt-mode and custom callback executors. This avoids calls through function pointers when using only the thread or interrupt executors. Faster, and friendlier to `cargo-call-stack`. `embassy-executor` now has `arch-xxx` Cargo features to select the arch and to enable the builtin executors (thread and interrupt). Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
This commit is contained in:
commit
5923e143e3
@ -6,7 +6,7 @@ version = "0.1.0"
|
|||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-executor = { version = "0.1.0", path = "../../../../../embassy-executor", features = ["defmt", "nightly", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../../../../embassy-executor", features = ["defmt", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../../../../embassy-time", features = ["defmt", "nightly"] }
|
embassy-time = { version = "0.1.0", path = "../../../../../embassy-time", features = ["defmt", "nightly"] }
|
||||||
embassy-nrf = { version = "0.1.0", path = "../../../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "nightly"] }
|
embassy-nrf = { version = "0.1.0", path = "../../../../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "nightly"] }
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
cortex-m = "0.7"
|
cortex-m = "0.7"
|
||||||
cortex-m-rt = "0.7"
|
cortex-m-rt = "0.7"
|
||||||
embassy-stm32 = { version = "0.1.0", features = ["stm32l475vg", "memory-x", "exti"], default-features = false }
|
embassy-stm32 = { version = "0.1.0", features = ["stm32l475vg", "memory-x", "exti"], default-features = false }
|
||||||
embassy-executor = { version = "0.1.0", default-features = false, features = ["nightly"] }
|
embassy-executor = { version = "0.1.0", default-features = false, features = ["nightly", "arch-cortex-m", "executor-thread"] }
|
||||||
|
|
||||||
defmt = "0.3.0"
|
defmt = "0.3.0"
|
||||||
defmt-rtt = "0.3.0"
|
defmt-rtt = "0.3.0"
|
||||||
|
@ -1,116 +0,0 @@
|
|||||||
//! Executor specific to cortex-m devices.
|
|
||||||
|
|
||||||
use core::cell::UnsafeCell;
|
|
||||||
use core::mem::MaybeUninit;
|
|
||||||
|
|
||||||
use atomic_polyfill::{AtomicBool, Ordering};
|
|
||||||
use cortex_m::interrupt::InterruptNumber;
|
|
||||||
use cortex_m::peripheral::NVIC;
|
|
||||||
pub use embassy_executor::*;
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
|
||||||
struct N(u16);
|
|
||||||
unsafe impl cortex_m::interrupt::InterruptNumber for N {
|
|
||||||
fn number(self) -> u16 {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pend_by_number(n: u16) {
|
|
||||||
cortex_m::peripheral::NVIC::pend(N(n))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Interrupt mode executor.
|
|
||||||
///
|
|
||||||
/// This executor runs tasks in interrupt mode. The interrupt handler is set up
|
|
||||||
/// to poll tasks, and when a task is woken the interrupt is pended from software.
|
|
||||||
///
|
|
||||||
/// This allows running async tasks at a priority higher than thread mode. One
|
|
||||||
/// use case is to leave thread mode free for non-async tasks. Another use case is
|
|
||||||
/// to run multiple executors: one in thread mode for low priority tasks and another in
|
|
||||||
/// interrupt mode for higher priority tasks. Higher priority tasks will preempt lower
|
|
||||||
/// priority ones.
|
|
||||||
///
|
|
||||||
/// It is even possible to run multiple interrupt mode executors at different priorities,
|
|
||||||
/// by assigning different priorities to the interrupts. For an example on how to do this,
|
|
||||||
/// See the 'multiprio' example for 'embassy-nrf'.
|
|
||||||
///
|
|
||||||
/// To use it, you have to pick an interrupt that won't be used by the hardware.
|
|
||||||
/// Some chips reserve some interrupts for this purpose, sometimes named "software interrupts" (SWI).
|
|
||||||
/// If this is not the case, you may use an interrupt from any unused peripheral.
|
|
||||||
///
|
|
||||||
/// It is somewhat more complex to use, it's recommended to use the thread-mode
|
|
||||||
/// [`Executor`] instead, if it works for your use case.
|
|
||||||
pub struct InterruptExecutor {
|
|
||||||
started: AtomicBool,
|
|
||||||
executor: UnsafeCell<MaybeUninit<raw::Executor>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl Send for InterruptExecutor {}
|
|
||||||
unsafe impl Sync for InterruptExecutor {}
|
|
||||||
|
|
||||||
impl InterruptExecutor {
|
|
||||||
/// Create a new, not started `InterruptExecutor`.
|
|
||||||
#[inline]
|
|
||||||
pub const fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
started: AtomicBool::new(false),
|
|
||||||
executor: UnsafeCell::new(MaybeUninit::uninit()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Executor interrupt callback.
|
|
||||||
///
|
|
||||||
/// # Safety
|
|
||||||
///
|
|
||||||
/// You MUST call this from the interrupt handler, and from nowhere else.
|
|
||||||
pub unsafe fn on_interrupt(&'static self) {
|
|
||||||
let executor = unsafe { (&*self.executor.get()).assume_init_ref() };
|
|
||||||
executor.poll();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Start the executor.
|
|
||||||
///
|
|
||||||
/// This initializes the executor, enables the interrupt, and returns.
|
|
||||||
/// The executor keeps running in the background through the interrupt.
|
|
||||||
///
|
|
||||||
/// This returns a [`SendSpawner`] you can use to spawn tasks on it. A [`SendSpawner`]
|
|
||||||
/// is returned instead of a [`Spawner`](embassy_executor::Spawner) because the executor effectively runs in a
|
|
||||||
/// different "thread" (the interrupt), so spawning tasks on it is effectively
|
|
||||||
/// sending them.
|
|
||||||
///
|
|
||||||
/// To obtain a [`Spawner`](embassy_executor::Spawner) for this executor, use [`Spawner::for_current_executor()`](embassy_executor::Spawner::for_current_executor()) from
|
|
||||||
/// a task running in it.
|
|
||||||
///
|
|
||||||
/// # Interrupt requirements
|
|
||||||
///
|
|
||||||
/// You must write the interrupt handler yourself, and make it call [`on_interrupt()`](Self::on_interrupt).
|
|
||||||
///
|
|
||||||
/// This method already enables (unmasks) the interrupt, you must NOT do it yourself.
|
|
||||||
///
|
|
||||||
/// You must set the interrupt priority before calling this method. You MUST NOT
|
|
||||||
/// do it after.
|
|
||||||
///
|
|
||||||
pub fn start(&'static self, irq: impl InterruptNumber) -> SendSpawner {
|
|
||||||
if self
|
|
||||||
.started
|
|
||||||
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
|
|
||||||
.is_err()
|
|
||||||
{
|
|
||||||
panic!("InterruptExecutor::start() called multiple times on the same executor.");
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
(&mut *self.executor.get()).as_mut_ptr().write(raw::Executor::new(
|
|
||||||
|ctx| pend_by_number(ctx as u16),
|
|
||||||
irq.number() as *mut (),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
let executor = unsafe { (&*self.executor.get()).assume_init_ref() };
|
|
||||||
|
|
||||||
unsafe { NVIC::unmask(irq) }
|
|
||||||
|
|
||||||
executor.spawner().make_send()
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,6 +5,6 @@
|
|||||||
// This mod MUST go first, so that the others see its macros.
|
// This mod MUST go first, so that the others see its macros.
|
||||||
pub(crate) mod fmt;
|
pub(crate) mod fmt;
|
||||||
|
|
||||||
pub mod executor;
|
pub use embassy_executor as executor;
|
||||||
pub mod interrupt;
|
pub mod interrupt;
|
||||||
pub mod peripheral;
|
pub mod peripheral;
|
||||||
|
@ -31,9 +31,22 @@ flavors = [
|
|||||||
features = ["std", "nightly", "defmt"]
|
features = ["std", "nightly", "defmt"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
|
||||||
std = ["critical-section/std"]
|
# Architecture
|
||||||
wasm = ["dep:wasm-bindgen", "dep:js-sys"]
|
_arch = [] # some arch was picked
|
||||||
|
arch-std = ["_arch", "critical-section/std"]
|
||||||
|
arch-cortex-m = ["_arch", "dep:cortex-m"]
|
||||||
|
arch-xtensa = ["_arch"]
|
||||||
|
arch-riscv32 = ["_arch"]
|
||||||
|
arch-wasm = ["_arch", "dep:wasm-bindgen", "dep:js-sys"]
|
||||||
|
|
||||||
|
# Enable creating a `Pender` from an arbitrary function pointer callback.
|
||||||
|
pender-callback = []
|
||||||
|
|
||||||
|
# Enable the thread-mode executor (using WFE/SEV in Cortex-M, WFI in other embedded archs)
|
||||||
|
executor-thread = []
|
||||||
|
# Enable the interrupt-mode executor (available in Cortex-M only)
|
||||||
|
executor-interrupt = []
|
||||||
|
|
||||||
# Enable nightly-only features
|
# Enable nightly-only features
|
||||||
nightly = []
|
nightly = []
|
||||||
@ -55,9 +68,11 @@ embassy-macros = { version = "0.1.0", path = "../embassy-macros" }
|
|||||||
embassy-time = { version = "0.1.0", path = "../embassy-time", optional = true}
|
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"
|
|
||||||
static_cell = "1.0"
|
static_cell = "1.0"
|
||||||
|
|
||||||
# WASM dependencies
|
# arch-cortex-m dependencies
|
||||||
|
cortex-m = { version = "0.7.6", optional = true }
|
||||||
|
|
||||||
|
# arch-wasm dependencies
|
||||||
wasm-bindgen = { version = "0.2.82", optional = true }
|
wasm-bindgen = { version = "0.2.82", optional = true }
|
||||||
js-sys = { version = "0.3", optional = true }
|
js-sys = { version = "0.3", optional = true }
|
||||||
|
@ -1,59 +1,209 @@
|
|||||||
use core::arch::asm;
|
#[cfg(feature = "executor-thread")]
|
||||||
use core::marker::PhantomData;
|
pub use thread::*;
|
||||||
use core::ptr;
|
#[cfg(feature = "executor-thread")]
|
||||||
|
mod thread {
|
||||||
|
use core::arch::asm;
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use super::{raw, Spawner};
|
#[cfg(feature = "nightly")]
|
||||||
|
pub use embassy_macros::main_cortex_m as main;
|
||||||
|
|
||||||
/// Thread mode executor, using WFE/SEV.
|
use crate::raw::{Pender, PenderInner};
|
||||||
///
|
use crate::{raw, Spawner};
|
||||||
/// This is the simplest and most common kind of executor. It runs on
|
|
||||||
/// thread mode (at the lowest priority level), and uses the `WFE` ARM instruction
|
|
||||||
/// to sleep when it has no more work to do. When a task is woken, a `SEV` instruction
|
|
||||||
/// is executed, to make the `WFE` exit from sleep and poll the task.
|
|
||||||
///
|
|
||||||
/// This executor allows for ultra low power consumption for chips where `WFE`
|
|
||||||
/// triggers low-power sleep without extra steps. If your chip requires extra steps,
|
|
||||||
/// you may use [`raw::Executor`] directly to program custom behavior.
|
|
||||||
pub struct Executor {
|
|
||||||
inner: raw::Executor,
|
|
||||||
not_send: PhantomData<*mut ()>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Executor {
|
#[derive(Copy, Clone)]
|
||||||
/// Create a new Executor.
|
pub(crate) struct ThreadPender;
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
impl ThreadPender {
|
||||||
inner: raw::Executor::new(|_| unsafe { asm!("sev") }, ptr::null_mut()),
|
pub(crate) fn pend(self) {
|
||||||
not_send: PhantomData,
|
unsafe { core::arch::asm!("sev") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run the executor.
|
/// Thread mode executor, using WFE/SEV.
|
||||||
///
|
///
|
||||||
/// The `init` closure is called with a [`Spawner`] that spawns tasks on
|
/// This is the simplest and most common kind of executor. It runs on
|
||||||
/// this executor. Use it to spawn the initial task(s). After `init` returns,
|
/// thread mode (at the lowest priority level), and uses the `WFE` ARM instruction
|
||||||
/// the executor starts running the tasks.
|
/// to sleep when it has no more work to do. When a task is woken, a `SEV` instruction
|
||||||
|
/// is executed, to make the `WFE` exit from sleep and poll the task.
|
||||||
///
|
///
|
||||||
/// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`),
|
/// This executor allows for ultra low power consumption for chips where `WFE`
|
||||||
/// for example by passing it as an argument to the initial tasks.
|
/// triggers low-power sleep without extra steps. If your chip requires extra steps,
|
||||||
///
|
/// you may use [`raw::Executor`] directly to program custom behavior.
|
||||||
/// This function requires `&'static mut self`. This means you have to store the
|
pub struct Executor {
|
||||||
/// Executor instance in a place where it'll live forever and grants you mutable
|
inner: raw::Executor,
|
||||||
/// access. There's a few ways to do this:
|
not_send: PhantomData<*mut ()>,
|
||||||
///
|
}
|
||||||
/// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe)
|
|
||||||
/// - a `static mut` (unsafe)
|
impl Executor {
|
||||||
/// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe)
|
/// Create a new Executor.
|
||||||
///
|
pub fn new() -> Self {
|
||||||
/// This function never returns.
|
Self {
|
||||||
pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
|
inner: raw::Executor::new(Pender(PenderInner::Thread(ThreadPender))),
|
||||||
init(self.inner.spawner());
|
not_send: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Run the executor.
|
||||||
|
///
|
||||||
|
/// The `init` closure is called with a [`Spawner`] that spawns tasks on
|
||||||
|
/// this executor. Use it to spawn the initial task(s). After `init` returns,
|
||||||
|
/// the executor starts running the tasks.
|
||||||
|
///
|
||||||
|
/// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`),
|
||||||
|
/// for example by passing it as an argument to the initial tasks.
|
||||||
|
///
|
||||||
|
/// This function requires `&'static mut self`. This means you have to store the
|
||||||
|
/// Executor instance in a place where it'll live forever and grants you mutable
|
||||||
|
/// access. There's a few ways to do this:
|
||||||
|
///
|
||||||
|
/// - 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)
|
||||||
|
///
|
||||||
|
/// This function never returns.
|
||||||
|
pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
|
||||||
|
init(self.inner.spawner());
|
||||||
|
|
||||||
|
loop {
|
||||||
|
unsafe {
|
||||||
|
self.inner.poll();
|
||||||
|
asm!("wfe");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "executor-interrupt")]
|
||||||
|
pub use interrupt::*;
|
||||||
|
#[cfg(feature = "executor-interrupt")]
|
||||||
|
mod interrupt {
|
||||||
|
use core::cell::UnsafeCell;
|
||||||
|
use core::mem::MaybeUninit;
|
||||||
|
|
||||||
|
use atomic_polyfill::{AtomicBool, Ordering};
|
||||||
|
use cortex_m::interrupt::InterruptNumber;
|
||||||
|
use cortex_m::peripheral::NVIC;
|
||||||
|
|
||||||
|
use crate::raw::{self, Pender, PenderInner};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub(crate) struct InterruptPender(u16);
|
||||||
|
|
||||||
|
impl InterruptPender {
|
||||||
|
pub(crate) fn pend(self) {
|
||||||
|
// STIR is faster, but is only available in v7 and higher.
|
||||||
|
#[cfg(not(armv6m))]
|
||||||
|
{
|
||||||
|
let mut nvic: cortex_m::peripheral::NVIC = unsafe { core::mem::transmute(()) };
|
||||||
|
nvic.request(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(armv6m)]
|
||||||
|
cortex_m::peripheral::NVIC::pend(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl cortex_m::interrupt::InterruptNumber for InterruptPender {
|
||||||
|
fn number(self) -> u16 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Interrupt mode executor.
|
||||||
|
///
|
||||||
|
/// This executor runs tasks in interrupt mode. The interrupt handler is set up
|
||||||
|
/// to poll tasks, and when a task is woken the interrupt is pended from software.
|
||||||
|
///
|
||||||
|
/// This allows running async tasks at a priority higher than thread mode. One
|
||||||
|
/// use case is to leave thread mode free for non-async tasks. Another use case is
|
||||||
|
/// to run multiple executors: one in thread mode for low priority tasks and another in
|
||||||
|
/// interrupt mode for higher priority tasks. Higher priority tasks will preempt lower
|
||||||
|
/// priority ones.
|
||||||
|
///
|
||||||
|
/// It is even possible to run multiple interrupt mode executors at different priorities,
|
||||||
|
/// by assigning different priorities to the interrupts. For an example on how to do this,
|
||||||
|
/// See the 'multiprio' example for 'embassy-nrf'.
|
||||||
|
///
|
||||||
|
/// To use it, you have to pick an interrupt that won't be used by the hardware.
|
||||||
|
/// Some chips reserve some interrupts for this purpose, sometimes named "software interrupts" (SWI).
|
||||||
|
/// If this is not the case, you may use an interrupt from any unused peripheral.
|
||||||
|
///
|
||||||
|
/// It is somewhat more complex to use, it's recommended to use the thread-mode
|
||||||
|
/// [`Executor`] instead, if it works for your use case.
|
||||||
|
pub struct InterruptExecutor {
|
||||||
|
started: AtomicBool,
|
||||||
|
executor: UnsafeCell<MaybeUninit<raw::Executor>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for InterruptExecutor {}
|
||||||
|
unsafe impl Sync for InterruptExecutor {}
|
||||||
|
|
||||||
|
impl InterruptExecutor {
|
||||||
|
/// Create a new, not started `InterruptExecutor`.
|
||||||
|
#[inline]
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
started: AtomicBool::new(false),
|
||||||
|
executor: UnsafeCell::new(MaybeUninit::uninit()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Executor interrupt callback.
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// You MUST call this from the interrupt handler, and from nowhere else.
|
||||||
|
pub unsafe fn on_interrupt(&'static self) {
|
||||||
|
let executor = unsafe { (&*self.executor.get()).assume_init_ref() };
|
||||||
|
executor.poll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start the executor.
|
||||||
|
///
|
||||||
|
/// This initializes the executor, enables the interrupt, and returns.
|
||||||
|
/// The executor keeps running in the background through the interrupt.
|
||||||
|
///
|
||||||
|
/// This returns a [`SendSpawner`] you can use to spawn tasks on it. A [`SendSpawner`]
|
||||||
|
/// is returned instead of a [`Spawner`](embassy_executor::Spawner) because the executor effectively runs in a
|
||||||
|
/// different "thread" (the interrupt), so spawning tasks on it is effectively
|
||||||
|
/// sending them.
|
||||||
|
///
|
||||||
|
/// To obtain a [`Spawner`](embassy_executor::Spawner) for this executor, use [`Spawner::for_current_executor()`](embassy_executor::Spawner::for_current_executor()) from
|
||||||
|
/// a task running in it.
|
||||||
|
///
|
||||||
|
/// # Interrupt requirements
|
||||||
|
///
|
||||||
|
/// You must write the interrupt handler yourself, and make it call [`on_interrupt()`](Self::on_interrupt).
|
||||||
|
///
|
||||||
|
/// This method already enables (unmasks) the interrupt, you must NOT do it yourself.
|
||||||
|
///
|
||||||
|
/// You must set the interrupt priority before calling this method. You MUST NOT
|
||||||
|
/// do it after.
|
||||||
|
///
|
||||||
|
pub fn start(&'static self, irq: impl InterruptNumber) -> crate::SendSpawner {
|
||||||
|
if self
|
||||||
|
.started
|
||||||
|
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
panic!("InterruptExecutor::start() called multiple times on the same executor.");
|
||||||
|
}
|
||||||
|
|
||||||
loop {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
self.inner.poll();
|
(&mut *self.executor.get())
|
||||||
asm!("wfe");
|
.as_mut_ptr()
|
||||||
};
|
.write(raw::Executor::new(Pender(PenderInner::Interrupt(InterruptPender(
|
||||||
|
irq.number(),
|
||||||
|
)))))
|
||||||
|
}
|
||||||
|
|
||||||
|
let executor = unsafe { (&*self.executor.get()).assume_init_ref() };
|
||||||
|
|
||||||
|
unsafe { NVIC::unmask(irq) }
|
||||||
|
|
||||||
|
executor.spawner().make_send()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,72 +1,83 @@
|
|||||||
use core::marker::PhantomData;
|
#[cfg(feature = "executor-interrupt")]
|
||||||
use core::ptr;
|
compile_error!("`executor-interrupt` is not supported with `arch-riscv32`.");
|
||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
|
||||||
|
|
||||||
use super::{raw, Spawner};
|
#[cfg(feature = "executor-thread")]
|
||||||
|
pub use thread::*;
|
||||||
|
#[cfg(feature = "executor-thread")]
|
||||||
|
mod thread {
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
/// global atomic used to keep track of whether there is work to do since sev() is not available on RISCV
|
use crate::raw::{Pender, PenderInner};
|
||||||
///
|
use crate::{raw, Spawner};
|
||||||
static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false);
|
|
||||||
|
|
||||||
/// RISCV32 Executor
|
#[derive(Copy, Clone)]
|
||||||
pub struct Executor {
|
pub(crate) struct ThreadPender;
|
||||||
inner: raw::Executor,
|
|
||||||
not_send: PhantomData<*mut ()>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Executor {
|
impl ThreadPender {
|
||||||
/// Create a new Executor.
|
#[allow(unused)]
|
||||||
pub fn new() -> Self {
|
pub(crate) fn pend(self) {
|
||||||
Self {
|
SIGNAL_WORK_THREAD_MODE.store(true, core::sync::atomic::Ordering::SeqCst);
|
||||||
// use Signal_Work_Thread_Mode as substitute for local interrupt register
|
|
||||||
inner: raw::Executor::new(
|
|
||||||
|_| {
|
|
||||||
SIGNAL_WORK_THREAD_MODE.store(true, Ordering::SeqCst);
|
|
||||||
},
|
|
||||||
ptr::null_mut(),
|
|
||||||
),
|
|
||||||
not_send: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run the executor.
|
/// global atomic used to keep track of whether there is work to do since sev() is not available on RISCV
|
||||||
///
|
static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false);
|
||||||
/// The `init` closure is called with a [`Spawner`] that spawns tasks on
|
|
||||||
/// this executor. Use it to spawn the initial task(s). After `init` returns,
|
|
||||||
/// the executor starts running the tasks.
|
|
||||||
///
|
|
||||||
/// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`),
|
|
||||||
/// for example by passing it as an argument to the initial tasks.
|
|
||||||
///
|
|
||||||
/// This function requires `&'static mut self`. This means you have to store the
|
|
||||||
/// Executor instance in a place where it'll live forever and grants you mutable
|
|
||||||
/// access. There's a few ways to do this:
|
|
||||||
///
|
|
||||||
/// - 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)
|
|
||||||
///
|
|
||||||
/// This function never returns.
|
|
||||||
pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
|
|
||||||
init(self.inner.spawner());
|
|
||||||
|
|
||||||
loop {
|
/// RISCV32 Executor
|
||||||
unsafe {
|
pub struct Executor {
|
||||||
self.inner.poll();
|
inner: raw::Executor,
|
||||||
// we do not care about race conditions between the load and store operations, interrupts
|
not_send: PhantomData<*mut ()>,
|
||||||
//will only set this value to true.
|
}
|
||||||
critical_section::with(|_| {
|
|
||||||
// if there is work to do, loop back to polling
|
impl Executor {
|
||||||
// TODO can we relax this?
|
/// Create a new Executor.
|
||||||
if SIGNAL_WORK_THREAD_MODE.load(Ordering::SeqCst) {
|
pub fn new() -> Self {
|
||||||
SIGNAL_WORK_THREAD_MODE.store(false, Ordering::SeqCst);
|
Self {
|
||||||
}
|
inner: raw::Executor::new(Pender(PenderInner::Thread(ThreadPender))),
|
||||||
// if not, wait for interrupt
|
not_send: PhantomData,
|
||||||
else {
|
}
|
||||||
core::arch::asm!("wfi");
|
}
|
||||||
}
|
|
||||||
});
|
/// Run the executor.
|
||||||
// if an interrupt occurred while waiting, it will be serviced here
|
///
|
||||||
|
/// The `init` closure is called with a [`Spawner`] that spawns tasks on
|
||||||
|
/// this executor. Use it to spawn the initial task(s). After `init` returns,
|
||||||
|
/// the executor starts running the tasks.
|
||||||
|
///
|
||||||
|
/// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`),
|
||||||
|
/// for example by passing it as an argument to the initial tasks.
|
||||||
|
///
|
||||||
|
/// This function requires `&'static mut self`. This means you have to store the
|
||||||
|
/// Executor instance in a place where it'll live forever and grants you mutable
|
||||||
|
/// access. There's a few ways to do this:
|
||||||
|
///
|
||||||
|
/// - 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)
|
||||||
|
///
|
||||||
|
/// This function never returns.
|
||||||
|
pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
|
||||||
|
init(self.inner.spawner());
|
||||||
|
|
||||||
|
loop {
|
||||||
|
unsafe {
|
||||||
|
self.inner.poll();
|
||||||
|
// we do not care about race conditions between the load and store operations, interrupts
|
||||||
|
//will only set this value to true.
|
||||||
|
critical_section::with(|_| {
|
||||||
|
// if there is work to do, loop back to polling
|
||||||
|
// TODO can we relax this?
|
||||||
|
if SIGNAL_WORK_THREAD_MODE.load(Ordering::SeqCst) {
|
||||||
|
SIGNAL_WORK_THREAD_MODE.store(false, Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
// if not, wait for interrupt
|
||||||
|
else {
|
||||||
|
core::arch::asm!("wfi");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// if an interrupt occurred while waiting, it will be serviced here
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,84 +1,100 @@
|
|||||||
use std::marker::PhantomData;
|
#[cfg(feature = "executor-interrupt")]
|
||||||
use std::sync::{Condvar, Mutex};
|
compile_error!("`executor-interrupt` is not supported with `arch-std`.");
|
||||||
|
|
||||||
use super::{raw, Spawner};
|
#[cfg(feature = "executor-thread")]
|
||||||
|
pub use thread::*;
|
||||||
|
#[cfg(feature = "executor-thread")]
|
||||||
|
mod thread {
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use std::sync::{Condvar, Mutex};
|
||||||
|
|
||||||
/// Single-threaded std-based executor.
|
#[cfg(feature = "nightly")]
|
||||||
pub struct Executor {
|
pub use embassy_macros::main_std as main;
|
||||||
inner: raw::Executor,
|
|
||||||
not_send: PhantomData<*mut ()>,
|
|
||||||
signaler: &'static Signaler,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Executor {
|
use crate::raw::{Pender, PenderInner};
|
||||||
/// Create a new Executor.
|
use crate::{raw, Spawner};
|
||||||
pub fn new() -> Self {
|
|
||||||
let signaler = &*Box::leak(Box::new(Signaler::new()));
|
#[derive(Copy, Clone)]
|
||||||
Self {
|
pub(crate) struct ThreadPender(&'static Signaler);
|
||||||
inner: raw::Executor::new(
|
|
||||||
|p| unsafe {
|
impl ThreadPender {
|
||||||
let s = &*(p as *const () as *const Signaler);
|
#[allow(unused)]
|
||||||
s.signal()
|
pub(crate) fn pend(self) {
|
||||||
},
|
self.0.signal()
|
||||||
signaler as *const _ as _,
|
|
||||||
),
|
|
||||||
not_send: PhantomData,
|
|
||||||
signaler,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run the executor.
|
/// Single-threaded std-based executor.
|
||||||
///
|
pub struct Executor {
|
||||||
/// The `init` closure is called with a [`Spawner`] that spawns tasks on
|
inner: raw::Executor,
|
||||||
/// this executor. Use it to spawn the initial task(s). After `init` returns,
|
not_send: PhantomData<*mut ()>,
|
||||||
/// the executor starts running the tasks.
|
signaler: &'static Signaler,
|
||||||
///
|
|
||||||
/// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`),
|
|
||||||
/// for example by passing it as an argument to the initial tasks.
|
|
||||||
///
|
|
||||||
/// This function requires `&'static mut self`. This means you have to store the
|
|
||||||
/// Executor instance in a place where it'll live forever and grants you mutable
|
|
||||||
/// access. There's a few ways to do this:
|
|
||||||
///
|
|
||||||
/// - 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)
|
|
||||||
///
|
|
||||||
/// This function never returns.
|
|
||||||
pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
|
|
||||||
init(self.inner.spawner());
|
|
||||||
|
|
||||||
loop {
|
|
||||||
unsafe { self.inner.poll() };
|
|
||||||
self.signaler.wait()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
struct Signaler {
|
impl Executor {
|
||||||
mutex: Mutex<bool>,
|
/// Create a new Executor.
|
||||||
condvar: Condvar,
|
pub fn new() -> Self {
|
||||||
}
|
let signaler = &*Box::leak(Box::new(Signaler::new()));
|
||||||
|
Self {
|
||||||
|
inner: raw::Executor::new(Pender(PenderInner::Thread(ThreadPender(signaler)))),
|
||||||
|
not_send: PhantomData,
|
||||||
|
signaler,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Signaler {
|
/// Run the executor.
|
||||||
fn new() -> Self {
|
///
|
||||||
Self {
|
/// The `init` closure is called with a [`Spawner`] that spawns tasks on
|
||||||
mutex: Mutex::new(false),
|
/// this executor. Use it to spawn the initial task(s). After `init` returns,
|
||||||
condvar: Condvar::new(),
|
/// the executor starts running the tasks.
|
||||||
|
///
|
||||||
|
/// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`),
|
||||||
|
/// for example by passing it as an argument to the initial tasks.
|
||||||
|
///
|
||||||
|
/// This function requires `&'static mut self`. This means you have to store the
|
||||||
|
/// Executor instance in a place where it'll live forever and grants you mutable
|
||||||
|
/// access. There's a few ways to do this:
|
||||||
|
///
|
||||||
|
/// - 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)
|
||||||
|
///
|
||||||
|
/// This function never returns.
|
||||||
|
pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
|
||||||
|
init(self.inner.spawner());
|
||||||
|
|
||||||
|
loop {
|
||||||
|
unsafe { self.inner.poll() };
|
||||||
|
self.signaler.wait()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wait(&self) {
|
struct Signaler {
|
||||||
let mut signaled = self.mutex.lock().unwrap();
|
mutex: Mutex<bool>,
|
||||||
while !*signaled {
|
condvar: Condvar,
|
||||||
signaled = self.condvar.wait(signaled).unwrap();
|
|
||||||
}
|
|
||||||
*signaled = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signal(&self) {
|
impl Signaler {
|
||||||
let mut signaled = self.mutex.lock().unwrap();
|
fn new() -> Self {
|
||||||
*signaled = true;
|
Self {
|
||||||
self.condvar.notify_one();
|
mutex: Mutex::new(false),
|
||||||
|
condvar: Condvar::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wait(&self) {
|
||||||
|
let mut signaled = self.mutex.lock().unwrap();
|
||||||
|
while !*signaled {
|
||||||
|
signaled = self.condvar.wait(signaled).unwrap();
|
||||||
|
}
|
||||||
|
*signaled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signal(&self) {
|
||||||
|
let mut signaled = self.mutex.lock().unwrap();
|
||||||
|
*signaled = true;
|
||||||
|
self.condvar.notify_one();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,74 +1,88 @@
|
|||||||
use core::marker::PhantomData;
|
#[cfg(feature = "executor-interrupt")]
|
||||||
|
compile_error!("`executor-interrupt` is not supported with `arch-wasm`.");
|
||||||
|
|
||||||
use js_sys::Promise;
|
#[cfg(feature = "executor-thread")]
|
||||||
use wasm_bindgen::prelude::*;
|
pub use thread::*;
|
||||||
|
#[cfg(feature = "executor-thread")]
|
||||||
|
mod thread {
|
||||||
|
|
||||||
use super::raw::util::UninitCell;
|
use core::marker::PhantomData;
|
||||||
use super::raw::{self};
|
|
||||||
use super::Spawner;
|
|
||||||
|
|
||||||
/// WASM executor, wasm_bindgen to schedule tasks on the JS event loop.
|
#[cfg(feature = "nightly")]
|
||||||
pub struct Executor {
|
pub use embassy_macros::main_wasm as main;
|
||||||
inner: raw::Executor,
|
use js_sys::Promise;
|
||||||
ctx: &'static WasmContext,
|
use wasm_bindgen::prelude::*;
|
||||||
not_send: PhantomData<*mut ()>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) struct WasmContext {
|
use crate::raw::util::UninitCell;
|
||||||
promise: Promise,
|
use crate::raw::{Pender, PenderInner};
|
||||||
closure: UninitCell<Closure<dyn FnMut(JsValue)>>,
|
use crate::{raw, Spawner};
|
||||||
}
|
|
||||||
|
|
||||||
impl WasmContext {
|
/// WASM executor, wasm_bindgen to schedule tasks on the JS event loop.
|
||||||
pub fn new() -> Self {
|
pub struct Executor {
|
||||||
Self {
|
inner: raw::Executor,
|
||||||
promise: Promise::resolve(&JsValue::undefined()),
|
ctx: &'static WasmContext,
|
||||||
closure: UninitCell::uninit(),
|
not_send: PhantomData<*mut ()>,
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Executor {
|
pub(crate) struct WasmContext {
|
||||||
/// Create a new Executor.
|
promise: Promise,
|
||||||
pub fn new() -> Self {
|
closure: UninitCell<Closure<dyn FnMut(JsValue)>>,
|
||||||
let ctx = &*Box::leak(Box::new(WasmContext::new()));
|
}
|
||||||
let inner = raw::Executor::new(
|
|
||||||
|p| unsafe {
|
#[derive(Copy, Clone)]
|
||||||
let ctx = &*(p as *const () as *const WasmContext);
|
pub(crate) struct ThreadPender(&'static WasmContext);
|
||||||
let _ = ctx.promise.then(ctx.closure.as_mut());
|
|
||||||
},
|
impl ThreadPender {
|
||||||
ctx as *const _ as _,
|
#[allow(unused)]
|
||||||
);
|
pub(crate) fn pend(self) {
|
||||||
Self {
|
let _ = self.0.promise.then(unsafe { self.0.closure.as_mut() });
|
||||||
inner,
|
|
||||||
not_send: PhantomData,
|
|
||||||
ctx,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run the executor.
|
impl WasmContext {
|
||||||
///
|
pub fn new() -> Self {
|
||||||
/// The `init` closure is called with a [`Spawner`] that spawns tasks on
|
Self {
|
||||||
/// this executor. Use it to spawn the initial task(s). After `init` returns,
|
promise: Promise::resolve(&JsValue::undefined()),
|
||||||
/// the executor starts running the tasks.
|
closure: UninitCell::uninit(),
|
||||||
///
|
}
|
||||||
/// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`),
|
}
|
||||||
/// for example by passing it as an argument to the initial tasks.
|
}
|
||||||
///
|
|
||||||
/// This function requires `&'static mut self`. This means you have to store the
|
impl Executor {
|
||||||
/// Executor instance in a place where it'll live forever and grants you mutable
|
/// Create a new Executor.
|
||||||
/// access. There's a few ways to do this:
|
pub fn new() -> Self {
|
||||||
///
|
let ctx = &*Box::leak(Box::new(WasmContext::new()));
|
||||||
/// - a [StaticCell](https://docs.rs/static_cell/latest/static_cell/) (safe)
|
Self {
|
||||||
/// - a `static mut` (unsafe)
|
inner: raw::Executor::new(Pender(PenderInner::Thread(ThreadPender(ctx)))),
|
||||||
/// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe)
|
not_send: PhantomData,
|
||||||
pub fn start(&'static mut self, init: impl FnOnce(Spawner)) {
|
ctx,
|
||||||
unsafe {
|
}
|
||||||
let executor = &self.inner;
|
}
|
||||||
self.ctx.closure.write(Closure::new(move |_| {
|
|
||||||
executor.poll();
|
/// Run the executor.
|
||||||
}));
|
///
|
||||||
init(self.inner.spawner());
|
/// The `init` closure is called with a [`Spawner`] that spawns tasks on
|
||||||
|
/// this executor. Use it to spawn the initial task(s). After `init` returns,
|
||||||
|
/// the executor starts running the tasks.
|
||||||
|
///
|
||||||
|
/// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`),
|
||||||
|
/// for example by passing it as an argument to the initial tasks.
|
||||||
|
///
|
||||||
|
/// This function requires `&'static mut self`. This means you have to store the
|
||||||
|
/// Executor instance in a place where it'll live forever and grants you mutable
|
||||||
|
/// access. There's a few ways to do this:
|
||||||
|
///
|
||||||
|
/// - 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)) {
|
||||||
|
unsafe {
|
||||||
|
let executor = &self.inner;
|
||||||
|
self.ctx.closure.write(Closure::new(move |_| {
|
||||||
|
executor.poll();
|
||||||
|
}));
|
||||||
|
init(self.inner.spawner());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,73 +1,84 @@
|
|||||||
use core::marker::PhantomData;
|
#[cfg(feature = "executor-interrupt")]
|
||||||
use core::ptr;
|
compile_error!("`executor-interrupt` is not supported with `arch-xtensa`.");
|
||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
|
||||||
|
|
||||||
use super::{raw, Spawner};
|
#[cfg(feature = "executor-thread")]
|
||||||
|
pub use thread::*;
|
||||||
|
#[cfg(feature = "executor-thread")]
|
||||||
|
mod thread {
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
/// global atomic used to keep track of whether there is work to do since sev() is not available on Xtensa
|
use crate::raw::{Pender, PenderInner};
|
||||||
///
|
use crate::{raw, Spawner};
|
||||||
static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false);
|
|
||||||
|
|
||||||
/// Xtensa Executor
|
#[derive(Copy, Clone)]
|
||||||
pub struct Executor {
|
pub(crate) struct ThreadPender;
|
||||||
inner: raw::Executor,
|
|
||||||
not_send: PhantomData<*mut ()>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Executor {
|
impl ThreadPender {
|
||||||
/// Create a new Executor.
|
#[allow(unused)]
|
||||||
pub fn new() -> Self {
|
pub(crate) fn pend(self) {
|
||||||
Self {
|
SIGNAL_WORK_THREAD_MODE.store(true, core::sync::atomic::Ordering::SeqCst);
|
||||||
// use Signal_Work_Thread_Mode as substitute for local interrupt register
|
|
||||||
inner: raw::Executor::new(
|
|
||||||
|_| {
|
|
||||||
SIGNAL_WORK_THREAD_MODE.store(true, Ordering::SeqCst);
|
|
||||||
},
|
|
||||||
ptr::null_mut(),
|
|
||||||
),
|
|
||||||
not_send: PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run the executor.
|
/// global atomic used to keep track of whether there is work to do since sev() is not available on Xtensa
|
||||||
///
|
static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false);
|
||||||
/// The `init` closure is called with a [`Spawner`] that spawns tasks on
|
|
||||||
/// this executor. Use it to spawn the initial task(s). After `init` returns,
|
|
||||||
/// the executor starts running the tasks.
|
|
||||||
///
|
|
||||||
/// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`),
|
|
||||||
/// for example by passing it as an argument to the initial tasks.
|
|
||||||
///
|
|
||||||
/// This function requires `&'static mut self`. This means you have to store the
|
|
||||||
/// Executor instance in a place where it'll live forever and grants you mutable
|
|
||||||
/// access. There's a few ways to do this:
|
|
||||||
///
|
|
||||||
/// - 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)
|
|
||||||
///
|
|
||||||
/// This function never returns.
|
|
||||||
pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
|
|
||||||
init(self.inner.spawner());
|
|
||||||
|
|
||||||
loop {
|
/// Xtensa Executor
|
||||||
unsafe {
|
pub struct Executor {
|
||||||
self.inner.poll();
|
inner: raw::Executor,
|
||||||
// we do not care about race conditions between the load and store operations, interrupts
|
not_send: PhantomData<*mut ()>,
|
||||||
// will only set this value to true.
|
}
|
||||||
// if there is work to do, loop back to polling
|
|
||||||
// TODO can we relax this?
|
impl Executor {
|
||||||
critical_section::with(|_| {
|
/// Create a new Executor.
|
||||||
if SIGNAL_WORK_THREAD_MODE.load(Ordering::SeqCst) {
|
pub fn new() -> Self {
|
||||||
SIGNAL_WORK_THREAD_MODE.store(false, Ordering::SeqCst);
|
Self {
|
||||||
} else {
|
inner: raw::Executor::new(Pender(PenderInner::Thread(ThreadPender))),
|
||||||
// waiti sets the PS.INTLEVEL when slipping into sleep
|
not_send: PhantomData,
|
||||||
// because critical sections in Xtensa are implemented via increasing
|
}
|
||||||
// PS.INTLEVEL the critical section ends here
|
}
|
||||||
// take care not add code after `waiti` if it needs to be inside the CS
|
|
||||||
core::arch::asm!("waiti 0"); // critical section ends here
|
/// Run the executor.
|
||||||
}
|
///
|
||||||
});
|
/// The `init` closure is called with a [`Spawner`] that spawns tasks on
|
||||||
|
/// this executor. Use it to spawn the initial task(s). After `init` returns,
|
||||||
|
/// the executor starts running the tasks.
|
||||||
|
///
|
||||||
|
/// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`),
|
||||||
|
/// for example by passing it as an argument to the initial tasks.
|
||||||
|
///
|
||||||
|
/// This function requires `&'static mut self`. This means you have to store the
|
||||||
|
/// Executor instance in a place where it'll live forever and grants you mutable
|
||||||
|
/// access. There's a few ways to do this:
|
||||||
|
///
|
||||||
|
/// - 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)
|
||||||
|
///
|
||||||
|
/// This function never returns.
|
||||||
|
pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
|
||||||
|
init(self.inner.spawner());
|
||||||
|
|
||||||
|
loop {
|
||||||
|
unsafe {
|
||||||
|
self.inner.poll();
|
||||||
|
// we do not care about race conditions between the load and store operations, interrupts
|
||||||
|
// will only set this value to true.
|
||||||
|
// if there is work to do, loop back to polling
|
||||||
|
// TODO can we relax this?
|
||||||
|
critical_section::with(|_| {
|
||||||
|
if SIGNAL_WORK_THREAD_MODE.load(Ordering::SeqCst) {
|
||||||
|
SIGNAL_WORK_THREAD_MODE.store(false, Ordering::SeqCst);
|
||||||
|
} else {
|
||||||
|
// waiti sets the PS.INTLEVEL when slipping into sleep
|
||||||
|
// because critical sections in Xtensa are implemented via increasing
|
||||||
|
// PS.INTLEVEL the critical section ends here
|
||||||
|
// take care not add code after `waiti` if it needs to be inside the CS
|
||||||
|
core::arch::asm!("waiti 0"); // critical section ends here
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#![cfg_attr(not(any(feature = "std", feature = "wasm")), no_std)]
|
#![cfg_attr(not(any(feature = "arch-std", feature = "arch-wasm")), no_std)]
|
||||||
#![cfg_attr(all(feature = "nightly", target_arch = "xtensa"), feature(asm_experimental_arch))]
|
#![cfg_attr(all(feature = "nightly", feature = "arch-xtensa"), feature(asm_experimental_arch))]
|
||||||
#![allow(clippy::new_without_default)]
|
#![allow(clippy::new_without_default)]
|
||||||
#![doc = include_str!("../README.md")]
|
#![doc = include_str!("../README.md")]
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
@ -10,47 +10,43 @@ pub(crate) mod fmt;
|
|||||||
#[cfg(feature = "nightly")]
|
#[cfg(feature = "nightly")]
|
||||||
pub use embassy_macros::task;
|
pub use embassy_macros::task;
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
macro_rules! check_at_most_one {
|
||||||
if #[cfg(cortex_m)] {
|
(@amo [$($feats:literal)*] [] [$($res:tt)*]) => {
|
||||||
#[path="arch/cortex_m.rs"]
|
#[cfg(any($($res)*))]
|
||||||
mod arch;
|
compile_error!(concat!("At most one of these features can be enabled at the same time:", $(" `", $feats, "`",)*));
|
||||||
pub use arch::*;
|
};
|
||||||
#[cfg(feature = "nightly")]
|
(@amo $feats:tt [$curr:literal $($rest:literal)*] [$($res:tt)*]) => {
|
||||||
pub use embassy_macros::main_cortex_m as main;
|
check_at_most_one!(@amo $feats [$($rest)*] [$($res)* $(all(feature=$curr, feature=$rest),)*]);
|
||||||
}
|
};
|
||||||
else if #[cfg(target_arch="riscv32")] {
|
($($f:literal),*$(,)?) => {
|
||||||
#[path="arch/riscv32.rs"]
|
check_at_most_one!(@amo [$($f)*] [$($f)*] []);
|
||||||
mod arch;
|
};
|
||||||
pub use arch::*;
|
|
||||||
#[cfg(feature = "nightly")]
|
|
||||||
pub use embassy_macros::main_riscv as main;
|
|
||||||
}
|
|
||||||
else if #[cfg(all(target_arch="xtensa", feature = "nightly"))] {
|
|
||||||
#[path="arch/xtensa.rs"]
|
|
||||||
mod arch;
|
|
||||||
pub use arch::*;
|
|
||||||
}
|
|
||||||
else if #[cfg(feature="wasm")] {
|
|
||||||
#[path="arch/wasm.rs"]
|
|
||||||
mod arch;
|
|
||||||
pub use arch::*;
|
|
||||||
#[cfg(feature = "nightly")]
|
|
||||||
pub use embassy_macros::main_wasm as main;
|
|
||||||
}
|
|
||||||
else if #[cfg(feature="std")] {
|
|
||||||
#[path="arch/std.rs"]
|
|
||||||
mod arch;
|
|
||||||
pub use arch::*;
|
|
||||||
#[cfg(feature = "nightly")]
|
|
||||||
pub use embassy_macros::main_std as main;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
check_at_most_one!("arch-cortex-m", "arch-riscv32", "arch-xtensa", "arch-std", "arch-wasm",);
|
||||||
|
|
||||||
|
#[cfg(feature = "_arch")]
|
||||||
|
#[cfg_attr(feature = "arch-cortex-m", path = "arch/cortex_m.rs")]
|
||||||
|
#[cfg_attr(feature = "arch-riscv32", path = "arch/riscv32.rs")]
|
||||||
|
#[cfg_attr(feature = "arch-xtensa", path = "arch/xtensa.rs")]
|
||||||
|
#[cfg_attr(feature = "arch-std", path = "arch/std.rs")]
|
||||||
|
#[cfg_attr(feature = "arch-wasm", path = "arch/wasm.rs")]
|
||||||
|
mod arch;
|
||||||
|
|
||||||
|
#[cfg(feature = "_arch")]
|
||||||
|
pub use arch::*;
|
||||||
|
|
||||||
|
pub mod raw;
|
||||||
|
|
||||||
|
mod spawner;
|
||||||
|
pub use spawner::*;
|
||||||
|
|
||||||
|
/// Implementation details for embassy macros.
|
||||||
|
/// Do not use. Used for macros and HALs only. Not covered by semver guarantees.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
/// Implementation details for embassy macros. DO NOT USE.
|
pub mod _export {
|
||||||
pub mod export {
|
|
||||||
#[cfg(feature = "rtos-trace")]
|
#[cfg(feature = "rtos-trace")]
|
||||||
pub use rtos_trace::trace;
|
pub use rtos_trace::trace;
|
||||||
|
pub use static_cell::StaticCell;
|
||||||
|
|
||||||
/// Expands the given block of code when `embassy-executor` is compiled with
|
/// Expands the given block of code when `embassy-executor` is compiled with
|
||||||
/// the `rtos-trace-interrupt` feature.
|
/// the `rtos-trace-interrupt` feature.
|
||||||
@ -70,14 +66,3 @@ pub mod export {
|
|||||||
($($tt:tt)*) => {};
|
($($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;
|
|
||||||
}
|
|
||||||
|
@ -19,7 +19,6 @@ use core::marker::PhantomData;
|
|||||||
use core::mem;
|
use core::mem;
|
||||||
use core::pin::Pin;
|
use core::pin::Pin;
|
||||||
use core::ptr::NonNull;
|
use core::ptr::NonNull;
|
||||||
use core::sync::atomic::AtomicPtr;
|
|
||||||
use core::task::{Context, Poll};
|
use core::task::{Context, Poll};
|
||||||
|
|
||||||
use atomic_polyfill::{AtomicU32, Ordering};
|
use atomic_polyfill::{AtomicU32, Ordering};
|
||||||
@ -290,10 +289,60 @@ impl<F: Future + 'static, const N: usize> TaskPool<F, N> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub(crate) enum PenderInner {
|
||||||
|
#[cfg(feature = "executor-thread")]
|
||||||
|
Thread(crate::arch::ThreadPender),
|
||||||
|
#[cfg(feature = "executor-interrupt")]
|
||||||
|
Interrupt(crate::arch::InterruptPender),
|
||||||
|
#[cfg(feature = "pender-callback")]
|
||||||
|
Callback { func: fn(*mut ()), context: *mut () },
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for PenderInner {}
|
||||||
|
unsafe impl Sync for PenderInner {}
|
||||||
|
|
||||||
|
/// Platform/architecture-specific action executed when an executor has pending work.
|
||||||
|
///
|
||||||
|
/// When a task within an executor is woken, the `Pender` is called. This does a
|
||||||
|
/// platform/architecture-specific action to signal there is pending work in the executor.
|
||||||
|
/// When this happens, you must arrange for [`Executor::poll`] to be called.
|
||||||
|
///
|
||||||
|
/// You can think of it as a waker, but for the whole executor.
|
||||||
|
pub struct Pender(pub(crate) PenderInner);
|
||||||
|
|
||||||
|
impl Pender {
|
||||||
|
/// Create a `Pender` that will call an arbitrary function pointer.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// - `func`: The function pointer to call.
|
||||||
|
/// - `context`: Opaque context pointer, that will be passed to the function pointer.
|
||||||
|
#[cfg(feature = "pender-callback")]
|
||||||
|
pub fn new_from_callback(func: fn(*mut ()), context: *mut ()) -> Self {
|
||||||
|
Self(PenderInner::Callback {
|
||||||
|
func,
|
||||||
|
context: context.into(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pender {
|
||||||
|
pub(crate) fn pend(&self) {
|
||||||
|
match self.0 {
|
||||||
|
#[cfg(feature = "executor-thread")]
|
||||||
|
PenderInner::Thread(x) => x.pend(),
|
||||||
|
#[cfg(feature = "executor-interrupt")]
|
||||||
|
PenderInner::Interrupt(x) => x.pend(),
|
||||||
|
#[cfg(feature = "pender-callback")]
|
||||||
|
PenderInner::Callback { func, context } => func(context),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) struct SyncExecutor {
|
pub(crate) struct SyncExecutor {
|
||||||
run_queue: RunQueue,
|
run_queue: RunQueue,
|
||||||
signal_fn: fn(*mut ()),
|
pender: Pender,
|
||||||
signal_ctx: AtomicPtr<()>,
|
|
||||||
|
|
||||||
#[cfg(feature = "integrated-timers")]
|
#[cfg(feature = "integrated-timers")]
|
||||||
pub(crate) timer_queue: timer_queue::TimerQueue,
|
pub(crate) timer_queue: timer_queue::TimerQueue,
|
||||||
@ -302,16 +351,13 @@ pub(crate) struct SyncExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SyncExecutor {
|
impl SyncExecutor {
|
||||||
pub(crate) fn new(signal_fn: fn(*mut ()), signal_ctx: *mut ()) -> Self {
|
pub(crate) fn new(pender: Pender) -> Self {
|
||||||
#[cfg(feature = "integrated-timers")]
|
#[cfg(feature = "integrated-timers")]
|
||||||
let alarm = unsafe { unwrap!(driver::allocate_alarm()) };
|
let alarm = unsafe { unwrap!(driver::allocate_alarm()) };
|
||||||
#[cfg(feature = "integrated-timers")]
|
|
||||||
driver::set_alarm_callback(alarm, signal_fn, signal_ctx);
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
run_queue: RunQueue::new(),
|
run_queue: RunQueue::new(),
|
||||||
signal_fn,
|
pender,
|
||||||
signal_ctx: AtomicPtr::new(signal_ctx),
|
|
||||||
|
|
||||||
#[cfg(feature = "integrated-timers")]
|
#[cfg(feature = "integrated-timers")]
|
||||||
timer_queue: timer_queue::TimerQueue::new(),
|
timer_queue: timer_queue::TimerQueue::new(),
|
||||||
@ -332,10 +378,16 @@ impl SyncExecutor {
|
|||||||
trace::task_ready_begin(task.as_ptr() as u32);
|
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.load(Ordering::Relaxed))
|
self.pender.pend();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "integrated-timers")]
|
||||||
|
fn alarm_callback(ctx: *mut ()) {
|
||||||
|
let this: &Self = unsafe { &*(ctx as *const Self) };
|
||||||
|
this.pender.pend();
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) unsafe fn spawn(&'static self, task: TaskRef) {
|
pub(super) unsafe fn spawn(&'static self, task: TaskRef) {
|
||||||
task.header().executor.set(Some(self));
|
task.header().executor.set(Some(self));
|
||||||
|
|
||||||
@ -351,6 +403,9 @@ impl SyncExecutor {
|
|||||||
///
|
///
|
||||||
/// Same as [`Executor::poll`], plus you must only call this on the thread this executor was created.
|
/// Same as [`Executor::poll`], plus you must only call this on the thread this executor was created.
|
||||||
pub(crate) unsafe fn poll(&'static self) {
|
pub(crate) unsafe fn poll(&'static self) {
|
||||||
|
#[cfg(feature = "integrated-timers")]
|
||||||
|
driver::set_alarm_callback(self.alarm, Self::alarm_callback, self as *const _ as *mut ());
|
||||||
|
|
||||||
#[allow(clippy::never_loop)]
|
#[allow(clippy::never_loop)]
|
||||||
loop {
|
loop {
|
||||||
#[cfg(feature = "integrated-timers")]
|
#[cfg(feature = "integrated-timers")]
|
||||||
@ -417,14 +472,14 @@ impl SyncExecutor {
|
|||||||
///
|
///
|
||||||
/// - To get the executor to do work, call `poll()`. This will poll all queued tasks (all tasks
|
/// - To get the executor to do work, call `poll()`. This will poll all queued tasks (all tasks
|
||||||
/// that "want to run").
|
/// that "want to run").
|
||||||
/// - You must supply a `signal_fn`. The executor will call it to notify you it has work
|
/// - You must supply a [`Pender`]. The executor will call it to notify you it has work
|
||||||
/// to do. You must arrange for `poll()` to be called as soon as possible.
|
/// to do. You must arrange for `poll()` to be called as soon as possible.
|
||||||
///
|
///
|
||||||
/// `signal_fn` can be called from *any* context: any thread, any interrupt priority
|
/// The [`Pender`] can be called from *any* context: any thread, any interrupt priority
|
||||||
/// level, etc. It may be called synchronously from any `Executor` method call as well.
|
/// level, etc. It may be called synchronously from any `Executor` method call as well.
|
||||||
/// You must deal with this correctly.
|
/// You must deal with this correctly.
|
||||||
///
|
///
|
||||||
/// In particular, you must NOT call `poll` directly from `signal_fn`, as this violates
|
/// In particular, you must NOT call `poll` directly from the pender callback, as this violates
|
||||||
/// the requirement for `poll` to not be called reentrantly.
|
/// the requirement for `poll` to not be called reentrantly.
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct Executor {
|
pub struct Executor {
|
||||||
@ -437,15 +492,15 @@ impl Executor {
|
|||||||
pub(crate) unsafe fn wrap(inner: &SyncExecutor) -> &Self {
|
pub(crate) unsafe fn wrap(inner: &SyncExecutor) -> &Self {
|
||||||
mem::transmute(inner)
|
mem::transmute(inner)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new executor.
|
/// Create a new executor.
|
||||||
///
|
///
|
||||||
/// When the executor has work to do, it will call `signal_fn` with
|
/// When the executor has work to do, it will call the [`Pender`].
|
||||||
/// `signal_ctx` as argument.
|
|
||||||
///
|
///
|
||||||
/// See [`Executor`] docs for details on `signal_fn`.
|
/// See [`Executor`] docs for details on `Pender`.
|
||||||
pub fn new(signal_fn: fn(*mut ()), signal_ctx: *mut ()) -> Self {
|
pub fn new(pender: Pender) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: SyncExecutor::new(signal_fn, signal_ctx),
|
inner: SyncExecutor::new(pender),
|
||||||
_not_sync: PhantomData,
|
_not_sync: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -468,16 +523,16 @@ impl Executor {
|
|||||||
/// This loops over all tasks that are queued to be polled (i.e. they're
|
/// This loops over all tasks that are queued to be polled (i.e. they're
|
||||||
/// freshly spawned or they've been woken). Other tasks are not polled.
|
/// freshly spawned or they've been woken). Other tasks are not polled.
|
||||||
///
|
///
|
||||||
/// You must call `poll` after receiving a call to `signal_fn`. It is OK
|
/// You must call `poll` after receiving a call to the [`Pender`]. It is OK
|
||||||
/// to call `poll` even when not requested by `signal_fn`, but it wastes
|
/// to call `poll` even when not requested by the `Pender`, but it wastes
|
||||||
/// energy.
|
/// energy.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// You must NOT call `poll` reentrantly on the same executor.
|
/// You must NOT call `poll` reentrantly on the same executor.
|
||||||
///
|
///
|
||||||
/// In particular, note that `poll` may call `signal_fn` synchronously. Therefore, you
|
/// In particular, note that `poll` may call the `Pender` synchronously. Therefore, you
|
||||||
/// must NOT directly call `poll()` from your `signal_fn`. Instead, `signal_fn` has to
|
/// must NOT directly call `poll()` from the `Pender` callback. Instead, the callback has to
|
||||||
/// somehow schedule for `poll()` to be called later, at a time you know for sure there's
|
/// somehow schedule for `poll()` to be called later, at a time you know for sure there's
|
||||||
/// no `poll()` already running.
|
/// no `poll()` already running.
|
||||||
pub unsafe fn poll(&'static self) {
|
pub unsafe fn poll(&'static self) {
|
||||||
|
@ -10,12 +10,12 @@ pub fn run(name: syn::Ident) -> Result<TokenStream, TokenStream> {
|
|||||||
let (isr_enter, isr_exit) = (
|
let (isr_enter, isr_exit) = (
|
||||||
quote! {
|
quote! {
|
||||||
::embassy_executor::rtos_trace_interrupt! {
|
::embassy_executor::rtos_trace_interrupt! {
|
||||||
::embassy_executor::export::trace::isr_enter();
|
::embassy_executor::_export::trace::isr_enter();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
quote! {
|
quote! {
|
||||||
::embassy_executor::rtos_trace_interrupt! {
|
::embassy_executor::rtos_trace_interrupt! {
|
||||||
::embassy_executor::export::trace::isr_exit();
|
::embassy_executor::_export::trace::isr_exit();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../../../embassy-sync" }
|
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 = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] }
|
||||||
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"] }
|
embassy-nrf = { version = "0.1.0", path = "../../../../embassy-nrf", features = ["time-driver-rtc1", "gpiote", "nightly"] }
|
||||||
embassy-boot = { version = "0.1.0", path = "../../../../embassy-boot/boot" }
|
embassy-boot = { version = "0.1.0", path = "../../../../embassy-boot/boot" }
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../../../embassy-sync" }
|
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 = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers", "arch-cortex-m", "executor-thread"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly"] }
|
embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly"] }
|
||||||
embassy-rp = { version = "0.1.0", path = "../../../../embassy-rp", features = ["time-driver", "unstable-traits", "nightly"] }
|
embassy-rp = { version = "0.1.0", path = "../../../../embassy-rp", features = ["time-driver", "unstable-traits", "nightly"] }
|
||||||
embassy-boot-rp = { version = "0.1.0", path = "../../../../embassy-boot/rp" }
|
embassy-boot-rp = { version = "0.1.0", path = "../../../../embassy-boot/rp" }
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../../../embassy-sync", 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 = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] }
|
||||||
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"] }
|
||||||
embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32" }
|
embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32" }
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../../../embassy-sync", 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 = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] }
|
||||||
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"] }
|
||||||
embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32" }
|
embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32" }
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../../../embassy-sync" }
|
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 = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32h743zi", "time-driver-any", "exti"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32h743zi", "time-driver-any", "exti"] }
|
||||||
embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32" }
|
embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32" }
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../../../embassy-sync", 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 = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l072cz", "time-driver-any", "exti", "memory-x"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l072cz", "time-driver-any", "exti", "memory-x"] }
|
||||||
embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32" }
|
embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32" }
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../../../embassy-sync", 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 = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l151cb-a", "time-driver-any", "exti"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l151cb-a", "time-driver-any", "exti"] }
|
||||||
embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32" }
|
embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32" }
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../../../embassy-sync", 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 = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l475vg", "time-driver-any", "exti"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32l475vg", "time-driver-any", "exti"] }
|
||||||
embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32" }
|
embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32" }
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../../../embassy-sync", 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 = ["arch-cortex-m", "executor-thread", "nightly", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../../../embassy-time", features = ["nightly", "tick-hz-32_768"] }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32wl55jc-cm4", "time-driver-any", "exti"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../../../embassy-stm32", features = ["unstable-traits", "nightly", "stm32wl55jc-cm4", "time-driver-any", "exti"] }
|
||||||
embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32" }
|
embassy-boot-stm32 = { version = "0.1.0", path = "../../../../embassy-boot/stm32" }
|
||||||
|
@ -17,7 +17,7 @@ log = [
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync" }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync" }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features=["rtos-trace", "rtos-trace-interrupt", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "rtos-trace", "rtos-trace-interrupt", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time" }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time" }
|
||||||
embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] }
|
embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] }
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ nightly = ["embassy-executor/nightly", "embassy-nrf/nightly", "embassy-net/night
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
|
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
|
||||||
embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
|
embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
|
||||||
embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"], optional = true }
|
embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"], optional = true }
|
||||||
|
@ -9,7 +9,7 @@ embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
|
|||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = [
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = [
|
||||||
"defmt",
|
"defmt",
|
||||||
] }
|
] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = [
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread",
|
||||||
"nightly",
|
"nightly",
|
||||||
"defmt",
|
"defmt",
|
||||||
"integrated-timers",
|
"integrated-timers",
|
||||||
|
@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
|
||||||
embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver", "pio", "critical-section-impl"] }
|
embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver", "pio", "critical-section-impl"] }
|
||||||
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
|
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["log"] }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["log"] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["log", "std", "nightly", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-std", "executor-thread", "log", "nightly", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["log", "std", "nightly"] }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["log", "std", "nightly"] }
|
||||||
embassy-net = { version = "0.1.0", path = "../../embassy-net", features=[ "std", "nightly", "log", "medium-ethernet", "tcp", "udp", "dns", "dhcpv4", "unstable-traits", "proto-ipv6"] }
|
embassy-net = { version = "0.1.0", path = "../../embassy-net", features=[ "std", "nightly", "log", "medium-ethernet", "tcp", "udp", "dns", "dhcpv4", "unstable-traits", "proto-ipv6"] }
|
||||||
embassy-net-driver = { version = "0.1.0", path = "../../embassy-net-driver" }
|
embassy-net-driver = { version = "0.1.0", path = "../../embassy-net-driver" }
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32c031c6", "memory-x", "unstable-pac", "exti"] }
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ defmt = "0.3"
|
|||||||
defmt-rtt = "0.4"
|
defmt-rtt = "0.4"
|
||||||
panic-probe = "0.3"
|
panic-probe = "0.3"
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "memory-x", "stm32f091rc", "time-driver-any", "exti", "unstable-pac"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "memory-x", "stm32f091rc", "time-driver-any", "exti", "unstable-pac"] }
|
||||||
static_cell = "1.0"
|
static_cell = "1.0"
|
||||||
|
@ -62,7 +62,7 @@ use core::mem;
|
|||||||
use cortex_m::peripheral::NVIC;
|
use cortex_m::peripheral::NVIC;
|
||||||
use cortex_m_rt::entry;
|
use cortex_m_rt::entry;
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_stm32::executor::{Executor, InterruptExecutor};
|
use embassy_executor::{Executor, InterruptExecutor};
|
||||||
use embassy_stm32::interrupt;
|
use embassy_stm32::interrupt;
|
||||||
use embassy_stm32::pac::Interrupt;
|
use embassy_stm32::pac::Interrupt;
|
||||||
use embassy_time::{Duration, Instant, Timer};
|
use embassy_time::{Duration, Instant, Timer};
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any"] }
|
||||||
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
|
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f207zg", "unstable-pac", "memory-x", "time-driver-any", "exti"] }
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-any", "exti"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f303ze", "unstable-pac", "memory-x", "time-driver-any", "exti"] }
|
||||||
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
|
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
|
||||||
|
@ -62,7 +62,7 @@ use core::mem;
|
|||||||
use cortex_m::peripheral::NVIC;
|
use cortex_m::peripheral::NVIC;
|
||||||
use cortex_m_rt::entry;
|
use cortex_m_rt::entry;
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_stm32::executor::{Executor, InterruptExecutor};
|
use embassy_executor::{Executor, InterruptExecutor};
|
||||||
use embassy_stm32::interrupt;
|
use embassy_stm32::interrupt;
|
||||||
use embassy_stm32::pac::Interrupt;
|
use embassy_stm32::pac::Interrupt;
|
||||||
use embassy_time::{Duration, Instant, Timer};
|
use embassy_time::{Duration, Instant, Timer};
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers", "arch-cortex-m", "executor-thread", "executor-interrupt"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti"] }
|
||||||
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
|
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
|
||||||
|
@ -62,7 +62,7 @@ use core::mem;
|
|||||||
use cortex_m::peripheral::NVIC;
|
use cortex_m::peripheral::NVIC;
|
||||||
use cortex_m_rt::entry;
|
use cortex_m_rt::entry;
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_stm32::executor::{Executor, InterruptExecutor};
|
use embassy_executor::{Executor, InterruptExecutor};
|
||||||
use embassy_stm32::interrupt;
|
use embassy_stm32::interrupt;
|
||||||
use embassy_stm32::pac::Interrupt;
|
use embassy_stm32::pac::Interrupt;
|
||||||
use embassy_time::{Duration, Instant, Timer};
|
use embassy_time::{Duration, Instant, Timer};
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f767zi", "unstable-pac", "time-driver-any", "exti"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f767zi", "unstable-pac", "time-driver-any", "exti"] }
|
||||||
embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet"] }
|
embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet"] }
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g071rb", "memory-x", "unstable-pac", "exti"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g071rb", "memory-x", "unstable-pac", "exti"] }
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "time-driver-any", "stm32g491re", "memory-x", "unstable-pac", "exti"] }
|
||||||
embassy-hal-common = {version = "0.1.0", path = "../../embassy-hal-common" }
|
embassy-hal-common = {version = "0.1.0", path = "../../embassy-hal-common" }
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h743bi", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h743bi", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] }
|
||||||
embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "unstable-traits", "proto-ipv6"] }
|
embassy-net = { path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet", "unstable-traits", "proto-ipv6"] }
|
||||||
|
@ -10,7 +10,7 @@ nightly = ["embassy-stm32/nightly", "embassy-lora", "lorawan-device", "lorawan",
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "time-driver-any", "exti", "unstable-traits", "memory-x"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "time-driver-any", "exti", "unstable-traits", "memory-x"] }
|
||||||
embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx127x", "time", "defmt"], optional = true}
|
embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx127x", "time", "defmt"], optional = true}
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32l151cb-a", "time-driver-any", "memory-x"] }
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
||||||
embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" }
|
embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l4s5vi", "time-driver-any", "exti", "unstable-traits"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l4s5vi", "time-driver-any", "exti", "unstable-traits"] }
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "unstable-traits", "memory-x"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l552ze", "time-driver-any", "exti", "unstable-traits", "memory-x"] }
|
||||||
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
|
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32u585ai", "time-driver-any", "memory-x" ] }
|
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32u585ai", "time-driver-any", "memory-x" ] }
|
||||||
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
|
embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55cc", "time-driver-any", "exti"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wb55cc", "time-driver-any", "exti"] }
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "subghz", "unstable-pac", "exti"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "subghz", "unstable-pac", "exti"] }
|
||||||
embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["stm32wl", "time", "defmt"] }
|
embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["stm32wl", "time", "defmt"] }
|
||||||
|
@ -9,7 +9,7 @@ crate-type = ["cdylib"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["log"] }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["log"] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["log", "wasm", "nightly", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-wasm", "executor-thread", "log", "nightly", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["log", "wasm", "nightly"] }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["log", "wasm", "nightly"] }
|
||||||
|
|
||||||
wasm-logger = "0.2.0"
|
wasm-logger = "0.2.0"
|
||||||
|
@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
|
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt", "nightly"] }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt", "nightly"] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "nightly", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "nightly", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "nightly", "defmt-timestamp-uptime"] }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "nightly", "defmt-timestamp-uptime"] }
|
||||||
embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nightly", "unstable-traits", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] }
|
embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nightly", "unstable-traits", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] }
|
||||||
embedded-io = { version = "0.4.0", features = ["async"] }
|
embedded-io = { version = "0.4.0", features = ["async"] }
|
||||||
|
@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt"] }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt"] }
|
||||||
embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "time-driver", "critical-section-impl"] }
|
embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "time-driver", "critical-section-impl"] }
|
||||||
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
|
embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
|
||||||
|
@ -15,7 +15,7 @@ stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] }
|
||||||
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] }
|
embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
|
||||||
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768"] }
|
embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768"] }
|
||||||
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "memory-x", "time-driver-tim2"] }
|
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "memory-x", "time-driver-tim2"] }
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user