ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
emu_run.c
Go to the documentation of this file.
1
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <sys/stat.h>
21#include <time.h>
22#include <unistd.h>
23
24#include "board_console.h"
25#include "board_input.h"
26#include "board_net.h"
27#include "board_overlay.h"
28#include "board_periph.h"
29#include "board_periph_sd.h"
30#include "board_usb.h"
31#include "board_view.h"
32#include "emu_console.h"
33#include "emu_cpu1.h"
34#include "emu_elf.h"
35#include "emu_engine.h"
36#include "emu_exc.h"
38#include "emu_memmap.h"
39#include "emu_mmio.h"
40#include "emu_mpu.h"
41#include "emu_prof.h"
42#include "emu_run_internal.h"
43#include "emu_seams.h"
44#include "emu_usbh_seam.h"
45#include "emu_view.h"
46
60typedef enum : uint8_t {
65
93
112{
113 if (cfg->want_view) {
114 st->view = board_view_open(&st->view_storage, st->comp_w, st->comp_h, cfg->win_title);
115 if (st->view == nullptr) {
116 (void)priv_emu_io_errf("ra8_emulator: could not open window; continuing headless\n");
117 }
118 }
119}
120
140{
141 if (!cfg->want_click) {
142 return;
143 }
144 (void)priv_emu_io_errf("ra8_emulator: --click armed at (%d,%d)\n", cfg->click_x, cfg->click_y);
145 uint32_t click_tab_idx = 0U;
146 if (board_overlay_hit_console_tab((uint16_t)cfg->click_x,
147 (uint16_t)cfg->click_y,
148 st->disp_w,
149 (uint32_t)k_board_console_ch_count,
150 &click_tab_idx)) {
151 emu_view_select_console_tab(click_tab_idx);
152 st->click_was_tab = true;
153 }
154 st->click_btn =
155 (!st->click_was_tab)
156 ? board_overlay_hit_button((uint16_t)cfg->click_x, (uint16_t)cfg->click_y, st->disp_w)
158}
159
178{
179 *st = (run_loop_t){};
180 st->cfg = cfg;
183 st->reboot_count = cfg->reboot_count;
184 st->run_pc = cfg->initial_pc;
185 st->err = UC_ERR_OK;
187 internal_run_open_view(cfg, st);
188 st->guards = run_read_guards(cfg, st->view);
190 st->t0 = clock();
191}
192
214{
215 const emu_run_cfg_t* cfg = st->cfg;
216 /* RA8_EMU_PROFILE: charge the wall time of the previous chunk to the
217 * function its execution started in (so a cheap WFI-halt chunk and an
218 * expensive compute chunk are weighted by real time, not by chunk count). */
219 if (emu_prof_mode() == k_prof_wall) {
220 const double now = board_now_s();
221 if (st->prof_prev_t > 0.0) {
222 prof_add(st->prof_prev_pc, now - st->prof_prev_t);
223 }
224 st->prof_prev_pc = st->run_pc;
225 st->prof_prev_t = now;
226 }
227 emu_view_publish(st->run_pc, st->chunks); /* PC + chunk counter for the board view. */
228
229 /* --reboot N: after each boot's settle window force a power-on warm reboot;
230 * the reset-retained models (VBATT backup) survive, proving reset-survival.
231 */
232 if ((st->reboot_count > 0) && ((st->chunks - st->last_boot_chunk) >= (uint32_t)k_reboot_settle)) {
233 st->reboot_count--;
234 board_periph_reset_set_cause(true, false, false, false); /* power-on reboot */
235 st->run_pc = warm_reboot(cfg->uc, cfg->elf, cfg->want_trace);
236 if (st->run_pc == 0U) {
237 return k_loop_break; /* reboot failed to reload the image -- end the run
238 */
239 }
240 st->last_boot_chunk = st->chunks;
241 return k_loop_continue;
242 }
243 /* A peripheral (the watchdog) may have requested a reset on its tick: latch
244 * the watchdog cause and warm-reboot so the next boot reads reset_by=wdt. */
245 bool wdt_rst = false;
246 bool iwdt_rst = false;
247 if (board_periph_reset_take_request(&wdt_rst, &iwdt_rst)) {
248 board_periph_reset_set_cause(false, false, wdt_rst, iwdt_rst);
249 st->run_pc = warm_reboot(cfg->uc, cfg->elf, cfg->want_trace);
250 if (st->run_pc == 0U) {
251 return k_loop_break; /* reboot failed to reload the image -- end the run
252 */
253 }
254 st->last_boot_chunk = st->chunks;
255 return k_loop_continue;
256 }
257 return k_loop_next;
258}
259
278{
279 const emu_run_cfg_t* cfg = st->cfg;
280 emu_exc_arm_systick(); /* one SysTick period per outer chunk. */
281 /* DWT cycle counter: keep a masked-context ra8_delay_ms (spins on CYCCNT with
282 * PRIMASK set) making progress. Inert unless the firmware enabled it. */
284 board_periph_tick(cfg->uc); /* advance timers; pend any wrap IRQ like SysTick. */
286
287 /* Drain buffered keystrokes into the console UART RX (the SCI channel --input
288 * targets), from the live window (keyDown) and the headless --keys injector.
289 */
290 char key_byte = 0;
291 while (board_input_pop_key(&key_byte)) {
292 const uint8_t kb = (uint8_t)key_byte;
294 }
295
296 /* Headless --click: keep one contact armed in the GT911 model until the
297 * firmware's real ra8_touch_read drains it; re-arming each chunk is needed
298 * because ra8_touch_open clears the GT911 status byte during bring-up. */
299 if (cfg->want_click && (st->click_btn != k_board_overlay_btn_none)) {
300 if (!st->button_fired) {
304 apply_battery_click(st->click_btn, (uint16_t)cfg->click_x, st->disp_w); /* SOC/CHG/LP. */
305 } else {
306 set_switch(st->click_btn, true); /* headless --click SW1/SW2: press + hold. */
307 }
308 st->button_fired = true;
309 }
310 } else if (cfg->want_click && !st->click_was_tab && (board_periph_touch_reported() == 0U)) {
311 uint16_t cnx = (uint16_t)cfg->click_x;
312 uint16_t cny = (uint16_t)cfg->click_y;
313 unrotate_click((uint16_t)cfg->click_x,
314 (uint16_t)cfg->click_y,
315 st->panel_w,
316 st->panel_h,
317 cfg->rotate_deg,
318 &cnx,
319 &cny);
321 }
322}
323
344{
345 const emu_run_cfg_t* cfg = st->cfg;
346 if (priv_run_inner(cfg->uc, cfg->vtor_base, &st->run_pc, &st->err)) {
347 return k_loop_break;
348 }
349 if (emu_prof_stop_hit()) {
350 st->prof_stopped = true; /* RA8_EMU_STOP_PC reached -- end the profiled run. */
351 return k_loop_break;
352 }
353 /* AIRCR.SYSRESETREQ: latch a software-reset cause and warm reboot the
354 * firmware from its reset vector, then keep running. */
356 board_periph_reset_set_cause(false, true, false, false); /* software reset */
357 st->run_pc = warm_reboot(cfg->uc, cfg->elf, cfg->want_trace);
359 if (st->run_pc == 0U) {
360 return k_loop_break; /* reboot failed to reload the image -- end the run
361 */
362 }
363 return k_loop_continue;
364 }
365 return k_loop_next;
366}
367
385{
386 const emu_run_cfg_t* cfg = st->cfg;
387 /* Dual-core: step cpu1 interleaved with cpu0; a cpu1 fault just stops cpu1.
388 */
390 /* --record: dump the composite every k_record_every chunks as a numbered PPM.
391 */
392 if ((cfg->record_dir != nullptr) && (st->presentation->fd >= 0) &&
393 ((st->chunks % (uint32_t)k_record_every) == 0U)) {
394 const bool built = build_composite(cfg->uc, st->presentation, cfg->win_title);
395 enum : uint16_t {
396 k_rec_path_cap = 1024U,
397 };
398 char fpath[k_rec_path_cap];
399 (void)snprintf(fpath,
400 sizeof(fpath),
401 "%s/frame_%06u.ppm",
402 cfg->record_dir,
403 (unsigned)st->rec_frames);
404 if (built && (write_ppm(fpath, st->presentation) == 0)) {
405 st->rec_frames++;
406 }
407 }
408}
409
428{
429 const emu_run_cfg_t* cfg = st->cfg;
430 struct timespec ts_now = {};
431 (void)clock_gettime(CLOCK_MONOTONIC, &ts_now);
432 const uint64_t now_us = ((uint64_t)ts_now.tv_sec * (uint64_t)k_us_per_s) +
433 ((uint64_t)ts_now.tv_nsec / (uint64_t)k_ns_per_us);
434 if ((now_us - st->last_present_us) >= (uint64_t)k_view_frame_us) {
435 if (build_composite(cfg->uc, st->presentation, cfg->win_title)) {
437 st->last_present_us = now_us;
438 }
439 } else {
440 (void)usleep((useconds_t)k_view_yield_us);
441 }
442}
443
465{
466 uint16_t cx = 0U;
467 uint16_t cy = 0U;
468 if (board_view_poll_click(st->view, &cx, &cy)) {
469 const board_overlay_btn_t hit =
470 route_click(cx, cy, st->panel_w, st->panel_h, st->disp_w, st->cfg->rotate_deg);
472 st->held_btn = ((hit == k_board_overlay_btn_sw1) || (hit == k_board_overlay_btn_sw2))
473 ? hit
475 }
476 if (board_view_poll_release(st->view)) { /* mouse-up: release a held button + grab. */
478 set_switch(st->held_btn, false);
480 }
481 st->slider_grab = false;
482 }
483 uint16_t dx = 0U;
484 uint16_t dy = 0U;
485 if (board_view_poll_drag(st->view, &dx, &dy) && st->slider_grab) {
487 }
488 emu_view_wheel(board_view_poll_scroll(st->view)); /* wheel pages the scrollback. */
489 if ((st->chunks % (uint32_t)k_view_present_every) == 0U) {
491 }
492 if (board_view_pump(st->view)) {
493 st->closed = true;
494 return k_loop_break;
495 }
496 return k_loop_next;
497}
498
519{
520 const bool click_acted = (st->click_btn != k_board_overlay_btn_none)
521 ? st->button_fired
523 if (click_acted) {
524 st->settle_left =
525 (st->settle_left == 0U) ? st->guards.click_settle_chunks : (st->settle_left - 1U);
526 if (st->settle_left == 1U) {
527 return k_loop_break;
528 }
529 }
530 if (st->guards.wall_guard_on &&
531 (((double)(clock() - st->t0) / (double)CLOCKS_PER_SEC) >= st->guards.wall_s)) {
532 st->timed_out = true;
533 return k_loop_break;
534 }
535 return k_loop_next;
536}
537
557{
558 if (!((emu_prof_mode() == k_prof_insn) && (st->cfg->record_dir == nullptr) &&
559 (st->chunks >= st->guards.prof_idle_arm))) {
560 return false;
561 }
562 const uint64_t d = emu_prof_total_insns() - st->prof_idle_prev_i;
564 if (d < (uint64_t)st->guards.prof_idle_insns) {
565 st->prof_idle_run++;
566 if (st->prof_idle_run >= st->guards.prof_idle_need) {
567 st->prof_stopped = true;
568 return true;
569 }
570 } else {
571 st->prof_idle_run = 0U;
572 }
573 return false;
574}
575
596{
597 if (!((st->guards.idle_stop_chunks > 0U) && (st->cfg->record_dir == nullptr))) {
598 return false;
599 }
600 const uint64_t idle_sig = (uint64_t)emu_mmio_reads() + (uint64_t)emu_mmio_writes() +
601 (uint64_t)emu_exc_pendsv_takes() + (uint64_t)emu_exc_svc_takes() +
602 (uint64_t)board_periph_irq_total();
603 if (idle_sig == st->idle_sig_prev) {
604 st->idle_run++;
605 if (st->idle_run >= st->guards.idle_stop_chunks) {
606 st->idle_stopped = true;
607 return true;
608 }
609 } else {
610 st->idle_sig_prev = idle_sig;
611 st->idle_run = 0U;
612 }
613 return false;
614}
615
636{
637 const bool recording = (st->cfg->record_dir != nullptr);
638 if ((st->guards.usb_stop_settle > 0U) && !recording && board_usb_configured()) {
639 st->usb_stop_run++;
640 if (st->usb_stop_run >= st->guards.usb_stop_settle) {
641 st->usb_stopped = true;
642 return true;
643 }
644 }
645 if ((st->guards.usbh_stop_settle > 0U) && !recording && emu_usbh_done()) {
646 st->usbh_stop_run++;
647 if (st->usbh_stop_run >= st->guards.usbh_stop_settle) {
648 st->usb_stopped = true;
649 return true;
650 }
651 }
652 return false;
653}
654
675{
676 const char* const stop_on = st->guards.stop_on;
677 if (stop_on == nullptr) {
678 return false;
679 }
680 const char* const last_uart = board_periph_uart_last_line();
681 const char* const last_itm = board_console_line(k_board_console_ch_itm, 0U);
682 const char* const last_rtt = board_console_line(k_board_console_ch_rtt, 0U);
683 const bool hit = ((last_uart != nullptr) && (strstr(last_uart, stop_on) != nullptr)) ||
684 ((last_itm != nullptr) && (strstr(last_itm, stop_on) != nullptr)) ||
685 ((last_rtt != nullptr) && (strstr(last_rtt, stop_on) != nullptr));
686 if (hit) {
687 st->usb_stopped = true;
688 return true;
689 }
690 return false;
691}
692
712{
713 const emu_run_cfg_t* cfg = st->cfg;
714 if (cfg->stop_sym_addr == 0U) {
715 return false;
716 }
717 uint32_t sv = 0U;
718 if ((emu_mem_read(cfg->uc, (uint64_t)cfg->stop_sym_addr, &sv, sizeof(sv)) == UC_ERR_OK) &&
719 (sv >= cfg->stop_sym_thresh)) {
720 st->stop_sym_hit = true;
721 return true;
722 }
723 return false;
724}
725
744{
745 if (st->guards.wall_guard_on &&
746 (((double)(clock() - st->t0) / (double)CLOCKS_PER_SEC) >= st->guards.wall_s)) {
747 st->timed_out = true;
748 return true;
749 }
750 return false;
751}
752
781
800{
801 if (st->view != nullptr) {
802 return internal_run_loop_view(st);
803 }
804 if (st->cfg->want_click) {
806 }
808}
809
828{
829 for (; st->chunks < st->guards.max_chunks; st->chunks++) {
831 if (pro == k_loop_break) {
832 break;
833 }
834 if (pro == k_loop_continue) {
835 continue;
836 }
839 if (chunk == k_loop_break) {
840 break;
841 }
842 if (chunk == k_loop_continue) {
843 continue;
844 }
847 break;
848 }
849 }
850}
851
853{
854 run_loop_t st = {};
855 internal_run_loop_setup(cfg, &st);
857 priv_run_report(&st);
860 return priv_run_cleanup(&st);
861}
Multi-channel console log store backing the board view's tabbed console.
const char * board_console_line(board_console_ch_t ch, uint32_t back)
Fetch a retained line by age (0 = newest) from a channel.
@ k_board_console_ch_itm
CoreSight ITM/SWO trace ([itm]).
@ k_board_console_ch_count
Channel count (ring + tab array size).
@ k_board_console_ch_rtt
SEGGER RTT up-buffer 0 drain ([rtt]).
Host-side keystroke FIFO: window / CLI key source -> UART RX sink.
bool board_input_pop_key(char *out)
Pop the oldest buffered keystroke, if any.
Definition board_input.c:37
Virtual network peer for ra8_emulator – talks TCP/IP to the firmware.
void board_net_tick(void)
Advance the peer's state machine one tick (ARP -> ping -> TCP echo).
Definition board_net.c:753
Composite board-view renderer: panel framebuffer + a status sidebar.
board_overlay_btn_t board_overlay_hit_button(uint16_t x, uint16_t y, uint16_t panel_w)
Classify a composite-space click against the sidebar's on-screen buttons.
board_overlay_btn_t
On-screen sidebar control a click landed on.
@ k_board_overlay_btn_sw2
On-screen SW2 (P008) push-button.
@ k_board_overlay_btn_battery
Battery slider track: set SOC.
@ k_board_overlay_btn_batt_chg
Battery CHG button: toggle charge.
@ k_board_overlay_btn_none
Click did not land on a control.
@ k_board_overlay_btn_lowpower
CORE low-power toggle button.
@ k_board_overlay_btn_sw1
On-screen SW1 (P009) push-button.
bool board_overlay_hit_console_tab(uint16_t x, uint16_t y, uint16_t panel_w, uint32_t tab_count, uint32_t *out_idx)
Map a composite-space click on the console tab bar to a tab index.
Register-accurate peripheral-model framework for the board emulator.
void board_periph_tick(uc_engine *uc)
Advance every modelled timer by one emulation chunk and raise events.
void board_periph_sci_feed_rx(uint8_t channel, const uint8_t *data, uint32_t len)
Queue host->firmware bytes for a channel's receive path.
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.
const char * board_periph_uart_last_line(void)
The most recent complete line the firmware transmitted over any SCI.
uint8_t board_periph_sci_console_channel(void)
The SCI channel the EK-RA8D2 console (J-Link OB VCOM) uses.
uint32_t board_periph_irq_total(void)
Total NVIC interrupts the ICU has delivered in this run.
uint32_t board_periph_touch_reported(void)
Count of touch contacts the firmware has drained from the GT911 model.
bool board_periph_reset_take_request(bool *out_watchdog, bool *out_iwdt)
Consume a pending peripheral reboot request, if any (run-loop side).
void board_periph_touch_inject(uint16_t x, uint16_t y)
Arm a pending touch contact for the modelled GT911 device.
SD-card-over-SPI device model for ra8_emulator (attached to SPI_B).
USBFS controller model + a virtual USB host for the board emulator.
bool board_usb_configured(void)
Report whether enumeration reached the CONFIGURED state.
Definition board_usb.c:191
Minimal self-contained macOS window for the board emulator.
bool board_view_poll_click(board_view_t *view, uint16_t *x, uint16_t *y)
Report the most recent unprocessed left mouse-down, once.
bool board_view_poll_drag(board_view_t *view, uint16_t *x, uint16_t *y)
Report the current position of a held-button drag, once.
bool board_view_pump(board_view_t *view)
Drain pending UI events; report whether the window was closed.
void board_view_present(board_view_t *view, emu_presentation_workspace_t *presentation)
Snapshot an RGB565 fd surface and request a redraw.
board_view_t * board_view_open(board_view_storage_t *storage, uint16_t width_px, uint16_t height_px, const char *title)
Open a desktop window of the given pixel size.
bool board_view_poll_release(board_view_t *view)
Report whether the primary mouse button was released since the last poll.
int32_t board_view_poll_scroll(board_view_t *view)
Drain the accumulated console scroll-wheel notches since the last poll.
Emulator text-console surfaces: UART echo, ITM/SWO echo, escapes.
Second-core (cpu1, Cortex-M33) engine: release watch, boot, stepping.
void emu_cpu1_step(void)
Boot cpu1 on a pending release, then step it one interleave chunk.
Definition emu_cpu1.c:196
ELF32 image services for the board emulator (load / symbols / vectors).
uint32_t warm_reboot(uc_engine *uc, const emu_elf_source_t *elf, bool trace)
Warm-reboot the firmware: re-run from the reset vector in place.
Shared Unicorn engine access utilities for the board emulator.
Cortex-M exception model constants and interfaces for ra8_emulator.
void emu_exc_arm_systick(void)
Pend the periodic SysTick for this outer chunk.
Definition emu_exc.c:926
void dwt_cyccnt_advance(uc_engine *uc)
Advance the DWT cycle counter by one outer chunk's worth of cycles.
uint32_t emu_exc_pendsv_takes(void)
PendSV exceptions taken this run (report + idle signature).
Definition emu_exc.c:973
void emu_exc_clear_reboot_request(void)
Clear the latched warm-reboot request (after performing it).
bool emu_exc_reboot_requested(void)
Whether AIRCR.SYSRESETREQ requested a warm reboot.
uint32_t emu_exc_svc_takes(void)
SVCall exceptions taken this run (report + idle signature).
Definition emu_exc.c:979
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.
Shared aliased-memory backing and Unicorn memory-map bindings.
uc_err emu_mem_read(uc_engine *uc, uint64_t address, void *bytes, size_t count)
Read guest memory through the central access seam.
Sparse MMIO model of the Renesas peripheral space.
uint32_t emu_mmio_writes(void)
Total peripheral MMIO writes this run (monotonic).
Definition emu_mmio.c:228
uint32_t emu_mmio_reads(void)
Total peripheral MMIO reads this run (monotonic).
Definition emu_mmio.c:222
Armv8-M MPU enforcement model for ra8_emulator.
Firmware profiler (RA8_EMU_PROFILE): sampling, hooks, reports.
prof_mode_t emu_prof_mode(void)
The latched profiler mode.
Definition emu_prof.c:949
@ k_prof_insn
=full/=insn: exact per-instruction + calls.
Definition emu_prof.h:53
@ k_prof_wall
=1: cheap chunk-start wall-time sampler.
Definition emu_prof.h:52
void prof_add(uint32_t pc, double dt)
Attribute wall seconds to the function owning pc (wall mode).
Definition emu_prof.c:210
bool emu_prof_stop_hit(void)
Whether the RA8_EMU_STOP_PC address was reached.
Definition emu_prof.c:967
double board_now_s(void)
Monotonic wall-clock seconds.
Definition emu_prof.c:31
uint64_t emu_prof_total_insns(void)
Total instructions retired under the per-instruction hook.
Definition emu_prof.c:955
static void internal_run_setup_geometry(const emu_run_cfg_t *cfg, run_loop_t *st)
Derive the presentation geometry from the panel size and rotation.
Definition emu_run.c:83
loop_action_t
Loop-control verdict a per-phase run-loop helper hands back.
Definition emu_run.c:60
@ k_loop_break
Leave the outer loop (stop condition / fault).
Definition emu_run.c:63
@ k_loop_continue
Restart the outer loop (reboot / tail-chain).
Definition emu_run.c:62
@ k_loop_next
Fall through to the next phase in the body.
Definition emu_run.c:61
static void internal_run_loop_tick_inputs(run_loop_t *st)
Arm the tick, advance time/peripherals, drain input, replay the click.
Definition emu_run.c:277
static loop_action_t internal_run_loop_click_tail(run_loop_t *st)
Run the bounded post-click tail and the CPU-time wall guard (headless).
Definition emu_run.c:518
static loop_action_t internal_run_loop_present_and_stops(run_loop_t *st)
Dispatch the per-chunk output / stop phase by run mode.
Definition emu_run.c:799
static bool internal_run_stop_idle(run_loop_t *st)
Steady-state idle early-stop (RA8_EMU_IDLE_STOP).
Definition emu_run.c:595
static bool internal_run_stop_usb(run_loop_t *st)
USB device- and host-mode enumeration early-stops.
Definition emu_run.c:635
static bool internal_run_stop_wall(run_loop_t *st)
CPU-time wall-clock safety guard (headless plain run).
Definition emu_run.c:743
static void internal_run_loop_setup(const emu_run_cfg_t *cfg, run_loop_t *st)
Populate the run state from the config before the chunk loop.
Definition emu_run.c:177
static void internal_run_open_view(const emu_run_cfg_t *cfg, run_loop_t *st)
Open the live window over the owned raw-fd surface when requested.
Definition emu_run.c:111
static bool internal_run_stop_sym(run_loop_t *st)
–stop-sym watched-global early-stop.
Definition emu_run.c:711
static void internal_run_loop(run_loop_t *st)
Drive the chunked run loop to a stop condition.
Definition emu_run.c:827
int emu_run_and_report(const emu_run_cfg_t *cfg)
Run the firmware to a stop condition, print the report, map the exit code.
Definition emu_run.c:852
static bool internal_run_stop_banner(run_loop_t *st)
Generic console-banner early-stop (RA8_EMU_STOP_ON).
Definition emu_run.c:674
static loop_action_t internal_run_loop_headless(run_loop_t *st)
Evaluate every headless plain-run early-stop in order.
Definition emu_run.c:773
static loop_action_t internal_run_loop_prologue(run_loop_t *st)
Run-loop prologue: wall-profiler charge, telemetry, warm reboots.
Definition emu_run.c:213
static loop_action_t internal_run_loop_view(run_loop_t *st)
Handle live-window mouse input, presenting, and the close request.
Definition emu_run.c:464
static void internal_run_classify_click(const emu_run_cfg_t *cfg, run_loop_t *st)
Classify a headless –click into a tab / button / panel target once.
Definition emu_run.c:139
static bool internal_run_stop_prof_idle(run_loop_t *st)
Profiler compute-idle early-stop (insn mode, build-stable).
Definition emu_run.c:556
static loop_action_t internal_run_loop_run_chunk(run_loop_t *st)
Run one chunk via priv_run_inner and service its post-chunk resets.
Definition emu_run.c:343
static void internal_run_loop_record(run_loop_t *st)
Step cpu1 and dump a –record frame at the recording cadence.
Definition emu_run.c:384
static void internal_run_view_maybe_present(run_loop_t *st)
Composite and present the live window at the ~60 Hz present cadence.
Definition emu_run.c:427
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).
Shared run-loop state + cross-TU run helpers (ra8_emulator internal).
void priv_run_report(const run_loop_t *st)
Print the run-end report (stop summary, verdict, –dump-sym probes).
void priv_run_write_outputs(const run_loop_t *st)
Write the –ppm snapshot and the –record summary line.
int priv_run_cleanup(const run_loop_t *st)
Save the SD image, close owned descriptors + engine, map the exit code.
bool priv_run_inner(uc_engine *uc, uint32_t vtor_base, uint32_t *run_pc_io, uc_err *err_out)
Run one outer chunk's inner exception-resolve loop.
void priv_run_hold_view(const run_loop_t *st)
Hold the live window on the final frame until the user closes it.
Armv8.1-M instruction-emulation seams (M85 ops on Unicorn's M33).
Virtual USB host-mode devices behind the ra8_usb_host_* / hmsc seams.
bool emu_usbh_done(void)
Whether the virtual host-mode device served its final request.
Board-view presentation: frames, composition, input routing, panels.
void apply_battery_click(board_overlay_btn_t btn, uint16_t cx, uint16_t disp_w)
Apply a POWER-section click to the fuel-gauge / core model.
Definition emu_view.c:289
void set_switch(board_overlay_btn_t btn, bool pressed)
Toggle a user switch's pressed level (active-low) for an on-screen button.
Definition emu_view.c:266
void emu_view_select_console_tab(uint32_t tab_idx)
Switch the visible console channel to tab_idx (tab-bar click).
Definition emu_view.c:615
void emu_view_publish(uint32_t pc, uint32_t chunks)
Publish the run-loop telemetry the board view shows.
Definition emu_view.c:584
@ k_view_yield_us
Yield this long when a present is skipped.
Definition emu_view.h:49
@ k_record_every
Chunks between recorded frames (1000/20).
Definition emu_view.h:59
@ k_view_frame_us
Min wall-us between live presents (~60 Hz).
Definition emu_view.h:48
@ k_view_present_every
Present the frame every Nth chunk.
Definition emu_view.h:45
@ k_ns_per_us
Nanoseconds per microsecond.
Definition emu_view.h:51
@ k_us_per_s
Microseconds per second.
Definition emu_view.h:50
@ k_reboot_settle
Chunks to run before a scheduled –reboot.
Definition emu_view.h:53
void emu_view_wheel(int32_t notches)
Page the console scrollback by mouse-wheel notches.
Definition emu_view.c:598
int write_ppm(const char *path, const emu_presentation_workspace_t *presentation)
Write an RGB565 frame to a binary PPM (P6) for headless inspection.
bool build_composite(uc_engine *uc, emu_presentation_workspace_t *presentation, const char *app_name)
Stream the panel and status sidebar into a raw-fd surface.
Definition emu_view.c:371
void unrotate_click(uint16_t cx, uint16_t cy, uint16_t panel_w, uint16_t panel_h, uint32_t deg, uint16_t *nx, uint16_t *ny)
Map a click in the rotated displayed panel back to native panel coords.
Definition emu_view.c:242
board_overlay_btn_t route_click(uint16_t cx, uint16_t cy, uint16_t panel_w, uint16_t panel_h, uint16_t disp_w, uint32_t rotate_deg)
Route a composite-space click to the right input model.
Definition emu_view.c:326
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
char * strstr(const char *haystack, const char *needle)
Locate substring in string.
uint16_t panel_height
Native panel height.
uint16_t composite_width
Display plus sidebar width.
int fd
Owned unlinked descriptor, or -1.
uint16_t display_height
Rotation-adjusted panel height.
uint16_t composite_height
Display/sidebar maximum height.
uint16_t display_width
Rotation-adjusted panel width.
uint16_t panel_width
Native panel width.
Everything setup hands the run loop: engine, image, CLI products.
Definition emu_run.h:122
int click_y
–click row (composite pixels).
Definition emu_run.h:131
int click_x
–click column (composite pixels).
Definition emu_run.h:130
const char * record_dir
–record directory (NULL when unused).
Definition emu_run.h:133
bool want_click
–click armed.
Definition emu_run.h:129
const char * win_title
Window / sidebar caption.
Definition emu_run.h:145
bool want_view
–view (live window requested).
Definition emu_run.h:128
emu_elf_source_t * elf
Open caller-owned firmware source.
Definition emu_run.h:124
uint32_t initial_pc
Reset-vector PC (Thumb bit set).
Definition emu_run.h:125
bool want_trace
–trace (forwarded to warm reboots).
Definition emu_run.h:127
uint32_t stop_sym_thresh
–stop-sym threshold value.
Definition emu_run.h:139
uc_engine * uc
The prepared cpu0 engine.
Definition emu_run.h:123
uint32_t rotate_deg
–rotate display rotation.
Definition emu_run.h:135
uint32_t stop_sym_addr
–stop-sym resolved address (0 = off).
Definition emu_run.h:138
int reboot_count
–reboot N scheduled warm reboots.
Definition emu_run.h:136
uint32_t vtor_base
VTOR fallback (the MRAM vector base).
Definition emu_run.h:126
emu_presentation_workspace_t * presentation
Owned streamed frame surface.
Definition emu_run.h:146
uint32_t max_chunks
Outer-chunk budget.
Definition emu_run.h:166
bool wall_guard_on
false: WALL_S=0 disabled the guard.
Definition emu_run.h:168
uint32_t prof_idle_arm
Chunks before the profiler stop arms.
Definition emu_run.h:175
const char * stop_on
Console-banner stop substring (or NULL).
Definition emu_run.h:172
uint32_t click_settle_chunks
Post-click drain window (chunks).
Definition emu_run.h:165
uint32_t idle_stop_chunks
Idle steady-state stop (0 = off).
Definition emu_run.h:169
uint32_t prof_idle_insns
Profiler idle chunk threshold.
Definition emu_run.h:173
uint32_t usbh_stop_settle
USB host-mode early-stop settle.
Definition emu_run.h:171
uint32_t prof_idle_need
Consecutive idle chunks that stop.
Definition emu_run.h:174
double wall_s
CPU-time guard bound, seconds.
Definition emu_run.h:167
uint32_t usb_stop_settle
USB device-mode early-stop settle.
Definition emu_run.h:170
The whole run's mutable state, threaded through the phase helpers.
bool timed_out
Wall-clock guard fired.
board_overlay_btn_t held_btn
SW held down (released on up).
clock_t t0
CPU-time origin for the guard.
board_view_storage_t view_storage
Caller-owned live-view handle storage.
emu_presentation_workspace_t * presentation
Owned raw-fd presentation surface.
double prof_prev_t
Start time of the prior chunk.
bool usb_stopped
USB / banner early stop fired.
uint16_t comp_h
Composite (panel + sidebar) height.
uint32_t usb_stop_run
USB device settle countup.
uint32_t last_boot_chunk
Chunk of the last (re)boot.
int reboot_count
–reboot warm reboots remaining.
board_overlay_btn_t click_btn
Classified –click target button.
uint16_t panel_w
Firmware render width in pixels.
bool closed
Live window was closed.
board_view_t * view
Live window (NULL when headless).
uint32_t prof_prev_pc
PC charged by the wall profiler.
run_guards_t guards
Env-tunable budgets + stop conditions.
uint32_t rec_frames
–record frames written.
bool slider_grab
Battery slider grabbed by a drag.
uint32_t settle_left
Post-click drain countdown.
uint32_t idle_run
Consecutive steady-idle chunks.
uint64_t prof_idle_prev_i
Prior total insns (profiler).
bool prof_stopped
Profiler stop fired.
const emu_run_cfg_t * cfg
Setup products (engine, image, CLI knobs).
uint16_t panel_h
Firmware render height in pixels.
uint64_t idle_sig_prev
Prior idle-signature sum.
uint32_t run_pc
Current resume PC.
uint16_t comp_w
Composite (panel + sidebar) width.
bool idle_stopped
Idle steady-state stop fired.
uint64_t last_present_us
wall-us of the last live present.
bool button_fired
Headless click button fired once.
bool stop_sym_hit
–stop-sym threshold reached.
uint32_t prof_idle_run
Consecutive profiler-idle chunks.
uc_err err
Latest uc_emu_start status.
uint32_t chunks
Outer chunks executed so far.
uint16_t disp_w
Displayed width (rotation-swapped).
bool click_was_tab
–click landed on a console tab.
uint16_t disp_h
Displayed height (rotation-swapped).
uint32_t usbh_stop_run
USB host settle countup.