Skip to content

Commit 335fe81

Browse files
Merge pull request #943 from driveraid/smp
defmt-semihosting: use critical_section for synchronization.
2 parents 45ae892 + 210508c commit 335fe81

File tree

4 files changed

+31
-10
lines changed

4 files changed

+31
-10
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,8 @@ Initial release
705705

706706
### [defmt-semihosting-next]
707707

708+
* [#943] use critical_section for synchronization.
709+
708710
### [defmt-semihosting-v0.1.0] (2024-11-27)
709711

710712
Initial release

firmware/defmt-semihosting/Cargo.toml

+4
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,7 @@ version = "0.1.0"
1414
defmt = { version = "0.3", path = "../../defmt" }
1515
cortex-m = "0.7"
1616
cortex-m-semihosting = "0.5"
17+
critical-section = "1.2"
18+
19+
[features]
20+
critical-section-single-core = ["cortex-m/critical-section-single-core"]

firmware/defmt-semihosting/src/lib.rs

+24-9
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,19 @@
44
//!
55
//! WARNING using `cortex_m_semihosting`'s `hprintln!` macro or `HStdout` API will corrupt `defmt`
66
//! log frames so don't use those APIs.
7+
//!
8+
//! # Critical section implementation
9+
//!
10+
//! This crate uses [`critical-section`](https://github.com/rust-embedded/critical-section) to ensure only one thread
11+
//! is writing to the buffer at a time. You must import a crate that provides a `critical-section` implementation
12+
//! suitable for the current target. See the `critical-section` README for details.
13+
//!
14+
//! For example, for single-core privileged-mode Cortex-M targets, you can add the following to your Cargo.toml.
15+
//!
16+
//! ```toml
17+
//! [dependencies]
18+
//! cortex-m = { version = "0.7.6", features = ["critical-section-single-core"]}
19+
//! ```
720
821
#![no_std]
922
// nightly warns about static_mut_refs, but 1.76 (our MSRV) does not know about
@@ -12,20 +25,19 @@
1225

1326
use core::sync::atomic::{AtomicBool, Ordering};
1427

15-
use cortex_m::{interrupt, register};
1628
use cortex_m_semihosting::hio;
1729

1830
#[defmt::global_logger]
1931
struct Logger;
2032

2133
static TAKEN: AtomicBool = AtomicBool::new(false);
22-
static INTERRUPTS_ACTIVE: AtomicBool = AtomicBool::new(false);
34+
static mut CS_RESTORE: critical_section::RestoreState = critical_section::RestoreState::invalid();
2335
static mut ENCODER: defmt::Encoder = defmt::Encoder::new();
2436

2537
unsafe impl defmt::Logger for Logger {
2638
fn acquire() {
27-
let primask = register::primask::read();
28-
interrupt::disable();
39+
// safety: Must be paired with corresponding call to release(), see below
40+
let restore = unsafe { critical_section::acquire() };
2941

3042
if TAKEN.load(Ordering::Relaxed) {
3143
panic!("defmt logger taken reentrantly")
@@ -34,7 +46,8 @@ unsafe impl defmt::Logger for Logger {
3446
// no need for CAS because interrupts are disabled
3547
TAKEN.store(true, Ordering::Relaxed);
3648

37-
INTERRUPTS_ACTIVE.store(primask.is_active(), Ordering::Relaxed);
49+
// safety: accessing the `static mut` is OK because we have acquired a critical section.
50+
unsafe { CS_RESTORE = restore };
3851

3952
// safety: accessing the `static mut` is OK because we have disabled interrupts.
4053
unsafe { ENCODER.start_frame(do_write) }
@@ -52,10 +65,12 @@ unsafe impl defmt::Logger for Logger {
5265
ENCODER.end_frame(do_write);
5366

5467
TAKEN.store(false, Ordering::Relaxed);
55-
if INTERRUPTS_ACTIVE.load(Ordering::Relaxed) {
56-
// re-enable interrupts
57-
interrupt::enable()
58-
}
68+
69+
// safety: accessing the `static mut` is OK because we have acquired a critical section.
70+
let restore = unsafe { CS_RESTORE };
71+
72+
// safety: Must be paired with corresponding call to acquire(), see above
73+
unsafe { critical_section::release(restore) };
5974
}
6075

6176
unsafe fn write(bytes: &[u8]) {

firmware/qemu/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ harness = false
1414
defmt = { path = "../../defmt" }
1515
defmt-semihosting = { path = "../defmt-semihosting" }
1616
defmt-test = { path = "../defmt-test" }
17-
cortex-m = "0.7"
17+
cortex-m = { version = "0.7", features = ["critical-section-single-core"] }
1818
cortex-m-rt = "0.7"
1919
cortex-m-semihosting = "0.5"
2020
alloc-cortex-m = { version = "0.4", optional = true }

0 commit comments

Comments
 (0)