aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-03-26 23:22:06 +0100
committerDario Nieuwenhuis <[email protected]>2021-03-29 00:58:58 +0200
commit7a41541ab279e200b7bda93704e8ba66df52f5b4 (patch)
tree412154b40724427638ae2976697d5a2daed0a4b2
parent0e8bb5dc0b59a490f679f82c3efc6c2994c2d1d9 (diff)
nrf/uarte: use Peripheral, wait for stop on drop.
-rw-r--r--embassy-nrf/src/uarte.rs239
1 files changed, 101 insertions, 138 deletions
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs
index 9a6e49907..06493da69 100644
--- a/embassy-nrf/src/uarte.rs
+++ b/embassy-nrf/src/uarte.rs
@@ -3,10 +3,11 @@
3use core::future::Future; 3use core::future::Future;
4use core::marker::PhantomData; 4use core::marker::PhantomData;
5use core::pin::Pin; 5use core::pin::Pin;
6use core::sync::atomic::{compiler_fence, Ordering}; 6use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
7use core::task::Poll; 7use core::task::Poll;
8use embassy::traits::uart::{Error, Read, Write}; 8use embassy::traits::uart::{Error, Read, Write};
9use embassy::util::{wake_on_interrupt, OnDrop, PeripheralBorrow}; 9use embassy::util::{AtomicWaker, OnDrop, PeripheralBorrow};
10use embassy_extras::peripheral_shared::{Peripheral, PeripheralState};
10use embassy_extras::unborrow; 11use embassy_extras::unborrow;
11use futures::future::poll_fn; 12use futures::future::poll_fn;
12 13
@@ -37,10 +38,18 @@ impl Default for Config {
37 } 38 }
38} 39}
39 40
41struct State<T: Instance> {
42 peri: T,
43 did_stoprx: AtomicBool,
44 did_stoptx: AtomicBool,
45
46 endrx_waker: AtomicWaker,
47 endtx_waker: AtomicWaker,
48}
49
40/// Interface to the UARTE peripheral 50/// Interface to the UARTE peripheral
41pub struct Uarte<'d, T: Instance> { 51pub struct Uarte<'d, T: Instance> {
42 peri: T, 52 inner: Peripheral<State<T>>,
43 irq: T::Interrupt,
44 phantom: PhantomData<&'d mut T>, 53 phantom: PhantomData<&'d mut T>,
45} 54}
46 55
@@ -90,23 +99,85 @@ impl<'d, T: Instance> Uarte<'d, T> {
90 r.baudrate.write(|w| w.baudrate().variant(config.baudrate)); 99 r.baudrate.write(|w| w.baudrate().variant(config.baudrate));
91 r.config.write(|w| w.parity().variant(config.parity)); 100 r.config.write(|w| w.parity().variant(config.parity));
92 101
102 // Disable all interrupts
103 r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
104
93 // Enable 105 // Enable
94 r.enable.write(|w| w.enable().enabled()); 106 r.enable.write(|w| w.enable().enabled());
95 107
96 Self { 108 Self {
97 peri: uarte, 109 inner: Peripheral::new(
98 irq, 110 irq,
111 State {
112 did_stoprx: AtomicBool::new(false),
113 did_stoptx: AtomicBool::new(false),
114 peri: uarte,
115 endrx_waker: AtomicWaker::new(),
116 endtx_waker: AtomicWaker::new(),
117 },
118 ),
99 phantom: PhantomData, 119 phantom: PhantomData,
100 } 120 }
101 } 121 }
122
123 fn inner(self: Pin<&mut Self>) -> Pin<&mut Peripheral<State<T>>> {
124 unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) }
125 }
102} 126}
103 127
104impl<'d, T: Instance> Drop for Uarte<'d, T> { 128impl<T: Instance> PeripheralState for State<T> {
105 fn drop(&mut self) { 129 type Interrupt = T::Interrupt;
130
131 fn on_interrupt(&self) {
132 info!("irq");
133
106 let r = self.peri.regs(); 134 let r = self.peri.regs();
135 if r.events_endrx.read().bits() != 0 {
136 self.endrx_waker.wake();
137 r.intenclr.write(|w| w.endrx().clear());
138 }
139 if r.events_endtx.read().bits() != 0 {
140 self.endtx_waker.wake();
141 r.intenclr.write(|w| w.endtx().clear());
142 }
143
144 if r.events_rxto.read().bits() != 0 {
145 r.intenclr.write(|w| w.rxto().clear());
146 }
147 if r.events_txstopped.read().bits() != 0 {
148 r.intenclr.write(|w| w.txstopped().clear());
149 }
150 }
151}
152
153impl<'a, T: Instance> Drop for Uarte<'a, T> {
154 fn drop(&mut self) {
155 info!("uarte drop");
156
157 let s = unsafe { Pin::new_unchecked(&mut self.inner) }.state();
158 let r = s.peri.regs();
159
160 let did_stoprx = s.did_stoprx.load(Ordering::Relaxed);
161 let did_stoptx = s.did_stoptx.load(Ordering::Relaxed);
162 info!("did_stoprx {} did_stoptx {}", did_stoprx, did_stoptx);
163
164 // Wait for rxto or txstopped, if needed.
165 r.intenset.write(|w| w.rxto().set().txstopped().set());
166 while (did_stoprx && r.events_rxto.read().bits() == 0)
167 || (did_stoptx && r.events_txstopped.read().bits() == 0)
168 {
169 info!("uarte drop: wfe");
170 cortex_m::asm::wfe();
171 }
172
173 cortex_m::asm::sev();
174
175 // Finally we can disable!
107 r.enable.write(|w| w.enable().disabled()); 176 r.enable.write(|w| w.enable().disabled());
108 177
109 // todo disable pins 178 info!("uarte drop: done");
179
180 // TODO: disable pins
110 } 181 }
111} 182}
112 183
@@ -114,25 +185,29 @@ impl<'d, T: Instance> Read for Uarte<'d, T> {
114 #[rustfmt::skip] 185 #[rustfmt::skip]
115 type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Error>> + 'a; 186 type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Error>> + 'a;
116 187
117 fn read<'a>(self: Pin<&'a mut Self>, rx_buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { 188 fn read<'a>(mut self: Pin<&'a mut Self>, rx_buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
118 async move { 189 self.as_mut().inner().register_interrupt();
119 let this = unsafe { self.get_unchecked_mut() };
120 190
191 async move {
121 let ptr = rx_buffer.as_ptr(); 192 let ptr = rx_buffer.as_ptr();
122 let len = rx_buffer.len(); 193 let len = rx_buffer.len();
123 assert!(len <= EASY_DMA_SIZE); 194 assert!(len <= EASY_DMA_SIZE);
124 195
125 let r = this.peri.regs(); 196 let s = self.inner().state();
197 let r = s.peri.regs();
126 198
199 let did_stoprx = &s.did_stoprx;
127 let drop = OnDrop::new(move || { 200 let drop = OnDrop::new(move || {
128 info!("read drop: stopping"); 201 info!("read drop: stopping");
129 202
130 r.intenclr.write(|w| w.endrx().clear()); 203 r.intenclr.write(|w| w.endrx().clear());
204 r.events_rxto.reset();
131 r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); 205 r.tasks_stoprx.write(|w| unsafe { w.bits(1) });
132 206
133 // TX is stopped almost instantly, spinning is fine.
134 while r.events_endrx.read().bits() == 0 {} 207 while r.events_endrx.read().bits() == 0 {}
208
135 info!("read drop: stopped"); 209 info!("read drop: stopped");
210 did_stoprx.store(true, Ordering::Relaxed);
136 }); 211 });
137 212
138 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); 213 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
@@ -146,21 +221,17 @@ impl<'d, T: Instance> Read for Uarte<'d, T> {
146 trace!("startrx"); 221 trace!("startrx");
147 r.tasks_startrx.write(|w| unsafe { w.bits(1) }); 222 r.tasks_startrx.write(|w| unsafe { w.bits(1) });
148 223
149 let irq = &mut this.irq;
150 poll_fn(|cx| { 224 poll_fn(|cx| {
225 s.endrx_waker.register(cx.waker());
151 if r.events_endrx.read().bits() != 0 { 226 if r.events_endrx.read().bits() != 0 {
152 r.events_endrx.reset();
153 return Poll::Ready(()); 227 return Poll::Ready(());
154 } 228 }
155
156 wake_on_interrupt(irq, cx.waker());
157
158 Poll::Pending 229 Poll::Pending
159 }) 230 })
160 .await; 231 .await;
161 232
162 compiler_fence(Ordering::SeqCst); 233 compiler_fence(Ordering::SeqCst);
163 r.intenclr.write(|w| w.endrx().clear()); 234 s.did_stoprx.store(false, Ordering::Relaxed);
164 drop.defuse(); 235 drop.defuse();
165 236
166 Ok(()) 237 Ok(())
@@ -172,26 +243,30 @@ impl<'d, T: Instance> Write for Uarte<'d, T> {
172 #[rustfmt::skip] 243 #[rustfmt::skip]
173 type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), Error>> + 'a; 244 type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), Error>> + 'a;
174 245
175 fn write<'a>(self: Pin<&'a mut Self>, tx_buffer: &'a [u8]) -> Self::WriteFuture<'a> { 246 fn write<'a>(mut self: Pin<&'a mut Self>, tx_buffer: &'a [u8]) -> Self::WriteFuture<'a> {
176 async move { 247 self.as_mut().inner().register_interrupt();
177 let this = unsafe { self.get_unchecked_mut() };
178 248
249 async move {
179 let ptr = tx_buffer.as_ptr(); 250 let ptr = tx_buffer.as_ptr();
180 let len = tx_buffer.len(); 251 let len = tx_buffer.len();
181 assert!(len <= EASY_DMA_SIZE); 252 assert!(len <= EASY_DMA_SIZE);
182 // TODO: panic if buffer is not in SRAM 253 // TODO: panic if buffer is not in SRAM
183 254
184 let r = this.peri.regs(); 255 let s = self.inner().state();
256 let r = s.peri.regs();
185 257
258 let did_stoptx = &s.did_stoptx;
186 let drop = OnDrop::new(move || { 259 let drop = OnDrop::new(move || {
187 info!("write drop: stopping"); 260 info!("write drop: stopping");
188 261
189 r.intenclr.write(|w| w.endtx().clear()); 262 r.intenclr.write(|w| w.endtx().clear());
263 r.events_txstopped.reset();
190 r.tasks_stoptx.write(|w| unsafe { w.bits(1) }); 264 r.tasks_stoptx.write(|w| unsafe { w.bits(1) });
191 265
192 // TX is stopped almost instantly, spinning is fine. 266 // TX is stopped almost instantly, spinning is fine.
193 while r.events_endtx.read().bits() == 0 {} 267 while r.events_endtx.read().bits() == 0 {}
194 info!("write drop: stopped"); 268 info!("write drop: stopped");
269 did_stoptx.store(true, Ordering::Relaxed);
195 }); 270 });
196 271
197 r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); 272 r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
@@ -205,21 +280,17 @@ impl<'d, T: Instance> Write for Uarte<'d, T> {
205 trace!("starttx"); 280 trace!("starttx");
206 r.tasks_starttx.write(|w| unsafe { w.bits(1) }); 281 r.tasks_starttx.write(|w| unsafe { w.bits(1) });
207 282
208 let irq = &mut this.irq;
209 poll_fn(|cx| { 283 poll_fn(|cx| {
284 s.endtx_waker.register(cx.waker());
210 if r.events_endtx.read().bits() != 0 { 285 if r.events_endtx.read().bits() != 0 {
211 r.events_endtx.reset();
212 return Poll::Ready(()); 286 return Poll::Ready(());
213 } 287 }
214
215 wake_on_interrupt(irq, cx.waker());
216
217 Poll::Pending 288 Poll::Pending
218 }) 289 })
219 .await; 290 .await;
220 291
221 compiler_fence(Ordering::SeqCst); 292 compiler_fence(Ordering::SeqCst);
222 r.intenclr.write(|w| w.endtx().clear()); 293 s.did_stoptx.store(false, Ordering::Relaxed);
223 drop.defuse(); 294 drop.defuse();
224 295
225 Ok(()) 296 Ok(())
@@ -227,114 +298,6 @@ impl<'d, T: Instance> Write for Uarte<'d, T> {
227 } 298 }
228} 299}
229 300
230/*
231/// Future for the [`Uarte::send()`] method.
232pub struct SendFuture<'a, T>
233where
234 T: Instance,
235{
236 uarte: &'a mut Uarte<T>,
237 buf: &'a [u8],
238}
239
240impl<'a, T> Drop for SendFuture<'a, T>
241where
242 T: Instance,
243{
244 fn drop(self: &mut Self) {
245 if self.uarte.tx_started() {
246 trace!("stoptx");
247
248 // Stop the transmitter to minimize the current consumption.
249 self.uarte.peri.events_txstarted.reset();
250 self.uarte.peri.tasks_stoptx.write(|w| unsafe { w.bits(1) });
251
252 // TX is stopped almost instantly, spinning is fine.
253 while !T::state().tx_done.signaled() {}
254 }
255 }
256}
257
258/// Future for the [`Uarte::receive()`] method.
259pub struct ReceiveFuture<'a, T>
260where
261 T: Instance,
262{
263 uarte: &'a mut Uarte<T>,
264 buf: &'a mut [u8],
265}
266
267impl<'a, T> Drop for ReceiveFuture<'a, T>
268where
269 T: Instance,
270{
271 fn drop(self: &mut Self) {
272 if self.uarte.rx_started() {
273 trace!("stoprx (drop)");
274
275 self.uarte.peri.events_rxstarted.reset();
276 self.uarte.peri.tasks_stoprx.write(|w| unsafe { w.bits(1) });
277
278 embassy_extras::low_power_wait_until(|| T::state().rx_done.signaled())
279 }
280 }
281}
282
283impl<'a, T> Future for ReceiveFuture<'a, T>
284where
285 T: Instance,
286{
287 type Output = Result<(), embassy::traits::uart::Error>;
288
289 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
290 let Self { uarte, buf } = unsafe { self.get_unchecked_mut() };
291
292 match T::state().rx_done.poll_wait(cx) {
293 Poll::Pending if !uarte.rx_started() => {
294 let ptr = buf.as_ptr();
295 let len = buf.len();
296 assert!(len <= EASY_DMA_SIZE);
297
298 uarte.enable();
299
300 compiler_fence(Ordering::SeqCst);
301 r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) });
302 r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
303
304 trace!("startrx");
305 uarte.peri.tasks_startrx.write(|w| unsafe { w.bits(1) });
306 while !uarte.rx_started() {} // Make sure reception has started
307
308 Poll::Pending
309 }
310 Poll::Pending => Poll::Pending,
311 Poll::Ready(_) => Poll::Ready(Ok(())),
312 }
313 }
314}
315
316/// Future for the [`receive()`] method.
317impl<'a, T> ReceiveFuture<'a, T>
318where
319 T: Instance,
320{
321 /// Stops the ongoing reception and returns the number of bytes received.
322 pub async fn stop(self) -> usize {
323 let len = if self.uarte.rx_started() {
324 trace!("stoprx (stop)");
325
326 self.uarte.peri.events_rxstarted.reset();
327 self.uarte.peri.tasks_stoprx.write(|w| unsafe { w.bits(1) });
328 T::state().rx_done.wait().await
329 } else {
330 // Transfer was stopped before it even started. No bytes were sent.
331 0
332 };
333 len as _
334 }
335}
336 */
337
338mod sealed { 301mod sealed {
339 use super::*; 302 use super::*;
340 303