fs: fcb: add option to disable CRC for fcb entries

Add option to disable CRC for fcb entries. This improves the write
throughput significantly at the cost of not detecting corrupted data
in flash. This is beneficial for aplications that needs the extra
write throughput, where error detection is done elsewhere.

Allow the FCB entries in flash to have a valid CRC when CRC is
disabled in the FCB. This allows existing solutions to disable
CRC checking, while keeping the CRC areas intact. Note that this
is a one-way option.

Fixes #53707

Signed-off-by: Eivind Jølsgard <eivind.jolsgard@nordicsemi.no>
This commit is contained in:
Eivind Jølsgard 2023-01-05 10:26:15 +01:00 committed by Fabio Baltieri
commit cfa1ba1261
16 changed files with 204 additions and 49 deletions

View file

@ -1,6 +1,6 @@
# Flash Circular Buffer module
# Copyright (c) 2017 Nordic Semiconductor ASA
# Copyright (c) 2017-2023 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0
#
@ -13,3 +13,13 @@ config FCB
select CRC
help
Enable support of Flash Circular Buffer.
if FCB
config FCB_ALLOW_FIXED_ENDMARKER
bool "Allow FCB instances to have a fixed endmarker"
help
This allows the FCB instances to disable CRC checks in
favor of increased write throughput.
endif

View file

