Computing stuff tied to the physical world

Developing in Lua for STM32

Lua is a very interesting small programming language, in the same way as Perl, Python, Ruby, and Tcl are – i.e. a dynamically-typed “scripting language”. Here’s the blurb:

Lua combines simple procedural syntax with powerful data description constructs based on associative arrays and extensible semantics. Lua is dynamically typed, runs by interpreting bytecode for a register-based virtual machine, and has automatic memory management with incremental garbage collection, making it ideal for configuration, scripting, and rapid prototyping.

Lua’s implementation in C is also amazingly clean and small. So small in fact, that it supports a variant called eLua which fits in several moderately small microcontrollers.

With the ARMinARM installation, it’s a matter of starting up the ./setup script:

Fast start:
    [...]
    11) Upload elua.bin to ARMinARM board

… and selecting option 11 to upload eLua to the STM32F103. Once this is done, we will have an eLua system running on the µC, ready to accept, compile, and run Lua scripts. Quite an amazing feat, and there’s no need to “cross-compile” or build anything on the Raspberry Pi.

Here is a sample session, which uses the screen command to talk to the µC over serial:

$ screen /dev/ttyAMA0 115200
eLua# 

We end up in the eLua “shell”, which understands commands such as “help” and “ver”:

eLua# help
Shell commands:
  help   - shell help
  lua    - start a Lua session
  ls     - lists files and directories
  dir    - lists files and directories
  cat    - list the contents of a file
  type   - list the contents of a file
  recv   - receive files via XMODEM
  cp     - copy files
  ver    - show version information
  mkdir  - create directories
  wofmt  - WOFS format
  exit   - exit the shell
For more information use 'help <command>'.
eLua# ver
eLua version v0.9-214-g30ee5de
For more information visit www.eluaproject.net and wiki.eluaproject.net
eLua# 

There’s even a small built-in “rom filesystem” with some demo code:

eLua# ls

/wo

Total on /wo: 0 bytes

/rom
info.lua                       134 bytes
hello.lua                      116 bytes
hangman.lua                    3417 bytes

Total on /rom: 3667 bytes

And we can view the contents of such a file using the very Unix’y “cat” command:

eLua# cat /rom/hello.lua
-- eLua example
-- Hello World, the classic simplest example of a program on a framework

print( "Hello, World!" )

Let’s find out how we can launch such an example:

eLua# help lua
lua - start a Lua session
Usage: lua [-e <stat>] [-l <name>] [-i] [-v] [<script>]
  [<script>]: execute the given script.
  [-e <stat>]: execute string 'stat'.
  [-l <name>]: require library 'name'.
  [-i]: enter interactive mode after executing 'script'.
  [-v]: show version information.
Without arguments it executes the interactive Lua interpreter.

Excellent. As you can see, eLua is very good at helping us figure it out:

eLua# lua /rom/hello.lua
Press CTRL+Z to exit Lua
Hello, World!
eLua#

Woohoo! Signed, sealed, and delivered!

Now let’s go into “interactive mode” and try a few things of our own:

eLua# lua
Press CTRL+Z to exit Lua
Lua 5.1.4  Copyright (C) 1994-2011 Lua.org, PUC-Rio
> =1+1
2
> print(1/3)
0.33333333333333
> ^Z
eLua# 

As you can see, eLua supports double-precision floating point calculations. Serious stuff! Ok, it’s time for the blinking LED demo (using eLua’s excellent reference manual):

> pio.pin.setdir(pio.OUTPUT, pio.PB_0)
> repeat
>> pio.pin.setval(1-pio.pin.getval(pio.PB_0), pio.PB_0)
>> tmr.delay(nil, 1000000)
>> until false

And as we hit return, the LED starts blinking, 1 sec on / 1 sec off. That was easy.

Five lines of code, not bad! But that’s not the real story: the point is that we’re “sitting at the controls” now. We can type in commands, and try them out to see what happens!

As you can see, this environment is extremely conducive to experimentation (as Lua always is, and as scripting languages always are, in fact). You can just explore and try things out. And there’s a lot more to eLua than blinking an LED: ADC, DAC, I2C, SPI, PWM, CAN, etc.

There is a “Write Once File System” (WOFS) which is a simple mechanism for storing code and data “files” in flash memory. The twist being that it fills up gradually, and that you can only recover space by wiping all of WOFS and starting over (see the “/wo” area above).

This does allow storing a complete application in flash, which could then automatically be started up after reset. This way, a complete project can be saved on the STM32F103, ready to go as soon as it is powered up, completely independent of the Raspberry Pi. In the case of a “runaway” script, the Pi can still force the µC to reset and enter its serial boot loader.

The very limited RAM space imposes fairly strict limitations on what a Lua application can do, but within those constraints, this setup is amazingly powerful and “big computer” like.

For more information, visit the eLua website – in particular the bleeding edge pages.