ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_io_blockdev.c
Go to the documentation of this file.
1
18
19#include "ra8_io_blockdev.h"
20
21#include <stdint.h>
22
23#include "ra8_attributes.h"
24#include "ra8_check.h"
25#include "ra8_err.h"
26#include "ra8_fs.h"
28#include "ra8_log.h"
29
31static const char* const s_tag = "ra8_io_blockdev";
32
33/* =============================================================================
34 * Internal helpers
35 * =============================================================================
36 */
37
63{
64 if (bd == nullptr) {
65 return k_ra8_err_null_ptr;
66 }
67 if (bd->iface == nullptr) {
69 }
70 return k_ra8_ok;
71}
72
73/* =============================================================================
74 * Public API -- dispatch through the bound backend
75 * =============================================================================
76 */
77
79ra8_io_blockdev_read(const ra8_io_blockdev_t* bd, uint32_t lba, uint32_t count, uint8_t* buf)
80{
81 const ra8_err_t v = internal_validate(bd);
82 if (v != k_ra8_ok) {
83 return v;
84 }
85 RA8_CHECK_NULL_PTR(buf, s_tag, "buf must not be nullptr");
86 RA8_CHECK_NULL_PTR(bd->iface->read, s_tag, "backend read op missing");
87 return bd->iface->read(bd->ctx, lba, count, buf);
88}
89
91ra8_io_blockdev_write(const ra8_io_blockdev_t* bd, uint32_t lba, uint32_t count, const uint8_t* buf)
92{
93 const ra8_err_t v = internal_validate(bd);
94 if (v != k_ra8_ok) {
95 return v;
96 }
97 RA8_CHECK_NULL_PTR(buf, s_tag, "buf must not be nullptr");
98 RA8_CHECK_NULL_PTR(bd->iface->write, s_tag, "backend write op missing");
99 return bd->iface->write(bd->ctx, lba, count, buf);
100}
101
102ra8_err_t ra8_io_blockdev_erase(const ra8_io_blockdev_t* bd, uint32_t lba, uint32_t count)
103{
104 const ra8_err_t v = internal_validate(bd);
105 if (v != k_ra8_ok) {
106 return v;
107 }
108 if (bd->iface->erase == nullptr) {
110 }
111 return bd->iface->erase(bd->ctx, lba, count);
112}
113
115{
116 const ra8_err_t v = internal_validate(bd);
117 if (v != k_ra8_ok) {
118 return v;
119 }
120 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
121 RA8_CHECK_NULL_PTR(bd->iface->get_caps, s_tag, "backend get_caps op missing");
122 return bd->iface->get_caps(bd->ctx, out);
123}
124
126{
127 const ra8_err_t v = internal_validate(bd);
128 if (v != k_ra8_ok) {
129 return v;
130 }
131 if (bd->iface->sync == nullptr) {
132 return k_ra8_ok;
133 }
134 return bd->iface->sync(bd->ctx);
135}
136
137/* =============================================================================
138 * ra8_fs_backend_t bridge
139 * =============================================================================
140 */
141
169static ra8_err_t internal_fs_read(void* ctx, uint64_t lba, uint32_t count, uint8_t* buf)
170{
171 RA8_CHECK_NULL_PTR(ctx, s_tag, "ctx (blockdev) must not be nullptr");
172 RA8_CHECK_NULL_PTR(buf, s_tag, "buf must not be nullptr");
173 /* The io fabric addresses 32-bit LBAs -- every backend it fronts (SD, XSPI,
174 * SDRAM, MRAM) fits comfortably -- so an address past that reach is refused
175 * here rather than truncated. The 64-bit `ra8_fs` interface (#683) stays
176 * fully honest: media needing it use a 64-bit-native backend. */
177 if (lba > (uint64_t)UINT32_MAX) {
179 }
180 return ra8_io_blockdev_read((const ra8_io_blockdev_t*)ctx, (uint32_t)lba, count, buf);
181}
182
210static ra8_err_t internal_fs_write(void* ctx, uint64_t lba, uint32_t count, const uint8_t* buf)
211{
212 RA8_CHECK_NULL_PTR(ctx, s_tag, "ctx (blockdev) must not be nullptr");
213 RA8_CHECK_NULL_PTR(buf, s_tag, "buf must not be nullptr");
214 if (lba > (uint64_t)UINT32_MAX) {
215 return k_ra8_err_out_of_range; /* fabric LBAs are 32-bit; see internal_fs_read */
216 }
217 return ra8_io_blockdev_write((const ra8_io_blockdev_t*)ctx, (uint32_t)lba, count, buf);
218}
219
246static ra8_err_t internal_fs_get_capacity(void* ctx, uint64_t* block_count, uint32_t* block_size)
247{
248 RA8_CHECK_NULL_PTR(ctx, s_tag, "ctx (blockdev) must not be nullptr");
249 RA8_CHECK_NULL_PTR(block_count, s_tag, "block_count must not be nullptr");
250 RA8_CHECK_NULL_PTR(block_size, s_tag, "block_size must not be nullptr");
251 ra8_io_blockdev_caps_t caps = {};
252 const ra8_err_t e = ra8_io_blockdev_get_caps((const ra8_io_blockdev_t*)ctx, &caps);
253 if (e != k_ra8_ok) {
254 return e;
255 }
256 *block_count = caps.block_count;
257 *block_size = (uint32_t)caps.logical_block_bytes;
258 return k_ra8_ok;
259}
260
289static ra8_err_t internal_fs_erase(void* ctx, uint64_t lba, uint64_t count)
290{
291 RA8_CHECK_NULL_PTR(ctx, s_tag, "ctx (blockdev) must not be nullptr");
292 const ra8_io_blockdev_t* bd = (const ra8_io_blockdev_t*)ctx;
293 ra8_io_blockdev_caps_t caps = {};
294 const ra8_err_t e = ra8_io_blockdev_get_caps(bd, &caps);
295 if (e != k_ra8_ok) {
296 return e;
297 }
298 if (caps.erase_value != (uint8_t)k_ra8_io_erase_value_zero) {
300 }
301 if ((lba > (uint64_t)UINT32_MAX) || (count > (uint64_t)UINT32_MAX)) {
302 return k_ra8_err_out_of_range; /* fabric LBAs are 32-bit; see internal_fs_read */
303 }
304 return ra8_io_blockdev_erase(bd, (uint32_t)lba, (uint32_t)count);
305}
306
308{
309 const ra8_err_t v = internal_validate(bd);
310 if (v != k_ra8_ok) {
311 return v;
312 }
313 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
318 out->ctx = (void*)(uintptr_t)bd;
319 return k_ra8_ok;
320}
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
Error Code Definitions for ra8-firmware.
@ k_ra8_err_not_supported
Requested feature not compiled in, not wired, or not supported by this MCU variant.
Definition ra8_err.h:180
@ 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
@ k_ra8_err_null_ptr
Pointer was NULL where a valid pointer was required.
Definition ra8_err.h:478
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Minimal FAT12/FAT16/FAT32 filesystem adapter (read + write).
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_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.
static ra8_err_t internal_fs_write(void *ctx, uint64_t lba, uint32_t count, const uint8_t *buf)
ra8_fs write trampoline – forward into the bound block device.
static ra8_err_t internal_fs_get_capacity(void *ctx, uint64_t *block_count, uint32_t *block_size)
ra8_fs capacity trampoline – map block-device caps to (count, size).
static ra8_err_t internal_fs_erase(void *ctx, uint64_t lba, uint64_t count)
ra8_fs erase trampoline – only advertise erase on zero-erase media.
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_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_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_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.
static ra8_err_t internal_validate(const ra8_io_blockdev_t *bd)
Reject a handle that is NULL or has no backend bound.
static ra8_err_t internal_fs_read(void *ctx, uint64_t lba, uint32_t count, uint8_t *buf)
ra8_fs read trampoline – forward into the bound block device.
ra8_io block-device fabric – one LBA vtable across every storage medium.
@ k_ra8_io_erase_value_zero
Block reads back as 0x00 after erase.
Backend implementation contract for the ra8_io block-device fabric.
Lightweight Logging Interface for ra8-firmware.
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.
Static properties a backend reports about its medium.
uint32_t block_count
Total addressable logical blocks.
uint8_t erase_value
Post-erase byte (ra8_io_erase_value_t).
uint16_t logical_block_bytes
Logical block size (always 512).
ra8_err_t(* get_caps)(const void *ctx, ra8_io_blockdev_caps_t *out)
Fill *out with the medium capabilities.
ra8_err_t(* erase)(void *ctx, uint32_t lba, uint32_t count)
Erase count blocks at lba.
ra8_err_t(* read)(void *ctx, uint32_t lba, uint32_t count, uint8_t *buf)
Read count blocks at lba into buf.
ra8_err_t(* write)(void *ctx, uint32_t lba, uint32_t count, const uint8_t *buf)
Write count blocks from buf at lba.
ra8_err_t(* sync)(void *ctx)
Commit any write buffering.
Caller-allocated block-device handle binding a backend to its context.
const ra8_io_blockdev_iface_t * iface
Bound backend vtable (private).
void * ctx
Backend-private context (private).