aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-03-20 03:37:48 +0100
committerDario Nieuwenhuis <[email protected]>2021-03-29 00:58:57 +0200
commitba6e0a405831793ab1e5acaa4694171199012df0 (patch)
treef8f4eeda64d5d516eb3d96f3bd3c22d72932205f
parent15eb46ec714beaf443577f2f7bef4610d22f54f5 (diff)
util: add wake_on_interrupt.
This is a lighter version of InterruptFuture.
-rw-r--r--embassy/src/util/signal.rs42
1 files changed, 27 insertions, 15 deletions
diff --git a/embassy/src/util/signal.rs b/embassy/src/util/signal.rs
index 0fd5c9275..749b32247 100644
--- a/embassy/src/util/signal.rs
+++ b/embassy/src/util/signal.rs
@@ -5,6 +5,8 @@ use core::ptr;
5use core::task::{Context, Poll, Waker}; 5use core::task::{Context, Poll, Waker};
6use cortex_m::peripheral::NVIC; 6use cortex_m::peripheral::NVIC;
7use cortex_m::peripheral::{scb, SCB}; 7use cortex_m::peripheral::{scb, SCB};
8use executor::raw::TaskHeader;
9use ptr::NonNull;
8 10
9use crate::executor; 11use crate::executor;
10use crate::fmt::panic; 12use crate::fmt::panic;
@@ -79,6 +81,30 @@ impl<T: Send> Signal<T> {
79 } 81 }
80} 82}
81 83
84// ==========
85
86pub fn wake_on_interrupt(interrupt: &mut impl Interrupt, waker: &Waker) {
87 interrupt.disable();
88 interrupt.set_handler(irq_wake_handler);
89 interrupt.set_handler_context(unsafe { executor::raw::task_from_waker(waker) }.as_ptr() as _);
90 interrupt.enable();
91}
92
93unsafe fn irq_wake_handler(ctx: *mut ()) {
94 if let Some(task) = NonNull::new(ctx as *mut TaskHeader) {
95 executor::raw::wake_task(task);
96 }
97
98 let irq = match SCB::vect_active() {
99 scb::VectActive::Interrupt { irqn } => irqn,
100 _ => unreachable!(),
101 };
102
103 NVIC::mask(crate::interrupt::NrWrap(irq as u16));
104}
105
106// ==========
107
82struct NrWrap(u8); 108struct NrWrap(u8);
83unsafe impl cortex_m::interrupt::Nr for NrWrap { 109unsafe impl cortex_m::interrupt::Nr for NrWrap {
84 fn nr(&self) -> u8 { 110 fn nr(&self) -> u8 {
@@ -119,26 +145,13 @@ impl<'a, I: Interrupt> Drop for InterruptFuture<'a, I> {
119impl<'a, I: Interrupt> InterruptFuture<'a, I> { 145impl<'a, I: Interrupt> InterruptFuture<'a, I> {
120 pub fn new(interrupt: &'a mut I) -> Self { 146 pub fn new(interrupt: &'a mut I) -> Self {
121 interrupt.disable(); 147 interrupt.disable();
122 interrupt.set_handler(Self::interrupt_handler); 148 interrupt.set_handler(irq_wake_handler);
123 interrupt.set_handler_context(ptr::null_mut()); 149 interrupt.set_handler_context(ptr::null_mut());
124 interrupt.unpend(); 150 interrupt.unpend();
125 interrupt.enable(); 151 interrupt.enable();
126 152
127 Self { interrupt } 153 Self { interrupt }
128 } 154 }
129
130 unsafe fn interrupt_handler(ctx: *mut ()) {
131 let irq = match SCB::vect_active() {
132 scb::VectActive::Interrupt { irqn } => irqn,
133 _ => unreachable!(),
134 };
135
136 if !ctx.is_null() {
137 executor::raw::wake_task(ptr::NonNull::new_unchecked(ctx as _));
138 }
139
140 NVIC::mask(crate::interrupt::NrWrap(irq as u16));
141 }
142} 155}
143 156
144impl<'a, I: Interrupt> Unpin for InterruptFuture<'a, I> {} 157impl<'a, I: Interrupt> Unpin for InterruptFuture<'a, I> {}
@@ -148,7 +161,6 @@ impl<'a, I: Interrupt> Future for InterruptFuture<'a, I> {
148 161
149 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { 162 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
150 let s = unsafe { self.get_unchecked_mut() }; 163 let s = unsafe { self.get_unchecked_mut() };
151 s.interrupt.set_handler(Self::interrupt_handler);
152 s.interrupt.set_handler_context(unsafe { 164 s.interrupt.set_handler_context(unsafe {
153 executor::raw::task_from_waker(&cx.waker()).cast().as_ptr() 165 executor::raw::task_from_waker(&cx.waker()).cast().as_ptr()
154 }); 166 });