ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
emu_cpu1.c File Reference

Second-core (cpu1) engine implementation (see emu_cpu1.h). More...

#include "emu_cpu1.h"
#include <stdio.h>
#include <string.h>
#include "emu_console.h"
#include "emu_elf.h"
#include "emu_engine.h"
#include "emu_host_io_internal.h"
#include "emu_memmap.h"
#include "emu_mmio.h"
Include dependency graph for emu_cpu1.c:

Go to the source code of this file.

Enumerations

enum  dual_core_addr_t : uint64_t {
  k_cpu1_initvtor_addr = 0x4000F044UL ,
  k_cpu1_actcsr_addr = 0x4000F064UL ,
  k_cpu1_mram_base = 0x020C0000UL ,
  k_cpu1_mram_end = 0x02100000UL
}
 CPU_CTRL registers + activation bit for the second core (cpu1). More...
enum  dual_core_bits_t : uint32_t {
  k_cpu1_actcsr_actreq = 1U << 0U ,
  k_cpu1_actcsr_key = 0xA5U ,
  k_cpu1_actcsr_key_shift = 8U ,
  k_cpu1_actcsr_key_mask = 0xFFU ,
  k_cpu1_chunk_insns = 100000U
}

Functions

void emu_cpu1_notify_mmio_write (uint64_t mmio_abs, uint64_t value)
 Implementation of emu_cpu1_notify_mmio_write() – release capture.
static bool internal_cpu1_segment (const elf_exec_segment_t *segment, void *opaque)
 True if elf carries a PT_LOAD segment in the cpu1 MRAM window.
static bool internal_cpu1_image_present (const emu_elf_source_t *elf)
 Detect a PT_LOAD segment in the cpu1 MRAM window.
static uc_engine * internal_cpu1_engine_init (const emu_elf_source_t *elf, emu_memmap_workspace_t *memory)
 Create the second emulator engine for cpu1 (Cortex-M33), if present.
void emu_cpu1_init (const emu_elf_source_t *elf, emu_memmap_workspace_t *memory)
 Implementation of emu_cpu1_init() – detect + build the engine.
void emu_cpu1_close (emu_memmap_workspace_t *memory)
 Detach and close the optional cpu1 engine.
void emu_cpu1_step (void)
 Implementation of emu_cpu1_step() – release boot + one interleave.

Variables

static uc_engine * s_cpu1_uc
 2nd engine for cpu1 (NULL if N/A).
static bool s_cpu1_active
 cpu1 released and stepping.
static bool s_cpu1_release_req
 CPU1ACTCSR.ACTREQ observed.
static uint32_t s_cpu1_initvtor
 Captured CPU1INITVTOR value.
static uint32_t s_cpu1_pc
 cpu1 run PC across interleaves.

Detailed Description

Second-core (cpu1) engine implementation (see emu_cpu1.h).

The CPU_CTRL release watcher, the second Unicorn engine bring-up with the shared-SRAM backing, and the interleaved stepping – moved verbatim out of the ra8_emulator main translation unit.

Since
0.1.0

Definition in file emu_cpu1.c.

Enumeration Type Documentation

◆ dual_core_addr_t

enum dual_core_addr_t : uint64_t

CPU_CTRL registers + activation bit for the second core (cpu1).

The RA8D2 boots cpu0 (Cortex-M85); the application releases cpu1 (Cortex-M33) by writing CPU1INITVTOR (its vector table) then CPU1ACTCSR.ACTREQ. ra8_emulator emulates cpu1 in a second Unicorn engine that shares the on-chip SRAM with cpu0 (host-backed), so cpu1_pingpong's cross-core IPC over shared SRAM actually runs. Inert unless the firmware carries a cpu1 image and asserts ACTREQ.

Enumerator
k_cpu1_initvtor_addr 

CPU_CTRL.CPU1INITVTOR (32-bit).

k_cpu1_actcsr_addr 

CPU_CTRL.CPU1ACTCSR (16-bit).

k_cpu1_mram_base 

MRAM_CPU1: cpu1 image base.

k_cpu1_mram_end 

