【开源分享】EasyFlash,一款开源的轻量级嵌入式Flash存储器库

EasyFlash - 嵌入式小型数据库学习 在嵌入式产品开发时,需要存储一些用户数据,如:设备账户密码、SN、校准参数等,可以使用一款叫做EasyFlash的开源轻量级存储库,该存储库资源占用极低,移植简单。 阅读详情
AI摘要

EasyFlash是开源轻量级嵌入式Flash存储器库,适合多种需断电存储功能的产品。它有ENV快速保存参数、IAP在线升级、Log日志存储三大功能。V4.0 NG模式有诸多新特性,资源占用低。还介绍了在STM32F103 & FW25QXX上的移植集成步骤、注意事项及常见问题解决方法。

请添加图片描述


1. EasyFlash简介

EasyFlash是一款开源的轻量级嵌入式Flash存储器库,方便开发者更加轻松的实现基于Flash存储器的常见应用开发。非常适合智能家居、可穿戴、工控、医疗、物联网等需要断电存储功能的产品,资源占用极低,支持各种 MCU 片上存储器。该库主要包括 三大实用功能 :

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

  • IAP 在线升级再也不是难事儿
    该库封装了 IAP(In-Application Programming) 功能常用的接口,支持 CRC32 校验,同时支持 Bootloader 及 Application 的升级。

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


1.1 V4.0 NG 模式

EasyFlash V4.0 版本中的 ENV 功能被命名为 NG (Next Generation) 模式,这是一个完全重构的新版本,具有以下新特性:

  • 更小的资源占用,内存占用 几乎为 0 ;(V4.0 以前版本会使用额外的 RAM 空间进行缓存)
  • ENV 的值类型支持 任意类型 、任意长度,相当于直接 memcpy 变量至 flash ;(V4.0 之前只支持存储字符串)
  • ENV 操作效率比以前的模式高,充分利用剩余空闲区域,擦除次数及操作时间显著降低;
  • 原生支持 磨损平衡、掉电保护功能 (V4.0 之前需要占用额外的 Flash 扇区);
  • ENV 支持 增量升级 ,固件升级后 ENV 也支持升级;
  • 支持大数据存储模式,长度无限制,数据可在多个 Flash 扇区上顺序存储。像脚本程序、音频等占用 Flash 超过 1 个扇区的资源也都可以存入 ENV(即将在 V4.2 支持);
  • 支持 数据加密 ,提升存储的安全性,物联网时代的必备功能(即将在 V4.3 支持);
  • 支持 数据压缩 ,减低 Flash 占用(即将在 V4.4 支持);

1.2 资源占用

最低要求: ROM: 6K bytes RAM: 0.1K bytes


2. 移植与集成实例

2.1 STM32F103 & FW25QXX上集成

2.1.1 准备工作

1. 硬件资源确认
  • STM32F103C8T6 Flash 规格:
    • 总容量:64KB(0x08000000 ~ 0x0800FFFF)
    • 页大小:1KB(部分型号为2KB,需根据数据手册确认)
    • 擦写次数:约10万次
2. 软件依赖
  • 开发环境:Keil MDK/STM32CubeIDE + HAL库 或标准外设库
  • EasyFlash源码:GitHub仓库
  • 确保已集成 EasyLogger(可选,用于调试输出)

2.1.2 移植步骤

1. 添加源码到工程
  • 下载 EasyFlash 源码,将以下文件加入工程:

    • easylogger/inc/(头文件)
    • easylogger/src/(源文件,包括 ef_port.c、ef_utils.c 等)
    • 注意:需根据需求启用 EF_USING_ENV(环境变量)或 EF_USING_LOG(日志存储)。
  • 在工程中配置头文件路径:

// 例如在Keil中:
- ".\easylogger\inc"
- ".\User\Inc"       // 存放移植接口文件

2. 移植接口实现
2.1 Flash驱动函数

在 ef_port.c 中实现以下接口:

#include "ef_port.h"
#include "stm32f1xx_hal_flash.h"  // 使用HAL库

/* 定义EasyFlash使用的Flash区域 */
#define EF_START_ADDR    0x0800F000  // 假设使用最后4KB(需根据实际Flash大小调整)
#define EF_SIZE          0x00001000  // 4KB

/* 初始化Flash */
EfErrCode ef_port_init(void) {
    // 无需特殊初始化
    return EF_NO_ERR;
}

