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

Ultra-Low-Power Timer (ULPT) 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_ulpt.c:

Go to the source code of this file.

Data Structures

struct  ulpt_channel_t
 One modelled ULPT channel: a 32-bit reloading down-counter + status. More...

Enumerations

enum  ulpt_order_t : uint32_t { k_ulpt_block_order = 64U }
 Per-tick order slot for the ULPT block. More...
enum  ulpt_geom_t : uint64_t {
  k_ulpt_base = 0x40220000UL ,
  k_ulpt_stride = 0x100UL ,
  k_ulpt_count = 2UL ,
  k_ulpt_span = 0x100UL * 2UL
}
 ULPT register window geometry (ra8_ulpt_regs.h). More...
enum  ulpt_off_t : uint64_t {
  k_ulpt_off_cnt = 0x00UL ,
  k_ulpt_off_cma = 0x04UL ,
  k_ulpt_off_cmb = 0x08UL ,
  k_ulpt_off_cr = 0x0CUL ,
  k_ulpt_off_mr1 = 0x0DUL ,
  k_ulpt_off_mr2 = 0x0EUL ,
  k_ulpt_off_mr3 = 0x0FUL ,
  k_ulpt_off_ioc = 0x10UL
}
 ULPT per-channel register byte offsets (ra8_ulpt_regs.h). More...
enum  ulpt_cr_bit_t : uint8_t {
  k_ulpt_cr_tstart = 0x01U ,
  k_ulpt_cr_tcstf = 0x02U ,
  k_ulpt_cr_tstop = 0x04U ,
  k_ulpt_cr_tundf = 0x20U
}
 ULPTCR control / status bit masks. More...
enum  ulpt_rate_t : uint32_t { k_ulpt_step_per_chunk }
 Down-count step applied per emulation chunk while a channel runs. More...
enum  ulpt_event_t : uint16_t { k_ulpt_event_ch0_underflow = 0x080U }
 ULPT0 underflow ELC event the model emits (HUM Ch 19 ELC). More...
enum  ulpt_byte_t : uint32_t {
  k_ulpt_byte_mask = 0xFFU ,
  k_ulpt_byte_bits = 8U
}
 Sub-word access constants for the byte-granular MMIO path. More...

Functions

static RA8_INTERNAL uint32_t internal_ulpt_cell_value (const ulpt_channel_t *c, uint64_t off)
 Current 32-bit value of the register cell that contains off.
static RA8_INTERNAL uint64_t internal_ulpt_cell_base (uint64_t off)
 Byte offset of the start of the register cell that contains off.
static RA8_INTERNAL uint64_t internal_ulpt_read (uc_engine *uc, uint64_t addr, unsigned size)
 Read size bytes little-endian from the addressed ULPT channel.
static RA8_INTERNAL void internal_ulpt_write_cr (ulpt_channel_t *c, uint8_t value)
 Apply a write to ULPTCR: TSTART arms, TCSTF tracks it, TUNDF clears on 0.
static RA8_INTERNAL void internal_ulpt_write (uc_engine *uc, uint64_t addr, unsigned size, uint64_t value)
 Write size bytes little-endian into the addressed ULPT channel.
static RA8_INTERNAL void internal_ulpt_tick_channel (uc_engine *uc, uint32_t ch)
 Advance one running ULPT channel by one chunk; raise its underflow event.
static RA8_INTERNAL void internal_ulpt_tick (uc_engine *uc)
 Advance every running ULPT channel one chunk.
static RA8_INTERNAL void internal_ulpt_reset (void)
 Clear every ULPT channel to its power-on state.
static RA8_INTERNAL void internal_ulpt_report (void)
 Print each ULPT channel that underflowed at least once.
static RA8_INTERNAL void internal_board_periph_ulpt_register (void)
 Self-register the ULPT window before main runs (decentralized).

Variables

static ulpt_channel_t s_ulpt [k_ulpt_count]
static const board_periph_block_t s_k_ulpt_block
 ULPT register window + the down-count tick / reset / report.

Detailed Description

Ultra-Low-Power Timer (ULPT) peripheral-block model for ra8_emulator.

Models the RA8D2 ULPT (ra8_ulpt_regs.h, ra8_ulpt.c): two channels of a 32-bit reloading down-counter that clock from the LOCO-derived ULPTLCLK and keep running through Software Standby. The ULPT is the canonical low-power periodic-wake source, so this block is what lets the deep-idle examples run their genuine wake path in the headless emulator:

  • lpm_periodic_idle (hw_pending): each period it starts ULPT0, confirms ULPTCR.TCSTF = 1, drops to Software Standby (WFI), and relies on the ULPT0 underflow to cancel standby through the ICU -> NVIC path. Without a model the underflow event is never raised, so its registered ISR never runs and the wake counter stays 0; with this block the ULPT0_ULPTI event fires once per armed period, exactly as on silicon.
  • ulpt_demo / lpm_ulpt_standby (hw_validated): the same wake source, polled (TUNDF) and ISR-driven respectively.

The ULPT control/status register (ULPTCR) shares the AGT's AGTCR bit layout (HUM Ch 25.2.1 ULPTCR p 1190, mirror of HUM Ch 24.2.6 AGTCR p 1175): TSTART is bit 0, the read-only count-status flag TCSTF is bit 1, the forced-stop request TSTOP is bit 2, and the underflow flag TUNDF is bit 5. The model follows that authoritative layout so a TCSTF poll (bit 1) and a TUNDF poll (bit 5) both observe real timer state.

Timing is instruction-counted, not wall-clock: while a channel is started the counter steps down by k_ulpt_step_per_chunk each emulation chunk (the same device-independent cadence the AGT model uses), so a multi-thousand-tick period underflows within a handful of chunks and the periodic loops finish inside the headless budget deterministically. The ULPT0 underflow event is raised on the rising edge of TUNDF only (until firmware clears it by stopping/re-arming the channel), so each armed period contributes exactly one wake – the wake count is reproducible run to run.

Window: ULPT0 @ 0x40220000, ULPT1 @ 0x40220100 (stride 0x100), a single 0x200-byte block (HUM Ch 25.1 "Ultra-Low-Power Timer (ULPT)" p 1187).

Since
0.1.0

Definition in file board_periph_ulpt.c.

Enumeration Type Documentation

◆ ulpt_byte_t

enum ulpt_byte_t : uint32_t

Sub-word access constants for the byte-granular MMIO path.

Enumerator
k_ulpt_byte_mask 

Low 8 bits of a register lane.

k_ulpt_byte_bits 

Bits per byte lane.

Definition at line 132 of file board_periph_ulpt.c.

◆ ulpt_cr_bit_t

enum ulpt_cr_bit_t : uint8_t

ULPTCR control / status bit masks.

Identical to the AGT AGTCR layout (HUM Ch 25.2.1 ULPTCR p 1190, mirror of HUM Ch 24.2.6 AGTCR p 1175). TSTART/TSTOP are control, TCSTF/TUNDF are status.

Enumerator
k_ulpt_cr_tstart 

TSTART start request (bit 0, RW).

k_ulpt_cr_tcstf 

TCSTF count-status flag (bit 1, RO).

k_ulpt_cr_tstop 

TSTOP forced-stop request (bit 2, W).

k_ulpt_cr_tundf 

TUNDF underflow flag (bit 5, write-0-clear).

Definition at line 91 of file board_periph_ulpt.c.

◆ ulpt_event_t

enum ulpt_event_t : uint16_t

ULPT0 underflow ELC event the model emits (HUM Ch 19 ELC).

The RA8D2 ELC signal table places the ULPT0 underflow interrupt (ULPT0_ULPTI) at 0x080, matching k_ra8_elc_event_ulpt0_ulpti. A firmware that routes it through ra8_isr_register writes 0x080 into an IELSR slot, so the core's ICU links the raised event to that slot. ULPT1 has no distinct event in this codebase, so only channel 0 raises one (no example drives ULPT1).

Enumerator
k_ulpt_event_ch0_underflow 

