?? cell.c
字號:
/**
* Cell.c
*
*/
#include "Cell.h"
#include "CellTable.h"
#include "CellInfo.h"
#include "Block.h"
#include "BlockTable.h"
#include "Sector.h"
#include "SectorInfo.h"
#include "SectorHeader.h"
#include <malloc.h>
extern SECTOR_DESCRIPTIOR gpDeviceArchitecture[];
/**
* dms_CellRead
*
* This function reads cell data from the Flash. The location
* that the data is stored is designated in apData. apData
* must be allocated before calling this function.
*
* Arguments
* aiCellNumber The cell number to read
* apData The location to put the cell data
* that is stored in the flash.
* Prerequisites:
* dms_CellInitialize();
* Uses:
* dms_CellTableResetBlockPointer()
* dms_CellTableGetNextBlock()
* dms_BlockRead()
* Used By:
* dms_Read()
*/
DMS_STATUS dms_CellRead (WORD awCellIndex, BYTE *apData){
DMS_STATUS eStatus;
WORD wSectorIndex;
WORD wSectorBlockIndex;
WORD wBlockIndex;
/*
* Read each block.
*/
wBlockIndex = 0;
dms_CellTableResetBlockPointer(awCellIndex);
while (dms_CellTableGetNextBlock(&wSectorIndex,&wSectorBlockIndex)){
eStatus = dms_BlockRead(wSectorIndex,wSectorBlockIndex,apData+(((DWORD)sizeof(DATABLOCK))*((DWORD)wBlockIndex)));
if (eStatus != No_Error){
return eStatus;
}
wBlockIndex++;
}
return No_Error;
}
/**
* dms_CellWrite
*
* Writes the apData to the flash in the defined cell.
* The old cell data is destroyed when writing of the new
* cell has completed.
* This function will not return to the calling program until the
* write completes.
* The Cell Write Process:
* Foreach block in existing cell
* write CellValid2 in cell status.
* Foreach block in cell
* Get new block.
* Write BlockBeingWritten in block status.
* Write cell number.
* Write block number.
* Write CellValid1 in cell status.
* Write block data.
* Write BlockValid in block status.
* Foreach old block in cell
* Write BlockErase in block status.
* Add block to garbage count.
*
* Arguments
* aiCellNumber The cell number to write
* apData The location containing the cell data
* that is to be written to the flash.
* Prerequisites:
* dms_CellInitialize();
* Uses:
* dms_CellInfoGetBlockCount()
* dms_CellTableResetBlockPointer()
* dms_CellTableGetNextBlock()
* dms_CellTableSetCellInProcess()
* dms_CellTableGetAvailableBlock()
* dms_CellTableDeleteCellInProcess()
* dms_BlockWrite()
* dms_BlockTableWriteCellStatus()
* dms_BlockTableWriteBlockStatus()
* dms_SectorCleanup()
* Used By:
* dms_Write()
*/
DMS_STATUS dms_CellWrite(WORD awCellIndex, BYTE *apData){
DMS_STATUS eStatus;
WORD wBlockIndex;
WORD wSectorIndex;
WORD wSectorBlockIndex;
/*
* Change cell status of each existing block in cell.
*/
dms_CellTableResetBlockPointer(awCellIndex);
while (dms_CellTableGetNextBlock(&wSectorIndex,&wSectorBlockIndex)){
eStatus = dms_BlockTableWriteCellStatus(wSectorIndex,wSectorBlockIndex,CellValid2);
if (eStatus != No_Error){
return eStatus;
}
}
/* dmsdbg_Printf(" Cell Start Write Of New\n"); */
/* Move cell from cell table to cell in process */
eStatus = dms_CellTableSetCellInProcess(awCellIndex);
if (eStatus != No_Error){
return eStatus;
}
/*
* Get a new block and write the new data for each block in the cell.
* It is better here to write the blocks in reverse order to allow
* efficient insertion of the block entries into the cell table.
* (Adding the block at the beginning of the list instead of having to
* traverse through all the blocks to insert at the end.)
* The condition on the look cannot be wBlockIndex >= 0 because wBlockIndex
* is a WORD which is always positive therefore wBlockIndex + 1 != 0 is
* used.
*/
wBlockIndex = dms_CellInfoGetBlockCount(awCellIndex);
do {
wBlockIndex--; /* Pre-decrement */
eStatus = dms_CellTableGetAvailableBlock(awCellIndex,wBlockIndex,&wSectorIndex,&wSectorBlockIndex);
/* dmsdbg_Printf(" New Block: Status=%d\n",eStatus); */
/* dmsdbg_Printf(" New Block: Cell=%d, Block=%d, Sector=%d, SectorBlock=%d\n",awCellIndex,wBlockIndex,wSectorIndex,wSectorBlockIndex); */
if (eStatus == No_Available_Blocks){
/* perform a clean to free blocks */
eStatus = dms_SectorCleanup();
if (eStatus != No_Error) {
return eStatus;
}
eStatus = dms_CellTableGetAvailableBlock(awCellIndex,wBlockIndex,&wSectorIndex,&wSectorBlockIndex);
if (eStatus != No_Error) {
/* something is wrong because a clean should at least clean one block. */
return eStatus;
}
} else if (eStatus != No_Error) {
return eStatus;
}
eStatus = dms_BlockWrite(awCellIndex,wBlockIndex,(BYTE)CellValid1,wSectorIndex,wSectorBlockIndex,
apData+(((DWORD)sizeof(DATABLOCK))*((DWORD)wBlockIndex)));
if (eStatus != No_Error) {
return eStatus;
}
} while (wBlockIndex != 0);
/* Cleanup any cell that was in process one block at a time. */
while (dms_CellTableDeleteCellInProcess(&wSectorIndex,&wSectorBlockIndex)){
eStatus = dms_BlockTableWriteBlockStatus(wSectorIndex,wSectorBlockIndex,BlockErase);
if (eStatus != No_Error) {
return eStatus;
}
}
return No_Error;
}
/**
* dms_CellInitialize
* Prepairs the DMS software to do Reads and Writes.
*
* Prerequisites:
* gpDeviceArchitecture must be defined.
* Uses:
* dms_SectorInfoDefineArchitecture()
* dms_SectorInfoGetCount()
* dms_SectorInfoFinalize()
* dms_SectorHeaderGetCellCount()
* dms_CellTableInitialize()
* dms_CellTableCheckValidity()
* dms_CellTableDeleteBlockInProcess()
* dms_CellTableDeleteCellInProcess()
* dms_CellTableIsBlockAvailable()
* dms_CellTableFinalize()
* dms_BlockTableWriteBlockStatus()
* dms_SectorInitialize()
* dms_SectorCleanup()
* Used By:
* dms_Initialize()
*/
DMS_STATUS dms_CellInitialize(void)
{
DMS_STATUS eStatus;
WORD wSectorIndex;
WORD wSectorBlockIndex;
WORD wCellCount;
/* dmsdbg_Printf("CellInitialize\n"); */
eStatus = dms_SectorInfoDefineArchitecture(gpDeviceArchitecture);
if (eStatus != No_Error) {
dms_SectorInfoFinalize();
return eStatus;
}
eStatus = dms_SectorHeaderGetCellCount(&wCellCount);
if (eStatus != No_Error) {
dms_SectorInfoFinalize();
return eStatus;
}
eStatus = dms_CellTableInitialize(wCellCount);
if (eStatus != No_Error) {
dms_SectorInfoFinalize();
return eStatus;
}
for (wSectorIndex = 0; wSectorIndex < dms_SectorInfoGetCount(); wSectorIndex++){
/*
* Reads block table of sector and adds blocks to cell table and
* block allocate list
*/
eStatus = dms_SectorInitialize(wSectorIndex);
if (eStatus != No_Error) {
dms_CellTableFinalize();
dms_SectorInfoFinalize();
return eStatus;
}
}
/*
* Check that all the blocks are in each cell. (Note: Cannot detect if
* the last block is missing because it uses the blocks that are found
* to determine the size of each cell.
* Check for a partial cell that was in-process durring a power loss.
*/
eStatus = dms_CellTableCheckValidity();
if (eStatus != No_Error) {
dms_CellTableFinalize();
dms_SectorInfoFinalize();
return eStatus;
}
/* Cleanup any block that was in process */
if(dms_CellTableDeleteBlockInProcess(&wSectorIndex,&wSectorBlockIndex)){
eStatus = dms_BlockTableWriteBlockStatus(wSectorIndex,wSectorBlockIndex,BlockErase);
if (eStatus != No_Error) {
dms_CellTableFinalize();
dms_SectorInfoFinalize();
return eStatus;
}
}
/* Cleanup any cell that was in process one block at a time. */
while (dms_CellTableDeleteCellInProcess(&wSectorIndex,&wSectorBlockIndex)){
eStatus = dms_BlockTableWriteBlockStatus(wSectorIndex,wSectorBlockIndex,BlockErase);
if (eStatus != No_Error) {
dms_CellTableFinalize();
dms_SectorInfoFinalize();
return eStatus;
}
}
/*
* Everything is initialized and ok.
* It is time to do some cleanups.
* If power was lost durring a cleanup where there could be
* many less available blocks than the allowable minimum.
* In which case it may take several ceanups to get above
* the allowable minimum. A dmsWrite allows for only one
* cleanup per block so it would fail if it took more than
* one cleanup to get above the minumum allowable available
* blocks.
* By doing "SectorCount" number of cleanups it guarantees that
* all sectors will be clean and there will be the maximum
* amount of available blocks.
* Stops doing cleanups when the number of free blocks is
* greater than the minimum allowable free block count or
* when no sectors are dirty.
*/
for (wSectorIndex = 0; wSectorIndex < dms_SectorInfoGetCount(); wSectorIndex++){
/*
* do a sector cleanup
*/
if (dms_CellTableIsBlockAvailable()){
/*
* Done enough cleanup for now.
*/
break;
}
eStatus = dms_SectorCleanup();
if (eStatus == No_Garbage_Blocks){
/*
* All Sectors are clean.
* break out of for loop.
*/
break;
} else if (eStatus != No_Error) {
dms_CellTableFinalize();
dms_SectorInfoFinalize();
return eStatus;
}
}
/*
* Ready to read and write.
*/
return No_Error;
}
/**
* dms_CellFormat
*
* Upon completion of dms_CellFormat() the DMS software is
* completely shutdown.
*
* If dms_CellFormat returns anything other than No_Error then
* the flash must be reformated.
*
* Arguments
* aCellSize Array of DWORDS that contains the size,
* in bytes, of each cell. The array index
* is the Cell number and the value in the
* index is the size of the cell.
* awCellCount The number of elements in the array.
* Prerequisites:
* gpDeviceArchitecture must be defined.
* Uses:
* dms_SectorInfoDefineArchitecture()
* dms_SectorInfoGetBlockCount()
* dms_SectorInfoGetCount()
* dms_SectorInfoFinalize()
* dms_SectorFormatAll()
* dms_CellInfoDefineCellList()
* dms_CellInfoGetCount()
* dms_CellInfoGetBlockCount()
* dms_CellInfoFinalize()
* dms_BlockWrite()
* malloc()
* free()
* Used By:
* dms_Format()
*/
DMS_STATUS dms_CellFormat (DWORD *apdwCellSize, WORD awCellCount)
{
DMS_STATUS eStatus;
WORD wSectorIndex;
WORD wSectorBlockCount;
WORD wCellIndex;
WORD wBlockIndex;
WORD wIndex;
BYTE *bEmptyData;
/* dmsdbg_Printf("CellFormat\n"); */
eStatus = dms_SectorInfoDefineArchitecture(gpDeviceArchitecture);
if (eStatus != No_Error) {
return eStatus;
}
eStatus = dms_CellInfoDefineCellList(apdwCellSize, awCellCount);
if (eStatus != No_Error) {
dms_SectorInfoFinalize();
return eStatus;
}
/* erase sectors and write header information */
eStatus = dms_SectorFormatAll(dms_CellInfoGetCount());
if (eStatus != No_Error) {
dms_CellInfoFinalize();
dms_SectorInfoFinalize();
return eStatus;
}
/* Create empty data to fill each new block with */
bEmptyData = (BYTE*) malloc(sizeof(DATABLOCK));
if (bEmptyData == NULL){
dms_CellInfoFinalize();
dms_SectorInfoFinalize();
return Out_Of_Memory_Error;
}
/* Initialize data to 0 */
for (wIndex = 0; wIndex < sizeof(DATABLOCK); wIndex++) bEmptyData[wIndex] = 0;
/* Write each block of each cell into sector block table */
wSectorIndex = 0;
wSectorBlockCount = 0;
for (wCellIndex = 0; wCellIndex < dms_CellInfoGetCount(); wCellIndex++){
for (wBlockIndex = 0; wBlockIndex < dms_CellInfoGetBlockCount(wCellIndex); wBlockIndex++){
if (wSectorBlockCount >= dms_SectorInfoGetBlockCount(wSectorIndex)){
/* Increment through sectors as needed */
wSectorIndex++;
wSectorBlockCount = 0;
if (wSectorIndex >= dms_SectorInfoGetCount()){
free(bEmptyData);
dms_CellInfoFinalize();
dms_SectorInfoFinalize();
return Total_Cell_Size_Too_Large;
}
}
eStatus = dms_BlockWrite(wCellIndex,wBlockIndex,(BYTE)CellValid1,wSectorIndex,wSectorBlockCount,bEmptyData);
if (eStatus != No_Error) {
free(bEmptyData);
dms_CellInfoFinalize();
dms_SectorInfoFinalize();
return eStatus;
}
wSectorBlockCount++;
}
}
/* leave format with everything shut down */
free(bEmptyData);
dms_CellInfoFinalize();
dms_SectorInfoFinalize();
return No_Error;
}
/**
* dms_CellFinalize
* Frees all dynamic memory used by the dms software.
* After this function is called then dms_CellInitialize()
* must be called to use dms again.
* Prerequisites:
* None.
* Uses:
* dms_CellTableFinalize()
* dms_SectorInfoFinalize()
* Used By:
* dms_Shutdown()
*/
void dms_CellFinalize(void)
{
dms_CellTableFinalize();
dms_SectorInfoFinalize();
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -