#![deny(missing_docs)]
#![no_std]
use core::fmt;
#[macro_export]
macro_rules! dprint {
($s:expr) => {
$crate::write_str($s)
};
($($tt:tt)*) => {
$crate::write_fmt(format_args!($($tt)*))
};
}
#[macro_export]
macro_rules! dprintln {
() => {
$crate::write_str("\n")
};
($s:expr) => {
$crate::write_str(concat!($s, "\n"))
};
($s:expr, $($tt:tt)*) => {
$crate::write_fmt(format_args!(concat!($s, "\n"), $($tt)*))
};
}
pub struct Writer;
impl fmt::Write for Writer {
fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
write_str(s);
Ok(())
}
}
#[allow(unused_variables)]
#[inline(always)]
pub fn write(word: u32) {
match () {
#[cfg(not(target_arch = "arm"))]
() => unimplemented!(),
#[cfg(all(target_arch = "arm", feature = "nop"))]
() => {}
#[cfg(all(target_arch = "arm", not(feature = "nop")))]
() => {
const W: u32 = 1 << 29;
unsafe {
let mut r: u32;
loop {
core::arch::asm!("MRC p14, 0, {}, c0, c1, 0", out(reg) r);
if r & W == 0 {
break;
}
}
core::arch::asm!("MCR p14, 0, {}, c0, c5, 0", in(reg) word);
}
}
}
}
pub fn write_all(bytes: &[u8]) {
bytes.iter().for_each(|byte| write(u32::from(*byte)))
}
#[doc(hidden)]
pub fn write_fmt(args: fmt::Arguments) {
use core::fmt::Write;
Writer.write_fmt(args).ok();
}
pub fn write_str(string: &str) {
write_all(string.as_bytes())
}
#[cfg(target_arch = "arm")]
core::arch::global_asm!(
r#"
// Routine for putting data in the DCC register
.section .text.__dcc_write
.global __dcc_write
__dcc_write:
1: mrc p14, 0, r1, c0, c1, 0
tst r1, #536870912 /* 0x20000000 */
bne 1b
mcr p14, 0, r0, c0, c5, 0
bx lr
"#
);