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
43
44#include <stddef.h>
45#include <stdint.h>
46
47#include "ra8_attributes.h"
48#include "ra8_board_ek_ra8d2.h"
49#include "ra8_boot_entry.h"
50#include "ra8_cgc.h"
51#include "ra8_err.h"
52#include "ra8_isr.h"
53#include "ra8_log.h"
54#include "ra8_mstp.h"
55
57typedef enum : uint32_t {
58 k_fd_uart_baud = 115200U,
62
64typedef enum : uintptr_t {
65 k_fd_scb_ccr_addr = 0xE000ED14UL,
67
69typedef enum : uint32_t {
70 k_fd_ccr_div_0_trp = 1UL << 4,
72
73static const uint8_t s_msg_boot[] = "fault-div0: boot\r\n";
74static const uint8_t s_msg_fail[] = "fault-div0: FAIL init\r\n";
75static const uint8_t s_msg_armed[] = "fault-div0: trap armed\r\n";
76static const uint8_t s_msg_unarmed[] = "fault-div0: FAIL trap not armed\r\n";
77static const uint8_t s_msg_survived[] = "fault-div0: survived divide quotient=";
78static const uint8_t s_msg_emu_tail[] = " (trap not modelled -- ra8_emulator)\r\n";
79
90static volatile uint32_t s_fd_dividend = (uint32_t)k_fd_dividend;
91
100static volatile uint32_t s_fd_divisor = (uint32_t)k_fd_divisor;
101
110volatile uint32_t g_fd_quotient = 0U;
111
118volatile uint32_t g_fd_heartbeat = 0U;
119
134RA8_INTERNAL static void internal_print(const uint8_t* msg, uint32_t len)
135{
136 (void)ra8_board_uart_console_write(msg, (size_t)len);
137}
138
160RA8_INTERNAL static void internal_log_sink(void* ctx, uint8_t byte)
161{
162 (void)ctx;
163 (void)ra8_board_uart_console_write(&byte, 1U);
164}
165
180[[noreturn]] RA8_INTERNAL static void internal_panic_halt(const uint8_t* msg, uint32_t len)
181{
182 internal_print(msg, len);
183 __asm__ volatile("bkpt #0");
184 while (1) {
185 __asm__ volatile("wfi");
186 }
187}
188
202RA8_INTERNAL static void internal_print_uint(uint32_t value)
203{
204 enum : uint32_t {
205 k_fd_dec_base = 10U,
206 k_fd_dec_digits = 10U,
207 };
208 uint8_t buf[k_fd_dec_digits];
209 uint32_t n = 0U;
210 if (value == 0U) {
211 buf[n] = '0';
212 n++;
213 }
214 while ((value > 0U) && (n < (uint32_t)k_fd_dec_digits)) {
215 buf[n] = (uint8_t)('0' + (value % (uint32_t)k_fd_dec_base));
216 n++;
217 value /= (uint32_t)k_fd_dec_base;
218 }
219 for (uint32_t i = 0U; i < n; i++) {
220 internal_print(&buf[n - 1U - i], 1U);
221 }
222}
223
237{
238 if (ra8_cgc_init() != k_ra8_ok) {
239 internal_panic_halt(s_msg_fail, (uint32_t)sizeof(s_msg_fail) - 1U);
240 }
241 if (ra8_mstp_init() != k_ra8_ok) {
242 internal_panic_halt(s_msg_fail, (uint32_t)sizeof(s_msg_fail) - 1U);
243 }
245 internal_panic_halt(s_msg_fail, (uint32_t)sizeof(s_msg_fail) - 1U);
246 }
247}
248
249void main(void)
250{
253 /* Route the fault handler's ra8_log dump onto the bench console. */
255 internal_print(s_msg_boot, (uint32_t)sizeof(s_msg_boot) - 1U);
256
257 /* Prove the boot-path write landed before relying on it: CCR must
258 * read back with DIV_0_TRP set (works on silicon AND ra8_emulator --
259 * the fake's SCS window stores the write even though its CPU model
260 * ignores it). ARMv8-M SCB->CCR, read-only probe. */
261 const uint32_t ccr = *(volatile uint32_t*)k_fd_scb_ccr_addr;
262 if ((ccr & (uint32_t)k_fd_ccr_div_0_trp) == 0U) {
263 internal_panic_halt(s_msg_unarmed, (uint32_t)sizeof(s_msg_unarmed) - 1U);
264 }
265 internal_print(s_msg_armed, (uint32_t)sizeof(s_msg_armed) - 1U);
266
267 /* The guarded zero-divide. Volatile operands force a run-time UDIV.
268 * Silicon: UsageFault here -> decoded dump prints -> halt (the app
269 * never reaches the next line). ra8_emulator: quotient 0, fall through. */
270 const uint32_t quotient = s_fd_dividend / s_fd_divisor;
271
272 g_fd_quotient = quotient;
273 internal_print(s_msg_survived, (uint32_t)sizeof(s_msg_survived) - 1U);
274 internal_print_uint(quotient);
275 internal_print(s_msg_emu_tail, (uint32_t)sizeof(s_msg_emu_tail) - 1U);
276
277 while (1) {
279 __asm__ volatile("wfi");
280 }
281}
void main(void)
Secure fallback main entry point.
Definition main.c:37
static const uint8_t s_msg_boot[]
Console marker emitted after core and peripheral setup.
Definition main.c:216
static const uint8_t s_msg_fail[]
Diagnostic emitted when the VFS round-trip fails.
Definition main.c:104
static void internal_setup_or_halt(void)
Bring up clocks, MSTP, delay timing, and the board console.
Definition main.c:211
static void internal_panic_halt(void)
Park the core after an unrecoverable ADC demo failure.
Definition main.c:123
static volatile uint32_t s_fd_dividend
Volatile numerator so the divide executes at run time.
Definition main.c:90
static volatile uint32_t s_fd_divisor
Volatile zero divisor – the UDIV of this value must trap.
Definition main.c:100
volatile uint32_t g_fd_heartbeat
Bumps forever in the survival idle loop – liveness for probes.
Definition main.c:118
fd_scb_addr_t
ARMv8-M SCB register addresses this app reads.
Definition main.c:64
@ k_fd_scb_ccr_addr
Configuration and Control Register.
Definition main.c:65
fd_ccr_bits_t
CCR bits checked by the arming probe.
Definition main.c:69
@ k_fd_ccr_div_0_trp
ARMv8-M CCR.DIV_0_TRP – divide-by-zero traps.
Definition main.c:70
static void internal_print(const uint8_t *msg, uint32_t len)
Emit a byte run on the SCI8 console.
Definition main.c:134
static const uint8_t s_msg_unarmed[]
Definition main.c:76
static void internal_log_sink(void *ctx, uint8_t byte)
ra8_log byte sink: forward every log byte to the SCI8 console.
Definition main.c:160
static const uint8_t s_msg_survived[]
Definition main.c:77
static void internal_print_uint(uint32_t value)
Print a small unsigned integer in decimal (quotient display).
Definition main.c:202
static const uint8_t s_msg_emu_tail[]
Definition main.c:78
volatile uint32_t g_fd_quotient
Quotient observed when the trap did NOT fire (emulator survival path).
Definition main.c:110
static const uint8_t s_msg_armed[]
Definition main.c:75
fd_consts_t
Console + divide-test knobs (no magic numbers).
Definition main.c:57
@ k_fd_dividend
Numerator for the guarded zero-divide.
Definition main.c:59
@ k_fd_divisor
The zero divisor that must trap on silicon.
Definition main.c:60
@ k_fd_uart_baud
SCI8 J-Link VCOM console baud.
Definition main.c:58
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
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
Error Code Definitions for ra8-firmware.
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
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