eForth for cheap STM8S gadgets

Turn cheap modules from AliExpress into interactive development kits!

Similar projects worth following
STM8 eForth is a compact interactive Forth programming platform for STM8S and STM8L µCs. Code and binaries support many low-cost modules, e.g. the W1209 thermostat or the C0135 MODBUS relay board, and a layered build system makes it easy to add yours.

The project supports all STM8 devices, provides a library and serial interface options, uses test automation with uCsim and Docker on Travis-CI, and has e4thcom support for interactive programming.

The list of features includes Idle- and Background Tasks, interrupt handlers, I/O redirection, 7S LED or LCD drivers, analog and digital I/O, string evaluation, the VOC dictionary extension, and ALIAS for temporary dictionary entries.

STM8 eForth is based on Dr. C.H. Ting's STM8EF, an STC Forth that compiles machine code. Since the SDCC assembler and linker are used for building the Forth core, embedding it in C applications is possible. e.g. as a scripting engine.

What is it?

STM8 eForth is among the smallest user friendly Forth systems for µCs: it brings the simplicity of a 1980s style Forth to today's low-cost controllers. The project provides code for STM8 variants, board support for selected low cost targets, and docs. STM8 eForth has a long feature list but it uses very little memory. Innovative solutions, steady support, and an active community makes using it for new projects easy!

The code and binaries on GitHub can be used in many ways:

  • as an alternative firmware for Chinese commodity boards (e.g. thermostats, DCDC converters, and relay boards)
  • build embedded systems with an interactive shell (scriptable and extensible)
  • for creating smart sensors with SPI, I2C, or RS232 and a scripting shell, e.g. for RaspberryPi, Arduino, or ESP8266
  • as an interactive environment for exploring the STM8 architecture
  • for learning Forth - it's easy and fun (find out why in the text below!)
  • ...

Why a Forth for Cheap Chinese boards?

Because it's fun: cheap mass-produced imperfection is a playground for creativity :-)

The W1209 has long been my favourite target: it's a rather complete embedded control board with a UI at a very good price. It's as cheap as it looks, and the challenge is in it's imperfections: the guy who designed the board clearly didn't have a connected application in mind, and I had a lot of fun making it do things it was never intended to do.

There are challenges, like the lack of communication ports. The "sensor connector" can either be used as a a 2-wire RS232 "bus" or for sensing. If you need sensing and communication at the same time the project also provides a full-duplex 3-wire RS232 interface through the key pins (while keeping the keys functional). A plug-in system makes it easy to test new ideas, like using the "update connector" as a home brew field bus interface!

Which target boards are supported?

Besides generic targets for STM8S001, STM8S103, STM8S105, STM8S207 and STM8L051, there is currently support for the following boards:

Some more boards can be supported on request, e.g.

@Elliot Williams worked on using the ESP-14 as an IoT deviced (the ESP-14 module combines an ESP8266 with an STM8S003F3P6).

Programmable power supplies based on the XH-M188 and a cheap DC/DC converter are both work in progress. There are also several types of STM8S003F3 based voltmeters that are known to work.

Read more about possible future targets below.

Why Forth?

Again, because it's fun!

Forth starts out as a stack machine with a tiny instruction set and minimal hardware requirements. It fits in a few KiB, and the target, even a lowly µC, can even be used as the development system. The Forth stack machine is a minimalistic VM on a standard CPU, but there are also hardware implementations (e.g. for FPGAs, or a 144 core Forth processor). The VM is ideal for fast context switching and Forth easily meets hard-real-time requirements. It's no surprise that Forth was used in many NASA projects.

Consider this:

  • compared to other programming environments Forth is easy to understand fully
  • like Lisp, Forth has a REPL (Read-Evaluate-Print-Loop) which enables software testing in a way impossible with "Edit-Compile-Run-Debug" (e.g. Arduino)
  • it's easy to build Domain Specific Languages (one can literally program the compiler!)
  • the stack-oriented "factoring" method results in implicit data flow and modular code
  • Interpreter-compiler, basic OS functions fit in just 4K code :-)

A Forth programmer is in control of all levels of problem abstraction, a unique advantage in a...

Read more »

Original version of STM8EFalong with docs as received from Dr. C.H. Ting on 21/Nov/2016. The docs are worth reading, the eForth binary will run on the STM8S Discovery.

Zip Archive - 21.97 kB - 11/21/2016 at 20:13


  • 1 × ST-Link V2 ICP adapter (e.g. $2.00 from AliExpress) The ST-Link on an STM8S Discovery Board can be used, too
  • 1 × serial interface adapter /w 3.3V signal level (e.g. $0.60) e.g a USB interfacea with a CH340, or better a PL2303, chip
  • 1 × STM8S target device as listed in the GitHub Wiki (e.g. a $0.70 "STM8S103F3P6 minimal system board") e.g. "STM8S103F3P6 STM8S development board" from your favorite China source
  • 1 × Some headers, patchwires, breadboard etc (about $2.00) and other things you fancy, e.g. a RC-servo, SPI display, LEDs ...

  • STM8L051F3: Experimenting with LSE, BEEP and RTC

    Thomas10/29/2020 at 08:38 0 comments

    I made a write-up about my experiments the STM8L LSE (Low Speed External) oscillator that uses a 32.768kHz crystal to clock peripherals like the RTC.

    For my experiments I used the nrf24stm8l board that I made some time ago but a chip on a standard "green TSSOP20 breakout PCB" for $0.10 with a crystal soldered to pins 1 and 2 also works (caps were not needed when I tried it):

    The write-up gets started with the LSE and the beeper peripheral. Using the beeper is a good test for a crystal oscillator since one can hear the crystal start up! The next experiment introduces the RTC peripheral with a basic example for configuration, initialization and use.

  • A debug console in 4 lines of code

    Thomas10/25/2020 at 08:23 0 comments

    A Forth system on a $0.20 MCU like the STM8S003F3 with 8K ROM and 1K RAM can offer surprising advantages. Based on an idea I found in the ROBOFORTH II tutorial I added of just 4 lines to the latest STM8 eForth release to provide a very simple debug console that allows examining the state of a Forth program in the middle of the execution

    Here is a simple example:

    #require BYE
    : test ( n -- )
        I DUP . 2 MOD 0= IF
          CR ."  Break - mind the stack - continue with BYE" CR
          OUTER THEN
      NEXT ."  done"

    A debug session on a STM8S003F3, where a "FOR ... NEXT" loop is terminated manually by changing the loop counter on the return stack ($3FF growing down), may look like this:

    66 7 test 7 6
     Break - mind the stack - continue with BYE
    $03F0 10 dump
     3F0  23  0  0  A 8D 1E 8D 12  1 1D  0  6 8D 1E 8D 12  1_______________ ok
    bye 5 4      
     Break - mind the stack - continue with BYE
    $03F0 10 dump
     3F0  23  0  0  A 8D 1E 8D 12  1 1D  0  4 8D 1E 8D 12  1_______________ ok
    $3FA ? 4 ok
    0 $3FA ! ok  
    bye done ok
    . 66 ok

    Note that a single misspelled word will clear both the data and the return stacks. This will not only reset the console but it will terminate the program and typing BYE in this situation will crash the system! There is clearly room for improvement in the implementation of the library word BYE here.

    Edit: here is an improved version of BYE, one that will show a more friendly behavior:

    #require OUTER
    : BYE ( -- ) [
      \ exit the interpreter on the condition that OUTER was called
      $1605 ,           \ LDW Y,(5,SP)
      $905A ,           \ DECW Y
      $905A ,           \ DECW Y
      $90FE ,           \ LDW  Y,(Y)
      $90A3 , ' OUTER , \ CPW Y,#OUTER
      $2604 ,           \ JRNE +4
      $9085 ,           \ POPW Y
      $9085 ,           \ POPW Y

  • STM8 eForth 2.2.26: The STM8L Release

    Thomas10/24/2020 at 09:26 0 comments

    I released STM8 eForth 2.2.26 that adds support for all STM8S "Mainstream" and STM8L "Low Power" devices, at least that's what I assume.

    No, I didn't test all the 40 STM8S variants, 37 STM8L variants and none of the 47 STM8AF or STM8AL variants listed here. Instead I looked for evidence what's really the difference between all those devices and thus identified two-and-a-half families (STM8S, STM8L and RM0013-STM8L) with "Low", "Medium" and "High density" devices - and that amounts to just 7 STM8 configurations. The rest is specs and marketing "Product Lines". 

    Read more about this in the STM8 eForth 2.2.26 Release Notes!

  • A new STM8 eForth pre-release 2.2.26.pr3 is available

    Thomas09/27/2020 at 12:49 0 comments

    The goal of this release to improve STM8L, and to support all STM8L devices, is getting closer.

    I could need some help with testing support for STM8L High Density devices: there is test code in the repository but I don't have a board (yet). 

    So, if you have a NUCLEO-8L152R8 or a similar board with an STM8L High Density chip (e.g. the STM8L152R8 or a also a similar STM8L Medium+ Density chip) I'd be happy to hear from you.

    The GitHub issue is here.

  • OpenOCD config files for STM8L Low Density Devices

    Thomas09/25/2020 at 05:32 0 comments

    For RM0031 STM8L Low Density devices (e.g. STM8L051F3 or STM8L050J3) I'm using the following OpenOCD target configuration:

    #config script for STM8L051
    set FLASHEND 0x9FFF
    set BLOCKSIZE 0x40
    set EEPROMSTART 0x1000
    set EEPROMEND 0x10ff
    proc stm8_reset_rop {} {
       mwb 0x4800 0xaa
       mwb 0x4800 0xaa
       reset halt
    source [find target/stm8l.cfg]

    For STM8L101 family devices (i.e. STM8L101F3 or STM8L001J3) the following configuration works for me:

    #config script for STM8L101
    set FLASHEND 0x9FFF
    set BLOCKSIZE 0x40
    proc stm8_reset_rop {} {
       mwb 0x4800 0x00
       reset halt
    source [find target/stm8l.cfg]

     I didn't bother about the EEPROM because for all practical purposes the memory blocks designated as "DATA EEPROM" behave like Flash ROM.

    My OpenOCD version is "Open On-Chip Debugger 0.10.0+dev-01404-g3934483-dirty". Using OpenOCD I could reset chips such that they consequently worked with STM8FLASH.

  • STM8L001J3M3: another SOP-8 µC runs STM8 eForth

    Thomas09/22/2020 at 19:47 0 comments

    Flashing an STM8L001J3M3 never worked for me and I had given up - until debugging an STM8L101F3 with OpenOCD and stm8-gdb showed that I had been chasing a phantom.

    I figured that clearing the chip might help but that didn't work, until now: the OpenOCD STM8L example target configuration had RESET ROP (Read-Out Protection) wrong!

    EDIT: It's true that the reset routine in the STM8L152.cfg is wrong ... for the STM8L101 family, not for STM8L051 Low Density devices! A file stm8l101.cfg should simply use the stm8_clear_rop code in stm8_clear_rop and that's it.

    Fortunately, OpenOCD uses Jim, a TCL subset, for configuration and writing a new "stm8_clear_rop" was quickly done:

    #config script for STM8L101
    set FLASHEND 0x9FFF
    set BLOCKSIZE 0x40
    proc stm8_reset_rop {} {
       mwb 0x4800 0xaa
       mwb 0x4800 0xaa
       reset halt
    proc stm8_clear_rop {} {
       mwb 0x4800 0x00
       reset halt
    source [find target/stm8l.cfg]

    After typing the new command on the OpenOCD telnet console programming just worked!

    A STM8L001J3M3 is basically a STM8L101 chip in a SOP-8 package.

    The problem with this thing is that there is

    1. a fair chance to lock the chip up by setting any of the GPIOs PA0, PC3 or PC4 to output mode after reset so that PA0/SWIM no longer works
    2. UART TX is on PC3 - this obviously means "output mode"
    3. there is no NRST to back you up if you made a mistake

    The STM8L101F3 code works around this by *not* configuring PC3 to push pull -  the STM8L101F3 binary uses a weak pull-up and active low signaling. It's possible that the pull-up is too weak, but an external 4k7 pull-up will help.


    I just tested a Forth console through the simulated serial interface: it works nicely! This means that at least the core functionality of GPIOs and TIM4 (interrupts, peripheral registers) are compatible with the STM8L051 STM8L Low Density devices.

    I'm using the following UART section:

            HALF_DUPLEX      = 0    ; Use UART in half duplex mode
            HAS_TXUART       = 0    ; UART TXD, word TX!
            HAS_RXUART       = 0    ; UART RXD, word ?RX
            HAS_TXSIM        = 1    ; Enable TxD via GPIO/TIM4, word TXGP!
            HAS_RXSIM        = 1    ; Enable RxD via GPIO/TIM4, word ?RXGP
            PSIM     = PORTB        ; Port for UART simulation
            PNRX             = 6    ; Port GPIO# for HAS_RXDSIM
            PNTX             = 7    ; Port GPIO# for HAS_TXDSIM

    It's also possible to use the simulated port half-duplex mode (which means that RX/TX and SWIM should get along fine on pin1.

  • STM8L101F3: experimental support added to STM8 eForth

    Thomas09/21/2020 at 06:00 0 comments

    I merged support for the STM8L101F3 yesterday. For very low power applications the chip is definitely worth looking at (the datasheet claims that it needs around 6µA at 38kHz clock when running from RAM).

    New are:

    The BG task works now: timer register addresses are different from other STM8L devices. That's why it will be necessary to use "\res MCU: STM8L101" for many use cases (not for getting GPIO symbols, though).

    I also managed to download the code with stm8flash (!). In case someone wants to try it, here is how to wire the chip:

    What's still missing is a working STM8L001J3M3 based system. The one chip on my breadboard works when I change bytes in the Flash ROM in an OpenOCD terminal session (commands mdb and mwb) but writing an ELF file with stm8-gdb stops after the first four bytes. I'm confident that there is a spare chip in the basement...

    It definitively looks like the STM8L101 jinx (or self-inflicted failure) is halfway broken.

  • STM8L101F3L3: first STM8 eForth prompt

    Thomas09/19/2020 at 14:35 0 comments

    Thanks to OpenOCD and GDB: STM8L101 now works!

    Besides resolving the problem of actually flashing this chip (I never managed to do that with STM8FLASH), and finding the right configuration for OpenOCD (see the previous log entry), setting the SP to a valid address for this chip (1.5K RAM!) resulted in a prompt (GDB again proved helpfull).

    For now I'm using the following

    ;       STM8L101F3 device and memory layout configuration
            TARGET = STM8L051F3     ; let's use this for now - to be fixed later
            RAMEND =        0x05FF  ; "RAMEND" system (return) stack, growing down
            EEPROMBASE =    0x1000  ; "EESTART" EEPROM start address (not really)
            EEPROMEND =     0x10FF  ; "EEEND" 256 bytes EEPROM (see datasheet...)
            FLASHEND =      0x9FFF  ; "FLASHEND" 8K devices
            FORTHRAM =      0x0030  ; Start of RAM controlled by Forth
            UPPLOC  =       0x0060  ; UPP (user/system area) location for 1K RAM
            CTOPLOC =       0x0080  ; CTOP (user dictionary) location for 1K RAM
            SPPLOC  =       0x0550  ; SPP (data stack top), TIB start
            RPPLOC  =       RAMEND  ; RPP (return stack top)

    Here is a initialization code snippet of that enables TX push-pull:

    ;       BOARDINIT  ( -- )
    ;       Init board GPIO (except COM ports)
            ; Board I/O initialization: enable USART TX->PC3, RX->PC2
            MOV     CLK_PCKENR1,#0x21
            BSET    PC_DDR,#3
            BSET    PC_CR1,#3

    There are some points that need to be worked on (e.g. BG, EEPROM, RAM layout) and many things are untested. All the important bits works, e.g. writing to NVM!

    This means that I'll have to review many docs that state that it's unlikely that STM8 eForth will ever support this chip.

  • STM8L101: some new findings

    Thomas09/19/2020 at 13:08 0 comments

    Using the methods described in the previous log entry, I tried programming the STM8L101, and using STM8-GDB and OpenOCD already proves to be *very* useful!

    Connecting with OpenOCD works. I first used openocd -f interface/st-link.cfg -f target/stm8l152.cfg -c "init" -c "reset halt"). but it turned out that the that target configuration uses 128 bytes block size - Low Density devices have 64 bytes block size - and programming failed after the 5th block (setting breakpoints with GDB and inspecting memory with x/i helped a lot).

    I'm now using the following OpenOCD configuration (stored as target/stm8l101.cfg):

    #config script for STM8L101
    set FLASHEND 0x9FFF
    set BLOCKSIZE 0x40
    proc stm8_reset_rop {} {
       mwb 0x4800 0xaa
       mwb 0x4800 0xaa
       reset halt
    source [find target/stm8l.cfg]

    With this file programming an STM8L101F3P6 chip actually works!

    I made a trimmed-down STM8 eForth board configuration without background task but running it results in a reset

    (gdb) run
    Starting program: /home/thomas/source/stm8s/stm8ef/out/STM8L101F3/STM8L101F3.elf 
    Remote debugging using localhost:3333
    0x00008bd2 in ?? ()
    Loading section SSEG, size 0x1 lma 0x1
    Loading section HOME, size 0x73 lma 0x8000
    Loading section GSINIT, size 0x1a lma 0x8073
    Loading section GSFINAL, size 0x3 lma 0x808d
    Loading section CODE, size 0x1152 lma 0x8090
    Start address 0x8073, load size 4579
    Transfer rate: 7 KB/sec, 915 bytes/write.
    Program stopped.
    0x00008000 in ?? ()

     I tentatively set a breakpoints and single stepped execution until I learned that returning from a LITERAL (implemented with TRAP) doesn't work. That's very good (and very fast!) progress :-)

  • For STM8 programming OpenOCD is cool stuff

    Thomas09/19/2020 at 10:37 0 comments

    The combination OpenOCD / GDB for the STM8 appears to be a bit inaccessible. In fact it's a really good "text adventure game", and I've had fun finding my way in a "software landscape" with a long history and a specific patois.

    It turns out that one can set breakpoints or watchpoints and inspect memory with OpenOCD alone - GDB required for that, and instead one can use commands from the built-in gdbserver through a telnet session. The combination of STM8-GDB and OpenOCD can replace stm8flash for most (if not all) use case. I guess that writing STM8 flash, configuration, and option bytes with a script, instead of using GDB, is possible too.

    New applications, like writing a tethered Forth that runs on a PC and interacts with the target device through OpenOCD is within reach, and it might be interesting to explore work by @Lars Brinkhoff and in that direction (@RigTig once started there).

    What's more, both OpenOCD and GDB are scriptable. OpenOCD in the TCL dialect Jim (Rule #1: Everything is a string, Rule #2: If you think otherwise, See Rule #1).

    I guess it's about time to get one of those unloved STM8L101F3P6 and STM8L001J3M3 devices from the basement. Maybe I now have the tools to program some Forth into them :-)

View all 160 project logs

  • 1
    Step 1

    Get some cheap hardware (e.g. a STM8S103F3P6 breakout board for $0.65 and a ST-Link V2 dongle for $2). download the binary release, flash it, and have fun!

    If you like it, and you want to hack board support code for your favorite STM8China gadget, you need:

  • 2
    Step 2

    a Linux SDCC tool chain installation (installation instructions for SDCC & stm8flash are in the Wiki)

  • 3
    Step 3

    Clone the project on GitHub

View all 4 instructions

Enjoy this project?



Ken Yap wrote 05/17/2020 at 03:15 point

For what it's worth, I've contributed a wizard to the code::blocks IDE to handle stm8 projects for people who like IDEs. I still do a lot with a text editor and Makefiles.

At the moment you have to install it yourself in your C::B wizard directory, but hopefully some C::B developer will adopt it for a future release. They invited me to submit a patch, but I didn't want to download the whole SVN tree or get involved in C::B development. So many interesting projects, so little time.

C::B is:

  Are you sure? yes | no

Thomas wrote 05/17/2020 at 05:53 point

Hi Ken, thanks! I had a look at code::blocks - I loved using SVN and I still miss the clarity and ease-of-use it provides for centrally hosting repositories. Collaboration and integration in a community is a different beast, though and I wouldn't want to go back :-)

For the code::blocks IDE some OS/desktop environments appear to be more equal than others (e.g. TurtoiseSVN integration). It might be interesting if a Forth terminal or a ST-LINK debug interface can be integrated. I didn't find anything on "tethered development". How do you use it for µCs like the STM8?

  Are you sure? yes | no

Ken Yap wrote 05/17/2020 at 06:04 point

At the moment the only integration I have is a Makefile rule to call stmflash.  😁 It's a weak point of the OSS stm8 tools that there isn't a debugger or simulator or ICE. Perhaps an onboard stmforth monitor can be part of the solution?

  Are you sure? yes | no

Thomas wrote 05/17/2020 at 15:52 point

As far as I know no-support is a thing of the past. I've never tried it (since I have Forth as a "monitor" and uCsim for the rare cases when it really got difficult).

You're right, using Forth as a driver for unit testing C routines can be useful. So far, however, I didn't have an STM8 application that would have required using C...

  Are you sure? yes | no

Ken Yap wrote 05/17/2020 at 23:09 point

C::B is supposed to support gdb but I haven't got around to trying that. I just noted a couple of days back that there wasn't a wizard to start stm8 projects and whipped up one by hacking the mcs51 one. My next stm8 project is still on my ever expanding queue. I ought to finish a few projects before I add new ones. The C::B wizard was a quick hack so I couldn't resist.

  Are you sure? yes | no

marian2002go wrote 05/12/2020 at 01:42 point

Hi, Thomas! Do you think it's possible to program the W1209 thermostat to have the following values hard coded:

1. Heater mode

2. Trigger offset 1°C

3. Minimum temperature 15°C

4. Maximum temperature 35°C

When the SET button gets pushed, the current set temperature will start blinking. Adjusting the preferred temperature using + and - buttons. When the SET button gets pushed the second time, the value gets saved.

Please let me know if this would be possible to achieve and if you are interested in helping me. If yes, we'll speak about the costs in private. Thank you! Dumitru

  Are you sure? yes | no

mikael_lundgren_ak wrote 07/01/2018 at 17:21 point

Thanks for your good answer. 

For beginers a well dokumentet memory map for ram flash and eeprom if used for dichenary would be helpful. also a map of how dichenary entries are saved in ram ore flash. i have read the eforth dokumentation but i still is not totaly clear to me. wbr Mikael.

  Are you sure? yes | no

Thomas wrote 07/01/2018 at 17:53 point

Hi Mikael,

did you check the (rather lengthy) explanation in the Wiki?

The STM8 eForth method is rather unique (at least that's what seasoned Forthers say), but it's also robust and, due to ALIAS words, even the EEPROM can be used to increase the available dictionary space.

Have a look at this page:

Besides NVM and RAM there is a number of helper words, e.g. WIPE, PERSIST, :NVM, or EEALIAS. Please have a look at the example code in the lib/ folder.

  Are you sure? yes | no

mikael_lundgren_ak wrote 06/18/2018 at 07:28 point

how can I check all the different usage of memory; flash ram dictionary space user variable space etc. I would like to monitor the memory space automaticly used by the forth vm to understand more and know when i have consumed some area of memory. wbr mikael.

  Are you sure? yes | no

Thomas wrote 06/18/2018 at 21:17 point

Check this out:

 To check the free flash area I always use "NVM $A000 here - . RAM"

FYI: WIPE removes the dictionary entries in RAM, and, after defining variables in NVM mode, also moves up the dictionary start in RAM.

Regards, Thomas

  Are you sure? yes | no

mikael_lundgren_ak wrote 04/10/2018 at 13:57 point

Thanks for a good and fast answer, now I have som nice testing to do.

  Are you sure? yes | no

mikael_lundgren_ak wrote 04/09/2018 at 13:42 point

Hi Thomas 

I have been playing with your fantastic eforth now for a while and must say it is both extremly fanny/addictive yet powerful. For me the whole forth concept was new but quickly i got to like the speed of testing and clean way of writing the code. So thank you. I have som questions: for the real beginners more example code with comment would be great specially for using hardware like spi i2c timmers and more. If I build a program but then realize that one of my earliest building words need to be altered, how can i manage this? Is it possible to edit a word by decompiling with SEE and then edit and recompiling ? wbr Mikael

  Are you sure? yes | no

Thomas wrote 04/09/2018 at 18:45 point

Hi Mikael,

it's great to hear that you have fun with STM8 eForth!

Here is a (certainly incomplete) list of example code:

If you need to recompile a word at the base of your dictionary, the Forth development cycle usually requires re-compiling code from the source. Since the source code in most cases isn't stored on the µC, tools like e4thcom, Manfred Marlow's nifty Forth terminal, or, can be used to upload code efficiently (take note of the #include, #require, and \res statements in the examples). It's also possible to change existing code in-place, e.g. by replacing the code of an existing word with a JP to a new word (this has a twist due to the STM8 eForth ALIAS feature!). For a rather elaborate example check out the lib/CURRENT and lib/VOC implementations.

The STM8 eForth core consists of optimized assembly code (even the compiler does some optimizations), and therefore a simple SEE implementation will fail. In order to understand the core it's easiest to compare it with the code in Dr. C.H. Ting's "eForth Overview",

Best Regards

  Are you sure? yes | no

BigVulcanDeal wrote 02/03/2018 at 13:23 point

'You haven't lived until this thing has thrown a 8" pair of vise-grips at you'

It seems the controller for many of the Harbor Freight cordless tools uses an STM8 mcu of some sort.


  Are you sure? yes | no

Thomas wrote 02/03/2018 at 15:09 point

STM8S are used frequently, but I'd like to see some evidence before I buy that it's "likely a genericized or pin-and-code compatible version available on the Chinese market".
The Meloncraft, however, isn't half bad.

  Are you sure? yes | no

Eelco wrote 01/24/2018 at 22:47 point

Hi Thomas

I am having an issue with MARKER. Compilation stops when I call a word that is defined just before in the same file. If I use MARKER from version 2.2.19 it works fine. Did I miss something, once again?

  Are you sure? yes | no

Thomas wrote 01/25/2018 at 03:25 point

Hi Eelco, could you please let me know the version or git hash you're using? Also please provide a code example, e.g. in a GitHub Gist or even better, as an Issue :-)

  Are you sure? yes | no

Thomas wrote 01/25/2018 at 06:27 point

On a second thought... could it be that you ran out of RAM? The available RAM didn't change much since 2.2.19 but its usage by library words might have changed.

  Are you sure? yes | no

Eelco wrote 01/25/2018 at 08:31 point

OK, I found what I was doing wrong: I forgot to define a dummy word before calling MARKER. In version 2.2.18 ( I mentioned 2.2.19 but that should be 2.2.18, I skipped 2.2.19) this was done when you uploaded MARKER, in version 2.2.20 you must do it yourself.

My apologies.

  Are you sure? yes | no

Thomas wrote 01/26/2018 at 05:40 point

No need to apologize, I still take the blame!
MARKER needs at least one word definition in RAM to operate, and that's not obvious. I'm rarely ever confronted to that because of the "#include STARTTEMP ... TARGET ... ENDTEMP"  template I apply. In my main.fs, TARGET is usually defined as ": TARGET NVM ;"  before STARTEMP in the first module even issues "#require MARKER" ( ).
Maybe I should  re-introduce a dummy word in MARKER. 

  Are you sure? yes | no

Eelco wrote 11/18/2017 at 14:09 point

Hi Thomas

I am encountering strange behavior when allocating ram to variable arrays.

e.g.  NVM variable qqq variable zzz RAM

qqq $20 allot drop

zzz $20 allot drop

qqq $20 $AA fill

zzz $20 $BB fill

qqq $40 dump

  80  AA AA BB BB BB BB BB BB BB BB BB BB BB BB BB BB  ________________
  90  BB BB BB BB BB BB BB BB BB BB BB BB BB BB BB BB  ________________
  A0  BB BB  0  0  0  0  5 61 6C 6C 6F 74  0  0  0  0  _______allot____
  B0   0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  ________________ ok

It seems the second array is using the same space as the first one.

I am trying to communicate with sdhc cards FAT32 file systems in SPI mode. Using one array for 512 byte data buffer works great but now I try to define a second array as a filename buffer and I run into this problem. Do you have a solution? Btw I tried with the latest version, 2.2.20.

  Are you sure? yes | no

Thomas wrote 11/18/2017 at 15:48 point

Hi Eelco,

there are two issues with your code:

One is related to how VARIABLE works in NVM mode: memory is allocated from a small pool (just 32 bytes) which is reserved during COLD. The implementation is described here: [ ]. Of course you can allocate more memory than there is in the pool, but then you'll have to cycle through cold before using it.

The second is a "Forth thing". You'll have to allocate memory directly after defining the variable. Of course it's possible to create a malloc()-like device, but variables are static.

The following log shows the procedure:

STM8eForth 2.2.20
here . 160 ok
nvm variable qqq $1e allot ram ok
nvm variable zzz $1e allot ram ok
STM8eForth 2.2.20
here . 224 ok
qqq $20 $aa fill ok
zzz $20 $bb fill ok
qqq $30 dump    
  80  AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA  ________________
  90  AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA  ________________
  A0  BB BB BB BB BB BB BB BB BB BB BB BB BB BB BB BB  ________________
  B0  BB BB BB BB BB BB BB BB BB BB BB BB BB BB BB BB  ________________ ok

I assume that you use a low density device with just 1KiB RAM. You can try using the EEPROM for storing the second buffer - writing it is slow but for manipulating the FAT it might be sufficient.

  Are you sure? yes | no

Eelco wrote 11/18/2017 at 17:05 point

OK, thank you very much, this works. I will study the link again. I am using a board with stm8s103f, 1KiB ram indeed.

  Are you sure? yes | no

Roy wrote 11/17/2017 at 14:22 point

Just hooked up a MINDEV STM8S103 directly to an HC12 wireless serial communication module at 9600 baud and have 100% console eForth results over many hundreds of metres.

HC12      STM8S

TXD        RX  PD6

RXD        TX  PD5

  Are you sure? yes | no

Thomas wrote 11/17/2017 at 20:02 point

The HC12 is quite good! I experimented with running Forth on the STM8S003F3P6 that powers the HC12. Maybe I'll continue with it at the end of the year.

  Are you sure? yes | no

Roy wrote 11/12/2017 at 12:02 point

\ C0135 display data 4 bits and power relays with LED for HI nibble

\ 12 NOV 2017 RS
VARIABLE Startaddr

$1000 Var ! \ inner delay
$40 Varloop ! \ outer delay
$8090 Finaddr !
$8080 Startaddr !

: vardelay Varloop @ 0 DO Var @ 0 DO LOOP LOOP ;
: newflasher2
 Finaddr @
 Startaddr @ DUP addr !
  Addr @ DUP . C@ DUP . Byte ! CR
  Byte @ $F0 AND $10 / \ mask and rotate hi nibble
  $10 OR OUT! \ also turn on LED
  Byte @ $F AND OUT!
  Addr @ 1 + Addr !


8080 0
8081 0
8082 5A
8083 26
8084 F7
8085 CC
8086 80
8087 68
8088 CC
8089 80
808A EC
808B 5A
808C 5A
808D 1F
808E 3
808F 51

  Are you sure? yes | no

Thomas wrote 11/12/2017 at 18:31 point

Got one? A nice little board, isn't it?
Also have a look at this one:
I don't know why they call it "5 way relay time control panel" when it has 6 relays, but I ordered one yesterday. The 11.11 price was just $10.35 (€8.87, ₤7.85).

  Are you sure? yes | no

Eelco wrote 10/28/2017 at 14:19 point

Hi Thomas 

I am trying to use a timer interrupt similar to your description ( .

I think I had to rewrite IVEC!:    (: IVEC! 2* 2* $8008 +  ULOCK ! LOCKF ; )  to be able to write to the interrupt vector address. 

: timer_4_interrupt SAVEC 0 $5344 0 b! OUT! IRET ;    \ Simple interrupt routine.

' timer_4_interrupt 23 IVEC!    \ Link interrupt routine to IRQ23 (TIM4 update).

But as soon as an interrupt occurs the chip reboots. How should I proceed to use timer interrupts?

  Are you sure? yes | no

Thomas wrote 10/28/2017 at 18:31 point

Hi Eelco,

what a coincidence! I continued working on the interrupt features, and I also got reboots. I'm currently debugging, and as soon as I've figured out what goes wrong I'll let you know!


  Are you sure? yes | no

Thomas wrote 10/28/2017 at 19:53 point

OK, that was easy but I've got no idea why it ever worked. 

Here is the fix (a new pre-release will be out soonish):

;       SAVEC ( -- )
;       Minimal context switch for low level interrupt code
;       This should be the first word called in the interrupt handler

        POPW    Y
        LDW     X,YTEMP
        PUSHW   X
        LDW     X,#(ISPP)       ; init data stack for interrupt ISPP
        JP      (Y)

;       IRET ( -- )
;       Restore context and return from low level interrupt code
;       This should be the last word called in the interrupt handler

        POPW    X               ; discard CALL return address
        POPW    X
        LDW     YTEMP,X         ; restore context

Edit: the bug was even worse than I thought - the above code does the job.

By the way: you don't need ULOCKF / LOCKF if you set the interrupt vector in NVM mode. I'll also put the interrupt vector addresses into the STM8S103.efr file so that setting an interrupt works with a simple ! (store), and IVEC! is no longer needed.

  Are you sure? yes | no

Eelco wrote 10/29/2017 at 09:59 point

Hi Thomas

Wow, that was really fast. I should have asked you a week ago, would have saved me a lot of time.

I tried setting the interrupt vector in nvm mode but with 2.2.17 this forced the chip in a strange loop, even after a power cycle. I then had to reflash the mindev board. (I think I really need to get into assembly). 

Thank you very much for solving this issue.


  Are you sure? yes | no

Thomas wrote 10/29/2017 at 20:22 point

The bug clearly was on the silly side. Next time please drop me note when it looks like you're stuck :-)

  Are you sure? yes | no

Thomas wrote 10/28/2017 at 21:11 point

I updated the example code:

I used a headerless interrupt handler but with the patch above your code should now work as intended :-)

  Are you sure? yes | no

Thomas wrote 10/28/2017 at 22:08 point

  Are you sure? yes | no

Roy wrote 10/06/2017 at 09:31 point

Microchip produced a humorous self-critical video about the failings of the PICkit 3 vs the older 2. Perhaps ST Micro should be shamed to do the same with their products. I realise that this is off topic but still a good example of how not to do things and take ownership for getting it wrong. My ST Visual Programmer is 3.4.0 Jul 12 2017.

  Are you sure? yes | no

Roy wrote 10/04/2017 at 17:23 point

Having lived in Quebec a long time ago, there is a local swear word that sounds like ST. This is what I say every time I use ST software and hardware. STVP does not even show the latest factory ST-LINK/V2 as an option - 'ST-LINK All Versions' would be useful. The thing never connected as I tried a few times a year over many years. They do nothing to alert you that the target device needs external power. I always had clones that did the job so there was no great urgency to learn it.

Many (all?) of the cheaper USB - STM programming adaptors had figured this out a very long time ago. Even Microchip PICkit 2/3 monitors power on the target but gives the option to power their external devices.

Simply logging in to ST to get free software goes into an email / validation death spiral loop that is a complete waste of our valuable time. If the people of ST responsible for this nonsense worked for me, then they would be all unemployed.  


  Are you sure? yes | no

Eelco wrote 09/30/2017 at 16:11 point

Hi Thomas

I saw you solved the issue. Great! Thanks.

  Are you sure? yes | no

Eelco wrote 09/27/2017 at 18:13 point

Hi Thomas, I am enjoying your project for more then a year now. Today I joined hackaday to be able to participate. I bought a couple of W1209 and mindev boards to play with. I also have an ssd1306 i2c oled display (about $3 at Aliexpress). I managed to drive it using the i2c capabilities of the chip, no bit-banging. This was a few months ago, with version stm8ef-bin.2.2.8 and a MINDEV board. I used $" to compile the text to be send to the display (e.g. : txt $" text" ;) I upgraded to more recent versions, up to 2.2.16, but executing a word that contains $" freezes (or reinitilizes, as with COLD) the board. What am I doing wrong here? Do I have to raise a flag in Can you point me in the right direction?

Btw, I'm happy to share the code if anyone is interested.

  Are you sure? yes | no

Thomas wrote 09/28/2017 at 06:07 point

Hoi Eelco,

thanks for letting us know about your work! Your contribution in the I2C field would be very much appreciated!

Also thanks for reporting the issue with $": this is a regression. It's tracked here, and I'll fix it as soon as possible.

The root cause is insufficient testing. Some of the progress for building a test infrastructure is tracked here:

I would love to have you in the team at GitHub. I'm quite sure that the other team members would say the same.

Met friendelijke groeten,

  Are you sure? yes | no

Eelco wrote 09/28/2017 at 08:43 point

Hallo Thomas

Thank you for your kind reply and invitation, I would like to join. I have to warn you though that I have little coding experience but I am learning thanks to projects like yours. How do I proceed to upload the code?

I just saw you have a separate project with W1209 thermostat boards. I use two of such devices in my household: one as a replacement thermostat in a refrigarator. The other one in the boiler of the central heating unit. Maybe I can make small contributions on that project too.

mit freundlichen Grüßen


  Are you sure? yes | no

Thomas wrote 09/30/2017 at 12:20 point

Hi Eelco,

the only way to gain coding experience is coding. There is still a lot you can do, e.g. write tests (which improves coding skills significantly!), or write library code (e.g. I2C), or do a review (also a great way to learn), or spread the word... Please let us know your GitHub ID, and you'll receive an invite!

A warning about W1209 in safety critical applications:
* only use hobby stuff for adding features that aren't safety critical
* always rely on built-in safety features of the product
* make sure to get a review of your design from someone who knows safety

Creating a HaD-project is a great way to get feedback from experts!

  Are you sure? yes | no

richard wrote 10/05/2017 at 03:08 point

Hi Eelco,

I would welcome seeing your code. I'm likely to use i2c one day and your code will give me a head start.



  Are you sure? yes | no

Eelco wrote 10/05/2017 at 08:47 point

Hi Richard

Here is the link:

Please let me know if  you have recommendations for improvement.



  Are you sure? yes | no

richard wrote 10/05/2017 at 15:04 point

Hi Eelco,

thanks for the code below. Already I have learned about the B! word from reviewing your code. That's going to help me enormously with my W1209 project where I want to turn an input port into an output port for some of the time.

You've done a much better job than I would have. Thanks again


  Are you sure? yes | no

Eelco wrote 10/05/2017 at 21:59 point

Hi Richard

You're welcome, I am glad it is of use to you. I uploaded another file on my github account with io-manipulating words: io.fs. These words use a numbering of the gpio-portpins. The word io. displays the state of the IDR,ODR,DDR,CR1 and CR2 for a portpin. (e.g. $15 io.  displays these bit states for the  second port (Port B), pin 5. Maybe useful for you as well.

  Are you sure? yes | no

Peter wrote 08/21/2017 at 14:11 point

I'm a newbie and have implemented eForth on a STM8S103F3. While I have successfully implemented the "mystart" boot example which remains in NVM  following a power reset, I just can't seem to get any other created word to be available. Could I have some guidance please? 

  Are you sure? yes | no

Thomas wrote 09/24/2017 at 07:24 point

Hi @Peter, sorry, I noticed your message just now, which is very unfortunate. Yesterday I independently found the problem you were facing. The problem, which existed since 5/August/2017, has been fixed. A new binary release is being prepared.

  Are you sure? yes | no

Thomas wrote 09/24/2017 at 08:38 point

I just released v2.2.16 to fix this issue.

  Are you sure? yes | no

Peter wrote 09/25/2017 at 20:56 point

Hi Thomas. On my second MinDev I was able to re-programme it using STVP ID 3.4.0. However as it says "stm8eForth v2.2" which is identical to other boards, how do I distinguish it elegantly via communication? Incidentally the first board which has been running a blink programme as an endless loop on "problem 2.2.13" refuses to re-programme via SWIM reporting not blank though ROP is off. Any suggestions on recovering it?

  Are you sure? yes | no

Thomas wrote 09/29/2017 at 18:06 point

Hi Peter,
you have a point there.  @barewires already filed an issue. I'll be looking into it!

  Are you sure? yes | no

Peter wrote 10/13/2017 at 13:50 point

Hi Thomas, small update to follow. I don't know whether it's my ignorance but I was expecting to be able to reply as another indent to your reply 09/29/2017 at 18:06 but replying via 09/24/2017 at 07:24.

  Are you sure? yes | no

Peter wrote 10/13/2017 at 14:28 point

To cover my experience described earlier I'll split it into two responses in case anybody wants to work on that part of it. I have not been doing any compiling but just running STVP in windows burning IHX files as required. Any compiling I'm likely to do will be in Windows as I've found setting up a Linux similar to what I use a challenge (...ST). Zorin I'd suggest is a better start that many.

I solved how to re-programme a stubborn STM8S103F3P6 mentioned by specifically selecting the Option Byte window tab and then using Program > Current Tab.  Then I was able to program as I normally do so by using Program > All tabs.  Possibly a glitch but nothing else worked.

  Are you sure? yes | no

Peter wrote 10/13/2017 at 17:59 point

To distinguish between the different versions of 2.2.xx appearing as v2.2 I've started to modify the IHX file so that the same 4 bytes now display 2v17 for example. I'll explain the procedure for newbies like me used to Windows.

1. Copy the IHX file and rename including the version and change the file type to HEX. e.g. C0135.IHX becomes C0135-2v17.HEX.

2. Open the file using STVP and choose the Program Memory tab to display both the hexadecimal and ascii contents.

3. Go to around line 000081E0 and you should see in the ascii columns on the right  stm8 eForth v2.2. Put the cusor on the v and update. The hexadecimal will change.

4. Save

Now on STVP default settings the files are easily accessible. For me the approach above is easier than directly locating the file with STVP and using the Save As to create the HEX copy. 

  Are you sure? yes | no

Thomas wrote 10/13/2017 at 20:25 point

Hi Peter, thanks for updating on the Windows tools!

I'm currently working on `` - it should mirror the properties of e4thcom (require, \ res, \\ Example). Maybe the same is achievable on Windows with ``.

  Are you sure? yes | no

jeff1937 wrote 07/29/2017 at 07:38 point

Just wondering does anyone know if it could it be possible to read the temperature of a W1209 via wire serial communication ?

In other words I just want to log the temperature to a computer, but still leave the W1209 to function as a thermostat.

  Are you sure? yes | no

Thomas wrote 08/05/2017 at 13:08 point

Yes, that's possible. The steps are as follows:

1. determine the R_ntc to voltage function (e.g. using a trimmer and an unmodified W1209, 5 values, e.g. 0 deg C, 80 deg C, and 3 values around (and including) the temperature you care most about)

2. flash W1209-FD from the v2.2.13 release

3. determine the ADC6 values for relevant R_ntc from 1.

4. create an interpolation function from 3.

5. write a simple background task that does thermostat control by reading ADC6 and using 4.

6. read the temperature value from 5. using console commands from your computer. Alternatively send the values in the background task

If you describe your use case more precisely, I can write something to get you started

  Are you sure? yes | no

jeff1937 wrote 08/06/2017 at 00:47 point

Thanks Thomas for the helpful reply.

My applications are to turn off a immersion heating element in a cooking pot when the water reaches near to boiling and secondly to operate a fan in a solar dryer at a temperature around 100C, with computer logging every 10 minutes or so.

Thanks for your kind offer of assistance, but I will try to get some unmodified W1209s operating in a circuit, just to get started first.

If I was able to reflash them, I would hope to retain the 3 digit temperature display.  Which sounds easy as you say they are fully supported by STM8EF vectored I/O.

I guess the key pins don't operate when they are used for serial connection, which is OK because the temperature points could be hard coded in software.

  Are you sure? yes | no

Thomas wrote 08/06/2017 at 05:07 point

Jeff1937, thanks for the info! How do you think about making a small project out of this? I've got a feeling that quite some people would be interested in using this :-)

Know what, I've got a couple of spare W1209 boards here. I'll start a new project, and invite you as a team member. Does this sound good?

  Are you sure? yes | no

jeff1937 wrote 08/06/2017 at 06:54 point

Also was thinking that you could use a datasheet for an NTC 10K.

It shows a resistance table between -55 to 125°C.

eg 25°C = 10,000Ω, 80°C = 1,068Ω,  100°C = 549Ω

Then calculate the theoretical voltage at PD6 with a 20k pull-up to 5V.

This would need a later calibration correction adjustment, but should give a good starting point.

  Are you sure? yes | no

jeff1937 wrote 08/06/2017 at 06:59 point

Yes I would like to have a go at making this a project, or helping.

My W1209 boards haven't arrived yet, but there's plenty to learn in the meantime.

  Are you sure? yes | no

Thomas wrote 08/06/2017 at 07:02 point

Good idea, at least to validate the temperature readings we get.

By the way, I started a HaD project for this. Let's continue with our discussion there!

  Are you sure? yes | no

Thomas wrote 08/06/2017 at 07:16 point

Ok, great! Get's let started. Please visit the project page, and "Follow" the project to get a notification when there is something new.

There is a first project log, where you can add comments. I also added a GitHub project for code and docs.

See you there!

  Are you sure? yes | no

jeff1937 wrote 08/06/2017 at 08:02 point

OK, will follow you there, thanks Thomas

  Are you sure? yes | no

richard wrote 07/22/2017 at 02:02 point

My first attempt at using a W1209 board has been very rewarding. A couple of suggestions for anyone starting out and for the project team:


1. I had no success flashing the board with the suggested ST software on  You may also consider the ST software used by the person who published the schematic of the W1209. It can be found at


2. When putting the header on for the SWIM connector use 5 pins instead of 4. The 5th pin is a convenient place to tie one end of the diode to for the half duplex link.


3. While the SWIMCOM binary may work on the W1209 board, for the newcomer there is a lot of reward in seeing the "4th" string on the LED display once the binary is flashed. With that feedback you know it is just a matter of getting the serial comms to work.


4. With the extra pin the SWIM connection would be a much better place to have half duplex communications. It would prevent the serial communication from disrupting measurements on the sensor pin while debugging and gives you a pin that your push on connector holds better.


5. Is there a place to share code snippets? For instance, I wanted to blank the display before sending another character to it. I used

 : Clrdisplay \ clear anything showing

        32 E7S 32 E7S 32 E7S ;


I also wanted a delay between displaying “On” and “Off”. I used the following but I suspect there is an easier way:


variable bigtimer


: tSet TIM 1000 + timer ! ;

: tTest TIM timer @ - 0 < ;

: delayInner tSet begin ttest until ;

: delay 0 bigtimer ! begin delayInner 1 bigtimer +! 25000 bigtimer @ - 0 < until ;


If there was a way to share these snippets it may prove useful to the newcomer. Maybe I just don’t understand the features of github well enough *grin*.


Anyway, I can recommend this forth implementation to anyone looking to hack one of these boards. I’m having a blast . I only wish I had found about this project before I built my electric gate controller with an atmel avr chip programmed in assembly. I could have just brought a cheap relay board and achieved the same thing without having to fabricate a board, populate it then program it in assembly.


Keep up the great work team.


Kind regards


  Are you sure? yes | no

Thomas wrote 07/22/2017 at 08:49 point

Hello Richard, thanks for your comment, it's higly appreciated!
Here are a few pointers to related actions, some new, some in the making.

1: the Wiki is updated

2, 3, 4: using a 5-pin header and a diode is a good idea! I'm currently experimenting with using the W1209 key GPIOs (PC4, PC5) for full-duplex communication, which has several advantages. What do you think?

The usability of STM8EF programming is currently under active development.   Especially a. and b. should be helpful for new users:

  a. improved full-duplex serial code, e.g. for W1209
  b. e4thcom support with libraries
  c. temporay "scaffolding" code in RAM
  d. board hex file generation in uCsim

5: I created a GitHub Gist with your code snippets - let's see if that works as advertised: 

I created an issue on GitHub
It would be great if you could contribute to  taking the decisions for a better W1209 support. Also feel free to open an issue on GitHub for topic oriented discussion.

Thanks again for your contribution.

  Are you sure? yes | no

richard wrote 07/22/2017 at 10:04 point


great stuff. I've been at it all day so real life drags me away for now. I don't have much to contribute on full or half duplex serial. I used Teraterm and slowed it down (25ms each character, 500ms for each line return) so the compiling could keep up. I was happy with that.

The Github Gist is interesting. Over time it could be really useful. Perhaps the main Github wiki needs to alert readers to it's existence?

I'm happy to help out with the W1209 where I can. You've no doubt heard of the saying "the blind leading the blind". 

The W1209 is a great platform and it is very exciting to think that much of what I used F-PC for years ago I could do on something costing so little. I plan to contribute as much as I can. 



  Are you sure? yes | no

Thomas wrote 07/22/2017 at 12:59 point


the voice of users is important, especially in a hobby project where there is no such thing as "market research" - users know very well what makes a product  useful for them. One I'd like to figure out is if connecting a serial interface to the keys "+" and "-" is acceptable (the keys will remain usable), at last during interactive programming. The other thing is whether support for "sensor header COM" needs to be maintained, or if I can simply replace it with something better :-)

  Are you sure? yes | no

Thomas wrote 07/22/2017 at 17:06 point

FYI: issue #41 is closed (which means that full duplex communication now works without character delays). I'll make a pre-release.

EDIT: please check the project log

  Are you sure? yes | no

RigTig wrote 02/27/2017 at 21:59 point

Thomas mentioned that a better file loader would be nice. Here is my attempt. Simple to start with, but obviously capable of being expanded with features later. It is in Python2 and runs from the command line of the host machine (mine is LinuxMint).


#!/usr/bin/env python2

import serial
import sys
import time

port = serial.Serial(

if len(sys.argv) < 2:
    print('Usage %s ... [fileN]' % (sys.argv[0]))

def upload(path):
    with open(path) as source:
        for line in source.readlines():
            line = line.strip()
            if not line: continue
            if len(line) > 64:
                raise 'Line is too long: %s' % (line)
            print('\n\rsending: ' + line)
            chin = ''
            response_buffer = []
            while chin <> '\v':
                while port.inWaiting() > 0:
                    chin =
            response = ''.join(response_buffer)

for path in sys.argv[1:]:
    print('Uploading %s' % path)


Usage: Save this code as a file (say named and change its permissions to be executable (just the lines in between the code tags). I put in my local /bin folder. Edit so the port matches what you use when using a terminal console to connect to STM8 machine.

WARNING: I've just noticed that the indentation was inconsistently displayed, and python is indentation sensitive. So be very careful with just copy-and-paste. I'll put a copy of it up on RigTig's Big 3d Printer project here on

Either put FILE on first line of the file to be sent, or type it into a terminal console and close it, then use a local command line interface thus: <code>  filename file2send </code>. Enjoy!

  Are you sure? yes | no

Thomas wrote 02/27/2017 at 22:26 point

Hi RigTig, this is cool! Now the last reason not to learn Python (the haploid language, as I use to say) has gone. I'm going to need it in my job, anyway ;-)

PS: I just added the tag v2.2.8.1.snapshot, and this means that the binary size of CORE is below 4096 bytes, complete with the new "transparent" VARIABLE feature

  Are you sure? yes | no

Thomas wrote 03/04/2017 at 11:07 point

I just tried your script - the handshake seems to work, and compiling code to NVM is very fast compared to the "worst case delay" method!

However, I had to interrupt the script with ctrl-c after the transfer was finished. The reason was that my Forth code ended with "HAND", after which waited in vain for the handshake signal.

I can imagine that an improved uploader does the following:

* handle FILE and HAND (no need to include those in source file), or

* terminate transfer when the response is anything but the handshake character

The next thing on a programmer's wish list is a way for including source files (nested, of course). I can also imagine testing if "base code" has already been transferred, e.g. using some query-response between the Forth system and the uploader.

  Are you sure? yes | no

Thomas wrote 02/27/2017 at 22:26 point

Hi RigTig, this is cool! Now the last reason not to learn Python (the haploid language, as I use to say) has gone. I'm going to need it in my job, anyway ;-)

PS: I just added the tag v2.2.8.1.snapshot, and this means that the binary size of CORE is below 4096 bytes, complete with the new "transparent" VARIABLE feature

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates