WINCE的內存配置-config.bib文件的解析

朋友給的一個學習WINCE內存的配置文件,引自一個達人的博客,名字未知,在這裏向他致敬!

WINCE的內存(包括SDRAMFLASH)的配置包含兩個方面:源代碼(包括C和彙編)中的定義,及系統配置文件CONFIG.BIB中的定義。源代碼中需要定義內存的物理及虛擬地址,大小,並初始化名爲OEMAddressTable的結構數組,以告知系統物理地址與虛擬地址的對應關係,系統根據其設置生成MMU頁表。而CONFIG.BIB中一般會將內存定義成不同的段,各段用作不同的用途。

CONFIG.BIB
文件
CONFIG.BIB
文件分兩個部分,我們且稱之爲段,MEMORY段和CONFIG段。MEMORY段定義內存的分片方法,CONFIG段定義系統其它的一些屬性。以下是一個CONFIG.BIB文件MEMORY段的例子:
MEMORY
名稱 起始地址 大小 屬性
RESERVED 80000000 00008000 RESERVED
DRV_GLB 80008000 00001000 RESERVED
CS8900 80010000 00030000 RESERVED
EDBG 80040000 00080000 RESERVED
NK 800C0000 00740000 RAMIMAGE
RAM 81000000 00800000 RAM

名稱原則上可以取任意字符串,ROMIMAGE通過一個內存片的屬性來判斷它的用途。RESERVE屬性表明該片內存是BSP自己使用的,系統不必關心其用途;RAMIMAGE說明它是一片存放OS IMAGE的內存;而RAM則表示些片內存爲RAM,系統可以在其中分配空間,運行程序。
但存放 ROM的這片內存的名稱,即NK一般不要改動。因爲BIB文件中定義將一個文件加入到哪個ROM片(WINCE支持將ROM IMAGE存放在不連續的幾個內存片中)中時會用到這個名稱,如下現這行BIB文件項就定義將touch.dll放在名稱爲NK這片ROM中,
touch.dll $(_FLATRELEASEDIR)/touch.dll NK SH
因而,如果將NK改爲其它名稱,則系統中所有的BIB文件中的這個NK串都需要改動。
注意:保證各片內存不要重疊;而且中間不要留空洞,以節約內存;兩種設備如果不能同時被加載,就應該只爲其保留一片從而節約內存,例如,本例中的 CS8950是爲網卡驅動程序保留的,EDBG是爲網卡作調試(KITL)用時保留的,而系統設計成這兩個程序不會同時加載(CS8950在啓動時判斷如果EDBG在運行就會自動退出),這樣爲這兩個驅動程序各保留一片內存實在浪費而且也沒有必要。
RAM
片必須在物理上是連續的,如果系統的物理內存被分成了幾片,則在RAM片只能聲明一片,其它的內存在啓動階段由OEMGetExtensionDRAM報告給系統,如果有多於一個的內存片,應該用 OEMEnumExtensionDRAM報告。NK片則沒有此限制,只是NK跨越兩個以上物理內存片時,系統啓動時會顯示這個OS包跨越了多個物理內存片,認爲是個錯誤,但並不影響系統的執行與穩定性,因爲系統啓動之時便會打開MMU而使用虛擬地址,從而看到連續的內存空間。當然,如果內核自己都被放在了兩個內存片上,那系統應該就無法啓動了。而其它保留起來的內存片是一般是給驅動程序DMA用,應該保證它們在物理上的連續性,因爲DMA是直接用物理地址的。
CONFIG
段中以下幾個需要格外注意:
ROMSTART
,它定義ROM的起始位置,應該和NK片的起始位置相同。
ROMSIZE
,定義ROM的大小,應該和NK片的大小相同。
如果不需要NKBIN文件,則可以不設這兩個值。
ROMWIDTH
,它只是定義ROMIMAG生成ROM包時如何組織文件,而非其字面含義:ROM的寬度,所以一般都應該爲32
COMPRESSION
,一般定義爲ON,以打開壓縮功能,從而減小BIN文件的尺寸。

AUTOSIZE
,一般應該設爲ON,以使系統將定義給ROM但沒有用掉的內存當做RAM使用,而提高RAM的使用率。注意,如果ROMFLASH,則不能設爲ON,因爲FLASH不能當作RAM使用。
ROMOFFSET
,它定義OS起始位置(即ROMSTART)的物理地址和虛擬地址的差值,有些BSP中並沒有使用這個定義。
OEMAddressTable
及其它
OEMAddressTable
用來初始化系統中各種設備的虛擬地址與物理地址的對映關係。在我使用的BSP中,它是這樣定義並初始化的:
typedef struct
{
ULONG ulVirtualAddress;
ULONG ulPhysicalAddress;
ULONG ulSizeInMegs;
} AddressTableStruct;

#define MEG(A) (((A - 1)>>20) + 1)

const AddressTableStruct OEMAddressTable[] =
{
{ SDRAM_VIRTUAL_MEMORY, //
虛擬地址
PHYSICAL_ADDR_SDRAM_MAIN, //
物理地址
MEG(SDRAM_MAIN_BLOCK_SIZE) //
這段空間的大小,以M
},
………………………
{
0,
0,
0
}
}

如例子所示,OEMAddressTable爲一個結構數組,每項的第一個成員爲虛擬地址,第二個成員爲對應的物理地址,最後一個成員爲該段空間的大小。這個數組的最後一項必須全部爲0,以示整個數組的結束。內核啓動時會讀取這個數組的內容以初始化MMU頁表,啓用MMU,從爾使程序可以用虛擬地址來訪問設備。當然,OEMAddressTable中所用到的每個物理地址及虛擬地址都需要在頭文件中定義,每個BSP中定義這些值的文件不盡相同,所以,在此不能說明具體在哪個文件,讀者朋友可以參考具體BSP的文檔及代碼。

不連續內存的處理
如果內存在物理上是連續的,則 OEMAddressTable中只需要一項就可以完成對內存的地址映射。但如果BSP運行在SDRAM物理上不連續的系統上時, OEMAddressTable中需要更多的項來將SDRAM映射到連續的虛擬地址上,當然也可以將它們映射到不連續的虛擬地址上,但似乎沒有理由那麼做。而且,當其物理地址不連續時系統需要做更多的工作。例如,我有這樣一個系統:32M SDRAM16M FLASHSDRAM在物理上不連續,被分成了48M的內存塊,我的SDRAM的使用情況如下圖所示:



CONFIG
BIB文件的MEMORY段如下所示:
MEMORY
RESERVED 80000000 00008000 RESERVED
DRV_GLB 80008000 00001000 RESERVED
CS8900 80010000 00030000 RESERVED
EDBG 80040000 00080000 RESERVED
NK 800C0000 00940000 RAMIMAGE
RAM 81800000 00800000 RAM

在這32M的空間中,BSP保留了前0x80000字節,接下來是NK,它佔用了0x940000字節,而且它跨越了兩個內存片,這些和其它BSP的設置都沒有多大差別,接下來看RAM,它只佔用了最後的8M空間,前面說過,在這種物理內存不連續的系統中,RAM片不能跨越兩個物理內存塊,所以它被設計成只佔用該系統中的最後一個物理內存片,而其它兩片則由OEMEnumExtensionDRAM在運行時刻報告給系統,該函數的內容如下:

pMemSections[0].dwFlags=0;
pMemSections[0].dwStart=(SDRAM_VIRTUAL_MEMORY + 0x1000000);
pMemSections[0].dwLen=0x800000;

pMemSections[1].dwFlags=0;
pMemSections[1].dwStart=(SDRAM_VIRTUAL_MEMORY + 0x0A00000);
pMemSections[1].dwLen=0x600000;
return 2;
這樣,系統所有的內存都被激活,系統可用內存就變成了8+8+6=24M,可以將RAM定義爲這三片中的任意一片,而在 OEMEnumExtensionDRAM中報告其它兩片。但把RAM放在最後一片物理內存上有一個很大的好處,即如果NK變大,例如編譯一個DEBUG 版的系統時,這時,只需要將OEMEnumExtensionDRAM中的內容註釋掉,CONFIG.BIB文件不用做任何改動,系統就可運行,只是在 MAKEIMG時會有一個警告說系統包太大,可能無法運行,但實際不會影響系統的執行與穩定性,因爲NK之後的那段內存並沒有被使用,正好被漲大的系統佔用,這在調試時極其方便。

而如果系統物理內存是連續的,那將變得簡單的多,還以上面的設置爲例,如果這32MSDRAM是物理上連續的,內存的使用情況就可以表示如下圖:


所有者系統可用內存都可以定義在RAM片中。
對硬件知識瞭解不多的朋友請注意:SDRAM是否在物理上連續,與我們的板上有幾片SDRAM沒有關係,應該向硬件工程師瞭解SDRAM的地址分佈情況。

 

 

 

 

Understanding Memory Sections in config.bib, boot.bib, and OEMAddressTable in Windows CE 5.0 and 6.0

Introduction

Windows CE uses .bib (binary image builder) files to track, among other things, the memory layout of bootloaders as well as OS images.  If you’re writing a new BSP, you’ll definitely need a config.bib file for your OS, and you’ll likely need a boot.bib file for your bootloader.

 Let’s take a few minutes to understand how .bib files relate to memory usage.  It’s going to be muddy at the beginning, but I promise if you stick with me through the end you’ll be glad that you did.  Well, maybe you won’t be glad but you’ll know more about .bib files.  Let’s get to it!

 OEMAddressTable

Before we look at the .bib files themselves, it’s important to understand the OEMAddressTable.  This table defines the mappings between physical and virtual addresses.  For MIPS and SH processors, this table is hard coded into the processor.  For x86 and ARM, the mapping is defined in a variable called OEMAddressTable.  Since .bib files operate largely on virtual addresses, we need to remember to reference the OEMAddressTable to address any confusion about what is happening at a particular physical address.

 The table’s layout is quite simple.  Each line creates a mapping of virtual addresses to physical addresses.  The syntax is: Base virtual address, base physical address, size.  Let’s take an example from the Mainstone BSP:

 DCD     0x80000000, 0xA0000000,  64     ; MAINSTONEII: SDRAM (64MB).

DCD     0x88000000, 0x5C000000,   1     ; BULVERDE: Internal SRAM (64KB bank 0).

DCD     0x88100000, 0x58000000,   1     ; BULVERDE: Internal memory PM registers.

DCD     0x88200000, 0x4C000000,   1     ; BULVERDE: USB host controller.

 So in the first line, we are mapping the 64MB of RAM at physical address 0xA0000000 to the virtual address 0x80000000.  Since 64MB = 0x04000000 this means that the physical addresses 0xA000000-0xA4000000 are now mapped to virtual addresses 0x80000000-0x84000000.  Likewise, we’ve mapped the USB host controller which resides at physical addresses 0x4C000000-0x4C100000 to virtual addresses 0x88200000-0x88300000.

 Inside Windows CE, memory access is virtual by default.  So when we access memory at 0x81005000, we’ll be accessing some physical memory in the Mainstone’s 64MB SDRAM bank.  If we access memory at 0x88201000, we’ll be accessing the USB host controller, physically.  If we access memory at 0x86001000, we’ll get a page fault because this virtual address has no corresponding physical address.

 Now that we understand the OEMAddressTable, let’s talk about the .bib files.

 Config.bib – this contains a lot of configuration info for a CE OS image.  The MEMORY section is what we’ll focus on – it defines the memory blueprint for the CE image.  Here are the important terms:

 RAMIMAGE – This is the virtual address region that the kernel and any other components you select for your image will be placed in.  This can be RAM or linearly addressable flash.  Your config.bib file should have exactly one RAMIMAGE section.  It needs to be virtually contiguous, and it needs to be large enough to hold whatever components you’ve selected.

 RAM – This is the virtual address region of RAM that the kernel can allocate to applications and RAM-based file systems.  It needs to be virtually contiguous.  (If you need a non-contiguous section, you can allocate another, non-virtually-contiguous section at run-time by implementing the OEMGetExtensionDRAM function, but that’s outside our scope)

 RESERVED – These are virtual address regions that are set aside – the kernel won’t allocate memory in these addresses and components won’t be placed in these addresses.

 AUTOSIZE - In the CONFIG section, we have the AUTOSIZE=ON (or OFF) variable.  If this variable is on, it will treat the RAMIMAGE and RAM regions as a single region, allocating just enough space to hold all of the components to the RAMIMAGE section and making the rest of the space available as RAM.  This is a pretty convenient and easy way to make sure you’re getting maximal use out of your RAM.  One thing autosize won’t do is interfere with reserved or unallocated regions.

 Eboot.bib (sometimes known as boot.bib) – this works identically to config.bib, except we’re building a bootloader image as opposed to one with a full kernel.  All of the terminology is exactly the same.  The only difference is, in the case where we’re not using an MMU in the bootloader (CEPC is an example of these), the addresses will be physical as opposed to virtual.  Otherwise, the layout is identical.

 Bringing it together

In almost all cases, the bootloader and OS use the same OEMAddressTable.  Thus, they have the same virtual address space.

 This is especially useful when it comes to RESERVED regions.  Since nothing will be allocated or placed in these addresses, only components that refer directly to the address will have access.  That means we can use these regions for special buffers (say, DMA) or passing arguments passed in from the bootloader to the OS.  It also means that, if you want, you can leave the bootloader in RAM.

 Keep in mind that while RESERVED means that we won’t allocate/place components in those virtual addresses, by default if an area isn’t specified in a .bib file then we won’t allocate/place in it.  This means RESERVED is really more of a comment then anything.  However, it is useful in our .bib files because it helps us identify the location of special buffers and arguments so that we know not to overwrite them in other modules.

 An Example

Let’s take a look at a simplified example in the CEPC BSP:

Here’s our OEMAddressTable (platform/common/src/x86/common/startup/startup.asm):

_OEMAddressTable:

        dd  80000000h,     0,      04000000h

This means that we’re mapping physical addresses 0x00000000-0x04000000 to virtual addresses 0x80000000-0x84000000.  That’s 64MB of RAM.

Here’s our boot.bib (platform/CEPC/src/bootloader/eboot/boot.bib):

MEMORY

;   Name     Start     Size      Type

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

    EBOOT   00130000  00020000  RAMIMAGE

    RAM        00150000  00070000  RAM

    ETHDMA     00200000  00020000  RESERVED

Remember the CEPC bootloader uses physical addresses.  So in virtual address terms, our bootloader code is living at 0x80130000-0x80150000, with RAM available from 0x80150000-0x801C0000.  We’re reserving a buffer for our Ethernet card from 0x80200000-0x80220000.

 And a condensed version of config.bib (platform/CEPC/files/config.bib):

 MEMORY

;   Name     Start     Size      Type

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

; 64 MB of RAM (note: AUTOSIZE will adjust boundary)

    NK       80220000  009E0000  RAMIMAGE

    RAM      80C00000  03400000  RAM

    DMA      80100000  00030000  RESERVED   ; Native DMA reserved.

    BOOTARGS 801FFF00  00000100  RESERVED   ; Boot arguments

    EDBG_DMA 80200000  00020000  RESERVED   ; EDBG DMA buffer

There are several interesting things going on here:

First, our OS image (NK) starts at 0x80220000, and RAM resides directly above it.  That means we’re not allowing any components or allocation to write below 0x80220000, and thus our bootloader code is protected.

 Second, note that we have also reserved some regions.  The EDBG_DMA corresponds to the same addresses that the bootloader reserved.  This way we can make a smooth transition from bootloader to kernel without worrying about the contents of this memory being tampered with. 

 Another region has been reserved from 0x80100000-0x80130000.  This is very close to the start of our bootloader.  If we reserved even a byte more, we would not expect our bootloader to continue to be executable after we boot the OS.  However, since the bootloader’s address space isn’t referenced by any region in config.bib, we know that it will remain untouched by the OS.  This way we can jump back to the bootloader code during a warm reset, if desired.

 We’re not required to keep our bootloader in memory, though.  We could easily place the bootloader (in boot.bib) at the end of the RAM space (in config.bib).  This way after the image was successfully downloaded we could allocate memory over the top of the bootloader and make full use of all of our system RAM.  What you don’t want to do is intersect the bootloader with the RAMIMAGE part of config.bib – this means you’ll overwrite the code you’re running to download, during download!

Finally, notice we have a special reserved region called “boot arguments”.  If we at the CEPC’s bootloader we will see that it writes explicitly to the (physical) 0x001FFF00-0x002000000.  You’ll also notice this isn’t used anywhere in the boot.bib layout.  That means we can be assured it will be untouched (unless, of course, something else in the bootloader writes explicitly to that address range).

This is how we pass arguments from the bootloader to the OS – the OS can read directly from 0x801FFF00 and be assured that the kernel won’t tamper with it because it is RESERVED.  Technically, we could have indicated that area as RESERVED in the bootloader as well.

 Hopefully this has given you some insight into .bib memory layouts.

update: In response to a comment generated by this entry I'd like to point out that the virtual addresses used in both OEMAddressTable and config.bib must fall between 0x80000000 and 0xA0000000 - the kernel virtual memory space reserved for cachable access.

 

發佈了21 篇原創文章 · 獲贊 3 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章