⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nand.c

📁 s3c2440 bootloader适用于S3C2440开发板
💻 C
📖 第 1 页 / 共 3 页
字号:
 //   SEccUnlock();
/*	
 printf("ecc2:");
 for(i=0;i<8;i++)
	 printf("0x%x ",tmp[i]);
 printf("\n");
*/
	for(i=0;i<8;i++)
		WrNFDat(tmp[i]);
	
//	SEccLock();
	
}

	WrNFCmd(PROGCMD1);
	stat = WaitNFBusy();
	NFChipDs();
	
#ifdef	WR_BAD_BLK_TEST
	if((addr&0xff)==0x17) stat = 1;	//just for test bad block
#endif
		
	if(stat)
		printf("Write nand flash 0x%x fail\n", addr);
	else {	
		U8 RdDat[512];
		
		ReadPage(addr, RdDat);		
		for(i=0; i<512; i++)
			if(RdDat[i]!=buf[i]) {
				printf("Check data at page 0x%x, offset 0x%x fail\n", addr, i);
				stat = 1;
				break;
			}
	}
		
	return stat;	
}

static void MarkBadBlk(U32 addr)
{
	addr &= ~0x1f;
	
	NFChipEn();
	
	WrNFCmd(READCMD2);	//point to area c
	
	WrNFCmd(PROGCMD0);
	WrNFAddr(4);		//mark offset 4,5,6,7
	WrNFAddr(addr);
	WrNFAddr(addr>>8);
	if(NandAddr)
		WrNFAddr(addr>>16);
	WrNFDat(0);			//mark with 0
	WrNFDat(0);
	WrNFDat(0);			//mark with 0
	WrNFDat(0);
	WrNFCmd(PROGCMD1);
	WaitNFBusy();		//needn't check return status
	
	WrNFCmd(READCMD0);	//point to area a
		
	NFChipDs();
}

static int CheckBadBlk(U32 addr)
{
	U8 dat;
	
	addr &= ~0x1f;
	
	NFChipEn();
	
	WrNFCmd(READCMD2);	//point to area c
	WrNFAddr(5);		//mark offset 4,5,6,7
	WrNFAddr(addr);
	WrNFAddr(addr>>8);
	if(NandAddr)
		WrNFAddr(addr>>16);
	WaitNFBusy();
	dat = RdNFDat();
	
	WrNFCmd(READCMD0);	//point to area a
	
	NFChipDs();

	return (dat!=0xff);
}

/************************************************************/
// Nand Flash 的分区
struct Partition{
	U32 offset;
	U32 size;
	char *name;
};

// Nand Flash 的分区设置
static struct Partition NandPart[] = {
	{0, 		 0x00040000, "ATBOOT"},        // 256    K
	{0x00040000, 0x02300000, "WINCE  "},         // 35     M
	{0x02340000, 0x01cc0000, "USER"},          // 28.75  M 
	{0,			 0         , 0}
};


static U32 StartPage, BlockCnt;
extern U32 downloadAddress; 
extern U32 downloadFileSize;
extern int sel_part;
extern int auto_nk;

static int NandSelPart(char *info)
{
	U16 i, max_sel;
	struct Partition *ptr = NandPart;

	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';
			StartPage = NandPart[i].offset>>9;
			BlockCnt  = NandPart[i].size>>14;
			return i;
		}
	}
}

static void WrFileToNF(void)
{
S32 nf_part, i ,size, skip_blks;
U32 ram_addr;
	
	if(auto_nk==1)
		nf_part = sel_part;
	else
	 	nf_part = NandSelPart("write");
	
	if(nf_part<0)
		return;	
	
	if(downloadFileSize>NandPart[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", StartPage, downloadAddress, downloadFileSize);

	skip_blks = 0;
	ram_addr  = downloadAddress;
	size      = downloadFileSize;
	
	for(i=0; size>0; )	{	
		if(!(i&0x1f)) {
			if(EraseBlock(i+StartPage)) {
				NandPart[nf_part].size -= 32<<9;	//partition available size - 1 block size
				if(downloadFileSize>NandPart[nf_part].size) {
					puts("Program nand flash fail\n");
					return;
				}
				MarkBadBlk(i+StartPage);
				skip_blks++;				
				i += 32;				
				continue;
			}
		}
		if(WritePage(i+StartPage, (U8 *)ram_addr)) {
			ram_addr -= (i&0x1f)<<9;
			size += (i&0x1f)<<9;
			i &= ~0x1f;
			NandPart[nf_part].size -= 32<<9;	//partition available size - 1 block size
			if(downloadFileSize>NandPart[nf_part].size) {
				puts("Program nand flash fail\n");
				return;
			}			
			MarkBadBlk(i+StartPage);
			skip_blks++;			
			i += 32;			
			continue;
		}
		ram_addr += 512;
		size -= 512;
		i++;
	}
	puts("Program nand flash partition success\n");
	if(skip_blks)
		printf("Skiped %d bad block(s)\n", skip_blks);
	
}

#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_os(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();
}

// 启动应用程序
// 包括linux 和 WinCE
// 
void call_os(U32 a0, U32 a1, U32 a2)
{
	void (*goto_start)(U32, U32);
	
	rINTMSK=BIT_ALLMSK;
	
	cache_clean_invalidate();
	tlb_invalidate();	

	__asm{
		mov	ip, #0
		mcr	p15, 0, ip, c13, c0, 0	/* zero PID */
		mcr	p15, 0, ip, c7, c7, 0	/* invalidate I,D caches */
		mcr	p15, 0, ip, c7, c10, 4	/* drain write buffer */
		mcr	p15, 0, ip, c8, c7, 0	/* invalidate I,D TLBs */
		mrc	p15, 0, ip, c1, c0, 0	/* get control register */
		bic	ip, ip, #0x0001			/* disable MMU */
		mcr	p15, 0, ip, c1, c0, 0	/* write control register */

	}

	goto_start = (void (*)(U32, U32))a2;
	(*goto_start)(a0, a1);	
}

extern int sprintf(char * /*s*/, const char * /*format*/, ...);

#define ATAG_NONE       0x00000000
#define ATAG_CORE       0x54410001
#define ATAG_RAMDISK    0x54410004
#define ATAG_CMDLINE    0x54410009

struct tag_core {
        U32 flags;              /* bit 0 = read-only */
        U32 pagesize;
        U32 rootdev;
};
struct tag_header {
        U32 size;
        U32 tag;
};
struct tag_mem32 {
        U32     size;
        U32     start;  /* physical start address */
};
struct tag_videotext {
        U8              x;
        U8              y;
        U16             video_page;
        U8              video_mode;
        U8              video_cols;
        U16             video_ega_bx;
        U8              video_lines;
        U8              video_isvga;
        U16             video_points;
};
struct tag_ramdisk {
        U32 flags;      /* bit 0 = load, bit 1 = prompt */
        U32 size;       /* decompressed ramdisk size in _kilo_ bytes */
        U32 start;      /* starting block of floppy-based RAM disk image */
};
struct tag_initrd {
        U32 start;      /* physical start address */
        U32 size;       /* size of compressed ramdisk image in bytes */
};
struct tag_serialnr {
        U32 low;
        U32 high;
};
struct tag_revision {
        U32 rev;
};
struct tag_videolfb {
        U16             lfb_width;
        U16             lfb_height;
        U16             lfb_depth;
        U16             lfb_linelength;
        U32             lfb_base;
        U32             lfb_size;
        U8              red_size;
        U8              red_pos;
        U8              green_size;
        U8              green_pos;
        U8              blue_size;
        U8              blue_pos;
        U8              rsvd_size;
        U8              rsvd_pos;
};
struct tag_cmdline {
        char    cmdline[1];     /* this is the minimum size */
};
struct tag_acorn {
        U32 memc_control_reg;
        U32 vram_pages;
        U8 sounddefault;
        U8 adfsdrives;
};
struct tag_memclk {
        U32 fmemclk;
};
struct tag {
        struct tag_header hdr;
        union {
                struct tag_core         core;
                struct tag_mem32        mem;
                struct tag_videotext    videotext;
                struct tag_ramdisk      ramdisk;
                struct tag_initrd       initrd;
                struct tag_serialnr     serialnr;
                struct tag_revision     revision;
                struct tag_videolfb     videolfb;
                struct tag_cmdline      cmdline;

                /*
                 * Acorn specific
                 */
                struct tag_acorn        acorn;

                /*
                 * DC21285 specific
                 */
                struct tag_memclk       memclk;
        } u;
};
#define tag_next(t)     ((struct tag *)((U32 *)(t) + (t)->hdr.size))
#define tag_size(type)  ((sizeof(struct tag_header) + sizeof(struct type)) >> 2)

static void SetTAG(void){
	struct tag *params = (struct tag *)0x30000100;
	char *linux_cmd;
	char *p;

	memset(params, 0, sizeof(struct tag));

	/* step1: setup start tag */
	params->hdr.tag = ATAG_CORE;
	params->hdr.size = tag_size(tag_core);
	params->u.core.flags = 0;
	params->u.core.pagesize = LINUX_PAGE_SIZE;
	params->u.core.rootdev = 0;

	params = tag_next(params);

	/* step2: setup commandline tag */
//	linux_cmd = get_linux_cmd_line();
	linux_cmd = "root=/dev/mtdblock1 rw rootfstype=jffs2 noinitrd init=/linuxrc console=ttySAC1,115200 mem=64M\0";

	if (linux_cmd == NULL) {
		 printf("Wrong magic; could not find linux command line\n");
	} else {
		 /* eat leading white space */
		 for (p=linux_cmd; *p==' '; p++) {
				 ;
		 }
		 /* setup cmdline tag magic number */
		 params->hdr.tag = ATAG_CMDLINE;
		 /* please notice that size counts by word. */
		 params->hdr.size = (sizeof(struct tag_header) + strlen(linux_cmd) + 1 + 4) >> 2;
		 memcpy(params->u.cmdline.cmdline, linux_cmd, strlen(linux_cmd)+1);
		 params = tag_next(params);
		 printf("linux command line is: \"%s\"\n", linux_cmd);
	}

	/* step3: setup end tag */
	params->hdr.tag = ATAG_NONE;
	params->hdr.size = 0;

	/* help info that tagged list setups up completely */
	printf("Tagged list setups up successfully\n");

}

static void LoadRun(void)
{
	U32 i, ram_addr, buf = boot_params.run_addr.val;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -