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

SRAM (with ECC) HAL driver implementation. More...

#include "ra8_sram.h"
#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_log.h"
#include "ra8_mstp.h"
#include "ra8_sram_internal.h"
#include "ra8_sram_regs.h"
Include dependency graph for ra8_sram.c:

Go to the source code of this file.

Enumerations

enum  ra8_sram_local_t : uint8_t {
  k_ra8_sram_eccmod_shift = 2U ,
  k_ra8_sram_eccmod_max = 2U ,
  k_ra8_sram_on_error_max = 1U ,
  k_ra8_sram_eccrgn_max012 = 4U ,
  k_ra8_sram_eccrgn_max3 = 1U ,
  k_ra8_sram_ear_slot_max = 1U ,
  k_ra8_sram_bank_max_idx = 3U
}
 Internal helpers / shifts / sizes. More...
enum  ra8_sram_self_test_inject_t : uint8_t {
  k_ra8_sram_self_test_flip_1bit = 0x01U ,
  k_ra8_sram_self_test_flip_2bit = 0x03U
}
 Bit masks for the ECC self-test fault injection. More...

Functions

static ra8_err_t internal_validate_bank_cfg (const ra8_sram_bank_cfg_t *cfg, uint8_t bank)
 Validate per-bank config.
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.
static void internal_write_cr_locked (uint8_t bank, uint8_t value)
 Write SRAMCRn for bank under SRAMPRCR_S unlock.
static void internal_write_eccrgn_locked (uint8_t bank, uint8_t value)
 Write SRAMECCRGNn for bank under SRAMPRCR_S unlock.
static void internal_write_wtsc_locked (uint8_t value)
 Write SRAMWTSC under SRAMPRCR_S unlock.
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.
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.14 p 3537).
static void internal_apply_security (const ra8_sram_security_cfg_t *sec)
 Apply the optional security cfg from ra8_sram_init.
static void internal_zero_fill_bank (uint8_t bank)
 8-byte zero fill across the bank's data window.
static void internal_zero_init_with_no_check (uint8_t bank)
 Run a single bank's deterministic zero-init pass.
static ra8_err_t internal_validate_and_ungate (const ra8_sram_config_t *cfg)
 Validate every bank cfg and ungate the corresponding MSTP bits.
static void internal_apply_per_bank (const ra8_sram_config_t *cfg)
 Apply the per-bank zero-init + ECC mode programming pass.
ra8_err_t ra8_sram_init (const ra8_sram_config_t *cfg)
 Initialise the SRAM driver and configure each bank.
ra8_err_t ra8_sram_deinit (void)
 Tear down the driver and re-gate each bank.
ra8_err_t ra8_sram_enter_stop (uint8_t bank)
 Re-gate a single bank's clock (Module-Stop entry).
ra8_err_t ra8_sram_exit_stop (uint8_t bank)
 Re-ungate a single bank's clock (Module-Stop exit).
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.
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.
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.
ra8_err_t ra8_sram_get_status (ra8_sram_status_t *out)
 Snapshot the current ECC error state across all four banks.
ra8_err_t ra8_sram_clear_status (uint16_t esr_mask)
 Clear the listed ECC error bits in SRAMESR (also clears EAR).
ra8_err_t ra8_sram_clear_address (uint8_t bank, uint8_t slot)
 Clear the captured EAR address for a single (bank, slot) pair.
ra8_err_t ra8_sram_zero_init_bank (uint8_t bank)
 Deterministically zero one bank under ECC-no-check.
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.
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.
ra8_err_t ra8_sram_get_bank_info (uint8_t bank, ra8_sram_bank_info_t *out)
 Report the static layout of one bank.

Variables

static const char * s_tag = "SRAM"
 Module log tag.
static const ra8_mstp_t s_sram_mstp_table [k_ra8_sram_bank_count]
 Bank-index -> ra8_mstp_t lookup.
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).
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).
static bool s_initialized = false
 Driver init flag (set at end of ra8_sram_init).

Detailed Description

SRAM (with ECC) HAL driver implementation.

Tag
[Ring 3 / HAL] {World: S}

Implements ra8_sram.h. Owns:

  • per-bank module-stop ungate via ra8_mstp (HUM Ch 11.2.6 p 443)
  • per-bank ECC mode programming through SRAMCRn and per-bank region size through SRAMECCRGNn under the SRAMPRCR_S half-word unlock (HUM Ch 58.2.4 / 58.2.7 / 58.2.8..58.2.11)
  • SRAMWTSC wait-state programming with auto-tuning per ICLK frequency (HUM Ch 58.2.6 / 58.3.7)
  • CPSCU SRAMSAR / SRAMESAR / SRAMSABARn security attribution (HUM Ch 58.2.1..58.2.3)
  • deterministic 64-bit zero-init pass before enabling ECC with check mode (HUM Ch 58.3.2)
  • ECC decoder self-test sequence (HUM Ch 58.3.4)
  • SRAMESR / SRAMESCLR / SRAMEAR readout + per-(bank, slot) clear
  • global + per-bank ECC error callback fan-out, including a dispatch_from_esr helper that walks all eight flags

