aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-01-21 18:04:13 +0100
committerGitHub <[email protected]>2021-01-21 18:04:13 +0100
commit57eabb372e750e0604c8d56a4d4e4ecd5ca3e853 (patch)
treeeaf016d91b7204d705cf5d0277479fa5e8e77f9d
parent27831124a761e89563c50c4ca41005fe4cac720e (diff)
parente0183f4495d937e1b11bd2ecb2871f42aac86c3e (diff)
Merge pull request #31 from xoviat/interrupt-signal
add InterruptSignal
-rw-r--r--embassy/src/lib.rs2
-rw-r--r--embassy/src/util/signal.rs68
2 files changed, 70 insertions, 0 deletions
diff --git a/embassy/src/lib.rs b/embassy/src/lib.rs
index 4fa37a55c..74c69b541 100644
--- a/embassy/src/lib.rs
+++ b/embassy/src/lib.rs
@@ -2,6 +2,8 @@
2#![feature(generic_associated_types)] 2#![feature(generic_associated_types)]
3#![feature(const_fn)] 3#![feature(const_fn)]
4#![feature(const_fn_fn_ptr_basics)] 4#![feature(const_fn_fn_ptr_basics)]
5#![feature(const_in_array_repeat_expressions)]
6#![feature(const_option)]
5 7
6// This mod MUST go first, so that the others see its macros. 8// This mod MUST go first, so that the others see its macros.
7pub(crate) mod fmt; 9pub(crate) mod fmt;
diff --git a/embassy/src/util/signal.rs b/embassy/src/util/signal.rs
index 8e778d1e3..2c9c52f1e 100644
--- a/embassy/src/util/signal.rs
+++ b/embassy/src/util/signal.rs
@@ -1,8 +1,13 @@
1use crate::executor;
1use crate::fmt::panic; 2use crate::fmt::panic;
3use crate::interrupt::OwnedInterrupt;
2use core::cell::UnsafeCell; 4use core::cell::UnsafeCell;
3use core::future::Future; 5use core::future::Future;
4use core::mem; 6use core::mem;
7use core::ptr;
5use core::task::{Context, Poll, Waker}; 8use core::task::{Context, Poll, Waker};
9use cortex_m::peripheral::NVIC;
10use cortex_m::peripheral::{scb, SCB};
6 11
7pub struct Signal<T> { 12pub struct Signal<T> {
8 state: UnsafeCell<State<T>>, 13 state: UnsafeCell<State<T>>,
@@ -67,3 +72,66 @@ impl<T: Send> Signal<T> {
67 cortex_m::interrupt::free(|_| matches!(unsafe { &*self.state.get() }, State::Signaled(_))) 72 cortex_m::interrupt::free(|_| matches!(unsafe { &*self.state.get() }, State::Signaled(_)))
68 } 73 }
69} 74}
75
76struct NrWrap(u8);
77unsafe impl cortex_m::interrupt::Nr for NrWrap {
78 fn nr(&self) -> u8 {
79 self.0
80 }
81}
82
83pub struct InterruptFuture<'a, I: OwnedInterrupt> {
84 interrupt: &'a mut I,
85}
86
87impl<'a, I: OwnedInterrupt> Drop for InterruptFuture<'a, I> {
88 fn drop(&mut self) {
89 self.interrupt.disable();
90 self.interrupt.remove_handler();
91 }
92}
93
94impl<'a, I: OwnedInterrupt> InterruptFuture<'a, I> {
95 pub fn new(interrupt: &'a mut I) -> Self {
96 interrupt.disable();
97 interrupt.set_handler(Self::interrupt_handler, ptr::null_mut());
98 interrupt.unpend();
99 interrupt.enable();
100
101 Self {
102 interrupt: interrupt,
103 }
104 }
105
106 unsafe fn interrupt_handler(ctx: *mut ()) {
107 let irq = match SCB::vect_active() {
108 scb::VectActive::Interrupt { irqn } => irqn,
109 _ => unreachable!(),
110 };
111
112 if ctx as *const _ != ptr::null() {
113 executor::raw::wake_task(ptr::NonNull::new_unchecked(ctx));
114 }
115
116 NVIC::mask(NrWrap(irq));
117 }
118}
119
120impl<'a, I: OwnedInterrupt> Unpin for InterruptFuture<'a, I> {}
121
122impl<'a, I: OwnedInterrupt> Future for InterruptFuture<'a, I> {
123 type Output = ();
124
125 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
126 let s = unsafe { self.get_unchecked_mut() };
127 s.interrupt.set_handler(
128 Self::interrupt_handler,
129 executor::raw::task_from_waker(&cx.waker()).cast().as_ptr(),
130 );
131 if s.interrupt.is_enabled() {
132 Poll::Pending
133 } else {
134 Poll::Ready(())
135 }
136 }
137}