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

📄 nand.c

📁 这是三星ARM9系列开发板S3C2440的BIOS和测试例程源码.
💻 C
📖 第 1 页 / 共 2 页
字号:
	    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);
	cache_clean_invalidate();
	tlb_invalidate();	

	__asm{
//		mov	r0, a0//%0
//		mov	r1, a1//%1
//		mov	r2, a2//%2
		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 */
		//mov	pc, r2
		//nop
		//nop
		/* no outpus */
		//: "r" (a0), "r" (a1), "r" (a2)
	}
//	SetClockDivider(1, 1);
//	SetSysFclk(FCLK_200M);		//start kernel, use 200M
	SET_IF();
	goto_start = (void (*)(U32, U32))a2;
	(*goto_start)(a0, a1);	
}

static void LoadRun(void)
{
	U32 i, ram_addr, buf = boot_params.run_addr.val;
	struct param_struct *params = (struct param_struct *)0x30000100;
	int size;
	
	memset(params, 0, sizeof(struct param_struct));
	/*{
		U32 *pD = (U32 *)0x30000100;
		
		for(i=0; i<0x1000; i++)
			pD[i] = 0;
	}*/
	if(boot_params.start.val) {
		char parameters[512];
		char *rootfs;
		char initrd[32];
		char *tty_sel;
		char *devfs_sel;
		
		switch (boot_params.root_sel.val) {
		case 0:
			rootfs = "/dev/ram";
			break;
		case 1:
			rootfs = "nfs";
			break;
		case 2:
			rootfs = "/dev/mtdblock2";
			break;
		case 3:
			rootfs = "/dev/mtdblock3";
			break;
		case 4:
			rootfs = "/dev/hda1";
		default:
			rootfs="";	//user define
			break;
		}
	
		if(boot_params.root_sel.val)
			Uart_Printf(initrd, "load_ramdisk=0");
		else
			Uart_Printf(initrd, "initrd=0x%08x,0x%08x",
						boot_params.initrd_addr.val,
						boot_params.initrd_len.val);
	
		switch (boot_params.tty_sel.val) {
		case 0:
			tty_sel="ttyS0";
			break;
		case 1:
			tty_sel="ttyS1";
			break;
		case 2:
			tty_sel="tty1";
			break;
		default:
			tty_sel="";	//user define
			break;
		}
	
		if(boot_params.devfs_sel.val)
			devfs_sel = "devfs=mount";
		else
			devfs_sel = "";
		
		memset(parameters, 0, sizeof(parameters));
		Uart_Printf(parameters,
					"root=%s init=/linuxrc %s console=%s,%d mem=%dK %s %s",
					rootfs,
					initrd,
					tty_sel,
					boot_params.serial_baud.val,
					boot_params.mem_cfg.val>>10,
					devfs_sel,
					boot_params.string);
		
		params->u1.s.page_size = LINUX_PAGE_SIZE;
		params->u1.s.nr_pages = (boot_params.mem_cfg.val >> LINUX_PAGE_SHIFT);
		memcpy(params->commandline, parameters, strlen(parameters));
	
		Uart_Printf("Set boot params = %s\n", params->commandline);
	}
	
	StartPage = NandPart[1].offset>>9;
	size = NandPart[1].size;
	ram_addr = buf;	
	
	Uart_Printf("Load Kernel...\n");
	for(i=0; size>0; ) {
		
		if(!(i&0x1f)) {
			if(CheckBadBlk(i+StartPage)) {
				Uart_Printf("Skipped bad block at 0x%x\n", i+StartPage);
				i += 32;
				size -= 32<<9;
				continue;
			}
		}
		ReadPage((i+StartPage), (U8 *)ram_addr);
		i++;
		size -= 512;
		ram_addr += 512;
	}
	
	if(!boot_params.root_sel.val) {
		int ramdisk_sz;
		
		Uart_Printf("Load Ramdisk...\n");
		
		StartPage = NandPart[2].offset>>9;
		size = NandPart[1].size;
		
		ram_addr = boot_params.initrd_addr.val;
		ramdisk_sz = boot_params.initrd_len.val;
		
		for(i=0; size>0&&ramdisk_sz>0; ) {
			if(!(i&0x1f)) {
				if(CheckBadBlk(i+StartPage)) {
					Uart_Printf("Skipped bad block at 0x%x\n", i+StartPage);
					i += 32;
					size -= 32<<9;
					continue;
				}
			}
			ReadPage((i+StartPage), (U8 *)ram_addr);
			i++;
			size -= 512;
			ram_addr += 512;
			ramdisk_sz -= 512;
		}
	}
	
	DsNandFlash();

		//ChangeClockDivider(13,12);
		//ChangeMPllValue(67,1,1);	//300MHz,2440A!
		//rCLKCON = 0x7fff0;
	call_linux(0, boot_params.machine.val, buf);
}

/************************************************************/
static void InitNandFlash(int info)
{	
	U32 i;
	
	InitNandCfg();
	i = ReadChipId();
	if(info)
		Uart_Printf("Read chip id = %x\n", i);	
	if((i==0x9873)||(i==0xec75))	
		NandAddr = 0;
	else if(i==0xec76)
		NandAddr = 1;
	else {	
		Uart_Printf("Chip id error!!!\n");
		return;
	}
	if(info)
		Uart_Printf("Nand flash status = %x\n", ReadStatus());
}

