Skip to content

Commit e7fb81e

Browse files
committed
[nrf fromtree] settings: ZMS: add a backend for ZMS (Zephyr Memory Storage)
This adds the initial backend support for the ZMS storage system. Signed-off-by: Riadh Ghaddab <[email protected]> (cherry picked from commit ef4e8dd)
1 parent 4e20baa commit e7fb81e

File tree

10 files changed

+793
-0
lines changed

10 files changed

+793
-0
lines changed

subsys/settings/Kconfig

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,21 @@ config SETTINGS_ENCODE_LEN
3232

3333
choice SETTINGS_BACKEND
3434
prompt "Storage back-end"
35+
default SETTINGS_ZMS if ZMS
3536
default SETTINGS_NVS if NVS
3637
default SETTINGS_FCB if FCB
3738
default SETTINGS_FILE if FILE_SYSTEM
3839
default SETTINGS_NONE
3940
help
4041
Storage back-end to be used by the settings subsystem.
4142

43+
config SETTINGS_ZMS
44+
bool "ZMS (Zephyr Memory Storage)"
45+
depends on ZMS
46+
select SYS_HASH_FUNC32
47+
help
48+
Use ZMS as settings storage backend.
49+
4250
config SETTINGS_FCB
4351
bool "FCB"
4452
depends on FCB
@@ -132,6 +140,37 @@ config SETTINGS_NVS_SECTOR_COUNT
132140
help
133141
Number of sectors used for the NVS settings area
134142

143+
config SETTINGS_ZMS_SECTOR_SIZE_MULT
144+
int "Sector size of the ZMS settings area"
145+
default 1
146+
depends on SETTINGS_ZMS
147+
help
148+
The sector size to use for the ZMS settings area as a multiple of
149+
FLASH_ERASE_BLOCK_SIZE.
150+
151+
config SETTINGS_ZMS_CUSTOM_SECTOR_COUNT
152+
bool "Customize the sector count of the ZMS settings partition"
153+
depends on SETTINGS_ZMS
154+
help
155+
The number of sectors used by default is the maximum value that can
156+
fit in the settings storage partition.
157+
Enabling this config allows to customize the number of used sectors.
158+
159+
config SETTINGS_ZMS_SECTOR_COUNT
160+
int "Sector count of the ZMS settings area"
161+
default 8
162+
depends on SETTINGS_ZMS && SETTINGS_ZMS_CUSTOM_SECTOR_COUNT
163+
help
164+
Number of sectors used for the ZMS settings area
165+
166+
config SETTINGS_ZMS_MAX_COLLISIONS_BITS
167+
int "number of bits reserved to handle collisions between hash numbers"
168+
default 4
169+
depends on SETTINGS_ZMS
170+
help
171+
The maximum number of hash collisions needs to be well sized depending
172+
on the data that is going to be stored in ZMS and its hash values
173+
135174
config SETTINGS_SHELL
136175
bool "Settings shell"
137176
depends on SHELL
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/* Copyright (c) 2024 BayLibre SAS
2+
*
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#ifndef __SETTINGS_ZMS_H_
7+
#define __SETTINGS_ZMS_H_
8+
9+
#include <zephyr/fs/zms.h>
10+
#include <zephyr/settings/settings.h>
11+
12+
#ifdef __cplusplus
13+
extern "C" {
14+
#endif
15+
16+
/* In the ZMS backend, each setting is stored in two ZMS entries:
17+
* 1. setting's name
18+
* 2. setting's value
19+
*
20+
* The ZMS entry ID for the setting's value is determined implicitly based on
21+
* the ID of the ZMS entry for the setting's name, once that is found. The
22+
* difference between name and value ID is constant and equal to
23+
* ZMS_NAME_ID_OFFSET.
24+
*
25+
* Setting's name is hashed into 29 bits minus hash_collisions_bits.
26+
* The 2 MSB_bits have always the same value 10, the LL_bit for the name's hash is 0
27+
* and the hash_collisions_bits is configurable through CONFIG_SETTINGS_ZMS_MAX_COLLISIONS_BITS.
28+
* The resulted 32 bits is the ZMS_ID of the Setting's name.
29+
* If we detect a collision between ZMS_IDs we increment the value within hash_collision_bits
30+
* until we find a free ZMS_ID.
31+
* Separately, we store a linked list using the Setting's name ZMS_ID but setting the lsb to 1.
32+
*
33+
* The linked list is used to maintain a relation between all ZMS_IDs. This is necessary to load
34+
* all settings at initialization.
35+
* The linked list contains at least a header followed by multiple linked list elements that
36+
* we can refer to as LL_x (where x is the order of that element in that list).
37+
* This is a representation of the Linked List that is stored in the storage.
38+
* LL_header <--> LL_0 <--> LL_1 <--> LL_2.
39+
* The "next_hash" pointer of each LL element refers to the next element in the linked list.
40+
* The "previous_hash" pointer is referring the previous element in the linked list.
41+
*
42+
* The bit representation of the 32 bits ZMS_ID is the following:
43+
* --------------------------------------------------------------
44+
* | MSB_bits | hash (truncated) | hash_collision_bits | LL_bit |
45+
* --------------------------------------------------------------
46+
* Where:
47+
* MSB_bits (2 bits width) : = 10 for Name IDs
48+
* = 11 for Data IDs
49+
* hash (29 bits - hash_collision_bits) : truncated hash obtained from sys_hash32
50+
* hash_collision_bits (configurable width) : used to handle hash collisions
51+
* LL_bit : = 0 when this is a name's ZMS_ID
52+
* = 1 when this is the linked list ZMS_ID corresponding to the name
53+
*
54+
* if a settings element is deleted it won't be found.
55+
*/
56+
57+
#define ZMS_LL_HEAD_HASH_ID 0x80000000
58+
#define ZMS_DATA_ID_OFFSET 0x40000000
59+
#define ZMS_HASH_MASK GENMASK(29, CONFIG_SETTINGS_ZMS_MAX_COLLISIONS_BITS + 1)
60+
#define ZMS_COLLISIONS_MASK GENMASK(CONFIG_SETTINGS_ZMS_MAX_COLLISIONS_BITS, 1)
61+
#define ZMS_HASH_TOTAL_MASK GENMASK(29, 1)
62+
#define ZMS_MAX_COLLISIONS (BIT(CONFIG_SETTINGS_ZMS_MAX_COLLISIONS_BITS) - 1)
63+
#define ZMS_HEADER_HASH 0x80000000
64+
65+
/* some useful macros */
66+
#define ZMS_NAME_HASH_ID(x) (x & ZMS_HASH_TOTAL_MASK)
67+
#define ZMS_UPDATE_COLLISION_NUM(x, y) \
68+
((x & ~ZMS_COLLISIONS_MASK) | ((y << 1) & ZMS_COLLISIONS_MASK))
69+
#define ZMS_COLLISION_NUM(x) ((x & ZMS_COLLISIONS_MASK) >> 1)
70+
71+
struct settings_zms {
72+
struct settings_store cf_store;
73+
struct zms_fs cf_zms;
74+
const struct device *flash_dev;
75+
uint32_t last_hash_id;
76+
uint32_t second_to_last_hash_id;
77+
uint8_t hash_collision_num;
78+
};
79+
80+
struct settings_hash_linked_list {
81+
uint32_t previous_hash;
82+
uint32_t next_hash;
83+
};
84+
85+
#ifdef __cplusplus
86+
}
87+
#endif
88+
89+
#endif /* __SETTINGS_ZMS_H_ */

subsys/settings/src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ zephyr_sources_ifdef(CONFIG_SETTINGS_FCB settings_fcb.c)
1313
zephyr_sources_ifdef(CONFIG_SETTINGS_NVS settings_nvs.c)
1414
zephyr_sources_ifdef(CONFIG_SETTINGS_NONE settings_none.c)
1515
zephyr_sources_ifdef(CONFIG_SETTINGS_SHELL settings_shell.c)
16+
zephyr_sources_ifdef(CONFIG_SETTINGS_ZMS settings_zms.c)

0 commit comments

Comments
 (0)