summaryrefslogtreecommitdiffstats
path: root/ble
diff options
context:
space:
mode:
Diffstat (limited to 'ble')
-rw-r--r--ble/Cargo.lock4
-rw-r--r--ble/Cargo.toml1
-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
6 files changed, 113 insertions, 83 deletions
diff --git a/ble/Cargo.lock b/ble/Cargo.lock
index 1818d36..41baa15 100644
--- a/ble/Cargo.lock
+++ b/ble/Cargo.lock
@@ -51,7 +51,7 @@ dependencies = [
"panic-semihosting 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rubble 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rubble-nrf52 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "starb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "starb 0.1.1",
]
[[package]]
@@ -299,7 +299,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "starb"
version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "syn"
@@ -377,7 +376,6 @@ dependencies = [
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
-"checksum starb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9f1f4612a1188db46379a8ce956a2c7e47f3995a9b16dceeb838c3e753a35e"
"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
diff --git a/ble/Cargo.toml b/ble/Cargo.toml
index ad11b18..7ef4dcf 100644
--- a/ble/Cargo.toml
+++ b/ble/Cargo.toml
@@ -25,6 +25,7 @@ rt = ["nrf52840-hal/rt"]
[patch.crates-io]
nrf52840-hal = { path = "../../nrf52-hal/nrf52840-hal" }
+starb = { path = "../../usbh/starb" }
[profile.dev]
incremental = false
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");
+}