Sound Byte Libs 29c5ff3
C++ firmware library for audio applications on 32-bit ARM Cortex-M processors
Loading...
Searching...
No Matches
fault.hpp
Go to the documentation of this file.
1#pragma once
2/**
3 * @file fault.hpp
4 * @brief HardFault handler with register dump
5 *
6 * Bridge between the MCU's HardFault vector (in sbl-hardware startup.cpp)
7 * and the library's diagnostic output. Including this header provides:
8 *
9 * 1. sbl::fault::on_hard_fault() — formats the Cortex-M exception frame
10 * 2. sbl_on_hard_fault() — strong C symbol that overrides the weak default
11 * in startup.cpp, connecting the vector to the formatter
12 *
13 * The startup.cpp in sbl-hardware declares a weak sbl_on_hard_fault() that
14 * just hits a breakpoint. When this header is included in the application,
15 * the strong symbol here wins, giving formatted register output on any fault.
16 *
17 * Usage:
18 * // Include once in your main.cpp (or any single TU)
19 * #include <sbl/fault.hpp>
20 *
21 * // That's it. HardFaults now dump registers to your log output.
22 *
23 * The output sink is shared with assert.hpp (SBL_FAULT_OUTPUT).
24 * See assert.hpp for sink configuration.
25 */
26
27#include <sbl/assert.hpp> // For SBL_FAULT_OUTPUT and sbl::log::format
28
29namespace sbl::fault {
30
31/**
32 * @brief Format and output the Cortex-M exception stack frame.
33 *
34 * The Cortex-M exception entry pushes these registers onto the
35 * active stack (MSP or PSP):
36 * [0] R0 [1] R1 [2] R2 [3] R3
37 * [4] R12 [5] LR [6] PC [7] xPSR
38 *
39 * The faulting instruction address is frame[6] (stacked PC).
40 * frame[5] (stacked LR) shows where the faulting function would
41 * have returned to.
42 *
43 * @param frame Pointer to the exception stack frame
44 */
45[[noreturn]] inline void on_hard_fault(const uint32_t* frame) {
46 __asm volatile("cpsid i");
47
48 char buf[256];
49 int pos = 0;
50
51 pos += sbl::log::format(buf + pos, sizeof(buf) - pos,
52 "\r\n!!! HARD FAULT\r\n"
53 " PC = 0x%08lX (faulting instruction)\r\n"
54 " LR = 0x%08lX (return address)\r\n"
55 " PSR = 0x%08lX\r\n",
56 frame[6], frame[5], frame[7]);
57
58 pos += sbl::log::format(buf + pos, sizeof(buf) - pos,
59 " R0 = 0x%08lX R1 = 0x%08lX\r\n"
60 " R2 = 0x%08lX R3 = 0x%08lX\r\n"
61 " R12 = 0x%08lX\r\n",
62 frame[0], frame[1], frame[2], frame[3], frame[4]);
63
64 SBL_FAULT_OUTPUT::write(buf);
65
66 while (true) {
67 __asm volatile("bkpt #1");
68 }
69}
70
71} // namespace sbl::fault
72
73// ============================================================================
74// HardFault handler override
75// ============================================================================
76// This strong symbol overrides the weak default in startup.cpp,
77// connecting the MCU's HardFault vector to the formatted output above.
78//
79// __attribute__((used)) forces the compiler to emit the symbol even
80// though nothing in C++ calls it directly — the call comes from the
81// HardFault assembly stub in startup.cpp via the vector table.
82
83extern "C" [[noreturn]] __attribute__((used))
84inline void sbl_on_hard_fault(const uint32_t* frame) {
86}
Assert and panic for embedded firmware.
__attribute__((used)) inline void sbl_on_hard_fault(const uint32_t *frame)
Definition fault.hpp:83
void on_hard_fault(const uint32_t *frame)
Format and output the Cortex-M exception stack frame.
Definition fault.hpp:45
int format(char *buf, size_t size, const char *fmt,...)
Format a string into a buffer (snprintf-style)
Definition format.hpp:265