Skip to content

STM8 eForth Programming Tools

Thomas edited this page Jun 26, 2021 · 23 revisions

Interacting with the console

Interacting with the STM8 eForth console typically requires a serial terminal program like e4thcom (the "official" terminal for STM8 eForth - more about that below), picocom, miniterm, cutecom... for Windows HyperTerminal or any alternative. Even a vintage 70s "dumb terminal" can be used.

The serial connection uses the UART_TX and UART_RX pins - for an STM8S that's typically PD5 and PD6 but the STM8L families use different GPIOs, some devices can do remapping, and STM8S and STM8L High Density variants offer two or more serial interface. Please refer to the descriptions in the README.md of the board and base image configuration folders.

STM8 eForth can simulate a 3-wire or a 2-wire serial connection with GPIO change- and TIM4 interrupts (see below).

It's also possible to connect an alphanumeric display and a keyboard directly - maybe a "retro computing" project tries to do that one day.

Note: at least on STM8 Low Density devices with 1KiB RAM there isn't enough space to support a disk block buffer for source code: the only source code storage in STM8 eForth is a 80 bytes line buffer, and backspace (^h) is the only editing feature. STM8 Medium and High Density devices have enough RAM to store at least one "screen buffer" (i.e. 64x16 chars, 1 KiB), and they have the potential to support a Forth file system. High Density devices offer from 32K to 96K of "far memory" Flash ROM - using some compression that's almost the equivalent of an 80s single-sided floppy disk, although the far memory would be a good fit for a linked-lists of text blocks.

Transferring Forth Code

STM8 eForth uses a serial interface (or any other character I/O device that you provide) for the interactive console. Typically, STM8 eForth source code will be stored on a host computer, and transferred to the embedded system.

This can be done with the following tools:

Tool Description Features
e4thcom The "official" STM8 eForth interactive terminal provides an STM8EF plugin (linux) #include, #require, res, \\, synchronization.
codeload.py A command line tool for non-interactive programming and automated testing #include, #require, res, \\, synchronization
simload.sh A command line tool for automated testing and code generation using uCsim #include, #require, res, \\, synchronization
ascii-xfr Picoterm standard ASCII upload plug-in with flat files, no synchronization, slow none
generic terminal most terminal programs provide a text transfer feature with line delay, no synchronization, slow none

Using e4thcom

e4thcom is a terminal program for embedded Forth systems, e.g. noForth, AmForth, and Mecrisp with a line editor, a line history, and conditional/direct source upload. X86 Linux and Raspberry Pi binaries are provided (there have been attempts to support Window10 WSL). From release v2.2.15 STM8 eForth uses the e4thcom transfer method, which is also supported by codeload.py in the tools folder.

e4thcom

When starting e4thcom from the Linux command line several parameters need to be passed, e.g. e4thcom-0.6.2/e4thcom-0.6.2 -t stm8ef -d ttyUSB0. This is simplified by an STM8 eForth Makefile target: running make term sets default parameters and starts e4thcom. A viable solution for selecting an e4thcom binary release is placing a symlink to the e4thcom binary in a folder that's in the search path (e.g. /usr/local/bin/e4thcom).

As a Forth system e4thcom interprets some user inputs from the keyboard or from a file input stream and thus adds some nifty features, some of which are currently not publicly undocumented (e.g. it can run a target system assembler). e4thcom starts in interactive mode, \ at the beginning of a line initiates the terminal control mode (\ alone closes e4thcom). #i and #r are short forms for #include and #require). These commands, followed by the name of a source file, bring the terminal into the non-interactive transfer mode.

The method endorsed by STM8 eForth relies heavily on the following e4thcom keywords:

Keyword file/interactive description
\res MCU: <file> file preload the contents <file>.efr from the mcu folder
\res export <name> file export <name> from a preloaded efr-file as a CONSTANT
\\ file treat the rest of the file as a comment (i.e. don't transfer it to the target)
#include <name> both transfer the file <name> in the search path
#require <name> both test if the word <name> is in current dictionary, otherwise transfer the file <name> in the search path
#ifdef <name> file interpret the rest of the line if the word <name> is in the dictionary
#ifndef <name> file interpret the rest of the line if the word <name> isn't in the dictionary

Here is an STM8 eForth source file example with e4thcom keywords:

#include hw/pd8544.fs \ unconditional uploading
#require ALIAS \ conditional uploading if the word ALIAS isn't in the dictionary

\res MCU: STM8S103  \ use the STM8S103.efr symbol/address file

\ get GPIO registers addresses, insert definitions like `hex 5000 CONSTANT PA_ODR`
\res export PA_ODR PA_IDR PA_DDR PA_CR1 PA_CR2

#ifndef OUT! \res export PB_ODR
#ifndef OUT! : OUT! ( f -- ) PB_ODR 4 B! ;

\\ ignore the rest
 of the file

The e4thcom conditional upload feature in #require and \res export checks for the presents of a word equal to <filename> (e.g. ]C!), and uploads the file only if it's not already in the dictionary. After successful it tests again, and creates a dummy word corresponding to the filename, if no such word is in the dictionary.

Filenames must not contain whitespace characters, and under Linux the character / (forward slash) is forbidden. Under Windows, a long list of reserved characters and filenames applies.

Source files can include (or #require) other source files.

e4thcom has a defined search path order for include files: normally the search is done in the order cwd:cwd/mcu:cwd/target:cwd/lib (cwd or . is the directory from which e4thcom was started) but this can be modified by parameters.

The author suggests the following organization for source code:

  • cwd project sources
  • cwd/lib STM8 eForth library
  • cwd/target symlink to out/<board>/target
  • cwd/mcu hardware-specific words

The folders can be created and populated by downloading a binary release and creating a symlink to out/<board>/target. The W1209 Makefile automates this (i.e. run make target).

The conditional directives #ifdef and #ifndef (new in e4thcom 0.8.5) use the same conditional feature as #require or \res export but they act on the rest of the source file line. The example above demonstrates a method to interact with the target on a level below "dictionary - source file". The main application for this feature is dealing with device variants in hardware drivers: it's possible to "negotiate" with the target system which action to take.

Please refer to the documentation provided on the e4thcom page.

Using codeload.py

The command line tool codeload.py emulates the code transfer and conditional features of e4thcom described in the last chapter but it offers some more options for automation. It can be used with the serial interface (using pySerial) and UART emulation of uCsim using telnet, and it's intended to work with the same source files, search directories, and \res MCU: ... \res export directives as e4thcom. It depends on Python3 but a Python 2.7 version is still available.

thomas@w500:~/source/stm8s/stm8ef$ tools/codeload.py  -h
usage: codeload.py [-h] [-b base] [-p port] [-r rate] [-q] [-t tracefile]
                   {serial,telnet,dryrun} [files [files ...]]

positional arguments:
  {serial,telnet,dryrun}
                        transfer method
  files                 name of one or more files to transfer

optional arguments:
  -h, --help            show this help message and exit
  -b base, --target-base base
                        target base folder, default: ./
  -p port, --port port  PORT for transfer, default: /dev/ttyUSB0,
                        localhost:10000
  -r rate, --rate rate  RATE for serial transfer, default: 9600
  -q, --quiet           don't print status messages to stdout
  -t tracefile, --trace tracefile
                        write source code (with includes) to tracefile

codeload.py is a core part of the STM8 eForth Continous Integration framework: it can be used to load main.fs or board.fs and run automated tests or install code for periphery support.

Note that codeload.py is intended to be platform independent but up to bbf69e1 the author only used it on Linux x86-64. Please file an issue if you have new test results, e.g. on MAC or Windows (negative as well as positive).

Using simload.sh

In order to support build and test automation simload.sh wraps uCsim and codeload.py.

It accepts a board name as a parameter, and performs the following actions:

  • load the board's binary file (out\<BOARD>\<BOARD>.ihx) into uCsim
  • set a breakpoint at HI and patch the communication routines to use plain UART I/O
  • transfer the Forth code in main.fs or, if not present, in <BOARD>/board.fs using codeload.py

The recommended execution environment for simload.sh is tg9541/docker-sdcc.

Using picocom and ascii-xfr

The following picocom wrapper works for full-duplex and wired-or half-duplex with implicit echo (e.g. W1209). It also sets a suitable line delay for programming Forth to NVM without handshake:

#!/bin/sh
#    "$@" --imap lfcrlf --emap crcrlf --omap delbs \
exec picocom \
    --send-cmd="ascii-xfr -s -c10 -l500" \
    "$@" --imap igncr,lfcrlf --omap delbs \
    /dev/ttyUSB0

Using a Serial Interface for 2-Wire Communication

Normally the Forth console uses the STM8 UART as a 3-wire interfaces (Rx, Tx and GND) in full-duplex mode. Alternatively STM8 eForth can be configured to "half-duplex" mode where it sends and receives through a 2-wire interface (shared Rx/TX-pin and GND).

The STM8 UART provides native support for 2-wire half-duplex, and for STM8 Low Density Devices the binary STM8S001J3 implements this interface configuration (it also works for e.g. STM8S003F3, STM8S903K3, etc).

For boards that don't offer access to UART pins the generic binary SWIMCOM can be used (for 2-wire communication PD1 on the SWIM ICP header is the default but any other GPIO that supports interrupts can be configured in globconf.inc).

The following simple wired-or interface can be used to interface an STM8 2-wire interface to a PC UART converter:


STM8 device    .      .----o serial TxD "TTL"
               .      |      (e.g. "PL2303 USB serial converter")
               .     ---
               .     / \  1N4148
               .     ---
               .      |
STM8 PD1/SWIM-->>-----*----o serial RxD "TTL"
               .
GND------------>>----------o serial GND
               .
................

Common USB interface chips are known to work well (e.g. CH340, CP2102 or PL2303). Please note that a common type of CH340 USB serial converters has a 1k5 resistor in series with the TxD signal which makes it unreliable. Refer to issue #269 for additional information.