Skip to content
This repository has been archived by the owner on May 23, 2024. It is now read-only.

Commit

Permalink
Defmt: add to CI, actually provide defmt-raw feature (#49)
Browse files Browse the repository at this point in the history
* Add defmt-raw

* Respect critical section in defmt

* Add log drivers to CI
  • Loading branch information
bugadani committed Sep 4, 2023
1 parent c15e85d commit 1f06472
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 39 deletions.
40 changes: 30 additions & 10 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,19 +1,39 @@
[target.riscv32imc-unknown-none-elf]
runner = "espflash --speed 921600 --monitor"

rustflags = [
"-C", "link-arg=-Tlinkall.x",
# comment the cfgs below if you do _not_ wish to emulate atomics.
# enable the atomic codegen option for RISCV
"-C", "target-feature=+a",
# tell the core library have atomics even though it's not specified in the target definition
"--cfg", "target_has_atomic_load_store",
"--cfg", 'target_has_atomic_load_store="8"',
"--cfg", 'target_has_atomic_load_store="16"',
"--cfg", 'target_has_atomic_load_store="32"',
"--cfg", 'target_has_atomic_load_store="ptr"',
# enable cas
"--cfg", "target_has_atomic",
"--cfg", 'target_has_atomic="8"',
"--cfg", 'target_has_atomic="16"',
"--cfg", 'target_has_atomic="32"',
"--cfg", 'target_has_atomic="ptr"',
]

[target.xtensa-esp32-none-elf]
runner = "espflash --speed 921600 --monitor"

[target.xtensa-esp32s2-none-elf]
rustflags = [
"-C", "link-arg=-Tlinkall.x",
# Enable the atomic codegen option for Xtensa
"-C", "target-feature=+s32c1i",
# tell the core library have atomics even though it's not specified in the target definition
"--cfg", "target_has_atomic_load_store",
"--cfg", 'target_has_atomic_load_store="8"',
"--cfg", 'target_has_atomic_load_store="16"',
"--cfg", 'target_has_atomic_load_store="32"',
"--cfg", 'target_has_atomic_load_store="ptr"',
# enable cas
"--cfg", "target_has_atomic",
"--cfg", 'target_has_atomic="8"',
"--cfg", 'target_has_atomic="16"',
"--cfg", 'target_has_atomic="32"',
"--cfg", 'target_has_atomic="ptr"',
]

[build]
target = "riscv32imc-unknown-none-elf"

[unstable]
build-std = [ "core" ]
21 changes: 21 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,27 @@ jobs:
- uses: Swatinem/rust-cache@v2
- run: cargo check -Zbuild-std=core --no-default-features --target=xtensa-${{ matrix.chip }}-none-elf --features=${{ matrix.chip }},${{ matrix.printer }}

check-log-riscv:
name: Log drivers
runs-on: ubuntu-latest
strategy:
matrix:
logger: ["", ",log", ",defmt", ",defmt-raw"]
color: [""]
critical-section: ["", ",critical-section"]
include:
- logger: ",log"
color: ",colors"
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@v1
with:
target: riscv32imc-unknown-none-elf
toolchain: nightly
components: rust-src
- uses: Swatinem/rust-cache@v2
- run: cargo check -Zbuild-std=core --no-default-features --target=riscv32imc-unknown-none-elf --features=uart,esp32c2${{ matrix.logger }}${{ matrix.color }}${{ matrix.critical-section }}

rustfmt:
name: Check formatting
runs-on: ubuntu-latest
Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ rtt = []
no-op = []

# Enables a `defmt` backend usable with espflash. We force rzcobs encoding to simplify implementation
defmt = ["dep:defmt", "defmt/encoding-rzcobs"]
defmt = ["dep:defmt", "defmt?/encoding-rzcobs"]
defmt-raw = ["dep:defmt", "defmt?/encoding-raw"]

# logging sub-features
colors = []
63 changes: 36 additions & 27 deletions src/defmt.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,44 @@
//! defmt global logger implementation.
// Implementation taken from defmt-rtt, with a custom framing prefix

#[cfg(feature = "critical-section")]
use core::sync::atomic::{AtomicBool, Ordering};

#[cfg(feature = "critical-section")]
use critical_section::RestoreState;

use super::Printer;

/// Global logger lock.
#[cfg(feature = "critical-section")]
static TAKEN: AtomicBool = AtomicBool::new(false);
#[cfg(feature = "critical-section")]
static mut CS_RESTORE: RestoreState = RestoreState::invalid();
static mut ENCODER: defmt::Encoder = defmt::Encoder::new();

#[defmt::global_logger]
pub struct Logger;
unsafe impl defmt::Logger for Logger {
fn acquire() {
// safety: Must be paired with corresponding call to release(), see below
let restore = unsafe { critical_section::acquire() };

// safety: accessing the `static mut` is OK because we have acquired a critical
// section.
if TAKEN.load(Ordering::Relaxed) {
panic!("defmt logger taken reentrantly")
#[cfg(feature = "critical-section")]
{
// safety: Must be paired with corresponding call to release(), see below
let restore = unsafe { critical_section::acquire() };

// safety: accessing the `static mut` is OK because we have acquired a critical
// section.
if TAKEN.load(Ordering::Relaxed) {
panic!("defmt logger taken reentrantly")
}

// safety: accessing the `static mut` is OK because we have acquired a critical
// section.
TAKEN.store(true, Ordering::Relaxed);

// safety: accessing the `static mut` is OK because we have acquired a critical
// section.
unsafe { CS_RESTORE = restore };
}

// safety: accessing the `static mut` is OK because we have acquired a critical
// section.
TAKEN.store(true, Ordering::Relaxed);

// safety: accessing the `static mut` is OK because we have acquired a critical
// section.
unsafe { CS_RESTORE = restore };

// If not disabled, write a non-UTF8 sequence to indicate the start of a defmt
// frame. We need this to distinguish defmt frames from other data that
// might be written to the printer.
Expand All @@ -49,20 +55,23 @@ unsafe impl defmt::Logger for Logger {
// section.
ENCODER.end_frame(do_write);

// We don't need to write a custom end-of-frame sequence because:
// - using `defmt`, the rzcobs encoding already includes a terminating zero
// - using `defmt-raw`, we don't add any additional framing data
#[cfg(feature = "critical-section")]
{
// We don't need to write a custom end-of-frame sequence because:
// - using `defmt`, the rzcobs encoding already includes a terminating zero
// - using `defmt-raw`, we don't add any additional framing data

// safety: accessing the `static mut` is OK because we have acquired a critical
// section.
TAKEN.store(false, Ordering::Relaxed);
// safety: accessing the `static mut` is OK because we have acquired a critical
// section.
TAKEN.store(false, Ordering::Relaxed);

// safety: accessing the `static mut` is OK because we have acquired a critical
// section.
let restore = CS_RESTORE;
// safety: accessing the `static mut` is OK because we have acquired a critical
// section.
let restore = CS_RESTORE;

// safety: Must be paired with corresponding call to acquire(), see above
critical_section::release(restore);
// safety: Must be paired with corresponding call to acquire(), see above
critical_section::release(restore);
}
}

unsafe fn flush() {}
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![no_std]

#[cfg(any(feature = "defmt", feature = "defmt_raw"))]
#[cfg(any(feature = "defmt", feature = "defmt-raw"))]
pub mod defmt;
#[cfg(feature = "log")]
pub mod logger;
Expand Down

0 comments on commit 1f06472

Please sign in to comment.