forked from Imagelibrary/littlefs
Moved emulation of erase values up into lfs_testbd
Yes this is more expensive, since small programs need to rewrite the whole block in order to conform to the block device API. However, it reduces code duplication and keeps all of the test-related block device emulation in lfs_testbd. Some people have used lfs_filebd/lfs_rambd as a starting point for new block devices and I think it should be clear that erase does not need to have side effects. Though to be fair this also just means we should have more examples of block devices...
This commit is contained in:
111
bd/lfs_filebd.c
111
bd/lfs_filebd.c
@@ -15,39 +15,6 @@
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
int lfs_filebd_createcfg(const struct lfs_config *cfg, const char *path,
|
||||
const struct lfs_filebd_config *bdcfg) {
|
||||
LFS_FILEBD_TRACE("lfs_filebd_createcfg(%p {.context=%p, "
|
||||
".read=%p, .prog=%p, .erase=%p, .sync=%p, "
|
||||
".read_size=%"PRIu32", .prog_size=%"PRIu32", "
|
||||
".block_size=%"PRIu32", .block_count=%"PRIu32"}, "
|
||||
"\"%s\", "
|
||||
"%p {.erase_value=%"PRId32"})",
|
||||
(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,
|
||||
path, (void*)bdcfg, bdcfg->erase_value);
|
||||
lfs_filebd_t *bd = cfg->context;
|
||||
bd->cfg = bdcfg;
|
||||
|
||||
// open file
|
||||
#ifdef _WIN32
|
||||
bd->fd = open(path, O_RDWR | O_CREAT | O_BINARY, 0666);
|
||||
#else
|
||||
bd->fd = open(path, O_RDWR | O_CREAT, 0666);
|
||||
#endif
|
||||
|
||||
if (bd->fd < 0) {
|
||||
int err = -errno;
|
||||
LFS_FILEBD_TRACE("lfs_filebd_createcfg -> %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
LFS_FILEBD_TRACE("lfs_filebd_createcfg -> %d", 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lfs_filebd_create(const struct lfs_config *cfg, const char *path) {
|
||||
LFS_FILEBD_TRACE("lfs_filebd_create(%p {.context=%p, "
|
||||
".read=%p, .prog=%p, .erase=%p, .sync=%p, "
|
||||
@@ -58,11 +25,24 @@ int lfs_filebd_create(const struct lfs_config *cfg, const char *path) {
|
||||
(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,
|
||||
path);
|
||||
static const struct lfs_filebd_config defaults = {.erase_value=-1};
|
||||
int err = lfs_filebd_createcfg(cfg, path, &defaults);
|
||||
LFS_FILEBD_TRACE("lfs_filebd_create -> %d", err);
|
||||
return err;
|
||||
path, (void*)bdcfg, bdcfg->erase_value);
|
||||
lfs_filebd_t *bd = cfg->context;
|
||||
|
||||
// open file
|
||||
#ifdef _WIN32
|
||||
bd->fd = open(path, O_RDWR | O_CREAT | O_BINARY, 0666);
|
||||
#else
|
||||
bd->fd = open(path, O_RDWR | O_CREAT, 0666);
|
||||
#endif
|
||||
|
||||
if (bd->fd < 0) {
|
||||
int err = -errno;
|
||||
LFS_FILEBD_TRACE("lfs_filebd_create -> %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
LFS_FILEBD_TRACE("lfs_filebd_create -> %d", 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lfs_filebd_destroy(const struct lfs_config *cfg) {
|
||||
@@ -86,14 +66,13 @@ int lfs_filebd_read(const struct lfs_config *cfg, lfs_block_t block,
|
||||
lfs_filebd_t *bd = cfg->context;
|
||||
|
||||
// check if read is valid
|
||||
LFS_ASSERT(block < cfg->block_count);
|
||||
LFS_ASSERT(off % cfg->read_size == 0);
|
||||
LFS_ASSERT(size % cfg->read_size == 0);
|
||||
LFS_ASSERT(block < cfg->block_count);
|
||||
LFS_ASSERT(off+size <= cfg->block_size);
|
||||
|
||||
// zero for reproducibility (in case file is truncated)
|
||||
if (bd->cfg->erase_value != -1) {
|
||||
memset(buffer, bd->cfg->erase_value, size);
|
||||
}
|
||||
memset(buffer, 0, size);
|
||||
|
||||
// read
|
||||
off_t res1 = lseek(bd->fd,
|
||||
@@ -122,32 +101,10 @@ int lfs_filebd_prog(const struct lfs_config *cfg, lfs_block_t block,
|
||||
lfs_filebd_t *bd = cfg->context;
|
||||
|
||||
// check if write is valid
|
||||
LFS_ASSERT(block < cfg->block_count);
|
||||
LFS_ASSERT(off % cfg->prog_size == 0);
|
||||
LFS_ASSERT(size % cfg->prog_size == 0);
|
||||
LFS_ASSERT(block < cfg->block_count);
|
||||
|
||||
// check that data was erased? only needed for testing
|
||||
if (bd->cfg->erase_value != -1) {
|
||||
off_t res1 = lseek(bd->fd,
|
||||
(off_t)block*cfg->block_size + (off_t)off, SEEK_SET);
|
||||
if (res1 < 0) {
|
||||
int err = -errno;
|
||||
LFS_FILEBD_TRACE("lfs_filebd_prog -> %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
for (lfs_off_t i = 0; i < size; i++) {
|
||||
uint8_t c;
|
||||
ssize_t res2 = read(bd->fd, &c, 1);
|
||||
if (res2 < 0) {
|
||||
int err = -errno;
|
||||
LFS_FILEBD_TRACE("lfs_filebd_prog -> %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
LFS_ASSERT(c == bd->cfg->erase_value);
|
||||
}
|
||||
}
|
||||
LFS_ASSERT(off+size <= cfg->block_size);
|
||||
|
||||
// program data
|
||||
off_t res1 = lseek(bd->fd,
|
||||
@@ -171,29 +128,12 @@ int lfs_filebd_prog(const struct lfs_config *cfg, lfs_block_t block,
|
||||
|
||||
int lfs_filebd_erase(const struct lfs_config *cfg, lfs_block_t block) {
|
||||
LFS_FILEBD_TRACE("lfs_filebd_erase(%p, 0x%"PRIx32")", (void*)cfg, block);
|
||||
lfs_filebd_t *bd = cfg->context;
|
||||
|
||||
// check if erase is valid
|
||||
LFS_ASSERT(block < cfg->block_count);
|
||||
|
||||
// erase, only needed for testing
|
||||
if (bd->cfg->erase_value != -1) {
|
||||
off_t res1 = lseek(bd->fd, (off_t)block*cfg->block_size, SEEK_SET);
|
||||
if (res1 < 0) {
|
||||
int err = -errno;
|
||||
LFS_FILEBD_TRACE("lfs_filebd_erase -> %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
for (lfs_off_t i = 0; i < cfg->block_size; i++) {
|
||||
ssize_t res2 = write(bd->fd, &(uint8_t){bd->cfg->erase_value}, 1);
|
||||
if (res2 < 0) {
|
||||
int err = -errno;
|
||||
LFS_FILEBD_TRACE("lfs_filebd_erase -> %d", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
// erase is a noop
|
||||
(void)block;
|
||||
|
||||
LFS_FILEBD_TRACE("lfs_filebd_erase -> %d", 0);
|
||||
return 0;
|
||||
@@ -201,6 +141,7 @@ int lfs_filebd_erase(const struct lfs_config *cfg, lfs_block_t block) {
|
||||
|
||||
int lfs_filebd_sync(const struct lfs_config *cfg) {
|
||||
LFS_FILEBD_TRACE("lfs_filebd_sync(%p)", (void*)cfg);
|
||||
|
||||
// file sync
|
||||
lfs_filebd_t *bd = cfg->context;
|
||||
#ifdef _WIN32
|
||||
|
||||
@@ -26,25 +26,14 @@ extern "C"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// filebd config (optional)
|
||||
struct lfs_filebd_config {
|
||||
// 8-bit erase value to use for simulating erases. -1 does not simulate
|
||||
// erases, which can speed up testing by avoiding all the extra block-device
|
||||
// operations to store the erase value.
|
||||
int32_t erase_value;
|
||||
};
|
||||
|
||||
// filebd state
|
||||
typedef struct lfs_filebd {
|
||||
int fd;
|
||||
const struct lfs_filebd_config *cfg;
|
||||
} lfs_filebd_t;
|
||||
|
||||
|
||||
// Create a file block device using the geometry in lfs_config
|
||||
int lfs_filebd_create(const struct lfs_config *cfg, const char *path);
|
||||
int lfs_filebd_createcfg(const struct lfs_config *cfg, const char *path,
|
||||
const struct lfs_filebd_config *bdcfg);
|
||||
|
||||
// Clean up memory associated with block device
|
||||
int lfs_filebd_destroy(const struct lfs_config *cfg);
|
||||
|
||||
@@ -13,12 +13,12 @@ int lfs_rambd_createcfg(const struct lfs_config *cfg,
|
||||
".read=%p, .prog=%p, .erase=%p, .sync=%p, "
|
||||
".read_size=%"PRIu32", .prog_size=%"PRIu32", "
|
||||
".block_size=%"PRIu32", .block_count=%"PRIu32"}, "
|
||||
"%p {.erase_value=%"PRId32", .buffer=%p})",
|
||||
"%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->erase_value, bdcfg->buffer);
|
||||
(void*)bdcfg, bdcfg->buffer);
|
||||
lfs_rambd_t *bd = cfg->context;
|
||||
bd->cfg = bdcfg;
|
||||
|
||||
@@ -33,13 +33,8 @@ int lfs_rambd_createcfg(const struct lfs_config *cfg,
|
||||
}
|
||||
}
|
||||
|
||||
// zero for reproducibility?
|
||||
if (bd->cfg->erase_value != -1) {
|
||||
memset(bd->buffer, bd->cfg->erase_value,
|
||||
cfg->block_size * cfg->block_count);
|
||||
} else {
|
||||
memset(bd->buffer, 0, cfg->block_size * cfg->block_count);
|
||||
}
|
||||
// zero for reproducibility
|
||||
memset(bd->buffer, 0, cfg->block_size * cfg->block_count);
|
||||
|
||||
LFS_RAMBD_TRACE("lfs_rambd_createcfg -> %d", 0);
|
||||
return 0;
|
||||
@@ -54,7 +49,7 @@ int lfs_rambd_create(const struct lfs_config *cfg) {
|
||||
(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 lfs_rambd_config defaults = {.erase_value=-1};
|
||||
static const struct lfs_rambd_config defaults = {0};
|
||||
int err = lfs_rambd_createcfg(cfg, &defaults);
|
||||
LFS_RAMBD_TRACE("lfs_rambd_create -> %d", err);
|
||||
return err;
|
||||
@@ -79,9 +74,10 @@ int lfs_rambd_read(const struct lfs_config *cfg, lfs_block_t block,
|
||||
lfs_rambd_t *bd = cfg->context;
|
||||
|
||||
// check if read is valid
|
||||
LFS_ASSERT(block < cfg->block_count);
|
||||
LFS_ASSERT(off % cfg->read_size == 0);
|
||||
LFS_ASSERT(size % cfg->read_size == 0);
|
||||
LFS_ASSERT(block < cfg->block_count);
|
||||
LFS_ASSERT(off+size <= cfg->block_size);
|
||||
|
||||
// read data
|
||||
memcpy(buffer, &bd->buffer[block*cfg->block_size + off], size);
|
||||
@@ -98,17 +94,10 @@ int lfs_rambd_prog(const struct lfs_config *cfg, lfs_block_t block,
|
||||
lfs_rambd_t *bd = cfg->context;
|
||||
|
||||
// check if write is valid
|
||||
LFS_ASSERT(block < cfg->block_count);
|
||||
LFS_ASSERT(off % cfg->prog_size == 0);
|
||||
LFS_ASSERT(size % cfg->prog_size == 0);
|
||||
LFS_ASSERT(block < cfg->block_count);
|
||||
|
||||
// check that data was erased? only needed for testing
|
||||
if (bd->cfg->erase_value != -1) {
|
||||
for (lfs_off_t i = 0; i < size; i++) {
|
||||
LFS_ASSERT(bd->buffer[block*cfg->block_size + off + i] ==
|
||||
bd->cfg->erase_value);
|
||||
}
|
||||
}
|
||||
LFS_ASSERT(off+size <= cfg->block_size);
|
||||
|
||||
// program data
|
||||
memcpy(&bd->buffer[block*cfg->block_size + off], buffer, size);
|
||||
@@ -119,16 +108,12 @@ int lfs_rambd_prog(const struct lfs_config *cfg, lfs_block_t block,
|
||||
|
||||
int lfs_rambd_erase(const struct lfs_config *cfg, lfs_block_t block) {
|
||||
LFS_RAMBD_TRACE("lfs_rambd_erase(%p, 0x%"PRIx32")", (void*)cfg, block);
|
||||
lfs_rambd_t *bd = cfg->context;
|
||||
|
||||
// check if erase is valid
|
||||
LFS_ASSERT(block < cfg->block_count);
|
||||
|
||||
// erase, only needed for testing
|
||||
if (bd->cfg->erase_value != -1) {
|
||||
memset(&bd->buffer[block*cfg->block_size],
|
||||
bd->cfg->erase_value, cfg->block_size);
|
||||
}
|
||||
// erase is a noop
|
||||
(void)block;
|
||||
|
||||
LFS_RAMBD_TRACE("lfs_rambd_erase -> %d", 0);
|
||||
return 0;
|
||||
@@ -136,8 +121,10 @@ int lfs_rambd_erase(const struct lfs_config *cfg, lfs_block_t block) {
|
||||
|
||||
int lfs_rambd_sync(const struct lfs_config *cfg) {
|
||||
LFS_RAMBD_TRACE("lfs_rambd_sync(%p)", (void*)cfg);
|
||||
// sync does nothing because we aren't backed by anything real
|
||||
|
||||
// sync is a noop
|
||||
(void)cfg;
|
||||
|
||||
LFS_RAMBD_TRACE("lfs_rambd_sync -> %d", 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -28,10 +28,6 @@ extern "C"
|
||||
|
||||
// rambd config (optional)
|
||||
struct lfs_rambd_config {
|
||||
// 8-bit erase value to simulate erasing with. -1 indicates no erase
|
||||
// occurs, which is still a valid block device
|
||||
int32_t erase_value;
|
||||
|
||||
// Optional statically allocated buffer for the block device.
|
||||
void *buffer;
|
||||
};
|
||||
|
||||
@@ -35,6 +35,20 @@ int lfs_testbd_createcfg(const struct lfs_config *cfg, const char *path,
|
||||
bd->persist = path;
|
||||
bd->power_cycles = bd->cfg->power_cycles;
|
||||
|
||||
// create scratch block if we need it (for emulating erase values)
|
||||
if (bd->cfg->erase_value != -1) {
|
||||
if (bd->cfg->scratch_buffer) {
|
||||
bd->scratch = bd->cfg->scratch_buffer;
|
||||
} else {
|
||||
bd->scratch = lfs_malloc(cfg->block_size);
|
||||
if (!bd->scratch) {
|
||||
LFS_TESTBD_TRACE("lfs_testbd_createcfg -> %d", LFS_ERR_NOMEM);
|
||||
return LFS_ERR_NOMEM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create map of wear
|
||||
if (bd->cfg->erase_cycles) {
|
||||
if (bd->cfg->wear_buffer) {
|
||||
bd->wear = bd->cfg->wear_buffer;
|
||||
@@ -51,15 +65,11 @@ int lfs_testbd_createcfg(const struct lfs_config *cfg, const char *path,
|
||||
|
||||
// create underlying block device
|
||||
if (bd->persist) {
|
||||
bd->u.file.cfg = (struct lfs_filebd_config){
|
||||
.erase_value = bd->cfg->erase_value,
|
||||
};
|
||||
int err = lfs_filebd_createcfg(cfg, path, &bd->u.file.cfg);
|
||||
int err = lfs_filebd_create(cfg, path);
|
||||
LFS_TESTBD_TRACE("lfs_testbd_createcfg -> %d", err);
|
||||
return err;
|
||||
} else {
|
||||
bd->u.ram.cfg = (struct lfs_rambd_config){
|
||||
.erase_value = bd->cfg->erase_value,
|
||||
.buffer = bd->cfg->buffer,
|
||||
};
|
||||
int err = lfs_rambd_createcfg(cfg, &bd->u.ram.cfg);
|
||||
@@ -88,6 +98,10 @@ int lfs_testbd_create(const struct lfs_config *cfg, const char *path) {
|
||||
int lfs_testbd_destroy(const struct lfs_config *cfg) {
|
||||
LFS_TESTBD_TRACE("lfs_testbd_destroy(%p)", (void*)cfg);
|
||||
lfs_testbd_t *bd = cfg->context;
|
||||
|
||||
if (bd->cfg->erase_value != -1 && !bd->cfg->scratch_buffer) {
|
||||
lfs_free(bd->scratch);
|
||||
}
|
||||
if (bd->cfg->erase_cycles && !bd->cfg->wear_buffer) {
|
||||
lfs_free(bd->wear);
|
||||
}
|
||||
@@ -152,9 +166,10 @@ int lfs_testbd_read(const struct lfs_config *cfg, lfs_block_t block,
|
||||
lfs_testbd_t *bd = cfg->context;
|
||||
|
||||
// check if read is valid
|
||||
LFS_ASSERT(block < cfg->block_count);
|
||||
LFS_ASSERT(off % cfg->read_size == 0);
|
||||
LFS_ASSERT(size % cfg->read_size == 0);
|
||||
LFS_ASSERT(block < cfg->block_count);
|
||||
LFS_ASSERT(off+size <= cfg->block_size);
|
||||
|
||||
// block bad?
|
||||
if (bd->cfg->erase_cycles && bd->wear[block] >= bd->cfg->erase_cycles &&
|
||||
@@ -177,9 +192,10 @@ int lfs_testbd_prog(const struct lfs_config *cfg, lfs_block_t block,
|
||||
lfs_testbd_t *bd = cfg->context;
|
||||
|
||||
// check if write is valid
|
||||
LFS_ASSERT(block < cfg->block_count);
|
||||
LFS_ASSERT(off % cfg->prog_size == 0);
|
||||
LFS_ASSERT(size % cfg->prog_size == 0);
|
||||
LFS_ASSERT(block < cfg->block_count);
|
||||
LFS_ASSERT(off+size <= cfg->block_size);
|
||||
|
||||
// block bad?
|
||||
if (bd->cfg->erase_cycles && bd->wear[block] >= bd->cfg->erase_cycles) {
|
||||
@@ -196,11 +212,41 @@ int lfs_testbd_prog(const struct lfs_config *cfg, lfs_block_t block,
|
||||
}
|
||||
}
|
||||
|
||||
// prog
|
||||
int err = lfs_testbd_rawprog(cfg, block, off, buffer, size);
|
||||
if (err) {
|
||||
LFS_TESTBD_TRACE("lfs_testbd_prog -> %d", err);
|
||||
return err;
|
||||
// emulate an erase value?
|
||||
if (bd->cfg->erase_value != -1) {
|
||||
int err = lfs_testbd_rawread(cfg, block, 0,
|
||||
bd->scratch, cfg->block_size);
|
||||
if (err) {
|
||||
LFS_TESTBD_TRACE("lfs_testbd_prog -> %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
// assert that program block was erased
|
||||
for (lfs_off_t i = 0; i < size; i++) {
|
||||
LFS_ASSERT(bd->scratch[off+i] == bd->cfg->erase_value);
|
||||
}
|
||||
|
||||
memcpy(&bd->scratch[off], buffer, size);
|
||||
|
||||
err = lfs_testbd_rawerase(cfg, block);
|
||||
if (err) {
|
||||
LFS_TESTBD_TRACE("lfs_testbd_prog -> %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = lfs_testbd_rawprog(cfg, block, 0,
|
||||
bd->scratch, cfg->block_size);
|
||||
if (err) {
|
||||
LFS_TESTBD_TRACE("lfs_testbd_prog -> %d", err);
|
||||
return err;
|
||||
}
|
||||
} else {
|
||||
// prog
|
||||
int err = lfs_testbd_rawprog(cfg, block, off, buffer, size);
|
||||
if (err) {
|
||||
LFS_TESTBD_TRACE("lfs_testbd_prog -> %d", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
// lose power?
|
||||
@@ -243,11 +289,29 @@ int lfs_testbd_erase(const struct lfs_config *cfg, lfs_block_t block) {
|
||||
}
|
||||
}
|
||||
|
||||
// erase
|
||||
int err = lfs_testbd_rawerase(cfg, block);
|
||||
if (err) {
|
||||
LFS_TESTBD_TRACE("lfs_testbd_erase -> %d", err);
|
||||
return err;
|
||||
// emulate an erase value?
|
||||
if (bd->cfg->erase_value != -1) {
|
||||
memset(bd->scratch, bd->cfg->erase_value, cfg->block_size);
|
||||
|
||||
int err = lfs_testbd_rawerase(cfg, block);
|
||||
if (err) {
|
||||
LFS_TESTBD_TRACE("lfs_testbd_erase -> %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = lfs_testbd_rawprog(cfg, block, 0,
|
||||
bd->scratch, cfg->block_size);
|
||||
if (err) {
|
||||
LFS_TESTBD_TRACE("lfs_testbd_erase -> %d", err);
|
||||
return err;
|
||||
}
|
||||
} else {
|
||||
// erase
|
||||
int err = lfs_testbd_rawerase(cfg, block);
|
||||
if (err) {
|
||||
LFS_TESTBD_TRACE("lfs_testbd_erase -> %d", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
// lose power?
|
||||
|
||||
@@ -50,7 +50,7 @@ typedef int32_t lfs_testbd_swear_t;
|
||||
// testbd config, this is required for testing
|
||||
struct lfs_testbd_config {
|
||||
// 8-bit erase value to use for simulating erases. -1 does not simulate
|
||||
// erases, which can speed up testing by avoiding all the extra block-device
|
||||
// erases, which can speed up testing by avoiding the extra block-device
|
||||
// operations to store the erase value.
|
||||
int32_t erase_value;
|
||||
|
||||
@@ -68,8 +68,11 @@ struct lfs_testbd_config {
|
||||
// Optional buffer for RAM block device.
|
||||
void *buffer;
|
||||
|
||||
// Optional buffer for wear
|
||||
// Optional buffer for wear.
|
||||
void *wear_buffer;
|
||||
|
||||
// Optional buffer for scratch memory, needed when erase_value != -1.
|
||||
void *scratch_buffer;
|
||||
};
|
||||
|
||||
// testbd state
|
||||
@@ -77,7 +80,6 @@ typedef struct lfs_testbd {
|
||||
union {
|
||||
struct {
|
||||
lfs_filebd_t bd;
|
||||
struct lfs_filebd_config cfg;
|
||||
} file;
|
||||
struct {
|
||||
lfs_rambd_t bd;
|
||||
@@ -88,6 +90,7 @@ typedef struct lfs_testbd {
|
||||
bool persist;
|
||||
uint32_t power_cycles;
|
||||
lfs_testbd_wear_t *wear;
|
||||
uint8_t *scratch;
|
||||
|
||||
const struct lfs_testbd_config *cfg;
|
||||
} lfs_testbd_t;
|
||||
|
||||
Reference in New Issue
Block a user