您的位置:首页 > 其它

OEMAddressTable介绍

2012-11-29 16:44 585 查看
一般在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中要访问相关硬件的时候,查查这张表,然后通过虚拟地址就可以访问了。如果没有定义,自己添加一个物理地址到虚拟地址的映射就好了。

;------------------------------------------------------------------------------
;
; File: memory_cfg.inc
;
; This file is used to define g_oalAddressTable. This table is passed to
; KernelStart to estabilish physical to virtual memory mapping. This table
; is used also in IOMEM OAL module to map between physical and virtual
; memory addresses via OALPAtoVA/OALVAtoPA functions.
;
;------------------------------------------------------------------------------

; Export Definition

EXPORT g_oalAddressTable[DATA]

;------------------------------------------------------------------------------
;
; TABLE FORMAT
; cached address, physical address, size
;------------------------------------------------------------------------------

g_oalAddressTable

DCD 0x80000000, 0x30000000, 64 ; 32 MB DRAM BANK 6
DCD 0x84000000, 0x10000000, 32 ; nGCS2: PCMCIA/PCCARD
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, 0x08000000, 32 ; 32 MB SROM(SRAM/ROM) BANK 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 0x90F00000, 0x4F000000, 1 ; Camera 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, 32 ; 32 MB SROM(SRAM/ROM) BANK 0
DCD 0x00000000, 0x00000000, 0 ; end of table

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

END

以前,一直不知道这个表是怎么回事,刚才偶然的机会,看见了调用他的函数

C:\WINCE500\PLATFORM\COMMON\SRC\ARM\COMMON\MEMORY\memory.c

//------------------------------------------------------------------------------
//
// File: memory.c
// 从这个代码看出ARM虚拟内存和物理内存的关系
// Memory interface routines.
//
#include <windows.h>
#include <oal_log.h>
#include <oal_memory.h>

typedef struct {
UINT32 CA; // cached virtual address
UINT32 PA; // physical address
UINT32 size; // size, in MB bytes
} OAL_ADDRESS_TABLE, *POAL_ADDRESS_TABLE;

//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
//
// Function: OALPAtoVA
//
// Converts a physical address (PA) to a virtual address (VA). This routine
// uses the OEMAddressTable defined in the platform.
//
VOID* OALPAtoVA(UINT32 pa, BOOL cached)
{
OAL_ADDRESS_TABLE *pTable = g_oalAddressTable;
VOID *va = NULL;

OALMSG(OAL_MEMORY&&OAL_FUNC, (L"+OALPAtoVA(0x%x, %d)\r\n", pa, cached));

// Search the table for address range
while (pTable->size != 0) {
if (
pa >= pTable->PA &&
pa <= (pTable->PA + (pTable->size << 20) - 1)
) break; // match found 找到表中相近的内存
pTable++;
}

// If address table entry is valid compute the VA
if (pTable->size != 0) {
va = (VOID *)(pTable->CA + (pa - pTable->PA));
// If VA is uncached, set the uncached bit
if (!cached) (UINT32)va |= OAL_MEMORY_CACHE_BIT;
}

// Indicate the virtual address
OALMSG(OAL_MEMORY&&OAL_FUNC, (L"-OALPAtoVA(va = 0x%08x)\r\n", va));
return va;
}

//------------------------------------------------------------------------------
//
// Function: OALVAtoPA
//
// Converts a virtual address (VA) to a physical address (PA). This routine
// uses the OEMAddressTable defined in the platform.
//
UINT32 OALVAtoPA(VOID *pVA)
{
OAL_ADDRESS_TABLE *pTable = g_oalAddressTable;
UINT32 va = (UINT32)pVA;
UINT32 pa = 0;

OALMSG(OAL_MEMORY&&OAL_FUNC, (L"+OALVAtoPA(0x%08x)\r\n", pVA));

// Virtual address must be in CACHED or UNCACHED regions.虚拟内存范围
if (va < 0x80000000 || va >= 0xC0000000) {
OALMSG(OAL_ERROR, (
L"ERROR:OALVAtoPA: invalid virtual address 0x%08x\r\n", pVA
));
goto cleanUp;
}

// Address must be cached, as entries in OEMAddressTable are cached address.
va = va&~OAL_MEMORY_CACHE_BIT;

// Search the table for address range
while (pTable->size != 0) {
if (va >= pTable->CA && va <= pTable->CA + (pTable->size << 20) - 1) {
break;
}
pTable++;
}

// If address table entry is valid compute the PA
if (pTable->size != 0) pa = pTable->PA + va - pTable->CA;

cleanUp:
// Indicate physical address
OALMSG(OAL_MEMORY&&OAL_FUNC, (L"-OALVAtoPA(pa = 0x%x)\r\n", pa));
return pa;
}

//------------------------------------------------------------------------------
//从这两个函数可以看出,这个表只是为了容易修改而已,其实手动访问虚拟内存也是可
//的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: