This article is intended as a primer on using the Forth block device words to load and execute Forth source code under your programs control. This article may contain example code that can be used on other Forth systems however the examples are specific to MV4th16 Forth. The article first explains the main Forth words used to load Forth source code from the block device. Next we include examples showing how a Forth system can dynamically load and unload Forth words.
This article assumes you have MV4th16 loaded on a Parallax Propeller chip target system. For information on configuring MV4th16 to match your target system see the article Configure MV4th16 version 0.94 and Higher. You will also need the ForthTerm terminal program installed on your development system. See the article Configuring the ForthTerm terminal program for information on configuring ForthTerm for use with MV4th16.
The hello word example and the block edit example files can be downloaded here: Example source code.
There are two primary Forth words use to load source code stored in Forth block device blocks (1024 bytes). The forth word LOAD is used to load and interpret one Block of Forth source code. The forth word THRU is used to load and interpret a number of sequential blocks of forth source code.
The LOAD word:
The forth word LOAD is used to read a block of forth source code from the block device and then interpret the source code as thought it was entered at the console device. The source code loaded by the LOAD word can itself contain a Forth LOAD or THRU word. It is the programmer's responsibility to assure that at no time will block A load block B and at some point block B loads block A. This is known as a circular reference and will cause a system crash.
The data stack must be persevered after the Forth source code in the block is interpreted. If the data stack is modified from its initial state when the load began an "Invalid input state?" error will abort the Forth code being executed.
In MV4th16 the LOAD word executes the SAVE-INPUT word before loading and interpreting the Forth source code in the specified forth block. The SAVE-INPUT word is used to save information about the current input buffer being interpreted by MV4th16. When the source code in the specified Forth block has been interpreted the LOAD word calls the RESTORE-INPUT word to restore the input buffer position and buffer address to the values before the load operation began. This allows one block to load another block(s) then continue loading itself.
As an example the following forth code entered at the console would load blocks 10 and 11 one at a time, then load block 22 and finally block 19;10 LOAD 11 LOAD 22 LOAD 19 LOAD
The THRU word:
The Forth word THRU is used to read a sequence of blocks containing Forth source code from the block device and interpret each of the blocks of source code as thought it was entered at the console device.
The data stack must be persevered after the Forth source code in the last block is interpreted. If the data stack is modified from its initial state when the load of the first block began an "Invalid input state?" error will abort the Forth code being executed.
In MV4th16 the THRU word executes the SAVE-INPUT word before loading and interpreting the Forth source code in the first forth block specified. When the source code in the last specified Forth block has been interpreted the THRU word calls the RESTORE-INPUT word to restore the input buffer position and buffer address to the values before the first block load operation began. This allows one block to load other block(s) then continue loading itself. It is permissible to pass data on the data stack between loaded blocks when loading multiple blocks with the THRU word. However the data stack must be restored to its initial state at the end of the last block load operation. The BLK variable contains the current block number being loaded.
- When using the THRU word special care must be taken to assure that all Forth creation words such as VARIABLE, CONSTANT, TO, IS, CREATE... have there name parameter in the same source code block.
- Each string constant must be fully contained in a single Forth block and may not span in to the next block.
- When using the THRU word to load source code it is permissible for a complied Forth word to span across consecutive forth blocks.
As an example the following forth code entered at the console would load blocks 10 through 11, then load blocks 15 through 19;
10 11 THRU 15 19 THRU
The MARKER word:
The Forth word MARKER is used to save the state of the Forth dictionary before the marker was created in the dictionary. When the marker is invoked all Forth words and data allocations made after the marker will be removed from the Forth dictionary. The marker itself is also removed from the dictionary.
As an example the code below creates two variables then loads Forth code presumably to initialize the variables. Finally the marker is invoked to remove the code used to initialize the variables.
VARIABLE FirstVar \ variable to be set by initialization code
VARIABLE NextVar \ variable to be set by initialization code
MARKER DumpCode \ create a marker to remove code
10 22 THRU \ load the initialization code
DumpCode \ remove initialization code from Forth dictionary
There are a couple of things to keep in mind when using a marker to remove code from the dictionary;
- If the dictionary memory is used by another Propeller chip COG the other COG should be stopped before deleting any variables or memory allocations in the dictionary it may be using.
- If the dictionary memory removed by the marker contains Forth words assigned to deferred Forth words (words declared with DEFER xxxx) outside the scope of the dictionary entries being removed must be linked to other forth words before the marker is executed.
- The Forth word MARKER should not be used in a compiled Forth word.
Getting The whole Thing Going:
By default when the MV4th16 system starts up it loads and interprets the contents of Forth block number 1 on the block device. By placing your start up source code in block 1 you can initialize your system. The auto loading of block 1 is treated as a "1 LOAD" Forth statement and the source code in block 1 may contain further LOAD and THRU forth statements.
Block number 0 is reserved by MV4th16 as a comment block. Attempting to load block 0 will always fail and abort the system. You should use block 0 to comment what is on the block device.
If required the code set to auto load can be bypassed at start up of the target system. With the ForthTerm program connected to the target system reset the target system. At start up the target system will prompt as to whether the auto load feature should be used. If you press the "N" key in the terminal the system will start without loading block 1. The prompt will only remain for 2 or 3 seconds and then will default to "Y" and will auto load block 1.
MV4th16 start up auto load prompt.
Hello World Example:
In this example we will load a simple program (one Forth word) to the auto loaded block 1. After the target system boots we can execute the program at the Forth console in the ForthTerm terminal program.
First connect to your target system using ForthTerm program. After the target system boots up press the ENTER key and the Forth system should respond with "OK".
Next select the "Code Editor" tab in the ForthTerm program and enter the following Forth code into the editor;
: hello CR ." Hello world, how are you" CR ;
Next select the "Block Manager" tab in ForthTerm program. You should see one line of Forth code if you do not, go into the options dialog and select the "Block File" tab and set the "Synchronize Block File to Code Editor" options to checked. See the article Configuring the ForthTerm terminal program for more information.
In the "Block Manager" tab press the "Upload Blocks" button, the ForthTerm transfer dialog will appear allowing you to transfer the Forth source code to the target system. Because we are working with a blank target system the ForthTerm program will need to paste the block transfer software to the target system. Answer yes when prompted to upload the transfer software. When the transfer software is loaded on the target system you are ready to transfer the program we just created in the editor to the target system.
Confirm upload of transfer software to forth target system
In the "Upload Forth Blocks" dialog set the "First Block" setting to 1. Make sure the "Pad Block With Space Character" is selected and press the "Upload" button. If all went well our Hello World program is stored in block 1 and will be auto loaded when the target system resets. At this point select the "Terminal" tab in the ForthTerm program and reset the target system.
Upload block(s) to target system dialog.
Once the target system is started type the Forth word hello and press the Enter key in the terminal window. If all went well you should see;
Hello world, how are you
Congratulations you have created you first Forth program.
To illustrate how chaining load commands works lets change how our simple hello world program is loaded. We will move our program currently in block 1 in to block 2 then change block 1 Forth code to load block 2.
With the sample hello world program in the "Code Editor" select the "Block Manager" tab and press the "Upload Blocks" button. This time set the "First Block" to 2. Press the "Upload" button. If all went well our Hello World program is now stored in block 2.
Next clear the "Code Editor" and enter the following Forth code;
Jut as before select the "Block Manager" tab in the ForthTerm program and upload the block to the target system setting the "First Block" to 1. Now reset the Target system. After the system starts up type the Forth word hello and press the Enter key in the terminal window. If all went well you should see;
Hello world, how are you
This simple example shows how one source code block can load other source code blocks.
Saving Your Work:
To save the blocks stored on the target system use the "Download Block File" command in the "Communications" menu in the ForthTerm program. In the case of our simple example;
Select the "Download Block File" command. When prompted where to save the file make sure the file type is set to "Block File (*.blk)" and select a file folder and name to save the target blocks to. As with the upload command ForthTerm will transfer the download code to the target system if required.
Confirm transfer software upload to target system.
Once the download code is transferred to the target system set the "First Block" to 0 and the "Source Blocks" to 3 in the download dialog and press the "Download" button.
Download target system blocks to development system block file dialog.
If all went well the 3 blocks will be saved in to the specified block file on the development system. You can use the ForthTerm "Upload Block File" command in the "Communications" menu to restore the blocks on the target system or move them to another target Forth system.
Using Fast Find To Speed Load Time:
The Fast Find extension for MV4th16 can be used to speed up load times by a factor of 7 to 10 times. If you are using an I2C EEProm as your block device you will need to allocate a free Propeller chip COG to run the Fast Find extension. If you are using the an SD Card as the block device the COG used to access the SD Card already contains the code for the Fast Find extension and no additional COG is required. See the article Speeding Up MV4th16 Compiler Speed for more information on how Fast Find speeds up the Forth compiler.
The simplest method to load the Fast Find feature in MV4th16 is to use the Forth source code and Parallax COG binary that can be found in the "Forth\Fast Find" folder of the downloaded MV4th16 release. The Forth source code is in the file "FastFindAutoDetect.forth" and the file "FastFindAutoDetect.forth.blk" contains the source code saved as a Forth block file. The file "FastFindAutoDetect.forth.blk" is updated each time the "FastFindAutoDetect.forth" file is saved in the ForthTerm code editor. The Forth source code will require one block of storage on the target system and another block for the binary COG code. The Fast Find source code is written to not load a COG with the Fast Find binary when it detects a system using an SD Card for the block device. Instead the code will link to the code executing in the SD Card control COG.
This example assumes that there is no Forth code stored on the block device. We will store the Fast Find source code in block 2 and the binary for the COG in block 3 on the target system (any block numbers could be used). Then we will add Forth source code to block 1 to load and enable the Fast Find extension. Use the following steps to load the Fast Find extension from the block device during MV4th16 start up, it is assumed the target system is connected to the ForthTerm terminal program;
- Load the "FastFindAutoDetect.forth" file in to the ForthTerm program code editor.
- At the top of the file is the declaration for the value FF_Blk set the block number to 3, Change the line to read: #3 VALUE FF_Blk.
- Save the changes to the source code.
- Select the "Block Manager" tab in ForthTerm and press the "Upload Blocks" button, save the source code to the target system as block 2 (First Block = 2). See the "Hello World Example" above for more information on saving a source code block.
- Select the ForthTerm "Upload Block File" command in the "Communications" menu, when prompted for the file name change the file type to "Binary File" and select the "FastFind.binary" file. This time set the "First Block" to 3 and select the "Pad block with Nulls (0)" options.
- Now we just have to start Fast Find during the auto loading of block 1. Select "New" in the ForthTerm code editor. add following line; #2 LOAD FF-RUN. Select the "Block Manager" tab and upload the source to block 1.
- Reboot the target system and the Fast Find extension should be enabled.
Even though the SD Card version of MV4th16 does not require the COG binary it is best to include it on you block device. This way the block file produced by saving the target system blocks could be used on any system, whether it is using an EEProm or SD Card based block device. See the section "Saving Your Work" above for more information on saving target blocks to the development system.
Target System Block Editor:
MV4th16 has a simple block editor that can be run on the target system to edit the contents of any block on the target system. The block editor requires a terminal driver to operate. There are two terminal drivers included with MV4th16, one for the ForthTerm terminal and another for an ANSI terminal. You can use these terminal drivers as examples to create a custom terminal driver say for an ADM3 or a VT100 terminal.
The target Forth block editor is quite large and should be loaded from the block device when needed. The current block editor requires about 9 blocks for the editor and 1 block for the terminal driver Forth source code. We are using target system block 2 and 3 for Fast Find extension. We will now load the terminal driver in to block 4 and then the block editor in to blocks 5..13 on the target system.
To load the terminal driver select the ForthTerm "Upload Block File" command in the "Communications" menu, when prompted for the file name change the file type to "Block File" and select the the "ForthTerm.forth.blk" file in the folder "Forth". Now upload the Forth source code block saving the source code to block 4 on to the target system. See the "Hello World Example" above for more information on saving a source code block.
Now that we have loaded the terminal driver we will load the block editor code in to blocks 5...13 on the target system. Just repeat the steps to load the terminal driver but select the "BlockEdit.forth.blk" file and save it starting at block number 5 on the target system.
To test that the editor works select the terminal tab in ForthTerm and type the following at the Forth console; 4 13 THRU 1 edit and press the Enter key. The Forth block editor should be displayed on the terminal.
With the block editor running on the target system lets update block 1 on the target system to auto load our terminal driver and add a compiled function to load the block editor and remove it from memory when we are done editing. Use the following steps to to edit block 1;
- Press the "i" key to enter insert mode in the target system block editor.
- Add the lines listed below to the block editor.
- Press the "ESC" key and select the "S" command to update the contents of block 1, Answer "Y" to the save changes prompt.
- Press the "Q" key to exit the block editor.
- Reset the target system to auto run new Forth source code in block 1 on the target system.
The following source code should be added to block 1;
#2 LOAD FF-RUN \ start fast find extension.
#4 LOAD ft>term \ load the ForthTerm terminal driver.
\ code to execute a forth word using late binding
: exec ( cAdrName -- )
\ load block editor and after use remove from memory
: edit ( uBlkNum -- )
#5 #13 THRU \ load editor program
C" edit" exec \ find program in dictionary and run
C" unload-edit" exec ; \ execute marker to unload editor
Block editor running on target system after changes made to block 1
The Forth word "edit" is used to load the block editor and then remove the editor once editing is completed. See the article Configuring the ForthTerm terminal program for information on mapping the special keyboard keys in the ForthTerm terminal display to the control keys used by the Forth block editor code.
If we reset the target system we can now edit a block on the target system using the Forth block edit program. To invoke the block editor on the target system type x edit and press the Enter key at the console prompt where x is a number from 0 to max blocks - 1. When you exit the block editor a marker at the start of the block editor code is called to remove the editor from the Forth dictionary.
The block editor requires about 6.5K bytes of memory to load. To see how much free memory is available on the target system type UNUSED U. followed by the Enter key, this will print the number of free bytes on the target system. The free bytes is available memory shared by both the data stack and dictionary expansion.
At this point you may want to save the entire block range on target system so that you could reload this functionality on any target system. See the section "Saving Your Work:" for information on downloading the target blocks to the development system. To save the entire load image set the "First Block" to 0 and set the "Source Blocks" to 14 in the download dialog then press the "Download" button..The base install of MV4th16 contains a number of prebuilt block files that can be used to save time in getting a target system ready for use.
Before using either the upload or download dialog in ForthTerm assure that the target system is connected and responding at the console. As an example if the block editor was running on the target system you would have to stop the editor before uploading or downloading could occur.