stm32 + w25qxx + EasyFlash

一,软件介绍

EasyFlash 是一款开源的轻量级嵌入式Flash存储器库,方便实现基于Flash存储器的常见应用开发。适合智能家居、可穿戴、工控、医疗等需要断电存储功能的产品,资源占用低,支持各种 MCU 片上存储器。 [1] 

该库目前提供三大实用功能:

  • Env:小型KV数据库,支持写平衡(磨损平衡)及掉电保护模式

EasyFlash不仅能够实现对产品的设定参数或运行日志等信息的掉电保存功能,还封装了简洁的增加、删除、修改及查询方法, 降低了开发者对产品参数的处理难度,也保证了产品在后期升级时拥有更好的扩展性。让Flash变为NoSQL(非关系型数据库)模型的小型键值(Key-Value)存储数据库。

  • IAP:在线升级再也不是难事儿

该库封装了IAP(In-Application Programming)功能常用的接口,支持CRC32校验,同时支持Bootloader及Application的升级。

  • Log:无需文件系统,日志可直接存储在Flash上

非常适合应用在小型的不带文件系统的产品中,方便开发人员快速定位、查找系统发生崩溃或死机的原因。同时配合EasyLogger(我开源的超轻量级、高性能C日志库,它提供与EasyFlash的无缝接口)一起使用,轻松实现C日志的Flash存储功能。

V4.0 NG 模式

EasyFlash 经过 4 年多的迭代,发布了完全重构的 V4.0 版本,该版本中的 ENV 功能被命名为NG(Next Generation) 模式,具有以下新特性 [2]  :

  • 更小的资源占用,0 内存占用;

  • ENV 的值类型支持任意类型、任意长度;

  • ENV 操作效率比以前的模式高,充分利用剩余空闲区域;

  • 原生支持磨损平衡、掉电保护功能 ;

  • ENV 支持增量升级,固件升级后 ENV 也支持升级;

  • 支持大数据存储模式,长度无限制。占用 Flash 超过 1 个扇区的资源可以直接存入 ENV(即将在 V4.1 支持);

  • 支持数据加密,提升存储的安全性,物联网时代的必备功能(即将在 V4.2 支持);

  • 支持数据压缩,减低 Flash 占用(即将在 V4.3 支持);

V4.0 设计及内部原理,V4.0 迁移指南等更多内容请继续阅读下面的文档章节

二,移植步骤。

        移植步骤参考port.md手册,内有详细说明。

1,添加文件。

源文件下载地址:

GitHub:https://github.com/armink/EasyFlash

 根据自己的需求,可以删减部分文件,全部的源文件并不大,这里不做删减。

2,添加头文件库路径及源文件路径。

 3,首先配置ef_cfg.h

添加完文件,不配置ef_cfg.h,编译的话会出现很多错误,配置完就不会报错了。

 

## 5、设置参数配置时需要修改项目中的`ef_cfg.h`文件,开启、关闭、修改对应的宏即可。### 5.1 环境变量功能- 默认状态:开启
- 操作方法:开启、关闭`EF_USING_ENV`宏即可#### 5.1.1 自动更新(增量更新)可以对 ENV 设置版本号(参照 5.1.2)。当 ENV 初始化时,如果检测到产品存储的版本号与设定版本号不一致,会自动追加默认环境变量集合中新增的环境变量。该功能非常适用于经常升级的产品中,当产品功能变更时,有可能会新增环境变量,此时只需要增大当前设定的 ENV 版本号,下次固件升级后,新增的环境变量将会自动追加上去。- 默认状态:关闭
- 操作方法:开启、关闭`EF_ENV_AUTO_UPDATE`宏即可#### 5.1.2 环境变量版本号该配置依赖于 5.1.1 配置。设置的环境变量版本号为整形数值,可以从 0 开始。如果在默认环境变量表中增加了环境变量,此时需要对该配置进行修改(通常加 1 )。- 操作方法:修改`EF_ENV_VER_NUM`宏对应值即可### 5.2 在线升级功能- 默认状态:开启
- 操作方法:开启、关闭`EF_USING_IAP`宏即可### 5.3 日志功能- 默认状态:开启
- 操作方法:开启、关闭`EF_USING_LOG`宏即可### 5.4 Flash 擦除粒度(最小擦除单位)- 操作方法:修改`EF_ERASE_MIN_SIZE`宏对应值即可,单位:byte### 5.5 Flash 写入粒度- 操作方法:修改`EF_WRITE_GRAN`宏对应值即可,单位:bit,仅支持:1/8/32### 5.5 备份区备份区共计包含3个区域,依次为:环境变量区、日志区及在线升级区。分区方式如下图所示![backup_area_partiton](images/BackupAreaPartition.jpg)在配置时需要注意以下几点:- 1、所有的区域必须按照`EF_ERASE_MIN_SIZE`对齐;
- 2、环境变量分区大少至少为两倍以上 `EF_ERASE_MIN_SIZE`;
- 3、从 V4.0 开始 ENV 的模式命名为 NG 模式,V4.0 之前的称之为 LEGACY 遗留模式;- 遗留模式已经被废弃,不再建议继续使用;- 如果需要继续使用遗留模式,请 EasyFlash 的 V3.X 版本。#### 5.5.1 备份区起始地址- 操作方法:修改`EF_START_ADDR`宏对应值即可#### 5.5.2 环境变量区总容量- 操作方法:修改`ENV_AREA_SIZE`宏对应值即可> 注意:不使用环境变量功能时,可以不定义此宏。#### 5.5.3 日志区总容量- 操作方法:修改`LOG_AREA_SIZE`宏对应值即可> 注意:不使用日志功能时,可以不定义此宏。### 5.6 调试日志开启后,将会库运行时自动输出调试日志- 默认状态:开启
- 操作方法:开启、关闭`PRINT_DEBUG`宏即可## 6、测试验证如果`\demo\`文件夹下有与项目Flash规格一致的Demo,则直接编译运行,观察测试结果即可。无需关注下面的步骤。每次使用前,务必先执行`easyflash_init()`方法对EasyFlash库及所使用的Flash进行初始化,保证初始化没问题后,再使用各功能的API方法。如果出现错误或断言,需根据提示信息检查移植配置及接口。

4,完善接口函数。

## 4、移植接口### 4.1 移植初始化EasyFlash移植初始化。可以传递默认环境变量,初始化EasyFlash移植所需的资源等等。```C
EfErrCode ef_port_init(ef_env const **default_env, size_t *default_env_size)
```|参数                                    |描述|
|:-----                                  |:----|
|default_env                             |默认的环境变量|
|default_env_size                        |默认环境变量的数量|### 4.2 读取Flash最小单位为4个字节。```C
EfErrCode ef_port_read(uint32_t addr, uint32_t *buf, size_t size)
```|参数                                    |描述|
|:-----                                  |:----|
|addr                                    |读取起始地址(4字节对齐)|
|buf                                     |存放读取数据的缓冲区|
|size                                    |读取数据的大小(字节)|### 4.3 擦除Flash```C
EfErrCode ef_port_erase(uint32_t addr, size_t size)
```|参数                                    |描述|
|:-----                                  |:----|
|addr                                    |擦除起始地址|
|size                                    |擦除数据的大小(字节)|### 4.4 写入Flash最小单位为4个字节。```C
EfErrCode ef_port_write(uint32_t addr, const uint32_t *buf, size_t size)
```|参数                                    |描述|
|:-----                                  |:----|
|addr                                    |写入的起始地址(4字节对齐)|
|buf                                     |源数据的缓冲区|
|size                                    |写入数据的大小(字节)|### 4.5 对环境变量缓冲区加锁为了保证RAM缓冲区在并发执行的安全性,所以需要对其进行加锁(如果项目的使用场景不存在并发情况,则可以忽略)。有操作系统时可以使用获取信号量来加锁,裸机时可以通过关闭全局中断来加锁。```C
void ef_port_env_lock(void)
```### 4.6 对环境变量缓冲区解锁有操作系统是可以使用释放信号量来解锁,裸机时可以通过开启全局中断来解锁。```C
void ef_port_env_unlock(void)
```### 4.7 打印调试日志信息在定义`PRINT_DEBUG`宏后,打印调试日志信息。```C
void ef_log_debug(const char *file, const long line, const char *format, ...)
```|参数                                    |描述|
|:-----                                  |:----|
|file                                    |调用该方法的文件|
|line                                    |调用该方法的行号|
|format                                  |打印格式|
|...                                     |不定参|### 4.8 打印普通日志信息```C
void ef_log_info(const char *format, ...)
```|参数                                    |描述|
|:-----                                  |:----|
|format                                  |打印格式|
|...                                     |不定参|### 4.9 无格式打印信息该方法输出无固定格式的打印信息,为`ef_print_env`方法所用(如果不使用`ef_print_env`则可以忽略)。而`ef_log_debug`及`ef_log_info`可以输出带指定前缀及格式的打印日志信息。```C
void ef_print(const char *format, ...)
```|参数                                    |描述|
|:-----                                  |:----|
|format                                  |打印格式|
|...                                     |不定参|### 4.10 默认环境变量集合在 ef_port.c 文件顶部定义有 `static const ef_env default_env_set[]` ,我们可以将产品上需要的默认环境变量集中定义在这里。当 flash 第一次初始化时会将默认的环境变量写入。默认环境变量内部采用 void * 类型,所以支持任意类型,可参考如下示例:```C
static uint32_t boot_count = 0;
static time_t boot_time[10] = {0, 1, 2, 3};
static const ef_env default_env_set[] = {
//      {   key  , value, value_len },{"username", "armink", 0},   //类型为字符串的环境变量可以设定值的长度为 0 ,此时会在初始化时会自动检测其长度{"password", "123456", 0},{"boot_count", &boot_count, sizeof(boot_count)},  //整形{"boot_time", &boot_time, sizeof(boot_time)},  //数组类型,其他类型使用方式类似
};
```

w25qxx修改了ef_port_read(),ef_port_erase(),ef_port_write()

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. */BSP_W25Qx_Read((uint8_t*)buf, addr, size);return result;
}/*** Erase data on flash.* @note This operation is irreversible.* @note This operation's units is different which on many chips.** @param addr flash address* @param size erase bytes size** @return result*/
EfErrCode ef_port_erase(uint32_t addr, size_t size) {EfErrCode result = EF_NO_ERR;u32 i=0;/* 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. */for(i=0;i<((size-1)/EF_ERASE_MIN_SIZE+1);i++)BSP_W25Qx_Erase_Sector(addr+i*EF_ERASE_MIN_SIZE);return result;
}
/*** Write data to flash.* @note This operation's units is word.* @note This operation must after erase. @see flash_erase.** @param addr flash address* @param buf the write data buffer* @param size write bytes size** @return result*/
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. */BSP_W25Qx_Write((uint8_t*) buf, addr, size);return result;
}

5,移植完成。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/3706.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qt/C++编写超精美自定义控件(历时9年更新迭代/超202个控件/祖传原创)

一、前言 无论是哪一门开发框架&#xff0c;如果涉及到UI这块&#xff0c;肯定需要用到自定义控件&#xff0c;越复杂功能越多的项目&#xff0c;自定义控件的数量就越多&#xff0c;最开始的时候可能每个自定义控件都针对特定的应用场景&#xff0c;甚至里面带了特定的场景的…

chatgpt赋能python:如何通过Python赚钱

如何通过Python赚钱 介绍 Python是一种高级编程语言&#xff0c;广泛用于Web开发、数据分析、机器学习等领域。Python具有简单易学、功能强大、易于维护等特点&#xff0c;因此非常受欢迎。而且&#xff0c;Python开源免费&#xff0c;可以在各个平台上运行&#xff0c;不需要…

CH543乐得瑞单C口显示器方案(LDR6020)

首先显示器的种类很多&#xff0c;有桌面显示器&#xff0c;便携显示器&#xff0c;智能显示器&#xff0c;甚至AR眼镜也可以算是一个微型显示器。以往的显示器传输视频信号多为VGA和HDMI,当然DP也有&#xff0c;只是占少数&#xff0c;再早之前还有模拟信号接口等等&#xff0…

第4章 信息系统管理

文章目录 4.1.1 管理基础1 层次结构2 系统管理 4.1.2 规划和组织1 规划模型2 组织模型1&#xff09;业务战略&#xff08;竞争力优势模型&#xff1a;差异化、总成本领先、专注 战略&#xff09;2&#xff09;组织机制战略&#xff08;莱维特钻石模型&#xff1a;信息与控制、人…

进程间通信之共享内存

一、共享内存实现进程间通信的原理 共享内存实际是操作系统在实际物理内存中开辟的一段内存。 共享内存实现进程间通信&#xff0c;是操作系统在实际物理内存开辟一块空间&#xff0c;一个进程在自己的页表中&#xff0c;将该空间和进程地址空间上的共享区的一块地址空间形成…

数字孪生场景渲染能力中的WebGL技术路线

使用三维建模技术构建出的虚拟现实场景后&#xff0c;需要通过渲染引擎实现场景的高精度、高保真和实时渲染。同时&#xff0c;需要将现实场景中的数据信息融合到虚拟场景中&#xff0c;实现对现实情况的监测和控制。 目前大多数数字孪生城市项目在三维渲染引擎的技术选型上通…

测试工程师首chatGPT,编写python读取xmind测试用例chatgtp+python+xmind

背景 有用xmind写测试用例的吧&#xff0c;统计一个xmind的条&#xff0c;需要花大量的时间&#xff0c;还有要统计有多少条冒烟的&#xff0c;多少条不通过的&#xff0c;还有通过的条数。 需求 快速使用python&#xff0c;写一个简单的脚本&#xff0c;统计所有xmind节点&…

c++ 内存管理一:初识内存分配工具

文章目录 前言1 new 和 delete2 new[]和delete[]3 operator new4 placement new5 malloc和free6 allocator 前言 侯捷 c内存管理学习总结笔记。 在C中&#xff0c;有几种常用的内存分配工具可以帮助进行动态内存管理。 从c应用程序自上而下&#xff0c;通常会有这样的几种分配…

算法分析基础题目

第一章-算法概述 递归算法必须具备的两个条件是边界条件或停止条件和递推方程或递归方程冒泡排序时间复杂度是___&#xff0c;堆排序时间复杂度是___。 O ( n 2 ) O(n^2) O(n2), O ( n l o g n ) O(nlogn) O(nlogn)斐波那契数列的第1项为1&#xff0c;第2项为2&#xff0c;以…

[RocketMQ] Producer发送消息的总体流程 (七)

单向发送: 把消息发向Broker服务器, 不管Broker是否接收, 只管发, 不管结果。同步发送: 把消息发向Broker服务器, 如果Broker成功接收, 可以得到Broker的响应。异步发送: 把消息发向Broker服务器, 如果Broker成功接收, 可以得到Broker的响应。异步所以发送消息后, 不用等待, 等…

LLaMA模型微调版本:斯坦福 Alpaca 详解

项目代码&#xff1a;https://github.com/tatsu-lab/stanford_alpaca 博客介绍&#xff1a;https://crfm.stanford.edu/2023/03/13/alpaca.html Alpaca 总览 Alpaca 是 LLaMA-7B 的微调版本&#xff0c;使用Self-instruct[2]方式借用text-davinct-003构建了52K的数据&#x…

vue3框架开发uniapp高仿度小满金融App项目

vue3框架开发uniapp高仿度小满金融App项目 心血来潮写了度小满前端项目使用vue3开发地址&#xff1a;度小满金融 下面是实现效果