#![doc(html_logo_url = "https://knurling.ferrous-systems.com/knurling_logo_light_text.svg")]
#![no_std]
use core::sync::atomic::{AtomicBool, Ordering};
use cortex_m::{
asm, itm,
peripheral::{itm::Stim, ITM},
};
#[cfg(armv6m)]
compile_error!(
"`defmt-itm` cannot be used on Cortex-M0(+) chips, because it requires an ITM peripheral"
);
static ENABLED: AtomicBool = AtomicBool::new(false);
pub fn enable(itm: ITM) {
unsafe { itm.ter[0].write(1) }
ENABLED.store(true, Ordering::Relaxed);
}
#[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();
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 {
let encoder: &mut defmt::Encoder = &mut *core::ptr::addr_of_mut!(ENCODER);
encoder.start_frame(do_write)
}
}
unsafe fn flush() {
while !stim_0().is_fifo_ready() {}
asm::delay(100);
}
unsafe fn release() {
unsafe {
let encoder: &mut defmt::Encoder = &mut *core::ptr::addr_of_mut!(ENCODER);
encoder.end_frame(do_write);
}
TAKEN.store(false, Ordering::Relaxed);
let restore = unsafe { CS_RESTORE };
unsafe {
critical_section::release(restore);
}
}
unsafe fn write(bytes: &[u8]) {
unsafe {
let encoder: &mut defmt::Encoder = &mut *core::ptr::addr_of_mut!(ENCODER);
encoder.write(bytes, do_write);
}
}
}
fn do_write(bytes: &[u8]) {
unsafe { itm::write_all(stim_0(), bytes) }
}
unsafe fn stim_0<'a>() -> &'a mut Stim {
&mut (*ITM::PTR).stim[0]
}