diff options
Diffstat (limited to 'ble/src/uarte1.rs')
-rw-r--r-- | ble/src/uarte1.rs | 119 |
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"); +} |