|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
RA8D2 board emulator – boot a real .elf on a CPU emulator, with ticks. More...
#include <capstone/capstone.h>#include <ctype.h>#include <stdalign.h>#include <stddef.h>#include <stdint.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/stat.h>#include <time.h>#include <unicorn/unicorn.h>#include <unistd.h>#include "board_console.h"#include "board_input.h"#include "board_net.h"#include "board_overlay.h"#include "board_periph.h"#include "board_periph_eink.h"#include "board_periph_modem.h"#include "board_periph_sd.h"#include "board_usb.h"#include "board_usb_host.h"#include "board_view.h"#include "emu_args.h"#include "emu_console.h"#include "emu_cpu1.h"#include "emu_elf.h"#include "emu_elf_source_internal.h"#include "emu_engine.h"#include "emu_exc.h"#include "emu_host_io_internal.h"#include "emu_memmap.h"#include "emu_mmio.h"#include "emu_mpu.h"#include "emu_prof.h"#include "emu_run.h"#include "emu_seams.h"#include "emu_trace.h"#include "emu_tz.h"#include "emu_usbh_seam.h"#include "emu_view.h"Go to the source code of this file.
Functions | |
| static RA8_INTERNAL bool | internal_main_open_memory (emu_memmap_workspace_t *memory) |
| Open the shared aliased-memory backing before engine mutation. | |
| static RA8_INTERNAL const char * | internal_main_apply_panel (const emu_args_t *args, uint16_t *view_w, uint16_t *view_h) |
| Apply a –panel descriptor to the window size and title. | |
| static RA8_INTERNAL bool | internal_main_open_presentation (const emu_args_t *args, uint16_t view_w, uint16_t view_h, emu_presentation_workspace_t *workspace) |
| Create the exact fd-backed surface before engine/output mutation. | |
| static RA8_INTERNAL int | internal_main_open_engine (uc_engine **uc_out, emu_memmap_workspace_t *memory) |
| Open the Unicorn engine, set the memory map, seed hardwired SCS regs. | |
| static RA8_INTERNAL void | internal_main_arm_touch_seq (const char *touch_seq_str) |
| Arm the modelled GT911 injection FIFO from a –touch-seq string. | |
| static RA8_INTERNAL void | internal_main_apply_button_battery (const emu_args_t *args) |
| Apply –button and –battery / –charge before the firmware boots. | |
| static RA8_INTERNAL void | internal_main_feed_inputs (const emu_args_t *args) |
| Queue the –input / –keys / –usb-in injected byte streams. | |
| static RA8_INTERNAL void | internal_main_bringup_peripherals (const emu_args_t *args) |
| Bring up the peripheral models and apply pre-boot input state. | |
| static RA8_INTERNAL int | internal_main_load_primary (uc_engine *uc, const char *elf_path, emu_elf_source_t *elf_out) |
| Read + load the primary firmware ELF and print the load banner. | |
| static RA8_INTERNAL int | internal_main_load_ns (uc_engine *uc, const char *ns_elf_path, emu_elf_source_t *elf, emu_elf_source_t *ns_out) |
| Read + load the optional –ns second (Non-Secure) image. | |
| static RA8_INTERNAL void | internal_main_resolve_symbols (const emu_elf_source_t *elf, const emu_elf_source_t *ns_elf, const emu_args_t *args, uint32_t *dump_sym_addrs, uint32_t *stop_sym_addr) |
| Resolve the –dump-sym globals and the –stop-sym watch address. | |
| static RA8_INTERNAL uint32_t | internal_main_reset_vector (uc_engine *uc) |
| Read the reset vector, set the initial CPU registers, print the banner. | |
| static RA8_INTERNAL void | internal_main_install_core_seams (uc_engine *uc, const emu_elf_source_t *elf) |
| Install the core execution, exception, console, TrustZone + MPU seams. | |
| static RA8_INTERNAL void | internal_main_install_run_seams (uc_engine *uc, const emu_elf_source_t *elf, const emu_args_t *args, emu_memmap_workspace_t *memory) |
| Install the USB, symbol-trace, ISA-emulation and profiler seams. | |
| static RA8_INTERNAL emu_run_cfg_t | internal_main_build_run_cfg (const emu_args_t *args, uc_engine *uc, emu_elf_source_t *elf, uint32_t pc, uint32_t vtor_base, uint16_t view_w, uint16_t view_h, const char *win_title, const uint32_t *dump_sym_addrs, uint32_t stop_sym_addr, emu_presentation_workspace_t *presentation, emu_memmap_workspace_t *memory) |
| Build the run configuration handed to emu_run_and_report(). | |
| static RA8_INTERNAL int | internal_main_run_loaded (const emu_args_t *args, emu_memmap_workspace_t *memory, emu_presentation_workspace_t *presentation, uc_engine *uc, emu_elf_source_t *elf, emu_elf_source_t *ns_elf, uint16_t view_w, uint16_t view_h, const char *win_title) |
| Resolve loaded firmware state, install seams, and run the emulator. | |
| static RA8_INTERNAL int | internal_main_load_images (uc_engine *uc, const emu_args_t *args, emu_memmap_workspace_t *memory, emu_presentation_workspace_t *presentation, emu_elf_source_t *elf, emu_elf_source_t *ns_elf) |
| Load the primary and optional non-secure images into the engine. | |
| int | main (int argc, char **argv) |
Variables | |
| static uint8_t | s_main_presentation_scratch [k_emu_presentation_max_scratch_bytes] |
| Explicit bounded presentation scratch owned by the process root. | |
RA8D2 board emulator – boot a real .elf on a CPU emulator, with ticks.
Loads an EK-RA8D2 firmware ELF into an emulated Cortex-M memory map (Unicorn, QEMU's CPU core as a library) and boots it from the vector table, with the RA8D2 peripheral space modelled as logged MMIO.
Feasibility (proven): Unicorn 2.x tops out at Cortex-M33 (Armv8-M) while the RA8D2 is M85 (Armv8.1-M), yet the GCC-built firmware executes on the M33 core – no v8.1-M-only opcode (e.g. low-overhead loops) is emitted on the boot path. The invalid-instruction trap below still reports exactly where and what if that ever changes.
Time: bare-metal delays here are SysTick-driven (ra8_time enables SysTick with TICKINT and counts exceptions). Nothing advances time on a plain memory model, so the run loop is chunked and, between chunks, cooperatively invokes the firmware's installed SysTick_Handler as a function – its tick-counter memory write persists while the interrupted context's registers are restored, which is precisely a real SysTick IRQ's observable effect. This carries the firmware past ra8_delay_ms so it reaches its main loop (e.g. driving the GLCDC), instead of spinning forever on a tick that never increments.
ra8_emulator <firmware.elf>
Definition in file main.c.
|
static |
Apply –button and –battery / –charge before the firmware boots.
–button holds a user switch pressed (active-low) so a button-polling app takes its pressed path (SW1 = P009, SW2 = P008); the battery flags set the MAX17048 fuel-gauge state-of-charge and charging status.
| [in] | args | The parsed CLI args (button / battery fields). |
args is non-NULL. Definition at line 299 of file main.c.
References emu_args_t::battery_charging, emu_args_t::battery_opt, emu_args_t::battery_soc, board_periph_battery_get(), board_periph_battery_set(), board_periph_gpio_set_input(), emu_args_t::button_press, k_emu_sw1_pin, k_emu_sw2_pin, k_emu_sw_port, pin, priv_emu_io_errf(), and RA8_INTERNAL.
Referenced by internal_main_bringup_peripherals().
|
static |
Apply a –panel descriptor to the window size and title.
A –panel descriptor sizes the window to that display (so the emulator can present any panel, not just 1024x600); an explicit –size still wins. Returns the window caption – the panel name when named, else the default.
| [in] | args | The parsed CLI args (–panel path + –size flag). |
| [in,out] | view_w | In: default width; out: panel width when adopted. |
| [in,out] | view_h | In: default height; out: panel height when adopted. |
| ra8_emulator | No named panel was loaded. |
args, view_w and view_h are non-NULL. view_w / view_h hold the default or –size dimensions. view_w / view_h reflect the panel size iff adopted. Definition at line 130 of file main.c.
References load_panel(), emu_args_t::panel_path, s_panel, and emu_args_t::size_set.
Referenced by main().
|
static |
Arm the modelled GT911 injection FIFO from a –touch-seq string.
Parses "x0:y0,x1:y1,..." (bounded per NASA Rule 2) and pushes each valid raw point into the GT911 model, which then serves one queued point per drained frame through the genuine ra8_touch_read decode (a headless multi-tap flow). Must run AFTER board_periph_init so the per-block reset does not clear it.
| [in] | touch_seq_str | The –touch-seq spec, or NULL when unset. |
touch_seq_str is a valid string or NULL. < Bounded pair-parse iterations (NASA R2).
Definition at line 249 of file main.c.
References board_periph_touch_seq_push(), board_periph_touch_seq_reset(), k_strtol_base10, priv_emu_io_errf(), and RA8_INTERNAL.
Referenced by internal_main_bringup_peripherals().
|
static |
Bring up the peripheral models and apply pre-boot input state.
Resets the peripheral-model framework, arms the –touch-seq FIFO, selects the emulated part, wires the USBHS-loop / external-host bridge, brings up the network model and console TX sink, then applies the button / battery / injected-input options – all before the firmware boots.
| [in] | args | The parsed CLI args. |
args is non-NULL. Definition at line 380 of file main.c.
References board_net_init(), board_periph_init(), board_periph_sci_set_tx_sink(), board_periph_set_device(), board_periph_set_usbhs_loop(), board_usb_set_external_host(), console_tx_sink(), emu_args_t::emu_device, internal_main_apply_button_battery(), internal_main_arm_touch_seq(), internal_main_feed_inputs(), RA8_INTERNAL, emu_args_t::touch_seq_str, emu_args_t::usbhs_loop, and emu_args_t::want_trace.
Referenced by main().
|
static |
Build the run configuration handed to emu_run_and_report().
Bundles the engine, image, resolved reset PC / vector base, the output-mode CLI knobs and the resolved symbol probes into the read-only emu_run_cfg_t. The dump_sym_addrs pointer aliases the caller's array, which must outlive the run.
| [in] | args | The parsed CLI args. |
| [in] | uc | The prepared engine. |
| [in] | elf | The run-long open ELF source. |
| [in] | pc | The initial (Thumb) PC. |
| [in] | vtor_base | The MRAM vector-table base. |
| [in] | view_w | The panel width. |
| [in] | view_h | The panel height. |
| [in] | win_title | The window / sidebar caption. |
| [in] | dump_sym_addrs | The resolved –dump-sym addresses (caller-owned). |
| [in] | stop_sym_addr | The resolved –stop-sym address (0 = off). |
| [in,out] | presentation | Open fd-backed presentation surface. |
| [in,out] | memory | Open authoritative aliased-memory backing. |
| (cfg) | Every field mirrors its argument / CLI source. |
args and uc are non-NULL. Definition at line 701 of file main.c.
References emu_args_t::click_x, emu_args_t::click_y, emu_args_t::dump_sym_n, emu_args_t::dump_sym_names, emu_args_t::ppm_path, emu_args_t::reboot_count, emu_args_t::record_dir, emu_args_t::record_secs, emu_args_t::rotate_deg, emu_args_t::save_sd_path, emu_args_t::stop_sym_thresh, emu_args_t::want_click, emu_args_t::want_trace, and emu_args_t::want_view.
Referenced by internal_main_run_loaded().
|
static |
Queue the –input / –keys / –usb-in injected byte streams.
–input feeds the console UART RX (SCI8); –keys pushes through the SAME keystroke FIFO the live window feeds (a headless keyboard test); –usb-in queues bytes for the virtual host to push over the CDC bulk OUT pipe (echoed back on bulk IN). Each decodes escape sequences first.
| [in] | args | The parsed CLI args (input string fields). |
args is non-NULL. Definition at line 336 of file main.c.
References board_input_push_key(), board_periph_sci_console_channel(), board_periph_sci_feed_rx(), board_usb_feed_bulk_in(), decode_escapes(), emu_args_t::input_str, k_uart_line_max, emu_args_t::keys_str, priv_emu_io_errf(), RA8_INTERNAL, and emu_args_t::usb_in_str.
Referenced by internal_main_bringup_peripherals().
|
static |
Install the core execution, exception, console, TrustZone + MPU seams.
Arms the invalid-instruction + long-shift/MVE decode seams' core, the Cortex-M exception entry/return, the ITM/console echo, the TrustZone S->NS BLXNS world switch (armed only for a secure-boot image), the SCB/NVIC model and the MPU model.
| [in,out] | uc | The engine. |
| [in] | elf | The open primary ELF source (symbol tables). |
uc is a ready engine and elf remains open. Definition at line 607 of file main.c.
References emu_console_install(), emu_exc_install_core(), emu_exc_install_scb_nvic(), emu_insn_seams_install(), emu_mpu_install(), emu_tz_install(), and RA8_INTERNAL.
Referenced by internal_main_run_loaded().
|
static |
Install the USB, symbol-trace, ISA-emulation and profiler seams.
The virtual USB host-mode device is skipped under –usbhs-loop (the real ra8_usb_host_* must drive the modelled USBHS controller); the register-level host model is allowed only for an unseamed, non-loop firmware. Arms –trace-sym hooks, the M85-only long-shift/MVE seams (gated by –primary-core), the div-0 UsageFault sites, –fast-sd, the profiler and the cpu1 engine.
| [in,out] | uc | The engine. |
| [in] | elf | The open primary ELF source (symbol tables). |
| [in] | args | The parsed CLI args (usbhs-loop / trace-sym). |
| [in,out] | memory | Open authoritative backing shared with CPU1. |
uc is a ready engine and elf remains open. Definition at line 644 of file main.c.
References board_usb_host_set_allowed(), div0_seam_install(), emu_cpu1_init(), emu_primary_core(), emu_prof_install(), fast_sd_seam_install(), k_core_m85, long_shift_seam_install(), prof_load(), RA8_INTERNAL, sym_trace_install(), emu_args_t::trace_sym_n, emu_args_t::trace_sym_names, usbh_seam_install(), and emu_args_t::usbhs_loop.
Referenced by internal_main_run_loaded().
|
static |
Load the primary and optional non-secure images into the engine.
Loads the primary ELF, then the optional non-secure ELF, and unwinds the whole open session – engine, memory map, presentation – on either failure so the caller only has to propagate the status.
| [in,out] | uc | Active Unicorn engine receiving both images. |
| [in] | args | Parsed command line naming the image paths. |
| [in,out] | memory | Open emulated memory map, released on failure. |
| [in,out] | presentation | Open presentation workspace, released on failure. |
| [out] | elf | Receives the loaded primary ELF source. |
| [out] | ns_elf | Receives the loaded non-secure ELF source, if any. |
| 0 | Both requested images loaded and the session stays open. |
| 1 | A load failed; every session resource has been released. |
uc, memory and presentation are open. elf and ns_elf are initialised with fd set to -1. Definition at line 824 of file main.c.
References emu_args_t::elf_path, emu_memmap_close(), emu_memmap_detach(), emu_presentation_close(), internal_main_load_ns(), internal_main_load_primary(), emu_args_t::ns_elf_path, priv_emu_elf_source_close(), and RA8_INTERNAL.
Referenced by main().
|
static |
Read + load the optional –ns second (Non-Secure) image.
Loads the Non-Secure image of a two-image TrustZone app at its LMA so the Secure boot's NS-image copy + BLXNS land on it, and records its actual vector base for the world switch. An open / load failure closes the primary ELF source and fails. A no-op when –ns is unset (ns_out stays closed).
| [in] | uc | The engine to load into. |
| [in] | ns_elf_path | The –ns path, or NULL when unset. |
| [in] | elf | The primary source (closed on this path's failure). |
| [out] | ns_out | Receives the open NS source, or stays closed. |
| 0 | The NS image loaded, or –ns was not requested. |
| 1 | The –ns file could not be read or loaded (message printed). |
uc is a ready engine; the out params are non-NULL. elf is the loaded primary image. ns_out is open when requested and the vector base is set. elf is closed. Definition at line 466 of file main.c.
References elf_vector_base(), emu_tz_ns_vector_base(), emu_tz_set_ns_vector_base(), k_emu_elf_io_ok, emu_elf_source_t::length, load_elf(), priv_emu_elf_source_close(), priv_emu_elf_source_open(), priv_emu_io_errf(), RA8_INTERNAL, and emu_elf_io_result_t::status.
Referenced by internal_main_load_images().
|
static |
Read + load the primary firmware ELF and print the load banner.
Opens the ELF file, prints the load + device + primary-core banner, and streams its PT_LOAD segments into Unicorn memory. The open source is returned to the caller and kept alive for symbol resolution + warm reboots.
| [in] | uc | The engine to load into. |
| [in] | elf_path | The firmware ELF path. |
| [out] | elf_out | Receives the independently owned source on success. |
| 0 | The image is loaded and elf_out is open. |
| 1 | The file could not be read or loaded (message printed). |
uc is a ready engine; the out params are non-NULL. elf_path is a valid path. Definition at line 418 of file main.c.
References board_periph_device(), emu_low_power(), emu_primary_core(), k_board_device_ra8p1, k_core_m33, k_emu_elf_io_ok, emu_elf_source_t::length, load_elf(), priv_emu_elf_source_close(), priv_emu_elf_source_open(), priv_emu_io_errf(), and emu_elf_io_result_t::status.
Referenced by internal_main_load_images().
|
static |
Open the Unicorn engine, set the memory map, seed hardwired SCS regs.
Opens an Armv8-M (Thumb, M-class) engine on the closest emulated core to the M85 (Cortex-M33), lays down the RA8D2 memory map, and hardwires MPU_TYPE.DREGION to the M85's 8 data regions so ra8_mpu_configure validates (ra8_emulator does not enforce MPU permissions; the app takes its no-trap host path).
| [out] | uc_out | Receives the opened engine on success. |
| [in,out] | memory | Open authoritative backing to bind. |
| 0 | The engine, memory map and seeds are ready. |
| 1 | uc_open or the memory-map init failed (message printed). |
uc_out is non-NULL. *uc_out. *uc_out is a ready engine with the RA8D2 map. *uc_out is unchanged or NULL. Definition at line 209 of file main.c.
References emu_memmap_attach(), k_emu_memmap_ok, k_mpu_type, k_mpu_type_seed, priv_emu_io_errf(), RA8_INTERNAL, and wr32().
Referenced by main().
|
static |
Open the shared aliased-memory backing before engine mutation.
Acquires the three host apertures the Secure and Non-secure views of SRAM, SDRAM and OSPI share; this step is contained within the main model and uses bounded caller or module-owned storage.
| [in,out] | memory | Memory state or storage updated in place by the operation. |
| true | The main open memory condition holds or completed successfully; false otherwise. |
Definition at line 96 of file main.c.
References emu_memmap_open(), k_emu_memmap_ok, emu_memmap_result_t::logical_backing_bytes, emu_memmap_result_t::os_error, priv_emu_io_errf(), RA8_INTERNAL, and emu_memmap_result_t::status.
Referenced by main().
|
static |
Create the exact fd-backed surface before engine/output mutation.
Create the exact fd-backed surface before engine/output mutation; this step is contained within the main model and uses bounded caller or module-owned storage.
| [in] | args | Args input used by the operation. |
| [in] | view_w | View w input used by the operation. |
| [in] | view_h | View h input used by the operation. |
| [in,out] | workspace | Caller-owned workspace used by the operation. |
| true | The main open presentation condition holds or completed successfully; false otherwise. |
Definition at line 158 of file main.c.
References emu_presentation_open(), k_emu_presentation_ok, emu_presentation_result_t::os_error, emu_args_t::ppm_path, priv_emu_io_errf(), RA8_INTERNAL, emu_args_t::record_dir, emu_presentation_result_t::required_scratch_bytes, emu_presentation_result_t::required_surface_bytes, emu_args_t::rotate_deg, s_main_presentation_scratch, emu_presentation_result_t::status, emu_presentation_result_t::supplied_scratch_bytes, emu_args_t::want_click, and emu_args_t::want_view.
Referenced by main().
|
static |
Read the reset vector, set the initial CPU registers, print the banner.
Cortex-M reset: SP = vectors[0], PC = vectors[1] (Thumb). Sets SP / PC / xPSR.T so Unicorn enters Thumb decoding, and prints the reset banner.
| [in,out] | uc | The engine (memory read, registers written). |
| (PC) | vectors[1] | 1 from the MRAM vector table. |
uc is a ready engine with the vector table in MRAM. Definition at line 566 of file main.c.
References emu_mem_read(), emu_memmap_mram_base(), k_run_chunk_insns, k_run_max_chunks, k_run_wall_s, k_xpsr_t_bit, priv_emu_io_errf(), and RA8_INTERNAL.
Referenced by internal_main_run_loaded().
|
static |
Resolve the –dump-sym globals and the –stop-sym watch address.
Resolves each probe to a memory address while the ELF sources are still open (the software analog of the JLink memprobe HIL mode). A two-image app's probe counters live in the NS image, so a miss in the primary table falls through to the –ns table; an unresolved name is reported.
| [in] | elf | The open primary ELF source. |
| [in] | ns_elf | The open NS source, or a closed source. |
| [in] | args | The parsed CLI args (probe names). |
| [out] | dump_sym_addrs | Receives the resolved –dump-sym addresses. |
| [out] | stop_sym_addr | Receives the resolved –stop-sym address (0 = off). |
dump_sym_addrs has room for args->dump_sym_n entries. *stop_sym_addr is the watch address or 0. Definition at line 520 of file main.c.
References emu_args_t::dump_sym_n, emu_args_t::dump_sym_names, elf_sym_addr(), emu_elf_source_t::fd, priv_emu_io_errf(), RA8_INTERNAL, and emu_args_t::stop_sym_name.
Referenced by internal_main_run_loaded().
|
static |
Resolve loaded firmware state, install seams, and run the emulator.
Resolves reporting symbols while both ELF descriptors remain live, closes the optional non-secure source, applies TrustZone patches, installs core/run seams, and transfers the assembled run configuration to the loop.
| [in] | args | Parsed command-line configuration for this run. |
| [in,out] | memory | Authoritative memory workspace owned by the session. |
| [in,out] | presentation | Descriptor-backed presentation workspace. |
| [in,out] | uc | Initialized Unicorn engine containing the loaded images. |
| [in,out] | elf | Primary ELF source retained through final reporting. |
| [in,out] | ns_elf | Optional non-secure ELF source to close after lookup. |
| [in] | view_w | Resolved presentation width in pixels. |
| [in] | view_h | Resolved presentation height in pixels. |
| [in] | win_title | NUL-terminated title selected for the board view. |
| value | The run loop's operation-specific process status. |
Definition at line 766 of file main.c.
References emu_memmap_mram_base(), emu_run_and_report(), emu_tz_patch_cmse(), emu_elf_source_t::fd, internal_main_build_run_cfg(), internal_main_install_core_seams(), internal_main_install_run_seams(), internal_main_reset_vector(), internal_main_resolve_symbols(), k_dump_sym_max, priv_emu_elf_source_close(), and RA8_INTERNAL.
Referenced by main().
| int main | ( | int | argc, |
| char ** | argv ) |
Definition at line 849 of file main.c.
References emu_args_parse(), emu_memmap_close(), emu_presentation_close(), internal_main_apply_panel(), internal_main_bringup_peripherals(), internal_main_load_images(), internal_main_open_engine(), internal_main_open_memory(), internal_main_open_presentation(), internal_main_run_loaded(), priv_emu_io_configure(), emu_args_t::view_h, and emu_args_t::view_w.
|
static |
Explicit bounded presentation scratch owned by the process root.
Exactly 16,384 B supports two 64x64 RGB565 rotation tiles; modes and smaller geometry bind only the exact required prefix.
Definition at line 81 of file main.c.
Referenced by internal_main_open_presentation().