bootmain.c

来自「s3c2440 bootloader适用于S3C2440开发板」· C语言 代码 · 共 1,058 行 · 第 1/2 页

C
1,058
字号
/****************************************************************
 NAME: BootMain.c
 DESC: BootMain entry point,menu,download
 HISTORY:.
 ****************************************************************/
#define	GLOBAL_CLK		1           

//#define DEBUG_VERSION

#include <stdlib.h>
#include <string.h>
#include "def.h"
#include "option.h"
#include "2440addr.h"
#include "2440lib.h"
#include "2440slib.h"
#include "mmu.h"
#include "profile.h"
#include "memtest.h"

#include "usbmain.h"
#include "usbout.h"
#include "usblib.h"
#include "2440usb.h"

#include "norflash.h"
#include "bootpara.h"

extern void cache_clean_invalidate(void);
extern void tlb_invalidate(void);
void Isr_Init(void);
void HaltUndef(void);
void HaltSwi(void);
void HaltPabort(void);
void HaltDabort(void);
void WaitDownload(void);
void Menu(void);
void ClearMemory(void);


void Clk0_Enable(int clock_sel);	
void Clk1_Enable(int clock_sel);
void Clk0_Disable(void);
void Clk1_Disable(void);


void LcdDisplay(void);
void Led_Test(void);
void comdownload(void);
void NandErase(int bootType);
void NandWrite(void);
void NandLoadRun(void);
void call_os(U32 a0, U32 a1, U32 a2);

int  SectorProg(U32 begin, U16 *data, U32 size);
int  RelocateNKBIN(U32 img_src, U32 *pStart, U32 *pLength, U32 *pLaunch);
int  write_24c02(U8 *pBuf);
int  read_24c02(U8 *pBuf);
int  find_camera(void);

U32  GetFlashID(void);

void (*restart)(void)=(void (*)(void))0x0;
extern S8 Image$$RW$$Limit[];
U32 *pMagicNum=(U32 *)Image$$RW$$Limit;



volatile U32 downloadAddress;
volatile U32 downloadFileSize;
volatile U16 checkSum;
volatile U32 err=0;
volatile U32 totalDmaCount;
volatile S32 isUsbdSetConfiguration;
volatile U8 *downPt;

S32 menuUsed        = 0;
S32 download_run    = 0;
U32 tempDownloadAddress;
S32 consoleNum;



//static U32 autorun_10ms;
static U16 autorun_ds;
static U16 autorun_trig;

static U32 cpu_freq;
static U32 UPLL;


extern S32 sel_part = -1;
extern S32 auto_nk  = 0;
extern S32 jffs2  = 0;

#define	printf	Uart_Printf
#define	DM9000_BASE			0x18000300
#define	DM9000_DATA_OFFSET	4

#define DOWN_RUN_ADDR       0x30200000


void mdelay(int ms)
{
	U32 val = (PCLK>>3)/1000-1;
	
	rTCFG0 &= ~(0xff<<8);
	rTCFG0 |= 3<<8;			//prescaler = 3+1
	rTCFG1 &= ~(0xf<<12);
	rTCFG1 |= 0<<12;		//mux = 1/2

	rTCNTB3 = val;
	rTCMPB3 = val>>1;		// 50%
	rTCON &= ~(0xf<<16);
	rTCON |= 0xb<<16;		//interval, inv-off, update TCNTB3&TCMPB3, start timer 3
	rTCON &= ~(2<<16);		//clear manual update bit
	while(ms--) {
		while(rTCNTO3>=val>>1);
		while(rTCNTO3<val>>1);
	};

}

static __inline int RtcAlmWake(void)
{	
	return ((rBCDHOUR==rALMHOUR)&&(rBCDMIN==rALMMIN));
}

void LcdBackLightOff(void)
{
	rGPBCON &= ~3;
	rGPBCON |= 1;		//set GPB0 as output
	rGPBDAT &= ~1;		//output 0;
}


// 配置CPU时钟
static void cal_cpu_bus_clk(void)
{
	U32 val;
	U8 m, p, s;
	
	val = rMPLLCON;
	m = (val>>12)&0xff;
	p = (val>>4)&0x3f;
	s = val&3;

	//(m+8)*FIN*2 不要超出32位数!
	FCLK = ((m+8)*(FIN/100)*2)/((p+2)*(1<<s))*100;
	
	val = rCLKDIVN;
	m = (val>>1)&3;
	p = val&1;	
	val = rCAMDIVN;
	s = val>>8;
	
	switch (m) {
	case 0:
		HCLK = FCLK;
		break;
	case 1:
		HCLK = FCLK>>1;
		break;
	case 2:
		if(s&2)
			HCLK = FCLK>>3;
		else
			HCLK = FCLK>>2;
		break;
	case 3:
		if(s&1)
			HCLK = FCLK/6;
		else
			HCLK = FCLK/3;
		break;
	}
	
	if(p)
		PCLK = HCLK>>1;
	else
		PCLK = HCLK;
	
	if(s&0x10)
		cpu_freq = HCLK;
	else
		cpu_freq = FCLK;
		
	val = rUPLLCON;
	m = (val>>12)&0xff;
	p = (val>>4)&0x3f;
	s = val&3;
	UPLL = ((m+8)*FIN)/((p+2)*(1<<s));
	if(UPLL==96*MEGA)
		rCLKDIVN |= 8;	//UCLK=UPLL/2
	UCLK = (rCLKDIVN&8)?(UPLL>>1):UPLL;
}


void Delay100us(int time)
{
	while(time)
	{
	    int i;
	    for(i=0;i<1000;i++);
	    time--;
    }
}	
/*************************************************************/
// BOOT LOADER 主程序
int Main(U32 RstStat)
{
	char *mode;
	int i,j;
	U8 key=0;
	U32 mpll_val, divn_upll=0;
		    
	#if ADS10   
	__rt_lib_init();                      //for ADS 1.0
	#endif

	Port_Init();
	
	rGPGCON &= ~(3<<24);
	rGPGCON |=  (1<<24); // output
	rGPGUP  |=  (1<<12); // pullup disable
	rGPGDAT |=  (1<<12); // output	
	
	Isr_Init();
	
	// 从nand flash里面读取配置信息
	// don't use 100M!
	i = search_params();	
	
	cal_cpu_bus_clk();

 	MMU_EnableICache();  
 	  
	consoleNum = boot_params.serial_sel.val&1;	// Uart 0 select for debug.
	Uart_Init(0,boot_params.serial_baud.val);
	Uart_Select(consoleNum);

	LcdDisplay();

	Uart_Printf("\ns3c2440x WinCE/Linux ATBOOTLOADER v4.12\n" __DATE__ " " __TIME__ "\n");
	
	if (boot_params.run_addr.val == 0x30400000) {
		key = 1;
	} else {
		for(j=0;j<boot_params.boot_delay.val;j++)
		{
			Uart_SendString("*");
		 	Delay100us(10000);
		 	i = Uart_GetKey();
		 	if((i==' ')||(i=='\r'))
		 	{
			 	Uart_SendString("\nLoading s3c2440x WinCE/Linux BOOT\n");
			 	key = 1;
			 	break;	
		 	}
		}
	}
	
	Uart_Printf("\n");
	
	if(key != 1){                                   // 如过在规定时间内没用按'空格'或‘回车。直接
		U32 *pt;                                    // 运行OS
		pt=(U32 *)(_RAM_STARTADDRESS+0x0020000);	// 清除RAM空间
    	while((U32)pt<(_RAM_STARTADDRESS+0x0020800))
    	{
			*pt=(U32)0;
			pt++;
   		}
    	NandLoadRun();                              // 运行Wince
	}
		
    // USBH1 Device 初始化
	rMISCCR=rMISCCR&~(1<<3);    // USBH1  配置为device
	rMISCCR=rMISCCR&~(1<<13);   // USB 1  端口配置.
		
	isUsbdSetConfiguration = 0; // USB 是否连接标志初始化为0
	
	rDSC0 = 0x2aa;
	rDSC1 = 0x2aaaaaaa;
	//Enable NAND, USBD, PWM TImer, UART0,1 and GPIO clock,
	//the others must be enabled in OS!!!
	if(0) {
		int i;
		volatile U16 *p = (volatile U16 *)0x08000000;
		
		p[3] = 0xbf;
		p[2] = 0;
		p[3] = 0;
		p[2] = 1;
		printf("dr2=0x%04x\n", p[2]);
		
		for(i=0; i<8; i++)
			printf("0x%08x\n", p[i]);
		
	}

#if 0
	UsbdMain(); 
	MMU_Init();                //MMU should be reconfigured or turned off for the debugger, 
	//After downloading, MMU should be turned off for the MMU based program,such as WinCE.	
#else

	MMU_Init();	
	Delay(0);	

  #ifdef DEBUG_VERSION
	comdownload();	
	NandWrite();
  #endif
	UsbdMain(); 
#endif
	
	pISR_SWI=(_ISR_STARTADDRESS+0xf0);	                 //for pSOS
	Led_Display(0x6);

#if USBDMA
	mode="DMA";
#else
	mode="Int";
#endif
	
	Clk0_Disable();   // 0:MPLLin, 1:UPLL, 2:FCLK, 3:HCLK, 4:PCLK, 5:DCLK0
	Clk1_Disable();   // 0:MPLLout, 1:UPLL, 2:RTC, 3:HCLK, 4:PCLK, 5:DCLK1
	
	Uart_Printf("FCLK=%dMHz, HCLK=%dMHz, PCLK=%dMHz, CPU is running at %dMHz\n",
					FCLK/MEGA, HCLK/MEGA, PCLK/MEGA, FCLK/MEGA);
	Uart_Printf("UPLL=%dMHz, UCLK=%dMHz\n", UPLL/MEGA, UCLK/MEGA);
	mpll_val = rMPLLCON;
	Uart_Printf("DIVN_UPLL%x\n", divn_upll);
	Uart_Printf("MPLLVal [M:%xh,P:%xh,S:%xh]\n", (mpll_val&(0xff<<12))>>12,(mpll_val&(0x3f<<4))>>4,(mpll_val&0x3));
	Uart_Printf("CLKDIVN:%xh\n", rCLKDIVN);
	Uart_Printf("<***************************************************>\n");
	Uart_Printf("AVANTECH BOOTLOADER v4.12 , Model 1280*120 Truly\n");
	Uart_Printf("http://www.avantech.com.cn\n");
	Uart_Printf("<***************************************************>\n");
	Uart_Printf("+---------------------------------------------+\n");
	Uart_Printf("| AT2440EVB USB Downloader 2008-12-15   |\n");
	Uart_Printf("+---------------------------------------------+\n");
	Uart_Printf("FCLK=%4.1fMHz,%s mode\n",FCLK/1000000.,mode); 
	Uart_Printf("USB: IN_ENDPOINT:1 OUT_ENDPOINT:3\n"); 
	Uart_Printf("FORMAT: <ADDR(DATA):4>+<SIZE(n+10):4>+<DATA:n>+<CS:2>\n");
	Uart_Printf("NOTE: 1. Power off/on or press the reset button for 1 sec\n");
	Uart_Printf("		  in order to get a valid USB device address.\n");
	Uart_Printf("	   2. For additional menu, Press any key. \n");
	Uart_Printf("\n");

	// The default menu is the Download & Run mode.
	// download_run = 1; 

	while(1)
	{
		if(menuUsed==1){
			Menu();
		}
		WaitDownload();	
	}

}

