summaryrefslogtreecommitdiffstats
path: root/ble/src/uarte1.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ble/src/uarte1.rs')
-rw-r--r--ble/src/uarte1.rs119
1 files changed, 90 insertions, 29 deletions
diff --git a/ble/src/uarte1.rs b/ble/src/uarte1.rs
index 61d631e..1afce29 100644
--- a/ble/src/uarte1.rs
+++ b/ble/src/uarte1.rs
@@ -4,6 +4,42 @@ use starb::{Reader, RingBuffer, Writer};
static mut RB: RingBuffer<u8> = RingBuffer::new(0);
+const BUFLEN: usize = 128;
+
+struct DoubleBuffer {
+ bank0: [u8; BUFLEN],
+ bank1: [u8; BUFLEN],
+ is_bank0: bool,
+}
+impl DoubleBuffer {
+ const fn new() -> Self {
+ Self {
+ bank0: [0; BUFLEN],
+ bank1: [0; BUFLEN],
+ is_bank0: true,
+ }
+ }
+
+ fn cur_ptr(&mut self) -> *mut u8 {
+ if self.is_bank0 {
+ self.bank0.as_mut_ptr()
+ } else {
+ self.bank1.as_mut_ptr()
+ }
+ }
+
+ fn next_ptr(&mut self) -> *mut u8 {
+ self.is_bank0 = !self.is_bank0;
+ if self.is_bank0 {
+ self.bank1.as_mut_ptr()
+ } else {
+ self.bank0.as_mut_ptr()
+ }
+ }
+}
+
+static mut DBL_BUFF: DoubleBuffer = DoubleBuffer::new();
+
pub fn setup<I>(mut uarte: Uarte<I>) -> (Reader<'static, u8>, impl FnMut())
where
I: uarte::Instance,
@@ -15,60 +51,73 @@ where
w.rxstarted().set_bit()
});
- let mut buf: [u8; 255] = [0; 255];
- uarte
- .0
- .rxd
- .ptr
- .write(|w| unsafe { w.ptr().bits(buf.as_mut_ptr() as _) });
+ let ptr = unsafe { DBL_BUFF.next_ptr() };
+ info!("setting up dma: p: {:x}, maxcnt: {}", ptr as u32, BUFLEN);
+ uarte.0.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) });
uarte
.0
.rxd
.maxcnt
- .write(|w| unsafe { w.maxcnt().bits(buf.len() as _) });
+ .write(|w| unsafe { w.maxcnt().bits(BUFLEN as _) });
uarte.0.tasks_startrx.write(|w| w.tasks_startrx().set_bit());
let (rbr, mut rbw) = unsafe { RB.split() };
// start rx into a buffer. it would be nice if we could do this
// with rxrdy or something like i2c does.
- let cl = move || handler(&mut uarte, &mut rbw, &mut buf);
+ let cl = move || handler(&mut uarte, &mut rbw);
(rbr, cl)
}
-fn handler<I>(uarte: &mut Uarte<I>, writer: &mut Writer<u8>, buf: &mut [u8])
+fn handler<I>(uarte: &mut Uarte<I>, writer: &mut Writer<u8>)
where
I: uarte::Instance,
{
if uarte.0.events_endrx.read().events_endrx().bit_is_set() {
uarte.0.events_endrx.write(|w| w.events_endrx().clear_bit());
- // Copy DMA buffer to ring buffer.
- let len = uarte.0.rxd.amount.read().amount().bits();
- info!("endrx - {}", len);
- for i in 0..len {
- writer.unshift(buf[i as usize]).ok();
+ // The buffer should be swapped from the RXSTARTED event, so
+ // we can restart the read immediately.
+ let optr = uarte.0.rxd.ptr.read().ptr().bits();
+ let ptr = unsafe { DBL_BUFF.cur_ptr() as u32 };
+ /*
+ if optr == ptr {
+ uarte
+ .0
+ .rxd
+ .ptr
+ .write(|w| unsafe { w.ptr().bits(DBL_BUFF.next_ptr() as _) });
}
+ */
+ uarte.0.tasks_startrx.write(|w| w.tasks_startrx().set_bit());
- // Reset the DMA buffer. TODO: this is probably unneccesary.
- uarte
- .0
- .rxd
- .ptr
- .write(|w| unsafe { w.ptr().bits(buf.as_mut_ptr() as _) });
- uarte
- .0
- .rxd
- .maxcnt
- .write(|w| unsafe { w.maxcnt().bits(buf.len() as _) });
+ // Copy DMA buffer to ring buffer.
+ let len = uarte.0.rxd.amount.read().amount().bits();
+ let mc = uarte.0.rxd.maxcnt.read().maxcnt().bits();
+ info!(
+ "endrx - l: {}, p: {:x}, mc: {}, b: {:x}",
+ len, optr, mc, ptr
+ );
+ flush_buf(writer, unsafe { DBL_BUFF.cur_ptr() }, len.into());
- // restart the read.
- uarte.0.tasks_startrx.write(|w| w.tasks_startrx().set_bit());
+ /*
+ uarte
+ .0
+ .rxd
+ .maxcnt
+ .write(|w| unsafe { w.maxcnt().bits(BUFLEN as _) });
+ */
} else if uarte.0.events_error.read().events_error().bit_is_set() {
uarte.0.events_error.write(|w| w.events_error().clear_bit());
- info!("error: {:b}", uarte.0.errorsrc.read().bits());
+
+ let len = uarte.0.rxd.amount.read().amount().bits();
+ info!("error: {:b} {}b", uarte.0.errorsrc.read().bits(), len,);
} else if uarte.0.events_rxto.read().events_rxto().bit_is_set() {
uarte.0.events_rxto.write(|w| w.events_rxto().clear_bit());
- info!("rxto");
+
+ let len = uarte.0.rxd.amount.read().amount().bits();
+ info!("rxto - {}", len);
+ flush_buf(writer, unsafe { DBL_BUFF.cur_ptr() }, len.into());
+ uarte.0.tasks_flushrx.write(|w| w.tasks_flushrx().set_bit());
} else if uarte
.0
.events_rxstarted
@@ -81,5 +130,17 @@ where
.events_rxstarted
.write(|w| w.events_rxstarted().clear_bit());
info!("rxstarted");
+
+ // Swap to the next buffer as soon as the transfer starts to
+ // try and lose as little data as possible.
+ let ptr = unsafe { DBL_BUFF.next_ptr() };
+ uarte.0.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) });
}
}
+
+fn flush_buf(writer: &mut Writer<u8>, ptr: *mut u8, len: usize) {
+ let buf = unsafe { core::slice::from_raw_parts(ptr, len) };
+ info!("flush start");
+ writer.unshift_from(buf);
+ info!("flush end");
+}