flash 读写操作
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