📄 mx_nand512.c
字号:
#include <nand/mx_nand512_define.h>
#include <nand/flashreport.h>
#include "MX31_HABTools.h"
/*******************************************************************************/
// MX21 Register - Memory MAP
/*
#define SYS_FMCR (0x10027800+0x14)
#define CRM_PCCR0 (0x10027000+0x20)
#define NFC_BASE_ADDR (0xDF003000)
*/
//MX31
#define CCM_RCSR (0x53F80000+0x0C)
#define CCM_PDR0 (0x53F80000+0x04)
#define NFC_BASE_ADDR (0xB8000000)
//MX27
#define NFC_MAB0_BASE (NFC_BASE_ADDR+0x000) // main area buffer0
#define NFC_MAB1_BASE (NFC_BASE_ADDR+0x200) // main area buffer1
#define NFC_MAB2_BASE (NFC_BASE_ADDR+0x400) // main area buffer2
#define NFC_MAB3_BASE (NFC_BASE_ADDR+0x600) // main area buffer3
#define NFC_SAB0_BASE (NFC_BASE_ADDR+0x800) // spare area buffer0
#define NFC_SAB1_BASE (NFC_BASE_ADDR+0x810) // spare area buffer1
#define NFC_SAB2_BASE (NFC_BASE_ADDR+0x820) // spare area buffer2
#define NFC_SAB3_BASE (NFC_BASE_ADDR+0x830) // spare area buffer3
#define NFC_REG_BASE (NFC_BASE_ADDR+0xE00) // nfc register area
#define NFC_BUFSIZE (NFC_REG_BASE+0x00)
#define NFC_BLK_ADD_LOCK (NFC_REG_BASE+0x02)
#define NFC_RAM_BUF_ADDR (NFC_REG_BASE+0x04)
#define NFC_NAND_FLASH_ADDR (NFC_REG_BASE+0x06)
#define NFC_NAND_FLASH_CMD (NFC_REG_BASE+0x08)
#define NFC_CONFIGURATION (NFC_REG_BASE+0x0A)
#define NFC_ECC_STAT_RES (NFC_REG_BASE+0x0C)
#define NFC_ECC_RSLT_MA (NFC_REG_BASE+0x0E)
#define NFC_ECC_RSLT_SA (NFC_REG_BASE+0x10)
#define NFC_NF_WR_PROT (NFC_REG_BASE+0x12)
#define NFC_ULOCK_START_BLK (NFC_REG_BASE+0x14)
#define NFC_ULOCK_END_BLK (NFC_REG_BASE+0x16)
#define NFC_NF_WR_PROT_STAT (NFC_REG_BASE+0x18)
#define NFC_NF_CONFIG1 (NFC_REG_BASE+0x1A)
#define NFC_NF_CONFIG2 (NFC_REG_BASE+0x1C)
/*******************************************************************************/
#define NAND512_CMD_READ (0x00)
#define NAND512_CMD_READ1 (0x01)
#define NAND512_CMD_READ2 (0x50)
#define NAND512_CMD_READ_CONFIRM (0x30)
#define NAND512_CMD_PAGE_PROG (0x80)
#define NAND512_CMD_PAGE_PROG_CONFIRM (0x10)
#define NAND512_CMD_ERASE (0x60)
#define NAND512_CMD_ERASE_CONFIRM (0xD0)
#define NAND512_CMD_READID (0x90)
#define NAND512_CMD_RESET (0xFFFF)
#define NAND512_CMD_READ_STATUS (0x70)
#define NAND_STATUS_READY (0x40)
#define NAND_STATUS_NOT_PROTECT (0x80)
#define NAND_STATUS_PROG_ERROR (0x01)
/* MX21
#define NF_FMS_2KB (0x20)
#define NF_16BIT (0x10)
*/
#define NF_FMS_2KB (0x40000000)
#define NF_16BIT (0x80000000)
#define NFC_BUSY (!( *(volatile u16 *)NFC_NF_CONFIG2 & 0x8000 ))
nand_t nand_type[] = {
// manuf device io badblock row num num
// id id width marker addr of of
// offset cycle block page
{ 0xEC, 0x76, 8, 5, 3, 4096, 32 }, // K9F1208U0M
{ 0xEC, 0x36, 8, 5, 3, 4096, 32 }, // K9K1208Q0C
{ 0xEC, 0x75, 8, 5, 2, 2048, 32 }, // K9F5608U0D
{ 0xEC, 0x79, 8, 5, 3, 8192, 32 }, // K9K1G08U0B
{ 0xEC, 0x78, 8, 5, 3, 8192, 32 }, // K9K1G08R0B
{ 0xEC, 0x45, 16, 11, 2, 2048, 32 }, // K9F5616Q0C
{ 0x98, 0x79, 8, 5, 3, 8192, 32 } // TC58DVG02A1FT00
};
nand_t *gNAND;
extern U32 _gchannel;
void nfc_memcpy(u32 SourceAddress, u32 TargetAddress, u32 ByteSize)
{
u32 i;
for(i=0; i<ByteSize; i+=4)
*(volatile u32 *)(TargetAddress+i) = *(volatile u32 *)(SourceAddress+i);
}
u8 nfc_wait(void)
{
while(NFC_BUSY); /* Wait for Basic Operation Complete */
return 0;
}
void nfc_address_input(u16 address)
{
*(volatile u16 *)NFC_NAND_FLASH_ADDR = address;
*(volatile u16 *)NFC_NF_CONFIG2 = 0x0002;
nfc_wait();
}
void nfc_address_cycle(u32 Address, u8 NumOfCycle)
{
u8 i;
for(i=0; i<NumOfCycle; i++)
nfc_address_input( (u16)( (Address>>(i*8))&0xFF ) );
}
void nfc_command_input(u16 command)
{
*(volatile u16 *)NFC_NAND_FLASH_CMD = command;
*(volatile u16 *)NFC_NF_CONFIG2 = 0x0001;
nfc_wait();
}
void nfc_flash_data_input(void)
{
*(volatile u16 *)NFC_NF_CONFIG2 = 0x0004;
nfc_wait();
}
void nfc_flash_data_output(void)
{
*(volatile u16 *)NFC_NF_CONFIG2 = 0x0008;
nfc_wait();
}
u8 nfc_ecc_uncorrectable_error(void)
{
return ( *(volatile u32 *)NFC_ECC_STAT_RES & 0xA ) ? 1 : 0;
}
void NAND_ReadID(u8 *man_id, u8 *dev_id)
{
u32 tmp;
nfc_command_input(0x90);
nfc_address_input(0);
*(volatile u16 *)NFC_NF_CONFIG2 = 0x0010; // FDO = ID Read
nfc_wait();
tmp = *(volatile u32 *)(NFC_MAB3_BASE);
*man_id = (u8)tmp;
*dev_id = (u8)(tmp>>8);
}
void NAND_Init(void)
{
u8 man_id;
u8 dev_id;
u16 i;
/* MX21
*(volatile u32 *)SYS_FMCR &= ~NF_16BIT; // Set to 8-bit NAND
*(volatile u32 *)SYS_FMCR &= ~NF_FMS_2KB; // Set to 512B Page Size
*(volatile u32 *)CRM_PCCR0 |= 0x00080000; // enable NFC Clock
*/
//MX31
*(volatile u32 *)CCM_RCSR &= ~NF_16BIT; // Set to 8-bit NAND
*(volatile u32 *)CCM_RCSR &= ~NF_FMS_2KB; // Set to 512B Page Size
*(volatile u32 *)CCM_PDR0 |= 5 << 8; // set NFC_PODF = 5 (133MHz/6 = 22.2MHz)
//MX27
*(volatile u16 *)NFC_RAM_BUF_ADDR = 3; // select Buffer 3
*(volatile u16 *)NFC_ULOCK_START_BLK = 0x0000;
*(volatile u16 *)NFC_ULOCK_END_BLK = 0xFFFF;
*(volatile u16 *)NFC_NF_WR_PROT = 0x0004;
*(volatile u16 *)NFC_CONFIGURATION = 0x0002; // unlock the internal RAM buffer
*(volatile u16 *)NFC_NF_CONFIG2 = 0x8000; // clear all operation
*(volatile u16 *)NFC_NF_CONFIG1 = 0x0008; // enable ECC and disable spare only
NAND_ReadID(&man_id, &dev_id);
gNAND = nand_type;
i = sizeof(nand_type) / sizeof(nand_t);
while(i--)
if( nand_type[i].man_id == man_id && nand_type[i].dev_id == dev_id )
{
gNAND = nand_type + i;
break;
}
if( gNAND->io_width == 16 )
//MX21 *(volatile u32 *)SYS_FMCR |= NF_16BIT; // Set to 16-bit NAND
//MX31
*(volatile u32 *)CCM_RCSR |= NF_16BIT; // Set to 16-bit NAND
}
u8 NAND_ReadStatus(void)
{
nfc_command_input(NAND512_CMD_READ_STATUS);
*(volatile u16 *)NFC_NF_CONFIG2 = 0x0020; // FDO -> Read Status
nfc_wait();
return (u8)((*(volatile u32 *)(NFC_MAB3_BASE)) & 0xFF) ;
}
u8 NAND_BlockIsGood(u32 BlockNum)
{
u16 tmp;
u32 ttt;
nfc_command_input(NAND512_CMD_READ);
nfc_address_input(0); // one column cycle for 512B-Page Size NAND
nfc_address_cycle(BlockNum*NAND_NUM_OF_PAGES, NAND_NUM_OF_ROW_ADDR_CYCLES);
nfc_flash_data_output();
ttt = (NFC_SAB3_BASE+(NAND_BADBLOCK_MARKER_OFFSET/2));
tmp = *(volatile u16 *)(NFC_SAB3_BASE+((NAND_BADBLOCK_MARKER_OFFSET/2)*2)) ;
if(NAND_BADBLOCK_MARKER_OFFSET%2)
return ((tmp&0xFF00)==0xFF00) ;
else
return ((tmp&0x00FF)==0x00FF) ;
}
u8 NAND_MarkBadBlock(u32 BlockNum)
{
u8 i;
for(i=0; i<16; i+=2)
*(volatile u16 *)(NFC_SAB3_BASE+i) = 0;
nfc_command_input(NAND512_CMD_PAGE_PROG);
nfc_address_input(0); // one column cycle for 512B-Page Size NAND
nfc_address_cycle(BlockNum*NAND_NUM_OF_PAGES, NAND_NUM_OF_ROW_ADDR_CYCLES);
nfc_flash_data_input();
nfc_command_input(NAND512_CMD_PAGE_PROG_CONFIRM);
return 0;
}
u8 NAND_EraseBlock(u32 BlockNum)
{
nfc_command_input(NAND512_CMD_ERASE);
nfc_address_cycle(BlockNum*NAND_NUM_OF_PAGES, NAND_NUM_OF_ROW_ADDR_CYCLES);
nfc_command_input(NAND512_CMD_ERASE_CONFIRM);
if( NAND_ReadStatus() & NAND_STATUS_PROG_ERROR )
{
return NAND_ERROR_ERASE;
}
else
return NAND_ERROR_NO;
}
u8 NAND_ReadPage(u32 BlockNum, u32 PageNum, u32 TargetAddress, u32 ByteSize)
{
nfc_command_input(NAND512_CMD_READ);
nfc_address_input(0); // one column cycle for 512B-Page Size NAND
nfc_address_cycle(BlockNum*NAND_NUM_OF_PAGES+PageNum, NAND_NUM_OF_ROW_ADDR_CYCLES);
nfc_flash_data_output();
if(nfc_ecc_uncorrectable_error())
return NAND_ERROR_ECC;
nfc_memcpy(NFC_MAB3_BASE, TargetAddress, ByteSize);
return NAND_ERROR_NO; // No Error
}
u8 NAND_StatusReady(void)
{
return ( NAND_STATUS_READY & NAND_ReadStatus() ) ? 1 : 0;
}
void NAND_Wait(void)
{
while(!NAND_StatusReady());
}
u8 NAND_WritePage(u32 BlockNum, u32 PageNum, u32 SourceAddress, u32 ByteSize)
{
u8 i;
for(i=0; i<16; i+=2)
*(volatile u16 *)(NFC_SAB3_BASE+i) = 0xFFFF;
nfc_memcpy(SourceAddress, NFC_MAB3_BASE, ByteSize);
nfc_command_input(NAND512_CMD_PAGE_PROG);
nfc_address_input(0); // one column cycle for 512B-Page Size NAND
nfc_address_cycle(BlockNum*NAND_NUM_OF_PAGES+PageNum, NAND_NUM_OF_ROW_ADDR_CYCLES);
nfc_flash_data_input();
nfc_command_input(NAND512_CMD_PAGE_PROG_CONFIRM);
if( NAND_ReadStatus() & NAND_STATUS_PROG_ERROR )
{
return NAND_ERROR_PROG; // Program Error
}
NAND_Wait();
nfc_command_input(NAND512_CMD_READ);
nfc_address_input(0); // one column cycle for 512B-Page Size NAND
nfc_address_cycle(BlockNum*NAND_NUM_OF_PAGES+PageNum, NAND_NUM_OF_ROW_ADDR_CYCLES);
nfc_flash_data_output();
if(nfc_ecc_uncorrectable_error())
return NAND_ERROR_ECC;
return NAND_ERROR_NO; // No Error
}
u8 NAND_ComparePage(u32 BlockNum, u32 PageNum, u32 TargetAddress, u32 ByteSize)
{
u32 i;
u32 error = 0;
nfc_command_input(NAND512_CMD_READ);
nfc_address_input(0); // one column cycle for 512B-Page Size NAND
nfc_address_cycle(BlockNum*NAND_NUM_OF_PAGES+PageNum, NAND_NUM_OF_ROW_ADDR_CYCLES);
nfc_flash_data_output();
if(nfc_ecc_uncorrectable_error())
return NAND_ERROR_ECC;
for(i=0; i<ByteSize; i+=2)
if( (*(volatile u16 *)(NFC_MAB3_BASE+i)) != (*(volatile u16 *)(TargetAddress+i)) ) {
FlashReport_Error(REPORT_ERROR_VERIFY, TargetAddress+i);
error++;
}
if(error)
return NAND_ERROR_VERIFY;
return NAND_ERROR_NO; // No Error
}
u8 NAND_Read(u32 FlashAddress, u32 TargetAddress, u32 ByteSize)
{
u32 ByteDone = 0;
u32 BlockNum = FlashAddress/(NAND_NUM_OF_PAGES*NAND_MAIN_BYTESIZE); // FlashAddress must equal to start of block
u32 PageNum = 0;
u32 ReadSize;
u32 tmp;
while(ByteSize > ByteDone)
{
if( PageNum >= NAND_NUM_OF_PAGES ) { // if end of a block
BlockNum++; // go to next block
PageNum=0;
}
if( PageNum == 0 ) // if Start of Block
if(!NAND_BlockIsGood(BlockNum)) // if Block is not Good
{
BlockNum++;
continue;
}
ReadSize = ((ByteSize-ByteDone)>NAND_MAIN_BYTESIZE) ? NAND_MAIN_BYTESIZE : (ByteSize-ByteDone);
tmp = NAND_ReadPage(BlockNum, PageNum, TargetAddress+ByteDone, ReadSize);
if( tmp != NAND_ERROR_NO ) { // if error
FlashReport_Error(REPORT_ERROR_STOP, 0);
return tmp;
}
ByteDone+=ReadSize;
PageNum++;
}
return 0; // complete for no error
}
u8 NAND_Write(u32 FlashAddress, u32 SourceAddress, u32 ByteSize)
{
u32 tmp;
u32 ByteDone = 0;
u32 BlockNum = FlashAddress/(NAND_NUM_OF_PAGES*NAND_MAIN_BYTESIZE); // FlashAddress must equal to start of block
u32 PageNum = 0;
u32 WriteSize;
while(ByteSize>ByteDone)
{
if( PageNum >= NAND_NUM_OF_PAGES ) { // if end of a block
BlockNum++; // go to next block
PageNum=0;
FlashReport_ProgramByteDone(ByteDone);
}
if( PageNum == 0 ) { // if Start of Block
NAND_Wait();
if(!NAND_BlockIsGood(BlockNum)) { // if Block is not Good
BlockNum++;
continue;
}
NAND_Wait();
if( NAND_EraseBlock(BlockNum) != NAND_ERROR_NO ) // if Block Erase Error
{
#ifdef HABTOOLKIT_FLASH_LIB
HAB_flash_status(FLASH_ERASE, ByteDone, _gchannel);
#endif
NAND_MarkBadBlock(BlockNum);
BlockNum++; // Skip this block
continue;
}
}
NAND_Wait();
WriteSize = ((ByteSize-ByteDone)>NAND_MAIN_BYTESIZE) ? NAND_MAIN_BYTESIZE : (ByteSize-ByteDone);
tmp = NAND_WritePage(BlockNum, PageNum, SourceAddress+ByteDone, WriteSize);
if( tmp == NAND_ERROR_ECC ) // if ECC error
{
NAND_Wait();
NAND_MarkBadBlock(BlockNum);
BlockNum++; // Skip this block
PageNum = 0;
ByteDone = ByteDone - (PageNum*NAND_MAIN_BYTESIZE) ;
continue;
}
if( tmp == NAND_ERROR_PROG ) // if PROG error
{
FlashReport_Error(REPORT_ERROR_PROGEAM,
BlockNum*NAND_MAIN_BYTESIZE*NAND_NUM_OF_PAGES+PageNum*NAND_MAIN_BYTESIZE);
FlashReport_ProgramComplete();
return tmp;
}
// Preparation for Next Page
ByteDone+=WriteSize;
PageNum++;
}
FlashReport_ProgramByteDone(ByteDone);
FlashReport_ProgramComplete();
return 0; // complete for no error
}
u8 NAND_Compare(u32 FlashAddress, u32 TargetAddress, u32 ByteSize)
{
u32 ByteDone = 0;
u32 BlockNum = FlashAddress/(NAND_NUM_OF_PAGES*NAND_MAIN_BYTESIZE); // FlashAddress must equal to start of block
u32 PageNum = 0;
u32 ReadSize;
u32 tmp;
while(ByteSize > ByteDone)
{
if( PageNum >= NAND_NUM_OF_PAGES ) { // if end of a block
FlashReport_VerifyByteDone(ByteDone);
BlockNum++; // go to next block
PageNum=0;
}
if( PageNum == 0 ) // if Start of Block
if(!NAND_BlockIsGood(BlockNum)) // if Block is not Good
{
BlockNum++;
continue;
}
ReadSize = ((ByteSize-ByteDone)>NAND_MAIN_BYTESIZE) ? NAND_MAIN_BYTESIZE : (ByteSize-ByteDone);
tmp = NAND_ComparePage(BlockNum, PageNum, TargetAddress+ByteDone, ReadSize);
if( tmp != NAND_ERROR_NO ) { // if error
FlashReport_Error(REPORT_ERROR_STOP, 0);
return tmp;
}
ByteDone+=ReadSize;
PageNum++;
}
FlashReport_VerifyByteDone(ByteDone);
FlashReport_VerifyComplete();
return 0; // complete for no error
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -