
We get calls regularly about memory utilization in Rabbit products. Usually customers are running out of it! In this ask Larry article I will show you how to interpret the ORG file that is generated every time you compile a Rabbit program. There is only one caveat with this analysis – the compilation must be successful. So… if you are running out of memory you will need to “back up” your code to the last successful compilation.
Note: The information in this article is only valid for Dynamic C versions 9.4 and up and 10.
There are several sets of diagrams on the following pages. All the values were derived from the ORG files for each of the times the program was compiled. They are memory maps of a simple, one line “Hello World” program compiled as indicated in each diagram. Even though the compilations were to specific Rabbit products, the information will be valid for all devices using the same memory model: run from flash/RAM, Separate I&D enabled/disabled. The actual memory addresses will vary according to how much memory is present but the model will be the same. The numbers on the right are physical addresses. The numbers inside the blocks are the number of bytes (rounded) in decimal.
For the Run in Flash model, the usage of flash is independent of the amount of RAM but it does vary between Separate I&D Enabled vs Disabled. The memory layout for RAM does not vary much except for the amount used in some of the sections.
For the Run in RAM model, the diagram compares/contrasts Separate I&D Enabled vs Disabled. You can see that the upper memory is used the same (with some size variations) but the lower RAM is quite different.
For more tips on how to use memory you should read TN238.
Here are some ways to re-allocate memory for several situations IF YOUR CODE IS RUNNING IN FLASH. Any macro definitions should go into your Options – Project Options – Defines.
- If you are running out of Root Code space
- Enable Separate I&D spaces if you have not already done so.
- Force selected functions into xmem by using the xmem keyword in the function declaration. You can use the MAP file to see where functions are located in memory.
- Place a “#memmap xmem” directive at the top of your program. This will move all your code to xmem and leave Root code for Dynamic C usage.
- If Separate I&D is disabled, you can define the macro “ROOT_SIZE_4K” (for versions prior to 10.21 you need to use DATAORG) to a value other than 6 (the default). Please refer to the diagram for the following:
- Increasing ROOT_SIZE_4K will
- increase the amount of Root Code
- decrease the amount of “DC Stuff” in flash
- decrease the amount of Root Data
- shift the “DC Stuff” in RAM down – its size does not change
- increase the amount of XMEM Data
- Decreasing ROOT_SIZE_4K will do just the opposite
- Increasing ROOT_SIZE_4K will
- If you are running out of XMEM code space
- For Separate I&D, you can move the boundary between XMEM Code and Root Constants by defining the macro “ROOT_SIZE_4K”. The default value is 3 so you can drop it down to 1 or 2. However, keep in mind that you are moving the boundary in 4K blocks and that for every 4K added to XMEM you are giving up 4K of Root Constant memory.
- You can force functions into Root by placing the “root” qualifier in front of the function declaration.
- If you are running out of Root Data space:
- The best solution is to declare some of your variables as “far.” This essentially puts them into XMEM Data. This is only valid for DC10.
- If you are running out of XMEM Data
- Make sure you are using all of Root Data
- Specify that some variables go into Battery Backed RAM if your product has it.
- Get a product with more memory
Consider the following IF YOUR CODE IS RUNNING FROM RAM and is using DC10.21 or newer:
- The macro “XMEMCODE_SIZE” defines the boundary between XMEM code and XMEM Data. In the sample showing the RCM5600W the boundary is 0x60000 (the default will vary by product and compilation settings). You may change this value based on your requirement.
- The macro “ROOT_SIZE_4K” may also be used as described above.
Another piece of data that you may find important in the ORG file is that for each section of memory it shows how much of it is being used. You can use this information to help you determine the best solution for moving code and/or data to other areas.
Although we generally recommend that Separate I&D be enabled, there are instances where having it disabled (the default) will provide a better solution. Keep in mind that no matter how you partition memory the amount available does not change. By changing definitions, moving boundaries, etc. you are merely changing how memory is being used.
The next page has the main portion of an ORG file for the simple “Hello World” compiled to an RCM5700 with Separate I&D enabled – left side chart on page 4. Here are the explanations of the titles on the chart:
- The Name is how the section is “known” to the Dynamic C Compiler
- The Type is the type of section
- Code, data, etc.
- The u means that the content builds up from the bottom of the section
- The d means that the content builds down from the top of the section
- The BB R M title is described in the ORG file.
- The upper line in the Allocated Range is in segmented format while the second line contains absolute addresses. The segmented format is constructed as follows: Segment:Offset. The absolute address can be calculated from it as follows:
- Absolute Address = ( Segment * 0x1000 ) + Offset
- The Size value is the number of bytes allocated
- The Used Range and Size show how much the program has actually used
- The Next column indicates the name of the ORG section which will be used for the same purpose once the current section is filled.
I have highlighted the addresses (bold red) that were used as addresses in the diagram. I have also highlighted in green those origin sections which were combined into a single “DC Stuff” block of the diagram.
Compiler Origin Data:
BB = Battery backup capable RAM
R = Reserve origin
M = Merged
Name | Type |BB R M| Allocated Range Size | Used Range Size | Next
-----------------------------------------------------------------------------------------------
rootcode@0 | RCOD u | | 00:0000 - 00:c800 c800h | 00:0000 - 00:28a6 28a6h |
| | | 00000h - 0c800h | 00000h - 028a6h |
-----------------------------------------------------------------------------------------------
no_lcall@0 | RESV u | x | fffe:e800 - 00:e000 1800h | fffe:e800 - 00:e000 1800h |
| | | 0c800h - 0e000h | 0c800h - 0e000h |
-----------------------------------------------------------------------------------------------
xmemcode@0 | XCOD u | | 00:e000 - 02:e000 2000h | 00:e000 - 01:ef83 1f83h | xmemcode@1
| | | 0e000h - 10000h | 0e000h - 0ff83h |
-----------------------------------------------------------------------------------------------
rootconst@0 | RCON u | | 10:0000 - 10:3000 3000h | 10:0000 - 10:0277 277h |
| | | 10000h - 13000h | 10000h - 10277h |
-----------------------------------------------------------------------------------------------
xmemcode@1 | XCOD u | | 05:e000 - ea:e000 e5000h | 05:e000 - 05:e916 916h |
| | | 13000h - f8000h | 13000h - 13916h |
-----------------------------------------------------------------------------------------------
user_block@0| RESV u | x | ea:e000 - f2:e000 8000h | ea:e000 - f2:e000 8000h |
| | | f8000h - 100000h | f8000h - 100000h |
-----------------------------------------------------------------------------------------------
xmemdata3@0 | XVAR d | | f2:e000 - f5:e000 3000h | f4:f000 - f5:e000 0h |
| | | 100000h - 103000h | 103000h - 103000h |
-----------------------------------------------------------------------------------------------
rootdata@0 | RVAR d | | 100:3000 - 100:c800 9800h | 100:c2cb - 100:c800 535h |
| | | 103000h - 10c800h | 10c2cbh - 10c800h |
-----------------------------------------------------------------------------------------------
intvec@0 | RESV u | x | 100:c800 - 100:ca00 200h | 100:c800 - 100:ca00 200h |
| | | 10c800h - 10ca00h | 10c800h - 10ca00h |
-----------------------------------------------------------------------------------------------
xintvec@0 | RESV u | x | 100:ca00 - 100:cb00 100h | 100:ca00 - 100:cb00 100h |
| | | 10ca00h - 10cb00h | 10ca00h - 10cb00h |
-----------------------------------------------------------------------------------------------
watcode@0 | WCOD u | x | 100:cb00 - 100:ce00 300h | 100:cb00 - 100:ce00 300h |
| | | 10cb00h - 10ce00h | 10cb00h - 10ce00h |
-----------------------------------------------------------------------------------------------
run_in_ram@0| RVAR d | | 100:ce00 - 100:d000 200h | 100:ce05 - 100:d000 1fbh |
| | | 10ce00h - 10d000h | 10ce05h - 10d000h |
-----------------------------------------------------------------------------------------------
xmemdata@0 | XVAR d | | ff:e000 - 111:e000 12000h | 110:f000 - 111:e000 0h |
| | | 10d000h - 11f000h | 11f000h - 11f000h |
-----------------------------------------------------------------------------------------------
tc_buff@0 | RESV u | x | 111:e000 - 112:e000 1000h | 111:e000 - 112:e000 1000h |
| | | 11f000h - 120000h | 11f000h - 120000h |



- Larry C.
Larry Cicchinelli is Rabbit’s Technical Support Manager. He has 30 years of embedded experience, and is considered one of the foremost authorities on Rabbit products. Larry and his staff offer comprehensive technical support to Rabbit customers.
Submit your questions for Larry via email at AskLarry@rabbit.com
Read more Ask Larry Answers