ULPT0_ULPTI underflow event.

Definition at line 127 of file board_periph_ulpt.c.

◆ ulpt_geom_t

enum ulpt_geom_t : uint64_t

ULPT register window geometry (ra8_ulpt_regs.h).

Enumerator
k_ulpt_base 

ULPT0 base (FSP R_ULPT0_BASE).

k_ulpt_stride 

Bytes per channel (ULPT0 -> ULPT1).

k_ulpt_count 

ULPT0 and ULPT1.

k_ulpt_span 

Whole-block window (both channels).

Definition at line 65 of file board_periph_ulpt.c.

◆ ulpt_off_t

enum ulpt_off_t : uint64_t

ULPT per-channel register byte offsets (ra8_ulpt_regs.h).

Enumerator
k_ulpt_off_cnt 

ULPTCNT counter / reload (32-bit).

k_ulpt_off_cma 

ULPTCMA compare match A (32-bit).

k_ulpt_off_cmb 

ULPTCMB compare match B (32-bit).

k_ulpt_off_cr 

ULPTCR control / status (8-bit).

k_ulpt_off_mr1 

ULPTMR1 mode 1 (8-bit).

k_ulpt_off_mr2 

ULPTMR2 mode 2 (8-bit).

k_ulpt_off_mr3 

ULPTMR3 mode 3 (8-bit).

k_ulpt_off_ioc 

ULPTIOC I/O control (8-bit).

Definition at line 73 of file board_periph_ulpt.c.

◆ ulpt_order_t

enum ulpt_order_t : uint32_t

Per-tick order slot for the ULPT block.

Placed just above the RTC (60) and IPC (62) slots so the ULPT ticks with the other low-frequency timer/event blocks. Only the relative order matters; the absolute value is free because the block shares no state with another. A local enum keeps the value typed without editing the shared header.

Enumerator
k_ulpt_block_order 

ULPT tick / reset / report order slot.

Definition at line 60 of file board_periph_ulpt.c.

◆ ulpt_rate_t

enum ulpt_rate_t : uint32_t

Down-count step applied per emulation chunk while a channel runs.

Sized above the largest period the deep-idle examples load (ULPTCNT = 0x8000 in ulpt_demo, 0x4000 in lpm_periodic_idle) so an armed channel underflows on its first idle tick. That matters because ra8_emulator fast-forwards a Software Standby WFI one tick (one SysTick period) at a time: the ULPT underflow has to be raised within that single idle tick to be the source that cancels standby (and to pend the ULPT0_ULPTI IRQ before the firmware stops the channel), mirroring how the LOCO-clocked ULPT wakes the CPU on silicon. A period larger than the step still counts down faithfully across several chunks for a polled (non-standby) reader.

Enumerator
k_ulpt_step_per_chunk 

256 Ki ticks/chunk: example periods underflow on the first idle tick.

Definition at line 112 of file board_periph_ulpt.c.

Function Documentation

◆ internal_board_periph_ulpt_register()

RA8_INTERNAL void internal_board_periph_ulpt_register ( void )
static

Self-register the ULPT window before main runs (decentralized).

Definition at line 463 of file board_periph_ulpt.c.

References board_periph_register_block(), RA8_INTERNAL, and s_k_ulpt_block.

◆ internal_ulpt_cell_base()

RA8_INTERNAL uint64_t internal_ulpt_cell_base ( uint64_t off)
static

Byte offset of the start of the register cell that contains off.

Byte offset of the start of the register cell that contains off; this step is contained within the board periph ulpt model and uses bounded caller or module-owned storage.

Parameters
[in]offRegister or byte offset addressed by the operation.
Returns
The ulpt cell base result produced by the board periph ulpt model.
Return values
valueThe operation-specific ulpt cell base value.
Precondition
Arguments satisfy the ranges documented for ulpt cell base.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph ulpt 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 215 of file board_periph_ulpt.c.

References k_ulpt_off_cma, k_ulpt_off_cmb, k_ulpt_off_cnt, k_ulpt_off_cr, and RA8_INTERNAL.

Referenced by internal_ulpt_read().

