blob: aa6aae0ec0fe304d6990c3625b58238adbff7d5c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#ifndef __SYS_FCB_H_
#define __SYS_FCB_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
* \defgroup FCB Flash circular buffer.
* @{
*/
#include <inttypes.h>
#include <limits.h>
#include <assert.h>
#include <syscfg/syscfg.h>
#include <os/os_mutex.h>
#include <flash_map/flash_map.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 */
uint32_t fe_elem_off; /* start of entry */
uint32_t fe_data_off; /* start of data */
uint16_t fe_data_len; /* size of data area */
};
struct fcb {
/* Caller of fcb_init fills this in */
uint32_t f_magic; /* As placed on the disk */
uint8_t f_version; /* Current version number of the data */
uint8_t f_sector_cnt; /* Number of elements in sector array */
uint8_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 os_mutex f_mtx; /* Locking for accessing the FCB data */
struct flash_area *f_oldest;
struct fcb_entry f_active;
uint16_t f_active_id;
uint8_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
#define FCB_ERR_VERSION -8
#define FCB_ERR_NEXT_SECT -9
int fcb_init(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 *, uint16_t len, struct fcb_entry *loc);
int fcb_append_finish(struct fcb *, struct fcb_entry *append_loc);
/**
* Walk over all entries in FCB.
* 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 *, struct flash_area *, fcb_walk_cb cb, void *cb_arg);
int fcb_getnext(struct fcb *, struct fcb_entry *loc);
/**
* Erases the data from oldest sector.
*/
int fcb_rotate(struct fcb *);
/**
* Start using the scratch block.
*/
int fcb_append_to_scratch(struct 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, uint8_t entries,
struct fcb_entry *last_n_entry);
/**
* Clears FCB passed to it
*/
int fcb_clear(struct fcb *fcb);
/**
* Usage report for a given FCB area. Returns number of elements and the
* number of bytes stored in them.
*/
int fcb_area_info(struct fcb *fcb, struct flash_area *fa, int *elemsp,
int *bytesp);
#ifdef __cplusplus
}
/**
* @} FCB
*/
#endif
#endif /* __SYS_FLASHVAR_H_ */
/**
* @} FCB
*/