|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
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"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. | |
DTC vector-table / TI coherency HIL proof with the M85 D-cache ENABLED.
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):
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.
Bare EK-RA8D2 only – no shields or external transceivers.
Definition in file main.c.
| 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.
| 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. |
| 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.
| 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.
| 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. |
| 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.
| Enumerator | |
|---|---|
| k_dtc_coh_event_swevt0 | ELC software event 0 (HUM Table 19.3). |
| 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.
| 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.
| enum dtc_coh_swevt_t : uint8_t |
ELSEGRn index fired by ra8_elc_software_trigger.
ELSEGR0 generates ELC software event 0 (0x0CC).
| Enumerator | |
|---|---|
| k_dtc_coh_swevt_index | ELSEGR0 -> ELC_SWEVT0 (0x0CC). |
| 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).
| 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. |
|
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.
| k_ra8_ok | DTCE is set for the slot. |
| k_ra8_err_hw_error | The IELSR accessor returned NULL. |
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().
|
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.
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().
|
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).
| [in] | ctx | Unused registration context. |
| [in] | status | Unused DTCSTS snapshot at completion. |
Definition at line 341 of file main.c.
Referenced by dtc_coh_bringup_or_halt().
|
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.
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().
|
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.
Definition at line 315 of file main.c.
Referenced by dtc_coh_bringup_or_halt(), dtc_coh_setup_or_halt(), and main().
|
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.
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().
|
static |
Emit the PASS/FAIL result over VCOM and ITM, toggle an LED.
| [in] | ok | Non-zero if the coherency check passed. |
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().
|
staticnodiscard |
Clean src + TI, enable + trigger the DTC, then wait for the copy.
Implements the descriptor + data coherency pattern:
| [out] | out_ok | 1 if the destination matched the source, else 0. |
| k_ra8_ok | The copy landed and matched within the poll bound. |
| k_ra8_err_null_ptr | out_ok was NULL. |
| k_ra8_err_hw_error | A cache-maintenance op or the IELSR accessor failed. |
| k_ra8_err_hw_timeout | The copy never matched within the poll bound. |
| (other) | Propagated ra8_dtc_enable / ra8_elc_software_trigger error. |
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().
|
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.
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().
|
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.
| [in] | ctx | Unused registration context. |
Definition at line 366 of file main.c.
References ra8_dtc_dispatch().
Referenced by dtc_coh_bringup_or_halt().
|
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.
| 1 | Buffers identical – copy + cache maintenance coherent. |
| 0 | At least one word differs. |
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().
| 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.
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.
|
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.
Definition at line 239 of file main.c.
Referenced by dtc_coh_report().
|
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.
Definition at line 230 of file main.c.
Referenced by dtc_coh_report().
|
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).
|
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.
|
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.
|
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.
|
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).