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

ra8_fs block-device trampolines onto LevelX wear-levelled NOR storage More...

#include "lx_fs_backend.h"
#include <stdint.h>
#include <string.h>
#include "ra8_attributes.h"
#include "ra8_check.h"
Include dependency graph for lx_fs_backend.c:

Go to the source code of this file.

Enumerations

enum  lx_fs_backend_geometry_t : uint32_t {
  k_lx_fsbe_sector_bytes = 512U ,
  k_lx_fsbe_erased_byte = 0xFFU
}
 Fixed LevelX <-> ra8_fs sector geometry. More...

Functions

static uint64_t internal_usable_sectors (const LX_NOR_FLASH *nor_flash)
 FAT-usable 512-byte sector count of an open LevelX partition.
static ra8_err_t internal_read_block (void *ctx, uint64_t lba, uint32_t count, uint8_t *buf)
 read_block trampoline: LevelX sector reads into a byte buffer.
static ra8_err_t internal_write_block (void *ctx, uint64_t lba, uint32_t count, const uint8_t *buf)
 write_block trampoline: byte buffer into LevelX sector writes.
static ra8_err_t internal_get_capacity (void *ctx, uint64_t *block_count, uint32_t *block_size)
 get_capacity trampoline: report the FAT-usable LevelX window.
ra8_err_t lx_fs_backend_bind (LX_NOR_FLASH *nor_flash, ra8_fs_backend_t *out)
 Implementation of lx_fs_backend_bind() – fills the three trampolines.

Variables

static const char *const s_tag = "lx_fs_be"
 Module log tag.
static ULONG s_lx_fsbe_bounce [LX_NOR_SECTOR_SIZE]
 One-sector ULONG-aligned bounce buffer for LevelX transfers.

Detailed Description

ra8_fs block-device trampolines onto LevelX wear-levelled NOR storage

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

Implements lx_fs_backend_bind(): three ra8_fs_backend_t callbacks (read_block / write_block / get_capacity) that forward each 512-byte block request into one lx_nor_flash_sector_read / lx_nor_flash_sector_write call against the bound LX_NOR_FLASH.

The adapter is intentionally thin: LevelX's 512-byte logical sector is also the smallest ra8_fs sector size, so each block maps 1:1 onto one LevelX call. No sector cache lives here; ra8_fs (its FAT cache and sector arena) and LevelX (its mapping cache) bring their own.

Two translation details carry the semantics:

  • LX_SECTOR_NOT_FOUND on a read means LevelX has never mapped that logical sector – it is erased space, not an I/O failure – so the caller's buffer is filled with the NOR erased value 0xFF and the read succeeds, exactly as a raw block device serves erased flash.
  • LevelX requires ULONG-aligned sector buffers; ra8_fs hands over plain byte pointers. Every transfer bounces through one static aligned sector buffer, which is safe because ra8_fs serialises all backend calls (see ra8_fs_set_lock()).
Author
Brighton Sikarskie
Date
2026-08-10
Since
0.1.0

Definition in file lx_fs_backend.c.

Enumeration Type Documentation

◆ lx_fs_backend_geometry_t

enum lx_fs_backend_geometry_t : uint32_t

Fixed LevelX <-> ra8_fs sector geometry.

A LevelX logical sector is LX_NOR_SECTOR_SIZE ULONG words = 512 bytes on every platform (the word COUNT varies with sizeof(ULONG) – 128 on the 32-bit target, 64 on an LP64 test host – the byte size does not), and 512 bytes is also the smallest block size ra8_fs accepts. The erased byte is what NOR flash reads back after erase, served for never-mapped sectors.

Since
0.1.0
Enumerator
k_lx_fsbe_sector_bytes 

LevelX logical sector size in bytes.

k_lx_fsbe_erased_byte 

NOR erased value for unmapped sectors.

Definition at line 61 of file lx_fs_backend.c.

Function Documentation

◆ internal_get_capacity()

ra8_err_t internal_get_capacity ( void * ctx,
uint64_t * block_count,
uint32_t * block_size )
static

get_capacity trampoline: report the FAT-usable LevelX window.

Answers ra8_fs's size query from the bound control block: internal_usable_sectors for the block count (LevelX's usable window minus one spare sector per block of wear-levelling headroom) and the fixed 512-byte LevelX logical sector for the block size. A zero window means the flash was never opened, which is reported as an error rather than a zero-sector disk.

Parameters
[in]ctxBound LX_NOR_FLASH*.
[out]block_countReceives the usable 512-byte sector count.
[out]block_sizeReceives the block size (always 512).
Returns
ra8_err_t Error code.
Return values
k_ra8_okOutputs populated.
k_ra8_err_null_ptrAny argument was NULL.
k_ra8_err_not_initializedThe flash reports zero usable sectors.
Precondition
ctx points at an open LevelX flash.
block_count and block_size are writable.
Postcondition
On k_ra8_ok, *block_count > 0 and *block_size == 512.
No flash state is mutated.
Note
Thread-safe (pure read of the control block).
Since
0.1.0

Definition at line 246 of file lx_fs_backend.c.

References internal_usable_sectors(), k_lx_fsbe_sector_bytes, k_ra8_err_not_initialized, k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.

Referenced by lx_fs_backend_bind().

◆ internal_read_block()

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

read_block trampoline: LevelX sector reads into a byte buffer.

One lx_nor_flash_sector_read per block, staged through the aligned bounce buffer. LX_SECTOR_NOT_FOUND (a logical sector LevelX has never mapped) fills that block with 0xFF and continues – unmapped wear-levelled NOR is erased space, and a block device serves erased space, it does not error on it. Any other LevelX failure aborts the request.

Parameters
[in]ctxBound LX_NOR_FLASH*.
[in]lbaFirst logical 512-byte sector to read.
[in]countNumber of consecutive sectors to read.
[out]bufDestination buffer (>= count * 512 bytes).
Returns
ra8_err_t Error code.
Return values
k_ra8_okBlocks read (or served as erased fill).
k_ra8_err_null_ptrctx or buf was NULL.
k_ra8_err_out_of_rangelba + count exceeds the usable window.
k_ra8_err_hw_init_failedLevelX reported an I/O failure.
Precondition
ctx points at an open LevelX flash.
buf is writable for count * 512 bytes.
Postcondition
On k_ra8_ok, buf holds count sectors of data or erased fill.
On any non-ok return the flash is unchanged.
Note
Not thread-safe; serialised by ra8_fs (see the bounce buffer note).
Since
0.1.0

Definition at line 150 of file lx_fs_backend.c.

References internal_usable_sectors(), k_lx_fsbe_erased_byte, k_lx_fsbe_sector_bytes, k_ra8_err_hw_init_failed, k_ra8_err_out_of_range, k_ra8_ok, memcpy(), memset(), RA8_CHECK_NULL_PTR, s_lx_fsbe_bounce, and s_tag.

Referenced by lx_fs_backend_bind().

◆ internal_usable_sectors()

uint64_t internal_usable_sectors ( const LX_NOR_FLASH * nor_flash)
static

FAT-usable 512-byte sector count of an open LevelX partition.

lx_nor_flash_physical_sectors_per_block already excludes the one physical sector per block LevelX reserves for its mapping metadata (lx_nor_flash_open computes words_per_block / LX_NOR_SECTOR_SIZE - 1). This helper subtracts ONE MORE sector per block as wear-levelling headroom, so LevelX always has free physical sectors to remap writes into even when the filesystem has touched every logical sector it was offered – the same margin the retired FileX adapter gave fx_media_format. A flash that is not open (or whose driver never programmed the geometry) reports zero.

Parameters
[in]nor_flashLevelX control block to size. Must not be NULL.
Returns
Number of usable 512-byte sectors.
Return values
0nor_flash is not open or its geometry is not programmed.
Precondition
nor_flash is non-NULL (callers have already null-checked it).
nor_flash geometry fields are stable for the duration of the call.
Postcondition
No state is mutated; pure computation over the control block.
The result is 0 unless physical_sectors_per_block > 1.
Note
Thread-safe (pure read).
Since
0.1.0

Definition at line 111 of file lx_fs_backend.c.

References RA8_INTERNAL.

Referenced by internal_get_capacity(), internal_read_block(), internal_write_block(), and lx_fs_backend_bind().

◆ internal_write_block()

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

write_block trampoline: byte buffer into LevelX sector writes.

One lx_nor_flash_sector_write per block, staged through the aligned bounce buffer. LevelX handles the mark-old-obsolete / pick-new- physical-sector dance internally – that is the wear-levelling this stack exists for.

Parameters
[in]ctxBound LX_NOR_FLASH*.
[in]lbaFirst logical 512-byte sector to write.
[in]countNumber of consecutive sectors to write.
[in]bufSource buffer (>= count * 512 bytes).
Returns
ra8_err_t Error code.
Return values
k_ra8_okBlocks written.
k_ra8_err_null_ptrctx or buf was NULL.
k_ra8_err_out_of_rangelba + count exceeds the usable window.
k_ra8_err_hw_init_failedLevelX reported an I/O failure.
Precondition
ctx points at an open LevelX flash.
buf is readable for count * 512 bytes.
Postcondition
On k_ra8_ok every written sector reads back identically.
On any non-ok return sectors before the failing one may be written.
Note
Not thread-safe; serialised by ra8_fs (see the bounce buffer note).
Since
0.1.0

Definition at line 200 of file lx_fs_backend.c.

References internal_usable_sectors(), k_lx_fsbe_sector_bytes, k_ra8_err_hw_init_failed, k_ra8_err_out_of_range, k_ra8_ok, memcpy(), RA8_CHECK_NULL_PTR, s_lx_fsbe_bounce, and s_tag.

Referenced by lx_fs_backend_bind().

◆ lx_fs_backend_bind()

ra8_err_t lx_fs_backend_bind ( LX_NOR_FLASH * nor_flash,
ra8_fs_backend_t * out )
nodiscard

Variable Documentation

◆ s_lx_fsbe_bounce

ULONG s_lx_fsbe_bounce[LX_NOR_SECTOR_SIZE]
static

One-sector ULONG-aligned bounce buffer for LevelX transfers.

LevelX's sector calls take ULONG* and perform word accesses; ra8_fs supplies byte pointers with no alignment promise. Every read and write stages through this buffer instead of casting the caller's pointer.

Note
Serialised by ra8_fs itself: backend callbacks only run inside a public ra8_fs entry point, which the library serialises (its lock seam under an RTOS, the single-threaded contract otherwise).
Warning
Not for use outside the two transfer trampolines in this TU.
Since
0.1.0

Definition at line 83 of file lx_fs_backend.c.

Referenced by internal_read_block(), and internal_write_block().

◆ s_tag

const char* const s_tag = "lx_fs_be"
static

Module log tag.

Definition at line 46 of file lx_fs_backend.c.