/* 擦除Flash页 */
EfErrCode ef_port_erase(uint32_t addr, size_t size) {
    HAL_FLASH_Unlock();  // 解锁Flash
    FLASH_EraseInitTypeDef erase;
    erase.TypeErase = FLASH_TYPEERASE_PAGES;
    erase.PageAddress = addr;
    erase.NbPages = (size + FLASH_PAGE_SIZE - 1) / FLASH_PAGE_SIZE;  // 计算需擦除的页数

    uint32_t pageError;
    if (HAL_FLASHEx_Erase(&erase, &pageError) != HAL_OK) {
        HAL_FLASH_Lock();
        return EF_ERASE_ERR;
    }
    HAL_FLASH_Lock();
    return EF_NO_ERR;
}

/* 写入Flash */
EfErrCode ef_port_write(uint32_t addr, const uint32_t *buf, size_t size) {
    HAL_FLASH_Unlock();
    for (size_t i = 0; i < size; i += 4) {
        if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr + i, *buf) != HAL_OK) {
            HAL_FLASH_Lock();
            return EF_WRITE_ERR;
        }
        buf++;
    }
    HAL_FLASH_Lock();
    return EF_NO_ERR;
}

/* 读取Flash */
void ef_port_read(uint32_t addr, uint32_t *buf, size_t size) {
    memcpy(buf, (void*)addr, size);
}

2.2 配置EasyFlash参数

在 ef_cfg.h 中修改配置:

#define EF_START_ADDR            EF_START_ADDR  // 与前述定义一致
#define EF_ERASE_MIN_SIZE        FLASH_PAGE_SIZE  // 擦除最小单位(1KB)
#define EF_WRITE_GRAN            EF_WRITE_GRAN_4BYTE  // STM32F1按4字节写入

3. 初始化与测试
3.1 初始化EasyFlash

在 main.c 中:

#include "easyflash.h"

int main(void) {
    HAL_Init();
    SystemClock_Config();

    /* 初始化EasyFlash */
    if (easyflash_init() == EF_NO_ERR) {
        log_i("EasyFlash init success!");
    }

    /* 测试环境变量读写 */
    ef_set_env("boot_count", "0");
    char *value = ef_get_env("boot_count");
    log_d("boot_count = %s", value);

    while (1) { }
}
3.2 测试输出

通过串口查看日志(需集成EasyLogger):

[I][main.c:25] EasyFlash init success!
[D][main.c:28] boot_count = 0

2.1.3 关键注意事项

1. Flash地址对齐
  • 擦除地址:必须按页对齐(如 0x0800F000)。
  • 写入地址:需按4字节对齐(STM32F1要求)。
2. 存储寿命优化
  • 磨损均衡:若频繁擦写,建议使用多扇区轮换存储。
  • 减少擦除次数:合并多次写操作,避免频繁擦除。
3. 多线程安全

在RTOS中,需在Flash操作前后加锁(如使用互斥量)。


2.1.4 常见问题解决

1. 擦除失败(返回EF_ERASE_ERR)
  • 检查Flash地址是否越界(如超出64KB)。
  • 确认 FLASH_PAGE_SIZE 是否正确(部分STM32F103型号为2KB)。
2. 写入数据异常
  • 确保写入前已擦除对应页。
  • 检查写入地址是否按4字节对齐。
3. EasyFlash初始化失败
  • 确认 ef_port.c 中的驱动函数是否实现完整。
  • 检查 ef_cfg.h 中的参数配置。
EasyFlash移植 概述 easyflash是开源的轻量级嵌入式flash存储器库,非常适合小型项目开发使用。 正文 废话不多说,直接开始盘它。 第一步:下载源文件 链接 第二步:工程 准备好一个工程。 第三步:将源文件添加进工程,并包含好头文件路径 第四步:修改工程文件 修改ef_port.c文件。 主要修改:ef_port_read、ef_port_erase、ef_port_write函数,这里函数实现对flash的读写操作,需要自行实现。 注意:其他功能函数,如log打印、加锁和解锁操作也需要自行实现。 ef_ 阅读详情

相关推荐

RT-T下使用easyflash的配置过程

RT-T下使用easyflash的配置过程

wanghongshuai1的博客 1015

EasyFlash | 让 Flash 成为小型 KV 数据库

嵌入式开源项目精选专栏 本专栏由Mculover666创建,主要内容为寻找嵌入式领域内的优质开源项目,一是帮助开发者使用开源项目实现更多的功能,二是通过这些开源项目,学习大佬的代码及背后的实现思想,提升自己的代码水平,和其它专栏相比,本专栏的优势在于: 不会单纯的介绍分享项目,还会包含作者亲自实践的过程分享,甚至还会有对它背后的设计思想解读。 目前本专栏包含的开源项目有: SFUD | 一个简...

Mculover666的博客(嵌入式) 1万+

告别SD卡!用STM32内部Flash和EasyFlash打造你的物联网设备‘黑匣子’

本文介绍如何利用STM32内部Flash和开源框架EasyFlash构建物联网设备的'黑匣子'系统,解决传统SD卡存储方案的可靠性问题。通过详细的硬件选型建议、软件架构设计和具体实现步骤,帮助开发者打造轻量级、高可靠的日志存储系统,适用于工业物联网和消费级IoT设备。

weixin_30421809的博客 378

easyflash 教程

可以看easyflash下的docs文档,万一你们手头没有文档呢。这里我就直接黏贴了。 API 说明文档: docs/zh/api.md 通用移植文档: docs/zh/port.md EasyFlash API 说明 所有支持的API接口都在\easyflash\inc\easyflash.h中声明。以下内容较多,建议使用 CTRL+F 搜索。 名词介绍: 备份区 :是EasyFlash定义的...

injre! injre~ 1万+

避坑指南:RT-Thread Studio中ulog与EasyFlash的最佳拍档配置法

本文详细介绍了在RT-Thread Studio中高效整合ulog日志框架与EasyFlash闪存管理库的配置方法。通过分析ulog_easyflash的协作原理、硬件平台适配、关键参数配置及常见问题解决方案,帮助开发者避开配置陷阱,实现日志系统与闪存管理的高效协作。特别针对SFUD库的片外Flash配置提供了实用建议。

weixin_30689307的博客 678

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

是一款开源的轻量级嵌入式Flash存储器库,方便开发者更加轻松的实现基于Flash存储器的常见应用开发EasyFlash不仅能够实现对产品的或等信息的掉电保存功能,还封装了简洁的方法, 降低了开发者对产品参数的处理难度,也保证了产品在后期升级时拥有更好的扩展性。。该库封装了IAP(In-Application Programming)功能常用的接口,支持CRC32校验,。

Car12 1220

嵌入式Flash存储与文件系统选型指南:SFUD、lwext4等10+轻量级方案盘点

痞子衡嵌入式半月刊(开源项目 pzh-mcu-bi-weekly)收录了大量嵌入式 Flash 存储与文件系统的实用项目。这篇文章为你盘点其中 **10+ 个轻量级方案**:从 SPI Flash 驱动库 SFUD,到断电存储库 EasyFlash、FlashDB,再到 FatFs、Spiffs、RanFS、lwext4 等文件系统,帮你快速搞懂"嵌入式 Flash 存储与文件系统"这条技术栈该怎

gitblog_00903的博客 996

轻松实现STM32数据存储:EasyFlash框架移植指南

STM32微控制器家族是STMicroelectronics(意法半导体)推出的32位ARM Cortex-M系列处理器的核心产品。这些微控制器因其高性能、低功耗和灵活的外设配置而广受欢迎,尤其是在工业控制、消费电子、汽车电子等领域。HAL库(硬件抽象层库)是ST为STM32系列微控制器提供的标准软件库,它为开发者提供了一个简单易用的编程接口,以方便快速开发应用程序,同时保持了代码的可移植性和可维护性。

weixin_36464343的博客 1774

flash实现镜头由远及近_EasyFlash | 让 Flash 成为小型 KV 数据库

本文首发于公众号Mculover666嵌入式开源项目精选专栏本专栏由Mculover666创建,主要内容为寻找嵌入式领域内的优质开源项目,一是帮助开发者使用开源项目实现更多的功能,二是通过这些开源项目,学习大佬的代码及背后的实现思想,提升自己的代码水平,和其它专栏相比,本专栏的优势在于:不会单纯的介绍分享项目,还会包含作者亲自实践的过程分享,甚至还会有对它背后的设计思想解读。目前本专栏包含的开源项...

weixin_39819671的博客 321

从零开始的计网学习——物理层

计算机网络对于IT人不论是就业还是升学都是核心的一门课程,一起从零开始,学习计算机网络!

Nimrod__的博客 2万+

5G Multicast/Broadcast Services(MBS) (七) MBS广播DRX

当处于RRC_IDLE或RRC_INACTIVE或RRC_CONNECTED 状态时,如果为 G-RNTI 配置了broadcast DRX,则允许MAC entity使用broadcast DRX 操作不连续地监听此G-RNTI的PDCCH;此 G-RNTI 的 drx-onDurationTimerPTM 或 drx-InactivityTimerPTM 正在运行的时间,也就是。long DRX周期drx-LongCycle-PTM和drx-StartOffset-PTM定义DRX周期开始的子帧。

