We write C code in an object oriented manner for our S12XE-based units.
This means that all the functions take pointers to data as arguments.
This way we produce nice, portable, reusable and testable code. And we have a lot of it.
We recently needed to create a multi-CAN router capability.
That meant that we needed to have a lot of message buffers of considerable size.
So we ended up having around 10kB of RAM consumed.
By default, only 8kB of non-paged RAM is available in the CodeWarrior project.
I added page FC to get additional 4kB of RAM (additionally to already available 8kB of non-paged area between 0x2000 and 0x4000 address space).
In linker file (.prm) this page is assigned to DEFAULT_RAM segment, so we have it like this:
SEGMENTS /* Here all RAM/ROM areas of the device are listed. Used in PLACEMENT below. */ RAM = READ_WRITE 0x2000 TO 0x3FFF; ROM_C000 = READ_ONLY 0xC000 TO 0xFEFF; PAGE_E0 = READ_ONLY 0xE08000 TO 0xE0BFFF; PAGE_E1 = READ_ONLY 0xE18000 TO 0xE1BFFF; PAGE_E2 = READ_ONLY 0xE28000 TO 0xE2BFFF; PAGE_E3 = READ_ONLY 0xE38000 TO 0xE3BFFF; PAGE_E4 = READ_ONLY 0xE48000 TO 0xE4BFFF; PAGE_E5 = READ_ONLY 0xE58000 TO 0xE5BFFF; PAGE_E6 = READ_ONLY 0xE68000 TO 0xE6BFFF; PAGE_E7 = READ_ONLY 0xE78000 TO 0xE7BFFF; PAGE_F8 = READ_ONLY 0xF88000 TO 0xF8BFFF; PAGE_F9 = READ_ONLY 0xF98000 TO 0xF9BFFF; PAGE_FA = READ_ONLY 0xFA8000 TO 0xFABFFF; PAGE_FB = READ_ONLY 0xFB8000 TO 0xFBBFFF; PAGE_FC = READ_ONLY 0xFC8000 TO 0xFCBFFF; PAGE_FE = READ_ONLY 0xFE8000 TO 0xFEBFFF; RAM_FC = READ_WRITE 0xFC1000 TO 0xFC1FFF; END PLACEMENT /* here all predefined and user segments are placed into the SEGMENTS defined above. */ _PRESTART, STARTUP, ROM_VAR, STRINGS, NON_BANKED, COPY INTO ROM_C000; DEFAULT_ROM INTO PAGE_FE, PAGE_FC, PAGE_FB, PAGE_FA, PAGE_F9, PAGE_F8, PAGE_E7, PAGE_E6, PAGE_E5, PAGE_E4, PAGE_E3, PAGE_E2, PAGE_E1, PAGE_E0; DEFAULT_RAM INTO RAM, RAM_FC; END
I got linked warning L1128: Cutting value _Range beg data member from 0xFC1000 to 0x1000.
This means that linker placed some RAM data into address 0x1000 instead of 0xFC1000 because no __FAR_DATA compilation macro has been added to compilation command.
Anyway this will work now because page FC is mapped to 0x1000 address so refering to data at address 0x1000 actually refers to data at address 0xFC1000.
But this will not work when we need more pages (FD and so on).
According to Technical Note TN 238 to use more RAM pages I should mark my data (variables) with special pragma like:
#pragma DATA_SEG __RPAGE_SEG PAGED_RAM unsigned char rub_far_var; #pragma DATA_SEG DEFAULT
#pragma DATA_SEG __GPAGE_SEG PAGED_RAM unsigned char rub_far_var; #pragma DATA_SEG DEFAULT
to tell compiler/linker to place that data into RAM pages.
This is not nice (portability) but acceptable.
What is not acceptable is that to reffer to this data with a pointer, that pointer has to be specially qualified like:
unsigned char * __rptr ptr_on_far_var;
unsigned char *__far ptr_on_far_var;
This means that all our libraries that use non-qualified ("normal") pointers will not work with data allocated to paged RAM.
I checked that and this is true, for data allocated to address 0xFC1020 its pointer inside one of our libraries will show address 0x1020...
So effectively for us we can only reach 12kB of RAM memory even if we use S12XEP that has 64kB of RAM...
Otherwise our libraries won't work.
It is not possible to rewrite those libraries to have (for example) far pointers because they will stop compiling on other targets (windows, linux, other MCUs)...
Did anyone of you faced this kind of problem?
Do you have any idea what to do now?
We are lucky we needed "only" 10kB.
I don't know what would happen if we needed more than 12kB of RAM...
But I know I need to figure something out because some new projects will require lot more RAM...
Should we start to think about looking for another MCU?
Waiting for your ideas.