EasyFlash在GD32F303CC上面的移植

记录学习的过程,如果在GD32F303CC上面移植EasyFlash。关于EasyFlash的相关介绍和源码,请参考:https://gitee.com/Armink/EasyFlash 或者 https://github.com/armink/EasyFlash

主要记录移植过程中需要注意的点,移植还是比较简单的。基本就是填充几个宏定义和FLASH的操作函数即可。

一、下载源码、添加源码和头文件到工程中

这里就不具体展开了。作者给的文档有很详细,我就不复制搬运了,贴两张图片就好。

 二、根据芯片FLASH参数修改宏定义

 主要是修改ef_cfg.h文件。GD32F303CC用于手册里面的描述,可以知道一个页大小为2KB,支持编程写入16bit或者32bit。

基本修改的宏定义如下,具体含义参考注释。

/* The minimum size of flash erasure. May be a flash sector size. */
// 芯片FLASH的扇区大小或者说页大小 查询手册我使用芯片页大小为2K
#define EF_ERASE_MIN_SIZE       2048  /* @note you must define it for a value */  //2k
/* the flash write granularity, unit: bit
 * only support 1(nor flash)/ 8(stm32f4)/ 32(stm32f1) */
// FLASH支持的写入bit位数   查询手册 支持16bit和32bit 但是EasyFlash不支持 16bit
#define EF_WRITE_GRAN         32    /* @note you must define it for a value */
/* backup area start address */
// 使用内部FLASH来存储 存储的起始地址为 0x0803F000,即从252KB开始储存
#define EF_START_ADDR      0x0803F000       /* @note you must define it for a value */
/* ENV area size. It's at least one empty sector for GC. So it's definition must more then or equal 2 flash sector size. */
// 用来存储的空间大小 4KB  即从252~256KB
#define ENV_AREA_SIZE      (EF_ERASE_MIN_SIZE * 2)       /* @note you must define it for a value if you used ENV */
/* print debug information of flash */
// 宏定义开启串口调试输出
#define PRINT_DEBUG   1

三、接口移植

集中在ef_port.c文件下。主要需要完成,对FLASH读、写、擦除、加锁以及初始化等操作的接口。接口GD32固件库里面对FLASH操作的demo和EasyFlash提供的移植demo,依葫芦画瓢即可。

GD32固件库中关于FLASH操作demo(具体上GD32官网下载即可):

EasyFlash提供的移植demo:

最后附上自己修改的接口函数代码,注意的一点就是在RTOS和裸机上面采用的保护是不同的,RTOS直接利用了二值信号量,裸机直接关中断。

/* 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"},
};

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]);
		
	//如果使用了 RTOS 一般会在这里初始化信号量  rt_sem_init(&env_cache_lock, "env lock", 1, RT_IPC_FLAG_PRIO);
    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;
    /* You can add your code under here. */
    /*copy from flash to ram */
    for (i = 0; i < size; i++, addr++, buf_8++)
    {
        *buf_8 = *(uint8_t *)addr;
    }
    return result;
}

EfErrCode ef_port_erase(uint32_t addr, size_t size)
{
    EfErrCode result = EF_NO_ERR;
    fmc_state_enum flash_status;
    size_t erase_pages, i;

    /* 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. */

    /* calculate pages */
    erase_pages = size / EF_ERASE_MIN_SIZE;
    if (size % EF_ERASE_MIN_SIZE != 0)
    {
        erase_pages++;
    }

    /* start erase */
    fmc_unlock();

    /* clear all pending flags */
    fmc_flag_clear(FMC_FLAG_BANK0_END);
    fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
    fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
    // 一个扇区一个扇区的擦除
    for (i = 0; i < erase_pages; i++)
    {
        flash_status = fmc_page_erase(addr + (EF_ERASE_MIN_SIZE * i));
        fmc_flag_clear(FMC_FLAG_BANK0_END);
        fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
        fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
        if (flash_status != FMC_READY)
        {
            result = EF_ERASE_ERR;
            break;
        }
    }
    fmc_lock();

    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. */
    size_t i;
    uint32_t read_data;

    /* unlock the flash program/erase controller */
    fmc_unlock();
    fmc_flag_clear(FMC_FLAG_BANK0_END);
    fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
    fmc_flag_clear(FMC_FLAG_BANK0_PGERR);

    for (i = 0; i < size; i += 4, buf++, addr += 4)
    {
        /* write data */
        fmc_word_program(addr, *buf);
        read_data = *(uint32_t *)addr;

        fmc_flag_clear(FMC_FLAG_BANK0_END);
        fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
        fmc_flag_clear(FMC_FLAG_BANK0_PGERR);

        /* check data */
        if (read_data != *buf)
        {
            result = EF_WRITE_ERR;
            break;
        }
    }
    /* lock the main FMC after the program operation */
    fmc_lock();

    return result;
}

void ef_port_env_lock(void)
{

    /* You can add your code under here. */
    // TODO:这里根据实际情况来判断
    // 如果是裸机就直接关中断
    __disable_irq();
    // 如果RTOS利用互斥量  rt_sem_take(&env_cache_lock, RT_WAITING_FOREVER);
}

void ef_port_env_unlock(void)
{

    /* You can add your code under here. */
    // TODO:这里根据实际情况来判断
    // 如果是裸机就直接开中断
    __enable_irq();
    // 如果RTOS利用互斥量    rt_sem_release(&env_cache_lock);
}



 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring 事务和事务传播机制

✏️作者&#xff1a;银河罐头 &#x1f4cb;系列专栏&#xff1a;JavaEE &#x1f332;“种一棵树最好的时间是十年前&#xff0c;其次是现在” 目录 Spring 中事务的实现Spring 编程式事务Spring 声明式事务Transactional 作⽤范围Transactional 参数说明Spring 事务隔离级别…

[State of GPT] OpenAI讲座随笔记

原版&#xff1a;State of GPT B站翻译版&#xff1a;【精校版】Andrej Karpathy微软Build大会精彩演讲&#xff1a; GPT状态和原理 - 解密OpenAI模型训练 1 GPT Training Pipeline图解 记录一下对这个图的理解&#xff1a; 大模型训练的四个阶段&#xff1a; Pretraining 阶…

【深入了解Spring Cloud Alibaba Nacos:服务注册和配置中心】—— 每天一点小知识

&#x1f4a7; 深入了解 S p r i n g C l o u d A l i b a b a N a c o s &#xff1a;服务注册和配置中心 \color{#FF1493}{深入了解Spring Cloud Alibaba Nacos&#xff1a;服务注册和配置中心} 深入了解SpringCloudAlibabaNacos&#xff1a;服务注册和配置中心&#x1f4a7;…

带你用Python制作一个经典必收藏的游戏:地铁跑酷(含完整代码)

名字&#xff1a;阿玥的小东东 学习&#xff1a;Python、C/C 主页链接&#xff1a;阿玥的小东东的博客_CSDN博客-python&&c高级知识,过年必备,C/C知识讲解领域博主 目录 一、游戏简介 二、游戏设计 引入必要的库 初始化游戏 定义游戏元素 定义游戏循环 更新游戏…

Qt QGraphicsScene、QGraphicsView类实现仪表盘

Qt QGraphicsScene、QGraphicsView类实现仪表盘 【1】UI界面设计【2】效果【3】QGraphicsScene简介【4】QGraphicsEllipseItem简介【5】QGraphicsPolygonItem简介【6】QGraphicsLineItem简介【7】QGraphicsView简介【8】仪表源码头文件源码 【1】UI界面设计 【2】效果 【3】QGr…

caffeine和google-guava cache缓存使用详解和源码介绍

google-guava cache 1.pom引入其依赖 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>20.0</version></dependency> 2.具体使用 com.google.common.cache.LoadingCache<Strin…

leetcode题集训 sql

目录 背景步骤175组合两个表&#xff08;多表联查&#xff09;176 177 第n高的薪水&#xff08;Distinct关键字 排序&#xff09;178分数排名 &#xff08;排序 order over关键字&#xff09;179 连续出现的数字 &#xff08;模拟多张表联查&#xff09;181. 超过经理收入的员工…

TCP/IP协议是什么?

78. TCP/IP协议是什么&#xff1f; TCP/IP协议是一组用于互联网通信的网络协议&#xff0c;它定义了数据在网络中的传输方式和规则。作为前端工程师&#xff0c;了解TCP/IP协议对于理解网络通信原理和调试网络问题非常重要。本篇文章将介绍TCP/IP协议的概念、主要组成部分和工…

Elasticsearch:使用 SIMD 指令加速向量搜索

作者&#xff1a;Chris Hegarty, Elastic Principal Engineer, Lucene PMC 翻译&#xff1a;杰瑞朱 多年来&#xff0c;Java 平台上运行的代码一直受益于自动向量化 —— HotSpot C2 编译器中的 superword 优化&#xff0c;将多个标量操作打包到 SIMD&#xff08;单指令多数据…

Git:git merge和git rebase的区别

分支合并 git merge是用来合并两个分支的。比如&#xff1a;将 b 分支合并到当前分支。同样git rebase b&#xff0c;也是把 b 分支合并到当前分支。他们的 「原理」如下&#xff1a; 假设你现在基于远程分支"origin"&#xff0c;创建一个叫"mywork"的分支…

【react全家桶学习】react的 (新/旧) 生命周期(重点)

目录 生命周期&#xff08;旧&#xff09; 挂载时的生命周期 constructor&#xff08;props&#xff09; componentWillMount&#xff08;&#xff09;-------------新生命周期已替换 render&#xff08;&#xff09; componentDidMount&#xff08;&#xff09;--- 组件…

PACS/RIS医学影像管理系统源码 提供先进图像处理和算法

PACS&#xff08;医学影像存档与通信系统&#xff09;主要应用于医学影像的存储、传输和显示。它可以使医生突破胶片的局限&#xff0c;对病人的影像进行全方位的处理和观察&#xff0c;以便得出更准确的诊断。同时&#xff0c;PACS可以节省大量的胶片&#xff0c;降低成本。医…

flex布局瀑布流占位两边对齐不对称

.page{display: flex;justify-content: space-between;flex-wrap: wrap; }.page:after {content: ;width: 400px; // 也可以 flex:1}

jmeter:BeanShell预处理程序获取/设置/引用变量

BeanShell预处理程序 1、局部变量 获取局部变量&#xff1a;vars.get("变量名") 设置局部变量&#xff1a;vars.put("变量名",变量值) 调用 ${变量名} 2、全局变量 获取局部变量&#xff1a;props.get("变量名") 设置局部变量&#xff1a…

KNIME工作流和节点比较功能

KNIME工作流和节点比较功能是一个在 << KNIME 视觉化数据分析 >> 中没有讲到的知识点。 KNIME工作流和节点比较功能在以下几种情况下非常有用&#xff1a; 版本控制&#xff1a;此功能可以跟踪工作流和节点中的更改。如果需要返回到之前的工作流或节点版本&#xf…

Vscode platformio Arduino开发STM32,点灯+串口调试

1.工具 USB-TTL(非常便宜&#xff0c;几块钱)STM32F103C8T6(几块钱) 2.引脚连线 USB-TTLSTM32TXPA10RXPA9VCC3.3VGNDGND 注意事项&#xff1a; 跳线帽位置&#xff1a;BOOT0接高电平(1)&#xff0c;BOOT1接低电平(0)每次上传程序前需要按一下复位键(之后&#xff0c;跳线帽…

2020年全国硕士研究生入学统一考试管理类专业学位联考逻辑试题——纯享题目版

&#x1f3e0;个人主页&#xff1a;fo安方的博客✨ &#x1f482;个人简历&#xff1a;大家好&#xff0c;我是fo安方&#xff0c;考取过HCIE Cloud Computing、CCIE Security、CISP等证书。&#x1f433; &#x1f495;兴趣爱好&#xff1a;b站天天刷&#xff0c;题目常常看&a…

Nginx SSL使用自制证书

1. 生成证书 keytool -genkey -v -alias <Alias别名> -keyalg RSA -keystore <KeyStore文件> -validity <有效期> keytool -genkey -v -alias nginx -keyalg RSA -keystore nginx.keystore -validity 36500 alias别名为 nginxkeystore文件为 nginx.keystore…

【Nginx】第七章 Nginx原理与优化参数配置

7.1 Nginx原理 master-workers的机制的好处 首先&#xff0c;对于每个worker进程来说&#xff0c;独立的进程&#xff0c;不需要加锁&#xff0c;所以省掉了锁带来的开销&#xff0c;同时在编程以及问题查找时&#xff0c;也会方便很多。 其次&#xff0c;采用独立的进程&…

第11节 跟上板块轮动的节奏

板块 文章目录 板块什么是板块板块的分类板块的轮动 板块相关接口本节课任务 什么是板块 股票板块是一些具有相同特征的股票的集合&#xff0c;命名通常也会简单明了的直接按照特征命名。例如沪深300板块&#xff0c;蓝筹板块。对上市公司进行“分班”不论是对于企业还是对于投…