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.

Table 1. Generic components
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

XMODEM support

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

ANSI terminal support

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

TCP/IP support

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

Lua and command line history

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:

Table 2. LM3S 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

Table 3. STM32 specific components
Key Parameters Meaning

stm32_enc

None (true or false)

Enable support for the STM32 timer encoder module

Table 4. LPC17xx specific components
Key Parameters Meaning

lpc17xx_semifs

None (true or false)

Enable support for the semifs file system (mbed only)

Table 5. AVR32 specific components
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.

Table 6. Generic configuration data
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:

Table 7. LM3S specific configuration data
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:

Table 8. Module configuration section
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:

  1. 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.

  2. 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.

  3. 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.