aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-nrf-examples/src/bin/buffered_uart.rs6
-rw-r--r--embassy-nrf/src/buffered_uarte.rs181
2 files changed, 106 insertions, 81 deletions
diff --git a/embassy-nrf-examples/src/bin/buffered_uart.rs b/embassy-nrf-examples/src/bin/buffered_uart.rs
index 68a76f71e..57c6b4cf4 100644
--- a/embassy-nrf-examples/src/bin/buffered_uart.rs
+++ b/embassy-nrf-examples/src/bin/buffered_uart.rs
@@ -8,6 +8,7 @@ use example_common::*;
8 8
9use cortex_m_rt::entry; 9use cortex_m_rt::entry;
10use defmt::panic; 10use defmt::panic;
11use nrf52840_hal as hal;
11use nrf52840_hal::gpio; 12use nrf52840_hal::gpio;
12 13
13use embassy::executor::{task, Executor}; 14use embassy::executor::{task, Executor};
@@ -35,9 +36,14 @@ async fn run() {
35 rts: None, 36 rts: None,
36 }; 37 };
37 38
39 let ppi = hal::ppi::Parts::new(p.PPI);
40
38 let irq = interrupt::take!(UARTE0_UART0); 41 let irq = interrupt::take!(UARTE0_UART0);
39 let mut u = buffered_uarte::BufferedUarte::new( 42 let mut u = buffered_uarte::BufferedUarte::new(
40 p.UARTE0, 43 p.UARTE0,
44 p.TIMER0,
45 ppi.ppi0,
46 ppi.ppi1,
41 irq, 47 irq,
42 unsafe { &mut RX_BUFFER }, 48 unsafe { &mut RX_BUFFER },
43 unsafe { &mut TX_BUFFER }, 49 unsafe { &mut TX_BUFFER },
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs
index ceb52916f..fac3703a6 100644
--- a/embassy-nrf/src/buffered_uarte.rs
+++ b/embassy-nrf/src/buffered_uarte.rs
@@ -16,22 +16,20 @@ use embedded_hal::digital::v2::OutputPin;
16 16
17use crate::fmt::{panic, todo, *}; 17use crate::fmt::{panic, todo, *};
18use crate::hal::gpio::Port as GpioPort; 18use crate::hal::gpio::Port as GpioPort;
19use crate::hal::ppi::ConfigurablePpi;
19use crate::interrupt::{self, OwnedInterrupt}; 20use crate::interrupt::{self, OwnedInterrupt};
20use crate::pac; 21use crate::pac;
21use crate::pac::uarte0;
22use crate::util::peripheral::{PeripheralMutex, PeripheralState}; 22use crate::util::peripheral::{PeripheralMutex, PeripheralState};
23use crate::util::ring_buffer::RingBuffer; 23use crate::util::ring_buffer::RingBuffer;
24 24
25// Re-export SVD variants to allow user to directly set values 25// Re-export SVD variants to allow user to directly set values
26pub use crate::hal::uarte::Pins; 26pub use crate::hal::uarte::Pins;
27pub use uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; 27pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
28 28
29#[derive(Copy, Clone, Debug, PartialEq)] 29#[derive(Copy, Clone, Debug, PartialEq)]
30enum RxState { 30enum RxState {
31 Idle, 31 Idle,
32 Receiving, 32 Receiving,
33 ReceivingReady,
34 Stopping,
35} 33}
36 34
37#[derive(Copy, Clone, Debug, PartialEq)] 35#[derive(Copy, Clone, Debug, PartialEq)]
@@ -40,8 +38,11 @@ enum TxState {
40 Transmitting(usize), 38 Transmitting(usize),
41} 39}
42 40
43struct State<'a, U: Instance> { 41struct State<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi> {
44 inner: U, 42 uarte: U,
43 timer: T,
44 ppi_channel_1: P1,
45 ppi_channel_2: P2,
45 46
46 rx: RingBuffer<'a>, 47 rx: RingBuffer<'a>,
47 rx_state: RxState, 48 rx_state: RxState,
@@ -60,12 +61,16 @@ struct State<'a, U: Instance> {
60/// are disabled before using `Uarte`. See product specification: 61/// are disabled before using `Uarte`. See product specification:
61/// - nrf52832: Section 15.2 62/// - nrf52832: Section 15.2
62/// - nrf52840: Section 6.1.2 63/// - nrf52840: Section 6.1.2
63pub struct BufferedUarte<'a, U: Instance> { 64pub struct BufferedUarte<
64 inner: PeripheralMutex<State<'a, U>>, 65 'a,
66 U: Instance,
67 T: TimerInstance,
68 P1: ConfigurablePpi,
69 P2: ConfigurablePpi,
70> {
71 inner: PeripheralMutex<State<'a, U, T, P1, P2>>,
65} 72}
66 73
67impl<'a, U: Instance> Unpin for BufferedUarte<'a, U> {}
68
69#[cfg(any(feature = "52833", feature = "52840"))] 74#[cfg(any(feature = "52833", feature = "52840"))]
70fn port_bit(port: GpioPort) -> bool { 75fn port_bit(port: GpioPort) -> bool {
71 match port { 76 match port {
@@ -74,9 +79,14 @@ fn port_bit(port: GpioPort) -> bool {
74 } 79 }
75} 80}
76 81
77impl<'a, U: Instance> BufferedUarte<'a, U> { 82impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi>
83 BufferedUarte<'a, U, T, P1, P2>
84{
78 pub fn new( 85 pub fn new(
79 uarte: U, 86 uarte: U,
87 timer: T,
88 mut ppi_channel_1: P1,
89 mut ppi_channel_2: P2,
80 irq: U::Interrupt, 90 irq: U::Interrupt,
81 rx_buffer: &'a mut [u8], 91 rx_buffer: &'a mut [u8],
82 tx_buffer: &'a mut [u8], 92 tx_buffer: &'a mut [u8],
@@ -141,10 +151,41 @@ impl<'a, U: Instance> BufferedUarte<'a, U> {
141 irq.disable(); 151 irq.disable();
142 irq.pend(); 152 irq.pend();
143 153
154 // BAUDRATE register values are `baudrate * 2^32 / 16000000`
155 // source: https://devzone.nordicsemi.com/f/nordic-q-a/391/uart-baudrate-register-values
156 //
157 // We want to stop RX if line is idle for 2 bytes worth of time
158 // That is 20 bits (each byte is 1 start bit + 8 data bits + 1 stop bit)
159 // This gives us the amount of 16M ticks for 20 bits.
160 let timeout = 0x8000_0000 / (baudrate as u32 / 40);
161
162 timer.tasks_stop.write(|w| w.tasks_stop().set_bit());
163 timer.bitmode.write(|w| w.bitmode()._32bit());
164 timer.prescaler.write(|w| unsafe { w.prescaler().bits(0) });
165 timer.cc[0].write(|w| unsafe { w.bits(timeout) });
166 timer.mode.write(|w| w.mode().timer());
167 timer.shorts.write(|w| {
168 w.compare0_clear().set_bit();
169 w.compare0_stop().set_bit();
170 w
171 });
172
173 ppi_channel_1.set_event_endpoint(&uarte.events_rxdrdy);
174 ppi_channel_1.set_task_endpoint(&timer.tasks_clear);
175 ppi_channel_1.set_fork_task_endpoint(&timer.tasks_start);
176 ppi_channel_1.enable();
177
178 ppi_channel_2.set_event_endpoint(&timer.events_compare[0]);
179 ppi_channel_2.set_task_endpoint(&uarte.tasks_stoprx);
180 ppi_channel_2.enable();
181
144 BufferedUarte { 182 BufferedUarte {
145 inner: PeripheralMutex::new( 183 inner: PeripheralMutex::new(
146 State { 184 State {
147 inner: uarte, 185 uarte,
186 timer,
187 ppi_channel_1,
188 ppi_channel_2,
148 189
149 rx: RingBuffer::new(rx_buffer), 190 rx: RingBuffer::new(rx_buffer),
150 rx_state: RxState::Idle, 191 rx_state: RxState::Idle,
@@ -159,19 +200,23 @@ impl<'a, U: Instance> BufferedUarte<'a, U> {
159 } 200 }
160 } 201 }
161 202
162 fn inner(self: Pin<&mut Self>) -> Pin<&mut PeripheralMutex<State<'a, U>>> { 203 fn inner(self: Pin<&mut Self>) -> Pin<&mut PeripheralMutex<State<'a, U, T, P1, P2>>> {
163 unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) } 204 unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) }
164 } 205 }
165} 206}
166 207
167impl<'a, U: Instance> Drop for BufferedUarte<'a, U> { 208impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi> Drop
209 for BufferedUarte<'a, U, T, P1, P2>
210{
168 fn drop(&mut self) { 211 fn drop(&mut self) {
169 // stop DMA before dropping, because DMA is using the buffer in `self`. 212 // stop DMA before dropping, because DMA is using the buffer in `self`.
170 todo!() 213 todo!()
171 } 214 }
172} 215}
173 216
174impl<'a, U: Instance> AsyncBufRead for BufferedUarte<'a, U> { 217impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi> AsyncBufRead
218 for BufferedUarte<'a, U, T, P1, P2>
219{
175 fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> { 220 fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> {
176 self.inner().with(|state, _irq| { 221 self.inner().with(|state, _irq| {
177 // Conservative compiler fence to prevent optimizations that do not 222 // Conservative compiler fence to prevent optimizations that do not
@@ -190,13 +235,6 @@ impl<'a, U: Instance> AsyncBufRead for BufferedUarte<'a, U> {
190 } 235 }
191 236
192 trace!(" empty"); 237 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()); 238 state.rx_waker.register(cx.waker());
201 Poll::<Result<&[u8]>>::Pending 239 Poll::<Result<&[u8]>>::Pending
202 }) 240 })
@@ -211,7 +249,9 @@ impl<'a, U: Instance> AsyncBufRead for BufferedUarte<'a, U> {
211 } 249 }
212} 250}
213 251
214impl<'a, U: Instance> AsyncWrite for BufferedUarte<'a, U> { 252impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi> AsyncWrite
253 for BufferedUarte<'a, U, T, P1, P2>
254{
215 fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> { 255 fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> {
216 self.inner().with(|state, irq| { 256 self.inner().with(|state, irq| {
217 trace!("poll_write: {:?}", buf.len()); 257 trace!("poll_write: {:?}", buf.len());
@@ -241,38 +281,28 @@ impl<'a, U: Instance> AsyncWrite for BufferedUarte<'a, U> {
241 } 281 }
242} 282}
243 283
244impl<'a, U: Instance> PeripheralState for State<'a, U> { 284impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi> PeripheralState
285 for State<'a, U, T, P1, P2>
286{
245 type Interrupt = U::Interrupt; 287 type Interrupt = U::Interrupt;
246
247 fn on_interrupt(&mut self) { 288 fn on_interrupt(&mut self) {
248 trace!("irq: start"); 289 trace!("irq: start");
249 let mut more_work = true; 290 loop {
250 while more_work {
251 more_work = false;
252 match self.rx_state { 291 match self.rx_state {
253 RxState::Idle => { 292 RxState::Idle => {
254 trace!(" irq_rx: in state idle"); 293 trace!(" irq_rx: in state idle");
255 294
256 if self.inner.events_rxdrdy.read().bits() != 0 {
257 trace!(" irq_rx: rxdrdy?????");
258 self.inner.events_rxdrdy.reset();
259 }
260
261 if self.inner.events_endrx.read().bits() != 0 {
262 panic!("unexpected endrx");
263 }
264
265 let buf = self.rx.push_buf(); 295 let buf = self.rx.push_buf();
266 if buf.len() != 0 { 296 if buf.len() != 0 {
267 trace!(" irq_rx: starting {:?}", buf.len()); 297 trace!(" irq_rx: starting {:?}", buf.len());
268 self.rx_state = RxState::Receiving; 298 self.rx_state = RxState::Receiving;
269 299
270 // Set up the DMA read 300 // Set up the DMA read
271 self.inner.rxd.ptr.write(|w| 301 self.uarte.rxd.ptr.write(|w|
272 // The PTR field is a full 32 bits wide and accepts the full range 302 // The PTR field is a full 32 bits wide and accepts the full range
273 // of values. 303 // of values.
274 unsafe { w.ptr().bits(buf.as_ptr() as u32) }); 304 unsafe { w.ptr().bits(buf.as_ptr() as u32) });
275 self.inner.rxd.maxcnt.write(|w| 305 self.uarte.rxd.maxcnt.write(|w|
276 // We're giving it the length of the buffer, so no danger of 306 // We're giving it the length of the buffer, so no danger of
277 // accessing invalid memory. We have verified that the length of the 307 // accessing invalid memory. We have verified that the length of the
278 // buffer fits in an `u8`, so the cast to `u8` is also fine. 308 // buffer fits in an `u8`, so the cast to `u8` is also fine.
@@ -282,60 +312,34 @@ impl<'a, U: Instance> PeripheralState for State<'a, U> {
282 unsafe { w.maxcnt().bits(buf.len() as _) }); 312 unsafe { w.maxcnt().bits(buf.len() as _) });
283 trace!(" irq_rx: buf {:?} {:?}", buf.as_ptr() as u32, buf.len()); 313 trace!(" irq_rx: buf {:?} {:?}", buf.as_ptr() as u32, buf.len());
284 314
285 // Enable RXRDY interrupt.
286 self.inner.events_rxdrdy.reset();
287 self.inner.intenset.write(|w| w.rxdrdy().set());
288
289 // Start UARTE Receive transaction 315 // Start UARTE Receive transaction
290 self.inner.tasks_startrx.write(|w| 316 self.uarte.tasks_startrx.write(|w|
291 // `1` is a valid value to write to task registers. 317 // `1` is a valid value to write to task registers.
292 unsafe { w.bits(1) }); 318 unsafe { w.bits(1) });
293 } 319 }
320 break;
294 } 321 }
295 RxState::Receiving => { 322 RxState::Receiving => {
296 trace!(" irq_rx: in state receiving"); 323 trace!(" irq_rx: in state receiving");
297 if self.inner.events_rxdrdy.read().bits() != 0 { 324 if self.uarte.events_endrx.read().bits() != 0 {
298 trace!(" irq_rx: rxdrdy"); 325 self.timer.tasks_stop.write(|w| w.tasks_stop().set_bit());
299
300 // Disable the RXRDY event interrupt
301 // RXRDY is triggered for every byte, but we only care about whether we have
302 // some bytes or not. So as soon as we have at least one, disable it, to avoid
303 // wasting CPU cycles in interrupts.
304 self.inner.intenclr.write(|w| w.rxdrdy().clear());
305
306 self.inner.events_rxdrdy.reset();
307
308 self.rx_waker.wake();
309 self.rx_state = RxState::ReceivingReady;
310 more_work = true; // in case we also have endrx pending
311 }
312 }
313 RxState::ReceivingReady | RxState::Stopping => {
314 trace!(" irq_rx: in state ReceivingReady");
315
316 if self.inner.events_rxdrdy.read().bits() != 0 {
317 trace!(" irq_rx: rxdrdy");
318 self.inner.events_rxdrdy.reset();
319 }
320 326
321 if self.inner.events_endrx.read().bits() != 0 { 327 let n: usize = self.uarte.rxd.amount.read().amount().bits() as usize;
322 let n: usize = self.inner.rxd.amount.read().amount().bits() as usize;
323 trace!(" irq_rx: endrx {:?}", n); 328 trace!(" irq_rx: endrx {:?}", n);
324 self.rx.push(n); 329 self.rx.push(n);
325 330
326 self.inner.events_endrx.reset(); 331 self.uarte.events_endrx.reset();
327 332
328 self.rx_waker.wake(); 333 self.rx_waker.wake();
329 self.rx_state = RxState::Idle; 334 self.rx_state = RxState::Idle;
330 more_work = true; // start another rx if possible 335 } else {
336 break;
331 } 337 }
332 } 338 }
333 } 339 }
334 } 340 }
335 341
336 more_work = true; 342 loop {
337 while more_work {
338 more_work = false;
339 match self.tx_state { 343 match self.tx_state {
340 TxState::Idle => { 344 TxState::Idle => {
341 trace!(" irq_tx: in state Idle"); 345 trace!(" irq_tx: in state Idle");
@@ -345,11 +349,11 @@ impl<'a, U: Instance> PeripheralState for State<'a, U> {
345 self.tx_state = TxState::Transmitting(buf.len()); 349 self.tx_state = TxState::Transmitting(buf.len());
346 350
347 // Set up the DMA write 351 // Set up the DMA write
348 self.inner.txd.ptr.write(|w| 352 self.uarte.txd.ptr.write(|w|
349 // The PTR field is a full 32 bits wide and accepts the full range 353 // The PTR field is a full 32 bits wide and accepts the full range
350 // of values. 354 // of values.
351 unsafe { w.ptr().bits(buf.as_ptr() as u32) }); 355 unsafe { w.ptr().bits(buf.as_ptr() as u32) });
352 self.inner.txd.maxcnt.write(|w| 356 self.uarte.txd.maxcnt.write(|w|
353 // We're giving it the length of the buffer, so no danger of 357 // We're giving it the length of the buffer, so no danger of
354 // accessing invalid memory. We have verified that the length of the 358 // accessing invalid memory. We have verified that the length of the
355 // buffer fits in an `u8`, so the cast to `u8` is also fine. 359 // buffer fits in an `u8`, so the cast to `u8` is also fine.
@@ -359,21 +363,23 @@ impl<'a, U: Instance> PeripheralState for State<'a, U> {
359 unsafe { w.maxcnt().bits(buf.len() as _) }); 363 unsafe { w.maxcnt().bits(buf.len() as _) });
360 364
361 // Start UARTE Transmit transaction 365 // Start UARTE Transmit transaction
362 self.inner.tasks_starttx.write(|w| 366 self.uarte.tasks_starttx.write(|w|
363 // `1` is a valid value to write to task registers. 367 // `1` is a valid value to write to task registers.
364 unsafe { w.bits(1) }); 368 unsafe { w.bits(1) });
365 } 369 }
370 break;
366 } 371 }
367 TxState::Transmitting(n) => { 372 TxState::Transmitting(n) => {
368 trace!(" irq_tx: in state Transmitting"); 373 trace!(" irq_tx: in state Transmitting");
369 if self.inner.events_endtx.read().bits() != 0 { 374 if self.uarte.events_endtx.read().bits() != 0 {
370 self.inner.events_endtx.reset(); 375 self.uarte.events_endtx.reset();
371 376
372 trace!(" irq_tx: endtx {:?}", n); 377 trace!(" irq_tx: endtx {:?}", n);
373 self.tx.pop(n); 378 self.tx.pop(n);
374 self.tx_waker.wake(); 379 self.tx_waker.wake();
375 self.tx_state = TxState::Idle; 380 self.tx_state = TxState::Idle;
376 more_work = true; // start another tx if possible 381 } else {
382 break;
377 } 383 }
378 } 384 }
379 } 385 }
@@ -388,9 +394,14 @@ mod sealed {
388 impl Instance for crate::pac::UARTE0 {} 394 impl Instance for crate::pac::UARTE0 {}
389 #[cfg(any(feature = "52833", feature = "52840", feature = "9160"))] 395 #[cfg(any(feature = "52833", feature = "52840", feature = "9160"))]
390 impl Instance for crate::pac::UARTE1 {} 396 impl Instance for crate::pac::UARTE1 {}
397
398 pub trait TimerInstance {}
399 impl TimerInstance for crate::pac::TIMER0 {}
400 impl TimerInstance for crate::pac::TIMER1 {}
401 impl TimerInstance for crate::pac::TIMER2 {}
391} 402}
392 403
393pub trait Instance: Deref<Target = uarte0::RegisterBlock> + sealed::Instance { 404pub trait Instance: Deref<Target = pac::uarte0::RegisterBlock> + sealed::Instance {
394 type Interrupt: OwnedInterrupt; 405 type Interrupt: OwnedInterrupt;
395} 406}
396 407
@@ -402,3 +413,11 @@ impl Instance for pac::UARTE0 {
402impl Instance for pac::UARTE1 { 413impl Instance for pac::UARTE1 {
403 type Interrupt = interrupt::UARTE1Interrupt; 414 type Interrupt = interrupt::UARTE1Interrupt;
404} 415}
416
417pub trait TimerInstance:
418 Deref<Target = pac::timer0::RegisterBlock> + sealed::TimerInstance
419{
420}
421impl TimerInstance for crate::pac::TIMER0 {}
422impl TimerInstance for crate::pac::TIMER1 {}
423impl TimerInstance for crate::pac::TIMER2 {}