1
0
mirror of https://github.com/elua/elua.git synced 2025-01-25 01:02:54 +08:00

Merge branch 'luabuild' of vps.eluaproject.net:elua into luabuild

This commit is contained in:
Bogdan Marinescu 2012-07-14 13:53:47 +03:00
commit 97d9cac313
43 changed files with 2141 additions and 845 deletions

2
.gitignore vendored
View File

@ -19,3 +19,5 @@ inc/git_version.h
*~
*.*~
luac.cross*
boards/*.h

3
boards/custom/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*
!.gitignore

3
boards/headers/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*
!.gitignore

26
boards/known/elua-puc.lua Normal file
View File

@ -0,0 +1,26 @@
-- eLua-PUC board build configuration
return {
cpu = 'lpc2468',
components = {
sercon = { uart = 0, speed = 115200, buf_size = 128 },
romfs = true,
shell = true,
term = { lines = 25, cols = 80 },
cints = true,
luaints = true,
linenoise = { shell_lines = 10, lua_lines = 50 },
rpc = { uart = 0, speed = 115200 },
adc = { buf_size = 4, first_timer = 0, num_timers = 4 },
xmodem = true
},
config = {
vtmr = { num = 4, freq = 4 },
extmem = { start = { 0xA0000000 }, size = { 8 * 1048576 } }
},
modules = {
generic = 'all',
exclude_generic = { "i2c", "net", "spi", "can" },
}
}

29
boards/known/et-stm32.lua Normal file
View File

@ -0,0 +1,29 @@
-- ET-STM32 build configuration
return {
cpu = 'stm32f103re',
components = {
sercon = { uart = 0, speed = 115200, buf_size = 128 },
wofs = true,
romfs = true,
shell = true,
term = { lines = 25, cols = 80 },
cints = true,
luaints = true,
linenoise = { shell_lines = 10, lua_lines = 50 },
stm32_enc = true,
rpc = { uart = 0, speed = 115200 },
adc = { buf_size = 4 },
xmodem = true
},
config = {
egc = { mode = "alloc" },
vtmr = { num = 4, freq = 10 },
},
modules = {
generic = 'all',
exclude_generic = { "i2c", "net" },
platform = 'all',
}
}

16
boards/known/mod711.lua Normal file
View File

@ -0,0 +1,16 @@
-- MOD711 build configuration
return {
cpu = 'str711fr2',
components = {
sercon = { uart = 1, speed = 38400, timer = 0 },
romfs = true,
shell = true,
term = { lines = 25, cols = 80 },
xmodem = true
},
modules = {
generic = { 'pio', 'tmr', 'pd', 'pwm', 'uart', 'term', 'pack', 'bit', 'elua', 'cpu', 'math' }
}
}

16
boards/known/sim.lua Normal file
View File

@ -0,0 +1,16 @@
-- eLua simulator running on linux
return {
cpu = 'linux',
components = {
sercon = { uart = 0, speed = 0 },
wofs = true,
romfs = true,
shell = true,
term = { lines = 25, cols = 80 },
},
modules = {
generic = { 'pd', 'math', 'term', 'elua' }
}
}

View File

@ -0,0 +1,30 @@
-- STM3210E-EVAL build configuration
return {
cpu = 'stm32f103ze',
components = {
sercon = { uart = 0, speed = 115200, buf_size = 128 },
wofs = true,
romfs = true,
shell = true,
term = { lines = 25, cols = 80 },
cints = true,
luaints = true,
linenoise = { shell_lines = 10, lua_lines = 50 },
stm32_enc = true,
rpc = { uart = 0, speed = 115200 },
adc = { buf_size = 4 },
xmodem = true,
mmcfs = { cs_port = 0, cs_pin = 8, spi = 0 }
},
config = {
egc = { mode = "alloc" },
vtmr = { num = 4, freq = 10 },
},
modules = {
generic = 'all',
exclude_generic = { "i2c", "net" },
platform = 'all',
}
}

163
build_data.lua Normal file
View File

@ -0,0 +1,163 @@
-- eLua build data
-- This contains various build time information:
-- supported toolchains
-- supported platforms and CPUs
module( ..., package.seeall )
local utils = require "utils"
-------------------------------------------------------------------------------
-- Build data
-- List of toolchains
local toolchain_list =
{
[ 'arm-gcc' ] = {
compile = 'arm-elf-gcc',
link = 'arm-elf-ld',
asm = 'arm-elf-as',
bin = 'arm-elf-objcopy',
size = 'arm-elf-size',
cross_cpumode = 'little',
cross_lua = 'float_arm 64',
cross_lualong = 'int 32',
version = '--version'
},
[ 'arm-eabi-gcc' ] = {
compile = 'arm-eabi-gcc',
link = 'arm-eabi-ld',
asm = 'arm-eabi-as',
bin = 'arm-eabi-objcopy',
size = 'arm-eabi-size',
cross_cpumode = 'little',
cross_lua = 'float 64',
cross_lualong = 'int 32',
version = '--version'
},
codesourcery = {
compile = 'arm-none-eabi-gcc',
link = 'arm-none-eabi-ld',
asm = 'arm-none-eabi-as',
bin = 'arm-none-eabi-objcopy',
size = 'arm-none-eabi-size',
cross_cpumode = 'little',
cross_lua = 'float 64',
cross_lualong = 'int 32',
version = '--version'
},
[ 'avr32-gcc' ] = {
compile = 'avr32-gcc',
link = 'avr32-ld',
asm = 'avr32-as',
bin = 'avr32-objcopy',
size = 'avr32-size',
cross_cpumode = 'big',
cross_lua = 'float 64',
cross_lualong = 'int 32',
version = '--version'
},
[ 'avr32-unknown-none-gcc' ] = {
compile = 'avr32-unknown-none-gcc',
link = 'avr32-unknown-none-ld',
asm = 'avr32-unknown-none-as',
bin = 'avr32-unknown-none-objcopy',
size = 'avr32-unknown-none-size',
cross_cpumode = 'big',
cross_lua = 'float 64',
cross_lualong = 'int 32',
version = '--version'
},
[ 'i686-gcc' ] = {
compile = 'i686-elf-gcc',
link = 'i686-elf-ld',
asm = 'nasm',
bin = 'i686-elf-objcopy',
size = 'i686-elf-size',
cross_cpumode = 'little',
cross_lua = 'float 64',
cross_lualong = 'int 32',
version = '--version'
}
}
-- Toolchain Aliases
toolchain_list[ 'devkitarm' ] = toolchain_list[ 'arm-eabi-gcc' ]
-- List of acrhitectures and their endianness
local arch_data = {
arm = 'little',
cortexm3 = 'little',
cortexm4 = 'little',
avr32 = 'big',
i386 = 'little'
}
-- Toolchain to arch mapping
local toolchain_map = {
arm = { 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' },
cortexm3 = { 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' },
cortexm4 = { 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' },
avr32 = { 'avr32-gcc', 'avr32-unknown-none-gcc' },
i386 = { 'i686-gcc' }
}
-- List of platform/CPU combinations
local platform_list =
{
at91sam7x = { cpus = { 'AT91SAM7X256', 'AT91SAM7X512' }, arch = 'arm' },
lm3s = { cpus = { 'LM3S1968', 'LM3S8962', 'LM3S6965', 'LM3S6918', 'LM3S9B92', 'LM3S9D92' }, arch = 'cortexm3' },
str9 = { cpus = { 'STR912FAW44' }, arch = 'arm' },
i386 = { cpus = { 'I386' }, arch = 'i386' },
sim = { cpus = { 'LINUX' }, arch = 'i386' },
lpc288x = { cpus = { 'LPC2888' }, arch = 'arm' },
str7 = { cpus = { 'STR711FR2' }, arch = 'arm' },
stm32 = { cpus = { 'STM32F103ZE', 'STM32F103RE' }, arch = 'cortexm3' },
avr32 = { cpus = { 'AT32UC3A0128', 'AT32UC3A0256', 'AT32UC3A0512', 'AT32UC3B0256' }, arch = 'avr32' },
lpc24xx = { cpus = { 'LPC2468' }, arch = 'arm' },
lpc17xx = { cpus = { 'LPC1768' }, arch = 'cortexm3' }
}
-- Returns the platform of a given CPU
function get_platform_of_cpu( cpu )
for p, v in pairs( platform_list ) do
if utils.array_element_index( v.cpus, cpu:upper() ) then return p end
end
end
-- Return all the CPUs in the 'platform_list' table
function get_all_cpus()
local t = {}
for pl, desc in pairs( platform_list ) do
for _, cpu in pairs( desc.cpus ) do
if not utils.array_element_index( t, cpu ) then t[ #t + 1 ] = cpu end
end
end
return t
end
-- Returns the complete list of toolchains
function get_all_toolchains()
local t = {}
for arch, chains in pairs( toolchain_map ) do
for _, cname in pairs( chains ) do
if not utils.array_element_index( t, cname ) then t[ #t + 1 ] = cname end
end
end
return t
end
-- Returns the list of toolchains for a given platform
function get_toolchains_of_platform( platform )
return toolchain_map[ platform_list[ platform ].arch ]
end
-- Returns the data of the given toolchain
function get_toolchain_data( name )
return toolchain_list[ name ]
end
-- Returns the endianness of the given platform
function get_endianness_of_platform( platform )
return arch_data[ platform_list[ platform ].arch ]
end

View File

@ -20,6 +20,10 @@
local args = { ... }
local b = require "utils.build"
local mkfs = require "utils.mkfs"
local bconf = require "config.config"
local board_base_dir = "boards"
local bd = require "build_data"
builder = b.new_builder()
utils = b.utils
sf = string.format
@ -75,143 +79,30 @@ function addlib( data )
end
-------------------------------------------------------------------------------
-- Build data
-- List of toolchains
local toolchain_list =
{
[ 'arm-gcc' ] = {
compile = 'arm-elf-gcc',
link = 'arm-elf-ld',
asm = 'arm-elf-as',
bin = 'arm-elf-objcopy',
size = 'arm-elf-size',
cross_cpumode = 'little',
cross_lua = 'float_arm 64',
cross_lualong = 'int 32',
version = '--version'
},
[ 'arm-eabi-gcc' ] = {
compile = 'arm-eabi-gcc',
link = 'arm-eabi-ld',
asm = 'arm-eabi-as',
bin = 'arm-eabi-objcopy',
size = 'arm-eabi-size',
cross_cpumode = 'little',
cross_lua = 'float 64',
cross_lualong = 'int 32',
version = '--version'
},
codesourcery = {
compile = 'arm-none-eabi-gcc',
link = 'arm-none-eabi-ld',
asm = 'arm-none-eabi-as',
bin = 'arm-none-eabi-objcopy',
size = 'arm-none-eabi-size',
cross_cpumode = 'little',
cross_lua = 'float 64',
cross_lualong = 'int 32',
version = '--version'
},
[ 'avr32-gcc' ] = {
compile = 'avr32-gcc',
link = 'avr32-ld',
asm = 'avr32-as',
bin = 'avr32-objcopy',
size = 'avr32-size',
cross_cpumode = 'big',
cross_lua = 'float 64',
cross_lualong = 'int 32',
version = '--version'
},
[ 'avr32-unknown-none-gcc' ] = {
compile = 'avr32-unknown-none-gcc',
link = 'avr32-unknown-none-ld',
asm = 'avr32-unknown-none-as',
bin = 'avr32-unknown-none-objcopy',
size = 'avr32-unknown-none-size',
cross_cpumode = 'big',
cross_lua = 'float 64',
cross_lualong = 'int 32',
version = '--version'
},
[ 'i686-gcc' ] = {
compile = 'i686-elf-gcc',
link = 'i686-elf-ld',
asm = 'nasm',
bin = 'i686-elf-objcopy',
size = 'i686-elf-size',
cross_cpumode = 'little',
cross_lua = 'float 64',
cross_lualong = 'int 32',
version = '--version'
}
}
-- Return the full path of a board configuration file
local function get_conf_file_path( bname )
local known_board_name = utils.concat_path( { board_base_dir, "known", bname .. ".lua" } )
local custom_board_name = utils.concat_path( { board_base_dir, "custom", bname .. ".lua" } )
if utils.is_file( custom_board_name ) then return custom_board_name end
if utils.is_file( known_board_name ) then return known_board_name end
assert( sf( "board configuration file for board '%s' not found!", bname ) )
end
-- Toolchain Aliases
toolchain_list[ 'devkitarm' ] = toolchain_list[ 'arm-eabi-gcc' ]
-- List of platform/CPU/toolchains combinations
-- The first toolchain in the toolchains list is the default one
-- (the one that will be used if none is specified)
local platform_list =
{
at91sam7x = { cpus = { 'AT91SAM7X256', 'AT91SAM7X512' }, toolchains = { 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' }, big_endian = false },
lm3s = { cpus = { 'LM3S1968', 'LM3S8962', 'LM3S6965', 'LM3S6918', 'LM3S9B92', 'LM3S9D92' }, toolchains = { 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' }, big_endian = false },
str9 = { cpus = { 'STR912FAW44' }, toolchains = { 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' }, big_endian = false },
i386 = { cpus = { 'I386' }, toolchains = { 'i686-gcc' }, big_endian = false },
sim = { cpus = { 'LINUX' }, toolchains = { 'i686-gcc' }, big_endian = false },
lpc288x = { cpus = { 'LPC2888' }, toolchains = { 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' }, big_endian = false },
str7 = { cpus = { 'STR711FR2' }, toolchains = { 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' }, big_endian = false },
stm32 = { cpus = { 'STM32F103ZE', 'STM32F103RE' }, toolchains = { 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' }, big_endian = false },
avr32 = { cpus = { 'AT32UC3A0128', 'AT32UC3A0256', 'AT32UC3A0512', 'AT32UC3B0256' }, toolchains = { 'avr32-gcc', 'avr32-unknown-none-gcc' }, big_endian = true },
lpc24xx = { cpus = { 'LPC2468' }, toolchains = { 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' }, big_endian = false },
lpc17xx = { cpus = { 'LPC1768' }, toolchains = { 'arm-gcc', 'codesourcery', 'devkitarm', 'arm-eabi-gcc' }, big_endian = false }
}
-- List of board/CPU combinations
local board_list =
{
[ 'SAM7-EX256' ] = { 'AT91SAM7X256', 'AT91SAM7X512' },
[ 'EK-LM3S1968' ] = { 'LM3S1968' },
[ 'EK-LM3S8962' ] = { 'LM3S8962' },
[ 'EK-LM3S6965' ] = { 'LM3S6965' },
[ 'EK-LM3S9B92' ] = { 'LM3S9B92' },
[ 'SOLDERCORE' ] = { 'LM3S9D92' },
[ 'STR9-COMSTICK' ] = { 'STR912FAW44' },
[ 'STR-E912' ] = { 'STR912FAW44' },
[ 'PC' ] = { 'I386' },
[ 'SIM' ] = { 'LINUX' },
[ 'LPC-H2888' ] = { 'LPC2888' },
[ 'MOD711' ] = { 'STR711FR2' },
[ 'STM3210E-EVAL' ] = { 'STM32F103ZE' },
[ 'ATEVK1100' ] = { 'AT32UC3A0512' },
[ 'ATEVK1101' ] = { 'AT32UC3B0256' },
[ 'ET-STM32' ] = { 'STM32F103RE' },
[ 'EAGLE-100' ] = { 'LM3S6918' },
[ 'ELUA-PUC' ] = { 'LPC2468' },
[ 'MBED' ] = { 'LPC1768' },
[ 'MIZAR32' ] = { 'AT32UC3A0256', 'AT32UC3A0512', 'AT32UC3A0128' },
[ 'NETDUINO' ] = { 'AT91SAM7X512' },
[ 'EK-LM3S9D92' ] = { 'LM3S9D92' }
}
-- Build the CPU list starting from the above list
local cpu_list = {}
for k, v in pairs( board_list ) do
local clist = v
for i = 1, #clist do
if not utils.array_element_index( cpu_list, clist[ i ] ) then
table.insert( cpu_list, clist[ i ] )
end
end
-- Automatically build the list of available boards by scanning the board_base_dir directory
local board_flist = utils.linearize_array( utils.string_to_table( utils.get_files( board_base_dir, "%.lua$" ) ) )
local board_list = {}
for k, v in pairs( board_flist ) do
local temp = utils.replace_extension( v, '' )
temp = utils.string_to_table( temp, utils.dir_sep )
temp = temp[ #temp ] -- now 'temp' contains the actual name of the board
if not utils.array_element_index( board_list, temp ) then board_list[ #board_list + 1 ] = temp end
end
builder:add_option( 'target', 'build "regular" float lua, 32 bit integer-only "lualong" or 64-bit integer only lua "lualonglong"', 'lua', { 'lua', 'lualong', 'lualonglong' } )
builder:add_option( 'cpu', 'build for the specified CPU (board will be inferred, if possible)', 'auto', { cpu_list, 'auto' } )
builder:add_option( 'allocator', 'select memory allocator', 'auto', { 'newlib', 'multiple', 'simple', 'auto' } )
builder:add_option( 'board', 'selects board for target (cpu will be inferred)', 'auto', { utils.table_keys( board_list ), 'auto' } )
builder:add_option( 'toolchain', 'specifies toolchain to use (auto=search for usable toolchain)', 'auto', { utils.table_keys( toolchain_list ), 'auto' } )
builder:add_option( 'board', 'selects board for target (cpu will be inferred)', nil, board_list )
builder:add_option( 'toolchain', 'specifies toolchain to use (auto=search for usable toolchain)', 'auto', { bd.get_all_toolchains(), 'auto' } )
builder:add_option( 'optram', 'enables Lua Tiny RAM enhancements', true )
builder:add_option( 'boot', 'boot mode, standard will boot to shell, luarpc boots to an rpc server', 'standard', { 'standard' , 'luarpc' } )
builder:add_option( 'romfs', 'ROMFS compilation mode', 'verbatim', { 'verbatim' , 'compress', 'compile' } )
@ -225,83 +116,111 @@ builder:set_build_mode( builder.BUILD_DIR_LINEARIZED )
comp = {}
setmetatable( comp, { __index = function( t, key ) return builder:get_option( key ) end } )
-- Variants: board = <board>
-- cpu = <cpuname>
-- board = <board> cpu=<cpuname>
if comp.board == 'auto' and comp.cpu == 'auto' then
print "You must specify board, cpu, or both"
if not comp.board then
print "You must specify the board"
os.exit( -1 )
elseif comp.board ~= 'auto' and comp.cpu ~= 'auto' then
-- Check if the board, cpu pair is correct
if utils.array_element_index( board_list[ comp.board:upper() ], comp.cpu:upper() ) == nil then
print( sf( "Invalid CPU '%s' for board '%s'" , comp.cpu, comp.board ) )
os.exit( -1 )
end
elseif comp.board ~= 'auto' then
-- Find CPU
comp.cpu = board_list[ comp.board:upper() ][ 1 ]
else
-- cpu = <cputype>
-- Find board name
for b, v in pairs( board_list ) do
if utils.array_element_index( v, comp.cpu:upper() ) then
comp.board = b
break
end
end
if comp.board == 'auto' then
print( sf( "CPU '%s' not found", comp.cpu ) )
os.exit( -1 )
end
end
-- Look for the given CPU in the list of platforms
for p, v in pairs( platform_list ) do
if utils.array_element_index( v.cpus, comp.cpu:upper() ) then
platform = p
break
-- Interpret the board definition file
local bfname = get_conf_file_path( comp.board )
if not bfname then
io.write( utils.col_red( sf( "[CONFIG] Error: board configuration file for board '%s' not found in '%s'.", comp.board, board_base_dir ) ) )
os.exit( -1 )
end
print( utils.col_blue( "[CONFIG] Found board description file at " .. bfname ) )
local bdata, err = bconf.compile_board( bfname, comp.board )
if not bdata then
print( utils.col_red( "[CONFIG] Error compiling board description file: " .. err ) )
do return end
end
-- Check if the file has changed. If not, do not rewrite it. This keeps the compilation time sane.
local bhname = utils.concat_path( { board_base_dir, "headers", "board_" .. comp.board:lower() .. ".h" } )
if utils.get_hash_of_string( bdata.header ) ~= utils.get_hash_of_file( bhname ) or not utils.is_file( bhname ) then
-- Save the header file
local f = assert( io.open( bhname, "wb" ) )
f:write( bdata.header )
f:close()
print( utils.col_blue( "[CONFIG] Generated board header file at " .. bhname ) )
else
print( utils.col_blue( "[CONFIG] Board header file is unchanged." ) )
end
-- Define the correct CPU header for inclusion in the platform_conf.h file
addm( 'ELUA_CPU_HEADER="\\"cpu_' .. bdata.cpu:lower() .. '.h\\""' )
-- Define the correct board header for inclusion in the platform_conf.h file
addm( 'ELUA_BOARD_HEADER="\\"board_' .. comp.board:lower() .. '.h\\""' )
-- Make available the board directory for the generated header files
addi( utils.concat_path{ board_base_dir, "headers" } )
-- Force target if needed
if bdata.target and bdata.target ~= comp.target then
if builder:is_user_option( 'target' ) then
print( utils.col_yellow( sf( "[CONFIG] WARNING: changing the target from '%s' to '%s' as specified in the command line", bdata.target, comp.target ) ) )
else
comp.target = bdata.target
end
end
-- Force allocator if needed
if bdata.allocator then
if comp.allocator == "auto" then
comp.allocator = bdata.allocator
elseif bdata.allocator ~= comp.allocator then
if builder:is_user_option( 'allocator' ) then
print( utils.col_yellow( sf( "[CONFIG] WARNING: changing the allocator from '%s' to '%s' as specified in the command line", bdata.allocator, comp.allocator ) ) )
else
comp.allocator = bdata.allocator
end
end
end
-- Automatically set the allocator to 'multiple' if needed
if bdata.multi_alloc and comp.allocator == "newlib" then
io.write( utils.col_yellow( "[CONFIG] WARNING: your board has non-contigous RAM areas, but you specified an allocator ('newlib') that can't handle this configuration." ) )
print( utils.col_yellow( "Rebuild with another allocator ('multiple' or 'simple')" ) )
end
if comp.allocator == "auto" and bdata.multi_alloc then comp.allocator = "multiple" end
comp.cpu = bdata.cpu:upper()
platform = bd.get_platform_of_cpu( comp.cpu )
if not platform then
print( "Unable to find platform (this shouldn't happen, check the build script for errors)" )
os.exit( -1 )
end
-- Check the toolchain
local usable_chains = bd.get_toolchains_of_platform( platform )
if comp.toolchain ~= 'auto' then
if utils.array_element_index( platform_list[ platform ].toolchains, comp.toolchain ) == nil then
if utils.array_element_index( usable_chains, comp.toolchain ) == nil then
print( sf( "Invalid toolchain '%s' for CPU '%s'", comp.toolchain, comp.cpu ) )
print( sf( "List of accepted toolchains (for %s): %s", comp.cpu, table.concat( usable_chains, "," ) ) )
os.exit( -1 )
end
toolset = toolchain_list[ comp.toolchain ]
toolset = bd.get_toolchain_data( comp.toolchain )
comp.CC = toolset.compile
comp.AS = toolset.compile
else
-- If 'auto' try to match a working toolchain with target
local usable_chains = platform_list[ platform ].toolchains
-- Try to execute all compilers, exit when one found
local chain
for i = 1, #usable_chains do
local c = usable_chains[ i ]
local t = toolchain_list[ c ]
local t = bd.get_toolchain_data( c )
local res = utils.check_command( t.compile .. " " .. t.version )
if res == 0 then chain = c break end
end
if chain then
comp.toolchain = chain
comp.CC = toolchain_list[ chain ].compile
toolset = bd.get_toolchain_data( chain )
comp.CC = toolset.compile
comp.AS = comp.CC
toolset = toolchain_list[ chain ]
else
print "Unable to find an usable toolchain in your path."
print( sf( "List of accepted toolchains (for %s): %s", comp.cpu, table.concat( usable_chains ) ) )
print( sf( "List of accepted toolchains (for %s): %s", comp.cpu, table.concat( usable_chains, "," ) ) )
os.exit( -1 )
end
end
-- CPU/allocator mapping (if allocator not specified)
-- TODO: this needs to go away too, since the allocator is now automatically inferred
if comp.allocator == 'auto' then
if comp.board:upper() == 'MIZAR32' and comp.cpu:upper() == 'AT32UC3A0128' then
if comp.board:upper() == 'MIZAR32' or comp.cpu:upper() == 'AT32UC3A0128' then
comp.allocator = 'simple'
elseif utils.array_element_index( { 'LPC-H2888', 'ATEVK1100', 'MIZAR32', 'MBED' }, comp.board:upper() ) then
comp.allocator = 'multiple'
@ -314,7 +233,7 @@ end
local fscompcmd = ''
if comp.romfs == 'compile' then
if comp.target == 'lualonglong' then
print "Cross-compilation is not yet supported for 64-bit integer only Lua (lualonglong)."
print "Cross-compilation is not yet supported for 64-bit integer-only Lua (lualonglong)."
os.exit( -1 )
end
local suffix = ''
@ -341,18 +260,19 @@ if utils.check_command('git describe --always') == 0 then
if string.find(elua_vers, "^[+-]?%x+$") then
elua_vers = 'dev-' .. elua_vers
end
utils.gen_header('git_version',{elua_version=elua_vers, elua_str_version=("\"" .. elua_vers .. "\"")})
local sver = utils.gen_header_string( 'git_version', { elua_version = elua_vers, elua_str_version = ("\"" .. elua_vers .. "\"" ) } )
if utils.get_hash_of_string( sver ) ~= utils.get_hash_of_file( utils.concat_path{ 'inc', 'git_version.h' } ) then
utils.gen_header_file( 'git_version', { elua_version = elua_vers, elua_str_version = ("\"" .. elua_vers .. "\"" ) } )
end
else
print "WARNING: unable to determine version from repository"
elua_vers = "unknown"
end
-- Output file
output = 'elua_' .. comp.target .. '_' .. comp.cpu:lower()
output = 'elua_' .. comp.target .. '_' .. comp.board:lower()
builder:set_output_dir( ".build" .. utils.dir_sep .. comp.board:lower() )
-- User report
print ""
print "*********************************"
@ -389,9 +309,9 @@ if comp.boot == 'luarpc' then addm( "ELUA_BOOT_RPC" ) end
if comp.target == 'lualong' or comp.target == 'lualonglong' then addm( "LUA_NUMBER_INTEGRAL" ) end
if comp.target == 'lualonglong' then addm( "LUA_INTEGRAL_LONGLONG" ) end
if comp.target ~= 'lualong' and comp.target ~= "lualonglong" then addm( "LUA_PACK_VALUE" ) end
if platform_list[ platform ].big_endian then addm( "ELUA_ENDIAN_BIG" ) else addm( "ELUA_ENDIAN_LITTLE" ) end
if bd.get_endianness_of_platform( platform ) == "big" then addm( "ELUA_ENDIAN_BIG" ) else addm( "ELUA_ENDIAN_LITTLE" ) end
-- Special macro definitions for the SYM target
-- Special macro definitions for the SIM target
if platform == 'sim' then addm( { "ELUA_SIMULATOR", "ELUA_SIM_" .. cnorm( comp.cpu ) } ) end
-- Lua source files and include path
@ -430,11 +350,11 @@ romfs_exclude_patterns = { '%.DS_Store', '%.gitignore' }
function match_pattern_list( item, list )
for k, v in pairs( list ) do
if item:find(v) then return true end
if item:find(v) then return true end
end
end
local function make_romfs()
local function make_romfs( target, deps )
print "Building ROM file system ..."
local flist = {}
flist = utils.string_to_table( utils.get_files( 'romfs', function( fname ) return not match_pattern_list( fname, romfs_exclude_patterns ) end ) )
@ -491,11 +411,13 @@ builder:set_link_cmd( linkcmd )
builder:set_asm_cmd( ascmd )
builder:set_exe_extension( ".elf" )
-- Create the ROM file system
make_romfs()
-- Creaate executable targets
-- Create the ROMFS target
local romfs_target = builder:target( "#phony:romfs", nil, make_romfs )
romfs_target:force_rebuild( true )
-- Create executable targets
odeps = builder:create_compile_targets( source_files )
exetarget = builder:link_target( output, odeps )
exetarget = builder:link_target( output, { romfs_target, odeps } )
-- This is also the default target
builder:default( builder:add_target( exetarget, 'build eLua executable' ) )

182
config/attributes.lua Normal file
View File

@ -0,0 +1,182 @@
-- Attributes are used by various parts of the board description
-- system (for example configs and components)
module( ..., package.seeall )
local ct = require "constants"
local sf = string.format
-- Validator for a 'choice' attribute
-- Returns the value if OK, (false, errmsg) for error
-- Needs: attrvals - list of permitted values for this attribute
local function _validate_choice( adesc, aname, aval, elname, sectname )
aval = tostring( aval ):lower()
for k, v in pairs( adesc.attrvals ) do
if v == aval then return v end
end
return false, sf( "invalid value '%s' for attribute '%s' of element '%s' in section '%s'", aval, aname, elname, sectname )
end
-- Validator for a 'number' attribute
-- Returns the value if OK, (false, errmsg) for error
-- Needs: attrtype - the number type ('int' or 'float')
-- attrmin - minimum value (no minimum check will be performed if not specified)
-- attrmax - maximum value (no maximum check will be performed if not specified)
local function _validate_number( adesc, aname, aval, elname, sectname )
aval = tonumber( aval )
if not aval then return false, sf( "value of attribute '%s' for element '%s' in section '%s' must be a number", aname, elname, sectname ) end
if adesc.attrtype == 'int' and math.floor( aval ) ~= aval then
return false, sf( "value of attribute '%s' for element '%s' in section '%s' must be an integer", aname, elname, sectname )
end
local minval = adesc.attrmin or aval
local maxval = adesc.attrmax or aval
if aval < minval then
return false, sf( "value of attribute '%s' for element '%s' in section '%s' must be larger than '%s'", aname, elname, sectname, tostring( minval ) )
end
if aval > maxval then
return false, sf( "value of attribute '%s' for element '%s' in section '%s' must be smaller than '%s'", aname, elname, sectname, tostring( maxval ) )
end
return aval
end
-- Validator for a log2 number attribute
-- Works like number, but additionaly checks that the value is a power of 2
-- Also changes the attribute value to its log2
local function _validate_log2( adesc, aname, aval, elname, sectname )
local res, err = _validate_number( adesc, aname, aval, elname, sectname )
if not res then return res, err end
if aval <= 0 then
return false, sf( "value of attribute '%s' for element '%s' in section '%s' must be larger than 0", aname, elname, sectname )
end
local thelog = math.log( res ) / math.log( 2 )
if thelog ~= math.floor( thelog ) then
return false, sf( "value of attribute '%s' for element '%s' in section '%s' must be a power of 2", aname, elname, sectname )
end
return thelog
end
-- Validator for a string attribute
-- Return the string if OK, (false, errmsg) for error
-- Needs: attrmaxsize - maximum size of the string
local function _validate_string( adesc, aname, aval, elname, sectname )
aval = tostring( aval )
if type( aval ) ~= "string" then
return false, sf( "value of attribute '%s' for element '%s' in section '%s' must be a string", aname, elname, sectname )
end
maxsize = adesc.attrmaxsize or math.huge
if #aval > maxsize then
return false, sf( "value of attribute '%s' for element '%s' in section '%s' must be less than %d chars in length", aname, elname, sectname, maxsize )
end
return aval
end
-- Validator for an IP attribute
-- Return the IP as a table of numbers if OK, (false, errmsg) for error
local function _validate_ip( adesc, aname, aval, elname, sectname )
if type( aval ) == "string" then -- transform this to table
if aval:sub( -1, -1 ) ~= "." then aval = aval .. "." end -- add a final dot to make parsing easier
local t = {}
for w in aval:gmatch( "(%w+)%." ) do t[ #t + 1 ] = tonumber( w ) end
aval = t
elseif type( aval ) ~= "table" then
return false, sf( "attribute '%s' of element '%s' in section '%s' must be a string or a table", aname, elname, sectname )
end
if #aval ~= 4 then return false, sf( "invalid IP for attribute '%s' of element '%s' in section '%s'", aname, elname, sectname ) end
for i = 1, 4 do
local e = aval[ i ]
if type( e ) ~= "number" or math.floor( e ) ~= e or e < 0 or e > 255 then
return false, sf( "invalid IP for attribute '%s' of element '%s' in section '%s'", aname, elname, sectname )
end
end
return aval
end
-- Builds a validator with the given array element checker
local function build_validator( realvname )
return function( adesc, aname, aval, elname, sectname )
if not adesc.is_array then return realvname( adesc, aname, aval, elname, sectname ) end
if type( aval ) ~= "table" then return false, sf( "value of attribute '%s' for element '%s' in section '%s' must be an array", aname, elname, sectname ) end
for i = 1, #aval do
local res, err = realvname( adesc, aname, aval[ i ], elname, sectname )
if not res then
return false, sf( "error at index %d: %s", i, err )
else
aval[ i ] = res
end
end
return aval
end
end
local validate_number = build_validator( _validate_number )
local validate_choice = build_validator( _validate_choice )
local validate_log2 = build_validator( _validate_log2 )
local validate_string = build_validator( _validate_string )
local validate_ip = build_validator( _validate_ip )
-------------------------------------------------------------------------------
-- Public interface
-- Returns a new choice attribute with the given possible values
function choice_attr( macro, values, default )
return { macro = macro, default = default, validator = validate_choice, attrvals = values }
end
-- Returns a new timer attribute with the given macro and default (systmr if not specified)
function timer_attr( macro, default )
default = default or 'systmr'
local t = choice_attr( macro, utils.table_keys( ct.timer_values ), default )
t.is_timer, t.mapping = true, ct.timer_values
return t
end
-- Returns a new integer number attribute with the given limits
function int_attr( macro, minv, maxv, default )
return { macro = macro, default = default, validator = validate_number, attrtype = 'int', attrmin = minv, attrmax = maxv }
end
-- Returns a new UART attribute
function uart_attr( macro, default )
local t = choice_attr( macro, utils.table_keys( ct.uart_values ), default )
t.is_uart, t.mapping = true, ct.uart_values
return t
end
-- Returns a new integer number attribute with the given limits
-- The generated value will be the integer's base 2 logarithm
function int_log2_attr( macro, minv, maxv, default )
local t = int_attr( macro, minv, maxv, default )
t.validator = validate_log2
return t
end
-- Returns a new flow control attribute
function flow_control_attr( macro, default )
default = default or 'none'
local t = choice_attr( macro, utils.table_keys( ct.uart_flow ), default )
t.mapping = ct.uart_flow
return t
end
-- Returns a new string attribute
function string_attr( macro, maxsize, default )
return { macro = macro, default = default, validator = validate_string, attrmaxsize = maxsize }
end
-- Returns a new IP attribute
function ip_attr( macro, default )
return { macro = macro, default = default, validator = validate_ip, is_ip = true }
end
-- Make the given attribute optional
function make_optional( attr )
attr.optional = true
return attr
end
-- Mark the given attribute as an array of element of the same type
function array_of( attr )
attr.is_array = true
return attr
end

166
config/components.lua Normal file
View File

@ -0,0 +1,166 @@
-- eLua components description
module( ..., package.seeall )
local at = require "attributes"
local gen = require "generators"
local sf = string.format
-------------------------------------------------------------------------------
-- Sermux support
local function sermux_auxcheck( eldesc, data, enabled )
local v = data.SERMUX_BUFFER_SIZES.value
if #v < 2 then
return false, sf( "array 'buf_sizes' of element 'sermux' in section 'components' must have at least 2 elements" )
end
return true
end
local function sermux_auxgen( eldesc, data, generated )
local v = data.SERMUX_BUFFER_SIZES.value
return gen.print_define( 'SERMUX_NUM_VUART', #v )
end
-------------------------------------------------------------------------------
-- Public interface
-- Build all components needed by eLua, save them in the "components" table
function init()
local components = {}
-- Serial console
components.sercon = {
macro = 'BUILD_CON_GENERIC',
attrs = {
uart = at.uart_attr( 'CON_UART_ID' ),
speed = at.int_attr( 'CON_UART_SPEED' ),
timer = at.timer_attr( 'CON_TIMER_ID' ),
flow = at.flow_control_attr( 'CON_FLOW_TYPE' ),
buf_size = at.make_optional( at.int_log2_attr( 'CON_BUF_SIZE' ) )
}
}
-- TCP/IP console
components.tcpipcon = { macro = 'BUILD_CON_TCP', needs = 'tcpip' }
-- UART buffering
-- Not really a component, not quite a config ... Implementation wise,
-- it is easier to declare it as a component
components.uart_buffers = { macro = 'BUF_ENABLE_UART' }
-- XMODEM
components.xmodem = {
macro = 'BUILD_XMODEM',
attrs = {
uart = at.uart_attr( 'CON_UART_ID' ),
speed = at.int_attr( 'CON_UART_SPEED' ),
timer = at.timer_attr( 'CON_TIMER_ID' ),
flow = at.flow_control_attr( 'CON_FLOW_TYPE'),
buf_size = at.make_optional( at.int_log2_attr( 'CON_BUF_SIZE' ) )
}
}
-- Shell
components.shell = { macro = 'BUILD_SHELL' }
-- Term
components.term = {
macro = 'BUILD_TERM',
attrs = {
uart = at.uart_attr( 'CON_UART_ID' ),
speed = at.int_attr( 'CON_UART_SPEED' ),
timer = at.timer_attr( 'CON_TIMER_ID' ),
flow = at.flow_control_attr( 'CON_FLOW_TYPE' ),
buf_size = at.make_optional( at.int_log2_attr( 'CON_BUF_SIZE' ) ),
lines = at.int_attr( 'TERM_LINES' ),
cols = at.int_attr( 'TERM_COLS' )
}
}
-- C interrupt support
components.cints = { macro = 'BUILD_C_INT_HANDLERS' }
-- Lua interrupt support
components.luaints = {
macro = 'BUILD_LUA_INT_HANDLERS',
attrs = {
queue_size = at.int_log2_attr( 'PLATFORM_INT_QUEUE_LOG_SIZE', nil, nil, 5 )
},
needs = 'cints'
}
-- Linenoise
components.linenoise = {
macro = 'BUILD_LINENOISE',
attrs = {
shell_lines = at.int_attr( 'LINENOISE_HISTORY_SIZE_SHELL' ),
lua_lines = at.int_attr( 'LINENOISE_HISTORY_SIZE_LUA' ),
autosave_file = at.make_optional( at.string_attr( 'LINENOISE_AUTOSAVE_FNAME', 32 ) )
}
}
-- RFS
components.rfs = {
macro = 'BUILD_RFS',
attrs = {
uart = at.uart_attr( 'RFS_UART_ID' ),
speed = at.int_attr( 'RFS_UART_SPEED' ),
timer = at.timer_attr( 'RFS_TIMER_ID' ),
flow = at.flow_control_attr( 'RFS_FLOW_TYPE' ),
buf_size = at.int_log2_attr( 'RFS_BUFFER_SIZE', nil, nil, 9 ),
timeout = at.int_attr( 'RFS_TIMEOUT', nil, nil, 100000 )
}
}
-- MMCFS
components.mmcfs = {
macro = 'BUILD_MMCFS',
attrs = {
cs_port = at.int_attr( 'MMCFS_CS_PORT' ),
cs_pin = at.int_attr( 'MMCFS_CS_PIN' ),
spi = at.int_attr( 'MMCFS_SPI_NUM' )
}
}
-- RPC
-- (values are optional, since they are required only if booting in RPC mode)
components.rpc = {
macro = 'BUILD_RPC',
attrs = {
uart = at.make_optional( at.uart_attr( 'RPC_UART_ID' ) ),
speed = at.make_optional( at.int_attr( 'RPC_UART_SPEED' ) ),
timer = at.make_optional( at.timer_attr( 'RPC_TIMER_ID' ) )
}
}
-- TCP/IP
components.tcpip = {
macro = 'BUILD_UIP',
attrs = {
ip = at.ip_attr( 'ELUA_CONF_IPADDR' ),
netmask = at.ip_attr( 'ELUA_CONF_NETMASK' ),
gw = at.ip_attr( 'ELUA_CONF_DEFGW' ),
dns = at.ip_attr( 'ELUA_CONF_DNS' )
}
}
-- Serial multiplexer
components.sermux = {
macro = 'BUILD_SERMUX',
auxgen = sermux_auxgen,
auxcheck = sermux_auxcheck,
attrs = {
uart = at.uart_attr( 'SERMUX_PHYS_ID' ),
speed = at.int_attr( 'SERMUX_PHYS_SPEED' ),
flow = at.flow_control_attr( 'SERMUX_FLOW_TYPE' ),
buf_sizes = at.array_of( at.int_log2_attr( 'SERMUX_BUFFER_SIZES' ) )
}
}
-- ADC
components.adc = {
macro = 'BUILD_ADC',
attrs = {
buf_size = at.make_optional( at.int_log2_attr( 'ADC_BUF_SIZE' ) ),
first_timer = at.make_optional( at.int_attr( 'ADC_TIMER_FIRST_ID' ) ),
num_timers = at.make_optional( at.int_attr( 'ADC_NUM_TIMERS' ) )
}
}
-- DNS client
components.dns = { macro = 'BUILD_DNS', needs = 'tcpip' }
-- DHCP client
components.dhcp = { macro = 'BUILD_DHCPC', needs = 'tcpip' }
-- ROMFS
components.romfs = { macro = 'BUILD_ROMFS' }
-- WOFS
components.wofs = { macro = "BUILD_WOFS" }
-- All done
return components
end

304
config/config.lua Normal file
View File

@ -0,0 +1,304 @@
-- Generate a C configuration starting from a Lua description file
-- for an eLua board
module( ..., package.seeall )
package.path = package.path .. ";utils/?.lua;config/?.lua"
local comps = require "components"
local cfgs = require "configurations"
local gen = require "generators"
local utils = require "utils"
local bd = require "build_data"
local mgen = require "modules"
local cpuct = require "cpuconstants"
local sects = require "sections"
local components, configs
local glconf, glen
-------------------------------------------------------------------------------
-- Various helpers and internal functions
-- Generator for section 'components'
local function generate_components( data, plconf )
local compdata = data.components or {}
-- Prerequisites: check for keys that might be needed in components, but might not be there
-- At the moment, we need to definer either BUILD_CON_GENERIC or BUILD_CON_TCP (but not both)
if compdata.sercon and compdata.tcpipcon then
return nil, "serial and TCP/IP console can't be enabled at the same time in section 'components'"
elseif not compdata.sercon and not compdata.tcpipcon then
return nil, "either serial (sercon) or TCP/IP (tcpipcon) console must be enabled in 'components'"
end
-- Configure section first
local res, err = sects.configure_section( components, 'components', compdata )
if not res then return false, err end
-- Let the backend do its validation
if plconf.pre_generate_section then
res, err = plconf.pre_generate_section( components, 'components', compdata, conf, enabled )
if not res then return false, err end
end
-- Generate all data for section 'components'
return sects.generate_section( components, 'components', compdata )
end
-- Generator for section 'config'
local function generate_config( data, plconf )
local confdata = data.config or {}
-- Configure section first
local res, err = sects.configure_section( configs, 'config', confdata )
if not res then return false, err end
-- Let the backend do its validation
if plconf.pre_generate_section then
res, err = plconf.pre_generate_section( configs, 'config', confdata, conf, enabled )
if not res then return false, err end
end
return sects.generate_section( configs, 'config', confdata )
end
-- Global sanity checks (data is in 'glconf' and 'glen'
local function check_components_and_config()
-- Check all uart IDs. If VUARTs are specified but sermux is not enabled, return with error
if not glen.sermux then
for _, attrdata in pairs( glconf ) do
local attrval = attrdata.value
if attrdata.desc.is_uart and type( attrval ) == "string" and attrval:find( "^vuart" ) then
return false, sf( "attribute '%s' of element '%s' in section '%s' reffers to a virtual UART, but the serial multiplexer ('sermux') is not enabled",
attrdata.name, attrdata.elname, attrdata.sectname )
end
end
end
-- Check all timer IDs. If virtual timers are specified but vtmr is not enabled, return with error
if not glen.vtmr or tostring( glconf.VTMR_NUM_TIMERS.value ) == "0" then
for _, attrdata in pairs( glconf ) do
local attrval = attrdata.value
if attrdata.desc.is_timer and type( attrval ) == "string" and attrval:find( "^vtmr" ) then
return false, sf( "attribute '%s' of element '%s' in section '%s' reffers to a virtual timer, but virtual timers ('vtmr') are not enabled",
attrdata.name, attrdata.elname, attrdata.sectname )
end
end
end
-- Check sermux/RFS+console proper UART assignment
if glen.sermux and glen.sercon and glen.rfs then
local rfs_uart_value = tostring( glconf.RFS_UART_ID.value )
local con_uart_value = tostring( glconf.CON_UART_ID.value )
if rfs_uart_value:find( "^vuart" ) and rfs_uart_value ~= "vuart0" then
io.write( utils.col_yellow( "[CONFIG] WARNING: you have enabled the serial multiplexer and RFS over a virtual serial port which is not the first virtual serial port ('vuart0')" ) )
print( utils.col_yellow( "In this configuration, the serial multiplexer will not work in 'rfsmux' mode. Check the serial multiplexer section of the eLua manual for more details." ) )
elseif rfs_uart_value == "vuart0" and con_uart_value:find( "^vuart" ) and con_uart_value ~= "vuart1" then
io.write( utils.col_yellow( "[CONFIG] WARNING: when using both RFS and the serial console with 'sermux', it's best to set the serial console uart ID to the second virtual serial port ('vuart1')" ) )
print( utils.col_yellow( "In this configuration, the serial multiplexer will work directly in 'rfsmux' mode with a console. Check the serial multiplexer section of the eLua manual for more details." ) )
end
end
return true
end
-- Default table for backend configuration data
-- If the platform doesn't have a boardconf.lua, this is what we're going to use
local default_platform_conf = {
add_platform_components = function() end,
add_platform_configs = function() end,
get_platform_modules = function() end,
pre_generate_section = function() return true end,
}
-- Sanity code
-- These are more checks added to the generated header file
-- Some of these are the result of pure paranoia. Nevertheless, they seem to work.
local sanity_code = [[
///////////////////////////////////////////////////////////////////////////////
// Static sanity checks and additional defines
#if defined( ELUA_BOOT_RPC ) && !defined( BUILD_RPC )
#define BUILD_RPC
#endif
#if defined( BUILD_LUA_INT_HANDLERS ) || defined( BUILD_C_INT_HANDLERS )
#define BUILD_INT_HANDLERS
#ifndef INT_TMR_MATCH
#define INT_TMR_MATCH ELUA_INT_INVALID_INTERRUPT
#endif
#endif // #if defined( BUILD_LUA_INT_HANDLERS ) || defined( BUILD_C_INT_HANDLERS )
#ifndef VTMR_NUM_TIMERS
#define VTMR_NUM_TIMERS 0
#endif // #ifndef VTMR_NUM_TIMERS
#ifndef SERMUX_FLOW_TYPE
#define SERMUX_FLOW_TYPE PLATFORM_UART_FLOW_NONE
#endif
#ifndef CON_FLOW_TYPE
#define CON_FLOW_TYPE PLATFORM_UART_FLOW_NONE
#endif
#ifndef CON_TIMER_ID
#define CON_TIMER_ID PLATFORM_TIMER_SYS_ID
#endif
#ifdef ELUA_BOOT_RPC
#ifndef RPC_UART_ID
#define RPC_UART_ID CON_UART_ID
#endif
#ifndef RPC_TIMER_ID
#define RPC_TIMER_ID PLATFORM_TIMER_SYS_ID
#endif
#ifndef RPC_UART_SPEED
#define RPC_UART_SPEED CON_UART_SPEED
#endif
#endif // #ifdef ELUA_BOOT_RPC
#if ( defined( BUILD_RFS ) || defined( BUILD_SERMUX ) || defined( CON_BUF_SIZE ) ) && !defined( BUF_ENABLE_UART )
#define BUF_ENABLE_UART
#endif
#if defined( ADC_BUF_SIZE ) && !defined( BUF_ENABLE_ADC )
#define BUF_ENABLE_ADC
#endif
#ifndef CPU_FREQUENCY
#define CPU_FREQUENCY 0
#endif
]]
-------------------------------------------------------------------------------
-- Public interface
-- This code is executed an initialization time (the first 'require')
components = comps.init()
configs = cfgs.init()
-- Read the Lua description file of a board and return the corresponding header file
-- as a string or (false, error) if an error occured
function compile_board( fname, boardname )
local cboardname = boardname:upper():gsub( "[%-%.%s]", "_" )
local header = sf([[
// Lua board configuration file, automatically generated
#ifndef __GENERATED_%s_H__
#define __GENERATED_%s_H__
]], cboardname, cboardname )
local desc, err = dofile( fname )
if not desc then return false, err end
if not desc.cpu then return false, "cpu not specified in board configuration file" end
-- Check the keys in 'desc'
local known_keys = { 'cpu', 'components', 'config', 'headers', 'macros', 'modules', 'cpu_constants', 'allocator', 'target' }
for k, _ in pairs( desc ) do
if not utils.array_element_index( known_keys, k ) then return false, sf( "unknown key '%s'", k ) end
end
-- Check CPU
local cpulist = bd.get_all_cpus()
if not utils.array_element_index( cpulist, desc.cpu:upper() ) then
return false, sf( "unknown cpu '%s'", desc.cpu )
end
-- Find and require the platform board configuration file
local platform = bd.get_platform_of_cpu( desc.cpu )
if not platform then return false, sf( "unable to find the platform of cpu '%s'", desc.cpu ) end
local plconf = default_platform_conf
if utils.is_file( utils.concat_path{ 'src', 'platform', platform, 'build_config.lua' } ) then
plconf = require( "src.platform." .. platform .. ".build_config" )
print( utils.col_blue( sf( "[CONFIG] Found a backend build configuration file for platform %s", platform ) ) )
end
-- Read platform specific components/configs
plconf.add_platform_components( components )
plconf.add_platform_configs( configs )
-- Do we need to include any configured headers?
if type( desc.headers ) == "table" and #desc.headers > 0 then
for _, h in pairs( desc.headers ) do
header = header .. "#include " .. h .. "\n"
end
header = header .. "\n"
end
-- Do we need to add definitions for any configured macros?
if type( desc.macros ) == "table" and #desc.macros > 0 then
for _, m in pairs( desc.macros ) do
if type( m ) == "string" then -- #define m
header = header .. gen.print_define( m )
elseif type( m ) == "table" then -- { macro, value } -> #define macro value
header = header .. gen.print_define( m[ 1 ], m[ 2 ] )
end
end
header = header .. "\n"
end
-- Generate components first
local gen, err = generate_components( desc, plconf )
if not gen then return false, err end
header = header .. gen
-- Keep generated data for later use
glconf, glen = sects.conf, sects.enabled
-- Then configs
gen, err = generate_config( desc, plconf )
local multi_alloc = cfgs.needs_multiple_allocator()
if not gen then return false, err end
header = header .. gen
-- Accumulate generated data into 'glconf' and 'glen'
utils.concat_tables( glconf, sects.conf )
utils.concat_tables( glen, sects.enabled )
-- Now we have all components and the configuration generated
-- It's a good time for some sanity checks
gen, err = check_components_and_config()
if not gen then return false, err end
-- Now it's a good time to include the fixed sanity checks
header = header .. sanity_code
-- Generate module configuration
gen, err = mgen.gen_module_list( desc, plconf, platform )
if not gen then return false, err end
header = header .. gen
-- Generate additional CPU constants
gen, err = cpuct.gen_constants( desc )
if not gen then return false, err end
header = header .. gen
-- All done, write the header's footer
header = header .. sf( "#endif // #ifndef __GENERATED_%s_H__\n", cboardname )
-- We are done with the header, we still need to check the compile flags
local allocator
if desc.allocator then
local allocs = { 'newlib', 'multiple', 'simple' }
if not utils.array_element_index( allocs, desc.allocator ) then
return false, sf( "unknown allocator '%s'", desc.allocator )
end
allocator = desc.allocator
end
local target
if desc.target then
local targets = { 'lua', 'lualong', 'lualonglong' }
if not utils.array_element_index( targets, desc.target ) then
return false, sf( "unknown target '%ws'", desc.target )
end
target = desc.target
end
-- Return the contents of the header, as well as the name of the CPU used by this
-- board (this information is needed by the builder) and the build information
return { header = header, cpu = desc.cpu, multi_alloc = multi_alloc, allocator = allocator, target = target }
end

166
config/configurations.lua Normal file
View File

@ -0,0 +1,166 @@
-- eLua configurations description
module( ..., package.seeall )
local sf = string.format
local at = require "attributes"
local gen = require "generators"
local use_multiple_allocator
-------------------------------------------------------------------------------
-- Attribute checkers
local function mem_checker( eldesc, vals )
local startvals = vals.MEM_START_ADDRESS and vals.MEM_START_ADDRESS.value
local sizevals = vals.MEM_END_ADDRESS and vals.MEM_END_ADDRESS.value
if not startvals and not sizevals then return true end
if not startvals then
return false, "attribute 'start' must also be specified for element 'extmem' of section 'config'"
elseif not sizevals then
return false, "attribute 'size' must also be specified for element 'extmem' of section 'config'"
end
if #startvals == 0 then
return false, "attribute 'start' of element 'extmem' in section 'config' must have at least one element"
elseif #sizevals == 0 then
return false, "attribute 'size' of element 'extmem' in section 'config' must have at least one element"
end
if #startvals ~= #sizevals then
return false, "attributes 'start' and 'size' of element 'extmem' in section 'config' must have the same number of elements'"
end
return true
end
local egc_mode_map =
{
disabled = "EGC_NOT_ACTIVE",
alloc = "EGC_ON_ALLOC_FAILURE",
limit = "EGC_ON_MEM_LIMIT",
always = "EGC_ALWAYS"
}
local function egc_checker( eldesc, vals )
local modev = vals.EGC_INITIAL_MODE.value
local limv = vals.EGC_INITIAL_MEMLIMIT and vals.EGC_INITIAL_MEMLIMIT.value
local allmodes = {}
for w in modev:gmatch( "(%w+)" ) do allmodes[ #allmodes + 1 ] = w:lower() end
local has_memlimit
for k, v in pairs( allmodes ) do
if not egc_mode_map[ v ] then
return false, sf( "'%s' is not a valid value for attribute 'mode' of element 'egc' in section 'config'", v )
end
if v == "limit" then has_memlimit = true end
end
if has_memlimit and not limv then
return false, sf( "you must specify the 'limit' attribute when using 'limit' as a value for attribute 'mode' of element 'egc' in section 'config'" )
end
return true
end
-------------------------------------------------------------------------------
-- Specific generators
-- Automatically generates the MEM_START_ADDRESS and MEM_END_ADDRESS macros
-- Assumes that definitions for INTERNAL_RAM_FIRST_FREE and INTERNAL_RAM_LAST_FREE
-- exist (they should come from <cpu>.h)
local function mem_generator( desc, vals, generated )
if not vals.MEM_START_ADDRESS and not vals.MEM_END_ADDRESS then
-- Generate configuration only for the internal memory
local gstr = gen.print_define( "MEM_START_ADDRESS", "{ ( u32 )( INTERNAL_RAM_FIRST_FREE ) }" )
gstr = gstr .. gen.print_define( "MEM_END_ADDRESS", "{ ( u32 )( INTERNAL_RAM_LAST_FREE ) }" )
generated.MEM_START_ADDRESS = true
generated.MEM_END_ADDRESS = true
return gstr
end
local startvals = vals.MEM_START_ADDRESS.value
local sizevals = vals.MEM_END_ADDRESS.value
table.insert( startvals, 1, "INTERNAL_RAM_FIRST_FREE" )
table.insert( sizevals, 1, "INTERNAL_RAM_LAST_FREE" )
-- Transform the data in 'sizevals' to 'last address' (the format accepted by eLua)
for i = 2, #sizevals do
sizevals[ i ] = tonumber( startvals[ i ] ) + tonumber( sizevals[ i ] ) - 1
end
-- Prefix all the values in the 'start' and 'size' arrays with 'u32'
for i = 1, #sizevals do
startvals[ i ] = "( u32 )( " .. tostring( startvals[ i ] ) .. ( i > 1 and "u" or "" ) .. " )"
sizevals[ i ] = "( u32 )( " .. tostring( sizevals[ i ] ) .. ( i > 1 and "u" or "" ) .. " )"
end
local gstr = gen.simple_gen( "MEM_START_ADDRESS", vals, generated )
gstr = gstr .. gen.simple_gen( "MEM_END_ADDRESS", vals, generated )
use_multiple_allocator = #startvals > 1
return gstr
end
local function egc_generator( desc, vals, generated )
local modev = vals.EGC_INITIAL_MODE.value
local limv = vals.EGC_INITIAL_MEMLIMIT and vals.EGC_INITIAL_MEMLIMIT.value
local allmodes = {}
local has_memlimit, has_always
for w in modev:gmatch( "(%w+)" ) do
w = w:lower()
if w == "limit" then has_memlimit = true end
if w == "always" then has_always = true end
allmodes[ #allmodes + 1 ] = w:lower()
end
if has_always then
local gstr = gen.print_define( "EGC_INITIAL_MODE", "EGC_ALWAYS" )
generated.EGC_INITIAL_MODE = true
return gstr
end
local cmodes = {}
for k, v in pairs( allmodes ) do
cmodes[ #cmodes + 1 ] = egc_mode_map[ v ]
end
local gstr = gen.print_define( "EGC_INITIAL_MODE", "( " .. table.concat( cmodes, "|" ) .. " )" )
generated.EGC_INITIAL_MODE = true
if has_memlimit then gstr = gstr .. gen.simple_gen( "EGC_INITIAL_MEMLIMIT", vals, generated ) end
return gstr
end
-------------------------------------------------------------------------------
-- Public interface
-- Build the configuration data needed by eLua, save it in the "configs" table
function init()
local configs = {}
-- Virtual timers
configs.vtmr = {
attrs = {
num = at.int_attr( 'VTMR_NUM_TIMERS', 1 ),
freq = at.int_attr( 'VTMR_FREQ_HZ', 1 )
},
required = { num = 0, freq = 1 }
}
-- EGC
configs.egc = {
confcheck = egc_checker,
gen = egc_generator,
attrs = {
mode = at.string_attr( 'EGC_INITIAL_MODE' ),
limit = at.make_optional( at.int_attr( 'EGC_INITIAL_MEMLIMIT', 1 ) )
},
}
-- Memory configuration generator
configs.extmem = {
gen = mem_generator,
confcheck = mem_checker,
attrs = {
start = at.array_of( at.int_attr( 'MEM_START_ADDRESS' ) ),
size = at.array_of( at.int_attr( 'MEM_END_ADDRESS', 1 ) )
},
required = {}
}
-- All done
return configs
end
-- Returns true if a multiple allocator is needed for this configuration,
-- false otherwise
function needs_multiple_allocator()
return use_multiple_allocator
end

50
config/constants.lua Normal file
View File

@ -0,0 +1,50 @@
-- Various constants used by the build descriptor
module( ..., package.seeall )
local sf = string.format
-------------------------------------------------------------------------------
-- UART data
-- UART flow types
uart_flow =
{
none = 'PLATFORM_UART_FLOW_NONE',
rts = 'PLATFORM_UART_FLOW_RTS',
cts = 'PLATFORM_UART_FLOW_CTS',
rtscts = '( PLATFORM_UART_FLOW_RTS | PLATFORM_UART_FLOW_CTS )'
}
uart_values = {}
-- Add a sufficient number of virtual and real UARTs
for i = 0, 127 do
uart_values[ sf( 'vuart%d', i ) ] = sf( '( SERMUX_SERVICE_ID_FIRST + %d )', i )
uart_values[ tostring( i ) ] = i
end
-------------------------------------------------------------------------------
-- Timer data
-- System timer ID
timer_values =
{
systmr = 'PLATFORM_TIMER_SYS_ID'
}
-- Add a sufficient number of virtual timers
for i = 0, 127 do
timer_values[ sf( 'vtmr%d', i ) ] = sf( '( VTMR_FIRST_ID + %d )', i )
timer_values[ tostring( i ) ] = i
end
-------------------------------------------------------------------------------
-- EGC data
egc =
{
alloc_failure = 1,
mem_limit = 2,
always = 4
}

31
config/cpuconstants.lua Normal file
View File

@ -0,0 +1,31 @@
-- CPU constants generator
module( ..., package.seeall )
local sf = string.format
local gen = require "generators"
function gen_constants( desc )
local ct = desc.cpu_constants
if not ct then return '' end
local gstr = string.rep( "/", 80 ) .. "\n" .. "// Configured CPU constants\n\n"
-- There are two types of macros in cpu_constants: simple (that are already defined somewhere)
-- and full ((macro, def) pairs). We need to iterate over the full list first and define those
-- macros. After that we generate the whole PLATFORM_CPU_CONSTANTS_CONFIGURED macro
for _, m in pairs( ct ) do
if type( m ) == "table" then
local name, val = m[ 1 ], m[ 2 ]
gstr = gstr .. "\n#ifndef " .. name .. "\n"
gstr = gstr .. gen.print_define( name, val )
gstr = gstr .. "#endif\n\n"
end
end
gstr = gstr .. "#define PLATFORM_CPU_CONSTANTS_CONFIGURED\\\n"
for _, m in pairs( ct ) do
gstr = gstr .. sf( " _C( %s ),\\\n", type( m ) == "string" and m or m[ 1 ] )
end
gstr = gstr .. "\n"
return gstr:gsub( "\n\n\n", "\n\n" )
end

40
config/generators.lua Normal file
View File

@ -0,0 +1,40 @@
-- Code generators for various attributes and other constructs
module( ..., package.seeall )
local sf = string.format
local MACRO_DEF_POS = 41
-- Formatted print for "#define"
function print_define( k, v )
local s = sf( "#define %s", k )
if v then
if #s < MACRO_DEF_POS then s = s .. string.rep( ' ', MACRO_DEF_POS - #s ) end
else
v = ''
end
s = s .. tostring( v ) .. "\n"
return s
end
-- Simple generator for an attribute
function simple_gen( attrname, conf, gentable )
if gentable[ attrname ] then return '' end
if not conf[ attrname ] then return '' end
local adesc, aval = conf[ attrname ].desc, conf[ attrname ].value
gentable[ attrname ] = true
if adesc.is_ip then -- special generation for this one
local s = ''
for i = 1, 4 do
s = s .. print_define( sf( "%s%d", attrname, i - 1 ), aval[ i ] )
end
return s
end
if adesc.mapping then aval = adesc.mapping[ aval ] end
if adesc.is_array then
-- The element is an array. The default is to define its value as { elements }
aval = "{ " .. table.concat( aval, "," ) .. " }"
end
return print_define( attrname, tostring( aval ) )
end

194
config/modules.lua Normal file
View File

@ -0,0 +1,194 @@
-- Build configuration: module selection
module( ..., package.seeall )
local sf = string.format
local gen = require "generators"
-- List of all generic modules and their build guards
-- (if the module guard evaluates to false at compile time, the module is not included in the build)
local generic_modules = {
adc = { "BUILD_ADC", "NUM_ADC > 0" },
bit = {},
can = { "NUM_CAN > 0"},
cpu = {},
elua = {},
i2c = { "NUM_I2C > 0" },
pack = {},
rpc = { "BUILD_RPC" },
net = { "BUILD_UIP" },
pd = {},
pio = { "NUM_PIO > 0" },
pwm = { "NUM_PWM > 0" },
spi = { "NUM_SPI > 0" },
term = { "BUILD_TERM" },
tmr = { "NUM_TIMER > 0" },
uart = { "NUM_UART > 0" },
math = {}
}
-- Auxlib names
local auxlibs = { math = "LUA_MATHLIBNAME" }
-- Open function names
local opennames = {}
-- Map array names
local mapnames = {}
-- Return the auxlib name of a given module
local function get_auxlib( m )
return auxlibs[ m ] or sf( "AUXLIB_%s", m:upper() )
end
-- Return the open function name of a given module
local function get_openf_name( m )
return opennames[ m ] or sf( "luaopen_%s", m:lower() )
end
-- Return the map array name of a given module
local function get_map_name( m )
return mapnames[ m ] or sf( "%s_map", m:lower() )
end
-- Generate a condition string starting from a guard
local function gen_cond_string( g )
local condition = ''
for idx, e in pairs( g ) do
local suffix = idx == #g and "" or " && "
if e:find( '%s' ) then -- if it has a string, add the condition as it was given, between parantheses
condition = condition .. "( " .. e .. " )"
else
condition = condition .. "defined( " .. e .. " )"
end
condition = condition .. suffix
end
return condition
end
-- Generate the complete module list starting from the board description
function gen_module_list( desc, plconf, platform )
local mdesc = desc.modules
if not mdesc then return '' end
local gen_list_generic, gen_list_platform = {}, {}
local platform_modules = plconf.get_platform_modules() or {}
local gstr = string.rep( "/", 80 ) .. "\n" .. "// Module configuration\n\n"
local ngenmods, nplmods = 0, 0
if mdesc == "all" then -- include all the modules. what a brave, brave soul.
for m, _ in pairs( generic_modules ) do
gen_list_generic[ m ] = true
ngenmods = ngenmods + 1
end
for m, _ in pairs( platform_modules ) do
gen_list_platform[ m ] = true
nplmods = nplmods + 1
end
else
-- Include only some modules. Validate their names against the corresponding module list
if mdesc.generic == "all" then -- all generic modules
for m, _ in pairs( generic_modules ) do
gen_list_generic[ m ] = true
ngenmods = ngenmods + 1
end
elseif mdesc.generic then
for _, m in pairs( mdesc.generic ) do
if not generic_modules[ m ] then return false, sf( "unknown generic module '%s' in section 'modules'", m ) end
gen_list_generic[ m ] = true
ngenmods = ngenmods + 1
end
end
if mdesc.platform == "all" then -- all platform modules
for m, _ in pairs( platform_modules ) do
gen_list_platform[ m ] = true
nplmods = nplmods + 1
end
elseif mdesc.platform then
for _, m in pairs( mdesc.platform ) do
if not platform_modules[ m ] then return false, sf( "unknown platform module '%s' in section 'modules'", m ) end
gen_list_platform[ m ] = true
nplmods = nplmods + 1
end
end
end
-- Need to exclude anything?
if type( mdesc.exclude_generic ) == "table" then
for _, m in pairs( mdesc.exclude_generic ) do
if not gen_list_generic[ m ] then
return false, sf( "module '%s' in exclude_generic not found in the generic module list", m )
end
gen_list_generic[ m ] = nil
ngenmods = ngenmods - 1
end
end
if type( mdesc.exclude_platform ) == "table" then
for _, m in pairs( mdesc.exclude_platform ) do
if not gen_list_platform[ m ] then
return false, sf( "module '%s' in exclude_platform not found in the platform specific module list", m )
end
gen_list_platform[ m ] = nil
nplmods = nplmods - 1
end
end
if ngenmods + nplmods == 0 then return '' end
-- Now build all the module lines, starting from the gen_list and the guards
-- First define the platform specific line if needed
if nplmods > 0 then
-- The (hopefully) proper way to generate this is a bit tricky. We enable the
-- platform module if _any_ of the modules in gen_list_platform can be enabled.
-- In order to do this, we gather their guards in a single, long condition
-- Count all guards first
local nguards = 0
for m, _ in pairs( gen_list_platform ) do nguards = nguards + #platform_modules[ m ] end
if nguards == 0 then -- nothing to guard
gstr = gstr .. gen.print_define( "PLATFORM_MODULES_LINE", sf( '_ROM( "%s", luaopen_platform, platform_map )', platform ) )
gstr = gstr .. gen.print_define( "PS_LIB_TABLE_NAME", sf( '"%s"', platform ) )
gstr = gstr .. gen.print_define( "PLATFORM_MODULES_ENABLE" )
else
-- Gather the composed condition in 'cond'
local cond = '\n#if 0' -- the '0' is included here for an easier generation of the composed condition
for m, _ in pairs( gen_list_platform ) do
local g = platform_modules[ m ]
if #g > 0 then
cond = cond .. " || ( " .. gen_cond_string( g ) .. " )"
end
end
gstr = gstr .. cond .. "\n"
gstr = gstr .. gen.print_define( "PLATFORM_MODULES_LINE", sf( '_ROM( "%s", luaopen_platform, platform_map )', platform ) )
gstr = gstr .. gen.print_define( "PS_LIB_TABLE_NAME", sf( '"%s"', platform ) )
gstr = gstr .. gen.print_define( "PLATFORM_MODULES_ENABLE" )
gstr = gstr .. "#else\n"
gstr = gstr .. gen.print_define( sf( "PLATFORM_MODULES_LINE" ) )
gstr = gstr .. sf( "#warning Unable to include platform modules in the image\n#endif\n\n" )
end
else -- no platform modules here, people. move along.
gstr = gstr .. gen.print_define( "PLATFORM_MODULES_LINE" )
end
for m, _ in pairs( gen_list_generic ) do
local g = generic_modules[ m ]
if #g == 0 then -- no guards
gstr = gstr .. gen.print_define( sf( "MODULE_%s_LINE", m:upper() ), sf( "_ROM( %s, %s, %s )", get_auxlib( m ), get_openf_name( m ), get_map_name( m ) ) )
else
-- Check the guard. If the guard is not satisfied, issue a compile time warning and set the line as empty
gstr = gstr .. "\n#if " .. gen_cond_string( g ) .. "\n"
gstr = gstr .. gen.print_define( sf( "MODULE_%s_LINE", m:upper() ), sf( "_ROM( %s, %s, %s )", get_auxlib( m ), get_openf_name( m ), get_map_name( m ) ) )
gstr = gstr .. "#else\n"
gstr = gstr .. gen.print_define( sf( "MODULE_%s_LINE", m:upper() ) )
gstr = gstr .. sf( "#warning Unable to include module '%s' in the image\n#endif\n\n", m )
end
end
gstr = gstr .. "\n"
-- Finally, generate the acutal list of libraries. Phew.
gstr = gstr .. "#define LUA_PLATFORM_LIBS_ROM\\\n PLATFORM_MODULES_LINE"
for m, _ in pairs( gen_list_generic ) do
gstr = gstr .. sf( "\\\n MODULE_%s_LINE", m:upper() )
end
gstr = gstr .. "\n"
-- A bit of cosmetic touch ...
gstr = gstr .. "\n"
gstr = gstr:gsub( "\n\n\n", "\n\n" )
return gstr
end

174
config/sections.lua Normal file
View File

@ -0,0 +1,174 @@
-- Sections (collection of elements) management
module( ..., package.seeall )
local sf = string.format
local gen = require "generators"
local utils = require "utils"
conf, enabled, required = {}, {}, {}
-- Enables and configures an element (a collection of attributes)
-- section - the section of the element
-- sectname - the name of the section that contains the element (components, config ...)
-- name - name of the element
-- data - values of attributes in the element
-- req: required mode. true if this element's value are forced to its required values, false otherwise
-- Returns true if OK, (false, err) for error
function config_element( section, sectname, name, data, req )
local desc = section[ name ]
local attrs = desc.attrs or {}
-- Process each element in 'data' in turn
for attr, v in pairs( data ) do
local attrmeta = attrs[ attr ]
if not attrmeta then return false, sf( "attribute '%s' is not defined for element '%s' in section '%s'", attr, name, sectname ) end
if attrmeta.validator and not req then
local res, err = attrmeta:validator( attr, v, name, sectname )
if not res then
return false, err
else
-- The validator can also change the attribute's value
v = res
end
end
if conf[ attrmeta.macro ] and tostring( conf[ attrmeta.macro ].value ) ~= tostring( v ) and not conf[ attrmeta.macro ].from_default then
print( utils.col_yellow( sf( "[CONFIG] WARNING: overriding value of attribute '%s' in element '%s' from '%s' to '%s' in section '%s'",
attr, name, conf[ attrmeta.macro ].value, v, sectname ) ) )
end
conf[ attrmeta.macro ] = { name = attr, desc = attrmeta, value = v, sectname = sectname, elname = name, from_default = false }
end
-- Set default values where needed
for name, data in pairs( attrs ) do
if not conf[ data.macro ] and data.default then
conf[ data.macro ] = { name = name, desc = data, value = data.default, sectname = sectname, elname = name, from_default = true }
end
end
-- Mark this component as configured
enabled[ name ] = true
if req then required[ name ] = true end
return true
end
-- Configures the given section
-- section: the section that will be compiled
-- sectname: the name of the section
-- data: the data corresponding to the section
-- Returns true if OK, (false, errmsg) for error
function configure_section( section, sectname, data )
conf, enabled, required = {}, {}, {}
-- Configure each element in turn, doing validation if required
for elname, elval in pairs( data ) do
if not section[ elname ] then return nil, sf( "unknown element '%s' in section '%s'", elname, sectname ) end
-- Handle the special situation <elname> = true (or anything else that is not false)
if type( elval ) ~= "table" and elval then
data[ elname ] = {}
elval = data[ elname ]
end
if elval then
local cres, cerr = config_element( section, sectname, elname, elval )
if not cres then return false, cerr end
end
end
-- We also need to generated required elements. A required element is an element that
-- is generated every time, even if it was not specified in the configuration file.
for elname, eldesc in pairs( section ) do
if eldesc.required and not enabled[ elname ] then
config_element( section, sectname, elname, eldesc.required, true )
end
end
-- Step 2: basic consistency check
-- For each element, we check that all its required attributes (the ones that don't have
-- an 'optional' key set to true) have a value. An element can overwrite this default
-- verification by specifying its own 'confcheck' function. There is another function called
-- 'auxcheck' that is called AFTER the basic consistency check (if it exists)
for elname, _ in pairs( enabled ) do
if not required[ elname ] then
local desc = section[ elname ]
local attrs = desc.attrs or {}
if desc.confcheck then
local d, err = desc:confcheck( conf, enabled )
if not d then return false, err end
else
for attr, adesc in pairs( attrs ) do
if not conf[ adesc.macro ] and not adesc.optional then
return false, sf( "required attribute '%s' of component '%s' in section '%s' not specified", attr, elname, sectname )
end
end
if desc.auxcheck then
local d, err = desc:auxcheck( conf, enabled )
if not d then return false, err end
end
end
end
end
return true
end
-- Generate configuration data for the given section (must be called after configure_section!)
-- section: the section that will be compiled
-- sectname: the name of the section
-- data: the data corresponding to the section
-- Returns the generated header if OK, (false, errmsg) for error
function generate_section( section, sectname, data )
-- Actual generation of code
-- The default generator simply adds '#define KEY VALUE' pairs. An element can overwrite this
-- default generation by specifying its own 'gen' function. If the element has an 'auxgen'
-- function, it will be called after the default attribute generation
-- Also, we never generate the same key twice. We ensure this by keeping a table of the
-- keys that were already generated
local generated = {}
local genstr = string.rep( "/", 80 ) .. "\n" .. sf( "// Configuration for section '%s'\n\n", sectname )
for elname, _ in pairs( enabled ) do
local desc = section[ elname ]
local attrs = desc.attrs or {}
genstr = genstr .. sf( "// Configuration for element '%s'\n", elname )
if desc.gen then
genstr = genstr .. desc:gen( conf, generated )
else
for aname, adesc in pairs( attrs ) do
genstr = genstr .. gen.simple_gen( adesc.macro, conf, generated )
end
if desc.auxgen then genstr = genstr .. desc:auxgen( conf, generated ) end
end
-- Add the "build enable" macro
if desc.macro then
genstr = genstr .. gen.print_define( desc.macro ) .. "\n"
else
genstr = genstr .. "\n"
end
end
-- Finally, check for dependencies
-- For each attribute that has a 'needs' element, check if the dependency is met
-- The attribute can also define the 'depcheck' function for a default dependency check
for elname, _ in pairs( enabled ) do
local desc = section[ elname ]
if desc.depcheck then
local res, err = desc:depcheck( conf, generated )
if not res then return false, err end
elseif desc.needs then
local needs = type( desc.needs ) == "table" and desc.needs or { desc.needs }
for _, v in pairs( needs ) do
-- Look for negative expressions (not enabled)
local neg
if v:sub( 1, 1 ) == "!" then
neg = true
v = v:sub( 2 )
end
if not neg and not enabled[ v ] then
return false, sf( "element '%s' in section '%s' needs element '%s' to be enabled", elname, sectname, v )
elseif neg and enabled[ v ] then
return false, sf( "element '%s' in section '%s' needs element '%s' to be disabled", elname, sectname, v )
end
end
end
end
-- All done
return genstr
end

View File

@ -1,6 +1,9 @@
package.path = package.path .. ";../utils/?.lua;"
require "lfs"
require "eluadoc"
require "md5"
local utils = require "utils"
-- Uncomment this when generating offline docs
local is_offline = true
@ -150,21 +153,6 @@ local function copy_dir_rec( src, dst )
end
end
-- Remove a directory recusively
-- USE WITH CARE!! Doesn't do much checks :)
local function rm_dir_rec( dirname )
for f in lfs.dir( dirname ) do
local ename = string.format( "%s/%s", dirname, f )
local attrs = lfs.attributes( ename )
if attrs.mode == 'directory' and f ~= '.' and f ~= '..' then
rm_dir_rec( ename )
elseif attrs.mode == 'file' or attrs.mode == 'named pipe' or attrs.mode == 'link' then
os.remove( ename )
end
end
lfs.rmdir( dirname )
end
-- Copy a directory to another directory
local function copy_dir( src, dst )
local newdir = string.format( "%s/%s", dst, src )
@ -678,7 +666,7 @@ else
print( string.format( "%s is not a directory", destdir ) )
return
end
rm_dir_rec( destdir )
utils.rm_dir_rec( destdir )
lfs.mkdir( destdir )
end
@ -690,7 +678,7 @@ if cleancache then
print( "'cache' is not a directory" )
return
end
rm_dir_rec( 'cache' )
utils.rm_dir_rec( 'cache' )
lfs.mkdir( 'cache' )
end
end

19
inc/platform_conf.h Normal file
View File

@ -0,0 +1,19 @@
// Generic platform configuration file
#ifndef __PLATFORM_CONF_H__
#define __PLATFORM_CONF_H__
#include "buf.h"
#include "sermux.h"
#include "legc.h"
#include "platform.h"
#include "auxmods.h"
#include "elua_int.h"
#include "lualib.h"
#include ELUA_CPU_HEADER
#include ELUA_BOARD_HEADER
#include "platform_generic.h" // generic platform header (include whatever else is missing here)
#endif

View File

@ -4,7 +4,7 @@
stty -echo raw -igncr
# Run simulator
./elua_lua$1_linux.elf
./elua_lua$1_sim.elf
# Restore terminal to default settings
stty echo cooked

View File

@ -20,43 +20,14 @@
#include "lapi.h"
#include "lauxlib.h"
// [TODO] the new builder should automatically do this
#if defined( BUILD_LUA_INT_HANDLERS ) || defined( BUILD_C_INT_HANDLERS )
#define BUILD_INT_HANDLERS
#ifndef INT_TMR_MATCH
#define INT_TMR_MATCH ELUA_INT_INVALID_INTERRUPT
#endif
#ifdef BUILD_INT_HANDLERS
extern const elua_int_descriptor elua_int_table[ INT_ELUA_LAST ];
#endif // #ifdef BUILD_INT_HANDLERS
#endif // #if defined( BUILD_LUA_INT_HANDLERS ) || defined( BUILD_C_INT_HANDLERS )
// [TODO] the new builder should automatically do this
#ifndef VTMR_NUM_TIMERS
#define VTMR_NUM_TIMERS 0
#endif // #ifndef VTMR_NUM_TIMERS
// [TODO] the new builder should automatically do this
#ifndef CON_BUF_SIZE
#define CON_BUF_SIZE 0
#endif // #ifndef CON_BUF_SIZE
// [TODO] the new builder should automatically do this
#ifndef SERMUX_FLOW_TYPE
#define SERMUX_FLOW_TYPE PLATFORM_UART_FLOW_NONE
#endif
// [TODO] the new builder should automatically do this
#ifndef CON_FLOW_TYPE
#define CON_FLOW_TYPE PLATFORM_UART_FLOW_NONE
#endif
// [TODO] the new builder should automatically do this
#ifndef CON_TIMER_ID
#define CON_TIMER_ID PLATFORM_TIMER_SYS_ID
#endif
// ****************************************************************************
// XMODEM support code
@ -350,12 +321,12 @@ extern char end[];
void* platform_get_first_free_ram( unsigned id )
{
void* mstart[] = MEM_START_ADDRESS;
u32 mstart[] = MEM_START_ADDRESS;
u32 p;
if( id >= sizeof( mstart ) / sizeof( void* ) )
if( id >= sizeof( mstart ) / sizeof( u32 ) )
return NULL;
p = ( u32 )mstart[ id ];
p = mstart[ id ];
if( p & ( MIN_ALIGN - 1 ) )
p = ( ( p >> MIN_ALIGN_SHIFT ) + 1 ) << MIN_ALIGN_SHIFT;
return ( void* )p;
@ -363,12 +334,12 @@ void* platform_get_first_free_ram( unsigned id )
void* platform_get_last_free_ram( unsigned id )
{
void* mend[] = MEM_END_ADDRESS;
u32 mend[] = MEM_END_ADDRESS;
u32 p;
if( id >= sizeof( mend ) / sizeof( void* ) )
if( id >= sizeof( mend ) / sizeof( u32 ) )
return NULL;
p = ( u32 )mend[ id ];
p = mend[ id ];
if( p & ( MIN_ALIGN - 1 ) )
p = ( ( p >> MIN_ALIGN_SHIFT ) - 1 ) << MIN_ALIGN_SHIFT;
return ( void* )p;

View File

@ -40,21 +40,7 @@ char *boot_order[] = {
extern char etext[];
#ifdef ELUA_BOOT_RPC
#ifndef RPC_UART_ID
#define RPC_UART_ID CON_UART_ID
#endif
#ifndef RPC_TIMER_ID
#define RPC_TIMER_ID PLATFORM_TIMER_SYS_ID
#endif
#ifndef RPC_UART_SPEED
#define RPC_UART_SPEED CON_UART_SPEED
#endif
void boot_rpc( void )
{
lua_State *L = lua_open();
@ -70,7 +56,7 @@ void boot_rpc( void )
lua_pushnumber( L, RPC_TIMER_ID );
lua_pcall( L, 2, 0, 0 );
}
#endif
#endif // #ifdef ELUA_BOOT_RPC
// ****************************************************************************
// Program entry point

View File

@ -11,6 +11,22 @@
#define _C( x ) { #x, x }
#include "platform_conf.h"
#if defined( PLATFORM_CPU_CONSTANTS_INTS ) || defined( PLATFORM_CPU_CONSTANTS_PLATFORM ) || defined( PLATFORM_CPU_CONSTANTS_CONFIGURED )
#define HAS_CPU_CONSTANTS
#endif
#if defined( HAS_CPU_CONSTANTS ) && !defined( PLATFORM_CPU_CONSTANTS_INTS )
#define PLATFORM_CPU_CONSTANTS_INTS
#endif
#if defined( HAS_CPU_CONSTANTS ) && !defined( PLATFORM_CPU_CONSTANTS_PLATFORM )
#define PLATFORM_CPU_CONSTANTS_PLATFORM
#endif
#if defined( HAS_CPU_CONSTANTS ) && !defined( PLATFORM_CPU_CONSTANTS_CONFIGURED )
#define PLATFORM_CPU_CONSTANTS_CONFIGURED
#endif
// Lua: w32( address, data )
static int cpu_w32( lua_State *L )
{
@ -143,10 +159,12 @@ typedef struct
u32 val;
} cpu_const_t;
#ifdef PLATFORM_CPU_CONSTANTS
#ifdef HAS_CPU_CONSTANTS
static const cpu_const_t cpu_constants[] =
{
PLATFORM_CPU_CONSTANTS,
PLATFORM_CPU_CONSTANTS_INTS
PLATFORM_CPU_CONSTANTS_PLATFORM
PLATFORM_CPU_CONSTANTS_CONFIGURED
{ NULL, 0 }
};
@ -166,7 +184,7 @@ static int cpu_mt_index( lua_State *L )
}
return 0;
}
#endif
#endif // #ifdef HAS_CPU_CONSTANTS
#ifdef BUILD_LUA_INT_HANDLERS
@ -258,10 +276,10 @@ const LUA_REG_TYPE cpu_map[] =
{ LSTRKEY( "get_int_handler" ), LFUNCVAL( cpu_get_int_handler ) },
{ LSTRKEY( "get_int_flag" ), LFUNCVAL( cpu_get_int_flag) },
#endif
#if defined( PLATFORM_CPU_CONSTANTS ) && LUA_OPTIMIZE_MEMORY > 0
#if defined( HAS_CPU_CONSTANTS ) && LUA_OPTIMIZE_MEMORY > 0
{ LSTRKEY( "__metatable" ), LROVAL( cpu_map ) },
#endif
#ifdef PLATFORM_CPU_CONSTANTS
#ifdef HAS_CPU_CONSTANTS
{ LSTRKEY( "__index" ), LFUNCVAL( cpu_mt_index ) },
#endif
{ LNILKEY, LNILVAL }
@ -281,11 +299,11 @@ LUALIB_API int luaopen_cpu( lua_State *L )
// Register methods
luaL_register( L, AUXLIB_CPU, cpu_map );
#ifdef PLATFORM_CPU_CONSTANTS
#ifdef HAS_CPU_CONSTANTS
// Set table as its own metatable
lua_pushvalue( L, -1 );
lua_setmetatable( L, -2 );
#endif // #ifdef PLATFORM_CPU_CONSTANTS
#endif // #ifdef HAS_CPU_CONSTANTS
return 1;
#endif // #if LUA_OPTIMIZE_MEMORY > 0

View File

@ -0,0 +1,47 @@
// LPC2468 CPU definitions
#ifndef __CPU_LPC2468_H__
#define __CPU_LPC2468_H__
#include "stacks.h"
#include "target.h"
#include "platform_ints.h"
// Number of resources (0 if not available/not implemented)
#define NUM_PIO 5
#define NUM_SPI 0
#define NUM_UART 4
#define NUM_PWM 12
#define NUM_ADC 8
#define NUM_CAN 0
#define NUM_TIMER 4
// ADC Configuration Params
#define ADC_BIT_RESOLUTION 10
// CPU frequency (needed by the CPU module and MMCFS code, 0 if not used)
#define CPU_FREQUENCY Fcclk
// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...)
#define PIO_PREFIX '0'
// Pins per port configuration:
// #define PIO_PINS_PER_PORT (n) if each port has the same number of pins, or
// #define PIO_PIN_ARRAY { n1, n2, ... } to define pins per port in an array
// Use #define PIO_PINS_PER_PORT 0 if this isn't needed
#define PIO_PINS_PER_PORT 32
// Internal RAM
#define SRAM_ORIGIN 0x40000000
#define SRAM_SIZE 0x10000 // [TODO]: make this 96k?
#define INTERNAL_RAM_FIRST_FREE end
#define INTERNAL_RAM_LAST_FREE ( SRAM_ORIGIN + SRAM_SIZE - STACK_SIZE_TOTAL - 1 )
// Interrupt list for this CPU
#define PLATFORM_CPU_CONSTANTS_INTS\
_C( INT_GPIO_POSEDGE ), \
_C( INT_GPIO_NEGEDGE ), \
_C( INT_TMR_MATCH ), \
_C( INT_UART_RX ),
#endif // #ifndef __CPU_LPC2468_H__

View File

@ -1,197 +0,0 @@
// eLua platform configuration
#ifndef __PLATFORM_CONF_H__
#define __PLATFORM_CONF_H__
#include "auxmods.h"
#include "stacks.h"
#include "target.h"
#include "buf.h"
#include "elua_int.h"
#include "sermux.h"
// *****************************************************************************
// Define here what components you want for this platform
#define BUILD_XMODEM
#define BUILD_SHELL
#define BUILD_ROMFS
#define BUILD_TERM
#define BUILD_CON_GENERIC
#define BUILD_ADC
#define BUILD_RPC
//#define BUILD_RFS
//#define BUILD_SERMUX
#define BUILD_LUA_INT_HANDLERS
#define BUILD_C_INT_HANDLERS
#define PLATFORM_HAS_SYSTIMER
// *****************************************************************************
// UART/Timer IDs configuration data (used in main.c)
//#define CON_UART_ID ( SERMUX_SERVICE_ID_FIRST + 1 )
#define CON_UART_ID 0
#define CON_UART_SPEED 115200
#define TERM_LINES 25
#define TERM_COLS 80
// *****************************************************************************
// Auxiliary libraries that will be compiled for this platform
#ifdef BUILD_ADC
#define ADCLINE _ROM( AUXLIB_ADC, luaopen_adc, adc_map )
#else
#define ADCLINE
#endif
#if defined( ELUA_BOOT_RPC ) && !defined( BUILD_RPC )
#define BUILD_RPC
#endif
#if defined( BUILD_RPC )
#define RPCLINE _ROM( AUXLIB_RPC, luaopen_rpc, rpc_map )
#else
#define RPCLINE
#endif
#define LUA_PLATFORM_LIBS_ROM\
_ROM( AUXLIB_PIO, luaopen_pio, pio_map )\
_ROM( AUXLIB_TMR, luaopen_tmr, tmr_map )\
ADCLINE\
_ROM( AUXLIB_UART, luaopen_uart, uart_map )\
_ROM( AUXLIB_PIO, luaopen_pio, pio_map )\
_ROM( AUXLIB_PD, luaopen_pd, pd_map )\
_ROM( AUXLIB_TERM, luaopen_term, term_map )\
_ROM( AUXLIB_PACK, luaopen_pack, pack_map )\
_ROM( AUXLIB_BIT, luaopen_bit, bit_map )\
_ROM( AUXLIB_CPU, luaopen_cpu, cpu_map )\
_ROM( AUXLIB_ELUA, luaopen_elua, elua_map )\
_ROM( AUXLIB_PWM, luaopen_pwm, pwm_map )\
RPCLINE\
_ROM( LUA_MATHLIBNAME, luaopen_math, math_map )
// *****************************************************************************
// Configuration data
// Virtual timers (0 if not used)
#define VTMR_NUM_TIMERS 4
// NOTE: DON'T define VTMR_FREQ_HZ as 0!
#define VTMR_FREQ_HZ 4
// Number of resources (0 if not available/not implemented)
#define NUM_PIO 5
#define NUM_SPI 0
#define NUM_UART 4
#define NUM_PWM 12
#define NUM_ADC 8
#define NUM_CAN 0
// If virtual timers are enabled, the last timer will be used only for them
#if VTMR_NUM_TIMERS == 0
#define NUM_TIMER 4
#else
#define NUM_TIMER 3
#endif
// Interrupt data
#define PLATFORM_INT_QUEUE_LOG_SIZE BUF_SIZE_32
// Enable RX buffering on UART
#define BUF_ENABLE_UART
#define CON_BUF_SIZE BUF_SIZE_128
// ADC Configuration Params
#define ADC_BIT_RESOLUTION 10
#define BUF_ENABLE_ADC
#define ADC_BUF_SIZE BUF_SIZE_2
// These should be adjusted to support multiple ADC devices
#define ADC_TIMER_FIRST_ID 0
#define ADC_NUM_TIMERS 4
// RPC boot options
#define RPC_UART_ID CON_UART_ID
#define RPC_UART_SPEED CON_UART_SPEED
// CPU frequency (needed by the CPU module and MMCFS code, 0 if not used)
#define CPU_FREQUENCY Fcclk
// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...)
#define PIO_PREFIX '0'
// Pins per port configuration:
// #define PIO_PINS_PER_PORT (n) if each port has the same number of pins, or
// #define PIO_PIN_ARRAY { n1, n2, ... } to define pins per port in an array
// Use #define PIO_PINS_PER_PORT 0 if this isn't needed
#define PIO_PINS_PER_PORT 32
// Remote file system data
/*
#define RFS_BUFFER_SIZE BUF_SIZE_512
#define RFS_UART_ID ( SERMUX_SERVICE_ID_FIRST )
#define RFS_TIMEOUT 100000
#define RFS_UART_SPEED 115200
#define SERMUX_PHYS_ID 0
#define SERMUX_PHYS_SPEED 115200
#define SERMUX_NUM_VUART 2
#define SERMUX_BUFFER_SIZES { RFS_BUFFER_SIZE, CON_BUF_SIZE }
*/
// Allocator data: define your free memory zones here in two arrays
// (start address and end address)
#define SRAM_ORIGIN 0x40000000
#define SRAM_SIZE 0x10000 // [TODO]: make this 96k?
#ifdef ELUA_BOARD_ELUAPUC
#define SDRAM_BASE_ADDR2 0xA0000000
#define SDRAM_SIZE ( 8 * 1048576 )
#define MEM_START_ADDRESS { ( void* )end, ( void* )SDRAM_BASE_ADDR2 }
#define MEM_END_ADDRESS { ( void* )( SRAM_ORIGIN + SRAM_SIZE - STACK_SIZE_TOTAL - 1 ), ( void* )( SDRAM_BASE_ADDR2 + SDRAM_SIZE - 1 ) }
//#define MEM_START_ADDRESS { ( void* )SDRAM_BASE_ADDR2 }
//#define MEM_END_ADDRESS { ( void* )( SDRAM_BASE_ADDR2 + SDRAM_SIZE - 1 ) }
#else
#define MEM_START_ADDRESS { ( void* )end }
#define MEM_END_ADDRESS { ( void* )( SRAM_ORIGIN + SRAM_SIZE - STACK_SIZE_TOTAL - 1 ) }
#endif
// *****************************************************************************
// CPU constants that should be exposed to the eLua "cpu" module
#define PINSEL_BASE_ADDR 0xE002C000
#define IO_PINSEL0 ( PINSEL_BASE_ADDR + 0x00 )
#define IO_PINSEL1 ( PINSEL_BASE_ADDR + 0x04 )
#define IO_PINSEL2 ( PINSEL_BASE_ADDR + 0x08 )
#define IO_PINSEL3 ( PINSEL_BASE_ADDR + 0x0C )
#define IO_PINSEL4 ( PINSEL_BASE_ADDR + 0x10 )
#define IO_PINSEL5 ( PINSEL_BASE_ADDR + 0x14 )
#define IO_PINSEL6 ( PINSEL_BASE_ADDR + 0x18 )
#define IO_PINSEL7 ( PINSEL_BASE_ADDR + 0x1C )
#define IO_PINSEL8 ( PINSEL_BASE_ADDR + 0x20 )
#define IO_PINSEL9 ( PINSEL_BASE_ADDR + 0x24 )
#define IO_PINSEL10 ( PINSEL_BASE_ADDR + 0x28 )
// Interrupt list
#define INT_GPIO_POSEDGE ELUA_INT_FIRST_ID
#define INT_GPIO_NEGEDGE ( ELUA_INT_FIRST_ID + 1 )
#define INT_TMR_MATCH ( ELUA_INT_FIRST_ID + 2 )
#define INT_UART_RX ( ELUA_INT_FIRST_ID + 3 )
#define INT_ELUA_LAST INT_UART_RX
#define PLATFORM_CPU_CONSTANTS\
_C( IO_PINSEL0 ),\
_C( IO_PINSEL1 ),\
_C( IO_PINSEL2 ),\
_C( IO_PINSEL3 ),\
_C( IO_PINSEL4 ),\
_C( IO_PINSEL5 ),\
_C( IO_PINSEL6 ),\
_C( IO_PINSEL7 ),\
_C( IO_PINSEL8 ),\
_C( IO_PINSEL9 ),\
_C( IO_PINSEL10 ),\
_C( INT_GPIO_POSEDGE ),\
_C( INT_GPIO_NEGEDGE ),\
_C( INT_TMR_MATCH ),\
_C( INT_UART_RX )
#endif // #ifndef __PLATFORM_CONF_H__

