Added nonblocking UART logging module
This commit is contained in:
parent
accfc73248
commit
2f8516cce7
85
src/logger.rs
Normal file
85
src/logger.rs
Normal file
|
@ -0,0 +1,85 @@
|
|||
|
||||
use rp2040_hal::uart::{Enabled, UartDevice, UartPeripheral, ValidUartPinout};
|
||||
use embedded_hal::serial::Write;
|
||||
use heapless::spsc::Queue;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum LoggerError {
|
||||
OutOfMemory,
|
||||
WriteError
|
||||
}
|
||||
|
||||
pub struct Logger<D, P, const QLEN: usize>
|
||||
where
|
||||
D: UartDevice,
|
||||
P: ValidUartPinout<D>
|
||||
{
|
||||
uart: UartPeripheral<Enabled, D, P>,
|
||||
queue: Queue<u8, QLEN>,
|
||||
}
|
||||
|
||||
impl<D, P, const QLEN: usize> Logger<D, P, QLEN>
|
||||
where
|
||||
D: UartDevice,
|
||||
P: ValidUartPinout<D>
|
||||
{
|
||||
pub fn new(
|
||||
uart: UartPeripheral<Enabled, D, P>
|
||||
) -> Self
|
||||
{
|
||||
Logger::<D, P, QLEN> {
|
||||
uart,
|
||||
queue: Queue::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn log(&mut self, msg: &[u8]) -> Result<(), LoggerError>
|
||||
{
|
||||
for c in msg.iter() {
|
||||
match self.queue.enqueue(*c) {
|
||||
Ok(_) => {},
|
||||
Err(_c) => return Err(LoggerError::OutOfMemory)
|
||||
}
|
||||
}
|
||||
|
||||
self.process().map(|_| ())
|
||||
}
|
||||
|
||||
pub fn log_fatal(&mut self, msg: &[u8])
|
||||
{
|
||||
// first flush all data in the queue
|
||||
self.flush();
|
||||
|
||||
// enqueue the message
|
||||
let _ = self.log(msg);
|
||||
|
||||
// block until it is actually handed over to the hardware
|
||||
self.flush();
|
||||
}
|
||||
|
||||
pub fn flush(&mut self)
|
||||
{
|
||||
// call process() until no more data remains in the queue
|
||||
loop {
|
||||
match self.process() {
|
||||
Ok(more_data) => if !more_data {
|
||||
break;
|
||||
},
|
||||
Err(_) => break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// returns whether data remains in the queue
|
||||
pub fn process(&mut self) -> Result<bool, LoggerError>
|
||||
{
|
||||
while !self.queue.is_empty() && self.uart.uart_is_writable() {
|
||||
match self.uart.write(self.queue.dequeue().unwrap()) {
|
||||
Ok(_) => {},
|
||||
Err(_) => return Err(LoggerError::WriteError)
|
||||
}
|
||||
}
|
||||
|
||||
Ok(!self.queue.is_empty())
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue