Loading Your Program Into Memory
This chapter describes:
- How to use the flash-backed shadowed RAM memory;
- How to write protect RAM so that it cannot be corrupted; and,
- How to configure your program to autostart so that it runs each time the board turns on.
In general, C programmers will be able to begin writing programs for the PDQ Board using the default settings in Mosaic IDE Plus™ for memory usage, and will not need to make any changes except for configuring a finished program to autostart, which is done using the menu option Project → Project Compiler Options. The C functions and corresponding Forth commands described here thus do not need to be used directly, and you may skip reading this page. However, understanding the issues discussed here will enable you to write fast, responsive programs to control your instrument using the PDQ Single Board Computer (SBC).
The default memory map uses flash-backed (shadowed) RAM
The default starting location for both C and Forth program code is the beginning of page 0 of shadowed RAM, starting at address 0x8000 on page 0. The C compiler locates the top level main
program at this starting address, then compiles other application code on the remainder of page 0 and on subsequent pages of flash-shadowed RAM. For Forth programmers, the recommended DEFAULT.MAP function invoked at the start of the Forth source code sets up a similar memory map as the source code is compiled by the QED-Forth interpreter/compiler.
The Mosaic IDE Plus™ (Integrated Development Environment) does most of the work for you in configuring your C-language application program to load properly under the QED-Forth operating system. The Mosaic IDE Plus generates a .dlf
download file that contains a RECEIVE.HEX command followed by an S-record image of the compiled program to the PDQ Board, followed by some additional operating system function calls that manage the shadow feature of the flash-backed RAM. The S-record encodes program data and target address and page information, plus checksums to facilitate error checking. The RECEIVE.HEX command accepts the S-record and locates its data at the specified xaddresses in the PDQ Board’s memory space. RECEIVE.HEX is smart enough to deduce the type of target memory based on the specified memory pages, and performs the storage accordingly. If the target is in shadowed RAM, the data is stored in RAM (but note that it is not saved to the backup shadow Flash chip by RECEIVE.HEX). If the target is in the Freescale 9S12 (HCS12) microcontroller's onchip Flash, it is stored there via transparent calls to the Kernel’s ToFlash() function. The download file contains commands that back up the received code to the shadow flash, and provide for it to be restored to RAM on subsequent restarts.
As detailed below, by default code in the .dlf file loaded into RAM is also saved into shadow flash and configured to re-load into RAM on restarts, and you can set an autostart vector that causes the top level program to run every time the PDQ Board resets. This behavior can be adjusted before compilation by clicking Build → Global compiler options or Project → Project compiler options in Mosaic IDE Plus, and selecting the "Embedded Settings" tab, or after loading code by typing commands to the PDQ Board from the terminal.
Let’s trace the activities stimulated by compiling a C program using the Mosaic IDE Plus; by default Mosaic IDE Plus is configured to insert SAVE.ALL into the .dlf file, and you will generally not need to type any of these commands manually. The Make process generates a .dlf download file, and we invoke the Terminal (via Tools → Mosaic Terminal) to send the file to the PDQ Board. After the RECEIVE.HEX command in the .dlf file stores the image as specified in the S-record in paged RAM, the following command in the .dlf file is executed:
SAVE.ALL
which is equivalent to:
0 0x18 STORE.PAGES 0 0x18 1 LOAD.PAGES.AT.STARTUP SAVE
This STORE.PAGES command (which is invoked by SAVE.ALL) tells the operating system to start at page 0 and store twenty four RAM pages (that is, pages 0x00 through 0x17) to shadow Flash. This command invokes the lower level operating system function called TO.XFLASH (called ToXFlash() in C) which performs the write from RAM into the shadow external Flash chip.
The LOAD.PAGES.AT.STARTUP command (which is also invoked by SAVE.ALL) tells the operating system to restore the RAM contents of pages 0 through 0x17 (using area identifier 1) from shadow Flash upon each reset or restart. To undo the effect of a LOAD.PAGES.AT.STARTUP command, simply execute UNSAVE.ALL. Alternatively, call the LOAD.PAGES.AT.STARTUP function with a valid starting page, setting the specified number of pages equal to zero, and passing in the area ID that you want to undo.
The SAVE command (which is also invoked by SAVE.ALL) saves the current memory map parameters in EEPROM; these parameters are only meaningful when the memory pointed to has been saved to shadow flash and later reloaded into RAM. Executing:
RESTORE.ALL
immediately reads the saved shadow Flash contents into RAM, and also restores the memory map pointers. The RESTORE.ALL command is equivalent to:
0 0x18 LOAD.PAGES RESTORE
RESTORE should never be executed by itself on the PDQ Board, as the restored memory map will not point to valid data without also reloading RAM from shadow flash; use RESTORE.ALL instead. However, if LOAD.PAGES.AT.STARTUP or SAVE.ALL was executed, then it should not be necessary to manually restore the memory map or RAM contents, except after a factory clean.
Complete definitions of these functions can be found in the "Interactive Debugger Glossary" section of the PDQ C Glossary document. Definitions and function prototypes of the corresponding C-callable functions can be found in the main section of the PDQ C Glossary, though calling these functions in C applications would only be necessary if you wish to store application-specific data in otherwise-unused flash pages. Because Mosaic IDE Plus places the SAVE.ALL command in the .dlf file, your application and defined Forth names (using the _Q directive) will be loaded back into RAM automatically at startup.
Write protecting the paged RAM
Keeping your compiled application code in Flash-shadowed paged RAM ensures that the contents are not lost when power is removed, but we also want the code to be safe from “errant writes” that can occur when a program crashes or invokes buggy routines. This is accomplished by “write protecting” the RAM so that it cannot be modified after it is loaded. “Write enabling” simply means undoing the protection so that the RAM can be written to. You can use the dialog box found in Build → Global compiler options or Project → Project compiler options to specify write protection of the downloaded code in the PDQ Board. This section describes the operating system functions that write protect and write enable the paged RAM; by default, write protection commands are included in the .dlf file, and normally you should not need to enter these commands manually.
There are two write protection “regions”. Region 1 comprises the sixteen pages from 0x00 through 0x0F, and region 2 comprises the eight pages from 0x10 through 0x13. Each region can be independently write protected or write enabled. The write protection functions are typically typed interactively at the terminal, although C-callable versions are available if you want to invoke them from your program. As usual for Forth commands, the input parameter is typed before the function name, and spaces separate all the entries on the command line. To write protect pages 0x00 through 0x13, you could type at the terminal prompt:
1 WRITE.PROTECT 2 WRITE.PROTECT
or, equivalently, you could execute the single short-hand Forth command:
WP.ALL
which write protects pages 0x00 through 0x13, inclusive.
Now, even if you try to overwrite the contents of pages 0x00-0x0F (region 1) or 0x10-0x13 (region 2), the original contents will remain until the write protection is removed. The LOAD.PAGES and LOAD.PAGES.AT.STARTUP functions mentioned in the prior section are smart enough to note the write protection status, write enable the RAM before restoring the RAM contents from shadow Flash, and restore the write protection status of the RAM when the processor is powered up or restarted.
To undo the write protection, simply execute the commands
1 WRITE.ENABLE 2 WRITE.ENABLE
or, equivalently, you could execute the single short-hand command:
WE.ALL
which write enables pages 0x00 through 0x13, inclusive.
C-callable versions of the two fundamental write protection configuration commands are also declared in the C:\MosaicPlus\c\libraries\include\mosaic
directory in the OPSYSTEM.h
files, with function prototypes:
void WriteProtect( int ram_region_id ); void WriteEnable( int ram_region_id );
The relevant functions are documented in the PDQ C Function Glossary (R-Z) and in the Interactive Debugger Glossary.
Autostarting your application
You can configure QED-Forth to automatically execute a specified application program after every reset, restart, and error-induced ABORT. This makes it easy to design a production instrument based on the PDQ Board; the instrument will automatically perform its required function when it is turned on or reset. The "Embedded Settings" tab, found under Build → Global compiler options or Project → Project compiler options, lets you specify the setting of the autostart vector. If you select "Set Autostart in download file" in one of the Embedded Settings boxes before compiling, you do not need to enter these commands manually.
QED-Forth provides two functions named AUTOSTART: and PRIORITY.AUTOSTART: that allow you to specify a startup routine. Both write a pattern in memory that instructs QED-Forth to execute a user-specified program. AUTOSTART: stores the pattern at the top of page 0x37 in onchip Flash inside the HCS12 processor chip, and PRIORITY.AUTOSTART: stores the pattern near the top of page 0x0F in both RAM and the shadow Flash memory. The choice of which version to use depends upon where you are locating your program code. The recommended area for compiled code is on pages 0x00-0x0F in write-protectable shadowed RAM; use of the PRIORITY.AUTOSTART: routine locates the autostart information in this same memory region. If you prefer to instruct the compiler to load code into onchip Flash, then the AUTOSTART: routine makes sense, as it locates the vector in onchip Flash.
PRIORITY.AUTOSTART:
or the top 6 bytes of page 0x37 for AUTOSTART:
) are included in the image that is loaded into production boards. The convenient utility function DUMP.AUTOSTARTS can help you to accomplish this; see its entry in the Interactive Debugger Glossary.
Let’s assume that you want to want to run the top level main
routine every time you turn on, reset, or restart the PDQ Board. The following command:
AUTOSTART: MAIN↓
writes a pattern into onchip Flash at addresses 0xBFFA-BFFF on page 0x37 comprising a 16-bit flag (equal to 0x1357) followed by the 32-bit extended code field address (xcfa) of the specified startup program. All subsequent resets and restarts will call the specified application program after QED-Forth initializes the system.
To specify the startup vector so that it can eventually reside in write-protectable shadowed RAM, we would execute a different command:
PRIORITY.AUTOSTART: MAIN↓
which writes a pattern starting at 0xBFFA on page 0x0F comprising a 16-bit flag (equal to 0x1357) followed by the 32-bit xcfa of the specified startup program. All subsequent resets and restarts will call the specified application program after QED-Forth initializes the system.
The priority autostart and autostart locations are checked each time QED-Forth executes ABORT, which is called after every reset, COLD or WARM restart, or error. ABORT first checks the priority autostart location at 0xBFFA\37, and if 0x1357 is stored there it executes the program whose xcfa is stored in the next four bytes. If the priority autostart pattern is not present, or if the specified priority startup program finishes executing and “returns”, ABORT then checks the autostart pattern at 0xBFFA\0F. If 0x1357 is stored there it executes the program whose 32-bit xcfa is stored in the next four bytes starting at 0xBFFC\0F.
To remove the autostart pattern or patterns, execute:
NO.AUTOSTART↓
This command clears all of the startup patterns in onchip flash, RAM and shadow flash.
Program loading and memory configuration summary
As described above, when programming in C it is generally not necessary to enter any of these commands manually. Forth programmers will however need to be familiar with these commands/words when writing an application for production use. It is easy to invoke functions that automatically restore your program from shadow flash into the paged RAM at startup, to write protect your code so it can’t be corrupted by a processor crash, and to configure the PDQ Board to automatically run your top level program each time the controller is powered up or restarted. The following functions are callable from Forth (either interactively from the terminal or from a compiled Forth program), and most are callable from your compiled C program:
Interactive (Forth) Functions | C Functions |
---|---|
STORE.PAGES | StorePages() |
LOAD.PAGES | LoadPages() |
LOAD.PAGES.AT.STARTUP | LoadPagesAtStartup() |
SAVE SAVE.ALL RESTORE RESTORE.ALL | |
WRITE.PROTECT WP.ALL | WriteProtect() |
WRITE.ENABLE WE.ALL | WriteEnable() |
PRIORITY.AUTOSTART: AUTOSTART: | |
IS.AUTOSTART | IsAutostart() |
IS.PRIORITY.AUTOSTART | IsPriorityAutostart() |
NO.AUTOSTART | NoAutostart() |
The following table presents a brief summary of these functions and their uses, including including examples of C syntax and Forth syntax and comments. Don’t forget to type spaces between the parameters and before and after function names when typing Forth commands. Consult the C Glossary for detailed descriptions of the functions. The Forth function descriptions can be found in the Interactive Debugger section of the C Glossary, and the C function descriptions are located in the main section of the C Glossary.
For a complete listing of operating system configuration commands, browse through the entire Interactive Debugger Glossary, or equivalently, see the functions listed in the Operating System category of the Forth Glossary.
Shadow Flash, Write Protection, and Autostarting Configuration Functions | |
---|---|
Forth Function Name C Function Name | Example of use and comments |
Store from RAM into Shadow Flash now: | |
STORE.PAGES StorePages() | Interactive Forth: 0 0x18 STORE.PAGES Compiled C: StorePages( 0, 0x18); Moves the contents of 0x18 pages starting at page 0 from RAM to shadow flash. Returns –1 flag if successful. See also SAVE.ALL |
Load into RAM from shadow Flash now: | |
LOAD.PAGES LoadPages() | Interactive Forth: 0 0x18 LOAD.PAGES Compiled C: LoadPages( 0, 0x18); Moves the contents of 0x18 pages starting at page 0 from shadow flash to RAM. Works even if the RAM is write-protected. See also RESTORE.ALL |
Load into RAM from shadow Flash at each power up or restart: | |
LOAD.PAGES.AT.STARTUP LoadPagesAtStartup() | Interactive Forth: 0 0x18 1 LOAD.PAGES.AT.STARTUP Compiled C: LoadPagesAtStartup( 0, 0x18, 1); Defines restoration behavior at each subsequent reset or COLD restart for area ID 1: Moves the contents of 0x18 pages starting at page 0 from shadow flash to RAM. Works even if the RAM is write-protected. See also SAVE.ALL. By default Mosaic IDE Plus is configured in menu Build → Global Compiler Options to insert SAVE.ALL into the .dlf file, which internally executes LOAD.PAGES.AT.STARTUP, so you will not need to type this command manually. |
Save and restore a set of memory map pointers: | |
SAVE | Interactive Forth: SAVE Saves the operating system memory pointers in reserved eeprom. Generally this command should never be used; instead see SAVE.ALL |
RESTORE | Interactive Forth: RESTORE Restores the memory pointers to values they had when SAVE was executed. Generally this command should never be used; instead see RESTORE.ALL |
Copy from RAM into shadow Flash now, load into RAM from shadow Flash at each power up or restart, and save the memory map pointers: | |
SAVE.ALL | Interactive Forth: SAVE.ALL Invokes STORE.PAGES, LOAD.PAGES.AT.STARTUP, and SAVE to back up pages 0x00 through 0x17 inclusive to the shadow Flash, and automatically causes the RAM contents and memory map to be restored upon each power-up or COLD restart. Returns flag =-1 if successful. By default Mosaic IDE Plus is configured in menu Build → Global Compiler Options to insert SAVE.ALL into the .dlf file, so you will not need to type this command manually. |
Restore from shadow Flash to RAM now, and restore to the memory map pointers: | |
RESTORE.ALL | Interactive Forth: RESTORE.ALL Invokes LOAD.PAGES to restore RAM pages 0x00 - 0x17 from shadow Flash, and calls RESTORE to revert to the memory map that existed when SAVE or SAVE.ALL was called. |
Write protect or write enable paged RAM: | |
WRITE.PROTECT WriteProtect() | Interactive Forth: 1 WRITE.PROTECT Compiled C: WriteProtect(1); Disallows writes to RAM pages 0x00-0x0F (WP region 1). Passing a 2 disallows writes to pages 0x10-13 (region 2). By default Mosaic IDE Plus is configured in menu Build → Global Compiler Options to insert 1 WRITE.PROTECT and 2 WRITE.PROTECT into the .dlf file, so you will not need to type this command manually. |
WP.ALL | Interactive Forth: WP.ALL Disallows writes to RAM pages 0x00-0x13 (WP regions 1 and 2). By default Mosaic IDE Plus is configured in menu Build → Global Compiler Options to insert 1 WRITE.PROTECT and 2 WRITE.PROTECT into the .dlf file, so you will not need to type this command manually. |
WRITE.ENABLE WriteEnable() | Interactive Forth: 1 WRITE.ENABLE Compiled C: WriteEnable( 1); Allows writes to RAM pages 0x00-0x0F (WP region 1). Passing a 2 allows writes to pages 0x10-13 (region 2). |
WE.ALL | Interactive Forth: WE.ALL Allows writes to RAM pages 0x00-0x13 (WP regions 1 and 2). |
Automatically run a specified program at each power up or restart: | |
PRIORITY.AUTOSTART: | Interactive Forth: PRIORITY.AUTOSTART: main Automatically runs main (execution address 0x8000 on page 0) on each subsequent power up, restart, or abort. The autostart vector is stored at 7FFA-7FFF on page 0x0F. |
IS.PRIORITY.AUTOSTART IsPriorityAutostart() | Interactive Forth: CFA.FOR main IS.PRIORITY.AUTOSTART Compiled C: IsPriorityAutostart( COMMON_XADDR( main ) ); Automatically runs main (execution address 0x8000 on page 0) on each subsequent power up, restart, or abort. The autostart vector is stored at 7FFA-7FFF on page 0x0F. If you select "Set Autostart in download file" in Mosaic IDE Plus menu Project → Project Compiler Options before compiling, you do not need to include this function call in your code nor enter the corresponding Forth command manually. |
AUTOSTART: | Interactive Forth: AUTOSTART: main Automatically runs main (execution address 0x8000 on page 0) on each subsequent power up, restart, or abort. The autostart vector is stored at 7FFA-7FFF on page 0x37. |
IS.AUTOSTART IsAutostart() | Interactive Forth: CFA.FOR main IS.AUTOSTART Compiled C: IsAutostart( COMMON_XADDR( main ) ); Automatically runs main (execution address 0x8000 on page 0) on each subsequent power up, restart, or abort. The autostart vector is stored at 7FFA-7FFF on page 0x37. If you select "Set Autostart in download file" in Mosaic IDE Plus menu Project → Project Compiler Options before compiling, you do not need to include this function call in your code nor enter the corresponding Forth command manually. |
NO.AUTOSTART NoAutostart() | Interactive Forth: NO.AUTOSTART Compiled C: NoAutostart( ); Erases the priority autostart vectors at 7FFA-7FFF on page 0x0F RAM and shadow flash and erases the autostart vector at 7FFA-7FFF on page 0x37. |
See also → Storing and Accessing Data in Paged RAM and Flash