📄 nanddrvr.c
字号:
/*-----------------------------------------------------------------*/
while ((MPC860_SIPEND & IRQ3) == FALSE) ;
/*-----------------------------------------------------------------*/
/* Read one byte and then end the device access. */
/*-----------------------------------------------------------------*/
NandPort;
raiseCE();
/*-----------------------------------------------------------------*/
/* Set flag since NAND pointer is set to the extra bytes. */
/*-----------------------------------------------------------------*/
ExtraBytes = TRUE;
}
/*-------------------------------------------------------------------*/
/* Clear any pre-existing interrupt and begin write access. */
/*-------------------------------------------------------------------*/
MPC860_SIPEND = IRQ3;
lowerCE();
/*-------------------------------------------------------------------*/
/* Send Serial Data Input command. */
/*-------------------------------------------------------------------*/
raiseCLE();
NandPort = 0x80; /* serial data input command */
lowerCLE();
/*-------------------------------------------------------------------*/
/* Send address as three separate bytes. */
/*-------------------------------------------------------------------*/
raiseALE();
NandPort = 10; /* start just past ECC bytes */
NandPort = (ui8)(addr >> 9);
NandPort = (ui8)(addr >> 17);
lowerALE();
/*-------------------------------------------------------------------*/
/* Write the four type bytes. */
/*-------------------------------------------------------------------*/
NandPort = (ui8)(type >> 24);
NandPort = (ui8)(type >> 16);
NandPort = (ui8)(type >> 8);
NandPort = (ui8)type;
/*-------------------------------------------------------------------*/
/* Send Auto Program command. */
/*-------------------------------------------------------------------*/
raiseCLE();
NandPort = 0x10; /* auto program command */
lowerCLE();
/*-------------------------------------------------------------------*/
/* Wait until device is ready. */
/*-------------------------------------------------------------------*/
while ((MPC860_SIPEND & IRQ3) == FALSE) ;
/*-------------------------------------------------------------------*/
/* Send Status Read command. */
/*-------------------------------------------------------------------*/
raiseCLE();
NandPort = 0x70; /* status read command */
lowerCLE();
/*-------------------------------------------------------------------*/
/* Read device status and end write access. */
/*-------------------------------------------------------------------*/
status = NandPort;
raiseCE();
/*-------------------------------------------------------------------*/
/* Return -1 if chip reports program error. Else return success. */
/*-------------------------------------------------------------------*/
if (status != 0xC0)
return -1;
else
return 0;
}
/***********************************************************************/
/* read_type: Read page's write_page() type value */
/* */
/* Inputs: addr = the page address */
/* vol = driver's volume pointer */
/* */
/* Returns: The four byte type value written during write_page() */
/* and possibly updated by write_type(). */
/* */
/***********************************************************************/
static ui32 read_type(ui32 addr, void *vol)
{
ui32 type;
/*-------------------------------------------------------------------*/
/* Clear any pre-existing interrupt and begin access. */
/*-------------------------------------------------------------------*/
MPC860_SIPEND = IRQ3;
lowerCE();
/*-------------------------------------------------------------------*/
/* Send read extra bytes command and set flag. */
/*-------------------------------------------------------------------*/
raiseCLE();
NandPort = 0x50; /* read extra bytes command */
ExtraBytes = TRUE;
lowerCLE();
/*-------------------------------------------------------------------*/
/* Send address as three separate bytes. */
/*-------------------------------------------------------------------*/
raiseALE();
NandPort = 10; /* start just past ECC bytes */
NandPort = (ui8)(addr >> 9);
NandPort = (ui8)(addr >> 17);
lowerALE();
/*-------------------------------------------------------------------*/
/* Wait until device is ready. */
/*-------------------------------------------------------------------*/
while ((MPC860_SIPEND & IRQ3) == FALSE) ;
/*-------------------------------------------------------------------*/
/* Read the four type bytes. */
/*-------------------------------------------------------------------*/
type = NandPort;
type = (type << 8) | NandPort;
type = (type << 8) | NandPort;
type = (type << 8) | NandPort;
/*-------------------------------------------------------------------*/
/* End the device access and return the coded type value. */
/*-------------------------------------------------------------------*/
raiseCE();
return type;
}
/***********************************************************************/
/* read_page: Read and ECC correct one NAND flash page */
/* */
/* Inputs: buffer = pointer to buffer to copy data to */
/* addr = the page address */
/* wear = wear count of this page's block */
/* vol = driver's volume pointer */
/* */
/* Returns: 0 for success, -1 for uncorrectable error */
/* */
/***********************************************************************/
static int read_page(void *buffer, ui32 addr, ui32 wear, void *vol)
{
int n;
ui8 *dst = buffer;
ui8 ecc[10];
/*-------------------------------------------------------------------*/
/* Clear any pre-existing interrupt and begin access. */
/*-------------------------------------------------------------------*/
MPC860_SIPEND = IRQ3;
lowerCE();
/*-------------------------------------------------------------------*/
/* Send command to start reading at first half of NAND data page. */
/*-------------------------------------------------------------------*/
raiseCLE();
NandPort = 0x00; /* read command */
ExtraBytes = FALSE;
lowerCLE();
/*-------------------------------------------------------------------*/
/* Send address as three separate bytes. */
/*-------------------------------------------------------------------*/
raiseALE();
NandPort = 0;
NandPort = (ui8)(addr >> 9);
NandPort = (ui8)(addr >> 17);
lowerALE();
/*-------------------------------------------------------------------*/
/* Wait until device is ready. */
/*-------------------------------------------------------------------*/
while ((MPC860_SIPEND & IRQ3) == FALSE) ;
/*-------------------------------------------------------------------*/
/* Read the data portion. */
/*-------------------------------------------------------------------*/
for (n = 0; n < PAGE_SIZE; ++n)
*dst++ = NandPort;
/*-------------------------------------------------------------------*/
/* Read the 10-byte ECC portion. */
/*-------------------------------------------------------------------*/
for (n = 0; n < 10; ++n)
ecc[n] = NandPort;
/*-------------------------------------------------------------------*/
/* End the device access. */
/*-------------------------------------------------------------------*/
raiseCE();
/*-------------------------------------------------------------------*/
/* Perform ECC decoding, return error if uncorrectable error. */
/*-------------------------------------------------------------------*/
if (DecodeEcc(buffer, ecc))
return -1;
else
return 0;
}
/***********************************************************************/
/* erase_block: Erase entire flash block */
/* */
/* Inputs: addr = base address of block to be erased */
/* vol = driver's volume pointer */
/* */
/* Returns: 0 on success, -1 on failure */
/* */
/***********************************************************************/
static int erase_block(ui32 addr, void *vol)
{
ui8 status;
/*-------------------------------------------------------------------*/
/* Clear any pre-existing interrupt and begin access. */
/*-------------------------------------------------------------------*/
MPC860_SIPEND = IRQ3;
lowerCE();
/*-------------------------------------------------------------------*/
/* Send Auto Block Erase Setup command. */
/*-------------------------------------------------------------------*/
raiseCLE();
NandPort = 0x60; /* auto block erase setup command */
lowerCLE();
/*-------------------------------------------------------------------*/
/* Send address as two separate bytes. */
/*-------------------------------------------------------------------*/
raiseALE();
NandPort = (ui8)(addr >> 9);
NandPort = (ui8)(addr >> 17);
lowerALE();
/*-------------------------------------------------------------------*/
/* Send Erase Start command. */
/*-------------------------------------------------------------------*/
raiseCLE();
NandPort = 0xD0; /* erase start command */
lowerCLE();
/*-------------------------------------------------------------------*/
/* Wait until device is ready. */
/*-------------------------------------------------------------------*/
while ((MPC860_SIPEND & IRQ3) == FALSE) ;
/*-------------------------------------------------------------------*/
/* Send Status Read command. */
/*-------------------------------------------------------------------*/
raiseCLE();
NandPort = 0x70; /* status read command */
lowerCLE();
/*-------------------------------------------------------------------*/
/* Read device status. */
/*-------------------------------------------------------------------*/
status = NandPort;
/*-------------------------------------------------------------------*/
/* End device access and return success. */
/*-------------------------------------------------------------------*/
raiseCE();
return status == 0xC0 ? 0 : -1;
}
/***********************************************************************/
/* Global Function Definitions */
/***********************************************************************/
/***********************************************************************/
/* NandDriverModule: Flash driver's module list entry */
/* */
/* Inputs: req = module request code */
/* ... = additional parameters specific to request */
/* */
/***********************************************************************/
void *NandDriverModule(int req, ...)
{
FfsVol vol;
if (req == kInitMod)
{
/*-----------------------------------------------------------------*/
/* Reset the NAND device. */
/*-----------------------------------------------------------------*/
lowerCE();
raiseCLE();
NandPort = 0xFF; /* reset command */
lowerCLE();
raiseCE();
/*-----------------------------------------------------------------*/
/* Wait until the device is ready. */
/*-----------------------------------------------------------------*/
MPC860_SIEL &= ~ED3; /* -> level mode */
SysWait50ms();
while ((MPC860_SIPEND & IRQ3) == FALSE) ;
MPC860_SIEL |= ED3; /* -> edge mode */
/*-----------------------------------------------------------------*/
/* Remove write protection, allowing the device to be programmed. */
/*-----------------------------------------------------------------*/
raiseWP();
/*-----------------------------------------------------------------*/
/* Register flash NAND volume with TargetFFS. */
/*-----------------------------------------------------------------*/
vol.name = "nand";
vol.page_size = PAGE_SIZE;
vol.block_size = BLOCK_SIZE;
vol.num_blocks = NUM_BLOCKS;
vol.max_bad_blocks = 10; /* from data sheet */
vol.mem_base = 0;
vol.vol = NULL;
vol.flag = FFS_QUOTA_ENABLED;
vol.driver.nand.write_page = write_page;
vol.driver.nand.write_type = write_type;
vol.driver.nand.read_page = read_page;
vol.driver.nand.read_type = read_type;
vol.driver.nand.page_erased = page_erased;
vol.driver.nand.erase_block = erase_block;
if (FsNandAddVol(&vol))
perror("FsNandAddVol() failed");
}
return NULL;
}
#endif /* INC_NAND_FS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -