ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_sram.c
Go to the documentation of this file.
1
34
35#include "ra8_sram.h"
36
37#include <stdint.h>
38
39#include "ra8_attributes.h"
40#include "ra8_check.h"
41#include "ra8_err.h"
42#include "ra8_log.h"
43#include "ra8_mstp.h"
44#include "ra8_sram_internal.h"
45#include "ra8_sram_regs.h"
46
47/* =============================================================================
48 * Constants
49 * =============================================================================
50 */
51
53static const char* s_tag = "SRAM";
54
68
82
98
109
120
121/* =============================================================================
122 * Module state
123 * =============================================================================
124 */
125
127static bool s_initialized = false;
128
129/* The ECC error callback table (``g_sram_on_error*``) lives in
130 * ``ra8_sram_security.c`` and is reached from ``ra8_sram_deinit`` below
131 * through the ``extern`` declarations in ``ra8_sram_internal.h``. */
132
133/* =============================================================================
134 * Internal helpers
135 * =============================================================================
136 */
137
155 uint8_t bank)
156{
157 if ((uint8_t)cfg->ecc_mode > k_ra8_sram_eccmod_max) {
159 }
160 if ((uint8_t)cfg->on_error > k_ra8_sram_on_error_max) {
162 }
163 const uint8_t max_rgn =
165 if ((uint8_t)cfg->eccrgn > max_rgn) {
167 }
168 return k_ra8_ok;
169}
170
189{
190 uint8_t eccmod_field = k_ra8_sram_eccmod_disabled;
191 if (cfg->ecc_mode == k_ra8_sram_ecc_no_check) {
192 eccmod_field = k_ra8_sram_eccmod_no_check;
193 } else if (cfg->ecc_mode == k_ra8_sram_ecc_with_chk) {
194 eccmod_field = k_ra8_sram_eccmod_with_chk;
195 } else {
196 eccmod_field = k_ra8_sram_eccmod_disabled;
197 }
198
199 uint8_t value = eccmod_field;
201 value |= k_ra8_sram_cr_mask_oad;
202 }
203 if (cfg->enable_1bit_latch) {
205 }
206 return value;
207}
208
227RA8_INTERNAL static void internal_write_cr_locked(uint8_t bank, uint8_t value)
228{
229 volatile r_sram_regs_t* regs = ra8_sram_regs();
230
231 /* HUM Ch 58.2.4 "SRAMPRCR_S : SRAM Protection Control Register
232 * for Secure", p 3530 -- write 0xA501 to enable PR=1. */
234
235 /* HUM Ch 58.2.7 "SRAMCRn : SRAM Control Register n For ECC RAM",
236 * p 3532 -- per-bank SRAMCR layout (OAD / ECCMOD / E1STSEN). */
237 *ra8_sram_cr_ptr(regs, bank) = value;
238
239 /* Re-lock with PR=0.
240 * HUM Ch 58.2.4 "SRAMPRCR_S", p 3530 */
242}
243
260RA8_INTERNAL static void internal_write_eccrgn_locked(uint8_t bank, uint8_t value)
261{
262 volatile r_sram_regs_t* regs = ra8_sram_regs();
263
264 /* HUM Ch 58.2.4 "SRAMPRCR_S", p 3530 */
266
267 /* HUM Ch 58.2.8 "SRAMECCRGN0 : SRAM ECC Region Control Register 0",
268 * p 3533 (and 58.2.9..58.2.11 for banks 1..3). */
269 *ra8_sram_eccrgn_ptr(regs, bank) = (uint8_t)(value & k_ra8_sram_eccrgn_field_msk);
270
271 /* HUM Ch 58.2.4 "SRAMPRCR_S", p 3530 */
273}
274
287RA8_INTERNAL static void internal_write_wtsc_locked(uint8_t value)
288{
289 volatile r_sram_regs_t* regs = ra8_sram_regs();
290
291 /* HUM Ch 58.2.4 "SRAMPRCR_S", p 3530 */
293
294 /* HUM Ch 58.2.6 "SRAMWTSC : SRAM Wait State Control Register",
295 * p 3531. */
296 regs->SRAMWTSC = (uint8_t)(value & k_ra8_sram_wtsc_msk);
297
298 /* HUM Ch 58.2.4 "SRAMPRCR_S", p 3530 */
300}
301
321RA8_INTERNAL static void
322internal_decode_esr(uint16_t raw, uint8_t* one_bit_mask, uint8_t* two_bit_mask)
323{
324 uint8_t one = 0U;
325 uint8_t two = 0U;
326 for (uint8_t bank = 0U; bank < k_ra8_sram_bank_count; ++bank) {
327 const uint16_t one_bit_pos = (uint16_t)((uint16_t)2U * (uint16_t)bank);
328 const uint16_t two_bit_pos = (uint16_t)(one_bit_pos + 1U);
329 if ((raw & (uint16_t)((uint16_t)1U << one_bit_pos)) != 0U) {
330 one |= (uint8_t)((uint8_t)1U << bank);
331 }
332 if ((raw & (uint16_t)((uint16_t)1U << two_bit_pos)) != 0U) {
333 two |= (uint8_t)((uint8_t)1U << bank);
334 }
335 }
336 *one_bit_mask = one;
337 *two_bit_mask = two;
338}
339
355RA8_INTERNAL static uintptr_t internal_ear_to_abs_addr(uint32_t ear)
356{
357 if (ear == 0U) {
358 return (uintptr_t)0U;
359 }
360 return k_ra8_sram_data_base_addr + (uintptr_t)ear;
361}
362
382{
383 uint32_t sar = 0U;
384 for (uint8_t bank = 0U; bank < k_ra8_sram_bank_count; ++bank) {
385 if (sec->bank_ns[bank]) {
386 sar |= k_ra8_sram_sar_bit_sa0 << bank;
387 }
388 }
389 if (sec->wtsc_ns) {
391 }
392
393 volatile r_sram_cpscu_regs_t* cpscu = ra8_sram_cpscu_regs();
394
395 /* HUM Ch 58.2.2 "SRAMSAR : SRAM Security Attribution Register",
396 * p 3528 -- per-bank register security + SRAMWTSC security. */
397 cpscu->SRAMSAR = sar;
398
399 /* HUM Ch 58.2.3 "SRAMESAR : SRAM ECC region Security Attribute
400 * Register", p 3529 -- ECC region NS bit. */
401 uint32_t esar = 0U;
402 if (sec->ecc_region_ns) {
404 }
405 cpscu->SRAMESAR = esar;
406
407 for (uint8_t bank = 0U; bank < k_ra8_sram_bank_count; ++bank) {
408 /* HUM Ch 58.2.1 "SRAMSABARn : SRAM Security Attribute Boundary
409 * Address Register", p 3527 -- boundary value, low 13 bits forced
410 * to zero (4 KB aligned). */
411 cpscu->SRAMSABAR[bank] = sec->boundary_offset[bank] & ~k_ra8_sram_sabar_align_mask;
412 }
413}
414
431RA8_INTERNAL static void internal_zero_fill_bank(uint8_t bank)
432{
433 const uint32_t bytes = ra8_sram_bank_size_bytes(bank);
434 volatile uint64_t* const dst = ra8_sram_bank_data_ptr(bank);
435 const uint32_t words = bytes >> (uint32_t)k_ra8_sram_ecc_word_shift;
436 for (uint32_t i = 0U; i < words; ++i) {
438 }
439}
440
463{
464 /* Step 1: enable ECC encode without checking. */
466
467 /* Step 2: deterministic 64-bit zero fill of the data window. */
469
470 /* Step 3: leave the bank with ECC fully disabled so the caller can
471 * pick the final mode safely. */
473}
474
475/* =============================================================================
476 * Lifecycle
477 * =============================================================================
478 */
479
504{
505 for (uint8_t bank = 0U; bank < k_ra8_sram_bank_count; ++bank) {
506 const ra8_err_t verr = internal_validate_bank_cfg(&cfg->banks[bank], bank);
507 RA8_RETURN_ON_ERROR(verr, s_tag, "ra8_sram_init: bad bank cfg");
508 }
509 for (uint8_t bank = 0U; bank < k_ra8_sram_bank_count; ++bank) {
510 const ra8_err_t merr = ra8_mstp_enable(s_sram_mstp_table[bank]);
511 /* GCOVR_EXCL_BR_START -- MSTP HW readback */
512 RA8_RETURN_ON_ERROR(merr, s_tag, "ra8_sram_init: mstp enable");
513 /* GCOVR_EXCL_BR_STOP */
514 }
515 return k_ra8_ok;
516}
517
538{
539 for (uint8_t bank = 0U; bank < k_ra8_sram_bank_count; ++bank) {
540 if (cfg->banks[bank].zero_init) {
542 }
543 }
544 for (uint8_t bank = 0U; bank < k_ra8_sram_bank_count; ++bank) {
545 internal_write_eccrgn_locked(bank, (uint8_t)cfg->banks[bank].eccrgn);
546 const uint8_t cr_value = internal_encode_cr(&cfg->banks[bank]);
547 internal_write_cr_locked(bank, cr_value);
548 }
549}
550
552{
553 RA8_CHECK_NULL_PTR(cfg, s_tag, "cfg must not be nullptr");
554
555 const ra8_err_t v_err = internal_validate_and_ungate(cfg);
556 RA8_RETURN_ON_ERROR(v_err, s_tag, "ra8_sram_init: validate/ungate");
557
558 if (cfg->apply_security) {
560 }
561
562 /* SRAMWTSC is deliberately NOT touched here -- ra8_cgc_init owns it,
563 * derived from ICLK per HUM Ch 58.3.7 p 3540. Clearing it from a
564 * zero-initialised config is how a caller silently takes the memory
565 * system outside guaranteed operation (tracker #524). */
566
568
569 /* Clear any stale error flags. HUM 58.2.13 p 3536. */
570 volatile r_sram_regs_t* regs = ra8_sram_regs();
572
573 s_initialized = true;
574 ra8_log_info(s_tag, "ra8_sram_init done");
575 return k_ra8_ok;
576}
577
578[[nodiscard]] ra8_err_t ra8_sram_deinit(void)
579{
580 /* Disable ECC + clear OAD on every bank before clock-gating, so a
581 * spurious bus error during teardown does not latch a fault. */
582 for (uint8_t bank = 0U; bank < k_ra8_sram_bank_count; ++bank) {
583 internal_write_cr_locked(bank, 0U);
585 }
586 /* SRAMWTSC stays as ra8_cgc_init left it. Tearing down the ECC
587 * configuration says nothing about the clock, and the caller is still
588 * executing out of this SRAM: clearing WTEN here would leave every
589 * subsequent access outside the guarantee of HUM Ch 58.3.7 p 3540. */
590
591 /* HUM Ch 58.3.1 "Module Stop Function", p 3538 -- re-gate the
592 * clock for every bank (HUM 11.2.6 MSTPCRA p 443). */
593 for (uint8_t bank = 0U; bank < k_ra8_sram_bank_count; ++bank) {
595 }
596
597 g_sram_on_error = nullptr;
598 g_sram_on_error_ctx = nullptr;
599 for (uint8_t bank = 0U; bank < k_ra8_sram_bank_count; ++bank) {
600 g_sram_on_error_bank[bank] = nullptr;
601 g_sram_on_error_bank_ctx[bank] = nullptr;
602 }
603 s_initialized = false;
604 return k_ra8_ok;
605}
606
607[[nodiscard]] ra8_err_t ra8_sram_enter_stop(uint8_t bank)
608{
609 if ((uint16_t)bank >= (uint16_t)k_ra8_sram_bank_count) {
611 }
612 /* HUM Ch 58.3.1 "Module Stop Function" p 3538 */
614}
615
616[[nodiscard]] ra8_err_t ra8_sram_exit_stop(uint8_t bank)
617{
618 if ((uint16_t)bank >= (uint16_t)k_ra8_sram_bank_count) {
620 }
621 /* HUM Ch 58.3.1 "Module Stop Function" p 3538 */
623}
624
625/* =============================================================================
626 * ECC mode set
627 * =============================================================================
628 */
629
630[[nodiscard]] ra8_err_t ra8_sram_set_mode(uint8_t bank, const ra8_sram_bank_cfg_t* cfg)
631{
632 RA8_CHECK_NULL_PTR(cfg, s_tag, "cfg must not be nullptr");
633 if ((uint16_t)bank >= (uint16_t)k_ra8_sram_bank_count) {
635 }
636
637 const ra8_err_t verr = internal_validate_bank_cfg(cfg, bank);
638 /* GCOVR_EXCL_BR_START -- internal_validate_bank_cfg() error edge; set_mode pre-checks the bank */
639 RA8_RETURN_ON_ERROR(verr, s_tag, "ra8_sram_set_mode: bad bank cfg");
640 /* GCOVR_EXCL_BR_STOP */
641
642 internal_write_eccrgn_locked(bank, (uint8_t)cfg->eccrgn);
644 return k_ra8_ok;
645}
646
647[[nodiscard]] ra8_err_t ra8_sram_set_eccrgn(uint8_t bank, ra8_sram_eccrgn_size_t region)
648{
649 if ((uint16_t)bank >= (uint16_t)k_ra8_sram_bank_count) {
651 }
652 const uint8_t max_rgn =
654 if ((uint8_t)region > max_rgn) {
656 }
657 internal_write_eccrgn_locked(bank, (uint8_t)region);
658 return k_ra8_ok;
659}
660
661[[nodiscard]] ra8_err_t ra8_sram_set_wait_state_for_clock(uint32_t iclk_hz, uint32_t iclk_max_hz)
662{
663 if ((iclk_hz == 0U) || (iclk_max_hz == 0U)) {
665 }
666 /* HUM Ch 58.3.7 "Wait State", p 3540: WTEN must be 1 when the
667 * current ICLK exceeds half the maximum, otherwise it stays 0. */
668 const uint32_t threshold = iclk_max_hz >> 1U;
669 uint8_t wtsc = 0U;
670 if (iclk_hz > threshold) {
672 }
674 return k_ra8_ok;
675}
676
677/* =============================================================================
678 * Status / clear
679 * =============================================================================
680 */
681
683{
684 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
685
686 volatile r_sram_regs_t* regs = ra8_sram_regs();
687
688 /* HUM Ch 58.2.12 "SRAMESR : SRAM Error Status Register For ECC
689 * RAM", p 3535 -- packed 1-bit/2-bit flags per bank. */
690 const uint16_t raw = regs->SRAMESR;
691 out->raw_esr = raw;
693
694 /* HUM Ch 58.2.14 "SRAMEARnm : SRAM Error Address Register nm
695 * For ECC RAM", p 3537 -- m=0 is the 1-bit slot, m=1 is the
696 * 2-bit slot. Stored as an offset; this driver presents the
697 * absolute Secure address to callers. */
698 for (uint8_t bank = 0U; bank < k_ra8_sram_bank_count; ++bank) {
699 out->addr_1bit[bank] = internal_ear_to_abs_addr(regs->SRAMEAR[bank][0]);
700 out->addr_2bit[bank] = internal_ear_to_abs_addr(regs->SRAMEAR[bank][1]);
701 }
702 return k_ra8_ok;
703}
704
705[[nodiscard]] ra8_err_t ra8_sram_clear_status(uint16_t esr_mask)
706{
707 if ((esr_mask & (uint16_t)~k_ra8_sram_err_all_mask) != 0U) {
709 }
710 volatile r_sram_regs_t* regs = ra8_sram_regs();
711 /* HUM Ch 58.2.13 "SRAMESCLR : SRAM Error Status Clear Register
712 * For ECC RAM", p 3536 -- write 1 to each bit to clear. */
713 regs->SRAMESCLR = esr_mask;
714 return k_ra8_ok;
715}
716
717[[nodiscard]] ra8_err_t ra8_sram_clear_address(uint8_t bank, uint8_t slot)
718{
719 if ((uint16_t)bank >= (uint16_t)k_ra8_sram_bank_count) {
721 }
722 if (slot > k_ra8_sram_ear_slot_max) {
724 }
725 /* The EAR is auto-cleared by writing 1 to the corresponding
726 * SRAMESCLR bit. HUM Ch 58.2.14 p 3537 -- "These bits are cleared
727 * by clearing 1-bit/2-bit ECC error from SRAMESCLR." */
728 const uint16_t bit_pos = (uint16_t)(((uint16_t)2U * (uint16_t)bank) + (uint16_t)slot);
729 const uint16_t mask = (uint16_t)((uint16_t)1U << bit_pos);
730 volatile r_sram_regs_t* regs = ra8_sram_regs();
731 /* HUM Ch 58.2.13 "SRAMESCLR : SRAM Error Status Clear Register
732 * For ECC RAM" p 3536 */
733 regs->SRAMESCLR = mask;
734 return k_ra8_ok;
735}
736
737/* =============================================================================
738 * Zero-init / self-test / introspection
739 * =============================================================================
740 */
741
742[[nodiscard]] ra8_err_t ra8_sram_zero_init_bank(uint8_t bank)
743{
744 if ((uint16_t)bank >= (uint16_t)k_ra8_sram_bank_count) {
746 }
748 return k_ra8_ok;
749}
750
774RA8_INTERNAL static void
775internal_self_test_inject(uint8_t bank, volatile uint64_t* data, bool inject_two_bit)
776{
778
779 uint8_t inject_mask = k_ra8_sram_self_test_flip_1bit;
780 if (inject_two_bit) {
781 inject_mask = k_ra8_sram_self_test_flip_2bit;
782 }
783 const uint64_t syndrome = *data;
784 const uint64_t corrupted = syndrome ^ (uint64_t)inject_mask;
785 *data = corrupted;
786
788}
789
790[[nodiscard]] ra8_err_t
791ra8_sram_self_test(uint8_t bank, uint32_t probe_offset, bool inject_two_bit, bool* out_caught)
792{
793 RA8_CHECK_NULL_PTR(out_caught, s_tag, "out_caught must not be nullptr");
794 if ((uint16_t)bank >= (uint16_t)k_ra8_sram_bank_count) {
796 }
797 /* Probe must be 8-byte aligned and inside the bank (HUM 58.4.2
798 * p 3541 -- 8-byte ECC line size). */
799 if ((probe_offset & ((uint32_t)k_ra8_sram_ecc_word_bytes - 1U)) != 0U) {
801 }
802 if (probe_offset >= ra8_sram_bank_size_bytes(bank)) {
804 }
805
806 *out_caught = false;
807
808 volatile uint64_t* const bank_base = ra8_sram_bank_data_ptr(bank);
809 const uintptr_t data_addr = (uintptr_t)bank_base + (uintptr_t)probe_offset;
810 volatile uint64_t* const data = (volatile uint64_t*)data_addr;
811
812 /* Step 1: seed the line under ECC encode-only (HUM Ch 58.3.4 p 3539). */
815
816 /* Steps 2-3: bypass-read, inject, then arm verify. */
817 internal_self_test_inject(bank, data, inject_two_bit);
818
819 /* Read the line. On real silicon this triggers the ECC engine, which
820 * latches SRAMESR / SRAMEAR for the faulted slot. The RAM-backed host
821 * register file has no ECC engine, so on the unit-test build the read
822 * is inert and host tests stage SRAMESR before the call to drive both
823 * legs of the caught decision below. */
824 volatile uint64_t scratch = *data;
825 (void)scratch;
826
827 /* Step 4: confirm SRAMESR latched the expected flag. */
828 volatile r_sram_regs_t* check_regs = ra8_sram_regs();
829 const uint16_t esr = check_regs->SRAMESR;
830 uint16_t slot_bit = 0U;
831 if (inject_two_bit) {
832 slot_bit = 1U;
833 }
834 const uint16_t want_bit =
835 (uint16_t)((uint16_t)1U << (uint16_t)(((uint16_t)2U * (uint16_t)bank) + slot_bit));
836 *out_caught = ((esr & want_bit) != 0U);
837
838 return k_ra8_ok;
839}
840
842{
843 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
844 if ((uint16_t)bank >= (uint16_t)k_ra8_sram_bank_count) {
846 }
847 out->bank = bank;
852 return k_ra8_ok;
853}
854
855/*
856 * TrustZone security attribution + the ECC error callback fan-out live
857 * in ``ra8_sram_security.c`` (split for the 1000-line file-size cap).
858 */
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_RETURN_ON_ERROR(err, tag, message)
Early return on error, propagating the code upward.
Definition ra8_check.h:184
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
static bool s_initialized
True once display_init has succeeded.
Error Code Definitions for ra8-firmware.
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Lightweight Logging Interface for ra8-firmware.
#define ra8_log_info(tag, message)
RA8 log info.
Definition ra8_log.h:364
Ref-counted Module Stop Control wrapper for the RA8D2.
ra8_err_t ra8_mstp_enable(ra8_mstp_t id)
Reference-counted "ungate this peripheral" request.
Definition ra8_mstp.c:343
ra8_err_t ra8_mstp_disable(ra8_mstp_t id)
Reference-counted "gate this peripheral" request.
Definition ra8_mstp.c:382
ra8_mstp_t
Packed (reg << 8) | bit module-stop identifier.
@ k_ra8_mstp_sram2
MSTPA2 SRAM2.
@ k_ra8_mstp_sram0
MSTPA0 SRAM0.
@ k_ra8_mstp_sram3
MSTPA3 SRAM3.
@ k_ra8_mstp_sram1
MSTPA1 SRAM1.
ra8_err_t ra8_sram_clear_address(uint8_t bank, uint8_t slot)
Clear the captured EAR address for a single (bank, slot) pair.
Definition ra8_sram.c:717
ra8_err_t ra8_sram_exit_stop(uint8_t bank)
Re-ungate a single bank's clock (Module-Stop exit).
Definition ra8_sram.c:616
static void internal_self_test_inject(uint8_t bank, volatile uint64_t *data, bool inject_two_bit)
Inject a 1- or 2-bit fault on a probed ECC line.
Definition ra8_sram.c:775
static void internal_write_wtsc_locked(uint8_t value)
Write SRAMWTSC under SRAMPRCR_S unlock.
Definition ra8_sram.c:287
ra8_err_t ra8_sram_set_wait_state_for_clock(uint32_t iclk_hz, uint32_t iclk_max_hz)
Derive SRAMWTSC.WTEN from an ICLK frequency and program it.
Definition ra8_sram.c:661
ra8_sram_local_t
Internal helpers / shifts / sizes.
Definition ra8_sram.c:59
@ k_ra8_sram_eccmod_shift
ECCMOD field is at bits [3:2] of SRAMCRn.
Definition ra8_sram.c:60
@ k_ra8_sram_ear_slot_max
0 (1-bit) or 1 (2-bit).
Definition ra8_sram.c:65
@ k_ra8_sram_eccmod_max
ra8_sram_ecc_mode_t enumerates 0..2.
Definition ra8_sram.c:61
@ k_ra8_sram_eccrgn_max012
Largest legal ECCRGN for SRAM0..2.
Definition ra8_sram.c:63
@ k_ra8_sram_on_error_max
OAD is single-bit (0 or 1).
Definition ra8_sram.c:62
@ k_ra8_sram_eccrgn_max3
Largest legal ECCRGN for SRAM3.
Definition ra8_sram.c:64
@ k_ra8_sram_bank_max_idx
Last legal bank index.
Definition ra8_sram.c:66
static void internal_decode_esr(uint16_t raw, uint8_t *one_bit_mask, uint8_t *two_bit_mask)
Compose the per-bank 1-bit / 2-bit error-status masks.
Definition ra8_sram.c:322
static const uint32_t s_sram_ecc_off_table[k_ra8_sram_bank_count]
Bank-index -> ECC syndrome window offset (HUM Ch 58.1, p 3527).
Definition ra8_sram.c:114
ra8_err_t ra8_sram_deinit(void)
Tear down the driver and re-gate each bank.
Definition ra8_sram.c:578
static const ra8_mstp_t s_sram_mstp_table[k_ra8_sram_bank_count]
Bank-index -> ra8_mstp_t lookup.
Definition ra8_sram.c:92
ra8_err_t ra8_sram_set_mode(uint8_t bank, const ra8_sram_bank_cfg_t *cfg)
Change the ECC mode of a single bank at runtime.
Definition ra8_sram.c:630
ra8_err_t ra8_sram_zero_init_bank(uint8_t bank)
Deterministically zero one bank under ECC-no-check.
Definition ra8_sram.c:742
static ra8_err_t internal_validate_and_ungate(const ra8_sram_config_t *cfg)
Validate every bank cfg and ungate the corresponding MSTP bits.
Definition ra8_sram.c:503
static uintptr_t internal_ear_to_abs_addr(uint32_t ear)
Translate a SRAMEAR offset into its absolute Secure-alias address (per HUM Ch 58.2....
Definition ra8_sram.c:355
static void internal_zero_fill_bank(uint8_t bank)
8-byte zero fill across the bank's data window.
Definition ra8_sram.c:431
static void internal_apply_per_bank(const ra8_sram_config_t *cfg)
Apply the per-bank zero-init + ECC mode programming pass.
Definition ra8_sram.c:537
ra8_err_t ra8_sram_set_eccrgn(uint8_t bank, ra8_sram_eccrgn_size_t region)
Update only the ECC region size (SRAMECCRGNn) for one bank.
Definition ra8_sram.c:647
ra8_err_t ra8_sram_enter_stop(uint8_t bank)
Re-gate a single bank's clock (Module-Stop entry).
Definition ra8_sram.c:607
static const uint32_t s_sram_data_off_table[k_ra8_sram_bank_count]
Bank-index -> data-window offset (HUM Ch 58.1 Table 58.1, p 3527).
Definition ra8_sram.c:103
static void internal_zero_init_with_no_check(uint8_t bank)
Run a single bank's deterministic zero-init pass.
Definition ra8_sram.c:462
static void internal_write_eccrgn_locked(uint8_t bank, uint8_t value)
Write SRAMECCRGNn for bank under SRAMPRCR_S unlock.
Definition ra8_sram.c:260
ra8_sram_self_test_inject_t
Bit masks for the ECC self-test fault injection.
Definition ra8_sram.c:78
@ k_ra8_sram_self_test_flip_2bit
Flip bits 0+1 of the syndrome.
Definition ra8_sram.c:80
@ k_ra8_sram_self_test_flip_1bit
Flip bit 0 of the syndrome.
Definition ra8_sram.c:79
ra8_err_t ra8_sram_get_status(ra8_sram_status_t *out)
Snapshot the current ECC error state across all four banks.
Definition ra8_sram.c:682
static ra8_err_t internal_validate_bank_cfg(const ra8_sram_bank_cfg_t *cfg, uint8_t bank)
Validate per-bank config.
Definition ra8_sram.c:154
static void internal_write_cr_locked(uint8_t bank, uint8_t value)
Write SRAMCRn for bank under SRAMPRCR_S unlock.
Definition ra8_sram.c:227
ra8_err_t ra8_sram_get_bank_info(uint8_t bank, ra8_sram_bank_info_t *out)
Report the static layout of one bank.
Definition ra8_sram.c:841
static void internal_apply_security(const ra8_sram_security_cfg_t *sec)
Apply the optional security cfg from ra8_sram_init.
Definition ra8_sram.c:381
ra8_err_t ra8_sram_init(const ra8_sram_config_t *cfg)
Initialise the SRAM driver and configure each bank.
Definition ra8_sram.c:551
static uint8_t internal_encode_cr(const ra8_sram_bank_cfg_t *cfg)
Encode a ra8_sram_bank_cfg_t into an SRAMCRn byte value.
Definition ra8_sram.c:188
ra8_err_t ra8_sram_self_test(uint8_t bank, uint32_t probe_offset, bool inject_two_bit, bool *out_caught)
Run the HUM Ch 58.3.4 ECC decoder self-test on one bank.
Definition ra8_sram.c:791
ra8_err_t ra8_sram_clear_status(uint16_t esr_mask)
Clear the listed ECC error bits in SRAMESR (also clears EAR).
Definition ra8_sram.c:705
SRAM (with ECC) HAL driver public API.
ra8_sram_eccrgn_size_t
Public form of SRAMECCRGNn.ECCRGN (per-bank ECC region size).
Definition ra8_sram.h:95
@ k_ra8_sram_ecc_no_check
ECC encode/correct, no error reporting (10b).
Definition ra8_sram.h:70
@ k_ra8_sram_ecc_with_chk
Full ECC (11b) – raises NMI / reset.
Definition ra8_sram.h:71
@ k_ra8_sram_on_error_reset
Reset the MCU on ECC error.
Definition ra8_sram.h:83
src/-local shared surface for the SRAM HAL driver split.
ra8_sram_error_fn_t g_sram_on_error
Registered global ECC error callback (NULL until attach).
ra8_sram_error_fn_t g_sram_on_error_bank[k_ra8_sram_bank_count]
Per-bank ECC error callback table (NULL until attach).
void * g_sram_on_error_ctx
Caller context forwarded to g_sram_on_error.
void * g_sram_on_error_bank_ctx[k_ra8_sram_bank_count]
Per-bank context forwarded to g_sram_on_error_bank.
SRAM (with ECC) control / status / security register layout.
static volatile uint8_t * ra8_sram_eccrgn_ptr(volatile r_sram_regs_t *regs, uint8_t bank)
Indexed write helper: SRAMECCRGNn slot.
@ k_ra8_sram_eccrgn_off
000b – no ECC target region.
@ k_ra8_sram_eccrgn_field_msk
ECCRGN[2:0] bit mask.
@ k_ra8_sram_err_all_mask
Union of all 8 error bits.
@ k_ra8_sram_wtsc_wten
Insert one wait state on SRAM access.
@ k_ra8_sram_wtsc_msk
All R/W bits in SRAMWTSC.
@ k_ra8_sram_data_base_addr
Secure SRAM data alias (bank 0).
@ k_ra8_sram_ecc_word_bytes
64-bit ECC word width (bytes).
@ k_ra8_sram_ecc_word_shift
log2(word bytes), for size>>shift loops.
static volatile uint8_t * ra8_sram_cr_ptr(volatile r_sram_regs_t *regs, uint8_t bank)
Indexed write helper: SRAMCRn slot.
@ k_ra8_sram_sabar_align_mask
b12..b0 must be 0.
@ k_ra8_sram_ecc_bank1_off
SRAM1 ECC region @ 0x221B_0000.
@ k_ra8_sram_ecc_bank2_off
SRAM2 ECC region @ 0x221C_0000.
@ k_ra8_sram_ecc_bank3_off
SRAM3 ECC region @ 0x221D_0000.
@ k_ra8_sram_ecc_bank0_off
SRAM0 ECC region @ 0x221A_0000.
@ k_ra8_sram_bank2_data_off
SRAM2 starts at 0x2210_0000.
@ k_ra8_sram_bank1_data_off
SRAM1 starts at 0x2208_0000.
@ k_ra8_sram_bank3_data_off
SRAM3 starts at 0x2218_0000.
@ k_ra8_sram_bank0_data_off
SRAM0 starts at 0x2200_0000.
@ k_ra8_sram_cr_mask_e1stsen
E1STSEN bit 4.
@ k_ra8_sram_cr_mask_oad
OAD bit 0.
static volatile r_sram_cpscu_regs_t * ra8_sram_cpscu_regs(void)
Get pointer to the (Secure) CPSCU SRAM security register block.
@ k_ra8_sram_prcr_lock
KW=0xA5, PR=0 – writes blocked.
@ k_ra8_sram_prcr_unlock
KW=0xA5, PR=1 – writes enabled.
@ k_ra8_sram_esar_bit_esa
SRAMESA – ECC region Non-Secure.
@ k_ra8_sram_cr_self_test_phase_write
ECCMOD=10, all others 0.
@ k_ra8_sram_cr_self_test_phase_bypass
TSTBYP=1, ECCMOD=00.
@ k_ra8_sram_cr_self_test_phase_verify
ECCMOD=11, E1STSEN=1.
@ k_ra8_sram_sar_bit_wtsa
SRAMWTSC Non-Secure.
@ k_ra8_sram_sar_bit_sa0
SRAM0 register set Non-Secure.
static uint32_t ra8_sram_bank_size_bytes(uint8_t bank)
Per-bank data-region size in bytes.
static volatile uint64_t * ra8_sram_bank_data_ptr(uint8_t bank)
Per-bank data window helper: pointer to the start of the data alias.
@ k_ra8_sram_bank_count
SRAM0, SRAM1, SRAM2, SRAM3.
static uint32_t ra8_sram_bank_ecc_size_bytes(uint8_t bank)
Per-bank ECC syndrome region size in bytes.
@ k_ra8_sram_eccmod_disabled
00b<<2 = 0x00 (ECC off).
@ k_ra8_sram_eccmod_no_check
10b<<2 = 0x08 (ECC, no check).
@ k_ra8_sram_eccmod_with_chk
11b<<2 = 0x0C (ECC + checking).
static volatile r_sram_regs_t * ra8_sram_regs(void)
Get pointer to the (Secure) SRAM control register block.
@ k_ra8_sram_zero_init_word
Default fill pattern.
Memory layout of the CPSCU SRAM security window.
volatile uint32_t SRAMSAR
+0x010 SRAM register security.
volatile uint32_t SRAMSABAR[k_ra8_sram_bank_count]
+0x400..+0x40F Bank boundary.
volatile uint32_t SRAMESAR
+0x510 ECC region security.
Memory layout of the SRAM control window.
volatile uint16_t SRAMESR
+0x40 ECC error status.
volatile uint16_t SRAMPRCR_S
+0x00 Secure write-protect.
volatile uint8_t SRAMWTSC
+0x08 Wait-state control.
volatile uint32_t SRAMEAR[k_ra8_sram_bank_count][k_ra8_sram_ear_pair_count]
+0x50..+0x7F Error addresses.
volatile uint16_t SRAMESCLR
+0x48 ECC error status clear.
Per-bank ECC configuration descriptor.
Definition ra8_sram.h:111
ra8_sram_eccrgn_size_t eccrgn
ECC target region size (SRAMECCRGNn).
Definition ra8_sram.h:115
ra8_sram_on_error_t on_error
NMI vs Reset on ECC error.
Definition ra8_sram.h:113
ra8_sram_ecc_mode_t ecc_mode
ECC mode (off / no-check / with-check).
Definition ra8_sram.h:112
bool zero_init
If true, init() runs the zero-init pass.
Definition ra8_sram.h:116
bool enable_1bit_latch
Set E1STSEN: latch 1-bit errors.
Definition ra8_sram.h:114
Static description of one bank.
Definition ra8_sram.h:205
uintptr_t ecc_base
Absolute Secure base of ECC syndrome.
Definition ra8_sram.h:209
uint8_t bank
Bank index 0..3.
Definition ra8_sram.h:206
uintptr_t data_base
Absolute Secure base of data region.
Definition ra8_sram.h:207
uint32_t ecc_size
Bytes in the ECC syndrome region.
Definition ra8_sram.h:210
uint32_t data_size
Bytes in the data region.
Definition ra8_sram.h:208
Top-level driver configuration.
Definition ra8_sram.h:164
bool apply_security
Touch CPSCU registers if true.
Definition ra8_sram.h:167
ra8_sram_security_cfg_t security
CPSCU security attribution.
Definition ra8_sram.h:166
ra8_sram_bank_cfg_t banks[k_ra8_sram_bank_count]
Per-bank settings.
Definition ra8_sram.h:165
TrustZone security attribution configured at init time.
Definition ra8_sram.h:134
uint32_t boundary_offset[k_ra8_sram_bank_count]
SRAMSABARn boundary value.
Definition ra8_sram.h:138
bool ecc_region_ns
SRAMESAR.SRAMESA bit.
Definition ra8_sram.h:137
bool wtsc_ns
SRAMSAR.SRAMWTSA bit.
Definition ra8_sram.h:136
bool bank_ns[k_ra8_sram_bank_count]
Bit n -> SRAMSAn = 1 (NS).
Definition ra8_sram.h:135
Snapshot of ECC error state (filled by ra8_sram_get_status).
Definition ra8_sram.h:189
uint8_t two_bit_mask
Bit i = SRAMi 2-bit error.
Definition ra8_sram.h:192
uintptr_t addr_2bit[k_ra8_sram_bank_count]
Captured 2-bit error address per bank.
Definition ra8_sram.h:194
uintptr_t addr_1bit[k_ra8_sram_bank_count]
Captured 1-bit error address per bank.
Definition ra8_sram.h:193
uint8_t one_bit_mask
Bit i = SRAMi 1-bit error.
Definition ra8_sram.h:191
uint16_t raw_esr
Raw SRAMESR value.
Definition ra8_sram.h:190