ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
emu_run_guards.c
Go to the documentation of this file.
1
15
16#include <stdio.h>
17#include <stdlib.h>
18#include <sys/stat.h>
19
21#include "emu_prof.h"
22#include "emu_run.h"
23#include "emu_view.h"
24
26enum : uint32_t {
27 /* ra8_delay_ms(16) in the render loop spins on SysTick, which advances one
28 * tick per chunk, so ~16 chunks == one loop iteration. Give the injected
29 * tap many iterations to flow DOWN -> UP -> CLICKED -> tab switch -> repaint. */
31};
32
51RA8_INTERNAL static uint32_t internal_guard_env_u32(const char* name, uint32_t dflt)
52{
53 const char* const e = getenv(name);
54 if (e == nullptr) {
55 return dflt;
56 }
57 const long v = strtol(e, nullptr, (int)k_env_strtol_base);
58 return (v > 0L) ? (uint32_t)v : dflt;
59}
60
80RA8_INTERNAL static uint32_t
81internal_guard_env_u32_headless(const char* name, uint32_t dflt, const board_view_t* view)
82{
83 if (view != nullptr) {
84 return dflt;
85 }
86 return internal_guard_env_u32(name, dflt);
87}
88
107RA8_INTERNAL static void internal_guard_read_wall(double* wall_s, bool* wall_guard_on)
108{
109 const char* const e_wall = getenv("RA8_EMU_WALL_S");
110 if (e_wall == nullptr) {
111 return;
112 }
113 const long v = strtol(e_wall, nullptr, (int)k_env_strtol_base);
114 if (v > 0L) {
115 *wall_s = (double)v;
116 } else if (v == 0L) {
117 *wall_guard_on = false; /* explicit opt-out: bound the run by chunks only */
118 }
119}
120
141 const board_view_t* view,
142 uint32_t* max_chunks)
143{
144 const char* const record_dir = cfg->record_dir;
145 const uint32_t record_secs = cfg->record_secs;
146 if ((record_dir != nullptr) && (record_secs > 0U) && (view == nullptr)) {
147 *max_chunks = record_secs * (uint32_t)k_record_ms_per_sec;
148 }
149 if (record_dir != nullptr) {
150 (void)mkdir(record_dir, (mode_t)k_record_dir_mode);
151 (void)priv_emu_io_errf(
152 "ra8_emulator: recording to %s/frame_NNNNNN.ppm (every %u chunks, ~%u fps)\n",
153 record_dir,
154 (unsigned)k_record_every,
155 (unsigned)k_record_fps);
156 }
157}
158
177{
178 const char* stop_on = getenv("RA8_EMU_STOP_ON");
179 if ((stop_on != nullptr) && ((stop_on[0] == '\0') || (view != nullptr))) {
180 stop_on = nullptr;
181 }
182 return stop_on;
183}
184
201{
202 const char* const e_spc = getenv("RA8_EMU_STOP_PC");
203 if (e_spc != nullptr) {
204 const unsigned long v = strtoul(e_spc, nullptr, (int)k_env_strtol_base);
205 emu_prof_set_stop_pc((uint32_t)(v & ~1UL)); /* clear the Thumb bit if supplied. */
206 }
207}
208
230RA8_INTERNAL static void
231internal_guard_read_prof_idle(uint32_t* insns, uint32_t* need, uint32_t* arm)
232{
233 enum : uint32_t {
234 k_prof_idle_insns = 4000U,
235 k_prof_idle_need = 600U,
236 k_prof_idle_arm = 16U,
237 };
238 *insns = (uint32_t)k_prof_idle_insns;
239 *need = (uint32_t)k_prof_idle_need;
240 *arm = (uint32_t)k_prof_idle_arm;
241 const char* const e_pi = getenv("RA8_EMU_PROFILE_IDLE_INSNS");
242 const char* const e_pn = getenv("RA8_EMU_PROFILE_IDLE_NEED");
243 const char* const e_pa = getenv("RA8_EMU_PROFILE_IDLE_ARM");
244 if (e_pi != nullptr) {
245 *insns = (uint32_t)strtoul(e_pi, nullptr, (int)k_strtol_base10);
246 }
247 if (e_pn != nullptr) {
248 *need = (uint32_t)strtoul(e_pn, nullptr, (int)k_strtol_base10);
249 }
250 if (e_pa != nullptr) {
251 *arm = (uint32_t)strtoul(e_pa, nullptr, (int)k_strtol_base10);
252 }
253}
254
256{
257 /* RA8_EMU_CLICK_SETTLE=N: widen the post-click drain for a tap that kicks off
258 * a long operation (e.g. opening a big book from SD). Unset keeps the default. */
259 const uint32_t click_settle_chunks =
260 internal_guard_env_u32("RA8_EMU_CLICK_SETTLE", (uint32_t)k_click_settle_chunks);
261
262 /* Chunked run: one SysTick (one ThreadX tick) per outer chunk. Headless runs
263 * stop on a chunk budget + wall-clock guard; --view runs until the window is
264 * closed. RA8_EMU_WALL_S / MAX_CHUNKS override the guards without a recompile
265 * and have no effect in --view mode. */
266 uint32_t max_chunks =
267 (view != nullptr) ? (uint32_t)k_view_max_chunks : (uint32_t)k_run_max_chunks;
268 double wall_s = (double)k_run_wall_s;
269 bool wall_guard_on = true;
270 internal_guard_read_wall(&wall_s, &wall_guard_on);
271 max_chunks = internal_guard_env_u32_headless("RA8_EMU_MAX_CHUNKS", max_chunks, view);
272 internal_guard_setup_record(cfg, view, &max_chunks);
273
274 /* Headless-only early-stop knobs: idle steady-state (IDLE_STOP), USB device
275 * CONFIGURED (USB_STOP) and USB host complete (USBH_STOP). Off (0) by default. */
276 const uint32_t idle_stop_chunks = internal_guard_env_u32_headless("RA8_EMU_IDLE_STOP", 0U, view);
277 const uint32_t usb_stop_settle = internal_guard_env_u32_headless("RA8_EMU_USB_STOP", 0U, view);
278 const uint32_t usbh_stop_settle = internal_guard_env_u32_headless("RA8_EMU_USBH_STOP", 0U, view);
279 const char* const stop_on = internal_guard_read_stop_on(view);
281 uint32_t prof_idle_insns = 0U;
282 uint32_t prof_idle_need = 0U;
283 uint32_t prof_idle_arm = 0U;
284 internal_guard_read_prof_idle(&prof_idle_insns, &prof_idle_need, &prof_idle_arm);
285
286 return (run_guards_t){
287 .click_settle_chunks = click_settle_chunks,
288 .max_chunks = max_chunks,
289 .wall_s = wall_s,
290 .wall_guard_on = wall_guard_on,
291 .idle_stop_chunks = idle_stop_chunks,
292 .usb_stop_settle = usb_stop_settle,
293 .usbh_stop_settle = usbh_stop_settle,
294 .stop_on = stop_on,
295 .prof_idle_insns = prof_idle_insns,
296 .prof_idle_need = prof_idle_need,
297 .prof_idle_arm = prof_idle_arm,
298 };
299}
struct board_view board_view_t
Opaque desktop-window handle (defined in board_view.m).
Definition board_view.h:31
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.
Firmware profiler (RA8_EMU_PROFILE): sampling, hooks, reports.
void emu_prof_set_stop_pc(uint32_t pc)
Set the RA8_EMU_STOP_PC early-stop address (0 disables).
Definition emu_prof.c:961
The chunked emulation run loop, report and exit-code mapping.
@ k_env_strtol_base
Decimal base for env-var integer parse.
Definition emu_run.h:64
@ k_run_wall_s
Wall-clock safety bound (seconds).
Definition emu_run.h:62
@ k_run_max_chunks
Chunk budget.
Definition emu_run.h:42
@ k_record_dir_mode
mkdir mode for the –record dir.
Definition emu_run.h:96
static RA8_INTERNAL const char * internal_guard_read_stop_on(const board_view_t *view)
Resolve the RA8_EMU_STOP_ON console-banner stop substring.
static RA8_INTERNAL uint32_t internal_guard_env_u32_headless(const char *name, uint32_t dflt, const board_view_t *view)
Read a headless-only RA8_EMU_* positive uint32 knob.
static RA8_INTERNAL void internal_guard_read_prof_idle(uint32_t *insns, uint32_t *need, uint32_t *arm)
Read the profiler compute-idle early-stop tunables.
static RA8_INTERNAL uint32_t internal_guard_env_u32(const char *name, uint32_t dflt)
Read a RA8_EMU_* env var as a positive decimal uint32.
static RA8_INTERNAL void internal_guard_read_wall(double *wall_s, bool *wall_guard_on)
Apply the RA8_EMU_WALL_S CPU-time guard override.
static RA8_INTERNAL void internal_guard_apply_stop_pc(void)
Hand RA8_EMU_STOP_PC (if set) to the profiler stop hook.
run_guards_t run_read_guards(const emu_run_cfg_t *cfg, const board_view_t *view)
Read the run-guard environment knobs (see run_guards_t).
@ k_click_settle_chunks
Extra chunks after the click lands.
static RA8_INTERNAL void internal_guard_setup_record(const emu_run_cfg_t *cfg, const board_view_t *view, uint32_t *max_chunks)
Apply the –record chunk bound and create the frame directory.
Board-view presentation: frames, composition, input routing, panels.
@ k_strtol_base10
Base-10 radix for strtol parses.
Definition emu_view.h:85
@ k_record_every
Chunks between recorded frames (1000/20).
Definition emu_view.h:59
@ k_record_fps
Recorded frames per emulated second.
Definition emu_view.h:58
@ k_record_ms_per_sec
Emulated ms (= chunks) per second.
Definition emu_view.h:57
@ k_view_max_chunks
Cap in –view; closing the window ends.
Definition emu_view.h:46
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Everything setup hands the run loop: engine, image, CLI products.
Definition emu_run.h:122
const char * record_dir
–record directory (NULL when unused).
Definition emu_run.h:133
uint32_t record_secs
–record-secs bound (0 = unbounded).
Definition emu_run.h:134
The run-guard knobs (env-tunable budgets + stop conditions).
Definition emu_run.h:164