aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2021-01-01 14:59:57 -0600
committerxoviat <[email protected]>2021-01-01 14:59:57 -0600
commit2ee2d184654380c84ee8ea62d00ab701ceacd13c (patch)
treecab5b8a693565d8bf88accdc3bd8e41cad41f101
parentd5cb9bebaa6d33bffa63211ed53ddf8a80ad975b (diff)
simplify impl. and add interupt idea
-rw-r--r--embassy-stm32f4/src/serial.rs209
-rw-r--r--examples-stm32f4/src/serial.rs1
2 files changed, 63 insertions, 147 deletions
diff --git a/embassy-stm32f4/src/serial.rs b/embassy-stm32f4/src/serial.rs
index 5c3e3f1ac..7efb4a0bb 100644
--- a/embassy-stm32f4/src/serial.rs
+++ b/embassy-stm32f4/src/serial.rs
@@ -43,11 +43,13 @@ pub struct Serial<USART: PeriAddress<MemSize = u8>, TSTREAM: Stream, RSTREAM: St
43struct State { 43struct State {
44 tx_done: Signal<()>, 44 tx_done: Signal<()>,
45 rx_done: Signal<()>, 45 rx_done: Signal<()>,
46 dma_done: Signal<()>,
46} 47}
47 48
48static STATE: State = State { 49static STATE: State = State {
49 tx_done: Signal::new(), 50 tx_done: Signal::new(),
50 rx_done: Signal::new(), 51 rx_done: Signal::new(),
52 dma_done: Signal::new(),
51}; 53};
52 54
53impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> { 55impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
@@ -56,13 +58,14 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
56 rxd: PA10<Alternate<AF7>>, 58 rxd: PA10<Alternate<AF7>>,
57 tx_int: interrupt::DMA2_STREAM2Interrupt, 59 tx_int: interrupt::DMA2_STREAM2Interrupt,
58 rx_int: interrupt::DMA2_STREAM7Interrupt, 60 rx_int: interrupt::DMA2_STREAM7Interrupt,
61 usart_int: interrupt::USART1Interrupt,
59 dma: DMA2, 62 dma: DMA2,
60 usart: USART1, 63 usart: USART1,
61 parity: Parity, 64 parity: Parity,
62 baudrate: Bps, 65 baudrate: Bps,
63 clocks: Clocks, 66 clocks: Clocks,
64 ) -> Self { 67 ) -> Self {
65 let serial = HalSerial::usart1( 68 let mut serial = HalSerial::usart1(
66 usart, 69 usart,
67 (txd, rxd), 70 (txd, rxd),
68 SerialConfig { 71 SerialConfig {
@@ -76,9 +79,10 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
76 ) 79 )
77 .unwrap(); 80 .unwrap();
78 81
79 let (usart, _) = serial.release(); 82 serial.listen(SerialEvent::Idle);
83 serial.listen(SerialEvent::Txe);
80 84
81 // serial.listen(SerialEvent::Idle); 85 let (usart, _) = serial.release();
82 86
83 // Register ISR 87 // Register ISR
84 tx_int.set_handler(Self::on_tx_irq); 88 tx_int.set_handler(Self::on_tx_irq);
@@ -89,6 +93,10 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
89 rx_int.unpend(); 93 rx_int.unpend();
90 rx_int.enable(); 94 rx_int.enable();
91 95
96 // usart_int.set_handler(Self::on_usart_irq);
97 // usart_int.unpend();
98 // usart_int.enable();
99
92 let streams = StreamsTuple::new(dma); 100 let streams = StreamsTuple::new(dma);
93 101
94 Serial { 102 Serial {
@@ -105,38 +113,50 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
105 unsafe fn on_rx_irq() { 113 unsafe fn on_rx_irq() {
106 STATE.rx_done.signal(()); 114 STATE.rx_done.signal(());
107 } 115 }
116
117 unsafe fn on_usart_irq() {
118 /*
119 TODO: Signal tx_done if txe
120 */
121
122 /*
123 TODO: Signal rx_done if idle
124 */
125
126 // STATE.rx_done.signal(());
127 }
108 /// Sends serial data. 128 /// Sends serial data.
109 /// 129 ///
110 /// `tx_buffer` is marked as static as per `embedded-dma` requirements. 130 /// `tx_buffer` is marked as static as per `embedded-dma` requirements.
111 /// It it safe to use a buffer with a non static lifetime if memory is not 131 /// It it safe to use a buffer with a non static lifetime if memory is not
112 /// reused until the future has finished. 132 /// reused until the future has finished.
113 pub fn send<'a, B>( 133 pub fn send<'a, B>(&'a mut self, tx_buffer: B) -> impl Future<Output = ()> + 'a
114 &'a mut self,
115 tx_buffer: B,
116 ) -> SendFuture<'a, B, USART1, Stream7<DMA2>, Stream2<DMA2>, Channel4>
117 where 134 where
118 B: WriteBuffer<Word = u8> + 'static, 135 B: WriteBuffer<Word = u8> + 'static,
119 { 136 {
120 let tx_stream = self.tx_stream.take().unwrap(); 137 let tx_stream = self.tx_stream.take().unwrap();
121 let usart = self.usart.take().unwrap(); 138 let usart = self.usart.take().unwrap();
122 let mut tx_transfer = Transfer::init(
123 tx_stream,
124 usart,
125 tx_buffer,
126 None,
127 DmaConfig::default()
128 .transfer_complete_interrupt(true)
129 .memory_increment(true)
130 .double_buffer(false),
131 );
132
133 STATE.tx_done.reset(); 139 STATE.tx_done.reset();
134 140
135 SendFuture { 141 async move {
136 Serial: self, 142 let mut tx_transfer = Transfer::init(
137 tx_transfer: Some(tx_transfer), 143 tx_stream,
138 // tx_stream: Some(tx_stream), 144 usart,
139 // usart: Some(usart), 145 tx_buffer,
146 None,
147 DmaConfig::default()
148 .transfer_complete_interrupt(true)
149 .memory_increment(true)
150 .double_buffer(false),
151 );
152
153 tx_transfer.start(|_usart| {});
154
155 STATE.tx_done.wait().await;
156
157 let (tx_stream, usart, _buf, _) = tx_transfer.free();
158 self.tx_stream.replace(tx_stream);
159 self.usart.replace(usart);
140 } 160 }
141 } 161 }
142 162
@@ -150,140 +170,35 @@ impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> {
150 /// `rx_buffer` is marked as static as per `embedded-dma` requirements. 170 /// `rx_buffer` is marked as static as per `embedded-dma` requirements.
151 /// It it safe to use a buffer with a non static lifetime if memory is not 171 /// It it safe to use a buffer with a non static lifetime if memory is not
152 /// reused until the future has finished. 172 /// reused until the future has finished.
153 pub fn receive<'a, B>( 173 pub fn receive<'a, B>(&'a mut self, rx_buffer: B) -> impl Future<Output = B> + 'a
154 &'a mut self,
155 rx_buffer: B,
156 ) -> ReceiveFuture<'a, B, USART1, Stream7<DMA2>, Stream2<DMA2>, Channel4>
157 where 174 where
158 B: WriteBuffer<Word = u8> + 'static, 175 B: WriteBuffer<Word = u8> + 'static + Unpin,
159 { 176 {
160 let rx_stream = self.rx_stream.take().unwrap(); 177 let rx_stream = self.rx_stream.take().unwrap();
161 let usart = self.usart.take().unwrap(); 178 let usart = self.usart.take().unwrap();
162 let mut rx_transfer = Transfer::init(
163 rx_stream,
164 usart,
165 rx_buffer,
166 None,
167 DmaConfig::default()
168 .transfer_complete_interrupt(true)
169 .half_transfer_interrupt(true)
170 .memory_increment(true)
171 .double_buffer(false),
172 );
173
174 STATE.rx_done.reset(); 179 STATE.rx_done.reset();
175 180
176 ReceiveFuture { 181 async move {
177 Serial: self, 182 let mut rx_transfer = Transfer::init(
178 rx_transfer: Some(rx_transfer), 183 rx_stream,
179 } 184 usart,
180 } 185 rx_buffer,
181} 186 None,
182 187 DmaConfig::default()
183/// Future for the [`LowPowerSerial::send()`] method. 188 .transfer_complete_interrupt(true)
184pub struct SendFuture< 189 .memory_increment(true)
185 'a, 190 .double_buffer(false),
186 B: WriteBuffer<Word = u8> + 'static, 191 );
187 USART: PeriAddress<MemSize = u8>,
188 TSTREAM: Stream,
189 RSTREAM: Stream,
190 CHANNEL,
191> {
192 Serial: &'a mut Serial<USART, TSTREAM, RSTREAM>,
193 tx_transfer: Option<Transfer<TSTREAM, CHANNEL, USART, MemoryToPeripheral, B>>,
194}
195
196// impl<'a, B> Drop for SendFuture<'a, B>
197// where
198// B: WriteBuffer<Word = u8> + 'static,
199// {
200// fn drop(self: &mut Self) {}
201// }
202
203impl<'a, B> Future for SendFuture<'a, B, USART1, Stream7<DMA2>, Stream2<DMA2>, Channel4>
204where
205 B: WriteBuffer<Word = u8> + 'static,
206{
207 type Output = ();
208
209 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
210 let Self {
211 Serial,
212 tx_transfer,
213 } = unsafe { self.get_unchecked_mut() };
214 let mut taken = tx_transfer.take().unwrap();
215 if Stream7::<DMA2>::get_transfer_complete_flag() {
216 let (tx_stream, usart, buf, _) = taken.free();
217
218 Serial.tx_stream.replace(tx_stream);
219 Serial.usart.replace(usart);
220
221 Poll::Ready(())
222 } else {
223 // waker_interrupt!(DMA2_STREAM7, cx.waker().clone());
224 taken.start(|_usart| {});
225 tx_transfer.replace(taken);
226
227 // Poll::Pending
228 STATE.tx_done.poll_wait(cx)
229 }
230 }
231}
232
233/// Future for the [`Serial::receive()`] method.
234pub struct ReceiveFuture<
235 'a,
236 B: WriteBuffer<Word = u8> + 'static,
237 USART: PeriAddress<MemSize = u8>,
238 TSTREAM: Stream,
239 RSTREAM: Stream,
240 CHANNEL,
241> {
242 Serial: &'a mut Serial<USART, TSTREAM, RSTREAM>,
243 rx_transfer: Option<Transfer<RSTREAM, CHANNEL, USART, PeripheralToMemory, B>>,
244}
245
246// impl<'a, B> Drop for ReceiveFuture<'a, B, USART1, Stream7<DMA2>, Channel4>
247// where
248// B: WriteBuffer<Word = u8> + 'static,
249// {
250// fn drop(self: &mut Self) {}
251// }
252
253impl<'a, B> Future for ReceiveFuture<'a, B, USART1, Stream7<DMA2>, Stream2<DMA2>, Channel4>
254where
255 B: WriteBuffer<Word = u8> + 'static + Unpin,
256{
257 type Output = B;
258
259 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<B> {
260 let Self {
261 Serial,
262 rx_transfer,
263 } = unsafe { self.get_unchecked_mut() };
264 let mut taken = rx_transfer.take().unwrap();
265
266 if Stream7::<DMA2>::get_transfer_complete_flag() {
267 let (rx_stream, usart, buf, _) = rx_transfer.take().unwrap().free();
268
269 Serial.rx_stream.replace(rx_stream);
270 Serial.usart.replace(usart);
271 192
272 Poll::Ready(buf) 193 rx_transfer.start(|_usart| {});
273 } else {
274 // waker_interrupt!(DMA2_STREAM2, cx.waker().clone());
275 194
276 taken.start(|_usart| {}); 195 STATE.rx_done.wait().await;
277 rx_transfer.replace(taken);
278 196
279 STATE.rx_done.poll_wait(cx); 197 let (rx_stream, usart, buf, _) = rx_transfer.free();
198 self.rx_stream.replace(rx_stream);
199 self.usart.replace(usart);
280 200
281 /* 201 buf
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 */
286 Poll::Pending
287 } 202 }
288 } 203 }
289} 204}
diff --git a/examples-stm32f4/src/serial.rs b/examples-stm32f4/src/serial.rs
index 296da4043..6c757dd2f 100644
--- a/examples-stm32f4/src/serial.rs
+++ b/examples-stm32f4/src/serial.rs
@@ -32,6 +32,7 @@ async fn run(dp: stm32::Peripherals, cp: cortex_m::Peripherals) {
32 gpioa.pa10.into_alternate_af7(), 32 gpioa.pa10.into_alternate_af7(),
33 interrupt::take!(DMA2_STREAM2), 33 interrupt::take!(DMA2_STREAM2),
34 interrupt::take!(DMA2_STREAM7), 34 interrupt::take!(DMA2_STREAM7),
35 interrupt::take!(USART1),
35 dp.DMA2, 36 dp.DMA2,
36 dp.USART1, 37 dp.USART1,
37 config::Parity::ParityNone, 38 config::Parity::ParityNone,