?? c2312.c
字號:
completed
Step 7: Return to Read mode (if an error occurred)
*******************************************************************************/
ReturnType FlashMultipleBlockErase(uBlockType ublNumBlocks,uBlockType *ublpBlock,ReturnType *rpResults) {
ReturnType rRetVal = Flash_Success, /* Holds return value: optimistic initially! */
rProtStatus; /* Holds the protection status of each block */
uBlockType ublCurBlock; /* Range Variable to track current block */
uCPUBusType ucFirstRead, ucSecondRead; /* used to check toggle bit DQ2 */
/* Step 1: Check for invalid block. */
if( ublNumBlocks > NUM_BLOCKS ){ /* Check specified blocks <= NUM_BLOCKS */
eiErrorInfo.sprRetVal = FlashSpec_TooManyBlocks;
return Flash_SpecificError;
} /* EndIf */
/* Step 2: Check if some blocks are protected */
for (ublCurBlock=0; ublCurBlock < ublNumBlocks;ublCurBlock++) {
if (FlashCheckBlockProtection(ublCurBlock)==Flash_BlockProtected) {
rProtStatus = Flash_BlockProtected;
rRetVal = Flash_BlockEraseFailed;
} else
rProtStatus =Flash_Success;
if (rpResults != NULL)
rpResults[ublCurBlock] = rProtStatus;
} /* Next ublCurBlock */
/* Step 3: Write Block Erase command */
FlashWrite( ConvAddr(0x00555), (uCPUBusType)CMD(0x00AA) );
FlashWrite( ConvAddr(0x002AA), (uCPUBusType)CMD(0x0055) );
FlashWrite( ConvAddr(0x00555), (uCPUBusType)CMD(0x0080) );
FlashWrite( ConvAddr(0x00555), (uCPUBusType)CMD(0x00AA) );
FlashWrite( ConvAddr(0x002AA), (uCPUBusType)CMD(0x0055) );
/* DSI!: Disable Interrupt, Time critical section. Additional blocks must be added
every 50us */
for( ublCurBlock = 0; ublCurBlock < ublNumBlocks; ublCurBlock++ ) {
FlashWrite( BlockOffset[ublpBlock[ublCurBlock]], (uCPUBusType)CMD(0x0030) );
/* Check for Erase Timeout Period (is bit DQ3 set?)*/
if( (FlashRead( BlockOffset[ublpBlock[0]] ) & CMD(0x0008)) != 0 )
break; /* Cannot set any more blocks due to timeout */
} /* Next ublCurBlock */
/* ENI!: Enable Interrupt */
/* Step 4: Check for time-out blocks */
/* if timeout occurred then check if current block is erasing or not */
/* Use DQ2 of status register, toggle implies block is erasing */
if ( ublCurBlock < ublNumBlocks ) {
ucFirstRead = FlashRead( BlockOffset[ublpBlock[ublCurBlock]] ) & CMD(0x0004);
ucSecondRead = FlashRead( BlockOffset[ublpBlock[ublCurBlock]] ) & CMD(0x0004);
if( ucFirstRead != ucSecondRead )
ublCurBlock++; /* Point to the next block */
if( ublCurBlock < ublNumBlocks ){
/* Indicate that some blocks have been timed out of the erase list */
rRetVal = Flash_SpecificError;
eiErrorInfo.sprRetVal = FlashSpec_MpuTooSlow;
} /* EndIf */
/* Now specify all other blocks as not being erased */
while( ublCurBlock < ublNumBlocks ) {
rpResults[ublCurBlock++] = Flash_BlockEraseFailed;
} /* EndWhile */
} /* EndIf ( ublCurBlock < ublNumBlocks ) */
/* Step 5: Wait for the Erase Timer Bit (DQ3) to be set */
FlashTimeOut(0); /* Initialize TimeOut Counter */
while( !(FlashRead( BlockOffset[ublpBlock[0]] ) & CMD(0x0008) ) ){
if (FlashTimeOut(5) == Flash_OperationTimeOut) {
FlashWrite( ANY_ADDR, (uCPUBusType)CMD(0x00F0) ); /* Use single instruction
cycle method */
return Flash_OperationTimeOut;
} /* EndIf */
} /* EndWhile */
/* Step 6: Follow Data Toggle Flow Chart until Program/Erase Controlle completes */
if( FlashDataToggle(BlockOffset[ublpBlock[0]]) != Flash_Success ) {
if (rpResults != NULL) {
for (ublCurBlock=0;ublCurBlock < ublNumBlocks;ublCurBlock++)
if (rpResults[ublCurBlock]==Flash_Success)
rpResults[ublCurBlock] = FlashCheckBlockEraseError(ublCurBlock);
} /* EndIf */
/* Step 7: Return to Read mode (if an error occurred) */
FlashWrite( ANY_ADDR, (uCPUBusType)CMD(0x00F0) ); /* Use single instruction cycle method */
rRetVal=Flash_BlockEraseFailed;
} /* EndIf */
return rRetVal;
} /* EndFunction FlashMultipleBlockErase */
/*******************************************************************************
Function: void FlashPause( udword udMicroSeconds )
Arguments: udMicroSeconds is the length of the pause in microseconds
Returns: None
Description: This routine returns after udMicroSeconds have elapsed. It is used
in several parts of the code to generate a pause required for correct
operation of the flash part.
Pseudo Code:
Step 1: Initilize clkReset variable.
Step 2: Count to the required size.
*******************************************************************************/
#ifdef TIME_H_EXISTS
/*-----------------------------------------------------------------------------
Note:The Routine uses the function clock() inside of the ANSI C library "time.h".
-----------------------------------------------------------------------------*/
static void FlashPause(udword udMicroSeconds){
clock_t clkReset,clkCounts;
/* Step 1: Initialize clkReset variable */
clkReset=clock();
/* Step 2: Count to the required size */
do
clkCounts = clock()-clkReset;
while (clkCounts < ((CLOCKS_PER_SEC/1e6L)*udMicroSeconds));
} /* EndFunction FlashPause */
#else
/*-----------------------------------------------------------------------------
Note: The routine here works by counting. The user may already have a more suitable
routine for timing which can be used.
-----------------------------------------------------------------------------*/
static void FlashPause(udword udMicroSeconds) {
static udword udCounter;
/* Step 1: Compute the count size */
udCounter = udMicroSeconds * COUNT_FOR_MICROSECOND;
/* Step 2: Count to the required size */
while( udCounter > 0 ) /* Test to see if finished */
udCounter--; /* and count down */
} /* EndFunction FlashPause */
#endif
/*******************************************************************************
Function: ReturnType FlashProgram( udword udMode, udword udAddrOff,
udword udNrOfElementsInArray, void *pArray )
Arguments: udMode changes between programming modes
udAddrOff is the address offset into the flash to be programmed
udNrOfElementsInArray holds the number of elements (uCPUBusType) in the array.
pArray is a void pointer to the array with the contents to be programmed.
Return Value: The function returns the following conditions:
Flash_Success
Flash_AddressInvalid
Flash_ProgramFailed
Description: This function is used to program an array into the flash. It does
not erase the flash first and will not produce proper results, if the block(s)
are not erased first.
Any errors are returned without any further attempts to program other addresses
of the device. The function returns Flash_Success when all addresses have
successfully been programmed.
Note: Two program modes are available:
- udMode = 0, Normal Program Mode
The number of elements (udNumberOfElementsInArray) contained in pArray
are programmed directly to the flash starting with udAddrOff.
- udMode = 1, Single Value Program Mode
? Only the first value of the pArray will be programmed to the flash
starting from udAddrOff.
.
Pseudo Code:
Step 1: Check whether the data to be programmed are are within the
Flash memory
Step 2: Determine first and last block to program
Step 3: Check protection status for the blocks to be programmed
Step 4: Issue the Unlock Bypass command
Step 5: Unlock Bypass Program command
Step 6: Wait until Program/Erase Controller has completed
Step 7: Return to Read Mode
Step 8: Decision between direct and single value programming
Step 9: Unlock Bypass Reset
*******************************************************************************/
ReturnType FlashProgram(udword udMode, udword udAddrOff, udword udNrOfElementsInArray, void *pArray ) {
ReturnType rRetVal = Flash_Success; /* Return Value: Initially optimistic */
ReturnType rProtStatus; /* Protection Status of a block */
uCPUBusType *ucpArrayPointer; /* Use an uCPUBusType to access the array */
udword udLastOff; /* Holds the last offset to be programmed */
uBlockType ublFirstBlock; /* The block where start to program */
uBlockType ublLastBlock; /* The last block to be programmed */
uBlockType ublCurBlock; /* Current block */
if (udMode > 1)
return Flash_FunctionNotSupported;
/* Step 1: Check if the data to be programmed are within the Flash memory space */
udLastOff = udAddrOff + udNrOfElementsInArray - 1;
if( udLastOff >= FLASH_SIZE )
return Flash_AddressInvalid;
/* Step 2: Determine first and last block to program */
for (ublFirstBlock=0; ublFirstBlock < NUM_BLOCKS-1;ublFirstBlock++)
if (udAddrOff < BlockOffset[ublFirstBlock+1])
break;
for (ublLastBlock=ublFirstBlock; ublLastBlock < NUM_BLOCKS-1;ublLastBlock++)
if (udLastOff < BlockOffset[ublLastBlock+1])
break;
/* Step 3: Check protection status for the blocks to be programmed */
for (ublCurBlock = ublFirstBlock; ublCurBlock <= ublLastBlock; ublCurBlock++){
if ( (rProtStatus = FlashCheckBlockProtection(ublCurBlock)) != Flash_BlockUnprotected ){
rRetVal = Flash_BlockProtected;
if (ublCurBlock == ublFirstBlock){
eiErrorInfo.udGeneralInfo[0] = udAddrOff;
return rRetVal;
} else {
eiErrorInfo.udGeneralInfo[0] = BlockOffset[ublCurBlock];
udLastOff = BlockOffset[ublCurBlock]-1;
} /* EndIf ublCurBlock */
} /* EndIf rProtStatus */
} /* Next ublCurBlock */
/* Step 4: Issue the Unlock Bypass command */
FlashWrite( ConvAddr(0x00555), (uCPUBusType)CMD(0x00AA) ); /* 1st cycle */
FlashWrite( ConvAddr(0x002AA), (uCPUBusType)CMD(0x0055) ); /* 2nd cycle */
FlashWrite( ConvAddr(0x00555), (uCPUBusType)CMD(0x0020) ); /* 3nd cycle */
ucpArrayPointer = (uCPUBusType *)pArray;
/* Step 5: Unlock Bypass Program command */
while( udAddrOff <= udLastOff ){
FlashWrite( ANY_ADDR, CMD(0x00A0) ); /* 1st cycle */
FlashWrite( udAddrOff, *ucpArrayPointer ); /* 2nd Cycle */
/* Step 6: Wait until Program/Erase Controller has completed */
if( FlashDataToggle(udAddrOff) != Flash_Success){
/* Step 7: Return to Read Mode */
FlashWrite( ANY_ADDR, (uCPUBusType)CMD(0x00F0) ); /* Use single instruction cycle method */
rRetVal=Flash_ProgramFailed;
eiErrorInfo.udGeneralInfo[0] = udAddrOff;
break; /* exit while cycle */
} /* EndIf */
/* Step 8: Decision between direct and single value programming */
if (udMode == 0) /* Decision between direct and single value programming */
ucpArrayPointer++;
udAddrOff++;
} /* EndWhile */
/* Step 9: Unlock Bypass Reset */
FlashWrite( ANY_ADDR, (uCPUBusType)CMD(0x0090) ); /* 1st cycle */
FlashWrite( ANY_ADDR, (uCPUBusType)CMD(0x0000) ); /* 2st cycle */
return rRetVal;
} /* EndFunction FlashProgram */
/*******************************************************************************
Function: ReturnType FlashQuadProgram( udword udAddrOff, uCPUBusType ucValue1,
uCPUBusType ucValue2,uCPUBusType ucValue3, uCPUBusType ucValue4 )
Arguments: udAddrOff is the address to program.
ucValue1, ucValue2, ucValue3 and ucValue4 are the values to program
on the chip
Return Value: The function returns the following conditions:
Flash_Success
Flash_ProgramFailed
Note:
1) This procedure is available both in 8-bit/16-bit mode.
2) This procedure automatically put the 2 least significati bits of udAddrOff
to zero, to align the address with a quad-bytes/words boundary.
Description: This function programs four consecutive byte/words, starting from the
quadbytes/quadwords boundary.
Pseudo Code:
Step 1: Align address to quadbytes/quadwords boundary
Step 2: Program
Step 3: Wait until the Program/Erase Controller has completed
Step 4: Return to read Array mode
********************************************************************************/
ReturnType FlashQuadProgram( udword udAddrOff, uCPUBusType ucValue1, uCPUBusType ucValue2,
uCPUBusType ucValue3, uCPUBusType ucValue4 ) {
ReturnType rRetVal = Flash_Success; /* Return value */
/* Step 1: Align address to QUAD-BYTE/Word boundary */
udAddrOff = udAddrOff & (0xFFFFFFFC);
/* Step 2: Program */
/* Note: the command is expressed with ConvAddr, because it is possible both 8bit and 16bit mode*/
FlashWrite( ConvAddr(0x0555), CMD(0x0056) ); /* Quadruple Byte Command */
FlashWrite( udAddrOff, ucValue1 );
FlashWrite( udAddrOff+1, ucValue2 );
FlashWrite( udAddrOff+2, ucValue3 );
FlashWrite( udAddrOff+3, ucValue4 );
/* Step 3: Wait until Program/Erase Controller has completed */
if (FlashDataToggle(udAddrOff) != Flash_Success)
rRetVal = Flash_ProgramFailed;
/* Step 4: Return to read Array mode */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -