diff --git a/.gitmodules b/.gitmodules index 1f3dc6ec..1ca8bec5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -22,3 +22,6 @@ [submodule "thirdparty/json"] path = thirdparty/json url = https://github.com/nlohmann/json.git +[submodule "thirdparty/Catch2"] + path = thirdparty/Catch2 + url = https://github.com/catchorg/Catch2.git diff --git a/CMakeLists.txt b/CMakeLists.txt index e9b1b68c..656ee3ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,8 +18,9 @@ if(TGT_BSP MATCHES "arm/q7s") option(BUILD_Q7S_SIMPLE_MODE OFF "Simple mode with a minimal main function") endif() -option(ADD_ETL_LIB "Add ETL library" ON) -option(ADD_JSON_LIB "Add JSON library" ON) +option(EIVE_BUILD_UNITTESTS "Build Catch2 unittests" OFF) +option(EIVE_ADD_ETL_LIB "Add ETL library" ON) +option(EIVE_ADD_JSON_LIB "Add JSON library" ON) option(EIVE_SYSROOT_MAGIC "Perform sysroot magic which might not be necessary" OFF) if(NOT FSFW_OSAL) @@ -34,9 +35,14 @@ endif() include(${CMAKE_SCRIPT_PATH}/PreProjectConfig.cmake) pre_project_config() -set(PROJECT_NAME_TO_SET eive-obsw-$ENV{USERNAME}) if(EIVE_BUILD_WATCHDOG) set(PROJECT_NAME_TO_SET eive-watchdog) +elseif(EIVE_BUILD_UNITTESTS) + set(PROJECT_NAME_TO_SET eive-unittest) +elseif(TGT_BSP MATCHES "arm/q7s") + set(PROJECT_NAME_TO_SET eive-obsw-$ENV{USERNAME}) +else() + set(PROJECT_NAME_TO_SET eive-obsw) endif() # Project Name @@ -59,26 +65,41 @@ set(LIB_LWGPS_NAME lwgps) set(LIB_ARCSEC wire) set(THIRD_PARTY_FOLDER thirdparty) set(LIB_CXX_FS -lstdc++fs) +set(LIB_CATCH2 Catch2) set(LIB_JSON_NAME nlohmann_json::nlohmann_json) # Set path names set(FSFW_PATH fsfw) set(MISSION_PATH mission) set(TEST_PATH test/testtasks) +set(UNITTEST_PATH unittest) set(LINUX_PATH linux) set(COMMON_PATH common) set(WATCHDOG_PATH watchdog) set(COMMON_CONFIG_PATH ${COMMON_PATH}/config) +set(UNITTEST_CFG_PATH ${UNITTEST_PATH}/testcfg) -set(FSFW_HAL_LIB_PATH fsfw_hal) -set(CSP_LIB_PATH ${THIRD_PARTY_FOLDER}/libcsp) -set(ETL_LIB_PATH ${THIRD_PARTY_FOLDER}/etl) -set(LWGPS_LIB_PATH ${THIRD_PARTY_FOLDER}/lwgps) -set(ARCSEC_LIB_PATH ${THIRD_PARTY_FOLDER}/arcsec_star_tracker) +set(LIB_CSP_PATH ${THIRD_PARTY_FOLDER}/libcsp) +set(LIB_ETL_PATH ${THIRD_PARTY_FOLDER}/etl) +set(LIB_CATCH2_PATH ${THIRD_PARTY_FOLDER}/Catch2) +set(LIB_LWGPS_PATH ${THIRD_PARTY_FOLDER}/lwgps) +set(LIB_ARCSEC_PATH ${THIRD_PARTY_FOLDER}/arcsec_star_tracker) set(LIB_JSON_PATH ${THIRD_PARTY_FOLDER}/json) set(FSFW_WARNING_SHADOW_LOCAL_GCC OFF) -set(ADD_LINUX_FILES False) +set(EIVE_ADD_LINUX_FILES False) + +if(EIVE_BUILD_UNITTESTS) + option(FSFW_ADD_UNITTESTS "Build the FSFW unittests as well" ON) + # Use FSFW custom main for unittests + set(FSFW_CUSTOM_UNITTEST_RUNNER ON) +endif() + +if(FSFW_CUSTOM_UNITTEST_RUNNER OR FSFW_ADD_UNITTESTS) + set(CATCH2_TARGET Catch2) +else() + set(CATCH2_TARGET Catch2WithMain) +endif() # Analyse different OS and architecture/target options, determine BSP_PATH, # display information about compiler etc. @@ -91,7 +112,7 @@ if(TGT_BSP) ) set(FSFW_CONFIG_PATH "linux/fsfwconfig") if(NOT BUILD_Q7S_SIMPLE_MODE) - set(ADD_LINUX_FILES TRUE) + set(EIVE_ADD_LINUX_FILES TRUE) set(ADD_CSP_LIB TRUE) set(FSFW_HAL_ADD_LINUX ON) endif() @@ -117,6 +138,11 @@ else() set(FSFW_CONFIG_PATH "${BSP_PATH}/fsfwconfig") endif() +if(EIVE_BUILD_UNITTESTS) + configure_file(${UNITTEST_CFG_PATH}/TestsConfig.h.in TestsConfig.h) + set(FSFW_CONFIG_PATH ${UNITTEST_CFG_PATH}) +endif() + # Configuration files if(NOT EIVE_BUILD_WATCHDOG) configure_file(${COMMON_CONFIG_PATH}/commonConfig.h.in commonConfig.h) @@ -128,6 +154,9 @@ if(NOT EIVE_BUILD_WATCHDOG) configure_file(${BSP_PATH}/boardconfig/rpiConfig.h.in rpiConfig.h) endif() endif() + + + configure_file(${WATCHDOG_PATH}/watchdogConf.h.in watchdogConf.h) # Set common config path for FSFW @@ -143,31 +172,38 @@ set(FSFW_ADDITIONAL_INC_PATHS # Add executable add_executable(${TARGET_NAME}) -if(ADD_ETL_LIB) - add_subdirectory(${ETL_LIB_PATH}) +if(EIVE_ADD_ETL_LIB) + add_subdirectory(${LIB_ETL_PATH}) endif() -if(ADD_JSON_LIB) +if(EIVE_ADD_JSON_LIB) add_subdirectory(${LIB_JSON_PATH}) endif() if(NOT EIVE_BUILD_WATCHDOG) - if(ADD_LINUX_FILES) - add_subdirectory(${LINUX_PATH}) + if(NOT EIVE_BUILD_UNITTESTS) + if(EIVE_ADD_LINUX_FILES) + add_subdirectory(${LINUX_PATH}) + endif() + add_subdirectory(${BSP_PATH}) + if(ADD_CSP_LIB) + add_subdirectory(${LIB_CSP_PATH}) + endif() endif() - add_subdirectory(${BSP_PATH}) add_subdirectory(${COMMON_PATH}) - if(ADD_CSP_LIB) - add_subdirectory(${CSP_LIB_PATH}) - endif() endif() if((NOT BUILD_Q7S_SIMPLE_MODE) AND (NOT EIVE_BUILD_WATCHDOG)) - add_subdirectory(${LWGPS_LIB_PATH}) + add_subdirectory(${LIB_LWGPS_PATH}) add_subdirectory(${FSFW_PATH}) add_subdirectory(${MISSION_PATH}) add_subdirectory(${TEST_PATH}) - add_subdirectory(${ARCSEC_LIB_PATH}) + add_subdirectory(${LIB_ARCSEC_PATH}) +endif() + +if(EIVE_BUILD_UNITTESTS) + add_subdirectory(${LIB_CATCH2_PATH}) + add_subdirectory(${UNITTEST_PATH}) endif() if(EIVE_BUILD_WATCHDOG) @@ -195,6 +231,7 @@ if((NOT BUILD_Q7S_SIMPLE_MODE) AND (NOT EIVE_BUILD_WATCHDOG)) endif() endif() + if(NOT EIVE_BUILD_WATCHDOG) if(ADD_CSP_LIB) target_link_libraries(${TARGET_NAME} PRIVATE @@ -203,18 +240,24 @@ if(NOT EIVE_BUILD_WATCHDOG) endif() endif() -if(ADD_ETL_LIB) +if(EIVE_ADD_ETL_LIB) target_link_libraries(${TARGET_NAME} PRIVATE ${LIB_ETL_NAME} ) endif() -if(ADD_JSON_LIB) +if(EIVE_ADD_JSON_LIB) target_link_libraries(${TARGET_NAME} PRIVATE ${LIB_JSON_NAME} ) endif() +if(EIVE_BUILD_UNITTESTS) + target_link_libraries(${TARGET_NAME} PRIVATE + ${CATCH2_TARGET} + ) +endif() + target_link_libraries(${TARGET_NAME} PRIVATE ${LIB_CXX_FS} ) @@ -224,7 +267,7 @@ target_include_directories(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${FSFW_CONFIG_PATH} ${CMAKE_CURRENT_BINARY_DIR} - ${ARCSEC_LIB_PATH} + ${LIB_ARCSEC_PATH} ) if(TGT_BSP MATCHES "arm/q7s") diff --git a/README.md b/README.md index b12400e9..b6a18947 100644 --- a/README.md +++ b/README.md @@ -171,6 +171,26 @@ cmake -DTGT_BSP=arm/q7s -DFSFW_OSAL=linux -DEIVE_BUILD_WATCHDOG=ON -DCMAKE_BUILD cmake --build . -j ``` +### Hosted + +You can also replace `linux` by `host` for this command to build on Windows or for generic OSes + +```sh +mkdir build-Debug-Host && cd build-Debug-Host +cmake -DFSFW_OSAL=linux -DCMAKE_BUILD_TYPE=Debug .. +cmake --build . -j +``` + +### Unittests + +You can also replace `linux` by `host` for this command to build on Windows + +```sh +mkdir build-Debug-Unittest && cd build-Debug-Unittest +cmake -DFSFW_OSAL=linux -DEIVE_BUILD_UNITTESTS=ON .. +cmake --build . -j +``` + ## Connect to EIVE flatsat ### DNS diff --git a/bsp_hosted/ObjectFactory.cpp b/bsp_hosted/ObjectFactory.cpp index d7878e46..6803ace4 100644 --- a/bsp_hosted/ObjectFactory.cpp +++ b/bsp_hosted/ObjectFactory.cpp @@ -44,18 +44,5 @@ void ObjectFactory::produce(void* args){ Factory::setStaticFrameworkObjectIds(); ObjectFactory::produceGenericObjects(); -#if OBSW_USE_TMTC_TCP_BRIDGE == 0 - sif::info << "Setting up UDP TMTC bridge with listener port " << - UdpTmTcBridge::DEFAULT_SERVER_PORT << std::endl; - new UdpTmTcBridge(objects::TMTC_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR); - new UdpTcPollingTask(objects::TMTC_POLLING_TASK, objects::TMTC_BRIDGE); -#else - sif::info << "Setting up TCP TMTC bridge with listener port " << - TcpTmTcServer::DEFAULT_SERVER_PORT << std::endl; - new TcpTmTcBridge(objects::TMTC_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR); - new TcpTmTcServer(objects::TMTC_POLLING_TASK, objects::TMTC_BRIDGE); -#endif - new TestTask(objects::TEST_TASK); - } diff --git a/bsp_q7s/core/InitMission.cpp b/bsp_q7s/core/InitMission.cpp index bc9139fb..deda0ed8 100644 --- a/bsp_q7s/core/InitMission.cpp +++ b/bsp_q7s/core/InitMission.cpp @@ -82,19 +82,21 @@ void initmission::initTasks() { initmission::printAddObjectError("TM_FUNNEL", objects::TM_FUNNEL); } - /* UDP bridge */ +#if OBSW_ADD_TCPIP_BRIDGE == 1 + // TMTC bridge PeriodicTaskIF* tmtcBridgeTask = factory->createPeriodicTask( - "UDP_UNIX_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc); + "TCPIP_TMTC_BRIDGE", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc); result = tmtcBridgeTask->addComponent(objects::TMTC_BRIDGE); if(result != HasReturnvaluesIF::RETURN_OK) { initmission::printAddObjectError("UDP_BRIDGE", objects::TMTC_BRIDGE); } PeriodicTaskIF* tmtcPollingTask = factory->createPeriodicTask( - "UDP_POLLING", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc); + "TMTC_POLLING", 80, PeriodicTaskIF::MINIMUM_STACK_SIZE, 2.0, missedDeadlineFunc); result = tmtcPollingTask->addComponent(objects::TMTC_POLLING_TASK); if(result != HasReturnvaluesIF::RETURN_OK) { initmission::printAddObjectError("UDP_POLLING", objects::TMTC_POLLING_TASK); } +#endif # if BOARD_TE0720 == 0 // FS task, task interval does not matter because it runs in permanent loop, priority low @@ -139,8 +141,12 @@ void initmission::initTasks() { sif::info << "Starting tasks.." << std::endl; tmTcDistributor->startTask(); + +#if OBSW_ADD_TCPIP_BRIDGE == 1 tmtcBridgeTask->startTask(); tmtcPollingTask->startTask(); +#endif + #if BOARD_TE0720 == 0 coreController->startTask(); #endif diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp index e0cc084d..b916977a 100644 --- a/bsp_q7s/core/ObjectFactory.cpp +++ b/bsp_q7s/core/ObjectFactory.cpp @@ -69,16 +69,6 @@ #include "fsfw/tmtcservices/PusServiceBase.h" #include "fsfw/tmtcpacket/pus/tm.h" -#if OBSW_USE_TMTC_TCP_BRIDGE == 0 -// UDP server includes -#include "fsfw/osal/common/UdpTmTcBridge.h" -#include "fsfw/osal/common/UdpTcPollingTask.h" -#else -// TCP server includes -#include "fsfw/osal/common/TcpTmTcBridge.h" -#include "fsfw/osal/common/TcpTmTcServer.h" -#endif - #include "linux/boardtest/SpiTestClass.h" #if OBSW_TEST_LIBGPIOD == 1 @@ -114,6 +104,7 @@ void Factory::setStaticFrameworkObjectIds() { void ObjectFactory::produce(void* args) { ObjectFactory::setStatics(); ObjectFactory::produceGenericObjects(); + LinuxLibgpioIF* gpioComIF = nullptr; UartComIF* uartComIF = nullptr; SpiComIF* spiComIF = nullptr; @@ -173,19 +164,6 @@ void ObjectFactory::produce(void* args) { #endif /* TE7020 != 0 */ -#if OBSW_USE_TMTC_TCP_BRIDGE == 0 - auto udpBridge = new UdpTmTcBridge(objects::TMTC_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR); - new UdpTcPollingTask(objects::TMTC_POLLING_TASK, objects::TMTC_BRIDGE); - sif::info << "Created UDP server for TMTC commanding with listener port " << - udpBridge->getUdpPort() << std::endl; -#else - auto tmtcBridge = new TcpTmTcBridge(objects::TMTC_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR); - tmtcBridge->setMaxNumberOfPacketsStored(50); - auto tcpServer = new TcpTmTcServer(objects::TMTC_POLLING_TASK, objects::TMTC_BRIDGE); - sif::info << "Created TCP server for TMTC commanding with listener port " - << tcpServer->getTcpPort() << std::endl; -#endif /* OBSW_USE_TMTC_TCP_BRIDGE == 0 */ - /* Test Task */ #if OBSW_ADD_TEST_CODE == 1 createTestComponents(gpioComIF); diff --git a/common/config/CMakeLists.txt b/common/config/CMakeLists.txt index f38f2c50..5c4b4942 100644 --- a/common/config/CMakeLists.txt +++ b/common/config/CMakeLists.txt @@ -1,3 +1,7 @@ target_include_directories(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} +) + +target_sources(${TARGET_NAME} PRIVATE + commonConfig.cpp ) \ No newline at end of file diff --git a/common/config/commonConfig.cpp b/common/config/commonConfig.cpp new file mode 100644 index 00000000..1c9ece8b --- /dev/null +++ b/common/config/commonConfig.cpp @@ -0,0 +1,5 @@ +#include "commonConfig.h" +#include "tmtc/apid.h" +#include "fsfw/tmtcpacket/SpacePacket.h" + +const uint16_t common::TC_PACKET_ID = spacepacket::getTcSpacePacketIdFromApid(apid::EIVE_OBSW); diff --git a/common/config/commonConfig.h.in b/common/config/commonConfig.h.in index 52b5dd45..055f86aa 100644 --- a/common/config/commonConfig.h.in +++ b/common/config/commonConfig.h.in @@ -1,10 +1,18 @@ #ifndef COMMON_CONFIG_COMMONCONFIG_H_ #define COMMON_CONFIG_COMMONCONFIG_H_ +#include + #define OBSW_ADD_LWGPS_TEST 0 +// Disable this for mission code. It allows exchanging TMTC packets via the Ethernet port +#define OBSW_ADD_TCPIP_BRIDGE 1 // Use TCP instead of UDP for the TMTC bridge. This allows using the TMTC client locally // because UDP packets are not allowed in the VPN -#define OBSW_USE_TMTC_TCP_BRIDGE 1 +#define OBSW_USE_TCP_BRIDGE 1 + +namespace common { +extern const uint16_t TC_PACKET_ID; +} #endif /* COMMON_CONFIG_COMMONCONFIG_H_ */ diff --git a/common/config/devices/powerSwitcherList.h b/common/config/devices/powerSwitcherList.h new file mode 100644 index 00000000..45428a2e --- /dev/null +++ b/common/config/devices/powerSwitcherList.h @@ -0,0 +1,60 @@ +#ifndef FSFWCONFIG_DEVICES_POWERSWITCHERLIST_H_ +#define FSFWCONFIG_DEVICES_POWERSWITCHERLIST_H_ + +#include "OBSWConfig.h" + +#include + +namespace pcduSwitches { + /* Switches are uint8_t datatype and go from 0 to 255 */ + enum SwitcherList: uint8_t { + Q7S, + PAYLOAD_PCDU_CH1, + RW, + TCS_BOARD_8V_HEATER_IN, + SUS_REDUNDANT, + DEPLOYMENT_MECHANISM, + PAYLOAD_PCDU_CH6, + ACS_BOARD_SIDE_B, + PAYLOAD_CAMERA, + TCS_BOARD_3V3, + SYRLINKS, + STAR_TRACKER, + MGT, + SUS_NOMINAL, + SOLAR_CELL_EXP, + PLOC, + ACS_BOARD_SIDE_A, + NUMBER_OF_SWITCHES + }; + + static const uint8_t ON = 1; + static const uint8_t OFF = 0; + + /* Output states after reboot of the PDUs */ + static const uint8_t INIT_STATE_Q7S = ON; + static const uint8_t INIT_STATE_PAYLOAD_PCDU_CH1 = OFF; + static const uint8_t INIT_STATE_RW = OFF; +#if BOARD_TE0720 == 1 + /* Because the TE0720 is not connected to the PCDU, this switch is always on */ + static const uint8_t INIT_STATE_TCS_BOARD_8V_HEATER_IN = ON; +#else + static const uint8_t INIT_STATE_TCS_BOARD_8V_HEATER_IN = OFF; +#endif + static const uint8_t INIT_STATE_SUS_REDUNDANT = OFF; + static const uint8_t INIT_STATE_DEPLOYMENT_MECHANISM = OFF; + static const uint8_t INIT_STATE_PAYLOAD_PCDU_CH6 = OFF; + static const uint8_t INIT_STATE_ACS_BOARD_SIDE_B = OFF; + static const uint8_t INIT_STATE_PAYLOAD_CAMERA = OFF; + static const uint8_t INIT_STATE_TCS_BOARD_3V3 = OFF; + static const uint8_t INIT_STATE_SYRLINKS = OFF; + static const uint8_t INIT_STATE_STAR_TRACKER = OFF; + static const uint8_t INIT_STATE_MGT = OFF; + static const uint8_t INIT_STATE_SUS_NOMINAL = OFF; + static const uint8_t INIT_STATE_SOLAR_CELL_EXP = OFF; + static const uint8_t INIT_STATE_PLOC = OFF; + static const uint8_t INIT_STATE_ACS_BOARD_SIDE_A = OFF; +} + + +#endif /* FSFWCONFIG_DEVICES_POWERSWITCHERLIST_H_ */ diff --git a/linux/fsfwconfig/tmtc/apid.h b/common/config/tmtc/apid.h similarity index 100% rename from linux/fsfwconfig/tmtc/apid.h rename to common/config/tmtc/apid.h diff --git a/fsfw b/fsfw index a84c770d..3d0ce199 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit a84c770dfb8447325c263da42d5cecd99b38d1f0 +Subproject commit 3d0ce1998114c5d7a43034233ee03a800c8821b0 diff --git a/misc/eclipse/.cproject b/misc/eclipse/.cproject index fe0208b8..7d7c4c09 100644 --- a/misc/eclipse/.cproject +++ b/misc/eclipse/.cproject @@ -1357,6 +1357,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1374,6 +1436,7 @@ + @@ -1385,6 +1448,9 @@ + + + diff --git a/misc/eclipse/.project b/misc/eclipse/.project index 86d98589..62145ff4 100644 --- a/misc/eclipse/.project +++ b/misc/eclipse/.project @@ -7,7 +7,7 @@ org.eclipse.cdt.managedbuilder.core.genmakebuilder - full,incremental, + clean,full,incremental, diff --git a/misc/eclipse/Host/eive-linux-host-debug-cmake.launch b/misc/eclipse/Host/eive-linux-host-debug-cmake.launch index 294772d8..d8cfc8c1 100644 --- a/misc/eclipse/Host/eive-linux-host-debug-cmake.launch +++ b/misc/eclipse/Host/eive-linux-host-debug-cmake.launch @@ -18,7 +18,7 @@ - + diff --git a/misc/eclipse/Host/eive-linux-host-unittest.launch b/misc/eclipse/Host/eive-linux-host-unittest.launch new file mode 100644 index 00000000..85d54281 --- /dev/null +++ b/misc/eclipse/Host/eive-linux-host-unittest.launch @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mission/core/GenericFactory.cpp b/mission/core/GenericFactory.cpp index 4ee1ff70..a0939f1c 100644 --- a/mission/core/GenericFactory.cpp +++ b/mission/core/GenericFactory.cpp @@ -4,6 +4,7 @@ #include #include +#include "objects/systemObjectList.h" #include #include @@ -23,12 +24,24 @@ #include #include +#if OBSW_ADD_TCPIP_BRIDGE == 1 +#if OBSW_USE_TCP_BRIDGE == 0 +// UDP server includes +#include "fsfw/osal/common/UdpTmTcBridge.h" +#include "fsfw/osal/common/UdpTcPollingTask.h" +#else +// TCP server includes +#include "fsfw/osal/common/TcpTmTcBridge.h" +#include "fsfw/osal/common/TcpTmTcServer.h" +#endif +#endif + #if OBSW_ADD_TEST_CODE == 1 - #include +#include #endif void ObjectFactory::produceGenericObjects() { - /* Framework objects */ + // Framework objects new EventManager(objects::EVENT_MANAGER); new HealthTable(objects::HEALTH_TABLE); new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER); @@ -61,10 +74,10 @@ void ObjectFactory::produceGenericObjects() { objects::CCSDS_PACKET_DISTRIBUTOR); - /* TMTC Reception via UDP socket */ + // Every TM packet goes through this funnel new TmFunnel(objects::TM_FUNNEL); - /* PUS stack */ + // PUS service stack new Service1TelecommandVerification(objects::PUS_SERVICE_1_VERIFICATION, apid::EIVE_OBSW, pus::PUS_SERVICE_1, objects::TM_FUNNEL, 20); new Service2DeviceAccess(objects::PUS_SERVICE_2_DEVICE_ACCESS, @@ -83,4 +96,23 @@ void ObjectFactory::produceGenericObjects() { pus::PUS_SERVICE_20); new CService200ModeCommanding(objects::PUS_SERVICE_200_MODE_MGMT, apid::EIVE_OBSW, pus::PUS_SERVICE_200); + + +#if OBSW_ADD_TCPIP_BRIDGE == 1 +#if OBSW_USE_TCP_BRIDGE == 0 + auto tmtcBridge = new UdpTmTcBridge(objects::TMTC_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR); + tmtcBridge->setMaxNumberOfPacketsStored(50); + new UdpTcPollingTask(objects::TMTC_POLLING_TASK, objects::TMTC_BRIDGE); + sif::info << "Created UDP server for TMTC commanding with listener port " << + udpBridge->getUdpPort() << std::endl; +#else + auto tmtcBridge = new TcpTmTcBridge(objects::TMTC_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR); + tmtcBridge->setMaxNumberOfPacketsStored(50); + auto tcpServer = new TcpTmTcServer(objects::TMTC_POLLING_TASK, objects::TMTC_BRIDGE); + // TCP is stream based. Use packet ID as start marker when parsing for space packets + tcpServer->setSpacePacketParsingOptions({common::TC_PACKET_ID}); + sif::info << "Created TCP server for TMTC commanding with listener port " + << tcpServer->getTcpPort() << std::endl; +#endif /* OBSW_USE_TMTC_TCP_BRIDGE == 0 */ +#endif /* OBSW_ADD_TCPIP_BRIDGE == 1 */ } diff --git a/thirdparty/Catch2 b/thirdparty/Catch2 new file mode 160000 index 00000000..42695403 --- /dev/null +++ b/thirdparty/Catch2 @@ -0,0 +1 @@ +Subproject commit 426954032f263754d2fff4cffce8552e7371965e diff --git a/tmtc b/tmtc index 53bf6508..82495ad7 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 53bf65083889af10f77c3899972b1153ea835f3c +Subproject commit 82495ad785c83440ee90846bce70be1659b66209 diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt new file mode 100644 index 00000000..0c799d45 --- /dev/null +++ b/unittest/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(testcfg) + +target_sources(${TARGET_NAME} PRIVATE + main.cpp +) \ No newline at end of file diff --git a/unittest/main.cpp b/unittest/main.cpp new file mode 100644 index 00000000..cd4f4b77 --- /dev/null +++ b/unittest/main.cpp @@ -0,0 +1,7 @@ +#include "fsfw/serviceinterface/ServiceInterfaceStream.h" +#include "fsfw_tests/unit/CatchRunner.h" + +int main(int argc, char* argv[]) { + fsfwtest::customMain(argc, argv); +} + diff --git a/unittest/testcfg/CMakeLists.txt b/unittest/testcfg/CMakeLists.txt new file mode 100644 index 00000000..50d13663 --- /dev/null +++ b/unittest/testcfg/CMakeLists.txt @@ -0,0 +1,9 @@ +target_sources(${TARGET_NAME} PRIVATE + ipc/MissionMessageTypes.cpp + pollingsequence/PollingSequenceFactory.cpp +) + +# Add include paths for the executable +target_include_directories(${TARGET_NAME} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} +) diff --git a/unittest/testcfg/FSFWConfig.h.in b/unittest/testcfg/FSFWConfig.h.in new file mode 100644 index 00000000..d2ed901d --- /dev/null +++ b/unittest/testcfg/FSFWConfig.h.in @@ -0,0 +1,81 @@ +#ifndef CONFIG_FSFWCONFIG_H_ +#define CONFIG_FSFWCONFIG_H_ + +#include +#include + +//! Used to determine whether C++ ostreams are used which can increase +//! the binary size significantly. If this is disabled, +//! the C stdio functions can be used alternatively +#define FSFW_CPP_OSTREAM_ENABLED 1 + +//! More FSFW related printouts. Useful for development. +#define FSFW_ENHANCED_PRINTOUT 0 + +//! Can be used to completely disable printouts, even the C stdio ones. +//! By default, printouts will be disabled for the unit tests. +#if FSFW_CPP_OSTREAM_ENABLED == 0 && FSFW_ENHANCED_PRINTOUT == 0 + #ifndef FSFW_DISABLE_PRINTOUT + #define FSFW_DISABLE_PRINTOUT 1 + #endif +#endif + +#define FSFW_USE_PUS_C_TELEMETRY 1 +#define FSFW_USE_PUS_C_TELECOMMANDS 1 + +//! Can be used to enable additional debugging printouts for developing the FSFW +#define FSFW_PRINT_VERBOSITY_LEVEL 0 + +//! Can be used to disable the ANSI color sequences for C stdio. +#define FSFW_COLORED_OUTPUT 0 + +//! If FSFW_OBJ_EVENT_TRANSLATION is set to one, +//! additional output which requires the translation files translateObjects +//! and translateEvents (and their compiled source files) +#define FSFW_OBJ_EVENT_TRANSLATION 0 + +#if FSFW_OBJ_EVENT_TRANSLATION == 1 +//! Specify whether info events are printed too. +#define FSFW_DEBUG_INFO 1 +#include "objects/translateObjects.h" +#include "events/translateEvents.h" +#else +#endif + +//! When using the newlib nano library, C99 support for stdio facilities +//! will not be provided. This define should be set to 1 if this is the case. +#define FSFW_NO_C99_IO 1 + +//! Specify whether a special mode store is used for Subsystem components. +#define FSFW_USE_MODESTORE 0 + +//! Defines if the real time scheduler for linux should be used. +//! If set to 0, this will also disable priority settings for linux +//! as most systems will not allow to set nice values without privileges +//! For embedded linux system set this to 1. +//! If set to 1 the binary needs "cap_sys_nice=eip" privileges to run +#define FSFW_USE_REALTIME_FOR_LINUX 1 + +namespace fsfwconfig { +//! Default timestamp size. The default timestamp will be an eight byte CDC +//! short timestamp. +static constexpr uint8_t FSFW_MISSION_TIMESTAMP_SIZE = 8; + +//! Configure the allocated pool sizes for the event manager. +static constexpr size_t FSFW_EVENTMGMR_MATCHTREE_NODES = 240; +static constexpr size_t FSFW_EVENTMGMT_EVENTIDMATCHERS = 120; +static constexpr size_t FSFW_EVENTMGMR_RANGEMATCHERS = 120; + +//! Defines the FIFO depth of each commanding service base which +//! also determines how many commands a CSB service can handle in one cycle +//! simulataneously. This will increase the required RAM for +//! each CSB service ! +static constexpr uint8_t FSFW_CSB_FIFO_DEPTH = 6; + +static constexpr size_t FSFW_PRINT_BUFFER_SIZE = 124; + +static constexpr size_t FSFW_MAX_TM_PACKET_SIZE = 1500; + +} + +#endif /* CONFIG_FSFWCONFIG_H_ */ diff --git a/unittest/testcfg/OBSWConfig.h.in b/unittest/testcfg/OBSWConfig.h.in new file mode 100644 index 00000000..34eda31f --- /dev/null +++ b/unittest/testcfg/OBSWConfig.h.in @@ -0,0 +1,8 @@ +#ifndef TESTCFG_OBSWCONFIG_H_ +#define TESTCFG_OBSWCONFIG_H_ + + + + + +#endif /* TESTCFG_OBSWCONFIG_H_ */ diff --git a/unittest/testcfg/TestsConfig.h.in b/unittest/testcfg/TestsConfig.h.in new file mode 100644 index 00000000..7d950070 --- /dev/null +++ b/unittest/testcfg/TestsConfig.h.in @@ -0,0 +1,21 @@ +#ifndef FSFW_UNITTEST_CONFIG_TESTSCONFIG_H_ +#define FSFW_UNITTEST_CONFIG_TESTSCONFIG_H_ + +#define FSFW_ADD_DEFAULT_FACTORY_FUNCTIONS 1 + +#ifdef __cplusplus + +#include "objects/systemObjectList.h" +#include "events/subsystemIdRanges.h" +#include "returnvalues/classIds.h" + +namespace config { +#endif + +/* Add mission configuration flags here */ + +#ifdef __cplusplus +} +#endif + +#endif /* FSFW_UNITTEST_CONFIG_TESTSCONFIG_H_ */ diff --git a/unittest/testcfg/devices/logicalAddresses.cpp b/unittest/testcfg/devices/logicalAddresses.cpp new file mode 100644 index 00000000..c7ce314d --- /dev/null +++ b/unittest/testcfg/devices/logicalAddresses.cpp @@ -0,0 +1,5 @@ +#include "logicalAddresses.h" + + + + diff --git a/unittest/testcfg/devices/logicalAddresses.h b/unittest/testcfg/devices/logicalAddresses.h new file mode 100644 index 00000000..cdf87025 --- /dev/null +++ b/unittest/testcfg/devices/logicalAddresses.h @@ -0,0 +1,15 @@ +#ifndef CONFIG_DEVICES_LOGICALADDRESSES_H_ +#define CONFIG_DEVICES_LOGICALADDRESSES_H_ + +#include +#include +#include + +namespace addresses { + /* Logical addresses have uint32_t datatype */ + enum logicalAddresses: address_t { + }; +} + + +#endif /* CONFIG_DEVICES_LOGICALADDRESSES_H_ */ diff --git a/unittest/testcfg/devices/powerSwitcherList.cpp b/unittest/testcfg/devices/powerSwitcherList.cpp new file mode 100644 index 00000000..343f78d0 --- /dev/null +++ b/unittest/testcfg/devices/powerSwitcherList.cpp @@ -0,0 +1,4 @@ +#include "powerSwitcherList.h" + + + diff --git a/unittest/testcfg/devices/powerSwitcherList.h b/unittest/testcfg/devices/powerSwitcherList.h new file mode 100644 index 00000000..86ddea57 --- /dev/null +++ b/unittest/testcfg/devices/powerSwitcherList.h @@ -0,0 +1,12 @@ +#ifndef CONFIG_DEVICES_POWERSWITCHERLIST_H_ +#define CONFIG_DEVICES_POWERSWITCHERLIST_H_ + +namespace switches { + /* Switches are uint8_t datatype and go from 0 to 255 */ + enum switcherList { + }; + +} + + +#endif /* CONFIG_DEVICES_POWERSWITCHERLIST_H_ */ diff --git a/unittest/testcfg/events/subsystemIdRanges.h b/unittest/testcfg/events/subsystemIdRanges.h new file mode 100644 index 00000000..26af041e --- /dev/null +++ b/unittest/testcfg/events/subsystemIdRanges.h @@ -0,0 +1,19 @@ +#ifndef CONFIG_EVENTS_SUBSYSTEMIDRANGES_H_ +#define CONFIG_EVENTS_SUBSYSTEMIDRANGES_H_ + +#include +#include "commonSubsystemIds.h" +#include + +/** + * @brief Custom subsystem IDs can be added here + * @details + * Subsystem IDs are used to create unique events. + */ +namespace SUBSYSTEM_ID { +enum: uint8_t { + SUBSYSTEM_ID_START = FW_SUBSYSTEM_ID_RANGE, +}; +} + +#endif /* CONFIG_EVENTS_SUBSYSTEMIDRANGES_H_ */ diff --git a/unittest/testcfg/ipc/MissionMessageTypes.cpp b/unittest/testcfg/ipc/MissionMessageTypes.cpp new file mode 100644 index 00000000..d68cb58c --- /dev/null +++ b/unittest/testcfg/ipc/MissionMessageTypes.cpp @@ -0,0 +1,12 @@ +#include "MissionMessageTypes.h" + +#include + +void messagetypes::clearMissionMessage(CommandMessage* message) { + switch(message->getMessageType()) { + default: + break; + } +} + + diff --git a/unittest/testcfg/ipc/MissionMessageTypes.h b/unittest/testcfg/ipc/MissionMessageTypes.h new file mode 100644 index 00000000..832d8e58 --- /dev/null +++ b/unittest/testcfg/ipc/MissionMessageTypes.h @@ -0,0 +1,22 @@ +#ifndef CONFIG_IPC_MISSIONMESSAGETYPES_H_ +#define CONFIG_IPC_MISSIONMESSAGETYPES_H_ + +#include + +class CommandMessage; + +/** + * Custom command messages are specified here. + * Most messages needed to use FSFW are already located in + * + * @param message Generic Command Message + */ +namespace messagetypes{ +enum MESSAGE_TYPE { + MISSION_MESSAGE_TYPE_START = FW_MESSAGES_COUNT, +}; + +void clearMissionMessage(CommandMessage* message); +} + +#endif /* CONFIG_IPC_MISSIONMESSAGETYPES_H_ */ diff --git a/unittest/testcfg/objects/systemObjectList.h b/unittest/testcfg/objects/systemObjectList.h new file mode 100644 index 00000000..9ed43873 --- /dev/null +++ b/unittest/testcfg/objects/systemObjectList.h @@ -0,0 +1,33 @@ +#ifndef HOSTED_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_ +#define HOSTED_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_ + +#include +#include "commonObjects.h" +#include + +// The objects will be instantiated in the ID order +namespace objects { + enum sourceObjects: uint32_t { + /* All addresses between start and end are reserved for the FSFW */ + FSFW_CONFIG_RESERVED_START = PUS_SERVICE_1_VERIFICATION, + FSFW_CONFIG_RESERVED_END = TM_STORE, + + CCSDS_DISTRIBUTOR = 10, + PUS_DISTRIBUTOR = 11, + TM_FUNNEL = 12, + + UDP_BRIDGE = 15, + UDP_POLLING_TASK = 16, + + TEST_ECHO_COM_IF = 20, + TEST_DEVICE = 21, + + HK_RECEIVER_MOCK = 22, + TEST_LOCAL_POOL_OWNER_BASE = 25, + + SHARED_SET_ID = 26 + + }; +} + +#endif /* BSP_CONFIG_OBJECTS_SYSTEMOBJECTLIST_H_ */ diff --git a/unittest/testcfg/pollingsequence/PollingSequenceFactory.cpp b/unittest/testcfg/pollingsequence/PollingSequenceFactory.cpp new file mode 100644 index 00000000..e3ee874a --- /dev/null +++ b/unittest/testcfg/pollingsequence/PollingSequenceFactory.cpp @@ -0,0 +1,39 @@ +#include "PollingSequenceFactory.h" + +#include + +#include +#include +#include + +ReturnValue_t pst::pollingSequenceInitDefault( + FixedTimeslotTaskIF *thisSequence) { + /* Length of a communication cycle */ + uint32_t length = thisSequence->getPeriodMs(); + + /* Add polling sequence table here */ + thisSequence->addSlot(objects::TEST_DEVICE, 0, + DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::TEST_DEVICE, 0.3, + DeviceHandlerIF::SEND_WRITE); + thisSequence->addSlot(objects::TEST_DEVICE, 0.45 * length, + DeviceHandlerIF::GET_WRITE); + thisSequence->addSlot(objects::TEST_DEVICE, 0.6 * length, + DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::TEST_DEVICE, 0.8 * length, + DeviceHandlerIF::GET_READ); + + if (thisSequence->checkSequence() == HasReturnvaluesIF::RETURN_OK) { + return HasReturnvaluesIF::RETURN_OK; + } + else { +#if FSFW_CPP_OSTREAM_ENABLED + sif::error << "pst::pollingSequenceInitDefault: Sequence invalid!" + << std::endl; +#else + sif::printError("pst::pollingSequenceInitDefault: Sequence invalid!"); +#endif + return HasReturnvaluesIF::RETURN_FAILED; + } +} + diff --git a/unittest/testcfg/pollingsequence/PollingSequenceFactory.h b/unittest/testcfg/pollingsequence/PollingSequenceFactory.h new file mode 100644 index 00000000..c5d41b7d --- /dev/null +++ b/unittest/testcfg/pollingsequence/PollingSequenceFactory.h @@ -0,0 +1,32 @@ +#ifndef POLLINGSEQUENCEFACTORY_H_ +#define POLLINGSEQUENCEFACTORY_H_ + +#include + +class FixedTimeslotTaskIF; + +/** + * All device handlers are scheduled by adding them into Polling Sequence Tables (PST) + * to satisfy stricter timing requirements of device communication, + * A device handler has four different communication steps: + * 1. DeviceHandlerIF::SEND_WRITE -> Send write via interface + * 2. DeviceHandlerIF::GET_WRITE -> Get confirmation for write + * 3. DeviceHandlerIF::SEND_READ -> Send read request + * 4. DeviceHandlerIF::GET_READ -> Read from interface + * The PST specifies precisely when the respective ComIF functions are called + * during the communication cycle time. + * The task is created using the FixedTimeslotTaskIF, + * which utilises the underlying Operating System Abstraction Layer (OSAL) + * + * @param thisSequence FixedTimeslotTaskIF * object is passed inside the Factory class when creating the PST + * @return + */ +namespace pst { + +/* Default PST */ +ReturnValue_t pollingSequenceInitDefault(FixedTimeslotTaskIF *thisSequence); + + +} + +#endif /* POLLINGSEQUENCEINIT_H_ */ diff --git a/unittest/testcfg/returnvalues/classIds.h b/unittest/testcfg/returnvalues/classIds.h new file mode 100644 index 00000000..7a292708 --- /dev/null +++ b/unittest/testcfg/returnvalues/classIds.h @@ -0,0 +1,17 @@ +#ifndef CONFIG_RETURNVALUES_CLASSIDS_H_ +#define CONFIG_RETURNVALUES_CLASSIDS_H_ + +#include "commonClassIds.h" +#include + +/** + * @brief CLASS_ID defintions which are required for custom returnvalues. + */ +namespace CLASS_ID { +enum { + MISSION_CLASS_ID_START = FW_CLASS_ID_COUNT, +}; +} + + +#endif /* CONFIG_RETURNVALUES_CLASSIDS_H_ */ diff --git a/unittest/testcfg/tmtc/apid.h b/unittest/testcfg/tmtc/apid.h new file mode 100644 index 00000000..0172f6e3 --- /dev/null +++ b/unittest/testcfg/tmtc/apid.h @@ -0,0 +1,18 @@ +#ifndef CONFIG_TMTC_APID_H_ +#define CONFIG_TMTC_APID_H_ + +#include + +/** + * Application Process Definition: entity, uniquely identified by an + * application process ID (APID), capable of generating telemetry source + * packets and receiving telecommand packets. + * + * Chose APID(s) for mission and define it here. + */ +namespace apid { + static const uint16_t EIVE_OBSW = 0x65; +} + + +#endif /* CONFIG_TMTC_APID_H_ */ diff --git a/unittest/testcfg/tmtc/pusIds.h b/unittest/testcfg/tmtc/pusIds.h new file mode 100644 index 00000000..821a9982 --- /dev/null +++ b/unittest/testcfg/tmtc/pusIds.h @@ -0,0 +1,25 @@ +#ifndef CONFIG_TMTC_PUSIDS_HPP_ +#define CONFIG_TMTC_PUSIDS_HPP_ + +#include + +namespace pus { +enum Ids: uint8_t { + PUS_SERVICE_1 = 1, + PUS_SERVICE_2 = 2, + PUS_SERVICE_3 = 3, + PUS_SERVICE_5 = 5, + PUS_SERVICE_6 = 6, + PUS_SERVICE_8 = 8, + PUS_SERVICE_9 = 9, + PUS_SERVICE_11 = 11, + PUS_SERVICE_17 = 17, + PUS_SERVICE_19 = 19, + PUS_SERVICE_20 = 20, + PUS_SERVICE_23 = 23, + PUS_SERVICE_200 = 200, + PUS_SERVICE_201 = 201, +}; +}; + +#endif /* CONFIG_TMTC_PUSIDS_HPP_ */ diff --git a/unittest/unittest.mk b/unittest/unittest.mk deleted file mode 100644 index e69de29b..00000000