ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_crashlog.c
Go to the documentation of this file.
1
22
23#include "ra8_crashlog.h"
24
25#include <stddef.h>
26#include <stdint.h>
27
28#include "ra8_attributes.h"
30#include "ra8_exception.h"
31
42typedef enum : uint32_t {
43 k_ra8_crashlog_crc_poly = 0xEDB88320UL,
44 k_ra8_crashlog_crc_seed = 0xFFFFFFFFUL,
46
52typedef enum : uint8_t {
55
67typedef enum : uint32_t {
70
90#ifdef RA8_OFF_TARGET
92#else
93[[gnu::section(".noinit")]] static volatile ra8_crashlog_record_t s_ra8_crashlog_record;
94#endif
95
96static_assert(sizeof(ra8_crashlog_record_t) <= (size_t)k_ra8_crashlog_reserve_bytes,
97 "ra8_crashlog_record_t must fit the linker NOINIT region (LENGTH(NOINIT))");
98
124RA8_INTERNAL static uint32_t internal_crashlog_crc32(const volatile uint8_t* data, uint32_t len)
125{
126 if (data == nullptr) {
127 return 0U;
128 }
129 uint32_t crc = (uint32_t)k_ra8_crashlog_crc_seed;
130 for (uint32_t i = 0U; i < len; i++) {
131 crc ^= (uint32_t)data[i];
132 for (uint8_t bit = 0U; bit < (uint8_t)k_ra8_crashlog_crc_bits; bit++) {
133 const uint32_t mask = 0U - (crc & 1U);
134 crc = (crc >> 1U) ^ ((uint32_t)k_ra8_crashlog_crc_poly & mask);
135 }
136 }
137 return crc ^ (uint32_t)k_ra8_crashlog_crc_seed;
138}
139
160{
161 const volatile uint8_t* base = (const volatile uint8_t*)&s_ra8_crashlog_record;
162 const uint32_t off = (uint32_t)offsetof(ra8_crashlog_record_t, boot_loops);
163 return internal_crashlog_crc32(&base[off], (uint32_t)sizeof(s_ra8_crashlog_record) - off);
164}
165
194
201
205{
206 if (decoded == nullptr) {
207 return;
208 }
209 /* Carry the prior crash count forward only if the existing record still
210 * validates; a cold-boot / corrupted record restarts the count at 1. */
211 uint32_t next = 1U;
213 const uint32_t prior = s_ra8_crashlog_record.boot_loops;
214 next = (prior < (uint32_t)k_ra8_crashlog_loops_max) ? (prior + 1U)
215 : (uint32_t)k_ra8_crashlog_loops_max;
216 }
217 s_ra8_crashlog_record.magic = 0U; /* invalidate for the write window */
218 s_ra8_crashlog_record.boot_loops = next;
219 s_ra8_crashlog_record.fault = *decoded;
221 s_ra8_crashlog_record.magic = (uint32_t)k_ra8_crashlog_magic_valid; /* validate LAST */
222}
223
226{
227 if (out == nullptr) {
228 return false;
229 }
231 return false;
232 }
234 return true;
235}
236
240{
241 s_ra8_crashlog_record.magic = 0U;
242 s_ra8_crashlog_record.crc = 0U;
243 s_ra8_crashlog_record.boot_loops = 0U;
244}
245
249{
251 if (!ra8_crashlog_peek(&rec)) {
252 return false;
253 }
254 return rec.boot_loops > (uint32_t)k_ra8_crashlog_loop_threshold;
255}
256
257#ifdef RA8_OFF_TARGET
260volatile ra8_crashlog_record_t* ra8_crashlog_test_record(void)
261{
262 return &s_ra8_crashlog_record;
263}
264
267void ra8_crashlog_test_wipe(void)
268{
269 volatile uint8_t* p = (volatile uint8_t*)&s_ra8_crashlog_record;
270 for (uint32_t i = 0U; i < (uint32_t)sizeof(s_ra8_crashlog_record); i++) {
271 p[i] = 0U;
272 }
273}
274#endif /* RA8_OFF_TARGET */
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
void ra8_crashlog_claim(void)
Implementation of ra8_crashlog_claim() – clear magic + reset the guard.
static bool internal_crashlog_is_valid(void)
Whether the stored record is a trustworthy post-mortem.
static volatile ra8_crashlog_record_t s_ra8_crashlog_record
The one cross-reset crash-log record instance.
bool ra8_crashlog_peek(ra8_crashlog_record_t *out)
Implementation of ra8_crashlog_peek() – validate then copy out.
bool ra8_crashlog_safe_mode_requested(void)
Implementation of ra8_crashlog_safe_mode_requested() – count vs threshold.
static uint32_t internal_crashlog_payload_crc(void)
CRC-32 over the integrity-protected payload of the record.
void ra8_crashlog_record_fault(const volatile ra8_exception_last_t *decoded)
Implementation of ra8_crashlog_record_fault() – write payload, magic last.
ra8_crashlog_crc_iter_t
Per-byte iteration count for the bitwise CRC-32.
@ k_ra8_crashlog_crc_bits
Bits consumed per input byte.
void ra8_crashlog_install(void)
Implementation of ra8_crashlog_install() – register the persist hook.
static uint32_t internal_crashlog_crc32(const volatile uint8_t *data, uint32_t len)
Compute a reflected CRC-32 over a byte span.
ra8_crashlog_crc_const_t
Constants for the self-contained bitwise CRC-32.
@ k_ra8_crashlog_crc_poly
Reflected CRC-32 polynomial.
@ k_ra8_crashlog_crc_seed
Initial value and final XOR mask.
ra8_crashlog_loops_const_t
Saturation ceiling for the reset-loop counter.
@ k_ra8_crashlog_loops_max
boot_loops never grows past this.
Cross-reset crash-log: persist the last fault + a reset-loop guard.
@ k_ra8_crashlog_loop_threshold
Safe mode when boot_loops exceeds this.
@ k_ra8_crashlog_reserve_bytes
Bytes reserved for .noinit at SRAM top.
void ra8_crashlog_record_fault(const volatile ra8_exception_last_t *decoded)
Persist a decoded fault snapshot into the cross-reset record.
@ k_ra8_crashlog_magic_valid
"SAFE-BOOT": record is valid.
Cross-TU surface for ra8_crashlog (host-test white-box access only).
Cortex-M85 CPU exception diagnostic helpers.
void ra8_exception_set_persist_hook(ra8_exception_persist_fn hook)
Register (or clear) the post-decode fault-persistence hook.
The .noinit cross-reset post-mortem record.
uint32_t boot_loops
Monotonic recorded-fault counter; cleared by a claim.
Fixed-SRAM post-mortem snapshot of the most recent fault or NMI.