| /* |
| * 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 <inttypes.h> |
| #include <limits.h> |
| |
| #include "flash_map.h" |
| |
| #include <kernel.h> |
| |
| #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_area *fe_area; /* ptr to area 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 */ |
| }; |
| |
| 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_area *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_area *f_oldest; |
| struct fcb_entry f_active; |
| u16_t f_active_id; |
| u8_t f_align; /* writes to flash have to aligned to this */ |
| }; |
| |
| /* |
| * 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(struct fcb *fcb); |
| |
| /* |
| * fcb_log is needed as the number of entries in a log |
| */ |
| struct fcb_log { |
| struct fcb fl_fcb; |
| u8_t fl_entries; |
| }; |
| |
| int log_fcb_init(struct fcb_log *fcblog, struct fcb *fcb, u16_t entries); |
| |
| /* |
| * 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 *loc, void *arg); |
| int fcb_walk(struct fcb *fcb, struct flash_area *fa, 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); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* __FCB_H_ */ |