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---
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
comment "MTD Device Drivers"

View file

@ -93,7 +93,8 @@
struct nvs_fs
{
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 */
uint32_t ate_wra; /* Next alloc table entry
* Write address
@ -203,7 +204,7 @@ static int nvs_flash_wrt(FAR struct nvs_fs *fs, uint32_t addr,
off_t offset;
int ret;
offset = fs->geo.erasesize * (addr >> ADDR_BLOCK_SHIFT);
offset = fs->blocksize * (addr >> ADDR_BLOCK_SHIFT);
offset += addr & ADDR_OFFS_MASK;
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;
int ret;
offset = fs->geo.erasesize * (addr >> ADDR_BLOCK_SHIFT);
offset = fs->blocksize * (addr >> ADDR_BLOCK_SHIFT);
offset += addr & ADDR_OFFS_MASK;
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;
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)
{
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)
{
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;
}
@ -579,7 +582,7 @@ static int nvs_close_ate_valid(FAR struct nvs_fs *fs,
return 0;
}
if ((fs->geo.erasesize - entry->offset) % sizeof(struct nvs_ate))
if ((fs->blocksize - entry->offset) % sizeof(struct nvs_ate))
{
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);
if (((*addr) & ADDR_OFFS_MASK) !=
(fs->geo.erasesize - sizeof(struct nvs_ate)))
(fs->blocksize - sizeof(struct nvs_ate)))
{
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)
{
*addr += ((fs->geo.neraseblocks - 1) << ADDR_BLOCK_SHIFT);
*addr += ((fs->nblocks - 1) << ADDR_BLOCK_SHIFT);
}
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)
{
*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 &= 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);
@ -950,7 +953,7 @@ static int nvs_gc(FAR struct nvs_fs *fs)
sec_addr = (fs->ate_wra & ADDR_BLOCK_MASK);
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,
gc_addr);
@ -1068,8 +1071,9 @@ static int nvs_startup(FAR struct nvs_fs *fs)
uint32_t second_addr;
uint32_t last_addr;
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
* 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,
(unsigned long)((uintptr_t)&(fs->geo)));
(unsigned long)((uintptr_t)&(geo)));
if (rc < 0)
{
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;
}
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. */
if (fs->geo.neraseblocks < 2)
if (fs->nblocks < 2)
{
ferr("Configuration error - block count\n");
return -EINVAL;
@ -1114,10 +1121,10 @@ static int nvs_startup(FAR struct nvs_fs *fs)
* 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) +
(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,
sizeof(struct nvs_ate));
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 */
if (closed_blocks == fs->geo.neraseblocks)
if (closed_blocks == fs->nblocks)
{
return -EDEADLK;
}
if (i == fs->geo.neraseblocks)
if (i == fs->nblocks)
{
/* None of the blocks where closed, in most cases we can set
* 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;
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)
{
return rc;
@ -1241,7 +1248,7 @@ static int nvs_startup(FAR struct nvs_fs *fs)
addr = fs->ate_wra + sizeof(struct nvs_ate);
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);
if (rc)
@ -1279,7 +1286,7 @@ static int nvs_startup(FAR struct nvs_fs *fs)
}
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);
finfo("GC when data_wra=0x%" PRIx32 "\n", fs->data_wra);
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).
*/
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)))
{
rc = nvs_flash_erase_block(fs, fs->ate_wra);
@ -1411,13 +1418,13 @@ end:
*/
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);
}
finfo("%" PRIu32 " Eraseblocks of %" PRIu32 " bytes\n",
fs->geo.neraseblocks, fs->geo.erasesize);
fs->nblocks, fs->blocksize);
finfo("alloc wra: %" PRIu32 ", 0x%" PRIx32 "\n",
(fs->ate_wra >> ADDR_BLOCK_SHIFT), (fs->ate_wra & ADDR_OFFS_MASK));
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,
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)))
{
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;
while (1)
{
if (gc_count == fs->geo.neraseblocks)
if (gc_count == fs->nblocks)
{
/* Gc'ed all blocks, no extra space will be created
* 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_count >= fs->geo.neraseblocks - 1 -
(block_to_write_befor_gc + fs->geo.neraseblocks -
if (gc_count >= fs->nblocks - 1 -
(block_to_write_befor_gc + fs->nblocks -
(hist_addr >> ADDR_BLOCK_SHIFT))
% fs->geo.neraseblocks)
% fs->nblocks)
{
rc = nvs_read_entry(fs, key, key_size, NULL, 0,
&hist_addr);