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

OSPI NOR block-device backend – 512-byte LBAs over ra8_xspi flash. More...

#include "ra8_io_blockdev_xspi.h"
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_io_blockdev.h"
#include "ra8_io_blockdev_backend.h"
#include "ra8_ospi_regs.h"
#include "ra8_xspi.h"
Include dependency graph for ra8_io_blockdev_xspi.c:

Go to the source code of this file.

Enumerations

enum  ra8_io_xspi_const_t : uint32_t {
  k_xspi_sector_bytes = 4096 ,
  k_xspi_blocks_per_sector = 8 ,
  k_xspi_program_bytes = 256 ,
  k_xspi_zero_blocks = 0 ,
  k_xspi_min_instance = 0
}
 OSPI NOR backend layout constants. More...

Functions

static ra8_err_t internal_xspi_bounds (const ra8_io_blockdev_xspi_state_t *st, uint32_t lba, uint32_t count)
 Reject an out-of-range [lba, lba+count) block range.
static ra8_err_t internal_xspi_read_chunked (uint8_t instance, uint32_t flash_addr, uint8_t *buf, uint32_t len)
 Read len flash bytes at flash_addr, chunked to the HAL limit.
static ra8_err_t internal_xspi_program_chunked (uint8_t instance, uint32_t flash_addr, const uint8_t *data, uint32_t len)
 Program len flash bytes at flash_addr, chunked to the HAL limit.
static ra8_err_t internal_write_one_sector (const ra8_io_blockdev_xspi_state_t *st, uint32_t sector_lba, uint32_t first_blk, uint32_t n_blocks, const uint8_t *src)
 Read-modify-write one 4 KiB sector, overlaying the touched blocks.
static ra8_err_t internal_xspi_read (void *ctx, uint32_t lba, uint32_t count, uint8_t *buf)
 xSPI backend: read count blocks at lba into buf.
static ra8_err_t internal_xspi_write (void *ctx, uint32_t lba, uint32_t count, const uint8_t *buf)
 xSPI backend: write count blocks from buf at lba.
static ra8_err_t internal_xspi_erase (void *ctx, uint32_t lba, uint32_t count)
 xSPI backend: erase sector-aligned count blocks at lba.
static ra8_err_t internal_xspi_get_caps (const void *ctx, ra8_io_blockdev_caps_t *out)
 xSPI backend: report medium capabilities.
static ra8_err_t internal_xspi_check_geom (uint8_t instance, uint32_t base_off, uint32_t block_count)
 Validate the window geometry for ra8_io_blockdev_xspi_init.
ra8_err_t ra8_io_blockdev_xspi_init (ra8_io_blockdev_t *bd, ra8_io_blockdev_xspi_state_t *state, uint8_t instance, uint32_t base_off, uint32_t block_count, bool read_only)
 Bind an OSPI NOR block-device backend into a caller-owned handle.

Variables

static const char *const s_tag = "ra8_io_blockdev_xspi"
 Module log tag.
static uint8_t s_sector [k_xspi_sector_bytes]
 Whole-sector read-modify-write scratch (zero-malloc, NASA Rule 3).
static const ra8_io_blockdev_iface_t s_xspi_iface
 OSPI NOR backend vtable.

Detailed Description

OSPI NOR block-device backend – 512-byte LBAs over ra8_xspi flash.

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

Implementation of ra8_io_blockdev_iface over the ra8_xspi HAL. Reads chunk ra8_xspi_flash_read to the controller's per-transfer limit. Arbitrary writes are correct on NOR's erase-then-program semantics via a whole-sector read-modify-write through a module-static 4 KiB scratch buffer: read the sector, overlay the touched 512-byte blocks, erase the sector, and program the 4 KiB back (chunked). Erases are sector-aligned. The file touches no MMIO; every flash access routes through the HAL, which owns the HUM citations.

Definition in file ra8_io_blockdev_xspi.c.