View File

@ -0,0 +1,44 @@
// Platform-wide configuration file, included by platform_conf.h
#ifndef __PLATFORM_GENERIC_H__
#define __PLATFORM_GENERIC_H__
#define PLATFORM_HAS_SYSTIMER
// If virtual timers are enabled, the last timer will be used only for them
#if VTMR_NUM_TIMERS > 0
#undef NUM_TIMER
#define NUM_TIMER 3
#endif
// *****************************************************************************
// CPU constants that should be exposed to the eLua "cpu" module
#define PINSEL_BASE_ADDR 0xE002C000
#define IO_PINSEL0 ( PINSEL_BASE_ADDR + 0x00 )
#define IO_PINSEL1 ( PINSEL_BASE_ADDR + 0x04 )
#define IO_PINSEL2 ( PINSEL_BASE_ADDR + 0x08 )
#define IO_PINSEL3 ( PINSEL_BASE_ADDR + 0x0C )
#define IO_PINSEL4 ( PINSEL_BASE_ADDR + 0x10 )
#define IO_PINSEL5 ( PINSEL_BASE_ADDR + 0x14 )
#define IO_PINSEL6 ( PINSEL_BASE_ADDR + 0x18 )
#define IO_PINSEL7 ( PINSEL_BASE_ADDR + 0x1C )
#define IO_PINSEL8 ( PINSEL_BASE_ADDR + 0x20 )
#define IO_PINSEL9 ( PINSEL_BASE_ADDR + 0x24 )
#define IO_PINSEL10 ( PINSEL_BASE_ADDR + 0x28 )
#define PLATFORM_CPU_CONSTANTS_PLATFORM\
_C( IO_PINSEL0 ),\
_C( IO_PINSEL1 ),\
_C( IO_PINSEL2 ),\
_C( IO_PINSEL3 ),\
_C( IO_PINSEL4 ),\
_C( IO_PINSEL5 ),\
_C( IO_PINSEL6 ),\
_C( IO_PINSEL7 ),\
_C( IO_PINSEL8 ),\
_C( IO_PINSEL9 ),\
_C( IO_PINSEL10 ),
#endif // #ifndef __PLATFORM_GENERIC_H__

