本帖最后由 nicholasldf 于 2011-4-11 13:47 编辑
这是我的驱动程序,CPU为atmel的ARM9芯片9260,要注意一下接口的参数,CPU和NandFlash芯片的速度匹配::)
//*----------------------------------------------------------------------------
//* AT91NandFlash_initialise
//*----------------------------------------------------------------------------
int AT91NandFlash_initialise(struct yaffs_dev *dev)
{
/* SMC init - 在汇编代码配置向导中设置读写时序 */
//BOARD_ConfigureNandFlash(8);
//CS Pio Init
AT91_NAND_PIO_CS->IO_PER = AT91_NAND_PIN_CS;//PIO Enable Register
AT91_NAND_PIO_CS->IO_OER = AT91_NAND_PIN_CS;//Output Enable Register
AT91_NAND_PIO_CS->IO_SODR = AT91_NAND_PIN_CS;//Set Output Data Register
//Ready/Busy Pio Init
AT91_NAND_PIO_BUSY->IO_PER = AT91_NAND_PIN_BUSY;//PIO Enable Register
AT91_NAND_PIO_BUSY->IO_ODR = AT91_NAND_PIN_BUSY;//Output Disable Registerr
//reset
AT91NandFlash_Reset();
//check device id - 0xEC76A5C0 or 0xEC765A3F
//it should be samsung k9f1208 device
if(NAND_DEVICE_ID != (0xFFFF0000 & AT91NandFlash_rd_id())){
Debug_Printf(ARM_INTERNAL_UNIT, LOG_ERROR, "NandFlash : read device id failed\n\r");
return YAFFS_FAIL;
}
//Check Device Status Register - 0xC0
if(STATUS_REGISTER_VALUE != AT91NandFlash_rd_status()){
Debug_Printf(ARM_INTERNAL_UNIT, LOG_ERROR, "NandFlash : Status Register Wrong(not %x)\n\r", STATUS_REGISTER_VALUE);
return YAFFS_FAIL;
}else{
return YAFFS_OK;
}
}
//*----------------------------------------------------------------------------
//* AT91F_NandFlash_Reset
//* The device offers a reset feature, executed by writing FFh to the command
//* register. When the device is in Busy state during random read, program or
//* erase mode, the reset operation will abort these operations. The contents
//* of memory cells being altered are no longer valid, as the data will be
//* partially programmed or erased. The command register is cleared to wait
//* for the next command, and the Status Register is cleared to value C0h when
//* WP is high. If the device is already in reset state a new reset command
//* will not be accepted by the command register. The R/B pin transitions to
//* low for tRST after the Reset command is written.
//*----------------------------------------------------------------------------
void AT91NandFlash_Reset(void)
{
NAND_ENABLE_CE();//Enable the NAND Flash device
WRITE_NAND_COMMAND(NAND_CMD_RESET);
//Device Resetting Time(Read/Program/Erase) tRST - 5/10/500uS
OSTimeDlyHMSM(0, 0, 0, 10);//10mS
NAND_WAIT_READY();//Wait for Read/Busy Signal assertion
NAND_DISABLE_CE();//Disable the NAND Flash device
}
//*----------------------------------------------------------------------------
//* AT91NandFlash_rd_id - 0xEC76A5C0 or 0xEC765A3F
//*----------------------------------------------------------------------------
unsigned int AT91NandFlash_rd_id(void)
{
unsigned int DeviceID;
NAND_ENABLE_CE();//Enable the NAND Flash device
// Write the Read ID Command
WRITE_NAND_COMMAND(NAND_CMD_READID);
//Write the Address
WRITE_NAND_ADDRESS(0x00);
//ALE to RE Delay( ID read ) tAR1 10 - ns
//WE High to RE Low tWHR 60 - ns
delay_ns(100);
DeviceID <<= 8;
DeviceID |= READ_NAND();
DeviceID <<= 8;
DeviceID |= READ_NAND();
DeviceID <<= 8;
DeviceID |= READ_NAND();
DeviceID <<= 8;
DeviceID |= READ_NAND();
NAND_DISABLE_CE();//Disable the NAND Flash device
return DeviceID;//should be 0xEC76A5C0 or 0xEC765A3F
}
//*----------------------------------------------------------------------------
//* AT91NandFlash_rd_status
//*----------------------------------------------------------------------------
unsigned char AT91NandFlash_rd_status(void)
{
unsigned char status;
NAND_ENABLE_CE();//Enable the NAND Flash device
WRITE_NAND_COMMAND(NAND_CMD_STATUS);//Status Command
//WE High to RE Low tWHR 60 - ns
//CLE to RE Delay tCLR 50 - ns
delay_ns(100);
//bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0
//NWP(1) Ready(1) - - - - - Pass(0)
status = READ_NAND();//should be 0xC0
NAND_DISABLE_CE();//Disable the NAND Flash device
return status;
}
//*----------------------------------------------------------------------------
//* identifying bad block(s)
//* All device locations are erased(FFh) except locations where the invalid block(s)
//* information is written prior to shipping. The invalid block(s) status is defined
//* by the 6th byte in the spare area. Samsung makes sure that either the 1st or 2nd
//* page of every invalid block has non-FFh data at the Byte address of 517. Since
//* the invalid block information is also erasable in most cases, it is impossible to
//* recover the information once it has been erased. Therefore, the system must be
//* able to recognize the invalid block(s) based on the original invalid block
//* information and create the invalid block table via the following suggested flow
//* chart(Figure 1). Any intentional erasure of the original invalid block
//* information is prohibited.
//*----------------------------------------------------------------------------
unsigned int AT91NandFlash_Identify_Bad_Block(int blockNumber)
{
struct yaffs_spare spare;
unsigned char BlockStatus1;
unsigned char BlockStatus2;
AT91NandFlash_rd_chunk(NULL, blockNumber * NAND_PAGES_PER_BLOCK, NULL, &spare);
BlockStatus1 = spare.block_status;
//CE High Hold Time(at the last serial read) tCEH 100 - ns
delay_ns(100);
AT91NandFlash_rd_chunk(NULL, blockNumber * NAND_PAGES_PER_BLOCK + 1, NULL, &spare);
BlockStatus2 = spare.block_status;
if( (0xFF != BlockStatus1) || (0xFF != BlockStatus2) ){
return YAFFS_FAIL;
}else{
return YAFFS_OK;
}
}
//*----------------------------------------------------------------------------
//* AT91NandFlash_erase_block
//*----------------------------------------------------------------------------
int AT91NandFlash_erase_block(struct yaffs_dev *dev, int blockNumber)
{
/* Block address loading is accomplished in three cycles initiated by an
Erase Setup command(60h). Only address A14 to A26 is valid while A9 to A13
is ignored. */
blockNumber <<= 5;//5 bit page address offset
NAND_ENABLE_CE(); // Enable the NAND Flash device
WRITE_NAND_COMMAND(NAND_CMD_ERASE1);//Erase Command 1
WRITE_NAND_ADDRESS(blockNumber);//block address
WRITE_NAND_ADDRESS(blockNumber >> 8);//block address
WRITE_NAND_ADDRESS(blockNumber >> 16);//block address
WRITE_NAND_COMMAND(NAND_CMD_ERASE2);//Erase Command 2
//WE High to Busy tWB - 100 ns
//Block Erase Time tBERS - 2-3 ms
delay_us(100);
NAND_WAIT_READY();//Wait for Read/Busy Signal assertion
delay_us(2);
NAND_WAIT_READY();//Wait for Read/Busy Signal assertion
NAND_DISABLE_CE();//Disable the NAND Flash device
delay_us(1);
if(AT91NandFlash_rd_status() & STATUS_BIT0_PASS_OR_FAIL){
return YAFFS_FAIL;
}else{
return YAFFS_OK;
}
}
//*----------------------------------------------------------------------------
//* AT91NandFlash_format
//*----------------------------------------------------------------------------
void AT91NandFlash_format(void)
{
unsigned int i;
unsigned int ret = YAFFS_FAIL;
for(i=0; i < NAND_TOTAL_BLOCKS; i++){
//if(YAFFS_OK == AT91NandFlash_Identify_Bad_Block(i))
ret = AT91NandFlash_erase_block(NULL, i);
if(YAFFS_FAIL == ret)
Debug_Printf(ARM_INTERNAL_UNIT, LOG_ERROR, "NandFlash : Block(%d) erase failed\n\r", i);
}
}
//*----------------------------------------------------------------------------
//* AT91NandFlash_List_Bad_Block
//*----------------------------------------------------------------------------
void AT91NandFlash_List_Bad_Block(void)
{
unsigned int i;
for(i=0; i < NAND_TOTAL_BLOCKS; i++){
if(YAFFS_FAIL == AT91NandFlash_Identify_Bad_Block(i))
Debug_Printf(ARM_INTERNAL_UNIT, LOG_ERROR, "NandFlash : Find Bad Block(%d)\n\r", i);
}
} |