Compare commits

..

140 Commits

Author SHA1 Message Date
c1a9678abb fixing merge again
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
2023-06-02 12:08:06 +02:00
1f4ad10dff fixing merge
Some checks failed
fsfw/fsfw/pipeline/head There was a failure building this commit
2023-06-02 11:50:09 +02:00
17ed22039e Merge remote-tracking branch 'origin/development' into mohr/windows
Some checks failed
fsfw/fsfw/pipeline/head There was a failure building this commit
2023-06-02 11:41:28 +02:00
f95c373076 Merge pull request 'TCP/IP server fixes and improvements' (#747) from eive/fsfw:tcpip_server_fixes_improvements into development
Some checks failed
fsfw/fsfw/pipeline/head There was a failure building this commit
Reviewed-on: #747
2023-05-25 16:04:28 +02:00
e03731bcf8 Merge pull request 'event manager improvements' (#741) from eive/fsfw:event_manager_improvements into development
Some checks failed
fsfw/fsfw/pipeline/head There was a failure building this commit
Reviewed-on: #741
2023-05-25 15:46:42 +02:00
2714e588d7 improvements
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-05-25 15:01:53 +02:00
e905288adc Merge remote-tracking branch 'upstream/development' into tcpip_server_fixes_improvements
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-05-25 15:00:42 +02:00
3805ea50a7 remove unused constant
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-05-25 14:58:18 +02:00
699bd694cd Merge branch 'development' into event_manager_improvements
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-05-25 14:44:22 +02:00
4518fec65c CHANGELOG
Some checks failed
fsfw/fsfw/pipeline/head There was a failure building this commit
2023-05-08 15:25:47 +02:00
dac1aacab2 Merge pull request 'Update Power Switch IF' (#743) from eive/fsfw:update_power_switch_if into development
Some checks failed
fsfw/fsfw/pipeline/head There was a failure building this commit
Reviewed-on: #743
2023-05-08 15:00:47 +02:00
0042f92fdf Merge pull request 'bump ETL version' (#748) from KSat/fsfw:bump_etl_dep into development
Some checks failed
fsfw/fsfw/pipeline/head There was a failure building this commit
Reviewed-on: #748
2023-05-08 14:53:02 +02:00
656faf8169 Merge remote-tracking branch 'upstream/development' into update_power_switch_if
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-05-08 14:44:27 +02:00
f84431e965 Merge pull request 'bugfix and changelog for Linux getUptime' (#745) from eive/fsfw:important_bugfix_linux_get_uptime into development
Some checks failed
fsfw/fsfw/pipeline/head There was a failure building this commit
Reviewed-on: #745
2023-05-08 14:29:55 +02:00
0cec9ebb73 Merge pull request 'small tweak for version getter' (#744) from eive/fsfw:small_version_getter_tweak into development
Some checks failed
fsfw/fsfw/pipeline/head There was a failure building this commit
Reviewed-on: #744
2023-05-08 14:13:06 +02:00
a440b7c394 Merge pull request 'add CFDP subsystem ID' (#742) from eive/fsfw:add_cfdp_subsystem_id into development
Some checks failed
fsfw/fsfw/pipeline/head There was a failure building this commit
Reviewed-on: #742
2023-05-08 14:09:04 +02:00
bbfc1b2b34 Merge pull request 'FixedArrayList compile time assert' (#740) from eive/fsfw:container_additional_assert into development
Some checks failed
fsfw/fsfw/pipeline/head There was a failure building this commit
Reviewed-on: #740
2023-05-08 14:04:56 +02:00
025b379e8b bump ETL version
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-05-04 14:04:55 +02:00
c35a0a8541 TCP/IP server fixes and improvements
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2023-03-15 12:40:44 +01:00
0f81d5e458 Merge remote-tracking branch 'upstream/development' into container_additional_assert
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-03-15 12:34:36 +01:00
e0a072859b Merge remote-tracking branch 'upstream/development' into event_manager_improvements
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-03-15 12:33:57 +01:00
b50f092939 Merge remote-tracking branch 'upstream/development' into update_power_switch_if
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2023-03-15 12:33:08 +01:00
2f90e12179 Merge remote-tracking branch 'upstream/development' into important_bugfix_linux_get_uptime
Some checks are pending
fsfw/fsfw/pipeline/pr-development Build started...
2023-03-15 12:32:25 +01:00
8b77fac099 Merge pull request 'health service fixes and changelog' (#746) from eive/fsfw:health_service_fixes into development
Some checks failed
fsfw/fsfw/pipeline/head There was a failure building this commit
Reviewed-on: #746
2023-03-15 12:29:31 +01:00
47503824d7 health service fixes and changelog
Some checks are pending
fsfw/fsfw/pipeline/pr-development Build started...
2023-03-15 12:27:39 +01:00
5e3f5c4121 fuse update
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2023-03-15 12:25:39 +01:00
1f36c082ef bugfix and changelog for Linux getUptime
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2023-03-15 12:21:50 +01:00
aa84e93603 small tweak for version getter
Some checks are pending
fsfw/fsfw/pipeline/pr-development Build started...
2023-03-15 12:17:36 +01:00
8f63a0e747 changelog
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-03-15 12:15:21 +01:00
6fc8f756a7 update power switch IF 2023-03-15 12:13:55 +01:00
067cb7d0f8 update catch factory
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2023-03-15 12:11:22 +01:00
d98ed40e3d add CFDP subsystem ID
Some checks are pending
fsfw/fsfw/pipeline/pr-development Build started...
2023-03-15 12:09:30 +01:00
2c17af4ef8 changelog
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2023-03-15 12:06:13 +01:00
110fb43b9c event manager improvements
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2023-03-15 12:05:22 +01:00
b057250bfb changelog
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2023-03-15 11:53:12 +01:00
066dd0d397 changelog 2023-03-15 11:52:20 +01:00
f735c2e9d4 assert size larger than 0 2023-03-15 11:51:51 +01:00
dc7afc5415 Version bump, CHANGELOG update, format
Some checks failed
fsfw/fsfw/pipeline/pr-master This commit looks good
fsfw/fsfw/pipeline/head There was a failure building this commit
2023-02-23 13:38:24 +01:00
9bf3ff95b7 Merge pull request 'Add Health Service Announce All Health Info' (#725) from eive/fsfw:add_health_service_announce_all into development
All checks were successful
fsfw/fsfw/pipeline/pr-master This commit looks good
Reviewed-on: #725
2023-02-23 13:13:56 +01:00
61562b18ab Merge branch 'development' into add_health_service_announce_all
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-02-23 12:56:12 +01:00
d76d97a36b changed health table parameter to objectId
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2023-02-23 12:44:42 +01:00
76b377c4c0 Merge pull request 'Mode Service: Add allowed subservice' (#739) from eive/fsfw:small_mode_service_fix into development
All checks were successful
fsfw/fsfw/pipeline/pr-master This commit looks good
Reviewed-on: #739
2023-02-20 13:40:53 +01:00
3562bf11b9 CHANGELOG update
All checks were successful
fsfw/fsfw/pipeline/pr-master This commit looks good
2023-02-10 11:06:46 +01:00
fffb2b61e5 release check helper 2023-02-10 11:06:30 +01:00
94e5f62331 add allowed subservice
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-02-09 18:30:08 +01:00
0a9c563bbc format 2023-02-09 15:58:48 +01:00
fa7675897d Merge pull request 'Mode Service Bugfixes' (#736) from eive/fsfw:mode_service_fixes into development
All checks were successful
fsfw/fsfw/pipeline/pr-master This commit looks good
Reviewed-on: #736
2023-02-09 15:56:26 +01:00
3a2393885f more style
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-02-09 15:44:39 +01:00
c752b6d143 Merge pull request 'Generic TMTC Bridge Update' (#734) from eive/fsfw:tmtcbridge_tweaks into development
All checks were successful
fsfw/fsfw/pipeline/pr-master This commit looks good
Reviewed-on: #734
2023-02-09 15:37:35 +01:00
b676040c7c Merge pull request 'CMakeLists file updates' (#731) from eive/fsfw:cmakelists_update into development
All checks were successful
fsfw/fsfw/pipeline/pr-master This commit looks good
Reviewed-on: #731
2023-02-09 15:29:46 +01:00
b1160cfb2e fixing setsockopt for windows
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
2023-02-09 14:56:40 +01:00
010509efb4 removed unneeded find_package parameter for etl
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-02-09 13:50:16 +01:00
dfb1633f00 Merge branch 'development' into mode_service_fixes
Some checks reported errors
fsfw/fsfw/pipeline/pr-development Something is wrong with the build of this commit
2023-02-09 13:46:19 +01:00
99896f2695 tweaking cmake toolchains layout
Some checks failed
fsfw/fsfw/pipeline/head There was a failure building this commit
2023-02-09 13:43:35 +01:00
5f7172e130 Merge pull request 'TCP/IP TMTC bridge memory leak fixes' (#737) from eive/fsfw:possible_tcpip_bridge_fixes into development
All checks were successful
fsfw/fsfw/pipeline/pr-master This commit looks good
Reviewed-on: #737
2023-02-09 12:15:45 +01:00
0c6465cd95 Merge pull request 'time stamper empty ctor' (#730) from eive/fsfw:empty_cds_short_ctor into development
All checks were successful
fsfw/fsfw/pipeline/pr-master This commit looks good
Reviewed-on: #730
2023-02-09 11:45:49 +01:00
f94987c46d Merge pull request 'RM3100 important bugfix' (#733) from eive/fsfw:rm3100_fixes into development
All checks were successful
fsfw/fsfw/pipeline/pr-master This commit looks good
Reviewed-on: #733
2023-02-09 11:41:53 +01:00
1809ce359b Merge pull request 'comment tweak to event parser can read everything' (#732) from eive/fsfw:health_if_update into development
All checks were successful
fsfw/fsfw/pipeline/pr-master This commit looks good
Reviewed-on: #732
2023-02-09 11:39:53 +01:00
8c712441ab Making fetch Catch2 quiet as well.
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-02-09 11:34:58 +01:00
45b686a028 Merge remote-tracking branch 'origin/development' into mohr/windows 2023-02-08 22:08:55 +01:00
f1b0ca7cff add PR link
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-02-08 21:26:37 +01:00
000df85556 bump changelog
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2023-02-08 21:24:00 +01:00
1fffcc2229 possiible leak fixes 2023-02-08 21:23:21 +01:00
329e80e7ee enabling win unittests
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
2023-02-08 14:08:09 +01:00
3772db4753 group id conflict
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
2023-02-08 11:46:39 +01:00
a419806a05 Merge remote-tracking branch 'upstream/development' into mode_service_fixes
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2023-02-08 09:33:13 +01:00
6445debfa1 bump changelog
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2023-02-08 09:24:55 +01:00
8014e4adf9 mode service fixes 2023-02-08 09:23:48 +01:00
3d13ead275 moved to newer wine
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
2023-02-07 21:56:06 +01:00
e7e9ce4baf one more warning suppressed in MSVC 2023-02-07 13:25:13 +01:00
134d908f26 that stuff is not in upstream yet..
Some checks are pending
fsfw/fsfw/pipeline/pr-development Build started...
2023-02-07 12:52:18 +01:00
40a9e12416 1000 is a bit much
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-02-07 12:47:40 +01:00
f39054edd4 introduce warning switch 2023-02-07 12:45:29 +01:00
5adf89b911 changelog update
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2023-02-07 12:41:42 +01:00
c2e6a22dec important bugfix for RM3100 2023-02-07 12:39:43 +01:00
c8e065a713 comment tweak to event parser can read everything
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-02-07 12:36:42 +01:00
e4c11f8107 fixing problem which causes a looooooong hang in CI by illegaly overrideing internal CMake Variable
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
2023-02-07 12:26:44 +01:00
3ed49dbae3 Merge remote-tracking branch 'upstream/development' into empty_cds_short_ctor
Some checks are pending
fsfw/fsfw/pipeline/pr-development Build started...
2023-02-07 12:24:02 +01:00
4cf52d5dfe Merge pull request 'Time Service 9 update' (#726) from eive/fsfw:updates_fixes_pus_time_service into development
All checks were successful
fsfw/fsfw/pipeline/pr-master This commit looks good
Reviewed-on: #726
2023-02-07 12:19:45 +01:00
539d7aac9e suppress error if ETL is not found
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-02-07 12:17:03 +01:00
0a23f2c85a correction for printout, add prefix
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-02-07 12:15:44 +01:00
46230e6c6d Merge remote-tracking branch 'upstream/development' into updates_fixes_pus_time_service
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-02-07 12:11:29 +01:00
b22d439300 bump changelog
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2023-02-07 12:10:11 +01:00
7e7b3bbbc9 time stamper empty ctor
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-02-07 12:07:41 +01:00
270622a5f1 no coverage with clang so far; using correct path to push coverage data
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
2023-02-06 22:49:37 +01:00
4b52e5bec4 windows and clang builds in CI
Some checks failed
fsfw/fsfw/pipeline/head There was a failure building this commit
2023-02-06 22:45:00 +01:00
5b92247fbd Merge branch 'development' into add_health_service_announce_all
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2023-02-06 16:31:05 +01:00
e2b66df72e Merge pull request 'various fixes related to linux Unittests and memory leaks' (#715) from eive/fsfw:unittest_fix_semaphore into development
All checks were successful
fsfw/fsfw/pipeline/pr-master This commit looks good
Reviewed-on: #715
2023-02-06 16:30:37 +01:00
efc2773f84 docker update for windows
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
2023-02-06 16:29:53 +01:00
d9da55fdab Merge branch 'development' into add_health_service_announce_all
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-02-06 15:03:52 +01:00
7b828f233a Merge pull request 'I2C Linux: remove duplicate printout' (#718) from eive/fsfw:i2c_remove_duplicate_printout into development
All checks were successful
fsfw/fsfw/pipeline/pr-master This commit looks good
Reviewed-on: #718
2023-02-06 14:54:58 +01:00
c3d1000cd5 Merge branch 'development' into unittest_fix_semaphore
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-02-06 14:46:45 +01:00
8e0e57714d Merge pull request 'allow using SO_REUSEADDR and SO_REUSEPORT on TCP server' (#722) from eive/fsfw:tcp_server_reuseaddr_reusesocket into development
All checks were successful
fsfw/fsfw/pipeline/pr-master This commit looks good
Reviewed-on: #722
2023-02-06 14:45:40 +01:00
066f7a6f9b remove unreachable code
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-02-06 14:41:14 +01:00
cc9e54ea6b Merge pull request 'improve srv20 error messages' (#723) from eive/fsfw:srv20_error_msgs into development
All checks were successful
fsfw/fsfw/pipeline/pr-master This commit looks good
Reviewed-on: #723
2023-02-06 14:37:26 +01:00
31465a4e0f Merge pull request 'MGM: small tweak, gain factor was always them same' (#724) from eive/fsfw:mgm_handler_small_fix into development
All checks were successful
fsfw/fsfw/pipeline/pr-master This commit looks good
Reviewed-on: #724
2023-02-06 14:36:34 +01:00
c0e5d1eb99 Merge branch 'development' into tcp_server_reuseaddr_reusesocket
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-02-06 14:34:52 +01:00
3bc5d4a2e0 Merge remote-tracking branch 'upstream/development' into mgm_handler_small_fix
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-02-06 14:25:33 +01:00
b1e9dd9e4a Merge remote-tracking branch 'upstream/development' into updates_fixes_pus_time_service
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2023-02-06 14:24:38 +01:00
ab86599db3 Merge pull request 'Bugfix DHB setNormalDatapoolEntriesInvalid' (#728) from eive/fsfw:bugfix_dhb_set_datapool_entries_invalid into development
All checks were successful
fsfw/fsfw/pipeline/pr-master This commit looks good
Reviewed-on: #728
2023-02-06 14:20:34 +01:00
87bb29a66a compiler parameter tuning
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
2023-02-06 13:10:50 +01:00
034eb34c2e small tweak
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-02-03 16:05:50 +01:00
4374c7c4f4 changelog
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-02-03 16:01:56 +01:00
5343844be5 bugfix in setNormalDataPoolEntriesInvalid
Do not forget to call read and write to actually update the
validity state
2023-02-03 16:00:55 +01:00
e300490b93 Merge pull request 'Bugfix PUS packet creators Sequence flags' (#727) from eive/fsfw:bugfix_pus_packets_seq_flags into development
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
fsfw/fsfw/pipeline/pr-master This commit looks good
Reviewed-on: #727
2023-02-02 17:22:29 +01:00
0f811777a7 changelog update
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-02-01 20:49:53 +01:00
e93137939e set sequence flags for PUS TMTC to unsegmented 2023-02-01 20:48:26 +01:00
c1f42618db small but important bugfix for health service
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-02-01 19:59:32 +01:00
1f88c006d9 update changelog
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2023-02-01 18:42:09 +01:00
7e94baceef service 9 update
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
- fix time info event
- add time dump subservice
2023-02-01 18:39:23 +01:00
61df451dd8 update changelog
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-02-01 17:41:47 +01:00
29ea89044e beatufil 2023-02-01 17:35:49 +01:00
e487f5be87 proper announce all impl 2023-02-01 17:35:32 +01:00
9b05e8f274 re-order fields in TcpConfig
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-01-30 14:24:48 +01:00
eb223dae88 bump changelog
Some checks failed
fsfw/fsfw/pipeline/pr-development There was a failure building this commit
2023-01-30 14:20:28 +01:00
3656662d88 small tweak, gain factory was always them same
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-01-30 14:18:03 +01:00
fe71978467 improve srv20 error messages
Some checks are pending
fsfw/fsfw/pipeline/pr-development Build started...
2023-01-30 14:15:37 +01:00
b646717a76 bump changelog
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-01-30 14:11:00 +01:00
99d8c845f2 allow using SO_REUSEADDR and SO_REUSEPORT on TCP server
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-01-30 14:07:41 +01:00
45963b2064 tuning win build
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
2023-01-27 17:26:03 +01:00
bc312243df clang -Weverything -Wno-gnu-anonymous-struct
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
2023-01-27 00:50:10 +01:00
9589d702dd windows unittests succeed
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
2023-01-26 18:14:35 +01:00
c66fab90f9 filesystem stuff works on linux/host
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
2023-01-26 17:05:25 +01:00
3e8446ba8b windows building again 2023-01-26 15:30:23 +01:00
e37af4fe70 format
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
2023-01-26 13:40:44 +01:00
941bf61f28 constant number of assertions in unittests
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
2023-01-26 13:26:11 +01:00
70fd9ff3e5 fixed impact of windows fixes on other builds
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
2023-01-26 12:33:39 +01:00
81c5b2ec95 Merge branch 'mohr/rtems' into windows
Some checks failed
fsfw/fsfw/pipeline/head There was a failure building this commit
2023-01-26 11:55:16 +01:00
7426e10f82 clocks suck a little less
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
2023-01-26 11:33:40 +01:00
uli
123c81777a clocks suck 2023-01-26 00:01:40 +01:00
dcc28622a5 windows compiles, some unittests give exceptions
Some checks failed
fsfw/fsfw/pipeline/head There was a failure building this commit
2023-01-25 23:54:46 +01:00
6d85fa155e cleaning up unittest build
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
2023-01-20 16:05:04 +01:00
e6af6200ae updating CI
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
2023-01-19 17:32:23 +01:00
5ca3e83934 working on rtems CI build
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
2023-01-19 16:46:43 +01:00
6adabb059a fixing rtems cmake config
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
2023-01-19 16:27:10 +01:00
5d0a5cd201 exiting qemu nonzero when tests fail 2023-01-19 14:47:40 +01:00
adb8483bb0 unittests for rtems working
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
2023-01-19 14:24:33 +01:00
fdfdce2fb0 compiling, crashing when run
All checks were successful
fsfw/fsfw/pipeline/head This commit looks good
2023-01-18 00:25:25 +01:00
ba62c28b64 adding linux ci and fixing problems
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-01-12 15:40:52 +01:00
7adb47aecb remove duplicate printout
All checks were successful
fsfw/fsfw/pipeline/pr-development This commit looks good
2023-01-11 08:45:37 +01:00
131 changed files with 1549 additions and 965 deletions

3
.gitmodules vendored
View File

@ -0,0 +1,3 @@
[submodule "automation/msvc-wine"]
path = automation/msvc-wine
url = https://github.com/mstorsjo/msvc-wine

View File

@ -8,14 +8,71 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
# [unreleased] # [unreleased]
# [v6.0.0] ## Fixes
- PUS Health Service: Size check for set health command.
Perform operation completion for announce health command.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/746
- Linux OSAL `getUptime` fix: Check validity of `/proc/uptime` file before reading uptime.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/745
- Small tweak for version getter
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/744
## Added
- add CFDP subsystem ID
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/742
## Changed
- Bump ETL version to 20.35.14
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/748
- Renamed `PCDU_2` subsystem ID to `POWER_SWITCH_IF`.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/743
- Add new `PowerSwitchIF::SWITCH_UNKNOWN` returnvalue.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/743
- Assert that `FixedArrayList` is larger than 0 at compile time.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/740
## Added
- `EventManager`: Add function to print all listeners.
## Changed
- `EventManager`: Queue depth is configurable now
# [v6.0.0] 2023-02-10
## Fixes ## Fixes
- Mode Service: Add allowed subservice
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/739
- `CService200ModeManagement`: Various bugfixes which lead to now execution complete being generated
on mode announcements, duplicate mode reply generated on announce commands, and the mode read
subservice not working properly.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/736
- Memory leak fixes for the TCP/IP TMTC bridge.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/737
- `Service9TimeManagement`: Fix the time dump at the `SET_TIME` subservice: Include clock timeval
seconds instead of uptime.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/726
- HAL MGM3100 Handler: Use axis specific gain/scaling factors. Previously,
only the X scaling factor was used.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/724
- HAL MGM3100 Handler: Z value was previously calculated with bytes of the X value.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/733
- DHB `setNormalDatapoolEntriesInvalid`: The default implementation did not set the validity
to false correctly because the `read` and `write` calls were missing.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/728
- PUS TMTC creator module: Sequence flags were set to continuation segment (0b00) instead
of the correct unsegmented flags (0b11) as specified in the standard.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/727
- TC Scheduler Service 11: Add size and CRC check for contained TC. - TC Scheduler Service 11: Add size and CRC check for contained TC.
Bug: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/issues/719
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/720
- Only delete health table entry in `HealthHelper` destructor if - Only delete health table entry in `HealthHelper` destructor if
health table was set. health table was set.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/710/files PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/710
- I2C Bugfixes: Do not keep iterator as member and fix some incorrect handling with the iterator. - I2C Bugfixes: Do not keep iterator as member and fix some incorrect handling with the iterator.
Also properly reset the reply size for successfull transfers and erroneous transfers. Also properly reset the reply size for successfull transfers and erroneous transfers.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/700 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/700
@ -25,22 +82,82 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- `TcpTmTcServer.cpp`: The server was actually not able to handle - `TcpTmTcServer.cpp`: The server was actually not able to handle
CCSDS packets which were clumped together. This has been fixed now. CCSDS packets which were clumped together. This has been fixed now.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/673 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/673
- `CServiceHealthCommanding`: Add announce all health info implementation
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/725
- various fixes related to linux Unittests and memory leaks
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/715
- small fix to allow teardown handling
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/713
- fix compiler warning for fixed array list copy ctor
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/704
- missing include
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/703
- defaultconfig did not build anymore
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/702
- hotfix
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/699
- small fix for helper
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/698
- missing retval conv
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/697
- DHB Countdown Bug
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/693
- doc corrections
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/687
- better error printout
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/686
- include correction
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/683
- better warning for missing include paths
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/676
- Service 11 regression
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/670
## Added ## Added
- Empty constructor for `CdsShortTimeStamper` which does not do an object manager registration.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/730
- `Service9TimeManagement`: Add `DUMP_TIME` (129) subservice.
- `TcpTmTcServer`: Allow setting the `SO_REUSEADDR` and `SO_REUSEPORT`
option on the TCP server. CTOR prototype has changed and expects an explicit
TCP configuration struct to be passed.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/722
- `DleParser` helper class to parse DLE encoded packets from a byte stream. - `DleParser` helper class to parse DLE encoded packets from a byte stream.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/711 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/711
- `UioMapper` is able to resolve symlinks now. - `UioMapper` is able to resolve symlinks now.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/709 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/709
- Add new `UnsignedByteField` class - Add new `UnsignedByteField` class
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/660 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/660
- publish documentation for development and master branch
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/681
- Add Linux HAL options
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/663
- Expand SerializeIF
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/656
- PUS Service 11: Additional Safety Check
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/666
- improvements for auto-formatter script
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/665
- provide a weak print char impl
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/674
## Removed
- now that doc server is up, remove markdown files
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/688
- remove bsp specific code
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/679
## Changes ## Changes
- `CService201HealthCommanding` renamed to `CServiceHealthCommanding`,
service ID customizable now. `CServiceHealthCommanding` expects configuration struct
`HealthServiceCfg` now
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/725
- `AcceptsTelemetryIF`: `getReportReceptionQueue` is const now - `AcceptsTelemetryIF`: `getReportReceptionQueue` is const now
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/712 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/712
- Moved some container returnvalues to dedicated header and namespace - Moved some container returnvalues to dedicated header and namespace
to they can be used without template specification. so they can be used without template specification.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/707 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/707
- Remove default secondary header argument for - Remove default secondary header argument for
`uint16_t getTcSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag)` and `uint16_t getTcSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag)` and
@ -70,18 +187,41 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- `DeviceHandlerBase`: New signature of `handleDeviceTm` which expects - `DeviceHandlerBase`: New signature of `handleDeviceTm` which expects
a `const SerializeIF&` and additional helper variant which expects `const uint8_t*` a `const SerializeIF&` and additional helper variant which expects `const uint8_t*`
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/671 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/671
- Move some generic `StorageManagerIF` implementations from `LocalPool` to
interface itself so it can be re-used more easily. Also add new
abstract function `bool hasDataAtId(store_address_t storeId) const`.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/685
- Improvements for `AcceptsTelemetryIF` and `AcceptsTelecommandsIF`: - Improvements for `AcceptsTelemetryIF` and `AcceptsTelecommandsIF`:
- Make functions `const` where it makes sense - Make functions `const` where it makes sense
- Add `const char* getName const` abstract function - Add `const char* getName const` abstract function
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/684 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/684
- Move some generic `StorageManagerIF` implementations from `LocalPool` to - Generic TMTC Bridge Update
interface itself so it can be re-used more easily. Also add new PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/734
abstract function `bool hasDataAtId(store_address_t storeId) const`. - comment tweak to event parser can read everything
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/685 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/732
- CMakeLists file updates
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/731
- improve srv20 error messages
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/723
- I2C Linux: remove duplicate printout
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/718
- printout handling improvements
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/717
- vec getter, reset for content
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/716
- updates for source sequence counter
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/714
- SP reader getPacketData is const now
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/708
- refactoring of serial drivers for linux
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/705
- Local Pool Update Remove Add Data Ignore Fault Argument
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/701
- Switch to new documentation server
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/694
- Windows Tweaks
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/691
- Refactor Local Pool API
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/667
- group MGM data in local pool vectors
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/664
## CFDP ## CFDP
@ -101,7 +241,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
implementation without an extra component implementation without an extra component
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/682 PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/682
# [v5.0.0] 25.07.2022 # [v5.0.0] 2022-07-25
## Changes ## Changes

View File

@ -13,7 +13,7 @@ list(APPEND CMAKE_MODULE_PATH
# Version file handling # # Version file handling #
# ############################################################################## # ##############################################################################
set(FSFW_VERSION_IF_GIT_FAILS 5) set(FSFW_VERSION_IF_GIT_FAILS 6)
set(FSFW_SUBVERSION_IF_GIT_FAILS 0) set(FSFW_SUBVERSION_IF_GIT_FAILS 0)
set(FSFW_REVISION_IF_GIT_FAILS 0) set(FSFW_REVISION_IF_GIT_FAILS 0)
@ -64,6 +64,13 @@ elseif(${CMAKE_CXX_STANDARD} LESS 17)
"${MSG_PREFIX} Compiling the FSFW requires a minimum of C++17 support") "${MSG_PREFIX} Compiling the FSFW requires a minimum of C++17 support")
endif() endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
# Manually tweak MSVC to emit (about) the same warnings as clang and gcc on linux
# needs to be done here using add_compile_definitions() (as opposed to target_compile_definitions()) to be available for all binaries and libraries
add_compile_options("/permissive-" /wd4267 /wd4244 /wd4244 /wd4305 /wd4805 /wd4267 /wd4646 /wd4065 /wd4996 /Dand=&& /Dor=|| /Dnot=!)
add_compile_definitions(NOMINMAX)
endif()
set(FSFW_SOURCES_DIR "${CMAKE_SOURCE_DIR}/src/fsfw") set(FSFW_SOURCES_DIR "${CMAKE_SOURCE_DIR}/src/fsfw")
set(FSFW_ETL_LIB_NAME etl) set(FSFW_ETL_LIB_NAME etl)
@ -72,7 +79,7 @@ set(FSFW_ETL_LIB_MAJOR_VERSION
20 20
CACHE STRING "ETL library major version requirement") CACHE STRING "ETL library major version requirement")
set(FSFW_ETL_LIB_VERSION set(FSFW_ETL_LIB_VERSION
${FSFW_ETL_LIB_MAJOR_VERSION}.28.0 ${FSFW_ETL_LIB_MAJOR_VERSION}.35.14
CACHE STRING "ETL library exact version requirement") CACHE STRING "ETL library exact version requirement")
set(FSFW_ETL_LINK_TARGET etl::etl) set(FSFW_ETL_LINK_TARGET etl::etl)
@ -153,12 +160,12 @@ if(FSFW_BUILD_TESTS)
"${MSG_PREFIX} Building the FSFW unittests in addition to the static library" "${MSG_PREFIX} Building the FSFW unittests in addition to the static library"
) )
# Check whether the user has already installed Catch2 first # Check whether the user has already installed Catch2 first
find_package(Catch2 ${FSFW_CATCH2_LIB_MAJOR_VERSION}) find_package(Catch2 ${FSFW_CATCH2_LIB_MAJOR_VERSION} QUIET)
# Not installed, so use FetchContent to download and provide Catch2 # Not installed, so use FetchContent to download and provide Catch2
if(NOT Catch2_FOUND) if(NOT Catch2_FOUND)
message( message(
STATUS STATUS
"${MSG_PREFIX} Catch2 installation not found. Downloading Catch2 library with FetchContent" "${MSG_PREFIX} Catch2 installation not found. Downloading Catch2 library with FetchContent."
) )
include(FetchContent) include(FetchContent)
@ -222,8 +229,8 @@ find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET)
if(NOT ${FSFW_ETL_LIB_NAME}_FOUND) if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
message( message(
STATUS STATUS
"${MSG_PREFIX} No ETL installation was found with find_package. Installing and providing " "${MSG_PREFIX} ETL installation not found. Downloading ETL with FetchContent."
"etl with FindPackage") )
include(FetchContent) include(FetchContent)
FetchContent_Declare( FetchContent_Declare(
@ -472,8 +479,8 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
endif() endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(COMPILER_FLAGS "/permissive-") set(FSFW_WARNING_FLAGS -Wall -Wno-gnu-anonymous-struct)
endif() endif()
# Required include paths to compile the FSFW # Required include paths to compile the FSFW

View File

@ -5,7 +5,7 @@ RUN apt-get --yes upgrade
#tzdata is a dependency, won't install otherwise #tzdata is a dependency, won't install otherwise
ARG DEBIAN_FRONTEND=noninteractive ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get --yes install gcc g++ cmake make lcov git valgrind nano iputils-ping python3 pip doxygen graphviz rsync RUN apt-get --yes install ca-certificates clang cmake doxygen g++ gcc git graphviz iputils-ping lcov make msitools nano ninja-build pip python3 python3-simplejson python3-six qemu-system-arm rsync valgrind wget winbind
RUN python3 -m pip install sphinx breathe RUN python3 -m pip install sphinx breathe
@ -21,9 +21,37 @@ RUN git clone https://github.com/ETLCPP/etl.git && \
cmake -B build . && \ cmake -B build . && \
cmake --install build/ cmake --install build/
# install our own rtems build
RUN wget -qO- https://buggy.irs.uni-stuttgart.de/rtems_releases/rtems6-12.2.1.tar.bz2 | tar -xj -C /opt/
ENV PATH="$PATH:/opt/rtems/6/bin"
# install modern wine for MSVC, removing a conflicting file
RUN dpkg --add-architecture i386 && \
mkdir -pm755 /etc/apt/keyrings && \
wget -O /etc/apt/keyrings/winehq-archive.key https://dl.winehq.org/wine-builds/winehq.key && \
wget -NP /etc/apt/sources.list.d/ https://dl.winehq.org/wine-builds/ubuntu/dists/focal/winehq-focal.sources && \
apt-get update && \
apt-get --yes install winehq-stable
# silence wine
ENV WINEDEBUG=-all
# install MSVC using https://github.com/mstorsjo/msvc-wine
# see msvc-wine/LICENSE.txt
COPY msvc-wine/lowercase msvc-wine/fixinclude msvc-wine/install.sh msvc-wine/vsdownload.py ./
COPY msvc-wine/wrappers/* ./wrappers/
RUN PYTHONUNBUFFERED=1 ./vsdownload.py --accept-license --dest /opt/msvc && \
./install.sh /opt/msvc && \
rm lowercase fixinclude install.sh vsdownload.py && \
rm -rf wrappers
RUN wine64 wineboot --init && \
while pgrep wineserver > /dev/null; do sleep 1; done
#ssh needs a valid user to work #ssh needs a valid user to work
RUN adduser --uid 114 jenkins RUN addgroup -q --gid 117 jenkins && adduser -q --uid 114 --gid 117 jenkins
#add documentation server to known hosts #add documentation server to known hosts
RUN echo "|1|/LzCV4BuTmTb2wKnD146l9fTKgQ=|NJJtVjvWbtRt8OYqFgcYRnMQyVw= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNL8ssTonYtgiR/6RRlSIK9WU1ywOcJmxFTLcEblAwH7oifZzmYq3XRfwXrgfMpylEfMFYfCU8JRqtmi19xc21A=" >> /etc/ssh/ssh_known_hosts RUN echo "|1|/LzCV4BuTmTb2wKnD146l9fTKgQ=|NJJtVjvWbtRt8OYqFgcYRnMQyVw= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNL8ssTonYtgiR/6RRlSIK9WU1ywOcJmxFTLcEblAwH7oifZzmYq3XRfwXrgfMpylEfMFYfCU8JRqtmi19xc21A=" >> /etc/ssh/ssh_known_hosts
RUN echo "|1|CcBvBc3EG03G+XM5rqRHs6gK/Gg=|oGeJQ+1I8NGI2THIkJsW92DpTzs= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNL8ssTonYtgiR/6RRlSIK9WU1ywOcJmxFTLcEblAwH7oifZzmYq3XRfwXrgfMpylEfMFYfCU8JRqtmi19xc21A=" >> /etc/ssh/ssh_known_hosts RUN echo "|1|CcBvBc3EG03G+XM5rqRHs6gK/Gg=|oGeJQ+1I8NGI2THIkJsW92DpTzs= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNL8ssTonYtgiR/6RRlSIK9WU1ywOcJmxFTLcEblAwH7oifZzmYq3XRfwXrgfMpylEfMFYfCU8JRqtmi19xc21A=" >> /etc/ssh/ssh_known_hosts

View File

@ -3,28 +3,29 @@ pipeline {
BUILDDIR_HOST = 'cmake-build-tests-host' BUILDDIR_HOST = 'cmake-build-tests-host'
BUILDDIR_LINUX = 'cmake-build-tests-linux' BUILDDIR_LINUX = 'cmake-build-tests-linux'
BUILDDIR_FREERTOS = 'cmake-build-tests-freertos' BUILDDIR_FREERTOS = 'cmake-build-tests-freertos'
BUILDDIR_RTEMS = 'cmake-build-tests-rtems'
BUILDDIR_WIN = 'cmake-build-tests-windows'
DOCDDIR = 'cmake-build-documentation' DOCDDIR = 'cmake-build-documentation'
} }
agent { agent {
docker { docker {
image 'fsfw-ci:d6' image 'fsfw-ci:d9'
args '--network host --sysctl fs.mqueue.msg_max=100' args '--network host --sysctl fs.mqueue.msg_max=100'
} }
} }
stages { stages {
stage('Host') { stage('x64-linux-clang-host') {
steps { steps {
sh 'rm -rf $BUILDDIR_HOST' sh 'rm -rf $BUILDDIR_HOST'
dir(BUILDDIR_HOST) { dir(BUILDDIR_HOST) {
sh 'cmake -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..' sh 'CC=clang CXX=clang++ cmake -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
sh 'cmake --build . -j4' sh 'cmake --build . -j4'
sh 'cmake --build . -- fsfw-tests_coverage -j4'
sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests' sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
} }
} }
} }
stage('Linux') { stage('x64-linux-gcc') {
steps { steps {
sh 'rm -rf $BUILDDIR_LINUX' sh 'rm -rf $BUILDDIR_LINUX'
@ -36,18 +37,40 @@ pipeline {
} }
} }
} }
stage('FreeRTOS') { stage('x64-FreeRTOS-gcc') {
steps { steps {
sh 'rm -rf $BUILDDIR_FREERTOS' sh 'rm -rf $BUILDDIR_FREERTOS'
dir(BUILDDIR_FREERTOS) { dir(BUILDDIR_FREERTOS) {
sh 'cmake -DFSFW_OSAL=freertos -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..' sh 'cmake -DFSFW_OSAL=freertos -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
sh 'cmake --build . -j4' sh 'cmake --build . -j4'
sh 'cmake --build . -- fsfw-tests_coverage -j4' sh './fsfw-tests'
//sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests' //sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
} }
} }
} }
stage('aarch64-rtems6-gcc') {
steps {
sh 'rm -rf $BUILDDIR_RTEMS'
dir(BUILDDIR_RTEMS) {
sh 'cmake -DFSFW_OSAL=rtems -DFSFW_BUILD_TESTS=ON -DFSFW_TESTS_GEN_COV=OFF -DFSFW_CICD_BUILD=ON -DCMAKE_TOOLCHAIN_FILE=../cmake/aarch64-rtems6-gcc.cmake ..'
sh 'cmake --build . -j4'
sh 'qemu-system-aarch64 -no-reboot -nographic -serial mon:stdio -semihosting -machine virt,gic-version=3 -cpu cortex-a72 -m 4000 -kernel fsfw-tests'
}
}
}
stage('x64-windows-msvc-host') {
steps {
sh 'rm -rf $BUILDDIR_WIN'
dir(BUILDDIR_WIN) {
sh 'cmake -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON -DFSFW_TESTS_GEN_COV=OFF -DFSFW_CICD_BUILD=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../cmake/x64-windows-msvc.cmake -GNinja ..'
sh 'cmake --build . -j4'
sh 'wine64 fsfw-tests.exe'
}
}
}
stage('Documentation') { stage('Documentation') {
when { when {
branch 'development' branch 'development'
@ -60,7 +83,7 @@ pipeline {
sh 'rsync -r --delete docs/sphinx/* buildfix@documentation.irs.uni-stuttgart.de:/fsfw/development' sh 'rsync -r --delete docs/sphinx/* buildfix@documentation.irs.uni-stuttgart.de:/fsfw/development'
} }
} }
dir(BUILDDIR) { dir(BUILDDIR_LINUX) {
sshagent(credentials: ['documentation-buildfix']) { sshagent(credentials: ['documentation-buildfix']) {
sh 'rsync -r --delete fsfw-tests_coverage/* buildfix@documentation.irs.uni-stuttgart.de:/fsfw/coverage/development' sh 'rsync -r --delete fsfw-tests_coverage/* buildfix@documentation.irs.uni-stuttgart.de:/fsfw/coverage/development'
} }
@ -79,7 +102,7 @@ pipeline {
sh 'rsync -r --delete docs/sphinx/* buildfix@documentation.irs.uni-stuttgart.de:/fsfw/master' sh 'rsync -r --delete docs/sphinx/* buildfix@documentation.irs.uni-stuttgart.de:/fsfw/master'
} }
} }
dir(BUILDDIR) { dir(BUILDDIR_LINUX) {
sshagent(credentials: ['documentation-buildfix']) { sshagent(credentials: ['documentation-buildfix']) {
sh 'rsync -r --delete fsfw-tests_coverage/* buildfix@documentation.irs.uni-stuttgart.de:/fsfw/coverage/master' sh 'rsync -r --delete fsfw-tests_coverage/* buildfix@documentation.irs.uni-stuttgart.de:/fsfw/coverage/master'
} }

1
automation/msvc-wine Submodule

Submodule automation/msvc-wine added at 2d2d7db0b5

View File

@ -0,0 +1,3 @@
add_compile_options("-mcpu=cortex-a72" "-I/opt/rtems/6/aarch64-rtems6/a72_lp64_qemu/lib/include")
add_link_options("-B/opt/rtems/6/aarch64-rtems6/a72_lp64_qemu/lib" "-qrtems")

View File

@ -0,0 +1,33 @@
## the name of the target operating system
set(CMAKE_SYSTEM_NAME a72_lp64_qemu)
set(CMAKE_SYSTEM_PROCESSOR a72)
# which compilers to use for C and C++
set(CMAKE_C_COMPILER aarch64-rtems6-gcc)
set(CMAKE_CXX_COMPILER aarch64-rtems6-g++)
# built in tests fail
set(CMAKE_C_COMPILER_WORKS 1)
set(CMAKE_CXX_COMPILER_WORKS 1)
# adjust the default behavior of the FIND_XXX() commands:
# search programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
# search headers and libraries in the target environment
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
# ignore host installed libraries
# makes find_package() ignore the <package>Config.cmake files
set(CMAKE_IGNORE_PATH /usr/local)
# supress errors
add_compile_definitions("__STDC_VERSION__")
# make newlib behave like glib with an intercepted cmath
add_compile_options("-I${CMAKE_SOURCE_DIR}/unittests/testcfg/rtems/include")

View File

@ -0,0 +1,27 @@
set(CMAKE_SYSTEM_NAME Windows)
# which compilers to use for C and C++
set(CMAKE_C_COMPILER /opt/msvc/bin/x64/cl)
set(CMAKE_CXX_COMPILER /opt/msvc/bin/x64/cl)
# built in tests fail
set(CMAKE_C_COMPILER_WORKS ON)
set(CMAKE_CXX_COMPILER_WORKS ON)
# fails somewhere caused by wine
# overriding internal variable DO NOT TRY THIS AT HOME!
set(CMAKE_C_ABI_COMPILED ON)
set(CMAKE_CXX_ABI_COMPILED ON)
# adjust the default behavior of the FIND_XXX() commands:
# search programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
# search headers and libraries in the target environment
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
# ignore host installed libraries
# makes find_package() ignore the <package>Config.cmake files
set(CMAKE_IGNORE_PATH /usr/local)

110
scripts/check_release.py Executable file
View File

@ -0,0 +1,110 @@
#! /bin/python
import argparse
import json
import urllib.request
import re
from pathlib import Path
def main() -> None:
parser = argparse.ArgumentParser(
description="List undocumented PRs"
)
parser.add_argument("-v", "--version", type=str, required=True)
args = parser.parse_args()
match = re.search("([0-9]+\.[0-9]+\.[0-9]+)", args.version)
if not match:
print("invalid version")
exit(1)
version = "v" + match.group(1)
print("looking for milestone for " + version + " ...")
with urllib.request.urlopen("https://egit.irs.uni-stuttgart.de/api/v1/repos/fsfw/fsfw/milestones?name=" + version) as milestone_json:
milestones = json.load(milestone_json)
if (len(milestones) == 0):
print("did not find any milestone")
exit(1)
if (len(milestones) > 1):
print("found multiple milestons")
milestone_title = milestones[0]['title']
milestone = str(milestones[0]['id'])
print("Using Milestone \""+ milestone_title + "\" with id " + milestone)
milestone_prs = []
page = 1
last_count = 1;
while last_count != 0:
with urllib.request.urlopen("https://egit.irs.uni-stuttgart.de/api/v1/repos/fsfw/fsfw/pulls?state=closed&milestone=" + str(milestone) + "&limit=100&page=" + str(page)) as pull_requests_json:
pull_requests = json.load(pull_requests_json)
for pr in pull_requests:
milestone_prs.append({'number': str(pr['number']), 'title' : pr['title']})
page += 1
last_count = len(pull_requests)
print("Found " + str(len(milestone_prs)) + " closed PRs in Milestone")
print("looking for CHANGELOG.md ...")
path = Path(".")
files = list(path.glob("CHANGELOG.md"))
if (len(files) != 1):
files = list(path.glob("../CHANGELOG.md"))
if (len(files) != 1):
print("did not find CHANGELOG.md. Run script in either root directory or scripts subfolder.")
exit(1)
print("Scanning CHANGELOG.md ...")
changelog_prs = []
with open(files[0]) as changelog:
line = changelog.readline()
while (line):
#print("line: " + line)
match = re.search("\#.+(v[0-9]+\.[0-9]+\.[0-9]+)", line)
if (match):
if match.group(1) == version:
#print("found version")
line = changelog.readline()
continue
else:
#print("done with " + match.group(1))
break
match = re.search("PR: https://egit\.irs\.uni-stuttgart\.de/fsfw/fsfw/pulls/([0-9]+)", line)
if match:
changelog_prs.append(match.group(1))
line = changelog.readline()
print("Found " + str(len(changelog_prs)) + " PRs in CHANGELOG.md")
print("")
copy_array = changelog_prs.copy()
print("PRs in CHANGELOG.md that are not in Milestone:")
for pr in milestone_prs:
if pr['number'] in copy_array:
copy_array.remove(pr['number'])
for pr in copy_array:
print("https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/" + pr)
print("")
print("PRs in milestone that are not in CHANGELOG.md:")
for pr in milestone_prs:
if pr['number'] not in changelog_prs:
print("- " + pr['title'] + "\n PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/" + pr['number'])
main()

View File

@ -21,7 +21,7 @@ struct FileSize : public SerializeIF {
this->largeFile = isLarge; this->largeFile = isLarge;
return serialize(buffer, size, maxSize, streamEndianness); return serialize(buffer, size, maxSize, streamEndianness);
} }
using SerializeIF::serialize;
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const override { Endianness streamEndianness) const override {
if (not largeFile) { if (not largeFile) {

View File

@ -3,7 +3,7 @@
#include "fsfw/serialize/SerializeAdapter.h" #include "fsfw/serialize/SerializeAdapter.h"
#include "fsfw/serviceinterface.h" #include "fsfw/serviceinterface.h"
cfdp::VarLenField::VarLenField(cfdp::WidthInBytes width, size_t value) : VarLenField() { cfdp::VarLenField::VarLenField(cfdp::WidthInBytes width, uint64_t value) : VarLenField() {
ReturnValue_t result = this->setValue(width, value); ReturnValue_t result = this->setValue(width, value);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
#if FSFW_DISABLE_PRINTOUT == 0 #if FSFW_DISABLE_PRINTOUT == 0
@ -20,7 +20,7 @@ cfdp::VarLenField::VarLenField() : width(cfdp::WidthInBytes::ONE_BYTE) { value.o
cfdp::WidthInBytes cfdp::VarLenField::getWidth() const { return width; } cfdp::WidthInBytes cfdp::VarLenField::getWidth() const { return width; }
ReturnValue_t cfdp::VarLenField::setValue(cfdp::WidthInBytes widthInBytes, size_t value_) { ReturnValue_t cfdp::VarLenField::setValue(cfdp::WidthInBytes widthInBytes, uint64_t value_) {
switch (widthInBytes) { switch (widthInBytes) {
case (cfdp::WidthInBytes::ONE_BYTE): { case (cfdp::WidthInBytes::ONE_BYTE): {
if (value_ > UINT8_MAX) { if (value_ > UINT8_MAX) {
@ -51,7 +51,7 @@ ReturnValue_t cfdp::VarLenField::setValue(cfdp::WidthInBytes widthInBytes, size_
return returnvalue::OK; return returnvalue::OK;
} }
size_t cfdp::VarLenField::getValue() const { uint64_t cfdp::VarLenField::getValue() const {
switch (width) { switch (width) {
case (cfdp::WidthInBytes::ONE_BYTE): { case (cfdp::WidthInBytes::ONE_BYTE): {
return value.oneByte; return value.oneByte;

View File

@ -25,13 +25,13 @@ class VarLenField : public SerializeIF {
template <typename T> template <typename T>
explicit VarLenField(UnsignedByteField<T> byteField); explicit VarLenField(UnsignedByteField<T> byteField);
VarLenField(cfdp::WidthInBytes width, size_t value); VarLenField(cfdp::WidthInBytes width, uint64_t value);
bool operator==(const VarLenField &other) const; bool operator==(const VarLenField &other) const;
bool operator!=(const VarLenField &other) const; bool operator!=(const VarLenField &other) const;
bool operator<(const VarLenField &other) const; bool operator<(const VarLenField &other) const;
ReturnValue_t setValue(cfdp::WidthInBytes, size_t value); ReturnValue_t setValue(cfdp::WidthInBytes, uint64_t value);
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const override; Endianness streamEndianness) const override;
@ -42,7 +42,7 @@ class VarLenField : public SerializeIF {
Endianness streamEndianness); Endianness streamEndianness);
[[nodiscard]] cfdp::WidthInBytes getWidth() const; [[nodiscard]] cfdp::WidthInBytes getWidth() const;
[[nodiscard]] size_t getValue() const; [[nodiscard]] uint64_t getValue() const;
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
friend std::ostream &operator<<(std::ostream &os, const VarLenField &id) { friend std::ostream &operator<<(std::ostream &os, const VarLenField &id) {
@ -53,6 +53,7 @@ class VarLenField : public SerializeIF {
#endif #endif
private: private:
using SerializeIF::deSerialize;
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override; Endianness streamEndianness) override;

View File

@ -9,6 +9,11 @@
#include "fsfw/returnvalues/FwClassIds.h" #include "fsfw/returnvalues/FwClassIds.h"
#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/returnvalues/returnvalue.h"
// Thanks, windows
#ifdef NO_ERROR
#undef NO_ERROR
#endif
namespace cfdp { namespace cfdp {
static constexpr char CFDP_VERSION_2_NAME[] = "CCSDS 727.0-B-5"; static constexpr char CFDP_VERSION_2_NAME[] = "CCSDS 727.0-B-5";

View File

@ -42,6 +42,6 @@ size_t EofInfo::getSerializedSize(bool fssLarge) {
return size; return size;
} }
ReturnValue_t EofInfo::setFileSize(size_t fileSize, bool isLarge) { ReturnValue_t EofInfo::setFileSize(uint64_t fileSize, bool isLarge) {
return this->fileSize.setFileSize(fileSize, isLarge); return this->fileSize.setFileSize(fileSize, isLarge);
} }

View File

@ -21,7 +21,7 @@ struct EofInfo {
void setChecksum(uint32_t checksum); void setChecksum(uint32_t checksum);
void setConditionCode(cfdp::ConditionCode conditionCode); void setConditionCode(cfdp::ConditionCode conditionCode);
void setFaultLoc(EntityIdTlv* faultLoc); void setFaultLoc(EntityIdTlv* faultLoc);
ReturnValue_t setFileSize(size_t size, bool isLarge); ReturnValue_t setFileSize(uint64_t size, bool isLarge);
private: private:
cfdp::ConditionCode conditionCode; cfdp::ConditionCode conditionCode;

View File

@ -1,5 +1,10 @@
#include "FinishedPduReader.h" #include "FinishedPduReader.h"
// Thanks, windows
#ifdef NO_ERROR
#undef NO_ERROR
#endif
FinishPduReader::FinishPduReader(const uint8_t* pduBuf, size_t maxSize, FinishedInfo& info) FinishPduReader::FinishPduReader(const uint8_t* pduBuf, size_t maxSize, FinishedInfo& info)
: FileDirectiveReader(pduBuf, maxSize), finishedInfo(info) {} : FileDirectiveReader(pduBuf, maxSize), finishedInfo(info) {}

View File

@ -23,6 +23,7 @@ class EntityIdTlv : public TlvIF {
*/ */
ReturnValue_t deSerialize(cfdp::Tlv& tlv, Endianness endianness); ReturnValue_t deSerialize(cfdp::Tlv& tlv, Endianness endianness);
using SerializeIF::deSerialize;
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override; Endianness streamEndianness) override;

View File

@ -26,6 +26,7 @@ class FilestoreRequestTlv : public cfdp::FilestoreTlvBase {
*/ */
ReturnValue_t deSerialize(cfdp::Tlv &tlv, Endianness endianness); ReturnValue_t deSerialize(cfdp::Tlv &tlv, Endianness endianness);
using SerializeIF::deSerialize;
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override; Endianness streamEndianness) override;

View File

@ -29,6 +29,7 @@ class FilestoreResponseTlv : public cfdp::FilestoreTlvBase {
*/ */
ReturnValue_t deSerialize(const cfdp::Tlv& tlv, Endianness endianness); ReturnValue_t deSerialize(const cfdp::Tlv& tlv, Endianness endianness);
using SerializeIF::deSerialize;
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override; Endianness streamEndianness) override;

View File

@ -12,6 +12,7 @@ template <typename T, size_t MAX_SIZE, typename count_t = uint8_t>
class FixedArrayList : public ArrayList<T, count_t> { class FixedArrayList : public ArrayList<T, count_t> {
static_assert(MAX_SIZE <= std::numeric_limits<count_t>::max(), static_assert(MAX_SIZE <= std::numeric_limits<count_t>::max(),
"count_t is not large enough to hold MAX_SIZE"); "count_t is not large enough to hold MAX_SIZE");
static_assert(MAX_SIZE > 0, "MAX_SIZE is 0");
private: private:
T data[MAX_SIZE]; T data[MAX_SIZE];

View File

@ -364,6 +364,10 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
void printWarningOrError(sif::OutputTypes outputType, const char* functionName, void printWarningOrError(sif::OutputTypes outputType, const char* functionName,
ReturnValue_t errorCode = returnvalue::FAILED, ReturnValue_t errorCode = returnvalue::FAILED,
const char* errorPrint = nullptr); const char* errorPrint = nullptr);
private:
using ProvidesDataPoolSubscriptionIF::subscribeForPeriodicPacket;
using ProvidesDataPoolSubscriptionIF::subscribeForUpdatePacket;
}; };
template <class T> template <class T>

View File

@ -1,5 +1,6 @@
#include "fsfw/devicehandlers/DeviceHandlerBase.h" #include "fsfw/devicehandlers/DeviceHandlerBase.h"
#include "fsfw/datapool/PoolReadGuard.h"
#include "fsfw/datapoollocal/LocalPoolVariable.h" #include "fsfw/datapoollocal/LocalPoolVariable.h"
#include "fsfw/devicehandlers/AcceptsDeviceResponsesIF.h" #include "fsfw/devicehandlers/AcceptsDeviceResponsesIF.h"
#include "fsfw/devicehandlers/DeviceTmReportingWrapper.h" #include "fsfw/devicehandlers/DeviceTmReportingWrapper.h"
@ -321,8 +322,7 @@ void DeviceHandlerBase::doStateMachine() {
if (mode != currentMode) { if (mode != currentMode) {
break; break;
} }
uint32_t currentUptime; uint32_t currentUptime = Clock::getUptime_ms();
Clock::getUptime(&currentUptime);
if (currentUptime - timeoutStart >= childTransitionDelay) { if (currentUptime - timeoutStart >= childTransitionDelay) {
#if FSFW_VERBOSE_LEVEL >= 1 && FSFW_OBJ_EVENT_TRANSLATION == 0 #if FSFW_VERBOSE_LEVEL >= 1 && FSFW_OBJ_EVENT_TRANSLATION == 0
char printout[60]; char printout[60];
@ -346,8 +346,7 @@ void DeviceHandlerBase::doStateMachine() {
setMode(_MODE_WAIT_ON); setMode(_MODE_WAIT_ON);
break; break;
case _MODE_WAIT_ON: { case _MODE_WAIT_ON: {
uint32_t currentUptime; uint32_t currentUptime = Clock::getUptime_ms();
Clock::getUptime(&currentUptime);
if (powerSwitcher != nullptr and if (powerSwitcher != nullptr and
currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) { currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) {
triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0); triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0);
@ -366,8 +365,7 @@ void DeviceHandlerBase::doStateMachine() {
} }
} break; } break;
case _MODE_WAIT_OFF: { case _MODE_WAIT_OFF: {
uint32_t currentUptime; uint32_t currentUptime = Clock::getUptime_ms();
Clock::getUptime(&currentUptime);
if (powerSwitcher == nullptr) { if (powerSwitcher == nullptr) {
setMode(MODE_OFF); setMode(MODE_OFF);
@ -577,7 +575,7 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
modeHelper.modeChanged(newMode, newSubmode); modeHelper.modeChanged(newMode, newSubmode);
announceMode(false); announceMode(false);
} }
Clock::getUptime(&timeoutStart); timeoutStart = Clock::getUptime_ms();
if (mode == MODE_OFF and thermalSet != nullptr) { if (mode == MODE_OFF and thermalSet != nullptr) {
ReturnValue_t result = thermalSet->read(); ReturnValue_t result = thermalSet->read();
@ -1508,7 +1506,10 @@ DeviceCommandId_t DeviceHandlerBase::getPendingCommand() const {
void DeviceHandlerBase::setNormalDatapoolEntriesInvalid() { void DeviceHandlerBase::setNormalDatapoolEntriesInvalid() {
for (const auto& reply : deviceReplyMap) { for (const auto& reply : deviceReplyMap) {
if (reply.second.dataSet != nullptr) { if (reply.second.dataSet != nullptr) {
reply.second.dataSet->setValidity(false, true); PoolReadGuard pg(reply.second.dataSet);
if (pg.getReadResult() == returnvalue::OK) {
reply.second.dataSet->setValidity(false, true);
}
} }
} }
} }

View File

@ -206,9 +206,9 @@ class DeviceHandlerBase : public DeviceHandlerIF,
Mode_t getTransitionSourceMode() const; Mode_t getTransitionSourceMode() const;
Submode_t getTransitionSourceSubMode() const; Submode_t getTransitionSourceSubMode() const;
virtual void getMode(Mode_t *mode, Submode_t *submode); virtual void getMode(Mode_t *mode, Submode_t *submode) override;
HealthState getHealth(); HealthState getHealth() override;
ReturnValue_t setHealth(HealthState health); ReturnValue_t setHealth(HealthState health) override;
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper, ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, const ParameterWrapper *newValues,
@ -1073,7 +1073,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
bool forceDirectTm = false); bool forceDirectTm = false);
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode); uint32_t *msToReachTheMode) override;
virtual ReturnValue_t letChildHandleMessage(CommandMessage *message); virtual ReturnValue_t letChildHandleMessage(CommandMessage *message);

View File

@ -15,11 +15,12 @@ const LocalPool::LocalPoolConfig EventManager::poolConfig = {
{fsfwconfig::FSFW_EVENTMGMT_EVENTIDMATCHERS, sizeof(EventIdRangeMatcher)}, {fsfwconfig::FSFW_EVENTMGMT_EVENTIDMATCHERS, sizeof(EventIdRangeMatcher)},
{fsfwconfig::FSFW_EVENTMGMR_RANGEMATCHERS, sizeof(ReporterRangeMatcher)}}; {fsfwconfig::FSFW_EVENTMGMR_RANGEMATCHERS, sizeof(ReporterRangeMatcher)}};
EventManager::EventManager(object_id_t setObjectId) EventManager::EventManager(object_id_t setObjectId, uint32_t eventQueueDepth)
: SystemObject(setObjectId), factoryBackend(0, poolConfig, false, true) { : SystemObject(setObjectId), factoryBackend(0, poolConfig, false, true) {
mutex = MutexFactory::instance()->createMutex(); mutex = MutexFactory::instance()->createMutex();
eventReportQueue = QueueFactory::instance()->createMessageQueue(MAX_EVENTS_PER_CYCLE, auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
EventMessage::EVENT_MESSAGE_SIZE); eventReportQueue = QueueFactory::instance()->createMessageQueue(
eventQueueDepth, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
} }
EventManager::~EventManager() { EventManager::~EventManager() {
@ -47,9 +48,20 @@ ReturnValue_t EventManager::performOperation(uint8_t opCode) {
void EventManager::notifyListeners(EventMessage* message) { void EventManager::notifyListeners(EventMessage* message) {
lockMutex(); lockMutex();
for (auto iter = listenerList.begin(); iter != listenerList.end(); ++iter) { for (auto& listener : listenerList) {
if (iter->second.match(message)) { if (listener.second.match(message)) {
MessageQueueSenderIF::sendMessage(iter->first, message, message->getSender()); ReturnValue_t result =
MessageQueueSenderIF::sendMessage(listener.first, message, message->getSender());
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << std::hex << "EventManager::notifyListeners: MSG to 0x" << std::setfill('0')
<< std::setw(8) << listener.first << " failed with result 0x" << std::setw(4)
<< result << std::setfill(' ') << std::endl;
#else
sif::printError("Sending message to listener 0x%08x failed with result %04x\n",
listener.first, result);
#endif
}
} }
} }
unlockMutex(); unlockMutex();
@ -200,4 +212,19 @@ void EventManager::printUtility(sif::OutputTypes printType, EventMessage* messag
} }
} }
void EventManager::printListeners() {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "Event manager listener MQ IDs:" << std::setfill('0') << std::hex << std::endl;
for (auto& listener : listenerList) {
sif::info << "0x" << std::setw(8) << listener.first << std::endl;
}
sif::info << std::dec << std::setfill(' ');
#else
sif::printInfo("Event manager listener MQ IDs:\n");
for (auto& listener : listenerList) {
sif::printInfo("0x%08x\n", listener.first);
}
#endif
}
#endif /* FSFW_OBJ_EVENT_TRANSLATION == 1 */ #endif /* FSFW_OBJ_EVENT_TRANSLATION == 1 */

View File

@ -21,29 +21,32 @@ extern const char* translateEvents(Event event);
class EventManager : public EventManagerIF, public ExecutableObjectIF, public SystemObject { class EventManager : public EventManagerIF, public ExecutableObjectIF, public SystemObject {
public: public:
static const uint16_t MAX_EVENTS_PER_CYCLE = 80;
EventManager(object_id_t setObjectId); EventManager(object_id_t setObjectId, uint32_t eventQueueDepth);
virtual ~EventManager(); virtual ~EventManager();
void setMutexTimeout(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs); void setMutexTimeout(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs);
MessageQueueId_t getEventReportQueue(); MessageQueueId_t getEventReportQueue() override;
ReturnValue_t registerListener(MessageQueueId_t listener, bool forwardAllButSelected = false); ReturnValue_t registerListener(MessageQueueId_t listener,
bool forwardAllButSelected = false) override;
ReturnValue_t unregisterListener(MessageQueueId_t listener) override; ReturnValue_t unregisterListener(MessageQueueId_t listener) override;
ReturnValue_t subscribeToEvent(MessageQueueId_t listener, EventId_t event); ReturnValue_t subscribeToEvent(MessageQueueId_t listener, EventId_t event) override;
ReturnValue_t subscribeToAllEventsFrom(MessageQueueId_t listener, object_id_t object); ReturnValue_t subscribeToAllEventsFrom(MessageQueueId_t listener, object_id_t object) override;
ReturnValue_t subscribeToEventRange(MessageQueueId_t listener, EventId_t idFrom = 0, ReturnValue_t subscribeToEventRange(MessageQueueId_t listener, EventId_t idFrom = 0,
EventId_t idTo = 0, bool idInverted = false, EventId_t idTo = 0, bool idInverted = false,
object_id_t reporterFrom = 0, object_id_t reporterTo = 0, object_id_t reporterFrom = 0, object_id_t reporterTo = 0,
bool reporterInverted = false); bool reporterInverted = false) override;
ReturnValue_t unsubscribeFromAllEvents(MessageQueueId_t listener, object_id_t object); ReturnValue_t unsubscribeFromAllEvents(MessageQueueId_t listener, object_id_t object) override;
ReturnValue_t unsubscribeFromEventRange(MessageQueueId_t listener, EventId_t idFrom = 0, ReturnValue_t unsubscribeFromEventRange(MessageQueueId_t listener, EventId_t idFrom = 0,
EventId_t idTo = 0, bool idInverted = false, EventId_t idTo = 0, bool idInverted = false,
object_id_t reporterFrom = 0, object_id_t reporterTo = 0, object_id_t reporterFrom = 0, object_id_t reporterTo = 0,
bool reporterInverted = false); bool reporterInverted = false) override;
ReturnValue_t performOperation(uint8_t opCode); ReturnValue_t performOperation(uint8_t opCode) override;
void printListeners();
protected: protected:
MessageQueueIF* eventReportQueue = nullptr; MessageQueueIF* eventReportQueue = nullptr;

View File

@ -10,7 +10,7 @@ enum : uint8_t {
CDH = 28, CDH = 28,
TCS_1 = 59, TCS_1 = 59,
PCDU_1 = 42, PCDU_1 = 42,
PCDU_2 = 43, POWER_SWITCH_IF = 43,
HEATER = 50, HEATER = 50,
T_SENSORS = 52, T_SENSORS = 52,
FDIR = 70, FDIR = 70,
@ -33,6 +33,7 @@ enum : uint8_t {
PUS_SERVICE_23 = 103, PUS_SERVICE_23 = 103,
MGM_LIS3MDL = 106, MGM_LIS3MDL = 106,
MGM_RM3100 = 107, MGM_RM3100 = 107,
CFDP = 108,
FW_SUBSYSTEM_ID_RANGE FW_SUBSYSTEM_ID_RANGE
}; };

View File

@ -52,6 +52,7 @@ ReturnValue_t DleParser::parseRingBuf(size_t& readSize) {
// without skipping the STX // without skipping the STX
readSize = vectorIdx; readSize = vectorIdx;
ErrorInfo info; ErrorInfo info;
info.len = vectorIdx;
setErrorContext(ErrorTypes::CONSECUTIVE_STX_CHARS, info); setErrorContext(ErrorTypes::CONSECUTIVE_STX_CHARS, info);
return POSSIBLE_PACKET_LOSS; return POSSIBLE_PACKET_LOSS;
} }

View File

@ -58,7 +58,7 @@ class Type : public SerializeIF {
template <typename T> template <typename T>
struct PodTypeConversion { struct PodTypeConversion {
static_assert(not std::is_same<T, bool>::value, static_assert(!std::is_same<T, bool>::value,
"Do not use boolean for the PoolEntry type, use uint8_t " "Do not use boolean for the PoolEntry type, use uint8_t "
"instead! The ECSS standard defines a boolean as a one bit " "instead! The ECSS standard defines a boolean as a one bit "
"field. Therefore it is preferred to store a boolean as an " "field. Therefore it is preferred to store a boolean as an "

View File

@ -37,16 +37,16 @@ void arrayprinter::print(const uint8_t *data, size_t size, OutputType type, bool
} }
} }
void arrayprinter::printHex(const uint8_t *data, size_t size, size_t maxCharPerLine) { void arrayprinter::printHex(const uint8_t *data, size_t datasize, size_t maxCharPerLine) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
if (sif::info.crAdditionEnabled()) { if (sif::info.crAdditionEnabled()) {
std::cout << "\r" << std::endl; std::cout << "\r" << std::endl;
} }
std::cout << "hex [" << std::setfill('0') << std::hex; std::cout << "hex [" << std::setfill('0') << std::hex;
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < datasize; i++) {
std::cout << std::setw(2) << static_cast<int>(data[i]); std::cout << std::setw(2) << static_cast<int>(data[i]);
if (i < size - 1) { if (i < datasize - 1) {
std::cout << ","; std::cout << ",";
if (i > 0 and (i + 1) % maxCharPerLine == 0) { if (i > 0 and (i + 1) % maxCharPerLine == 0) {
std::cout << std::endl; std::cout << std::endl;
@ -56,27 +56,11 @@ void arrayprinter::printHex(const uint8_t *data, size_t size, size_t maxCharPerL
std::cout << std::dec << std::setfill(' '); std::cout << std::dec << std::setfill(' ');
std::cout << "]" << std::endl; std::cout << "]" << std::endl;
#else #else
// General format: 0x01, 0x02, 0x03 so it is number of chars times 6 printf("hex [");
// plus line break plus small safety margin. for (size_t i = 0; i < datasize; i++) {
char printBuffer[(size + 1) * 7 + 1] = {}; printf("0x%02x ", data[i]);
size_t currentPos = 0;
for (size_t i = 0; i < size; i++) {
// To avoid buffer overflows.
if (sizeof(printBuffer) - currentPos <= 7) {
break;
}
currentPos += snprintf(printBuffer + currentPos, 6, "%02x", data[i]);
if (i < size - 1) {
currentPos += sprintf(printBuffer + currentPos, ",");
if ((i + 1) % maxCharPerLine == 0) {
currentPos += sprintf(printBuffer + currentPos, "\n");
}
}
} }
#if FSFW_DISABLE_PRINTOUT == 0 printf("]\n");
printf("hex [%s]\n", printBuffer);
#endif /* FSFW_DISABLE_PRINTOUT == 0 */
#endif #endif
} }
@ -100,26 +84,10 @@ void arrayprinter::printDec(const uint8_t *data, size_t size, size_t maxCharPerL
#else #else
// General format: 32,243,-12 so it is number of chars times 4 // General format: 32,243,-12 so it is number of chars times 4
// plus line break plus small safety margin. // plus line break plus small safety margin.
uint16_t expectedLines = ceil((double)size / maxCharPerLine);
char printBuffer[size * 4 + 1 + expectedLines] = {};
size_t currentPos = 0;
for (size_t i = 0; i < size; i++) {
// To avoid buffer overflows.
if (sizeof(printBuffer) - currentPos <= 4) {
break;
}
currentPos += snprintf(printBuffer + currentPos, 4, "%d", data[i]); for (size_t i = 0; i < size; i++) {
if (i < size - 1) { // TODO
currentPos += sprintf(printBuffer + currentPos, ",");
if ((i + 1) % maxCharPerLine == 0) {
currentPos += sprintf(printBuffer + currentPos, "\n");
}
}
} }
#if FSFW_DISABLE_PRINTOUT == 0
printf("dec [%s]\n", printBuffer);
#endif /* FSFW_DISABLE_PRINTOUT == 0 */
#endif #endif
} }

View File

@ -16,26 +16,24 @@ class HasHealthIF {
}; };
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_HEALTH_IF; static const uint8_t INTERFACE_ID = CLASS_ID::HAS_HEALTH_IF;
static const ReturnValue_t OBJECT_NOT_HEALTHY = MAKE_RETURN_CODE(1); static constexpr ReturnValue_t OBJECT_NOT_HEALTHY = returnvalue::makeCode(INTERFACE_ID, 1);
static const ReturnValue_t INVALID_HEALTH_STATE = MAKE_RETURN_CODE(2); static constexpr ReturnValue_t INVALID_HEALTH_STATE = returnvalue::makeCode(INTERFACE_ID, 2);
static constexpr ReturnValue_t IS_EXTERNALLY_CONTROLLED = returnvalue::makeCode(INTERFACE_ID, 3);
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_MANAGER_1; static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_MANAGER_1;
//! P1: New Health, P2: Old Health
static const Event HEALTH_INFO = MAKE_EVENT(6, severity::INFO); static const Event HEALTH_INFO = MAKE_EVENT(6, severity::INFO);
static const Event CHILD_CHANGED_HEALTH = MAKE_EVENT(7, severity::INFO); static const Event CHILD_CHANGED_HEALTH = MAKE_EVENT(7, severity::INFO);
static const Event CHILD_PROBLEMS = MAKE_EVENT(8, severity::LOW); static const Event CHILD_PROBLEMS = MAKE_EVENT(8, severity::LOW);
static const Event OVERWRITING_HEALTH = //! Assembly overwrites health information of children to keep satellite alive.
MAKE_EVENT(9, severity::LOW); //!< Assembly overwrites health information of children to keep static const Event OVERWRITING_HEALTH = MAKE_EVENT(9, severity::LOW);
//!< satellite alive. //! Someone starts a recovery of a component (typically power-cycle). No parameters.
static const Event TRYING_RECOVERY = static const Event TRYING_RECOVERY = MAKE_EVENT(10, severity::MEDIUM);
MAKE_EVENT(10, severity::MEDIUM); //!< Someone starts a recovery of a component (typically //! Recovery is ongoing. Comes twice during recovery.
//!< power-cycle). No parameters. //! P1: 0 for the first, 1 for the second event. P2: 0
static const Event RECOVERY_STEP = static const Event RECOVERY_STEP = MAKE_EVENT(11, severity::MEDIUM);
MAKE_EVENT(11, severity::MEDIUM); //!< Recovery is ongoing. Comes twice during recovery. P1: //! Recovery was completed. Not necessarily successful. No parameters.
//!< 0 for the first, 1 for the second event. P2: 0 static const Event RECOVERY_DONE = MAKE_EVENT(12, severity::MEDIUM);
static const Event RECOVERY_DONE = MAKE_EVENT(
12,
severity::MEDIUM); //!< Recovery was completed. Not necessarily successful. No parameters.
virtual ~HasHealthIF() {} virtual ~HasHealthIF() {}
virtual MessageQueueId_t getCommandQueue() const = 0; virtual MessageQueueId_t getCommandQueue() const = 0;

View File

@ -8,6 +8,8 @@
#include "HealthTableIF.h" #include "HealthTableIF.h"
class HealthTable : public HealthTableIF, public SystemObject { class HealthTable : public HealthTableIF, public SystemObject {
friend class CServiceHealthCommanding;
public: public:
explicit HealthTable(object_id_t objectid); explicit HealthTable(object_id_t objectid);
~HealthTable() override; ~HealthTable() override;

View File

@ -55,7 +55,7 @@ class HousekeepingSnapshot : public SerializeIF {
: timeStamp(timeStamp), timeStampSize(timeStampSize), updateData(dataSetPtr){}; : timeStamp(timeStamp), timeStampSize(timeStampSize), updateData(dataSetPtr){};
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const { Endianness streamEndianness) const override {
if (timeStamp != nullptr) { if (timeStamp != nullptr) {
/* Endianness will always be MACHINE, so we can simply use memcpy /* Endianness will always be MACHINE, so we can simply use memcpy
here. */ here. */
@ -70,7 +70,7 @@ class HousekeepingSnapshot : public SerializeIF {
return updateData->serialize(buffer, size, maxSize, streamEndianness); return updateData->serialize(buffer, size, maxSize, streamEndianness);
} }
virtual size_t getSerializedSize() const { virtual size_t getSerializedSize() const override {
if (updateData == nullptr) { if (updateData == nullptr) {
return 0; return 0;
} }

View File

@ -7,10 +7,10 @@
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth) InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth)
: SystemObject(setObjectId), : SystemObject(setObjectId),
commandQueue(QueueFactory::instance()->createMessageQueue(messageQueueDepth)),
poolManager(this, commandQueue), poolManager(this, commandQueue),
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID), internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
internalErrorDataset(this) { internalErrorDataset(this) {
commandQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
mutex = MutexFactory::instance()->createMutex(); mutex = MutexFactory::instance()->createMutex();
} }

View File

@ -24,3 +24,19 @@ void ModeMessage::setCantReachMode(CommandMessage* message, ReturnValue_t reason
message->setParameter(reason); message->setParameter(reason);
message->setParameter2(0); message->setParameter2(0);
} }
void ModeMessage::setModeAnnounceMessage(CommandMessage& message, bool recursive) {
Command_t cmd;
if (recursive) {
cmd = CMD_MODE_ANNOUNCE_RECURSIVELY;
} else {
cmd = CMD_MODE_ANNOUNCE;
}
message.setCommand(cmd);
}
void ModeMessage::setCmdModeMessage(CommandMessage& message, Mode_t mode, Submode_t submode) {
setModeMessage(&message, CMD_MODE_COMMAND, mode, submode);
}
void ModeMessage::setModeReadMessage(CommandMessage& message) { message.setCommand(CMD_MODE_READ); }

View File

@ -45,6 +45,9 @@ class ModeMessage {
static void setModeMessage(CommandMessage* message, Command_t command, Mode_t mode, static void setModeMessage(CommandMessage* message, Command_t command, Mode_t mode,
Submode_t submode); Submode_t submode);
static void setCmdModeMessage(CommandMessage& message, Mode_t mode, Submode_t submode);
static void setModeAnnounceMessage(CommandMessage& message, bool recursive);
static void setModeReadMessage(CommandMessage& message);
static void setCantReachMode(CommandMessage* message, ReturnValue_t reason); static void setCantReachMode(CommandMessage* message, ReturnValue_t reason);
static void clear(CommandMessage* message); static void clear(CommandMessage* message);
}; };

View File

@ -18,7 +18,7 @@ class AbsLimitMonitor : public MonitorBase<T> {
violationEvent(violationEvent), violationEvent(violationEvent),
aboveIsViolation(aboveIsViolation) {} aboveIsViolation(aboveIsViolation) {}
virtual ~AbsLimitMonitor() {} virtual ~AbsLimitMonitor() {}
virtual ReturnValue_t checkSample(T sample, T *crossedLimit) { ReturnValue_t checkSample(T sample, T *crossedLimit) override {
*crossedLimit = limit; *crossedLimit = limit;
if (aboveIsViolation) { if (aboveIsViolation) {
if ((std::abs(sample) > limit)) { if ((std::abs(sample) > limit)) {
@ -32,9 +32,9 @@ class AbsLimitMonitor : public MonitorBase<T> {
return returnvalue::OK; // We're not out of range. return returnvalue::OK; // We're not out of range.
} }
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, ReturnValue_t getParameter(uint8_t domainId, uint8_t parameterId,
ParameterWrapper *parameterWrapper, ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
const ParameterWrapper *newValues, uint16_t startAtIndex) { uint16_t startAtIndex) override {
ReturnValue_t result = this->MonitorBase<T>::getParameter( ReturnValue_t result = this->MonitorBase<T>::getParameter(
domainId, parameterId, parameterWrapper, newValues, startAtIndex); domainId, parameterId, parameterWrapper, newValues, startAtIndex);
// We'll reuse the DOMAIN_ID of MonitorReporter, // We'll reuse the DOMAIN_ID of MonitorReporter,
@ -61,7 +61,7 @@ class AbsLimitMonitor : public MonitorBase<T> {
void setLimit(T value) { limit = value; } void setLimit(T value) { limit = value; }
protected: protected:
void sendTransitionEvent(T currentValue, ReturnValue_t state) { void sendTransitionEvent(T currentValue, ReturnValue_t state) override {
switch (state) { switch (state) {
case MonitoringIF::OUT_OF_RANGE: case MonitoringIF::OUT_OF_RANGE:
EventManagerIF::triggerEvent(this->reportingId, violationEvent, this->globalPoolId.objectId, EventManagerIF::triggerEvent(this->reportingId, violationEvent, this->globalPoolId.objectId,

View File

@ -18,7 +18,10 @@ elseif(FSFW_OSAL MATCHES "host")
endif() endif()
set(FSFW_OSAL_HOST 1) set(FSFW_OSAL_HOST 1)
else() else()
message(WARNING "The OS_FSFW variable was not set. Assuming host OS..") message(
WARNING
"${MSG_PREFIX} The FSFW_OSAL variable was not set. Assuming host OS..")
# Not set. Assumuing this is a host build, try to determine host OS # Not set. Assumuing this is a host build, try to determine host OS
if(WIN32) if(WIN32)
add_subdirectory(host) add_subdirectory(host)

View File

@ -24,8 +24,11 @@
#else #else
#ifdef WIN32 #ifdef WIN32
#include <windows.h> // Thanks, windows
// clang-format off
#include <winsock2.h> #include <winsock2.h>
#include <windows.h>
// clang-format on
#if REG_DWORD == REG_DWORD_LITTLE_ENDIAN #if REG_DWORD == REG_DWORD_LITTLE_ENDIAN
#define BYTE_ORDER_SYSTEM LITTLE_ENDIAN #define BYTE_ORDER_SYSTEM LITTLE_ENDIAN
#else #else

View File

@ -40,6 +40,8 @@ int TcpIpBase::closeSocket(socket_t socket) {
return closesocket(socket); return closesocket(socket);
#elif defined(PLATFORM_UNIX) #elif defined(PLATFORM_UNIX)
return close(socket); return close(socket);
#else
return -1;
#endif #endif
} }
@ -48,5 +50,7 @@ int TcpIpBase::getLastSocketError() {
return WSAGetLastError(); return WSAGetLastError();
#elif defined(PLATFORM_UNIX) #elif defined(PLATFORM_UNIX)
return errno; return errno;
#else
return 0;
#endif #endif
} }

View File

@ -16,9 +16,9 @@
#endif #endif
TcpTmTcBridge::TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination, object_id_t tmStoreId, TcpTmTcBridge::TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
object_id_t tcStoreId) uint32_t msgQueueDepth, object_id_t tmStoreId, object_id_t tcStoreId)
: TmTcBridge("TCP TMTC Bridge", objectId, tcDestination, tmStoreId, tcStoreId) { : TmTcBridge("TCP TMTC Bridge", objectId, tcDestination, msgQueueDepth, tmStoreId, tcStoreId) {
mutex = MutexFactory::instance()->createMutex(); mutex = MutexFactory::instance()->createMutex();
// Connection is always up, TM is requested by connecting to server and receiving packets // Connection is always up, TM is requested by connecting to server and receiving packets
registerCommConnect(); registerCommConnect();

View File

@ -38,7 +38,7 @@ class TcpTmTcBridge : public TmTcBridge {
* @param tmStoreId TM store object ID. It is recommended to the default object ID * @param tmStoreId TM store object ID. It is recommended to the default object ID
* @param tcStoreId TC store object ID. It is recommended to the default object ID * @param tcStoreId TC store object ID. It is recommended to the default object ID
*/ */
TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination, TcpTmTcBridge(object_id_t objectId, object_id_t tcDestination, uint32_t msgQueueDepth,
object_id_t tmStoreId = objects::TM_STORE, object_id_t tmStoreId = objects::TM_STORE,
object_id_t tcStoreId = objects::TC_STORE); object_id_t tcStoreId = objects::TC_STORE);
virtual ~TcpTmTcBridge(); virtual ~TcpTmTcBridge();

View File

@ -16,7 +16,7 @@
#ifdef PLATFORM_WIN #ifdef PLATFORM_WIN
#include <winsock2.h> #include <winsock2.h>
#include <ws2tcpip.h> typedef SSIZE_T ssize_t;
#elif defined(PLATFORM_UNIX) #elif defined(PLATFORM_UNIX)
#include <netdb.h> #include <netdb.h>
@ -26,12 +26,12 @@
const std::string TcpTmTcServer::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT; const std::string TcpTmTcServer::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
TcpTmTcServer::TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge, TcpTmTcServer::TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge,
size_t receptionBufferSize, size_t ringBufferSize, TcpTmTcServer::TcpConfig cfg, size_t receptionBufferSize,
std::string customTcpServerPort, ReceptionModes receptionMode) size_t ringBufferSize, ReceptionModes receptionMode)
: SystemObject(objectId), : SystemObject(objectId),
tmtcBridgeId(tmtcTcpBridge), tmtcBridgeId(tmtcTcpBridge),
receptionMode(receptionMode), receptionMode(receptionMode),
tcpConfig(std::move(customTcpServerPort)), tcpConfig(cfg),
receptionBuffer(receptionBufferSize), receptionBuffer(receptionBufferSize),
ringBuffer(ringBufferSize, true) {} ringBuffer(ringBufferSize, true) {}
@ -91,6 +91,25 @@ ReturnValue_t TcpTmTcServer::initialize() {
return returnvalue::FAILED; return returnvalue::FAILED;
} }
if (tcpConfig.reuseAddr) {
#ifdef PLATFORM_WIN
DWORD enable = 1;
setsockopt(listenerTcpSocket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&enable),
sizeof(enable));
#elif defined(PLATFORM_UNIX)
unsigned int enable = 1;
setsockopt(listenerTcpSocket, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
#endif
}
if (tcpConfig.reusePort) {
// Not supported in windows
#ifdef PLATFORM_UNIX
unsigned int enable = 1;
setsockopt(listenerTcpSocket, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable));
#endif
}
// Bind to the address found by getaddrinfo // Bind to the address found by getaddrinfo
retval = bind(listenerTcpSocket, addrResult->ai_addr, static_cast<int>(addrResult->ai_addrlen)); retval = bind(listenerTcpSocket, addrResult->ai_addr, static_cast<int>(addrResult->ai_addrlen));
if (retval == SOCKET_ERROR) { if (retval == SOCKET_ERROR) {

View File

@ -41,11 +41,11 @@ class SpacePacketParser;
*/ */
class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableObjectIF { class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableObjectIF {
public: public:
enum class ReceptionModes { SPACE_PACKETS };
struct TcpConfig { struct TcpConfig {
public: public:
explicit TcpConfig(std::string tcpPort) : tcpPort(std::move(tcpPort)) {} TcpConfig(bool reuseAddr, bool reusePort) : reuseAddr(reuseAddr), reusePort(reusePort) {}
TcpConfig(std::string tcpPort, bool reuseAddr, bool reusePort)
: tcpPort(std::move(tcpPort)), reuseAddr(reuseAddr), reusePort(reusePort) {}
/** /**
* Passed to the recv call * Passed to the recv call
@ -63,8 +63,23 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
*/ */
int tcpTmFlags = 0; int tcpTmFlags = 0;
const std::string tcpPort; std::string tcpPort = DEFAULT_SERVER_PORT;
/**
* Sets the SO_REUSEADDR option on the socket. See
* https://man7.org/linux/man-pages/man7/socket.7.html for more details. This option is
* especially useful in a debugging and development environment where an OBSW image might be
* re-flashed oftentimes and where all incoming telecommands are received on a dedicated TCP
* port.
*/
bool reuseAddr = false;
/**
* Sets the SO_REUSEPORT option on the socket. See
* https://man7.org/linux/man-pages/man7/socket.7.html for more details.
*/
bool reusePort = false;
}; };
enum class ReceptionModes { SPACE_PACKETS };
static const std::string DEFAULT_SERVER_PORT; static const std::string DEFAULT_SERVER_PORT;
@ -80,10 +95,9 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
* size will be the Ethernet MTU size * size will be the Ethernet MTU size
* @param customTcpServerPort The user can specify another port than the default (7301) here. * @param customTcpServerPort The user can specify another port than the default (7301) here.
*/ */
TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge, TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge, TcpTmTcServer::TcpConfig cfg,
size_t receptionBufferSize = RING_BUFFER_SIZE, size_t receptionBufferSize = RING_BUFFER_SIZE,
size_t ringBufferSize = RING_BUFFER_SIZE, size_t ringBufferSize = RING_BUFFER_SIZE,
std::string customTcpServerPort = DEFAULT_SERVER_PORT,
ReceptionModes receptionMode = ReceptionModes::SPACE_PACKETS); ReceptionModes receptionMode = ReceptionModes::SPACE_PACKETS);
~TcpTmTcServer() override; ~TcpTmTcServer() override;
@ -116,7 +130,7 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
ReceptionModes receptionMode; ReceptionModes receptionMode;
TcpConfig tcpConfig; TcpConfig tcpConfig;
struct sockaddr tcpAddress = {}; // struct sockaddr tcpAddress = {};
socket_t listenerTcpSocket = 0; socket_t listenerTcpSocket = 0;
MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE; MessageQueueId_t targetTcDestination = MessageQueueIF::NO_QUEUE;

View File

@ -8,6 +8,7 @@
#ifdef PLATFORM_WIN #ifdef PLATFORM_WIN
#include <winsock2.h> #include <winsock2.h>
typedef SSIZE_T ssize_t;
#elif defined(PLATFORM_UNIX) #elif defined(PLATFORM_UNIX)
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/types.h> #include <sys/types.h>

View File

@ -7,6 +7,7 @@
#ifdef PLATFORM_WIN #ifdef PLATFORM_WIN
#include <ws2tcpip.h> #include <ws2tcpip.h>
typedef SSIZE_T ssize_t;
#elif defined(PLATFORM_UNIX) #elif defined(PLATFORM_UNIX)
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
@ -20,9 +21,9 @@
const std::string UdpTmTcBridge::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT; const std::string UdpTmTcBridge::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
UdpTmTcBridge::UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination, UdpTmTcBridge::UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
const std::string &udpServerPort_, object_id_t tmStoreId, uint32_t msgQueueDepth, const std::string &udpServerPort_,
object_id_t tcStoreId) object_id_t tmStoreId, object_id_t tcStoreId)
: TmTcBridge("UDP TMTC Bridge", objectId, tcDestination, tmStoreId, tcStoreId) { : TmTcBridge("UDP TMTC Bridge", objectId, tcDestination, msgQueueDepth, tmStoreId, tcStoreId) {
if (udpServerPort_.empty()) { if (udpServerPort_.empty()) {
udpServerPort = DEFAULT_SERVER_PORT; udpServerPort = DEFAULT_SERVER_PORT;
} else { } else {
@ -126,10 +127,7 @@ ReturnValue_t UdpTmTcBridge::sendTm(const uint8_t *data, size_t dataLen) {
tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::SENDTO_CALL); tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::SENDTO_CALL);
} }
#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1
sif::debug << "TmTcUdpBridge::sendTm: " << bytesSent sif::debug << "TmTcUdpBridge::sendTm: " << bytesSent << " bytes were sent" << std::endl;
<< " bytes were"
" sent."
<< std::endl;
#endif #endif
return returnvalue::OK; return returnvalue::OK;
} }

View File

@ -29,7 +29,7 @@ class UdpTmTcBridge : public TmTcBridge, public TcpIpBase {
/* The ports chosen here should not be used by any other process. */ /* The ports chosen here should not be used by any other process. */
static const std::string DEFAULT_SERVER_PORT; static const std::string DEFAULT_SERVER_PORT;
UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination, UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination, uint32_t msgQueueDepth,
const std::string& udpServerPort = "", object_id_t tmStoreId = objects::TM_STORE, const std::string& udpServerPort = "", object_id_t tmStoreId = objects::TM_STORE,
object_id_t tcStoreId = objects::TC_STORE); object_id_t tcStoreId = objects::TC_STORE);
~UdpTmTcBridge() override; ~UdpTmTcBridge() override;

View File

@ -11,19 +11,6 @@
// TODO sanitize input? // TODO sanitize input?
// TODO much of this code can be reused for tick-only systems // TODO much of this code can be reused for tick-only systems
uint32_t Clock::getTicksPerSecond(void) { return 1000; }
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
timeval time_timeval;
ReturnValue_t result = convertTimeOfDayToTimeval(time, &time_timeval);
if (result != returnvalue::OK) {
return result;
}
return setClock(&time_timeval);
}
ReturnValue_t Clock::setClock(const timeval* time) { ReturnValue_t Clock::setClock(const timeval* time) {
timeval uptime = getUptime(); timeval uptime = getUptime();
@ -44,83 +31,12 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
return returnvalue::OK; return returnvalue::OK;
} }
ReturnValue_t Clock::getUptime(timeval* uptime) {
*uptime = getUptime();
return returnvalue::OK;
}
timeval Clock::getUptime() { timeval Clock::getUptime() {
TickType_t ticksSinceStart = xTaskGetTickCount(); TickType_t ticksSinceStart = xTaskGetTickCount();
return Timekeeper::ticksToTimeval(ticksSinceStart); return Timekeeper::ticksToTimeval(ticksSinceStart);
} }
ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
timeval uptime = getUptime();
*uptimeMs = uptime.tv_sec * 1000 + uptime.tv_usec / 1000;
return returnvalue::OK;
}
// uint32_t Clock::getUptimeSeconds() { // uint32_t Clock::getUptimeSeconds() {
// timeval uptime = getUptime(); // timeval uptime = getUptime();
// return uptime.tv_sec; // return uptime.tv_sec;
// } // }
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
timeval time_timeval;
ReturnValue_t result = getClock_timeval(&time_timeval);
if (result != returnvalue::OK) {
return result;
}
*time = time_timeval.tv_sec * 1000000 + time_timeval.tv_usec;
return returnvalue::OK;
}
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
timeval time_timeval;
ReturnValue_t result = getClock_timeval(&time_timeval);
if (result != returnvalue::OK) {
return result;
}
struct tm time_tm;
gmtime_r(&time_timeval.tv_sec, &time_tm);
time->year = time_tm.tm_year + 1900;
time->month = time_tm.tm_mon + 1;
time->day = time_tm.tm_mday;
time->hour = time_tm.tm_hour;
time->minute = time_tm.tm_min;
time->second = time_tm.tm_sec;
time->usecond = time_timeval.tv_usec;
return returnvalue::OK;
}
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to) {
struct tm time_tm = {};
time_tm.tm_year = from->year - 1900;
time_tm.tm_mon = from->month - 1;
time_tm.tm_mday = from->day;
time_tm.tm_hour = from->hour;
time_tm.tm_min = from->minute;
time_tm.tm_sec = from->second;
time_tm.tm_isdst = 0;
time_t seconds = timegm(&time_tm);
to->tv_sec = seconds;
to->tv_usec = from->usecond;
return returnvalue::OK;
}
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
*JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.;
return returnvalue::OK;
}

View File

@ -15,27 +15,6 @@
using SystemClock = std::chrono::system_clock; using SystemClock = std::chrono::system_clock;
uint32_t Clock::getTicksPerSecond(void) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Clock::getTicksPerSecond: Not implemented for host OSAL" << std::endl;
#else
sif::printWarning("Clock::getTicksPerSecond: Not implemented for host OSAL\n");
#endif
/* To avoid division by zero */
return 1;
}
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
/* I don't know why someone would need to set a clock which is probably perfectly fine on a
host system with internet access so this is not implemented for now. */
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Clock::setClock: Not implemented for host OSAL" << std::endl;
#else
sif::printWarning("Clock::setClock: Not implemented for host OSAL\n");
#endif
return returnvalue::OK;
}
ReturnValue_t Clock::setClock(const timeval* time) { ReturnValue_t Clock::setClock(const timeval* time) {
/* I don't know why someone would need to set a clock which is probably perfectly fine on a /* I don't know why someone would need to set a clock which is probably perfectly fine on a
host system with internet access so this is not implemented for now. */ host system with internet access so this is not implemented for now. */
@ -66,6 +45,7 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
time->tv_usec = timeUnix.tv_nsec / 1000.0; time->tv_usec = timeUnix.tv_nsec / 1000.0;
return returnvalue::OK; return returnvalue::OK;
#else #else
#warning Clock::getClock_timeval() not implemented for your platform
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Clock::getUptime: Not implemented for found OS!" << std::endl; sif::warning << "Clock::getUptime: Not implemented for found OS!" << std::endl;
#else #else
@ -75,15 +55,6 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
#endif #endif
} }
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
if (time == nullptr) {
return returnvalue::FAILED;
}
using namespace std::chrono;
*time = duration_cast<microseconds>(system_clock::now().time_since_epoch()).count();
return returnvalue::OK;
}
timeval Clock::getUptime() { timeval Clock::getUptime() {
timeval timeval; timeval timeval;
#if defined(PLATFORM_WIN) #if defined(PLATFORM_WIN)
@ -100,73 +71,10 @@ timeval Clock::getUptime() {
timeval.tv_usec = uptimeSeconds * (double)1e6 - (timeval.tv_sec * 1e6); timeval.tv_usec = uptimeSeconds * (double)1e6 - (timeval.tv_sec * 1e6);
} }
#else #else
#warning Clock::getUptime() not implemented for your platform
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl; sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl;
#endif #endif
#endif #endif
return timeval; return timeval;
} }
ReturnValue_t Clock::getUptime(timeval* uptime) {
*uptime = getUptime();
return returnvalue::OK;
}
ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
timeval uptime = getUptime();
*uptimeMs = uptime.tv_sec * 1000 + uptime.tv_usec / 1000;
return returnvalue::OK;
}
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
/* Do some magic with chrono (C++20!) */
/* Right now, the library doesn't have the new features to get the required values yet.
so we work around that for now. */
auto now = SystemClock::now();
auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(now);
auto fraction = now - seconds;
time_t tt = SystemClock::to_time_t(now);
ReturnValue_t result = checkOrCreateClockMutex();
if (result != returnvalue::OK) {
return result;
}
MutexGuard helper(timeMutex);
// gmtime writes its output in a global buffer which is not Thread Safe
// Therefore we have to use a Mutex here
struct tm* timeInfo;
timeInfo = gmtime(&tt);
time->year = timeInfo->tm_year + 1900;
time->month = timeInfo->tm_mon + 1;
time->day = timeInfo->tm_mday;
time->hour = timeInfo->tm_hour;
time->minute = timeInfo->tm_min;
time->second = timeInfo->tm_sec;
auto usecond = std::chrono::duration_cast<std::chrono::microseconds>(fraction);
time->usecond = usecond.count();
return returnvalue::OK;
}
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to) {
struct tm time_tm {};
time_tm.tm_year = from->year - 1900;
time_tm.tm_mon = from->month - 1;
time_tm.tm_mday = from->day;
time_tm.tm_hour = from->hour;
time_tm.tm_min = from->minute;
time_tm.tm_sec = from->second;
time_tm.tm_isdst = 0;
time_t seconds = timegm(&time_tm);
to->tv_sec = seconds;
to->tv_usec = from->usecond;
// Fails in 2038..
return returnvalue::OK;
}
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
*JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.;
return returnvalue::OK;
}

View File

@ -9,7 +9,6 @@
#include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/serviceinterface/ServiceInterface.h"
#if defined(PLATFORM_WIN) #if defined(PLATFORM_WIN)
#include <processthreadsapi.h>
#include "fsfw/osal/windows/winTaskHelpers.h" #include "fsfw/osal/windows/winTaskHelpers.h"
#elif defined(PLATFORM_UNIX) #elif defined(PLATFORM_UNIX)

View File

@ -50,6 +50,6 @@ void TaskFactory::printMissedDeadline() {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TaskFactory::printMissedDeadline: " << name << std::endl; sif::warning << "TaskFactory::printMissedDeadline: " << name << std::endl;
#else #else
sif::printWarning("TaskFactory::printMissedDeadline: %s\n", name); sif::printWarning("TaskFactory::printMissedDeadline: %s\n", name.c_str());
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */ #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
} }

View File

@ -3,6 +3,7 @@
#include <fsfw/returnvalues/returnvalue.h> #include <fsfw/returnvalues/returnvalue.h>
#include <string>
#include <thread> #include <thread>
namespace tasks { namespace tasks {

View File

@ -10,26 +10,6 @@
#include "fsfw/ipc/MutexGuard.h" #include "fsfw/ipc/MutexGuard.h"
#include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/serviceinterface/ServiceInterface.h"
uint32_t Clock::getTicksPerSecond() {
uint32_t ticks = sysconf(_SC_CLK_TCK);
return ticks;
}
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
timespec timeUnix{};
timeval timeTimeval{};
convertTimeOfDayToTimeval(time, &timeTimeval);
timeUnix.tv_sec = timeTimeval.tv_sec;
timeUnix.tv_nsec = (__syscall_slong_t)timeTimeval.tv_usec * 1000;
int status = clock_settime(CLOCK_REALTIME, &timeUnix);
if (status != 0) {
// TODO errno
return returnvalue::FAILED;
}
return returnvalue::OK;
}
ReturnValue_t Clock::setClock(const timeval* time) { ReturnValue_t Clock::setClock(const timeval* time) {
timespec timeUnix{}; timespec timeUnix{};
timeUnix.tv_sec = time->tv_sec; timeUnix.tv_sec = time->tv_sec;
@ -53,104 +33,22 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
return returnvalue::OK; return returnvalue::OK;
} }
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
timeval timeVal{};
ReturnValue_t result = getClock_timeval(&timeVal);
if (result != returnvalue::OK) {
return result;
}
*time = static_cast<uint64_t>(timeVal.tv_sec) * 1e6 + timeVal.tv_usec;
return returnvalue::OK;
}
timeval Clock::getUptime() { timeval Clock::getUptime() {
timeval uptime{}; timeval uptime{};
auto result = getUptime(&uptime);
if (result != returnvalue::OK) { double uptimeSeconds;
std::ifstream ifile("/proc/uptime");
if (ifile.bad()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Clock::getUptime: Error getting uptime" << std::endl; sif::error << "Clock::getUptime: Error getting uptime" << std::endl;
#endif #endif
return uptime;
}
if (ifile >> uptimeSeconds) {
uptime.tv_sec = uptimeSeconds;
uptime.tv_usec = (uptimeSeconds - uptime.tv_sec) * (double)1e6;
} }
return uptime; return uptime;
} }
ReturnValue_t Clock::getUptime(timeval* uptime) {
// TODO This is not posix compatible and delivers only seconds precision
// Linux specific file read but more precise.
double uptimeSeconds;
if (std::ifstream("/proc/uptime", std::ios::in) >> uptimeSeconds) {
uptime->tv_sec = uptimeSeconds;
uptime->tv_usec = uptimeSeconds * (double)1e6 - (uptime->tv_sec * 1e6);
}
return returnvalue::OK;
}
// Wait for new FSFW Clock function delivering seconds uptime.
// uint32_t Clock::getUptimeSeconds() {
// //TODO This is not posix compatible and delivers only seconds precision
// struct sysinfo sysInfo;
// int result = sysinfo(&sysInfo);
// if(result != 0){
// return returnvalue::FAILED;
// }
// return sysInfo.uptime;
//}
ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
timeval uptime{};
ReturnValue_t result = getUptime(&uptime);
if (result != returnvalue::OK) {
return result;
}
*uptimeMs = uptime.tv_sec * 1e3 + uptime.tv_usec / 1e3;
return returnvalue::OK;
}
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
timespec timeUnix{};
int status = clock_gettime(CLOCK_REALTIME, &timeUnix);
if (status != 0) {
// TODO errno
return returnvalue::FAILED;
}
ReturnValue_t result = checkOrCreateClockMutex();
if (result != returnvalue::OK) {
return result;
}
MutexGuard helper(timeMutex);
// gmtime writes its output in a global buffer which is not Thread Safe
// Therefore we have to use a Mutex here
struct std::tm* timeInfo;
timeInfo = gmtime(&timeUnix.tv_sec);
time->year = timeInfo->tm_year + 1900;
time->month = timeInfo->tm_mon + 1;
time->day = timeInfo->tm_mday;
time->hour = timeInfo->tm_hour;
time->minute = timeInfo->tm_min;
time->second = timeInfo->tm_sec;
time->usecond = timeUnix.tv_nsec / 1000.0;
return returnvalue::OK;
}
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to) {
std::tm fromTm{};
// Note: Fails for years before AD
fromTm.tm_year = from->year - 1900;
fromTm.tm_mon = from->month - 1;
fromTm.tm_mday = from->day;
fromTm.tm_hour = from->hour;
fromTm.tm_min = from->minute;
fromTm.tm_sec = from->second;
fromTm.tm_isdst = 0;
to->tv_sec = timegm(&fromTm);
to->tv_usec = from->usecond;
return returnvalue::OK;
}
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
*JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.;
return returnvalue::OK;
}

View File

@ -2,6 +2,8 @@
#include <rtems/rtems/sem.h> #include <rtems/rtems/sem.h>
// TODO
BinarySemaphore::BinarySemaphore() {} BinarySemaphore::BinarySemaphore() {}
BinarySemaphore::~BinarySemaphore() {} BinarySemaphore::~BinarySemaphore() {}

View File

@ -6,20 +6,21 @@
#include "fsfw/ipc/MutexGuard.h" #include "fsfw/ipc/MutexGuard.h"
#include "fsfw/osal/rtems/RtemsBasic.h" #include "fsfw/osal/rtems/RtemsBasic.h"
uint32_t Clock::getTicksPerSecond(void) { ReturnValue_t Clock::setClock(const timeval* time) {
rtems_interval ticks_per_second = rtems_clock_get_ticks_per_second(); TimeOfDay_t time_tod;
return static_cast<uint32_t>(ticks_per_second); ReturnValue_t result = convertTimevalToTimeOfDay(time, &time_tod);
} if (result != returnvalue::OK) {
return result;
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) { }
rtems_time_of_day timeRtems; rtems_time_of_day timeRtems;
timeRtems.year = time->year; timeRtems.year = time_tod.year;
timeRtems.month = time->month; timeRtems.month = time_tod.month;
timeRtems.day = time->day; timeRtems.day = time_tod.day;
timeRtems.hour = time->hour; timeRtems.hour = time_tod.hour;
timeRtems.minute = time->minute; timeRtems.minute = time_tod.minute;
timeRtems.second = time->second; timeRtems.second = time_tod.second;
timeRtems.ticks = time->usecond * getTicksPerSecond() / 1e6; timeRtems.ticks =
static_cast<uint64_t>(time_tod.usecond) * rtems_clock_get_ticks_per_second() / 1e6;
rtems_status_code status = rtems_clock_set(&timeRtems); rtems_status_code status = rtems_clock_set(&timeRtems);
switch (status) { switch (status) {
case RTEMS_SUCCESSFUL: case RTEMS_SUCCESSFUL:
@ -33,27 +34,6 @@ ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
} }
} }
ReturnValue_t Clock::setClock(const timeval* time) {
timespec newTime;
newTime.tv_sec = time->tv_sec;
if (time->tv_usec < 0) {
// better returnvalue.
return returnvalue::FAILED;
}
newTime.tv_nsec = time->tv_usec * TOD_NANOSECONDS_PER_MICROSECOND;
ISR_lock_Context context;
_TOD_Lock();
_TOD_Acquire(&context);
Status_Control status = _TOD_Set(&newTime, &context);
_TOD_Unlock();
if (status == STATUS_SUCCESSFUL) {
return returnvalue::OK;
}
// better returnvalue
return returnvalue::FAILED;
}
ReturnValue_t Clock::getClock_timeval(timeval* time) { ReturnValue_t Clock::getClock_timeval(timeval* time) {
// Callable from ISR // Callable from ISR
rtems_status_code status = rtems_clock_get_tod_timeval(time); rtems_status_code status = rtems_clock_get_tod_timeval(time);
@ -67,86 +47,13 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
} }
} }
ReturnValue_t Clock::getUptime(timeval* uptime) { timeval Clock::getUptime() {
// According to docs.rtems.org for rtems 5 this method is more accurate than // According to docs.rtems.org for rtems 5 this method is more accurate than
// rtems_clock_get_ticks_since_boot // rtems_clock_get_ticks_since_boot
timeval time_timeval;
timespec time; timespec time;
rtems_status_code status = rtems_clock_get_uptime(&time); rtems_status_code status = rtems_clock_get_uptime(&time);
uptime->tv_sec = time.tv_sec; time_timeval.tv_sec = time.tv_sec;
time.tv_nsec = time.tv_nsec / 1000; time_timeval.tv_usec = time.tv_nsec / 1000;
uptime->tv_usec = time.tv_nsec; return time_timeval;
switch (status) { }
case RTEMS_SUCCESSFUL:
return returnvalue::OK;
default:
return returnvalue::FAILED;
}
}
ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
// This counter overflows after 50 days
*uptimeMs = rtems_clock_get_ticks_since_boot();
return returnvalue::OK;
}
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
timeval temp_time;
rtems_status_code returnValue = rtems_clock_get_tod_timeval(&temp_time);
*time = ((uint64_t)temp_time.tv_sec * 1000000) + temp_time.tv_usec;
switch (returnValue) {
case RTEMS_SUCCESSFUL:
return returnvalue::OK;
default:
return returnvalue::FAILED;
}
}
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
/* For all but the last field, the struct will be filled with the correct values */
rtems_time_of_day timeRtems;
rtems_status_code status = rtems_clock_get_tod(&timeRtems);
switch (status) {
case RTEMS_SUCCESSFUL: {
/* The last field now contains the RTEMS ticks of the seconds from 0
to rtems_clock_get_ticks_per_second() minus one.
We calculate the microseconds accordingly */
time->day = timeRtems.day;
time->hour = timeRtems.hour;
time->minute = timeRtems.minute;
time->month = timeRtems.month;
time->second = timeRtems.second;
time->usecond =
static_cast<float>(timeRtems.ticks) / rtems_clock_get_ticks_per_second() * 1e6;
time->year = timeRtems.year;
return returnvalue::OK;
}
case RTEMS_NOT_DEFINED:
/* System date and time is not set */
return returnvalue::FAILED;
case RTEMS_INVALID_ADDRESS:
/* time_buffer is NULL */
return returnvalue::FAILED;
default:
return returnvalue::FAILED;
}
}
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to) {
// Fails in 2038..
rtems_time_of_day timeRtems;
timeRtems.year = from->year;
timeRtems.month = from->month;
timeRtems.day = from->day;
timeRtems.hour = from->hour;
timeRtems.minute = from->minute;
timeRtems.second = from->second;
timeRtems.ticks = from->usecond * getTicksPerSecond() / 1e6;
to->tv_sec = _TOD_To_seconds(&timeRtems);
to->tv_usec = from->usecond;
return returnvalue::OK;
}
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
*JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.;
return returnvalue::OK;
}

View File

@ -93,8 +93,8 @@ ReturnValue_t CpuUsage::serialize(uint8_t** buffer, size_t* size, size_t maxSize
streamEndianness); streamEndianness);
} }
uint32_t CpuUsage::getSerializedSize() const { size_t CpuUsage::getSerializedSize() const {
uint32_t size = 0; size_t size = 0;
size += sizeof(timeSinceLastReset); size += sizeof(timeSinceLastReset);
size += SerialArrayListAdapter<ThreadData>::getSerializedSize(&threadData); size += SerialArrayListAdapter<ThreadData>::getSerializedSize(&threadData);
@ -136,8 +136,8 @@ ReturnValue_t CpuUsage::ThreadData::serialize(uint8_t** buffer, size_t* size, si
return returnvalue::OK; return returnvalue::OK;
} }
uint32_t CpuUsage::ThreadData::getSerializedSize() const { size_t CpuUsage::ThreadData::getSerializedSize() const {
uint32_t size = 0; size_t size = 0;
size += sizeof(id); size += sizeof(id);
size += MAX_LENGTH_OF_THREAD_NAME; size += MAX_LENGTH_OF_THREAD_NAME;

View File

@ -35,20 +35,19 @@ ReturnValue_t InternalErrorCodes::translate(uint8_t code) {
return OUT_OF_PROXIES; return OUT_OF_PROXIES;
case INTERNAL_ERROR_INVALID_GLOBAL_ID: case INTERNAL_ERROR_INVALID_GLOBAL_ID:
return INVALID_GLOBAL_ID; return INVALID_GLOBAL_ID;
#ifndef STM32H743ZI_NUCLEO // TODO this one is not there anymore in rtems-6 (5 as well?)
case INTERNAL_ERROR_BAD_STACK_HOOK: // case INTERNAL_ERROR_BAD_STACK_HOOK:
return BAD_STACK_HOOK; // return BAD_STACK_HOOK;
#endif // case INTERNAL_ERROR_BAD_ATTRIBUTES:
// case INTERNAL_ERROR_BAD_ATTRIBUTES: // return BAD_ATTRIBUTES;
// return BAD_ATTRIBUTES; // case INTERNAL_ERROR_IMPLEMENTATION_KEY_CREATE_INCONSISTENCY:
// case INTERNAL_ERROR_IMPLEMENTATION_KEY_CREATE_INCONSISTENCY: // return IMPLEMENTATION_KEY_CREATE_INCONSISTENCY;
// return IMPLEMENTATION_KEY_CREATE_INCONSISTENCY; // case INTERNAL_ERROR_IMPLEMENTATION_BLOCKING_OPERATION_CANCEL:
// case INTERNAL_ERROR_IMPLEMENTATION_BLOCKING_OPERATION_CANCEL: // return IMPLEMENTATION_BLOCKING_OPERATION_CANCEL;
// return IMPLEMENTATION_BLOCKING_OPERATION_CANCEL; // case INTERNAL_ERROR_MUTEX_OBTAIN_FROM_BAD_STATE:
// case INTERNAL_ERROR_MUTEX_OBTAIN_FROM_BAD_STATE: // return MUTEX_OBTAIN_FROM_BAD_STATE;
// return MUTEX_OBTAIN_FROM_BAD_STATE; // case INTERNAL_ERROR_UNLIMITED_AND_MAXIMUM_IS_0:
// case INTERNAL_ERROR_UNLIMITED_AND_MAXIMUM_IS_0: // return UNLIMITED_AND_MAXIMUM_IS_0;
// return UNLIMITED_AND_MAXIMUM_IS_0;
default: default:
return returnvalue::FAILED; return returnvalue::FAILED;
} }

View File

@ -1,5 +1,5 @@
#include "fsfw/osal/rtems/BinarySemaphore.h" #include "fsfw/osal/rtems/BinarySemaphore.h"
//#include "fsfw/osal/rtems/CountingSemaphore.h" // #include "fsfw/osal/rtems/CountingSemaphore.h"
#include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw/tasks/SemaphoreFactory.h" #include "fsfw/tasks/SemaphoreFactory.h"
@ -18,7 +18,9 @@ SemaphoreFactory* SemaphoreFactory::instance() {
} }
SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t argument) { SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t argument) {
return new BinarySemaphore(); return nullptr;
// TODO
// return new BinarySemaphore();
} }
SemaphoreIF* SemaphoreFactory::createCountingSemaphore(uint8_t maxCount, uint8_t initCount, SemaphoreIF* SemaphoreFactory::createCountingSemaphore(uint8_t maxCount, uint8_t initCount,

View File

@ -5,7 +5,11 @@
#ifdef _WIN32 #ifdef _WIN32
#include <minwindef.h> // Thanks, windows
// clang-format off
#include <windows.h>
#include <processthreadsapi.h>
// clang-format on
namespace tasks { namespace tasks {

View File

@ -45,6 +45,7 @@ class ParameterWrapper : public SerializeIF {
virtual size_t getSerializedSize() const override; virtual size_t getSerializedSize() const override;
using SerializeIF::deSerialize;
virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override; Endianness streamEndianness) override;

View File

@ -32,7 +32,7 @@ class Fuse : public SystemObject,
gp_id_t poolIdPower; gp_id_t poolIdPower;
}; };
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_1; static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::POWER_SWITCH_IF;
//! PSS detected that current on a fuse is totally out of bounds. //! PSS detected that current on a fuse is totally out of bounds.
static const Event FUSE_CURRENT_HIGH = MAKE_EVENT(1, severity::LOW); static const Event FUSE_CURRENT_HIGH = MAKE_EVENT(1, severity::LOW);
//! PSS detected a fuse that went off. //! PSS detected a fuse that went off.
@ -62,13 +62,13 @@ class Fuse : public SystemObject,
SerializeIF::Endianness streamEndianness) override; SerializeIF::Endianness streamEndianness) override;
void setAllMonitorsToUnchecked(); void setAllMonitorsToUnchecked();
ReturnValue_t performOperation(uint8_t opCode); ReturnValue_t performOperation(uint8_t opCode);
MessageQueueId_t getCommandQueue() const; MessageQueueId_t getCommandQueue() const override;
void setDataPoolEntriesInvalid(); void setDataPoolEntriesInvalid();
ReturnValue_t setHealth(HealthState health); ReturnValue_t setHealth(HealthState health) override;
HasHealthIF::HealthState getHealth(); HasHealthIF::HealthState getHealth() override;
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper *parameterWrapper, ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex); const ParameterWrapper *newValues, uint16_t startAtIndex) override;
private: private:
uint8_t oldFuseState; uint8_t oldFuseState;

View File

@ -10,15 +10,15 @@ class PowerComponent : public PowerComponentIF {
PowerComponent(object_id_t setId, uint8_t moduleId, float minPower, float maxPower, PowerComponent(object_id_t setId, uint8_t moduleId, float minPower, float maxPower,
uint8_t switchId1, bool twoSwitches = false, uint8_t switchId2 = 0xFF); uint8_t switchId1, bool twoSwitches = false, uint8_t switchId2 = 0xFF);
virtual object_id_t getDeviceObjectId(); object_id_t getDeviceObjectId() override;
virtual uint8_t getSwitchId1(); uint8_t getSwitchId1() override;
virtual uint8_t getSwitchId2(); uint8_t getSwitchId2() override;
bool hasTwoSwitches(); bool hasTwoSwitches() override;
float getMin(); float getMin() override;
float getMax(); float getMax() override;
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override; Endianness streamEndianness) const override;
@ -29,7 +29,7 @@ class PowerComponent : public PowerComponentIF {
Endianness streamEndianness) override; Endianness streamEndianness) override;
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper* parameterWrapper, ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper* parameterWrapper,
const ParameterWrapper* newValues, uint16_t startAtIndex); const ParameterWrapper* newValues, uint16_t startAtIndex) override;
private: private:
const object_id_t deviceObjectId = objects::NO_OBJECT; const object_id_t deviceObjectId = objects::NO_OBJECT;

View File

@ -28,10 +28,12 @@ class PowerSwitchIF {
static const ReturnValue_t SWITCH_TIMEOUT = MAKE_RETURN_CODE(2); static const ReturnValue_t SWITCH_TIMEOUT = MAKE_RETURN_CODE(2);
static const ReturnValue_t FUSE_ON = MAKE_RETURN_CODE(3); static const ReturnValue_t FUSE_ON = MAKE_RETURN_CODE(3);
static const ReturnValue_t FUSE_OFF = MAKE_RETURN_CODE(4); static const ReturnValue_t FUSE_OFF = MAKE_RETURN_CODE(4);
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_2; static const ReturnValue_t SWITCH_UNKNOWN = MAKE_RETURN_CODE(5);
static const Event SWITCH_WENT_OFF = MAKE_EVENT(
0, severity::LOW); //!< Someone detected that a switch went off which shouldn't. Severity: static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::POWER_SWITCH_IF;
//!< Low, Parameter1: switchId1, Parameter2: switchId2 //!< Someone detected that a switch went off which shouldn't. Severity:
//!< Low, Parameter1: switchId1, Parameter2: switchId2
static const Event SWITCH_WENT_OFF = MAKE_EVENT(0, severity::LOW);
/** /**
* send a direct command to the Power Unit to enable/disable the specified switch. * send a direct command to the Power Unit to enable/disable the specified switch.
* *
@ -50,6 +52,7 @@ class PowerSwitchIF {
* @return * @return
* - @c SWITCH_ON if the specified switch is on. * - @c SWITCH_ON if the specified switch is on.
* - @c SWITCH_OFF if the specified switch is off. * - @c SWITCH_OFF if the specified switch is off.
* - @c SWITCH_UNKNOWN if the state of the specified switch is unknown.
* - @c returnvalue::FAILED if an error occured * - @c returnvalue::FAILED if an error occured
*/ */
virtual ReturnValue_t getSwitchState(power::Switch_t switchNr) const = 0; virtual ReturnValue_t getSwitchState(power::Switch_t switchNr) const = 0;

View File

@ -9,4 +9,4 @@ target_sources(
Service17Test.cpp Service17Test.cpp
Service20ParameterManagement.cpp Service20ParameterManagement.cpp
CService200ModeCommanding.cpp CService200ModeCommanding.cpp
CService201HealthCommanding.cpp) CServiceHealthCommanding.cpp)

View File

@ -19,7 +19,8 @@ ReturnValue_t CService200ModeCommanding::isValidSubservice(uint8_t subservice) {
switch (subservice) { switch (subservice) {
case (Subservice::COMMAND_MODE_COMMAND): case (Subservice::COMMAND_MODE_COMMAND):
case (Subservice::COMMAND_MODE_READ): case (Subservice::COMMAND_MODE_READ):
case (Subservice::COMMAND_MODE_ANNCOUNCE): case (Subservice::COMMAND_MODE_ANNOUNCE):
case (Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY):
return returnvalue::OK; return returnvalue::OK;
default: default:
return AcceptsTelecommandsIF::INVALID_SUBSERVICE; return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
@ -53,16 +54,32 @@ ReturnValue_t CService200ModeCommanding::checkInterfaceAndAcquireMessageQueue(
ReturnValue_t CService200ModeCommanding::prepareCommand(CommandMessage *message, uint8_t subservice, ReturnValue_t CService200ModeCommanding::prepareCommand(CommandMessage *message, uint8_t subservice,
const uint8_t *tcData, size_t tcDataLen, const uint8_t *tcData, size_t tcDataLen,
uint32_t *state, object_id_t objectId) { uint32_t *state, object_id_t objectId) {
ModePacket modeCommandPacket; bool recursive = false;
ReturnValue_t result = switch (subservice) {
modeCommandPacket.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG); case (Subservice::COMMAND_MODE_COMMAND): {
if (result != returnvalue::OK) { ModePacket modeCommandPacket;
return result; ReturnValue_t result =
} modeCommandPacket.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
if (result != returnvalue::OK) {
return result;
}
ModeMessage::setModeMessage(message, ModeMessage::CMD_MODE_COMMAND, modeCommandPacket.getMode(), ModeMessage::setModeMessage(message, ModeMessage::CMD_MODE_COMMAND,
modeCommandPacket.getSubmode()); modeCommandPacket.getMode(), modeCommandPacket.getSubmode());
return result; return returnvalue::OK;
}
case (Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY):
recursive = true;
[[fallthrough]];
case (Subservice::COMMAND_MODE_ANNOUNCE):
ModeMessage::setModeAnnounceMessage(*message, recursive);
return EXECUTION_COMPLETE;
case (Subservice::COMMAND_MODE_READ):
ModeMessage::setModeReadMessage(*message);
return returnvalue::OK;
default:
return CommandingServiceBase::INVALID_SUBSERVICE;
}
} }
ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply, ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply,
@ -73,8 +90,10 @@ ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply
ReturnValue_t result = returnvalue::FAILED; ReturnValue_t result = returnvalue::FAILED;
switch (replyId) { switch (replyId) {
case (ModeMessage::REPLY_MODE_REPLY): { case (ModeMessage::REPLY_MODE_REPLY): {
result = prepareModeReply(reply, objectId); if (previousCommand != ModeMessage::CMD_MODE_COMMAND) {
break; return prepareModeReply(reply, objectId);
}
return returnvalue::OK;
} }
case (ModeMessage::REPLY_WRONG_MODE_REPLY): { case (ModeMessage::REPLY_WRONG_MODE_REPLY): {
result = prepareWrongModeReply(reply, objectId); result = prepareWrongModeReply(reply, objectId);

View File

@ -52,7 +52,7 @@ class CService200ModeCommanding : public CommandingServiceBase {
COMMAND_MODE_READ = 3, COMMAND_MODE_READ = 3,
//!< [EXPORT] : [COMMAND] Trigger an ModeInfo Event. //!< [EXPORT] : [COMMAND] Trigger an ModeInfo Event.
//! This command does NOT have a reply //! This command does NOT have a reply
COMMAND_MODE_ANNCOUNCE = 4, COMMAND_MODE_ANNOUNCE = 4,
//!< [EXPORT] : [COMMAND] Trigger a ModeInfo Event and to send this //!< [EXPORT] : [COMMAND] Trigger a ModeInfo Event and to send this
//! command to every child. This command does NOT have a reply. //! command to every child. This command does NOT have a reply.
COMMAND_MODE_ANNOUNCE_RECURSIVELY = 5, COMMAND_MODE_ANNOUNCE_RECURSIVELY = 5,

View File

@ -1,106 +0,0 @@
#include "fsfw/pus/CService201HealthCommanding.h"
#include "fsfw/health/HasHealthIF.h"
#include "fsfw/health/HealthMessage.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/pus/servicepackets/Service201Packets.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
CService201HealthCommanding::CService201HealthCommanding(object_id_t objectId, uint16_t apid,
uint8_t serviceId,
uint8_t numParallelCommands,
uint16_t commandTimeoutSeconds)
: CommandingServiceBase(objectId, apid, "PUS 201 Health MGMT", serviceId, numParallelCommands,
commandTimeoutSeconds) {}
ReturnValue_t CService201HealthCommanding::isValidSubservice(uint8_t subservice) {
switch (subservice) {
case (Subservice::COMMAND_SET_HEALTH):
case (Subservice::COMMAND_ANNOUNCE_HEALTH):
case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL):
return returnvalue::OK;
default:
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Invalid Subservice" << std::endl;
#endif
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
}
}
ReturnValue_t CService201HealthCommanding::getMessageQueueAndObject(uint8_t subservice,
const uint8_t *tcData,
size_t tcDataLen,
MessageQueueId_t *id,
object_id_t *objectId) {
if (tcDataLen < sizeof(object_id_t)) {
return CommandingServiceBase::INVALID_TC;
}
SerializeAdapter::deSerialize(objectId, &tcData, &tcDataLen, SerializeIF::Endianness::BIG);
return checkInterfaceAndAcquireMessageQueue(id, objectId);
}
ReturnValue_t CService201HealthCommanding::checkInterfaceAndAcquireMessageQueue(
MessageQueueId_t *messageQueueToSet, const object_id_t *objectId) {
auto *destination = ObjectManager::instance()->get<HasHealthIF>(*objectId);
if (destination == nullptr) {
return CommandingServiceBase::INVALID_OBJECT;
}
*messageQueueToSet = destination->getCommandQueue();
return returnvalue::OK;
}
ReturnValue_t CService201HealthCommanding::prepareCommand(CommandMessage *message,
uint8_t subservice, const uint8_t *tcData,
size_t tcDataLen, uint32_t *state,
object_id_t objectId) {
ReturnValue_t result = returnvalue::OK;
switch (subservice) {
case (Subservice::COMMAND_SET_HEALTH): {
HealthSetCommand healthCommand;
result = healthCommand.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
if (result != returnvalue::OK) {
break;
}
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_SET,
healthCommand.getHealth());
break;
}
case (Subservice::COMMAND_ANNOUNCE_HEALTH): {
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE);
break;
}
case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): {
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE_ALL);
break;
}
default: {
// Should never happen, subservice was already checked
result = returnvalue::FAILED;
}
}
return result;
}
ReturnValue_t CService201HealthCommanding::handleReply(const CommandMessage *reply,
Command_t previousCommand, uint32_t *state,
CommandMessage *optionalNextCommand,
object_id_t objectId, bool *isStep) {
Command_t replyId = reply->getCommand();
if (replyId == HealthMessage::REPLY_HEALTH_SET) {
return EXECUTION_COMPLETE;
} else if (replyId == CommandMessageIF::REPLY_REJECTED) {
return reply->getReplyRejectedReason();
}
return CommandingServiceBase::INVALID_REPLY;
}
// Not used for now, health state already reported by event
[[maybe_unused]] ReturnValue_t CService201HealthCommanding::prepareHealthSetReply(
const CommandMessage *reply) {
auto health = static_cast<uint8_t>(HealthMessage::getHealth(reply));
auto oldHealth = static_cast<uint8_t>(HealthMessage::getOldHealth(reply));
HealthSetReply healthSetReply(health, oldHealth);
return sendTmPacket(Subservice::REPLY_HEALTH_SET, healthSetReply);
}

View File

@ -0,0 +1,161 @@
#include <fsfw/events/EventManagerIF.h>
#include <fsfw/pus/CServiceHealthCommanding.h>
#include "fsfw/health/HasHealthIF.h"
#include "fsfw/health/HealthMessage.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/pus/servicepackets/Service201Packets.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
CServiceHealthCommanding::CServiceHealthCommanding(HealthServiceCfg args)
: CommandingServiceBase(args.objectId, args.apid, "PUS 201 Health MGMT", args.service,
args.numParallelCommands, args.commandTimeoutSeconds),
healthTableId(args.table),
maxNumHealthInfoPerCycle(args.maxNumHealthInfoPerCycle) {}
ReturnValue_t CServiceHealthCommanding::initialize() {
ReturnValue_t result = CommandingServiceBase::initialize();
if (result != returnvalue::OK) {
return result;
}
healthTable = ObjectManager::instance()->get<HealthTable>(healthTableId);
if (healthTable == nullptr) {
return returnvalue::FAILED;
}
return returnvalue::OK;
}
ReturnValue_t CServiceHealthCommanding::isValidSubservice(uint8_t subservice) {
switch (subservice) {
case (Subservice::COMMAND_SET_HEALTH):
case (Subservice::COMMAND_ANNOUNCE_HEALTH):
case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL):
return returnvalue::OK;
default:
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Invalid Subservice" << std::endl;
#endif
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
}
}
ReturnValue_t CServiceHealthCommanding::getMessageQueueAndObject(uint8_t subservice,
const uint8_t *tcData,
size_t tcDataLen,
MessageQueueId_t *id,
object_id_t *objectId) {
switch (subservice) {
case (Subservice::COMMAND_SET_HEALTH):
case (Subservice::COMMAND_ANNOUNCE_HEALTH): {
if (tcDataLen < sizeof(object_id_t)) {
return CommandingServiceBase::INVALID_TC;
}
SerializeAdapter::deSerialize(objectId, &tcData, &tcDataLen, SerializeIF::Endianness::BIG);
return checkInterfaceAndAcquireMessageQueue(id, objectId);
}
case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): {
return returnvalue::OK;
}
default: {
return returnvalue::FAILED;
}
}
}
ReturnValue_t CServiceHealthCommanding::checkInterfaceAndAcquireMessageQueue(
MessageQueueId_t *messageQueueToSet, const object_id_t *objectId) {
auto *destination = ObjectManager::instance()->get<HasHealthIF>(*objectId);
if (destination == nullptr) {
return CommandingServiceBase::INVALID_OBJECT;
}
*messageQueueToSet = destination->getCommandQueue();
return returnvalue::OK;
}
ReturnValue_t CServiceHealthCommanding::prepareCommand(CommandMessage *message, uint8_t subservice,
const uint8_t *tcData, size_t tcDataLen,
uint32_t *state, object_id_t objectId) {
ReturnValue_t result = returnvalue::OK;
switch (subservice) {
case (Subservice::COMMAND_SET_HEALTH): {
if (tcDataLen != sizeof(object_id_t) + sizeof(HasHealthIF::HealthState)) {
return CommandingServiceBase::INVALID_TC;
}
HealthSetCommand healthCommand;
result = healthCommand.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
if (result != returnvalue::OK) {
break;
}
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_SET,
healthCommand.getHealth());
break;
}
case (Subservice::COMMAND_ANNOUNCE_HEALTH): {
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE);
return CommandingServiceBase::EXECUTION_COMPLETE;
}
case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): {
ReturnValue_t result = iterateHealthTable(true);
if (result == returnvalue::OK) {
reportAllHealth = true;
return EXECUTION_COMPLETE;
}
return result;
}
default: {
// Should never happen, subservice was already checked
result = returnvalue::FAILED;
}
}
return result;
}
ReturnValue_t CServiceHealthCommanding::handleReply(const CommandMessage *reply,
Command_t previousCommand, uint32_t *state,
CommandMessage *optionalNextCommand,
object_id_t objectId, bool *isStep) {
Command_t replyId = reply->getCommand();
if (replyId == HealthMessage::REPLY_HEALTH_SET) {
return EXECUTION_COMPLETE;
} else if (replyId == CommandMessageIF::REPLY_REJECTED) {
return reply->getReplyRejectedReason();
}
return CommandingServiceBase::INVALID_REPLY;
}
void CServiceHealthCommanding::doPeriodicOperation() {
if (reportAllHealth) {
for (uint8_t i = 0; i < maxNumHealthInfoPerCycle; i++) {
ReturnValue_t result = iterateHealthTable(false);
if (result != returnvalue::OK) {
reportAllHealth = false;
break;
}
}
}
}
// Not used for now, health state already reported by event
[[maybe_unused]] ReturnValue_t CServiceHealthCommanding::prepareHealthSetReply(
const CommandMessage *reply) {
auto health = static_cast<uint8_t>(HealthMessage::getHealth(reply));
auto oldHealth = static_cast<uint8_t>(HealthMessage::getOldHealth(reply));
HealthSetReply healthSetReply(health, oldHealth);
return sendTmPacket(Subservice::REPLY_HEALTH_SET, healthSetReply);
}
ReturnValue_t CServiceHealthCommanding::iterateHealthTable(bool reset) {
std::pair<object_id_t, HasHealthIF::HealthState> pair;
ReturnValue_t result = healthTable->iterate(&pair, reset);
if (result != returnvalue::OK) {
return result;
} else {
EventManagerIF::triggerEvent(pair.first, HasHealthIF::HEALTH_INFO, pair.second, pair.second);
return returnvalue::OK;
}
}

View File

@ -1,8 +1,26 @@
#ifndef FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_ #ifndef FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
#define FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_ #define FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
#include <fsfw/health/HealthTable.h>
#include "fsfw/tmtcservices/CommandingServiceBase.h" #include "fsfw/tmtcservices/CommandingServiceBase.h"
struct HealthServiceCfg {
HealthServiceCfg(object_id_t objectId, uint16_t apid, object_id_t healthTable,
uint16_t maxNumHealthInfoPerCycle)
: objectId(objectId),
apid(apid),
table(healthTable),
maxNumHealthInfoPerCycle(maxNumHealthInfoPerCycle) {}
object_id_t objectId;
uint16_t apid;
object_id_t table;
uint16_t maxNumHealthInfoPerCycle;
uint8_t service = 201;
uint8_t numParallelCommands = 4;
uint16_t commandTimeoutSeconds = 60;
};
/** /**
* @brief Custom PUS service to set health of all objects * @brief Custom PUS service to set health of all objects
* implementing hasHealthIF. * implementing hasHealthIF.
@ -17,11 +35,12 @@
* child class like this service * child class like this service
* *
*/ */
class CService201HealthCommanding : public CommandingServiceBase { class CServiceHealthCommanding : public CommandingServiceBase {
public: public:
CService201HealthCommanding(object_id_t objectId, uint16_t apid, uint8_t serviceId, CServiceHealthCommanding(HealthServiceCfg args);
uint8_t numParallelCommands = 4, uint16_t commandTimeoutSeconds = 60); ~CServiceHealthCommanding() override = default;
~CService201HealthCommanding() override = default;
ReturnValue_t initialize() override;
protected: protected:
/* CSB abstract function implementations */ /* CSB abstract function implementations */
@ -37,7 +56,14 @@ class CService201HealthCommanding : public CommandingServiceBase {
CommandMessage *optionalNextCommand, object_id_t objectId, CommandMessage *optionalNextCommand, object_id_t objectId,
bool *isStep) override; bool *isStep) override;
void doPeriodicOperation() override;
private: private:
const object_id_t healthTableId;
HealthTable *healthTable;
uint16_t maxNumHealthInfoPerCycle = 0;
bool reportAllHealth = false;
ReturnValue_t iterateHealthTable(bool reset);
static ReturnValue_t checkInterfaceAndAcquireMessageQueue(MessageQueueId_t *MessageQueueToSet, static ReturnValue_t checkInterfaceAndAcquireMessageQueue(MessageQueueId_t *MessageQueueToSet,
const object_id_t *objectId); const object_id_t *objectId);

View File

@ -13,7 +13,7 @@ Service1TelecommandVerification::Service1TelecommandVerification(object_id_t obj
uint16_t messageQueueDepth, uint16_t messageQueueDepth,
TimeWriterIF* timeStamper) TimeWriterIF* timeStamper)
: SystemObject(objectId), : SystemObject(objectId),
apid(apid), // apid(apid),
serviceId(serviceId), serviceId(serviceId),
targetDestination(targetDestination), targetDestination(targetDestination),
storeHelper(apid), storeHelper(apid),

View File

@ -72,7 +72,7 @@ class Service1TelecommandVerification : public AcceptsVerifyMessageIF,
ReturnValue_t initialize() override; ReturnValue_t initialize() override;
private: private:
uint16_t apid = 0; // uint16_t apid = 0;
uint8_t serviceId = 0; uint8_t serviceId = 0;
object_id_t targetDestination = objects::NO_OBJECT; object_id_t targetDestination = objects::NO_OBJECT;

View File

@ -69,14 +69,14 @@ ReturnValue_t Service20ParameterManagement::checkInterfaceAndAcquireMessageQueue
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Service20ParameterManagement::checkInterfaceAndAcquire" sif::error << "Service20ParameterManagement::checkInterfaceAndAcquire"
<< "MessageQueue: Can't access object" << std::endl; << "MessageQueue: Can't access object" << std::endl;
sif::error << "Object ID: " << std::hex << objectId << std::dec << std::endl; sif::error << "Object ID: 0x" << std::hex << *objectId << std::dec << std::endl;
sif::error << "Make sure it implements ReceivesParameterMessagesIF!" << std::endl; sif::error << "Make sure it implements ReceivesParameterMessagesIF" << std::endl;
#else #else
sif::printError( sif::printError(
"Service20ParameterManagement::checkInterfaceAndAcquire" "Service20ParameterManagement::checkInterfaceAndAcquire"
"MessageQueue: Can't access object\n"); "MessageQueue: Can't access object\n");
sif::printError("Object ID: 0x%08x\n", *objectId); sif::printError("Object ID: 0x%08x\n", *objectId);
sif::printError("Make sure it implements ReceivesParameterMessagesIF!\n"); sif::printError("Make sure it implements ReceivesParameterMessagesIF\n");
#endif #endif
return CommandingServiceBase::INVALID_OBJECT; return CommandingServiceBase::INVALID_OBJECT;

View File

@ -1,5 +1,7 @@
#include "fsfw/pus/Service9TimeManagement.h" #include "fsfw/pus/Service9TimeManagement.h"
#include <cmath>
#include "fsfw/events/EventManagerIF.h" #include "fsfw/events/EventManagerIF.h"
#include "fsfw/pus/servicepackets/Service9Packets.h" #include "fsfw/pus/servicepackets/Service9Packets.h"
#include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/serviceinterface/ServiceInterface.h"
@ -15,9 +17,17 @@ ReturnValue_t Service9TimeManagement::performService() { return returnvalue::OK;
ReturnValue_t Service9TimeManagement::handleRequest(uint8_t subservice) { ReturnValue_t Service9TimeManagement::handleRequest(uint8_t subservice) {
switch (subservice) { switch (subservice) {
case SUBSERVICE::SET_TIME: { case Subservice::SET_TIME: {
return setTime(); return setTime();
} }
case Subservice::DUMP_TIME: {
timeval newTime;
Clock::getClock_timeval(&newTime);
uint32_t subsecondMs =
static_cast<uint32_t>(std::floor(static_cast<double>(newTime.tv_usec) / 1000.0));
triggerEvent(CLOCK_DUMP, newTime.tv_sec, subsecondMs);
return returnvalue::OK;
}
default: default:
return AcceptsTelecommandsIF::INVALID_SUBSERVICE; return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
} }
@ -33,14 +43,14 @@ ReturnValue_t Service9TimeManagement::setTime() {
return result; return result;
} }
uint32_t formerUptime; timeval time;
Clock::getUptime(&formerUptime); Clock::getClock_timeval(&time);
result = Clock::setClock(&timeToSet); result = Clock::setClock(&timeToSet);
if (result == returnvalue::OK) { if (result == returnvalue::OK) {
uint32_t newUptime; timeval newTime;
Clock::getUptime(&newUptime); Clock::getClock_timeval(&newTime);
triggerEvent(CLOCK_SET, newUptime, formerUptime); triggerEvent(CLOCK_SET, time.tv_sec, newTime.tv_sec);
return returnvalue::OK; return returnvalue::OK;
} else { } else {
triggerEvent(CLOCK_SET_FAILURE, result, 0); triggerEvent(CLOCK_SET_FAILURE, result, 0);

View File

@ -6,10 +6,13 @@
class Service9TimeManagement : public PusServiceBase { class Service9TimeManagement : public PusServiceBase {
public: public:
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_9; static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_9;
static constexpr Event CLOCK_SET =
MAKE_EVENT(0, severity::INFO); //!< Clock has been set. P1: New Uptime. P2: Old Uptime //!< Clock has been set. P1: old timeval seconds. P2: new timeval seconds.
static constexpr Event CLOCK_SET_FAILURE = static constexpr Event CLOCK_SET = MAKE_EVENT(0, severity::INFO);
MAKE_EVENT(1, severity::LOW); //!< Clock could not be set. P1: Returncode. //!< Clock dump event. P1: timeval seconds P2: timeval milliseconds.
static constexpr Event CLOCK_DUMP = MAKE_EVENT(1, severity::INFO);
//!< Clock could not be set. P1: Returncode.
static constexpr Event CLOCK_SET_FAILURE = MAKE_EVENT(2, severity::LOW);
static constexpr uint8_t CLASS_ID = CLASS_ID::PUS_SERVICE_9; static constexpr uint8_t CLASS_ID = CLASS_ID::PUS_SERVICE_9;
@ -30,8 +33,9 @@ class Service9TimeManagement : public PusServiceBase {
virtual ReturnValue_t setTime(); virtual ReturnValue_t setTime();
private: private:
enum SUBSERVICE { enum Subservice {
SET_TIME = 128 //!< [EXPORT] : [COMMAND] Time command in ASCII, CUC or CDS format SET_TIME = 128, //!< [EXPORT] : [COMMAND] Time command in ASCII, CUC or CDS format
DUMP_TIME = 129,
}; };
}; };

View File

@ -69,7 +69,7 @@ class FailureReport : public SerializeIF { //!< [EXPORT] : [SUBSERVICE] 2, 4, 6
return result; return result;
} }
virtual size_t getSerializedSize() const { virtual size_t getSerializedSize() const override {
size_t size = 0; size_t size = 0;
size += SerializeAdapter::getSerializedSize(&packetId); size += SerializeAdapter::getSerializedSize(&packetId);
size += sizeof(packetSequenceControl); size += sizeof(packetSequenceControl);

View File

@ -10,11 +10,11 @@
////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////
// RMAP command bits // RMAP command bits
//#define RMAP_COMMAND_BIT_INCREMENT 2 // #define RMAP_COMMAND_BIT_INCREMENT 2
//#define RMAP_COMMAND_BIT_REPLY 3 // #define RMAP_COMMAND_BIT_REPLY 3
//#define RMAP_COMMAND_BIT_WRITE 5 // #define RMAP_COMMAND_BIT_WRITE 5
//#define RMAP_COMMAND_BIT_VERIFY 4 // #define RMAP_COMMAND_BIT_VERIFY 4
//#define RMAP_COMMAND_BIT 6 // #define RMAP_COMMAND_BIT 6
namespace RMAPIds { namespace RMAPIds {
@ -32,14 +32,14 @@ static const uint8_t RMAP_COMMAND_READ = ((1 << RMAP_COMMAND_BIT) | (1 << RMAP_C
static const uint8_t RMAP_REPLY_WRITE = static const uint8_t RMAP_REPLY_WRITE =
((1 << RMAP_COMMAND_BIT_WRITE) | (1 << RMAP_COMMAND_BIT_REPLY)); ((1 << RMAP_COMMAND_BIT_WRITE) | (1 << RMAP_COMMAND_BIT_REPLY));
static const uint8_t RMAP_REPLY_READ = ((1 << RMAP_COMMAND_BIT_REPLY)); static const uint8_t RMAP_REPLY_READ = ((1 << RMAP_COMMAND_BIT_REPLY));
//#define RMAP_COMMAND_WRITE ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_WRITE) // #define RMAP_COMMAND_WRITE ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_WRITE)
//| (1<<RMAP_COMMAND_BIT_REPLY)) #define RMAP_COMMAND_WRITE_VERIFY ((1<<RMAP_COMMAND_BIT) | //| (1<<RMAP_COMMAND_BIT_REPLY)) #define RMAP_COMMAND_WRITE_VERIFY ((1<<RMAP_COMMAND_BIT) |
//(1<<RMAP_COMMAND_BIT_WRITE) | (1<<RMAP_COMMAND_BIT_REPLY) | (1<<RMAP_COMMAND_BIT_VERIFY)) #define //(1<<RMAP_COMMAND_BIT_WRITE) | (1<<RMAP_COMMAND_BIT_REPLY) | (1<<RMAP_COMMAND_BIT_VERIFY)) #define
// RMAP_COMMAND_READ ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_REPLY)) // RMAP_COMMAND_READ ((1<<RMAP_COMMAND_BIT) | (1<<RMAP_COMMAND_BIT_REPLY))
//#define RMAP_REPLY_WRITE ((1<<RMAP_COMMAND_BIT_WRITE) | // #define RMAP_REPLY_WRITE ((1<<RMAP_COMMAND_BIT_WRITE) |
//(1<<RMAP_COMMAND_BIT_REPLY)) //(1<<RMAP_COMMAND_BIT_REPLY))
//#define RMAP_REPLY_WRITE_VERIFY ((1<<RMAP_COMMAND_BIT_WRITE) | // #define RMAP_REPLY_WRITE_VERIFY ((1<<RMAP_COMMAND_BIT_WRITE) |
//(1<<RMAP_COMMAND_BIT_REPLY) | (1<<RMAP_COMMAND_BIT_VERIFY)) #define RMAP_REPLY_READ //(1<<RMAP_COMMAND_BIT_REPLY) | (1<<RMAP_COMMAND_BIT_VERIFY)) #define RMAP_REPLY_READ
//((1<<RMAP_COMMAND_BIT_REPLY)) //((1<<RMAP_COMMAND_BIT_REPLY))
@ -49,9 +49,9 @@ static const uint8_t RMAP_COMMAND_HEADER_LEN = 16;
static const uint8_t RMAP_WRITE_REPLY_HEADER_LEN = 8; static const uint8_t RMAP_WRITE_REPLY_HEADER_LEN = 8;
static const uint8_t RMAP_READ_REPLY_HEADER_LEN = 12; static const uint8_t RMAP_READ_REPLY_HEADER_LEN = 12;
static const uint8_t RMAP_DATA_FOOTER_SIZE = 1; // SIZE OF CRC static const uint8_t RMAP_DATA_FOOTER_SIZE = 1; // SIZE OF CRC
//#define RMAP_COMMAND_HEADER_LEN 16 // #define RMAP_COMMAND_HEADER_LEN 16
//#define RMAP_WRITE_REPLY_HEADER_LEN 8 // #define RMAP_WRITE_REPLY_HEADER_LEN 8
//#define RMAP_READ_REPLY_HEADER_LEN 12 // #define RMAP_READ_REPLY_HEADER_LEN 12
} // namespace RMAPIds } // namespace RMAPIds

View File

@ -33,7 +33,7 @@
* @author baetz * @author baetz
* @ingroup serialize * @ingroup serialize
*/ */
template <typename T, typename count_t = uint8_t> template <typename T, typename count_t = size_t>
class SerialLinkedListAdapter : public SinglyLinkedList<T>, public SerializeIF { class SerialLinkedListAdapter : public SinglyLinkedList<T>, public SerializeIF {
public: public:
SerialLinkedListAdapter(typename LinkedElement<T>::Iterator start, bool printCount = false) SerialLinkedListAdapter(typename LinkedElement<T>::Iterator start, bool printCount = false)

View File

@ -109,7 +109,8 @@ ReturnValue_t LocalPool::deleteData(uint8_t* ptr, size_t size, store_address_t*
ReturnValue_t result = ILLEGAL_ADDRESS; ReturnValue_t result = ILLEGAL_ADDRESS;
for (uint16_t n = 0; n < NUMBER_OF_SUBPOOLS; n++) { for (uint16_t n = 0; n < NUMBER_OF_SUBPOOLS; n++) {
// Not sure if new allocates all stores in order. so better be careful. // Not sure if new allocates all stores in order. so better be careful.
if ((store[n].data() <= ptr) and (&store[n][numberOfElements[n] * elementSizes[n]] > ptr)) { if ((store[n].data() <= ptr) and
(&store[n][numberOfElements[n] * elementSizes[n] - 1] >= ptr)) {
localId.poolIndex = n; localId.poolIndex = n;
uint32_t deltaAddress = ptr - store[n].data(); uint32_t deltaAddress = ptr - store[n].data();
// Getting any data from the right "block" is ok. // Getting any data from the right "block" is ok.

View File

@ -91,11 +91,10 @@ void Subsystem::performChildOperation() {
} }
if (currentSequenceIterator->getWaitSeconds() != 0) { if (currentSequenceIterator->getWaitSeconds() != 0) {
if (uptimeStartTable == 0) { if (uptimeStartTable == 0) {
Clock::getUptime(&uptimeStartTable); uptimeStartTable = Clock::getUptime_ms();
return; return;
} else { } else {
uint32_t uptimeNow; uint32_t uptimeNow = Clock::getUptime_ms();
Clock::getUptime(&uptimeNow);
if ((uptimeNow - uptimeStartTable) < (currentSequenceIterator->getWaitSeconds() * 1000)) { if ((uptimeNow - uptimeStartTable) < (currentSequenceIterator->getWaitSeconds() * 1000)) {
return; return;
} }
@ -586,7 +585,12 @@ void Subsystem::sendSerializablesAsCommandMessage(Command_t command, SerializeIF
return; return;
} }
for (uint8_t i = 0; i < count; i++) { for (uint8_t i = 0; i < count; i++) {
elements[i]->serialize(&storeBuffer, &size, maxSize, SerializeIF::Endianness::BIG); result = elements[i]->serialize(&storeBuffer, &size, maxSize, SerializeIF::Endianness::BIG);
if (result != returnvalue::OK) {
replyToCommand(result, 0);
IPCStore->deleteData(address);
return;
}
} }
CommandMessage reply; CommandMessage reply;
ModeSequenceMessage::setModeSequenceMessage(&reply, command, address); ModeSequenceMessage::setModeSequenceMessage(&reply, command, address);

View File

@ -9,7 +9,6 @@ class FixedTimeslotTaskBase : public FixedTimeslotTaskIF {
public: public:
explicit FixedTimeslotTaskBase(TaskPeriod period, TaskDeadlineMissedFunction dlmFunc = nullptr); explicit FixedTimeslotTaskBase(TaskPeriod period, TaskDeadlineMissedFunction dlmFunc = nullptr);
~FixedTimeslotTaskBase() override = default; ~FixedTimeslotTaskBase() override = default;
;
protected: protected:
/** /**

View File

@ -196,12 +196,11 @@ void Heater::setSwitch(uint8_t number, ReturnValue_t state, uint32_t* uptimeOfSw
if (powerSwitcher->getSwitchState(number) == state) { if (powerSwitcher->getSwitchState(number) == state) {
*uptimeOfSwitching = INVALID_UPTIME; *uptimeOfSwitching = INVALID_UPTIME;
} else { } else {
if ((*uptimeOfSwitching == INVALID_UPTIME)) { if (*uptimeOfSwitching == INVALID_UPTIME) {
powerSwitcher->sendSwitchCommand(number, state); powerSwitcher->sendSwitchCommand(number, state);
Clock::getUptime(uptimeOfSwitching); *uptimeOfSwitching = Clock::getUptime_ms();
} else { } else {
uint32_t currentUptime; uint32_t currentUptime = Clock::getUptime_ms();
Clock::getUptime(&currentUptime);
if (currentUptime - *uptimeOfSwitching > powerSwitcher->getSwitchDelayMs()) { if (currentUptime - *uptimeOfSwitching > powerSwitcher->getSwitchDelayMs()) {
*uptimeOfSwitching = INVALID_UPTIME; *uptimeOfSwitching = INVALID_UPTIME;
if (healthHelper.healthTable->isHealthy(getObjectId())) { if (healthHelper.healthTable->isHealthy(getObjectId())) {

View File

@ -1,4 +1,9 @@
target_sources( target_sources(
${LIB_FSFW_NAME} ${LIB_FSFW_NAME}
PRIVATE CCSDSTime.cpp Countdown.cpp Stopwatch.cpp TimeMessage.cpp PRIVATE CCSDSTime.cpp
CdsShortTimeStamper.cpp ClockCommon.cpp) Countdown.cpp
Stopwatch.cpp
TimeMessage.cpp
CdsShortTimeStamper.cpp
ClockCommon.cpp
boost_timegm.cpp)

View File

@ -4,6 +4,8 @@
#include "fsfw/timemanager/Clock.h" #include "fsfw/timemanager/Clock.h"
CdsShortTimeStamper::CdsShortTimeStamper() : SystemObject(0, false) {}
CdsShortTimeStamper::CdsShortTimeStamper(object_id_t objectId) : SystemObject(objectId) {} CdsShortTimeStamper::CdsShortTimeStamper(object_id_t objectId) : SystemObject(objectId) {}
ReturnValue_t CdsShortTimeStamper::serialize(uint8_t **buffer, size_t *size, size_t maxSize, ReturnValue_t CdsShortTimeStamper::serialize(uint8_t **buffer, size_t *size, size_t maxSize,

View File

@ -18,6 +18,7 @@
class CdsShortTimeStamper : public TimeWriterIF, public TimeReaderIF, public SystemObject { class CdsShortTimeStamper : public TimeWriterIF, public TimeReaderIF, public SystemObject {
public: public:
static constexpr size_t TIMESTAMP_LEN = 7; static constexpr size_t TIMESTAMP_LEN = 7;
CdsShortTimeStamper();
/** /**
* @brief Default constructor which also registers the time stamper as a * @brief Default constructor which also registers the time stamper as a
* system object so it can be found with the #objectManager. * system object so it can be found with the #objectManager.

View File

@ -16,6 +16,7 @@
class Clock { class Clock {
public: public:
// https://xkcd.com/927/
typedef struct { typedef struct {
uint32_t year; //!< Year, A.D. uint32_t year; //!< Year, A.D.
uint32_t month; //!< Month, 1 .. 12. uint32_t month; //!< Month, 1 .. 12.
@ -26,14 +27,6 @@ class Clock {
uint32_t usecond; //!< Microseconds, 0 .. 999999 uint32_t usecond; //!< Microseconds, 0 .. 999999
} TimeOfDay_t; } TimeOfDay_t;
/**
* This method returns the number of clock ticks per second.
* In RTEMS, this is typically 1000.
* @return The number of ticks.
*
* @deprecated, we should not worry about ticks, but only time
*/
static uint32_t getTicksPerSecond();
/** /**
* This system call sets the system time. * This system call sets the system time.
* To set the time, it uses a TimeOfDay_t struct. * To set the time, it uses a TimeOfDay_t struct.
@ -61,13 +54,8 @@ class Clock {
/** /**
* Get the time since boot in a timeval struct * Get the time since boot in a timeval struct
* *
* @param[out] time A pointer to a timeval struct where the uptime is stored. * @return a timeval struct where the uptime is stored
* @return @c returnvalue::OK on success. Otherwise, the OS failure code is returned.
*
* @deprecated, I do not think this should be able to fail, use timeval getUptime()
*/ */
static ReturnValue_t getUptime(timeval *uptime);
static timeval getUptime(); static timeval getUptime();
/** /**
@ -79,7 +67,7 @@ class Clock {
* @param ms uptime in ms * @param ms uptime in ms
* @return returnvalue::OK on success. Otherwise, the OS failure code is returned. * @return returnvalue::OK on success. Otherwise, the OS failure code is returned.
*/ */
static ReturnValue_t getUptime(uint32_t *uptimeMs); static uint32_t getUptime_ms();
/** /**
* Returns the time in microseconds since an OS-defined epoch. * Returns the time in microseconds since an OS-defined epoch.
@ -90,6 +78,7 @@ class Clock {
* - Otherwise, the OS failure code is returned. * - Otherwise, the OS failure code is returned.
*/ */
static ReturnValue_t getClock_usecs(uint64_t *time); static ReturnValue_t getClock_usecs(uint64_t *time);
/** /**
* Returns the time in a TimeOfDay_t struct. * Returns the time in a TimeOfDay_t struct.
* @param time A pointer to a TimeOfDay_t struct. * @param time A pointer to a TimeOfDay_t struct.
@ -106,6 +95,7 @@ class Clock {
* @return * @return
*/ */
static ReturnValue_t convertTimevalToTimeOfDay(const timeval *from, TimeOfDay_t *to); static ReturnValue_t convertTimevalToTimeOfDay(const timeval *from, TimeOfDay_t *to);
/** /**
* Converts a time of day struct to POSIX seconds. * Converts a time of day struct to POSIX seconds.
* @param time The time of day as input * @param time The time of day as input

View File

@ -1,5 +1,7 @@
#include <cstdlib>
#include <ctime> #include <ctime>
#include "boost_timegm.h"
#include "fsfw/ipc/MutexGuard.h" #include "fsfw/ipc/MutexGuard.h"
#include "fsfw/timemanager/Clock.h" #include "fsfw/timemanager/Clock.h"
@ -53,34 +55,58 @@ ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) {
} }
ReturnValue_t Clock::convertTimevalToTimeOfDay(const timeval* from, TimeOfDay_t* to) { ReturnValue_t Clock::convertTimevalToTimeOfDay(const timeval* from, TimeOfDay_t* to) {
struct tm* timeInfo; struct tm time_tm;
// According to https://en.cppreference.com/w/c/chrono/gmtime, the implementation of gmtime_s // WINDOWS does not provide gmtime_r, but gmtime_s
// in the Windows CRT is incompatible with the C standard but this should not be an issue for #ifdef _MSC_VER
// this implementation time_t seconds = from->tv_sec;
ReturnValue_t result = checkOrCreateClockMutex(); errno_t result = gmtime_s(&time_tm, &seconds);
if (result != returnvalue::OK) { if (result != 0) {
return result; return returnvalue::FAILED;
} }
// gmtime writes its output in a global buffer which is not Thread Safe
// Therefore we have to use a Mutex here
MutexGuard helper(timeMutex);
#ifdef PLATFORM_WIN
time_t time;
time = from->tv_sec;
timeInfo = gmtime(&time);
#else #else
timeInfo = gmtime(&from->tv_sec); void* result = gmtime_r(&from->tv_sec, &time_tm);
if (result == nullptr) {
return returnvalue::FAILED;
}
#endif #endif
to->year = timeInfo->tm_year + 1900;
to->month = timeInfo->tm_mon + 1; to->year = time_tm.tm_year + 1900;
to->day = timeInfo->tm_mday; to->month = time_tm.tm_mon + 1;
to->hour = timeInfo->tm_hour; to->day = time_tm.tm_mday;
to->minute = timeInfo->tm_min; to->hour = time_tm.tm_hour;
to->second = timeInfo->tm_sec; to->minute = time_tm.tm_min;
to->second = time_tm.tm_sec;
to->usecond = from->tv_usec; to->usecond = from->tv_usec;
return returnvalue::OK; return returnvalue::OK;
} }
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to) {
struct tm time_tm = {};
time_tm.tm_year = from->year - 1900;
time_tm.tm_mon = from->month - 1;
time_tm.tm_mday = from->day;
time_tm.tm_hour = from->hour;
time_tm.tm_min = from->minute;
time_tm.tm_sec = from->second;
time_tm.tm_isdst = 0;
time_t seconds = internal_timegm(&time_tm);
to->tv_sec = seconds;
to->tv_usec = from->usecond;
return returnvalue::OK;
}
ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
*JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. / 3600.;
return returnvalue::OK;
}
ReturnValue_t Clock::checkOrCreateClockMutex() { ReturnValue_t Clock::checkOrCreateClockMutex() {
if (timeMutex == nullptr) { if (timeMutex == nullptr) {
MutexFactory* mutexFactory = MutexFactory::instance(); MutexFactory* mutexFactory = MutexFactory::instance();
@ -94,3 +120,37 @@ ReturnValue_t Clock::checkOrCreateClockMutex() {
} }
return returnvalue::OK; return returnvalue::OK;
} }
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
timeval time_timeval;
ReturnValue_t result = getClock_timeval(&time_timeval);
if (result != returnvalue::OK) {
return result;
}
return convertTimevalToTimeOfDay(&time_timeval, time);
}
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
timeval timeVal{};
ReturnValue_t result = getClock_timeval(&timeVal);
if (result != returnvalue::OK) {
return result;
}
*time = static_cast<uint64_t>(timeVal.tv_sec) * 1e6 + timeVal.tv_usec;
return returnvalue::OK;
}
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
timeval timeTimeval{};
ReturnValue_t result = convertTimeOfDayToTimeval(time, &timeTimeval);
if (result != returnvalue::OK) {
return result;
}
return setClock(&timeTimeval);
}
uint32_t Clock::getUptime_ms() {
timeval uptime = getUptime();
// TODO verify that overflow is correct
return uptime.tv_sec * 1e3 + uptime.tv_usec / 1e3;
}

View File

@ -7,9 +7,9 @@ Countdown::Countdown(uint32_t initialTimeout) : timeout(initialTimeout) {
Countdown::~Countdown() {} Countdown::~Countdown() {}
ReturnValue_t Countdown::setTimeout(uint32_t milliseconds) { ReturnValue_t Countdown::setTimeout(uint32_t milliseconds) {
ReturnValue_t returnValue = Clock::getUptime(&startTime); startTime = Clock::getUptime_ms();
timeout = milliseconds; timeout = milliseconds;
return returnValue; return returnvalue::OK;
} }
bool Countdown::hasTimedOut() const { bool Countdown::hasTimedOut() const {
@ -38,8 +38,4 @@ uint32_t Countdown::getRemainingMillis() const {
} }
} }
uint32_t Countdown::getCurrentTime() const { uint32_t Countdown::getCurrentTime() const { return Clock::getUptime_ms(); }
uint32_t currentTime;
Clock::getUptime(&currentTime);
return currentTime;
}

View File

@ -9,10 +9,10 @@
Stopwatch::Stopwatch(bool displayOnDestruction, StopwatchDisplayMode displayMode) Stopwatch::Stopwatch(bool displayOnDestruction, StopwatchDisplayMode displayMode)
: displayOnDestruction(displayOnDestruction), displayMode(displayMode) { : displayOnDestruction(displayOnDestruction), displayMode(displayMode) {
// Measures start time on initialization. // Measures start time on initialization.
Clock::getUptime(&startTime); startTime = Clock::getUptime();
} }
void Stopwatch::start() { Clock::getUptime(&startTime); } void Stopwatch::start() { startTime = Clock::getUptime(); }
dur_millis_t Stopwatch::stop(bool display) { dur_millis_t Stopwatch::stop(bool display) {
stopInternal(); stopInternal();
@ -62,7 +62,6 @@ void Stopwatch::setDisplayMode(StopwatchDisplayMode displayMode) {
StopwatchDisplayMode Stopwatch::getDisplayMode() const { return displayMode; } StopwatchDisplayMode Stopwatch::getDisplayMode() const { return displayMode; }
void Stopwatch::stopInternal() { void Stopwatch::stopInternal() {
timeval endTime; timeval endTime = Clock::getUptime();
Clock::getUptime(&endTime);
elapsedTime = endTime - startTime; elapsedTime = endTime - startTime;
} }

View File

@ -3,12 +3,17 @@
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <ctime>
#include "fsfw/platform.h" #include "fsfw/platform.h"
#ifdef PLATFORM_WIN #ifdef PLATFORM_WIN
// wtf? Required for timeval! // wtf? Required for timeval!
// Thanks, windows
// clang-format off
#include <winsock2.h>
#include <winsock.h> #include <winsock.h>
// clang-format off
#endif #endif
#include "TimeStampIF.h" #include "TimeStampIF.h"

View File

@ -0,0 +1,66 @@
// (C) Copyright Howard Hinnant
// (C) Copyright 2010-2011 Vicente J. Botet Escriba
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt).
//===-------------------------- locale ------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// This code was adapted by Vicente from Howard Hinnant's experimental work
// on chrono i/o to Boost and some functions from libc++/locale to emulate the missing
// time_get::get()
#include "boost_timegm.h"
#include <cstdint>
int32_t is_leap(int32_t year) {
if (year % 400 == 0) return 1;
if (year % 100 == 0) return 0;
if (year % 4 == 0) return 1;
return 0;
}
int32_t days_from_0(int32_t year) {
year--;
return 365 * year + (year / 400) - (year / 100) + (year / 4);
}
int32_t days_from_1970(int32_t year) {
static const int32_t days_from_0_to_1970 = days_from_0(1970);
return days_from_0(year) - days_from_0_to_1970;
}
int32_t days_from_1jan(int32_t year, int32_t month, int32_t day) {
static const int32_t days[2][12] = {{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
{0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}};
return days[is_leap(year)][month - 1] + day - 1;
}
time_t internal_timegm(std::tm const *t) {
int year = t->tm_year + 1900;
int month = t->tm_mon;
if (month > 11) {
year += month / 12;
month %= 12;
} else if (month < 0) {
int years_diff = (-month + 11) / 12;
year -= years_diff;
month += 12 * years_diff;
}
month++;
int day = t->tm_mday;
int day_of_year = days_from_1jan(year, month, day);
int days_since_epoch = days_from_1970(year) + day_of_year;
time_t seconds_in_day = 3600 * 24;
time_t result =
seconds_in_day * days_since_epoch + 3600 * t->tm_hour + 60 * t->tm_min + t->tm_sec;
return result;
}

View File

@ -0,0 +1,3 @@
#include <ctime>
time_t internal_timegm(std::tm const *t);

View File

@ -100,5 +100,6 @@ ReturnValue_t PusTcCreator::setSerializableUserData(const SerializeIF &serializa
void PusTcCreator::setup() { void PusTcCreator::setup() {
spCreator.setPacketType(ccsds::PacketType::TC); spCreator.setPacketType(ccsds::PacketType::TC);
spCreator.setSecHeaderFlag(); spCreator.setSecHeaderFlag();
spCreator.setSeqFlags(ccsds::SequenceFlags::UNSEGMENTED);
updateSpLengthField(); updateSpLengthField();
} }

View File

@ -119,6 +119,7 @@ void PusTmCreator::setup() {
updateSpLengthField(); updateSpLengthField();
spCreator.setPacketType(ccsds::PacketType::TM); spCreator.setPacketType(ccsds::PacketType::TM);
spCreator.setSecHeaderFlag(); spCreator.setSecHeaderFlag();
spCreator.setSeqFlags(ccsds::SequenceFlags::UNSEGMENTED);
} }
void PusTmCreator::setMessageTypeCounter(uint16_t messageTypeCounter) { void PusTmCreator::setMessageTypeCounter(uint16_t messageTypeCounter) {

View File

@ -348,7 +348,7 @@ void CommandingServiceBase::startExecution(store_address_t storeId, CommandMapIt
sendResult = commandQueue->sendMessage(iter.value->first, &command); sendResult = commandQueue->sendMessage(iter.value->first, &command);
} }
if (sendResult == returnvalue::OK) { if (sendResult == returnvalue::OK) {
Clock::getUptime(&iter->second.uptimeOfStart); iter->second.uptimeOfStart = Clock::getUptime_ms();
iter->second.step = 0; iter->second.step = 0;
iter->second.subservice = tcReader.getSubService(); iter->second.subservice = tcReader.getSubService();
iter->second.command = command.getCommand(); iter->second.command = command.getCommand();
@ -434,8 +434,7 @@ inline void CommandingServiceBase::doPeriodicOperation() {}
MessageQueueId_t CommandingServiceBase::getCommandQueue() { return commandQueue->getId(); } MessageQueueId_t CommandingServiceBase::getCommandQueue() { return commandQueue->getId(); }
void CommandingServiceBase::checkTimeout() { void CommandingServiceBase::checkTimeout() {
uint32_t uptime; uint32_t uptime = Clock::getUptime_ms();
Clock::getUptime(&uptime);
CommandMapIter iter; CommandMapIter iter;
for (iter = commandMap.begin(); iter != commandMap.end(); ++iter) { for (iter = commandMap.begin(); iter != commandMap.end(); ++iter) {
if ((iter->second.uptimeOfStart + (timeoutSeconds * 1000)) < uptime) { if ((iter->second.uptimeOfStart + (timeoutSeconds * 1000)) < uptime) {

View File

@ -8,7 +8,7 @@
#define TMTCBRIDGE_WIRETAPPING 0 #define TMTCBRIDGE_WIRETAPPING 0
TmTcBridge::TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDestination, TmTcBridge::TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDestination,
object_id_t tmStoreId, object_id_t tcStoreId) uint32_t msgQueueDepth, object_id_t tmStoreId, object_id_t tcStoreId)
: SystemObject(objectId), : SystemObject(objectId),
name(name), name(name),
tmStoreId(tmStoreId), tmStoreId(tmStoreId),
@ -16,7 +16,9 @@ TmTcBridge::TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDes
tcDestination(tcDestination) tcDestination(tcDestination)
{ {
tmTcReceptionQueue = QueueFactory::instance()->createMessageQueue(TMTC_RECEPTION_QUEUE_DEPTH); auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
tmTcReceptionQueue = QueueFactory::instance()->createMessageQueue(
msgQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
} }
TmTcBridge::~TmTcBridge() { QueueFactory::instance()->deleteMessageQueue(tmTcReceptionQueue); } TmTcBridge::~TmTcBridge() { QueueFactory::instance()->deleteMessageQueue(tmTcReceptionQueue); }
@ -35,7 +37,7 @@ ReturnValue_t TmTcBridge::setNumberOfSentPacketsPerCycle(uint8_t sentPacketsPerC
} }
} }
ReturnValue_t TmTcBridge::setMaxNumberOfPacketsStored(uint8_t maxNumberOfPacketsStored) { ReturnValue_t TmTcBridge::setMaxNumberOfPacketsStored(unsigned int maxNumberOfPacketsStored) {
if (maxNumberOfPacketsStored <= LIMIT_DOWNLINK_PACKETS_STORED) { if (maxNumberOfPacketsStored <= LIMIT_DOWNLINK_PACKETS_STORED) {
this->maxNumberOfPacketsStored = maxNumberOfPacketsStored; this->maxNumberOfPacketsStored = maxNumberOfPacketsStored;
return returnvalue::OK; return returnvalue::OK;
@ -143,13 +145,17 @@ ReturnValue_t TmTcBridge::handleTmQueue() {
#endif /* FSFW_VERBOSE_LEVEL >= 3 */ #endif /* FSFW_VERBOSE_LEVEL >= 3 */
if (communicationLinkUp == false or packetSentCounter >= sentPacketsPerCycle) { if (communicationLinkUp == false or packetSentCounter >= sentPacketsPerCycle) {
storeDownlinkData(&message); ReturnValue_t result = storeDownlinkData(&message);
if (result != returnvalue::OK) {
tmStore->deleteData(message.getStorageId());
}
continue; continue;
} }
result = tmStore->getData(message.getStorageId(), &data, &size); result = tmStore->getData(message.getStorageId(), &data, &size);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
status = result; status = result;
tmStore->deleteData(message.getStorageId());
continue; continue;
} }
@ -157,9 +163,9 @@ ReturnValue_t TmTcBridge::handleTmQueue() {
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
status = result; status = result;
} else { } else {
tmStore->deleteData(message.getStorageId());
packetSentCounter++; packetSentCounter++;
} }
tmStore->deleteData(message.getStorageId());
} }
return status; return status;
} }
@ -171,15 +177,18 @@ ReturnValue_t TmTcBridge::storeDownlinkData(TmTcMessage* message) {
} }
if (tmFifo->full()) { if (tmFifo->full()) {
if (warningSwitch) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "TmTcBridge::storeDownlinkData: TM downlink max. number " sif::warning << "TmTcBridge::storeDownlinkData: TM downlink max. number "
"of stored packet IDs reached!" "of stored packet IDs reached!"
<< std::endl; << std::endl;
#else #else
sif::printWarning( sif::printWarning(
"TmTcBridge::storeDownlinkData: TM downlink max. number " "TmTcBridge::storeDownlinkData: TM downlink max. number "
"of stored packet IDs reached!\n"); "of stored packet IDs reached!\n");
#endif #endif
warningSwitch = false;
}
if (overwriteOld) { if (overwriteOld) {
tmFifo->retrieve(&storeId); tmFifo->retrieve(&storeId);
tmStore->deleteData(storeId); tmStore->deleteData(storeId);
@ -221,6 +230,7 @@ ReturnValue_t TmTcBridge::handleStoredTm() {
packetSentCounter++; packetSentCounter++;
if (tmFifo->empty()) { if (tmFifo->empty()) {
warningSwitch = true;
tmStored = false; tmStored = false;
} }
tmStore->deleteData(storeId); tmStore->deleteData(storeId);

View File

@ -15,15 +15,14 @@ class TmTcBridge : public AcceptsTelemetryIF,
public ExecutableObjectIF, public ExecutableObjectIF,
public SystemObject { public SystemObject {
public: public:
static constexpr uint8_t TMTC_RECEPTION_QUEUE_DEPTH = 20;
static constexpr uint8_t LIMIT_STORED_DATA_SENT_PER_CYCLE = 15; static constexpr uint8_t LIMIT_STORED_DATA_SENT_PER_CYCLE = 15;
static constexpr uint8_t LIMIT_DOWNLINK_PACKETS_STORED = 200; static constexpr unsigned int LIMIT_DOWNLINK_PACKETS_STORED = 500;
static constexpr uint8_t DEFAULT_STORED_DATA_SENT_PER_CYCLE = 5; static constexpr uint8_t DEFAULT_STORED_DATA_SENT_PER_CYCLE = 5;
static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10; static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10;
TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDestination, TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDestination,
object_id_t tmStoreId, object_id_t tcStoreId); uint32_t msgQueueDepth, object_id_t tmStoreId, object_id_t tcStoreId);
~TmTcBridge() override; ~TmTcBridge() override;
/** /**
@ -42,7 +41,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
* @return -@c returnvalue::OK if value was set successfully * @return -@c returnvalue::OK if value was set successfully
* -@c returnvalue::FAILED otherwise, stored value stays the same * -@c returnvalue::FAILED otherwise, stored value stays the same
*/ */
ReturnValue_t setMaxNumberOfPacketsStored(uint8_t maxNumberOfPacketsStored); ReturnValue_t setMaxNumberOfPacketsStored(unsigned int maxNumberOfPacketsStored);
/** /**
* This will set up the bridge to overwrite old data in the FIFO. * This will set up the bridge to overwrite old data in the FIFO.
@ -91,6 +90,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
//! by default, so telemetry will be handled immediately. //! by default, so telemetry will be handled immediately.
bool communicationLinkUp = true; bool communicationLinkUp = true;
bool tmStored = false; bool tmStored = false;
bool warningSwitch = true;
bool overwriteOld = true; bool overwriteOld = true;
uint8_t packetSentCounter = 0; uint8_t packetSentCounter = 0;
@ -152,7 +152,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
*/ */
DynamicFIFO<store_address_t>* tmFifo = nullptr; DynamicFIFO<store_address_t>* tmFifo = nullptr;
uint8_t sentPacketsPerCycle = DEFAULT_STORED_DATA_SENT_PER_CYCLE; uint8_t sentPacketsPerCycle = DEFAULT_STORED_DATA_SENT_PER_CYCLE;
uint8_t maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED; unsigned int maxNumberOfPacketsStored = DEFAULT_DOWNLINK_PACKETS_STORED;
}; };
#endif /* FSFW_TMTCSERVICES_TMTCBRIDGE_H_ */ #endif /* FSFW_TMTCSERVICES_TMTCBRIDGE_H_ */

View File

@ -1,6 +1,7 @@
#include "version.h" #include "version.h"
#include <cstdio> #include <cstdio>
#include <cstring>
#include "fsfw/FSFWVersion.h" #include "fsfw/FSFWVersion.h"
@ -20,7 +21,7 @@ fsfw::Version::Version(int major, int minor, int revision, const char* addInfo)
void fsfw::Version::getVersion(char* str, size_t maxLen) const { void fsfw::Version::getVersion(char* str, size_t maxLen) const {
size_t len = snprintf(str, maxLen, "%d.%d.%d", major, minor, revision); size_t len = snprintf(str, maxLen, "%d.%d.%d", major, minor, revision);
if (addInfo != nullptr) { if (addInfo != nullptr and std::strcmp(addInfo, "") != 0) {
snprintf(str + len, maxLen - len, "-%s", addInfo); snprintf(str + len, maxLen - len, "-%s", addInfo);
} }
} }
@ -30,7 +31,7 @@ namespace fsfw {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
std::ostream& operator<<(std::ostream& os, const Version& v) { std::ostream& operator<<(std::ostream& os, const Version& v) {
os << v.major << "." << v.minor << "." << v.revision; os << v.major << "." << v.minor << "." << v.revision;
if (v.addInfo != nullptr) { if (v.addInfo != nullptr and std::strcmp(v.addInfo, "") != 0) {
os << "-" << v.addInfo; os << "-" << v.addInfo;
} }
return os; return os;

View File

@ -1,7 +1,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
void __attribute__((weak)) printChar(const char* character, bool errStream) { void printChar(const char* character, bool errStream) {
if (errStream) { if (errStream) {
fprintf(stderr, "%c", *character); fprintf(stderr, "%c", *character);
} else { } else {

View File

@ -72,7 +72,7 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
uint32_t transitionDelay; uint32_t transitionDelay;
// Single SPI command has 2 bytes, first for adress, second for content // Single SPI command has 2 bytes, first for adress, second for content
size_t singleComandSize = 2; // size_t singleComandSize = 2;
// Has the size for all adresses of the lis3mdl + the continous write bit // Has the size for all adresses of the lis3mdl + the continous write bit
uint8_t commandBuffer[MGMLIS3MDL::NR_OF_DATA_AND_CFG_REGISTERS + 1]; uint8_t commandBuffer[MGMLIS3MDL::NR_OF_DATA_AND_CFG_REGISTERS + 1];
@ -87,7 +87,7 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
*/ */
uint8_t registers[MGMLIS3MDL::NR_OF_CTRL_REGISTERS]; uint8_t registers[MGMLIS3MDL::NR_OF_CTRL_REGISTERS];
uint8_t statusRegister = 0; // uint8_t statusRegister = 0;
bool goToNormalMode = false; bool goToNormalMode = false;
enum class InternalState { enum class InternalState {

View File

@ -325,12 +325,12 @@ ReturnValue_t MgmRM3100Handler::handleDataReadout(const uint8_t *packet) {
// trickery here to calculate the raw values first // trickery here to calculate the raw values first
int32_t fieldStrengthRawX = ((packet[1] << 24) | (packet[2] << 16) | (packet[3] << 8)) >> 8; int32_t fieldStrengthRawX = ((packet[1] << 24) | (packet[2] << 16) | (packet[3] << 8)) >> 8;
int32_t fieldStrengthRawY = ((packet[4] << 24) | (packet[5] << 16) | (packet[6] << 8)) >> 8; int32_t fieldStrengthRawY = ((packet[4] << 24) | (packet[5] << 16) | (packet[6] << 8)) >> 8;
int32_t fieldStrengthRawZ = ((packet[7] << 24) | (packet[8] << 16) | (packet[3] << 8)) >> 8; int32_t fieldStrengthRawZ = ((packet[7] << 24) | (packet[8] << 16) | (packet[9] << 8)) >> 8;
// Now scale to physical value in microtesla // Now scale to physical value in microtesla
float fieldStrengthX = fieldStrengthRawX * scaleFactorX; float fieldStrengthX = fieldStrengthRawX * scaleFactorX;
float fieldStrengthY = fieldStrengthRawY * scaleFactorX; float fieldStrengthY = fieldStrengthRawY * scaleFactorY;
float fieldStrengthZ = fieldStrengthRawZ * scaleFactorX; float fieldStrengthZ = fieldStrengthRawZ * scaleFactorZ;
if (periodicPrintout) { if (periodicPrintout) {
if (debugDivider.checkAndIncrement()) { if (debugDivider.checkAndIncrement()) {

Some files were not shown because too many files have changed in this diff Show More