OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4182|回复: 2

flash无法擦除,只有擦除函数是可以的,但是有写入就不行了

[复制链接]

31

主题

85

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
294
金钱
294
注册时间
2018-5-3
在线时间
69 小时
发表于 2021-3-16 17:54:46 | 显示全部楼层 |阅读模式
1金钱
当下列flash地址有数据时,直接使用EraseFlash函数擦除时正常的。当时flash空间没数据,写入数据,写完擦除第一区域块或者写完第一区域块,擦第二区域的时候么就无法擦除了。

//#define  APP_ADDR                                                     0x08003000   //应用程序首地址
//#define  PARAM_START_ADDR                     0x0800F800                //配置参数存储地址
//#define  ABNORMAI_STATE_ADDR     0x0800FC00                //异常状态存储地址
//#define  HISTORY_DATA_ADDR                    0x0800E800                //履历数据存储地址
//#define  HISTORY_DATA_MAXINUM                    128                //履历数据单存储区的最大存储字节
//#define  HISTORY_DATA_NUM_CUR                           37*2                //履历数据单存储区的当前存储数

//共4K的空间,分区两个大区域块,保证擦除时最小可以读到2K的数据。
//以128字节为一个小存储区,共32个小存储区块,保证最小读取数量为16条
//目前通信协议规定履历存储数据为37字数据,共74字节,其余为预留空间。
//当写入第一区域块的最后一个数据时,擦除第二区域块的内容。
//写入时,发现4k空间写满数据,擦除第一区域块内容。/////////当写入第而区域块的最后一个数据时,擦除第一区域块的内容
                unsigned short dqwdqd =0;
   uint32_t addr1112222=0;
void HisData_Write_flash(uint8_t size)
{
    uint8_t i=0;                                //目前参数区域块的计数,共计128字节
//    uint8_t j=0;
    uint8_t block_counts=0;                //目前将1K的空间分为8块
    uint8_t date_flash=0;
    uint32_t addr=0;
       
       
//                EraseFlash(HISTORY_DATA_ADDR,2);
//                        EraseFlash(0x0800F000,2);
READAGAIN:
    date_flash=*(uint8_t*)(HISTORY_DATA_ADDR+block_counts*HISTORY_DATA_MAXINUM+i);
    if(date_flash==0xFF)
    {
        i++;
        if(i<=(HISTORY_DATA_MAXINUM-1))
        {
            goto READAGAIN;
        }
        else
        {
            addr=HISTORY_DATA_ADDR+block_counts*HISTORY_DATA_MAXINUM;
                                                addr1112222  = addr;
//                                                if(addr == (HISTORY_DATA_ADDR+0x400+7*128))//写入第一区域块的最后一个存储区的数据,擦除第二存储区
//                                                EraseFlash((HISTORY_DATA_ADDR+0x800),1);
//                                                if(addr == (HISTORY_DATA_ADDR+0x400+7*128))//写入第一区域块的最后一个存储区的数据,擦除第二存储区
                                                if(addr == 0x0800EF80)//写入第一区域块的最后一个存储区的数据,擦除第二存储区
                                                {
                                                                //EraseFlash((HISTORY_DATA_ADDR+0x800),2);
                                                                EraseFlash(0x0800F000,2);
                                                }
                                               
                                                // WriteFlash(&params.Rsaddr,addr,size);//设置参数列
                                                WriteFlash(&dqwdqd,addr,sizeof(dqwdqd));//设置参数列
                                                if(addr == HISTORY_DATA_ADDR)//写入第一区域块的最后一个存储区的数据,擦除第二存储区
                                                {
                                                                WriteFlash(&dqwdqd,0x0800F000,sizeof(dqwdqd));//设置参数列
                                                }

                                               
        }
    }
    else
    {
                       
        //addr=parameters_start_address+128*j;
        block_counts++;
        i=0;  //需从下去区块重新开始读取
        if(block_counts<32)
        {

            goto READAGAIN; //重新开始下个存储区的读写
        }
        else
        {
            //擦除flash    参数区已全部轮询完毕,第一区域块
            EraseFlash(HISTORY_DATA_ADDR,2);
            block_counts=0;
            addr=HISTORY_DATA_ADDR+block_counts*HISTORY_DATA_MAXINUM;
//           WriteFlash(&params.Rsaddr,HISTORY_DATA_ADDR,size);//设置参数列
                                                dqwdqd ++;
                                                WriteFlash(&dqwdqd,addr,sizeof(dqwdqd));//设置参数列
        }

    }

}



// 清除Flash
//Address 最好为页的其实地址
//size 擦除size页,不包含本页,1页为1K
void EraseFlash(uint32_t  Address,uint8_t size)
{
        FLASH_EraseInitTypeDef My_Flash;
        uint32_t PageError = 0;
        My_Flash.TypeErase = FLASH_TYPEERASE_PAGES;  //标明Flash执行页面只做擦除操作
        My_Flash.PageAddress = Address;  //声明要擦除的地址
        My_Flash.NbPages = size;
        HAL_FLASH_Unlock(); //解锁FLASH编程擦除控制器
//        FLASH->SR = FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPERR;
        FLASH->SR = FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPERR;
        HAL_FLASHEx_Erase(&My_Flash, &PageError);
//        FLASH->SR = FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPERR;
        FLASH->SR = FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPERR;
        HAL_FLASH_Lock(); //锁定FLASH编程擦除控制器


}


//Data  为16位数据
//Address 写入的起始地址
//len    写入n个字节
void WriteFlash(uint16_t *Data,uint32_t Address, int len)
{
        uint8_t i = 0;
        uint16_t data_flash;
        len=len/2;
        HAL_FLASH_Unlock(); //解锁FLASH编程擦除控制器
//        FLASH->SR = FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPERR;
        FLASH->SR = FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPERR;
        while(i < len)
        {
                //Data[i]为0x1234,写入的为12 34
                data_flash = (Data[i]>>8)+ (((uint8_t)Data[i])<<8);
                FLASH_Program_HalfWord(Address, data_flash);
                i=i+1;
                Address = Address+2;
        }       
//        FLASH->SR = FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPERR;
        FLASH->SR = FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPERR;
        HAL_FLASH_Lock(); //锁定FLASH编程擦除控制器
}

QQ截图20210316175406.png
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

821

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3369
金钱
3369
注册时间
2011-11-10
在线时间
207 小时
发表于 2021-3-16 18:36:19 | 显示全部楼层
用Address = Address+4试试。
另外注意FLASH有擦除时间。在此时间内写入指令肯定是无效的。
对效率要求不高的可以写完再擦,或者擦完再写。
回复

使用道具 举报

0

主题

14

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
273
金钱
273
注册时间
2016-2-11
在线时间
131 小时
发表于 2021-3-27 10:17:59 | 显示全部楼层
我也遇见过!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-28 01:57

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表