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

DTC vector-table / TI coherency HIL proof with the M85 D-cache ENABLED. More...

#include <stddef.h>
#include <stdint.h>
#include "ra8_board_ek_ra8d2.h"
#include "ra8_boot_entry.h"
#include "ra8_cache.h"
#include "ra8_cgc.h"
#include "ra8_check.h"
#include "ra8_dtc.h"
#include "ra8_dtc_regs.h"
#include "ra8_elc.h"
#include "ra8_err.h"
#include "ra8_icu_regs.h"
#include "ra8_isr.h"
#include "ra8_log.h"
#include "ra8_mstp.h"
Include dependency graph for main.c:

Go to the source code of this file.

Enumerations

enum  dtc_coh_config_t : uint32_t {
  k_dtc_coh_baud = 115200U ,
  k_dtc_coh_buf_words = 256U ,
  k_dtc_coh_buf_bytes = 1024U ,
  k_dtc_coh_poll_limit = 100000U ,
  k_dtc_coh_sentinel = 0xA5A5A5A5U
}
 Compile-time scalar parameters for the DTC coherency self-test. More...
enum  dtc_coh_byte_t : uint8_t {
  k_dtc_coh_byte_sh = 8U ,
  k_dtc_coh_align = 32U ,
  k_dtc_coh_isr_prio = 12U
}
 Single-byte scalar constants for the self-test. More...
enum  dtc_coh_event_t : uint16_t { k_dtc_coh_event_swevt0 = 0x0CCU }
 ELC software event 0 -> ICU event number. More...
enum  dtc_coh_swevt_t : uint8_t { k_dtc_coh_swevt_index = 0U }
 ELSEGRn index fired by ra8_elc_software_trigger. More...
enum  dtc_coh_mr_field_t : uint8_t {
  k_dtc_coh_md_block = 0x2U ,
  k_dtc_coh_sz_word = 0x2U ,
  k_dtc_coh_sm_inc = 0x2U ,
  k_dtc_coh_dm_inc = 0x2U
}
 DTC Transfer-Information mode-bit field values. More...
enum  dtc_coh_mr_pos_t : uint8_t {
  k_dtc_coh_mra_md_pos = 6U ,
  k_dtc_coh_mra_sz_pos = 4U ,
  k_dtc_coh_mra_sm_pos = 2U ,
  k_dtc_coh_mrb_dm_pos = 2U ,
  k_dtc_coh_mra_byte_pos = 24U ,
  k_dtc_coh_mrb_byte_pos = 16U
}
 Bit positions inside the DTC TI MR word. More...
enum  dtc_coh_count_t : uint16_t {
  k_dtc_coh_cra_block_256 = 0x0000U ,
  k_dtc_coh_crb_one_block = 0x0001U
}
 DTC count-register values for one 256-word block. More...
enum  dtc_coh_vt_geom_t : uint32_t {
  k_dtc_coh_vt_entries = 96U ,
  k_dtc_coh_vt_align = 1024U ,
  k_dtc_coh_cra_units = 256U
}
 DTC vector-table geometry. More...

Functions

static void dtc_coh_park (void)
 Park the Cortex-M85 forever in a WFI idle loop.
static void dtc_coh_complete_cb (void *ctx, uint16_t status)
 DTC completion callback (fanned out by ra8_dtc_dispatch).
static void dtc_coh_swevt_isr (void *ctx)
 IELSR-slot ISR for the DTC-complete interrupt (masked in this app).
static void dtc_coh_setup_or_halt (void)
 Bring CGC + MSTP + ISR + ELC + SCI8 console + LEDs up.
static void dtc_coh_bringup_or_halt (void)
 Initialise the DTC and allocate its ELC-software-event activation slot.
static void dtc_coh_fill_buffers (void)
 Fill s_src with a deterministic pattern; prime s_dst.
static void dtc_coh_program_ti (void)
 Write the 16-byte TI block and point the slot's vector entry at it.
static ra8_err_t dtc_coh_arm_slot (void)
 Re-arm DTC activation on the slot (set IELSRn.DTCE).
static uint8_t dtc_coh_verify (void)
 Verify s_dst matches s_src element-by-element.
static ra8_err_t dtc_coh_run_once (uint8_t *out_ok)
 Clean src + TI, enable + trigger the DTC, then wait for the copy.
static void dtc_coh_report (uint8_t ok)
 Emit the PASS/FAIL result over VCOM and ITM, toggle an LED.
void main (void)
 Application entry: one-shot DTC descriptor-coherency proof, then WFI.

Variables

static const char * s_tag = "dtc_coherency_hil"
 Diagnostic / ITM log tag.
static const uint8_t k_dtc_coh_pass_banner [] = "dtc_coherency_hil: dtc coherent PASS\r\n"
 Deterministic one-shot HIL success banner (uart_scrape gate).
static const uint8_t k_dtc_coh_fail_banner [] = "dtc_coherency_hil: dtc coherent FAIL\r\n"
 Failure banner: the copy was wrong, absent, or timed out.
static uint32_t s_src [k_dtc_coh_buf_words]
 Source buffer – M85 writes leave it dirty in the D-cache.
static uint32_t s_dst [k_dtc_coh_buf_words]
 Destination buffer the DTC writes; the M85 must invalidate to read it.
static uint32_t s_dtc_vt [k_dtc_coh_vt_entries]
 DTC vector table – one 4-byte TI start address per IELSR slot.
static r_dtc_xfer_info_t s_dtc_ti
 The 16-byte Transfer Information block the DTC reads at activation.
static uint16_t s_dtc_slot
 IELSR slot allocated for the DTC activation = DTC vector number.

Detailed Description

DTC vector-table / TI coherency HIL proof with the M85 D-cache ENABLED.

Tag
[Ring 6 / APP] {World: S}

Single-core (Cortex-M85) hardware-in-the-loop test that proves the DTC cache-coherency wiring keeps a software-triggered DTC mem-to-mem copy correct while the M85 L1 D-cache is turned ON.

The Data Transfer Controller fetches its DTC vector table – and, one indirection on, each per-source Transfer Information (TI) block – straight from SRAM at activation. With the D-cache enabled the CPU's writes to those descriptors (the vector-table entry and the TI fields) sit dirty in cache where the engine cannot see them, so a missing clean would let the DTC fetch stale descriptors and transfer the wrong data, or nothing at all. The HAL ra8_dtc_enable() now cleans the caller-populated vector table back to RAM before DTCST = 1 (commit b80c247b); the DTC is direction-blind (like the DMAC), so this app – as the owning driver – cleans the TI block and the source buffer and invalidates the destination buffer itself.

This app builds with RA8_BOOT_ENABLE_CACHE_MPU (set in its CMakeLists.txt). With that flag the shared boot (libs/ra8_board_ek_ra8d2/src/boot/system_init.c) brings up the MPU (5 regions) + I-cache + D-cache + branch predictor before main() runs. The vector table, the TI block, and both data buffers live in MPU region 1 (0x22000000, M85-private cacheable SRAM), so the cache hazard is real on silicon.

Sequence (one-shot, then WFI):

  1. ra8_cgc_init() + ra8_mstp_init() + ra8_isr_init() + ra8_elc_init() + the SCI8 J-Link OB console + the two LEDs.
  2. ra8_dtc_init(s_dtc_vt) programmes DTCVBR; ra8_isr_register() allocates an IELSR slot for ELC software event 0 (its slot index is the DTC activation-source vector number).
  3. Fill s_src with a deterministic pattern (M85 stores -> dirty in the D-cache) and s_dst with a sentinel so a no-op copy fails the verify.
  4. Write the 16-byte TI block (a 256-word, 32-bit, increment-both block copy) and point s_dtc_vt[slot] at it – both more dirty CPU writes.
  5. ra8_cache_dcache_clean_by_addr(s_src) and ... (s_dtc_ti) (the app owns the TI + source); ra8_dtc_enable() (the HAL cleans the vector table, then DTCST = 1); arm IELSRn.DTCE; fire ELC software event 0.
  6. Wait for the copy to land in SRAM by invalidating s_dst and re-reading it each poll iteration (the read therefore observes RAM, not the stale sentinel still cached) until s_dst == s_src (bounded). This poll IS the completion gate and the coherency proof: if any descriptor clean were missing on silicon the DTC would fetch a stale entry, the copy would be wrong/absent, and the poll would time out.
  7. PASS -> emit "dtc_coherency_hil: dtc coherent PASS\r\n" over VCOM and the same verdict over ITM (ra8_log_info), toggle LED1. Mismatch / timeout -> a distinct ... FAIL line (never containing "PASS") + LED2. Either way the core parks in WFI so ra8_emulator's idle-stop terminates the run.

