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