Line data Source code
1 0 : /* Copyright (c) 2018 Laczen
2 : * Copyright (c) 2024 BayLibre SAS
3 : *
4 : * SPDX-License-Identifier: Apache-2.0
5 : *
6 : * ZMS: Zephyr Memory Storage
7 : */
8 : #ifndef ZEPHYR_INCLUDE_FS_ZMS_H_
9 : #define ZEPHYR_INCLUDE_FS_ZMS_H_
10 :
11 : #include <sys/types.h>
12 : #include <zephyr/drivers/flash.h>
13 : #include <zephyr/kernel.h>
14 : #include <zephyr/device.h>
15 : #include <zephyr/toolchain.h>
16 :
17 : #ifdef __cplusplus
18 : extern "C" {
19 : #endif
20 :
21 : /**
22 : * @defgroup zms Zephyr Memory Storage (ZMS)
23 : * @ingroup file_system_storage
24 : * @{
25 : * @}
26 : */
27 :
28 : /**
29 : * @defgroup zms_data_structures ZMS data structures
30 : * @ingroup zms
31 : * @{
32 : */
33 :
34 : /** Zephyr Memory Storage file system structure */
35 1 : struct zms_fs {
36 : /** File system offset in flash */
37 1 : off_t offset;
38 : /** Allocation Table Entry (ATE) write address.
39 : * Addresses are stored as `uint64_t`:
40 : * - high 4 bytes correspond to the sector
41 : * - low 4 bytes are the offset in the sector
42 : */
43 1 : uint64_t ate_wra;
44 : /** Data write address */
45 1 : uint64_t data_wra;
46 : /** Storage system is split into sectors. The sector size must be a multiple of
47 : * `erase-block-size` if the device has erase capabilities
48 : */
49 1 : uint32_t sector_size;
50 : /** Number of sectors in the file system */
51 1 : uint32_t sector_count;
52 : /** Current cycle counter of the active sector (pointed to by `ate_wra`) */
53 1 : uint8_t sector_cycle;
54 : /** Flag indicating if the file system is initialized */
55 1 : bool ready;
56 : /** Mutex used to lock flash writes */
57 1 : struct k_mutex zms_lock;
58 : /** Flash device runtime structure */
59 1 : const struct device *flash_device;
60 : /** Flash memory parameters structure */
61 1 : const struct flash_parameters *flash_parameters;
62 : /** Size of an Allocation Table Entry */
63 1 : size_t ate_size;
64 : #if CONFIG_ZMS_LOOKUP_CACHE
65 : /** Lookup table used to cache ATE addresses of written IDs */
66 : uint64_t lookup_cache[CONFIG_ZMS_LOOKUP_CACHE_SIZE];
67 : #endif
68 : };
69 :
70 : /**
71 : * @}
72 : */
73 :
74 : /**
75 : * @defgroup zms_high_level_api ZMS API
76 : * @ingroup zms
77 : * @{
78 : */
79 :
80 : /**
81 : * @brief ID type used in the ZMS API.
82 : *
83 : * @note The width of this type depends on @kconfig{CONFIG_ZMS_ID_64BIT}.
84 : */
85 : #if CONFIG_ZMS_ID_64BIT
86 : typedef uint64_t zms_id_t;
87 : #else
88 1 : typedef uint32_t zms_id_t;
89 : #endif
90 :
91 : /**
92 : * @brief Mount a ZMS file system onto the device specified in `fs`.
93 : *
94 : * @param fs Pointer to the file system.
95 : *
96 : * @retval 0 on success.
97 : * @retval -ENOTSUP if the detected file system is not ZMS.
98 : * @retval -EPROTONOSUPPORT if the ZMS version is not supported.
99 : * @retval -EINVAL if `fs` is NULL or any of the flash parameters or the sector layout is invalid.
100 : * @retval -ENXIO if there is a device error.
101 : * @retval -EIO if there is a memory read/write error.
102 : */
103 1 : int zms_mount(struct zms_fs *fs);
104 :
105 : /**
106 : * @brief Clear the ZMS file system from device. The ZMS file system must be re-mounted after this
107 : * operation.
108 : *
109 : * @param fs Pointer to the file system.
110 : *
111 : * @retval 0 on success.
112 : * @retval -EACCES if `fs` is not mounted.
113 : * @retval -ENXIO if there is a device error.
114 : * @retval -EIO if there is a memory read/write error.
115 : * @retval -EINVAL if `fs` is NULL.
116 : */
117 1 : int zms_clear(struct zms_fs *fs);
118 :
119 : /**
120 : * @brief Write an entry to the file system.
121 : *
122 : * @note When the `len` parameter is equal to `0` the entry is effectively removed (it is
123 : * equivalent to calling @ref zms_delete()). It is not possible to distinguish between a deleted
124 : * entry and an entry with data of length 0.
125 : *
126 : * @param fs Pointer to the file system.
127 : * @param id ID of the entry to be written.
128 : * @param data Pointer to the data to be written.
129 : * @param len Number of bytes to be written (maximum 64 KiB).
130 : *
131 : * @return Number of bytes written. On success, it will be equal to the number of bytes requested
132 : * to be written or 0.
133 : * When a rewrite of the same data already stored is attempted, nothing is written to flash,
134 : * thus 0 is returned. On error, returns negative value of error codes defined in `errno.h`.
135 : * @retval Number of bytes written (`len` or 0) on success.
136 : * @retval -EACCES if ZMS is still not initialized.
137 : * @retval -ENXIO if there is a device error.
138 : * @retval -EIO if there is a memory read/write error.
139 : * @retval -EINVAL if `fs` is NULL or `len` is invalid.
140 : * @retval -ENOSPC if no space is left on the device.
141 : */
142 1 : ssize_t zms_write(struct zms_fs *fs, zms_id_t id, const void *data, size_t len);
143 :
144 : /**
145 : * @brief Delete an entry from the file system
146 : *
147 : * @param fs Pointer to the file system.
148 : * @param id ID of the entry to be deleted.
149 : *
150 : * @retval 0 on success.
151 : * @retval -EACCES if ZMS is still not initialized.
152 : * @retval -ENXIO if there is a device error.
153 : * @retval -EIO if there is a memory read/write error.
154 : * @retval -EINVAL if `fs` is NULL.
155 : */
156 1 : int zms_delete(struct zms_fs *fs, zms_id_t id);
157 :
158 : /**
159 : * @brief Read an entry from the file system.
160 : *
161 : * @param fs Pointer to the file system.
162 : * @param id ID of the entry to be read.
163 : * @param data Pointer to data buffer.
164 : * @param len Number of bytes to read at most.
165 : *
166 : * @return Number of bytes read. On success, it will be equal to the number of bytes requested
167 : * to be read or less than that if the stored data has a smaller size than the requested one.
168 : * On error, returns negative value of error codes defined in `errno.h`.
169 : * @retval Number of bytes read (> 0) on success.
170 : * @retval -EACCES if ZMS is still not initialized.
171 : * @retval -EIO if there is a memory read/write error.
172 : * @retval -ENOENT if there is no entry with the given `id`.
173 : * @retval -EINVAL if `fs` is NULL.
174 : */
175 1 : ssize_t zms_read(struct zms_fs *fs, zms_id_t id, void *data, size_t len);
176 :
177 : /**
178 : * @brief Read a history entry from the file system.
179 : *
180 : * @param fs Pointer to the file system.
181 : * @param id ID of the entry to be read.
182 : * @param data Pointer to data buffer.
183 : * @param len Number of bytes to be read.
184 : * @param cnt History counter: 0: latest entry, 1: one before latest ...
185 : *
186 : * @return Number of bytes read. On success, it will be equal to the number of bytes requested
187 : * to be read. When the return value is larger than the number of bytes requested to read this
188 : * indicates not all bytes were read, and more data is available. On error, returns negative
189 : * value of error codes defined in `errno.h`.
190 : * @retval Number of bytes read (> 0) on success.
191 : * @retval -EACCES if ZMS is still not initialized.
192 : * @retval -EIO if there is a memory read/write error.
193 : * @retval -ENOENT if there is no entry with the given `id` and history counter.
194 : * @retval -EINVAL if `fs` is NULL.
195 : */
196 1 : ssize_t zms_read_hist(struct zms_fs *fs, zms_id_t id, void *data, size_t len, uint32_t cnt);
197 :
198 : /**
199 : * @brief Gets the length of the data that is stored in an entry with a given `id`
200 : *
201 : * @param fs Pointer to the file system.
202 : * @param id ID of the entry whose data length to retrieve.
203 : *
204 : * @return Data length contained in the ATE. On success, it will be equal to the number of bytes
205 : * in the ATE. On error, returns negative value of error codes defined in `errno.h`.
206 : * @retval Length of the entry with the given `id` (> 0) on success.
207 : * @retval -EACCES if ZMS is still not initialized.
208 : * @retval -EIO if there is a memory read/write error.
209 : * @retval -ENOENT if there is no entry with the given id.
210 : * @retval -EINVAL if `fs` is NULL.
211 : */
212 1 : ssize_t zms_get_data_length(struct zms_fs *fs, zms_id_t id);
213 :
214 : /**
215 : * @brief Calculate the available free space in the file system.
216 : *
217 : * @param fs Pointer to the file system.
218 : *
219 : * @return Number of free bytes. On success, it will be equal to the number of bytes that can
220 : * still be written to the file system.
221 : * Calculating the free space is a time-consuming operation, especially on SPI flash.
222 : * On error, returns negative value of error codes defined in `errno.h`.
223 : * @retval Number of free bytes (>= 0) on success.
224 : * @retval -EACCES if ZMS is still not initialized.
225 : * @retval -EIO if there is a memory read/write error.
226 : * @retval -EINVAL if `fs` is NULL.
227 : */
228 1 : ssize_t zms_calc_free_space(struct zms_fs *fs);
229 :
230 : /**
231 : * @brief Tell how much contiguous free space remains in the currently active ZMS sector.
232 : *
233 : * @param fs Pointer to the file system.
234 : *
235 : * @retval >=0 Number of free bytes in the currently active sector
236 : * @retval -EACCES if ZMS is still not initialized.
237 : * @retval -EINVAL if `fs` is NULL.
238 : */
239 1 : ssize_t zms_active_sector_free_space(struct zms_fs *fs);
240 :
241 : /**
242 : * @brief Close the currently active sector and switch to the next one.
243 : *
244 : * @note The garbage collector is called on the new sector.
245 : *
246 : * @warning This routine is made available for specific use cases.
247 : * It collides with ZMS's goal of avoiding any unnecessary flash erase operations.
248 : * Using this routine extensively can result in premature failure of the flash device.
249 : *
250 : * @param fs Pointer to the file system.
251 : *
252 : * @retval 0 on success.
253 : * @retval -EACCES if ZMS is still not initialized.
254 : * @retval -EIO if there is a memory read/write error.
255 : * @retval -EINVAL if `fs` is NULL.
256 : */
257 1 : int zms_sector_use_next(struct zms_fs *fs);
258 :
259 : /**
260 : * @}
261 : */
262 :
263 : #ifdef __cplusplus
264 : }
265 : #endif
266 :
267 : #endif /* ZEPHYR_INCLUDE_FS_ZMS_H_ */
|