View File

@ -0,0 +1,15 @@
// This header lists all interrupts defined for this platform
#ifndef __PLATFORM_INTS_H__
#define __PLATFORM_INTS_H__
#include "elua_int.h"
#define INT_GPIO_POSEDGE ELUA_INT_FIRST_ID
#define INT_GPIO_NEGEDGE ( ELUA_INT_FIRST_ID + 1 )
#define INT_TMR_MATCH ( ELUA_INT_FIRST_ID + 2 )
#define INT_UART_RX ( ELUA_INT_FIRST_ID + 3 )
#define INT_ELUA_LAST INT_UART_RX
#endif // #ifndef __PLATFORM_INTS_H__

View File

@ -0,0 +1,32 @@
// Linux "CPU" description for the eLua simulator
#ifndef __CPU_LINUX_H__
#define __CPU_LINUX_H__
// Number of resources (0 if not available/not implemented)
#define NUM_PIO 0
#define NUM_SPI 0
#define NUM_UART 0
#define NUM_TIMER 0
#define NUM_PWM 0
#define NUM_ADC 0
#define NUM_CAN 0
// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...)
#define PIO_PREFIX 'A'
// Pins per port configuration:
// #define PIO_PINS_PER_PORT (n) if each port has the same number of pins, or
// #define PIO_PIN_ARRAY { n1, n2, ... } to define pins per port in an array
// Use #define PIO_PINS_PER_PORT 0 if this isn't needed
#define PIO_PINS_PER_PORT 0
// Allocator data: define your free memory zones here in two arrays
// (start address and end address)
extern void *memory_start_address;
extern void *memory_end_address;
#define MEM_LENGTH (1024 * 1024)
#define INTERNAL_RAM_FIRST_FREE ( void* )memory_start_address
#define INTERNAL_RAM_LAST_FREE ( void* )memory_end_address
#endif

View File

@ -1,78 +0,0 @@
// eLua platform configuration
#ifndef __PLATFORM_CONF_H__
#define __PLATFORM_CONF_H__
#include "auxmods.h"
#include "type.h"
#include "stacks.h"
#include "buf.h"
// *****************************************************************************
// Define here what components you want for this platform
#define BUILD_SHELL
#define BUILD_ROMFS
#define BUILD_CON_GENERIC
#define BUILD_TERM
//#define BUILD_RFS
#define BUILD_WOFS
#define TERM_LINES 25
#define TERM_COLS 80
#define PLATFORM_HAS_SYSTIMER
// *****************************************************************************
// Auxiliary libraries that will be compiled for this platform
#define LUA_PLATFORM_LIBS_ROM\
_ROM( AUXLIB_PD, luaopen_pd, pd_map )\
_ROM( LUA_MATHLIBNAME, luaopen_math, math_map )\
_ROM( AUXLIB_TERM, luaopen_term, term_map )\
_ROM( AUXLIB_ELUA, luaopen_elua, elua_map )\
_ROM( AUXLIB_TMR, luaopen_tmr, tmr_map )\
// Bogus defines for common.c
#define CON_UART_ID 0
#define CON_UART_SPEED 0
// *****************************************************************************
// Configuration data
// Virtual timers (0 if not used)
#define VTMR_NUM_TIMERS 0
// Number of resources (0 if not available/not implemented)
#define NUM_PIO 0
#define NUM_SPI 0
#define NUM_UART 0
#define NUM_TIMER 0
#define NUM_PWM 0
#define NUM_ADC 0
#define NUM_CAN 0
// CPU frequency (needed by the CPU module and MMCFS code, 0 if not used)
#define CPU_FREQUENCY 0
// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...)
#define PIO_PREFIX 'A'
// Pins per port configuration:
// #define PIO_PINS_PER_PORT (n) if each port has the same number of pins, or
// #define PIO_PIN_ARRAY { n1, n2, ... } to define pins per port in an array
// Use #define PIO_PINS_PER_PORT 0 if this isn't needed
#define PIO_PINS_PER_PORT 0
// Allocator data: define your free memory zones here in two arrays
// (start address and end address)
extern void *memory_start_address;
extern void *memory_end_address;
#define MEM_LENGTH (1024 * 1024)
#define MEM_START_ADDRESS { ( void* )memory_start_address }
#define MEM_END_ADDRESS { ( void* )memory_end_address }
// RFS configuration
#define RFS_TIMEOUT 0 // dummy, always blocking by implementation
#define RFS_BUFFER_SIZE BUF_SIZE_512
#endif // #ifndef __PLATFORM_CONF_H__

View File

@ -0,0 +1,9 @@
// Included by platform_conf.h for platform customizations
#ifndef __PLATFORM_GENERIC_H__
#define __PLATFORM_GENERIC_H__
#define PLATFORM_HAS_SYSTIMER
#endif // #ifndef __PLATFORM_GENERIC_H__

View File

@ -0,0 +1,19 @@
-- This is the platform specific board configuration file
-- It is used by the generic board configuration system (config/)
module( ..., package.seeall )
-- Add specific components to the 'components' table
function add_platform_components( t )
t.stm32_enc = { macro = 'ENABLE_ENC' }
end
-- Add specific configuration to the 'configs' table
function add_platform_configs( t )
end
-- Return an array of all the available platform modules for the given cpu
function get_platform_modules( cpu )
return { enc = { 'ENABLE_ENC' } }
end

View File

@ -0,0 +1,51 @@
// CPU definition file for STM32F103RE
#ifndef __CPU_STM32F103RE_H__
#define __CPU_STM32F103RE_H__
#include "type.h"
#include "stacks.h"
#include "stm32f10x.h"
#include "platform_ints.h"
// Number of resources (0 if not available/not implemented)
#define NUM_PIO 7
#define NUM_SPI 2
#define NUM_UART 5
#define NUM_TIMER 5
#define NUM_PHYS_TIMER 5
#define NUM_PWM 4
#define NUM_ADC 16
#define NUM_CAN 1
#define ADC_BIT_RESOLUTION 12
u32 platform_s_cpu_get_frequency();
#define CPU_FREQUENCY platform_s_cpu_get_frequency()
// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...)
#define PIO_PREFIX 'A'
// Pins per port configuration:
// #define PIO_PINS_PER_PORT (n) if each port has the same number of pins, or
// #define PIO_PIN_ARRAY { n1, n2, ... } to define pins per port in an array
// Use #define PIO_PINS_PER_PORT 0 if this isn't needed
#define PIO_PINS_PER_PORT 16
// Internal memory data
#define SRAM_SIZE ( 64 * 1024 )
#define INTERNAL_RAM_FIRST_FREE end
#define INTERNAL_RAM_LAST_FREE ( SRAM_BASE + SRAM_SIZE - STACK_SIZE_TOTAL - 1 )
#define INTERNAL_FLASH_SIZE ( 512 * 1024 )
#define INTERNAL_FLASH_SECTOR_SIZE 2048
#define INTERNAL_FLASH_START_ADDRESS 0x08000000
// Interrupt list for this CPU
#define PLATFORM_CPU_CONSTANTS_INTS\
_C( INT_GPIO_POSEDGE ), \
_C( INT_GPIO_NEGEDGE ), \
_C( INT_TMR_MATCH ), \
_C( INT_UART_RX ),
#endif // #ifndef __CPU_STM32F103RE_H__

