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 + -
显示快捷键?