1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
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");
}
}
}
|