Skip to content

Commit d391e46

Browse files
authored
Merge pull request #49 from probe-rs/defmt
General overhaul and defmt support
2 parents 3d14e3b + 04cbd89 commit d391e46

File tree

15 files changed

+218
-103
lines changed

15 files changed

+218
-103
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
[workspace]
22
members = ["examples-cortex-m", "rtt-target", "panic-rtt-target", "panic-test"]
3+
resolver = "2"
34

45
[patch.crates-io]
56
rtt-target = { path = "./rtt-target" }

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ fn main() {
2727
}
2828
```
2929

30+
`rtt-target` also supports initializing multiple RTT channels, and even has a logger implementation
31+
for [`defmt`](https://defmt.ferrous-systems.com/) that can be used in conjunction with arbitrary
32+
channel setups. The `defmt` integration requires setting `features = ["defmt"]`, and the used
33+
channel needs to be manually configured with `set_defmt_channel`.
34+
35+
For more information, please check out the [documentation](https://docs.rs/rtt-target).
36+
3037
## Development
3138

3239
The examples-cortex-m and panic-test crates come with build files for the venerable STM32F103C8xx by default, but can be easily adapted for any chip as they contain only minimal platform-specific runtime code to get `fn main` to run.

examples-cortex-m/.cargo/config.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[build]
2+
target = "thumbv7m-none-eabi"
3+
4+
[unstable]
5+
build-std = ["core"]

examples-cortex-m/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@ version = "0.1.0"
44
authors = ["Matti Virkkunen <[email protected]>"]
55
edition = "2018"
66

7+
[features]
8+
defmt = ["dep:defmt", "rtt-target/defmt"]
9+
710
[dependencies]
811
cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
912
cortex-m-rt = "0.7"
1013
panic-halt = "0.2.0"
1114
rtt-target = { path = "../rtt-target" }
1215
ufmt = "0.2.0"
16+
defmt = { version = "0.3.0", optional = true }
1317

1418
[[bin]]
1519
name = "custom"
@@ -19,3 +23,7 @@ name = "print"
1923

2024
[[bin]]
2125
name = "ufmt"
26+
27+
[[bin]]
28+
name = "defmt"
29+
required-features = ["defmt"]

examples-cortex-m/src/bin/defmt.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#![no_std]
2+
#![no_main]
3+
4+
use cortex_m_rt::entry;
5+
use panic_halt as _;
6+
use rtt_target::rtt_init;
7+
8+
#[entry]
9+
fn main() -> ! {
10+
let channels = rtt_init! {
11+
up: {
12+
0: {
13+
size: 1024,
14+
name: "defmt"
15+
}
16+
}
17+
};
18+
19+
rtt_target::set_defmt_channel(channels.up.0);
20+
21+
let mut i = 0;
22+
loop {
23+
defmt::println!("Loop {}...", i);
24+
25+
i += 1;
26+
}
27+
}

panic-rtt-target/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
[package]
22
name = "panic-rtt-target"
33
description = "Logs panic messages over RTT using rtt-target"
4-
version = "0.1.3"
4+
version = "0.2.0"
55
edition = "2021"
66
readme = "README.md"
77
keywords = ["no-std", "embedded", "debugging", "rtt"]
88
license = "MIT"
9-
license-file = "../LICENSE"
109
authors = [
1110
"Matti Virkkunen <[email protected]>",
1211
"Per Lindgren <[email protected]>",
1312
]
1413
repository = "https://github.com/probe-rs/rtt-target"
1514

1615
[dependencies]
17-
rtt-target = "0.5.0"
16+
rtt-target = {version = "0.6.0", path = "../rtt-target" }
1817
critical-section = "1.1.1"
18+
portable-atomic = { version = "1.6.0", default-features = false }

panic-rtt-target/README.md

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@ Logs panic messages over RTT. A companion crate for rtt-target.
88

99
RTT must have been initialized by using one of the `rtt_init` macros. Otherwise you will get a linker error at compile time.
1010

11-
Panics are always logged on channel 0. Upon panicking the channel mode is also automatically set to `BlockIfFull`, so that the full message will always be logged. If the code somehow manages to panic at runtime before RTT is initialized (quite unlikely), or if channel 0 doesn't exist, nothing is logged.
11+
Panics are always logged to the print channel. Upon panicking the channel mode is also automatically set to `BlockIfFull`, so that the full message will always be logged. If the code somehow manages to panic at runtime before RTT is initialized (quite unlikely), or if the print channel doesn't exist, nothing is logged.
1212

13-
The panic handler runs in a non-returning [critical_section](https://docs.rs/critical-section) which implementation should be provided by the user.
13+
The panic handler runs in a non-returning [critical_section](https://docs.rs/critical-section) which implementation should be provided by the user.
1414

1515
# Usage
1616

1717
Cargo.toml:
1818

1919
```toml
2020
[dependencies]
21-
cortex-m = { version = "0.7.6", features = ["critical-section-single-core"]}
22-
panic-rtt-target = { version = "x.y.z" }
21+
rtt-target = "x.y.z"
22+
panic-rtt-target = "x.y.z"
2323
```
2424

2525
main.rs:
@@ -31,34 +31,9 @@ use panic_rtt_target as _;
3131
use rtt_target::rtt_init_default;
3232

3333
fn main() -> ! {
34-
// you can use any init macro as long as it creates channel 0
34+
// you can use `rtt_init_print` or you can call `set_print_channel` after initialization.
3535
rtt_init_default!();
3636

3737
panic!("Something has gone terribly wrong");
3838
}
3939
```
40-
41-
## Implementation details
42-
43-
The provided interrupt handler checks if RTT channel 0 is configured, writes the `info` and enters an infinite loop. If RTT channel 0 is not configured, the panic handler enters the *failed to get channel* infinite loop. The final state can be observed by breaking/halting the target.
44-
```rust
45-
fn panic(info: &PanicInfo) -> ! {
46-
critical_section::with(|_| {
47-
if let Some(mut channel) = unsafe { UpChannel::conjure(0) } {
48-
channel.set_mode(ChannelMode::BlockIfFull);
49-
50-
writeln!(channel, "{}", info).ok();
51-
} else {
52-
// failed to get channel, but not much else we can do but spin
53-
loop {
54-
compiler_fence(SeqCst);
55-
}
56-
}
57-
58-
// we should never leave critical section
59-
loop {
60-
compiler_fence(SeqCst);
61-
}
62-
})
63-
}
64-
```

panic-rtt-target/src/lib.rs

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,22 @@
33
//! RTT must have been initialized by using one of the `rtt_init` macros. Otherwise you will get a
44
//! linker error at compile time.
55
//!
6-
//! Panics are always logged on channel 0. Upon panicking the channel mode is also automatically set
7-
//! to `BlockIfFull`, so that the full message will always be logged. If the code somehow manages to
8-
//! panic at runtime before RTT is initialized (quite unlikely), or if channel 0 doesn't exist,
9-
//! nothing is logged.
6+
//! Panics are always logged to the print channel. Upon panicking the channel mode is also
7+
//! automatically set to `BlockIfFull`, so that the full message will always be logged.
8+
//! If the code somehow manages to panic at runtime before RTT is initialized (quite unlikely),
9+
//! or if the print channel doesn't exist, nothing is logged.
1010
//!
11-
//! A platform feature such as `cortex-m` is required to use this crate.
11+
//! The panic handler runs in a non-returning [critical_section](https://docs.rs/critical-section)
12+
//! which implementation should be provided by the user.
1213
//!
1314
//! # Usage
1415
//!
1516
//! Cargo.toml:
1617
//!
1718
//! ```toml
1819
//! [dependencies]
19-
//! panic-rtt-target = { version = "x.y.z", features = ["cortex-m"] }
20+
//! rtt-target = "x.y.z"
21+
//! panic-rtt-target = "x.y.z"
2022
//! ```
2123
//!
2224
//! main.rs:
@@ -28,7 +30,7 @@
2830
//! use rtt_target::rtt_init_default;
2931
//!
3032
//! fn main() -> ! {
31-
//! // you can use any init macro as long as it creates channel 0
33+
//! // you can use `rtt_init_print` or you can call `set_print_channel` after initialization.
3234
//! rtt_init_default!();
3335
//!
3436
//! panic!("Something has gone terribly wrong");
@@ -37,37 +39,25 @@
3739
3840
#![no_std]
3941

40-
// allow(unused) is used so that warnings when no platform feature is defined don't drown out the
41-
// compile_error
42+
use core::{fmt::Write, panic::PanicInfo};
43+
use portable_atomic::{compiler_fence, Ordering};
4244

43-
#[allow(unused)]
44-
use core::{
45-
fmt::Write,
46-
panic::PanicInfo,
47-
sync::atomic::{compiler_fence, Ordering::SeqCst},
48-
};
49-
50-
#[allow(unused)]
51-
use rtt_target::{ChannelMode, UpChannel};
45+
use rtt_target::{with_terminal_channel, ChannelMode};
5246

5347
#[inline(never)]
5448
#[panic_handler]
5549
fn panic(info: &PanicInfo) -> ! {
5650
critical_section::with(|_| {
57-
if let Some(mut channel) = unsafe { UpChannel::conjure(0) } {
58-
channel.set_mode(ChannelMode::BlockIfFull);
51+
with_terminal_channel(|term| {
52+
term.set_mode(ChannelMode::BlockIfFull);
53+
let mut channel = term.write(0);
5954

6055
writeln!(channel, "{}", info).ok();
61-
} else {
62-
// failed to get channel, but not much else we can do but spin
63-
loop {
64-
compiler_fence(SeqCst);
65-
}
66-
}
56+
});
6757

6858
// we should never leave critical section
6959
loop {
70-
compiler_fence(SeqCst);
60+
compiler_fence(Ordering::SeqCst);
7161
}
7262
})
7363
}

panic-test/.cargo/config.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[build]
2+
target = "thumbv7m-none-eabi"
3+
4+
[unstable]
5+
build-std = ["core"]

rtt-target/Cargo.toml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
[package]
22
name = "rtt-target"
33
description = "Target side implementation of the RTT (Real-Time Transfer) I/O protocol"
4-
version = "0.5.0"
4+
version = "0.6.0"
55
edition = "2018"
66
readme = "../README.md"
77
keywords = ["no-std", "embedded", "debugging", "rtt"]
88
license = "MIT"
9-
license-file = "../LICENSE"
109
authors = ["Matti Virkkunen <[email protected]>"]
1110
repository = "https://github.com/probe-rs/rtt-target"
1211

12+
[features]
13+
default = []
14+
1315
[dependencies]
1416
ufmt-write = "0.1.0"
1517
critical-section = "1.0.0"
18+
portable-atomic = { version = "1.6.0", default-features = false }
19+
20+
defmt = { version = "0.3.0", optional = true }

0 commit comments

Comments
 (0)