TachyonESP
ESP32Forth à la Tachyon
Console and kernel enhancements for RISC-V development
This version is only for the C3 RISCV chip version !
by Peter Jakacki - September 2024 (link repaired Feb 2026)
Tachyon Forth Model *TachyonESP files*
Introduction
I have used Forth since very early in my career as a hardware/software embedded systems designer. In the last few years though I have seen the proliferation of RISC-V MCUs in all shapes and sizes, so now I want to write Forth to suit this ISA. But where to start? Perhaps the ESP32-C3 is a good start because it is a very capable MCU that is readily available that also has lots of RAM, and a Forth already available. This is important because it will allow me to develop the tools I need to hand-craft a custom machine level Forth in the style of Tachyon that I used on the P1 and P2 Propeller chips.
TachyonRV will be a "hard-core" Forth, written in assembly and extracting every ounce of RISC-V goodness that can be had so that it can run on an ESP32, or a tiny 10 cent CH32V003. The aim is to have an industrial grade Forth that can be used in commercial products just as I have done with the Propeller and other chips before them.
However, this document is mainly concerned with the enhancements and changes made to ESP32Forth to accommodate hosting the Tachyon development environment.
My Linux workspace window
FEATURES
CONSOLE
Enhanced Console supports ANSI terminal emulators
Fast Serial Batch load - echo suppressed, print line number and errors etc
History buffer uses ANSI navigation keys and allows editing ins/del etc.
ANSI support detect at boot - also sets line-width according to terminal width-10
ANSI colors
System prompts in dark blue
User input in bold yellow
Errors in bold red
Colored words list highlights colon defs, immediate, constants, variables, etc
Compact stack depth prompt
Press Enter will stay on same line with a clear --- separator between user inputs and response
STACK
Stack retention holds current values even after an error. (underflow will reset stack)
Stack print shows hex, ASCII, and decimal values in visual top to bottom stack format
AUX STACK
Simple fixed stack to complement data stack
Supports locals A B C D
PUSHA POPA pushes and pops multiple values
A@+ Fetches the long pointed to by A and increments A by 4
LOOP STACK
DO LOOP words are simple fast non-immediate runtime words and does not use the return stack
DO pushes index and limit and IP instruction pointer onto a loop stack
LOOP performs a fast increment and compare on the loop stack (as fast as FOR NEXT)
LOOP reads the stacked IP to loop (no compile-time branch needed)
Note: Only partially implemented as DO: and LOOP: at present for testing.
MEASURE
LAP timing saves previous LAP and latches current millisecond tick
.LAP calculates and reports the difference between the lap times.
NUMBER INPUT/OUTPUT
Accept % for binary
Allow passive grouping symbols such as , and _
Dedicated hex print words .L .W .B for long/word/byte
CONTROL & ANSI KEYS
Control key shortcuts - Print Stack, Clear Stack, list words, System Report, Reset, <user controls>
<ESC> clear current entry
^C Cancel and reset (bye)
^Q Query stack
^S Stack reset
^X Re-eXecute previous entry (recall + enter)
^W Words list
^L Clear screen and stack, and print boot report
^? Boot report
ANSI CSI navigation keys for editing current line or recalling previous line up to 8 levels deep (default)
UP recall previous entry
DN recall next entry
LEFT navigate into current entry (non-destructive)
RIGHT “ “
HOME Navigate to start of current line
END Navigate to end of current line
INS Toggle insert/overwrite mode
DEL Delete current entry from history
DUMP MODES
DUMP hex bytes + ASCII (16/line)
DUMPW hex words (16-bits)
DUMPL hex longs (32-bits)
DUMPA ASCII characters (64/line)
DUMPB memory blocks as a byte/block
DATA SPACE
Forth has a very primitive variable that is always one cell wide. Often the word “allot” has to be used to increase or decrease it in a rather kludgy manner. It seems to make more sense to specify the type and size of that variable as: byte bytes long longs
To allow these variables to exist in a contiguous manner rather than crammed in between Forth code, an area of 4KB is set aside and the variables are actually constants formed from the data origin pointer. The user is free to choose another area using the “org” word much as is done in assembly.
org ( addr -- )
byte bytes long longs
ALIASES
Many simple Forth symbols that are functions have been given an alias that are easier to see and read. Symbols such as dot has a PRINT alias for instance. Likewise, many operator symbols in Forth are words rather than common symbols. If Forth were consistent it would say ADD and SUBTRACT rather than + and -. But symbols are what we are familiar with for math and logic operations.
Forth | Tachyon |
. | |
.” | PRINT” |
AND | & |
OR | | |
XOR | ^ |
LSHIFT | << |
RSHIFT | >> |
constant | := |
word | stack | |
|< | ( b -- m ) | Convert bit number to bit mask |
>| | ( m -- b ) | Convert msb of bit mask to bit |
++ | ( a -- ) | Increment long |
-- | ( a -- ) | Decrement long |
~ | ( a -- ) | Clear long |
~~ | ( a -- ) | Set long |
README for ESP32Forth Enhancements
Trying to keep my readme file updated for the changes I am making to ESP32Forth which also includes EXTEND.FTH.
+------------------------------+
| ESP32forth -Tachyon |
+------------------------------+
This is ESP32forth v7.0.7.15 which is being modified to be more like Tachyon Forth so
that I can port whatever tools I need to develop Tachyon Forth for RISC-V.
* USE Espressif ESP32 V2 board manager libs *
This is being tested on an ESP32-C3 XIAO module using the older V2.0.17 Espressif ESP32 board manager libraries in Arduino 2.3.2
Note: Espressif V3 libs do not work
* Editing and compiling *
I am editing the files in VS Code and running a terminal in minicom in a separate window, although you can use the Arduino 2 IDE edit and terminal of course.
When I make a change I disengage the minicom terminal with a ^A P which brings up the coms parameter window and this permits the coms port to be used by the Arduino uploader.
Then I toggle to the Arduino window and hit ^U to compile and upload.
Once it is done I go back to the minicom window and hit escape to cancel the coms parameter window, and not the terminal is ready to use.
I set minicom to 921600 baud with zero delays and there is an EXTEND.FTH file that I am also using at present.
--------------------------------------------------------------------
NEW:
--------------------------------------------------------------------
DEBUG
* Formatted dumps such as
DUMP hex plus ASCII
DUMPW eight 16-bit words/line
DUMPL eight 32-bit longs/line
DUMPA 64 ASCII characters/line
DUMPB ( addr cnt blksiz -- ) - dump memory as a byte/block where the byte is an average
.L Print as 8 digit hex
.B print byte as 2 digit hex
.L_ print as 8 digit hex 6C00_1400
.h ( n cnt -- ) Print hex digits
LAP - capture ms-ticks into lap latch (save old lap)
.LAP - Print the timing difference between last and previous LAP
CWORDS - list words in color
plain = colon defs
red = immediate
green = constants/values
yellow = variables
magenta =
blue = unknown
.WORDS - detail one/line list of words with address etc
NUMBERS
* Add % as binary number prefix
* Allow , and _ within numbers (useful digit group separator) 1,234,567 $6000_C240 etc
* Stack freeze on errors - it won't reset the stack just because you made a mistake
* .S now prints each item on a new line from top to bottom as hex, ascii, and decimal
CONSOLE
* prompt - only displays fixed size stack depth, base symbol, and arrow. - revector via _prompt
* ANSI colors used to distinguish prompts, user, response, and errors.
* Control keys - now you can use control keys for shortcuts and even add your own at runtime
^Q Query Stack
^S Stack init
^W WORDS list
See ^ctrl in EXTEND for more options
Unused control keys are discarded (no errors)
Use your own custom ctrl keys - default is ' ^ctrls is ?ctrls
( NOTE: moving this to EXTEND for easy edits )
BATCH LOAD
ESP32 - The keyword ESP32 will place the console into non-echo mode only reflecting line numbers and errors.
- this also ensures that this source file is designed for the ESP32
*END* - ends batch mode and reports download stats.
STRUCTURES
* DO: LOOP: is a very fast do loop with its own loop stack - as fast as for next
DO: push index and limit and current IP onto loop stack
LOOP: increment index and loop with saved IP if <> limit - else unloop
I: loop stack index
AUX STACK
@A ( -- a ) - address of A in A stack
A! ( n -- ) - store n in A (top of A stack)
A ( -- n ) - top of A stack value
>A ( n -- ) - Push n onto A stack
A> ( -- n ) - Pop A stack
PUSHA ( <n> cnt -- ) - push cnt values onto the A stack
POPA ( cnt -- <n> ) - Pop cnt values from the A stack
A@+ ( -- n ) Read long from pointer in A and increment A by 4
AW@+ ( -- n ) Read 16-bit word from pointer in A and increment A by 2
B ( -- n ) - Read B = second A stack item
OPERATORS:
~ ( addr -- ) - clear the cell to zeros
~~ ( addr -- ) - set the cell to ones (-1)
++ ( addr -- ) - increment variable
-- ( addr -- ) - decrement variable
>< ( n min max -- f ) - within inclusive
MASK ( bit -- mask )
[^] - to compile the control key value of an ascii character
FUNCTIONS:
LOOKDOWN ( ch str cnt -- index+1|0 )
LOOKUP ( index str cnt -- byte )
CSIKEY ( -- keycode ) - return with ascii or compressed CSI code
HIGH ( pin -- ) - make the pin an output and set high
LOW ( pin -- ) - make the pin an output and set low
INP ( pin -- ) - make the pin an input
ON ( -- 1 )
OFF ( -- 0 )
KERNEL MODS:
Reassign HIGH and LOW as functions ( simpler and faster )
Added ON and OFF as true and false values ( very general constants )
--------------------------------------------------------------------
CHANGES:
--------------------------------------------------------------------
renamed prompt to eol because it is an end of line action
made eol and prompt revectorable within code for batch loader
renamed ?arrow. to prompt because that is what it is - also _prompt is the variable
added --- separator on the same line when the return is pressed
added stack underflow and reset check (the only time I want it to reset on an error)
add in ANSI colors and apply to console prompts etc and words list
--------------------------------------------------------------------
TO DO:
--------------------------------------------------------------------
Make ?ctrls into a user table of vectors - perhaps in EXTEND
Add escape to cancel the current accept line
Add history buffer to tib - use ^R to recall (or arrow up if CSI keys added)
Check system timer operation
Have fun!
Peter Jakacki
--------------------------------------------------------------------
NOTES:
--------------------------------------------------------------------
Linux users may use the send script from the VSCode terminal
while the minicom terminal window is still active (no need to close etc)
If your ESP32 creates an ACM0 port for instance:
./send EXTEND ACM0 3
where send is
ascii-xfr -s -n -l $3 $1.FTH > /dev/tty$2
minicom color:
Here is a script which I name as tty to easily open a minicom terminal with color etc
minicom --color=on -w -b 921600 -D /dev/tty$1
usage: ./tty ACM0