⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flashfile.cpp

📁 基于Nuleus操作系统和s3c4510的编写的EFC。已经包含了该EFC的设计说明。这是个实际产品的代码
💻 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 + -