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()中。

擦除功能

  1. 解除 FLASH 的寄存器写保护(EFM_FAPRT 先写 0x0123, 再写 0x3210)。
  2. 解除 EFM_KEY1 锁定。 (EFM_KEY1 先写 0x01234567, 再写 0xFEDCBA98)
  3. 设定擦除模式(EFM_FWMC.PEMOD[2:0]=100)。
  4. 解除写保护。 (EFM_ F0/1NWPRTx(x=0~3)对应位设定为 1)
  5. 对需要擦除扇区内的任意地址(地址需以 4 对齐)写入 32 位任意值。
  6. 等待 FLASH 处于空闲状态。 (EFM_FSR.RDY0/1=1)
  7. 清除擦除结束标志位。 (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 读写操作相关推荐

  1. 瑞萨R78族Flash读写操作详细探讨

    前言 最近使用到瑞萨R78族的MCU,准备做一个关于掉电保存参数配置的功能,需求大概是对200多个参数在掉电瞬间保存到芯片flash空间中,网上关于瑞萨MCU的flash读写操作教程也比较少,于是笔者 ...

  2. 【FPGA】SPI协议详解及对flash读写操作

    FPGA基于SPI实现对flash读写操作 概括 一.SPI协议.flash讲解 1.SPI协议 2.flash (1)WREN (2)RDID (3)WRSR (4)READ (5)PP (6)SE ...

  3. NAND FLASH 读写操作 简介

    NAND FLASH 内存详解与读写寻址方式 一.内存详解 NAND闪存阵列分为一系列128kB的区块(block),这些区块是 NAND器件中最小的可擦除实体.擦除一个区块就是把所有的位(bit)设 ...

  4. Esp8266的Flash读写操作以及Flash上传文件

    1.Flash的读写操作 Esp8266的Flash为4M,其中1M用于存储程序,其他的空间有一部分用于系统,3M中剩下的大部分空间可以用来存放文件. #include <FS.h> St ...

  5. (超详细)STM32芯片Flash读写操作讲解和代码(寄存器版本)

    关于Flash,官方的解释为:Flash为32位宽的存储单元,可用于存储代码和数据常量.Flash模块位于微控制器内存映射中的特定基址--.而对于我们来说,只要知道Flash闪存区是一个掉电后也不会清 ...

  6. c语言指针flash,STM32F103RCT6之FLASH读写操作

    一.STM32F103的FLASH简介 1.如图所示,STM32F103内部FLASH存储区分为三个区域:主存储区.信信息块和闪存存储器接口寄存器. 储存储区是我们读写FLASH的主要的存储区,MCU ...

  7. STM32远程升级IAP功能+备份功能实现。(flash读写操作)

    远程升级加备份一共需要4个扇区,要确保flash可以被分成四个扇区(F4的扇区好大,4个16k,1个64k,剩下都是128k,对于小容量芯片非常不友好). 第一个存放出厂程序,也叫启动程序boot l ...

  8. Xilinx ZYNQ 7000学习笔记三(qspi flash读写操作)

    参考文献:Zynq-7000 SoC Technical Reference Manual (UG585)-ch12 Quad-SPI Flash Controller 一.nor Flash介绍 z ...

  9. ZYNQ-QSPI Flash读写操作

    学习内容 本文首先介绍Flash和QSPI Flash控制器的相关内容,然后使用 QSPI Flash 控制器,开发板上的 QSPI Flash 进行写. 读操作.通过对比读出的数据是否等于写入的数据 ...

最新文章

  1. 好理解的Java内存虚假共享(False Sharing)性能损耗以及解决方案
  2. 01H5-fe-html5-005插入音频
  3. Android 依赖注入可以更简单 —— 新版本 Dagger 2 使用教学
  4. Jenkins默认工作空间及更改默认工作空间
  5. PyQt5 笔记2 -- Qt Designer使用
  6. 飞天技术汇“2018云栖大会·上海峰会”专场,等你加入
  7. 【C#程序设计】教学讲义——第一章:C#语言概述
  8. linux的进程/线程/协程系列1:进程到协程的演化
  9. Go语言学习Day04
  10. 史上最壕无人车买家诞生!泥潭中的Uber要搞个超大的无人出租车队
  11. matlab注释的方法
  12. 怎样在计算机上注册dll文件,win10如何注册dll文件_win10系统dll文件怎样安装
  13. 常用的软件测试方法及特点分析
  14. python 导入自己写的包
  15. epub文件格式揭秘
  16. 【Python】只需2行代码,轻松将PDF转换成Word(含示范案例)
  17. chm打开秒退_Mac_Mac电脑程序无响应怎么办?Mac程序无响应解决方法,虽然Mac电脑一向以运行稳定、 - phpStudy...
  18. redis数据结构hash
  19. 3.1 CUDA执行模型概述
  20. CGTrader新赛CG Wildlife Challenge(CG野生生物竞赛)重磅推出

热门文章

  1. 一阶数字低通滤波器的实现
  2. 自由的百科全书 Wikipedia 18 周岁了
  3. 【技术分享】你想知道的网易云音乐推荐架构解析,都在这里!
  4. 一款开源的播放器框架WMPlayer
  5. 用python将图片上传到SM.MS图床
  6. it's +时间+since/that/when/before句型用法的差别
  7. FCF中文指南-第七章--FusionCharts Free和XML
  8. fdma调制解调matlab,信号与系统Matlab实验—频分多址FDMA
  9. sqlserver 2008 varchar字段 转 nvarchar 存储过程
  10. Bluetooth Profile Specification之(AVRCP篇)5.1AVCTP的连接和释放