Line data Source code
1 0 : /*
2 : * Copyright (c) 2017-2023 Nordic Semiconductor ASA
3 : * Copyright (c) 2015 Runtime Inc
4 : *
5 : * SPDX-License-Identifier: Apache-2.0
6 : */
7 : #ifndef ZEPHYR_INCLUDE_FS_FCB_H_
8 : #define ZEPHYR_INCLUDE_FS_FCB_H_
9 :
10 : /*
11 : * Flash circular buffer.
12 : */
13 : #include <inttypes.h>
14 : #include <limits.h>
15 :
16 : #include <zephyr/storage/flash_map.h>
17 : #include <zephyr/sys/util_macro.h>
18 :
19 : #include <zephyr/kernel.h>
20 :
21 : #ifdef __cplusplus
22 : extern "C" {
23 : #endif
24 :
25 : /**
26 : * @defgroup fcb Flash Circular Buffer (FCB)
27 : * @since 1.11
28 : * @version 1.0.0
29 : * @ingroup file_system_storage
30 : * @{
31 : * @}
32 : */
33 :
34 : /**
35 : * @defgroup fcb_data_structures Flash Circular Buffer Data Structures
36 : * @ingroup fcb
37 : * @{
38 : */
39 :
40 1 : #define FCB_MAX_LEN (0x3fffu) /**< Max length of element (16,383) */
41 :
42 : /**
43 : * @brief FCB entry info structure. This data structure describes the element
44 : * location in the flash.
45 : *
46 : * You would use it to figure out what parameters to pass to flash_area_read()
47 : * to read element contents. Or to flash_area_write() when adding a new element.
48 : * Entry location is pointer to area (within fcb->f_sectors), and offset
49 : * within that area.
50 : */
51 1 : struct fcb_entry {
52 1 : struct flash_sector *fe_sector;
53 : /**< Pointer to info about sector where data are placed */
54 :
55 1 : uint32_t fe_elem_off;
56 : /**< Offset from the start of the sector to beginning of element. */
57 :
58 1 : uint32_t fe_data_off;
59 : /**< Offset from the start of the sector to the start of element. */
60 :
61 1 : uint16_t fe_data_len; /**< Size of data area in fcb entry*/
62 : };
63 :
64 : /**
65 : * @brief Helper macro for calculating the data offset related to
66 : * the fcb flash_area start offset.
67 : *
68 : * @param entry fcb entry structure
69 : */
70 1 : #define FCB_ENTRY_FA_DATA_OFF(entry) (entry.fe_sector->fs_off +\
71 : entry.fe_data_off)
72 : /**
73 : * @brief Structure for transferring complete information about FCB entry
74 : * location within flash memory.
75 : */
76 1 : struct fcb_entry_ctx {
77 1 : struct fcb_entry loc; /**< FCB entry info */
78 1 : const struct flash_area *fap;
79 : /**< Flash area where the entry is placed */
80 : };
81 :
82 : /**
83 : * @brief Flag to disable CRC for the fcb_entries in flash.
84 : */
85 1 : #define FCB_FLAGS_CRC_DISABLED BIT(0)
86 :
87 : /**
88 : * @brief FCB instance structure
89 : *
90 : * The following data structure describes the FCB itself. First part should
91 : * be filled in by the user before calling @ref fcb_init. The second part is
92 : * used by FCB for its internal bookkeeping.
93 : */
94 1 : struct fcb {
95 : /* Caller of fcb_init fills this in */
96 1 : uint32_t f_magic;
97 : /**< Magic value, should not be 0xFFFFFFFF.
98 : * It is xored with inversion of f_erase_value and placed in
99 : * the beginning of FCB flash sector. FCB uses this when determining
100 : * whether sector contains valid data or not.
101 : * Giving it value of 0xFFFFFFFF means leaving bytes of the filed
102 : * in "erased" state.
103 : */
104 :
105 1 : uint8_t f_version; /**< Current version number of the data */
106 1 : uint8_t f_sector_cnt; /**< Number of elements in sector array */
107 1 : uint8_t f_scratch_cnt;
108 : /**< Number of sectors to keep empty. This can be used if you need
109 : * to have scratch space for garbage collecting when FCB fills up.
110 : */
111 :
112 1 : struct flash_sector *f_sectors;
113 : /**< Array of sectors, must be contiguous */
114 :
115 : /* Flash circular buffer internal state */
116 1 : struct k_mutex f_mtx;
117 : /**< Locking for accessing the FCB data, internal state */
118 :
119 1 : struct flash_sector *f_oldest;
120 : /**< Pointer to flash sector containing the oldest data,
121 : * internal state
122 : */
123 :
124 1 : struct fcb_entry f_active; /**< internal state */
125 1 : uint16_t f_active_id;
126 : /**< Flash location where the newest data is, internal state */
127 :
128 1 : uint8_t f_align;
129 : /**< writes to flash have to aligned to this, internal state */
130 :
131 1 : const struct flash_area *fap;
132 : /**< Flash area used by the fcb instance, internal state.
133 : * This can be transfer to FCB user
134 : */
135 :
136 1 : uint8_t f_erase_value;
137 : /**< The value flash takes when it is erased. This is read from
138 : * flash parameters and initialized upon call to fcb_init.
139 : */
140 : #ifdef CONFIG_FCB_ALLOW_FIXED_ENDMARKER
141 : const uint8_t f_flags;
142 : /**< Flags for configuring the FCB. */
143 : #endif
144 : };
145 :
146 : /**
147 : * @}
148 : */
149 :
150 : /**
151 : * @brief Flash Circular Buffer APIs
152 : * @defgroup fcb_api fcb API
153 : * @ingroup fcb
154 : * @{
155 : */
156 :
157 : /**
158 : * Initialize FCB instance.
159 : *
160 : * @param[in] f_area_id ID of flash area where fcb storage resides.
161 : * @param[in,out] fcbp FCB instance structure.
162 : *
163 : * @return 0 on success, non-zero on failure.
164 : */
165 1 : int fcb_init(int f_area_id, struct fcb *fcbp);
166 :
167 : /**
168 : * Appends an entry to circular buffer.
169 : *
170 : * When writing the
171 : * contents for the entry, use loc->fe_sector and loc->fe_data_off with
172 : * flash_area_write() to fcb flash_area.
173 : * When you're finished, call fcb_append_finish() with loc as argument.
174 : *
175 : * @param[in] fcbp FCB instance structure.
176 : * @param[in] len Length of data which are expected to be written as the entry
177 : * payload.
178 : * @param[out] loc entry location information
179 : *
180 : * @return 0 on success, non-zero on failure.
181 : */
182 1 : int fcb_append(struct fcb *fcbp, uint16_t len, struct fcb_entry *loc);
183 :
184 : /**
185 : * Finishes entry append operation.
186 : *
187 : * @param[in] fcbp FCB instance structure.
188 : * @param[in] append_loc entry location information
189 : *
190 : * @return 0 on success, non-zero on failure.
191 : */
192 1 : int fcb_append_finish(struct fcb *fcbp, struct fcb_entry *append_loc);
193 :
194 : /**
195 : * FCB Walk callback function type.
196 : *
197 : * Type of function which is expected to be called while walking over fcb
198 : * entries thanks to a @ref fcb_walk call.
199 : *
200 : * Entry data can be read using flash_area_read(), using
201 : * loc_ctx fields as arguments.
202 : * If cb wants to stop the walk, it should return non-zero value.
203 : *
204 : * @param[in] loc_ctx entry location information (full context)
205 : * @param[in,out] arg callback context, transferred from @ref fcb_walk.
206 : *
207 : * @return 0 continue walking, non-zero stop walking.
208 : */
209 1 : typedef int (*fcb_walk_cb)(struct fcb_entry_ctx *loc_ctx, void *arg);
210 :
211 : /**
212 : * Walk over all entries in the FCB sector
213 : *
214 : * @param[in] sector fcb sector to be walked. If null, traverse entire
215 : * storage.
216 : * @param[in] fcbp FCB instance structure.
217 : * @param[in] cb pointer to the function which gets called for every
218 : * entry. If cb wants to stop the walk, it should return
219 : * non-zero value.
220 : * @param[in,out] cb_arg callback context, transferred to the callback
221 : * implementation.
222 : *
223 : * @return 0 on success, negative on failure (or transferred form callback
224 : * return-value), positive transferred form callback return-value
225 : */
226 1 : int fcb_walk(struct fcb *fcbp, struct flash_sector *sector, fcb_walk_cb cb, void *cb_arg);
227 :
228 : /**
229 : * Get next fcb entry location.
230 : *
231 : * Function to obtain fcb entry location in relation to entry pointed by
232 : * <p> loc.
233 : * If loc->fe_sector is set and loc->fe_elem_off is not 0 function fetches next
234 : * fcb entry location.
235 : * If loc->fe_sector is NULL function fetches the oldest entry location within
236 : * FCB storage. loc->fe_sector is set and loc->fe_elem_off is 0 function fetches
237 : * the first entry location in the fcb sector.
238 : *
239 : * @param[in] fcbp FCB instance structure.
240 : * @param[in,out] loc entry location information
241 : *
242 : * @return 0 on success, non-zero on failure.
243 : */
244 1 : int fcb_getnext(struct fcb *fcbp, struct fcb_entry *loc);
245 :
246 : /**
247 : * Rotate fcb sectors
248 : *
249 : * Function erases the data from oldest sector. Upon that the next sector
250 : * becomes the oldest. Active sector is also switched if needed.
251 : *
252 : * @param[in] fcbp FCB instance structure.
253 : */
254 1 : int fcb_rotate(struct fcb *fcbp);
255 :
256 : /**
257 : * Start using the scratch block.
258 : *
259 : * Take one of the scratch blocks into use. So a scratch sector becomes
260 : * active sector to which entries can be appended.
261 : *
262 : * @param[in] fcbp FCB instance structure.
263 : *
264 : * @return 0 on success, non-zero on failure.
265 : */
266 1 : int fcb_append_to_scratch(struct fcb *fcbp);
267 :
268 : /**
269 : * Get free sector count.
270 : *
271 : * @param[in] fcbp FCB instance structure.
272 : *
273 : * @return Number of free sectors.
274 : */
275 1 : int fcb_free_sector_cnt(struct fcb *fcbp);
276 :
277 : /**
278 : * Check whether FCB has any data.
279 : *
280 : * @param[in] fcbp FCB instance structure.
281 : *
282 : * @return Positive value if fcb is empty, otherwise 0.
283 : */
284 1 : int fcb_is_empty(struct fcb *fcbp);
285 :
286 : /**
287 : * Finds the fcb entry that gives back up to n entries at the end.
288 : *
289 : * @param[in] fcbp FCB instance structure.
290 : * @param[in] entries number of fcb entries the user wants to get
291 : * @param[out] last_n_entry last_n_entry the fcb_entry to be returned
292 : *
293 : * @return 0 on there are any fcbs available; -ENOENT otherwise
294 : */
295 1 : int fcb_offset_last_n(struct fcb *fcbp, uint8_t entries, struct fcb_entry *last_n_entry);
296 :
297 : /**
298 : * Clear fcb instance storage.
299 : *
300 : * @param[in] fcbp FCB instance structure.
301 : *
302 : * @return 0 on success; non-zero on failure
303 : */
304 1 : int fcb_clear(struct fcb *fcbp);
305 :
306 : /**
307 : * @}
308 : */
309 :
310 : /**
311 : * @brief Flash Circular internal
312 : * @defgroup fcb_internal fcb non-API prototypes
313 : * @ingroup fcb
314 : * @{
315 : */
316 :
317 : /**
318 : * Read raw data from the fcb flash sector.
319 : *
320 : * @param[in] fcbp FCB instance structure.
321 : * @param[in] sector FCB sector.
322 : * @param[in] off Read offset form sector begin.
323 : * @param[out] dst Destination buffer.
324 : * @param[in] len Read-out size.
325 : *
326 : * @return 0 on success, negative errno code on fail.
327 : */
328 1 : int fcb_flash_read(const struct fcb *fcbp, const struct flash_sector *sector, off_t off,
329 : void *dst, size_t len);
330 :
331 : /**
332 : * Write raw data to the fcb flash sector.
333 : *
334 : * @param[in] fcbp FCB instance structure.
335 : * @param[in] sector FCB sector.
336 : * @param[in] off Write offset form sector begin.
337 : * @param[in] src Source buffer.
338 : * @param[in] len Write size.
339 : *
340 : * @return 0 on success, negative errno code on fail.
341 : */
342 1 : int fcb_flash_write(const struct fcb *fcbp, const struct flash_sector *sector, off_t off,
343 : const void *src, size_t len);
344 :
345 : /**
346 : * @}
347 : */
348 :
349 : #ifdef __cplusplus
350 : }
351 : #endif
352 :
353 : #endif /* ZEPHYR_INCLUDE_FS_FCB_H_ */
|