aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2020-12-31 17:59:01 -0600
committerxoviat <[email protected]>2020-12-31 17:59:01 -0600
commitd5cb9bebaa6d33bffa63211ed53ddf8a80ad975b (patch)
treeb564a0d4f0235675460399cfe43487022d682a21
parentcc8d1628597d449e3b2e2e1545af25fc47b0a8a5 (diff)
implement on irqs
-rw-r--r--embassy-stm32f4/src/lib.rs56
-rw-r--r--embassy-stm32f4/src/serial.rs59
2 files changed, 65 insertions, 50 deletions
diff --git a/embassy-stm32f4/src/lib.rs b/embassy-stm32f4/src/lib.rs
index 40a40ef4b..2a5a34a2a 100644
--- a/embassy-stm32f4/src/lib.rs
+++ b/embassy-stm32f4/src/lib.rs
@@ -329,34 +329,34 @@ pub use stm32f4xx_hal::stm32 as pac;
329/// 329///
330/// [`Waker`]: core::task::Waker 330/// [`Waker`]: core::task::Waker
331/// [`Future::poll`]: core::future::Future::poll 331/// [`Future::poll`]: core::future::Future::poll
332macro_rules! waker_interrupt { 332// macro_rules! waker_interrupt {
333 ($INT:ident, $waker:expr) => {{ 333// ($INT:ident, $waker:expr) => {{
334 use core::sync::atomic::{self, Ordering}; 334// use core::sync::atomic::{self, Ordering};
335 use core::task::Waker; 335// use core::task::Waker;
336 use stm32f4xx_hal::pac::{interrupt, Interrupt, NVIC}; 336// use stm32f4xx_hal::pac::{interrupt, Interrupt, NVIC};
337 337//
338 static mut WAKER: Option<Waker> = None; 338// static mut WAKER: Option<Waker> = None;
339 339//
340 #[interrupt] 340// #[interrupt]
341 fn $INT() { 341// fn $INT() {
342 // Safety: This context is disabled while the lower priority context accesses WAKER 342// // Safety: This context is disabled while the lower priority context accesses WAKER
343 if let Some(waker) = unsafe { WAKER.as_ref() } { 343// if let Some(waker) = unsafe { WAKER.as_ref() } {
344 waker.wake_by_ref(); 344// waker.wake_by_ref();
345 345//
346 NVIC::mask(Interrupt::$INT); 346// NVIC::mask(Interrupt::$INT);
347 } 347// }
348 } 348// }
349 349//
350 NVIC::mask(Interrupt::$INT); 350// NVIC::mask(Interrupt::$INT);
351 atomic::compiler_fence(Ordering::Acquire); 351// atomic::compiler_fence(Ordering::Acquire);
352 // Safety: The other relevant context, the interrupt, is disabled 352// // Safety: The other relevant context, the interrupt, is disabled
353 unsafe { WAKER = Some($waker) } 353// unsafe { WAKER = Some($waker) }
354 NVIC::unpend(Interrupt::$INT); 354// NVIC::unpend(Interrupt::$INT);
355 atomic::compiler_fence(Ordering::Release); 355// atomic::compiler_fence(Ordering::Release);
356 // Safety: This is the end of a mask-based critical section 356// // Safety: This is the end of a mask-based critical section
357 unsafe { NVIC::unmask(Interrupt::$INT) } 357// unsafe { NVIC::unmask(Interrupt::$INT) }
358 }}; 358// }};
359} 359// }
360 360
361// This mod MUST go first, so that the others see its macros. 361// This mod MUST go first, so that the others see its macros.
362pub(crate) mod fmt; 362pub(crate) mod fmt;
diff --git a/embassy-stm32f4/src/serial.rs b/embassy-stm32f4/src/serial.rs
index 5042566db..5c3e3f1ac 100644
--- a/embassy-stm32f4/src/serial.rs
+++ b/embassy-stm32f4/src/serial.rs
@@ -4,31 +4,20 @@
4//! Lowest power consumption can only be guaranteed if the send receive futures 4//! Lowest power consumption can only be guaranteed if the send receive futures
5//! are dropped correctly (e.g. not using `mem::forget()`). 5//! are dropped correctly (e.g. not using `mem::forget()`).
6 6
7use core::cell::UnsafeCell;
8use core::cmp::min;
9use core::future::Future; 7use core::future::Future;
10use core::marker::PhantomPinned;
11use core::ops::Deref;
12use core::pin::Pin;
13use core::ptr;
14use core::sync::atomic::{compiler_fence, Ordering};
15use core::task::{Context, Poll}; 8use core::task::{Context, Poll};
16use cortex_m::singleton;
17 9
10use embassy::interrupt::OwnedInterrupt;
18use embassy::util::Signal; 11use embassy::util::Signal;
19use embedded_dma::{StaticReadBuffer, StaticWriteBuffer, WriteBuffer}; 12use embedded_dma::{StaticReadBuffer, StaticWriteBuffer, WriteBuffer};
20 13
21use crate::fmt::assert;
22use crate::hal::dma::config::DmaConfig; 14use crate::hal::dma::config::DmaConfig;
23use crate::hal::dma::traits::{PeriAddress, Stream}; 15use crate::hal::dma::traits::{PeriAddress, Stream};
24use crate::hal::dma::{ 16use crate::hal::dma::{
25 Channel4, Channel7, MemoryToPeripheral, PeripheralToMemory, Stream2, Stream7, StreamsTuple, 17 Channel4, MemoryToPeripheral, PeripheralToMemory, Stream2, Stream7, StreamsTuple, Transfer,
26 Transfer,
27}; 18};
28use crate::hal::gpio::gpioa::{PA10, PA9}; 19use crate::hal::gpio::gpioa::{PA10, PA9};
29use crate::hal::gpio::{Alternate, AF10, AF7, AF9}; 20use crate::hal::gpio::{Alternate, AF7};
30use crate::hal::gpio::{Floating, Input, Output, PushPull};
31use crate::hal::pac;
32use crate::hal::prelude::*; 21use crate::hal::prelude::*;
33use crate::hal::rcc::Clocks; 22use crate::hal::rcc::Clocks;
34use crate::hal::serial::config::{ 23use crate::hal::serial::config::{
@@ -42,8 +31,6 @@ use crate::interrupt;
42use crate::pac::Interrupt; 31use crate::pac::Interrupt;
43use crate::pac::{DMA2, USART1}; 32use crate::pac::{DMA2, USART1};
44 33
45use embedded_hal::digital::v2::OutputPin;
46
47/// Interface to the Serial peripheral 34/// Interface to the Serial peripheral
48pub struct Serial<USART: PeriAddress<MemSize = u8>, TSTREAM: Stream, RSTREAM: Stream> { 35pub struct Serial<USART: PeriAddress<MemSize = u8>, TSTREAM: Stream, RSTREAM: Stream> {
49 // tx_transfer: Transfer<Stream7<DMA2>, Channel4, USART1, MemoryToPeripheral, &mut [u8; 20]>, 36 // tx_transfer: Transfer<Stream7<DMA2>, Channel4, USART1, MemoryToPeripheral, &mut [u8; 20]>,
@@ -55,7 +42,7 @@ pub struct Serial<USART: PeriAddress<MemSize = u8>, TSTREAM: Stream, RSTREAM: St
55 42
56struct State { 43struct State {
57 tx_done: Signal<()>, 44 tx_done: Signal<()>,
58 rx_done: Signal<u32>, 45 rx_done: Signal<()>,
59} 46}
60 47
61static STATE: State = State { 48static STATE: State = State {
@@ -93,6 +80,15 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
93 80
94 // serial.listen(SerialEvent::Idle); 81 // serial.listen(SerialEvent::Idle);
95 82
83 // Register ISR
84 tx_int.set_handler(Self::on_tx_irq);
85 tx_int.unpend();
86 tx_int.enable();
87
88 rx_int.set_handler(Self::on_rx_irq);
89 rx_int.unpend();
90 rx_int.enable();
91
96 let streams = StreamsTuple::new(dma); 92 let streams = StreamsTuple::new(dma);
97 93
98 Serial { 94 Serial {
@@ -102,6 +98,13 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
102 } 98 }
103 } 99 }
104 100
101 unsafe fn on_tx_irq() {
102 STATE.tx_done.signal(());
103 }
104
105 unsafe fn on_rx_irq() {
106 STATE.rx_done.signal(());
107 }
105 /// Sends serial data. 108 /// Sends serial data.
106 /// 109 ///
107 /// `tx_buffer` is marked as static as per `embedded-dma` requirements. 110 /// `tx_buffer` is marked as static as per `embedded-dma` requirements.
@@ -127,6 +130,8 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
127 .double_buffer(false), 130 .double_buffer(false),
128 ); 131 );
129 132
133 STATE.tx_done.reset();
134
130 SendFuture { 135 SendFuture {
131 Serial: self, 136 Serial: self,
132 tx_transfer: Some(tx_transfer), 137 tx_transfer: Some(tx_transfer),
@@ -166,6 +171,8 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
166 .double_buffer(false), 171 .double_buffer(false),
167 ); 172 );
168 173
174 STATE.rx_done.reset();
175
169 ReceiveFuture { 176 ReceiveFuture {
170 Serial: self, 177 Serial: self,
171 rx_transfer: Some(rx_transfer), 178 rx_transfer: Some(rx_transfer),
@@ -213,11 +220,12 @@ where
213 220
214 Poll::Ready(()) 221 Poll::Ready(())
215 } else { 222 } else {
216 waker_interrupt!(DMA2_STREAM7, cx.waker().clone()); 223 // waker_interrupt!(DMA2_STREAM7, cx.waker().clone());
217 taken.start(|usart| {}); 224 taken.start(|_usart| {});
218 tx_transfer.replace(taken); 225 tx_transfer.replace(taken);
219 226
220 Poll::Pending 227 // Poll::Pending
228 STATE.tx_done.poll_wait(cx)
221 } 229 }
222 } 230 }
223} 231}
@@ -263,11 +271,18 @@ where
263 271
264 Poll::Ready(buf) 272 Poll::Ready(buf)
265 } else { 273 } else {
266 waker_interrupt!(DMA2_STREAM2, cx.waker().clone()); 274 // waker_interrupt!(DMA2_STREAM2, cx.waker().clone());
267 275
268 taken.start(|usart| {}); 276 taken.start(|_usart| {});
269 rx_transfer.replace(taken); 277 rx_transfer.replace(taken);
270 278
279 STATE.rx_done.poll_wait(cx);
280
281 /*
282 Note: we have to do this because rx_transfer owns the buffer and we can't
283 access it until the transfer is completed. Therefore we can't pass
284 the buffer to poll_wait, but we still need to be woken.
285 */
271 Poll::Pending 286 Poll::Pending
272 } 287 }
273 } 288 }