View File

@ -0,0 +1,14 @@
// CPU definition file for STM32F103ZE
// Use the STM32F103RE description as a base
#ifndef __CPU_STM32F103ZE_H__
#define __CPU_STM32F103ZE_H__
#include "cpu_stm32f103re.h"
// 21 ADCs instead of 16
#undef NUM_ADC
#define NUM_ADC 21
#endif // #ifndef __CPU_STM32F103ZE_H__

View File

@ -1,200 +0,0 @@
// eLua platform configuration
#ifndef __PLATFORM_CONF_H__
#define __PLATFORM_CONF_H__
#include "auxmods.h"
#include "type.h"
#include "stacks.h"
#include "stm32f10x.h"
#include "elua_int.h"
#include "sermux.h"
// *****************************************************************************
// Define here what components you want for this platform
#define BUILD_XMODEM
#define BUILD_SHELL
#define BUILD_ROMFS
//#define BUILD_MMCFS
#define BUILD_TERM
//#define BUILD_UIP
//#define BUILD_DHCPC
//#define BUILD_DNS
#define BUILD_CON_GENERIC
#define BUILD_ADC
#define BUILD_RPC
//#define BUILD_RFS
//#define BUILD_CON_TCP
#define BUILD_LINENOISE
#define BUILD_C_INT_HANDLERS
#define BUILD_LUA_INT_HANDLERS
#define ENABLE_ENC
#define PLATFORM_HAS_SYSTIMER
// *****************************************************************************
// UART/Timer IDs configuration data (used in main.c)
#define CON_UART_ID 0
#define CON_UART_SPEED 115200
#define TERM_LINES 25
#define TERM_COLS 80
// *****************************************************************************
// Auxiliary libraries that will be compiled for this platform
//#ifdef FORSTM3210E_EVAL
//#define AUXLIB_LCD "stm3210lcd"
//LUALIB_API int ( luaopen_lcd )( lua_State* L );
//#define LCDLINE _ROM( AUXLIB_LCD, luaopen_lcd, lcd_map )
//#else
#define LCDLINE
//#endif
#ifdef ENABLE_ENC
#define PS_LIB_TABLE_NAME "stm32"
#endif
#ifdef BUILD_ADC
#define ADCLINE _ROM( AUXLIB_ADC, luaopen_adc, adc_map )
#else
#define ADCLINE
#endif
#if defined( ELUA_BOOT_RPC ) && !defined( BUILD_RPC )
#define BUILD_RPC
#endif
#if defined( BUILD_RPC )
#define RPCLINE _ROM( AUXLIB_RPC, luaopen_rpc, rpc_map )
#else
#define RPCLINE
#endif
#ifdef PS_LIB_TABLE_NAME
#define PLATLINE _ROM( PS_LIB_TABLE_NAME, luaopen_platform, platform_map )
#else
#define PLATLINE
#endif
#define LUA_PLATFORM_LIBS_ROM\
_ROM( AUXLIB_PIO, luaopen_pio, pio_map )\
_ROM( AUXLIB_SPI, luaopen_spi, spi_map )\
_ROM( AUXLIB_PD, luaopen_pd, pd_map )\
_ROM( AUXLIB_UART, luaopen_uart, uart_map )\
_ROM( AUXLIB_TERM, luaopen_term, term_map )\
_ROM( AUXLIB_PACK, luaopen_pack, pack_map )\
_ROM( AUXLIB_BIT, luaopen_bit, bit_map )\
_ROM( AUXLIB_CPU, luaopen_cpu, cpu_map )\
_ROM( AUXLIB_ELUA, luaopen_elua, elua_map )\
_ROM( AUXLIB_TMR, luaopen_tmr, tmr_map )\
ADCLINE\
_ROM( AUXLIB_CAN, luaopen_can, can_map )\
_ROM( AUXLIB_PWM, luaopen_pwm, pwm_map )\
RPCLINE\
LCDLINE\
_ROM( AUXLIB_ELUA, luaopen_elua, elua_map )\
_ROM( LUA_MATHLIBNAME, luaopen_math, math_map )\
PLATLINE
// *****************************************************************************
// Configuration data
#define EGC_INITIAL_MODE 1
// Virtual timers (0 if not used)
#define VTMR_NUM_TIMERS 4
#define VTMR_FREQ_HZ 10
// Number of resources (0 if not available/not implemented)
#define NUM_PIO 7
#define NUM_SPI 2
#define NUM_UART 5
#define NUM_TIMER 5
#define NUM_PHYS_TIMER 5
#define NUM_PWM 4
#define NUM_ADC 16
#define NUM_CAN 1
// Enable RX buffering on UART
#define BUF_ENABLE_UART
#define CON_BUF_SIZE BUF_SIZE_128
// ADC Configuration Params
#define ADC_BIT_RESOLUTION 12
#define BUF_ENABLE_ADC
#define ADC_BUF_SIZE BUF_SIZE_2
// These should be adjusted to support multiple ADC devices
#define ADC_TIMER_FIRST_ID 0
#define ADC_NUM_TIMERS 4
// RPC boot options
#define RPC_UART_ID CON_UART_ID
#define RPC_UART_SPEED CON_UART_SPEED
// MMCFS Support (FatFs on SD/MMC)
// For STM32F103RET6 - PA5 = CLK, PA6 = MISO, PA7 = MOSI, PA8 = CS
#define MMCFS_CS_PORT 0
#define MMCFS_CS_PIN 8
#define MMCFS_SPI_NUM 0
// CPU frequency (needed by the CPU module, 0 if not used)
u32 platform_s_cpu_get_frequency();
#define CPU_FREQUENCY platform_s_cpu_get_frequency()
// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...)
#define PIO_PREFIX 'A'
// Pins per port configuration:
// #define PIO_PINS_PER_PORT (n) if each port has the same number of pins, or
// #define PIO_PIN_ARRAY { n1, n2, ... } to define pins per port in an array
// Use #define PIO_PINS_PER_PORT 0 if this isn't needed
#define PIO_PINS_PER_PORT 16
// Remote file system data
#define RFS_BUFFER_SIZE BUF_SIZE_512
#define RFS_UART_ID 0
#define RFS_TIMEOUT 100000
#define RFS_UART_SPEED 115200
// Linenoise buffer sizes
#define LINENOISE_HISTORY_SIZE_LUA 50
#define LINENOISE_HISTORY_SIZE_SHELL 10
// Allocator data: define your free memory zones here in two arrays
// (start address and end address)
#define SRAM_SIZE ( 64 * 1024 )
#define MEM_START_ADDRESS { ( void* )end }
#define MEM_END_ADDRESS { ( void* )( SRAM_BASE + SRAM_SIZE - STACK_SIZE_TOTAL - 1 ) }
// Flash data (only for STM32F103RE for now)
#ifdef ELUA_CPU_STM32F103RE
#define INTERNAL_FLASH_SIZE ( 512 * 1024 )
#define INTERNAL_FLASH_SECTOR_SIZE 2048
#define INTERNAL_FLASH_START_ADDRESS 0x08000000
#define BUILD_WOFS
#endif // #ifdef ELUA_CPU_STM32F103RE
// Interrupt queue size
#define PLATFORM_INT_QUEUE_LOG_SIZE 5
// Interrupt list
#define INT_GPIO_POSEDGE ELUA_INT_FIRST_ID
#define INT_GPIO_NEGEDGE ( ELUA_INT_FIRST_ID + 1 )
#define INT_TMR_MATCH ( ELUA_INT_FIRST_ID + 2 )
#define INT_UART_RX ( ELUA_INT_FIRST_ID + 3 )
#define INT_ELUA_LAST INT_UART_RX
#define PLATFORM_CPU_CONSTANTS\
_C( INT_GPIO_POSEDGE ), \
_C( INT_GPIO_NEGEDGE ), \
_C( INT_TMR_MATCH ), \
_C( INT_UART_RX )
#endif // #ifndef __PLATFORM_CONF_H__

