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

📄 nand.c

📁 DMA-2442开发板bootloader
💻 C
📖 第 1 页 / 共 4 页
字号:
	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();
	//printf("goto_start...\n");	

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




static int nand_boot;
static int have_nandflash;
int nand_config()
{
	int ret;
	U16 id;
	nandif_t ni;
	NF_Init();
	id = NF_CheckId();
	//printf("chip ID = %x\n",id);
	if(id == K9F1208_ID)
	{
		//printf("k9f1208\n");
		ni.cpage_size = 512;
		ni.cpages_in_block = 32;
		ni.cpage2Kis = 0;
		ni.page_offset = 9;
		ni.block_offset = 14;
		have_nandflash =1;
		NAND_PART = K9f1208_Part;
		
	}
	else if(id == K9F1G08_ID)
	{
		ni.cpage_size = 2048;
		ni.cpages_in_block = 64;
		ni.cpage2Kis = 1;
		ni.page_offset = 11;
		ni.block_offset = 17;
		have_nandflash =1;
		NAND_PART = K9f1g08_Part;

	}
	else
		{
				have_nandflash =0;
		}



	cpage2Kis = ni.cpage2Kis;
	cpage_size = ni.cpage_size;	/* Current Page Size */
	cpages_in_block = ni.cpages_in_block;
	coob_size = (ni.cpage_size/512)*16;
	cblock_size = ni.cpage_size * ni.cpages_in_block;
	page_offset = ni.page_offset;
	block_offset =ni.block_offset;
#if 0	
	printf("cpage2Kis=%d\n",cpage2Kis);
	printf("cpage_size=%d\n",cpage_size);
	printf("cpages_in_block=%d\n",cpages_in_block);
	printf("coob_size=%d\n",coob_size);
	printf("cblock_size=%d\n",cblock_size);

	printf("coob_size=%d\n",coob_size);
	printf("page_offset=%d\n",page_offset);
	printf("block_offset=%d\n",block_offset);
#endif
	/*
	GSTATUS4 = ((ni.cpage_size <<16) & 0xffff0000 ) |
	           ((ni.cpages_in_block <<8)& 0xff00) | 
	           ((ni.cpage2Kis  )& 0xff );
	           */
}


void get_nandinfo(void)
{
	//nandif_t ni;
	//ni.cpage_size  = (GSTATUS4>>16) & 0xffff;
	//ni.cpage2Kis =  (GSTATUS4) & 0xff;
	//ni.cpages_in_block = (GSTATUS4>>8) & 0xff;

}

void check_nandflash(void)
{

}

void Nand_Detect()
{
	int boot_mode;
	boot_mode =rBWSCON;
	if(!(boot_mode &0x6))
		nand_boot =1; //boot_mode:nand flash
	else 
		nand_boot =0;//boot from nor flash
		
	
	nand_config();
	get_nandinfo();
	
	//Test_Write();
}

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

static void LoadRun(void)
{
	U32 i, block,ram_addr, buf = boot_params.run_addr.val;
	struct param_struct *params = (struct param_struct *)0x30000100;
	int size;
//	int page;
	
	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)
			sprintf(initrd, "load_ramdisk=0");
		else
			sprintf(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;
		case 3:
			tty_sel="ttySAC0";
			break;
		case 4:
			tty_sel="ttySAC1";
			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));
		sprintf(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));
	
		printf("Set boot params = %s\n", params->commandline);
	}

	printf("Load Kernel...\n");	

	if(boot_params.osstor.val)	//load program from NOR or NAND FLASH
		memcpy((void *)buf, (void *)(0x04000000+0x00020000), 0x001e0000);
	else {
		block = NAND_PART[1].offset>>block_offset;
		size = NAND_PART[1].size;
		ram_addr = buf;	
		//page = NAND_PART[1].offset>>page_offset
		//printf("block =%x,size =%x,ram_addr=%x\n",block,size,ram_addr);

		s3c244x_nand_read(block,size,ram_addr);
	
	}
#if 0	
	if(!boot_params.root_sel.val) {
		int ramdisk_sz;
		
		printf("Load Ramdisk...\n");
		
		block = NAND_PART[2].offset>>block_offset;
		size = NAND_PART[1].size;
	
		ram_addr = boot_params.initrd_addr.val;
		ramdisk_sz = boot_params.initrd_len.val;
		printf("block =%x,size =%x,ram_addr=%x\n",block,size,ram_addr);
		if(ramdisk_sz>0)
		s3c244x_nand_read(block,size,ram_addr);

	
	}
#endif	
	//NF_DIS();

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


