Skip to content

Commit 4734e23

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 4734e23

File tree

6 files changed

+87
-10
lines changed

6 files changed

+87
-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 %u",
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: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ static void *setup(void)
5454
fixture.fs.sector_count = TEST_SECTOR_COUNT;
5555
fixture.fs.flash_device = flash_area_get_device(fa);
5656

57+
TC_PRINT("fs.offset = %u (0x%x), fs.sector_size = %u (0x%x), fs.sector_count = %u\n",
58+
fixture.fs.offset, fixture.fs.offset,
59+
fixture.fs.sector_size, fixture.fs.sector_size,
60+
fixture.fs.sector_count);
61+
5762
return &fixture;
5863
}
5964

@@ -96,7 +101,14 @@ ZTEST_SUITE(nvs, NULL, setup, before, after, NULL);
96101
ZTEST_F(nvs, test_nvs_mount)
97102
{
98103
int err;
104+
size_t orig_sector_size = fixture->fs.sector_size;
105+
106+
fixture->fs.sector_size = KB(128);
107+
err = nvs_mount(&fixture->fs);
108+
zassert_true(err == -EINVAL,
109+
"nvs_mount did not return expected err for invalid sector_size");
99110

111+
fixture->fs.sector_size = orig_sector_size;
100112
err = nvs_mount(&fixture->fs);
101113
zassert_true(err == 0, "nvs_mount call failure: %d", err);
102114
}
@@ -307,7 +319,7 @@ static void write_content(uint16_t max_id, uint16_t begin, uint16_t end,
307319

308320
for (uint16_t i = begin; i < end; i++) {
309321
uint8_t id = (i % max_id);
310-
uint8_t id_data = id + max_id * (i / max_id);
322+
uint8_t id_data = id + max_id * ((i % 256) / max_id);
311323

312324
memset(buf, id_data, sizeof(buf));
313325

@@ -346,13 +358,25 @@ ZTEST_F(nvs, test_nvs_gc_3sectors)
346358

347359
const uint16_t max_id = 10;
348360
/* 50th write will trigger 1st GC. */
349-
const uint16_t max_writes = 51;
361+
uint16_t max_writes = 51;
350362
/* 75th write will trigger 2st GC. */
351-
const uint16_t max_writes_2 = 51 + 25;
363+
uint16_t max_writes_2 = 51 + 25;
352364
/* 100th write will trigger 3st GC. */
353-
const uint16_t max_writes_3 = 51 + 25 + 25;
365+
uint16_t max_writes_3 = 51 + 25 + 25;
354366
/* 125th write will trigger 4st GC. */
355-
const uint16_t max_writes_4 = 51 + 25 + 25 + 25;
367+
uint16_t max_writes_4 = 51 + 25 + 25 + 25;
368+
369+
if (fixture->fs.sector_size == KB(64)) {
370+
/* write 1637 will trigger 1st GC. */
371+
/* write 3274 will trigger 2nd GC. */
372+
max_writes = 3275;
373+
/* write 4911 will trigger 3rd GC. */
374+
max_writes_2 = 3275 + 1637;
375+
/* write 6548 will trigger 4th GC. */
376+
max_writes_3 = 3275 + 1637 + 1637;
377+
/* write 8185 will trigger 5th GC. */
378+
max_writes_4 = 3275 + 1637 + 1637 + 1637;
379+
}
356380

357381
fixture->fs.sector_count = 3;
358382

@@ -361,7 +385,7 @@ ZTEST_F(nvs, test_nvs_gc_3sectors)
361385
zassert_equal(fixture->fs.ate_wra >> ADDR_SECT_SHIFT, 0,
362386
"unexpected write sector");
363387

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

367391
/* sector sequence: empty,closed, write */
@@ -376,7 +400,7 @@ ZTEST_F(nvs, test_nvs_gc_3sectors)
376400
"unexpected write sector");
377401
check_content(max_id, &fixture->fs);
378402

379-
/* Trigger 2nd GC */
403+
/* Trigger 3rd GC */
380404
write_content(max_id, max_writes, max_writes_2, &fixture->fs);
381405

382406
/* sector sequence: write, empty, closed */
@@ -391,7 +415,7 @@ ZTEST_F(nvs, test_nvs_gc_3sectors)
391415
"unexpected write sector");
392416
check_content(max_id, &fixture->fs);
393417

394-
/* Trigger 3rd GC */
418+
/* Trigger 4th GC */
395419
write_content(max_id, max_writes_2, max_writes_3, &fixture->fs);
396420

397421
/* sector sequence: closed, write, empty */
@@ -406,7 +430,7 @@ ZTEST_F(nvs, test_nvs_gc_3sectors)
406430
"unexpected write sector");
407431
check_content(max_id, &fixture->fs);
408432

409-
/* Trigger 4th GC */
433+
/* Trigger 5th GC */
410434
write_content(max_id, max_writes_3, max_writes_4, &fixture->fs);
411435

412436
/* 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)