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

📄 main.c

📁 BB40X的bootloader源代码
💻 C
字号:
/*

Main entry of this simple bootloader

Some of the code is taken from SAMSUNG's demo code

This source is free of charge. 

*/

#include "stdio.h"
#include "stdlib.h"
#include "stdarg.h"

#include "inc\44b.h"
#include "inc\option.h"

#include "Typedef.h"
#include "Nand.h"


#define CONSOLE_PORT	0

typedef (*uClinuxKernel)(void);

/*  Fout = (8 + M_DIV) * Fin / [ (2+P_DIV) * (2^S_DIV) ]  */
void SetPLL(int mdiv,int pdiv,int sdiv)
{
	rPLLCON = (mdiv << 12) | (pdiv << 4) | sdiv;
}


/* init the programmable port */
void Port_Init(void)
{
	// PORT A GROUP
	/*  BIT 9	8	7	6	5	4	3	2	1	0	*/
	/*  A24	  A23	A22	A21	A20	A19	A18	A17	A16	A0	*/	      
	/*  0		1	1	1	1	1	1	1	1	1	*/
	rPCONA = 0x3ff;	
	rPDATA = 0xfff;

	// PORT B GROUP
	/*  BIT 10	9		8		7		6		5		4		3		2		1		0		*/
	/*	/CS5	/CS4	/CS3	/CS2	/CS1	nWBE3	nWBE2	/SRAS	/SCAS	SCLK	SCKE	*/
	/*	EXT		NIC		USB		IDE		SMC		NC		NC		Sdram	Sdram	Sdram	Sdram	*/
	/*      0,        0,   0,   0,    1,    0,       0,     1,    1,    1,   1          */
	rPDATB = 0x7ff;
	rPCONB = 0xfff;

	/*  PC7		6		5		4		3		2		1		0	*/
	/*   o		o		o		o		o		o		o		o	*/
	/*   NC		NC		NC		NC		SMCALE	SMCCLE	SMCCE	SMCRB*/
	/*   01		01		01		01		01		01		01		01	*/
	rPDATC = 0x0000;	//All IO is low
	rPCONC = 0x5f555555;	
	rPUPC  = 0x3000;	//PULL UP RESISTOR should be enabled to I/O

	//PORT D GROUP
	/*  PORT D GROUP(I/O OR LCD)										*/
	/*  BIT7		6		5		4		3		2		1		0	*/
	/*      VF		VM		VLINE	VCLK	VD3		VD2		VD1		VD0	*/
	/*	   01		01		01		01		01		01		01		01	*/
	rPDATD= 0x55;
	rPCOND= 0xaaaa;	
	rPUPD = 0x00;
	//These pins must be set only after CPU's internal LCD controller is enable
	
	//PORT E GROUP 
	/*  Bit 8		7		6		5		4		3		2		1		0		*/
	/*		ENDLAN	LED3	LED2	LED1	LED0	BEEP	RXD0	TXD0	CLKOUT	*/ 
	/*      00		01		01		01		01		01		10		10		01		*/
	rPDATE	= 0x157;
	rPCONE	= 0x5568;	
	rPUPE	= 0xff;
	
	//PORT F GROUP
	/*  Bit8		7		6		5		 4		3		2		1		0		*/   
	/*  IISCLK	IISDI	IISDO	IISLRCK	Input	Input	Input	IICSDA	IICSCL	*/
	/*	100		010		010		001		00		01		01		10		10		*/
	rPDATF = 0x0;
	rPCONF = 0x22445a;
	rPUPF  = 0x1d3;

	
}


