📄 main.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 + -