Compare commits

...

208 Commits

Author SHA1 Message Date
6f05d6b7b0 possiible leak fixes 2023-02-08 20:38:32 +01:00
84bbef0167 make it consistent 2023-02-08 09:27:14 +01:00
88b2b0e005 Merge branch 'mode_service_fixes' into develop 2023-02-08 09:26:38 +01:00
6445debfa1 bump changelog 2023-02-08 09:24:55 +01:00
8014e4adf9 mode service fixes 2023-02-08 09:23:48 +01:00
84dc7ac0ce bump changelog 2023-02-08 01:31:32 +01:00
ec12ab5daa mode service fixes 2023-02-08 01:20:28 +01:00
69c94645df add back HAL section 2023-02-07 12:36:01 +01:00
37e850c5a7 use upstream changelog 2023-02-07 12:31:19 +01:00
2646707d3f Merge branch 'cmakelists_update' into develop 2023-02-07 12:18:49 +01:00
539d7aac9e suppress error if ETL is not found 2023-02-07 12:17:03 +01:00
0a23f2c85a correction for printout, add prefix 2023-02-07 12:15:44 +01:00
06e30684fe Merge remote-tracking branch 'upstream/development' into develop 2023-02-07 12:14:31 +01:00
e2b66df72e Merge pull request 'various fixes related to linux Unittests and memory leaks' (#715) from eive/fsfw:unittest_fix_semaphore into development
Reviewed-on: fsfw/fsfw#715
2023-02-06 16:30:37 +01:00
7b828f233a Merge pull request 'I2C Linux: remove duplicate printout' (#718) from eive/fsfw:i2c_remove_duplicate_printout into development
Reviewed-on: fsfw/fsfw#718
2023-02-06 14:54:58 +01:00
c3d1000cd5 Merge branch 'development' into unittest_fix_semaphore 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
Reviewed-on: fsfw/fsfw#722
2023-02-06 14:45:40 +01:00
cc9e54ea6b Merge pull request 'improve srv20 error messages' (#723) from eive/fsfw:srv20_error_msgs into development
Reviewed-on: fsfw/fsfw#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
Reviewed-on: fsfw/fsfw#724
2023-02-06 14:36:34 +01:00
c0e5d1eb99 Merge branch 'development' into tcp_server_reuseaddr_reusesocket 2023-02-06 14:34:52 +01:00
3bc5d4a2e0 Merge remote-tracking branch 'upstream/development' into mgm_handler_small_fix 2023-02-06 14:25:33 +01:00
ab86599db3 Merge pull request 'Bugfix DHB setNormalDatapoolEntriesInvalid' (#728) from eive/fsfw:bugfix_dhb_set_datapool_entries_invalid into development
Reviewed-on: fsfw/fsfw#728
2023-02-06 14:20:34 +01:00
034eb34c2e small tweak 2023-02-03 16:05:50 +01:00
38789e053b Merge branch 'bugfix_dhb_set_datapool_entries_invalid' into develop 2023-02-03 16:05:29 +01:00
4374c7c4f4 changelog 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
e11eabdbcf bugfix in setNormalDataPoolEntriesInvalid
Do not forget to call read and write to actually update the
validity state
2023-02-03 15:58:26 +01:00
3250bbf269 changelog update 2023-02-02 18:34:24 +01:00
a78fe0a7f3 Merge pull request 'RM3100 Z-Value fix' (#123) from RM3100-fix into develop
Reviewed-on: #123
Reviewed-by: Robin Müller <muellerr@irs.uni-stuttgart.de>
2023-02-02 18:33:13 +01:00
acfc1cbf21 bump changelog 2023-02-02 18:31:40 +01:00
d17ec02cf0 fixed Z value calculation 2023-02-02 18:26:08 +01:00
e300490b93 Merge pull request 'Bugfix PUS packet creators Sequence flags' (#727) from eive/fsfw:bugfix_pus_packets_seq_flags into development
Reviewed-on: fsfw/fsfw#727
2023-02-02 17:22:29 +01:00
f2461cd7e9 helper method for commanding mode 2023-02-02 16:22:29 +01:00
01cc619e67 Merge branch 'bugfix_pus_packets_seq_flags' into develop 2023-02-01 20:52:08 +01:00
0f811777a7 changelog update 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
2339712373 set sequence flags for PUS TMTC to unsegmented 2023-02-01 20:46:48 +01:00
d9d253d3bb small but important bugfix for health service 2023-02-01 19:58:27 +01:00
bd586f6564 Merge branch 'updates_fixes_pus_time_service' into develop 2023-02-01 18:42:18 +01:00
1f88c006d9 update changelog 2023-02-01 18:42:09 +01:00
5f481739d8 Merge branch 'updates_fixes_pus_time_service' into develop 2023-02-01 18:39:51 +01:00
7e94baceef service 9 update
- fix time info event
- add time dump subservice
2023-02-01 18:39:23 +01:00
7ee83e4e5d service 9 update
- fix time info event
- add time dump subservice
2023-02-01 18:10:07 +01:00
64787f85ca update changelog 2023-02-01 17:42:06 +01:00
1cacceddad beatufil 2023-02-01 17:33:24 +01:00
5c35b8e3cd proper announce all impl 2023-02-01 17:07:38 +01:00
9b05e8f274 re-order fields in TcpConfig 2023-01-30 14:24:48 +01:00
7766b24a1d re-order fields in TcpConfig 2023-01-30 14:24:28 +01:00
eb223dae88 bump changelog 2023-01-30 14:20:28 +01:00
3656662d88 small tweak, gain factory was always them same 2023-01-30 14:18:03 +01:00
fe71978467 improve srv20 error messages 2023-01-30 14:15:37 +01:00
b646717a76 bump changelog 2023-01-30 14:11:00 +01:00
99d8c845f2 allow using SO_REUSEADDR and SO_REUSEPORT on TCP server 2023-01-30 14:07:41 +01:00
9a4ae550ab Merge branch 'develop' of https://egit.irs.uni-stuttgart.de/eive/fsfw into develop 2023-01-30 14:07:10 +01:00
c64b9b3e71 allow using SO_REUSEADDR and SO_REUSEPORT on TCP server 2023-01-30 14:05:39 +01:00
226818886f improve srv20 error messages 2023-01-28 14:31:32 +01:00
da12495335 connect mode tree parent: make health helper optional 2023-01-27 15:08:24 +01:00
049e3b431d small tweak for printout 2023-01-23 11:31:00 +01:00
bd189518b6 small tweak, gain factory was always them same 2023-01-20 11:10:05 +01:00
0e7c6b117f Merge pull request 'Service 11 TC Scheduler Robustness Improvements' (#720) from service_11_bugfixes into development
Reviewed-on: fsfw/fsfw#720
2023-01-13 13:33:19 +01:00
accaf855ee Merge remote-tracking branch 'upstream/service_11_bugfixes' into develop 2023-01-13 11:19:17 +01:00
75fa7caf25 Merge remote-tracking branch 'upstream/development' into develop 2023-01-13 11:19:09 +01:00
d16c5024dc small include improvement 2023-01-13 11:15:36 +01:00
a4531e4ced typo 2023-01-13 10:59:39 +01:00
97c629ad84 update changelog 2023-01-13 10:53:36 +01:00
bf12f284fa add size and crc check for contained TC 2023-01-13 10:53:04 +01:00
ba62c28b64 adding linux ci and fixing problems 2023-01-12 15:40:52 +01:00
7adb47aecb remove duplicate printout 2023-01-11 08:45:37 +01:00
5bb66c9723 remove duplicate printout 2023-01-10 11:55:54 +01:00
8589f4d63a Merge pull request 'updates for source sequence counter' (#714) from eive/fsfw:source_seq_counter_update into development
Reviewed-on: fsfw/fsfw#714
2022-12-19 15:00:28 +01:00
ca80589233 make get const 2022-12-19 14:58:08 +01:00
f2ebaed092 Merge pull request 'vec getter, reset for content' (#716) from eive/fsfw:get_cmd_exec_read_buf into development
Reviewed-on: fsfw/fsfw#716
2022-12-19 14:56:11 +01:00
f0b89e98df Merge pull request 'printout handling improvements' (#717) from eive/fsfw:i2c_printout_improvements into development
Reviewed-on: fsfw/fsfw#717
2022-12-19 14:45:04 +01:00
05cad893a2 introduce error counter to avoid spam 2022-12-06 10:05:23 +01:00
5557d95994 Merge branch 'development' into i2c_printout_improvements 2022-12-05 14:20:58 +01:00
fc24c9b5d8 Merge branch 'development' into get_cmd_exec_read_buf 2022-12-05 14:20:52 +01:00
5b0ea91222 statically assert MAX_SIZE > 0 2022-11-29 23:24:29 +01:00
7ef69c839c Merge pull request 'small fix to allow teardown handling' (#713) from eive/fsfw:mueller/shutdown_for_failed_to_on_transition into development
Reviewed-on: fsfw/fsfw#713
2022-11-28 14:30:15 +01:00
9b798d798e Merge pull request 'DLE parser' (#711) from eive/fsfw:mueller/dle_parser into development
Reviewed-on: fsfw/fsfw#711
2022-11-28 14:13:18 +01:00
8eb869e073 run black 2022-11-28 11:21:36 +01:00
b13453f46b vec getter, reset for content 2022-11-28 08:43:54 +01:00
d0e322d7e2 printout handling improvements 2022-11-28 08:42:08 +01:00
46a1c2bace remove data wrapper 2022-11-28 08:35:10 +01:00
2643ff194c Merge remote-tracking branch 'upstream/development' into develop 2022-11-28 08:34:04 +01:00
ecde164f68 updates for source sequence counter 2022-11-28 08:30:45 +01:00
50930b41ba Merge remote-tracking branch 'upstream/development' into mueller/dle_parser 2022-11-28 08:27:24 +01:00
d6ee2ed400 Merge pull request 'AcceptsTelemetryIF tweaks' (#712) from eive/fsfw:mueller/accepts_tm_if_adaptions into development
Reviewed-on: fsfw/fsfw#712
2022-11-21 16:30:43 +01:00
f2150ff9c2 Merge pull request 'only delete table entry if not nullptr' (#710) from eive/fsfw:mueller/health_helper_bugfix into development
Reviewed-on: fsfw/fsfw#710
2022-11-21 16:24:13 +01:00
1b9c98f3fe Merge pull request 'uio able to resolve symlinks now' (#709) from eive/fsfw:mueller/uio_mapper_handle_symlinks into development
Reviewed-on: fsfw/fsfw#709
2022-11-21 16:14:36 +01:00
742152b28e Merge branch 'development' into mueller/accepts_tm_if_adaptions 2022-11-21 15:29:35 +01:00
bf4ca56658 Merge branch 'development' into mueller/shutdown_for_failed_to_on_transition 2022-11-21 15:29:11 +01:00
16ffa00155 Merge branch 'development' into mueller/dle_parser 2022-11-21 15:28:34 +01:00
14c681c93a Merge branch 'development' into mueller/uio_mapper_handle_symlinks 2022-11-21 15:27:06 +01:00
0958c3a00e Merge branch 'development' into mueller/health_helper_bugfix 2022-11-21 15:24:51 +01:00
d699d16307 Merge pull request 'SP reader getPacketData is const now' (#708) from eive/fsfw:mueller/sp_reader_const_get_data into development
Reviewed-on: fsfw/fsfw#708
2022-11-21 15:23:39 +01:00
3b0fed733f Merge branch 'development' into mueller/uio_mapper_handle_symlinks 2022-11-21 15:23:15 +01:00
23d3812fe3 this is actually important 2022-11-21 15:22:25 +01:00
dec7db3ae2 Merge remote-tracking branch 'upstream/development' into mueller/accepts_tm_if_adaptions 2022-11-21 15:00:06 +01:00
65a5abab49 move free call 2022-11-21 14:56:08 +01:00
0129783e34 Merge branch 'development' into mueller/sp_reader_const_get_data 2022-11-21 14:50:44 +01:00
cabe0868ec Merge pull request 'move container returnvalues to namespace' (#707) from eive/fsfw:mueller/update_containers_retval into development
Reviewed-on: fsfw/fsfw#707
2022-11-21 14:49:44 +01:00
f05295bada small fix to allow teardown handling 2022-11-17 15:16:29 +01:00
160ff799ac small fix to allow teardown handling 2022-11-17 15:09:08 +01:00
b85ca64690 update changelog 2022-11-15 11:48:28 +01:00
3bc3da5a8d update changelog 2022-11-15 11:47:26 +01:00
f8c07ec9cf update changelog 2022-11-15 11:46:43 +01:00
8199b8f359 bump changelog 2022-11-15 11:45:39 +01:00
cbc8dbcdd4 update changelog 2022-11-15 11:44:45 +01:00
d31a5306f0 fix mock 2022-11-15 11:41:03 +01:00
a236a5ec50 adaptions for AcceptsTelemetryIF 2022-11-15 11:40:26 +01:00
03620970e2 function to get queue is const now 2022-11-15 11:38:32 +01:00
8fe8d810e9 only delete table if not nullptr 2022-11-15 11:27:31 +01:00
9483c2809d DLE parser 2022-11-15 11:26:53 +01:00
fe3d6bd432 uio able to resolve symlinks now 2022-11-15 10:56:46 +01:00
c5f91926c9 remove includes 2022-11-15 10:54:47 +01:00
be4a87535d remove data wrapper 2022-11-15 10:54:11 +01:00
99927b8e95 afmt 2022-11-15 10:53:38 +01:00
5e5eb82830 make warning switch protected 2022-11-15 10:53:14 +01:00
686dc97234 this is better / more correct 2022-11-15 10:52:47 +01:00
2a842666d5 SP reader getPacketData is const now 2022-11-15 10:46:46 +01:00
c013fcc1f5 move container retvals to namespace 2022-11-15 10:01:37 +01:00
1f58ba1f9b update changelog 2022-11-15 09:58:15 +01:00
002845108d Merge remote-tracking branch 'upstream/development' into develop_update 2022-11-14 15:05:47 +01:00
1b8fc2af19 Merge pull request 'CFDP Update' (#682) from mueller/cfdp-update-without-handlers into development
Reviewed-on: fsfw/fsfw#682
2022-11-14 15:04:43 +01:00
72d7c43445 updates for storage manager mock 2022-11-14 14:57:37 +01:00
ab9b6c8c89 Merge remote-tracking branch 'origin/development' into mueller/cfdp-update-without-handlers 2022-11-14 14:51:33 +01:00
69d338f9bb Merge pull request 'Local Pool Update Remove Add Data Ignore Fault Argument' (#701) from eive/fsfw:mueller/local-pool-update-remove-ignore-fault-arg into development
Reviewed-on: fsfw/fsfw#701
2022-11-14 14:49:34 +01:00
68223869d5 Merge branch 'development' into mueller/local-pool-update-remove-ignore-fault-arg 2022-11-14 14:47:07 +01:00
93fda71989 Merge pull request 'refactoring of serial drivers for linux' (#705) from eive/fsfw:mueller/refactor_serial_linux into development
Reviewed-on: fsfw/fsfw#705
2022-11-14 14:39:41 +01:00
7b0db08962 Merge branch 'development' into mueller/refactor_serial_linux 2022-11-14 14:36:31 +01:00
0956fbc740 Merge pull request 'fix compiler warning for fixed array list copy ctor' (#704) from eive/fsfw:mueller/fixed_array_list_copy_ctor into development
Reviewed-on: fsfw/fsfw#704
2022-11-14 14:28:46 +01:00
b48e0fdc0d Merge remote-tracking branch 'origin/development' into mueller/cfdp-update-without-handlers 2022-11-14 14:25:36 +01:00
1d084ee22f Merge branch 'development' into mueller/fixed_array_list_copy_ctor 2022-11-14 14:21:04 +01:00
1bea2344f6 remove using declaraction 2022-11-14 14:21:00 +01:00
d7e16a67a7 Merge pull request 'Windows Tweaks' (#691) from eive/fsfw:windows-tweaks-upstream into development
Reviewed-on: fsfw/fsfw#691
2022-11-14 14:18:47 +01:00
6021d897b8 Merge branch 'development' into windows-tweaks-upstream 2022-11-14 14:13:57 +01:00
83a6f0b5f8 reenable setup function call 2022-11-14 14:12:26 +01:00
a9c6c088f2 remove leftover debugging code 2022-11-14 14:08:38 +01:00
e03e7f5260 Merge branch 'mueller/refactor_serial_linux' into develop 2022-11-11 11:37:55 +01:00
b6a3c206cc smaller include tweaks 2022-11-11 11:34:58 +01:00
5b352978c5 rename cookie class 2022-11-11 11:33:35 +01:00
819a298b19 refactoring of serial drivers for linux 2022-11-10 17:50:21 +01:00
39946bff58 some renaming and tweaks for linux serial driver 2022-11-10 17:31:11 +01:00
16246d6ece replace other memcpy 2022-11-10 16:18:36 +01:00
5c84f12440 this not crash 2022-11-10 16:15:52 +01:00
2a203ae13d this not crash 2022-11-10 16:15:28 +01:00
6ca1a5c796 fix unittests 2022-11-10 16:11:05 +01:00
83c2c4825c fix compiler error for fixed array list copy ctor 2022-11-10 15:54:03 +01:00
194b3e100a fix compiler error for fixed array list copy ctor 2022-11-10 15:53:18 +01:00
177c39dd53 helper interface implementations 2022-11-10 15:38:34 +01:00
530a261e14 dedicated header file for container retvals 2022-11-10 15:12:18 +01:00
c913fe40bf tweaks 2022-11-09 17:54:08 +01:00
70ec08bf1d Merge pull request 'missing include' (#703) from KSat/fsfw:mueller/time_reader_include into development
Reviewed-on: fsfw/fsfw#703
2022-11-09 16:59:25 +01:00
ef23665d9c Merge branch 'development' into mueller/time_reader_include 2022-11-09 16:39:55 +01:00
eefc122292 Merge pull request 'defaultconfig did not build anymore' (#702) from mohr/fix_defaultconfig into development
Reviewed-on: fsfw/fsfw#702
2022-11-09 14:12:41 +01:00
bee33526a1 missing include 2022-11-09 13:49:40 +01:00
0e8f5ddd26 added missing const specifier 2022-11-08 11:07:56 +01:00
672fca5169 extend uart helper a bit 2022-11-04 11:08:23 +01:00
84b9d1ce21 Merge pull request 'dhb2normal' (#115) from eive/dhb2normal into develop
Reviewed-on: #115
2022-11-03 15:32:26 +01:00
e5b5c7d253 higher default MQ depth for events, printout tweak 2022-11-03 10:33:52 +01:00
9a0cc64be3 Merge branch 'develop' into eive/dhb2normal 2022-11-03 10:12:19 +01:00
00f1c5bbe9 missing replacements 2022-11-03 10:12:05 +01:00
8a61af779d Merge remote-tracking branch 'origin/develop' into eive/dhb2normal 2022-11-03 10:10:47 +01:00
6efa482eb0 use uniform uart api 2022-11-03 10:10:36 +01:00
f0fa1bf477 Merge remote-tracking branch 'origin/develop' into eive/dhb2normal 2022-11-03 10:08:35 +01:00
91ebf98c28 add new ping with data TC 2022-11-02 19:35:22 +01:00
e1d4209fbe missing fifo pop command 2022-11-02 16:07:00 +01:00
e302c89f74 health helper dtor bugfix 2022-11-02 15:48:13 +01:00
a38279f813 Merge branch 'develop' into eive/dhb2normal 2022-11-02 10:47:25 +01:00
7600ed1ea7 Merge pull request 'Improve Subsystem DHB logic' (#112) from mueller/improve-ss-dhb-logic into develop
Reviewed-on: #112
2022-11-02 10:32:25 +01:00
61ab770d9d Merge branch 'develop' into mueller/improve-ss-dhb-logic 2022-11-02 10:31:43 +01:00
f715b65d6e Merge remote-tracking branch 'upstream/development' into mueller/local-pool-update-remove-ignore-fault-arg 2022-10-28 10:06:04 +02:00
c11af63015 Merge remote-tracking branch 'origin/development' into mueller/cfdp-update-without-handlers 2022-10-28 10:04:21 +02:00
852f27cec2 Merge remote-tracking branch 'origin/develop' into mueller/improve-ss-dhb-logic 2022-10-27 16:58:30 +02:00
fa01798ebb Merge remote-tracking branch 'origin/develop' into mueller/improve-ss-dhb-logic 2022-10-27 08:30:30 +02:00
dc1583c932 Merge branch 'development' into windows-tweaks-upstream 2022-10-24 17:10:44 +02:00
81a7de2814 make dtor virtual 2022-10-24 16:39:32 +02:00
d26f230bee builds 2022-10-24 15:43:20 +02:00
4db124c680 ignore fault 2022-10-24 15:41:29 +02:00
2df66c9304 Merge branch 'mueller/local-pool-update' of https://egit.irs.uni-stuttgart.de/fsfw/fsfw into mueller/local-pool-update 2022-10-24 14:39:11 +02:00
54ad6b3016 add some docs 2022-10-24 14:39:05 +02:00
73e313c35b Merge branch 'development' into mueller/local-pool-update 2022-10-24 14:35:24 +02:00
dd2f42d22b Merge branch 'development' into mueller/local-pool-update 2022-10-24 14:34:56 +02:00
11422a658c Merge remote-tracking branch 'origin/develop' into mueller/improve-ss-dhb-logic 2022-10-21 15:35:27 +02:00
ec7566fb8c Merge remote-tracking branch 'origin/develop' into mueller/improve-ss-dhb-logic 2022-10-20 16:59:53 +02:00
652c31a683 missing validity check 2022-10-17 17:25:27 +02:00
bfe120636c this should have the same effect 2022-10-17 15:08:46 +02:00
a8041f220f Merge branch 'development' into mueller/cfdp-update-without-handlers 2022-10-17 14:44:28 +02:00
dd636b186b size check bugfix 2022-10-17 14:30:27 +02:00
3349fc36f8 Merge branch 'development' into windows-tweaks-upstream 2022-10-17 14:20:48 +02:00
df06064df0 Merge branch 'development' into windows-tweaks-upstream 2022-10-10 13:41:09 +02:00
1d6ccfe5ab Service 200: Add mode announcement support 2022-10-10 11:06:58 +02:00
221df7ece6 allow recursive mode announcements 2022-10-10 10:46:29 +02:00
7f180ac1fa Merge remote-tracking branch 'origin/develop' into mueller/improve-ss-dhb-logic 2022-10-10 10:29:08 +02:00
1eceef4645 move retvals 2022-09-30 15:05:32 +02:00
acab5f6bce added missing health and mode helper init 2022-09-30 14:14:45 +02:00
10dd855244 expose child itself in interface 2022-09-30 13:30:07 +02:00
f824004897 need to fix all of these TODOs 2022-09-29 19:39:37 +02:00
7c5308429c this seems to work 2022-09-29 19:21:24 +02:00
f78344b8fb Merge remote-tracking branch 'origin/develop' into mueller/improve-ss-dhb-logic 2022-09-29 17:46:54 +02:00
77f7fa2ef1 typo 2022-09-29 16:48:23 +02:00
78314ad966 this makes a bit more sense 2022-09-29 16:47:23 +02:00
e0c780f21c better comment 2022-09-28 09:59:31 +02:00
876815b1c9 another small windows tweak 2022-09-28 09:59:22 +02:00
b0ecf87580 last windows tweak 2022-09-28 09:59:12 +02:00
68ce8b5b08 tweaks to make windows build again 2022-09-28 09:59:02 +02:00
fe03da6def Merge remote-tracking branch 'origin/development' into mueller/cfdp-update-without-handlers 2022-09-26 15:38:45 +02:00
4f7f8310c9 Merge remote-tracking branch 'origin/development' into mueller/local-pool-update 2022-09-15 11:00:43 +02:00
113 changed files with 1373 additions and 1064 deletions

View File

@ -12,6 +12,23 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Fixes
- `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.
- `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
- DHB `setNormalDatapoolEntriesInvalid`: The default implementation did not set the validity
to false correctly because the `read` and `write` calls were missing.
- PUS TMTC creator module: Sequence flags were set to continuation segment (0b00) instead
of the correct unsegmented flags (0b11) as specified in the standard.
- TC Scheduler Service 11: Add size and CRC check for contained TC.
- Only delete health table entry in `HealthHelper` destructor if
health table was set.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/710/files
- 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.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/700
@ -24,19 +41,31 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Added
- DHB TM handler `handleDeviceTM` renamed to `handleDeviceTm` and now takes
`util::DataWrapper` as the data input argument. This allows more flexibility in the possible
types of telemetry.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/669
- Add `util::DataWrapper` class inside the `util` module. This is a tagged union which allows
to specify raw data either as a classic C-style raw pointer and size or as a `SerializeIF`
pointer.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/668
- `CServiceHealthCommanding`: Add announce all health info implementation
PR: https://egit.irs.uni-stuttgart.de/eive/fsfw/pulls/122
- `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.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/711
- `UioMapper` is able to resolve symlinks now.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/709
- Add new `UnsignedByteField` class
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/660
## Changes
- `CService201HealthCommanding` renamed to `CServiceHealthCommanding`,
service ID customizable now. `CServiceHealthCommanding` expects configuration struct
`HealthServiceCfg` now
PR: https://egit.irs.uni-stuttgart.de/eive/fsfw/pulls/122
- `AcceptsTelemetryIF`: `getReportReceptionQueue` is const now
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/712
- Moved some container returnvalues to dedicated header and namespace
to they can be used without template specification.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/707
- Remove default secondary header argument for
`uint16_t getTcSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag)` and
`uint16_t getTmSpacePacketIdFromApid(uint16_t apid, bool secondaryHeaderFlag)`
@ -65,6 +94,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- `DeviceHandlerBase`: New signature of `handleDeviceTm` which expects
a `const SerializeIF&` and additional helper variant which expects `const uint8_t*`
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`:
- Make functions `const` where it makes sense
- Add `const char* getName const` abstract function
@ -92,6 +125,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
implementation without an extra component
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/682
## HAL
- SPI: Cache the SPI device in the communication interface. Architecturally, this makes a
lot more sense because each ComIF should be responsible for one SPI bus.
- SPI: Move the empty transfer to update the line polarity to separate function. This means
it is not automatically called when calling the setter function for SPI speed and mode.
The user should call this function after locking the CS mutex if multiple SPI devices with
differing speeds and modes are attached to one bus.
- SPI: Getter functions for SPI speed and mode.
# [v5.0.0] 25.07.2022
## Changes
@ -225,6 +268,7 @@ https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/593
- https://gitlab.kitware.com/cmake/cmake/-/issues/21696
Easiest solution for now: Keep this option OFF by default.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/616
- Linux HAL: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1
- Dedicated Version class and constant `fsfw::FSFW_VERSION` containing version information
inside `fsfw/version.h`
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
@ -239,17 +283,6 @@ https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/593
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
- `Subsystem`: New API to add table and sequence entries
## HAL
- SPI: Cache the SPI device in the communication interface. Architecturally, this makes a
lot more sense because each ComIF should be responsible for one SPI bus.
- SPI: Move the empty transfer to update the line polarity to separate function. This means
it is not automatically called when calling the setter function for SPI speed and mode.
The user should call this function after locking the CS mutex if multiple SPI devices with
differing speeds and modes are attached to one bus.
- SPI: Getter functions for SPI speed and mode.
- I2C: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1.
## Fixed
- TCP TMTC Server: `MutexGuard` was not created properly in

View File

@ -122,6 +122,7 @@ if(UNIX)
option(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS "Add Linux peripheral drivers"
OFF)
option(FSFW_HAL_LINUX_ADD_LIBGPIOD "Attempt to add Linux GPIOD drivers" OFF)
option(FSFW_HAL_LINUX_ADD_SERIAL_DRIVERS "Add serial drivers" ON)
endif()
# Optional sources

View File

@ -1,45 +1,87 @@
pipeline {
environment {
BUILDDIR = 'cmake-build-tests'
BUILDDIR_HOST = 'cmake-build-tests-host'
BUILDDIR_LINUX = 'cmake-build-tests-linux'
DOCDDIR = 'cmake-build-documentation'
}
agent {
docker {
image 'fsfw-ci:d6'
args '--network host'
args '--network host --sysctl fs.mqueue.msg_max=100'
}
}
stages {
stage('Clean') {
steps {
sh 'rm -rf $BUILDDIR'
}
}
stage('Configure') {
steps {
dir(BUILDDIR) {
sh 'cmake -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
stage('Host') {
stages{
stage('Clean') {
steps {
sh 'rm -rf $BUILDDIR_HOST'
}
}
stage('Configure') {
steps {
dir(BUILDDIR_HOST) {
sh 'cmake -DFSFW_OSAL=host -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
}
}
}
stage('Build') {
steps {
dir(BUILDDIR_HOST) {
sh 'cmake --build . -j4'
}
}
}
stage('Unittests') {
steps {
dir(BUILDDIR_HOST) {
sh 'cmake --build . -- fsfw-tests_coverage -j4'
}
}
}
stage('Valgrind') {
steps {
dir(BUILDDIR_HOST) {
sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
}
}
}
}
}
stage('Build') {
steps {
dir(BUILDDIR) {
sh 'cmake --build . -j4'
stage('Linux') {
stages{
stage('Clean') {
steps {
sh 'rm -rf $BUILDDIR_LINUX'
}
}
}
}
stage('Unittests') {
steps {
dir(BUILDDIR) {
sh 'cmake --build . -- fsfw-tests_coverage -j4'
stage('Configure') {
steps {
dir(BUILDDIR_LINUX) {
sh 'cmake -DFSFW_OSAL=linux -DFSFW_BUILD_TESTS=ON -DFSFW_CICD_BUILD=ON ..'
}
}
}
}
}
stage('Valgrind') {
steps {
dir(BUILDDIR) {
sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
stage('Build') {
steps {
dir(BUILDDIR_LINUX) {
sh 'cmake --build . -j4'
}
}
}
stage('Unittests') {
steps {
dir(BUILDDIR_LINUX) {
sh 'cmake --build . -- fsfw-tests_coverage -j4'
}
}
}
stage('Valgrind') {
steps {
dir(BUILDDIR_LINUX) {
sh 'valgrind --leak-check=full --error-exitcode=1 ./fsfw-tests'
}
}
}
}
}

View File

@ -140,7 +140,7 @@ find_program( GCOV_PATH gcov )
find_program( LCOV_PATH NAMES lcov lcov.bat lcov.exe lcov.perl)
find_program( FASTCOV_PATH NAMES fastcov fastcov.py )
find_program( GENHTML_PATH NAMES genhtml genhtml.perl genhtml.bat )
find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test)
find_program( GCOVR_PATH gcovr )
find_program( CPPFILT_PATH NAMES c++filt )
if(NOT GCOV_PATH)

View File

@ -51,7 +51,10 @@ exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
html_theme = "alabaster"
html_theme_options = {
"extra_nav_links": {"Impressum" : "https://www.uni-stuttgart.de/impressum", "Datenschutz": "https://info.irs.uni-stuttgart.de/datenschutz/datenschutzWebmit.html"}
"extra_nav_links": {
"Impressum": "https://www.uni-stuttgart.de/impressum",
"Datenschutz": "https://info.irs.uni-stuttgart.de/datenschutz/datenschutzWebmit.html",
}
}

View File

@ -4,6 +4,7 @@
#include "../returnvalues/returnvalue.h"
#include "../serialize/SerializeAdapter.h"
#include "../serialize/SerializeIF.h"
#include "definitions.h"
/**
* @brief A List that stores its values in an array.
@ -19,9 +20,6 @@ class ArrayList {
friend class SerialArrayListAdapter;
public:
static const uint8_t INTERFACE_ID = CLASS_ID::ARRAY_LIST;
static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01);
/**
* This is the allocating constructor.
* It allocates an array of the specified size.
@ -187,7 +185,7 @@ class ArrayList {
*/
ReturnValue_t insert(T entry) {
if (size >= maxSize_) {
return FULL;
return containers::LIST_FULL;
}
entries[size] = entry;
++size;

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> {
static_assert(MAX_SIZE <= std::numeric_limits<count_t>::max(),
"count_t is not large enough to hold MAX_SIZE");
static_assert(MAX_SIZE > 0, "MAX_SIZE is 0");
private:
T data[MAX_SIZE];
@ -20,15 +21,19 @@ class FixedArrayList : public ArrayList<T, count_t> {
FixedArrayList() : ArrayList<T, count_t>(data, MAX_SIZE) {}
FixedArrayList(const FixedArrayList& other) : ArrayList<T, count_t>(data, MAX_SIZE) {
memcpy(this->data, other.data, sizeof(this->data));
this->entries = data;
this->size = other.size;
for (size_t idx = 0; idx < this->size; idx++) {
data[idx] = other.data[idx];
}
}
FixedArrayList& operator=(FixedArrayList other) {
memcpy(this->data, other.data, sizeof(this->data));
this->entries = data;
this->size = other.size;
for (size_t idx = 0; idx < this->size; idx++) {
data[idx] = other.data[idx];
}
return *this;
}

View File

@ -4,8 +4,8 @@
#include <type_traits>
#include <utility>
#include "../returnvalues/returnvalue.h"
#include "ArrayList.h"
#include "definitions.h"
/**
* @brief Map implementation for maps with a pre-defined size.
@ -24,11 +24,6 @@ class FixedMap : public SerializeIF {
"derived class from SerializeIF to be serialize-able");
public:
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP;
static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);
private:
static const key_t EMPTY_SLOT = -1;
ArrayList<std::pair<key_t, T>, uint32_t> theMap;
@ -76,10 +71,10 @@ class FixedMap : public SerializeIF {
ReturnValue_t insert(key_t key, T value, Iterator* storedValue = nullptr) {
if (exists(key) == returnvalue::OK) {
return KEY_ALREADY_EXISTS;
return containers::KEY_ALREADY_EXISTS;
}
if (_size == theMap.maxSize()) {
return MAP_FULL;
return containers::MAP_FULL;
}
theMap[_size].first = key;
theMap[_size].second = value;
@ -93,7 +88,7 @@ class FixedMap : public SerializeIF {
ReturnValue_t insert(std::pair<key_t, T> pair) { return insert(pair.first, pair.second); }
ReturnValue_t exists(key_t key) const {
ReturnValue_t result = KEY_DOES_NOT_EXIST;
ReturnValue_t result = containers::KEY_DOES_NOT_EXIST;
if (findIndex(key) < _size) {
result = returnvalue::OK;
}
@ -103,7 +98,7 @@ class FixedMap : public SerializeIF {
ReturnValue_t erase(Iterator* iter) {
uint32_t i;
if ((i = findIndex((*iter).value->first)) >= _size) {
return KEY_DOES_NOT_EXIST;
return containers::KEY_DOES_NOT_EXIST;
}
theMap[i] = theMap[_size - 1];
--_size;
@ -114,7 +109,7 @@ class FixedMap : public SerializeIF {
ReturnValue_t erase(key_t key) {
uint32_t i;
if ((i = findIndex(key)) >= _size) {
return KEY_DOES_NOT_EXIST;
return containers::KEY_DOES_NOT_EXIST;
}
theMap[i] = theMap[_size - 1];
--_size;

View File

@ -0,0 +1,14 @@
#ifndef FSFW_CONTAINER_DEFINITIONS_H_
#define FSFW_CONTAINER_DEFINITIONS_H_
#include "fsfw/retval.h"
namespace containers {
static const ReturnValue_t KEY_ALREADY_EXISTS = returnvalue::makeCode(CLASS_ID::FIXED_MAP, 0x01);
static const ReturnValue_t MAP_FULL = returnvalue::makeCode(CLASS_ID::FIXED_MAP, 0x02);
static const ReturnValue_t KEY_DOES_NOT_EXIST = returnvalue::makeCode(CLASS_ID::FIXED_MAP, 0x03);
static const ReturnValue_t LIST_FULL = returnvalue::makeCode(CLASS_ID::ARRAY_LIST, 0x01);
} // namespace containers
#endif /* FSFW_CONTAINER_DEFINITIONS_H_ */

View File

@ -4,11 +4,10 @@
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/subsystem/SubsystemBase.h"
#include "fsfw/subsystem/helper.h"
ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
size_t commandQueueDepth)
ControllerBase::ControllerBase(object_id_t setObjectId, size_t commandQueueDepth)
: SystemObject(setObjectId),
parentId(parentId),
mode(MODE_OFF),
submode(SUBMODE_NONE),
modeHelper(this),
@ -21,33 +20,15 @@ ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
ControllerBase::~ControllerBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
ReturnValue_t ControllerBase::initialize() {
ReturnValue_t result = SystemObject::initialize();
ReturnValue_t result = modeHelper.initialize();
if (result != returnvalue::OK) {
return result;
}
MessageQueueId_t parentQueue = 0;
if (parentId != objects::NO_OBJECT) {
auto* parent = ObjectManager::instance()->get<SubsystemBase>(parentId);
if (parent == nullptr) {
return returnvalue::FAILED;
}
parentQueue = parent->getCommandQueue();
parent->registerChild(getObjectId());
}
result = healthHelper.initialize(parentQueue);
result = healthHelper.initialize();
if (result != returnvalue::OK) {
return result;
}
result = modeHelper.initialize(parentQueue);
if (result != returnvalue::OK) {
return result;
}
return returnvalue::OK;
return SystemObject::initialize();
}
MessageQueueId_t ControllerBase::getCommandQueue() const { return commandQueue->getId(); }
@ -120,3 +101,13 @@ void ControllerBase::setTaskIF(PeriodicTaskIF* task_) { executingTask = task_; }
void ControllerBase::changeHK(Mode_t mode_, Submode_t submode_, bool enable) {}
ReturnValue_t ControllerBase::initializeAfterTaskCreation() { return returnvalue::OK; }
const HasHealthIF* ControllerBase::getOptHealthIF() const { return this; }
const HasModesIF& ControllerBase::getModeIF() const { return *this; }
ModeTreeChildIF& ControllerBase::getModeTreeChildIF() { return *this; }
ReturnValue_t ControllerBase::connectModeTreeParent(HasModeTreeChildrenIF& parent) {
return modetree::connectModeTreeParent(parent, *this, &healthHelper, modeHelper);
}

View File

@ -6,6 +6,9 @@
#include "fsfw/modes/HasModesIF.h"
#include "fsfw/modes/ModeHelper.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/subsystem/HasModeTreeChildrenIF.h"
#include "fsfw/subsystem/ModeTreeChildIF.h"
#include "fsfw/subsystem/ModeTreeConnectionIF.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw/tasks/PeriodicTaskIF.h"
@ -18,13 +21,18 @@
class ControllerBase : public HasModesIF,
public HasHealthIF,
public ExecutableObjectIF,
public ModeTreeChildIF,
public ModeTreeConnectionIF,
public SystemObject {
public:
static const Mode_t MODE_NORMAL = 2;
ControllerBase(object_id_t setObjectId, object_id_t parentId, size_t commandQueueDepth = 3);
ControllerBase(object_id_t setObjectId, size_t commandQueueDepth = 3);
~ControllerBase() override;
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override;
ModeTreeChildIF &getModeTreeChildIF() override;
/** SystemObject override */
ReturnValue_t initialize() override;
@ -38,6 +46,8 @@ class ControllerBase : public HasModesIF,
ReturnValue_t performOperation(uint8_t opCode) override;
void setTaskIF(PeriodicTaskIF *task) override;
ReturnValue_t initializeAfterTaskCreation() override;
const HasHealthIF *getOptHealthIF() const override;
const HasModesIF &getModeIF() const override;
protected:
/**
@ -56,8 +66,6 @@ class ControllerBase : public HasModesIF,
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) override = 0;
const object_id_t parentId;
Mode_t mode;
Submode_t submode;

View File

@ -1,8 +1,7 @@
#include "fsfw/controller/ExtendedControllerBase.h"
ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, object_id_t parentId,
size_t commandQueueDepth)
: ControllerBase(objectId, parentId, commandQueueDepth),
ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, size_t commandQueueDepth)
: ControllerBase(objectId, commandQueueDepth),
poolManager(this, commandQueue),
actionHelper(this, commandQueue) {}

View File

@ -17,7 +17,7 @@ class ExtendedControllerBase : public ControllerBase,
public HasActionsIF,
public HasLocalDataPoolIF {
public:
ExtendedControllerBase(object_id_t objectId, object_id_t parentId, size_t commandQueueDepth = 3);
ExtendedControllerBase(object_id_t objectId, size_t commandQueueDepth = 3);
~ExtendedControllerBase() override;
/* SystemObjectIF overrides */

View File

@ -1,7 +1,7 @@
#include "fsfw/devicehandlers/AssemblyBase.h"
AssemblyBase::AssemblyBase(object_id_t objectId, object_id_t parentId, uint16_t commandQueueDepth)
: SubsystemBase(objectId, parentId, MODE_OFF, commandQueueDepth),
AssemblyBase::AssemblyBase(object_id_t objectId, uint16_t commandQueueDepth)
: SubsystemBase(objectId, MODE_OFF, commandQueueDepth),
internalState(STATE_NONE),
recoveryState(RECOVERY_IDLE),
recoveringDevice(childrenMap.end()),

View File

@ -41,7 +41,7 @@ class AssemblyBase : public SubsystemBase {
static const ReturnValue_t NEED_TO_CHANGE_HEALTH = MAKE_RETURN_CODE(0x05);
static const ReturnValue_t NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE = MAKE_RETURN_CODE(0xa1);
AssemblyBase(object_id_t objectId, object_id_t parentId, uint16_t commandQueueDepth = 8);
AssemblyBase(object_id_t objectId, uint16_t commandQueueDepth = 8);
virtual ~AssemblyBase();
protected:

View File

@ -3,17 +3,12 @@
#include "fsfw/subsystem/SubsystemBase.h"
ChildHandlerBase::ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication,
CookieIF* cookie, object_id_t hkDestination,
uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId,
object_id_t parent, FailureIsolationBase* customFdir,
size_t cmdQueueSize)
CookieIF* cookie, HasModeTreeChildrenIF& parent,
FailureIsolationBase* customFdir, size_t cmdQueueSize)
: DeviceHandlerBase(setObjectId, deviceCommunication, cookie,
(customFdir == nullptr ? &childHandlerFdir : customFdir), cmdQueueSize),
parentId(parent),
childHandlerFdir(setObjectId) {
this->setHkDestination(hkDestination);
this->setThermalStateRequestPoolIds(thermalStatePoolId, thermalRequestPoolId);
}
parent(parent),
childHandlerFdir(setObjectId) {}
ChildHandlerBase::~ChildHandlerBase() {}
@ -23,21 +18,5 @@ ReturnValue_t ChildHandlerBase::initialize() {
return result;
}
MessageQueueId_t parentQueue = 0;
if (parentId != objects::NO_OBJECT) {
SubsystemBase* parent = ObjectManager::instance()->get<SubsystemBase>(parentId);
if (parent == NULL) {
return returnvalue::FAILED;
}
parentQueue = parent->getCommandQueue();
parent->registerChild(getObjectId());
}
healthHelper.setParentQueue(parentQueue);
modeHelper.setParentQueue(parentQueue);
return returnvalue::OK;
return DeviceHandlerBase::connectModeTreeParent(parent);
}

View File

@ -1,22 +1,23 @@
#ifndef FSFW_DEVICEHANDLER_CHILDHANDLERBASE_H_
#define FSFW_DEVICEHANDLER_CHILDHANDLERBASE_H_
#include <fsfw/subsystem/HasModeTreeChildrenIF.h>
#include "ChildHandlerFDIR.h"
#include "DeviceHandlerBase.h"
class ChildHandlerBase : public DeviceHandlerBase {
public:
ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, CookieIF* cookie,
object_id_t hkDestination, uint32_t thermalStatePoolId,
uint32_t thermalRequestPoolId, object_id_t parent = objects::NO_OBJECT,
FailureIsolationBase* customFdir = nullptr, size_t cmdQueueSize = 20);
HasModeTreeChildrenIF& parent, FailureIsolationBase* customFdir = nullptr,
size_t cmdQueueSize = 20);
virtual ~ChildHandlerBase();
virtual ReturnValue_t initialize();
protected:
const uint32_t parentId;
HasModeTreeChildrenIF& parent;
ChildHandlerFDIR childHandlerFdir;
};

View File

@ -1,5 +1,6 @@
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
#include "DeviceHandlerBase.h"
#include "fsfw/datapool/PoolReadGuard.h"
#include "fsfw/datapoollocal/LocalPoolVariable.h"
#include "fsfw/devicehandlers/AcceptsDeviceResponsesIF.h"
#include "fsfw/devicehandlers/DeviceTmReportingWrapper.h"
@ -12,6 +13,7 @@
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw/storagemanager/StorageManagerIF.h"
#include "fsfw/subsystem/SubsystemBase.h"
#include "fsfw/subsystem/helper.h"
#include "fsfw/thermal/ThermalComponentIF.h"
object_id_t DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT;
@ -132,14 +134,6 @@ ReturnValue_t DeviceHandlerBase::initialize() {
new DeviceHandlerFailureIsolation(this->getObjectId(), defaultFdirParentId);
}
if (this->parent != objects::NO_OBJECT) {
HasModesIF* modeIF = ObjectManager::instance()->get<HasModesIF>(this->parent);
HasHealthIF* healthIF = ObjectManager::instance()->get<HasHealthIF>(this->parent);
if (modeIF != nullptr and healthIF != nullptr) {
setParentQueue(modeIF->getCommandQueue());
}
}
communicationInterface =
ObjectManager::instance()->get<DeviceCommunicationIF>(deviceCommunicationId);
if (communicationInterface == nullptr) {
@ -368,6 +362,8 @@ void DeviceHandlerBase::doStateMachine() {
if ((switchState == PowerSwitchIF::SWITCH_ON) || (switchState == NO_SWITCH)) {
// NOTE: TransitionSourceMode and -SubMode are set by handleCommandedModeTransition
childTransitionFailure = CHILD_TIMEOUT;
transitionSourceMode = _MODE_SHUT_DOWN;
transitionSourceSubMode = SUBMODE_NONE;
setMode(_MODE_START_UP);
callChildStatemachine();
}
@ -573,7 +569,6 @@ void DeviceHandlerBase::setTransition(Mode_t modeTo, Submode_t submodeTo) {
}
void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
/**
* handle transition from OFF to NORMAL by continuing towards normal when ON is reached
*/
@ -1530,7 +1525,10 @@ DeviceCommandId_t DeviceHandlerBase::getPendingCommand() const {
void DeviceHandlerBase::setNormalDatapoolEntriesInvalid() {
for (const auto& reply : deviceReplyMap) {
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);
}
}
}
}
@ -1587,19 +1585,13 @@ MessageQueueId_t DeviceHandlerBase::getCommanderQueueId(DeviceCommandId_t replyI
void DeviceHandlerBase::setCustomFdir(FailureIsolationBase* fdir) { this->fdirInstance = fdir; }
void DeviceHandlerBase::setParent(object_id_t parent) { this->parent = parent; }
void DeviceHandlerBase::setPowerSwitcher(PowerSwitchIF* switcher) {
this->powerSwitcher = switcher;
}
Mode_t DeviceHandlerBase::getMode() {
return mode;
}
Mode_t DeviceHandlerBase::getMode() { return mode; }
Submode_t DeviceHandlerBase::getSubmode() {
return submode;
}
Submode_t DeviceHandlerBase::getSubmode() { return submode; }
void DeviceHandlerBase::disableCommandsAndReplies() {
for (auto& command : deviceCommandMap) {
@ -1619,6 +1611,16 @@ void DeviceHandlerBase::disableCommandsAndReplies() {
}
}
ReturnValue_t DeviceHandlerBase::connectModeTreeParent(HasModeTreeChildrenIF& parent) {
return modetree::connectModeTreeParent(parent, *this, &healthHelper, modeHelper);
}
const HasHealthIF* DeviceHandlerBase::getOptHealthIF() const { return this; }
const HasModesIF& DeviceHandlerBase::getModeIF() const { return *this; }
ModeTreeChildIF& DeviceHandlerBase::getModeTreeChildIF() { return *this; }
ReturnValue_t DeviceHandlerBase::finishAction(bool success, DeviceCommandId_t action,
ReturnValue_t result) {
auto commandIter = deviceCommandMap.find(action);

View File

@ -21,9 +21,9 @@
#include "fsfw/returnvalues/returnvalue.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw/serviceinterface/serviceInterfaceDefintions.h"
#include "fsfw/subsystem/ModeTreeConnectionIF.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw/tasks/PeriodicTaskIF.h"
#include "fsfw/util/dataWrapper.h"
namespace Factory {
void setStaticFrameworkObjectIds();
@ -84,6 +84,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
public HasModesIF,
public HasHealthIF,
public HasActionsIF,
public ModeTreeChildIF,
public ModeTreeConnectionIF,
public ReceivesParameterMessagesIF,
public HasLocalDataPoolIF {
friend void(Factory::setStaticFrameworkObjectIds)();
@ -104,7 +106,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
FailureIsolationBase *fdirInstance = nullptr, size_t cmdQueueSize = 20);
void setCustomFdir(FailureIsolationBase *fdir);
void setParent(object_id_t parent);
void setPowerSwitcher(PowerSwitchIF *switcher);
/**
@ -169,6 +170,10 @@ class DeviceHandlerBase : public DeviceHandlerIF,
lp_id_t thermalStatePoolId = DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID,
lp_id_t thermalRequestPoolId = DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID,
uint32_t thermalSetId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID);
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override;
ModeTreeChildIF &getModeTreeChildIF() override;
/**
* @brief Helper function to ease device handler development.
* This will instruct the transition to MODE_ON immediately
@ -214,7 +219,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* @param counter Specifies which Action to perform
* @return returnvalue::OK for successful execution
*/
virtual ReturnValue_t performOperation(uint8_t counter) override;
ReturnValue_t performOperation(uint8_t counter) override;
/**
* @brief Initializes the device handler
@ -224,14 +229,14 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* Calls fillCommandAndReplyMap().
* @return
*/
virtual ReturnValue_t initialize() override;
ReturnValue_t initialize() override;
/**
* @brief Intialization steps performed after all tasks have been created.
* This function will be called by the executing task.
* @return
*/
virtual ReturnValue_t initializeAfterTaskCreation() override;
ReturnValue_t initializeAfterTaskCreation() override;
/** Destructor. */
virtual ~DeviceHandlerBase();
@ -248,6 +253,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
virtual object_id_t getObjectId() const override;
/**
* This is a helper method for classes which are parent nodes in the mode tree.
* It registers the passed queue as the destination for mode and health messages.
* @param parentQueueId
*/
virtual void setParentQueue(MessageQueueId_t parentQueueId);
@ -1012,6 +1019,9 @@ class DeviceHandlerBase : public DeviceHandlerIF,
*/
LocalDataPoolManager *getHkManagerHandle() override;
const HasHealthIF *getOptHealthIF() const override;
const HasModesIF &getModeIF() const override;
/**
* Returns the delay cycle count of a reply.
* A count != 0 indicates that the command is already executed.

View File

@ -4,7 +4,6 @@
#include "fsfw/action/HasActionsIF.h"
#include "fsfw/objectmanager/SystemObjectIF.h"
#include "fsfw/serialize/SerializeIF.h"
#include "fsfw/util/dataWrapper.h"
class DeviceTmReportingWrapper : public SerializeIF {
public:

View File

@ -24,6 +24,7 @@ EventManager::EventManager(object_id_t setObjectId)
}
EventManager::~EventManager() {
listenerList.clear();
QueueFactory::instance()->deleteMessageQueue(eventReportQueue);
MutexFactory::instance()->deleteMutex(mutex);
}
@ -73,9 +74,14 @@ ReturnValue_t EventManager::registerListener(MessageQueueId_t listener,
if (!result.second) {
return returnvalue::FAILED;
}
return returnvalue::OK;
}
ReturnValue_t EventManager::unregisterListener(MessageQueueId_t listener) {
return listenerList.erase(listener) == 1 ? returnvalue::OK : returnvalue::FAILED;
}
ReturnValue_t EventManager::subscribeToEvent(MessageQueueId_t listener, EventId_t event) {
return subscribeToEventRange(listener, event);
}

View File

@ -31,6 +31,7 @@ class EventManager : public EventManagerIF, public ExecutableObjectIF, public Sy
MessageQueueId_t getEventReportQueue();
ReturnValue_t registerListener(MessageQueueId_t listener, bool forwardAllButSelected = false);
ReturnValue_t unregisterListener(MessageQueueId_t listener) override;
ReturnValue_t subscribeToEvent(MessageQueueId_t listener, EventId_t event);
ReturnValue_t subscribeToAllEventsFrom(MessageQueueId_t listener, object_id_t object);
ReturnValue_t subscribeToEventRange(MessageQueueId_t listener, EventId_t idFrom = 0,

View File

@ -18,6 +18,7 @@ class EventManagerIF {
virtual ReturnValue_t registerListener(MessageQueueId_t listener,
bool forwardAllButSelected = false) = 0;
virtual ReturnValue_t unregisterListener(MessageQueueId_t listener) = 0;
virtual ReturnValue_t subscribeToEvent(MessageQueueId_t listener, EventId_t event) = 0;
virtual ReturnValue_t subscribeToAllEventsFrom(MessageQueueId_t listener, object_id_t object) = 0;
virtual ReturnValue_t unsubscribeFromAllEvents(MessageQueueId_t listener, object_id_t object) = 0;

View File

@ -24,7 +24,7 @@ FailureIsolationBase::~FailureIsolationBase() {
#endif
return;
}
manager->unsubscribeFromAllEvents(eventQueue->getId(), ownerId);
manager->unregisterListener(eventQueue->getId());
QueueFactory::instance()->deleteMessageQueue(eventQueue);
}

View File

@ -24,7 +24,7 @@ class MatchTree : public SerializeableMatcherIF<T>, public BinaryTree<Serializea
MatchTree(iterator root, uint8_t maxDepth = -1)
: BinaryTree<SerializeableMatcherIF<T>>(root.element), maxDepth(maxDepth) {}
MatchTree() : BinaryTree<SerializeableMatcherIF<T>>(), maxDepth(-1) {}
virtual ~MatchTree() {}
virtual ~MatchTree() { clear(); }
virtual bool match(T number) override { return matchesTree(number); }
bool matchesTree(T number) {
iterator iter = this->begin();
@ -176,6 +176,45 @@ class MatchTree : public SerializeableMatcherIF<T>, public BinaryTree<Serializea
return cleanUpElement(position);
}
void clear() {
Node* localRoot = BinaryTree<SerializeableMatcherIF<T>>::rootNode;
if (localRoot == nullptr) {
return;
}
Node* node = localRoot->left;
while (true) {
if (node->left != nullptr) {
node = node->left;
continue;
}
if (node->right != nullptr) {
node = node->right;
continue;
}
if (node->parent == nullptr) {
// this is the root node with no children
if (node->value != nullptr) {
cleanUpElement(iterator(node));
}
return;
}
// leaf
{
Node* parent = node->parent;
if (parent->left == node) {
parent->left = nullptr;
} else {
parent->right = nullptr;
}
cleanUpElement(iterator(node));
node = parent;
}
}
}
virtual ReturnValue_t cleanUpElement(iterator position) { return returnvalue::OK; }
bool matchSubtree(iterator iter, T number) {

View File

@ -1,8 +1,8 @@
#include "fsfw/globalfunctions/timevalOperations.h"
timeval& operator+=(timeval& lhs, const timeval& rhs) {
int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec;
sum += rhs.tv_sec * 1000000. + rhs.tv_usec;
int64_t sum = static_cast<int64_t>(lhs.tv_sec) * 1000000. + lhs.tv_usec;
sum += static_cast<int64_t>(rhs.tv_sec) * 1000000. + rhs.tv_usec;
lhs.tv_sec = sum / 1000000;
lhs.tv_usec = sum - lhs.tv_sec * 1000000;
return lhs;

View File

@ -5,7 +5,11 @@
HealthHelper::HealthHelper(HasHealthIF* owner, object_id_t objectId)
: objectId(objectId), owner(owner) {}
HealthHelper::~HealthHelper() { healthTable->removeObject(objectId); }
HealthHelper::~HealthHelper() {
if (healthTable != nullptr) {
healthTable->removeObject(objectId);
}
}
ReturnValue_t HealthHelper::handleHealthCommand(CommandMessage* message) {
switch (message->getCommand()) {

View File

@ -6,8 +6,6 @@
HealthTable::HealthTable(object_id_t objectid) : SystemObject(objectid) {
mutex = MutexFactory::instance()->createMutex();
;
mapIterator = healthMap.begin();
}

View File

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

View File

@ -10,13 +10,17 @@ InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t m
poolManager(this, commandQueue),
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
internalErrorDataset(this) {
commandQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
mutex = MutexFactory::instance()->createMutex();
auto mqArgs = MqArgs(setObjectId, static_cast<void *>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
messageQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
InternalErrorReporter::~InternalErrorReporter() { MutexFactory::instance()->deleteMutex(mutex); }
InternalErrorReporter::~InternalErrorReporter() {
MutexFactory::instance()->deleteMutex(mutex);
QueueFactory::instance()->deleteMessageQueue(commandQueue);
}
void InternalErrorReporter::setDiagnosticPrintout(bool enable) {
this->diagnosticPrintout = enable;

View File

@ -24,3 +24,19 @@ void ModeMessage::setCantReachMode(CommandMessage* message, ReturnValue_t reason
message->setParameter(reason);
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

@ -1,43 +1,42 @@
#ifndef FSFW_MODES_MODEMESSAGE_H_
#define FSFW_MODES_MODEMESSAGE_H_
#include "../ipc/CommandMessage.h"
#include "fsfw/ipc/CommandMessage.h"
typedef uint32_t Mode_t;
typedef uint8_t Submode_t;
class ModeMessage {
private:
ModeMessage();
public:
static const uint8_t MESSAGE_ID = messagetypes::MODE_COMMAND;
static const Command_t CMD_MODE_COMMAND =
MAKE_COMMAND_ID(0x01); //!> Command to set the specified Mode, replies are: REPLY_MODE_REPLY,
//! REPLY_WRONG_MODE_REPLY, and REPLY_REJECTED; don't add any replies,
//! as this will break the subsystem mode machine!!
static const Command_t CMD_MODE_COMMAND_FORCED = MAKE_COMMAND_ID(
0xF1); //!> Command to set the specified Mode, regardless of external control flag, replies
//! are: REPLY_MODE_REPLY, REPLY_WRONG_MODE_REPLY, and REPLY_REJECTED; don't add any
//! replies, as this will break the subsystem mode machine!!
static const Command_t REPLY_MODE_REPLY =
MAKE_COMMAND_ID(0x02); //!> Reply to a CMD_MODE_COMMAND or CMD_MODE_READ
static const Command_t REPLY_MODE_INFO =
MAKE_COMMAND_ID(0x03); //!> Unrequested info about the current mode (used for composites to
//! inform their container of a changed mode)
static const Command_t REPLY_CANT_REACH_MODE = MAKE_COMMAND_ID(
0x04); //!> Reply in case a mode command can't be executed. Par1: returnCode, Par2: 0
static const Command_t REPLY_WRONG_MODE_REPLY =
MAKE_COMMAND_ID(0x05); //!> Reply to a CMD_MODE_COMMAND, indicating that a mode was commanded
//! and a transition started but was aborted; the parameters contain
//! the mode that was reached
static const Command_t CMD_MODE_READ = MAKE_COMMAND_ID(
0x06); //!> Command to read the current mode and reply with a REPLY_MODE_REPLY
static const Command_t CMD_MODE_ANNOUNCE = MAKE_COMMAND_ID(
0x07); //!> Command to trigger an ModeInfo Event. This command does NOT have a reply.
static const Command_t CMD_MODE_ANNOUNCE_RECURSIVELY =
MAKE_COMMAND_ID(0x08); //!> Command to trigger an ModeInfo Event and to send this command to
//! every child. This command does NOT have a reply.
//!> Command to set the specified Mode, replies are: REPLY_MODE_REPLY,
//! REPLY_WRONG_MODE_REPLY, and REPLY_REJECTED; don't add any replies,
//! as this will break the subsystem mode machine!!
static const Command_t CMD_MODE_COMMAND = MAKE_COMMAND_ID(0x01);
//!> Command to set the specified Mode, regardless of external control flag, replies
//! are: REPLY_MODE_REPLY, REPLY_WRONG_MODE_REPLY, and REPLY_REJECTED; don't add any
//! replies, as this will break the subsystem mode machine!!
static const Command_t CMD_MODE_COMMAND_FORCED = MAKE_COMMAND_ID(0xF1);
//!> Reply to a CMD_MODE_COMMAND or CMD_MODE_READ
static const Command_t REPLY_MODE_REPLY = MAKE_COMMAND_ID(0x02);
//!> Unrequested info about the current mode (used for composites to
//! inform their container of a changed mode)
static const Command_t REPLY_MODE_INFO = MAKE_COMMAND_ID(0x03);
//!> Reply in case a mode command can't be executed. Par1: returnCode, Par2: 0
static const Command_t REPLY_CANT_REACH_MODE = MAKE_COMMAND_ID(0x04);
//!> Reply to a CMD_MODE_COMMAND, indicating that a mode was commanded
//! and a transition started but was aborted; the parameters contain
//! the mode that was reached
static const Command_t REPLY_WRONG_MODE_REPLY = MAKE_COMMAND_ID(0x05);
//!> Command to read the current mode and reply with a REPLY_MODE_REPLY
static const Command_t CMD_MODE_READ = MAKE_COMMAND_ID(0x06);
//!> Command to trigger an ModeInfo Event. This command does NOT have a reply.
static const Command_t CMD_MODE_ANNOUNCE = MAKE_COMMAND_ID(0x07);
//!> Command to trigger an ModeInfo Event and to send this command to
//! every child. This command does NOT have a reply.
static const Command_t CMD_MODE_ANNOUNCE_RECURSIVELY = MAKE_COMMAND_ID(0x08);
ModeMessage() = delete;
static Mode_t getMode(const CommandMessage* message);
static Submode_t getSubmode(const CommandMessage* message);
@ -45,6 +44,9 @@ class ModeMessage {
static void setModeMessage(CommandMessage* message, Command_t command, Mode_t mode,
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 clear(CommandMessage* message);
};

View File

@ -23,9 +23,17 @@ void ObjectManager::setObjectFactoryFunction(produce_function_t objFactoryFunc,
ObjectManager::ObjectManager() = default;
void ObjectManager::clear() {
if (objManagerInstance != nullptr) {
delete objManagerInstance;
objManagerInstance = nullptr;
}
}
ObjectManager::~ObjectManager() {
for (auto const& iter : objectList) {
delete iter.second;
teardown = true;
for (auto iter = objectList.begin(); iter != objectList.end(); iter = objectList.erase(iter)) {
delete iter->second;
}
}
@ -53,6 +61,12 @@ ReturnValue_t ObjectManager::insert(object_id_t id, SystemObjectIF* object) {
}
ReturnValue_t ObjectManager::remove(object_id_t id) {
// this function is called during destruction of System Objects
// disabeld for teardown to avoid iterator invalidation and
// double free
if (teardown) {
return returnvalue::OK;
}
if (this->getSystemObject(id) != nullptr) {
this->objectList.erase(id);
#if FSFW_CPP_OSTREAM_ENABLED == 1

View File

@ -24,12 +24,17 @@ class ObjectManager : public ObjectManagerIF {
using produce_function_t = void (*)(void* args);
/**
* Returns the single instance of TaskFactory.
* Returns the single instance of ObjectManager.
* The implementation of #instance is found in its subclasses.
* Thus, we choose link-time variability of the instance.
*/
static ObjectManager* instance();
/**
* Deletes the single instance of ObjectManager
*/
static void clear();
void setObjectFactoryFunction(produce_function_t prodFunc, void* args);
template <typename T>
@ -66,6 +71,9 @@ class ObjectManager : public ObjectManagerIF {
*/
std::map<object_id_t, SystemObjectIF*> objectList;
static ObjectManager* objManagerInstance;
// used when the OM itself is deleted to modify behaviour of remove()
// to avoid iterator invalidation and double free
bool teardown = false;
};
// Documentation can be found in the class method declaration above

View File

@ -1,10 +1,13 @@
# Check the OS_FSFW variable
if(FSFW_OSAL MATCHES "freertos")
add_subdirectory(freertos)
set(FSFW_OSAL_FREERTOS 1)
elseif(FSFW_OSAL MATCHES "rtems")
add_subdirectory(rtems)
set(FSFW_OSAL_RTEMS 1)
elseif(FSFW_OSAL MATCHES "linux")
add_subdirectory(linux)
set(FSFW_OSAL_LINUX 1)
elseif(FSFW_OSAL MATCHES "host")
add_subdirectory(host)
if(WIN32)
@ -13,18 +16,20 @@ elseif(FSFW_OSAL MATCHES "host")
# We still need to pull in some Linux specific sources
target_sources(${LIB_FSFW_NAME} PUBLIC linux/tcpipHelpers.cpp)
endif()
set(FSFW_OSAL_HOST 1)
else()
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
if(WIN32)
add_subdirectory(host)
add_subdirectory(windows)
set(FSFW_OSAL_HOST 1)
elseif(UNIX)
add_subdirectory(linux)
set(FSFW_OSAL_LINUX 1)
else()
# MacOS or other OSes have not been tested yet / are not supported.
message(FATAL_ERROR "The host OS could not be determined! Aborting.")
@ -33,3 +38,5 @@ else()
endif()
add_subdirectory(common)
configure_file(osal.h.in ${CMAKE_BINARY_DIR}/fsfw/osal/osal.h)

View File

@ -26,12 +26,12 @@
const std::string TcpTmTcServer::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
TcpTmTcServer::TcpTmTcServer(object_id_t objectId, object_id_t tmtcTcpBridge,
size_t receptionBufferSize, size_t ringBufferSize,
std::string customTcpServerPort, ReceptionModes receptionMode)
TcpTmTcServer::TcpConfig cfg, size_t receptionBufferSize,
size_t ringBufferSize, ReceptionModes receptionMode)
: SystemObject(objectId),
tmtcBridgeId(tmtcTcpBridge),
receptionMode(receptionMode),
tcpConfig(std::move(customTcpServerPort)),
tcpConfig(cfg),
receptionBuffer(receptionBufferSize),
ringBuffer(ringBufferSize, true) {}
@ -91,6 +91,15 @@ ReturnValue_t TcpTmTcServer::initialize() {
return returnvalue::FAILED;
}
if (tcpConfig.reuseAddr) {
unsigned int enable = 1;
setsockopt(listenerTcpSocket, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
}
if (tcpConfig.reusePort) {
unsigned int enable = 1;
setsockopt(listenerTcpSocket, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable));
}
// Bind to the address found by getaddrinfo
retval = bind(listenerTcpSocket, addrResult->ai_addr, static_cast<int>(addrResult->ai_addrlen));
if (retval == SOCKET_ERROR) {
@ -274,6 +283,8 @@ ReturnValue_t TcpTmTcServer::handleTmSending(socket_t connSocket, bool& tmSent)
ConstStorageAccessor storeAccessor(storeId);
ReturnValue_t result = tmStore->getData(storeId, storeAccessor);
if (result != returnvalue::OK) {
// Invalid entry, pop FIFO
tmtcBridge->tmFifo->pop();
return result;
}
if (wiretappingEnabled) {

View File

@ -41,11 +41,11 @@ class SpacePacketParser;
*/
class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableObjectIF {
public:
enum class ReceptionModes { SPACE_PACKETS };
struct TcpConfig {
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
@ -63,9 +63,25 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
*/
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 constexpr size_t ETHERNET_MTU_SIZE = 1500;
@ -80,10 +96,9 @@ class TcpTmTcServer : public SystemObject, public TcpIpBase, public ExecutableOb
* size will be the Ethernet MTU size
* @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 ringBufferSize = RING_BUFFER_SIZE,
std::string customTcpServerPort = DEFAULT_SERVER_PORT,
ReceptionModes receptionMode = ReceptionModes::SPACE_PACKETS);
~TcpTmTcServer() override;

View File

@ -21,7 +21,7 @@ MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize, MqArgs*
attributes.mq_msgsize = maxMessageSize;
attributes.mq_flags = 0; // Flags are ignored on Linux during mq_open
// Set the name of the queue. The slash is mandatory!
sprintf(name, "/FSFW_MQ%u\n", queueCounter++);
sprintf(name, "/FSFW_MQ%u", queueCounter++);
// Create a nonblocking queue if the name is available (the queue is read
// and writable for the owner as well as the group)

36
src/fsfw/osal/osal.h.in Normal file
View File

@ -0,0 +1,36 @@
#pragma once
namespace osal {
enum osalTarget{
HOST,
LINUX,
WINDOWS,
FREERTOS,
RTEMS,
};
#cmakedefine FSFW_OSAL_HOST
#cmakedefine FSFW_OSAL_LINUX
#cmakedefine FSFW_OSAL_WINDOWS
#cmakedefine FSFW_OSAL_FREERTOS
#cmakedefine FSFW_OSAL_RTEMS
constexpr osalTarget getTarget() {
#ifdef FSFW_OSAL_HOST
return HOST;
#endif
#ifdef FSFW_OSAL_LINUX
return LINUX;
#endif
#ifdef FSFW_OSAL_WINDOWS
return WINDOWS;
#endif
#ifdef FSFW_OSAL_FREERTOS
return FREERTOS;
#endif
#ifdef FSFW_OSAL_RTEMS
return RTEMS;
#endif
}
};

View File

@ -3,7 +3,7 @@
#include <fsfw/ipc/QueueFactory.h>
#include <fsfw/power/PowerSwitchIF.h>
PowerSwitcherComponent::PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF *pwrSwitcher,
PowerSwitcherComponent::PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF* pwrSwitcher,
power::Switch_t pwrSwitch)
: SystemObject(objectId),
switcher(pwrSwitcher, pwrSwitch),
@ -54,7 +54,7 @@ ReturnValue_t PowerSwitcherComponent::initialize() {
MessageQueueId_t PowerSwitcherComponent::getCommandQueue() const { return queue->getId(); }
void PowerSwitcherComponent::getMode(Mode_t *mode, Submode_t *submode) {
void PowerSwitcherComponent::getMode(Mode_t* mode, Submode_t* submode) {
*mode = this->mode;
*submode = this->submode;
}
@ -65,7 +65,7 @@ ReturnValue_t PowerSwitcherComponent::setHealth(HealthState health) {
}
ReturnValue_t PowerSwitcherComponent::checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) {
uint32_t* msToReachTheMode) {
*msToReachTheMode = 5000;
if (mode != MODE_ON and mode != MODE_OFF) {
return TRANS_NOT_ALLOWED;
@ -105,3 +105,15 @@ void PowerSwitcherComponent::setMode(Mode_t newMode, Submode_t newSubmode) {
}
HasHealthIF::HealthState PowerSwitcherComponent::getHealth() { return healthHelper.getHealth(); }
const HasHealthIF* PowerSwitcherComponent::getOptHealthIF() const { return this; }
const HasModesIF& PowerSwitcherComponent::getModeIF() const { return *this; }
ReturnValue_t PowerSwitcherComponent::connectModeTreeParent(HasModeTreeChildrenIF& parent) {
return parent.registerChild(*this);
}
object_id_t PowerSwitcherComponent::getObjectId() const { return SystemObject::getObjectId(); }
ModeTreeChildIF& PowerSwitcherComponent::getModeTreeChildIF() { return *this; }

View File

@ -8,6 +8,8 @@
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/power/PowerSwitcher.h>
#include <fsfw/power/definitions.h>
#include <fsfw/subsystem/ModeTreeChildIF.h>
#include <fsfw/subsystem/ModeTreeConnectionIF.h>
#include <fsfw/tasks/ExecutableObjectIF.h>
class PowerSwitchIF;
@ -24,12 +26,17 @@ class PowerSwitchIF;
*/
class PowerSwitcherComponent : public SystemObject,
public ExecutableObjectIF,
public ModeTreeChildIF,
public ModeTreeConnectionIF,
public HasModesIF,
public HasHealthIF {
public:
PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF *pwrSwitcher,
power::Switch_t pwrSwitch);
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override;
ModeTreeChildIF &getModeTreeChildIF() override;
private:
MessageQueueIF *queue = nullptr;
PowerSwitcher switcher;
@ -56,6 +63,10 @@ class PowerSwitcherComponent : public SystemObject,
ReturnValue_t setHealth(HealthState health) override;
HasHealthIF::HealthState getHealth() override;
object_id_t getObjectId() const override;
const HasHealthIF *getOptHealthIF() const override;
const HasModesIF &getModeIF() const override;
};
#endif /* _FSFW_POWER_POWERSWITCHERCOMPONENT_H_ */

View File

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

View File

@ -20,6 +20,7 @@ ReturnValue_t CService200ModeCommanding::isValidSubservice(uint8_t subservice) {
case (Subservice::COMMAND_MODE_COMMAND):
case (Subservice::COMMAND_MODE_READ):
case (Subservice::COMMAND_MODE_ANNCOUNCE):
case (Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY):
return returnvalue::OK;
default:
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
@ -53,16 +54,36 @@ ReturnValue_t CService200ModeCommanding::checkInterfaceAndAcquireMessageQueue(
ReturnValue_t CService200ModeCommanding::prepareCommand(CommandMessage *message, uint8_t subservice,
const uint8_t *tcData, size_t tcDataLen,
uint32_t *state, object_id_t objectId) {
ModePacket modeCommandPacket;
ReturnValue_t result =
modeCommandPacket.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
if (result != returnvalue::OK) {
return result;
}
switch (subservice) {
case (Subservice::COMMAND_MODE_COMMAND): {
ModePacket modeCommandPacket;
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(),
modeCommandPacket.getSubmode());
return result;
ModeMessage::setModeMessage(message, ModeMessage::CMD_MODE_COMMAND,
modeCommandPacket.getMode(), modeCommandPacket.getSubmode());
return returnvalue::OK;
}
case (Subservice::COMMAND_MODE_ANNCOUNCE):
case (Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY): {
bool recursive = true;
if (subservice == Subservice::COMMAND_MODE_ANNCOUNCE) {
recursive = false;
}
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,
@ -73,8 +94,10 @@ ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply
ReturnValue_t result = returnvalue::FAILED;
switch (replyId) {
case (ModeMessage::REPLY_MODE_REPLY): {
result = prepareModeReply(reply, objectId);
break;
if (previousCommand != ModeMessage::CMD_MODE_COMMAND) {
return prepareModeReply(reply, objectId);
}
return returnvalue::OK;
}
case (ModeMessage::REPLY_WRONG_MODE_REPLY): {
result = prepareWrongModeReply(reply, objectId);

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,152 @@
#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),
healthTable(args.table),
maxNumHealthInfoPerCycle(args.maxNumHealthInfoPerCycle) {}
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): {
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): {
ReturnValue_t result = iterateHealthTable(true);
if (result == returnvalue::OK) {
reportAllHealth = true;
return EXECUTION_COMPLETE;
}
return result;
while (true) {
ReturnValue_t result = iterateHealthTable(false);
if (result != returnvalue::OK) {
break;
}
}
return returnvalue::OK;
}
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_
#define FSFW_PUS_CSERVICE201HEALTHCOMMANDING_H_
#include <fsfw/health/HealthTable.h>
#include "fsfw/tmtcservices/CommandingServiceBase.h"
struct HealthServiceCfg {
HealthServiceCfg(object_id_t objectId, uint16_t apid, HealthTable &healthTable,
uint16_t maxNumHealthInfoPerCycle)
: objectId(objectId),
apid(apid),
table(healthTable),
maxNumHealthInfoPerCycle(maxNumHealthInfoPerCycle) {}
object_id_t objectId;
uint16_t apid;
HealthTable &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
* implementing hasHealthIF.
@ -17,11 +35,10 @@
* child class like this service
*
*/
class CService201HealthCommanding : public CommandingServiceBase {
class CServiceHealthCommanding : public CommandingServiceBase {
public:
CService201HealthCommanding(object_id_t objectId, uint16_t apid, uint8_t serviceId,
uint8_t numParallelCommands = 4, uint16_t commandTimeoutSeconds = 60);
~CService201HealthCommanding() override = default;
CServiceHealthCommanding(HealthServiceCfg args);
~CServiceHealthCommanding() override = default;
protected:
/* CSB abstract function implementations */
@ -37,7 +54,13 @@ class CService201HealthCommanding : public CommandingServiceBase {
CommandMessage *optionalNextCommand, object_id_t objectId,
bool *isStep) override;
void doPeriodicOperation() override;
private:
HealthTable &healthTable;
uint16_t maxNumHealthInfoPerCycle = 0;
bool reportAllHealth = false;
ReturnValue_t iterateHealthTable(bool reset);
static ReturnValue_t checkInterfaceAndAcquireMessageQueue(MessageQueueId_t *MessageQueueToSet,
const object_id_t *objectId);

View File

@ -41,6 +41,8 @@ class Service11TelecommandScheduling final : public PusServiceBase {
static constexpr ReturnValue_t INVALID_TIME_WINDOW = returnvalue::makeCode(CLASS_ID, 2);
static constexpr ReturnValue_t TIMESHIFTING_NOT_POSSIBLE = returnvalue::makeCode(CLASS_ID, 3);
static constexpr ReturnValue_t INVALID_RELATIVE_TIME = returnvalue::makeCode(CLASS_ID, 4);
static constexpr ReturnValue_t CONTAINED_TC_TOO_SMALL = returnvalue::makeCode(CLASS_ID, 5);
static constexpr ReturnValue_t CONTAINED_TC_CRC_MISSMATCH = returnvalue::makeCode(CLASS_ID, 6);
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_11;

View File

@ -2,9 +2,11 @@
#include <cstddef>
#include "fsfw/globalfunctions/CRC.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/serialize/SerializeAdapter.h"
#include "fsfw/serviceinterface.h"
#include "fsfw/tmtcpacket/pus/tc/PusTcIF.h"
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
static constexpr auto DEF_END = SerializeIF::Endianness::BIG;
@ -171,6 +173,14 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doInsertActivi
return returnvalue::FAILED;
}
if (size < PusTcIF::MIN_SIZE) {
return CONTAINED_TC_TOO_SMALL;
}
if (CRC::crc16ccitt(data, size) != 0) {
return CONTAINED_TC_CRC_MISSMATCH;
}
// store currentPacket and receive the store address
store_address_t addr{};
if (tcStore->addData(&addr, data, size) != returnvalue::OK ||

View File

@ -1,5 +1,7 @@
#include "fsfw/pus/Service17Test.h"
#include <fsfw/serialize/SerializeElement.h>
#include "fsfw/FSFW.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/objectmanager/SystemObject.h"
@ -31,6 +33,15 @@ ReturnValue_t Service17Test::handleRequest(uint8_t subservice) {
}
return tmHelper.storeAndSendTmPacket();
}
case Subservice::PING_WITH_DATA: {
SerializeElement<uint32_t> receivedDataLen = currentPacket.getUserDataLen();
ReturnValue_t result =
tmHelper.prepareTmPacket(Subservice::PING_WITH_DATA_REPORT_WITH_SIZE, receivedDataLen);
if (result != returnvalue::OK) {
return result;
}
return tmHelper.storeAndSendTmPacket();
}
default:
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
}

View File

@ -32,6 +32,9 @@ class Service17Test : public PusServiceBase {
CONNECTION_TEST_REPORT = 2,
//! [EXPORT] : [COMMAND] Trigger test reply and test event
EVENT_TRIGGER_TEST = 128,
PING_WITH_DATA = 129,
//! [EXPORT] : [COMMAND] Report which reports the sent user data size
PING_WITH_DATA_REPORT_WITH_SIZE = 130
};
explicit Service17Test(PsbParams params);

View File

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

View File

@ -42,7 +42,7 @@
class Service5EventReporting : public PusServiceBase {
public:
Service5EventReporting(PsbParams params, size_t maxNumberReportsPerCycle = 10,
uint32_t messageQueueDepth = 10);
uint32_t messageQueueDepth = 20);
~Service5EventReporting() override;
/***

View File

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

View File

@ -6,10 +6,13 @@
class Service9TimeManagement : public PusServiceBase {
public:
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_9;
//!< 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 = MAKE_EVENT(0, severity::INFO);
//!< 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(1, severity::LOW);
static constexpr Event CLOCK_SET_FAILURE = MAKE_EVENT(2, severity::LOW);
static constexpr uint8_t CLASS_ID = CLASS_ID::PUS_SERVICE_9;
@ -30,8 +33,9 @@ class Service9TimeManagement : public PusServiceBase {
virtual ReturnValue_t setTime();
private:
enum SUBSERVICE {
SET_TIME = 128 //!< [EXPORT] : [COMMAND] Time command in ASCII, CUC or CDS format
enum Subservice {
SET_TIME = 128, //!< [EXPORT] : [COMMAND] Time command in ASCII, CUC or CDS format
DUMP_TIME = 129,
};
};

View File

@ -1,9 +1,9 @@
#ifndef FSFW_PUS_SERVICEPACKETS_SERVICE200PACKETS_H_
#define FSFW_PUS_SERVICEPACKETS_SERVICE200PACKETS_H_
#include "../../modes/ModeMessage.h"
#include "../../serialize/SerialLinkedListAdapter.h"
#include "../../serialize/SerializeIF.h"
#include "fsfw/modes/ModeMessage.h"
#include "fsfw/serialize/SerialLinkedListAdapter.h"
#include "fsfw/serialize/SerializeIF.h"
/**
* @brief Subservice 1, 2, 3, 4, 5

View File

@ -31,9 +31,8 @@ LocalPool::LocalPool(object_id_t setObjectId, const LocalPoolConfig& poolConfig,
LocalPool::~LocalPool() = default;
ReturnValue_t LocalPool::addData(store_address_t* storageId, const uint8_t* data, size_t size,
bool ignoreFault) {
ReturnValue_t status = reserveSpace(size, storageId, ignoreFault);
ReturnValue_t LocalPool::addData(store_address_t* storageId, const uint8_t* data, size_t size) {
ReturnValue_t status = reserveSpace(size, storageId);
if (status == returnvalue::OK) {
write(*storageId, data, size);
}
@ -49,8 +48,8 @@ ReturnValue_t LocalPool::getData(store_address_t packetId, const uint8_t** packe
}
ReturnValue_t LocalPool::getFreeElement(store_address_t* storageId, const size_t size,
uint8_t** pData, bool ignoreFault) {
ReturnValue_t status = reserveSpace(size, storageId, ignoreFault);
uint8_t** pData) {
ReturnValue_t status = reserveSpace(size, storageId);
if (status == returnvalue::OK) {
*pData = &store[storageId->poolIndex][getRawPosition(*storageId)];
} else {
@ -167,7 +166,7 @@ void LocalPool::clearStore() {
}
}
ReturnValue_t LocalPool::reserveSpace(size_t size, store_address_t* storeId, bool ignoreFault) {
ReturnValue_t LocalPool::reserveSpace(size_t size, store_address_t* storeId) {
ReturnValue_t status = getSubPoolIndex(size, &storeId->poolIndex);
if (status != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
@ -318,27 +317,3 @@ bool LocalPool::hasDataAtId(store_address_t storeId) const {
}
return false;
}
ReturnValue_t LocalPool::getFreeElement(store_address_t* storeId, size_t size, uint8_t** pData) {
return StorageManagerIF::getFreeElement(storeId, size, pData);
}
ConstAccessorPair LocalPool::getData(store_address_t storeId) {
return StorageManagerIF::getData(storeId);
}
ReturnValue_t LocalPool::addData(store_address_t* storeId, const uint8_t* data, size_t size) {
return StorageManagerIF::addData(storeId, data, size);
}
ReturnValue_t LocalPool::getData(store_address_t storeId, ConstStorageAccessor& accessor) {
return StorageManagerIF::getData(storeId, accessor);
}
ReturnValue_t LocalPool::modifyData(store_address_t storeId, StorageAccessor& accessor) {
return StorageManagerIF::modifyData(storeId, accessor);
}
AccessorPair LocalPool::modifyData(store_address_t storeId) {
return StorageManagerIF::modifyData(storeId);
}

View File

@ -86,21 +86,13 @@ class LocalPool : public SystemObject, public StorageManagerIF {
/**
* Documentation: See StorageManagerIF.h
*/
ReturnValue_t addData(store_address_t* storeId, const uint8_t* data, size_t size,
bool ignoreFault) override;
ReturnValue_t addData(store_address_t* storeId, const uint8_t* data, size_t size) override;
ReturnValue_t getFreeElement(store_address_t* storeId, size_t size, uint8_t** pData) override;
ReturnValue_t getFreeElement(store_address_t* storeId, size_t size, uint8_t** pData,
bool ignoreFault) override;
ConstAccessorPair getData(store_address_t storeId) override;
ReturnValue_t getData(store_address_t storeId, ConstStorageAccessor& accessor) override;
ReturnValue_t getData(store_address_t storeId, const uint8_t** packet_ptr, size_t* size) override;
AccessorPair modifyData(store_address_t storeId) override;
ReturnValue_t modifyData(store_address_t storeId, uint8_t** packet_ptr, size_t* size) override;
ReturnValue_t modifyData(store_address_t storeId, StorageAccessor& accessor) override;
ReturnValue_t deleteData(store_address_t storeId) override;
ReturnValue_t deleteData(uint8_t* ptr, size_t size, store_address_t* storeId) override;
@ -136,6 +128,12 @@ class LocalPool : public SystemObject, public StorageManagerIF {
[[nodiscard]] max_subpools_t getNumberOfSubPools() const override;
[[nodiscard]] bool hasDataAtId(store_address_t storeId) const override;
// Using functions provided by StorageManagerIF requires either a fully qualified path
// like for example localPool.StorageManagerIF::getFreeElement(...) or re-exporting
// the fully qualified path with the using directive.
using StorageManagerIF::getData;
using StorageManagerIF::modifyData;
protected:
/**
* With this helper method, a free element of @c size is reserved.
@ -144,7 +142,7 @@ class LocalPool : public SystemObject, public StorageManagerIF {
* @return - returnvalue::OK on success,
* - the return codes of #getPoolIndex or #findEmpty otherwise.
*/
virtual ReturnValue_t reserveSpace(size_t size, store_address_t* address, bool ignoreFault);
virtual ReturnValue_t reserveSpace(size_t size, store_address_t* address);
private:
/**
@ -188,6 +186,8 @@ class LocalPool : public SystemObject, public StorageManagerIF {
std::vector<std::vector<size_type>> sizeLists =
std::vector<std::vector<size_type>>(NUMBER_OF_SUBPOOLS);
bool ignoreFault = false;
//! A variable to determine whether higher n pools are used if
//! the store is full.
bool spillsToHigherPools = false;

View File

@ -9,10 +9,9 @@ PoolManager::PoolManager(object_id_t setObjectId, const LocalPoolConfig& localPo
PoolManager::~PoolManager() { MutexFactory::instance()->deleteMutex(mutex); }
ReturnValue_t PoolManager::reserveSpace(const size_t size, store_address_t* address,
bool ignoreFault) {
ReturnValue_t PoolManager::reserveSpace(const size_t size, store_address_t* address) {
MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeoutMs);
ReturnValue_t status = LocalPool::reserveSpace(size, address, ignoreFault);
ReturnValue_t status = LocalPool::reserveSpace(size, address);
return status;
}

View File

@ -57,7 +57,7 @@ class PoolManager : public LocalPool {
//! Default mutex timeout value to prevent permanent blocking.
uint32_t mutexTimeoutMs = 20;
ReturnValue_t reserveSpace(size_t size, store_address_t* address, bool ignoreFault) override;
ReturnValue_t reserveSpace(size_t size, store_address_t* address) override;
/**
* @brief The mutex is created in the constructor and makes

View File

@ -55,7 +55,7 @@ class StorageManagerIF {
/**
* @brief This is the empty virtual destructor as required for C++ interfaces.
*/
~StorageManagerIF() = default;
virtual ~StorageManagerIF() = default;
/**
* @brief With addData, a free storage position is allocated and data
* stored there.
@ -66,12 +66,7 @@ class StorageManagerIF {
* @return Returns @returnvalue::OK if data was added.
* @returnvalue::FAILED if data could not be added, storageId is unchanged then.
*/
virtual ReturnValue_t addData(store_address_t* storageId, const uint8_t* data, size_t size,
bool ignoreFault) = 0;
virtual ReturnValue_t addData(store_address_t* storageId, const uint8_t* data, size_t size) {
return addData(storageId, data, size, false);
}
virtual ReturnValue_t addData(store_address_t* storageId, const uint8_t* data, size_t size) = 0;
/**
* @brief With deleteData, the storageManager frees the memory region
@ -186,12 +181,8 @@ class StorageManagerIF {
* @return Returns @returnvalue::OK if data was added.
* @returnvalue::FAILED if data could not be added, storageId is unchanged then.
*/
virtual ReturnValue_t getFreeElement(store_address_t* storageId, size_t size, uint8_t** dataPtr,
bool ignoreFault) = 0;
virtual ReturnValue_t getFreeElement(store_address_t* storageId, size_t size, uint8_t** dataPtr) {
return getFreeElement(storageId, size, dataPtr, false);
}
virtual ReturnValue_t getFreeElement(store_address_t* storageId, size_t size,
uint8_t** dataPtr) = 0;
[[nodiscard]] virtual bool hasDataAtId(store_address_t storeId) const = 0;

View File

@ -1,3 +1,4 @@
target_sources(${LIB_FSFW_NAME} PRIVATE Subsystem.cpp SubsystemBase.cpp)
target_sources(${LIB_FSFW_NAME} PRIVATE Subsystem.cpp SubsystemBase.cpp
helper.cpp)
add_subdirectory(modes)

View File

@ -0,0 +1,13 @@
#ifndef FSFW_SUBSYSTEM_HASMODETREECHILDRENIF_H_
#define FSFW_SUBSYSTEM_HASMODETREECHILDRENIF_H_
#include "ModeTreeChildIF.h"
class HasModeTreeChildrenIF {
public:
virtual ~HasModeTreeChildrenIF() = default;
virtual ReturnValue_t registerChild(const ModeTreeChildIF& child) = 0;
virtual MessageQueueId_t getCommandQueue() const = 0;
};
#endif // FSFW_SUBSYSTEM_HASMODETREECHILDRENIF_H_

View File

@ -0,0 +1,15 @@
#ifndef FSFW_SUBSYSTEM_MODETREECHILDIF_H_
#define FSFW_SUBSYSTEM_MODETREECHILDIF_H_
#include <fsfw/health/HasHealthIF.h>
#include <fsfw/modes/HasModesIF.h>
class ModeTreeChildIF {
public:
virtual ~ModeTreeChildIF() = default;
virtual object_id_t getObjectId() const = 0;
virtual const HasHealthIF* getOptHealthIF() const = 0;
virtual const HasModesIF& getModeIF() const = 0;
};
#endif /* FSFW_SUBSYSTEM_MODETREECHILDIF_H_ */

View File

@ -0,0 +1,13 @@
#ifndef FSFW_SUBSYSTEM_MODES_MODETREECONNECTIONIF_H_
#define FSFW_SUBSYSTEM_MODES_MODETREECONNECTIONIF_H_
#include "fsfw/subsystem/HasModeTreeChildrenIF.h"
class ModeTreeConnectionIF {
public:
virtual ~ModeTreeConnectionIF() = default;
virtual ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent) = 0;
virtual ModeTreeChildIF& getModeTreeChildIF() = 0;
};
#endif /* FSFW_SRC_FSFW_SUBSYSTEM_MODES_MODETREECONNECTIONIF_H_ */

View File

@ -9,9 +9,9 @@
#include "fsfw/serialize/SerialLinkedListAdapter.h"
#include "fsfw/serialize/SerializeElement.h"
Subsystem::Subsystem(object_id_t setObjectId, object_id_t parent, uint32_t maxNumberOfSequences,
Subsystem::Subsystem(object_id_t setObjectId, uint32_t maxNumberOfSequences,
uint32_t maxNumberOfTables)
: SubsystemBase(setObjectId, parent, 0),
: SubsystemBase(setObjectId, 0),
isInTransition(false),
childrenChangedHealth(false),
currentTargetTable(),
@ -36,6 +36,13 @@ ReturnValue_t Subsystem::checkSequence(HybridIterator<ModeListEntry> iter,
for (; iter.value != nullptr; ++iter) {
if (!existsModeTable(iter->getTableId())) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
using namespace std;
sif::warning << "Subsystem::checkSequence: "
<< "Object " << setfill('0') << hex << "0x" << setw(8) << getObjectId()
<< setw(0) << ": Mode table for mode ID "
<< "0x" << setw(8) << iter->getTableId() << " does not exist" << dec << endl;
#endif
return TABLE_DOES_NOT_EXIST;
} else {
ReturnValue_t result = checkTable(getTable(iter->getTableId()));

View File

@ -66,8 +66,7 @@ class Subsystem : public SubsystemBase, public HasModeSequenceIF {
* @param maxNumberOfSequences
* @param maxNumberOfTables
*/
Subsystem(object_id_t setObjectId, object_id_t parent, uint32_t maxNumberOfSequences,
uint32_t maxNumberOfTables);
Subsystem(object_id_t setObjectId, uint32_t maxNumberOfSequences, uint32_t maxNumberOfTables);
virtual ~Subsystem();
ReturnValue_t addSequence(SequenceEntry sequence);

View File

@ -1,16 +1,17 @@
#include "fsfw/subsystem/SubsystemBase.h"
#include "fsfw/FSFW.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw/serviceinterface.h"
#include "fsfw/subsystem/helper.h"
SubsystemBase::SubsystemBase(object_id_t setObjectId, object_id_t parent, Mode_t initialMode,
SubsystemBase::SubsystemBase(object_id_t setObjectId, Mode_t initialMode,
uint16_t commandQueueDepth)
: SystemObject(setObjectId),
mode(initialMode),
healthHelper(this, setObjectId),
modeHelper(this),
parentId(parent) {
modeHelper(this) {
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
commandQueueDepth, CommandMessage::MAX_MESSAGE_SIZE, &mqArgs);
@ -18,36 +19,6 @@ SubsystemBase::SubsystemBase(object_id_t setObjectId, object_id_t parent, Mode_t
SubsystemBase::~SubsystemBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
ReturnValue_t SubsystemBase::registerChild(object_id_t objectId) {
ChildInfo info;
HasModesIF* child = ObjectManager::instance()->get<HasModesIF>(objectId);
// This is a rather ugly hack to have the changedHealth info for all
// children available.
HasHealthIF* healthChild = ObjectManager::instance()->get<HasHealthIF>(objectId);
if (child == nullptr) {
if (healthChild == nullptr) {
return CHILD_DOESNT_HAVE_MODES;
} else {
info.commandQueue = healthChild->getCommandQueue();
info.mode = MODE_OFF;
}
} else {
// intentional to force an initial command during system startup
info.commandQueue = child->getCommandQueue();
info.mode = HasModesIF::MODE_UNDEFINED;
}
info.submode = SUBMODE_NONE;
info.healthChanged = false;
auto resultPair = childrenMap.emplace(objectId, info);
if (not resultPair.second) {
return COULD_NOT_INSERT_CHILD;
}
return returnvalue::OK;
}
ReturnValue_t SubsystemBase::checkStateAgainstTable(HybridIterator<ModeListEntry> tableIter,
Submode_t targetSubmode) {
std::map<object_id_t, ChildInfo>::iterator childIter;
@ -87,7 +58,8 @@ void SubsystemBase::executeTable(HybridIterator<ModeListEntry> tableIter, Submod
if ((iter = childrenMap.find(object)) == childrenMap.end()) {
// illegal table entry, should only happen due to misconfigured mode table
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << std::hex << getObjectId() << ": invalid mode table entry" << std::endl;
sif::debug << std::hex << SystemObject::getObjectId() << ": invalid mode table entry"
<< std::endl;
#endif
continue;
}
@ -158,36 +130,15 @@ ReturnValue_t SubsystemBase::updateChildChangedHealth(MessageQueueId_t queue, bo
MessageQueueId_t SubsystemBase::getCommandQueue() const { return commandQueue->getId(); }
ReturnValue_t SubsystemBase::initialize() {
MessageQueueId_t parentQueue = MessageQueueIF::NO_QUEUE;
ReturnValue_t result = SystemObject::initialize();
ReturnValue_t result = modeHelper.initialize();
if (result != returnvalue::OK) {
return result;
}
if (parentId != objects::NO_OBJECT) {
SubsystemBase* parent = ObjectManager::instance()->get<SubsystemBase>(parentId);
if (parent == nullptr) {
return returnvalue::FAILED;
}
parentQueue = parent->getCommandQueue();
parent->registerChild(getObjectId());
}
result = healthHelper.initialize(parentQueue);
result = healthHelper.initialize();
if (result != returnvalue::OK) {
return result;
}
result = modeHelper.initialize(parentQueue);
if (result != returnvalue::OK) {
return result;
}
return returnvalue::OK;
return SystemObject::initialize();
}
ReturnValue_t SubsystemBase::performOperation(uint8_t opCode) {
@ -240,8 +191,14 @@ ReturnValue_t SubsystemBase::handleModeReply(CommandMessage* message) {
}
ReturnValue_t SubsystemBase::checkTable(HybridIterator<ModeListEntry> tableIter) {
for (; tableIter.value != NULL; ++tableIter) {
for (; tableIter.value != nullptr; ++tableIter) {
if (childrenMap.find(tableIter.value->getObject()) == childrenMap.end()) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
using namespace std;
sif::warning << "SubsystemBase::checkTable: Could not find object " << setfill('0') << hex
<< "0x" << setw(8) << tableIter.value->getObject() << " in object " << setw(8)
<< setw(0) << "0x" << setw(8) << SystemObject::getObjectId() << dec << std::endl;
#endif
return TABLE_CONTAINS_INVALID_OBJECT_ID;
}
}
@ -326,4 +283,33 @@ ReturnValue_t SubsystemBase::setHealth(HealthState health) {
HasHealthIF::HealthState SubsystemBase::getHealth() { return healthHelper.getHealth(); }
ReturnValue_t SubsystemBase::connectModeTreeParent(HasModeTreeChildrenIF& parent) {
return modetree::connectModeTreeParent(parent, *this, &healthHelper, modeHelper);
}
object_id_t SubsystemBase::getObjectId() const { return SystemObject::getObjectId(); }
void SubsystemBase::modeChanged() {}
ReturnValue_t SubsystemBase::registerChild(const ModeTreeChildIF& child) {
ChildInfo info;
const HasModesIF& modeChild = child.getModeIF();
// intentional to force an initial command during system startup
info.commandQueue = modeChild.getCommandQueue();
info.mode = HasModesIF::MODE_UNDEFINED;
info.submode = SUBMODE_NONE;
info.healthChanged = false;
auto resultPair = childrenMap.emplace(child.getObjectId(), info);
if (not resultPair.second) {
return COULD_NOT_INSERT_CHILD;
}
return returnvalue::OK;
}
const HasHealthIF* SubsystemBase::getOptHealthIF() const { return this; }
const HasModesIF& SubsystemBase::getModeIF() const { return *this; }
ModeTreeChildIF& SubsystemBase::getModeTreeChildIF() { return *this; }

View File

@ -3,14 +3,16 @@
#include <map>
#include "../container/HybridIterator.h"
#include "../health/HasHealthIF.h"
#include "../health/HealthHelper.h"
#include "../ipc/MessageQueueIF.h"
#include "../modes/HasModesIF.h"
#include "../objectmanager/SystemObject.h"
#include "../returnvalues/returnvalue.h"
#include "../tasks/ExecutableObjectIF.h"
#include "fsfw/container/HybridIterator.h"
#include "fsfw/health/HasHealthIF.h"
#include "fsfw/health/HealthHelper.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/modes/HasModesIF.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/returnvalues/returnvalue.h"
#include "fsfw/subsystem/HasModeTreeChildrenIF.h"
#include "fsfw/subsystem/ModeTreeConnectionIF.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "modes/HasModeSequenceIF.h"
/**
@ -27,6 +29,9 @@
class SubsystemBase : public SystemObject,
public HasModesIF,
public HasHealthIF,
public HasModeTreeChildrenIF,
public ModeTreeConnectionIF,
public ModeTreeChildIF,
public ExecutableObjectIF {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::SUBSYSTEM_BASE;
@ -36,32 +41,34 @@ class SubsystemBase : public SystemObject,
static const ReturnValue_t COULD_NOT_INSERT_CHILD = MAKE_RETURN_CODE(0x04);
static const ReturnValue_t TABLE_CONTAINS_INVALID_OBJECT_ID = MAKE_RETURN_CODE(0x05);
SubsystemBase(object_id_t setObjectId, object_id_t parent, Mode_t initialMode = 0,
uint16_t commandQueueDepth = 8);
SubsystemBase(object_id_t setObjectId, Mode_t initialMode = 0, uint16_t commandQueueDepth = 8);
virtual ~SubsystemBase();
virtual MessageQueueId_t getCommandQueue() const override;
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override;
ModeTreeChildIF &getModeTreeChildIF() override;
/**
* Function to register the child objects.
* Performs a checks if the child does implement HasHealthIF and/or HasModesIF
*
* Also adds them to the internal childrenMap.
* Also adds them to the internal childrenMap.
*
* @param objectId
* @return returnvalue::OK if successful
* CHILD_DOESNT_HAVE_MODES if Child is no HasHealthIF and no HasModesIF
* COULD_NOT_INSERT_CHILD If the Child could not be added to the ChildrenMap
* CHILD_DOESNT_HAVE_MODES if Child is no HasHealthIF and no HasModesIF
* COULD_NOT_INSERT_CHILD If the Child could not be added to the ChildrenMap
*/
ReturnValue_t registerChild(object_id_t objectId);
ReturnValue_t registerChild(const ModeTreeChildIF &child) override;
virtual ReturnValue_t initialize() override;
ReturnValue_t initialize() override;
virtual ReturnValue_t performOperation(uint8_t opCode) override;
ReturnValue_t performOperation(uint8_t opCode) override;
virtual ReturnValue_t setHealth(HealthState health) override;
ReturnValue_t setHealth(HealthState health) override;
virtual HasHealthIF::HealthState getHealth() override;
HasHealthIF::HealthState getHealth() override;
protected:
struct ChildInfo {
@ -88,8 +95,6 @@ class SubsystemBase : public SystemObject,
ModeHelper modeHelper;
const object_id_t parentId;
typedef std::map<object_id_t, ChildInfo> ChildrenMap;
ChildrenMap childrenMap;
@ -136,6 +141,10 @@ class SubsystemBase : public SystemObject,
virtual void getMode(Mode_t *mode, Submode_t *submode) override;
object_id_t getObjectId() const override;
const HasHealthIF *getOptHealthIF() const override;
const HasModesIF &getModeIF() const override;
virtual void setToExternalControl() override;
virtual void announceMode(bool recursive) override;

View File

@ -0,0 +1,15 @@
#include "helper.h"
ReturnValue_t modetree::connectModeTreeParent(HasModeTreeChildrenIF& parent,
const ModeTreeChildIF& child,
HealthHelper* healthHelper, ModeHelper& modeHelper) {
ReturnValue_t result = parent.registerChild(child);
if (result != returnvalue::OK) {
return result;
}
if (healthHelper != nullptr) {
healthHelper->setParentQueue(parent.getCommandQueue());
}
modeHelper.setParentQueue(parent.getCommandQueue());
return returnvalue::OK;
}

View File

@ -0,0 +1,14 @@
#ifndef FSFW_SUBSYSTEM_HELPER_H_
#define FSFW_SUBSYSTEM_HELPER_H_
#include "HasModeTreeChildrenIF.h"
#include "fsfw/health/HealthHelper.h"
namespace modetree {
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent, const ModeTreeChildIF& child,
HealthHelper* healthHelper, ModeHelper& modeHelper);
}
#endif /* FSFW_SRC_FSFW_SUBSYSTEM_HELPER_H_ */

View File

@ -1,6 +1,7 @@
#ifndef FSFW_TIMEMANAGER_TIMEREADERIF_H
#define FSFW_TIMEMANAGER_TIMEREADERIF_H
#include <cstdio>
#include <cstdlib>
#include "fsfw/platform.h"

View File

@ -21,7 +21,7 @@ SpacePacketReader::~SpacePacketReader() = default;
inline uint16_t SpacePacketReader::getPacketIdRaw() const { return ccsds::getPacketId(*spHeader); }
const uint8_t* SpacePacketReader::getPacketData() { return packetDataField; }
const uint8_t* SpacePacketReader::getPacketData() const { return packetDataField; }
ReturnValue_t SpacePacketReader::setData(uint8_t* data, size_t maxSize_, void* args) {
return setInternalFields(data, maxSize_);

View File

@ -71,7 +71,7 @@ class SpacePacketReader : public SpacePacketIF,
// Helper methods:
[[nodiscard]] ReturnValue_t checkSize() const;
const uint8_t* getPacketData();
const uint8_t* getPacketData() const;
ReturnValue_t setReadOnlyData(const uint8_t* data, size_t maxSize);

View File

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

View File

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

View File

@ -27,8 +27,8 @@ ReturnValue_t PusServiceBase::performOperation(uint8_t opCode) {
ReturnValue_t result = performService();
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "PusService " << psbParams.serviceId << ": performService returned with "
<< static_cast<uint16_t>(result) << std::endl;
sif::error << "PusService " << static_cast<int>(psbParams.serviceId)
<< ": performService returned with " << static_cast<uint16_t>(result) << std::endl;
#endif
return returnvalue::FAILED;
}

View File

@ -11,7 +11,7 @@ class SourceSequenceCounter {
SourceSequenceCounter(uint16_t initialSequenceCount = 0) : sequenceCount(initialSequenceCount) {}
void increment() { sequenceCount = (sequenceCount + 1) % (ccsds::LIMIT_SEQUENCE_COUNT); }
void decrement() { sequenceCount = (sequenceCount - 1) % (ccsds::LIMIT_SEQUENCE_COUNT); }
uint16_t get() { return this->sequenceCount; }
uint16_t get() const { return this->sequenceCount; }
void reset(uint16_t toValue = 0) { sequenceCount = toValue % (ccsds::LIMIT_SEQUENCE_COUNT); }
SourceSequenceCounter& operator++(int) {
this->increment();

View File

@ -145,13 +145,17 @@ ReturnValue_t TmTcBridge::handleTmQueue() {
#endif /* FSFW_VERBOSE_LEVEL >= 3 */
if (communicationLinkUp == false or packetSentCounter >= sentPacketsPerCycle) {
storeDownlinkData(&message);
ReturnValue_t result = storeDownlinkData(&message);
if (result != returnvalue::OK) {
tmStore->deleteData(message.getStorageId());
}
continue;
}
result = tmStore->getData(message.getStorageId(), &data, &size);
if (result != returnvalue::OK) {
status = result;
tmStore->deleteData(message.getStorageId());
continue;
}
@ -159,9 +163,9 @@ ReturnValue_t TmTcBridge::handleTmQueue() {
if (result != returnvalue::OK) {
status = result;
} else {
tmStore->deleteData(message.getStorageId());
packetSentCounter++;
}
tmStore->deleteData(message.getStorageId());
}
return status;
}
@ -183,7 +187,7 @@ ReturnValue_t TmTcBridge::storeDownlinkData(TmTcMessage* message) {
"TmTcBridge::storeDownlinkData: TM downlink max. number "
"of stored packet IDs reached!\n");
#endif
warningSwitch = true;
warningSwitch = false;
}
if (overwriteOld) {
tmFifo->retrieve(&storeId);
@ -226,6 +230,7 @@ ReturnValue_t TmTcBridge::handleStoredTm() {
packetSentCounter++;
if (tmFifo->empty()) {
warningSwitch = true;
tmStored = false;
}
tmStore->deleteData(storeId);

View File

@ -65,15 +65,13 @@ class TmTcBridge : public AcceptsTelemetryIF,
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
/** AcceptsTelemetryIF override */
MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel = 0) const override;
MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const override;
/** AcceptsTelecommandsIF override */
uint32_t getIdentifier() const override;
MessageQueueId_t getRequestQueue() const override;
const char* getName() const override;
bool warningSwitch = true;
protected:
const char* name = "";
@ -93,6 +91,7 @@ class TmTcBridge : public AcceptsTelemetryIF,
//! by default, so telemetry will be handled immediately.
bool communicationLinkUp = true;
bool tmStored = false;
bool warningSwitch = true;
bool overwriteOld = true;
uint8_t packetSentCounter = 0;

View File

@ -1,72 +0,0 @@
#ifndef FSFW_UTIL_DATAWRAPPER_H
#define FSFW_UTIL_DATAWRAPPER_H
#include <cstddef>
#include <cstdint>
#include <utility>
#include "fsfw/serialize.h"
namespace util {
using BufPair = std::pair<const uint8_t*, size_t>;
struct RawData {
RawData() = default;
const uint8_t* data = nullptr;
size_t len = 0;
};
enum DataTypes { NONE, RAW, SERIALIZABLE };
union DataUnion {
RawData raw{};
SerializeIF* serializable;
};
struct DataWrapper {
DataWrapper() = default;
DataWrapper(const uint8_t* data, size_t size) : type(DataTypes::RAW) { setRawData({data, size}); }
explicit DataWrapper(BufPair raw) : type(DataTypes::RAW) { setRawData(raw); }
explicit DataWrapper(SerializeIF& serializable) : type(DataTypes::SERIALIZABLE) {
setSerializable(serializable);
}
DataTypes type = DataTypes::NONE;
DataUnion dataUnion;
[[nodiscard]] size_t getLength() const {
if (type == DataTypes::RAW) {
return dataUnion.raw.len;
} else if (type == DataTypes::SERIALIZABLE and dataUnion.serializable != nullptr) {
return dataUnion.serializable->getSerializedSize();
}
return 0;
}
[[nodiscard]] bool isNull() const {
if ((type == DataTypes::NONE) or (type == DataTypes::RAW and dataUnion.raw.data == nullptr) or
(type == DataTypes::SERIALIZABLE and dataUnion.serializable == nullptr)) {
return true;
}
return false;
}
void setRawData(BufPair bufPair) {
type = DataTypes::RAW;
dataUnion.raw.data = bufPair.first;
dataUnion.raw.len = bufPair.second;
}
void setSerializable(SerializeIF& serializable) {
type = DataTypes::SERIALIZABLE;
dataUnion.serializable = &serializable;
}
};
} // namespace util
#endif // FSFW_UTIL_DATAWRAPPER_H

View File

@ -325,12 +325,12 @@ ReturnValue_t MgmRM3100Handler::handleDataReadout(const uint8_t *packet) {
// trickery here to calculate the raw values first
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 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
float fieldStrengthX = fieldStrengthRawX * scaleFactorX;
float fieldStrengthY = fieldStrengthRawY * scaleFactorX;
float fieldStrengthZ = fieldStrengthRawZ * scaleFactorX;
float fieldStrengthY = fieldStrengthRawY * scaleFactorY;
float fieldStrengthZ = fieldStrengthRawZ * scaleFactorZ;
if (periodicPrintout) {
if (debugDivider.checkAndIncrement()) {

View File

@ -5,11 +5,14 @@ endif()
target_sources(${LIB_FSFW_NAME} PRIVATE UnixFileGuard.cpp CommandExecutor.cpp
utility.cpp)
if(FSFW_HAL_LINUX_ADD_LIBGPIOD)
add_subdirectory(gpio)
endif()
if(FSFW_HAL_LINUX_ADD_SERIAL_DRIVERS)
add_subdirectory(serial)
endif()
if(FSFW_HAL_LINUX_ADD_PERIPHERAL_DRIVERS)
if(FSFW_HAL_LINUX_ADD_LIBGPIOD)
add_subdirectory(gpio)
endif()
add_subdirectory(uart)
# Adding those does not really make sense on Apple systems which are generally
# host systems. It won't even compile as the headers are missing
if(NOT APPLE)

View File

@ -109,14 +109,17 @@ ReturnValue_t I2cComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, s
}
if (write(fd, sendData, sendLen) != static_cast<int>(sendLen)) {
i2cCookie->errorCounter++;
if (i2cCookie->errorCounter < 3) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "I2cComIF::sendMessage: Failed to send data to I2C "
"device with error code "
<< errno << ". Error description: " << strerror(errno) << std::endl;
sif::error << "I2cComIF::sendMessage: Failed to send data to I2C "
"device with error code "
<< errno << ". Error description: " << strerror(errno) << std::endl;
#endif
}
return returnvalue::FAILED;
}
i2cCookie->errorCounter = 0;
#if FSFW_HAL_I2C_WIRETAPPING == 1
sif::info << "Sent I2C data to bus " << deviceFile << ":" << std::endl;
arrayprinter::print(sendData, sendLen);
@ -180,10 +183,6 @@ ReturnValue_t I2cComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLe
}
#else
#endif
#endif
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "I2cComIF::requestReceiveMessage: Read " << readLen << " of " << requestLen
<< " bytes" << std::endl;
#endif
return returnvalue::FAILED;
}

View File

@ -27,6 +27,8 @@ class I2cCookie : public CookieIF {
size_t getMaxReplyLen() const;
std::string getDeviceFile() const;
uint8_t errorCounter = 0;
private:
address_t i2cAddress = 0;
size_t maxReplyLen = 0;

View File

@ -0,0 +1,2 @@
target_sources(${LIB_FSFW_NAME} PUBLIC SerialComIF.cpp SerialCookie.cpp
helper.cpp)

View File

@ -1,7 +1,8 @@
#include "UartComIF.h"
#include "SerialComIF.h"
#include <errno.h>
#include <fcntl.h>
#include <fsfw_hal/linux/serial/SerialComIF.h>
#include <termios.h>
#include <unistd.h>
@ -11,18 +12,18 @@
#include "fsfw/serviceinterface.h"
#include "fsfw_hal/linux/utility.h"
UartComIF::UartComIF(object_id_t objectId) : SystemObject(objectId) {}
SerialComIF::SerialComIF(object_id_t objectId) : SystemObject(objectId) {}
UartComIF::~UartComIF() {}
SerialComIF::~SerialComIF() {}
ReturnValue_t UartComIF::initializeInterface(CookieIF* cookie) {
ReturnValue_t SerialComIF::initializeInterface(CookieIF* cookie) {
std::string deviceFile;
if (cookie == nullptr) {
return NULLPOINTER;
}
UartCookie* uartCookie = dynamic_cast<UartCookie*>(cookie);
SerialCookie* uartCookie = dynamic_cast<SerialCookie*>(cookie);
if (uartCookie == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "UartComIF::initializeInterface: Invalid UART Cookie!" << std::endl;
@ -59,7 +60,7 @@ ReturnValue_t UartComIF::initializeInterface(CookieIF* cookie) {
return returnvalue::OK;
}
int UartComIF::configureUartPort(UartCookie* uartCookie) {
int SerialComIF::configureUartPort(SerialCookie* uartCookie) {
struct termios options = {};
std::string deviceFile = uartCookie->getDeviceFile();
@ -88,7 +89,7 @@ int UartComIF::configureUartPort(UartCookie* uartCookie) {
return fd;
}
setParityOptions(&options, uartCookie);
uart::setParity(options, uartCookie->getParity());
setStopBitOptions(&options, uartCookie);
setDatasizeOptions(&options, uartCookie);
setFixedOptions(&options);
@ -114,24 +115,7 @@ int UartComIF::configureUartPort(UartCookie* uartCookie) {
return fd;
}
void UartComIF::setParityOptions(struct termios* options, UartCookie* uartCookie) {
/* Clear parity bit */
options->c_cflag &= ~PARENB;
switch (uartCookie->getParity()) {
case Parity::EVEN:
options->c_cflag |= PARENB;
options->c_cflag &= ~PARODD;
break;
case Parity::ODD:
options->c_cflag |= PARENB;
options->c_cflag |= PARODD;
break;
default:
break;
}
}
void UartComIF::setStopBitOptions(struct termios* options, UartCookie* uartCookie) {
void SerialComIF::setStopBitOptions(struct termios* options, SerialCookie* uartCookie) {
/* Clear stop field. Sets stop bit to one bit */
options->c_cflag &= ~CSTOPB;
switch (uartCookie->getStopBits()) {
@ -143,7 +127,7 @@ void UartComIF::setStopBitOptions(struct termios* options, UartCookie* uartCooki
}
}
void UartComIF::setDatasizeOptions(struct termios* options, UartCookie* uartCookie) {
void SerialComIF::setDatasizeOptions(struct termios* options, SerialCookie* uartCookie) {
/* Clear size bits */
options->c_cflag &= ~CSIZE;
switch (uartCookie->getBitsPerWord()) {
@ -167,7 +151,7 @@ void UartComIF::setDatasizeOptions(struct termios* options, UartCookie* uartCook
}
}
void UartComIF::setFixedOptions(struct termios* options) {
void SerialComIF::setFixedOptions(struct termios* options) {
/* Disable RTS/CTS hardware flow control */
options->c_cflag &= ~CRTSCTS;
/* Turn on READ & ignore ctrl lines (CLOCAL = 1) */
@ -190,7 +174,7 @@ void UartComIF::setFixedOptions(struct termios* options) {
options->c_oflag &= ~ONLCR;
}
ReturnValue_t UartComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) {
ReturnValue_t SerialComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) {
int fd = 0;
std::string deviceFile;
@ -205,7 +189,7 @@ ReturnValue_t UartComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData,
return returnvalue::FAILED;
}
UartCookie* uartCookie = dynamic_cast<UartCookie*>(cookie);
SerialCookie* uartCookie = dynamic_cast<SerialCookie*>(cookie);
if (uartCookie == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UartComIF::sendMessasge: Invalid UART Cookie!" << std::endl;
@ -236,12 +220,12 @@ ReturnValue_t UartComIF::sendMessage(CookieIF* cookie, const uint8_t* sendData,
return returnvalue::OK;
}
ReturnValue_t UartComIF::getSendSuccess(CookieIF* cookie) { return returnvalue::OK; }
ReturnValue_t SerialComIF::getSendSuccess(CookieIF* cookie) { return returnvalue::OK; }
ReturnValue_t UartComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLen) {
ReturnValue_t SerialComIF::requestReceiveMessage(CookieIF* cookie, size_t requestLen) {
std::string deviceFile;
UartCookie* uartCookie = dynamic_cast<UartCookie*>(cookie);
SerialCookie* uartCookie = dynamic_cast<SerialCookie*>(cookie);
if (uartCookie == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "UartComIF::requestReceiveMessage: Invalid Uart Cookie!" << std::endl;
@ -274,8 +258,8 @@ ReturnValue_t UartComIF::requestReceiveMessage(CookieIF* cookie, size_t requestL
}
}
ReturnValue_t UartComIF::handleCanonicalRead(UartCookie& uartCookie, UartDeviceMap::iterator& iter,
size_t requestLen) {
ReturnValue_t SerialComIF::handleCanonicalRead(SerialCookie& uartCookie,
UartDeviceMap::iterator& iter, size_t requestLen) {
ReturnValue_t result = returnvalue::OK;
uint8_t maxReadCycles = uartCookie.getReadCycles();
uint8_t currentReadCycles = 0;
@ -332,8 +316,9 @@ ReturnValue_t UartComIF::handleCanonicalRead(UartCookie& uartCookie, UartDeviceM
return result;
}
ReturnValue_t UartComIF::handleNoncanonicalRead(UartCookie& uartCookie,
UartDeviceMap::iterator& iter, size_t requestLen) {
ReturnValue_t SerialComIF::handleNoncanonicalRead(SerialCookie& uartCookie,
UartDeviceMap::iterator& iter,
size_t requestLen) {
int fd = iter->second.fileDescriptor;
auto bufferPtr = iter->second.replyBuffer.data();
// Size check to prevent buffer overflow
@ -366,10 +351,10 @@ ReturnValue_t UartComIF::handleNoncanonicalRead(UartCookie& uartCookie,
return returnvalue::OK;
}
ReturnValue_t UartComIF::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) {
ReturnValue_t SerialComIF::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) {
std::string deviceFile;
UartCookie* uartCookie = dynamic_cast<UartCookie*>(cookie);
SerialCookie* uartCookie = dynamic_cast<SerialCookie*>(cookie);
if (uartCookie == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "UartComIF::readReceivedMessage: Invalid uart cookie!" << std::endl;
@ -396,9 +381,9 @@ ReturnValue_t UartComIF::readReceivedMessage(CookieIF* cookie, uint8_t** buffer,
return returnvalue::OK;
}
ReturnValue_t UartComIF::flushUartRxBuffer(CookieIF* cookie) {
ReturnValue_t SerialComIF::flushUartRxBuffer(CookieIF* cookie) {
std::string deviceFile;
UartCookie* uartCookie = dynamic_cast<UartCookie*>(cookie);
SerialCookie* uartCookie = dynamic_cast<SerialCookie*>(cookie);
if (uartCookie == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UartComIF::flushUartRxBuffer: Invalid uart cookie!" << std::endl;
@ -415,9 +400,9 @@ ReturnValue_t UartComIF::flushUartRxBuffer(CookieIF* cookie) {
return returnvalue::FAILED;
}
ReturnValue_t UartComIF::flushUartTxBuffer(CookieIF* cookie) {
ReturnValue_t SerialComIF::flushUartTxBuffer(CookieIF* cookie) {
std::string deviceFile;
UartCookie* uartCookie = dynamic_cast<UartCookie*>(cookie);
SerialCookie* uartCookie = dynamic_cast<SerialCookie*>(cookie);
if (uartCookie == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UartComIF::flushUartTxBuffer: Invalid uart cookie!" << std::endl;
@ -434,9 +419,9 @@ ReturnValue_t UartComIF::flushUartTxBuffer(CookieIF* cookie) {
return returnvalue::FAILED;
}
ReturnValue_t UartComIF::flushUartTxAndRxBuf(CookieIF* cookie) {
ReturnValue_t SerialComIF::flushUartTxAndRxBuf(CookieIF* cookie) {
std::string deviceFile;
UartCookie* uartCookie = dynamic_cast<UartCookie*>(cookie);
SerialCookie* uartCookie = dynamic_cast<SerialCookie*>(cookie);
if (uartCookie == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UartComIF::flushUartTxAndRxBuf: Invalid uart cookie!" << std::endl;

View File

@ -3,13 +3,12 @@
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw_hal/linux/serial/SerialCookie.h>
#include <fsfw_hal/linux/serial/helper.h>
#include <unordered_map>
#include <vector>
#include "UartCookie.h"
#include "helper.h"
/**
* @brief This is the communication interface to access serial ports on linux based operating
* systems.
@ -19,7 +18,7 @@
*
* @author J. Meier
*/
class UartComIF : public DeviceCommunicationIF, public SystemObject {
class SerialComIF : public DeviceCommunicationIF, public SystemObject {
public:
static constexpr uint8_t uartRetvalId = CLASS_ID::HAL_UART;
@ -27,9 +26,9 @@ class UartComIF : public DeviceCommunicationIF, public SystemObject {
static constexpr ReturnValue_t UART_READ_SIZE_MISSMATCH = returnvalue::makeCode(uartRetvalId, 2);
static constexpr ReturnValue_t UART_RX_BUFFER_TOO_SMALL = returnvalue::makeCode(uartRetvalId, 3);
UartComIF(object_id_t objectId);
SerialComIF(object_id_t objectId);
virtual ~UartComIF();
virtual ~SerialComIF();
ReturnValue_t initializeInterface(CookieIF* cookie) override;
ReturnValue_t sendMessage(CookieIF* cookie, const uint8_t* sendData, size_t sendLen) override;
@ -76,20 +75,9 @@ class UartComIF : public DeviceCommunicationIF, public SystemObject {
* uart device file, baudrate, parity, stopbits etc.
* @return The file descriptor of the configured uart.
*/
int configureUartPort(UartCookie* uartCookie);
int configureUartPort(SerialCookie* uartCookie);
/**
* @brief This function adds the parity settings to the termios options struct.
*
* @param options Pointer to termios options struct which will be modified to enable or disable
* parity checking.
* @param uartCookie Pointer to uart cookie containing the information about the desired
* parity settings.
*
*/
void setParityOptions(struct termios* options, UartCookie* uartCookie);
void setStopBitOptions(struct termios* options, UartCookie* uartCookie);
void setStopBitOptions(struct termios* options, SerialCookie* uartCookie);
/**
* @brief This function sets options which are not configurable by the uartCookie.
@ -99,11 +87,11 @@ class UartComIF : public DeviceCommunicationIF, public SystemObject {
/**
* @brief With this function the datasize settings are added to the termios options struct.
*/
void setDatasizeOptions(struct termios* options, UartCookie* uartCookie);
void setDatasizeOptions(struct termios* options, SerialCookie* uartCookie);
ReturnValue_t handleCanonicalRead(UartCookie& uartCookie, UartDeviceMap::iterator& iter,
ReturnValue_t handleCanonicalRead(SerialCookie& uartCookie, UartDeviceMap::iterator& iter,
size_t requestLen);
ReturnValue_t handleNoncanonicalRead(UartCookie& uartCookie, UartDeviceMap::iterator& iter,
ReturnValue_t handleNoncanonicalRead(SerialCookie& uartCookie, UartDeviceMap::iterator& iter,
size_t requestLen);
};

View File

@ -0,0 +1,51 @@
#include "SerialCookie.h"
#include <fsfw/serviceinterface.h>
SerialCookie::SerialCookie(object_id_t handlerId, std::string deviceFile, UartBaudRate baudrate,
size_t maxReplyLen, UartModes uartMode)
: handlerId(handlerId),
deviceFile(deviceFile),
uartMode(uartMode),
baudrate(baudrate),
maxReplyLen(maxReplyLen) {}
SerialCookie::~SerialCookie() {}
UartBaudRate SerialCookie::getBaudrate() const { return baudrate; }
size_t SerialCookie::getMaxReplyLen() const { return maxReplyLen; }
std::string SerialCookie::getDeviceFile() const { return deviceFile; }
void SerialCookie::setParityOdd() { parity = Parity::ODD; }
void SerialCookie::setParityEven() { parity = Parity::EVEN; }
Parity SerialCookie::getParity() const { return parity; }
void SerialCookie::setBitsPerWord(BitsPerWord bitsPerWord_) { bitsPerWord = bitsPerWord_; }
BitsPerWord SerialCookie::getBitsPerWord() const { return bitsPerWord; }
StopBits SerialCookie::getStopBits() const { return stopBits; }
void SerialCookie::setTwoStopBits() { stopBits = StopBits::TWO_STOP_BITS; }
void SerialCookie::setOneStopBit() { stopBits = StopBits::ONE_STOP_BIT; }
UartModes SerialCookie::getUartMode() const { return uartMode; }
void SerialCookie::setReadCycles(uint8_t readCycles) { this->readCycles = readCycles; }
void SerialCookie::setToFlushInput(bool enable) { this->flushInput = enable; }
uint8_t SerialCookie::getReadCycles() const { return readCycles; }
bool SerialCookie::getInputShouldBeFlushed() { return this->flushInput; }
object_id_t SerialCookie::getHandlerId() const { return this->handlerId; }
void SerialCookie::setNoFixedSizeReply() { replySizeFixed = false; }
bool SerialCookie::isReplySizeFixed() { return replySizeFixed; }

View File

@ -3,11 +3,10 @@
#include <fsfw/devicehandlers/CookieIF.h>
#include <fsfw/objectmanager/SystemObjectIF.h>
#include <fsfw_hal/linux/serial/helper.h>
#include <string>
#include "helper.h"
/**
* @brief Cookie for the UartComIF. There are many options available to configure the UART driver.
* The constructor only requests for common options like the baudrate. Other options can
@ -15,7 +14,7 @@
*
* @author J. Meier
*/
class UartCookie : public CookieIF {
class SerialCookie : public CookieIF {
public:
/**
* @brief Constructor for the uart cookie.
@ -30,10 +29,10 @@ class UartCookie : public CookieIF {
* 8 databits (number of bits transfered with one uart frame)
* One stop bit
*/
UartCookie(object_id_t handlerId, std::string deviceFile, UartBaudRate baudrate,
size_t maxReplyLen, UartModes uartMode = UartModes::NON_CANONICAL);
SerialCookie(object_id_t handlerId, std::string deviceFile, UartBaudRate baudrate,
size_t maxReplyLen, UartModes uartMode = UartModes::NON_CANONICAL);
virtual ~UartCookie();
virtual ~SerialCookie();
UartBaudRate getBaudrate() const;
size_t getMaxReplyLen() const;

View File

@ -0,0 +1,163 @@
#include <fsfw_hal/linux/serial/helper.h>
#include <sys/ioctl.h>
#include "fsfw/serviceinterface.h"
void uart::setMode(struct termios& options, UartModes mode) {
if (mode == UartModes::NON_CANONICAL) {
/* Disable canonical mode */
options.c_lflag &= ~ICANON;
} else if (mode == UartModes::CANONICAL) {
options.c_lflag |= ICANON;
}
}
void uart::setBaudrate(struct termios& options, UartBaudRate baud) {
switch (baud) {
case UartBaudRate::RATE_50:
cfsetspeed(&options, B50);
break;
case UartBaudRate::RATE_75:
cfsetspeed(&options, B75);
break;
case UartBaudRate::RATE_110:
cfsetspeed(&options, B110);
break;
case UartBaudRate::RATE_134:
cfsetspeed(&options, B134);
break;
case UartBaudRate::RATE_150:
cfsetspeed(&options, B150);
break;
case UartBaudRate::RATE_200:
cfsetspeed(&options, B200);
break;
case UartBaudRate::RATE_300:
cfsetspeed(&options, B300);
break;
case UartBaudRate::RATE_600:
cfsetspeed(&options, B600);
break;
case UartBaudRate::RATE_1200:
cfsetspeed(&options, B1200);
break;
case UartBaudRate::RATE_1800:
cfsetspeed(&options, B1800);
break;
case UartBaudRate::RATE_2400:
cfsetspeed(&options, B2400);
break;
case UartBaudRate::RATE_4800:
cfsetspeed(&options, B4800);
break;
case UartBaudRate::RATE_9600:
cfsetspeed(&options, B9600);
break;
case UartBaudRate::RATE_19200:
cfsetspeed(&options, B19200);
break;
case UartBaudRate::RATE_38400:
cfsetspeed(&options, B38400);
break;
case UartBaudRate::RATE_57600:
cfsetspeed(&options, B57600);
break;
case UartBaudRate::RATE_115200:
cfsetspeed(&options, B115200);
break;
case UartBaudRate::RATE_230400:
cfsetspeed(&options, B230400);
break;
#ifndef __APPLE__
case UartBaudRate::RATE_460800:
cfsetspeed(&options, B460800);
break;
case UartBaudRate::RATE_500000:
cfsetspeed(&options, B500000);
break;
case UartBaudRate::RATE_576000:
cfsetspeed(&options, B576000);
break;
case UartBaudRate::RATE_921600:
cfsetspeed(&options, B921600);
break;
case UartBaudRate::RATE_1000000:
cfsetspeed(&options, B1000000);
break;
case UartBaudRate::RATE_1152000:
cfsetspeed(&options, B1152000);
break;
case UartBaudRate::RATE_1500000:
cfsetspeed(&options, B1500000);
break;
case UartBaudRate::RATE_2000000:
cfsetspeed(&options, B2000000);
break;
case UartBaudRate::RATE_2500000:
cfsetspeed(&options, B2500000);
break;
case UartBaudRate::RATE_3000000:
cfsetspeed(&options, B3000000);
break;
case UartBaudRate::RATE_3500000:
cfsetspeed(&options, B3500000);
break;
case UartBaudRate::RATE_4000000:
cfsetspeed(&options, B4000000);
break;
#endif // ! __APPLE__
default:
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UartComIF::configureBaudrate: Baudrate not supported" << std::endl;
#endif
break;
}
}
void uart::setBitsPerWord(struct termios& options, BitsPerWord bits) {
options.c_cflag &= ~CSIZE; // Clear all the size bits
if (bits == BitsPerWord::BITS_5) {
options.c_cflag |= CS5;
} else if (bits == BitsPerWord::BITS_6) {
options.c_cflag |= CS6;
} else if (bits == BitsPerWord::BITS_7) {
options.c_cflag |= CS7;
} else if (bits == BitsPerWord::BITS_8) {
options.c_cflag |= CS8;
}
}
void uart::enableRead(struct termios& options) { options.c_cflag |= CREAD; }
void uart::ignoreCtrlLines(struct termios& options) { options.c_cflag |= CLOCAL; }
void uart::setParity(struct termios& options, Parity parity) {
/* Clear parity bit */
options.c_cflag &= ~PARENB;
switch (parity) {
case Parity::EVEN:
options.c_cflag |= PARENB;
options.c_cflag &= ~PARODD;
break;
case Parity::ODD:
options.c_cflag |= PARENB;
options.c_cflag |= PARODD;
break;
default:
break;
}
}
int uart::readCountersAndErrors(int serialPort, serial_icounter_struct& icounter) {
return ioctl(serialPort, TIOCGICOUNT, &icounter);
}
void uart::setStopbits(struct termios& options, StopBits bits) {
if (bits == StopBits::TWO_STOP_BITS) {
// Use two stop bits
options.c_cflag |= CSTOPB;
} else {
// Clear stop field, only one stop bit used in communication
options.c_cflag &= ~CSTOPB;
}
}

View File

@ -54,6 +54,16 @@ void setMode(struct termios& options, UartModes mode);
*/
void setBaudrate(struct termios& options, UartBaudRate baud);
void setStopbits(struct termios& options, StopBits bits);
void setBitsPerWord(struct termios& options, BitsPerWord bits);
void enableRead(struct termios& options);
void setParity(struct termios& options, Parity parity);
void ignoreCtrlLines(struct termios& options);
int readCountersAndErrors(int serialPort, serial_icounter_struct& icounter);
} // namespace uart

View File

@ -1 +0,0 @@
target_sources(${LIB_FSFW_NAME} PUBLIC UartComIF.cpp UartCookie.cpp helper.cpp)

View File

@ -1,51 +0,0 @@
#include "UartCookie.h"
#include <fsfw/serviceinterface.h>
UartCookie::UartCookie(object_id_t handlerId, std::string deviceFile, UartBaudRate baudrate,
size_t maxReplyLen, UartModes uartMode)
: handlerId(handlerId),
deviceFile(deviceFile),
uartMode(uartMode),
baudrate(baudrate),
maxReplyLen(maxReplyLen) {}
UartCookie::~UartCookie() {}
UartBaudRate UartCookie::getBaudrate() const { return baudrate; }
size_t UartCookie::getMaxReplyLen() const { return maxReplyLen; }
std::string UartCookie::getDeviceFile() const { return deviceFile; }
void UartCookie::setParityOdd() { parity = Parity::ODD; }
void UartCookie::setParityEven() { parity = Parity::EVEN; }
Parity UartCookie::getParity() const { return parity; }
void UartCookie::setBitsPerWord(BitsPerWord bitsPerWord_) { bitsPerWord = bitsPerWord_; }
BitsPerWord UartCookie::getBitsPerWord() const { return bitsPerWord; }
StopBits UartCookie::getStopBits() const { return stopBits; }
void UartCookie::setTwoStopBits() { stopBits = StopBits::TWO_STOP_BITS; }
void UartCookie::setOneStopBit() { stopBits = StopBits::ONE_STOP_BIT; }
UartModes UartCookie::getUartMode() const { return uartMode; }
void UartCookie::setReadCycles(uint8_t readCycles) { this->readCycles = readCycles; }
void UartCookie::setToFlushInput(bool enable) { this->flushInput = enable; }
uint8_t UartCookie::getReadCycles() const { return readCycles; }
bool UartCookie::getInputShouldBeFlushed() { return this->flushInput; }
object_id_t UartCookie::getHandlerId() const { return this->handlerId; }
void UartCookie::setNoFixedSizeReply() { replySizeFixed = false; }
bool UartCookie::isReplySizeFixed() { return replySizeFixed; }

View File

@ -1,148 +0,0 @@
#include "helper.h"
#include <sys/ioctl.h>
#include "fsfw/serviceinterface.h"
void uart::setMode(struct termios& options, UartModes mode) {
if (mode == UartModes::NON_CANONICAL) {
/* Disable canonical mode */
options.c_lflag &= ~ICANON;
} else if (mode == UartModes::CANONICAL) {
options.c_lflag |= ICANON;
}
}
void uart::setBaudrate(struct termios& options, UartBaudRate baud) {
switch (baud) {
case UartBaudRate::RATE_50:
cfsetispeed(&options, B50);
cfsetospeed(&options, B50);
break;
case UartBaudRate::RATE_75:
cfsetispeed(&options, B75);
cfsetospeed(&options, B75);
break;
case UartBaudRate::RATE_110:
cfsetispeed(&options, B110);
cfsetospeed(&options, B110);
break;
case UartBaudRate::RATE_134:
cfsetispeed(&options, B134);
cfsetospeed(&options, B134);
break;
case UartBaudRate::RATE_150:
cfsetispeed(&options, B150);
cfsetospeed(&options, B150);
break;
case UartBaudRate::RATE_200:
cfsetispeed(&options, B200);
cfsetospeed(&options, B200);
break;
case UartBaudRate::RATE_300:
cfsetispeed(&options, B300);
cfsetospeed(&options, B300);
break;
case UartBaudRate::RATE_600:
cfsetispeed(&options, B600);
cfsetospeed(&options, B600);
break;
case UartBaudRate::RATE_1200:
cfsetispeed(&options, B1200);
cfsetospeed(&options, B1200);
break;
case UartBaudRate::RATE_1800:
cfsetispeed(&options, B1800);
cfsetospeed(&options, B1800);
break;
case UartBaudRate::RATE_2400:
cfsetispeed(&options, B2400);
cfsetospeed(&options, B2400);
break;
case UartBaudRate::RATE_4800:
cfsetispeed(&options, B4800);
cfsetospeed(&options, B4800);
break;
case UartBaudRate::RATE_9600:
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
break;
case UartBaudRate::RATE_19200:
cfsetispeed(&options, B19200);
cfsetospeed(&options, B19200);
break;
case UartBaudRate::RATE_38400:
cfsetspeed(&options, B38400);
break;
case UartBaudRate::RATE_57600:
cfsetispeed(&options, B57600);
cfsetospeed(&options, B57600);
break;
case UartBaudRate::RATE_115200:
cfsetspeed(&options, B115200);
break;
case UartBaudRate::RATE_230400:
cfsetispeed(&options, B230400);
cfsetospeed(&options, B230400);
break;
#ifndef __APPLE__
case UartBaudRate::RATE_460800:
cfsetispeed(&options, B460800);
cfsetospeed(&options, B460800);
break;
case UartBaudRate::RATE_500000:
cfsetispeed(&options, B500000);
cfsetospeed(&options, B500000);
break;
case UartBaudRate::RATE_576000:
cfsetispeed(&options, B576000);
cfsetospeed(&options, B576000);
break;
case UartBaudRate::RATE_921600:
cfsetispeed(&options, B921600);
cfsetospeed(&options, B921600);
break;
case UartBaudRate::RATE_1000000:
cfsetispeed(&options, B1000000);
cfsetospeed(&options, B1000000);
break;
case UartBaudRate::RATE_1152000:
cfsetispeed(&options, B1152000);
cfsetospeed(&options, B1152000);
break;
case UartBaudRate::RATE_1500000:
cfsetispeed(&options, B1500000);
cfsetospeed(&options, B1500000);
break;
case UartBaudRate::RATE_2000000:
cfsetispeed(&options, B2000000);
cfsetospeed(&options, B2000000);
break;
case UartBaudRate::RATE_2500000:
cfsetispeed(&options, B2500000);
cfsetospeed(&options, B2500000);
break;
case UartBaudRate::RATE_3000000:
cfsetispeed(&options, B3000000);
cfsetospeed(&options, B3000000);
break;
case UartBaudRate::RATE_3500000:
cfsetispeed(&options, B3500000);
cfsetospeed(&options, B3500000);
break;
case UartBaudRate::RATE_4000000:
cfsetispeed(&options, B4000000);
cfsetospeed(&options, B4000000);
break;
#endif // ! __APPLE__
default:
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "UartComIF::configureBaudrate: Baudrate not supported" << std::endl;
#endif
break;
}
}
int uart::readCountersAndErrors(int serialPort, serial_icounter_struct& icounter) {
return ioctl(serialPort, TIOCGICOUNT, &icounter);
}

View File

@ -21,10 +21,12 @@ UioMapper::UioMapper(std::string uioFile, int mapNum) : mapNum(mapNum) {
char* res = realpath(uioFile.c_str(), nullptr);
if (res) {
this->uioFile = res;
free(res);
} else {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Could not resolve real path of UIO file " << uioFile << std::endl;
#endif
}
free(res);
} else {
this->uioFile = std::move(uioFile);
}

View File

@ -2,19 +2,17 @@
#include <fsfw/objectmanager/ObjectManager.h>
TestAssembly::TestAssembly(object_id_t objectId, object_id_t parentId, object_id_t testDevice0,
object_id_t testDevice1)
: AssemblyBase(objectId, parentId),
deviceHandler0Id(testDevice0),
deviceHandler1Id(testDevice1) {
TestAssembly::TestAssembly(object_id_t objectId, object_id_t parentId, ModeTreeChildIF& testDevice0,
ModeTreeChildIF& testDevice1)
: AssemblyBase(objectId, parentId), deviceHandler0(testDevice0), deviceHandler1(testDevice1) {
ModeListEntry newModeListEntry;
newModeListEntry.setObject(testDevice0);
newModeListEntry.setObject(testDevice0.getObjectId());
newModeListEntry.setMode(MODE_OFF);
newModeListEntry.setSubmode(SUBMODE_NONE);
commandTable.insert(newModeListEntry);
newModeListEntry.setObject(testDevice1);
newModeListEntry.setObject(testDevice1.getObjectId());
newModeListEntry.setMode(MODE_OFF);
newModeListEntry.setSubmode(SUBMODE_NONE);
@ -43,8 +41,8 @@ ReturnValue_t TestAssembly::commandChildren(Mode_t mode, Submode_t submode) {
commandTable[1].setMode(MODE_OFF);
commandTable[1].setSubmode(SUBMODE_NONE);
// We try to prefer 0 here but we try to switch to 1 even if it might fail
if (isDeviceAvailable(deviceHandler0Id)) {
if (childrenMap[deviceHandler0Id].mode == MODE_ON) {
if (isDeviceAvailable(deviceHandler0.getObjectId())) {
if (childrenMap[deviceHandler0.getObjectId()].mode == MODE_ON) {
commandTable[0].setMode(mode);
commandTable[0].setSubmode(SUBMODE_NONE);
} else {
@ -53,7 +51,7 @@ ReturnValue_t TestAssembly::commandChildren(Mode_t mode, Submode_t submode) {
result = NEED_SECOND_STEP;
}
} else {
if (childrenMap[deviceHandler1Id].mode == MODE_ON) {
if (childrenMap[deviceHandler1.getObjectId()].mode == MODE_ON) {
commandTable[1].setMode(mode);
commandTable[1].setSubmode(SUBMODE_NONE);
} else {
@ -64,7 +62,7 @@ ReturnValue_t TestAssembly::commandChildren(Mode_t mode, Submode_t submode) {
}
} else {
// Dual Mode Normal
if (childrenMap[deviceHandler0Id].mode == MODE_ON) {
if (childrenMap[deviceHandler0.getObjectId()].mode == MODE_ON) {
commandTable[0].setMode(mode);
commandTable[0].setSubmode(SUBMODE_NONE);
} else {
@ -72,7 +70,7 @@ ReturnValue_t TestAssembly::commandChildren(Mode_t mode, Submode_t submode) {
commandTable[0].setSubmode(SUBMODE_NONE);
result = NEED_SECOND_STEP;
}
if (childrenMap[deviceHandler1Id].mode == MODE_ON) {
if (childrenMap[deviceHandler1.getObjectId()].mode == MODE_ON) {
commandTable[1].setMode(mode);
commandTable[1].setSubmode(SUBMODE_NONE);
} else {
@ -89,7 +87,7 @@ ReturnValue_t TestAssembly::commandChildren(Mode_t mode, Submode_t submode) {
commandTable[1].setMode(MODE_OFF);
commandTable[1].setSubmode(SUBMODE_NONE);
// We try to prefer 0 here but we try to switch to 1 even if it might fail
if (isDeviceAvailable(deviceHandler0Id)) {
if (isDeviceAvailable(deviceHandler0.getObjectId())) {
commandTable[0].setMode(MODE_ON);
commandTable[0].setSubmode(SUBMODE_NONE);
} else {
@ -133,23 +131,14 @@ ReturnValue_t TestAssembly::initialize() {
if (result != returnvalue::OK) {
return result;
}
handler0 = ObjectManager::instance()->get<TestDevice>(deviceHandler0Id);
handler1 = ObjectManager::instance()->get<TestDevice>(deviceHandler1Id);
auto* handler0 = ObjectManager::instance()->get<TestDevice>(deviceHandler0.getObjectId());
auto* handler1 = ObjectManager::instance()->get<TestDevice>(deviceHandler1.getObjectId());
if ((handler0 == nullptr) or (handler1 == nullptr)) {
return returnvalue::FAILED;
}
handler0->setParentQueue(this->getCommandQueue());
handler1->setParentQueue(this->getCommandQueue());
result = registerChild(deviceHandler0Id);
if (result != returnvalue::OK) {
return result;
}
result = registerChild(deviceHandler1Id);
if (result != returnvalue::OK) {
return result;
}
handler0->connectModeTreeParent(*this);
handler1->connectModeTreeParent(*this);
return result;
}

View File

@ -7,8 +7,8 @@
class TestAssembly : public AssemblyBase {
public:
TestAssembly(object_id_t objectId, object_id_t parentId, object_id_t testDevice0,
object_id_t testDevice1);
TestAssembly(object_id_t objectId, object_id_t parentId, ModeTreeChildIF& testDevice0,
ModeTreeChildIF& testDevice1);
virtual ~TestAssembly();
ReturnValue_t initialize() override;
@ -41,10 +41,8 @@ class TestAssembly : public AssemblyBase {
private:
FixedArrayList<ModeListEntry, 2> commandTable;
object_id_t deviceHandler0Id = 0;
object_id_t deviceHandler1Id = 0;
TestDevice* handler0 = nullptr;
TestDevice* handler1 = nullptr;
ModeTreeChildIF& deviceHandler0;
ModeTreeChildIF& deviceHandler1;
bool isDeviceAvailable(object_id_t object);
};

View File

@ -4,8 +4,8 @@
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/serviceinterface/ServiceInterface.h>
TestController::TestController(object_id_t objectId, object_id_t parentId, size_t commandQueueDepth)
: ExtendedControllerBase(objectId, parentId, commandQueueDepth) {}
TestController::TestController(object_id_t objectId, size_t commandQueueDepth)
: ExtendedControllerBase(objectId, commandQueueDepth) {}
TestController::~TestController() {}

View File

@ -7,7 +7,7 @@
class TestController : public ExtendedControllerBase {
public:
TestController(object_id_t objectId, object_id_t parentId, size_t commandQueueDepth = 10);
TestController(object_id_t objectId, size_t commandQueueDepth = 10);
virtual ~TestController();
protected:

View File

@ -31,4 +31,7 @@ int customSetup() {
return 0;
}
int customTeardown() { return 0; }
int customTeardown() {
ObjectManager::clear();
return 0;
}

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