View File

@ -0,0 +1,9 @@
// Generic platform-wide header
#ifndef __PLATFORM_GENERIC_H__
#define __PLATFORM_GENERIC_H__
#define PLATFORM_HAS_SYSTIMER
#endif // #ifndef __PLATFORM_GENERIC_H__

View File

@ -0,0 +1,15 @@
// This header lists all interrupts defined for this platform
#ifndef __PLATFORM_INTS_H__
#define __PLATFORM_INTS_H__
#include "elua_int.h"
#define INT_GPIO_POSEDGE ELUA_INT_FIRST_ID
#define INT_GPIO_NEGEDGE ( ELUA_INT_FIRST_ID + 1 )
#define INT_TMR_MATCH ( ELUA_INT_FIRST_ID + 2 )
#define INT_UART_RX ( ELUA_INT_FIRST_ID + 3 )
#define INT_ELUA_LAST INT_UART_RX
#endif // #ifndef __PLATFORM_INTS_H__

View File

@ -0,0 +1,34 @@
// STR711FR2 CPU description
#ifndef __CPU_STR711FR2_H__
#define __CPU_STR711FR2_H__
#include "stacks.h"
// Number of resources (0 if not available/not implemented)
#define NUM_PIO 2
#define NUM_SPI 0
#define NUM_UART 4
#define NUM_TIMER 4
#define NUM_PWM 3
#define NUM_ADC 0
#define NUM_CAN 0
// CPU frequency (needed by the CPU module and MMCFS code, 0 if not used)
#define CPU_FREQUENCY 0
// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...)
#define PIO_PREFIX '0'
// Pins per port configuration:
// #define PIO_PINS_PER_PORT (n) if each port has the same number of pins, or
// #define PIO_PIN_ARRAY { n1, n2, ... } to define pins per port in an array
// Use #define PIO_PINS_PER_PORT 0 if this isn't needed
#define PIO_PINS_PER_PORT 16
#define SRAM_ORIGIN 0x20000000
#define SRAM_SIZE 0x10000
#define INTERNAL_RAM_FIRST_FREE end
#define INTERNAL_RAM_LAST_FREE ( SRAM_ORIGIN + SRAM_SIZE - STACK_SIZE_TOTAL - 1 )
#endif // #ifndef __CPU_STR711FR2_H__

