Compare commits

..

134 Commits

Author SHA1 Message Date
2f511523cb Merge pull request 'Apollo Sojus Test Project Version 1.0.0' (#408) from development into master
Reviewed-on: fsfw/fsfw#408
2021-04-27 14:20:06 +02:00
9f83739771 Merge pull request 'dhb multiple replies support' (#416) from eive/fsfw:meier/multipleRepliesDhb into development
Reviewed-on: fsfw/fsfw#416
2021-04-27 14:18:15 +02:00
054de9781b avoid duplicate printout 2021-04-27 14:17:27 +02:00
20e7fe6cb1 Merge branch 'development' into meier/multipleRepliesDhb 2021-04-26 16:19:57 +02:00
f8cd8e1e7d Merge pull request 'ParameterHelper: Returnvalue not checked' (#417) from KSat/fsfw:mueller/parameter-bugfix into development
Reviewed-on: fsfw/fsfw#417
2021-04-26 16:19:31 +02:00
818634755d checking returnvalue now 2021-04-26 15:47:49 +02:00
87fee9bd0e dhb multiple replies support 2021-04-25 11:40:04 +02:00
6a40b8244d Merge pull request 'Subsystems replaced Magic Numbers' (#415) from gaisser_fixes_subsystem into development
Reviewed-on: fsfw/fsfw#415
2021-04-22 19:52:08 +02:00
4fd443f70b Merge remote-tracking branch 'origin/gaisser_fixes_subsystem' into gaisser_fixes_subsystem 2021-04-20 22:03:52 +02:00
06631d06a5 Added comments in AssemblyBase and SubsystemBase 2021-04-20 22:01:56 +02:00
9244a96e7b Merge branch 'development' into gaisser_fixes_subsystem 2021-04-20 21:07:31 +02:00
03ef63302b Replaced Magic Numbers 2021-04-20 20:45:15 +02:00
c50796b785 Merge pull request 'calling empty ctor now for SerializeElement (coverity)' (#413) from mueller/serialiize-element-coverity into development
Reviewed-on: fsfw/fsfw#413
2021-04-20 17:57:00 +02:00
a0caa92a8a Merge branch 'development' into mueller/serialiize-element-coverity 2021-04-20 17:52:01 +02:00
a91139be76 Merge pull request 'small fix for linux printf printout in TCP/IP code' (#411) from mueller/linuxtcpip-printout-fix into development
Reviewed-on: fsfw/fsfw#411
2021-04-20 17:51:48 +02:00
fee2ac0eb9 Merge branch 'development' into mueller/linuxtcpip-printout-fix 2021-04-20 17:50:10 +02:00
2878f21c93 Merge pull request 'Possible bugfix found by coverity in TimeMessage' (#412) from mueller/timemessage-override-fix into development
Reviewed-on: fsfw/fsfw#412
2021-04-20 17:49:44 +02:00
4caf906d96 Merge branch 'development' into mueller/timemessage-override-fix 2021-04-20 17:44:07 +02:00
b38e9ede0c Merge branch 'development' into mueller/linuxtcpip-printout-fix 2021-04-20 17:43:44 +02:00
17b3672330 Merge pull request 'heater tweaks + coverity fix' (#410) from mueller/heater-coverity into development
Reviewed-on: fsfw/fsfw#410
2021-04-20 17:43:19 +02:00
629814bc9b Just comments 2021-04-20 17:35:28 +02:00
4fb792447e Small rearragenment in Heater.cpp 2021-04-20 17:29:56 +02:00
40dae8c961 Merge branch 'development' into mueller/heater-coverity 2021-04-20 16:38:52 +02:00
9e1f3ee585 Merge pull request 'small coverity tweak for Health Device' (#409) from mueller/health-coverity-fix into development
Reviewed-on: fsfw/fsfw#409
2021-04-20 16:38:37 +02:00
e851d8a46c Merge branch 'development' into mueller/heater-coverity 2021-04-20 16:38:33 +02:00
0038c1dc53 Merge branch 'development' into mueller/health-coverity-fix 2021-04-20 16:38:16 +02:00
1a3bb5bada Merge branch 'development' into mueller/serialiize-element-coverity 2021-04-20 16:38:08 +02:00
0055d34d9a bugfix found by coverity 2021-04-20 16:17:37 +02:00
a2ba3181b9 small coverity tweak 2021-04-20 16:16:35 +02:00
864621ee37 small fix for linux printout 2021-04-20 16:15:30 +02:00
54ff8f9341 heater tweaks + coverity fix 2021-04-20 16:12:50 +02:00
e4efc01e34 Merge pull request 'thermal sensor update' (#402) from mueller/thermal-handler into development
Reviewed-on: fsfw/fsfw#402
2021-04-20 16:10:20 +02:00
c455fc1417 Merge branch 'development' into mueller/thermal-handler 2021-04-20 16:10:14 +02:00
d792679d49 calling empty ctor now (coverity) 2021-04-20 16:09:50 +02:00
38a5e7e618 ctor variable better name 2021-04-20 16:00:01 +02:00
0c342ad7fc minor changes 2021-04-20 15:57:11 +02:00
524e50a6dd comment block corrected 2021-04-20 15:54:44 +02:00
17adb2cc3e Merge pull request 'small improvements for Linux' (#407) from mueller/linux-small-improvements into development
Reviewed-on: fsfw/fsfw#407
2021-04-20 15:46:34 +02:00
7b29583f8f small improvements 2021-04-20 15:32:12 +02:00
1af7870b15 Merge branch 'development' into mueller/thermal-handler 2021-04-20 15:11:19 +02:00
1cbeb54b8d Merge pull request 'Makes linux realtime optional' (#406) from gaisser/fsfw:gaisser_make_linux_realtime_optional into development
Reviewed-on: fsfw/fsfw#406
2021-04-20 15:10:44 +02:00
0ec83afa13 Merge remote-tracking branch 'my_fork/gaisser_make_linux_realtime_optional' into gaisser_make_linux_realtime_optional 2021-04-20 15:06:40 +02:00
153c44601b refixed spelling 2021-04-20 15:04:42 +02:00
e6a8371d4a temperature sensor update 2021-04-20 15:00:59 +02:00
64efb8ec7f temperature sensor update 2021-04-20 14:58:35 +02:00
c8b2b3a038 Merge branch 'mueller/thermal-handler' of https://egit.irs.uni-stuttgart.de/fsfw/fsfw into mueller/thermal-handler 2021-04-20 14:47:18 +02:00
6873d2b847 temp sensor update 2021-04-20 14:46:59 +02:00
91c3692f6d Merge branch 'development' into gaisser_make_linux_realtime_optional 2021-04-20 14:39:56 +02:00
69788e1279 Merge pull request 'Updating TC Distributor modules' (#403) from mueller/tmtcservices-update into development
Reviewed-on: fsfw/fsfw#403
2021-04-20 14:39:07 +02:00
ec69076652 Merge branch 'development' into mueller/tmtcservices-update 2021-04-20 14:38:59 +02:00
a62bda97a0 Merge pull request 'UDP and TCPIP smaller tweaks' (#400) from mueller/udp-ai-passive-opt into development
Reviewed-on: fsfw/fsfw#400
2021-04-20 14:38:16 +02:00
32f0131973 Merge branch 'development' into mueller/udp-ai-passive-opt 2021-04-20 14:38:01 +02:00
9784d5123b Merge branch 'development' into mueller/thermal-handler 2021-04-20 14:37:04 +02:00
ea8d887a6b Merge pull request 'proper MQ implementation' (#401) from mueller/host-osal-vector-mq into development
Reviewed-on: fsfw/fsfw#401
2021-04-20 14:36:47 +02:00
29cebab790 Merge remote-tracking branch 'origin/development' into mueller/udp-ai-passive-opt 2021-04-20 14:18:06 +02:00
03095776f1 Added a comment and corrected a mistake 2021-04-20 13:31:15 +02:00
bad9f67c39 Merge remote-tracking branch 'origin/development' into gaisser_make_linux_realtime_optional 2021-04-20 13:06:11 +02:00
98add88d14 Makes linux realtime optional
Adds new config variable FSFW_USE_REALTIME_FOR_LINUX
2021-04-20 13:01:24 +02:00
e1b595d620 Merge branch 'development' into mueller/tmtcservices-update 2021-04-20 11:38:42 +02:00
39940823d1 Merge branch 'development' into mueller/thermal-handler 2021-04-13 14:44:43 +02:00
4479a2628d Merge branch 'development' into mueller/host-osal-vector-mq 2021-04-13 14:32:18 +02:00
b09119cd8d Merge pull request 'Small patch for CMakeLists file' (#397) from KSat/fsfw:mueller/cmake-lists-add-inc-paths into development
Reviewed-on: fsfw/fsfw#397
2021-04-13 14:31:20 +02:00
10bc568560 Merge branch 'development' into mueller/cmake-lists-add-inc-paths 2021-04-13 14:23:04 +02:00
6e09e29ec2 Merge pull request 'added all coverity fixes' (#398) from KSat/fsfw:mueller/coverity-fixes into development
Reviewed-on: fsfw/fsfw#398
2021-04-13 14:22:53 +02:00
43fb05ac5d Merge branch 'development' into mueller/thermal-handler 2021-04-13 14:02:24 +02:00
e832487081 Merge branch 'development' into mueller/coverity-fixes 2021-04-13 14:02:03 +02:00
01acbaa270 Merge branch 'development' into mueller/cmake-lists-add-inc-paths 2021-04-13 14:01:45 +02:00
a8b5fec725 Merge branch 'development' into mueller/udp-ai-passive-opt 2021-04-13 10:01:14 +02:00
321de4e46b Merge pull request 'bumped version to 1.0.0' (#399) from KSat/fsfw:mueller/version-bump into development
Reviewed-on: fsfw/fsfw#399
2021-04-12 17:04:14 +02:00
2635ec3d56 Merge branch 'development' into mueller/cmake-lists-add-inc-paths 2021-04-12 16:10:03 +02:00
3f7915fe49 Merge branch 'development' into mueller/tmtcservices-update 2021-04-12 16:09:56 +02:00
f87a10891a Merge branch 'development' into mueller/udp-ai-passive-opt 2021-04-12 16:09:42 +02:00
f4ac5c3844 Merge branch 'development' into mueller/version-bump 2021-04-12 16:09:30 +02:00
922f145ffa Merge branch 'development' into mueller/coverity-fixes 2021-04-12 15:28:51 +02:00
9731127eaf Merge pull request 'typo fix' (#396) from KSat/fsfw:mueller/destination-invalid-typo into development
Reviewed-on: fsfw/fsfw#396
2021-04-12 15:28:38 +02:00
5124f314f4 updated distributor modules 2021-04-12 12:50:23 +02:00
4bb078c451 thermal sensor update 2021-04-12 12:40:59 +02:00
547538fbc5 proper MQ implementation 2021-04-12 12:38:56 +02:00
06d34efa74 UDP and TCPIP smaller tweaks
Using AI_PASSIVE now so the UDP server listens to all
addresses (0.0.0.0) instead of just localhost.
Also implemented address print function properly
2021-04-12 12:33:45 +02:00
b786b53c35 added all coverity fixes 2021-04-11 21:54:48 +02:00
e50d0738ab bumped version to 1.0.0 2021-04-11 21:22:58 +02:00
01d0bd6c64 Small patch for CMakeLists file
This adds the additional includes to the interface as well
so libraries linking again fsfw get the additional includes
as well.
2021-04-11 21:20:45 +02:00
5676969fe3 typo fix 2021-04-11 21:13:43 +02:00
b4594e6f43 Merge pull request 'bugfix for RTEMS' (#395) from rtems/hotfix-mq into development
Reviewed-on: fsfw/fsfw#395
2021-04-08 16:31:21 +02:00
6e12f08965 Merge branch 'development' into rtems/hotfix-mq 2021-04-08 16:31:13 +02:00
2dd2d8f133 Merge pull request 'Important bugfix for Linux MQ' (#394) from KSat/fsfw:linux/hotfix-mq into development
Reviewed-on: fsfw/fsfw#394
2021-04-08 16:31:02 +02:00
10c3483fe5 bugfix for RTEMS 2021-04-08 16:20:59 +02:00
23e3f2f34f now fixed properly 2021-04-08 15:39:23 +02:00
6983ddc3e0 super evil bugfix 2021-04-08 15:27:03 +02:00
c234da6f07 Merge pull request 'Linux Fix' (#393) from KSat/fsfw:mueller/linux-fix into development
Reviewed-on: fsfw/fsfw#393
2021-04-06 14:09:59 +02:00
8930be9f32 Merge branch 'development' into mueller/linux-fix 2021-04-06 14:09:24 +02:00
32996338a0 Merge pull request 'CMake update' (#392) from mueller/cmake-update into development
Reviewed-on: fsfw/fsfw#392
2021-04-06 14:09:14 +02:00
2736ebbd19 Merge branch 'development' into mueller/cmake-update 2021-04-06 14:08:06 +02:00
509945c323 Merge remote-tracking branch 'upstream/development' into mueller/master 2021-03-30 01:14:06 +02:00
435c6e6410 bugfix for linux/host 2021-03-30 00:37:10 +02:00
3429918f5e fixed cmakelists for linux 2021-03-30 00:25:22 +02:00
3a75be2683 this version is working 2021-03-27 21:51:04 +01:00
aa9d7b2226 Merge remote-tracking branch 'ksat/mueller/master' into mueller/master 2021-03-27 21:33:22 +01:00
eea482b438 added specific compile definitions 2021-03-27 21:27:46 +01:00
3a90578780 minor bridge improveements 2021-03-27 10:40:38 +01:00
1d818294e4 added option to remove unused code 2021-03-25 18:48:00 +01:00
581832e4f4 added unittest folder 2021-03-25 18:05:18 +01:00
9e559658a7 added way to add additional include paths and libraries 2021-03-25 15:35:05 +01:00
b1c532078e Merge pull request 'OSAL update' (#391) from mueller/update-osal-package into development
Reviewed-on: fsfw/fsfw#391
2021-03-23 15:01:39 +01:00
37ac579f51 Merge branch 'development' into mueller/update-osal-package 2021-03-23 15:01:11 +01:00
aaceac81af updated fixed timeslot task 2021-03-23 14:45:33 +01:00
d781c6fcec name storage abstraction available for linux as well 2021-03-23 14:40:30 +01:00
bdd9889718 pool read guard in scope 2021-03-23 14:28:01 +01:00
a5f44b8580 doc updatedoc updatedd 2021-03-23 14:25:50 +01:00
d1265a55b4 Merge pull request 'UDP Hotfix' (#390) from mueller/udp-hotfix into development
Reviewed-on: fsfw/fsfw#390
2021-03-23 14:21:43 +01:00
b542ed5c03 Merge branch 'development' into mueller/udp-hotfix 2021-03-23 14:20:14 +01:00
8b42132cbe Merge pull request 'Bugfix validity buffer' (#389) from mueller/unit-test-bugfixes into development
Reviewed-on: fsfw/fsfw#389
2021-03-23 14:20:03 +01:00
b1670decf7 Using C++ way of zero initializing struct 2021-03-23 11:35:23 +01:00
1d3d2be853 more doc 2021-03-23 11:33:40 +01:00
d4ab2c6cdb corrected doc 2021-03-23 11:32:35 +01:00
1c021651d7 missing include added 2021-03-23 11:26:44 +01:00
3175883346 oopsie 2021-03-22 15:28:36 +01:00
4d403b40c9 Merge remote-tracking branch 'upstream/mueller/master' into source/develop 2021-03-22 15:24:56 +01:00
f6afa36b1c small tweak 2021-03-22 15:24:25 +01:00
0c77ce4dcf important bugfix 2021-03-22 15:23:47 +01:00
4c11b2f660 Merge remote-tracking branch 'upstream/mueller/master' into source/develop 2021-03-22 15:19:44 +01:00
614d1ccb7c resorted functions 2021-03-21 16:29:04 +01:00
e3c44fd27f implemented deadlien missed print for host 2021-03-21 16:20:13 +01:00
078116c7be generic windows udp bridge working as well 2021-03-21 14:38:28 +01:00
b5a14bb9df deleted old linux code 2021-03-21 13:02:14 +01:00
86577f4b80 fixed for linux 2021-03-21 12:51:28 +01:00
d625642abc created common OSAL stuff to unify UDP code 2021-03-21 00:30:33 +01:00
951eb40e96 relativ include 2021-03-20 13:14:30 +01:00
538dec7062 Merge remote-tracking branch 'upstream/mueller/master' into mueller/master 2021-03-20 12:59:27 +01:00
8f17d6623a removed duplicate include 2021-03-20 12:54:05 +01:00
0585ef9051 Merge remote-tracking branch 'upstream/development' into mueller/hosted-osal-fixes 2021-03-20 12:51:43 +01:00
0da95b75a2 fixed for hosted OSAL 2021-03-20 12:49:15 +01:00
a4ca61d834 bugfix and printout improvement 2021-03-18 00:01:29 +01:00
b41eb518e7 improved internal error reporter 2021-03-17 23:28:01 +01:00
83 changed files with 1825 additions and 1697 deletions

View File

@@ -1,5 +1,13 @@
cmake_minimum_required(VERSION 3.13)
option(FSFW_GENERATE_SECTIONS
"Generate function and data sections. Required to remove unused code" ON
)
if(FSFW_GENERATE_SECTIONS)
option(FSFW_REMOVE_UNUSED_CODE "Remove unused code" ON)
endif()
option(FSFW_WARNING_SHADOW_LOCAL_GCC "Enable -Wshadow=local warning in GCC" ON)
# Options to exclude parts of the FSFW from compilation.
option(FSFW_USE_RMAP "Compile with RMAP" ON)
@@ -26,15 +34,22 @@ if(NOT OS_FSFW)
endif()
set(FSFW_OSAL_DEFINITION FSFW_HOST)
if(${OS_FSFW} STREQUAL host)
set(OS_FSFW_NAME "Host")
elseif(${OS_FSFW} STREQUAL linux)
set(OS_FSFW_NAME "Linux")
set(FSFW_OSAL_DEFINITION FSFW_LINUX)
elseif(${OS_FSFW} STREQUAL freertos)
set(OS_FSFW_NAME "FreeRTOS")
target_link_libraries(${LIB_FSFW_NAME} ${LIB_OS_NAME})
set(FSFW_OSAL_DEFINITION FSFW_FREERTOS)
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
${LIB_OS_NAME}
)
elseif(${OS_FSFW} STREQUAL rtems)
set(OS_FSFW_NAME "RTEMS")
set(FSFW_OSAL_DEFINITION FSFW_RTEMS)
else()
message(WARNING
"Invalid operating system for FSFW specified! Setting to host.."
@@ -43,6 +58,14 @@ else()
set(OS_FSFW "host")
endif()
target_compile_definitions(${LIB_FSFW_NAME} PRIVATE
${FSFW_OSAL_DEFINITION}
)
target_compile_definitions(${LIB_FSFW_NAME} INTERFACE
${FSFW_OSAL_DEFINITION}
)
message(STATUS "Compiling FSFW for the ${OS_FSFW_NAME} operating system.")
add_subdirectory(action)
@@ -88,6 +111,7 @@ add_subdirectory(timemanager)
add_subdirectory(tmstorage)
add_subdirectory(tmtcpacket)
add_subdirectory(tmtcservices)
add_subdirectory(unittest)
# The project CMakeLists file has to set the FSFW_CONFIG_PATH and add it.
# If this is not given, we include the default configuration and emit a warning.
@@ -107,6 +131,21 @@ else()
)
endif()
foreach(INCLUDE_PATH ${FSFW_ADDITIONAL_INC_PATH})
if(IS_ABSOLUTE ${INCLUDE_PATH})
set(CURR_ABS_INC_PATH "${FREERTOS_PATH}")
else()
get_filename_component(CURR_ABS_INC_PATH
${INCLUDE_PATH} REALPATH BASE_DIR ${CMAKE_SOURCE_DIR})
endif()
if(CMAKE_VERBOSE)
message(STATUS "FSFW include path: ${CURR_ABS_INC_PATH}")
endif()
list(APPEND FSFW_ADD_INC_PATHS_ABS ${CURR_ABS_INC_PATH})
endforeach()
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if(NOT DEFINED FSFW_WARNING_FLAGS)
set(FSFW_WARNING_FLAGS
@@ -118,6 +157,19 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
)
endif()
if(FSFW_GENERATE_SECTIONS)
target_compile_options(${LIB_FSFW_NAME} PRIVATE
"-ffunction-sections"
"-fdata-sections"
)
endif()
if(FSFW_REMOVE_UNUSED_CODE)
target_link_options(${LIB_FSFW_NAME} PRIVATE
"Wl,--gc-sections"
)
endif()
if(FSFW_WARNING_SHADOW_LOCAL_GCC)
list(APPEND WARNING_FLAGS "-Wshadow=local")
endif()
@@ -132,6 +184,7 @@ endif()
target_include_directories(${LIB_FSFW_NAME} INTERFACE
${CMAKE_SOURCE_DIR}
${FSFW_CONFIG_PATH_ABSOLUTE}
${FSFW_ADD_INC_PATHS_ABS}
)
# Includes path required to compile FSFW itself as well
@@ -140,9 +193,14 @@ target_include_directories(${LIB_FSFW_NAME} INTERFACE
target_include_directories(${LIB_FSFW_NAME} PRIVATE
${CMAKE_SOURCE_DIR}
${FSFW_CONFIG_PATH_ABSOLUTE}
${FSFW_ADD_INC_PATHS_ABS}
)
target_compile_options(${LIB_FSFW_NAME} PRIVATE
${FSFW_WARNING_FLAGS}
${COMPILER_FLAGS}
)
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
${FSFW_ADDITIONAL_LINK_LIBS}
)

View File

@@ -3,9 +3,9 @@
const char* const FSFW_VERSION_NAME = "ASTP";
#define FSFW_VERSION 0
#define FSFW_VERSION 1
#define FSFW_SUBVERSION 0
#define FSFW_REVISION 1
#define FSFW_REVISION 0

View File

@@ -147,11 +147,6 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
return result;
}
if (result != HasReturnvaluesIF::RETURN_OK) {
ipcStore->deleteData(storeAddress);
return result;
}
/* We don't need to report the objectId, as we receive REQUESTED data before the completion
success message. True aperiodic replies need to be reported with another dedicated message. */
ActionMessage::setDataReply(&reply, replyId, storeAddress);

View File

@@ -17,6 +17,9 @@ SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer,
mutex = MutexFactory::instance()->createMutex();
}
SharedRingBuffer::~SharedRingBuffer() {
MutexFactory::instance()->deleteMutex(mutex);
}
void SharedRingBuffer::setToUseReceiveSizeFIFO(size_t fifoDepth) {
this->fifoDepth = fifoDepth;

View File

@@ -26,6 +26,18 @@ public:
*/
SharedRingBuffer(object_id_t objectId, const size_t size,
bool overwriteOld, size_t maxExcessBytes);
/**
* This constructor takes an external buffer with the specified size.
* @param buffer
* @param size
* @param overwriteOld
* If the ring buffer is overflowing at a write operartion, the oldest data
* will be overwritten.
*/
SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const size_t size,
bool overwriteOld, size_t maxExcessBytes);
virtual~ SharedRingBuffer();
/**
* @brief This function can be used to add an optional FIFO to the class
@@ -37,16 +49,7 @@ public:
*/
void setToUseReceiveSizeFIFO(size_t fifoDepth);
/**
* This constructor takes an external buffer with the specified size.
* @param buffer
* @param size
* @param overwriteOld
* If the ring buffer is overflowing at a write operartion, the oldest data
* will be overwritten.
*/
SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const size_t size,
bool overwriteOld, size_t maxExcessBytes);
/**
* Unless a read-only constant value is read, all operations on the

View File

@@ -7,7 +7,7 @@ HkSwitchHelper::HkSwitchHelper(EventReportingProxyIF* eventProxy) :
}
HkSwitchHelper::~HkSwitchHelper() {
// TODO Auto-generated destructor stub
QueueFactory::instance()->deleteMessageQueue(actionQueue);
}
ReturnValue_t HkSwitchHelper::initialize() {

View File

@@ -64,11 +64,11 @@ ReturnValue_t PoolDataSetBase::read(MutexIF::TimeoutType timeoutType,
}
else {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DataSet::read(): Call made in wrong position. Don't forget to commit"
" member datasets!" << std::endl;
sif::warning << "PoolDataSetBase::read: Call made in wrong position. Don't forget to "
"commit member datasets!" << std::endl;
#else
sif::printError("DataSet::read(): Call made in wrong position. Don't forget to commit"
" member datasets!\n");
sif::printWarning("PoolDataSetBase::read: Call made in wrong position. Don't forget to "
"commit member datasets!\n");
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
result = SET_WAS_ALREADY_READ;
}

View File

@@ -909,27 +909,29 @@ void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
errorPrint = "Unknown error";
}
}
object_id_t objectId = 0xffffffff;
if(owner != nullptr) {
objectId = owner->getObjectId();
}
if(outputType == sif::OutputTypes::OUT_WARNING) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "LocalDataPoolManager::" << functionName
<< ": Object ID 0x" << std::setw(8) << std::setfill('0')
<< std::hex << owner->getObjectId() << " | " << errorPrint
<< std::dec << std::setfill(' ') << std::endl;
sif::warning << "LocalDataPoolManager::" << functionName << ": Object ID 0x" <<
std::setw(8) << std::setfill('0') << std::hex << objectId << " | " << errorPrint <<
std::dec << std::setfill(' ') << std::endl;
#else
sif::printWarning("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n",
functionName, owner->getObjectId(), errorPrint);
functionName, objectId, errorPrint);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
}
else if(outputType == sif::OutputTypes::OUT_ERROR) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "LocalDataPoolManager::" << functionName
<< ": Object ID 0x" << std::setw(8) << std::setfill('0')
<< std::hex << owner->getObjectId() << " | " << errorPrint
<< std::dec << std::setfill(' ') << std::endl;
sif::error << "LocalDataPoolManager::" << functionName << ": Object ID 0x" <<
std::setw(8) << std::setfill('0') << std::hex << objectId << " | " << errorPrint <<
std::dec << std::setfill(' ') << std::endl;
#else
sif::printError("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n",
functionName, owner->getObjectId(), errorPrint);
functionName, objectId, errorPrint);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
}
#endif /* #if FSFW_VERBOSE_LEVEL >= 1 */

View File

@@ -40,6 +40,13 @@
//! 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.
@@ -52,11 +59,12 @@ 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
//! simultaneously. 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;
}
#endif /* CONFIG_FSFWCONFIG_H_ */

View File

@@ -24,6 +24,13 @@
* 1. check logic when active-> checkChildrenStateOn
* 2. transition logic to change the mode -> commandChildren
*
* Important:
*
* The implementation must call registerChild(object_id_t child)
* for all commanded children during initialization.
* The implementation must call the initialization function of the base class.
* (This will call the function in SubsystemBase)
*
*/
class AssemblyBase: public SubsystemBase {
public:
@@ -41,9 +48,6 @@ public:
virtual ~AssemblyBase();
protected:
// SHOULDDO: Change that OVERWRITE_HEALTH may be returned
// (or return internalState directly?)
/**
* Command children to reach [mode,submode] combination
* Can be done by setting #commandsOutstanding correctly,
@@ -68,6 +72,18 @@ protected:
virtual ReturnValue_t checkChildrenStateOn(Mode_t wantedMode,
Submode_t wantedSubmode) = 0;
/**
* Check whether a combination of mode and submode is valid.
*
* Ground Controller like precise return values from HasModesIF.
* So, please return any of them.
*
* @param mode The targeted mode
* @param submode The targeted submmode
* @return Any information why this combination is invalid from HasModesIF
* like HasModesIF::INVALID_SUBMODE.
* On success return HasReturnvaluesIF::RETURN_OK
*/
virtual ReturnValue_t isModeCombinationValid(Mode_t mode,
Submode_t submode) = 0;

View File

@@ -308,11 +308,11 @@ void DeviceHandlerBase::doStateMachine() {
uint32_t currentUptime;
Clock::getUptime(&currentUptime);
if (currentUptime - timeoutStart >= childTransitionDelay) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_VERBOSE_LEVEL >= 1 && FSFW_OBJ_EVENT_TRANSLATION == 0
char printout[60];
sprintf(printout, "Transition timeout (%lu) occured !",
static_cast<unsigned long>(childTransitionDelay));
/* Very common configuration error, so print it */
/* Common configuration error for development, so print it */
printWarningOrError(sif::OutputTypes::OUT_WARNING, "doStateMachine",
RETURN_FAILED, printout);
#endif
@@ -456,6 +456,15 @@ ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceComm
}
}
size_t DeviceHandlerBase::getNextReplyLength(DeviceCommandId_t commandId){
DeviceReplyIter iter = deviceReplyMap.find(commandId);
if(iter != deviceReplyMap.end()) {
return iter->second.replyLen;
}else{
return 0;
}
}
ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceReply,
uint16_t delayCycles, uint16_t maxDelayCycles, bool periodic) {
auto replyIter = deviceReplyMap.find(deviceReply);
@@ -646,16 +655,12 @@ void DeviceHandlerBase::doGetWrite() {
void DeviceHandlerBase::doSendRead() {
ReturnValue_t result;
size_t requestLen = 0;
size_t replyLen = 0;
if(cookieInfo.pendingCommand != deviceCommandMap.end()) {
DeviceReplyIter iter = deviceReplyMap.find(
cookieInfo.pendingCommand->first);
if(iter != deviceReplyMap.end()) {
requestLen = iter->second.replyLen;
}
replyLen = getNextReplyLength(cookieInfo.pendingCommand->first);
}
result = communicationInterface->requestReceiveMessage(comCookie, requestLen);
result = communicationInterface->requestReceiveMessage(comCookie, replyLen);
if (result == RETURN_OK) {
cookieInfo.state = COOKIE_READ_SENT;
@@ -1491,7 +1496,7 @@ void DeviceHandlerBase::printWarningOrError(sif::OutputTypes errorType,
if(errorCode == ObjectManagerIF::CHILD_INIT_FAILED) {
errorPrint = "Initialization error";
}
if(errorCode == HasReturnvaluesIF::RETURN_FAILED) {
else if(errorCode == HasReturnvaluesIF::RETURN_FAILED) {
if(errorType == sif::OutputTypes::OUT_WARNING) {
errorPrint = "Generic Warning";
}
@@ -1503,6 +1508,9 @@ void DeviceHandlerBase::printWarningOrError(sif::OutputTypes errorType,
errorPrint = "Unknown error";
}
}
if(functionName == nullptr) {
functionName = "unknown function";
}
if(errorType == sif::OutputTypes::OUT_WARNING) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
@@ -1511,18 +1519,18 @@ void DeviceHandlerBase::printWarningOrError(sif::OutputTypes errorType,
std::dec << std::setfill(' ') << std::endl;
#else
sif::printWarning("DeviceHandlerBase::%s: Object ID 0x%08x | %s\n",
this->getObjectId(), errorPrint);
functionName, this->getObjectId(), errorPrint);
#endif
}
else if(errorType == sif::OutputTypes::OUT_ERROR) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DeviceHandlerBase::" << functionName << ": Object ID "
sif::error << "DeviceHandlerBase::" << functionName << ": Object ID 0x"
<< std::hex << std::setw(8) << std::setfill('0')
<< this->getObjectId() << " | " << errorPrint << std::dec
<< std::setfill(' ') << std::endl;
#else
sif::printError("DeviceHandlerBase::%s: Object ID 0x%08x | %s\n",
this->getObjectId(), errorPrint);
functionName, this->getObjectId(), errorPrint);
#endif
}

View File

@@ -471,6 +471,7 @@ protected:
ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand,
uint16_t maxDelayCycles, LocalPoolDataSetBase* dataSet = nullptr,
size_t replyLen = 0, bool periodic = false);
/**
* @brief A simple command to add a command to the commandList.
* @param deviceCommand The command to add
@@ -478,6 +479,19 @@ protected:
* - @c RETURN_FAILED else.
*/
ReturnValue_t insertInCommandMap(DeviceCommandId_t deviceCommand);
/**
* @brief This function returns the reply length of the next reply to read.
*
* @param deviceCommand The command which triggered the device reply.
*
* @details The default implementation assumes only one reply is triggered by the command. In
* case the command triggers multiple replies (e.g. one acknowledgment, one data,
* and one execution status reply), this function can be overwritten to get the
* reply length of the next reply to read.
*/
virtual size_t getNextReplyLength(DeviceCommandId_t deviceCommand);
/**
* @brief This is a helper method to facilitate updating entries
* in the reply map.
@@ -953,7 +967,7 @@ protected:
* - NO_REPLY_EXPECTED if there was no reply found. This is not an
* error case as many commands do not expect a reply.
*/
virtual ReturnValue_t enableReplyInReplyMap(DeviceCommandMap::iterator cmd,
virtual ReturnValue_t enableReplyInReplyMap(DeviceCommandMap::iterator command,
uint8_t expectedReplies = 1, bool useAlternateId = false,
DeviceCommandId_t alternateReplyID = 0);

View File

@@ -16,9 +16,9 @@ ReturnValue_t HealthDevice::performOperation(uint8_t opCode) {
CommandMessage command;
ReturnValue_t result = commandQueue->receiveMessage(&command);
if (result == HasReturnvaluesIF::RETURN_OK) {
healthHelper.handleHealthCommand(&command);
result = healthHelper.handleHealthCommand(&command);
}
return HasReturnvaluesIF::RETURN_OK;
return result;
}
ReturnValue_t HealthDevice::initialize() {

View File

@@ -109,6 +109,6 @@ bool EventMessage::isClearedEventMessage() {
return getEvent() == INVALID_EVENT;
}
size_t EventMessage::getMinimumMessageSize() {
size_t EventMessage::getMinimumMessageSize() const {
return EVENT_MESSAGE_SIZE;
}

View File

@@ -45,7 +45,7 @@ public:
protected:
static const Event INVALID_EVENT = 0;
virtual size_t getMinimumMessageSize();
virtual size_t getMinimumMessageSize() const override;
};

View File

@@ -5,15 +5,6 @@
void arrayprinter::print(const uint8_t *data, size_t size, OutputType type,
bool printInfo, size_t maxCharPerLine) {
if(size == 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "Size is zero, nothing to print" << std::endl;
#else
sif::printInfo("Size is zero, nothing to print\n");
#endif
return;
}
#if FSFW_CPP_OSTREAM_ENABLED == 1
if(printInfo) {
sif::info << "Printing data with size " << size << ": " << std::endl;
@@ -60,7 +51,7 @@ void arrayprinter::printHex(const uint8_t *data, size_t size,
#else
// General format: 0x01, 0x02, 0x03 so it is number of chars times 6
// plus line break plus small safety margin.
char printBuffer[(size + 1) * 7 + 1];
char printBuffer[(size + 1) * 7 + 1] = {};
size_t currentPos = 0;
for(size_t i = 0; i < size; i++) {
// To avoid buffer overflows.
@@ -103,7 +94,7 @@ void arrayprinter::printDec(const uint8_t *data, size_t size,
#else
// General format: 32, 243, -12 so it is number of chars times 5
// plus line break plus small safety margin.
char printBuffer[(size + 1) * 5 + 1];
char printBuffer[(size + 1) * 5 + 1] = {};
size_t currentPos = 0;
for(size_t i = 0; i < size; i++) {
// To avoid buffer overflows.

View File

@@ -68,14 +68,30 @@ void HealthTable::printAll(uint8_t* pointer, size_t maxSize) {
MutexGuard(mutex, timeoutType, mutexTimeoutMs);
size_t size = 0;
uint16_t count = healthMap.size();
SerializeAdapter::serialize(&count,
ReturnValue_t result = SerializeAdapter::serialize(&count,
&pointer, &size, maxSize, SerializeIF::Endianness::BIG);
if(result != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "HealthTable::printAll: Serialization of health table failed" << std::endl;
#else
sif::printWarning("HealthTable::printAll: Serialization of health table failed\n");
#endif
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return;
}
for (const auto& health: healthMap) {
SerializeAdapter::serialize(&health.first,
result = SerializeAdapter::serialize(&health.first,
&pointer, &size, maxSize, SerializeIF::Endianness::BIG);
if(result != HasReturnvaluesIF::RETURN_OK) {
return;
}
uint8_t healthValue = health.second;
SerializeAdapter::serialize(&healthValue, &pointer, &size,
result = SerializeAdapter::serialize(&healthValue, &pointer, &size,
maxSize, SerializeIF::Endianness::BIG);
if(result != HasReturnvaluesIF::RETURN_OK) {
return;
}
}
}
@@ -86,7 +102,7 @@ ReturnValue_t HealthTable::iterate(HealthEntry *value, bool reset) {
mapIterator = healthMap.begin();
}
if (mapIterator == healthMap.end()) {
result = HasReturnvaluesIF::RETURN_FAILED;
return HasReturnvaluesIF::RETURN_FAILED;
}
*value = *mapIterator;
mapIterator++;

View File

@@ -3,6 +3,7 @@
#include "../ipc/QueueFactory.h"
#include "../ipc/MutexFactory.h"
#include "../serviceinterface/ServiceInterface.h"
#include "../datapool/PoolReadGuard.h"
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId,
uint32_t messageQueueDepth): SystemObject(setObjectId),
@@ -23,13 +24,17 @@ void InternalErrorReporter::setDiagnosticPrintout(bool enable) {
}
ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
internalErrorDataset.read(timeoutType, timeoutMs);
CommandMessage message;
ReturnValue_t result = commandQueue->receiveMessage(&message);
if(result != MessageQueueIF::EMPTY) {
poolManager.handleHousekeepingMessage(&message);
}
uint32_t newQueueHits = getAndResetQueueHits();
uint32_t newTmHits = getAndResetTmHits();
uint32_t newStoreHits = getAndResetStoreHits();
#if FSFW_VERBOSE_LEVEL == 1
#if FSFW_VERBOSE_LEVEL >= 1
if(diagnosticPrintout) {
if((newQueueHits > 0) or (newTmHits > 0) or (newStoreHits > 0)) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
@@ -48,19 +53,17 @@ ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
}
#endif
{
PoolReadGuard readGuard(&internalErrorDataset);
if(readGuard.getReadResult() == HasReturnvaluesIF::RETURN_OK) {
internalErrorDataset.queueHits.value += newQueueHits;
internalErrorDataset.storeHits.value += newStoreHits;
internalErrorDataset.tmHits.value += newTmHits;
internalErrorDataset.setValidity(true, true);
internalErrorDataset.commit(timeoutType, timeoutMs);
}
}
poolManager.performHkOperation();
CommandMessage message;
ReturnValue_t result = commandQueue->receiveMessage(&message);
if(result != MessageQueueIF::EMPTY) {
poolManager.handleHousekeepingMessage(&message);
}
return HasReturnvaluesIF::RETURN_OK;
}
@@ -155,14 +158,11 @@ MessageQueueId_t InternalErrorReporter::getCommandQueue() const {
ReturnValue_t InternalErrorReporter::initializeLocalDataPool(
localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(errorPoolIds::TM_HITS,
new PoolEntry<uint32_t>());
localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS,
new PoolEntry<uint32_t>());
localDataPoolMap.emplace(errorPoolIds::STORE_HITS,
new PoolEntry<uint32_t>());
poolManager.subscribeForPeriodicPacket(internalErrorSid, false,
getPeriodicOperationFrequency(), true);
localDataPoolMap.emplace(errorPoolIds::TM_HITS, new PoolEntry<uint32_t>());
localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS, new PoolEntry<uint32_t>());
localDataPoolMap.emplace(errorPoolIds::STORE_HITS, new PoolEntry<uint32_t>());
poolManager.subscribeForPeriodicPacket(internalErrorSid, false, getPeriodicOperationFrequency(),
true);
internalErrorDataset.setValidity(true, true);
return HasReturnvaluesIF::RETURN_OK;
}

View File

@@ -17,7 +17,8 @@
* All functions were kept virtual so this class can be extended easily
* to store custom internal errors (e.g. communication interface errors).
*/
class InternalErrorReporter: public SystemObject,
class InternalErrorReporter:
public SystemObject,
public ExecutableObjectIF,
public InternalErrorReporterIF,
public HasLocalDataPoolIF {

View File

@@ -27,7 +27,7 @@ public:
//! Returned if a reply method was called without partner
static const ReturnValue_t NO_REPLY_PARTNER = MAKE_RETURN_CODE(3);
//! Returned if the target destination is invalid.
static constexpr ReturnValue_t DESTINVATION_INVALID = MAKE_RETURN_CODE(4);
static constexpr ReturnValue_t DESTINATION_INVALID = MAKE_RETURN_CODE(4);
virtual ~MessageQueueIF() {}
/**

View File

@@ -86,3 +86,7 @@ size_t MessageQueueMessage::getMaximumMessageSize() const {
return this->MAX_MESSAGE_SIZE;
}
size_t MessageQueueMessage::getMaximumDataSize() const {
return this->MAX_DATA_SIZE;
}

View File

@@ -139,6 +139,7 @@ public:
virtual void setMessageSize(size_t messageSize) override;
virtual size_t getMinimumMessageSize() const override;
virtual size_t getMaximumMessageSize() const override;
virtual size_t getMaximumDataSize() const override;
/**
* @brief This is a debug method that prints the content.

View File

@@ -72,6 +72,7 @@ public:
virtual void setMessageSize(size_t messageSize) = 0;
virtual size_t getMinimumMessageSize() const = 0;
virtual size_t getMaximumMessageSize() const = 0;
virtual size_t getMaximumDataSize() const = 0;
};

View File

@@ -10,10 +10,9 @@ elseif(${OS_FSFW} STREQUAL "host")
if (WIN32)
add_subdirectory(windows)
elseif(UNIX)
target_sources(${LIB_FSFW_NAME}
PUBLIC
linux/TcUnixUdpPollingTask.cpp
linux/TmTcUnixUdpBridge.cpp
# We still need to pull in some Linux specific sources
target_sources(${LIB_FSFW_NAME} PUBLIC
linux/tcpipHelpers.cpp
)
endif ()

View File

@@ -111,7 +111,7 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from,
timeval* to) {
struct tm time_tm;
struct tm time_tm = {};
time_tm.tm_year = from->year - 1900;
time_tm.tm_mon = from->month - 1;

View File

@@ -135,7 +135,7 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
QueueHandle_t destination = nullptr;
if(sendTo == MessageQueueIF::NO_QUEUE or sendTo == 0x00) {
return MessageQueueIF::DESTINVATION_INVALID;
return MessageQueueIF::DESTINATION_INVALID;
}
else {
destination = reinterpret_cast<QueueHandle_t>(sendTo);

View File

@@ -1,3 +1,16 @@
target_sources(${LIB_FSFW_NAME} PRIVATE
if(DEFINED WIN32 OR DEFINED UNIX)
target_sources(${LIB_FSFW_NAME} PRIVATE
tcpipCommon.cpp
)
TcpIpBase.cpp
UdpTcPollingTask.cpp
UdpTmTcBridge.cpp
TcpTmTcServer.cpp
)
endif()
if(WIN32)
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
wsock32
ws2_32
)
endif()

54
osal/common/TcpIpBase.cpp Normal file
View File

@@ -0,0 +1,54 @@
#include "TcpIpBase.h"
#ifdef __unix__
#include <errno.h>
#include <unistd.h>
#endif
TcpIpBase::TcpIpBase() {
}
ReturnValue_t TcpIpBase::initialize() {
#ifdef _WIN32
/* Initiates Winsock DLL. */
WSAData wsaData;
WORD wVersionRequested = MAKEWORD(2, 2);
int err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
/* Tell the user that we could not find a usable Winsock DLL. */
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TmTcWinUdpBridge::TmTcWinUdpBridge: WSAStartup failed with error: " <<
err << std::endl;
#endif
return HasReturnvaluesIF::RETURN_FAILED;
}
#endif
return HasReturnvaluesIF::RETURN_OK;
}
TcpIpBase::~TcpIpBase() {
closeSocket(serverSocket);
#ifdef _WIN32
WSACleanup();
#endif
}
int TcpIpBase::closeSocket(socket_t socket) {
#ifdef _WIN32
return closesocket(socket);
#elif defined(__unix__)
return close(socket);
#endif
}
int TcpIpBase::getLastSocketError() {
#ifdef _WIN32
return WSAGetLastError();
#elif defined(__unix__)
return errno;
#endif
}

50
osal/common/TcpIpBase.h Normal file
View File

@@ -0,0 +1,50 @@
#ifndef FSFW_OSAL_COMMON_TCPIPIF_H_
#define FSFW_OSAL_COMMON_TCPIPIF_H_
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
#ifdef _WIN32
#include <winsock2.h>
#elif defined(__unix__)
#include <sys/socket.h>
#endif
class TcpIpBase {
protected:
#ifdef _WIN32
static constexpr int SHUT_RECV = SD_RECEIVE;
static constexpr int SHUT_SEND = SD_SEND;
static constexpr int SHUT_BOTH = SD_BOTH;
using socket_t = SOCKET;
#elif defined(__unix__)
using socket_t = int;
static constexpr int INVALID_SOCKET = -1;
static constexpr int SOCKET_ERROR = -1;
static constexpr int SHUT_RECV = SHUT_RD;
static constexpr int SHUT_SEND = SHUT_WR;
static constexpr int SHUT_BOTH = SHUT_RDWR;
#endif
TcpIpBase();
virtual ~TcpIpBase();
ReturnValue_t initialize();
int closeSocket(socket_t socket);
int getLastSocketError();
socket_t serverSocket = 0;
};
#endif /* FSFW_OSAL_COMMON_TCPIPIF_H_ */

View File

@@ -1,14 +1,21 @@
#include "TcWinTcpServer.h"
#include "TcpTmTcServer.h"
#include "tcpipHelpers.h"
#include "../../serviceinterface/ServiceInterface.h"
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
const std::string TcWinTcpServer::DEFAULT_TCP_SERVER_PORT = "7301";
const std::string TcWinTcpServer::DEFAULT_TCP_CLIENT_PORT = "7302";
#elif defined(__unix__)
TcWinTcpServer::TcWinTcpServer(object_id_t objectId, object_id_t tmtcUnixUdpBridge,
#include <netdb.h>
#endif
const std::string TcpTmTcServer::DEFAULT_TCP_SERVER_PORT = "7301";
const std::string TcpTmTcServer::DEFAULT_TCP_CLIENT_PORT = "7302";
TcpTmTcServer::TcpTmTcServer(object_id_t objectId, object_id_t tmtcUnixUdpBridge,
std::string customTcpServerPort):
SystemObject(objectId), tcpPort(customTcpServerPort) {
if(tcpPort == "") {
@@ -16,25 +23,18 @@ TcWinTcpServer::TcWinTcpServer(object_id_t objectId, object_id_t tmtcUnixUdpBrid
}
}
ReturnValue_t TcWinTcpServer::initialize() {
ReturnValue_t TcpTmTcServer::initialize() {
using namespace tcpip;
int retval = 0;
struct addrinfo *addrResult = nullptr;
struct addrinfo hints;
/* Initiates Winsock DLL. */
WSAData wsaData;
WORD wVersionRequested = MAKEWORD(2, 2);
int err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
/* Tell the user that we could not find a usable Winsock DLL. */
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TmTcWinUdpBridge::TmTcWinUdpBridge: WSAStartup failed with error: " <<
err << std::endl;
#endif
return HasReturnvaluesIF::RETURN_FAILED;
ReturnValue_t result = TcpIpBase::initialize();
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
ZeroMemory(&hints, sizeof (hints));
int retval = 0;
struct addrinfo *addrResult = nullptr;
struct addrinfo hints = {};
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
@@ -43,7 +43,7 @@ ReturnValue_t TcWinTcpServer::initialize() {
retval = getaddrinfo(nullptr, tcpPort.c_str(), &hints, &addrResult);
if (retval != 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TcWinTcpServer::TcWinTcpServer: Retrieving address info failed!" <<
sif::warning << "TcWinTcpServer::TcpTmTcServer: Retrieving address info failed!" <<
std::endl;
#endif
handleError(Protocol::TCP, ErrorSources::GETADDRINFO_CALL);
@@ -65,11 +65,12 @@ ReturnValue_t TcWinTcpServer::initialize() {
retval = bind(listenerTcpSocket, addrResult->ai_addr, static_cast<int>(addrResult->ai_addrlen));
if(retval == SOCKET_ERROR) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TcWinTcpServer::TcWinTcpServer: Binding socket failed!" <<
sif::warning << "TcWinTcpServer::TcpTmTcServer: Binding socket failed!" <<
std::endl;
#endif
freeaddrinfo(addrResult);
handleError(Protocol::TCP, ErrorSources::BIND_CALL);
return HasReturnvaluesIF::RETURN_FAILED;
}
freeaddrinfo(addrResult);
@@ -77,17 +78,16 @@ ReturnValue_t TcWinTcpServer::initialize() {
}
TcWinTcpServer::~TcWinTcpServer() {
closesocket(listenerTcpSocket);
WSACleanup();
TcpTmTcServer::~TcpTmTcServer() {
closeSocket(listenerTcpSocket);
}
ReturnValue_t TcWinTcpServer::performOperation(uint8_t opCode) {
ReturnValue_t TcpTmTcServer::performOperation(uint8_t opCode) {
using namespace tcpip;
/* If a connection is accepted, the corresponding socket will be assigned to the new socket */
SOCKET clientSocket;
sockaddr_in clientSockAddr;
int connectorSockAddrLen = 0;
socket_t clientSocket = 0;
sockaddr clientSockAddr = {};
socklen_t connectorSockAddrLen = 0;
int retval = 0;
/* Listen for connection requests permanently for lifetime of program */
@@ -98,11 +98,11 @@ ReturnValue_t TcWinTcpServer::performOperation(uint8_t opCode) {
continue;
}
clientSocket = accept(listenerTcpSocket, reinterpret_cast<sockaddr*>(&clientSockAddr),
&connectorSockAddrLen);
clientSocket = accept(listenerTcpSocket, &clientSockAddr, &connectorSockAddrLen);
if(clientSocket == INVALID_SOCKET) {
handleError(Protocol::TCP, ErrorSources::ACCEPT_CALL, 500);
closeSocket(clientSocket);
continue;
};
@@ -110,7 +110,7 @@ ReturnValue_t TcWinTcpServer::performOperation(uint8_t opCode) {
receptionBuffer.size(), 0);
if(retval > 0) {
#if FSFW_TCP_RCV_WIRETAPPING_ENABLED == 1
sif::info << "TcWinTcpServer::performOperation: Received " << retval << " bytes."
sif::info << "TcpTmTcServer::performOperation: Received " << retval << " bytes."
std::endl;
#endif
handleError(Protocol::TCP, ErrorSources::RECV_CALL, 500);
@@ -123,7 +123,8 @@ ReturnValue_t TcWinTcpServer::performOperation(uint8_t opCode) {
}
/* Done, shut down connection */
retval = shutdown(clientSocket, SD_SEND);
retval = shutdown(clientSocket, SHUT_SEND);
closeSocket(clientSocket);
}
return HasReturnvaluesIF::RETURN_OK;
}

View File

@@ -1,9 +1,14 @@
#ifndef FSFW_OSAL_WINDOWS_TCWINTCPSERVER_H_
#define FSFW_OSAL_WINDOWS_TCWINTCPSERVER_H_
#include "TcpIpBase.h"
#include "../../objectmanager/SystemObject.h"
#include "../../tasks/ExecutableObjectIF.h"
#ifdef __unix__
#include <sys/socket.h>
#endif
#include <string>
#include <vector>
@@ -15,17 +20,18 @@
* @details
* Based on: https://docs.microsoft.com/en-us/windows/win32/winsock/complete-server-code
*/
class TcWinTcpServer:
class TcpTmTcServer:
public SystemObject,
public TcpIpBase,
public ExecutableObjectIF {
public:
/* The ports chosen here should not be used by any other process. */
static const std::string DEFAULT_TCP_SERVER_PORT;
static const std::string DEFAULT_TCP_CLIENT_PORT;
TcWinTcpServer(object_id_t objectId, object_id_t tmtcUnixUdpBridge,
TcpTmTcServer(object_id_t objectId, object_id_t tmtcUnixUdpBridge,
std::string customTcpServerPort = "");
virtual~ TcWinTcpServer();
virtual~ TcpTmTcServer();
ReturnValue_t initialize() override;
ReturnValue_t performOperation(uint8_t opCode) override;
@@ -33,8 +39,8 @@ public:
private:
std::string tcpPort;
SOCKET listenerTcpSocket = 0;
struct sockaddr_in tcpAddress;
socket_t listenerTcpSocket = 0;
struct sockaddr tcpAddress;
int tcpAddrLen = sizeof(tcpAddress);
int currentBacklog = 3;

View File

@@ -0,0 +1,180 @@
#include "UdpTcPollingTask.h"
#include "tcpipHelpers.h"
#include "../../globalfunctions/arrayprinter.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#ifdef _WIN32
#include <winsock2.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#endif
//! Debugging preprocessor define.
#define FSFW_UDP_RECV_WIRETAPPING_ENABLED 0
UdpTcPollingTask::UdpTcPollingTask(object_id_t objectId,
object_id_t tmtcUnixUdpBridge, size_t maxRecvSize,
double timeoutSeconds): SystemObject(objectId),
tmtcBridgeId(tmtcUnixUdpBridge) {
if(frameSize > 0) {
this->frameSize = frameSize;
}
else {
this->frameSize = DEFAULT_MAX_RECV_SIZE;
}
/* Set up reception buffer with specified frame size.
For now, it is assumed that only one frame is held in the buffer! */
receptionBuffer.reserve(this->frameSize);
receptionBuffer.resize(this->frameSize);
if(timeoutSeconds == -1) {
receptionTimeout = DEFAULT_TIMEOUT;
}
else {
receptionTimeout = timevalOperations::toTimeval(timeoutSeconds);
}
}
UdpTcPollingTask::~UdpTcPollingTask() {}
ReturnValue_t UdpTcPollingTask::performOperation(uint8_t opCode) {
/* Sender Address is cached here. */
struct sockaddr senderAddress;
socklen_t senderAddressSize = sizeof(senderAddress);
/* Poll for new UDP datagrams in permanent loop. */
while(true) {
int bytesReceived = recvfrom(
this->serverSocket,
reinterpret_cast<char*>(receptionBuffer.data()),
frameSize,
receptionFlags,
&senderAddress,
&senderAddressSize
);
if(bytesReceived == SOCKET_ERROR) {
/* Handle error */
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "UdpTcPollingTask::performOperation: Reception error." << std::endl;
#endif
tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::RECVFROM_CALL, 1000);
continue;
}
#if FSFW_UDP_RECV_WIRETAPPING_ENABLED == 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "UdpTcPollingTask::performOperation: " << bytesReceived <<
" bytes received" << std::endl;
#else
#endif
#endif /* FSFW_UDP_RCV_WIRETAPPING_ENABLED == 1 */
ReturnValue_t result = handleSuccessfullTcRead(bytesReceived);
if(result != HasReturnvaluesIF::RETURN_FAILED) {
}
tmtcBridge->checkAndSetClientAddress(senderAddress);
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t UdpTcPollingTask::handleSuccessfullTcRead(size_t bytesRead) {
store_address_t storeId;
#if FSFW_UDP_RECV_WIRETAPPING_ENABLED == 1
arrayprinter::print(receptionBuffer.data(), bytesRead);
#endif
ReturnValue_t result = tcStore->addData(&storeId, receptionBuffer.data(), bytesRead);
if (result != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning<< "UdpTcPollingTask::transferPusToSoftwareBus: Data storage failed." <<
std::endl;
sif::warning << "Packet size: " << bytesRead << std::endl;
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return HasReturnvaluesIF::RETURN_FAILED;
}
TmTcMessage message(storeId);
result = MessageQueueSenderIF::sendMessage(targetTcDestination, &message);
if (result != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UdpTcPollingTask::handleSuccessfullTcRead: "
" Sending message to queue failed" << std::endl;
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
tcStore->deleteData(storeId);
}
return result;
}
ReturnValue_t UdpTcPollingTask::initialize() {
tcStore = objectManager->get<StorageManagerIF>(objects::TC_STORE);
if (tcStore == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "UdpTcPollingTask::initialize: TC store uninitialized!" << std::endl;
#endif
return ObjectManagerIF::CHILD_INIT_FAILED;
}
tmtcBridge = objectManager->get<UdpTmTcBridge>(tmtcBridgeId);
if(tmtcBridge == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "UdpTcPollingTask::initialize: Invalid TMTC bridge object!" <<
std::endl;
#endif
return ObjectManagerIF::CHILD_INIT_FAILED;
}
ReturnValue_t result = TcpIpBase::initialize();
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t UdpTcPollingTask::initializeAfterTaskCreation() {
/* Initialize the destination after task creation. This ensures
that the destination has already been set in the TMTC bridge. */
targetTcDestination = tmtcBridge->getRequestQueue();
/* The server socket is set up in the bridge intialization. Calling this function here
ensures that it is set up regardless of which class was initialized first */
this->serverSocket = tmtcBridge->serverSocket;
return HasReturnvaluesIF::RETURN_OK;
}
void UdpTcPollingTask::setTimeout(double timeoutSeconds) {
#ifdef _WIN32
DWORD timeoutMs = timeoutSeconds * 1000.0;
int result = setsockopt(serverSocket, SOL_SOCKET, SO_RCVTIMEO,
reinterpret_cast<const char*>(&timeoutMs), sizeof(DWORD));
if(result == -1) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TcWinUdpPollingTask::TcSocketPollingTask: Setting "
"receive timeout failed with " << strerror(errno) << std::endl;
#endif
}
#elif defined(__unix__)
timeval tval;
tval = timevalOperations::toTimeval(timeoutSeconds);
int result = setsockopt(serverSocket, SOL_SOCKET, SO_RCVTIMEO,
&tval, sizeof(receptionTimeout));
if(result == -1) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TcSocketPollingTask::TcSocketPollingTask: Setting "
"receive timeout failed with " << strerror(errno) << std::endl;
#endif
}
#endif
}

View File

@@ -1,7 +1,7 @@
#ifndef FSFW_OSAL_WINDOWS_TCSOCKETPOLLINGTASK_H_
#define FSFW_OSAL_WINDOWS_TCSOCKETPOLLINGTASK_H_
#include "TmTcWinUdpBridge.h"
#include "UdpTmTcBridge.h"
#include "../../objectmanager/SystemObject.h"
#include "../../tasks/ExecutableObjectIF.h"
#include "../../storagemanager/StorageManagerIF.h"
@@ -9,25 +9,22 @@
#include <vector>
/**
* @brief This class can be used to implement the polling of a Unix socket,
* using UDP for now.
* @details
* The task will be blocked while the specified number of bytes has not been
* received, so TC reception is handled inside a separate task.
* This class caches the IP address of the sender. It is assumed there
* is only one sender for now.
* @brief This class should be used with the UdpTmTcBridge to implement a UDP server
* for receiving and sending PUS TMTC.
*/
class TcWinUdpPollingTask: public SystemObject,
class UdpTcPollingTask:
public TcpIpBase,
public SystemObject,
public ExecutableObjectIF {
friend class TmTcWinUdpBridge;
public:
static constexpr size_t DEFAULT_MAX_FRAME_SIZE = 2048;
static constexpr size_t DEFAULT_MAX_RECV_SIZE = 1500;
//! 0.5 default milliseconds timeout for now.
static constexpr timeval DEFAULT_TIMEOUT = {0, 500};
TcWinUdpPollingTask(object_id_t objectId, object_id_t tmtcUnixUdpBridge,
size_t frameSize = 0, double timeoutSeconds = -1);
virtual~ TcWinUdpPollingTask();
UdpTcPollingTask(object_id_t objectId, object_id_t tmtcUnixUdpBridge,
size_t maxRecvSize = 0, double timeoutSeconds = -1);
virtual~ UdpTcPollingTask();
/**
* Turn on optional timeout for UDP polling. In the default mode,
@@ -46,16 +43,12 @@ protected:
private:
//! TMTC bridge is cached.
object_id_t tmtcBridgeId = objects::NO_OBJECT;
TmTcWinUdpBridge* tmtcBridge = nullptr;
UdpTmTcBridge* tmtcBridge = nullptr;
MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE;
//! See: https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-recvfrom
int receptionFlags = 0;
//! Server socket, which is member of TMTC bridge.
//! Will be cached shortly after SW intialization.
SOCKET serverUdpSocket = 0;
std::vector<uint8_t> receptionBuffer;
size_t frameSize = 0;

View File

@@ -1,16 +1,26 @@
#include "TmTcWinUdpBridge.h"
#include "tcpipHelpers.h"
#include <fsfw/serviceinterface/ServiceInterface.h>
#include <fsfw/ipc/MutexGuard.h>
#include <fsfw/osal/common/UdpTmTcBridge.h>
#ifdef _WIN32
#include <ws2tcpip.h>
#elif defined(__unix__)
#include <netdb.h>
#include <arpa/inet.h>
#endif
//! Debugging preprocessor define.
#define FSFW_UDP_SEND_WIRETAPPING_ENABLED 0
const std::string TmTcWinUdpBridge::DEFAULT_UDP_SERVER_PORT = tcpip::DEFAULT_UDP_SERVER_PORT;
const std::string UdpTmTcBridge::DEFAULT_UDP_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
TmTcWinUdpBridge::TmTcWinUdpBridge(object_id_t objectId, object_id_t tcDestination,
UdpTmTcBridge::UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
object_id_t tmStoreId, object_id_t tcStoreId, std::string udpServerPort):
TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) {
if(udpServerPort == "") {
@@ -24,16 +34,18 @@ TmTcWinUdpBridge::TmTcWinUdpBridge(object_id_t objectId, object_id_t tcDestinati
communicationLinkUp = false;
}
ReturnValue_t TmTcWinUdpBridge::initialize() {
ReturnValue_t UdpTmTcBridge::initialize() {
ReturnValue_t result = TmTcBridge::initialize();
if(result != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TmTcWinUdpBridge::initialize: TmTcBridge initialization failed!"
sif::error << "TmTcUdpBridge::initialize: TmTcBridge initialization failed!"
<< std::endl;
#endif
return result;
}
#ifdef _WIN32
/* Initiates Winsock DLL. */
WSAData wsaData;
WORD wVersionRequested = MAKEWORD(2, 2);
@@ -42,25 +54,22 @@ ReturnValue_t TmTcWinUdpBridge::initialize() {
/* Tell the user that we could not find a usable */
/* Winsock DLL. */
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TmTcWinUdpBridge::TmTcWinUdpBridge: WSAStartup failed with error: " <<
sif::error << "TmTcUdpBridge::TmTcUdpBridge: WSAStartup failed with error: " <<
err << std::endl;
#else
sif::printError("TmTcWinUdpBridge::TmTcWinUdpBridge: WSAStartup failed with error: %d\n",
sif::printError("TmTcUdpBridge::TmTcUdpBridge: WSAStartup failed with error: %d\n",
err);
#endif
return HasReturnvaluesIF::RETURN_FAILED;
}
#endif
struct addrinfo *addrResult = nullptr;
struct addrinfo hints;
struct addrinfo hints = {};
ZeroMemory(&hints, sizeof (hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
/* See:
https://docs.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfo
for information about AI_PASSIVE. */
hints.ai_flags = AI_PASSIVE;
/* Set up UDP socket:
@@ -70,7 +79,7 @@ ReturnValue_t TmTcWinUdpBridge::initialize() {
int retval = getaddrinfo(nullptr, udpServerPort.c_str(), &hints, &addrResult);
if (retval != 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TmTcWinUdpBridge::TmTcWinUdpBridge: Retrieving address info failed!" <<
sif::warning << "TmTcUdpBridge::TmTcUdpBridge: Retrieving address info failed!" <<
std::endl;
#endif
return HasReturnvaluesIF::RETURN_FAILED;
@@ -79,7 +88,7 @@ ReturnValue_t TmTcWinUdpBridge::initialize() {
serverSocket = socket(addrResult->ai_family, addrResult->ai_socktype, addrResult->ai_protocol);
if(serverSocket == INVALID_SOCKET) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TmTcWinUdpBridge::TmTcWinUdpBridge: Could not open UDP socket!" <<
sif::warning << "TmTcUdpBridge::TmTcUdpBridge: Could not open UDP socket!" <<
std::endl;
#endif
freeaddrinfo(addrResult);
@@ -87,37 +96,38 @@ ReturnValue_t TmTcWinUdpBridge::initialize() {
return HasReturnvaluesIF::RETURN_FAILED;
}
#if FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1
tcpip::printAddress(addrResult->ai_addr);
#endif
retval = bind(serverSocket, addrResult->ai_addr, static_cast<int>(addrResult->ai_addrlen));
if(retval != 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TmTcWinUdpBridge::TmTcWinUdpBridge: Could not bind "
sif::error << "TmTcUdpBridge::TmTcUdpBridge: Could not bind "
"local port (" << udpServerPort << ") to server socket!" << std::endl;
#endif
freeaddrinfo(addrResult);
tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::BIND_CALL);
return HasReturnvaluesIF::RETURN_FAILED;
}
freeaddrinfo(addrResult);
return HasReturnvaluesIF::RETURN_OK;
}
TmTcWinUdpBridge::~TmTcWinUdpBridge() {
UdpTmTcBridge::~UdpTmTcBridge() {
if(mutex != nullptr) {
MutexFactory::instance()->deleteMutex(mutex);
}
closesocket(serverSocket);
WSACleanup();
}
ReturnValue_t TmTcWinUdpBridge::sendTm(const uint8_t *data, size_t dataLen) {
ReturnValue_t UdpTmTcBridge::sendTm(const uint8_t *data, size_t dataLen) {
int flags = 0;
/* The target address can be set by different threads so this lock ensures thread-safety */
MutexGuard lock(mutex, timeoutType, mutexTimeoutMs);
#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1
char ipAddress [15];
sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET,
&clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl;
#if FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1
tcpip::printAddress(&clientAddress);
#endif
int bytesSent = sendto(
@@ -125,33 +135,31 @@ ReturnValue_t TmTcWinUdpBridge::sendTm(const uint8_t *data, size_t dataLen) {
reinterpret_cast<const char*>(data),
dataLen,
flags,
reinterpret_cast<sockaddr*>(&clientAddress),
&clientAddress,
clientAddressLen
);
if(bytesSent == SOCKET_ERROR) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TmTcWinUdpBridge::sendTm: Send operation failed." << std::endl;
sif::warning << "TmTcUdpBridge::sendTm: Send operation failed." << std::endl;
#endif
tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::SENDTO_CALL);
}
#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1
sif::debug << "TmTcUnixUdpBridge::sendTm: " << bytesSent << " bytes were"
sif::debug << "TmTcUdpBridge::sendTm: " << bytesSent << " bytes were"
" sent." << std::endl;
#endif
return HasReturnvaluesIF::RETURN_OK;
}
void TmTcWinUdpBridge::checkAndSetClientAddress(sockaddr_in& newAddress) {
void UdpTmTcBridge::checkAndSetClientAddress(sockaddr& newAddress) {
/* The target address can be set by different threads so this lock ensures thread-safety */
MutexGuard lock(mutex, timeoutType, mutexTimeoutMs);
#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1
char ipAddress [15];
sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET,
&newAddress.sin_addr.s_addr, ipAddress, 15) << std::endl;
sif::debug << "IP Address Old: " << inet_ntop(AF_INET,
&clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl;
#if FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1
tcpip::printAddress(&newAddress);
tcpip::printAddress(&clientAddress);
#endif
registerCommConnect();
/* Set new IP address to reply to */
@@ -159,7 +167,7 @@ void TmTcWinUdpBridge::checkAndSetClientAddress(sockaddr_in& newAddress) {
clientAddressLen = sizeof(clientAddress);
}
void TmTcWinUdpBridge::setMutexProperties(MutexIF::TimeoutType timeoutType,
void UdpTmTcBridge::setMutexProperties(MutexIF::TimeoutType timeoutType,
dur_millis_t timeoutMs) {
this->timeoutType = timeoutType;
this->mutexTimeoutMs = timeoutMs;

View File

@@ -1,20 +1,36 @@
#ifndef FSFW_OSAL_WINDOWS_TMTCWINUDPBRIDGE_H_
#define FSFW_OSAL_WINDOWS_TMTCWINUDPBRIDGE_H_
#include "TcpIpBase.h"
#include "../../tmtcservices/TmTcBridge.h"
#include <string>
#include <winsock2.h>
#ifdef _WIN32
class TmTcWinUdpBridge: public TmTcBridge {
friend class TcWinUdpPollingTask;
#include <ws2tcpip.h>
#elif defined(__unix__)
#include <sys/socket.h>
#endif
#include <string>
/**
* @brief This class should be used with the UdpTcPollingTask to implement a UDP server
* for receiving and sending PUS TMTC.
*/
class UdpTmTcBridge:
public TmTcBridge,
public TcpIpBase {
friend class UdpTcPollingTask;
public:
/* The ports chosen here should not be used by any other process. */
static const std::string DEFAULT_UDP_SERVER_PORT;
TmTcWinUdpBridge(object_id_t objectId, object_id_t tcDestination,
UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
object_id_t tmStoreId, object_id_t tcStoreId, std::string udpServerPort = "");
virtual~ TmTcWinUdpBridge();
virtual~ UdpTmTcBridge();
/**
* Set properties of internal mutex.
@@ -23,17 +39,16 @@ public:
ReturnValue_t initialize() override;
void checkAndSetClientAddress(sockaddr_in& clientAddress);
void checkAndSetClientAddress(sockaddr& clientAddress);
protected:
virtual ReturnValue_t sendTm(const uint8_t * data, size_t dataLen) override;
private:
SOCKET serverSocket = 0;
std::string udpServerPort;
struct sockaddr_in clientAddress;
int clientAddressLen = 0;
struct sockaddr clientAddress;
socklen_t clientAddressLen = 0;
//! Access to the client address is mutex protected as it is set by another task.
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;

View File

@@ -1,4 +1,9 @@
#include "tcpipCommon.h"
#include <fsfw/serviceinterface/ServiceInterface.h>
#ifdef _WIN32
#include <ws2tcpip.h>
#endif
void tcpip::determineErrorStrings(Protocol protocol, ErrorSources errorSrc, std::string &protStr,
std::string &srcString) {
@@ -34,3 +39,37 @@ void tcpip::determineErrorStrings(Protocol protocol, ErrorSources errorSrc, std:
srcString = "unknown call";
}
}
void tcpip::printAddress(struct sockaddr* addr) {
char ipAddress[INET6_ADDRSTRLEN] = {};
const char* stringPtr = NULL;
switch(addr->sa_family) {
case AF_INET: {
struct sockaddr_in *addrIn = reinterpret_cast<struct sockaddr_in*>(addr);
stringPtr = inet_ntop(AF_INET, &(addrIn->sin_addr), ipAddress, INET_ADDRSTRLEN);
break;
}
case AF_INET6: {
struct sockaddr_in6 *addrIn = reinterpret_cast<struct sockaddr_in6*>(addr);
stringPtr = inet_ntop(AF_INET6, &(addrIn->sin6_addr), ipAddress, INET6_ADDRSTRLEN);
break;
}
}
#if FSFW_CPP_OSTREAM_ENABLED == 1
if(stringPtr == NULL) {
sif::debug << "Could not convert IP address to text representation, error code "
<< errno << std::endl;
}
else {
sif::debug << "IP Address Sender: " << ipAddress << std::endl;
}
#else
if(stringPtr == NULL) {
sif::printDebug("Could not convert IP address to text representation, error code %d\n",
errno);
}
else {
sif::printDebug("IP Address Sender: %s\n", ipAddress);
}
#endif
}

View File

@@ -4,10 +4,16 @@
#include "../../timemanager/clockDefinitions.h"
#include <string>
#ifdef _WIN32
#include <winsock2.h>
#else
#include <netdb.h>
#include <arpa/inet.h>
#endif
namespace tcpip {
const char* const DEFAULT_UDP_SERVER_PORT = "7301";
const char* const DEFAULT_TCP_SERVER_PORT = "7303";
const char* const DEFAULT_SERVER_PORT = "7301";
enum class Protocol {
UDP,
@@ -29,8 +35,8 @@ enum class ErrorSources {
void determineErrorStrings(Protocol protocol, ErrorSources errorSrc, std::string& protStr,
std::string& srcString);
void printAddress(struct sockaddr* addr);
}
#endif /* FSFW_OSAL_COMMON_TCPIPCOMMON_H_ */

View File

@@ -2,7 +2,7 @@
#define FSFW_OSAL_WINDOWS_TCPIPHELPERS_H_
#include "../../timemanager/clockDefinitions.h"
#include "../common/tcpipCommon.h"
#include "tcpipCommon.h"
namespace tcpip {

View File

@@ -10,6 +10,7 @@ target_sources(${LIB_FSFW_NAME}
QueueMapManager.cpp
SemaphoreFactory.cpp
TaskFactory.cpp
taskHelpers.cpp
)
if(UNIX)

View File

@@ -1,10 +1,9 @@
#include "taskHelpers.h"
#include "../../osal/host/FixedTimeslotTask.h"
#include "../../ipc/MutexFactory.h"
#include "../../osal/host/Mutex.h"
#include "../../osal/host/FixedTimeslotTask.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include "../../serviceinterface/ServiceInterface.h"
#include "../../tasks/ExecutableObjectIF.h"
#include <thread>
@@ -12,6 +11,7 @@
#if defined(WIN32)
#include <windows.h>
#include "../windows/winTaskHelpers.h"
#elif defined(LINUX)
#include <pthread.h>
#endif
@@ -24,34 +24,12 @@ FixedTimeslotTask::FixedTimeslotTask(const char *name, TaskPriority setPriority,
// It is propably possible to set task priorities by using the native
// task handles for Windows / Linux
mainThread = std::thread(&FixedTimeslotTask::taskEntryPoint, this, this);
#if defined(WIN32)
/* List of possible priority classes:
* https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/
* nf-processthreadsapi-setpriorityclass
* And respective thread priority numbers:
* https://docs.microsoft.com/en-us/windows/
* win32/procthread/scheduling-priorities */
int result = SetPriorityClass(
reinterpret_cast<HANDLE>(mainThread.native_handle()),
ABOVE_NORMAL_PRIORITY_CLASS);
if(result != 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "FixedTimeslotTask: Windows SetPriorityClass failed with code "
<< GetLastError() << std::endl;
#endif
}
result = SetThreadPriority(
reinterpret_cast<HANDLE>(mainThread.native_handle()),
THREAD_PRIORITY_NORMAL);
if(result != 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "FixedTimeslotTask: Windows SetPriorityClass failed with code "
<< GetLastError() << std::endl;
#endif
}
#elif defined(LINUX)
// TODO: we can just copy and paste the code from the linux OSAL here.
#if defined(_WIN32)
tasks::setTaskPriority(reinterpret_cast<HANDLE>(mainThread.native_handle()), setPriority);
#elif defined(__unix__)
// TODO: We could reuse existing code here.
#endif
tasks::insertTaskName(mainThread.get_id(), taskName);
}
FixedTimeslotTask::~FixedTimeslotTask(void) {
@@ -60,7 +38,6 @@ FixedTimeslotTask::~FixedTimeslotTask(void) {
if(mainThread.joinable()) {
mainThread.join();
}
delete this;
}
void FixedTimeslotTask::taskEntryPoint(void* argument) {
@@ -141,8 +118,11 @@ ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId,
}
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Component " << std::hex << componentId <<
" not found, not adding it to pst" << std::endl;
sif::error << "Component " << std::hex << "0x" << componentId << "not found, "
"not adding it to PST.." << std::dec << std::endl;
#else
sif::printError("Component 0x%08x not found, not adding it to PST..\n",
static_cast<unsigned int>(componentId));
#endif
return HasReturnvaluesIF::RETURN_FAILED;
}

View File

@@ -63,12 +63,9 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
if(messageQueue.empty()) {
return MessageQueueIF::EMPTY;
}
// not sure this will work..
//*message = std::move(messageQueue.front());
MutexGuard mutexLock(queueLock, MutexIF::TimeoutType::WAITING, 20);
MessageQueueMessage* currentMessage = &messageQueue.front();
std::copy(currentMessage->getBuffer(),
currentMessage->getBuffer() + messageSize, message->getBuffer());
std::copy(messageQueue.front().data(), messageQueue.front().data() + messageSize,
message->getBuffer());
messageQueue.pop();
// The last partner is the first uint32_t field in the message
this->lastPartner = message->getSender();
@@ -82,7 +79,7 @@ MessageQueueId_t MessageQueue::getLastPartner() const {
ReturnValue_t MessageQueue::flush(uint32_t* count) {
*count = messageQueue.size();
// Clears the queue.
messageQueue = std::queue<MessageQueueMessage>();
messageQueue = std::queue<std::vector<uint8_t>>();
return HasReturnvaluesIF::RETURN_OK;
}
@@ -108,6 +105,9 @@ bool MessageQueue::isDefaultDestinationSet() const {
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault) {
if(message == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
message->setSender(sentFrom);
if(message->getMessageSize() > message->getMaximumMessageSize()) {
// Actually, this should never happen or an error will be emitted
@@ -130,21 +130,10 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
return HasReturnvaluesIF::RETURN_FAILED;
}
if(targetQueue->messageQueue.size() < targetQueue->messageDepth) {
MutexGuard mutexLock(targetQueue->queueLock,
MutexIF::TimeoutType::WAITING, 20);
// not ideal, works for now though.
MessageQueueMessage* mqmMessage =
dynamic_cast<MessageQueueMessage*>(message);
if(message != nullptr) {
targetQueue->messageQueue.push(*mqmMessage);
}
else {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MessageQueue::sendMessageFromMessageQueue: Message"
"is not MessageQueueMessage!" << std::endl;
#endif
}
MutexGuard mutexLock(targetQueue->queueLock, MutexIF::TimeoutType::WAITING, 20);
targetQueue->messageQueue.push(std::vector<uint8_t>(message->getMaximumMessageSize()));
memcpy(targetQueue->messageQueue.back().data(), message->getBuffer(),
message->getMaximumMessageSize());
}
else {
return MessageQueueIF::FULL;

View File

@@ -212,7 +212,7 @@ protected:
//static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault);
private:
std::queue<MessageQueueMessage> messageQueue;
std::queue<std::vector<uint8_t>> messageQueue;
/**
* @brief The class stores the queue id it got assigned.
* If initialization fails, the queue id is set to zero.

View File

@@ -1,5 +1,6 @@
#include "Mutex.h"
#include "PeriodicTask.h"
#include "taskHelpers.h"
#include "../../ipc/MutexFactory.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
@@ -10,7 +11,8 @@
#if defined(WIN32)
#include <processthreadsapi.h>
#elif defined(LINUX)
#include <fsfw/osal/windows/winTaskHelpers.h>
#elif defined(__unix__)
#include <pthread.h>
#endif
@@ -19,37 +21,15 @@ PeriodicTask::PeriodicTask(const char *name, TaskPriority setPriority,
void (*setDeadlineMissedFunc)()) :
started(false), taskName(name), period(setPeriod),
deadlineMissedFunc(setDeadlineMissedFunc) {
// It is propably possible to set task priorities by using the native
// It is probably possible to set task priorities by using the native
// task handles for Windows / Linux
mainThread = std::thread(&PeriodicTask::taskEntryPoint, this, this);
#if defined(WIN32)
/* List of possible priority classes:
* https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/
* nf-processthreadsapi-setpriorityclass
* And respective thread priority numbers:
* https://docs.microsoft.com/en-us/windows/
* win32/procthread/scheduling-priorities */
int result = SetPriorityClass(
reinterpret_cast<HANDLE>(mainThread.native_handle()),
ABOVE_NORMAL_PRIORITY_CLASS);
if(result != 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PeriodicTask: Windows SetPriorityClass failed with code "
<< GetLastError() << std::endl;
#endif
}
result = SetThreadPriority(
reinterpret_cast<HANDLE>(mainThread.native_handle()),
THREAD_PRIORITY_NORMAL);
if(result != 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PeriodicTask: Windows SetPriorityClass failed with code "
<< GetLastError() << std::endl;
#endif
}
#elif defined(LINUX)
// we can just copy and paste the code from linux here.
#if defined(_WIN32)
tasks::setTaskPriority(reinterpret_cast<HANDLE>(mainThread.native_handle()), setPriority);
#elif defined(__unix__)
// TODO: We could reuse existing code here.
#endif
tasks::insertTaskName(mainThread.get_id(), taskName);
}
PeriodicTask::~PeriodicTask(void) {
@@ -58,7 +38,6 @@ PeriodicTask::~PeriodicTask(void) {
if(mainThread.joinable()) {
mainThread.join();
}
delete this;
}
void PeriodicTask::taskEntryPoint(void* argument) {

View File

@@ -10,6 +10,10 @@ QueueMapManager::QueueMapManager() {
mapLock = MutexFactory::instance()->createMutex();
}
QueueMapManager::~QueueMapManager() {
MutexFactory::instance()->deleteMutex(mapLock);
}
QueueMapManager* QueueMapManager::instance() {
if (mqManagerInstance == nullptr){
mqManagerInstance = new QueueMapManager();

View File

@@ -36,6 +36,8 @@ public:
private:
//! External instantiation is forbidden.
QueueMapManager();
~QueueMapManager();
uint32_t queueCounter = 0;
MutexIF* mapLock;
QueueMap queueMap;

View File

@@ -1,14 +1,16 @@
#include "taskHelpers.h"
#include "../../tasks/TaskFactory.h"
#include "../../osal/host/FixedTimeslotTask.h"
#include "../../osal/host/PeriodicTask.h"
#include "../../tasks/TaskFactory.h"
#include "../../returnvalues/HasReturnvaluesIF.h"
#include "../../tasks/PeriodicTaskIF.h"
#include "../../serviceinterface/ServiceInterface.h"
#include <chrono>
TaskFactory* TaskFactory::factoryInstance = new TaskFactory();
// Will propably not be used for hosted implementation
// Not used for the host implementation for now because C++ thread abstraction is used
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = 0;
TaskFactory::TaskFactory() {
@@ -49,8 +51,12 @@ ReturnValue_t TaskFactory::delayTask(uint32_t delayMs){
}
void TaskFactory::printMissedDeadline() {
/* TODO: Implement */
return;
std::string name = tasks::getTaskName(std::this_thread::get_id());
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TaskFactory::printMissedDeadline: " << name << std::endl;
#else
sif::printWarning("TaskFactory::printMissedDeadline: %s\n", name);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
}

27
osal/host/taskHelpers.cpp Normal file
View File

@@ -0,0 +1,27 @@
#include "taskHelpers.h"
#include <map>
#include <mutex>
std::mutex nameMapLock;
std::map<std::thread::id, std::string> taskNameMap;
ReturnValue_t tasks::insertTaskName(std::thread::id threadId, std::string taskName) {
std::lock_guard<std::mutex> lg(nameMapLock);
auto returnPair = taskNameMap.emplace(threadId, taskName);
if(not returnPair.second) {
return HasReturnvaluesIF::RETURN_FAILED;
}
return HasReturnvaluesIF::RETURN_OK;
}
std::string tasks::getTaskName(std::thread::id threadId) {
std::lock_guard<std::mutex> lg(nameMapLock);
auto resultIter = taskNameMap.find(threadId);
if(resultIter != taskNameMap.end()) {
return resultIter->second;
}
else {
return "Unknown task";
}
}

16
osal/host/taskHelpers.h Normal file
View File

@@ -0,0 +1,16 @@
#ifndef FSFW_OSAL_HOST_TASKHELPERS_H_
#define FSFW_OSAL_HOST_TASKHELPERS_H_
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
#include <thread>
namespace tasks {
ReturnValue_t insertTaskName(std::thread::id threadId, std::string taskName);
std::string getTaskName(std::thread::id threadId);
}
#endif /* FSFW_OSAL_HOST_TASKHELPERS_H_ */

View File

@@ -13,8 +13,6 @@ target_sources(${LIB_FSFW_NAME}
QueueFactory.cpp
SemaphoreFactory.cpp
TaskFactory.cpp
TcUnixUdpPollingTask.cpp
TmTcUnixUdpBridge.cpp
Timer.cpp
tcpipHelpers.cpp
)

View File

@@ -190,13 +190,15 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
return HasReturnvaluesIF::RETURN_FAILED;
}
return HasReturnvaluesIF::RETURN_OK;
}else if(status==0){
}
else if (status==0) {
//Success but no message received
return MessageQueueIF::EMPTY;
} else {
}
else {
//No message was received. Keep lastPartner anyway, I might send
//something later. But still, delete packet content.
memset(message->getData(), 0, message->getMaximumMessageSize());
memset(message->getData(), 0, message->getMaximumDataSize());
switch(errno){
case EAGAIN:
//O_NONBLOCK or MQ_NONBLOCK was set and there are no messages
@@ -371,7 +373,7 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
<<"mq_send to: " << sendTo << " sent from "
<< sentFrom << std::endl;
#endif
return DESTINVATION_INVALID;
return DESTINATION_INVALID;
}
case EINTR:
//The call was interrupted by a signal.

View File

@@ -6,7 +6,7 @@
#include <errno.h>
PosixThread::PosixThread(const char* name_, int priority_, size_t stackSize_):
thread(0),priority(priority_),stackSize(stackSize_) {
thread(0), priority(priority_), stackSize(stackSize_) {
name[0] = '\0';
std::strncat(name, name_, PTHREAD_MAX_NAMELEN - 1);
}
@@ -57,8 +57,10 @@ void PosixThread::suspend() {
void PosixThread::resume(){
/* Signal the thread to start. Makes sense to call kill to start or? ;)
According to POSIX raise(signal) will call pthread_kill(pthread_self(), sig),
but as the call must be done from the thread itself this is not possible here */
*
* According to Posix raise(signal) will call pthread_kill(pthread_self(), sig),
* but as the call must be done from the thread itsself this is not possible here
*/
pthread_kill(thread,SIGUSR1);
}
@@ -66,7 +68,7 @@ bool PosixThread::delayUntil(uint64_t* const prevoiusWakeTime_ms,
const uint64_t delayTime_ms) {
uint64_t nextTimeToWake_ms;
bool shouldDelay = false;
/* Get current Time */
//Get current Time
const uint64_t currentTime_ms = getCurrentMonotonicTimeMs();
/* Generate the tick time at which the task wants to wake. */
nextTimeToWake_ms = (*prevoiusWakeTime_ms) + delayTime_ms;
@@ -100,7 +102,7 @@ bool PosixThread::delayUntil(uint64_t* const prevoiusWakeTime_ms,
PosixThread::sleep(sleepTime * 1000000ull);
return true;
}
/* We are shifting the time in case the deadline was missed like RTEMS */
//We are shifting the time in case the deadline was missed like rtems
(*prevoiusWakeTime_ms) = currentTime_ms;
return false;
@@ -123,10 +125,10 @@ void PosixThread::createTask(void* (*fnc_)(void*), void* arg_) {
#endif
/*
* The attr argument points to a pthread_attr_t structure whose contents
* are used at thread creation time to determine attributes for the new
* thread; this structure is initialized using pthread_attr_init(3) and
* related functions. If attr is NULL, then the thread is created with
* default attributes.
are used at thread creation time to determine attributes for the new
thread; this structure is initialized using pthread_attr_init(3) and
related functions. If attr is NULL, then the thread is created with
default attributes.
*/
pthread_attr_t attributes;
int status = pthread_attr_init(&attributes);
@@ -182,8 +184,11 @@ void PosixThread::createTask(void* (*fnc_)(void*), void* arg_) {
strerror(status) << std::endl;
#endif
}
// TODO FIFO -> This needs root privileges for the process
#ifndef FSFW_USE_REALTIME_FOR_LINUX
#error "Please define FSFW_USE_REALTIME_FOR_LINUX with either 0 or 1"
#endif
#if FSFW_USE_REALTIME_FOR_LINUX == 1
// FIFO -> This needs root privileges for the process
status = pthread_attr_setschedpolicy(&attributes,SCHED_FIFO);
if(status != 0){
#if FSFW_CPP_OSTREAM_ENABLED == 1
@@ -201,7 +206,7 @@ void PosixThread::createTask(void* (*fnc_)(void*), void* arg_) {
strerror(status) << std::endl;
#endif
}
#endif
//Set Signal Mask for suspend until startTask is called
sigset_t waitSignal;
sigemptyset(&waitSignal);
@@ -218,8 +223,16 @@ void PosixThread::createTask(void* (*fnc_)(void*), void* arg_) {
status = pthread_create(&thread,&attributes,fnc_,arg_);
if(status != 0){
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Posix Thread create failed with: " <<
sif::error << "PosixThread::createTask: Failed with: " <<
strerror(status) << std::endl;
sif::error << "For FSFW_USE_REALTIME_FOR_LINUX == 1 make sure to call " <<
"\"all sudo setcap 'cap_sys_nice=eip'\" on the application or set "
"/etc/security/limit.conf" << std::endl;
#else
sif::printError("PosixThread::createTask: Create failed with: %s\n", strerror(status));
sif::printError("For FSFW_USE_REALTIME_FOR_LINUX == 1 make sure to call "
"\"all sudo setcap 'cap_sys_nice=eip'\" on the application or set "
"/etc/security/limit.conf\n");
#endif
}

View File

@@ -1,152 +0,0 @@
#include "TcUnixUdpPollingTask.h"
#include "tcpipHelpers.h"
#include "../../globalfunctions/arrayprinter.h"
#define FSFW_UDP_RCV_WIRETAPPING_ENABLED 0
TcUnixUdpPollingTask::TcUnixUdpPollingTask(object_id_t objectId,
object_id_t tmtcUnixUdpBridge, size_t frameSize,
double timeoutSeconds): SystemObject(objectId),
tmtcBridgeId(tmtcUnixUdpBridge) {
if(frameSize > 0) {
this->frameSize = frameSize;
}
else {
this->frameSize = DEFAULT_MAX_FRAME_SIZE;
}
/* Set up reception buffer with specified frame size.
For now, it is assumed that only one frame is held in the buffer! */
receptionBuffer.reserve(this->frameSize);
receptionBuffer.resize(this->frameSize);
if(timeoutSeconds == -1) {
receptionTimeout = DEFAULT_TIMEOUT;
}
else {
receptionTimeout = timevalOperations::toTimeval(timeoutSeconds);
}
}
TcUnixUdpPollingTask::~TcUnixUdpPollingTask() {}
ReturnValue_t TcUnixUdpPollingTask::performOperation(uint8_t opCode) {
/* Sender Address is cached here. */
struct sockaddr_in senderAddress;
socklen_t senderAddressSize = sizeof(senderAddress);
/* Poll for new UDP datagrams in permanent loop. */
while(true) {
ssize_t bytesReceived = recvfrom(
serverUdpSocket,
receptionBuffer.data(),
frameSize,
receptionFlags,
reinterpret_cast<sockaddr*>(&senderAddress),
&senderAddressSize
);
if(bytesReceived < 0) {
/* Handle error */
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TcSocketPollingTask::performOperation: Reception error." << std::endl;
#endif
tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::RECVFROM_CALL, 500);
continue;
}
#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_RCV_WIRETAPPING_ENABLED == 1
sif::debug << "TcSocketPollingTask::performOperation: " << bytesReceived
<< " bytes received" << std::endl;
#endif
ReturnValue_t result = handleSuccessfullTcRead(bytesReceived);
if(result != HasReturnvaluesIF::RETURN_FAILED) {
}
tmtcBridge->checkAndSetClientAddress(senderAddress);
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t TcUnixUdpPollingTask::handleSuccessfullTcRead(size_t bytesRead) {
store_address_t storeId;
#if FSFW_UDP_RCV_WIRETAPPING_ENABLED == 1
arrayprinter::print(receptionBuffer.data(), bytesRead);
#endif
ReturnValue_t result = tcStore->addData(&storeId, receptionBuffer.data(), bytesRead);
if (result != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TcUnixUdpPollingTask::handleSuccessfullTcRead: Data "
"storage failed" << std::endl;
sif::error << "Packet size: " << bytesRead << std::endl;
#else
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return HasReturnvaluesIF::RETURN_FAILED;
}
TmTcMessage message(storeId);
result = MessageQueueSenderIF::sendMessage(targetTcDestination, &message);
if (result != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TcUnixUdpPollingTask::handleSuccessfullTcRead: Sending message to queue "
"failed" << std::endl;
#else
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
tcStore->deleteData(storeId);
}
return result;
}
ReturnValue_t TcUnixUdpPollingTask::initialize() {
tcStore = objectManager->get<StorageManagerIF>(objects::TC_STORE);
if (tcStore == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TcSerialPollingTask::initialize: TC Store uninitialized!"
<< std::endl;
#endif
return ObjectManagerIF::CHILD_INIT_FAILED;
}
tmtcBridge = objectManager->get<TmTcUnixUdpBridge>(tmtcBridgeId);
if(tmtcBridge == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TcSocketPollingTask::TcSocketPollingTask: Invalid"
" TMTC bridge object!" << std::endl;
#endif
return ObjectManagerIF::CHILD_INIT_FAILED;
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t TcUnixUdpPollingTask::initializeAfterTaskCreation() {
/* Initialize the destination after task creation. This ensures
that the destination has already been set in the TMTC bridge. */
targetTcDestination = tmtcBridge->getRequestQueue();
/* The server socket is set up in the bridge intialization. Calling this function here
ensures that it is set up properly in any case*/
serverUdpSocket = tmtcBridge->serverSocket;
return HasReturnvaluesIF::RETURN_OK;
}
void TcUnixUdpPollingTask::setTimeout(double timeoutSeconds) {
timeval tval;
tval = timevalOperations::toTimeval(timeoutSeconds);
int result = setsockopt(serverUdpSocket, SOL_SOCKET, SO_RCVTIMEO,
&tval, sizeof(receptionTimeout));
if(result == -1) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TcSocketPollingTask::TcSocketPollingTask: Setting "
"receive timeout failed with " << strerror(errno) << std::endl;
#endif
}
}

View File

@@ -1,67 +0,0 @@
#ifndef FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_
#define FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_
#include "../../objectmanager/SystemObject.h"
#include "../../osal/linux/TmTcUnixUdpBridge.h"
#include "../../tasks/ExecutableObjectIF.h"
#include <sys/socket.h>
#include <vector>
/**
* @brief This class can be used to implement the polling of a Unix socket,
* using UDP for now.
* @details
* The task will be blocked while the specified number of bytes has not been
* received, so TC reception is handled inside a separate task.
* This class caches the IP address of the sender. It is assumed there
* is only one sender for now.
*/
class TcUnixUdpPollingTask: public SystemObject,
public ExecutableObjectIF {
friend class TmTcUnixUdpBridge;
public:
static constexpr size_t DEFAULT_MAX_FRAME_SIZE = 2048;
//! 0.5 default milliseconds timeout for now.
static constexpr timeval DEFAULT_TIMEOUT = {.tv_sec = 0, .tv_usec = 500};
TcUnixUdpPollingTask(object_id_t objectId, object_id_t tmtcUnixUdpBridge,
size_t frameSize = 0, double timeoutSeconds = -1);
virtual~ TcUnixUdpPollingTask();
/**
* Turn on optional timeout for UDP polling. In the default mode,
* the receive function will block until a packet is received.
* @param timeoutSeconds
*/
void setTimeout(double timeoutSeconds);
virtual ReturnValue_t performOperation(uint8_t opCode) override;
virtual ReturnValue_t initialize() override;
virtual ReturnValue_t initializeAfterTaskCreation() override;
protected:
StorageManagerIF* tcStore = nullptr;
private:
//! TMTC bridge is cached.
object_id_t tmtcBridgeId = objects::NO_OBJECT;
TmTcUnixUdpBridge* tmtcBridge = nullptr;
MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE;
//! Reception flags: https://linux.die.net/man/2/recvfrom.
int receptionFlags = 0;
//! Server socket, which is member of TMTC bridge and is assigned in
//! constructor
int serverUdpSocket = 0;
std::vector<uint8_t> receptionBuffer;
size_t frameSize = 0;
timeval receptionTimeout;
ReturnValue_t handleSuccessfullTcRead(size_t bytesRead);
};
#endif /* FRAMEWORK_OSAL_LINUX_TCSOCKETPOLLINGTASK_H_ */

View File

@@ -1,157 +0,0 @@
#include "TmTcUnixUdpBridge.h"
#include "tcpipHelpers.h"
#include "../../serviceinterface/ServiceInterface.h"
#include "../../ipc/MutexGuard.h"
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <cstring>
//! Debugging preprocessor define.
#define FSFW_UDP_SEND_WIRETAPPING_ENABLED 0
const std::string TmTcUnixUdpBridge::DEFAULT_UDP_SERVER_PORT = tcpip::DEFAULT_UDP_SERVER_PORT;
TmTcUnixUdpBridge::TmTcUnixUdpBridge(object_id_t objectId, object_id_t tcDestination,
object_id_t tmStoreId, object_id_t tcStoreId, std::string udpServerPort):
TmTcBridge(objectId, tcDestination, tmStoreId, tcStoreId) {
if(udpServerPort == "") {
this->udpServerPort = DEFAULT_UDP_SERVER_PORT;
}
else {
this->udpServerPort = udpServerPort;
}
mutex = MutexFactory::instance()->createMutex();
communicationLinkUp = false;
}
ReturnValue_t TmTcUnixUdpBridge::initialize() {
using namespace tcpip;
ReturnValue_t result = TmTcBridge::initialize();
if(result != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TmTcUnixUdpBridge::initialize: TmTcBridge initialization failed!"
<< std::endl;
#endif
return result;
}
struct addrinfo *addrResult = nullptr;
struct addrinfo hints;
std::memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
hints.ai_flags = AI_PASSIVE;
/* Set up UDP socket:
https://man7.org/linux/man-pages/man3/getaddrinfo.3.html
Passing nullptr as the first parameter and specifying AI_PASSIVE in hints will cause
getaddrinfo to assign the address 0.0.0.0 (any address) */
int retval = getaddrinfo(nullptr, udpServerPort.c_str(), &hints, &addrResult);
if (retval != 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TmTcWinUdpBridge::TmTcWinUdpBridge: Retrieving address info failed!" <<
std::endl;
#endif
return HasReturnvaluesIF::RETURN_FAILED;
}
/* Set up UDP socket: https://man7.org/linux/man-pages/man7/ip.7.html */
serverSocket = socket(addrResult->ai_family, addrResult->ai_socktype, addrResult->ai_protocol);
if(serverSocket < 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TmTcUnixUdpBridge::TmTcUnixUdpBridge: Could not open UDP socket!" <<
std::endl;
#else
sif::printError("TmTcUnixUdpBridge::TmTcUnixUdpBridge: Could not open UDP socket!\n");
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
freeaddrinfo(addrResult);
handleError(Protocol::UDP, ErrorSources::SOCKET_CALL);
return HasReturnvaluesIF::RETURN_FAILED;
}
retval = bind(serverSocket, addrResult->ai_addr, static_cast<int>(addrResult->ai_addrlen));
if(retval != 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TmTcWinUdpBridge::TmTcWinUdpBridge: Could not bind "
"local port (" << udpServerPort << ") to server socket!" << std::endl;
#endif
freeaddrinfo(addrResult);
handleError(Protocol::UDP, ErrorSources::BIND_CALL);
return HasReturnvaluesIF::RETURN_FAILED;
}
return HasReturnvaluesIF::RETURN_OK;
}
TmTcUnixUdpBridge::~TmTcUnixUdpBridge() {
if(mutex != nullptr) {
MutexFactory::instance()->deleteMutex(mutex);
}
close(serverSocket);
}
ReturnValue_t TmTcUnixUdpBridge::sendTm(const uint8_t *data, size_t dataLen) {
int flags = 0;
/* The target address can be set by different threads so this lock ensures thread-safety */
MutexGuard lock(mutex, timeoutType, mutexTimeoutMs);
#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1
char ipAddress [15];
sif::debug << "IP Address Sender: "<<
inet_ntop(AF_INET,&clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl;
#endif
ssize_t bytesSent = sendto(
serverSocket,
data,
dataLen,
flags,
reinterpret_cast<sockaddr*>(&clientAddress),
clientAddressLen
);
if(bytesSent < 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TmTcUnixUdpBridge::sendTm: Send operation failed." << std::endl;
#endif
tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::SENDTO_CALL);
}
#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1
sif::debug << "TmTcUnixUdpBridge::sendTm: " << bytesSent << " bytes were"
" sent." << std::endl;
#endif
return HasReturnvaluesIF::RETURN_OK;
}
void TmTcUnixUdpBridge::checkAndSetClientAddress(sockaddr_in& newAddress) {
/* The target address can be set by different threads so this lock ensures thread-safety */
MutexGuard lock(mutex, timeoutType, mutexTimeoutMs);
#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_RCV_WIRETAPPING_ENABLED == 1
char ipAddress [15];
sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET,
&newAddress.sin_addr.s_addr, ipAddress, 15) << std::endl;
sif::debug << "IP Address Old: " << inet_ntop(AF_INET,
&clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl;
#endif
registerCommConnect();
/* Set new IP address to reply to. */
clientAddress = newAddress;
clientAddressLen = sizeof(clientAddress);
}
void TmTcUnixUdpBridge::setMutexProperties(MutexIF::TimeoutType timeoutType,
dur_millis_t timeoutMs) {
this->timeoutType = timeoutType;
this->mutexTimeoutMs = timeoutMs;
}

View File

@@ -1,49 +0,0 @@
#ifndef FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_
#define FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_
#include "../../tmtcservices/AcceptsTelecommandsIF.h"
#include "../../tmtcservices/TmTcBridge.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/udp.h>
class TmTcUnixUdpBridge:
public TmTcBridge {
friend class TcUnixUdpPollingTask;
public:
/* The ports chosen here should not be used by any other process.
List of used ports on Linux: /etc/services */
static const std::string DEFAULT_UDP_SERVER_PORT;
TmTcUnixUdpBridge(object_id_t objectId, object_id_t tcDestination,
object_id_t tmStoreId, object_id_t tcStoreId,
std::string serverPort = "");
virtual~ TmTcUnixUdpBridge();
/**
* Set properties of internal mutex.
*/
void setMutexProperties(MutexIF::TimeoutType timeoutType, dur_millis_t timeoutMs);
ReturnValue_t initialize() override;
void checkAndSetClientAddress(sockaddr_in& clientAddress);
protected:
virtual ReturnValue_t sendTm(const uint8_t * data, size_t dataLen) override;
private:
int serverSocket = 0;
std::string udpServerPort;
struct sockaddr_in clientAddress;
socklen_t clientAddressLen = 0;
//! Access to the client address is mutex protected as it is set by another task.
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
dur_millis_t mutexTimeoutMs = 20;
MutexIF* mutex;
};
#endif /* FRAMEWORK_OSAL_LINUX_TMTCUNIXUDPBRIDGE_H_ */

View File

@@ -1,5 +1,6 @@
#include "tcpipHelpers.h"
#include "../common/tcpipHelpers.h"
#include "../../serviceinterface/ServiceInterface.h"
#include "../../tasks/TaskFactory.h"
#include <errno.h>
@@ -98,8 +99,8 @@ void tcpip::handleError(Protocol protocol, ErrorSources errorSrc, dur_millis_t s
sif::warning << "tcpip::handleError: " << protocolString << " | " << errorSrcString <<
" | " << infoString << std::endl;
#else
sif::printWarning("tcpip::handleError: %s | %s | %s\n", protocolString,
errorSrcString, infoString);
sif::printWarning("tcpip::handleError: %s | %s | %s\n", protocolString.c_str(),
errorSrcString.c_str(), infoString.c_str());
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
if(sleepDuration > 0) {

View File

@@ -1,14 +0,0 @@
#ifndef FSFW_OSAL_LINUX_TCPIPHELPERS_H_
#define FSFW_OSAL_LINUX_TCPIPHELPERS_H_
#include "../../timemanager/clockDefinitions.h"
#include "../common/tcpipCommon.h"
namespace tcpip {
void handleError(Protocol protocol, ErrorSources errorSrc, dur_millis_t sleepDuration = 0);
}
#endif /* FSFW_OSAL_LINUX_TCPIPHELPERS_H_ */

View File

@@ -61,7 +61,7 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
} else {
//No message was received. Keep lastPartner anyway, I might send something later.
//But still, delete packet content.
memset(message->getData(), 0, message->getMaximumMessageSize());
memset(message->getData(), 0, message->getMaximumDataSize());
}
return convertReturnCode(status);
}

View File

@@ -1,11 +1,4 @@
target_sources(${LIB_FSFW_NAME} PRIVATE
TcWinUdpPollingTask.cpp
TmTcWinUdpBridge.cpp
TcWinTcpServer.cpp
tcpipHelpers.cpp
)
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
wsock32
ws2_32
winTaskHelpers.cpp
)

View File

@@ -1,149 +0,0 @@
#include "TcWinUdpPollingTask.h"
#include "tcpipHelpers.h"
#include "../../globalfunctions/arrayprinter.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include <winsock2.h>
//! Debugging preprocessor define.
#define FSFW_UDP_RCV_WIRETAPPING_ENABLED 0
TcWinUdpPollingTask::TcWinUdpPollingTask(object_id_t objectId,
object_id_t tmtcUnixUdpBridge, size_t frameSize,
double timeoutSeconds): SystemObject(objectId),
tmtcBridgeId(tmtcUnixUdpBridge) {
if(frameSize > 0) {
this->frameSize = frameSize;
}
else {
this->frameSize = DEFAULT_MAX_FRAME_SIZE;
}
/* Set up reception buffer with specified frame size.
For now, it is assumed that only one frame is held in the buffer! */
receptionBuffer.reserve(this->frameSize);
receptionBuffer.resize(this->frameSize);
if(timeoutSeconds == -1) {
receptionTimeout = DEFAULT_TIMEOUT;
}
else {
receptionTimeout = timevalOperations::toTimeval(timeoutSeconds);
}
}
TcWinUdpPollingTask::~TcWinUdpPollingTask() {}
ReturnValue_t TcWinUdpPollingTask::performOperation(uint8_t opCode) {
/* Sender Address is cached here. */
struct sockaddr_in senderAddress;
int senderAddressSize = sizeof(senderAddress);
/* Poll for new UDP datagrams in permanent loop. */
while(true) {
int bytesReceived = recvfrom(
serverUdpSocket,
reinterpret_cast<char*>(receptionBuffer.data()),
frameSize,
receptionFlags,
reinterpret_cast<sockaddr*>(&senderAddress),
&senderAddressSize
);
if(bytesReceived == SOCKET_ERROR) {
/* Handle error */
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TcWinUdpPollingTask::performOperation: Reception error." << std::endl;
#endif
tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::RECVFROM_CALL, 1000);
continue;
}
#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_RCV_WIRETAPPING_ENABLED == 1
sif::debug << "TcWinUdpPollingTask::performOperation: " << bytesReceived <<
" bytes received" << std::endl;
#endif
ReturnValue_t result = handleSuccessfullTcRead(bytesReceived);
if(result != HasReturnvaluesIF::RETURN_FAILED) {
}
tmtcBridge->checkAndSetClientAddress(senderAddress);
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t TcWinUdpPollingTask::handleSuccessfullTcRead(size_t bytesRead) {
store_address_t storeId;
#if FSFW_UDP_RCV_WIRETAPPING_ENABLED == 1
arrayprinter::print(receptionBuffer.data(), bytesRead);
#endif
ReturnValue_t result = tcStore->addData(&storeId, receptionBuffer.data(), bytesRead);
if (result != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning<< "TcWinUdpPollingTask::transferPusToSoftwareBus: Data storage failed." <<
std::endl;
sif::warning << "Packet size: " << bytesRead << std::endl;
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return HasReturnvaluesIF::RETURN_FAILED;
}
TmTcMessage message(storeId);
result = MessageQueueSenderIF::sendMessage(targetTcDestination, &message);
if (result != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TcWinUdpPollingTask::handleSuccessfullTcRead: "
" Sending message to queue failed" << std::endl;
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
tcStore->deleteData(storeId);
}
return result;
}
ReturnValue_t TcWinUdpPollingTask::initialize() {
tcStore = objectManager->get<StorageManagerIF>(objects::TC_STORE);
if (tcStore == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TcWinUdpPollingTask::initialize: TC store uninitialized!" << std::endl;
#endif
return ObjectManagerIF::CHILD_INIT_FAILED;
}
tmtcBridge = objectManager->get<TmTcWinUdpBridge>(tmtcBridgeId);
if(tmtcBridge == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TcWinUdpPollingTask::initialize: Invalid TMTC bridge object!" <<
std::endl;
#endif
return ObjectManagerIF::CHILD_INIT_FAILED;
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t TcWinUdpPollingTask::initializeAfterTaskCreation() {
/* Initialize the destination after task creation. This ensures
that the destination has already been set in the TMTC bridge. */
targetTcDestination = tmtcBridge->getRequestQueue();
/* The server socket is set up in the bridge intialization. Calling this function here
ensures that it is set up properly in any case*/
serverUdpSocket = tmtcBridge->serverSocket;
return HasReturnvaluesIF::RETURN_OK;
}
void TcWinUdpPollingTask::setTimeout(double timeoutSeconds) {
DWORD timeoutMs = timeoutSeconds * 1000.0;
int result = setsockopt(serverUdpSocket, SOL_SOCKET, SO_RCVTIMEO,
reinterpret_cast<const char*>(&timeoutMs), sizeof(DWORD));
if(result == -1) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "TcWinUdpPollingTask::TcSocketPollingTask: Setting "
"receive timeout failed with " << strerror(errno) << std::endl;
#endif
}
}

View File

@@ -1,4 +1,4 @@
#include "tcpipHelpers.h"
#include "../common/tcpipHelpers.h"
#include <FSFWConfig.h>
#include "../../tasks/TaskFactory.h"

View File

@@ -0,0 +1,107 @@
#include <fsfw/osal/windows/winTaskHelpers.h>
#include <mutex>
TaskPriority tasks::makeWinPriority(PriorityClass prioClass, PriorityNumber prioNumber) {
return (static_cast<uint16_t>(prioClass) << 16) | static_cast<uint16_t> (prioNumber);
}
void tasks::getWinPriorityParameters(TaskPriority priority,
DWORD& priorityClass, int& priorityNumber) {
PriorityClass classInternal = static_cast<PriorityClass>(priority >> 16 & 0xff);
PriorityNumber numberInternal = static_cast<PriorityNumber>(priority & 0xff);
switch(classInternal) {
case(CLASS_IDLE): {
priorityClass = IDLE_PRIORITY_CLASS;
break;
}
case(CLASS_BELOW_NORMAL): {
priorityClass = BELOW_NORMAL_PRIORITY_CLASS;
break;
}
case(CLASS_NORMAL): {
priorityClass = NORMAL_PRIORITY_CLASS;
break;
}
case(CLASS_ABOVE_NORMAL): {
priorityClass = ABOVE_NORMAL_PRIORITY_CLASS;
break;
}
case(CLASS_HIGH): {
priorityClass = HIGH_PRIORITY_CLASS;
break;
}
case(CLASS_REALTIME): {
priorityClass = REALTIME_PRIORITY_CLASS;
break;
}
default: {
priorityClass = NORMAL_PRIORITY_CLASS;
}
}
switch(numberInternal) {
case(IDLE): {
priorityNumber = THREAD_PRIORITY_IDLE;
break;
}
case(LOWEST): {
priorityNumber = THREAD_PRIORITY_LOWEST;
break;
}
case(BELOW_NORMAL): {
priorityNumber = THREAD_PRIORITY_BELOW_NORMAL;
break;
}
case(NORMAL): {
priorityNumber = THREAD_PRIORITY_NORMAL;
break;
}
case(ABOVE_NORMAL): {
priorityNumber = THREAD_PRIORITY_ABOVE_NORMAL;
break;
}
case(HIGHEST): {
priorityNumber = THREAD_PRIORITY_HIGHEST;
break;
}
case(CRITICAL): {
priorityNumber = THREAD_PRIORITY_TIME_CRITICAL;
break;
}
default: {
priorityNumber = THREAD_PRIORITY_NORMAL;
}
}
}
ReturnValue_t tasks::setTaskPriority(HANDLE nativeHandle, TaskPriority priority) {
/* List of possible priority classes:
https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setpriorityclass
And respective thread priority numbers:
https://docs.microsoft.com/en-us/windows/win32/procthread/scheduling-priorities
*/
DWORD dwPriorityClass = 0;
int nPriorityNumber = 0;
tasks::getWinPriorityParameters(priority, dwPriorityClass, nPriorityNumber);
int result = SetPriorityClass(
reinterpret_cast<HANDLE>(nativeHandle),
dwPriorityClass);
if(result != 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PeriodicTask: Windows SetPriorityClass failed with code "
<< GetLastError() << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
#endif
}
result = SetThreadPriority(
reinterpret_cast<HANDLE>(nativeHandle),
nPriorityNumber);
if(result != 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PeriodicTask: Windows SetPriorityClass failed with code "
<< GetLastError() << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
#endif
}
return HasReturnvaluesIF::RETURN_OK;
}

View File

@@ -0,0 +1,37 @@
#include "../../tasks/TaskFactory.h"
#include <thread>
#include <map>
#ifdef _WIN32
namespace tasks {
enum PriorityClass: uint16_t {
CLASS_IDLE,
CLASS_BELOW_NORMAL,
CLASS_NORMAL,
CLASS_ABOVE_NORMAL,
CLASS_HIGH,
CLASS_REALTIME
};
enum PriorityNumber: uint16_t {
IDLE,
LOWEST,
BELOW_NORMAL,
NORMAL,
ABOVE_NORMAL,
HIGHEST,
CRITICAL
};
TaskPriority makeWinPriority(PriorityClass prioClass = PriorityClass::CLASS_NORMAL,
PriorityNumber prioNumber = PriorityNumber::NORMAL);
void getWinPriorityParameters(TaskPriority priority, DWORD& priorityClass,
int& priorityNumber);
ReturnValue_t setTaskPriority(HANDLE nativeHandle, TaskPriority priority);
}
#endif

View File

@@ -65,6 +65,9 @@ ReturnValue_t ParameterHelper::handleParameterMessage(CommandMessage *message) {
ParameterWrapper ownerWrapper;
result = owner->getParameter(domain, uniqueIdentifier, &ownerWrapper,
&streamWrapper, linearIndex);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = ownerWrapper.copyFrom(&streamWrapper, linearIndex);
if (result != HasReturnvaluesIF::RETURN_OK) {

View File

@@ -61,8 +61,7 @@ ReturnValue_t CService200ModeCommanding::prepareCommand(
return result;
}
ModeMessage::setModeMessage(dynamic_cast<CommandMessage*>(message),
ModeMessage::CMD_MODE_COMMAND, modeCommandPacket.getMode(),
ModeMessage::setModeMessage(message, ModeMessage::CMD_MODE_COMMAND, modeCommandPacket.getMode(),
modeCommandPacket.getSubmode());
return result;
}

View File

@@ -15,7 +15,9 @@ Service1TelecommandVerification::Service1TelecommandVerification(
tmQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
}
Service1TelecommandVerification::~Service1TelecommandVerification() {}
Service1TelecommandVerification::~Service1TelecommandVerification() {
QueueFactory::instance()->deleteMessageQueue(tmQueue);
}
MessageQueueId_t Service1TelecommandVerification::getVerificationQueue(){
return tmQueue->getId();

View File

@@ -75,9 +75,8 @@ ReturnValue_t Service20ParameterManagement::checkInterfaceAndAcquireMessageQueue
#else
sif::printError("Service20ParameterManagement::checkInterfaceAndAcquire"
"MessageQueue: Can't access object\n");
sif::printError("Object ID: 0x%08x\n", objectId);
sif::printError("Make sure it implements "
"ReceivesParameterMessagesIF!\n");
sif::printError("Object ID: 0x%08x\n", *objectId);
sif::printError("Make sure it implements ReceivesParameterMessagesIF!\n");
#endif
return CommandingServiceBase::INVALID_OBJECT;

View File

@@ -15,7 +15,9 @@ Service5EventReporting::Service5EventReporting(object_id_t objectId,
eventQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
}
Service5EventReporting::~Service5EventReporting(){}
Service5EventReporting::~Service5EventReporting() {
QueueFactory::instance()->deleteMessageQueue(eventQueue);
}
ReturnValue_t Service5EventReporting::performService() {
EventMessage message;

View File

@@ -53,12 +53,14 @@ ReturnValue_t Service8FunctionManagement::checkInterfaceAndAcquireMessageQueue(
ReturnValue_t Service8FunctionManagement::prepareCommand(
CommandMessage* message, uint8_t subservice, const uint8_t* tcData,
size_t tcDataLen, uint32_t* state, object_id_t objectId) {
return prepareDirectCommand(dynamic_cast<CommandMessage*>(message),
tcData, tcDataLen);
return prepareDirectCommand(message, tcData, tcDataLen);
}
ReturnValue_t Service8FunctionManagement::prepareDirectCommand(
CommandMessage *message, const uint8_t *tcData, size_t tcDataLen) {
if(message == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
if(tcDataLen < sizeof(object_id_t) + sizeof(ActionId_t)) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "Service8FunctionManagement::prepareDirectCommand:"

View File

@@ -43,8 +43,8 @@ public:
private:
DirectCommand(const DirectCommand &command);
object_id_t objectId;
ActionId_t actionId;
object_id_t objectId = 0;
ActionId_t actionId = 0;
uint32_t parametersSize; //!< [EXPORT] : [IGNORE]
const uint8_t * parameterBuffer; //!< [EXPORT] : [MAXSIZE] 65535 Bytes

View File

@@ -25,7 +25,7 @@ public:
}
SerializeElement() :
LinkedElement<SerializeIF>(this) {
LinkedElement<SerializeIF>(this), entry() {
}
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,

View File

@@ -5,8 +5,7 @@
SubsystemBase::SubsystemBase(object_id_t setObjectId, object_id_t parent,
Mode_t initialMode, uint16_t commandQueueDepth) :
SystemObject(setObjectId), mode(initialMode), submode(SUBMODE_NONE),
childrenChangedMode(false),
SystemObject(setObjectId), mode(initialMode),
commandQueue(QueueFactory::instance()->createMessageQueue(
commandQueueDepth, CommandMessage::MAX_MESSAGE_SIZE)),
healthHelper(this, setObjectId), modeHelper(this), parentId(parent) {
@@ -167,16 +166,16 @@ MessageQueueId_t SubsystemBase::getCommandQueue() const {
}
ReturnValue_t SubsystemBase::initialize() {
MessageQueueId_t parentQueue = 0;
MessageQueueId_t parentQueue = MessageQueueIF::NO_QUEUE;
ReturnValue_t result = SystemObject::initialize();
if (result != RETURN_OK) {
return result;
}
if (parentId != 0) {
if (parentId != objects::NO_OBJECT) {
SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId);
if (parent == NULL) {
if (parent == nullptr) {
return RETURN_FAILED;
}
parentQueue = parent->getCommandQueue();

View File

@@ -37,6 +37,17 @@ public:
virtual MessageQueueId_t getCommandQueue() const override;
/**
* Function to register the child objects.
* Performs a checks if the child does implement HasHealthIF and/or HasModesIF
*
* Also adds them to the internal childrenMap.
*
* @param objectId
* @return RETURN_OK if successful
* CHILD_DOESNT_HAVE_MODES if Child is no HasHealthIF and no HasModesIF
* COULD_NOT_INSERT_CHILD If the Child could not be added to the ChildrenMap
*/
ReturnValue_t registerChild(object_id_t objectId);
virtual ReturnValue_t initialize() override;
@@ -56,9 +67,9 @@ protected:
Mode_t mode;
Submode_t submode;
Submode_t submode = SUBMODE_NONE;
bool childrenChangedMode;
bool childrenChangedMode = false;
/**
* Always check this against <=0, so you are robust against too many replies

View File

@@ -22,9 +22,26 @@ public:
/**
* Creates a new periodic task and returns the interface pointer.
* @param name_ Name of the task
* @param taskPriority_ Priority of the task
* @param taskPriority_
* Priority of the task. This value might have different ranges for the various OSALs.
* - Linux Value ranging from 0 to 99 with 99 being the highest value.
* - Host For Windows, the value can be retrieved by using the #tasks::makeWinPriority
* function. For Linux, same priority system as specified above. MacOS not tested
* yet
* - FreeRTOS Value depends on the FreeRTOS configuration, higher number means higher priority
* - RTEMS Values ranging from 0 to 99 with 99 being the highest value.
*
* @param stackSize_ Stack Size of the task
* This value might have different recommended ranges for the various OSALs.
* - Linux Lowest limit is the PeriodicTaskIF::MINIMUM_STACK_SIZE value
* - Host Value is ignored for now because the C++ threading abstraction layer is used.
* - FreeRTOS Stack size in bytes. It is recommended to specify at least 1kB of stack for
* FSFW tasks, but the lowest possible size is specified in the
* FreeRTOSConfig.h file.
* - RTEMS Lowest limit is specified the PeriodicTaskIF::MINIMUM_STACK_SIZE value.
*
* @param period_ Period of the task
*
* @param deadLineMissedFunction_ Function to be called if a deadline was missed
* @return PeriodicTaskIF* Pointer to the newly created Task
*/
@@ -34,7 +51,8 @@ public:
TaskDeadlineMissedFunction deadLineMissedFunction_);
/**
*
* The meaning for the variables for fixed timeslot tasks is the same as for periodic tasks.
* See #createPeriodicTask documentation.
* @param name_ Name of the task
* @param taskPriority_ Priority of the task
* @param stackSize_ Stack Size of the task

View File

@@ -2,7 +2,7 @@
#define FRAMEWORK_TASKS_TYPEDEF_H_
typedef const char* TaskName;
typedef uint8_t TaskPriority;
typedef uint32_t TaskPriority;
typedef size_t TaskStackSize;
typedef double TaskPeriod;
typedef void (*TaskDeadlineMissedFunction)();

View File

@@ -1,8 +1,10 @@
#include "CCSDSDistributor.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../serviceinterface/ServiceInterface.h"
#include "../tmtcpacket/SpacePacketBase.h"
#define CCSDS_DISTRIBUTOR_DEBUGGING 0
CCSDSDistributor::CCSDSDistributor(uint16_t setDefaultApid,
object_id_t setObjectId):
TcDistributor(setObjectId), defaultApid( setDefaultApid ) {
@@ -11,26 +13,36 @@ CCSDSDistributor::CCSDSDistributor(uint16_t setDefaultApid,
CCSDSDistributor::~CCSDSDistributor() {}
TcDistributor::TcMqMapIter CCSDSDistributor::selectDestination() {
#if CCSDS_DISTRIBUTOR_DEBUGGING == 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
// sif::debug << "CCSDSDistributor::selectDestination received: " <<
// this->currentMessage.getStorageId().pool_index << ", " <<
// this->currentMessage.getStorageId().packet_index << std::endl;
sif::debug << "CCSDSDistributor::selectDestination received: " <<
this->currentMessage.getStorageId().poolIndex << ", " <<
this->currentMessage.getStorageId().packetIndex << std::endl;
#else
sif::printDebug("CCSDSDistributor::selectDestination received: %d, %d\n",
currentMessage.getStorageId().poolIndex, currentMessage.getStorageId().packetIndex);
#endif
#endif
const uint8_t* packet = nullptr;
size_t size = 0;
ReturnValue_t result = this->tcStore->getData(currentMessage.getStorageId(),
&packet, &size );
if(result != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "CCSDSDistributor::selectDestination: Getting data from"
" store failed!" << std::endl;
#else
sif::printError("CCSDSDistributor::selectDestination: Getting data from"
" store failed!\n");
#endif
#endif
}
SpacePacketBase currentPacket(packet);
#if FSFW_CPP_OSTREAM_ENABLED == 1
// sif:: info << "CCSDSDistributor::selectDestination has packet with APID "
// << std::hex << currentPacket.getAPID() << std::dec << std::endl;
#if FSFW_CPP_OSTREAM_ENABLED == 1 && CCSDS_DISTRIBUTOR_DEBUGGING == 1
sif::info << "CCSDSDistributor::selectDestination has packet with APID " << std::hex <<
currentPacket.getAPID() << std::dec << std::endl;
#endif
TcMqMapIter position = this->queueMap.find(currentPacket.getAPID());
if ( position != this->queueMap.end() ) {
@@ -76,9 +88,14 @@ ReturnValue_t CCSDSDistributor::initialize() {
ReturnValue_t status = this->TcDistributor::initialize();
this->tcStore = objectManager->get<StorageManagerIF>( objects::TC_STORE );
if (this->tcStore == nullptr) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "CCSDSDistributor::initialize: Could not initialize"
" TC store!" << std::endl;
#else
sif::printError("CCSDSDistributor::initialize: Could not initialize"
" TC store!\n");
#endif
#endif
status = RETURN_FAILED;
}

View File

@@ -1,10 +1,12 @@
#include "CCSDSDistributorIF.h"
#include "PUSDistributor.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../serviceinterface/ServiceInterface.h"
#include "../tmtcpacket/pus/TcPacketStored.h"
#include "../tmtcservices/PusVerificationReport.h"
#define PUS_DISTRIBUTOR_DEBUGGING 0
PUSDistributor::PUSDistributor(uint16_t setApid, object_id_t setObjectId,
object_id_t setPacketSource) :
TcDistributor(setObjectId), checker(setApid), verifyChannel(),
@@ -13,10 +15,10 @@ PUSDistributor::PUSDistributor(uint16_t setApid, object_id_t setObjectId,
PUSDistributor::~PUSDistributor() {}
PUSDistributor::TcMqMapIter PUSDistributor::selectDestination() {
#if FSFW_CPP_OSTREAM_ENABLED == 1
// sif:: debug << "PUSDistributor::handlePacket received: "
// << this->current_packet_id.store_index << ", "
// << this->current_packet_id.packet_index << std::endl;
#if FSFW_CPP_OSTREAM_ENABLED == 1 && PUS_DISTRIBUTOR_DEBUGGING == 1
store_address_t storeId = this->currentMessage.getStorageId());
sif:: debug << "PUSDistributor::handlePacket received: " << storeId.poolIndex << ", " <<
storeId.packetIndex << std::endl;
#endif
TcMqMapIter queueMapIt = this->queueMap.end();
if(this->currentPacket == nullptr) {
@@ -25,15 +27,17 @@ PUSDistributor::TcMqMapIter PUSDistributor::selectDestination() {
this->currentPacket->setStoreAddress(this->currentMessage.getStorageId());
if (currentPacket->getWholeData() != nullptr) {
tcStatus = checker.checkPacket(currentPacket);
#ifdef DEBUG
if(tcStatus != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "PUSDistributor::handlePacket: Packet format "
<< "invalid, code "<< static_cast<int>(tcStatus)
<< std::endl;
sif::debug << "PUSDistributor::handlePacket: Packet format invalid, code " <<
static_cast<int>(tcStatus) << std::endl;
#else
sif::printDebug("PUSDistributor::handlePacket: Packet format invalid, code %d\n",
static_cast<int>(tcStatus));
#endif
#endif
}
#endif
uint32_t queue_id = currentPacket->getService();
queueMapIt = this->queueMap.find(queue_id);
}
@@ -43,11 +47,12 @@ PUSDistributor::TcMqMapIter PUSDistributor::selectDestination() {
if (queueMapIt == this->queueMap.end()) {
tcStatus = DESTINATION_NOT_FOUND;
#ifdef DEBUG
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "PUSDistributor::handlePacket: Destination not found, "
<< "code "<< static_cast<int>(tcStatus) << std::endl;
#endif
sif::debug << "PUSDistributor::handlePacket: Destination not found" << std::endl;
#else
sif::printDebug("PUSDistributor::handlePacket: Destination not found\n");
#endif /* !FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif
}
@@ -63,15 +68,23 @@ PUSDistributor::TcMqMapIter PUSDistributor::selectDestination() {
ReturnValue_t PUSDistributor::registerService(AcceptsTelecommandsIF* service) {
uint16_t serviceId = service->getIdentifier();
#if PUS_DISTRIBUTOR_DEBUGGING == 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
// sif::info << "Service ID: " << (int)serviceId << std::endl;
sif::info << "Service ID: " << static_cast<int>(serviceId) << std::endl;
#else
sif::printInfo("Service ID: %d\n", static_cast<int>(serviceId));
#endif
#endif
MessageQueueId_t queue = service->getRequestQueue();
auto returnPair = queueMap.emplace(serviceId, queue);
if (not returnPair.second) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PUSDistributor::registerService: Service ID already"
" exists in map." << std::endl;
" exists in map" << std::endl;
#else
sif::printError("PUSDistributor::registerService: Service ID already exists in map\n");
#endif
#endif
return SERVICE_ID_ALREADY_EXISTS;
}
@@ -115,9 +128,11 @@ ReturnValue_t PUSDistributor::initialize() {
objectManager->get<CCSDSDistributorIF>(packetSource);
if (ccsdsDistributor == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PUSDistributor::initialize: Packet source invalid."
<< " Make sure it exists and implements CCSDSDistributorIF!"
<< std::endl;
sif::error << "PUSDistributor::initialize: Packet source invalid" << std::endl;
sif::error << " Make sure it exists and implements CCSDSDistributorIF!" << std::endl;
#else
sif::printError("PUSDistributor::initialize: Packet source invalid\n");
sif::printError("Make sure it exists and implements CCSDSDistributorIF\n");
#endif
return RETURN_FAILED;
}

View File

@@ -1,15 +1,13 @@
#include "../devicehandlers/DeviceHandlerFailureIsolation.h"
#include "Heater.h"
#include "../devicehandlers/DeviceHandlerFailureIsolation.h"
#include "../power/Fuse.h"
#include "../ipc/QueueFactory.h"
Heater::Heater(uint32_t objectId, uint8_t switch0, uint8_t switch1) :
HealthDevice(objectId, 0), internalState(STATE_OFF), powerSwitcher(
NULL), pcduQueueId(0), switch0(switch0), switch1(switch1), wasOn(
false), timedOut(false), reactedToBeingFaulty(false), passive(
false), eventQueue(NULL), heaterOnCountdown(10800000)/*about two orbits*/, parameterHelper(
this), lastAction(CLEAR) {
HealthDevice(objectId, 0), internalState(STATE_OFF), switch0(switch0), switch1(switch1),
heaterOnCountdown(10800000)/*about two orbits*/,
parameterHelper(this) {
eventQueue = QueueFactory::instance()->createMessageQueue();
}
@@ -226,7 +224,6 @@ void Heater::setSwitch(uint8_t number, ReturnValue_t state,
triggerEvent(HEATER_STAYED_ON);
}
}
//SHOULDDO MiniOps during switch timeout leads to a faulty switch
}
}
}
@@ -286,7 +283,10 @@ void Heater::handleQueue() {
if (result == HasReturnvaluesIF::RETURN_OK) {
return;
}
parameterHelper.handleParameterMessage(&command);
result = parameterHelper.handleParameterMessage(&command);
if (result == HasReturnvaluesIF::RETURN_OK) {
return;
}
}
}
@@ -316,7 +316,9 @@ void Heater::handleEventQueue() {
switch (event.getEvent()) {
case Fuse::FUSE_WENT_OFF:
case HEATER_STAYED_OFF:
case HEATER_STAYED_ON://Setting it faulty does not help, but we need to reach a stable state and can check for being faulty before throwing this event again.
// HEATER_STAYED_ON is a setting if faulty does not help, but we need to reach a stable state and can check
// for being faulty before throwing this event again.
case HEATER_STAYED_ON:
if (healthHelper.healthTable->isCommandable(getObjectId())) {
healthHelper.setHealth(HasHealthIF::FAULTY);
internalState = STATE_FAULTY;

View File

@@ -1,13 +1,13 @@
#ifndef FRAMEWORK_THERMAL_HEATER_H_
#define FRAMEWORK_THERMAL_HEATER_H_
#ifndef FSFW_THERMAL_HEATER_H_
#define FSFW_THERMAL_HEATER_H_
#include "../devicehandlers/HealthDevice.h"
#include "../parameters/ParameterHelper.h"
#include "../power/PowerSwitchIF.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../timemanager/Countdown.h"
#include <stdint.h>
//class RedundantHeater;
#include <cstdint>
class Heater: public HealthDevice, public ReceivesParameterMessagesIF {
friend class RedundantHeater;
@@ -47,35 +47,38 @@ protected:
STATE_PASSIVE,
STATE_WAIT_FOR_SWITCHES_ON,
STATE_WAIT_FOR_SWITCHES_OFF,
STATE_WAIT_FOR_FDIR, //used to avoid doing anything until fdir decided what to do
STATE_WAIT_FOR_FDIR, // Used to avoid doing anything until fdir decided what to do
STATE_FAULTY,
STATE_WAIT, //used when waiting for system to recover from miniops
STATE_EXTERNAL_CONTROL //entered when under external control and a fdir reaction would be triggered. This is useful when leaving external control into an unknown state
//if no fdir reaction is triggered under external control the state is still ok and no need for any special treatment is needed
STATE_WAIT, // Used when waiting for system to recover from miniops
// Entered when under external control and a fdir reaction would be triggered.
// This is useful when leaving external control into an unknown state
STATE_EXTERNAL_CONTROL
// If no fdir reaction is triggered under external control the state is still ok and
// no need for any special treatment is needed
} internalState;
PowerSwitchIF *powerSwitcher;
MessageQueueId_t pcduQueueId;
PowerSwitchIF *powerSwitcher = nullptr;
MessageQueueId_t pcduQueueId = MessageQueueIF::NO_QUEUE;
uint8_t switch0;
uint8_t switch1;
bool wasOn;
bool wasOn = false;
bool timedOut;
bool timedOut = false;
bool reactedToBeingFaulty;
bool reactedToBeingFaulty = false;
bool passive;
bool passive = false;
MessageQueueIF* eventQueue;
MessageQueueIF* eventQueue = nullptr;
Countdown heaterOnCountdown;
Countdown switchCountdown;
ParameterHelper parameterHelper;
enum Action {
SET, CLEAR
} lastAction;
} lastAction = CLEAR;
void doAction(Action action);
@@ -87,4 +90,4 @@ protected:
void handleEventQueue();
};
#endif /* FRAMEWORK_THERMAL_HEATER_H_ */
#endif /* FSFW_THERMAL_HEATER_H_ */

View File

@@ -1,11 +1,14 @@
#ifndef TEMPERATURESENSOR_H_
#define TEMPERATURESENSOR_H_
#ifndef FSFW_THERMAL_TEMPERATURESENSOR_H_
#define FSFW_THERMAL_TEMPERATURESENSOR_H_
#include "../thermal/AbstractTemperatureSensor.h"
#include "../datapoolglob/GlobalDataSet.h"
#include "../datapoolglob/GlobalPoolVariable.h"
#include "tcsDefinitions.h"
#include "AbstractTemperatureSensor.h"
#include "../datapoollocal/LocalPoolDataSetBase.h"
#include "../datapoollocal/LocalPoolVariable.h"
#include "../monitoring/LimitMonitor.h"
/**
* @brief This building block handles non-linear value conversion and
* range checks for analog temperature sensors.
@@ -58,26 +61,24 @@ public:
/**
* Instantiate Temperature Sensor Object.
* @param setObjectid objectId of the sensor object
* @param inputValue Input value which is converted to a temperature
* @param poolVariable Pool Variable to store the temperature value
* @param inputTemperature Pointer to a raw input value which is converted to an floating
* point C output temperature
* @param outputGpid Global Pool ID of the output value
* @param vectorIndex Vector Index for the sensor monitor
* @param parameters Calculation parameters, temperature limits, gradient limit
* @param datapoolId Datapool ID of the output temperature
* @param outputSet Output dataset for the output temperature to fetch it with read()
* @param thermalModule respective thermal module, if it has one
* @param thermalModule Respective thermal module, if it has one
*/
TemperatureSensor(object_id_t setObjectid,
inputType *inputValue, PoolVariableIF *poolVariable,
uint8_t vectorIndex, uint32_t datapoolId, Parameters parameters = {0, 0, 0, 0, 0, 0},
GlobDataSet *outputSet = NULL, ThermalModuleIF *thermalModule = NULL) :
TemperatureSensor(object_id_t setObjectid,lp_var_t<limitType>* inputTemperature,
gp_id_t outputGpid, uint8_t vectorIndex, Parameters parameters = {0, 0, 0, 0, 0, 0},
LocalPoolDataSetBase *outputSet = nullptr, ThermalModuleIF *thermalModule = nullptr) :
AbstractTemperatureSensor(setObjectid, thermalModule), parameters(parameters),
inputValue(inputValue), poolVariable(poolVariable),
outputTemperature(datapoolId, outputSet, PoolVariableIF::VAR_WRITE),
sensorMonitor(setObjectid, DOMAIN_ID_SENSOR,
GlobalDataPool::poolIdAndPositionToPid(poolVariable->getDataPoolId(), vectorIndex),
inputTemperature(inputTemperature),
outputTemperature(outputGpid, outputSet, PoolVariableIF::VAR_WRITE),
sensorMonitor(setObjectid, DOMAIN_ID_SENSOR, outputGpid,
DEFAULT_CONFIRMATION_COUNT, parameters.lowerLimit, parameters.upperLimit,
TEMP_SENSOR_LOW, TEMP_SENSOR_HIGH),
oldTemperature(20), uptimeOfOldTemperature( { INVALID_TEMPERATURE, 0 }) {
oldTemperature(20), uptimeOfOldTemperature({ thermal::INVALID_TEMPERATURE, 0 }) {
}
@@ -98,7 +99,7 @@ protected:
private:
void setInvalid() {
outputTemperature = INVALID_TEMPERATURE;
outputTemperature = thermal::INVALID_TEMPERATURE;
outputTemperature.setValid(false);
uptimeOfOldTemperature.tv_sec = INVALID_UPTIME;
sensorMonitor.setToInvalid();
@@ -108,11 +109,8 @@ protected:
UsedParameters parameters;
inputType * inputValue;
PoolVariableIF *poolVariable;
gp_float_t outputTemperature;
lp_var_t<limitType>* inputTemperature;
lp_var_t<float> outputTemperature;
LimitMonitor<limitType> sensorMonitor;
@@ -120,22 +118,27 @@ protected:
timeval uptimeOfOldTemperature;
void doChildOperation() {
if (!poolVariable->isValid()
|| !healthHelper.healthTable->isHealthy(getObjectId())) {
ReturnValue_t result = inputTemperature->read(MutexIF::TimeoutType::WAITING, 20);
if(result != HasReturnvaluesIF::RETURN_OK) {
return;
}
if ((not inputTemperature->isValid()) or
(not healthHelper.healthTable->isHealthy(getObjectId()))) {
setInvalid();
return;
}
outputTemperature = calculateOutputTemperature(*inputValue);
outputTemperature = calculateOutputTemperature(inputTemperature->value);
outputTemperature.setValid(PoolVariableIF::VALID);
timeval uptime;
Clock::getUptime(&uptime);
if (uptimeOfOldTemperature.tv_sec != INVALID_UPTIME) {
//In theory, we could use an AbsValueMonitor to monitor the gradient.
//But this would require storing the maxGradient in DP and quite some overhead.
//The concept of delta limits is a bit strange anyway.
// In theory, we could use an AbsValueMonitor to monitor the gradient.
// But this would require storing the maxGradient in DP and quite some overhead.
// The concept of delta limits is a bit strange anyway.
float deltaTime;
float deltaTemp;
@@ -148,17 +151,17 @@ protected:
}
if (parameters.gradient < deltaTemp / deltaTime) {
triggerEvent(TEMP_SENSOR_GRADIENT);
//Don't set invalid, as we did not recognize it as invalid with full authority, let FDIR handle it
// Don't set invalid, as we did not recognize it as invalid with full authority,
// let FDIR handle it
}
}
//Check is done against raw limits. SHOULDDO: Why? Using <20>C would be more easy to handle.
sensorMonitor.doCheck(outputTemperature.value);
if (sensorMonitor.isOutOfLimits()) {
uptimeOfOldTemperature.tv_sec = INVALID_UPTIME;
outputTemperature.setValid(PoolVariableIF::INVALID);
outputTemperature = INVALID_TEMPERATURE;
outputTemperature = thermal::INVALID_TEMPERATURE;
} else {
oldTemperature = outputTemperature;
uptimeOfOldTemperature = uptime;
@@ -179,7 +182,10 @@ public:
static const uint16_t ADDRESS_C = 2;
static const uint16_t ADDRESS_GRADIENT = 3;
static const uint16_t DEFAULT_CONFIRMATION_COUNT = 1; //!< Changed due to issue with later temperature checking even tough the sensor monitor was confirming already (Was 10 before with comment = Correlates to a 10s confirmation time. Chosen rather large, should not be so bad for components and helps survive glitches.)
//! Changed due to issue with later temperature checking even tough the sensor monitor was
//! confirming already (Was 10 before with comment = Correlates to a 10s confirmation time.
//! Chosen rather large, should not be so bad for components and helps survive glitches.)
static const uint16_t DEFAULT_CONFIRMATION_COUNT = 1;
static const uint8_t DOMAIN_ID_SENSOR = 1;
@@ -219,4 +225,4 @@ public:
};
#endif /* TEMPERATURESENSOR_H_ */
#endif /* FSFW_THERMAL_TEMPERATURESENSOR_H_ */

View File

@@ -25,6 +25,6 @@ uint32_t TimeMessage::getCounterValue() {
return temp;
}
size_t TimeMessage::getMinimumMessageSize() {
size_t TimeMessage::getMinimumMessageSize() const {
return this->MAX_SIZE;
}

View File

@@ -11,7 +11,7 @@ protected:
* @brief This call always returns the same fixed size of the message.
* @return Returns HEADER_SIZE + \c sizeof(timeval) + sizeof(uint32_t).
*/
size_t getMinimumMessageSize();
size_t getMinimumMessageSize() const override;
public:
/**

View File

@@ -4,6 +4,8 @@
#include "../serviceinterface/ServiceInterface.h"
#include "../globalfunctions/arrayprinter.h"
#define TMTCBRIDGE_WIRETAPPING 0
TmTcBridge::TmTcBridge(object_id_t objectId, object_id_t tcDestination,
object_id_t tmStoreId, object_id_t tcStoreId):
SystemObject(objectId),tmStoreId(tmStoreId), tcStoreId(tcStoreId),
@@ -14,7 +16,9 @@ TmTcBridge::TmTcBridge(object_id_t objectId, object_id_t tcDestination,
createMessageQueue(TMTC_RECEPTION_QUEUE_DEPTH);
}
TmTcBridge::~TmTcBridge() {}
TmTcBridge::~TmTcBridge() {
QueueFactory::instance()->deleteMessageQueue(tmTcReceptionQueue);
}
ReturnValue_t TmTcBridge::setNumberOfSentPacketsPerCycle(
uint8_t sentPacketsPerCycle) {
@@ -234,17 +238,11 @@ ReturnValue_t TmTcBridge::handleStoredTm() {
void TmTcBridge::registerCommConnect() {
if(not communicationLinkUp) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
//sif::info << "TMTC Bridge: Registered Comm Link Connect" << std::endl;
#endif
communicationLinkUp = true;
}
}
void TmTcBridge::registerCommDisconnect() {
#if FSFW_CPP_OSTREAM_ENABLED == 1
//sif::info << "TMTC Bridge: Registered Comm Link Disconnect" << std::endl;
#endif
if(communicationLinkUp) {
communicationLinkUp = false;
}