diff options
| author | xoviat <[email protected]> | 2021-01-04 12:48:13 -0600 |
|---|---|---|
| committer | xoviat <[email protected]> | 2021-01-04 12:48:13 -0600 |
| commit | 9bf09488f10b65401ec4c830c5b974c19508624f (patch) | |
| tree | 35a57bee8d0f51f07ce46b06009b7a3c9307027e | |
| parent | 2ee2d184654380c84ee8ea62d00ab701ceacd13c (diff) | |
fix interrupts
| -rw-r--r-- | embassy-stm32f4/src/serial.rs | 90 |
1 files changed, 55 insertions, 35 deletions
diff --git a/embassy-stm32f4/src/serial.rs b/embassy-stm32f4/src/serial.rs index 7efb4a0bb..cc55ef325 100644 --- a/embassy-stm32f4/src/serial.rs +++ b/embassy-stm32f4/src/serial.rs | |||
| @@ -5,6 +5,8 @@ | |||
| 5 | //! are dropped correctly (e.g. not using `mem::forget()`). | 5 | //! are dropped correctly (e.g. not using `mem::forget()`). |
| 6 | 6 | ||
| 7 | use core::future::Future; | 7 | use core::future::Future; |
| 8 | use core::ptr; | ||
| 9 | use core::sync::atomic::{self, Ordering}; | ||
| 8 | use core::task::{Context, Poll}; | 10 | use core::task::{Context, Poll}; |
| 9 | 11 | ||
| 10 | use embassy::interrupt::OwnedInterrupt; | 12 | use embassy::interrupt::OwnedInterrupt; |
| @@ -33,31 +35,32 @@ use crate::pac::{DMA2, USART1}; | |||
| 33 | 35 | ||
| 34 | /// Interface to the Serial peripheral | 36 | /// Interface to the Serial peripheral |
| 35 | pub struct Serial<USART: PeriAddress<MemSize = u8>, TSTREAM: Stream, RSTREAM: Stream> { | 37 | pub struct Serial<USART: PeriAddress<MemSize = u8>, TSTREAM: Stream, RSTREAM: Stream> { |
| 36 | // tx_transfer: Transfer<Stream7<DMA2>, Channel4, USART1, MemoryToPeripheral, &mut [u8; 20]>, | ||
| 37 | // rx_transfer: Transfer<Stream2<DMA2>, Channel4, USART1, PeripheralToMemory, &mut [u8; 20]>, | ||
| 38 | tx_stream: Option<TSTREAM>, | 38 | tx_stream: Option<TSTREAM>, |
| 39 | rx_stream: Option<RSTREAM>, | 39 | rx_stream: Option<RSTREAM>, |
| 40 | usart: Option<USART>, | 40 | usart: Option<USART>, |
| 41 | tx_int: interrupt::DMA2_STREAM7Interrupt, | ||
| 42 | rx_int: interrupt::DMA2_STREAM2Interrupt, | ||
| 43 | usart_int: interrupt::USART1Interrupt, | ||
| 41 | } | 44 | } |
| 42 | 45 | ||
| 43 | struct State { | 46 | struct State { |
| 44 | tx_done: Signal<()>, | 47 | tx_int: Signal<()>, |
| 45 | rx_done: Signal<()>, | 48 | rx_int: Signal<()>, |
| 46 | dma_done: Signal<()>, | ||
| 47 | } | 49 | } |
| 48 | 50 | ||
| 49 | static STATE: State = State { | 51 | static STATE: State = State { |
| 50 | tx_done: Signal::new(), | 52 | tx_int: Signal::new(), |
| 51 | rx_done: Signal::new(), | 53 | rx_int: Signal::new(), |
| 52 | dma_done: Signal::new(), | ||
| 53 | }; | 54 | }; |
| 54 | 55 | ||
| 56 | static mut INSTANCE: *const Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> = ptr::null_mut(); | ||
| 57 | |||
| 55 | impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> { | 58 | impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> { |
| 56 | pub fn new( | 59 | pub fn new( |
| 57 | txd: PA9<Alternate<AF7>>, | 60 | txd: PA9<Alternate<AF7>>, |
| 58 | rxd: PA10<Alternate<AF7>>, | 61 | rxd: PA10<Alternate<AF7>>, |
| 59 | tx_int: interrupt::DMA2_STREAM2Interrupt, | 62 | tx_int: interrupt::DMA2_STREAM7Interrupt, |
| 60 | rx_int: interrupt::DMA2_STREAM7Interrupt, | 63 | rx_int: interrupt::DMA2_STREAM2Interrupt, |
| 61 | usart_int: interrupt::USART1Interrupt, | 64 | usart_int: interrupt::USART1Interrupt, |
| 62 | dma: DMA2, | 65 | dma: DMA2, |
| 63 | usart: USART1, | 66 | usart: USART1, |
| @@ -80,20 +83,14 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> { | |||
| 80 | .unwrap(); | 83 | .unwrap(); |
| 81 | 84 | ||
| 82 | serial.listen(SerialEvent::Idle); | 85 | serial.listen(SerialEvent::Idle); |
| 83 | serial.listen(SerialEvent::Txe); | 86 | // serial.listen(SerialEvent::Txe); |
| 84 | 87 | ||
| 85 | let (usart, _) = serial.release(); | 88 | let (usart, _) = serial.release(); |
| 86 | 89 | ||
| 87 | // Register ISR | 90 | // Register ISR |
| 88 | tx_int.set_handler(Self::on_tx_irq); | 91 | tx_int.set_handler(Self::on_tx_irq); |
| 89 | tx_int.unpend(); | ||
| 90 | tx_int.enable(); | ||
| 91 | |||
| 92 | rx_int.set_handler(Self::on_rx_irq); | 92 | rx_int.set_handler(Self::on_rx_irq); |
| 93 | rx_int.unpend(); | 93 | usart_int.set_handler(Self::on_rx_irq); |
| 94 | rx_int.enable(); | ||
| 95 | |||
| 96 | // usart_int.set_handler(Self::on_usart_irq); | ||
| 97 | // usart_int.unpend(); | 94 | // usart_int.unpend(); |
| 98 | // usart_int.enable(); | 95 | // usart_int.enable(); |
| 99 | 96 | ||
| @@ -103,40 +100,56 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> { | |||
| 103 | tx_stream: Some(streams.7), | 100 | tx_stream: Some(streams.7), |
| 104 | rx_stream: Some(streams.2), | 101 | rx_stream: Some(streams.2), |
| 105 | usart: Some(usart), | 102 | usart: Some(usart), |
| 103 | tx_int: tx_int, | ||
| 104 | rx_int: rx_int, | ||
| 105 | usart_int: usart_int, | ||
| 106 | } | 106 | } |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | unsafe fn on_tx_irq() { | 109 | unsafe fn on_tx_irq() { |
| 110 | STATE.tx_done.signal(()); | 110 | let s = &(*INSTANCE); |
| 111 | |||
| 112 | s.tx_int.disable(); | ||
| 113 | |||
| 114 | STATE.tx_int.signal(()); | ||
| 111 | } | 115 | } |
| 112 | 116 | ||
| 113 | unsafe fn on_rx_irq() { | 117 | unsafe fn on_rx_irq() { |
| 114 | STATE.rx_done.signal(()); | 118 | let s = &(*INSTANCE); |
| 119 | |||
| 120 | atomic::compiler_fence(Ordering::Acquire); | ||
| 121 | s.rx_int.disable(); | ||
| 122 | s.usart_int.disable(); | ||
| 123 | atomic::compiler_fence(Ordering::Release); | ||
| 124 | |||
| 125 | STATE.rx_int.signal(()); | ||
| 115 | } | 126 | } |
| 116 | 127 | ||
| 117 | unsafe fn on_usart_irq() { | 128 | unsafe fn on_usart_irq() { |
| 118 | /* | 129 | let s = &(*INSTANCE); |
| 119 | TODO: Signal tx_done if txe | ||
| 120 | */ | ||
| 121 | 130 | ||
| 122 | /* | 131 | atomic::compiler_fence(Ordering::Acquire); |
| 123 | TODO: Signal rx_done if idle | 132 | s.rx_int.disable(); |
| 124 | */ | 133 | s.usart_int.disable(); |
| 134 | atomic::compiler_fence(Ordering::Release); | ||
| 125 | 135 | ||
| 126 | // STATE.rx_done.signal(()); | 136 | STATE.rx_int.signal(()); |
| 127 | } | 137 | } |
| 138 | |||
| 128 | /// Sends serial data. | 139 | /// Sends serial data. |
| 129 | /// | 140 | /// |
| 130 | /// `tx_buffer` is marked as static as per `embedded-dma` requirements. | 141 | /// `tx_buffer` is marked as static as per `embedded-dma` requirements. |
| 131 | /// It it safe to use a buffer with a non static lifetime if memory is not | 142 | /// It it safe to use a buffer with a non static lifetime if memory is not |
| 132 | /// reused until the future has finished. | 143 | /// reused until the future has finished. |
| 133 | pub fn send<'a, B>(&'a mut self, tx_buffer: B) -> impl Future<Output = ()> + 'a | 144 | pub fn send<'a, B: 'a>(&'a mut self, tx_buffer: B) -> impl Future<Output = ()> + 'a |
| 134 | where | 145 | where |
| 135 | B: WriteBuffer<Word = u8> + 'static, | 146 | B: StaticWriteBuffer<Word = u8>, |
| 136 | { | 147 | { |
| 148 | unsafe { INSTANCE = self }; | ||
| 149 | |||
| 137 | let tx_stream = self.tx_stream.take().unwrap(); | 150 | let tx_stream = self.tx_stream.take().unwrap(); |
| 138 | let usart = self.usart.take().unwrap(); | 151 | let usart = self.usart.take().unwrap(); |
| 139 | STATE.tx_done.reset(); | 152 | STATE.tx_int.reset(); |
| 140 | 153 | ||
| 141 | async move { | 154 | async move { |
| 142 | let mut tx_transfer = Transfer::init( | 155 | let mut tx_transfer = Transfer::init( |
| @@ -150,9 +163,11 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> { | |||
| 150 | .double_buffer(false), | 163 | .double_buffer(false), |
| 151 | ); | 164 | ); |
| 152 | 165 | ||
| 166 | self.tx_int.unpend(); | ||
| 167 | self.tx_int.enable(); | ||
| 153 | tx_transfer.start(|_usart| {}); | 168 | tx_transfer.start(|_usart| {}); |
| 154 | 169 | ||
| 155 | STATE.tx_done.wait().await; | 170 | STATE.tx_int.wait().await; |
| 156 | 171 | ||
| 157 | let (tx_stream, usart, _buf, _) = tx_transfer.free(); | 172 | let (tx_stream, usart, _buf, _) = tx_transfer.free(); |
| 158 | self.tx_stream.replace(tx_stream); | 173 | self.tx_stream.replace(tx_stream); |
| @@ -170,13 +185,15 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> { | |||
| 170 | /// `rx_buffer` is marked as static as per `embedded-dma` requirements. | 185 | /// `rx_buffer` is marked as static as per `embedded-dma` requirements. |
| 171 | /// It it safe to use a buffer with a non static lifetime if memory is not | 186 | /// It it safe to use a buffer with a non static lifetime if memory is not |
| 172 | /// reused until the future has finished. | 187 | /// reused until the future has finished. |
| 173 | pub fn receive<'a, B>(&'a mut self, rx_buffer: B) -> impl Future<Output = B> + 'a | 188 | pub fn receive<'a, B: 'a>(&'a mut self, rx_buffer: B) -> impl Future<Output = B> + 'a |
| 174 | where | 189 | where |
| 175 | B: WriteBuffer<Word = u8> + 'static + Unpin, | 190 | B: StaticWriteBuffer<Word = u8> + Unpin, |
| 176 | { | 191 | { |
| 192 | unsafe { INSTANCE = self }; | ||
| 193 | |||
| 177 | let rx_stream = self.rx_stream.take().unwrap(); | 194 | let rx_stream = self.rx_stream.take().unwrap(); |
| 178 | let usart = self.usart.take().unwrap(); | 195 | let usart = self.usart.take().unwrap(); |
| 179 | STATE.rx_done.reset(); | 196 | STATE.rx_int.reset(); |
| 180 | 197 | ||
| 181 | async move { | 198 | async move { |
| 182 | let mut rx_transfer = Transfer::init( | 199 | let mut rx_transfer = Transfer::init( |
| @@ -190,9 +207,12 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> { | |||
| 190 | .double_buffer(false), | 207 | .double_buffer(false), |
| 191 | ); | 208 | ); |
| 192 | 209 | ||
| 210 | self.rx_int.unpend(); | ||
| 211 | self.rx_int.enable(); | ||
| 212 | |||
| 193 | rx_transfer.start(|_usart| {}); | 213 | rx_transfer.start(|_usart| {}); |
| 194 | 214 | ||
| 195 | STATE.rx_done.wait().await; | 215 | STATE.rx_int.wait().await; |
| 196 | 216 | ||
| 197 | let (rx_stream, usart, buf, _) = rx_transfer.free(); | 217 | let (rx_stream, usart, buf, _) = rx_transfer.free(); |
| 198 | self.rx_stream.replace(rx_stream); | 218 | self.rx_stream.replace(rx_stream); |
