for the SAM7.
I have written a version of forth for the atmel SAM7 ARM based micro-controller.
2007 February 2'nd,
This project is continued at Nerdipedia
I am a design chauvinist. I believe
that good design is magical and not to be lightly tinkered with. The
difference between a great design and a lousy one is in the meshing
of the thousand details that either fit or don't, and the spirit of
the passionate intellect that has tied them together, or tried.
That's why programming---or buying software---on the basis of "lists
of features" is a doomed and misguided effort. The features can
be thrown together, as in a garbage can, or carefully laid together
and interwoven in elegant unification, as in APL, or the Forth
language, or the game of chess.
-- Ted Nelson
The history of EMForth
EMForth and ARM.
Every processor I've ported forth too has been different from every other. ARM has some unique characteristics I had to work with or around. It is pretty much impossible to foresee all the pit falls so my style is to jump in and see how it goes.
All in all the ARM runs forth fairly well. My high level forth compiles to machine code and my comments may not be relevant to indirect threaded compilers.
One of the difference between the ARM
and most processors I've used in the lack of a regular subroutine
call instruction. The ARM has several ways to call a subroutine
but these don't automatically push a return address onto a return
stack. If fact the ARM doesn't have a dedicated return stack. By
convention (which I stick to) a return stack is implemented using
register R13 but it doesn't have to be done that way.
The ARM is the only CPU I've “forthed”
that doesn't have and absolute jump or call instruction. You can
use absolute addresses but only with multi words instruction
sequences. The lack of absolute calls wrecked some ideas I had for
compiling rom-able code but also made code relocation pretty easy.
As usual my forth can build new versions of itself. In all cases
I've compiled the new version into higher memory and then
relocated it to where I want it. This is pretty easy on the ARM –
some absolute links and literals have to be patched up but the
main body of code will run in either location. The code will run
when moved to flash, you can't use the variables but you can run
it well enough the do the initialization.
Thumb and ARM.
The SAM7 has two different instruction sets. It has the regular 32 bit set and also a reduced 16 bit set which is called the “thumb” mode. I started out using the thumb mode but after getting a 16 bit kernel working decided I really needed to use the 32 bit mode. The main problem was I still ended up needing 32 bits to perform a call so most of the code size reduction I'd hope for wasn't possible. I may have given up to early and 16 bit calls may have been possible but my experiments indicated otherwise.
I am running forth on a olimex header pcb http://www.olimex.com/dev/sam7-h256.html. I also have the sam7-64 version. I bought these online from Dontronics and have found the service there to be quite good. I contacted olimex directly before Don had these in stock and found the response to be very terse. I made a logic to rs232 converter myself using a max202 type chip. Don also sells pre-made converters – both logic level to rs232 and logical level to USB. I use SAM7 com port one for coms not port zero – the reason is port one has power to drive the max202 available on the same connector. The board is powered via the USB cable.
I use the build in SAMBA boot loader to upload my firmware via the USB port. The PC side software can be download from the atmel web site. I have had some serious PC crashes and hard drive corruption which seems to be triggered by unplugging and replugging the USB cable too quickly after enabling SAMBA on the SAM7. I don't know if this is a problem on other PCs. To be safe wait five or ten seconds before replugging the cable.
This is the first forth I've done
without cross compiling from another forth based computer. I used
the assembler in WinARM to write a tiny forth like kernel.
I was surprised how little machine code I needed. With “AND” “+” and “–“ predefined I could fudge all the logical operators I needed – the high level definitions for words like “OR” will run very slowly but still fast enough to get the job done.
The only low level conditional code I
needed was [IF] – this is used not only by “IF”
but also “WHILE” and “REPEAT” constructs.
The kernel is derived from startup code
found in WinARM and still bears the same name.
Mature emforth systems use a dedicated serial server to interface to the PC but these early versions just use line delays to allow the micro to keep up and respond. I'm using a 80 millisecond delay. This is crude and slow but even so the 32 bit kernel can rebuild itself in just over four minutes. The bootstrap kernel to 32 bit kernel takes just over six. Crude as it is I think its neat to be able to rebuild forth using nothing more than windows hyperterminal and one text file.
The file needed to build a 32 bit arm
mode system is from the thumb kernel is here.
Just dump this into a newly booted bootstrap kernel (38.4 Kbaud
with line delays) and 6ish minutes later a new kernel should
be sitting in ARM ram. The command MIRROR64K can be used to write
this to flash so it boots on the next reset. I do not recommend
you use this kernel for anything too serious because I have better
A bunch of absolute addressed get patched and we finish off by compiling the words needed to write the image to flash.
At the end of this we have a new 32 bit forth but this doesn't include an assembler yet. This is not a complete system but is complete enough to rebuild itself again and this is an important milestone.
ARM 32 EMForth release one.
My first release of ARM forth consists
of two binaries and one source file.
Release1.bin is the one most people will want.
Rebuild1.for is the source file to rebuild a new system. I don't think too many people will want to hack the kernel but the possibility is there. For those with the know how you can see how every bit of the system works.
This is a work in progress there is still a lot to do.
EMForth is not an ANSI forth. It
started out as CMforth written by chuck Moore the inventor of
forth and was customized however I wanted it. One notable
difference is I don't use “ACCEPT” or “EXPECT”
I use “GETLINE” instead. I may try to make it more
standard later on.
A mature Emforth has client/server serial protocol, multiple dictionary threads, memory management, file management and object extensions. None of this will happen any time soon. I would also like to use the USB for coms instead of the serial port but this looks like a lot of work.
There are currently no interrupts or exception handlers.
There is also no support for thumb
If you managed to get it running. It
will flash and come up with this prompt.
The default number base is 16 – ie hex.
Now type VLIST – it must be upper case – and the vocabulary will be displayed.
To hex dump memory.
> RAM 100 DUMP
HERE . prints the address of the free
There are a lot of ways to crash it.
One common one is the do something like this -
To my micros