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

Inter-Processor Communication (IPC) peripheral-block model for ra8_emulator. More...

#include <stdint.h>
#include <stdio.h>
#include "board_periph_block.h"
#include "emu_host_io_internal.h"
Include dependency graph for board_periph_ipc.c:

Go to the source code of this file.

Data Structures

struct  ipc_fifo_t
 One channel's 4-stage message FIFO plus its sticky error latches. More...
struct  ipc_state_t
 Modelled IPC state: per-channel IRQ bits + FIFOs plus run counters. More...

Enumerations

enum  ipc_order_t : uint32_t { k_ipc_block_order = 62U }
 Per-tick order slot for the IPC block. More...
enum  ipc_geom_t : uint64_t {
  k_ipc_base = 0x40020000UL ,
  k_ipc_span = 0x140UL
}
 IPC register window geometry (ra8_ipc_regs.h). More...
enum  ipc_reg_off_t : uint64_t {
  k_ipc_ch0_off = 0xC0UL ,
  k_ipc_ch_stride = 0x20UL ,
  k_ipc_reg_sta = 0x00UL ,
  k_ipc_reg_iset = 0x04UL ,
  k_ipc_reg_txd = 0x08UL ,
  k_ipc_reg_rxd = 0x0CUL ,
  k_ipc_reg_clr = 0x10UL
}
 Channel-window layout within the IPC register block. More...
enum  ipc_chan_t : uint32_t {
  k_ipc_ch_count = 4U ,
  k_ipc_unit_split = 2U ,
  k_ipc_fifo_depth = 4U
}
 Channel-count, unit-split and FIFO-depth constants. More...
enum  ipc_status_t : uint32_t {
  k_ipc_sta_irq_mask = 0x000000FFU ,
  k_ipc_sta_rdy = 0x00010000U ,
  k_ipc_sta_full = 0x00020000U ,
  k_ipc_sta_rerr = 0x01000000U ,
  k_ipc_sta_ferr = 0x02000000U ,
  k_ipc_clr_rst = 0x00010000U ,
  k_ipc_clr_rclr = 0x01000000U ,
  k_ipc_clr_fclr = 0x02000000U ,
  k_ipc0_irq_event = 0x05BU ,
  k_ipc1_irq_event = 0x05CU
}
 Status-register masks and the receiving-core ELC event ids. More...

Functions

static RA8_INTERNAL bool internal_ipc_decode (uint64_t off, uint32_t *ch, uint32_t *reg)
 Decode a window offset to its channel index and register offset.
static RA8_INTERNAL uint32_t internal_ipc_sta_value (uint32_t ch)
 Compose one channel's live STA value from its shadows.
static RA8_INTERNAL uint32_t internal_ipc_fifo_pop (uint32_t ch)
 Pop the oldest word off a channel's message FIFO (RXD read).
static RA8_INTERNAL uint64_t internal_ipc_read (uc_engine *uc, uint64_t addr, unsigned size)
 Read an IPC register: STA composes live status, RXD pops the FIFO.
static RA8_INTERNAL void internal_ipc_fifo_push (uint32_t ch, uint32_t value)
 Push one word onto a channel's message FIFO (TXD write).
static RA8_INTERNAL void internal_ipc_clr_write (uint32_t ch, uint32_t value)
 Apply a CLR write: W1C IRQ lines, FIFO reset, error-latch clears.
static RA8_INTERNAL void internal_ipc_write (uc_engine *uc, uint64_t addr, unsigned size, uint64_t value)
 Write an IPC register: ISET latches + raises, TXD pushes, CLR clears.
static RA8_INTERNAL void internal_ipc_reset (void)
 Clear the IPC channel shadows and the run counters.
static RA8_INTERNAL void internal_ipc_report (void)
 Print the IPC send / wake / FIFO totals when the path was exercised.
static RA8_INTERNAL void internal_board_periph_ipc_register (void)
 Self-register the IPC window before main runs (decentralised).

Variables

static ipc_state_t s_ipc
 Single shared IPC model instance (both engines dispatch into it).
static const board_periph_block_t s_k_ipc_block
 IPC register window + reset / report (no tick: event-driven only).

Detailed Description

Inter-Processor Communication (IPC) peripheral-block model for ra8_emulator.

Models the maskable-IRQ event path of the RA8D2 IPC unit (ra8_ipc_regs.h, ra8_ipc.c) so the dual-core compile_on_m33 example can replace its busy done-flag poll with a real interrupt-driven wake: the secondary Cortex-M33, having finished the EPUB->RABOOK1 compile, pokes IPC0ISET0 (HUM Ch 3.2.11 "IPC0ISET0" p 215) and the primary Cortex-M85 – idling in WFI – takes the IPC0 receive interrupt and re-checks the mailbox.

Two surfaces are modelled per channel; the semaphores / NMI windows are not exercised by any consumer, so reads there return 0 and writes are benign no-ops. Per channel the model keeps the STA pending-IRQ shadow plus a 4-stage message FIFO (HUM Ch 3.1 "Overview" p 204 fixes the depth):

  • A write to ISET (set-IRQ, +0x04) latches the written IRQ-line bits into STA and raises the receiving core's ELC event through the core's ICU -> NVIC path, exactly the cross-core poke real silicon performs. IPC0 channels (CPU1 -> CPU0) raise ELC_EVENT_IPC_IRQ0 (0x05B); IPC1 channels (CPU0 -> CPU1) raise ELC_EVENT_IPC_IRQ1 (0x05C).
  • A read of STA (+0x00) returns the latched pending bits the receiver's ra8_ipc_dispatch decodes, plus the live FIFO status: RDY (bit 16, FIFO non-empty), FULL (bit 17), and the RERR / FERR sticky error latches (bits 24 / 25). HUM Ch 3.2.10 "IPC0STA0" p 214.
  • A write to TXD (+0x08) pushes one 32-bit word onto the channel FIFO (FERR latches on a write-while-full); a read of RXD (+0x0C) pops one word (RERR latches on a read-while-empty). This is the data path the dual-core ping-pong (cpu1_pingpong_ipc) exchanges its magic words over: the sender pushes on one engine, the receiver polls STA.RDY and pops on the other, against ONE shared model instance. HUM Ch 3.2.12 "IPC0TXD0" p 215 / Ch 3.2.13 "IPC0RXD0" p 216.
  • A write to CLR (W1C, +0x10) clears the acknowledged IRQ-line bits; RST (bit 16) empties the FIFO (dropping RDY / FULL), and RCLR / FCLR (bits 24 / 25) drop the sticky error latches. HUM Ch 3.2.14 "IPC0CLR0" p 216-217.

The M33 reaches this window through the bit[28] non-secure peripheral alias (0x50020000); the cpu1 engine maps that alias to the same models via the same MMIO hooks, so an alias access dispatches here identically to a Secure one.

The IPC has no time-based behaviour, so the block carries no tick.

Since
0.1.0

Definition in file board_periph_ipc.c.

Enumeration Type Documentation

◆ ipc_chan_t

enum ipc_chan_t : uint32_t

Channel-count, unit-split and FIFO-depth constants.

Enumerator
k_ipc_ch_count 

IPC0_0, IPC0_1, IPC1_0, IPC1_1.

k_ipc_unit_split 

Channels < split are IPC0, the rest IPC1.

k_ipc_fifo_depth 

4-stage message FIFO (HUM Ch 3.1 p 204).

Definition at line 86 of file board_periph_ipc.c.

◆ ipc_geom_t

enum ipc_geom_t : uint64_t

IPC register window geometry (ra8_ipc_regs.h).

Enumerator
k_ipc_base 

IPC unit base (Secure alias).

k_ipc_span 

Semaphores + NMI + four channel windows.

Definition at line 69 of file board_periph_ipc.c.

◆ ipc_order_t

enum ipc_order_t : uint32_t

Per-tick order slot for the IPC block.

The IPC carries no tick, so its order is never consulted for advance; the value only has to be unique among the registered blocks. Placed above the RTC slot (60) following the same decentralised-ordering convention.

Enumerator
k_ipc_block_order 

IPC reset / report order slot.

Definition at line 64 of file board_periph_ipc.c.

◆ ipc_reg_off_t

enum ipc_reg_off_t : uint64_t

Channel-window layout within the IPC register block.

Enumerator
k_ipc_ch0_off 

IPC0 channel 0 (FIFO00) window base.

k_ipc_ch_stride 

Stride between consecutive channels.

k_ipc_reg_sta 

STA pending-IRQ register (read).

k_ipc_reg_iset 

ISET set-IRQ register (write).

k_ipc_reg_txd 

TXD FIFO transmit register (write).

k_ipc_reg_rxd 

RXD FIFO receive register (read).

k_ipc_reg_clr 

CLR clear register (W1C).

Definition at line 75 of file board_periph_ipc.c.

◆ ipc_status_t

enum ipc_status_t : uint32_t

Status-register masks and the receiving-core ELC event ids.

Enumerator
k_ipc_sta_irq_mask 

Eight maskable IRQ-line bits.

k_ipc_sta_rdy 

STA.RDY: receive FIFO non-empty.

k_ipc_sta_full 

STA.FULL: message FIFO full.

k_ipc_sta_rerr 

STA.RERR: read-while-empty sticky.

k_ipc_sta_ferr 

STA.FERR: write-while-full sticky.

k_ipc_clr_rst 

CLR.RST: reset the message FIFO.

k_ipc_clr_rclr 

CLR.RCLR: drop the RERR sticky.

k_ipc_clr_fclr 

CLR.FCLR: drop the FERR sticky.

k_ipc0_irq_event 

ELC_EVENT_IPC_IRQ0 -> CPU0/M85.

k_ipc1_irq_event 

ELC_EVENT_IPC_IRQ1 -> CPU1/M33.

Definition at line 93 of file board_periph_ipc.c.

Function Documentation

◆ internal_board_periph_ipc_register()

RA8_INTERNAL void internal_board_periph_ipc_register ( void )
static

Self-register the IPC window before main runs (decentralised).

Definition at line 460 of file board_periph_ipc.c.

References board_periph_register_block(), RA8_INTERNAL, and s_k_ipc_block.

◆ internal_ipc_clr_write()

RA8_INTERNAL void internal_ipc_clr_write ( uint32_t ch,
uint32_t value )
static

Apply a CLR write: W1C IRQ lines, FIFO reset, error-latch clears.

Parameters
[in]chChannel index (0..k_ipc_ch_count - 1).
[in]valueThe written CLR word.
Returns
Nothing.
Precondition
ch is a decoded channel index (< k_ipc_ch_count).
The model state s_ipc is initialised.
Postcondition
IRQ-line bits written as 1 are cleared from the STA shadow.
RST empties the FIFO; RCLR / FCLR drop the sticky error latches.
Note
HUM Ch 3.2.14 "IPC0CLR0" p 216-217 – field layout.
Since
0.1.0

Apply a clr write: w1c irq lines, fifo reset, error-latch clears; this step is contained within the board periph ipc model and uses bounded caller or module-owned storage.

Definition at line 339 of file board_periph_ipc.c.

References ipc_fifo_t::count, ipc_fifo_t::ferr, k_ipc_clr_fclr, k_ipc_clr_rclr, k_ipc_clr_rst, k_ipc_sta_irq_mask, RA8_INTERNAL, ipc_fifo_t::rd, ipc_fifo_t::rerr, and s_ipc.

Referenced by internal_ipc_write().

◆ internal_ipc_decode()

RA8_INTERNAL bool internal_ipc_decode ( uint64_t off,
uint32_t * ch,
uint32_t * reg )
static

Decode a window offset to its channel index and register offset.

Parameters
[in]offByte offset from k_ipc_base.
[out]chReceives the channel index 0..3 on success.
[out]regReceives the in-channel register offset on success.
Returns
Whether off lands inside a channel window.
Return values
trueoff is in [0xC0, 0x140); ch / reg are set.
falseoff is in the semaphore / NMI region (no channel).
Precondition
ch and reg are non-NULL.
off is within the block span.
Postcondition
On true, ch < k_ipc_ch_count.
On false, ch and reg are untouched.
Note
Pure decode; touches no model state.
Since
0.1.0

Decode a window offset to its channel index and register offset; this step is contained within the board periph ipc model and uses bounded caller or module-owned storage.

Definition at line 172 of file board_periph_ipc.c.

References k_ipc_ch0_off, k_ipc_ch_count, k_ipc_ch_stride, and RA8_INTERNAL.

Referenced by internal_ipc_read(), and internal_ipc_write().

◆ internal_ipc_fifo_pop()

RA8_INTERNAL uint32_t internal_ipc_fifo_pop ( uint32_t ch)
static

Pop the oldest word off a channel's message FIFO (RXD read).

Parameters
[in]chChannel index (0..k_ipc_ch_count - 1).
Returns
The dequeued word, or 0 with RERR latched on an empty FIFO.
Return values
0FIFO was empty (RERR sticky latched) or the queued word was 0.
Precondition
ch is a decoded channel index (< k_ipc_ch_count).
The model state s_ipc is initialised.
Postcondition
On a non-empty FIFO one word is consumed and pops advances.
On an empty FIFO the RERR sticky latch is set.
Note
HUM Ch 3.2.13 "IPC0RXD0" p 216 – a read pops one FIFO stage.
Since
0.1.0

Pop the oldest word off a channel's message fifo (rxd read); this step is contained within the board periph ipc model and uses bounded caller or module-owned storage.

Definition at line 246 of file board_periph_ipc.c.

References ipc_fifo_t::count, k_ipc_fifo_depth, RA8_INTERNAL, ipc_fifo_t::rd, ipc_fifo_t::rerr, s_ipc, and ipc_fifo_t::word.

Referenced by internal_ipc_read().

◆ internal_ipc_fifo_push()

RA8_INTERNAL void internal_ipc_fifo_push ( uint32_t ch,
uint32_t value )
static

Push one word onto a channel's message FIFO (TXD write).

Parameters
[in]chChannel index (0..k_ipc_ch_count - 1).
[in]valueThe 32-bit message word to queue.
Returns
Nothing.
Precondition
ch is a decoded channel index (< k_ipc_ch_count).
The model state s_ipc is initialised.
Postcondition
On a non-full FIFO the word is appended and pushes advances; the receiver's next STA read shows RDY.
On a full FIFO the word is dropped and the FERR sticky latch is set.
Note
HUM Ch 3.2.12 "IPC0TXD0" p 215-216 – a write pushes one FIFO stage.
Since
0.1.0

Push one word onto a channel's message fifo (txd write); this step is contained within the board periph ipc model and uses bounded caller or module-owned storage.

Definition at line 310 of file board_periph_ipc.c.

References ipc_fifo_t::count, ipc_fifo_t::ferr, k_ipc_fifo_depth, RA8_INTERNAL, ipc_fifo_t::rd, s_ipc, and ipc_fifo_t::word.

Referenced by internal_ipc_write().

◆ internal_ipc_read()

RA8_INTERNAL uint64_t internal_ipc_read ( uc_engine * uc,
uint64_t addr,
unsigned size )
static

Read an IPC register: STA composes live status, RXD pops the FIFO.

Read an ipc register: sta composes live status, rxd pops the fifo; this step is contained within the board periph ipc model and uses bounded caller or module-owned storage.

Parameters
[in,out]ucUnicorn engine whose emulated state is read or updated.
[in]addrGuest address involved in the operation.
[in]sizeSize of the requested region or access in bytes.
Returns
The ipc read result produced by the board periph ipc model.
Return values
valueThe operation-specific ipc read value.
Precondition
Arguments satisfy the ranges documented for ipc read.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph ipc model and documented output objects.
Ownership of caller-supplied storage is unchanged.
Note
The operation is synchronous and does not transfer heap ownership.
Since
0.1.0

Definition at line 273 of file board_periph_ipc.c.

References internal_ipc_decode(), internal_ipc_fifo_pop(), internal_ipc_sta_value(), k_ipc_base, k_ipc_reg_rxd, k_ipc_reg_sta, and RA8_INTERNAL.

◆ internal_ipc_report()

RA8_INTERNAL void internal_ipc_report ( void )
static

Print the IPC send / wake / FIFO totals when the path was exercised.

Print the ipc send / wake / fifo totals when the path was exercised; this step is contained within the board periph ipc model and uses bounded caller or module-owned storage.

Precondition
Arguments satisfy the ranges documented for ipc report.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph ipc model and documented output objects.
Ownership of caller-supplied storage is unchanged.
Note
The operation is synchronous and does not transfer heap ownership.
Since
0.1.0

Definition at line 434 of file board_periph_ipc.c.

References priv_emu_io_errf(), RA8_INTERNAL, and s_ipc.

◆ internal_ipc_reset()

RA8_INTERNAL void internal_ipc_reset ( void )
static

Clear the IPC channel shadows and the run counters.

Clear the ipc channel shadows and the run counters; this step is contained within the board periph ipc model and uses bounded caller or module-owned storage.

Precondition
Arguments satisfy the ranges documented for ipc reset.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph ipc model and documented output objects.
Ownership of caller-supplied storage is unchanged.
Note
The operation is synchronous and does not transfer heap ownership.
Since
0.1.0

Definition at line 421 of file board_periph_ipc.c.

References RA8_INTERNAL, and s_ipc.

◆ internal_ipc_sta_value()

RA8_INTERNAL uint32_t internal_ipc_sta_value ( uint32_t ch)
static

Compose one channel's live STA value from its shadows.

Parameters
[in]chChannel index (0..k_ipc_ch_count - 1).
Returns
The STA read value: pending-IRQ bits, RDY / FULL FIFO status, and the RERR / FERR sticky error latches.
Return values
0Channel idle: no pending IRQ, empty FIFO, no latched error.
Precondition
ch is a decoded channel index (< k_ipc_ch_count).
The model state s_ipc is initialised (constructor ran).
Postcondition
No model state is modified (pure compose).
RDY reflects count > 0 and FULL reflects count == depth.
Note
HUM Ch 3.2.10 "IPC0STA0" p 214 – field layout.
Since
0.1.0

Compose one channel's live sta value from its shadows; this step is contained within the board periph ipc model and uses bounded caller or module-owned storage.

Definition at line 210 of file board_periph_ipc.c.

References ipc_fifo_t::count, ipc_fifo_t::ferr, k_ipc_fifo_depth, k_ipc_sta_ferr, k_ipc_sta_full, k_ipc_sta_rdy, k_ipc_sta_rerr, RA8_INTERNAL, ipc_fifo_t::rerr, and s_ipc.

Referenced by internal_ipc_read().

◆ internal_ipc_write()

RA8_INTERNAL void internal_ipc_write ( uc_engine * uc,
uint64_t addr,
unsigned size,
uint64_t value )
static

Write an IPC register: ISET latches + raises, TXD pushes, CLR clears.

Write an ipc register: iset latches + raises, txd pushes, clr clears; this step is contained within the board periph ipc model and uses bounded caller or module-owned storage.

Parameters
[in,out]ucUnicorn engine whose emulated state is read or updated.
[in]addrGuest address involved in the operation.
[in]sizeSize of the requested region or access in bytes.
[in]valueRegister or payload value involved in the operation.
Precondition
Arguments satisfy the ranges documented for ipc write.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph ipc model and documented output objects.
Ownership of caller-supplied storage is unchanged.
Note
The operation is synchronous and does not transfer heap ownership.
Since
0.1.0

Definition at line 368 of file board_periph_ipc.c.

References board_periph_icu_raise_event(), board_periph_trace(), internal_ipc_clr_write(), internal_ipc_decode(), internal_ipc_fifo_push(), k_ipc0_irq_event, k_ipc1_irq_event, k_ipc_base, k_ipc_reg_clr, k_ipc_reg_iset, k_ipc_reg_txd, k_ipc_sta_irq_mask, k_ipc_unit_split, priv_emu_io_errf(), and s_ipc.

Variable Documentation

◆ s_ipc

ipc_state_t s_ipc
static

Single shared IPC model instance (both engines dispatch into it).

Warning
Mutated only from the ra8_emulator MMIO hooks; not for direct use.

Definition at line 145 of file board_periph_ipc.c.

Referenced by internal_ipc_clr_write(), internal_ipc_fifo_pop(), internal_ipc_fifo_push(), internal_ipc_report(), internal_ipc_reset(), internal_ipc_sta_value(), and internal_ipc_write().

◆ s_k_ipc_block

const board_periph_block_t s_k_ipc_block
static
Initial value:
= {
.base = (uint64_t)k_ipc_base,
.span = (uint64_t)k_ipc_span,
.order = (uint32_t)k_ipc_block_order,
.tick = nullptr,
.name = "IPC",
}
static RA8_INTERNAL void internal_ipc_write(uc_engine *uc, uint64_t addr, unsigned size, uint64_t value)
Write an IPC register: ISET latches + raises, TXD pushes, CLR clears.
@ k_ipc_span
Semaphores + NMI + four channel windows.
@ k_ipc_base
IPC unit base (Secure alias).
static RA8_INTERNAL uint64_t internal_ipc_read(uc_engine *uc, uint64_t addr, unsigned size)
Read an IPC register: STA composes live status, RXD pops the FIFO.
static RA8_INTERNAL void internal_ipc_reset(void)
Clear the IPC channel shadows and the run counters.
@ k_ipc_block_order
IPC reset / report order slot.
static RA8_INTERNAL void internal_ipc_report(void)
Print the IPC send / wake / FIFO totals when the path was exercised.
-proof

IPC register window + reset / report (no tick: event-driven only).

Definition at line 447 of file board_periph_ipc.c.

Referenced by internal_board_periph_ipc_register().