📄 c2188.c
字号:
/* Issue the Program Command*/
NAND_CommandInput((ubyte)0x10);
/* Wait for ready */
ubStatus=waitForReady();
NAND_Close();
if( (ubStatus&(0x80))==0)
return ubStatus&(0x80);
return ubStatus&(0x01);
}
/************** NAND_CopyBack ***************/
/******************************************************************************
NAND_CacheProgram
Function: NAND_Ret NAND_CacheProgram(udword udPageAddresses[],
ubyte piecesNumber,ubyte *Buffers[],
udword udlength[],ubyte* errorPage)
Arguments: udPageAddresses:
The addresses of page where copy in.
piecesNumber:
the number of data pieces to write
Buffers:
buffer of data to write
udlength:
the size of each piece of data to write
errorPage:
the number of the page where (if happen) the cache program
have failed
Return Value: NAND_FLASH_SIZE_OVERFLOW:
The address is not within the flash
NAND_PASS
The operation are successfully executed
NAND_FAIL
The operation are not successfully executed.
NAND_WRONG_ADDRESS
The pages are not in the same half of the flash.
Description: This function issue a cache program command as explained in the
datasheet of the 2112 byte/1056 word page family.
The function stores in errorPage parameter, the page where the
program have failed(if it happen)
******************************************************************************/
NAND_Ret NAND_CacheProgram(udword udPageAddresses[],ubyte piecesNumber, dataWidth **Buffers, uword udlength[],ubyte* errorPage)
{
ubyte ubStatus;
udword index;
ubyte i,j;
byte lastPage=-1;
byte currentPage=0;
byte prev,next;
ubyte count;
int val,value;
ubyte random_op;
/*check addresses*/
for (i=0; i<piecesNumber; i++){
/*check if the addresses are within a same block*/
if (ADDRESS_2_BLOCK(udPageAddresses[i]) != ADDRESS_2_BLOCK(udPageAddresses[0]) )
return NAND_WRONG_ADDRESS;
/*check if the addresses are within the flash*/
if (udPageAddresses[i]>=FLASH_SIZE)
return NAND_FLASH_SIZE_OVERFLOW;
/*check if there is an overflow in main or spare*/
if ((udlength[i] & 0x8000) != 0) {
/*IN SPARE */
if (( (udPageAddresses[i] & (0x000003FF<<SHIFT_A8)) + (udlength[i]&0x7FFF) ) > PAGE_SPARE_SIZE) {
return NAND_FAIL;
}
} else
/* IN MAIN */
if ( ( (udPageAddresses[i] & (0x000003FF<<SHIFT_A8)) + udlength[i]) > PAGE_SIZE) {
return NAND_FAIL;
}
/*check if there is an overlapping*/
prev = ( udPageAddresses[i] & (0x0000FC00<<SHIFT_A8) ) >> (10+SHIFT_A8);
for (j=i+1; j<piecesNumber; j++){
/*check if the addresses are within a same block*/
if (ADDRESS_2_BLOCK(udPageAddresses[j]) != ADDRESS_2_BLOCK(udPageAddresses[0]) )
return NAND_WRONG_ADDRESS;
next = ( udPageAddresses[j] & (0x0000FC00<<SHIFT_A8) ) >> (10+SHIFT_A8);
/* the same page*/
if (prev == next) {
/* i spare ~ j spare */
if ( ((udlength[i] & 0x8000) != 0) && ((udlength[j] & 0x8000) != 0) ) {
if (udPageAddresses[j]>udPageAddresses[i]){ /* j address > i address */
if ( ((udPageAddresses[i] & (0x000003FF<<SHIFT_A8))+(udlength[i]&0x7FFF) ) > (udPageAddresses[j] & (0x000003FF<<SHIFT_A8)) ) {
return NAND_FAIL;
}
} else { /* i address > j address */
if ( ((udPageAddresses[j] & (0x000003FF<<SHIFT_A8))+(udlength[j]&0x7FFF) ) > (udPageAddresses[i] & (0x000003FF<<SHIFT_A8)) ) {
return NAND_FAIL;
}
}
}
/* i main ~ j main */
if ( ((udlength[i] & 0x8000) == 0) && ((udlength[j] & 0x8000) == 0) ) {
if (udPageAddresses[j]>udPageAddresses[i]){ /* j address > i address */
if ( ((udPageAddresses[i] & (0x000003FF<<SHIFT_A8))+(udlength[i]&0x7FFF) ) > (udPageAddresses[j] & (0x000003FF<<SHIFT_A8)) ) {
return NAND_FAIL;
}
} else { /* i address > j address */
if ( ((udPageAddresses[j] & (0x000003FF<<SHIFT_A8))+(udlength[j]&0x7FFF) ) > (udPageAddresses[i] & (0x000003FF<<SHIFT_A8)) ) {
return NAND_FAIL;
}
}
}
/* i main ~ j spare */
if ( ((udlength[i] & 0x8000) == 0) && ((udlength[j] & 0x8000) != 0) ){
if ( ((udPageAddresses[i] & (0x000003FF<<SHIFT_A8))+udlength[i]) > (udPageAddresses[j] & (0x000003FF<<SHIFT_A8))+PAGE_DATA_SIZE ) {
return NAND_FAIL;
}
}
/* i spare ~ j main */
if ( ((udlength[i] & 0x8000) != 0) && ((udlength[j] & 0x8000) == 0) ){
if ( ((udPageAddresses[j] & (0x000003FF<<SHIFT_A8))+udlength[j]) > (udPageAddresses[i] & (0x000003FF<<SHIFT_A8))+PAGE_DATA_SIZE ) {
return NAND_FAIL;
}
}
}
}
}
/* program flash */
count = 0;
val = -1;
value =-1;
do {
for (j=0; j<piecesNumber; j++){
next = ( udPageAddresses[j] & (0x0000FC00<<SHIFT_A8) ) >> (10+SHIFT_A8);
if ( ( next != value) && ( next > val ) ) {
value = next;
break;
}
}
/* find the min page different to previous min ( val ) */
for (j=0; j<piecesNumber; j++){
next = ( udPageAddresses[j] & (0x0000FC00<<SHIFT_A8) ) >> (10+SHIFT_A8);
if ( (val == -1) && ( next < value ) ) {
value = next;
} else {
if ((val != -1) && ( next > val ) && ( next < value ) ) {
value = next;
}
}
}
val = value;
/* Perform cache program with random data input of the chuncks with page address equal to val*/
random_op = 0 ;
for (i=0; i<piecesNumber; i++) {
next = ( udPageAddresses[i] & (0x0000FC00<<SHIFT_A8) ) >> (10+SHIFT_A8);
if (next == val) {
count++;
if ( random_op) {
/* Issue random Data input command */
NAND_CommandInput((ubyte)0x85);
/* insert the column address */
if((udlength[i]&0x8000)==0x8000){
InsertColumnAddressSpare(udPageAddresses[i]);
}else{
InsertColumnAddress(udPageAddresses[i]);
}
/* write data */
#ifdef DMA_ENABLE
/* to be implemented*/
#else
for (index=0; index<((0x7FFF)&udlength[i]);index++)
NAND_DataInput(*((*(Buffers+i))+index));
#endif
} else {
/* Issue page program code */
NAND_CommandInput((ubyte)0x80);
/* insert the address */
if((udlength[i]&0x8000)==0x8000){
InsertSpareAddress(udPageAddresses[i]);
}else{
InsertAddress(udPageAddresses[i]);
}
/* write data */
#ifdef DMA_ENABLE
/* to be implemented*/
#else
for (index=0;index<((0x7FFF)&udlength[i]);index++)
NAND_DataInput(*((*(Buffers+i))+index));
#endif
}
random_op = 1;
}
}
if (count<piecesNumber){
/* issue cache program confirm code */
NAND_CommandInput((ubyte)0x15);
/* Wait for Cache Register ready, SR6=1 */
NAND_CommandInput((ubyte)0x70);
ubStatus = NAND_DataOutput();
ubStatus = waitForReady();
if ((ubStatus & 0x02) == 0x01) {
*errorPage = lastPage;
NAND_Close();
return NAND_FAIL;
}
}
} while (count<piecesNumber);
/* issue page program confirm code */
NAND_CommandInput((ubyte)0x10);
ubStatus = waitForReady();
if ((ubStatus & 0x01) == 0x01) {
*errorPage = currentPage;
NAND_Close();
return NAND_FAIL;
}
NAND_Close();
return NAND_PASS;
}
/******************************************************************************
NAND_ReadElectronicSignature
Function: void NAND_ReadElectronicSignature(ubyte *Buffer)
Arguments: Buffer:
contains the byte returned from ReadElectronicSignature
command.
Return Value: na
Description: The ReadElectronicSignature operation issue a
ReadElectronicSignature Command as explained in the datasheet
of the 2112 byte/1056 word page family.
******************************************************************************/
void NAND_ReadElectronicSignature(dataWidth *Buffer) {
ubyte ubIndex;
NAND_Open();
/* Insert ReadElectronicSignature command */
NAND_CommandInput((ubyte)0x90);
/* Issue the address */
NAND_AddressInput((ubyte)0x00); /* first address byte */
/* read data */
for (ubIndex=0;ubIndex<4;ubIndex++)
Buffer[ubIndex]= NAND_DataOutput();
NAND_Close();
}
/******************************************************************************
NAND_Reset
Function: void NAND_Reset(void)
Arguments: na
Return Value: na
Description: The Reset operation issue a Reset Command as explained in the
datasheet of the 2112 byte/1056 word page family.
******************************************************************************/
void NAND_Reset(void) {
NAND_Open();
/* Issue the Reset Command*/
NAND_CommandInput((ubyte)0xFF);
NAND_Close();
}
/************** NAND_Reset ***************/
/******************************************************************************
NAND_Lock
Function: void NAND_Lock(void)
Arguments: na
Return Value: na
Description: The NAND_Lock function issue a Lock Command as explained in the
datasheet of the 2112 byte/1056 word page family.
******************************************************************************/
void NAND_Lock(void)
{
NAND_Open();
/*issue the lock command*/
NAND_CommandInput((ubyte)0x2A);
NAND_Close();
}
/******************************************************************************
LockDown
Function: void NAND_LockDown(void)
Arguments: na
Return Value: na
Description: The NAND_LockDown function issue a Lock Down Command as
explained in the datasheet of the 2112 byte/1056 word page
family.
******************************************************************************/
void NAND_LockDown(void)
{
NAND_Open();
/*issue the lock down command*/
NAND_CommandInput((ubyte)0x2C);
NAND_Close();
}
/******************************************************************************
NAND_UnLock
Function: void NAND_UnLock(udword startBlock,udword endBlock)
Arguments: startBlock:
the address of the first block to unlock
endBlock:
the address of the last block to unlock
Return Value: NAND_WRONG_ADDRESS
the addresses provide as arguments aren't valid
NAND_FLASH_SIZE_OVERFLOW:
the addresses provided as arguments exceedes the flash size
Description: The NAND_UnLock function issue a UnLock Command as explained
in the datasheet of the 2112 byte/1056 word page family.
******************************************************************************/
NAND_Ret NAND_UnLock(udword startBlock,udword endBlock)
{
if(((startBlock%BLOCK_SIZE)!=0)||((startBlock%BLOCK_SIZE)!=0)||(startBlock>endBlock))
return NAND_WRONG_ADDRESS;
if( (startBlock >= FLASH_SIZE )||(endBlock >= FLASH_SIZE))
return NAND_FLASH_SIZE_OVERFLOW;
NAND_Open();
/*issue lock command*/
NAND_CommandInput((ubyte)0x23);
InsertBlockAddress(startBlock);
NAND_CommandInput((ubyte)0x24);
InsertBlockAddress(endBlock);
NAND_Close();
return NAND_PASS;
}
/******************************************************************************
NAND_ReadBlockLockStatus(udword address)
Function: NAND_Ret NAND_ReadBlockLockStatus(udword address)
Arguments: address:
the address of the block to check
Return Value: NAND_WRONG_ADDRESS
the addresse provided isn't valid
NAND_FLASH_SIZE_OVERFLOW:
the addresse provided as argument exceede the flash size
NAND_UNLOCKED_BLOCK
the block is not locked
NAND_LOCKED_BLOCK
the block is locked
NAND_LOCK_DOWN
the block is locked tight
Description: The NAND_ReadBlockLockStatus function issue a read block lock
status Command as explained in the datasheet of the
2112 byte/1056 word page family.
******************************************************************************/
NAND_Ret NAND_ReadBlockLockStatus(udword address)
{
ubyte ubStatus;
if((address%BLOCK_SIZE)!=0)
return NAND_WRONG_ADDRESS;
if( address >= FLASH_SIZE )
return NAND_FLASH_SIZE_OVERFLOW;
NAND_Open();
/*read lock status command*/
NAND_CommandInput((ubyte)0x7A);
InsertBlockAddress(address);
/*read the block lock status*/
ubStatus=NAND_DataOutput();
return ubStatus&0x0f;
NAND_Close();
return NAND_PASS;
}
/******************************************************************************
NAND_UnlockDown()
Function: void NAND_UnlockDown()
Arguments: na
Return Value: na
Description: The NAND_UnlockDown function unlocks Locked-Down blocks
******************************************************************************/
void NAND_UnlockDown(){
NAND_Open();
NAND_SetWriteProtect();
/* wait almost 100ns as explained in the datasheet */
NAND_WaitTime(100);
NAND_UnsetWriteProtect();
NAND_Close();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -