avrforth is a 16-bit subroutine threaded forth kernel for atmel's avr series of microcontrollers. Current development is done for the at90can128 (my cansynth board, to be exact), but it will run on most any mega device with minimal adjustments.
avrforth borrows some ideas from Terry Loveall's 4word. It is a colorless colorforth. The interpreter only interprets. Words must be compiled explicitly using the ] operator. Numeric input is handled by $, which parses the next word as a hexidecimal number.
avrforth uses null-terminated strings internally against tradition. I may switch to counted strings if they prove easier to deal with.
avrforth supports using the entire 128k instruction address space of the atmega128 and at90can128 for code.
avrforth has an interactive interpreter. It interprets input from the uart and compiles directly to flash. avrforth does not require separate memory to store program tokens.
avrforth has an integrated assembler. Assembly code words can be added without recompiling the kernel.
avrforth is public domain.
You need a host forth system to assemble avrforth. Development is done with gforth. You also need a utility to program the flash and a terminal program to communicate with the kernel through the avr's uart. I use avrdude and picocom for those tasks.
a quick run through...
Now you can send more program code or type commands interactively at the console.
Documentation has been pretty sparse but is getting better. Email me if there is anything in particular you need to know about.
Support for atmega328, atmega88p, atmega168p, and atmega328p.
Actually use the config options when declaring the interpreter stack.
Support for atmega640, atmega1280, and atmega2560. The full flash space isn't fully supported on the atmega2560 yet.
Update usart driver to use indexedname. Support usart2 and usart3.
Generate an error if the usart specified in config.f doesn't exist for the selected device.
Update gpio driver to support porth, portj, portk, and portl.
Update timer driver to support timer4 and timer5.
Initialize prescaler in twi
.
Add config options for interpreter stack sizes.
Specify the amount of high flash used for i!
separately for each device.
Use $ for hex literals.
Rename status register bits to avoid clashes with existing forth words.
Support 22 bit addresses in absolute mode instructions (call,
and jmp,
).
New words xt>r
and r>xt
access the return address.
These are equivalent to >r
and r>
for most devices,
but the atmega2560 has 3 byte return addresses.
Add latest
to the dictionary.
Make memory usage information more accurate.
Generate an error if a memory range is exceeded.
Don't write output files if an error is generated.
Support for at90usb647 and at90usb1287.
Driver for device mode USB controller.
Vim syntax highlighting description.
Support for interrupt serivice routines in forth. Use the words
int:
and int;
instead of :
and ;
to define a word and store it to a ram vector
provided by one of the peripheral drivers.
Support for (optional) separate interrupt stacks. This feature avoids having to make all task stacks large enough for the task and interrupt code. Configuration of stack sizes is in config.f.
task-dequeue
added to remove a task from the task
queue.
-!
added to complement +!
.
New drivers for spi and external memory which are more comprehensive than the previous versions.
Additional factoring in the assembler.
New a/d driver which is more comprehensive than the old version.
Make task initization easier -- task-init
now takes
the size of return and data stacks as parameters instead of the
actual pointer addresses.
Use create-file
instead of open-file
in
the assembler to open files for writing.
Add predecrement memory access words: c@-
,
@-
, c!-
, and !-
.
Predecrement and postincrement words that write to memory now take the
address on the top of stack like !
. They previously took
the data on the top of stack.
Make send.f work for gforth versions < 0.6.9-20070604.
Added support for atmega48, atmega88, and atmega168. avrforth now runs on the arduino.
Added timer driver.
Added idump
debugging word.
Made ;;
a macro (bugfix).
Fall back to the proper unoptimized versions of set
and clear
if there are no literals (bugfix).
Use ram addresses instead of io addresses for atmega32 register definitions.
New gpio driver which simply creates constants for all pinx
,
ddrx
, and portx
words.
Added autoincrement memory words: c@+
, @+
,
c!+
, and !+
. debug.f depends on c@+
,
which wasn't included previously.
New forth implementation of the 'send' shell script to send source files via the serial port. This version waits for avrforth to send a newline before sending the next line of source. The previous version simply waited a constant amount of time.
Support for at90can32 and at90can64.
Allow atmega8 and atmega32 to assemble again.
Turnkey action: the xt stored in the eeprom variable it
will be executed at startup.
Bugfix for prescaler setting in timer initialization.
Support for atmega16 and atmega162.
New word single
stops all tasks except the interpreter.
Added 2*
and 2/
words to core.f. They were
originally just macros.
Started debug.f, which contains dump
for inspecting memory.
Made location of gforth configurable in the makefile.
Support for atmega128.
Added u*/mod
and u*/
.
Initial versions of extended precision arithmetic and linear interpolation wordsets.
avrforth has been rewritten to use my own forth style assembler, which is included under asm/. Presently, only the at90can128 has been tested -- support for other devices will be added back eventually.
Renamed bit operations on
and off
to
set
and clear
. Added byte flag words on
and off
with the usual meaning.
Added words to control external memory. xmem
enables external
memory and bank
selects the current bank. Current support
assumes 128k of sram and maps it from $8000 to $ffff in 4 banks. Different
configurations can be handled by modifying the source.
Updated atmega8 defines.
Initial twi driver.
Smaller and faster implementation of $
.
New words, mainly double cell: tuck
, -rot
,
2@
, 2!
, 2drop
, 2dup
,
2swap
, 2over
, d+
, and d-
.
Updated atmega32 support.
Fixed a bug with conditional assembly that prevented usart initialization from occurring if usart0 was selected.
Ensured that the can driver is only included for the at90can128.
mobtx
, mobrx
, and mobrxb
now clear
status bits before enabling the mob.
spix
calls pause
while waiting for spi transfer to complete.
Switched back to round robin cooperative multitasking.
ec@
and ec!
support eeprom byte access.
evar
allocates variables in eeprom.
ticks
returns system tick counter.
var
now requires the length of variable to allocate.
rot
no longer reverses the second stack item (bugfix).
Initial can driver.
The usart driver is now interrupt driven. The sizes of the tx and rx circular buffers can be set in config.asm.
avrforth has switched to a state machine type multitasking. There is now
a periodic timer interrupt to run tasks. run
and stop
add and remove tasks from the active list.
>int
and int>
save and restore registers
for use in interrupt service routines.
initial drivers for the spi and a/d converter.
added assembler.
added within
to core wordset.
added on
and off
to set and clear bits.
Literals are optimized to sbi and cbi instructions.
supported multiple usarts.
moved target specific defines to config.asm.
cmove
, cmove>
, and fill
added.
pop
renamed to ones
to avoid confusion with the
stack operation.
key
and emit
now use vectored i/o. 'key
and 'emit
are the respective vectors. rx
and tx
interface with the usart and are the default values for these vectors.
;
, then
, and the various if
s are now macros.
h.
and b.
are new words for hex output that use
#
and digit
as factors.
pop
calculates population count (number of ones).
ntz
calculates number of trailing zeros.
f@
, f!
fetch and store condition codes.
0?
tests the TOS, like ?
used to.
?
now compares the TOS with a literal.
c@
, @
, c!
, and !
now
optimize literals.
Added some double cell words: dinvert
, d1+
,
dnegate
, and extend
.
High level multiplication: *
and u*
.
High level division: m/mod
, /mod
, /
,
mod
, */mod
, */
, u/mod
,
u/
, and umod
. Fixed bug in um/mod
.
Large input values are now handled correctly.
Support for counted loops: for
, next
, and
-next
. The index is stored on the return stack.
Made words
a high level word. Added macros
and a common factor words'
.
true
and false
affect the condition codes
for a future if
.
i!
now only performs an erase cycle if a bit needs to change
from 0 to 1; saves flash cycles.
Added high level register definitions for the at90can128. My main avrforth development board is the cansynth.
?dup
which removes a preceding drop
or compiles a dup
if the previous word was not a
drop
.
?lit
. or
, and
,
-
, and +
now have macros which produce optimized
code when preceded by a literal.
jump
now uses a list of addresses since calls are
no longer always two words due to the rcall optimization.
."
which prevented it from working with
odd-length strings.
go
which was reseting the stack pointers
after each line of input.
??
, which
performs a nondestructive comparision (much like ?
is a nondestructive test). added support for the atmega16. the compiler
now uses relative addressing instructions if they will reach
(rcall and rjmp).um/mod
,
um/mod2
, and m/mod
. moved usart words
to a separate driver source file.."
, um*
,
m*
, and *
. Also changed over a few more
i/o instructions to use the optimizing macros..db
with an odd number of bytes.jump
implements jump tables, and wait
waits for a bit flag
deferring with pause until the flag is set. also changed a few calls
to rcalls.+
, -
, and
, and
or
are optimized for literals in the kernel. the next
step is to add macros to use the optimizations in compiled
code. cells
, icells
, and ecells
have been removed. since you already need to keep track of which
memory space you're using on the avr, remembering to add
in a 2*
is not such a big deal.taskinit
initializes a task
stack frame. taskqueue
puts a task in the round robin queue.
pause
defers execution to other tasks. key
and emit
now call pause
when blocking.if
and then
high level words. added -if
.
if
and -if
are non-destuctive now (they branch based on
cpu flags and don't consume the top stack item). added atmega8 as
supported target. added rshift
and lshift
.e!
, edp
, ~edp
, ehere
,
eallot
, e,
, and ecells
. also added mark
and
empty
to save/restore interpreter state.2*
, 2/
, 1+
, and 1-
are now macros. added
negate
.find
, accept
, i!
, and others rewritten as high level wordsitype
and x"
fixeddp
and idp
back in ramdp
and idp
put in registers