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

news2025/1/10 20:40:06

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_DEBUG
	
    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_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.coloradmin.cn/o/1964716.html

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

相关文章

文心智能体零代码开发实践,创建一个智能体:从理论到实践AI技术落地

文心智能体引领零代码智能体开发新风尚&#xff0c;诚邀您一同探索这前沿科技的魅力&#xff01;以下为实践创建一个叫”从理论到实践AI技术落地“智能体的步骤。 首先登录官网&#xff1a;文心智能体平台AgentBuilder | 想象即现实 登录后点击&#xff1a;创建智能体 输入“…

《660》+《880》强化带刷计划‼️45天吃透所有核心知识点

如果把660吃透再去做880&#xff0c;肯定会轻松一些&#xff01; 因为660题对于基础的考查很深入&#xff0c;每一道题都有难度&#xff0c;都需要认真思考才能做出来&#xff0c;所以&#xff0c;660建议在基础结束之后再开始做&#xff0c;因为基础阶段本身对基础知识的理解…

240731-一图解释LM-Studio如何设置模型的国内下载

感谢微信公众号作者数翼分享的文章 — 本地 LLM 可视化工具 LM Studio 突破国内网络限制使用 A. 图文指南 B. 具体步骤 Step 1. 安装软件并通过VSCode等编辑打开软件所在目录 官网下载并安装。随后找到软件的安装路径&#xff0c;并通过VSCode打开。 Step 2. 全局替换 被替…

2024年8月1日 十二生肖 今日运势

小运播报&#xff1a;2024年8月1日&#xff0c;星期四&#xff0c;农历六月廿七 &#xff08;甲辰年辛未月丁酉日&#xff09;&#xff0c;法定工作日。今天建军节&#xff0c;祝保家卫国、英勇无畏的解放军战士们节日快乐&#xff01; 红榜生肖&#xff1a;龙、牛、猪 需要注…

JavaSE基础 (认识String类)

一&#xff0c;什么是String类 在C语言中已经涉及到字符串了&#xff0c;但是在C语言中要表示字符串只能使用字符数组或者字符指针&#xff0c;可以使用标准库提 供的字符串系列函数完成大部分操作&#xff0c;但是这种将数据和操作数据方法分离开的方式不符合面相对象的思想&…

vue中scoped详解以及样式穿透>>>、/deep/、::v-deep

1、scoped scoped属性用于限制样式仅应用于当前组件。当一个style标签拥有scoped属性时&#xff0c;它的CSS样式就只能作用于当前的组件&#xff0c;通过该属性&#xff0c;可以使得组件之间的样式不互相污染。 原理&#xff1a;当样式中加了scoped属性时候&#xff0c;编译的…

解决 Python 中 AttributeError: module ‘typing‘ has no attribute ‘_ClassVar‘

启动 Flask 的时候遇到&#xff1a; AttributeError: module typing has no attribute _ClassVar 卸载 dataclasses pip uninstall dataclasses 启动 Flask 正常

jenkins pipeline 发布 jar并运行

废话不多说&#xff0c;上教程 一&#xff0c;配置publish ssh 二&#xff0c;配置 ssh server 记住Name 三 设置发布选项 1 设置模块多选&#xff08;请安装多选插件&#xff1a;Active Choices Plug-in&#xff09; ​ ​ 四 编写pipeline 说明&#xff1a; 1 module…

vue项目实战 vueCropper 仿微信头像任意区域截取图片,上传到腾讯云保存

在package.json中添加 "vue-cropperjs": "4", 后在控制台执行&#xff1a;npm install ImageCropper.vue <template><div v-if"src"><!-- Vue Cropper区域 --><el-row class"cropper-wrapper" v-if"src…

stm32_按键消抖_代码与流程分析

stm32按键消抖 一 问题背景二 解决思路三 代码实现 一 问题背景 开关按钮&#xff1a;按下信号为0&#xff0c;正常信号为1 在按下时&#xff0c;表面上看我们只按了一下&#xff0c;但信号的传递并不是单纯的由1直接变为0。这是由于机械触点断开/闭合时会有抖动&#xff0c;…

