ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_crashlog.c File Reference

Cross-reset crash-log implementation (.noinit record + loop guard). More...

#include "ra8_crashlog.h"
#include <stddef.h>
#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_crashlog_internal.h"
#include "ra8_exception.h"
Include dependency graph for ra8_crashlog.c:

Go to the source code of this file.

Enumerations

enum  ra8_crashlog_crc_const_t : uint32_t {
  k_ra8_crashlog_crc_poly = 0xEDB88320UL ,
  k_ra8_crashlog_crc_seed = 0xFFFFFFFFUL
}
 Constants for the self-contained bitwise CRC-32. More...
enum  ra8_crashlog_crc_iter_t : uint8_t { k_ra8_crashlog_crc_bits = 8U }
 Per-byte iteration count for the bitwise CRC-32. More...
enum  ra8_crashlog_loops_const_t : uint32_t { k_ra8_crashlog_loops_max = 255U }
 Saturation ceiling for the reset-loop counter. More...

Functions

static uint32_t internal_crashlog_crc32 (const volatile uint8_t *data, uint32_t len)
 Compute a reflected CRC-32 over a byte span.
static uint32_t internal_crashlog_payload_crc (void)
 CRC-32 over the integrity-protected payload of the record.
static bool internal_crashlog_is_valid (void)
 Whether the stored record is a trustworthy post-mortem.
void ra8_crashlog_install (void)
 Implementation of ra8_crashlog_install() – register the persist hook.
void ra8_crashlog_record_fault (const volatile ra8_exception_last_t *decoded)
 Implementation of ra8_crashlog_record_fault() – write payload, magic last.
bool ra8_crashlog_peek (ra8_crashlog_record_t *out)
 Implementation of ra8_crashlog_peek() – validate then copy out.
void ra8_crashlog_claim (void)
 Implementation of ra8_crashlog_claim() – clear magic + reset the guard.
bool ra8_crashlog_safe_mode_requested (void)
 Implementation of ra8_crashlog_safe_mode_requested() – count vs threshold.

Variables

static volatile ra8_crashlog_record_t s_ra8_crashlog_record
 The one cross-reset crash-log record instance.

Detailed Description

Cross-reset crash-log implementation (.noinit record + loop guard).

Owns the one .noinit ra8_crashlog_record_t instance, the self-contained software CRC-32 that protects it, and the write/validate/claim state machine described in ra8_crashlog.h. The record is placed in the linker's .noinit section (pinned at the top of SRAM, above the stack) on the firmware build so Reset_Handler's .bss zero-fill never touches it; on the host unit-test build it is an ordinary zero-init static (there is no cross-reset survival to model in a single test process).

A hardware CRC peripheral is deliberately NOT used: the write path runs from a fault context where no peripheral may be assumed powered or initialised, so the checksum is a tiny bitwise CRC-32 that touches nothing but the record's own bytes.

Definition in file ra8_crashlog.c.

Enumeration Type Documentation

◆ ra8_crashlog_crc_const_t

enum ra8_crashlog_crc_const_t : uint32_t

Constants for the self-contained bitwise CRC-32.

Standard reflected CRC-32 (IEEE 802.3 / zlib): the polynomial is applied LSB-first and the seed doubles as the final XOR mask.

Since
0.1.0
Enumerator
k_ra8_crashlog_crc_poly 

Reflected CRC-32 polynomial.

k_ra8_crashlog_crc_seed 

Initial value and final XOR mask.

Definition at line 42 of file ra8_crashlog.c.

◆ ra8_crashlog_crc_iter_t

enum ra8_crashlog_crc_iter_t : uint8_t

Per-byte iteration count for the bitwise CRC-32.

Since
0.1.0
Enumerator
k_ra8_crashlog_crc_bits 

Bits consumed per input byte.

Definition at line 52 of file ra8_crashlog.c.

◆ ra8_crashlog_loops_const_t

enum ra8_crashlog_loops_const_t : uint32_t

Saturation ceiling for the reset-loop counter.

boot_loops saturates here instead of wrapping, so a very long crash loop can never roll the counter back below k_ra8_crashlog_loop_threshold and silently clear the safe-mode request.

Since
0.1.0
Enumerator
k_ra8_crashlog_loops_max 

boot_loops never grows past this.

Definition at line 67 of file ra8_crashlog.c.

Function Documentation

◆ internal_crashlog_crc32()

uint32_t internal_crashlog_crc32 ( const volatile uint8_t * data,
uint32_t len )
static

Compute a reflected CRC-32 over a byte span.

Bitwise (table-free) reflected CRC-32 so the checksum adds no .rodata table and is safe to run from a fault context. The mask trick 0 - (crc & 1) yields 0x00000000 or 0xFFFFFFFF branchlessly.

