Skip to content
This repository was archived by the owner on May 23, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
"editor.formatOnSave": true,
"rust-analyzer.cargo.features": [
"esp32c3",
"jtag_serial"
"jtag_serial",
"log"
],
"rust-analyzer.cargo.target": "riscv32imc-unknown-none-elf",
"rust-analyzer.showUnlinkedFileNotification": false,
}
7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ log = { version = "0.4.17", optional = true }
critical-section = { version = "1.1.1", optional = true }

[features]
default = ["uart", "critical-section"]
default = ["uart", "critical-section", "colors"]

crlf = []

log = ["dep:log"]

# You must enable exactly 1 of the below features to support the correct chip:
esp32 = []
esp32c2 = []
Expand All @@ -40,3 +42,6 @@ uart = []
jtag_serial = [] # C3, C6, H2, and S3 only!
rtt = []
no-op = []

# logging sub-features
colors = []
23 changes: 21 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# esp-println

Provides `print!` and `println!` implementations for various Espressif devices.
Provides `print!`, `println!` and `dbg!` 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
## RTT on ESP32-C3 / ESP32-C6

The _cli_ utility should work for flashing and showing RTT logs on ESP32-C3 by using it's `run` command.
You need to use the `direct-boot` feature of the HAL to flash via _probe-rs_.
Expand All @@ -31,6 +31,25 @@ use esp_println::println;

You can now `println!("Hello world")` as usual.

## Logging

With the feature `log` activated you can initialize a simple logger like this
```rust
init_logger(log::LevelFilter::Info);
```

There is a default feature `colors` which enables colored log output.

Additionally you can use
```rust
init_logger_from_env();
```

In this case the following environment variables are used:
- `ESP_LOGLEVEL` sets the log level, use values like `trace`, `info` etc.
- `ESP_LOGTARGETS` if set you should provide the crate names of crates (optionally with a path e.g. `esp_wifi::compat::common`) which should get logged, separated by `,` and no additional whitespace between

If this simple logger implementation isn't sufficient for your needs you can implement your own logger on top of `esp-println` - see https://docs.rs/log/0.4.17/log/#implementing-a-logger

## License

Expand Down
57 changes: 56 additions & 1 deletion src/logger.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
use core::str::FromStr;

use log::LevelFilter;

use super::println;

const LOG_TARGETS: Option<&'static str> = option_env!("ESP_LOGTARGETS");

pub fn init_logger(level: log::LevelFilter) {
unsafe {
log::set_logger_racy(&EspLogger).unwrap();
}

log::set_max_level(level);
}

pub fn init_logger_from_env() {
unsafe {
log::set_logger_racy(&EspLogger).unwrap();
}

const LEVEL: Option<&'static str> = option_env!("ESP_LOGLEVEL");

if let Some(lvl) = LEVEL {
let level = LevelFilter::from_str(lvl).unwrap_or_else(|_| LevelFilter::Off);
log::set_max_level(level);
}
}
Expand All @@ -14,8 +34,43 @@ impl log::Log for EspLogger {
true
}

#[allow(unused)]
fn log(&self, record: &log::Record) {
println!("{} - {}", record.level(), record.args());
// check enabled log targets if any
if let Some(targets) = LOG_TARGETS {
if targets
.split(",")
.find(|v| record.target().starts_with(v))
.is_none()
{
return;
}
}

const RESET: &str = "\u{001B}[0m";
const RED: &str = "\u{001B}[31m";
const GREEN: &str = "\u{001B}[32m";
const YELLOW: &str = "\u{001B}[33m";
const BLUE: &str = "\u{001B}[34m";
const CYAN: &str = "\u{001B}[35m";

#[cfg(feature = "colors")]
let color = match record.level() {
log::Level::Error => RED,
log::Level::Warn => YELLOW,
log::Level::Info => GREEN,
log::Level::Debug => BLUE,
log::Level::Trace => CYAN,
};
#[cfg(feature = "colors")]
let reset = RESET;

#[cfg(not(feature = "colors"))]
let color = "";
#[cfg(not(feature = "colors"))]
let reset = "";

println!("{}{} - {}{}", color, record.level(), record.args(), reset);
}

fn flush(&self) {}
Expand Down