From 350f57e6a5a34d1cd27446e4459fd16e23124478 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Wed, 31 Jan 2024 10:10:08 -0500 Subject: [PATCH] Fix #2507, add EDS cmake hooks Adds CFE_EDS_ENABLED_BUILD option at the top level, along with other logic that is tied in only when this is set TRUE. By default it is set to FALSE, so it does not change any existing workflows yet. Also added are the keys for two configuration values for reflecting EDS DB objects (pointers) and some minor cleanup. --- CMakeLists.txt | 16 ++++- cmake/arch_build.cmake | 11 ++++ cmake/global_functions.cmake | 16 ++++- cmake/mission_build.cmake | 9 +-- cmake/mission_defaults.cmake | 35 +++++++++++ cmake/target/CMakeLists.txt | 32 +++++++++- cmake/target/inc/target_config.h | 34 ++++++++++ cmake/target/src/target_config.c | 80 +++++++++++++++++++++++- modules/config/fsw/src/cfe_config_init.c | 4 ++ modules/config/mission_build.cmake | 2 + modules/core_api/CMakeLists.txt | 8 ++- modules/evs/fsw/src/cfe_evs_task.c | 6 -- modules/evs/ut-coverage/evs_UT.c | 3 +- 13 files changed, 236 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f313fb20c..7a147eeb6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,6 +66,21 @@ project(CFE C) # Allow unit tests to be added by any recipe enable_testing() +# This switch determines whether to use EDS framework +# By default it is set OFF/false as this is a new/experimental feature. +option(CFE_EDS_ENABLED_BUILD "Use EDS framework" OFF) + +# Always create directories to hold generated files/wrappers +# EDS makes signficant use of generated files. In non-EDS builds +# some headers and wrapper files are also generated. Directories +# may simply remain empty if not used/needed in the current config. +file(MAKE_DIRECTORY + "${CMAKE_BINARY_DIR}/eds" + "${CMAKE_BINARY_DIR}/obj" + "${CMAKE_BINARY_DIR}/inc" + "${CMAKE_BINARY_DIR}/src" +) + # Include the global routines include("cmake/global_functions.cmake") @@ -123,4 +138,3 @@ prepare() foreach(SYSVAR ${TGTSYS_LIST}) process_arch(${SYSVAR}) endforeach(SYSVAR ${TGTSYS_LIST}) - diff --git a/cmake/arch_build.cmake b/cmake/arch_build.cmake index e0bae5dde..e152d7182 100644 --- a/cmake/arch_build.cmake +++ b/cmake/arch_build.cmake @@ -101,6 +101,17 @@ function(add_cfe_app APP_NAME APP_SRC_FILES) add_library(${APP_NAME} ${APPTYPE} ${APP_SRC_FILES} ${ARGN}) target_link_libraries(${APP_NAME} core_api) + # If using "local" EDS linkage, then link the app with the EDS library here. + # Note that the linker will only pull in the compilation unit that actually + # resolves an undefined symbol, which in this case would be the app-specific + # DATATYPE_DB object if one is referenced at all. + # + # By linking with the respective application like this, the net result is that + # only the _referenced_ EDS DBs (i.e. those for loaded apps) are held in memory. + if (CFE_EDS_ENABLED_BUILD AND CFE_EDS_LINK_MODE STREQUAL LOCAL) + target_link_libraries($(APP_NAME) cfe_edsdb_static) + endif() + # An "install" step is only needed for dynamic/runtime loaded apps if (APP_DYNAMIC_TARGET_LIST) cfs_app_do_install(${APP_NAME} ${APP_DYNAMIC_TARGET_LIST}) diff --git a/cmake/global_functions.cmake b/cmake/global_functions.cmake index 494b6c62c..d99a92c7e 100644 --- a/cmake/global_functions.cmake +++ b/cmake/global_functions.cmake @@ -10,6 +10,20 @@ include(CMakeParseArguments) +# This is done here at the global level so this definition is used for +# ALL code on ALL targets, including host-side tools. Ideally, this should +# only be necessary on the core_api interface, but it does not fully propagate +# to all unit test targets. If/when that issue is resolved, this can be removed. +if (CFE_EDS_ENABLED_BUILD) + + # Propagate the setting to a C preprocessor define of the same name + # The CFE_EDS_ENABLED_BUILD switch indicates that any + # compile-time preprocessor blocks should be enabled in this build + add_definitions(-DCFE_EDS_ENABLED_BUILD) + +endif(CFE_EDS_ENABLED_BUILD) + + ################################################################## # # FUNCTION: cfe_locate_implementation_file @@ -58,7 +72,7 @@ function(cfe_locate_implementation_file OUTPUT_VAR FILE_NAME) string(REPLACE ${MISSION_SOURCE_DIR} "" RELATIVEDIR ${BASEDIR}) # A target-specific prefixed filename gets priority over a direct filename match - # But do not include this variant if the prefix is already part of the relative search path + # But do not include this variant if the prefix is already part of the relative search path foreach (PREFIX ${LOCATEIMPL_ARG_PREFIX}) if (NOT "${RELATIVEDIR}" MATCHES "/${PREFIX}/") list(APPEND IMPL_SEARCH_PATH "${BASEDIR}${PREFIX}_${FILE_NAME}") diff --git a/cmake/mission_build.cmake b/cmake/mission_build.cmake index 76adfe97c..26285e56d 100644 --- a/cmake/mission_build.cmake +++ b/cmake/mission_build.cmake @@ -293,12 +293,6 @@ function(prepare) add_definitions(-DSIMULATION=${SIMULATION}) endif (SIMULATION) - # Create directories to hold generated files/wrappers - file(MAKE_DIRECTORY "${MISSION_BINARY_DIR}/eds") - file(MAKE_DIRECTORY "${MISSION_BINARY_DIR}/obj") - file(MAKE_DIRECTORY "${MISSION_BINARY_DIR}/inc") - file(MAKE_DIRECTORY "${MISSION_BINARY_DIR}/src") - # Certain runtime variables need to be "exported" to the subordinate build, such as # the specific arch settings and the location of all the apps. This list is collected # during this function execution and exported at the end. @@ -548,7 +542,7 @@ function(process_arch TARGETSYSTEM) # convert to a string which is safe for a directory name string(REGEX REPLACE "[^A-Za-z0-9]" "_" ARCH_CONFIG_NAME "${BUILD_CONFIG}") set(ARCH_BINARY_DIR "${CMAKE_BINARY_DIR}/${ARCH_TOOLCHAIN_NAME}/${ARCH_CONFIG_NAME}") - file(MAKE_DIRECTORY "${ARCH_BINARY_DIR}" "${ARCH_BINARY_DIR}/inc") + file(MAKE_DIRECTORY "${ARCH_BINARY_DIR}") message(STATUS "Configuring for system arch: ${ARCH_TOOLCHAIN_NAME}/${ARCH_CONFIG_NAME}") @@ -578,6 +572,7 @@ function(process_arch TARGETSYSTEM) -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=${CMAKE_EXPORT_COMPILE_COMMANDS} + -DCFE_EDS_ENABLED_BUILD:BOOL=${CFE_EDS_ENABLED_BUILD} ${SELECTED_TOOLCHAIN_FILE} ${CFE_SOURCE_DIR} WORKING_DIRECTORY diff --git a/cmake/mission_defaults.cmake b/cmake/mission_defaults.cmake index c7871c5ce..45193fea1 100644 --- a/cmake/mission_defaults.cmake +++ b/cmake/mission_defaults.cmake @@ -67,6 +67,41 @@ set(MISSION_MODULE_SEARCH_PATH set(osal_SEARCH_PATH ".") set(psp_SEARCH_PATH ".") +# Account for differences when EDS is enabled +if(CFE_EDS_ENABLED_BUILD) + + # The EDS database is an object (or set of objects) generated by the tools from the EDS files. + # This can be linked into CFE either as a whole (GLOBAL) or as part of each app (LOCAL). + # + # LOCAL mode may use less memory by only only including DB objects for the apps that are + # originating or terminating CFS message traffic, but GLOBAL mode is simpler as it ensures + # that the entire DB is accessible by any app, even for data definitions that are not its own. + # + # NOTE: If running CI/TO, SBN, or other "generic" apps that relay SB traffic (or otherwise + # handle data that may not have originated on the same CFE instance) then it is recommended + # to stay with GLOBAL mode. + if (NOT DEFINED CFE_EDS_LINK_MODE) + set(CFE_EDS_LINK_MODE GLOBAL) + endif() + + # The standard msg module is not used in EDS build, edslib provides an alternate + list(REMOVE_ITEM MISSION_CORE_MODULES msg) + + list(APPEND MISSION_CORE_MODULES + "edslib" + "missionlib" + "edsmsg" + ) + + list(APPEND MISSION_MODULE_SEARCH_PATH + "tools/eds/cfecfs" # CFE/CFS modules and extensions from EdsLib + ) + + # edslib exists directly under tools/eds (EDS runtime libraries) + set(edslib_SEARCH_PATH "tools/eds") + +endif(CFE_EDS_ENABLED_BUILD) + # Include "cfe_assert" library in all builds, because it is included # in the default startup script. It should not have any effect if not # used. diff --git a/cmake/target/CMakeLists.txt b/cmake/target/CMakeLists.txt index 5e5eb73c4..adb1e8fde 100644 --- a/cmake/target/CMakeLists.txt +++ b/cmake/target/CMakeLists.txt @@ -193,6 +193,37 @@ set(CFE_LINK_NORMAL_LIBS ${${TGTNAME}_STATIC_APPLIST} ) +# If EDS is enabled, then the generated dictionary objects are linked with CFE. +# This can be done statically or dynamically, depending on user preferences. +if (CFE_EDS_ENABLED_BUILD) + + # Determine EDS object linking mode for final executable. + # This should be configured via the toolchain file, + # with the default being FALSE (static link) + if (CFE_EDS_LINK_MODE STREQUAL GLOBAL) + + # In this mode the full EDS object is statically linked + # In addition, also pull in the runtime lib, which + # supports script language bindings and UI display + list(APPEND CFE_LINK_WHOLE_LIBS + cfe_edsdb_static + edslib_runtime_static + ) + + endif() + + list(APPEND CFE_LINK_WHOLE_LIBS + cfe_missionlib_runtime_static + cfe_missionlib_interfacedb_static + ) + + # Set a preprocessor define so the source will reference the right thing + target_compile_definitions(core-${TGTNAME} PRIVATE + CFE_EDS_LINK_MODE_${CFE_EDS_LINK_MODE} + ) + +endif(CFE_EDS_ENABLED_BUILD) + # Handle the list of "embedded files" that should be linked into CFE. # These are arbitrary files in the mission config that are converted # into C data structures and linked with the executable. This is @@ -276,4 +307,3 @@ target_link_libraries(core-${TGTNAME} # This is implemented in a separate function so # it may be overridden in an OS-specific manner if necessary. cfe_exec_do_install(${TGTNAME}) - diff --git a/cmake/target/inc/target_config.h b/cmake/target/inc/target_config.h index 3a18d33f4..a01baebb4 100644 --- a/cmake/target/inc/target_config.h +++ b/cmake/target/inc/target_config.h @@ -89,6 +89,12 @@ typedef const struct const void *Value; } CFE_ConfigKeyValue_t; +/** + * The "EdsLib_DatabaseObject" is an abstract structure here. + */ +typedef struct EdsLib_DatabaseObject CFE_EdsDbObject_t; +typedef struct CFE_MissionLib_SoftwareBus_Interface CFE_SbIntfDbObject_t; + /** * Core Flight Executive configuration information. */ @@ -196,6 +202,34 @@ typedef const struct CFE_ConfigName_t * CoreModuleList; /**< List of CFE core support module names that are statically linked */ CFE_ConfigName_t *StaticAppList; /**< List of additional CFS Applications that are statically linked into this binary */ + + /** + * Normal read-only EDS Database object + * + * This EDS DB object pointer is always initialized to be non-null. + * It is qualified as "const" and used for all EDS query requests. + */ + const CFE_EdsDbObject_t *EdsDb; + + /** + * Dynamic EDS Database object + * + * This provides a writable (non-const) pointer to the same EDS object as above, + * but only when when dynamic EDS link mode is selected. It will be set NULL + * when static EDS link mode is selected. + * + * This can checked by runtime code to determine the EDS link mode. If it is + * NULL this means the EDS DB is fixed/static and no runtime registration is needed. + * If this pointer is non-null then the EDS DB is dynamic and runtime registration + * is needed. + */ + CFE_EdsDbObject_t *DynamicEdsDb; + + /** + * Software bus interface EDS object (MsgId mappings) + */ + const CFE_SbIntfDbObject_t *SbIntfDb; + } Target_ConfigData; /** diff --git a/cmake/target/src/target_config.c b/cmake/target/src/target_config.c index 0b389f079..b5c1adf04 100644 --- a/cmake/target/src/target_config.c +++ b/cmake/target/src/target_config.c @@ -126,6 +126,78 @@ extern CFE_ConfigKeyValue_t CFE_MODULE_VERSION_TABLE[]; */ extern CFE_StaticModuleLoadEntry_t CFE_PSP_MODULE_LIST[]; +#ifdef CFE_EDS_ENABLED_BUILD + +#include "cfe_mission_eds_parameters.h" +#include "cfe_mission_eds_interface_parameters.h" + +#define CFE_SB_INTF_DB_PTR &CFE_SOFTWAREBUS_INTERFACE + +#endif /* CFE_EDS_ENABLED_BUILD */ + +/* + * Determine the proper values for populating the EDS-related + * fields of the configuration structure. This depends on the + * selected linkage mode (static or dynamic). + */ + +/* + * Static (const) EDS object link mode: + * Only the const pointer gets assigned to the EDS object, and the + * non-const pointer gets set NULL. There are no "write" operations + * in this mode -- registration and de-registration is not necessary. + */ +#ifdef CFE_EDS_LINK_MODE_GLOBAL + +/* This mode is simple, just point directly at the object defined in the external DB */ +#define CFE_CONST_EDS_DB_PTR &EDS_DATABASE + +#endif /* CFE_EDS_LINK_MODE_GLOBAL */ + +/* + * Dynamic (non-const) runtime EDS database object + * This is filled in as additional EDS datasheet objects are registered + */ +#ifdef CFE_EDS_LINK_MODE_LOCAL + +static EdsLib_DataTypeDB_t CFE_DYNAMIC_EDS_TABLE[EDS_MAX_DATASHEETS] = {NULL}; + +static EdsLib_DatabaseObject_t CFE_DYNAMIC_EDSDB_OBJECT = {.AppTableSize = EDS_MAX_DATASHEETS, + .DataTypeDB_Table = CFE_DYNAMIC_EDS_TABLE}; + +/* The object registered in config points at the local (empty) object */ +#define CFE_NONCONST_EDS_DB_PTR &CFE_DYNAMIC_EDSDB_OBJECT + +#endif /* CFE_EDS_LINK_MODE_LOCAL */ + +/* + * For all of these DB objects, use NULL if not defined. + * This covers the case where EDS is not being used. + */ +#ifndef CFE_NONCONST_EDS_DB_PTR +#define CFE_NONCONST_EDS_DB_PTR NULL +#endif + +/* + * Note that the non-const object can be used as a const object, + * but not the other way around. This can also be NULL. + */ +#ifndef CFE_CONST_EDS_DB_PTR +#define CFE_CONST_EDS_DB_PTR CFE_NONCONST_EDS_DB_PTR +#endif + +/* + * The SB intf DB serves as the lookup table for identification + * of the software bus messages. This can also be NULL if + * EDS is not being used. + */ +#ifndef CFE_SB_INTF_DB_PTR +#define CFE_SB_INTF_DB_PTR NULL +#endif + +/* Disable clang-format for the rest of this file, to preserve columns in the struct defs */ +/* clang-format off */ + /** * A structure that encapsulates all the CFE static configuration */ @@ -152,7 +224,9 @@ Target_CfeConfigData GLOBAL_CFE_CONFIGDATA = { .UserReservedSize = CFE_PLATFORM_ES_USER_RESERVED_SIZE, .RamDiskSectorSize = CFE_PLATFORM_ES_RAM_DISK_SECTOR_SIZE, - .RamDiskTotalSectors = CFE_PLATFORM_ES_RAM_DISK_NUM_SECTORS}; + .RamDiskTotalSectors = CFE_PLATFORM_ES_RAM_DISK_NUM_SECTORS +}; + /** * Instantiation of global system-wide configuration struct @@ -176,4 +250,8 @@ Target_ConfigData GLOBAL_CONFIGDATA = { .ModuleVersionList = CFE_MODULE_VERSION_TABLE, .CoreModuleList = CFE_CORE_MODULE_LIST, .StaticAppList = CFE_STATIC_APP_LIST, + .EdsDb = CFE_CONST_EDS_DB_PTR, + .DynamicEdsDb = CFE_NONCONST_EDS_DB_PTR, + .SbIntfDb = CFE_SB_INTF_DB_PTR }; + diff --git a/modules/config/fsw/src/cfe_config_init.c b/modules/config/fsw/src/cfe_config_init.c index 6791b45c4..e8cee9cc4 100644 --- a/modules/config/fsw/src/cfe_config_init.c +++ b/modules/config/fsw/src/cfe_config_init.c @@ -177,6 +177,10 @@ void CFE_Config_SetupBasicBuildInfo(void) KeyVal = CFE_Config_FindTargetKeyValue(GLOBAL_CONFIGDATA.ModuleVersionList, "MISSION"); CFE_Config_SetString(CFE_CONFIGID_MISSION_SRCVER, KeyVal); + /* Global mission EDS runtime DB */ + CFE_Config_SetObjPointer(CFE_CONFIGID_MISSION_EDS_DB, GLOBAL_CONFIGDATA.EdsDb); + CFE_Config_SetObjPointer(CFE_CONFIGID_MISSION_SBINTF_DB, GLOBAL_CONFIGDATA.SbIntfDb); + /* propagate the version numbers from version.h */ CFE_Config_SetValue(CFE_CONFIGID_CORE_VERSION_MAJOR, CFE_MAJOR_VERSION); CFE_Config_SetValue(CFE_CONFIGID_CORE_VERSION_MINOR, CFE_MINOR_VERSION); diff --git a/modules/config/mission_build.cmake b/modules/config/mission_build.cmake index a5a6d4551..c79774c46 100644 --- a/modules/config/mission_build.cmake +++ b/modules/config/mission_build.cmake @@ -18,6 +18,8 @@ set(GENERATED_IDNAME_MAP_LIST) list(APPEND CFE_CONFIG_IDS MISSION_NAME MISSION_SRCVER + MISSION_EDS_DB + MISSION_SBINTF_DB CORE_VERSION_MAJOR CORE_VERSION_MINOR diff --git a/modules/core_api/CMakeLists.txt b/modules/core_api/CMakeLists.txt index ebdacd669..bcb65ebc3 100644 --- a/modules/core_api/CMakeLists.txt +++ b/modules/core_api/CMakeLists.txt @@ -12,6 +12,13 @@ add_library(core_api INTERFACE) # The fsw/inc here defines global/shared structures and interfaces target_include_directories(core_api INTERFACE fsw/inc) +# Propagate the setting to a C preprocessor define of the same name +# The CFE_EDS_ENABLED_BUILD switch indicates that any +# compile-time preprocessor blocks should be enabled in this build +if (CFE_EDS_ENABLED_BUILD) + target_compile_definitions(core_api INTERFACE CFE_EDS_ENABLED_BUILD) +endif() + # Propagate any INTERFACE-level include dirs and compile definitions from # the modules into this abstract interface target foreach(MOD ${MISSION_CORE_MODULES}) @@ -46,4 +53,3 @@ cfs_app_check_intf(core_api cfe_tbl_filedef.h ) - diff --git a/modules/evs/fsw/src/cfe_evs_task.c b/modules/evs/fsw/src/cfe_evs_task.c index 2d5024784..59e8c1ce4 100644 --- a/modules/evs/fsw/src/cfe_evs_task.c +++ b/modules/evs/fsw/src/cfe_evs_task.c @@ -43,12 +43,6 @@ CFE_EVS_Global_t CFE_EVS_Global; /* Defines */ #define CFE_EVS_PANIC_DELAY 500 /**< \brief Task delay before PSP panic */ -/* -** Local function prototypes. -*/ -void CFE_EVS_ProcessGroundCommand(CFE_SB_Buffer_t *SBBufPtr, CFE_SB_MsgId_t MsgId); -bool CFE_EVS_VerifyCmdLength(CFE_MSG_Message_t *MsgPtr, size_t ExpectedLength); - /* Function Definitions */ /*---------------------------------------------------------------- diff --git a/modules/evs/ut-coverage/evs_UT.c b/modules/evs/ut-coverage/evs_UT.c index 7169e351d..5f3da04bd 100644 --- a/modules/evs/ut-coverage/evs_UT.c +++ b/modules/evs/ut-coverage/evs_UT.c @@ -277,7 +277,6 @@ void Test_Init(void) { CFE_EVS_EnablePortsCmd_t bitmaskcmd; CFE_EVS_EnableAppEventTypeCmd_t appbitcmd; - CFE_SB_MsgId_t msgid = CFE_SB_INVALID_MSG_ID; UtPrintf("Begin Test Init"); @@ -307,7 +306,7 @@ void Test_Init(void) UT_InitData_EVS(); /* Set unexpected message ID */ - UT_SetDataBuffer(UT_KEY(CFE_MSG_GetMsgId), &msgid, sizeof(msgid), false); + UT_SetupBasicMsgDispatch(&UT_TPID_CFE_EVS_INVALID_MID, 0, true); UT_EVS_DoGenericCheckEvents(CFE_EVS_TaskMain, &UT_EVS_EventBuf); CFE_UtAssert_SYSLOG(EVS_SYSLOG_MSGS[8]);