asd199086的博客 391

FlashDB移植到STM32F103内部flash,FatFs、FlashDB 、EasyFlash的不同

最近项目用到了,Flash的存储,早就听过armink 大神开源的EsayFlash,于是乎就决定移植到新的项目上,发现 EasyFlash 升级到了 5.0.0 版本后因 API 接口与之前不完全兼容,故重新命名为 FlashDB,有很多种框架,FatFsFlashDBEasyFlash等等。最终这个项目选择了FLASHDB,因为FlashDB的查询比EasyFlash快FatFs是针对大文件系统的那种项目。下面简单说一下FlashDB的移植。还有这三个的区别和使用环境。

Lim的博客 1万+

PC 端微信页面拆分及 JavaFx 使用

一、前言 对于一个知识点的学习过程来说,往往使用自己熟悉的工具或方式才更易于上手。因为所有同类型的知识点在抛出复杂的流程拨云见日后,所能得到的几乎都是同样的设计思想和实现理论。 在 Java 语言桌面版开发中,直至目前共提供了三套 UI 开发方式;Awt、Swing、JavaFx,以及一些扩展组件 SWT 等。在这三套 UI 组件中,JavaFx 是最新也是最为好用的,因为他提供了丰富的功能,以及...

bugstack虫洞栈 3610

STM32HAL 移植 EasyFlash 开源框架(裸机开发神器)

概述 本篇文章介绍如何使用STM32内部Flash,将日志信息保存在Flash中,使用时再去读取。这样做得好处,就是非常适合物联网终端设备使用,使得日志可以更加容易的存储在非文件系统中,并具有历史日志检索的功能。 GitHub:https://github.com/armink/EasyLogger/blob/master/docs/zh/port/flash.md 硬件:STM32F103CBT6最小系统板 软件:Keil 5.29 + STM32CubeMX6.01 一、使...

qq_36075612的博客 1万+

8年ES运维经验整理出的Elasticsearch运维手册(超实用)

k1 : 控制非线性词频率归一化(饱和),Elasticsearch中默认值为1.2。用人能看懂的话说就是词语在文档中出现的次数对于得分的重要性。例如说我觉得在某些场景,一个搜索词在文档中出现越多则越接近我希望搜索的内容,就可以将这个参数调大一点。b :控制文档长度对于分数的惩罚力度。变量b处于分母上,它乘以刚刚讨论过的字段长度的比值,Elasticsearch中的b 默认值为0.75。如果b较大,则文档长度相对于平均长度的影响更大。

yonggeit的博客 5275

在 SAP S/4HANA Public Cloud 中做产品扩展:从 Key User 到 ABAP Cloud 与 BTP 的三轨实践指南

摘要:SAP S/4HANA Public Cloud 提供三种扩展方式(key user、developer extensibility 和 side-by-side),遵循 clean core 原则确保升级稳定。key user 扩展适合无代码轻量改良,developer extensibility 用于受控 ABAP 开发,side-by-side 则适用于云原生独立应用。文章通过销售订单优先级字段、退货审批微服务和采购校验等案例,说明不同扩展路径的适用场景与实现方法,帮助开发者在三系统景观中合理选

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 294

【亲测免费】 EasyFlash: 简单易用的嵌入式Flash存储库

是一个开源、轻量级且高度可定制化的嵌入式系统Flash管理库,由知名开发者armink贡献。该项目旨在解决微控制器(MCU)中Flash内存的操作问题,提供可靠的存储解决方案,适用于各种物联网和嵌入式设备。 ## 技术分析 ### 内存布局与分区 EasyFlash支持动态分区,可以根据应用需求动态调整数据存储区域,避免了静态分区可能导致的空间浪费。它还提供了坏块检测和替换机制,以保证数据的完...

gitblog_00095的博客 1393

Autosar 下电过程-基于ETAS工具

本文介绍基于ETAS工具对应的BIP包的下电过程,仅供参考。在最后调用SBC下电时,需要理清楚SBC的休眠流程,否则可能会出现休眠又唤醒情况。后面有空会介绍9471的休眠流程。

赞的博客 811

RT-Thread:flash驱动包 easyflash 移植

1.介绍: EasyFlash是一款开源的轻量级面向嵌入式平台的Flash存储器库,方便开发者更加轻松的实现基于Flash存储器的常见应用开发。非常适合智能家居、可穿戴、工控、医疗等需要断电存储功能的产品,资源占用极低,支持各种 MCU 片上存储器。该库目前提供 三大实用功能: a. Env小型KV数据库,支持写平衡(磨损平衡)及掉电保护模式 让Flash变为NoSQL(非关系型数据库)模型的小型键值(Key-Value)存储数据库。在产品上,能够更加简捷的实现设定参数或运行日

yutian0606的博客 2680

ADS基础教程23 - 有限元电磁仿真(FEM)可视化操作

一、引言 二、FEM可视化操作流程1.打开可视化界面2.查看介质的网格3.设置网格颜色4.选择网格5.传感器选择6.编辑传感器7.选择频率8.动画 三、总结介绍了在ADS中如何进行FEM仿真场视图操作过程。

XZ_ZC的博客 1815

最新Python爬虫实战(入门爬虫篇)——案例7:电影网站电影数据采集(详细爬虫思路截图+抓包动图演示+完整爬虫代码+详细注释)

本次案例通过Python爬虫技术,成功实现了对某电影网站Top250多页电影详细信息的批量爬取与Excel保存。代码采用模块化设计,包含分页请求构造、XPath+正则提取结构化信息、Excel数据持久化保存等完整流程。通过配置User-Agent等请求头信息,有效模拟浏览器行为以绕过豆瓣基础反爬策略。整个爬虫逻辑遵循"分页遍历 → 请求页面 → 解析HTML → 提取电影信息 → 保存到Excel"的标准流程,与主流静态网站爬取范式高度一致。

努力让自己发光,对的人才能迎着光而来 11万+

RT-Thread完整版fal及easyflash移植

最近深圳开始隔离了,居家办公对于我们这种需要做验证仿真的,而家伙都没在手上的打工人太难了。因为最近项目需要用到fal加easyflash软件包,而之前搞过,但是忘记具体的了。还好留有文档,现在也转为文章吧。现在是真的体会到了学了东西没做记录等于白学是什么意思了。 (该移植操作基于stm32f103系列RT-Thread3.1.3) 环境:Keil5,ENV工具,STM32F103VET6,STM32CubeMX,stm32f103_hal_1.7.0 只要会制作BSP模板,都可以根据本文进行移植,同时博

弓长于水的博客 3341

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

EasyFlash——基础原理

是一款开源的轻量级嵌入式Flash存储器库,方便开发者更加轻松的实现基于Flash存储器的常见应用开发。非常适合智能家居、可穿戴、工控、医疗、物联网等需要断电存储功能的产品,资源占用极低,支持各种 MCU 片上存储器。该库主要包括非常适合应用在小型的不带文件系统的产品中,方便开发人员快速定位、查找系统发生崩溃或死机的原因。同时配合(我开源的超轻量级、高性能C日志库,它提供与EasyFlash的无缝接口)一起使用,轻松实现C日志的Flash存储功能。

lijunnanxcx的博客 1446

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

EasyFlash:嵌入式开发者的得力助手

在嵌入式系统开发领域,数据存储和管理一直是开发者面临的挑战之一。今天,我要向大家推荐一个强大的开源项目——EasyFlash,它能够极大地简化嵌入式设备中Flash存储器的使用,提升开发效率。 ## 项目介绍 [EasyFlash](https://github.com/armink/EasyFlash) 是一个开源的轻量级嵌入式Flash存储器库,专为简化基于Flash存储器的应用开发而设计...

gitblog_00771的博客 794

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

【亲测免费】 EasyFlash 开源项目安装和配置指南

EasyFlash 是一个开源的轻量级嵌入式Flash存储器库,主要用于物联网设备的信息存储。它提供了方便的应用接口,帮助开发者更高效地实现基于Flash存储器的常见应用开发。EasyFlash 主要使用 C 语言编写,适用于各种 MCU(微控制单元)平台。 ## 2. 项目使用的关键技术和框架 EasyFlash 项目主要使用了以下关键技术和框架: - **KV存储(Key-Value存储...

gitblog_01215的博客 1037

RT-thread应用讲解——easyflash

在实际的应用中,我们经常需要使用片外flash来保存一些数据,比如设备的一些配置参数,但是如果每个数据都按固定地址和长度读写,就要先把所有数据的地址和长度都分配好,数据量大的话使用起来就很不方便,所以我们需要一个内存管理的应用。 easyflash是一款开源的轻量级嵌入式flash存储器库,方便开发者更加轻松的实现基于flash存储器的常见应用开发。

ShenZhen_zixian的博客 5848
上一篇: STM32 串口升级程序方法说明
下一篇: S19文件格式详解:汽车ECU软件升级中的核心镜像格式
智驾
博客等级 码龄11年 6671粉丝 574原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

智驾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值