◆ internal_ulpt_cell_value()

RA8_INTERNAL uint32_t internal_ulpt_cell_value ( const ulpt_channel_t * c,
uint64_t off )
static

Current 32-bit value of the register cell that contains off.

Current 32-bit value of the register cell that contains off; this step is contained within the board periph ulpt model and uses bounded caller or module-owned storage.

Parameters
[in]cActive controller, card, or command state processed by the operation.
[in]offRegister or byte offset addressed by the operation.
Returns
The ulpt cell value result produced by the board periph ulpt model.
Return values
valueThe operation-specific ulpt cell value value.
Precondition
Arguments satisfy the ranges documented for ulpt cell value.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph ulpt 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 170 of file board_periph_ulpt.c.

References ulpt_channel_t::cmpa, ulpt_channel_t::cmpb, ulpt_channel_t::counter, ulpt_channel_t::cr, ulpt_channel_t::ioc, k_ulpt_off_cma, k_ulpt_off_cmb, k_ulpt_off_cr, k_ulpt_off_mr1, k_ulpt_off_mr2, k_ulpt_off_mr3, ulpt_channel_t::mr1, ulpt_channel_t::mr2, ulpt_channel_t::mr3, and RA8_INTERNAL.

Referenced by internal_ulpt_read().

◆ internal_ulpt_read()

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

Read size bytes little-endian from the addressed ULPT channel.

Read size bytes little-endian from the addressed ulpt channel; this step is contained within the board periph ulpt 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 ulpt read result produced by the board periph ulpt model.
Return values
valueThe operation-specific ulpt read value.
Precondition
Arguments satisfy the ranges documented for ulpt read.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph ulpt 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 247 of file board_periph_ulpt.c.

References internal_ulpt_cell_base(), internal_ulpt_cell_value(), k_ulpt_base, k_ulpt_byte_bits, k_ulpt_byte_mask, k_ulpt_count, k_ulpt_stride, RA8_INTERNAL, and s_ulpt.

◆ internal_ulpt_report()

RA8_INTERNAL void internal_ulpt_report ( void )
static

Print each ULPT channel that underflowed at least once.

Print each ulpt channel that underflowed at least once; this step is contained within the board periph ulpt model and uses bounded caller or module-owned storage.

Precondition
Arguments satisfy the ranges documented for ulpt report.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph ulpt 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_ulpt.c.

References ulpt_channel_t::counter, ulpt_channel_t::cr, k_ulpt_count, k_ulpt_cr_tstart, priv_emu_io_errf(), RA8_INTERNAL, s_ulpt, and ulpt_channel_t::underflows.

◆ internal_ulpt_reset()

RA8_INTERNAL void internal_ulpt_reset ( void )
static

Clear every ULPT channel to its power-on state.

Clear every ulpt channel to its power-on state; this step is contained within the board periph ulpt model and uses bounded caller or module-owned storage.

Precondition
Arguments satisfy the ranges documented for ulpt reset.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph ulpt 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 419 of file board_periph_ulpt.c.

References k_ulpt_count, RA8_INTERNAL, and s_ulpt.

◆ internal_ulpt_tick()

RA8_INTERNAL void internal_ulpt_tick ( uc_engine * uc)
static

Advance every running ULPT channel one chunk.

Advance every running ulpt channel one chunk; this step is contained within the board periph ulpt model and uses bounded caller or module-owned storage.

Parameters
[in,out]ucUnicorn engine whose emulated state is read or updated.
Precondition
Arguments satisfy the ranges documented for ulpt tick.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph ulpt 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 399 of file board_periph_ulpt.c.

References internal_ulpt_tick_channel(), k_ulpt_count, and RA8_INTERNAL.

◆ internal_ulpt_tick_channel()

RA8_INTERNAL void internal_ulpt_tick_channel ( uc_engine * uc,
uint32_t ch )
static

Advance one running ULPT channel by one chunk; raise its underflow event.

Advance one running ulpt channel by one chunk; raise its underflow event; this step is contained within the board periph ulpt model and uses bounded caller or module-owned storage.

