ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
emu_seam_sd.c
Go to the documentation of this file.
1
16
17#include <stdio.h>
18
19#include "board_periph_sd.h"
20#include "emu_elf.h"
21#include "emu_engine.h"
23#include "emu_seams.h"
24#include "emu_trace.h"
25
26/* =============================================================================
27 * --fast-sd: serve whole SD blocks in C instead of clocking 512 SPI bytes each.
28 * =============================================================================
29 *
30 * The firmware reads an SD card over SCI0 in Simple-SPI mode one byte at a time:
31 * ra8_sci_spi_xfer8() issues a FIXED five MMIO accesses per byte (poll TDRE, write
32 * TDR, poll RDRF, read RDR, clear RDRF), and a 512-byte block is 512 of those. A
33 * book-sized read is millions of MMIO callbacks -- tens of wall-clock seconds in
34 * Unicorn (QEMU-TCG) -- versus ~0.1 s on the real 25 MHz bus, so the cost is a
35 * pure emulation artifact, not firmware behaviour.
36 *
37 * The right granularity to skip is the BLOCK, not the byte: redirecting a hooked
38 * function back to its caller needs a uc_emu_stop/relaunch, which is far more
39 * expensive than an MMIO callback, so a per-byte hook is a net loss (millions of
40 * relaunches). Opt-in --fast-sd instead installs a UC_HOOK_CODE at the entry of
41 * ra8_sdmmc_spi_read_block(lba, buf): with a card attached it copies the 512-byte
42 * block straight from the image via ::board_sd_read_block -- the byte-identical
43 * data the CMD17 path would stream -- writes it to @c buf, returns k_ra8_ok and
44 * jumps to LR. One relaunch per sector (hundreds per book) instead of millions
45 * per byte, so the rendered framebuffer is byte-for-byte identical while the read
46 * drops from tens of seconds to well under one.
47 *
48 * Faithfulness: this serves block DATA directly, bypassing the SD-over-SPI block
49 * protocol (CMD17 / 0xFE token / CRC16 / the per-byte SPI loop) for the data
50 * path. The FAT parse, inflate, and render all still run on the real firmware and
51 * see identical bytes; the bypassed block protocol is covered by the host unit
52 * test (apps/shared_libs/reflow/tests/src/test_ra8_sdmmc_card_reflow.c) and by hardware. It is
53 * OFF by default:
54 * HIL gates and the default run exercise the full handshake; turn it on only to
55 * load a large book fast for an interactive or recorded capture. A card-absent
56 * call, an out-of-range LBA, or a firmware without the symbol falls through to
57 * the real driver, so nothing else is affected.
58 */
59
61typedef enum : uint16_t {
64
73static bool s_fast_sd;
74
87RA8_INTERNAL static void
88internal_on_sdmmc_read_block(uc_engine* uc, uint64_t address, uint32_t size, void* user)
89{
90 (void)address;
91 (void)size;
92 (void)user;
93 uint32_t lba = 0U;
94 uint32_t buf_ptr = 0U;
95 (void)uc_reg_read(uc, UC_ARM_REG_R0, &lba);
96 (void)uc_reg_read(uc, UC_ARM_REG_R1, &buf_ptr);
97 uint8_t blk[k_fast_sd_block];
98 /* No card, a null buffer, or an out-of-range LBA -> run the real driver so the
99 * card-absent / error path stays exactly as on hardware. */
100 if (!board_sd_attached() || (buf_ptr == 0U) || !board_sd_read_block(lba, blk)) {
101 return;
102 }
103 (void)emu_mem_write(uc, (uint64_t)buf_ptr, blk, sizeof blk);
104 /* Relaunch as a zero-time seam (no chunk / SysTick cost) so a whole book-sized
105 * read drains within one settle window. */
107 eth_hook_return(uc, 0U); /* k_ra8_ok: set r0 + jump to LR, skipping the body. */
108}
109
124void fast_sd_seam_install(uc_engine* uc, const emu_elf_source_t* elf)
125{
126 if (!s_fast_sd) {
127 return;
128 }
129 const uint32_t addr = elf_sym_addr(elf, "ra8_sdmmc_spi_read_block", nullptr);
130 if (addr == 0U) {
131 (void)priv_emu_io_errf(
132 " [fast-sd] ra8_sdmmc_spi_read_block not found -- SD stays on the per-byte path\n");
133 return;
134 }
135 static uc_hook s_h_fast_sd;
136 (void)uc_hook_add(uc,
137 &s_h_fast_sd,
138 UC_HOOK_CODE,
140 nullptr,
141 (uint64_t)addr,
142 (uint64_t)addr);
143 (void)priv_emu_io_errf(" [fast-sd] ra8_sdmmc_spi_read_block block-hook armed @ 0x%08X "
144 "(SD blocks served direct from the image)\n",
145 (unsigned)addr);
146}
147
150{
151 s_fast_sd = true;
152}
SD-card-over-SPI device model for ra8_emulator (attached to SPI_B).
bool board_sd_attached(void)
Report whether an SD-card image is currently attached.
bool board_sd_read_block(uint32_t lba, uint8_t *dst)
Copy one 512-byte block straight out of the backing image.
ELF32 image services for the board emulator (load / symbols / vectors).
uint32_t elf_sym_addr(const emu_elf_source_t *elf, const char *name, uint32_t *size_out)
Resolve a function symbol's entry address from the ELF .symtab.
Shared Unicorn engine access utilities for the board emulator.
void emu_seam_request_relaunch(void)
Mark the pending engine stop as a zero-time seam relaunch.
Definition emu_engine.c:52
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.
uc_err emu_mem_write(uc_engine *uc, uint64_t address, const void *bytes, size_t count)
Write guest memory through the central access seam.
fast_sd_const_t
–fast-sd block-serving constants.
Definition emu_seam_sd.c:61
@ k_fast_sd_block
SD block size served per hook entry.
Definition emu_seam_sd.c:62
void fast_sd_seam_install(uc_engine *uc, const emu_elf_source_t *elf)
Install the --fast-sd block-read hook if opted-in and the symbol exists.
void emu_fast_sd_enable(void)
Implementation of emu_fast_sd_enable() – CLI opt-in latch.
static bool s_fast_sd
True once --fast-sd is requested on the command line.
Definition emu_seam_sd.c:73
static RA8_INTERNAL void internal_on_sdmmc_read_block(uc_engine *uc, uint64_t address, uint32_t size, void *user)
Perform on sdmmc read block for the emu seam SD model.
Definition emu_seam_sd.c:88
Armv8.1-M instruction-emulation seams (M85 ops on Unicorn's M33).
Function-entry seam glue + the –trace-sym instrument.
void eth_hook_return(uc_engine *uc, uint32_t r0)
Emulate "return r0;" from a hooked function: set R0, branch to LR.
Definition emu_trace.c:32
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
One independently owned immutable raw-descriptor ELF source.
Definition emu_elf.h:91