stm32 + w25qxx + EasyFlash

news2024/11/15 23:45:49

一,软件介绍

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.coloradmin.cn/o/707950.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CrossOver软件Mac2023下载安装教程

CrossOver是一款可以让Mac和Linux系统中正常运行Windows软件的应用程序。它不像虚拟机一样需要安装Windows系统之后才可以安装Windows的应用程序&#xff0c;这一方式给大多数用户带来了方便。通过CrossOver实现跨平台的文件复制粘贴&#xff0c;使Mac/Linux系统与Windows应用良…

数字图像处理1-概述

目录 一、数字图像与数字图像处理 1. 基本概念 1.1 处理方法通常有: 1.2 图像处理的基本特征∶ 2. 图像处理与图像分析的关系 3. 数字图像处理的优点 二、数字图像处理系统组成及研究内容 1.数字图像处理系统的组成 1.1 基本图象处理系统的结构 1.2 图像输入设备 1.3 扫描仪分…

leetcode 26.删除有序数组中的重复项

⭐️ 题目描述 &#x1f31f; leetcode链接&#xff1a;删除有序数组中的重复项 代码&#xff1a; /*思路&#xff1a;双指针问题[1,1,2]src-> [ 1 , 1 , 2 ]destnums[src] nums[dest] > src;src-> [ 1 , 1 , 2 ]destnums[src]…

volatile和-O3测试

一个延时函数&#xff1a; #include <stdio.h> #include <stdlib.h> #include <time.h> void delay(){int i 0;int j 0;for(i 0;i < 50000;i){for(j 0;j < 50000;j);} }int main(int argc, char **argv){printf("time %ld\n",time(NUL…

碳排放预测模型 | Python实现基于机器学习的碳排放预测模型(模型对比)

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 碳排放预测模型 | Python实现基于机器学习的碳排放预测模型(模型对比) 碳排放被认为是全球变暖的最主要原因之一。 该项目旨在提供各国碳排放未来趋势的概述以及未来十年的全球趋势预测。 其方法是分析这些国家各…

供应链管理-亿发供应链计划管理系统,赋能中小型制造企业信息化

供应链管理是现代企业成功的关键因素。中小型制造企业可以通过建立有效的供应链管理系统实现成本控制、增加交付速度、增强灵活度&#xff0c;增加客户满意度。供应链管理系统&#xff0c;利用物联网技术工具来实现中小型企业供应链自动化和优化。减少人为错误&#xff0c;增加…

30_小驰私房菜_qcom根据关键日志信息,快速排查问题

根据关键日志信息,能帮忙我们快速的定位和分析问题。是一项必须得掌握的技能。 一、查看当前是哪个app调用的相机 logcat 关键字“CameraService::connect” 如下面日志打印所示,我们还可以看到是调用的Camera API 1还是Camera API 2. 二、查看配流情况 1) qcom 平台 …

多元回归预测 | Matlab基于粒子群算法(PSO)优化混合核极限学习机HKELM回归预测, PSO-HKELM数据回归预测,多变量输入模型

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 多元回归预测 | Matlab基于粒子群算法(PSO)优化混合核极限学习机HKELM回归预测, PSO-HKELM数据回归预测,多变量输入模型 评价指标包括:MAE、RMSE和R2等,代码质量极高,方便学习和替换数据。要求2018版本及以上。…

Update module V1 V2

原文&#xff1a; https://www.cnblogs.com/helileng/archive/2010/10/15/1852237.html 这是讲RFC V1 V2最清楚的一个帖子了 SAP中V1和V2的区别及各功能 SAP的进程种类分&#xff1a;前台进程、后台进程、打印进程、更新进程、队列进程 其中更新进程分两种&#xff0c;V1和V2…

【2022吴恩达机器学习课程视频翻译笔记】2.4无监督学习-part-1

B站上面那个翻译我有点看不懂&#xff0c;打算自己啃英文翻译了&#xff08;有自己意译的部分&#xff09;&#xff0c;然后懒得做字幕&#xff0c;就丢在博客上面了&#xff0c;2.2之前的章节结合那个机翻字幕能看懂 2.4无监督学习-part-1 After supervised learning, the m…

