forked from nrfconnect/sdk-zephyr
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathzms.h
More file actions
331 lines (306 loc) · 11.2 KB
/
Copy pathzms.h
File metadata and controls
331 lines (306 loc) · 11.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
/* Copyright (c) 2018 Laczen
* Copyright (c) 2024 BayLibre SAS
*
* SPDX-License-Identifier: Apache-2.0
*
* ZMS: Zephyr Memory Storage
*/
#ifndef ZEPHYR_INCLUDE_KVSS_ZMS_H_
#define ZEPHYR_INCLUDE_KVSS_ZMS_H_
#include <sys/types.h>
#include <zephyr/drivers/flash.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/toolchain.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup zms Zephyr Memory Storage (ZMS)
* @ingroup file_system_storage
* @{
* @}
*/
/**
* @defgroup zms_data_structures ZMS data structures
* @ingroup zms
* @{
*/
/** Mount options for @ref zms_mount and @ref zms_mount_force. */
enum zms_mount_flags {
/**
* Do not format erased media during mount.
*
* When this flag is set and the backing flash area is erased (no valid ZMS
* header), mount fails instead of creating a new ZMS header.
*/
ZMS_MOUNT_FLAG_NO_FORMAT = BIT(0),
};
/** Zephyr Memory Storage file system structure */
struct zms_fs {
/** File system offset in flash */
off_t offset;
/** Allocation Table Entry (ATE) write address.
* Addresses are stored as `uint64_t`:
* - high 4 bytes correspond to the sector
* - low 4 bytes are the offset in the sector
*/
uint64_t ate_wra;
/** Data write address */
uint64_t data_wra;
/** Storage system is split into sectors. The sector size must be a multiple of
* `erase-block-size` if the device has erase capabilities
*/
uint32_t sector_size;
/** Number of sectors in the file system */
uint32_t sector_count;
/** Mount behavior flags from @ref zms_mount_flags */
uint32_t mount_flags;
/** Current cycle counter of the active sector (pointed to by `ate_wra`) */
uint8_t sector_cycle;
/** Flag indicating if the file system is initialized */
bool ready;
/** Mutex used to lock flash writes */
struct k_mutex zms_lock;
/** Flash device runtime structure */
const struct device *flash_device;
/** Flash memory parameters structure */
const struct flash_parameters *flash_parameters;
/** Size of an Allocation Table Entry */
size_t ate_size;
#if CONFIG_ZMS_LOOKUP_CACHE
/** Lookup table used to cache ATE addresses of written IDs */
uint64_t lookup_cache[CONFIG_ZMS_LOOKUP_CACHE_SIZE];
#endif
};
/**
* @}
*/
/**
* @defgroup zms_high_level_api ZMS API
* @ingroup zms
* @{
*/
/**
* @brief ID type used in the ZMS API.
*
* @note The width of this type depends on @kconfig{CONFIG_ZMS_ID_64BIT}.
*/
#if CONFIG_ZMS_ID_64BIT
typedef uint64_t zms_id_t;
#else
typedef uint32_t zms_id_t;
#endif
/**
* @brief Mount a ZMS file system onto the device specified in `fs`.
*
* @details If the flash area is erased and no valid ZMS header is found,
* mount will format the area and create a valid header by default.
* Set @ref ZMS_MOUNT_FLAG_NO_FORMAT in `fs->mount_flags` to disable this
* auto-format behavior and fail the mount instead.
*
* @param fs Pointer to the file system.
*
* @retval 0 on success.
* @retval -ENOTSUP if the detected file system is not ZMS.
* @retval -EPROTONOSUPPORT if the ZMS version is not supported.
* @retval -EINVAL if `fs` is NULL or any of the flash parameters or the sector layout is invalid.
* @retval -ENXIO if there is a device error.
* @retval -EIO if there is a memory read/write error.
*/
int zms_mount(struct zms_fs *fs);
/**
* @brief Mount a ZMS file system onto the device specified in `fs`, wiping the partition if
* mounting fails the first time.
*
* @param fs Pointer to the file system.
*
* @retval 0 on success.
* @retval -ENOTSUP if the detected file system is not ZMS.
* @retval -EPROTONOSUPPORT if the ZMS version is not supported.
* @retval -EINVAL if `fs` is NULL or any of the flash parameters or the sector layout is invalid.
* @retval -ENXIO if there is a device error.
* @retval -EIO if there is a memory read/write error.
*/
int zms_mount_force(struct zms_fs *fs);
/**
* @brief Clear the ZMS file system from device. The ZMS file system must be re-mounted after this
* operation.
*
* @param fs Pointer to the file system.
*
* @retval 0 on success.
* @retval -EACCES if `fs` is not mounted.
* @retval -ENXIO if there is a device error.
* @retval -EIO if there is a memory read/write error.
* @retval -EINVAL if `fs` is NULL.
*/
int zms_clear(struct zms_fs *fs);
/**
* @brief Write an entry to the file system.
*
* @note When the `len` parameter is equal to `0` the entry is effectively removed (it is
* equivalent to calling @ref zms_delete()). It is not possible to distinguish between a deleted
* entry and an entry with data of length 0.
*
* @param fs Pointer to the file system.
* @param id ID of the entry to be written.
* @param data Pointer to the data to be written.
* @param len Number of bytes to be written (maximum 64 KiB).
*
* @return Number of bytes written. On success, it will be equal to the number of bytes requested
* to be written or 0.
* When a rewrite of the same data already stored is attempted, nothing is written to flash,
* thus 0 is returned. On error, returns negative value of error codes defined in `errno.h`.
* @return Number of bytes written (`len` or 0) on success.
* @retval -EACCES if ZMS is still not initialized.
* @retval -ENXIO if there is a device error.
* @retval -EIO if there is a memory read/write error.
* @retval -EINVAL if `fs` is NULL or `len` is invalid.
* @retval -ENOSPC if no space is left on the device.
*/
ssize_t zms_write(struct zms_fs *fs, zms_id_t id, const void *data, size_t len);
/**
* @brief Delete an entry from the file system
*
* @param fs Pointer to the file system.
* @param id ID of the entry to be deleted.
*
* @retval 0 on success.
* @retval -EACCES if ZMS is still not initialized.
* @retval -ENXIO if there is a device error.
* @retval -EIO if there is a memory read/write error.
* @retval -EINVAL if `fs` is NULL.
*/
int zms_delete(struct zms_fs *fs, zms_id_t id);
/**
* @brief Read an entry from the file system.
*
* @param fs Pointer to the file system.
* @param id ID of the entry to be read.
* @param data Pointer to data buffer.
* @param len Number of bytes to read at most.
*
* @return Number of bytes read. On success, it will be equal to the number of bytes requested
* to be read or less than that if the stored data has a smaller size than the requested one.
* On error, returns negative value of error codes defined in `errno.h`.
* @return Number of bytes read (> 0) on success.
* @retval -EACCES if ZMS is still not initialized.
* @retval -EIO if there is a memory read/write error.
* @retval -ENOENT if there is no entry with the given `id`.
* @retval -EINVAL if `fs` is NULL.
*/
ssize_t zms_read(struct zms_fs *fs, zms_id_t id, void *data, size_t len);
/**
* @brief Read a history entry from the file system.
*
* @param fs Pointer to the file system.
* @param id ID of the entry to be read.
* @param data Pointer to data buffer.
* @param len Number of bytes to be read.
* @param cnt History counter: 0: latest entry, 1: one before latest ...
*
* @return Number of bytes read. On success, it will be equal to the number of bytes requested
* to be read. When the return value is larger than the number of bytes requested to read this
* indicates not all bytes were read, and more data is available. On error, returns negative
* value of error codes defined in `errno.h`.
* @return Number of bytes read (> 0) on success.
* @retval -EACCES if ZMS is still not initialized.
* @retval -EIO if there is a memory read/write error.
* @retval -ENOENT if there is no entry with the given `id` and history counter.
* @retval -EINVAL if `fs` is NULL.
*/
ssize_t zms_read_hist(struct zms_fs *fs, zms_id_t id, void *data, size_t len, uint32_t cnt);
/**
* @brief Gets the length of the data that is stored in an entry with a given `id`
*
* @param fs Pointer to the file system.
* @param id ID of the entry whose data length to retrieve.
*
* @return Data length contained in the ATE. On success, it will be equal to the number of bytes
* in the ATE. On error, returns negative value of error codes defined in `errno.h`.
* @return Length of the entry with the given `id` (> 0) on success.
* @retval -EACCES if ZMS is still not initialized.
* @retval -EIO if there is a memory read/write error.
* @retval -ENOENT if there is no entry with the given id.
* @retval -EINVAL if `fs` is NULL.
*/
ssize_t zms_get_data_length(struct zms_fs *fs, zms_id_t id);
/**
* @brief Calculate the available free space in the file system.
*
* @param fs Pointer to the file system.
*
* @return Number of free bytes. On success, it will be equal to the number of bytes that can
* still be written to the file system.
* Calculating the free space is a time-consuming operation, especially on SPI flash.
* On error, returns negative value of error codes defined in `errno.h`.
* @return Number of free bytes (>= 0) on success.
* @retval -EACCES if ZMS is still not initialized.
* @retval -EIO if there is a memory read/write error.
* @retval -EINVAL if `fs` is NULL.
*/
ssize_t zms_calc_free_space(struct zms_fs *fs);
/**
* @brief Tell how much contiguous free space remains in the currently active ZMS sector.
*
* @param fs Pointer to the file system.
*
* @retval >=0 Number of free bytes in the currently active sector. On success, it will be equal
* to the number of bytes that can be written without automatically advancing to the next sector.
* @retval -EACCES if ZMS is still not initialized.
* @retval -EINVAL if `fs` is NULL.
*/
ssize_t zms_active_sector_free_space(struct zms_fs *fs);
/**
* @brief Close the currently active sector and switch to the next one.
*
* @note The garbage collector is called on the new sector.
*
* @warning This routine is made available for specific use cases.
* It collides with ZMS's goal of avoiding any unnecessary flash erase operations.
* Using this routine extensively can result in premature failure of the flash device.
*
* @param fs Pointer to the file system.
*
* @retval 0 on success.
* @retval -EACCES if ZMS is still not initialized.
* @retval -EIO if there is a memory read/write error.
* @retval -EINVAL if `fs` is NULL.
*/
int zms_sector_use_next(struct zms_fs *fs);
/**
* @brief Return the maximum sector recycle count across all sectors.
*
* Iterates all sectors and stores the highest 32-bit cycle counter found in
* each sector's empty ATE in @p cycles. This can be used to estimate
* write-cycle consumption during testing.
*
* @param fs Pointer to the file system.
* @param cycles Pointer to store the maximum 32-bit cycle count across sectors.
*
* @retval 0 on success.
* @retval -EINVAL if @p fs or @p cycles is NULL.
* @retval -EACCES if the file system is not mounted.
*/
int zms_get_num_cycles(struct zms_fs *fs, uint32_t *cycles);
/**
* @brief Return the recycle count for a specific sector.
*
* @param fs Pointer to the file system.
* @param sector Sector index (0-based, must be less than @c fs->sector_count).
* @param cycles Pointer to store the 32-bit cycle count.
*
* @retval 0 on success.
* @retval -EINVAL if @p fs or @p cycles is NULL, or @p sector is out of range.
* @retval -EACCES if the file system is not mounted.
* @retval -ENOENT if the sector has no valid empty ATE.
*/
int zms_get_sector_num_cycles(struct zms_fs *fs, uint32_t sector, uint32_t *cycles);
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* ZEPHYR_INCLUDE_KVSS_ZMS_H_ */