WINCE6.0下配置BSP内存映射

来源:互联网 发布:淘宝售后是做什么的 编辑:程序博客网 时间:2024/05/01 05:54

作者:FLandY1982

转自:http://blog.csdn.net/flandy1982/article/details/5832391


配置BSP内存映射

FLandY1982(flandy1982@sina.com)

 日期:2010-8-23

 版本:1.0

 修改:

 

出处:http://blog.csdn.net/FLandY1982/

格式有点乱,pdf版本在:http://download.csdn.net/source/2641117


课程2: 配置BSP的内存映射

 

Windows CE6.0的内存管理与之前的版本相比有了显著的变化。在之前的版本中,所有的进程都共享一个4GB的地址空间。在CE6.0中,每个进程都拥有独有的地址空间。与之前的32个进程的限制相比新的虚拟内存管理系统使得CE6.0支持最多32000个进程。这一课包括了新的内存构架及管理细节,以便你在平台中可以映射内存空间到正确的物理内存地址上。

 

学习本课程后,你将能够:

 

 

■ 描述windows embedded CE是如何管理虚拟内存的。

 

 

■ 为硬件平台配置正确的静态内存映射。

 

 

■ 在系统中映射非连续的物理内存到虚拟内存上。

 

 

■ 在OAL及设备驱动之间共享资源。

 

 

大致课程时间:15分钟

 

 

           

 

 

 

 

 

 

 

 

系统内存映射

 

 

Windows Embedded CE使用一个包含32位虚拟地址空间的分页的虚拟内存管理系统,使用MMU映射到物理地址上。通过32位宽,系统可以寻址总共4GB的虚拟内存,CE6.0的驱动将这个虚拟内存空间分为以下2个区域(见图5-5):

 

 

�        内核空间 位于上层的(upper)2GB虚拟内存且被所有的目标设备应用进程共享。

 

 

�        用户空间 位于底层的(lower)2GB虚拟内存且被每个单独的进程独占的使用。所有的进程都使用自己拥有的独特的地址空间。内核通过一个进程切换发生器(process switch occurs)管理这种进程地址空间的映射。进程不能直接的访问内核地址空间。

 

 

5-5Windows Embedded CE 6.0的虚拟内存空间

 

 内核地址空间

 

Windows Embedded CE 6.0进一步的将内核地址空间分割成几个特定用途区域,如图5-6所示。底层(lower)的2个512MB的区域分别静态映射物理内存到缓存和非缓存的虚拟内存上。中间的2个区域用于对于操作系统设计很重要的内核XIP(execute in place) DLLs以及存储对象(Object store)。剩下的空间则是用于内核模块及CPU相关的用途。

 

 

5-6Windows Embedded CE 6.0的内核空间

 

 

表 59内核虚拟内存区域起始结束地址概述。

 

 表 5-9 内核内存区域

 

起始地址

 

 

结束地址

 

 

描述

 

 

0xF0000000

 

 

0xFFFFFFFF

 

 

用于CPU相关的系统自陷(trap)和内核数据页。

 

 

0xE0000000

 

 

0xEFFFFFFF

 

 

内核虚拟机,这个是有CPU依赖的,譬如对于SHx体系的CPU这个空间是不存在的。

 

 

0xD0000000

 

 

0xDFFFFFFF

 

 

用所有的内核模式系统模块。

 

 

0xC8000000

 

 

0xCFFFFFFF

 

 

RAM文件系统的对象存储,数据库和注册表。

 

 

0xC0000000

 

 

0xC7FFFFFF

 

 

XIP DLLs.

 

 

0xA0000000

 

 

0xBFFFFFFF

 

 

非缓存的物理内存映射。

 

 

0x80000000

 

 

0x9FFFFFFF

 

 

缓存的物理内存映射。

 

 

 

 进程地址空间

 

进程地址空间范围时从0x00000000到0x7fffffff,这个区域被分割成一个依赖于CPU的内核数据段(section),四个主要的进程区域和一个位于用户及内核空间之间的1MB的缓冲。图5-7表示出主要的区域。第一个1GB的进程区域是用于存储应用程序代码及数据。接下来的两个256MB及255MB的区域是用于内存映射对象和共享系统堆。共享系统堆对于应用进程是只读的,但是对于内核是可读写的。

 

 

5-7Windows Embedded CE 6.0的进程空间

 

表 510用户空间的虚拟内存区域起始结束地址概述。

 

表 5-10 进程内存区域

 

起始地址

 

 

结束地址

 

 

描述

 

 

0x7FF00000

 

 

0x7FFFFFFF

 

 

一个位于用户和内核空间之间的禁止映射的保护缓冲。

 

 

0x70000000

 

 

0x7FEFFFFF

 

 

内核和进程之间的共享堆。

 

 

0x60000000

 

 

0x6FFFFFFF

 

 

内存映射文件对象(并非相当于真实的物理文件),主要用于向上兼容使用为内部处理通信而使用RAM-backed映射文件的应用。

 

 

0x40000000

 

 

0x5FFFFFFF

 

 

载入到进程的DLLs及只读的数据

 

 

0x00010000

 

 

0x3FFFFFFF

 

 

应用代码及数据

 

 

0x40000000

 

 

0x00010000

 

 

CPU相关的用户内核数据(对于用户进程只读)

 

 

 

 

<> <>

 

 

内存管理单元(MMU)

 

 

 

 

Windows Embedded CE 6.0需要处理器提供一个内存映射机制来将物理内存和虚拟内存联系在一起,映射最大达到512MB的物理内存。图5-8展示了32MB的flash内存和64MB的RAM映射到内核的缓存及非缓存的静态映射区域。在ARM体系和X86体系的平台上,内存映射依赖于一个用户定义的OEMAddressTable,而在SHx体系及MIPS体系的平台上,则是直接由CPU定义。内存管理单元(MMU)负责管理物理到虚拟地址的映射。

 

 

5-8物理到虚拟内存映射的例子

 

<> <>

 

 

NOTE MMU初始化

 

 

在系统启动的时候内核初始化MMU并创建必要的页表。内核的处理器相关的部分取决于硬件平台的构架。关于更详细的实现,请参考Windows Embedded CE的私有代码,位于每种处理器类型的子目录下,%_PRIVATEROOT%/Winceos/Coreos/Kernel

 

 

 

 静态的映射虚拟地址

 

虚拟内存区域在图5-8中描述为静态的映射的物理地址,是为了强调在启动时这些地址被定义且这些映射不会改变。在内核模式下静态的映射虚拟地址总是可用并且能够直接访问的。值得注意的是,尽管如此,Windows Embedded CE也支持在运行时使用CreateStaticMapping和NKCreateStaticMapping等APIs来进行静态映射。这些函数返回一个非缓存的映射到指定物理地址的虚拟地址。

 

动态的映射虚拟地址

 

内核也能够动态的管理物理到虚拟地址的映射,这种技术用于所有的非静态映射。某个驱动或者DLL通过LoadKernelLibrary被载入到内核,能够通过调用VirtualAlloc保留一个内核地址空间的虚拟内存区域然后通过调用VirtualCopy创建一个新的页表入口映射这个虚拟地址到一个物理地址。这是一个用于映射虚拟地址到外设寄存器或者帧缓冲上以实现输入/输出操作的通用技术。如果不再需要映射缓冲,驱动或者DLL能够调用VirtualFree来删除页表入口并释放所分配的虚拟内存。

 

 内存映射和BSP

 

你必须自定义两个部分来包含某个BSP中静态内存映射相关的信息:

 

Config.bib文件提供关于系统式应该如何在平台上使用不同的内存区域的信息。譬如,你可以定义多少内存对于操作系统(OS)是可用的,多少内存可以用作空闲的RAM及多少内存被保留下来作为特殊用途。

 

■  OEMAddressTable提供关于底层平台硬件内存布局的信息,如第一课中讨论的那样。内存在Config.bib中定义应该也在OEMAddressTable中被映射。

 

映射非连续的物理内存

 

如第2Building and Deploying a Run-Time Image,提到的,在Config.bib文件中的MEMORY段中,你必须为操作系统使用的RAMIMAGE内存区域定义一个唯一的连续的内存区域。系统使用这个定义来载入内核映像及你在MODULES和FILES段定义的所有模块。你不能定义多个RAMIMAGE区域,而OAL可以在运行时扩展RAMIMAGE并且提供额外的非连续内存段。

 

表 511用于扩展RAM区域的重要的变量及函数概述。

 

表 5-11 扩展RAM区域的变量及函数

Variable/Function

 

 

Description

 

 

MainMemoryEndAddress

 

 

这个变量表示了RAM区域的结束地址。内核这个变量最初是按照Config.bib文件中系统保留的内存大小来设置的。如果有额外的连续的内存存在,OAL的OEMInit函数可以更新这个变量。

 

 

OEMGetExtensionDRAM

 

 

OAL可以使用此函数向内核报告存在的额外的非连续内存区域。OEMGetExtensionDRAM返回起始地址及第2个内存区域的长度。

 

 

pNKEnumExtensionDRAM

 

 

OAL可以使用这个函数指针向内核报告存在的超过一个以上的额外的内存区域。这个机制支持最多15个不同的非连续内存区域。如果你实现了pNKEnumExtensionDRAM函数指针,OEMGetExtensionDRAM在启动处理中就不会被调用。

 

 

 

 

实现驱动和OAL之间的资源共享

 

 

设备驱动经常需要访问物理资源,如内存映射的寄存器或者DMA缓冲区,而由于系统只与虚拟内存打交道,驱动不能直接的访问物理内存。为了使设备驱动获得访问物理内存的能力,物理地址必须被映射到虚拟地址上。

 

动态访问物理地址

 

如果某个驱动需要物理上连续的内存,在有DMA操作缓存需求的情况下,驱动可以通过调用AllocPhysMem函数分配连续的物理内存。如果分配成功了,AllocPhysMem返回一个指向虚拟地址的指针,这相当于指定的物理地址。因为系统分配了内存,在内存不在使用后调用FreePhysMem释放内存是很重要的。

 

在另一方面,如果某个驱动需要非页式的(non-paged)访问一个Config.bib中定义的物理内存区域,你可以使用MmMapIoSpace函数。MmMapIoSpace返回一个非页式的直接映射到具体的物理地址的虚拟地址。这个函数通常用于访问设备寄存器。

 

静态保留的物理内存

 

偶尔,可能有需要在一些驱动或一个驱动与OAL(如在IST和ISR之间)之间共享一个公共的物理内存区域。类似于为bootload和内核之间的启动参数使用共享一段内存区域,你可以在Config.bib文件中为驱动通信目的来保留一个共享的内存驱动。一个标准的做法是使用Drv_glob.h中的DRIVER_GLOBALS结构,如第1课中提到的那样。

 

 驱动和OAL层之间的通信

 

除了系统必须的标准的IOCTLS集外,驱动可以通过OEMIoControl中实现的自定义的IOCTLs与OAL通信。内核模式驱动通过KernelIoControl间接的调用OEMIoControl,传递自定义的IOCTL。除了直接通过OEMIoControl传递参数外,内核不会任何处理。不论如何,默认情况下用户模式驱动不能直接调用自定义的OAL IOCTL。用户模式驱动或进程调用KernelIOControl通过内核模式组件(Oalioctrl.dll)传递给OEMIoControl,这个组件维护一个用户可访问的(user-accessible)OAL IOCTL code列表。如果请求的IOCTL code不在这个模块的OAL IOCTRL code列表内调用会被拒绝,但你可以通过修改该Oalioctl.cpp文件中的IOCTL列表来定制IOCTL code,这个文件可以在%_WINCEROOT%/Public/Common/Oak/Oalioctl下找到。

 

课程总结

 

对Windows Embedded CE 6.0的内存结构有比较好的理解对每个CE开发者来说都是必要的。特别是对于BSP开发者,知道CE6.0是如何映射现有的物理内存到虚拟内存地址空间是很重要的。通过OAL、内核模式、用户模式驱动以及应用程序访问内存都需要详细的理解现有的内核模式和用户模式的静态及动态映射技术。更多的关于内核模式及用户模式组件间的通信的信息,请参考第6章,Developing Device Drivers.

 

 


原创粉丝点击