mtd_config/nvs: add data crc8

The purpose is to reduce the conflict rate of ate CRC and
verify the data

Signed-off-by: zhaoxingyu1 <zhaoxingyu1@xiaomi.com>
This commit is contained in:
zhaoxingyu1
2025-07-13 17:44:14 +08:00
committed by Xiang Xiao
parent 59f05be525
commit 2e4ce22774
+21 -4
View File
@@ -95,7 +95,7 @@ begin_packed_struct struct nvs_ate
uint16_t offset; /* Data offset within block */ uint16_t offset; /* Data offset within block */
uint16_t len; /* Data len within block */ uint16_t len; /* Data len within block */
uint16_t key_len; /* Key string len */ uint16_t key_len; /* Key string len */
uint8_t part; /* Part of a multipart data - future extension */ uint8_t data_crc8; /* Crc8 check of the data */
uint8_t crc8; /* Crc8 check of the ate entry */ uint8_t crc8; /* Crc8 check of the ate entry */
uint8_t expired[0]; uint8_t expired[0];
} end_packed_struct; } end_packed_struct;
@@ -670,13 +670,15 @@ static void nvs_ate_crc8_update(FAR struct nvs_ate *entry)
* *
****************************************************************************/ ****************************************************************************/
static bool nvs_ate_crc8_check(FAR const struct nvs_ate *entry) static bool nvs_ate_crc8_check(FAR struct nvs_fs *fs,
FAR const struct nvs_ate *entry)
{ {
uint8_t ate_crc; uint8_t ate_crc;
ate_crc = crc8part((FAR const uint8_t *)entry, ate_crc = crc8part((FAR const uint8_t *)entry,
offsetof(struct nvs_ate, crc8), 0xff); offsetof(struct nvs_ate, crc8), 0xff);
return ate_crc == entry->crc8; return ate_crc == entry->crc8 && (entry->len > 0 ||
entry->data_crc8 == 0 || entry->data_crc8 == fs->erasestate);
} }
/**************************************************************************** /****************************************************************************
@@ -716,7 +718,7 @@ static int nvs_ate_cmp_const(FAR const struct nvs_ate *entry,
static bool nvs_ate_valid(FAR struct nvs_fs *fs, static bool nvs_ate_valid(FAR struct nvs_fs *fs,
FAR const struct nvs_ate *entry) FAR const struct nvs_ate *entry)
{ {
return nvs_ate_crc8_check(entry) && return nvs_ate_crc8_check(fs, entry) &&
entry->offset < (fs->blocksize - nvs_ate_size(fs)) && entry->offset < (fs->blocksize - nvs_ate_size(fs)) &&
(entry->key_len > 0 || entry->id == nvs_special_ate_id(fs)); (entry->key_len > 0 || entry->id == nvs_special_ate_id(fs));
} }
@@ -807,6 +809,7 @@ static int nvs_flash_wrt_entry(FAR struct nvs_fs *fs, uint32_t id,
entry->offset = fs->data_wra & NVS_ADDR_OFFS_MASK; entry->offset = fs->data_wra & NVS_ADDR_OFFS_MASK;
entry->len = len; entry->len = len;
entry->key_len = key_size; entry->key_len = key_size;
entry->data_crc8 = crc8(data, len);
nvs_ate_crc8_update(entry); nvs_ate_crc8_update(entry);
@@ -1654,6 +1657,7 @@ static ssize_t nvs_read_entry(FAR struct nvs_fs *fs, FAR const uint8_t *key,
uint32_t rd_addr; uint32_t rd_addr;
uint32_t hist_addr; uint32_t hist_addr;
uint32_t hash_id; uint32_t hash_id;
uint8_t data_crc8;
bool hit = true; bool hit = true;
int rc; int rc;
@@ -1732,6 +1736,19 @@ static ssize_t nvs_read_entry(FAR struct nvs_fs *fs, FAR const uint8_t *key,
ferr("Data read failed, rc=%d\n", rc); ferr("Data read failed, rc=%d\n", rc);
return rc; return rc;
} }
if (len >= wlk_ate->len && wlk_ate->data_crc8 != fs->erasestate)
{
/* Do not compute CRC for partial reads as CRC won't match */
data_crc8 = crc8(data, wlk_ate->len);
if (wlk_ate->data_crc8 != data_crc8)
{
ferr("Invalid data crc: %" PRIx8 ", wlk_ate->data_crc8: "
"%" PRIx8 "\n", data_crc8, wlk_ate->data_crc8);
return -EIO;
}
}
} }
if (ate_addr) if (ate_addr)