||
注:本文所叙述的BSP是从WINCE4.2升级到WINCE5.0的,所以本BSP包是非标准的,目录和标准的BSP包有些差异,但原理是一样的。
物理内存
在WINCE中物理内存,RAM(比如SDRAM)、ROM(比如EPPROM)和Flash Memory(比如nand flash,或是nor flash)都被看成物理内存,而不仅仅是传统意义上的,只有RAM才被认为是物理内存。
RAM在WINCE中像传统的物理内存一样,为操作系统和应用程序提供运行和缓存空间,对于WINCE来说,BSP包下SMDK2440\FILES\config.bib下的内容的名字为RAM处分配大小为0x6900000(105M)的SDRAM给WINCE操作系统和应用程序提供运行和缓存空间,这个大小需要根据系统的SDRAM的大小来分配,我们的系统的SDRAM是128M的。
MEMORY
;;; Tarzan Debug mode
NK 8C200000 01500000 RAMIMAGE
;RAM 8D700000 02900000 RAM;kandi chang SDRAM from 64M to 128M
RAM 8D700000 06900000 RAM
在此顺便提及所分配SDRAM大小的计算,我们知道 SMDK2440\SRC\KERNEL\HAL\ARM
下的文件map.a的以下内容
OEMAddressTable
;;;-------------------------------------------------------------
;;; Virt Addr Phys Addr MB
;;;-------------------------------------------------------------
DCD 0x80000000, 0x02000000, 30 ; 30 MB SRAM(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, 128 ; 128 MB DRAM BANK 0, 1
DCD 0x94800000, 0x48000000, 1 ; Memory control register
DCD 0x94900000, 0x49000000, 1 ; USB Host register
DCD 0x94A00000, 0x4A000000, 1 ; Interrupt Control register
…………………………………
DCD 0x95B00000, 0x5B000000, 1 ; AC97 Interface register
DCD 0x96000000, 0x00000000, 32 ; 32 MB SROM(SRAM/ROM) BANK 0
DCD 0x00000000, 0x00000000, 0 ; End of Table (MB MUST BE ZERO!)
END
根据以上内容的0x8C000000可以算出本系统的SDRAM对应的结束虚拟地址是0x94000000(=0x8C000000+128M(0x08000000)),根据这个值,可以算出本系统可以分配为RAM的SDRAM大小为0x06900000(=0x94000000 – 0x8D700000),但是0x8D700000需要根据NK.bin的大小来调整,而NK的大小(0x01500000)需要根据自己的系统来调整。
在我分配RAM过程中,遇到一个这样的问题:如果我分配的大小大于最大能分配的空间大小时(假如我分配为0x06B00000,那么0x8D700000+0x06B00000=0x94200000 >0x94000000 ),而这时系统跑不起来,会停止在以下debug信息处
……………………….
OEMInit Done...
Sp=ffffc7cc
但本人不甚明白,麻烦知道的朋友告知,谢谢!
ROM在WINCE中通常用来存储程序,其内容可断电永久保存,就像PC中的硬盘一样,它通常保存操作系统映像本身和组成操作系统的一些其他文件。ROM中的内容通常是不能改动的,这样也防止了操作系统的内容被无意改写了。ROM中的程序可被复制到内存中然后再执行,WINCE支持本地执行(execure in place,XIP),本地执行使代码无须复制到RAM中,而直接在ROM中执行。在ROM中直接运行程序可以节省一些RAM,但XIP执行的效率不如在RAM中执行的效率高;WINCE中的程序如果不使用XIP的话,那么可被压缩后存放在ROM中,当程序加载到RAM中再进行解压,这样可以节省ROM。
ROM的一个替代品是Flash Memory,通常成为闪存,其与ROM相比最大的优点是可擦写。这样它既可以用来保存操作系统本身(本系统采用Nand Flash来存储nboot、eboot及NK.bin),也可以用来存储后来安装的程序(系统启动完成后,执行shell应用程序的安装程序,从SD卡中安装并且把代码保存到Nand Flash中)。从结构上分,Flash Memory主要有AND,NAND,NOR及DINOR等,其中NAND和NOR是目前的主流类型,NOR(或非)在存储格式和读写方式上都与常用的内存相近,支持线性访问和随机读写,具有较高的速度,这也使其非常适合存储程序及相关数据。但是NOR类型的最大缺点是容量小,而其一个很重要的特点就是支持XIP。NAND(与非)类型的Flash Memory的存储和传输是以页和块为单位的,相对适合大数据的连续传输,其优点就是容量大,但其读写速度相对慢。
WINCE最大支持512MB的物理内存。
虚拟内存
WINCE是32位的操作系统,所以WINCE的虚拟寻址能力可达4GB,但是与WINXP的每个进程独享4GB虚拟地址空间不同,WINCE中所有的经常共享一个4GB的虚拟地址空间。
WINCE的内存是基于页式管理的,所以这4GB虚拟内存空间又可被分为若干个页,而不同的处理器支持的页大小通常也是不一样的,ARMV4处理器支持1KB,4KB,64KB和1MB4种页大小。WINCE操作系统支持两种页大小:1KB和4KB,WINCE虚拟内存的申请分为保留(reserve)和提交(commit)连个过程。虚拟地址空间的保留是以64KB为边界的,也就是说,任何一次虚拟内存申请都会返回一个64KB的整数倍的地址,但是把虚拟内存提交到物理内存是以页为单位的。
MMU(Memory Management Unit)是管理虚拟内存的硬件,其负责把虚拟地址映射到物理内存,并且提供一定的内存保护。MMU是WINCE中重要的模块,它把进程申请的内存映射到物理内存,并且提供系统4GB的寻址能力。在程序启动是,虚拟内存可按照需要及时地申请程序代码空间所需要的物理内存,而不是在程序启动时就把它完全加载到物理内存中。
WINCE的4GB的虚拟地址空间被分为2个2GB区域:低地址2GB是用户空间,供应用程序使用,应用程序申请的内存都会从低2GB地址空间返回;高地址2GB是内核空间,供WINCE操作系统本身使用。从0x80000000开始是WINCE内核使用的虚拟地址空间。虚拟地址0x80000000~0x9FFFFFFF一段用来静态映射所有的物理内存。也就是说WINCE会把所有的物理内存1:1地映射到这段虚拟地址上,而这段地址一共有512M,这也就是WINCE所支持的物理地址的最大值是512MB的由来。
虚拟地址0xA0000000~0xBFFFFFFF会重复映射所有的物理内存,这段对物理内存的映射与0x80000000一段最大的不同是0x80000000开始的一段物理内存是有缓冲的,而从0xA0000000开始的一段是没有缓存的。通常,缓冲可以提高系统的I/O效率,但是对于一些OAL或者bootloader中的设备驱动程序来说,使用缓冲有可能会造成灾难性后果,因为缓冲有可能会更改我们对设备的写操作顺序。因此在驱动程序中如果直接访问设备I/O或寄存器,那么通常使用0xA0000000开始的那段虚拟地址,比如
// Clock & Power Management Special Register
#define CLKPWR_BASE 0xB4C00000 // 0x4C000000
typedef struct {
unsigned long rLOCKTIME;
unsigned long rMPLLCON;
unsigned long rUPLLCON;
unsigned long rCLKCON;
unsigned long rCLKSLOW;
unsigned long rCLKDIVN;
unsigned long rCAMDIVN;
}CLKPWRreg;
在X86和ARM处理器中,WINCE的静态内存映射是有OAL层中的OEMAddressTable数组来决定的,如
OEMAddressTable
;;;-------------------------------------------------------------
;;; Virt Addr Phys Addr MB
;;;-------------------------------------------------------------
DCD 0x80000000, 0x02000000, 30 ; 30 MB SRAM(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, 128 ; 128 MB DRAM BANK 0, 1
…………………………..
逻辑内存
逻辑内存分为堆和栈两种,堆和栈对于程序代码中动态(动态申请堆上的内存)和静态(静态分配栈上的内存)的分配内存都有着重要的作用。
堆是进程中一块连续的虚拟内存空间,应用程序可以在堆上动态进行内存申请和释放。申请堆上的内存每次都可以申请4字节或8字节,因为堆上申请内存是以字节为单位的,而与页的大小无关。
在WINCE中堆是通过句柄来访问的,所有的进程都有一个默认的堆,可用函数GetProcessHeap()来得到默认堆。当进程创建时,默认堆会被一起创建,并且位置保留192KB的虚拟内存。当然,如果进程需要更多的内存,那么WINCE可以用VirtualAlloc()函数来为默认堆申请更多内存。WINCE中堆上的数据不能移动,这种算法虽然简化了虚拟内存的分配,但是容易造成堆上的内存碎片。碎片过多会导致即使堆上即使有可使用的空闲的内存空间,因为无法得到一块连续的虚拟空间,却无法分配给申请者。而为避免堆上的碎片,通常可建立一个单独的堆,当使用完这个堆后,可直接把这个堆删除。
栈是进程中另外一个重要的数据结构,函数调用时进行参数传递,函数中的局部变量都占用栈上的内存,而且函数调用结束后自动释放。栈是从高地址到低地址增长的。WINCE为每个线程分配60KB的栈,并且把栈顶的2KB拿来作为检测栈是否已满,因此每个线程用户可用栈为58KB。
应用程序可常见自己的堆,但是不能创建自己的栈。栈溢出会导致应用程序退出,因此不要在栈上放置过多的数据。