4 releases

0.1.3 Jan 4, 2024
0.1.2 Apr 27, 2021
0.1.1 Aug 21, 2020
0.1.0 Apr 19, 2020

#1525 in Embedded development

Download history 1071/week @ 2024-07-21 1542/week @ 2024-07-28 1470/week @ 2024-08-04 1441/week @ 2024-08-11 1495/week @ 2024-08-18 1227/week @ 2024-08-25 1687/week @ 2024-09-01 1372/week @ 2024-09-08 1335/week @ 2024-09-15 1385/week @ 2024-09-22 974/week @ 2024-09-29 632/week @ 2024-10-06 1089/week @ 2024-10-13 1090/week @ 2024-10-20 1086/week @ 2024-10-27 847/week @ 2024-11-03

4,156 downloads per month
Used in fewer than 29 crates

MIT license

45KB
623 lines

panic-rtt-target

crates.io documentation

Logs panic messages over RTT. A companion crate for rtt-target.

Documentation

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

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.

The panic handler runs in a non-returning critical_section which implementation should be provided by the user.

Usage

Cargo.toml:

[dependencies]
cortex-m = { version = "0.7.6", features = ["critical-section-single-core"]}
panic-rtt-target = { version = "x.y.z" }

main.rs:

#![no_std]

use panic_rtt_target as _;
use rtt_target::rtt_init_default;

fn main() -> ! {
    // you can use any init macro as long as it creates channel 0
    rtt_init_default!();

    panic!("Something has gone terribly wrong");
}

Implementation details

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.

fn panic(info: &PanicInfo) -> ! {
    critical_section::with(|_| {
        if let Some(mut channel) = unsafe { UpChannel::conjure(0) } {
            channel.set_mode(ChannelMode::BlockIfFull);

            writeln!(channel, "{}", info).ok();
        } else {
            // failed to get channel, but not much else we can do but spin
            loop {
                compiler_fence(SeqCst);
            }
        }

        // we should never leave critical section
        loop {
            compiler_fence(SeqCst);
        }
    })
}

Dependencies

~37KB