aboutsummaryrefslogtreecommitdiff
path: root/embassy-rp/src
diff options
context:
space:
mode:
authorJames Munns <[email protected]>2023-12-20 17:06:57 +0100
committerJames Munns <[email protected]>2024-01-19 14:02:17 +0100
commit94290981c359cfc4bb2355055a8a5d1497cf09aa (patch)
treedfb535fcd8d8d456b3f747461d74f2ea42137f91 /embassy-rp/src
parentfe172109be8644b1e0d86735f4bd267ef7180c36 (diff)
Debugging RSR
Diffstat (limited to 'embassy-rp/src')
-rw-r--r--embassy-rp/src/uart/mod.rs128
1 files changed, 80 insertions, 48 deletions
diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs
index 998f7ccac..61d3af5de 100644
--- a/embassy-rp/src/uart/mod.rs
+++ b/embassy-rp/src/uart/mod.rs
@@ -116,10 +116,16 @@ pub enum Error {
116 Parity, 116 Parity,
117 /// Triggered when the received character didn't have a valid stop bit. 117 /// Triggered when the received character didn't have a valid stop bit.
118 Framing, 118 Framing,
119 /// There was an issue when calculating the number of transferred items 119}
120 /// in an aborted DMA transaction. This is likely an error in the 120
121 /// driver implementation, please open an embassy issue. 121/// Read To Break error
122 Calculation, 122#[derive(Debug, Eq, PartialEq, Copy, Clone)]
123#[cfg_attr(feature = "defmt", derive(defmt::Format))]
124#[non_exhaustive]
125pub enum ReadToBreakError {
126 /// Read this many bytes, but never received a line break.
127 MissingBreak(usize),
128 Other(Error),
123} 129}
124 130
125/// Internal DMA state of UART RX. 131/// Internal DMA state of UART RX.
@@ -432,12 +438,10 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
432 ) 438 )
433 .await; 439 .await;
434 440
435 let mut did_finish = false;
436 let errors = match transfer_result { 441 let errors = match transfer_result {
437 Either::First(()) => { 442 Either::First(()) => {
438 // We're here because the DMA finished, BUT if an error occurred on the LAST 443 // We're here because the DMA finished, BUT if an error occurred on the LAST
439 // byte, then we may still need to grab the error state! 444 // byte, then we may still need to grab the error state!
440 did_finish = true;
441 Uartris(T::dma_state().rx_errs.swap(0, Ordering::Relaxed) as u32) 445 Uartris(T::dma_state().rx_errs.swap(0, Ordering::Relaxed) as u32)
442 } 446 }
443 Either::Second(e) => { 447 Either::Second(e) => {
@@ -452,12 +456,7 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
452 return Ok(()); 456 return Ok(());
453 } 457 }
454 458
455 // If we DID get an error, and DID finish, we'll have one error byte left in the FIFO. 459 // If we DID get an error, we need to figure out which one it was.
456 // Pop it since we are reporting the error on THIS transaction.
457 if did_finish {
458 let _ = T::regs().uartdr().read();
459 }
460
461 if errors.oeris() { 460 if errors.oeris() {
462 return Err(Error::Overrun); 461 return Err(Error::Overrun);
463 } else if errors.beris() { 462 } else if errors.beris() {
@@ -470,15 +469,27 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
470 unreachable!("unrecognized rx error"); 469 unreachable!("unrecognized rx error");
471 } 470 }
472 471
473 /// Read from the UART, until one of the following occurs: 472 /// Read from the UART, waiting for a line break.
473 ///
474 /// We read until one of the following occurs:
474 /// 475 ///
475 /// * We read `buffer.len()` bytes without a line break 476 /// * We read `buffer.len()` bytes without a line break
476 /// * returns `Ok(buffer)` 477 /// * returns `Err(ReadToBreakError::MissingBreak(buffer.len()))`
477 /// * We read `n` bytes then a line break occurs 478 /// * We read `n` bytes then a line break occurs
478 /// * returns `Ok(&mut buffer[..n])` 479 /// * returns `Ok(n)`
479 /// * We encounter some error OTHER than a line break 480 /// * We encounter some error OTHER than a line break
480 /// * returns `Err(Error)` 481 /// * returns `Err(ReadToBreakError::Other(error))`
481 pub async fn read_to_break<'a>(&mut self, buffer: &'a mut [u8]) -> Result<&'a mut [u8], Error> { 482 ///
483 /// **NOTE**: you MUST provide a buffer one byte larger than your largest expected
484 /// message to reliably detect the framing on one single call to `read_to_break()`.
485 ///
486 /// * If you expect a message of 20 bytes + line break, and provide a 20-byte buffer:
487 /// * The first call to `read_to_break()` will return `Err(ReadToBreakError::MissingBreak(20))`
488 /// * The next call to `read_to_break()` will immediately return `Ok(0)`, from the "stale" line break
489 /// * If you expect a message of 20 bytes + line break, and provide a 21-byte buffer:
490 /// * The first call to `read_to_break()` will return `Ok(20)`.
491 /// * The next call to `read_to_break()` will work as expected
492 pub async fn read_to_break(&mut self, buffer: &mut [u8]) -> Result<usize, ReadToBreakError> {
482 // clear error flags before we drain the fifo. errors that have accumulated 493 // clear error flags before we drain the fifo. errors that have accumulated
483 // in the flags will also be present in the fifo. 494 // in the flags will also be present in the fifo.
484 T::dma_state().rx_errs.store(0, Ordering::Relaxed); 495 T::dma_state().rx_errs.store(0, Ordering::Relaxed);
@@ -498,11 +509,11 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
498 // Drained fifo, still some room left! 509 // Drained fifo, still some room left!
499 Ok(len) if len < buffer.len() => &mut buffer[len..], 510 Ok(len) if len < buffer.len() => &mut buffer[len..],
500 // Drained (some/all of the fifo), no room left 511 // Drained (some/all of the fifo), no room left
501 Ok(_) => return Ok(buffer), 512 Ok(len) => return Err(ReadToBreakError::MissingBreak(len)),
502 // We got a break WHILE draining the FIFO, return what we did get before the break 513 // We got a break WHILE draining the FIFO, return what we did get before the break
503 Err((i, Error::Break)) => return Ok(&mut buffer[..i]), 514 Err((i, Error::Break)) => return Ok(i),
504 // Some other error, just return the error 515 // Some other error, just return the error
505 Err((_i, e)) => return Err(e), 516 Err((_i, e)) => return Err(ReadToBreakError::Other(e)),
506 }; 517 };
507 518
508 // start a dma transfer. if errors have happened in the interim some error 519 // start a dma transfer. if errors have happened in the interim some error
@@ -538,14 +549,11 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
538 ) 549 )
539 .await; 550 .await;
540 551
541 let mut did_finish = false;
542
543 // Figure out our error state 552 // Figure out our error state
544 let errors = match transfer_result { 553 let errors = match transfer_result {
545 Either::First(()) => { 554 Either::First(()) => {
546 // We're here because the DMA finished, BUT if an error occurred on the LAST 555 // We're here because the DMA finished, BUT if an error occurred on the LAST
547 // byte, then we may still need to grab the error state! 556 // byte, then we may still need to grab the error state!
548 did_finish = true;
549 Uartris(T::dma_state().rx_errs.swap(0, Ordering::Relaxed) as u32) 557 Uartris(T::dma_state().rx_errs.swap(0, Ordering::Relaxed) as u32)
550 } 558 }
551 Either::Second(e) => { 559 Either::Second(e) => {
@@ -557,7 +565,8 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
557 565
558 if errors.0 == 0 { 566 if errors.0 == 0 {
559 // No errors? That means we filled the buffer without a line break. 567 // No errors? That means we filled the buffer without a line break.
560 return Ok(buffer); 568 // For THIS function, that's a problem.
569 return Err(ReadToBreakError::MissingBreak(buffer.len()));
561 } else if errors.beris() { 570 } else if errors.beris() {
562 // We got a Line Break! By this point, we've finished/aborted the DMA 571 // We got a Line Break! By this point, we've finished/aborted the DMA
563 // transaction, which means that we need to figure out where it left off 572 // transaction, which means that we need to figure out where it left off
@@ -568,36 +577,60 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
568 let sval = buffer.as_ptr() as usize; 577 let sval = buffer.as_ptr() as usize;
569 let eval = sval + buffer.len(); 578 let eval = sval + buffer.len();
570 579
571 // Note: the `write_addr()` is where the NEXT write would be. 580 // Note: the `write_addr()` is where the NEXT write would be, but we ALSO
572 let mut last_written = ch.regs().write_addr().read() as usize; 581 // got a line break, so take an offset of 1
582 let mut next_addr = ch.regs().write_addr().read() as usize;
573 583
574 // Did we finish the whole DMA transfer? 584 // If we DON'T end up inside the range, something has gone really wrong.
575 if !did_finish { 585 if (next_addr < sval) || (next_addr > eval) {
576 // No, we did not! We stopped because we got a line break. That means the 586 unreachable!("UART DMA reported invalid `write_addr`");
577 // DMA transferred one "garbage byte" from the FIFO that held an error. 587 }
578 last_written -= 1; 588
579 } else { 589 // If we finished the full DMA, AND the FIFO is not-empty, AND that
580 // We did finish and got a "late break", where the interrupt error fired AFTER 590 // byte reports a break error, THAT byte caused the error, and not data
581 // we got the last byte. Pop that from the FIFO so we don't trip on it next time. 591 // in the DMA transfer! Otherwise: our DMA grabbed one "bad" byte.
582 let dr = T::regs().uartdr().read(); 592 //
583 if !dr.be() { 593 // Note: even though we COULD detect this and return `Ok(buffer.len())`,
584 // Got an error after DMA but no error in the FIFO? 594 // we DON'T, as that is racy: if we read the error state AFTER the data
585 return Err(Error::Calculation); 595 // was transferred but BEFORE the line break interrupt fired, we'd return
596 // `MissingBreak`. Ignoring the fact that there's a line break in the FIFO
597 // means callers consistently see the same error regardless of
598 let regs = T::regs();
599 let is_end = next_addr == eval;
600 let not_empty = !regs.uartfr().read().rxfe();
601 let is_break = regs.uartrsr().read().be();
602 let last_good = is_end && not_empty && is_break;
603
604 defmt::println!("next: {=usize}, sval: {=usize}, eval: {=usize}", next_addr, sval, eval);
605 defmt::println!("lg: {=bool}, is_end: {=bool}, not_empty: {=bool}, is_break: {=bool}", last_good, is_end, not_empty, is_break);
606
607 if is_end && not_empty && !is_break {
608 let val = regs.uartdr().read();
609 let tb = regs.uartrsr().read().be();
610 let te = regs.uartfr().read().rxfe();
611 defmt::println!("THEN: {=bool}, {=bool}", tb, te);
612 if val.be() {
613 panic!("Oh what the hell");
586 } 614 }
587 } 615 }
588 616
589 // If we DON'T end up inside the range, something has gone really wrong. 617 if !last_good {
590 if (last_written < sval) || (last_written > eval) { 618 defmt::println!("Last not good!");
591 return Err(Error::Calculation); 619 // The last is NOT good (it's the line-break `0x00`), so elide it
620 next_addr -= 1;
621 } else {
622 defmt::println!("last good!");
592 } 623 }
593 let taken = last_written - sval; 624
594 return Ok(&mut buffer[..taken]); 625 defmt::println!("->{=usize}", next_addr - sval);
626
627 return Ok(next_addr - sval);
595 } else if errors.oeris() { 628 } else if errors.oeris() {
596 return Err(Error::Overrun); 629 return Err(ReadToBreakError::Other(Error::Overrun));
597 } else if errors.peris() { 630 } else if errors.peris() {
598 return Err(Error::Parity); 631 return Err(ReadToBreakError::Other(Error::Parity));
599 } else if errors.feris() { 632 } else if errors.feris() {
600 return Err(Error::Framing); 633 return Err(ReadToBreakError::Other(Error::Framing));
601 } 634 }
602 unreachable!("unrecognized rx error"); 635 unreachable!("unrecognized rx error");
603 } 636 }
@@ -902,7 +935,7 @@ impl<'d, T: Instance> Uart<'d, T, Async> {
902 self.rx.read(buffer).await 935 self.rx.read(buffer).await
903 } 936 }
904 937
905 pub async fn read_to_break<'a>(&mut self, buf: &'a mut [u8]) -> Result<&'a mut [u8], Error> { 938 pub async fn read_to_break<'a>(&mut self, buf: &'a mut [u8]) -> Result<usize, ReadToBreakError> {
906 self.rx.read_to_break(buf).await 939 self.rx.read_to_break(buf).await
907 } 940 }
908} 941}
@@ -1004,7 +1037,6 @@ impl embedded_hal_nb::serial::Error for Error {
1004 Self::Break => embedded_hal_nb::serial::ErrorKind::Other, 1037 Self::Break => embedded_hal_nb::serial::ErrorKind::Other,
1005 Self::Overrun => embedded_hal_nb::serial::ErrorKind::Overrun, 1038 Self::Overrun => embedded_hal_nb::serial::ErrorKind::Overrun,
1006 Self::Parity => embedded_hal_nb::serial::ErrorKind::Parity, 1039 Self::Parity => embedded_hal_nb::serial::ErrorKind::Parity,
1007 Self::Calculation => embedded_hal_nb::serial::ErrorKind::Other,
1008 } 1040 }
1009 } 1041 }
1010} 1042}