📄 nandmtd.c
字号:
#include "tffs/flflash.h"#include "tffs/reedsol.h"#define WRITE_COMMAND(val) (*(volatile UINT8 *)0x02000002 = (UINT8)(val)) /* CLE = A20 */#define WRITE_DATA(val) (*(volatile UINT8 *)0x02000000 = (UINT8)(val)) /* CE = 0 */#define READ_DATA(val) val = *(volatile UINT8 *)0x02000000 /* CE = 0 */#define NAND_EN() rPDATC &=~(0x200)#define NAND_DS() rPDATC |=0x0200#define rPCONC (*(volatile UINT32 *)0x1d20010)#define rPDATC (*(volatile UINT32 *)0x1d20014)#define PAGES_PER_BLOCK 32 /* 16 pages per block on a single chip*//* Flash IDs*/#define K9F2808U0C 0xec73/* Flash commands:*/#define SERIAL_DATA_INPUT 0x80#define READ_MODE_A 0x00#define READ_MODE_B 0x01#define READ_MODE_2 0x50#define RESET_FLASH 0xff#define SETUP_WRITE 0x10#define SETUP_ERASE 0x60#define CONFIRM_ERASE 0xd0#define READ_STATUS 0x70#define READ_ID 0x90#define FAIL 0x01 #undef DEBUG_PRINT printf/* commands for moving flash pointer to areeas A,B or C of page*/typedef enum { AREA_A = READ_MODE_A, AREA_B = READ_MODE_B, AREA_C = READ_MODE_2 } PointerOp;/* customization for this MTD*/typedef struct { unsigned short vendorID; unsigned short chipID; unsigned short pageSize ; /* all....................*/ unsigned short pageMask ; /* ...these...............*/ unsigned short pageAreaSize ; /* .......variables.......*/ unsigned short tailSize ; /* .............interleave*/ unsigned short noOfBlocks ; /* total erasable blocks in flash device*/ FLBuffer *buffer; /* buffer for map through buffer */} Vars;UINT8 mapBuffer[6000];static Vars mtdVars[DRIVES];#define thisVars ((Vars *) vol.mtdVars) void flashPinInit(){ rPCONC&=~(0x0f<<16); rPCONC|=0x01<<18;}LOCAL void WRITE_ADDRESS(UINT8 val){/* UINT8 temp; char i; temp=0; for(i=0;i<8;i++) { temp<<=1; if(val&0x01) temp|=0x01; val>>=1; }*/ *(volatile UINT8 *)0x02000004 = val; } #define TFFS_DEBUG#ifdef TFFS_DEBUGSTATUS checkBlock(short blockNum){ int j; UINT32 address; UINT8 data; NAND_EN(); for(j=0;j<2;j++) { address=0x4000*blockNum+0x200*j+0x05; WRITE_COMMAND(READ_MODE_2); WRITE_ADDRESS((UINT8)address); WRITE_ADDRESS((UINT8)(address >> 9)); WRITE_ADDRESS((UINT8)(address >> 17)); waitForReady(); READ_DATA(data); if(data != 0xFF) { printf("Block %d is a invalid block\n",blockNum ); return ERROR; } } NAND_DS(); return OK;}short checkAllBlock(void){ int i; short badBlockNum=0; for(i=0; i<1024; i++) { if(checkBlock(i)==ERROR) badBlockNum++; } return badBlockNum;}void readFlash(int address, UINT8 *buffer,int length, int mode){ int i, bit8; NAND_EN(); if(mode == 0) { bit8 = (unsigned short)address & 0x100; if(bit8 == 0) WRITE_COMMAND(READ_MODE_A); else WRITE_COMMAND(READ_MODE_B); } else WRITE_COMMAND(READ_MODE_2); WRITE_ADDRESS(address&0xff); WRITE_ADDRESS((address >> 9)&0xff); WRITE_ADDRESS((address >> 17)&0xff); waitForReady(); for(i=0; i<length; i++) { READ_DATA(buffer[i]); } NAND_DS();}FLStatus writeFlash(int address, UINT8 *buffer,int len,int mode){ int i, bit8; /*printf("readFlash: address = 0x%x, length = %d\n", address, length);*/ NAND_EN(); if(mode == 0) { bit8 = (unsigned short)address & 0x100; if(bit8 == 0) WRITE_COMMAND(READ_MODE_A); else WRITE_COMMAND(READ_MODE_B); } else WRITE_COMMAND(READ_MODE_2);/* address += 1; */ WRITE_COMMAND(SERIAL_DATA_INPUT); WRITE_ADDRESS((unsigned char)address); WRITE_ADDRESS((unsigned char)(address >> 9)); WRITE_ADDRESS((unsigned char)(address >> 17)); for(i=0; i<len; i++) { WRITE_DATA(buffer[i]); /* printf("WriteFlash: data = 0x%x\n", data);*/ } WRITE_COMMAND(SETUP_WRITE); waitForReady(); NAND_DS(); if(readStatus() & FAIL) return flWriteFault;}void flashErase(int blockNo){ unsigned short pageNo = blockNo * PAGES_PER_BLOCK ; NAND_EN(); WRITE_COMMAND(SETUP_ERASE); WRITE_ADDRESS((unsigned char)pageNo); /* A9 ~ A16 */ WRITE_ADDRESS((unsigned char)(pageNo >> 8)); /* A17 ~ A22 */ WRITE_COMMAND(CONFIRM_ERASE); waitForReady(); if(readStatus() & FAIL) { printf("block %d failed!\n",blockNo); return flWriteFault; } NAND_DS(); }void flashEraseAll(void){ int i; for(i=0; i<1024; i++) { flashErase(i); }}#endifLOCAL FLBoolean waitForReady (void){ int val; do { val=rPDATC; val &= 0x100; /* R/B PORTE.0 */ } while(val == 0); return TRUE; }LOCAL void makeCommand (PointerOp *cmd, CardAddress address, int modes){ int bit8; if (modes & EXTRA) *cmd = AREA_C; else { bit8 = (unsigned short)address & 0x100; if(bit8 == 0) *cmd = AREA_A; else *cmd = AREA_B; }}LOCAL void setAddress(CardAddress address ){ WRITE_ADDRESS((unsigned char)address); WRITE_ADDRESS((unsigned char)(address >> 9)); WRITE_ADDRESS((unsigned char)(address >> 17));}LOCAL void readCommand (PointerOp cmd, CardAddress address){ WRITE_COMMAND (cmd); /* move flash pointer to respective area of the page*/ setAddress (address); waitForReady();}LOCAL void writeCommand (PointerOp cmd, CardAddress address){ WRITE_COMMAND(cmd); /* move flash pointer to respective area of the page */ WRITE_COMMAND(SERIAL_DATA_INPUT); /* start data loading for write */ setAddress (address);}LOCAL UINT8 readStatus(void){ UINT8 chipStatus ; WRITE_COMMAND(READ_STATUS); READ_DATA(chipStatus); return chipStatus;}UINT8 statusRead(void){ UINT8 chipStatus ; NAND_EN(); WRITE_COMMAND(READ_STATUS); READ_DATA(chipStatus); NAND_DS(); return chipStatus;}LOCAL FLStatus writeExecute (void){ UINT8 chipStatus; WRITE_COMMAND(SETUP_WRITE); /* execute page program*/ WRITE_COMMAND(READ_STATUS); waitForReady(); READ_DATA(chipStatus); if(chipStatus & FAIL) return flWriteFault ; return flOK ;}LOCAL FLStatus readOnePage (FLFlash vol, CardAddress address, /* starting flash address*/ UINT8 FAR1 *buffer, /* target buffer */ int length, /* bytes to read */ int modes) /* EDC flag etc.*/{ FLStatus status = flOK; PointerOp cmd; UINT8 FAR1 *tempBuffer; int oldLenth; UINT8 readBuffer[512]; tempBuffer=buffer; oldLenth=length; /* move flash pointer to areas A,B or C of page*/retry: makeCommand (&cmd, address, modes); taskLock(); NAND_EN(); readCommand (cmd, address); while(length-->0) READ_DATA(*buffer++); readFlash(address,readBuffer,oldLenth,0); taskUnlock(); if(memcmp(tempBuffer,readBuffer,oldLenth)==0) return status; else { printf("read error, retry!\n"); buffer=tempBuffer; length=oldLenth; goto retry; } }LOCAL FLStatus writeOnePage(FLFlash vol, CardAddress address, /* target flash addres */ const UINT8 FAR1 *buffer, /* source RAM buffer */ int length, /* bytes to write (up to BLOCK) */ int modes) /* OVERWRITE, EDC flags etc. */{ FLStatus status=flOK; PointerOp cmd; UINT8 FAR1 *tempBuffer; UINT8 readBuffer[512]; int oldLenth; tempBuffer=buffer; oldLenth=length; if (flWriteProtected(vol.socket)) return flWriteProtect; /* move flash pointer to areas A,B or C of page */ makeCommand (&cmd, address, modes); taskLock(); NAND_EN(); writeCommand (cmd, address); while(length-->0) WRITE_DATA(*buffer++); status = writeExecute(); readFlash(address,readBuffer,oldLenth,0); taskUnlock(); if(memcmp(tempBuffer,readBuffer,oldLenth)!=0) { printf("write %08x error!\n",address); status=flWriteFault; } return status;}LOCAL FLStatus nandMTDRead( FLFlash vol, CardAddress address, /* target flash address */ const FAR1 *buffer, /* source RAM buffer */ int length, /* bytes to write */ int modes) /* Overwrite, EDC flags etc. */{ char FAR1 *temp; int readNow; /* read in sectors; first and last might be partial */ int page = modes & EXTRA ? 16 : 512; readNow = page - ((unsigned short)address & (page - 1)); temp = (UINT8 FAR1 *)buffer; for ( ; length > 0 ; ) { if (readNow > length) /* 如果要读的长度小于一个页面中偏移地址之后的空间大小 */ readNow = length; /* 那要读的就是该长度 04-8-6 */ /* turn off EDC on partial block read*/ /* 如果要读的长度大于一个页面的大小,就先读一个页面 */#ifdef DEBUG_PRINT DEBUG_PRINT("READ: address = 0x%x, length = 0x%x , 0x%x\n", address, readNow,modes);#endif checkStatus(readOnePage(&vol, address, temp, readNow, (readNow != SECTOR_SIZE ? (modes & ~EDC) : modes)) ); length -= readNow; address += readNow; temp += readNow; /* align at sector */ readNow = page; } return flOK ;}void resetFlash(void){ NAND_EN(); WRITE_COMMAND(RESET_FLASH); waitForReady(); NAND_DS();}LOCAL FLStatus nandMTDWrite( FLFlash vol, CardAddress address, /* target flash address*/ const FAR1 *buffer, /* source RAM buffer */ int length, /* bytes to write */ int modes) /* Overwrite, EDC flags etc.*/ { int writeNow; const UINT8 FAR1 *temp; FLStatus status = flOK; /* write in sectors; first and last might be partial*/ int page = modes & EXTRA ? 16 : 512; writeNow = page - ((unsigned short)address & (page - 1)); temp = (const UINT8 FAR1 *)buffer; for ( ; length > 0 ; ) { if (writeNow > length) writeNow = length; status = writeOnePage(&vol, address, temp, writeNow, writeNow != 512 ? (modes & ~EDC) : modes);#ifdef DEBUG_PRINT DEBUG_PRINT("WRITE: address = 0x%x, length = 0x%x, mode = %d\n", address, writeNow, modes);#endif if(status!=flOK) { printf("write flash disk failted!\n"); return flWriteFault; } length -= writeNow; address += writeNow; temp += writeNow; /* align at sector */ writeNow = page; } return flOK ;}LOCAL FLStatus nandMTDErase( FLFlash vol, int blockNo, /* start' block (0 .. chipNoOfBlocks-1)*/ int blocksToErase) /* Number of blocks to be erased */{ int i; FLStatus status = flOK; if (flWriteProtected(vol.socket)) return flWriteProtect; /* blockNo %= thisVars->noOfBlocks; */ /* within flash device */ if ( blockNo + blocksToErase > thisVars->noOfBlocks ) /* accross device boundary */ return flBadParameter; #ifdef DEBUG_PRINT DEBUG_PRINT("firstBlock = 0x%x, numOfBlock = 0x%x\n", blockNo, blocksToErase); #endif for ( i=0; i < blocksToErase; i++, blockNo++ ) { unsigned short pageNo = blockNo * PAGES_PER_BLOCK ; taskLock(); NAND_EN(); WRITE_COMMAND(SETUP_ERASE); WRITE_ADDRESS((unsigned char)pageNo); /* A9 ~ A16 */ WRITE_ADDRESS((unsigned char)(pageNo >> 8)); /* A17 ~ A22 */ WRITE_COMMAND(CONFIRM_ERASE); waitForReady(); if(readStatus() & FAIL) { status = flWriteFault; /* erase operation failed */ } #ifdef DEBUG_PRINT DEBUG_PRINT("ERASE: blockNo = 0x%x\n", blockNo); /* DEBUG_PRINT("ERASE: blockNo = 0x%x\n", blockNo); */ #endif if(checkBlock(blockNo)==ERROR) { taskUnlock(); status=flWriteFault; } taskUnlock(); if (status != flOK) /* reset flash device and abort */ { #ifdef DEBUG_PRINT DEBUG_PRINT("Debug: erase failed in K9F2808U0C.\n"); #endif NAND_EN(); WRITE_COMMAND(RESET_FLASH); waitForReady(); NAND_DS(); break ; } } /* block loop */ return status;}LOCAL void FAR0 * nandMTDMap ( FLFlash vol, CardAddress address, int length ){ nandMTDRead(&vol,address,mapBuffer,length, 0); vol.socket->remapped = 1; return (void FAR0 *)mapBuffer;}static FLBoolean isKnownMedia( FLFlash vol, unsigned short vendorId_p, unsigned short chipId_p, int dev ){ if (dev == 1) { thisVars->vendorID = vendorId_p; /* remember for next chips */ thisVars->chipID = chipId_p; if (vendorId_p == 0xEC) /* Samsung */ { switch (chipId_p) { case 0x73: /*SAMSUNG K9F2808U0C /* 16M */ vol.type=K9F2808U0C; vol.chipSize=0x1000000L; vol.flags|=BIG_PAGE; return TRUE; default: return FALSE; } } } else /* dev != 0*/ if( (vendorId_p == thisVars->vendorID) && (chipId_p == thisVars->chipID) ) return TRUE ; return FALSE ;}LOCAL int readFlashID (FLFlash vol, int dev){ unsigned char vendorId_p, chipId_p; NAND_EN(); WRITE_COMMAND(RESET_FLASH); waitForReady(); WRITE_COMMAND(READ_ID); WRITE_ADDRESS(0x00); /* Address. 1cycle */ READ_DATA(vendorId_p); READ_DATA(chipId_p);/* printf("vendorId=%04x chipId=%04x\n",vendorId_p,chipId_p); */ NAND_DS(); if (isKnownMedia(&vol, vendorId_p, chipId_p, dev) != TRUE) /* no chip or diff.*/ return FALSE ; /* type of flash */ if ( dev == 1 ) { thisVars->pageAreaSize = 0x100 * vol.interleaving; thisVars->pageSize = (vol.flags & BIG_PAGE ? 0x200 : 0x100) * vol.interleaving; thisVars->tailSize = (vol.flags & BIG_PAGE ? 16 : 8) * vol.interleaving; thisVars->pageMask = thisVars->pageSize - 1 ; vol.erasableBlockSize = PAGES_PER_BLOCK * thisVars->pageSize; thisVars->noOfBlocks = (unsigned short)( (vol.chipSize * vol.interleaving) / vol.erasableBlockSize ) ; } return TRUE ;}FLStatus nandMTDIdentify(FLFlash vol){#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: Entering K9F6408U0C identification routine\n");#endif flSetWindowBusWidth(vol.socket,8);/* use 8-bits */ flSetWindowSpeed(vol.socket,120); /* 120 nsec. */ flSetWindowSize(vol.socket,2); /* 4 KBytes */ vol.mtdVars = &mtdVars[flSocketNoOf(vol.socket)]; thisVars->buffer = flBufferOf(flSocketNoOf(vol.socket)); vol.interleaving = 1; vol.noOfChips = 1; /* 以1为起始 */ if(readFlashID(&vol, vol.noOfChips) != TRUE ) { #ifdef DEBUG_PRINT DEBUG_PRINT("Debug: did not identify K9F2808U0C flash media.\n"); #endif return flUnknownMedia; } /* Register our flash handlers */ vol.write = nandMTDWrite; vol.erase = nandMTDErase; vol.read = nandMTDRead; vol.map = nandMTDMap; vol.flags |= SUSPEND_FOR_WRITE;#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: Identified K9F2808U0C.\n");#endif return flOK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -