📄 nand.c
字号:
rNFCMD = NAND_CMD_ERASE2;
//for(i=0;i<40;i++);
//NF_DETECT_RB();
//rNFCMD = NAND_CMD_STATUS;
stat = WaitNFBusy();
NFChipDs();
return OK;
#if 0
if (NF_RDDATA() & 0x1) {
NF_nFCE_H();
printf("[ERASE_ERROR:block#=%d]\n",block);
//NF_MarkBadBlock(block);
return FAIL;
}
else {
NF_nFCE_H();
return OK;
}
#endif
}
#endif
static int NF_IsBadBlock(U32 block)
{
int i;
unsigned int blockPage;
U8 data;
blockPage = block * cpages_in_block ;
//NF_RSTECC();
NF_nFCE_L();
NF_CLEAR_RB();
if (cpage2Kis) {
rNFCMD = NAND_CMD_READ0;
rNFADDR = cpage_size & 0xff;
rNFADDR = (cpage_size >> 8) & 0x0f; // The mark of bad block is in 0 page
rNFADDR = blockPage & 0xff; // For block number A[24:17]
rNFADDR = (blockPage >> 8) & 0xff; // For block number A[25]
rNFCMD = NAND_CMD_READSTART;
}
else {
rNFCMD = NAND_CMD_READOOB;
rNFADDR = 517 & 0xf;
rNFADDR = blockPage & 0xff; // The mark of bad block is in 0 page
rNFADDR = (blockPage >> 8) & 0xff; // For block number A[24:17]
rNFADDR = (blockPage >> 16) & 0xff; // For block number A[25]
}
for(i=0;i<10;i++); /* dummy check me */
NF_DETECT_RB();
data=NF_RDDATA();
NF_nFCE_H();
//printf("NF_IsBadBlock:data =%x\n",data);
if(data != 0xff)
{
printf("[block %d has been marked as a bad block(%x)]\n",block,data);
return 1;
}
else
{
return 0;
}
}
/*
* Read data from NAND.
*/
int
s3c244x_nand_read(U32 targetBlock,U32 targetSize, U32 srcAddress)
{
int i;
//int programError=0;
U8 *srcPt,*saveSrcPt;
U32 blockIndex;
#if 0
printf("NAND Flash reading\n");
printf("Source base address =0x%x\n",srcAddress);
printf("Target start block num =%x\n",targetBlock);
printf("Target size =0x%x\n",targetSize);
printf("block read :\n");
#endif
srcPt=(U8 *)srcAddress;
blockIndex=targetBlock;
while(1) {
saveSrcPt=srcPt;
#if BAD_CHECK
if(NF_IsBadBlock(blockIndex)) { // 1:bad 0:good
blockIndex++; // for next block
continue;
}
#endif
for(i=0; i< cpages_in_block ;i++) {
if(!NF_ReadPage(blockIndex,i,srcPt)) {
printf("ECC Error(block=%d,page=%d!!!\n",(int)blockIndex,i);
}
srcPt += cpage_size;
//printf(".");
}
//printf("srcPt = %x",srcPt);
//printf( "%X ", blockIndex );
//if (!( blockIndex % 16 )) printf(".");
//printf( "%X ", blockIndex );
if((U32)srcPt>=(srcAddress+targetSize))
break; // Exit while loop
blockIndex++;
}
//printf("\n\n");
return 0;
}
static int s3c244x_nand_write(U32 targetBlock,U32 targetSize, U32 srcAddress )
{
int i,j;
int programError=0;
U8 *srcPt,*saveSrcPt;
U8 *dstPt=(U8*)0x33000000;
U32 blockIndex;
printf("NAND Flash writing\n");
printf("Source base address =0x%x\n",srcAddress);
printf("Target start block num =%d\n",targetBlock);
printf("Target size =0x%x\n",targetSize);
printf("block writed :\n");
srcPt=(U8 *)srcAddress;
blockIndex=targetBlock;
while(1) {
saveSrcPt=srcPt;
#if BAD_CHECK
if(NF_IsBadBlock(blockIndex)) { // 1:bad 0:good
blockIndex++; // for next block
continue;
}
#endif
if(!NF_EraseBlock(blockIndex)) {
blockIndex++; // for next block
printf(" Error-> Erase Block %d \n",(int)blockIndex);
continue;
}
for(i=0; i< cpages_in_block ;i++) {
if(!NF_WritePage(blockIndex,i,srcPt)) {
// block num, page num, buffer
programError=1;
break;
}
#if ECC_CHECK
if(!NF_ReadPage(blockIndex,i,srcPt)) {
printf("ECC Error(block=%d,page=%d!!!\n",(int)blockIndex,i);
}
for(j=0;j<2048;j++)
{
//if(i==0)
//printf("srcpt=%x,dstpt=%x\n",srcPt[j],dstPt[j]);
if(srcPt[j]!=dstPt[j])
printf("Error:%x\n",srcPt[j]);
}
#endif
srcPt += cpage_size;
//printf(".");
if((U32)srcPt>=(srcAddress+targetSize)) // Check end of buffer
break; // Exit for loop
}
if(programError==1) {
blockIndex++;
srcPt=saveSrcPt;
programError=0;
continue;
}
printf( "%X ", blockIndex );
if (!( blockIndex % 16 )) printf("\n");
if((U32)srcPt>=(srcAddress+targetSize))
break; // Exit while loop
blockIndex++;
}
printf("\n\n");
return 0;
}
/************************************************************/
/************************************************************/
struct Partition{
U32 offset;
U32 size;
char *name;
};
/*********************************************************************
type page_size obb_size pages_in_block block_size block_num
K9F1208 512 16 32 16K 4096
K9F1G08 2048 64 64 128K 1024
***********************************************************************/
/**************************************************************
partition:
boot: 0 0x00030000 256k
kernel: 0x00030000 0x001d0000
rootfs 0x00200000 0x01e00000 30M
extfs 0x02000000 0x02000000 32M
*************************************************************/
/************************************************************/
static struct Partition K9f1208_Part[] = {
{0, 0x00030000, "boot"}, //196K
{0x00030000, 0x001d0000, "kernel"},
{0x00200000, 0x01e00000, "rootfs"}, //30M
{0x02000000, 0x02000000, "ext-fs1"}, //32M
{0, 0 , 0}
};
static struct Partition K9f1g08_Part[] = {
{0, 0x00040000, "boot"}, //256K
{0x00040000, 0x00200000, "kernel"}, // 2m-256k
{0x00200000, 0x01e00000, "rootfs"}, //30M
{0x02000000, 0x02000000, "ext-fs1"}, //32M
{0, 0 , 0}
};
static struct Partition *NAND_PART;
static void Test_Write(void)
{
U32 block=0, page=0;
U32 i, status=FAIL, error, offset;
unsigned char *srcPt, *dstPt;
srcPt=(unsigned char *)0x31100000;
dstPt=(unsigned char *)0x31200000;
Uart_Printf("(K9F1G08) NAND Flash R/W test.\n");
Uart_Printf("Block number: ");
block = Uart_GetIntNum();
Uart_Printf("Page nember: ");
page = Uart_GetIntNum();
Uart_Printf("offset data(-1:random): ");
offset = Uart_GetIntNum();
// Init R/W data.
for(i=0; i<2048; i++) *dstPt++=0x0;
for(i=0; i<2048; i++) {
if(offset==-1) *srcPt++ = i%0xff;
else *srcPt++ = i+offset;
}
srcPt=(unsigned char *)0x31100000;
dstPt=(unsigned char *)0x31200000;
// Block erase
Uart_Printf("%d block erase.\n", block);
if(NF_EraseBlock(block)==FAIL) return;
Uart_Printf("Write data[%d block, %d page].\n", block, page);
if(NF_WritePage(block, page, srcPt)==FAIL) return;
Uart_Printf("Read data.\n");
if(NF_ReadPage(block, page, dstPt)==FAIL) return;
Uart_Printf("Checking data.\n");
for(error=0, i=0; i<2048; i++) {
if(*srcPt++!=*dstPt++) {
Uart_Printf("Error:%d[W:%x,R:%x]\n", i, *srcPt, *dstPt);
error++;
}
}
if(error!=0)
Uart_Printf("Fail to R/W test(%d).\n", error);
else
Uart_Printf("R/W test OK.\n");
#if 0
U8 *dstPt;
U8 *srcPt;
U32 i;
for(i=0;i<2048;i++)
{
*srcPt++ = (i&0xff);
}
srcPt=(unsigned char *)0x31100000;
dstPt=(unsigned char *)0x31300000;
NF_WritePage(0,0,srcPt);
NF_ReadPage(0,0,dstPt);
for(i=0;i<2048;i++)
{
if(*srcPt++!=*dstPt++)
{
printf("Error:%d[W:%x,R:%x]\n", i, *srcPt, *dstPt);
}
}
printf("R/W test Ok!\n");
#endif
}
/*
static void TestFunc(void)
{
U32 i;
U8 buf[512];
if(EraseBlock(0x180))
return;
for(i=0; i<512; i++)
buf[i] = i;
WritePage(0x180, buf);
for(i=0; i<512; i++)
buf[i] = 0;
ReadPage(0x180, buf);
for(i=0; i<512; i++)
printf("%4x", buf[i]);
}
*/
static U32 StartBlock, BlockCnt;
extern U32 downloadAddress;
extern U32 downloadFileSize;
static int NandSelPart(char *info)
{
U16 i, max_sel;
struct Partition *ptr = NAND_PART;
printf("Please select which region to %s : Esc to abort\n", info);
for(i=0; ptr->size!=0; i++, ptr++)
printf("%d : offset 0x%-8x, size 0x%-8x [%s]\n", i, ptr->offset, ptr->size, ptr->name);
max_sel = i;
while(1) {
i = getch();
if(i==0x1b)
return -1;
if((i>='0')&&(i<(max_sel+'0'))) {
i -= '0';
StartBlock = NAND_PART[i].offset>>block_offset;
BlockCnt = NAND_PART[i].size>>block_offset;
printf("StartBlock=%x,BlockCnt=%d",StartBlock,BlockCnt);
return i;
}
}
}
static void WrFileToNF(void)
{
int nf_part ,size,block;
U32 ram_addr;
nf_part = NandSelPart("write");
if(nf_part<0)
return;
if(downloadFileSize>NAND_PART[nf_part].size) {
puts("Download file size is more large than selected partition size!!!\n");
return;
}
printf("Now write nand flash page 0x%x from ram address 0x%x, filesize = %d\n", StartBlock, downloadAddress, downloadFileSize);
puts("Are you sure? [y/n]\n");
while(1) {
char c = getch();
if((c=='y')||(c=='Y'))
break;
if((c=='n')||(c=='N'))
return;
}
block = StartBlock;
ram_addr = downloadAddress;
size = downloadFileSize;
s3c244x_nand_write(block, size,ram_addr);
puts("Program nand flash partition success\n");
}
#define LINUX_PAGE_SHIFT 12
#define LINUX_PAGE_SIZE (1<<LINUX_PAGE_SHIFT)
#define COMMAND_LINE_SIZE 1024
struct param_struct {
union {
struct {
unsigned long page_size; /* 0 */
unsigned long nr_pages; /* 4 */
unsigned long ramdisk_size; /* 8 */
unsigned long flags; /* 12 */
#define FLAG_READONLY 1
#define FLAG_RDLOAD 4
#define FLAG_RDPROMPT 8
unsigned long rootdev; /* 16 */
unsigned long video_num_cols; /* 20 */
unsigned long video_num_rows; /* 24 */
unsigned long video_x; /* 28 */
unsigned long video_y; /* 32 */
unsigned long memc_control_reg; /* 36 */
unsigned char sounddefault; /* 40 */
unsigned char adfsdrives; /* 41 */
unsigned char bytes_per_char_h; /* 42 */
unsigned char bytes_per_char_v; /* 43 */
unsigned long pages_in_bank[4]; /* 44 */
unsigned long pages_in_vram; /* 60 */
unsigned long initrd_start; /* 64 */
unsigned long initrd_size; /* 68 */
unsigned long rd_start; /* 72 */
unsigned long system_rev; /* 76 */
unsigned long system_serial_low; /* 80 */
unsigned long system_serial_high; /* 84 */
unsigned long mem_fclk_21285; /* 88 */
} s;
char unused[256];
} u1;
union {
char paths[8][128];
struct {
unsigned long magic;
char n[1024 - sizeof(unsigned long)];
} s;
} u2;
char commandline[COMMAND_LINE_SIZE];
};
extern void call_linux(U32 a0, U32 a1, U32 a2);
/*************************************************************/
static __inline void cpu_arm920_cache_clean_invalidate_all(void)
{
__asm{
mov r1, #0
mov r1, #7 << 5 /* 8 segments */
cache_clean_loop1:
orr r3, r1, #63UL << 26 /* 64 entries */
cache_clean_loop2:
mcr p15, 0, r3, c7, c14, 2 /* clean & invalidate D index */
subs r3, r3, #1 << 26
bcs cache_clean_loop2 /* entries 64 to 0 */
subs r1, r1, #1 << 5
bcs cache_clean_loop1 /* segments 7 to 0 */
mcr p15, 0, r1, c7, c5, 0 /* invalidate I cache */
mcr p15, 0, r1, c7, c10, 4 /* drain WB */
}
}
void cache_clean_invalidate(void)
{
cpu_arm920_cache_clean_invalidate_all();
}
static __inline void cpu_arm920_tlb_invalidate_all(void)
{
__asm{
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 /* drain WB */
mcr p15, 0, r0, c8, c7, 0 /* invalidate I & D TLBs */
}
}
void tlb_invalidate(void)
{
cpu_arm920_tlb_invalidate_all();
}
void disable_irq(void);
void call_linux(U32 a0, U32 a1, U32 a2)
{
void (*goto_start)(U32, U32);
rINTMSK=BIT_ALLMSK;
cache_clean_invalidate();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -