×
单片机 > 单片机程序设计 > 详情

STM32 Flash操作(擦写)过程中器件复位导致数据丢失问题

发布时间:2020-06-16 发布时间:
|

1.问题描述

产品在运行过程中需要保存一些断电不丢失的数据,为此将数据保存在STM32内部的flash中。但是测试人员在测试的过程中,修改了数据参数,直接断电重启机器,并没有等待flash的操作时间,导致原有的数据丢失。


2. 原理分析

本产品硬件平台是基于STM32F429,采用HAL库开发。在操作内部flash这部分中,查看数据手册得知: 


 
 


对于操作128KB的扇区擦写32位数据需要的时间,典型值是1S。最大值是2S。才能保证操作完成。 


而在参考手册中提到:在Flash操作期间发生器件复位,则无法保证flash中的内容, 

 

 


为此,我特地在擦写过程中,断电,然后看flash中的数据是什么,经过多次擦写,断电,然后用ST-Link查看扇区的数据发现,其数据如图所示: 


 
 

数据为0xFFFFFFFF 或者0x00000000 不定。但是经过多次发现,基本上都是在这两个数据当中变化,无规则。 

为此在判断的时候,可以采用这两个数据进行判断。


3. 解决方案:

采用一块Backup sector(备份扇区)用来存储修改参数前的数据,当第一块扇区数据丢失的时候,就读取备份扇区的内容。 

具体看代码:


void flash_set_date(void)

{

    static u8 update_flag=0;

    uint8_t i=0;

    //读取扇区内容,2块扇区内容同时为0xFFFFFFFF 表示没有参数,使用默认值

    if((FLASH_ReadWord(MDATA_BASE+0)==0xffffffff)&&(FLASH_ReadWord(BACK_FLASH_BASE+0)==0xffffffff))

    {

        GD_BUF[INDEX_ID] = 0xff;//子控制板的ID默认设置为0xff

        GD_BUF[INDEX_RED_CURRENT]=110;       //红光电流默认值100mA

        GD_BUF[INDEX_FORWORD_V]=38;      //前向光默认值500

        GD_BUF[INDEX_PD_BACK]=193;       //回光默认值2500

        GD_BUF[INDEX_5620_A2]=27;

        GD_BUF[INDEX_5620_B2]=27;

        GD_BUF[INDEX_BIAS_V]=154;     //偏置电压默认值2000


        GD_BUF[INDEX_OV_DTEMP]=40;     //电水冷板温度报警默认值40

        GD_BUF[INDEX_ADJ_POWER]=187;   //满功率微调值默认186


        GD_BUF[INDEX_OV_TEMP]=45;      //泵源温度报警默认值45

        GD_BUF[INDEX_OV_GTEMP]=35;     //光水冷板温度报警默认值35

        GD_BUF[INDEX_5620_A1]=27;   


        GD_BUF[INDEX_OVER_V]=131;//过压报警点

        GD_BUF[INDEX_LOW_V]=100;//低压报警点

        GD_BUF[INDEX_OVER_I]=181;//过流报警点

    }

    else//有参数,先读取扇区1

    {

        for(i=0;i

        {

            GD_BUF_FLASH[i] = FLASH_ReadWord(MDATA_BASE+i*4);

        }

        //意外擦除了

        if((GD_BUF_FLASH[FLASH_RED_CURRENT]==0xffffffff)&&(GD_BUF_FLASH[FLASH_FORWORD_V]==0xffffffff)&&(GD_BUF_FLASH[FLASH_PD_BACK]==0xffffffff)\

        &&(GD_BUF_FLASH[FLASH_BIAS_V]==0xffffffff))update_flag=1;

        //被意外清零了。

        if((GD_BUF_FLASH[FLASH_RED_CURRENT]==0)&&(GD_BUF_FLASH[FLASH_FORWORD_V]==0)&&(GD_BUF_FLASH[FLASH_PD_BACK]==0)\

        &&(GD_BUF_FLASH[FLASH_BIAS_V]==0))update_flag=1;

    }


    //不正确,读取扇区2的内容  

    if(update_flag>0)

    {

        for(i=0;i

        {

            GD_BUF[i] = FLASH_ReadWord(BACK_FLASH_BASE+i*4);

        }

//      flash_update();//写入扇区1

//      pcset_5620_pro();//第一次上电设置5620输出。

        TLC5620_Set1((u8)GD_BUF[INDEX_5620_A1],0);

        TLC5620_Set1((u8)GD_BUF[INDEX_RED_CURRENT],1);

        TLC5620_Set1((u8)GD_BUF[INDEX_FORWORD_V],2);

        TLC5620_Set1((u8)GD_BUF[INDEX_PD_BACK],3);

        TLC5620_Set2((u8)GD_BUF[INDEX_5620_A2],0);

        TLC5620_Set2((u8)GD_BUF[INDEX_5620_B2],1);

        TLC5620_Set2((u8)GD_BUF[INDEX_BIAS_V],2);

    }

    else//参数正确,比较扇区1 

    {

        if(Compare_Sector_Date(MDATA_BASE,BACK_FLASH_BASE,GD_LEN_FLASH))

        {

            Update_Back_Flash(BACK_FLASH_BASE,GD_LEN_FLASH);

        }

        for(i=0;i

        {

            GD_BUF[i]=GD_BUF_FLASH[i];

        }

        TLC5620_Set1((u8)GD_BUF[INDEX_5620_A1],0);

        TLC5620_Set1((u8)GD_BUF[INDEX_RED_CURRENT],1);

        TLC5620_Set1((u8)GD_BUF[INDEX_FORWORD_V],2);

        TLC5620_Set1((u8)GD_BUF[INDEX_PD_BACK],3);

        TLC5620_Set2((u8)GD_BUF[INDEX_5620_A2],0);

        TLC5620_Set2((u8)GD_BUF[INDEX_5620_B2],1);

        TLC5620_Set2((u8)GD_BUF[INDEX_BIAS_V],2);

    }   

}


具体流程: 

1. 读取到两块扇区都为0xFFFFFFFF时,表示第一次烧写程序,采用默认值。 

2. 有参数,则读取第一块扇区内容, 

3. 判断第一块扇区内容是否正确,(可以采用校验的方式,或者采用在一个固定的位置写入固定的数据:写入0x55AA55AA)如果说扇区数据丢失,则写入的固定数据也将丢失,则说明第一块扇区内容不正确。 

4. 不正确,读取第二块扇区内容,写入第一块扇区中。正确,比较两个扇区内容的差异,不同,则写入备份扇区。 

对此,操作完成。flash扇区数据备份。


关键字:STM32  Flash操作  器件复位  数据丢失


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
AVR熔丝位操作时的要点和需要注意的相关事项