PFAVR -- An ANS Forth Implementation for the Atmel
AVR
Andrew Sterian
Padnos School of Engineering
Grand Valley State University
Introduction
PFAVR is a 16-bit implementation of the Forth programming language
for Atmel AVR microcontrollers. 13Kwords of FLASH and 32Kbytes of
external RAM
are required, thus the ATmega64 and ATmega128 are really the only
devices supported as of this writing.
The main features of this package are as follows.
- PFAVR enables quick prototyping and interactive control of the
Atmel AVR
- PFAVR 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.
- PFAVR fits into less than 13Kwords of FLASH and less than
32Kbytes of RAM
- PFAVR is written entirely in C
thus can easily be extended or embedded with custom code.
- PFAVR is free, licensed under the terms of the GNU General Public License.
You can download the latest version of PFAVR from:
http://claymore.engineer.gvsu.edu/~steriana/Software
Requirements
If you will not be recompiling PFAVR from source, then you don't need
anything. You can just download one of the provided HEX files in the misc/ directory to your target
system and start using PFAVR right away. The provided HEX files
have the following attributes:
- They were designed for the ATmega128 processor with at least 32K
of
external RAM with one wait-state. Other AVR's may work too if they have
at least 13Kwords of FLASH and 32Kbytes of external RAM.
- They use the USART1 peripheral for asynchronous serial
communication at 9600 baud, 8 data bits, 1 stop bit, no parity. The
different
HEX files have file names that encode the clock frequency they were
designed for:
- pfavr.3.68MHz.hex
assumes a 3.68 MHz clock frequency. The UBRR register is set to 23.
- pfavr.8MHz.hex
assumes an 8 MHz clock frequency. The UBRR register is set to 51.
- pfavr.16MHz.hex
assumes a 16 MHz clock frequency. The UBRR register is set to 103.
- Two USART1 interrupts are used. The reset vector is programmed to
start PFAVR upon reset.
- The first 13Kwords of flash program memory and 32Kbytes of
external RAM are used.
If you want anything else other than what is described above, you will
have to recompile PFAVR from source.
One final note: PFAVR can be configured to reset the watchdog of the
AVR (if so programmed by the fuse bits).
Note, however, that this feature has not been tested.
Communicating with PFAVR
PFAVR uses either the USART0 or USART1 peripheral on the AVR for
communication with XON/XOFF flow control. The default baud rate is 9600
baud, no parity, 8 data bits, 1 stop bit at an external clock frequency
of 3.68 MHz (the maximum frequency on the Atmel STK500 development
system). You can change these
parameters by editing the config.h
file in the top-level directory and recompiling.
If you want to communicate with PFAVR using a different peripheral, you
will have to provide your own driver.
Terminal Parameters
Depending upon the settings of your serial port and the communication
program you use, you may observe strange output from PFAVR, or not see
any of the characters you type. In addition to fiddling with the
settings of your communication program, you can configure PFAVR's
behavior with respect to character echo and linefeeds.
PFAVR has an internal variable named ECHO that comprises 5 flag bits.
You can print the current value of ECHO as follows:
echo ?
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).
- When bit 0 is set, PFAVR will echo each character as it is
received.
- When bit 1 is set, PFAVR will echo each complete line after ENTER
is pressed.
- When bit 2 is set, PFAVR 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
set).
- When bit 3 is set, PFAVR will not print "OK" when waiting for
user
input
- When bit 4 is set, PFAVR will automatically send a carriage
return
character ('\r') before sending a linefeed character ('\n'),
regardless of the value of bit 0.
The default value of the ECHO variable in PFAVR 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 PFAVR (all at 9600 baud,
8
data bits, 1 stop bit, no parity).
This is a popular free terminal program
for Linux. Settings compatible with PFAVR 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 PFAVR 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 PFAVR 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 HEX files distributed with PFAVR 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 PFAVR.
Writing a new Communication Driver
The interface to PFAVR 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
driver:
- output() writes a
single character to the host
- isinput() returns
non-zero if a character from the host is available (does not return the
character)
- input() returns -1
if
no characters are available from the host, else the character is
returned in the lower byte
- sio_init()
initializes the communication driver
- sio_cleanup()
terminates the communication driver
For more information on the built-in serial I/O driver, see the Serial Driver section of the
documentation.
Debugging
PFAVR comes with only one mechanism to support debugging, a trace
facility. This facility works as follows:
- PFAVR 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
As an example, try the following.
: test ." Hi Mom!" ;
test
1 trace-level ! See some trace info
test
2 trace-level ! See deeper trace info
test
3 trace-level ! See even deeper
test
2 trace-flags ! Show instruction pointer chains
test
0 trace-level ! Back to no tracing
test
1 trace-stack ! Display stack at every prompt
2 3 4 5
0 trace-stack ! Do not display stack at every prompt
The Forth SEE word, useful for "decompiling" Forth words, is not a part
of PFAVR, 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 PFAVR, as it makes
use of features like local variables that are not supported by PFAVR.
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 PFAVR.
Compiling PFAVR
If the pre-built HEX files are not suitable for you (see the Requirements section above), then you will
need to compile PFAVR from source. If you do so, please send me an e-mail
and let me know what target system you used and attach your HEX file so
that it can be made available for others.
PFAVR can be extended with your own C code or Forth code. Read the Extending PFAVR section of the
documentation.
Note that I've only compiled PFAVR on a Linux system. Compiling
PFAVR
using WinAVR tools under Windows should be possible.
To compile PFAVR from source you will need:
- a complete installation of the GNU
Development Chain for the AVR.
You need to have the BINUTILS, GCC, and GDB components installed, even
if you don't use all of them yourself.
- The AVR-LIBC
C library
- The SimulAVR
simulator. NOTE:
This
simulator (as of this writing) does not support external RAM. The
program has to be patched to fool it into believing the target device
has about 64K of RAM (even if you only have 32K). This is easily
accomplished by editing the
SimulAVR src/devsupp.c
file and editing the size.sram
field of the DevSuppDefn
structure for the target device (at about line 319...for now) to read
64*1024 instead of 4*1024. After recompiling SimulAVR, it seems
to work, but there are no guarantees that this patch won't break
something.
- Python version 2.2 or later
- GNU make
Compilation requires at least the following steps:
- Edit the config.mk
file to set compilation options.
- Edit the config.h
file to set program options.
- Edit the src/crt0.s
file to set program start-up options such as number of wait states in
external RAM, bus-keeper circuits, etc.
- Start the patched SimulAVR program as a GDB server (e.g., 'simulavr -g -d atmega128 &')
- Type 'make' and hope
for the best.
- Optionally type 'make
analyze' to see how much of each memory section you are using.
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
new parameters.
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).
Typing "make download" will invoke AVRDUDE (if installed and configured
in config.mk) to download
pfavr.hex to your target
system.
TargetSystems
PFAVR has been known to work on the following systems. Please e-mail me if you
get PFAVR working on other systems.
- Atmel STK500/STK501 development system, ATmega128, CY7C1019B-15
128K
external SRAM soldered to STK501
What Next?
It depends. Do you know Forth? If not, now is a good time to learn.
Download one of the pre-built HEX files in the misc/
directory to your target system (assuming your target system meets the Requirements listed above). Once the program
has started, you should see a short message:
PFAVR 1.0
indicating the program name and version number. Type the following and
press ENTER:
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 PFAVR might be useful on an
AVR. Type in the following:
7 TCCR0 C!
The line above set the TCCR0 register to 7, enabling
Timer/Counter Register 0 (on the ATmega128 at least) with a count
frequency of Fclk/1024. Now type the following:
:
delay71ms TCNT0 c@ OCR0 c! 2 TIFR c!
begin
TIFR c@ 2 and
until
;
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 PFAVR. You have defined a new function (word) called 'delay71ms'.
Now just type 'delay71ms'.
If you are superhuman, you may have noticed a 71ms delay (assuming your
AVR is clocked at 3.68 MHz).
Let's put this delay in a loop to make it more pronounced. Type the
following:
: delay1s 14 0 do delay71ms loop ;
Replace 14 with 31 for an 8 MHz clock frequency, and with 61 for
a 16 MHz clock frequency.
Now type 'delay1s'. You
should observe an approximate delay of 1 second (again, assuming your
AVR is clocked at 3.68 MHz).
Let's make our delay function more useful by allowing it to take a
parameter, the number of seconds to delay:
: delay 14 * 0 do delay71ms loop ;
Try the following:
1
delay
2
delay
5
delay
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 AVR
hardware now. No more edit-compile-link-download cycles just to
manipulate a few registers.
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
of links.
A good starting point, including the
Forth FAQ.
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
This is an editable Wiki of many
Forth resources
Copyright & License
Copyright © 2003-2004 Andrew Sterian.
All Rights Reserved. mailto: steriana@claymore.engineer.gvsu.edu
PFAVR 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.
Credits
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 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. Thanks to the open-source community
of AVR freaks for coming up
with AVR-GCC, AVR-LIBC, SimulAVR, AVRDUDE, and lots of other great
resources for AVR development. 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.
History
Version 1.2 -- February 28, 2004
- Worked around a GCC crash when the pre-built dictionary was not
an even number of bytes, thus causing misalignment in the text section.
The tools/doprebuild.py script was modified to always generate an
even-aligned pre-built dictionary. Thanks to Chuck Swiger for helping
with this bug.
Version 1.1 -- October 23, 2003
- Updates to documentation on extending PFAVR
Version 1.0 -- October 16, 2003
© 2003-2004, Copyright by Andrew Sterian;
All Rights Reserved. mailto: steriana@claymore.engineer.gvsu.edu