PF11 -- An ANS Forth Implementation for the 68HC11
Padnos School of Engineering
Grand Valley State University
PF11 is a 16-bit implementation of the Forth programming language
for the Motorola 68HC11 microcontroller. The main features of this
package are as follows.
- PF11 enables quick prototyping and interactive control of the
- PF11 is 99% compliant with the ANS Forth
specification, implementing nearly all of the words in the core, extended
core, double-number, exception, programming
tools, and string word sets.
- PF11 fits into less than 28K of RAM, if desired, allowing for
experimentation (but not much development) in a 68HC11 system with only
32K of RAM
- PF11 can be programmed into ROM, which allows for more
interesting programs when combined with 32K of RAM
- PF11 can co-exist with BUFFALO in 32K of ROM, allowing
experimentation on existing BUFFALO-based hardware without giving up
- PF11 is free, licensed under the terms of the GNU General Public License.
You can download the latest version of PF11 from:
If you will not be recompiling PF11 from source, then you don't need
anything. You can just download the provided S-record files (pf11ram.s19, pf11rom.s19, or pf11buffalo.s19) to your target
system and start using PF11 right away. The provided S-record files have
the following attributes:
- pf11ram.s19 was
compiled to reside between 0x1040 and 0x7FFF in external RAM. The start
address for the program is 0x1040. This is a good file to download when
you just want to try things out and not have to program ROM/EPROM. It is
assumed that you have 32K of RAM up to 0x7FFF and that your special
function registers are located at the default address of 0x1000. Also,
it is assumed that the interrupt vectors starting at 0xFFD6 are either
in RAM/NVRAM or are vector addresses that point to a JMP instruction in
RAM (as BUFFALO does).
- pf11rom.s19 was
compiled to reside between 0x8000 to 0xB5F7 and 0xB800 to 0xFFFF in
external ROM (i.e., there is a "hole" for the 68HC11 on-chip EEPROM).
The start address is 0x8000, and this is programmed into the reset
vector at 0xFFFE. Note that this program assumes you are burning a ROM
or programming an EPROM starting at 0x8000, and that you have
32K of RAM from 0x0000 to 0x7FFF.
If you want anything else other than what is described above, you will
have to recompile PF11 from source.
- pf11buffalo.s19 is
just like pf11rom.s19 but
additionally contains BUFFALO version 3.4 programmed from 0xE000 through
0xFFFF, and the reset vector is set to point to BUFFALO. PF11 can be
started from within BUFFALO by typing 'go 8000'. As above, it is
expected that you have 32K of ROM/EPROM/EEPROM from 0x8000 to 0xFFFF and 32K of RAM
from 0x0000 to 0x7FFF.
The PF11 distribution also comes with pf11.elf, a file that can be
loaded into the GDB 68HC11 simulator where you can try PF11 without any
68HC11 hardware. Simply type (assuming you've installed the GNU
Development Chain for the 68HC11):
(gdb) target sim
(gdb) load pf11.elf
(gdb) sim cpu-config 0x0C
Note that some GDB simulator versions have bugs that prevent proper
operation of PF11. If the simulator doesn't work, you can try a
different version or just stick to actual hardware. Undefining
PF11_INTERRUPT_SIO in the top-level config.h file prior to
recompiling the source may improve things.
One final note: PF11 can be configured to reset the
computer-operating-properly (COP) watchdog of the 68HC11 (if USE_COP is
defined in config.h).
Note, however, that this feature has not been tested. The COP watchdog
can be disabled by setting the NOCOP bit (bit 2) of the CONFIG register
(location 0x103F). Remember that the CONFIG register must be programmed
as an EEPROM cell and does not reflect its new value until after reset.
Communicating with PF11
PF11 uses the SCI peripheral (serial port) on the 68HC11 for
communication with XON/XOFF flow control. The default baud rate is 9600
baud, no parity, 8 data bits, 1 stop bit. You can change these
parameters by editing the sio_init()
function in the sio.c file
in the src/ subdirectory.
If you want to communicate with PF11 using a different peripheral, you
will have to provide your own driver.
Depending upon the settings of your serial port and the communication
program you use, you may observe strange output from PF11, or not see
any of the characters you type. In addition to fiddling with the
settings of your communication program, you can configure PF11's
behavior with respect to character echo and linefeeds.
PF11 has an internal variable named ECHO that comprises 5 flag bits.
You can print the current value of ECHO as follows:
You can change the value of ECHO as follows:
23 echo !
which would set ECHO=23 (decimal), or:
hex 17 echo !
which would set ECHO=0x17 (hexadecimal).
The bits of ECHO are interpreted as follows (bit 0 is the LSB).
The default value of the ECHO variable in PF11 is 0, but the system/autoinit.ft defines an
AUTO.INIT word that sets ECHO to 21 (decimal). I've found that this
value works well with three major terminal programs, listed below along
with the settings of each that works well with PF11 (all at 9600 baud, 8
data bits, 1 stop bit, no parity).
- When bit 0 is set, PF11 will echo each character as it is
- When bit 1 is set, PF11 will echo each complete line after ENTER
- When bit 2 is set, PF11 will automatically send a linefeed
character ('\n' or hexadecimal 0x0A) after every carriage return
character ('\r' or hexadecimal 0x0D) that is echoed back (if bit 0 is
- When bit 3 is set, PF11 will not print "OK" when waiting for user
- When bit 4 is set, PF11 will automatically send a carriage return
character ('\r') before sending a linefeed character ('\n'),
regardless of the value of bit 0.
This is a popular free terminal program
for Linux. Settings compatible with PF11 are VT102 terminal emulation,
backspace key sends BS, add linefeed OFF, local echo OFF.
TeraTerm is a popular free terminal
program for Windows. Settings compatible with PF11 are newline receive
character is CR, newline transmit character is CR, no local echo.
Hyperterm is the default terminal
program that comes with Windows. Settings compatible with PF11 are
backspace sends Ctrl-H, no local echo, no send line ends with line
feeds, no append line feeds to incoming line ends.
The pre-built S19 files distributed with PF11 cause an ABORT (interrupt
program, clear the stack) when the user sends a Ctrl-C character (ASCII
0x03). This behavior can be disabled by undefining SIO_CTRL_C_ABORTS in
the top-level config.h
file and recompiling PF11.
Writing a new Communication Driver
The interface to PF11 is very clean. You will need to write the
following functions (see src/sio.h
for the prototypes) if you want to replace the existing serial I/O
For more information on the built-in serial I/O driver, see the Serial Driver section of the
- output() writes a
single character to the host
- isinput() returns
non-zero if a character from the host is available (does not return the
- input() returns -1 if
no characters are available from the host, else the character is
returned in the lower byte
initializes the communication driver
terminates the communication driver
PF11 comes with only one mechanism to support debugging, a trace
facility. This facility works as follows:
As an example, try the following.
- PF11 must have been compiled with PF_SUPPORT_TRACE enabled in the
top-level config.h file.
- The TRACE-LEVEL Forth variable is an integer indicating the
maximum depth of threading to trace
- The TRACE-STACK Forth variable causes a display of the entire
stack at every prompt when set
- The TRACE-FLAGS Forth variables contains various bits
(well...just one for now) that enable additional trace messages:
- When bit 1 is set, calls to Forth words print out the current
instruction pointer and the address to jump to
: test ." Hi Mom!" ;
The Forth SEE word, useful for "decompiling" Forth words, is not a part
of PF11, although the original pForth implementation of SEE is available
in the misc/see.ft file.
You will not be able to load this file directly into PF11, as it makes
use of features like local variables that are not supported by PF11.
1 trace-level ! See some trace info
2 trace-level ! See deeper trace info
3 trace-level ! See even deeper
2 trace-flags ! Show instruction pointer chains
0 trace-level ! Back to no tracing
1 trace-stack ! Display stack at every prompt
2 3 4 5
0 trace-stack ! Do not display stack at every prompt
Similarly, pForth comes with a word named TRACE that allows for
single-step debugging of a word. The implementation of TRACE is in misc/trace.ft, and like SEE, it
is big, complicated, and needs to be edited to work under PF11.
If none of the pre-built S19 files are suitable for you (see the Requirements section above), then you will
need to compile PF11 from source. If you do so, please send me an e-mail
and let me know what target system you used and what memory map file you
used/created so that I may maintain the list
of working target systems for others to use.
To compile PF11 from source you will need:
- a complete installation of the GNU Development Chain for the 68HC11.
You need to have the BINUTILS, GCC, and GDB components installed, even
if you don't use all of them yourself.
- Python version 2.2 or later
- GNU make
Compilation requires at least the following steps:
If you change any of the parameters in config.mk or config.h, it is safest to first
type "make clean" before typing "make" to rebuild the program with the
- Decide whether you are compiling for a RAM-based or ROM-based
- Select a memory configuration file for your target hardware.
Several are provided for you in the memory/ subdirectory.
- Edit the config.mk
file to set compilation options.
- Edit the config.h
file to set program options.
- Type 'make' and hope
for the best.
- Optionally type 'make
analyze' to see how much of each memory section you are using.
Typing "make doc" rebuilds the documentation, if necessary. Typing
"make realclean" will clean everything, including the pre-built
documentation (so you generally do not want to do this).
PF11 has been known to work on the following systems. Please e-mail me if you
get PF11 working on other systems. Memory map configuration files to
support these systems are listed in the memory/ subdirectory.
- Axiom CMM11-E1, RAM target and
It depends. Do you know Forth? If not, now is a good time to learn.
Download the pf11ram.s19
file to your target system (assuming you have 32K of RAM from 0x0000 to
0x7FFF). Once the program has started, you should see a short message:
indicating the program name and version number. Type the following and
2 3 + .
You should see the number 5 displayed, as this is the result of adding
2 and 3. Forth uses postfix notation, thus the expression '2 3 +' means "take the operands
2 and 3 then add them". The single dot is a command (known as a word in Forth) that displays the
result to the screen.
Skipping ahead a few lessons, let's see why PF11 might be useful on a
68HC11. Type in the following:
: delay32ms tcnt @ toc1 ! 128 tflg1 c!
tflg1 c@ 128 and
Make sure you get it exactly right! If you didn't, just type it again
from the first line. After the last line (with the semicolon on it) you
should get the message 'OK'
from PF11. You have defined a new function (word) called 'delay32ms'.
Now just type 'delay32ms'.
If you are superhuman, you may have noticed a 32ms delay (assuming your
68HC11 is clocked at 8 MHz).
If your session is "hung", you are probably running in the GDB
simulator, which currently doesn't seem to implement the TFLG1 register
correctly. Restart the simulator (press Ctrl-C then 'quit' to exit). Type in the
above definition for 'delay32ms'
replacing 'tflg1' with 'tflg2' and try again.
Let's put this delay in a loop to make it more pronounced. Type the
: delay1s 30 0 do delay32ms loop ;
Now type 'delay1s'. You
should observe an approximate delay of 1 second (again, assuming your
68HC11 is clocked at 8 MHz).
Let's make our delay function more useful by allowing it to take a
parameter, the number of seconds to delay:
: delay 30 * 0 do delay32ms loop ;
Try the following:
If you don't know Forth, the above is probably fairly intimidating and
you are probably thinking of just forgetting the whole thing. Don't give
up. Forth has a non-negligible learning curve but a very nice payoff.
Think about it...you have a scripting language built-in to your 68HC11
hardware now. No more edit-compile-link-download cycles just to
manipulate a few registers. BUFFALO lets you peek and poke into memory
locations, but it doesn't let you write scripts, as you did above.
Here are some links that will help you get started with Forth.
This web site has many useful Forth
links, perhaps the best of which is the on-line version of Leo Brodie's
"Starting Forth" text, an excellent introduction to the language.
As with all web rings, this is a list
A good starting point, including the
An active FIG, also the home of
Forthwrite, a Forth magazine, and an extensive library.
This is a brief but very useful
introduction to Forth
Copyright & License
Copyright © 2003 Andrew Sterian.
All Rights Reserved. mailto: email@example.com
PF11 comes with ABSOLUTELY NO WARRANTY. This is free software
licensed under the terms of the GNU General Public
License. You are welcome to redistribute this software under
certain conditions. For more details, see the previous link or visit The Free Software Foundation.
This help file is based on a template for the help file for mxTools
by M.A. Lemburg.
This software was created with VIM;
thanks to the authors of this program and special thanks for the
Python and Forth syntax support. Thanks to Stéphane Carrez for his
GCC 68HC11 tools. Thanks to the Python developers and support
community, and to the helpful people in the comp.lang.forth
newsgroup. Thanks to William Chia-Wei Cheng for his tgif drawing program.
Thanks to the Mozilla authors for
the great web browser and composer. And of course, thanks to Phil Burk,
Larry Polansky, David Rosenboom, and Darren Gibbs for writing pForth and for placing it in
the public domain.
Version 1.0 -- July 18, 2003
© 2003, Copyright by Andrew Sterian;
All Rights Reserved. mailto: firstname.lastname@example.org