Layered after rx_eccram.c from the STAR project (RX72N) – same shape (PRCR unlock, mode set, error status, ISR trampoline) but with RA8D2's per-bank registers and the 0xA5 key code, plus the additions above to satisfy the full HUM Ch 58 surface.

Definition in file ra8_sram.c.

Enumeration Type Documentation

◆ ra8_sram_local_t

enum ra8_sram_local_t : uint8_t

Internal helpers / shifts / sizes.

Enumerator
k_ra8_sram_eccmod_shift 

ECCMOD field is at bits [3:2] of SRAMCRn.

k_ra8_sram_eccmod_max 

ra8_sram_ecc_mode_t enumerates 0..2.

k_ra8_sram_on_error_max 

OAD is single-bit (0 or 1).

k_ra8_sram_eccrgn_max012 

Largest legal ECCRGN for SRAM0..2.

k_ra8_sram_eccrgn_max3 

Largest legal ECCRGN for SRAM3.

k_ra8_sram_ear_slot_max 

0 (1-bit) or 1 (2-bit).

k_ra8_sram_bank_max_idx 

Last legal bank index.

Definition at line 59 of file ra8_sram.c.

◆ ra8_sram_self_test_inject_t

Bit masks for the ECC self-test fault injection.

Per HUM Ch 58.3.4 "ECC Decoder Testing", p 3539. The bypass-mode read returns 8 bits of syndrome; flipping one or two of those bits before writing back is what makes the verify-step fire SRAMESR.

Enumerator
k_ra8_sram_self_test_flip_1bit 

Flip bit 0 of the syndrome.

k_ra8_sram_self_test_flip_2bit 

Flip bits 0+1 of the syndrome.

Definition at line 78 of file ra8_sram.c.

Function Documentation

◆ internal_apply_per_bank()

void internal_apply_per_bank ( const ra8_sram_config_t * cfg)
static

Apply the per-bank zero-init + ECC mode programming pass.

HUM Ch 58.3.2 p 3538 (zero-init) + HUM Ch 58.2.10 / 58.2.5 (ECC region size + SRAMCRn final mode). Run as one helper so the top-level init stays small.

Parameters
[in]cfgValidated init config.
Precondition
Module clock ungated for every bank.
Postcondition
Each bank's eccrgn + SRAMCRn matches cfg.
Note
Internal helper, not thread-safe.
Precondition
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Since
0.1.0

Definition at line 537 of file ra8_sram.c.

References ra8_sram_config_t::banks, ra8_sram_bank_cfg_t::eccrgn, internal_encode_cr(), internal_write_cr_locked(), internal_write_eccrgn_locked(), internal_zero_init_with_no_check(), k_ra8_sram_bank_count, RA8_INTERNAL, and ra8_sram_bank_cfg_t::zero_init.

Referenced by ra8_sram_init().

◆ internal_apply_security()

void internal_apply_security ( const ra8_sram_security_cfg_t * sec)
static

Apply the optional security cfg from ra8_sram_init.

The CPSCU writes are unconditionally ungated – they belong to the Secure World caller per HUM Ch 58.2.2 (p 3528) and HUM 58.2.3 (p 3529). This helper just walks the cfg fields and writes the three register groups in the order SRAMSAR -> SRAMESAR -> SABARn so boundary writes happen after the per-bank security flag is set.

Parameters
[in]secSee implementation.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 381 of file ra8_sram.c.

References ra8_sram_security_cfg_t::bank_ns, ra8_sram_security_cfg_t::boundary_offset, ra8_sram_security_cfg_t::ecc_region_ns, k_ra8_sram_bank_count, k_ra8_sram_esar_bit_esa, k_ra8_sram_sabar_align_mask, k_ra8_sram_sar_bit_sa0, k_ra8_sram_sar_bit_wtsa, RA8_INTERNAL, ra8_sram_cpscu_regs(), r_sram_cpscu_regs_t::SRAMESAR, r_sram_cpscu_regs_t::SRAMSABAR, r_sram_cpscu_regs_t::SRAMSAR, and ra8_sram_security_cfg_t::wtsc_ns.

Referenced by ra8_sram_init().

◆ internal_decode_esr()

void internal_decode_esr ( uint16_t raw,
uint8_t * one_bit_mask,
uint8_t * two_bit_mask )
static

Compose the per-bank 1-bit / 2-bit error-status masks.

Per HUM Ch 58.2.12 "SRAMESR" p 3535 the bit pattern is ERR{bank}{0=1bit | 1=2bit} packed two bits per bank starting at bit 0. So bit 2*bank is the 1-bit flag and bit 2*bank + 1 is the 2-bit flag.

Parameters
[in]rawSee implementation.
[in]one_bit_maskSee implementation.
[in]two_bit_maskSee implementation.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 322 of file ra8_sram.c.

References k_ra8_sram_bank_count.

Referenced by ra8_sram_get_status().

◆ internal_ear_to_abs_addr()

uintptr_t internal_ear_to_abs_addr ( uint32_t ear)
static

Translate a SRAMEAR offset into its absolute Secure-alias address (per HUM Ch 58.2.14 p 3537).

See implementation.

Parameters
[in]earSee implementation.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 355 of file ra8_sram.c.

References k_ra8_sram_data_base_addr, and RA8_INTERNAL.

Referenced by ra8_sram_get_status().

◆ internal_encode_cr()

uint8_t internal_encode_cr ( const ra8_sram_bank_cfg_t * cfg)
static

Encode a ra8_sram_bank_cfg_t into an SRAMCRn byte value.

Per HUM Ch 58.2.7 "SRAMCRn", p 3532. The TSTBYP bit is left clear here – the self-test routine sets it explicitly when it needs to.

Parameters
[in]cfgSee implementation.
Returns
Result code.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 188 of file ra8_sram.c.

References ra8_sram_bank_cfg_t::ecc_mode, ra8_sram_bank_cfg_t::enable_1bit_latch, k_ra8_sram_cr_mask_e1stsen, k_ra8_sram_cr_mask_oad, k_ra8_sram_ecc_no_check, k_ra8_sram_ecc_with_chk, k_ra8_sram_eccmod_disabled, k_ra8_sram_eccmod_no_check, k_ra8_sram_eccmod_with_chk, k_ra8_sram_on_error_reset, ra8_sram_bank_cfg_t::on_error, and RA8_INTERNAL.

Referenced by internal_apply_per_bank(), and ra8_sram_set_mode().

◆ internal_self_test_inject()

void internal_self_test_inject ( uint8_t bank,
volatile uint64_t * data,
bool inject_two_bit )
static

Inject a 1- or 2-bit fault on a probed ECC line.

Steps 2 and 3 of the HUM Ch 58.3.4 self-test flowchart, p 3539. Writes through SRAMCRn = 0x80 (bypass) so the read returns the raw syndrome, XORs in the requested fault mask, then arms the "ECC+check" mode so the next normal read triggers the latch.

Parameters
[in]bankBank index that owns data.
[in,out]dataPointer to the probed 64-bit ECC line.
[in]inject_two_bittrue to inject a 2-bit fault.
Precondition
data was seeded by step 1 of the flowchart.
Postcondition
Bypass mode left active long enough to corrupt the syndrome, then re-armed for verification.
Note
Internal helper, not thread-safe.
Precondition
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Since
0.1.0

Definition at line 775 of file ra8_sram.c.

References internal_write_cr_locked(), k_ra8_sram_cr_self_test_phase_bypass, k_ra8_sram_cr_self_test_phase_verify, k_ra8_sram_self_test_flip_1bit, and k_ra8_sram_self_test_flip_2bit.

Referenced by ra8_sram_self_test().

◆ internal_validate_and_ungate()

ra8_err_t internal_validate_and_ungate ( const ra8_sram_config_t * cfg)
static

Validate every bank cfg and ungate the corresponding MSTP bits.

HUM Ch 58.3.1 "Module Stop Function" p 3538 + HUM Ch 11.2.6 MSTPCRA p 443. Run as a single pass so a half-applied config never leaks past the init boundary.

Parameters
[in]cfgCaller-supplied init config.
Returns
k_ra8_ok if every bank was validated and ungated.
Precondition
cfg is non-null.
Postcondition
All four SRAM banks are clock-ungated on success; on failure the caller must clean up.
Note
Internal helper, not thread-safe.
Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Since
0.1.0

Definition at line 503 of file ra8_sram.c.

References ra8_sram_config_t::banks, internal_validate_bank_cfg(), k_ra8_ok, k_ra8_sram_bank_count, RA8_INTERNAL, ra8_mstp_enable(), RA8_RETURN_ON_ERROR, s_sram_mstp_table, and s_tag.

Referenced by ra8_sram_init().

◆ internal_validate_bank_cfg()

ra8_err_t internal_validate_bank_cfg ( const ra8_sram_bank_cfg_t * cfg,
uint8_t bank )
static

Validate per-bank config.

Parameters
[in]cfgNon-NULL pointer (caller already checked).
[in]bankBank index (used for the SRAM3 region check).
Returns
k_ra8_ok or k_ra8_err_invalid_arg.

See implementation.

Return values
k_ra8_okOperation succeeded.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 154 of file ra8_sram.c.

References ra8_sram_bank_cfg_t::ecc_mode, ra8_sram_bank_cfg_t::eccrgn, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sram_bank_max_idx, k_ra8_sram_eccmod_max, k_ra8_sram_eccrgn_max012, k_ra8_sram_eccrgn_max3, k_ra8_sram_on_error_max, ra8_sram_bank_cfg_t::on_error, and RA8_INTERNAL.

Referenced by internal_validate_and_ungate(), and ra8_sram_set_mode().

◆ internal_write_cr_locked()

void internal_write_cr_locked ( uint8_t bank,
uint8_t value )
static

Write SRAMCRn for bank under SRAMPRCR_S unlock.

Per HUM Ch 58.2.4 "SRAMPRCR_S" p 3530, writes to SRAMWTSC / SRAMCRn / SRAMECCRGNn are gated by the PR bit which is enabled by writing the half-word 0xA501 (KW=0xA5, PR=1). This function unlocks, writes, and re-locks.

Parameters
[in]bankSee implementation.
[in]valueSee implementation.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 227 of file ra8_sram.c.

References k_ra8_sram_prcr_lock, k_ra8_sram_prcr_unlock, RA8_INTERNAL, ra8_sram_cr_ptr(), ra8_sram_regs(), and r_sram_regs_t::SRAMPRCR_S.

Referenced by internal_apply_per_bank(), internal_self_test_inject(), internal_zero_init_with_no_check(), ra8_sram_deinit(), ra8_sram_self_test(), and ra8_sram_set_mode().

◆ internal_write_eccrgn_locked()

void internal_write_eccrgn_locked ( uint8_t bank,
uint8_t value )
static

Write SRAMECCRGNn for bank under SRAMPRCR_S unlock.

Per HUM Ch 58.2.8..58.2.11 (p 3533-3535) the per-bank ECC region registers share the SRAMPRCR_S protection scheme.

Parameters
[in]bankSee implementation.
[in]valueSee implementation.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 260 of file ra8_sram.c.

References k_ra8_sram_eccrgn_field_msk, k_ra8_sram_prcr_lock, k_ra8_sram_prcr_unlock, RA8_INTERNAL, ra8_sram_eccrgn_ptr(), ra8_sram_regs(), and r_sram_regs_t::SRAMPRCR_S.

Referenced by internal_apply_per_bank(), ra8_sram_deinit(), ra8_sram_set_eccrgn(), and ra8_sram_set_mode().

◆ internal_write_wtsc_locked()

void internal_write_wtsc_locked ( uint8_t value)
static

Write SRAMWTSC under SRAMPRCR_S unlock.

See implementation.

Parameters
[in]valueSee implementation.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 287 of file ra8_sram.c.

References k_ra8_sram_prcr_lock, k_ra8_sram_prcr_unlock, k_ra8_sram_wtsc_msk, RA8_INTERNAL, ra8_sram_regs(), r_sram_regs_t::SRAMPRCR_S, and r_sram_regs_t::SRAMWTSC.

Referenced by ra8_sram_set_wait_state_for_clock().

◆ internal_zero_fill_bank()

void internal_zero_fill_bank ( uint8_t bank)
static

8-byte zero fill across the bank's data window.

Per HUM Ch 58.3.2 (p 3538) and HUM 58.4.2 (p 3541) the SRAM is read in 8-byte units, so the syndrome line is computed per uint64_t. The loop bound is the bank's documented size, divided by 8.

Parameters
[in]bankSee implementation.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 431 of file ra8_sram.c.

References k_ra8_sram_ecc_word_shift, k_ra8_sram_zero_init_word, RA8_INTERNAL, ra8_sram_bank_data_ptr(), and ra8_sram_bank_size_bytes().

Referenced by internal_zero_init_with_no_check().

◆ internal_zero_init_with_no_check()

void internal_zero_init_with_no_check ( uint8_t bank)
static

Run a single bank's deterministic zero-init pass.

The sequence mirrors the STAR rx_eccram_init pattern but adapted for RA8D2's per-bank SRAMCRn:

  1. SRAMCRn = ECCMOD=10b (encode but do not check). Writes from this point produce valid syndromes.
  2. Walk the bank in 8-byte stores, writing zero.
  3. SRAMCRn = ECCMOD=00b (ECC off) so the caller can pick its own final mode via ra8_sram_set_mode.
Parameters
[in]bankSee implementation.
Precondition
Module state is consistent.
Module state is consistent.
Postcondition
Caller-visible state matches the documented contract.
Caller-visible state matches the documented contract.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 462 of file ra8_sram.c.

References internal_write_cr_locked(), internal_zero_fill_bank(), k_ra8_sram_eccmod_disabled, k_ra8_sram_eccmod_no_check, and RA8_INTERNAL.

Referenced by internal_apply_per_bank(), and ra8_sram_zero_init_bank().

◆ ra8_sram_clear_address()

ra8_err_t ra8_sram_clear_address ( uint8_t bank,
uint8_t slot )
nodiscard

Clear the captured EAR address for a single (bank, slot) pair.

Parameters
[in]bankBank index 0..3.
[in]slotk_ra8_sram_ear_slot_1bit or k_ra8_sram_ear_slot_2bit.
Returns
ra8_err_t error code.
Return values
k_ra8_okEAR cleared via the matching SRAMESCLR bit.
k_ra8_err_invalid_argBank or slot out of range.
Precondition
ra8_sram_init has run.
Caller already drained the corresponding callback so a stale address is acceptable.
Postcondition
SRAMEAR[bank][slot] reads back as 0.
SRAMESR.ERR{bank}{slot} is cleared.
Note
Not thread-safe.
Since
0.1.0

Definition at line 717 of file ra8_sram.c.

References k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sram_bank_count, k_ra8_sram_ear_slot_max, ra8_sram_regs(), and r_sram_regs_t::SRAMESCLR.

◆ ra8_sram_clear_status()

ra8_err_t ra8_sram_clear_status ( uint16_t esr_mask)
nodiscard

Clear the listed ECC error bits in SRAMESR (also clears EAR).

Parameters
[in]esr_maskBitmask in SRAMESR encoding (see ra8_sram_esr_bit_t).
Returns
ra8_err_t error code.
Return values
k_ra8_okMask written to SRAMESCLR.
k_ra8_err_invalid_argesr_mask includes reserved bits.
Precondition
ra8_sram_init has run (the register is not PRCR-protected so the precondition is just module-level state).
esr_mask fits in the low 8 bits of SRAMESCLR.
Postcondition
Bits set in esr_mask are cleared in SRAMESR on read-back.
SRAMEAR for the corresponding bank/slot is also cleared (per HUM 58.2.13 p 3536).
Note
Not thread-safe.
Since
0.1.0

Definition at line 705 of file ra8_sram.c.

References k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sram_err_all_mask, ra8_sram_regs(), and r_sram_regs_t::SRAMESCLR.

Referenced by internal_mecc_inject().

◆ ra8_sram_deinit()

ra8_err_t ra8_sram_deinit ( void )
nodiscard

Tear down the driver and re-gate each bank.

Returns
ra8_err_t error code.
Return values
k_ra8_okAlways.
Precondition
Caller has drained any in-flight DMA targeting the SRAM banks.
ra8_sram_init has been called previously (deinit is idempotent even if not, but the log line says "not initialized" in that case).
Postcondition
Each bank's SRAMCRn is cleared (ECC disabled).
Each bank's MSTPCRA bit is set (peripheral clock-gated).
Note
Not thread-safe.
See also
ra8_sram_init
Since
0.1.0

Definition at line 578 of file ra8_sram.c.

References g_sram_on_error, g_sram_on_error_bank, g_sram_on_error_bank_ctx, g_sram_on_error_ctx, internal_write_cr_locked(), internal_write_eccrgn_locked(), k_ra8_ok, k_ra8_sram_bank_count, k_ra8_sram_eccrgn_off, ra8_mstp_disable(), s_initialized, and s_sram_mstp_table.

◆ ra8_sram_enter_stop()

ra8_err_t ra8_sram_enter_stop ( uint8_t bank)
nodiscard

Re-gate a single bank's clock (Module-Stop entry).

Parameters
[in]bankBank index 0..3.
Returns
ra8_err_t error code.
Return values
k_ra8_okBank gated.
k_ra8_err_invalid_argbank >= k_ra8_sram_bank_count.
Precondition
ra8_sram_init has run.
No CPU is currently accessing the bank (HUM 58.3.1 p 3538).
Postcondition
MSTPCRA bit for the bank is set.
Note
Not thread-safe.
Since
0.1.0

Definition at line 607 of file ra8_sram.c.

References k_ra8_err_invalid_arg, k_ra8_sram_bank_count, ra8_mstp_disable(), and s_sram_mstp_table.

◆ ra8_sram_exit_stop()

ra8_err_t ra8_sram_exit_stop ( uint8_t bank)
nodiscard

Re-ungate a single bank's clock (Module-Stop exit).

Parameters
[in]bankBank index 0..3.
Returns
ra8_err_t error code.
Return values
k_ra8_okBank ungated.
k_ra8_err_invalid_argbank >= k_ra8_sram_bank_count.
Precondition
Bank is currently in the Module-Stop state (or never entered).
Caller has not yet started access to the bank.
Postcondition
MSTPCRA bit for the bank is cleared.
Note
Not thread-safe.
Since
0.1.0

Definition at line 616 of file ra8_sram.c.

References k_ra8_err_invalid_arg, k_ra8_sram_bank_count, ra8_mstp_enable(), and s_sram_mstp_table.

◆ ra8_sram_get_bank_info()

ra8_err_t ra8_sram_get_bank_info ( uint8_t bank,
ra8_sram_bank_info_t * out )
nodiscard

Report the static layout of one bank.

Parameters
[in]bankBank index 0..3.
[out]outNon-NULL destination.
Returns
ra8_err_t error code.
Return values
k_ra8_okLayout filled.
k_ra8_err_invalid_argBank out of range.
k_ra8_err_null_ptrout was NULL.
Precondition
out points to writable storage of size ra8_sram_bank_info_t.
bank < k_ra8_sram_bank_count.
Postcondition
out->bank == bank.
out->data_size matches HUM Ch 58.1 Table 58.1 p 3527.
Note
Side-effect free.
Since
0.1.0

Definition at line 841 of file ra8_sram.c.

References ra8_sram_bank_info_t::bank, ra8_sram_bank_info_t::data_base, ra8_sram_bank_info_t::data_size, ra8_sram_bank_info_t::ecc_base, ra8_sram_bank_info_t::ecc_size, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sram_bank_count, k_ra8_sram_data_base_addr, RA8_CHECK_NULL_PTR, ra8_sram_bank_ecc_size_bytes(), ra8_sram_bank_size_bytes(), s_sram_data_off_table, s_sram_ecc_off_table, and s_tag.

Referenced by internal_configure().

◆ ra8_sram_get_status()

ra8_err_t ra8_sram_get_status ( ra8_sram_status_t * out)
nodiscard

Snapshot the current ECC error state across all four banks.

Parameters
[out]outNon-NULL status receiver.
Returns
ra8_err_t error code.
Return values
k_ra8_okStatus copied to *out.
k_ra8_err_null_ptrout was NULL.
Precondition
out points to writable memory of at least sizeof(ra8_sram_status_t) bytes.
Reads from SRAMESR / SRAMEAR are non-destructive.
Postcondition
out->raw_esr matches the live SRAMESR.
out->one_bit_mask / two_bit_mask decode the same value.
Note
Thread-safe with respect to the hardware (read-only path).
Since
0.1.0

Definition at line 682 of file ra8_sram.c.

References ra8_sram_status_t::addr_1bit, ra8_sram_status_t::addr_2bit, internal_decode_esr(), internal_ear_to_abs_addr(), k_ra8_ok, k_ra8_sram_bank_count, ra8_sram_status_t::one_bit_mask, RA8_CHECK_NULL_PTR, ra8_sram_regs(), ra8_sram_status_t::raw_esr, s_tag, r_sram_regs_t::SRAMEAR, r_sram_regs_t::SRAMESR, and ra8_sram_status_t::two_bit_mask.

Referenced by internal_mecc_inject(), internal_sample(), and ra8_sram_dispatch_from_esr().

◆ ra8_sram_init()

ra8_err_t ra8_sram_init ( const ra8_sram_config_t * cfg)
nodiscard

Initialise the SRAM driver and configure each bank.

Parameters
[in]cfgNon-NULL configuration descriptor.
Returns
ra8_err_t error code.
Return values
k_ra8_okDriver initialized, all banks programmed.
k_ra8_err_null_ptrcfg was NULL.
k_ra8_err_invalid_argA bank carries an out-of-range mode value.
k_ra8_err_hw_init_failedMSTP ungate failed for one of the banks.
Precondition
ra8_mstp_init has run.
Caller is in single-threaded init context (writes to SRAMPRCR_S are not thread-safe).
Postcondition
Each bank's MSTPCRA bit is cleared.
Each bank's SRAMCRn matches the requested ecc_mode / on_error / enable_1bit_latch / eccrgn.
Init Sequence:
  1. Validate every bank cfg (mode + region in range).
  2. ra8_mstp_enable per bank (HUM 58.3.1 p 3538).
  3. Optionally apply security cfg via SRAMSAR / SRAMESAR / SRAMSABARn.
  4. For each bank requested in zero_init, run the deterministic ECC zero pass (HUM 58.3.2) before any with-check mode.
  5. Apply per-bank SRAMECCRGNn and SRAMCRn under SRAMPRCR_S unlock.
  6. Clear any latched SRAMESR / EAR state.

SRAMWTSC is not in that list: it belongs to ra8_cgc_init.

Note
Not thread-safe.
Warning
Per HUM 58.2.7 p 3533, enabling ecc_with_chk on uninitialized SRAM can immediately trigger a spurious NMI or reset. Set zero_init = true for any bank where ecc_mode == k_ra8_sram_ecc_with_chk.
See also
ra8_sram_deinit
ra8_sram_zero_init_bank
Since
0.1.0

Definition at line 551 of file ra8_sram.c.

References ra8_sram_config_t::apply_security, internal_apply_per_bank(), internal_apply_security(), internal_validate_and_ungate(), k_ra8_ok, k_ra8_sram_err_all_mask, RA8_CHECK_NULL_PTR, ra8_log_info, RA8_RETURN_ON_ERROR, ra8_sram_regs(), s_initialized, s_tag, ra8_sram_config_t::security, and r_sram_regs_t::SRAMESCLR.

Referenced by internal_configure(), and internal_mecc_configure().

◆ ra8_sram_self_test()

ra8_err_t ra8_sram_self_test ( uint8_t bank,
uint32_t probe_offset,
bool inject_two_bit,
bool * out_caught )
nodiscard

Run the HUM Ch 58.3.4 ECC decoder self-test on one bank.

Implements the eight-step flowchart from HUM p 3539:

  1. Unlock SRAMPRCR_S.
  2. SRAMCRn = 0x08 (ECC, no check, bypass off).
  3. Write 8 bytes of seed data at probe_offset.
  4. SRAMCRn = 0x80 (ECC off, bypass on) – raw syndrome readable.
  5. Read syndrome, XOR inject_mask to corrupt 1 or 2 bits, write back.
  6. SRAMCRn = 0x1C (ECC + check, E1STSEN=1, bypass off).
  7. Read the probed line.
  8. Confirm SRAMESR.ERR{bank}{0|1} latched.

Each step is preceded by a Data Memory Barrier on the real chip; under RA8_OFF_TARGET the barrier is a no-op.

Parameters
[in]bankBank index 0..3.
[in]probe_offsetOffset from the bank base, 8-byte aligned, strictly less than the bank size.
[in]inject_two_bittrue to flip 2 bits (uncorrectable), false to flip 1 bit (correctable).
[out]out_caughttrue if SRAMESR latched the expected flag.
Returns
ra8_err_t error code.
Return values
k_ra8_okSelf-test ran to completion.
k_ra8_err_invalid_argBank/offset/out_caught invalid.
Precondition
ra8_sram_init has run.
Bank is not currently being used by the application; the sequence corrupts probe_offset deliberately.
Postcondition
SRAMCRn is left in 0x1C (ECC + check + 1-bit latch) so the application can re-claim the bank.
*out_caught reflects whether SRAMESR latched the error.
Note
Not thread-safe. Designed for boot-time / diagnostic use.
Since
0.1.0

Definition at line 791 of file ra8_sram.c.

References internal_self_test_inject(), internal_write_cr_locked(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sram_bank_count, k_ra8_sram_cr_self_test_phase_write, k_ra8_sram_ecc_word_bytes, k_ra8_sram_zero_init_word, RA8_CHECK_NULL_PTR, ra8_sram_bank_data_ptr(), ra8_sram_bank_size_bytes(), ra8_sram_regs(), s_tag, and r_sram_regs_t::SRAMESR.

Referenced by internal_mecc_inject().

◆ ra8_sram_set_eccrgn()

ra8_err_t ra8_sram_set_eccrgn ( uint8_t bank,
ra8_sram_eccrgn_size_t region )
nodiscard

Update only the ECC region size (SRAMECCRGNn) for one bank.

Parameters
[in]bankBank index 0..3.
[in]regionOne of ra8_sram_eccrgn_size_t.
Returns
ra8_err_t error code.
Return values
k_ra8_okRegion size applied.
k_ra8_err_invalid_argBank or region out of range, or bank 3 with a region > 128 KB.
Precondition
ra8_sram_init has run.
region matches the HUM Ch 58.2.8..58.2.11 encoding.
Postcondition
SRAMECCRGNn[bank] reflects region.
SRAMPRCR_S is re-locked on return.
Note
Not thread-safe.
Since
0.1.0

Definition at line 647 of file ra8_sram.c.

References internal_write_eccrgn_locked(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sram_bank_count, k_ra8_sram_bank_max_idx, k_ra8_sram_eccrgn_max012, and k_ra8_sram_eccrgn_max3.

◆ ra8_sram_set_mode()

ra8_err_t ra8_sram_set_mode ( uint8_t bank,
const ra8_sram_bank_cfg_t * cfg )
nodiscard

Change the ECC mode of a single bank at runtime.

Parameters
[in]bankBank index 0..3.
[in]cfgNon-NULL bank configuration.
Returns
ra8_err_t error code.
Return values
k_ra8_okBank reprogrammed.
k_ra8_err_null_ptrcfg was NULL.
k_ra8_err_invalid_argbank >= k_ra8_sram_bank_count or cfg->ecc_mode invalid.
Precondition
ra8_sram_init has run.
Bank's MSTPCRA bit is already clear.
Postcondition
SRAMCRn for bank reflects cfg.
SRAMECCRGNn for bank reflects cfg->eccrgn.
SRAMPRCR_S is re-locked on return.
Note
Not thread-safe. Does NOT run the zero-init pass; call ra8_sram_zero_init_bank first if switching to with-check mode on an uninitialized region.
Since
0.1.0

Definition at line 630 of file ra8_sram.c.

References ra8_sram_bank_cfg_t::eccrgn, internal_encode_cr(), internal_validate_bank_cfg(), internal_write_cr_locked(), internal_write_eccrgn_locked(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sram_bank_count, RA8_CHECK_NULL_PTR, RA8_RETURN_ON_ERROR, and s_tag.

◆ ra8_sram_set_wait_state_for_clock()

ra8_err_t ra8_sram_set_wait_state_for_clock ( uint32_t iclk_hz,
uint32_t iclk_max_hz )
nodiscard

Derive SRAMWTSC.WTEN from an ICLK frequency and program it.

The ONLY way this driver writes SRAMWTSC, and deliberately so: the register has exactly one correct value at a given ICLK, so a raw set(bool) setter would only ever be a way to get it wrong.

HUM Ch 58.3.7 "Wait State" p 3540 states the rule and the stakes: above half the rated maximum ICLK a wait cycle must be inserted, and "when the wait is not inserted, the operation is not guaranteed". The observed failure is not a hang – it is a single bit dropped out of a value read back from SRAM at full speed, silently, with the memory itself intact (tracker #524, and the Ethernet TX frame corruption of #499, which is the same fault seen through the GWCA's DMA reads).

Called from ra8_cgc_init before the SCKSCR switch that raises ICLK, so no code ever executes in the unguaranteed window.

Parameters
[in]iclk_hzICLK frequency in Hz, > 0.
[in]iclk_max_hzRated maximum ICLK for the part variant (250e6, 200e6, or 150e6 – HUM 58.3.7); on RA8D2 use k_ra8_iclk_max_hz.
Returns
ra8_err_t error code.
Return values
k_ra8_okWTEN written.
k_ra8_err_invalid_argEither argument is zero.
Precondition
The SRAM control window is reachable (it is out of reset).
iclk_max_hz matches the part-specific datasheet.
Postcondition
WTEN=1 iff iclk_hz > iclk_max_hz / 2.
SRAMPRCR_S is re-locked on return.
Note
Not thread-safe; boot context.
Since
0.1.0

Definition at line 661 of file ra8_sram.c.

References internal_write_wtsc_locked(), k_ra8_err_invalid_arg, k_ra8_ok, and k_ra8_sram_wtsc_wten.

Referenced by internal_cgc_init_protected().

◆ ra8_sram_zero_init_bank()

ra8_err_t ra8_sram_zero_init_bank ( uint8_t bank)
nodiscard

Deterministically zero one bank under ECC-no-check.

Per HUM Ch 58.3.2 "Correction of ECC Errors", p 3538: SRAM contents are undefined after power-on, so reading any address with ECCMOD=11b will fire spurious 2-bit errors. This routine puts the bank into ECCMOD=10b (encode but do not check), writes a 64-bit zero across every word so each line carries a valid syndrome, then leaves the bank in ECC-disabled mode so the caller can pick the final mode via ra8_sram_set_mode.

The fill stride is 8 bytes (HUM 58.4.2 p 3541 – "SRAM are read in 8-byte (64-bit) units"), and the bank size comes from ra8_sram_bank_size_bytes so SRAM3's smaller 128 KB region is handled correctly.

Parameters
[in]bankBank index 0..3.
Returns
ra8_err_t error code.
Return values
k_ra8_okBank zeroed.
k_ra8_err_invalid_argBank out of range.
Precondition
ra8_sram_init has run.
No live data lives in this bank (the routine overwrites everything).
Postcondition
Every 64-bit word in the bank holds 0x00000000_00000000.
Bank is left in ECCMOD=00b (ECC disabled) – caller reprograms via ra8_sram_set_mode if a different mode is desired.
Note
Not thread-safe. Holds SRAMPRCR_S unlocked across two writes.
Since
0.1.0

Definition at line 742 of file ra8_sram.c.

References internal_zero_init_with_no_check(), k_ra8_err_invalid_arg, k_ra8_ok, and k_ra8_sram_bank_count.

Variable Documentation

◆ s_initialized

bool s_initialized = false
static

Driver init flag (set at end of ra8_sram_init).

Definition at line 127 of file ra8_sram.c.

◆ s_sram_data_off_table

const uint32_t s_sram_data_off_table[k_ra8_sram_bank_count]
static
Initial value:
= {
}
@ 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.

Bank-index -> data-window offset (HUM Ch 58.1 Table 58.1, p 3527).

Definition at line 103 of file ra8_sram.c.

Referenced by ra8_sram_get_bank_info().

◆ s_sram_ecc_off_table

const uint32_t s_sram_ecc_off_table[k_ra8_sram_bank_count]
static
Initial value:
= {
}
@ 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.

Bank-index -> ECC syndrome window offset (HUM Ch 58.1, p 3527).

Definition at line 114 of file ra8_sram.c.

Referenced by ra8_sram_get_bank_info().

◆ s_sram_mstp_table

const ra8_mstp_t s_sram_mstp_table[k_ra8_sram_bank_count]
static
Initial value:
= {
}
@ k_ra8_mstp_sram2
MSTPA2 SRAM2.
@ k_ra8_mstp_sram0
MSTPA0 SRAM0.
@ k_ra8_mstp_sram3
MSTPA3 SRAM3.
@ k_ra8_mstp_sram1
MSTPA1 SRAM1.

Bank-index -> ra8_mstp_t lookup.

Per HUM Ch 11.2.6 "MSTPCRA" p 443: bits MSTPA0..MSTPA3 select SRAM0..SRAM3. The shared ra8_mstp.h already exposes typed enum values for these.

Definition at line 92 of file ra8_sram.c.

Referenced by internal_validate_and_ungate(), ra8_sram_deinit(), ra8_sram_enter_stop(), and ra8_sram_exit_stop().

◆ s_tag

const char* s_tag = "SRAM"
static

Module log tag.

Definition at line 53 of file ra8_sram.c.