OEMAddressTable介绍

 引自:http://blog.csdn.net/gooogleman/archive/2008/08/06/2776564.aspx

一般在ARM架构的CPU上,物理地址都是统一编址的,寻址空间为4GB(32Bit CPU)。也就是说,针对一个ARM的处理器,它可以访问的物理空间是4GB。在WinCE中,ARM中的4GB物理地址空间将被映射为512MB的虚拟内存空间。 OEMAddressTable就是一个4GB物理地址空间到WinCE Kernel中的512MB虚拟地址空间的映射表。

在BSP中,会定义OEMAddressTable来描述系统中可访问的物理空间及对应的虚拟地址空间,还有大小。这个表会在WinCE系统开始启动的时候传给MMU,具体到BSP中应该是在OAL中的startup.s中,OEMAddressTable的起始地址会被放到r0寄存器中,然后就跳转到KernelStart里面,KernelStart会用OEMAddressTable完成MMU得初始化。当WinCE启动以后,就只能访问虚拟地址空间了。

举个例子,比如我们要开发一个Flash的驱动程序,那么首先我们知道这个flash所接的片选对应的物理起始地址是多少(假如是0x60000000),大小是多少(假如是0x2000000)。如果我们要在WinCE中访问它,就必须为它定义一个虚拟地址(假如是0x80000000),并添加到OEMAddressTable中,这样,我们才能在我们的驱动里面通过这个虚拟地址访问到flash。

虚拟地址不是随便定义的,WinCE中有规定,必须在0x80000000---0x9FFFFFFF。实际上WinCE创建了两套虚拟地址空间,一个是0x80000000---0x9FFFFFFF,是Cache Enabled。另一个是0xA0000000---0xBFFFFFFF,是Cache Disabled。有啥区别呢:

如果我们访问的这个空间只是一段内存空间(比如SDRAM),那么就可以用Cache Enabled的空间来访问,这样存取数据的速度会比较快,因为数据被保存在Cache中。

如果我们访问的这个空间是一个外设的地址,那么我们就要使用Cached Disabled的空间来访问,这样才能使CPU与外设同步。

可能说得有点绕,我的经验就是:只要是SDRAM,可以用Cache Enabled空间访问。如果是寄存器,就用Cache Disabled空间访问。

如何定义OEMAddressTable呢,如果安装了WinCE5.0或者6.0,那么提供的参考BSP中都已经有定义了,在BSP目录下搜索“OEMAddressTable”,一看代码就明白了,这里重复一下,格式如下:

                    虚拟地址                物理地址               大小

比如:

OEMAddressTable:

dd             0x80000000          0x60000000        0x2000000

dd             0                              0                            0

上面这个表定义了一个flash的物理地址到虚拟地址的映射,物理地址是0x60000000,虚拟地址是0x80000000,大小是32MB。OEMAddressTable最后必须以0结尾,表示OEMAddressTable结束。

 

总之,说白了就是一张物理地址/虚拟地址映射表,当我们要在WinCE中要访问相关硬件的时候,查查这张表,然后通过虚拟地址就可以访问了。如果没有定义,自己添加一个物理地址到虚拟地址的映射就好了


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/gooogleman/archive/2008/08/06/2776564.aspx

 

 

;   This module contains the OEM memory map for the S3c2410

;

;--

;

; OEMAddressTable defines the mapping from the 4GB physical address space

; to the kernel's 512MB "un-mapped" spaces.  The kernel will create two ranges

; of virtual addresses from this table. One from 0x80000000 to 0x9FFFFFFF which

; has caching & buffering enabled and one from 0xA0000000 to 0xBFFFFFFF which

; has the cache & buffering disabled.

;

; Each entry in the table consists of the Virtual Base Address to map to,

; the Physical Base Address to map from, and the number of megabytes to map.

;

; The order of the entries is arbitrary, but DRAM should be placed first for

; optimal performance. The table is zero-terminated, so the last entry MUST

; be all zeroes.

;

        

; Mapped for S3C2400X01

 

    EXPORT      OEMAddressTable[DATA]

 

OEMAddressTable

    ;;;-------------------------------------------------------------

    ;;; Virt Addr   Phys Addr   MB

    ;;;-------------------------------------------------------------

    DCD 0x80000000, 0x02000000, 30  ; 30 MB SROM(SRAM/ROM) BANK 0

    DCD 0x82000000, 0x08000000, 32  ; 32 MB SROM(SRAM/ROM) BANK 1

    DCD 0x84000000, 0x10000000, 32  ; 32 MB SROM(SRAM/ROM) BANK 2

    DCD 0x86000000, 0x18000000, 32  ; 32 MB SROM(SRAM/ROM) BANK 3

    DCD 0x88000000, 0x20000000, 32  ; 32 MB SROM(SRAM/ROM) BANK 4

    DCD 0x8A000000, 0x28000000, 32  ; 32 MB SROM(SRAM/ROM) BANK 5

    DCD 0x8C000000, 0x30000000, 64  ; 64 MB DRAM BANK 0,1

    DCD 0x90800000, 0x48000000,  1  ; Memory control register

    DCD 0x90900000, 0x49000000,  1  ; USB Host register

    DCD 0x90A00000, 0x4A000000,  1  ; Interrupt Control register

    DCD 0x90B00000, 0x4B000000,  1  ; DMA control register

    DCD 0x90C00000, 0x4C000000,  1  ; Clock & Power register

    DCD 0x90D00000, 0x4D000000,  1  ; LCD control register

    DCD 0x90E00000, 0x4E000000,  1  ; NAND flash control register

    DCD 0x91000000, 0x50000000,  1  ; UART control register

    DCD 0x91100000, 0x51000000,  1  ; PWM timer register

    DCD 0x91200000, 0x52000000,  1  ; USB device register

    DCD 0x91300000, 0x53000000,  1  ; Watchdog Timer register

    DCD 0x91400000, 0x54000000,  1  ; IIC control register

    DCD 0x91500000, 0x55000000,  1  ; IIS control register

    DCD 0x91600000, 0x56000000,  1  ; I/O Port register

    DCD 0x91700000, 0x57000000,  1  ; RTC control register

    DCD 0x91800000, 0x58000000,  1  ; A/D convert register

    DCD 0x91900000, 0x59000000,  1  ; SPI register

    DCD 0x91A00000, 0x5A000000,  1  ; SD Interface register

         DCD 0x92000000, 0x00000000,  2  ;  2 MB SROM(SRAM/ROM) BANK 0

    DCD 0x00000000, 0x00000000,  0  ; End of Table (MB MUST BE ZERO!)

 

END

 

 

Config.bib

 

MEMORY  // 定义可用的物理内存,包括起始地址大小和内存类型.

    NK      80001000  01E00000  RAMIMAGE

    RAM     8C200000  01E00000  RAM

    FLASH   92000000  00100000  RESERVED

 

; Common RAM areas

          AUD_DMA                   8c002000  00000800  RESERVED

SDIO_DMA            8c010000  00010000  RESERVED

ARGS                8C020800  00000800  RESERVED

          DBGSER_DMA                8c022000  00002000  RESERVED

          SER_DMA                     8c024000  00002000  RESERVED

          IR_DMA                       8c026000  00002000  RESERVED

          EDBG                         8c030000  00020000  RESERVED

          DISPLAY               8c100000  00100000  RESERVED  

 

 

Boot.bib  

MEMORY

;   Name     Start     Size      Type

;   -------  --------  --------  ----

    ARGS     8c020800  00000800  RESERVED

    RAM      8c026000  00006000  RAM   

    STACK    8c02c000  00004000  RESERVED

    EBOOT    8c038000  00040000  RAMIMAGE

 

; Area used to cache nk.bin while programming flash

    FLSCACHE 8c200000  01400000  RESERVED

    DISPLAY  8c100000  00100000  RESERVED

 

OEMAddressTable里定义的映射关系是给ARM MMU用的,是在KernelStart(source code参考wince420private目录)时建立的,只要WINCE还在跑,就不会解除. OEMAddressTable里的Virtual AddrPhysical Addr是对ARM来说的. 其实对于WINCE,就只能访问到它的Virtual address. 也就是说,OEMAddressTable里的Virtual addressWINCE 系统来说才是Physical Address. 经过OEMAddressTable映射后的系统的物理地址,0x80000000~0x9fffffff之间.caching and buffering的地址,这个地址加上0x20000000,就是它的cache & buffering disabled地址.所有的硬件寄存器的地址都在这个地址段上,MMU保护的.
   
上面讲的系统的物理地址,0x80000000~0xbfffffff,Kernel Mode下都可以直接访问. ISR是在KERNEL,也就可以直接访问这些系统的物理地址.无所谓"因为ISR只能访问静态映射的虚拟地址
".
   
上面说过,对于ARM来说,有虚拟地址和物理地址之分,对于WINCE来说,也有虚拟地址和物理地址之分. 可以这么说,ARM的虚拟地址就是WINCE系统的物理地址.

    32
位的OS总共有4G的虚拟地址空间,WINCE也不例外. 其中,0x00000000~0x80000000Application Space; 0x80000000~0xffffffffSystem Reserved. 系统的物理地址就在System Reserved的这段,只能在KERNEL MODE访问. 那么,APPLICATIONDRIVER(都是运行在USER MODE)要访问这些在System Reserved地址段的硬件寄存器或MEMORY怎么办呢? 只好再建立一层映射关系,Application Space里分配一段空间,把它映射到System Reserved里的地址上,这就是VirtualAlloc/CopyMmMapIoSpace干的事情.(居然这讲的是错的 )

如果你的地址是这样声明的:
#define RTC_COUNTER *((volatile unsigned *)0x91000000)
那么直接读写就可以了,比如
:
int nRtc = RTC_COUNTER;
RTC_COUNTER = nRtc;

否则,可以用
:
int nRtc = READ_REGISTER_ULONG(0x91000000);
WRITE_REGISTER_ULONG(0X91000000, nRtc);

其实这两种方式的本质是一样的,都是把地址声明成某个数据类型,然后就可以直接读写了.下面是READ_REGISTER_ULONG()WRITE_REGISTER_ULONG()的定义
:
#define READ_REGISTER_ULONG(reg) (*(volatile unsigned long * const)(reg))
#define WRITE_REGISTER_ULONG(reg, val) (*(volatile unsigned long * const)(reg)) = (val)

嵌入式设备与桌面PC的一个显著不同是它的应用程序中通常需要直接访问某一段物理内存,这在驱动程序中对物理内存的访问尤为重要,尤其是像ARM体系结构下,I/O端口也被映射成某一个物理内存地址。因此,与桌面版本Windows相比,Windows CE提供了相对简单的物理内存访问方式。无论是驱动程序还是应用程序都可以通过API访问某一段物理内存。
Windows CE
的有些函数中需要用到物理内存结构体PHYSICAL_ADDRESS Windows CEceddk.h中定义了PHYSICAL_ADDRESS,它其实是LARGE_INTEGER类型,其定义如下:
// in ceddk.h
typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS;
// in winnt.h
typedef union _LARGE_INTEGER{
  struct{
     DWORD LowPart;
    LONG HighPart;
   };
   LONGLONG QuadPart;
} LARGE_INTEGER;
可见,Windows CE中用64Bit来代表物理地址,对于大多数32位的CPU而言,只需要把它的HighPart设置为0就可以了。
如果要直接访问某一个地址的物理内存,Windows CE提供了VirtualAlloc()VirtualCopy()函数,VirtualAlloc负责在虚拟内存空间内保留一段虚拟内存,而VirtualCopy负责把一段物理内存和虚拟内存绑定,这样,最终对物理内存的访问还是通过虚拟地址进行。它们的声明如下:
//
申请虚拟内存
LPVOID VirtualAlloc(
   LPVOID lpAddress,         //
希望的虚拟内存起始地址
   DWORD dwSize,                 //
以字节为单位的大小
   DWORD flAllocationType,     //
申请类型,分为ReserveCommit
   DWORD flProtect             //
访问权限
);
//
把物理内存绑定到虚拟地址空间
BOOL VirtualCopy(
   LPVOID lpvDest,             //
虚拟内存的目标地址
   LPVOID lpvSrc,             //
物理内存地址
   DWORD cbSize,                 //
要绑定的大小
   DWORD fdwProtect             //
访问权限
);
VirtualAlloc
对虚拟内存的申请分为两步,保留MEM_RESERVE和提交MEM_COMMIT。其中MEM_RESERVE只是在进程的虚拟地址空间内保留一段,并不分配实际的物理内存,因此保留的虚拟内存并不能被应用程序直接使用。MEM_COMMIT阶段才真正的为虚拟内存分配物理内存。
下面的代码显示了如何使用VirtualAllocVirtualCopy来访问物理内存。因为VirtualCopy负责把一段物理内存和虚拟内存绑定,所以VirtualAlloc的时候只需要对内存保留,没有必要提交。
FpDriverGlobals =
(PDRIVER_GLOBALS) VirtualAlloc(
     0,
     DRIVER_GLOBALS_PHYSICAL_MEMORY_SIZE,
     MEM_RESERVE,
     PAGE_NOACCESS);
