summaryrefslogtreecommitdiffstats
path: root/ble/src
diff options
context:
space:
mode:
authorBrian Cully <bjc@kublai.com>2019-08-13 20:35:16 -0400
committerBrian Cully <bjc@kublai.com>2019-08-13 20:35:16 -0400
commit852c73760589e663e484c1783bd5b73c7df6907c (patch)
treeba47ed0dba656530346133984abf4b70c1c6d739 /ble/src
parent32054b06803988cd06e3c7913454856e4fdc5906 (diff)
downloadbleusb-852c73760589e663e484c1783bd5b73c7df6907c.tar.gz
bleusb-852c73760589e663e484c1783bd5b73c7df6907c.zip
Use bulk starb read/write operations.
This should speed things up a bit, but, unfortunately, doesn't solve my serial1 problems.
Diffstat (limited to 'ble/src')
-rw-r--r--ble/src/i2c.rs8
-rw-r--r--ble/src/logger.rs26
-rw-r--r--ble/src/main.rs38
-rw-r--r--ble/src/uarte1.rs119
4 files changed, 111 insertions, 80 deletions
diff --git a/ble/src/i2c.rs b/ble/src/i2c.rs
index 0f7fe5e..b5a5114 100644
--- a/ble/src/i2c.rs
+++ b/ble/src/i2c.rs
@@ -39,11 +39,9 @@ where
let mut buf: [u8; 255] = [0; 255];
match twis.read(&mut buf) {
Ok(len) => {
- for b in &buf[0..len] {
- // Ignore unshift errors for now, as I don't think
- // there's much we can do about it.
- writer.unshift(*b).ok();
- }
+ // Ignore unshift overflow for now, as I don't think
+ // there's much we can do about it.
+ writer.unshift_from(&buf[0..len]);
trace!("write done");
}
Err(e) => error!("{:?}", e),
diff --git a/ble/src/logger.rs b/ble/src/logger.rs
index f102b74..b4167b2 100644
--- a/ble/src/logger.rs
+++ b/ble/src/logger.rs
@@ -2,6 +2,7 @@ use crate::rtc;
use core::cell::UnsafeCell;
use core::fmt::{self, Write};
+use core::mem::MaybeUninit;
use log::{Metadata, Record};
use nrf52840_hal::{target::UARTE0, uarte, Uarte};
use starb::{Reader, RingBuffer, Writer};
@@ -22,12 +23,9 @@ impl<'a> JoinedRingBuffer<'a> {
impl fmt::Write for JoinedRingBuffer<'_> {
fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
- for b in s.bytes() {
- if let Err(_) = self.lbw.unshift(b) {
- // Ignore buffer full errors for logging.
- return Ok(());
- }
- }
+ // Drop anything that couldn't fit on the ground so we don't
+ // back up.
+ self.lbw.unshift_from(s.as_bytes());
Ok(())
}
}
@@ -94,20 +92,12 @@ where
}
fn flush(&self) {
- // Unsafe due to mutable static. We can only deal with the
- // tail position of the buffer here to keep things safe.
let jrb = unsafe { &mut JRB };
- if jrb.lbr.is_empty() {
- return;
- }
-
let writer = unsafe { &mut (*self.writer.get()) };
- while let Some(b) = jrb.lbr.shift() {
- // TODO: The UARTE peripheral uses DMA to send a bunch of
- // stuff at speed, in hardware. It would be nice to use
- // it, but we can't just take a slice of the ring buffer,
- // since we don't know about its internal structure here.
- writer.w.write(&[b]).expect("writing log");
+ let mut buf: [u8; 256] = unsafe { MaybeUninit::<[u8; 256]>::uninit().assume_init() };
+ let len = jrb.lbr.shift_into(&mut buf);
+ if len > 0 {
+ writer.w.write(&buf[0..len]).expect("writing log")
}
}
}
diff --git a/ble/src/main.rs b/ble/src/main.rs
index 3c98b7e..71e3b82 100644
--- a/ble/src/main.rs
+++ b/ble/src/main.rs
@@ -90,38 +90,20 @@ fn main() -> ! {
last_tick -= last_tick % 1024;
}
- if !twis_reader.is_empty() {
- let mut i = 0;
- for b in &mut twis_reader {
- if i == buf.len() {
- info!("i²c data: {:?}", &buf[0..i]);
- i = 0;
- }
- buf[i] = b;
- i += 1;
- }
- info!("i²c data: {:?}", &buf[0..i]);
+ let mut len = twis_reader.shift_into(&mut buf);
+ while len > 0 {
+ info!("i²c data: {:?}", &buf[0..len]);
+ len = twis_reader.shift_into(&mut buf);
}
- if !uarte1_reader.is_empty() {
- let mut i = 0;
- for b in &mut uarte1_reader {
- if i == buf.len() {
- info!(
- "serial - {}: {}",
- i,
- core::str::from_utf8(&buf[0..i]).expect("utf8conv")
- );
- i = 0;
- }
- buf[i] = b;
- i += 1;
- }
+ let mut len = uarte1_reader.shift_into(&mut buf);
+ while len > 0 {
info!(
- "serial - {}: {}",
- i,
- core::str::from_utf8(&buf[0..i]).expect("utf8conv")
+ "serial {}: {}",
+ len,
+ core::str::from_utf8(&buf[0..len]).expect("utf8conv")
);
+ len = uarte1_reader.shift_into(&mut buf);
}
wfi();
}
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");
+}