nvs: modify nvs block size and block numbers

mtd_config_fs/Kconfig: update nvs block size and block number to configurable

Signed-off-by: zhaoxingyu1 <zhaoxingyu1@xiaomi.com>
This commit is contained in:
zhaoxingyu1 2024-08-07 18:48:20 +08:00 committed by Petro Karashchenko
parent 352e3a6873
commit 517d55a2ce
2 changed files with 44 additions and 30 deletions

View File

@ -202,6 +202,13 @@ config MTD_WRITE_ALIGN_SIZE
---help--- ---help---
align size will be one of 1,2,4,8,16 align size will be one of 1,2,4,8,16
config MTD_BLOCKSIZE_MULTIPLE
int "Set NVS blocksize multiple"
default 1
depends on MTD_CONFIG_FAIL_SAFE
---help---
The size of a multiple of blocksize compared to erasize
endif # MTD_CONFIG endif # MTD_CONFIG
comment "MTD Device Drivers" comment "MTD Device Drivers"

View File

@ -93,7 +93,8 @@
struct nvs_fs struct nvs_fs
{ {
FAR struct mtd_dev_s *mtd; /* MTD device */ FAR struct mtd_dev_s *mtd; /* MTD device */
struct mtd_geometry_s geo; uint32_t blocksize; /* Size of one nvs block */
uint32_t nblocks; /* Number of nvs blocks */
uint8_t erasestate; /* Erased value */ uint8_t erasestate; /* Erased value */
uint32_t ate_wra; /* Next alloc table entry uint32_t ate_wra; /* Next alloc table entry
* Write address * Write address
@ -203,7 +204,7 @@ static int nvs_flash_wrt(FAR struct nvs_fs *fs, uint32_t addr,
off_t offset; off_t offset;
int ret; int ret;
offset = fs->geo.erasesize * (addr >> ADDR_BLOCK_SHIFT); offset = fs->blocksize * (addr >> ADDR_BLOCK_SHIFT);
offset += addr & ADDR_OFFS_MASK; offset += addr & ADDR_OFFS_MASK;
ret = MTD_WRITE(fs->mtd, offset, len, data); ret = MTD_WRITE(fs->mtd, offset, len, data);
@ -229,7 +230,7 @@ static int nvs_flash_rd(FAR struct nvs_fs *fs, uint32_t addr,
off_t offset; off_t offset;
int ret; int ret;
offset = fs->geo.erasesize * (addr >> ADDR_BLOCK_SHIFT); offset = fs->blocksize * (addr >> ADDR_BLOCK_SHIFT);
offset += addr & ADDR_OFFS_MASK; offset += addr & ADDR_OFFS_MASK;
ret = MTD_READ(fs->mtd, offset, len, data); ret = MTD_READ(fs->mtd, offset, len, data);
@ -461,7 +462,9 @@ static int nvs_flash_erase_block(FAR struct nvs_fs *fs, uint32_t addr)
int rc; int rc;
finfo("Erasing addr %" PRIx32 "\n", addr); finfo("Erasing addr %" PRIx32 "\n", addr);
rc = MTD_ERASE(fs->mtd, addr >> ADDR_BLOCK_SHIFT, 1); rc = MTD_ERASE(fs->mtd,
CONFIG_MTD_BLOCKSIZE_MULTIPLE * (addr >> ADDR_BLOCK_SHIFT),
CONFIG_MTD_BLOCKSIZE_MULTIPLE);
if (rc < 0) if (rc < 0)
{ {
ferr("Erasing failed %d\n", rc); ferr("Erasing failed %d\n", rc);
@ -549,7 +552,7 @@ static int nvs_ate_valid(FAR struct nvs_fs *fs,
FAR const struct nvs_ate *entry) FAR const struct nvs_ate *entry)
{ {
if (nvs_ate_crc8_check(entry) || if (nvs_ate_crc8_check(entry) ||
entry->offset >= (fs->geo.erasesize - sizeof(struct nvs_ate))) entry->offset >= (fs->blocksize - sizeof(struct nvs_ate)))
{ {
return 0; return 0;
} }
@ -579,7 +582,7 @@ static int nvs_close_ate_valid(FAR struct nvs_fs *fs,
return 0; return 0;
} }
if ((fs->geo.erasesize - entry->offset) % sizeof(struct nvs_ate)) if ((fs->blocksize - entry->offset) % sizeof(struct nvs_ate))
{ {
return 0; return 0;
} }
@ -788,7 +791,7 @@ static int nvs_prev_ate(FAR struct nvs_fs *fs, FAR uint32_t *addr,
*addr += sizeof(struct nvs_ate); *addr += sizeof(struct nvs_ate);
if (((*addr) & ADDR_OFFS_MASK) != if (((*addr) & ADDR_OFFS_MASK) !=
(fs->geo.erasesize - sizeof(struct nvs_ate))) (fs->blocksize - sizeof(struct nvs_ate)))
{ {
return 0; return 0;
} }
@ -797,7 +800,7 @@ static int nvs_prev_ate(FAR struct nvs_fs *fs, FAR uint32_t *addr,
if (((*addr) >> ADDR_BLOCK_SHIFT) == 0) if (((*addr) >> ADDR_BLOCK_SHIFT) == 0)
{ {
*addr += ((fs->geo.neraseblocks - 1) << ADDR_BLOCK_SHIFT); *addr += ((fs->nblocks - 1) << ADDR_BLOCK_SHIFT);
} }
else else
{ {
@ -847,9 +850,9 @@ static int nvs_prev_ate(FAR struct nvs_fs *fs, FAR uint32_t *addr,
static void nvs_block_advance(FAR struct nvs_fs *fs, FAR uint32_t *addr) static void nvs_block_advance(FAR struct nvs_fs *fs, FAR uint32_t *addr)
{ {
*addr += (1 << ADDR_BLOCK_SHIFT); *addr += (1 << ADDR_BLOCK_SHIFT);
if ((*addr >> ADDR_BLOCK_SHIFT) == fs->geo.neraseblocks) if ((*addr >> ADDR_BLOCK_SHIFT) == fs->nblocks)
{ {
*addr -= (fs->geo.neraseblocks << ADDR_BLOCK_SHIFT); *addr -= (fs->nblocks << ADDR_BLOCK_SHIFT);
} }
} }
@ -875,7 +878,7 @@ static int nvs_block_close(FAR struct nvs_fs *fs)
(fs->ate_wra + sizeof(struct nvs_ate)) & ADDR_OFFS_MASK; (fs->ate_wra + sizeof(struct nvs_ate)) & ADDR_OFFS_MASK;
fs->ate_wra &= ADDR_BLOCK_MASK; fs->ate_wra &= ADDR_BLOCK_MASK;
fs->ate_wra += fs->geo.erasesize - sizeof(struct nvs_ate); fs->ate_wra += fs->blocksize - sizeof(struct nvs_ate);
nvs_ate_crc8_update(&close_ate); nvs_ate_crc8_update(&close_ate);
@ -950,7 +953,7 @@ static int nvs_gc(FAR struct nvs_fs *fs)
sec_addr = (fs->ate_wra & ADDR_BLOCK_MASK); sec_addr = (fs->ate_wra & ADDR_BLOCK_MASK);
nvs_block_advance(fs, &sec_addr); nvs_block_advance(fs, &sec_addr);
gc_addr = sec_addr + fs->geo.erasesize - sizeof(struct nvs_ate); gc_addr = sec_addr + fs->blocksize - sizeof(struct nvs_ate);
finfo("gc: set, sec_addr %" PRIx32 ", gc_addr %" PRIx32 "\n", sec_addr, finfo("gc: set, sec_addr %" PRIx32 ", gc_addr %" PRIx32 "\n", sec_addr,
gc_addr); gc_addr);
@ -1068,8 +1071,9 @@ static int nvs_startup(FAR struct nvs_fs *fs)
uint32_t second_addr; uint32_t second_addr;
uint32_t last_addr; uint32_t last_addr;
struct nvs_ate second_ate; struct nvs_ate second_ate;
struct mtd_geometry_s geo;
/* Initialize addr to 0 for the case fs->geo.neraseblocks == 0. This /* Initialize addr to 0 for the case fs->nblocks == 0. This
* should never happen but both * should never happen but both
* Coverity and GCC believe the contrary. * Coverity and GCC believe the contrary.
*/ */
@ -1087,7 +1091,7 @@ static int nvs_startup(FAR struct nvs_fs *fs)
*/ */
rc = MTD_IOCTL(fs->mtd, MTDIOC_GEOMETRY, rc = MTD_IOCTL(fs->mtd, MTDIOC_GEOMETRY,
(unsigned long)((uintptr_t)&(fs->geo))); (unsigned long)((uintptr_t)&(geo)));
if (rc < 0) if (rc < 0)
{ {
ferr("ERROR: MTD ioctl(MTDIOC_GEOMETRY) failed: %d\n", rc); ferr("ERROR: MTD ioctl(MTDIOC_GEOMETRY) failed: %d\n", rc);
@ -1102,9 +1106,12 @@ static int nvs_startup(FAR struct nvs_fs *fs)
return rc; return rc;
} }
fs->blocksize = CONFIG_MTD_BLOCKSIZE_MULTIPLE * geo.erasesize;
fs->nblocks = geo.neraseblocks / CONFIG_MTD_BLOCKSIZE_MULTIPLE;
/* Check the number of blocks, it should be at least 2. */ /* Check the number of blocks, it should be at least 2. */
if (fs->geo.neraseblocks < 2) if (fs->nblocks < 2)
{ {
ferr("Configuration error - block count\n"); ferr("Configuration error - block count\n");
return -EINVAL; return -EINVAL;
@ -1114,10 +1121,10 @@ static int nvs_startup(FAR struct nvs_fs *fs)
* a closed block, this is where NVS can write. * a closed block, this is where NVS can write.
*/ */
for (i = 0; i < fs->geo.neraseblocks; i++) for (i = 0; i < fs->nblocks; i++)
{ {
addr = (i << ADDR_BLOCK_SHIFT) + addr = (i << ADDR_BLOCK_SHIFT) +
(uint16_t)(fs->geo.erasesize - sizeof(struct nvs_ate)); (uint16_t)(fs->blocksize - sizeof(struct nvs_ate));
rc = nvs_flash_cmp_const(fs, addr, fs->erasestate, rc = nvs_flash_cmp_const(fs, addr, fs->erasestate,
sizeof(struct nvs_ate)); sizeof(struct nvs_ate));
fwarn("rc=%d\n", rc); fwarn("rc=%d\n", rc);
@ -1143,12 +1150,12 @@ static int nvs_startup(FAR struct nvs_fs *fs)
/* All blocks are closed, this is not a nvs fs */ /* All blocks are closed, this is not a nvs fs */
if (closed_blocks == fs->geo.neraseblocks) if (closed_blocks == fs->nblocks)
{ {
return -EDEADLK; return -EDEADLK;
} }
if (i == fs->geo.neraseblocks) if (i == fs->nblocks)
{ {
/* None of the blocks where closed, in most cases we can set /* None of the blocks where closed, in most cases we can set
* the address to the first block, except when there are only * the address to the first block, except when there are only
@ -1224,7 +1231,7 @@ static int nvs_startup(FAR struct nvs_fs *fs)
addr = fs->ate_wra & ADDR_BLOCK_MASK; addr = fs->ate_wra & ADDR_BLOCK_MASK;
nvs_block_advance(fs, &addr); nvs_block_advance(fs, &addr);
rc = nvs_flash_cmp_const(fs, addr, fs->erasestate, fs->geo.erasesize); rc = nvs_flash_cmp_const(fs, addr, fs->erasestate, fs->blocksize);
if (rc < 0) if (rc < 0)
{ {
return rc; return rc;
@ -1241,7 +1248,7 @@ static int nvs_startup(FAR struct nvs_fs *fs)
addr = fs->ate_wra + sizeof(struct nvs_ate); addr = fs->ate_wra + sizeof(struct nvs_ate);
while ((addr & ADDR_OFFS_MASK) < while ((addr & ADDR_OFFS_MASK) <
(fs->geo.erasesize - sizeof(struct nvs_ate))) (fs->blocksize - sizeof(struct nvs_ate)))
{ {
rc = nvs_flash_ate_rd(fs, addr, &gc_done_ate); rc = nvs_flash_ate_rd(fs, addr, &gc_done_ate);
if (rc) if (rc)
@ -1279,7 +1286,7 @@ static int nvs_startup(FAR struct nvs_fs *fs)
} }
fs->ate_wra &= ADDR_BLOCK_MASK; fs->ate_wra &= ADDR_BLOCK_MASK;
fs->ate_wra += (fs->geo.erasesize - 2 * sizeof(struct nvs_ate)); fs->ate_wra += (fs->blocksize - 2 * sizeof(struct nvs_ate));
fs->data_wra = (fs->ate_wra & ADDR_BLOCK_MASK); fs->data_wra = (fs->ate_wra & ADDR_BLOCK_MASK);
finfo("GC when data_wra=0x%" PRIx32 "\n", fs->data_wra); finfo("GC when data_wra=0x%" PRIx32 "\n", fs->data_wra);
rc = nvs_gc(fs); rc = nvs_gc(fs);
@ -1313,7 +1320,7 @@ static int nvs_startup(FAR struct nvs_fs *fs)
* valid data (this also avoids closing a block without any data). * valid data (this also avoids closing a block without any data).
*/ */
if (((fs->ate_wra + 2 * sizeof(struct nvs_ate)) == fs->geo.erasesize) && if (((fs->ate_wra + 2 * sizeof(struct nvs_ate)) == fs->blocksize) &&
(fs->data_wra != (fs->ate_wra & ADDR_BLOCK_MASK))) (fs->data_wra != (fs->ate_wra & ADDR_BLOCK_MASK)))
{ {
rc = nvs_flash_erase_block(fs, fs->ate_wra); rc = nvs_flash_erase_block(fs, fs->ate_wra);
@ -1411,13 +1418,13 @@ end:
*/ */
if ((!rc) && ((fs->ate_wra & ADDR_OFFS_MASK) == if ((!rc) && ((fs->ate_wra & ADDR_OFFS_MASK) ==
(fs->geo.erasesize - 2 * sizeof(struct nvs_ate)))) (fs->blocksize - 2 * sizeof(struct nvs_ate))))
{ {
rc = nvs_add_gc_done_ate(fs); rc = nvs_add_gc_done_ate(fs);
} }
finfo("%" PRIu32 " Eraseblocks of %" PRIu32 " bytes\n", finfo("%" PRIu32 " Eraseblocks of %" PRIu32 " bytes\n",
fs->geo.neraseblocks, fs->geo.erasesize); fs->nblocks, fs->blocksize);
finfo("alloc wra: %" PRIu32 ", 0x%" PRIx32 "\n", finfo("alloc wra: %" PRIu32 ", 0x%" PRIx32 "\n",
(fs->ate_wra >> ADDR_BLOCK_SHIFT), (fs->ate_wra & ADDR_OFFS_MASK)); (fs->ate_wra >> ADDR_BLOCK_SHIFT), (fs->ate_wra & ADDR_OFFS_MASK));
finfo("data wra: %" PRIu32 ", 0x%" PRIx32 "\n", finfo("data wra: %" PRIu32 ", 0x%" PRIx32 "\n",
@ -1581,7 +1588,7 @@ static ssize_t nvs_write(FAR struct nvs_fs *fs,
finfo("key_size=%zu, len=%zu, data_size = %zu\n", key_size, finfo("key_size=%zu, len=%zu, data_size = %zu\n", key_size,
pdata->len, data_size); pdata->len, data_size);
if ((data_size > (fs->geo.erasesize - 3 * sizeof(struct nvs_ate))) || if ((data_size > (fs->blocksize - 3 * sizeof(struct nvs_ate))) ||
((pdata->len > 0) && (pdata->configdata == NULL))) ((pdata->len > 0) && (pdata->configdata == NULL)))
{ {
return -EINVAL; return -EINVAL;
@ -1696,7 +1703,7 @@ static ssize_t nvs_write(FAR struct nvs_fs *fs,
block_to_write_befor_gc = fs->ate_wra >> ADDR_BLOCK_SHIFT; block_to_write_befor_gc = fs->ate_wra >> ADDR_BLOCK_SHIFT;
while (1) while (1)
{ {
if (gc_count == fs->geo.neraseblocks) if (gc_count == fs->nblocks)
{ {
/* Gc'ed all blocks, no extra space will be created /* Gc'ed all blocks, no extra space will be created
* by extra gc. * by extra gc.
@ -1716,10 +1723,10 @@ static ssize_t nvs_write(FAR struct nvs_fs *fs,
/* If gc touched second latest ate, search for it again */ /* If gc touched second latest ate, search for it again */
if (gc_count >= fs->geo.neraseblocks - 1 - if (gc_count >= fs->nblocks - 1 -
(block_to_write_befor_gc + fs->geo.neraseblocks - (block_to_write_befor_gc + fs->nblocks -
(hist_addr >> ADDR_BLOCK_SHIFT)) (hist_addr >> ADDR_BLOCK_SHIFT))
% fs->geo.neraseblocks) % fs->nblocks)
{ {
rc = nvs_read_entry(fs, key, key_size, NULL, 0, rc = nvs_read_entry(fs, key, key_size, NULL, 0,
&hist_addr); &hist_addr);