MRAM_CPU1 end (256 KiB).

Definition at line 39 of file emu_cpu1.c.

◆ dual_core_bits_t

enum dual_core_bits_t : uint32_t
Enumerator
k_cpu1_actcsr_actreq 

CPU1ACTCSR.ACTREQ -> release cpu1.

k_cpu1_actcsr_key 

KEY[15:8] required to honor a write.

k_cpu1_actcsr_key_shift 

KEY byte position (bits [15:8]).

k_cpu1_actcsr_key_mask 

KEY byte mask after the shift.

k_cpu1_chunk_insns 

cpu1 instructions per interleave.

Definition at line 46 of file emu_cpu1.c.

Function Documentation

◆ emu_cpu1_close()

void emu_cpu1_close ( emu_memmap_workspace_t * memory)

Detach and close the optional cpu1 engine.

Parameters
[in,out]memoryBacking supplied to emu_cpu1_init.
Returns
Nothing.
Postcondition
The cpu1 binding no longer participates in publications.
Repeated calls are harmless.
Since
0.1.0

Detach and close the optional cpu1 engine; this step is contained within the emu cpu1 model and uses bounded caller or module-owned storage.

Precondition
Arguments satisfy the ranges documented for emu cpu1 close.
The call executes on the emulator's single owning thread.
Note
The operation is synchronous and does not transfer heap ownership.

Definition at line 183 of file emu_cpu1.c.

References emu_memmap_detach(), s_cpu1_active, s_cpu1_release_req, and s_cpu1_uc.

Referenced by priv_run_cleanup().

◆ emu_cpu1_init()

void emu_cpu1_init ( const emu_elf_source_t * elf,
emu_memmap_workspace_t * memory )

Implementation of emu_cpu1_init() – detect + build the engine.

Create the second emulator engine for cpu1, if the image carries one.

Definition at line 178 of file emu_cpu1.c.

References internal_cpu1_engine_init(), and s_cpu1_uc.

Referenced by internal_main_install_run_seams().

◆ emu_cpu1_notify_mmio_write()

void emu_cpu1_notify_mmio_write ( uint64_t mmio_abs,
uint64_t value )

Implementation of emu_cpu1_notify_mmio_write() – release capture.

Watch a peripheral MMIO write for the cpu1 release sequence.

Definition at line 68 of file emu_cpu1.c.

References k_cpu1_actcsr_actreq, k_cpu1_actcsr_addr, k_cpu1_actcsr_key, k_cpu1_actcsr_key_mask, k_cpu1_actcsr_key_shift, k_cpu1_initvtor_addr, s_cpu1_initvtor, and s_cpu1_release_req.

Referenced by mmio_write().

◆ emu_cpu1_step()

void emu_cpu1_step ( void )

Implementation of emu_cpu1_step() – release boot + one interleave.

Boot cpu1 on a pending release, then step it one interleave chunk.

Definition at line 196 of file emu_cpu1.c.

References k_cpu1_chunk_insns, rd32(), s_cpu1_active, s_cpu1_initvtor, s_cpu1_pc, s_cpu1_release_req, and s_cpu1_uc.

Referenced by internal_run_loop_record().

◆ internal_cpu1_engine_init()

uc_engine * internal_cpu1_engine_init ( const emu_elf_source_t * elf,
emu_memmap_workspace_t * memory )
static

Create the second emulator engine for cpu1 (Cortex-M33), if present.