@ -121,18 +121,18 @@ int
fcb_append_finish(struct fcb *fcb, struct fcb_entry *loc)
{
int rc;
uint8_t crc8[fcb->f_align];
uint8_t em[fcb->f_align];
off_t off;
(void)memset(crc8, 0xFF, sizeof(crc8));
(void)memset(em, 0xFF, sizeof(em));
rc = fcb_elem_crc8(fcb, loc, &crc8[0]);
rc = fcb_elem_endmarker(fcb, loc, &em[0]);
if (rc) {
return rc;
}
off = loc->fe_data_off + fcb_len_in_flash(fcb, loc->fe_data_len);
rc = fcb_flash_write(fcb, loc->fe_sector, off, crc8, fcb->f_align);
rc = fcb_flash_write(fcb, loc->fe_sector, off, em, fcb->f_align);
if (rc) {
return -EIO;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017 Nordic Semiconductor ASA
* Copyright (c) 2017-2023 Nordic Semiconductor ASA
* Copyright (c) 2015 Runtime Inc
*
* SPDX-License-Identifier: Apache-2.0
@ -10,12 +10,14 @@
#include <zephyr/fs/fcb.h>
#include "fcb_priv.h"
#define FCB_FIXED_ENDMARKER 0xab
/*
* Given offset in flash sector, fill in rest of the fcb_entry, and crc8 over
* the data.
*/
int
fcb_elem_crc8(struct fcb *fcb, struct fcb_entry *loc, uint8_t *c8p)
static int
fcb_elem_crc8(struct fcb *_fcb, struct fcb_entry *loc, uint8_t *c8p)
{
uint8_t tmp_str[FCB_TMP_BUF_SZ];
int cnt;
@ -29,16 +31,17 @@ fcb_elem_crc8(struct fcb *fcb, struct fcb_entry *loc, uint8_t *c8p)
if (loc->fe_elem_off + 2 > loc->fe_sector->fs_size) {
return -ENOTSUP;
}
rc = fcb_flash_read(fcb, loc->fe_sector, loc->fe_elem_off, tmp_str, 2);
rc = fcb_flash_read(_fcb, loc->fe_sector, loc->fe_elem_off, tmp_str, 2);
if (rc) {
return -EIO;
}
cnt = fcb_get_len(fcb, tmp_str, &len);
cnt = fcb_get_len(_fcb, tmp_str, &len);
if (cnt < 0) {
return cnt;
}
loc->fe_data_off = loc->fe_elem_off + fcb_len_in_flash(fcb, cnt);
loc->fe_data_off = loc->fe_elem_off + fcb_len_in_flash(_fcb, cnt);
loc->fe_data_len = len;
crc8 = CRC8_CCITT_INITIAL_VALUE;
@ -52,7 +55,7 @@ fcb_elem_crc8(struct fcb *fcb, struct fcb_entry *loc, uint8_t *c8p)
blk_sz = sizeof(tmp_str);
}
rc = fcb_flash_read(fcb, loc->fe_sector, off, tmp_str, blk_sz);
rc = fcb_flash_read(_fcb, loc->fe_sector, off, tmp_str, blk_sz);
if (rc) {
return -EIO;
}
@ -63,25 +66,83 @@ fcb_elem_crc8(struct fcb *fcb, struct fcb_entry *loc, uint8_t *c8p)
return 0;
}
int fcb_elem_info(struct fcb *fcb, struct fcb_entry *loc)
#if IS_ENABLED(CONFIG_FCB_ALLOW_FIXED_ENDMARKER)
/* Given the offset in flash sector, calculate the FCB entry data offset and size, and set
* the fixed endmarker.
*/
static int
fcb_elem_endmarker_fixed(struct fcb *_fcb, struct fcb_entry *loc, uint8_t *em)
{
uint8_t tmp_str[2];
int cnt;
uint16_t len;
int rc;
uint8_t crc8;
uint8_t fl_crc8;
off_t off;
rc = fcb_elem_crc8(fcb, loc, &crc8);
if (rc) {
return rc;
if (loc->fe_elem_off + 2 > loc->fe_sector->fs_size) {
return -ENOTSUP;
}
off = loc->fe_data_off + fcb_len_in_flash(fcb, loc->fe_data_len);
rc = fcb_flash_read(fcb, loc->fe_sector, off, &fl_crc8, sizeof(fl_crc8));
rc = fcb_flash_read(_fcb, loc->fe_sector, loc->fe_elem_off, tmp_str, 2);
if (rc) {
return -EIO;
}
if (fl_crc8 != crc8) {
cnt = fcb_get_len(_fcb, tmp_str, &len);
if (cnt < 0) {
return cnt;
}
loc->fe_data_off = loc->fe_elem_off + fcb_len_in_flash(_fcb, cnt);
loc->fe_data_len = len;
*em = FCB_FIXED_ENDMARKER;
return 0;
}
#endif /* IS_ENABLED(CONFIG_FCB_ALLOW_FIXED_ENDMARKER) */
/* Given the offset in flash sector, calculate the FCB entry data offset and size, and calculate
* the expected endmarker.
*/
int
fcb_elem_endmarker(struct fcb *_fcb, struct fcb_entry *loc, uint8_t *em)
{
#if IS_ENABLED(CONFIG_FCB_ALLOW_FIXED_ENDMARKER)
if (_fcb->f_flags & FCB_FLAGS_CRC_DISABLED) {
return fcb_elem_endmarker_fixed(_fcb, loc, em);
}
#endif /* IS_ENABLED(CONFIG_FCB_ALLOW_FIXED_ENDMARKER) */
return fcb_elem_crc8(_fcb, loc, em);
}
/* Given the offset in flash sector, calculate the FCB entry data offset and size, and verify that
* the FCB entry endmarker is correct.
*/
int fcb_elem_info(struct fcb *_fcb, struct fcb_entry *loc)
{
int rc;
uint8_t em;
uint8_t fl_em;
off_t off;
rc = fcb_elem_endmarker(_fcb, loc, &em);
if (rc) {
return rc;
}
off = loc->fe_data_off + fcb_len_in_flash(_fcb, loc->fe_data_len);
rc = fcb_flash_read(_fcb, loc->fe_sector, off, &fl_em, sizeof(fl_em));
if (rc) {
return -EIO;
}
if (IS_ENABLED(CONFIG_FCB_ALLOW_FIXED_ENDMARKER) && (fl_em != em)) {
rc = fcb_elem_crc8(_fcb, loc, &em);
if (rc) {
return rc;
}
}
if (fl_em != em) {
return -EBADMSG;
}
return 0;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2020 Nordic Semiconductor ASA
* Copyright (c) 2017-2023 Nordic Semiconductor ASA
* Copyright (c) 2015 Runtime Inc
*
* SPDX-License-Identifier: Apache-2.0
@ -70,7 +70,7 @@ struct flash_sector *fcb_getnext_sector(struct fcb *fcb,
int fcb_getnext_nolock(struct fcb *fcb, struct fcb_entry *loc);
int fcb_elem_info(struct fcb *fcb, struct fcb_entry *loc);
int fcb_elem_crc8(struct fcb *fcb, struct fcb_entry *loc, uint8_t *crc8p);
int fcb_elem_endmarker(struct fcb *fcb, struct fcb_entry *loc, uint8_t *crc8p);
int fcb_sector_hdr_init(struct fcb *fcb, struct flash_sector *sector, uint16_t id);
int fcb_sector_hdr_read(struct fcb *fcb, struct flash_sector *sector,