flash.c
来自「FreeScale imx21开发板Nand flash烧写程序」· C语言 代码 · 共 1,195 行 · 第 1/3 页
C
1,195 行
{
u32 ByteDone = 0;
/* FlashAddress is byte offset in nand */
u32 BlockNum = FlashAddress/(NAND_NUM_OF_PAGES*NAND_MAIN_BYTESIZE);
u32 PageNum = 0;
u32 ReadSize;
u32 tmp;
while(ByteSize > ByteDone)
{
/* if end of a block*/
if( PageNum >= NAND_NUM_OF_PAGES ) {
BlockNum++; /*go to next block*/
PageNum=0;
}
if( PageNum == 0 ) { /* if Start of Block */
if(!nand_block_is_good(BlockNum)) /* if Block is not Good */
{
BlockNum++;
continue;
}
}
ReadSize = ((ByteSize-ByteDone)>NAND_MAIN_BYTESIZE) ? NAND_MAIN_BYTESIZE : (ByteSize-ByteDone);
tmp = nand_read_page(BlockNum, PageNum, TargetAddress+ByteDone, ReadSize);
if( tmp != NAND_ERROR_NO ) { /* if error */
//flash_report_error(REPORT_ERROR_STOP, 0);
return tmp;
}
ByteDone+=ReadSize;
PageNum++;
}
return 0; // complete for no error
}
U8 nand_write_page(U32 BlockNum, U32 PageNum, U32 SourceAddress, U32 ByteSize/*,u8 file_format*/)
{
U8 i;
// if (FILE_FORMAT_NB0 == file_format)
// {
/* fill internal RAM buffer */
// for(i=0; i<64; i+=2)
// {
// if((i == 4)||(i == 20) ||(i == 36)||(i == 52))
// *(volatile u16 *)(NFC_SAB0_BASE+i) = 0xFF00;
// else
// *(volatile u16 *)(NFC_SAB0_BASE+i) = 0xFFFF;
// }
// }
// else
// {
/* fill internal RAM buffer */
for(i=0; i<64; i+=2)
*(volatile u16 *)(NFC_SAB0_BASE+i) = 0xFFFF;
// }
nfc_memcpy(SourceAddress, NFC_MAB0_BASE, ByteSize);
*(volatile u16 *)NFC_RAM_BUF_ADDR = 0;
nfc_command_input(NAND_CMD_PAGE_PROG);
nfc_address_cycle(0, 2);
nfc_address_cycle(BlockNum*NAND_NUM_OF_PAGES+PageNum, NAND_NUM_OF_ROW_ADDR_CYCLES);
nfc_flash_data_input();
*(volatile u16 *)NFC_RAM_BUF_ADDR = 1;
nfc_flash_data_input();
*(volatile u16 *)NFC_RAM_BUF_ADDR = 2;
nfc_flash_data_input();
*(volatile u16 *)NFC_RAM_BUF_ADDR = 3;
nfc_flash_data_input();
nfc_command_input(NAND_CMD_PAGE_PROG_CONFIRM);
nand_wait();
if( nand_read_status() & NAND_STATUS_PROG_ERROR )
{
return NAND_ERROR_PROG;
}
return NAND_ERROR_NO;
}
//CheckFlashComplete(0x67676767);
U32 FlashWrite(U32 sAddress,
U32 pData,
U32 nData)
{
U32 tmp;
U32 ByteDone = 0;
U32 BlockNum = sAddress/(NAND_NUM_OF_PAGES*NAND_MAIN_BYTESIZE);
U32 PageNum = 0;
U32 WriteSize;
while(nData>ByteDone)
{
if( PageNum >= NAND_NUM_OF_PAGES )
{ /* if end of a block */
BlockNum++; /* go to next block */
PageNum=0;
//flash_report_program_byte_done(ByteDone);
}
if( PageNum == 0 )
{ /* if Start of Block */
nand_wait();
if(!nand_block_is_good(BlockNum))
{ /* if Block is not Good */
//dbg("Write meet bad block:%d",BlockNum);
BlockNum++;
continue;
}
nand_wait();
if( nand_erase_block(BlockNum) != NAND_ERROR_NO )
{
/* block erase error */
//flash_report_error(REPORT_ERROR_ERASE, BlockNum);
nand_mark_bad_block(BlockNum);
BlockNum++; /* Skip this block */
continue;
}
}//end of if( PageNum == 0 ) by fcding
nand_wait();
WriteSize = ((nData-ByteDone)>NAND_MAIN_BYTESIZE) ? NAND_MAIN_BYTESIZE : (nData-ByteDone);
tmp = nand_write_page(BlockNum, PageNum, pData+ByteDone, WriteSize/*,file_format*/);
if( tmp == NAND_ERROR_ECC ) /* if ECC error */
{
nand_wait();
nand_mark_bad_block(BlockNum);
BlockNum++; /* Skip this block */
PageNum = 0;
continue;
}
if( tmp == NAND_ERROR_PROG ) /* if PROG error */
{
//flash_report_error(REPORT_ERROR_PROGEAM,
// BlockNum*NAND_MAIN_BYTESIZE*NAND_NUM_OF_PAGES+PageNum*NAND_MAIN_BYTESIZE);
//flash_report_program_complete();
return NAND_ERROR_PROG;
}
/*Preparation for Next Page*/
ByteDone+=WriteSize;
PageNum++;
}//end of while by fcding
//flash_report_program_byte_done(ByteDone);
return 0;
}
void Nand_bad_test(void)
{
U32 BlockNum = 0;
for (BlockNum = 150; BlockNum < 200; BlockNum++)
{
if(!nand_block_is_good(BlockNum))
{
while(1);
printf("Bad Block#\n");
}
}
}
void Nand_test(void)
{
U32 fWalk, mWalk;
U32 result;
U32 blockIndex, i;
fWalk = 0xC2000000;
mWalk = 0xC3000000;
result = 0xC1900000;
for (blockIndex = 0; blockIndex < 1024; blockIndex++)
{
FlashWrite(blockIndex*NAND_NUM_OF_PAGES*2048, 0xC2000000, 2048*64);
nand_read (blockIndex*NAND_NUM_OF_PAGES*2048, 0xC3000000, 2048*64);
for (i = 0; i < (2048*64/4); i++)
{
if (*(volatile U32 *)(fWalk + i) != *(volatile U32 *)(mWalk + i))
{
break;
}
}
if (i != (2048*64/4))
{
*(volatile U32 *)(result+4) = 77;
break;
}
*(volatile U32 *)(result) = 99;
}
}
void nand_unconditional_erase_all(void)
{
U32 i;
for(i=0; i<NAND_NUM_OF_BLOCKS; i++) {
nand_wait();
if(nand_erase_block(i)) {
//flash_report_error(REPORT_ERROR_ERASE, i*NAND_MAIN_BYTESIZE*NAND_NUM_OF_PAGES);
//dbg("Erasing Block# %d\n", i+1);
}
}
}
U32 FlashSectorErase(U32 sAddress,
U32 nAddress)
{
U32 i;
U32 j=0;
U8 ret = 0;
i=sAddress/(NAND_NUM_OF_PAGES*NAND_MAIN_BYTESIZE);
for(; i<=(nAddress/(NAND_NUM_OF_PAGES*NAND_MAIN_BYTESIZE)); i++){
nand_wait();
if(nand_block_is_good(i)) {
nand_wait();
if(nand_erase_block(i)){
ret = NAND_ERROR_ERASE;
//flash_report_error(REPORT_ERROR_ERASE, i*NAND_MAIN_BYTESIZE*NAND_NUM_OF_PAGES);
}
else {
j++;
//flash_report_erase_byte_done(j*NAND_NUM_OF_PAGES*NAND_MAIN_BYTESIZE);
}
}
else{
}
}
//flash_report_erase_complete();
return ret;
}
//end change by fcding
// ***************************************************************************
//
// Function: FlashSectorErase
//
// This function erases all flash memory sectors overlapping
// the address range specified in the parameters.
//
//
// Parameters: U32 sAddress start address for erase
// U32 nAddress end address for erase
//
// Return Value: U32 number of bytes erased (rounded up to
// next sector limit), or zero on error
//
// ***************************************************************************
/*
U32 FlashSectorErase(U32 sAddress,
U32 nAddress)
{
volatile U32* pBase;
volatile U32* pWalk;
BOOL bFailTotal;
BOOL bDone;
BOOL bFail;
U32 nWalk;
U32 nSize;
U32 nPoll;
U32 nDone;
U32 nSec;
U32 SA;
U32 i = 0;
U32 Flash_Erase = 0x17171717;
// Check the Flash Starting Address
pBase = (volatile U32*)(sAddress & 0xFE000000);
// Reset flash devices before starting erase sequences
// ***************************************************
*(pBase + 0x000) = 0x00f000f0;
nSec = (U32)pBase;
nDone = 0;
nWalk = sAddress;
#ifdef DEBUG
printf("Sector Erase at [0x%08X - 0x%08X]...\n",sAddress, nAddress);
#endif
for (SA = 1; SA <= 270; SA++)
{
if ((SA >= 1 && SA <= 8) || (SA >= 263 && SA <= 270))
{
nSize = 0x1000*4;
}
else
{
nSize = 0x8000*4;
}
if ((nSec <= nWalk) && (nSec + nSize > nWalk) && (nSec <= nAddress))
{
// This sector overlaps the address range. Erase it
// ************************************************
pWalk = (volatile U32*) nWalk;
// Execute "normal" sector erase algorithm
// ***************************************
*(pBase + 0x555) = 0x00aa00aa;
*(pBase + 0x2aa) = 0x00550055;
*(pBase + 0x555) = 0x00800080;
*(pBase + 0x555) = 0x00aa00aa;
*(pBase + 0x2aa) = 0x00550055;
*(pWalk) = 0x00300030;
// Data polling algorithm for erase operation
// ******************************************
bDone = FALSE;
bFail = FALSE;
while ((!bDone) && (!bFail))
{
nPoll = *(pWalk);
if (((~nPoll) & FLASH_DQ7_2X16) == 0)
{
bDone = TRUE;
}
else if ((nPoll & FLASH_DQ5_2X16) == FLASH_DQ5_2X16)
{
nPoll = *(pWalk);
if (((~nPoll) & FLASH_DQ7_2X16) == 0)
{
bDone = TRUE;
}
else
{
bFail = TRUE;
bFailTotal = TRUE;
}
}
if ( (i &= 0xFFFF) ==0)
{
#ifdef DEBUG
printf(".");
#endif
CheckFlashComplete(Flash_Erase);
}
i++;
}
nDone += nSize;
nWalk += nSize;
}
nSec += nSize;
}
// Reset flash devices
// *******************
*(pBase + 0x000) = 0x00f000f0;
return bFailTotal ? 0 : nDone;
}
*/
// ***************************************************************************
//
// Function: FlashRead
//
//
//
// Parameters: U32 sAddress start address for read
// void* pData data to read
// U32 nData number of bytes to read
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?