src.dualinventive.com/dinet/libdi_fw/include/di_fw/drv/stm32fx_flash.h

110 lines
4.0 KiB
C

/**
* @file di_fw/drv/stm32fx_flash.h
* @brief Cortex-M flash eeprom driver
* @date March 22, 2016
* @author J.J.J. Jacobs
* @copyright 2016 Dual Inventive Technology Centre B.V.
*
* Cortex-M flash eeprom emulation driver for di_config_ctx
* @note di_time component MUST be initialized before using this driver
*/
#ifndef INCLUDE_DI_FW_FLASH_H_
#define INCLUDE_DI_FW_FLASH_H_
#include <stdint.h>
#include <di/config.h>
#define DI_FW_FLASH_ADDR_SECTOR1 (uint32_t)((FLASH_BASE) + 0x4000)
#define DI_FW_FLASH_ID_SECTOR1 1U
#define DI_FW_FLASH_ADDR_SECTOR2 (uint32_t)0x08008000
#define DI_FW_FLASH_ID_SECTOR2 2U
#define DI_FW_FLASH_PAGE_ADDR_INVAL 0x0 /* Invalid page address */
#define DI_FW_FLASH_PAGE_STATUS_SIZE 2U /**< Size of flash page status field (in bytes) */
#define DI_FW_FLASH_PAGE_SIZE (1 * 1024)
#define DI_FW_FLASH_SECTOR_SIZE (16 * 1024)
#define DI_FW_FLASH_PAGE_CONFIG_SIZE (DI_FW_FLASH_PAGE_SIZE - \
DI_FW_FLASH_PAGE_STATUS_SIZE) /**< Page size for di_config_ctx size */
enum di_fw_flash_page_status {
DI_FW_FLASH_PAGE_STATUS_ERASED = (uint16_t)0xffff,
DI_FW_FLASH_PAGE_STATUS_WRITTEN = (uint16_t)0xeeee,
DI_FW_FLASH_PAGE_STATUS_VALID = (uint16_t)0xeee0,
DI_FW_FLASH_PAGE_STATUS_DIRTY = (uint16_t)0xee00,
DI_FW_FLASH_PAGE_STATUS_CORRUPT = (uint16_t)0xe000
};
struct di_fw_flash_ctx {
struct {
uint32_t sector_one; /* First sector physical address */
uint32_t sector_two; /* Second sector physical address */
} addr;
struct {
uint32_t sector_one; /* Physical id of first sector */
uint32_t sector_two; /* Physical id of second sector */
} id;
struct {
uint32_t sector; /* Sector size in bytes */
uint32_t page; /* Page size in bytes */
uint32_t pages; /* Pages per sector */
} size;
struct {
uint32_t addr; /* Current valid/cached page address (0x0 when unset) */
uint32_t sector; /* Current page sector number */
uint8_t *cache; /* Page cache buffer */
bool is_cached; /* Page is cached flag */
} page;
};
static inline void di_fw_flash_set_addr_sector_one(struct di_fw_flash_ctx *ctx, uint32_t addr)
{
ctx->addr.sector_one = addr;
}
static inline void di_fw_flash_set_addr_sector_two(struct di_fw_flash_ctx *ctx, uint32_t addr)
{
ctx->addr.sector_two = addr;
}
static inline void di_fw_flash_set_id_sector_one(struct di_fw_flash_ctx *ctx, uint32_t id) { ctx->id.sector_one = id; }
static inline void di_fw_flash_set_id_sector_two(struct di_fw_flash_ctx *ctx, uint32_t id) { ctx->id.sector_two = id; }
static inline void di_fw_flash_set_sector_size(struct di_fw_flash_ctx *ctx, uint32_t size) { ctx->size.sector = size; }
static inline void di_fw_flash_set_page_size(struct di_fw_flash_ctx *ctx, uint32_t size)
{
ctx->size.page = size;
ctx->size.pages = ctx->size.sector / ctx->size.page;
}
static inline void di_fw_flash_set_page_cache(struct di_fw_flash_ctx *ctx, uint8_t *page)
{
ctx->page.cache = page;
ctx->page.is_cached = false;
ctx->page.addr = DI_FW_FLASH_PAGE_ADDR_INVAL;
ctx->page.sector = 0;
}
size_t di_fw_flash_read(struct di_config_ctx *ctx, uint32_t offset, void *data, size_t size);
size_t di_fw_flash_write(struct di_config_ctx *ctx, uint32_t offset, const void *data, size_t size);
void di_fw_flash_sector_erase(uint32_t sector_nr);
void di_fw_flash_page_set_status(uint32_t addr, enum di_fw_flash_page_status status);
enum di_fw_flash_page_status di_fw_flash_page_get_status(uint32_t addr);
/**
* Search for first flash page with given status
* @param ctx Flash context
* @param sector_addr The start address of the sector
* @param status Page status to search for
* @retval 0 When no such page is found
* @retval !0 Valid base address of page
*/
uint32_t di_fw_flash_page_search(struct di_fw_flash_ctx *ctx, uint32_t sector_addr,
enum di_fw_flash_page_status status);
void di_fw_flash_read_data(uint32_t addr, uint8_t *data, size_t size);
void di_fw_flash_write_data(uint32_t addr, const uint8_t *data, size_t size);
void di_fw_flash_sync(struct di_config_ctx *ctx);
#endif /* INCLUDE_DI_FW_FLASH_H */