Welcome to the official eLua FAQ! It is assumed that you already know what eLua is, so here's a list of questions you might find useful while exploring eLua.
What's the deal with floating-point Lua and integer only Lua?
Will you ever post instructions about how to compile toolchains under Cygwin in Windows?
I get "out of memory" errors when I run my Lua programs, what should I do?
Q: How can I learn Lua? Is it hard?
A: Lua is a minimalistic language (yet very powerful) which is quite easy to learn. Once you understand the basic concepts you'll find yourself writing Lua programs in notime. The main resource is the Lua homepage. In the documentation page you'll find the reference manual and the first version of the excellent "Programming in Lua" book. I recommend purchasing the second version of this book, since it's likely that this is all you'll ever need to learn Lua. Another very good resource is the Lua wiki. If you need more help, check the community page. Lua has a very friendly and active community.
Q: I see a lot of files in the docs/ directory of the eLua source distribution, and I'm not sure how I should read them. Is there a recommened reading order?
A: It depends:
- if you just want to build eLua, reading building.txt (or, alternatively, this page) should be enough.
- if you want to take control of what's getting built in your eLua image, read elua_components.txt and platform_modules.txt.
- if you want to know what goodies you're getting from eLua, read the_elua_shell.txt, generic_modules.txt, platform_modules.txt, the_rom_file_system.txt and tcpip_in_elua.txt.
- if you want to add a new I/O interface to eLua, read console_input_output.txt and terminal_support.txt.
- if you want to add a new platform to eLua, read all of the above plus platform_interface.txt and adding_a_new_platform.txt.
A: OK, so I lied, this is NOT a frequently asked question :) However, if you really want to help eLua, keep in mind that we're looking for developers. eLua has many ambitious goals, so it would be great to have more people working on it. Take a look at the roadmap page, and if you see something there that you'd like to implement, don't hesitate to contact us. Also, if you'd like to make a donation to the project (money, or maybe a development board) rest assured that wwe won't say no :) It also helps a lot if you test eLua on your own board and you find a bug or an incomplete feature. Or if you just thought about a cool feature that you'd like to see in eLua. If so, feel free to contact us.
Q: Can I use eLua in my commercial, closed source project?
A: No. Since eLua is licensed under GPL, you can't use it in a commercial closed source project. You can use it in a commercial application if you make your source code public. However, if all goes as planned, this will change soon enough. I won't give any details just yet, but keep on watching the project. You know, just in case ... :)
A: This pretty much depends on what you expect. If you expect your Lua code to run as fast as your compiled C code, this won't happen, simply because C is a compiled language, while Lua is an interpreted language. That said, you'll be happy to know that Lua is one of the fastest interpreted languages out there. If you really need both high speed and Lua, you can write your speed critical code sections in C and export them as a Lua module. This way you get the best of both worlds. I don't have any official benchmarks about Lua speed on embedded devices, but you might want to check the TV-B-Gone example on the examples page. TV-B-Gone is a "software remote control" application coded directly in eLua. If you're familiar with the remote control protocols, you'll know that this kind of application is quite "real time", and delays in the order of milliseconds or even less can make your software remote control fail. Yet this sample runs without problems on a 50MHz Cortex (Thumb2) CPU. This should give you a fairly intuitive view on the speed of eLua.
Q: What are the minimum requirements for eLua?
A: It's hard to give a precise answer to this. As a general rule for a 32-bit CPU, I recommend at least 256k of Flash (program memory) and at least 64k of RAM. However, this isn't a strict requirement. A stripped down, integer-only version of eLua can definetely fit in 128k of Flash, and depending on your type of application, 32k of RAM might prove just fine. It largely depends on your needs.
Q: Since I'm using the Lua platform modules (uart, spi, pwm, tmr...), can I trust my peripheral code to run the same on all my platforms?
A: Unfortunately, no. While eLua makes it possible to have a common code on different platforms using the platform interface (docs/platform_interface.txt), it can't possibly provide the same functionality on all platforms, since all CPUs are not created equal. It is very recommended (and many times imperative) to have an understanding of the peripherals on your particular CPU before you write your code. This, of course, is not particular to eLua, but it's especially important since the platform interface might give the impression that it offers an uniform functionality over all platforms, when in fact the only thing in common is often just the interface itself (that is, the methods and variables you can access in a given module). eLua tries to help here by giving you an error when you try to access a physical resource that is not available (for example a timer, a PWM channel, or a PIO pin/port), but it doesn't try to cover all the possible platform-related issues, since this would increase the code size and complexity too much. These are some caveats that come to mind (note that these are only a few examples, the complete list is much longer):
- timers: from all the platforms on which eLua runs, only the Luminary Cortex CPUs has rock solid 32-bit timers. You can do pretty much everything you need with them. All the other platforms have 16-bit timers, which imposes some limits on the range of delays you can achieve with them. Make sure to use tmr.mindelay(id) and tmr.maxdelay(id) to check the actual resolution of your timers, and adapt your code accordingly. To 'compensate' for this, it's not possible to change the base timer frequency on the Cortex CPUs, but it is possible on most other platforms :) So be sure to also check the result of tmr.setclock(id)
- also, when using timers, remember that if you're using XMODEM and/or the "term" module, TMR0 is used by both of them. So, if you change the TMR0 base clock in your code, be sure to restore the original setting before returning to the shell. You can change this static timer assignment by modifying src/main.c. It might also be possible to change it dynamically in the future, although I see little use for this.
- PWM: the Cortex CPUs have 6 PWM channels, but channels 0/1, 2/3 and 4/5 respectively share the same base clock setting. So, when you're changing the base clock for channel 1, you're also changing the base clock for channel 0; if channel 0 was already running, you won't like what will happen next. This time no eLua function can save you, you simply need you know your CPU architecture.
- GPIO: only some platform have internal pullups for the GPIO pins, while Cortex is the only platform that also provides pulldowns for its GPIOs. However, in this case you're safe, as eLua will signal an error if you try to execute a pullup operatin on a platform that does not support it.
The lesson here is clear: understand your platform first!
Q: What's the deal with floating-point Lua and integer only Lua?
A: Lua is build around a number type. Every number in Lua will have this type. By default, this number type is a double. This means that even if your program only does integer operations, they will still be treated as doubles. On embedded platforms this is a problem, since the floating point operations are generally emulated in software, thus they are very slow. This is why eLua gives you "integer only Lua": a Lua with the default number type changed to long. The advantages are increased speed and smaller code size (since we can force Newlib to "cut" the floating point code from printf/scanf and friends, which has quite a strong impact on the code size) and increased speed. The downside is that you'll loose the ability to do any floating point operations.
Q: All your tutorials give instructions on how to compile eLua under Linux, yet you seem to use a lot of Windows tools. How come?
A: It's true that I do all the eLua development under Linux, since I find Linux an environment much more suited for development. At the same time it's true that most of the tools that come with my development boards run under Windows. So I choose to use the best of both world: I run Linux under an emulator and I do everything else under Windows. My emulator of choice is VirtualBox. It runs very well and I can do everything from the emulator without problems. And to make everything even more flexible, I keep my VirtualBox Ubuntu image on an external WD passport disk that I can carry with me wherever I go, so I can work on eLua whenever I have a bit of spare time :) (and yes, I know that technically speaking VirtualBox is not an emulator, but it makes no sense to get into details like this)
Q: Will you ever post instructions about how to compile toolchains under Cygwin in Windows?
A: If I ever have way too much spare time on my hands, yes. Otherwise, no. There are many reasons for this. As I already mentioned, I favour Linux over Windows when it comes to developing applications. Also, I noticed that the GNU based toolchains are noticeable slower on Cygwin than on Linux, so experimenting with them can prove frustrating. Also, compiling under Linux and Cygwin should be quite similar, so try starting from my Linux based tutorials, they might work as well on Cygwin.
Q: I know that Lua can be compiled to bytecode, so I compiled one of the eLua examples with luac and tried to run it on my eLua board, but it didn't work. Is this a bug in eLua?
A: This is not a bug in eLua, it's a bit more subtle than that. It's true that ARM and i386 are very similar when it comes to data types: all the fundamental data types have the same length, and they are both little endian. So, in theory, if you compile a Lua source file on PC you should be able to run the compiled bytecode on your eLua board without any modifications. But there's a problem here: the default double precision floating point representation is different on ARM and PC. So, while the two data types have the same endianess and size, they are represented differently in memory. This means that you can't use the "regular" luac compiler for this task. However, starting with version 0.5, you can cross-compile Lua code on PC to run on target. See docs/crosscompilation.txt if you want to know how to do this.
Q: Does eLua run only on ARM based CPUs?
A: Currently, yes, but this is not by design. eLua runs only on ARM CPUs right now because that's what I had access to. It can run on any other platform as long as there is Newlib support for that platform. For example, it could run very well on AVR32, which is a very likely future target for eLua. The main problem here is the Newlib dependency. Once this is eliminated, it will be able to run on a much larger range of platforms, including 8-bit CPUs (yes, this is actually possible, and personally I can't wait to see eLua running on my eZ80 board). But it will probably be a while until I manage to get rid of Newlib and provide a generic libc replacement.
Q: I get "out of memory" errors when I run my Lua programs, what should I do?
A: There are a number of things you can try to overcome this:
- precompile your source to bytecode: see docs/crosscompilation.txt for details. If you use bytecode instead of source code Lua won't need to compile your source, so you save some RAM.
- try to avoid using too many strings: strings are immutable in Lua. That means that a statement like s = s .. "\n" (where s is a string) will create a new string each time it's called. If this happens a lot (for example in a loop), your memory will quickly run out because of all the strings. If you really need to do frequent string operations, put them in a table and then use table.concat to make a string from your table.
- call 'collectgarbage' manually: if you're still running out of memory, try calling collectgarbage('collect') from your code, which will force a garbage collection and thus might free some memory.