gd32f103 的flash操作

1.定义扇区大小

/*对于主存储闪存容量不多于512KB的GD32F10x_CL和GD32F10x_HD,只使用了bank0;对 于 GD32F10x_MD , 闪 存 页 大 小 为 1KB 。GD32F10x_CL 和 GD32F10x_HD ,GD32F10x_XD, bank0的闪存页大小为2KB, bank1的闪存页大小为4KB;
*/
/*页大小*/
#define FMC_PAGE_SIZE           ((uint16_t)0x400U)

2.读取flash

/*读取flash数据,函数内部做了4字节对齐操作
*/
void read_4Btye(uint32_t read_addr, uint32_t *data, uint32_t len)
{int dest_addr;dest_addr = read_addr & 0xfffffffc;//4字节对齐dest_addr += read_addr & 0x03 > 0 ? 4 : 0;int real_len = len >> 2;uint32_t *addr = (uint32_t*)dest_addr;for(int i = 0; i < real_len; i++){*(data + i) = *(addr + i);}
}

4.检测flash是否需要擦除

/*检查是否需要擦除页addr:待检查页起始地址*/
int check_ease(int start_addr )
{//指着类型转换uint32_t *addr = (uint32_t*)start_addr;for(int i = 0; i<FMC_PAGE_SIZE >> 2; i++){if(*(addr + i) != 0xffffffff){return 1;}}return 0;
}

5.擦除需要使用的扇区,并保存扇区前半部分没有使用的部分

/*擦除需要使用的扇区,并保存扇区前半部分没有使用的部分
*/
void ease_flash(uint32_t write_addr, int page_num)
{int i = 0;//当前页的偏移地址uint32_t page_offset = write_addr & (FMC_PAGE_SIZE - 1);page_offset = page_offset >> 2; //换算为4字节//页起始地址uint32_t start_addr  = write_addr & (0xffffffff - FMC_PAGE_SIZE + 1);//指着类型转换uint32_t *addr = (uint32_t*)start_addr;uint32_t *buff = (uint32_t*)malloc(FMC_PAGE_SIZE);//将不操作的空间保存起来if(page_offset){for( i = 0; i < page_offset; i++){buff[i] = *(addr + i);}}uint32_t erase_counter;/* 解锁flash */fmc_unlock();//清除操作结束标志fmc_flag_clear(FMC_FLAG_BANK0_END);//清除擦除/错误标志fmc_flag_clear(FMC_FLAG_BANK0_WPERR);//清楚页编程错误标志fmc_flag_clear(FMC_FLAG_BANK0_PGERR);/* 擦除使用到的页 */for(erase_counter = 0; erase_counter < page_num; erase_counter++){//擦除指定的页,参数页地址if(check_ease(start_addr + FMC_PAGE_SIZE * erase_counter)){fmc_page_erase(start_addr + FMC_PAGE_SIZE * erase_counter);fmc_flag_clear(FMC_FLAG_BANK0_END);fmc_flag_clear(FMC_FLAG_BANK0_WPERR);fmc_flag_clear(FMC_FLAG_BANK0_PGERR);}}//写入扇区前半部分没有使用的空间if(page_offset){for( i = 0; i < page_offset; i++){//对flash编程,也就是写数据,每次写入1个字=4个字节fmc_word_program(start_addr + (i * 4), *(buff + i));fmc_flag_clear(FMC_FLAG_BANK0_END);fmc_flag_clear(FMC_FLAG_BANK0_WPERR);fmc_flag_clear(FMC_FLAG_BANK0_PGERR);}}/* flash加锁,禁止编程 */fmc_lock();free(buff);
}

6.写入flash任意长度的数据数据,函数内部做了4字节对齐操作

