📄 nandflash.c
字号:
byte_loc -= 8; // 减去两个RS占的长度(4B*2)
if (byte_loc < 518) // is data error(is not ECC itself error)
{
if (byte_loc < 512)
{
printf("excute bch %d: 0x%x --> 0x%x\r\n",
cnt, buf[byte_loc], buf[byte_loc] ^ (1 << bit_loc));
buf[byte_loc] = buf[byte_loc] ^ (1 << bit_loc); // correct
}
else
{
// 暂忽略文件系统信息
//printf("Is file system error, ignore it\r\n");
printf("excute bch %d: 0x%x --> 0x%x\r\n",
cnt, fileSysBuf[byte_loc - 512], fileSysBuf[byte_loc - 512] ^ (1 << bit_loc));
fileSysBuf[byte_loc - 512] = fileSysBuf[byte_loc - 512] ^ (1 << bit_loc); // correct
}
}
else
{
printf("Is BCH %d ECC itself error, ignore it\r\n", cnt);
printf("byte_loc = %d\r\n", byte_loc);
}
} // end if (ecc_loc == 0xFF)
} // end for (cnt=0; cnt<2; cnt++)
} // end if (status & BCH_CANT_CORRECT_BIT)
} // end if ((status & BCH_NO_ERR_BIT) != BCH_NO_ERR_BIT)
else
{
// printf("BCH no error\r\n");
}
return ret;
}
//********************tools funciton********************************//
static T_U16 getShiftNum(T_U32 tot)
{
T_U16 i=0;
while (tot>1)
{
i++;
tot=(tot>>1);
}
return i;
}
/**
* @BRIEF check cmd_done bit
* @AUTHOR lgj
* @DATE 2005-10-18
* @PARAM T_VOID
* @RETURN
* @RETVAL
*/
static T_BOOL check_cmd_done(T_VOID)
{
volatile T_U32 status;
HAL_READ_UINT32(FLASH_CTRL_REG22, status);
//printf("status = 0x%x\r\n", status);
if (status & 0x80000000)
return AK_TRUE;
else
return AK_FALSE;
}
/**
* @BRIEF read data from FIFO to memory(cpu mode)
* @AUTHOR lgj
modify dengjian
* @DATE 2005-10-18
* @PARAM *dest: destination pointer.
* fifo_start: fifo start address.
* count: word count(32BIT);
* @RETURN
* @RETVAL
* @NOTE 大小端(字节顺序)
*/
static T_VOID CPU_FIFO2memory(T_U32 *dest, T_U32 fifo_start, T_U8 count)
{
T_U32 tmp;
T_U32 next_reg_addr;
volatile T_U32 status;
//T_U32 dest_value = (T_U32)dest;
//switch(dest_value%4)
switch(((T_U32)dest)%4)
{
case 0://basic condition
for (next_reg_addr=fifo_start; next_reg_addr<count; next_reg_addr++)
{
// CPU mode read: set dump address, CPU request
HAL_WRITE_UINT32(FLASH_DMA_REG0, (1 << 29) | ((next_reg_addr & 0x7F) << 21));
// delay?
do {
HAL_READ_UINT32(FLASH_DMA_REG0, status);
} while (status & (1 << 29));
HAL_READ_UINT32(FLASH_DMA_REG5, tmp);
*dest++ = tmp;
//HAL_READ_UINT32(FLASH_DMA_REG5, *dest++);
//printf("read tmp = 0x%x\r\n", tmp);
}
break;
default:
{
//T_U32 temp_value;
T_U8 *temp_p8;
temp_p8 = (T_U8 *)dest;
// printf("\nnand read not T_U32 dest,dest =0x%x",dest);
for (next_reg_addr=fifo_start; next_reg_addr<count; next_reg_addr++)
{
// CPU mode read: set dump address, CPU request
HAL_WRITE_UINT32(FLASH_DMA_REG0, (1 << 29) | ((next_reg_addr & 0x7F) << 21));
// delay?
do {
HAL_READ_UINT32(FLASH_DMA_REG0, status);
} while (status & (1 << 29));
/*
//this read is wrong,FLASH_DMA_REG5 is not fifo, it is a 32-bit register
HAL_READ_UINT8(FLASH_DMA_REG5, *temp_p8++);
HAL_READ_UINT8(FLASH_DMA_REG5, *temp_p8++);
HAL_READ_UINT8(FLASH_DMA_REG5, *temp_p8++);
HAL_READ_UINT8(FLASH_DMA_REG5, *temp_p8++);
*/
/*
HAL_READ_UINT32(FLASH_DMA_REG5, temp_value);
*temp_p8++ = temp_value & 0xFF;
*temp_p8++ = (temp_value>>8) & 0xFF;
*temp_p8++ = (temp_value>>16) & 0xFF;
*temp_p8++ = (temp_value>>24) & 0xFF;
*/
//maybe this is the fastest code,cpu control register to memory
*temp_p8++ = (*(volatile T_U32*)FLASH_DMA_REG5) & 0xFF;
*temp_p8++ = ((*(volatile T_U32*)FLASH_DMA_REG5)>>8) & 0xFF;
*temp_p8++ = ((*(volatile T_U32*)FLASH_DMA_REG5)>>16) & 0xFF;
*temp_p8++ = ((*(volatile T_U32*)FLASH_DMA_REG5)>>24) & 0xFF;
HAL_READ_UINT32(FLASH_DMA_REG5, tmp);
}
break;
}
}
}
//******************************************read chipstatus control(not sure) *******************************//
/**
* @BRIEF read one physical page from nandflash directly.
* @AUTHOR Junhua Zhao
* @DATE 2006-3-30
* @PARAM PhyPage:physical page no.
* *data:pointer of data buffer
* @RETURN
* @RETVAL
*/
//***********************************************************************************
//tip:chip select by mtd manager, this driver just read current chip page data
//***********************************************************************************
static T_S16 nf_read_page(T_U8 chip,T_U32 page, T_U32 offset, T_U8 *data, T_S32 len,T_BOOL bECC)
{
T_U32 status;
T_U16 j;
T_U32 columnAddr, rowAddr;
if(data == 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;
}
//calculate column address and row address
rowAddr = page;
columnAddr = offset;
#ifdef CHK_STA_BEFORE
if (NF_SUCCESS != nf_check_status(chip))
return NF_ERR_LAST;
#endif
//read data and do ecc check
if( data != AK_NULL )
{
#ifdef STORE_ALL_INT
store_all_int();//need or not?
#endif
if(bECC)
{
//enable ECC encode
HAL_WRITE_UINT32(FLASH_ECC_REG4, ECC_DECODE_CONFIG);
}
else
{
//disable ECC encode
HAL_WRITE_UINT32(FLASH_ECC_REG4, ECC_DECODE_DISCFG | ((len-1) << 17));
}
//***************************push nandflash command,if need,make next code be a function*************************//
{
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 & 0xff) << 11) | ADDRESS_CYCLES_CONF);
HAL_WRITE_UINT32(reg_addr++, (((columnAddr & 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 one times***********//
HAL_WRITE_UINT32(reg_addr, ((len-1) << 11) | READ_DATA_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
//printf("before check cmd ");
while(!check_cmd_done());
// 从FIFO中读出数据(data部分), 存到memory中
//DMA_FIFO2memory((T_U32*) data, 0, (T_U8) (NFC_FIFO_SIZE/sizeof(T_U32)));
//CPU_FIFO2memory((T_U32*) data, 0, (T_U8) (NFC_FIFO_SIZE/sizeof(T_U32)));
switch(((T_U32)data) & 0x01)
{
case 0:
/* if (bECC)
DMA_FIFO2memory((T_U32*)data,0,NFC_FIFO_SIZE/4);
else
DMA_FIFO2memory((T_U32*)data,0,len/4);
break;
*/
case 1:
if (bECC)
CPU_FIFO2memory((T_U32*)data,0,NFC_FIFO_SIZE/4);
else
CPU_FIFO2memory((T_U32*)data,0,len/4);
break;
default:
printf("\r\nimpoisble read \r\n");
break;
}
#ifdef STORE_ALL_INT
restore_all_int(); //need or not??
#endif// need or not??
}
return NF_SUCCESS;
}
//******************************check ecc*****************************************//
/*
* @BRIEF ECC check and correct error for a page.
* @AUTHOR Junhua Zhao
MODIFY Dengjian
* @DATE 2006-01-07
* @PARAM UINT8 *pData: the main area data(must be 512 byte)
* UINT8 *pSpare: the spare area data (file system information,must be 6 byte)
* @RETURN if no error or correct error successfully return AK_TRUE,otherwise return AK_FALSE
* @NOTE
*/
T_BOOL ECC_Check(T_U8 *data, T_U8 *fs, T_U16 CRC_FS)
{
T_S32 ret;
ret = do_ECC_coerr(data, fs);
if (ret < ECC_NEED_CRC_CHECK)
{
return AK_TRUE;
}
else if (ret >= ECC_CANT_CORRECT)
{
printf("Too much error, ECC can't correct\r\n");
return AK_FALSE;
}
else
{
T_U16 CRC;
// check CRC
printf("More than 2 error, need check CRC\r\n");
// get CRC
CRC = (T_U16)MakeCRC(CRC_TYPE_CRC16, data, NFC_FIFO_SIZE);
// printf("org CRT = 0x%x, calculate CRC = 0x%x\r\n", tmp, CRC);
if (CRC != CRC_FS)
{
printf("CRC check error, ECC fail\r\n");
return AK_FALSE;
}
}
}
//******************************check ecc done*****************************************
//******************************************init,read chipID and set information(not sure)*******************************//
/**
* @BRIEF 配置并口为NAND FLASH, 配置AC参数
* @AUTHOR lgj
* @DATE 2005-10-13
* @PARAM T_VOID
* @RETURN
* @RETVAL
*/
T_VOID pp_nandf_init(T_VOID)
{
T_U32 tmp;
// 配置并口为NAND FLASH, 在FPGA上如何验证?
HAL_READ_UINT32(0x20090020, tmp);
tmp |= (1 << 16);
HAL_WRITE_UINT32(0x20090020, tmp);
// close host interface pull up control
HAL_READ_UINT32(0x20090060, tmp);
tmp |= (1 << 24);
HAL_WRITE_UINT32(0x20090060, tmp);
HAL_READ_UINT32(0x20090064, tmp);
tmp |= 0x1FFFF;
HAL_WRITE_UINT32(0x20090064, tmp);
/*
HAL_READ_UINT32(ANALOG_CONTROL1, tmp);
tmp |= (1 << 16);
HAL_WRITE_UINT32(ANALOG_CONTROL1, tmp);
// close host interface pull up control
HAL_READ_UINT32(PULL_UP_REG1, tmp);
tmp |= (1 << 24);
HAL_WRITE_UINT32(PULL_UP_REG1, tmp);
HAL_READ_UINT32(PULL_UP_REG2, tmp);
tmp |= 0x1FFFF;
HAL_WRITE_UINT32(PULL_UP_REG2, tmp);
*/
// HAL_WRITE_UINT32(FLASH_CTRL_REG23, 0xC3671);
// HAL_WRITE_UINT32(FLASH_CTRL_REG24, 0xF3637);
// bypass ECC, length is 528Byte
HAL_WRITE_UINT16(FLASH_ECC_REG0 + 0x02, (1 << 12) | 0x210);
}
/**
* @BRIEF init current nandchip
* @AUTHOR dengjian
* @DATE 2006-01-05
* @PARAM
* @RETURN chip id
* @RETVAL
*/
T_S16 nf_init()
{
T_U32 i;
T_S16 ret;
// if (bNandInit)
// return NF_SUCCESS;
pp_nandf_init();
ret = read_chipinfo();
if (ret != NF_SUCCESS)
{
printf("error read chipInfo\r\n");
return ret;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -