Compare commits

...

266 Commits

Author SHA1 Message Date
a837a78bd4 Merge branch 'develop' into develop_update 2023-09-01 12:14:08 +02:00
d246ce34d0 Merge pull request 'Change TLE validity duration' (#159) from spg4-tle-too-old into develop
Reviewed-on: #159
Reviewed-by: Robin Müller <muellerr@irs.uni-stuttgart.de>
2023-08-14 10:09:00 +02:00
796c7a9e37 tle is too old after 30 days now 2023-08-09 11:42:11 +02:00
d575da8540 Merge pull request 'Small tweak to allow immediate HK generation' (#158) from small-hk-tweak into develop
Reviewed-on: #158
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-17 10:37:39 +02:00
62ace649a7 fix unittest 2023-07-17 10:35:35 +02:00
aac74fae38 shared cmake file 2023-07-17 10:34:19 +02:00
a26b0c38ac small tweak to allow immediate HK generation 2023-07-17 10:31:02 +02:00
42e74d22cc Merge pull request 'countdown based HK generation' (#156) from hk-generation-countdown-based into develop
Reviewed-on: #156
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-11 17:35:10 +02:00
36caa58043 Merge branch 'develop' into hk-generation-countdown-based 2023-07-11 17:34:24 +02:00
988e07f0be countdown 2023-07-11 15:40:43 +02:00
88e8665280 important bugfix for PUS TM creator 2023-07-10 17:45:02 +02:00
9c8b1c697b added back missing function 2023-07-10 14:20:02 +02:00
110cb903a6 countdown based HK generation 2023-07-10 14:14:31 +02:00
8da89eba80 Merge pull request 'add API to set msg counter' (#155) from pus-msg-counter-mutable into develop
Reviewed-on: #155
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-06-28 13:19:28 +02:00
7e8845f2c2 Merge remote-tracking branch 'origin/develop' into pus-msg-counter-mutable 2023-06-26 18:12:36 +02:00
6aff3250c2 Merge pull request 'Internal Error Reporter Configurability' (#154) from internal-error-reporter-set into develop
Reviewed-on: #154
2023-06-26 18:10:06 +02:00
c3572e31a8 add API to set msg counter 2023-06-25 12:35:50 +02:00
2293e7f2bb typo 2023-06-22 16:12:41 +02:00
a85a38c882 some thnings are configurable now 2023-06-22 16:08:29 +02:00
0f76cdb3ba typo 2023-06-20 20:36:03 +02:00
268c2e87c9 Merge pull request 'max value calc fix' (#153) from max-value-fix-v2 into develop
Reviewed-on: #153
2023-06-20 18:20:00 +02:00
87f94a252f Merge branch 'develop' into max-value-fix-v2 2023-06-20 18:19:19 +02:00
c7037d417a nullptr check for optional argument 2023-06-20 11:54:15 +02:00
f80c5980ea max value calc fix 2023-06-19 17:04:45 +02:00
ad01642fee Merge pull request 'specify truncate flag explicitely' (#151) from specify-truncate-flag-explicitely into develop
Reviewed-on: #151
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-06-19 09:32:19 +02:00
f2947bc78e specify truncate flag explicitely 2023-06-18 19:04:36 +02:00
0a977ea688 Merge pull request 'make number of parallel cmds configurable' (#149) from make-srv3-num-parallel-cmds-configurable into develop
Reviewed-on: #149
2023-06-14 03:37:02 +02:00
74b164b1da make number of parallel cmds configurable 2023-06-13 08:09:04 +02:00
5322de0599 Merge pull request 'Pull CFPD bugfix in dev branch' (#147) from pull-cfdp-fix-into-dev-branch into obsw-v3.0.0-dev
Reviewed-on: #147
2023-06-09 13:41:29 +02:00
9a4bf51006 Merge branch 'develop' into obsw-v3.0.0-dev 2023-06-09 13:11:30 +02:00
3a70229510 Merge pull request 'configurable queue depth' (#146) from service-8-configurable-queue-depth into obsw-v3.0.0-dev
Reviewed-on: #146
2023-06-09 13:03:17 +02:00
b3beedad9f Merge branch 'obsw-v3.0.0-dev' into service-8-configurable-queue-depth 2023-06-09 13:03:08 +02:00
efe217a197 Merge pull request 'Rework L3GD20H Config' (#143) from gyr-config-rework into obsw-v3.0.0-dev
Reviewed-on: #143
2023-06-09 13:01:23 +02:00
b442ca09b9 configurable queue depth 2023-06-07 13:46:46 +02:00
9372b2a575 Merge remote-tracking branch 'upstream/development' into develop 2023-05-25 15:03:54 +02:00
aafa53148e Merge pull request 'CFDP Bugfix' (#144) from cfdp-bugfix-unittest-fixes into develop
Reviewed-on: #144
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-05-22 10:40:44 +02:00
e0adb3325f werks 2023-05-22 10:37:26 +02:00
4391823f01 changelog 2023-05-15 16:14:36 +02:00
1a77e6bb09 proper floating point comparison 2023-05-15 16:13:05 +02:00
cae131edcf CFDP and unittest bugfixes 2023-05-15 16:02:55 +02:00
4518fec65c CHANGELOG 2023-05-08 15:25:47 +02:00
dac1aacab2 Merge pull request 'Update Power Switch IF' (#743) from eive/fsfw:update_power_switch_if into development
Reviewed-on: fsfw/fsfw#743
2023-05-08 15:00:47 +02:00
0042f92fdf Merge pull request 'bump ETL version' (#748) from KSat/fsfw:bump_etl_dep into development
Reviewed-on: fsfw/fsfw#748
2023-05-08 14:53:02 +02:00
656faf8169 Merge remote-tracking branch 'upstream/development' into update_power_switch_if 2023-05-08 14:44:27 +02:00
f84431e965 Merge pull request 'bugfix and changelog for Linux getUptime' (#745) from eive/fsfw:important_bugfix_linux_get_uptime into development
Reviewed-on: fsfw/fsfw#745
2023-05-08 14:29:55 +02:00
0cec9ebb73 Merge pull request 'small tweak for version getter' (#744) from eive/fsfw:small_version_getter_tweak into development
Reviewed-on: fsfw/fsfw#744
2023-05-08 14:13:06 +02:00
a440b7c394 Merge pull request 'add CFDP subsystem ID' (#742) from eive/fsfw:add_cfdp_subsystem_id into development
Reviewed-on: fsfw/fsfw#742
2023-05-08 14:09:04 +02:00
bbfc1b2b34 Merge pull request 'FixedArrayList compile time assert' (#740) from eive/fsfw:container_additional_assert into development
Reviewed-on: fsfw/fsfw#740
2023-05-08 14:04:56 +02:00
025b379e8b bump ETL version 2023-05-04 14:04:55 +02:00
258f0d3313 use both LPFs 2023-04-19 15:25:14 +02:00
5eb9ee8bc1 DHB fdir: event queue depth confgurable 2023-04-14 21:22:24 +02:00
7f61d17cee even better event manager printout 2023-04-14 21:08:44 +02:00
ffa2fa477f Merge pull request 'move CFDP handler' (#142) from move_cfdp_handler into develop
Reviewed-on: #142
2023-04-11 16:50:46 +02:00
894d1e3b87 move CFDP handler 2023-04-11 16:36:54 +02:00
285d327b97 clean up spi retval defs 2023-04-07 17:42:44 +02:00
e97fa5ac84 add skip directive for retvals 2023-04-07 11:03:46 +02:00
5a9304765f accepts action commands without ipc data 2023-04-06 22:34:57 +02:00
6650c293da change collection interval is public now 2023-04-04 15:59:26 +02:00
9fca7581dd Merge branch 'develop' of https://egit.irs.uni-stuttgart.de/eive/fsfw into develop 2023-04-04 01:52:29 +02:00
4af90f99f3 changelog 2023-04-04 01:52:26 +02:00
94cdf67a80 make health functions virtual 2023-04-04 01:51:58 +02:00
7966ede11b add O_SYNC flag for UioMapper 2023-04-03 21:57:18 +02:00
7a392dc33a new register function 2023-04-03 18:54:35 +02:00
1e3c89b672 i dont think ths needs to be public 2023-04-03 17:59:14 +02:00
e2e87b149d initialize switch state list 2023-04-03 14:31:45 +02:00
4f632e2c68 ctrl base bugfix 2023-03-28 19:37:47 +02:00
314f0fa2cd start power switch component in undefined mode 2023-03-28 15:27:48 +02:00
b31e1037fb HK service configurable queue depth 2023-03-26 20:05:10 +02:00
b814e7198f Merge pull request 'Allow creating regular threads' (#140) from allow_creating_regular_threads into develop
Reviewed-on: #140
2023-03-24 14:15:53 +01:00
6328b70d7b Merge branch 'develop' into allow_creating_regular_threads 2023-03-24 14:15:39 +01:00
a937b457f9 this is so confusing 2023-03-24 14:10:47 +01:00
4415dc24e1 fix host OSAL 2023-03-24 13:25:34 +01:00
e704295cce default value 2023-03-24 11:58:23 +01:00
d16b3c7e67 try to do this cleanly 2023-03-24 11:53:41 +01:00
3b86545725 Merge pull request 'add BUSY retval' (#141) from busy_retval_dhb_com into develop
Reviewed-on: #141
2023-03-24 11:35:09 +01:00
cf6150cc18 add BUSY retval 2023-03-24 00:57:44 +01:00
bfb5c2ff03 Merge branch 'develop' into allow_creating_regular_threads 2023-03-23 18:45:49 +01:00
bf02061d47 Merge pull request 'use RR sched instead of FIFO for Linux RT' (#139) from use_rr_sched into develop
Reviewed-on: #139
2023-03-23 18:45:09 +01:00
2c4e110254 Merge branch 'develop' into use_rr_sched 2023-03-23 18:44:59 +01:00
7ed75ea87b Merge remote-tracking branch 'origin/develop' into allow_creating_regular_threads 2023-03-23 18:44:06 +01:00
db4587bb59 allow creating regular threads 2023-03-23 18:29:17 +01:00
33ac395072 use RR sched instead of FIFO for Linux RT 2023-03-23 15:42:14 +01:00
f8a7c1d4ed rename namespace 2023-03-22 01:03:49 +01:00
341437df13 add flush functions for serial helpers 2023-03-21 20:20:13 +01:00
227524a21d transition source submode is tricky 2023-03-20 15:49:09 +01:00
0f81d5e458 Merge remote-tracking branch 'upstream/development' into container_additional_assert 2023-03-15 12:34:36 +01:00
b50f092939 Merge remote-tracking branch 'upstream/development' into update_power_switch_if 2023-03-15 12:33:08 +01:00
2f90e12179 Merge remote-tracking branch 'upstream/development' into important_bugfix_linux_get_uptime 2023-03-15 12:32:25 +01:00
8b77fac099 Merge pull request 'health service fixes and changelog' (#746) from eive/fsfw:health_service_fixes into development
Reviewed-on: fsfw/fsfw#746
2023-03-15 12:29:31 +01:00
47503824d7 health service fixes and changelog 2023-03-15 12:27:39 +01:00
5e3f5c4121 fuse update 2023-03-15 12:25:39 +01:00
1f36c082ef bugfix and changelog for Linux getUptime 2023-03-15 12:21:50 +01:00
aa84e93603 small tweak for version getter 2023-03-15 12:17:36 +01:00
8f63a0e747 changelog 2023-03-15 12:15:21 +01:00
6fc8f756a7 update power switch IF 2023-03-15 12:13:55 +01:00
d98ed40e3d add CFDP subsystem ID 2023-03-15 12:09:30 +01:00
b057250bfb changelog 2023-03-15 11:53:12 +01:00
066dd0d397 changelog 2023-03-15 11:52:20 +01:00
f735c2e9d4 assert size larger than 0 2023-03-15 11:51:51 +01:00
54ef9ec3f6 Merge branch 'develop' into develop_update 2023-03-15 11:50:12 +01:00
43fd0b2f59 resolve some more merge conflicts 2023-03-15 11:48:50 +01:00
d0607824ad Merge remote-tracking branch 'upstream/development' into develop 2023-03-15 11:40:48 +01:00
cf27954a86 changelog 2023-03-14 19:55:01 +01:00
f84e3284ab just hardcode spill option to true 2023-03-14 19:54:21 +01:00
5250423d1d Merge pull request 'Periodic HK helper simplification' (#136) from periodic_hk_helper_simplification into develop
Reviewed-on: #136
2023-03-14 18:27:14 +01:00
522bd41d6e changelog 2023-03-14 18:26:44 +01:00
c61c85280b remove more code 2023-03-14 18:26:04 +01:00
afbe5e1f65 Merge remote-tracking branch 'origin/develop' into periodic_hk_helper_simplification 2023-03-14 18:23:57 +01:00
4c88ab80c8 Merge pull request 'Pool Manager spill to higher pools option' (#135) from pool_manager_spilling_opt into develop
Reviewed-on: #135
2023-03-14 18:22:31 +01:00
5ba69b169f changelog 2023-03-14 18:22:00 +01:00
40405fe6c7 add spill option 2023-03-14 18:21:16 +01:00
aac32e763c some compile fixes 2023-03-14 18:20:17 +01:00
bf980d74c0 HK helper simplification 2023-03-14 17:40:39 +01:00
b6b9d1d790 make dataset enable idempotent 2023-03-14 16:49:46 +01:00
0973ba6bf2 Merge pull request 'basic faulty cb for power switcher component' (#134) from feature_power_switch_faulty_cb into develop
Reviewed-on: #134
2023-03-14 14:15:11 +01:00
1cfebb5d47 Merge branch 'develop' into feature_power_switch_faulty_cb 2023-03-14 14:14:50 +01:00
0b0a0299bc power switch IF improvements 2023-03-14 13:45:03 +01:00
8382d61b92 possible fix for power switch component 2023-03-14 11:44:13 +01:00
7208343b6d basic faulty cb for power switcher component 2023-03-13 16:01:13 +01:00
9a8d775eb1 optimization for cmd executor 2023-03-12 20:49:34 +01:00
4d6f6e6b23 event manager queue depth configurable 2023-03-10 14:58:20 +01:00
55f6825a03 Revert "Modes: reusing submode for mode mask, more unittests"
This reverts commit f0bddfcb21.
2023-03-10 14:50:16 +01:00
c162acb7df Merge branch 'develop' of https://egit.irs.uni-stuttgart.de/eive/fsfw into develop 2023-03-10 14:23:51 +01:00
87462afe6d better error printout for i2c write error 2023-03-10 14:23:40 +01:00
a8de395ea0 Merge pull request 'Modes: reusing submode for mode mask, more unittests' (#133) from mohr/submode_mask into develop
Reviewed-on: #133
Reviewed-by: Robin Müller <muellerr@irs.uni-stuttgart.de>
2023-03-10 11:22:11 +01:00
f0bddfcb21 Modes: reusing submode for mode mask, more unittests 2023-03-09 16:43:45 +01:00
23d9b44b3e Merge pull request 'exceptionless host filesystem' (#132) from avoid_exceptions into develop
Reviewed-on: #132
2023-03-08 14:55:18 +01:00
26e4445189 exceptionless host filesystem 2023-03-08 14:47:03 +01:00
9ee3cdf729 Merge pull request 'OFF -> NORMAL: Set transition source modes' (#131) from off_to_normal_transition_sources into develop
Reviewed-on: #131
2023-03-08 01:24:54 +01:00
1b7493f945 OFF -> NORMAL: Set transition source modes 2023-03-08 01:18:11 +01:00
7f6ba5f40b Merge pull request 'Feature: Allowed Submodes Mask for Mode List Entry' (#130) from feature_allow_submodes_mode_list_entry into develop
Reviewed-on: #130
Reviewed-by: Steffen Gaisser <gaisser@irs.uni-stuttgart.de>
2023-03-07 17:20:47 +01:00
070b48ada2 review improvements 2023-03-07 17:15:34 +01:00
d9a139e1ef Merge remote-tracking branch 'origin/develop' into feature_allow_submodes_mode_list_entry 2023-03-07 16:31:28 +01:00
c80a3752d9 afmt 2023-03-07 16:31:08 +01:00
af58c414fc bugfix in submode check logic 2023-03-07 16:29:10 +01:00
4c48668125 add copy and assignment ctor for mode definition 2023-03-07 16:03:28 +01:00
2745b2080d allow submode mask now 2023-03-07 13:55:40 +01:00
e9d9f44605 added length check 2023-03-06 14:01:45 +01:00
2c5af91db1 Merge pull request 'new monotonic clock API' (#128) from feature_monotonic_clock_api into develop
Reviewed-on: #128
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-03-04 11:47:37 +01:00
5cd7b98ba7 more todo docs 2023-03-04 11:38:16 +01:00
a39f1271ec return FAILED for win 2023-03-04 11:32:32 +01:00
bbf0d7a0d2 add basic impl (no windows) for host 2023-03-04 11:31:54 +01:00
04ee3c7362 renaming 2023-03-04 11:04:55 +01:00
95dab69b35 new monotonic clock API 2023-03-04 11:03:22 +01:00
33de15205b Merge pull request 'configurable queue depth' (#127) from feature_configurable_queue_depth_tcpip_servers into develop
Reviewed-on: #127
2023-03-03 16:33:29 +01:00
4d353a1ad2 remove obsolete constant 2023-03-03 16:36:30 +01:00
6006c97e48 configurable queue depth 2023-03-03 15:45:44 +01:00
6e17e45506 Merge pull request 'timeval: Use system clock' (#126) from feature_timeval_use_sysclock into develop
Reviewed-on: #126
2023-03-03 15:25:38 +01:00
64537d442a extneded and fixed countdown unittests 2023-03-03 14:54:52 +01:00
78cf00315d use sys clock for Countdown 2023-03-03 14:30:35 +01:00
245886c555 add lock context for pool manager 2023-03-02 15:33:49 +01:00
f84097543e allow passing context to mutex guard 2023-03-02 15:20:59 +01:00
511d07c0c7 refactored MGM device code 2023-02-26 21:26:24 +01:00
cf735143fe update for SPI/gyro dev handler code 2023-02-26 14:54:35 +01:00
bdfe31dba4 Merge branch 'mueller/pus-15-tm-storage' into develop 2023-02-24 19:03:21 +01:00
216f603d62 Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2023-02-24 16:56:32 +01:00
174a6aa862 Merge pull request 'use timeval instead of uptime for stopwatch' (#125) from stopwatch-fix into develop
Reviewed-on: #125
Reviewed-by: Robin Müller <muellerr@irs.uni-stuttgart.de>
2023-02-24 16:51:28 +01:00
c2d9370aa1 Merge branch 'develop' into stopwatch-fix 2023-02-24 16:51:08 +01:00
893b434728 allow dest handler to handle folder destinations 2023-02-24 16:49:23 +01:00
6eba84566d use timeval instead of uptime 2023-02-24 16:39:49 +01:00
f0415a97b1 some fixes and improvements 2023-02-24 15:49:05 +01:00
abcf1b29b2 execution complete 2023-02-24 14:50:36 +01:00
dc7afc5415 Version bump, CHANGELOG update, format 2023-02-23 13:38:24 +01:00
9bf3ff95b7 Merge pull request 'Add Health Service Announce All Health Info' (#725) from eive/fsfw:add_health_service_announce_all into development
Reviewed-on: fsfw/fsfw#725
2023-02-23 13:13:56 +01:00
61562b18ab Merge branch 'development' into add_health_service_announce_all 2023-02-23 12:56:12 +01:00
d76d97a36b changed health table parameter to objectId 2023-02-23 12:44:42 +01:00
d373c45d36 Merge branch 'develop' into mueller/pus-15-tm-storage 2023-02-22 15:45:54 +01:00
bd208038dd printout fixes 2023-02-22 15:45:39 +01:00
206af00c8b Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2023-02-21 11:14:19 +01:00
2efff4d2c5 missing include 2023-02-21 02:59:13 +01:00
2a0c244468 add pus 15 store ID 2023-02-20 16:10:21 +01:00
e1711f0345 Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2023-02-20 15:04:13 +01:00
c327985222 printout tweak 2023-02-20 15:02:00 +01:00
76b377c4c0 Merge pull request 'Mode Service: Add allowed subservice' (#739) from eive/fsfw:small_mode_service_fix into development
Reviewed-on: fsfw/fsfw#739
2023-02-20 13:40:53 +01:00
b45206ccd6 Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2023-02-20 13:33:10 +01:00
c8469ca647 a lot of bug potential here 2023-02-18 14:03:19 +01:00
2d6622b8b8 wtf is this interface 2023-02-18 13:51:24 +01:00
5f9eb01d94 better naming 2023-02-18 13:46:51 +01:00
3568bdbecf lets see if this fixes the issue 2023-02-18 13:45:49 +01:00
fcd84b59ae how the hell does this break anything 2023-02-18 13:37:39 +01:00
e3c968096b i2c small improvements 2023-02-18 13:07:38 +01:00
c745c0c8b4 Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2023-02-17 13:18:09 +01:00
be015b4c66 service 11: cast to fix warning 2023-02-17 12:07:50 +01:00
dae5e988fd Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2023-02-17 11:52:23 +01:00
a6d707a7db SubsystemBase: Add function to update child modes 2023-02-17 02:04:17 +01:00
fe41d73895 remove obsolete mode 2023-02-16 17:57:03 +01:00
70b785984c Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2023-02-14 17:33:59 +01:00
9de6c4b3aa printout corrections 2023-02-14 14:33:02 +01:00
d256ede8c1 fix cppcheck lint 2023-02-14 10:33:22 +01:00
f0b8457ba2 bugfix for SPI
- Set transfer length to 0 for failed transfers
2023-02-13 13:51:52 +01:00
dac2d210b5 updates for thermal module in DHB 2023-02-13 00:36:54 +01:00
8b4f73a97b better error msg 2023-02-12 21:07:11 +01:00
7fae6cbd6d added missing CS unlock 2023-02-12 20:06:32 +01:00
d302ba7185 afmt 2023-02-10 13:51:16 +01:00
3562bf11b9 CHANGELOG update 2023-02-10 11:06:46 +01:00
fffb2b61e5 release check helper 2023-02-10 11:06:30 +01:00
94e5f62331 add allowed subservice 2023-02-09 18:30:08 +01:00
14a92b3d89 typo 2023-02-09 18:28:16 +01:00
e4fd424d66 Merge branch 'possible_tc_sched_fixes' into develop 2023-02-09 18:25:44 +01:00
341a66c265 changelog 2023-02-09 18:22:00 +01:00
b9b076aa4c logic error 2023-02-09 18:18:25 +01:00
d93486a340 that time margin check is possible broken 2023-02-09 18:18:05 +01:00
820a7f059c logic error 2023-02-09 18:13:58 +01:00
f4d188c36f that time margin check is possible broken 2023-02-09 18:12:43 +01:00
1841f92944 important bugfix for thermal set 2023-02-09 17:17:42 +01:00
b279985859 refactor DHB: Bugfix for thermal module 2023-02-09 16:42:38 +01:00
0a9c563bbc format 2023-02-09 15:58:48 +01:00
fa7675897d Merge pull request 'Mode Service Bugfixes' (#736) from eive/fsfw:mode_service_fixes into development
Reviewed-on: fsfw/fsfw#736
2023-02-09 15:56:26 +01:00
3a2393885f more style 2023-02-09 15:44:39 +01:00
c752b6d143 Merge pull request 'Generic TMTC Bridge Update' (#734) from eive/fsfw:tmtcbridge_tweaks into development
Reviewed-on: fsfw/fsfw#734
2023-02-09 15:37:35 +01:00
b676040c7c Merge pull request 'CMakeLists file updates' (#731) from eive/fsfw:cmakelists_update into development
Reviewed-on: fsfw/fsfw#731
2023-02-09 15:29:46 +01:00
010509efb4 removed unneeded find_package parameter for etl 2023-02-09 13:50:16 +01:00
dfb1633f00 Merge branch 'development' into mode_service_fixes 2023-02-09 13:46:19 +01:00
5f7172e130 Merge pull request 'TCP/IP TMTC bridge memory leak fixes' (#737) from eive/fsfw:possible_tcpip_bridge_fixes into development
Reviewed-on: fsfw/fsfw#737
2023-02-09 12:15:45 +01:00
0c6465cd95 Merge pull request 'time stamper empty ctor' (#730) from eive/fsfw:empty_cds_short_ctor into development
Reviewed-on: fsfw/fsfw#730
2023-02-09 11:45:49 +01:00
f94987c46d Merge pull request 'RM3100 important bugfix' (#733) from eive/fsfw:rm3100_fixes into development
Reviewed-on: fsfw/fsfw#733
2023-02-09 11:41:53 +01:00
1809ce359b Merge pull request 'comment tweak to event parser can read everything' (#732) from eive/fsfw:health_if_update into development
Reviewed-on: fsfw/fsfw#732
2023-02-09 11:39:53 +01:00
8c712441ab Making fetch Catch2 quiet as well. 2023-02-09 11:34:58 +01:00
6ce80ea6c5 Merge branch 'possible_tcpip_bridge_fixes' into develop 2023-02-08 21:27:26 +01:00
f1b0ca7cff add PR link 2023-02-08 21:26:37 +01:00
000df85556 bump changelog 2023-02-08 21:24:00 +01:00
1fffcc2229 possiible leak fixes 2023-02-08 21:23:21 +01:00
7f907fb9d3 Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2023-02-08 17:17:33 +01:00
a419806a05 Merge remote-tracking branch 'upstream/development' into mode_service_fixes 2023-02-08 09:33:13 +01:00
134d908f26 that stuff is not in upstream yet.. 2023-02-07 12:52:18 +01:00
40a9e12416 1000 is a bit much 2023-02-07 12:47:40 +01:00
f39054edd4 introduce warning switch 2023-02-07 12:45:29 +01:00
5adf89b911 changelog update 2023-02-07 12:41:42 +01:00
c2e6a22dec important bugfix for RM3100 2023-02-07 12:39:43 +01:00
c8e065a713 comment tweak to event parser can read everything 2023-02-07 12:36:42 +01:00
4dc49c57d5 Merge branch 'develop' into develop_update 2023-02-07 12:31:41 +01:00
e9d629b9b3 Merge branch 'develop' into develop_update 2023-02-07 12:24:27 +01:00
3ed49dbae3 Merge remote-tracking branch 'upstream/development' into empty_cds_short_ctor 2023-02-07 12:24:02 +01:00
a1567de9e8 Merge branch 'develop' into mueller/pus-15-tm-storage 2023-02-07 12:21:35 +01:00
4cf52d5dfe Merge pull request 'Time Service 9 update' (#726) from eive/fsfw:updates_fixes_pus_time_service into development
Reviewed-on: fsfw/fsfw#726
2023-02-07 12:19:45 +01:00
46230e6c6d Merge remote-tracking branch 'upstream/development' into updates_fixes_pus_time_service 2023-02-07 12:11:29 +01:00
b22d439300 bump changelog 2023-02-07 12:10:11 +01:00
7e7b3bbbc9 time stamper empty ctor 2023-02-07 12:07:41 +01:00
06dca7608a time stamper empty ctor 2023-02-07 12:06:34 +01:00
6af5274b68 Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2023-02-07 10:51:17 +01:00
5b92247fbd Merge branch 'development' into add_health_service_announce_all 2023-02-06 16:31:05 +01:00
d9da55fdab Merge branch 'development' into add_health_service_announce_all 2023-02-06 15:03:52 +01:00
066f7a6f9b remove unreachable code 2023-02-06 14:41:14 +01:00
b1e9dd9e4a Merge remote-tracking branch 'upstream/development' into updates_fixes_pus_time_service 2023-02-06 14:24:38 +01:00
c1f42618db small but important bugfix for health service 2023-02-01 19:59:32 +01:00
61df451dd8 update changelog 2023-02-01 17:41:47 +01:00
29ea89044e beatufil 2023-02-01 17:35:49 +01:00
e487f5be87 proper announce all impl 2023-02-01 17:35:32 +01:00
0cc3231ceb Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2023-01-23 14:20:38 +01:00
041d1b8795 Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2023-01-11 09:17:57 +01:00
48403c002d Merge remote-tracking branch 'upstream/development' into develop_update 2022-12-19 15:02:07 +01:00
2aa4af6974 make function public 2022-12-14 13:50:57 +01:00
75fc7a056d Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2022-12-12 09:02:04 +01:00
1b005d706a Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2022-12-01 16:40:39 +01:00
e68f54b9bd Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2022-11-28 11:37:15 +01:00
e86d8c64db Merge branch 'develop' into develop_update 2022-11-28 08:36:13 +01:00
1de1b045cd Merge remote-tracking branch 'upstream/development' into develop_update 2022-11-28 08:28:56 +01:00
296bc56e2a Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2022-11-24 15:16:34 +01:00
2b6a33e718 afmt 2022-11-11 14:13:46 +01:00
61fd5d1b62 impl function to generate ASCII timestamp sec accuracy 2022-11-11 14:12:42 +01:00
046dbe1deb Merge branch 'develop' into mueller/pus-15-tm-storage 2022-11-11 11:38:32 +01:00
0303c1a885 remove file 2022-11-11 11:31:22 +01:00
4d2802a470 Merge remote-tracking branch 'origin/develop' into mueller/pus-15-tm-storage 2022-11-11 11:29:29 +01:00
819a2bfac4 add prototype for new ToAscii CCSDSTime function 2022-10-25 18:20:48 +02:00
096af44e39 needs some fixing 2022-10-24 10:56:01 +02:00
56e8e5a8b3 dont know if I am going to need this 2022-10-24 10:39:43 +02:00
143 changed files with 1625 additions and 1218 deletions

8
.idea/cmake.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeSharedSettings">
<configurations>
<configuration PROFILE_NAME="Debug Test" ENABLED="true" CONFIG_NAME="Debug" GENERATION_OPTIONS="-DFSFW_BUILD_TESTS=ON -DFSFW_OSAL=host" />
</configurations>
</component>
</project>

View File

@ -8,27 +8,72 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
# [unreleased]
# [v6.0.0]
## Fixes
- The `PusTmCreator` API only accepted 255 bytes of source data. It can now accept source
data with a size limited only by the size of `size_t`.
- Important bugfix in CFDP PDU header format: The entity length field and the transaction sequence
number fields stored the actual length of the field instead of the length minus 1 like specified
in the CFDP standard.
- PUS Health Service: Size check for set health command.
Perform operation completion for announce health command.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/746
- Linux OSAL `getUptime` fix: Check validity of `/proc/uptime` file before reading uptime.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/745
- Small tweak for version getter
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/744
## Added
- add CFDP subsystem ID
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/742
- `PusTmZcWriter` now exposes API to set message counter field.
## Changed
- HK generation is now countdown based.
- Bump ETL version to 20.35.14
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/748
- Renamed `PCDU_2` subsystem ID to `POWER_SWITCH_IF`.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/743
- Add new `PowerSwitchIF::SWITCH_UNKNOWN` returnvalue.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/743
- Assert that `FixedArrayList` is larger than 0 at compile time.
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/740
- Health functions are virtual now.
# [v6.0.0] 2023-02-10
## Fixes
- Mode Service: Add allowed subservice
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/739
- `CService200ModeManagement`: Various bugfixes which lead to now execution complete being generated
on mode announcements, duplicate mode reply generated on announce commands, and the mode read
subservice not working properly.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/736
- Memory leak fixes for the TCP/IP TMTC bridge.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/737
- `Service9TimeManagement`: Fix the time dump at the `SET_TIME` subservice: Include clock timeval
seconds instead of uptime.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/726
- HAL MGM3100 Handler: Use axis specific gain/scaling factors. Previously,
only the X scaling factor was used.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/724
- HAL MGM3100 Handler: Z value was previously calculated with bytes of the X value.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/733
- DHB `setNormalDatapoolEntriesInvalid`: The default implementation did not set the validity
to false correctly because the `read` and `write` calls were missing.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/728
- PUS TMTC creator module: Sequence flags were set to continuation segment (0b00) instead
of the correct unsegmented flags (0b11) as specified in the standard.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/727
- TC Scheduler Service 11: Add size and CRC check for contained TC.
Bug: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/issues/719
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/720
- Only delete health table entry in `HealthHelper` destructor if
health table was set.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/710/files
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/710
- I2C Bugfixes: Do not keep iterator as member and fix some incorrect handling with the iterator.
Also properly reset the reply size for successfull transfers and erroneous transfers.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/700
@ -38,11 +83,43 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- `TcpTmTcServer.cpp`: The server was actually not able to handle
CCSDS packets which were clumped together. This has been fixed now.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/673
- `CServiceHealthCommanding`: Add announce all health info implementation
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/725
- various fixes related to linux Unittests and memory leaks
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/715
- small fix to allow teardown handling
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/713
- fix compiler warning for fixed array list copy ctor
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/704
- missing include
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/703
- defaultconfig did not build anymore
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/702
- hotfix
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/699
- small fix for helper
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/698
- missing retval conv
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/697
- DHB Countdown Bug
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/693
- doc corrections
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/687
- better error printout
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/686
- include correction
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/683
- better warning for missing include paths
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/676
- Service 11 regression
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/670
## Added
- `CServiceHealthCommanding`: Add announce all health info implementation
PR: https://egit.irs.uni-stuttgart.de/eive/fsfw/pulls/122
- Empty constructor for `CdsShortTimeStamper` which does not do an object manager registration.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/730
- `Service9TimeManagement`: Add `DUMP_TIME` (129) subservice.
- `TcpTmTcServer`: Allow setting the `SO_REUSEADDR` and `SO_REUSEPORT`
option on the TCP server. CTOR prototype has changed and expects an explicit
@ -54,17 +131,36 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
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
- publish documentation for development and master branch
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/681
- Add Linux HAL options
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/663
- Expand SerializeIF
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/656
- PUS Service 11: Additional Safety Check
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/666
- improvements for auto-formatter script
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/665
- provide a weak print char impl
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/674
## Removed
- now that doc server is up, remove markdown files
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/688
- remove bsp specific code
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/679
## Changes
- `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
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/725
- `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.
so 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
@ -94,18 +190,41 @@ 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
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/684
- 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
- Generic TMTC Bridge Update
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/734
- comment tweak to event parser can read everything
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/732
- CMakeLists file updates
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/731
- improve srv20 error messages
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/723
- I2C Linux: remove duplicate printout
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/718
- printout handling improvements
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/717
- vec getter, reset for content
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/716
- updates for source sequence counter
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/714
- SP reader getPacketData is const now
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/708
- refactoring of serial drivers for linux
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/705
- Local Pool Update Remove Add Data Ignore Fault Argument
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/701
- Switch to new documentation server
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/694
- Windows Tweaks
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/691
- Refactor Local Pool API
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/667
- group MGM data in local pool vectors
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/664
## CFDP
@ -125,17 +244,7 @@ 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
# [v5.0.0] 2022-07-25
## Changes

View File

@ -13,7 +13,7 @@ list(APPEND CMAKE_MODULE_PATH
# Version file handling #
# ##############################################################################
set(FSFW_VERSION_IF_GIT_FAILS 5)
set(FSFW_VERSION_IF_GIT_FAILS 6)
set(FSFW_SUBVERSION_IF_GIT_FAILS 0)
set(FSFW_REVISION_IF_GIT_FAILS 0)
@ -72,7 +72,7 @@ set(FSFW_ETL_LIB_MAJOR_VERSION
20
CACHE STRING "ETL library major version requirement")
set(FSFW_ETL_LIB_VERSION
${FSFW_ETL_LIB_MAJOR_VERSION}.28.0
${FSFW_ETL_LIB_MAJOR_VERSION}.35.14
CACHE STRING "ETL library exact version requirement")
set(FSFW_ETL_LINK_TARGET etl::etl)
@ -153,12 +153,12 @@ if(FSFW_BUILD_TESTS)
"${MSG_PREFIX} Building the FSFW unittests in addition to the static library"
)
# Check whether the user has already installed Catch2 first
find_package(Catch2 ${FSFW_CATCH2_LIB_MAJOR_VERSION})
find_package(Catch2 ${FSFW_CATCH2_LIB_MAJOR_VERSION} QUIET)
# Not installed, so use FetchContent to download and provide Catch2
if(NOT Catch2_FOUND)
message(
STATUS
"${MSG_PREFIX} Catch2 installation not found. Downloading Catch2 library with FetchContent"
"${MSG_PREFIX} Catch2 installation not found. Downloading Catch2 library with FetchContent."
)
include(FetchContent)
@ -196,13 +196,13 @@ message(
)
# Check whether the user has already installed ETL first
find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} CONFIG QUIET)
find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET)
# Not installed, so use FetchContent to download and provide etl
if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
message(
STATUS
"${MSG_PREFIX} No ETL installation was found with find_package. Installing and providing "
"etl with FindPackage")
"${MSG_PREFIX} ETL installation not found. Downloading ETL with FetchContent."
)
include(FetchContent)
FetchContent_Declare(

110
scripts/check_release.py Executable file
View File

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

View File

@ -59,17 +59,24 @@ void ActionHelper::setQueueToUse(MessageQueueIF* queue) { queueToUse = queue; }
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
store_address_t dataAddress) {
bool hasAdditionalData = false;
const uint8_t* dataPtr = nullptr;
size_t size = 0;
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
if (result != returnvalue::OK) {
CommandMessage reply;
ActionMessage::setStepReply(&reply, actionId, 0, result);
queueToUse->sendMessage(commandedBy, &reply);
return;
ReturnValue_t result;
if (dataAddress != store_address_t::invalid()) {
hasAdditionalData = true;
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
if (result != returnvalue::OK) {
CommandMessage reply;
ActionMessage::setStepReply(&reply, actionId, 0, result);
queueToUse->sendMessage(commandedBy, &reply);
return;
}
}
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
ipcStore->deleteData(dataAddress);
if (hasAdditionalData) {
ipcStore->deleteData(dataAddress);
}
if (result == HasActionsIF::EXECUTION_FINISHED) {
CommandMessage reply;
ActionMessage::setCompletionReply(&reply, actionId, true, result);

View File

@ -2,7 +2,6 @@
#define FSFW_CFDP_H
#include "cfdp/definitions.h"
#include "cfdp/handler/CfdpHandler.h"
#include "cfdp/handler/DestHandler.h"
#include "cfdp/handler/FaultHandlerBase.h"
#include "cfdp/helpers.h"

View File

@ -1,3 +1,2 @@
target_sources(
${LIB_FSFW_NAME} PRIVATE SourceHandler.cpp DestHandler.cpp
FaultHandlerBase.cpp UserBase.cpp CfdpHandler.cpp)
target_sources(${LIB_FSFW_NAME} PRIVATE SourceHandler.cpp DestHandler.cpp
FaultHandlerBase.cpp UserBase.cpp)

View File

@ -1,134 +0,0 @@
#include "CfdpHandler.h"
#include "fsfw/cfdp/pdu/AckPduReader.h"
#include "fsfw/cfdp/pdu/PduHeaderReader.h"
#include "fsfw/globalfunctions/arrayprinter.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/tmtcservices/TmTcMessage.h"
using namespace returnvalue;
using namespace cfdp;
CfdpHandler::CfdpHandler(const FsfwHandlerParams& fsfwParams, const CfdpHandlerCfg& cfdpCfg)
: SystemObject(fsfwParams.objectId),
msgQueue(fsfwParams.msgQueue),
destHandler(
DestHandlerParams(LocalEntityCfg(cfdpCfg.id, cfdpCfg.indicCfg, cfdpCfg.faultHandler),
cfdpCfg.userHandler, cfdpCfg.remoteCfgProvider, cfdpCfg.packetInfoList,
cfdpCfg.lostSegmentsList),
FsfwParams(fsfwParams.packetDest, nullptr, this, fsfwParams.tcStore,
fsfwParams.tmStore)) {
destHandler.setMsgQueue(msgQueue);
}
[[nodiscard]] const char* CfdpHandler::getName() const { return "CFDP Handler"; }
[[nodiscard]] uint32_t CfdpHandler::getIdentifier() const {
return destHandler.getDestHandlerParams().cfg.localId.getValue();
}
[[nodiscard]] MessageQueueId_t CfdpHandler::getRequestQueue() const { return msgQueue.getId(); }
ReturnValue_t CfdpHandler::initialize() {
ReturnValue_t result = destHandler.initialize();
if (result != OK) {
return result;
}
tcStore = destHandler.getTcStore();
tmStore = destHandler.getTmStore();
return SystemObject::initialize();
}
ReturnValue_t CfdpHandler::performOperation(uint8_t operationCode) {
// TODO: Receive TC packets and route them to source and dest handler, depending on which is
// correct or more appropriate
ReturnValue_t status;
ReturnValue_t result = OK;
TmTcMessage tmtcMsg;
for (status = msgQueue.receiveMessage(&tmtcMsg); status == returnvalue::OK;
status = msgQueue.receiveMessage(&tmtcMsg)) {
result = handleCfdpPacket(tmtcMsg);
if (result != OK) {
status = result;
}
}
auto& fsmRes = destHandler.performStateMachine();
// TODO: Error handling?
while (fsmRes.callStatus == CallStatus::CALL_AGAIN) {
destHandler.performStateMachine();
// TODO: Error handling?
}
return status;
}
ReturnValue_t CfdpHandler::handleCfdpPacket(TmTcMessage& msg) {
auto accessorPair = tcStore->getData(msg.getStorageId());
if (accessorPair.first != OK) {
return accessorPair.first;
}
PduHeaderReader reader(accessorPair.second.data(), accessorPair.second.size());
ReturnValue_t result = reader.parseData();
if (result != returnvalue::OK) {
return INVALID_PDU_FORMAT;
}
// The CFDP distributor should have taken care of ensuring the destination ID is correct
PduType type = reader.getPduType();
// Only the destination handler can process these PDUs
if (type == PduType::FILE_DATA) {
// Disable auto-deletion of packet
accessorPair.second.release();
PacketInfo info(type, msg.getStorageId());
result = destHandler.passPacket(info);
} else {
// Route depending on PDU type and directive type if applicable. It retrieves directive type
// from the raw stream for better performance (with sanity and directive code check).
// The routing is based on section 4.5 of the CFDP standard which specifies the PDU forwarding
// procedure.
// PDU header only. Invalid supplied data. A directive packet should have a valid data field
// with at least one byte being the directive code
const uint8_t* pduDataField = reader.getPduDataField();
if (pduDataField == nullptr) {
return INVALID_PDU_FORMAT;
}
if (not FileDirectiveReader::checkFileDirective(pduDataField[0])) {
return INVALID_DIRECTIVE_FIELD;
}
auto directive = static_cast<FileDirective>(pduDataField[0]);
auto passToDestHandler = [&]() {
accessorPair.second.release();
PacketInfo info(type, msg.getStorageId(), directive);
result = destHandler.passPacket(info);
};
auto passToSourceHandler = [&]() {
};
if (directive == FileDirective::METADATA or directive == FileDirective::EOF_DIRECTIVE or
directive == FileDirective::PROMPT) {
// Section b) of 4.5.3: These PDUs should always be targeted towards the file receiver a.k.a.
// the destination handler
passToDestHandler();
} else if (directive == FileDirective::FINISH or directive == FileDirective::NAK or
directive == FileDirective::KEEP_ALIVE) {
// Section c) of 4.5.3: These PDUs should always be targeted towards the file sender a.k.a.
// the source handler
passToSourceHandler();
} else if (directive == FileDirective::ACK) {
// Section a): Recipient depends of the type of PDU that is being acknowledged. We can simply
// extract the PDU type from the raw stream. If it is an EOF PDU, this packet is passed to
// the source handler, for a Finished PDU, it is passed to the destination handler.
FileDirective ackedDirective;
if (not AckPduReader::checkAckedDirectiveField(pduDataField[1], ackedDirective)) {
return INVALID_ACK_DIRECTIVE_FIELDS;
}
if (ackedDirective == FileDirective::EOF_DIRECTIVE) {
passToSourceHandler();
} else if (ackedDirective == FileDirective::FINISH) {
passToDestHandler();
}
}
}
return result;
}

View File

@ -1,71 +0,0 @@
#ifndef FSFW_EXAMPLE_HOSTED_CFDPHANDLER_H
#define FSFW_EXAMPLE_HOSTED_CFDPHANDLER_H
#include <utility>
#include "fsfw/cfdp/handler/DestHandler.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
#include "fsfw/tmtcservices/TmTcMessage.h"
struct FsfwHandlerParams {
FsfwHandlerParams(object_id_t objectId, HasFileSystemIF& vfs, AcceptsTelemetryIF& packetDest,
StorageManagerIF& tcStore, StorageManagerIF& tmStore, MessageQueueIF& msgQueue)
: objectId(objectId),
vfs(vfs),
packetDest(packetDest),
tcStore(tcStore),
tmStore(tmStore),
msgQueue(msgQueue) {}
object_id_t objectId{};
HasFileSystemIF& vfs;
AcceptsTelemetryIF& packetDest;
StorageManagerIF& tcStore;
StorageManagerIF& tmStore;
MessageQueueIF& msgQueue;
};
struct CfdpHandlerCfg {
CfdpHandlerCfg(cfdp::EntityId localId, cfdp::IndicationCfg indicationCfg,
cfdp::UserBase& userHandler, cfdp::FaultHandlerBase& userFaultHandler,
cfdp::PacketInfoListBase& packetInfo, cfdp::LostSegmentsListBase& lostSegmentsList,
cfdp::RemoteConfigTableIF& remoteCfgProvider)
: id(std::move(localId)),
indicCfg(indicationCfg),
packetInfoList(packetInfo),
lostSegmentsList(lostSegmentsList),
remoteCfgProvider(remoteCfgProvider),
userHandler(userHandler),
faultHandler(userFaultHandler) {}
cfdp::EntityId id;
cfdp::IndicationCfg indicCfg;
cfdp::PacketInfoListBase& packetInfoList;
cfdp::LostSegmentsListBase& lostSegmentsList;
cfdp::RemoteConfigTableIF& remoteCfgProvider;
cfdp::UserBase& userHandler;
cfdp::FaultHandlerBase& faultHandler;
};
class CfdpHandler : public SystemObject, public ExecutableObjectIF, public AcceptsTelecommandsIF {
public:
explicit CfdpHandler(const FsfwHandlerParams& fsfwParams, const CfdpHandlerCfg& cfdpCfg);
[[nodiscard]] const char* getName() const override;
[[nodiscard]] uint32_t getIdentifier() const override;
[[nodiscard]] MessageQueueId_t getRequestQueue() const override;
ReturnValue_t initialize() override;
ReturnValue_t performOperation(uint8_t operationCode) override;
private:
MessageQueueIF& msgQueue;
cfdp::DestHandler destHandler;
StorageManagerIF* tcStore = nullptr;
StorageManagerIF* tmStore = nullptr;
ReturnValue_t handleCfdpPacket(TmTcMessage& msg);
};
#endif // FSFW_EXAMPLE_HOSTED_CFDPHANDLER_H

View File

@ -178,16 +178,25 @@ ReturnValue_t cfdp::DestHandler::handleFileDataPdu(const cfdp::PacketInfo& info)
dp.user.fileSegmentRecvdIndication(segParams);
}
result = dp.user.vfs.writeToFile(fileOpParams, fileData);
if (offset.value() + fileSegmentLen > tp.progress) {
tp.progress = offset.value() + fileSegmentLen;
}
if (result != returnvalue::OK) {
// TODO: Proper Error handling
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "File write error" << std::endl;
sif::error << "cfdp::DestHandler: VFS file write error with code 0x" << std::hex << std::setw(2)
<< result << std::endl;
#endif
tp.vfsErrorCount++;
if (tp.vfsErrorCount < 3) {
// TODO: Provide execution step as parameter
fp.eventReporter->forwardEvent(events::FILESTORE_ERROR, static_cast<uint8_t>(fsmRes.step),
result);
}
return result;
} else {
tp.deliveryStatus = FileDeliveryStatus::RETAINED_IN_FILESTORE;
tp.vfsErrorCount = 0;
}
if (offset.value() + fileSegmentLen > tp.progress) {
tp.progress = offset.value() + fileSegmentLen;
}
return result;
}
@ -271,35 +280,55 @@ ReturnValue_t cfdp::DestHandler::startTransaction(MetadataPduReader& reader, Met
return OK;
}
ReturnValue_t result = OK;
fsmRes.step = TransactionStep::TRANSACTION_START;
if (reader.getTransmissionMode() == TransmissionMode::UNACKNOWLEDGED) {
fsmRes.state = CfdpStates::BUSY_CLASS_1_NACKED;
} else if (reader.getTransmissionMode() == TransmissionMode::ACKNOWLEDGED) {
fsmRes.state = CfdpStates::BUSY_CLASS_2_ACKED;
}
tp.checksumType = info.getChecksumType();
tp.closureRequested = info.isClosureRequested();
size_t sourceNameSize = 0;
const uint8_t* sourceNamePtr = info.getSourceFileName().getValue(&sourceNameSize);
if (sourceNameSize > tp.sourceName.size()) {
// TODO: Warning, event etc.
if (sourceNameSize + 1 > tp.sourceName.size()) {
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "source filename too large");
return FAILED;
}
std::memcpy(tp.sourceName.data(), sourceNamePtr, sourceNameSize);
tp.sourceName[sourceNameSize] = '\0';
size_t destNameSize = 0;
const uint8_t* destNamePtr = info.getDestFileName().getValue(&destNameSize);
if (destNameSize > tp.destName.size()) {
// TODO: Warning, event etc.
if (destNameSize + 1 > tp.destName.size()) {
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "dest filename too large");
return FAILED;
}
std::memcpy(tp.destName.data(), destNamePtr, destNameSize);
tp.destName[destNameSize] = '\0';
reader.fillConfig(tp.pduConf);
tp.pduConf.direction = Direction::TOWARDS_SENDER;
tp.transactionId.entityId = tp.pduConf.sourceId;
tp.transactionId.seqNum = tp.pduConf.seqNum;
if (not dp.remoteCfgTable.getRemoteCfg(tp.pduConf.sourceId, &tp.remoteCfg)) {
// If both dest name size and source name size are 0, we are dealing with a metadata only PDU,
// so there is no need to create a file or truncate an existing file
if (destNameSize > 0 and sourceNameSize > 0) {
FilesystemParams fparams(tp.destName.data());
// handling to allow only specifying target directory. Example:
// Source path /test/hello.txt, dest path /tmp -> dest path /tmp/hello.txt
if (dp.user.vfs.isDirectory(tp.destName.data())) {
result = tryBuildingAbsoluteDestName(destNameSize);
if (result != OK) {
return result;
}
}
if (dp.user.vfs.fileExists(fparams)) {
result = dp.user.vfs.truncateFile(fparams);
if (result != returnvalue::OK) {
fileErrorHandler(events::FILESTORE_ERROR, result, "file truncation error");
return FAILED;
// TODO: Relevant for filestore rejection error?
}
} else {
result = dp.user.vfs.createFile(fparams);
if (result != OK) {
fileErrorHandler(events::FILESTORE_ERROR, result, "file creation error");
return FAILED;
// TODO: Relevant for filestore rejection error?
}
}
}
EntityId sourceId;
reader.getSourceId(sourceId);
if (not dp.remoteCfgTable.getRemoteCfg(sourceId, &tp.remoteCfg)) {
// TODO: Warning, event etc.
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler" << __func__
@ -308,22 +337,18 @@ ReturnValue_t cfdp::DestHandler::startTransaction(MetadataPduReader& reader, Met
#endif
return FAILED;
}
// If both dest name size and source name size are 0, we are dealing with a metadata only PDU,
// so there is no need to create a file or truncate an existing file
if (destNameSize > 0 and sourceNameSize > 0) {
FilesystemParams fparams(tp.destName.data());
// TODO: Filesystem errors?
if (dp.user.vfs.fileExists(fparams)) {
dp.user.vfs.truncateFile(fparams);
} else {
result = dp.user.vfs.createFile(fparams);
if (result != OK) {
// TODO: Handle FS error. This is probably a case for the filestore rejection mechanism of
// CFDP.
// In any case, it does not really make sense to continue here
}
}
fsmRes.step = TransactionStep::TRANSACTION_START;
if (reader.getTransmissionMode() == TransmissionMode::UNACKNOWLEDGED) {
fsmRes.state = CfdpStates::BUSY_CLASS_1_NACKED;
} else if (reader.getTransmissionMode() == TransmissionMode::ACKNOWLEDGED) {
fsmRes.state = CfdpStates::BUSY_CLASS_2_ACKED;
}
tp.checksumType = info.getChecksumType();
tp.closureRequested = info.isClosureRequested();
reader.fillConfig(tp.pduConf);
tp.pduConf.direction = Direction::TOWARDS_SENDER;
tp.transactionId.entityId = tp.pduConf.sourceId;
tp.transactionId.seqNum = tp.pduConf.seqNum;
fsmRes.step = TransactionStep::RECEIVING_FILE_DATA_PDUS;
MetadataRecvdParams params(tp.transactionId, tp.pduConf.sourceId);
params.fileSize = tp.fileSize.getSize();
@ -362,6 +387,37 @@ ReturnValue_t cfdp::DestHandler::handleTransferCompletion() {
return OK;
}
ReturnValue_t cfdp::DestHandler::tryBuildingAbsoluteDestName(size_t destNameSize) {
char baseNameBuf[tp.destName.size()]{};
FilesystemParams fparamsSrc(tp.sourceName.data());
size_t baseNameLen = 0;
ReturnValue_t result =
dp.user.vfs.getBaseFilename(fparamsSrc, baseNameBuf, sizeof(baseNameBuf), baseNameLen);
if (result != returnvalue::OK or baseNameLen == 0) {
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0, "error retrieving source base name");
return FAILED;
}
// Destination name + slash + base name + null termination
if (destNameSize + 1 + baseNameLen + 1 > tp.destName.size()) {
fileErrorHandler(events::FILENAME_TOO_LARGE_ERROR, 0,
"dest filename too large after adding source base name");
return FAILED;
}
tp.destName[destNameSize++] = '/';
std::memcpy(tp.destName.data() + destNameSize, baseNameBuf, baseNameLen);
destNameSize += baseNameLen;
tp.destName[destNameSize++] = '\0';
return OK;
}
void cfdp::DestHandler::fileErrorHandler(Event event, ReturnValue_t result, const char* info) {
fp.eventReporter->forwardEvent(events::FILENAME_TOO_LARGE_ERROR,
static_cast<uint8_t>(fsmRes.step), result);
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "cfdp::DestHandler: " << info << std::endl;
#endif
}
void cfdp::DestHandler::finish() {
tp.reset();
dp.packetListRef.clear();

View File

@ -84,7 +84,7 @@ enum class CallStatus { DONE, CALL_AFTER_DELAY, CALL_AGAIN };
class DestHandler {
public:
enum class TransactionStep {
enum class TransactionStep : uint8_t {
IDLE = 0,
TRANSACTION_START = 1,
RECEIVING_FILE_DATA_PDUS = 2,
@ -157,11 +157,13 @@ class DestHandler {
progress = 0;
remoteCfg = nullptr;
closureRequested = false;
vfsErrorCount = 0;
checksumType = ChecksumType::NULL_CHECKSUM;
}
ChecksumType checksumType = ChecksumType::NULL_CHECKSUM;
bool closureRequested = false;
uint16_t vfsErrorCount = 0;
std::vector<char> sourceName;
std::vector<char> destName;
cfdp::FileSize fileSize;
@ -189,9 +191,11 @@ class DestHandler {
ReturnValue_t handleMetadataParseError(ReturnValue_t result, const uint8_t* rawData,
size_t maxSize);
ReturnValue_t handleTransferCompletion();
ReturnValue_t tryBuildingAbsoluteDestName(size_t destNameSize);
ReturnValue_t sendFinishedPdu();
ReturnValue_t noticeOfCompletion();
ReturnValue_t checksumVerification();
void fileErrorHandler(Event event, ReturnValue_t result, const char* info);
const FsmResult& updateFsmRes(uint8_t errors);
void checkAndHandleError(ReturnValue_t result, uint8_t& errorIdx);
void finish();

View File

@ -12,6 +12,9 @@ namespace events {
static constexpr Event STORE_ERROR = event::makeEvent(SSID, 0, severity::LOW);
static constexpr Event MSG_QUEUE_ERROR = event::makeEvent(SSID, 1, severity::LOW);
static constexpr Event SERIALIZATION_ERROR = event::makeEvent(SSID, 2, severity::LOW);
static constexpr Event FILESTORE_ERROR = event::makeEvent(SSID, 3, severity::LOW);
//! [EXPORT] : [COMMENT] P1: Transaction step ID, P2: 0 for source file name, 1 for dest file name
static constexpr Event FILENAME_TOO_LARGE_ERROR = event::makeEvent(SSID, 4, severity::LOW);
} // namespace events

View File

@ -24,8 +24,8 @@ ReturnValue_t HeaderCreator::serialize(uint8_t **buffer, size_t *size, size_t ma
*buffer += 1;
**buffer = pduDataFieldLen & 0x00ff;
*buffer += 1;
**buffer = segmentationCtrl << 7 | pduConf.sourceId.getWidth() << 4 | segmentMetadataFlag << 3 |
pduConf.seqNum.getWidth();
**buffer = segmentationCtrl << 7 | ((pduConf.sourceId.getWidth() - 1) << 4) |
segmentMetadataFlag << 3 | (pduConf.seqNum.getWidth() - 1);
*buffer += 1;
*size += 4;
ReturnValue_t result = pduConf.sourceId.serialize(buffer, size, maxSize, streamEndianness);

View File

@ -78,11 +78,11 @@ cfdp::SegmentationControl PduHeaderReader::getSegmentationControl() const {
}
cfdp::WidthInBytes PduHeaderReader::getLenEntityIds() const {
return static_cast<cfdp::WidthInBytes>((pointers.fixedHeader->fourthByte >> 4) & 0x07);
return static_cast<cfdp::WidthInBytes>(((pointers.fixedHeader->fourthByte >> 4) & 0b111) + 1);
}
cfdp::WidthInBytes PduHeaderReader::getLenSeqNum() const {
return static_cast<cfdp::WidthInBytes>(pointers.fixedHeader->fourthByte & 0x07);
return static_cast<cfdp::WidthInBytes>((pointers.fixedHeader->fourthByte & 0b111) + 1);
}
cfdp::SegmentMetadataFlag PduHeaderReader::getSegmentMetadataFlag() const {

View File

@ -58,7 +58,7 @@ void ControllerBase::handleQueue() {
void ControllerBase::startTransition(Mode_t mode_, Submode_t submode_) {
changeHK(this->mode, this->submode, false);
triggerEvent(CHANGING_MODE, mode, submode);
triggerEvent(CHANGING_MODE, mode_, submode_);
mode = mode_;
submode = submode_;
modeHelper.modeChanged(mode, submode);

View File

@ -166,9 +166,9 @@ ReturnValue_t Sgp4Propagator::propagate(double* position, double* velocity, time
timeval timeSinceEpoch = time - epoch;
double minutesSinceEpoch = timeSinceEpoch.tv_sec / 60. + timeSinceEpoch.tv_usec / 60000000.;
double yearsSinceEpoch = minutesSinceEpoch / 60 / 24 / 365;
double monthsSinceEpoch = minutesSinceEpoch / 60 / 24 / 30;
if ((yearsSinceEpoch > 1) || (yearsSinceEpoch < -1)) {
if ((monthsSinceEpoch > 1) || (monthsSinceEpoch < -1)) {
return TLE_TOO_OLD;
}

View File

@ -70,8 +70,7 @@ ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) {
return returnvalue::OK;
}
ReturnValue_t LocalDataPoolManager::initializeAfterTaskCreation(uint8_t nonDiagInvlFactor) {
setNonDiagnosticIntervalFactor(nonDiagInvlFactor);
ReturnValue_t LocalDataPoolManager::initializeAfterTaskCreation() {
return initializeHousekeepingPoolEntriesOnce();
}
@ -506,9 +505,9 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(CommandMessage* me
float newCollIntvl = 0;
HousekeepingMessage::getCollectionIntervalModificationCommand(message, &newCollIntvl);
if (command == HousekeepingMessage::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL) {
result = changeCollectionInterval(sid, newCollIntvl, true);
result = changeCollectionInterval(sid, newCollIntvl);
} else {
result = changeCollectionInterval(sid, newCollIntvl, false);
result = changeCollectionInterval(sid, newCollIntvl);
}
break;
}
@ -661,10 +660,6 @@ ReturnValue_t LocalDataPoolManager::serializeHkPacketIntoStore(HousekeepingPacke
return hkPacket.serialize(&dataPtr, serializedSize, maxSize, SerializeIF::Endianness::MACHINE);
}
void LocalDataPoolManager::setNonDiagnosticIntervalFactor(uint8_t nonDiagInvlFactor) {
this->nonDiagnosticIntervalFactor = nonDiagInvlFactor;
}
void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
sid_t sid = receiver.dataId.sid;
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
@ -718,15 +713,15 @@ ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid, bool ena
if ((LocalPoolDataSetAttorney::getReportingEnabled(*dataSet) and enable) or
(not LocalPoolDataSetAttorney::getReportingEnabled(*dataSet) and not enable)) {
return REPORTING_STATUS_UNCHANGED;
return returnvalue::OK;
}
LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, enable);
return returnvalue::OK;
}
ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid, float newCollectionInterval,
bool isDiagnostics) {
ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid,
float newCollectionInterval) {
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
if (dataSet == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "changeCollectionInterval",
@ -734,11 +729,6 @@ ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid, float ne
return DATASET_NOT_FOUND;
}
bool targetIsDiagnostics = LocalPoolDataSetAttorney::isDiagnostics(*dataSet);
if ((targetIsDiagnostics and not isDiagnostics) or (not targetIsDiagnostics and isDiagnostics)) {
return WRONG_HK_PACKET_TYPE;
}
PeriodicHousekeepingHelper* periodicHelper =
LocalPoolDataSetAttorney::getPeriodicHelper(*dataSet);

View File

@ -102,7 +102,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
* @param nonDiagInvlFactor
* @return
*/
ReturnValue_t initializeAfterTaskCreation(uint8_t nonDiagInvlFactor = 5);
ReturnValue_t initializeAfterTaskCreation();
/**
* @brief This should be called in the periodic handler of the owner.
@ -152,17 +152,6 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
MessageQueueId_t targetQueueId,
bool generateSnapshot) override;
/**
* Non-Diagnostics packets usually have a lower minimum sampling frequency
* than diagnostic packets.
* A factor can be specified to determine the minimum sampling frequency
* for non-diagnostic packets. The minimum sampling frequency of the
* diagnostics packets,which is usually jusst the period of the
* performOperation calls, is multiplied with that factor.
* @param factor
*/
void setNonDiagnosticIntervalFactor(uint8_t nonDiagInvlFactor);
/**
* @brief The manager is also able to handle housekeeping messages.
* @details
@ -185,6 +174,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
ReturnValue_t generateHousekeepingPacket(sid_t sid, LocalPoolDataSetBase* dataSet,
bool forDownlink,
MessageQueueId_t destination = MessageQueueIF::NO_QUEUE);
ReturnValue_t changeCollectionInterval(sid_t sid, float newCollectionInterval);
HasLocalDataPoolIF* getOwner();
@ -348,8 +338,6 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
void performPeriodicHkGeneration(HkReceiver& hkReceiver);
ReturnValue_t togglePeriodicGeneration(sid_t sid, bool enable, bool isDiagnostics);
ReturnValue_t changeCollectionInterval(sid_t sid, float newCollectionInterval,
bool isDiagnostics);
ReturnValue_t generateSetStructurePacket(sid_t sid, bool isDiagnostics);
void handleHkUpdateResetListInsertion(DataType dataType, DataId dataId);

View File

@ -250,9 +250,8 @@ void LocalPoolDataSetBase::setReportingEnabled(bool reportingEnabled) {
bool LocalPoolDataSetBase::getReportingEnabled() const { return reportingEnabled; }
void LocalPoolDataSetBase::initializePeriodicHelper(float collectionInterval,
dur_millis_t minimumPeriodicInterval,
uint8_t nonDiagIntervalFactor) {
periodicHelper->initialize(collectionInterval, minimumPeriodicInterval, nonDiagIntervalFactor);
dur_millis_t minimumPeriodicInterval) {
periodicHelper->initialize(collectionInterval, minimumPeriodicInterval);
}
void LocalPoolDataSetBase::setChanged(bool changed) { this->changed = changed; }

View File

@ -191,8 +191,7 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
*/
bool reportingEnabled = false;
void initializePeriodicHelper(float collectionInterval, dur_millis_t minimumPeriodicInterval,
uint8_t nonDiagIntervalFactor = 5);
void initializePeriodicHelper(float collectionInterval, dur_millis_t minimumPeriodicInterval);
/**
* If the valid state of a dataset is always relevant to the whole

View File

@ -12,10 +12,8 @@ class LocalPoolDataSetAttorney {
static bool isDiagnostics(LocalPoolDataSetBase& set) { return set.isDiagnostics(); }
static void initializePeriodicHelper(LocalPoolDataSetBase& set, float collectionInterval,
uint32_t minimumPeriodicIntervalMs,
uint8_t nonDiagIntervalFactor = 5) {
set.initializePeriodicHelper(collectionInterval, minimumPeriodicIntervalMs,
nonDiagIntervalFactor);
uint32_t minimumPeriodicIntervalMs) {
set.initializePeriodicHelper(collectionInterval, minimumPeriodicIntervalMs);
}
static void setReportingEnabled(LocalPoolDataSetBase& set, bool enabled) {

View File

@ -49,6 +49,7 @@ class DeviceCommunicationIF {
// is this needed if there is no open/close call?
static const ReturnValue_t NOT_ACTIVE = MAKE_RETURN_CODE(0x05);
static const ReturnValue_t TOO_MUCH_DATA = MAKE_RETURN_CODE(0x06);
static constexpr ReturnValue_t BUSY = MAKE_RETURN_CODE(0x07);
virtual ~DeviceCommunicationIF() {}

View File

@ -58,12 +58,7 @@ void DeviceHandlerBase::setHkDestination(object_id_t hkDestination) {
this->hkDestination = hkDestination;
}
void DeviceHandlerBase::setThermalStateRequestPoolIds(lp_id_t thermalStatePoolId,
lp_id_t heaterRequestPoolId,
uint32_t thermalSetId) {
thermalSet =
new DeviceHandlerThermalSet(this, thermalSetId, thermalStatePoolId, heaterRequestPoolId);
}
void DeviceHandlerBase::enableThermalModule(ThermalStateCfg cfg) { this->thermalStateCfg = cfg; }
DeviceHandlerBase::~DeviceHandlerBase() {
if (comCookie != nullptr) {
@ -227,12 +222,11 @@ ReturnValue_t DeviceHandlerBase::initialize() {
fillCommandAndReplyMap();
if (thermalSet != nullptr) {
PoolReadGuard pg(thermalSet);
// Set temperature target state to NON_OP.
result = thermalSet->read();
if (result == returnvalue::OK) {
if (pg.getReadResult() == returnvalue::OK) {
thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
thermalSet->heaterRequest.setValid(true);
thermalSet->commit();
}
}
@ -382,7 +376,7 @@ void DeviceHandlerBase::doStateMachine() {
}
ReturnValue_t switchState = getStateOfSwitches();
if ((switchState == PowerSwitchIF::SWITCH_OFF) || (switchState == NO_SWITCH)) {
setMode(_MODE_SWITCH_IS_OFF);
setMode(MODE_OFF, SUBMODE_NONE);
}
} break;
case MODE_OFF:
@ -395,9 +389,6 @@ void DeviceHandlerBase::doStateMachine() {
case MODE_NORMAL:
case MODE_ERROR_ON:
break;
case _MODE_SWITCH_IS_OFF:
setMode(MODE_OFF, SUBMODE_NONE);
break;
default:
triggerEvent(OBJECT_IN_INVALID_MODE, mode, submode);
setMode(_MODE_POWER_DOWN, 0);
@ -574,6 +565,9 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
*/
if (newMode == MODE_ON and continueToNormal) {
continueToNormal = false;
// TODO: Check whether the following two lines are okay to do so.
transitionSourceMode = MODE_ON;
transitionSourceSubMode = newSubmode;
mode = _MODE_TO_NORMAL;
return;
}
@ -594,12 +588,12 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
Clock::getUptime(&timeoutStart);
if (mode == MODE_OFF and thermalSet != nullptr) {
ReturnValue_t result = thermalSet->read();
if (result == returnvalue::OK) {
PoolReadGuard pg(thermalSet);
if (pg.getReadResult() == returnvalue::OK) {
if (thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) {
thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
}
thermalSet->heaterRequest.commit(PoolVariableIF::VALID);
thermalSet->heaterRequest.setValid(true);
}
}
/* TODO: This will probably be done by the LocalDataPoolManager now */
@ -1088,8 +1082,8 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode, Submode_
// Do not check thermal state for MODE_RAW
if ((mode == MODE_OFF) and ((commandedMode == MODE_ON) or (commandedMode == MODE_NORMAL)) and
(thermalSet != nullptr)) {
ReturnValue_t result = thermalSet->read();
if (result == returnvalue::OK) {
PoolReadGuard pg(thermalSet);
if (pg.getReadResult() == returnvalue::OK) {
if ((thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) and
(not ThermalComponentIF::isOperational(thermalSet->thermalState.value))) {
triggerEvent(ThermalComponentIF::TEMP_NOT_IN_OP_RANGE, thermalSet->thermalState.value);
@ -1150,11 +1144,10 @@ void DeviceHandlerBase::handleTransitionToOnMode(Mode_t commandedMode, Submode_t
childTransitionDelay = getTransitionDelayMs(_MODE_START_UP, MODE_ON);
triggerEvent(CHANGING_MODE, commandedMode, commandedSubmode);
if (thermalSet != nullptr) {
ReturnValue_t result = thermalSet->read();
if (result == returnvalue::OK) {
PoolReadGuard pg(thermalSet);
if (pg.getReadResult() == returnvalue::OK) {
if (thermalSet->heaterRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) {
thermalSet->heaterRequest = ThermalComponentIF::STATE_REQUEST_OPERATIONAL;
thermalSet->commit();
}
}
}
@ -1477,11 +1470,11 @@ void DeviceHandlerBase::performOperationHook() {}
ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) {
if (thermalSet != nullptr) {
localDataPoolMap.emplace(thermalSet->thermalStatePoolId,
new PoolEntry<DeviceHandlerIF::dh_thermal_state_t>);
localDataPoolMap.emplace(thermalSet->heaterRequestPoolId,
new PoolEntry<DeviceHandlerIF::dh_heater_request_t>);
if (thermalStateCfg.has_value()) {
localDataPoolMap.emplace(thermalStateCfg.value().thermalStatePoolId,
new PoolEntry<DeviceHandlerIF::dh_thermal_state_t>());
localDataPoolMap.emplace(thermalStateCfg.value().thermalRequestPoolId,
new PoolEntry<DeviceHandlerIF::dh_heater_request_t>());
}
return returnvalue::OK;
}
@ -1494,6 +1487,10 @@ ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() {
}
this->poolManager.initializeAfterTaskCreation();
if (thermalStateCfg.has_value()) {
ThermalStateCfg& cfg = thermalStateCfg.value();
thermalSet = new DeviceHandlerThermalSet(this, cfg);
}
if (setStartupImmediately) {
startTransition(MODE_ON, getInitialSubmode());
}

View File

@ -2,6 +2,7 @@
#define FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_
#include <map>
#include <optional>
#include "DeviceCommunicationIF.h"
#include "DeviceHandlerFailureIsolation.h"
@ -149,11 +150,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
//! has been commanded on and the handler waits for it to be on.
//! When the switch is on, the mode changes to @c _MODE_TO_ON.
static const Mode_t _MODE_WAIT_ON = TRANSITION_MODE_BASE_ACTION_MASK | 4;
//! This is a transitional state which can not be commanded. The switch has
//! been commanded off and is off now. This state is only to do an RMAP
//! cycle once more where the doSendRead() function will set the mode to
//! MODE_OFF. The reason to do this is to get rid of stuck packets in the IO Board.
static const Mode_t _MODE_SWITCH_IS_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 5;
void setHkDestination(object_id_t hkDestination);
@ -163,13 +159,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* The device handler will then take care of creating local pool entries
* for the device thermal state and device heating request.
* Custom local pool IDs can be assigned as well.
* @param thermalStatePoolId
* @param thermalRequestPoolId
*/
void setThermalStateRequestPoolIds(
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);
void enableThermalModule(ThermalStateCfg cfg);
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override;
ModeTreeChildIF &getModeTreeChildIF() override;
@ -266,8 +257,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
Mode_t getTransitionSourceMode() const;
Submode_t getTransitionSourceSubMode() const;
virtual void getMode(Mode_t *mode, Submode_t *submode);
HealthState getHealth();
ReturnValue_t setHealth(HealthState health);
virtual HealthState getHealth() override;
virtual ReturnValue_t setHealth(HealthState health) override;
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues,
@ -931,6 +922,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
//! Object which may be the root cause of an identified fault.
static object_id_t defaultFdirParentId;
std::optional<ThermalStateCfg> thermalStateCfg;
/**
* @brief Send a reply to a received device handler command.
*

View File

@ -10,8 +10,9 @@
object_id_t DeviceHandlerFailureIsolation::powerConfirmationId = objects::NO_OBJECT;
DeviceHandlerFailureIsolation::DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent)
: FailureIsolationBase(owner, parent),
DeviceHandlerFailureIsolation::DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent,
uint8_t eventQueueDepth)
: FailureIsolationBase(owner, parent, eventQueueDepth),
strangeReplyCount(DEFAULT_MAX_STRANGE_REPLIES, DEFAULT_STRANGE_REPLIES_TIME_MS,
parameterDomainBase++),
missedReplyCount(DEFAULT_MAX_MISSED_REPLY_COUNT, DEFAULT_MISSED_REPLY_TIME_MS,

View File

@ -13,7 +13,8 @@ class DeviceHandlerFailureIsolation : public FailureIsolationBase {
friend class Heater;
public:
DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent);
DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent,
uint8_t eventQueueDepth = 10);
~DeviceHandlerFailureIsolation();
ReturnValue_t initialize();
void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0);

View File

@ -136,4 +136,10 @@ class DeviceHandlerIF {
virtual MessageQueueId_t getCommandQueue() const = 0;
};
struct ThermalStateCfg {
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;
};
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ */

View File

@ -7,27 +7,21 @@
class DeviceHandlerThermalSet : public StaticLocalDataSet<2> {
public:
DeviceHandlerThermalSet(
HasLocalDataPoolIF* hkOwner, uint32_t setId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID,
lp_id_t thermalStateId = DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID,
lp_id_t heaterRequestId = DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID)
: DeviceHandlerThermalSet(hkOwner->getObjectId(), setId, thermalStateId, heaterRequestId) {}
DeviceHandlerThermalSet(HasLocalDataPoolIF* hkOwner, ThermalStateCfg cfg)
: DeviceHandlerThermalSet(hkOwner->getObjectId(), cfg) {}
DeviceHandlerThermalSet(
object_id_t deviceHandler, uint32_t setId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID,
lp_id_t thermalStateId = DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID,
lp_id_t thermalStateRequestId = DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID)
: StaticLocalDataSet(sid_t(deviceHandler, setId)),
thermalStatePoolId(thermalStateId),
heaterRequestPoolId(thermalStateRequestId) {}
DeviceHandlerThermalSet(object_id_t deviceHandler, ThermalStateCfg cfg)
: StaticLocalDataSet(sid_t(deviceHandler, cfg.thermalSetId)),
thermalStatePoolId(cfg.thermalStatePoolId),
heaterRequestPoolId(cfg.thermalRequestPoolId) {}
const lp_id_t thermalStatePoolId;
const lp_id_t heaterRequestPoolId;
lp_var_t<DeviceHandlerIF::dh_thermal_state_t> thermalState =
lp_var_t<DeviceHandlerIF::dh_thermal_state_t>(thermalStatePoolId, sid.objectId, this);
lp_var_t<DeviceHandlerIF::dh_thermal_state_t>(sid.objectId, thermalStatePoolId, this);
lp_var_t<DeviceHandlerIF::dh_heater_request_t> heaterRequest =
lp_var_t<DeviceHandlerIF::dh_heater_request_t>(heaterRequestPoolId, sid.objectId, this);
lp_var_t<DeviceHandlerIF::dh_heater_request_t>(sid.objectId, heaterRequestPoolId, this);
};
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERTHERMALSET_H_ */

View File

@ -29,11 +29,10 @@ ReturnValue_t HealthDevice::initialize() {
if (result != returnvalue::OK) {
return result;
}
if (parentQueue != 0) {
if (parentQueue != MessageQueueIF::NO_QUEUE) {
return healthHelper.initialize(parentQueue);
} else {
return healthHelper.initialize();
}
return healthHelper.initialize();
}
MessageQueueId_t HealthDevice::getCommandQueue() const { return commandQueue->getId(); }

View File

@ -29,10 +29,8 @@ class HealthDevice : public SystemObject, public ExecutableObjectIF, public HasH
protected:
HealthState lastHealth;
MessageQueueId_t parentQueue;
MessageQueueId_t parentQueue = MessageQueueIF::NO_QUEUE;
MessageQueueIF* commandQueue;
public:
HealthHelper healthHelper;
};

View File

@ -15,12 +15,12 @@ const LocalPool::LocalPoolConfig EventManager::poolConfig = {
{fsfwconfig::FSFW_EVENTMGMT_EVENTIDMATCHERS, sizeof(EventIdRangeMatcher)},
{fsfwconfig::FSFW_EVENTMGMR_RANGEMATCHERS, sizeof(ReporterRangeMatcher)}};
EventManager::EventManager(object_id_t setObjectId)
EventManager::EventManager(object_id_t setObjectId, uint32_t eventQueueDepth)
: SystemObject(setObjectId), factoryBackend(0, poolConfig, false, true) {
mutex = MutexFactory::instance()->createMutex();
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
eventReportQueue = QueueFactory::instance()->createMessageQueue(
MAX_EVENTS_PER_CYCLE, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
eventQueueDepth, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
}
EventManager::~EventManager() {
@ -55,8 +55,9 @@ void EventManager::notifyListeners(EventMessage* message) {
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << std::hex << "EventManager::notifyListeners: MSG to 0x" << std::setfill('0')
<< std::setw(8) << listener.first << " failed with result 0x" << std::setw(4)
<< result << std::setfill(' ') << std::endl;
<< std::setw(8) << listener.first << " for event 0x" << std::setw(4)
<< message->getEventId() << " failed with result 0x" << std::setw(4) << result
<< std::setfill(' ') << std::endl;
#else
sif::printError("Sending message to listener 0x%08x failed with result %04x\n",
listener.first, result);

View File

@ -21,9 +21,9 @@ extern const char* translateEvents(Event event);
class EventManager : public EventManagerIF, public ExecutableObjectIF, public SystemObject {
public:
static const uint16_t MAX_EVENTS_PER_CYCLE = 80;
static const uint16_t DEFAULT_MAX_EVENTS_PER_CYCLE = 80;
EventManager(object_id_t setObjectId);
EventManager(object_id_t setObjectId, uint32_t eventQueueDepth);
virtual ~EventManager();
void setMutexTimeout(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs);

View File

@ -10,7 +10,7 @@ enum : uint8_t {
CDH = 28,
TCS_1 = 59,
PCDU_1 = 42,
PCDU_2 = 43,
POWER_SWITCH_IF = 43,
HEATER = 50,
T_SENSORS = 52,
FDIR = 70,

View File

@ -68,7 +68,7 @@ ReturnValue_t FaultCounter::getParameter(uint8_t domainId, uint8_t uniqueId,
parameterWrapper->set(faultCount);
break;
case ParameterIds::TIMEOUT:
parameterWrapper->set(timer.timeout);
parameterWrapper->set(timer.getTimeoutMs());
break;
default:
return INVALID_IDENTIFIER_ID;

View File

@ -74,6 +74,12 @@ class HasFileSystemIF {
return MessageQueueIF::NO_QUEUE;
}
// Get the base filename without the full directory path
virtual ReturnValue_t getBaseFilename(FilesystemParams params, char* nameBuf, size_t maxLen,
size_t& baseNameLen) = 0;
virtual bool isDirectory(const char* path) = 0;
virtual bool fileExists(FilesystemParams params) = 0;
/**

View File

@ -18,8 +18,11 @@
*/
class DleParser {
public:
//! [EXPORT] : [SKIP]
static constexpr ReturnValue_t NO_PACKET_FOUND = returnvalue::makeCode(1, 1);
//! [EXPORT] : [SKIP]
static constexpr ReturnValue_t POSSIBLE_PACKET_LOSS = returnvalue::makeCode(1, 2);
using BufPair = std::pair<uint8_t*, size_t>;
enum class ContextType { NONE, PACKET_FOUND, ERROR };

View File

@ -53,8 +53,9 @@ class VectorOperations {
mulScalar(vector, 1 / norm(vector, size), normalizedVector, size);
}
static T maxAbsValue(const T *vector, uint8_t size, uint8_t *index = 0) {
T max = -1;
static T maxAbsValue(const T *vector, uint8_t size, uint8_t *index = nullptr) {
T max = vector[size - 1];
uint8_t foundIndex = size - 1;
for (; size > 0; size--) {
T abs = vector[size - 1];
@ -64,24 +65,35 @@ class VectorOperations {
if (abs > max) {
max = abs;
if (index != 0) {
*index = size - 1;
foundIndex = size - 1;
}
}
}
if (index != nullptr) {
*index = foundIndex;
}
return max;
}
static T maxValue(const T *vector, uint8_t size, uint8_t *index = 0) {
T max = -1;
static T maxValue(const T *vector, uint8_t size, uint8_t *index = nullptr) {
T max = vector[size - 1];
uint8_t foundIndex = size - 1;
for (; size > 0; size--) {
if (vector[size - 1] > max) {
max = vector[size - 1];
if (index != 0) {
*index = size - 1;
foundIndex = size - 1;
}
}
}
if (index != nullptr) {
*index = foundIndex;
}
return max;
}

View File

@ -3,85 +3,37 @@
#include <cmath>
#include "fsfw/datapoollocal/LocalPoolDataSetBase.h"
#include "fsfw/serviceinterface.h"
PeriodicHousekeepingHelper::PeriodicHousekeepingHelper(LocalPoolDataSetBase* owner)
: owner(owner) {}
void PeriodicHousekeepingHelper::initialize(float collectionInterval,
dur_millis_t minimumPeriodicInterval,
uint8_t nonDiagIntervalFactor) {
dur_millis_t minimumPeriodicInterval) {
this->minimumPeriodicInterval = minimumPeriodicInterval;
this->nonDiagIntervalFactor = nonDiagIntervalFactor;
collectionIntervalTicks = intervalSecondsToIntervalTicks(collectionInterval);
/* This will cause a checkOpNecessary call to be true immediately. I think it's okay
if a HK packet is generated immediately instead of waiting one generation cycle. */
internalTickCounter = collectionIntervalTicks;
changeCollectionInterval(collectionInterval);
}
float PeriodicHousekeepingHelper::getCollectionIntervalInSeconds() const {
return intervalTicksToSeconds(collectionIntervalTicks);
return collectionInterval;
}
bool PeriodicHousekeepingHelper::checkOpNecessary() {
if (internalTickCounter >= collectionIntervalTicks) {
internalTickCounter = 1;
if (hkGenerationCd.hasTimedOut()) {
hkGenerationCd.resetTimer();
return true;
}
internalTickCounter++;
return false;
}
uint32_t PeriodicHousekeepingHelper::intervalSecondsToIntervalTicks(
float collectionIntervalSeconds) {
if (owner == nullptr) {
return 0;
}
bool isDiagnostics = owner->isDiagnostics();
/* Avoid division by zero */
if (minimumPeriodicInterval == 0) {
if (isDiagnostics) {
/* Perform operation each cycle */
return 1;
} else {
return nonDiagIntervalFactor;
}
} else {
dur_millis_t intervalInMs = collectionIntervalSeconds * 1000;
uint32_t divisor = minimumPeriodicInterval;
if (not isDiagnostics) {
/* We need to multiply the divisor because non-diagnostics only
allow a multiple of the minimum periodic interval */
divisor *= nonDiagIntervalFactor;
}
uint32_t ticks = std::ceil(static_cast<float>(intervalInMs) / divisor);
if (not isDiagnostics) {
/* Now we need to multiply the calculated ticks with the factor as as well
because the minimum tick count to generate a non-diagnostic is the factor itself.
Example calculation for non-diagnostic with
0.4 second interval and 0.2 second task interval.
Resultant tick count of 5 is equal to operation each second.
Examle calculation for non-diagnostic with 2.0 second interval and 0.2 second
task interval.
Resultant tick count of 10 is equal to operatin every 2 seconds.
Example calculation for diagnostic with 0.4 second interval and 0.3
second task interval. Resulting tick count of 2 is equal to operation
every 0.6 seconds. */
ticks *= nonDiagIntervalFactor;
}
return ticks;
}
}
float PeriodicHousekeepingHelper::intervalTicksToSeconds(uint32_t collectionInterval) const {
/* Number of ticks times the minimum interval is in milliseconds, so we divide by 1000 to get
the value in seconds */
return static_cast<float>(collectionInterval * minimumPeriodicInterval / 1000.0);
}
void PeriodicHousekeepingHelper::changeCollectionInterval(float newIntervalSeconds) {
collectionIntervalTicks = intervalSecondsToIntervalTicks(newIntervalSeconds);
uint32_t intervalMs = newIntervalSeconds * 1000;
if (newIntervalSeconds <= 0) {
intervalMs = minimumPeriodicInterval;
newIntervalSeconds = static_cast<float>(minimumPeriodicInterval) / 1000.0;
}
collectionInterval = newIntervalSeconds;
hkGenerationCd.setTimeout(intervalMs);
// We want an immediate HK packet at the start, so time out the generation CD immediately.
hkGenerationCd.timeOut();
}

View File

@ -4,6 +4,7 @@
#include <cstdint>
#include "fsfw/timemanager/Clock.h"
#include "fsfw/timemanager/Countdown.h"
class LocalPoolDataSetBase;
@ -11,8 +12,7 @@ class PeriodicHousekeepingHelper {
public:
PeriodicHousekeepingHelper(LocalPoolDataSetBase* owner);
void initialize(float collectionInterval, dur_millis_t minimumPeriodicInterval,
uint8_t nonDiagIntervalFactor);
void initialize(float collectionInterval, dur_millis_t minimumPeriodicInterval);
void changeCollectionInterval(float newInterval);
float getCollectionIntervalInSeconds() const;
@ -20,14 +20,10 @@ class PeriodicHousekeepingHelper {
private:
LocalPoolDataSetBase* owner = nullptr;
uint8_t nonDiagIntervalFactor = 0;
uint32_t intervalSecondsToIntervalTicks(float collectionIntervalSeconds);
float intervalTicksToSeconds(uint32_t collectionInterval) const;
Countdown hkGenerationCd;
float collectionInterval = 0.0;
dur_millis_t minimumPeriodicInterval = 0;
uint32_t internalTickCounter = 1;
uint32_t collectionIntervalTicks = 0;
};
#endif /* FSFW_HOUSEKEEPING_PERIODICHOUSEKEEPINGHELPER_H_ */

View File

@ -5,9 +5,12 @@
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth)
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth,
bool enableSetByDefault, float generationFrequency)
: SystemObject(setObjectId),
poolManager(this, commandQueue),
enableSetByDefault(enableSetByDefault),
generationFrequency(generationFrequency),
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
internalErrorDataset(this) {
commandQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
@ -134,9 +137,8 @@ ReturnValue_t InternalErrorReporter::initializeLocalDataPool(localpool::DataPool
localDataPoolMap.emplace(errorPoolIds::TM_HITS, &tmHitsEntry);
localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS, &queueHitsEntry);
localDataPoolMap.emplace(errorPoolIds::STORE_HITS, &storeHitsEntry);
poolManager.subscribeForDiagPeriodicPacket(subdp::DiagnosticsHkPeriodicParams(
internalErrorSid, false,
static_cast<float>(getPeriodicOperationFrequency()) / static_cast<float>(1000.0)));
poolManager.subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams(internalErrorSid, enableSetByDefault, generationFrequency));
internalErrorDataset.setValidity(true, true);
return returnvalue::OK;
}

View File

@ -21,7 +21,8 @@ class InternalErrorReporter : public SystemObject,
public InternalErrorReporterIF,
public HasLocalDataPoolIF {
public:
InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth = 5);
InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth,
bool enableSetByDefault, float generationFrequency);
/**
* Enable diagnostic printout. Please note that this feature will
@ -63,6 +64,8 @@ class InternalErrorReporter : public SystemObject,
MutexIF* mutex = nullptr;
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
uint32_t timeoutMs = 20;
bool enableSetByDefault;
float generationFrequency;
sid_t internalErrorSid;
InternalErrorDataset internalErrorDataset;

View File

@ -7,14 +7,17 @@
class MutexGuard {
public:
MutexGuard(MutexIF* mutex, MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::BLOCKING,
uint32_t timeoutMs = 0)
uint32_t timeoutMs = 0, const char* context = nullptr)
: internalMutex(mutex) {
if (context == nullptr) {
context = "unknown";
}
if (mutex == nullptr) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MutexGuard: Passed mutex is invalid!" << std::endl;
sif::error << "MutexGuard::" << context << ": Passed mutex is invalid!" << std::endl;
#else
sif::printError("MutexGuard: Passed mutex is invalid!\n");
sif::printError("MutexGuard::%s: Passed mutex is invalid!\n", context);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
return;
@ -23,11 +26,11 @@ class MutexGuard {
#if FSFW_VERBOSE_LEVEL >= 1
if (result == MutexIF::MUTEX_TIMEOUT) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MutexGuard: Lock of mutex failed with timeout of " << timeoutMs
<< " milliseconds!" << std::endl;
sif::error << "MutexGuard::" << context << ": Lock of mutex failed with timeout of "
<< timeoutMs << " milliseconds!" << std::endl;
#else
sif::printError("MutexGuard: Lock of mutex failed with timeout of %lu milliseconds\n",
timeoutMs);
sif::printError("MutexGuard::%s: Lock of mutex failed with timeout of %lu milliseconds\n",
context, timeoutMs);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
} else if (result != returnvalue::OK) {

View File

@ -15,6 +15,7 @@ enum framework_objects : object_id_t {
PUS_SERVICE_8_FUNCTION_MGMT = 0x53000008,
PUS_SERVICE_9_TIME_MGMT = 0x53000009,
PUS_SERVICE_11_TC_SCHEDULER = 0x53000011,
PUS_SERVICE_15_TM_STORAGE = 0x53000015,
PUS_SERVICE_17_TEST = 0x53000017,
PUS_SERVICE_20_PARAMETERS = 0x53000020,
PUS_SERVICE_200_MODE_MGMT = 0x53000200,

View File

@ -41,6 +41,7 @@ int TcpIpBase::closeSocket(socket_t socket) {
#elif defined(PLATFORM_UNIX)
return close(socket);
#endif
return -1;
}
int TcpIpBase::getLastSocketError() {
@ -49,4 +50,5 @@ int TcpIpBase::getLastSocketError() {
#elif defined(PLATFORM_UNIX)
return errno;
#endif
return 0;
}

View File

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

View File

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

View File

@ -20,9 +20,9 @@
const std::string UdpTmTcBridge::DEFAULT_SERVER_PORT = tcpip::DEFAULT_SERVER_PORT;
UdpTmTcBridge::UdpTmTcBridge(object_id_t objectId, object_id_t tcDestination,
const std::string &udpServerPort_, object_id_t tmStoreId,
object_id_t tcStoreId)
: TmTcBridge("UDP TMTC Bridge", objectId, tcDestination, tmStoreId, tcStoreId) {
uint32_t msgQueueDepth, const std::string &udpServerPort_,
object_id_t tmStoreId, object_id_t tcStoreId)
: TmTcBridge("UDP TMTC Bridge", objectId, tcDestination, msgQueueDepth, tmStoreId, tcStoreId) {
if (udpServerPort_.empty()) {
udpServerPort = DEFAULT_SERVER_PORT;
} else {
@ -126,10 +126,7 @@ ReturnValue_t UdpTmTcBridge::sendTm(const uint8_t *data, size_t dataLen) {
tcpip::handleError(tcpip::Protocol::UDP, tcpip::ErrorSources::SENDTO_CALL);
}
#if FSFW_CPP_OSTREAM_ENABLED == 1 && FSFW_UDP_SEND_WIRETAPPING_ENABLED == 1
sif::debug << "TmTcUdpBridge::sendTm: " << bytesSent
<< " bytes were"
" sent."
<< std::endl;
sif::debug << "TmTcUdpBridge::sendTm: " << bytesSent << " bytes were sent" << std::endl;
#endif
return returnvalue::OK;
}

View File

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

View File

@ -47,7 +47,32 @@ ReturnValue_t Clock::setClock(const timeval* time) {
return returnvalue::OK;
}
ReturnValue_t Clock::getClock_timeval(timeval* time) {
ReturnValue_t Clock::getClockMonotonic(timeval* time) {
#if defined(PLATFORM_WIN)
// TODO: Implement with std::chrono::steady_clock.. or in some other way. I am not even sure
// whether this is possible with steady_clock. The conversion we have to do here just to be
// generic is kind of awkward..
return returnvalue::FAILED;
#elif defined(PLATFORM_UNIX)
timespec timeMonotonic;
int status = clock_gettime(CLOCK_MONOTONIC_RAW, &timeMonotonic);
if (status != 0) {
return returnvalue::FAILED;
}
time->tv_sec = timeMonotonic.tv_sec;
time->tv_usec = timeMonotonic.tv_nsec / 1000.0;
return returnvalue::OK;
#else
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Clock::getUptime: Not implemented for found OS!" << std::endl;
#else
sif::printWarning("Clock::getUptime: Not implemented for found OS!\n");
#endif
return returnvalue::FAILED;
#endif
}
ReturnValue_t Clock::getClock(timeval* time) {
#if defined(PLATFORM_WIN)
auto now = std::chrono::system_clock::now();
auto secondsChrono = std::chrono::time_point_cast<std::chrono::seconds>(now);
@ -75,6 +100,8 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
#endif
}
ReturnValue_t Clock::getClock_timeval(timeval* time) { return Clock::getClock(time); }
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
if (time == nullptr) {
return returnvalue::FAILED;

View File

@ -20,16 +20,18 @@ TaskFactory::~TaskFactory() = default;
TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; }
PeriodicTaskIF* TaskFactory::createPeriodicTask(
TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_,
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) {
PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_, TaskPriority taskPriority_,
TaskStackSize stackSize_,
TaskPeriod periodInSeconds_,
TaskDeadlineMissedFunction deadLineMissedFunction_,
void* args) {
return new PeriodicTask(name_, taskPriority_, stackSize_, periodInSeconds_,
deadLineMissedFunction_);
}
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(
TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_,
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) {
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_, void* args) {
return new FixedTimeslotTask(name_, taskPriority_, stackSize_, periodInSeconds_,
deadLineMissedFunction_);
}

View File

@ -42,7 +42,7 @@ ReturnValue_t Clock::setClock(const timeval* time) {
return returnvalue::OK;
}
ReturnValue_t Clock::getClock_timeval(timeval* time) {
ReturnValue_t Clock::getClock(timeval* time) {
timespec timeUnix{};
int status = clock_gettime(CLOCK_REALTIME, &timeUnix);
if (status != 0) {
@ -53,6 +53,8 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
return returnvalue::OK;
}
ReturnValue_t Clock::getClock_timeval(timeval* time) { return Clock::getClock(time); }
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
timeval timeVal{};
ReturnValue_t result = getClock_timeval(&timeVal);
@ -64,6 +66,17 @@ ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
return returnvalue::OK;
}
ReturnValue_t Clock::getClockMonotonic(timeval* time) {
timespec timeMonotonic{};
int status = clock_gettime(CLOCK_MONOTONIC_RAW, &timeMonotonic);
if (status != 0) {
return returnvalue::FAILED;
}
time->tv_sec = timeMonotonic.tv_sec;
time->tv_usec = timeMonotonic.tv_nsec / 1000.0;
return returnvalue::OK;
}
timeval Clock::getUptime() {
timeval uptime{};
auto result = getUptime(&uptime);
@ -76,14 +89,17 @@ timeval Clock::getUptime() {
}
ReturnValue_t Clock::getUptime(timeval* uptime) {
// TODO This is not posix compatible and delivers only seconds precision
// Linux specific file read but more precise.
double uptimeSeconds;
if (std::ifstream("/proc/uptime", std::ios::in) >> uptimeSeconds) {
std::ifstream ifile("/proc/uptime");
if (ifile.bad()) {
return returnvalue::FAILED;
}
if (ifile >> uptimeSeconds) {
uptime->tv_sec = uptimeSeconds;
uptime->tv_usec = uptimeSeconds * (double)1e6 - (uptime->tv_sec * 1e6);
return returnvalue::OK;
}
return returnvalue::OK;
return returnvalue::FAILED;
}
// Wait for new FSFW Clock function delivering seconds uptime.

View File

@ -7,10 +7,15 @@
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = PTHREAD_STACK_MIN;
FixedTimeslotTask::FixedTimeslotTask(const char* name_, TaskPriority priority_, size_t stackSize_,
TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_)
TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_,
PosixThreadArgs* args)
: FixedTimeslotTaskBase(periodSeconds_, dlmFunc_),
posixThread(name_, priority_, stackSize_),
started(false) {}
posixThread(name_, SchedulingPolicy::REGULAR, priority_, stackSize_),
started(false) {
if (args != nullptr) {
posixThread.setSchedPolicy(args->policy);
}
}
void* FixedTimeslotTask::taskEntryPoint(void* arg) {
// The argument is re-interpreted as PollingTask.

View File

@ -23,7 +23,8 @@ class FixedTimeslotTask : public FixedTimeslotTaskBase {
* @param deadlineMissedFunc_
*/
FixedTimeslotTask(const char* name_, TaskPriority priority_, size_t stackSize_,
TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_);
TaskPeriod periodSeconds_, TaskDeadlineMissedFunction dlmFunc_,
PosixThreadArgs* args);
~FixedTimeslotTask() override = default;
ReturnValue_t startTask() override;

View File

@ -4,10 +4,15 @@
#include "fsfw/tasks/ExecutableObjectIF.h"
PeriodicPosixTask::PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_,
TaskPeriod period_, TaskDeadlineMissedFunction dlmFunc_)
TaskPeriod period_, TaskDeadlineMissedFunction dlmFunc_,
PosixThreadArgs* args)
: PeriodicTaskBase(period_, dlmFunc_),
posixThread(name_, priority_, stackSize_),
started(false) {}
posixThread(name_, SchedulingPolicy::REGULAR, priority_, stackSize_),
started(false) {
if (args != nullptr) {
posixThread.setSchedPolicy(args->policy);
}
}
void* PeriodicPosixTask::taskEntryPoint(void* arg) {
// The argument is re-interpreted as PollingTask.

View File

@ -24,7 +24,7 @@ class PeriodicPosixTask : public PeriodicTaskBase {
* @param deadlineMissedFunc_
*/
PeriodicPosixTask(const char* name_, int priority_, size_t stackSize_, TaskPeriod period_,
TaskDeadlineMissedFunction dlmFunc_);
TaskDeadlineMissedFunction dlmFunc_, PosixThreadArgs* args);
~PeriodicPosixTask() override = default;
/**

View File

@ -7,8 +7,9 @@
#include "fsfw/osal/linux/unixUtility.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
PosixThread::PosixThread(const char* name_, int priority_, size_t stackSize_)
: thread(0), priority(priority_), stackSize(stackSize_) {
PosixThread::PosixThread(const char* name_, SchedulingPolicy schedPolciy, int priority_,
size_t stackSize_)
: thread(0), schedPolicy(schedPolciy), priority(priority_), stackSize(stackSize_) {
name[0] = '\0';
std::strncat(name, name_, PTHREAD_MAX_NAMELEN - 1);
}
@ -178,20 +179,30 @@ void PosixThread::createTask(void* (*fnc_)(void*), void* arg_) {
#ifndef FSFW_USE_REALTIME_FOR_LINUX
#error "Please define FSFW_USE_REALTIME_FOR_LINUX with either 0 or 1"
#endif
if (schedPolicy == SchedulingPolicy::RR) {
// RR -> This needs root privileges for the process
#if FSFW_USE_REALTIME_FOR_LINUX == 1
// FIFO -> This needs root privileges for the process
status = pthread_attr_setschedpolicy(&attributes, SCHED_FIFO);
if (status != 0) {
utility::printUnixErrorGeneric(CLASS_NAME, "createTask", "pthread_attr_setschedpolicy");
status = pthread_attr_setschedpolicy(&attributes, SCHED_RR);
if (status != 0) {
utility::printUnixErrorGeneric(CLASS_NAME, "createTask", "pthread_attr_setschedpolicy");
}
sched_param scheduleParams;
scheduleParams.sched_priority = priority;
status = pthread_attr_setschedparam(&attributes, &scheduleParams);
if (status != 0) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "PosixThread: Setting priority failed" << std::endl;
#endif
}
#else
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning
<< "Real time priorities are only allowed if FSFW_USE_REALTIME_FOR_LINUX is set to 1"
<< std::endl;
#endif
#endif
}
sched_param scheduleParams;
scheduleParams.__sched_priority = priority;
status = pthread_attr_setschedparam(&attributes, &scheduleParams);
if (status != 0) {
utility::printUnixErrorGeneric(CLASS_NAME, "createTask", "pthread_attr_setschedparam");
}
#endif
// Set Signal Mask for suspend until startTask is called
sigset_t waitSignal;
sigemptyset(&waitSignal);
@ -243,3 +254,5 @@ void PosixThread::createTask(void* (*fnc_)(void*), void* arg_) {
utility::printUnixErrorGeneric(CLASS_NAME, "createTask", "pthread_attr_destroy");
}
}
void PosixThread::setSchedPolicy(SchedulingPolicy policy) { this->schedPolicy = policy; }

View File

@ -9,10 +9,15 @@
#include "../../returnvalues/returnvalue.h"
enum SchedulingPolicy { REGULAR, RR };
struct PosixThreadArgs {
SchedulingPolicy policy = SchedulingPolicy::REGULAR;
};
class PosixThread {
public:
static constexpr uint8_t PTHREAD_MAX_NAMELEN = 16;
PosixThread(const char* name_, int priority_, size_t stackSize_);
PosixThread(const char* name_, SchedulingPolicy schedPolicy, int priority_, size_t stackSize_);
virtual ~PosixThread();
/**
* Set the Thread to sleep state
@ -20,6 +25,9 @@ class PosixThread {
* @return Returns Failed if sleep fails
*/
static ReturnValue_t sleep(uint64_t ns);
void setSchedPolicy(SchedulingPolicy policy);
/**
* @brief Function to suspend the task until SIGUSR1 was received
*
@ -72,6 +80,7 @@ class PosixThread {
private:
char name[PTHREAD_MAX_NAMELEN];
SchedulingPolicy schedPolicy;
int priority;
size_t stackSize = 0;

View File

@ -12,18 +12,20 @@ TaskFactory::~TaskFactory() = default;
TaskFactory* TaskFactory::instance() { return TaskFactory::factoryInstance; }
PeriodicTaskIF* TaskFactory::createPeriodicTask(
TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_,
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) {
PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_, TaskPriority taskPriority_,
TaskStackSize stackSize_,
TaskPeriod periodInSeconds_,
TaskDeadlineMissedFunction deadLineMissedFunction_,
void* args) {
return new PeriodicPosixTask(name_, taskPriority_, stackSize_, periodInSeconds_,
deadLineMissedFunction_);
deadLineMissedFunction_, reinterpret_cast<PosixThreadArgs*>(args));
}
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(
TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_,
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_) {
TaskPeriod periodInSeconds_, TaskDeadlineMissedFunction deadLineMissedFunction_, void* args) {
return new FixedTimeslotTask(name_, taskPriority_, stackSize_, periodInSeconds_,
deadLineMissedFunction_);
deadLineMissedFunction_, reinterpret_cast<PosixThreadArgs*>(args));
}
ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) {

View File

@ -1,5 +1,5 @@
#include "fsfw/osal/rtems/BinarySemaphore.h"
//#include "fsfw/osal/rtems/CountingSemaphore.h"
// #include "fsfw/osal/rtems/CountingSemaphore.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw/tasks/SemaphoreFactory.h"

View File

@ -6,7 +6,11 @@ DummyPowerSwitcher::DummyPowerSwitcher(object_id_t objectId, size_t numberOfSwit
: SystemObject(objectId, registerGlobally),
switcherList(numberOfSwitches),
fuseList(numberOfFuses),
switchDelayMs(switchDelayMs) {}
switchDelayMs(switchDelayMs) {
for (auto &switchState : switcherList) {
switchState = PowerSwitchIF::SWITCH_UNKNOWN;
}
}
void DummyPowerSwitcher::setInitialSwitcherList(std::vector<ReturnValue_t> switcherList) {
this->switcherList = switcherList;

View File

@ -32,7 +32,7 @@ class Fuse : public SystemObject,
gp_id_t poolIdPower;
};
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_1;
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::POWER_SWITCH_IF;
//! PSS detected that current on a fuse is totally out of bounds.
static const Event FUSE_CURRENT_HIGH = MAKE_EVENT(1, severity::LOW);
//! PSS detected a fuse that went off.

View File

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

View File

@ -2,6 +2,7 @@
#include <fsfw/ipc/QueueFactory.h>
#include <fsfw/power/PowerSwitchIF.h>
#include <fsfw/subsystem/helper.h>
PowerSwitcherComponent::PowerSwitcherComponent(object_id_t objectId, PowerSwitchIF* pwrSwitcher,
power::Switch_t pwrSwitch)
@ -28,6 +29,9 @@ ReturnValue_t PowerSwitcherComponent::performOperation(uint8_t opCode) {
continue;
}
}
if (getHealth() == FAULTY) {
performFaultyOperation();
}
if (switcher.active()) {
switcher.doStateMachine();
auto currState = switcher.getState();
@ -111,9 +115,11 @@ const HasHealthIF* PowerSwitcherComponent::getOptHealthIF() const { return this;
const HasModesIF& PowerSwitcherComponent::getModeIF() const { return *this; }
ReturnValue_t PowerSwitcherComponent::connectModeTreeParent(HasModeTreeChildrenIF& parent) {
return parent.registerChild(*this);
return modetree::connectModeTreeParent(parent, *this, &healthHelper, modeHelper);
}
object_id_t PowerSwitcherComponent::getObjectId() const { return SystemObject::getObjectId(); }
ModeTreeChildIF& PowerSwitcherComponent::getModeTreeChildIF() { return *this; }
void PowerSwitcherComponent::performFaultyOperation() {}

View File

@ -1,5 +1,4 @@
#ifndef _FSFW_POWER_POWERSWITCHERCOMPONENT_H_
#define _FSFW_POWER_POWERSWITCHERCOMPONENT_H_
#pragma once
#include <fsfw/health/HasHealthIF.h>
#include <fsfw/health/HealthHelper.h>
@ -37,11 +36,13 @@ class PowerSwitcherComponent : public SystemObject,
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF &parent) override;
ModeTreeChildIF &getModeTreeChildIF() override;
private:
MessageQueueIF *queue = nullptr;
protected:
PowerSwitcher switcher;
Mode_t mode = MODE_OFF;
private:
MessageQueueIF *queue = nullptr;
Mode_t mode = MODE_UNDEFINED;
Submode_t submode = 0;
ModeHelper modeHelper;
@ -49,24 +50,23 @@ class PowerSwitcherComponent : public SystemObject,
void setMode(Mode_t newMode, Submode_t newSubmode);
virtual ReturnValue_t performOperation(uint8_t opCode) override;
ReturnValue_t performOperation(uint8_t opCode) override;
ReturnValue_t initialize() override;
MessageQueueId_t getCommandQueue() const override;
[[nodiscard]] MessageQueueId_t getCommandQueue() const override;
void getMode(Mode_t *mode, Submode_t *submode) override;
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) override;
void startTransition(Mode_t mode, Submode_t submode) override;
virtual void performFaultyOperation();
void setToExternalControl() override;
void announceMode(bool recursive) override;
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;
[[nodiscard]] object_id_t getObjectId() const override;
[[nodiscard]] const HasHealthIF *getOptHealthIF() const override;
[[nodiscard]] const HasModesIF &getModeIF() const override;
};
#endif /* _FSFW_POWER_POWERSWITCHERCOMPONENT_H_ */

View File

@ -19,7 +19,7 @@ ReturnValue_t CService200ModeCommanding::isValidSubservice(uint8_t subservice) {
switch (subservice) {
case (Subservice::COMMAND_MODE_COMMAND):
case (Subservice::COMMAND_MODE_READ):
case (Subservice::COMMAND_MODE_ANNCOUNCE):
case (Subservice::COMMAND_MODE_ANNOUNCE):
case (Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY):
return returnvalue::OK;
default:
@ -54,6 +54,7 @@ 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) {
bool recursive = false;
switch (subservice) {
case (Subservice::COMMAND_MODE_COMMAND): {
ModePacket modeCommandPacket;
@ -67,22 +68,17 @@ ReturnValue_t CService200ModeCommanding::prepareCommand(CommandMessage *message,
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;
}
case (Subservice::COMMAND_MODE_ANNOUNCE_RECURSIVELY):
recursive = true;
[[fallthrough]];
case (Subservice::COMMAND_MODE_ANNOUNCE):
ModeMessage::setModeAnnounceMessage(*message, recursive);
return EXECUTION_COMPLETE;
}
case (Subservice::COMMAND_MODE_READ): {
case (Subservice::COMMAND_MODE_READ):
ModeMessage::setModeReadMessage(*message);
return returnvalue::OK;
}
default: {
default:
return CommandingServiceBase::INVALID_SUBSERVICE;
}
}
}

View File

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

View File

@ -10,9 +10,23 @@
CServiceHealthCommanding::CServiceHealthCommanding(HealthServiceCfg args)
: CommandingServiceBase(args.objectId, args.apid, "PUS 201 Health MGMT", args.service,
args.numParallelCommands, args.commandTimeoutSeconds),
healthTable(args.table),
healthTableId(args.table),
maxNumHealthInfoPerCycle(args.maxNumHealthInfoPerCycle) {}
ReturnValue_t CServiceHealthCommanding::initialize() {
ReturnValue_t result = CommandingServiceBase::initialize();
if (result != returnvalue::OK) {
return result;
}
healthTable = ObjectManager::instance()->get<HealthTable>(healthTableId);
if (healthTable == nullptr) {
return returnvalue::FAILED;
}
return returnvalue::OK;
}
ReturnValue_t CServiceHealthCommanding::isValidSubservice(uint8_t subservice) {
switch (subservice) {
case (Subservice::COMMAND_SET_HEALTH):
@ -68,6 +82,9 @@ ReturnValue_t CServiceHealthCommanding::prepareCommand(CommandMessage *message,
ReturnValue_t result = returnvalue::OK;
switch (subservice) {
case (Subservice::COMMAND_SET_HEALTH): {
if (tcDataLen != sizeof(object_id_t) + sizeof(HasHealthIF::HealthState)) {
return CommandingServiceBase::INVALID_TC;
}
HealthSetCommand healthCommand;
result = healthCommand.deSerialize(&tcData, &tcDataLen, SerializeIF::Endianness::BIG);
if (result != returnvalue::OK) {
@ -79,7 +96,7 @@ ReturnValue_t CServiceHealthCommanding::prepareCommand(CommandMessage *message,
}
case (Subservice::COMMAND_ANNOUNCE_HEALTH): {
HealthMessage::setHealthMessage(message, HealthMessage::HEALTH_ANNOUNCE);
break;
return CommandingServiceBase::EXECUTION_COMPLETE;
}
case (Subservice::COMMAND_ANNOUNCE_HEALTH_ALL): {
ReturnValue_t result = iterateHealthTable(true);
@ -88,14 +105,6 @@ ReturnValue_t CServiceHealthCommanding::prepareCommand(CommandMessage *message,
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
@ -142,7 +151,7 @@ void CServiceHealthCommanding::doPeriodicOperation() {
ReturnValue_t CServiceHealthCommanding::iterateHealthTable(bool reset) {
std::pair<object_id_t, HasHealthIF::HealthState> pair;
ReturnValue_t result = healthTable.iterate(&pair, reset);
ReturnValue_t result = healthTable->iterate(&pair, reset);
if (result != returnvalue::OK) {
return result;
} else {

View File

@ -6,7 +6,7 @@
#include "fsfw/tmtcservices/CommandingServiceBase.h"
struct HealthServiceCfg {
HealthServiceCfg(object_id_t objectId, uint16_t apid, HealthTable &healthTable,
HealthServiceCfg(object_id_t objectId, uint16_t apid, object_id_t healthTable,
uint16_t maxNumHealthInfoPerCycle)
: objectId(objectId),
apid(apid),
@ -14,7 +14,7 @@ struct HealthServiceCfg {
maxNumHealthInfoPerCycle(maxNumHealthInfoPerCycle) {}
object_id_t objectId;
uint16_t apid;
HealthTable &table;
object_id_t table;
uint16_t maxNumHealthInfoPerCycle;
uint8_t service = 201;
uint8_t numParallelCommands = 4;
@ -40,6 +40,8 @@ class CServiceHealthCommanding : public CommandingServiceBase {
CServiceHealthCommanding(HealthServiceCfg args);
~CServiceHealthCommanding() override = default;
ReturnValue_t initialize() override;
protected:
/* CSB abstract function implementations */
ReturnValue_t isValidSubservice(uint8_t subservice) override;
@ -57,7 +59,8 @@ class CServiceHealthCommanding : public CommandingServiceBase {
void doPeriodicOperation() override;
private:
HealthTable &healthTable;
const object_id_t healthTableId;
HealthTable *healthTable;
uint16_t maxNumHealthInfoPerCycle = 0;
bool reportAllHealth = false;
ReturnValue_t iterateHealthTable(bool reset);

View File

@ -160,7 +160,7 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::doInsertActivi
// (See requirement for Time margin)
timeval tNow = {};
Clock::getClock_timeval(&tNow);
if (timestamp - tNow.tv_sec <= RELEASE_TIME_MARGIN_SECONDS) {
if (timestamp < static_cast<uint32_t>(tNow.tv_sec + RELEASE_TIME_MARGIN_SECONDS)) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "Service11TelecommandScheduling::doInsertActivity: Release time too close to "
"current time"

View File

@ -4,9 +4,10 @@
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/pus/servicepackets/Service3Packets.h"
Service3Housekeeping::Service3Housekeeping(object_id_t objectId, uint16_t apid, uint8_t serviceId)
: CommandingServiceBase(objectId, apid, "PUS 3 HK", serviceId, NUM_OF_PARALLEL_COMMANDS,
COMMAND_TIMEOUT_SECONDS) {}
Service3Housekeeping::Service3Housekeeping(object_id_t objectId, uint16_t apid, uint8_t serviceId,
uint32_t queueDepth, uint8_t numParallelCommands)
: CommandingServiceBase(objectId, apid, "PUS 3 HK", serviceId, numParallelCommands,
COMMAND_TIMEOUT_SECONDS, queueDepth) {}
Service3Housekeeping::~Service3Housekeeping() {}

View File

@ -28,7 +28,8 @@ class Service3Housekeeping : public CommandingServiceBase, public AcceptsHkPacke
static constexpr uint8_t NUM_OF_PARALLEL_COMMANDS = 4;
static constexpr uint16_t COMMAND_TIMEOUT_SECONDS = 60;
Service3Housekeeping(object_id_t objectId, uint16_t apid, uint8_t serviceId);
Service3Housekeeping(object_id_t objectId, uint16_t apid, uint8_t serviceId, uint32_t queueDepth,
uint8_t numParallelCommands);
virtual ~Service3Housekeeping();
protected:

View File

@ -9,11 +9,11 @@
#include "fsfw/serviceinterface/ServiceInterface.h"
Service8FunctionManagement::Service8FunctionManagement(object_id_t objectId, uint16_t apid,
uint8_t serviceId,
uint8_t serviceId, size_t queueDepth,
uint8_t numParallelCommands,
uint16_t commandTimeoutSeconds)
: CommandingServiceBase(objectId, apid, "PUS 8 Functional Commanding", serviceId,
numParallelCommands, commandTimeoutSeconds) {}
numParallelCommands, commandTimeoutSeconds, queueDepth) {}
Service8FunctionManagement::~Service8FunctionManagement() {}

View File

@ -31,7 +31,8 @@
class Service8FunctionManagement : public CommandingServiceBase {
public:
Service8FunctionManagement(object_id_t objectId, uint16_t apid, uint8_t serviceId,
uint8_t numParallelCommands = 4, uint16_t commandTimeoutSeconds = 60);
size_t queueDepth, uint8_t numParallelCommands = 4,
uint16_t commandTimeoutSeconds = 60);
~Service8FunctionManagement() override;
protected:

View File

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

View File

@ -3,14 +3,14 @@
#include "fsfw/FSFW.h"
PoolManager::PoolManager(object_id_t setObjectId, const LocalPoolConfig& localPoolConfig)
: LocalPool(setObjectId, localPoolConfig, true) {
: LocalPool(setObjectId, localPoolConfig, true, true) {
mutex = MutexFactory::instance()->createMutex();
}
PoolManager::~PoolManager() { MutexFactory::instance()->deleteMutex(mutex); }
ReturnValue_t PoolManager::reserveSpace(const size_t size, store_address_t* address) {
MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeoutMs);
MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeoutMs, LOCK_CTX);
ReturnValue_t status = LocalPool::reserveSpace(size, address);
return status;
}
@ -22,12 +22,12 @@ ReturnValue_t PoolManager::deleteData(store_address_t storeId) {
<< storeId.poolIndex << ". id is " << storeId.packetIndex << std::endl;
#endif
#endif
MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeoutMs);
MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeoutMs, LOCK_CTX);
return LocalPool::deleteData(storeId);
}
ReturnValue_t PoolManager::deleteData(uint8_t* buffer, size_t size, store_address_t* storeId) {
MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, 20);
MutexGuard mutexHelper(mutex, MutexIF::TimeoutType::WAITING, mutexTimeoutMs, LOCK_CTX);
ReturnValue_t status = LocalPool::deleteData(buffer, size, storeId);
return status;
}

View File

@ -56,6 +56,7 @@ class PoolManager : public LocalPool {
protected:
//! Default mutex timeout value to prevent permanent blocking.
uint32_t mutexTimeoutMs = 20;
static constexpr char LOCK_CTX[] = "PoolManager";
ReturnValue_t reserveSpace(size_t size, store_address_t* address) override;

View File

@ -21,6 +21,7 @@ SubsystemBase::~SubsystemBase() { QueueFactory::instance()->deleteMessageQueue(c
ReturnValue_t SubsystemBase::checkStateAgainstTable(HybridIterator<ModeListEntry> tableIter,
Submode_t targetSubmode) {
using namespace mode;
std::map<object_id_t, ChildInfo>::iterator childIter;
for (; tableIter.value != NULL; ++tableIter) {
@ -34,13 +35,21 @@ ReturnValue_t SubsystemBase::checkStateAgainstTable(HybridIterator<ModeListEntry
return returnvalue::FAILED;
}
Submode_t submodeToCheckAgainst = tableIter.value->getSubmode();
// Check submodes here.
uint8_t mask;
bool submodesAllowedMask = tableIter.value->submodesAllowed(&mask);
uint8_t submodeToCheckAgainst = tableIter.value->getSubmode();
if (tableIter.value->inheritSubmode()) {
submodeToCheckAgainst = targetSubmode;
}
if (childIter->second.submode != submodeToCheckAgainst) {
return returnvalue::FAILED;
if (submodesAllowedMask) {
if ((childIter->second.submode | mask) != mask) {
return returnvalue::FAILED;
}
} else {
if (childIter->second.submode != submodeToCheckAgainst) {
return returnvalue::FAILED;
}
}
}
return returnvalue::OK;
@ -117,6 +126,20 @@ ReturnValue_t SubsystemBase::updateChildMode(MessageQueueId_t queue, Mode_t mode
return CHILD_NOT_FOUND;
}
ReturnValue_t SubsystemBase::updateChildModeByObjId(object_id_t objectId, Mode_t mode,
Submode_t submode) {
std::map<object_id_t, ChildInfo>::iterator iter;
for (iter = childrenMap.begin(); iter != childrenMap.end(); iter++) {
if (iter->first == objectId) {
iter->second.mode = mode;
iter->second.submode = submode;
return returnvalue::OK;
}
}
return CHILD_NOT_FOUND;
}
ReturnValue_t SubsystemBase::updateChildChangedHealth(MessageQueueId_t queue, bool changedHealth) {
for (auto iter = childrenMap.begin(); iter != childrenMap.end(); iter++) {
if (iter->second.commandQueue == queue) {
@ -292,20 +315,7 @@ object_id_t SubsystemBase::getObjectId() const { return SystemObject::getObjectI
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;
return registerChild(child.getObjectId(), child.getModeIF().getCommandQueue());
}
const HasHealthIF* SubsystemBase::getOptHealthIF() const { return this; }
@ -313,3 +323,19 @@ const HasHealthIF* SubsystemBase::getOptHealthIF() const { return this; }
const HasModesIF& SubsystemBase::getModeIF() const { return *this; }
ModeTreeChildIF& SubsystemBase::getModeTreeChildIF() { return *this; }
ReturnValue_t SubsystemBase::registerChild(object_id_t childObjectId, MessageQueueId_t childQueue) {
ChildInfo info;
// intentional to force an initial command during system startup
info.commandQueue = childQueue;
info.mode = HasModesIF::MODE_UNDEFINED;
info.submode = SUBMODE_NONE;
info.healthChanged = false;
auto resultPair = childrenMap.emplace(childObjectId, info);
if (not resultPair.second) {
return COULD_NOT_INSERT_CHILD;
}
return returnvalue::OK;
}

View File

@ -61,6 +61,8 @@ class SubsystemBase : public SystemObject,
* COULD_NOT_INSERT_CHILD If the Child could not be added to the ChildrenMap
*/
ReturnValue_t registerChild(const ModeTreeChildIF &child) override;
// TODO: Add this to HasModeTreeChildrenIF.
ReturnValue_t registerChild(object_id_t childObjectId, MessageQueueId_t childQueue);
ReturnValue_t initialize() override;
@ -115,6 +117,7 @@ class SubsystemBase : public SystemObject,
Submode_t targetSubmode = SUBMODE_NONE);
ReturnValue_t updateChildMode(MessageQueueId_t queue, Mode_t mode, Submode_t submode);
ReturnValue_t updateChildModeByObjId(object_id_t objectId, Mode_t mode, Submode_t submode);
ReturnValue_t updateChildChangedHealth(MessageQueueId_t queue, bool changedHealth = true);

View File

@ -1,111 +1,126 @@
#ifndef FSFW_SUBSYSTEM_MODES_MODEDEFINITIONS_H_
#define FSFW_SUBSYSTEM_MODES_MODEDEFINITIONS_H_
#include "../../modes/HasModesIF.h"
#include "../../objectmanager/SystemObjectIF.h"
#include "../../serialize/SerialLinkedListAdapter.h"
#include "../../serialize/SerializeIF.h"
#include "fsfw/modes/HasModesIF.h"
#include "fsfw/objectmanager/SystemObjectIF.h"
#include "fsfw/serialize/SerialLinkedListAdapter.h"
#include "fsfw/serialize/SerializeIF.h"
class ModeListEntry : public SerializeIF, public LinkedElement<ModeListEntry> {
namespace mode {
enum SpecialSubmodeFlags : uint8_t { INHERIT = 1 << 0, ALLOWED_MASK = 1 << 1 };
}
class ModeListEntry : public SerialLinkedListAdapter<SerializeIF>,
public LinkedElement<ModeListEntry> {
public:
ModeListEntry() : LinkedElement<ModeListEntry>(this) {}
static constexpr uint8_t ALL_SUBMODES_ALLOWED_MASK = 0xff;
uint32_t value1 = 0;
uint32_t value2 = 0;
uint8_t value3 = 0;
uint8_t value4 = 0;
ModeListEntry() : SerialLinkedListAdapter(), LinkedElement<ModeListEntry>(this) { setLinks(); }
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const {
ReturnValue_t result;
SerializeElement<uint32_t> value1 = 0;
SerializeElement<uint32_t> value2 = 0;
SerializeElement<uint8_t> value3 = 0;
SerializeElement<uint8_t> value4 = 0;
SerializeElement<uint8_t> value5 = 0;
result = SerializeAdapter::serialize(&value1, buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::serialize(&value2, buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::serialize(&value3, buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::serialize(&value4, buffer, size, maxSize, streamEndianness);
return result;
ModeListEntry(const ModeListEntry& other)
: SerialLinkedListAdapter(), LinkedElement<ModeListEntry>(this) {
value1.entry = other.value1.entry;
value2.entry = other.value2.entry;
value3.entry = other.value3.entry;
value4.entry = other.value4.entry;
value5.entry = other.value5.entry;
setLinks();
}
virtual size_t getSerializedSize() const {
return sizeof(value1) + sizeof(value2) + sizeof(value3) + sizeof(value4);
ModeListEntry& operator=(const ModeListEntry& other) {
this->value1.entry = other.value1.entry;
this->value2.entry = other.value2.entry;
this->value3.entry = other.value3.entry;
this->value4.entry = other.value4.entry;
this->value5.entry = other.value5.entry;
return *this;
}
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) {
ReturnValue_t result;
result = SerializeAdapter::deSerialize(&value1, buffer, size, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::deSerialize(&value2, buffer, size, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::deSerialize(&value3, buffer, size, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::deSerialize(&value4, buffer, size, streamEndianness);
return result;
void setLinks() {
setStart(&value1);
value1.setNext(&value2);
value2.setNext(&value3);
value3.setNext(&value4);
value4.setNext(&value5);
}
// for Sequences
Mode_t getTableId() const { return value1; }
Mode_t getTableId() const { return value1.entry; }
void setTableId(Mode_t tableId) { this->value1 = tableId; }
void setTableId(Mode_t tableId) { this->value1.entry = tableId; }
uint8_t getWaitSeconds() const { return value2; }
uint8_t getWaitSeconds() const { return value2.entry; }
void setWaitSeconds(uint8_t waitSeconds) { this->value2 = waitSeconds; }
void setWaitSeconds(uint8_t waitSeconds) { this->value2.entry = waitSeconds; }
bool checkSuccess() const { return value3 == 1; }
bool checkSuccess() const { return value3.entry == 1; }
void setCheckSuccess(bool checkSuccess) { this->value3 = checkSuccess; }
void setCheckSuccess(bool checkSuccess) { this->value3.entry = checkSuccess; }
// for Tables
object_id_t getObject() const { return value1; }
object_id_t getObject() const { return value1.entry; }
void setObject(object_id_t object) { this->value1 = object; }
void setObject(object_id_t object) { this->value1.entry = object; }
Mode_t getMode() const { return value2; }
Mode_t getMode() const { return value2.entry; }
void setMode(Mode_t mode) { this->value2 = mode; }
void setMode(Mode_t mode) { this->value2.entry = mode; }
Submode_t getSubmode() const { return value3; }
Submode_t getSubmode() const { return value3.entry; }
void setSubmode(Submode_t submode) { this->value3 = submode; }
void setSubmode(Submode_t submode) { this->value3.entry = submode; }
bool inheritSubmode() const { return value4 == 1; }
void setInheritSubmode(bool inherit) {
if (inherit) {
value4 = 1;
} else {
value4 = 0;
bool inheritSubmode() const {
return (value4.entry & mode::SpecialSubmodeFlags::INHERIT) ==
mode::SpecialSubmodeFlags::INHERIT;
}
bool submodesAllowed(uint8_t* mask) const {
bool submodesAllowed = (value4.entry & mode::SpecialSubmodeFlags::ALLOWED_MASK) ==
mode::SpecialSubmodeFlags::ALLOWED_MASK;
if (submodesAllowed and mask != nullptr) {
*mask = value5.entry;
}
return submodesAllowed;
}
bool operator==(ModeListEntry other) {
return ((value1 == other.value1) && (value2 == other.value2) && (value3 == other.value3));
/**
* Enable the inheritance of submodes. This is relevant for both the execution
* of mode tables and for mode checking.
*/
void enableInheritSubmode() { value4.entry |= mode::SpecialSubmodeFlags::INHERIT; }
/**
* Disable the inheritance of submodes. This is relevant for both the execution
* of mode tables and for mode checking.
*/
void disableInheritSubmode() { value4.entry &= ~mode::SpecialSubmodeFlags::INHERIT; }
/**
* Specialization of @enableSubmodeAllowed which allows all submodes.
*/
void allowAllSubmodes() { enableSubmodeAllowed(ALL_SUBMODES_ALLOWED_MASK); }
/**
* Enable an allowed submode mask for mode checks. Any submode which contains bits
* outside of the mask will be declined.
*
* For example, for a mask of 0b11, only the modes 0b00, 0b01 and 0b11 will be accepted.
*/
void enableSubmodeAllowed(uint8_t mask) {
value4.entry |= mode::SpecialSubmodeFlags::ALLOWED_MASK;
value5.entry = mask;
}
/**
* Enforce the equality of submodes for mode checks. This is the default.
*/
void disableSubmodeAllowed() {
value4.entry &= ~mode::SpecialSubmodeFlags::ALLOWED_MASK;
value5.entry = 0;
}
};

View File

@ -15,10 +15,10 @@ ReturnValue_t FixedTimeslotTaskBase::addSlot(object_id_t execId, ExecutableObjec
uint32_t slotTimeMs, int8_t executionStep) {
if (execObj == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Component 0x" << std::hex << std::setw(8) << std::setfill('0') << execObj
sif::error << "Component 0x" << std::hex << std::setw(8) << std::setfill('0') << execId
<< std::setfill(' ') << " not found, not adding it to PST" << std::dec << std::endl;
#else
sif::printError("Component 0x%08x not found, not adding it to PST\n");
sif::printError("Component 0x%08x not found, not adding it to PST\n", execId);
#endif
return returnvalue::FAILED;
}

View File

@ -47,7 +47,8 @@ class TaskFactory {
*/
PeriodicTaskIF* createPeriodicTask(TaskName name_, TaskPriority taskPriority_,
TaskStackSize stackSize_, TaskPeriod periodInSeconds_,
TaskDeadlineMissedFunction deadLineMissedFunction_);
TaskDeadlineMissedFunction deadLineMissedFunction_,
void* args = nullptr);
/**
* The meaning for the variables for fixed timeslot tasks is the same as for periodic tasks.
@ -62,7 +63,8 @@ class TaskFactory {
FixedTimeslotTaskIF* createFixedTimeslotTask(TaskName name_, TaskPriority taskPriority_,
TaskStackSize stackSize_,
TaskPeriod periodInSeconds_,
TaskDeadlineMissedFunction deadLineMissedFunction_);
TaskDeadlineMissedFunction deadLineMissedFunction_,
void* args = nullptr);
/**
* Function to be called to delete a task

View File

@ -283,7 +283,7 @@ ReturnValue_t Heater::getParameter(uint8_t domainId, uint8_t uniqueId,
}
switch (uniqueId) {
case 0:
parameterWrapper->set(heaterOnCountdown.timeout);
parameterWrapper->set(heaterOnCountdown.getTimeoutMs());
break;
default:
return INVALID_IDENTIFIER_ID;

View File

@ -246,6 +246,20 @@ ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t*
return UNSUPPORTED_TIME_FORMAT;
}
ReturnValue_t CCSDSTime::convertToAsciiWithSecs(int8_t* to, const Clock::TimeOfDay_t* from,
uint8_t length) {
if (from == nullptr or to == nullptr) {
return returnvalue::FAILED;
}
int count = snprintf(reinterpret_cast<char*>(to), length,
"%4" SCNu32 "-%2" SCNu32 "-%2" SCNu32 "T%2" SCNu32 ":%2" SCNu32 ":%2" SCNu32,
from->year, from->month, from->day, from->hour, from->minute, from->second);
if (count >= length) {
return returnvalue::FAILED;
}
return returnvalue::OK;
}
ReturnValue_t CCSDSTime::checkCcs(const uint8_t* time, uint8_t length) {
const Ccs_mseconds* time_struct = reinterpret_cast<const Ccs_mseconds*>(time);

View File

@ -207,7 +207,8 @@ class CCSDSTime {
static ReturnValue_t convertFromASCII(Clock::TimeOfDay_t *to, uint8_t const *from,
uint8_t length);
static ReturnValue_t convertToAsciiWithSecs(int8_t *to, const Clock::TimeOfDay_t *from,
uint8_t length);
static uint32_t subsecondsToMicroseconds(uint16_t subseconds);
private:

View File

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

View File

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

View File

@ -49,6 +49,13 @@ class Clock {
* @return -@c returnvalue::OK on success. Otherwise, the OS failure code is returned.
*/
static ReturnValue_t setClock(const timeval *time);
/**
* @deprecated Use getClock instead, which does the same.
* @param time
* @return
*/
static ReturnValue_t getClock_timeval(timeval *time);
/**
* This system call returns the current system clock in timeval format.
* The timval format has the fields @c tv_sec with seconds and @c tv_usec with
@ -56,7 +63,18 @@ class Clock {
* @param time A pointer to a timeval struct where the current time is stored.
* @return @c returnvalue::OK on success. Otherwise, the OS failure code is returned.
*/
static ReturnValue_t getClock_timeval(timeval *time);
static ReturnValue_t getClock(timeval *time);
/**
* Retrieve a monotonic clock. This clock this is also more suited for measuring elapsed times
* between two time points, but less suited when the absolute time is required.
*
* Implementation example: A generic UNIX implementation can use CLOCK_MONOTONIC_RAW with
* `clock_gettime`.
* @param time
* @return
*/
static ReturnValue_t getClockMonotonic(timeval *time);
/**
* Get the time since boot in a timeval struct

View File

@ -1,49 +1,62 @@
#include "fsfw/timemanager/Countdown.h"
Countdown::Countdown(uint32_t initialTimeout, bool startImmediately) : timeout(initialTimeout) {
#include "fsfw/globalfunctions/timevalOperations.h"
Countdown::Countdown(uint32_t initialTimeout, bool startImmediately) {
if (startImmediately) {
setTimeout(initialTimeout);
} else {
timeout = initialTimeout;
timeout.tv_sec = initialTimeout / 1000;
timeout.tv_usec = (initialTimeout % 1000) * 1000;
}
}
Countdown::~Countdown() {}
Countdown::~Countdown() = default;
ReturnValue_t Countdown::setTimeout(uint32_t milliseconds) {
ReturnValue_t returnValue = Clock::getUptime(&startTime);
timeout = milliseconds;
return returnValue;
timeout.tv_sec = milliseconds / 1000;
timeout.tv_usec = (milliseconds % 1000) * 1000;
return Clock::getClockMonotonic(&startTime);
}
bool Countdown::hasTimedOut() const {
if (uint32_t(this->getCurrentTime() - startTime) >= timeout) {
// Account for system clock going back in time.
if (getCurrentTime() < startTime) {
return true;
} else {
return false;
}
if (getCurrentTime() - startTime >= timeout) {
return true;
}
return false;
}
bool Countdown::isBusy() const { return !hasTimedOut(); }
ReturnValue_t Countdown::resetTimer() { return setTimeout(timeout); }
ReturnValue_t Countdown::resetTimer() { return setTimeoutTv(timeout); }
void Countdown::timeOut() { startTime = this->getCurrentTime() - timeout; }
uint32_t Countdown::getRemainingMillis() const {
// We fetch the time before the if-statement
// to be sure that the return is in
// range 0 <= number <= timeout
uint32_t currentTime = this->getCurrentTime();
if (this->hasTimedOut()) {
return 0;
} else {
return (startTime + timeout) - currentTime;
}
timeval remainingMillisTv = (startTime + timeout) - this->getCurrentTime();
return remainingMillisTv.tv_sec * 1000 + remainingMillisTv.tv_usec / 1000;
}
uint32_t Countdown::getCurrentTime() const {
uint32_t currentTime;
Clock::getUptime(&currentTime);
uint32_t Countdown::timevalToMs(timeval &tv) { return tv.tv_sec * 1000 + tv.tv_usec / 1000; }
ReturnValue_t Countdown::setTimeoutTv(timeval tv) {
timeout = tv;
return Clock::getClockMonotonic(&startTime);
}
uint32_t Countdown::getTimeoutMs() const { return timeout.tv_sec * 1000 + timeout.tv_usec / 1000; }
timeval Countdown::getTimeout() const { return timeout; }
timeval Countdown::getCurrentTime() const {
timeval currentTime{};
Clock::getClockMonotonic(&currentTime);
return currentTime;
}

View File

@ -6,6 +6,10 @@
/**
*
* Countdown keeps track of a timespan.
* This class uses the system clock internally to achieve
* a high resolution. This means that the API is only partially
* resistant against time jumps. The user must take care to account
* for time jumps in some from if this relevant.
*
* Countdown::resetTimer restarts the timer.
* Countdown::setTimeout sets a new countdown duration and resets.
@ -39,6 +43,8 @@ class Countdown {
* @return Returnvalue from Clock::getUptime
*/
ReturnValue_t setTimeout(uint32_t milliseconds);
ReturnValue_t setTimeoutTv(timeval tv);
/**
* Returns true if the countdown duration has passed.
*
@ -61,22 +67,31 @@ class Countdown {
* Returns the remaining milliseconds (0 if timeout)
*/
uint32_t getRemainingMillis() const;
uint32_t getTimeoutMs() const;
timeval getTimeout() const;
/**
* Makes hasTimedOut() return true
*/
void timeOut();
/**
* Internal countdown duration in milliseconds
*/
uint32_t timeout;
static inline uint32_t timevalToMs(timeval& tv);
private:
/**
* Last time the timer was started (uptime)
* Start time of the countdown.
*/
uint32_t startTime = 0;
timeval startTime{};
uint32_t getCurrentTime() const;
/**
* Timeout as timeval type. The countdown has timed out when the
* current time exceeds the start time plus the timeout.
*/
timeval timeout{};
timeval getCurrentTime() const;
};
#endif /* FSFW_TIMEMANAGER_COUNTDOWN_H_ */

View File

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

View File

@ -6,47 +6,12 @@
#include "fsfw/returnvalues/returnvalue.h"
#include "tmStorageConf.h"
class TmPacketMinimal;
class SpacePacketBase;
class PusTmReader;
class SpacePacketReader;
class TmStoreBackendIF;
class TmStoreFrontendIF {
public:
virtual TmStoreBackendIF* getBackend() const = 0;
/**
* What do I need to implement here?
* This is propably used by PUS Service 15 so we should propably check for messages..
* Provide base implementation?
* @param opCode
* @return
*/
virtual ReturnValue_t performOperation(uint8_t opCode) = 0;
/**
* Callback from the back-end to indicate a certain packet was received.
* front-end takes care of discarding/downloading the packet.
* @param packet Pointer to the newly received Space Packet.
* @param address Start address of the packet found
* @param isLastPacket Indicates if no more packets can be fetched.
* @return If more packets shall be fetched, returnvalue::OK must be returned.
* Any other code stops fetching packets.
*/
virtual ReturnValue_t packetRetrieved(TmPacketMinimal* packet, uint32_t address) = 0;
virtual void noMorePacketsInStore() = 0;
virtual void handleRetrievalFailed(ReturnValue_t errorCode, uint32_t parameter1 = 0,
uint32_t parameter2 = 0) = 0;
/**
* To get the queue where commands shall be sent.
* @return Id of command queue.
*/
virtual MessageQueueId_t getCommandQueue() const = 0;
virtual ReturnValue_t fetchPackets(ApidSsc start, ApidSsc end) = 0;
virtual ReturnValue_t deletePackets(ApidSsc upTo) = 0;
virtual ReturnValue_t checkPacket(SpacePacketBase* tmPacket) = 0;
virtual bool isEnabled() const = 0;
virtual void setEnabled(bool enabled) = 0;
virtual void resetDownlinkedPacketCount() = 0;
virtual ReturnValue_t setDumpTarget(object_id_t dumpTarget) = 0;
static const uint8_t INTERFACE_ID = CLASS_ID::TM_STORE_FRONTEND_IF;
static const ReturnValue_t BUSY = MAKE_RETURN_CODE(1);
static const ReturnValue_t LAST_PACKET_FOUND = MAKE_RETURN_CODE(2);
@ -57,7 +22,38 @@ class TmStoreFrontendIF {
static const ReturnValue_t ALL_DELETED = MAKE_RETURN_CODE(7);
static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(8);
static const ReturnValue_t NOT_READY = MAKE_RETURN_CODE(9);
virtual ~TmStoreFrontendIF() {}
virtual ~TmStoreFrontendIF() = default;
/**
* To get the queue where commands shall be sent.
* @return Id of command queue.
*/
virtual MessageQueueId_t getCommandQueue() const = 0;
virtual TmStoreBackendIF* getBackend() const = 0;
/**
* Callback from the back-end to indicate a certain packet was received.
* front-end takes care of discarding/downloading the packet.
* @param packet Pointer to the newly received Space Packet.
* @param address Start address of the packet found
* @param isLastPacket Indicates if no more packets can be fetched.
* @return If more packets shall be fetched, returnvalue::OK must be returned.
* Any other code stops fetching packets.
*/
virtual ReturnValue_t packetRetrieved(PusTmReader* packet, uint32_t address) = 0;
virtual void noMorePacketsInStore() = 0;
virtual void handleRetrievalFailed(ReturnValue_t errorCode, uint32_t parameter1 = 0,
uint32_t parameter2 = 0) = 0;
virtual ReturnValue_t fetchPackets(ApidSsc start, ApidSsc end) = 0;
virtual ReturnValue_t deletePackets(ApidSsc upTo) = 0;
virtual ReturnValue_t checkPacket(SpacePacketReader* tmPacket) = 0;
virtual bool isEnabled() const = 0;
virtual void setEnabled(bool enabled) = 0;
virtual void resetDownlinkedPacketCount() = 0;
virtual ReturnValue_t setDumpTarget(object_id_t dumpTarget) = 0;
};
#endif /* FSFW_TMTCSERVICES_TMSTOREFRONTENDIF_H_ */

View File

@ -0,0 +1,15 @@
#ifndef FSFW_SRC_FSFW_TMSTORAGE_TMSTOREBACKENDSIMPLEIF_H_
#define FSFW_SRC_FSFW_TMSTORAGE_TMSTOREBACKENDSIMPLEIF_H_
#include <fsfw/ipc/messageQueueDefinitions.h>
class TmStoreFrontendSimpleIF {
public:
virtual ~TmStoreFrontendSimpleIF() = default;
virtual MessageQueueId_t getCommandQueue() const = 0;
private:
};
#endif /* FSFW_SRC_FSFW_TMSTORAGE_TMSTOREBACKENDSIMPLEIF_H_ */

View File

@ -1,6 +1,10 @@
#ifndef FSFW_TMSTORAGE_TMSTOREPACKETS_H_
#define FSFW_TMSTORAGE_TMSTOREPACKETS_H_
#include <fsfw/tmtcpacket/pus/tm/PusTmReader.h>
#include <vector>
#include "fsfw/globalfunctions/timevalOperations.h"
#include "fsfw/serialize/SerialBufferAdapter.h"
#include "fsfw/serialize/SerialFixedArrayListAdapter.h"
@ -24,7 +28,7 @@ class ServiceSubservice : public SerialLinkedListAdapter<SerializeIF> {
class ApidSsc : public SerializeIF {
public:
ApidSsc() : apid(SpacePacketBase::LIMIT_APID), ssc(0) {}
ApidSsc() : apid(ccsds::LIMIT_APID), ssc(0) {}
ApidSsc(uint16_t apid, uint16_t ssc) : apid(apid), ssc(ssc) {}
uint16_t apid;
uint16_t ssc;
@ -62,51 +66,59 @@ class ChangeSelectionDefinition : public SerialLinkedListAdapter<SerializeIF> {
class TmPacketInformation : public SerializeIF {
public:
TmPacketInformation(TmPacketMinimal* packet) { setContent(packet); }
TmPacketInformation()
: apid(SpacePacketBase::LIMIT_APID),
TmPacketInformation(PusTmReader* packet, size_t timestampLen) : rawTimestamp(timestampLen) {
setContent(packet);
}
TmPacketInformation(size_t timestampLen)
: apid(ccsds::LIMIT_APID),
sourceSequenceCount(0),
serviceType(0),
serviceSubtype(0),
subCounter(0) {}
subCounter(0),
rawTimestamp(timestampLen) {}
void reset() {
apid = SpacePacketBase::LIMIT_APID;
apid = ccsds::LIMIT_APID;
sourceSequenceCount = 0;
serviceType = 0;
serviceSubtype = 0;
subCounter = 0;
memset(rawTimestamp, 0, sizeof(rawTimestamp));
memset(rawTimestamp.data(), 0, rawTimestamp.size());
}
void setContent(TmPacketMinimal* packet) {
apid = packet->getAPID();
sourceSequenceCount = packet->getPacketSequenceCount();
void setContent(PusTmReader* packet) {
apid = packet->getApid();
sourceSequenceCount = packet->getSequenceCount();
serviceType = packet->getService();
serviceSubtype = packet->getSubService();
subCounter = packet->getPacketSubcounter();
memset(rawTimestamp, 0, sizeof(rawTimestamp));
const uint8_t* pField = NULL;
uint32_t size = 0;
ReturnValue_t result = packet->getPacketTimeRaw(&pField, &size);
if (result != returnvalue::OK) {
return;
}
if (*pField == CCSDSTime::P_FIELD_CDS_SHORT && size <= TimeStamperIF::MISSION_TIMESTAMP_SIZE) {
// Shortcut to avoid converting CDS back and forth.
memcpy(rawTimestamp, pField, size);
return;
}
timeval time = {0, 0};
result = packet->getPacketTime(&time);
if (result != returnvalue::OK) {
return;
}
CCSDSTime::CDS_short cdsFormat;
result = CCSDSTime::convertToCcsds(&cdsFormat, &time);
if (result != returnvalue::OK) {
return;
}
memcpy(rawTimestamp, &cdsFormat, sizeof(cdsFormat));
subCounter = packet->getMessageTypeCounter();
memset(rawTimestamp.data(), 0, rawTimestamp.size());
// TODO: Fix all of this
// const uint8_t* pField = NULL;
// uint32_t size = 0;
// auto* timeReader = packet->getTimeReader();
// ReturnValue_t result = packet->getPacketTimeRaw(&pField, &size);
// if (result != returnvalue::OK) {
// return;
//}
// if (*pField == CCSDSTime::P_FIELD_CDS_SHORT && size <= TimeStamperIF::MISSION_TIMESTAMP_SIZE)
// {
// Shortcut to avoid converting CDS back and forth.
// TODO: Fix
// memcpy(rawTimestamp, pField, size);
// return;
// }
// timeval time = {0, 0};
// result = packet->getPacketTime(&time);
// if (result != returnvalue::OK) {
// return;
// }
//
// CCSDSTime::CDS_short cdsFormat;
// result = CCSDSTime::convertToCcsds(&cdsFormat, &time);
// if (result != returnvalue::OK) {
// return;
// }
// TODO: Fix
// memcpy(rawTimestamp, &cdsFormat, sizeof(cdsFormat));
}
void setContent(TmPacketInformation* content) {
apid = content->apid;
@ -114,9 +126,10 @@ class TmPacketInformation : public SerializeIF {
serviceType = content->serviceType;
serviceSubtype = content->serviceSubtype;
subCounter = content->subCounter;
memcpy(rawTimestamp, content->rawTimestamp, sizeof(rawTimestamp));
// TODO: Fix
// memcpy(rawTimestamp, content->rawTimestamp, sizeof(rawTimestamp));
}
bool isValid() const { return (apid < SpacePacketBase::LIMIT_APID) ? true : false; }
bool isValid() const { return (apid < ccsds::LIMIT_APID) ? true : false; }
static void reset(TmPacketInformation* packet) { packet->reset(); }
static bool isOlderThan(const TmPacketInformation* packet, const timeval* cmpTime) {
@ -216,7 +229,7 @@ class TmPacketInformation : public SerializeIF {
if (result != returnvalue::OK) {
return result;
}
SerialBufferAdapter<uint8_t> adapter(rawTimestamp, sizeof(rawTimestamp));
SerialBufferAdapter<uint8_t> adapter(rawTimestamp.data(), rawTimestamp.size());
return adapter.serialize(buffer, size, maxSize, streamEndianness);
}
@ -227,7 +240,7 @@ class TmPacketInformation : public SerializeIF {
size += SerializeAdapter::getSerializedSize(&serviceType);
size += SerializeAdapter::getSerializedSize(&serviceSubtype);
size += SerializeAdapter::getSerializedSize(&subCounter);
SerialBufferAdapter<uint8_t> adapter(rawTimestamp, sizeof(rawTimestamp));
SerialBufferAdapter<uint8_t> adapter(rawTimestamp.data(), rawTimestamp.size());
size += adapter.getSerializedSize();
return size;
};
@ -253,7 +266,7 @@ class TmPacketInformation : public SerializeIF {
if (result != returnvalue::OK) {
return result;
}
SerialBufferAdapter<uint8_t> adapter(rawTimestamp, sizeof(rawTimestamp));
SerialBufferAdapter<uint8_t> adapter(rawTimestamp.data(), rawTimestamp.size());
return adapter.deSerialize(buffer, size, streamEndianness);
}
@ -263,6 +276,6 @@ class TmPacketInformation : public SerializeIF {
uint8_t serviceType;
uint8_t serviceSubtype;
uint8_t subCounter;
uint8_t rawTimestamp[TimeStamperIF::MISSION_TIMESTAMP_SIZE];
std::vector<uint8_t> rawTimestamp;
};
#endif /* FSFW_TMSTORAGE_TMSTOREPACKETS_H_ */

View File

@ -40,7 +40,7 @@ struct PusTmParams {
size_t dataLen)
: secHeader(service, subservice, timeStamper), adapter(data, dataLen), sourceData(&adapter) {}
PusTmSecHeader secHeader;
SerialBufferAdapter<uint8_t> adapter;
SerialBufferAdapter<size_t> adapter;
const SerializeIF* sourceData = nullptr;
};

View File

@ -24,3 +24,9 @@ void PusTmZeroCopyWriter::updateErrorControl() {
crcStart[0] = (crc16 >> 8) & 0xff;
crcStart[1] = crc16 & 0xff;
}
void PusTmZeroCopyWriter::setMessageCount(uint16_t msgCount) {
size_t serSize = 0;
SerializeAdapter::serialize(&msgCount, const_cast<uint8_t*>(pointers.secHeaderStart + 3),
&serSize, 2, SerializeIF::Endianness::NETWORK);
}

View File

@ -14,6 +14,7 @@ class PusTmZeroCopyWriter : public PusTmReader {
PusTmZeroCopyWriter(TimeReaderIF& timeReader, uint8_t* data, size_t size);
void setSequenceCount(uint16_t seqCount);
void setMessageCount(uint16_t msgCount);
void updateErrorControl();
private:

View File

@ -8,7 +8,7 @@
#define TMTCBRIDGE_WIRETAPPING 0
TmTcBridge::TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDestination,
object_id_t tmStoreId, object_id_t tcStoreId)
uint32_t msgQueueDepth, object_id_t tmStoreId, object_id_t tcStoreId)
: SystemObject(objectId),
name(name),
tmStoreId(tmStoreId),
@ -18,7 +18,7 @@ TmTcBridge::TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDes
{
auto mqArgs = MqArgs(objectId, static_cast<void*>(this));
tmTcReceptionQueue = QueueFactory::instance()->createMessageQueue(
TMTC_RECEPTION_QUEUE_DEPTH, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
msgQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
TmTcBridge::~TmTcBridge() { QueueFactory::instance()->deleteMessageQueue(tmTcReceptionQueue); }

View File

@ -15,15 +15,14 @@ class TmTcBridge : public AcceptsTelemetryIF,
public ExecutableObjectIF,
public SystemObject {
public:
static constexpr uint8_t TMTC_RECEPTION_QUEUE_DEPTH = 20;
static constexpr uint8_t LIMIT_STORED_DATA_SENT_PER_CYCLE = 15;
static constexpr unsigned int LIMIT_DOWNLINK_PACKETS_STORED = 1000;
static constexpr unsigned int LIMIT_DOWNLINK_PACKETS_STORED = 500;
static constexpr uint8_t DEFAULT_STORED_DATA_SENT_PER_CYCLE = 5;
static constexpr uint8_t DEFAULT_DOWNLINK_PACKETS_STORED = 10;
TmTcBridge(const char* name, object_id_t objectId, object_id_t tcDestination,
object_id_t tmStoreId, object_id_t tcStoreId);
uint32_t msgQueueDepth, object_id_t tmStoreId, object_id_t tcStoreId);
~TmTcBridge() override;
/**

View File

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

View File

@ -5,8 +5,18 @@
namespace spi {
static constexpr uint8_t CLASS_ID = CLASS_ID::HAL_SPI;
static constexpr ReturnValue_t OPENING_FILE_FAILED = returnvalue::makeCode(CLASS_ID, 0);
/* Full duplex (ioctl) transfer failure */
static constexpr ReturnValue_t FULL_DUPLEX_TRANSFER_FAILED = returnvalue::makeCode(CLASS_ID, 1);
/* Half duplex (read/write) transfer failure */
static constexpr ReturnValue_t HALF_DUPLEX_TRANSFER_FAILED = returnvalue::makeCode(CLASS_ID, 2);
static constexpr ReturnValue_t TIMEOUT = returnvalue::makeCode(CLASS_ID, 3);
static constexpr ReturnValue_t BUSY = returnvalue::makeCode(CLASS_ID, 4);
static constexpr ReturnValue_t GENERIC_ERROR = returnvalue::makeCode(CLASS_ID, 5);
enum SpiModes : uint8_t { MODE_0, MODE_1, MODE_2, MODE_3 };
}
} // namespace spi
#endif /* FSFW_HAL_COMMON_SPI_SPICOMMON_H_ */

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