The completion IRQ is intentionally left masked (the app never calls ra8_isr_globals_enable): the registered slot + DTCE still activate the DTC, the app simply polls for the result instead of taking the interrupt, which avoids the completion ISR (which writes DTCSTS) racing the in-flight copy.

ra8_emulator note (off-target path)
tools/ra8_emulator DOES model the DTC transfer engine (board_periph_dtc.c): the ELC software-event trigger reads the vector-table entry at DTCVBR + slot*4, fetches the TI, and actually MOVES the bytes in emulated memory, so the real ra8_dtc + ELC path runs off-target and the copy verifies. ra8_emulator's memory is byte-exact and it does not model the L1 D-cache, so the clean / invalidate calls are exercised (the line-size and barrier logic run) but have no caching effect, and the poll falls through on its first iteration. The cache hazard this app guards against is only observable on real silicon. RA8_OFF_TARGET is a host-unit-test define and is NOT set for the ARM cross-build that ra8_emulator executes, so there is nothing to #ifdef here.

Bare EK-RA8D2 only – no shields or external transceivers.

Author
Brighton Sikarskie
Date
2026-06-29
Since
0.1.0

Definition in file main.c.

Enumeration Type Documentation

◆ dtc_coh_byte_t

enum dtc_coh_byte_t : uint8_t

Single-byte scalar constants for the self-test.

The pattern xor-shift, the D-cache line size, and the NVIC priority of the (masked) DTC-activation slot.

Since
0.1.0
Enumerator
k_dtc_coh_byte_sh 

Source-pattern shift (i ^ (i >> 8)).

k_dtc_coh_align 

D-cache line size (bytes).

k_dtc_coh_isr_prio 

NVIC priority for the DTC-complete slot.

Definition at line 125 of file main.c.

◆ dtc_coh_config_t

enum dtc_coh_config_t : uint32_t

Compile-time scalar parameters for the DTC coherency self-test.

Groups the console baud, buffer geometry, the destination sentinel, and the bounded completion-poll limit.

Since
0.1.0
Enumerator
k_dtc_coh_baud 

VCOM console line rate (8N1).

k_dtc_coh_buf_words 

32-bit words per buffer (256 x 4).

k_dtc_coh_buf_bytes 

Bytes copied per pass (>= 256, 1 KiB).

k_dtc_coh_poll_limit 

Bounded wait for the copy to land in RAM.

k_dtc_coh_sentinel 

Destination pre-fill; no-op copy fails.

Definition at line 110 of file main.c.

◆ dtc_coh_count_t

enum dtc_coh_count_t : uint16_t

DTC count-register values for one 256-word block.

HUM Ch 18.2.7 "CRA" (p 790): in block mode CRAH/CRAL hold the block size and "the transfer count is ... 256 when the set value is 0x00". HUM Ch 18.2.8 "CRB" (p 791): CRB is the block count.

Since
0.1.0
Enumerator
k_dtc_coh_cra_block_256 

CRAH = CRAL = 0 => 256-unit block.

k_dtc_coh_crb_one_block 

CRB = 1 => one block per pass.

Definition at line 194 of file main.c.

◆ dtc_coh_event_t

enum dtc_coh_event_t : uint16_t

ELC software event 0 -> ICU event number.

HUM Table 19.3 (p 824) row "0x0CC | ELC | ELC_SWEVT0 | Software event 0": ra8_elc_software_trigger(0) raises this event; routed to an IELSR slot with DTCE = 1 it activates the DTC. App-local (the shared ra8_elc_event_t table only carries events the HAL itself wires), mirroring dtc_transfer_demo.

Since
0.1.0
Enumerator
k_dtc_coh_event_swevt0 

ELC software event 0 (HUM Table 19.3).

Definition at line 141 of file main.c.

◆ dtc_coh_mr_field_t

enum dtc_coh_mr_field_t : uint8_t

DTC Transfer-Information mode-bit field values.

HUM Ch 18.2.2 "MRA" (p 786) and 18.2.3 "MRB" (p 787): a block-mode, 32-bit-word, increment-both copy. 2 selects "increment" for SM/DM, "32-bit word" for SZ, and "block transfer" for MD.

Since
0.1.0
Enumerator
k_dtc_coh_md_block 

MRA.MD[7:6] = 10b: block transfer mode.

k_dtc_coh_sz_word 

MRA.SZ[5:4] = 10b: 32-bit word units.

k_dtc_coh_sm_inc 

MRA.SM[3:2] = 10b: increment SAR.

k_dtc_coh_dm_inc 

MRB.DM[3:2] = 10b: increment DAR.

Definition at line 163 of file main.c.

◆ dtc_coh_mr_pos_t

enum dtc_coh_mr_pos_t : uint8_t

Bit positions inside the DTC TI MR word.

HUM Figure 18.4 (p 799) lays the first TI long-word out as MR[31:24] = MRA, MR[23:16] = MRB, MR[15:8] = MRC, MR[7:0] = reserved.

Since
0.1.0
Enumerator
k_dtc_coh_mra_md_pos 

MRA.MD field position.

k_dtc_coh_mra_sz_pos 

MRA.SZ field position.

k_dtc_coh_mra_sm_pos 

MRA.SM field position.

k_dtc_coh_mrb_dm_pos 

MRB.DM field position.

k_dtc_coh_mra_byte_pos 

MRA byte offset within MR.

k_dtc_coh_mrb_byte_pos 

MRB byte offset within MR.

Definition at line 177 of file main.c.

◆ dtc_coh_swevt_t

enum dtc_coh_swevt_t : uint8_t

ELSEGRn index fired by ra8_elc_software_trigger.

ELSEGR0 generates ELC software event 0 (0x0CC).

Since
0.1.0
Enumerator
k_dtc_coh_swevt_index 

ELSEGR0 -> ELC_SWEVT0 (0x0CC).

Definition at line 151 of file main.c.

◆ dtc_coh_vt_geom_t

enum dtc_coh_vt_geom_t : uint32_t

DTC vector-table geometry.

HUM Ch 18.3.1 (p 796) + Figure 18.3 (p 798): DTCVBR points at a table of 4-byte entries, one per interrupt vector number; entry n (at DTCVBR + n*4) holds the 16-byte-aligned start address of that source's TI. DTCVBR itself must be 1 KiB-aligned (HUM Ch 18.2.2).

Since
0.1.0
Enumerator
k_dtc_coh_vt_entries 

One pointer per IELSR slot 0..95.

k_dtc_coh_vt_align 

DTCVBR 1 KiB alignment (HUM 18.2.2).

k_dtc_coh_cra_units 

Units per block when CRAH/CRAL = 0.

Definition at line 208 of file main.c.

Function Documentation

◆ dtc_coh_arm_slot()

ra8_err_t dtc_coh_arm_slot ( void )
staticnodiscard

Re-arm DTC activation on the slot (set IELSRn.DTCE).

The DTC activates from an IELSR slot only when its DTCE bit is set; the read-modify-write preserves the IELS event field that ra8_isr_register wrote.

Returns
k_ra8_ok on success, k_ra8_err_hw_error if the slot accessor returned NULL.
Return values
k_ra8_okDTCE is set for the slot.
k_ra8_err_hw_errorThe IELSR accessor returned NULL.
Precondition
s_dtc_slot was assigned by ra8_isr_register.
Called single-threaded with the completion IRQ masked.
Postcondition
IELSRn.DTCE for the slot reads 1.
No other IELSR field is modified.
Note
Not thread-safe.
Since
0.1.0

Definition at line 539 of file main.c.

References k_ra8_err_hw_error, k_ra8_ielsr_dtce_mask, k_ra8_ok, ra8_icu_ielsr(), and s_dtc_slot.

Referenced by dtc_coh_run_once().

◆ dtc_coh_bringup_or_halt()

void dtc_coh_bringup_or_halt ( void )
static

Initialise the DTC and allocate its ELC-software-event activation slot.

Programmes DTCVBR to s_dtc_vt, attaches the (masked) completion callback, and allocates an IELSR slot for ELC software event 0 whose index is the DTC activation-source vector number. Halts on any failure or an out-of-range slot.

Returns
Nothing.
Precondition
dtc_coh_setup_or_halt has run (ISR + ELC initialised).
Global IRQs are still masked (boot leaves PRIMASK set).
Postcondition
DTCVBR == s_dtc_vt and s_dtc_slot < k_dtc_coh_vt_entries.
On any failure the function does not return (parks in WFI).
Note
Single-threaded init context; not thread-safe.
Since
0.1.0

Definition at line 433 of file main.c.

References dtc_coh_complete_cb(), dtc_coh_park(), dtc_coh_swevt_isr(), k_dtc_coh_event_swevt0, k_dtc_coh_isr_prio, k_dtc_coh_vt_entries, k_ra8_ok, ra8_dtc_attach_handler(), ra8_dtc_init(), ra8_isr_register(), s_dtc_slot, and s_dtc_vt.

Referenced by main().

◆ dtc_coh_complete_cb()

void dtc_coh_complete_cb ( void * ctx,
uint16_t status )
static

DTC completion callback (fanned out by ra8_dtc_dispatch).

Registered for symmetry with the activation slot; it does not run in this app because the completion IRQ is left globally masked (the app polls).

Parameters
[in]ctxUnused registration context.
[in]statusUnused DTCSTS snapshot at completion.
Returns
Nothing.
Precondition
Attached via ra8_dtc_attach_handler.
Reached only if global IRQs are enabled (they are not, here).
Postcondition
No application state is modified.
No hardware register is modified by this callback.
Note
ISR context; not re-entrant.
Since
0.1.0

Definition at line 341 of file main.c.

Referenced by dtc_coh_bringup_or_halt().

◆ dtc_coh_fill_buffers()

void dtc_coh_fill_buffers ( void )
static

Fill s_src with a deterministic pattern; prime s_dst.

s_src[i] = i ^ (i >> 8) are M85 stores that sit dirty in the D-cache. s_dst is primed with a sentinel distinct from every source word so a copy that never lands fails the verify.

MC/DC:
Single counting loop, no compound decision; only the implicit loop bound. No N+1 vectors required.
Returns
Nothing.
Precondition
Buffers are statically allocated and 32-byte aligned.
Called single-threaded before the DTC is armed.
Postcondition
Every word of s_src holds the pattern.
Every word of s_dst holds k_dtc_coh_sentinel.
Note
Not thread-safe.
Since
0.1.0

Definition at line 474 of file main.c.

References k_dtc_coh_buf_words, k_dtc_coh_byte_sh, k_dtc_coh_sentinel, s_dst, and s_src.

Referenced by main().

◆ dtc_coh_park()

void dtc_coh_park ( void )
static

Park the Cortex-M85 forever in a WFI idle loop.

Reached after the one-shot banner has been emitted (pass or fail), or on a fatal init failure. The WFI lets ra8_emulator's idle detector stop the run cleanly and models the low-power posture on silicon.

Returns
This function never returns.
Note
The core stays asleep between (unconfigured) wake events.
Precondition
The self-test verdict has been emitted, or a fatal error occurred.
No further forward progress is required of the M85.
Postcondition
The core makes no further architectural progress.
No further bus activity is generated.
Note
Not thread-safe; terminal sink.
Since
0.1.0

Definition at line 315 of file main.c.

Referenced by dtc_coh_bringup_or_halt(), dtc_coh_setup_or_halt(), and main().

◆ dtc_coh_program_ti()

void dtc_coh_program_ti ( void )
static

Write the 16-byte TI block and point the slot's vector entry at it.

Field encoding per HUM Figure 18.4 (p 799): MR holds MRA/MRB/MRC, then SAR, DAR, CRB, CRA – a 256-word, 32-bit, increment-both block copy of s_src into s_dst. s_dtc_vt[s_dtc_slot] is set to the TI start address (bit 0 = privilege attribution, left 0 = privileged). Both the TI fields and the vector-table entry are CPU writes that land dirty in the D-cache.

MC/DC:
Straight-line assignment – no decision points.
Returns
Nothing.
Precondition
s_src / s_dst are populated and s_dtc_slot is valid.
Postcondition
s_dtc_ti describes the block copy and s_dtc_vt[s_dtc_slot] points at it (both possibly still dirty in cache until cleaned).
Note
Not thread-safe. SRAM writes only (no MMIO).
Since
0.1.0

Definition at line 503 of file main.c.

References k_dtc_coh_cra_block_256, k_dtc_coh_crb_one_block, k_dtc_coh_dm_inc, k_dtc_coh_md_block, k_dtc_coh_mra_byte_pos, k_dtc_coh_mra_md_pos, k_dtc_coh_mra_sm_pos, k_dtc_coh_mra_sz_pos, k_dtc_coh_mrb_byte_pos, k_dtc_coh_mrb_dm_pos, k_dtc_coh_sm_inc, k_dtc_coh_sz_word, s_dst, s_dtc_slot, s_dtc_ti, s_dtc_vt, and s_src.

Referenced by main().

◆ dtc_coh_report()

void dtc_coh_report ( uint8_t ok)
static

Emit the PASS/FAIL result over VCOM and ITM, toggle an LED.

Parameters
[in]okNon-zero if the coherency check passed.
Returns
Nothing.
Precondition
The console has been initialised by dtc_coh_setup_or_halt.
Both LEDs have been initialised.
Postcondition
Exactly one terminal banner has been written and flushed to VCOM.
The matching result line has been emitted over ITM.
Note
Not thread-safe; single-shot reporting.
Since
0.1.0

Definition at line 686 of file main.c.

References k_dtc_coh_fail_banner, k_dtc_coh_pass_banner, k_ra8_board_led1, k_ra8_board_led2, ra8_board_led_toggle(), ra8_board_uart_console_flush(), ra8_board_uart_console_write(), ra8_log_info, and s_tag.

Referenced by main().

◆ dtc_coh_run_once()

ra8_err_t dtc_coh_run_once ( uint8_t * out_ok)
staticnodiscard

Clean src + TI, enable + trigger the DTC, then wait for the copy.

Implements the descriptor + data coherency pattern:

  1. ra8_cache_dcache_clean_by_addr(s_src) and ... (s_dtc_ti) flush the dirty source bytes and TI fields to SRAM so the DTC reads live descriptors and data (the app owns the TI + source; the HAL owns the vector table).
  2. ra8_dtc_enable() cleans the caller-populated vector table back to RAM (commit b80c247b), then sets DTCST = 1.
  3. dtc_coh_arm_slot sets IELSRn.DTCE so the event activates the DTC.
  4. ra8_elc_software_trigger fires ELC software event 0, activating the DTC.
  5. Poll for completion by invalidating s_dst and re-verifying each iteration – the read therefore observes RAM, not the dirty sentinel still cached, so the loop ends exactly when the DTC's copy has fully landed (bounded by k_dtc_coh_poll_limit). This poll is both the completion gate and the coherency proof: a stale descriptor would leave s_dst wrong and time the loop out.
Parameters
[out]out_ok1 if the destination matched the source, else 0.
Returns
ra8_err_t error code.
Return values
k_ra8_okThe copy landed and matched within the poll bound.
k_ra8_err_null_ptrout_ok was NULL.
k_ra8_err_hw_errorA cache-maintenance op or the IELSR accessor failed.
k_ra8_err_hw_timeoutThe copy never matched within the poll bound.
(other)Propagated ra8_dtc_enable / ra8_elc_software_trigger error.
Precondition
Buffers are filled and the TI + vector entry are programmed.
Global IRQs are masked (the completion IRQ is not taken).
Postcondition
On k_ra8_ok s_dst holds the source pattern in SRAM and its cache lines are invalid.
*out_ok reflects the post-copy comparison.
Note
Not thread-safe; single-shot init-context use.
Since
0.1.0

Definition at line 622 of file main.c.

References dtc_coh_arm_slot(), dtc_coh_verify(), k_dtc_coh_poll_limit, k_dtc_coh_swevt_index, k_ra8_err_hw_error, k_ra8_err_hw_timeout, k_ra8_ok, ra8_cache_dcache_clean_by_addr(), ra8_cache_dcache_invalidate_by_addr(), RA8_CHECK_NULL_PTR, ra8_dtc_enable(), ra8_elc_software_trigger(), s_dst, s_dtc_ti, s_src, and s_tag.

Referenced by main().

◆ dtc_coh_setup_or_halt()

void dtc_coh_setup_or_halt ( void )
static

Bring CGC + MSTP + ISR + ELC + SCI8 console + LEDs up.

Panic-halts.

The DTC0 module clock shares MSTPA22 with DMAC0 and is ungated by the ra8_dtc driver via ra8_mstp. The SCI8 J-Link OB console (TXD8 = PD_02 / RXD8 = PD_03 @ 115200 8N1) comes up through the BSP console API. ELC + ISR are needed to allocate the DTC activation slot and fire the software event.

Returns
Nothing.
Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has enabled the MPU + caches (RA8_BOOT_ENABLE_CACHE_MPU).
Postcondition
On success CGC, MSTP, ISR, ELC, the console and both LEDs are ready.
On any failure the function does not return (parks in WFI).
Note
Single-threaded init context; not thread-safe.
Since
0.1.0

Definition at line 390 of file main.c.

References dtc_coh_park(), k_dtc_coh_baud, k_ra8_board_led1, k_ra8_board_led2, k_ra8_ok, ra8_board_led_init(), ra8_board_uart_console_init(), ra8_cgc_init(), ra8_elc_init(), ra8_isr_init(), and ra8_mstp_init().

Referenced by main().

◆ dtc_coh_swevt_isr()

void dtc_coh_swevt_isr ( void * ctx)
static

IELSR-slot ISR for the DTC-complete interrupt (masked in this app).

Routes the slot event through the HAL dispatch into dtc_coh_complete_cb. Present so ra8_isr_register has a valid handler; it does not run because the completion IRQ stays globally masked.

Parameters
[in]ctxUnused registration context.
Returns
Nothing.
Precondition
Registered via ra8_isr_register for ELC software event 0.
Reached only if global IRQs are enabled (they are not, here).
Postcondition
ra8_dtc_dispatch has run at most once per entry.
No application state is modified.
Note
ISR context; not re-entrant.
Since
0.1.0

Definition at line 366 of file main.c.

References ra8_dtc_dispatch().

Referenced by dtc_coh_bringup_or_halt().

◆ dtc_coh_verify()

uint8_t dtc_coh_verify ( void )
staticnodiscard

Verify s_dst matches s_src element-by-element.

Must run on an invalidated s_dst so the reads miss the cache and fetch the DTC-written bytes from SRAM. A non-empty mismatch (sentinel still present, or a stale-descriptor partial copy) returns 0.

MC/DC:
One atomic condition s_dst[i] != s_src[i] x 2 vectors: all-match (steady state, this run) and one mismatch (the cache-hazard regression that occurs on silicon if a descriptor clean is omitted – the DTC fetches a stale entry and the copy is wrong/absent).
Returns
1 if all words equal, 0 otherwise.
Return values
1Buffers identical – copy + cache maintenance coherent.
0At least one word differs.
Precondition
Both buffers are filled and s_dst lines have been invalidated.
Postcondition
The return value is exactly 0 or 1.
Neither buffer is modified.
Note
Not thread-safe.
Since
0.1.0

Definition at line 575 of file main.c.

References k_dtc_coh_buf_words, s_dst, and s_src.

Referenced by dtc_coh_run_once().

◆ main()

void main ( void )

Application entry: one-shot DTC descriptor-coherency proof, then WFI.

The application entry point Reset_Handler hands control to.

Brings up the clock tree, MSTP, ISR/ELC, and the VCOM console, programs a software-triggered DTC block copy, runs it with the L1 caches + MPU enabled by the shared boot (RA8_BOOT_ENABLE_CACHE_MPU), emits the matching PASS / FAIL banner over the console and ra8_log, then parks in WFI.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit enabled the MPU + caches via RA8_BOOT_ENABLE_CACHE_MPU.
Postcondition
Exactly one PASS/FAIL banner is emitted, then the core parks.
The core ends in WFI so ra8_emulator's idle-stop terminates the run.
Note
Single-threaded; the completion IRQ is left masked and the result polled.
Since
0.1.0

Definition at line 719 of file main.c.

References dtc_coh_bringup_or_halt(), dtc_coh_fill_buffers(), dtc_coh_park(), dtc_coh_program_ti(), dtc_coh_report(), dtc_coh_run_once(), dtc_coh_setup_or_halt(), k_ra8_ok, ra8_log_info, ra8_log_init(), and s_tag.

Variable Documentation

◆ k_dtc_coh_fail_banner

const uint8_t k_dtc_coh_fail_banner[] = "dtc_coherency_hil: dtc coherent FAIL\r\n"
static

Failure banner: the copy was wrong, absent, or timed out.

Distinct from the PASS banner and free of "PASS"; caught by the hil.conf HIL_EXPECT_NEGATIVE alternation.

Since
0.1.0

Definition at line 239 of file main.c.

Referenced by dtc_coh_report().

◆ k_dtc_coh_pass_banner

const uint8_t k_dtc_coh_pass_banner[] = "dtc_coherency_hil: dtc coherent PASS\r\n"
static

Deterministic one-shot HIL success banner (uart_scrape gate).

Emitted only on the all-pass path over the VCOM console. The trailing CRLF terminates the line on the wire; the HIL gate matches the text exactly. Contains "PASS" and is not a substring of the FAIL banner.

Warning
Do not modify; hil.conf HIL_EXPECT matches it verbatim.
Since
0.1.0

Definition at line 230 of file main.c.

Referenced by dtc_coh_report().

◆ s_dst

uint32_t s_dst[k_dtc_coh_buf_words]
static

Destination buffer the DTC writes; the M85 must invalidate to read it.

1 KiB, 32-byte aligned and a whole number of cache lines so ra8_cache_dcache_invalidate_by_addr drops exactly the buffer's lines. Lives in MPU region 1 (cacheable SRAM).

Warning
Stale cached lines here are the exact hazard this app proves.
Since
0.1.0

Definition at line 261 of file main.c.

◆ s_dtc_slot

uint16_t s_dtc_slot
static

IELSR slot allocated for the DTC activation = DTC vector number.

Assigned by ra8_isr_register; indexes both the IELSR table and the s_dtc_vt vector table.

Note
Written once during bring-up, then read-only.
Since
0.1.0

Definition at line 295 of file main.c.

◆ s_dtc_ti

r_dtc_xfer_info_t s_dtc_ti
static

The 16-byte Transfer Information block the DTC reads at activation.

Lives in MPU region 1 (cacheable SRAM), 32-byte aligned (one cache line; satisfies the 16-byte TI requirement, HUM Ch 18.3.1 p 796). The CPU writes to its fields are dirty in cache; the app cleans it before activation so the DTC reads the live descriptor from RAM.

Warning
The DTC reads this from RAM; it must be cleaned before activation.
Since
0.1.0

Definition at line 285 of file main.c.

◆ s_dtc_vt

uint32_t s_dtc_vt[k_dtc_coh_vt_entries]
static

DTC vector table – one 4-byte TI start address per IELSR slot.

Lives in MPU region 1 (cacheable SRAM). The CPU write to s_dtc_vt[slot] is dirty in cache; ra8_dtc_enable() cleans this region back to RAM before DTCST = 1 so the DTC fetches the live entry, not a stale line – the wiring this app validates.

Warning
1 KiB-aligned: DTCVBR requires the lower 10 bits be 0.
Since
0.1.0

Definition at line 273 of file main.c.

◆ s_src

uint32_t s_src[k_dtc_coh_buf_words]
static

Source buffer – M85 writes leave it dirty in the D-cache.

1 KiB, 32-byte (D-cache line) aligned and an exact whole number of lines, so ra8_cache_dcache_clean_by_addr cleans exactly the buffer with no partial-line spill. Lives in MPU region 1 (cacheable SRAM).

Warning
The DTC reads this from RAM; it must be cleaned before activation.
Since
0.1.0

Definition at line 250 of file main.c.

◆ s_tag

const char* s_tag = "dtc_coherency_hil"
static

Diagnostic / ITM log tag.

Definition at line 101 of file main.c.