Parameters
[in]dataStart of the span. Reads are volatile so the record's own storage can be checksummed in place. Must not be nullptr.
[in]lenNumber of bytes to fold in (0 yields the empty CRC 0).
Returns
The CRC-32 of the span.
Return values
0When data is nullptr or len is 0.
otherThe reflected CRC-32 of the len bytes at data.
Precondition
data points at len readable bytes, or is nullptr.
len does not exceed the size of the span at data.
Postcondition
No memory outside the span is read; nothing is written.
The result depends only on the len bytes and their order.
Note
Not stateful; trivially thread-safe.
Since
0.1.0

Definition at line 124 of file ra8_crashlog.c.

References k_ra8_crashlog_crc_bits, k_ra8_crashlog_crc_poly, k_ra8_crashlog_crc_seed, and RA8_INTERNAL.

Referenced by internal_crashlog_payload_crc().

◆ internal_crashlog_is_valid()

bool internal_crashlog_is_valid ( void )
static

Whether the stored record is a trustworthy post-mortem.

The record is valid only when both integrity signals agree: the magic sentinel equals k_ra8_crashlog_magic_valid AND the recomputed payload CRC equals the stored crc. Either failing – as with the random SRAM after a cold power-on – rejects the record.

Returns
Whether the record validates.
Return values
truemagic matches AND the payload CRC matches.
falseEither signal disagrees (empty, stale, or corrupted).
Precondition
The record storage is readable.
A prior writer used the magic-written-last ordering.
Postcondition
No record byte is modified.
true is returned only for a fully-written, intact record.
Note
Not thread-safe. This two-condition record-validity check (the magic sentinel plus the payload CRC) is the module's MC/DC-covered compound; the vectors live in tests/misc/src/test_ra8_crashlog.c.
Since
0.1.0

Definition at line 189 of file ra8_crashlog.c.

References internal_crashlog_payload_crc(), k_ra8_crashlog_magic_valid, RA8_INTERNAL, and s_ra8_crashlog_record.

Referenced by ra8_crashlog_peek(), and ra8_crashlog_record_fault().

◆ internal_crashlog_payload_crc()

uint32_t internal_crashlog_payload_crc ( void )
static

CRC-32 over the integrity-protected payload of the record.

Covers every byte from boot_loops to the end of the record – i.e. the record minus its leading magic sentinel and the crc field itself – so the sentinel and the checksum are two independent integrity signals.

Returns
The CRC-32 of the record payload.
Return values
0..UINT32_MAXWhatever the current payload bytes hash to.
Precondition
The record storage is readable.
boot_loops is the first CRC-covered field of the record.
Postcondition
No record byte is modified.
The result matches crc exactly when the payload is intact.
Note
Not thread-safe w.r.t. a concurrent record write.
Since
0.1.0

Definition at line 159 of file ra8_crashlog.c.

References internal_crashlog_crc32(), RA8_INTERNAL, and s_ra8_crashlog_record.

Referenced by internal_crashlog_is_valid(), and ra8_crashlog_record_fault().

◆ ra8_crashlog_claim()

void ra8_crashlog_claim ( void )

Implementation of ra8_crashlog_claim() – clear magic + reset the guard.

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().

◆ ra8_crashlog_install()

void ra8_crashlog_install ( void )

Implementation of ra8_crashlog_install() – register the persist hook.

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().

◆ ra8_crashlog_peek()

bool ra8_crashlog_peek ( ra8_crashlog_record_t * out)

Implementation of ra8_crashlog_peek() – validate then copy out.

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().

◆ ra8_crashlog_record_fault()

void ra8_crashlog_record_fault ( const volatile ra8_exception_last_t * decoded)

Implementation of ra8_crashlog_record_fault() – write payload, magic last.

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().

◆ ra8_crashlog_safe_mode_requested()

bool ra8_crashlog_safe_mode_requested ( void )

Implementation of ra8_crashlog_safe_mode_requested() – count vs 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().

Variable Documentation

◆ s_ra8_crashlog_record

volatile ra8_crashlog_record_t s_ra8_crashlog_record
static

The one cross-reset crash-log record instance.

On the firmware build it lives in .noinit (NOLOAD, pinned at the top of SRAM by libs/ra8_board_ek_ra8d2/ld/linker_script.ld) so a warm/watchdog reset does not clear it. On the host test build (RA8_OFF_TARGET) the section attribute is dropped – Mach-O rejects a bare section name and a single test process has no reset to survive – leaving a plain zero-init static.

Note
volatile so the compiler cannot elide the write sequence or reorder the magic-written-last ordering the integrity model depends on.
Warning
Written only through this module's API; the linker address is exposed as g_ra8_ls_noinit_start for debugger inspection.
Since
0.1.0

Definition at line 93 of file ra8_crashlog.c.

Referenced by internal_crashlog_is_valid(), internal_crashlog_payload_crc(), ra8_crashlog_claim(), ra8_crashlog_peek(), and ra8_crashlog_record_fault().