基于N32L406MB EasyFlash参数(key-value)记录库移植

EasyFlash

感谢作者的分享https://github.com/armink/EasyFlash

EasyFlash是一款开源的轻量级嵌入式Flash存储器库,方便开发者更加轻松的实现基于Flash存储器的常见应用开发

三大实用功能

  1. ENV快速保存产品参数(key-value),支持 写平衡(磨损平衡)掉电保护 功能

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

  1. IAP 在线升级再也不是难事儿

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

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

移植

下载源码

https://github.com/armink/EasyFlash

https://gitee.com/Armink/EasyFlash

在这里插入图片描述

复制源码

在这里插入图片描述

添加源码至工程

配置文件参考stm32f103中的配置文件和接口文件

在这里插入图片描述

添加头文件

…\middle\easyflash\inc

在这里插入图片描述

修改配置文件


#ifndef EF_CFG_H_
#define EF_CFG_H_#include "n32l40x.h"/* 使用 ENV 功能 默认NG using ENV function, default is NG (Next Generation) mode start from V4.0 */
#define EF_USING_ENV/* 使用 IAP 功能  using IAP function */
//#define EF_USING_IAP/* using save log function */
/* #define EF_USING_LOG *//* stm32 的扇区大小 page size for stm32 flash */
#if defined(STM32F10X_LD) || defined(STM32F10X_LD_VL) || defined (STM32F10X_MD) || defined (STM32F10X_MD_VL)
#define PAGE_SIZE     1024
#else
#define PAGE_SIZE     2048  //N32L406=>2K
#endif/* 最小的擦除大小 the minimum size of flash erasure */
#define EF_ERASE_MIN_SIZE         PAGE_SIZE              /* it is one page for STM3210x *//* 闪存写入粒度,单位:位 the flash write granularity, unit: bit* only support 1(nor flash)/ 8(stm32f4)/ 32(stm32f1)/ 64(stm32l4) */
#define EF_WRITE_GRAN             32/* The size of read_env and continue_ff_addr function used*/
#define EF_READ_BUF_SIZE             32     /* @default 32, 较大的数字可以提高alloc_env的首次速度,但需要更多的堆栈空间Larger numbers can improve first-time speed of alloc_env but require more stack space*//*** 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  N32L406MB 128K 24K*/
#define EF_START_ADDR                  (FLASH_BASE + 100 * 1024) /* from the chip position: 100KB *//* ENV区域大小。GC至少有一个空扇区。因此,它的定义必须大于或等于2个闪存扇区大小 ENV area size. It's at least one empty sector for GC. So it's definination must more then or equal 2 flash sector size. */
#define ENV_AREA_SIZE                  (10 * EF_ERASE_MIN_SIZE)      /* 8K *//* saved log area size */
/* #define LOG_AREA_SIZE             (10 * EF_ERASE_MIN_SIZE)*/      /* 20K *//* 输出调试信息 print debug information of flash */#define PRINT_DEBUG											 //自定义调试答应函数#endif /* EF_CFG_H_ */

实现接口文件

本实验是基于国民技术的N32L406