void NandErase(void)
{
	int i, err = 0;
	
	InitNandFlash(1);
	
	i = NandSelPart("erase");
	if(i<0)
		return;	
	
	Uart_Printf("Are you sure to erase nand flash from page 0x%x, block count 0x%x ? [y/n]\n", StartPage, BlockCnt);
	while(1) {
		char c;
		
		c = Uart_Getch();
		if((c=='y')||(c=='Y'))
			break;
		if((c=='n')||(c=='N'))
			return;
	}	
	
	for(i=0; BlockCnt; BlockCnt--, i+=32) {
		if(EraseBlock(i+StartPage)) {
			err ++;
			Uart_Printf("Press any key to continue...\n");
			Uart_Getch();
		}
	}	

	DsNandFlash();		//disable nand flash interface
	Uart_Printf("Erase Nand partition completed ");
	if(err)
		Uart_Printf("with %d bad block(s)\n", err);
	else
		Uart_Printf("success\n");
}

void NandWrite(void)
{
	InitNandFlash(1);
	WrFileToNF();
	DsNandFlash();		//disable nand flash interface
}

void NandLoadRun(void)
{
	InitNandFlash(1);
	LoadRun();
}

/*
void TestNandFlash(void)
{		
	InitNandFlash();	
	
	while(1)
	{
		U8 key = '2';
		
		Uart_Printf("\nNand flash operations, press ESC to exit\n");
		Uart_Printf("1.Write nand flash with download file\n");
		Uart_Printf("2.Load progam from nand flash and run\n");
		Uart_Printf("3.Erase nand flash partition\n");
		Uart_Printf("4.Test nand flash erase, write, read\n");
	
		key = Uart_Getch();		
		
		if(key==0x1b)
			goto TestNandExit;
		else if(key=='1')
			WrFileToNF();
		else if(key=='2')
			LoadRun();
		else if(key=='3')
			NandErase();
		else if(key=='4')	
			TestFunc();
	}			
TestNandExit:	
	DsNandFlash();		//disable nand flash interface
}*/

int search_params(void)
{
	U32 page, page_cnt;
	U8 dat[528];
	BootParams *pBP = (BootParams *)dat;
	int ret=-1;
	
	InitNandFlash(0);	//don't show info in InitNandFlash!
	
	page     = NandPart[0].offset>>9;
	page_cnt = NandPart[0].size>>9;
	
	//search from the last page	
	while(page_cnt--) {
		ReadPage(page+page_cnt, dat);
		if(!strncmp(boot_params.start.flags, pBP->start.flags, 10)) {
			ret = 0;
			break;
		}
	}
	
	if(!ret) {
		ParamItem *pPIS = &pBP->start, *pPID = &boot_params.start;
		
		for(; pPID<=&boot_params.user_params; pPIS++, pPID++)
			if(!strncmp(pPID->flags, pPIS->flags, sizeof(pPID->flags)))
				pPID->val = pPIS->val;
		strncpy(boot_params.string, pPIS->flags, boot_params.user_params.val+1);
		if(boot_params.user_params.val!=strlen(pPID->flags)) {
			memset(boot_params.string, 0, sizeof(boot_params.string));
			boot_params.user_params.val = 0;
		}
	} else {
		//Uart_Printf("Fail to find boot params! Use Default parameters.\n");
		//don't Uart_Printf anything before serial initialized!
	}
		
	DsNandFlash();
	
	return ret;
}

//保存在最后两个block,应确保程序(包括出现坏块时)不会覆盖到最后两块
int save_params(void)
{
	U32 page, page_cnt;
	U8 dat[528];
	
	InitNandFlash(1);
	
	memset(dat, 0, sizeof(dat));
	memcpy(dat, &boot_params, sizeof(boot_params));
	
	page = (NandPart[1].offset>>9)-64;
	
	for(page_cnt=0; page_cnt<64; page_cnt++) {
		if(!(page_cnt%32))
			EraseBlock(page);
		if(!WritePage(page+page_cnt, dat))
			break;
	}
	
	DsNandFlash();
	
	Uart_Printf("Save boot params %s.\n", (page_cnt>=64)?"fail":"success");
	
	return page_cnt>=64;
}

int set_params(void)
{
	int i, key, chg=0;
	ParamItem *pPID;
	
	Uart_Printf("\nConfig parameters\n");
	
	do {
		pPID = &boot_params.start;
		for(i=0; pPID<=&boot_params.user_params; pPID++, i++)
			Uart_Printf("[%d] : %s%-8s is 0x%08x (%d)\n",
						i, (i>9)?"":" ", pPID->flags, pPID->val, pPID->val);
		Uart_Printf("[%d] : Exit\n", i);
		if(boot_params.user_params.val)
			Uart_Printf("User parameters is : \"%s\"\n", boot_params.string);
		
		Uart_Printf("\nplease select item:");
		key = Uart_GetIntNum();
		if(key>=0&&key<i) {
			chg = 1;
			Uart_Printf("please enter value:");
			i = key;
			if((&boot_params.start + i)==&boot_params.user_params) {
				//确保输入的字节数不超过127!
				char cmd[128];
				memset(cmd, 0, sizeof(cmd));
				Uart_GetString(cmd);
				strncpy(boot_params.string, cmd, strlen(cmd)+1);
				boot_params.user_params.val = strlen(cmd);
			} else {
				key = Uart_GetIntNum();
				(&boot_params.start + i)->val = key;
			}
		} else
			break;
	} while(1);
	
	if(chg) {
		Uart_Printf("Do you want to save parameters? press y or Y for save.\n");
		key = Uart_Getch();
		if(key=='y'||key=='Y')
			save_params();
	}
	
	return 0;
}

⌨️ 快捷键说明

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