springboot项目外卖管理 day09-mysql主从复制以及nginx入门

文章目录 一、读写分离问题分析MySQL主从复制介绍 配置配置主库&#xff0c;我这里就用虚拟机上的mysql当主库了配置从库&#xff0c;我这里就用我的另一台克隆的虚拟机了 读写分离案例背景Sharding-JDBC介绍项目实现读写分离 二、Nginx简介Nginx的下载和安装安装过程&#xff…

物联网芯片

1、当前我的个人开源库基于STM32F103&#xff0c;开发环境基于Keil&#xff0c;操作系统基于FreeRTOS V9.0 2、基于官方标准固件库V3.5基础上开发的BSP驱动外设库。 3、当前完成的有BKP_BSP、DMA_BSP、EXTI_BSP、FSMC_BSP、GPIO_BSP、IWDG_BSP、I2C_BSP、RTC_BSP、SPI_BSP、U…

Postgresql源码(108)不同类型insert在parse阶段的差异分析

0 概述 分析三种类型的insert在parse的各个阶段的差异&#xff1a; insert into TAB_IS SELECT * FROM STUDENT a WHERE a.sno > ANY (SELECT b.sno from STUDENT b); insert into TAB_IS values(10, AAA); insert into TAB_IS values(20, CCC),(30, DDD),(40, EEE);不同i…

代码随想录再战day4

24 两两交换链表的节点 力扣 思路&#xff1a; 还是看了carl哥的视频讲解才写出来。有点难搞 首先 还是老样子 需要一个dummyhead虚拟头节点。 然后核心就是 我们要操作后面两个节点的时候 一定要移动到 这两个节点的上一个节点。 &#xff08;来自代码随想录&#xff09; 然后…

EasyFlash在GD32F303CC上面的移植

记录学习的过程&#xff0c;如果在GD32F303CC上面移植EasyFlash。关于EasyFlash的相关介绍和源码&#xff0c;请参考&#xff1a;https://gitee.com/Armink/EasyFlash 或者 https://github.com/armink/EasyFlash 主要记录移植过程中需要注意的点&#xff0c;移植还是比较简单的…

6.6 极重要的复习,权限与指令间的关系

权限对于使用者账号很重要&#xff0c;因为他可以限制使用者能不能读取/创建/删除/修改文件或目录。 一、让使用者能进入某目录成为“可工作目录”的基本权限为何&#xff1a; 可使用的指令&#xff1a;例如 cd 等变换工作目录的指令&#xff1b; 目录所需权限&#xff1a;使…

liunx安装git

liunx安装git &#xff1a; 提示&#xff1a;记录自己装git 过程 执行下边命令安装 yum -y install git 安装完查看是否安装成功 git --version安装路径默认在/usr/libexe 愉快开始使用git

帆软 FineReport 绘制漏斗图

七一建党节&#xff0c;祝党生日快乐&#xff01; 夏日炎炎&#xff0c;周末在家&#xff0c;想起在用帆软做页面展示的时候&#xff0c;使用到了漏斗图&#xff0c;记录下来&#xff0c;方便查看。 以订单销量变化为例&#xff0c;分为五个阶段&#xff0c;商品浏览人数&#…

fastadmin给操作按钮添加权限菜单控制|新增权限控制菜单

1、在对应的控制器文件中&#xff0c;添加如下代码&#xff1a; $adminIds $this->getDataLimitAdminIds(); if (is_array($adminIds)) {if (!in_array($row[$this->dataLimitField], $adminIds)) {$this->error(__(You have no permission));} } 2、在对应的index…

Redis实战篇(三)

四.分布式锁 4.1.分布式锁概述 分布式锁&#xff1a;满足分布式系统或集群模式下多进程可见并且互斥的锁。分布式锁的核心思想就是让大家都使用同一把锁&#xff0c;只要大家使用的是同一把锁&#xff0c;那么我们就能锁住线程&#xff0c;不让线程并行&#xff0c;让程序串行…