|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Cross-reset crash-log: persist the last fault + a reset-loop guard. More...
Go to the source code of this file.
Data Structures | |
| struct | ra8_crashlog_record_t |
| The .noinit cross-reset post-mortem record. More... | |
Enumerations | |
| enum | ra8_crashlog_magic_t : uint32_t { k_ra8_crashlog_magic_valid = 0x5AFEB007UL } |
| Sentinel marking a fully-written ra8_crashlog_record_t. More... | |
| enum | ra8_crashlog_limits_t : uint32_t { k_ra8_crashlog_loop_threshold = 3U , k_ra8_crashlog_reserve_bytes = 256U } |
| Reset-loop threshold and the linker reservation size. More... | |
Functions | |
| void | ra8_crashlog_install (void) |
| Arm the fault-persist hook so decoded faults are logged to .noinit. | |
| void | ra8_crashlog_record_fault (const volatile ra8_exception_last_t *decoded) |
| Persist a decoded fault snapshot into the cross-reset record. | |
| bool | ra8_crashlog_peek (ra8_crashlog_record_t *out) |
| Validate and copy out the last cross-reset record (non-destructive). | |
| void | ra8_crashlog_claim (void) |
| Consume the record and reset the reset-loop guard (clean claim). | |
| bool | ra8_crashlog_safe_mode_requested (void) |
| Whether accumulated crashes crossed the reset-loop threshold. | |
Cross-reset crash-log: persist the last fault + a reset-loop guard.
ra8_exception.c decodes every CPU fault / NMI into the fixed-SRAM ra8_exception_last_t snapshot g_ra8_exception_last and then halts. That snapshot lives in ordinary .bss-adjacent SRAM, so the very next reset's Reset_Handler zero-fills it and the post-mortem is gone before a field technician can read it. This module adds the missing survival + guard layer ON TOP of that decode path:
| Reset class | SRAM kept | Record survives |
|---|---|---|
| Watchdog / IWDT underflow (warm) | yes | yes |
| Software reset (SYSRESETREQ) | yes | yes |
| Pin / debugger reset (no power cut) | yes | yes |
| Power-on reset / LVD brown-out | no | no (fail-safe) |
VBATT-backed / MRAM persistence across power loss is out of scope here (VBATT ra8_bkup is silicon-blocked – see issue #131) and is the named follow-up for surviving a cold power cycle.
Definition in file ra8_crashlog.h.
| enum ra8_crashlog_limits_t : uint32_t |
Reset-loop threshold and the linker reservation size.
k_ra8_crashlog_loop_threshold is the number of recorded faults that may accumulate before ra8_crashlog_safe_mode_requested() latches; the app resets the count by reaching a known-good state and calling ra8_crashlog_claim(). k_ra8_crashlog_reserve_bytes MUST equal the LENGTH(NOINIT) region size in libs/ra8_board_ek_ra8d2/ld/linker_script.ld; a compile-time assertion in ra8_crashlog.c proves the record fits it.
| Enumerator | |
|---|---|
| k_ra8_crashlog_loop_threshold | Safe mode when boot_loops exceeds this. |
| k_ra8_crashlog_reserve_bytes | Bytes reserved for .noinit at SRAM top. |
Definition at line 110 of file ra8_crashlog.h.
| enum ra8_crashlog_magic_t : uint32_t |
Sentinel marking a fully-written ra8_crashlog_record_t.
Written LAST when a record is complete and cleared FIRST when it is consumed, so neither a secondary fault mid-write nor random cold-boot SRAM can be mistaken for a valid post-mortem. The value is distinct from k_ra8_exc_magic_valid so the two fixed-SRAM records are never confused by a debugger.
| Enumerator | |
|---|---|
| k_ra8_crashlog_magic_valid | "SAFE-BOOT": record is valid. |
Definition at line 91 of file ra8_crashlog.h.
| void ra8_crashlog_claim | ( | void | ) |
Consume the record and reset the reset-loop guard (clean claim).
Marks the current record handled: clears magic (so a following ra8_crashlog_peek() reports empty) and zeroes boot_loops (so the reset-loop guard re-arms from a clean slate). Call it only after the application has reached a known-good checkpoint – claiming before the risky work would defeat the loop guard. Idempotent.
Consume the record and reset the reset-loop guard (clean claim).
Definition at line 239 of file ra8_crashlog.c.
References s_ra8_crashlog_record.
Referenced by main().
| void ra8_crashlog_install | ( | void | ) |
Arm the fault-persist hook so decoded faults are logged to .noinit.
Registers ra8_crashlog_record_fault() as the exception module's post-decode persist sink (see ra8_exception_set_persist_hook()). After this call, every fault/NMI that reaches ra8_exception_report() copies its decoded snapshot into the cross-reset record and bumps the reset-loop counter BEFORE the CPU halts. Must be called early each boot: the hook pointer lives in .bss and is zeroed by every reset, so it has to be re-armed before any code that might fault.
Arm the fault-persist hook so decoded faults are logged to .noinit.
Definition at line 197 of file ra8_crashlog.c.
References ra8_crashlog_record_fault(), and ra8_exception_set_persist_hook().
Referenced by main().
| bool ra8_crashlog_peek | ( | ra8_crashlog_record_t * | out | ) |
Validate and copy out the last cross-reset record (non-destructive).
Recomputes the payload CRC and compares it plus the magic sentinel. On a match, copies the whole record into out and returns true; the stored record is left intact (call ra8_crashlog_claim() to consume it). On any mismatch – including the all-random SRAM of a cold power-on – returns false and leaves out unmodified.
| [out] | out | Destination for the validated record. Must not be nullptr. Untouched when the function returns false. |
| true | A valid record existed and was copied to out. |
| false | No valid record (empty, corrupted, or out == nullptr). |
out is either nullptr or points to writable storage. Validate and copy out the last cross-reset record (non-destructive).
Definition at line 225 of file ra8_crashlog.c.
References internal_crashlog_is_valid(), and s_ra8_crashlog_record.
Referenced by main(), and ra8_crashlog_safe_mode_requested().
| void ra8_crashlog_record_fault | ( | const volatile ra8_exception_last_t * | decoded | ) |
Persist a decoded fault snapshot into the cross-reset record.
The write path installed by ra8_crashlog_install(): reads the prior boot_loops (only if the existing record still validates), invalidates the record (magic = 0), copies decoded into the embedded snapshot, increments the loop counter (saturating so it can never wrap back below the threshold), stamps the CRC, and finally re-arms magic LAST so a secondary fault mid-write leaves the record invalid rather than half-written. Also directly callable by an application to record a software-detected fatal condition (assertion, corruption, watchdog arming) in the same field-readable format.
| [in] | decoded | Decoded fault snapshot to persist. Must not be nullptr; typically &g_ra8_exception_last. |
decoded points at a populated ra8_exception_last_t. Persist a decoded fault snapshot into the cross-reset record.
Definition at line 204 of file ra8_crashlog.c.
References internal_crashlog_is_valid(), internal_crashlog_payload_crc(), k_ra8_crashlog_loops_max, k_ra8_crashlog_magic_valid, and s_ra8_crashlog_record.
Referenced by main(), and ra8_crashlog_install().
| bool ra8_crashlog_safe_mode_requested | ( | void | ) |
Whether accumulated crashes crossed the reset-loop threshold.
Returns true only when a valid record exists AND its boot_loops exceeds k_ra8_crashlog_loop_threshold – i.e. the device has recorded more than the allowed number of faults without a clean ra8_crashlog_claim() in between. The application reads this early in boot to divert into a minimal safe mode instead of re-running the code that keeps faulting.
| true | Valid record and boot_loops > k_ra8_crashlog_loop_threshold. |
| false | No valid record, or the count is within the threshold. |
Whether accumulated crashes crossed the reset-loop threshold.
Definition at line 248 of file ra8_crashlog.c.
References ra8_crashlog_record_t::boot_loops, k_ra8_crashlog_loop_threshold, and ra8_crashlog_peek().
Referenced by main().