> What’s New ? <

Forth (embedded) Interactive Alternatives On Cortex M

A quick look at other Open Source interactive development systems for Cortex M, are they any good, do they even compete with Forth ?

Distribution Website Last Updated? Minimum Flash Image Size Run on Cortex M0 with 32KB flash ? binary image tested Binary Image URL’s ? My conclusion ?
Micropython https://micropython.org/ current V1.9.4 309KB No stm32f4disc-20170526-v1.9.dfu http://micropython.org/resources/firmware/ Stable, fast, seems well designed
Circuit Python https://github.com/adafruit/circuitpython current V3.0.0 184KB No Not tested https://github.com/adafruit/circuitpython/releases Not tested, I don’t use SAMx or ESPxx
eLua http://www.eluaproject.net current V0.9 260KB No elua_lua_stm32f407vg.bin http://stm32f4.web.fc2.com/elua.html Stable, fast, seems well designed
Armpit Scheme http://armpit.sourceforge.net/ Dec 5, 2014 V070 60KB No armpit_060_STM32F4_Discov.bin <— Doesn’t work


MicroPython v1.9 on 2017-05-26; F4DISC with STM32F407

How does Micropython Work?

Micropython compiles the python source into bytecode, then the interpreter evaluates the bytecode. Using the Decorator it compiles typed python into assembly.

You can write functions in Arm assembly with the Decorator

Testing Micropython

I installed the stm32f4disc-20170526-v1.9.dfu image on a STM32F4 Discovery following the tutorial at https://github.com/micropython/micropython/wiki/Board-STM32F407-Discovery, which went very smoothly and quickly.

The Micropython bulk USB storage device mounted easily with the Micropython files visible and the terminal was fast and bugfree using Picocom on Linux (freeBSD was buggy however).

Micropython Terminal demo

>>> help()
Welcome to MicroPython!

For online help please visit http://micropython.org/help/.

Quick overview of commands for the board:
 pyb.info()    -- print some general information
 pyb.delay(n)  -- wait for n milliseconds
 pyb.millis()  -- get number of milliseconds since hard reset
 pyb.Switch()  -- create a switch object
                  Switch methods: (), callback(f)
 pyb.LED(n)    -- create an LED object for LED n (n=1,2,3,4)
                  LED methods: on(), off(), toggle(), intensity(<n>)
 pyb.Pin(pin)  -- get a pin, eg pyb.Pin('X1')
 pyb.Pin(pin, m, [p]) -- get a pin and configure it for IO mode m, pull mode p
                  Pin methods: init(..), value([v]), high(), low()
 pyb.ExtInt(pin, m, p, callback) -- create an external interrupt object
 pyb.ADC(pin)  -- make an analog object from a pin
                  ADC methods: read(), read_timed(buf, freq)
 pyb.DAC(port) -- make a DAC object
                  DAC methods: triangle(freq), write(n), write_timed(buf, freq)
 pyb.RTC()     -- make an RTC object; methods: datetime([val])
 pyb.rng()     -- get a 30-bit hardware random number
 pyb.Servo(n)  -- create Servo object for servo n (n=1,2,3,4)
                  Servo methods: calibration(..), angle([x, [t]]), speed([x, [t]])
 pyb.Accel()   -- create an Accelerometer object
                  Accelerometer methods: x(), y(), z(), tilt(), filtered_xyz()

Pins are numbered X1-X12, X17-X22, Y1-Y12, or by their MCU name
Pin IO modes are: pyb.Pin.IN, pyb.Pin.OUT_PP, pyb.Pin.OUT_OD
Pin pull modes are: pyb.Pin.PULL_NONE, pyb.Pin.PULL_UP, pyb.Pin.PULL_DOWN
Additional serial bus objects: pyb.I2C(n), pyb.SPI(n), pyb.UART(n)

Control commands:
 CTRL-A        -- on a blank line, enter raw REPL mode
 CTRL-B        -- on a blank line, enter normal REPL mode
 CTRL-C        -- interrupt a running program
 CTRL-D        -- on a blank line, do a soft reset of the board
 CTRL-E        -- on a blank line, enter paste mode

For further help on a specific object, type help(obj)
For a list of available modules, type help('modules')

STM32F4 Discovery led tests

>>> led2 = pyb.LED(2)
>>> led2.on()          <-- the board led 2 turned on
>>> led2.off()         <-- the board led 2 turned off

>>>  led2.toggle()     <-- toggles the led!



Micropython needs a Cortex M4 generally.

  • Positives
    • Stable, fast, seems well designed
    • Documantation is excellent
    • Lots of libraries
    • The CTRL-E serial terminal “paste mode”, which is just like a rock solid full screen editor is just awesome, I want one for Forth too!
  • Not so positives
    • The Flash Image I built was 309KB. The website ( https://micropython.org/) says “it is compact enough to fit and run within just 256k of code space and 16k of RAM”. By Contrast Mecrisp-Stellaris only requires a Flash image of 20KB, making it perfect for inexpensive MCUS with as little as 32KB Flash.
    • For some reason the Micropython home website ( https://github.com/micropython/micropython) does not offer any prebuilt binary images.
    • Garbage collection is required which means that there will be delay while this is done, possibly a few mS, making this non real time.
    • Manual testing is tedious due to the language constraints, I’ve been spoilt by Forth.

My thanks to Per Ljung for updates and information re Micropython, and Vincent Hamp for taking the time to point out a major typo.

Circuit Python

  • CircuitPython is an education friendly open source derivative of MicroPython. CircuitPython supports use on educational development boards designed and sold by Adafruit. Adafruit CircuitPython features unified Python core APIs and a growing list of Adafruit libraries and drivers of that work with it.
  • Minmum Flash Image size seems to be 184KB
  • Includes ports for MicroChip SAMD21 (Commonly known as M0 in Adafruit product names) and SAMD51 (M4).
  • Supports only SAMD21, SAMD51, and ESP8266 ports. An nRF port is under development.
  • Tracks MicroPython’s releases (not master).
  • Longints (arbitrary-length integers) are enabled for most M0 Express boards (those boards with SPI flash chips external to the microcontroller), and for all M4 builds. Longints are disabled on other boards due to lack of flash space.


The binary flashed to a STM32F407VG Discovery easily using st-flash as below:- st-flash write elua_lua_stm32f407vg.bin 0x08000000

Then a terminal was connected at 115200 Baud, 8,n,1.

picocom -b 115200 /dev/cuaU20

Terminal Board

eLua Terminal demo

eLua# ver
eLua version v0.8
For more information visit www.eluaproject.net and wiki.eluaproject.net

eLua# help
Shell commands:
 exit        - exit from this shell
 help        - print this help
 ls or dir   - lists filesystems files and sizes
 cat or type - lists file contents
 lua [args]  - run Lua with the given arguments
 recv [path] - receive a file via XMODEM. If path is given save it there, otherwise run it.
 cp <src> <dst> - copy source file 'src' to 'dst'
 wofmt       - format the internal WOFS
 ed  [args]  - run 'ed' text editor with the given arguments
 ver         - print eLua versio

 eLua# lua /rom/info.lua
 Press CTRL+Z to exit Lua
 I'm running on platform STM32F4
 The CPU is a STM32F407VG
 The board name is STM32F4DSCY

 eLua# lua
 Press CTRL+Z to exit Lua
 Lua 5.1.4  Copyright (C) 1994-2011 Lua.org, PUC-Rio
 > print ( 355 / 113.0)

 > print ( math.sin(355/113/2))

eLua Blinky

The following program based on a eLua example file was loaded, and the board led blinked nicely.

-- eLua blinking led example, the Hello World of embedded :)

local uartid, invert, ledpin = 0, false

-- STM32F4 Discovery
 ledpin = pio.PD_13
 uartid = uart.CDC

function cycle()
 if not invert then
   pio.pin.sethigh( ledpin )
   pio.pin.setlow( ledpin )
 tmr.delay( 0, 500000 )
 if not invert then
   pio.pin.setlow( ledpin )
   pio.pin.sethigh( ledpin )
 tmr.delay( 0, 500000 )

pio.pin.setdir( pio.OUTPUT, ledpin )
print( "Hello from eLua on STM32F4 Discovery" )
print "Watch the red led blinking :)"
print "Press the Disco Reset Button to end this demo.\n"

while 1
do  cycle()


  • Positives
  • Not so positives
    • File upload is via Xmodem, which is painful with Minicom, but there are probably better ways.
    • Requires a 260KB Flash image, this makes it unusable on any MCU with less than 512KB Flash. By Contrast Mecrisp-Stellaris only requires a Flash image of 20KB, making it perfect for inexpensive MCUS with as little as 32KB Flash.
    • Garbage collection is required which means that there will be delay while this is done, possibly a few mS, making this non real time.
    • Manual testing is tedious like Micropython due to the language requirements

Armpit Scheme

This looked promising when installed on a STM32F4 Discovery, but only partially ran.


I would have been interested in Micropython if I hadn’t already seen the Forth light a few years ago.

For instance, if I want to turn a led on or off with Forth, I’ll make a ‘lon’ and ‘loff’ Word that I use during manual testing, and change it to something like ‘overspeed-indicator-led-on’ (or off) when it’s debugged and part of a lower level Word where the naming is everything.

With Microptyhon I’d find ‘l.on()’ and ‘l.off()’ too tedious for on the fly manual typing during testing as it involves double the keys and two shifts. I’d be trapped in a non extensible language again where the problem solution still looks like the same language I started with.

I’m a hardware guy, I’ll have the keyboard balanced on the scope, trying to avoid the hot soldering iron and my coffee as I’m developing, so I want the most for the least when I type.

eLua on Cortex M4 is not a bad effort either, but requires similar resources to Micropython.

Armpit-Scheme is still dead and stuck in 2014.

In summary, I can only find two competitors for Forth, and neither of them will even run on any MCU with less than 256K Flash.

Not to mention lack of speed, ram usage, garbage collection issues and so on ...

In the small embedded end of the market, this means that Forth really has no interactive competitors, so nothing has changed that I can see.