ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
main.c
Go to the documentation of this file.
1
44
45#include <stddef.h>
46#include <stdint.h>
47
48#include "ra8_board_ek_ra8d2.h"
49#include "ra8_boot_entry.h"
50#include "ra8_cgc.h"
51#include "ra8_crashlog.h"
52#include "ra8_err.h"
53#include "ra8_exception.h"
54#include "ra8_isr.h"
55#include "ra8_log.h"
56#include "ra8_mstp.h"
57
59typedef enum : uint32_t {
60 k_fc_uart_baud = 115200U,
63
65typedef enum : uint8_t {
68} fc_hex_t;
69
71typedef enum : uint32_t {
73 k_fc_synth_pc = 0x02001234U,
74 k_fc_synth_lr = 0x02001200U,
75 k_fc_synth_cfsr = 0x02000000U,
77
78static const uint8_t k_msg_boot[] = "crashlog: boot\r\n";
79static const uint8_t k_msg_fail[] = "crashlog: FAIL init\r\n";
80static const uint8_t k_msg_none[] = "crashlog: no prior record (cold/first boot)\r\n";
81static const uint8_t k_msg_prior[] = "crashlog: prior record exc=";
82static const uint8_t k_msg_pc[] = " pc=";
83static const uint8_t k_msg_loops[] = " boot_loops=";
84static const uint8_t k_msg_safemode[] = "crashlog: SAFE-MODE requested -- reset loop, idling\r\n";
85static const uint8_t k_msg_recorded[] = "crashlog: recorded+readback exc=";
86static const uint8_t k_msg_crlf[] = "\r\n";
87
102static void fc_print(const uint8_t* msg, uint32_t len)
103{
104 (void)ra8_board_uart_console_write(msg, (size_t)len);
105}
106
120static void fc_print_uint(uint32_t value)
121{
122 enum : uint32_t {
123 k_fc_dec_base = 10U,
124 k_fc_dec_digits = 10U,
125 };
126 uint8_t buf[k_fc_dec_digits];
127 uint32_t n = 0U;
128 if (value == 0U) {
129 buf[n] = '0';
130 n++;
131 }
132 while ((value > 0U) && (n < (uint32_t)k_fc_dec_digits)) {
133 buf[n] = (uint8_t)('0' + (value % (uint32_t)k_fc_dec_base));
134 n++;
135 value /= (uint32_t)k_fc_dec_base;
136 }
137 for (uint32_t i = 0U; i < n; i++) {
138 fc_print(&buf[n - 1U - i], 1U);
139 }
140}
141
154static void fc_print_hex32(uint32_t value)
155{
156 static const uint8_t k_hex[] = "0123456789ABCDEF";
157 const uint8_t prefix[] = {'0', 'x'};
158 fc_print(prefix, (uint32_t)sizeof(prefix));
159 for (uint32_t i = 0U; i < (uint32_t)k_fc_hex_digits; i++) {
160 const uint32_t shift = (uint32_t)((k_fc_hex_digits - 1U - i) * (uint32_t)k_fc_hex_nib_bits);
161 const uint32_t nib = (value >> shift) & (uint32_t)k_fc_hex_nib_mask;
162 fc_print(&k_hex[nib], 1U);
163 }
164}
165
181static void fc_log_sink(void* ctx, uint8_t byte)
182{
183 (void)ctx;
184 (void)ra8_board_uart_console_write(&byte, 1U);
185}
186
199[[noreturn]] static void fc_panic_halt(const uint8_t* msg, uint32_t len)
200{
201 fc_print(msg, len);
202 __asm__ volatile("bkpt #0");
203 while (1) {
204 __asm__ volatile("wfi");
205 }
206}
207
219static void fc_setup_or_halt(void)
220{
221 if (ra8_cgc_init() != k_ra8_ok) {
222 fc_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
223 }
224 if (ra8_mstp_init() != k_ra8_ok) {
225 fc_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
226 }
228 fc_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
229 }
230}
231
244{
245 if (rec == nullptr) {
246 return;
247 }
248 fc_print(k_msg_prior, (uint32_t)sizeof(k_msg_prior) - 1U);
250 fc_print(k_msg_pc, (uint32_t)sizeof(k_msg_pc) - 1U);
252 fc_print(k_msg_loops, (uint32_t)sizeof(k_msg_loops) - 1U);
254 fc_print(k_msg_crlf, (uint32_t)sizeof(k_msg_crlf) - 1U);
255}
256
269{
270 if (out == nullptr) {
271 return;
272 }
273 *out = (ra8_exception_last_t){};
274 out->magic = (uint32_t)k_ra8_exc_magic_valid;
275 out->exc_number = (uint32_t)k_fc_synth_exc;
276 out->frame.pc = (uint32_t)k_fc_synth_pc;
277 out->frame.lr = (uint32_t)k_fc_synth_lr;
278 out->diag.cfsr = (uint32_t)k_fc_synth_cfsr;
279}
280
281void main(void)
282{
286 fc_print(k_msg_boot, (uint32_t)sizeof(k_msg_boot) - 1U);
287
288 /* Arm the persist hook so any subsequent real fault is captured, then
289 * read whatever a prior (warm-reset) boot left behind. */
291
292 ra8_crashlog_record_t rec = {};
293 if (ra8_crashlog_peek(&rec)) {
294 fc_print_record(&rec);
296 fc_print(k_msg_safemode, (uint32_t)sizeof(k_msg_safemode) - 1U);
297 ra8_crashlog_claim(); /* clean claim: reset the loop guard */
298 while (1) {
299 __asm__ volatile("wfi");
300 }
301 }
302 } else {
303 fc_print(k_msg_none, (uint32_t)sizeof(k_msg_none) - 1U);
304 }
305
306 /* In-process write+decode proof (the only leg ra8_emulator can show): push
307 * a synthesised decoded snapshot through the installed write path, then
308 * read it back. Left in place so a bench warm reset shows survival. */
309 ra8_exception_last_t synth = {};
310 fc_make_synth(&synth);
312
313 if (ra8_crashlog_peek(&rec)) {
314 fc_print(k_msg_recorded, (uint32_t)sizeof(k_msg_recorded) - 1U);
316 fc_print(k_msg_pc, (uint32_t)sizeof(k_msg_pc) - 1U);
318 fc_print(k_msg_loops, (uint32_t)sizeof(k_msg_loops) - 1U);
320 fc_print(k_msg_crlf, (uint32_t)sizeof(k_msg_crlf) - 1U);
321 } else {
322 fc_panic_halt(k_msg_fail, (uint32_t)sizeof(k_msg_fail) - 1U);
323 }
324
325 while (1) {
326 __asm__ volatile("wfi");
327 }
328}
void main(void)
Secure fallback main entry point.
Definition main.c:37
static const uint8_t k_msg_boot[]
Definition main.c:140
static const uint8_t k_msg_fail[]
Definition main.c:63
static void fc_print_record(const ra8_crashlog_record_t *rec)
Print a decoded record's exception class, PC, and loop count.
Definition main.c:243
static const uint8_t k_msg_safemode[]
Definition main.c:84
static void fc_print(const uint8_t *msg, uint32_t len)
Emit a byte run on the SCI8 console.
Definition main.c:102
static const uint8_t k_msg_crlf[]
Definition main.c:86
static const uint8_t k_msg_none[]
Definition main.c:80
static const uint8_t k_msg_loops[]
Definition main.c:83
static void fc_make_synth(ra8_exception_last_t *out)
Fill a decoded snapshot with representative synthetic fault values.
Definition main.c:268
fc_synth_t
Synthetic decoded-fault values for the write proof.
Definition main.c:71
@ k_fc_synth_exc
Pretend UsageFault class.
Definition main.c:72
@ k_fc_synth_cfsr
CFSR.DIVBYZERO, mirrors fault_div0's dump.
Definition main.c:75
@ k_fc_synth_pc
Representative faulting PC (MRAM).
Definition main.c:73
@ k_fc_synth_lr
Representative link register.
Definition main.c:74
static void fc_print_hex32(uint32_t value)
Print a uint32 as "0x" + 8 fixed hex digits (MSB-first).
Definition main.c:154
fc_consts_t
Console + hex-printer knobs (no magic numbers).
Definition main.c:59
@ k_fc_hex_nib_mask
Low-nibble mask for hex printing.
Definition main.c:61
@ k_fc_uart_baud
SCI8 J-Link VCOM console baud.
Definition main.c:60
fc_hex_t
Hex-printer iteration constants.
Definition main.c:65
@ k_fc_hex_digits
Nibbles in a uint32 value.
Definition main.c:67
@ k_fc_hex_nib_bits
Bits per hex nibble.
Definition main.c:66
static const uint8_t k_msg_prior[]
Definition main.c:81
static const uint8_t k_msg_recorded[]
Definition main.c:85
static const uint8_t k_msg_pc[]
Definition main.c:82
static void fc_setup_or_halt(void)
Bring up clocks / MSTP + the SCI8 console; halt on failure.
Definition main.c:219
static void fc_print_uint(uint32_t value)
Print a uint32 in decimal (0 prints as "0").
Definition main.c:120
static void fc_log_sink(void *ctx, uint8_t byte)
ra8_log byte sink: forward every log byte to the SCI8 console.
Definition main.c:181
static void fc_panic_halt(const uint8_t *msg, uint32_t len)
Print the fail banner and trap (ra8_emulator halts on the BKPT).
Definition main.c:199
Board-support layer for the Renesas EK-RA8D2 v1 evaluation kit.
ra8_err_t ra8_board_uart_console_write(const uint8_t *data, size_t len)
Polled blocking write to the J-Link OB VCOM console.
ra8_err_t ra8_board_uart_console_init(uint32_t baud)
Configure SCI8 + PD02/PD03 as the debug-console UART.
Boot entry points shared between a vector table and its startup code.
High-level Clock Generation Circuit driver.
ra8_err_t ra8_cgc_init(void)
Configure the clock tree to a safe default.
Definition ra8_cgc.c:727
Cross-reset crash-log: persist the last fault + a reset-loop guard.
void ra8_crashlog_claim(void)
Consume the record and reset the reset-loop guard (clean claim).
bool ra8_crashlog_peek(ra8_crashlog_record_t *out)
Validate and copy out the last cross-reset record (non-destructive).
bool ra8_crashlog_safe_mode_requested(void)
Whether accumulated crashes crossed the reset-loop threshold.
void ra8_crashlog_record_fault(const volatile ra8_exception_last_t *decoded)
Persist a decoded fault snapshot into the cross-reset record.
void ra8_crashlog_install(void)
Arm the fault-persist hook so decoded faults are logged to .noinit.
Error Code Definitions for ra8-firmware.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
Cortex-M85 CPU exception diagnostic helpers.
@ k_ra8_exc_magic_valid
Snapshot is fully populated.
NVIC + ICU IELSR allocator.
void ra8_isr_globals_enable(void)
Globally enable maskable interrupts (PRIMASK = 0).
Definition ra8_isr.c:439
Lightweight Logging Interface for ra8-firmware.
void ra8_log_set_byte_sink(ra8_log_byte_sink_fn_t fn, void *ctx)
Install (or clear) an optional byte sink for log output.
Definition ra8_log.c:56
Ref-counted Module Stop Control wrapper for the RA8D2.
ra8_err_t ra8_mstp_init(void)
Re-establish the ra8_mstp ref-count table from current hardware state.
Definition ra8_mstp.c:291
The .noinit cross-reset post-mortem record.
ra8_exception_last_t fault
Embedded copy of the decoded fault / NMI snapshot.
uint32_t boot_loops
Monotonic recorded-fault counter; cleared by a claim.
uint32_t cfsr
Configurable Fault Status Register.
uint32_t pc
Program counter at fault.
uint32_t lr
Link register (return addr).
Fixed-SRAM post-mortem snapshot of the most recent fault or NMI.
uint32_t magic
k_ra8_exc_magic_valid when valid.
uint32_t exc_number
Architectural exception number.
ra8_exception_diagnostics_t diag
SCB fault-status snapshot.
ra8_exception_frame_t frame
Stacked GPR frame.