stm32H7内部flash存储结构体 固件库,寄存器结合使用,解决无法写入问题

一、慎用固件库

1.HAL_FLASH_Program有问题,写入不正常

2.采用直接操作寄存器操作flash

好处是写好一次,后面基本不会出问题
我使用的是正点原子的寄存器版本,接口比较清晰,
但也有一个问题STMFLASH_EraseSector 操作内部有延时,会莫名卡在里面
发现HAL_FLASHEx_Erase的操作正常并且很快,
将STMFLASH_Write函数中擦除flash替换为HAL库操作方式,速度瞬间提升。
并且兼容了BANK1,BANK2的操作

void STMFLASH_Write(u32 WriteAddr,u32 *pBuffer,u32 NumToWrite)
{ 
    FLASH_EraseInitTypeDef FlashEraseInit;
    HAL_StatusTypeDef FlashStatus=HAL_OK;
    u32 SectorError=0;
    u8 status=0;
    u32 addrx=0;
    u32 endaddr=0;
    if(WriteAddr<STM32_FLASH_BASE||WriteAddr%32)return; //非法地址
    STMFLASH_Unlock();                                  //解锁
    addrx=WriteAddr;                //写入的起始地址
    endaddr=WriteAddr+NumToWrite*4; //写入的结束地址
    if(addrx<0X1FF00000)            //只有主存储区,才需要执行擦除操作!!
    {
        while(addrx<endaddr)        //扫清一切障碍.(对非FFFFFFFF的地方,先擦除)
        {
            if(STMFLASH_ReadWord(addrx)!=0XFFFFFFFF)//有非0XFFFFFFFF的地方,要擦除这个扇区
            {
#if 1
                FlashEraseInit.TypeErase=FLASH_TYPEERASE_SECTORS; //擦除类型
                FlashEraseInit.Sector=STMFLASH_GetFlashSector(addrx)%8;//要擦除的扇区
                FlashEraseInit.Banks=addrx>=BANK2_FLASH_SECTOR_0?FLASH_BANK_2:FLASH_BANK_1; //操作 BANK1
                FlashEraseInit.NbSectors=1; //一次只擦除一个扇区
                FlashEraseInit.VoltageRange=FLASH_VOLTAGE_RANGE_3; //电压范围
                if(HAL_FLASHEx_Erase(&FlashEraseInit,&SectorError)!=HAL_OK)
                {
                break; //发生错误了
                }
                SCB_CleanInvalidateDCache(); //清除无效的 D-Cach
#else
                //status=STMFLASH_EraseSector(STMFLASH_GetFlashSector(addrx));
               // if(status)break;    //发生错误了
                // SCB_CleanInvalidateDCache();  //清除无效的D-Cache
#endif

            }else addrx+=4;
        }
    }
    if(status==0)
    {
        while(WriteAddr<endaddr)//写数据
        {
            if(STMFLASH_Write8Word(WriteAddr,pBuffer))//写入数据
            {
                break;  //写入异常
            }
            WriteAddr+=32;
            pBuffer+=8;
        }
    }
    STMFLASH_Lock();//上锁
} 

二、测试函数

  1. 我们可以通过一个结构体将所有需要保存的参数放到一起管理并保存,这是最简单的方式
#define GP_LENTH sizeof(PARAM_T)              //数组长度
#define SAVE_SIZE GP_LENTH/4+((GP_LENTH%4)?1:0) // 必须是4的整数倍
	PARAM_T gp;
	
	void SPIFlash_test(void)
	{
  		memset(&gp,3,sizeof(gp));
        STMFLASH_Write(FLASH_SAVE_ADDR,(u32*)&gp,SAVE_SIZE);

        STMFLASH_Read(FLASH_SAVE_ADDR,(u32*)&gp,25);
        memset(&gp,1,sizeof(gp));
        STMFLASH_Read(FLASH_SAVE_ADDR,(u32*)&gp,SAVE_SIZE);
       
    }

2.通常可以将结构体的首字节,末字节作为验证是否数据已经保存或正确保存的标志

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值