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.
Understanding these issues 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, you can optionally write protect the RAM that contains the compiled code for enhanced reliability, and you can set an autostart vector that causes the top level program to run every time the PDQ Board resets. You can accomplish these feats by typing commands to the PDQ Board from the terminal, or by clicking Project → Project compiler options, and to specifying the features you want in the "Embedded Settings" tab.
Let’s trace the activities stimulated by compiling a C program using the Mosaic IDE Plus; we’ll assume that the code is targeted to the default location in shadowed RAM on the PDQ Board. 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; a corresponding RESTORE or RESTORE.ALL command will restore the machine to the saved state. Executing RESTORE reverts to the SAVEd memory map pointers, while 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
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. C-callable versions of many of the shadow Flash management functions are also available if you want to invoke them from within your C program. The function prototypes are documented in the C:\MosaicPlus\c\libraries\include\mosaic directory in the MEMORY.h and OPSYSTEM.h files:
extern int StorePages (int basePage, int numPages); extern void LoadPagesAtStartup (int start_page, int num_pages, int area_id);
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 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.
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:
extern void __attribute__((far)) WriteProtect (int ram_region_id); extern void __attribute__((far)) WriteEnable (int ram_region_id);
The relevant functions are documented in the PDQ C Function Glossary (A-H) in the main glossary section and in the interactive debugger glossary section.
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, lets you specify the setting of the autostart vector, or you can follow the instructions in this section to accomplish the same thing.
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
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 to 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. ee also SAVE.ALL |
| Load from RAM to 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 from RAM to 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 |
| Save and restore a set of memory map pointers: | |
| SAVE | Interactive Forth: SAVESaves the operating system memory pointers in reserved eeprom. See also SAVE.ALL |
| RESTORE | Interactive Forth: RESTORERestores the memory pointers to values they had when SAVE was executed. See also RESTORE.ALL |
| Store from RAM to shadow Flash now, load from RAM to shadow Flash at each power up or restart, and save the memory map pointers: | |
| SAVE.ALL | Interactive Forth: SAVE.ALLInvokes 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. |
| Restore from shadow Flash to RAM now, and restore to the memory map pointers: | |
| RESTORE.ALL | Interactive Forth: RESTORE.ALLInvokes 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.PROTET 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). |
| WP.ALL | Interactive Forth: WP.ALLDisallows writes to RAM pages 0x00-0x13 (WP regions 1 and 2). |
| WRITE.ENABLE WriteEnable() | Interactive Forth: 1 WRITE.ENABLE Compiled C: WriteEnable( 1);Allows writes to RAM pages 0x00-0x0F (WP region 1). Ppassing a 2 allows writes to pages 0x10-13 (region 2). |
| WE.ALL | Interactive Forth: WE.ALLAllows 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: mainAutomatically 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( 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. |
| AUTOSTART: | Interactive Forth: AUTOSTART: mainAutomatically 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( 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. |
| 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
