Open japaric opened 3 years ago
One disadvantage is this will only work when directyl attached to the device with SWD. It won't work when using a custom Logger impl that sends the defmt data over e.g. the network. It's also highly specific to embedded (#463)
For the "nested acquire" problem: with rzcobs encoding, it is possible to write a 0x00 byte to "force-terminate" the previous frame (corrupting it) and then write the panic message frame, so that it is always sent. This works in the "defmt over the network" and non-embedded cases.
Not sure how this fits in the Logger
trait though. Can it be done backwards-compatibly?
Summary
add an alternative panicking mechanism,
defmt::abort
, that does NOT use theLogger
infrastructure but still reports some information to the user when used withprobe-run
.Motivation
currently, there are two places where one can run into "silent" panics:
defmt_rtt::acquire
. this can be triggered with:struct S;
impl Format for S { fn format(&self, _: defmt::Formatter) { defmt::error!("S") } }
[cortex_m_rt::entry]
fn main() -> ! { defmt::error!("{}", S); loop { asm::nop() } }
both of these failure modes don't report any information to the end user and thus are hard to debug.
This document proposes using
defmt::abort
in those two cases to provide information to the end userDetailed design
User API
defmt::abort
is a "diverging" (fn() -> !
) macro likedefmt::panic
. It takes a single argument: a string literal. Example usage:When
defmt::abort
is reached,probe-run
will report the string literal argument, the location of thedefmt::abort
call, a stack backtrace and then will exit with non-zero exit code. This will work regardless of whatLogger
implementation (e.g.defmt-rtt
) the program uses.when
probe-run
is not used. the program will execute the UDF instructionhand-wavy implementation details
The expansion of
defmt::abort!("string literal")
will roughly look like this:When unwinding the code,
probe-run
will identify the above pattern and report"string literal"
as the abort reason.The tricky part is the implementation of
expose_to_debugger
. The simplest thing to do would be to use custom assembly that:istr
is one general purpose register, e.g.r0
probe-run
will understand as the DEFMT_ABORT instruction(+) there are different machine instruction encodings that are considered "undefined" instructions. Another option could be using the immediate value of the BKPT instruction, e.g.
BKPT 0x42
Alternatives
defmt::abort
is up for discussionprobe-run
is also up for discussion