void SerialInit(int port,int mclk,int baud)
{
	if(mclk <= 0)
		mclk = MCLK;
	
	if(port == 0)
	{
		rUFCON0 = 0x0;     	
    		rUMCON0 = 0x0;     	
    		rULCON0 = 0x3;     	
    		rUCON0 	= 0x245;
    		
    		rUBRDIV0 = ( (int)(mclk/(16*baud) + 0.5) -1 );
    	}
    	else if(port == 1)
    	{
    		rUFCON1 = 0x0;     	
    		rUMCON1 = 0x0;     	
    		rULCON1 = 0x3;     	
    		rUCON1 	= 0x245;
    		
    		rUBRDIV1 = ( (int)(mclk/(16*baud) + 0.5) -1 );
    	}
    	
    	return;
}
    	
    		  
char SerialGetChar(int port)
{
	if(port == 0)
	{
		while(!(rUTRSTAT0 & 0x1));    
    
    		return rURXH0;
    	}
    	else if(port == 1)
    	{
    		while(!(rUTRSTAT1 & 0x1));    
    
    		return rURXH1;
    	}
    	
    	return 0;
}

    		
void SerialSendChar(int port,UINT8 ch)
{
	if(port == 0)
	{
		if(ch == '\n')
		{
			while(!(rUTRSTAT0 & 0x2));
			
			rUTXH0 = '\r';
		}
		
		while(!(rUTRSTAT0 & 0x2));
		
		rUTXH0 = ch;
	}
	else if(port == 1)
	{
		if(ch == '\n')
		{
			while(!(rUTRSTAT1 & 0x2));
			
			rUTXH1 = '\r';
		}
		
		while(!(rUTRSTAT1 & 0x2));
		
		rUTXH1 = ch;
	}
}


void SerialSendString(int port,UINT8 *str)
{
	while(*str != '\0')
	{
		SerialSendChar(port,*str);
		
		str++;
	}
}


void SerialPrintf(char *fmt,...)
{
    va_list ap;
    char string[512];

    va_start(ap,fmt);
    vsprintf(string,fmt,ap);
    SerialSendString(0,(UINT8 *)string);
    va_end(ap);
}	


/*	Main entry	*/
void Main(void)
{
  volatile uClinuxKernel fp;
  char c;
  
  volatile unsigned int *KernelSrc;
  volatile unsigned int *KernelDst;
  volatile int KernelSize;
  
  volatile unsigned int BlockID, PageID;
  unsigned char *cKernelDst;
  
	
  rSYSCFG = 0x0; 		//8K  cache, Write Buf Disable
  rNCACHBE0 = 0xc0002000; 	//Disable I/O cache

  Port_Init();  		//IO  initialization
     
  SerialInit(0,MCLK,19200);      	// Serial port 0 is used as our console
  
  SerialPrintf("\nSystem Inited successfully!\n");
  
  SerialPrintf("(O)Boot Linux Kernel from NOR  flash\n");
  SerialPrintf("(A)Boot Linux Kernel from NAND flash\n");
    
  c = 0;
    
  do {
     c = SerialGetChar(0);
  } while (!c) ;
    
  if(c=='o' || c=='O') 
  {
  	  rSYSCFG = 0x6;	//Enable cache
  	 
  	  KernelSrc = (unsigned int *)0x10000;
  	  KernelDst = (unsigned int *)0x0C008000;
  	  
  	  KernelSize = 0x200000 - 0x10000;
  	  
  	  for(;KernelSize>0;KernelSize--)
  	  {
  	  	*(KernelDst) = *(KernelSrc);
  	  	KernelDst++;
  	  	KernelSrc++;
  	  }
  
      SerialPrintf(0,"\n\nuClinux for ARM7TDMI is booting...\n");      		
      
      fp = (uClinuxKernel)0x0C008000;
      (*fp)();
  }
  
  else if(c=='A' || c=='a')
  {
  		cKernelDst = (unsigned char *)0x0C008000;
  		KernelSize = 0x200000 - 0x10000;
  		
  		
  		rSYSCFG = 0x6;
  		
  		NandInit();						// Init the nand chip and interface
  		
  		while(KernelSize > 0)
  		{
  			for(BlockID=0;BlockID<1024;BlockID++)
  			{
  				for(PageID=0;PageID<32;PageID++)
  				{
  					ReadPage(BlockID,PageID,cKernelDst);
  					
  					cKernelDst += 512;
  					KernelSize -= 512;
  					if(KernelSize <= 0)
  						goto BOOT_KERNEL;
  				}
  			}
  		}
  }
  
  else
  {
  		SerialPrintf("\n\n");
  
  		SerialPrintf("\nPlease Reset your ARM7TDMI target");
  		while(1);
  }

BOOT_KERNEL:  					
  SerialPrintf(0,"\n\nuClinux for ARM7TDMI is booting...\n");      		
      
  fp = (uClinuxKernel)0x0C008000;
  (*fp)();				// call the kernel, 
  					// the start address is defined by TEXTADDR in Linux Kernel	
  
  SerialPrintf(0,"\n\n");
  SerialPrintf(0,"\nPlease Reset your ARM7TDMI target");
  
}



⌨️ 快捷键说明

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