void NandErase(void)
{
	int i, err = 0;
	
	Nand_Detect();
	//Test_Write();
	if(!have_nandflash)
		return;
	i = NandSelPart("erase");
	if(i<0)
		return;	
	
	printf("Are you sure to erase nand flash from page 0x%x, block count 0x%x ? [y/n]\n", StartBlock, BlockCnt);
	while(1) {
		char c;
		
		c = getch();
		if((c=='y')||(c=='Y'))
			break;
		if((c=='n')||(c=='N'))
			return;
	}	
	
	for(i=0; i<BlockCnt; i++) {
		if(!NF_EraseBlock(StartBlock+i)) {
			err ++;
			puts("Press any key to continue...\n");
			getch();
		}
	}	

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

void NandWrite(void)
{
	Nand_Detect();
	if(!have_nandflash)
		return;
	WrFileToNF();
	NF_DIS();		//disable nand flash interface
}

int RelocateNKBIN(U32 img_src, U32 *pStart, U32 *pLength, U32 *pLaunch);

static void LoadRunWince(void)
{
	U32 ram_addr, buf = boot_params.initrd_addr.val;
	int size;

	printf("Load Kernel...\n");	

	if(boot_params.osstor.val)	//load program from NOR or NAND FLASH
		memcpy((void *)buf, (void *)(0x04000000+0x00020000), 0x00fe0000);
	else {
		StartBlock= NAND_PART[boot_params.start.val].offset>>block_offset;	//part 2,3...
		//size = boot_params.initrd_len.val;//NandPart[boot_params.root_sel.val].size;
		size = NAND_PART[3].size;
		//ram_addr = buf;
		ram_addr = 0x30200000;
		
		printf("start_block=%x,size=%x,ram_addr=%x\n",StartBlock,size,ram_addr);
		s3c244x_nand_read(StartBlock,size,ram_addr);
	}
	
	printf("run 0x%08x...\n", boot_params.run_addr.val);
	//RelocateNKBIN(buf, &buf, &i, &boot_params.run_addr.val);
	call_linux(0, 0, boot_params.run_addr.val);
}



void NandLoadRun(void)
{
	Nand_Detect();
	//if(!nand_boot)
	//	return;
	if(boot_params.start.val<2)	//linux
		LoadRun();
	MemoryTest();
	LoadRunWince();
}

#include "norflash.h"
#define	NOR_PARAMS_OFFSET	0x1c000

int search_params(void)
{
	U32 block;
	U32 page, page_cnt;
	U8 dat[0x20000];
	BootParams *pBP = (BootParams *)dat;
	int ret=-1;
	
	Nand_Detect();	//don't show info in Nand_Detect!
	if(nand_boot) {
		block = (NAND_PART[1].offset>>block_offset)-1;
				//page_cnt = NAND_PART[0].size>>page_offset;
		//printf("block = %x\n",block);
		//search from the last page
			s3c244x_nand_read(block,cblock_size, (U32)dat);
			if(!strncmp(boot_params.start.flags, pBP->start.flags, 10)) {
				ret = 0;
			}
	
	} else {	
		memcpy(dat, (void *)(NOR_PARAMS_OFFSET), 512);	//now mmu is not set, so use original address
		if(!strncmp(boot_params.start.flags, pBP->start.flags, 10))
			ret = 0;
	}
	
	
	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 {
		printf("Fail to find boot params! Use Default parameters.\n");
		//don't printf anything before serial initialized!
	}

	return ret;
}
//保存在最后一个block,应确保程序(包括出现坏块时)不会覆盖到最后两块
int save_params(void)
{
	U32 block;
	U8 dat[0x20000];
	int ret = 0;

	Nand_Detect();
	if(nand_boot) {
		memset(dat, 0, sizeof(boot_params));
		memcpy(dat, &boot_params, sizeof(boot_params));

		block = (NAND_PART[1].offset>>block_offset)-1;
		//printf("block  = %x\n",block );
		s3c244x_nand_write(block,cblock_size,(U32)dat);
		printf("Save boot params success.\n");
	} else {
		//memcpy(dat, (void *)0x04000000, NOR_PARAMS_OFFSET);
		memcpy(dat, &boot_params, sizeof(boot_params));
		//ProgNorFlash(0, (U32)dat, sizeof(dat));	//28F128
		SectorProg((NOR_PARAMS_OFFSET),(U16 *)dat,0x1000);
	}
	
	
	return ret;
}

int set_params(void)
{
	int i, key, chg=0;
	ParamItem *pPID;
	int lcd_type;
	char *string;
	printf("\nConfig parameters\n");
	
	do {
		pPID = &boot_params.start;
		for(i=0; pPID<=&boot_params.user_params; pPID++, i++)
			printf("[%d] : %s%-8s is 0x%08x (%d)\n",
						i, (i>9)?"":" ", pPID->flags, pPID->val, pPID->val);
		printf("[%d] : Exit\n", i);
		if(boot_params.user_params.val)
			printf("User parameters is : \"%s\"\n", boot_params.string);
		
		printf("\nplease select item:");
		key = Uart_GetIntNum();
		if(key>=0&&key<i) {
			chg = 1;
			printf("please enter value:");
			i = key;
			if((&boot_params.start + i)==&boot_params.user_params) {
				//确保输入的字节数不超过127!
				    printf("\n");
			    printf("1: display 240x320\n");
			    printf("2: display 320x240\n");
			    printf("3: display 480x272\n");
			    printf("4: display 640x480\n");
			
			    lcd_type = Uart_GetIntNum();
					
			    switch(lcd_type)
			    {
			      case 1:
					string =  "display=shp240";
					 strncpy(boot_params.string, string,strlen(string)+1);
			               strncpy(boot_params.string, string,strlen(string)+1);

					break;
				case 2:
					string =  "display=shp320";
					 strncpy(boot_params.string, string,strlen(string)+1);
			               boot_params.user_params.val = strlen(string);
				        break;
				case 3:
					string =  "display=shp480";
					 strncpy(boot_params.string, string,strlen(string)+1);
			              boot_params.user_params.val = strlen(string);
					break;
				case 4:
					string =  "display=shp640";
					 strncpy(boot_params.string, string,strlen(string)+1);
			               boot_params.user_params.val = strlen(string);
					break;
				default:
					break;
			    }
				//strncpy(boot_params.string, cmd, strlen(cmd)+1);
				//boot_params.user_params.val = strlen(string);
			} else {
				key = Uart_GetIntNum();
				(&boot_params.start + i)->val = key;
			}
		} else
			break;
	} while(1);
	
	if(chg) {
		printf("Do you want to save parameters? press y or Y for save.\n");
		key = getch();
		if(key=='y'||key=='Y')
			save_params();
	}
	
	return 0;
}

⌨️ 快捷键说明

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