void Menu(void)
{
U8 key;

	menuUsed = 1;
	
	while(1)
	{
	
		Uart_Printf("\n###### Select Menu ######\n");
		Uart_Printf(" [0] Download & run to SDRAM WinCE5.0\n");
		Uart_Printf(" [1] Download Only\n");
		Uart_Printf(" [2] Write File to NAND Flash\n");
//		Uart_Printf(" [a] Write File to NOR Flash\n");
		Uart_Printf(" [3] Erase NAND Flash Partition\n");
		Uart_Printf(" [4] Auto Flash WinCE5.0 \n");
		Uart_Printf(" [5] MemoryTest \n");
		Uart_Printf(" [6] Config parameters\n");
		Uart_Printf(" [7] Start OS\n");	
		Uart_Printf(" [8] Auto Flash Linux2.6\n");	
/*		Uart_Printf(" [5] Relocate NK.bin\n");
		Uart_Printf(" [7] Test TopsunLCD\n");
		Uart_Printf(" [9] down&run\n");
*/		key=Uart_Getch();
		switch(key)
		{
	
		case '0':
			{                                           // 很重要,如果不是启动的时候系统会有不稳定
			U32 *pt;                                    // 运行OS
			pt=(U32 *)(_RAM_STARTADDRESS+0x0020000);	// 清除RAM空间
			while((U32)pt<(_RAM_STARTADDRESS+0x0020800))
			{
				*pt=(U32)0;
				pt++;
			}
			Uart_Printf("\nDownload&Run is selected.\n\n");
			tempDownloadAddress = 0x31000000;
			download_run        = 1;
			}
			return;
    	case '1':
			Uart_Printf("\nDownload Only is selected.\n");
			Uart_Printf("Enter a new temporary download address(0x3...):");
			tempDownloadAddress=Uart_GetIntNum();
			download_run = 0;
			Uart_Printf("The temporary download address is 0x%x.\n\n",tempDownloadAddress);
			return;
		case '2':
			if(downloadFileSize)
				NandWrite();
		break;
/*		case 'a':
			if(downloadFileSize)
			{int WriteAddress;
			 Uart_Printf("enter WriteAddress\n");
		//	 WriteAddress=Uart_GetIntNum();(U32)WriteAddress
			 SectorProg(0, (U16*)downloadAddress, (U32)downloadFileSize);
			}
*/		break;
		case '3':
			NandErase(boot_params.start.val);
		break;
		case '4':
			auto_nk            = 1;
			NandErase(3);
			tempDownloadAddress= 0x31000000 ;
			download_run       = 0;
			Uart_Printf("The temporary download address is 0x%x.\n\n",tempDownloadAddress);
			return;
		break;
		case '5':
			MemoryTest();
		break;
		case '7':
			NandLoadRun();
		break;
		case '6':
			set_params();
			break;
		case '8':
			auto_nk            	= 1;
			NandErase(1);
			tempDownloadAddress	= 0x31000000 ;
			download_run       	= 0;
			Uart_Printf("The temporary download address for Linux is 0x%x.\n\n",tempDownloadAddress);
			return;			
/*		case '5':
		//case 'A':
		{
			U32 launch;
			//downloadAddress=0x30200000;
			if(!RelocateNKBIN(downloadAddress, (U32 *)&downloadAddress, (U32 *)&downloadFileSize, &launch)) {
				boot_params.run_addr.val    = launch;
				boot_params.initrd_addr.val = downloadAddress;
				boot_params.initrd_len.val  = downloadFileSize;
				save_params();	//save initrd_len.val
			}
		}
			break;

		case '7':
			Testlcd();
			break;
		case '8':
			EnterPowerOff();
			break;
		case '9':
			//comdownload();
			//tempDownloadAddress=0x31000000;
			auto_nk=0;
			download_run=0;
			Uart_Printf("tempDownloadAddress=0x%x,downloadFileSize=0x%x\n",tempDownloadAddress,downloadFileSize);

			if(downloadFileSize){
	
				register void(*run)(void);	//hzh,使用寄存器变量以防止禁止DCACHE后数据不一致!!!
				rINTMSK=BIT_ALLMSK;
				run=(void (*)(void))tempDownloadAddress;	//使用DCACHE且RW区也在CACHE区间downloadAddress会在cache中
				{	//hzh
				MMU_DisableDCache();	//download program must be in 
    			MMU_DisableICache();	//non-cache area
    			MMU_InvalidateDCache();	//使所有DCACHE失效,本程序的MMU_Init中将会刷新DCACHE到存储器,
    								//为使应用此MMU_Init方式的程序能被正确运行必须先使DCACHE失效!!!
    			MMU_DisableMMU();
    			//call_os(0, 193, tempDownloadAddress);	//或不用上面3个函数而直接使用call_os
				}
				run();
			}
			Uart_Printf("enter DownloadAddress\n");

			tempDownloadAddress=Uart_GetIntNum();
			return;
*/		default:
			break;	
		}		
	}
}


// 等待下载的主逻辑函数
// 
void WaitDownload(void)
{
U32 i;
U32 j;
U32 temp;
U16 cs;
U16 dnCS;
U8  tempMem[16];
U8  key;
int first=1;
float time;
	
	checkSum        = 0;
	downloadAddress = (U32)tempMem;                             //_RAM_STARTADDRESS; 
	downPt          = (U8 *)downloadAddress;
	//This address is used for receiving first 8 byte.
	downloadFileSize=0;
	
#if 0
	MMU_DisableICache(); 
		//For multi-ICE. 
		//If ICache is not turned-off, debugging is started with ICache-on.
#endif

⌨️ 快捷键说明

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