diff options
| author | Dario Nieuwenhuis <[email protected]> | 2021-03-20 03:37:48 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2021-03-29 00:58:57 +0200 |
| commit | ba6e0a405831793ab1e5acaa4694171199012df0 (patch) | |
| tree | f8f4eeda64d5d516eb3d96f3bd3c22d72932205f | |
| parent | 15eb46ec714beaf443577f2f7bef4610d22f54f5 (diff) | |
util: add wake_on_interrupt.
This is a lighter version of InterruptFuture.
| -rw-r--r-- | embassy/src/util/signal.rs | 42 |
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; | |||
| 5 | use core::task::{Context, Poll, Waker}; | 5 | use core::task::{Context, Poll, Waker}; |
| 6 | use cortex_m::peripheral::NVIC; | 6 | use cortex_m::peripheral::NVIC; |
| 7 | use cortex_m::peripheral::{scb, SCB}; | 7 | use cortex_m::peripheral::{scb, SCB}; |
| 8 | use executor::raw::TaskHeader; | ||
| 9 | use ptr::NonNull; | ||
| 8 | 10 | ||
| 9 | use crate::executor; | 11 | use crate::executor; |
| 10 | use crate::fmt::panic; | 12 | use crate::fmt::panic; |
| @@ -79,6 +81,30 @@ impl<T: Send> Signal<T> { | |||
| 79 | } | 81 | } |
| 80 | } | 82 | } |
| 81 | 83 | ||
| 84 | // ========== | ||
| 85 | |||
| 86 | pub 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 | |||
| 93 | unsafe 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 | |||
| 82 | struct NrWrap(u8); | 108 | struct NrWrap(u8); |
| 83 | unsafe impl cortex_m::interrupt::Nr for NrWrap { | 109 | unsafe 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> { | |||
| 119 | impl<'a, I: Interrupt> InterruptFuture<'a, I> { | 145 | impl<'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 | ||
| 144 | impl<'a, I: Interrupt> Unpin for InterruptFuture<'a, I> {} | 157 | impl<'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 | }); |