Enumeration Type Documentation

◆ ra8_io_xspi_const_t

enum ra8_io_xspi_const_t : uint32_t

OSPI NOR backend layout constants.

Since
0.1.0
Enumerator
k_xspi_sector_bytes 

Erase sector size in bytes.

k_xspi_blocks_per_sector 

512-byte blocks per 4 KiB sector.

k_xspi_program_bytes 

NOR page-program granularity in bytes.

k_xspi_zero_blocks 

Sentinel for an empty block range.

k_xspi_min_instance 

Lowest valid xSPI instance index.

Definition at line 44 of file ra8_io_blockdev_xspi.c.

Function Documentation

◆ internal_write_one_sector()

ra8_err_t internal_write_one_sector ( const ra8_io_blockdev_xspi_state_t * st,
uint32_t sector_lba,
uint32_t first_blk,
uint32_t n_blocks,
const uint8_t * src )
static

Read-modify-write one 4 KiB sector, overlaying the touched blocks.

Reads the whole sector at sector_lba into s_sector, overlays the n_blocks logical blocks starting at offset first_blk within the sector from src, erases the sector to all-ones, then programs the 4 KiB back. Keeps NOR's erase-before-program contract correct for arbitrary writes.

Parameters
[in]stxSPI backend state.
[in]sector_lbaFirst logical block of the sector (multiple of 8).
[in]first_blkIndex of the first touched block within the sector.
[in]n_blocksNumber of consecutive blocks to overlay.
[in]srcSource bytes for the overlaid blocks.
Returns
ra8_err_t Error code.
Return values
k_ra8_okSector rewritten with the overlay applied.
k_ra8_err_null_ptrst, src, or a HAL pointer was NULL.
k_ra8_err_invalid_argHAL rejected a transfer length.
k_ra8_err_timeoutFlash WIP bit never cleared.
Precondition
st is a populated xSPI state.
first_blk + n_blocks <= k_xspi_blocks_per_sector.
Postcondition
On success the sector equals its prior contents with the overlay.
On failure no further chunks are issued past the first error.
Note
Not thread-safe with respect to the same device.
Since
0.1.0

Definition at line 218 of file ra8_io_blockdev_xspi.c.

References ra8_io_blockdev_xspi_state_t::base_off, ra8_io_blockdev_xspi_state_t::instance, internal_xspi_program_chunked(), internal_xspi_read_chunked(), k_ra8_io_block_size_bytes, k_ra8_ok, k_xspi_sector_bytes, memcpy(), RA8_CHECK_NULL_PTR, RA8_INTERNAL, ra8_xspi_flash_erase_sector(), s_sector, and s_tag.

Referenced by internal_xspi_write().

◆ internal_xspi_bounds()

ra8_err_t internal_xspi_bounds ( const ra8_io_blockdev_xspi_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]stxSPI 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 flash 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 81 of file ra8_io_blockdev_xspi.c.

References ra8_io_blockdev_xspi_state_t::block_count, k_ra8_err_out_of_range, and k_ra8_ok.

Referenced by internal_xspi_erase(), internal_xspi_read(), and internal_xspi_write().

◆ internal_xspi_check_geom()

ra8_err_t internal_xspi_check_geom ( uint8_t instance,
uint32_t base_off,
uint32_t block_count )
static

Validate the window geometry for ra8_io_blockdev_xspi_init.

Split single-condition checks (no compound decision) covering instance range, sector-aligned base offset, and a non-zero whole-sector block count.

Parameters
[in]instancexSPI HAL instance index.
[in]base_offFlash byte offset of logical block 0.
[in]block_countNumber of 512-byte logical blocks.
Returns
ra8_err_t Error code.
Return values
k_ra8_okGeometry is valid.
k_ra8_err_invalid_argSome constraint was violated.
Precondition
instance, base_off, block_count are the caller's raw arguments.
No device state has yet been bound.
Postcondition
No state is mutated.
The return reflects only the geometry constraints.
Note
Thread-safe (pure comparison).
Since
0.1.0

