C Forth for Teensy 3.1
Since the article below, work on C Forth has proceeded, and the latest C Forth can be found in Mitch Bradley's repository. My repository linked below is much older.
For people using 64-bit Linux as builder, I've added 32-bit dependencies in the article below. Thanks to Oliver Večerník.
C Forth is an implementation of Forth by Mitch Bradley, optimised for embedded use in semi-constrained systems such as System-on-Chip processors. See git.
The Teensy 3.1 is a Freescale MK20DX256 ARM Cortex-M4 with a Nuvoton MINI54 ARM Cortex-M0 management controller. Paul Stoffregen maintains a build environment, which can be used with or without an IDE. See git.
An initial build of C Forth, without removing unnecessary features, used 51 kB out of the available 256 kB FLASH. It requires UART0 at 115200 baud. Source is available in git.
The Teensy 3.1 modules were purchased from OSH Park, but are also available from Sparkfun and Little Bird Electronics.
(You don't need to do this to use C Forth, but it helps to know how in case you wish to extend C Forth.)
sudo apt install gcc-arm-none-eabi binutils-arm-none-eabi git
sudo apt install lib32gcc-4.8-dev libc6-dev-i386
git clone -b arm-teensy3 https://github.com/quozl/cforth.git
cd cforth/build/arm-teensy3 make
Once loaded into the program Flash, C Forth is running whenever the module is powered. Without any prior configuration, C Forth will display the system prompt "ok" on the serial port or via USB serial.
Attach the Teensy 3.1 via USB, and run a terminal emulator. The baud rate is 115200 baud. For instance, use the Screen program on Linux:
screen /dev/ttyACM0 115200Press enter. The "ok" prompt should appear.
okOr, connect a 3.3V serial adapter to Teensy pins RX1 (0) and TX1 (1). C Forth sends output to both TX1 and USB ACM, and accepts input from both RX1 and USB ACM.
First, set the port as an output:
ok #1 #13 m!This pushes the decimal number one to the stack, then pushes the decimal number thirteen, then calls the predefined m! (mode store) word which is the equivalent of the Arduino pinMode function. Both numbers are consumed from the stack, nothing is left on it.
Now, turn on the port:
ok #1 #13 p!This pushes the decimal number one to the stack, then pushes the decimal number thirteen, then calls the predefined p! (pin store) word which is the equivalent of the Arduino digitalWrite function. Nothing is left on the stack.
Now, turn it off:
ok #0 #13 p!Notice how #1 is used to turn it on, and #0 is used to turn it off, but that #13 is used each time.
|m!||( mode pin# -- )||mode store, set the mode of a pin,|
zero is input, one is output, two is input with pullup
|p!||( value pin# -- )||pin store, set the digital state of a pin,|
zero is low, one is high
|p@||( pin# -- value )||pin at, read the digital state of a pin,|
|a@||( pin# -- value )||analog at, read the analog value of an analog pin,|
(but check the pinout; digital pin 14 is analog pin 0)
|.||( value -- )||print, remove the top of stack and display the value in the current base.|
C Forth runs the instructions as soon as you press enter. But how to write a program?
ok : setup #1 #13 m! ; ok : thing #1 #13 p! #100 ms #0 #13 p! #400 ms ; ok : blink setup begin thing key? until ;This creates in the temporary dictionary three new words:
|ms||( n -- )||delay for n milliseconds,|
|us||( n -- )||delay for n microseconds,|
|key?||( -- true|false )||report on the stack whether a key is pressed,|
|begin||( -- )||mark the start of a loop structure,|
|until||( flag -- )||if the flag on stack is false, repeat the loop,|
At any time you can ask C Forth to show you the meaning of a word:
ok decimal see thing : thing #1 #13 p! #100 ms #0 #13 p! #400 ms ; okC Forth starts up in hexadecimal base for displaying or entering numbers. The word decimal is used to switch to decimal.
|#n||( -- n)||push a decimal number,|
|$n||( -- n)||push a hexadecimal number,|
|%n||( -- n)||push a binary number,|
|n||( -- n)||push a number in the current base,|
|decimal||( -- )||set the current base to decimal,|
|hex||( -- )||set the current base to hexadecimal,|
|binary||( -- )||set the current base to hexadecimal,|
Working with the temporary dictionary can be very quick and efficient. But the temporary dictionary is lost when the power turns off. To make a permanent, non-volatile program, read below.
ok nv : setup #1 #13 m! ; ok nv : thing #1 #13 p! #100 ms #0 #13 p! #400 ms ; ok nv : blink setup begin thing key? until ; ok nv blink
|nv||( -- )||add a line to the non-volatile buffer,|
|nv-undo||( -- )||remove the last line from the non-volatile buffer,|
|.nv||( -- )||display the non-volatile buffer,|
|nv-wipe||( -- )||empty the non-volatile buffer,|
The non-volatile buffer is run on power up. Now, when the power is lost and regained, the module will begin blinking the LED immediately. Serial is no longer required.
If pin 13 is grounded, C Forth will not run the non-volatile buffer. You can use this to recover from a mistake that would otherwise prevent further use.
The size of the non-volatile buffer is limited to 2048 bytes, and there is much more room in the Program Flash memory, so for larger programs it is easier to extend C Forth. The non-volatile buffer also has limited endurance, and is harder to edit, so for best results, extend C Forth.
To have your program run on boot, add it to the Forth word app, in the same file.