2
2
3
3
Zephyr Memory Storage (ZMS)
4
4
###########################
5
+
5
6
Zephyr Memory Storage is a new key-value storage system that is designed to work with all types
6
7
of non-volatile storage technologies. It supports classical on-chip NOR flash as well as new
7
8
technologies like RRAM and MRAM that do not require a separate erase operation at all, that is,
8
9
data on these types of devices can be overwritten directly at any time.
9
10
10
11
General behavior
11
12
****************
13
+
12
14
ZMS divides the memory space into sectors (minimum 2), and each sector is filled with key-value
13
15
pairs until it is full.
14
16
@@ -32,6 +34,7 @@ the first sector after garbage collecting it and erasing its content.
32
34
33
35
Composition of a sector
34
36
=======================
37
+
35
38
A sector is organized in this form (example with 3 sectors):
36
39
37
40
.. list-table ::
@@ -88,7 +91,7 @@ Definition of each element in the sector
88
91
``GC_done ATE `` is written to indicate that the next sector has already been garbage-collected.
89
92
This ATE could be at any position of the sector.
90
93
91
- ``ID ATE `` are entries that contain a 32-bit key and describe where the data is stored, its
94
+ ``ID ATE `` contains a key of type :c:type: ` zms_id_t ` and describes where the data is stored, its
92
95
size and its CRC32.
93
96
94
97
``Data `` is the actual value associated to the ID-ATE.
@@ -103,7 +106,7 @@ Mounting the storage system starts by getting the flash parameters, checking tha
103
106
properties are correct (sector_size, sector_count ...) then calling the zms_init function to
104
107
make the storage ready.
105
108
106
- To mount the filesystem the following elements in the `` zms_fs ` ` structure must be initialized:
109
+ To mount the filesystem the following elements in the :c:struct: ` zms_fs ` structure must be initialized:
107
110
108
111
.. code-block :: c
109
112
@@ -132,15 +135,14 @@ It must look for a closed sector followed by an open one, then within the open s
132
135
After that, it checks that the sector after this one is empty, or it will erase it.
133
136
134
137
ZMS ID/data write
135
- ===================
138
+ =================
136
139
137
140
To avoid rewriting the same data with the same ID again, ZMS must look in all the sectors if the
138
141
same ID exists and then compares its data. If the data is identical, no write is performed.
139
142
If it must perform a write, then an ATE and the data (if the operation is not a delete) are written
140
143
in the sector.
141
144
If the sector is full (cannot hold the current data + ATE), ZMS has to move to the next sector,
142
145
garbage collect the sector after the newly opened one then erase it.
143
- Data whose size is smaller or equal to 8 bytes are written within the ATE.
144
146
145
147
ZMS ID/data read (with history)
146
148
===============================
@@ -162,7 +164,7 @@ could slow down the calling thread.
162
164
The cycle counter
163
165
=================
164
166
165
- Each sector has a lead cycle counter which is a ``uin8_t `` that is used to validate all the other
167
+ Each sector has a lead cycle counter which is a ``uint8_t `` that is used to validate all the other
166
168
ATEs.
167
169
The lead cycle counter is stored in the empty ATE.
168
170
To become valid, an ATE must have the same cycle counter as the one stored in the empty ATE.
@@ -196,16 +198,52 @@ This will guarantee the application that the next write won't trigger the garbag
196
198
ATE (Allocation Table Entry) structure
197
199
======================================
198
200
199
- An entry has 16 bytes divided between these fields:
201
+ An entry uses 16 bytes to encode its information.
202
+ The exact structure is determined by ATE format which can be selected for a given application.
203
+
204
+ ZMS defines multiple ATE formats tailored for different feature sets. At runtime, it recognizes
205
+ the format using the metadata field in empty ATEs, which has the same byte position in all formats.
200
206
201
- See the :c:struct: `zms_ate ` structure.
207
+ .. table :: Entry format for 32-bit IDs
208
+
209
+ +-----+----------+--+--+--+--+--+--+--+--+---+---+---+---+---+---+
210
+ | 0 | 1 | 2| 3| 4| 5| 6| 7| 8| 9| 10| 11| 12| 13| 14| 15|
211
+ +=====+==========+==+==+==+==+==+==+==+==+===+===+===+===+===+===+
212
+ | | | | | data (if len <= 8) |
213
+ | | | | +-------------+---------------+
214
+ | crc8| cycle_cnt| len | id | | data_crc |
215
+ | | | | | offset +---------------+
216
+ | | | | | | metadata |
217
+ +-----+----------+-----+-----------+-------------+---------------+
218
+
219
+ This is the default format which is captured in the API documentation for :c:struct: `zms_ate `.
220
+ The ``data_crc `` is optionally included to integrity-check data stored at the top of the sector.
202
221
203
222
.. note :: The CRC of the data is checked only when a full read of the data is made.
204
223
The CRC of the data is not checked for a partial read, as it is computed for the whole element.
205
224
206
225
.. warning :: Enabling the CRC feature on previously existing ZMS content that did not have it
207
226
enabled will make all existing data invalid.
208
227
228
+ .. table :: Entry format for 64-bit IDs
229
+
230
+ +-----+----------+--+--+--+--+--+--+--+--+---+---+----+----+----+----+
231
+ | 0 | 1 | 2| 3| 4| 5| 6| 7| 8| 9| 10| 11| 12 | 13 | 14 | 15 |
232
+ +=====+==========+==+==+==+==+==+==+==+==+===+===+====+====+====+====+
233
+ | | | | | data (if len <= 4)|
234
+ | | | | +-------------------+
235
+ | crc8| cycle_cnt| len | id | offset |
236
+ | | | | +-------------------+
237
+ | | | | | metadata |
238
+ +-----+----------+-----+-------------------------+-------------------+
239
+
240
+ This format is selected when :kconfig:option: `CONFIG_ZMS_ID_64BIT ` is enabled.
241
+
242
+ .. warning :: Selecting a different ATE format than the one used by previously existing ZMS content
243
+ will make all existing data invalid.
244
+
245
+ .. note :: The ZMS backend for :ref:`Settings <settings_api>` does not support this format.
246
+
209
247
Available space for user data (key-value pairs)
210
248
***********************************************
211
249
@@ -220,8 +258,11 @@ The empty sector will rotate between the 4 sectors in the partition.
220
258
Small data values
221
259
=================
222
260
223
- Values smaller than or equal to 8 bytes will be stored within the entry (ATE) itself, without
261
+ Values which are sufficiently small will be stored within the entry (ATE) itself, without
224
262
writing data at the top of the sector.
263
+ The amount of data that can fit inside the entry depends on its selected format.
264
+ See the `ATE structure <#ate-allocation-table-entry-structure >`_ section.
265
+
225
266
ZMS has an entry size of 16 bytes which means that the maximum available space in a partition to
226
267
store data is computed in this scenario as:
227
268
@@ -239,24 +280,25 @@ Where:
239
280
240
281
``(5 * ATE_SIZE) ``: Reserved ATEs for header and delete items
241
282
242
- ``DATA_SIZE ``: Size of the small data values (range from 1 to 8)
283
+ ``DATA_SIZE ``: 8 bytes or 4 bytes depending on the ATE format
243
284
244
- For example for 4 sectors of 1024 bytes, free space for 8-byte length data is :math: `\frac {3 \times 944 \times 8 }{16 } = 1416 \, \text { bytes}`.
285
+ For example for 4 sectors of 1024 bytes, with the default ATE format, free space for 8-byte length
286
+ data is :math: `\frac {3 \times 944 \times 8 }{16 } = 1416 \, \text { bytes}`.
245
287
246
288
Large data values
247
289
=================
248
290
249
- Large data values ( > 8 bytes) are stored separately at the top of the sector.
291
+ Values exceeding `` DATA_SIZE `` are stored outside of the ATE at the top of the sector.
250
292
In this case, it is hard to estimate the free available space, as this depends on the size of
251
- the data. But we can take into account that for N bytes of data (N > 8 bytes) an additional
252
- 16 bytes of ATE must be added at the bottom of the sector.
293
+ the data. But we can take into account that for N bytes of data added at the top of the sector,
294
+ an additional 16 bytes of ATE must be added at the bottom of the sector, which adds up to
295
+ :math: `N + 16 ` bytes for the key-value pair.
253
296
254
297
Let's take an example:
255
298
256
299
For a partition that has 4 sectors of 1024 bytes and for data size of 64 bytes.
257
- Only 3 sectors are available for writes with a capacity of 944 bytes each.
258
- Each key-value pair needs an extra 16 bytes for the ATE, which makes it possible to store 11 pairs
259
- in each sector (:math: `\frac {944 }{80 }`).
300
+ Only 3 sectors are available for writes with a capacity of 944 bytes each,
301
+ which makes it possible to store 11 key-value pairs in each sector (:math: `\frac {944 }{64 + 16 }`).
260
302
Total data that could be stored in this partition for this case is :math: `11 \times 3 \times 64 = 2112 \text { bytes}`.
261
303
262
304
Wear leveling
@@ -292,7 +334,7 @@ memory cells cannot be overwritten), and for storage devices that do not require
292
334
operation, memory cells can be overwritten directly.
293
335
294
336
A typical scenario is shown here to calculate the life expectancy of a device:
295
- Let's suppose that we store an 8 -byte variable using the same ID but its content changes every
337
+ Let's suppose that we store a 4 -byte variable using the same ID but its content changes every
296
338
minute. The partition has 4 sectors with 1024 bytes each.
297
339
Each write of the variable requires 16 bytes of storage.
298
340
As we have 944 bytes available for ATEs for each sector, and because ZMS is a fast-forward
@@ -308,8 +350,8 @@ For storage devices that can be written 20 000 times, the storage will last abou
308
350
309
351
To make a more general formula we must first compute the effective used size in ZMS by our
310
352
typical set of data.
311
- For ID/data pairs with data <= 8 bytes , ``effective_size `` is 16 bytes.
312
- For ID/data pairs with data > 8 bytes , ``effective_size `` is ``16 + sizeof(data) `` bytes.
353
+ For ID/data pairs with ` small data <#small-data-values >`_ , ``effective_size `` is `` 16 `` bytes,
354
+ while for ` large data < #large-data-values >`_ , ``effective_size `` is ``16 + sizeof(data) `` bytes.
313
355
Let's suppose that ``total_effective_size `` is the total size of the data that is written in
314
356
the storage and that the partition is sized appropriately (double of the effective size) to avoid
315
357
having the garbage collector moving blocks all the time.
@@ -334,28 +376,32 @@ Where:
334
376
335
377
Features
336
378
********
379
+
337
380
ZMS has introduced many features compared to existing storage system like NVS and will evolve
338
381
from its initial version to include more features that satisfies new technologies requirements
339
382
such as low latency and bigger storage space.
340
383
341
384
Existing features
342
385
=================
386
+
343
387
Version 1
344
388
---------
389
+
345
390
- Supports storage devices that do not require an erase operation (only one write operation
346
391
to invalidate a sector)
347
392
- Supports large partition and sector sizes (64-bit address space)
348
- - Supports 32-bit IDs
349
- - Small-sized data (<= 8 bytes) are stored in the ATE itself
393
+ - Supports 32-bit IDs and 64-bit IDs
394
+ - Small data values are stored in the ATE itself
350
395
- Built-in data CRC32 (included in the ATE)
351
396
- Versioning of ZMS (to handle future evolutions)
352
397
- Supports large ``write-block-size `` (only for platforms that need it)
398
+ - Supports multiple ATE formats to satisfy the requirements of different applications
353
399
354
400
Future features
355
401
===============
356
402
357
- - Add multiple format ATE support to be able to use ZMS with different ATE formats that satisfies
358
- requirements from application
403
+ - Add the possibility to mount multiple filesystems with different ATE formats
404
+ (currently, all filesystems in the same application must use the same format)
359
405
- Add the possibility to skip garbage collector for some application usage where ID/value pairs
360
406
are written periodically and do not exceed half of the partition size (there is always an old
361
407
entry with the same ID).
@@ -369,6 +415,7 @@ Future features
369
415
370
416
ZMS and other storage systems in Zephyr
371
417
=======================================
418
+
372
419
This section describes ZMS in the wider context of storage systems in Zephyr (not full filesystems,
373
420
but simpler, non-hierarchical ones).
374
421
Today Zephyr includes at least two other systems that are somewhat comparable in scope and
@@ -386,8 +433,8 @@ and this section provides information to help make a choice.
386
433
ATEs and smaller header ATEs). Erasing flash in NVS is also very fast and do not require an
387
434
additional write operation compared to ZMS.
388
435
For these devices, NVS reads/writes will be faster as well than ZMS as it has smaller ATE size.
389
- - If your application needs more than 64K IDs for storage, :ref: `ZMS <zms_api >` is recommended here as it
390
- has a 32-bit ID field.
436
+ - If your application needs more than 64K IDs for storage, :ref: `ZMS <zms_api >` is recommended here
437
+ because the ID field is up to 64-bit .
391
438
- If your application is working in a FIFO mode (First-in First-out) then :ref: `FCB <fcb_api >` is
392
439
the best storage solution for this use case.
393
440
@@ -417,7 +464,7 @@ Sector size and count
417
464
- For some subsystems like :ref: `Settings <settings_api >`, all path-value pairs are split into two ZMS entries (ATEs).
418
465
The headers needed by the two entries should be accounted for when computing the needed storage
419
466
space.
420
- - Storing small data (<= 8 bytes) in ZMS entries can increase the performance, as this data is
467
+ - Using ` small data values < #small-data-values >`_ can increase the performance, as this data is
421
468
written within the entry.
422
469
For example, for the :ref: `Settings <settings_api >` subsystem, choosing a path name that is
423
470
less than or equal to 8 bytes can make reads and writes faster.
@@ -433,6 +480,14 @@ Cache size
433
480
divided into two ZMS entries. The recommendation for the cache size is to make it at least
434
481
twice the number of Settings entries.
435
482
483
+ ID size
484
+ =======
485
+
486
+ - The 64-bit ID space is expected to be larger than necessary for most applications.
487
+ Unless you have a particular need for this, it's recommended to stick with 32-bit IDs.
488
+ This is expected to have a slight impact on code size and performance, even on 64-bit systems,
489
+ because the byte position of IDs in storage is not aligned to an 8-byte boundary.
490
+
436
491
API Reference
437
492
*************
438
493
0 commit comments