【GD32F407】 读写内部flash函数
GD32的flash特征
1、在flash的前512K字节空间内,CPU执行指令零等待;在此范围外,CPU读取指令存在较长延时;
2、对于flash大于1024KB(不包括等于1024KB)的,使用了两片闪存;前1024KB容量在第一片闪存(bank0)中,后续的容量在第二片闪存(bank1)中;
3、对于flash容量小于等于1024KB,只使用了bank0;
4、支持32位整字或16位半字编程,页擦除和整片擦除操作;
GD32 flash内部结构
bank0 内存分布入下
bank1内存分布如下
GD32 flash读函数
flash可以想普通空间一样直接地址访问内存
value = *(volatile u32 *)flash_addr;
u32 IapFlashRead(u32 addr)
{return (*(volatile u32 *)addr);
}
GD32 flash 擦除函数
由于GD32 flash只支持四种擦除模式:整体擦除,bank0擦除,bank1擦除,页擦除,我们在实际读写flash过程中使用最多的还是页擦除
这里我们可以直接调用GD32的库函数进行擦除
/*!\brief erase sector\param[in] fmc_sector: select the sector to erase\arg CTL_SECTOR_NUMBER_0: sector 0 \arg CTL_SECTOR_NUMBER_1: sector 1 \arg CTL_SECTOR_NUMBER_2: sector 2 \arg CTL_SECTOR_NUMBER_3: sector 3 \arg CTL_SECTOR_NUMBER_4: sector 4 \arg CTL_SECTOR_NUMBER_5: sector 5 \arg CTL_SECTOR_NUMBER_6: sector 6 \arg CTL_SECTOR_NUMBER_7: sector 7 \arg CTL_SECTOR_NUMBER_8: sector 8 \arg CTL_SECTOR_NUMBER_9: sector 9 \arg CTL_SECTOR_NUMBER_10: sector 10 \arg CTL_SECTOR_NUMBER_11: sector 11 \arg CTL_SECTOR_NUMBER_12: sector 12 \arg CTL_SECTOR_NUMBER_13: sector 13 \arg CTL_SECTOR_NUMBER_14: sector 14 \arg CTL_SECTOR_NUMBER_15: sector 15 \arg CTL_SECTOR_NUMBER_16: sector 16 \arg CTL_SECTOR_NUMBER_17: sector 17 \arg CTL_SECTOR_NUMBER_18: sector 18 \arg CTL_SECTOR_NUMBER_19: sector 19 \arg CTL_SECTOR_NUMBER_20: sector 20 \arg CTL_SECTOR_NUMBER_21: sector 21 \arg CTL_SECTOR_NUMBER_22: sector 22 \arg CTL_SECTOR_NUMBER_23: sector 23 \arg CTL_SECTOR_NUMBER_24: sector 24 \arg CTL_SECTOR_NUMBER_25: sector 25 \arg CTL_SECTOR_NUMBER_26: sector 26 \arg CTL_SECTOR_NUMBER_27: sector 27 \arg CTL_SECTOR_NUMBER_28: sector 28 \arg CTL_SECTOR_NUMBER_29: sector 29 \arg CTL_SECTOR_NUMBER_30: sector 30 \param[out] none\retval fmc_state_enum
*/
fmc_state_enum fmc_sector_erase(uint32_t fmc_sector)
{fmc_state_enum fmc_state = FMC_READY;/* wait for the FMC ready */fmc_state = fmc_ready_wait();if(FMC_READY == fmc_state){ /* start sector erase */FMC_CTL &= ~FMC_CTL_SN;FMC_CTL |= (FMC_CTL_SER | fmc_sector);FMC_CTL |= FMC_CTL_START;/* wait for the FMC ready */fmc_state = fmc_ready_wait();/* reset the SER bit */FMC_CTL &= (~FMC_CTL_SER);FMC_CTL &= ~FMC_CTL_SN; }/* return the FMC state */return fmc_state;
}
这里我们发现传参是内部定义好的宏,我们只需要将需要写入的地址先进行判断所处页上再将该页进行整体擦除即可,擦除时记得解除flash写保护
/*==============================================================================函数名 : IapGetSecNum功能 : 根据地址得到扇区号输入参数说明: addr: 地址返回值说明 : 扇区号,这里这个函数写的稍微有点复杂了
------------------------------------------------------------------------------*/
static uint32_t IapGetSecNum (uint32_t addr)
{if((addr >= ADDR_FLASH_SECTOR_0) && (addr < ADDR_FLASH_SECTOR_1))return 0;else if((addr >= ADDR_FLASH_SECTOR_1) && (addr < ADDR_FLASH_SECTOR_2))return 1;else if((addr >= ADDR_FLASH_SECTOR_2) && (addr < ADDR_FLASH_SECTOR_3))return 2;else if((addr >= ADDR_FLASH_SECTOR_3) && (addr < ADDR_FLASH_SECTOR_4))return 3;else if((addr >= ADDR_FLASH_SECTOR_4) && (addr < ADDR_FLASH_SECTOR_5))return 4;else if((addr >= ADDR_FLASH_SECTOR_5) && (addr < ADDR_FLASH_SECTOR_6))return 5;else if((addr >= ADDR_FLASH_SECTOR_6) && (addr < ADDR_FLASH_SECTOR_7))return 6;else if((addr >= ADDR_FLASH_SECTOR_8) && (addr < ADDR_FLASH_SECTOR_9))return 8;else if((addr >= ADDR_FLASH_SECTOR_9) && (addr < ADDR_FLASH_SECTOR_10))return 9;else if((addr >= ADDR_FLASH_SECTOR_11) && (addr < ADDR_FLASH_SECTOR_12))return 11;else if((addr >= ADDR_FLASH_SECTOR_12) && (addr < ADDR_FLASH_SECTOR_13))return 12;else if((addr >= ADDR_FLASH_SECTOR_13) && (addr < ADDR_FLASH_SECTOR_14))return 13;else if((addr >= ADDR_FLASH_SECTOR_14) && (addr < ADDR_FLASH_SECTOR_15))return 14;return 0;}/*==============================================================================函数名 : IapEraseSector功能 : 擦除相关扇区输入参数说明: addr_start: 起始地址addr_end: 结束地址
------------------------------------------------------------------------------*/
fmc_state_enum IapEraseSector(uint32_t addr_start, uint32_t addr_end)
{printf("erase\r\n");uint32_t start_sec, end_sec;uint32_t i = 0;start_sec = IapGetSecNum(addr_start);end_sec = IapGetSecNum(addr_end);fmc_unlock(); //解锁flash保护for(i = start_sec; i <= end_sec; i++){if((i >= 12) && (i <= 23)){if((fmc_sector_erase(CTL_SN(i + 4))) != FMC_READY){return FMC_WPERR;}}else if((i >= 24) && (i <= 27)){if((fmc_sector_erase(CTL_SN(i - 12))) != FMC_READY){return FMC_WPERR;}}else{if((fmc_sector_erase(CTL_SN(i))) != FMC_READY){return FMC_WPERR;}}}fmc_luck(); //flash上锁return FMC_READY;
}
GD32 flash写函数
在写入数据时,需要先调用擦除函数进行页的擦除,关于写flash的函数,GD32提供了3个格式的写入分别时32位整字写入,16位半字写入,8位字节写入,这里我们采用32位整字写入
#define IAP_FLASH_PAGE_SIZE 4
/*==============================================================================函数名 : IapFlashWrite功能 : 写入FLASH输入参数说明: dwAddr: 写入Flash的起始地址, 从0开始的偏移地址dwLen : 写入数据的字节数pbyBuf: 写入数据的buf, 地址必须4字节对齐返回值说明 : 成功返回0; 失败返回-1或错误码
------------------------------------------------------------------------------*/
s32 IapFlashWrite(u32 dwAddr, u32 dwLen, u8 *pbyBuf)
{fmc_state_enum tRtn;/* 写入数据的字节数,必须是4字节,即一个page的大小,不足则补齐 */if (dwLen % IAP_FLASH_PAGE_SIZE){dwLen = (dwLen / IAP_FLASH_PAGE_SIZE + 1) * IAP_FLASH_PAGE_SIZE;}if (((u32)pbyBuf) % 4)return -4;fmc_unlock();while (dwLen){fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR | \FMC_FLAG_PGMERR | FMC_FLAG_PGSERR);tRtn = fmc_word_program(dwAddr, *(u32 *)pbyBuf);if (tRtn != FMC_READY){IAP_ERR("failed, rtn=%d\n", tRtn);return -5;}dwAddr += IAP_FLASH_PAGE_SIZE;pbyBuf += IAP_FLASH_PAGE_SIZE;dwLen -= IAP_FLASH_PAGE_SIZE;}fmc_lock(); return 0;
}
【GD32F407】 读写内部flash函数相关推荐
- STM32F4读写内部FLASH【使用库函数】
STM32F4Discovery开发帮使用的STM32F407VGT6芯片,内部FLASH有1M之多.平时写的代码,烧写完之后还有大量的剩余.有效利用这剩余的FLASH能存储不少数据.因此研究了一下S ...
- 第50章 读写内部FLASH—零死角玩转STM32-F429系列
第50章 读写内部FLASH 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fire ...
- STM32学习笔记:读写内部Flash。
首先我们需要了解一个内存映射: stm32的flash地址起始于0x0800 0000,结束地址是0x0800 0000加上芯片实际的flash大小,不同的芯片flash大小不同. RAM起始地 ...
- STM32学习笔记:读写内部Flash(介绍+附代码)
一.介绍 首先我们需要了解一个内存映射: stm32的flash地址起始于0x0800 0000,结束地址是0x0800 0000加上芯片实际的flash大小,不同的芯片flash大小不同. RAM起 ...
- STM32读写内部flash
概念:计算机中最小的信息单位是bit,也就是一个二进制位,8个bit组成一个Byte,也就是1个字节, 1个存储单元存放1个字节,每个存储单元对应一个32位(bit)地址,所以重要的话说三遍:对于32 ...
- STM32读写内部Flash(介绍+附代码)
概述 内部flash读写详解 一.介绍 首先我们需要了解一个内存映射: stm32的flash地址起始于0x0800 0000,结束地址是0x0800 0000加上芯片实际的flash大小,不同的芯片 ...
- STM32学习笔记:读写内部FLASH
ST提供的库函数基本能搞定 简介 由于 FLASH 存储器的内容在掉电后不会丢失,芯片重新上电复位后,内核可从内部 FLASH 中加载代码并运行,亦可当做EEROM来使用保存所需要的数据,以便下次启用 ...
- STM32F103 读写内部FLASH—学习笔记(野火)
STM32F103的Flash类型是NOR Flash 烧录过程:调试器→STM32的SRAM→运行→Flash 内部Flash比外部Flash更高效,原因是使用了内部总线,且工作频率是72MHz 2 ...
- 图文介绍STM32L4读写内部flash
型号:STM32L431KBU6: 该型号内存 = 128KB,起始地址 = 0x0800_0000;只有63页: 在L4的user manual手册的第三章详细介绍了FLASH的操作细节,我挑一些重 ...
- 【dsPIC33E】内部Flash读写
基于某些安全考虑或者降成本,我们不希望使用外部存储器件,但有时我们由需要记录一下参数,确保断电不丢失,这时,富余的内部代码存储Flash就派上用场了. 不同于外部存储器,几乎所有的内部Flash读写都 ...
最新文章
- 前谷歌工程师:如何看待程序员普遍缺乏数据结构和算法知识?
- Linux与win2003下修改mac地址方法
- Python+selenium 自动化-切换窗口页签、切换iframe框架。确定页面是否包含iframe方法。
- 你需要XXX的权限对此文件(此文件夹进行)修改
- java nginx 例子_Nginx配置日志
- 堆元素插入 二叉堆一般用数组来表示。typedef struct _otherInfo{ int i; int j;}OtherInfo;-icoding-C-数据结构
- 京东布局消费物联网 聚合产业链共建生态
- Python logging模块切分和轮转日志
- 数据:以太坊2.0存款合约新增9.4万ETH
- 对“优秀工程师”的一点感悟
- Microsoft Deployment Toolkit build 8456
- 基于WebRTC搭建直播系统源码
- 英雄联盟加载的时候特卡,排查记录:win10那些破玩意
- 计算机系统还原后 桌面不显示图标,电脑桌面图标不见了怎么恢复原状?电脑桌面便签不见了怎么找回...
- 百度地图结合echarts实现飞线
- 20155232《网络对抗》 Exp1 PC平台逆向破解(5)M
- 大白话解析Context中的cancelCtx
- 英语天天秀(2007/06/16) -- 老美口头禅
- Linux磁盘清理策略
- 你了解CPU吗?(三)