Lua on Embedded Systems

Introduction

Quoting the creators: "Lua is a powerful, fast, lightweight, embeddable scripting language."
Lightweight means, that it takes about 150-250 kBytes on a PC. This is still a challenge
for small embedded systems running Nut/OS, specifically for the 8-bit AVR targets like
Ethernut 1 and 2.

In a first attempt, Laszlo Parrag succeeded in 2008 with implementing
a subset, that runs small Lua scripts on an ARM7 based board. The source
code of a Lua script had been stored in a local character array of a sample
Nut/OS application. After adding a few minor modifications, the Lua libraries
had been added to the official Nut/OS distribution, enabled for ARM CPUs only.
Not much happened to it since June 2009, when Nut/OS 4.9.2 beta became available.
This version is able to run a stand-alone Lua interpreter on most target systems,
including 8-bit AVRs. However, due to memory limitations, not all targets are
able to offer the full set of Lua standard libraries. The developer can use
the Nut/OS Configurator to enable or disable specific parts.

Lua Configuration

The Nut/OS Configurator had been enhanced with several items to adapt
Lua to the specific platform and the needs of the application. Btw. actually
the Configurator itself is driven by Lua scripts, and only these scripts had
been modified to add these new functions. But that's a different story.

The following screenshot shows the initial configuration. All Lua default
libraries are disabled, parser and dump are not excluded. With these
settings Nut/OS can run basic Lua source code.

Enabling Libraries

Disabling the libraries doesn't mean, that these libraries are not available.
The Configurator will still build them, but they will not be loaded automatically
by calling luaL_openlibs. Instead, the Nut/OS application can load individual
libraries by calling the related initialization function like luaopen_io or
luaopen_string.

Enabling Floating Point Support

In general Lua numbers are floating point values by default. This requires
some more memory space and, more important, significantly slows down execution
on embedded systems without floating point hardware. Therefore, number are
integer by default in Lua for Nut/OS.

You probably noticed that the item Floating Point Numbers is greyed out,
which means that you can't enable it without providing a specific requirement.
In this case you must enable Nut/OS floating point support for file streams
first. This will allow Lua to read and write floats.

Excluding Parser and Dump

The parser allows to directly execute Lua source code. Well, not really
directly. In fact the parser translates the source code to Lua binary
code first. This step could be done on a desktop computer and only the
binaries may be uploaded to the target. As you can imagine, this can
save a lot of RAM.

The Lua dump allows to display Lua binary code and is typically not required
by the final firmware. Excluding it saves a few kilobytes.

Unlike standard libraries, Lua parser and Lua dump will be completely removed,
if excluded. There is no way to load them by function calls in the application
during runtime.

TCP/IP Support

The highlighted configuration item in the screenshot above doesn't represent
a library. Instead it is an option of the I/O library and will be removed
from it unless enabled. More on this later.

Lua Interpreter

A standalone interpreter had been created as a Nut/OS sample application
to demonstrate the capabilities. It will read Lua source code and print
out results on the RS-232 port, which is available on most embedded boards.

The interpreter uses the new EdLine module of the Nut/OS Gorp library.
It is not yet documented. For now, have a look to the source code.

Lua Implementation

TCP Connections

There is no socket library available yet. Instead, the standard I/O library
had been extended by two additional functions. They allow to write basic
TCP servers and clients.

The Lua code for a client connecting port 80 at IP address 192.0.0.2 may look
like this: