summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Cully <bjc@kublai.com>2019-08-13 14:19:05 -0400
committerBrian Cully <bjc@kublai.com>2019-08-13 15:33:41 -0400
commitede53457a9d37ac62221d18cbfcca459e58ced94 (patch)
tree2beb44c3c9eeab2a456b0d3b6724b83eb58ab22c
parente158425081f1bce61051969c3059f09546c31dc7 (diff)
downloadbleusb-ede53457a9d37ac62221d18cbfcca459e58ced94.tar.gz
bleusb-ede53457a9d37ac62221d18cbfcca459e58ced94.zip
Basic, and somewhat broken, UARTE1 handling.
Using this for serial output from the Trinket M0. Currently it needs to fill up a DMA buffer before we get any output, and it seems like some data is being lost. But at least its not garbled, so there's nothing wrong with the UART device setup.
-rw-r--r--ble/src/main.rs53
-rw-r--r--ble/src/uarte1.rs85
2 files changed, 131 insertions, 7 deletions
diff --git a/ble/src/main.rs b/ble/src/main.rs
index 2da6de9..3c98b7e 100644
--- a/ble/src/main.rs
+++ b/ble/src/main.rs
@@ -7,13 +7,13 @@ mod i2c;
mod logger;
mod macros;
mod rtc;
+mod uarte1;
use clint::HandlerArray;
-use core::fmt::Write;
use core::mem;
use cortex_m::asm::wfi;
use cortex_m_rt::{entry, exception, ExceptionFrame};
-use log::{info, trace, LevelFilter};
+use log::{info, LevelFilter};
#[allow(unused_imports)]
extern crate panic_semihosting;
@@ -33,7 +33,6 @@ const I2C_ADDR: u8 = 4;
// TODO:
// * set up serial reader for trinket
-// * set up i²c interface for keyboard reports
// * and, finally, bluetooth
// Interrupt handler table.
@@ -53,7 +52,7 @@ fn main() -> ! {
let mut nvic = nrf52.NVIC;
let mut rtc_handler = rtc::setup(Rtc::new(nrf52.RTC0), Clocks::new(nrf52.CLOCK));
- let mut twis_handler = i2c::setup(Twis::new(
+ let (mut twis_reader, mut twis_handler) = i2c::setup(Twis::new(
I2C_ADDR,
nrf52.TWIS0,
twis::Pins {
@@ -68,27 +67,62 @@ fn main() -> ! {
.into_push_pull_output(Level::High)
.degrade();
let rxp = nrf52.pins.P0_25.into_floating_input().degrade();
- let mut uarte1 = uarte1(nrf52.UARTE1, txp, rxp);
+ let uarte1 = uarte1(nrf52.UARTE1, txp, rxp);
+ let (mut uarte1_reader, mut uarte1_handler) = uarte1::setup(uarte1);
HANDLERS.with_overrides(|hs| {
hs.register(0, &mut rtc_handler);
nvic.enable(Interrupt::RTC0);
hs.register(1, &mut twis_handler);
nvic.enable(Interrupt::SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
+ hs.register(2, &mut uarte1_handler);
+ nvic.enable(Interrupt::UARTE1);
info!("Bootstrap complete.");
let mut last_tick = rtc::millis();
last_tick -= last_tick % 1024;
+ let mut buf: [u8; 256] = [0; 256];
loop {
let tick = rtc::millis();
if tick >= last_tick + 1024 {
last_tick = tick;
last_tick -= last_tick % 1024;
- trace!(".");
- write!(uarte1, "!").expect("uarte1 write");
}
+ 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]);
+ }
+
+ 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;
+ }
+ info!(
+ "serial - {}: {}",
+ i,
+ core::str::from_utf8(&buf[0..i]).expect("utf8conv")
+ );
+ }
wfi();
}
});
@@ -132,3 +166,8 @@ fn RTC0() {
fn SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0() {
HANDLERS.call(1);
}
+
+#[interrupt]
+fn UARTE1() {
+ HANDLERS.call(2);
+}
diff --git a/ble/src/uarte1.rs b/ble/src/uarte1.rs
new file mode 100644
index 0000000..61d631e
--- /dev/null
+++ b/ble/src/uarte1.rs
@@ -0,0 +1,85 @@
+use log::info;
+use nrf52840_hal::uarte::{self, Uarte};
+use starb::{Reader, RingBuffer, Writer};
+
+static mut RB: RingBuffer<u8> = RingBuffer::new(0);
+
+pub fn setup<I>(mut uarte: Uarte<I>) -> (Reader<'static, u8>, impl FnMut())
+where
+ I: uarte::Instance,
+{
+ uarte.0.intenset.write(|w| {
+ w.endrx().set_bit();
+ w.error().set_bit();
+ w.rxto().set_bit();
+ 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 _) });
+ uarte
+ .0
+ .rxd
+ .maxcnt
+ .write(|w| unsafe { w.maxcnt().bits(buf.len() 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);
+ (rbr, cl)
+}
+
+fn handler<I>(uarte: &mut Uarte<I>, writer: &mut Writer<u8>, buf: &mut [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();
+ }
+
+ // 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 _) });
+
+ // restart the read.
+ uarte.0.tasks_startrx.write(|w| w.tasks_startrx().set_bit());
+ } 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());
+ } 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");
+ } else if uarte
+ .0
+ .events_rxstarted
+ .read()
+ .events_rxstarted()
+ .bit_is_set()
+ {
+ uarte
+ .0
+ .events_rxstarted
+ .write(|w| w.events_rxstarted().clear_bit());
+ info!("rxstarted");
+ }
+}