|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
SYSC register-write-protection (PRCR) model. More...
#include <stdint.h>#include <stdio.h>#include "board_periph_block.h"#include "board_periph_prcr_internal.h"#include "emu_host_io_internal.h"#include "ra8_attributes.h"Go to the source code of this file.
Data Structures | |
| struct | prcr_state_t |
| Live PRCR group-unlock mask, and the counters behind the report. More... | |
Enumerations | |
| enum | prcr_geom_t : uint64_t { k_prcr_base = 0x4001E3FAUL , k_prcr_span = 0x2UL } |
| PRCR window geometry (HUM Ch 13.2.1 p 522). More... | |
| enum | prcr_mask_t : uint16_t { k_prcr_key_mask = 0xFF00U , k_prcr_key_value = 0xA500U , k_prcr_group_mask = 0x003BU } |
| PRCR field masks (HUM Ch 13.2.1 p 522). More... | |
| enum | prcr_order_t : uint32_t { k_prcr_block_order = 170U } |
| Per-tick order slot for the PRCR block (relative order). More... | |
Functions | |
| static void | internal_prcr_reset (void) |
| Return PRCR to its power-on state: every group locked. | |
| bool | priv_board_prcr_group_unlocked (uint16_t group_mask) |
Report whether every bit in group_mask is currently unlocked. | |
| static uint64_t | internal_prcr_read (uc_engine *uc, uint64_t addr, unsigned size) |
| MMIO read stub – never called for an observe-only block. | |
| static void | internal_prcr_write (uc_engine *uc, uint64_t addr, unsigned size, uint64_t value) |
| Snoop a PRCR write and update the retained group mask. | |
| static void | internal_prcr_report (void) |
| End-of-run PRCR section: unlock traffic and any key mistakes. | |
| static void | internal_prcr_block_register (void) |
| Register the PRCR block before main (host constructor). | |
Variables | |
| static prcr_state_t | s_prcr |
| static const board_periph_block_t | s_k_prcr_block |
| PRCR block descriptor (observe-only: snoops, does not own). | |
SYSC register-write-protection (PRCR) model.
Models the RA8D2 Protect Register (PRCR) at 0x4001_E3FA – HUM Ch 13 "Register Write Protection Function" p 520-523. PRCR gates writes to whole families of SYSC-adjacent registers; reads are never gated. A write to a protected register while its group bit is 0 is silently discarded by the hardware: no bus fault, no status flag, the register simply keeps its old value.
That silence is exactly what makes the protection worth modelling. Issue #131 was a driver (ra8_bkup.c) that wrote the entire VBATT backup register file with PRCR locked. On silicon every write vanished and bkup_survival_demo reported rw=BAD; in the emulator, which modelled no protection at all, the same firmware reported rw=ok. The emulator passed where the bench failed, which is the defect this block removes.
The block is observe-only: it snoops the PRCR window so the sparse fallback continues to serve reads and record writes exactly as before, while the protected blocks consult priv_board_prcr_group_unlocked to decide whether to accept a store. Bench-confirmed on an EK-RA8D2 by J-Link: writing VBTBKR0 with PRCR locked reads back 0x00000000; after PRCR = 0xA502 the identical write reads back intact.
Scope: the mask is maintained for every group, but only the blocks that have been silicon-verified against it consult it (currently the VBATT backup block, PRC1). Wiring the remaining protected windows – CGC under PRC0, the PVD registers under PRC3 – is deliberately left to the change that verifies each on hardware, so no gate is tightened on theory alone.
Definition in file board_periph_prcr.c.
| enum prcr_geom_t : uint64_t |
PRCR window geometry (HUM Ch 13.2.1 p 522).
| Enumerator | |
|---|---|
| k_prcr_base | PRCR_S: SYSC base 0x4001_E000 + 0x3FA. |
| k_prcr_span | One 16-bit register. |
Definition at line 47 of file board_periph_prcr.c.
| enum prcr_mask_t : uint16_t |
PRCR field masks (HUM Ch 13.2.1 p 522).
| Enumerator | |
|---|---|
| k_prcr_key_mask | PRKEY[7:0] lives in bits 15:8. |
| k_prcr_key_value | Mandatory 0xA5 write key. |
| k_prcr_group_mask | PRC0/1/3/4/5; bit 2 + 7:6 reserved. |
Definition at line 53 of file board_periph_prcr.c.
| enum prcr_order_t : uint32_t |
Per-tick order slot for the PRCR block (relative order).
| Enumerator | |
|---|---|
| k_prcr_block_order | Just before the VBATT-backup block. |
Definition at line 60 of file board_periph_prcr.c.
|
static |
Register the PRCR block before main (host constructor).
Definition at line 192 of file board_periph_prcr.c.
References board_periph_register_block(), RA8_INTERNAL, and s_k_prcr_block.
|
static |
MMIO read stub – never called for an observe-only block.
The sparse fallback answers PRCR reads (the block snoops rather than owns its window), so this exists only to satisfy the descriptor's required read slot.
| [in,out] | uc | Unicorn engine whose emulated state is read or updated. |
| [in] | addr | Guest address involved in the operation. |
| [in] | size | Size of the requested region or access in bytes. |
| value | The operation-specific prcr read value. |
Definition at line 111 of file board_periph_prcr.c.
References RA8_INTERNAL.
|
static |
End-of-run PRCR section: unlock traffic and any key mistakes.
End-of-run prcr section: unlock traffic and any key mistakes; this step is contained within the board periph prcr model and uses bounded caller or module-owned storage.
Definition at line 161 of file board_periph_prcr.c.
References priv_emu_io_errf(), RA8_INTERNAL, and s_prcr.
|
static |
Return PRCR to its power-on state: every group locked.
HUM Ch 13.2.1 p 522 gives PRCR a reset value of 0x0000, so no group is write-enabled until firmware presents the key.
Definition at line 85 of file board_periph_prcr.c.
References RA8_INTERNAL, and s_prcr.
|
static |
Snoop a PRCR write and update the retained group mask.
HUM Ch 13.2.1 p 522: "PRKEY[7:0] ... Write 0xA5 to this bit field to permit the write to the PRCn bits." A write whose key byte is not 0xA5 is discarded and leaves the mask untouched – modelled here so firmware that forgets the key gets the silicon result (no unlock) rather than a free one.
| [in,out] | uc | Unicorn engine whose emulated state is read or updated. |
| [in] | addr | Guest address involved in the operation. |
| [in] | size | Size of the requested region or access in bytes. |
| [in] | value | Register or payload value involved in the operation. |
Definition at line 137 of file board_periph_prcr.c.
References k_prcr_group_mask, k_prcr_key_mask, k_prcr_key_value, and s_prcr.
| bool priv_board_prcr_group_unlocked | ( | uint16_t | group_mask | ) |
Report whether every bit in group_mask is currently unlocked.
Reflects the last PRCR write that carried the correct 0xA5 key. A write with a wrong key is ignored by the hardware and by this model, so the mask keeps its previous value.
| [in] | group_mask | One or more k_board_prcr_grp* bits. |
true when all requested groups are write-enabled. | true | Every bit in group_mask is set in the live PRCR mask. |
| false | At least one requested group is still locked. |
group_mask names only bits defined by board_prcr_group_t. Definition at line 90 of file board_periph_prcr.c.
References RA8_PRIV, and s_prcr.
Referenced by internal_bkup_write(), and internal_pdctr_write().
|
static |
PRCR block descriptor (observe-only: snoops, does not own).
Definition at line 178 of file board_periph_prcr.c.
Referenced by internal_prcr_block_register().
|
static |
Definition at line 73 of file board_periph_prcr.c.
Referenced by internal_prcr_report(), internal_prcr_reset(), internal_prcr_write(), and priv_board_prcr_group_unlocked().