<< Previous | Index | Next >>

5. Rabbit Memory Organization

The architecture of earlier Rabbit processors was derived from the original Z80 microprocessor. The original Z80 instruction set used 16-bit addresses to address a 64 KB memory space. All code and data had to fit in this 64 KB space. To expand the available memory space, the Rabbit 4000 adopts a scheme similar to that used by the Z180.

The 64 KB space is divided into segments and the Rabbit's Memory Mapping Unit (MMU) maps each segment to a block in a larger memory. The larger memory is 1 MB by default, although the Rabbit 4000 allows this larger address space to be resized. The segments are effectively windows to the larger memory. The view from the window can be adjusted so that the window looks at different blocks in the larger memory. Note also that the Rabbit 4000 has many new instructions that allow direct access to the larger memory space. Figure 5-1 shows the memory mapping schematically.

NOTE: Please see Technical Note 202, "Rabbit Memory Management in a Nutshell," for more details on how memory mapping works on the Rabbit 2000 and 3000. This document is available at:
www.rabbit.com/support/techNotes_whitePapers.shtml

5.1 Physical Memory

The Rabbit 4000 has a configurable physical address space. The default addressable space on the 4000 is 1 MB, the same as that used on the Rabbit 2000 and 3000. However, on the Rabbit 4000, the physical address space can be reconfigured to use additional address lines to resize the physical memory from 512 K to 16 MB. The physical memory can be increased to 4 MB without the use of additional address lines by mapping in 1 MB memory devices into the four available physical memory banks. In special circumstances more than 16 MB of memory can be installed and accessed using auxiliary memory mapping schemes. Typical Rabbit 4000 systems have two types of directly addressable physical memory: flash memory and static RAM.

5.1.1 Flash Memory

Flash memory in a Rabbit 4000-based system may be small-sector or large-sector type. Small-sector memory typically has sectors of 128 to 4096 bytes. Individual sectors may be separately erased and written. In large-sector memory the sectors are often 16 KB to 64 KB or more. Large-sector memory is less expensive and has faster access time. The best solution will usually be to lay out a design to accept several different types of flash memory, including the flexible small-sector memories and the fast large-sector memories.

Flash memory follows a write-once-in-a-while and read-frequently model. Depending on the particular type of flash used, the flash memory may wear out after it has been written approximately 10,000 to 100,000 times.

5.1.2 SRAM

Static RAM may or may not be battery-backed. If the SRAM is battery-backed it retains its data when primary power is disconnected. SRAM chips typically used for Rabbit systems are 128 KB, 256 KB, 512 KB, or 1 MB. With the configurable physical memory of the Rabbit 4000 and support in Dynamic C 10.21 and later versions, static RAM chips of 1 MB and larger may also be used.

When the memory is battery-backed, power is supplied at 2 V to 3 V from a battery. While preserving memory contents with battery power, the shutdown circuitry must keep the chip select line high.

5.1.3 Basic Memory Configuration

A basic Rabbit system typically contains two or three static memory devices: one flash memory device and one or two RAM devices. Additional static memory devices may be added. If an application requires storing a lot of data in flash memory, it is recommended that a mass storage flash device be added such as NAND or serial flash. Dynamic C contains drivers for both NAND and serial mass storage devices. Alternatively, another parallel flash memory device could be added, although these devices tend to be smaller and more expensive and are not as suitable for larger amounts of data. Note that some board designs may only contain a serial boot flash and SRAM. On these boards, the program is copied into the SRAM at boot time from the serial flash. The program is then executed from static RAM.

Trying to use a single, parallel flash memory chip to store both a program and live data that must be frequently changed can create software latency problems. When data is written to a small-sector flash memory, the memory is inoperative during the 5 to 20 ms that it takes to write a sector. If the same memory is used to hold data and the program, then the execution of code must cease during this write time. The 5-20 ms is timed out by a small routine executing from root RAM while system interrupts are disabled, effectively freezing the system for 5-20 ms. The 5-20 ms lockup period can adversely affect real-time operation.

5.2 Memory Segments

From the point of view of a Dynamic C programmer, there are a number of different uses of memory. Each memory use occupies a different segment in the logical 16-bit address space. The four segments are shown in Figure 5-1.

Figure 5-1 Memory Map of 16-bit Logical Address Space

The figure above shows that the segments of the 16-bit logical address space map to the physical address space. The extended register set and additional 32 bit registers provided by the Rabbit 4000 make it easy to access the physical memory directly, bypassing the logical to physical mapping and allowing linear access of up to 16 MB. The size of the physical address space is determined by the quadrant size.

The quadrant size is determined by the MMU Expanded Code Register (MECR). This register contains the Bank Select Address setting. The Bank Select Address represents the two most significant bits of the physical address that will be used to select amony the different quadrants. By default, the MECR selects A19 and A18, thus leaving 18 bits for the address, which results in a quadrant size of 256 KB. Table 5-1 shows the possible MECR values and the resulting quadrant sizes.

Table 5-1 Selecting the Quadrant Size
MECR Value
Address Bits Used to Select Quadrant
Quadrant Size
Physical Address Space
11100000b
A18, A17
128 KB
512 KB
00000000b
A19, A18
256 KB
1 MB (default)
00100000b
A20, A19
512 KB
2 MB
01000000b
A21, A20
1 MB
4 MB
01100000b
A22, A21
2 MB
8 MB
10000000b
A23, A22
4 MB
16 MB

One advantage of retaining the Rabbit 16-bit logical memory organization is that 16-bit addresses and pointers can reduce code size and execution times.

NOTE: The relative size of the base and data segments can be adjusted by increasing or decreasing the BIOS macro DATAORG in increments of 0x1000.

5.2.1 Definition of Terms

The following definitions clarify some of the terms that will be encountered in this chapter.

Extended Code (a.k.a., xmem code): Instructions located in the extended memory segment.

Extended Constants (a.k.a., xmem constants): C constants located in the extended memory segment. They are mixed together with the extended code.

Extended Memory (a.k.a., xmem): Logical addresses in 0xE000 - 0xFFFF range.

Extended RAM: RAM not used for root variables or stack. Extended memory in RAM may be used for large buffers to save root RAM space. The Dynamic C compiler supports the far keyword to allow C data types to be declared and defined in extended memory. The code generation for the far data types makes use of the expanded Rabbit 4000 instructions and registers. The function xalloc() also allocates space in extended RAM memory. See the Dynamic C User's Manual for more information on the far keyword.

Far Constants: C constants declared with the "far" keyword currently located in the extended memory segment. The location of far constants may be changed in the future.

Root Code: Instructions located in the base segment.

Root Constants: C constants, such as quoted strings, initialized variables or data tables, that are located in the base segment. Root constants share space with root code unless separate I&D space is enabled.

Root Memory: Logical addresses below 0xE000. Please note that root memory is not the same as the root segment. The root segment is contained in root memory, as are the data and stack segments. The root segment is also known as the base segment.

Root Variables: C variables, including structures and arrays that are not initialized to a fixed value, are located in the data segment.

5.2.2 The Base (or Root) Segment

The base segment has a typical size of 24 KB. The larger the base segment, the smaller the data segment and vice-versa. Base segment address zero is always mapped to physical address zero. Sometimes the base segment is mapped to flash memory since root code and root constants do not change except when the system is reprogrammed. It may be mapped to RAM for debugging, or to take advantage of the faster access time offered by RAM. Serial flash boot configurations always map the base segment to RAM since there is no parallel flash.

With separate I&D space disabled, the base segment holds a mixture of code and constants. C functions or assembly language programs that are compiled to the base segment are interspersed with data constants. Data constants are inserted between blocks of code. Data constants defined inside a C function are placed after the end of the code belonging to the function. Data constants defined outside of C functions are placed in memory where they are encountered in the source code.

Except in small programs, the bulk of the code in a program is executed using the extended memory (xmem) segment. Code operates at the same speed whether addressed through the base segment or the xmem segment, except that calling and returning from xmem functions takes a few extra clock cycles. It just takes a few cycles longer to call xmem functions and return from them.

5.2.2.1 Types of Code Best-Suited for the Base Segment

5.2.3 The Data Segment

The data segment has a typical size of 28 KB, starting at 24 KB (0x6000 above root code) and ending at 52 KB (0xCFFF). The data segment is mapped to RAM and contains C variables. Data allocation starts at or near the top and proceeds in a downward direction. It is also possible to place executable code in the data segment if it is copied from flash to the data segment. This can be desirable for code that is self modifying, code to implement debugging aids or code that controls writes to the flash memory.

In separate I&D space, the data segment is twice as big (~54 KB), but code cannot be executed from it.

5.2.4 The Stack Segment

Usually the stack segment is assigned to the range of logical addresses 0xD000 to 0xDFFF. It is always mapped to RAM and holds the system stack. Multiple stacks may be implemented by defining them in the 4 KB space, by remapping the 4 KB space to different locations in physical RAM memory, or by using both approaches. Multiple stack allocation is handled by µC/OS-II internally. For example, if sixteen 1 KB stacks are needed then four stacks can be placed in each 4 KB mapping and four different mappings for the window can be used.

5.2.5 The Extended Memory Segment

This 8 KB segment from logical address 0xE000 to 0xFFFF is a sliding window into extended code and it can also be used by routines that manipulate data located in extended memory. The xmem window uses up only 8 KB of the 16-bit addressing space. While executing code the mapping is shifted by 4 KB each time the code passes the halfway point in the 8 KB xmem window. The halfway point corresponds to the root address 0xF000, or 60KB. On all Rabbit processors, up to 1 MB of code can be efficiently executed by moving the mapping of the 8 KB window using special instructions that are designed for this purpose: long call (LCALL), long jump (LJP) and long return (LRET). Dynamic C currently supports up to 1MB of code using these instructions. The Rabbit 4000 processor allows up to 16 MB of code using new extended versions of these instructions: long long call (LLCALL), long long jump (LLJP), and long long return (LLRET).

The xmem segment is a window into the physical address space. Using the appropriate segment register (XPC or LXPC) any logical address in the range 0xE000 to 0xFFFF can be mapped to any address in the physical address space. Consider the following examples:

Table 5-2 Mapping Xmem Addresses
Segment Register
Logical Address
Mapping Equation
Physical Address
XPC = 0xFE 0xE74F 0xFE000 + 0xE74F = 0x10C74F 0x10C74F
LXPC = 0x0FE 0xE74F 0x0FE000 + 0xE74F = 0x10C74F 0x10C74F
XPC = 0xF2 0xE000 0xF2000 + 0xE000 = 0x100000 0x100000
LXPC = 0xFF0 0xFFFF 0xFF0000 + 0xFFFF = 0xFFFFFF 0xFFFFFF

WARNING: The XPC is used for addressing up to 1 MB, and the LXPC is used for addressing up to 16 MB. Mixing the use of the XPC and LXPC is dangerous.

Please see Technical Note 202, "Rabbit Memory Management in a Nutshell," for more details on how memory mapping works on the Rabbit 2000 and Rabbit 3000. This document is available at: rabbit.com.

5.3 Separate I&D Space

Separate instruction and data space is a hardware memory management scheme that uses address line inversion to double the amount of logical address space in the base and data segments. In other words, this doubles the amount of root code and root data available for an application program.

Without separate I&D space, recall that in a typical memory map of the 16-bit address space, the base segment holds a mixture of code and constants and is mapped to flash; the data segment holds C variables and is mapped to RAM. With separate I&D space, code and data no longer have to divide this space because they share logical addresses by inverting address lines depending on whether the CPU is fetching instructions or data.

The drawing in Figure 5-2 shows the logical address space when separate I&D space is both enabled and disabled. Typical SEGSIZE values are shown. The boundary at 0x3000 (and 0x6000) is determined by the macro ROOT_SIZE_4K in the BIOS. The value of this macro is the number of 4 kilobyte pages used for the base segment. The boundary may be changed, but care must be taken. To change the boundary, define ROOT_SIZE_4K to the desired number of 4K pages on the "Defines" tab in Options | Project Options.

Figure 5-2 16-Bit Logical Address Space
NOTE: This diagram illustrates how separate I&D space works; the actual values used in the BIOS may differ from those shown here.
Separate I&D logical addresses map to physical addresses by inverting address lines A16, the most significant address bit or both.The most significant address bit may be A18-A23, depending on the MECR setting. The MMU Instruction/Data Register (MMIDR) determines which lines are inverted. Please see the Rabbit 4000 Microprocessor User's Manual for more information about the MMIDR.

The following diagram (Figure 5-3) shows the physical address space when separate I&D space is enabled, SEGSIZE = 0xD3 and code is compiled to flash.

The inversion of A16 causes the root constants in the data space to be addressed in the second 64 KB block of the flash. The inversion of MSB (A19 in this example) causes the root data in the data space to be located in RAM (RAM is mapped at 0x80000), starting at 0x83000 as directed by the lower nibble of SEGSIZE.

Figure 5-3 Physical Address Space when Separate I&D Space is Enabled
and the Quadrant Size is 256 KB

When using separate I&D space you can not reference code as data or data as code in logical memory below the stack. When using separate I&D space, the processor makes a distinction between fetching an instruction from memory and fetching data from memory. The RAM segment register determines the window in RAM where root code may be executed.

Embedded applications that do not need more code or data space do not require any changes for separate I&D space. By default, Dynamic C compiles without separate I&D space enabled.

5.3.1 Enable Separate I&D Space

To use separate I&D space, check the enable separate I&D space option on the Compiler tab of the Options | Project Options dialog. The Dynamic C command line compiler equivalent is -id+ (enable I&D space) and -id- (disable I&D space). Please see the Dynamic C User's Manual for more information about the command line compiler.

The BIOS and the compiler handle the memory mappings so the user does not need to know the details. However, if you want to change the way an interrupt vector is handled or you need to write a flash driver, the rest of this chapter provides you with the necessary information.

5.3.2 Separate I&D Space Mappings in Dynamic C

The next two subsections show the default MMU settings that Dynamic C uses when separate I&D space is enabled.

5.3.2.1 Compiling to RAM

For RAM compiles, all banks (quadrants) are mapped to RAM. In a 20-bit physical address space (i.e., 1 MB physical address space), a 512 KB memory would be mapped with the lower 256 KB mapped to banks 0 and 2. The higher 256 KB are mapped to banks 1 and 3. In this configuration, A16 is inverted to provide access to the constants and data starting at the 64K boundary. The standard configuration is to set the SEGSIZE register to 0xDD so that the base segment occupies the entire 52 KB region up to the stack segment. Note that this configuration causes the DATASEG register to be irrelevant.

The BIOS sets the MMIDR to 0x21. Bit 5 of this register enables the instruction/data split and bit 0 causes the inversion of A16.

Figure 5-4 RAM Compile Memory Mapping

5.3.2.2 Compiling to Flash

For flash compiles, flash is mapped to banks 0 and 1. The address range depends on the size of the physical address space. For example, a 20-bit address space with 512 KB of flash would mean that flash is mapped from 0x00000 to 0x7FFFF. Alternatively, a 22-bit address space (1 MB quadrants) with 1 MB of flash would mean that the flash is mapped to 0x000000 to 0x0FFFFF in bank 0 and is repeated again in bank 1 from 0x100000 to 0x1FFFFF. RAM is mapped to banks 2 and 3 (address range 0x80000 to 0xFFFFF for 20 bit, and 0x200000 to 0x3FFFFF for 24 bit, respectively).

Figure 5-5 Flash Compile Memory Mapping

The BIOS sets the MMIDR to 0x29 to enable the I&D space for flash compilation. Bit 5 of this register enables the I&D split, bit 0 enables inversion of A16 for the data space base segment (i.e., the logical address space for constants) and bit 3 enables inversion of MSB for the data space data segment (i.e., the logical address space for root data).

5.3.3 Customizing Interrupts

No special code is required to customize interrupts using separate I&D space on the Rabbit 4000 with the addition of the RAM segment register (RAMSR). Use SetVectIntern() and SetVectExtern() to set interrupts. Please see the Dynamic C Function Reference Manual for more information on these functions.

5.4 How The Compiler Compiles to Memory

The compiler generates code for root code, root constants, extended code, extended constants, and far constants. It allocates space for data variables, but, except for constants, does not generate data to be stored in memory. Any initialization of RAM variables must be accomplished by code since the compiler is not present when the program starts in the field. (Please see #GLOBAL_INIT in the Dynamic C User's Manual.)

Static variables are not zeroed out by default.The BIOS macro ZERO_OUT_STATIC_DATA may be set to "1" which will only zero out static variables on board power-up or reset. Zeroing out static variables is not compatible with the use of "protected" variables because they will be zeroed out along with the rest of the static data.

5.4.1 Placement of Code in Memory

Code may be placed in either extended memory or root memory. Functions execute at the same speed, but calls to functions in root memory are slightly more efficient than calls to functions in extended memory.

In all but the smallest programs, most of the code is compiled to extended memory. Root constants share the memory space needed for root code (when separate I&D space is disabled), so as the memory needed for root constants increases, the amount of code that can be stored in root memory decreases and code must be moved to extended memory.

Please see the Dynamic C User's Manual regarding the compiler directive #memmap for more information about controlling the placement of code in memory.

5.4.2 Paged Access in Extended Memory

The code in extended memory executes in the 8 KB window from 0xE000 to 0xFFFF. This 8 KB window uses paged access. Instructions that use 16-bit addressing can jump within the page and also outside of the page to the remainder of the 64 KB logical space. Special instructions, particularly LCALL, LJP, and LRET, are used to access code outside of the 8 KB window for addresses below 0x100000. Similarly, LLCALL, LLJP, and LLRET can be used to access code outside of the 8KB window to any place in the physical address space. When one of these transfer-of-control instructions is executed, both the address and the view through the 8 KB window change, allowing transfer to any instruction in the physical memory space. The 12-bit LXPC register controls which of two consecutive 4 KB pages the 8 KB window aligns with (there are 256 pages in a 1 MB physical address space). The 16-bit PC controls the address of the instruction, usually in the region 0xE000 to 0xFFFF. The advantage of paged access is that most instructions continue to use 16-bit addressing. Only when a page change is needed does a physical address transfer of control need to be made.

As the compiler compiles code for the extended code window, it checks to see if the code has passed the midpoint of the window or 0xF000. When the code passes 0xF000, the compiler generates code to slide the window down by 4 KB so that the code at F000+x becomes resident at 0xE000+x. This automatic paging results in the code being divided into segments that are typically 4 KB long, but which can be very short or as long as 8 KB. Transfer of control within each segment can be accomplished by 16-bit addressing. Between segments, physical addressing (19- to 24-bit depending on configuration) is required. Assembly blocks are limited to 4 KB because the compiler cannot generate automatic paging code in assembly.

5.5 Memory Planning

Design conventions for memory configuration of a Rabbit 4000-based system specify flash and SRAM.

Table 5-3 Typical Interface Between the Rabbit 4000 and Memory
Primary Flash
SRAM
Secondary Flash
/CS0, /OE0 and /WE0
/CS1, /OE1 and /WE1
/CS2, /OE0 and /WE0

5.5.1 Flash

Code is typically stored in flash memory, so the size of code must be anticipated. Usually code size up to 1 MB is handled by one or two flash memory chips. If you are writing a program from scratch, remember that 1 MB of code is equivalent to 50,000 to 100,000 C statements, and such a large program can take years to write. If you are using Dynamic C libraries, it is fairly easy to have this much code in your application.

Constant data tables can be conveniently placed in extended memory using the xdata and xstring declarations supported by Dynamic C, so the amount of space needed for constant data can be added to the amount of space needed for code.The far keyword can also be used to create constants in xmem using standard C variables.

5.5.2 Static RAM

C programs vary in how much RAM will be required and having more RAM is necessary for debugging. Since debugging and program testing generally operate more powerfully and faster when sufficient RAM is available to hold the program and data, most controllers based on the Rabbit 4000 use a dual footprint for RAM that can accommodate 128K x 8 or 512K x 8, which are both in 32-pin packages. The base RAM is interfaced to /CS1 and /WE1, and /OE1.

RAM is required for the following items:


Rabbit 4000
Designer's Handbook
<< Previous | Index | Next>> rabbit.com