ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_io_blockdev_mram.c
Go to the documentation of this file.
1
26
28
29#include <stddef.h>
30#include <stdint.h>
31#include <string.h>
32
33#include "ra8_attributes.h"
34#include "ra8_check.h"
35#include "ra8_err.h"
36#include "ra8_flash.h"
37#include "ra8_flash_regs.h"
38#include "ra8_io_blockdev.h"
40
42static const char* const s_tag = "ra8_io_blockdev_mram";
43
66
93internal_mram_bounds(const ra8_io_blockdev_mram_state_t* st, uint32_t lba, uint32_t count)
94{
95 if (count > st->block_count) {
97 }
98 if (lba > st->block_count - count) {
100 }
101 return k_ra8_ok;
102}
103
131RA8_INTERNAL static ra8_err_t internal_mram_window_ok(uintptr_t base, uint32_t block_count)
132{
133 const uintptr_t extra_start = (uintptr_t)k_ra8_flash_extra_start;
134 const uintptr_t extra_end = extra_start + (uintptr_t)k_ra8_flash_extra_size;
135 const uintptr_t span = (uintptr_t)block_count * (uintptr_t)k_ra8_io_block_size_bytes;
136 if ((base % (uintptr_t)k_ra8_io_mram_erase_block_bytes) != 0U) {
138 }
139 if ((span % (uintptr_t)k_ra8_io_mram_erase_block_bytes) != 0U) {
141 }
142 if (base < extra_start) {
144 }
145 if (base >= extra_end) {
147 }
148 if (span > extra_end - base) {
150 }
151 return k_ra8_ok;
152}
153
182internal_mram_read(void* ctx, uint32_t lba, uint32_t count, uint8_t* buf)
183{
184 RA8_CHECK_NULL_PTR(ctx, s_tag, "ctx must not be nullptr");
185 RA8_CHECK_NULL_PTR(buf, s_tag, "buf must not be nullptr");
187 const ra8_err_t b = internal_mram_bounds(st, lba, count);
188 if (b != k_ra8_ok) {
189 return b;
190 }
191 const size_t off = (size_t)lba * (size_t)k_ra8_io_block_size_bytes;
192 const size_t n = (size_t)count * (size_t)k_ra8_io_block_size_bytes;
193 (void)memcpy(buf, (const uint8_t*)(st->base + (uintptr_t)off), n);
194 return k_ra8_ok;
195}
196
229internal_mram_write(void* ctx, uint32_t lba, uint32_t count, const uint8_t* buf)
230{
231 RA8_CHECK_NULL_PTR(ctx, s_tag, "ctx must not be nullptr");
232 RA8_CHECK_NULL_PTR(buf, s_tag, "buf must not be nullptr");
234 if (st->read_only) {
236 }
237 const ra8_err_t b = internal_mram_bounds(st, lba, count);
238 if (b != k_ra8_ok) {
239 return b;
240 }
241 const uintptr_t off = (uintptr_t)lba * (uintptr_t)k_ra8_io_block_size_bytes;
242 const uintptr_t span = (uintptr_t)count * (uintptr_t)k_ra8_io_block_size_bytes;
243 const uint32_t step = (uint32_t)k_ra8_io_mram_program_bytes;
244 for (uintptr_t done = (uintptr_t)k_ra8_io_mram_zero_len; done < span; done += step) {
245 const ra8_err_t w =
246 ra8_flash_extra_mram_write((uint32_t)(st->base + off + done), &buf[done], step);
247 if (w != k_ra8_ok) {
248 return w;
249 }
250 }
251 return k_ra8_ok;
252}
253
284RA8_INTERNAL static ra8_err_t internal_mram_erase(void* ctx, uint32_t lba, uint32_t count)
285{
286 RA8_CHECK_NULL_PTR(ctx, s_tag, "ctx must not be nullptr");
288 if (st->read_only) {
290 }
291 const ra8_err_t b = internal_mram_bounds(st, lba, count);
292 if (b != k_ra8_ok) {
293 return b;
294 }
295 const uintptr_t off = (uintptr_t)lba * (uintptr_t)k_ra8_io_block_size_bytes;
296 const uintptr_t span = (uintptr_t)count * (uintptr_t)k_ra8_io_block_size_bytes;
297 const uint32_t step = (uint32_t)k_ra8_io_mram_erase_block_bytes;
298 for (uintptr_t done = (uintptr_t)k_ra8_io_mram_zero_len; done < span; done += step) {
299 const ra8_err_t e = ra8_flash_extra_mram_erase((uint32_t)(st->base + off + done));
300 if (e != k_ra8_ok) {
301 return e;
302 }
303 }
304 return k_ra8_ok;
305}
306
332{
333 RA8_CHECK_NULL_PTR(ctx, s_tag, "ctx must not be nullptr");
334 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
336 out->block_count = st->block_count;
341 out->must_erase_before_write = true;
342 out->read_only = st->read_only;
343 return k_ra8_ok;
344}
345
348 .read = internal_mram_read,
349 .write = internal_mram_write,
350 .erase = internal_mram_erase,
351 .get_caps = internal_mram_get_caps,
352 .sync = nullptr,
353};
354
357 uintptr_t base_addr,
358 uint32_t block_count,
359 bool read_only)
360{
361 RA8_CHECK_NULL_PTR(bd, s_tag, "bd must not be nullptr");
362 RA8_CHECK_NULL_PTR(state, s_tag, "state must not be nullptr");
363 if (block_count < (uint32_t)k_ra8_io_mram_min_blocks) {
365 }
366 const ra8_err_t w = internal_mram_window_ok(base_addr, block_count);
367 if (w != k_ra8_ok) {
368 return w;
369 }
370 state->base = base_addr;
371 state->block_count = block_count;
372 state->read_only = read_only;
373 bd->iface = &s_mram_iface;
374 bd->ctx = state;
375 return k_ra8_ok;
376}
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_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ 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
Code MRAM + Extra MRAM + Option-Setting driver – DANGEROUS, brick-capable.
ra8_err_t ra8_flash_extra_mram_erase(uint32_t mram_addr)
Erase one 32-byte block of extra-MRAM via MACI.
ra8_err_t ra8_flash_extra_mram_write(uint32_t mram_addr, const uint8_t *src, uint32_t len)
Program 1..32 contiguous bytes into the general-purpose extra-MRAM window.
Flash / MRAM controller register layout for the Renesas RA8D2.
@ k_ra8_flash_extra_start
First legal Program target (FSBL setting).
@ k_ra8_flash_extra_size
Covers through 0x02E179F0 (last, reserved).
@ k_ra8_mram_block_size_bytes
One programmable block.
@ k_ra8_mram_write_size_bytes
Minimum programmable unit.
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
ra8_io block-device fabric – one LBA vtable across every storage medium.
struct ra8_io_blockdev_iface ra8_io_blockdev_iface_t
@ k_ra8_io_erase_value_ones
Block reads back as 0xFF after erase.
@ k_ra8_io_block_size_bytes
Bytes per logical block (the only size).
Backend implementation contract for the ra8_io block-device fabric.
static ra8_err_t internal_mram_erase(void *ctx, uint32_t lba, uint32_t count)
MRAM backend: erase count blocks at lba to all-ones.
static ra8_err_t internal_mram_write(void *ctx, uint32_t lba, uint32_t count, const uint8_t *buf)
MRAM backend: program count blocks from buf at lba.
ra8_io_mram_const_t
MRAM-backend layout constants.
@ k_ra8_io_mram_min_blocks
Smallest legal device size.
@ k_ra8_io_mram_erase_block_bytes
MRAM erase/program unit in bytes (32).
@ k_ra8_io_mram_erase_unit_blocks
Logical-block erase granularity: 1 (MRAM erases in 32-byte sub-units).
@ k_ra8_io_mram_program_bytes
MRAM minimum program granularity in bytes (32).
@ k_ra8_io_mram_zero_len
Sentinel for an empty length.
static ra8_err_t internal_mram_get_caps(const void *ctx, ra8_io_blockdev_caps_t *out)
MRAM backend: report medium capabilities.
static ra8_err_t internal_mram_window_ok(uintptr_t base, uint32_t block_count)
Validate that an MRAM window is erase-aligned and inside data MRAM.
static ra8_err_t internal_mram_bounds(const ra8_io_blockdev_mram_state_t *st, uint32_t lba, uint32_t count)
Reject an out-of-range [lba, lba+count) block range.
ra8_err_t ra8_io_blockdev_mram_init(ra8_io_blockdev_t *bd, ra8_io_blockdev_mram_state_t *state, uintptr_t base_addr, uint32_t block_count, bool read_only)
Bind a hard-fenced MRAM block-device backend into a caller handle.
static const ra8_io_blockdev_iface_t s_mram_iface
MRAM backend vtable.
static ra8_err_t internal_mram_read(void *ctx, uint32_t lba, uint32_t count, uint8_t *buf)
MRAM backend: read count blocks at lba into buf.
ra8_io block-device backend over the on-chip extra/data MRAM region.
Static properties a backend reports about its medium.
uint32_t erase_unit_blocks
Erase granularity, in logical blocks.
uint32_t block_count
Total addressable logical blocks.
bool must_erase_before_write
true => program needs a prior erase.
bool read_only
true => writes/erases are rejected.
uint8_t erase_value
Post-erase byte (ra8_io_erase_value_t).
uint16_t logical_block_bytes
Logical block size (always 512).
uint32_t program_size_bytes
Minimum program granularity in bytes.
Caller-owned private state for an MRAM block device.
uint32_t block_count
Number of 512-byte logical blocks (private).
uintptr_t base
First MRAM byte address of the window (private).
bool read_only
true => writes and erases are rejected (private).
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).