ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
board_periph_wdt.c
Go to the documentation of this file.
1
39
40#include <stdint.h>
41#include <stdio.h>
42
43#include "board_periph.h"
44#include "board_periph_block.h"
46
48typedef enum : uint64_t {
49 k_wdt_base = 0x40202600UL,
50 k_wdt_span = 0x10UL,
51 k_wdt_off_wdtrr = 0x00UL,
52 k_wdt_off_wdtcr = 0x02UL,
53 k_wdt_off_wdtsr = 0x04UL,
56
58typedef enum : uint32_t {
62 k_wdt_sr_cntval = 0x3FFFU,
63 k_wdt_sr_undff = 0x4000U,
64 /* Emulation timeout in run-loop chunks. The demo refreshes about every 50
65 * chunks; this is comfortably longer (so a refreshing app never trips) yet
66 * well within the run budget once refreshing stops. */
69
71typedef enum : uint32_t {
74
76typedef struct {
77 uint16_t wdtcr;
78 uint8_t wdtrcr;
79 uint8_t last_rr;
80 bool armed;
81 bool fired;
82 uint32_t counter;
83 uint16_t undff;
84 uint32_t refreshes;
86
88
98RA8_INTERNAL static void internal_wdt_tick(uc_engine* uc)
99{
100 (void)uc;
101 if (!s_wdt.armed || s_wdt.fired) {
102 return;
103 }
104 if (s_wdt.counter > 0U) {
105 s_wdt.counter--;
106 return;
107 }
108 /* Underflow. Latch UNDFF; if configured for reset, request a warm reboot with
109 * the watchdog-reset cause and disarm so it fires exactly once. */
110 s_wdt.undff = (uint16_t)k_wdt_sr_undff;
111 if ((s_wdt.wdtrcr & (uint8_t)k_wdt_rcr_rstirqs) != 0U) {
112 s_wdt.fired = true;
113 s_wdt.armed = false;
115 }
116}
117
127{
128 s_wdt = (wdt_state_t){};
129}
130
144RA8_INTERNAL static uint64_t internal_wdt_read(uc_engine* uc, uint64_t addr, unsigned size)
145{
146 (void)uc;
147 (void)size;
148 const uint64_t off = addr - (uint64_t)k_wdt_base;
149 if (off == (uint64_t)k_wdt_off_wdtcr) {
150 return s_wdt.wdtcr;
151 }
152 if (off == (uint64_t)k_wdt_off_wdtsr) {
153 const uint16_t cnt = (uint16_t)(s_wdt.counter & (uint32_t)k_wdt_sr_cntval);
154 return (uint64_t)(cnt | s_wdt.undff);
155 }
156 if (off == (uint64_t)k_wdt_off_wdtrcr) {
157 return s_wdt.wdtrcr;
158 }
159 return 0U;
160}
161
174RA8_INTERNAL static void
175internal_wdt_write(uc_engine* uc, uint64_t addr, unsigned size, uint64_t value)
176{
177 (void)uc;
178 (void)size;
179 const uint64_t off = addr - (uint64_t)k_wdt_base;
180 if (off == (uint64_t)k_wdt_off_wdtrr) {
181 const uint8_t b = (uint8_t)value;
182 /* The 0x00 then 0xFF sequence refreshes: arm (first time) and reload. */
183 if ((s_wdt.last_rr == (uint8_t)k_wdt_refresh_a) && (b == (uint8_t)k_wdt_refresh_b)) {
184 s_wdt.armed = true;
185 s_wdt.counter = (uint32_t)k_wdt_timeout_ticks;
186 s_wdt.undff = 0U;
187 s_wdt.refreshes++;
188 }
189 s_wdt.last_rr = b;
190 } else if (off == (uint64_t)k_wdt_off_wdtcr) {
191 s_wdt.wdtcr = (uint16_t)value;
192 } else if (off == (uint64_t)k_wdt_off_wdtrcr) {
193 s_wdt.wdtrcr = (uint8_t)value;
194 }
195}
196
206{
207 if ((s_wdt.refreshes == 0U) && !s_wdt.fired) {
208 return; /* Untouched: stay quiet. */
209 }
210 (void)priv_emu_io_errf(" WDT0 : refreshes=%u armed=%u reset_fired=%u\n",
211 s_wdt.refreshes,
212 (unsigned)s_wdt.armed,
213 (unsigned)s_wdt.fired);
214}
215
218 .base = (uint64_t)k_wdt_base,
219 .span = (uint64_t)k_wdt_span,
220 .order = (uint32_t)k_wdt_block_order,
221 .read = internal_wdt_read,
223 .tick = internal_wdt_tick,
224 .reset = internal_wdt_reset,
225 .report = internal_wdt_report,
226 .name = "WDT0",
227};
228
230[[gnu::constructor]] RA8_INTERNAL static void internal_wdt_block_register(void)
231{
233}
Register-accurate peripheral-model framework for the board emulator.
void board_periph_reset_request_reboot(bool watchdog, bool iwdt)
Request a warm reboot from a peripheral model (e.g.
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_wdt_tick(uc_engine *uc)
Per-chunk advance: run the armed down-counter; reset on underflow.
static RA8_INTERNAL void internal_wdt_write(uc_engine *uc, uint64_t addr, unsigned size, uint64_t value)
MMIO write inside the WDT window.
static RA8_INTERNAL uint64_t internal_wdt_read(uc_engine *uc, uint64_t addr, unsigned size)
MMIO read inside the WDT window.
static RA8_INTERNAL void internal_wdt_block_register(void)
Register the WDT0 block before main (host constructor).
wdt_field_t
WDT register field constants (ra8_wdt_regs.h).
@ k_wdt_timeout_ticks
Wdt timeout ticks.
@ k_wdt_refresh_b
Second byte of the refresh sequence.
@ k_wdt_sr_cntval
WDTSR.CNTVAL[13:0] live counter.
@ k_wdt_sr_undff
WDTSR.UNDFF underflow flag (bit 14).
@ k_wdt_refresh_a
First byte of the refresh sequence.
@ k_wdt_rcr_rstirqs
WDTRCR.RSTIRQS: 1 = reset on underflow.
wdt_order_t
Per-tick order slot for the WDT block (relative order only).
@ k_wdt_block_order
After the reset block; report order.
static const board_periph_block_t s_k_wdt_block
WDT0 block descriptor (self-registered with the core).
static RA8_INTERNAL void internal_wdt_reset(void)
Reset the WDT model to power-on state.
static wdt_state_t s_wdt
static RA8_INTERNAL void internal_wdt_report(void)
End-of-run WDT section: refreshes and whether it fired a reset.
wdt_geom_t
WDT0 block geometry (ra8_wdt_regs.h, r_wdt_regs_t).
@ k_wdt_off_wdtcr
WDTCR control (16b).
@ k_wdt_base
WDT0 base (HUM Ch 27).
@ k_wdt_span
Covers WDTRR..WDTRCR.
@ k_wdt_off_wdtrcr
WDTRCR reset control (8b).
@ k_wdt_off_wdtsr
WDTSR status (16b).
@ k_wdt_off_wdtrr
WDTRR refresh register (8b).
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.
WDT model state.
uint32_t refreshes
Refreshes serviced (for the report).
bool armed
Counter is running (first refresh seen).
uint16_t undff
UNDFF status latch.
bool fired
Reset already requested (one-shot).
uint32_t counter
Down-counter, in ticks.
uint16_t wdtcr
WDTCR shadow (timeout / window select).
uint8_t wdtrcr
WDTRCR shadow (RSTIRQS).
uint8_t last_rr
Last WDTRR byte (for the 0x00->0xFF seq).