-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Lua support #8434
Description
Description
There is an external developer who wants to build a modular piece of hardware with a coprocessor running RIOT, with potential to be a commercial product. For this, he wishes to use Lua to control part of it, and therefore Lua support could enable commercial use of RIOT. Additionally, dynamic language support (see also #7796 and #2968) could be an approach to achieve over-the-air update of an application and a multi-application development paradigm for the RAPstore project (RIOT app store).
There is a benefit/cost tradeoff: the above description is the benefit, and time spent to implement Lua support (and eg not develop other features) is the cost. Therefore part of the earlier stages of development will be to judge the total amount of time that would be required.
Approach
The current approach followed is to adapt other FOSS projects which have implemented Lua in an embedded context. The ones that have been considered are as follows.
-
Currently the most promising vector of approach seems to be to use the LuaRTOS project, where the Lua engine has been implemented on top of FreeRTOS, including a range of API bindings we would need to implement such as I2C, ADCs, and LoRAWAN. They have implemented supporting threads which can handle concurrent Lua programs with the same Lua state. The project would probably be pretty stable (as it is developed by a company, Whitecat, and used in their commercial product), and it is currently under active development. It also uses Google Blockly, a simple graphical programming language which is being considered to develop RIOT programs in Javascript. It uses a BSD license and the build system is based on Make.
-
NutOS also includes a Lua interpreter on top of an RTOS. It also uses a BSD license and a make-based build system. However, the Lua engine is not under current development (with the last substantial work done in 2012) and it seems that there is no implementation of supporting threads, just a callable library of functions.
-
eLua, a standalone Lua runtime environment for embedded devices, was also investigated in some detail. However, it was clear that the Lua interpreter was not designed to be separated from the rest of the program (which was designed to be loaded onto a microchip on its own, not used on top of an RTOS). Some of the reasons for this, along with other reasons that suggested that eLua wouldn't be a suitable approach, are as follows:
-
eLua is very ingrained in its own build system and intended to be built as a whole with it, which means that picking components out and building them separately was difficult. I tried porting using the eLua build system but came across an issue where there were symbols defined in the eLua linker files which were used in core functions. Which meant that I couldn't link the generated object files with the rest of RIOT using the RIOT build system. This was found fairly immediately and suggested that it wouldn't have been the only issue I would have come across by using this approach.
-
The eLua build system is based on Lua and depends on some Lua libraries too, introducing several dependencies for users to use this library.
-
I also tried using RIOT's build system to build using source files from eLua. As would be expected there were a range of errors to sort out including eLua specific typedefs, #defines, generated header files, and cflags, so this would also have proved to be a lot of work.
-
The eLua "sim" configuration, which is their simulator which runs on Linux, is currently not working. This is because eLua has a dependency on newlib, which doesn't work on Linux. Someone tried "hard" to fix this but failed: reent.h is missing elua/elua#108. This makes a port to RIOT native difficult
-
Design and implementation
Currently, development is proceeding using LuaRTOS as a starting point. As a very high level set of milestones, the approach will be as follows:
- Get the relevant LuaRTOS files building into a binary with the rest of RIOT
- Get a simple Lua function working (e.g. serial print or LED flash)
- Implement the RIOT API bindings
Regarding how the lua commands and code are input, there are a few options:
- manual input via RIOT shell
- lua scripts in an example directory at compile time
- lua scripts able to be dynamically loaded into RAM
Which of these are going to be implemented needs considering
Issues
- Lua is an interpreted language, which inherently requires dynamic allocation, in case e.g. callbacks are redefined during runtime. We try and avoid dynamic memory allocation as far as possible. We should keep an eye on how Lua handles this without potentally running out of heap space.