Parameters
[in,out]ucUnicorn engine whose emulated state is read or updated.
[in]chSelected channel identifier.
Precondition
Arguments satisfy the ranges documented for ulpt tick channel.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph ulpt 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 359 of file board_periph_ulpt.c.

References board_periph_icu_raise_event(), board_periph_trace(), ulpt_channel_t::counter, ulpt_channel_t::cr, k_ulpt_cr_tstart, k_ulpt_cr_tundf, k_ulpt_event_ch0_underflow, k_ulpt_step_per_chunk, priv_emu_io_errf(), RA8_INTERNAL, ulpt_channel_t::reload, s_ulpt, and ulpt_channel_t::underflows.

Referenced by internal_ulpt_tick().

◆ internal_ulpt_write()

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

Write size bytes little-endian into the addressed ULPT channel.

Write size bytes little-endian into the addressed ulpt channel; this step is contained within the board periph ulpt 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 ulpt write.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph ulpt 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 303 of file board_periph_ulpt.c.

References ulpt_channel_t::cmpa, ulpt_channel_t::cmpb, ulpt_channel_t::counter, internal_ulpt_write_cr(), ulpt_channel_t::ioc, k_ulpt_base, k_ulpt_count, k_ulpt_off_cma, k_ulpt_off_cmb, k_ulpt_off_cr, k_ulpt_off_ioc, k_ulpt_off_mr1, k_ulpt_off_mr2, k_ulpt_off_mr3, k_ulpt_stride, ulpt_channel_t::mr1, ulpt_channel_t::mr2, ulpt_channel_t::mr3, ulpt_channel_t::reload, and s_ulpt.

◆ internal_ulpt_write_cr()

RA8_INTERNAL void internal_ulpt_write_cr ( ulpt_channel_t * c,
uint8_t value )
static

Apply a write to ULPTCR: TSTART arms, TCSTF tracks it, TUNDF clears on 0.

Apply a write to ulptcr: tstart arms, tcstf tracks it, tundf clears on 0; this step is contained within the board periph ulpt model and uses bounded caller or module-owned storage.

Parameters
[in,out]cActive controller, card, or command state processed by the operation.
[in]valueRegister or payload value involved in the operation.
Precondition
Arguments satisfy the ranges documented for ulpt write cr.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph ulpt 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 280 of file board_periph_ulpt.c.

References ulpt_channel_t::cr, k_ulpt_cr_tcstf, k_ulpt_cr_tstart, k_ulpt_cr_tundf, and RA8_INTERNAL.

Referenced by internal_ulpt_write().

Variable Documentation

◆ s_k_ulpt_block

const board_periph_block_t s_k_ulpt_block
static
Initial value:
= {
.base = (uint64_t)k_ulpt_base,
.span = (uint64_t)k_ulpt_span,
.order = (uint32_t)k_ulpt_block_order,
.name = "ULPT",
}
@ k_ulpt_block_order
ULPT tick / reset / report order slot.
static RA8_INTERNAL void internal_ulpt_report(void)
Print each ULPT channel that underflowed at least once.
static RA8_INTERNAL void internal_ulpt_write(uc_engine *uc, uint64_t addr, unsigned size, uint64_t value)
Write size bytes little-endian into the addressed ULPT channel.
@ k_ulpt_span
Whole-block window (both channels).
@ k_ulpt_base
ULPT0 base (FSP R_ULPT0_BASE).
static RA8_INTERNAL void internal_ulpt_tick(uc_engine *uc)
Advance every running ULPT channel one chunk.
static RA8_INTERNAL void internal_ulpt_reset(void)
Clear every ULPT channel to its power-on state.
static RA8_INTERNAL uint64_t internal_ulpt_read(uc_engine *uc, uint64_t addr, unsigned size)
Read size bytes little-endian from the addressed ULPT channel.
-proof

ULPT register window + the down-count tick / reset / report.

Definition at line 450 of file board_periph_ulpt.c.

Referenced by internal_board_periph_ulpt_register().

◆ s_ulpt