Definition at line 484 of file ra8_io_blockdev_xspi.c.

References k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_xspi_instance_count, k_xspi_blocks_per_sector, k_xspi_sector_bytes, and k_xspi_zero_blocks.

Referenced by ra8_io_blockdev_xspi_init().

◆ internal_xspi_erase()

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

xSPI backend: erase sector-aligned count blocks at lba.

Requires lba and count to be multiples of k_xspi_blocks_per_sector (eight blocks per 4 KiB sector); a non-aligned request is rejected. Each spanned sector is erased to all-ones via ra8_xspi_flash_erase_sector.

Parameters
[in]ctxxSPI backend state (as a void cookie).
[in]lbaFirst logical block address (multiple of 8).
[in]countNumber of blocks to erase (multiple of 8).
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_invalid_argRange is not sector-aligned.
k_ra8_err_out_of_rangeRange past capacity.
k_ra8_err_timeoutFlash WIP bit never cleared.
Precondition
ctx is a populated xSPI state.
lba and count are multiples of eight blocks.
Postcondition
On success every spanned sector reads back as 0xFF.
On failure earlier sectors may already be erased.
Note
Not thread-safe with respect to the same device.
Since
0.1.0

Definition at line 381 of file ra8_io_blockdev_xspi.c.

References ra8_io_blockdev_xspi_state_t::base_off, ra8_io_blockdev_xspi_state_t::instance, internal_xspi_bounds(), k_ra8_err_invalid_arg, k_ra8_err_not_supported, k_ra8_io_block_size_bytes, k_ra8_ok, k_xspi_blocks_per_sector, k_xspi_zero_blocks, RA8_CHECK_NULL_PTR, ra8_xspi_flash_erase_sector(), ra8_io_blockdev_xspi_state_t::read_only, and s_tag.

◆ internal_xspi_get_caps()

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

xSPI backend: report medium capabilities.

Reports an all-ones-erase NOR medium that must be erased before programming, with an 8-block (4 KiB) erase unit.

Parameters
[in]ctxxSPI 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 xSPI state.
out is writable.
Postcondition
On success *out describes an all-ones-erase, erase-required medium.
No state is mutated.
Note
Thread-safe (pure read).
Since
0.1.0

Definition at line 434 of file ra8_io_blockdev_xspi.c.

References ra8_io_blockdev_caps_t::block_count, ra8_io_blockdev_xspi_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_ok, k_xspi_blocks_per_sector, k_xspi_program_bytes, 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_io_blockdev_caps_t::read_only, ra8_io_blockdev_xspi_state_t::read_only, and s_tag.

◆ internal_xspi_program_chunked()

ra8_err_t internal_xspi_program_chunked ( uint8_t instance,
uint32_t flash_addr,
const uint8_t * data,
uint32_t len )
static

Program len flash bytes at flash_addr, chunked to the HAL limit.

Splits the request into transfers of at most k_ra8_xspi_max_xfer bytes so every ra8_xspi_flash_program call stays within the controller window. The target sector must already have been erased to all-ones by the caller.

Parameters
[in]instancexSPI HAL instance index.
[in]flash_addrAbsolute flash byte offset to program.
[in]dataSource buffer (>= len bytes).
[in]lenNumber of bytes to program.
Returns
ra8_err_t Error code.
Return values
k_ra8_okAll bytes programmed.
k_ra8_err_null_ptrdata invalid or instance out of range.
k_ra8_err_invalid_argHAL rejected a chunk length.
k_ra8_err_timeoutFlash WIP bit never cleared.
Precondition
data is readable for len bytes.
The covering sector was erased before this call.
Postcondition
On success the flash window equals data.
On failure the program stops at the first failing chunk.
Note
Not thread-safe with respect to the same device.
Since
0.1.0

