1
0
mirror of https://github.com/elua/elua.git synced 2025-01-08 20:56:17 +08:00
elua/config/config.lua
Bogdan Marinescu d09bea3273 Platform conversion + other changes
- AVR32 platform converted to use the new build system
- new section in configuration: 'build'. Used to set predefined
  build parameters (such as allocator, target, boot mode...)
2012-07-20 23:30:25 +03:00

293 lines
11 KiB
Lua

-- 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 bargs = require "buildargs"
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', 'build' }
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
header = header .. string.rep( "/", 80 ) .. "\n"
header = header .. "// Configuration for section 'macros'\n\n"
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
gen, err = bargs.validate( desc, platform )
if not gen then return false, err 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, build = desc.build }
end