下面是SMDK2410中的BootLoader中的main函数实现代码:
void main(void)
{
//清空LED
OEMWriteDebugLED(0, 0xF);
//通用BootLoader (blcommon)主入口
BootloaderMain();
//注意,在此调用了BootloaderMain函数,并且没有返回值
SpinForever();
}
(1)BLCOMMON模块函数
下面列举出BLCOMMON中的控制函数并分析它们,这些函数在Blcommon.h中声明,代码实现在Blcommon.lib里:
n OEMDebugInit函数:
在运行BootloaderMain程序后,将首先调用OEMDebugInit函数,它用来初始化调试信息的I/O设备,最常见的是串口设备。由于RS232协议简单性,在系统没有启动前对串口初始化较适用。在OEMDebugInit里,又通常调用OEMInitDebugSerial函数来初始化串口。
n OEMPlatformInit函数
OEM层的初始化函数,它主要负责目标机上的硬件初始化。在汇编阶段只是初始化了很小一部分硬件,这是由于BootLoader要求处理时间短,因此在汇编阶段的硬件初始化是十分简单的。所以有必要用高级语言完成对目标机的硬件设置,这包括具体的时钟设置、驱动和传输设备接口的初始化。
下面是此函数代码实例:
BOOL OEMPlatformInit(void)
{
BYTE BootDelay;
BYTE KeySelect;
EBOOT_CFG EbootCfg;
DWORD dwStartTime, dwPrevTime, dwCurrTime;
PCI_REG_INFO NANDInfo;
EdbgOutputDebugString("Microsoft Windows CE Bootloader for the Samsung SMDK2410 Version %d.%d Built %s/r/n/r/n", EBOOT_VERSION_MAJOR, EBOOT_VERS
ION_MINOR, __DATE__);
//初始化LCD显示器
InitDisplay();
// 初始化驱动全局区域
memset(pDriverGlobals, 0, sizeof(DRIVER_GLOBALS));
pDriverGlobals->MajorVer = DRVGLB_MAJOR_VER;
pDriverGlobals->MinorVer = DRVGLB_MINOR_VER;
pDriverGlobals->eth.EbootMagicNum = EBOOT_MAGIC_NUM;
// 初始化Flash,SMDK2410上的FLASH为AMD AM29LV800型。
if (!AM29LV800_Init(AMD_FLASH_START))
{
RETAILMSG(1, (TEXT("ERROR: OEMPlatformInit: Flash 初始化
failed./r/n")));
return(FALSE);
}
........
// 让用户选择启动选项
while((dwCurrTime - dwStartTime) < EbootCfg.BootDelay)
{
KeySelect = OEMReadDebugByte();
......
}
switch(KeySelect)//判别用户命令
{
case 0x20: // 根菜单项
g_bDownloadImage = MainMenu(&EbootCfg);
break;
case 0x00: //无按键失败
case 0x0d: //用户取消了倒计时
default:
if (EbootCfg.ConfigFlags & CONFIG_FLAGS_AUTOBOOT)
{
EdbgOutputDebugString ( "/r/nLaunching flash image ... /r/n");
g_bDownloadImage = FALSE;
}
else
{
EdbgOutputDebugString ( "/r/nStarting auto-download ... /r/n");
g_bDownloadImage = TRUE;
}
break;
}
//如果用户指定了静态IP地址,那么就使用静态IP地址(不使用DHCP)
if (g_bDownloadImage && !(EbootCfg.ConfigFlags & CONFIG_FLAGS_DHCP))
{
pDriverGlobals->eth.TargetAddr.dwIP = EbootCfg.IPAddr;
pDriverGlobals->eth.SubnetMask = EbootCfg.SubnetMask;
}
//配制以太网控制器
if (!InitEthDevice(&EbootCfg))
{
DEBUGMSG(1, (TEXT("OEMPlatformInit: Failed to initialize Ethernet
controller./r/n")));
return(FALSE);
}
return(TRUE);
}
n OEMPreDownload函数
在下载操作系统前执行这个函数,它可以用来设置如何进行Image文件下载。例如,可以设置成从网络下载或者跳过下载直接加载Flash中的Image文件。
下面是此函数代码实例:
DWORD OEMPreDownload(void)
{
CHAR szDeviceName[EDBG_MAX_DEV_NAMELEN];
BOOL bGotJump = FALSE;
DWORD dwDHCPLeaseTime = 0;
PDWORD pdwDHCPLeaseTime = &dwDHCPLeaseTime;
DWORD dwBootFlags = 0;
//如果用户想进入已存在的映像,那么跳过下载
if (!g_bDownloadImage)
{
g_bWaitForConnect = FALSE; // 不等待宿主机连接
return(BL_JUMP);
}
//如果用户想用一个静态IP地址,那么就不要从DHCP服务器请求一个地址
//将DHCP租期时间变量设置为NULL
if (pDriverGlobals->eth.TargetAddr.dwIP &&
pDriverGlobals->eth.SubnetMask)
{
pdwDHCPLeaseTime = NULL;
RETAILMSG(1, (TEXT("INFO: Using static IP address %s./r/n"),
inet_ntoa(pDriverGlobals->eth.TargetAddr.dwIP)));
RETAILMSG(1, (TEXT("INFO: Using subnet mask %s./r/n"),
inet_ntoa(pDriverGlobals->eth.SubnetMask)));
}
//创建基于以太网地址的设备名称(也就是Platform Builder如何定义设备)
//
memset(szDeviceName, 0, EDBG_MAX_DEV_NAMELEN);
CreateDeviceName(&pDriverGlobals->eth.TargetAddr, szDeviceName,
PLATFORM_STRING);
EdbgOutputDebugString("INFO: Using device name: '%s'/n", szDeviceName);
//初始化TFTP传送
//
if (!EbootInitEtherTransport(&pDriverGlobals->eth.TargetAddr,
&pDriverGlobals->eth.SubnetMask,
&bGotJump,
pdwDHCPLeaseTime,
EBOOT_VERSION_MAJOR,
EBOOT_VERSION_MINOR,
PLATFORM_STRING,
szDeviceName,
EDBG_CPU_ARM720,
dwBootFlags))
{
return(BL_ERROR);
}
//保存DHCP租期时间(注意,本例中使用的是静态IP)
pDriverGlobals->eth.DHCPLeaseTime = dwDHCPLeaseTime;
return(bGotJump ? BL_JUMP : BL_DOWNLOAD);
}