📄 flashfile.cpp
字号:
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2003, Ulink Telecom Equipment Co., Ltd. All rights reserved.
//
// File:
//
// FlashFile.cpp
//
// Abstract:
//
// implementation of the CFlashFile class.
//
// History:
//
// V1.0 2003-02-27 Alex Duan Original version. (NOTE: file size <= 64k)
// V1.1 2003-07-04 Alex Duan Store the file in the continuous address.
// And all headers are stored in one sector
// together. The only restriction of the file
// size is the free space of the data area.
//
///////////////////////////////////////////////////////////////////////////////
#include "FlashFile.h"
#include "sfr_4510.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CFlashFile::CFlashFile(EFlashType eType)
{
ROMCON rcRom;
rcRom.dwReg = ROMCON0;
DWORD dwAddr = rcRom.bits.base;
dwAddr <<= 16;
m_cFlash.SetType(eType, dwAddr);
memset(&m_fhHeader, 0xFF, sizeof(m_fhHeader));
}
CFlashFile::~CFlashFile()
{
Close(); // Call CFlashFile::Close()
}
///////////////////////////////////////////////////////////////////////////////
// Parameters:
// lpszFileName A string that is the name(8.3) of the desired file.
// nOpenFlags An UINT that defines the file's access mode.
// Return Value:
// TRUE if the open was successful; otherwise FALSE.
// Remarks:
// Open a flash file for reading/writing/creating.
BOOL CFlashFile::Open(LPCSTR lpszFileName, UINT nOpenFlags)
{
ASSERT(lpszFileName);
if (m_nOpenFlags) // file was opened before
return FALSE;
BOOL bRetVal = TRUE;
DWORD dwHeaderAddr;
m_strFileName = lpszFileName;
m_nOpenFlags = nOpenFlags;
if (nOpenFlags & modeCreate)
{// required to create a new file
GetSystemTime(&m_fhHeader.stCreationTime);
UINT nLen = m_strFileName.GetLength();
if (nLen > sizeof(m_fhHeader.szFileName) - 1)
nLen = sizeof(m_fhHeader.szFileName) - 1;
memcpy(m_fhHeader.szFileName, (LPCSTR)m_strFileName, nLen);
m_fhHeader.szFileName[nLen] = '\0';
}
else if (FindFile(lpszFileName, dwHeaderAddr))
{// file found
// copy file header
m_cFlash.Read(&m_fhHeader, dwHeaderAddr, sizeof(FILE_HEADER));
if (m_nOpenFlags & modeRead)
{// read data from flash to memory file
BYTE arruBuff[1024];
DWORD dwAddr = m_fhHeader.dwStartAddr;
DWORD dwSize = m_fhHeader.dwFileSize;
UINT nCount = sizeof(arruBuff);
do
{
if (dwSize < nCount)
{
nCount = dwSize;
}
m_cFlash.Read(arruBuff, dwAddr, nCount);
Write(arruBuff, nCount);
dwAddr += nCount;
dwSize -= nCount;
} while (dwSize);
SeekToBegin();
}
}
else
{
bRetVal = FALSE;
m_strFileName.Empty();
m_nOpenFlags = 0;
}
return bRetVal;
}
///////////////////////////////////////////////////////////////////////////////
// Parameters:
// lpszFileName A string that is the name of the file.
// dwHeaderAddr [out] Start Address of the FILE_HEADER structure
// Return Value:
// TRUE if successful, else FALSE.
// Remarks:
// Find one file in the flash
BOOL CFlashFile::FindFile(LPCSTR lpszFileName, DWORD &dwHeaderAddr) const
{
ASSERT(lpszFileName);
BOOL bRetVal = FALSE;
FILE_HEADER fhHeader;
CString strFileName = lpszFileName;
DWORD dwAddr;
for (dwAddr = m_cFlash.GetSectorAddr(SECTOR_FHEADER_MIN);
dwAddr < m_cFlash.GetSectorNext(SECTOR_FHEADER_MAX);)
{
// Here I do not use the code like the following:
// FILE_HEADER *pfhHeader = (FILE_HEADER*)dwAddr;
// because I do not know whether dwAddr is even or not and
// whether it is writing/erasing now.
m_cFlash.Read(&fhHeader, dwAddr, sizeof(FILE_HEADER));
if (fhHeader.cbSize == (WORD)-1)
{
break;
}
else if (strFileName == (LPCSTR)(fhHeader.szFileName) &&
fhHeader.uFileFlag != FILE_FLAG_DELETED)
{// File name same and no deleted flag
dwHeaderAddr = dwAddr;
bRetVal = TRUE;
break;
}
else if (fhHeader.cbSize == 0)
{// get rid of dead loop
ASSERT(FALSE);
break;
}
else
{
dwAddr += fhHeader.cbSize;
}
}
return bRetVal;
}
///////////////////////////////////////////////////////////////////////////////
// Parameters:
// dwHeaderAddr [out]FILE_HEADER position of the last file
// Return Value:
// TRUE if file exists, otherwise FALSE
// Remarks:
// Find the file in the last position
BOOL CFlashFile::FindLastFile(DWORD &dwHeaderAddr) const
{
FILE_HEADER fhHeader, fhNext;
DWORD dwAddr; // current record address
for (dwAddr = m_cFlash.GetSectorAddr(SECTOR_FHEADER_MIN);
dwAddr < m_cFlash.GetSectorNext(SECTOR_FHEADER_MAX);)
{
// Here I do not use the code like the following:
// FILE_HEADER *pfhHeader = (FILE_HEADER*)dwAddr;
// because I do not know whether dwAddr is even or not and
// whether it is writing/erasing now.
m_cFlash.Read(&fhHeader, dwAddr, sizeof(FILE_HEADER));
m_cFlash.Read(&fhNext, dwAddr + fhHeader.cbSize, sizeof(FILE_HEADER));
if (fhHeader.cbSize == (WORD)-1)
{// The last file isn't found
return FALSE;
}
else if (fhNext.cbSize == (WORD)-1)
{// area in the next record address is blank
dwHeaderAddr = dwAddr;
return TRUE;
}
else if (fhHeader.cbSize == 0)
{
ASSERT(FALSE);
dwAddr += sizeof(FILE_HEADER);
}
else
{
dwAddr += fhHeader.cbSize;
}
}
return FALSE;
}
// Close the file and save the file if necessary.
void CFlashFile::Close()
{
if (m_nOpenFlags & modeWrite)
{
if (GetFreeSpace() < m_nFileSize)
{// file defragment
Defrag();
}
if (GetFreeSpace() >= m_nFileSize)
{
VERIFY(SaveFile());
}
else
{
ASSERT(FALSE);
}
}
m_nPosition = 0;
m_nFileSize = 0;
m_nOpenFlags = 0;
memset(&m_fhHeader, 0xFF, sizeof(m_fhHeader));
}
///////////////////////////////////////////////////////////////////////////////
// Return Value:
// return TRUE if successful, else FALSE.
// Remarks:
// Remove the file (Set deleted flag).
BOOL CFlashFile::Remove()
{
BOOL bRetVal = FALSE;
DWORD dwHeaderAddr;
FILE_HEADER fhHeader;
if (m_nOpenFlags & modeWrite)
{
if (FindFile(m_strFileName, dwHeaderAddr))
{
m_cFlash.Read(&fhHeader, dwHeaderAddr, sizeof(FILE_HEADER));
if (fhHeader.uFileFlag != FILE_FLAG_DELETED)
{
fhHeader.uFileFlag = FILE_FLAG_DELETED;
bRetVal = m_cFlash.Write(dwHeaderAddr, &fhHeader, fhHeader.cbSize);
}
}
}
return bRetVal;
}
///////////////////////////////////////////////////////////////////////////////
// Return Value:
// TRUE if saved successful, otherwise FALSE.
// Remarks:
// SaveFile file from memory to the flash
BOOL CFlashFile::SaveFile()
{
BOOL bRetVal = FALSE; // operation result
FILE_HEADER fhHeader;
DWORD dwNewAddr;
DWORD dwOldAddr;
BOOL bOldFound = FALSE; // found old file with the same name
// set start address of the new file
if (FindLastFile(dwNewAddr))
{
m_cFlash.Read(&fhHeader, dwNewAddr, sizeof(FILE_HEADER));
m_fhHeader.dwStartAddr = fhHeader.dwStartAddr + fhHeader.dwFileSize;
dwNewAddr += fhHeader.cbSize; // new record address
bOldFound = FindFile(m_strFileName, dwOldAddr);
}
else
{
m_fhHeader.dwStartAddr = m_cFlash.GetSectorAddr(SECTOR_FDATA_MIN);
ASSERT(m_fhHeader.dwStartAddr != -1);
dwNewAddr = m_cFlash.GetSectorAddr(SECTOR_FHEADER_MIN);
ASSERT(dwNewAddr != -1);
}
// set other file parameters
m_fhHeader.cbSize = sizeof(FILE_HEADER);
m_fhHeader.dwFileSize = m_nFileSize;
GetSystemTime(&m_fhHeader.stLastWriteTime);
// save new record of the FILE_HEADER
bRetVal = m_cFlash.Write(dwNewAddr, &m_fhHeader, m_fhHeader.cbSize);
BYTE arruBuff[1024];
UINT nCount;
SeekToBegin();
DWORD dwAddr = m_fhHeader.dwStartAddr;
do
{
nCount = Read(arruBuff, sizeof(arruBuff));
bRetVal = m_cFlash.Write(dwAddr, arruBuff, nCount);
dwAddr += nCount;
} while (bRetVal && nCount != 0);
if (bRetVal && bOldFound)
{// delet old file
FILE_HEADER fhHeader;
m_cFlash.Read(&fhHeader, dwOldAddr, sizeof(FILE_HEADER));
fhHeader.uFileFlag = FILE_FLAG_DELETED;
bRetVal = m_cFlash.Write(dwOldAddr, &fhHeader, fhHeader.cbSize);
}
return bRetVal;
}
// file sectors defragment
void CFlashFile::Defrag()
{
CString strFileName;
FILE_HEADER fhHeader;
CFlashFile *pFile = NULL;
CMap<CString, LPCSTR, CFlashFile*, CFlashFile*&> mapFiles;
DWORD dwAddr;
// Open all files to memory
for (dwAddr = m_cFlash.GetSectorAddr(SECTOR_FHEADER_MIN);
dwAddr < m_cFlash.GetSectorNext(SECTOR_FHEADER_MAX);)
{
m_cFlash.Read(&fhHeader, dwAddr, sizeof(FILE_HEADER));
if (fhHeader.cbSize == (WORD)-1)
{
break;
}
else if (fhHeader.uFileFlag != FILE_FLAG_DELETED)
{
strFileName = (LPCSTR)fhHeader.szFileName;
pFile = new CFlashFile;
ASSERT(pFile);
pFile->Open(strFileName, CFile::modeReadWrite);
mapFiles.SetAt(strFileName, pFile);
}
dwAddr += fhHeader.cbSize ? fhHeader.cbSize : sizeof(FILE_HEADER);
}
// Erase all sectors used by file system
UINT i;
for (i = SECTOR_FHEADER_MIN; i <= SECTOR_FHEADER_MAX; i++)
{
VERIFY(m_cFlash.EraseSector(i));
}
for (i = SECTOR_FDATA_MIN; i <= SECTOR_FDATA_MAX; i++)
{
VERIFY(m_cFlash.EraseSector(i));
}
// Close the opened files (will save to flash) & free memory
POSITION pos = mapFiles.GetStartPosition();
while (pos != NULL)
{
mapFiles.GetNextAssoc(pos, strFileName, pFile);
ASSERT(pFile);
delete pFile;
}
mapFiles.RemoveAll();
}
// get free space of the file area.
DWORD CFlashFile::GetFreeSpace() const
{
DWORD dwSpace;
FLASH_SECTOR fsMin, fsMax;
VERIFY(m_cFlash.Lookup(SECTOR_FDATA_MIN, fsMin));
VERIFY(m_cFlash.Lookup(SECTOR_FDATA_MAX, fsMax));
DWORD dwAddr;
if (FindLastFile(dwAddr))
{
if (dwAddr + sizeof(FILE_HEADER) >
m_cFlash.GetSectorNext(SECTOR_FHEADER_MAX))
{//no space to store FILE_HEADER
dwSpace = 0;
}
else
{
FILE_HEADER fhHeader;
m_cFlash.Read(&fhHeader, dwAddr, sizeof(FILE_HEADER));
dwSpace = (fsMax.dwAddr + fsMax.dwSize) -
(fhHeader.dwStartAddr + fhHeader.dwFileSize);
}
}
else
{
dwSpace = fsMax.dwAddr - fsMin.dwAddr + fsMax.dwSize;
}
return dwSpace;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -