|
| 1 | +//! An implementation of the defmt logging traits, but using the `log` crate for output |
| 2 | +
|
| 3 | +use std::sync::{Condvar, Mutex}; |
| 4 | + |
| 5 | +#[defmt::global_logger] |
| 6 | +struct FakeLogger; |
| 7 | + |
| 8 | +#[derive(PartialEq, Eq)] |
| 9 | +enum State { |
| 10 | + Waiting, |
| 11 | + AcquiredNeedAddr, |
| 12 | + WantArgs, |
| 13 | +} |
| 14 | + |
| 15 | +struct Context { |
| 16 | + state: State |
| 17 | +} |
| 18 | + |
| 19 | +impl Context { |
| 20 | + const fn new() -> Context { |
| 21 | + Context { |
| 22 | + state: State::Waiting |
| 23 | + } |
| 24 | + } |
| 25 | +} |
| 26 | + |
| 27 | +static CONTEXT: (Mutex<Context>, Condvar) = (Mutex::new(Context::new()), Condvar::new()); |
| 28 | + |
| 29 | +unsafe impl defmt::Logger for FakeLogger { |
| 30 | + fn acquire() { |
| 31 | + log::info!("Acquiring {:?}", std::thread::current().id()); |
| 32 | + let mut ctx = CONTEXT.0.lock().unwrap(); |
| 33 | + while ctx.state != State::Waiting { |
| 34 | + // sit on the condvar because only one thread can grab the lock |
| 35 | + ctx = CONTEXT.1.wait(ctx).unwrap(); |
| 36 | + } |
| 37 | + // cool, we can take it |
| 38 | + ctx.state = State::AcquiredNeedAddr; |
| 39 | + } |
| 40 | + |
| 41 | + unsafe fn flush() { |
| 42 | + log::info!("Flushing {:?}", std::thread::current().id()); |
| 43 | + } |
| 44 | + |
| 45 | + unsafe fn release() { |
| 46 | + log::info!("Releasing {:?}", std::thread::current().id()); |
| 47 | + let mut ctx = CONTEXT.0.lock().unwrap(); |
| 48 | + ctx.state = State::Waiting; |
| 49 | + CONTEXT.1.notify_one(); |
| 50 | + } |
| 51 | + |
| 52 | + unsafe fn write(bytes: &[u8]) { |
| 53 | + use std::convert::TryInto; |
| 54 | + log::info!("Bytes {:?} {:02x?}", std::thread::current().id(), bytes); |
| 55 | + let mut ctx = CONTEXT.0.lock().unwrap(); |
| 56 | + match ctx.state { |
| 57 | + State::Waiting => panic!("Unlocked write!!"), |
| 58 | + State::AcquiredNeedAddr => { |
| 59 | + let addr = &bytes[0..std::mem::size_of::<usize>()]; |
| 60 | + let addr: usize = usize::from_le_bytes(addr.try_into().unwrap()); |
| 61 | + let ptr = addr as *const &'static str; |
| 62 | + let format_str: &'static str = unsafe { ptr.read() }; |
| 63 | + log::info!("Format string: {}", format_str); |
| 64 | + ctx.state = State::WantArgs; |
| 65 | + }, |
| 66 | + State::WantArgs => { |
| 67 | + log::info!("Arg: {:02x?}", bytes); |
| 68 | + }, |
| 69 | + } |
| 70 | + } |
| 71 | +} |
| 72 | + |
| 73 | +#[export_name = "_defmt_timestamp"] |
| 74 | +fn defmt_timestamp(_: defmt::Formatter<'_>) {} |
0 commit comments