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