北京大学:利用好不确定性,8B小模型也能超越GPT-4

大模型有一个显著的特点&#xff0c;那就是不确定性——对于特定输入&#xff0c;相同的LLM在不同解码配置下可能生成显著不同的输出。 比如问一问chatgpt“今天开心吗&#xff1f;”&#xff0c;可以得到两种不同的回答。 常用的解码策略有两种&#xff0c;一个是贪婪解码&am…

好展位,抢先订!2025浙江(玉环)机械展

2025第18届浙江&#xff08;玉环&#xff09;机械工业展览会 时间地点&#xff1a;2025年4月25-28日 玉环会展中心 近年来&#xff0c;随着玉环工业经济的蓬勃发展&#xff0c;汽摩配件、阀门水暖五金产业、铜加工、眼镜配件、金属加工生产等行业&#xff0c;如同贪婪的巨人&…

React Native初次使用遇到的问题

Write By Monkeyfly 以下内容均为原创&#xff0c;如需转载请注明出处。 前提&#xff1a;距离上次写博文已经过去了5年之久&#xff0c;诸多原因导致的&#xff0c;写一篇优质博文确实费时费力&#xff0c;中间有其他更感兴趣的事要做&#xff08;打游戏、旅游、逛街、看电影…

4.2、存储管理-页式存储

页式存储和段氏存储会考 页式存储几乎必考&#xff0c;段氏存储可能会考 页式存储 页式存储是操作系统的一种存储管理方式。 因为我们的程序往往是远远大于内存的&#xff0c;所以程序在执行的时候&#xff0c;是不会一次性把所有内容都装入到内存中&#xff0c;它会把程序分…

实验3-3 比较大小 想知道①和②的区别是什么(都错)

//实验3-3 比较大小 代码① #include<stdio.h> #include<math.h>void swap(int a, int b);// 正确声明 swap 函数int main() {int a, b, c;scanf("%d %d %d",&a,&b,&c);// 比较并交换 a 和 bif (a > b) {swap(a, b);}// 比较并交换 b 和 …

力扣刷题之3111.覆盖所有点的最少矩形数目

题干描述 给你一个二维整数数组 point &#xff0c;其中 points[i] [xi, yi] 表示二维平面内的一个点。同时给你一个整数 w 。你需要用矩形 覆盖所有 点。 每个矩形的左下角在某个点 (x1, 0) 处&#xff0c;且右上角在某个点 (x2, y2) 处&#xff0c;其中 x1 < x2 且 y2 …

关于vue开发中,高德地图有时不显示的问题

场景1&#xff1a;在弹出框中初始化地图 先设置 this.dialogVisible true; 然后再用nextTick初始化地图 this.$nextTick(() > { this.initAmap(); }); 场景2&#xff1a;点击tab页路由回退&#xff0c;导致高德地图不初始化的问题 解决方法&#xff1a; 通过$refs的方…

焦化行业超低排放改造巩固提升方案(朗观视觉)

朗观视觉小编观察发现&#xff1a;随着全球对环境保护意识的日益增强&#xff0c;焦化行业作为高污染、高排放的工业领域&#xff0c;其超低排放改造已成为行业转型升级的必然趋势。为了积极响应国家关于推进生态文明建设、打赢蓝天保卫战的号召&#xff0c;山东省生态环境厅发…

Windows + Ubuntu双系统!小白轻松安装

前言 这几天有小伙伴想着装WindowsUbuntu双系统&#xff0c;但苦于找不到办法&#xff0c;就在某篇文章后台留言&#xff1a; 这不&#xff0c;今天就更新了嘛&#xff01;虽然做不到有求必应&#xff0c;但教程帖还是可以写写的&#xff0c;能帮一个是一个&#xff01; 今天要…

深入探讨RCE漏洞及其防御策略

1. RCE漏洞 1.1. 漏洞原理 远程代码执行&#xff08;RCE&#xff09;漏洞允许攻击者远程注入并执行操作系统命令或代码&#xff0c;从而控制后台系统。 1.2. 漏洞产生条件 调用第三方组件存在代码执行漏洞。用户输入内容作为系统命令参数拼接到命令中。对用户输入的过滤不严…