Definition at line 167 of file ra8_io_blockdev_xspi.c.

References k_ra8_ok, k_ra8_xspi_max_xfer, k_xspi_zero_blocks, RA8_CHECK_NULL_PTR, ra8_xspi_flash_program(), and s_tag.

Referenced by internal_write_one_sector().

◆ internal_xspi_read()

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

xSPI backend: read count blocks at lba into buf.

Bounds-checks the range, then reads count * 512 flash bytes in HAL-sized chunks from base_off + lba * 512.

Parameters
[in]ctxxSPI backend state (as a void cookie).
[in]lbaFirst logical block address.
[in]countNumber of 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_ptrctx or buf was NULL.
k_ra8_err_out_of_rangeRange past capacity.
k_ra8_err_invalid_argHAL rejected a chunk length.
Precondition
ctx is a populated xSPI state.
buf is writable for count * 512 bytes.
Postcondition
On success buf mirrors the flash window.
On failure buf may hold a partial prefix only.
Note
Not thread-safe with respect to the same device.
Since
0.1.0

Definition at line 274 of file ra8_io_blockdev_xspi.c.

References ra8_io_blockdev_xspi_state_t::base_off, ra8_io_blockdev_xspi_state_t::instance, internal_xspi_bounds(), internal_xspi_read_chunked(), k_ra8_io_block_size_bytes, k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.

◆ internal_xspi_read_chunked()

ra8_err_t internal_xspi_read_chunked ( uint8_t instance,
uint32_t flash_addr,
uint8_t * buf,
uint32_t len )
static

Read len flash bytes at flash_addr, chunked to the HAL limit.

Splits the request into transfers of at most k_ra8_xspi_max_xfer bytes so every ra8_xspi_flash_read call stays within the controller's per-transfer window. Stops and returns the first non-ok HAL status.

Parameters
[in]instancexSPI HAL instance index.
[in]flash_addrAbsolute flash byte offset to read from.
[out]bufDestination buffer (>= len bytes).
[in]lenNumber of bytes to read.
Returns
ra8_err_t Error code.
Return values
k_ra8_okAll bytes read.
k_ra8_err_null_ptrbuf invalid or instance out of range.
k_ra8_err_invalid_argHAL rejected a chunk length.
Precondition
buf is writable for len bytes.
The controller was initialised via ra8_xspi_init.
Postcondition
On success buf[0 .. len) mirrors the flash window.
On failure the read stops at the first failing chunk.
Note
Not thread-safe with respect to the same device.
Since
0.1.0

Definition at line 121 of file ra8_io_blockdev_xspi.c.

References k_ra8_ok, k_ra8_xspi_max_xfer, k_xspi_zero_blocks, RA8_CHECK_NULL_PTR, ra8_xspi_flash_read(), and s_tag.

Referenced by internal_write_one_sector(), and internal_xspi_read().

◆ internal_xspi_write()

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

xSPI backend: write count blocks from buf at lba.

Iterates the 4 KiB sectors the [lba, lba+count) range spans and rewrites each via internal_write_one_sector (whole-sector read-modify-write). Rejects the call up front when the device is read-only or the range exceeds capacity.

Parameters
[in]ctxxSPI backend state (as a void cookie).
[in]lbaFirst logical block address.
[in]countNumber of blocks to write.
[in]bufSource buffer (>= count * 512 bytes).
Returns
ra8_err_t Error code.
Return values
k_ra8_okBlocks committed to flash.
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_argHAL rejected a transfer length.
k_ra8_err_timeoutFlash WIP bit never cleared.
Precondition
ctx is a populated xSPI state.
buf is readable for count * 512 bytes.
Postcondition
On success flash blocks [lba, lba+count) equal buf.
On failure earlier sectors may already be rewritten.
Note
Not thread-safe with respect to the same device.
Since
0.1.0

Definition at line 320 of file ra8_io_blockdev_xspi.c.

References internal_write_one_sector(), internal_xspi_bounds(), k_ra8_err_not_supported, k_ra8_io_block_size_bytes, k_ra8_ok, k_xspi_blocks_per_sector, k_xspi_zero_blocks, RA8_CHECK_NULL_PTR, ra8_io_blockdev_xspi_state_t::read_only, and s_tag.

◆ ra8_io_blockdev_xspi_init()

ra8_err_t ra8_io_blockdev_xspi_init ( ra8_io_blockdev_t * bd,
ra8_io_blockdev_xspi_state_t * state,
uint8_t instance,
uint32_t base_off,
uint32_t block_count,
bool read_only )
nodiscard

Bind an OSPI NOR block-device backend into a caller-owned handle.

Records instance/base_off/block_count in state, marks it read-only per read_only, and points bd at the xSPI vtable with state as its context. No allocation occurs; the caller owns both bd and state. The window must be whole-sector aligned: base_off a multiple of 4096 and block_count a non-zero multiple of 8 (4096 / 512). The application must have brought up the controller with ra8_xspi_init(instance, mode) before any call is dispatched through the bound device.

Parameters
[out]bdHandle to bind (zero-initialised by the caller).
[out]stateCaller-owned backend state to populate.
[in]instancexSPI HAL instance index (0 or 1).
[in]base_offFlash byte offset of logical block 0 (% 4096 == 0).
[in]block_countNumber of 512-byte logical blocks (non-zero, % 8 == 0).
[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_arginstance >= 2, base_off not sector-aligned, or block_count not a non-zero multiple of 8.
Precondition
ra8_xspi_init(instance, mode) has already succeeded.
bd and state out-live every call made through the device.
Postcondition
On success bd dispatches to the xSPI backend over the flash window.
On any non-ok return bd and state are left unbound/untouched.
Note
Not thread-safe with respect to the same device.
Since
0.1.0

Definition at line 501 of file ra8_io_blockdev_xspi.c.

References ra8_io_blockdev_xspi_state_t::base_off, ra8_io_blockdev_xspi_state_t::block_count, ra8_io_blockdev_t::ctx, ra8_io_blockdev_t::iface, ra8_io_blockdev_xspi_state_t::instance, internal_xspi_check_geom(), k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_io_blockdev_xspi_state_t::read_only, s_tag, and s_xspi_iface.

Referenced by demo_run(), and internal_swap_run_all().

Variable Documentation

◆ s_sector

uint8_t s_sector[k_xspi_sector_bytes]
static

Whole-sector read-modify-write scratch (zero-malloc, NASA Rule 3).

Definition at line 53 of file ra8_io_blockdev_xspi.c.

Referenced by internal_write_one_sector().

◆ s_tag

const char* const s_tag = "ra8_io_blockdev_xspi"
static

Module log tag.

Definition at line 36 of file ra8_io_blockdev_xspi.c.

◆ s_xspi_iface

const ra8_io_blockdev_iface_t s_xspi_iface
static
Initial value:
= {
.sync = nullptr,
}
static ra8_err_t internal_xspi_get_caps(const void *ctx, ra8_io_blockdev_caps_t *out)
xSPI backend: report medium capabilities.
static ra8_err_t internal_xspi_write(void *ctx, uint32_t lba, uint32_t count, const uint8_t *buf)
xSPI backend: write count blocks from buf at lba.
static ra8_err_t internal_xspi_read(void *ctx, uint32_t lba, uint32_t count, uint8_t *buf)
xSPI backend: read count blocks at lba into buf.
static ra8_err_t internal_xspi_erase(void *ctx, uint32_t lba, uint32_t count)
xSPI backend: erase sector-aligned count blocks at lba.

OSPI NOR backend vtable.

sync is NULL: programs commit on return.

Definition at line 450 of file ra8_io_blockdev_xspi.c.

Referenced by ra8_io_blockdev_xspi_init().