Skip to content
This repository was archived by the owner on Jan 24, 2022. It is now read-only.
This repository was archived by the owner on Jan 24, 2022. It is now read-only.

Backtrace for HardFault #158

@perlindgren

Description

@perlindgren

I was experimenting with the latest release of cortex-m-rt (0.6.6).

Possibly related to #139.

The code (below) should hard fault, and it does and the handler is invoked.
a gdb bactrace works at the first breakpoint. (I used the "asm-inline" feature, to have the bkpts inlined).

(gdb) p/x *ef
$9 = cortex_m_rt::ExceptionFrame {r0: 0x2fffffff, r1: 0xf00000, r2: 0x20000000, r3: 0x20000008, r12: 0xdfffffff, lr: 0x80006c3, pc: 0x80002f8, xpsr: 0x61000000}

seems ok. (pc being the read_volatile on the faulty address)

However, when trying to make a backtrace from within testf or after testf (back in the HardFault handler), backtracing ends up in an infinite loop.

(gdb) bt
#0  HardFault (ef=<optimized out>) at examples/crash-semihosting.rs:121
#1  0x08001adc in HardFault (ef=0x2000ffe0) at examples/crash-semihosting.rs:120
#2  0x08001adc in HardFault (ef=0x2000ffe0) at examples/crash-semihosting.rs:120

I wonder if this is the expected behavior. If so, then the docs should perhaps indicate that if you want to make a backtrace, put an asm::bkptr at entry of the HardFault handler, and do the bactrace before you call any function, e.g.,

let _ = hprintln!("{:#?}", ef);

I did not use panic!(..) to print the ef, as I wanted the example as simple as possible (less indirections). Printing ef can of course be done from within gdb as well, and is often preferrable as bringing formatting and semi-hosting printing is somewhat bloating the code.

On another note, I tried printing `ef' over ITM, but that is not advisable, as (at least on the stlink/nucleo 64), the internal buffer of the debug interface will overflow causing the ITM channel to be frozen). After that ITM was inaccessible, requiring an openocd kill/restart, but that behaviour might be installation dependent.

I took a brief look at the generated asm (release mode), and it looks ok, it reserves som place on the stack for the HardFault handler, etc.

...
#[entry]
#[inline(never)]
fn main() -> ! {
    unsafe {
        // read an address outside of the RAM region; this causes a HardFault exception
        ptr::read_volatile(0x2FFF_FFFF as *const u32);
    }

    loop {}
}

#[inline(never)]
fn testf() {
    asm::bkpt();
}

#[exception]
fn HardFault(ef: &cortex_m_rt::ExceptionFrame) -> ! {
    // prints the exception frame using semihosting
    asm::bkpt();
    testf();
    asm::bkpt();
    let _ = hprintln!("{:#?}", ef);
    asm::bkpt();
    let _ = hprintln!("{:#?}", ef);
    asm::bkpt();
    loop {
        asm::bkpt();
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions