diff options
| -rw-r--r-- | .vscode/settings.json | 1 | ||||
| -rw-r--r-- | embassy-std/Cargo.toml | 10 | ||||
| -rw-r--r-- | embassy-std/src/lib.rs | 95 | ||||
| -rw-r--r-- | embassy/Cargo.toml | 5 | ||||
| -rw-r--r-- | embassy/src/rand.rs | 15 |
5 files changed, 106 insertions, 20 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json index ef95cf96e..8c53d2097 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json | |||
| @@ -2,7 +2,6 @@ | |||
| 2 | "editor.formatOnSave": true, | 2 | "editor.formatOnSave": true, |
| 3 | "rust-analyzer.cargo.allFeatures": false, | 3 | "rust-analyzer.cargo.allFeatures": false, |
| 4 | "rust-analyzer.checkOnSave.allFeatures": false, | 4 | "rust-analyzer.checkOnSave.allFeatures": false, |
| 5 | "rust-analyzer.cargo.target": "thumbv7em-none-eabihf", | ||
| 6 | "rust-analyzer.checkOnSave.allTargets": false, | 5 | "rust-analyzer.checkOnSave.allTargets": false, |
| 7 | "files.watcherExclude": { | 6 | "files.watcherExclude": { |
| 8 | "**/.git/objects/**": true, | 7 | "**/.git/objects/**": true, |
diff --git a/embassy-std/Cargo.toml b/embassy-std/Cargo.toml new file mode 100644 index 000000000..2a8028137 --- /dev/null +++ b/embassy-std/Cargo.toml | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | [package] | ||
| 2 | name = "embassy-std" | ||
| 3 | version = "0.1.0" | ||
| 4 | authors = ["Dario Nieuwenhuis <[email protected]>"] | ||
| 5 | edition = "2018" | ||
| 6 | |||
| 7 | [dependencies] | ||
| 8 | embassy = { version = "0.1.0", path = "../embassy", features = ["std"] } | ||
| 9 | lazy_static = "1.4.0" | ||
| 10 | rand_core = { version = "0.6.0", features = ["std"] } | ||
diff --git a/embassy-std/src/lib.rs b/embassy-std/src/lib.rs new file mode 100644 index 000000000..2fb814b4d --- /dev/null +++ b/embassy-std/src/lib.rs | |||
| @@ -0,0 +1,95 @@ | |||
| 1 | use embassy::executor::Executor; | ||
| 2 | use embassy::time::TICKS_PER_SECOND; | ||
| 3 | use embassy::time::{Alarm, Clock}; | ||
| 4 | use embassy::util::Forever; | ||
| 5 | use rand_core::{OsRng, RngCore}; | ||
| 6 | use std::mem::MaybeUninit; | ||
| 7 | use std::sync::{Condvar, Mutex}; | ||
| 8 | use std::time::{Duration as StdDuration, Instant as StdInstant}; | ||
| 9 | |||
| 10 | static mut CLOCK_ZERO: MaybeUninit<StdInstant> = MaybeUninit::uninit(); | ||
| 11 | struct StdClock; | ||
| 12 | impl Clock for StdClock { | ||
| 13 | fn now(&self) -> u64 { | ||
| 14 | let zero = unsafe { CLOCK_ZERO.as_ptr().read() }; | ||
| 15 | let dur = StdInstant::now().duration_since(zero); | ||
| 16 | dur.as_secs() * (TICKS_PER_SECOND as u64) | ||
| 17 | + (dur.subsec_nanos() as u64) * (TICKS_PER_SECOND as u64) / 1_000_000_000 | ||
| 18 | } | ||
| 19 | } | ||
| 20 | |||
| 21 | struct StdRand; | ||
| 22 | impl embassy::rand::Rand for StdRand { | ||
| 23 | fn rand(&self, buf: &mut [u8]) { | ||
| 24 | OsRng.fill_bytes(buf); | ||
| 25 | } | ||
| 26 | } | ||
| 27 | |||
| 28 | static mut ALARM_AT: u64 = u64::MAX; | ||
| 29 | |||
| 30 | pub struct StdAlarm; | ||
| 31 | impl Alarm for StdAlarm { | ||
| 32 | fn set_callback(&self, _callback: fn()) {} | ||
| 33 | fn set(&self, timestamp: u64) { | ||
| 34 | unsafe { ALARM_AT = timestamp } | ||
| 35 | } | ||
| 36 | |||
| 37 | fn clear(&self) { | ||
| 38 | unsafe { ALARM_AT = u64::MAX } | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | static EXECUTOR: Forever<Executor> = Forever::new(); | ||
| 43 | |||
| 44 | lazy_static::lazy_static! { | ||
| 45 | static ref MUTEX: Mutex<bool> = Mutex::new(false); | ||
| 46 | static ref CONDVAR: Condvar = Condvar::new(); | ||
| 47 | } | ||
| 48 | |||
| 49 | pub fn init() -> &'static Executor { | ||
| 50 | unsafe { | ||
| 51 | CLOCK_ZERO.as_mut_ptr().write(StdInstant::now()); | ||
| 52 | embassy::time::set_clock(&StdClock); | ||
| 53 | embassy::rand::set_rand(&StdRand); | ||
| 54 | |||
| 55 | EXECUTOR.put(Executor::new_with_alarm(&StdAlarm, || { | ||
| 56 | let mut signaled = MUTEX.lock().unwrap(); | ||
| 57 | *signaled = true; | ||
| 58 | CONDVAR.notify_one(); | ||
| 59 | })) | ||
| 60 | } | ||
| 61 | } | ||
| 62 | |||
| 63 | pub fn run(executor: &'static Executor) -> ! { | ||
| 64 | unsafe { | ||
| 65 | loop { | ||
| 66 | executor.run(); | ||
| 67 | |||
| 68 | let mut signaled = MUTEX.lock().unwrap(); | ||
| 69 | while !*signaled { | ||
| 70 | let alarm_at = ALARM_AT; | ||
| 71 | if alarm_at == u64::MAX { | ||
| 72 | signaled = CONDVAR.wait(signaled).unwrap(); | ||
| 73 | } else { | ||
| 74 | let now = StdClock.now(); | ||
| 75 | if now >= alarm_at { | ||
| 76 | break; | ||
| 77 | } | ||
| 78 | |||
| 79 | let left = alarm_at - now; | ||
| 80 | let dur = StdDuration::new( | ||
| 81 | left / (TICKS_PER_SECOND as u64), | ||
| 82 | (left % (TICKS_PER_SECOND as u64) * 1_000_000_000 | ||
| 83 | / (TICKS_PER_SECOND as u64)) as u32, | ||
| 84 | ); | ||
| 85 | let (signaled2, timeout) = CONDVAR.wait_timeout(signaled, dur).unwrap(); | ||
| 86 | signaled = signaled2; | ||
| 87 | if timeout.timed_out() { | ||
| 88 | break; | ||
| 89 | } | ||
| 90 | } | ||
| 91 | } | ||
| 92 | *signaled = false; | ||
| 93 | } | ||
| 94 | } | ||
| 95 | } | ||
diff --git a/embassy/Cargo.toml b/embassy/Cargo.toml index 8b05e29fe..1d16d1110 100644 --- a/embassy/Cargo.toml +++ b/embassy/Cargo.toml | |||
| @@ -5,7 +5,7 @@ authors = ["Dario Nieuwenhuis <[email protected]>"] | |||
| 5 | edition = "2018" | 5 | edition = "2018" |
| 6 | 6 | ||
| 7 | [features] | 7 | [features] |
| 8 | std = ["futures/std", "rand_core"] | 8 | std = ["futures/std"] |
| 9 | defmt-trace = [] | 9 | defmt-trace = [] |
| 10 | defmt-debug = [] | 10 | defmt-debug = [] |
| 11 | defmt-info = [] | 11 | defmt-info = [] |
| @@ -16,9 +16,6 @@ defmt-error = [] | |||
| 16 | defmt = { version = "0.1.3", optional = true } | 16 | defmt = { version = "0.1.3", optional = true } |
| 17 | log = { version = "0.4.11", optional = true } | 17 | log = { version = "0.4.11", optional = true } |
| 18 | 18 | ||
| 19 | # std-only | ||
| 20 | rand_core = { version = "0.5.1", optional = true, features = ["std"] } | ||
| 21 | |||
| 22 | cortex-m = "0.6.4" | 19 | cortex-m = "0.6.4" |
| 23 | futures = { version = "0.3.5", default-features = false } | 20 | futures = { version = "0.3.5", default-features = false } |
| 24 | pin-project = { version = "1.0.2", default-features = false } | 21 | pin-project = { version = "1.0.2", default-features = false } |
diff --git a/embassy/src/rand.rs b/embassy/src/rand.rs index 6e78c24ae..7e3788380 100644 --- a/embassy/src/rand.rs +++ b/embassy/src/rand.rs | |||
| @@ -4,9 +4,6 @@ pub trait Rand { | |||
| 4 | fn rand(&self, buf: &mut [u8]); | 4 | fn rand(&self, buf: &mut [u8]); |
| 5 | } | 5 | } |
| 6 | 6 | ||
| 7 | #[cfg(feature = "std")] | ||
| 8 | static mut RAND: Option<&'static dyn Rand> = Some(&if_std::Rand); | ||
| 9 | #[cfg(not(feature = "std"))] | ||
| 10 | static mut RAND: Option<&'static dyn Rand> = None; | 7 | static mut RAND: Option<&'static dyn Rand> = None; |
| 11 | 8 | ||
| 12 | pub unsafe fn set_rand(rand: &'static dyn Rand) { | 9 | pub unsafe fn set_rand(rand: &'static dyn Rand) { |
| @@ -16,15 +13,3 @@ pub unsafe fn set_rand(rand: &'static dyn Rand) { | |||
| 16 | pub fn rand(buf: &mut [u8]) { | 13 | pub fn rand(buf: &mut [u8]) { |
| 17 | unsafe { unwrap!(RAND, "No rand set").rand(buf) } | 14 | unsafe { unwrap!(RAND, "No rand set").rand(buf) } |
| 18 | } | 15 | } |
| 19 | |||
| 20 | #[cfg(feature = "std")] | ||
| 21 | mod if_std { | ||
| 22 | use rand_core::{OsRng, RngCore}; | ||
| 23 | |||
| 24 | pub(crate) struct Rand; | ||
| 25 | impl super::Rand for Rand { | ||
| 26 | fn rand(&self, buf: &mut [u8]) { | ||
| 27 | OsRng.fill_bytes(buf) | ||
| 28 | } | ||
| 29 | } | ||
| 30 | } | ||
