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

ra8_io block-device fabric – one LBA vtable across every storage medium. More...

#include <stdint.h>
#include "ra8_err.h"
#include "ra8_fs.h"
Include dependency graph for ra8_io_blockdev.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ra8_io_blockdev_caps_t
 Static properties a backend reports about its medium. More...
struct  ra8_io_blockdev_t
 Caller-allocated block-device handle binding a backend to its context. More...

Typedefs

typedef struct ra8_io_blockdev_iface ra8_io_blockdev_iface_t

Enumerations

enum  ra8_io_block_size_t : uint16_t { k_ra8_io_block_size_bytes = 512 }
 Logical block size of the fabric. More...
enum  ra8_io_erase_value_t : uint8_t {
  k_ra8_io_erase_value_zero = 0x00 ,
  k_ra8_io_erase_value_ones = 0xFF
}
 Byte value a block reads back as after a successful erase. More...

Functions

ra8_err_t ra8_io_blockdev_read (const ra8_io_blockdev_t *bd, uint32_t lba, uint32_t count, uint8_t *buf)
 Read count logical blocks starting at lba into buf.
ra8_err_t ra8_io_blockdev_write (const ra8_io_blockdev_t *bd, uint32_t lba, uint32_t count, const uint8_t *buf)
 Write count logical blocks from buf starting at lba.
ra8_err_t ra8_io_blockdev_erase (const ra8_io_blockdev_t *bd, uint32_t lba, uint32_t count)
 Erase count blocks starting at lba to the medium's erase value.
ra8_err_t ra8_io_blockdev_get_caps (const ra8_io_blockdev_t *bd, ra8_io_blockdev_caps_t *out)
 Report the bound backend's medium capabilities.
ra8_err_t ra8_io_blockdev_sync (const ra8_io_blockdev_t *bd)
 Flush any backend write buffering to the medium.
ra8_err_t ra8_io_blockdev_as_fs_backend (const ra8_io_blockdev_t *bd, ra8_fs_backend_t *out)
 Expose a bound block device as an ra8_fs_backend_t for ra8_fs.

Detailed Description

ra8_io block-device fabric – one LBA vtable across every storage medium.

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

A block device exposes fixed-size logical blocks (sectors) addressed by a Logical Block Address (LBA). This header defines the single block-device interface every storage backend implements – SD-over-SPI, native SDHI, OSPI NOR flash, MRAM, an SDRAM ramdisk, a hosted USB mass-storage device, and a pure-RAM scratch device – so the layers above (filesystem, cache, VFS) never name a peripheral.

The interface generalises the ra8_fs_backend_t seam the FAT filesystem already runs on: it keeps the same 512-byte logical block but adds an explicit capability query (erase granularity, program size, erase value, read-only, must-erase-before-write) so the filesystem and the write-back cache can do correct read-modify-write on flash media. ra8_io_blockdev_as_fs_backend() bridges any backend back to an ra8_fs_backend_t, so existing ra8_fs mounts unchanged on top of any medium.

Backend model

The handle (ra8_io_blockdev_t) is caller-allocated – declare one per device and bind a backend into it with that backend's _init() helper (see ra8_io_blockdev_ram.h and friends). No dynamic allocation occurs; backends keep their state in caller-provided storage. Multiple devices coexist because each owns its own handle and context.

static uint8_t s_disk[64U * 512U];
(void)ra8_io_blockdev_as_fs_backend(&bd, &be); // FAT now runs on the ramdisk
static uint8_t s_disk[(size_t) k_demo_disk_blocks *(size_t) k_ra8_io_block_size_bytes]
256 KiB RAM-disk backing buffer (in SRAM .bss) for the "ram" mount.
Definition main.c:75
ra8_err_t ra8_io_blockdev_as_fs_backend(const ra8_io_blockdev_t *bd, ra8_fs_backend_t *out)
Expose a bound block device as an ra8_fs_backend_t for ra8_fs.
ra8_err_t ra8_io_blockdev_ram_init(ra8_io_blockdev_t *bd, ra8_io_blockdev_ram_state_t *state, uint8_t *storage, uint32_t block_count, bool read_only)
Bind a RAM block-device backend into a caller-owned handle.
static uint32_t s_state
Block-device interface that ra8_fs runs on top of.
Caller-owned private state for a RAM block device.
Caller-allocated block-device handle binding a backend to its context.