View File

@ -1,94 +0,0 @@
// eLua platform configuration
#ifndef __PLATFORM_CONF_H__
#define __PLATFORM_CONF_H__
#include "auxmods.h"
#include "stacks.h"
// *****************************************************************************
// Define here what components you want for this platform
#define BUILD_XMODEM
#define BUILD_SHELL
#define BUILD_ROMFS
#define BUILD_TERM
#define BUILD_CON_GENERIC
//#define BUILD_RPC
// *****************************************************************************
// UART/Timer IDs configuration data (used in main.c)
#define CON_UART_ID 1
#define CON_UART_SPEED 38400
#define CON_TIMER_ID 0
#define TERM_LINES 25
#define TERM_COLS 80
// *****************************************************************************
// Auxiliary libraries that will be compiled for this platform
#if defined( ELUA_BOOT_RPC ) && !defined( BUILD_RPC )
#define BUILD_RPC
#endif
#if defined( BUILD_RPC )
#define RPCLINE _ROM( AUXLIB_RPC, luaopen_rpc, rpc_map )
#else
#define RPCLINE
#endif
#define LUA_PLATFORM_LIBS_ROM\
_ROM( AUXLIB_PIO, luaopen_pio, pio_map )\
_ROM( AUXLIB_TMR, luaopen_tmr, tmr_map )\
_ROM( AUXLIB_PD, luaopen_pd, pd_map )\
_ROM( AUXLIB_PWM, luaopen_pwm, pwm_map )\
_ROM( AUXLIB_UART, luaopen_uart, uart_map )\
_ROM( AUXLIB_TERM, luaopen_term, term_map )\
_ROM( AUXLIB_PACK, luaopen_pack, pack_map )\
_ROM( AUXLIB_BIT, luaopen_bit, bit_map )\
_ROM( AUXLIB_ELUA, luaopen_elua, elua_map )\
_ROM( AUXLIB_CPU, luaopen_cpu, cpu_map )\
RPCLINE\
_ROM( LUA_MATHLIBNAME, luaopen_math, math_map )
// *****************************************************************************
// Configuration data
// Virtual timers (0 if not used)
#define VTMR_NUM_TIMERS 0
#define VTMR_FREQ_HZ 4
// Number of resources (0 if not available/not implemented)
#define NUM_PIO 2
#define NUM_SPI 0
#define NUM_UART 4
#define NUM_TIMER 4
#define NUM_PWM 3
#define NUM_ADC 0
#define NUM_CAN 0
// RPC boot options
#define RPC_UART_ID CON_UART_ID
#define RPC_TIMER_ID CON_TIMER_ID
#define RPC_UART_SPEED CON_UART_SPEED
// CPU frequency (needed by the CPU module and MMCFS code, 0 if not used)
#define CPU_FREQUENCY 0
// PIO prefix ('0' for P0, P1, ... or 'A' for PA, PB, ...)
#define PIO_PREFIX '0'
// Pins per port configuration:
// #define PIO_PINS_PER_PORT (n) if each port has the same number of pins, or
// #define PIO_PIN_ARRAY { n1, n2, ... } to define pins per port in an array
// Use #define PIO_PINS_PER_PORT 0 if this isn't needed
#define PIO_PINS_PER_PORT 16
// Allocator data: define your free memory zones here in two arrays
// (start address and end address)
#define SRAM_ORIGIN 0x20000000
#define SRAM_SIZE 0x10000
#define MEM_START_ADDRESS { ( void* )end }
#define MEM_END_ADDRESS { ( void* )( SRAM_ORIGIN + SRAM_SIZE - STACK_SIZE_TOTAL - 1 ) }
#endif // #ifndef __PLATFORM_CONF_H__

View File

@ -0,0 +1,7 @@
// Platform customization header
#ifndef __PLATFORM_GENERIC_H__
#define __PLATFORM_GENERIC_H__
#endif // #ifndef __PLATFORM_GENERIC_H__

View File

@ -328,6 +328,7 @@ builder.new = function( build_dir )
self.clean_mode = false
self.opts = utils.options_handler()
self.args = {}
self.user_args = {}
self.build_mode = self.KEEP_DIR
self.targets = {}
self.targetargs = {}
@ -389,6 +390,7 @@ builder.init = function( self, args )
os.exit( 1 )
end
self.args[ k:upper() ] = v
self.user_args[ k:upper() ] = true
else -- this must be the target name / target arguments
if self.targetname == nil then
self.targetname = a
@ -408,6 +410,11 @@ builder.get_option = function( self, optname )
return self.args[ optname:upper() ]
end
-- Returns true if the given option was specified by the user on the command line, false otherwise
builder.is_user_option = function( self, optname )
return self.user_args[ optname:upper() ]
end
-- Show builder help
builder._show_help = function( self )
print( "[builder] Valid options:" )
@ -719,11 +726,11 @@ end
builder.build = function( self, target )
local t = self.targetname or self.deftarget
if not t then
print( "[builder] Error: build target not specified" )
print( utils.col_red( "[builder] Error: build target not specified" ) )
os.exit( 1 )
end
if not self.targets[ t ] then
print( sf( "[builder] Error: target '%s' not found", t ) )
print( utils.col_red( sf( "[builder] Error: target '%s' not found", t ) ) )
print( "Available targets: " )
for k, v in pairs( self.targets ) do
if not is_phony( k ) then
@ -738,19 +745,19 @@ builder.build = function( self, target )
self:_create_outdir()
-- At this point check if we have a change in the state that would require a rebuild
if self:_compare_config( 'comp' ) then
print "[builder] Forcing rebuild due to configuration change"
print( utils.col_yellow( "[builder] Forcing rebuild due to configuration change." ) )
self.global_force_rebuild = true
else
self.global_force_rebuild = false
end
-- Do the actual build
local res = self.targets[ t ].target:build()
if not res then print( sf( '[builder] %s: up to date', t ) ) end
if not res then print( utils.col_yellow( sf( '[builder] %s: up to date', t ) ) ) end
if self.clean_mode then
os.remove( self.build_dir .. utils.dir_sep .. ".builddata.comp" )
os.remove( self.build_dir .. utils.dir_sep .. ".builddata.link" )
end
print "[builder] Done building target."
print( utils.col_yellow( "[builder] Done building target." ) )
return res
end

View File

@ -4,6 +4,7 @@ module( ..., package.seeall )
local lfs = require "lfs"
local sf = string.format
local md5 = require "md5"
-- Taken from Lake
dir_sep = package.config:sub( 1, 1 )
@ -37,7 +38,13 @@ end
-- Replace the extension of a give file name
replace_extension = function( s, newext )
local p, e = split_path( s )
if e then s = p .. "." .. newext end
if e then
if newext and #newext > 0 then
s = p .. "." .. newext
else
s = p
end
end
return s
end
@ -111,6 +118,13 @@ table_keys = function( t )
return keys
end
-- Return an array with the values of a table
table_values = function( t )
local vals = {}
foreach( t, function( k, v ) table.insert( vals, v ) end )
return vals
end
-- Returns true if 'path' is a regular file, false otherwise
is_file = function( path )
return lfs.attributes( path, "mode" ) == "file"
@ -168,22 +182,71 @@ foreach = function ( t, cmd )
for k, v in pairs( t ) do cmd( k, v ) end
end
-- Template header
gen_header = function( name, defines )
local hname = "inc" .. dir_sep .. name:lower() .. ".h"
local h = assert(io.open(hname, "w"))
h:write("// eLua " .. name:lower() .. " definition\n\n")
h:write("#ifndef __" .. name:upper() .. "_H__\n")
h:write("#define __" .. name:upper() .. "_H__\n\n")
-- Generate header with the given #defines, return result as string
gen_header_string = function( name, defines )
local s = "// eLua " .. name:lower() .. " definition\n\n"
s = s .. "#ifndef __" .. name:upper() .. "_H__\n"
s = s .. "#define __" .. name:upper() .. "_H__\n\n"
for key,value in pairs(defines) do
h:write(string.format("#define %-25s%-19s\n",key:upper(),value))
s = s .. string.format("#define %-25s%-19s\n",key:upper(),value)
end
h:write("\n#endif\n")
s = s .. "\n#endif\n"
return s
end
-- Generate header with the given #defines, save result to file
gen_header_file = function( name, defines )
local hname = concat_path{ "inc", name:lower() .. ".h" }
local h = assert( io.open( hname, "w" ) )
h:write( gen_header_string( name, defines ) )
h:close()
end
-- Remove the given elements from an array
remove_array_elements = function( arr, del )
del = istable( del ) and del or { del }
foreach( del, function( k, v )
local pos = array_element_index( arr, v )
if pos then table.remove( arr, pos ) end
end )
end
-- Remove a directory recusively
-- USE WITH CARE!! Doesn't do much checks :)
rm_dir_rec = function ( dirname )
for f in lfs.dir( dirname ) do
local ename = string.format( "%s/%s", dirname, f )
local attrs = lfs.attributes( ename )
if attrs.mode == 'directory' and f ~= '.' and f ~= '..' then
rm_dir_rec( ename )
elseif attrs.mode == 'file' or attrs.mode == 'named pipe' or attrs.mode == 'link' then
os.remove( ename )
end
end
lfs.rmdir( dirname )
end
-- Computes the hash of the given string
get_hash_of_string = function( s )
return md5.sumhexa( s )
end
-- Computes the hash of the given file
get_hash_of_file = function( f )
local f = io.open( f, "rb" )
if not f then return end
local d = f:read( "*a" )
f:close()
return get_hash_of_string( d )
end
-- Concatenates the second table into the first one
concat_tables = function( dst, src )
foreach( src, function( k, v ) dst[ k ] = v end )
end
-------------------------------------------------------------------------------
-- Color-related funtions
-- Currently disabled when running in Windows