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

 

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

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


 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中完成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值