|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
SRAM (with ECC) HAL driver public API. More...
Go to the source code of this file.
Data Structures | |
| struct | ra8_sram_bank_cfg_t |
| Per-bank ECC configuration descriptor. More... | |
| struct | ra8_sram_security_cfg_t |
| TrustZone security attribution configured at init time. More... | |
| struct | ra8_sram_config_t |
| Top-level driver configuration. More... | |
| struct | ra8_sram_status_t |
| Snapshot of ECC error state (filled by ra8_sram_get_status). More... | |
| struct | ra8_sram_bank_info_t |
| Static description of one bank. More... | |
Typedefs | |
| typedef void(* | ra8_sram_error_fn_t) (void *ctx, uint8_t bank, bool is_2bit, uintptr_t err_addr) |
| ECC error callback signature. | |
Enumerations | |
| enum | ra8_sram_ecc_mode_t : uint8_t { k_ra8_sram_ecc_disabled = 0U , k_ra8_sram_ecc_no_check = 1U , k_ra8_sram_ecc_with_chk = 2U } |
| ECC operating mode for a single SRAM bank. More... | |
| enum | ra8_sram_on_error_t : uint8_t { k_ra8_sram_on_error_interrupt = 0U , k_ra8_sram_on_error_reset = 1U } |
| Action taken when ECC error is detected (mirrors SRAMCRn.OAD). More... | |
| enum | ra8_sram_eccrgn_size_t : uint8_t { k_ra8_sram_region_off = 0U , k_ra8_sram_region_128kb = 1U , k_ra8_sram_region_256kb = 2U , k_ra8_sram_region_384kb = 3U , k_ra8_sram_region_512kb = 4U } |
| Public form of SRAMECCRGNn.ECCRGN (per-bank ECC region size). More... | |
Functions | |
| 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. | |
| 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. | |
| ra8_err_t | ra8_sram_set_security (uint32_t sa_mask) |
| Write SRAMSAR (per-bank register security + WTSC security). | |
| ra8_err_t | ra8_sram_set_ecc_security (bool non_secure) |
| Write SRAMESAR (ECC region security). | |
| ra8_err_t | ra8_sram_set_boundary (uint8_t bank, uint32_t offset) |
| Write SRAMSABARn (per-bank Secure/Non-Secure boundary). | |
| ra8_err_t | ra8_sram_attach_handler (ra8_sram_error_fn_t fn, void *ctx) |
| Attach the global ECC error callback. | |
| ra8_err_t | ra8_sram_attach_bank_handler (uint8_t bank, ra8_sram_error_fn_t fn, void *ctx) |
| Attach a per-bank ECC error callback. | |
| void | ra8_sram_dispatch (uint8_t bank, bool is_2bit, uintptr_t err_addr) |
| Dispatch an ECC error event to the registered handler. | |
| uint16_t | ra8_sram_dispatch_from_esr (ra8_sram_status_t *out_status) |
| Read SRAMESR + EAR and dispatch every latched flag. | |
SRAM (with ECC) HAL driver public API.
Full HUM Ch 58 (p 3527-3541) coverage of the on-chip SRAM. The RA8D2 has 2 MB of SRAM split across four banks (SRAM0..SRAM2 = 512 KB each, SRAM3 = 128 KB) with optional SEC-DED (64-bit data + 8-bit syndrome) ECC.
Public surface:
Definition in file ra8_sram.h.
| typedef void(* ra8_sram_error_fn_t) (void *ctx, uint8_t bank, bool is_2bit, uintptr_t err_addr) |
ECC error callback signature.
| [in] | ctx | Caller-supplied opaque context pointer. |
| [in] | bank | Bank index 0..3 that raised the error. |
| [in] | is_2bit | true for 2-bit (uncorrectable), false for 1-bit. |
| [in] | err_addr | Faulting offset from the SRAM bank base. |
Definition at line 221 of file ra8_sram.h.
| enum ra8_sram_ecc_mode_t : uint8_t |
ECC operating mode for a single SRAM bank.
Mirrors SRAMCRn.ECCMOD[1:0] (HUM Ch 58.2.7 p 3532). The 01b encoding is documented as "Setting prohibited" and is not exposed.
| Enumerator | |
|---|---|
| k_ra8_sram_ecc_disabled | ECC off (00b). Default at reset. |
| k_ra8_sram_ecc_no_check | ECC encode/correct, no error reporting (10b). |
| k_ra8_sram_ecc_with_chk | Full ECC (11b) – raises NMI / reset. |
Definition at line 68 of file ra8_sram.h.
| enum ra8_sram_eccrgn_size_t : uint8_t |
Public form of SRAMECCRGNn.ECCRGN (per-bank ECC region size).
Per HUM Ch 58.2.8..58.2.11, p 3533-3535. SRAM0..SRAM2 step in 128 KB increments up to 512 KB. SRAM3 only ever holds the 128 KB encoding (any larger value is "Setting prohibited" for that bank).
Definition at line 95 of file ra8_sram.h.
| enum ra8_sram_on_error_t : uint8_t |
Action taken when ECC error is detected (mirrors SRAMCRn.OAD).
Per HUM Ch 58.2.7 "OAD bit" p 3533: 0=NMI, 1=Reset.
| Enumerator | |
|---|---|
| k_ra8_sram_on_error_interrupt | Raise NMI on ECC error. |
| k_ra8_sram_on_error_reset | Reset the MCU on ECC error. |
Definition at line 81 of file ra8_sram.h.
|
nodiscard |
Attach a per-bank ECC error callback.
| [in] | bank | Bank index 0..3. |
| [in] | fn | Non-NULL handler. |
| [in] | ctx | Opaque context pointer. |
| k_ra8_ok | Handler installed for this bank only. |
| k_ra8_err_null_ptr | fn was NULL. |
| k_ra8_err_invalid_arg | Bank out of range. |
Definition at line 128 of file ra8_sram_security.c.
References g_sram_on_error_bank, g_sram_on_error_bank_ctx, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sram_bank_count, RA8_CHECK_NULL_PTR, and s_tag.
|
nodiscard |
Attach the global ECC error callback.
| [in] | fn | Non-NULL handler invoked from the NMI ISR (or test code). |
| [in] | ctx | Opaque context pointer forwarded to the handler. |
| k_ra8_ok | Handler installed. |
| k_ra8_err_null_ptr | fn was NULL. |
Definition at line 119 of file ra8_sram_security.c.
References g_sram_on_error, g_sram_on_error_ctx, k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.
|
nodiscard |
Clear the captured EAR address for a single (bank, slot) pair.
| [in] | bank | Bank index 0..3. |
| [in] | slot | k_ra8_sram_ear_slot_1bit or k_ra8_sram_ear_slot_2bit. |
| k_ra8_ok | EAR cleared via the matching SRAMESCLR bit. |
| k_ra8_err_invalid_arg | Bank or slot out of range. |
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.
|
nodiscard |
Clear the listed ECC error bits in SRAMESR (also clears EAR).
| [in] | esr_mask | Bitmask in SRAMESR encoding (see ra8_sram_esr_bit_t). |
| k_ra8_ok | Mask written to SRAMESCLR. |
| k_ra8_err_invalid_arg | esr_mask includes reserved bits. |
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().
|
nodiscard |
Tear down the driver and re-gate each bank.
| k_ra8_ok | Always. |
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.
| void ra8_sram_dispatch | ( | uint8_t | bank, |
| bool | is_2bit, | ||
| uintptr_t | err_addr ) |
Dispatch an ECC error event to the registered handler.
| [in] | bank | Bank index 0..3 (out-of-range silently ignored). |
| [in] | is_2bit | true for uncorrectable, false for 1-bit. |
| [in] | err_addr | Faulting offset (from SRAMEARnm). |
Fires both the global handler (if attached) and the per-bank handler (if attached). Out-of-range bank is silently ignored so the caller can blindly walk SRAMESR bits.
Definition at line 139 of file ra8_sram_security.c.
References g_sram_on_error, g_sram_on_error_bank, g_sram_on_error_bank_ctx, g_sram_on_error_ctx, and k_ra8_sram_bank_count.
Referenced by ra8_sram_dispatch_from_esr().
| uint16_t ra8_sram_dispatch_from_esr | ( | ra8_sram_status_t * | out_status | ) |
Read SRAMESR + EAR and dispatch every latched flag.
The intended NMI path: snapshots SRAMESR once, walks each of the 8 defined error bits, calls ra8_sram_dispatch for every set bit with the corresponding EAR address, and returns the OR of all dispatched flags so the caller can clear them in a single SRAMESCLR write.
| [out] | out_status | Optional snapshot of the SRAMESR / EAR state (may be NULL if the caller does not need it). |
| k_ra8_ok | Operation succeeded. |
Definition at line 156 of file ra8_sram_security.c.
References ra8_sram_status_t::addr_1bit, ra8_sram_status_t::addr_2bit, k_ra8_ok, k_ra8_sram_bank_count, ra8_sram_dispatch(), ra8_sram_get_status(), and ra8_sram_status_t::raw_esr.
|
nodiscard |
Re-gate a single bank's clock (Module-Stop entry).
| [in] | bank | Bank index 0..3. |
| k_ra8_ok | Bank gated. |
| k_ra8_err_invalid_arg | bank >= k_ra8_sram_bank_count. |
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.
|
nodiscard |
Re-ungate a single bank's clock (Module-Stop exit).
| [in] | bank | Bank index 0..3. |
| k_ra8_ok | Bank ungated. |
| k_ra8_err_invalid_arg | bank >= k_ra8_sram_bank_count. |
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.
|
nodiscard |
Report the static layout of one bank.
| [in] | bank | Bank index 0..3. |
| [out] | out | Non-NULL destination. |
| k_ra8_ok | Layout filled. |
| k_ra8_err_invalid_arg | Bank out of range. |
| k_ra8_err_null_ptr | out was NULL. |
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().
|
nodiscard |
Snapshot the current ECC error state across all four banks.
| [out] | out | Non-NULL status receiver. |
| k_ra8_ok | Status copied to *out. |
| k_ra8_err_null_ptr | out was NULL. |
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().
|
nodiscard |
Initialise the SRAM driver and configure each bank.
| [in] | cfg | Non-NULL configuration descriptor. |
| k_ra8_ok | Driver initialized, all banks programmed. |
| k_ra8_err_null_ptr | cfg was NULL. |
| k_ra8_err_invalid_arg | A bank carries an out-of-range mode value. |
| k_ra8_err_hw_init_failed | MSTP ungate failed for one of the banks. |
SRAMWTSC is not in that list: it belongs to ra8_cgc_init.
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().
|
nodiscard |
Run the HUM Ch 58.3.4 ECC decoder self-test on one bank.
Implements the eight-step flowchart from HUM p 3539:
Each step is preceded by a Data Memory Barrier on the real chip; under RA8_OFF_TARGET the barrier is a no-op.
| [in] | bank | Bank index 0..3. |
| [in] | probe_offset | Offset from the bank base, 8-byte aligned, strictly less than the bank size. |
| [in] | inject_two_bit | true to flip 2 bits (uncorrectable), false to flip 1 bit (correctable). |
| [out] | out_caught | true if SRAMESR latched the expected flag. |
| k_ra8_ok | Self-test ran to completion. |
| k_ra8_err_invalid_arg | Bank/offset/out_caught invalid. |
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().
|
nodiscard |
Write SRAMSABARn (per-bank Secure/Non-Secure boundary).
| [in] | bank | Bank index 0..3. |
| [in] | offset | Boundary offset inside the bank's 0x80000-byte slot (must be 4 KB aligned per HUM 58.2.1 p 3527). |
| k_ra8_ok | SABAR updated. |
| k_ra8_err_invalid_arg | Bank or offset rejected. |
Definition at line 99 of file ra8_sram_security.c.
References k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sram_bank_count, k_ra8_sram_sabar_align_mask, ra8_sram_cpscu_regs(), and r_sram_cpscu_regs_t::SRAMSABAR.
|
nodiscard |
Write SRAMESAR (ECC region security).
| [in] | non_secure | true -> SRAMESA=1 (NS); false -> Secure. |
| k_ra8_ok | Always. |
Definition at line 86 of file ra8_sram_security.c.
References k_ra8_ok, k_ra8_sram_esar_bit_esa, ra8_sram_cpscu_regs(), and r_sram_cpscu_regs_t::SRAMESAR.
|
nodiscard |
Update only the ECC region size (SRAMECCRGNn) for one bank.
| [in] | bank | Bank index 0..3. |
| [in] | region | One of ra8_sram_eccrgn_size_t. |
| k_ra8_ok | Region size applied. |
| k_ra8_err_invalid_arg | Bank or region out of range, or bank 3 with a region > 128 KB. |
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.
|
nodiscard |
Change the ECC mode of a single bank at runtime.
| [in] | bank | Bank index 0..3. |
| [in] | cfg | Non-NULL bank configuration. |
| k_ra8_ok | Bank reprogrammed. |
| k_ra8_err_null_ptr | cfg was NULL. |
| k_ra8_err_invalid_arg | bank >= k_ra8_sram_bank_count or cfg->ecc_mode invalid. |
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.
|
nodiscard |
Write SRAMSAR (per-bank register security + WTSC security).
| [in] | sa_mask | Bitmask of ra8_sram_sar_bit_t values. |
| k_ra8_ok | SAR register updated. |
| k_ra8_err_invalid_arg | sa_mask includes undefined bits. |
Definition at line 74 of file ra8_sram_security.c.
References k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_sram_sar_writable, ra8_sram_cpscu_regs(), and r_sram_cpscu_regs_t::SRAMSAR.
|
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.
| [in] | iclk_hz | ICLK frequency in Hz, > 0. |
| [in] | iclk_max_hz | Rated maximum ICLK for the part variant (250e6, 200e6, or 150e6 – HUM 58.3.7); on RA8D2 use k_ra8_iclk_max_hz. |
| k_ra8_ok | WTEN written. |
| k_ra8_err_invalid_arg | Either argument is zero. |
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().
|
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.
| [in] | bank | Bank index 0..3. |
| k_ra8_ok | Bank zeroed. |
| k_ra8_err_invalid_arg | Bank out of range. |
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.