通用的EBOOT概念可参考“Windows CE 5.0 Boot Loader的流程分析”,本文仅通过抽象i.MX21平台上Windows CE 5.0 Eboot代码来说明从板子上电到WinCE跑起来的幕后故事以及各段代码所发挥的作用。对照源代码阅读本文会有更好的效果。
相关代码目录如下:
%WINCE\Platform\iMX21ADS\Src\Bootloader\eboot
%WINCE\PLATFORM\COMMON\SRC\ARM\Freescale\MX21\Startup
%WINCE\PLATFORM\Imx21ads\Src\Kernel\Oal
%WINCE\PUBLIC\COMMON\OAK\DRIVERS\ETHDBG\BLCOMMON\blcommon.c
(一)%WINCE\PLATFORM\COMMON\SRC\ARM\Freescale\MX21\Startup\startup.s
功能:在OEM板级初始化前先初始化i.MX21处理器的核心模块
主要的函数功能及流程分析如下:
1.StartUp()---这部分代码是Boot Loader和OAL共享的。
在板子上电后,第一步是将处理器设置为特权模式,跳转到MMUCacheDisable( ),使TLB和cache、写缓冲无效,并关闭 MMU、cache。接着设置AIPI寄存器,跳转到OALSetUpSystemControl 和OALSetUpFrequencies,初始化系统控制模式和时钟频率。程序接下来的工作是启用I Cache,并跳转到OALIsImageInRAM、OALSetUpExtMemories以初始化外部存储设备。随后是设置MAX寄存器、配置AITC中断控制器、屏蔽和清中断的一段代码。接下来程序先后跳转到OALSetUpGpio、OALSetUpKeypad,即初始化系统GPIO和键盘设备。最后程序跳转到OALStartUp(),加载g_oalAddressTable地址,再跳转到KernelStart(),完成代码重定位和从RAM中启动Eboot等功能。
上述KernelStart()函数,先跳转到OALIsImageInRAM程序段判断Image是否正跑在RAM里。如果不是,则在接下来的RelocateEBOOT程序段里进行代码重定位;如果已经在RAM里,则跳转到RamStart程序段,设置连接寄存器LR、加载OEMAddressTable和页表的地址,然后跳转到MMUSetup函数,根据OEMAddressTable设置MMU,并使能MMU、启用cache。在完成了MMU的设置后,程序跳转到blcommon.c中的BootloaderMain(),这个Eboot主控函数将调用main.c中的一系列OEM函数实现CE系统在板子上的启动。
上面提到的函数所在文件如下: OALSetUpSystemControl 、OALSetUpFrequencies、OALSetUpExtMemories、OALSetUpGpio、OALSetUpKeypad这几个函数位于 %WINCE\PLATFORM \iMX21\ Imx21ads\Src\Kernel\Oal\oal_startup.c中;OALIsImageInRAM和OALStartUp位于%WINCE\PLATFORM\Imx21ads\Src\Kernel\Oal\startup.s中。KernelStart则位于%WINCE\PLATFORM\Imx21ads\Src\Bootloader\Eboot\startup.s中。
2. MMUCacheDisable( ) --- 使TLB和cache、写缓冲无效,并关闭 MMU、cache。
3. MMUSetup()---这个函数将被%Eboot\startup.s调用,它根据OEMAddressTable设置MMU,并使能MMU、启用cache。
(二) main.c
基本流程:
初始化调试端口---初始化平台基本设备---打印用户菜单---初始化网络参数---下载内核---启动OS
主要函数及功能:
OEMReportError()----用于点亮LED,并打印出错误提示
OEMMultiBINNotify()---- 当系统具有多个BIN文件时用来提示用户下载的是哪一个BIN
OEMDebugInit( )------- 调用了OEMInitDebugSerial( ),初始化调试串口
OEMPlatformInit( )----- 初始化板上设备
① 通过调试串口打印出Eboot的版本信息
② 调用InitEthDevice(),初始化以太网控制器
③ 设置MAC地址,初始化OAL与eboot共享参数,RTC
④ 调用MainMenu( ),通过串口与用户交互,设置启动选项及参数
OEMPreDownload( )--- 判断是否下载,调用OALKitlCreateName()设置设备名,初始化IP参数,调用EbootInitEtherTransport()初始化TFTP参数
OEMReadData()----- 内部是通过OEMEthGetFrame( )来传输数据的
OEMLaunch( )----------- 根据PB里的设置来更新OAL与eboot共享参数,并判断是否需要将NK烧到Nand Flash中,最后调用Eboot\startup.s 里的Launch( )启动WinCE内核
在main.c中还有一个重要的函数,那就是ManiMenu( )。它提供了以下启动选项菜单:
0)MAC地址设置
1)静态IP设置
2)静态掩码设置
3)启用DHCP
4)恢复到出厂设置
5)保存目前Eboot的设置
D)下载
E)擦除Nor Flash
L)从Nor Flash启动
R)从RAM中启动
总的来说,在i.MX21平台上WinCE EBoot就是在以下几个文件间不断跳转的过程:
%Startup\startup.s --- oal_startup.c --- %Oal\startup.s --- %Eboot\startup.s--- blcommon.c---main.c
PS: 如果对i.MX21上电最初阶段系统初始化的汇编代码有兴趣的,可以看看“i.MX21平台上Startup.s代码分析”。