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

MRAM block-device backend – a hard-fenced data-MRAM window as blocks. More...

#include "ra8_io_blockdev_mram.h"
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_flash.h"
#include "ra8_flash_regs.h"
#include "ra8_io_blockdev.h"
#include "ra8_io_blockdev_backend.h"
Include dependency graph for ra8_io_blockdev_mram.c:

Go to the source code of this file.

Enumerations

enum  ra8_io_mram_const_t : uint32_t {
  k_ra8_io_mram_erase_block_bytes = (uint32_t)k_ra8_mram_block_size_bytes ,
  k_ra8_io_mram_program_bytes = (uint32_t)k_ra8_mram_write_size_bytes ,
  k_ra8_io_mram_erase_unit_blocks = 1U ,
  k_ra8_io_mram_min_blocks = 1U ,
  k_ra8_io_mram_zero_len = 0U
}
 MRAM-backend layout constants. More...

Functions

static ra8_err_t internal_mram_bounds (const ra8_io_blockdev_mram_state_t *st, uint32_t lba, uint32_t count)
 Reject an out-of-range [lba, lba+count) block range.
static ra8_err_t internal_mram_window_ok (uintptr_t base, uint32_t block_count)
 Validate that an MRAM window is erase-aligned and inside data MRAM.
static ra8_err_t internal_mram_read (void *ctx, uint32_t lba, uint32_t count, uint8_t *buf)
 MRAM backend: read count blocks at lba into buf.
static ra8_err_t internal_mram_write (void *ctx, uint32_t lba, uint32_t count, const uint8_t *buf)
 MRAM backend: program count blocks from buf at lba.
static ra8_err_t internal_mram_erase (void *ctx, uint32_t lba, uint32_t count)
 MRAM backend: erase count blocks at lba to all-ones.
static ra8_err_t internal_mram_get_caps (const void *ctx, ra8_io_blockdev_caps_t *out)
 MRAM backend: report medium capabilities.
ra8_err_t ra8_io_blockdev_mram_init (ra8_io_blockdev_t *bd, ra8_io_blockdev_mram_state_t *state, uintptr_t base_addr, uint32_t block_count, bool read_only)
 Bind a hard-fenced MRAM block-device backend into a caller handle.

Variables

static const char *const s_tag = "ra8_io_blockdev_mram"
 Module log tag.
static const ra8_io_blockdev_iface_t s_mram_iface
 MRAM backend vtable.

Detailed Description

MRAM block-device backend – a hard-fenced data-MRAM window as blocks.

Tag
[Ring 4 / PAL] {World: NS}

Implements ra8_io_blockdev_iface over the on-chip extra MRAM region. Reads memcpy from the memory-mapped MRAM array; writes route through ra8_flash_extra_mram_write chunked into the 32-byte MRAM program unit; erases route through ra8_flash_extra_mram_erase, one 32-byte block per call. The window is fenced at bind time to the extra MRAM region and every call is bounds-checked, so no access can reach the code-MRAM .text region. This file touches no raw MMIO – the ra8_flash driver carries the HUM citations.

Warning
The RA8D2 extra MRAM is one-time-programmable option-setting / OTP memory (HUM Ch 59.7.4.5 Table 59.15 p 3592), NOT a rewritable data-flash array – there is no erase-and-reuse cycle on this silicon. A rewritable block backend therefore belongs on a real rewritable medium (OSPI / SD); retargeting this backend and its demos off the OTP window is tracked by #315.

Definition in file ra8_io_blockdev_mram.c.

Enumeration Type Documentation

◆ ra8_io_mram_const_t

enum ra8_io_mram_const_t : uint32_t

MRAM-backend layout constants.

The MRAM program/erase unit is 32 bytes, so one 512-byte logical block maps onto exactly sixteen MRAM erase blocks. The medium erases to all-ones and needs an erase before a program can raise a bit, so callers must treat it as erase-before-write.

Since
0.1.0
Enumerator
k_ra8_io_mram_erase_block_bytes 

MRAM erase/program unit in bytes (32).

k_ra8_io_mram_program_bytes 

MRAM minimum program granularity in bytes (32).

k_ra8_io_mram_erase_unit_blocks 

Logical-block erase granularity: 1 (MRAM erases in 32-byte sub-units).

k_ra8_io_mram_min_blocks 

Smallest legal device size.

k_ra8_io_mram_zero_len 

Sentinel for an empty length.

Definition at line 56 of file ra8_io_blockdev_mram.c.

Function Documentation

◆ internal_mram_bounds()

ra8_err_t internal_mram_bounds ( const ra8_io_blockdev_mram_state_t * st,
uint32_t lba,
uint32_t count )
static

Reject an out-of-range [lba, lba+count) block range.

Split into two single-condition checks (no compound decision) so the bounds test needs no MC/DC vectors and never underflows block_count - count.

Parameters
[in]stMRAM backend state.
[in]lbaFirst logical block address.
[in]countNumber of blocks in the range.
Returns
ra8_err_t Error code.
Return values
k_ra8_okRange lies within the device.
k_ra8_err_out_of_rangeRange extends past the device capacity.
Precondition
st is non-NULL.
st->block_count reflects the fenced window size.
Postcondition
No state is mutated.
The return reflects only the range/capacity comparison.
Note
Thread-safe (pure comparison).
Since
0.1.0

Definition at line 93 of file ra8_io_blockdev_mram.c.

References ra8_io_blockdev_mram_state_t::block_count, k_ra8_err_out_of_range, and k_ra8_ok.

Referenced by internal_mram_erase(), internal_mram_read(), and internal_mram_write().

◆ internal_mram_erase()

ra8_err_t internal_mram_erase ( void * ctx,
uint32_t lba,
uint32_t count )
static

MRAM backend: erase count blocks at lba to all-ones.

Each 512-byte logical block spans sixteen 32-byte MRAM erase blocks, erased one block per ra8_flash_extra_mram_erase call across the range. After success the range reads back as 0xFF.

Parameters
[in]ctxMRAM backend state (as a void cookie).
[in]lbaFirst logical block address.
[in]countNumber of blocks to erase.
Returns
ra8_err_t Error code.
Return values
k_ra8_okRange erased to all-ones.
k_ra8_err_null_ptrctx was NULL.
k_ra8_err_not_supportedThe device is read-only.
k_ra8_err_out_of_rangeRange past capacity.
k_ra8_err_invalid_argThe driver rejected the erase request.
k_ra8_err_hw_errorThe controller reported a program error.
Precondition
ctx is a populated MRAM state.
count is non-zero for any observable effect.
Postcondition
On success the range reads back as 0xFF.
On failure the window may be partially erased (no rollback).
Note
Not thread-safe with respect to the same device.
Since
0.1.0

Definition at line 284 of file ra8_io_blockdev_mram.c.

References ra8_io_blockdev_mram_state_t::base, internal_mram_bounds(), k_ra8_err_not_supported, k_ra8_io_block_size_bytes, k_ra8_io_mram_erase_block_bytes, k_ra8_io_mram_zero_len, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_flash_extra_mram_erase(), RA8_INTERNAL, ra8_io_blockdev_mram_state_t::read_only, and s_tag.

◆ internal_mram_get_caps()

ra8_err_t internal_mram_get_caps ( const void * ctx,
ra8_io_blockdev_caps_t * out )
static

MRAM backend: report medium capabilities.

Reports an all-ones-erase, erase-before-write medium with a 32-byte program unit, sized by the fenced window.

Parameters
[in]ctxMRAM backend state (as a const void cookie).
[out]outCapabilities snapshot.
Returns
ra8_err_t Error code.
Return values
k_ra8_ok*out populated.
k_ra8_err_null_ptrctx or out was NULL.
Precondition
ctx is a populated MRAM state.
out is writable.
Postcondition
On success *out describes an all-ones-erase, erase-before-write medium.
No state is mutated.
Note
Thread-safe (pure read).
Since
0.1.0

Definition at line 331 of file ra8_io_blockdev_mram.c.

References ra8_io_blockdev_caps_t::block_count, ra8_io_blockdev_mram_state_t::block_count, ra8_io_blockdev_caps_t::erase_unit_blocks, ra8_io_blockdev_caps_t::erase_value, k_ra8_io_block_size_bytes, k_ra8_io_erase_value_ones, k_ra8_io_mram_erase_unit_blocks, k_ra8_io_mram_program_bytes, k_ra8_ok, ra8_io_blockdev_caps_t::logical_block_bytes, ra8_io_blockdev_caps_t::must_erase_before_write, ra8_io_blockdev_caps_t::program_size_bytes, RA8_CHECK_NULL_PTR, RA8_INTERNAL, ra8_io_blockdev_caps_t::read_only, ra8_io_blockdev_mram_state_t::read_only, and s_tag.

◆ internal_mram_read()

ra8_err_t internal_mram_read ( void * ctx,
uint32_t lba,
uint32_t count,
uint8_t * buf )
static

MRAM backend: read count blocks at lba into buf.

MRAM is memory-mapped, so the read is a bounds-checked memcpy from the device window. No ra8_flash call is needed for reads.

Parameters
[in]ctxMRAM backend state (as a void cookie).
[in]lbaFirst logical block address.
[in]countNumber of blocks to read.
[out]bufDestination buffer.
Returns
ra8_err_t Error code.
Return values
k_ra8_okBlocks copied into buf.
k_ra8_err_null_ptrctx or buf was NULL.
k_ra8_err_out_of_rangeRange past capacity.
Precondition
ctx is a populated MRAM state.
buf is writable for count * 512 bytes.
Postcondition
On success buf mirrors the MRAM window contents.
On failure buf is untouched.
Note
Not thread-safe with respect to the same device.
Since
0.1.0

Definition at line 182 of file ra8_io_blockdev_mram.c.

References ra8_io_blockdev_mram_state_t::base, internal_mram_bounds(), k_ra8_io_block_size_bytes, k_ra8_ok, memcpy(), RA8_CHECK_NULL_PTR, and s_tag.

◆ internal_mram_window_ok()

ra8_err_t internal_mram_window_ok ( uintptr_t base,
uint32_t block_count )
static

Validate that an MRAM window is erase-aligned and inside data MRAM.

Enforces the hard fence: the base must be erase-block aligned, the byte span must be a whole number of erase blocks, and the window must lie wholly inside the extra/data MRAM region – which is disjoint from (and above) code MRAM, so no access can reach the .text region. Each predicate is its own single-condition check so the fence needs no MC/DC vectors and cannot underflow.

Parameters
[in]baseFirst MRAM byte address of the window.
[in]block_countNumber of 512-byte logical blocks (>= 1).
Returns
ra8_err_t Error code.
Return values
k_ra8_okWindow is aligned and inside data MRAM.
k_ra8_err_invalid_argWindow misaligned, sized wrong, or out of region.
Precondition
block_count is non-zero.
The extra/data MRAM region constants describe the live silicon.
Postcondition
No state is mutated.
On success the window cannot reach code MRAM.
Note
Thread-safe (pure comparison).
Since
0.1.0

Definition at line 131 of file ra8_io_blockdev_mram.c.

References k_ra8_err_invalid_arg, k_ra8_flash_extra_size, k_ra8_flash_extra_start, k_ra8_io_block_size_bytes, k_ra8_io_mram_erase_block_bytes, k_ra8_ok, and RA8_INTERNAL.

Referenced by ra8_io_blockdev_mram_init().

◆ internal_mram_write()

ra8_err_t internal_mram_write ( void * ctx,
uint32_t lba,
uint32_t count,
const uint8_t * buf )
static

MRAM backend: program count blocks from buf at lba.

Routes the write through ra8_flash_extra_mram_write in 32-byte program-unit chunks (the driver's program granularity). The range is bounds-checked first and the device read-only flag is honoured.

Parameters
[in]ctxMRAM backend state (as a void cookie).
[in]lbaFirst logical block address.
[in]countNumber of blocks to write.
[in]bufSource buffer.
Returns
ra8_err_t Error code.
Return values
k_ra8_okBlocks programmed into the MRAM window.
k_ra8_err_null_ptrctx or buf was NULL.
k_ra8_err_not_supportedThe device is read-only.
k_ra8_err_out_of_rangeRange past capacity.
k_ra8_err_invalid_argThe driver rejected the program request.
k_ra8_err_hw_errorThe controller reported a program error.
Precondition
ctx is a populated MRAM state.
buf is readable for count * 512 bytes.
Postcondition
On success the MRAM window reflects buf.
On failure earlier chunks may already be committed (no rollback).
Note
Not thread-safe with respect to the same device.
Since
0.1.0

Definition at line 229 of file ra8_io_blockdev_mram.c.

References ra8_io_blockdev_mram_state_t::base, internal_mram_bounds(), k_ra8_err_not_supported, k_ra8_io_block_size_bytes, k_ra8_io_mram_program_bytes, k_ra8_io_mram_zero_len, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_flash_extra_mram_write(), ra8_io_blockdev_mram_state_t::read_only, and s_tag.

◆ ra8_io_blockdev_mram_init()

ra8_err_t ra8_io_blockdev_mram_init ( ra8_io_blockdev_t * bd,
ra8_io_blockdev_mram_state_t * state,
uintptr_t base_addr,
uint32_t block_count,
bool read_only )
nodiscard

Bind a hard-fenced MRAM block-device backend into a caller handle.

Validates the requested window aggressively, records it in state, marks it read-only per read_only, and points bd at the MRAM vtable with state as its context. No allocation occurs; the caller owns both bd and state.

The window [base_addr, base_addr + block_count * 512) must be erase-block aligned, an integral number of erase blocks, wholly inside the extra/data MRAM region, and must not overlap the code-MRAM .text region. Any violation leaves bd and state untouched and returns k_ra8_err_invalid_arg.

Parameters
[out]bdHandle to bind (zero-initialised by the caller).
[out]stateCaller-owned backend state to populate.
[in]base_addrFirst MRAM byte address of the window (erase aligned).
[in]block_countNumber of 512-byte logical blocks (>= 1).
[in]read_onlytrue to reject writes and erases on this device.
Returns
ra8_err_t Error code.
Return values
k_ra8_okBackend bound; bd is usable.
k_ra8_err_null_ptrbd or state was NULL.
k_ra8_err_invalid_argblock_count was zero, the window was misaligned, not a whole number of erase blocks, outside the extra/data MRAM region, or overlapped code MRAM.
Precondition
bd and state out-live every call made through the device.
ra8_flash_init (or ra8_flash_open) has been called before any write.
Postcondition
On success bd dispatches to the MRAM backend over the fenced window.
On any non-ok return bd and state are left unbound/untouched.
Note
Not thread-safe with respect to the same device.
Warning
The bound window is the ONLY range this device can ever touch; the fence is what keeps writes and erases out of the running .text.
See also
ra8_io_blockdev_ram_init
Since
0.1.0

Definition at line 355 of file ra8_io_blockdev_mram.c.

References ra8_io_blockdev_mram_state_t::base, ra8_io_blockdev_mram_state_t::block_count, ra8_io_blockdev_t::ctx, ra8_io_blockdev_t::iface, internal_mram_window_ok(), k_ra8_err_invalid_arg, k_ra8_io_mram_min_blocks, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_io_blockdev_mram_state_t::read_only, s_mram_iface, and s_tag.

Referenced by demo_open(), and internal_demo_open().

Variable Documentation

◆ s_mram_iface

const ra8_io_blockdev_iface_t s_mram_iface
static
Initial value:
= {
.sync = nullptr,
}
static ra8_err_t internal_mram_erase(void *ctx, uint32_t lba, uint32_t count)
MRAM backend: erase count blocks at lba to all-ones.
static ra8_err_t internal_mram_write(void *ctx, uint32_t lba, uint32_t count, const uint8_t *buf)
MRAM backend: program count blocks from buf at lba.
static ra8_err_t internal_mram_get_caps(const void *ctx, ra8_io_blockdev_caps_t *out)
MRAM backend: report medium capabilities.
static ra8_err_t internal_mram_read(void *ctx, uint32_t lba, uint32_t count, uint8_t *buf)
MRAM backend: read count blocks at lba into buf.

MRAM backend vtable.

sync NULL: ra8_flash_extra_mram_write commits inline.

Definition at line 347 of file ra8_io_blockdev_mram.c.

Referenced by ra8_io_blockdev_mram_init().

◆ s_tag

const char* const s_tag = "ra8_io_blockdev_mram"
static

Module log tag.

Definition at line 42 of file ra8_io_blockdev_mram.c.