📄 nandflash.c
字号:
Nand_SysInfo.Nand_LogPerPhy = chipInfo.phy_page_size/NFC_LOG_PAGE_SIZE;
Nand_SysInfo.log_spare_size = NFC_LOG_SPARE_SIZE;
Nand_SysInfo.Fs_Info_size = NFC_FS_INFO_SIZE;
Nand_SysInfo.log_page_size = NFC_LOG_PAGE_SIZE;
Nand_SysInfo.log_page_per_blk = Nand_SysInfo.Nand_LogPerPhy * chipInfo.phy_page_per_blk;
Nand_SysInfo.log_page_per_blk_shift = getShiftNum(Nand_SysInfo.log_page_per_blk);
Nand_SysInfo.phypage_per_chip = chipInfo.phy_page_per_blk * chipInfo.chip_blk_num;
Nand_SysInfo.phypage_shift_num = getShiftNum(Nand_SysInfo.phypage_per_chip);
Nand_SysInfo.chip_logpage_num = chipInfo.chip_blk_num*Nand_SysInfo.log_page_per_blk;
Nand_SysInfo.total_blk_num = chipInfo.chip_blk_num * chipInfo.count;
Nand_SysInfo.total_group_num = Nand_SysInfo.total_blk_num / chipInfo.group_blk_num;
Nand_SysInfo.total_phypage_num = Nand_SysInfo.total_blk_num * chipInfo.phy_page_per_blk;
Nand_SysInfo.total_logpage_num = Nand_SysInfo.log_page_per_blk * Nand_SysInfo.total_blk_num;
// bNandInit = AK_TRUE;
return NF_SUCCESS;
}
/**
* @BRIEF read one logic page to nandflash with ECC.
* total 518B valide data: incude 512Byte data and 6Byte file system information.
* hardware check ECC code.
* @AUTHOR dengjian
* @DATE 2006-1-4
* @PARAM LogPage:logic page number.
* *data:pointer of data buffer
*FS_info:pointer of fs information
* @RETURN
* @RETVAL
*/
//***********************************************************************************
//tip:chip select by mtd manager, this driver just read current chip page data
//***********************************************************************************
T_S16 nf_read_frame(T_U32 frame,T_U8 *data,T_U8 *fs_info)
{
T_U8 chip;
T_U32 status;
T_U16 j;
T_U32 columnAddr, rowAddr;
if( (data == AK_NULL) && (fs_info == AK_NULL))
{
printf("\r\nnand dirver read:all of fs_info and data is AK_NULL\r\n");
return NF_SUCCESS;//because mtd would handle error block,just alert,only write faile return falsereturn AK_FALSE;
}
if( frame >= Nand_SysInfo.total_logpage_num )
{
printf("\r\n nand read addr error, frame(%d)/total(%d)\r\n",frame,Nand_SysInfo.total_logpage_num);
//memset(data, 0xFF, Nand_frameSize);
return NF_SUCCESS;//because mtd would handle error block,just alert,only write faile return false
}
//calculate column address and row address
chip = (T_U8)(frame/Nand_SysInfo.chip_logpage_num);
rowAddr = (frame%Nand_SysInfo.chip_logpage_num) / Nand_SysInfo.Nand_LogPerPhy;
columnAddr = ( frame % Nand_SysInfo.Nand_LogPerPhy ) * (Nand_SysInfo.log_page_size + Nand_SysInfo.log_spare_size) ;
//read data and do ecc check
if( data != AK_NULL )
{
T_S16 ret;
ret = nf_read_page(chip,rowAddr,columnAddr,data,Nand_SysInfo.log_page_size + Nand_SysInfo.log_spare_size,AK_TRUE);
if(ret==NF_SUCCESS && fs_info != AK_NULL)
{
// 读出文件系统信息
HAL_READ_UINT32(FLASH_DMA_REG2, status); // low 4Byte
memcpy(fs_info,&status,4);
//HAL_READ_UINT16(FLASH_DMA_REG3, status); // high 2Byte
HAL_READ_UINT32(FLASH_DMA_REG3, status); // high 2Byte
memcpy(fs_info+4,&status,2);
return ECC_Check(data,(T_U8 *)fs_info,(T_U16)(status & 0xFFFF));
}
return ret;
}
//*****************************ONLY READ FS INFORMATION
else//only read fs information
{
#ifdef STORE_ALL_INT
store_all_int();//need or not?
#endif
//***************************push nandflash command,if need,make next code be a function*************************//
{
// execute FIFO to FLASH read sequence(because data is sequence, can only use NFLASH_READ1(0x00) command)
T_U32 *reg_addr = (T_U32 *) FLASH_CTRL_REG0;
// sta_clr = 0,
HAL_WRITE_UINT32(FLASH_CTRL_REG22, 0x00);
//nandflash read1 command
HAL_WRITE_UINT32(reg_addr++, (NFLASH_READ1 << 11) | COMMAND_CYCLES_CONF);
//nandflash byte offset in physic page
HAL_WRITE_UINT32(reg_addr++, (((columnAddr + NFC_FS_INFO_OFFSET) & 0xff) << 11) | ADDRESS_CYCLES_CONF);
HAL_WRITE_UINT32(reg_addr++, ((((columnAddr+ NFC_FS_INFO_OFFSET) & 0xff00)>>8) << 11) | ADDRESS_CYCLES_CONF);
//nandflash physic page address
HAL_WRITE_UINT32(reg_addr++, ((rowAddr & 0xff) << 11) | ADDRESS_CYCLES_CONF);
HAL_WRITE_UINT32(reg_addr++, (((rowAddr & 0xff00)>>8) << 11) | ADDRESS_CYCLES_CONF);
//*******if nand flash >= 256M, this address seek would send******//
if(3==chipInfo.row_cycle)
{
HAL_WRITE_UINT32(reg_addr++, (((rowAddr & 0xff0000)>>16) << 11) | ADDRESS_CYCLES_CONF);
}
//nandflash read2 command,this is a wait command
HAL_WRITE_UINT32(reg_addr++, (NFLASH_READ2 << 11) | COMMAND_CYCLES_CONF|(1 << 10));
HAL_WRITE_UINT32(reg_addr++, WAIT_JUMP_CONF);// wait R/B rising edge
//HAL_WRITE_UINT32(reg_addr++, (BASIC_DLYCNT << 11) | DELAY_CNT_CONF);
//******************read data to status register ***********//
HAL_WRITE_UINT32(reg_addr, ((NFC_FS_INFO_SIZE-1) << 11) | READ_INFO_CONF | LAST_CMD_FLAG);
//HAL_WRITE_UINT32(reg_addr, (7<<11) | READ_INFO_CONF | LAST_CMD_FLAG);
}
// excute operation, CE1, enable power saving, CE# keep LOW wait R/B
//HAL_WRITE_UINT32(FLASH_CTRL_REG22, NCHIP_SELECT(rowAddr%NFLASH_PAGE_SIZE)|DEFAULT_GO|SAVE_MODE_FLAG);
//HAL_WRITE_UINT32(FLASH_CTRL_REG22, NCHIP_SELECT(0)|DEFAULT_GO|SAVE_MODE_FLAG);
HAL_WRITE_UINT32(FLASH_CTRL_REG22, NCHIP_SELECT(chip)|DEFAULT_GO);
// wait reg22 fifo command send done
while(!check_cmd_done());
//从reg20中读出fs信息
HAL_READ_UINT32(FLASH_CTRL_REG20, status); // low 4Byte
memcpy(fs_info,&status,4);
HAL_READ_UINT32(FLASH_CTRL_REG21, status); // high 2Byte
memcpy(fs_info+4,&status,2);
#ifdef STORE_ALL_INT
restore_all_int(); //need or not??
#endif//need or not??
return NF_SUCCESS;
}
}
/**
* @BRIEF read a block data
* @AUTHOR qxj
* @DATE 2006-7-17
* @PARAM
BlockNO: block number
pData: point to buffer to store data,
the buffer size is Nand_SysInfo.log_page_size * Nand_SysInfo.log_page_per_blk
* @RETURN
* @RETVAL
return next valid block number, if return 0 indicate read this block fail
*/
static T_U16 nf_read_block(T_U32 BlockNO, T_U8 *pData)
{
T_U32 i = 0, j = 0;
T_U32 StartLogPageNO = 0;
T_U8 spare[NFC_FS_INFO_SIZE];
if(BlockNO >= Nand_SysInfo.total_blk_num || pData == AK_NULL)
return 0;
StartLogPageNO = BlockNO * Nand_SysInfo.log_page_per_blk;
//printf("StartLogPageNO %d\n", StartLogPageNO);
#ifdef BAD_BLOCK_TEST
if(if_write_read_bad_block(BlockNO))
return 0;
#endif
if( !nf_read_frame(StartLogPageNO , AK_NULL, spare) )
{
printf("read this block the first logpage 0x%x fail\n", StartLogPageNO);
return 0;
}
if(spare[AVAILABLE_FLAG_OFFSET] != AVAILABLE_FLAG)
{
printf("this block the first page 0x%x, error available flag 0x%x\n", StartLogPageNO, spare[AVAILABLE_FLAG_OFFSET]);
return 0;
}
if( (spare[BLOCK_INDEX_OFFSET] == 0xff)
&&(spare[BLOCK_INDEX_OFFSET + 1] == 0xff)
&&(spare[AVAILABLE_FLAG_OFFSET] == 0xff))//this block is a empty blk
{
printf("this is a empty block 0x%x, 0x%x 0x%x 0x%x\n",
StartLogPageNO + (i * Nand_SysInfo.Nand_LogPerPhy) + j, spare[BLOCK_INDEX_OFFSET],
spare[BLOCK_INDEX_OFFSET + 1], spare[AVAILABLE_FLAG_OFFSET]);
return 0;
}
for(i = 0; i < chipInfo.phy_page_per_blk; i++)
{
for(j = 0; j < Nand_SysInfo.Nand_LogPerPhy; j++)
{
//printf("read page %d\n", StartLogPageNO + (i * NFLASH_LOG_PER_PHY) + j);
if( nf_read_frame(StartLogPageNO + (i * Nand_SysInfo.Nand_LogPerPhy) + j,
(T_U8 *)(pData + ((i * Nand_SysInfo.Nand_LogPerPhy) + j) * Nand_SysInfo.log_page_size),
spare) != AK_TRUE)
{
printf("read logpage %x fail\n", StartLogPageNO + (i * Nand_SysInfo.Nand_LogPerPhy) + j);
return 0;
}
}
}
//printf("read block success\n");
return *(T_S16 *)(spare + BLOCK_INDEX_OFFSET);
}
/**
* @BRIEF read data from flash in chain
in this chain,each item is a block.each block's the last spare area store a index which indicate
next valid block.
CAUTION: must read all chain, because static value BlockIndex
* @AUTHOR qxj
* @DATE 2006-7-17
* @PARAM
StartAddress : start address,this value will be change to next read block address
EndAddress : the chain last block address
pData : read data
ReadLength : read data length
BackupMapAddress: backup chain store address
* @RETURN
* @RETVAL
return AK_TRUE : success AK_FAIL: unsucess
*/
T_BOOL nf_force_read(T_U32 *StartAddress, T_U32 EndAddress,
T_U8 *pData, T_U32 ReadLength,
T_U32 BackupMapAddress)
{
T_S32 readlen = (T_S32)ReadLength;
T_U32 Offset = 0;
T_U16 BackupBlockMap[NFC_LOG_PAGE_SIZE / 2];
T_U32 MapBlockPage = 0, preMapBlockPage = 0;
T_U32 StartBlockNumber;
T_U32 EndBlockNumber;
T_U32 CurrentBlockNumber;
T_U32 StartLogicPageNumber = 0;
T_U32 EndLogicPageNumber = 0;
T_U8 chip;
static T_U16 BlockIndex = 0;
if(StartAddress == AK_NULL || pData == AK_NULL)
return AK_FALSE;
if(*StartAddress < (Nand_SysInfo.log_page_size * Nand_SysInfo.log_page_per_blk))//the first block
{
StartLogicPageNumber = *StartAddress / Nand_SysInfo.log_page_size;
EndLogicPageNumber = EndAddress / Nand_SysInfo.log_page_size;
printf("read from 0 block\n");
printf("Start logic page 0x%x End logic page 0x%x data length 0x%x\n",
StartLogicPageNumber, EndLogicPageNumber, readlen);
while((StartLogicPageNumber < EndLogicPageNumber) && readlen > 0)
{
chip = (T_U8)(StartLogicPageNumber / Nand_SysInfo.chip_logpage_num);
if(nf_read_page(chip, StartLogicPageNumber / Nand_SysInfo.Nand_LogPerPhy,
(StartLogicPageNumber % Nand_SysInfo.Nand_LogPerPhy) * Nand_SysInfo.log_page_size,\
pData,Nand_SysInfo.log_page_size, AK_FALSE) == AK_FALSE)
{
printf("read failed!\n");
break;
}
//printf("successful!\n");
pData += Nand_SysInfo.log_page_size;
readlen -= Nand_SysInfo.log_page_size;
StartLogicPageNumber++;
*StartAddress += Nand_SysInfo.log_page_size;
}
if(readlen <= 0)
return AK_TRUE;
else
{
printf("not all data read\n");
return AK_FALSE;
}
}
StartBlockNumber = (*StartAddress) /
(Nand_SysInfo.log_page_size * Nand_SysInfo.log_page_per_blk);
EndBlockNumber = EndAddress /
(Nand_SysInfo.log_page_size * Nand_SysInfo.log_page_per_blk);
printf("StartBlockNumber 0x%x EndBlockNumber 0x%x readlen 0x%x\n",
StartBlockNumber, EndBlockNumber, readlen);
for(CurrentBlockNumber = StartBlockNumber;
CurrentBlockNumber <= EndBlockNumber && readlen > 0;)
{
//read ECC ok
printf("read block 0x%x\n", CurrentBlockNumber);
T_U32 tmp_block;
if((tmp_block = nf_read_block(CurrentBlockNumber, pData)) == 0)
{
printf("read block fail\n");
if(BackupMapAddress == 0)
{
printf("no backup data\n");
//return AK_FALSE;
CurrentBlockNumber++;
continue;
}
//read the backup page
MapBlockPage = BackupMapAddress / Nand_SysInfo.log_page_size;
MapBlockPage += (BlockIndex / (Nand_SysInfo.log_page_size / 2));
Offset = BlockIndex % (Nand_SysInfo.log_page_size / 2);
printf("backup map page 0x%x offset 0x%x\n", MapBlockPage, Offset);
if(MapBlockPage != preMapBlockPage)
{
preMapBlockPage = MapBlockPage;
chip = (T_U8)(MapBlockPage / Nand_SysInfo.chip_logpage_num);
if(nf_read_page(chip, MapBlockPage / Nand_SysInfo.Nand_LogPerPhy,
(MapBlockPage % Nand_SysInfo.Nand_LogPerPhy) * Nand_SysInfo.log_page_size,
(T_U8 *)BackupBlockMap, Nand_SysInfo.log_page_size, AK_FALSE) == AK_FALSE)
{
printf("read backup map false\n");
return AK_FALSE;
}
/*
T_U32 i;
for(i = 0; i < 512 / 2; i++)
{
if(i != 0 && i % 8 == 0)
printf("\n");
printf(" 0x%x ", BackupBlockMap[i]);
}
*/
}
printf("read backup block 0x%x\n", BackupBlockMap[Offset]);
if((tmp_block = nf_read_block((T_U32)(BackupBlockMap[Offset]),pData)) == 0)
{
printf("read backup data false\n");
return AK_FALSE;
}
}
CurrentBlockNumber = tmp_block;
printf("success, next block 0x%x\n", CurrentBlockNumber);
//Block is OK
//printf("BlockNO %d\n", BlockNO);
//to read the specified next Block
pData += (Nand_SysInfo.log_page_size * Nand_SysInfo.log_page_per_blk);
readlen -= (Nand_SysInfo.log_page_size * Nand_SysInfo.log_page_per_blk);
//the last block, all data be readed
if(CurrentBlockNumber == LAST_BLOCK_FLAG)
{
printf("last block flag\n");
readlen = 0;
BlockIndex = 0;
break;
}
printf("readlen 0x%x\n", readlen);
BlockIndex++;
}
*StartAddress = CurrentBlockNumber * (Nand_SysInfo.log_page_size * Nand_SysInfo.log_page_per_blk);
//force read ok
if (readlen <= 0)
return AK_TRUE;
else
return AK_FALSE;
}
#endif//OS_ANYKA
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -