Windows CE divides the system RAM into two parts; storage memory and program memory. These two parts are equally divided by default. The problem with that is that some systems need to store files than they need program space, and some systems need more program space than storage. The division can be changed dynamically at run time, which I discussed in Windows CE: Automatically setting the Object Store Size But the device OEM can change the division default in two ways:
1.       FSRAMPERCENT in config.bib
2.       pOEMCalcFSPages() in the kernel
 
FSRAMPERCENT in config.bib
FSRAMPERCENT is used to set the percent of RAM should be used for the storage memory. Setting FSRAMPERCENT looks like:
CONFIG
    FSRAMPERCENT=0x40404040
FSRAMPERCENT is difficult or at least awkward to set because each byte represents a different amount of RAM. Each byte represents the number of 4 KB blocks per megabyte, not the percent as the name would suggest.
·         Byte 0 is the number of 4 KB blocks per megabyte in the first two megabyte of RAM
·         Byte 1 is the number of 4 KB blocks per megabyte in the second two megabyte of RAM
·         Byte 2 is the number of 4 KB blocks per megabyte in the third two megabyte of RAM
·         Byte 3 is the number of 4 KB blocks per megabyte in rest of RAM
Sounds goofy, but there is an historical reason. This allowed for early very much RAM restricted devices to set up FSRAMPERCENT for various RAM configurations. A device with just 2 MB would use the first byte for its configuration, then if there were 3 MB more it would use the next byte which might be set up different and so on.
pOEMCalcFSPages()/pfnCalcFSPages() in the kernel
Then in Windows CE 4.0 it became easier to set up the RAM divisions. The kernel now calls a function in the OAL code to determine how many pages should be in the storage memory. This only happens if the OAL provides a function and initializes the pOEMCalcFSPages() or pfnCalcFSPages() function pointers. In Windows CE 6.0 the function pointer pfnCalcFSPages is a member of g_pOemGlobal, while previous version pOEMCalcFSPages was a standalone variable. So the code for CE 6.0 looks like this:
DWORD OEMCalcFSPages( DWORD dwMemPages, DWORD dwDefaultFSPages);
 
OEMInit()
{
                …
                g_pOemGlobal->pfnCalcFSPages = OEMCalcFSPages;
                …
}
 
DWORD OEMCalcFSPages(DWORD dwMemPages, DWORD dwDefaultFSPages)
{
                DWORD Percent = 50;
                return ( dwMemPages * Percent ) / 100;
}
 
And in previous version, the function would be the same, but the initialization of the pointer could be:
DWORD OEMCalcFSPages( DWORD dwMemPages, DWORD dwDefaultFSPages);
extern DWORD (*OEMCalcFSPagesPtr)( DWORD dwMemPages, DWORD dwDefaultFSPages) pOEMCalcFSPages=OEMCalcFSPages;
This example uses a hardcode percent, but with some imagination and a good understanding of your BSP, you can probably come up with a way to make this more dynamic.
 
With these three ways to change the configuration of RAM, the question now is which one wins? If you use FSRAMPERCENT and pOEMCalcFSPages/pfnCalcFSPages the function pointers will win and set the RAM percent. Of course the code to change it at run time will then override both.
Copyright © 2009 – Bruce Eitman
All Rights Reserved