mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 16:14:16 +01:00 
			
		
		
		
	Standardized on externally provided config structs in the block devices
I have another branch where I tried exploring inlined config structs backed by RAM, but this did not work out due to additional RAM and ROM costs. Changing the bds to follow this was surprisingly annoying, as they had a lot of shared geometry that was previously in a single shared config object, and the way that testbd contains either of rambd and filebd made configuring all three of these a bit complicated. Ended up settling on a lfs_testbd_cfg that contains optional pointers to lfs_rambd_cfg and lfs_filebd_cfg. These can be NULL, but only if that bd goes unused.
This commit is contained in:
		| @@ -19,9 +19,7 @@ int lfs_filebd_createcfg(lfs_filebd_t *bd, const char *path, | |||||||
|             (void*)bd, path, (void*)cfg, |             (void*)bd, path, (void*)cfg, | ||||||
|             cfg->read_size, cfg->prog_size, cfg->erase_size, cfg->erase_count, |             cfg->read_size, cfg->prog_size, cfg->erase_size, cfg->erase_count, | ||||||
|             cfg->erase_value); |             cfg->erase_value); | ||||||
|  |     bd->cfg = cfg; | ||||||
|     // copy over config |  | ||||||
|     bd->cfg = *cfg; |  | ||||||
|  |  | ||||||
|     // open file |     // open file | ||||||
|     bd->fd = open(path, O_RDWR | O_CREAT, 0666); |     bd->fd = open(path, O_RDWR | O_CREAT, 0666); | ||||||
| @@ -54,18 +52,18 @@ int lfs_filebd_read(lfs_filebd_t *bd, lfs_block_t block, | |||||||
|             (void*)bd, block, off, buffer, size); |             (void*)bd, block, off, buffer, size); | ||||||
|  |  | ||||||
|     // check if read is valid |     // check if read is valid | ||||||
|     LFS_ASSERT(off  % bd->cfg.read_size == 0); |     LFS_ASSERT(off  % bd->cfg->read_size == 0); | ||||||
|     LFS_ASSERT(size % bd->cfg.read_size == 0); |     LFS_ASSERT(size % bd->cfg->read_size == 0); | ||||||
|     LFS_ASSERT(block < bd->cfg.erase_count); |     LFS_ASSERT(block < bd->cfg->erase_count); | ||||||
|  |  | ||||||
|     // zero for reproducability (in case file is truncated) |     // zero for reproducability (in case file is truncated) | ||||||
|     if (bd->cfg.erase_value != -1) { |     if (bd->cfg->erase_value != -1) { | ||||||
|         memset(buffer, bd->cfg.erase_value, size); |         memset(buffer, bd->cfg->erase_value, size); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // read |     // read | ||||||
|     off_t res1 = lseek(bd->fd, |     off_t res1 = lseek(bd->fd, | ||||||
|             (off_t)block*bd->cfg.erase_size + (off_t)off, SEEK_SET); |             (off_t)block*bd->cfg->erase_size + (off_t)off, SEEK_SET); | ||||||
|     if (res1 < 0) { |     if (res1 < 0) { | ||||||
|         int err = -errno; |         int err = -errno; | ||||||
|         LFS_FILEBD_TRACE("lfs_filebd_read -> %d", err); |         LFS_FILEBD_TRACE("lfs_filebd_read -> %d", err); | ||||||
| @@ -90,14 +88,14 @@ int lfs_filebd_prog(lfs_filebd_t *bd, lfs_block_t block, | |||||||
|             (void*)bd, block, off, buffer, size); |             (void*)bd, block, off, buffer, size); | ||||||
|  |  | ||||||
|     // check if write is valid |     // check if write is valid | ||||||
|     LFS_ASSERT(off  % bd->cfg.prog_size == 0); |     LFS_ASSERT(off  % bd->cfg->prog_size == 0); | ||||||
|     LFS_ASSERT(size % bd->cfg.prog_size == 0); |     LFS_ASSERT(size % bd->cfg->prog_size == 0); | ||||||
|     LFS_ASSERT(block < bd->cfg.erase_count); |     LFS_ASSERT(block < bd->cfg->erase_count); | ||||||
|  |  | ||||||
|     // check that data was erased? only needed for testing |     // check that data was erased? only needed for testing | ||||||
|     if (bd->cfg.erase_value != -1) { |     if (bd->cfg->erase_value != -1) { | ||||||
|         off_t res1 = lseek(bd->fd, |         off_t res1 = lseek(bd->fd, | ||||||
|                 (off_t)block*bd->cfg.erase_size + (off_t)off, SEEK_SET); |                 (off_t)block*bd->cfg->erase_size + (off_t)off, SEEK_SET); | ||||||
|         if (res1 < 0) { |         if (res1 < 0) { | ||||||
|             int err = -errno; |             int err = -errno; | ||||||
|             LFS_FILEBD_TRACE("lfs_filebd_prog -> %d", err); |             LFS_FILEBD_TRACE("lfs_filebd_prog -> %d", err); | ||||||
| @@ -113,13 +111,13 @@ int lfs_filebd_prog(lfs_filebd_t *bd, lfs_block_t block, | |||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             LFS_ASSERT(c == bd->cfg.erase_value); |             LFS_ASSERT(c == bd->cfg->erase_value); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // program data |     // program data | ||||||
|     off_t res1 = lseek(bd->fd, |     off_t res1 = lseek(bd->fd, | ||||||
|             (off_t)block*bd->cfg.erase_size + (off_t)off, SEEK_SET); |             (off_t)block*bd->cfg->erase_size + (off_t)off, SEEK_SET); | ||||||
|     if (res1 < 0) { |     if (res1 < 0) { | ||||||
|         int err = -errno; |         int err = -errno; | ||||||
|         LFS_FILEBD_TRACE("lfs_filebd_prog -> %d", err); |         LFS_FILEBD_TRACE("lfs_filebd_prog -> %d", err); | ||||||
| @@ -141,19 +139,19 @@ int lfs_filebd_erase(lfs_filebd_t *bd, lfs_block_t block) { | |||||||
|     LFS_FILEBD_TRACE("lfs_filebd_erase(%p, 0x%"PRIx32")", (void*)bd, block); |     LFS_FILEBD_TRACE("lfs_filebd_erase(%p, 0x%"PRIx32")", (void*)bd, block); | ||||||
|  |  | ||||||
|     // check if erase is valid |     // check if erase is valid | ||||||
|     LFS_ASSERT(block < bd->cfg.erase_count); |     LFS_ASSERT(block < bd->cfg->erase_count); | ||||||
|  |  | ||||||
|     // erase, only needed for testing |     // erase, only needed for testing | ||||||
|     if (bd->cfg.erase_value != -1) { |     if (bd->cfg->erase_value != -1) { | ||||||
|         off_t res1 = lseek(bd->fd, (off_t)block*bd->cfg.erase_size, SEEK_SET); |         off_t res1 = lseek(bd->fd, (off_t)block*bd->cfg->erase_size, SEEK_SET); | ||||||
|         if (res1 < 0) { |         if (res1 < 0) { | ||||||
|             int err = -errno; |             int err = -errno; | ||||||
|             LFS_FILEBD_TRACE("lfs_filebd_erase -> %d", err); |             LFS_FILEBD_TRACE("lfs_filebd_erase -> %d", err); | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         for (lfs_off_t i = 0; i < bd->cfg.erase_size; i++) { |         for (lfs_off_t i = 0; i < bd->cfg->erase_size; i++) { | ||||||
|             ssize_t res2 = write(bd->fd, &(uint8_t){bd->cfg.erase_value}, 1); |             ssize_t res2 = write(bd->fd, &(uint8_t){bd->cfg->erase_value}, 1); | ||||||
|             if (res2 < 0) { |             if (res2 < 0) { | ||||||
|                 int err = -errno; |                 int err = -errno; | ||||||
|                 LFS_FILEBD_TRACE("lfs_filebd_erase -> %d", err); |                 LFS_FILEBD_TRACE("lfs_filebd_erase -> %d", err); | ||||||
|   | |||||||
| @@ -46,7 +46,7 @@ struct lfs_filebd_cfg { | |||||||
| // filebd state | // filebd state | ||||||
| typedef struct lfs_filebd { | typedef struct lfs_filebd { | ||||||
|     int fd; |     int fd; | ||||||
|     struct lfs_filebd_cfg cfg; |     const struct lfs_filebd_cfg *cfg; | ||||||
| } lfs_filebd_t; | } lfs_filebd_t; | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -15,15 +15,13 @@ int lfs_rambd_createcfg(lfs_rambd_t *bd, | |||||||
|             (void*)bd, (void*)cfg, |             (void*)bd, (void*)cfg, | ||||||
|             cfg->read_size, cfg->prog_size, cfg->erase_size, cfg->erase_count, |             cfg->read_size, cfg->prog_size, cfg->erase_size, cfg->erase_count, | ||||||
|             cfg->erase_value, cfg->buffer); |             cfg->erase_value, cfg->buffer); | ||||||
|  |     bd->cfg = cfg; | ||||||
|     // copy over config |  | ||||||
|     bd->cfg = *cfg; |  | ||||||
|  |  | ||||||
|     // allocate buffer? |     // allocate buffer? | ||||||
|     if (bd->cfg.buffer) { |     if (bd->cfg->buffer) { | ||||||
|         bd->buffer = bd->cfg.buffer; |         bd->buffer = bd->cfg->buffer; | ||||||
|     } else { |     } else { | ||||||
|         bd->buffer = lfs_malloc(bd->cfg.erase_size * bd->cfg.erase_count); |         bd->buffer = lfs_malloc(bd->cfg->erase_size * bd->cfg->erase_count); | ||||||
|         if (!bd->buffer) { |         if (!bd->buffer) { | ||||||
|             LFS_RAMBD_TRACE("lfs_rambd_createcfg -> %d", LFS_ERR_NOMEM); |             LFS_RAMBD_TRACE("lfs_rambd_createcfg -> %d", LFS_ERR_NOMEM); | ||||||
|             return LFS_ERR_NOMEM; |             return LFS_ERR_NOMEM; | ||||||
| @@ -31,9 +29,9 @@ int lfs_rambd_createcfg(lfs_rambd_t *bd, | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // zero for reproducability? |     // zero for reproducability? | ||||||
|     if (bd->cfg.erase_value != -1) { |     if (bd->cfg->erase_value != -1) { | ||||||
|         memset(bd->buffer, bd->cfg.erase_value, |         memset(bd->buffer, bd->cfg->erase_value, | ||||||
|                 bd->cfg.erase_size * bd->cfg.erase_count); |                 bd->cfg->erase_size * bd->cfg->erase_count); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     LFS_RAMBD_TRACE("lfs_rambd_createcfg -> %d", 0); |     LFS_RAMBD_TRACE("lfs_rambd_createcfg -> %d", 0); | ||||||
| @@ -43,7 +41,7 @@ int lfs_rambd_createcfg(lfs_rambd_t *bd, | |||||||
| int lfs_rambd_destroy(lfs_rambd_t *bd) { | int lfs_rambd_destroy(lfs_rambd_t *bd) { | ||||||
|     LFS_RAMBD_TRACE("lfs_rambd_destroy(%p)", (void*)bd); |     LFS_RAMBD_TRACE("lfs_rambd_destroy(%p)", (void*)bd); | ||||||
|     // clean up memory |     // clean up memory | ||||||
|     if (!bd->cfg.buffer) { |     if (!bd->cfg->buffer) { | ||||||
|         lfs_free(bd->buffer); |         lfs_free(bd->buffer); | ||||||
|     } |     } | ||||||
|     LFS_RAMBD_TRACE("lfs_rambd_destroy -> %d", 0); |     LFS_RAMBD_TRACE("lfs_rambd_destroy -> %d", 0); | ||||||
| @@ -57,12 +55,12 @@ int lfs_rambd_read(lfs_rambd_t *bd, lfs_block_t block, | |||||||
|             (void*)bd, block, off, buffer, size); |             (void*)bd, block, off, buffer, size); | ||||||
|  |  | ||||||
|     // check if read is valid |     // check if read is valid | ||||||
|     LFS_ASSERT(off  % bd->cfg.read_size == 0); |     LFS_ASSERT(off  % bd->cfg->read_size == 0); | ||||||
|     LFS_ASSERT(size % bd->cfg.read_size == 0); |     LFS_ASSERT(size % bd->cfg->read_size == 0); | ||||||
|     LFS_ASSERT(block < bd->cfg.erase_count); |     LFS_ASSERT(block < bd->cfg->erase_count); | ||||||
|  |  | ||||||
|     // read data |     // read data | ||||||
|     memcpy(buffer, &bd->buffer[block*bd->cfg.erase_size + off], size); |     memcpy(buffer, &bd->buffer[block*bd->cfg->erase_size + off], size); | ||||||
|  |  | ||||||
|     LFS_RAMBD_TRACE("lfs_rambd_read -> %d", 0); |     LFS_RAMBD_TRACE("lfs_rambd_read -> %d", 0); | ||||||
|     return 0; |     return 0; | ||||||
| @@ -75,20 +73,20 @@ int lfs_rambd_prog(lfs_rambd_t *bd, lfs_block_t block, | |||||||
|             (void*)bd, block, off, buffer, size); |             (void*)bd, block, off, buffer, size); | ||||||
|  |  | ||||||
|     // check if write is valid |     // check if write is valid | ||||||
|     LFS_ASSERT(off  % bd->cfg.prog_size == 0); |     LFS_ASSERT(off  % bd->cfg->prog_size == 0); | ||||||
|     LFS_ASSERT(size % bd->cfg.prog_size == 0); |     LFS_ASSERT(size % bd->cfg->prog_size == 0); | ||||||
|     LFS_ASSERT(block < bd->cfg.erase_count); |     LFS_ASSERT(block < bd->cfg->erase_count); | ||||||
|  |  | ||||||
|     // check that data was erased? only needed for testing |     // check that data was erased? only needed for testing | ||||||
|     if (bd->cfg.erase_value != -1) { |     if (bd->cfg->erase_value != -1) { | ||||||
|         for (lfs_off_t i = 0; i < size; i++) { |         for (lfs_off_t i = 0; i < size; i++) { | ||||||
|             LFS_ASSERT(bd->buffer[block*bd->cfg.erase_size + off + i] == |             LFS_ASSERT(bd->buffer[block*bd->cfg->erase_size + off + i] == | ||||||
|                     bd->cfg.erase_value); |                     bd->cfg->erase_value); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // program data |     // program data | ||||||
|     memcpy(&bd->buffer[block*bd->cfg.erase_size + off], buffer, size); |     memcpy(&bd->buffer[block*bd->cfg->erase_size + off], buffer, size); | ||||||
|  |  | ||||||
|     LFS_RAMBD_TRACE("lfs_rambd_prog -> %d", 0); |     LFS_RAMBD_TRACE("lfs_rambd_prog -> %d", 0); | ||||||
|     return 0; |     return 0; | ||||||
| @@ -98,12 +96,12 @@ int lfs_rambd_erase(lfs_rambd_t *bd, lfs_block_t block) { | |||||||
|     LFS_RAMBD_TRACE("lfs_rambd_erase(%p, 0x%"PRIx32")", (void*)bd, block); |     LFS_RAMBD_TRACE("lfs_rambd_erase(%p, 0x%"PRIx32")", (void*)bd, block); | ||||||
|  |  | ||||||
|     // check if erase is valid |     // check if erase is valid | ||||||
|     LFS_ASSERT(block < bd->cfg.erase_count); |     LFS_ASSERT(block < bd->cfg->erase_count); | ||||||
|  |  | ||||||
|     // erase, only needed for testing |     // erase, only needed for testing | ||||||
|     if (bd->cfg.erase_value != -1) { |     if (bd->cfg->erase_value != -1) { | ||||||
|         memset(&bd->buffer[block*bd->cfg.erase_size], |         memset(&bd->buffer[block*bd->cfg->erase_size], | ||||||
|                 bd->cfg.erase_value, bd->cfg.erase_size); |                 bd->cfg->erase_value, bd->cfg->erase_size); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     LFS_RAMBD_TRACE("lfs_rambd_erase -> %d", 0); |     LFS_RAMBD_TRACE("lfs_rambd_erase -> %d", 0); | ||||||
|   | |||||||
| @@ -37,8 +37,9 @@ struct lfs_rambd_cfg { | |||||||
|     // Number of erasable blocks on the device. |     // Number of erasable blocks on the device. | ||||||
|     lfs_size_t erase_count; |     lfs_size_t erase_count; | ||||||
|  |  | ||||||
|     // 8-bit erase value to simulate erasing with. -1 indicates no erase |     // 8-bit erase value to use for simulating erases. -1 does not simulate | ||||||
|     // occurs, which is still a valid block device |     // erases, which can speed up testing by avoiding all the extra block-device | ||||||
|  |     // operations to store the erase value. | ||||||
|     int32_t erase_value; |     int32_t erase_value; | ||||||
|  |  | ||||||
|     // Optional statically allocated buffer for the block device. |     // Optional statically allocated buffer for the block device. | ||||||
| @@ -48,7 +49,7 @@ struct lfs_rambd_cfg { | |||||||
| // rambd state | // rambd state | ||||||
| typedef struct lfs_rambd { | typedef struct lfs_rambd { | ||||||
|     uint8_t *buffer; |     uint8_t *buffer; | ||||||
|     struct lfs_rambd_cfg cfg; |     const struct lfs_rambd_cfg *cfg; | ||||||
| } lfs_rambd_t; | } lfs_rambd_t; | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -23,17 +23,15 @@ int lfs_testbd_createcfg(lfs_testbd_t *bd, const char *path, | |||||||
|             cfg->erase_value, cfg->erase_cycles, |             cfg->erase_value, cfg->erase_cycles, | ||||||
|             cfg->badblock_behavior, cfg->power_cycles, |             cfg->badblock_behavior, cfg->power_cycles, | ||||||
|             cfg->buffer, cfg->wear_buffer); |             cfg->buffer, cfg->wear_buffer); | ||||||
|  |     bd->cfg = cfg; | ||||||
|     // copy over config |  | ||||||
|     bd->cfg = *cfg; |  | ||||||
|  |  | ||||||
|     // setup testing things |     // setup testing things | ||||||
|     bd->persist = path; |     bd->persist = path; | ||||||
|     bd->power_cycles = bd->cfg.power_cycles; |     bd->power_cycles = bd->cfg->power_cycles; | ||||||
|  |  | ||||||
|     if (bd->cfg.erase_cycles) { |     if (bd->cfg->erase_cycles) { | ||||||
|         if (bd->cfg.wear_buffer) { |         if (bd->cfg->wear_buffer) { | ||||||
|             bd->wear = bd->cfg.wear_buffer; |             bd->wear = bd->cfg->wear_buffer; | ||||||
|         } else { |         } else { | ||||||
|             bd->wear = lfs_malloc(sizeof(lfs_testbd_wear_t)*cfg->erase_count); |             bd->wear = lfs_malloc(sizeof(lfs_testbd_wear_t)*cfg->erase_count); | ||||||
|             if (!bd->wear) { |             if (!bd->wear) { | ||||||
| @@ -42,29 +40,18 @@ int lfs_testbd_createcfg(lfs_testbd_t *bd, const char *path, | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         memset(bd->wear, 0, sizeof(lfs_testbd_wear_t) * bd->cfg.erase_count); |         memset(bd->wear, 0, sizeof(lfs_testbd_wear_t) * bd->cfg->erase_count); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // create underlying block device |     // create underlying block device | ||||||
|     if (bd->persist) { |     if (bd->persist) { | ||||||
|         int err = lfs_filebd_createcfg(&bd->impl.filebd, path, |         int err = lfs_filebd_createcfg(&bd->impl.filebd, path, | ||||||
|                 &(struct lfs_filebd_cfg){ |                 bd->cfg->filebd_cfg); | ||||||
|                     .read_size=bd->cfg.read_size, |  | ||||||
|                     .prog_size=bd->cfg.prog_size, |  | ||||||
|                     .erase_size=bd->cfg.erase_size, |  | ||||||
|                     .erase_count=bd->cfg.erase_count, |  | ||||||
|                     .erase_value=bd->cfg.erase_value}); |  | ||||||
|         LFS_TESTBD_TRACE("lfs_testbd_createcfg -> %d", err); |         LFS_TESTBD_TRACE("lfs_testbd_createcfg -> %d", err); | ||||||
|         return err; |         return err; | ||||||
|     } else { |     } else { | ||||||
|         int err = lfs_rambd_createcfg(&bd->impl.rambd, |         int err = lfs_rambd_createcfg(&bd->impl.rambd, | ||||||
|                 &(struct lfs_rambd_cfg){ |                 bd->cfg->rambd_cfg); | ||||||
|                     .read_size=bd->cfg.read_size, |  | ||||||
|                     .prog_size=bd->cfg.prog_size, |  | ||||||
|                     .erase_size=bd->cfg.erase_size, |  | ||||||
|                     .erase_count=bd->cfg.erase_count, |  | ||||||
|                     .erase_value=bd->cfg.erase_value, |  | ||||||
|                     .buffer=bd->cfg.buffer}); |  | ||||||
|         LFS_TESTBD_TRACE("lfs_testbd_createcfg -> %d", err); |         LFS_TESTBD_TRACE("lfs_testbd_createcfg -> %d", err); | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
| @@ -72,7 +59,7 @@ int lfs_testbd_createcfg(lfs_testbd_t *bd, const char *path, | |||||||
|  |  | ||||||
| int lfs_testbd_destroy(lfs_testbd_t *bd) { | int lfs_testbd_destroy(lfs_testbd_t *bd) { | ||||||
|     LFS_TESTBD_TRACE("lfs_testbd_destroy(%p)", (void*)bd); |     LFS_TESTBD_TRACE("lfs_testbd_destroy(%p)", (void*)bd); | ||||||
|     if (bd->cfg.erase_cycles && !bd->cfg.wear_buffer) { |     if (bd->cfg->erase_cycles && !bd->cfg->wear_buffer) { | ||||||
|         lfs_free(bd->wear); |         lfs_free(bd->wear); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -131,13 +118,13 @@ int lfs_testbd_read(lfs_testbd_t *bd, lfs_block_t block, | |||||||
|             (void*)bd, block, off, buffer, size); |             (void*)bd, block, off, buffer, size); | ||||||
|  |  | ||||||
|     // check if read is valid |     // check if read is valid | ||||||
|     LFS_ASSERT(off  % bd->cfg.read_size == 0); |     LFS_ASSERT(off  % bd->cfg->read_size == 0); | ||||||
|     LFS_ASSERT(size % bd->cfg.read_size == 0); |     LFS_ASSERT(size % bd->cfg->read_size == 0); | ||||||
|     LFS_ASSERT(block < bd->cfg.erase_count); |     LFS_ASSERT(block < bd->cfg->erase_count); | ||||||
|  |  | ||||||
|     // block bad? |     // block bad? | ||||||
|     if (bd->cfg.erase_cycles && bd->wear[block] >= bd->cfg.erase_cycles && |     if (bd->cfg->erase_cycles && bd->wear[block] >= bd->cfg->erase_cycles && | ||||||
|             bd->cfg.badblock_behavior == LFS_TESTBD_BADBLOCK_READERROR) { |             bd->cfg->badblock_behavior == LFS_TESTBD_BADBLOCK_READERROR) { | ||||||
|         LFS_TESTBD_TRACE("lfs_testbd_read -> %d", LFS_ERR_CORRUPT); |         LFS_TESTBD_TRACE("lfs_testbd_read -> %d", LFS_ERR_CORRUPT); | ||||||
|         return LFS_ERR_CORRUPT; |         return LFS_ERR_CORRUPT; | ||||||
|     } |     } | ||||||
| @@ -155,19 +142,19 @@ int lfs_testbd_prog(lfs_testbd_t *bd, lfs_block_t block, | |||||||
|             (void*)bd, block, off, buffer, size); |             (void*)bd, block, off, buffer, size); | ||||||
|  |  | ||||||
|     // check if write is valid |     // check if write is valid | ||||||
|     LFS_ASSERT(off  % bd->cfg.prog_size == 0); |     LFS_ASSERT(off  % bd->cfg->prog_size == 0); | ||||||
|     LFS_ASSERT(size % bd->cfg.prog_size == 0); |     LFS_ASSERT(size % bd->cfg->prog_size == 0); | ||||||
|     LFS_ASSERT(block < bd->cfg.erase_count); |     LFS_ASSERT(block < bd->cfg->erase_count); | ||||||
|  |  | ||||||
|     // block bad? |     // block bad? | ||||||
|     if (bd->cfg.erase_cycles && bd->wear[block] >= bd->cfg.erase_cycles) { |     if (bd->cfg->erase_cycles && bd->wear[block] >= bd->cfg->erase_cycles) { | ||||||
|         if (bd->cfg.badblock_behavior == |         if (bd->cfg->badblock_behavior == | ||||||
|                 LFS_TESTBD_BADBLOCK_PROGERROR) { |                 LFS_TESTBD_BADBLOCK_PROGERROR) { | ||||||
|             LFS_TESTBD_TRACE("lfs_testbd_prog -> %d", LFS_ERR_CORRUPT); |             LFS_TESTBD_TRACE("lfs_testbd_prog -> %d", LFS_ERR_CORRUPT); | ||||||
|             return LFS_ERR_CORRUPT; |             return LFS_ERR_CORRUPT; | ||||||
|         } else if (bd->cfg.badblock_behavior == |         } else if (bd->cfg->badblock_behavior == | ||||||
|                 LFS_TESTBD_BADBLOCK_PROGNOOP || |                 LFS_TESTBD_BADBLOCK_PROGNOOP || | ||||||
|                 bd->cfg.badblock_behavior == |                 bd->cfg->badblock_behavior == | ||||||
|                 LFS_TESTBD_BADBLOCK_ERASENOOP) { |                 LFS_TESTBD_BADBLOCK_ERASENOOP) { | ||||||
|             LFS_TESTBD_TRACE("lfs_testbd_prog -> %d", 0); |             LFS_TESTBD_TRACE("lfs_testbd_prog -> %d", 0); | ||||||
|             return 0; |             return 0; | ||||||
| @@ -200,16 +187,16 @@ int lfs_testbd_erase(lfs_testbd_t *bd, lfs_block_t block) { | |||||||
|     LFS_TESTBD_TRACE("lfs_testbd_erase(%p, 0x%"PRIx32")", (void*)bd, block); |     LFS_TESTBD_TRACE("lfs_testbd_erase(%p, 0x%"PRIx32")", (void*)bd, block); | ||||||
|  |  | ||||||
|     // check if erase is valid |     // check if erase is valid | ||||||
|     LFS_ASSERT(block < bd->cfg.erase_count); |     LFS_ASSERT(block < bd->cfg->erase_count); | ||||||
|  |  | ||||||
|     // block bad? |     // block bad? | ||||||
|     if (bd->cfg.erase_cycles) { |     if (bd->cfg->erase_cycles) { | ||||||
|         if (bd->wear[block] >= bd->cfg.erase_cycles) { |         if (bd->wear[block] >= bd->cfg->erase_cycles) { | ||||||
|             if (bd->cfg.badblock_behavior == |             if (bd->cfg->badblock_behavior == | ||||||
|                     LFS_TESTBD_BADBLOCK_ERASEERROR) { |                     LFS_TESTBD_BADBLOCK_ERASEERROR) { | ||||||
|                 LFS_TESTBD_TRACE("lfs_testbd_erase -> %d", LFS_ERR_CORRUPT); |                 LFS_TESTBD_TRACE("lfs_testbd_erase -> %d", LFS_ERR_CORRUPT); | ||||||
|                 return LFS_ERR_CORRUPT; |                 return LFS_ERR_CORRUPT; | ||||||
|             } else if (bd->cfg.badblock_behavior == |             } else if (bd->cfg->badblock_behavior == | ||||||
|                     LFS_TESTBD_BADBLOCK_ERASENOOP) { |                     LFS_TESTBD_BADBLOCK_ERASENOOP) { | ||||||
|                 LFS_TESTBD_TRACE("lfs_testbd_erase -> %d", 0); |                 LFS_TESTBD_TRACE("lfs_testbd_erase -> %d", 0); | ||||||
|                 return 0; |                 return 0; | ||||||
| @@ -256,8 +243,8 @@ lfs_testbd_swear_t lfs_testbd_getwear(lfs_testbd_t *bd, | |||||||
|     LFS_TESTBD_TRACE("lfs_testbd_getwear(%p, %"PRIu32")", (void*)bd, block); |     LFS_TESTBD_TRACE("lfs_testbd_getwear(%p, %"PRIu32")", (void*)bd, block); | ||||||
|  |  | ||||||
|     // check if block is valid |     // check if block is valid | ||||||
|     LFS_ASSERT(bd->cfg.erase_cycles); |     LFS_ASSERT(bd->cfg->erase_cycles); | ||||||
|     LFS_ASSERT(block < bd->cfg.erase_count); |     LFS_ASSERT(block < bd->cfg->erase_count); | ||||||
|  |  | ||||||
|     LFS_TESTBD_TRACE("lfs_testbd_getwear -> %"PRIu32, bd->wear[block]); |     LFS_TESTBD_TRACE("lfs_testbd_getwear -> %"PRIu32, bd->wear[block]); | ||||||
|     return bd->wear[block]; |     return bd->wear[block]; | ||||||
| @@ -268,8 +255,8 @@ int lfs_testbd_setwear(lfs_testbd_t *bd, | |||||||
|     LFS_TESTBD_TRACE("lfs_testbd_setwear(%p, %"PRIu32")", (void*)bd, block); |     LFS_TESTBD_TRACE("lfs_testbd_setwear(%p, %"PRIu32")", (void*)bd, block); | ||||||
|  |  | ||||||
|     // check if block is valid |     // check if block is valid | ||||||
|     LFS_ASSERT(bd->cfg.erase_cycles); |     LFS_ASSERT(bd->cfg->erase_cycles); | ||||||
|     LFS_ASSERT(block < bd->cfg.erase_count); |     LFS_ASSERT(block < bd->cfg->erase_count); | ||||||
|  |  | ||||||
|     bd->wear[block] = wear; |     bd->wear[block] = wear; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -44,6 +44,11 @@ typedef int32_t  lfs_testbd_swear_t; | |||||||
|  |  | ||||||
| // testbd config, this is required for testing | // testbd config, this is required for testing | ||||||
| struct lfs_testbd_cfg { | struct lfs_testbd_cfg { | ||||||
|  |     // Block device specific configuration, see the related config structs. | ||||||
|  |     // May be NULL if the underlying implementation goes unused. | ||||||
|  |     const struct lfs_rambd_cfg *rambd_cfg; | ||||||
|  |     const struct lfs_filebd_cfg *filebd_cfg; | ||||||
|  |  | ||||||
|     // Minimum size of block read. All read operations must be a |     // Minimum size of block read. All read operations must be a | ||||||
|     // multiple of this value. |     // multiple of this value. | ||||||
|     lfs_size_t read_size; |     lfs_size_t read_size; | ||||||
| @@ -74,9 +79,6 @@ struct lfs_testbd_cfg { | |||||||
|     // the program with exit. Simulates power-loss. 0 disables. |     // the program with exit. Simulates power-loss. 0 disables. | ||||||
|     uint32_t power_cycles; |     uint32_t power_cycles; | ||||||
|  |  | ||||||
|     // Optional buffer for RAM block device. |  | ||||||
|     void *buffer; |  | ||||||
|  |  | ||||||
|     // Optional buffer for wear |     // Optional buffer for wear | ||||||
|     void *wear_buffer; |     void *wear_buffer; | ||||||
| }; | }; | ||||||
| @@ -92,7 +94,7 @@ typedef struct lfs_testbd { | |||||||
|     uint32_t power_cycles; |     uint32_t power_cycles; | ||||||
|     lfs_testbd_wear_t *wear; |     lfs_testbd_wear_t *wear; | ||||||
|  |  | ||||||
|     struct lfs_testbd_cfg cfg; |     const struct lfs_testbd_cfg *cfg; | ||||||
| } lfs_testbd_t; | } lfs_testbd_t; | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -112,6 +112,20 @@ PROLOGUE = """ | |||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     __attribute__((unused)) const struct lfs_testbd_cfg bdcfg = { |     __attribute__((unused)) const struct lfs_testbd_cfg bdcfg = { | ||||||
|  |         .rambd_cfg = &(const struct lfs_rambd_cfg){ | ||||||
|  |             .read_size      = LFS_READ_SIZE, | ||||||
|  |             .prog_size      = LFS_PROG_SIZE, | ||||||
|  |             .erase_size     = LFS_BLOCK_SIZE, | ||||||
|  |             .erase_count    = LFS_BLOCK_COUNT, | ||||||
|  |             .erase_value    = LFS_ERASE_VALUE, | ||||||
|  |         }, | ||||||
|  |         .filebd_cfg = &(const struct lfs_filebd_cfg){ | ||||||
|  |             .read_size      = LFS_READ_SIZE, | ||||||
|  |             .prog_size      = LFS_PROG_SIZE, | ||||||
|  |             .erase_size     = LFS_BLOCK_SIZE, | ||||||
|  |             .erase_count    = LFS_BLOCK_COUNT, | ||||||
|  |             .erase_value    = LFS_ERASE_VALUE, | ||||||
|  |         }, | ||||||
|         .read_size          = LFS_READ_SIZE, |         .read_size          = LFS_READ_SIZE, | ||||||
|         .prog_size          = LFS_PROG_SIZE, |         .prog_size          = LFS_PROG_SIZE, | ||||||
|         .erase_size         = LFS_BLOCK_SIZE, |         .erase_size         = LFS_BLOCK_SIZE, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user