Compare commits

...

223 Commits

Author SHA1 Message Date
70c4f8f3fd Merge pull request 'v6.1.0' (#740) from prep_v6.1.0 into main
All checks were successful
EIVE/eive-obsw/pipeline/pr-v6.0.0-branch This commit looks good
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #740
2023-07-13 13:07:07 +02:00
1f44533b3e bump minor version
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-13 12:00:57 +02:00
546053f95a Merge pull request 'STR tests' (#739) from startracker-tests into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #739
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-13 09:33:03 +02:00
86f7d05526 changelog
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-12 17:03:17 +02:00
8cc5220dd0 remove printout
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-12 17:02:52 +02:00
a800ad6c9a Merge remote-tracking branch 'origin/main' into startracker-tests
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-12 16:58:49 +02:00
887bfc87c3 Merge pull request 'use correct clock API in TCS CTRL' (#738) from small-tcs-fix into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #738
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-12 10:29:47 +02:00
54309b512f use correct clock API
Some checks are pending
EIVE/eive-obsw/pipeline/head Build queued...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-11 17:29:27 +02:00
74859dd5c6 Merge pull request 'TCS Observability' (#733) from tcs-observability into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #733
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-11 16:47:58 +02:00
13e965948c TCS observability
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-11 13:52:41 +02:00
46bb602c96 bump tmtc
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-07-11 11:01:32 +02:00
72dbc34936 Merge remote-tracking branch 'origin/main' into tcs-observability
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-07-11 11:00:03 +02:00
55affe5a42 Merge pull request 'TCS heater upper burn limit' (#732) from tcs-heater-upper-limit into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #732
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-11 10:56:42 +02:00
914a22f642 Merge branch 'main' into tcs-heater-upper-limit
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-11 10:46:02 +02:00
ed7d75a777 thermal controller
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-11 10:44:46 +02:00
9443d3844a Merge pull request 'fsfw bump and changelog' (#737) from bump-fsfw into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #737
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-11 10:38:59 +02:00
8800b20409 Merge remote-tracking branch 'origin/main' into tcs-heater-upper-limit
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-07-11 09:45:01 +02:00
690f8cb49a Merge remote-tracking branch 'origin/main' into bump-fsfw
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-11 09:41:44 +02:00
dbc3868f47 Merge pull request 'minor tweaks for XADC code' (#736) from minor-xadc-tweak into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #736
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-11 09:40:05 +02:00
852f1203c6 changelog
Some checks are pending
EIVE/eive-obsw/pipeline/pr-main Build queued...
2023-07-11 09:39:21 +02:00
643f8c5b54 Merge branch 'main' into minor-xadc-tweak
Some checks are pending
EIVE/eive-obsw/pipeline/pr-main Build queued...
2023-07-11 09:38:14 +02:00
3fb083fd87 Merge pull request 'TCS improvements' (#735) from tcs-tweaks into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #735
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-11 09:37:57 +02:00
fdf1c7a611 seems to work now
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-10 18:29:55 +02:00
cf582dd6a4 Merge branch 'bump-fsfw' into tcs-observability
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-10 17:52:56 +02:00
c7f716c433 fsfw bump and changelog
Some checks are pending
EIVE/eive-obsw/pipeline/head Build queued...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-10 17:51:37 +02:00
d2dfc22373 Merge branch 'tcs-heater-upper-limit' into tcs-observability
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-10 16:33:42 +02:00
53d53e8771 disable test case
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-10 16:33:29 +02:00
84e37d8b7b bump tmtc
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-10 16:30:18 +02:00
7c4f98ec22 add back with other name and comment
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-10 15:23:04 +02:00
a61d7901bf Merge branch 'tcs-heater-upper-limit' into tcs-observability
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-10 14:58:16 +02:00
7e01a9602e TCS improvements
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-10 14:46:35 +02:00
be1d1cf5bf minor tweaks for XADC code
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-10 14:15:56 +02:00
ce2755e161 that should be it
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-10 13:56:30 +02:00
33de08eafc this should be better
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-10 13:28:36 +02:00
106d73238b Merge remote-tracking branch 'origin/main' into tcs-heater-upper-limit 2023-07-10 13:07:26 +02:00
3f4a34d616 Merge pull request 'Make OBSW compatible to prospective FW v5.0.0' (#734) from tmp-devs-to-q7-i2c into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #734
2023-07-10 11:19:35 +02:00
268f10ced5 COMPILE
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-10 11:14:19 +02:00
647f3d00bb this should do the job
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-07-10 11:03:17 +02:00
2210ec3737 Merge branch 'tcs-heater-upper-limit' into tcs-observability
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-07 16:21:42 +02:00
df3755d6cc done
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-07 16:18:16 +02:00
a351dcf99e changelog
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-07 15:59:15 +02:00
06fe113d7f that should be sufficient
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-07 15:33:48 +02:00
43d86c9aad resolve merge conflicts properly
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-07 12:24:48 +02:00
c0ae25a973 Merge branch 'tcs-heater-upper-limit' into tcs-observability 2023-07-07 12:23:00 +02:00
fa85cc4d78 pls compile
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-07 12:22:37 +02:00
f7c49adea5 Merge branch 'tcs-heater-upper-limit' into tcs-observability
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-07-07 12:06:51 +02:00
b662e220e1 bump tmtc
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-07-07 12:06:39 +02:00
7337595d47 add event
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-07-07 12:05:29 +02:00
f2f73b088d add event
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-07-07 12:03:34 +02:00
fce16cc695 Merge branch 'tcs-heater-upper-limit' into tcs-observability
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-07-07 11:58:24 +02:00
ff7d0b3989 compile fixes
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-07 11:57:00 +02:00
6bf9fd5969 changelog
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-07-07 11:51:11 +02:00
a7ab26d804 Merge branch 'tcs-heater-upper-limit' into tcs-observability
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-07-07 11:50:32 +02:00
977e9f366f Merge remote-tracking branch 'origin/main' into tcs-heater-upper-limit
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-07-07 11:47:58 +02:00
b3d2fdc277 Merge pull request 'Another TCS fix' (#731) from another-tcs-fix into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #731
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-07 11:47:27 +02:00
7388c4f661 Merge remote-tracking branch 'origin/main' into tcs-heater-upper-limit
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-07-07 11:47:05 +02:00
a6461fcaf8 Merge remote-tracking branch 'origin/main' into another-tcs-fix
Some checks are pending
EIVE/eive-obsw/pipeline/pr-main Build queued...
2023-07-07 11:45:22 +02:00
6ae0fdf191 Merge pull request 'TCS CTRL bugfix' (#730) from tcs-ctrl-bugfix into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #730
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-07 11:44:38 +02:00
3087049726 Merge branch 'main' into tcs-ctrl-bugfix 2023-07-07 11:44:27 +02:00
8255869f2d Merge pull request 'Some TCS tweaks' (#729) from some-more-tcs-tweaks into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #729
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-07 11:44:08 +02:00
603ddcef9c Merge branch 'tcs-heater-upper-limit' into tcs-observability
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-07-07 11:14:42 +02:00
0b673fcdec Merge remote-tracking branch 'origin/main' into tcs-heater-upper-limit
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-07-07 11:07:35 +02:00
908cf8dcc3 Merge remote-tracking branch 'origin/main' into another-tcs-fix
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-07 11:03:20 +02:00
ec39dc05ae Merge remote-tracking branch 'origin/main' into tcs-ctrl-bugfix
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-07 11:02:43 +02:00
bd33a51bf1 Merge remote-tracking branch 'origin/main' into some-more-tcs-tweaks
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-07 11:00:45 +02:00
06a24da2b9 Merge pull request 'Add TCS CTRL heater events' (#728) from add-tcs-ctrl-heater-events into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #728
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-07 10:59:36 +02:00
2bad2a142b changelog
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-07 10:58:42 +02:00
b0b43b3ecc Merge branch 'main' into some-more-tcs-tweaks
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-07 10:56:50 +02:00
c1a23e0d73 Merge remote-tracking branch 'origin/main' into add-tcs-ctrl-heater-events
Some checks are pending
EIVE/eive-obsw/pipeline/pr-main Build queued...
2023-07-07 10:56:38 +02:00
377cc64d0f bump tmtc
Some checks are pending
EIVE/eive-obsw/pipeline/pr-main Build queued...
2023-07-07 10:55:39 +02:00
351c33e504 changelog
Some checks are pending
EIVE/eive-obsw/pipeline/pr-main Build queued...
2023-07-07 10:55:13 +02:00
a7a530cb59 Merge pull request 'More TMP1075 bugfixes' (#727) from more-tmp-bugfixes into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #727
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-07 10:53:07 +02:00
f1ca4b174f comment
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-06 23:07:54 +02:00
027955597f done 2023-07-06 23:06:50 +02:00
c558a117b0 some docs
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-06 22:21:00 +02:00
fc697732b4 Merge branch 'another-tcs-fix' into tcs-heater-upper-limit 2023-07-06 22:07:06 +02:00
ce19f30325 continue max heater duration 2023-07-06 22:06:54 +02:00
faffca0c2c compile fix
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-06 20:19:05 +02:00
7b611810df there are actually 8 heaters
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-06 20:13:33 +02:00
3e92d175d5 form fix
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-07-06 20:01:57 +02:00
64ca329d5a update changelog
Some checks failed
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-07-06 19:58:24 +02:00
12ff365433 TCS ctrl bugfix
Some checks failed
EIVE/eive-obsw/pipeline/head There was a failure building this commit
2023-07-06 19:57:23 +02:00
5ea3bfeb7b Merge branch 'main' into some-more-tcs-tweaks
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-06 19:12:01 +02:00
785c1c65a0 add new events
Some checks are pending
EIVE/eive-obsw/pipeline/head Build queued...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-06 19:01:49 +02:00
3c9eec7b3f heater events for TCS ctrl
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
2023-07-06 18:58:57 +02:00
5630ae4962 changelog
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-06 17:28:12 +02:00
61ea80f92c remove some cruft
Some checks are pending
EIVE/eive-obsw/pipeline/head Build queued...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-06 17:26:09 +02:00
6182218813 this works but is kind of ugly
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
2023-07-06 17:23:55 +02:00
b7e4953126 the TCS subsystem does not work on the EM..
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-07-06 16:00:39 +02:00
ee4285075a Merge pull request 'Swap PL and PS I2C' (#725) from swap-pl-ps-i2c into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #725
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-06 15:05:53 +02:00
bda2ba79bf Merge remote-tracking branch 'origin/main' into swap-pl-ps-i2c
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
make marius extremely happy
2023-07-06 14:34:12 +02:00
0c47513e98 Merge pull request 'set dataset invalid on OFF mode' (#726) from tmp-1075-set-sets-invalid into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #726
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-06 14:27:04 +02:00
f4f365b110 pool read guard
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-06 13:56:43 +02:00
1d4b815452 this is better to read..
Some checks are pending
EIVE/eive-obsw/pipeline/head This commit looks good
EIVE/eive-obsw/pipeline/pr-main Build queued...
2023-07-06 12:04:36 +02:00
1e98fcbbd5 that really should not cause issues though..
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-07-06 12:01:48 +02:00
52eba5cae6 small fix/tweaks
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-05 17:20:42 +02:00
cd9cb48b04 set dataset invalid on OFF mode
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-05 16:31:41 +02:00
5c430212e7 that should fix the host build
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-03 17:32:35 +02:00
d8ab6abc49 FM should build again
Some checks failed
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-07-03 17:16:51 +02:00
d1b9608a14 that should do the job
Some checks failed
EIVE/eive-obsw/pipeline/head There was a failure building this commit
2023-07-03 17:13:11 +02:00
25c7058da5 changelog
Some checks failed
EIVE/eive-obsw/pipeline/head There was a failure building this commit
2023-07-03 16:56:36 +02:00
9ece676313 lets see if this works 2023-07-03 16:55:45 +02:00
697a3e8577 Merge remote-tracking branch 'origin/main' into swap-pl-ps-i2c
Some checks failed
EIVE/eive-obsw/pipeline/head There was a failure building this commit
2023-07-03 16:34:04 +02:00
dea3077f29 changelog, prep v6.0.0
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-07-02 14:44:15 +02:00
d687715bcb Merge pull request 'v6.0.0' (#724) from main-v6 into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #724
2023-07-02 14:43:24 +02:00
e2cd822e9c Merge branch 'main' into main-v6
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-02 14:30:50 +02:00
0e9035d6c1 changelog, prep v5.2.0
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-07-02 14:21:35 +02:00
c80eff4922 Merge pull request 'EM ACS board' (#723) from add-back-em-acs-brd into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #723
2023-07-02 14:19:54 +02:00
a5c9e1481b changelog
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-02 14:04:29 +02:00
e19ddcfbd8 EM ACS board
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-02 14:02:37 +02:00
add079a7c6 Merge pull request 'Updates for new firmware' (#721) from complete-fw-tests into main-v6
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #721
2023-07-01 13:30:26 +02:00
9cdcd47b1a Merge remote-tracking branch 'origin/main-v6' into complete-fw-tests
All checks were successful
EIVE/eive-obsw/pipeline/pr-main-v6 This commit looks good
2023-06-30 10:45:16 +02:00
d14e256901 STR tests
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-29 16:40:21 +02:00
dd5270e974 Merge pull request 'Important bugfix for live channel' (#720) from live-channel-bugfix into main-v6
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #720
2023-06-29 16:39:09 +02:00
56ea9af615 add documentation of initial delay
All checks were successful
EIVE/eive-obsw/pipeline/pr-main-v6 This commit looks good
2023-06-29 15:06:25 +02:00
4fc999e102 changelog
All checks were successful
EIVE/eive-obsw/pipeline/pr-main-v6 This commit looks good
2023-06-29 15:03:45 +02:00
04d24e74b1 q7s-package version specification
All checks were successful
EIVE/eive-obsw/pipeline/pr-main-v6 This commit looks good
2023-06-29 15:01:54 +02:00
8137c9ea25 Merge remote-tracking branch 'origin/main-v6' into complete-fw-tests
All checks were successful
EIVE/eive-obsw/pipeline/pr-main-v6 This commit looks good
2023-06-29 15:00:49 +02:00
723b4bba3f Merge remote-tracking branch 'origin/main-v6' into live-channel-bugfix 2023-06-29 15:00:20 +02:00
8cff2fd6f7 Merge remote-tracking branch 'origin/main' into live-channel-bugfix 2023-06-29 15:00:11 +02:00
a1f7f77e01 Merge remote-tracking branch 'origin/main' into main-v6
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-06-29 14:59:18 +02:00
f3aab775f3 Merge pull request 'Core controller bugfix' (#719) from core-ctrl-init-bugfix into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #719
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-06-29 14:58:28 +02:00
59d542ab39 Merge remote-tracking branch 'origin/main' into core-ctrl-init-bugfix 2023-06-29 14:58:13 +02:00
7b0285c4ce Merge pull request 'Only reset PTME on rate change' (#716) from only-reset-ptme-on-rate-change into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #716
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-06-29 14:56:35 +02:00
0a77ee0508 Merge remote-tracking branch 'origin/main' into only-reset-ptme-on-rate-change
Some checks are pending
EIVE/eive-obsw/pipeline/pr-main Build queued...
2023-06-29 14:51:15 +02:00
51cbe46cf5 why indeed
Some checks are pending
EIVE/eive-obsw/pipeline/pr-main Build started...
2023-06-29 14:49:57 +02:00
26fc4b8add Merge pull request 'small fix for persistent TM store' (#722) from persistent-tm-stores-fixes into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #722
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-06-29 14:46:50 +02:00
825de04f3b changelog
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-29 10:15:36 +02:00
33985937b7 typo
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-29 09:44:09 +02:00
ba36b5f091 Merge branch 'main-v6' into live-channel-bugfix
All checks were successful
EIVE/eive-obsw/pipeline/pr-main-v6 This commit looks good
2023-06-29 08:55:09 +02:00
4f5903227e changelog
Some checks are pending
EIVE/eive-obsw/pipeline/pr-main-v6 Build queued...
2023-06-29 08:54:58 +02:00
2173d89047 changelog 2023-06-29 08:54:34 +02:00
0a12dbf2be changelog
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-29 08:53:08 +02:00
ad3c0e2a0e small fix for persistent TM store
Some checks are pending
EIVE/eive-obsw/pipeline/head Build queued...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-29 01:28:40 +02:00
03e772246f less cycles..
All checks were successful
EIVE/eive-obsw/pipeline/pr-main-v6 This commit looks good
2023-06-29 00:35:06 +02:00
25da131653 seems to work well
Some checks are pending
EIVE/eive-obsw/pipeline/head Build queued...
EIVE/eive-obsw/pipeline/pr-main-v6 This commit looks good
2023-06-29 00:33:58 +02:00
4c6b098f42 Merge branch 'live-channel-bugfix' into only-reset-ptme-on-rate-change-v6
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-06-28 17:49:06 +02:00
b57283101b important bugfix for live channel
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-28 17:46:21 +02:00
9dfdf38822 important bugfix for live channel
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-06-28 17:20:10 +02:00
c6240285e2 Merge branch 'core-ctrl-init-bugfix' into only-reset-ptme-on-rate-change-v6
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-06-28 15:51:48 +02:00
87c05705ec core ctrl bugfix
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-28 15:43:44 +02:00
c881b36630 prevent warning
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-06-28 15:28:27 +02:00
a380ff5ac9 Merge branch 'main-v6' into only-reset-ptme-on-rate-change-v6
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-06-28 15:24:20 +02:00
4d17184fba Merge remote-tracking branch 'origin/main' into only-reset-ptme-on-rate-change
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-28 15:18:05 +02:00
d8efd05a88 Merge branch 'main' into main-v6
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-06-28 15:08:38 +02:00
109856eef8 Merge pull request 'prep v5.1.0' (#718) from prep_v5.1.0 into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #718
2023-06-28 13:57:04 +02:00
90bafa717b prep v5.1.0
Some checks are pending
EIVE/eive-obsw/pipeline/head Build queued...
EIVE/eive-obsw/pipeline/pr-main Build started...
2023-06-28 13:41:51 +02:00
0cdb850f69 Merge pull request 'Seq Count Persistent + MSG type counter' (#711) from sequence-counter-persistent-msg-type-count-support into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #711
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-06-28 13:37:14 +02:00
4c63fed69d that is annoying
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-28 13:35:38 +02:00
eb27ab4bb0 fix and optimization
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-28 13:32:35 +02:00
b0a38136c1 Merge remote-tracking branch 'origin/main' into only-reset-ptme-on-rate-change 2023-06-28 13:28:00 +02:00
6c2548fb56 Merge branch 'main' into sequence-counter-persistent-msg-type-count-support
Some checks are pending
EIVE/eive-obsw/pipeline/pr-main Build started...
2023-06-28 13:26:55 +02:00
7d3f9ada18 Merge pull request 'higher rx set rate during pass' (#715) from rx-dataset-higher-rate-during-pass into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #715
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-06-28 13:26:42 +02:00
b5cc430b5b Merge remote-tracking branch 'origin/main' into only-reset-ptme-on-rate-change
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-06-28 13:21:33 +02:00
52fedb94e8 bump fsfw and tmtc
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-28 13:20:50 +02:00
cdabf113ca Merge remote-tracking branch 'origin/main' into rx-dataset-higher-rate-during-pass
Some checks are pending
EIVE/eive-obsw/pipeline/pr-main Build started...
2023-06-28 13:18:45 +02:00
c3e66f5320 changelogge
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-28 13:18:00 +02:00
2d2c1d8721 Merge branch 'main' into sequence-counter-persistent-msg-type-count-support
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-28 10:07:51 +02:00
9e8a417115 Merge pull request 'various improvements for heater handler' (#717) from only-one-heater-cmd-at-a-time into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #717
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-06-28 10:01:20 +02:00
fba87cc0e8 changelog typos
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-27 18:09:38 +02:00
50a8a6fffe more changelog
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-27 18:02:49 +02:00
1e767afa11 only handle one message per cycle 2023-06-27 17:55:49 +02:00
15a67b81f9 various improvements
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-27 17:36:52 +02:00
bf25266055 Merge branch 'main' into rx-dataset-higher-rate-during-pass
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-27 11:05:56 +02:00
ef08f348dc Merge remote-tracking branch 'origin/main' into sequence-counter-persistent-msg-type-count-support
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-26 18:26:08 +02:00
47ff8a418e Merge pull request 'Internal Error Reporter Set' (#702) from internal-error-reporter-set into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #702
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-06-26 18:25:13 +02:00
f0fbed1593 Merge remote-tracking branch 'origin/main' into internal-error-reporter-set
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-26 18:13:44 +02:00
8b2bf21025 Merge remote-tracking branch 'origin/main' into sequence-counter-persistent-msg-type-count-support
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-06-26 18:12:45 +02:00
0764646d2b Merge pull request 'Ordered dumps' (#706) from ordered-dumps into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #706
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-06-26 18:11:07 +02:00
e752cdcc67 bump fsfw
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-26 18:10:41 +02:00
91c53df2c9 Merge remote-tracking branch 'origin/main' into internal-error-reporter-set
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-26 18:03:06 +02:00
c6231d2337 Merge remote-tracking branch 'origin/main' into sequence-counter-persistent-msg-type-count-support
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-26 17:59:26 +02:00
0dfe68eb8d Merge remote-tracking branch 'origin/main' into ordered-dumps
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-26 17:57:26 +02:00
27f77799a6 bump major version
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-06-26 17:33:17 +02:00
9080e7cbe4 Merge branch 'v5.0.0-dev' into main-v6 2023-06-26 17:33:01 +02:00
6c39e7dd0c and go back to newest version here
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-06-26 17:08:39 +02:00
1703f7a714 Merge remote-tracking branch 'origin/main' into internal-error-reporter-set
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-26 15:36:23 +02:00
13bb572348 Merge remote-tracking branch 'origin/main' into sequence-counter-persistent-msg-type-count-support
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-26 15:35:22 +02:00
3e21f9c259 Merge remote-tracking branch 'origin/main' into ordered-dumps
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-26 15:34:58 +02:00
fca6834d17 higher rx set rate during pass
Some checks are pending
EIVE/eive-obsw/pipeline/head This commit looks good
EIVE/eive-obsw/pipeline/pr-main Build queued...
2023-06-26 15:32:52 +02:00
1cc62238c2 only reset PTME on rate change init
Some checks failed
EIVE/eive-obsw/pipeline/head There was a failure building this commit
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-06-26 14:39:03 +02:00
05a5c63765 changelog
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-26 11:20:33 +02:00
c806aa81f0 what does the new compiler want?
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-26 11:14:11 +02:00
93fb207032 C++ insanity..
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-06-25 13:12:39 +02:00
80160e8291 that was hopefully the last set of fixes
Some checks failed
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-06-25 13:07:31 +02:00
5a15d39a1d important order bugfix
Some checks failed
EIVE/eive-obsw/pipeline/head There was a failure building this commit
2023-06-25 12:49:51 +02:00
e036ed2bff now its complete
Some checks failed
EIVE/eive-obsw/pipeline/head There was a failure building this commit
2023-06-25 12:47:28 +02:00
0db7b5251c Merge branch 'total-boot-counter-file' into sequence-counter-persistent-msg-type-count-support
Some checks failed
EIVE/eive-obsw/pipeline/head There was a failure building this commit
2023-06-25 12:45:34 +02:00
873316d012 sequence counter isn ow persistent, msg type count support 2023-06-25 12:41:20 +02:00
0f818a5596 Merge remote-tracking branch 'origin/main' into internal-error-reporter-set
All checks were successful
EIVE/eive-obsw/pipeline/pr-v4.1.0-dev This commit looks good
2023-06-25 11:12:10 +02:00
8b13337845 Merge branch 'ordered-dumps' of https://egit.irs.uni-stuttgart.de/eive/eive-obsw into ordered-dumps
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-25 11:07:47 +02:00
76933671a6 changelog 2023-06-25 11:07:41 +02:00
491a341efe Merge branch 'main' into ordered-dumps
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-25 11:06:24 +02:00
b4778f3ce9 Merge remote-tracking branch 'origin/main' into ordered-dumps
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-24 21:01:35 +02:00
c50a74d117 delete ordering 2023-06-24 21:00:57 +02:00
25d10e3877 that was all the fixes (hopefully) 2023-06-24 20:57:54 +02:00
04f4eedb78 that should make it work
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-24 12:01:12 +02:00
53b48ad99b this is tricky
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-06-24 11:46:56 +02:00
a8ab40674f seems to work well
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-24 11:08:50 +02:00
18b67d18a7 seems to work now
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-06-24 02:07:11 +02:00
97d41a125b Merge remote-tracking branch 'origin/main' into ordered-dumps
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-06-24 01:24:24 +02:00
2e041c3013 some more fixes
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-06-23 17:07:07 +02:00
9023405b96 some fxes
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-06-23 16:05:38 +02:00
1d047f3c92 implement ordered sets
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-06-23 14:55:51 +02:00
253af8193f fix unittest
All checks were successful
EIVE/eive-obsw/pipeline/pr-v4.1.0-dev This commit looks good
2023-06-22 18:43:04 +02:00
3d07814efb Merge remote-tracking branch 'origin/main' into internal-error-reporter-set
Some checks failed
EIVE/eive-obsw/pipeline/pr-v4.1.0-dev There was a failure building this commit
2023-06-22 18:39:34 +02:00
32b074b86e that should fix the build
Some checks failed
EIVE/eive-obsw/pipeline/pr-v4.1.0-dev There was a failure building this commit
2023-06-22 16:29:52 +02:00
461782acdb Merge branch 'v4.0.0-dev' into internal-error-reporter-set
Some checks failed
EIVE/eive-obsw/pipeline/pr-v4.0.0-dev There was a failure building this commit
2023-06-22 16:11:33 +02:00
74e945ddff changelog
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
2023-06-22 16:10:07 +02:00
a3b140b680 internal error reporter extension 2023-06-22 16:09:24 +02:00
df4e657ec3 create TCS CTRL TMP1075 PLCDU 1 se tdynamically
Some checks failed
EIVE/eive-obsw/pipeline/head There was a failure building this commit
2023-06-18 17:36:50 +02:00
8f7d3dd815 changelog
Some checks failed
EIVE/eive-obsw/pipeline/head There was a failure building this commit
2023-06-18 17:24:19 +02:00
97268af555 another tmp FDIR fix
Some checks failed
EIVE/eive-obsw/pipeline/head There was a failure building this commit
2023-06-18 17:11:38 +02:00
322151acf8 tmp fdir bugfix: use strange reply counter 2023-06-18 16:34:07 +02:00
ecb8de1550 need to verify some things here later.. 2023-06-18 16:23:08 +02:00
0cd5526de4 always add TMP devs now 2023-06-18 14:19:19 +02:00
07bb293816 tmp1075 workssssss
Some checks failed
EIVE/eive-obsw/pipeline/head There was a failure building this commit
2023-06-18 13:38:00 +02:00
727050520b that should do the job
Some checks failed
EIVE/eive-obsw/pipeline/head There was a failure building this commit
2023-06-17 17:24:51 +02:00
269d5f6a0a stupid tmps 2023-06-17 17:01:01 +02:00
d6dd943ebf tmp is back in the house
Some checks failed
EIVE/eive-obsw/pipeline/head There was a failure building this commit
2023-06-17 15:28:05 +02:00
31fdbac8c0 Merge remote-tracking branch 'origin/main' into swap-pl-ps-i2c 2023-06-17 14:29:38 +02:00
3e9accfa7b Merge remote-tracking branch 'origin/v4.0.0-dev' into swap-pl-ps-i2c
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-06-16 16:52:05 +02:00
1b919ceaec swap i2cs
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-06-16 13:54:50 +02:00
82 changed files with 1636 additions and 907 deletions

View File

@ -16,11 +16,103 @@ will consitute of a breaking change warranting a new major release:
# [unreleased]
# [v6.0.0] to be released
# [v6.1.0] 2023-07-13
- `eive-tmtc`: v5.2.0
## Changed
- TCS: Remove OBC IF board thermal module, which is exactly identical to OBC module and therefore
obsolete.
- Swapped PL and PS I2C, BPX battery and MGT are connected to PS I2C now for firmware versions
equal or above v4. However, this software version is compatible to both v3 and v4 of the firmware.
- The firmware version variables are global statics inititalized early during the program
runtime now. This makes it possible to check the firmware version earlier.
- The TCS controller will now always command heaters OFF when being blind for thermal
components (no sensors available), irrespective of current switch state.
- Make OBSW compatible to prospective FW version v5.0.0, where the Q7 I2C devices were
moved to a PL I2C block and the TMP sensor devices were moved to the PS I2C0.
- Made `Xadc` code a little bit more robust against errors.
## Fixed
- TMP1075: Set dataset invalid on shutdown explicitely
- Small fixes for TMP1075 FDIR: Use strange and missed reply counters.
- TCS controller: Last heater (S-band heater) was skipped for transition completion
checks.
- TCS controller: A helper member to track the elapsed heater control cycles was not reset
properly, which could lead to switch transitions being completed immediately. This can
lead to weird bugs like heaters being commanded ON twice and can potentially lead to
other bugs.
- TMP1075: Devices did not go to OFF mode when being set faulty.
- Update PL PCDU 1 in TCS mode tree on the EM.
- TMP1075: Possibly ignored health commands.
- Bugfix in FSFW where certain packet types could only be sent with source data fields with a
maximum size of 255 bytes.
- TCS CTRL: Limit number of heater handler messages sent in case there are not sensors available
anymore.
- Fix to allow adding real STR device for EM.
# Added
- Two events for heaters being commanded ON and OFF by the TCS controller
- Upper limit for burn time of TCS heaters. Currently set to 1 hour for each heater.
This mechanism will only track the burn time for heaters which were commanded by the
TCS controller.
- TCS controller is now observable by introducing a new HK dataset which exposes some internal
fields related to TCS control.
# [v6.0.0] 2023-07-02
- `q7s-package` version v3.2.0
- Important bugfixes for PTME. See `q7s-package` CHANGELOG.
# [v5.1.0] to be released
## Changed
- Added back PTME busy bit polling. This is necessary due to changes to the AXI APB interface
to the PTME core.
## Fixed
- For the live channel (VC0), telemetry was still only dumped if the transmitter is active.
Please note that this fix will lead to crashes for FW versions below v3.2.
However, it might not be an issue for the oldest firmware on the satellite (v2.5.1).
# [v5.2.0] 2023-07-02
## Fixed
- The firmware information event was not triggered even when possible because of an ordering
bug in the initializer function.
- Empty dumps (no TM in time range) will now correctly be completed immediately
## Changed
- PTME was always reset on submode changes. The reset will now only be performed if the actual data
rate changes.
- Add back ACS board code for the EM. Now that the radiation sensor was removed, the image switching
issue has disappeared and adding back the ACS board is worth it for the GPS timekeeping.
# [v5.1.0] 2023-06-28
- `eive-tmtc` version v5.1.0
## Changed
- Persistent TM store dumps are now performed in chronological order.
- Increase Syrlinks RX HK rate to 5.0 seconds during a pass.
- Various robustness improvements for the heater handler. The heater handler will now only
process the command queue if it is not busy with switch commanding which reduces the amount
of possible bugs.
- The heater handler is only able to process messages stricly sequentially now but is scheduled
twice in a 0.5 second slot so something like a consecutive heater ON or OFF command can still
be handled relatively quickly.
## Added
- Sequence counters for PUS and CFDP packets are now stored persistently across graceful reboots.
- The PUS packet message type counter will now be incremented properly for each PUS service.
- Internal error reporter set is now enabled by default and generated every 120 seconds.
# [v5.0.0] 2023-06-26

View File

@ -9,8 +9,8 @@
# ##############################################################################
cmake_minimum_required(VERSION 3.13)
set(OBSW_VERSION_MAJOR 5)
set(OBSW_VERSION_MINOR 0)
set(OBSW_VERSION_MAJOR 6)
set(OBSW_VERSION_MINOR 1)
set(OBSW_VERSION_REVISION 0)
# set(CMAKE_VERBOSE TRUE)
@ -105,7 +105,7 @@ set(OBSW_ADD_THERMAL_TEMP_INSERTER
${OBSW_Q7S_EM}
CACHE STRING "Add thermal sensor temperature inserter")
set(OBSW_ADD_ACS_BOARD
${INIT_VAL}
1
CACHE STRING "Add ACS board module")
set(OBSW_ADD_GPS_CTRL
${INIT_VAL}
@ -150,7 +150,7 @@ set(OBSW_ADD_SYRLINKS
1
CACHE STRING "Add Syrlinks module")
set(OBSW_ADD_TMP_DEVICES
${INIT_VAL}
1
CACHE STRING "Add TMP devices")
set(OBSW_ADD_GOMSPACE_PCDU
1

View File

@ -964,6 +964,12 @@ used by other software components to read the current chip and copy.
This is a configuration scripts which runs after the Network Time Protocol has run. This script
currently sets the static IP address `192.168.133.10` and starts the `can` interface.
## Initial boot delay
You can create a file named `boot_delays_secs.txt` inside the home folder to delay the OBSW boot
for 6 seconds if the file is empty of for the number of seconds specified inside the file. This
can be helpful if something inside the OBSW leads to an immediate crash of the OBC.
## PCDU
Connect to serial console of P60 Dock

View File

@ -68,7 +68,7 @@ void ObjectFactory::produce(void* args) {
#endif
auto sdcMan = new DummySdCardManager("/tmp");
ObjectFactory::produceGenericObjects(nullptr, &pusFunnel, &cfdpFunnel, *sdcMan, &ipcStore,
&tmStore, persistentStores, 120);
&tmStore, persistentStores, 120, enableHkSets);
new TmFunnelHandler(objects::LIVE_TM_TASK, *pusFunnel, *cfdpFunnel);
auto* dummyGpioIF = new DummyGpioIF();
@ -113,7 +113,7 @@ void ObjectFactory::produce(void* args) {
if (heaterHandler == nullptr) {
sif::error << "HeaterHandler could not be created" << std::endl;
} else {
ObjectFactory::createThermalController(*heaterHandler);
ObjectFactory::createThermalController(*heaterHandler, true);
}
new TestTask(objects::TEST_TASK);
}

View File

@ -1,7 +1,7 @@
/**
* @brief Auto-generated event translation file. Contains 296 translations.
* @brief Auto-generated event translation file. Contains 299 translations.
* @details
* Generated on: 2023-06-21 19:01:02
* Generated on: 2023-07-07 12:06:06
*/
#include "translateEvents.h"
@ -286,6 +286,9 @@ const char *CAMERA_OVERHEATING_STRING = "CAMERA_OVERHEATING";
const char *PCDU_SYSTEM_OVERHEATING_STRING = "PCDU_SYSTEM_OVERHEATING";
const char *HEATER_NOT_OFF_FOR_OFF_MODE_STRING = "HEATER_NOT_OFF_FOR_OFF_MODE";
const char *MGT_OVERHEATING_STRING = "MGT_OVERHEATING";
const char *TCS_SWITCHING_HEATER_ON_STRING = "TCS_SWITCHING_HEATER_ON";
const char *TCS_SWITCHING_HEATER_OFF_STRING = "TCS_SWITCHING_HEATER_OFF";
const char *TCS_HEATER_MAX_BURN_TIME_REACHED_STRING = "TCS_HEATER_MAX_BURN_TIME_REACHED";
const char *TX_TIMER_EXPIRED_STRING = "TX_TIMER_EXPIRED";
const char *BIT_LOCK_TX_ON_STRING = "BIT_LOCK_TX_ON";
const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION";
@ -866,6 +869,12 @@ const char *translateEvents(Event event) {
return HEATER_NOT_OFF_FOR_OFF_MODE_STRING;
case (14108):
return MGT_OVERHEATING_STRING;
case (14109):
return TCS_SWITCHING_HEATER_ON_STRING;
case (14110):
return TCS_SWITCHING_HEATER_OFF_STRING;
case (14111):
return TCS_HEATER_MAX_BURN_TIME_REACHED_STRING;
case (14201):
return TX_TIMER_EXPIRED_STRING;
case (14202):

View File

@ -2,7 +2,7 @@
* @brief Auto-generated object translation file.
* @details
* Contains 171 translations.
* Generated on: 2023-06-21 19:01:02
* Generated on: 2023-07-07 12:06:06
*/
#include "translateObjects.h"

View File

@ -7,7 +7,8 @@ target_link_libraries(${SIMPLE_OBSW_NAME} PUBLIC ${LIB_FSFW_NAME})
target_compile_definitions(${SIMPLE_OBSW_NAME} PRIVATE "Q7S_SIMPLE_MODE")
add_subdirectory(simple)
target_sources(${OBSW_NAME} PUBLIC main.cpp obsw.cpp)
target_sources(${OBSW_NAME} PUBLIC main.cpp obsw.cpp scheduling.cpp
objectFactory.cpp)
add_subdirectory(boardtest)

View File

@ -12,6 +12,9 @@ static constexpr char SPI_RW_DEV[] = "/dev/spi_rw";
static constexpr char I2C_PL_EIVE[] = "/dev/i2c_pl";
//! I2C bus using the I2C peripheral of the ARM processing system (PS)
static constexpr char I2C_PS_EIVE[] = "/dev/i2c_ps";
//! I2C bus using the first I2C peripheral of the ARM processing system (PS).
//! Named like this because it is used by default for the Q7 devices.
static constexpr char I2C_Q7_EIVE[] = "/dev/i2c_q7";
static constexpr char UART_GNSS_DEV[] = "/dev/gps0";
static constexpr char UART_PLOC_MPSOC_DEV[] = "/dev/ul_plmpsoc";
@ -85,13 +88,9 @@ static constexpr char EN_RW_4[] = "enable_rw_4";
static constexpr char RAD_SENSOR_CHIP_SELECT[] = "rad_sensor_chip_select";
static constexpr char ENABLE_RADFET[] = "enable_radfet";
static constexpr char PAPB_BUSY_SIGNAL_VC0[] = "papb_busy_signal_vc0";
static constexpr char PAPB_EMPTY_SIGNAL_VC0[] = "papb_empty_signal_vc0";
static constexpr char PAPB_BUSY_SIGNAL_VC1[] = "papb_busy_signal_vc1";
static constexpr char PAPB_EMPTY_SIGNAL_VC1[] = "papb_empty_signal_vc1";
static constexpr char PAPB_BUSY_SIGNAL_VC2[] = "papb_busy_signal_vc2";
static constexpr char PAPB_EMPTY_SIGNAL_VC2[] = "papb_empty_signal_vc2";
static constexpr char PAPB_BUSY_SIGNAL_VC3[] = "papb_busy_signal_vc3";
static constexpr char PAPB_EMPTY_SIGNAL_VC3[] = "papb_empty_signal_vc3";
static constexpr char PTME_RESETN[] = "ptme_resetn";

View File

@ -1,4 +1 @@
target_sources(${OBSW_NAME} PRIVATE CoreController.cpp scheduling.cpp
ObjectFactory.cpp WatchdogHandler.cpp)
target_sources(${SIMPLE_OBSW_NAME} PRIVATE scheduling.cpp)
target_sources(${OBSW_NAME} PRIVATE CoreController.cpp WatchdogHandler.cpp)

View File

@ -170,9 +170,6 @@ ReturnValue_t CoreController::initialize() {
sdStateMachine();
triggerEvent(core::REBOOT_SW, CURRENT_CHIP, CURRENT_COPY);
announceCurrentImageInfo();
announceVersionInfo();
EventManagerIF *eventManager =
ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER);
if (eventManager == nullptr or eventQueue == nullptr) {
@ -189,17 +186,11 @@ ReturnValue_t CoreController::initialize() {
if (result != returnvalue::OK) {
sif::warning << "Subscribing for GPS GPS_FIX_CHANGE event failed" << std::endl;
}
triggerEvent(core::REBOOT_SW, CURRENT_CHIP, CURRENT_COPY);
announceCurrentImageInfo();
announceVersionInfo();
if (common::OBSW_VERSION_MAJOR >= 6 or common::OBSW_VERSION_MAJOR == 4) {
UioMapper sysRomMapper(q7s::UIO_SYS_ROM);
result = sysRomMapper.getMappedAdress(&mappedSysRomAddr, UioMapper::Permissions::READ_ONLY);
if (result != returnvalue::OK) {
// TODO: This might be a reason to switch to another image..
sif::error << "Getting mapped SYS ROM UIO address failed" << std::endl;
return ObjectManager::CHILD_INIT_FAILED;
}
}
return returnvalue::OK;
return result;
}
ReturnValue_t CoreController::initializeAfterTaskCreation() {
@ -1224,6 +1215,10 @@ ReturnValue_t CoreController::actionReboot(const uint8_t *data, size_t size) {
ReturnValue_t CoreController::gracefulShutdownTasks(xsc::Chip chip, xsc::Copy copy,
bool &protOpPerformed) {
// Store both sequence counters persistently.
core::SAVE_CFDP_SEQUENCE_COUNT = true;
core::SAVE_PUS_SEQUENCE_COUNT = true;
sdcMan->setBlocking(true);
sdcMan->markUnusable();
// Wait two seconds to ensure no one uses the SD cards
@ -2520,14 +2515,10 @@ void CoreController::announceVersionInfo() {
}
triggerEvent(VERSION_INFO, p1, p2);
if (common::OBSW_VERSION_MAJOR >= 6 or common::OBSW_VERSION_MAJOR == 4) {
if (mappedSysRomAddr != nullptr) {
uint32_t p1Firmware = *(reinterpret_cast<uint32_t *>(mappedSysRomAddr));
uint32_t p2Firmware = *(reinterpret_cast<uint32_t *>(mappedSysRomAddr) + 1);
triggerEvent(FIRMWARE_INFO, p1Firmware, p2Firmware);
}
}
p1 = (core::FW_VERSION_MAJOR << 24) | (core::FW_VERSION_MINOR << 16) |
(core::FW_VERSION_REVISION << 8) | (core::FW_VERSION_HAS_SHA);
std::memcpy(&p2, core::FW_VERSION_GIT_SHA, 4);
triggerEvent(FIRMWARE_INFO, p1, p2);
}
void CoreController::announceCurrentImageInfo() {

View File

@ -1,6 +1,7 @@
#ifndef BSP_Q7S_CORE_CORECONTROLLER_H_
#define BSP_Q7S_CORE_CORECONTROLLER_H_
#include <bsp_q7s/core/defs.h>
#include <fsfw/container/DynamicFIFO.h>
#include <fsfw/container/SimpleRingBuffer.h>
#include <fsfw/globalfunctions/PeriodicOperationDivider.h>
@ -14,7 +15,6 @@
#include <atomic>
#include <cstddef>
#include "CoreDefinitions.h"
#include "OBSWConfig.h"
#include "bsp_q7s/fs/SdCardManager.h"
#include "events/subsystemIdRanges.h"

View File

@ -1,10 +1,16 @@
#ifndef BSP_Q7S_CORE_COREDEFINITIONS_H_
#define BSP_Q7S_CORE_COREDEFINITIONS_H_
#ifndef BSP_Q7S_CORE_DEFS_H_
#define BSP_Q7S_CORE_DEFS_H_
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
namespace core {
extern uint8_t FW_VERSION_MAJOR;
extern uint8_t FW_VERSION_MINOR;
extern uint8_t FW_VERSION_REVISION;
extern bool FW_VERSION_HAS_SHA;
extern char FW_VERSION_GIT_SHA[4];
static const uint8_t HK_SET_ENTRIES = 3;
static const uint32_t HK_SET_ID = 5;
@ -36,4 +42,4 @@ class HkSet : public StaticLocalDataSet<HK_SET_ENTRIES> {
} // namespace core
#endif /* BSP_Q7S_CORE_COREDEFINITIONS_H_ */
#endif /* BSP_Q7S_CORE_DEFS_H_ */

View File

@ -1,4 +1,5 @@
#include <bsp_q7s/callbacks/q7sGpioCallbacks.h>
#include <bsp_q7s/objectFactory.h>
#include <dummies/ComCookieDummy.h>
#include <dummies/PcduHandlerDummy.h>
#include <fsfw/health/HealthTableIF.h>
@ -10,8 +11,8 @@
#include "OBSWConfig.h"
#include "bsp_q7s/core/CoreController.h"
#include "bsp_q7s/core/ObjectFactory.h"
#include "busConf.h"
#include "common/config/devices/addresses.h"
#include "devConf.h"
#include "dummies/helperFactory.h"
#include "eive/objects.h"
@ -35,16 +36,17 @@ void ObjectFactory::produce(void* args) {
#endif
PersistentTmStores stores;
readFirmwareVersion();
ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel,
*SdCardManager::instance(), &ipcStore, &tmStore, stores,
200);
*SdCardManager::instance(), &ipcStore, &tmStore, stores, 200,
enableHkSets);
LinuxLibgpioIF* gpioComIF = nullptr;
SerialComIF* uartComIF = nullptr;
SpiComIF* spiMainComIF = nullptr;
I2cComIF* i2cComIF = nullptr;
createCommunicationInterfaces(&gpioComIF, &uartComIF, &spiMainComIF, &i2cComIF);
/* Adding gpios for chip select decoding to the gpioComIf */
// Adding GPIOs for chip select decoding and initializing them.
q7s::gpioCallbacks::initSpiCsDecoder(gpioComIF);
gpioCallbacks::disableAllDecoder(gpioComIF);
createPlI2cResetGpio(gpioComIF);
@ -60,11 +62,29 @@ void ObjectFactory::produce(void* args) {
#if OBSW_ADD_PLOC_SUPERVISOR == 1 || OBSW_ADD_PLOC_MPSOC == 1
dummyCfg.addPlocDummies = false;
#endif
#if OBSW_ADD_TMP_DEVICES == 1
std::vector<std::pair<object_id_t, address_t>> tmpDevsToAdd = {{
{objects::TMP1075_HANDLER_PLPCDU_0, addresses::TMP1075_PLPCDU_0},
{objects::TMP1075_HANDLER_PLPCDU_1, addresses::TMP1075_PLPCDU_1},
{objects::TMP1075_HANDLER_IF_BOARD, addresses::TMP1075_IF_BOARD},
}};
createTmpComponents(tmpDevsToAdd);
dummy::Tmp1075Cfg tmpCfg{};
tmpCfg.addTcsBrd0 = true;
tmpCfg.addTcsBrd1 = true;
tmpCfg.addPlPcdu0 = false;
tmpCfg.addPlPcdu1 = false;
tmpCfg.addIfBrd = false;
dummyCfg.tmp1075Cfg = tmpCfg;
#endif
#if OBSW_ADD_GOMSPACE_PCDU == 1
dummyCfg.addPowerDummies = false;
// The ACU broke.
dummyCfg.addOnlyAcuDummy = true;
#endif
#if OBSW_ADD_STAR_TRACKER == 1
dummyCfg.addStrDummy = false;
#endif
#if OBSW_ADD_BPX_BATTERY_HANDLER == 1
dummyCfg.addBpxBattDummy = false;
#endif
@ -84,9 +104,10 @@ void ObjectFactory::produce(void* args) {
new CoreController(objects::CORE_CONTROLLER, enableHkSets);
#if OBSW_ADD_ACS_BOARD == 1
// Still initialize chip select to avoid SPI bus issues.
// Initialize chip select to avoid SPI bus issues.
createRadSensorChipSelect(gpioComIF);
#if OBSW_ADD_ACS_BOARD == 1
createAcsBoardComponents(*spiMainComIF, gpioComIF, uartComIF, *pwrSwitcher, true,
adis1650x::Type::ADIS16507);
#else
@ -96,8 +117,12 @@ void ObjectFactory::produce(void* args) {
gpioChecker(gpioComIF->addGpios(acsBoardGpios), "ACS Board");
#endif
const char* battAndImtqI2cDev = q7s::I2C_PL_EIVE;
if (core::FW_VERSION_MAJOR >= 4) {
battAndImtqI2cDev = q7s::I2C_PS_EIVE;
}
#if OBSW_ADD_MGT == 1
createImtqComponents(pwrSwitcher, enableHkSets);
createImtqComponents(pwrSwitcher, enableHkSets, battAndImtqI2cDev);
#endif
#if OBSW_ADD_SYRLINKS == 1
@ -109,7 +134,7 @@ void ObjectFactory::produce(void* args) {
#endif
#if OBSW_ADD_BPX_BATTERY_HANDLER == 1
createBpxBatteryComponent(enableHkSets);
createBpxBatteryComponent(enableHkSets, battAndImtqI2cDev);
#endif
#if OBSW_ADD_STAR_TRACKER == 1
@ -141,6 +166,6 @@ void ObjectFactory::produce(void* args) {
createAcsController(true, enableHkSets);
HeaterHandler* heaterHandler;
createHeaterComponents(gpioComIF, pwrSwitcher, healthTable, heaterHandler);
createThermalController(*heaterHandler);
satsystem::init();
createThermalController(*heaterHandler, true);
satsystem::init(true);
}

View File

@ -1,4 +1,5 @@
#include <bsp_q7s/callbacks/q7sGpioCallbacks.h>
#include <bsp_q7s/objectFactory.h>
#include <devices/gpioIds.h>
#include <fsfw/storagemanager/LocalPool.h>
#include <fsfw/storagemanager/PoolManager.h>
@ -7,9 +8,9 @@
#include "OBSWConfig.h"
#include "bsp_q7s/core/CoreController.h"
#include "bsp_q7s/core/ObjectFactory.h"
#include "busConf.h"
#include "devConf.h"
#include "devices/addresses.h"
#include "eive/objects.h"
#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h"
#include "linux/ObjectFactory.h"
@ -32,9 +33,10 @@ void ObjectFactory::produce(void* args) {
#endif
PersistentTmStores stores;
readFirmwareVersion();
ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel,
*SdCardManager::instance(), &ipcStore, &tmStore, stores,
200);
*SdCardManager::instance(), &ipcStore, &tmStore, stores, 200,
true);
LinuxLibgpioIF* gpioComIF = nullptr;
SerialComIF* uartComIF = nullptr;
@ -67,7 +69,16 @@ void ObjectFactory::produce(void* args) {
HeaterHandler* heaterHandler;
createHeaterComponents(gpioComIF, pwrSwitcher, healthTable, heaterHandler);
#if OBSW_ADD_TMP_DEVICES == 1
createTmpComponents();
std::vector<std::pair<object_id_t, address_t>> tmpDevsToAdd = {{
{objects::TMP1075_HANDLER_TCS_0, addresses::TMP1075_TCS_0},
{objects::TMP1075_HANDLER_TCS_1, addresses::TMP1075_TCS_1},
{objects::TMP1075_HANDLER_PLPCDU_0, addresses::TMP1075_PLPCDU_0},
// damaged
// {objects::TMP1075_HANDLER_PLPCDU_1, addresses::TMP1075_PLPCDU_1},
{objects::TMP1075_HANDLER_IF_BOARD, addresses::TMP1075_IF_BOARD},
}};
createTmpComponents(tmpDevsToAdd);
#endif
createSolarArrayDeploymentComponents(*pwrSwitcher, *gpioComIF);
createPlPcduComponents(gpioComIF, spiMainComIF, pwrSwitcher, *stackHandler);
@ -77,13 +88,17 @@ void ObjectFactory::produce(void* args) {
createRtdComponents(q7s::SPI_DEFAULT_DEV, gpioComIF, pwrSwitcher, spiMainComIF);
createPayloadComponents(gpioComIF, *pwrSwitcher);
const char* battAndImtqI2cDev = q7s::I2C_PL_EIVE;
if (core::FW_VERSION_MAJOR >= 4) {
battAndImtqI2cDev = q7s::I2C_PS_EIVE;
}
#if OBSW_ADD_MGT == 1
createImtqComponents(pwrSwitcher, enableHkSets);
createImtqComponents(pwrSwitcher, enableHkSets, battAndImtqI2cDev);
#endif
createReactionWheelComponents(gpioComIF, pwrSwitcher);
#if OBSW_ADD_BPX_BATTERY_HANDLER == 1
createBpxBatteryComponent(enableHkSets);
createBpxBatteryComponent(enableHkSets, battAndImtqI2cDev);
#endif
#if OBSW_ADD_STAR_TRACKER == 1
@ -113,7 +128,7 @@ void ObjectFactory::produce(void* args) {
#endif /* OBSW_ADD_TEST_CODE == 1 */
createMiscComponents();
createThermalController(*heaterHandler);
createThermalController(*heaterHandler, false);
createAcsController(true, enableHkSets);
satsystem::init();
satsystem::init(false);
}

View File

@ -1,8 +1,9 @@
#include "ObjectFactory.h"
#include "objectFactory.h"
#include <fsfw/devicehandlers/HealthDevice.h>
#include <fsfw/subsystem/Subsystem.h>
#include <fsfw/tasks/TaskFactory.h>
#include <fsfw_hal/linux/uio/UioMapper.h>
#include <linux/acs/AcsBoardPolling.h>
#include <linux/acs/GpsHyperionLinuxController.h>
#include <linux/acs/ImtqPollingTask.h>
@ -32,6 +33,9 @@
#include <mission/system/objects/CamSwitcher.h>
#include <mission/system/tcs/TmpDevFdir.h>
#include <cstdint>
#include <cstring>
#include "OBSWConfig.h"
#include "bsp_q7s/boardtest/Q7STestTask.h"
#include "bsp_q7s/callbacks/gnssCallback.h"
@ -100,6 +104,7 @@
#include <sstream>
#include "bsp_q7s/core/defs.h"
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
#include "fsfw/tmtcpacket/pus/tm.h"
#include "fsfw/tmtcservices/CommandingServiceBase.h"
@ -130,6 +135,11 @@ ResetArgs RESET_ARGS_GNSS;
std::atomic_bool LINK_STATE = CcsdsIpCoreHandler::LINK_DOWN;
std::atomic_bool PTME_LOCKED = false;
std::atomic_uint16_t I2C_FATAL_ERRORS = 0;
uint8_t core::FW_VERSION_MAJOR = 0;
uint8_t core::FW_VERSION_MINOR = 0;
uint8_t core::FW_VERSION_REVISION = 0;
bool core::FW_VERSION_HAS_SHA = false;
char core::FW_VERSION_GIT_SHA[4] = {};
void Factory::setStaticFrameworkObjectIds() {
PusServiceBase::PUS_DISTRIBUTOR = objects::PUS_PACKET_DISTRIBUTOR;
@ -151,28 +161,23 @@ void Factory::setStaticFrameworkObjectIds() {
void ObjectFactory::setStatics() { Factory::setStaticFrameworkObjectIds(); }
void ObjectFactory::createTmpComponents() {
std::vector<std::pair<object_id_t, address_t>> tmpDevIds = {{
{objects::TMP1075_HANDLER_TCS_0, addresses::TMP1075_TCS_0},
{objects::TMP1075_HANDLER_TCS_1, addresses::TMP1075_TCS_1},
{objects::TMP1075_HANDLER_PLPCDU_0, addresses::TMP1075_PLPCDU_0},
// damaged
// {objects::TMP1075_HANDLER_PLPCDU_1, addresses::TMP1075_PLPCDU_1},
{objects::TMP1075_HANDLER_IF_BOARD, addresses::TMP1075_IF_BOARD},
}};
void ObjectFactory::createTmpComponents(
std::vector<std::pair<object_id_t, address_t>> tmpDevsToAdd) {
const char* tmpI2cDev = q7s::I2C_PS_EIVE;
if (core::FW_VERSION_MAJOR == 4) {
tmpI2cDev = q7s::I2C_PL_EIVE;
} else if (core::FW_VERSION_MAJOR >= 5) {
tmpI2cDev = q7s::I2C_Q7_EIVE;
}
std::vector<I2cCookie*> tmpDevCookies;
for (size_t idx = 0; idx < tmpDevIds.size(); idx++) {
for (size_t idx = 0; idx < tmpDevsToAdd.size(); idx++) {
tmpDevCookies.push_back(
new I2cCookie(tmpDevIds[idx].second, TMP1075::MAX_REPLY_LENGTH, q7s::I2C_PS_EIVE));
new I2cCookie(tmpDevsToAdd[idx].second, TMP1075::MAX_REPLY_LENGTH, tmpI2cDev));
auto* tmpDevHandler =
new Tmp1075Handler(tmpDevIds[idx].first, objects::I2C_COM_IF, tmpDevCookies[idx]);
tmpDevHandler->setCustomFdir(new TmpDevFdir(tmpDevIds[idx].first));
new Tmp1075Handler(tmpDevsToAdd[idx].first, objects::I2C_COM_IF, tmpDevCookies[idx]);
tmpDevHandler->setCustomFdir(new TmpDevFdir(tmpDevsToAdd[idx].first));
tmpDevHandler->connectModeTreeParent(satsystem::tcs::SUBSYSTEM);
// TODO: Remove this after TCS subsystem was added
// These devices are connected to the 3V3 stack and should be powered permanently. Therefore,
// we set them to normal mode immediately here.
tmpDevHandler->setModeNormal();
}
}
@ -731,20 +736,12 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(CcsdsComponentArgs& args) {
// GPIO definitions of signals connected to the virtual channel interfaces of the PTME IP Core
GpioCookie* gpioCookiePtmeIp = new GpioCookie;
GpiodRegularByLineName* gpio = nullptr;
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC0, "PAPB VC0");
gpioCookiePtmeIp->addGpio(gpioIds::VC0_PAPB_BUSY, gpio);
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC0, "PAPB VC0");
gpioCookiePtmeIp->addGpio(gpioIds::VC0_PAPB_EMPTY, gpio);
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC1, "PAPB VC1");
gpioCookiePtmeIp->addGpio(gpioIds::VC1_PAPB_BUSY, gpio);
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC1, "PAPB VC1");
gpioCookiePtmeIp->addGpio(gpioIds::VC1_PAPB_EMPTY, gpio);
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC2, "PAPB VC2");
gpioCookiePtmeIp->addGpio(gpioIds::VC2_PAPB_BUSY, gpio);
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC2, "PAPB VC2");
gpioCookiePtmeIp->addGpio(gpioIds::VC2_PAPB_EMPTY, gpio);
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC3, "PAPB VC3");
gpioCookiePtmeIp->addGpio(gpioIds::VC3_PAPB_BUSY, gpio);
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC3, "PAPB VC3");
gpioCookiePtmeIp->addGpio(gpioIds::VC3_PAPB_EMPTY, gpio);
gpio = new GpiodRegularByLineName(q7s::gpioNames::PTME_RESETN, "PTME RESETN",
@ -753,19 +750,14 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(CcsdsComponentArgs& args) {
gpioChecker(args.gpioComIF.addGpios(gpioCookiePtmeIp), "PTME PAPB VCs");
// Creating virtual channel interfaces
VirtualChannelIF* vc0 =
new PapbVcInterface(&args.gpioComIF, gpioIds::VC0_PAPB_BUSY, gpioIds::VC0_PAPB_EMPTY,
q7s::UIO_PTME, q7s::uiomapids::PTME_VC0);
VirtualChannelIF* vc1 =
new PapbVcInterface(&args.gpioComIF, gpioIds::VC1_PAPB_BUSY, gpioIds::VC1_PAPB_EMPTY,
q7s::UIO_PTME, q7s::uiomapids::PTME_VC1);
VirtualChannelIF* vc2 =
new PapbVcInterface(&args.gpioComIF, gpioIds::VC2_PAPB_BUSY, gpioIds::VC2_PAPB_EMPTY,
q7s::UIO_PTME, q7s::uiomapids::PTME_VC2);
VirtualChannelIF* vc3 =
new PapbVcInterface(&args.gpioComIF, gpioIds::VC3_PAPB_BUSY, gpioIds::VC3_PAPB_EMPTY,
q7s::UIO_PTME, q7s::uiomapids::PTME_VC3);
VirtualChannelIF* vc0 = new PapbVcInterface(&args.gpioComIF, gpioIds::VC0_PAPB_EMPTY,
q7s::UIO_PTME, q7s::uiomapids::PTME_VC0);
VirtualChannelIF* vc1 = new PapbVcInterface(&args.gpioComIF, gpioIds::VC1_PAPB_EMPTY,
q7s::UIO_PTME, q7s::uiomapids::PTME_VC1);
VirtualChannelIF* vc2 = new PapbVcInterface(&args.gpioComIF, gpioIds::VC2_PAPB_EMPTY,
q7s::UIO_PTME, q7s::uiomapids::PTME_VC2);
VirtualChannelIF* vc3 = new PapbVcInterface(&args.gpioComIF, gpioIds::VC3_PAPB_EMPTY,
q7s::UIO_PTME, q7s::uiomapids::PTME_VC3);
// Creating ptme object and adding virtual channel interfaces
Ptme* ptme = new Ptme(objects::PTME);
ptme->addVcInterface(ccsds::VC0, vc0);
@ -945,16 +937,7 @@ void ObjectFactory::createStrComponents(PowerSwitchIF* pwrSwitcher) {
starTrackerCookie->setNoFixedSizeReply();
StrComHandler* strComIF = new StrComHandler(objects::STR_COM_IF);
const char* paramJsonFile = nullptr;
#ifdef EGSE
paramJsonFile = "/home/pi/arcsec/json/flight-config.json";
#else
#if OBSW_STAR_TRACKER_GROUND_CONFIG == 1
paramJsonFile = "/mnt/sd0/startracker/ground-config.json";
#else
paramJsonFile = "/mnt/sd0/startracker/flight-config.json";
#endif
#endif
const char* paramJsonFile = "/mnt/sd0/startracker/flight-config.json";
if (paramJsonFile == nullptr) {
sif::error << "No valid Star Tracker parameter JSON file" << std::endl;
}
@ -967,12 +950,13 @@ void ObjectFactory::createStrComponents(PowerSwitchIF* pwrSwitcher) {
starTracker->setCustomFdir(strFdir);
}
void ObjectFactory::createImtqComponents(PowerSwitchIF* pwrSwitcher, bool enableHkSets) {
void ObjectFactory::createImtqComponents(PowerSwitchIF* pwrSwitcher, bool enableHkSets,
const char* i2cDev) {
auto* imtqAssy = new ImtqAssembly(objects::IMTQ_ASSY);
imtqAssy->connectModeTreeParent(satsystem::acs::ACS_SUBSYSTEM);
new ImtqPollingTask(objects::IMTQ_POLLING, I2C_FATAL_ERRORS);
I2cCookie* imtqI2cCookie = new I2cCookie(addresses::IMTQ, imtq::MAX_REPLY_SIZE, q7s::I2C_PL_EIVE);
I2cCookie* imtqI2cCookie = new I2cCookie(addresses::IMTQ, imtq::MAX_REPLY_SIZE, i2cDev);
auto imtqHandler = new ImtqHandler(objects::IMTQ_HANDLER, objects::IMTQ_POLLING, imtqI2cCookie,
power::Switches::PDU1_CH3_MGT_5V, enableHkSets);
imtqHandler->enableThermalModule(ThermalStateCfg());
@ -988,8 +972,8 @@ void ObjectFactory::createImtqComponents(PowerSwitchIF* pwrSwitcher, bool enable
#endif
}
void ObjectFactory::createBpxBatteryComponent(bool enableHkSets) {
I2cCookie* bpxI2cCookie = new I2cCookie(addresses::BPX_BATTERY, 100, q7s::I2C_PL_EIVE);
void ObjectFactory::createBpxBatteryComponent(bool enableHkSets, const char* i2cDev) {
I2cCookie* bpxI2cCookie = new I2cCookie(addresses::BPX_BATTERY, 100, i2cDev);
BpxBatteryHandler* bpxHandler = new BpxBatteryHandler(
objects::BPX_BATT_HANDLER, objects::I2C_COM_IF, bpxI2cCookie, enableHkSets);
bpxHandler->setStartUpImmediately();
@ -1045,3 +1029,32 @@ void ObjectFactory::createPlI2cResetGpio(LinuxLibgpioIF* gpioIF) {
gpioIF->pullHigh(gpioIds::PL_I2C_ARESETN);
}
}
ReturnValue_t ObjectFactory::readFirmwareVersion() {
uint32_t* mappedSysRomAddr = nullptr;
// The SYS ROM FPGA block is only available in those versions.
if (not(common::OBSW_VERSION_MAJOR >= 6) or (common::OBSW_VERSION_MAJOR == 4)) {
return returnvalue::OK;
}
// This has to come before the version announce because it might be required for retrieving
// the firmware version.
UioMapper sysRomMapper(q7s::UIO_SYS_ROM);
ReturnValue_t result =
sysRomMapper.getMappedAdress(&mappedSysRomAddr, UioMapper::Permissions::READ_ONLY);
if (result != returnvalue::OK) {
sif::error << "Getting mapped SYS ROM UIO address failed" << std::endl;
return returnvalue::FAILED;
}
if (mappedSysRomAddr != nullptr) {
uint32_t firstEntry = *(reinterpret_cast<uint32_t*>(mappedSysRomAddr));
uint32_t secondEntry = *(reinterpret_cast<uint32_t*>(mappedSysRomAddr) + 1);
core::FW_VERSION_MAJOR = (firstEntry >> 24) & 0xff;
core::FW_VERSION_MINOR = (firstEntry >> 16) & 0xff;
core::FW_VERSION_REVISION = (firstEntry >> 8) & 0xff;
bool hasGitSha = (firstEntry & 0x0b1);
if (hasGitSha) {
std::memcpy(core::FW_VERSION_GIT_SHA, &secondEntry, 4);
}
}
return returnvalue::OK;
}

View File

@ -58,7 +58,7 @@ void createPcduComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchIF** pwrSwitcher
bool enableHkSets);
void createPlPcduComponents(LinuxLibgpioIF* gpioComIF, SpiComIF* spiComIF,
PowerSwitchIF* pwrSwitcher, Stack5VHandler& stackHandler);
void createTmpComponents();
void createTmpComponents(std::vector<std::pair<object_id_t, address_t>> tmpDevsToAdd);
void createRadSensorChipSelect(LinuxLibgpioIF* gpioIF);
ReturnValue_t createRadSensorComponent(LinuxLibgpioIF* gpioComIF, Stack5VHandler& handler);
void createAcsBoardGpios(GpioCookie& cookie);
@ -67,14 +67,15 @@ void createAcsBoardComponents(SpiComIF& spiComIF, LinuxLibgpioIF* gpioComIF, Ser
adis1650x::Type adisType);
void createHeaterComponents(GpioIF* gpioIF, PowerSwitchIF* pwrSwitcher, HealthTableIF* healthTable,
HeaterHandler*& heaterHandler);
void createImtqComponents(PowerSwitchIF* pwrSwitcher, bool enableHkSets);
void createBpxBatteryComponent(bool enableHkSets);
void createImtqComponents(PowerSwitchIF* pwrSwitcher, bool enableHkSets, const char* i2cDev);
void createBpxBatteryComponent(bool enableHkSets, const char* i2cDev);
void createStrComponents(PowerSwitchIF* pwrSwitcher);
void createSolarArrayDeploymentComponents(PowerSwitchIF& pwrSwitcher, GpioIF& gpioIF);
void createSyrlinksComponents(PowerSwitchIF* pwrSwitcher);
void createPayloadComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchIF& pwrSwitcher);
void createReactionWheelComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchIF* pwrSwitcher);
ReturnValue_t createCcsdsComponents(CcsdsComponentArgs& args);
ReturnValue_t readFirmwareVersion();
void createMiscComponents();
void createTestComponents(LinuxLibgpioIF* gpioComIF);

View File

@ -11,13 +11,13 @@
#include "OBSWConfig.h"
#include "bsp_q7s/core/WatchdogHandler.h"
#include "commonConfig.h"
#include "core/scheduling.h"
#include "fsfw/tasks/TaskFactory.h"
#include "fsfw/version.h"
#include "mission/acs/defs.h"
#include "mission/com/defs.h"
#include "mission/system/systemTree.h"
#include "q7sConfig.h"
#include "scheduling.h"
#include "watchdog/definitions.h"
static constexpr int OBSW_ALREADY_RUNNING = -2;

View File

@ -9,7 +9,6 @@
#include <vector>
#include "OBSWConfig.h"
#include "bsp_q7s/core/ObjectFactory.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/objectmanager/ObjectManagerIF.h"
#include "fsfw/platform.h"
@ -21,6 +20,8 @@
#include "mission/pollingSeqTables.h"
#include "mission/scheduling.h"
#include "mission/utility/InitMission.h"
#include "objectFactory.h"
#include "q7sConfig.h"
/* This is configured for linux without CR */
#ifdef PLATFORM_UNIX
@ -324,6 +325,10 @@ void scheduling::initTasks() {
if (result != returnvalue::OK) {
scheduling::printAddObjectError("HEATER_HANDLER", objects::HEATER_HANDLER);
}
result = tcsSystemTask->addComponent(objects::HEATER_HANDLER);
if (result != returnvalue::OK) {
scheduling::printAddObjectError("HEATER_HANDLER", objects::HEATER_HANDLER);
}
#if OBSW_ADD_SYRLINKS == 1
PeriodicTaskIF* syrlinksCom = factory->createPeriodicTask(
@ -527,7 +532,15 @@ void scheduling::createPstTasks(TaskFactory& factory, TaskDeadlineMissedFunction
FixedTimeslotTaskIF* i2cPst =
factory.createFixedTimeslotTask("I2C_PS_PST", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.6,
missedDeadlineFunc, &RR_SCHEDULING);
result = pst::pstI2cProcessingSystem(i2cPst);
pst::TmpSchedConfig tmpSchedConf;
#if OBSW_Q7S_EM == 1
tmpSchedConf.scheduleTmpDev0 = true;
tmpSchedConf.scheduleTmpDev1 = true;
tmpSchedConf.schedulePlPcduDev0 = true;
tmpSchedConf.schedulePlPcduDev1 = true;
tmpSchedConf.scheduleIfBoardDev = true;
#endif
result = pst::pstI2c(tmpSchedConf, i2cPst);
if (result != returnvalue::OK) {
if (result == FixedTimeslotTaskIF::SLOT_LIST_EMPTY) {
sif::warning << "scheduling::initTasks: I2C PST is empty" << std::endl;

View File

@ -129,7 +129,7 @@ ReturnValue_t Xadc::readValFromFile(const char* filename, T& val) {
sif::warning << "Xadc::readValFromFile: Failed to open file " << filename << std::endl;
return returnvalue::FAILED;
}
char valstring[MAX_STR_LENGTH] = "";
char valstring[MAX_STR_LENGTH]{};
char* returnVal = fgets(valstring, MAX_STR_LENGTH, fp);
if (returnVal == nullptr) {
sif::warning << "Xadc::readValFromFile: Failed to read string from file " << filename
@ -139,6 +139,11 @@ ReturnValue_t Xadc::readValFromFile(const char* filename, T& val) {
}
std::istringstream valSstream(valstring);
valSstream >> val;
if (valSstream.bad()) {
sif::warning << "Xadc: Conversion of value to target type failed" << std::endl;
fclose(fp);
return returnvalue::FAILED;
}
fclose(fp);
return returnvalue::OK;
}

View File

@ -96,13 +96,9 @@ enum gpioId_t {
SPI_MUX,
VC0_PAPB_EMPTY,
VC0_PAPB_BUSY,
VC1_PAPB_EMPTY,
VC1_PAPB_BUSY,
VC2_PAPB_EMPTY,
VC2_PAPB_BUSY,
VC3_PAPB_EMPTY,
VC3_PAPB_BUSY,
PTME_RESETN,
PDEC_RESET,

View File

@ -11,6 +11,8 @@ static constexpr char SD_1_MOUNT_POINT[] = "/mnt/sd1";
static constexpr char OBSW_UPDATE_ARCHIVE_FILE_NAME[] = "eive-sw-update.tar.xz";
static constexpr char STRIPPED_OBSW_BINARY_FILE_NAME[] = "eive-obsw-stripped";
static constexpr char OBSW_VERSION_FILE_NAME[] = "obsw_version.txt";
static constexpr char PUS_SEQUENCE_COUNT_FILE[] = "pus-sequence-count.txt";
static constexpr char CFDP_SEQUENCE_COUNT_FILE[] = "cfdp-sequence-count.txt";
static constexpr char OBSW_PATH[] = "/usr/bin/eive-obsw";
static constexpr char OBSW_VERSION_FILE_PATH[] = "/usr/share/eive-obsw/obsw_version.txt";

View File

@ -1,6 +1,6 @@
#include "CoreControllerDummy.h"
#include <bsp_q7s/core/CoreDefinitions.h>
#include <bsp_q7s/core/defs.h>
#include <objects/systemObjectList.h>
#include <cmath>

View File

@ -7,15 +7,21 @@ using namespace returnvalue;
Max31865Dummy::Max31865Dummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
: DeviceHandlerBase(objectId, comif, comCookie), set(this, EiveMax31855::EXCHANGE_SET_ID) {}
void Max31865Dummy::doStartUp() { setMode(MODE_ON); }
void Max31865Dummy::doShutDown() { setMode(_MODE_POWER_DOWN); }
void Max31865Dummy::doShutDown() {
PoolReadGuard pg(&set);
set.setValidity(false, true);
setMode(MODE_OFF);
}
ReturnValue_t Max31865Dummy::buildNormalDeviceCommand(DeviceCommandId_t *id) {
return NOTHING_TO_SEND;
}
ReturnValue_t Max31865Dummy::buildTransitionDeviceCommand(DeviceCommandId_t *id) { return OK; }
ReturnValue_t Max31865Dummy::buildTransitionDeviceCommand(DeviceCommandId_t *id) {
return NOTHING_TO_SEND;
}
ReturnValue_t Max31865Dummy::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t *commandData,
size_t commandDataLen) {
return 0;
return NOTHING_TO_SEND;
}
ReturnValue_t Max31865Dummy::scanForReply(const uint8_t *start, size_t len,
DeviceCommandId_t *foundId, size_t *foundLen) {

View File

@ -7,9 +7,9 @@
#include <cstdlib>
#include <utility>
TemperatureSensorInserter::TemperatureSensorInserter(object_id_t objectId,
Max31865DummyMap tempSensorDummies_,
Tmp1075DummyMap tempTmpSensorDummies_)
TemperatureSensorInserter::TemperatureSensorInserter(
object_id_t objectId, Max31865DummyMap tempSensorDummies_,
std::optional<Tmp1075DummyMap> tempTmpSensorDummies_)
: SystemObject(objectId),
max31865DummyMap(std::move(tempSensorDummies_)),
tmp1075DummyMap(std::move(tempTmpSensorDummies_)) {}
@ -25,8 +25,10 @@ ReturnValue_t TemperatureSensorInserter::performOperation(uint8_t opCode) {
for (auto& rtdDummy : max31865DummyMap) {
rtdDummy.second->setTemperature(10, true);
}
for (auto& tmpDummy : tmp1075DummyMap) {
tmpDummy.second->setTemperature(10, true);
if (tmp1075DummyMap.has_value()) {
for (auto& tmpDummy : tmp1075DummyMap.value()) {
tmpDummy.second->setTemperature(10, true);
}
}
tempsWereInitialized = true;
}
@ -96,6 +98,25 @@ ReturnValue_t TemperatureSensorInserter::performOperation(uint8_t opCode) {
}
break;
}
case (TestCase::COLD_PLOC_CONSECUTIVE): {
if (cycles == 15) {
sif::debug << "Setting cold PLOC temperature" << std::endl;
max31865DummyMap[objects::RTD_0_IC3_PLOC_HEATSPREADER]->setTemperature(-15, true);
}
if (cycles == 30) {
sif::debug << "Setting warmer PLOC temperature" << std::endl;
max31865DummyMap[objects::RTD_0_IC3_PLOC_HEATSPREADER]->setTemperature(0, true);
}
if (cycles == 45) {
sif::debug << "Setting cold PLOC temperature again" << std::endl;
max31865DummyMap[objects::RTD_0_IC3_PLOC_HEATSPREADER]->setTemperature(-15, true);
}
if (cycles == 60) {
sif::debug << "Setting warmer PLOC temperature again" << std::endl;
max31865DummyMap[objects::RTD_0_IC3_PLOC_HEATSPREADER]->setTemperature(0, true);
}
break;
}
case (TestCase::COLD_CAMERA): {
if (cycles == 15) {
sif::debug << "Setting cold CAM temperature" << std::endl;
@ -105,6 +126,21 @@ ReturnValue_t TemperatureSensorInserter::performOperation(uint8_t opCode) {
sif::debug << "Setting CAM temperature back to normal" << std::endl;
max31865DummyMap[objects::RTD_2_IC5_4K_CAMERA]->setTemperature(0, true);
}
break;
}
case (TestCase::COLD_PLOC_STAYS_COLD): {
if (cycles == 15) {
sif::debug << "Setting cold PLOC temperature" << std::endl;
max31865DummyMap[objects::RTD_0_IC3_PLOC_HEATSPREADER]->setTemperature(-40, true);
}
break;
}
case (TestCase::COLD_CAMERA_STAYS_COLD): {
if (cycles == 15) {
sif::debug << "Setting cold PLOC temperature" << std::endl;
max31865DummyMap[objects::RTD_2_IC5_4K_CAMERA]->setTemperature(-40, true);
}
break;
}
}
cycles++;

View File

@ -12,7 +12,7 @@ class TemperatureSensorInserter : public ExecutableObjectIF, public SystemObject
using Max31865DummyMap = std::map<object_id_t, Max31865Dummy*>;
using Tmp1075DummyMap = std::map<object_id_t, Tmp1075Dummy*>;
explicit TemperatureSensorInserter(object_id_t objectId, Max31865DummyMap tempSensorDummies_,
Tmp1075DummyMap tempTmpSensorDummies_);
std::optional<Tmp1075DummyMap> tempTmpSensorDummies_);
ReturnValue_t initialize() override;
ReturnValue_t initializeAfterTaskCreation() override;
@ -22,7 +22,7 @@ class TemperatureSensorInserter : public ExecutableObjectIF, public SystemObject
private:
Max31865DummyMap max31865DummyMap;
Tmp1075DummyMap tmp1075DummyMap;
std::optional<Tmp1075DummyMap> tmp1075DummyMap;
enum TestCase {
NONE = 0,
@ -32,6 +32,9 @@ class TemperatureSensorInserter : public ExecutableObjectIF, public SystemObject
COLD_STR = 4,
COLD_STR_CONSECUTIVE = 5,
COLD_CAMERA = 6,
COLD_PLOC_CONSECUTIVE = 7,
COLD_PLOC_STAYS_COLD = 8,
COLD_CAMERA_STAYS_COLD = 9
};
int iteration = 0;
uint32_t cycles = 0;

View File

@ -8,35 +8,57 @@ using namespace returnvalue;
Tmp1075Dummy::Tmp1075Dummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
: DeviceHandlerBase(objectId, comif, comCookie), set(this) {}
void Tmp1075Dummy::doStartUp() { setMode(MODE_NORMAL); }
void Tmp1075Dummy::doShutDown() { setMode(MODE_OFF); }
void Tmp1075Dummy::doStartUp() { setMode(MODE_ON); }
void Tmp1075Dummy::doShutDown() {
PoolReadGuard pg(&set);
set.setValidity(false, true);
setMode(MODE_OFF);
}
ReturnValue_t Tmp1075Dummy::buildNormalDeviceCommand(DeviceCommandId_t *id) {
return NOTHING_TO_SEND;
}
ReturnValue_t Tmp1075Dummy::buildTransitionDeviceCommand(DeviceCommandId_t *id) { return OK; }
ReturnValue_t Tmp1075Dummy::buildTransitionDeviceCommand(DeviceCommandId_t *id) {
return NOTHING_TO_SEND;
}
ReturnValue_t Tmp1075Dummy::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t *commandData,
size_t commandDataLen) {
return 0;
return NOTHING_TO_SEND;
}
ReturnValue_t Tmp1075Dummy::scanForReply(const uint8_t *start, size_t len,
DeviceCommandId_t *foundId, size_t *foundLen) {
return 0;
}
ReturnValue_t Tmp1075Dummy::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) {
return 0;
}
void Tmp1075Dummy::setTemperature(float temperature, bool valid) {
PoolReadGuard pg(&set);
set.temperatureCelcius.value = temperature;
set.setValidity(valid, true);
}
void Tmp1075Dummy::fillCommandAndReplyMap() {}
uint32_t Tmp1075Dummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return 1000; }
ReturnValue_t Tmp1075Dummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(TMP1075::TEMPERATURE_C_TMP1075, new PoolEntry<float>({10.0}, true));
return OK;
}
ReturnValue_t Tmp1075Dummy::setHealth(HealthState health) {
if (health == FAULTY or health == PERMANENT_FAULTY) {
setMode(_MODE_SHUT_DOWN);
}
return DeviceHandlerBase::setHealth(health);
}
LocalPoolDataSetBase *Tmp1075Dummy::getDataSetHandle(sid_t sid) { return &set; }

View File

@ -26,6 +26,7 @@ class Tmp1075Dummy : public DeviceHandlerBase {
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) override;
ReturnValue_t setHealth(HealthState health) override;
protected:
LocalPoolDataSetBase *getDataSetHandle(sid_t sid) override;

View File

@ -63,11 +63,14 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
rws[3] = new RwDummy(objects::RW4, objects::DUMMY_COM_IF, comCookieDummy);
ObjectFactory::createRwAssy(pwrSwitcher, power::Switches::PDU2_CH2_RW_5V, rws, rwIds);
new SaDeplDummy(objects::SOLAR_ARRAY_DEPL_HANDLER);
auto* strAssy = new StrAssembly(objects::STR_ASSY);
strAssy->connectModeTreeParent(satsystem::acs::ACS_SUBSYSTEM);
auto* strDummy =
new StarTrackerDummy(objects::STAR_TRACKER, objects::DUMMY_COM_IF, comCookieDummy);
strDummy->connectModeTreeParent(*strAssy);
if (cfg.addStrDummy) {
auto* strAssy = new StrAssembly(objects::STR_ASSY);
strAssy->connectModeTreeParent(satsystem::acs::ACS_SUBSYSTEM);
auto* strDummy =
new StarTrackerDummy(objects::STAR_TRACKER, objects::DUMMY_COM_IF, comCookieDummy);
strDummy->connectModeTreeParent(*strAssy);
}
if (cfg.addSyrlinksDummies) {
auto* syrlinksDummy =
new SyrlinksDummy(objects::SYRLINKS_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
@ -191,25 +194,36 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
objects::RTD_15_IC18_IMTQ,
new Max31865Dummy(objects::RTD_15_IC18_IMTQ, objects::DUMMY_COM_IF, comCookieDummy));
std::map<object_id_t, Tmp1075Dummy*> tmpSensorDummies;
tmpSensorDummies.emplace(
objects::TMP1075_HANDLER_TCS_0,
new Tmp1075Dummy(objects::TMP1075_HANDLER_TCS_0, objects::DUMMY_COM_IF, comCookieDummy));
tmpSensorDummies.emplace(
objects::TMP1075_HANDLER_TCS_1,
new Tmp1075Dummy(objects::TMP1075_HANDLER_TCS_1, objects::DUMMY_COM_IF, comCookieDummy));
tmpSensorDummies.emplace(
objects::TMP1075_HANDLER_PLPCDU_0,
new Tmp1075Dummy(objects::TMP1075_HANDLER_PLPCDU_0, objects::DUMMY_COM_IF, comCookieDummy));
// damaged.
// tmpSensorDummies.emplace(
// objects::TMP1075_HANDLER_PLPCDU_1,
// new Tmp1075Dummy(objects::TMP1075_HANDLER_PLPCDU_1, objects::DUMMY_COM_IF,
// comCookieDummy));
tmpSensorDummies.emplace(
objects::TMP1075_HANDLER_IF_BOARD,
new Tmp1075Dummy(objects::TMP1075_HANDLER_IF_BOARD, objects::DUMMY_COM_IF, comCookieDummy));
std::optional<TemperatureSensorInserter::Tmp1075DummyMap> tmpSensorDummies;
if (cfg.addTmpDummies) {
TemperatureSensorInserter::Tmp1075DummyMap tmpDummyMap;
if (cfg.tmp1075Cfg.addTcsBrd0) {
tmpDummyMap.emplace(objects::TMP1075_HANDLER_TCS_0,
new Tmp1075Dummy(objects::TMP1075_HANDLER_TCS_0, objects::DUMMY_COM_IF,
comCookieDummy));
}
if (cfg.tmp1075Cfg.addTcsBrd1) {
tmpDummyMap.emplace(objects::TMP1075_HANDLER_TCS_1,
new Tmp1075Dummy(objects::TMP1075_HANDLER_TCS_1, objects::DUMMY_COM_IF,
comCookieDummy));
}
if (cfg.tmp1075Cfg.addPlPcdu0) {
tmpDummyMap.emplace(objects::TMP1075_HANDLER_PLPCDU_0,
new Tmp1075Dummy(objects::TMP1075_HANDLER_PLPCDU_0,
objects::DUMMY_COM_IF, comCookieDummy));
}
if (cfg.tmp1075Cfg.addPlPcdu1) {
tmpDummyMap.emplace(objects::TMP1075_HANDLER_PLPCDU_1,
new Tmp1075Dummy(objects::TMP1075_HANDLER_PLPCDU_1,
objects::DUMMY_COM_IF, comCookieDummy));
}
if (cfg.tmp1075Cfg.addIfBrd) {
tmpDummyMap.emplace(objects::TMP1075_HANDLER_IF_BOARD,
new Tmp1075Dummy(objects::TMP1075_HANDLER_IF_BOARD,
objects::DUMMY_COM_IF, comCookieDummy));
}
tmpSensorDummies = std::move(tmpDummyMap);
}
new TemperatureSensorInserter(objects::THERMAL_TEMP_INSERTER, rtdSensorDummies,
tmpSensorDummies);
TcsBoardAssembly* tcsBoardAssy =
@ -217,8 +231,10 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
for (auto& rtd : rtdSensorDummies) {
rtd.second->connectModeTreeParent(*tcsBoardAssy);
}
for (auto& tmp : tmpSensorDummies) {
tmp.second->connectModeTreeParent(satsystem::tcs::SUBSYSTEM);
if (tmpSensorDummies.has_value()) {
for (auto& tmp : tmpSensorDummies.value()) {
tmp.second->connectModeTreeParent(satsystem::tcs::SUBSYSTEM);
}
}
}
if (cfg.addCamSwitcherDummy) {

View File

@ -6,6 +6,14 @@ class GpioIF;
namespace dummy {
struct Tmp1075Cfg {
bool addTcsBrd0 = true;
bool addTcsBrd1 = true;
bool addPlPcdu0 = true;
bool addPlPcdu1 = true;
bool addIfBrd = true;
};
// Default values targeted towards EM.
struct DummyCfg {
bool addCoreCtrlCfg = true;
@ -19,6 +27,9 @@ struct DummyCfg {
bool addTempSensorDummies = true;
bool addRtdComIFDummy = true;
bool addPlocDummies = true;
bool addStrDummy = true;
bool addTmpDummies = true;
Tmp1075Cfg tmp1075Cfg;
bool addCamSwitcherDummy = false;
};

2
fsfw

Submodule fsfw updated: 0f76cdb3ba...88e8665280

View File

@ -280,6 +280,9 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
14106;0x371a;PCDU_SYSTEM_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
14107;0x371b;HEATER_NOT_OFF_FOR_OFF_MODE;MEDIUM;No description;mission/controller/tcsDefs.h
14108;0x371c;MGT_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
14109;0x371d;TCS_SWITCHING_HEATER_ON;INFO;P1: Module index. P2: Heater index;mission/controller/tcsDefs.h
14110;0x371e;TCS_SWITCHING_HEATER_OFF;INFO;P1: Module index. P2: Heater index;mission/controller/tcsDefs.h
14111;0x371f;TCS_HEATER_MAX_BURN_TIME_REACHED;MEDIUM;P1: Heater index. P2: Maximum burn time for heater.;mission/controller/tcsDefs.h
14201;0x3779;TX_TIMER_EXPIRED;INFO;The transmit timer to protect the Syrlinks expired P1: The current timer value;mission/system/com/ComSubsystem.h
14202;0x377a;BIT_LOCK_TX_ON;INFO;Transmitter will be turned on due to detection of bitlock;mission/system/com/ComSubsystem.h
14300;0x37dc;POSSIBLE_FILE_CORRUPTION;LOW;P1: Result code of TM packet parser. P2: Timestamp of possibly corrupt file as a unix timestamp.;mission/persistentTmStoreDefs.h

1 Event ID (dec) Event ID (hex) Name Severity Description File Path
280 14106 0x371a PCDU_SYSTEM_OVERHEATING HIGH No description mission/controller/tcsDefs.h
281 14107 0x371b HEATER_NOT_OFF_FOR_OFF_MODE MEDIUM No description mission/controller/tcsDefs.h
282 14108 0x371c MGT_OVERHEATING HIGH No description mission/controller/tcsDefs.h
283 14109 0x371d TCS_SWITCHING_HEATER_ON INFO P1: Module index. P2: Heater index mission/controller/tcsDefs.h
284 14110 0x371e TCS_SWITCHING_HEATER_OFF INFO P1: Module index. P2: Heater index mission/controller/tcsDefs.h
285 14111 0x371f TCS_HEATER_MAX_BURN_TIME_REACHED MEDIUM P1: Heater index. P2: Maximum burn time for heater. mission/controller/tcsDefs.h
286 14201 0x3779 TX_TIMER_EXPIRED INFO The transmit timer to protect the Syrlinks expired P1: The current timer value mission/system/com/ComSubsystem.h
287 14202 0x377a BIT_LOCK_TX_ON INFO Transmitter will be turned on due to detection of bitlock mission/system/com/ComSubsystem.h
288 14300 0x37dc POSSIBLE_FILE_CORRUPTION LOW P1: Result code of TM packet parser. P2: Timestamp of possibly corrupt file as a unix timestamp. mission/persistentTmStoreDefs.h

View File

@ -280,6 +280,9 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
14106;0x371a;PCDU_SYSTEM_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
14107;0x371b;HEATER_NOT_OFF_FOR_OFF_MODE;MEDIUM;No description;mission/controller/tcsDefs.h
14108;0x371c;MGT_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
14109;0x371d;TCS_SWITCHING_HEATER_ON;INFO;P1: Module index. P2: Heater index;mission/controller/tcsDefs.h
14110;0x371e;TCS_SWITCHING_HEATER_OFF;INFO;P1: Module index. P2: Heater index;mission/controller/tcsDefs.h
14111;0x371f;TCS_HEATER_MAX_BURN_TIME_REACHED;MEDIUM;P1: Heater index. P2: Maximum burn time for heater.;mission/controller/tcsDefs.h
14201;0x3779;TX_TIMER_EXPIRED;INFO;The transmit timer to protect the Syrlinks expired P1: The current timer value;mission/system/com/ComSubsystem.h
14202;0x377a;BIT_LOCK_TX_ON;INFO;Transmitter will be turned on due to detection of bitlock;mission/system/com/ComSubsystem.h
14300;0x37dc;POSSIBLE_FILE_CORRUPTION;LOW;P1: Result code of TM packet parser. P2: Timestamp of possibly corrupt file as a unix timestamp.;mission/persistentTmStoreDefs.h

1 Event ID (dec) Event ID (hex) Name Severity Description File Path
280 14106 0x371a PCDU_SYSTEM_OVERHEATING HIGH No description mission/controller/tcsDefs.h
281 14107 0x371b HEATER_NOT_OFF_FOR_OFF_MODE MEDIUM No description mission/controller/tcsDefs.h
282 14108 0x371c MGT_OVERHEATING HIGH No description mission/controller/tcsDefs.h
283 14109 0x371d TCS_SWITCHING_HEATER_ON INFO P1: Module index. P2: Heater index mission/controller/tcsDefs.h
284 14110 0x371e TCS_SWITCHING_HEATER_OFF INFO P1: Module index. P2: Heater index mission/controller/tcsDefs.h
285 14111 0x371f TCS_HEATER_MAX_BURN_TIME_REACHED MEDIUM P1: Heater index. P2: Maximum burn time for heater. mission/controller/tcsDefs.h
286 14201 0x3779 TX_TIMER_EXPIRED INFO The transmit timer to protect the Syrlinks expired P1: The current timer value mission/system/com/ComSubsystem.h
287 14202 0x377a BIT_LOCK_TX_ON INFO Transmitter will be turned on due to detection of bitlock mission/system/com/ComSubsystem.h
288 14300 0x37dc POSSIBLE_FILE_CORRUPTION LOW P1: Result code of TM packet parser. P2: Timestamp of possibly corrupt file as a unix timestamp. mission/persistentTmStoreDefs.h

View File

@ -1,7 +1,7 @@
/**
* @brief Auto-generated event translation file. Contains 296 translations.
* @brief Auto-generated event translation file. Contains 299 translations.
* @details
* Generated on: 2023-06-21 19:01:02
* Generated on: 2023-07-07 12:06:06
*/
#include "translateEvents.h"
@ -286,6 +286,9 @@ const char *CAMERA_OVERHEATING_STRING = "CAMERA_OVERHEATING";
const char *PCDU_SYSTEM_OVERHEATING_STRING = "PCDU_SYSTEM_OVERHEATING";
const char *HEATER_NOT_OFF_FOR_OFF_MODE_STRING = "HEATER_NOT_OFF_FOR_OFF_MODE";
const char *MGT_OVERHEATING_STRING = "MGT_OVERHEATING";
const char *TCS_SWITCHING_HEATER_ON_STRING = "TCS_SWITCHING_HEATER_ON";
const char *TCS_SWITCHING_HEATER_OFF_STRING = "TCS_SWITCHING_HEATER_OFF";
const char *TCS_HEATER_MAX_BURN_TIME_REACHED_STRING = "TCS_HEATER_MAX_BURN_TIME_REACHED";
const char *TX_TIMER_EXPIRED_STRING = "TX_TIMER_EXPIRED";
const char *BIT_LOCK_TX_ON_STRING = "BIT_LOCK_TX_ON";
const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION";
@ -866,6 +869,12 @@ const char *translateEvents(Event event) {
return HEATER_NOT_OFF_FOR_OFF_MODE_STRING;
case (14108):
return MGT_OVERHEATING_STRING;
case (14109):
return TCS_SWITCHING_HEATER_ON_STRING;
case (14110):
return TCS_SWITCHING_HEATER_OFF_STRING;
case (14111):
return TCS_HEATER_MAX_BURN_TIME_REACHED_STRING;
case (14201):
return TX_TIMER_EXPIRED_STRING;
case (14202):

View File

@ -2,7 +2,7 @@
* @brief Auto-generated object translation file.
* @details
* Contains 175 translations.
* Generated on: 2023-06-21 19:01:02
* Generated on: 2023-07-07 12:06:06
*/
#include "translateObjects.h"

View File

@ -1,7 +1,7 @@
/**
* @brief Auto-generated event translation file. Contains 296 translations.
* @brief Auto-generated event translation file. Contains 299 translations.
* @details
* Generated on: 2023-06-21 19:01:02
* Generated on: 2023-07-07 12:06:06
*/
#include "translateEvents.h"
@ -286,6 +286,9 @@ const char *CAMERA_OVERHEATING_STRING = "CAMERA_OVERHEATING";
const char *PCDU_SYSTEM_OVERHEATING_STRING = "PCDU_SYSTEM_OVERHEATING";
const char *HEATER_NOT_OFF_FOR_OFF_MODE_STRING = "HEATER_NOT_OFF_FOR_OFF_MODE";
const char *MGT_OVERHEATING_STRING = "MGT_OVERHEATING";
const char *TCS_SWITCHING_HEATER_ON_STRING = "TCS_SWITCHING_HEATER_ON";
const char *TCS_SWITCHING_HEATER_OFF_STRING = "TCS_SWITCHING_HEATER_OFF";
const char *TCS_HEATER_MAX_BURN_TIME_REACHED_STRING = "TCS_HEATER_MAX_BURN_TIME_REACHED";
const char *TX_TIMER_EXPIRED_STRING = "TX_TIMER_EXPIRED";
const char *BIT_LOCK_TX_ON_STRING = "BIT_LOCK_TX_ON";
const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION";
@ -866,6 +869,12 @@ const char *translateEvents(Event event) {
return HEATER_NOT_OFF_FOR_OFF_MODE_STRING;
case (14108):
return MGT_OVERHEATING_STRING;
case (14109):
return TCS_SWITCHING_HEATER_ON_STRING;
case (14110):
return TCS_SWITCHING_HEATER_OFF_STRING;
case (14111):
return TCS_HEATER_MAX_BURN_TIME_REACHED_STRING;
case (14201):
return TX_TIMER_EXPIRED_STRING;
case (14202):

View File

@ -2,7 +2,7 @@
* @brief Auto-generated object translation file.
* @details
* Contains 175 translations.
* Generated on: 2023-06-21 19:01:02
* Generated on: 2023-07-07 12:06:06
*/
#include "translateObjects.h"

View File

@ -16,9 +16,9 @@ AxiPtmeConfig::AxiPtmeConfig(object_id_t objectId, std::string axiUio, int mapNu
AxiPtmeConfig::~AxiPtmeConfig() {}
ReturnValue_t AxiPtmeConfig::initialize() {
ReturnValue_t result = returnvalue::OK;
UioMapper uioMapper(axiUio, mapNum);
result = uioMapper.getMappedAdress(&baseAddress, UioMapper::Permissions::READ_WRITE);
ReturnValue_t result =
uioMapper.getMappedAdress(&baseAddress, UioMapper::Permissions::READ_WRITE);
if (result != returnvalue::OK) {
return result;
}
@ -26,8 +26,7 @@ ReturnValue_t AxiPtmeConfig::initialize() {
}
ReturnValue_t AxiPtmeConfig::writeCaduRateReg(uint8_t rateVal) {
ReturnValue_t result = returnvalue::OK;
result = mutex->lockMutex(timeoutType, mutexTimeout);
ReturnValue_t result = mutex->lockMutex(timeoutType, mutexTimeout);
if (result != returnvalue::OK) {
sif::warning << "AxiPtmeConfig::writeCaduRateReg: Failed to lock mutex" << std::endl;
return returnvalue::FAILED;
@ -41,6 +40,11 @@ ReturnValue_t AxiPtmeConfig::writeCaduRateReg(uint8_t rateVal) {
return returnvalue::OK;
}
uint8_t AxiPtmeConfig::readCaduRateReg() {
MutexGuard mg(mutex);
return static_cast<uint8_t>(*(baseAddress + CADU_BITRATE_REG));
}
void AxiPtmeConfig::enableTxclockManipulator() {
writeBit(COMMON_CONFIG_REG, true, BitPos::EN_TX_CLK_MANIPULATOR);
}

View File

@ -38,6 +38,7 @@ class AxiPtmeConfig : public SystemObject {
* frequency of the clock connected to the bit clock input of PTME.
*/
ReturnValue_t writeCaduRateReg(uint8_t rateVal);
uint8_t readCaduRateReg();
/**
* @brief Next to functions control the tx clock manipulator component

View File

@ -7,20 +7,16 @@
#include "fsfw/serviceinterface/ServiceInterface.h"
PapbVcInterface::PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbBusyId,
gpioId_t papbEmptyId, std::string uioFile, int mapNum)
: gpioComIF(gpioComIF),
papbBusyId(papbBusyId),
papbEmptyId(papbEmptyId),
uioFile(std::move(uioFile)),
mapNum(mapNum) {}
PapbVcInterface::PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbEmptyId,
std::string uioFile, int mapNum)
: gpioComIF(gpioComIF), papbEmptyId(papbEmptyId), uioFile(std::move(uioFile)), mapNum(mapNum) {}
PapbVcInterface::~PapbVcInterface() {}
ReturnValue_t PapbVcInterface::initialize() {
UioMapper uioMapper(uioFile, mapNum);
ReturnValue_t result = uioMapper.getMappedAdress(const_cast<uint32_t**>(&vcBaseReg),
UioMapper::Permissions::WRITE_ONLY);
UioMapper::Permissions::READ_WRITE);
if (result != returnvalue::OK) {
return result;
}
@ -32,63 +28,27 @@ ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) {
if (size < 4) {
return returnvalue::FAILED;
}
if (pollInterfaceReadiness(0, true) == returnvalue::OK) {
if (pollReadyForPacket()) {
startPacketTransfer(ByteWidthCfg::ONE);
} else {
return DirectTmSinkIF::IS_BUSY;
}
// TODO: This should work but does not.. :(
// size_t idx = 0;
// while (idx < size) {
//
// nanosleep(&BETWEEN_POLL_DELAY, &remDelay);
// if ((size - idx) < 4) {
// *vcBaseReg = CONFIG_DATA_INPUT | (size - idx - 1);
// usleep(1);
// }
// if (pollPapbBusySignal(2) == returnvalue::OK) {
// // vcBaseReg + DATA_REG_OFFSET + 3 = static_cast<uint8_t>(data + idx);
// // vcBaseReg + DATA_REG_OFFSET + 2 = static_cast<uint8_t>(data + idx + 1);
// // vcBaseReg + DATA_REG_OFFSET + 1 = static_cast<uint8_t>(data + idx + 2);
// // vcBaseReg + DATA_REG_OFFSET = static_cast<uint8_t>(data + idx + 3);
//
// // std::memcpy((vcBaseReg + DATA_REG_OFFSET), data + idx , nextWriteSize);
// *(vcBaseReg + DATA_REG_OFFSET) = *reinterpret_cast<const uint32_t*>(data + idx);
// //uint8_t* byteReg = reinterpret_cast<uint8_t*>(vcBaseReg + DATA_REG_OFFSET);
//
// //byteReg[0] = data[idx];
// //byteReg[1] = data[idx];
// } else {
// abortPacketTransfer();
// return returnvalue::FAILED;
// }
// // TODO: Change this after the bugfix. Right now, the PAPB ignores the content of the byte
// // width configuration.5
// // It's okay to increment by a larger amount for the last segment here, loop will be over
// // in any case.
// idx += 4;
// }
for (size_t idx = 0; idx < size; idx++) {
// This delay is super-important, DO NOT REMOVE!
// Polling the GPIO or the config register too often messes up the scheduler.
// TODO: Maybe this should not be done like this. It would be better if there was a custom
// FPGA module which can accept packets and then takes care of dumping that packet into
// the PTME. DMA would be an ideal solution for this.
nanosleep(&BETWEEN_POLL_DELAY, &remDelay);
if (pollInterfaceReadiness(2, false) == returnvalue::OK) {
*(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(data[idx]);
} else {
abortPacketTransfer();
return returnvalue::FAILED;
}
}
nanosleep(&BETWEEN_POLL_DELAY, &remDelay);
if (pollInterfaceReadiness(2, false) == returnvalue::OK) {
completePacketTransfer();
} else {
if (not pollReadyForOctet(MAX_BUSY_POLLS)) {
abortPacketTransfer();
return returnvalue::FAILED;
}
for (size_t idx = 0; idx < size; idx++) {
if (not pollReadyForOctet(MAX_BUSY_POLLS)) {
abortPacketTransfer();
return returnvalue::FAILED;
}
*(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(data[idx]);
}
if (not pollReadyForOctet(MAX_BUSY_POLLS)) {
abortPacketTransfer();
return returnvalue::FAILED;
}
completePacketTransfer();
return returnvalue::OK;
}
@ -98,63 +58,49 @@ void PapbVcInterface::startPacketTransfer(ByteWidthCfg initWidth) {
void PapbVcInterface::completePacketTransfer() { *vcBaseReg = CONFIG_END; }
ReturnValue_t PapbVcInterface::pollInterfaceReadiness(uint32_t maxPollRetries,
bool checkReadyState) const {
uint32_t busyIdx = 0;
nextDelay.tv_nsec = FIRST_DELAY_PAPB_POLLING_NS;
while (true) {
// Check if PAPB interface is ready to receive data. Use the configuration register for this.
// Bit 5, see PTME ptme_001_01-0-7-r2 Table 31.
uint32_t reg = *vcBaseReg;
bool busy = (reg >> 5) & 0b1;
bool ready = (reg >> 6) & 0b1;
if (not busy) {
return returnvalue::OK;
}
if (checkReadyState and not ready) {
return PAPB_BUSY;
}
busyIdx++;
if (busyIdx >= maxPollRetries) {
return PAPB_BUSY;
}
// Ignore signal handling here for now.
nanosleep(&nextDelay, &remDelay);
// Adaptive delay.
if (nextDelay.tv_nsec * 2 <= MAX_DELAY_PAPB_POLLING_NS) {
nextDelay.tv_nsec *= 2;
}
}
return returnvalue::OK;
bool PapbVcInterface::pollReadyForPacket() const {
// Check if PAPB interface is ready to receive data. Use the configuration register for this.
// Bit 5, see PTME ptme_001_01-0-7-r2 Table 31.
uint32_t reg = *vcBaseReg;
return (reg >> 6) & 0b1;
}
void PapbVcInterface::isVcInterfaceBufferEmpty() {
bool PapbVcInterface::isVcInterfaceBufferEmpty() {
ReturnValue_t result = returnvalue::OK;
gpio::Levels papbEmptyState = gpio::Levels::HIGH;
result = gpioComIF->readGpio(papbEmptyId, papbEmptyState);
if (result != returnvalue::OK) {
sif::warning << "PapbVcInterface::isVcInterfaceBufferEmpty: Failed to read papb empty signal"
<< std::endl;
return;
sif::error << "PapbVcInterface::isVcInterfaceBufferEmpty: Failed to read papb empty signal"
<< std::endl;
return true;
}
if (papbEmptyState == gpio::Levels::HIGH) {
sif::debug << "PapbVcInterface::isVcInterfaceBufferEmpty: Buffer is empty" << std::endl;
} else {
sif::debug << "PapbVcInterface::isVcInterfaceBufferEmpty: Buffer is not empty" << std::endl;
return true;
}
return;
return false;
}
bool PapbVcInterface::isBusy() const { return pollInterfaceReadiness(0, true) == PAPB_BUSY; }
bool PapbVcInterface::isBusy() const { return not pollReadyForPacket(); }
void PapbVcInterface::cancelTransfer() { abortPacketTransfer(); }
inline bool PapbVcInterface::pollReadyForOctet(uint32_t maxCycles) const {
uint32_t reg;
uint32_t idx = 0;
while (idx < maxCycles) {
reg = *vcBaseReg;
// Busy bit.
if (not((reg >> 5) & 0b1)) {
return true;
}
idx++;
}
return false;
}
ReturnValue_t PapbVcInterface::sendTestFrame() {
/** Size of one complete transfer frame data field amounts to 1105 bytes */
uint8_t testPacket[1105];

View File

@ -30,8 +30,7 @@ class PapbVcInterface : public VirtualChannelIF {
* @param uioFile UIO file providing access to the PAPB bus
* @param mapNum Map number of UIO map associated with this virtual channel
*/
PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbBusyId, gpioId_t papbEmptyId,
std::string uioFile, int mapNum);
PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbEmptyId, std::string uioFile, int mapNum);
virtual ~PapbVcInterface();
bool isBusy() const override;
@ -81,11 +80,9 @@ class PapbVcInterface : public VirtualChannelIF {
static constexpr long int FIRST_DELAY_PAPB_POLLING_NS = 10;
static constexpr long int MAX_DELAY_PAPB_POLLING_NS = 40;
static constexpr uint32_t MAX_BUSY_POLLS = 1000;
LinuxLibgpioIF* gpioComIF = nullptr;
/** Pulled to low when virtual channel not ready to receive data */
gpioId_t papbBusyId = gpio::NO_GPIO;
/** High when external buffer memory of virtual channel is empty */
gpioId_t papbEmptyId = gpio::NO_GPIO;
@ -120,13 +117,15 @@ class PapbVcInterface : public VirtualChannelIF {
*
* @return returnvalue::OK when ready to receive data else PAPB_BUSY.
*/
inline ReturnValue_t pollInterfaceReadiness(uint32_t maxPollRetries, bool checkReadyState) const;
inline bool pollReadyForPacket() const;
inline bool pollReadyForOctet(uint32_t maxCycles) const;
/**
* @brief This function can be used for debugging to check whether there are packets in
* the packet buffer of the virtual channel or not.
*/
void isVcInterfaceBufferEmpty();
bool isVcInterfaceBufferEmpty();
/**
* @brief This function sends a complete telemetry transfer frame data field (1105 bytes)

View File

@ -26,6 +26,11 @@ ReturnValue_t PtmeConfig::setRate(uint32_t bitRate) {
return axiPtmeConfig->writeCaduRateReg(static_cast<uint8_t>(rateVal));
}
uint32_t PtmeConfig::getRate() {
uint8_t rateReg = axiPtmeConfig->readCaduRateReg();
return (BIT_CLK_FREQ / (rateReg + 1));
}
void PtmeConfig::invertTxClock(bool invert) {
if (invert) {
axiPtmeConfig->enableTxclockInversion();

View File

@ -32,6 +32,7 @@ class PtmeConfig : public SystemObject {
* of the CADU clock due to the convolutional code added by the s-Band transceiver.
*/
ReturnValue_t setRate(uint32_t bitRate);
uint32_t getRate();
/**
* @brief Will change the time the tx data signal is updated with respect to the tx clock

View File

@ -246,7 +246,13 @@ ReturnValue_t CcsdsIpCoreHandler::checkModeCommand(Mode_t mode, Submode_t submod
void CcsdsIpCoreHandler::startTransition(Mode_t mode, Submode_t submode) {
triggerEvent(CHANGING_MODE, mode, submode);
if (mode == HasModesIF::MODE_ON) {
if (this->submode != submode) {
uint32_t currentRate = ptmeConfig.getRate();
// Check whether the rate actually changes.
if ((this->submode != submode) and
(((submode == static_cast<Submode_t>(com::CcsdsSubmode::DATARATE_LOW) and
(currentRate != RATE_100KBPS))) or
((submode == static_cast<Submode_t>(com::CcsdsSubmode::DATARATE_HIGH) and
(currentRate != RATE_500KBPS))))) {
initPtmeUpdateAfterXCycles();
updateContext.enableTransmitAfterPtmeUpdate = true;
updateContext.updateClockRate = true;

View File

@ -19,13 +19,8 @@ LiveTmTask::LiveTmTask(object_id_t objectId, PusTmFunnel& pusFunnel, CfdpTmFunne
ReturnValue_t LiveTmTask::performOperation(uint8_t opCode) {
readCommandQueue();
while (true) {
bool performWriteOp = true;
if (mode == MODE_OFF or ptmeLocked) {
performWriteOp = false;
}
// The funnel tasks are scheduled here directly as well.
ReturnValue_t result = channel.handleNextTm(performWriteOp);
ReturnValue_t result = channel.handleNextTm(!ptmeLocked);
if (result == DirectTmSinkIF::IS_BUSY) {
sif::error << "Lost live TM, PAPB busy" << std::endl;
}

View File

@ -42,13 +42,7 @@ ReturnValue_t PersistentLogTmStoreTask::performOperation(uint8_t opCode) {
if (not someonesBusy) {
TaskFactory::delayTask(100);
} else if (vcBusyDuringDump) {
// TODO: Might not be necessary
sif::debug << "VC busy, delaying" << std::endl;
TaskFactory::delayTask(10);
} else {
// TODO: Would be best to remove this, but not delaying here can lead to evil issues.
// Polling the PAPB of the PTME core too often leads to scheuduling issues.
TaskFactory::delayTask(2);
}
}
}

View File

@ -24,13 +24,7 @@ ReturnValue_t PersistentSingleTmStoreTask::performOperation(uint8_t opCode) {
if (not busy) {
TaskFactory::delayTask(100);
} else if (dumpContext.vcBusyDuringDump) {
sif::debug << "VC busy, delaying" << std::endl;
// TODO: Might not be necessary
TaskFactory::delayTask(10);
} else {
// TODO: Would be best to remove this, but not delaying here can lead to evil issues.
// Polling the PAPB of the PTME core too often leads to scheuduling issues.
TaskFactory::delayTask(2);
}
}
}

View File

@ -773,11 +773,13 @@ void SyrlinksHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) {
auto txStandbyHandler = [&]() {
txDataset.setReportingEnabled(false);
poolManager.changeCollectionInterval(temperatureSet.getSid(), 60.0);
poolManager.changeCollectionInterval(rxDataset.getSid(), 60.0);
transState = TransitionState::SET_TX_STANDBY;
internalState = InternalState::TX_TRANSITION;
};
auto txOnHandler = [&](TransitionState tgtTransitionState) {
txDataset.setReportingEnabled(true);
poolManager.changeCollectionInterval(rxDataset.getSid(), 5.0);
poolManager.changeCollectionInterval(txDataset.getSid(), 10.0);
poolManager.changeCollectionInterval(temperatureSet.getSid(), 5.0);
transState = tgtTransitionState;

View File

@ -45,13 +45,19 @@ bool TmStoreTaskBase::handleOneStore(PersistentTmStoreWithTmQueue& store,
} else {
Command_t execCmd;
// Handle TC requests, for example deletion or retrieval requests.
// TODO: Not really clean here.. would be better if the executed command is returns as an
// enumeration.
result = store.handleCommandQueue(ipcStore, execCmd);
if (result == returnvalue::OK) {
if (execCmd == TmStoreMessage::DOWNLINK_STORE_CONTENT_TIME) {
if (execCmd == TmStoreMessage::DOWNLINK_STORE_CONTENT_TIME) {
if (result == PersistentTmStore::DUMP_DONE) {
dumpDoneHandler(store, dumpContext);
} else if (result == returnvalue::OK) {
cancelDumpCd.resetTimer();
tmSinkBusyCd.resetTimer();
dumpContext.reset();
}
}
if (execCmd != CommandMessageIF::CMD_NONE) {
tcRequestReceived = true;
}
}
@ -119,21 +125,13 @@ ReturnValue_t TmStoreTaskBase::performDump(PersistentTmStoreWithTmQueue& store,
DumpContext& dumpContext, bool& dumpPerformed) {
size_t dumpedLen = 0;
auto dumpDoneHandler = [&]() {
uint32_t startTime;
uint32_t endTime;
store.getStartAndEndTimeCurrentOrLastDump(startTime, endTime);
triggerEvent(dumpContext.eventIfDone, dumpContext.numberOfDumpedPackets,
dumpContext.dumpedBytes);
dumpContext.reset();
};
// Dump the next packet into the PTME.
dumpContext.ptmeBusyCounter = 0;
tmSinkBusyCd.resetTimer();
ReturnValue_t result = store.getNextDumpPacket(tmReader, fileHasSwapped);
if (fileHasSwapped and result == PersistentTmStore::DUMP_DONE) {
// This can happen if a file is corrupted and the next file swap completes the dump.
dumpDoneHandler();
dumpDoneHandler(store, dumpContext);
return returnvalue::OK;
} else if (result != returnvalue::OK) {
sif::error << "PersistentTmStore: Getting next dump packet failed" << std::endl;
@ -157,7 +155,7 @@ ReturnValue_t TmStoreTaskBase::performDump(PersistentTmStoreWithTmQueue& store,
}
}
if (result == PersistentTmStore::DUMP_DONE) {
dumpDoneHandler();
dumpDoneHandler(store, dumpContext);
}
return returnvalue::OK;
}
@ -198,6 +196,14 @@ ReturnValue_t TmStoreTaskBase::connectModeTreeParent(HasModeTreeChildrenIF& pare
return modetree::connectModeTreeParent(parent, *this, nullptr, modeHelper);
}
void TmStoreTaskBase::dumpDoneHandler(PersistentTmStore& store, DumpContext& dumpContext) {
uint32_t startTime;
uint32_t endTime;
store.getStartAndEndTimeCurrentOrLastDump(startTime, endTime);
triggerEvent(dumpContext.eventIfDone, dumpContext.numberOfDumpedPackets, dumpContext.dumpedBytes);
dumpContext.reset();
}
ModeTreeChildIF& TmStoreTaskBase::getModeTreeChildIF() { return *this; }
void TmStoreTaskBase::readCommandQueue(void) {

View File

@ -96,6 +96,8 @@ class TmStoreTaskBase : public SystemObject,
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t* msToReachTheMode) override;
void dumpDoneHandler(PersistentTmStore& store, DumpContext& dumpContext);
void announceMode(bool recursive) override;
object_id_t getObjectId() const override;
const HasHealthIF* getOptHealthIF() const override;

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
#ifndef MISSION_CONTROLLER_THERMALCONTROLLER_H_
#define MISSION_CONTROLLER_THERMALCONTROLLER_H_
#include <bsp_q7s/core/CoreDefinitions.h>
#include <bsp_q7s/core/defs.h>
#include <fsfw/controller/ExtendedControllerBase.h>
#include <fsfw/devicehandlers/DeviceHandlerThermalSet.h>
#include <fsfw/timemanager/Countdown.h>
@ -24,74 +24,7 @@
#include <atomic>
#include <list>
/**
* NOP Limit: Hard limit for device, usually from datasheet. Device damage is possible lif NOP limit
* is exceeded.
* OP Limit: Soft limit. Device should be switched off or TCS controller should take action if the
* limit is exceeded to avoid reaching NOP limit
*/
struct TempLimits {
TempLimits(float nopLowerLimit, float opLowerLimit, float cutOffLimit, float opUpperLimit,
float nopUpperLimit)
: opLowerLimit(opLowerLimit),
opUpperLimit(opUpperLimit),
cutOffLimit(cutOffLimit),
nopLowerLimit(nopLowerLimit),
nopUpperLimit(nopUpperLimit) {}
float opLowerLimit;
float opUpperLimit;
float cutOffLimit;
float nopLowerLimit;
float nopUpperLimit;
};
struct ThermalState {
uint8_t errorCounter;
// Is heating on for that thermal module?
bool heating = false;
heater::Switch heaterSwitch = heater::Switch::NUMBER_OF_SWITCHES;
// Heater start time and end times as UNIX seconds. Please note that these times will be updated
// when a switch command is sent, with no guarantess that the heater actually went on.
uint32_t heaterStartTime = 0;
uint32_t heaterEndTime = 0;
};
struct HeaterState {
bool switchTransition;
HeaterHandler::SwitchState target;
uint8_t heaterSwitchControlCycles;
};
using HeaterSwitchStates = std::array<HeaterHandler::SwitchState, heater::NUMBER_OF_SWITCHES>;
enum ThermalComponents : uint8_t {
NONE = 0,
ACS_BOARD = 1,
MGT = 2,
RW = 3,
STR = 4,
IF_BOARD = 5,
TCS_BOARD = 6,
OBC = 7,
OBCIF_BOARD = 8,
SBAND_TRANSCEIVER = 9,
PCDUP60_BOARD = 10,
PCDUACU = 11,
PCDUPDU = 12,
PLPCDU_BOARD = 13,
PLOCMISSION_BOARD = 14,
PLOCPROCESSING_BOARD = 15,
DAC = 16,
CAMERA = 17,
DRO = 18,
X8 = 19,
HPA = 20,
TX = 21,
MPA = 22,
SCEX_BOARD = 23,
NUM_ENTRIES
};
#include <optional>
class ThermalController : public ExtendedControllerBase {
public:
@ -102,8 +35,28 @@ class ThermalController : public ExtendedControllerBase {
static constexpr int16_t SANITY_LIMIT_LOWER_TEMP = -80;
static constexpr int16_t SANITY_LIMIT_UPPER_TEMP = 160;
// 1 hour
static constexpr uint32_t DEFAULT_MAX_HEATER_ON_DURATION_MS = 60 * 60 * 1000;
static constexpr uint32_t MAX_HEATER_ON_DURATIONS_MS[8] = {// PLOC PROC board
DEFAULT_MAX_HEATER_ON_DURATION_MS,
// PCDU PDU
DEFAULT_MAX_HEATER_ON_DURATION_MS,
// ACS Board
DEFAULT_MAX_HEATER_ON_DURATION_MS,
// OBC Board
DEFAULT_MAX_HEATER_ON_DURATION_MS,
// Camera
DEFAULT_MAX_HEATER_ON_DURATION_MS,
// STR
DEFAULT_MAX_HEATER_ON_DURATION_MS,
// DRO
DEFAULT_MAX_HEATER_ON_DURATION_MS,
// S-Band
DEFAULT_MAX_HEATER_ON_DURATION_MS};
ThermalController(object_id_t objectId, HeaterHandler& heater,
const std::atomic_bool& tcsBoardShortUnavailable);
const std::atomic_bool& tcsBoardShortUnavailable, bool pollPcdu1Tmp);
virtual ~ThermalController();
ReturnValue_t initialize() override;
@ -111,16 +64,16 @@ class ThermalController : public ExtendedControllerBase {
struct HeaterContext {
public:
HeaterContext(heater::Switch switchNr, heater::Switch redundantSwitchNr,
const TempLimits& tempLimit)
const tcsCtrl::TempLimits& tempLimit)
: switchNr(switchNr), redSwitchNr(redundantSwitchNr), tempLimit(tempLimit) {}
bool doHeaterHandling = true;
heater::Switch switchNr;
HeaterHandler::SwitchState switchState = HeaterHandler::SwitchState::OFF;
heater::SwitchState switchState = heater::SwitchState::OFF;
heater::Switch redSwitchNr;
const TempLimits& tempLimit;
const tcsCtrl::TempLimits& tempLimit;
};
void performThermalModuleCtrl(const HeaterSwitchStates& heaterSwitchStates);
void performThermalModuleCtrl(const tcsCtrl::HeaterSwitchStates& heaterSwitchStates);
ReturnValue_t handleCommandMessage(CommandMessage* message) override;
void performControlOperation() override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
@ -142,12 +95,12 @@ class ThermalController : public ExtendedControllerBase {
HeaterHandler& heaterHandler;
bool pollPcdu1Tmp;
tcsCtrl::SensorTemperatures sensorTemperatures;
tcsCtrl::SusTemperatures susTemperatures;
tcsCtrl::DeviceTemperatures deviceTemperatures;
tcsCtrl::HeaterInfo heaterInfo;
lp_vec_t<int16_t, 9> currentVecPdu2 =
lp_vec_t<int16_t, 9>(gp_id_t(objects::PDU2_HANDLER, PDU::pool::PDU_CURRENTS));
tcsCtrl::TcsCtrlInfo tcsCtrlInfo;
DeviceHandlerThermalSet imtqThermalSet;
@ -173,7 +126,7 @@ class ThermalController : public ExtendedControllerBase {
TMP1075::Tmp1075Dataset tmp1075SetTcs1;
TMP1075::Tmp1075Dataset tmp1075SetPlPcdu0;
// damaged
// TMP1075::Tmp1075Dataset tmp1075SetPlPcdu1;
TMP1075::Tmp1075Dataset* tmp1075SetPlPcdu1;
TMP1075::Tmp1075Dataset tmp1075SetIfBoard;
// SUS
@ -227,57 +180,67 @@ class ThermalController : public ExtendedControllerBase {
lp_var_t<float> tempMgm2 =
lp_var_t<float>(objects::MGM_2_LIS3_HANDLER, mgmLis3::TEMPERATURE_CELCIUS);
lp_var_t<float> tempAdcPayloadPcdu = lp_var_t<float>(objects::PLPCDU_HANDLER, plpcdu::TEMP);
lp_vec_t<int16_t, 9> currentVecPdu2 =
lp_vec_t<int16_t, 9>(gp_id_t(objects::PDU2_HANDLER, PDU::pool::PDU_CURRENTS));
// TempLimits
TempLimits acsBoardLimits = TempLimits(-40.0, -40.0, 80.0, 85.0, 85.0);
TempLimits mgtLimits = TempLimits(-40.0, -40.0, 65.0, 70.0, 70.0);
TempLimits rwLimits = TempLimits(-40.0, -40.0, 80.0, 85.0, 85.0);
TempLimits strLimits = TempLimits(-30.0, -20.0, 65.0, 70.0, 80.0);
TempLimits ifBoardLimits = TempLimits(-65.0, -40.0, 80.0, 85.0, 150.0);
TempLimits tcsBoardLimits = TempLimits(-60.0, -40.0, 80.0, 85.0, 130.0);
TempLimits obcLimits = TempLimits(-40.0, -40.0, 80.0, 85.0, 85.0);
TempLimits obcIfBoardLimits = TempLimits(-65.0, -40.0, 80.0, 85.0, 125.0);
TempLimits sBandTransceiverLimits = TempLimits(-40.0, -25.0, 35.0, 40.0, 65.0);
TempLimits pcduP60BoardLimits = TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0);
TempLimits pcduAcuLimits = TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0);
TempLimits pcduPduLimits = TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0);
TempLimits plPcduBoardLimits = TempLimits(-55.0, -40.0, 80.0, 85.0, 125.0);
TempLimits plocMissionBoardLimits = TempLimits(-30.0, -10.0, 40.0, 45.0, 60);
TempLimits plocProcessingBoardLimits = TempLimits(-30.0, -10.0, 40.0, 45.0, 60.0);
TempLimits dacLimits = TempLimits(-65.0, -40.0, 113.0, 118.0, 150.0);
TempLimits cameraLimits = TempLimits(-40.0, -30.0, 60.0, 65.0, 85.0);
TempLimits droLimits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
TempLimits x8Limits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
TempLimits hpaLimits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
TempLimits txLimits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
TempLimits mpaLimits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
TempLimits scexBoardLimits = TempLimits(-60.0, -40.0, 80.0, 85.0, 150.0);
tcsCtrl::TempLimits acsBoardLimits = tcsCtrl::TempLimits(-40.0, -40.0, 80.0, 85.0, 85.0);
tcsCtrl::TempLimits mgtLimits = tcsCtrl::TempLimits(-40.0, -40.0, 65.0, 70.0, 70.0);
tcsCtrl::TempLimits rwLimits = tcsCtrl::TempLimits(-40.0, -40.0, 80.0, 85.0, 85.0);
tcsCtrl::TempLimits strLimits = tcsCtrl::TempLimits(-30.0, -20.0, 65.0, 70.0, 80.0);
tcsCtrl::TempLimits ifBoardLimits = tcsCtrl::TempLimits(-65.0, -40.0, 80.0, 85.0, 150.0);
tcsCtrl::TempLimits tcsBoardLimits = tcsCtrl::TempLimits(-60.0, -40.0, 80.0, 85.0, 130.0);
tcsCtrl::TempLimits obcLimits = tcsCtrl::TempLimits(-40.0, -40.0, 80.0, 85.0, 85.0);
tcsCtrl::TempLimits obcIfBoardLimits = tcsCtrl::TempLimits(-65.0, -40.0, 80.0, 85.0, 125.0);
tcsCtrl::TempLimits sBandTransceiverLimits = tcsCtrl::TempLimits(-40.0, -25.0, 35.0, 40.0, 65.0);
tcsCtrl::TempLimits pcduP60BoardLimits = tcsCtrl::TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0);
tcsCtrl::TempLimits pcduAcuLimits = tcsCtrl::TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0);
tcsCtrl::TempLimits pcduPduLimits = tcsCtrl::TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0);
tcsCtrl::TempLimits plPcduBoardLimits = tcsCtrl::TempLimits(-55.0, -40.0, 80.0, 85.0, 125.0);
tcsCtrl::TempLimits plocMissionBoardLimits = tcsCtrl::TempLimits(-30.0, -10.0, 40.0, 45.0, 60);
tcsCtrl::TempLimits plocProcessingBoardLimits =
tcsCtrl::TempLimits(-30.0, -10.0, 40.0, 45.0, 60.0);
tcsCtrl::TempLimits dacLimits = tcsCtrl::TempLimits(-65.0, -40.0, 113.0, 118.0, 150.0);
tcsCtrl::TempLimits cameraLimits = tcsCtrl::TempLimits(-40.0, -30.0, 60.0, 65.0, 85.0);
tcsCtrl::TempLimits droLimits = tcsCtrl::TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
tcsCtrl::TempLimits x8Limits = tcsCtrl::TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
tcsCtrl::TempLimits hpaLimits = tcsCtrl::TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
tcsCtrl::TempLimits txLimits = tcsCtrl::TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
tcsCtrl::TempLimits mpaLimits = tcsCtrl::TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
tcsCtrl::TempLimits scexBoardLimits = tcsCtrl::TempLimits(-60.0, -40.0, 80.0, 85.0, 150.0);
struct CtrlContext {
double sensorTemp = INVALID_TEMPERATURE;
uint8_t currentSensorIndex = 0;
tcsCtrl::ThermalComponents thermalComponent = tcsCtrl::NONE;
bool redSwitchNrInUse = false;
bool componentAboveCutOffLimit = false;
bool componentAboveUpperLimit = false;
Event overHeatEventToTrigger;
} ctrlCtx;
double sensorTemp = INVALID_TEMPERATURE;
ThermalComponents thermalComponent = NONE;
bool redSwitchNrInUse = false;
MessageQueueId_t camId = MessageQueueIF::NO_QUEUE;
bool componentAboveCutOffLimit = false;
bool componentAboveUpperLimit = false;
Event overHeatEventToTrigger;
bool eBandTooHotFlag = false;
bool camTooHotOneShotFlag = false;
bool scexTooHotFlag = false;
bool plocTooHotFlag = false;
bool pcduSystemTooHotFlag = false;
bool syrlinksTooHotFlag = false;
bool obcTooHotFlag = false;
bool mgtTooHotFlag = false;
bool strTooHotFlag = false;
bool rwTooHotFlag = false;
struct TooHotFlags {
bool eBandTooHotFlag = false;
bool camTooHotOneShotFlag = false;
bool scexTooHotFlag = false;
bool plocTooHotFlag = false;
bool pcduSystemTooHotFlag = false;
bool syrlinksTooHotFlag = false;
bool obcTooHotFlag = false;
bool mgtTooHotFlag = false;
bool strTooHotFlag = false;
bool rwTooHotFlag = false;
} tooHotFlags;
bool transitionWhenHeatersOff = false;
uint32_t transitionWhenHeatersOffCycles = 0;
Mode_t targetMode = MODE_OFF;
Submode_t targetSubmode = SUBMODE_NONE;
uint32_t cycles = 0;
std::array<ThermalState, ThermalComponents::NUM_ENTRIES> thermalStates{};
std::array<HeaterState, heater::NUMBER_OF_SWITCHES> heaterStates{};
std::array<tcsCtrl::ThermalState, tcsCtrl::NUM_THERMAL_COMPONENTS> thermalStates{};
std::array<tcsCtrl::HeaterState, heater::NUMBER_OF_SWITCHES> heaterStates{};
// Initial delay to make sure all pool variables have been initialized their owners.
// Also, wait for system initialization to complete.
@ -298,6 +261,12 @@ class ThermalController : public ExtendedControllerBase {
PoolEntry<uint8_t> heaterSwitchStates = PoolEntry<uint8_t>(heater::NUMBER_OF_SWITCHES);
PoolEntry<int16_t> heaterCurrent = PoolEntry<int16_t>();
PoolEntry<uint8_t> tcsCtrlHeaterOn = PoolEntry<uint8_t>(tcsCtrl::NUM_THERMAL_COMPONENTS);
PoolEntry<uint8_t> tcsCtrlSensorIdx = PoolEntry<uint8_t>(tcsCtrl::NUM_THERMAL_COMPONENTS);
PoolEntry<uint8_t> tcsCtrlHeaterIdx = PoolEntry<uint8_t>(tcsCtrl::NUM_THERMAL_COMPONENTS);
PoolEntry<uint32_t> tcsCtrlStartTimes = PoolEntry<uint32_t>(tcsCtrl::NUM_THERMAL_COMPONENTS);
PoolEntry<uint32_t> tcsCtrlEndTimes = PoolEntry<uint32_t>(tcsCtrl::NUM_THERMAL_COMPONENTS);
static constexpr dur_millis_t MUTEX_TIMEOUT = 50;
void startTransition(Mode_t mode, Submode_t submode) override;
@ -319,8 +288,8 @@ class ThermalController : public ExtendedControllerBase {
bool selectAndReadSensorTemp(HeaterContext& htrCtx);
void heaterSwitchHelperAllOff();
void heaterSwitchHelper(heater::Switch switchNr, HeaterHandler::SwitchState state,
unsigned componentIdx);
void heaterSwitchHelper(heater::Switch switchNr, heater::SwitchState state,
std::optional<unsigned> componentIdx);
void ctrlAcsBoard();
void ctrlMgt();
@ -329,7 +298,6 @@ class ThermalController : public ExtendedControllerBase {
void ctrlIfBoard();
void ctrlTcsBoard();
void ctrlObc();
void ctrlObcIfBoard();
void ctrlSBandTransceiver();
void ctrlPcduP60Board();
void ctrlPcduAcu();
@ -345,7 +313,22 @@ class ThermalController : public ExtendedControllerBase {
void ctrlTx();
void ctrlMpa();
void ctrlScexBoard();
void heaterTransitionControl(const HeaterSwitchStates& currentHeaterStates);
/**
* The transition of heaters might take some time. As long as a transition is
* going on, the TCS controller works in a reduced form. This function takes care
* of tracking transition and capturing their completion.
* @param currentHeaterStates
*/
void heaterTransitionControl(const tcsCtrl::HeaterSwitchStates& currentHeaterStates);
/**
* Control tasks to prevent heaters being on for prolonged periods. Ideally, this
* should never happen, but this task prevents bugs from causing heaters to stay on
* for a long time, which draws a lot of power.
* @param currentHeaterStates
*/
void heaterMaxDurationControl(const tcsCtrl::HeaterSwitchStates& currentHeaterStates);
void crossCheckHeaterStateOfComponentsWhenHeaterGoesOff(heater::Switch switchIdx);
void setMode(Mode_t mode, Submode_t submode);
uint32_t tempFloatToU32() const;
bool tooHotHandler(object_id_t object, bool& oneShotFlag);

View File

@ -9,6 +9,85 @@
namespace tcsCtrl {
/**
* NOP Limit: Hard limit for device, usually from datasheet. Device damage is possible lif NOP limit
* is exceeded.
* OP Limit: Soft limit. Device should be switched off or TCS controller should take action if the
* limit is exceeded to avoid reaching NOP limit
*/
struct TempLimits {
TempLimits(float nopLowerLimit, float opLowerLimit, float cutOffLimit, float opUpperLimit,
float nopUpperLimit)
: opLowerLimit(opLowerLimit),
opUpperLimit(opUpperLimit),
cutOffLimit(cutOffLimit),
nopLowerLimit(nopLowerLimit),
nopUpperLimit(nopUpperLimit) {}
float opLowerLimit;
float opUpperLimit;
float cutOffLimit;
float nopLowerLimit;
float nopUpperLimit;
};
/**
* Abstraction for the state of a single thermal component
*/
struct ThermalState {
uint8_t noSensorAvailableCounter;
// Which sensor is used for this component?
uint8_t sensorIndex = 0;
// Is heating on for that thermal module?
bool heating = false;
// Which switch is being used for heating the component
heater::Switch heaterSwitch = heater::Switch::HEATER_NONE;
// Heater start time and end times as UNIX seconds. Please note that these times will be updated
// when a switch command is sent, with no guarantess that the heater actually went on.
uint32_t heaterStartTime = 0;
uint32_t heaterEndTime = 0;
};
/**
* Abstraction for the state of a single heater.
*/
struct HeaterState {
bool switchTransition = false;
heater::SwitchState target = heater::SwitchState::OFF;
uint8_t heaterSwitchControlCycles = 0;
bool trackHeaterMaxBurnTime = false;
Countdown heaterOnMaxBurnTime;
};
using HeaterSwitchStates = std::array<heater::SwitchState, heater::NUMBER_OF_SWITCHES>;
enum ThermalComponents : uint8_t {
NONE = 0,
ACS_BOARD = 1,
MGT = 2,
RW = 3,
STR = 4,
IF_BOARD = 5,
TCS_BOARD = 6,
OBC = 7,
LEGACY_OBCIF_BOARD = 8,
SBAND_TRANSCEIVER = 9,
PCDUP60_BOARD = 10,
PCDUACU = 11,
PCDUPDU = 12,
PLPCDU_BOARD = 13,
PLOCMISSION_BOARD = 14,
PLOCPROCESSING_BOARD = 15,
DAC = 16,
CAMERA = 17,
DRO = 18,
X8 = 19,
HPA = 20,
TX = 21,
MPA = 22,
SCEX_BOARD = 23,
NUM_THERMAL_COMPONENTS
};
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::TCS_CONTROLLER;
static constexpr Event NO_VALID_SENSOR_TEMPERATURE = MAKE_EVENT(0, severity::MEDIUM);
static constexpr Event NO_HEALTHY_HEATER_AVAILABLE = MAKE_EVENT(1, severity::MEDIUM);
@ -18,6 +97,12 @@ static constexpr Event CAMERA_OVERHEATING = MAKE_EVENT(5, severity::HIGH);
static constexpr Event PCDU_SYSTEM_OVERHEATING = MAKE_EVENT(6, severity::HIGH);
static constexpr Event HEATER_NOT_OFF_FOR_OFF_MODE = MAKE_EVENT(7, severity::MEDIUM);
static constexpr Event MGT_OVERHEATING = MAKE_EVENT(8, severity::HIGH);
//! [EXPORT] : [COMMENT] P1: Module index. P2: Heater index
static constexpr Event TCS_SWITCHING_HEATER_ON = MAKE_EVENT(9, severity::INFO);
//! [EXPORT] : [COMMENT] P1: Module index. P2: Heater index
static constexpr Event TCS_SWITCHING_HEATER_OFF = MAKE_EVENT(10, severity::INFO);
//! [EXPORT] : [COMMENT] P1: Heater index. P2: Maximum burn time for heater.
static constexpr Event TCS_HEATER_MAX_BURN_TIME_REACHED = MAKE_EVENT(11, severity::MEDIUM);
enum SetId : uint32_t {
SENSOR_TEMPERATURES = 0,
@ -25,6 +110,7 @@ enum SetId : uint32_t {
SUS_TEMPERATURES = 2,
COMPONENT_TEMPERATURES = 3,
HEATER_SET = 4,
TCS_CTRL_INFO = 5
};
enum PoolIds : lp_id_t {
@ -92,7 +178,13 @@ enum PoolIds : lp_id_t {
TEMP_ADC_PAYLOAD_PCDU,
HEATER_SWITCH_LIST,
HEATER_CURRENT
HEATER_CURRENT,
HEATER_ON_FOR_COMPONENT_VEC,
SENSOR_USED_FOR_TCS_CTRL,
HEATER_IDX_USED_FOR_TCS_CTRL,
HEATER_START_TIME,
HEATER_END_TIME
};
static const uint8_t ENTRIES_SENSOR_TEMPERATURE_SET = 25;
@ -232,6 +324,29 @@ class HeaterInfo : public StaticLocalDataSet<3> {
lp_var_t<int16_t> heaterCurrent = lp_var_t<int16_t>(sid.objectId, PoolIds::HEATER_CURRENT, this);
};
class TcsCtrlInfo : public StaticLocalDataSet<6> {
public:
explicit TcsCtrlInfo(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, TCS_CTRL_INFO) {}
explicit TcsCtrlInfo(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, TCS_CTRL_INFO)) {}
lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS> heatingOnVec =
lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS>(
sid.objectId, PoolIds::HEATER_ON_FOR_COMPONENT_VEC, this);
lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS> sensorIdxUsedForTcsCtrl =
lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS>(sid.objectId,
PoolIds::SENSOR_USED_FOR_TCS_CTRL, this);
lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS> heaterSwitchIdx =
lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS>(
sid.objectId, PoolIds::HEATER_IDX_USED_FOR_TCS_CTRL, this);
lp_vec_t<uint32_t, tcsCtrl::NUM_THERMAL_COMPONENTS> heaterStartTimes =
lp_vec_t<uint32_t, tcsCtrl::NUM_THERMAL_COMPONENTS>(sid.objectId, PoolIds::HEATER_START_TIME,
this);
lp_vec_t<uint32_t, tcsCtrl::NUM_THERMAL_COMPONENTS> heaterEndTimes =
lp_vec_t<uint32_t, tcsCtrl::NUM_THERMAL_COMPONENTS>(sid.objectId, PoolIds::HEATER_END_TIME,
this);
};
} // namespace tcsCtrl
#endif /* MISSION_CONTROLLER_CONTROLLERDEFINITIONS_THERMALCONTROLLERDEFINITIONS_H_ */

View File

@ -91,19 +91,21 @@ EiveFaultHandler EIVE_FAULT_HANDLER;
} // namespace cfdp
std::atomic_bool tcs::TCS_BOARD_SHORTLY_UNAVAILABLE = false;
std::atomic_bool core::SAVE_PUS_SEQUENCE_COUNT = false;
std::atomic_bool core::SAVE_CFDP_SEQUENCE_COUNT = false;
void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFunnel** pusFunnel,
CfdpTmFunnel** cfdpFunnel, SdCardMountedIF& sdcMan,
StorageManagerIF** ipcStore, StorageManagerIF** tmStore,
PersistentTmStores& stores,
uint32_t eventManagerQueueDepth) {
uint32_t eventManagerQueueDepth, bool enableHkSets) {
// Framework objects
new EventManager(objects::EVENT_MANAGER, eventManagerQueueDepth);
auto healthTable = new HealthTable(objects::HEALTH_TABLE);
if (healthTable_ != nullptr) {
*healthTable_ = healthTable;
}
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER);
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER, 5, enableHkSets, 120);
new VerificationReporter();
auto* timeStamper = new CdsShortTimeStamper(objects::TIME_STAMPER);
StorageManagerIF* tcStore;
@ -155,9 +157,11 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun
new PusDistributor(config::EIVE_PUS_APID, objects::PUS_PACKET_DISTRIBUTOR, ccsdsDistrib);
PusTmFunnel::FunnelCfg pusFunnelCfg(objects::PUS_TM_FUNNEL, "PusTmFunnel", **tmStore, **ipcStore,
config::MAX_PUS_FUNNEL_QUEUE_DEPTH);
config::MAX_PUS_FUNNEL_QUEUE_DEPTH, sdcMan,
config::PUS_SEQUENCE_COUNT_FILE,
core::SAVE_PUS_SEQUENCE_COUNT);
// The PUS funnel routes all live TM to the live destinations and to the TM stores.
*pusFunnel = new PusTmFunnel(pusFunnelCfg, *ramToFileStore, *timeStamper, sdcMan);
*pusFunnel = new PusTmFunnel(pusFunnelCfg, *ramToFileStore, *timeStamper);
// MISC store and PUS funnel to MISC store routing
{
@ -216,7 +220,9 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun
stores.cfdpStore->getReportReceptionQueue(0));
}
PusTmFunnel::FunnelCfg cfdpFunnelCfg(objects::CFDP_TM_FUNNEL, "CfdpTmFunnel", **tmStore,
**ipcStore, config::MAX_CFDP_FUNNEL_QUEUE_DEPTH);
**ipcStore, config::MAX_CFDP_FUNNEL_QUEUE_DEPTH, sdcMan,
config::CFDP_SEQUENCE_COUNT_FILE,
core::SAVE_CFDP_SEQUENCE_COUNT);
*cfdpFunnel = new CfdpTmFunnel(cfdpFunnelCfg, stores.cfdpStore->getReportReceptionQueue(0),
*ramToFileStore, config::EIVE_CFDP_APID);
@ -305,9 +311,9 @@ void ObjectFactory::createGenericHeaterComponents(GpioIF& gpioIF, PowerSwitchIF&
heaterHandler->connectModeTreeParent(satsystem::tcs::SUBSYSTEM);
}
void ObjectFactory::createThermalController(HeaterHandler& heaterHandler) {
void ObjectFactory::createThermalController(HeaterHandler& heaterHandler, bool pollPlPcduTmp1) {
auto* tcsCtrl = new ThermalController(objects::THERMAL_CONTROLLER, heaterHandler,
tcs::TCS_BOARD_SHORTLY_UNAVAILABLE);
tcs::TCS_BOARD_SHORTLY_UNAVAILABLE, pollPlPcduTmp1);
tcsCtrl->connectModeTreeParent(satsystem::tcs::SUBSYSTEM);
}
void ObjectFactory::createRwAssy(PowerSwitchIF& pwrSwitcher, power::Switch_t theSwitch,

View File

@ -45,11 +45,12 @@ namespace ObjectFactory {
void produceGenericObjects(HealthTableIF** healthTable, PusTmFunnel** pusFunnel,
CfdpTmFunnel** cfdpFunnel, SdCardMountedIF& sdcMan,
StorageManagerIF** ipcStore, StorageManagerIF** tmStore,
PersistentTmStores& stores, uint32_t eventManagerQueueDepth);
PersistentTmStores& stores, uint32_t eventManagerQueueDepth,
bool enableHkSets);
void createGenericHeaterComponents(GpioIF& gpioIF, PowerSwitchIF& pwrSwitcher,
HeaterHandler*& heaterHandler);
void createThermalController(HeaterHandler& heaterHandler);
void createThermalController(HeaterHandler& heaterHandler, bool pollPlPcduTmp1);
void createRwAssy(PowerSwitchIF& pwrSwitcher, power::Switch_t theSwitch,
std::array<DeviceHandlerBase*, 4> rws, std::array<object_id_t, 4> rwIds);
void createSusAssy(PowerSwitchIF& pwrSwitcher, std::array<DeviceHandlerBase*, 12> suses);

View File

@ -39,56 +39,67 @@ ReturnValue_t pst::pstSyrlinks(FixedTimeslotTaskIF *thisSequence) {
// I don't think this needs to be in a PST because linux takes care of bus serialization, but
// keep it like this for now, it works
ReturnValue_t pst::pstI2cProcessingSystem(FixedTimeslotTaskIF *thisSequence) {
ReturnValue_t pst::pstI2c(TmpSchedConfig schedConf, FixedTimeslotTaskIF *thisSequence) {
// Length of a communication cycle
uint32_t length = thisSequence->getPeriodMs();
static_cast<void>(length);
// These are actually part of another bus, but this works, so keep it like this for now
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_0, length * 0.2,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_0, length * 0.2, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_0, length * 0.2, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_0, length * 0.3, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_0, length * 0.3, DeviceHandlerIF::GET_READ);
if (schedConf.scheduleTmpDev0) {
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_0, length * 0,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_0, length * 0, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_0, length * 0.1, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_0, length * 0.1, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_0, length * 0.1, DeviceHandlerIF::GET_READ);
}
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_1, length * 0.4,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_1, length * 0.4, DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_1, length * 0.4, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_1, length * 0.5, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_1, length * 0.5, DeviceHandlerIF::GET_READ);
if (schedConf.scheduleTmpDev1) {
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_1, length * 0.2,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_1, length * 0.2,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_1, length * 0.2, DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_1, length * 0.3, DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_1, length * 0.3, DeviceHandlerIF::GET_READ);
}
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_0, length * 0.6,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_0, length * 0.6,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_0, length * 0.6,
DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_0, length * 0.7,
DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_0, length * 0.7, DeviceHandlerIF::GET_READ);
// damaged
/*
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_1, length * 0.4,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_1, length * 0.4,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_1, length * 0.4,
DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_1, length * 0.4,
DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_1, length * 0.4, DeviceHandlerIF::GET_READ);
*/
thisSequence->addSlot(objects::TMP1075_HANDLER_IF_BOARD, length * 0.8,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::TMP1075_HANDLER_IF_BOARD, length * 0.8,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_IF_BOARD, length * 0.8,
DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_IF_BOARD, length * 0.9,
DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::TMP1075_HANDLER_IF_BOARD, length * 0.9, DeviceHandlerIF::GET_READ);
if (schedConf.schedulePlPcduDev0) {
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_0, length * 0.4,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_0, length * 0.4,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_0, length * 0.4,
DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_0, length * 0.5,
DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_0, length * 0.5,
DeviceHandlerIF::GET_READ);
}
if (schedConf.schedulePlPcduDev1) {
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_1, length * 0.6,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_1, length * 0.6,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_1, length * 0.6,
DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_1, length * 0.7,
DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_1, length * 0.7,
DeviceHandlerIF::GET_READ);
}
if (schedConf.scheduleIfBoardDev) {
thisSequence->addSlot(objects::TMP1075_HANDLER_IF_BOARD, length * 0.8,
DeviceHandlerIF::PERFORM_OPERATION);
thisSequence->addSlot(objects::TMP1075_HANDLER_IF_BOARD, length * 0.8,
DeviceHandlerIF::SEND_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_IF_BOARD, length * 0.8,
DeviceHandlerIF::GET_WRITE);
thisSequence->addSlot(objects::TMP1075_HANDLER_IF_BOARD, length * 0.9,
DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::TMP1075_HANDLER_IF_BOARD, length * 0.9,
DeviceHandlerIF::GET_READ);
}
static_cast<void>(length);
return thisSequence->checkSequence();
}

View File

@ -39,6 +39,16 @@ struct AcsPstCfg {
bool scheduleStr = true;
};
// Default config is for FM.
struct TmpSchedConfig {
bool scheduleTmpDev0 = true;
bool scheduleTmpDev1 = true;
bool schedulePlPcduDev0 = true;
// damaged on FM
bool schedulePlPcduDev1 = false;
bool scheduleIfBoardDev = true;
};
/**
* @brief This function creates the PST for all gomspace devices.
* @details
@ -51,7 +61,7 @@ ReturnValue_t pstSyrlinks(FixedTimeslotTaskIF* thisSequence);
ReturnValue_t pstTcsAndAcs(FixedTimeslotTaskIF* thisSequence, AcsPstCfg cfg);
ReturnValue_t pstI2cProcessingSystem(FixedTimeslotTaskIF* thisSequence);
ReturnValue_t pstI2c(TmpSchedConfig schedConf, FixedTimeslotTaskIF* thisSequence);
/**
* Generic test PST

View File

@ -34,6 +34,9 @@ enum Copy : int { COPY_0, COPY_1, NO_COPY, SELF_COPY, ALL_COPY };
namespace core {
extern std::atomic_bool SAVE_PUS_SEQUENCE_COUNT;
extern std::atomic_bool SAVE_CFDP_SEQUENCE_COUNT;
// TODO: Support for status? Or maybe some command to quickly get information whether a unit
// is running.
enum SystemctlCmd : uint8_t { START = 0, STOP = 1, RESTART = 2, NUM_CMDS = 3 };

View File

@ -31,12 +31,12 @@ void buildPtgInertialSequence(Subsystem& ss, ModeListEntry& eh);
static const auto OFF = HasModesIF::MODE_OFF;
static const auto NML = DeviceHandlerIF::MODE_NORMAL;
void satsystem::init() {
void satsystem::init(bool commandPlPcdu1) {
auto& acsSubsystem = acs::init();
acsSubsystem.connectModeTreeParent(EIVE_SYSTEM);
auto& payloadSubsystem = payload::init();
payloadSubsystem.connectModeTreeParent(EIVE_SYSTEM);
auto& tcsSubsystem = tcs::init();
auto& tcsSubsystem = tcs::init(commandPlPcdu1);
tcsSubsystem.connectModeTreeParent(EIVE_SYSTEM);
auto& comSubsystem = com::init();
comSubsystem.connectModeTreeParent(EIVE_SYSTEM);

View File

@ -5,7 +5,7 @@
namespace satsystem {
void init();
void init(bool commandPlPcdu1);
extern EiveSystem EIVE_SYSTEM;

View File

@ -20,7 +20,7 @@ ReturnValue_t TmpDevFdir::eventReceived(EventMessage* event) {
// We'll try a recovery as long as defined in MAX_REBOOT.
// Might cause some AssemblyBase cycles, so keep number low.
// Ignored for TMP device, no way to power cycle it without going to OFF/BOOT mode.
// handleRecovery(event->getEvent());
setFaulty(event->getEvent());
break;
case DeviceHandlerIF::DEVICE_INTERPRETING_REPLY_FAILED:
case DeviceHandlerIF::DEVICE_READING_REPLY_FAILED:
@ -28,8 +28,10 @@ ReturnValue_t TmpDevFdir::eventReceived(EventMessage* event) {
case DeviceHandlerIF::DEVICE_UNKNOWN_REPLY: // Some DH's generate generic reply-ids.
case DeviceHandlerIF::DEVICE_BUILDING_COMMAND_FAILED:
// These faults all mean that there were stupid replies from a device.
// With now way to do a recovery, set the device to faulty immediately.
setFaulty(event->getEvent());
// With no way to do a recovery, set the device to faulty instead of trying a recovery.
if (strangeReplyCount.incrementAndCheck()) {
setFaulty(event->getEvent());
}
break;
case DeviceHandlerIF::DEVICE_SENDING_COMMAND_FAILED:
case DeviceHandlerIF::DEVICE_REQUESTING_REPLY_FAILED:
@ -40,7 +42,9 @@ ReturnValue_t TmpDevFdir::eventReceived(EventMessage* event) {
break;
}
// else
setFaulty(event->getEvent());
if (missedReplyCount.incrementAndCheck()) {
setFaulty(event->getEvent());
}
break;
case StorageManagerIF::GET_DATA_FAILED:
case StorageManagerIF::STORE_DATA_FAILED:

View File

@ -10,8 +10,8 @@ TcsSubsystem satsystem::tcs::SUBSYSTEM(objects::TCS_SUBSYSTEM, 12, 24);
namespace {
// Alias for checker function
const auto check = subsystem::checkInsert;
void buildOffSequence(Subsystem& ss, ModeListEntry& eh);
void buildNormalSequence(Subsystem& ss, ModeListEntry& eh);
void buildOffSequence(Subsystem& ss, ModeListEntry& eh, bool commandPlPcdu1);
void buildNormalSequence(Subsystem& ss, ModeListEntry& eh, bool commandPlPcdu1);
} // namespace
static const auto OFF = HasModesIF::MODE_OFF;
@ -27,17 +27,17 @@ auto TCS_TABLE_NORMAL_TGT = std::make_pair((NML << 24) | 1, FixedArrayList<ModeL
auto TCS_TABLE_NORMAL_TRANS_0 = std::make_pair((NML << 24) | 2, FixedArrayList<ModeListEntry, 7>());
auto TCS_TABLE_NORMAL_TRANS_1 = std::make_pair((NML << 24) | 3, FixedArrayList<ModeListEntry, 2>());
Subsystem& satsystem::tcs::init() {
Subsystem& satsystem::tcs::init(bool commandPlPcdu1) {
ModeListEntry entry;
buildOffSequence(SUBSYSTEM, entry);
buildNormalSequence(SUBSYSTEM, entry);
buildOffSequence(SUBSYSTEM, entry, commandPlPcdu1);
buildNormalSequence(SUBSYSTEM, entry, commandPlPcdu1);
SUBSYSTEM.setInitialMode(OFF);
return SUBSYSTEM;
}
namespace {
void buildOffSequence(Subsystem& ss, ModeListEntry& eh) {
void buildOffSequence(Subsystem& ss, ModeListEntry& eh, bool commandPlPcdu1) {
std::string context = "satsystem::tcs::buildOffSequence";
auto ctxc = context.c_str();
// Insert Helper Table
@ -67,7 +67,9 @@ void buildOffSequence(Subsystem& ss, ModeListEntry& eh) {
iht(objects::TMP1075_HANDLER_TCS_0, OFF, 0, TCS_TABLE_OFF_TRANS_1.second);
iht(objects::TMP1075_HANDLER_TCS_1, OFF, 0, TCS_TABLE_OFF_TRANS_1.second);
iht(objects::TMP1075_HANDLER_PLPCDU_0, OFF, 0, TCS_TABLE_OFF_TRANS_1.second);
// TMP PL PCDU 1 is damaged
if (commandPlPcdu1) {
iht(objects::TMP1075_HANDLER_PLPCDU_1, OFF, 0, TCS_TABLE_OFF_TRANS_1.second);
}
iht(objects::TMP1075_HANDLER_IF_BOARD, OFF, 0, TCS_TABLE_OFF_TRANS_1.second);
check(ss.addTable(TableEntry(TCS_TABLE_OFF_TRANS_1.first, &TCS_TABLE_OFF_TRANS_1.second)), ctxc);
@ -79,7 +81,7 @@ void buildOffSequence(Subsystem& ss, ModeListEntry& eh) {
ctxc);
}
void buildNormalSequence(Subsystem& ss, ModeListEntry& eh) {
void buildNormalSequence(Subsystem& ss, ModeListEntry& eh, bool commandPlPcdu1) {
std::string context = "satsystem::tcs::buildNormalSequence";
auto ctxc = context.c_str();
// Insert Helper Table
@ -105,7 +107,9 @@ void buildNormalSequence(Subsystem& ss, ModeListEntry& eh) {
iht(objects::TMP1075_HANDLER_TCS_0, NML, 0, TCS_TABLE_NORMAL_TRANS_0.second);
iht(objects::TMP1075_HANDLER_TCS_1, NML, 0, TCS_TABLE_NORMAL_TRANS_0.second);
iht(objects::TMP1075_HANDLER_PLPCDU_0, NML, 0, TCS_TABLE_NORMAL_TRANS_0.second);
// TMP PL PCDU 1 is damaged
if (commandPlPcdu1) {
iht(objects::TMP1075_HANDLER_PLPCDU_1, NML, 0, TCS_TABLE_NORMAL_TRANS_0.second);
}
iht(objects::TMP1075_HANDLER_IF_BOARD, NML, 0, TCS_TABLE_NORMAL_TRANS_0.second);
check(ss.addTable(TableEntry(TCS_TABLE_NORMAL_TRANS_0.first, &TCS_TABLE_NORMAL_TRANS_0.second)),
ctxc);

View File

@ -7,7 +7,7 @@ namespace satsystem {
namespace tcs {
extern TcsSubsystem SUBSYSTEM;
Subsystem& init();
Subsystem& init(bool commandPlPcdu1);
} // namespace tcs
} // namespace satsystem

View File

@ -51,9 +51,13 @@ ReturnValue_t HeaterHandler::performOperation(uint8_t operationCode) {
if (mainLineSwitcher->getSwitchState(mainLineSwitch) == SWITCH_OFF) {
waitForSwitchOff = false;
mode = MODE_OFF;
busyWithSwitchCommanding = false;
modeHelper.modeChanged(mode, submode);
}
}
if (busyWithSwitchCommanding and heaterCmdBusyCd.hasTimedOut()) {
busyWithSwitchCommanding = false;
}
} catch (const std::out_of_range& e) {
sif::warning << "HeaterHandler::performOperation: "
"Out of range error | "
@ -93,7 +97,7 @@ ReturnValue_t HeaterHandler::initialize() {
ReturnValue_t HeaterHandler::initializeHeaterMap() {
for (power::Switch_t switchNr = 0; switchNr < heater::NUMBER_OF_SWITCHES; switchNr++) {
heaterVec.push_back(HeaterWrapper(helper.heaters[switchNr], SwitchState::OFF));
heaterVec.push_back(HeaterWrapper(helper.heaters[switchNr], heater::SwitchState::OFF));
}
return returnvalue::OK;
}
@ -101,23 +105,23 @@ ReturnValue_t HeaterHandler::initializeHeaterMap() {
void HeaterHandler::readCommandQueue() {
ReturnValue_t result = returnvalue::OK;
CommandMessage command;
do {
if (not busyWithSwitchCommanding) {
result = commandQueue->receiveMessage(&command);
if (result == MessageQueueIF::EMPTY) {
break;
return;
} else if (result != returnvalue::OK) {
sif::warning << "HeaterHandler::readCommandQueue: Message reception error" << std::endl;
break;
}
result = actionHelper.handleActionMessage(&command);
if (result == returnvalue::OK) {
continue;
return;
}
result = modeHelper.handleModeCommand(&command);
if (result == returnvalue::OK) {
continue;
return;
}
} while (result == returnvalue::OK);
result = actionHelper.handleActionMessage(&command);
if (result == returnvalue::OK) {
return;
}
}
}
ReturnValue_t HeaterHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
@ -167,6 +171,8 @@ ReturnValue_t HeaterHandler::executeAction(ActionId_t actionId, MessageQueueId_t
heater.action = action;
heater.cmdActive = true;
heater.replyQueue = commandedBy;
busyWithSwitchCommanding = true;
heaterCmdBusyCd.resetTimer();
return returnvalue::OK;
}
@ -208,7 +214,7 @@ ReturnValue_t HeaterHandler::sendSwitchCommand(uint8_t switchNr, ReturnValue_t o
void HeaterHandler::handleSwitchHandling() {
for (uint8_t idx = 0; idx < heater::NUMBER_OF_SWITCHES; idx++) {
auto health = heaterVec[idx].healthDevice->getHealth();
if (heaterVec[idx].switchState == SwitchState::ON) {
if (heaterVec[idx].switchState == heater::SwitchState::ON) {
// If a heater is still on but the device was marked faulty by the operator, the SW
// will shut down the heater
if (health == HasHealthIF::FAULTY or health == HasHealthIF::PERMANENT_FAULTY) {
@ -249,6 +255,7 @@ void HeaterHandler::handleSwitchOnCommand(heater::Switch heaterIdx) {
sif::error << "HeaterHandler::handleSwitchOnCommand: Main switch setting on timeout"
<< std::endl;
heater.cmdActive = false;
busyWithSwitchCommanding = false;
heater.waitMainSwitchOn = false;
if (heater.replyQueue != commandQueue->getId()) {
actionHelper.finish(false, heater.replyQueue, heater.action, MAIN_SWITCH_SET_TIMEOUT);
@ -259,27 +266,25 @@ void HeaterHandler::handleSwitchOnCommand(heater::Switch heaterIdx) {
// Check state of main line switch
ReturnValue_t mainSwitchState = mainLineSwitcher->getSwitchState(mainLineSwitch);
if (mainSwitchState == PowerSwitchIF::SWITCH_ON) {
if (getSwitchState(heaterIdx) == SwitchState::OFF) {
gpioId_t gpioId = heater.gpioId;
result = gpioInterface->pullHigh(gpioId);
if (result != returnvalue::OK) {
sif::error << "HeaterHandler::handleSwitchOnCommand: Failed to pull gpio with id " << gpioId
<< " high" << std::endl;
triggerEvent(GPIO_PULL_HIGH_FAILED, result);
} else {
triggerEvent(HEATER_WENT_ON, heaterIdx, 0);
EventManagerIF::triggerEvent(helper.heaters[heaterIdx].first->getObjectId(), MODE_INFO,
MODE_ON, 0);
{
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
heater.switchState = ON;
}
}
} else {
triggerEvent(SWITCH_ALREADY_ON, heaterIdx);
gpioId_t gpioId = heater.gpioId;
result = gpioInterface->pullHigh(gpioId);
if (result != returnvalue::OK) {
sif::error << "HeaterHandler::handleSwitchOnCommand: Failed to pull GPIO with ID " << gpioId
<< " high" << std::endl;
triggerEvent(GPIO_PULL_HIGH_FAILED, result);
}
if (result == returnvalue::OK) {
triggerEvent(HEATER_WENT_ON, heaterIdx, 0);
{
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
heater.switchState = heater::SwitchState::ON;
}
EventManagerIF::triggerEvent(helper.heaters[heaterIdx].first->getObjectId(), MODE_INFO,
MODE_ON, 0);
busyWithSwitchCommanding = false;
mode = HasModesIF::MODE_ON;
modeHelper.modeChanged(mode, submode);
}
mode = HasModesIF::MODE_ON;
modeHelper.modeChanged(mode, submode);
// There is no need to send action finish replies if the sender was the
// HeaterHandler itself
if (heater.replyQueue != commandQueue->getId()) {
@ -312,30 +317,33 @@ void HeaterHandler::handleSwitchOnCommand(heater::Switch heaterIdx) {
void HeaterHandler::handleSwitchOffCommand(heater::Switch heaterIdx) {
ReturnValue_t result = returnvalue::OK;
auto& heater = heaterVec.at(heaterIdx);
// Check whether switch is already off
if (getSwitchState(heaterIdx)) {
gpioId_t gpioId = heater.gpioId;
result = gpioInterface->pullLow(gpioId);
if (result != returnvalue::OK) {
sif::error << "HeaterHandler::handleSwitchOffCommand: Failed to pull gpio with id" << gpioId
<< " low" << std::endl;
triggerEvent(GPIO_PULL_LOW_FAILED, result);
} else {
gpioId_t gpioId = heater.gpioId;
result = gpioInterface->pullLow(gpioId);
if (result != returnvalue::OK) {
sif::error << "HeaterHandler::handleSwitchOffCommand: Failed to pull gpio with id" << gpioId
<< " low" << std::endl;
triggerEvent(GPIO_PULL_LOW_FAILED, result);
}
if (result == returnvalue::OK) {
// Check whether switch is already off
if (getSwitchState(heaterIdx) == heater::SwitchState::ON) {
{
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
heater.switchState = OFF;
heater.switchState = heater::SwitchState::OFF;
}
triggerEvent(HEATER_WENT_OFF, heaterIdx, 0);
EventManagerIF::triggerEvent(helper.heaters[heaterIdx].first->getObjectId(), MODE_INFO,
MODE_OFF, 0);
// When all switches are off, also main line switch will be turned off
if (allSwitchesOff()) {
mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
waitForSwitchOff = true;
}
} else {
triggerEvent(SWITCH_ALREADY_OFF, heaterIdx);
}
EventManagerIF::triggerEvent(helper.heaters[heaterIdx].first->getObjectId(), MODE_INFO,
MODE_OFF, 0);
// When all switches are off, also main line switch will be turned off
if (allSwitchesOff()) {
mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
waitForSwitchOff = true;
} else {
busyWithSwitchCommanding = false;
}
} else {
triggerEvent(SWITCH_ALREADY_OFF, heaterIdx);
}
if (heater.replyQueue != NO_COMMANDER) {
// Report back switch command reply if necessary
@ -348,15 +356,15 @@ void HeaterHandler::handleSwitchOffCommand(heater::Switch heaterIdx) {
heater.cmdActive = false;
}
HeaterHandler::SwitchState HeaterHandler::getSwitchState(heater::Switch switchNr) const {
heater::SwitchState HeaterHandler::getSwitchState(heater::Switch switchNr) const {
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
return heaterVec.at(switchNr).switchState;
}
ReturnValue_t HeaterHandler::switchHeater(heater::Switch heater, SwitchState switchState) {
if (switchState == SwitchState::ON) {
ReturnValue_t HeaterHandler::switchHeater(heater::Switch heater, heater::SwitchState switchState) {
if (switchState == heater::SwitchState::ON) {
return sendSwitchCommand(heater, PowerSwitchIF::SWITCH_ON);
} else if (switchState == SwitchState::OFF) {
} else if (switchState == heater::SwitchState::OFF) {
return sendSwitchCommand(heater, PowerSwitchIF::SWITCH_OFF);
}
return returnvalue::FAILED;
@ -365,10 +373,10 @@ ReturnValue_t HeaterHandler::switchHeater(heater::Switch heater, SwitchState swi
void HeaterHandler::announceMode(bool recursive) {
triggerEvent(MODE_INFO, mode, submode);
std::array<SwitchState, 8> states;
std::array<heater::SwitchState, 8> states;
getAllSwitchStates(states);
for (unsigned idx = 0; idx < helper.heaters.size(); idx++) {
if (states[idx] == ON) {
if (states[idx] == heater::SwitchState::ON) {
EventManagerIF::triggerEvent(helper.heaters[idx].first->getObjectId(), MODE_INFO, MODE_ON, 0);
} else {
EventManagerIF::triggerEvent(helper.heaters[idx].first->getObjectId(), MODE_INFO, MODE_OFF,
@ -397,7 +405,7 @@ ModeTreeChildIF& HeaterHandler::getModeTreeChildIF() { return *this; }
object_id_t HeaterHandler::getObjectId() const { return SystemObject::getObjectId(); }
ReturnValue_t HeaterHandler::getAllSwitchStates(std::array<SwitchState, 8>& statesBuf) {
ReturnValue_t HeaterHandler::getAllSwitchStates(std::array<heater::SwitchState, 8>& statesBuf) {
{
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
if (mg.getLockResult() != returnvalue::OK) {
@ -411,13 +419,13 @@ ReturnValue_t HeaterHandler::getAllSwitchStates(std::array<SwitchState, 8>& stat
}
bool HeaterHandler::allSwitchesOff() {
bool allSwitchesOrd = false;
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
/* Or all switches. As soon one switch is on, allSwitchesOrd will be true */
for (power::Switch_t switchNr = 0; switchNr < heater::NUMBER_OF_SWITCHES; switchNr++) {
allSwitchesOrd = allSwitchesOrd || heaterVec.at(switchNr).switchState;
if (heaterVec.at(switchNr).switchState == heater::SwitchState::ON) {
return false;
}
}
return !allSwitchesOrd;
return true;
}
MessageQueueId_t HeaterHandler::getCommandQueue() const { return commandQueue->getId(); }
@ -432,7 +440,7 @@ ReturnValue_t HeaterHandler::getSwitchState(uint8_t switchNr) const {
if (switchNr > 7) {
return returnvalue::FAILED;
}
if (getSwitchState(static_cast<heater::Switch>(switchNr)) == SwitchState::ON) {
if (getSwitchState(static_cast<heater::Switch>(switchNr)) == heater::SwitchState::ON) {
return PowerSwitchIF::SWITCH_ON;
}
return PowerSwitchIF::SWITCH_OFF;

View File

@ -60,7 +60,6 @@ class HeaterHandler : public ExecutableObjectIF,
static const ReturnValue_t COMMAND_ALREADY_WAITING = MAKE_RETURN_CODE(0xA5);
enum CmdSourceParam : uint8_t { INTERNAL = 0, EXTERNAL = 1 };
enum SwitchState : uint8_t { ON = 1, OFF = 0 };
/** Device command IDs */
static const DeviceCommandId_t SWITCH_HEATER = 0x0;
@ -69,14 +68,14 @@ class HeaterHandler : public ExecutableObjectIF,
PowerSwitchIF* mainLineSwitcherObjectId, power::Switch_t mainLineSwitch);
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent) override;
ReturnValue_t getAllSwitchStates(std::array<SwitchState, 8>& statesBuf);
ReturnValue_t getAllSwitchStates(std::array<heater::SwitchState, 8>& statesBuf);
virtual ~HeaterHandler();
protected:
enum SwitchAction : uint8_t { SET_SWITCH_OFF, SET_SWITCH_ON, NONE };
ReturnValue_t switchHeater(heater::Switch heater, SwitchState switchState);
ReturnValue_t switchHeater(heater::Switch heater, heater::SwitchState switchState);
HasHealthIF::HealthState getHealth(heater::Switch heater);
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
@ -121,14 +120,14 @@ class HeaterHandler : public ExecutableObjectIF,
* @param mainSwitchCountdown Sets timeout to wait for main switch being set on.
*/
struct HeaterWrapper {
HeaterWrapper(HeaterPair pair, SwitchState initState)
HeaterWrapper(HeaterPair pair, heater::SwitchState initState)
: healthDevice(pair.first), gpioId(pair.second), switchState(initState) {}
HealthDevice* healthDevice = nullptr;
gpioId_t gpioId = gpio::NO_GPIO;
SwitchAction action = SwitchAction::NONE;
MessageQueueId_t replyQueue = MessageQueueIF::NO_QUEUE;
bool cmdActive = false;
SwitchState switchState = SwitchState::OFF;
heater::SwitchState switchState = heater::SwitchState::OFF;
bool waitMainSwitchOn = false;
Countdown mainSwitchCountdown;
};
@ -148,6 +147,7 @@ class HeaterHandler : public ExecutableObjectIF,
/** Size of command queue */
size_t cmdQueueSize = 20;
bool waitForSwitchOff = true;
bool busyWithSwitchCommanding = false;
GpioIF* gpioInterface = nullptr;
@ -163,6 +163,7 @@ class HeaterHandler : public ExecutableObjectIF,
power::Switch_t mainLineSwitch;
ActionHelper actionHelper;
Countdown heaterCmdBusyCd = Countdown(2000);
StorageManagerIF* ipcStore = nullptr;
@ -175,7 +176,7 @@ class HeaterHandler : public ExecutableObjectIF,
* @brief Returns the state of a switch (ON - true, or OFF - false).
* @param switchNr The number of the switch to check.
*/
SwitchState getSwitchState(heater::Switch switchNr) const;
heater::SwitchState getSwitchState(heater::Switch switchNr) const;
/**
* @brief This function runs commands waiting for execution.

View File

@ -1,4 +1,5 @@
#include <OBSWConfig.h>
#include <fsfw/datapool/PoolReadGuard.h>
#include <mission/tcs/Tmp1075Definitions.h>
#include <mission/tcs/Tmp1075Handler.h>
@ -11,14 +12,12 @@ Tmp1075Handler::Tmp1075Handler(object_id_t objectId, object_id_t comIF, CookieIF
Tmp1075Handler::~Tmp1075Handler() {}
void Tmp1075Handler::doStartUp() {
if (getMode() == _MODE_START_UP) {
setMode(MODE_ON);
}
}
void Tmp1075Handler::doStartUp() { setMode(MODE_ON); }
void Tmp1075Handler::doShutDown() {
communicationStep = CommunicationStep::START_ADC_CONVERSION;
PoolReadGuard pg(&dataset);
dataset.setValidity(false, true);
setMode(_MODE_POWER_DOWN);
}
@ -134,12 +133,14 @@ ReturnValue_t Tmp1075Handler::initializeLocalDataPool(localpool::DataPool &local
return returnvalue::OK;
}
void Tmp1075Handler::setModeNormal() { setMode(_MODE_TO_NORMAL); }
ReturnValue_t Tmp1075Handler::setHealth(HealthState health) {
if (health != FAULTY and health != PERMANENT_FAULTY and health != HEALTHY and
health != EXTERNAL_CONTROL) {
return returnvalue::FAILED;
}
return returnvalue::OK;
// Required because we do not have an assembly.
if (health == FAULTY or health == PERMANENT_FAULTY) {
setMode(_MODE_SHUT_DOWN);
}
return DeviceHandlerBase::setHealth(health);
}

View File

@ -20,8 +20,6 @@ class Tmp1075Handler : public DeviceHandlerBase {
Tmp1075Handler(object_id_t objectId, object_id_t comIF, CookieIF *comCookie);
virtual ~Tmp1075Handler();
void setModeNormal();
protected:
void doStartUp() override;
void doShutDown() override;

View File

@ -4,6 +4,7 @@
#include <cstdint>
namespace heater {
enum Switch : uint8_t {
HEATER_0_PLOC_PROC_BRD,
HEATER_1_PCDU_PDU,
@ -13,9 +14,13 @@ enum Switch : uint8_t {
HEATER_5_STR,
HEATER_6_DRO,
HEATER_7_S_BAND,
NUMBER_OF_SWITCHES
NUMBER_OF_SWITCHES = 8,
HEATER_NONE = 0xff
};
}
enum SwitchState : uint8_t { ON = 1, OFF = 0 };
} // namespace heater
namespace tcs {

View File

@ -15,8 +15,16 @@ const char* CfdpTmFunnel::getName() const { return "CFDP TM Funnel"; }
ReturnValue_t CfdpTmFunnel::performOperation(uint8_t) {
TmTcMessage currentMessage;
ReturnValue_t status;
unsigned int count = 0;
ReturnValue_t status = tmQueue->receiveMessage(&currentMessage);
if (saveSequenceCount) {
status = saveSequenceCountToFile();
if (status != returnvalue::OK) {
sif::error << "CfdpTmFunnel: Storing sequence count to file has failed" << std::endl;
}
saveSequenceCount = false;
}
status = tmQueue->receiveMessage(&currentMessage);
while (status == returnvalue::OK) {
status = handlePacket(currentMessage);
if (status != returnvalue::OK) {

View File

@ -3,6 +3,7 @@
#include <mission/tmtc/TmFunnelBase.h>
#include <atomic>
#include <vector>
#include "fsfw/objectmanager/SystemObject.h"
@ -23,7 +24,6 @@ class CfdpTmFunnel : public TmFunnelBase {
MessageQueueId_t fileStoreDest;
StorageManagerIF& ramToFileStore;
uint16_t sourceSequenceCount = 0;
uint16_t cfdpInCcsdsApid;
};
#endif // FSFW_EXAMPLE_COMMON_CFDPTMFUNNEL_H

View File

@ -17,6 +17,8 @@
using namespace returnvalue;
static constexpr bool DEBUG_DUMPS = false;
PersistentTmStore::PersistentTmStore(PersistentTmStoreArgs args)
: SystemObject(args.objectId),
tmStore(args.tmStore),
@ -32,6 +34,91 @@ ReturnValue_t PersistentTmStore::cancelDump() {
return returnvalue::OK;
}
ReturnValue_t PersistentTmStore::buildDumpSet(uint32_t fromUnixSeconds, uint32_t upToUnixSeconds) {
using namespace std::filesystem;
std::error_code e;
dumpParams.orderedDumpFilestamps.clear();
for (auto const& fileOrDir : directory_iterator(basePath)) {
if (not fileOrDir.is_regular_file(e)) {
continue;
}
dumpParams.fileSize = std::filesystem::file_size(fileOrDir.path(), e);
if (e) {
sif::error << "PersistentTmStore: Could not retrieve file size: " << e.message() << std::endl;
continue;
}
// File empty or can't even read CCSDS header.
if (dumpParams.fileSize <= 6) {
continue;
}
if (dumpParams.fileSize > fileBuf.size()) {
sif::error << "PersistentTmStore: File too large, is deleted" << std::endl;
triggerEvent(persTmStore::FILE_TOO_LARGE, dumpParams.fileSize, fileBuf.size());
std::filesystem::remove(fileOrDir.path(), e);
continue;
}
const path& file = fileOrDir.path();
struct tm fileTime {};
if (pathToTime(file, fileTime) != returnvalue::OK) {
sif::error << "Time extraction for file " << file << "failed" << std::endl;
continue;
}
auto fileEpoch = static_cast<uint32_t>(timegm(&fileTime));
if ((fileEpoch > dumpParams.fromUnixTime) and
(fileEpoch + rolloverDiffSeconds <= dumpParams.untilUnixTime)) {
std::ifstream ifile(file, std::ios::binary);
if (ifile.bad()) {
sif::error << "PersistentTmStore: File is bad" << std::endl;
// TODO: Consider deleting file here?
continue;
}
if (DEBUG_DUMPS) {
sif::debug << "Inserting file " << fileOrDir.path() << std::endl;
}
DumpIndex dumpIndex;
dumpIndex.epoch = fileEpoch;
// Multiple files for the same time are supported via a special suffix. We simply count the
// number of copies and later try to dump the same number of files with the additional
// suffixes
auto iter = dumpParams.orderedDumpFilestamps.find(dumpIndex);
if (iter != dumpParams.orderedDumpFilestamps.end()) {
dumpIndex.epoch = iter->epoch;
dumpIndex.additionalFiles = iter->additionalFiles + 1;
dumpParams.orderedDumpFilestamps.erase(dumpIndex);
} else {
dumpIndex.additionalFiles = 0;
}
dumpParams.orderedDumpFilestamps.emplace(dumpIndex);
}
}
return returnvalue::OK;
}
std::optional<uint8_t> PersistentTmStore::extractSuffix(const std::string& pathStr) {
std::string numberStr;
// Find the position of the dot at the end of the file path
size_t dotPos = pathStr.find_last_of('.');
if ((dotPos < pathStr.length()) and not std::isdigit(pathStr[dotPos + 1])) {
return std::nullopt;
}
// Extract the substring after the dot
numberStr = pathStr.substr(dotPos + 1);
std::optional<uint8_t> number;
try {
number = std::stoi(numberStr);
if (number.value() > std::numeric_limits<uint8_t>::max()) {
return std::nullopt;
}
} catch (std::invalid_argument& exception) {
sif::error << "PersistentTmStore::extractSuffix: Exception " << exception.what()
<< ", invald input string: " << numberStr << std::endl;
}
return number;
}
ReturnValue_t PersistentTmStore::assignAndOrCreateMostRecentFile() {
if (not activeFile.has_value()) {
return createMostRecentFile(std::nullopt);
@ -41,6 +128,7 @@ ReturnValue_t PersistentTmStore::assignAndOrCreateMostRecentFile() {
ReturnValue_t PersistentTmStore::handleCommandQueue(StorageManagerIF& ipcStore,
Command_t& execCmd) {
execCmd = CommandMessageIF::CMD_NONE;
CommandMessage cmdMessage;
ReturnValue_t result = tcQueue->receiveMessage(&cmdMessage);
if (result != returnvalue::OK) {
@ -75,9 +163,9 @@ ReturnValue_t PersistentTmStore::handleCommandQueue(StorageManagerIF& ipcStore,
result = startDumpFromUpTo(dumpFromUnixSeconds, dumpUntilUnixSeconds);
if (result == BUSY_DUMPING) {
triggerEvent(persTmStore::BUSY_DUMPING_EVENT);
} else {
execCmd = cmd;
return result;
}
execCmd = cmd;
}
}
return result;
@ -159,6 +247,12 @@ bool PersistentTmStore::updateBaseDir() {
if (not exists(basePath, e)) {
create_directories(basePath);
}
// Each file will have the base name as a prefix again
path preparedFullFilePath = basePath / baseName;
basePathSize = preparedFullFilePath.string().length();
std::memcpy(filePathBuf.data(), preparedFullFilePath.c_str(), basePathSize);
filePathBuf[basePathSize] = '_';
basePathSize += 1;
baseDirUninitialized = false;
return true;
}
@ -189,12 +283,20 @@ ReturnValue_t PersistentTmStore::startDumpFromUpTo(uint32_t fromUnixSeconds,
if (state == State::DUMPING) {
return returnvalue::FAILED;
}
dumpParams.dirIter = directory_iterator(basePath);
if (dumpParams.dirIter == directory_iterator()) {
auto dirIter = directory_iterator(basePath);
// Directory empty case.
if (dirIter == directory_iterator()) {
return returnvalue::FAILED;
}
dumpParams.fromUnixTime = fromUnixSeconds;
dumpParams.untilUnixTime = upToUnixSeconds;
buildDumpSet(fromUnixSeconds, upToUnixSeconds);
// No files in time window found.
if (dumpParams.orderedDumpFilestamps.empty()) {
return DUMP_DONE;
}
dumpParams.dumpIter = dumpParams.orderedDumpFilestamps.begin();
dumpParams.currentSameFileIdx = std::nullopt;
state = State::DUMPING;
return loadNextDumpFile();
}
@ -203,49 +305,54 @@ ReturnValue_t PersistentTmStore::loadNextDumpFile() {
using namespace std::filesystem;
dumpParams.currentSize = 0;
std::error_code e;
for (; dumpParams.dirIter != directory_iterator(); dumpParams.dirIter++) {
dumpParams.dirEntry = *dumpParams.dirIter;
if (dumpParams.dirEntry.is_directory(e)) {
continue;
}
dumpParams.fileSize = std::filesystem::file_size(dumpParams.dirEntry.path(), e);
if (e) {
sif::error << "PersistentTmStore: Could not retrieve file size: " << e.message() << std::endl;
continue;
}
// sif::debug << "Path: " << dumpParams.dirEntry.path() << std::endl;
// File empty or can't even read CCSDS header.
if (dumpParams.fileSize <= 6) {
continue;
}
if (dumpParams.fileSize > fileBuf.size()) {
sif::error << "PersistentTmStore: File too large, is deleted" << std::endl;
triggerEvent(persTmStore::FILE_TOO_LARGE, dumpParams.fileSize, fileBuf.size());
std::filesystem::remove(dumpParams.dirEntry.path(), e);
continue;
}
const path& file = dumpParams.dirEntry.path();
struct tm fileTime {};
if (pathToTime(file, fileTime) != returnvalue::OK) {
sif::error << "Time extraction for file " << file << "failed" << std::endl;
continue;
}
auto fileEpoch = static_cast<uint32_t>(timegm(&fileTime));
if ((fileEpoch > dumpParams.fromUnixTime) and
(fileEpoch + rolloverDiffSeconds <= dumpParams.untilUnixTime)) {
dumpParams.currentFileUnixStamp = fileEpoch;
std::ifstream ifile(file, std::ios::binary);
if (ifile.bad()) {
sif::error << "PersistentTmStore: File is bad" << std::endl;
continue;
// Handle iteration, which does not necessarily have to increment the set iterator
// if there are multiple files for a given timestamp.
auto handleIteration = [&](DumpIndex& dumpIndex) {
if (dumpIndex.additionalFiles > 0) {
if (not dumpParams.currentSameFileIdx.has_value()) {
// Initialize the file index and stay on same file
dumpParams.currentSameFileIdx = 0;
return;
} else if (dumpParams.currentSameFileIdx.value() < dumpIndex.additionalFiles - 1) {
dumpParams.currentSameFileIdx = dumpParams.currentSameFileIdx.value() + 1;
return;
}
ifile.read(reinterpret_cast<char*>(fileBuf.data()),
static_cast<std::streamsize>(dumpParams.fileSize));
// Increment iterator for next cycle.
dumpParams.dirIter++;
return returnvalue::OK;
}
// File will change, reset this field for correct state-keeping.
dumpParams.currentSameFileIdx = std::nullopt;
// Increment iterator for next cycle.
dumpParams.dumpIter++;
};
while (dumpParams.dumpIter != dumpParams.orderedDumpFilestamps.end()) {
DumpIndex dumpIndex = *dumpParams.dumpIter;
timeval tv{};
tv.tv_sec = dumpIndex.epoch;
size_t fullPathLength = 0;
createFileName(tv, dumpParams.currentSameFileIdx, fullPathLength);
dumpParams.currentFile =
path(std::string(reinterpret_cast<const char*>(filePathBuf.data()), fullPathLength));
if (DEBUG_DUMPS) {
sif::debug << baseName << " dump: Loading " << dumpParams.currentFile << std::endl;
}
dumpParams.fileSize = std::filesystem::file_size(dumpParams.currentFile, e);
if (e) {
// TODO: Event?
sif::error << "PersistentTmStore: Could not load next dump file: " << e.message()
<< std::endl;
handleIteration(dumpIndex);
continue;
}
std::ifstream ifile(dumpParams.currentFile, std::ios::binary);
if (ifile.bad()) {
sif::error << "PersistentTmStore: File is bad. Loading next file" << std::endl;
handleIteration(dumpIndex);
continue;
}
ifile.read(reinterpret_cast<char*>(fileBuf.data()),
static_cast<std::streamsize>(dumpParams.fileSize));
// Next file is loaded, exit the loop.
handleIteration(dumpIndex);
return returnvalue::OK;
}
// Directory iterator was consumed and we are done.
state = State::IDLE;
@ -253,7 +360,10 @@ ReturnValue_t PersistentTmStore::loadNextDumpFile() {
}
ReturnValue_t PersistentTmStore::getNextDumpPacket(PusTmReader& reader, bool& fileHasSwapped) {
if (state == State::IDLE or dumpParams.pendingPacketDump) {
if (state == State::IDLE) {
return DUMP_DONE;
}
if (dumpParams.pendingPacketDump) {
return returnvalue::FAILED;
}
fileHasSwapped = false;
@ -267,8 +377,8 @@ ReturnValue_t PersistentTmStore::getNextDumpPacket(PusTmReader& reader, bool& fi
// Delete the file and load next. Could use better algorithm to partially
// restore the file dump, but for now do not trust the file.
std::error_code e;
std::filesystem::remove(dumpParams.dirEntry.path().c_str(), e);
if (dumpParams.dirEntry.path() == activeFile) {
std::filesystem::remove(dumpParams.currentFile.c_str(), e);
if (dumpParams.currentFile == activeFile) {
activeFile == std::nullopt;
assignAndOrCreateMostRecentFile();
}
@ -302,37 +412,9 @@ ReturnValue_t PersistentTmStore::pathToTime(const std::filesystem::path& path, s
ReturnValue_t PersistentTmStore::createMostRecentFile(std::optional<uint8_t> suffix) {
using namespace std::filesystem;
unsigned currentIdx = 0;
path pathStart = basePath / baseName;
memcpy(fileBuf.data() + currentIdx, pathStart.c_str(), pathStart.string().length());
currentIdx += pathStart.string().length();
fileBuf[currentIdx] = '_';
currentIdx += 1;
time_t epoch = currentTv.tv_sec;
struct tm* time = gmtime(&epoch);
size_t writtenBytes = strftime(reinterpret_cast<char*>(fileBuf.data() + currentIdx),
fileBuf.size(), config::FILE_DATE_FORMAT, time);
if (writtenBytes == 0) {
sif::error << "PersistentTmStore::createMostRecentFile: Could not create file timestamp"
<< std::endl;
return returnvalue::FAILED;
}
currentIdx += writtenBytes;
char* res = strcpy(reinterpret_cast<char*>(fileBuf.data() + currentIdx), ".bin");
if (res == nullptr) {
return returnvalue::FAILED;
}
currentIdx += 4;
if (suffix.has_value()) {
std::string fullSuffix = "." + std::to_string(suffix.value());
res = strcpy(reinterpret_cast<char*>(fileBuf.data() + currentIdx), fullSuffix.c_str());
if (res == nullptr) {
return returnvalue::FAILED;
}
currentIdx += fullSuffix.size();
}
path newPath(std::string(reinterpret_cast<const char*>(fileBuf.data()), currentIdx));
size_t currentIdx;
createFileName(currentTv, suffix, currentIdx);
path newPath(std::string(reinterpret_cast<const char*>(filePathBuf.data()), currentIdx));
std::ofstream of(newPath, std::ios::binary);
activeFile = newPath;
activeFileTv = currentTv;
@ -354,3 +436,33 @@ void PersistentTmStore::getStartAndEndTimeCurrentOrLastDump(uint32_t& startTime,
startTime = dumpParams.fromUnixTime;
endTime = dumpParams.untilUnixTime;
}
ReturnValue_t PersistentTmStore::createFileName(timeval& tv, std::optional<uint8_t> suffix,
size_t& fullPathLength) {
unsigned currentIdx = basePathSize;
time_t epoch = tv.tv_sec;
struct tm* time = gmtime(&epoch);
size_t writtenBytes = strftime(reinterpret_cast<char*>(filePathBuf.data() + currentIdx),
filePathBuf.size(), config::FILE_DATE_FORMAT, time);
if (writtenBytes == 0) {
sif::error << "PersistentTmStore::createMostRecentFile: Could not create file timestamp"
<< std::endl;
return returnvalue::FAILED;
}
currentIdx += writtenBytes;
char* res = strcpy(reinterpret_cast<char*>(filePathBuf.data() + currentIdx), ".bin");
if (res == nullptr) {
return returnvalue::FAILED;
}
currentIdx += 4;
if (suffix.has_value()) {
std::string fullSuffix = "." + std::to_string(suffix.value());
res = strcpy(reinterpret_cast<char*>(filePathBuf.data() + currentIdx), fullSuffix.c_str());
if (res == nullptr) {
return returnvalue::FAILED;
}
currentIdx += fullSuffix.size();
}
fullPathLength = currentIdx;
return returnvalue::OK;
}

View File

@ -10,6 +10,7 @@
#include <mission/memory/SdCardMountedIF.h>
#include <filesystem>
#include <set>
#include "eive/eventSubsystemIds.h"
#include "eive/resultClassIds.h"
@ -37,6 +38,14 @@ struct PersistentTmStoreArgs {
SdCardMountedIF& sdcMan;
};
struct DumpIndex {
uint32_t epoch = 0;
// Number of additional files with a suffix like .0, .1 etc.
uint8_t additionalFiles = 0;
// Define a custom comparison function based on the epoch variable
bool operator<(const DumpIndex& other) const { return epoch < other.epoch; }
};
class PersistentTmStore : public TmStoreFrontendSimpleIF, public SystemObject {
public:
enum class State { IDLE, DUMPING };
@ -96,7 +105,10 @@ class PersistentTmStore : public TmStoreFrontendSimpleIF, public SystemObject {
std::string baseName;
uint8_t currentSameSecNumber = 0;
std::filesystem::path basePath;
// std::filesystem::path pathStart = basePath / baseName;
uint32_t rolloverDiffSeconds = 0;
std::array<uint8_t, 524> filePathBuf{};
size_t basePathSize;
std::array<uint8_t, MAX_FILESIZE> fileBuf{};
timeval currentTv;
timeval activeFileTv{};
@ -106,8 +118,10 @@ class PersistentTmStore : public TmStoreFrontendSimpleIF, public SystemObject {
uint32_t fromUnixTime = 0;
uint32_t untilUnixTime = 0;
uint32_t currentFileUnixStamp = 0;
std::filesystem::directory_iterator dirIter;
std::filesystem::directory_entry dirEntry;
std::filesystem::path currentFile;
std::set<DumpIndex> orderedDumpFilestamps{};
std::set<DumpIndex>::iterator dumpIter;
std::optional<uint8_t> currentSameFileIdx = 0;
size_t fileSize = 0;
size_t currentSize = 0;
};
@ -122,10 +136,13 @@ class PersistentTmStore : public TmStoreFrontendSimpleIF, public SystemObject {
[[nodiscard]] MessageQueueId_t getCommandQueue() const override;
void calcDiffSeconds(RolloverInterval intervalUnit, uint32_t intervalCount);
ReturnValue_t buildDumpSet(uint32_t fromUnixSeconds, uint32_t upToUnixSeconds);
ReturnValue_t createMostRecentFile(std::optional<uint8_t> suffix);
static ReturnValue_t pathToTime(const std::filesystem::path& path, struct tm& time);
void fileToPackets(const std::filesystem::path& path, uint32_t unixStamp);
ReturnValue_t loadNextDumpFile();
ReturnValue_t createFileName(timeval& tv, std::optional<uint8_t> suffix, size_t& fullPathLength);
std::optional<uint8_t> extractSuffix(const std::string& pathStr);
bool updateBaseDir();
ReturnValue_t assignAndOrCreateMostRecentFile();
};

View File

@ -1,5 +1,7 @@
#include "PusTmFunnel.h"
#include <limits>
#include "eive/definitions.h"
#include "eive/objects.h"
#include "fsfw/ipc/CommandMessage.h"
@ -11,8 +13,8 @@
#include "tmtc/pusIds.h"
PusTmFunnel::PusTmFunnel(TmFunnelBase::FunnelCfg cfg, StorageManagerIF &ramToFileStore,
TimeReaderIF &timeReader, SdCardMountedIF &sdcMan)
: TmFunnelBase(cfg), ramToFileStore(ramToFileStore), timeReader(timeReader), sdcMan(sdcMan) {}
TimeReaderIF &timeReader)
: TmFunnelBase(cfg), ramToFileStore(ramToFileStore), timeReader(timeReader) {}
PusTmFunnel::~PusTmFunnel() = default;
@ -21,6 +23,13 @@ ReturnValue_t PusTmFunnel::performOperation(uint8_t) {
ReturnValue_t result;
TmTcMessage currentMessage;
unsigned int count = 0;
if (saveSequenceCount) {
result = saveSequenceCountToFile();
if (result != returnvalue::OK) {
sif::error << "PusTmFunnel: Storing sequence count to file has failed" << std::endl;
}
saveSequenceCount = false;
}
result = tmQueue->receiveMessage(&currentMessage);
while (result == returnvalue::OK) {
result = handleTmPacket(currentMessage);
@ -59,7 +68,33 @@ ReturnValue_t PusTmFunnel::handleTmPacket(TmTcMessage &message) {
return result;
}
packet.setSequenceCount(sourceSequenceCount++);
// NOTE: This only works because the limit value bit width is below 16 bits!
sourceSequenceCount = sourceSequenceCount % ccsds::LIMIT_SEQUENCE_COUNT;
// Message type counter handling.
uint8_t service = packet.getService();
bool insertionFailed = false;
auto mapIter = msgCounterMap.find(service);
if (mapIter == msgCounterMap.end()) {
auto iterPair = msgCounterMap.emplace(service, 0);
if (iterPair.second) {
mapIter = iterPair.first;
} else {
// Should really never never happen but you never know..
insertionFailed = true;
}
}
if (not insertionFailed) {
packet.setMessageCount(mapIter->second);
// Sane overflow handling.
if (mapIter->second == std::numeric_limits<uint16_t>::max()) {
mapIter->second = 0;
} else {
mapIter->second++;
}
}
// Re-calculate CRC after changing the fields. This operation HAS to come last!
packet.updateErrorControl();
// Send to persistent TM store if the packet matches some filter.

View File

@ -9,6 +9,8 @@
#include <mission/tmtc/PusTmRouteByFilterHelper.h>
#include <mission/tmtc/TmFunnelBase.h>
#include <atomic>
#include <map>
#include <vector>
#include "PersistentTmStore.h"
@ -25,7 +27,7 @@
class PusTmFunnel : public TmFunnelBase {
public:
PusTmFunnel(TmFunnelBase::FunnelCfg cfg, StorageManagerIF &ramToFileStore,
TimeReaderIF &timeReader, SdCardMountedIF &sdcMan);
TimeReaderIF &timeReader);
[[nodiscard]] const char *getName() const override;
~PusTmFunnel() override;
@ -36,11 +38,10 @@ class PusTmFunnel : public TmFunnelBase {
// Update TV stamp every 5 minutes
static constexpr dur_millis_t TV_UPDATE_INTERVAL_SECS = 60 * 5;
uint16_t sourceSequenceCount = 0;
std::map<uint8_t, uint16_t> msgCounterMap;
StorageManagerIF &ramToFileStore;
TimeReaderIF &timeReader;
bool storesInitialized = false;
SdCardMountedIF &sdcMan;
PusTmRouteByFilterHelper persistentTmMap;
ReturnValue_t handleTmPacket(TmTcMessage &message);

View File

@ -2,6 +2,10 @@
#include <fsfw/tmtcservices/TmTcMessage.h>
#include <atomic>
#include <filesystem>
#include <fstream>
#include "fsfw/ipc/QueueFactory.h"
TmFunnelBase::TmFunnelBase(FunnelCfg cfg)
@ -10,7 +14,10 @@ TmFunnelBase::TmFunnelBase(FunnelCfg cfg)
tmStore(cfg.tmStore),
ipcStore(cfg.ipcStore),
tmQueue(QueueFactory::instance()->createMessageQueue(cfg.tmMsgDepth)),
liveDemux(*tmQueue) {}
liveDemux(*tmQueue),
sdcMan(cfg.sdcMan),
sequenceCounterFilename(cfg.sequenceCounterFilename),
saveSequenceCount(cfg.saveSequenceCount) {}
ReturnValue_t TmFunnelBase::demultiplexLivePackets(store_address_t origStoreId,
const uint8_t *tmData, size_t tmSize) {
@ -27,3 +34,38 @@ void TmFunnelBase::addLiveDestination(const char *name,
const AcceptsTelemetryIF &downlinkDestination, uint8_t vcid) {
liveDemux.addDestination(name, downlinkDestination, vcid);
}
ReturnValue_t TmFunnelBase::initialize() {
using namespace std::filesystem;
// The filesystem should always be available at the start.. Let's assume it always is, otherwise
// we just live with a regular 0 initialization. It simplifies a lot.
std::error_code e;
path filePath =
path(path(sdcMan.getCurrentMountPrefix()) / path("conf") / path(sequenceCounterFilename));
if (exists(filePath, e)) {
std::ifstream ifile(filePath);
if (ifile.bad()) {
sif::error << "TmFunnelBase::initialize: Faulty file open for sequence counter initialization"
<< std::endl;
return returnvalue::OK;
}
if (not(ifile >> sourceSequenceCount)) {
// Initialize to 0 in any case if reading a number failed.
sourceSequenceCount = 0;
}
}
return returnvalue::OK;
}
ReturnValue_t TmFunnelBase::saveSequenceCountToFile() {
using namespace std::filesystem;
std::error_code e;
path filePath =
path(path(sdcMan.getCurrentMountPrefix()) / path("conf") / path(sequenceCounterFilename));
std::ofstream ofile(filePath);
if (ofile.bad()) {
return returnvalue::FAILED;
}
ofile << sourceSequenceCount << "\n";
return returnvalue::OK;
}

View File

@ -6,25 +6,34 @@
#include <fsfw/tmstorage/TmStoreFrontendSimpleIF.h>
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
#include <fsfw/tmtcservices/TmTcMessage.h>
#include <mission/memory/SdCardMountedIF.h>
#include <mission/tmtc/PusLiveDemux.h>
#include <atomic>
#include <vector>
class TmFunnelBase : public AcceptsTelemetryIF, public SystemObject {
public:
struct FunnelCfg {
FunnelCfg(object_id_t objId, const char* name, StorageManagerIF& tmStore,
StorageManagerIF& ipcStore, uint32_t tmMsgDepth)
StorageManagerIF& ipcStore, uint32_t tmMsgDepth, SdCardMountedIF& sdcMan,
const char* sequenceCounterFilename, std::atomic_bool& saveSequenceCount)
: objectId(objId),
name(name),
tmStore(tmStore),
ipcStore(ipcStore),
tmMsgDepth(tmMsgDepth) {}
tmMsgDepth(tmMsgDepth),
sdcMan(sdcMan),
sequenceCounterFilename(sequenceCounterFilename),
saveSequenceCount(saveSequenceCount) {}
object_id_t objectId;
const char* name;
StorageManagerIF& tmStore;
StorageManagerIF& ipcStore;
uint32_t tmMsgDepth;
SdCardMountedIF& sdcMan;
const char* sequenceCounterFilename;
std::atomic_bool& saveSequenceCount;
};
explicit TmFunnelBase(FunnelCfg cfg);
[[nodiscard]] MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const override;
@ -32,6 +41,9 @@ class TmFunnelBase : public AcceptsTelemetryIF, public SystemObject {
uint8_t vcid = 0);
ReturnValue_t demultiplexLivePackets(store_address_t origStoreId, const uint8_t* tmData,
size_t tmSize);
ReturnValue_t initialize() override;
ReturnValue_t saveSequenceCountToFile();
~TmFunnelBase() override;
@ -41,6 +53,10 @@ class TmFunnelBase : public AcceptsTelemetryIF, public SystemObject {
StorageManagerIF& ipcStore;
MessageQueueIF* tmQueue = nullptr;
PusLiveDemux liveDemux;
SdCardMountedIF& sdcMan;
const char* sequenceCounterFilename;
std::atomic_bool& saveSequenceCount;
uint16_t sourceSequenceCount = 0;
};
#endif /* MISSION_TMTC_TMFUNNELBASE_H_ */

2
tmtc

Submodule tmtc updated: ec0ebc3653...eea7683581

View File

@ -4,7 +4,7 @@ add_subdirectory(mocks)
target_sources(${UNITTEST_NAME} PRIVATE
main.cpp
testEnvironment.cpp
testStampInFilename.cpp
testGenericFilesystem.cpp
hdlcEncodingRw.cpp
printChar.cpp
)

View File

@ -30,7 +30,8 @@ TEST_CASE("Thermal Controller", "[ThermalController]") {
// testEnvironment::initialize();
ThermalController controller(THERMAL_CONTROLLER_ID, *heaterHandler, tcsBrdShortlyUnavailable);
ThermalController controller(THERMAL_CONTROLLER_ID, *heaterHandler, tcsBrdShortlyUnavailable,
true);
ReturnValue_t result = controller.initialize();
REQUIRE(result == returnvalue::OK);

View File

@ -27,7 +27,7 @@ void factory(void* args) {
new HouseKeepingMock();
eventManager = new EventManagerMock();
new HealthTable(objects::HEALTH_TABLE);
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER);
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER, 5, false, 60.0);
new CdsShortTimeStamper(objects::TIME_STAMPER);
{

View File

@ -0,0 +1,43 @@
#include <catch2/catch_test_macros.hpp>
#include <cinttypes>
#include "fsfw/timemanager/Clock.h"
uint8_t extractSuffix(const std::string& pathStr) {
std::string numberStr;
// Find the position of the dot at the end of the file path
size_t dotPos = pathStr.find_last_of('.');
if (dotPos != std::string::npos && dotPos < pathStr.length() - 1) {
// Extract the substring after the dot
numberStr = pathStr.substr(dotPos + 1);
}
int number = std::stoi(numberStr);
if (number < 0 or number > std::numeric_limits<uint8_t>::max()) {
return 0;
}
return static_cast<uint8_t>(number);
}
TEST_CASE("Stamp in Filename", "[Stamp In Filename]") {
Clock::TimeOfDay_t tod;
std::string baseName = "verif";
std::string pathStr = "verif_2022-05-25T16:55:23Z.bin";
unsigned int underscorePos = pathStr.find_last_of('_');
std::string stampStr = pathStr.substr(underscorePos + 1);
float seconds = 0.0;
char* prefix = nullptr;
int count =
sscanf(stampStr.c_str(),
"%4" SCNu32 "-%2" SCNu32 "-%2" SCNu32 "T%2" SCNu32 ":%2" SCNu32 ":%2" SCNu32 "Z",
&tod.year, &tod.month, &tod.day, &tod.hour, &tod.minute, &tod.second);
static_cast<void>(count);
CHECK(count == 6);
}
TEST_CASE("Suffix Extraction") {
std::string pathStr = "/mnt/sd0/tm/hk/hk-some-stamp.bin.0";
CHECK(extractSuffix(pathStr) == 0);
pathStr = "/mnt/sd0/tm/hk/hk-some-stamp.bin.2";
CHECK(extractSuffix(pathStr) == 2);
}

View File

@ -1,21 +0,0 @@
#include <catch2/catch_test_macros.hpp>
#include <cinttypes>
#include "fsfw/timemanager/Clock.h"
TEST_CASE("Stamp in Filename", "[Stamp In Filename]") {
Clock::TimeOfDay_t tod;
std::string baseName = "verif";
std::string pathStr = "verif_2022-05-25T16:55:23Z.bin";
unsigned int underscorePos = pathStr.find_last_of('_');
std::string stampStr = pathStr.substr(underscorePos + 1);
float seconds = 0.0;
char* prefix = nullptr;
int count =
sscanf(stampStr.c_str(),
"%4" SCNu32 "-%2" SCNu32 "-%2" SCNu32 "T%2" SCNu32 ":%2" SCNu32 ":%2" SCNu32 "Z",
&tod.year, &tod.month, &tod.day, &tod.hour, &tod.minute, &tod.second);
static_cast<void>(count);
CHECK(count == 6);
}