easyflash版本:4.10
EasyFlash是一款开源的轻量级嵌入式Flash存储器库,方便开发者更加轻松的实现基于Flash存储器的常见应用开发。非常适合智能家居、可穿戴、工控、医疗、物联网等需要断电存储功能的产品,资源占用极低,支持各种 MCU 片上存储器。该库主要包括 三大实用功能 :
ENV 快速保存产品参数,支持 写平衡(磨损平衡) 及 掉电保护 功能
EasyFlash不仅能够实现对产品的 设定参数 或 运行日志 等信息的掉电保存功能,还封装了简洁的 增加、删除、修改及查询 方法, 降低了开发者对产品参数的处理难度,也保证了产品在后期升级时拥有更好的扩展性。让Flash变为NoSQL(非关系型数据库)模型的小型键值(Key-Value)存储数据库。
IAP 在线升级再也不是难事儿
该库封装了IAP(In-Application Programming)功能常用的接口,支持CRC32校验,同时支持Bootloader及Application的升级。
非常适合应用在小型的不带文件系统的产品中,方便开发人员快速定位、查找系统发生崩溃或死机的原因。同时配合EasyLogger(我开源的超轻量级、高性能C日志库,它提供与EasyFlash的无缝接口)一起使用,轻松实现C日志的Flash存储功能。
复制下面的文件到工程中
easyflash/src/easyflash.c
easyflash/src/ef_env.c
easyflash/src/ef_utils.c
easyflash/port/ef_port.c
EasyFlash-4.1.0\easyflash\inc中的头文件
ef_cfg.h
文件#define EF_ENV_VER_NUM (0) /* @note you must define it for a value, such as 0 */
/* MCU Endian Configuration, default is Little Endian Order.*/
/* #define EF_BIG_ENDIAN */
#endif /* EF_USING_ENV */
/* using IAP function */
/* #define EF_USING_IAP */
/* using save log function */
/* #define EF_USING_LOG */
/* The minimum size of flash erasure. May be a flash sector size. */
#define EF_ERASE_MIN_SIZE (2048) /* @note you must define it for a value */
/*FLASH_PAGE_SIZE 为0x800, 就是2048*/
/* the flash write granularity, unit: bit
* only support 1(nor flash)/ 8(stm32f4)/ 32(stm32f1) */
#define EF_WRITE_GRAN (32) /* @note you must define it for a value */
/*
*
* This all Backup Area Flash storage index. All used flash area configure is under here.
* |----------------------------| Storage Size
* | Environment variables area | ENV area size @see ENV_AREA_SIZE
* |----------------------------|
* | Saved log area | Log area size @see LOG_AREA_SIZE
* |----------------------------|
* |(IAP)Downloaded application | IAP already downloaded application, unfixed size
* |----------------------------|
*
* @note all area sizes must be aligned with EF_ERASE_MIN_SIZE
*
* The EasyFlash add the NG (Next Generation) mode start from V4.0. All old mode before V4.0, called LEGACY mode.
*
* - NG (Next Generation) mode is default mode from V4.0. It's easy to settings, only defined the ENV_AREA_SIZE.
* - The LEGACY mode has been DEPRECATED. It is NOT RECOMMENDED to continue using.
* Beacuse it will use ram to buffer the ENV and spend more flash erase times.
* If you want use it please using the V3.X version.
*/
/* backup area start address */
#define EF_START_ADDR (64 * EF_ERASE_MIN_SIZE + 0x08000000) /* @note you must define it for a value */
/* ENV area size. It's at least one empty sector for GC. So it's definition must more then or equal 2 flash sector size. */
#define ENV_AREA_SIZE (2 * EF_ERASE_MIN_SIZE) /* @note you must define it for a value if you used ENV */
/* saved log area size */
#define LOG_AREA_SIZE (10 * EF_ERASE_MIN_SIZE) /* @note you must define it for a value if you used log */
/* print debug information of flash */
#define PRINT_DEBUG
主要实现一下几个函数的接口
ef_port_init(如果使用FAL, 则需要配置,本例程不需要配置)
ef_port_read
ef_port_erase
ef_port_write
1.添加头文件, 在最上面添加#include "main.h"
完善default_env_set
static const ef_env default_env_set[] = {
{"iap_need_copy_app","0"},
{"iap_copy_app_size","0"},
{"stop_in_bootloader","0"},
{"device_id","1"},
{"boot_times","0"},
};
2.添加读函数
EfErrCode ef_port_read(uint32_t addr, uint32_t *buf, size_t size) {
EfErrCode result = EF_NO_ERR;
/* You can add your code under here. */
uint8_t *buf_8 = (uint8_t *)buf;
size_t i;
for (i = 0; i < size; i++, addr++, buf_8++)
{
*buf_8 = *(uint8_t *) addr;
}
return result;
}
3.添加擦除函数
EfErrCode ef_port_erase(uint32_t addr, size_t size) {
EfErrCode result = EF_NO_ERR;
/* make sure the start address is a multiple of EF_ERASE_MIN_SIZE */
EF_ASSERT(addr % EF_ERASE_MIN_SIZE == 0);
/* You can add your code under here. */
HAL_FLASH_Unlock();
/* 擦除FLASH*/
FLASH_EraseInitTypeDef FlashSet;
FlashSet.TypeErase = FLASH_TYPEERASE_PAGES;
FlashSet.PageAddress = addr;
FlashSet.NbPages = (size + EF_ERASE_MIN_SIZE -1)/ EF_ERASE_MIN_SIZE;
/*设置PageError,调用擦除函数*/
uint32_t PageError = 0;
HAL_FLASHEx_Erase(&FlashSet, &PageError);
HAL_FLASH_Lock();
return result;
}
4.添加读函数
EfErrCode ef_port_write(uint32_t addr, const uint32_t *buf, size_t size) {
EfErrCode result = EF_NO_ERR;
/* You can add your code under here. */
size_t i;
uint32_t read_data;
HAL_FLASH_Unlock();
for (i = 0; i < size; i += 4, buf++, addr += 4)
{
/* write data */
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr, *buf);
read_data = *(uint32_t *)addr;
/* check data */
if (read_data != *buf)
{
result = EF_WRITE_ERR;
break;
}
}
HAL_FLASH_Lock();
return result;
}
/* USER CODE BEGIN 2 */
int i = 0;
typedef struct {
uint16_t lux;
uint16_t arc;
}lux_arc_t;
lux_arc_t lux_arc[5];
for (i = 0; i < 5; ++i)
{
lux_arc[i].arc = i + 120;
lux_arc[i].lux = 10 * i + 134;
}
unsigned int Reboot_Time = 0;
char str[30] = "hello word";
char ptr[30];
if(easyflash_init() == EF_NO_ERR) // 初始化成功
{
ef_get_env_blob("boot_times", &Reboot_Time, 8, NULL); // 读出reboot_time的值
}
Reboot_Time++; // reboot_time的值加1
/*存储结构体也可以*/
ef_set_env_blob("stop_in_bootloader", lux_arc, 5 * sizeof(lux_arc_t));
ef_set_env_blob("iap_need_copy_app", str, strlen(str));
ef_set_env_blob("iap_copy_app_size", "我是中国人", strlen("我是中国人"));
memset(str, 0, sizeof(str));
memset(lux_arc, 0, sizeof(lux_arc));
ef_set_env_blob("boot_times", &Reboot_Time, 8); // 保存reboot_time的值
ef_get_env_blob("iap_need_copy_app", ptr, 30, NULL);
ef_get_env_blob("iap_copy_app_size", str, 30, NULL);
ef_get_env_blob("stop_in_bootloader", lux_arc, 5 * sizeof(lux_arc_t), NULL);
snprintf(buf, 128, "Reboot_Time is %d, %s, %s, arc:%d, lux:%d\r\n",Reboot_Time,
ptr, str, lux_arc[2].arc, lux_arc[2].lux); // 打印reboot_time的值
HAL_UART_Transmit(&huart1, (uint8_t*)buf, strlen(buf), 10);
/* USER CODE END 2 */