1 /* 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 #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 struct fcb_entry { 52 struct flash_sector *fe_sector; 53 /**< Pointer to info about sector where data are placed */ 54 55 uint32_t fe_elem_off; 56 /**< Offset from the start of the sector to beginning of element. */ 57 58 uint32_t fe_data_off; 59 /**< Offset from the start of the sector to the start of element. */ 60 61 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 #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 struct fcb_entry_ctx { 77 struct fcb_entry loc; /**< FCB entry info */ 78 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 #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 struct fcb { 95 /* Caller of fcb_init fills this in */ 96 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 uint8_t f_version; /**< Current version number of the data */ 106 uint8_t f_sector_cnt; /**< Number of elements in sector array */ 107 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 struct flash_sector *f_sectors; 113 /**< Array of sectors, must be contiguous */ 114 115 /* Flash circular buffer internal state */ 116 struct k_mutex f_mtx; 117 /**< Locking for accessing the FCB data, internal state */ 118 119 struct flash_sector *f_oldest; 120 /**< Pointer to flash sector containing the oldest data, 121 * internal state 122 */ 123 124 struct fcb_entry f_active; /**< internal state */ 125 uint16_t f_active_id; 126 /**< Flash location where the newest data is, internal state */ 127 128 uint8_t f_align; 129 /**< writes to flash have to aligned to this, internal state */ 130 131 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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_ */ 354