if (FpDriverGlobals == NULL) {
     ERRORMSG(DRIVER_ERROR_MSG, (TEXT(" VirtualAlloc failed!/r/n")));
    return;
}
else {
    if (!VirtualCopy(
     (PVOID)FpDriverGlobals,
     (PVOID)(DRIVER_GLOBALS_PHYSICAL_MEMORY_START),
     DRIVER_GLOBALS_PHYSICAL_MEMORY_SIZE,
     (PAGE_READWRITE | PAGE_NOCACHE))) {
        ERRORMSG(DRIVER_ERROR_MSG, (TEXT("VirtualCopy failed!/r/n")));
       return;
     }
}
CEDDK
还提供了函数MmMapIoSpace用来把一段物理内存直接映射到虚拟内存。用MmMapIoSpace申请的内存要用MmUnmapIoSpace释放,此函数的原形如下:
PVOID MmMapIoSpace(
   PHYSICAL_ADDRESS PhysicalAddress,     //
起始物理地址
   ULONG NumberOfBytes,                     //
要映射的字节数
   BOOLEAN CacheEnable                     //
是否缓存
);

VOID MmUnmapIoSpace(
   PVOID BaseAddress,                     // MmMapIoSpace
返回的起始虚拟地址
   ULONG NumberOfBytes                     //
);
其实,MmMapIoSpace函数内部也是调用VirtualAllocVirtualCopy函数来实现物理地址到虚拟地址的映射的。MmMapIoSpace函数的原代码是公开的,我们可以从%_WINCEROOT%/PUBLIC/COMMON/OAK/DRIVERS/CEDDK/DDK_MAP/ddk_map.c得到。从MmMapIoSpace的实现我们也可以看出VirtualAllocVirtualCopy的用法:
PVOID MmMapIoSpace (
    IN PHYSICAL_ADDRESS PhysicalAddress,
    IN ULONG NumberOfBytes,
    IN BOOLEAN CacheEnable
     )
{
PVOID pVirtualAddress; ULONGLONG SourcePhys;
ULONG SourceSize; BOOL bSuccess;

     SourcePhys = PhysicalAddress.QuadPart & ~(PAGE_SIZE - 1);
     SourceSize = NumberOfBytes + (PhysicalAddress.LowPart & (PAGE_SIZE - 1));

     pVirtualAddress = VirtualAlloc(0, SourceSize, MEM_RESERVE, PAGE_NOACCESS);
    if (pVirtualAddress != NULL)
     {
         bSuccess = VirtualCopy(
             pVirtualAddress, (PVOID)(SourcePhys >> 8), SourceSize,
             PAGE_PHYSICAL | PAGE_READWRITE | (CacheEnable ? 0 : PAGE_NOCACHE));

        if (bSuccess) {
             (ULONG)pVirtualAddress += PhysicalAddress.LowPart & (PAGE_SIZE - 1);
         }
        else {
             VirtualFree(pVirtualAddress, 0, MEM_RELEASE);
             pVirtualAddress = NULL;
         }
     }
    return pVirtualAddress;
}
此外,Windows CE还供了AllocPhysMem函数和FreePhysMem函数,用来申请和释放一段连续的物理内存。函数可以保证申请的物理内存是连续的,如果函数成功,会返回虚拟内存的句柄和物理内存的起始地址。这对于DMA设备尤为有用。在这里就不详细介绍了,读者可以参考Windows CE的联机文档。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值