Files
littlefs/bd/lfs3_rambd.c
Christopher Haster 232f039ccc kiwibd: Added kiwibd, a lighter-weight variant of emubd
Useful for emulating much larger disks in a file (or in RAM). kiwibd
doesn't have all the features of emubd, but this allows it to prioritize
disk size and speed for benchmarking.

kiwibd still keeps some features useful for benchmarking/emulation:

- Optional erase value emulation, including nor-masking

- Read/prog/erase trackers for measuring bd operations

- Read/prog/erase sleeps for slowing down the simulation to a human
  viewable speed
2025-10-01 17:57:39 -05:00

132 lines
4.3 KiB
C

/*
* Block device emulated in RAM
*
* Copyright (c) 2022, The littlefs authors.
* Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "bd/lfs3_rambd.h"
int lfs3_rambd_createcfg(const struct lfs3_cfg *cfg,
const struct lfs3_rambd_cfg *bdcfg) {
LFS3_RAMBD_TRACE("lfs3_rambd_createcfg(%p {.context=%p, "
".read=%p, .prog=%p, .erase=%p, .sync=%p, "
".read_size=%"PRIu32", .prog_size=%"PRIu32", "
".block_size=%"PRIu32", .block_count=%"PRIu32"}, "
"%p {.buffer=%p})",
(void*)cfg, cfg->context,
(void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog,
(void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync,
cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count,
(void*)bdcfg, bdcfg->buffer);
lfs3_rambd_t *bd = cfg->context;
bd->cfg = bdcfg;
// allocate buffer?
if (bd->cfg->buffer) {
bd->mem = bd->cfg->buffer;
} else {
bd->mem = lfs3_malloc(cfg->block_size * cfg->block_count);
if (!bd->mem) {
LFS3_RAMBD_TRACE("lfs3_rambd_createcfg -> %d", LFS3_ERR_NOMEM);
return LFS3_ERR_NOMEM;
}
}
// zero for reproducibility
memset(bd->mem, 0, cfg->block_size * cfg->block_count);
LFS3_RAMBD_TRACE("lfs3_rambd_createcfg -> %d", 0);
return 0;
}
int lfs3_rambd_create(const struct lfs3_cfg *cfg) {
LFS3_RAMBD_TRACE("lfs3_rambd_create(%p {.context=%p, "
".read=%p, .prog=%p, .erase=%p, .sync=%p, "
".read_size=%"PRIu32", .prog_size=%"PRIu32", "
".block_size=%"PRIu32", .block_count=%"PRIu32"})",
(void*)cfg, cfg->context,
(void*)(uintptr_t)cfg->read, (void*)(uintptr_t)cfg->prog,
(void*)(uintptr_t)cfg->erase, (void*)(uintptr_t)cfg->sync,
cfg->read_size, cfg->prog_size, cfg->block_size, cfg->block_count);
static const struct lfs3_rambd_cfg defaults = {0};
int err = lfs3_rambd_createcfg(cfg, &defaults);
LFS3_RAMBD_TRACE("lfs3_rambd_create -> %d", err);
return err;
}
int lfs3_rambd_destroy(const struct lfs3_cfg *cfg) {
LFS3_RAMBD_TRACE("lfs3_rambd_destroy(%p)", (void*)cfg);
// clean up memory
lfs3_rambd_t *bd = cfg->context;
if (!bd->cfg->buffer) {
lfs3_free(bd->mem);
}
LFS3_RAMBD_TRACE("lfs3_rambd_destroy -> %d", 0);
return 0;
}
int lfs3_rambd_read(const struct lfs3_cfg *cfg, lfs3_block_t block,
lfs3_off_t off, void *buffer, lfs3_size_t size) {
LFS3_RAMBD_TRACE("lfs3_rambd_read(%p, "
"0x%"PRIx32", %"PRIu32", %p, %"PRIu32")",
(void*)cfg, block, off, buffer, size);
lfs3_rambd_t *bd = cfg->context;
// check if read is valid
LFS3_ASSERT(block < cfg->block_count);
LFS3_ASSERT(off % cfg->read_size == 0);
LFS3_ASSERT(size % cfg->read_size == 0);
LFS3_ASSERT(off+size <= cfg->block_size);
// read data
memcpy(buffer, &bd->mem[block*cfg->block_size + off], size);
LFS3_RAMBD_TRACE("lfs3_rambd_read -> %d", 0);
return 0;
}
int lfs3_rambd_prog(const struct lfs3_cfg *cfg, lfs3_block_t block,
lfs3_off_t off, const void *buffer, lfs3_size_t size) {
LFS3_RAMBD_TRACE("lfs3_rambd_prog(%p, "
"0x%"PRIx32", %"PRIu32", %p, %"PRIu32")",
(void*)cfg, block, off, buffer, size);
lfs3_rambd_t *bd = cfg->context;
// check if write is valid
LFS3_ASSERT(block < cfg->block_count);
LFS3_ASSERT(off % cfg->prog_size == 0);
LFS3_ASSERT(size % cfg->prog_size == 0);
LFS3_ASSERT(off+size <= cfg->block_size);
// program data
memcpy(&bd->mem[block*cfg->block_size + off], buffer, size);
LFS3_RAMBD_TRACE("lfs3_rambd_prog -> %d", 0);
return 0;
}
int lfs3_rambd_erase(const struct lfs3_cfg *cfg, lfs3_block_t block) {
LFS3_RAMBD_TRACE("lfs3_rambd_erase(%p, 0x%"PRIx32" (%"PRIu32"))",
(void*)cfg, block, cfg->block_size);
// check if erase is valid
LFS3_ASSERT(block < cfg->block_count);
// erase is a noop
(void)block;
LFS3_RAMBD_TRACE("lfs3_rambd_erase -> %d", 0);
return 0;
}
int lfs3_rambd_sync(const struct lfs3_cfg *cfg) {
LFS3_RAMBD_TRACE("lfs3_rambd_sync(%p)", (void*)cfg);
// sync is a noop
(void)cfg;
LFS3_RAMBD_TRACE("lfs3_rambd_sync -> %d", 0);
return 0;
}