/* * Copyright (c) 2017 Nordic Semiconductor ASA * Copyright (c) 2015 Runtime Inc * * SPDX-License-Identifier: Apache-2.0 */ #ifndef __FCB_H_ #define __FCB_H_ #ifdef __cplusplus extern "C" { #endif /* * Flash circular buffer. */ #include #include #include "flash_map.h" #include #define FCB_MAX_LEN (CHAR_MAX | CHAR_MAX << 7) /* Max length of element */ /* * Entry location is pointer to area (within fcb->f_sectors), and offset * within that area. */ struct fcb_entry { struct flash_sector *fe_sector; /* ptr to sector */ /* within fcb->f_sectors */ u32_t fe_elem_off; /* start of entry */ u32_t fe_data_off; /* start of data */ u16_t fe_data_len; /* size of data area */ }; /* * Helper macro for calculate the data offset related to * the fcb flash_area start offset. */ #define FCB_ENTRY_FA_DATA_OFF(entry) (entry.fe_sector->fs_off +\ entry.fe_data_off) struct fcb_entry_ctx { struct fcb_entry loc; const struct flash_area *fap; }; struct fcb { /* Caller of fcb_init fills this in */ u32_t f_magic; /* As placed on the disk */ u8_t f_version; /* Current version number of the data */ u8_t f_sector_cnt; /* Number of elements in sector array */ u8_t f_scratch_cnt; /* How many sectors should be kept empty */ struct flash_sector *f_sectors; /* Array of sectors, */ /* must be contiguous */ /* Flash circular buffer internal state */ struct k_mutex f_mtx; /* Locking for accessing the FCB data */ struct flash_sector *f_oldest; struct fcb_entry f_active; u16_t f_active_id; u8_t f_align; /* writes to flash have to aligned to this */ const struct flash_area *fap; /* Flash area used by the fcb instance */ /* This can be transfer to FCB user */ }; /* * Error codes. */ #define FCB_OK 0 #define FCB_ERR_ARGS -1 #define FCB_ERR_FLASH -2 #define FCB_ERR_NOVAR -3 #define FCB_ERR_NOSPACE -4 #define FCB_ERR_NOMEM -5 #define FCB_ERR_CRC -6 #define FCB_ERR_MAGIC -7 int fcb_init(int f_area_id, struct fcb *fcb); /* * fcb_append() appends an entry to circular buffer. When writing the * contents for the entry, use loc->fl_area and loc->fl_data_off with * flash_area_write(). When you're finished, call fcb_append_finish() with * loc as argument. */ int fcb_append(struct fcb *fcb, u16_t len, struct fcb_entry *loc); int fcb_append_finish(struct fcb *fcb, struct fcb_entry *append_loc); /* * Walk over all log entries in FCB, or entries in a given flash_area. * cb gets called for every entry. If cb wants to stop the walk, it should * return non-zero value. * * Entry data can be read using flash_area_read(), using * loc->fe_area, loc->fe_data_off, and loc->fe_data_len as arguments. */ typedef int (*fcb_walk_cb)(struct fcb_entry_ctx *loc_ctx, void *arg); int fcb_walk(struct fcb *fcb, struct flash_sector *sector, fcb_walk_cb cb, void *cb_arg); int fcb_getnext(struct fcb *fcb, struct fcb_entry *loc); /* * Erases the data from oldest sector. */ int fcb_rotate(struct fcb *fcb); /* * Start using the scratch block. */ int fcb_append_to_scratch(struct fcb *fcb); /* * How many sectors are unused. */ int fcb_free_sector_cnt(struct fcb *fcb); /* * Whether FCB has any data. */ int fcb_is_empty(struct fcb *fcb); /* * Element at offset *entries* from last position (backwards). */ int fcb_offset_last_n(struct fcb *fcb, u8_t entries, struct fcb_entry *last_n_entry); /* * Clears FCB passed to it */ int fcb_clear(struct fcb *fcb); int fcb_flash_read(const struct fcb *fcb, const struct flash_sector *sector, off_t off, void *dst, size_t len); int fcb_flash_write(const struct fcb *fcb, const struct flash_sector *sector, off_t off, const void *src, size_t len); #ifdef __cplusplus } #endif #endif /* __FCB_H_ */