ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
board_periph_reset.c
Go to the documentation of this file.
1
36
37#include <stdint.h>
38#include <stdio.h>
39
40#include "board_periph_block.h"
42
44typedef enum : uint64_t {
45 k_rstsr1_base = 0x4001E0C0UL,
46 k_rstsr1_span = 0x04UL,
48
50typedef enum : uint64_t {
51 k_rstsr0_base = 0x4001EA40UL,
52 k_rstsr0_span = 0x0CUL,
53 k_rstsr0_off_r0 = 0x00UL,
54 k_rstsr0_off_r2 = 0x04UL,
55 k_rstsr0_off_r3 = 0x08UL,
57
59typedef enum : uint32_t {
60 k_rstsr0_porf = 0x01U,
61 k_rstsr1_iwdtrf = 0x00000001U,
62 k_rstsr1_wdtrf = 0x00000002U,
63 k_rstsr1_swrf = 0x00000004U,
65
67typedef enum : uint32_t {
70
79static uint32_t s_rstsr1;
80static uint8_t s_rstsr0;
81static uint8_t s_rstsr2;
82static uint8_t s_rstsr3;
83
84/* A pending warm-reboot request raised by a peripheral model (e.g. the WDT on a
85 * watchdog-reset underflow). The run loop polls board_periph_reset_take_request
86 * each chunk and performs the reboot. 0 = none; otherwise the cause to latch. */
87static uint32_t s_reboot_req_cause;
88
95
96void board_periph_reset_request_reboot(bool watchdog, bool iwdt)
97{
98 if (watchdog) {
100 } else if (iwdt) {
102 }
103}
104
105bool board_periph_reset_take_request(bool* out_watchdog, bool* out_iwdt)
106{
107 if ((out_watchdog == nullptr) || (out_iwdt == nullptr)) {
108 return false;
109 }
110 if (s_reboot_req_cause == (uint32_t)k_reboot_cause_none) {
111 return false;
112 }
113 *out_watchdog = (s_reboot_req_cause == (uint32_t)k_reboot_cause_wdt);
114 *out_iwdt = (s_reboot_req_cause == (uint32_t)k_reboot_cause_iwdt);
116 return true;
117}
118
119void board_periph_reset_set_cause(bool power_on, bool software, bool watchdog, bool iwdt)
120{
121 if (power_on) {
122 /* A power-on / cold reboot: PORF is the cause; leave it set (the reset model
123 * retains it across the warm reboot) and assert nothing else. */
124 s_rstsr0 |= (uint8_t)k_rstsr0_porf;
125 return;
126 }
127 /* Any non-power-on reset clears PORF and latches the specific cause flag(s). */
128 s_rstsr0 &= (uint8_t)~(uint8_t)k_rstsr0_porf;
129 if (software) {
130 s_rstsr1 |= (uint32_t)k_rstsr1_swrf;
131 }
132 if (watchdog) {
133 s_rstsr1 |= (uint32_t)k_rstsr1_wdtrf;
134 }
135 if (iwdt) {
136 s_rstsr1 |= (uint32_t)k_rstsr1_iwdtrf;
137 }
138}
139
149{
150 /* Intentionally a no-op: the RSTSRn flags must survive a warm reboot so the
151 * firmware can read the cause that triggered it. They clear only at process
152 * start (static init) where the constructor seeds PORF. */
153}
154
168RA8_INTERNAL static uint64_t internal_reset1_read(uc_engine* uc, uint64_t addr, unsigned size)
169{
170 (void)uc;
171 (void)addr;
172 (void)size;
173 return s_rstsr1;
174}
175
188RA8_INTERNAL static void
189internal_reset1_write(uc_engine* uc, uint64_t addr, unsigned size, uint64_t value)
190{
191 (void)uc;
192 (void)addr;
193 (void)size;
194 /* Keep only bits that are set AND written as 1; a written 0 clears the bit. */
195 s_rstsr1 &= (uint32_t)value;
196}
197
211RA8_INTERNAL static uint64_t internal_reset0_read(uc_engine* uc, uint64_t addr, unsigned size)
212{
213 (void)uc;
214 (void)size;
215 const uint64_t off = addr - (uint64_t)k_rstsr0_base;
216 if (off == (uint64_t)k_rstsr0_off_r0) {
217 return s_rstsr0;
218 }
219 if (off == (uint64_t)k_rstsr0_off_r2) {
220 return s_rstsr2;
221 }
222 if (off == (uint64_t)k_rstsr0_off_r3) {
223 return s_rstsr3;
224 }
225 return 0U;
226}
227
240RA8_INTERNAL static void
241internal_reset0_write(uc_engine* uc, uint64_t addr, unsigned size, uint64_t value)
242{
243 (void)uc;
244 (void)size;
245 const uint64_t off = addr - (uint64_t)k_rstsr0_base;
246 if (off == (uint64_t)k_rstsr0_off_r0) {
247 s_rstsr0 &= (uint8_t)value; /* write-0-to-clear */
248 } else if (off == (uint64_t)k_rstsr0_off_r2) {
249 s_rstsr2 = (uint8_t)value; /* RSTSR2.CWSF is write-1 set; shadow it */
250 } else if (off == (uint64_t)k_rstsr0_off_r3) {
251 s_rstsr3 = (uint8_t)value;
252 }
253}
254
264{
265 if ((s_rstsr1 == 0U) && ((s_rstsr0 & (uint8_t)k_rstsr0_porf) == 0U)) {
266 return; /* nothing notable to report */
267 }
268 (void)priv_emu_io_errf(" RESET-CAUSE : RSTSR0=0x%02X RSTSR1=0x%08X (%s%s%s%s)\n",
269 (unsigned)s_rstsr0,
270 s_rstsr1,
271 ((s_rstsr0 & (uint8_t)k_rstsr0_porf) != 0U) ? "POR " : "",
272 ((s_rstsr1 & (uint32_t)k_rstsr1_swrf) != 0U) ? "SW " : "",
273 ((s_rstsr1 & (uint32_t)k_rstsr1_wdtrf) != 0U) ? "WDT " : "",
274 ((s_rstsr1 & (uint32_t)k_rstsr1_iwdtrf) != 0U) ? "IWDT " : "");
275}
276
279 .base = (uint64_t)k_rstsr1_base,
280 .span = (uint64_t)k_rstsr1_span,
281 .order = (uint32_t)k_reset_block_order,
282 .read = internal_reset1_read,
284 .tick = nullptr,
285 .reset = internal_reset_reset,
286 .report = internal_reset_report,
287 .name = "RESET-RSTSR1",
288};
289
292 .base = (uint64_t)k_rstsr0_base,
293 .span = (uint64_t)k_rstsr0_span,
294 .order = (uint32_t)k_reset_block_order,
295 .read = internal_reset0_read,
297 .tick = nullptr,
298 .reset = nullptr,
299 .report = nullptr,
300 .name = "RESET-RSTSR0",
301};
302
304[[gnu::constructor]] RA8_INTERNAL static void internal_reset_block_register(void)
305{
306 s_rstsr0 |= (uint8_t)k_rstsr0_porf; /* first-ever boot is a power-on reset */
309}
Decentralized peripheral-block registry for the board emulator core.
void board_periph_register_block(const board_periph_block_t *block)
Register a peripheral block's descriptor with the core registry.
static RA8_INTERNAL void internal_reset_report(void)
End-of-run reset section: the latched cause flags.
static uint8_t s_rstsr0
RSTSR0 sticky flags.
static RA8_INTERNAL void internal_reset_reset(void)
Reset hook: the cause flags are sticky, so this preserves them.
static RA8_INTERNAL uint64_t internal_reset0_read(uc_engine *uc, uint64_t addr, unsigned size)
MMIO read inside the RSTSR0 / RSTSR2 / RSTSR3 window.
static uint8_t s_rstsr3
RSTSR3.
reset_order_t
Per-tick order slot for the reset block (relative order only).
@ k_reset_block_order
After the VBATT-backup block; report order.
static uint32_t s_reboot_req_cause
reset1_geom_t
RSTSR1 window geometry (ra8_reset_regs.h).
@ k_rstsr1_span
Single 32-bit register.
@ k_rstsr1_base
RSTSR1 (32-bit).
void board_periph_reset_set_cause(bool power_on, bool software, bool watchdog, bool iwdt)
Record the cause of a warm reboot in the sticky RSTSRn flags.
static const board_periph_block_t s_k_reset0_block
RSTSR0 / RSTSR2 / RSTSR3 block descriptor.
reset0_geom_t
RSTSR0 / RSTSR2 / RSTSR3 window geometry (ra8_reset_regs.h).
@ k_rstsr0_off_r3
RSTSR3.
@ k_rstsr0_span
Covers RSTSR0 / RSTSR2 / RSTSR3.
@ k_rstsr0_off_r2
RSTSR2 (CWSF).
@ k_rstsr0_base
RSTSR0 (8-bit) window base.
@ k_rstsr0_off_r0
RSTSR0 at the window base.
reboot_cause_t
Reboot-cause codes a peripheral can request via _request_reboot.
@ k_reboot_cause_wdt
Watchdog-0 reset (RSTSR1.WDTRF).
@ k_reboot_cause_none
No pending request.
@ k_reboot_cause_iwdt
Independent-watchdog reset.
static uint8_t s_rstsr2
RSTSR2 (CWSF).
static const board_periph_block_t s_k_reset1_block
RSTSR1 block descriptor (owns the report).
static RA8_INTERNAL uint64_t internal_reset1_read(uc_engine *uc, uint64_t addr, unsigned size)
MMIO read inside the RSTSR1 window.
static RA8_INTERNAL void internal_reset_block_register(void)
Register the reset-status windows + seed PORF (cold boot).
static RA8_INTERNAL void internal_reset1_write(uc_engine *uc, uint64_t addr, unsigned size, uint64_t value)
MMIO write inside the RSTSR1 window (write-0-to-clear flags).
reset_flag_t
RSTSR flag bit masks (ra8_reset_regs.h).
@ k_rstsr1_swrf
RSTSR1.SWRF software reset (bit 2).
@ k_rstsr1_iwdtrf
RSTSR1.IWDTRF independent WDT (bit 0).
@ k_rstsr1_wdtrf
RSTSR1.WDTRF watchdog reset (bit 1).
@ k_rstsr0_porf
RSTSR0.PORF power-on reset (bit 0).
static uint32_t s_rstsr1
Sticky reset-cause flags (survive a warm reboot).
bool board_periph_reset_take_request(bool *out_watchdog, bool *out_iwdt)
Consume a pending peripheral reboot request, if any (run-loop side).
static RA8_INTERNAL void internal_reset0_write(uc_engine *uc, uint64_t addr, unsigned size, uint64_t value)
MMIO write inside the RSTSR0 / RSTSR2 / RSTSR3 window.
void board_periph_reset_request_reboot(bool watchdog, bool iwdt)
Request a warm reboot from a peripheral model (e.g.
Bounded raw-descriptor I/O seam for the RA8 emulator.
emu_io_result_t priv_emu_io_errf(const char *format,...)
Format bounded text and write it to the injected error descriptor.
-proof
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
A modelled peripheral block's self-description for the core registry.