stm32f407 內部flash保存數據


 

#include "stm32f4xx.h"

//FLASH起始地址
#define STM32_FLASH_BASE 0x08000000     //STM32 FLASH的起始地址
#define FLASH_SAVE_ADDR  0x080A0000    //保存地址


//FLASH 扇區的起始地址
#define ADDR_FLASH_SECTOR_0     ((u32)0x08000000)     //扇區0起始地址, 16 Kbytes  
#define ADDR_FLASH_SECTOR_1     ((u32)0x08004000)     //扇區1起始地址, 16 Kbytes  
#define ADDR_FLASH_SECTOR_2     ((u32)0x08008000)     //扇區2起始地址, 16 Kbytes  
#define ADDR_FLASH_SECTOR_3     ((u32)0x0800C000)     //扇區3起始地址, 16 Kbytes  
#define ADDR_FLASH_SECTOR_4     ((u32)0x08010000)     //扇區4起始地址, 64 Kbytes  
#define ADDR_FLASH_SECTOR_5     ((u32)0x08020000)     //扇區5起始地址, 128 Kbytes  
#define ADDR_FLASH_SECTOR_6     ((u32)0x08040000)     //扇區6起始地址, 128 Kbytes  
#define ADDR_FLASH_SECTOR_7     ((u32)0x08060000)     //扇區7起始地址, 128 Kbytes  
#define ADDR_FLASH_SECTOR_8     ((u32)0x08080000)     //扇區8起始地址, 128 Kbytes  
#define ADDR_FLASH_SECTOR_9     ((u32)0x080A0000)     //扇區9起始地址, 128 Kbytes  
#define ADDR_FLASH_SECTOR_10    ((u32)0x080C0000)     //扇區10起始地址,128 Kbytes  
#define ADDR_FLASH_SECTOR_11    ((u32)0x080E0000)     //扇區11起始地址,128 Kbytes  



//讀取指定地址的半字(16位數據) 
//faddr:讀地址 
//返回值:對應數據.
u32 STMFLASH_ReadWord(u32 faddr)
{
    return *(vu32*)faddr; 
}  
//獲取某個地址所在的flash扇區
//addr:flash地址
//返回值:0~11,即addr所在的扇區
uint16_t STMFLASH_GetFlashSector(u32 addr)
{
    if(addr<ADDR_FLASH_SECTOR_1)return FLASH_Sector_0;
    else if(addr<ADDR_FLASH_SECTOR_2)return FLASH_Sector_1;
    else if(addr<ADDR_FLASH_SECTOR_3)return FLASH_Sector_2;
    else if(addr<ADDR_FLASH_SECTOR_4)return FLASH_Sector_3;
    else if(addr<ADDR_FLASH_SECTOR_5)return FLASH_Sector_4;
    else if(addr<ADDR_FLASH_SECTOR_6)return FLASH_Sector_5;
    else if(addr<ADDR_FLASH_SECTOR_7)return FLASH_Sector_6;
    else if(addr<ADDR_FLASH_SECTOR_8)return FLASH_Sector_7;
    else if(addr<ADDR_FLASH_SECTOR_9)return FLASH_Sector_8;
    else if(addr<ADDR_FLASH_SECTOR_10)return FLASH_Sector_9;
    else if(addr<ADDR_FLASH_SECTOR_11)return FLASH_Sector_10; 
    return FLASH_Sector_11;    
}
//從指定地址開始寫入指定長度的數據
//特別注意:因爲STM32F4的扇區實在太大,沒辦法本地保存扇區數據,所以本函數
//         寫地址如果非0XFF,那麼會先擦除整個扇區且不保存扇區數據.所以
//         寫非0XFF的地址,將導致整個扇區數據丟失.建議寫之前確保扇區裏
//         沒有重要數據,最好是整個扇區先擦除了,然後慢慢往後寫. 
//該函數對OTP區域也有效!可以用來寫OTP區!
//OTP區域地址範圍:0X1FFF7800~0X1FFF7A0F
//WriteAddr:起始地址(此地址必須爲4的倍數!!)
//pBuffer:數據指針
//NumToWrite:字(32位)數(就是要寫入的32位數據的個數.) 
void STMFLASH_Write(u32 WriteAddr,u32 *pBuffer,u32 NumToWrite)    
{ 
    FLASH_Status status = FLASH_COMPLETE;
    u32 addrx=0;
    u32 endaddr=0;    
    if(WriteAddr<STM32_FLASH_BASE||WriteAddr%4)return;    //非法地址
    FLASH_Unlock();     //解鎖 
    FLASH_DataCacheCmd(DISABLE);//FLASH擦除期間,必須禁止數據緩存

    addrx=WriteAddr;                //寫入的起始地址
    endaddr=WriteAddr+NumToWrite*4;    //寫入的結束地址
    if(addrx<0X1FFF0000)            //只有主存儲區,才需要執行擦除操作!!
    {
        while(addrx<endaddr)        //掃清一切障礙.(對非FFFFFFFF的地方,先擦除)
        {
            if(STMFLASH_ReadWord(addrx)!=0XFFFFFFFF)//有非0XFFFFFFFF的地方,要擦除這個扇區
            {   
                status=FLASH_EraseSector(STMFLASH_GetFlashSector(addrx),VoltageRange_3);//VCC=2.7~3.6V之間!!
                if(status!=FLASH_COMPLETE)break;    //發生錯誤了
            }else addrx+=4;
        } 
    }
    if(status==FLASH_COMPLETE)
    {
        while(WriteAddr<endaddr)//寫數據
        {
            if(FLASH_ProgramWord(WriteAddr,*pBuffer)!=FLASH_COMPLETE)//寫入數據
            { 
                break;    //寫入異常
            }
            WriteAddr+=4;
            pBuffer++;
        } 
    }
  FLASH_DataCacheCmd(ENABLE);    //FLASH擦除結束,開啓數據緩存
    FLASH_Lock();//上鎖
} 

//從指定地址開始讀出指定長度的數據
//ReadAddr:起始地址
//pBuffer:數據指針
//NumToRead:字(4位)數
void STMFLASH_Read(u32 ReadAddr,u32 *pBuffer,u32 NumToRead)       
{
    u32 i;
    for(i=0;i<NumToRead;i++)
    {
        pBuffer[i]=STMFLASH_ReadWord(ReadAddr);//讀取4個字節.
        ReadAddr+=4;//偏移4個字節.
    }
}


void FLASHEXT_ReadFlash( u8 *pbData, u32 dwDataLen )
{  
    u32  Len;
    u32  dwData;
    u32  i=0,j=0;

    
    Len=  dwDataLen/4+((dwDataLen%4)?1:0); 

    STMFLASH_Read(FLASH_SAVE_ADDR,(u32*)(pbData),Len);
  
    return;
}

void FLASHEXT_WriteFlash( u8 *pbData, u32 dwDataLen )
{
          
    u32     Len;
    u32     dStartTime;
    u8      pu8ReadData[60];
    u8      i=0;
    Len=  dwDataLen/4+((dwDataLen%4)?1:0);
   
    STMFLASH_Read(FLASH_SAVE_ADDR,(u32*)(pu8ReadData),Len);

    for(i=0;i<dwDataLen;i++)
    {
       if(pbData[i]!=pu8ReadData[i])
       {
           STMFLASH_Write(FLASH_SAVE_ADDR,(u32*)(pbData),Len); 
           break;
       }
    }
    

    return ;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章