ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
lx_fs_backend.c
Go to the documentation of this file.
1
36
37#include "lx_fs_backend.h"
38
39#include <stdint.h>
40#include <string.h>
41
42#include "ra8_attributes.h"
43#include "ra8_check.h"
44
46static const char* const s_tag = "lx_fs_be";
47
61typedef enum : uint32_t {
65
66static_assert((uint32_t)LX_NOR_SECTOR_SIZE * (uint32_t)sizeof(ULONG) ==
67 (uint32_t)k_lx_fsbe_sector_bytes,
68 "LevelX logical sector must be 512 bytes");
69
83static ULONG s_lx_fsbe_bounce[LX_NOR_SECTOR_SIZE];
84
111RA8_INTERNAL static uint64_t internal_usable_sectors(const LX_NOR_FLASH* nor_flash)
112{
113 uint64_t phys_per_block = (uint64_t)nor_flash->lx_nor_flash_physical_sectors_per_block;
114 if (phys_per_block <= 1U) {
115 return 0U;
116 }
117 uint64_t total_blocks = (uint64_t)nor_flash->lx_nor_flash_total_blocks;
118 return total_blocks * (phys_per_block - 1U);
119}
120
150internal_read_block(void* ctx, uint64_t lba, uint32_t count, uint8_t* buf)
151{
152 RA8_CHECK_NULL_PTR(ctx, s_tag, "ctx");
153 RA8_CHECK_NULL_PTR(buf, s_tag, "buf");
154 LX_NOR_FLASH* nor_flash = ctx;
155 if ((lba + (uint64_t)count) > internal_usable_sectors(nor_flash)) {
157 }
158 for (uint32_t i = 0U; i < count; i++) {
159 uint8_t* dst = &buf[(size_t)i * (size_t)k_lx_fsbe_sector_bytes];
160 UINT rc = lx_nor_flash_sector_read(nor_flash, (ULONG)(lba + (uint64_t)i), s_lx_fsbe_bounce);
161 if (rc == (UINT)LX_SECTOR_NOT_FOUND) {
162 (void)memset(dst, (int)k_lx_fsbe_erased_byte, (size_t)k_lx_fsbe_sector_bytes);
163 } else if (rc != (UINT)LX_SUCCESS) {
165 } else {
167 }
168 }
169 return k_ra8_ok;
170}
171
200internal_write_block(void* ctx, uint64_t lba, uint32_t count, const uint8_t* buf)
201{
202 RA8_CHECK_NULL_PTR(ctx, s_tag, "ctx");
203 RA8_CHECK_NULL_PTR(buf, s_tag, "buf");
204 LX_NOR_FLASH* nor_flash = ctx;
205 if ((lba + (uint64_t)count) > internal_usable_sectors(nor_flash)) {
207 }
208 for (uint32_t i = 0U; i < count; i++) {
209 const uint8_t* src = &buf[(size_t)i * (size_t)k_lx_fsbe_sector_bytes];
211 UINT rc = lx_nor_flash_sector_write(nor_flash, (ULONG)(lba + (uint64_t)i), s_lx_fsbe_bounce);
212 if (rc != (UINT)LX_SUCCESS) {
214 }
215 }
216 return k_ra8_ok;
217}
218
246internal_get_capacity(void* ctx, uint64_t* block_count, uint32_t* block_size)
247{
248 RA8_CHECK_NULL_PTR(ctx, s_tag, "ctx");
249 RA8_CHECK_NULL_PTR(block_count, s_tag, "block_count");
250 RA8_CHECK_NULL_PTR(block_size, s_tag, "block_size");
251 uint64_t usable = internal_usable_sectors(ctx);
252 if (usable == 0U) {
254 }
255 *block_count = usable;
256 *block_size = (uint32_t)k_lx_fsbe_sector_bytes;
257 return k_ra8_ok;
258}
259
261ra8_err_t lx_fs_backend_bind(LX_NOR_FLASH* nor_flash, ra8_fs_backend_t* out)
262{
263 RA8_CHECK_NULL_PTR(nor_flash, s_tag, "nor_flash");
264 RA8_CHECK_NULL_PTR(out, s_tag, "out");
265 if (internal_usable_sectors(nor_flash) == 0U) {
267 }
271 out->erase_blocks = nullptr; /* NOR erases to ones; ra8_fs wants zero-erase. */
272 out->ctx = nor_flash;
273 return k_ra8_ok;
274}
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.
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.
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.
static uint64_t internal_usable_sectors(const LX_NOR_FLASH *nor_flash)
FAT-usable 512-byte sector count of an open LevelX partition.
lx_fs_backend_geometry_t
Fixed LevelX <-> ra8_fs sector geometry.
@ k_lx_fsbe_sector_bytes
LevelX logical sector size in bytes.
@ k_lx_fsbe_erased_byte
NOR erased value for unmapped sectors.
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 ULONG s_lx_fsbe_bounce[LX_NOR_SECTOR_SIZE]
One-sector ULONG-aligned bounce buffer for LevelX transfers.
ra8_fs block-device backend over a LevelX wear-levelled NOR partition
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
@ k_ra8_err_hw_init_failed
Hardware peripheral failed to initialise.
Definition ra8_err.h:290
@ k_ra8_err_out_of_range
Sensor or peripheral output out of valid range.
Definition ra8_err.h:337
@ k_ra8_err_not_initialized
Module not initialized – _init() not yet called successfully.
Definition ra8_err.h:235
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
void * memset(void *dst, int value, size_t n)
Fill memory with a constant byte value.
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
unsigned int UINT
ThreadX-compatible unsigned int (host stub).
unsigned long ULONG
ThreadX-compatible unsigned long (host stub).
Block-device interface that ra8_fs runs on top of.
ra8_err_t(* read_block)(void *ctx, uint64_t lba, uint32_t count, uint8_t *buf)
Read count consecutive blocks starting at lba.
ra8_err_t(* write_block)(void *ctx, uint64_t lba, uint32_t count, const uint8_t *buf)
Write count consecutive blocks starting at lba.
ra8_err_t(* erase_blocks)(void *ctx, uint64_t lba, uint64_t count)
OPTIONAL: bulk-erase count blocks at lba to all-zero bytes.
void * ctx
Caller-owned context passed back into the function pointers.
ra8_err_t(* get_capacity)(void *ctx, uint64_t *block_count, uint32_t *block_size)
Report the device size.