#![cfg_attr(not(feature = "logger"), allow(dead_code))]
#![no_std]
use core::{
mem::MaybeUninit,
sync::atomic::{AtomicBool, Ordering},
};
mod ring_buffer;
pub use ring_buffer::{RingBuf, RingBuffer};
#[cfg_attr(feature = "logger", defmt::global_logger)]
struct Logger;
static TAKEN: AtomicBool = AtomicBool::new(false);
static mut CS_RESTORE: critical_section::RestoreState = critical_section::RestoreState::invalid();
static mut ENCODER: defmt::Encoder = defmt::Encoder::new();
static mut RING_BUFFER: Option<&'static mut dyn RingBuf> = None;
static mut LOG_AVAILABLE: fn() = || ();
unsafe impl defmt::Logger for Logger {
fn acquire() {
let restore = unsafe { critical_section::acquire() };
if TAKEN.load(Ordering::Relaxed) {
panic!("defmt logger taken reentrantly")
}
TAKEN.store(true, Ordering::Relaxed);
unsafe { CS_RESTORE = restore };
unsafe {
#[allow(static_mut_refs)]
ENCODER.start_frame(do_write)
}
}
unsafe fn flush() {
}
unsafe fn release() {
#[allow(static_mut_refs)]
ENCODER.end_frame(do_write);
TAKEN.store(false, Ordering::Relaxed);
let restore = CS_RESTORE;
critical_section::release(restore);
}
unsafe fn write(bytes: &[u8]) {
#[allow(static_mut_refs)]
ENCODER.write(bytes, do_write);
}
}
fn do_write(data: &[u8]) {
unsafe {
#![allow(static_mut_refs)]
if let Some(buffer) = RING_BUFFER.as_mut() {
buffer.write(data);
LOG_AVAILABLE();
}
}
}
pub unsafe fn init<const SIZE: usize>(
ring_buffer: &'static mut MaybeUninit<RingBuffer<SIZE>>, log_available: fn(),
) {
defmt::assert!({
#[allow(static_mut_refs)]
RING_BUFFER.is_none()
});
let ring_buffer = RingBuffer::init(ring_buffer);
RING_BUFFER = Some(ring_buffer as &mut dyn RingBuf);
LOG_AVAILABLE = log_available;
}
pub fn read(data: &mut [u8]) -> (usize, bool) {
unsafe {
critical_section::with(|_cs| {
#[allow(static_mut_refs)]
if let Some(buffer) = RING_BUFFER.as_mut() {
buffer.read(data)
} else {
(0, false)
}
})
}
}