diff options
author | Brian Cully <bjc@kublai.com> | 2019-06-24 21:14:32 -0400 |
---|---|---|
committer | Brian Cully <bjc@kublai.com> | 2019-07-23 19:55:18 -0400 |
commit | 63d4ce8154eb8f6feb67986e98ea9b5007632460 (patch) | |
tree | 187e66104eb7c848dcf73a5ee067c5f27235360a /app/src/log.rs | |
download | samd21-demo-63d4ce8154eb8f6feb67986e98ea9b5007632460.tar.gz samd21-demo-63d4ce8154eb8f6feb67986e98ea9b5007632460.zip |
Initial commit.
Diffstat (limited to 'app/src/log.rs')
-rw-r--r-- | app/src/log.rs | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/app/src/log.rs b/app/src/log.rs new file mode 100644 index 0000000..6cfba8f --- /dev/null +++ b/app/src/log.rs @@ -0,0 +1,95 @@ +use rb::{Reader, RingBuffer, Writer}; + +use core::fmt::{self, Write}; +use embedded_hal::{digital::v2::OutputPin, serial}; +use trinket_m0::{ + gpio::{Pa6, Pa7, PfD}, + sercom::{Sercom0Pad2, Sercom0Pad3, UART0}, +}; + +static mut LB: RingBuffer<u8> = RingBuffer::<u8>::new(0); + +struct JoinedRingBuffer<'a> { + lbr: Reader<'a, u8>, + lbw: Writer<'a, u8>, +} + +impl<'a> JoinedRingBuffer<'a> { + const fn new(rb: &'a RingBuffer<u8>) -> Self { + let (lbr, lbw) = rb.split(); + Self { lbr: lbr, lbw: lbw } + } +} + +impl 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(()); + } + } + Ok(()) + } +} + +static mut LOGBUF: JoinedRingBuffer = unsafe { JoinedRingBuffer::new(&LB) }; +static mut UART0: usize = 0; + +pub struct Processor<W, L> { + uart: W, + led: L, +} + +impl<W, L> Processor<W, L> +where + W: serial::Write<u8>, + L: OutputPin, +{ + pub fn new(uart: W, led: L) -> Self { + // Unsafe because we're creating a mutable alias. + unsafe { UART0 = core::mem::transmute(&uart) }; + Self { + uart: uart, + led: led, + } + } + + pub fn task(&mut self) { + // Unsafe due to mutable static. + if unsafe { LOGBUF.lbr.is_empty() } { + return; + } + self.led.set_high().ok(); + // Unsafe due to mutable static. + while let Some(b) = unsafe { LOGBUF.lbr.shift() } { + nb::block!(self.uart.write(b)).ok(); + } + self.led.set_low().ok(); + } +} + +// Write to the UART right now, instead of putting it on a ring +// buffer. This function is a huge hack, and only useful for debugging +// either before the main loop starts or if the ring buffer is broken. +pub unsafe fn write_fmt_now(args: fmt::Arguments, nl: bool) { + if UART0 == 0 { + return; + } + let uart: &mut UART0<Sercom0Pad3<Pa7<PfD>>, Sercom0Pad2<Pa6<PfD>>, (), ()> = + core::mem::transmute(UART0); + fmt::write(uart, args).expect("writing fmt now to uart"); + if nl { + uart.write_str("\r\n").expect("writing nl now to uart"); + } +} + +pub fn write_fmt(args: fmt::Arguments, nl: bool) { + // Unsafe due to mutable static. + unsafe { + fmt::write(&mut LOGBUF, args).expect("writing fmt to log"); + if nl { + LOGBUF.write_str("\r\n").expect("writing nl to log"); + } + } +} |