S3C2410-WinCE6.0-OAL的启动代码分析

简介: 到现在为止,我们已经了解了S3C2410平台上WinCE6.0的启动过程,包括NBOOT、EBOOT、OAL.exe、Kernel.dll的工作流程。关于WINCE600的目录也做了介绍。准备工作都做好了,接下来开始介绍S3C2410平台上WinCE6.0的移植。

    到现在为止,我们已经了解了S3C2410平台上WinCE6.0的启动过程,包括NBOOTEBOOTOAL.exeKernel.dll的工作流程。关于WINCE600的目录也做了介绍。准备工作都做好了,接下来开始介绍S3C2410平台上WinCE6.0的移植。BSP的移植很大一部分是代码的移植,所以,这里仍然以代码为主线,以函数为单位来做介绍。BSP的代码一般来说也不是自己从无到有CODE出来的,大多由芯片厂商或者微软提供,OEM厂商需要做得事情是修改相关代码以满足自己硬件的特定需求,快速推出新的产品。如果BSP的移植从零开始,那么市场的先机就完全丧失了。所以这里的介绍将基于现有代码,着重说明移植时需要修改和注意的地方。

       前面已经提到,EBOOT加载完NK后,执行的第一个函数为OAL.exe中的Startup函数,接下来我们就开始分析这个函数的实现,它的代码如下:
     

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif Code
 1         INCLUDE kxarm.h
 2 
 3         IMPORT  KernelStart
 4 
 5         TEXTAREA
 6         
 7         ;Include memory configuration file with g_oalAddressTable
 8 
 9         INCLUDE oemaddrtab_cfg.inc
10  
11         LEAF_ENTRY StartUp
12 
13         ; Compute the OEMAddressTable's physical address and 
14         ; load it into r0. KernelStart expects r0 to contain
15         ; the physical address of this table. The MMU isn'
16         ; turned on until well into KernelStart.  
17 
18         add     r0, pc, #g_oalAddressTable - (. + 8)
19         bl      KernelStart
20 
21         ENTRY_END 
22 
23         END
     

    代码简短,功能明确,完成一个函数调用。之所以能这么简短,是因为我们采用了BOOTLOADER,有关硬件初始化的工作都在BOOTLOADER中完成了,否则这里需要做硬件初始化,DeviceEmulator的对应代码就是如此,读者可以自行查看。

    代码虽然简短,但这里涉及很多内容,下面将一一分解。

    第一行代码,包括了头文件kxarm.h,它主要做了符号的宏定义,以便让我们的代码更简单,如宏定义了TEXTAREALEAF_ENTRY

第二行代码,引入一个外部函数KernelStart,它的实现在NKLDR中,前文已经做过详细介绍,这里不再赘述。

    第三行代码,TEXTAREA是一个宏定义,标明以下为代码段。

    第四行代码,包括了一个头文件,该文件中定义了一个全局变量g_oalAddressTable,它建立了虚拟内存到物理内存的映射关系。有关OEMAddressTable的内容下文会详细说明。

    第五行代码,LEAF_ENTRY StartUp,其中LEAF_ENTRY也是一个宏定义,它似乎是定义了一个入口函数,并将其EXPORT。这里我们只要知道EBOOT最后跳转到NK中,就是跳到这就可以了。

    第六行代码,add     r0, pc, #g_oalAddressTable - (. + 8),简单来说就是将OEMAddressTable的地址放到R0中,但为什么这么写,下文再做分析。

    第七行代码,bl      KernelStart,调用函数KernelStart,开始启动kernel,前文以做介绍,也不再赘述。

    有点啰嗦了,但对于新人来说,还是有必要说明一下。这段代码中,我们需要注意的地方有两处,一是OEMAddressTable的作用,二是第六行代码为什么这么写。

    先说说OEMAddressTable。一般情况下,在WinCE中我们使用的都是虚拟内存地址,甚至在访问IO时都是如此。那么在访问虚拟内存地址时如何控制其对应的硬件或物理内存呢?这个工作由MMU(内存管理单元)来完成,MMU的功能之一就是将虚拟内存地址转换为物理内存地址。当然这种转换得有一定的逻辑关系。对于X86ARMCPU来说,OEMAddressTable即定义了虚拟内存到物理内存的映射关系,在MIPSSH的处理器中,这种关系由CPU内部硬件控制,无须g_oalAddressTable。在WinCE中,这种通过OEMAddressTable的映射称为静态映射,对应的,我们还可以动态映射虚拟地址,一般用到VirtualAlloc()VirtualCopy()VirtualFree()这三个函数,而象MmMapIoSpace()等函数是CEDDK对前面几个函数的封装。

    再看第六行代码,add     r0, pc, #g_oalAddressTable - (. + 8),为什么这么写,这个+8是什么意思?反汇编看了下它对应的代码,如下图所示:
                        
     反汇编代码中的ADR是一个伪指令,它将一个地址loadR0中。源代码中采用了那么一行复杂的代码,不光S3C2410的这段代码如此,PXA270的也一样。要解释这个问题,就不得不说一下ARM中的指令预取。ARM处理器是流水线结构的,允许指令预取。在CPU执行当前指令的同时,可以从存储器中预取指令,所以当用户读取PC时,PC指向的是正在取指的指令,而非当前执行的指令,在ARM中,一般是当前执行指令下面的第2条指令(+8个字节)。所以这里的+8就不难理解了。

    本文分析了OAL的启动代码,重点介绍了OEMAddressTable的作用和指令预取对代码的影响。在移植BSP的过程中,如果硬件设备无法正常访问,首先应该确认OEMAddressTable是否建立了正确的映射关系。启动代码如果不正确,将会影响WinCE的启动,这时KITL、串口打印等常规调试方法都还无法使用,所以一定要多加小心,确保顺利通过。实在不行,只能通过点灯来Debug了。这里需要注意,OAL的启动代码执行之前,应该关闭MMUDisable MMU的工作在EBOOT中完成。

目录
相关文章
|
Linux 区块链 C语言
Linux嵌入式开发——uboot添加logo显示功能
Linux嵌入式开发——uboot添加logo显示功能
385 0
Linux嵌入式开发——uboot添加logo显示功能
|
Web App开发 测试技术
WinCE非通用调试工具汇总
WinCE-IIC调试助手(S3C2410) http://www.cnblogs.com/we-hjb/archive/2008/10/19/1314562.html WinCE下音频频谱显示(TDA7415) http://www.
1114 0
WinCE系统深度定制汇总
WinCE应用程序崩溃提示框的处理 WinCE6.0多国语言软键盘 定制WinCE6.0标准界面的一种方法 如何禁用WinCE下的沙漏图标 Silent RNAApp.exe for WinCE6.
1362 0
WinCE常用调试工具汇总
WinCE驱动调试助手V2.9 http://www.cnblogs.com/we-hjb/archive/2009/05/17/1458725.html WinCE串口调试助手V2.1 http://www.
1643 0
Wince 中的图形编程
  图形编程程序当中,笔者主要要和大家讨论的是画刷的创建和使用以及绘图函数,比如2D图像的绘制等等。  *画刷的定义:   HBRUSH hBrush;  *画刷的类型:   1. 系统内置画刷:GetStockObject()   2.
原创翻译 怎样让WinCE6.0 ARM套件下的USB摄像头工作
本文转载自微软嵌入式中文社区http://www.msembed.com     我看到过一些关于Windows Embedded CE的DirectShow摄像头的支持方面的问题咨询。
|
Windows
WinCE6.0内存分析工具
《Memory Usage Tool for Windows CE 6.x》中介绍了一个用于查看和分析WinCE6.0内存状态的工具,具体内容参见原文。       该工具主要有两部分组成,一个是运行于设备端的命令行程序(DevHealth60.exe),另一个是运行于PC端的分析和显示内存状态报告的工具(DevHealthViewer6.exe)。
1007 0
|
索引
WinCE下流驱动的一点说明
一般情况下,WinCE流驱动的索引为0~9。应用程序中,通过CreateFile(_T("XXXN:"),…)打开对应的驱动,N也为0~9。这样看来,似乎在WinCE下同名流驱动个数被限制在10个以内。
884 0
|
移动开发 索引
图解WinCE6.0下的内核驱动和用户驱动
在《WinCE驱动程序的分类》中曾提到,WinCE6.0的流驱动既可以加载到内核态也可以加载到用户态。下面通过一组图片简单说明一下这两种驱动的关系。       首先编写一个流驱动WCEDrv,代码如下。
933 0