ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
board_periph_sram.c
Go to the documentation of this file.
1
33
34#include <stdint.h>
35#include <stdio.h>
36
37#include "board_periph_block.h"
39
44typedef enum : uint64_t {
45 k_sram_base = 0x40002000ULL,
46 k_sram_span = 0x100ULL,
47 k_sram_off_cr0 = 0x10ULL,
48 k_sram_off_cr3 = 0x1CULL,
49 k_sram_off_esr = 0x40ULL,
50 k_sram_off_esclr = 0x48ULL,
51 k_sram_off_ear0 = 0x50ULL,
53
68
70static const uint32_t s_k_sram_bank_data_off[k_sram_bank_count] = {
71 0x00000000U, /* SRAM0 @ 0x22000000 */
72 0x00080000U, /* SRAM1 @ 0x22080000 */
73 0x00100000U, /* SRAM2 @ 0x22100000 */
74 0x00180000U, /* SRAM3 @ 0x22180000 */
75};
76
78typedef struct {
80 uint16_t esr;
82 uint32_t latch_count;
84
86
99RA8_INTERNAL static uint16_t internal_sram_esr_bit(uint32_t bank, uint32_t slot)
100{
101 const uint32_t pos = (k_sram_slots_bank * bank) + slot;
102 return (uint16_t)((uint16_t)1U << (uint16_t)pos);
103}
104
116RA8_INTERNAL static void internal_sram_shadow_store(uint64_t off, unsigned size, uint64_t value)
117{
118 for (unsigned i = 0U; i < size; ++i) {
119 const uint64_t at = off + (uint64_t)i;
120 if (at < (uint64_t)k_sram_span) {
121 s_sram.shadow[at] = (uint8_t)(value >> (k_sram_byte_bits * i));
122 }
123 }
124}
125
138RA8_INTERNAL static uint64_t internal_sram_shadow_load(uint64_t off, unsigned size)
139{
140 uint64_t v = 0U;
141 for (unsigned i = 0U; i < size; ++i) {
142 const uint64_t at = off + (uint64_t)i;
143 if (at < (uint64_t)k_sram_span) {
144 v |= (uint64_t)s_sram.shadow[at] << (k_sram_byte_bits * i);
145 }
146 }
147 return v;
148}
149
159RA8_INTERNAL static void internal_sram_latch_bank(uint32_t bank)
160{
161 s_sram.esr =
162 (uint16_t)(s_sram.esr | internal_sram_esr_bit(bank, 0U) | internal_sram_esr_bit(bank, 1U));
163 const uint64_t ear0 = k_sram_off_ear0 + ((uint64_t)bank * (uint64_t)k_sram_ear_bank_str);
164 internal_sram_shadow_store(ear0, sizeof(uint32_t), (uint64_t)s_k_sram_bank_data_off[bank]);
166 sizeof(uint32_t),
167 (uint64_t)s_k_sram_bank_data_off[bank]);
168 s_sram.latch_count++;
169}
170
181RA8_INTERNAL static void internal_sram_cr_write(uint32_t bank, uint8_t cr)
182{
183 bool was_bypass = (s_sram.last_cr[bank] == (uint8_t)k_sram_cr_bypass);
184 bool is_verify = (cr == (uint8_t)k_sram_cr_verify);
185 if (was_bypass) {
186 if (is_verify) {
188 }
189 }
190 s_sram.last_cr[bank] = cr;
191}
192
202RA8_INTERNAL static void internal_sram_clear(uint16_t mask)
203{
204 s_sram.esr = (uint16_t)(s_sram.esr & (uint16_t)~mask);
205 for (uint32_t bank = 0U; bank < k_sram_bank_count; ++bank) {
206 for (uint32_t slot = 0U; slot < k_sram_slots_bank; ++slot) {
207 if ((mask & internal_sram_esr_bit(bank, slot)) != 0U) {
208 const uint64_t ear = k_sram_off_ear0 + ((uint64_t)bank * (uint64_t)k_sram_ear_bank_str) +
209 ((uint64_t)slot * (uint64_t)k_sram_ear_slot_str);
210 internal_sram_shadow_store(ear, sizeof(uint32_t), 0U);
211 }
212 }
213 }
214}
215
229RA8_INTERNAL static uint64_t internal_sram_read(uc_engine* uc, uint64_t addr, unsigned size)
230{
231 (void)uc;
232 const uint64_t off = addr - (uint64_t)k_sram_base;
233 if (off == (uint64_t)k_sram_off_esr) {
234 return (uint64_t)s_sram.esr;
235 }
236 return internal_sram_shadow_load(off, size);
237}
238
251RA8_INTERNAL static void
252internal_sram_write(uc_engine* uc, uint64_t addr, unsigned size, uint64_t value)
253{
254 (void)uc;
255 const uint64_t off = addr - (uint64_t)k_sram_base;
256 if (off == (uint64_t)k_sram_off_esclr) {
257 internal_sram_clear((uint16_t)value);
258 return;
259 }
260 if (off == (uint64_t)k_sram_off_esr) {
261 s_sram.esr = (uint16_t)value;
262 return;
263 }
264 if ((off >= (uint64_t)k_sram_off_cr0) && (off <= (uint64_t)k_sram_off_cr3)) {
265 const uint64_t rel = off - (uint64_t)k_sram_off_cr0;
266 if ((rel % sizeof(uint32_t)) == 0U) {
267 internal_sram_cr_write((uint32_t)(rel / sizeof(uint32_t)),
268 (uint8_t)(value & (uint64_t)k_sram_cr_mask));
269 }
270 }
271 internal_sram_shadow_store(off, size, value);
272}
273
283{
284 s_sram = (sram_state_t){};
285}
286
296{
297 if (s_sram.latch_count == 0U) {
298 return; /* No fault-injection ran: stay quiet. */
299 }
300 (void)priv_emu_io_errf(" SRAM-ECC : decoder self-test latches=%u (SRAMESR modeled)\n",
301 s_sram.latch_count);
302}
303
305typedef enum : uint32_t {
308
311 .base = (uint64_t)k_sram_base,
312 .span = (uint64_t)k_sram_span,
313 .order = (uint32_t)k_sram_block_order,
314 .read = internal_sram_read,
316 .tick = nullptr,
317 .reset = internal_sram_reset,
318 .report = internal_sram_report,
319 .name = "SRAM-ECC",
320};
321
323[[gnu::constructor]] RA8_INTERNAL static void internal_sram_block_register(void)
324{
326}
Decentralized peripheral-block registry for the board emulator core.
void board_periph_register_block(const board_periph_block_t *block)
Register a peripheral block's descriptor with the core registry.
static RA8_INTERNAL void internal_sram_write(uc_engine *uc, uint64_t addr, unsigned size, uint64_t value)
MMIO write inside the SRAM-control window (width-aware).
static RA8_INTERNAL void internal_sram_shadow_store(uint64_t off, unsigned size, uint64_t value)
Write value (size bytes) into the read-back shadow at off.
static RA8_INTERNAL void internal_sram_reset(void)
Clear all SRAM-controller model state on reset / process start.
static RA8_INTERNAL uint64_t internal_sram_read(uc_engine *uc, uint64_t addr, unsigned size)
MMIO read inside the SRAM-control window (width-aware).
static RA8_INTERNAL void internal_sram_latch_bank(uint32_t bank)
Latch both ESR slots + EAR for bank (self-test verify reached).
static RA8_INTERNAL void internal_sram_cr_write(uint32_t bank, uint8_t cr)
Detect the self-test bypass->verify CR transition for bank.
static const uint32_t s_k_sram_bank_data_off[k_sram_bank_count]
Per-bank data-window offsets, for a plausible EAR fault address.
sram_order_t
Per-tick order slot for the SRAM-ECC block (relative order).
@ k_sram_block_order
After the VBATT-backup block; report order.
static RA8_INTERNAL void internal_sram_block_register(void)
Register the SRAM-controller block before main (host constructor).
static RA8_INTERNAL uint16_t internal_sram_esr_bit(uint32_t bank, uint32_t slot)
ESR bit for (bank, slot): slot 0 = 1-bit error, slot 1 = 2-bit.
sram_model_t
Self-test phase CR values + ESR/bank layout (no magic numbers).
@ k_sram_cr_mask
SRAMCRn is one byte wide.
@ k_sram_ear_slot_str
EAR stride per slot (32-bit register).
@ k_sram_cr_verify
Self-test verify phase (ECC+check).
@ k_sram_bank_count
SRAM0..SRAM3.
@ k_sram_slots_bank
ESR slots per bank: 0=1-bit, 1=2-bit.
@ k_sram_byte_bits
Bits per byte for width-aware assembly.
@ k_sram_cr_bypass
Self-test bypass phase (TSTBYP=1).
@ k_sram_ear_bank_str
EAR stride per bank (2 slots * 4 bytes).
static RA8_INTERNAL void internal_sram_clear(uint16_t mask)
Clear the ESR / EAR slots named by an SRAMESCLR write mask.
sram_geom_t
SRAM-controller window geometry + register offsets (ra8_sram_regs.h).
@ k_sram_off_esclr
SRAMESCLR error-status clear, 16-bit.
@ k_sram_off_cr3
SRAMCR3 – last per-bank control byte.
@ k_sram_off_ear0
SRAMEAR[0][0]; [bank][slot] at +8b/+4s.
@ k_sram_off_cr0
SRAMCR0 (CRn at 0x10 + 4*bank), 8-bit.
@ k_sram_off_esr
SRAMESR error status, 16-bit.
@ k_sram_span
Covers SRAMPRCR..SRAMEARnm.
static const board_periph_block_t s_k_sram_block
SRAM-controller block descriptor (self-registered with the core).
static RA8_INTERNAL void internal_sram_report(void)
End-of-run SRAM-ECC section: self-test latches observed this run.
static RA8_INTERNAL uint64_t internal_sram_shadow_load(uint64_t off, unsigned size)
Read size bytes from the read-back shadow at off.
static sram_state_t s_sram
Bounded raw-descriptor I/O seam for the RA8 emulator.
emu_io_result_t priv_emu_io_errf(const char *format,...)
Format bounded text and write it to the injected error descriptor.
@ k_sram_base
On-chip SRAM start.
Definition emu_memmap.h:42
-proof
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
A modelled peripheral block's self-description for the core registry.
SRAM-controller model state (cleared each run / reboot).
uint32_t latch_count
Self-test latches this run (report).
uint16_t esr
Modeled SRAMESR (latch + clear).
uint8_t last_cr[k_sram_bank_count]
Last SRAMCRn write per bank.
uint8_t shadow[k_sram_span]
Read-back store for all plain registers.