内部flash写入的时候,需要将代码分配到内存中执行
/*************************************************************************************************************
* 文件名 : hc32f46x_flash.c
* 功能 : HC32F46X 内部FLASH驱动
* 作者 : cp1300@139.com
* 创建时间 : 2021-07-27
* 最后修改时间 : 2021-07-27
* 详细 : flash操作时要禁止一切中断以及flash读取操作,相关接口函数都要定义到RAM中执行,不要调用任何其他函数
连续编程过程中,绝对不能调用非RAM函数,目前是先清除看门狗(有12秒以上时间),保证擦除时间不超过12秒即可
2021-10-09:解决了可能存在的读写错误,原因是擦写flash的时候访问了flash导致;
*************************************************************************************************************/
#include "hc32f46x.h"
#include "hc32f46x_map.h"
#include "system.h"
#include "hc32f46x_flash.h"
#define __at__IRAM3__ __attribute__((section("IRAM3")))
//FLASH编程模式
typedef enum
{
PEMOD_READ_ONLY = 0, //只读模式
PEMOD_SINGLE_PROGRAM = 1, //单编程模式
PEMOD_SINGLE_PROGRAM_RB = 2, //单编程回读模式
PEMOD_SEQUENCE_PROGRAM = 3, //连续编程模式
PEMOD_SECTOR_ERASE = 4, //扇区擦除模式
PEMOD_MASS_ERASE = 5, //全擦除模式
}FLASH_PEMOD;
/*************************************************************************************************************************
* 函数 : void HC32FLASH_Unlock(void)
* 功能 : 解锁HC32的FLASH编程
* 参数 : 无
* 返回 : 无
* 依赖 : 底层
* 作者 : cp1300@139.com
* 时间 : 2021-07-28
* 最后修改时间 : 2021-07-28
* 说明 : 解锁配置,并进入编程模式
*************************************************************************************************************************/
__at__IRAM3__
void HC32FLASH_Unlock(void)
{
SYS_EFM_CONFIG_Unlock(); //EFM配置解锁
EFM->FWMC |= BIT0; //允许修改编程模式
EFM->FWMC &= ~BIT8; //FLASH编程擦除期间,总线被占用
}
/*************************************************************************************************************************
* 函数 : void HC32FLASH_Lock(void)
* 功能 : 上锁HC32的FLASH
* 参数 : 无
* 返回 : 无
* 依赖 : 底层
* 作者 : cp1300@139.com
* 时间 : 2013-10-20
* 最后修改时间 : 2018-01-13
* 说明 : 上锁配置,并退出编程模式
*************************************************************************************************************************/
__at__IRAM3__
void HC32FLASH_Lock(void)
{
EFM->FWMC &= ~BIT0; //不允许修改编程模式
SYS_EFM_CONFIG_Lock(); //EFM配置上锁
}
/*************************************************************************************************************************
* 函数 : HC32FLASH_STATUS HC32FLASH_GetStatus(void)
* 功能 : 得到FLASH状态
* 参数 : 无
* 返回 : HC32FLASH_STATUS
* 依赖 : 底层
* 作者 : cp1300@139.com
* 时间 : 2021-07-27
* 最后修改时间 : 2021-07-27
* 说明 :
*************************************************************************************************************************/
__at__IRAM3__
HC32FLASH_STATUS HC32FLASH_GetStatus(void)
{
u32 temp=EFM->FSR;
if(!(temp&(1<<8))) return HC32FLASH_BUSY; //忙
else if(temp&(1<<1))return HC32FLASH_WPRERR; //写保护错误
else if(temp&(1<<2))return HC32FLASH_PGAERR; //编程对齐错误
else if(temp&(1<<0))return HC32FLASH_PEWERR; //在擦写不许可模式下擦写 FLASH
else if(temp&(1<<5))return HC32FLASH_COLERR; //读写访问错误
else if(temp&(1<<3))return HC32FLASH_PGMISMTCH; //单编程回读错误
return HC32FLASH_OK; //操作完成
}
/*************************************************************************************************************************
* 函数 : HC32FLASH_STATUS HC32FLASH_WaitDone(u32 time)
* 功能 : 等待操作完成
* 参数 : time:要延时的长短,单位us
* 返回 : HC32FLASH_STATUS
* 依赖 : 底层
* 作者 : cp1300@139.com
* 时间 : 2021-07-27
* 最后修改时间 : 2021-07-27
* 说明 :
*************************************************************************************************************************/
__at__IRAM3__
HC32FLASH_STATUS HC32FLASH_WaitDone(u32 time)
{
HC32FLASH_STATUS status;
u32 i;
if(time < 1) time = 1;
do
{
status=HC32FLASH_GetStatus(); //获取状态
if(status!=HC32FLASH_BUSY)break; //非忙,无需等待了,直接退出.
for(i = 0;i < 100;i ++)
{
nop;nop;nop;nop;nop;
}
time--;
}while(time);
return status;
}
/*************************************************************************************************************************
* 函数 : void HC32FLASH_SetErasePgmMode(FLASH_PEMOD mode)
* 功能 : 设置flash的擦除编程模式
* 参数 : mode:模式,见FLASH_PEMOD
* 返回 : 无
* 依赖 : 底层
* 作者 : cp1300@139.com
* 时间 : 2021-07-28
* 最后修改时间 : 2021-07-28
* 说明 : 必须先解锁才能调用
*************************************************************************************************************************/
__at__IRAM3__
void HC32FLASH_SetErasePgmMode(FLASH_PEMOD mode)
{
EFM->FWMC &= ~(0x7 << 4); //先清除之前配置
EFM->FWMC |= (mode & 0x07) << 4; //重新设置
}
/*************************************************************************************************************************
* 函数 : HC32FLASH_STATUS HC32FLASH_EraseSector(u32 u32Addr)
* 功能 : 扇区擦除
* 参数 : u32Addr:要擦除的数据所在地址(擦除数据所在扇区)
* 返回 : HC32FLASH_STATUS
* 依赖 : 底层
* 作者 : cp1300@139.com
* 时间 : 2021-07-28
* 最后修改时间 : 2021-07-28
* 说明 :
*************************************************************************************************************************/
__at__IRAM3__
HC32FLASH_STATUS HC32FLASH_EraseSector(u32 u32Addr)
{
HC32FLASH_STATUS status;
u32 FRMC_Temp;
SYS_DisableIrq(); //关闭中断
EFM->FSCLR = 0x3F; //清除所有错误标记
HC32FLASH_Unlock(); //解锁
FRMC_Temp = EFM->FRMC; //记录之前寄存器值
if(FRMC_Temp & BIT16) //使能了缓存,则先关闭
{
EFM->FRMC &= ~BIT16; //关闭缓存
}
#if(SYS_WDG_EN_) //使能了看门狗
IWDG_Feed();
#endif //SYS_WDG_EN_
HC32FLASH_SetErasePgmMode(PEMOD_SECTOR_ERASE); //进入扇区擦除模式
//擦除模式,必须在RAM中执行
*(uint32_t*)u32Addr = 0x12345678; //往所在位置随便写个数据,触发擦除
status=HC32FLASH_WaitDone(1000000); //等待操作结束,最大1s
//擦除结束了
EFM->FSCLR = 0x3F; //清除所有错误标记
HC32FLASH_SetErasePgmMode(PEMOD_READ_ONLY); //退出擦除模式
if(FRMC_Temp & BIT16) //使能了缓存
{
EFM->FRMC |= BIT16 | BIT24; //开启缓存-并复位缓存
}
HC32FLASH_Lock(); //上锁
SYS_EnableIrq(); //使能中断
if(status != HC32FLASH_OK)
{
DEBUG("擦除扇区%d失败(错误:%d) \r\n",u32Addr, status);
}
return status; //返回状态
}
|