📄 nandflash.c
字号:
if(*targetP++ != 0xffffffff)
return 0;
return 1;
}
int Verification(ulong *targetP, ulong limit, ulong *srcAddr)
{
ulong i;
// sourceP = (ushort *)srcAddr;
for(i=0; i<limit; i+=4, targetP++, srcAddr++)
if(*targetP != *srcAddr) {
return 0;
}
return 1;
}
int ReadChar(uchar *data, ulong targetAddr, ulong size)
{
ulong i, len, flen, status;
len = size;
for (i=0; i<size; i+=PAGE_SIZE) {
if(len > PAGE_SIZE)
flen = PAGE_SIZE;
else
flen = len;
*ale_reg = targetAddr & 0x01FFFE00;
*cle_reg = READ_DATA;
while(*status_reg & READ_DATA) {
*AutoKick_reg = 1;
*AutoKick_reg = 0;
}
status = *status_reg;
if( (status & FS_NAND_OP_ERR_MASK != 0) ||
(status & FS_NAND_ECC_SELF_ERR_MASK != 0) ||
(status & FS_NAND_READ_ECC_ERR_MASK != 0) )
return 0;
// for(j=0; j<flen; j++, data++)
// *data = *(data_reg+j);
memcpy((void *)data, (void *)data_reg, flen);
data += flen;
len -= PAGE_SIZE;
targetAddr += PAGE_SIZE;
AutoKick();
}
return 1;
}
int WriteChar(uchar *data, ulong page_addr)
{
ushort status;
memcpy((void *)data_reg, (void *)data, PAGE_SIZE);
*ale_reg = page_addr << 9;
*cle_reg = PROGRAM_CMD;
while(*status_reg & PROGRAM_CMD)
AutoKick();
status = *status_reg;
if( (status & FS_NAND_OP_ERR_MASK != 0) ||
(status & FS_NAND_OP_RESULT_MASK != 0) )
return 0;
return 1;
}
void ReadMem(void)
{
uchar *srcP;
srcP = (uchar *)Flash_Info.Buf;
ReadChar(srcP, Flash_Info.TargetAddr, Flash_Info.Length);
Flash_Info.Result = 1;
}
void InitFlash(void)
{
ulong status;
/* Reset NAND flash memory */
*cle_reg = RESET_CMD;
/* Software reset the controller. */
*cle_reg = RESET_CTRL;
/* Reset NAND flash memory */
*cle_reg = RESET_CMD;
/* Configure NAND flash */
*flash_cfg_reg = FS_NAND_CNFG_VAL;
/* Wait for completion. */
while(*status_reg & PROGRAM_CMD)
{
*AutoKick_reg = 1;
*AutoKick_reg = 0;
}
/* Do a id check. */
*cle_reg = ID_CMD;
/* Wait for completion. */
while(*status_reg & ID_CMD)
{
*AutoKick_reg = 1;
*AutoKick_reg = 0;
}
/* Do a status check */
*cle_reg = STATUS_CMD;
/* Wait for completion. */
while(*status_reg & STATUS_CMD)
{
*AutoKick_reg = 1;
*AutoKick_reg = 0;
}
crc = CRC_30_STEP_SEED;
image_size = 0;
LastAddr = 0;
status = *status_reg;
BIB_Block_No = 1;
while(!Bad_Block_Check(BIB_Block_No) && (BIB_Block_No < BLOCK_COUNT))
BIB_Block_No++;
Current_Block_No = BIB_Block_No;
Current_Page_No = Current_Block_No*PAGE_CNT;
}
void AutoKick(void)
{
*AutoKick_reg = 1;
*AutoKick_reg = 0;
}
ulong crc_30_step
(
ulong seed,
/* Either the result of a previous crc_30_step() or CRC_16_STEP_SEED
** the first time the routine is called. Note that the input is
** inverted prior to use, to counteract the inversion applied when
** it was returned as a result of the previous step.
*/
uchar *buf_ptr,
/* Pointer to bytes containing the data to CRC. The bit stream starts
** in the MS bit of the first uchar.
*/
ushort len
/* Number of data bits to calculate the CRC over */
)
{
ulong data, crc_30;
/* Generate a CRC-30 by looking up the transformation in a table and
** XOR-ing it into the CRC, one uchar at a time.
*/
for (crc_30 = ~seed & 0x3FFFFFFF; len >= 8; len -= 8, buf_ptr++) {
crc_30 = crc30_table[ ((crc_30 >> (30 - 8)) ^ *buf_ptr) & 0xff ]
^ (crc_30 << 8);
}
/* Finish calculating the CRC over the trailing data bits
**
** XOR the MS bit of data with the MS bit of the CRC.
** Shift the CRC and data left 1 bit.
** If the XOR result is 1, XOR the generating polynomial in with the CRC.
*/
if (len != 0) {
data = ((ulong) (*buf_ptr)) << (30-8); /* Align data MSB with CRC MSB */
while (len-- != 0) {
if ( ((crc_30 ^ data) & (1L << 29)) != 0 ) { /* Is MSB of XOR a 1 */
crc_30 <<= 1; /* Left shift CRC */
crc_30 ^= CRC_30_POLYNOMIAL; /* XOR polynomial into CRC */
} else {
crc_30 <<= 1; /* Left shift CRC */
}
data <<= 1; /* Left shift data */
}
}
crc_30 = ~crc_30; /* 1's complement the CRC */
return( crc_30 & 0x3FFFFFFF ); /* mask the result to 30 bits */
} /* end of crc_30_calc */
#ifdef SAMSUNG
// Samsung nand flash
int Bad_Block_Check(ulong block)
{
ulong page_address, status, spare_byte;
ulong page_no =0;
int block_size_shift;
ushort no_of_shifts = 1;
ushort no_pages_to_check;
block_size_shift = PAGE_CNT;
while( block_size_shift != 2 )
{
block_size_shift = block_size_shift >> 1;
no_of_shifts++;
}
/* Set the first page number */
page_no = block << no_of_shifts;
/* Check the first two pages of the samsung block */
for( no_pages_to_check=0; no_pages_to_check < 2 ; no_pages_to_check++ )
{
/* Read the 6th spare byte */
page_address = (page_no << 9) + 5;
*ale_reg = page_address;
*cle_reg = READ_FLAG;
while(*status_reg & READ_FLAG) ;
status = *status_reg;
if(status & FS_NAND_OP_ERR_MASK)
return 0;
spare_byte = *spare_data_reg;
*AutoKick_reg = 1;
*AutoKick_reg = 0;
if( (spare_byte & 0xFF ) != 0xFF )
{
return 0;
}
/* Check the second page in the block */
page_no++;
}
/* After the spare byte is read the nand device needs to be
reset before any other operation is performed */
/* Software reset the controller. */
*cle_reg = RESET_CTRL;
/* Reset NAND flash memory */
*cle_reg = RESET_CMD;
/* Configure NAND flash */
*flash_cfg_reg = FS_NAND_CNFG_VAL;
/* Wait for completion. */
while(*status_reg & PROGRAM_CMD)
;
/* Do a id check. */
*cle_reg = ID_CMD;
/* Wait for completion. */
while(*status_reg & ID_CMD)
;
return 1;
} /* End of samsung_nand_bad_block_check */
#endif
#ifdef TOSHIBA
int Bad_Block_Check(ulong block)
{
int i;
ulong page_address, status, page_no, first_page_no;
ulong sram_buffer=0x0;
int block_size_shift;
ushort no_of_shifts = 1;
int block_size=PAGE_CNT;
int page_size=PAGE_SIZE;
ulong ecc;
block_size_shift=PAGE_CNT;
while ( block_size_shift != 2 )
{
block_size_shift = block_size_shift >> 1;
no_of_shifts++;
}
/*Reset sram memory */
for (i = 0; i < page_size/4; i++)
*(data_reg + i) = 0;
/* Set the first page number */
first_page_no = block << no_of_shifts;
for ( page_no = first_page_no ; page_no < first_page_no+block_size ; page_no++ )
{
page_address = page_no << 9;
*ale_reg = page_address;
*cle_reg = READ_DATA;
status = *status_reg;
while ( status & READ_DATA != 0)
{
status = *status_reg;
}
status = *status_reg;
if ( (status & FS_NAND_OP_ERR_MASK != 0) ||
(status & FS_NAND_ECC_SELF_ERR_MASK != 0) ||
(status & FS_NAND_READ_ECC_ERR_MASK != 0) )
{
return 0;
}
/* TESTING ecc malfunction !!*/
ecc = *ecc_read_reg;
if ( ((ecc & FS_NAND_READ_ECC_ERR_MASK) != 0) || ((ecc & FS_NAND_ECC_UC_ERR_MASK) != 0 ))
{
/*printf("fs_nand_common_fnc: fs_nand_read_page - error bad ecc 0: 0x%08x", ecc);*/
status = *status_reg;
if ( (status & FS_NAND_OP_ERR_MASK != 0) ||
(status & FS_NAND_ECC_SELF_ERR_MASK != 0) ||
(status & FS_NAND_READ_ECC_ERR_MASK != 0) )
{
/* printf("ecc was bad and status was also bad\n");*/
}
}
/* Reading the sram buffer in chunks of 4 bytes */
for (i = 0; i < page_size/4; i++)
{
sram_buffer = *(data_reg + i);
if ( (sram_buffer & 0xFFFFFFFF ) != 0xFFFFFFFF )
return 0;
sram_buffer=0x0;
}
}
return 1;
} /* End of toshiba_nand_bad_block_check */
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -