Using Paged Memory
The GNU C compiler, RTOS, and your C language programs easily address the
HCS12/9S12 MCU's RAM and Flash memory pages
The memory map of the PDQ Board is described here, including;
- the types of available memory (Flash, RAM, and EEPROM),
- how different regions of memory are devoted to different uses,
- where the GNU C compiler allocates memory,
- how paged memory works, and,
- how to access paged memory from C language programs.
Understanding these issues will help you to write highly effective programs within the PDQ Board's RTOS for your instrument control and automation applications.
The PDQ Board’s memory map
The Freescale 9S12 (HCS12) microcontroller has a native address space of 64 Kbytes, but it can address up to 1 megabyte of memory implemented as 64 pages of 16 Kbyte each. The PDQ Single Board Computer (SBC) includes a variety of convenient memory types, including:
- sector-programmable Flash on the processor chip (onchip Flash),
- byte-programmable nonvolatile EEPROM,
- paged RAM backed up by an onboard Flash chip (shadowed RAM), and
- common RAM that is available regardless of the current page for variable storage, buffers and stacks.
Part of the common RAM is on the processor chip (onchip RAM), and the rest is implemented by an external RAM chip on the board. The memory and memory-mapped hardware on the PDQ Board fills the processor’s 1 Mbyte memory space, so there is no external memory bus brought out. However, if you need more memory you can simply plug in a Compact Flash Wildcard module to add 512 Mbytes or more of removable mass memory.
Flash memory is nonvolatile, so it retains its contents even when power is removed. Simple write-cycles do not modify the Flash memory contents, so program code stored in Flash is safe even if the processor gets lost and overwrites memory. Flash memory is also re-programmable, and the Flash programming functions are present in the PDQ Board’s onboard software library. Flash is ideal for storing compiled program code.
Code can also be compiled into paged RAM and saved to a shadow Flash device. Much as your desktop PC loads pre-compiled code from the hard drive into RAM each time you turn it on, you can configure the PDQ Board to load specified pages from the shadow Flash into paged RAM upon each power-up, reset or restart. The RAM has fast access time and can support full speed program execution, while the slower external shadow Flash provides nonvolatile storage of the contents when power is removed. Designated page regions (pages 0x00-0F
and/or pages 0x10-13
) of this shadowed RAM can be automatically write protected after the contents are loaded from the shadow Flash, so that an unexpected processor crash can not corrupt the RAM contents. Like Flash, write-protected shadowed RAM is an ideal place to store a compiled application program. Regions of shadowed RAM that are not needed for code storage can be dedicated to the storage of arrays of volatile data.
The PDQ Board includes 512K onchip Flash memory, 14K onchip RAM, 1K onchip EEPROM (384 bytes usable by application), and 496K off-chip RAM with Flash backup. Code can be located in the write-protectable Flash-backed RAM or the onchip Flash. Some memory is reserved for use by the Kernel (operating system), and the remaining memory is available for use by your application program.
The above figure illustrates the memory map. The processor’s native address space is only 64K, so a paging architecture is used to expand the addressable memory to 1 Mbyte. “Common memory” is accessible from any page, and “paged memory” comprises sixty four 16K pages located at addresses 0x8000
to 0xBFFF
on pages 0x00
through 0x3F
. The current page is specified by the contents of the processor’s PPAGE register, also called the PAGE_LATCH. As shown in the figure, the top 16K of the memory space is reserved for the common Kernel Flash and used for the RTOS. The bottom 32K of the memory space is common memory that is accessible regardless of the page, and comprises the 1K processor registers, 1K of common EEPROM (384 bytes usable by application), 14K of internal (onchip) common RAM, and 16K of external common RAM. The application program can use 10K of common onchip RAM at 0x0800-0x0FFF
and 0x2000-0x3FFF
, plus the 16K of common RAM at 0x4000-0x7FFF
.
The HCS12 processor chip contains 4 Kbytes of EEPROM at 0x0000-0x0FFF
, but fully 3 Kbytes are hidden by higher priority onchip resources (1K of registers at 0x0000-0x3FF
and 2K of onchip RAM at 0x0800-0x0FFF
). The kernel and RTOS reserves decimal 640 bytes of EEPROM at 0x0400-0x067F
. Your application program can store calibration constants and other nonvolatile data in the remaining 384 bytes of available common EEPROM at addresses 0x680
to 0x7FF
. EEPROM can be written one to four bytes at a time using Kernel drivers declared in the memory.h
file, and the memory EEPROM contents are retained even when power is removed.
The paged memory is located in the 16 Kbyte region at addresses 0x8000-0xBFFF
. Pages 0x00
through 0x1D
(decimal page 29) are implemented as fast RAM shadowed by Flash. Of these pages, pages 0x00
through 0x13
can be optionally write-protected in two regions: pages 0x00-0F
(region 1), and pages 0x10-13
(region 2), so they are ideal for code and non-volatile data. If these pages are not needed for program code, they can be left as write-enabled RAM and used for volatile data storage. Pages 0x14
through 0x1D
cannot be write-protected, so they are best used for volatile data storage. The kernel reserves page 0x1D
: the top portion from 0x9C00
to 0xBFFF
holds system arrays and buffers, and the bottom portion from 0x8000
to 0x9BFF
is allocated for code and names definitions that can be used for interactive debugging after a COLD restart. The real time operating system (RTOS) implements a heap memory manager and FORTH_ARRAY operators at pages 0x18–0x1C that make it easy to take advantage of this 80K of contiguous RAM for volatile data storage.
After a COLD restart, the operating system sets DP to 0x8000
and NP to 0x9000
on page 0x1D
so that short interactive debugging routines can be compiled in this out of the way location. The COLD restart also initializes an 80K heap to fill pages 0x18
to 0x1C
; this heap is useable by either Forth or C.
Forth programmers using the recommended DEFAULT.MAP will compile code (pointed to by dictionary pointer DP) starting at page 0x00
, and names (pointed to by names pointer NP) starting at page 0x10
. The Forth DEFAULT.MAP function initializes the variable pointer VP to 0x2000
, and leaves the heap occupying pages 0x18-1C
.
Pages 0x20
through 0x37
provide 384K of onchip Flash inside the HCS12 processor chip that is available for application code and pre-compiled libraries. It is typically used for pre-compiled device driver libraries, graphics images, and other non-volatile data objects, but it can also be used for compiled C application code. Pages 0x38
through 0x3F
hold the QED-Forth real-time operating system in write-protected onchip Flash.
To recap, the PDQ Board uses a paged memory system to expand the processor’s native 64 Kbyte address space to 1 Megabyte of addressable memory. The top 16 Kbytes at addresses 0xC000-0xFFFF
access the common kernel, and the bottom 32 Kbytes at addresses 0x0000-0x7FFF
access the common registers, EEPROM, and common RAM. These common memory areas always visible (i.e., accessible using standard 16-bit addresses) to any code running, no matter where it resides in the memory space. The remaining 16 Kbytes of the address space at addresses 0x8000
to 0xBFFF
is duplicated 64 times and addressed through the processor’s 16-bit address bus augmented by a 6-bit page address. Together the address and a padded-out version of the page are held in a 32-bit data type, an xaddress, which is described in more detail in Using Paged Memory below.
Memory allocation
The Mosaic IDE Plus intelligently allocates memory. C source code is compiled into paged memory, and allowed to span across many pages. The PPAGE register is seamlessly managed in the background so that you don't need to worry about it. The only limit is that the code compiled from any one C file cannot be larger than one 16K page. Variables are treated differently, and need to be addressed in common (unpaged) memory. The default memory map is very generous, giving ample space for variables and code.
Kernel versus application memory space
Table 5-1 details the partitioning of the onboard memory between the operating system (the Kernel) and your application functions. Of the 1 MB+ of memory on the PDQ Board, the RTOS/kernel reserves 128K of onchip flash, 4K of common RAM, 8K of paged RAM, and 640 bytes of EEPROM. The remaining memory is available for the application program and its data.
Partition of Flash and RAM among Kernel (RTOS) and Application Functions | ||||
---|---|---|---|---|
Function | Size | Memory Page | Memory Address | Physical Location |
Kernel RAM (12K) | ||||
Kernel stacks, buffers, task area | 4K | common | 1000 – 1FFF | HCS12 Processor Chip |
Kernel hash array, buffers | 8K | 1D | A000 – BFFF | PDQ Board RAM |
Kernel EEPROM (640 bytes) | ||||
Kernel vectors and structures | 640 b | common | 0400 – 067F | HCS12 Processor Chip |
Processor Registers (1K) | ||||
Kernel/HCS12 Hardware Registers | 1K | common | 0000 – 03FF | HCS12 Processor Chip |
Kernel Flash (128K) | ||||
Common Kernel Code | 16K | common | C000 – FFFF | HCS12 Processor Chip |
Kernel Code | 112K | 38 – 3E | 8000 – BFFF | HCS12 Processor Chip |
Application RAM (26K) | ||||
Application data and task areas8 | 2K | common | 0800 – 0FFF | HCS12 Processor Chip |
Application data and task areas | 8K | common | 2000 – 3FFF | HCS12 Processor Chip |
Application data | 16K | common | 4000 – 7FFF | PDQ Board RAM |
Application Non-Write-Protectable Shadowed RAM (144K) | ||||
Driver library RAM9 and/or Heap area for FORTH_ARRAYs | 144K | 14 – 1C | 8000 – BFFF | PDQ Board RAM backed by PDQ Board Flash |
Application paged RAM or Default Forth DP & NP after COLD restart | 8K | 1D | 8000 – 9FFF | PDQ Board RAM backed by PDQ Board Flash |
Application Write-Protectable Shadowed RAM (320K) | ||||
Application code and data (Write protect region 1 = pages 00–0F) (Write protect region 2 = pages 10–13) | 320K | 00 – 13 | 8000 – BFFF | PDQ Board RAM backed by PDQ Board Flash |
Application EEPROM (384 bytes) | ||||
EEPROM Variables | 384 b | common | 0680 – 07FF | HCS12 Processor Chip |
Application Flash (384K) | ||||
Application code, device drivers | 384K | 20 – 37 | 8000 – BFFF | HCS12 Processor Chip |
Shadow Flash (480K) | ||||
Transparently backs-up RAM | 480K | 00 – 1D | 8000 – BFFF | 512K onboard Flash chip |
- All pages and addresses are hexadecimal numbers; all numbers in the size column are decimal. 1K=1024 bytes.
- The unused page
0x1E
is unpopulated and not uniquely decoded; application programs must not write to it. - Page
0x1F
is reserved for address-mapped logic including Wildcard I/O. Application programs should not directly access it; rather, the built-in device drivers in the kernel access on-board address-mapped hardware. - The top 8K on page
0x1D
is reserved for kernel use. C programs may use the bottom 8K on page 1D at addresses0x8000-9FFF
if there is no need to access the QED-Forth interactive debugging functions located there. - Application programs may reside in Write-protectable Flash-shadowed RAM at pages
0x00-0F
and0x10-13
, corresponding to write protect regions 1 and 2 respectively. Non-write-protected shadowed RAM may be used for paged storage of data by C or Forth programs. To use the “write protect” feature, see the glossary entries for WRITE.PROTECT, WRITE.ENABLE, WP.ALL, and WE.ALL in the Interactive Debugging section of the Glossary. - To use the “shadow” feature, see the glossary entries for STORE.PAGES, LOAD.PAGES.AT.STARTUP, SAVE.ALL and RESTORE.ALL in the Interactive Debugging section of the C Glossary.
- Task areas should be preferentially located in onchip RAM; the C compiler performs this allocation automatically in Mosaic IDE Plus revisions 1500+.
- Starting with Mosaic IDE Plus revision 1525, the common RAM region at 0x800-0xFFF is used for the EXTRA_TASK macro, and is used internally by the Ether/Wifi Wildcard driver in
Ether_C_Task_Setup()
andWIFI_C_TASK_SETUP()
. - Some driver software libraries for external hardware use specific RAM pages as buffer space.
The Compact Flash Wildcard and USB-Drive Wildcard use page 0x17. The Ether/WiFi Wildcards use the bottom half of page 0x16. INIT_DEFAULT_HEAP() places the Forth heap (for Forth arrays) in pages 0x18–0x1C. The _flashconfig nonvolatile storage region for theSAVE_…_ARRAY()
macros is located on page 0x14.
Common memory
The common memory which is accessible regardless of the page is also partitioned between the operating system and application program. The following table presents a summary of the common memory addresses used by the operating system, and in bold type those addresses available to the application program.
Partition of the Common Memory | |||
---|---|---|---|
Address | Size (bytes) | Type | Function |
C000 – FFFF | 16K | Onchip Flash | Common Kernel – code |
4000 – 7FFF | 16K | Board RAM | Application – Variables* |
2000 – 3FFF | 8K | Onchip RAM | Application – Variables, buffers, task areas |
1000 – 1FFF | 4K | Onchip RAM | Kernel – Variables, buffers, Forth task area, stacks |
0800 – 0FFF | 2K | OnchipRAM | Application – one task area declared with EXTRA_TASK |
0680 – 07FF | 384 bytes | EEPROM | Application – Nonvolatile data storage |
0400 – 067F | 640 bytes | EEPROM | Kernel – Interrupt vectors, save/restore values, segment management |
0000 – 03FF | 1K | Registers | Kernel – Processor control registers |
* Highlighted entries indicate memory available for application programs. |
Referring to Table 5-2, there are four unencumbered common memory areas totaling 26 Kbytes of RAM and 384 bytes of EEPROM that your application can use. The C compiler automatically allocates TASK areas, buffers, C arrays and variables in the 24K of common RAM above 0x2000, and you can designate one task as EXTRA_TASK (instead of TASK) in Mosaic IDE Plus revisions greater than 1500 to place it in the 2K of common RAM starting at 0x800. You may also define EEPROM variables that are allocated to the user-available EEPROM area as explained later in this Chapter.
Forth programmers typically start their program with the DEFAULT.MAP declaration that initializes the VP (variable pointer) at 0x2000
to take advantage of the common RAM, and the EEP (EEPROM pointer) at 0x0680
to take advantage of available EEPROM.
Available common memory areas
0x0400
– 0x07FF
. Locations 0x0400
– 0x067F
are reserved by the operating system for use by the interrupt vectors, SAVE and RESTORE utilities, and for segment management data structures. EEPROM at 0x0680
– 0x07FF
is available to your programs. The pre-coded Kernel functions StoreEEChar, StoreEEInt, StoreEELong, StoreEEFloat, and ToEEPROM declared in the memory.h
header file can store data into the EEPROM. Fetching data from EEPROM uses standard read cycles and does not require the use of special functions.
0x0800 – 0x0FFF and 0x2000 – 0x3FFF: The processor’s 14K of onchip RAM extends from 0x0800
to 0x3FFF
, and the kernel reserves a 4K block at 0x1000
. The remaining 10K of onchip RAM available for the application program comprises the 2K block at 0x0800-0FFF
and the 8K block at 0x2000-0x3FFF
. This onchip RAM is ideal for task areas, program-implemented stacks, buffers, arrays, and variables. Task areas as declared by the TASK typedef (see the USER.h file
for its definition) are preferentially allocated by the C compiler in onchip RAM to optimize the timing of stack operations.
Note that the 8K block of onchip RAM at 0x2000-0x3FFF
is contiguous with the following 16K block of off-chip common RAM, resulting in a 24K block of contiguous common RAM available for your application program.
0x4000 – 0x7FFF: These 16K bytes of common RAM are also available for run-time variables, buffers and arrays. They are useable but not ideal (because of slight timing differences in HCS12 stack push/pull instructions) for implementing TASK areas and stacks.
The remainder of the common memory area is used by either the processor or the kernel/RTOS. The processor’s 1K register block is located at 0x0000
– 0x03FF
, the kernel reserves EEPROM at 0x400-0x067F
, and the operating system reserves common RAM at 0x1000-1FFF
for user areas, buffers, and stacks.
Paged memory overview
The PDQ Board uses a paged memory system to expand the processor’s native 64 Kbyte address space to 1 Megabyte of addressable memory. The 16 Kbyte page window at addresses 0x8000
to 0xBFFF
is duplicated 64 times and addressed through the processor’s 16-bit address bus augmented by a 6-bit page address. Although 6 bits are sufficient to address the 64 possible pages in the HCS12 architecture, the page is padded out to a more standard 16-bit date type so that the full address, lower 16 bits plus 16-bit page, occupies 32 bits. We’ll refer to this full address as an xaddress (32-bit extended addresses).
A subroutine on any page can fetch or store to any address on the same page or in the common memory, or transfer control to another routine in common memory. A routine in paged memory “sees” a 64K address space comprising its own page window at addresses 0x8000
to 0xBFFF
, with the common memory filling the rest of the address space. To access data stored on another page, special memory access routines located in the common Kernel Flash are used to change the page, fetch or store the data, restore the page, and return. These routines are declared in the memory.h
header file, and include functions such as FetchChar, FetchInt, FetchLong, FetchFloat, StoreChar, StoreInt, StoreLong, and StoreFloat. To move blocks of data from one location to another in paged or common RAM, use the CMoveMany, CmoveManyCheck, or ToMemory routines. To store large amounts of data in paged RAM, use FORTH_ARRAYs declared in the array.h
header file as described in Storing and Accessing Data in Paged RAM and Flash.
The operating system automatically handles function calls and returns among the pages in both the C and Forth languages. There is very little speed penalty associated with changing pages. The C compiler is configured to use the HCS12’s page-aware CALL and RTC assembly instructions for function invocation, so that functions can be called from anywhere in the paged or common memory space. For its part, the QED-Forth compiler is inherently page aware and compiles page-smart function calls wherever they are required.
See also →