aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2020-12-28 03:40:28 +0100
committerDario Nieuwenhuis <[email protected]>2020-12-28 03:41:40 +0100
commit4a7344cb6f33bc6acdb982b7c180e0da81ad2710 (patch)
tree289c869ccd6cb953d554fc085dfed388649e0b2b
parent32c67381df48979f6cf3c188b0dec447d1935d12 (diff)
Add embassy-std crate with glue to run embassy on std.
-rw-r--r--.vscode/settings.json1
-rw-r--r--embassy-std/Cargo.toml10
-rw-r--r--embassy-std/src/lib.rs95
-rw-r--r--embassy/Cargo.toml5
-rw-r--r--embassy/src/rand.rs15
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]
2name = "embassy-std"
3version = "0.1.0"
4authors = ["Dario Nieuwenhuis <[email protected]>"]
5edition = "2018"
6
7[dependencies]
8embassy = { version = "0.1.0", path = "../embassy", features = ["std"] }
9lazy_static = "1.4.0"
10rand_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 @@
1use embassy::executor::Executor;
2use embassy::time::TICKS_PER_SECOND;
3use embassy::time::{Alarm, Clock};
4use embassy::util::Forever;
5use rand_core::{OsRng, RngCore};
6use std::mem::MaybeUninit;
7use std::sync::{Condvar, Mutex};
8use std::time::{Duration as StdDuration, Instant as StdInstant};
9
10static mut CLOCK_ZERO: MaybeUninit<StdInstant> = MaybeUninit::uninit();
11struct StdClock;
12impl 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
21struct StdRand;
22impl embassy::rand::Rand for StdRand {
23 fn rand(&self, buf: &mut [u8]) {
24 OsRng.fill_bytes(buf);
25 }
26}
27
28static mut ALARM_AT: u64 = u64::MAX;
29
30pub struct StdAlarm;
31impl 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
42static EXECUTOR: Forever<Executor> = Forever::new();
43
44lazy_static::lazy_static! {
45 static ref MUTEX: Mutex<bool> = Mutex::new(false);
46 static ref CONDVAR: Condvar = Condvar::new();
47}
48
49pub 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
63pub 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]>"]
5edition = "2018" 5edition = "2018"
6 6
7[features] 7[features]
8std = ["futures/std", "rand_core"] 8std = ["futures/std"]
9defmt-trace = [] 9defmt-trace = []
10defmt-debug = [] 10defmt-debug = []
11defmt-info = [] 11defmt-info = []
@@ -16,9 +16,6 @@ defmt-error = []
16defmt = { version = "0.1.3", optional = true } 16defmt = { version = "0.1.3", optional = true }
17log = { version = "0.4.11", optional = true } 17log = { version = "0.4.11", optional = true }
18 18
19# std-only
20rand_core = { version = "0.5.1", optional = true, features = ["std"] }
21
22cortex-m = "0.6.4" 19cortex-m = "0.6.4"
23futures = { version = "0.3.5", default-features = false } 20futures = { version = "0.3.5", default-features = false }
24pin-project = { version = "1.0.2", default-features = false } 21pin-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")]
8static mut RAND: Option<&'static dyn Rand> = Some(&if_std::Rand);
9#[cfg(not(feature = "std"))]
10static mut RAND: Option<&'static dyn Rand> = None; 7static mut RAND: Option<&'static dyn Rand> = None;
11 8
12pub unsafe fn set_rand(rand: &'static dyn Rand) { 9pub unsafe fn set_rand(rand: &'static dyn Rand) {
@@ -16,15 +13,3 @@ pub unsafe fn set_rand(rand: &'static dyn Rand) {
16pub fn rand(buf: &mut [u8]) { 13pub 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")]
21mod 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}