1
0
mirror of https://github.com/elua/elua.git synced 2025-01-08 20:56:17 +08:00
elua/config/configurations.lua
Bogdan Marinescu 37e20330e7 LPC17xx modified for the new build system + other changes
- more flexible specification of the RAM structure in the build configuration file
- fix for allocator choice in build_elua.lua
2012-07-14 20:00:54 +03:00

177 lines
6.4 KiB
Lua

-- 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 ram_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
local ninternal = vals._NUM_INTERNAL_RAMS.value
if ( not startvals or not sizevals ) and ninternal == 0 then
return false, "RAM configuration must be defined in element 'ram' of section 'config'"
end
if not startvals and not sizevals then return true end
if not startvals then
return false, "attribute 'ext_start' must also be specified for element 'ram' of section 'config'"
elseif not sizevals then
return false, "attribute 'ext_size' must also be specified for element 'ram' of section 'config'"
end
if #startvals == 0 then
return false, "attribute 'ext_start' of element 'ram' in section 'config' must have at least one element"
elseif #sizevals == 0 then
return false, "attribute 'ext_size' of element 'ram' in section 'config' must have at least one element"
end
if #startvals ~= #sizevals then
return false, "attributes 'ext_start' and 'ext_size' of element 'ram' 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_RAMx_FIRST_FREE and INTERNAL_RAMx_LAST_FREE
-- exist (they should come from <cpu>.h)
local function ram_generator( desc, vals, generated )
-- Prepare internal memory configuration first
local ninternal = vals._NUM_INTERNAL_RAMS.value
local istart, iend = {}, {}
for i = 1, ninternal do
table.insert( istart, sf( "( u32 )( INTERNAL_RAM%d_FIRST_FREE )", i ) )
table.insert( iend, sf( "( u32 )( INTERNAL_RAM%d_LAST_FREE )", i ) )
end
if not vals.MEM_START_ADDRESS then
-- Generate configuration only for the internal memory
local gstr = gen.print_define( "MEM_START_ADDRESS", "{ " .. table.concat( istart, "," ) .. " }" )
gstr = gstr .. gen.print_define( "MEM_END_ADDRESS", "{ " .. table.concat( iend, "," ) .. " }" )
generated.MEM_START_ADDRESS = true
generated.MEM_END_ADDRESS = true
use_multiple_allocator = ninternal > 1
return gstr
end
local function fmtval( s ) return tonumber( s ) and tostring( s ) .. "UL" or ( "( u32 )( " .. s .. " )" ) end
local startvals, sizevals = vals.MEM_START_ADDRESS.value, vals.MEM_END_ADDRESS.value
for i = 1, ninternal do
table.insert( startvals, i, sf( "( u32 )( INTERNAL_RAM%d_FIRST_FREE )", i ) )
table.insert( sizevals, i, sf( "( u32 )( INTERNAL_RAM%d_LAST_FREE )", i ) )
end
for i = ninternal + 1, #sizevals do
sizevals[ i ] = sf( "( %s + %s - 1 )", fmtval( startvals[ i ] ), fmtval( sizevals[ i ] ) )
startvals[ i ] = sf( "( %s )", fmtval( startvals[ i ] ) )
end
use_multiple_allocator = #startvals > 1
local gstr = gen.simple_gen( "MEM_START_ADDRESS", vals, generated )
gstr = gstr .. gen.simple_gen( "MEM_END_ADDRESS", vals, generated )
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 ) )
},
}
-- RAM configuration generator
configs.ram = {
gen = ram_generator,
confcheck = ram_checker,
attrs = {
internal_rams = at.int_attr( '_NUM_INTERNAL_RAMS', 0, nil, 1 ),
ext_start = at.array_of( at.combine_attr( 'MEM_START_ADDRESS', { at.int_attr( '' ), at.string_attr( '' ) } ) ),
ext_size = at.array_of( at.combine_attr( 'MEM_END_ADDRESS', { at.int_attr( '', 1 ), at.string_attr( '' ) } ) ),
},
required = { internal_rams = 1, ext_start = {}, ext_size = {} }
}
-- 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