Compare commits

..

135 Commits

Author SHA1 Message Date
3f73ad86eb Merge pull request 'bump minor version' (#759) from prep-v6.2.0 into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #759
2023-07-26 14:04:48 +02:00
a0735b4fff bump minor version
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-26 13:37:21 +02:00
a71f773f63 Merge pull request 'ACS downwards compatibility' (#758) from acs-downwards-compat into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #758
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-26 13:27:42 +02:00
f7dccdc4c6 bump tmtc again
Some checks are pending
EIVE/eive-obsw/pipeline/pr-main Build started...
2023-07-26 13:20:32 +02:00
3ebb83b4c0 changelog
Some checks are pending
EIVE/eive-obsw/pipeline/head Build queued...
EIVE/eive-obsw/pipeline/pr-main Build started...
2023-07-26 13:18:36 +02:00
ee43c0fbd7 Merge remote-tracking branch 'origin/main' into acs-downwards-compat
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
2023-07-26 13:18:13 +02:00
91208c2808 bump tmtc, small tweak for definitions 2023-07-26 13:17:54 +02:00
1dc545c5f0 Merge pull request 'Bump events and tmtc' (#757) from bump-events-and-tmtc into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #757
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-26 13:17:29 +02:00
55c5df0519 ensure downwards compatibilitiy for enum
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-07-26 13:07:14 +02:00
e74ae18763 Merge branch 'main' into bump-events-and-tmtc
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-26 12:58:51 +02:00
e5b19a4463 Merge pull request 'cmake.xml' (#756) from cmake-update into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #756
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-26 12:58:21 +02:00
1f658ceee3 changelog
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
2023-07-26 12:58:12 +02:00
6ef05767c5 events and tmtc 2023-07-26 12:57:39 +02:00
9726c283ef Merge branch 'main' into cmake-update
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-26 12:48:09 +02:00
2110c54d96 Merge pull request 'Simplify image protection code' (#755) from simplify-image-prot-code into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #755
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-26 11:54:03 +02:00
7c0ee9114b changelog
Some checks are pending
EIVE/eive-obsw/pipeline/pr-main Build started...
2023-07-26 11:26:21 +02:00
e52195e195 bugfix in test
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-26 11:25:28 +02:00
4d195a1b8e bugfix
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-26 11:17:26 +02:00
8c54802e7a Merge remote-tracking branch 'origin/main' into simplify-image-prot-code
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-26 11:12:46 +02:00
8cd959f55a Merge pull request 'SD shutdown handling non-blocking' (#753) from sd-shutdown-non-blocking into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #753
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-26 11:09:47 +02:00
001630cece Merge remote-tracking branch 'origin/main' into sd-shutdown-non-blocking
Some checks are pending
EIVE/eive-obsw/pipeline/pr-main Build queued...
2023-07-26 11:09:24 +02:00
dbb3434cd9 Merge pull request 'New Safe Mode Controller' (#748) from acs-safe-flp-v2 into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #748
Reviewed-by: Robin Müller <muellerr@irs.uni-stuttgart.de>
2023-07-26 11:08:11 +02:00
61e73a4be9 docs
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-26 11:07:04 +02:00
81bb47a6d8 this is a lot better
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
2023-07-26 11:05:36 +02:00
a5c799180e bump tmtc
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-26 09:51:56 +02:00
f5a9a4973c Merge remote-tracking branch 'origin/main' into acs-safe-flp-v2
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-26 09:51:24 +02:00
f60c754c61 changelog typo
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-26 00:33:49 +02:00
ff05181dd3 another evil bug found 2023-07-26 00:30:09 +02:00
7014ab517d some info output 2023-07-25 23:53:39 +02:00
d59ea6eb3d fixed some bugs 2023-07-25 23:48:22 +02:00
abbf170ce2 core controller doing weird things
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-25 16:54:40 +02:00
6767e9a543 cmake.xml
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-25 16:32:22 +02:00
bf730060b5 SD shutdown handling non-blocking
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-25 16:25:00 +02:00
011f4bf5d9 Merge branch 'main' into acs-safe-flp-v2
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-25 09:58:23 +02:00
942b459066 changelog
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-25 09:56:35 +02:00
10dfa07cd9 aluli 2023-07-25 09:55:34 +02:00
61b3ef790a lets pretend this makes it all better
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-24 10:14:38 +02:00
c6294cadbd improved readability?
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-24 10:10:26 +02:00
e2926e25f6 bump tmtc
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-24 09:52:08 +02:00
7e1e02c2bc ????
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-21 14:24:52 +02:00
afc72c0d97 Merge pull request 'active SD Info event' (#752) from active-sd-info-event into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #752
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-21 13:56:13 +02:00
4539d25518 Merge branch 'main' into active-sd-info-event
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-21 11:52:32 +02:00
f989af51f2 Merge pull request 'RAD sensor delay after pulling pin high' (#751) from rad-sensor-delay-after-gpio into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #751
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-21 11:50:48 +02:00
566c1534ee bump tmtc
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-21 11:47:57 +02:00
5f75b22cec new event 2023-07-21 11:36:39 +02:00
7bedb1d307 even more useful events
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-21 11:15:35 +02:00
f736489430 bugfix
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-21 11:10:09 +02:00
7ac19c8ea8 Merge remote-tracking branch 'origin/main' into active-sd-info-event
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-21 10:27:27 +02:00
8251f28cda re-run generators 2023-07-21 10:26:57 +02:00
4e2989d2bd active SD Info event
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-21 10:23:35 +02:00
6efee8d4da whoops
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-21 09:51:14 +02:00
59e07d9b47 Merge branch 'main' into rad-sensor-delay-after-gpio
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-20 17:16:06 +02:00
880c09c510 changelog 2023-07-20 17:16:14 +02:00
7cc95be900 RAD sensor delay after pulling pin high
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-20 17:12:50 +02:00
5e9fd332d9 Merge pull request 'Reduced rad sensor polling' (#747) from rad-sensor-polling-update into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #747
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-20 16:26:53 +02:00
753b9f8a0e better detumble exit
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-20 14:43:43 +02:00
07e002ccd2 detumble from fusedRotRate
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-20 14:22:45 +02:00
53d2e7965a seems more logical 2023-07-20 14:22:24 +02:00
d618e913af old safe mode is default safe mode
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-20 13:53:19 +02:00
5f481fd4d0 keep going people, nothing to see here
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-20 13:09:49 +02:00
b26600ac64 no bugs to see here, please move on
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-20 11:36:44 +02:00
0d501e5064 extended state machine and corrected controller calls
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-07-20 11:32:36 +02:00
32e2d87143 Merge branch 'main' into acs-safe-flp-v2
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-07-20 11:10:46 +02:00
7b0a47b010 use calculation
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-07-20 11:09:46 +02:00
300a6c5ff2 use datasets 2023-07-20 11:09:34 +02:00
d90fd07ba3 a new dataset a day keeps the doctor away
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-20 09:32:48 +02:00
800e29bcb9 missing param
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-19 16:34:02 +02:00
beaacc251b new class YAY
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-07-19 16:25:03 +02:00
b80c96a02c Merge branch 'main' into rad-sensor-polling-update
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-19 16:14:03 +02:00
a52d116857 move CD reset
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-19 15:36:06 +02:00
1c8fea409a Merge pull request 'small fix for PL PCDU' (#749) from pl-pcdu-small-fix into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #749
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-19 15:34:36 +02:00
f61301db13 changelog
Some checks are pending
EIVE/eive-obsw/pipeline/pr-main Build queued...
2023-07-19 15:34:16 +02:00
c48be8f37b stuff
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-19 15:30:54 +02:00
9dfc8a0e93 new params 2023-07-19 14:41:09 +02:00
8db131f4ab the good fix
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-07-19 14:38:45 +02:00
e50aa2b620 small fix for PL PCDU
Some checks are pending
EIVE/eive-obsw/pipeline/head This commit looks good
EIVE/eive-obsw/pipeline/pr-main Build queued...
2023-07-19 14:01:08 +02:00
8451a2f8ef extended state machine
Some checks failed
EIVE/eive-obsw/pipeline/pr-main There was a failure building this commit
2023-07-19 13:24:37 +02:00
ebedb59929 new safe params 2023-07-19 13:24:21 +02:00
0f532e8511 more strats 2023-07-19 13:23:55 +02:00
fbff57dd45 filter galore
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-19 11:47:23 +02:00
910addc27a reset the timer
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-18 18:26:57 +02:00
b2d2c38c58 changelog
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-18 18:24:36 +02:00
a4a5800cba that should do the job
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-18 11:01:53 +02:00
2c9df747e8 Merge pull request 'Add RAD sensor dummy' (#745) from add-rad-sensor-dummy into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #745
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-18 10:52:05 +02:00
4fe921b2cc Merge branch 'main' into add-rad-sensor-dummy
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-18 10:14:33 +02:00
e5f8b08e4b Merge pull request 'sus dummy bugfix' (#746) from small-sus-dummy-bugfix into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #746
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-18 10:10:01 +02:00
ba0fe5f7da bump fsfw
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-18 10:08:04 +02:00
c9a4cf53ca changelog
Some checks are pending
EIVE/eive-obsw/pipeline/pr-main Build queued...
2023-07-18 10:06:35 +02:00
fa10b6fd95 sus dummy bugfix
Some checks are pending
EIVE/eive-obsw/pipeline/head Build queued...
EIVE/eive-obsw/pipeline/pr-main Build queued...
2023-07-18 10:04:31 +02:00
5102bd4d69 changelog
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-18 10:03:15 +02:00
ba6f55b93b map rad sensor set
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-18 10:02:14 +02:00
2b8a44f390 always schedule rad sensor
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
2023-07-18 09:57:24 +02:00
08c98bd354 add rad sensor dummy
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-07-18 09:52:26 +02:00
0587f40874 add rad sensor dummy
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-07-18 09:44:44 +02:00
320b460179 Merge pull request 'small FSFW bump' (#744) from small-fsfw-bump into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #744
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-17 13:11:31 +02:00
1510de19a6 small FSFW bump
Some checks are pending
EIVE/eive-obsw/pipeline/head Build queued...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-17 10:43:48 +02:00
6ae72db32d Merge pull request 'Add SCEX handler for EM' (#743) from add-scex-for-em into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #743
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-14 15:16:12 +02:00
88d1f9940f changelog
Some checks are pending
EIVE/eive-obsw/pipeline/pr-main Build queued...
2023-07-14 15:16:08 +02:00
8c4a35fc42 some adaptions for SCEX
Some checks are pending
EIVE/eive-obsw/pipeline/head Build queued...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-14 14:31:02 +02:00
e7c8d15773 add SCEX for EM 2023-07-14 14:04:23 +02:00
19a86ac29e Merge pull request 'STR Auto Threshold Config' (#742) from str-auto-threshold-cfg into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #742
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-14 14:03:52 +02:00
1d4e2a70a2 changelog
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-14 12:49:24 +02:00
f1028eb1d9 bump tmtc
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-14 12:47:35 +02:00
c028a696ce Merge branch 'main' into str-auto-threshold-cfg
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-14 12:44:08 +02:00
f832c4522e Merge pull request 'STR time' (#611) from str_set_time into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #611
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2023-07-14 12:43:19 +02:00
4e58614c56 changelog
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-13 21:21:42 +02:00
93ea8519b0 works
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-13 21:19:30 +02:00
16dbba6545 done
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-07-13 21:14:39 +02:00
9a451e3d5f COM error event 2023-07-13 21:09:27 +02:00
7870a2015e add auto threshold config
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-07-13 20:49:42 +02:00
80155285c8 remove an unnecessary tweak
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-13 17:37:13 +02:00
c61b0f55a4 some tweaks
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-13 17:35:12 +02:00
6d220692d5 changelog
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-13 17:33:04 +02:00
db61358639 Merge branch 'smaller-str-fix' into str_set_time
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-13 17:31:53 +02:00
fec85ffa6c correct fix
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
EIVE/eive-obsw/pipeline/head This commit looks good
2023-07-13 17:30:43 +02:00
462da5228a back to default FDIR
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-13 17:23:46 +02:00
e9d4104f88 some further investigation
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-13 17:03:56 +02:00
39022ce2f6 different max missed reply thresholds for STR FDIR
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-13 16:52:33 +02:00
0cefef8a35 rough but possible fix..
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-13 16:38:20 +02:00
d3f3a3efd0 Merge branch 'smaller-str-fix' into str_set_time
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-13 14:57:53 +02:00
6398532462 only enable STR set for normal mode
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-13 14:57:24 +02:00
16f26d7758 afmt
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-13 14:52:32 +02:00
0e3980dc37 this works
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-13 14:52:07 +02:00
cc7e39c484 Merge remote-tracking branch 'origin/main' into str_set_time
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-13 13:26:41 +02:00
448e24e69f Merge branch 'str_set_time' of https://egit.irs.uni-stuttgart.de/eive/eive-obsw into str_set_time 2023-07-13 13:21:56 +02:00
863c0af2a1 what the hell is wrong with the thing?
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-13 10:53:58 +02:00
0fb85883a5 always add STR, rename set field
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-13 10:16:52 +02:00
965c8d21cc Merge branch 'main' into str_set_time
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-13 10:09:38 +02:00
608eecb091 this is realy buggy somewhere.. 2023-07-12 18:33:02 +02:00
ff432a4194 what the hell is wrong here..
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-12 18:17:00 +02:00
e9d48687d7 i hate this stupid class
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-12 17:59:07 +02:00
735c60d4c2 Merge branch 'startracker-tests' into str_set_time
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-12 17:11:15 +02:00
770d9b7ad3 Merge remote-tracking branch 'origin/main' into str_set_time
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2023-07-12 17:06:18 +02:00
3aad452357 fix this some other time
Some checks are pending
EIVE/eive-obsw/pipeline/pr-develop This commit looks good
EIVE/eive-obsw/pipeline/head Build queued...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
EIVE/-/pipeline/pr-main Build queued...
2023-04-16 11:35:30 +02:00
67351d5ada set time for star tracker
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2023-04-16 11:25:10 +02:00
52 changed files with 1056 additions and 406 deletions

3
.idea/cmake.xml generated
View File

@ -2,7 +2,7 @@
<project version="4">
<component name="CMakeSharedSettings">
<configurations>
<configuration PROFILE_NAME="Debug Q7S" ENABLED="true" CONFIG_NAME="Debug" TOOLCHAIN_NAME="Q7S" GENERATION_OPTIONS="-DTGT_BSP=&quot;arm/q7s&quot;" NO_GENERATOR="true">
<configuration PROFILE_NAME="Debug Q7S" ENABLED="true" CONFIG_NAME="Debug" TOOLCHAIN_NAME="Default" GENERATION_OPTIONS="-DTGT_BSP=&quot;arm/q7s&quot;" NO_GENERATOR="true">
<ADDITIONAL_GENERATION_ENVIRONMENT>
<envs>
<env name="ZYNQ_7020_ROOTFS" value="/opt/xiphos/sdk/ark/sysroots/cortexa9hf-neon-xiphos-linux-gnueabi" />
@ -10,6 +10,7 @@
</envs>
</ADDITIONAL_GENERATION_ENVIRONMENT>
</configuration>
<configuration PROFILE_NAME="Debug" ENABLED="true" CONFIG_NAME="Debug" NO_GENERATOR="true" />
</configurations>
</component>
</project>

View File

@ -16,6 +16,49 @@ will consitute of a breaking change warranting a new major release:
# [unreleased]
# [v6.2.0] 2023-07-26
- `eive-tmtc`: v5.3.1
## Changed
- STR missed reply handling is now moved to DHB rather than the COM interface. The COM IF will
still trigger an event if a reply is taking too long, and FDIR should still work via reply
timeouts.
- Re-ordered some functions of the core controller in the initialize function.
- Rad sensor is now only polled every 30 minutes instead of every device cycle to reduce wear of
the RADFET electronics.
- The SD cards will still be switched OFF on a reboot, but this is done in a non-blocking manner
now with a timeout of 10 seconds where the reboot will be performed in any case.
- ACS Controller now includes the safe mode from FLP, which will calculate its rotational rate
from SUS and MGM measurements. To accommodate these changes, low-pass filters for SUS
measurements and rates as well as MGM measurements and rates are included. Usage of the new
controller as well as settings of the low-pass filters can be handled via parameter commands.
- Simplify and fix the chip and copy protection functions in the core controller. This mechanism
now is always performed for the target chip and target copy in the reboot handlers.
## Added
- 5 ms delay after pulling RADFET enable pin high before starting
the ADC conversion.
- Set STR time in configuration sequence to firmware mode.
- The STR `AutoThreshold` parameters are now set from the configuration JSON file at STR
startup.
- The STR handler can now handle the COM error reply and triggers an low severity event accordingly.
- Add SCEX handler for EM.
- Radiation sensor handler dummy for the EM.
- Added event for SD card information in core controller initialize function. This event will also
be triggered after the SD state machine has run, so the event will generally be triggered twice
at system boot, and once after commanding SD card switches.
## Fixed
- General bugs in the SD card state machine. This might fix some other known bugs for certain
combinations of switching ON and OFF SD cards and also makes the whole state machine a lot more
robust against hanging up.
- SUS dummy handler went to `MODE_NORMAL` for ON commands.
- PL PCDU dummy went to `MODE_NORMAL` for ON commands.
# [v6.1.0] 2023-07-13
- `eive-tmtc`: v5.2.0

View File

@ -10,7 +10,7 @@
cmake_minimum_required(VERSION 3.13)
set(OBSW_VERSION_MAJOR 6)
set(OBSW_VERSION_MINOR 1)
set(OBSW_VERSION_MINOR 2)
set(OBSW_VERSION_REVISION 0)
# set(CMAKE_VERBOSE TRUE)
@ -93,7 +93,7 @@ set(OBSW_ADD_BPX_BATTERY_HANDLER
1
CACHE STRING "Add BPX battery module")
set(OBSW_ADD_STAR_TRACKER
${INIT_VAL}
1
CACHE STRING "Add Startracker module")
set(OBSW_ADD_SUN_SENSORS
${INIT_VAL}
@ -162,7 +162,7 @@ set(OBSW_ADD_RW
${INIT_VAL}
CACHE STRING "Add RW modules")
set(OBSW_ADD_SCEX_DEVICE
${INIT_VAL}
1
CACHE STRING "Add Solar Cell Experiment module")
set(OBSW_SYRLINKS_SIMULATED
0

View File

@ -1,7 +1,7 @@
/**
* @brief Auto-generated event translation file. Contains 299 translations.
* @brief Auto-generated event translation file. Contains 301 translations.
* @details
* Generated on: 2023-07-07 12:06:06
* Generated on: 2023-07-26 12:51:20
*/
#include "translateEvents.h"
@ -139,6 +139,7 @@ const char *ERROR_STATE_STRING = "ERROR_STATE";
const char *RESET_OCCURED_STRING = "RESET_OCCURED";
const char *BOOTING_FIRMWARE_FAILED_EVENT_STRING = "BOOTING_FIRMWARE_FAILED_EVENT";
const char *BOOTING_BOOTLOADER_FAILED_EVENT_STRING = "BOOTING_BOOTLOADER_FAILED_EVENT";
const char *COM_ERROR_REPLY_RECEIVED_STRING = "COM_ERROR_REPLY_RECEIVED";
const char *SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING = "SUPV_MEMORY_READ_RPT_CRC_FAILURE";
const char *SUPV_UNKNOWN_TM_STRING = "SUPV_UNKNOWN_TM";
const char *SUPV_UNINIMPLEMENTED_TM_STRING = "SUPV_UNINIMPLEMENTED_TM";
@ -278,6 +279,7 @@ const char *TRYING_I2C_RECOVERY_STRING = "TRYING_I2C_RECOVERY";
const char *I2C_REBOOT_STRING = "I2C_REBOOT";
const char *PDEC_REBOOT_STRING = "PDEC_REBOOT";
const char *FIRMWARE_INFO_STRING = "FIRMWARE_INFO";
const char *ACTIVE_SD_INFO_STRING = "ACTIVE_SD_INFO";
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
@ -575,6 +577,8 @@ const char *translateEvents(Event event) {
return BOOTING_FIRMWARE_FAILED_EVENT_STRING;
case (11902):
return BOOTING_BOOTLOADER_FAILED_EVENT_STRING;
case (11903):
return COM_ERROR_REPLY_RECEIVED_STRING;
case (12001):
return SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING;
case (12002):
@ -853,6 +857,8 @@ const char *translateEvents(Event event) {
return PDEC_REBOOT_STRING;
case (14013):
return FIRMWARE_INFO_STRING;
case (14014):
return ACTIVE_SD_INFO_STRING;
case (14100):
return NO_VALID_SENSOR_TEMPERATURE_STRING;
case (14101):

View File

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

View File

@ -218,15 +218,30 @@ void Q7STestTask::testProtHandler() {
bool opPerformed = false;
ReturnValue_t result = returnvalue::OK;
// If any chips are unlocked, lock them here
result = coreController->setBootCopyProtection(xsc::Chip::ALL_CHIP, xsc::Copy::ALL_COPY, true,
opPerformed, true);
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::CHIP_0, xsc::Copy::COPY_0,
true);
if (result != returnvalue::OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::CHIP_0, xsc::Copy::COPY_1,
true);
if (result != returnvalue::OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::CHIP_1, xsc::Copy::COPY_0,
true);
if (result != returnvalue::OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::CHIP_1, xsc::Copy::COPY_1,
true);
if (result != returnvalue::OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}
// unlock own copy
result = coreController->setBootCopyProtection(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, false,
opPerformed, true);
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::SELF_CHIP,
xsc::Copy::SELF_COPY, false);
if (result != returnvalue::OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}
@ -239,8 +254,8 @@ void Q7STestTask::testProtHandler() {
}
// lock own copy
result = coreController->setBootCopyProtection(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, true,
opPerformed, true);
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::SELF_CHIP,
xsc::Copy::SELF_COPY, true);
if (result != returnvalue::OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}
@ -253,8 +268,8 @@ void Q7STestTask::testProtHandler() {
}
// unlock specific copy
result = coreController->setBootCopyProtection(xsc::Chip::CHIP_1, xsc::Copy::COPY_1, false,
opPerformed, true);
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::CHIP_1, xsc::Copy::COPY_1,
false);
if (result != returnvalue::OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}
@ -267,8 +282,8 @@ void Q7STestTask::testProtHandler() {
}
// lock specific copy
result = coreController->setBootCopyProtection(xsc::Chip::CHIP_1, xsc::Copy::COPY_1, true,
opPerformed, true);
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::CHIP_1, xsc::Copy::COPY_1,
true);
if (result != returnvalue::OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
}

View File

@ -156,20 +156,12 @@ ReturnValue_t CoreController::initialize() {
if (result != returnvalue::OK) {
sif::warning << "CoreController::initialize: Base init failed" << std::endl;
}
result = scratch::writeNumber(scratch::ALLOC_FAILURE_COUNT, 0);
if (result != returnvalue::OK) {
sif::warning << "CoreController::initialize: Setting up alloc failure "
"count failed"
<< std::endl;
}
result = paramHelper.initialize();
if (result != returnvalue::OK) {
return result;
}
sdStateMachine();
EventManagerIF *eventManager =
ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER);
if (eventManager == nullptr or eventQueue == nullptr) {
@ -189,7 +181,16 @@ ReturnValue_t CoreController::initialize() {
triggerEvent(core::REBOOT_SW, CURRENT_CHIP, CURRENT_COPY);
announceCurrentImageInfo();
announceVersionInfo();
SdCardManager::SdStatePair sdStates;
sdcMan->getSdCardsStatus(sdStates);
announceSdInfo(sdStates);
sdStateMachine();
result = scratch::writeNumber(scratch::ALLOC_FAILURE_COUNT, 0);
if (result != returnvalue::OK) {
sif::warning << "CoreController::initialize: Setting up alloc failure "
"count failed"
<< std::endl;
}
return result;
}
@ -553,21 +554,24 @@ ReturnValue_t CoreController::sdStateMachine() {
}
// This lambda checks the non-blocking operation of the SD card manager and assigns the new
// state on success. It returns true for an operation success and false otherwise
// state on success. It returns 0 for an operation success, -1 for failed operations, and 1
// for pending operations
auto nonBlockingSdcOpChecking = [&](SdStates newStateOnSuccess, uint16_t maxCycleCount,
std::string opPrintout) {
SdCardManager::OpStatus status = sdcMan->checkCurrentOp(operation);
if (status == SdCardManager::OpStatus::SUCCESS) {
if (status == SdCardManager::OpStatus::SUCCESS or sdInfo.cycleCount > maxCycleCount) {
sdFsmState = newStateOnSuccess;
sdInfo.commandPending = false;
if (sdInfo.cycleCount > maxCycleCount) {
sif::warning << "CoreController::sdStateMachine: " << opPrintout << " takes too long"
<< std::endl;
sdInfo.cycleCount = 0;
return -1;
}
sdInfo.cycleCount = 0;
return true;
} else if (sdInfo.cycleCount > 4) {
sif::warning << "CoreController::sdStateMachine: " << opPrintout << " takes too long"
<< std::endl;
return false;
}
return false;
return 0;
};
return 1;
};
if (sdFsmState == SdStates::UPDATE_SD_INFO_START) {
@ -643,7 +647,7 @@ ReturnValue_t CoreController::sdStateMachine() {
sdFsmState = tgtState;
}
} else {
if (nonBlockingSdcOpChecking(SdStates::MOUNT_SELF, 10, "Setting SDC state")) {
if (nonBlockingSdcOpChecking(SdStates::MOUNT_SELF, 10, "Setting SDC state") <= 0) {
sdInfo.activeState = sd::SdState::ON;
currentStateSetter(sdInfo.active, sd::SdState::ON);
// Skip the two cycles now.
@ -671,7 +675,7 @@ ReturnValue_t CoreController::sdStateMachine() {
result = sdCardSetup(sdInfo.active, sd::SdState::MOUNTED, sdInfo.activeChar);
sdInfo.commandPending = true;
} else {
if (nonBlockingSdcOpChecking(SdStates::DETERMINE_OTHER, 5, "Mounting SD card")) {
if (nonBlockingSdcOpChecking(SdStates::DETERMINE_OTHER, 5, "Mounting SD card") <= 0) {
sdcMan->setActiveSdCard(sdInfo.active);
currMntPrefix = sdcMan->getCurrentMountPrefix();
sdInfo.activeState = sd::SdState::MOUNTED;
@ -713,12 +717,7 @@ ReturnValue_t CoreController::sdStateMachine() {
sdInfo.commandPending = true;
} else {
if (nonBlockingSdcOpChecking(SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE, 10,
"Switching off other SD card")) {
sdInfo.otherState = sd::SdState::OFF;
currentStateSetter(sdInfo.other, sd::SdState::OFF);
} else {
// Continue.. avoid being stuck here..
sdFsmState = SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE;
"Switching off other SD card") <= 0) {
sdInfo.otherState = sd::SdState::OFF;
currentStateSetter(sdInfo.other, sd::SdState::OFF);
}
@ -729,12 +728,7 @@ ReturnValue_t CoreController::sdStateMachine() {
sdInfo.commandPending = true;
} else {
if (nonBlockingSdcOpChecking(SdStates::MOUNT_UNMOUNT_OTHER, 10,
"Switching on other SD card")) {
sdInfo.otherState = sd::SdState::ON;
currentStateSetter(sdInfo.other, sd::SdState::ON);
} else {
// Contnue.. avoid being stuck here.
sdFsmState = SdStates::MOUNT_UNMOUNT_OTHER;
"Switching on other SD card") <= 0) {
sdInfo.otherState = sd::SdState::ON;
currentStateSetter(sdInfo.other, sd::SdState::ON);
}
@ -749,7 +743,8 @@ ReturnValue_t CoreController::sdStateMachine() {
result = sdCardSetup(sdInfo.other, sd::SdState::ON, sdInfo.otherChar);
sdInfo.commandPending = true;
} else {
if (nonBlockingSdcOpChecking(SdStates::SET_STATE_OTHER, 10, "Unmounting other SD card")) {
if (nonBlockingSdcOpChecking(SdStates::SET_STATE_OTHER, 10, "Unmounting other SD card") <=
0) {
sdInfo.otherState = sd::SdState::ON;
currentStateSetter(sdInfo.other, sd::SdState::ON);
} else {
@ -763,7 +758,8 @@ ReturnValue_t CoreController::sdStateMachine() {
result = sdCardSetup(sdInfo.other, sd::SdState::MOUNTED, sdInfo.otherChar);
sdInfo.commandPending = true;
} else {
if (nonBlockingSdcOpChecking(SdStates::UPDATE_SD_INFO_END, 4, "Mounting other SD card")) {
if (nonBlockingSdcOpChecking(SdStates::UPDATE_SD_INFO_END, 4, "Mounting other SD card") <=
0) {
sdInfo.otherState = sd::SdState::MOUNTED;
currentStateSetter(sdInfo.other, sd::SdState::MOUNTED);
}
@ -800,6 +796,7 @@ ReturnValue_t CoreController::sdStateMachine() {
}
sif::info << "SD card update into " << modeStr
<< " mode finished. Active SD: " << sdInfo.activeChar << std::endl;
announceSdInfo(sdInfo.currentState);
if (not sdInfo.initFinished) {
updateInternalSdInfo();
sdInfo.initFinished = true;
@ -838,7 +835,7 @@ ReturnValue_t CoreController::sdCardSetup(sd::SdCard sdCard, sd::SdState targetS
if (state == sd::SdState::MOUNTED) {
if (targetState == sd::SdState::OFF) {
sif::info << "Switching off SD card " << sdChar << std::endl;
return sdcMan->switchOffSdCard(sdCard, true, &sdInfo.currentState);
return sdcMan->switchOffSdCard(sdCard, sdInfo.currentState, true);
} else if (targetState == sd::SdState::ON) {
sif::info << "Unmounting SD card " << sdChar << std::endl;
return sdcMan->unmountSdCard(sdCard);
@ -872,7 +869,7 @@ ReturnValue_t CoreController::sdCardSetup(sd::SdCard sdCard, sd::SdState targetS
return sdcMan->mountSdCard(sdCard);
} else if (targetState == sd::SdState::OFF) {
sif::info << "Switching off SD card " << sdChar << std::endl;
return sdcMan->switchOffSdCard(sdCard, false, &sdInfo.currentState);
return sdcMan->switchOffSdCard(sdCard, sdInfo.currentState, false);
}
} else {
sif::warning << "CoreController::sdCardSetup: Invalid state for this call" << std::endl;
@ -896,8 +893,7 @@ ReturnValue_t CoreController::sdColdRedundantBlockingInit() {
sif::info << "Switching off secondary SD card " << sdInfo.otherChar << std::endl;
// Switch off other SD card in cold redundant mode if setting up preferred one worked
// without issues
ReturnValue_t result2 =
sdcMan->switchOffSdCard(sdInfo.other, sdInfo.otherState, &sdInfo.currentState);
ReturnValue_t result2 = sdcMan->switchOffSdCard(sdInfo.other, sdInfo.currentState, true);
if (result2 != returnvalue::OK and result2 != SdCardManager::ALREADY_OFF) {
sif::warning << "Switching off secondary SD card " << sdInfo.otherChar
<< " in cold redundant mode failed" << std::endl;
@ -1227,18 +1223,25 @@ ReturnValue_t CoreController::gracefulShutdownTasks(xsc::Chip chip, xsc::Copy co
// Ensure that all writes/reads do finish.
sync();
// Attempt graceful shutdown by unmounting and switching off SD cards
sdcMan->switchOffSdCard(sd::SdCard::SLOT_0);
sdcMan->switchOffSdCard(sd::SdCard::SLOT_1);
// If any boot copies are unprotected.
// Actually this function only ensures that reboots to the own image are protected..
ReturnValue_t result = setBootCopyProtection(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, true,
protOpPerformed, false);
if (result == returnvalue::OK and protOpPerformed) {
// Unmount and switch off SD cards. This could possibly fix issues with the SD card and is
// the more graceful way to reboot the system. This function takes around 400 ms.
ReturnValue_t result = handleSwitchingSdCardsOffNonBlocking();
if (result != returnvalue::OK) {
sif::error
<< "CoreController::gracefulShutdownTasks: Issues unmounting or switching SD cards off"
<< std::endl;
}
// Ensure that the target chip is writeprotected in any case.
bool wasProtected = handleBootCopyProt(chip, copy, true);
if (wasProtected) {
// TODO: Would be nice to notify operator. But we can't use the filesystem anymore
// and a reboot is imminent. Use scratch buffer?
sif::info << "Running slot was writeprotected before reboot" << std::endl;
}
sif::info << "Graceful shutdown handling done" << std::endl;
// Ensure that all diagnostic prinouts arrive.
TaskFactory::delayTask(50);
return result;
}
@ -1272,144 +1275,50 @@ ReturnValue_t CoreController::generateChipStateFile() {
return returnvalue::OK;
}
ReturnValue_t CoreController::setBootCopyProtection(xsc::Chip targetChip, xsc::Copy targetCopy,
bool protect, bool &protOperationPerformed,
bool updateProtFile) {
bool allChips = false;
bool allCopies = false;
bool selfChip = false;
bool selfCopy = false;
protOperationPerformed = false;
switch (targetChip) {
case (xsc::Chip::ALL_CHIP): {
allChips = true;
break;
}
case (xsc::Chip::NO_CHIP): {
return returnvalue::OK;
}
case (xsc::Chip::SELF_CHIP): {
selfChip = true;
targetChip = CURRENT_CHIP;
break;
}
default: {
break;
}
}
switch (targetCopy) {
case (xsc::Copy::ALL_COPY): {
allCopies = true;
break;
}
case (xsc::Copy::NO_COPY): {
return returnvalue::OK;
}
case (xsc::Copy::SELF_COPY): {
selfCopy = true;
targetCopy = CURRENT_COPY;
break;
}
default: {
break;
}
ReturnValue_t CoreController::setBootCopyProtectionAndUpdateFile(xsc::Chip targetChip,
xsc::Copy targetCopy,
bool protect) {
if (targetChip == xsc::Chip::ALL_CHIP or targetCopy == xsc::Copy::ALL_COPY) {
return returnvalue::FAILED;
}
for (uint8_t arrIdx = 0; arrIdx < protArray.size(); arrIdx++) {
int result = handleBootCopyProtAtIndex(targetChip, targetCopy, protect, protOperationPerformed,
selfChip, selfCopy, allChips, allCopies, arrIdx);
if (result != 0) {
break;
}
}
if (protOperationPerformed and updateProtFile) {
bool protOperationPerformed = handleBootCopyProt(targetChip, targetCopy, protect);
if (protOperationPerformed) {
updateProtInfo();
}
return returnvalue::OK;
}
int CoreController::handleBootCopyProtAtIndex(xsc::Chip targetChip, xsc::Copy targetCopy,
bool protect, bool &protOperationPerformed,
bool selfChip, bool selfCopy, bool allChips,
bool allCopies, uint8_t arrIdx) {
bool currentProt = protArray[arrIdx];
bool CoreController::handleBootCopyProt(xsc::Chip targetChip, xsc::Copy targetCopy, bool protect) {
std::ostringstream oss;
bool performOp = false;
if (protect == currentProt) {
return 0;
}
if (protOperationPerformed) {
if ((selfChip and selfCopy) or (not allCopies and not allChips)) {
// No need to continue, only one operation was requested
return 1;
}
}
xsc::Chip currentChip;
xsc::Copy currentCopy;
oss << "writeprotect ";
if (arrIdx == 0 or arrIdx == 1) {
oss << "0 ";
currentChip = xsc::Chip::CHIP_0;
} else {
oss << "1 ";
currentChip = xsc::Chip::CHIP_1;
if (targetChip == xsc::Chip::SELF_CHIP) {
targetChip = CURRENT_CHIP;
}
if (arrIdx == 0 or arrIdx == 2) {
if (targetCopy == xsc::Copy::SELF_COPY) {
targetCopy = CURRENT_COPY;
}
if (targetChip == xsc::Chip::CHIP_0) {
oss << "0 ";
currentCopy = xsc::Copy::COPY_0;
} else {
} else if (targetChip == xsc::Chip::CHIP_1) {
oss << "1 ";
}
if (targetCopy == xsc::Copy::COPY_0) {
oss << "0 ";
} else if (targetCopy == xsc::Copy::COPY_1) {
oss << "1 ";
currentCopy = xsc::Copy::COPY_1;
}
if (protect) {
oss << "1";
} else {
oss << "0";
}
int result = 0;
if (allChips and allCopies) {
performOp = true;
} else if (allChips) {
if ((selfCopy and CURRENT_COPY == targetCopy) or (currentCopy == targetCopy)) {
performOp = true;
}
} else if (allCopies) {
if ((selfChip and CURRENT_COPY == targetCopy) or (currentChip == targetChip)) {
performOp = true;
}
} else if (selfChip and (currentChip == targetChip)) {
if (selfCopy) {
if (currentCopy == targetCopy) {
performOp = true;
}
} else {
performOp = true;
}
} else if (selfCopy and (currentCopy == targetCopy)) {
if (selfChip) {
if (currentChip == targetChip) {
performOp = true;
}
} else {
performOp = true;
}
} else if ((targetChip == currentChip) and (targetCopy == currentCopy)) {
performOp = true;
sif::info << "Executing command: " << oss.str() << std::endl;
int result = std::system(oss.str().c_str());
if (result == 0) {
return true;
}
if (result != 0) {
utility::handleSystemError(result, "CoreController::checkAndSetBootCopyProtection");
}
if (performOp) {
// TODO: Lock operation take a long time. Use command executor? That would require a
// new state machine..
protOperationPerformed = true;
sif::info << "Executing command: " << oss.str() << std::endl;
result = std::system(oss.str().c_str());
}
return 0;
return false;
}
ReturnValue_t CoreController::updateProtInfo(bool regenerateChipStateFile) {
@ -1454,7 +1363,6 @@ ReturnValue_t CoreController::handleProtInfoUpdateLine(std::string nextLine) {
using namespace std;
string word;
uint8_t wordIdx = 0;
uint8_t arrayIdx = 0;
istringstream iss(nextLine);
xsc::Chip currentChip = xsc::Chip::CHIP_0;
xsc::Copy currentCopy = xsc::Copy::COPY_0;
@ -1466,28 +1374,11 @@ ReturnValue_t CoreController::handleProtInfoUpdateLine(std::string nextLine) {
currentCopy = static_cast<xsc::Copy>(stoi(word));
}
if (wordIdx == 3) {
if (currentChip == xsc::Chip::CHIP_0) {
if (currentCopy == xsc::Copy::COPY_0) {
arrayIdx = 0;
} else if (currentCopy == xsc::Copy::COPY_1) {
arrayIdx = 1;
}
}
else if (currentChip == xsc::Chip::CHIP_1) {
if (currentCopy == xsc::Copy::COPY_0) {
arrayIdx = 2;
} else if (currentCopy == xsc::Copy::COPY_1) {
arrayIdx = 3;
}
}
}
if (wordIdx == 5) {
if (word == "unlocked.") {
protArray[arrayIdx] = false;
protArray[currentChip][currentCopy] = false;
} else {
protArray[arrayIdx] = true;
protArray[currentChip][currentCopy] = true;
}
}
wordIdx++;
@ -2570,6 +2461,68 @@ ReturnValue_t CoreController::performGracefulShutdown(xsc::Chip tgtChip, xsc::Co
return returnvalue::OK;
}
void CoreController::announceSdInfo(SdCardManager::SdStatePair sdStates) {
auto activeSdCard = sdcMan->getActiveSdCard();
uint32_t p1 = sd::SdCard::NONE;
if (activeSdCard.has_value()) {
p1 = static_cast<uint32_t>(activeSdCard.value());
}
uint32_t p2 =
(static_cast<uint32_t>(sdStates.first) << 16) | static_cast<uint32_t>(sdStates.second);
triggerEvent(core::ACTIVE_SD_INFO, p1, p2);
}
ReturnValue_t CoreController::handleSwitchingSdCardsOffNonBlocking() {
sdcMan->setBlocking(false);
SdCardManager::Operations op;
std::pair<sd::SdState, sd::SdState> sdStatus;
ReturnValue_t result = sdcMan->getSdCardsStatus(sdStatus);
if (result != returnvalue::OK) {
return result;
}
Countdown maxWaitTimeCd(10000);
// Stopwatch watch;
auto waitingForFinish = [&]() {
auto currentState = sdcMan->checkCurrentOp(op);
if (currentState == SdCardManager::OpStatus::IDLE) {
return returnvalue::OK;
}
while (currentState == SdCardManager::OpStatus::ONGOING) {
if (maxWaitTimeCd.hasTimedOut()) {
return returnvalue::FAILED;
}
TaskFactory::delayTask(50);
currentState = sdcMan->checkCurrentOp(op);
}
return returnvalue::OK;
};
if (sdStatus.first != sd::SdState::OFF) {
sdcMan->unmountSdCard(sd::SdCard::SLOT_0);
result = waitingForFinish();
if (result != returnvalue::OK) {
return result;
}
sdcMan->switchOffSdCard(sd::SdCard::SLOT_0, sdStatus, false);
result = waitingForFinish();
if (result != returnvalue::OK) {
return result;
}
}
if (sdStatus.second != sd::SdState::OFF) {
sdcMan->unmountSdCard(sd::SdCard::SLOT_1);
result = waitingForFinish();
if (result != returnvalue::OK) {
return result;
}
sdcMan->switchOffSdCard(sd::SdCard::SLOT_1, sdStatus, false);
result = waitingForFinish();
if (result != returnvalue::OK) {
return result;
}
}
return result;
}
bool CoreController::isNumber(const std::string &s) {
return !s.empty() && std::find_if(s.begin(), s.end(),
[](unsigned char c) { return !std::isdigit(c); }) == s.end();

View File

@ -199,8 +199,8 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
* @param updateProtFile Specify whether the protection info file is updated
* @return
*/
ReturnValue_t setBootCopyProtection(xsc::Chip targetChip, xsc::Copy targetCopy, bool protect,
bool& protOperationPerformed, bool updateProtFile = true);
ReturnValue_t setBootCopyProtectionAndUpdateFile(xsc::Chip targetChip, xsc::Copy targetCopy,
bool protect);
bool sdInitFinished() const;
@ -304,12 +304,10 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
Countdown sdCardCheckCd = Countdown(INIT_SD_CARD_CHECK_TIMEOUT);
/**
* Index 0: Chip 0 Copy 0
* Index 1: Chip 0 Copy 1
* Index 2: Chip 1 Copy 0
* Index 3: Chip 1 Copy 1
* First index: Chip.
* Second index: Copy.
*/
std::array<bool, 4> protArray;
bool protArray[2][2]{};
PeriodicOperationDivider opDivider5;
PeriodicOperationDivider opDivider10;
@ -374,9 +372,8 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
ReturnValue_t gracefulShutdownTasks(xsc::Chip chip, xsc::Copy copy, bool& protOpPerformed);
ReturnValue_t handleProtInfoUpdateLine(std::string nextLine);
int handleBootCopyProtAtIndex(xsc::Chip targetChip, xsc::Copy targetCopy, bool protect,
bool& protOperationPerformed, bool selfChip, bool selfCopy,
bool allChips, bool allCopies, uint8_t arrIdx);
ReturnValue_t handleSwitchingSdCardsOffNonBlocking();
bool handleBootCopyProt(xsc::Chip targetChip, xsc::Copy targetCopy, bool protect);
void rebootWatchdogAlgorithm(RebootWatchdogFile& rf, bool& needsReboot, xsc::Chip& tgtChip,
xsc::Copy& tgtCopy);
void resetRebootWatchdogCounters(xsc::Chip tgtChip, xsc::Copy tgtCopy);
@ -388,6 +385,7 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
void announceBootCounts();
void announceVersionInfo();
void announceCurrentImageInfo();
void announceSdInfo(SdCardManager::SdStatePair sdStates);
void readHkData();
void dirListingDumpHandler();
bool isNumber(const std::string& s);

View File

@ -85,6 +85,9 @@ void ObjectFactory::produce(void* args) {
#if OBSW_ADD_STAR_TRACKER == 1
dummyCfg.addStrDummy = false;
#endif
#if OBSW_ADD_SCEX_DEVICE == 0
dummyCfg.addScexDummy = true;
#endif
#if OBSW_ADD_BPX_BATTERY_HANDLER == 1
dummyCfg.addBpxBattDummy = false;
#endif
@ -121,6 +124,8 @@ void ObjectFactory::produce(void* args) {
if (core::FW_VERSION_MAJOR >= 4) {
battAndImtqI2cDev = q7s::I2C_PS_EIVE;
}
static_cast<void>(battAndImtqI2cDev);
#if OBSW_ADD_MGT == 1
createImtqComponents(pwrSwitcher, enableHkSets, battAndImtqI2cDev);
#endif

View File

@ -125,13 +125,8 @@ ReturnValue_t SdCardManager::switchOnSdCard(sd::SdCard sdCard, bool doMountSdCar
return mountSdCard(sdCard);
}
ReturnValue_t SdCardManager::switchOffSdCard(sd::SdCard sdCard, bool doUnmountSdCard,
SdStatePair* statusPair) {
std::pair<sd::SdState, sd::SdState> active;
ReturnValue_t result = getSdCardsStatus(active);
if (result != returnvalue::OK) {
return result;
}
ReturnValue_t SdCardManager::switchOffSdCard(sd::SdCard sdCard, SdStatePair& sdStates,
bool doUnmountSdCard) {
if (doUnmountSdCard) {
if (not blocking) {
sif::warning << "SdCardManager::switchOffSdCard: Two-step command but manager is"
@ -147,17 +142,17 @@ ReturnValue_t SdCardManager::switchOffSdCard(sd::SdCard sdCard, bool doUnmountSd
return returnvalue::FAILED;
}
if (sdCard == sd::SdCard::SLOT_0) {
if (active.first == sd::SdState::OFF) {
if (sdStates.first == sd::SdState::OFF) {
return ALREADY_OFF;
}
} else if (sdCard == sd::SdCard::SLOT_1) {
if (active.second == sd::SdState::OFF) {
if (sdStates.second == sd::SdState::OFF) {
return ALREADY_OFF;
}
}
if (doUnmountSdCard) {
result = unmountSdCard(sdCard);
ReturnValue_t result = unmountSdCard(sdCard);
if (result != returnvalue::OK) {
return result;
}
@ -189,7 +184,7 @@ ReturnValue_t SdCardManager::setSdCardState(sd::SdCard sdCard, bool on) {
command << "q7hw sd set " << sdstring << " " << statestring;
cmdExecutor.load(command.str(), blocking, printCmdOutput);
ReturnValue_t result = cmdExecutor.execute();
if (blocking and result != returnvalue::OK) {
if (result != returnvalue::OK) {
utility::handleSystemError(cmdExecutor.getLastError(), "SdCardManager::setSdCardState");
}
return result;
@ -204,6 +199,7 @@ ReturnValue_t SdCardManager::getSdCardsStatus(SdStatePair& sdStates) {
ReturnValue_t SdCardManager::mountSdCard(sd::SdCard sdCard) {
using namespace std;
if (cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING) {
sif::warning << "SdCardManager::mountSdCard: Command still pending" << std::endl;
return CommandExecutor::COMMAND_PENDING;
}
if (sdCard == sd::SdCard::BOTH) {

View File

@ -114,8 +114,7 @@ class SdCardManager : public SystemObject, public SdCardMountedIF {
* @return - returnvalue::OK on success, ALREADY_ON if it is already on,
* SYSTEM_CALL_ERROR on system error
*/
ReturnValue_t switchOffSdCard(sd::SdCard sdCard, bool doUnmountSdCard = true,
SdStatePair* statusPair = nullptr);
ReturnValue_t switchOffSdCard(sd::SdCard sdCard, SdStatePair& sdStates, bool doUnmountSdCard);
/**
* Get the state of the SD cards. If the state file does not exist, this function will

View File

@ -249,7 +249,7 @@ ReturnValue_t ObjectFactory::createRadSensorComponent(LinuxLibgpioIF* gpioComIF,
createRadSensorChipSelect(gpioComIF);
SpiCookie* spiCookieRadSensor =
new SpiCookie(addresses::RAD_SENSOR, gpioIds::CS_RAD_SENSOR, RAD_SENSOR::READ_SIZE,
new SpiCookie(addresses::RAD_SENSOR, gpioIds::CS_RAD_SENSOR, radSens::READ_SIZE,
spi::DEFAULT_MAX_1227_MODE, spi::DEFAULT_MAX_1227_SPEED);
spiCookieRadSensor->setMutexParams(MutexIF::TimeoutType::WAITING, spi::RAD_SENSOR_CS_TIMEOUT);
auto radSensor = new RadiationSensorHandler(objects::RAD_SENSOR, objects::SPI_MAIN_COM_IF,

View File

@ -19,6 +19,7 @@ target_sources(
GpsCtrlDummy.cpp
GyroAdisDummy.cpp
GyroL3GD20Dummy.cpp
RadSensorDummy.cpp
MgmLIS3MDLDummy.cpp
PlPcduDummy.cpp
ExecutableComIfDummy.cpp

View File

@ -7,7 +7,7 @@ PlPcduDummy::PlPcduDummy(object_id_t objectId, object_id_t comif, CookieIF *comC
PlPcduDummy::~PlPcduDummy() {}
void PlPcduDummy::doStartUp() { setMode(MODE_NORMAL); }
void PlPcduDummy::doStartUp() { setMode(MODE_ON); }
void PlPcduDummy::doShutDown() { setMode(MODE_OFF); }

View File

@ -0,0 +1,55 @@
#include "RadSensorDummy.h"
RadSensorDummy::RadSensorDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
: DeviceHandlerBase(objectId, comif, comCookie), sensorSet(this) {}
RadSensorDummy::~RadSensorDummy() {}
void RadSensorDummy::doStartUp() { setMode(MODE_ON); }
void RadSensorDummy::doShutDown() { setMode(MODE_OFF); }
ReturnValue_t RadSensorDummy::buildNormalDeviceCommand(DeviceCommandId_t *id) {
return NOTHING_TO_SEND;
}
ReturnValue_t RadSensorDummy::buildTransitionDeviceCommand(DeviceCommandId_t *id) {
return NOTHING_TO_SEND;
}
ReturnValue_t RadSensorDummy::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t *commandData,
size_t commandDataLen) {
return returnvalue::OK;
}
ReturnValue_t RadSensorDummy::scanForReply(const uint8_t *start, size_t len,
DeviceCommandId_t *foundId, size_t *foundLen) {
return returnvalue::OK;
}
ReturnValue_t RadSensorDummy::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) {
return returnvalue::OK;
}
void RadSensorDummy::fillCommandAndReplyMap() {}
uint32_t RadSensorDummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return 500; }
ReturnValue_t RadSensorDummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(radSens::TEMPERATURE_C, new PoolEntry<float>({0.0}));
localDataPoolMap.emplace(radSens::AIN0, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(radSens::AIN1, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(radSens::AIN4, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(radSens::AIN5, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(radSens::AIN6, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(radSens::AIN7, new PoolEntry<uint16_t>({0}));
poolManager.subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams(sensorSet.getSid(), false, 20.0));
return returnvalue::OK;
return returnvalue::OK;
}
LocalPoolDataSetBase *RadSensorDummy::getDataSetHandle(sid_t sid) { return &sensorSet; }

35
dummies/RadSensorDummy.h Normal file
View File

@ -0,0 +1,35 @@
#pragma once
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include "mission/payload/radSensorDefinitions.h"
class RadSensorDummy : public DeviceHandlerBase {
public:
static const DeviceCommandId_t SIMPLE_COMMAND = 1;
static const DeviceCommandId_t PERIODIC_REPLY = 2;
static const uint8_t SIMPLE_COMMAND_DATA = 1;
static const uint8_t PERIODIC_REPLY_DATA = 2;
RadSensorDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie);
virtual ~RadSensorDummy();
protected:
radSens::RadSensorDataset sensorSet;
void doStartUp() override;
void doShutDown() override;
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;
ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t *id) override;
ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t *commandData,
size_t commandDataLen) override;
ReturnValue_t scanForReply(const uint8_t *start, size_t len, DeviceCommandId_t *foundId,
size_t *foundLen) override;
ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) override;
void fillCommandAndReplyMap() override;
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) override;
LocalPoolDataSetBase *getDataSetHandle(sid_t sid) override;
};

View File

@ -5,7 +5,7 @@ SusDummy::SusDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
SusDummy::~SusDummy() {}
void SusDummy::doStartUp() { setMode(MODE_NORMAL); }
void SusDummy::doStartUp() { setMode(MODE_ON); }
void SusDummy::doShutDown() { setMode(MODE_OFF); }

View File

@ -18,6 +18,7 @@
#include <dummies/PlPcduDummy.h>
#include <dummies/PlocMpsocDummy.h>
#include <dummies/PlocSupervisorDummy.h>
#include <dummies/RadSensorDummy.h>
#include <dummies/RwDummy.h>
#include <dummies/SaDeploymentDummy.h>
#include <dummies/ScexDummy.h>
@ -34,6 +35,7 @@
#include "TemperatureSensorInserter.h"
#include "dummies/Max31865Dummy.h"
#include "dummies/SusDummy.h"
#include "dummies/Tmp1075Dummy.h"
#include "mission/genericFactory.h"
#include "mission/system/acs/acsModeTree.h"
@ -242,8 +244,10 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
power::Switches::PDU2_CH8_PAYLOAD_CAMERA);
camSwitcher->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
}
auto* scexDummy = new ScexDummy(objects::SCEX, objects::DUMMY_COM_IF, comCookieDummy);
scexDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
if (cfg.addScexDummy) {
auto* scexDummy = new ScexDummy(objects::SCEX, objects::DUMMY_COM_IF, comCookieDummy);
scexDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
}
auto* plPcduDummy =
new PlPcduDummy(objects::PLPCDU_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
plPcduDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
@ -255,4 +259,9 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
objects::PLOC_SUPERVISOR_HANDLER, objects::DUMMY_COM_IF, comCookieDummy, pwrSwitcher);
plocSupervisorDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
}
if (cfg.addRadSensorDummy) {
auto* radSensorDummy =
new RadSensorDummy(objects::RAD_SENSOR, objects::DUMMY_COM_IF, comCookieDummy);
radSensorDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
}
}

View File

@ -29,8 +29,10 @@ struct DummyCfg {
bool addPlocDummies = true;
bool addStrDummy = true;
bool addTmpDummies = true;
bool addRadSensorDummy = true;
Tmp1075Cfg tmp1075Cfg;
bool addCamSwitcherDummy = false;
bool addScexDummy = false;
};
void createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitch, GpioIF* gpioIF, bool enableHkSets);

2
fsfw

Submodule fsfw updated: 88e8665280...d575da8540

View File

@ -133,6 +133,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
11802;0x2e1a;RESET_OCCURED;LOW;No description;mission/acs/rwHelpers.h
11901;0x2e7d;BOOTING_FIRMWARE_FAILED_EVENT;LOW;Failed to boot firmware;mission/acs/str/StarTrackerHandler.h
11902;0x2e7e;BOOTING_BOOTLOADER_FAILED_EVENT;LOW;Failed to boot star tracker into bootloader mode;mission/acs/str/StarTrackerHandler.h
11903;0x2e7f;COM_ERROR_REPLY_RECEIVED;LOW;Received COM error. P1: Communication Error ID (datasheet p32);mission/acs/str/StarTrackerHandler.h
12001;0x2ee1;SUPV_MEMORY_READ_RPT_CRC_FAILURE;LOW;PLOC supervisor crc failure in telemetry packet;linux/payload/PlocSupervisorHandler.h
12002;0x2ee2;SUPV_UNKNOWN_TM;LOW;Unhandled event. P1: APID, P2: Service ID;linux/payload/PlocSupervisorHandler.h
12003;0x2ee3;SUPV_UNINIMPLEMENTED_TM;LOW;No description;linux/payload/PlocSupervisorHandler.h
@ -272,6 +273,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
14011;0x36bb;I2C_REBOOT;HIGH;I2C is unavailable. Recovery did not work, performing full reboot.;mission/sysDefs.h
14012;0x36bc;PDEC_REBOOT;HIGH;PDEC recovery through reset was not possible, performing full reboot.;mission/sysDefs.h
14013;0x36bd;FIRMWARE_INFO;INFO;Version information of the firmware (not OBSW). P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash P2: First four letters of Git SHA is the last byte of P1 is set.;mission/sysDefs.h
14014;0x36be;ACTIVE_SD_INFO;INFO;Active SD card info. SD States: 0: OFF, 1: ON, 2: MOUNTED. P1: Active SD Card Index, 0 if none is active P2: First two bytes: SD state of SD card 0, last two bytes SD state of SD card 1;mission/sysDefs.h
14100;0x3714;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/tcsDefs.h
14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/tcsDefs.h
14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h

1 Event ID (dec) Event ID (hex) Name Severity Description File Path
133 11802 0x2e1a RESET_OCCURED LOW No description mission/acs/rwHelpers.h
134 11901 0x2e7d BOOTING_FIRMWARE_FAILED_EVENT LOW Failed to boot firmware mission/acs/str/StarTrackerHandler.h
135 11902 0x2e7e BOOTING_BOOTLOADER_FAILED_EVENT LOW Failed to boot star tracker into bootloader mode mission/acs/str/StarTrackerHandler.h
136 11903 0x2e7f COM_ERROR_REPLY_RECEIVED LOW Received COM error. P1: Communication Error ID (datasheet p32) mission/acs/str/StarTrackerHandler.h
137 12001 0x2ee1 SUPV_MEMORY_READ_RPT_CRC_FAILURE LOW PLOC supervisor crc failure in telemetry packet linux/payload/PlocSupervisorHandler.h
138 12002 0x2ee2 SUPV_UNKNOWN_TM LOW Unhandled event. P1: APID, P2: Service ID linux/payload/PlocSupervisorHandler.h
139 12003 0x2ee3 SUPV_UNINIMPLEMENTED_TM LOW No description linux/payload/PlocSupervisorHandler.h
273 14011 0x36bb I2C_REBOOT HIGH I2C is unavailable. Recovery did not work, performing full reboot. mission/sysDefs.h
274 14012 0x36bc PDEC_REBOOT HIGH PDEC recovery through reset was not possible, performing full reboot. mission/sysDefs.h
275 14013 0x36bd FIRMWARE_INFO INFO Version information of the firmware (not OBSW). P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash P2: First four letters of Git SHA is the last byte of P1 is set. mission/sysDefs.h
276 14014 0x36be ACTIVE_SD_INFO INFO Active SD card info. SD States: 0: OFF, 1: ON, 2: MOUNTED. P1: Active SD Card Index, 0 if none is active P2: First two bytes: SD state of SD card 0, last two bytes SD state of SD card 1 mission/sysDefs.h
277 14100 0x3714 NO_VALID_SENSOR_TEMPERATURE MEDIUM No description mission/controller/tcsDefs.h
278 14101 0x3715 NO_HEALTHY_HEATER_AVAILABLE MEDIUM No description mission/controller/tcsDefs.h
279 14102 0x3716 SYRLINKS_OVERHEATING HIGH No description mission/controller/tcsDefs.h

View File

@ -133,6 +133,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
11802;0x2e1a;RESET_OCCURED;LOW;No description;mission/acs/rwHelpers.h
11901;0x2e7d;BOOTING_FIRMWARE_FAILED_EVENT;LOW;Failed to boot firmware;mission/acs/str/StarTrackerHandler.h
11902;0x2e7e;BOOTING_BOOTLOADER_FAILED_EVENT;LOW;Failed to boot star tracker into bootloader mode;mission/acs/str/StarTrackerHandler.h
11903;0x2e7f;COM_ERROR_REPLY_RECEIVED;LOW;Received COM error. P1: Communication Error ID (datasheet p32);mission/acs/str/StarTrackerHandler.h
12001;0x2ee1;SUPV_MEMORY_READ_RPT_CRC_FAILURE;LOW;PLOC supervisor crc failure in telemetry packet;linux/payload/PlocSupervisorHandler.h
12002;0x2ee2;SUPV_UNKNOWN_TM;LOW;Unhandled event. P1: APID, P2: Service ID;linux/payload/PlocSupervisorHandler.h
12003;0x2ee3;SUPV_UNINIMPLEMENTED_TM;LOW;No description;linux/payload/PlocSupervisorHandler.h
@ -272,6 +273,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
14011;0x36bb;I2C_REBOOT;HIGH;I2C is unavailable. Recovery did not work, performing full reboot.;mission/sysDefs.h
14012;0x36bc;PDEC_REBOOT;HIGH;PDEC recovery through reset was not possible, performing full reboot.;mission/sysDefs.h
14013;0x36bd;FIRMWARE_INFO;INFO;Version information of the firmware (not OBSW). P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash P2: First four letters of Git SHA is the last byte of P1 is set.;mission/sysDefs.h
14014;0x36be;ACTIVE_SD_INFO;INFO;Active SD card info. SD States: 0: OFF, 1: ON, 2: MOUNTED. P1: Active SD Card Index, 0 if none is active P2: First two bytes: SD state of SD card 0, last two bytes SD state of SD card 1;mission/sysDefs.h
14100;0x3714;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/tcsDefs.h
14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/tcsDefs.h
14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h

1 Event ID (dec) Event ID (hex) Name Severity Description File Path
133 11802 0x2e1a RESET_OCCURED LOW No description mission/acs/rwHelpers.h
134 11901 0x2e7d BOOTING_FIRMWARE_FAILED_EVENT LOW Failed to boot firmware mission/acs/str/StarTrackerHandler.h
135 11902 0x2e7e BOOTING_BOOTLOADER_FAILED_EVENT LOW Failed to boot star tracker into bootloader mode mission/acs/str/StarTrackerHandler.h
136 11903 0x2e7f COM_ERROR_REPLY_RECEIVED LOW Received COM error. P1: Communication Error ID (datasheet p32) mission/acs/str/StarTrackerHandler.h
137 12001 0x2ee1 SUPV_MEMORY_READ_RPT_CRC_FAILURE LOW PLOC supervisor crc failure in telemetry packet linux/payload/PlocSupervisorHandler.h
138 12002 0x2ee2 SUPV_UNKNOWN_TM LOW Unhandled event. P1: APID, P2: Service ID linux/payload/PlocSupervisorHandler.h
139 12003 0x2ee3 SUPV_UNINIMPLEMENTED_TM LOW No description linux/payload/PlocSupervisorHandler.h
273 14011 0x36bb I2C_REBOOT HIGH I2C is unavailable. Recovery did not work, performing full reboot. mission/sysDefs.h
274 14012 0x36bc PDEC_REBOOT HIGH PDEC recovery through reset was not possible, performing full reboot. mission/sysDefs.h
275 14013 0x36bd FIRMWARE_INFO INFO Version information of the firmware (not OBSW). P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash P2: First four letters of Git SHA is the last byte of P1 is set. mission/sysDefs.h
276 14014 0x36be ACTIVE_SD_INFO INFO Active SD card info. SD States: 0: OFF, 1: ON, 2: MOUNTED. P1: Active SD Card Index, 0 if none is active P2: First two bytes: SD state of SD card 0, last two bytes SD state of SD card 1 mission/sysDefs.h
277 14100 0x3714 NO_VALID_SENSOR_TEMPERATURE MEDIUM No description mission/controller/tcsDefs.h
278 14101 0x3715 NO_HEALTHY_HEATER_AVAILABLE MEDIUM No description mission/controller/tcsDefs.h
279 14102 0x3716 SYRLINKS_OVERHEATING HIGH No description mission/controller/tcsDefs.h

View File

@ -54,9 +54,13 @@ class BspConfig:
# Store this file in the root of the generators folder
self.csv_filename = Path(f"{ROOT_DIR}/{self.bsp_dir_name}_events.csv")
self.subsystems_csv_filename = Path(f"{ROOT_DIR}/{self.bsp_dir_name}_subsystems.csv")
self.subsystems_csv_filename = Path(
f"{ROOT_DIR}/{self.bsp_dir_name}_subsystems.csv"
)
self.csv_copy_dest = Path(f"{OBSW_ROOT_DIR}/tmtc/eive_tmtc/config/events.csv")
self.subsystem_csv_copy_dest = Path(f"{OBSW_ROOT_DIR}/tmtc/eive_tmtc/config/subsystems.csv")
self.subsystem_csv_copy_dest = Path(
f"{OBSW_ROOT_DIR}/tmtc/eive_tmtc/config/subsystems.csv"
)
if (
self.bsp_select == BspType.BSP_Q7S

View File

@ -1,7 +1,7 @@
/**
* @brief Auto-generated event translation file. Contains 299 translations.
* @brief Auto-generated event translation file. Contains 301 translations.
* @details
* Generated on: 2023-07-07 12:06:06
* Generated on: 2023-07-26 12:51:20
*/
#include "translateEvents.h"
@ -139,6 +139,7 @@ const char *ERROR_STATE_STRING = "ERROR_STATE";
const char *RESET_OCCURED_STRING = "RESET_OCCURED";
const char *BOOTING_FIRMWARE_FAILED_EVENT_STRING = "BOOTING_FIRMWARE_FAILED_EVENT";
const char *BOOTING_BOOTLOADER_FAILED_EVENT_STRING = "BOOTING_BOOTLOADER_FAILED_EVENT";
const char *COM_ERROR_REPLY_RECEIVED_STRING = "COM_ERROR_REPLY_RECEIVED";
const char *SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING = "SUPV_MEMORY_READ_RPT_CRC_FAILURE";
const char *SUPV_UNKNOWN_TM_STRING = "SUPV_UNKNOWN_TM";
const char *SUPV_UNINIMPLEMENTED_TM_STRING = "SUPV_UNINIMPLEMENTED_TM";
@ -278,6 +279,7 @@ const char *TRYING_I2C_RECOVERY_STRING = "TRYING_I2C_RECOVERY";
const char *I2C_REBOOT_STRING = "I2C_REBOOT";
const char *PDEC_REBOOT_STRING = "PDEC_REBOOT";
const char *FIRMWARE_INFO_STRING = "FIRMWARE_INFO";
const char *ACTIVE_SD_INFO_STRING = "ACTIVE_SD_INFO";
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
@ -575,6 +577,8 @@ const char *translateEvents(Event event) {
return BOOTING_FIRMWARE_FAILED_EVENT_STRING;
case (11902):
return BOOTING_BOOTLOADER_FAILED_EVENT_STRING;
case (11903):
return COM_ERROR_REPLY_RECEIVED_STRING;
case (12001):
return SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING;
case (12002):
@ -853,6 +857,8 @@ const char *translateEvents(Event event) {
return PDEC_REBOOT_STRING;
case (14013):
return FIRMWARE_INFO_STRING;
case (14014):
return ACTIVE_SD_INFO_STRING;
case (14100):
return NO_VALID_SENSOR_TEMPERATURE_STRING;
case (14101):

View File

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

View File

@ -2,6 +2,7 @@
#include <fcntl.h>
#include <fsfw/filesystem/HasFileSystemIF.h>
#include <fsfw/globalfunctions/arrayprinter.h>
#include <fsfw/tasks/TaskFactory.h>
#include <fsfw/timemanager/Stopwatch.h>
#include <mission/acs/str/strHelpers.h>
@ -23,6 +24,8 @@ extern "C" {
using namespace returnvalue;
static constexpr bool PACKET_WIRETAPPING = false;
StrComHandler::StrComHandler(object_id_t objectId) : SystemObject(objectId) {
lock = MutexFactory::instance()->createMutex();
semaphore.acquire();
@ -52,7 +55,7 @@ ReturnValue_t StrComHandler::performOperation(uint8_t operationCode) {
case InternalState::POLL_ONE_REPLY: {
// Stopwatch watch;
replyTimeout.setTimeout(200);
replyResult = readOneReply(static_cast<uint32_t>(state));
readOneReply(static_cast<uint32_t>(state));
{
MutexGuard mg(lock);
replyWasReceived = true;
@ -680,6 +683,10 @@ ReturnValue_t StrComHandler::sendMessage(CookieIF* cookie, const uint8_t* sendDa
const uint8_t* txFrame;
size_t frameLen;
datalinkLayer.encodeFrame(sendData, sendLen, &txFrame, frameLen);
if (PACKET_WIRETAPPING) {
sif::debug << "Sending STR frame" << std::endl;
arrayprinter::print(txFrame, frameLen);
}
ssize_t bytesWritten = write(serialPort, txFrame, frameLen);
if (bytesWritten != static_cast<ssize_t>(frameLen)) {
sif::warning << "StrComHandler: Sending packet failed" << std::endl;
@ -709,13 +716,11 @@ ReturnValue_t StrComHandler::requestReceiveMessage(CookieIF* cookie, size_t requ
}
ReturnValue_t StrComHandler::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) {
// Consider it a configuration error if the task is not done with a command -> reply cycle
// in time.
bool replyWasReceived = false;
{
MutexGuard mg(lock);
if (state != InternalState::SLEEPING) {
return BUSY;
return returnvalue::OK;
}
replyWasReceived = this->replyWasReceived;
}
@ -728,7 +733,7 @@ ReturnValue_t StrComHandler::readReceivedMessage(CookieIF* cookie, uint8_t** buf
*size = replyLen;
}
replyLen = 0;
return replyResult;
return returnvalue::OK;
}
ReturnValue_t StrComHandler::unlockAndEraseRegions(uint32_t from, uint32_t to) {
@ -782,8 +787,10 @@ ReturnValue_t StrComHandler::handleSerialReception() {
<< std::endl;
return FAILED;
} else if (bytesRead > 0) {
// sif::info << "Received " << bytesRead << " bytes from the STR" << std::endl;
// arrayprinter::print(recBuf.data(), bytesRead);
if (PACKET_WIRETAPPING) {
sif::info << "Received " << bytesRead << " bytes from the STR" << std::endl;
arrayprinter::print(recBuf.data(), bytesRead);
}
datalinkLayer.feedData(recBuf.data(), bytesRead);
}
return OK;
@ -797,6 +804,10 @@ ReturnValue_t StrComHandler::readOneReply(uint32_t failParameter) {
handleSerialReception();
result = datalinkLayer.checkRingBufForFrame(&replyPtr, replyLen);
if (result == returnvalue::OK) {
if (PACKET_WIRETAPPING) {
sif::debug << "Received STR reply frame" << std::endl;
arrayprinter::print(replyPtr, replyLen);
}
return returnvalue::OK;
} else if (result != ArcsecDatalinkLayer::DEC_IN_PROGRESS) {
triggerEvent(STR_HELPER_DEC_ERROR, result, failParameter);

View File

@ -1,7 +1,7 @@
/**
* @brief Auto-generated event translation file. Contains 299 translations.
* @brief Auto-generated event translation file. Contains 301 translations.
* @details
* Generated on: 2023-07-07 12:06:06
* Generated on: 2023-07-26 12:51:20
*/
#include "translateEvents.h"
@ -139,6 +139,7 @@ const char *ERROR_STATE_STRING = "ERROR_STATE";
const char *RESET_OCCURED_STRING = "RESET_OCCURED";
const char *BOOTING_FIRMWARE_FAILED_EVENT_STRING = "BOOTING_FIRMWARE_FAILED_EVENT";
const char *BOOTING_BOOTLOADER_FAILED_EVENT_STRING = "BOOTING_BOOTLOADER_FAILED_EVENT";
const char *COM_ERROR_REPLY_RECEIVED_STRING = "COM_ERROR_REPLY_RECEIVED";
const char *SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING = "SUPV_MEMORY_READ_RPT_CRC_FAILURE";
const char *SUPV_UNKNOWN_TM_STRING = "SUPV_UNKNOWN_TM";
const char *SUPV_UNINIMPLEMENTED_TM_STRING = "SUPV_UNINIMPLEMENTED_TM";
@ -278,6 +279,7 @@ const char *TRYING_I2C_RECOVERY_STRING = "TRYING_I2C_RECOVERY";
const char *I2C_REBOOT_STRING = "I2C_REBOOT";
const char *PDEC_REBOOT_STRING = "PDEC_REBOOT";
const char *FIRMWARE_INFO_STRING = "FIRMWARE_INFO";
const char *ACTIVE_SD_INFO_STRING = "ACTIVE_SD_INFO";
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
@ -575,6 +577,8 @@ const char *translateEvents(Event event) {
return BOOTING_FIRMWARE_FAILED_EVENT_STRING;
case (11902):
return BOOTING_BOOTLOADER_FAILED_EVENT_STRING;
case (11903):
return COM_ERROR_REPLY_RECEIVED_STRING;
case (12001):
return SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING;
case (12002):
@ -853,6 +857,8 @@ const char *translateEvents(Event event) {
return PDEC_REBOOT_STRING;
case (14013):
return FIRMWARE_INFO_STRING;
case (14014):
return ACTIVE_SD_INFO_STRING;
case (14100):
return NO_VALID_SENSOR_TEMPERATURE_STRING;
case (14101):

View File

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

View File

@ -26,10 +26,18 @@ enum SafeModeStrategy : uint8_t {
SAFECTRL_OFF = 0,
SAFECTRL_NO_MAG_FIELD_FOR_CONTROL = 1,
SAFECTRL_NO_SENSORS_FOR_CONTROL = 2,
SAFECTRL_ACTIVE_MEKF = 10,
SAFECTRL_WITHOUT_MEKF = 11,
SAFECTRL_ECLIPSE_DAMPING = 12,
SAFECTRL_ECLIPSE_IDELING = 13,
// OBSW version <= v6.1.0
LEGACY_SAFECTRL_ACTIVE_MEKF = 10,
LEGACY_SAFECTRL_WITHOUT_MEKF = 11,
LEGACY_SAFECTRL_ECLIPSE_DAMPING = 12,
LEGACY_SAFECTRL_ECLIPSE_IDELING = 13,
// Added in v6.2.0
SAFECTRL_MEKF = 14,
SAFECTRL_GYR = 15,
SAFECTRL_SUSMGM = 16,
SAFECTRL_ECLIPSE_DAMPING_GYR = 17,
SAFECTRL_ECLIPSE_DAMPING_SUSMGM = 18,
SAFECTRL_ECLIPSE_IDELING = 19,
SAFECTRL_DETUMBLE_FULL = 20,
SAFECTRL_DETUMBLE_DETERIORATED = 21,
};

View File

@ -1,3 +1,4 @@
#include <fsfw/globalfunctions/arrayprinter.h>
#include <fsfw/ipc/QueueFactory.h>
#include <fsfw/timemanager/Stopwatch.h>
#include <mission/acs/str/StarTrackerHandler.h>
@ -88,7 +89,6 @@ void StarTrackerHandler::doStartUp() {
default:
return;
}
solutionSet.setReportingEnabled(true);
startupState = StartupState::DONE;
internalState = InternalState::IDLE;
setMode(_MODE_TO_ON);
@ -325,7 +325,7 @@ ReturnValue_t StarTrackerHandler::buildNormalDeviceCommand(DeviceCommandId_t* id
ReturnValue_t StarTrackerHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) {
switch (internalState) {
case InternalState::BOOT_FIRMWARE: {
if (bootState == FwBootState::WAIT_FOR_EXECUTION or bootState == FwBootState::VERIFY_BOOT) {
if (bootState == FwBootState::VERIFY_BOOT or isAwaitingReply()) {
return NOTHING_TO_SEND;
}
if (bootState == FwBootState::NONE) {
@ -349,74 +349,69 @@ ReturnValue_t StarTrackerHandler::buildTransitionDeviceCommand(DeviceCommandId_t
*id = startracker::REQ_VERSION;
return buildCommandFromCommand(*id, nullptr, 0);
}
case (FwBootState::SET_TIME): {
*id = startracker::SET_TIME_FROM_SYS_TIME;
return buildCommandFromCommand(*id, nullptr, 0);
}
case (FwBootState::LOGLEVEL): {
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::LOGLEVEL;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
}
case (FwBootState::LIMITS): {
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::LIMITS;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
}
case (FwBootState::TRACKING): {
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::TRACKING;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
}
case FwBootState::MOUNTING:
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::MOUNTING;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::IMAGE_PROCESSOR:
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::IMAGE_PROCESSOR;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::CAMERA:
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::CAMERA;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::CENTROIDING:
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::CENTROIDING;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::LISA:
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::LISA;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::MATCHING:
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::MATCHING;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::VALIDATION:
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::VALIDATION;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::ALGO:
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::ALGO;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::LOG_SUBSCRIPTION:
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::LOGSUBSCRIPTION;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::DEBUG_CAMERA:
bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::DEBUG_CAMERA;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::AUTO_THRESHOLD:
*id = startracker::AUTO_THRESHOLD;
return buildCommandFromCommand(
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
default: {
sif::error << "STR: Unexpected boot state" << (int)bootState << std::endl;
return NOTHING_TO_SEND;
@ -459,6 +454,20 @@ ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t devi
preparePingRequest();
return returnvalue::OK;
}
case (startracker::SET_TIME_FROM_SYS_TIME): {
SetTimeActionRequest setTimeRequest{};
timeval tv;
Clock::getClock(&tv);
setTimeRequest.unixTime =
(static_cast<uint64_t>(tv.tv_sec) * 1000 * 1000) + (static_cast<uint64_t>(tv.tv_usec));
arc_pack_settime_action_req(&setTimeRequest, commandBuffer, &rawPacketLen);
size_t serLen = 0;
// Time in milliseconds. Manual serialization because arcsec API ignores endianness.
SerializeAdapter::serialize(&setTimeRequest.unixTime, commandBuffer + 2, &serLen,
sizeof(commandBuffer) - 2, SerializeIF::Endianness::LITTLE);
rawPacket = commandBuffer;
return returnvalue::OK;
}
case (startracker::REQ_TIME): {
prepareTimeRequest();
return returnvalue::OK;
@ -551,6 +560,11 @@ ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t devi
result = prepareParamCommand(commandData, commandDataLen, jcfgs.logLevel, reinitNextSetParam);
return result;
}
case (startracker::AUTO_THRESHOLD): {
result =
prepareParamCommand(commandData, commandDataLen, jcfgs.autoThreshold, reinitNextSetParam);
return result;
}
case (startracker::LOGSUBSCRIPTION): {
result = prepareParamCommand(commandData, commandDataLen, jcfgs.logSubscription,
reinitNextSetParam);
@ -655,19 +669,23 @@ void StarTrackerHandler::fillCommandAndReplyMap() {
startracker::MAX_FRAME_SIZE * 2 + 2);
this->insertInCommandAndReplyMap(startracker::LOGLEVEL, 3, nullptr,
startracker::MAX_FRAME_SIZE * 2 + 2);
this->insertInCommandAndReplyMap(startracker::SET_TIME_FROM_SYS_TIME, 2, nullptr,
startracker::MAX_FRAME_SIZE * 2 + 2);
this->insertInCommandAndReplyMap(startracker::LOGSUBSCRIPTION, 3, nullptr,
startracker::MAX_FRAME_SIZE * 2 + 2);
this->insertInCommandAndReplyMap(startracker::DEBUG_CAMERA, 3, nullptr,
startracker::MAX_FRAME_SIZE * 2 + 2);
this->insertInCommandAndReplyMap(startracker::LIMITS, 3, nullptr,
startracker::MAX_FRAME_SIZE * 2 + 2);
this->insertInCommandAndReplyMap(startracker::AUTO_THRESHOLD, 2, nullptr,
startracker::MAX_FRAME_SIZE * 2 + 2);
this->insertInCommandAndReplyMap(startracker::MOUNTING, 3, nullptr,
startracker::MAX_FRAME_SIZE * 2 + 2);
this->insertInCommandAndReplyMap(startracker::IMAGE_PROCESSOR, 3, nullptr,
startracker::MAX_FRAME_SIZE * 2 + 2);
this->insertInCommandAndReplyMap(startracker::CAMERA, 3, nullptr,
startracker::MAX_FRAME_SIZE * 2 + 2);
this->insertInCommandAndReplyMap(startracker::CENTROIDING, 3, nullptr,
this->insertInCommandAndReplyMap(startracker::CENTROIDING, 2, nullptr,
startracker::MAX_FRAME_SIZE * 2 + 2);
this->insertInCommandAndReplyMap(startracker::LISA, 3, nullptr,
startracker::MAX_FRAME_SIZE * 2 + 2);
@ -814,6 +832,7 @@ void StarTrackerHandler::bootFirmware(Mode_t toMode) {
setMode(toMode, startracker::SUBMODE_FIRMWARE);
}
sif::info << "STR: Firmware boot success" << std::endl;
solutionSet.setReportingEnabled(true);
internalState = InternalState::IDLE;
startupState = StartupState::IDLE;
break;
@ -837,6 +856,7 @@ void StarTrackerHandler::setUpJsonCfgs(JsonConfigs& cfgs, const char* paramJsonF
cfgs.mounting.init(paramJsonFile);
cfgs.limits.init(paramJsonFile);
cfgs.subscription.init(paramJsonFile);
cfgs.autoThreshold.init(paramJsonFile);
JCFG_DONE = true;
}
@ -860,13 +880,20 @@ ReturnValue_t StarTrackerHandler::scanForReply(const uint8_t* start, size_t rema
*foundLen = remainingSize;
return returnvalue::OK;
}
if (remainingSize < 3) {
sif::error << "StarTrackerHandler: Reply packet with length less than 3 is invalid"
if (remainingSize < 2) {
sif::error << "StarTrackerHandler: Reply packet with length " << remainingSize
<< " less than "
"2 is invalid"
<< std::endl;
return returnvalue::FAILED;
}
switch (startracker::getReplyFrameType(start)) {
case TMTC_COMM_ERROR: {
*foundLen = remainingSize;
triggerEvent(COM_ERROR_REPLY_RECEIVED, start[1]);
break;
}
case TMTC_ACTIONREPLY: {
*foundLen = remainingSize;
return scanForActionReply(startracker::getId(start), foundId);
@ -901,6 +928,10 @@ ReturnValue_t StarTrackerHandler::interpretDeviceReply(DeviceCommandId_t id,
ReturnValue_t result = returnvalue::OK;
switch (id) {
case (startracker::SET_TIME_FROM_SYS_TIME): {
result = handleActionReply(packet);
break;
}
case (startracker::REQ_TIME): {
result = handleTm(packet, timeSet, startracker::TimeSet::SIZE, "REQ_TIME");
break;
@ -960,7 +991,8 @@ ReturnValue_t StarTrackerHandler::interpretDeviceReply(DeviceCommandId_t id,
case (startracker::TRACKING):
case (startracker::VALIDATION):
case (startracker::IMAGE_PROCESSOR):
case (startracker::ALGO): {
case (startracker::ALGO):
case (startracker::AUTO_THRESHOLD): {
result = handleSetParamReply(packet);
break;
}
@ -1367,6 +1399,10 @@ ReturnValue_t StarTrackerHandler::scanForActionReply(uint8_t replyId, DeviceComm
*foundId = startracker::UPLOAD_IMAGE;
break;
}
case (ARC_ACTION_REQ_SETTIME_ID): {
*foundId = startracker::SET_TIME_FROM_SYS_TIME;
break;
}
case (startracker::ID::CHECKSUM): {
*foundId = startracker::CHECKSUM;
break;
@ -1434,6 +1470,10 @@ ReturnValue_t StarTrackerHandler::scanForSetParameterReply(uint8_t replyId,
*foundId = startracker::DEBUG_CAMERA;
break;
}
case (startracker::ID::AUTO_THRESHOLD): {
*foundId = startracker::AUTO_THRESHOLD;
break;
}
case (startracker::ID::LOG_SUBSCRIPTION): {
*foundId = startracker::LOGSUBSCRIPTION;
break;
@ -1861,7 +1901,7 @@ ReturnValue_t StarTrackerHandler::handleSetParamReply(const uint8_t* rawFrame) {
uint8_t status = startracker::getStatusField(rawFrame);
if (status != startracker::STATUS_OK) {
sif::warning << "StarTrackerHandler::handleSetParamReply: Failed to execute parameter set "
" command with parameter ID"
"command with parameter ID "
<< static_cast<unsigned int>(*(rawFrame + PARAMETER_ID_OFFSET)) << std::endl;
if (internalState != InternalState::IDLE) {
internalState = InternalState::IDLE;
@ -1869,21 +1909,25 @@ ReturnValue_t StarTrackerHandler::handleSetParamReply(const uint8_t* rawFrame) {
return SET_PARAM_FAILED;
}
if (internalState != InternalState::IDLE) {
handleStartup(*(rawFrame + PARAMETER_ID_OFFSET));
handleStartup(*rawFrame, *(rawFrame + PARAMETER_ID_OFFSET));
}
return returnvalue::OK;
}
ReturnValue_t StarTrackerHandler::handleActionReply(const uint8_t* rawFrame) {
uint8_t status = startracker::getStatusField(rawFrame);
ReturnValue_t result = returnvalue::OK;
if (status != startracker::STATUS_OK) {
sif::warning << "StarTrackerHandler::handleActionReply: Failed to execute action "
<< "command with action ID "
<< static_cast<unsigned int>(*(rawFrame + ACTION_ID_OFFSET)) << " and status "
<< static_cast<unsigned int>(status) << std::endl;
return ACTION_FAILED;
result = ACTION_FAILED;
}
return returnvalue::OK;
if (internalState != InternalState::IDLE) {
handleStartup(*rawFrame, *(rawFrame + PARAMETER_ID_OFFSET));
}
return result;
}
ReturnValue_t StarTrackerHandler::handleChecksumReply(const uint8_t* rawFrame) {
@ -1979,7 +2023,7 @@ ReturnValue_t StarTrackerHandler::checkProgram() {
startupState = StartupState::BOOT_BOOTLOADER;
}
if (bootState == FwBootState::VERIFY_BOOT) {
bootState = FwBootState::LOGLEVEL;
bootState = FwBootState::SET_TIME;
} else if (internalState == InternalState::BOOTLOADER_CHECK) {
triggerEvent(BOOTING_BOOTLOADER_FAILED_EVENT);
internalState = InternalState::FAILED_BOOTLOADER_BOOT;
@ -2056,7 +2100,18 @@ ReturnValue_t StarTrackerHandler::handleActionReplySet(const uint8_t* rawFrame,
return result;
}
void StarTrackerHandler::handleStartup(uint8_t parameterId) {
void StarTrackerHandler::handleStartup(uint8_t tmType, uint8_t parameterId) {
switch (tmType) {
case (TMTC_ACTIONREPLY): {
case (ARC_ACTION_REQ_SETTIME_ID): {
bootState = FwBootState::LOGLEVEL;
return;
}
default: {
break;
}
}
}
switch (parameterId) {
case (startracker::ID::LOG_LEVEL): {
bootState = FwBootState::LIMITS;
@ -2066,7 +2121,7 @@ void StarTrackerHandler::handleStartup(uint8_t parameterId) {
bootState = FwBootState::TRACKING;
break;
}
case (startracker::ID::TRACKING): {
case (ARC_PARAM_TRACKING_ID): {
bootState = FwBootState::MOUNTING;
break;
}
@ -2107,6 +2162,10 @@ void StarTrackerHandler::handleStartup(uint8_t parameterId) {
break;
}
case (startracker::ID::DEBUG_CAMERA): {
bootState = FwBootState::AUTO_THRESHOLD;
break;
}
case (startracker::ID::AUTO_THRESHOLD): {
bootState = FwBootState::NONE;
internalState = InternalState::DONE;
break;

View File

@ -6,6 +6,7 @@
#include <mission/acs/str/ArcsecJsonParamBase.h>
#include <mission/acs/str/strHelpers.h>
#include <mission/acs/str/strJsonCommands.h>
#include <thirdparty/sagittactl/wire/common/genericstructs.h>
#include <thread>
@ -16,7 +17,7 @@
#include "fsfw/timemanager/Countdown.h"
extern "C" {
#include <wire/common/SLIP.h>
#include <wire/common/genericstructs.h>
}
/**
@ -143,6 +144,8 @@ class StarTrackerHandler : public DeviceHandlerBase {
static const Event BOOTING_FIRMWARE_FAILED_EVENT = MAKE_EVENT(1, severity::LOW);
//! [EXPORT] : [COMMENT] Failed to boot star tracker into bootloader mode
static const Event BOOTING_BOOTLOADER_FAILED_EVENT = MAKE_EVENT(2, severity::LOW);
//! [EXPORT] : [COMMENT] Received COM error. P1: Communication Error ID (datasheet p32)
static constexpr Event COM_ERROR_REPLY_RECEIVED = MAKE_EVENT(3, severity::LOW);
static const uint8_t STATUS_OFFSET = 2;
static const uint8_t PARAMS_OFFSET = 2;
@ -226,6 +229,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
Mounting mounting;
Limits limits;
Subscription subscription;
AutoThreshold autoThreshold;
};
JsonConfigs jcfgs;
Countdown jcfgCountdown = Countdown(250);
@ -264,6 +268,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
BOOT_DELAY,
REQ_VERSION,
VERIFY_BOOT,
SET_TIME,
LOGLEVEL,
LIMITS,
TRACKING,
@ -278,7 +283,9 @@ class StarTrackerHandler : public DeviceHandlerBase {
ALGO,
LOG_SUBSCRIPTION,
DEBUG_CAMERA,
AUTO_THRESHOLD,
WAIT_FOR_EXECUTION,
RETRY_CFG_CMD
};
FwBootState bootState = FwBootState::NONE;
@ -468,7 +475,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
/**
* @brief Handles the startup state machine
*/
void handleStartup(uint8_t parameterId);
void handleStartup(uint8_t tmType, uint8_t parameterId);
/**
* @brief Handles telemtry replies and fills the appropriate dataset

View File

@ -176,6 +176,13 @@ static const char DEBUG_CAMERA[] = "DebugCamera";
static const char TIMING[] = "timing";
static const char TEST[] = "test";
static constexpr char AUTO_THRESHOLD[] = "AutoThreshold";
static constexpr char AT_MODE[] = "mode";
static constexpr char AT_DESIRED_BLOB_COUNTS[] = "desiredBlobsCount";
static constexpr char AT_MIN_THRESHOLD[] = "minThreshold";
static constexpr char AT_MAX_THRESHOLD[] = "maxThreshold";
static constexpr char AT_THRESHOLD_KP[] = "thresholdKp";
} // namespace arcseckeys
#endif /* BSP_Q7S_DEVICES_DEVICEDEFINITIONS_ARCSECJSONKEYS_H_ */

View File

@ -326,6 +326,8 @@ static const DeviceCommandId_t DEBUG_CAMERA = 83;
static const DeviceCommandId_t FIRMWARE_UPDATE = 84;
static const DeviceCommandId_t DISABLE_TIMESTAMP_GENERATION = 85;
static const DeviceCommandId_t ENABLE_TIMESTAMP_GENERATION = 86;
static constexpr DeviceCommandId_t SET_TIME_FROM_SYS_TIME = 87;
static constexpr DeviceCommandId_t AUTO_THRESHOLD = 88;
static const DeviceCommandId_t NONE = 0xFFFFFFFF;
static const uint32_t VERSION_SET_ID = REQ_VERSION;
@ -396,7 +398,6 @@ static const uint8_t ALGO = 16;
static const uint8_t REBOOT = 7;
static const uint8_t UPLOAD_IMAGE = 10;
static const uint8_t POWER = 11;
static const uint8_t SET_TIME = 14;
static const uint8_t SUBSCRIPTION = 18;
static const uint8_t SOLUTION = 24;
static const uint8_t TEMPERATURE = 27;
@ -410,6 +411,7 @@ static const uint8_t TAKE_IMAGE = 15;
static const uint8_t LOG_LEVEL = 3;
static const uint8_t LOG_SUBSCRIPTION = 19;
static const uint8_t DEBUG_CAMERA = 20;
static const uint8_t AUTO_THRESHOLD = 23;
} // namespace ID
namespace Program {
@ -441,6 +443,21 @@ static const uint32_t secret[16]{
REGION_12_SECRET, REGION_13_SECRET, REGION_14_SECRET, REGION_15_SECRET};
} // namespace region_secrets
namespace comError {
enum Id {
BAD_CRC = 1,
UNKNOWN_TM_ID = 2,
UNKNOWN_PARAM_ID = 3,
UNKNOWN_ACTION_REQ = 4,
INVALID_TM_SIZE = 5,
INVALID_PARAM_SIZE = 6,
INVALID_ACTION_REQ_SIZE = 7,
FRAME_TOO_SHORT = 8,
INVALID_FRAME_TYPE = 9,
UNKNOWN_ERROR = 10
};
}
enum class FlashSections : uint8_t {
BOOTLOADER_SECTION = 0,
MAIN_FIRMWARE_SECTION = 1,
@ -650,7 +667,7 @@ class SolutionSet : public StaticLocalDataSet<SOLUTION_SET_ENTRIES> {
// Ticks timestamp
lp_var_t<uint32_t> ticks = lp_var_t<uint32_t>(sid.objectId, PoolIds::TICKS_SOLUTION_SET, this);
/// Unix time stamp
lp_var_t<uint64_t> time = lp_var_t<uint64_t>(sid.objectId, PoolIds::TIME_SOLUTION_SET, this);
lp_var_t<uint64_t> timeUs = lp_var_t<uint64_t>(sid.objectId, PoolIds::TIME_SOLUTION_SET, this);
// Calibrated quaternion (takes into account the mounting quaternion), typically same as
// track q values
lp_var_t<float> caliQw = lp_var_t<float>(sid.objectId, PoolIds::CALI_QW, this);
@ -695,7 +712,7 @@ class SolutionSet : public StaticLocalDataSet<SOLUTION_SET_ENTRIES> {
void printSet() {
PoolReadGuard rg(this);
sif::info << "SolutionSet::printSet: Ticks: " << this->ticks << std::endl;
sif::info << "SolutionSet::printSet: Time: " << this->time << std::endl;
sif::info << "SolutionSet::printSet: Time: " << this->timeUs << std::endl;
sif::info << "SolutionSet::printSet: Calibrated quaternion Qw: " << this->caliQw << std::endl;
sif::info << "SolutionSet::printSet: Calibrated quaternion Qx: " << this->caliQx << std::endl;
sif::info << "SolutionSet::printSet: Calibrated quaternion Qy: " << this->caliQy << std::endl;

View File

@ -916,3 +916,45 @@ ReturnValue_t DebugCamera::createCommand(uint8_t* buffer) {
adduint32(param, buffer + offset);
return returnvalue::OK;
}
AutoThreshold::AutoThreshold() : ArcsecJsonParamBase(arcseckeys::AUTO_THRESHOLD) {}
size_t AutoThreshold::getSize() { return COMMAND_SIZE; }
ReturnValue_t AutoThreshold::createCommand(uint8_t* buffer) {
ReturnValue_t result = returnvalue::OK;
uint8_t offset = 0;
std::string param;
addSetParamHeader(buffer, startracker::ID::AUTO_THRESHOLD);
offset = 2;
result = getParam(arcseckeys::AT_MODE, param);
if (result != returnvalue::OK) {
return result;
}
adduint8(param, buffer + offset);
offset += 1;
result = getParam(arcseckeys::AT_DESIRED_BLOB_COUNTS, param);
if (result != returnvalue::OK) {
return result;
}
adduint8(param, buffer + offset);
offset += 1;
result = getParam(arcseckeys::AT_MIN_THRESHOLD, param);
if (result != returnvalue::OK) {
return result;
}
adduint16(param, buffer + offset);
offset += 2;
result = getParam(arcseckeys::AT_MAX_THRESHOLD, param);
if (result != returnvalue::OK) {
return result;
}
adduint16(param, buffer + offset);
offset += 2;
result = getParam(arcseckeys::AT_THRESHOLD_KP, param);
if (result != returnvalue::OK) {
return result;
}
addfloat(param, buffer + offset);
return returnvalue::OK;
}

View File

@ -222,6 +222,22 @@ class LogSubscription : public ArcsecJsonParamBase {
ReturnValue_t createCommand(uint8_t* buffer) override;
};
/**
* @brief Generates command to set log subscription parameters.
*
*/
class AutoThreshold : public ArcsecJsonParamBase {
public:
AutoThreshold();
size_t getSize();
private:
static const size_t COMMAND_SIZE = 12;
ReturnValue_t createCommand(uint8_t* buffer) override;
};
/**
* @brief Generates command to set debug camera parameters
*

View File

@ -7,6 +7,7 @@
AcsController::AcsController(object_id_t objectId, bool enableHkSets)
: ExtendedControllerBase(objectId),
enableHkSets(enableHkSets),
fusedRotationEstimation(&acsParameters),
guidance(&acsParameters),
safeCtrl(&acsParameters),
ptgCtrl(&acsParameters),
@ -20,7 +21,8 @@ AcsController::AcsController(object_id_t objectId, bool enableHkSets)
gpsDataProcessed(this),
mekfData(this),
ctrlValData(this),
actuatorCmdData(this) {}
actuatorCmdData(this),
fusedRotRateData(this) {}
ReturnValue_t AcsController::initialize() {
ReturnValue_t result = parameterHelper.initialize();
@ -146,6 +148,8 @@ void AcsController::performSafe() {
sensorProcessing.process(now, &sensorValues, &mgmDataProcessed, &susDataProcessed,
&gyrDataProcessed, &gpsDataProcessed, &acsParameters);
fusedRotationEstimation.estimateFusedRotationRateSafe(&susDataProcessed, &mgmDataProcessed,
&gyrDataProcessed, &fusedRotRateData);
ReturnValue_t result = navigation.useMekf(&sensorValues, &gyrDataProcessed, &mgmDataProcessed,
&susDataProcessed, &mekfData, &acsParameters);
if (result != MultiplicativeKalmanFilter::MEKF_RUNNING &&
@ -172,25 +176,42 @@ void AcsController::performSafe() {
acs::SafeModeStrategy safeCtrlStrat = safeCtrl.safeCtrlStrategy(
mgmDataProcessed.mgmVecTot.isValid(), not mekfInvalidFlag,
gyrDataProcessed.gyrVecTot.isValid(), susDataProcessed.susVecTot.isValid(),
fusedRotRateData.rotRateOrthogonal.isValid(), fusedRotRateData.rotRateTotal.isValid(),
acsParameters.safeModeControllerParameters.useMekf,
acsParameters.safeModeControllerParameters.useGyr,
acsParameters.safeModeControllerParameters.dampingDuringEclipse);
switch (safeCtrlStrat) {
case (acs::SafeModeStrategy::SAFECTRL_ACTIVE_MEKF):
case (acs::SafeModeStrategy::SAFECTRL_MEKF):
safeCtrl.safeMekf(mgmDataProcessed.mgmVecTot.value, mekfData.satRotRateMekf.value,
susDataProcessed.sunIjkModel.value, mekfData.quatMekf.value, sunTargetDir,
magMomMtq, errAng);
safeCtrlFailureFlag = false;
safeCtrlFailureCounter = 0;
break;
case (acs::SafeModeStrategy::SAFECTRL_WITHOUT_MEKF):
safeCtrl.safeNonMekf(mgmDataProcessed.mgmVecTot.value, gyrDataProcessed.gyrVecTot.value,
susDataProcessed.susVecTot.value, sunTargetDir, magMomMtq, errAng);
case (acs::SafeModeStrategy::SAFECTRL_GYR):
safeCtrl.safeGyr(mgmDataProcessed.mgmVecTot.value, gyrDataProcessed.gyrVecTot.value,
susDataProcessed.susVecTot.value, sunTargetDir, magMomMtq, errAng);
safeCtrlFailureFlag = false;
safeCtrlFailureCounter = 0;
break;
case (acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING):
safeCtrl.safeRateDamping(mgmDataProcessed.mgmVecTot.value, gyrDataProcessed.gyrVecTot.value,
sunTargetDir, magMomMtq, errAng);
case (acs::SafeModeStrategy::SAFECTRL_SUSMGM):
safeCtrl.safeSusMgm(mgmDataProcessed.mgmVecTot.value, fusedRotRateData.rotRateParallel.value,
fusedRotRateData.rotRateOrthogonal.value,
susDataProcessed.susVecTot.value, sunTargetDir, magMomMtq, errAng);
safeCtrlFailureFlag = false;
safeCtrlFailureCounter = 0;
break;
case (acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING_GYR):
safeCtrl.safeRateDampingGyr(mgmDataProcessed.mgmVecTot.value,
gyrDataProcessed.gyrVecTot.value, sunTargetDir, magMomMtq,
errAng);
safeCtrlFailureFlag = false;
safeCtrlFailureCounter = 0;
break;
case (acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING_SUSMGM):
safeCtrl.safeRateDampingSusMgm(mgmDataProcessed.mgmVecTot.value,
fusedRotRateData.rotRateTotal.value, sunTargetDir, magMomMtq,
errAng);
safeCtrlFailureFlag = false;
safeCtrlFailureCounter = 0;
break;
@ -214,12 +235,20 @@ void AcsController::performSafe() {
acsParameters.magnetorquerParameter.dipoleMax, magMomMtq, cmdDipoleMtqs);
// detumble check and switch
if (mekfData.satRotRateMekf.isValid() && acsParameters.safeModeControllerParameters.useMekf &&
VectorOperations<double>::norm(mekfData.satRotRateMekf.value, 3) >
acsParameters.detumbleParameter.omegaDetumbleStart) {
detumbleCounter++;
} else if (gyrDataProcessed.gyrVecTot.isValid() &&
VectorOperations<double>::norm(gyrDataProcessed.gyrVecTot.value, 3) >
if (acsParameters.safeModeControllerParameters.useMekf) {
if (mekfData.satRotRateMekf.isValid() and
VectorOperations<double>::norm(mekfData.satRotRateMekf.value, 3) >
acsParameters.detumbleParameter.omegaDetumbleStart) {
detumbleCounter++;
}
} else if (acsParameters.safeModeControllerParameters.useGyr) {
if (gyrDataProcessed.gyrVecTot.isValid() and
VectorOperations<double>::norm(gyrDataProcessed.gyrVecTot.value, 3) >
acsParameters.detumbleParameter.omegaDetumbleStart) {
detumbleCounter++;
}
} else if (fusedRotRateData.rotRateTotal.isValid() and
VectorOperations<double>::norm(fusedRotRateData.rotRateTotal.value, 3) >
acsParameters.detumbleParameter.omegaDetumbleStart) {
detumbleCounter++;
} else if (detumbleCounter > 0) {
@ -289,17 +318,26 @@ void AcsController::performDetumble() {
actuatorCmd.cmdDipoleMtq(*acsParameters.magnetorquerParameter.inverseAlignment,
acsParameters.magnetorquerParameter.dipoleMax, magMomMtq, cmdDipoleMtqs);
if (mekfData.satRotRateMekf.isValid() &&
VectorOperations<double>::norm(mekfData.satRotRateMekf.value, 3) <
acsParameters.detumbleParameter.omegaDetumbleEnd) {
detumbleCounter++;
} else if (gyrDataProcessed.gyrVecTot.isValid() &&
VectorOperations<double>::norm(gyrDataProcessed.gyrVecTot.value, 3) <
acsParameters.detumbleParameter.omegaDetumbleEnd) {
if (acsParameters.safeModeControllerParameters.useMekf) {
if (mekfData.satRotRateMekf.isValid() and
VectorOperations<double>::norm(mekfData.satRotRateMekf.value, 3) <
acsParameters.detumbleParameter.omegaDetumbleStart) {
detumbleCounter++;
}
} else if (acsParameters.safeModeControllerParameters.useGyr) {
if (gyrDataProcessed.gyrVecTot.isValid() and
VectorOperations<double>::norm(gyrDataProcessed.gyrVecTot.value, 3) <
acsParameters.detumbleParameter.omegaDetumbleStart) {
detumbleCounter++;
}
} else if (fusedRotRateData.rotRateTotal.isValid() and
VectorOperations<double>::norm(fusedRotRateData.rotRateTotal.value, 3) <
acsParameters.detumbleParameter.omegaDetumbleStart) {
detumbleCounter++;
} else if (detumbleCounter > 0) {
detumbleCounter -= 1;
}
if (detumbleCounter > acsParameters.detumbleParameter.detumblecounter) {
detumbleCounter = 0;
// Triggers safe mode transition in subsystem
@ -707,6 +745,11 @@ ReturnValue_t AcsController::initializeLocalDataPool(localpool::DataPool &localD
localDataPoolMap.emplace(acsctrl::PoolIds::RW_TARGET_SPEED, &rwTargetSpeed);
localDataPoolMap.emplace(acsctrl::PoolIds::MTQ_TARGET_DIPOLE, &mtqTargetDipole);
poolManager.subscribeForRegularPeriodicPacket({actuatorCmdData.getSid(), enableHkSets, 10.0});
// Fused Rot Rate
localDataPoolMap.emplace(acsctrl::PoolIds::ROT_RATE_ORTHOGONAL, &rotRateOrthogonal);
localDataPoolMap.emplace(acsctrl::PoolIds::ROT_RATE_PARALLEL, &rotRateParallel);
localDataPoolMap.emplace(acsctrl::PoolIds::ROT_RATE_TOTAL, &rotRateTotal);
poolManager.subscribeForRegularPeriodicPacket({fusedRotRateData.getSid(), enableHkSets, 10.0});
return returnvalue::OK;
}
@ -732,6 +775,8 @@ LocalPoolDataSetBase *AcsController::getDataSetHandle(sid_t sid) {
return &ctrlValData;
case acsctrl::ACTUATOR_CMD_DATA:
return &actuatorCmdData;
case acsctrl::FUSED_ROTATION_RATE_DATA:
return &fusedRotRateData;
default:
return nullptr;
}

View File

@ -13,6 +13,7 @@
#include <mission/acs/rwHelpers.h>
#include <mission/acs/susMax1227Helpers.h>
#include <mission/controller/acs/ActuatorCmd.h>
#include <mission/controller/acs/FusedRotationEstimation.h>
#include <mission/controller/acs/Guidance.h>
#include <mission/controller/acs/MultiplicativeKalmanFilter.h>
#include <mission/controller/acs/Navigation.h>
@ -49,6 +50,7 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
AcsParameters acsParameters;
SensorProcessing sensorProcessing;
FusedRotationEstimation fusedRotationEstimation;
Navigation navigation;
ActuatorCmd actuatorCmd;
Guidance guidance;
@ -226,6 +228,12 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
PoolEntry<int32_t> rwTargetSpeed = PoolEntry<int32_t>(4);
PoolEntry<int16_t> mtqTargetDipole = PoolEntry<int16_t>(3);
// Fused Rot Rate
acsctrl::FusedRotRateData fusedRotRateData;
PoolEntry<double> rotRateOrthogonal = PoolEntry<double>(3);
PoolEntry<double> rotRateParallel = PoolEntry<double>(3);
PoolEntry<double> rotRateTotal = PoolEntry<double>(3);
// Initial delay to make sure all pool variables have been initialized their owners
Countdown initialCountdown = Countdown(INIT_DELAY);
};

View File

@ -105,6 +105,9 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
parameterWrapper->setVector(mgmHandlingParameters.mgm4variance);
break;
case 0x12:
parameterWrapper->set(mgmHandlingParameters.mgmVectorFilterWeight);
break;
case 0x13:
parameterWrapper->set(mgmHandlingParameters.mgmDerivativeFilterWeight);
break;
default:
@ -224,6 +227,12 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
case 0x24:
parameterWrapper->set(susHandlingParameters.susBrightnessThreshold);
break;
case 0x25:
parameterWrapper->set(susHandlingParameters.susVectorFilterWeight);
break;
case 0x26:
parameterWrapper->set(susHandlingParameters.susRateFilterWeight);
break;
default:
return INVALID_IDENTIFIER_ID;
}
@ -339,26 +348,41 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
parameterWrapper->set(safeModeControllerParameters.k_parallelMekf);
break;
case 0x3:
parameterWrapper->set(safeModeControllerParameters.k_orthoNonMekf);
parameterWrapper->set(safeModeControllerParameters.k_orthoGyr);
break;
case 0x4:
parameterWrapper->set(safeModeControllerParameters.k_alignNonMekf);
parameterWrapper->set(safeModeControllerParameters.k_alignGyr);
break;
case 0x5:
parameterWrapper->set(safeModeControllerParameters.k_parallelNonMekf);
parameterWrapper->set(safeModeControllerParameters.k_parallelGyr);
break;
case 0x6:
parameterWrapper->setVector(safeModeControllerParameters.sunTargetDirLeop);
parameterWrapper->set(safeModeControllerParameters.k_orthoSusMgm);
break;
case 0x7:
parameterWrapper->setVector(safeModeControllerParameters.sunTargetDir);
parameterWrapper->set(safeModeControllerParameters.k_alignSusMgm);
break;
case 0x8:
parameterWrapper->set(safeModeControllerParameters.useMekf);
parameterWrapper->set(safeModeControllerParameters.k_parallelSusMgm);
break;
case 0x9:
parameterWrapper->setVector(safeModeControllerParameters.sunTargetDirLeop);
break;
case 0xA:
parameterWrapper->setVector(safeModeControllerParameters.sunTargetDir);
break;
case 0xB:
parameterWrapper->set(safeModeControllerParameters.useMekf);
break;
case 0xC:
parameterWrapper->set(safeModeControllerParameters.useGyr);
break;
case 0xD:
parameterWrapper->set(safeModeControllerParameters.dampingDuringEclipse);
break;
case 0xE:
parameterWrapper->set(safeModeControllerParameters.sineLimitSunRotRate);
break;
default:
return INVALID_IDENTIFIER_ID;
}

View File

@ -77,7 +77,8 @@ class AcsParameters : public HasParametersIF {
float mgm02variance[3] = {pow(3.2e-7, 2), pow(3.2e-7, 2), pow(4.1e-7, 2)};
float mgm13variance[3] = {pow(1.5e-8, 2), pow(1.5e-8, 2), pow(1.5e-8, 2)};
float mgm4variance[3] = {pow(1.7e-6, 2), pow(1.7e-6, 2), pow(1.7e-6, 2)};
float mgmDerivativeFilterWeight = 0.5;
float mgmVectorFilterWeight = 0.85;
float mgmDerivativeFilterWeight = 0.85;
} mgmHandlingParameters;
struct SusHandlingParameters {
@ -767,6 +768,8 @@ class AcsParameters : public HasParametersIF {
0.167666815691513, 0.163137400730063, -0.000609874123906977, -0.00205336098697513,
-0.000889232196185857, -0.00168429567131815}};
float susBrightnessThreshold = 0.7;
float susVectorFilterWeight = .85;
float susRateFilterWeight = .85;
} susHandlingParameters;
struct GyrHandlingParameters {
@ -825,15 +828,22 @@ class AcsParameters : public HasParametersIF {
double k_alignMekf = 4.0e-5;
double k_parallelMekf = 3.75e-4;
double k_orthoNonMekf = 4.4e-3;
double k_alignNonMekf = 4.0e-5;
double k_parallelNonMekf = 3.75e-4;
double k_orthoGyr = 4.4e-3;
double k_alignGyr = 4.0e-5;
double k_parallelGyr = 3.75e-4;
double k_orthoSusMgm = 1.1e-2;
double k_alignSusMgm = 2.0e-5;
double k_parallelSusMgm = 4.4e-4;
double sunTargetDirLeop[3] = {0, sqrt(.5), sqrt(.5)};
double sunTargetDir[3] = {0, 0, 1};
uint8_t useMekf = false;
uint8_t useGyr = true;
uint8_t dampingDuringEclipse = true;
float sineLimitSunRotRate = 0.24;
} safeModeControllerParameters;
struct PointingLawParameters {

View File

@ -2,6 +2,7 @@ target_sources(
${LIB_EIVE_MISSION}
PRIVATE AcsParameters.cpp
ActuatorCmd.cpp
FusedRotationEstimation.cpp
Guidance.cpp
Igrf13Model.cpp
MultiplicativeKalmanFilter.cpp

View File

@ -0,0 +1,103 @@
#include "FusedRotationEstimation.h"
FusedRotationEstimation::FusedRotationEstimation(AcsParameters *acsParameters_) {
acsParameters = acsParameters_;
}
void FusedRotationEstimation::estimateFusedRotationRateSafe(
acsctrl::SusDataProcessed *susDataProcessed, acsctrl::MgmDataProcessed *mgmDataProcessed,
acsctrl::GyrDataProcessed *gyrDataProcessed, acsctrl::FusedRotRateData *fusedRotRateData) {
if ((not mgmDataProcessed->mgmVecTot.isValid() and not susDataProcessed->susVecTot.isValid() and
not fusedRotRateData->rotRateTotal.isValid()) or
(not susDataProcessed->susVecTotDerivative.isValid() and
not mgmDataProcessed->mgmVecTotDerivative.isValid())) {
{
PoolReadGuard pg(fusedRotRateData);
std::memcpy(fusedRotRateData->rotRateOrthogonal.value, ZERO_VEC, 3 * sizeof(double));
std::memcpy(fusedRotRateData->rotRateParallel.value, ZERO_VEC, 3 * sizeof(double));
std::memcpy(fusedRotRateData->rotRateTotal.value, ZERO_VEC, 3 * sizeof(double));
fusedRotRateData->setValidity(false, true);
}
return;
}
if (not susDataProcessed->susVecTot.isValid()) {
estimateFusedRotationRateEclipse(gyrDataProcessed, fusedRotRateData);
return;
}
// calculate rotation around the sun
double magSunCross[3] = {0, 0, 0};
VectorOperations<double>::cross(mgmDataProcessed->mgmVecTot.value,
susDataProcessed->susVecTot.value, magSunCross);
double magSunCrossNorm = VectorOperations<double>::norm(magSunCross, 3);
double magNorm = VectorOperations<double>::norm(mgmDataProcessed->mgmVecTot.value, 3);
double fusedRotRateParallel[3] = {0, 0, 0};
if (magSunCrossNorm >
(acsParameters->safeModeControllerParameters.sineLimitSunRotRate * magNorm)) {
double omegaParallel =
VectorOperations<double>::dot(mgmDataProcessed->mgmVecTotDerivative.value, magSunCross) *
pow(magSunCrossNorm, -2);
VectorOperations<double>::mulScalar(susDataProcessed->susVecTot.value, omegaParallel,
fusedRotRateParallel, 3);
} else {
estimateFusedRotationRateEclipse(gyrDataProcessed, fusedRotRateData);
return;
}
// calculate rotation orthogonal to the sun
double fusedRotRateOrthogonal[3] = {0, 0, 0};
VectorOperations<double>::cross(susDataProcessed->susVecTotDerivative.value,
susDataProcessed->susVecTot.value, fusedRotRateOrthogonal);
VectorOperations<double>::mulScalar(
fusedRotRateOrthogonal,
pow(VectorOperations<double>::norm(susDataProcessed->susVecTot.value, 3), -2),
fusedRotRateOrthogonal, 3);
// calculate total rotation rate
double fusedRotRateTotal[3] = {0, 0, 0};
VectorOperations<double>::add(fusedRotRateParallel, fusedRotRateOrthogonal, fusedRotRateTotal);
// store for calculation of angular acceleration
if (gyrDataProcessed->gyrVecTot.isValid()) {
std::memcpy(rotRateOldB, gyrDataProcessed->gyrVecTot.value, 3 * sizeof(double));
}
{
PoolReadGuard pg(fusedRotRateData);
std::memcpy(fusedRotRateData->rotRateOrthogonal.value, fusedRotRateOrthogonal,
3 * sizeof(double));
std::memcpy(fusedRotRateData->rotRateParallel.value, fusedRotRateParallel, 3 * sizeof(double));
std::memcpy(fusedRotRateData->rotRateTotal.value, fusedRotRateTotal, 3 * sizeof(double));
fusedRotRateData->setValidity(true, true);
}
}
void FusedRotationEstimation::estimateFusedRotationRateEclipse(
acsctrl::GyrDataProcessed *gyrDataProcessed, acsctrl::FusedRotRateData *fusedRotRateData) {
if (not gyrDataProcessed->gyrVecTot.isValid() or
VectorOperations<double>::norm(fusedRotRateData->rotRateTotal.value, 3) == 0) {
{
PoolReadGuard pg(fusedRotRateData);
std::memcpy(fusedRotRateData->rotRateOrthogonal.value, ZERO_VEC, 3 * sizeof(double));
std::memcpy(fusedRotRateData->rotRateParallel.value, ZERO_VEC, 3 * sizeof(double));
std::memcpy(fusedRotRateData->rotRateTotal.value, ZERO_VEC, 3 * sizeof(double));
fusedRotRateData->setValidity(false, true);
}
return;
}
double angAccelB[3] = {0, 0, 0};
VectorOperations<double>::subtract(gyrDataProcessed->gyrVecTot.value, rotRateOldB, angAccelB, 3);
double fusedRotRateTotal[3] = {0, 0, 0};
VectorOperations<double>::add(fusedRotRateData->rotRateTotal.value, angAccelB, fusedRotRateTotal,
3);
{
PoolReadGuard pg(fusedRotRateData);
std::memcpy(fusedRotRateData->rotRateOrthogonal.value, ZERO_VEC, 3 * sizeof(double));
fusedRotRateData->rotRateOrthogonal.setValid(false);
std::memcpy(fusedRotRateData->rotRateParallel.value, ZERO_VEC, 3 * sizeof(double));
fusedRotRateData->rotRateParallel.setValid(false);
std::memcpy(fusedRotRateData->rotRateTotal.value, fusedRotRateTotal, 3 * sizeof(double));
fusedRotRateData->rotRateTotal.setValid(true);
}
}

View File

@ -0,0 +1,29 @@
#ifndef MISSION_CONTROLLER_ACS_FUSEDROTATIONESTIMATION_H_
#define MISSION_CONTROLLER_ACS_FUSEDROTATIONESTIMATION_H_
#include <fsfw/datapool/PoolReadGuard.h>
#include <fsfw/globalfunctions/math/VectorOperations.h>
#include <mission/controller/acs/AcsParameters.h>
#include <mission/controller/controllerdefinitions/AcsCtrlDefinitions.h>
class FusedRotationEstimation {
public:
FusedRotationEstimation(AcsParameters *acsParameters_);
void estimateFusedRotationRateSafe(acsctrl::SusDataProcessed *susDataProcessed,
acsctrl::MgmDataProcessed *mgmDataProcessed,
acsctrl::GyrDataProcessed *gyrDataProcessed,
acsctrl::FusedRotRateData *fusedRotRateData);
protected:
private:
static constexpr double ZERO_VEC[3] = {0, 0, 0};
AcsParameters *acsParameters;
double rotRateOldB[3] = {0, 0, 0};
void estimateFusedRotationRateEclipse(acsctrl::GyrDataProcessed *gyrDataProcessed,
acsctrl::FusedRotRateData *fusedRotRateData);
};
#endif /* MISSION_CONTROLLER_ACS_FUSEDROTATIONESTIMATION_H_ */

View File

@ -132,6 +132,10 @@ void SensorProcessing::processMgm(const float *mgm0Value, bool mgm0valid, const
for (uint8_t i = 0; i < 3; i++) {
mgmVecTot[i] = sensorFusionNumerator[i] / sensorFusionDenominator[i];
}
if (VectorOperations<double>::norm(mgmVecTot, 3) != 0 and mgmDataProcessed->mgmVecTot.isValid()) {
lowPassFilter(mgmVecTot, mgmDataProcessed->mgmVecTot.value,
mgmParameters->mgmVectorFilterWeight);
}
//-----------------------Mgm Rate Computation ---------------------------------------------------
double mgmVecTotDerivative[3] = {0.0, 0.0, 0.0};
@ -351,6 +355,11 @@ void SensorProcessing::processSus(
double susVecTot[3] = {0.0, 0.0, 0.0};
VectorOperations<double>::normalize(susMeanValue, susVecTot, 3);
if (VectorOperations<double>::norm(susVecTot, 3) != 0 and susDataProcessed->susVecTot.isValid()) {
lowPassFilter(susVecTot, susDataProcessed->susVecTot.value,
susParameters->susVectorFilterWeight);
}
/* -------- Sun Derivatiative --------------------- */
double susVecTotDerivative[3] = {0.0, 0.0, 0.0};
@ -363,6 +372,11 @@ void SensorProcessing::processSus(
susVecTotDerivativeValid = true;
}
}
if (VectorOperations<double>::norm(susVecTotDerivative, 3) != 0 and
susDataProcessed->susVecTotDerivative.isValid()) {
lowPassFilter(susVecTotDerivative, susDataProcessed->susVecTotDerivative.value,
susParameters->susRateFilterWeight);
}
timeOfSavedSusDirEst = timeOfSusMeasurement;
{
PoolReadGuard pg(susDataProcessed);

View File

@ -9,20 +9,36 @@ SafeCtrl::SafeCtrl(AcsParameters *acsParameters_) { acsParameters = acsParameter
SafeCtrl::~SafeCtrl() {}
acs::SafeModeStrategy SafeCtrl::safeCtrlStrategy(const bool magFieldValid, const bool mekfValid,
const bool satRotRateValid, const bool sunDirValid,
const uint8_t mekfEnabled,
const uint8_t dampingEnabled) {
acs::SafeModeStrategy SafeCtrl::safeCtrlStrategy(
const bool magFieldValid, const bool mekfValid, const bool satRotRateValid,
const bool sunDirValid, const bool fusedRateSplitValid, const bool fusedRateTotalValid,
const uint8_t mekfEnabled, const uint8_t gyrEnabled, const uint8_t dampingEnabled) {
if (not magFieldValid) {
return acs::SafeModeStrategy::SAFECTRL_NO_MAG_FIELD_FOR_CONTROL;
} else if (mekfEnabled and mekfValid) {
return acs::SafeModeStrategy::SAFECTRL_ACTIVE_MEKF;
} else if (satRotRateValid and sunDirValid) {
return acs::SafeModeStrategy::SAFECTRL_WITHOUT_MEKF;
} else if (dampingEnabled and satRotRateValid and not sunDirValid) {
return acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING;
} else if (not dampingEnabled and satRotRateValid and not sunDirValid) {
return acs::SafeModeStrategy::SAFECTRL_ECLIPSE_IDELING;
return acs::SafeModeStrategy::SAFECTRL_MEKF;
} else if (sunDirValid) {
if (gyrEnabled and satRotRateValid) {
return acs::SafeModeStrategy::SAFECTRL_GYR;
} else if (not gyrEnabled and fusedRateSplitValid) {
return acs::SafeModeStrategy::SAFECTRL_SUSMGM;
} else {
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
}
} else if (not sunDirValid) {
if (dampingEnabled) {
if (gyrEnabled and satRotRateValid) {
return acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING_GYR;
} else if (not gyrEnabled and satRotRateValid and fusedRateTotalValid) {
return acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING_SUSMGM;
} else {
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
}
} else if (not dampingEnabled and satRotRateValid) {
return acs::SafeModeStrategy::SAFECTRL_ECLIPSE_IDELING;
} else {
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
}
} else {
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
}
@ -43,8 +59,7 @@ void SafeCtrl::safeMekf(const double *magFieldB, const double *satRotRateB,
errorAngle = acos(dotSun);
splitRotationalRate(satRotRateB, sunDirB);
calculateRotationalRateTorque(sunDirB, sunDirRefB, errorAngle,
acsParameters->safeModeControllerParameters.k_parallelMekf,
calculateRotationalRateTorque(acsParameters->safeModeControllerParameters.k_parallelMekf,
acsParameters->safeModeControllerParameters.k_orthoMekf);
calculateAngleErrorTorque(sunDirB, sunDirRefB,
acsParameters->safeModeControllerParameters.k_alignMekf);
@ -57,9 +72,8 @@ void SafeCtrl::safeMekf(const double *magFieldB, const double *satRotRateB,
calculateMagneticMoment(magMomB);
}
void SafeCtrl::safeNonMekf(const double *magFieldB, const double *satRotRateB,
const double *sunDirB, const double *sunDirRefB, double *magMomB,
double &errorAngle) {
void SafeCtrl::safeGyr(const double *magFieldB, const double *satRotRateB, const double *sunDirB,
const double *sunDirRefB, double *magMomB, double &errorAngle) {
// convert magFieldB from uT to T
VectorOperations<double>::mulScalar(magFieldB, 1e-6, magFieldBT, 3);
@ -68,11 +82,10 @@ void SafeCtrl::safeNonMekf(const double *magFieldB, const double *satRotRateB,
errorAngle = acos(dotSun);
splitRotationalRate(satRotRateB, sunDirB);
calculateRotationalRateTorque(sunDirB, sunDirRefB, errorAngle,
acsParameters->safeModeControllerParameters.k_parallelNonMekf,
acsParameters->safeModeControllerParameters.k_orthoNonMekf);
calculateRotationalRateTorque(acsParameters->safeModeControllerParameters.k_parallelGyr,
acsParameters->safeModeControllerParameters.k_orthoGyr);
calculateAngleErrorTorque(sunDirB, sunDirRefB,
acsParameters->safeModeControllerParameters.k_alignNonMekf);
acsParameters->safeModeControllerParameters.k_alignGyr);
// sum of all torques
for (uint8_t i = 0; i < 3; i++) {
@ -82,8 +95,33 @@ void SafeCtrl::safeNonMekf(const double *magFieldB, const double *satRotRateB,
calculateMagneticMoment(magMomB);
}
void SafeCtrl::safeRateDamping(const double *magFieldB, const double *satRotRateB,
const double *sunDirRefB, double *magMomB, double &errorAngle) {
void SafeCtrl::safeSusMgm(const double *magFieldB, const double *rotRateParallelB,
const double *rotRateOrthogonalB, const double *sunDirB,
const double *sunDirRefB, double *magMomB, double &errorAngle) {
// convert magFieldB from uT to T
VectorOperations<double>::mulScalar(magFieldB, 1e-6, magFieldBT, 3);
// calculate error angle between sunDirRef and sunDir
double dotSun = VectorOperations<double>::dot(sunDirRefB, sunDirB);
errorAngle = acos(dotSun);
std::memcpy(satRotRateParallelB, rotRateParallelB, sizeof(satRotRateParallelB));
std::memcpy(satRotRateOrthogonalB, rotRateOrthogonalB, sizeof(satRotRateOrthogonalB));
calculateRotationalRateTorque(acsParameters->safeModeControllerParameters.k_parallelSusMgm,
acsParameters->safeModeControllerParameters.k_orthoSusMgm);
calculateAngleErrorTorque(sunDirB, sunDirRefB,
acsParameters->safeModeControllerParameters.k_alignSusMgm);
// sum of all torques
for (uint8_t i = 0; i < 3; i++) {
cmdTorque[i] = cmdAlign[i] + cmdOrtho[i] + cmdParallel[i];
}
calculateMagneticMoment(magMomB);
}
void SafeCtrl::safeRateDampingGyr(const double *magFieldB, const double *satRotRateB,
const double *sunDirRefB, double *magMomB, double &errorAngle) {
// convert magFieldB from uT to T
VectorOperations<double>::mulScalar(magFieldB, 1e-6, magFieldBT, 3);
@ -91,9 +129,28 @@ void SafeCtrl::safeRateDamping(const double *magFieldB, const double *satRotRate
errorAngle = NAN;
splitRotationalRate(satRotRateB, sunDirRefB);
calculateRotationalRateTorque(sunDirRefB, sunDirRefB, errorAngle,
acsParameters->safeModeControllerParameters.k_parallelNonMekf,
acsParameters->safeModeControllerParameters.k_orthoNonMekf);
calculateRotationalRateTorque(acsParameters->safeModeControllerParameters.k_parallelGyr,
acsParameters->safeModeControllerParameters.k_orthoGyr);
// sum of all torques
VectorOperations<double>::add(cmdParallel, cmdOrtho, cmdTorque, 3);
// calculate magnetic moment to command
calculateMagneticMoment(magMomB);
}
void SafeCtrl::safeRateDampingSusMgm(const double *magFieldB, const double *satRotRateB,
const double *sunDirRefB, double *magMomB,
double &errorAngle) {
// convert magFieldB from uT to T
VectorOperations<double>::mulScalar(magFieldB, 1e-6, magFieldBT, 3);
// no error angle available for eclipse
errorAngle = NAN;
splitRotationalRate(satRotRateB, sunDirRefB);
calculateRotationalRateTorque(acsParameters->safeModeControllerParameters.k_parallelSusMgm,
acsParameters->safeModeControllerParameters.k_orthoSusMgm);
// sum of all torques
VectorOperations<double>::add(cmdParallel, cmdOrtho, cmdTorque, 3);
@ -110,9 +167,7 @@ void SafeCtrl::splitRotationalRate(const double *satRotRateB, const double *sunD
VectorOperations<double>::subtract(satRotRateB, satRotRateParallelB, satRotRateOrthogonalB, 3);
}
void SafeCtrl::calculateRotationalRateTorque(const double *sunDirB, const double *sunDirRefB,
double &errorAngle, const double gainParallel,
const double gainOrtho) {
void SafeCtrl::calculateRotationalRateTorque(const double gainParallel, const double gainOrtho) {
// calculate torque for parallel rotational rate
VectorOperations<double>::mulScalar(satRotRateParallelB, -gainParallel, cmdParallel, 3);

View File

@ -14,23 +14,34 @@ class SafeCtrl {
acs::SafeModeStrategy safeCtrlStrategy(const bool magFieldValid, const bool mekfValid,
const bool satRotRateValid, const bool sunDirValid,
const uint8_t mekfEnabled, const uint8_t dampingEnabled);
const bool fusedRateSplitValid,
const bool fusedRateTotalValid, const uint8_t mekfEnabled,
const uint8_t gyrEnabled, const uint8_t dampingEnabled);
void safeMekf(const double *magFieldB, const double *satRotRateB, const double *sunDirModelI,
const double *quatBI, const double *sunDirRefB, double *magMomB,
double &errorAngle);
void safeNonMekf(const double *magFieldB, const double *satRotRateB, const double *sunDirB,
const double *sunDirRefB, double *magMomB, double &errorAngle);
void safeGyr(const double *magFieldB, const double *satRotRateB, const double *sunDirB,
const double *sunDirRefB, double *magMomB, double &errorAngle);
void safeRateDamping(const double *magFieldB, const double *satRotRateB, const double *sunDirRefB,
double *magMomB, double &errorAngle);
void safeSusMgm(const double *magFieldB, const double *rotRateParallelB,
const double *rotRateOrthogonalB, const double *sunDirB, const double *sunDirRefB,
double *magMomB, double &errorAngle);
void safeRateDampingGyr(const double *magFieldB, const double *satRotRateB,
const double *sunDirRefB, double *magMomB, double &errorAngle);
void safeRateDampingSusMgm(const double *magFieldB, const double *satRotRateB,
const double *sunDirRefB, double *magMomB, double &errorAngle);
void splitRotationalRate(const double *satRotRateB, const double *sunDirB);
void calculateRotationalRateTorque(const double *sunDirB, const double *sunDirRefB,
double &errorAngle, const double gainParallel,
const double gainOrtho);
void calculateRotationalRates(const double *magFieldB, const double *magRateB,
const double *sunDirB, const double *sunRateB,
double *fusedRotRate);
void calculateRotationalRateTorque(const double gainParallel, const double gainOrtho);
void calculateAngleErrorTorque(const double *sunDirB, const double *sunDirRefB,
const double gainAlign);

View File

@ -18,7 +18,8 @@ enum SetIds : uint32_t {
GPS_PROCESSED_DATA,
MEKF_DATA,
CTRL_VAL_DATA,
ACTUATOR_CMD_DATA
ACTUATOR_CMD_DATA,
FUSED_ROTATION_RATE_DATA,
};
enum PoolIds : lp_id_t {
@ -103,6 +104,10 @@ enum PoolIds : lp_id_t {
RW_TARGET_TORQUE,
RW_TARGET_SPEED,
MTQ_TARGET_DIPOLE,
// Fused Rotation Rate
ROT_RATE_ORTHOGONAL,
ROT_RATE_PARALLEL,
ROT_RATE_TOTAL,
};
static constexpr uint8_t MGM_SET_RAW_ENTRIES = 6;
@ -115,6 +120,7 @@ static constexpr uint8_t GPS_SET_PROCESSED_ENTRIES = 5;
static constexpr uint8_t MEKF_SET_ENTRIES = 3;
static constexpr uint8_t CTRL_VAL_SET_ENTRIES = 5;
static constexpr uint8_t ACT_CMD_SET_ENTRIES = 3;
static constexpr uint8_t FUSED_ROT_RATE_SET_ENTRIES = 3;
/**
* @brief Raw MGM sensor data. Includes the IMTQ sensor data and actuator status.
@ -273,6 +279,19 @@ class ActuatorCmdData : public StaticLocalDataSet<ACT_CMD_SET_ENTRIES> {
private:
};
class FusedRotRateData : public StaticLocalDataSet<FUSED_ROT_RATE_SET_ENTRIES> {
public:
FusedRotRateData(HasLocalDataPoolIF* hkOwner)
: StaticLocalDataSet(hkOwner, FUSED_ROTATION_RATE_DATA) {}
lp_vec_t<double, 3> rotRateOrthogonal =
lp_vec_t<double, 3>(sid.objectId, ROT_RATE_ORTHOGONAL, this);
lp_vec_t<double, 3> rotRateParallel = lp_vec_t<double, 3>(sid.objectId, ROT_RATE_PARALLEL, this);
lp_vec_t<double, 3> rotRateTotal = lp_vec_t<double, 3>(sid.objectId, ROT_RATE_TOTAL, this);
private:
};
} // namespace acsctrl
#endif /* MISSION_CONTROLLER_CONTROLLERDEFINITIONS_ACSCTRLDEFINITIONS_H_ */

View File

@ -1,6 +1,7 @@
#include <OBSWConfig.h>
#include <devices/gpioIds.h>
#include <fsfw/datapool/PoolReadGuard.h>
#include <fsfw/tasks/TaskFactory.h>
#include <mission/payload/RadiationSensorHandler.h>
#include <mission/power/gsDefs.h>
#include <mission/tcs/max1227.h>
@ -15,6 +16,8 @@ RadiationSensorHandler::RadiationSensorHandler(object_id_t objectId, object_id_t
if (comCookie == nullptr) {
sif::error << "RadiationSensorHandler: Invalid com cookie" << std::endl;
}
// Time out immediately so we get an immediate measurement at device startup.
measurementCd.timeOut();
}
RadiationSensorHandler::~RadiationSensorHandler() {}
@ -51,14 +54,17 @@ void RadiationSensorHandler::doShutDown() {
}
ReturnValue_t RadiationSensorHandler::buildNormalDeviceCommand(DeviceCommandId_t *id) {
if (measurementCd.isBusy()) {
return NOTHING_TO_SEND;
}
switch (communicationStep) {
case CommunicationStep::START_CONVERSION: {
*id = RAD_SENSOR::START_CONVERSION;
*id = radSens::START_CONVERSION;
communicationStep = CommunicationStep::READ_CONVERSIONS;
break;
}
case CommunicationStep::READ_CONVERSIONS: {
*id = RAD_SENSOR::READ_CONVERSIONS;
*id = radSens::READ_CONVERSIONS;
communicationStep = CommunicationStep::START_CONVERSION;
break;
}
@ -73,7 +79,7 @@ ReturnValue_t RadiationSensorHandler::buildNormalDeviceCommand(DeviceCommandId_t
ReturnValue_t RadiationSensorHandler::buildTransitionDeviceCommand(DeviceCommandId_t *id) {
if (internalState == InternalState::SETUP) {
*id = RAD_SENSOR::WRITE_SETUP;
*id = radSens::WRITE_SETUP;
} else {
return NOTHING_TO_SEND;
}
@ -84,15 +90,19 @@ ReturnValue_t RadiationSensorHandler::buildCommandFromCommand(DeviceCommandId_t
const uint8_t *commandData,
size_t commandDataLen) {
switch (deviceCommand) {
case (RAD_SENSOR::WRITE_SETUP): {
cmdBuffer[0] = RAD_SENSOR::SETUP_DEFINITION;
case (radSens::WRITE_SETUP): {
cmdBuffer[0] = radSens::SETUP_DEFINITION;
rawPacket = cmdBuffer;
rawPacketLen = 1;
internalState = InternalState::CONFIGURED;
return returnvalue::OK;
}
case (RAD_SENSOR::START_CONVERSION): {
case (radSens::START_CONVERSION): {
ReturnValue_t result = gpioIF->pullHigh(gpioIds::ENABLE_RADFET);
// Test a small delay between pulling the RADFET high and reading the sensor. As long as this
// delay remains small enough, this should not cause scheduling issues. Do not make this
// delay large, this device might be scheduled inside the ACS PST!
TaskFactory::delayTask(5);
if (result != returnvalue::OK) {
#if OBSW_VERBOSE_LEVEL >= 1
sif::warning
@ -102,25 +112,25 @@ ReturnValue_t RadiationSensorHandler::buildCommandFromCommand(DeviceCommandId_t
#endif
}
/* First the fifo will be reset here */
cmdBuffer[0] = RAD_SENSOR::RESET_DEFINITION;
cmdBuffer[1] = RAD_SENSOR::CONVERSION_DEFINITION;
cmdBuffer[0] = radSens::RESET_DEFINITION;
cmdBuffer[1] = radSens::CONVERSION_DEFINITION;
rawPacket = cmdBuffer;
rawPacketLen = 2;
return returnvalue::OK;
}
case (RAD_SENSOR::READ_CONVERSIONS): {
cmdBuffer[0] = RAD_SENSOR::DUMMY_BYTE;
std::memset(cmdBuffer, RAD_SENSOR::DUMMY_BYTE, RAD_SENSOR::READ_SIZE);
case (radSens::READ_CONVERSIONS): {
cmdBuffer[0] = radSens::DUMMY_BYTE;
std::memset(cmdBuffer, radSens::DUMMY_BYTE, radSens::READ_SIZE);
rawPacket = cmdBuffer;
rawPacketLen = RAD_SENSOR::READ_SIZE;
rawPacketLen = radSens::READ_SIZE;
return returnvalue::OK;
}
case RAD_SENSOR::ENABLE_DEBUG_OUTPUT: {
case radSens::ENABLE_DEBUG_OUTPUT: {
printPeriodicData = true;
rawPacketLen = 0;
return returnvalue::OK;
}
case RAD_SENSOR::DISABLE_DEBUG_OUTPUT: {
case radSens::DISABLE_DEBUG_OUTPUT: {
rawPacketLen = 0;
printPeriodicData = false;
return returnvalue::OK;
@ -132,12 +142,11 @@ ReturnValue_t RadiationSensorHandler::buildCommandFromCommand(DeviceCommandId_t
}
void RadiationSensorHandler::fillCommandAndReplyMap() {
this->insertInCommandMap(RAD_SENSOR::WRITE_SETUP);
this->insertInCommandMap(RAD_SENSOR::START_CONVERSION);
this->insertInCommandMap(RAD_SENSOR::ENABLE_DEBUG_OUTPUT);
this->insertInCommandMap(RAD_SENSOR::DISABLE_DEBUG_OUTPUT);
this->insertInCommandAndReplyMap(RAD_SENSOR::READ_CONVERSIONS, 1, &dataset,
RAD_SENSOR::READ_SIZE);
this->insertInCommandMap(radSens::WRITE_SETUP);
this->insertInCommandMap(radSens::START_CONVERSION);
this->insertInCommandMap(radSens::ENABLE_DEBUG_OUTPUT);
this->insertInCommandMap(radSens::DISABLE_DEBUG_OUTPUT);
this->insertInCommandAndReplyMap(radSens::READ_CONVERSIONS, 1, &dataset, radSens::READ_SIZE);
}
ReturnValue_t RadiationSensorHandler::scanForReply(const uint8_t *start, size_t remainingSize,
@ -145,11 +154,11 @@ ReturnValue_t RadiationSensorHandler::scanForReply(const uint8_t *start, size_t
*foundId = this->getPendingCommand();
switch (*foundId) {
case RAD_SENSOR::START_CONVERSION:
case RAD_SENSOR::WRITE_SETUP:
case radSens::START_CONVERSION:
case radSens::WRITE_SETUP:
*foundLen = remainingSize;
return IGNORE_REPLY_DATA;
case RAD_SENSOR::READ_CONVERSIONS: {
case radSens::READ_CONVERSIONS: {
ReturnValue_t result = gpioIF->pullLow(gpioIds::ENABLE_RADFET);
if (result != returnvalue::OK) {
#if OBSW_VERBOSE_LEVEL >= 1
@ -160,8 +169,8 @@ ReturnValue_t RadiationSensorHandler::scanForReply(const uint8_t *start, size_t
}
break;
}
case RAD_SENSOR::ENABLE_DEBUG_OUTPUT:
case RAD_SENSOR::DISABLE_DEBUG_OUTPUT:
case radSens::ENABLE_DEBUG_OUTPUT:
case radSens::DISABLE_DEBUG_OUTPUT:
sif::info << "RadiationSensorHandler::scanForReply: " << remainingSize << std::endl;
break;
default:
@ -176,24 +185,27 @@ ReturnValue_t RadiationSensorHandler::scanForReply(const uint8_t *start, size_t
ReturnValue_t RadiationSensorHandler::interpretDeviceReply(DeviceCommandId_t id,
const uint8_t *packet) {
switch (id) {
case RAD_SENSOR::READ_CONVERSIONS: {
case radSens::READ_CONVERSIONS: {
uint8_t offset = 0;
PoolReadGuard readSet(&dataset);
uint16_t tempRaw = ((packet[offset] & 0x0f) << 8) | packet[offset + 1];
dataset.temperatureCelcius = max1227::getTemperature(tempRaw);
offset += 2;
dataset.ain0 = (*(packet + offset) << 8) | *(packet + offset + 1);
offset += 2;
dataset.ain1 = (*(packet + offset) << 8) | *(packet + offset + 1);
offset += 6;
dataset.ain4 = (*(packet + offset) << 8) | *(packet + offset + 1);
offset += 2;
dataset.ain5 = (*(packet + offset) << 8) | *(packet + offset + 1);
offset += 2;
dataset.ain6 = (*(packet + offset) << 8) | *(packet + offset + 1);
offset += 2;
dataset.ain7 = (*(packet + offset) << 8) | *(packet + offset + 1);
dataset.setValidity(true, true);
measurementCd.resetTimer();
{
PoolReadGuard readSet(&dataset);
uint16_t tempRaw = ((packet[offset] & 0x0f) << 8) | packet[offset + 1];
dataset.temperatureCelcius = max1227::getTemperature(tempRaw);
offset += 2;
dataset.ain0 = (*(packet + offset) << 8) | *(packet + offset + 1);
offset += 2;
dataset.ain1 = (*(packet + offset) << 8) | *(packet + offset + 1);
offset += 6;
dataset.ain4 = (*(packet + offset) << 8) | *(packet + offset + 1);
offset += 2;
dataset.ain5 = (*(packet + offset) << 8) | *(packet + offset + 1);
offset += 2;
dataset.ain6 = (*(packet + offset) << 8) | *(packet + offset + 1);
offset += 2;
dataset.ain7 = (*(packet + offset) << 8) | *(packet + offset + 1);
dataset.setValidity(true, true);
}
if (printPeriodicData) {
sif::info << "Radiation sensor temperature: " << dataset.temperatureCelcius << " °C"
<< std::dec << std::endl;
@ -204,6 +216,12 @@ ReturnValue_t RadiationSensorHandler::interpretDeviceReply(DeviceCommandId_t id,
sif::info << "Radiation sensor ADC value channel 6: " << dataset.ain6 << std::endl;
sif::info << "Radiation sensor ADC value channel 7: " << dataset.ain7 << std::endl;
}
ReturnValue_t result =
getHkManagerHandle()->generateHousekeepingPacket(dataset.getSid(), &dataset, true);
if (result != returnvalue::OK) {
// TODO: Maybe add event?
sif::error << "Generating HK set for radiation sensor failed" << std::endl;
}
break;
}
default: {
@ -220,15 +238,18 @@ uint32_t RadiationSensorHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t mo
ReturnValue_t RadiationSensorHandler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(RAD_SENSOR::TEMPERATURE_C, new PoolEntry<float>({0.0}));
localDataPoolMap.emplace(RAD_SENSOR::AIN0, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(RAD_SENSOR::AIN1, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(RAD_SENSOR::AIN4, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(RAD_SENSOR::AIN5, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(RAD_SENSOR::AIN6, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(RAD_SENSOR::AIN7, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(radSens::TEMPERATURE_C, new PoolEntry<float>({0.0}));
localDataPoolMap.emplace(radSens::AIN0, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(radSens::AIN1, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(radSens::AIN4, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(radSens::AIN5, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(radSens::AIN6, new PoolEntry<uint16_t>({0}));
localDataPoolMap.emplace(radSens::AIN7, new PoolEntry<uint16_t>({0}));
// It should normally not be necessary to enable this set, as a sample TM will be generated
// after a measurement. If this is still enabled, sample with double the measurement frequency
// to ensure we get all measurements.
poolManager.subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams(dataset.getSid(), false, 20.0));
subdp::RegularHkPeriodicParams(dataset.getSid(), false, DEFAULT_MEASUREMENT_CD_MS / 2));
return returnvalue::OK;
}

View File

@ -38,13 +38,16 @@ class RadiationSensorHandler : public DeviceHandlerBase {
LocalDataPoolManager &poolManager) override;
private:
static constexpr uint32_t DEFAULT_MEASUREMENT_CD_MS = 30 * 60 * 1000;
enum class CommunicationStep { START_CONVERSION, READ_CONVERSIONS };
enum class InternalState { OFF, POWER_SWITCHING, SETUP, CONFIGURED };
bool printPeriodicData = false;
RAD_SENSOR::RadSensorDataset dataset;
static const uint8_t MAX_CMD_LEN = RAD_SENSOR::READ_SIZE;
radSens::RadSensorDataset dataset;
Countdown measurementCd = Countdown(DEFAULT_MEASUREMENT_CD_MS);
static const uint8_t MAX_CMD_LEN = radSens::READ_SIZE;
GpioIF *gpioIF = nullptr;
Stack5VHandler &stackHandler;

View File

@ -1,7 +1,7 @@
#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_RADSENSOR_H_
#define MISSION_DEVICES_DEVICEDEFINITIONS_RADSENSOR_H_
namespace RAD_SENSOR {
namespace radSens {
static const DeviceCommandId_t NONE = 0x0; // Set when no command is pending
@ -78,6 +78,6 @@ class RadSensorDataset : public StaticLocalDataSet<DATASET_ENTRIES> {
lp_var_t<uint16_t> ain6 = lp_var_t<uint16_t>(sid.objectId, AIN6, this);
lp_var_t<uint16_t> ain7 = lp_var_t<uint16_t>(sid.objectId, AIN7, this);
};
} // namespace RAD_SENSOR
} // namespace radSens
#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_RADSENSOR_H_ */

View File

@ -591,7 +591,6 @@ ReturnValue_t pst::pstTcsAndAcs(FixedTimeslotTaskIF *thisSequence, AcsPstCfg cfg
thisSequence->addSlot(objects::BPX_BATT_HANDLER, length * config::spiSched::SCHED_BLOCK_9_PERIOD,
DeviceHandlerIF::GET_READ);
#if OBSW_ADD_RAD_SENSORS == 1
/* Radiation sensor */
thisSequence->addSlot(objects::RAD_SENSOR, length * config::spiSched::SCHED_BLOCK_9_PERIOD,
DeviceHandlerIF::PERFORM_OPERATION);
@ -603,6 +602,5 @@ ReturnValue_t pst::pstTcsAndAcs(FixedTimeslotTaskIF *thisSequence, AcsPstCfg cfg
DeviceHandlerIF::SEND_READ);
thisSequence->addSlot(objects::RAD_SENSOR, length * config::spiSched::SCHED_BLOCK_9_PERIOD,
DeviceHandlerIF::GET_READ);
#endif
return returnvalue::OK;
}

View File

@ -125,6 +125,10 @@ static constexpr Event PDEC_REBOOT = event::makeEvent(SUBSYSTEM_ID, 12, severity
//! P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash
//! P2: First four letters of Git SHA is the last byte of P1 is set.
static constexpr Event FIRMWARE_INFO = event::makeEvent(SUBSYSTEM_ID, 13, severity::INFO);
//! [EXPORT] : [COMMENT] Active SD card info. SD States: 0: OFF, 1: ON, 2: MOUNTED.
//! P1: Active SD Card Index, 0 if none is active
//! P2: First two bytes: SD state of SD card 0, last two bytes SD state of SD card 1
static constexpr Event ACTIVE_SD_INFO = event::makeEvent(SUBSYSTEM_ID, 14, severity::INFO);
class ListDirectoryCmdBase {
public: // TODO: Packet definition for clean deserialization

2
tmtc

Submodule tmtc updated: eea7683581...cbcc06ede7