#include <easyflash.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "elog.h"/* 默认的环境变量设置default environment variables set for user */
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"},
};/*** Flash port for hardware initialize.** @param default_env default ENV set for user* @param default_env_size default ENV size** @return result*/
EfErrCode ef_port_init(ef_env const **default_env, size_t *default_env_size) {EfErrCode result = EF_NO_ERR;*default_env = default_env_set;*default_env_size = sizeof(default_env_set) / sizeof(default_env_set[0]);//时钟初始化if(FLASH_HSICLOCK_DISABLE == FLASH_ClockInit()){printf("HSI oscillator not yet ready\r\n");while(1);}return result;
}/*** Read data from flash.* @note This operation's units is word.** @param addr flash address* @param buf buffer to store read data* @param size read bytes size这里大小是字节** @return result*/
EfErrCode ef_port_read(uint32_t addr, uint32_t *buf, size_t size) {EfErrCode result = EF_NO_ERR;uint8_t *buf_8 = (uint8_t *)buf;size_t i;/*copy from flash to ram */for (i = 0; i < size; i++, addr ++, buf_8++) {*buf_8 = *(uint8_t *) addr;}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	flash地址* @param size erase bytes size  这里大小是字节** @return result*/
EfErrCode ef_port_erase(uint32_t addr, size_t size) {EfErrCode result = EF_NO_ERR;
//    FLASH_Status flash_status;
//    size_t erase_pages, i;
//    
//    /* make sure the start address is a multiple of FLASH_ERASE_MIN_SIZE */
//    EF_ASSERT(addr % EF_ERASE_MIN_SIZE == 0);
//    
//    /* calculate pages */
//    erase_pages = size / PAGE_SIZE;
//    if (size % PAGE_SIZE != 0) {
//        erase_pages++;
//    }//    /* start erase */
//    FLASH_Unlock();
//    FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
//    for (i = 0; i < erase_pages; i++) {
//        flash_status = FLASH_ErasePage(addr + (PAGE_SIZE * i));
//        if (flash_status != FLASH_COMPLETE) {
//            result = EF_ERASE_ERR;
//            break;
//        }
//    }
//    FLASH_Lock();/* 解锁*/FLASH_Unlock();/* 擦除 */if (FLASH_COMPL != FLASH_EraseOnePage(addr)){while(1){printf("Flash EraseOnePage Error. Please Deal With This Error Promptly\r\n");}}//加锁FLASH_Lock();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;size_t i;uint32_t read_data;//    FLASH_Unlock();
//    FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
//    for (i = 0; i < size; i += 4, buf++, addr += 4) {
//        /* write data */
//        FLASH_ProgramWord(addr, *buf);
//        read_data = *(uint32_t *)addr;
//        /* check data */
//        if (read_data != *buf) {
//            result = EF_WRITE_ERR;
//            break;
//        }
//    }
//    FLASH_Lock();/* 解锁*/FLASH_Unlock();/* Program */for (uint32_t Counter_Num = 0; Counter_Num < size; Counter_Num += 4,buf++){if (FLASH_COMPL != FLASH_ProgramWord(addr + Counter_Num, *buf)){while(1){printf("Flash ProgramWord Error. Please Deal With This Error Promptly\r\n");}}}/* Locks the FLASH Program Erase Controller */FLASH_Lock();return result;
}/*** lock the ENV ram cache*/
void ef_port_env_lock(void) {__disable_irq();
}/*** unlock the ENV ram cache*/
void ef_port_env_unlock(void) {__enable_irq();
}static char log_buf[128];/*** This function is print flash debug info.** @param file the file which has call this function* @param line the line number which has call this function* @param format output format* @param ... args**/
void ef_log_debug(const char *file, const long line, const char *format, ...) {#ifdef PRINT_DEBUGva_list args;/* args point to the first variable parameter */va_start(args, format);/* must use vprintf to print */vsprintf(log_buf, format, args);log_d("[easyflash]:%s", log_buf);// printf("\r");va_end(args);#endif}/*** This function is print flash routine info.** @param format output format* @param ... args*/
void ef_log_info(const char *format, ...) {va_list args;/* args point to the first variable parameter */va_start(args, format);/* must use vprintf to print */vsprintf(log_buf, format, args);log_i("[easyflash]:%s", log_buf);// printf("\r");va_end(args);
}/*** This function is print flash non-package info.** @param format output format* @param ... args*/
void ef_print(const char *format, ...) {va_list args;/* args point to the first variable parameter */va_start(args, format);/* must use vprintf to print */vsprintf(log_buf, format, args);log_v("%s\r\n", log_buf);va_end(args);
}

添加测试代码

这里的第一步就是初始化easyflash_init

void easyflash_demo(void)
{if (easyflash_init() == EF_NO_ERR){uint32_t i_boot_times = NULL;char *c_old_boot_times, c_new_boot_times[11] = {0};/* 从Env获取启动次数(boot_times) */c_old_boot_times = ef_get_env("boot_times");assert_param(c_old_boot_times);i_boot_times = atol(c_old_boot_times);/* 启动次数 +1 */i_boot_times ++;log_v("The system now boot %d times\n\r", i_boot_times);/* 格式化一个字符串 */sprintf(c_new_boot_times,"%d", i_boot_times);/* 设置启动次数*/ef_set_env("boot_times", c_new_boot_times);//保存ef_save_env();}
}

在这里插入图片描述

磨损平衡)

在这里插入图片描述

blob 数据类型的保存和读取测试

  /**blob 数据类型的保存和读取测试*/char buff[10];memset(buff,0,10);if(i_boot_times&1){int save_len;ef_get_env_blob("blob",buff,10,&save_len);elog_hexdump("blob ",10,buff,10);}else{for(int i=0;i<10;i++){buff[i]=i_boot_times&0xff;}ef_set_env_blob("blob",buff,10);}

在这里插入图片描述

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

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

相关文章

最小例程上加OLED显示

最小例程上加OLED显示 本工程代码链接: https://ww0.lanzoul.com/i8lNa265gj7g 失效联系:qq2958360390 我们其实就加上这几个文件, 然后会调用就可以了, 具体的就看江协科技的OLED, 讲的很清楚, 我们这里只说应用, 我们的重点在使用. 下面跟着我来, 复制黏贴: 更详细请看哔哩…

从零开始学习机器学习,掌握AI未来的关键!

从零开始学习机器学习 1. 介绍1.1 人工智能&#xff08;AI&#xff09;概述1.2 机器学习在人工智能中的应用1.3 机器学习基础概念 2. 监督学习2.1 什么是监督学习2.2 回归分析2.3 分类问题2.4 模型评估和选择 3. 无监督学习3.1 什么是无监督学习3.2 聚类算法3.3 降维技术 4. 深…

(39)智能电池

文章目录 前言 1 通过任务规划器进行设置 2 补充信息 3 限制条件 4 参数说明 前言 虽然还不是很普遍&#xff0c;但智能电池更容易从飞行器上安装和拆卸&#xff0c;并且能够提供更多关于电池状态的信息&#xff0c;包括容量、单个电池电压、温度等。 ArduPilot 支持几种…

qt的信号槽连接成功,但是就是无法触发槽函数。你必须使用connect的第5个参数,Qt::QueuedConnection

signals:void sends(); public slots:void sl();//这种是默认自动连接&#xff0c;故第五个参数不用写connect(this,&MainWindow::sends,this,&MainWindow::sl);emit sends();void sl() {}如果connect连接成功&#xff0c;但是无法触发槽函数。你应该使用第五个参数&…

【vue-cli】vue-cli@2源码学习

vue-cli 2 源码 @vue/cli: 3.11.0创建项目 vue create 项目名称 @vue/cli: 2.x.x 创建项目 vue init webpack yhh-project 脚手架初始化项目流程: 下载vue/cli@2 源码 下载完成后初始化 npm i 创建项目 vue init webpack yhh-project vue-init: bin/vue-init #!/usr/bin/e…

与Zoom集成获取会议开始和结束事件

一、注册一个Zoom免费帐号&#xff08;需要在国外注册&#xff0c;国内不允许&#xff09; 二、进入Zoom应用市场创建一个应用 点击”发展”&#xff08;开发&#xff09;菜单&#xff0c;选择构建应用。 同意条款&#xff1a; 选择应用类型&#xff1a; 设置应用信息&#x…

Linux进程控制——进程程序替换、bash的模拟实现

文章目录 exec系列函数execlexeclp和execle execv系列函数bash的模拟实现实现思路完整代码其他问题 在学习进程的时候&#xff0c;我们想fork一个子进程&#xff0c;然后就可以给他布置任务了 但是如果我们分成两个人开发&#xff0c;父子进程分别负责不同的任务&#xff0c;等…

编程小白如何成为大神?大学新生的最佳入门攻略

目录 方向一&#xff1a;选择适合的编程语言 方向二&#xff1a;制定有效的学习计划 方向三&#xff1a;避免常见的学习陷阱 方向四&#xff1a;额外建议 编程已成为当代大学生的必备技能&#xff0c;但面对众多编程语言和学习资源&#xff0c;新生们常常感到迷茫。如何选择…

深度学习模型服务端部署——flask+gunicorn+supervisor+nginx+docker

前言&#xff1a;深度学习模型经过前期的训练调优评估&#xff0c;最终得到一个精度速度满足要求的模型(.pth, .ckpt&#xff0c;或者.onnx等等格式)&#xff0c;但模型要实际用起来&#xff0c;还得部署起来&#xff0c;部署分为在移动端芯片上和服务器上。在移动端芯片部署通…

大龄程序员转型攻略:拥抱人工智能,开启新征程

前言 随着科技的飞速发展&#xff0c;人工智能浪潮席卷全球&#xff0c;相关岗位炙手可热。在这个背景下&#xff0c;许多大龄程序员开始思考如何转型&#xff0c;以适应时代的变化。结合自身编程基础&#xff0c;大龄程序员可以学习机器学习、深度学习算法&#xff0c;投身于…

蓝桥杯 Python 研究生组-2023-省赛-工作时长

蓝桥账户中心https://www.lanqiao.cn/problems/3494/learning/ 问题描述 小蓝手里有一份 20222022 年度自己的上班打卡记录文件&#xff0c;文件包含若干条打卡记录&#xff0c;每条记录的格式均为“yyyy-MM-dd HH:mm:ssyyyy-MM-dd HH:mm:ss”&#xff0c;即按照年-月-日 时:…

转录组数据去批次方法整理(combat,combat-seq,removeBatchEffect)

为什么需要去除批次效应&#xff1f; 批次效应是指样本在不同批次处理及测量的情况下引入与生物学情况不相关的技术误差&#xff0c;比如不同试剂耗材&#xff0c;不同操作者&#xff0c;不同的实验时间等。 正是因为这些非生物学的因素存在就有可能会导致我们的结果偏离真实…

网络通信---UDP

前两天做了个mplayer项目&#xff0c;今日继续学习 网络内容十分重要&#xff01;&#xff01;&#xff01; 1.OSI七层模型 应用层:要传输的数据信息&#xff0c;如文件传输&#xff0c;电子邮件等&#xff08;最接近用户&#xff0c;看传输的内容类型到底是什么&#xff09; …

精进日常:每日练习与明智取舍的艺术

目录 题目1.对于非运行时异常&#xff0c;程序中一般可不做处理&#xff0c;由java虚拟机自动进行处理。2.下面哪个关键字可以用于Java的构造方法上&#xff1f;3.以下代码执行的结果显示是多少&#xff08; &#xff09;&#xff1f;注解总结 题目 选自牛客网 1.对于非运行时…

[工具推荐]前端加解密之Burp插件Galaxy

如果觉得该文章有帮助的&#xff0c;麻烦师傅们可以搜索下微信公众号&#xff1a;良月安全。点个关注&#xff0c;感谢师傅们的支持。 免责声明 本号所发布的所有内容&#xff0c;包括但不限于信息、工具、项目以及文章&#xff0c;均旨在提供学习与研究之用。所有工具安全性…

前后端demo-WarehouseManagement

前端 数据库 其他 1.git下来&#xff0c;解决依赖问题&#xff0c;前端报错因为字体文件丢失&#xff0c;下载字体放到fonts文件夹字体.zip官方版下载丨最新版下载丨绿色版下载丨APP下载-123云盘 2.后端login验证&#xff0c;前端需要账号格式&#xff0c;linqq.com 3.自己…

国产麒麟操作系统下搞单机版

去年纪委单位的一个项目&#xff0c;因为单位保密性质&#xff0c;档案必须要保密&#xff0c;要求采用单机版&#xff0c; 要求跟EXE那样&#xff0c;双击打开&#xff0c;阿公单位信息人员电脑操作水平化滞后还是相当严重啊。 去年已经给他花了时间按他们的要求实现了。 上周…

嵌入式C++、ROS 、OpenCV、SLAM 算法和路径规划算法:自主导航的移动机器人流程设计(代码示例)

在当今科技迅速发展的背景下&#xff0c;嵌入式自主移动机器人以其广泛的应用前景和技术挑战吸引了越来越多的研究者和开发者。本文将详细介绍一个嵌入式自主移动机器人项目&#xff0c;涵盖其硬件与软件系统设计、代码实现及项目总结&#xff0c;并提供相关参考文献。 项目概…

Day14-Servlet后端验证码的实现

图片验证码的生成采用的是Kaptcha&#xff1b; Kaptcha是一个高度可配置的验证码生成工具&#xff0c;由Google开源。它通过一系列配置文件和插件&#xff0c;实现了将验证码字符串自动转换成图片流&#xff0c;并可以与session进行关联&#xff0c;从而在验证过程中使用&#…

unity2D游戏开发17战斗精灵

导入 将PlayerFight32x32.png拖Player文件夹进去 设置属性 创建动画剪辑 选中前四帧,右键Create|Animation,将动画命名为player-ire-east 其他几个动画也创建好后,将其拖到Animations|Animations文件夹 选中PlayerController,再点击Animator 创建新的Blend Tree Graph,并重…