/*写入flash任意长度的数据数据,函数内部做了4字节对齐操作
*/void write_flash(uint32_t write_addr, uint32_t *data, int len)
{int dest_addr;dest_addr = write_addr & 0xfffffffc;//4字节对齐dest_addr += write_addr & 0x03 > 0 ? 4 : 0;uint32_t page_num = len / FMC_PAGE_SIZE; //存放数据需要的扇区大小page_num += len % FMC_PAGE_SIZE ? 1 : 0;////擦除扇区ease_flash(dest_addr, page_num);int len_4Byte = len >> 2;/* 解锁 */fmc_unlock();for(int i = 0; i < len_4Byte; i++){//对flash编程,也就是写数据,每次写入1个字=4个字节fmc_word_program(dest_addr + i * 4, *(data + i));fmc_flag_clear(FMC_FLAG_BANK0_END);fmc_flag_clear(FMC_FLAG_BANK0_WPERR);fmc_flag_clear(FMC_FLAG_BANK0_PGERR);}/* 加锁*/fmc_lock();}

7.测试例程

uint8_t write[2300];
uint8_t read[2300];
int flash_test(void)
{for(int i = 0; i < 2300; i++){write[i] = i % 256;}write_flash(0x800400c, (uint32_t*)write, 2300);read_4Btye(0x800400c, (uint32_t*)read, 2300);for(int i = 0; i < 2300; i++){if(write[i] != read[i]){printf("write error %d\r\n", i);return 0;}}printf("write ok \r\n");return 1;
}

8. 测试结果

21. GD32F103C8T6入门教程-flash/fmc连续读写操作相关推荐

  1. Apollo Control——超详细入门教程(二):连续状态空间方程离散化与离散LQR公式推导

    专栏文章列表 Apollo Control--超详细入门教程(一):基于道路误差的车辆动力学模型 Apollo Control--超详细入门教程(二):连续状态空间方程离散化与离散LQR公式推导 Ap ...

  2. R语言七天入门教程六:文件相关操作

    R语言七天入门教程六:文件相关操作 一.文件的读写 R 语言作为统计学编程语言,常常需要处理大量数据,而这些数据通常会从文件中进行读取,因此文件读写在R语言中是非常重要的操作.在R语言中,用到最多的文 ...

  3. 24. GD32F103C8T6入门教程-IAP升级教程

    GD32f103C8T6 IAP 升级教程 参考stm32的IAP升级原理 IAP测试源码 GD32和stm32的内核都是一样的,又因为IAP升级主要涉及升级的路径之和内核先关,所以gd32和stm3 ...

  4. 17. GD32F103C8T6入门教程-adc 使用教程2-dma+连续扫描方式采集数据++dma中断通知

    adc 使用教程3-dma方式采集数据+dma中断通知 adc 的扫描模式就是把配置了规则或注入通道按照配置的顺序采集一轮 adc 的连续转换模式就是把配置了规则或注入通道按照配置的顺序采集N轮 1. ...

  5. 16. GD32F103C8T6入门教程-adc 使用教程2-dma+连续扫描方式采集数据

    adc 使用教程2-dma+连续扫描方式采集数据 adc 的扫描模式就是把配置了规则或注入通道按照配置的顺序采集一轮 adc 的连续转换模式就是把配置了规则或注入通道按照配置的顺序采集N轮 1.时钟配 ...

  6. 20. GD32F103C8T6入门教程-adc使用外部中断IT11触发启动adc规则通道,使用外中断IT15触发注入组

    adc 使用教程6-使用外部中断IT11触发启动adc规则通道,使用外中断IT15触发注入组 ADC支持18个多路通道,可以把转换组织成两组:一个规则组通道和一个注入组通道 规则组,可以按照特定的序列 ...

  7. FLASH与ASP通信入门教程(四) ASP操作数据库入门

    经过前几节的学习,我们对LV类和ASP的输入输出应该已经很熟练了吧,而且我们也已经了解了LV与ASP通讯的基本原理.这个原理可能并不复杂,不过如果你想利用它做出点东西来,关键还是要看你ASP和FLAS ...

  8. 19. GD32F103C8T6入门教程-adc使用教程6-外部中断线11触发adc0

    adc 使用教程6-外部中断线11触发adc0 使用外部中断线11 触发ADC开始采集数据,PA11 gpio 1.初始化时钟和定义全局变量 /*保存ADC值*/ uint32_t adc_value ...

  9. 18. GD32F103C8T6入门教程-adc-使用教程5-定时器TIM2更新事件触发adc0

    adc 使用教程5-定时器TIM2更新事件触发adc0 但是本实验出现了一个异常,单片机大概路出现更新事件没有启动ADC转换,可是没有找到处理办法,但是定时器的是正常工作LED灯闪烁 1.使能各种时钟 ...

最新文章

  1. SAP MM 执行事务代码MRRL报错-No message was found for partner 100065 company code 0001-
  2. Latex 设置文字大小
  3. word使用技巧(不定时更新)
  4. 前端学习(3071):vue+element今日头条管理-删除文章失败
  5. (JAVA)Integer类之基本数据类型之间的转换
  6. 中科大 计算机网络13 FTP文件传输协议
  7. .net core 正则表达式 获取 等号后面的值_Python3 正则表达式
  8. js压缩文件或文件夹
  9. 组成原理之全加器实验
  10. android 自定义锁屏api,如何设置Android锁屏图像
  11. oracle如何禁用job,Oracle中如何停用JOB及如何使用JOB
  12. Spring错误——Spring 注解——factory-bean reference points back to the same bean definition
  13. 照相机的计算机微处理器芯片是什么,芯片到底是什么?
  14. 2020年网络安全国赛解析(仅个人想法)
  15. oppofindx5pro评测
  16. 城市“智慧发展”的核心是人性化
  17. 开源之夏 2022 重磅来袭,欢迎报名 Casbin社区项目
  18. ICLR'22上的47页“神仙论文” | 子图聚合图神经网络
  19. cocos2dx3.17.2之梦幻西游开发日志(三)
  20. Android Studio 用USB连接到真机调试方法

热门文章

  1. oracle varchar2() 占几个字母,Oracle number date varchar2字段类型占用空间大小
  2. 自定义oracle异常,详解Oracle自定义异常示例
  3. php 滑动 图片,JQuery图片滑动
  4. GP学习(四)—Running a geoprocessing tool using background geoprocessing
  5. php手册学习怎样,PHP新手之如何学习PHP的讲解
  6. 学习Spring Security
  7. 使用pyLDAvis可视化LDA结果,与解决FileNotFoundError: [Errno 2] No such file or directory: ‘https://cdn.jsdel....
  8. python在原有的字符串的基础上追加列表构成的字符串,并保持格式一致
  9. 可行性研究和软件项目计划主要完成什么工作?_软件生命周期
  10. collapse用法