Skip to content

Commit 9ab7231

Browse files
committed
nvs: support sector_size of 64KB
Allows NVS to work with flash device configured to use only 64KB block erase. Due to how addresses are encoded internally in NVS, 64KB is the maximum sector size. Add a test for this during mount. Add a native_sim unit test case for 64kb erase block size Signed-off-by: Mike J. Chen <mjchen@google.com>
1 parent e82cabb commit 9ab7231

File tree

6 files changed

+82
-10
lines changed

6 files changed

+82
-10
lines changed

include/zephyr/fs/nvs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ struct nvs_fs {
4848
/** Data write address */
4949
uint32_t data_wra;
5050
/** File system is split into sectors, each sector must be multiple of erase-block-size */
51-
uint16_t sector_size;
51+
uint32_t sector_size;
5252
/** Number of sectors in the file system */
5353
uint16_t sector_count;
5454
/** Flag indicating if the file system is initialized */

subsys/fs/nvs/nvs.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,13 @@ int nvs_mount(struct nvs_fs *fs)
10251025
return -EINVAL;
10261026
}
10271027

1028+
/* check that sector size is not greater than max */
1029+
if (fs->sector_size > NVS_MAX_SECTOR_SIZE) {
1030+
LOG_ERR("Sector size %u too large, maximum is %zu",
1031+
fs->sector_size, NVS_MAX_SECTOR_SIZE);
1032+
return -EINVAL;
1033+
}
1034+
10281035
/* check that sector size is a multiple of pagesize */
10291036
rc = flash_get_page_info_by_offs(fs->flash_device, fs->offset, &info);
10301037
if (rc) {

subsys/fs/nvs/nvs_priv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ extern "C" {
2121
#define ADDR_SECT_SHIFT 16
2222
#define ADDR_OFFS_MASK 0x0000FFFF
2323

24+
#define NVS_MAX_SECTOR_SIZE KB(64)
25+
2426
/*
2527
* Status return values
2628
*/
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright (c) 2025 Google LLC
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
&flash0 {
8+
erase-block-size = <0x10000>;
9+
10+
/*
11+
* Delete old partitions that were not aligned on 64kb addresses and
12+
* create new ones that are aligned.
13+
*/
14+
/delete-node/ partitions;
15+
partitions {
16+
compatible = "fixed-partitions";
17+
#address-cells = <1>;
18+
#size-cells = <1>;
19+
20+
boot_partition: partition@0 {
21+
label = "mcuboot";
22+
reg = <0x00000000 0x00010000>;
23+
};
24+
slot0_partition: partition@10000 {
25+
label = "image-0";
26+
reg = <0x00010000 0x00070000>;
27+
};
28+
slot1_partition: partition@80000 {
29+
label = "image-1";
30+
reg = <0x00080000 0x00070000>;
31+
};
32+
scratch_partition: partition@f0000 {
33+
label = "image-scratch";
34+
reg = <0x000f0000 0x00020000>;
35+
};
36+
storage_partition: partition@110000 {
37+
label = "storage";
38+
reg = <0x00110000 0x00050000>;
39+
};
40+
};
41+
};

tests/subsys/fs/nvs/src/main.c

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,14 @@ ZTEST_SUITE(nvs, NULL, setup, before, after, NULL);
9696
ZTEST_F(nvs, test_nvs_mount)
9797
{
9898
int err;
99+
size_t orig_sector_size = fixture->fs.sector_size;
99100

101+
fixture->fs.sector_size = KB(128);
102+
err = nvs_mount(&fixture->fs);
103+
zassert_true(err == -EINVAL,
104+
"nvs_mount did not return expected err for invalid sector_size");
105+
106+
fixture->fs.sector_size = orig_sector_size;
100107
err = nvs_mount(&fixture->fs);
101108
zassert_true(err == 0, "nvs_mount call failure: %d", err);
102109
}
@@ -307,7 +314,7 @@ static void write_content(uint16_t max_id, uint16_t begin, uint16_t end,
307314

308315
for (uint16_t i = begin; i < end; i++) {
309316
uint8_t id = (i % max_id);
310-
uint8_t id_data = id + max_id * (i / max_id);
317+
uint8_t id_data = id + max_id * ((i % 256) / max_id);
311318

312319
memset(buf, id_data, sizeof(buf));
313320

@@ -346,13 +353,25 @@ ZTEST_F(nvs, test_nvs_gc_3sectors)
346353

347354
const uint16_t max_id = 10;
348355
/* 50th write will trigger 1st GC. */
349-
const uint16_t max_writes = 51;
356+
uint16_t max_writes = 51;
350357
/* 75th write will trigger 2st GC. */
351-
const uint16_t max_writes_2 = 51 + 25;
358+
uint16_t max_writes_2 = 51 + 25;
352359
/* 100th write will trigger 3st GC. */
353-
const uint16_t max_writes_3 = 51 + 25 + 25;
360+
uint16_t max_writes_3 = 51 + 25 + 25;
354361
/* 125th write will trigger 4st GC. */
355-
const uint16_t max_writes_4 = 51 + 25 + 25 + 25;
362+
uint16_t max_writes_4 = 51 + 25 + 25 + 25;
363+
364+
if (fixture->fs.sector_size == KB(64)) {
365+
/* write 1637 will trigger 1st GC. */
366+
/* write 3274 will trigger 2nd GC. */
367+
max_writes = 3275;
368+
/* write 4911 will trigger 3rd GC. */
369+
max_writes_2 = 3275 + 1637;
370+
/* write 6548 will trigger 4th GC. */
371+
max_writes_3 = 3275 + 1637 + 1637;
372+
/* write 8185 will trigger 5th GC. */
373+
max_writes_4 = 3275 + 1637 + 1637 + 1637;
374+
}
356375

357376
fixture->fs.sector_count = 3;
358377

@@ -361,7 +380,7 @@ ZTEST_F(nvs, test_nvs_gc_3sectors)
361380
zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 0,
362381
"unexpected write sector");
363382

364-
/* Trigger 1st GC */
383+
/* Trigger 1st and 2nd GC */
365384
write_content(max_id, 0, max_writes, &fixture->fs);
366385

367386
/* sector sequence: empty,closed, write */
@@ -376,7 +395,7 @@ ZTEST_F(nvs, test_nvs_gc_3sectors)
376395
"unexpected write sector");
377396
check_content(max_id, &fixture->fs);
378397

379-
/* Trigger 2nd GC */
398+
/* Trigger 3rd GC */
380399
write_content(max_id, max_writes, max_writes_2, &fixture->fs);
381400

382401
/* sector sequence: write, empty, closed */
@@ -391,7 +410,7 @@ ZTEST_F(nvs, test_nvs_gc_3sectors)
391410
"unexpected write sector");
392411
check_content(max_id, &fixture->fs);
393412

394-
/* Trigger 3rd GC */
413+
/* Trigger 4th GC */
395414
write_content(max_id, max_writes_2, max_writes_3, &fixture->fs);
396415

397416
/* sector sequence: closed, write, empty */
@@ -406,7 +425,7 @@ ZTEST_F(nvs, test_nvs_gc_3sectors)
406425
"unexpected write sector");
407426
check_content(max_id, &fixture->fs);
408427

409-
/* Trigger 4th GC */
428+
/* Trigger 5th GC */
410429
write_content(max_id, max_writes_3, max_writes_4, &fixture->fs);
411430

412431
/* sector sequence: empty,closed, write */

tests/subsys/fs/nvs/testcase.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,6 @@ tests:
2828
- CONFIG_NVS_LOOKUP_CACHE=y
2929
- CONFIG_NVS_LOOKUP_CACHE_SIZE=64
3030
platform_allow: native_sim
31+
filesystem.nvs.64kb_erase_block:
32+
extra_args: DTC_OVERLAY_FILE=boards/native_sim_64kb_erase_block.overlay
33+
platform_allow: native_sim

0 commit comments

Comments
 (0)