Boundary with ra8_vsource

This block device is the read/write/erase storage seam at [Ring 4 / PAL]. It is deliberately distinct from ra8_vsource (ra8_vsource.h, [Ring 2 / Core]), the read-only byte-offset view that feeds the #147 page cache. The split is intentional, not drift: a Ring-2 source must not depend on this Ring-4 fabric, since that would invert ring ordering (see docs/RING_AND_WORLD.md). The sanctioned bridge is the Ring-4 adapter ra8_io_blockdev_vsource.h, which exposes a bound block device as a ra8_vsource_read_fn so it can be wired into the page cache via ra8_vsource_add_paged.

Since
0.1.0

Definition in file ra8_io_blockdev.h.

Typedef Documentation

◆ ra8_io_blockdev_iface_t

Definition at line 158 of file ra8_io_blockdev.h.

Enumeration Type Documentation

◆ ra8_io_block_size_t

enum ra8_io_block_size_t : uint16_t

Logical block size of the fabric.

The fabric, like ra8_fs, addresses storage in 512-byte logical blocks. A backend whose medium has a different native sector or page size adapts to this logical size internally (e.g. NOR flash buffers a program/erase unit).

Since
0.1.0
Enumerator
k_ra8_io_block_size_bytes 

Bytes per logical block (the only size).

Definition at line 86 of file ra8_io_blockdev.h.

◆ ra8_io_erase_value_t

enum ra8_io_erase_value_t : uint8_t

Byte value a block reads back as after a successful erase.

RAM-backed media return zero after erase; NOR flash and MRAM return all-ones. The bridge to ra8_fs_backend_t consults this so it only advertises a zero-guaranteeing erase to the formatter (ra8_fs requires erased ranges to read back as 0x00).

Since
0.1.0
Enumerator
k_ra8_io_erase_value_zero 

Block reads back as 0x00 after erase.

k_ra8_io_erase_value_ones 

Block reads back as 0xFF after erase.

Definition at line 102 of file ra8_io_blockdev.h.

Function Documentation

◆ ra8_io_blockdev_as_fs_backend()

ra8_err_t ra8_io_blockdev_as_fs_backend ( const ra8_io_blockdev_t * bd,
ra8_fs_backend_t * out )
nodiscard

Expose a bound block device as an ra8_fs_backend_t for ra8_fs.

Fills out with trampolines that forward ra8_fs's read_block / write_block / get_capacity / erase_blocks calls into this fabric, with out->ctx pointing at bd. The erase trampoline advertises itself to the formatter only when the medium erases to zero (ra8_fs requires erased ranges to read back as 0x00); on all-ones flash it returns k_ra8_err_not_supported so the formatter falls back to writing zeros. After this call any existing ra8_fs API (ra8_fs_mount, ra8_fs_format, ...) works on the bound medium.

Parameters
[in]bdBound block-device handle (must out-live the filesystem use).
[out]outra8_fs_backend_t to populate.
Returns
ra8_err_t Error code.
Return values
k_ra8_ok*out wired to bd.
k_ra8_err_null_ptrbd or out was NULL.
k_ra8_err_not_initializedNo backend is bound to bd.
Precondition
A backend has been bound into bd.
out is writable and out-lives every filesystem call.
Postcondition
On success out's callbacks and ctx reference bd.
No device or handle state is mutated.
Note
bd must remain valid for the entire lifetime of the resulting mount.
Since
0.1.0

Definition at line 307 of file ra8_io_blockdev.c.

References ra8_fs_backend_t::ctx, ra8_fs_backend_t::erase_blocks, ra8_fs_backend_t::get_capacity, internal_fs_erase(), internal_fs_get_capacity(), internal_fs_read(), internal_fs_write(), internal_validate(), k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_fs_backend_t::read_block, s_tag, and ra8_fs_backend_t::write_block.

Referenced by fileops_mount_volume(), internal_demo_mount(), internal_demo_mount(), internal_demo_probe_fat(), internal_demo_probe_foreign(), internal_swap_run_one(), ra8_io_roundtrip_mount(), sdhi_demo_mount_via_io(), selftest_mount_volume(), selftest_mount_volume(), selftest_mount_volume(), selftest_mount_volume(), and selftest_mount_volume().

◆ ra8_io_blockdev_erase()

ra8_err_t ra8_io_blockdev_erase ( const ra8_io_blockdev_t * bd,
uint32_t lba,
uint32_t count )
nodiscard

Erase count blocks starting at lba to the medium's erase value.

After a successful erase the range reads back as caps.erase_value (zero for RAM media, all-ones for NOR/MRAM). Backends whose medium has no erase concept may omit the operation, in which case this returns k_ra8_err_not_supported.

Parameters
[in]bdBound block-device handle.
[in]lbaFirst logical block address to erase.
[in]countNumber of consecutive blocks to erase.
Returns
ra8_err_t Error code.
Return values
k_ra8_okRange erased.
k_ra8_err_null_ptrbd was NULL.
k_ra8_err_not_initializedNo backend is bound to bd.
k_ra8_err_not_supportedThe backend has no erase primitive.
k_ra8_err_out_of_rangelba + count exceeds the device capacity.
Precondition
A backend has been bound into bd.
count is non-zero for any observable effect.
Postcondition
On success the range reads back as caps.erase_value.
On any non-ok return the device is left unchanged by the fabric.
Note
Not thread-safe with respect to the same device.
Since
0.1.0

Definition at line 102 of file ra8_io_blockdev.c.

References ra8_io_blockdev_t::ctx, ra8_io_blockdev_iface::erase, ra8_io_blockdev_t::iface, internal_validate(), k_ra8_err_not_supported, and k_ra8_ok.

Referenced by demo_checkpoint(), internal_alloc_blank(), internal_cache_erase(), internal_demo_roundtrip(), internal_fs_erase(), and internal_reclaim_stale().

◆ ra8_io_blockdev_get_caps()

ra8_err_t ra8_io_blockdev_get_caps ( const ra8_io_blockdev_t * bd,
ra8_io_blockdev_caps_t * out )
nodiscard

Report the bound backend's medium capabilities.

Parameters
[in]bdBound block-device handle.
[out]outCapabilities snapshot.
Returns
ra8_err_t Error code.
Return values
k_ra8_ok*out populated.
k_ra8_err_null_ptrbd or out was NULL.
k_ra8_err_not_initializedNo backend is bound to bd.
Precondition
A backend has been bound into bd.
out is writable.
Postcondition
On success *out describes the bound medium.
No device or handle state is mutated.
Note
Thread-safe (pure read of immutable backend state).
Since
0.1.0

Definition at line 114 of file ra8_io_blockdev.c.

References ra8_io_blockdev_t::ctx, ra8_io_blockdev_iface::get_caps, ra8_io_blockdev_t::iface, internal_validate(), k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.

Referenced by internal_cache_get_caps(), internal_fs_erase(), internal_fs_get_capacity(), and ra8_ftl_init().

◆ ra8_io_blockdev_read()

ra8_err_t ra8_io_blockdev_read ( const ra8_io_blockdev_t * bd,
uint32_t lba,
uint32_t count,
uint8_t * buf )
nodiscard

Read count logical blocks starting at lba into buf.

Forwards to the bound backend's read primitive. buf must hold at least count * k_ra8_io_block_size_bytes bytes. Reading past the device capacity is rejected by the backend, not silently truncated.

Parameters
[in]bdBound block-device handle.
[in]lbaFirst logical block address to read.
[in]countNumber of consecutive blocks to read.
[out]bufDestination buffer (>= count * 512 bytes).
Returns
ra8_err_t Error code.
Return values
k_ra8_okBlocks read into buf.
k_ra8_err_null_ptrbd or buf was NULL.
k_ra8_err_not_initializedNo backend is bound to bd.
k_ra8_err_out_of_rangelba + count exceeds the device capacity.
k_ra8_err_invalid_argBackend rejected the request.
Precondition
A backend has been bound into bd.
buf is writable for count * 512 bytes.
Postcondition
On success buf[0 .. count*512) mirrors the device contents.
On any non-ok return buf is left unchanged by the fabric.
Note
Not thread-safe with respect to the same device.
Since
0.1.0

Definition at line 79 of file ra8_io_blockdev.c.

References ra8_io_blockdev_t::ctx, ra8_io_blockdev_t::iface, internal_validate(), k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_io_blockdev_iface::read, and s_tag.

Referenced by demo_reopen_naive(), demo_restore(), demo_write_verify(), fileops_probe_layout(), internal_bd_read_middle(), internal_bd_read_sector(), internal_cache_read_block(), internal_demo_roundtrip(), internal_fs_read(), and internal_read_one().

◆ ra8_io_blockdev_sync()

ra8_err_t ra8_io_blockdev_sync ( const ra8_io_blockdev_t * bd)
nodiscard

Flush any backend write buffering to the medium.

For buffered backends (e.g. a NOR write-coalescing shim) this commits pending data. Backends with no buffering treat it as a successful no-op.

Parameters
[in]bdBound block-device handle.
Returns
ra8_err_t Error code.
Return values
k_ra8_okPending writes committed (or none pending).
k_ra8_err_null_ptrbd was NULL.
k_ra8_err_not_initializedNo backend is bound to bd.
Precondition
A backend has been bound into bd.
The device is idle (no concurrent access).
Postcondition
On success the medium reflects every prior successful write.
No handle state is mutated.
Note
Not thread-safe with respect to the same device.
Since
0.1.0

Definition at line 125 of file ra8_io_blockdev.c.

References ra8_io_blockdev_t::ctx, ra8_io_blockdev_t::iface, internal_validate(), k_ra8_ok, and ra8_io_blockdev_iface::sync.

Referenced by internal_cache_sync(), and internal_dev_sync().

◆ ra8_io_blockdev_write()

ra8_err_t ra8_io_blockdev_write ( const ra8_io_blockdev_t * bd,
uint32_t lba,
uint32_t count,
const uint8_t * buf )
nodiscard

Write count logical blocks from buf starting at lba.

Forwards to the bound backend's write primitive. On media that require an erase before programming the backend performs the necessary read-modify-write or erase internally; callers that want erase-aligned efficiency should use ra8_io_blockdev_erase plus aligned writes.

Parameters
[in]bdBound block-device handle.
[in]lbaFirst logical block address to write.
[in]countNumber of consecutive blocks to write.
[in]bufSource buffer (>= count * 512 bytes).
Returns
ra8_err_t Error code.
Return values
k_ra8_okBlocks written.
k_ra8_err_null_ptrbd or buf was NULL.
k_ra8_err_not_initializedNo backend is bound to bd.
k_ra8_err_out_of_rangelba + count exceeds the device capacity.
k_ra8_err_not_supportedThe device is read-only.
Precondition
A backend has been bound into bd.
buf is readable for count * 512 bytes.
Postcondition
On success the device blocks [lba, lba+count) equal buf.
On any non-ok return the device is left unchanged by the fabric.
Note
Not thread-safe with respect to the same device.
Since
0.1.0

Definition at line 91 of file ra8_io_blockdev.c.

References ra8_io_blockdev_t::ctx, ra8_io_blockdev_t::iface, internal_validate(), k_ra8_ok, RA8_CHECK_NULL_PTR, s_tag, and ra8_io_blockdev_iface::write.

Referenced by demo_checkpoint(), demo_write_verify(), internal_bdsink_commit_sector(), internal_cache_write_block(), internal_demo_probe_foreign(), internal_demo_roundtrip(), internal_fs_write(), and internal_write_one().