HC32 flash 读写操作
flash 读写操作
- HC32 flash 简介
- HC32 flash 操作和时钟之间的关系
- Flash 的读写操作
- 解锁寄存器
- 单次编程无回读功能
- 单编程有回读
- 连续编程
- 擦除功能
- 全擦除功能
- 综合应用demo
HC32 flash 简介
HC32F4A0 的flash是两块独立 FLASH 构成 dual bank。容量高2Mbytes,由两块 1Mbytes 的 FLASH 构成,共 256 个扇区,每个扇区为8Kbytes。 块 0 中扇区 0~扇区 15 为可配置为 OTP 区域。
- OTP(One Time Program)区域共 134KBytes, 其中 128Kbytes 配置在块 0 地址0x0000_0000~0x0001_FFFF, 6Kbytes 配置在地址 0x0300_00000x0300_17FF。地址0x0300_18000x0300_1AD7 为 OTP 数据锁存区。
- 编程单位为 4bytes,擦除单位为 8Kbytes
+
HC32 flash 操作和时钟之间的关系
要正确读取 FLASH 数据,用户需要根据 CPU 动作频率在 FLASH 读模式寄存器
(EFM_FRMC)中正确设定等待周期数(FLWT[3:0])。具体可以参照下表进行相关设置。
对应相关处理在flash 初始化的时候,更改stc_efm_cfg_t结构体中的u32waitcycle.
eg
int Init(void)
{/** Clock <= 40MHZ EFM_WAIT_CYCLE_0* 40MHZ < Clock <= 80MHZ EFM_WAIT_CYCLE_1* 80MHZ < Clock <= 120MHZ EFM_WAIT_CYCLE_2* 120MHZ < Clock <= 160MHZ EFM_WAIT_CYCLE_3* 160MHZ < Clock <= 200MHZ EFM_WAIT_CYCLE_4* 200MHZ < Clock <= 240MHZ EFM_WAIT_CYCLE_5*/stc_efm_cfg_t stcEfmCfg;en_int_status_t flag1;en_int_status_t flag2;//解锁对应的寄存器UnLock_Flash();EFM_StructInit(&stcEfmCfg); //初始化结构体//stcEfmCfg.u32BusStatus = EFM_BUS_RELEASE; /* Bus release while programming or erasing */stcEfmCfg.u32WaitCycle = EFM_WAIT_CYCLE_5; // 5-wait @ 240MHz EFM_Init(&stcEfmCfg); // 初始化do{flag1 = EFM_GetFlagStatus(EFM_FLAG_RDY0);flag2 = EFM_GetFlagStatus(EFM_FLAG_RDY1);}while((Set != flag1) || (Set != flag2)); // 等待flash0 和 flash1 准备就绪/* 加锁所有扇区 */Lock_Flash();return 0;
}
Flash 的读写操作
FLASH 支持编程,扇区擦除,全擦除操作。FLASH 编程,扇区/全擦除地址末位必须以 4 对齐(末位地址为: 0x0, 0x4, 0x8, 0xC),编程单位是 4bytes, 扇区擦除单位为 8Kbytes,全擦除根据寄存器设定可以是单个 FLASH块也可是两个 FLASH 块。 FLASH 编程方式分为单次编程无回读模式,单次编程回读模式,连续编程模式三种。 FLASH 编程,擦除期间,设定 EFM_FWMC.BUSHLDCTL=0,则总线被占有,直至擦写结束; EFM_FWMC.BUSHLDCTL=1, 则总线被释放,总线可以继续访问另一块 FLASH 地址。 FLASH 编程,擦除前,请把缓存使能及预取指无效。
解锁寄存器
复位解除后, FLASH 编程,擦除模式寄存器( EFM_FWMC)处于写禁止状态,需要先解除 FLASH 访问保护寄存器( EFM_FAPRT),然后再解除 EFM_KEY1 的保护.
- 解除 FLASH 寄存器访问写保护(EFM_FAPRT 先写 0x0123, 再写 0x3210)
- 解除 EFM_KEY1 锁定(EFM_KEY1 先写 0x01234567, 再写 0xFEDCBA98)
对应的库函数为EFM_Unlock(),EFM_FWMC_Unlock();在调用的时候一定是先EFM_Unloc() 后EFM_FWMC_Unlock;
单次编程无回读功能
单编程有回读
eg
int32_t main(void)
{stc_efm_cfg_t stcEfmCfg;en_int_status_t flag1;en_int_status_t flag2;uint32_t u32Data = 0xAA5555AAU;uint32_t u32Addr;/* Unlock peripherals or registers */Peripheral_WE();/* Configure system clock. HClK = 240MHZ */BSP_CLK_Init();/* EFM default config. */(void)EFM_StructInit(&stcEfmCfg);/** Clock <= 40MHZ EFM_WAIT_CYCLE_0* 40MHZ < Clock <= 80MHZ EFM_WAIT_CYCLE_1* 80MHZ < Clock <= 120MHZ EFM_WAIT_CYCLE_2* 120MHZ < Clock <= 160MHZ EFM_WAIT_CYCLE_3* 160MHZ < Clock <= 200MHZ EFM_WAIT_CYCLE_4* 200MHZ < Clock <= 240MHZ EFM_WAIT_CYCLE_5*/stcEfmCfg.u32WaitCycle = EFM_WAIT_CYCLE_5;/* EFM config */(void)EFM_Init(&stcEfmCfg);/* Wait flash0, flash1 ready. */do{flag1 = EFM_GetFlagStatus(EFM_FLAG_RDY0);flag2 = EFM_GetFlagStatus(EFM_FLAG_RDY1);}while((Set != flag1) || (Set != flag2));/* Sector 10 disables write protection */(void)EFM_SectorCmd_Single(EFM_SECTOR_10, Enable);/* Erase sector 10. sector 10: 0x00014000~0x00015FFF */(void)EFM_SectorErase(EFM_ADDR_SECTOR10);u32Addr = EFM_ADDR_SECTOR10;//单个字节写if(Ok != EFM_SingleProgram(u32Addr, u32Data)){dosomething();}//写后回读if(Ok != EFM_ProgramReadBack(u32Addr + sizeof(u32Data), u32Data)){dosomething();}EFM_SectorCmd_Single(EFM_SECTOR_10, Disable);Peripheral_WP();for (;;){;}
}
连续编程
连续编程模式中特别要注意5步骤,连续编程不可以在程序运行的flash上进行,即如果程序运行在flash0 块上,只能在flash1 上进行连续编程。不然程序会死在EFM_SequenceProgram()中。
擦除功能
- 解除 FLASH 的寄存器写保护(EFM_FAPRT 先写 0x0123, 再写 0x3210)。
- 解除 EFM_KEY1 锁定。 (EFM_KEY1 先写 0x01234567, 再写 0xFEDCBA98)
- 设定擦除模式(EFM_FWMC.PEMOD[2:0]=100)。
- 解除写保护。 (EFM_ F0/1NWPRTx(x=0~3)对应位设定为 1)
- 对需要擦除扇区内的任意地址(地址需以 4 对齐)写入 32 位任意值。
- 等待 FLASH 处于空闲状态。 (EFM_FSR.RDY0/1=1)
- 清除擦除结束标志位。 (EFM_FSR.OPTEND0/1)
对已锁存的 OTP 地址发行擦除操作,擦除不成功, OTP 区域数据保留,标志位
EFM_FSR.OTPWERR0 置位。
对应的库函数为EFM_SectorErase;
全擦除功能
注意:不论擦除是以扇区进行的,即8K,写入的是后必须为4bytes.
综合应用demo
因为在同一个flash块上无法实现连续编程,因此要进行flash的连续的读写只能通过单次编程实现。
#define HC32FLASH_END (EFM_ADDR_SECTOR255 + 0x2000)
int FLASH_ReadBytes(uint32_t readAddr, void *pBuffer, int NumToRead)
{uint32_t nread = NumToRead;uint8_t* d = (uint8_t *)pBuffer;const uint8_t* s = (const uint8_t *)readAddr;//判断参数if (!pBuffer /*|| Address < HC32FLASH_BASE*/ || ((readAddr + NumToRead) >= HC32FLASH_END))return 0;while (nread >= sizeof(uint32_t) && (((uint32_t)s) <= (HC32FLASH_END - 4))){*(uint32_t *)d = *(uint32_t *)s;d += sizeof(uint32_t);s += sizeof(uint32_t);nread -= sizeof(uint32_t);}while ((nread != 0) && (((uint32_t)s) < HC32FLASH_END)){*d++ = *s++;nread--;}return (NumToRead - nread);
}//使用单次法写入多个数据
int FlashWriteBuff(uint32_t writeAddr,uint32_t u32Len, const uint32_t *pu32Buf)
{uint16_t i = 0;uint32_t mm;mm = *pu32Buf;if(NULL == pu32Buf){return 1;}for(i = 0; i < u32Len; i++){if(Ok != EFM_SingleProgram(writeAddr, *pu32Buf)){return 1;}writeAddr = writeAddr + sizeof(uint32_t);pu32Buf++;}return 0;}
/*** @brief: 写FLASH操作* @param: Address -- 写入起始地址,要求必须4字节对齐!!Buffer -- 待写入的数据,(uint32_t *)NumToWrite -- 要写入的数据量,单位:字节!* @note: 该函数是用的是单次写入,非连续* @return: none
**/
int FLASH_WriteBytes(uint32_t writeAddr, uint32_t *pBuffer, int NumToWrite)
{uint32_t i = 0;uint32_t sectorPos = 0; // 扇区位置uint32_t sectorOff = 0; // 扇区内偏移地址uint32_t sectorFre = 0; // 扇区内空余空间uint32_t offset = 0; // Address在FLASH中的偏移uint32_t worldNumber =(( NumToWrite %4 ==0)? (NumToWrite /4) :(NumToWrite /4 + 1));uint32_t nwrite = worldNumber;en_result_t res;//参数判断if ((((writeAddr) | 0xFFFFFFFCUL) != 0xFFFFFFFCUL) || writeAddr > (HC32FLASH_END - 4) || NumToWrite == 0 || pBuffer == NULL)return 0;/* 计算偏移地址 */offset = writeAddr - HC32FLASH_BASE;/* 计算当前扇区位置 */sectorPos = offset / HC32FLASH_SECTOR_SIZE;/* 计算要写数据的起始地址在当前页内的偏移地址 */sectorOff = ((offset % HC32FLASH_SECTOR_SIZE) >> 2);/* 计算当前扇区内空余空间 */sectorFre = ((HC32FLASH_SECTOR_SIZE >> 2) - sectorOff);/* 要写入的数据量低于当前扇区空余量 */if (nwrite <= sectorFre)sectorFre = nwrite;/* 解锁 */UnLock_Flash();while(nwrite != 0){/* 检查是否超扇区了 */if (sectorPos >= HC32FLASH_SECTOR_NUM)break;/* 读取整页 */BSP_STMFLASH_ReadBytes(HC32FLASH_BASE + sectorPos * HC32FLASH_SECTOR_SIZE, STMFLASHBuf,HC32FLASH_SECTOR_SIZE);/* 检查是否需要擦除 */for (i = 0; i < sectorFre; i++){if (*(STMFLASHBuf + sectorOff + i) != 0xFFFFFFFF) /* FLASH擦出后默认内容全为0xFF */break;}//设置flash单字节操作模式EFM_SectorCmd_Single( sectorPos, Enable);//擦除if (i < sectorFre){uint32_t index = 0;/* 擦除当前扇区 */res = EFM_SectorErase(HC32FLASH_BASE + sectorPos * HC32FLASH_SECTOR_SIZE);if (Ok != res){break;}/* 复制到缓存 */for (index = 0; index < sectorFre; index++){*(STMFLASHBuf + sectorOff + index) = *(pBuffer + index);}/* 写回FLASH */res = FlashWriteBuff(HC32FLASH_BASE + sectorPos * HC32FLASH_SECTOR_SIZE, HC32FLASH_SECTOR_SIZE, STMFLASHBuf);if (Ok != res){break;}}else{/* 直接写不需要擦除 */res = FlashWriteBuff(writeAddr, sectorFre, pBuffer);}EFM_SectorCmd_Single( sectorPos, Disable);pBuffer += sectorFre; /* 读取地址递增 */writeAddr += (sectorFre << 2); /* 写入地址递增 */nwrite -= sectorFre; /* 更新剩余未写入数据量 */sectorPos++; /* 下一扇区 */sectorOff = 0; /* 页内偏移地址置零 *//* 根据剩余量计算下次写入数据量 */sectorFre = nwrite >= (HC32FLASH_SECTOR_SIZE >> 2) ? (HC32FLASH_SECTOR_SIZE >> 2) : nwrite;}/* 加锁所有扇区 */Lock_Flash();return ((NumToWrite - nwrite) << 2);
}int BSP_STMFLASH_ReadBytes(uint32_t readAddr, void *pBuffer, int NumToRead)
{uint32_t nread = NumToRead;uint8_t* d = (uint8_t *)pBuffer;const uint8_t* s = (const uint8_t *)readAddr;if (!pBuffer /*|| Address < HC32FLASH_BASE*/ || ((readAddr + NumToRead) >= HC32FLASH_END))return 0;while (nread >= sizeof(uint32_t) && (((uint32_t)s) <= (HC32FLASH_END - 4))){*(uint32_t *)d = *(uint32_t *)s;d += sizeof(uint32_t);s += sizeof(uint32_t);nread -= sizeof(uint32_t);}while ((nread != 0) && (((uint32_t)s) < HC32FLASH_END)){*d++ = *s++;nread--;}return (NumToRead - nread);
}
HC32 flash 读写操作相关推荐
- 瑞萨R78族Flash读写操作详细探讨
前言 最近使用到瑞萨R78族的MCU,准备做一个关于掉电保存参数配置的功能,需求大概是对200多个参数在掉电瞬间保存到芯片flash空间中,网上关于瑞萨MCU的flash读写操作教程也比较少,于是笔者 ...
- 【FPGA】SPI协议详解及对flash读写操作
FPGA基于SPI实现对flash读写操作 概括 一.SPI协议.flash讲解 1.SPI协议 2.flash (1)WREN (2)RDID (3)WRSR (4)READ (5)PP (6)SE ...
- NAND FLASH 读写操作 简介
NAND FLASH 内存详解与读写寻址方式 一.内存详解 NAND闪存阵列分为一系列128kB的区块(block),这些区块是 NAND器件中最小的可擦除实体.擦除一个区块就是把所有的位(bit)设 ...
- Esp8266的Flash读写操作以及Flash上传文件
1.Flash的读写操作 Esp8266的Flash为4M,其中1M用于存储程序,其他的空间有一部分用于系统,3M中剩下的大部分空间可以用来存放文件. #include <FS.h> St ...
- (超详细)STM32芯片Flash读写操作讲解和代码(寄存器版本)
关于Flash,官方的解释为:Flash为32位宽的存储单元,可用于存储代码和数据常量.Flash模块位于微控制器内存映射中的特定基址--.而对于我们来说,只要知道Flash闪存区是一个掉电后也不会清 ...
- c语言指针flash,STM32F103RCT6之FLASH读写操作
一.STM32F103的FLASH简介 1.如图所示,STM32F103内部FLASH存储区分为三个区域:主存储区.信信息块和闪存存储器接口寄存器. 储存储区是我们读写FLASH的主要的存储区,MCU ...
- STM32远程升级IAP功能+备份功能实现。(flash读写操作)
远程升级加备份一共需要4个扇区,要确保flash可以被分成四个扇区(F4的扇区好大,4个16k,1个64k,剩下都是128k,对于小容量芯片非常不友好). 第一个存放出厂程序,也叫启动程序boot l ...
- Xilinx ZYNQ 7000学习笔记三(qspi flash读写操作)
参考文献:Zynq-7000 SoC Technical Reference Manual (UG585)-ch12 Quad-SPI Flash Controller 一.nor Flash介绍 z ...
- ZYNQ-QSPI Flash读写操作
学习内容 本文首先介绍Flash和QSPI Flash控制器的相关内容,然后使用 QSPI Flash 控制器,开发板上的 QSPI Flash 进行写. 读操作.通过对比读出的数据是否等于写入的数据 ...
最新文章
- 好理解的Java内存虚假共享(False Sharing)性能损耗以及解决方案
- 01H5-fe-html5-005插入音频
- Android 依赖注入可以更简单 —— 新版本 Dagger 2 使用教学
- Jenkins默认工作空间及更改默认工作空间
- PyQt5 笔记2 -- Qt Designer使用
- 飞天技术汇“2018云栖大会·上海峰会”专场,等你加入
- 【C#程序设计】教学讲义——第一章:C#语言概述
- linux的进程/线程/协程系列1:进程到协程的演化
- Go语言学习Day04
- 史上最壕无人车买家诞生!泥潭中的Uber要搞个超大的无人出租车队
- matlab注释的方法
- 怎样在计算机上注册dll文件,win10如何注册dll文件_win10系统dll文件怎样安装
- 常用的软件测试方法及特点分析
- python 导入自己写的包
- epub文件格式揭秘
- 【Python】只需2行代码,轻松将PDF转换成Word(含示范案例)
- chm打开秒退_Mac_Mac电脑程序无响应怎么办?Mac程序无响应解决方法,虽然Mac电脑一向以运行稳定、 - phpStudy...
- redis数据结构hash
- 3.1 CUDA执行模型概述
- CGTrader新赛CG Wildlife Challenge(CG野生生物竞赛)重磅推出
热门文章
- 一阶数字低通滤波器的实现
- 自由的百科全书 Wikipedia 18 周岁了
- 【技术分享】你想知道的网易云音乐推荐架构解析,都在这里!
- 一款开源的播放器框架WMPlayer
- 用python将图片上传到SM.MS图床
- it's +时间+since/that/when/before句型用法的差别
- FCF中文指南-第七章--FusionCharts Free和XML
- fdma调制解调matlab,信号与系统Matlab实验—频分多址FDMA
- sqlserver 2008 varchar字段 转 nvarchar 存储过程
- Bluetooth Profile Specification之(AVRCP篇)5.1AVCTP的连接和释放