Configuring the image
The eLua configurator
(new in 0.10) The configurator is used to configure your eLua image by specifying the various modules and components that will be part of the eLua firmware image, as well as their specific parameters. It replaces the old configuration mechanism (based on editing platform_conf.h files) with a number of improvements:
-
the configuration is specified using Lua files, with a simple to understand syntax
-
configuration consistency checks are build in the configurator
-
better module selection system
-
easier customization
The configurator works by reading a Lua based board configuration file and generating the corresponding C header file (which for the most part has the same role as the platform_conf.h file that was used before the configurator). The board name is given by the board argument to build_elua (see this link for more details about building your eLua image). The configurator looks for a file named <board>.lua in two locations:
-
boards/custom is searched first. The files under this directory are not part of the eLua source tree, so this is the place where you can add configuration files for your custom board or customize the configuration for one of the standard boards (see here for more details about this).
-
boards/known is searched if <board>.lua is not found in boards/custom. It contains the configuration of the boards on which eLua is known to run properly. The files under this directory are part of the eLua source tree.
After finding <board>.lua in one of these locations, the configurator runs and generates the corresponding header file in boards/headers/board_<board>.h. The files under boards/headers are also not part of the eLua source tree, so they can be edited manually if needed (see here for more details). After this, the configurator is done and the build process continues with the usual steps (compiling and linking the source files).
Configuring the build
The build is configured using a Lua file. The Lua file contains code that must return the board configuration as a regular Lua table. An example for the mbed board is given below:
-- MBED build configuration return { cpu = 'lpc1768', components = { sercon = { uart = 0, speed = 115200 }, romfs = true, shell = true, term = { lines = 25, cols = 80 }, linenoise = { shell_lines = 10, lua_lines = 50 }, rpc = { uart = 0, speed = 115200 }, adc = { buf_size = 4, first_timer = 0, num_timers = 4 }, xmodem = true, lpc17xx_semifs = true }, config = { egc = { mode = "alloc" }, ram = { internal_rams = 2 } }, modules = { generic = { 'all', "-spi", "-can", "-i2c", "-net" }, platform = 'all', } }
As can be seen, a configuration for a board contains a number of sections:
-
cpu: the CPU of the board
-
components: the components and their configuration
-
config: other configuration items
-
modules: list of Lua modules that will be part of the build
The next section will explain each of the above items (and some that are not present in the above mbed configuration file) in detail. Please keep in mind that the best way to understand the configurator (besides reading this document) is to look at the existing configurations in board/known.
Configuring the CPU
The CPU is given by the cpu key in the configuration table. The CPU must be already known to the build system. A list of the known CPUs can be found in the build_data.lua file in the platform_list table.
Configuring the components
The various components that will be part of the eLua firmware image are given as a table under the components section in the main configurator table. The list of components known to the configurator, as well as their configuration parameters are listed in the table below. Some parameters have default values; if this is the case, the default values are written in bold. Also, some parameters are required, others are optional. Optional parameters are written over a grey background. All the required timer ID attributes that are not specified in the configuration default to the system timer ID.
Key | Parameters | Meaning |
---|---|---|
romfs |
None (true or false) |
Enable the ROMFS file system |
wofs |
None (true or false) |
Enable the WOFS file system |
shell |
None (true or false) |
Enable the simple shell |
advanced_shell |
None (true or false) |
Enable the advanced shell |
sercon |
Serial console (console over UART) |
|
uart |
Serial console UART ID |
|
speed |
Serial port speed |
|
timer (systimer) |
ID of the timer used by the serial console subsystem |
|
flow (none,rts,cts,rtscts) |
Flow control on the console UART |
|
buf_size |
Buffer size of the console UART. Must be a power of 2. |
|
xmodem |
||
uart |
XMODEM UART ID (same as sercon.uart) |
|
speed |
XMODEM UART speed (same as sercon.speed) |
|
timer (systimer) |
XMODEM timer ID (same as sercon.timer) |
|
flow (none,rts,cts,rtscts) |
Flow control on the XMODEM UART (same as sercon.flow) |
|
buf_size |
Buffer size of the XMODEM UART (same as sercon.buf_size) |
|
term |
||
uart |
Term UART ID (same as sercon.uart) |
|
speed |
Term UART speed (same as sercon.speed) |
|
timer (systimer) |
Term timer ID (same as sercon.timer) |
|
flow (none,rts,cts,rtscts) |
Flow control on the term UART (same as sercon.flow) |
|
buf_size |
Buffer size of the term UART (same as sercon.buf_size) |
|
lines |
Number of lines in the terminal |
|
cols |
Number of columns in the terminal |
|
cints |
None (true or false) |
Enable support for eLua generic interrupts in C |
luaints |
Enable support for eLua generic interrupts in Lua |
|
queue_size (32) |
Size of Lua interrupt queue. Must be a power of 2. |
|
tcip |
||
ip |
IP of the board (for static IP configuration) |
|
netmask |
Network mask (for static IP configuration) |
|
gw |
Default gateway (for static IP configuration) |
|
dns |
Name server address (for static IP configuration) |
|
dns |
None (true or false) |
DNS resolver support |
dhcp |
None (true or false) |
Enable the DHCP client (dynamic IP configuration) |
tcpipcon |
None (true or false) |
Enable the telnet client |
linenoise |
||
shell_lines |
Number of lines from shell kept in history |
|
lua_lines |
Number of lines from Lua kept in history |
|
autosave_file |
After the Lua shell exits, the Lua history buffer will be automatically saved in the file with this name |
|
rfs |
Enable the remote file system. |
|
uart |
RFS UART ID |
|
speed |
RFS UART speed |
|
timer (systimer) |
ID of the timer used by the RFS implementation |
|
flow (none,rts,cts,rtscts) |
Flow control on the RFS UART |
|
buf_size |
Buffer size of the RFS UART. Must be a power of 2. |
|
timeout (usecs,100000) |
Timeout for RFS operations |
|
mmcfs |
Enable the MMC file system. |
|
spi (int or array of ints) |
ID(s) of the SPI interface used by the SD card |
|
cs_port (int or array of ints) |
Port number(s) of the SD card /CS line |
|
cs_pin (int or array of ints) |
Pin number(s) of the SD card /CS line |
|
rpc |
Enable the remote procedure call subsystem. The parameters are only required when booting in RPC server mode. |
|
uart |
RPC UART ID |
|
speed |
RPC UART speed |
|
timer (systimer) |
ID of the timer used by the RPC implementation |
|
sermux |
Enable the serial multiplexer |
|
uart |
ID of the serial multiplexer physical UART |
|
speed |
Speed of the serial multiplexer physical UART |
|
flow |
Flow control on the serial multiplexer physical UART |
|
buf_sizes (array) |
Buffer sizes for virtual UARTs. Each size must be a power of 2. |
|
adc |
Enable ADC support in eLua |
|
buf_size |
ADC sample buffer size. Must be a power of 2. |
As can be seen in the table above, some of the parameters are common to more than one component. For example, CON_UART_ID is shared between sercon, xmodem and term. It is enough to define a shared attribute only once (in one of the components). For example:
components = { sercon = { uart = 0, speed = 115200 }, term = { lines = 25, cols = 80 }, xmodem = true }
If you were to redefine a shared attribute to a different value:
components = { sercon = { uart = 0, speed = 115200 }, term = { lines = 25, cols = 80, uart = 1 }, xmodem = true }
you’d get a warning from the configurator:
[CONFIG] WARNING: overriding value of attribute 'uart' in element 'term' from '0' to '1' in section 'components'
Besides the generic components in the table above, each platform can specify its own list of platform-specific components:
Key | Parameters | Meaning |
---|---|---|
cdc |
None (true or false) |
Enable UART over CDC (USB to serial) |
lm3s_pio |
None (true or false) |
Enable the LM3S platform specific PIO support |
lm3s_disp |
None (true or false) |
Enable support for the LCD display on EK-LM3S1968, EK-LM3S6965 or EK-LM3S8962 |
Key | Parameters | Meaning |
---|---|---|
stm32_enc |
None (true or false) |
Enable support for the STM32 timer encoder module |
Key | Parameters | Meaning |
---|---|---|
lpc17xx_semifs |
None (true or false) |
Enable support for the semifs file system (mbed only) |
Key | Parameters | Meaning |
---|---|---|
cdc |
None (true or false) |
Enable UART over CDC (USB to serial) |
avr32_rtc |
None (true or false) |
Enable the AVR32 platform specific RTC module |
avr32_lcd |
None (true or false) |
Enable the AVR32 character display module (Mizar32) |
Configuration data
The config section contains various build time configuration data. The list of the known configuration data items, as well as their parameters are listed in the table below. Some parameters have default values; if this is the case, the default values are written in bold. Also, some parameters are required, others are optional. Optional parameters are written over a grey background.
Key | Parameters | Meaning |
---|---|---|
vtmr |
Enable support for virtual timers |
|
num (0) |
Number of virtual timers |
|
freq (Hz, 1) |
Virtual timer frequency |
|
egc |
Configure the emergency garbage collector |
|
mode (disable, alloc, limit, always) |
EGC activation mode |
|
limit (bytes) |
EGC activation memory limit |
|
ram |
Memory allocator configuration (RAM data) |
|
internal_rams (1) |
Number of MCU non-contiguous RAM areas |
|
ext_start (array of integers) |
Array of starting addresses for external RAM areas |
|
ext_size (array of integers) |
Array of sizes sof external RAM areas |
Besides the generic configuration items in the table above, each platform can specify its own list of platform-specific configuration items:
Key | Parameters | Meaning |
---|---|---|
lm3s_adc_timers |
Timer configuration for the ADC subsystem. |
|
first_timer (0) |
ID of the first timer used by the ADC subsystem |
|
num_timers (NUM_TIMER) |
Total number of timers used by the ADC subsystem |
Lua modules
The configurator has support for fine-grained selections of the Lua modules that are going to be part of the eLua firmware. It knows how to handle generic modules and platform specific modules (see here for more details about generic and platform specific modules). The modules are specified by the modules section of the configuration file:
Key | Parameters | Meaning |
---|---|---|
generic |
Array of module names |
The generic modules included in the image |
platform |
Array of module names |
The platform modules included in the image |
The module chooser knows how to differentiate between 3 categories of modules:
-
Lua modules: the standard Lua modules that are compiled in eLua (math, io, string, table, debug, package, co). These can be referenced as a group under the name all_lua.
-
Generic eLua modules: these are adc, bit, can, cpu, elua, i2c, pack, mrpc, net, pd, pio, pwm, spi, term, tmr, uart. These can be referenced as a group under the name all_elua.
-
Platform specific eLua modules: these are added by each platform as needed.
Besides the names above, the group name all can be used in both platform and generic:
-
if used in generic, all is equivalent with all_lua + all_elua (all the standard Lua modules and the generic eLua modules)
-
if used in platform, all is a list of all the platform specific modules.
A module name can be prefixed with a dash (-) if that module must be excluded from the image instead of being included. Generally, this makes sense only when a group name (all, all_lua or all_elua) is also used in the list of modules. A few examples will help clarify this:
modules = { generic = 'all', platform = 'all' }
Include all the modules (generic and platform specific) in the image.
modules = { generic = { 'math', 'io', 'string', 'uart', 'pio' } }
Include the Lua modules math, io and string and the eLua modules uart and pio in the image.
modules = { generic = { 'all_lua', 'uart', 'pd' }, platform = 'all' }
Include all the Lua modules, as well as the eLua generic modules uart and pd. Also include all the platform specific modules.
modules = { generic = { 'all_lua', '-debug', 'all_elua', '-net', '-can' }, platform = 'disp' }
Include all the Lua modules except debug and all the generic eLua modules except net and can in the image. Also include the LM3S platform specific disp module, which will be accesible via lm3s.disp. Of course, this only works if the platform corresponding to the board is LM3S. For a list of the currently available platform-specific modules, check the status page.
Additional header files
As previously explained, the configurator compiles the Lua board description file into a C header file (board_<board>.h) that is later used to compile the eLua firmware. If additional headers must be included in the generated header file, they can be specified in the headers section:
headers = { "specific1.h", "specific2.h" }
Additional C macros
Besides the macros generated by the configurator, it is sometimes useful to add other macros to the board_<board>.h file. These can be specified in the macros section. If present, macros must be a table with two kinds of keys:
-
strings: these define simple macros (macros without a value)
-
arrays with two entries: these define macros with values.
For example, this definition:
macros = { 'MACRO1', { 'MACRO2', 0 } }
will be compiled into this:
#define MACRO1 #define MACRO2 0
CPU module constants
The eLua cpu module has support for exposing various CPU related constants as keys in the cpu table. These are used, for example, to access the generic interrupt components from Lua. The CPU constants in this module are generally defined by the various eLua platforms, but there is support in the configuration file to add new CPU constants if needed. These are specified as part of the cpu_constants section. Much like the macro configurator, there are two types of constants that can be given in cpu_constants:
-
constants already defined are given by their corresponding macro name
-
new constants are given as an array with two entries. These are first defined, then included in the constant list
For example, this definition:
cpu_constants = { 'CPU1', { 'NEWC', '10' } }
will be compiled into this:
#ifndef NEWC #define NEWC 10 #endif #define PLATFORM_CPU_CONSTANTS_CONFIGURED\ _C( CPU1 ),\ _C( NEWC ),\
Build options
The build section of the configurator contains options that will be passed directly to the builder. The following keys of the build table are recognized by the builder: target, allocator, optram, boot, romfs, cpumode, bootloader (note that allocator is also inferred automatically from the number of non-contigours RAM regions specified in the configuration data section). For more details about these options, see the documentation on invoking the build system.
Customizing configurations
If a custom build configuration (one that is not present in boards/known) is needed, one way to handle this is to write the new configuration file from scratch. However, starting from a known configuration and customizing it might be a better way to approach this task. The main thing to remember is that configurations are written in Lua, so you can use Lua code to manipulate them directly. For example, suppose that your hardware is almost identical to an mbed board, but the console is on UART1 instead of UART0. You could simply copy _boards/known/mbed.lua to boards/custom (remember that boards/custom is not part of source control, so this is the place to put your custom configuration files) and modify the uart attribute of sercon. If you want to avoid duplication, you can simply "inherit" the basic mbed configuration and change only what you need:
-- File boards/custom/myboard.lua local t = dofile( "boards/known/mbed.lua" ) t.components.sercon.uart = 1 return t
Of couse, you can use any kind of Lua code in the configuration file. You can download the configuration from the Internet, make the whole configuration process interactive by asking the user to enter the configuration parameters at build time and so on.
Editing the configuration manually
While the configurator is designed to cover the complete set of eLua build configuration parameters, there might be rare occasions when there is a need to edit the generated configuration file manually, in order to cover functionality not provided by the configurator. There is a simple way to do this in conjuction with the build system:
-
use the configurator to generate a configuration file starting from the board description file by using the build system’s config_only=true command line parameter.
-
edit the generated boards/headers/board_<board>.h to suit your needs.
-
run the build completely, but using skip_conf=true to prevent the configurator from generating a header file and using the one edited manually in the previous step instead.
You need to be familiar with the eLua internals in order to properly modify the configuration file, so using this method carelessly might render your image unbuildable or unusable.