From cd80900646dbade1874973e757618d0ea07ca94b Mon Sep 17 00:00:00 2001 From: xucheng5 Date: Fri, 15 Dec 2023 17:59:39 +0800 Subject: [PATCH] mtd_config_fs : support algin size Signed-off-by: xucheng5 --- drivers/mtd/Kconfig | 7 ++++ drivers/mtd/mtd_config_fs.c | 65 +++++++++++++++++++++++++++++-------- 2 files changed, 59 insertions(+), 13 deletions(-) diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 5d75e849729..5b16be665a0 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -195,6 +195,13 @@ config MTD_CONFIG_FAIL_SAFE This replaces the drivers/mtd/mtd_config, which is resilient to power loss. +config MTD_WRITE_ALIGN_SIZE + int "align size [1,2,4,8,16] for per write operation" + default 1 + depends on MTD_CONFIG_FAIL_SAFE + ---help--- + align size will be one of 1,2,4,8,16 + endif # MTD_CONFIG comment "MTD Device Drivers" diff --git a/drivers/mtd/mtd_config_fs.c b/drivers/mtd/mtd_config_fs.c index aac530ae15e..ad2d3ca2b02 100644 --- a/drivers/mtd/mtd_config_fs.c +++ b/drivers/mtd/mtd_config_fs.c @@ -81,6 +81,12 @@ #define NVS_SPECIAL_ATE_ID 0xffffffff +#ifdef CONFIG_MTD_WRITE_ALIGN_SIZE +#define NVS_ALIGN_SIZE CONFIG_MTD_WRITE_ALIGN_SIZE +#else +#define NVS_ALIGN_SIZE 4 +#endif + /**************************************************************************** * Private Types ****************************************************************************/ @@ -110,8 +116,11 @@ begin_packed_struct struct nvs_ate uint16_t key_len; /* Key string len */ uint8_t part; /* Part of a multipart data - future extension */ uint8_t crc8; /* Crc8 check of the ate entry */ +#if CONFIG_MTD_WRITE_ALIGN_SIZE > 4 + uint8_t padding[NVS_ALIGN_SIZE - 4]; /* padding for align */ +#endif uint8_t expired; /* 0xFF-newest entry, others-old entry */ - uint8_t reserved[3]; /* For future extension */ + uint8_t reserved[NVS_ALIGN_SIZE - 1]; } end_packed_struct; /**************************************************************************** @@ -154,6 +163,19 @@ static const struct file_operations g_mtdnvs_fops = * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: nvs_al_size + ****************************************************************************/ + +static inline size_t nvs_al_size(size_t len) +{ +#ifdef CONFIG_MTD_WRITE_ALIGN_SIZE + return (len + (NVS_ALIGN_SIZE - 1U)) & ~(NVS_ALIGN_SIZE - 1U); +#else + return len; +#endif +} + /**************************************************************************** * Name: nvs_fnv_hash ****************************************************************************/ @@ -591,6 +613,8 @@ static int nvs_flash_wrt_entry(FAR struct nvs_fs *fs, uint32_t id, { int rc; struct nvs_ate entry; + uint16_t total; + uint8_t *tmp; memset(&entry, fs->erasestate, sizeof(entry)); entry.id = id; @@ -602,17 +626,23 @@ static int nvs_flash_wrt_entry(FAR struct nvs_fs *fs, uint32_t id, /* Let's sew key and data into one, key comes first, then data */ - rc = nvs_flash_data_wrt(fs, key, key_size); - if (rc) + total = nvs_al_size(key_size + len); + tmp = kmm_malloc(total); + if (tmp == NULL) { - ferr("Write key failed, rc=%d\n", rc); - return rc; + ferr("malloc size %u failed\n", total); + return -ENOMEM; } - rc = nvs_flash_data_wrt(fs, data, len); + memcpy(tmp, key, key_size); + memcpy(tmp + key_size, data, len); + memset(tmp + key_size + len, fs->erasestate, total - key_size - len); + + rc = nvs_flash_data_wrt(fs, tmp, total); if (rc) { ferr("Write value failed, rc=%d\n", rc); + kmm_free(tmp); return rc; } @@ -620,9 +650,11 @@ static int nvs_flash_wrt_entry(FAR struct nvs_fs *fs, uint32_t id, if (rc) { ferr("Write ate failed, rc=%d\n", rc); + kmm_free(tmp); return rc; } + kmm_free(tmp); return 0; } @@ -666,10 +698,16 @@ static int nvs_recover_last_ate(FAR struct nvs_fs *fs, /* Found a valid ate, update data_end_addr and *addr */ data_end_addr &= ADDR_BLOCK_MASK; - data_end_addr += end_ate.offset + end_ate.key_len + end_ate.len; + data_end_addr += end_ate.offset + + nvs_al_size(end_ate.key_len + end_ate.len); *addr = ate_end_addr; } + if (ate_end_addr < sizeof(struct nvs_ate)) + { + break; + } + ate_end_addr -= sizeof(struct nvs_ate); } @@ -829,10 +867,11 @@ static int nvs_add_gc_done_ate(FAR struct nvs_fs *fs) static int nvs_expire_ate(FAR struct nvs_fs *fs, uint32_t addr) { - uint8_t expired = 0; + uint8_t expired[NVS_ALIGN_SIZE]; + memset(expired, ~fs->erasestate, sizeof(expired)); return nvs_flash_wrt(fs, addr + offsetof(struct nvs_ate, expired), - &expired, sizeof(expired)); + expired, sizeof(expired)); } /**************************************************************************** @@ -932,7 +971,7 @@ static int nvs_gc(FAR struct nvs_fs *fs) nvs_ate_crc8_update(&gc_ate); rc = nvs_flash_block_move(fs, data_addr, - gc_ate.key_len + gc_ate.len); + nvs_al_size(gc_ate.key_len + gc_ate.len)); if (rc) { return rc; @@ -1117,8 +1156,8 @@ static int nvs_startup(FAR struct nvs_fs *fs) /* Complete write of ate was performed */ fs->data_wra = addr & ADDR_BLOCK_MASK; - fs->data_wra += last_ate.offset + last_ate.key_len + - last_ate.len; + fs->data_wra += last_ate.offset + nvs_al_size(last_ate.key_len + + last_ate.len); finfo("recovered data_wra=0x%" PRIx32 "\n", fs->data_wra); } @@ -1482,7 +1521,7 @@ static ssize_t nvs_write(FAR struct nvs_fs *fs, /* Data now contains input data and input key, input key first. */ - data_size = key_size + pdata->len; + data_size = nvs_al_size(key_size + pdata->len); /* The maximum data size is block size - 3 ate * where: 1 ate for data, 1 ate for block close, 1 ate for gc done.