aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-01-05 21:14:04 +0100
committerDario Nieuwenhuis <[email protected]>2021-01-05 21:14:04 +0100
commit607e67f51a33d83c59db5e091348e4bda0b5ddbb (patch)
tree98f6496e21a8093f84b8672e28dfd52723145d79
parent3a4dbfa52ece1d11ec4ded71074fb1e914671571 (diff)
Cleanup BufferedUarte
-rw-r--r--embassy-nrf/src/buffered_uarte.rs159
1 files changed, 68 insertions, 91 deletions
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs
index dbdb6f514..2e29da25a 100644
--- a/embassy-nrf/src/buffered_uarte.rs
+++ b/embassy-nrf/src/buffered_uarte.rs
@@ -33,12 +33,25 @@ enum RxState {
33 ReceivingReady, 33 ReceivingReady,
34 Stopping, 34 Stopping,
35} 35}
36
36#[derive(Copy, Clone, Debug, PartialEq)] 37#[derive(Copy, Clone, Debug, PartialEq)]
37enum TxState { 38enum TxState {
38 Idle, 39 Idle,
39 Transmitting(usize), 40 Transmitting(usize),
40} 41}
41 42
43struct State<'a, T: Instance> {
44 inner: T,
45
46 rx: RingBuffer<'a>,
47 rx_state: RxState,
48 rx_waker: WakerRegistration,
49
50 tx: RingBuffer<'a>,
51 tx_state: TxState,
52 tx_waker: WakerRegistration,
53}
54
42/// Interface to a UARTE instance 55/// Interface to a UARTE instance
43/// 56///
44/// This is a very basic interface that comes with the following limitations: 57/// This is a very basic interface that comes with the following limitations:
@@ -145,6 +158,10 @@ impl<'a, T: Instance> BufferedUarte<'a, T> {
145 ), 158 ),
146 } 159 }
147 } 160 }
161
162 fn inner(self: Pin<&mut Self>) -> Pin<&mut PeripheralMutex<T::Interrupt, State<'a, T>>> {
163 unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) }
164 }
148} 165}
149 166
150impl<'a, T: Instance> Drop for BufferedUarte<'a, T> { 167impl<'a, T: Instance> Drop for BufferedUarte<'a, T> {
@@ -156,111 +173,71 @@ impl<'a, T: Instance> Drop for BufferedUarte<'a, T> {
156 173
157impl<'a, T: Instance> AsyncBufRead for BufferedUarte<'a, T> { 174impl<'a, T: Instance> AsyncBufRead for BufferedUarte<'a, T> {
158 fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> { 175 fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> {
159 let this = unsafe { self.get_unchecked_mut() }; 176 self.inner().with(|_irq, state| {
160 let reg = unsafe { Pin::new_unchecked(&mut this.inner) }; 177 // Conservative compiler fence to prevent optimizations that do not
161 reg.with(|_irq, state| { 178 // take in to account actions by DMA. The fence has been placed here,
162 let z: Poll<Result<&[u8]>> = state.poll_fill_buf(cx); 179 // before any DMA action has started
163 let z: Poll<Result<&[u8]>> = unsafe { mem::transmute(z) }; 180 compiler_fence(Ordering::SeqCst);
164 z 181 trace!("poll_read");
182
183 // We have data ready in buffer? Return it.
184 let buf = state.rx.pop_buf();
185 if buf.len() != 0 {
186 trace!(" got {:?} {:?}", buf.as_ptr() as u32, buf.len());
187 let buf: &[u8] = buf;
188 let buf: &[u8] = unsafe { mem::transmute(buf) };
189 return Poll::Ready(Ok(buf));
190 }
191
192 trace!(" empty");
193
194 if state.rx_state == RxState::ReceivingReady {
195 trace!(" stopping");
196 state.rx_state = RxState::Stopping;
197 state.inner.tasks_stoprx.write(|w| unsafe { w.bits(1) });
198 }
199
200 state.rx_waker.register(cx.waker());
201 Poll::<Result<&[u8]>>::Pending
165 }) 202 })
166 } 203 }
167 204
168 fn consume(self: Pin<&mut Self>, amt: usize) { 205 fn consume(self: Pin<&mut Self>, amt: usize) {
169 let this = unsafe { self.get_unchecked_mut() }; 206 self.inner().with(|irq, state| {
170 let reg = unsafe { Pin::new_unchecked(&mut this.inner) }; 207 trace!("consume {:?}", amt);
171 reg.with(|irq, state| state.consume(irq, amt)) 208 state.rx.pop(amt);
209 irq.pend();
210 })
172 } 211 }
173} 212}
174 213
175impl<'a, T: Instance> AsyncWrite for BufferedUarte<'a, T> { 214impl<'a, T: Instance> AsyncWrite for BufferedUarte<'a, T> {
176 fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> { 215 fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> {
177 let this = unsafe { self.get_unchecked_mut() }; 216 self.inner().with(|irq, state| {
178 let reg = unsafe { Pin::new_unchecked(&mut this.inner) }; 217 trace!("poll_write: {:?}", buf.len());
179 reg.with(|irq, state| state.poll_write(irq, cx, buf)) 218
180 } 219 let tx_buf = state.tx.push_buf();
181} 220 if tx_buf.len() == 0 {
182 221 trace!("poll_write: pending");
183// ==================================== 222 state.tx_waker.register(cx.waker());
184// ==================================== 223 return Poll::Pending;
185// ==================================== 224 }
186
187// public because it needs to be used in Instance trait, but
188// should not be used outside the module
189#[doc(hidden)]
190pub struct State<'a, T: Instance> {
191 inner: T,
192
193 rx: RingBuffer<'a>,
194 rx_state: RxState,
195 rx_waker: WakerRegistration,
196
197 tx: RingBuffer<'a>,
198 tx_state: TxState,
199 tx_waker: WakerRegistration,
200}
201
202impl<'a, T: Instance> State<'a, T> {
203 fn poll_fill_buf(&mut self, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> {
204 // Conservative compiler fence to prevent optimizations that do not
205 // take in to account actions by DMA. The fence has been placed here,
206 // before any DMA action has started
207 compiler_fence(Ordering::SeqCst);
208 trace!("poll_read");
209
210 // We have data ready in buffer? Return it.
211 let buf = self.rx.pop_buf();
212 if buf.len() != 0 {
213 trace!(" got {:?} {:?}", buf.as_ptr() as u32, buf.len());
214 return Poll::Ready(Ok(buf));
215 }
216
217 trace!(" empty");
218
219 if self.rx_state == RxState::ReceivingReady {
220 trace!(" stopping");
221 self.rx_state = RxState::Stopping;
222 self.inner.tasks_stoprx.write(|w| unsafe { w.bits(1) });
223 }
224
225 self.rx_waker.register(cx.waker());
226 Poll::Pending
227 }
228
229 fn consume(&mut self, irq: &mut T::Interrupt, amt: usize) {
230 trace!("consume {:?}", amt);
231 self.rx.pop(amt);
232 irq.pend();
233 }
234
235 fn poll_write(
236 &mut self,
237 irq: &mut T::Interrupt,
238 cx: &mut Context<'_>,
239 buf: &[u8],
240 ) -> Poll<Result<usize>> {
241 trace!("poll_write: {:?}", buf.len());
242
243 let tx_buf = self.tx.push_buf();
244 if tx_buf.len() == 0 {
245 trace!("poll_write: pending");
246 self.tx_waker.register(cx.waker());
247 return Poll::Pending;
248 }
249 225
250 let n = min(tx_buf.len(), buf.len()); 226 let n = min(tx_buf.len(), buf.len());
251 tx_buf[..n].copy_from_slice(&buf[..n]); 227 tx_buf[..n].copy_from_slice(&buf[..n]);
252 self.tx.push(n); 228 state.tx.push(n);
253 229
254 trace!("poll_write: queued {:?}", n); 230 trace!("poll_write: queued {:?}", n);
255 231
256 // Conservative compiler fence to prevent optimizations that do not 232 // Conservative compiler fence to prevent optimizations that do not
257 // take in to account actions by DMA. The fence has been placed here, 233 // take in to account actions by DMA. The fence has been placed here,
258 // before any DMA action has started 234 // before any DMA action has started
259 compiler_fence(Ordering::SeqCst); 235 compiler_fence(Ordering::SeqCst);
260 236
261 irq.pend(); 237 irq.pend();
262 238
263 Poll::Ready(Ok(n)) 239 Poll::Ready(Ok(n))
240 })
264 } 241 }
265} 242}
266 243