Only dual-core firmware (one exporting cpu1_reset_handler) gets a cpu1 engine, so single-core apps pay nothing. The engine maps the same regions as cpu0 but binds the on-chip SRAM to the same authoritative descriptor so cross-core IPC over shared SRAM is coherent; the full ELF (which carries cpu1's image at MRAM_CPU1) is loaded so cpu1 can boot from its own vector table when released. The engine is left idle – the run loop boots it on the CPU1ACTCSR release.

Parameters
[in]elfThe open firmware image (cpu0 + cpu1).
[in,out]memoryThe authoritative backing already attached to CPU0.
Returns
The cpu1 engine, or NULL if this is not a dual-core image (or setup failed – cpu0 then runs alone, exactly as before).
Return values
NULLNot a dual-core image / engine setup failed.
Precondition
memory is open and already attached to CPU0.
elf is a valid open source retained through CPU1 loading.
Postcondition
On success a Cortex-M33 engine mirrors descriptor-backed shared memory.
No cpu1 instruction has executed yet (idle until released).
Note
cpu1's PPB / peripheral writes stay private to its engine.
Since
0.1.0

Definition at line 157 of file emu_cpu1.c.

References emu_memmap_attach(), emu_memmap_detach(), internal_cpu1_image_present(), k_emu_memmap_ok, load_elf(), priv_emu_io_errf(), and RA8_INTERNAL.

Referenced by emu_cpu1_init().

◆ internal_cpu1_image_present()

bool internal_cpu1_image_present ( const emu_elf_source_t * elf)
static

Detect a PT_LOAD segment in the cpu1 MRAM window.

Walks load headers without reading or retaining segment payloads.

Parameters
[in]elfOpen primary ELF source.
Returns
Whether a cpu1 MRAM load segment exists.
Return values
trueAt least one load segment targets the cpu1 aperture.
falseNo usable load segment targets the cpu1 aperture.
Precondition
elf is non-null.
elf remains open during the walk.
Postcondition
The source descriptor and cursor are unchanged.
No emulator state changes.
Note
Uses one caller-local accumulator.
Since
0.1.0

Definition at line 124 of file emu_cpu1.c.

References elf_foreach_load_segment(), internal_cpu1_segment(), and RA8_INTERNAL.

Referenced by internal_cpu1_engine_init().

◆ internal_cpu1_segment()

bool internal_cpu1_segment ( const elf_exec_segment_t * segment,
void * opaque )
static

True if elf carries a PT_LOAD segment in the cpu1 MRAM window.

Dual-core only: cpu1's image is embedded as raw bytes (.cpu1_image, not a cpu0 symbol), so detect it by a PT_LOAD segment whose physical address lands in the MRAM_CPU1 aperture.

Parameters
[in]segmentBounds-checked load-segment descriptor.
[in,out]opaqueBoolean presence accumulator.
Returns
Whether the load-segment walk should continue.
Return values
trueThe segment is outside the cpu1 MRAM window.
falseA cpu1 segment was found and the walk may stop.
Precondition
segment is non-null.
opaque points to a writable bool.
Postcondition
The accumulator is true exactly when this segment belongs to cpu1.
No source or emulator state changes.
Note
Pure apart from the caller-owned accumulator.
Since
0.1.0

Definition at line 102 of file emu_cpu1.c.

References k_cpu1_mram_base, k_cpu1_mram_end, elf_exec_segment_t::paddr, and RA8_INTERNAL.

Referenced by internal_cpu1_image_present().

Variable Documentation

◆ s_cpu1_active

bool s_cpu1_active
static

cpu1 released and stepping.

Definition at line 55 of file emu_cpu1.c.

Referenced by emu_cpu1_close(), and emu_cpu1_step().

◆ s_cpu1_initvtor

uint32_t s_cpu1_initvtor
static

Captured CPU1INITVTOR value.

Definition at line 57 of file emu_cpu1.c.

Referenced by emu_cpu1_notify_mmio_write(), and emu_cpu1_step().

◆ s_cpu1_pc

uint32_t s_cpu1_pc
static

cpu1 run PC across interleaves.

Definition at line 58 of file emu_cpu1.c.

Referenced by emu_cpu1_step().

◆ s_cpu1_release_req

bool s_cpu1_release_req
static

CPU1ACTCSR.ACTREQ observed.

Definition at line 56 of file emu_cpu1.c.

Referenced by emu_cpu1_close(), emu_cpu1_notify_mmio_write(), and emu_cpu1_step().

◆ s_cpu1_uc

uc_engine * s_cpu1_uc
static

2nd engine for cpu1 (NULL if N/A).

Definition at line 54 of file emu_cpu1.c.

Referenced by emu_cpu1_close(), emu_cpu1_init(), and emu_cpu1_step().