diff --git a/.vscode/settings.json b/.vscode/settings.json index f4964a4..8b9059e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,6 +2,7 @@ "editor.formatOnSave": true, "rust-analyzer.cargo.features": [ "esp32c3", + "jtag_serial" ], "rust-analyzer.cargo.target": "riscv32imc-unknown-none-elf", } \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index f9e1e6b..fbd783d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,8 @@ critical-section = { version = "1.1.1", optional = true } [features] default = ["uart", "critical-section"] +crlf = [] + # You must enable exactly 1 of the below features to support the correct chip: esp32 = [] esp32c2 = [] diff --git a/README.md b/README.md index 3dab645..b0ef63e 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,12 @@ # esp-println -Provides `print!` and `println!` implementations various Espressif devices. +Provides `print!` and `println!` implementations for various Espressif devices. - Supports ESP32, ESP32-C2/C3/C6, ESP32-H2, ESP32-S2/S3, and ESP8266 - Dependency free (not even depending on `esp-hal`, one optional dependency is `log`, another is `critical-section`) - Supports JTAG-Serial output where available - Supports RTT (lacking working RTT hosts besides _probe-rs_ for ESP32-C3) +- `no-op` features turns printing into a no-op ## RTT on ESP32-C3 diff --git a/src/lib.rs b/src/lib.rs index bbcd84c..7886503 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,10 +5,10 @@ pub mod logger; #[cfg(feature = "rtt")] mod rtt; +#[cfg(all(not(feature = "no-op"), not(feature = "crlf")))] #[macro_export] macro_rules! println { ($($arg:tt)*) => {{ - #[cfg(not(feature = "no-op"))] { use core::fmt::Write; writeln!($crate::Printer, $($arg)*).ok(); @@ -16,10 +16,22 @@ macro_rules! println { }}; } +#[cfg(all(not(feature = "no-op"), feature = "crlf"))] +#[macro_export] +macro_rules! println { + ($($arg:tt)*) => {{ + { + use core::fmt::Write; + write!($crate::Printer, $($arg)*).ok(); + write!($crate::Printer, "\r\n").ok(); + } + }}; +} + +#[cfg(not(feature = "no-op"))] #[macro_export] macro_rules! print { ($($arg:tt)*) => {{ - #[cfg(not(feature = "no-op"))] { use core::fmt::Write; write!($crate::Printer, $($arg)*).ok(); @@ -27,6 +39,18 @@ macro_rules! print { }}; } +#[cfg(feature = "no-op")] +#[macro_export] +macro_rules! println { + ($($arg:tt)*) => {{}}; +} + +#[cfg(feature = "no-op")] +#[macro_export] +macro_rules! print { + ($($arg:tt)*) => {{}}; +} + pub struct Printer; impl core::fmt::Write for Printer { @@ -76,9 +100,16 @@ mod serial_jtag_printer { impl super::Printer { pub fn write_bytes(&mut self, bytes: &[u8]) { super::with(|| { + const TIMEOUT_ITERATIONS: usize = 5_000; + let fifo = SERIAL_JTAG_FIFO_REG as *mut u32; let conf = SERIAL_JTAG_CONF_REG as *mut u32; + if unsafe { conf.read_volatile() } & 0b011 == 0b000 { + // still wasn't able to drain the FIFO - early return + return; + } + // todo 64 byte chunks max for chunk in bytes.chunks(32) { unsafe { @@ -87,8 +118,13 @@ mod serial_jtag_printer { } conf.write_volatile(0b001); + let mut timeout = TIMEOUT_ITERATIONS; while conf.read_volatile() & 0b011 == 0b000 { // wait + timeout -= 1; + if timeout == 0 { + return; + } } } }