Compare commits
218 Commits
Author | SHA1 | Date | |
---|---|---|---|
ee3ef042cd | |||
05b0efe851 | |||
8ade378a69 | |||
045d149946 | |||
a75f9553be | |||
f271242d66 | |||
1756b5edcc | |||
9c1fc44c60 | |||
f46a705900 | |||
9183d18acc | |||
befa84a74b | |||
432b400835 | |||
0eb6b7cccb | |||
74ee291983 | |||
a146c34140 | |||
61ced11766 | |||
468fb096c9 | |||
4a2dd19a73 | |||
2658cabc9d | |||
dc83061f80 | |||
00da51b6a2 | |||
f846a18b33 | |||
ab588b4844 | |||
d12dca183d | |||
701ecbd182 | |||
bdd2b23ec3 | |||
d70245b56a | |||
9097a3f3c7 | |||
e05d9d4b2a | |||
07572ab3a0 | |||
304aabc336 | |||
07e8f95a31 | |||
babea226ab | |||
8c24a7310d | |||
8f5982fd72 | |||
611a2c0b45 | |||
61e6b09704 | |||
a9a0266a84 | |||
b7e6315be7 | |||
740275f57a | |||
58dd53def8 | |||
ddbe30f832 | |||
680d496b28 | |||
9c163419b2 | |||
f4fedd20c9 | |||
016fab105e | |||
767a0eda30 | |||
f2c71d962a | |||
7bf880a29f | |||
0185691dba | |||
9997aa5470 | |||
c1ccfe66eb | |||
ae9f43c707 | |||
143002de48 | |||
d439aedee7 | |||
b8d010cd39 | |||
22370e3e1e | |||
b98f91f6c1 | |||
b47bda8ed1 | |||
078a04b317 | |||
d24a983985 | |||
b964b03b2d | |||
f0d55f9e5b | |||
aa54dbbd10 | |||
1a62a13d97 | |||
500b3b6fc6 | |||
fa746f910d | |||
602c635967 | |||
84db92f75e | |||
4de71062af | |||
a4c8319cec | |||
379fd6046e | |||
aa800c4524 | |||
7f1fe3a2d8 | |||
e023220be4 | |||
8cf9dd9136 | |||
62d18826f1 | |||
41f762c6ff | |||
644a768778 | |||
756ea6d90d | |||
2d19d94d09 | |||
09a2ba7843 | |||
716f2b2832 | |||
6934721a42 | |||
fc8a8ce5a9 | |||
5e53795cbe | |||
2f2d1c7c7a | |||
f7be454dae | |||
ca30fed4c3 | |||
54f742bf19 | |||
4bfd675073 | |||
36420a6855 | |||
b0a2b5886f | |||
33d60ccf7f | |||
c8472f222c | |||
e68ac9cc2d | |||
a306b2a0af | |||
f112c28391 | |||
4693407b68 | |||
4e6b3ec9ed | |||
38b9a9b34e | |||
7c67648b8e | |||
9b1d4de9c5 | |||
998f93e3fa | |||
b5e1e0c31b | |||
9a65a9f20b | |||
b2a52b0bfc | |||
46862825ec | |||
dc1e51891e | |||
213dba1e75 | |||
4e686b4ad0 | |||
1e521f0575 | |||
53cccc3c13 | |||
a7c227f8ea | |||
bc6531f7a5 | |||
e17b8d2ec4 | |||
f645b97ba3 | |||
e79e13416e | |||
33773179a7 | |||
c5b26eade4 | |||
28eaf8461a | |||
6f67bd500b | |||
af354bd9fb | |||
aa746276ae | |||
3e3ac9f5be | |||
ae66820b52 | |||
93013d18ff | |||
7f3f99c6aa | |||
600d0c580d | |||
2722e471ef | |||
d8089489c4 | |||
cebe6e1423 | |||
906aedc911 | |||
97df53554e | |||
a81e939e70 | |||
b5f4b6cf7b | |||
f14677ec4e | |||
29dc684455 | |||
3ff8c6a481 | |||
f7bc052070 | |||
9861772c38 | |||
d4080fe5cb | |||
6b976f1046 | |||
673826b131 | |||
ae729337a2 | |||
a09cc86336 | |||
8620bd0283 | |||
ea606ce217 | |||
99305846f8 | |||
dd211cdf54 | |||
2262a15e35 | |||
94431cfdb8 | |||
41ec6dc0f2 | |||
836ce9a6cd | |||
ae80eac9a2 | |||
e063a7148a | |||
2808079444 | |||
3ba81d19a7 | |||
0e6f222ef1 | |||
d9e38d97ee | |||
98d1da428a | |||
128bd7d41a | |||
061cd0468c | |||
ae8f80bb54 | |||
8ad68aca3a | |||
b1bd7e0215 | |||
8d9755c17f | |||
b6ba2f291a | |||
c66799b24f | |||
18be21a310 | |||
ece053e5c3 | |||
aacd4dc088 | |||
5243f304af | |||
6156cc0b88 | |||
4acf66a020 | |||
2af1735cfd | |||
13844bce65 | |||
d7dc3f34c7 | |||
086dbcc19e | |||
7a53ada4b4 | |||
c5e18957f5 | |||
64b4db98ba | |||
3a236a1a3b | |||
19006e79b1 | |||
44325ee176 | |||
397e23f1da | |||
3d48f4d046 | |||
0d7fe0ff74 | |||
543d147b37 | |||
34dde2640e | |||
205a672680 | |||
57b01a5d2c | |||
4624d5a2a6 | |||
518f9d73f6 | |||
65dd0f313b | |||
39b2a3420c | |||
ce7da9f513 | |||
7a7d0e650f | |||
4ca8c38c98 | |||
96bd188e57 | |||
90db9785ea | |||
506c8a3fa6 | |||
150595b7f7 | |||
07f482a98b | |||
c759e118fa | |||
330e26b2ba | |||
41215c9ae9 | |||
dce6323090 | |||
906413e800 | |||
ad72301ea0 | |||
44d0f1c533 | |||
9d8dfdfd4f | |||
e6813efb88 | |||
8597e04eaf | |||
d6331aab0b | |||
56642a11f7 | |||
f6a0954315 | |||
d00cfc420c |
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -10,9 +10,6 @@
|
||||
[submodule "thirdparty/lwgps"]
|
||||
path = thirdparty/lwgps
|
||||
url = https://github.com/rmspacefish/lwgps.git
|
||||
[submodule "thirdparty/arcsec_star_tracker"]
|
||||
path = thirdparty/arcsec_star_tracker
|
||||
url = https://egit.irs.uni-stuttgart.de/eive/arcsec_star_tracker.git
|
||||
[submodule "thirdparty/json"]
|
||||
path = thirdparty/json
|
||||
url = https://github.com/nlohmann/json.git
|
||||
@ -22,3 +19,6 @@
|
||||
[submodule "thirdparty/gomspace-sw"]
|
||||
path = thirdparty/gomspace-sw
|
||||
url = https://egit.irs.uni-stuttgart.de/eive/gomspace-sw.git
|
||||
[submodule "thirdparty/sagittactl"]
|
||||
path = thirdparty/sagittactl
|
||||
url = https://egit.irs.uni-stuttgart.de/eive/sagittactl.git
|
||||
|
133
CHANGELOG.md
133
CHANGELOG.md
@ -16,6 +16,126 @@ will consitute of a breaking change warranting a new major release:
|
||||
|
||||
# [unreleased]
|
||||
|
||||
# [v2.0.5] to be released
|
||||
|
||||
- The dual lane assembly transition failed handler started new transitions towards the current mode
|
||||
instead of the target mode. This means that if the dual lane assembly never reached the initial
|
||||
submode (e.g. mode normal and submode dual side), it will transition back to the current mode,
|
||||
which miht be `MODE_OFF`. Furthermore, this can lead to invalid internal states, so the subsequent
|
||||
recovery handling becomes stuck in the custom recovery sequence when swichting power back on.
|
||||
- The dual lane custom recovery handling was adapted to always perform proper power switch handling
|
||||
irrespective of current or target modes.
|
||||
|
||||
# [v2.0.4] 2023-04-19
|
||||
|
||||
## Fixed
|
||||
|
||||
- The dual lane assembly datasets were not marked invalid properly on OFF transitions.
|
||||
|
||||
# [v2.0.3] 2023-04-17
|
||||
|
||||
- eive-tmtc: v3.1.1
|
||||
|
||||
## Fixed
|
||||
|
||||
- Fixed shadowing within the `SafeCtrl`, which prevented actuator commands to be calculated during
|
||||
eclipse phase.
|
||||
- EM build idle mode fixes for RW dummy.
|
||||
|
||||
## Added
|
||||
|
||||
- Add `MGT_OVERHEATING` event and fallback to system SAFE mode if the MGT is overheating for
|
||||
whatever reason.
|
||||
|
||||
## Changed
|
||||
|
||||
- Low-pass filters can no longer be executed if no actual data is available.
|
||||
|
||||
# [v2.0.2] 2023-04-16
|
||||
|
||||
- Bump patch version to 2.
|
||||
|
||||
# [v2.0.1] 2023-04-16
|
||||
|
||||
- eive-tmtc: v3.1.0
|
||||
|
||||
# [v2.0.0] 2023-04-16
|
||||
|
||||
This is the version which will fly on the satellite for the initial launch phase.
|
||||
|
||||
- q7s-package: v2.5.0
|
||||
- eive-tmtc: v3.0.0
|
||||
- `wire` library is now on version v10.7 as well.
|
||||
|
||||
## Added
|
||||
|
||||
- Added `mv`, `cp` and `rm` action helpers for the core controller for common filesystem operations.
|
||||
- Extended directory listing helpers. There is now a directory listing helper which dumps the
|
||||
directory listing as an action data reply immediately. For smaller directory listings, this
|
||||
allows a listing without requiring a separate file downlink (which also has not been implemented
|
||||
yet)
|
||||
|
||||
## Changed
|
||||
|
||||
- The directory listing action commands now allow compressing of either the target output file
|
||||
for the directory listing into file action command, or compression in the helper which dumps
|
||||
the directory listing directly.
|
||||
|
||||
# [v1.45.0] 2023-04-14
|
||||
|
||||
- q7s-package: v2.5.0
|
||||
- eive-tmtc: v3.0.0
|
||||
- STR firmware was updated to v10.7. `wire` library still needs to be updated.
|
||||
|
||||
## Fixed
|
||||
|
||||
- Small fix for `install-obsw-yocto.sh` script
|
||||
- Bugfix for STR firmware update procedure where the last remaining
|
||||
bytes were not written properly.
|
||||
- Bugfix for STR where an invalid reply was received for special requests
|
||||
like firmware updates.
|
||||
- Bugfix for shell command executors in command controller which lead to a crash.
|
||||
- Important bugfix for STR solution set. Missing STR mode u8 parameter.
|
||||
- Fix for STR image download.
|
||||
- Possible fix for STR image upload.
|
||||
- Fixed regression where the reply result for ACS board and SUS board devices was set to FAILED
|
||||
even when going to OFF mode. In that case, it has to be set to OK so the device handler can
|
||||
complete the OFF transition.
|
||||
|
||||
## Changed
|
||||
|
||||
- STR `wire` library updated to v10.3. Submodule renamed to `sagittactl`.
|
||||
- Custom FDIR for TMP1075 sensors. The device handlers reject `NEEDS_RECOVERY` health commands
|
||||
anyway, so it does not really make sense to use the default FDIR.
|
||||
- Reject `NEEDS_RECOVERY` health commands for the heater health devices.
|
||||
- Adapted some queue sizes so that EM startup works without queue errors
|
||||
- Event Manager: 120 -> 160
|
||||
- UDP TMTC Bridge: 50 -> 120
|
||||
- TCP TMTC Bridge: 50 -> 120
|
||||
- Service 5: 120 -> 160, number of events handled in one cycle increased to 80
|
||||
- EM: PCDU dummy is not a device handler anymore, but a custom power switcher object. This avoids
|
||||
some issues where the event manager could not send an event message to the PCDU dummy because
|
||||
the FDIR event queue was too small.
|
||||
|
||||
## Added
|
||||
|
||||
- Add a way for the MAX31865 RTD handlers to recognize faulty/broken/off sensor devices.
|
||||
- Add parameter interface for core controller
|
||||
- Allow setting the preferred SD card via the new parameter interface of the core controller
|
||||
with domain ID 0 and unque ID 0.
|
||||
- Added action commands to reset the PDEC. Also added autonomous reset handling for the PDEC,
|
||||
because there is no way so send TCs with a faulty PDEC.
|
||||
- Added `I2C_REBOOT` and `PDEC_REBOOT` events for EIVE system component to ensure ground gets
|
||||
informed.
|
||||
|
||||
## ACS
|
||||
|
||||
- Commanding from ACS Controller is now enabled.
|
||||
- Safe Controller was reverted to FLP Design. This also introduces safe mode strategies.
|
||||
They contain what the controller does and which data it uses. The controller will
|
||||
automatically based on the available data decide on which strategy to use. If a strategy
|
||||
is undesirable (e.g. the MEKF should not be used) this can be handeld via setting parameters.
|
||||
|
||||
# [v1.44.1] 2023-04-12
|
||||
|
||||
- eive-tmtc: v2.22.1
|
||||
@ -24,6 +144,7 @@ will consitute of a breaking change warranting a new major release:
|
||||
|
||||
- Bugfixes and improvements for SDC state machine. Internal state was not updated correctly due
|
||||
to a regression, so commanding the SDC state machine externally lead to confusing results.
|
||||
- Heater states array in TCS controller was too small.
|
||||
- Fixed a bug in persistent TM store, where the active file was not reset of SD card switches.
|
||||
SD card switch from 0 to 1 and vice-versa works without errors from persistent TM stores now.
|
||||
- Add a way for the SUS polling to detect broken or off devices by checking the retrieved
|
||||
@ -39,16 +160,22 @@ will consitute of a breaking change warranting a new major release:
|
||||
the active SD card is switched or there is a transition from hot redundant to cold redundant mode.
|
||||
This gives other tasks some time to register the SD cards being unusable, and therefore provides
|
||||
a way for them to perform any re-initialization tasks necessary after SD card switches.
|
||||
- TCS controller now only has an OFF mode and an ON mode
|
||||
- The TCS controller pauses operations related to the TCS board assembly (reading sensors and
|
||||
the primary control loop) while a TCS board recovery is on-going.
|
||||
|
||||
## Changed
|
||||
|
||||
- Allow specifying custom OBSW update filename. This allowed keeping a cleaner file structure
|
||||
where each update has a name including the version
|
||||
- The files extracted during an update process are deleted after the update was performed to keep
|
||||
the update directory cleaner.
|
||||
|
||||
## Added
|
||||
|
||||
- TCS controller: SUBMODE_NO_HEATER_CTRL (1) added for ON mode. If this submode is
|
||||
commanded, all heaters will be switched off and then no further heater
|
||||
commanding will be done.
|
||||
- Fixed a bug in persistent TM store, where the active file was not reset of SD card switches.
|
||||
SD card switch from 0 to 1 and vice-versa works without errors from persistent TM stores now.
|
||||
|
||||
# [v1.44.0] 2023-04-07
|
||||
|
||||
- eive-tmtc: v2.22.0
|
||||
|
@ -9,9 +9,9 @@
|
||||
# ##############################################################################
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
set(OBSW_VERSION_MAJOR 1)
|
||||
set(OBSW_VERSION_MINOR 44)
|
||||
set(OBSW_VERSION_REVISION 1)
|
||||
set(OBSW_VERSION_MAJOR 2)
|
||||
set(OBSW_VERSION_MINOR 0)
|
||||
set(OBSW_VERSION_REVISION 5)
|
||||
|
||||
# set(CMAKE_VERBOSE TRUE)
|
||||
|
||||
@ -94,6 +94,9 @@ set(OBSW_ADD_SUN_SENSORS
|
||||
set(OBSW_ADD_SUS_BOARD_ASS
|
||||
${INIT_VAL}
|
||||
CACHE STRING "Add sun sensor board assembly")
|
||||
set(OBSW_ADD_THERMAL_TEMP_INSERTER
|
||||
${OBSW_Q7S_EM}
|
||||
CACHE STRING "Add thermal sensor temperature inserter")
|
||||
set(OBSW_ADD_ACS_BOARD
|
||||
${INIT_VAL}
|
||||
CACHE STRING "Add ACS board module")
|
||||
@ -220,7 +223,7 @@ set(LIB_EIVE_MISSION_PATH mission)
|
||||
set(LIB_ETL_PATH ${THIRD_PARTY_FOLDER}/etl)
|
||||
set(LIB_CATCH2_PATH ${THIRD_PARTY_FOLDER}/Catch2)
|
||||
set(LIB_LWGPS_PATH ${THIRD_PARTY_FOLDER}/lwgps)
|
||||
set(LIB_ARCSEC_PATH ${THIRD_PARTY_FOLDER}/arcsec_star_tracker)
|
||||
set(LIB_ARCSEC_PATH ${THIRD_PARTY_FOLDER}/sagittactl)
|
||||
set(LIB_JSON_PATH ${THIRD_PARTY_FOLDER}/json)
|
||||
|
||||
set(FSFW_WARNING_SHADOW_LOCAL_GCC OFF)
|
||||
|
6
automation/Jenkinsfile
vendored
6
automation/Jenkinsfile
vendored
@ -22,7 +22,7 @@ pipeline {
|
||||
steps {
|
||||
dir(BUILDDIR_Q7S) {
|
||||
sh 'cmake -DTGT_BSP="arm/q7s" -DCMAKE_BUILD_TYPE=Debug ..'
|
||||
sh 'cmake --build . -j6'
|
||||
sh 'cmake --build . -j8'
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -30,7 +30,7 @@ pipeline {
|
||||
steps {
|
||||
dir(BUILDDIR_Q7S_EM) {
|
||||
sh 'cmake -DTGT_BSP="arm/q7s" -DEIVE_Q7S_EM=ON -DCMAKE_BUILD_TYPE=Debug ..'
|
||||
sh 'cmake --build . -j6'
|
||||
sh 'cmake --build . -j8'
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -38,7 +38,7 @@ pipeline {
|
||||
steps {
|
||||
dir(BUILDDIR_LINUX) {
|
||||
sh 'cmake ..'
|
||||
sh 'cmake --build . -j6'
|
||||
sh 'cmake --build . -j8'
|
||||
sh './eive-unittest'
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @brief Auto-generated event translation file. Contains 285 translations.
|
||||
* @brief Auto-generated event translation file. Contains 291 translations.
|
||||
* @details
|
||||
* Generated on: 2023-04-07 17:42:57
|
||||
* Generated on: 2023-04-17 11:34:19
|
||||
*/
|
||||
#include "translateEvents.h"
|
||||
|
||||
@ -97,6 +97,7 @@ const char *SAFE_RATE_RECOVERY_STRING = "SAFE_RATE_RECOVERY";
|
||||
const char *MULTIPLE_RW_INVALID_STRING = "MULTIPLE_RW_INVALID";
|
||||
const char *MEKF_INVALID_INFO_STRING = "MEKF_INVALID_INFO";
|
||||
const char *MEKF_RECOVERY_STRING = "MEKF_RECOVERY";
|
||||
const char *MEKF_AUTOMATIC_RESET_STRING = "MEKF_AUTOMATIC_RESET";
|
||||
const char *MEKF_INVALID_MODE_VIOLATION_STRING = "MEKF_INVALID_MODE_VIOLATION";
|
||||
const char *SAFE_MODE_CONTROLLER_FAILURE_STRING = "SAFE_MODE_CONTROLLER_FAILURE";
|
||||
const char *SWITCH_CMD_SENT_STRING = "SWITCH_CMD_SENT";
|
||||
@ -160,8 +161,11 @@ const char *LOST_BIT_LOCK_PDEC_STRING = "LOST_BIT_LOCK_PDEC";
|
||||
const char *TOO_MANY_IRQS_STRING = "TOO_MANY_IRQS";
|
||||
const char *POLL_SYSCALL_ERROR_PDEC_STRING = "POLL_SYSCALL_ERROR_PDEC";
|
||||
const char *WRITE_SYSCALL_ERROR_PDEC_STRING = "WRITE_SYSCALL_ERROR_PDEC";
|
||||
const char *PDEC_TRYING_RESET_WITH_INIT_STRING = "PDEC_TRYING_RESET_WITH_INIT";
|
||||
const char *PDEC_TRYING_RESET_NO_INIT_STRING = "PDEC_TRYING_RESET_NO_INIT";
|
||||
const char *PDEC_RESET_FAILED_STRING = "PDEC_RESET_FAILED";
|
||||
const char *OPEN_IRQ_FILE_FAILED_STRING = "OPEN_IRQ_FILE_FAILED";
|
||||
const char *PDEC_INIT_FAILED_STRING = "PDEC_INIT_FAILED";
|
||||
const char *IMAGE_UPLOAD_FAILED_STRING = "IMAGE_UPLOAD_FAILED";
|
||||
const char *IMAGE_DOWNLOAD_FAILED_STRING = "IMAGE_DOWNLOAD_FAILED";
|
||||
const char *IMAGE_UPLOAD_SUCCESSFUL_STRING = "IMAGE_UPLOAD_SUCCESSFUL";
|
||||
@ -268,6 +272,7 @@ const char *REBOOT_COUNTER_STRING = "REBOOT_COUNTER";
|
||||
const char *INDIVIDUAL_BOOT_COUNTS_STRING = "INDIVIDUAL_BOOT_COUNTS";
|
||||
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 *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";
|
||||
@ -275,6 +280,7 @@ const char *OBC_OVERHEATING_STRING = "OBC_OVERHEATING";
|
||||
const char *CAMERA_OVERHEATING_STRING = "CAMERA_OVERHEATING";
|
||||
const char *PCDU_SYSTEM_OVERHEATING_STRING = "PCDU_SYSTEM_OVERHEATING";
|
||||
const char *HEATER_NOT_OFF_FOR_OFF_MODE_STRING = "HEATER_NOT_OFF_FOR_OFF_MODE";
|
||||
const char *MGT_OVERHEATING_STRING = "MGT_OVERHEATING";
|
||||
const char *TX_TIMER_EXPIRED_STRING = "TX_TIMER_EXPIRED";
|
||||
const char *BIT_LOCK_TX_ON_STRING = "BIT_LOCK_TX_ON";
|
||||
const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION";
|
||||
@ -478,8 +484,10 @@ const char *translateEvents(Event event) {
|
||||
case (11204):
|
||||
return MEKF_RECOVERY_STRING;
|
||||
case (11205):
|
||||
return MEKF_INVALID_MODE_VIOLATION_STRING;
|
||||
return MEKF_AUTOMATIC_RESET_STRING;
|
||||
case (11206):
|
||||
return MEKF_INVALID_MODE_VIOLATION_STRING;
|
||||
case (11207):
|
||||
return SAFE_MODE_CONTROLLER_FAILURE_STRING;
|
||||
case (11300):
|
||||
return SWITCH_CMD_SENT_STRING;
|
||||
@ -604,9 +612,15 @@ const char *translateEvents(Event event) {
|
||||
case (12409):
|
||||
return WRITE_SYSCALL_ERROR_PDEC_STRING;
|
||||
case (12410):
|
||||
return PDEC_RESET_FAILED_STRING;
|
||||
return PDEC_TRYING_RESET_WITH_INIT_STRING;
|
||||
case (12411):
|
||||
return PDEC_TRYING_RESET_NO_INIT_STRING;
|
||||
case (12412):
|
||||
return PDEC_RESET_FAILED_STRING;
|
||||
case (12413):
|
||||
return OPEN_IRQ_FILE_FAILED_STRING;
|
||||
case (12414):
|
||||
return PDEC_INIT_FAILED_STRING;
|
||||
case (12500):
|
||||
return IMAGE_UPLOAD_FAILED_STRING;
|
||||
case (12501):
|
||||
@ -819,6 +833,8 @@ const char *translateEvents(Event event) {
|
||||
return TRYING_I2C_RECOVERY_STRING;
|
||||
case (14011):
|
||||
return I2C_REBOOT_STRING;
|
||||
case (14012):
|
||||
return PDEC_REBOOT_STRING;
|
||||
case (14100):
|
||||
return NO_VALID_SENSOR_TEMPERATURE_STRING;
|
||||
case (14101):
|
||||
@ -833,6 +849,8 @@ const char *translateEvents(Event event) {
|
||||
return PCDU_SYSTEM_OVERHEATING_STRING;
|
||||
case (14107):
|
||||
return HEATER_NOT_OFF_FOR_OFF_MODE_STRING;
|
||||
case (14108):
|
||||
return MGT_OVERHEATING_STRING;
|
||||
case (14201):
|
||||
return TX_TIMER_EXPIRED_STRING;
|
||||
case (14202):
|
||||
|
@ -2,7 +2,7 @@
|
||||
* @brief Auto-generated object translation file.
|
||||
* @details
|
||||
* Contains 171 translations.
|
||||
* Generated on: 2023-04-07 17:42:57
|
||||
* Generated on: 2023-04-17 11:34:19
|
||||
*/
|
||||
#include "translateObjects.h"
|
||||
|
||||
|
@ -151,7 +151,6 @@ void scheduling::initTasks() {
|
||||
if (result != returnvalue::OK) {
|
||||
scheduling::printAddObjectError("Core controller dummy", objects::CORE_CONTROLLER);
|
||||
}
|
||||
|
||||
result = thermalTask->addComponent(objects::THERMAL_CONTROLLER);
|
||||
if (result != returnvalue::OK) {
|
||||
scheduling::printAddObjectError("THERMAL_CONTROLLER", objects::THERMAL_CONTROLLER);
|
||||
|
@ -43,6 +43,9 @@
|
||||
#define OBSW_ADD_PL_PCDU @OBSW_ADD_PL_PCDU@
|
||||
#define OBSW_ADD_SYRLINKS @OBSW_ADD_SYRLINKS@
|
||||
#define OBSW_ADD_CCSDS_IP_CORES @OBSW_ADD_CCSDS_IP_CORES@
|
||||
// Only relevant for EM for TCS tests.
|
||||
#define OBSW_ADD_THERMAL_TEMP_INSERTER @OBSW_ADD_THERMAL_TEMP_INSERTER@
|
||||
|
||||
// Set to 1 if all telemetry should be sent to the PTME IP Core
|
||||
#define OBSW_TM_TO_PTME @OBSW_TM_TO_PTME@
|
||||
// Set to 1 if telecommands are received via the PDEC IP Core
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
#include "fsfw/timemanager/Stopwatch.h"
|
||||
#include "fsfw/version.h"
|
||||
#include "mission/sysDefs.h"
|
||||
#include "watchdog/definitions.h"
|
||||
#if OBSW_ADD_TMTC_UDP_SERVER == 1
|
||||
#include "fsfw/osal/common/UdpTmTcBridge.h"
|
||||
@ -40,7 +39,8 @@ CoreController::CoreController(object_id_t objectId, bool enableHkSet)
|
||||
cmdRepliesSizes(128),
|
||||
opDivider5(5),
|
||||
opDivider10(10),
|
||||
hkSet(this) {
|
||||
hkSet(this),
|
||||
paramHelper(this) {
|
||||
cmdExecutor.setRingBuffer(&cmdReplyBuf, &cmdRepliesSizes);
|
||||
try {
|
||||
sdcMan = SdCardManager::instance();
|
||||
@ -88,6 +88,10 @@ CoreController::CoreController(object_id_t objectId, bool enableHkSet)
|
||||
CoreController::~CoreController() {}
|
||||
|
||||
ReturnValue_t CoreController::handleCommandMessage(CommandMessage *message) {
|
||||
ReturnValue_t result = paramHelper.handleParameterMessage(message);
|
||||
if (result == returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return ExtendedControllerBase::handleCommandMessage(message);
|
||||
}
|
||||
|
||||
@ -113,7 +117,7 @@ void CoreController::performControlOperation() {
|
||||
bool replyReceived = false;
|
||||
// TODO: We could read the data in the ring buffer and send it as an action data reply.
|
||||
if (cmdExecutor.check(replyReceived) == CommandExecutor::EXECUTION_FINISHED) {
|
||||
actionHelper.finish(true, successRecipient, core::EXECUTE_SHELL_CMD);
|
||||
actionHelper.finish(true, successRecipient, core::EXECUTE_SHELL_CMD_BLOCKING);
|
||||
shellCmdIsExecuting = false;
|
||||
cmdReplyBuf.clear();
|
||||
while (not cmdRepliesSizes.empty()) {
|
||||
@ -154,6 +158,11 @@ ReturnValue_t CoreController::initialize() {
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
result = paramHelper.initialize();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
sdStateMachine();
|
||||
|
||||
triggerEvent(core::REBOOT_SW, CURRENT_CHIP, CURRENT_COPY);
|
||||
@ -224,6 +233,84 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_
|
||||
case (LIST_DIRECTORY_INTO_FILE): {
|
||||
return actionListDirectoryIntoFile(actionId, commandedBy, data, size);
|
||||
}
|
||||
case (LIST_DIRECTORY_DUMP_DIRECTLY): {
|
||||
return actionListDirectoryDumpDirectly(actionId, commandedBy, data, size);
|
||||
}
|
||||
case (CP_HELPER): {
|
||||
CpHelperParser parser(data, size);
|
||||
ReturnValue_t result = parser.parse();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
std::ostringstream oss("cp ", std::ostringstream::ate);
|
||||
if (parser.isRecursiveOptSet()) {
|
||||
oss << "-r ";
|
||||
}
|
||||
auto &sourceTgt = parser.destTgtPair();
|
||||
oss << sourceTgt.sourceName << " " << sourceTgt.targetName;
|
||||
sif::info << "CoreController: Performing copy command: " << oss.str() << std::endl;
|
||||
int ret = std::system(oss.str().c_str());
|
||||
if (ret != 0) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return EXECUTION_FINISHED;
|
||||
}
|
||||
case (MV_HELPER): {
|
||||
MvHelperParser parser(data, size);
|
||||
ReturnValue_t result = parser.parse();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
std::ostringstream oss("mv ", std::ostringstream::ate);
|
||||
auto &sourceTgt = parser.destTgtPair();
|
||||
oss << sourceTgt.sourceName << " " << sourceTgt.targetName;
|
||||
sif::info << "CoreController: Performing move command: " << oss.str() << std::endl;
|
||||
int ret = std::system(oss.str().c_str());
|
||||
if (ret != 0) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return EXECUTION_FINISHED;
|
||||
}
|
||||
case (RM_HELPER): {
|
||||
RmHelperParser parser(data, size);
|
||||
ReturnValue_t result = parser.parse();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
std::ostringstream oss("rm ", std::ostringstream::ate);
|
||||
if (parser.isRecursiveOptSet() or parser.isForceOptSet()) {
|
||||
oss << "-";
|
||||
}
|
||||
if (parser.isRecursiveOptSet()) {
|
||||
oss << "r";
|
||||
}
|
||||
if (parser.isForceOptSet()) {
|
||||
oss << "f";
|
||||
}
|
||||
size_t removeTargetSize = 0;
|
||||
const char *removeTgt = parser.getRemoveTarget(removeTargetSize);
|
||||
oss << " " << removeTgt;
|
||||
sif::info << "CoreController: Performing remove command: " << oss.str() << std::endl;
|
||||
int ret = std::system(oss.str().c_str());
|
||||
if (ret != 0) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return EXECUTION_FINISHED;
|
||||
}
|
||||
case (MKDIR_HELPER): {
|
||||
if (size < 1) {
|
||||
return HasActionsIF::INVALID_PARAMETERS;
|
||||
}
|
||||
std::string createdDir = std::string(reinterpret_cast<const char *>(data), size);
|
||||
std::ostringstream oss("mkdir ", std::ostringstream::ate);
|
||||
oss << createdDir;
|
||||
sif::info << "CoreController: Performing directory creation: " << oss.str() << std::endl;
|
||||
int ret = std::system(oss.str().c_str());
|
||||
if (ret != 0) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return EXECUTION_FINISHED;
|
||||
}
|
||||
case (SWITCH_REBOOT_FILE_HANDLING): {
|
||||
if (size < 1) {
|
||||
return HasActionsIF::INVALID_PARAMETERS;
|
||||
@ -294,6 +381,41 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_
|
||||
// Completion will be reported by SD card state machine
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (SYSTEMCTL_CMD_EXECUTOR): {
|
||||
// Expect one byte systemctl command type and a unit name with at least one byte as minimum.
|
||||
if (size < 2) {
|
||||
return HasActionsIF::INVALID_PARAMETERS;
|
||||
}
|
||||
if (data[0] >= core::SystemctlCmd::NUM_CMDS) {
|
||||
return HasActionsIF::INVALID_PARAMETERS;
|
||||
}
|
||||
core::SystemctlCmd cmdType = static_cast<core::SystemctlCmd>(data[0]);
|
||||
std::string unitName = std::string(reinterpret_cast<const char *>(data + 1), size - 1);
|
||||
std::ostringstream oss("systemctl ", std::ostringstream::ate);
|
||||
switch (cmdType) {
|
||||
case (core::SystemctlCmd::START): {
|
||||
oss << "start ";
|
||||
break;
|
||||
}
|
||||
case (core::SystemctlCmd::STOP): {
|
||||
oss << "stop ";
|
||||
break;
|
||||
}
|
||||
case (core::SystemctlCmd::RESTART): {
|
||||
oss << "restart ";
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return HasActionsIF::INVALID_PARAMETERS;
|
||||
}
|
||||
}
|
||||
oss << unitName;
|
||||
int result = std::system(oss.str().c_str());
|
||||
if (result != 0) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return EXECUTION_FINISHED;
|
||||
}
|
||||
case (SWITCH_IMG_LOCK): {
|
||||
if (size != 3) {
|
||||
return HasActionsIF::INVALID_PARAMETERS;
|
||||
@ -324,13 +446,22 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_
|
||||
// Warning: This function will never return, because it reboots the system
|
||||
return actionReboot(data, size);
|
||||
}
|
||||
case (EXECUTE_SHELL_CMD): {
|
||||
std::string cmd = std::string(cmd, size);
|
||||
case (EXECUTE_SHELL_CMD_BLOCKING): {
|
||||
std::string cmdToExecute = std::string(reinterpret_cast<const char *>(data), size);
|
||||
int result = std::system(cmdToExecute.c_str());
|
||||
if (result != 0) {
|
||||
// TODO: Data reply with returnalue maybe?
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return EXECUTION_FINISHED;
|
||||
}
|
||||
case (EXECUTE_SHELL_CMD_NON_BLOCKING): {
|
||||
std::string cmdToExecute = std::string(reinterpret_cast<const char *>(data), size);
|
||||
if (cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING or
|
||||
shellCmdIsExecuting) {
|
||||
return HasActionsIF::IS_BUSY;
|
||||
}
|
||||
cmdExecutor.load(cmd, false, false);
|
||||
cmdExecutor.load(cmdToExecute, false, false);
|
||||
ReturnValue_t result = cmdExecutor.execute();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
@ -858,59 +989,144 @@ ReturnValue_t CoreController::initVersionFile() {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t CoreController::actionListDirectoryIntoFile(ActionId_t actionId,
|
||||
MessageQueueId_t commandedBy,
|
||||
const uint8_t *data, size_t size) {
|
||||
// TODO: Packet definition for clean deserialization
|
||||
// 2 bytes for a and R flag, at least 5 bytes for minimum valid path /tmp with
|
||||
// null termination, at least 7 bytes for minimum target file name /tmp/a with
|
||||
// null termination.
|
||||
if (size < 14) {
|
||||
return HasActionsIF::INVALID_PARAMETERS;
|
||||
ReturnValue_t CoreController::actionListDirectoryDumpDirectly(ActionId_t actionId,
|
||||
MessageQueueId_t commandedBy,
|
||||
const uint8_t *data, size_t size) {
|
||||
core::ListDirectoryCmdBase parser(data, size);
|
||||
ReturnValue_t result = parser.parse();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
// We could also make -l optional, but I can't think of a reason why to not use -l..
|
||||
|
||||
// This flag specifies to run ls with -a
|
||||
bool aFlag = data[0];
|
||||
data += 1;
|
||||
// This flag specifies to run ls with -R
|
||||
bool RFlag = data[1];
|
||||
data += 1;
|
||||
|
||||
size_t remainingSize = size - 2;
|
||||
// One larger for null termination, which prevents undefined behaviour if the sent
|
||||
// strings are not 0 terminated properly
|
||||
std::vector<uint8_t> repoAndTargetFileBuffer(remainingSize + 1, 0);
|
||||
std::memcpy(repoAndTargetFileBuffer.data(), data, remainingSize);
|
||||
const char *currentCharPtr = reinterpret_cast<const char *>(repoAndTargetFileBuffer.data());
|
||||
// Full target file name
|
||||
std::string repoName(currentCharPtr);
|
||||
size_t repoLength = repoName.length();
|
||||
// The other string needs to be at least one letter plus NULL termination to be valid at all
|
||||
// The first string also needs to be NULL terminated, but the termination is not included
|
||||
// in the string length, so this is subtracted from the remaining size as well
|
||||
if (repoLength > remainingSize - 3) {
|
||||
return HasActionsIF::INVALID_PARAMETERS;
|
||||
}
|
||||
// The file length will not include the NULL termination, so we skip it
|
||||
currentCharPtr += repoLength + 1;
|
||||
std::string targetFileName(currentCharPtr);
|
||||
std::ostringstream oss;
|
||||
oss << "ls -l";
|
||||
if (aFlag) {
|
||||
std::ostringstream oss("ls -l", std::ostringstream::ate);
|
||||
if (parser.aFlagSet()) {
|
||||
oss << "a";
|
||||
}
|
||||
if (RFlag) {
|
||||
if (parser.rFlagSet()) {
|
||||
oss << "R";
|
||||
}
|
||||
|
||||
oss << " " << repoName << " > " << targetFileName;
|
||||
int result = std::system(oss.str().c_str());
|
||||
if (result != 0) {
|
||||
utility::handleSystemError(result, "CoreController::actionListDirectoryIntoFile");
|
||||
actionHelper.finish(false, commandedBy, actionId);
|
||||
size_t repoNameLen = 0;
|
||||
const char *repoName = parser.getRepoName(repoNameLen);
|
||||
|
||||
oss << " " << repoName << " > " << LIST_DIR_DUMP_WORK_FILE;
|
||||
sif::info << "Executing " << oss.str() << " for direct dump";
|
||||
if (parser.compressionOptionSet()) {
|
||||
sif::info << " with compression";
|
||||
}
|
||||
return returnvalue::OK;
|
||||
sif::info << std::endl;
|
||||
int ret = std::system(oss.str().c_str());
|
||||
if (ret != 0) {
|
||||
utility::handleSystemError(result, "CoreController::actionListDirectoryDumpDirectly");
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (parser.compressionOptionSet()) {
|
||||
std::string compressedName = LIST_DIR_DUMP_WORK_FILE + std::string(".gz");
|
||||
oss.str("");
|
||||
oss << "gzip " << LIST_DIR_DUMP_WORK_FILE;
|
||||
ret = std::system(oss.str().c_str());
|
||||
if (ret != 0) {
|
||||
utility::handleSystemError(result, "CoreController::actionListDirectoryDumpDirectly");
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
oss.str("");
|
||||
// Overwrite the work file with the compressed archive.
|
||||
oss << "mv " << compressedName << " " << LIST_DIR_DUMP_WORK_FILE;
|
||||
ret = std::system(oss.str().c_str());
|
||||
if (ret != 0) {
|
||||
utility::handleSystemError(result, "CoreController::actionListDirectoryDumpDirectly");
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
std::array<uint8_t, 1024> dirListingBuf{};
|
||||
dirListingBuf[8] = parser.compressionOptionSet();
|
||||
// First four bytes reserved for segment index. One byte for compression option information
|
||||
std::strcpy(reinterpret_cast<char *>(dirListingBuf.data() + 2 * sizeof(uint32_t) + 1), repoName);
|
||||
std::ifstream ifile(LIST_DIR_DUMP_WORK_FILE, std::ios::binary);
|
||||
if (ifile.bad()) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
std::error_code e;
|
||||
size_t totalFileSize = std::filesystem::file_size(LIST_DIR_DUMP_WORK_FILE, e);
|
||||
uint32_t segmentIdx = 0;
|
||||
size_t dumpedBytes = 0;
|
||||
size_t nextDumpLen = 0;
|
||||
size_t dummy = 0;
|
||||
size_t maxDumpLen = dirListingBuf.size() - 2 * sizeof(uint32_t) - 1 - repoNameLen - 1;
|
||||
size_t listingDataOffset = 2 * sizeof(uint32_t) + 1 + repoNameLen + 1;
|
||||
uint32_t chunks = totalFileSize / maxDumpLen;
|
||||
if (totalFileSize % maxDumpLen != 0) {
|
||||
chunks++;
|
||||
}
|
||||
SerializeAdapter::serialize(&chunks, dirListingBuf.data() + sizeof(uint32_t), &dummy,
|
||||
dirListingBuf.size() - sizeof(uint32_t),
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
while (dumpedBytes < totalFileSize) {
|
||||
ifile.seekg(dumpedBytes, std::ios::beg);
|
||||
nextDumpLen = maxDumpLen;
|
||||
if (totalFileSize - dumpedBytes < maxDumpLen) {
|
||||
nextDumpLen = totalFileSize - dumpedBytes;
|
||||
}
|
||||
SerializeAdapter::serialize(&segmentIdx, dirListingBuf.data(), &dummy, dirListingBuf.size(),
|
||||
SerializeIF::Endianness::NETWORK);
|
||||
ifile.read(reinterpret_cast<char *>(dirListingBuf.data() + listingDataOffset), nextDumpLen);
|
||||
result = actionHelper.reportData(commandedBy, actionId, dirListingBuf.data(),
|
||||
listingDataOffset + nextDumpLen);
|
||||
if (result != returnvalue::OK) {
|
||||
// Remove work file when we are done
|
||||
std::filesystem::remove(LIST_DIR_DUMP_WORK_FILE, e);
|
||||
return result;
|
||||
}
|
||||
segmentIdx++;
|
||||
dumpedBytes += nextDumpLen;
|
||||
}
|
||||
// Remove work file when we are done
|
||||
std::filesystem::remove(LIST_DIR_DUMP_WORK_FILE, e);
|
||||
return EXECUTION_FINISHED;
|
||||
}
|
||||
|
||||
ReturnValue_t CoreController::actionListDirectoryIntoFile(ActionId_t actionId,
|
||||
MessageQueueId_t commandedBy,
|
||||
const uint8_t *data, size_t size) {
|
||||
core::ListDirectoryIntoFile parser(data, size);
|
||||
ReturnValue_t result = parser.parse();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::ostringstream oss("ls -l", std::ostringstream::ate);
|
||||
if (parser.aFlagSet()) {
|
||||
oss << "a";
|
||||
}
|
||||
if (parser.rFlagSet()) {
|
||||
oss << "R";
|
||||
}
|
||||
|
||||
size_t repoNameLen = 0;
|
||||
const char *repoName = parser.getRepoName(repoNameLen);
|
||||
size_t targetFileNameLen = 0;
|
||||
const char *targetFileName = parser.getTargetName(targetFileNameLen);
|
||||
oss << " " << repoName << " > " << targetFileName;
|
||||
sif::info << "Executing list directory request, command: " << oss.str() << std::endl;
|
||||
int ret = std::system(oss.str().c_str());
|
||||
if (ret != 0) {
|
||||
utility::handleSystemError(result, "CoreController::actionListDirectoryIntoFile");
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
// Compression will add a .gz ending. I don't have any issue with this, it makes it explicit
|
||||
// that this is a compressed file.
|
||||
if (parser.compressionOptionSet()) {
|
||||
oss.str("");
|
||||
oss << "gzip " << targetFileName;
|
||||
sif::info << "Compressing directory listing: " << oss.str() << std::endl;
|
||||
ret = std::system(oss.str().c_str());
|
||||
if (ret != 0) {
|
||||
utility::handleSystemError(result, "CoreController::actionListDirectoryIntoFile");
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
return EXECUTION_FINISHED;
|
||||
}
|
||||
|
||||
ReturnValue_t CoreController::initBootCopyFile() {
|
||||
@ -1298,7 +1514,7 @@ void CoreController::performMountedSdCardOperations() {
|
||||
auto mountedSdCardOp = [&](sd::SdCard sdCard, std::string mntPoint) {
|
||||
if (not performOneShotSdCardOpsSwitch) {
|
||||
std::ostringstream path;
|
||||
path << mntPoint << "/" << CONF_FOLDER;
|
||||
path << mntPoint << "/" << core::CONF_FOLDER;
|
||||
std::error_code e;
|
||||
if (not std::filesystem::exists(path.str()), e) {
|
||||
bool created = std::filesystem::create_directory(path.str(), e);
|
||||
@ -1996,6 +2212,8 @@ ReturnValue_t CoreController::executeSwUpdate(SwUpdateSources sourceDir, const u
|
||||
if (not exists(archivePath, e)) {
|
||||
return HasFileSystemIF::FILE_DOES_NOT_EXIST;
|
||||
}
|
||||
// TODO: Decompressing without limiting memory usage with xz is actually a bit risky..
|
||||
// But has not been an issue so far.
|
||||
ostringstream cmd("tar -xJf", ios::app);
|
||||
cmd << " " << archivePath << " -C " << prefixPath;
|
||||
int result = system(cmd.str().c_str());
|
||||
@ -2124,7 +2342,38 @@ void CoreController::announceBootCounts() {
|
||||
totalBootCount & 0xffffffff);
|
||||
}
|
||||
|
||||
MessageQueueId_t CoreController::getCommandQueue() const {
|
||||
return ExtendedControllerBase::getCommandQueue();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
ReturnValue_t CoreController::getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
|
||||
ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues,
|
||||
uint16_t startAtIndex) {
|
||||
if (domainId != 0) {
|
||||
return HasParametersIF::INVALID_DOMAIN_ID;
|
||||
}
|
||||
if (uniqueIdentifier >= ParamId::NUM_IDS) {
|
||||
return HasParametersIF::INVALID_IDENTIFIER_ID;
|
||||
}
|
||||
uint8_t newPrefSd;
|
||||
ReturnValue_t result = newValues->getElement(&newPrefSd);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
// Only SD card 0 (0) and 1 (1) are allowed values.
|
||||
if (newPrefSd > 1) {
|
||||
return HasParametersIF::INVALID_VALUE;
|
||||
}
|
||||
result = sdcMan->setPreferredSdCard(static_cast<sd::SdCard>(newPrefSd));
|
||||
if (result != returnvalue::OK) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
parameterWrapper->set(prefSdRaw);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include <fsfw/container/DynamicFIFO.h>
|
||||
#include <fsfw/container/SimpleRingBuffer.h>
|
||||
#include <fsfw/globalfunctions/PeriodicOperationDivider.h>
|
||||
#include <fsfw/parameters/ParameterHelper.h>
|
||||
#include <fsfw/parameters/ReceivesParameterMessagesIF.h>
|
||||
#include <libxiphos.h>
|
||||
#include <mission/acs/archive/GPSDefinitions.h>
|
||||
#include <mission/utility/trace.h>
|
||||
@ -16,17 +18,11 @@
|
||||
#include "bsp_q7s/fs/SdCardManager.h"
|
||||
#include "events/subsystemIdRanges.h"
|
||||
#include "fsfw/controller/ExtendedControllerBase.h"
|
||||
#include "mission/sysDefs.h"
|
||||
|
||||
class Timer;
|
||||
class SdCardManager;
|
||||
|
||||
namespace xsc {
|
||||
|
||||
enum Chip : int { CHIP_0, CHIP_1, NO_CHIP, SELF_CHIP, ALL_CHIP };
|
||||
enum Copy : int { COPY_0, COPY_1, NO_COPY, SELF_COPY, ALL_COPY };
|
||||
|
||||
} // namespace xsc
|
||||
|
||||
struct RebootFile {
|
||||
static constexpr uint8_t DEFAULT_MAX_BOOT_CNT = 10;
|
||||
|
||||
@ -48,8 +44,10 @@ struct RebootFile {
|
||||
xsc::Copy mechanismNextCopy = xsc::Copy::NO_COPY;
|
||||
};
|
||||
|
||||
class CoreController : public ExtendedControllerBase {
|
||||
class CoreController : public ExtendedControllerBase, public ReceivesParameterMessagesIF {
|
||||
public:
|
||||
enum ParamId : uint8_t { PREF_SD = 0, NUM_IDS };
|
||||
|
||||
static xsc::Chip CURRENT_CHIP;
|
||||
static xsc::Copy CURRENT_COPY;
|
||||
|
||||
@ -57,23 +55,18 @@ class CoreController : public ExtendedControllerBase {
|
||||
static constexpr char CHIP_STATE_FILE[] = "/tmp/chip_prot_status.txt";
|
||||
static constexpr char CURR_COPY_FILE[] = "/tmp/curr_copy.txt";
|
||||
|
||||
static constexpr char CONF_FOLDER[] = "conf";
|
||||
|
||||
static constexpr char VERSION_FILE_NAME[] = "version.txt";
|
||||
static constexpr char REBOOT_FILE_NAME[] = "reboot.txt";
|
||||
static constexpr char TIME_FILE_NAME[] = "time_backup.txt";
|
||||
|
||||
const std::string VERSION_FILE =
|
||||
"/" + std::string(CONF_FOLDER) + "/" + std::string(VERSION_FILE_NAME);
|
||||
"/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::VERSION_FILE_NAME);
|
||||
const std::string REBOOT_FILE =
|
||||
"/" + std::string(CONF_FOLDER) + "/" + std::string(REBOOT_FILE_NAME);
|
||||
"/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::REBOOT_FILE_NAME);
|
||||
const std::string BACKUP_TIME_FILE =
|
||||
"/" + std::string(CONF_FOLDER) + "/" + std::string(TIME_FILE_NAME);
|
||||
"/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::TIME_FILE_NAME);
|
||||
|
||||
static constexpr char CHIP_0_COPY_0_MOUNT_DIR[] = "/tmp/mntupdate-xdi-qspi0-nom-rootfs";
|
||||
static constexpr char CHIP_0_COPY_1_MOUNT_DIR[] = "/tmp/mntupdate-xdi-qspi0-gold-rootfs";
|
||||
static constexpr char CHIP_1_COPY_0_MOUNT_DIR[] = "/tmp/mntupdate-xdi-qspi1-nom-rootfs";
|
||||
static constexpr char CHIP_1_COPY_1_MOUNT_DIR[] = "/tmp/mntupdate-xdi-qspi1-gold-rootfs";
|
||||
static constexpr char LIST_DIR_DUMP_WORK_FILE[] = "/tmp/dir_listing.tmp";
|
||||
|
||||
static constexpr dur_millis_t INIT_SD_CARD_CHECK_TIMEOUT = 5000;
|
||||
static constexpr dur_millis_t DEFAULT_SD_CARD_CHECK_TIMEOUT = 60000;
|
||||
@ -152,6 +145,7 @@ class CoreController : public ExtendedControllerBase {
|
||||
SdCardManager* sdcMan = nullptr;
|
||||
MessageQueueIF* eventQueue = nullptr;
|
||||
|
||||
uint8_t prefSdRaw = sd::SdCard::SLOT_0;
|
||||
SdStates sdFsmState = SdStates::START;
|
||||
SdStates fsmStateAfterDelay = SdStates::IDLE;
|
||||
enum SdCfgMode { PASSIVE, COLD_REDUNDANT, HOT_REDUNDANT };
|
||||
@ -216,10 +210,16 @@ class CoreController : public ExtendedControllerBase {
|
||||
|
||||
core::HkSet hkSet;
|
||||
|
||||
ParameterHelper paramHelper;
|
||||
|
||||
#if OBSW_SD_CARD_MUST_BE_ON == 1
|
||||
bool remountAttemptFlag = true;
|
||||
#endif
|
||||
|
||||
MessageQueueId_t getCommandQueue() const override;
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
|
||||
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
||||
uint16_t startAtIndex) override;
|
||||
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) override;
|
||||
|
||||
@ -251,6 +251,12 @@ class CoreController : public ExtendedControllerBase {
|
||||
|
||||
ReturnValue_t actionListDirectoryIntoFile(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||
const uint8_t* data, size_t size);
|
||||
ReturnValue_t actionListDirectoryDumpDirectly(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||
const uint8_t* data, size_t size);
|
||||
|
||||
ReturnValue_t actionListDirectoryCommonCommandCreator(const uint8_t* data, size_t size,
|
||||
std::ostringstream& oss);
|
||||
|
||||
ReturnValue_t actionXscReboot(const uint8_t* data, size_t size);
|
||||
ReturnValue_t actionReboot(const uint8_t* data, size_t size);
|
||||
|
||||
|
@ -27,8 +27,9 @@
|
||||
#include <mission/system/acs/ImtqAssembly.h>
|
||||
#include <mission/system/acs/StrAssembly.h>
|
||||
#include <mission/system/acs/StrFdir.h>
|
||||
#include <mission/system/com/SyrlinksAssembly.h>
|
||||
#include <mission/system/objects/CamSwitcher.h>
|
||||
#include <mission/system/objects/SyrlinksAssembly.h>
|
||||
#include <mission/system/tcs/TmpDevFdir.h>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "bsp_q7s/boardtest/Q7STestTask.h"
|
||||
@ -62,17 +63,15 @@
|
||||
#include "mission/system/acs/acsModeTree.h"
|
||||
#include "mission/system/com/SyrlinksFdir.h"
|
||||
#include "mission/system/com/comModeTree.h"
|
||||
#include "mission/system/fdir/RtdFdir.h"
|
||||
#include "mission/system/objects/TcsBoardAssembly.h"
|
||||
#include "mission/system/power/GomspacePowerFdir.h"
|
||||
#include "mission/system/tcs/RtdFdir.h"
|
||||
#include "mission/system/tcs/TcsBoardAssembly.h"
|
||||
#include "mission/system/tcs/tcsModeTree.h"
|
||||
#include "mission/system/tree/payloadModeTree.h"
|
||||
#include "mission/system/tree/tcsModeTree.h"
|
||||
#include "mission/tmtc/tmFilters.h"
|
||||
#include "mission/utility/GlobalConfigHandler.h"
|
||||
#include "tmtc/pusIds.h"
|
||||
|
||||
using gpio::Direction;
|
||||
using gpio::Levels;
|
||||
#if OBSW_TEST_LIBGPIOD == 1
|
||||
#include "linux/boardtest/LibgpiodTest.h"
|
||||
#endif
|
||||
@ -123,6 +122,9 @@ using gpio::Levels;
|
||||
#include "mission/system/acs/AcsBoardAssembly.h"
|
||||
#include "mission/tmtc/TmFunnelHandler.h"
|
||||
|
||||
using gpio::Direction;
|
||||
using gpio::Levels;
|
||||
|
||||
ResetArgs RESET_ARGS_GNSS;
|
||||
std::atomic_bool LINK_STATE = CcsdsIpCoreHandler::LINK_DOWN;
|
||||
std::atomic_bool PTME_LOCKED = false;
|
||||
@ -164,6 +166,7 @@ void ObjectFactory::createTmpComponents() {
|
||||
new I2cCookie(tmpDevIds[idx].second, TMP1075::MAX_REPLY_LENGTH, q7s::I2C_PS_EIVE));
|
||||
auto* tmpDevHandler =
|
||||
new Tmp1075Handler(tmpDevIds[idx].first, objects::I2C_COM_IF, tmpDevCookies[idx]);
|
||||
tmpDevHandler->setCustomFdir(new TmpDevFdir(tmpDevIds[idx].first));
|
||||
tmpDevHandler->connectModeTreeParent(satsystem::tcs::SUBSYSTEM);
|
||||
// TODO: Remove this after TCS subsystem was added
|
||||
// These devices are connected to the 3V3 stack and should be powered permanently. Therefore,
|
||||
|
@ -302,6 +302,9 @@ void scheduling::initTasks() {
|
||||
|
||||
PeriodicTaskIF* tcsSystemTask = factory->createPeriodicTask(
|
||||
"TCS_TASK", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.5, missedDeadlineFunc, &RR_SCHEDULING);
|
||||
#if OBSW_ADD_THERMAL_TEMP_INSERTER == 1
|
||||
tcsSystemTask->addComponent(objects::THERMAL_TEMP_INSERTER);
|
||||
#endif
|
||||
scheduling::scheduleRtdSensors(tcsSystemTask);
|
||||
result = tcsSystemTask->addComponent(objects::TCS_SUBSYSTEM);
|
||||
if (result != returnvalue::OK) {
|
||||
@ -317,12 +320,10 @@ void scheduling::initTasks() {
|
||||
scheduling::printAddObjectError("THERMAL_CONTROLLER", objects::THERMAL_CONTROLLER);
|
||||
}
|
||||
#endif
|
||||
#if OBSW_ADD_HEATERS == 1
|
||||
result = tcsSystemTask->addComponent(objects::HEATER_HANDLER);
|
||||
if (result != returnvalue::OK) {
|
||||
scheduling::printAddObjectError("HEATER_HANDLER", objects::HEATER_HANDLER);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OBSW_ADD_SYRLINKS == 1
|
||||
PeriodicTaskIF* syrlinksCom = factory->createPeriodicTask(
|
||||
|
@ -63,8 +63,7 @@ void ObjectFactory::produce(void* args) {
|
||||
|
||||
PowerSwitchIF* pwrSwitcher = nullptr;
|
||||
#if OBSW_ADD_GOMSPACE_PCDU == 0
|
||||
auto* comCookieDummy = new ComCookieDummy();
|
||||
pwrSwitcher = new PcduHandlerDummy(objects::PCDU_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
pwrSwitcher = new PcduHandlerDummy(objects::PCDU_HANDLER);
|
||||
#else
|
||||
createPcduComponents(gpioComIF, &pwrSwitcher, enableHkSets);
|
||||
#endif
|
||||
|
@ -1,20 +0,0 @@
|
||||
#ifndef FSFWCONFIG_DEVICES_HEATERSWITCHERLIST_H_
|
||||
#define FSFWCONFIG_DEVICES_HEATERSWITCHERLIST_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace heater {
|
||||
enum Switchers : uint8_t {
|
||||
HEATER_0_OBC_BRD,
|
||||
HEATER_1_PLOC_PROC_BRD,
|
||||
HEATER_2_ACS_BRD,
|
||||
HEATER_3_PCDU_PDU,
|
||||
HEATER_4_CAMERA,
|
||||
HEATER_5_STR,
|
||||
HEATER_6_DRO,
|
||||
HEATER_7_S_BAND,
|
||||
NUMBER_OF_SWITCHES
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* FSFWCONFIG_DEVICES_HEATERSWITCHERLIST_H_ */
|
@ -37,9 +37,6 @@ enum commonClassIds : uint8_t {
|
||||
SUPV_RETURN_VALUES_IF, // SPVRTVIF
|
||||
ACS_CTRL, // ACSCTRL
|
||||
ACS_MEKF, // ACSMEKF
|
||||
ACS_SAFE, // ACSSAF
|
||||
ACS_PTG, // ACSPTG
|
||||
ACS_DETUMBLE, // ACSDTB
|
||||
SD_CARD_MANAGER, // SDMA
|
||||
LOCAL_PARAM_HANDLER, // LPH
|
||||
PERSISTENT_TM_STORE, // PTM
|
||||
|
@ -43,5 +43,7 @@ ReturnValue_t ImtqDummy::initializeLocalDataPool(localpool::DataPool &localDataP
|
||||
localDataPoolMap.emplace(imtq::ACTUATION_CAL_STATUS, new PoolEntry<uint8_t>({0}));
|
||||
localDataPoolMap.emplace(imtq::MTM_RAW, new PoolEntry<float>({0.12, 0.76, -0.45}, true));
|
||||
localDataPoolMap.emplace(imtq::ACTUATION_RAW_STATUS, new PoolEntry<uint8_t>({0}));
|
||||
localDataPoolMap.emplace(imtq::DIPOLES_ID, new PoolEntry<int16_t>({0, 0, 0}));
|
||||
localDataPoolMap.emplace(imtq::CURRENT_TORQUE_DURATION, new PoolEntry<uint16_t>({0}));
|
||||
return DeviceHandlerBase::initializeLocalDataPool(localDataPoolMap, poolManager);
|
||||
}
|
||||
|
@ -1,49 +1,20 @@
|
||||
#include "PcduHandlerDummy.h"
|
||||
|
||||
#include <fsfw/ipc/QueueFactory.h>
|
||||
#include <mission/power/gsDefs.h>
|
||||
|
||||
#include "mission/power/defs.h"
|
||||
|
||||
PcduHandlerDummy::PcduHandlerDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
|
||||
: DeviceHandlerBase(objectId, comif, comCookie), dummySwitcher(objectId, 18, 18, false) {
|
||||
PcduHandlerDummy::PcduHandlerDummy(object_id_t objectId)
|
||||
: SystemObject(objectId), manager(this, nullptr), dummySwitcher(objectId, 18, 18, false) {
|
||||
switcherLock = MutexFactory::instance()->createMutex();
|
||||
queue = QueueFactory::instance()->createMessageQueue(20);
|
||||
}
|
||||
|
||||
PcduHandlerDummy::~PcduHandlerDummy() {}
|
||||
|
||||
void PcduHandlerDummy::doStartUp() { setMode(MODE_NORMAL); }
|
||||
|
||||
void PcduHandlerDummy::doShutDown() { setMode(MODE_OFF); }
|
||||
|
||||
ReturnValue_t PcduHandlerDummy::buildNormalDeviceCommand(DeviceCommandId_t *id) {
|
||||
return NOTHING_TO_SEND;
|
||||
}
|
||||
|
||||
ReturnValue_t PcduHandlerDummy::buildTransitionDeviceCommand(DeviceCommandId_t *id) {
|
||||
return NOTHING_TO_SEND;
|
||||
}
|
||||
|
||||
ReturnValue_t PcduHandlerDummy::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
|
||||
const uint8_t *commandData,
|
||||
size_t commandDataLen) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PcduHandlerDummy::scanForReply(const uint8_t *start, size_t len,
|
||||
DeviceCommandId_t *foundId, size_t *foundLen) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PcduHandlerDummy::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void PcduHandlerDummy::fillCommandAndReplyMap() {}
|
||||
|
||||
uint32_t PcduHandlerDummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return 500; }
|
||||
|
||||
ReturnValue_t PcduHandlerDummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) {
|
||||
ReturnValue_t PcduHandlerDummy::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
@ -76,7 +47,8 @@ ReturnValue_t PcduHandlerDummy::getFuseState(uint8_t fuseNr) const {
|
||||
|
||||
uint32_t PcduHandlerDummy::getSwitchDelayMs(void) const { return dummySwitcher.getSwitchDelayMs(); }
|
||||
|
||||
void PcduHandlerDummy::performOperationHook() {
|
||||
ReturnValue_t PcduHandlerDummy::performOperation(uint8_t opCode) {
|
||||
// TODO: Handle HK messages in queue.
|
||||
SwitcherBoolArray switcherChangeCopy{};
|
||||
{
|
||||
MutexGuard mg(switcherLock);
|
||||
@ -93,4 +65,18 @@ void PcduHandlerDummy::performOperationHook() {
|
||||
switchChangeArray[idx] = false;
|
||||
}
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
object_id_t PcduHandlerDummy::getObjectId() const { return SystemObject::getObjectId(); }
|
||||
|
||||
MessageQueueId_t PcduHandlerDummy::getCommandQueue() const { return queue->getId(); }
|
||||
|
||||
dur_millis_t PcduHandlerDummy::getPeriodicOperationFrequency() const {
|
||||
// TODO: dummy value. Retrieve from intiitalize after task creation..
|
||||
return 400;
|
||||
}
|
||||
|
||||
LocalDataPoolManager* PcduHandlerDummy::getHkManagerHandle() { return &manager; }
|
||||
|
||||
LocalPoolDataSetBase* PcduHandlerDummy::getDataSetHandle(sid_t sid) { return nullptr; }
|
||||
|
@ -3,7 +3,10 @@
|
||||
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
||||
#include <fsfw/power/DummyPowerSwitcher.h>
|
||||
|
||||
class PcduHandlerDummy : public DeviceHandlerBase, public PowerSwitchIF {
|
||||
class PcduHandlerDummy : public PowerSwitchIF,
|
||||
public HasLocalDataPoolIF,
|
||||
public SystemObject,
|
||||
public ExecutableObjectIF {
|
||||
public:
|
||||
static const DeviceCommandId_t SIMPLE_COMMAND = 1;
|
||||
static const DeviceCommandId_t PERIODIC_REPLY = 2;
|
||||
@ -11,33 +14,49 @@ class PcduHandlerDummy : public DeviceHandlerBase, public PowerSwitchIF {
|
||||
static const uint8_t SIMPLE_COMMAND_DATA = 1;
|
||||
static const uint8_t PERIODIC_REPLY_DATA = 2;
|
||||
|
||||
PcduHandlerDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie);
|
||||
PcduHandlerDummy(object_id_t objectId);
|
||||
virtual ~PcduHandlerDummy();
|
||||
|
||||
protected:
|
||||
MutexIF *switcherLock;
|
||||
MessageQueueIF* queue;
|
||||
LocalDataPoolManager manager;
|
||||
MutexIF* switcherLock;
|
||||
DummyPowerSwitcher dummySwitcher;
|
||||
using SwitcherBoolArray = std::array<bool, 18>;
|
||||
|
||||
ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
SwitcherBoolArray switchChangeArray{};
|
||||
void performOperationHook() override;
|
||||
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;
|
||||
|
||||
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) override;
|
||||
|
||||
ReturnValue_t sendSwitchCommand(power::Switch_t switchNr, ReturnValue_t onOff) override;
|
||||
ReturnValue_t sendFuseOnCommand(uint8_t fuseNr) override;
|
||||
ReturnValue_t getSwitchState(power::Switch_t switchNr) const override;
|
||||
ReturnValue_t getFuseState(uint8_t fuseNr) const override;
|
||||
uint32_t getSwitchDelayMs(void) const override;
|
||||
|
||||
object_id_t getObjectId() const override;
|
||||
|
||||
/** Command queue for housekeeping messages. */
|
||||
MessageQueueId_t getCommandQueue() const override;
|
||||
|
||||
dur_millis_t getPeriodicOperationFrequency() const override;
|
||||
|
||||
/**
|
||||
* Every class implementing this interface should have a local data pool manager. This
|
||||
* function will return a reference to the manager.
|
||||
* @return
|
||||
*/
|
||||
LocalDataPoolManager* getHkManagerHandle() override;
|
||||
|
||||
/**
|
||||
* This function is used by the pool manager to get a valid dataset
|
||||
* from a SID. This function is protected to prevent users from
|
||||
* using raw data set pointers which could not be thread-safe. Users
|
||||
* should use the #ProvidesDataPoolSubscriptionIF.
|
||||
* @param sid Corresponding structure ID
|
||||
* @return
|
||||
*/
|
||||
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
|
||||
};
|
||||
|
@ -37,6 +37,9 @@ uint32_t RwDummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return
|
||||
|
||||
ReturnValue_t RwDummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) {
|
||||
localDataPoolMap.emplace(rws::RW_SPEED, &rwSpeed);
|
||||
localDataPoolMap.emplace(rws::RAMP_TIME, &rampTime);
|
||||
|
||||
localDataPoolMap.emplace(rws::TEMPERATURE_C, new PoolEntry<int32_t>({0}));
|
||||
|
||||
localDataPoolMap.emplace(rws::CURR_SPEED, new PoolEntry<int32_t>({0}));
|
||||
|
@ -15,6 +15,9 @@ class RwDummy : public DeviceHandlerBase {
|
||||
virtual ~RwDummy();
|
||||
|
||||
protected:
|
||||
PoolEntry<int32_t> rwSpeed = PoolEntry<int32_t>({0});
|
||||
PoolEntry<uint16_t> rampTime = PoolEntry<uint16_t>({10});
|
||||
|
||||
void doStartUp() override;
|
||||
void doShutDown() override;
|
||||
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;
|
||||
|
@ -64,6 +64,7 @@ ReturnValue_t StarTrackerDummy::initializeLocalDataPool(localpool::DataPool &loc
|
||||
localDataPoolMap.emplace(startracker::LISA_NR_CLOSE, new PoolEntry<uint8_t>({0}));
|
||||
localDataPoolMap.emplace(startracker::TRUST_WORTHY, new PoolEntry<uint8_t>({0}));
|
||||
localDataPoolMap.emplace(startracker::STABLE_COUNT, new PoolEntry<uint32_t>({0}));
|
||||
localDataPoolMap.emplace(startracker::STR_MODE, new PoolEntry<uint8_t>({0}));
|
||||
localDataPoolMap.emplace(startracker::SOLUTION_STRATEGY, new PoolEntry<uint8_t>({0}));
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "TemperatureSensorInserter.h"
|
||||
|
||||
#include <fsfw/datapool/PoolReadGuard.h>
|
||||
#include <objects/systemObjectList.h>
|
||||
|
||||
#include <cmath>
|
||||
@ -14,10 +15,7 @@ TemperatureSensorInserter::TemperatureSensorInserter(object_id_t objectId,
|
||||
tmp1075DummyMap(std::move(tempTmpSensorDummies_)) {}
|
||||
|
||||
ReturnValue_t TemperatureSensorInserter::initialize() {
|
||||
if (performTest) {
|
||||
if (testCase == TestCase::COOL_SYRLINKS) {
|
||||
}
|
||||
}
|
||||
testCase = TestCase::NONE;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
@ -33,35 +31,82 @@ ReturnValue_t TemperatureSensorInserter::performOperation(uint8_t opCode) {
|
||||
tempsWereInitialized = true;
|
||||
}
|
||||
|
||||
if (cycles == 10) {
|
||||
max31865DummyMap[objects::RTD_9_IC12_HPA]->setTemperature(-100, true);
|
||||
max31865DummyMap[objects::RTD_11_IC14_MPA]->setTemperature(-100, true);
|
||||
switch (testCase) {
|
||||
case (TestCase::NONE): {
|
||||
break;
|
||||
}
|
||||
case (TestCase::COLD_SYRLINKS): {
|
||||
// TODO: How do I insert this?
|
||||
// Does not work on EM, where a real syrlinks device is connected.
|
||||
if (cycles == 15) {
|
||||
lp_var_t<float> tempSyrlinksBasebandBoard =
|
||||
lp_var_t<float>(objects::SYRLINKS_HANDLER, syrlinks::TEMP_BASEBAND_BOARD);
|
||||
PoolReadGuard pg(&tempSyrlinksBasebandBoard);
|
||||
tempSyrlinksBasebandBoard.value = -50;
|
||||
}
|
||||
if (cycles == 30) {
|
||||
lp_var_t<float> tempSyrlinksBasebandBoard =
|
||||
lp_var_t<float>(objects::SYRLINKS_HANDLER, syrlinks::TEMP_BASEBAND_BOARD);
|
||||
PoolReadGuard pg(&tempSyrlinksBasebandBoard);
|
||||
tempSyrlinksBasebandBoard.value = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (TestCase::COLD_HPA): {
|
||||
if (cycles == 15) {
|
||||
sif::debug << "Setting cold HPA temperature" << std::endl;
|
||||
max31865DummyMap[objects::RTD_9_IC12_HPA]->setTemperature(-60, true);
|
||||
}
|
||||
if (cycles == 30) {
|
||||
sif::debug << "Setting HPA temperature back to normal" << std::endl;
|
||||
max31865DummyMap[objects::RTD_9_IC12_HPA]->setTemperature(0, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (TestCase::COLD_MGT): {
|
||||
if (cycles == 15) {
|
||||
sif::debug << "Setting cold MGT temperature" << std::endl;
|
||||
max31865DummyMap[objects::RTD_15_IC18_IMTQ]->setTemperature(-60, true);
|
||||
}
|
||||
if (cycles == 30) {
|
||||
sif::debug << "Setting MGT temperature back to normal" << std::endl;
|
||||
max31865DummyMap[objects::RTD_15_IC18_IMTQ]->setTemperature(0, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (TestCase::COLD_STR):
|
||||
case (TestCase::COLD_STR_CONSECUTIVE): {
|
||||
if (cycles == 15) {
|
||||
sif::debug << "Setting cold STR temperature" << std::endl;
|
||||
max31865DummyMap[objects::RTD_4_IC7_STARTRACKER]->setTemperature(-40, true);
|
||||
}
|
||||
if (cycles == 30) {
|
||||
sif::debug << "Setting STR temperature back to normal" << std::endl;
|
||||
max31865DummyMap[objects::RTD_4_IC7_STARTRACKER]->setTemperature(0, true);
|
||||
}
|
||||
if (testCase == TestCase::COLD_STR_CONSECUTIVE) {
|
||||
if (cycles == 45) {
|
||||
sif::debug << "Setting cold STR temperature again" << std::endl;
|
||||
max31865DummyMap[objects::RTD_4_IC7_STARTRACKER]->setTemperature(-40, true);
|
||||
}
|
||||
if (cycles == 60) {
|
||||
sif::debug << "Setting STR temperature back to normal again" << std::endl;
|
||||
max31865DummyMap[objects::RTD_4_IC7_STARTRACKER]->setTemperature(0, true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (TestCase::COLD_CAMERA): {
|
||||
if (cycles == 15) {
|
||||
sif::debug << "Setting cold CAM temperature" << std::endl;
|
||||
max31865DummyMap[objects::RTD_2_IC5_4K_CAMERA]->setTemperature(-40, true);
|
||||
}
|
||||
if (cycles == 30) {
|
||||
sif::debug << "Setting CAM temperature back to normal" << std::endl;
|
||||
max31865DummyMap[objects::RTD_2_IC5_4K_CAMERA]->setTemperature(0, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cycles == 35) {
|
||||
max31865DummyMap[objects::RTD_9_IC12_HPA]->setTemperature(0, true);
|
||||
max31865DummyMap[objects::RTD_11_IC14_MPA]->setTemperature(0, true);
|
||||
max31865DummyMap[objects::RTD_2_IC5_4K_CAMERA]->setTemperature(-100, true);
|
||||
}
|
||||
if (cycles == 60) {
|
||||
max31865DummyMap[objects::RTD_9_IC12_HPA]->setTemperature(-100, true);
|
||||
max31865DummyMap[objects::RTD_11_IC14_MPA]->setTemperature(0, true);
|
||||
}
|
||||
|
||||
/*
|
||||
ReturnValue_t result = max31865PlocHeatspreaderSet.read();
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "Failed to read temperature from MAX31865 dataset" << std::endl;
|
||||
}
|
||||
max31865PlocHeatspreaderSet.rtdValue = value - 5;
|
||||
max31865PlocHeatspreaderSet.temperatureCelcius = value;
|
||||
if ((iteration % 100) < 20) {
|
||||
max31865PlocHeatspreaderSet.setValidity(false, true);
|
||||
} else {
|
||||
max31865PlocHeatspreaderSet.setValidity(true, true);
|
||||
}
|
||||
max31865PlocHeatspreaderSet.commit();
|
||||
*/
|
||||
cycles++;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <fsfw/controller/ExtendedControllerBase.h>
|
||||
#include <mission/com/syrlinksDefs.h>
|
||||
#include <mission/tcs/Max31865Definitions.h>
|
||||
|
||||
#include "Max31865Dummy.h"
|
||||
@ -22,11 +23,19 @@ class TemperatureSensorInserter : public ExecutableObjectIF, public SystemObject
|
||||
private:
|
||||
Max31865DummyMap max31865DummyMap;
|
||||
Tmp1075DummyMap tmp1075DummyMap;
|
||||
enum TestCase { NONE = 0, COOL_SYRLINKS = 1 };
|
||||
|
||||
enum TestCase {
|
||||
NONE = 0,
|
||||
COLD_SYRLINKS = 1,
|
||||
COLD_HPA = 2,
|
||||
COLD_MGT = 3,
|
||||
COLD_STR = 4,
|
||||
COLD_STR_CONSECUTIVE = 5,
|
||||
COLD_CAMERA = 6,
|
||||
};
|
||||
int iteration = 0;
|
||||
uint32_t cycles = 0;
|
||||
bool tempsWereInitialized = false;
|
||||
bool performTest = false;
|
||||
TestCase testCase = TestCase::NONE;
|
||||
|
||||
// void noise();
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include <mission/system/acs/ImtqAssembly.h>
|
||||
#include <mission/system/acs/StrAssembly.h>
|
||||
#include <mission/system/objects/CamSwitcher.h>
|
||||
#include <mission/system/objects/TcsBoardAssembly.h>
|
||||
#include <mission/system/tcs/TcsBoardAssembly.h>
|
||||
|
||||
#include "TemperatureSensorInserter.h"
|
||||
#include "dummies/Max31865Dummy.h"
|
||||
@ -38,8 +38,8 @@
|
||||
#include "mission/genericFactory.h"
|
||||
#include "mission/system/acs/acsModeTree.h"
|
||||
#include "mission/system/com/comModeTree.h"
|
||||
#include "mission/system/tcs/tcsModeTree.h"
|
||||
#include "mission/system/tree/payloadModeTree.h"
|
||||
#include "mission/system/tree/tcsModeTree.h"
|
||||
#include "mission/tcs/defs.h"
|
||||
|
||||
void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpioIF) {
|
||||
@ -194,9 +194,11 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
|
||||
tmpSensorDummies.emplace(
|
||||
objects::TMP1075_HANDLER_PLPCDU_0,
|
||||
new Tmp1075Dummy(objects::TMP1075_HANDLER_PLPCDU_0, objects::DUMMY_COM_IF, comCookieDummy));
|
||||
tmpSensorDummies.emplace(
|
||||
objects::TMP1075_HANDLER_PLPCDU_1,
|
||||
new Tmp1075Dummy(objects::TMP1075_HANDLER_PLPCDU_1, objects::DUMMY_COM_IF, comCookieDummy));
|
||||
// damaged.
|
||||
// tmpSensorDummies.emplace(
|
||||
// objects::TMP1075_HANDLER_PLPCDU_1,
|
||||
// new Tmp1075Dummy(objects::TMP1075_HANDLER_PLPCDU_1, objects::DUMMY_COM_IF,
|
||||
// comCookieDummy));
|
||||
tmpSensorDummies.emplace(
|
||||
objects::TMP1075_HANDLER_IF_BOARD,
|
||||
new Tmp1075Dummy(objects::TMP1075_HANDLER_IF_BOARD, objects::DUMMY_COM_IF, comCookieDummy));
|
||||
|
2
fsfw
2
fsfw
Submodule fsfw updated: ffa2fa477f...5eb9ee8bc1
@ -86,13 +86,14 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
10802;0x2a32;SERIALIZATION_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
|
||||
10803;0x2a33;FILESTORE_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
|
||||
10804;0x2a34;FILENAME_TOO_LARGE_ERROR;LOW;P1: Transaction step ID, P2: 0 for source file name, 1 for dest file name;fsfw/src/fsfw/cfdp/handler/defs.h
|
||||
11200;0x2bc0;SAFE_RATE_VIOLATION;MEDIUM;No description;mission/acs/defs.h
|
||||
11201;0x2bc1;SAFE_RATE_RECOVERY;MEDIUM;No description;mission/acs/defs.h
|
||||
11202;0x2bc2;MULTIPLE_RW_INVALID;HIGH;No description;mission/acs/defs.h
|
||||
11203;0x2bc3;MEKF_INVALID_INFO;INFO;No description;mission/acs/defs.h
|
||||
11204;0x2bc4;MEKF_RECOVERY;INFO;No description;mission/acs/defs.h
|
||||
11205;0x2bc5;MEKF_INVALID_MODE_VIOLATION;HIGH;No description;mission/acs/defs.h
|
||||
11206;0x2bc6;SAFE_MODE_CONTROLLER_FAILURE;HIGH;No description;mission/acs/defs.h
|
||||
11200;0x2bc0;SAFE_RATE_VIOLATION;MEDIUM;The limits for the rotation in safe mode were violated.;mission/acs/defs.h
|
||||
11201;0x2bc1;SAFE_RATE_RECOVERY;MEDIUM;The system has recovered from a safe rate rotation violation.;mission/acs/defs.h
|
||||
11202;0x2bc2;MULTIPLE_RW_INVALID;HIGH;Multiple RWs are invalid, uncommandable and therefore higher ACS modes cannot be maintained.;mission/acs/defs.h
|
||||
11203;0x2bc3;MEKF_INVALID_INFO;INFO;MEKF was not able to compute a solution. P1: MEKF state on exit;mission/acs/defs.h
|
||||
11204;0x2bc4;MEKF_RECOVERY;INFO;MEKF is able to compute a solution again.;mission/acs/defs.h
|
||||
11205;0x2bc5;MEKF_AUTOMATIC_RESET;INFO;MEKF performed an automatic reset after detection of nonfinite values.;mission/acs/defs.h
|
||||
11206;0x2bc6;MEKF_INVALID_MODE_VIOLATION;HIGH;MEKF was not able to compute a solution during any pointing ACS mode for a prolonged time.;mission/acs/defs.h
|
||||
11207;0x2bc7;SAFE_MODE_CONTROLLER_FAILURE;HIGH;The ACS safe mode controller was not able to compute a solution and has failed. P1: Missing information about magnetic field, P2: Missing information about rotational rate;mission/acs/defs.h
|
||||
11300;0x2c24;SWITCH_CMD_SENT;INFO;Indicates that a FSFW object requested setting a switch P1: 1 if on was requested, 0 for off | P2: Switch Index;mission/power/defs.h
|
||||
11301;0x2c25;SWITCH_HAS_CHANGED;INFO;Indicated that a switch state has changed P1: New switch state, 1 for on, 0 for off | P2: Switch Index;mission/power/defs.h
|
||||
11302;0x2c26;SWITCHING_Q7S_DENIED;MEDIUM;No description;mission/power/defs.h
|
||||
@ -145,17 +146,20 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
12300;0x300c;SEND_MRAM_DUMP_FAILED;LOW;Failed to send mram dump command to supervisor handler P1: Return value of commandAction function P2: Start address of MRAM to dump with this command;linux/payload/PlocMemoryDumper.h
|
||||
12301;0x300d;MRAM_DUMP_FAILED;LOW;Received completion failure report form PLOC supervisor handler P1: MRAM start address of failing dump command;linux/payload/PlocMemoryDumper.h
|
||||
12302;0x300e;MRAM_DUMP_FINISHED;LOW;MRAM dump finished successfully;linux/payload/PlocMemoryDumper.h
|
||||
12401;0x3071;INVALID_TC_FRAME;HIGH;No description;linux/ipcore/PdecHandler.h
|
||||
12402;0x3072;INVALID_FAR;HIGH;Read invalid FAR from PDEC after startup;linux/ipcore/PdecHandler.h
|
||||
12403;0x3073;CARRIER_LOCK;INFO;Carrier lock detected;linux/ipcore/PdecHandler.h
|
||||
12404;0x3074;BIT_LOCK_PDEC;INFO;Bit lock detected (data valid);linux/ipcore/PdecHandler.h
|
||||
12405;0x3075;LOST_CARRIER_LOCK_PDEC;INFO;Lost carrier lock;linux/ipcore/PdecHandler.h
|
||||
12406;0x3076;LOST_BIT_LOCK_PDEC;INFO;Lost bit lock;linux/ipcore/PdecHandler.h
|
||||
12407;0x3077;TOO_MANY_IRQS;MEDIUM;Too many IRQs over the time window of one second. P1: Allowed TCs;linux/ipcore/PdecHandler.h
|
||||
12408;0x3078;POLL_SYSCALL_ERROR_PDEC;MEDIUM;No description;linux/ipcore/PdecHandler.h
|
||||
12409;0x3079;WRITE_SYSCALL_ERROR_PDEC;HIGH;No description;linux/ipcore/PdecHandler.h
|
||||
12410;0x307a;PDEC_RESET_FAILED;HIGH;Failed to pull PDEC reset to low;linux/ipcore/PdecHandler.h
|
||||
12411;0x307b;OPEN_IRQ_FILE_FAILED;HIGH;Failed to open the IRQ uio file;linux/ipcore/PdecHandler.h
|
||||
12401;0x3071;INVALID_TC_FRAME;HIGH;No description;linux/ipcore/pdec.h
|
||||
12402;0x3072;INVALID_FAR;HIGH;Read invalid FAR from PDEC after startup;linux/ipcore/pdec.h
|
||||
12403;0x3073;CARRIER_LOCK;INFO;Carrier lock detected;linux/ipcore/pdec.h
|
||||
12404;0x3074;BIT_LOCK_PDEC;INFO;Bit lock detected (data valid);linux/ipcore/pdec.h
|
||||
12405;0x3075;LOST_CARRIER_LOCK_PDEC;INFO;Lost carrier lock;linux/ipcore/pdec.h
|
||||
12406;0x3076;LOST_BIT_LOCK_PDEC;INFO;Lost bit lock;linux/ipcore/pdec.h
|
||||
12407;0x3077;TOO_MANY_IRQS;MEDIUM;Too many IRQs over the time window of one second. P1: Allowed TCs;linux/ipcore/pdec.h
|
||||
12408;0x3078;POLL_SYSCALL_ERROR_PDEC;MEDIUM;No description;linux/ipcore/pdec.h
|
||||
12409;0x3079;WRITE_SYSCALL_ERROR_PDEC;HIGH;No description;linux/ipcore/pdec.h
|
||||
12410;0x307a;PDEC_TRYING_RESET_WITH_INIT;LOW;Trying a PDEC reset with complete re-initialization;linux/ipcore/pdec.h
|
||||
12411;0x307b;PDEC_TRYING_RESET_NO_INIT;LOW;Trying a PDEC reset without re-initialization.;linux/ipcore/pdec.h
|
||||
12412;0x307c;PDEC_RESET_FAILED;HIGH;Failed to pull PDEC reset to low;linux/ipcore/pdec.h
|
||||
12413;0x307d;OPEN_IRQ_FILE_FAILED;HIGH;Failed to open the IRQ uio file;linux/ipcore/pdec.h
|
||||
12414;0x307e;PDEC_INIT_FAILED;HIGH;PDEC initialization failed. This might also be due to the persistent confiuration never becoming available, for example due to SD card issues.;linux/ipcore/pdec.h
|
||||
12500;0x30d4;IMAGE_UPLOAD_FAILED;LOW;Image upload failed;linux/acs/StrComHandler.h
|
||||
12501;0x30d5;IMAGE_DOWNLOAD_FAILED;LOW;Image download failed;linux/acs/StrComHandler.h
|
||||
12502;0x30d6;IMAGE_UPLOAD_SUCCESSFUL;LOW;Uploading image to star tracker was successfulop;linux/acs/StrComHandler.h
|
||||
@ -208,7 +212,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
12901;0x3265;NOT_ENOUGH_DEVICES_DUAL_MODE;HIGH;No description;mission/system/acs/SusAssembly.h
|
||||
12902;0x3266;POWER_STATE_MACHINE_TIMEOUT;MEDIUM;No description;mission/system/acs/SusAssembly.h
|
||||
12903;0x3267;SIDE_SWITCH_TRANSITION_NOT_ALLOWED;LOW;Not implemented, would increase already high complexity. Operator should instead command the assembly off first and then command the assembly on into the desired mode/submode combination;mission/system/acs/SusAssembly.h
|
||||
13000;0x32c8;CHILDREN_LOST_MODE;MEDIUM;No description;mission/system/objects/TcsBoardAssembly.h
|
||||
13000;0x32c8;CHILDREN_LOST_MODE;MEDIUM;No description;mission/system/tcs/TcsBoardAssembly.h
|
||||
13100;0x332c;GPS_FIX_CHANGE;INFO;Fix has changed. P1: Old fix. P2: New fix 0: Not seen, 1: No Fix, 2: 2D-Fix, 3: 3D-Fix;mission/acs/archive/GPSDefinitions.h
|
||||
13101;0x332d;CANT_GET_FIX;LOW;Could not get fix in maximum allowed time. P1: Maximum allowed time to get a fix after the GPS was switched on.;mission/acs/archive/GPSDefinitions.h
|
||||
13200;0x3390;P60_BOOT_COUNT;INFO;P60 boot count is broadcasted once at SW startup. P1: Boot count;mission/power/P60DockHandler.h
|
||||
@ -260,8 +264,9 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
14006;0x36b6;CURRENT_IMAGE_INFO;INFO;P1: Current Chip, P2: Current Copy;mission/sysDefs.h
|
||||
14007;0x36b7;REBOOT_COUNTER;INFO;Total reboot counter, which is the sum of the boot count of all individual images.;mission/sysDefs.h
|
||||
14008;0x36b8;INDIVIDUAL_BOOT_COUNTS;INFO;Get the boot count of the individual images. P1: First 16 bits boot count of image 0 0, last 16 bits boot count of image 0 1. P2: First 16 bits boot count of image 1 0, last 16 bits boot count of image 1 1.;mission/sysDefs.h
|
||||
14010;0x36ba;TRYING_I2C_RECOVERY;MEDIUM;I2C is unavailable. Trying recovery of I2C bus by power cycling all I2C devices.;mission/sysDefs.h
|
||||
14011;0x36bb;I2C_REBOOT;MEDIUM;I2C is unavailable. Recovery did not work, performing full reboot.;mission/sysDefs.h
|
||||
14010;0x36ba;TRYING_I2C_RECOVERY;HIGH;I2C is unavailable. Trying recovery of I2C bus by power cycling all I2C devices.;mission/sysDefs.h
|
||||
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
|
||||
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
|
||||
@ -269,6 +274,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
14105;0x3719;CAMERA_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
|
||||
14106;0x371a;PCDU_SYSTEM_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
|
||||
14107;0x371b;HEATER_NOT_OFF_FOR_OFF_MODE;MEDIUM;No description;mission/controller/tcsDefs.h
|
||||
14108;0x371c;MGT_OVERHEATING;MEDIUM;No description;mission/controller/tcsDefs.h
|
||||
14201;0x3779;TX_TIMER_EXPIRED;INFO;The transmit timer to protect the Syrlinks expired P1: The current timer value;mission/system/com/ComSubsystem.h
|
||||
14202;0x377a;BIT_LOCK_TX_ON;INFO;Transmitter will be turned on due to detection of bitlock;mission/system/com/ComSubsystem.h
|
||||
14300;0x37dc;POSSIBLE_FILE_CORRUPTION;LOW;P1: Result code of TM packet parser. P2: Timestamp of possibly corrupt file as a unix timestamp.;mission/persistentTmStoreDefs.h
|
||||
|
|
@ -500,7 +500,7 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path
|
||||
0x66a2;SADPL_MainSwitchTimeoutFailure;No description;162;SA_DEPL_HANDLER;mission/SolarArrayDeploymentHandler.h
|
||||
0x66a3;SADPL_SwitchingDeplSa1Failed;No description;163;SA_DEPL_HANDLER;mission/SolarArrayDeploymentHandler.h
|
||||
0x66a4;SADPL_SwitchingDeplSa2Failed;No description;164;SA_DEPL_HANDLER;mission/SolarArrayDeploymentHandler.h
|
||||
0x6900;ACSCTRL_FileDeletionFailed;No description;0;ACS_CTRL;mission/controller/AcsController.h
|
||||
0x6900;ACSCTRL_FileDeletionFailed;File deletion failed and at least one file is still existent.;0;ACS_CTRL;mission/controller/AcsController.h
|
||||
0x6a02;ACSMEKF_MekfUninitialized;No description;2;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||
0x6a03;ACSMEKF_MekfNoGyrData;No description;3;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||
0x6a04;ACSMEKF_MekfNoModelVectors;No description;4;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||
@ -509,9 +509,6 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path
|
||||
0x6a07;ACSMEKF_MekfNotFinite;No description;7;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||
0x6a08;ACSMEKF_MekfInitialized;No description;8;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||
0x6a09;ACSMEKF_MekfRunning;No description;9;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||
0x6b01;ACSSAF_SafectrlMekfInputInvalid;No description;1;ACS_SAFE;mission/controller/acs/control/SafeCtrl.h
|
||||
0x6c01;ACSPTG_PtgctrlMekfInputInvalid;No description;1;ACS_PTG;mission/controller/acs/control/PtgCtrl.h
|
||||
0x6d01;ACSDTB_DetumbleNoSensordata;No description;1;ACS_DETUMBLE;mission/controller/acs/control/Detumble.h
|
||||
0x7000;PTM_DumpDone;No description;0;PERSISTENT_TM_STORE;mission/tmtc/PersistentTmStore.h
|
||||
0x7001;PTM_BusyDumping;No description;1;PERSISTENT_TM_STORE;mission/tmtc/PersistentTmStore.h
|
||||
0x7100;TMS_IsBusy;No description;0;TM_SINK;mission/tmtc/DirectTmSinkIF.h
|
||||
0x6d00;PTM_DumpDone;No description;0;PERSISTENT_TM_STORE;mission/tmtc/PersistentTmStore.h
|
||||
0x6d01;PTM_BusyDumping;No description;1;PERSISTENT_TM_STORE;mission/tmtc/PersistentTmStore.h
|
||||
0x6e00;TMS_IsBusy;No description;0;TM_SINK;mission/tmtc/DirectTmSinkIF.h
|
||||
|
|
@ -86,13 +86,14 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
10802;0x2a32;SERIALIZATION_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
|
||||
10803;0x2a33;FILESTORE_ERROR;LOW;No description;fsfw/src/fsfw/cfdp/handler/defs.h
|
||||
10804;0x2a34;FILENAME_TOO_LARGE_ERROR;LOW;P1: Transaction step ID, P2: 0 for source file name, 1 for dest file name;fsfw/src/fsfw/cfdp/handler/defs.h
|
||||
11200;0x2bc0;SAFE_RATE_VIOLATION;MEDIUM;No description;mission/acs/defs.h
|
||||
11201;0x2bc1;SAFE_RATE_RECOVERY;MEDIUM;No description;mission/acs/defs.h
|
||||
11202;0x2bc2;MULTIPLE_RW_INVALID;HIGH;No description;mission/acs/defs.h
|
||||
11203;0x2bc3;MEKF_INVALID_INFO;INFO;No description;mission/acs/defs.h
|
||||
11204;0x2bc4;MEKF_RECOVERY;INFO;No description;mission/acs/defs.h
|
||||
11205;0x2bc5;MEKF_INVALID_MODE_VIOLATION;HIGH;No description;mission/acs/defs.h
|
||||
11206;0x2bc6;SAFE_MODE_CONTROLLER_FAILURE;HIGH;No description;mission/acs/defs.h
|
||||
11200;0x2bc0;SAFE_RATE_VIOLATION;MEDIUM;The limits for the rotation in safe mode were violated.;mission/acs/defs.h
|
||||
11201;0x2bc1;SAFE_RATE_RECOVERY;MEDIUM;The system has recovered from a safe rate rotation violation.;mission/acs/defs.h
|
||||
11202;0x2bc2;MULTIPLE_RW_INVALID;HIGH;Multiple RWs are invalid, uncommandable and therefore higher ACS modes cannot be maintained.;mission/acs/defs.h
|
||||
11203;0x2bc3;MEKF_INVALID_INFO;INFO;MEKF was not able to compute a solution. P1: MEKF state on exit;mission/acs/defs.h
|
||||
11204;0x2bc4;MEKF_RECOVERY;INFO;MEKF is able to compute a solution again.;mission/acs/defs.h
|
||||
11205;0x2bc5;MEKF_AUTOMATIC_RESET;INFO;MEKF performed an automatic reset after detection of nonfinite values.;mission/acs/defs.h
|
||||
11206;0x2bc6;MEKF_INVALID_MODE_VIOLATION;HIGH;MEKF was not able to compute a solution during any pointing ACS mode for a prolonged time.;mission/acs/defs.h
|
||||
11207;0x2bc7;SAFE_MODE_CONTROLLER_FAILURE;HIGH;The ACS safe mode controller was not able to compute a solution and has failed. P1: Missing information about magnetic field, P2: Missing information about rotational rate;mission/acs/defs.h
|
||||
11300;0x2c24;SWITCH_CMD_SENT;INFO;Indicates that a FSFW object requested setting a switch P1: 1 if on was requested, 0 for off | P2: Switch Index;mission/power/defs.h
|
||||
11301;0x2c25;SWITCH_HAS_CHANGED;INFO;Indicated that a switch state has changed P1: New switch state, 1 for on, 0 for off | P2: Switch Index;mission/power/defs.h
|
||||
11302;0x2c26;SWITCHING_Q7S_DENIED;MEDIUM;No description;mission/power/defs.h
|
||||
@ -145,17 +146,20 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
12300;0x300c;SEND_MRAM_DUMP_FAILED;LOW;Failed to send mram dump command to supervisor handler P1: Return value of commandAction function P2: Start address of MRAM to dump with this command;linux/payload/PlocMemoryDumper.h
|
||||
12301;0x300d;MRAM_DUMP_FAILED;LOW;Received completion failure report form PLOC supervisor handler P1: MRAM start address of failing dump command;linux/payload/PlocMemoryDumper.h
|
||||
12302;0x300e;MRAM_DUMP_FINISHED;LOW;MRAM dump finished successfully;linux/payload/PlocMemoryDumper.h
|
||||
12401;0x3071;INVALID_TC_FRAME;HIGH;No description;linux/ipcore/PdecHandler.h
|
||||
12402;0x3072;INVALID_FAR;HIGH;Read invalid FAR from PDEC after startup;linux/ipcore/PdecHandler.h
|
||||
12403;0x3073;CARRIER_LOCK;INFO;Carrier lock detected;linux/ipcore/PdecHandler.h
|
||||
12404;0x3074;BIT_LOCK_PDEC;INFO;Bit lock detected (data valid);linux/ipcore/PdecHandler.h
|
||||
12405;0x3075;LOST_CARRIER_LOCK_PDEC;INFO;Lost carrier lock;linux/ipcore/PdecHandler.h
|
||||
12406;0x3076;LOST_BIT_LOCK_PDEC;INFO;Lost bit lock;linux/ipcore/PdecHandler.h
|
||||
12407;0x3077;TOO_MANY_IRQS;MEDIUM;Too many IRQs over the time window of one second. P1: Allowed TCs;linux/ipcore/PdecHandler.h
|
||||
12408;0x3078;POLL_SYSCALL_ERROR_PDEC;MEDIUM;No description;linux/ipcore/PdecHandler.h
|
||||
12409;0x3079;WRITE_SYSCALL_ERROR_PDEC;HIGH;No description;linux/ipcore/PdecHandler.h
|
||||
12410;0x307a;PDEC_RESET_FAILED;HIGH;Failed to pull PDEC reset to low;linux/ipcore/PdecHandler.h
|
||||
12411;0x307b;OPEN_IRQ_FILE_FAILED;HIGH;Failed to open the IRQ uio file;linux/ipcore/PdecHandler.h
|
||||
12401;0x3071;INVALID_TC_FRAME;HIGH;No description;linux/ipcore/pdec.h
|
||||
12402;0x3072;INVALID_FAR;HIGH;Read invalid FAR from PDEC after startup;linux/ipcore/pdec.h
|
||||
12403;0x3073;CARRIER_LOCK;INFO;Carrier lock detected;linux/ipcore/pdec.h
|
||||
12404;0x3074;BIT_LOCK_PDEC;INFO;Bit lock detected (data valid);linux/ipcore/pdec.h
|
||||
12405;0x3075;LOST_CARRIER_LOCK_PDEC;INFO;Lost carrier lock;linux/ipcore/pdec.h
|
||||
12406;0x3076;LOST_BIT_LOCK_PDEC;INFO;Lost bit lock;linux/ipcore/pdec.h
|
||||
12407;0x3077;TOO_MANY_IRQS;MEDIUM;Too many IRQs over the time window of one second. P1: Allowed TCs;linux/ipcore/pdec.h
|
||||
12408;0x3078;POLL_SYSCALL_ERROR_PDEC;MEDIUM;No description;linux/ipcore/pdec.h
|
||||
12409;0x3079;WRITE_SYSCALL_ERROR_PDEC;HIGH;No description;linux/ipcore/pdec.h
|
||||
12410;0x307a;PDEC_TRYING_RESET_WITH_INIT;LOW;Trying a PDEC reset with complete re-initialization;linux/ipcore/pdec.h
|
||||
12411;0x307b;PDEC_TRYING_RESET_NO_INIT;LOW;Trying a PDEC reset without re-initialization.;linux/ipcore/pdec.h
|
||||
12412;0x307c;PDEC_RESET_FAILED;HIGH;Failed to pull PDEC reset to low;linux/ipcore/pdec.h
|
||||
12413;0x307d;OPEN_IRQ_FILE_FAILED;HIGH;Failed to open the IRQ uio file;linux/ipcore/pdec.h
|
||||
12414;0x307e;PDEC_INIT_FAILED;HIGH;PDEC initialization failed. This might also be due to the persistent confiuration never becoming available, for example due to SD card issues.;linux/ipcore/pdec.h
|
||||
12500;0x30d4;IMAGE_UPLOAD_FAILED;LOW;Image upload failed;linux/acs/StrComHandler.h
|
||||
12501;0x30d5;IMAGE_DOWNLOAD_FAILED;LOW;Image download failed;linux/acs/StrComHandler.h
|
||||
12502;0x30d6;IMAGE_UPLOAD_SUCCESSFUL;LOW;Uploading image to star tracker was successfulop;linux/acs/StrComHandler.h
|
||||
@ -208,7 +212,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
12901;0x3265;NOT_ENOUGH_DEVICES_DUAL_MODE;HIGH;No description;mission/system/acs/SusAssembly.h
|
||||
12902;0x3266;POWER_STATE_MACHINE_TIMEOUT;MEDIUM;No description;mission/system/acs/SusAssembly.h
|
||||
12903;0x3267;SIDE_SWITCH_TRANSITION_NOT_ALLOWED;LOW;Not implemented, would increase already high complexity. Operator should instead command the assembly off first and then command the assembly on into the desired mode/submode combination;mission/system/acs/SusAssembly.h
|
||||
13000;0x32c8;CHILDREN_LOST_MODE;MEDIUM;No description;mission/system/objects/TcsBoardAssembly.h
|
||||
13000;0x32c8;CHILDREN_LOST_MODE;MEDIUM;No description;mission/system/tcs/TcsBoardAssembly.h
|
||||
13100;0x332c;GPS_FIX_CHANGE;INFO;Fix has changed. P1: Old fix. P2: New fix 0: Not seen, 1: No Fix, 2: 2D-Fix, 3: 3D-Fix;mission/acs/archive/GPSDefinitions.h
|
||||
13101;0x332d;CANT_GET_FIX;LOW;Could not get fix in maximum allowed time. P1: Maximum allowed time to get a fix after the GPS was switched on.;mission/acs/archive/GPSDefinitions.h
|
||||
13200;0x3390;P60_BOOT_COUNT;INFO;P60 boot count is broadcasted once at SW startup. P1: Boot count;mission/power/P60DockHandler.h
|
||||
@ -260,8 +264,9 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
14006;0x36b6;CURRENT_IMAGE_INFO;INFO;P1: Current Chip, P2: Current Copy;mission/sysDefs.h
|
||||
14007;0x36b7;REBOOT_COUNTER;INFO;Total reboot counter, which is the sum of the boot count of all individual images.;mission/sysDefs.h
|
||||
14008;0x36b8;INDIVIDUAL_BOOT_COUNTS;INFO;Get the boot count of the individual images. P1: First 16 bits boot count of image 0 0, last 16 bits boot count of image 0 1. P2: First 16 bits boot count of image 1 0, last 16 bits boot count of image 1 1.;mission/sysDefs.h
|
||||
14010;0x36ba;TRYING_I2C_RECOVERY;MEDIUM;I2C is unavailable. Trying recovery of I2C bus by power cycling all I2C devices.;mission/sysDefs.h
|
||||
14011;0x36bb;I2C_REBOOT;MEDIUM;I2C is unavailable. Recovery did not work, performing full reboot.;mission/sysDefs.h
|
||||
14010;0x36ba;TRYING_I2C_RECOVERY;HIGH;I2C is unavailable. Trying recovery of I2C bus by power cycling all I2C devices.;mission/sysDefs.h
|
||||
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
|
||||
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
|
||||
@ -269,6 +274,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
14105;0x3719;CAMERA_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
|
||||
14106;0x371a;PCDU_SYSTEM_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
|
||||
14107;0x371b;HEATER_NOT_OFF_FOR_OFF_MODE;MEDIUM;No description;mission/controller/tcsDefs.h
|
||||
14108;0x371c;MGT_OVERHEATING;MEDIUM;No description;mission/controller/tcsDefs.h
|
||||
14201;0x3779;TX_TIMER_EXPIRED;INFO;The transmit timer to protect the Syrlinks expired P1: The current timer value;mission/system/com/ComSubsystem.h
|
||||
14202;0x377a;BIT_LOCK_TX_ON;INFO;Transmitter will be turned on due to detection of bitlock;mission/system/com/ComSubsystem.h
|
||||
14300;0x37dc;POSSIBLE_FILE_CORRUPTION;LOW;P1: Result code of TM packet parser. P2: Timestamp of possibly corrupt file as a unix timestamp.;mission/persistentTmStoreDefs.h
|
||||
|
|
@ -517,21 +517,21 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path
|
||||
0x5d05;GOMS_UnknownReplyId;No description;5;GOM_SPACE_HANDLER;mission/power/GomspaceDeviceHandler.h
|
||||
0x5ea0;PLMEMDUMP_MramAddressTooHigh;The capacity of the MRAM amounts to 512 kB. Thus the maximum address must not be higher than 0x7d000.;160;PLOC_MEMORY_DUMPER;linux/payload/PlocMemoryDumper.h
|
||||
0x5ea1;PLMEMDUMP_MramInvalidAddressCombination;The specified end address is lower than the start address;161;PLOC_MEMORY_DUMPER;linux/payload/PlocMemoryDumper.h
|
||||
0x5fa0;PDEC_AbandonedCltuRetval;No description;160;PDEC_HANDLER;linux/ipcore/PdecHandler.h
|
||||
0x5fa1;PDEC_FrameDirtyRetval;No description;161;PDEC_HANDLER;linux/ipcore/PdecHandler.h
|
||||
0x5fa2;PDEC_FrameIllegalMultipleReasons;No description;162;PDEC_HANDLER;linux/ipcore/PdecHandler.h
|
||||
0x5fa3;PDEC_AdDiscardedLockoutRetval;No description;163;PDEC_HANDLER;linux/ipcore/PdecHandler.h
|
||||
0x5fa4;PDEC_AdDiscardedWaitRetval;No description;164;PDEC_HANDLER;linux/ipcore/PdecHandler.h
|
||||
0x5fa5;PDEC_AdDiscardedNsVs;No description;165;PDEC_HANDLER;linux/ipcore/PdecHandler.h
|
||||
0x5fa6;PDEC_NoReportRetval;No description;166;PDEC_HANDLER;linux/ipcore/PdecHandler.h
|
||||
0x5fa7;PDEC_ErrorVersionNumberRetval;No description;167;PDEC_HANDLER;linux/ipcore/PdecHandler.h
|
||||
0x5fa8;PDEC_IllegalCombinationRetval;No description;168;PDEC_HANDLER;linux/ipcore/PdecHandler.h
|
||||
0x5fa9;PDEC_InvalidScIdRetval;No description;169;PDEC_HANDLER;linux/ipcore/PdecHandler.h
|
||||
0x5faa;PDEC_InvalidVcIdMsbRetval;No description;170;PDEC_HANDLER;linux/ipcore/PdecHandler.h
|
||||
0x5fab;PDEC_InvalidVcIdLsbRetval;No description;171;PDEC_HANDLER;linux/ipcore/PdecHandler.h
|
||||
0x5fac;PDEC_NsNotZeroRetval;No description;172;PDEC_HANDLER;linux/ipcore/PdecHandler.h
|
||||
0x5fae;PDEC_InvalidBcCc;No description;174;PDEC_HANDLER;linux/ipcore/PdecHandler.h
|
||||
0x5fb0;PDEC_CommandNotImplemented;Received action message with unknown action id;176;PDEC_HANDLER;linux/ipcore/PdecHandler.h
|
||||
0x5fa0;PDEC_AbandonedCltuRetval;No description;160;PDEC_HANDLER;linux/ipcore/pdec.h
|
||||
0x5fa1;PDEC_FrameDirtyRetval;No description;161;PDEC_HANDLER;linux/ipcore/pdec.h
|
||||
0x5fa2;PDEC_FrameIllegalMultipleReasons;No description;162;PDEC_HANDLER;linux/ipcore/pdec.h
|
||||
0x5fa3;PDEC_AdDiscardedLockoutRetval;No description;163;PDEC_HANDLER;linux/ipcore/pdec.h
|
||||
0x5fa4;PDEC_AdDiscardedWaitRetval;No description;164;PDEC_HANDLER;linux/ipcore/pdec.h
|
||||
0x5fa5;PDEC_AdDiscardedNsVs;No description;165;PDEC_HANDLER;linux/ipcore/pdec.h
|
||||
0x5fa6;PDEC_NoReportRetval;No description;166;PDEC_HANDLER;linux/ipcore/pdec.h
|
||||
0x5fa7;PDEC_ErrorVersionNumberRetval;No description;167;PDEC_HANDLER;linux/ipcore/pdec.h
|
||||
0x5fa8;PDEC_IllegalCombinationRetval;No description;168;PDEC_HANDLER;linux/ipcore/pdec.h
|
||||
0x5fa9;PDEC_InvalidScIdRetval;No description;169;PDEC_HANDLER;linux/ipcore/pdec.h
|
||||
0x5faa;PDEC_InvalidVcIdMsbRetval;No description;170;PDEC_HANDLER;linux/ipcore/pdec.h
|
||||
0x5fab;PDEC_InvalidVcIdLsbRetval;No description;171;PDEC_HANDLER;linux/ipcore/pdec.h
|
||||
0x5fac;PDEC_NsNotZeroRetval;No description;172;PDEC_HANDLER;linux/ipcore/pdec.h
|
||||
0x5fae;PDEC_InvalidBcCc;No description;174;PDEC_HANDLER;linux/ipcore/pdec.h
|
||||
0x5fb0;PDEC_CommandNotImplemented;Received action message with unknown action id;176;PDEC_HANDLER;linux/ipcore/pdec.h
|
||||
0x60a0;CCSDS_CommandNotImplemented;Received action message with unknown action id;160;CCSDS_HANDLER;mission/com/CcsdsIpCoreHandler.h
|
||||
0x61a0;RS_RateNotSupported;The commanded rate is not supported by the current FPGA design;160;RATE_SETTER;linux/ipcore/PtmeConfig.h
|
||||
0x61a1;RS_BadBitRate;Bad bitrate has been commanded (e.g. 0);161;RATE_SETTER;linux/ipcore/PtmeConfig.h
|
||||
@ -583,7 +583,7 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path
|
||||
0x68b5;SPVRTVIF_SupvHelperExecuting;Supervisor helper task ist currently executing a command (wait until helper tas has finished or interrupt by sending the terminate command);181;SUPV_RETURN_VALUES_IF;linux/payload/plocSupvDefs.h
|
||||
0x68c0;SPVRTVIF_BufTooSmall;No description;192;SUPV_RETURN_VALUES_IF;linux/payload/plocSupvDefs.h
|
||||
0x68c1;SPVRTVIF_NoReplyTimeout;No description;193;SUPV_RETURN_VALUES_IF;linux/payload/plocSupvDefs.h
|
||||
0x6900;ACSCTRL_FileDeletionFailed;No description;0;ACS_CTRL;mission/controller/AcsController.h
|
||||
0x6900;ACSCTRL_FileDeletionFailed;File deletion failed and at least one file is still existent.;0;ACS_CTRL;mission/controller/AcsController.h
|
||||
0x6a02;ACSMEKF_MekfUninitialized;No description;2;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||
0x6a03;ACSMEKF_MekfNoGyrData;No description;3;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||
0x6a04;ACSMEKF_MekfNoModelVectors;No description;4;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||
@ -592,21 +592,18 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path
|
||||
0x6a07;ACSMEKF_MekfNotFinite;No description;7;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||
0x6a08;ACSMEKF_MekfInitialized;No description;8;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||
0x6a09;ACSMEKF_MekfRunning;No description;9;ACS_MEKF;mission/controller/acs/MultiplicativeKalmanFilter.h
|
||||
0x6b01;ACSSAF_SafectrlMekfInputInvalid;No description;1;ACS_SAFE;mission/controller/acs/control/SafeCtrl.h
|
||||
0x6c01;ACSPTG_PtgctrlMekfInputInvalid;No description;1;ACS_PTG;mission/controller/acs/control/PtgCtrl.h
|
||||
0x6d01;ACSDTB_DetumbleNoSensordata;No description;1;ACS_DETUMBLE;mission/controller/acs/control/Detumble.h
|
||||
0x6e00;SDMA_OpOngoing;No description;0;SD_CARD_MANAGER;bsp_q7s/fs/SdCardManager.h
|
||||
0x6e01;SDMA_AlreadyOn;No description;1;SD_CARD_MANAGER;bsp_q7s/fs/SdCardManager.h
|
||||
0x6e02;SDMA_AlreadyMounted;No description;2;SD_CARD_MANAGER;bsp_q7s/fs/SdCardManager.h
|
||||
0x6e03;SDMA_AlreadyOff;No description;3;SD_CARD_MANAGER;bsp_q7s/fs/SdCardManager.h
|
||||
0x6e0a;SDMA_StatusFileNexists;No description;10;SD_CARD_MANAGER;bsp_q7s/fs/SdCardManager.h
|
||||
0x6e0b;SDMA_StatusFileFormatInvalid;No description;11;SD_CARD_MANAGER;bsp_q7s/fs/SdCardManager.h
|
||||
0x6e0c;SDMA_MountError;No description;12;SD_CARD_MANAGER;bsp_q7s/fs/SdCardManager.h
|
||||
0x6e0d;SDMA_UnmountError;No description;13;SD_CARD_MANAGER;bsp_q7s/fs/SdCardManager.h
|
||||
0x6e0e;SDMA_SystemCallError;No description;14;SD_CARD_MANAGER;bsp_q7s/fs/SdCardManager.h
|
||||
0x6e0f;SDMA_PopenCallError;No description;15;SD_CARD_MANAGER;bsp_q7s/fs/SdCardManager.h
|
||||
0x6f00;LPH_SdNotReady;No description;0;LOCAL_PARAM_HANDLER;bsp_q7s/memory/LocalParameterHandler.h
|
||||
0x7000;PTM_DumpDone;No description;0;PERSISTENT_TM_STORE;mission/tmtc/PersistentTmStore.h
|
||||
0x7001;PTM_BusyDumping;No description;1;PERSISTENT_TM_STORE;mission/tmtc/PersistentTmStore.h
|
||||
0x7100;TMS_IsBusy;No description;0;TM_SINK;mission/tmtc/DirectTmSinkIF.h
|
||||
0x7300;SCBU_KeyNotFound;No description;0;SCRATCH_BUFFER;bsp_q7s/memory/scratchApi.h
|
||||
0x6b00;SDMA_OpOngoing;No description;0;SD_CARD_MANAGER;bsp_q7s/fs/SdCardManager.h
|
||||
0x6b01;SDMA_AlreadyOn;No description;1;SD_CARD_MANAGER;bsp_q7s/fs/SdCardManager.h
|
||||
0x6b02;SDMA_AlreadyMounted;No description;2;SD_CARD_MANAGER;bsp_q7s/fs/SdCardManager.h
|
||||
0x6b03;SDMA_AlreadyOff;No description;3;SD_CARD_MANAGER;bsp_q7s/fs/SdCardManager.h
|
||||
0x6b0a;SDMA_StatusFileNexists;No description;10;SD_CARD_MANAGER;bsp_q7s/fs/SdCardManager.h
|
||||
0x6b0b;SDMA_StatusFileFormatInvalid;No description;11;SD_CARD_MANAGER;bsp_q7s/fs/SdCardManager.h
|
||||
0x6b0c;SDMA_MountError;No description;12;SD_CARD_MANAGER;bsp_q7s/fs/SdCardManager.h
|
||||
0x6b0d;SDMA_UnmountError;No description;13;SD_CARD_MANAGER;bsp_q7s/fs/SdCardManager.h
|
||||
0x6b0e;SDMA_SystemCallError;No description;14;SD_CARD_MANAGER;bsp_q7s/fs/SdCardManager.h
|
||||
0x6b0f;SDMA_PopenCallError;No description;15;SD_CARD_MANAGER;bsp_q7s/fs/SdCardManager.h
|
||||
0x6c00;LPH_SdNotReady;No description;0;LOCAL_PARAM_HANDLER;bsp_q7s/memory/LocalParameterHandler.h
|
||||
0x6d00;PTM_DumpDone;No description;0;PERSISTENT_TM_STORE;mission/tmtc/PersistentTmStore.h
|
||||
0x6d01;PTM_BusyDumping;No description;1;PERSISTENT_TM_STORE;mission/tmtc/PersistentTmStore.h
|
||||
0x6e00;TMS_IsBusy;No description;0;TM_SINK;mission/tmtc/DirectTmSinkIF.h
|
||||
0x7000;SCBU_KeyNotFound;No description;0;SCRATCH_BUFFER;bsp_q7s/memory/scratchApi.h
|
||||
|
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @brief Auto-generated event translation file. Contains 285 translations.
|
||||
* @brief Auto-generated event translation file. Contains 291 translations.
|
||||
* @details
|
||||
* Generated on: 2023-04-07 17:42:57
|
||||
* Generated on: 2023-04-17 11:34:19
|
||||
*/
|
||||
#include "translateEvents.h"
|
||||
|
||||
@ -97,6 +97,7 @@ const char *SAFE_RATE_RECOVERY_STRING = "SAFE_RATE_RECOVERY";
|
||||
const char *MULTIPLE_RW_INVALID_STRING = "MULTIPLE_RW_INVALID";
|
||||
const char *MEKF_INVALID_INFO_STRING = "MEKF_INVALID_INFO";
|
||||
const char *MEKF_RECOVERY_STRING = "MEKF_RECOVERY";
|
||||
const char *MEKF_AUTOMATIC_RESET_STRING = "MEKF_AUTOMATIC_RESET";
|
||||
const char *MEKF_INVALID_MODE_VIOLATION_STRING = "MEKF_INVALID_MODE_VIOLATION";
|
||||
const char *SAFE_MODE_CONTROLLER_FAILURE_STRING = "SAFE_MODE_CONTROLLER_FAILURE";
|
||||
const char *SWITCH_CMD_SENT_STRING = "SWITCH_CMD_SENT";
|
||||
@ -160,8 +161,11 @@ const char *LOST_BIT_LOCK_PDEC_STRING = "LOST_BIT_LOCK_PDEC";
|
||||
const char *TOO_MANY_IRQS_STRING = "TOO_MANY_IRQS";
|
||||
const char *POLL_SYSCALL_ERROR_PDEC_STRING = "POLL_SYSCALL_ERROR_PDEC";
|
||||
const char *WRITE_SYSCALL_ERROR_PDEC_STRING = "WRITE_SYSCALL_ERROR_PDEC";
|
||||
const char *PDEC_TRYING_RESET_WITH_INIT_STRING = "PDEC_TRYING_RESET_WITH_INIT";
|
||||
const char *PDEC_TRYING_RESET_NO_INIT_STRING = "PDEC_TRYING_RESET_NO_INIT";
|
||||
const char *PDEC_RESET_FAILED_STRING = "PDEC_RESET_FAILED";
|
||||
const char *OPEN_IRQ_FILE_FAILED_STRING = "OPEN_IRQ_FILE_FAILED";
|
||||
const char *PDEC_INIT_FAILED_STRING = "PDEC_INIT_FAILED";
|
||||
const char *IMAGE_UPLOAD_FAILED_STRING = "IMAGE_UPLOAD_FAILED";
|
||||
const char *IMAGE_DOWNLOAD_FAILED_STRING = "IMAGE_DOWNLOAD_FAILED";
|
||||
const char *IMAGE_UPLOAD_SUCCESSFUL_STRING = "IMAGE_UPLOAD_SUCCESSFUL";
|
||||
@ -268,6 +272,7 @@ const char *REBOOT_COUNTER_STRING = "REBOOT_COUNTER";
|
||||
const char *INDIVIDUAL_BOOT_COUNTS_STRING = "INDIVIDUAL_BOOT_COUNTS";
|
||||
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 *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";
|
||||
@ -275,6 +280,7 @@ const char *OBC_OVERHEATING_STRING = "OBC_OVERHEATING";
|
||||
const char *CAMERA_OVERHEATING_STRING = "CAMERA_OVERHEATING";
|
||||
const char *PCDU_SYSTEM_OVERHEATING_STRING = "PCDU_SYSTEM_OVERHEATING";
|
||||
const char *HEATER_NOT_OFF_FOR_OFF_MODE_STRING = "HEATER_NOT_OFF_FOR_OFF_MODE";
|
||||
const char *MGT_OVERHEATING_STRING = "MGT_OVERHEATING";
|
||||
const char *TX_TIMER_EXPIRED_STRING = "TX_TIMER_EXPIRED";
|
||||
const char *BIT_LOCK_TX_ON_STRING = "BIT_LOCK_TX_ON";
|
||||
const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION";
|
||||
@ -478,8 +484,10 @@ const char *translateEvents(Event event) {
|
||||
case (11204):
|
||||
return MEKF_RECOVERY_STRING;
|
||||
case (11205):
|
||||
return MEKF_INVALID_MODE_VIOLATION_STRING;
|
||||
return MEKF_AUTOMATIC_RESET_STRING;
|
||||
case (11206):
|
||||
return MEKF_INVALID_MODE_VIOLATION_STRING;
|
||||
case (11207):
|
||||
return SAFE_MODE_CONTROLLER_FAILURE_STRING;
|
||||
case (11300):
|
||||
return SWITCH_CMD_SENT_STRING;
|
||||
@ -604,9 +612,15 @@ const char *translateEvents(Event event) {
|
||||
case (12409):
|
||||
return WRITE_SYSCALL_ERROR_PDEC_STRING;
|
||||
case (12410):
|
||||
return PDEC_RESET_FAILED_STRING;
|
||||
return PDEC_TRYING_RESET_WITH_INIT_STRING;
|
||||
case (12411):
|
||||
return PDEC_TRYING_RESET_NO_INIT_STRING;
|
||||
case (12412):
|
||||
return PDEC_RESET_FAILED_STRING;
|
||||
case (12413):
|
||||
return OPEN_IRQ_FILE_FAILED_STRING;
|
||||
case (12414):
|
||||
return PDEC_INIT_FAILED_STRING;
|
||||
case (12500):
|
||||
return IMAGE_UPLOAD_FAILED_STRING;
|
||||
case (12501):
|
||||
@ -819,6 +833,8 @@ const char *translateEvents(Event event) {
|
||||
return TRYING_I2C_RECOVERY_STRING;
|
||||
case (14011):
|
||||
return I2C_REBOOT_STRING;
|
||||
case (14012):
|
||||
return PDEC_REBOOT_STRING;
|
||||
case (14100):
|
||||
return NO_VALID_SENSOR_TEMPERATURE_STRING;
|
||||
case (14101):
|
||||
@ -833,6 +849,8 @@ const char *translateEvents(Event event) {
|
||||
return PCDU_SYSTEM_OVERHEATING_STRING;
|
||||
case (14107):
|
||||
return HEATER_NOT_OFF_FOR_OFF_MODE_STRING;
|
||||
case (14108):
|
||||
return MGT_OVERHEATING_STRING;
|
||||
case (14201):
|
||||
return TX_TIMER_EXPIRED_STRING;
|
||||
case (14202):
|
||||
|
@ -2,7 +2,7 @@
|
||||
* @brief Auto-generated object translation file.
|
||||
* @details
|
||||
* Contains 175 translations.
|
||||
* Generated on: 2023-04-07 17:42:57
|
||||
* Generated on: 2023-04-17 11:34:19
|
||||
*/
|
||||
#include "translateObjects.h"
|
||||
|
||||
|
@ -17,8 +17,8 @@
|
||||
#include <mission/payload/ScexDeviceHandler.h>
|
||||
#include <mission/system/acs/SusAssembly.h>
|
||||
#include <mission/system/acs/SusFdir.h>
|
||||
#include <mission/system/fdir/RtdFdir.h>
|
||||
#include <mission/system/objects/TcsBoardAssembly.h>
|
||||
#include <mission/system/tcs/RtdFdir.h>
|
||||
#include <mission/system/tcs/TcsBoardAssembly.h>
|
||||
#include <mission/tcs/Max31865EiveHandler.h>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
@ -27,8 +27,8 @@
|
||||
#include "devices/gpioIds.h"
|
||||
#include "eive/definitions.h"
|
||||
#include "mission/system/acs/acsModeTree.h"
|
||||
#include "mission/system/tcs/tcsModeTree.h"
|
||||
#include "mission/system/tree/payloadModeTree.h"
|
||||
#include "mission/system/tree/tcsModeTree.h"
|
||||
#include "mission/tcs/defs.h"
|
||||
|
||||
void ObjectFactory::createSunSensorComponents(GpioIF* gpioComIF, SpiComIF* spiComIF,
|
||||
|
@ -122,13 +122,14 @@ ReturnValue_t AcsBoardPolling::sendMessage(CookieIF* cookie, const uint8_t* send
|
||||
} else {
|
||||
sif::warning << "AcsBoardPolling: Unknown ADIS type" << std::endl;
|
||||
}
|
||||
adis.replyResult = returnvalue::FAILED;
|
||||
adis.performStartup = true;
|
||||
} else if (req->mode == acs::SimpleSensorMode::OFF) {
|
||||
adis.performStartup = false;
|
||||
adis.ownReply.cfgWasSet = false;
|
||||
adis.ownReply.dataWasSet = false;
|
||||
adis.replyResult = returnvalue::OK;
|
||||
}
|
||||
adis.replyResult = returnvalue::FAILED;
|
||||
adis.mode = req->mode;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
@ -144,10 +145,11 @@ ReturnValue_t AcsBoardPolling::sendMessage(CookieIF* cookie, const uint8_t* send
|
||||
if (req->mode == acs::SimpleSensorMode::NORMAL) {
|
||||
std::memcpy(gyro.sensorCfg, req->ctrlRegs, 5);
|
||||
gyro.performStartup = true;
|
||||
gyro.replyResult = returnvalue::FAILED;
|
||||
} else {
|
||||
gyro.ownReply.cfgWasSet = false;
|
||||
gyro.replyResult = returnvalue::OK;
|
||||
}
|
||||
gyro.replyResult = returnvalue::FAILED;
|
||||
gyro.mode = req->mode;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
@ -162,11 +164,12 @@ ReturnValue_t AcsBoardPolling::sendMessage(CookieIF* cookie, const uint8_t* send
|
||||
if (req->mode != mgm.mode) {
|
||||
if (req->mode == acs::SimpleSensorMode::NORMAL) {
|
||||
mgm.performStartup = true;
|
||||
mgm.replyResult = returnvalue::FAILED;
|
||||
} else {
|
||||
mgm.ownReply.dataWasSet = false;
|
||||
mgm.replyResult = returnvalue::OK;
|
||||
mgm.ownReply.temperatureWasSet = false;
|
||||
}
|
||||
mgm.replyResult = returnvalue::FAILED;
|
||||
mgm.mode = req->mode;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
@ -181,10 +184,11 @@ ReturnValue_t AcsBoardPolling::sendMessage(CookieIF* cookie, const uint8_t* send
|
||||
if (req->mode != mgm.mode) {
|
||||
if (req->mode == acs::SimpleSensorMode::NORMAL) {
|
||||
mgm.performStartup = true;
|
||||
mgm.replyResult = returnvalue::FAILED;
|
||||
} else {
|
||||
mgm.ownReply.dataWasRead = false;
|
||||
mgm.replyResult = returnvalue::OK;
|
||||
}
|
||||
mgm.replyResult = returnvalue::FAILED;
|
||||
mgm.mode = req->mode;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
|
@ -1,6 +1,10 @@
|
||||
target_sources(
|
||||
${OBSW_NAME} PUBLIC AcsBoardPolling.cpp ImtqPollingTask.cpp RwPollingTask.cpp
|
||||
SusPolling.cpp StrComHandler.cpp)
|
||||
target_sources(${OBSW_NAME} PUBLIC AcsBoardPolling.cpp ImtqPollingTask.cpp
|
||||
RwPollingTask.cpp SusPolling.cpp)
|
||||
|
||||
# Dependency on proprietary library
|
||||
if(TGT_BSP MATCHES "arm/q7s")
|
||||
target_sources(${OBSW_NAME} PUBLIC StrComHandler.cpp)
|
||||
endif()
|
||||
|
||||
if(EIVE_BUILD_GPSD_GPS_HANDLER)
|
||||
target_sources(${OBSW_NAME} PRIVATE GpsHyperionLinuxController.cpp)
|
||||
|
@ -17,6 +17,10 @@
|
||||
#include "mission/utility/ProgressPrinter.h"
|
||||
#include "mission/utility/Timestamp.h"
|
||||
|
||||
extern "C" {
|
||||
#include <sagitta/client/actionreq.h>
|
||||
}
|
||||
|
||||
using namespace returnvalue;
|
||||
|
||||
StrComHandler::StrComHandler(object_id_t objectId) : SystemObject(objectId) {
|
||||
@ -89,7 +93,7 @@ ReturnValue_t StrComHandler::performOperation(uint8_t operationCode) {
|
||||
break;
|
||||
}
|
||||
case InternalState::FIRMWARE_UPDATE: {
|
||||
replyTimeout.setTimeout(200);
|
||||
replyTimeout.setTimeout(2000);
|
||||
resetReplyHandlingState();
|
||||
result = performFirmwareUpdate();
|
||||
if (result == returnvalue::OK) {
|
||||
@ -125,6 +129,7 @@ ReturnValue_t StrComHandler::startImageUpload(std::string fullname) {
|
||||
}
|
||||
{
|
||||
MutexGuard mg(lock);
|
||||
replyWasReceived = false;
|
||||
state = InternalState::UPLOAD_IMAGE;
|
||||
}
|
||||
semaphore.release();
|
||||
@ -151,6 +156,7 @@ ReturnValue_t StrComHandler::startImageDownload(std::string path) {
|
||||
downloadImage.path = path;
|
||||
{
|
||||
MutexGuard mg(lock);
|
||||
replyWasReceived = false;
|
||||
state = InternalState::DOWNLOAD_IMAGE;
|
||||
}
|
||||
terminate = false;
|
||||
@ -187,6 +193,7 @@ ReturnValue_t StrComHandler::startFirmwareUpdate(std::string fullname) {
|
||||
flashWrite.lastRegion = static_cast<uint8_t>(startracker::FirmwareRegions::LAST);
|
||||
{
|
||||
MutexGuard mg(lock);
|
||||
replyWasReceived = false;
|
||||
state = InternalState::FIRMWARE_UPDATE;
|
||||
}
|
||||
semaphore.release();
|
||||
@ -216,6 +223,7 @@ ReturnValue_t StrComHandler::startFlashRead(std::string path, uint8_t startRegio
|
||||
flashRead.size = length;
|
||||
{
|
||||
MutexGuard mg(lock);
|
||||
replyWasReceived = false;
|
||||
state = InternalState::FLASH_READ;
|
||||
}
|
||||
semaphore.release();
|
||||
@ -301,6 +309,7 @@ ReturnValue_t StrComHandler::performImageUpload() {
|
||||
uint32_t imageSize = 0;
|
||||
struct UploadActionRequest uploadReq;
|
||||
uploadReq.position = 0;
|
||||
size_t writtenBytes = 0;
|
||||
#ifdef XIPHOS_Q7S
|
||||
if (not sdcMan->getActiveSdCard()) {
|
||||
return HasFileSystemIF::FILESYSTEM_INACTIVE;
|
||||
@ -323,7 +332,9 @@ ReturnValue_t StrComHandler::performImageUpload() {
|
||||
#if OBSW_DEBUG_STARTRACKER == 1
|
||||
ProgressPrinter progressPrinter("Image upload", imageSize);
|
||||
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
|
||||
while ((uploadReq.position + 1) * SIZE_IMAGE_PART < imageSize) {
|
||||
size_t fullChunks = imageSize / SIZE_IMAGE_PART;
|
||||
size_t remainder = imageSize % SIZE_IMAGE_PART;
|
||||
for (size_t idx = 0; idx < fullChunks; idx++) {
|
||||
if (terminate) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
@ -342,6 +353,7 @@ ReturnValue_t StrComHandler::performImageUpload() {
|
||||
progressPrinter.print((uploadReq.position + 1) * SIZE_IMAGE_PART);
|
||||
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
|
||||
uploadReq.position++;
|
||||
writtenBytes += SIZE_IMAGE_PART;
|
||||
|
||||
// This does a bit of delaying roughly every second
|
||||
if (uploadReq.position % 50 == 0) {
|
||||
@ -349,20 +361,20 @@ ReturnValue_t StrComHandler::performImageUpload() {
|
||||
TaskFactory::delayTask(2);
|
||||
}
|
||||
}
|
||||
std::memset(uploadReq.data, 0, sizeof(uploadReq.data));
|
||||
uint32_t remainder = imageSize - uploadReq.position * SIZE_IMAGE_PART;
|
||||
file.seekg(uploadReq.position * SIZE_IMAGE_PART, file.beg);
|
||||
file.read(reinterpret_cast<char*>(uploadReq.data), remainder);
|
||||
file.close();
|
||||
uploadReq.position++;
|
||||
arc_pack_upload_action_req(&uploadReq, cmdBuf.data(), &size);
|
||||
result = sendAndRead(size, uploadReq.position);
|
||||
if (result != returnvalue::OK) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
result = checkActionReply(replyLen);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
if (remainder > 0) {
|
||||
std::memset(uploadReq.data, 0, sizeof(uploadReq.data));
|
||||
file.seekg(fullChunks * SIZE_IMAGE_PART, file.beg);
|
||||
file.read(reinterpret_cast<char*>(uploadReq.data), remainder);
|
||||
file.close();
|
||||
arc_pack_upload_action_req(&uploadReq, cmdBuf.data(), &size);
|
||||
result = sendAndRead(size, uploadReq.position);
|
||||
if (result != returnvalue::OK) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
result = checkActionReply(replyLen);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
#if OBSW_DEBUG_STARTRACKER == 1
|
||||
progressPrinter.print((uploadReq.position + 1) * SIZE_IMAGE_PART);
|
||||
@ -390,7 +402,8 @@ ReturnValue_t StrComHandler::performFlashWrite() {
|
||||
#endif
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
uint32_t size = 0;
|
||||
uint32_t bytesWritten = 0;
|
||||
uint32_t bytesWrittenInRegion = 0;
|
||||
size_t totalBytesWritten = 0;
|
||||
uint32_t fileSize = 0;
|
||||
|
||||
struct WriteActionRequest req;
|
||||
@ -412,20 +425,18 @@ ReturnValue_t StrComHandler::performFlashWrite() {
|
||||
ProgressPrinter progressPrinter("Flash write", fileSize);
|
||||
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
|
||||
uint32_t fileChunks = fileSize / CHUNK_SIZE;
|
||||
bytesWritten = 0;
|
||||
bytesWrittenInRegion = 0;
|
||||
req.region = flashWrite.firstRegion;
|
||||
req.length = CHUNK_SIZE;
|
||||
for (uint32_t idx = 0; idx < fileChunks; idx++) {
|
||||
if (terminate) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
file.seekg(idx * CHUNK_SIZE, file.beg);
|
||||
|
||||
auto writeNextSegment = [&](uint32_t chunkIdx) {
|
||||
file.seekg(chunkIdx * CHUNK_SIZE, file.beg);
|
||||
file.read(reinterpret_cast<char*>(req.data), CHUNK_SIZE);
|
||||
if (bytesWritten + CHUNK_SIZE > FLASH_REGION_SIZE) {
|
||||
if (bytesWrittenInRegion + CHUNK_SIZE > FLASH_REGION_SIZE) {
|
||||
req.region++;
|
||||
bytesWritten = 0;
|
||||
bytesWrittenInRegion = 0;
|
||||
}
|
||||
req.address = bytesWritten;
|
||||
req.address = bytesWrittenInRegion;
|
||||
arc_pack_write_action_req(&req, cmdBuf.data(), &size);
|
||||
result = sendAndRead(size, req.address);
|
||||
if (result != returnvalue::OK) {
|
||||
@ -435,34 +446,49 @@ ReturnValue_t StrComHandler::performFlashWrite() {
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
bytesWritten += CHUNK_SIZE;
|
||||
totalBytesWritten += CHUNK_SIZE;
|
||||
bytesWrittenInRegion += CHUNK_SIZE;
|
||||
#if OBSW_DEBUG_STARTRACKER == 1
|
||||
progressPrinter.print(idx * CHUNK_SIZE);
|
||||
progressPrinter.print(chunkIdx * CHUNK_SIZE);
|
||||
#endif /* OBSW_DEBUG_STARTRACKER == 1 */
|
||||
return result;
|
||||
};
|
||||
|
||||
for (uint32_t idx = 0; idx < fileChunks; idx++) {
|
||||
if (terminate) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
result = writeNextSegment(idx);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
if (idx % 50 == 0) {
|
||||
// Some grace time for other tasks
|
||||
TaskFactory::delayTask(2);
|
||||
}
|
||||
}
|
||||
uint32_t remainingBytes = fileSize - fileChunks * CHUNK_SIZE;
|
||||
file.seekg((fileChunks - 1) * CHUNK_SIZE, file.beg);
|
||||
file.read(reinterpret_cast<char*>(req.data), remainingBytes);
|
||||
file.close();
|
||||
if (bytesWritten + CHUNK_SIZE > FLASH_REGION_SIZE) {
|
||||
req.region++;
|
||||
bytesWritten = 0;
|
||||
}
|
||||
req.address = bytesWritten;
|
||||
req.length = remainingBytes;
|
||||
bytesWritten += remainingBytes;
|
||||
arc_pack_write_action_req(&req, cmdBuf.data(), &size);
|
||||
result = sendAndRead(size, req.address);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = checkActionReply(replyLen);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
if (remainingBytes > 0) {
|
||||
file.seekg(fileChunks * CHUNK_SIZE, file.beg);
|
||||
file.read(reinterpret_cast<char*>(req.data), remainingBytes);
|
||||
file.close();
|
||||
if (bytesWrittenInRegion + CHUNK_SIZE > FLASH_REGION_SIZE) {
|
||||
req.region++;
|
||||
bytesWrittenInRegion = 0;
|
||||
}
|
||||
req.address = bytesWrittenInRegion;
|
||||
req.length = remainingBytes;
|
||||
totalBytesWritten += CHUNK_SIZE;
|
||||
bytesWrittenInRegion += remainingBytes;
|
||||
arc_pack_write_action_req(&req, cmdBuf.data(), &size);
|
||||
result = sendAndRead(size, req.address);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = checkActionReply(replyLen);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
#if OBSW_DEBUG_STARTRACKER == 1
|
||||
progressPrinter.print(fileSize);
|
||||
|
@ -11,8 +11,6 @@
|
||||
#include "bsp_q7s/fs/SdCardManager.h"
|
||||
#endif
|
||||
|
||||
#include "arcsec/client/generated/actionreq.h"
|
||||
#include "arcsec/common/generated/tmtcstructs.h"
|
||||
#include "fsfw/devicehandlers/CookieIF.h"
|
||||
#include "fsfw/objectmanager/SystemObject.h"
|
||||
#include "fsfw/osal/linux/BinarySemaphore.h"
|
||||
@ -174,7 +172,7 @@ class StrComHandler : public SystemObject, public DeviceCommunicationIF, public
|
||||
static const uint32_t FLASH_REGION_SIZE = 0x20000;
|
||||
|
||||
struct ImageDownload {
|
||||
static const uint32_t LAST_POSITION = 4095;
|
||||
static const uint32_t LAST_POSITION = 4096;
|
||||
};
|
||||
|
||||
static const uint32_t MAX_POLLS = 10000;
|
||||
|
@ -69,11 +69,13 @@ ReturnValue_t SusPolling::sendMessage(CookieIF* cookie, const uint8_t* sendData,
|
||||
if (susDevs[susIdx].mode != susReq->mode) {
|
||||
if (susReq->mode == acs::SimpleSensorMode::NORMAL) {
|
||||
susDevs[susIdx].performStartup = true;
|
||||
susDevs[susIdx].replyResult = returnvalue::FAILED;
|
||||
} else {
|
||||
susDevs[susIdx].ownReply.cfgWasSet = false;
|
||||
susDevs[susIdx].ownReply.dataWasSet = false;
|
||||
// We are off now, but DHB wants a proper reply.
|
||||
susDevs[susIdx].replyResult = returnvalue::OK;
|
||||
}
|
||||
susDevs[susIdx].replyResult = returnvalue::FAILED;
|
||||
susDevs[susIdx].mode = susReq->mode;
|
||||
}
|
||||
if (state == InternalState::IDLE) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @brief Auto-generated event translation file. Contains 285 translations.
|
||||
* @brief Auto-generated event translation file. Contains 291 translations.
|
||||
* @details
|
||||
* Generated on: 2023-04-07 17:42:57
|
||||
* Generated on: 2023-04-17 11:34:19
|
||||
*/
|
||||
#include "translateEvents.h"
|
||||
|
||||
@ -97,6 +97,7 @@ const char *SAFE_RATE_RECOVERY_STRING = "SAFE_RATE_RECOVERY";
|
||||
const char *MULTIPLE_RW_INVALID_STRING = "MULTIPLE_RW_INVALID";
|
||||
const char *MEKF_INVALID_INFO_STRING = "MEKF_INVALID_INFO";
|
||||
const char *MEKF_RECOVERY_STRING = "MEKF_RECOVERY";
|
||||
const char *MEKF_AUTOMATIC_RESET_STRING = "MEKF_AUTOMATIC_RESET";
|
||||
const char *MEKF_INVALID_MODE_VIOLATION_STRING = "MEKF_INVALID_MODE_VIOLATION";
|
||||
const char *SAFE_MODE_CONTROLLER_FAILURE_STRING = "SAFE_MODE_CONTROLLER_FAILURE";
|
||||
const char *SWITCH_CMD_SENT_STRING = "SWITCH_CMD_SENT";
|
||||
@ -160,8 +161,11 @@ const char *LOST_BIT_LOCK_PDEC_STRING = "LOST_BIT_LOCK_PDEC";
|
||||
const char *TOO_MANY_IRQS_STRING = "TOO_MANY_IRQS";
|
||||
const char *POLL_SYSCALL_ERROR_PDEC_STRING = "POLL_SYSCALL_ERROR_PDEC";
|
||||
const char *WRITE_SYSCALL_ERROR_PDEC_STRING = "WRITE_SYSCALL_ERROR_PDEC";
|
||||
const char *PDEC_TRYING_RESET_WITH_INIT_STRING = "PDEC_TRYING_RESET_WITH_INIT";
|
||||
const char *PDEC_TRYING_RESET_NO_INIT_STRING = "PDEC_TRYING_RESET_NO_INIT";
|
||||
const char *PDEC_RESET_FAILED_STRING = "PDEC_RESET_FAILED";
|
||||
const char *OPEN_IRQ_FILE_FAILED_STRING = "OPEN_IRQ_FILE_FAILED";
|
||||
const char *PDEC_INIT_FAILED_STRING = "PDEC_INIT_FAILED";
|
||||
const char *IMAGE_UPLOAD_FAILED_STRING = "IMAGE_UPLOAD_FAILED";
|
||||
const char *IMAGE_DOWNLOAD_FAILED_STRING = "IMAGE_DOWNLOAD_FAILED";
|
||||
const char *IMAGE_UPLOAD_SUCCESSFUL_STRING = "IMAGE_UPLOAD_SUCCESSFUL";
|
||||
@ -268,6 +272,7 @@ const char *REBOOT_COUNTER_STRING = "REBOOT_COUNTER";
|
||||
const char *INDIVIDUAL_BOOT_COUNTS_STRING = "INDIVIDUAL_BOOT_COUNTS";
|
||||
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 *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";
|
||||
@ -275,6 +280,7 @@ const char *OBC_OVERHEATING_STRING = "OBC_OVERHEATING";
|
||||
const char *CAMERA_OVERHEATING_STRING = "CAMERA_OVERHEATING";
|
||||
const char *PCDU_SYSTEM_OVERHEATING_STRING = "PCDU_SYSTEM_OVERHEATING";
|
||||
const char *HEATER_NOT_OFF_FOR_OFF_MODE_STRING = "HEATER_NOT_OFF_FOR_OFF_MODE";
|
||||
const char *MGT_OVERHEATING_STRING = "MGT_OVERHEATING";
|
||||
const char *TX_TIMER_EXPIRED_STRING = "TX_TIMER_EXPIRED";
|
||||
const char *BIT_LOCK_TX_ON_STRING = "BIT_LOCK_TX_ON";
|
||||
const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION";
|
||||
@ -478,8 +484,10 @@ const char *translateEvents(Event event) {
|
||||
case (11204):
|
||||
return MEKF_RECOVERY_STRING;
|
||||
case (11205):
|
||||
return MEKF_INVALID_MODE_VIOLATION_STRING;
|
||||
return MEKF_AUTOMATIC_RESET_STRING;
|
||||
case (11206):
|
||||
return MEKF_INVALID_MODE_VIOLATION_STRING;
|
||||
case (11207):
|
||||
return SAFE_MODE_CONTROLLER_FAILURE_STRING;
|
||||
case (11300):
|
||||
return SWITCH_CMD_SENT_STRING;
|
||||
@ -604,9 +612,15 @@ const char *translateEvents(Event event) {
|
||||
case (12409):
|
||||
return WRITE_SYSCALL_ERROR_PDEC_STRING;
|
||||
case (12410):
|
||||
return PDEC_RESET_FAILED_STRING;
|
||||
return PDEC_TRYING_RESET_WITH_INIT_STRING;
|
||||
case (12411):
|
||||
return PDEC_TRYING_RESET_NO_INIT_STRING;
|
||||
case (12412):
|
||||
return PDEC_RESET_FAILED_STRING;
|
||||
case (12413):
|
||||
return OPEN_IRQ_FILE_FAILED_STRING;
|
||||
case (12414):
|
||||
return PDEC_INIT_FAILED_STRING;
|
||||
case (12500):
|
||||
return IMAGE_UPLOAD_FAILED_STRING;
|
||||
case (12501):
|
||||
@ -819,6 +833,8 @@ const char *translateEvents(Event event) {
|
||||
return TRYING_I2C_RECOVERY_STRING;
|
||||
case (14011):
|
||||
return I2C_REBOOT_STRING;
|
||||
case (14012):
|
||||
return PDEC_REBOOT_STRING;
|
||||
case (14100):
|
||||
return NO_VALID_SENSOR_TEMPERATURE_STRING;
|
||||
case (14101):
|
||||
@ -833,6 +849,8 @@ const char *translateEvents(Event event) {
|
||||
return PCDU_SYSTEM_OVERHEATING_STRING;
|
||||
case (14107):
|
||||
return HEATER_NOT_OFF_FOR_OFF_MODE_STRING;
|
||||
case (14108):
|
||||
return MGT_OVERHEATING_STRING;
|
||||
case (14201):
|
||||
return TX_TIMER_EXPIRED_STRING;
|
||||
case (14202):
|
||||
|
@ -2,7 +2,7 @@
|
||||
* @brief Auto-generated object translation file.
|
||||
* @details
|
||||
* Contains 175 translations.
|
||||
* Generated on: 2023-04-07 17:42:57
|
||||
* Generated on: 2023-04-17 11:34:19
|
||||
*/
|
||||
#include "translateObjects.h"
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
#include "fsfw/tmtcservices/TmTcMessage.h"
|
||||
#include "fsfw_hal/linux/uio/UioMapper.h"
|
||||
#include "linux/ipcore/PdecConfig.h"
|
||||
#include "pdec.h"
|
||||
|
||||
using namespace pdec;
|
||||
@ -103,21 +104,10 @@ ReturnValue_t PdecHandler::firstLoop() {
|
||||
|
||||
result = releasePdec();
|
||||
if (result != returnvalue::OK) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
// This configuration must be done while the PDEC is not held in reset.
|
||||
if (OP_MODE == Modes::IRQ) {
|
||||
// Configure interrupt mask register to enable interrupts
|
||||
*(registerBaseAddress + PDEC_IMR_OFFSET) = pdecConfig.getImrReg();
|
||||
}
|
||||
result = resetFarStatFlag();
|
||||
if (result != returnvalue::OK) {
|
||||
// Requires reconfiguration and reinitialization of PDEC
|
||||
triggerEvent(INVALID_FAR);
|
||||
return result;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
|
||||
return postResetOperation();
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::performOperation(uint8_t operationCode) {
|
||||
@ -141,10 +131,11 @@ ReturnValue_t PdecHandler::polledOperation() {
|
||||
if (newTcReceived()) {
|
||||
handleNewTc();
|
||||
}
|
||||
checkLocks();
|
||||
doPeriodicWork();
|
||||
break;
|
||||
}
|
||||
case State::PDEC_RESET: {
|
||||
triggerEvent(pdec::PDEC_TRYING_RESET_WITH_INIT);
|
||||
ReturnValue_t result = pdecToReset();
|
||||
if (result != returnvalue::OK) {
|
||||
triggerEvent(PDEC_RESET_FAILED);
|
||||
@ -165,8 +156,8 @@ ReturnValue_t PdecHandler::polledOperation() {
|
||||
// See https://yurovsky.github.io/2014/10/10/linux-uio-gpio-interrupt.html for more information.
|
||||
ReturnValue_t PdecHandler::irqOperation() {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
int fd = -1;
|
||||
// Used to unmask IRQ
|
||||
// int fd = -1;
|
||||
// Used to unmask IRQ
|
||||
uint32_t info = 1;
|
||||
|
||||
interruptWindowCd.resetTimer();
|
||||
@ -182,22 +173,29 @@ ReturnValue_t PdecHandler::irqOperation() {
|
||||
switch (state) {
|
||||
case State::INIT: {
|
||||
result = handleInitState();
|
||||
if (result == returnvalue::OK) {
|
||||
openIrqFile(&fd);
|
||||
if (result != returnvalue::OK) {
|
||||
break;
|
||||
}
|
||||
openIrqFile();
|
||||
if (ptmeResetWithReinitializationPending) {
|
||||
actionHelper.finish(true, commandedBy, pdec::RESET_PDEC_WITH_REINIITALIZATION);
|
||||
ptmeResetWithReinitializationPending = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case State::PDEC_RESET: {
|
||||
triggerEvent(pdec::PDEC_TRYING_RESET_WITH_INIT);
|
||||
result = pdecToReset();
|
||||
if (result != returnvalue::OK) {
|
||||
triggerEvent(PDEC_RESET_FAILED);
|
||||
}
|
||||
usleep(20);
|
||||
state = State::INIT;
|
||||
break;
|
||||
}
|
||||
case State::RUNNING: {
|
||||
checkLocks();
|
||||
checkAndHandleIrqs(fd, info);
|
||||
doPeriodicWork();
|
||||
checkAndHandleIrqs(info);
|
||||
break;
|
||||
}
|
||||
case State::WAIT_FOR_RECOVERY:
|
||||
@ -219,27 +217,28 @@ ReturnValue_t PdecHandler::handleInitState() {
|
||||
ReturnValue_t result = firstLoop();
|
||||
if (result != returnvalue::OK) {
|
||||
if (result == LocalParameterHandler::SD_NOT_READY) {
|
||||
TaskFactory::delayTask(400);
|
||||
if (initTries == MAX_INIT_TRIES) {
|
||||
sif::error << "PdecHandler::handleInitState: SD card never "
|
||||
"becomes ready"
|
||||
<< std::endl;
|
||||
state = State::WAIT_FOR_RECOVERY;
|
||||
} else {
|
||||
state = State::INIT;
|
||||
sif::error << "PdecHandler::handleInitState: SD card never becomes ready" << std::endl;
|
||||
initFailedHandler(result);
|
||||
return result;
|
||||
}
|
||||
state = State::INIT;
|
||||
initTries++;
|
||||
TaskFactory::delayTask(400);
|
||||
return result;
|
||||
}
|
||||
state = State::WAIT_FOR_RECOVERY;
|
||||
sif::error << "PDEC: Init failed with reason 0x" << std::hex << std::setw(4) << result
|
||||
<< std::endl;
|
||||
initFailedHandler(result);
|
||||
return result;
|
||||
}
|
||||
state = State::RUNNING;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void PdecHandler::openIrqFile(int* fd) {
|
||||
*fd = open(uioNames.irq, O_RDWR);
|
||||
if (*fd < 0) {
|
||||
void PdecHandler::openIrqFile() {
|
||||
irqFd = open(uioNames.irq, O_RDWR);
|
||||
if (irqFd < 0) {
|
||||
sif::error << "PdecHandler::irqOperation: Opening UIO IRQ file" << uioNames.irq << " failed"
|
||||
<< std::endl;
|
||||
triggerEvent(OPEN_IRQ_FILE_FAILED);
|
||||
@ -247,16 +246,16 @@ void PdecHandler::openIrqFile(int* fd) {
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::checkAndHandleIrqs(int fd, uint32_t& info) {
|
||||
ssize_t nb = write(fd, &info, sizeof(info));
|
||||
ReturnValue_t PdecHandler::checkAndHandleIrqs(uint32_t& info) {
|
||||
ssize_t nb = write(irqFd, &info, sizeof(info));
|
||||
if (nb != static_cast<ssize_t>(sizeof(info))) {
|
||||
sif::error << "PdecHandler::irqOperation: Unmasking IRQ failed" << std::endl;
|
||||
triggerEvent(WRITE_SYSCALL_ERROR_PDEC, errno);
|
||||
close(fd);
|
||||
close(irqFd);
|
||||
state = State::INIT;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
struct pollfd fds = {.fd = fd, .events = POLLIN, .revents = 0};
|
||||
struct pollfd fds = {.fd = irqFd, .events = POLLIN, .revents = 0};
|
||||
int ret = poll(&fds, 1, IRQ_TIMEOUT_MS);
|
||||
if (ret == 0) {
|
||||
// No TCs for timeout period
|
||||
@ -264,7 +263,7 @@ ReturnValue_t PdecHandler::checkAndHandleIrqs(int fd, uint32_t& info) {
|
||||
resetIrqLimiters();
|
||||
} else if (ret >= 1) {
|
||||
// Interrupt handling.
|
||||
nb = read(fd, &info, sizeof(info));
|
||||
nb = read(irqFd, &info, sizeof(info));
|
||||
interruptCounter++;
|
||||
if (nb == static_cast<ssize_t>(sizeof(info))) {
|
||||
uint32_t pisr = *(registerBaseAddress + PDEC_PISR_OFFSET);
|
||||
@ -303,7 +302,7 @@ ReturnValue_t PdecHandler::checkAndHandleIrqs(int fd, uint32_t& info) {
|
||||
sif::error << "PdecHandler::irqOperation: Poll error with errno " << errno << ": "
|
||||
<< strerror(errno) << std::endl;
|
||||
triggerEvent(POLL_SYSCALL_ERROR_PDEC, errno);
|
||||
close(fd);
|
||||
close(irqFd);
|
||||
state = State::INIT;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
@ -335,6 +334,7 @@ MessageQueueId_t PdecHandler::getCommandQueue() const { return commandQueue->get
|
||||
|
||||
ReturnValue_t PdecHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||
const uint8_t* data, size_t size) {
|
||||
using namespace pdec;
|
||||
switch (actionId) {
|
||||
case PRINT_CLCW:
|
||||
printClcw();
|
||||
@ -342,6 +342,16 @@ ReturnValue_t PdecHandler::executeAction(ActionId_t actionId, MessageQueueId_t c
|
||||
case PRINT_PDEC_MON:
|
||||
printPdecMon();
|
||||
return EXECUTION_FINISHED;
|
||||
case RESET_PDEC_NO_REINIITALIZATION: {
|
||||
pdecResetNoInit();
|
||||
return EXECUTION_FINISHED;
|
||||
}
|
||||
case RESET_PDEC_WITH_REINIITALIZATION: {
|
||||
initializeReset();
|
||||
ptmeResetWithReinitializationPending = true;
|
||||
this->commandedBy = commandedBy;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
default:
|
||||
return COMMAND_NOT_IMPLEMENTED;
|
||||
}
|
||||
@ -370,7 +380,7 @@ ReturnValue_t PdecHandler::getParameter(uint8_t domainId, uint8_t uniqueIdentifi
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
// PDEC needs reset to apply this parameter change
|
||||
state = State::PDEC_RESET;
|
||||
initializeReset();
|
||||
return returnvalue::OK;
|
||||
} else if ((domainId == 0) and (uniqueIdentifier == ParameterId::NEGATIVE_WINDOW)) {
|
||||
uint8_t newVal = 0;
|
||||
@ -392,7 +402,7 @@ ReturnValue_t PdecHandler::getParameter(uint8_t domainId, uint8_t uniqueIdentifi
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
// PDEC needs reset to apply this parameter change
|
||||
state = State::PDEC_RESET;
|
||||
initializeReset();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
@ -425,8 +435,7 @@ ReturnValue_t PdecHandler::releasePdec() {
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::pdecToReset() {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
result = gpioComIF->pullLow(pdecReset);
|
||||
ReturnValue_t result = gpioComIF->pullLow(pdecReset);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::error << "PdecHandler::pdecToReset: Failed to pull PDEC reset line"
|
||||
" to low"
|
||||
@ -449,22 +458,13 @@ bool PdecHandler::newTcReceived() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void PdecHandler::checkLocks() {
|
||||
uint32_t clcw = getClcw();
|
||||
if (not(clcw & NO_RF_MASK) && not carrierLock) {
|
||||
triggerEvent(CARRIER_LOCK);
|
||||
carrierLock = true;
|
||||
} else if ((clcw & NO_RF_MASK) && carrierLock) {
|
||||
carrierLock = false;
|
||||
triggerEvent(LOST_CARRIER_LOCK_PDEC);
|
||||
}
|
||||
if (not(clcw & NO_BITLOCK_MASK) && not bitLock) {
|
||||
triggerEvent(BIT_LOCK_PDEC);
|
||||
bitLock = true;
|
||||
} else if ((clcw & NO_BITLOCK_MASK) && bitLock) {
|
||||
bitLock = false;
|
||||
triggerEvent(LOST_BIT_LOCK_PDEC);
|
||||
}
|
||||
void PdecHandler::doPeriodicWork() {
|
||||
// scuffed test code
|
||||
// if(testCntr < 30) {
|
||||
// triggerEvent(pdec::INVALID_TC_FRAME, FRAME_DIRTY_RETVAL);
|
||||
// testCntr++;
|
||||
// }
|
||||
checkLocks();
|
||||
}
|
||||
|
||||
bool PdecHandler::checkFrameAna(uint32_t pdecFar) {
|
||||
@ -748,6 +748,68 @@ void PdecHandler::resetIrqLimiters() {
|
||||
interruptCounter = 0;
|
||||
}
|
||||
|
||||
void PdecHandler::checkLocks() {
|
||||
uint32_t clcw = getClcw();
|
||||
if (not(clcw & NO_RF_MASK) && not carrierLock) {
|
||||
triggerEvent(CARRIER_LOCK);
|
||||
carrierLock = true;
|
||||
} else if ((clcw & NO_RF_MASK) && carrierLock) {
|
||||
carrierLock = false;
|
||||
triggerEvent(LOST_CARRIER_LOCK_PDEC);
|
||||
}
|
||||
if (not(clcw & NO_BITLOCK_MASK) && not bitLock) {
|
||||
triggerEvent(BIT_LOCK_PDEC);
|
||||
bitLock = true;
|
||||
} else if ((clcw & NO_BITLOCK_MASK) && bitLock) {
|
||||
bitLock = false;
|
||||
triggerEvent(LOST_BIT_LOCK_PDEC);
|
||||
}
|
||||
}
|
||||
|
||||
void PdecHandler::initFailedHandler(ReturnValue_t reason) {
|
||||
triggerEvent(pdec::PDEC_INIT_FAILED, reason, 0);
|
||||
if (ptmeResetWithReinitializationPending) {
|
||||
actionHelper.finish(false, commandedBy, pdec::RESET_PDEC_WITH_REINIITALIZATION, reason);
|
||||
ptmeResetWithReinitializationPending = false;
|
||||
}
|
||||
state = State::WAIT_FOR_RECOVERY;
|
||||
}
|
||||
|
||||
void PdecHandler::pdecResetNoInit() {
|
||||
triggerEvent(pdec::PDEC_TRYING_RESET_NO_INIT);
|
||||
pdecToReset();
|
||||
usleep(20);
|
||||
releasePdec();
|
||||
ReturnValue_t result = postResetOperation();
|
||||
if (result != returnvalue::OK) {
|
||||
// What can we really do here? Event was already triggered if this is due to the FAR flag
|
||||
// not being reset.
|
||||
sif::error << "PdecHandler::pdecResetNoInit: Post reset operation failed unexpectedly"
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t PdecHandler::postResetOperation() {
|
||||
// This configuration must be done while the PDEC is not held in reset.
|
||||
if (OP_MODE == Modes::IRQ) {
|
||||
// Configure interrupt mask register to enable interrupts
|
||||
*(registerBaseAddress + PDEC_IMR_OFFSET) = pdecConfig.getImrReg();
|
||||
}
|
||||
ReturnValue_t result = resetFarStatFlag();
|
||||
if (result != returnvalue::OK) {
|
||||
// Requires reconfiguration and reinitialization of PDEC
|
||||
triggerEvent(INVALID_FAR);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void PdecHandler::initializeReset() {
|
||||
if (irqFd != 0) {
|
||||
close(irqFd);
|
||||
}
|
||||
state = State::PDEC_RESET;
|
||||
}
|
||||
|
||||
std::string PdecHandler::getMonStatusString(uint32_t status) {
|
||||
switch (status) {
|
||||
case TC_CHANNEL_INACTIVE:
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#include <fsfw/timemanager/Countdown.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "PdecConfig.h"
|
||||
#include "eive/definitions.h"
|
||||
@ -79,73 +81,11 @@ class PdecHandler : public SystemObject,
|
||||
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
||||
uint16_t startAtIndex) override;
|
||||
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PDEC_HANDLER;
|
||||
|
||||
//! [EXPORT] : [COMMENT] Frame acceptance report signals an invalid frame
|
||||
//! P1: The frame analysis information (FrameAna field of PDEC_FAR register)
|
||||
//! P2: When frame declared illegal this parameter this parameter gives information about the
|
||||
//! reason (IReason field of the PDEC_FAR register)
|
||||
static const Event INVALID_TC_FRAME = MAKE_EVENT(1, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] Read invalid FAR from PDEC after startup
|
||||
static const Event INVALID_FAR = MAKE_EVENT(2, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] Carrier lock detected
|
||||
static const Event CARRIER_LOCK = MAKE_EVENT(3, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] Bit lock detected (data valid)
|
||||
static const Event BIT_LOCK_PDEC = MAKE_EVENT(4, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] Lost carrier lock
|
||||
static const Event LOST_CARRIER_LOCK_PDEC = MAKE_EVENT(5, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] Lost bit lock
|
||||
static const Event LOST_BIT_LOCK_PDEC = MAKE_EVENT(6, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] Too many IRQs over the time window of one second. P1: Allowed TCs
|
||||
static constexpr Event TOO_MANY_IRQS = MAKE_EVENT(7, severity::MEDIUM);
|
||||
static constexpr Event POLL_SYSCALL_ERROR_PDEC =
|
||||
event::makeEvent(SUBSYSTEM_ID, 8, severity::MEDIUM);
|
||||
static constexpr Event WRITE_SYSCALL_ERROR_PDEC =
|
||||
event::makeEvent(SUBSYSTEM_ID, 9, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] Failed to pull PDEC reset to low
|
||||
static constexpr Event PDEC_RESET_FAILED = event::makeEvent(SUBSYSTEM_ID, 10, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] Failed to open the IRQ uio file
|
||||
static constexpr Event OPEN_IRQ_FILE_FAILED = event::makeEvent(SUBSYSTEM_ID, 11, severity::HIGH);
|
||||
|
||||
private:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::PDEC_HANDLER;
|
||||
|
||||
static constexpr Modes OP_MODE = Modes::IRQ;
|
||||
|
||||
static const ReturnValue_t ABANDONED_CLTU_RETVAL = MAKE_RETURN_CODE(0xA0);
|
||||
static const ReturnValue_t FRAME_DIRTY_RETVAL = MAKE_RETURN_CODE(0xA1);
|
||||
static const ReturnValue_t FRAME_ILLEGAL_ONE_REASON = MAKE_RETURN_CODE(0xA2);
|
||||
static const ReturnValue_t FRAME_ILLEGAL_MULTIPLE_REASONS = MAKE_RETURN_CODE(0xA2);
|
||||
static const ReturnValue_t AD_DISCARDED_LOCKOUT_RETVAL = MAKE_RETURN_CODE(0xA3);
|
||||
static const ReturnValue_t AD_DISCARDED_WAIT_RETVAL = MAKE_RETURN_CODE(0xA4);
|
||||
static const ReturnValue_t AD_DISCARDED_NS_VS = MAKE_RETURN_CODE(0xA5);
|
||||
|
||||
//! [EXPORT] : [COMMENT] Received action message with unknown action id
|
||||
static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xB0);
|
||||
|
||||
static const ReturnValue_t NO_REPORT_RETVAL = MAKE_RETURN_CODE(0xA6);
|
||||
//! Error in version number and reserved A and B fields
|
||||
static const ReturnValue_t ERROR_VERSION_NUMBER_RETVAL = MAKE_RETURN_CODE(0xA7);
|
||||
//! Illegal combination of bypass and control command flag
|
||||
static const ReturnValue_t ILLEGAL_COMBINATION_RETVAL = MAKE_RETURN_CODE(0xA8);
|
||||
//! Spacecraft identifier did not match
|
||||
static const ReturnValue_t INVALID_SC_ID_RETVAL = MAKE_RETURN_CODE(0xA9);
|
||||
//! VC identifier bits 0 to 4 did not match
|
||||
static const ReturnValue_t INVALID_VC_ID_MSB_RETVAL = MAKE_RETURN_CODE(0xAA);
|
||||
//! VC identifier bit 5 did not match
|
||||
static const ReturnValue_t INVALID_VC_ID_LSB_RETVAL = MAKE_RETURN_CODE(0xAB);
|
||||
//! N(S) of BC or BD frame not set to all zeros
|
||||
static const ReturnValue_t NS_NOT_ZERO_RETVAL = MAKE_RETURN_CODE(0xAC);
|
||||
//! Invalid BC control command
|
||||
static const ReturnValue_t INVALID_BC_CC = MAKE_RETURN_CODE(0xAE);
|
||||
|
||||
static const uint32_t QUEUE_SIZE = config::CCSDS_HANDLER_QUEUE_SIZE;
|
||||
|
||||
// Action IDs
|
||||
static const ActionId_t PRINT_CLCW = 0;
|
||||
// Print PDEC monitor register
|
||||
static const ActionId_t PRINT_PDEC_MON = 1;
|
||||
|
||||
#ifdef TE0720_1CFA
|
||||
static const int CONFIG_MEMORY_MAP_SIZE = 0x400;
|
||||
static const int RAM_MAP_SIZE = 0x4000;
|
||||
@ -185,17 +125,6 @@ class PdecHandler : public SystemObject,
|
||||
|
||||
static constexpr uint32_t MAX_ALLOWED_IRQS_PER_WINDOW = 800;
|
||||
|
||||
enum class FrameAna_t : uint8_t {
|
||||
ABANDONED_CLTU,
|
||||
FRAME_DIRTY,
|
||||
FRAME_ILLEGAL,
|
||||
FRAME_ILLEGAL_MULTI_REASON,
|
||||
AD_DISCARDED_LOCKOUT,
|
||||
AD_DISCARDED_WAIT,
|
||||
AD_DISCARDED_NS_VR,
|
||||
FRAME_ACCEPTED
|
||||
};
|
||||
|
||||
enum class IReason_t : uint8_t {
|
||||
NO_REPORT,
|
||||
ERROR_VERSION_NUMBER,
|
||||
@ -213,6 +142,7 @@ class PdecHandler : public SystemObject,
|
||||
|
||||
Countdown genericCheckCd = Countdown(IRQ_TIMEOUT_MS);
|
||||
object_id_t tcDestinationId;
|
||||
int irqFd = 0;
|
||||
|
||||
AcceptsTelecommandsIF* tcDestination = nullptr;
|
||||
|
||||
@ -258,6 +188,9 @@ class PdecHandler : public SystemObject,
|
||||
bool carrierLock = false;
|
||||
bool bitLock = false;
|
||||
|
||||
MessageQueueId_t commandedBy = MessageQueueIF::NO_QUEUE;
|
||||
bool ptmeResetWithReinitializationPending = false;
|
||||
|
||||
UioNames uioNames;
|
||||
|
||||
ParameterHelper paramHelper;
|
||||
@ -266,6 +199,9 @@ class PdecHandler : public SystemObject,
|
||||
|
||||
uint32_t initTries = 0;
|
||||
|
||||
// scuffed test counter.
|
||||
uint8_t testCntr = 0;
|
||||
|
||||
/**
|
||||
* @brief Performs initialization stuff which must be performed in first
|
||||
* loop of running task
|
||||
@ -282,8 +218,8 @@ class PdecHandler : public SystemObject,
|
||||
ReturnValue_t polledOperation();
|
||||
ReturnValue_t irqOperation();
|
||||
ReturnValue_t handleInitState();
|
||||
void openIrqFile(int* fd);
|
||||
ReturnValue_t checkAndHandleIrqs(int fd, uint32_t& info);
|
||||
void openIrqFile();
|
||||
ReturnValue_t checkAndHandleIrqs(uint32_t& info);
|
||||
|
||||
uint32_t readFar();
|
||||
|
||||
@ -325,6 +261,8 @@ class PdecHandler : public SystemObject,
|
||||
* @brief Checks if carrier lock or bit lock has been detected and triggers appropriate
|
||||
* event.
|
||||
*/
|
||||
void doPeriodicWork();
|
||||
|
||||
void checkLocks();
|
||||
|
||||
void resetIrqLimiters();
|
||||
@ -400,6 +338,13 @@ class PdecHandler : public SystemObject,
|
||||
*/
|
||||
void printPdecMon();
|
||||
|
||||
void pdecResetNoInit();
|
||||
|
||||
ReturnValue_t postResetOperation();
|
||||
void initializeReset();
|
||||
|
||||
void initFailedHandler(ReturnValue_t reason);
|
||||
|
||||
std::string getMonStatusString(uint32_t status);
|
||||
};
|
||||
|
||||
|
@ -1,10 +1,95 @@
|
||||
#ifndef LINUX_OBC_PDEC_H_
|
||||
#define LINUX_OBC_PDEC_H_
|
||||
|
||||
#include <eive/resultClassIds.h>
|
||||
#include <fsfw/action/ActionMessage.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace pdec {
|
||||
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::PDEC_HANDLER;
|
||||
static const ReturnValue_t ABANDONED_CLTU_RETVAL = MAKE_RETURN_CODE(0xA0);
|
||||
static const ReturnValue_t FRAME_DIRTY_RETVAL = MAKE_RETURN_CODE(0xA1);
|
||||
static const ReturnValue_t FRAME_ILLEGAL_ONE_REASON = MAKE_RETURN_CODE(0xA2);
|
||||
static const ReturnValue_t FRAME_ILLEGAL_MULTIPLE_REASONS = MAKE_RETURN_CODE(0xA2);
|
||||
static const ReturnValue_t AD_DISCARDED_LOCKOUT_RETVAL = MAKE_RETURN_CODE(0xA3);
|
||||
static const ReturnValue_t AD_DISCARDED_WAIT_RETVAL = MAKE_RETURN_CODE(0xA4);
|
||||
static const ReturnValue_t AD_DISCARDED_NS_VS = MAKE_RETURN_CODE(0xA5);
|
||||
|
||||
//! [EXPORT] : [COMMENT] Received action message with unknown action id
|
||||
static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xB0);
|
||||
|
||||
static const ReturnValue_t NO_REPORT_RETVAL = MAKE_RETURN_CODE(0xA6);
|
||||
//! Error in version number and reserved A and B fields
|
||||
static const ReturnValue_t ERROR_VERSION_NUMBER_RETVAL = MAKE_RETURN_CODE(0xA7);
|
||||
//! Illegal combination of bypass and control command flag
|
||||
static const ReturnValue_t ILLEGAL_COMBINATION_RETVAL = MAKE_RETURN_CODE(0xA8);
|
||||
//! Spacecraft identifier did not match
|
||||
static const ReturnValue_t INVALID_SC_ID_RETVAL = MAKE_RETURN_CODE(0xA9);
|
||||
//! VC identifier bits 0 to 4 did not match
|
||||
static const ReturnValue_t INVALID_VC_ID_MSB_RETVAL = MAKE_RETURN_CODE(0xAA);
|
||||
//! VC identifier bit 5 did not match
|
||||
static const ReturnValue_t INVALID_VC_ID_LSB_RETVAL = MAKE_RETURN_CODE(0xAB);
|
||||
//! N(S) of BC or BD frame not set to all zeros
|
||||
static const ReturnValue_t NS_NOT_ZERO_RETVAL = MAKE_RETURN_CODE(0xAC);
|
||||
//! Invalid BC control command
|
||||
static const ReturnValue_t INVALID_BC_CC = MAKE_RETURN_CODE(0xAE);
|
||||
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PDEC_HANDLER;
|
||||
|
||||
//! [EXPORT] : [COMMENT] Frame acceptance report signals an invalid frame
|
||||
//! P1: The frame analysis information (FrameAna field of PDEC_FAR register)
|
||||
//! P2: When frame declared illegal this parameter this parameter gives information about the
|
||||
//! reason (IReason field of the PDEC_FAR register)
|
||||
static const Event INVALID_TC_FRAME = MAKE_EVENT(1, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] Read invalid FAR from PDEC after startup
|
||||
static const Event INVALID_FAR = MAKE_EVENT(2, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] Carrier lock detected
|
||||
static const Event CARRIER_LOCK = MAKE_EVENT(3, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] Bit lock detected (data valid)
|
||||
static const Event BIT_LOCK_PDEC = MAKE_EVENT(4, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] Lost carrier lock
|
||||
static const Event LOST_CARRIER_LOCK_PDEC = MAKE_EVENT(5, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] Lost bit lock
|
||||
static const Event LOST_BIT_LOCK_PDEC = MAKE_EVENT(6, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] Too many IRQs over the time window of one second. P1: Allowed TCs
|
||||
static constexpr Event TOO_MANY_IRQS = MAKE_EVENT(7, severity::MEDIUM);
|
||||
static constexpr Event POLL_SYSCALL_ERROR_PDEC =
|
||||
event::makeEvent(SUBSYSTEM_ID, 8, severity::MEDIUM);
|
||||
static constexpr Event WRITE_SYSCALL_ERROR_PDEC = event::makeEvent(SUBSYSTEM_ID, 9, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] Trying a PDEC reset with complete re-initialization
|
||||
static constexpr Event PDEC_TRYING_RESET_WITH_INIT =
|
||||
event::makeEvent(SUBSYSTEM_ID, 10, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Trying a PDEC reset without re-initialization.
|
||||
static constexpr Event PDEC_TRYING_RESET_NO_INIT =
|
||||
event::makeEvent(SUBSYSTEM_ID, 11, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Failed to pull PDEC reset to low
|
||||
static constexpr Event PDEC_RESET_FAILED = event::makeEvent(SUBSYSTEM_ID, 12, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] Failed to open the IRQ uio file
|
||||
static constexpr Event OPEN_IRQ_FILE_FAILED = event::makeEvent(SUBSYSTEM_ID, 13, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] PDEC initialization failed. This might also be due to the persistent
|
||||
//! confiuration never becoming available, for example due to SD card issues.
|
||||
static constexpr Event PDEC_INIT_FAILED = event::makeEvent(SUBSYSTEM_ID, 14, severity::HIGH);
|
||||
|
||||
// Action IDs
|
||||
static constexpr ActionId_t PRINT_CLCW = 0;
|
||||
// Print PDEC monitor register
|
||||
static constexpr ActionId_t PRINT_PDEC_MON = 1;
|
||||
static constexpr ActionId_t RESET_PDEC_NO_REINIITALIZATION = 2;
|
||||
static constexpr ActionId_t RESET_PDEC_WITH_REINIITALIZATION = 3;
|
||||
|
||||
enum class FrameAna_t : uint8_t {
|
||||
ABANDONED_CLTU,
|
||||
FRAME_DIRTY,
|
||||
FRAME_ILLEGAL,
|
||||
FRAME_ILLEGAL_MULTI_REASON,
|
||||
AD_DISCARDED_LOCKOUT,
|
||||
AD_DISCARDED_WAIT,
|
||||
AD_DISCARDED_NS_VR,
|
||||
FRAME_ACCEPTED
|
||||
};
|
||||
|
||||
static const uint8_t STAT_POSITION = 31;
|
||||
static const uint8_t FRAME_ANA_POSITION = 28;
|
||||
static const uint8_t IREASON_POSITION = 25;
|
||||
|
@ -37,6 +37,7 @@ void GyrAdis1650XHandler::doStartUp() {
|
||||
void GyrAdis1650XHandler::doShutDown() {
|
||||
if (internalState != InternalState::SHUTDOWN) {
|
||||
commandExecuted = false;
|
||||
PoolReadGuard pg(&primaryDataset);
|
||||
primaryDataset.setValidity(false, true);
|
||||
internalState = InternalState::SHUTDOWN;
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ void GyrL3gCustomHandler::doStartUp() {
|
||||
void GyrL3gCustomHandler::doShutDown() {
|
||||
if (internalState != InternalState::SHUTDOWN) {
|
||||
internalState = InternalState::SHUTDOWN;
|
||||
PoolReadGuard pg(&dataset);
|
||||
dataset.setValidity(false, true);
|
||||
commandExecuted = false;
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ void MgmLis3CustomHandler::doStartUp() {
|
||||
|
||||
void MgmLis3CustomHandler::doShutDown() {
|
||||
if (internalState != InternalState::SHUTDOWN) {
|
||||
PoolReadGuard pg(&dataset);
|
||||
dataset.setValidity(false, true);
|
||||
internalState = InternalState::SHUTDOWN;
|
||||
commandExecuted = false;
|
||||
|
@ -33,6 +33,7 @@ void MgmRm3100CustomHandler::doStartUp() {
|
||||
void MgmRm3100CustomHandler::doShutDown() {
|
||||
if (internalState != InternalState::SHUTDOWN) {
|
||||
commandExecuted = false;
|
||||
PoolReadGuard pg(&primaryDataset);
|
||||
primaryDataset.setValidity(false, true);
|
||||
internalState = InternalState::SHUTDOWN;
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ void SusHandler::doStartUp() {
|
||||
|
||||
void SusHandler::doShutDown() {
|
||||
if (internalState != InternalState::SHUTDOWN) {
|
||||
PoolReadGuard pg(&dataset);
|
||||
dataset.setValidity(false, true);
|
||||
internalState = InternalState::SHUTDOWN;
|
||||
commandExecuted = false;
|
||||
|
@ -8,7 +8,7 @@ namespace acs {
|
||||
|
||||
enum class SimpleSensorMode { NORMAL = 0, OFF = 1 };
|
||||
|
||||
// These modes are the submodes of the ACS controller and the modes of the ACS subsystem.
|
||||
// These modes are the modes of the ACS controller and of the ACS subsystem.
|
||||
enum AcsMode : Mode_t {
|
||||
OFF = HasModesIF::MODE_OFF,
|
||||
SAFE = 10,
|
||||
@ -21,23 +21,40 @@ enum AcsMode : Mode_t {
|
||||
|
||||
enum SafeSubmode : Submode_t { DEFAULT = 0, DETUMBLE = 1 };
|
||||
|
||||
// static constexpr uint8_t ACS_SYSTEM_DETUMBLE_SUBMODE = 1;
|
||||
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,
|
||||
SAFECTRL_DETUMBLE_FULL = 20,
|
||||
SAFECTRL_DETUMBLE_DETERIORATED = 21,
|
||||
};
|
||||
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::ACS_SUBSYSTEM;
|
||||
//!< The limits for the rotation in safe mode were violated.
|
||||
static const Event SAFE_RATE_VIOLATION = MAKE_EVENT(0, severity::MEDIUM);
|
||||
//!< The system has recovered from a safe rate rotation violation.
|
||||
//! [EXPORT] : [COMMENT] The limits for the rotation in safe mode were violated.
|
||||
static constexpr Event SAFE_RATE_VIOLATION = MAKE_EVENT(0, severity::MEDIUM);
|
||||
//! [EXPORT] : [COMMENT] The system has recovered from a safe rate rotation violation.
|
||||
static constexpr Event SAFE_RATE_RECOVERY = MAKE_EVENT(1, severity::MEDIUM);
|
||||
//!< Multiple RWs are invalid, not commandable and therefore higher ACS modes cannot be maintained.
|
||||
//! [EXPORT] : [COMMENT] Multiple RWs are invalid, uncommandable and therefore higher ACS modes
|
||||
//! cannot be maintained.
|
||||
static constexpr Event MULTIPLE_RW_INVALID = MAKE_EVENT(2, severity::HIGH);
|
||||
//!< MEKF was not able to compute a solution.
|
||||
//! [EXPORT] : [COMMENT] MEKF was not able to compute a solution.
|
||||
//! P1: MEKF state on exit
|
||||
static constexpr Event MEKF_INVALID_INFO = MAKE_EVENT(3, severity::INFO);
|
||||
//!< MEKF is able to compute a solution again.
|
||||
//! [EXPORT] : [COMMENT] MEKF is able to compute a solution again.
|
||||
static constexpr Event MEKF_RECOVERY = MAKE_EVENT(4, severity::INFO);
|
||||
//!< MEKF was not able to compute a solution during any pointing ACS mode for a prolonged time.
|
||||
static constexpr Event MEKF_INVALID_MODE_VIOLATION = MAKE_EVENT(5, severity::HIGH);
|
||||
//!< The ACS safe mode controller was not able to compute a solution and has failed.
|
||||
static constexpr Event SAFE_MODE_CONTROLLER_FAILURE = MAKE_EVENT(6, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] MEKF performed an automatic reset after detection of nonfinite values.
|
||||
static constexpr Event MEKF_AUTOMATIC_RESET = MAKE_EVENT(5, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] MEKF was not able to compute a solution during any pointing ACS mode for a
|
||||
//! prolonged time.
|
||||
static constexpr Event MEKF_INVALID_MODE_VIOLATION = MAKE_EVENT(6, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] The ACS safe mode controller was not able to compute a solution and has
|
||||
//! failed.
|
||||
//! P1: Missing information about magnetic field, P2: Missing information about rotational rate
|
||||
static constexpr Event SAFE_MODE_CONTROLLER_FAILURE = MAKE_EVENT(7, severity::HIGH);
|
||||
|
||||
extern const char* getModeStr(AcsMode mode);
|
||||
|
||||
|
@ -1,6 +1,11 @@
|
||||
#include <mission/acs/str/ArcsecDatalinkLayer.h>
|
||||
#include "ArcsecDatalinkLayer.h"
|
||||
|
||||
ArcsecDatalinkLayer::ArcsecDatalinkLayer() : decodeRingBuf(BUFFER_LENGTHS, true) { slipInit(); }
|
||||
extern "C" {
|
||||
#include <wire/common/SLIP.h>
|
||||
#include <wire/common/misc.h>
|
||||
}
|
||||
|
||||
ArcsecDatalinkLayer::ArcsecDatalinkLayer() : decodeRingBuf(BUFFER_LENGTHS, true) {}
|
||||
|
||||
ArcsecDatalinkLayer::~ArcsecDatalinkLayer() {}
|
||||
|
||||
@ -11,38 +16,50 @@ ReturnValue_t ArcsecDatalinkLayer::checkRingBufForFrame(const uint8_t** decodedF
|
||||
return DEC_IN_PROGRESS;
|
||||
}
|
||||
decodeRingBuf.readData(rxAnalysisBuffer, currentLen);
|
||||
|
||||
bool startFound = false;
|
||||
size_t startIdx = 0;
|
||||
for (size_t idx = 0; idx < currentLen; idx++) {
|
||||
enum arc_dec_result decResult =
|
||||
arc_transport_decode_body(rxAnalysisBuffer[idx], &slipInfo, decodedRxFrame, &rxFrameSize);
|
||||
switch (decResult) {
|
||||
case ARC_DEC_INPROGRESS: {
|
||||
break;
|
||||
}
|
||||
case ARC_DEC_ERROR_FRAME_SHORT: {
|
||||
decodeRingBuf.deleteData(idx);
|
||||
return REPLY_TOO_SHORT;
|
||||
}
|
||||
case ARC_DEC_ERROR_CHECKSUM:
|
||||
decodeRingBuf.deleteData(idx);
|
||||
return CRC_FAILURE;
|
||||
case ARC_DEC_ASYNC:
|
||||
case ARC_DEC_SYNC: {
|
||||
// Reset length of SLIP struct for next frame
|
||||
slipInfo.length = 0;
|
||||
if (rxAnalysisBuffer[idx] != SLIP_START_AND_END) {
|
||||
continue;
|
||||
}
|
||||
if (not startFound) {
|
||||
startFound = true;
|
||||
startIdx = idx;
|
||||
continue;
|
||||
}
|
||||
// Now we can try decoding the whole frame.
|
||||
size_t encodedDataSize = 0;
|
||||
slip_error_t slipError =
|
||||
slip_decode_frame(decodedRxFrame, &rxFrameSize, rxAnalysisBuffer + startIdx,
|
||||
idx - startIdx + 1, &encodedDataSize, ARC_DEF_SAGITTA_SLIP_ID);
|
||||
decodeRingBuf.deleteData(idx + 1);
|
||||
switch (slipError) {
|
||||
case (SLIP_OK): {
|
||||
if (decodedFrame != nullptr) {
|
||||
*decodedFrame = decodedRxFrame;
|
||||
}
|
||||
frameLen = rxFrameSize;
|
||||
decodeRingBuf.deleteData(idx);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
default:
|
||||
sif::debug << "ArcsecDatalinkLayer::decodeFrame: Unknown result code" << std::endl;
|
||||
break;
|
||||
case (SLIP_BAD_CRC): {
|
||||
return CRC_FAILURE;
|
||||
}
|
||||
case (SLIP_OVERFLOW): {
|
||||
return SLIP_OVERFLOW_RETVAL;
|
||||
}
|
||||
// Should not happen, we searched for start and end marker..
|
||||
case (SLIP_NO_END): {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
case (SLIP_ID_MISMATCH): {
|
||||
return SLIP_ID_MISSMATCH_RETVAL;
|
||||
}
|
||||
default: {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
}
|
||||
decodeRingBuf.deleteData(currentLen);
|
||||
return DEC_IN_PROGRESS;
|
||||
}
|
||||
|
||||
@ -55,18 +72,11 @@ ReturnValue_t ArcsecDatalinkLayer::feedData(const uint8_t* rawData, size_t rawDa
|
||||
return decodeRingBuf.writeData(rawData, rawDataLen);
|
||||
}
|
||||
|
||||
void ArcsecDatalinkLayer::reset() {
|
||||
slipInit();
|
||||
decodeRingBuf.clear();
|
||||
}
|
||||
|
||||
void ArcsecDatalinkLayer::slipInit() {
|
||||
slip_decode_init(rxBufferArc, sizeof(rxBufferArc), &slipInfo);
|
||||
}
|
||||
void ArcsecDatalinkLayer::reset() { decodeRingBuf.clear(); }
|
||||
|
||||
void ArcsecDatalinkLayer::encodeFrame(const uint8_t* data, size_t length, const uint8_t** txFrame,
|
||||
size_t& size) {
|
||||
arc_transport_encode_body(data, length, txEncoded, &size);
|
||||
slip_encode_frame(data, length, txEncoded, &size, ARC_DEF_SAGITTA_SLIP_ID);
|
||||
if (txFrame != nullptr) {
|
||||
*txFrame = txEncoded;
|
||||
}
|
||||
|
@ -5,10 +5,13 @@
|
||||
#include <fsfw/devicehandlers/CookieIF.h>
|
||||
#include <mission/acs/str/strHelpers.h>
|
||||
|
||||
#include "arcsec/common/misc.h"
|
||||
#include "eive/resultClassIds.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
|
||||
extern "C" {
|
||||
#include <wire/common/SLIP.h>
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Helper class to handle the datalinklayer of replies from the star tracker of arcsec.
|
||||
*/
|
||||
@ -22,6 +25,8 @@ class ArcsecDatalinkLayer {
|
||||
static const ReturnValue_t REPLY_TOO_SHORT = MAKE_RETURN_CODE(0xA1);
|
||||
//! [EXPORT] : [COMMENT] Detected CRC failure in received frame
|
||||
static const ReturnValue_t CRC_FAILURE = MAKE_RETURN_CODE(0xA2);
|
||||
static const ReturnValue_t SLIP_OVERFLOW_RETVAL = MAKE_RETURN_CODE(0xA3);
|
||||
static const ReturnValue_t SLIP_ID_MISSMATCH_RETVAL = MAKE_RETURN_CODE(0xA4);
|
||||
|
||||
static const uint8_t STATUS_OK = 0;
|
||||
|
||||
@ -74,7 +79,7 @@ class ArcsecDatalinkLayer {
|
||||
// Decoded frame will be copied to this buffer
|
||||
uint8_t decodedRxFrame[startracker::MAX_FRAME_SIZE];
|
||||
// Size of decoded frame
|
||||
uint32_t rxFrameSize = 0;
|
||||
size_t rxFrameSize = 0;
|
||||
|
||||
// Buffer where encoded frames will be stored. First byte of encoded frame represents type of
|
||||
// reply
|
||||
@ -82,7 +87,7 @@ class ArcsecDatalinkLayer {
|
||||
// Size of encoded frame
|
||||
uint32_t txFrameSize = 0;
|
||||
|
||||
slip_decode_state slipInfo;
|
||||
// slip_decode_state slipInfo;
|
||||
|
||||
void slipInit();
|
||||
};
|
||||
|
@ -3,6 +3,10 @@
|
||||
|
||||
#include "arcsecJsonKeys.h"
|
||||
|
||||
extern "C" {
|
||||
#include <wire/common/genericstructs.h>
|
||||
}
|
||||
|
||||
ArcsecJsonParamBase::ArcsecJsonParamBase(std::string setName) : setName(setName) {}
|
||||
|
||||
ReturnValue_t ArcsecJsonParamBase::create(uint8_t* buffer) {
|
||||
|
@ -7,8 +7,6 @@
|
||||
#include <fstream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "arcsec/common/generated/tmtcstructs.h"
|
||||
#include "arcsec/common/genericstructs.h"
|
||||
#include "eive/resultClassIds.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
|
||||
|
@ -1,18 +1,22 @@
|
||||
#include <arcsec/client/generated/actionreq.h>
|
||||
#include <arcsec/client/generated/parameter.h>
|
||||
#include <arcsec/client/generated/telemetry.h>
|
||||
#include <fsfw/ipc/QueueFactory.h>
|
||||
#include <fsfw/timemanager/Stopwatch.h>
|
||||
#include <mission/acs/str/StarTrackerHandler.h>
|
||||
#include <mission/acs/str/strHelpers.h>
|
||||
#include <mission/acs/str/strJsonCommands.h>
|
||||
|
||||
extern "C" {
|
||||
#include <sagitta/client/actionreq.h>
|
||||
#include <sagitta/client/client_tm_structs.h>
|
||||
#include <sagitta/client/parameter.h>
|
||||
#include <sagitta/client/telemetry.h>
|
||||
#include <wire/common/genericstructs.h>
|
||||
}
|
||||
|
||||
#include <atomic>
|
||||
#include <fstream>
|
||||
#include <thread>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "arcsec/common/misc.h"
|
||||
|
||||
std::atomic_bool JCFG_DONE(false);
|
||||
|
||||
@ -880,7 +884,7 @@ ReturnValue_t StarTrackerHandler::interpretDeviceReply(DeviceCommandId_t id,
|
||||
|
||||
switch (id) {
|
||||
case (startracker::REQ_TIME): {
|
||||
result = handleTm(packet, timeSet, startracker::TimeSet::SIZE);
|
||||
result = handleTm(packet, timeSet, startracker::TimeSet::SIZE, "REQ_TIME");
|
||||
break;
|
||||
}
|
||||
case (startracker::PING_REQUEST): {
|
||||
@ -895,7 +899,7 @@ ReturnValue_t StarTrackerHandler::interpretDeviceReply(DeviceCommandId_t id,
|
||||
break;
|
||||
}
|
||||
case (startracker::REQ_VERSION): {
|
||||
result = handleTm(packet, versionSet, startracker::VersionSet::SIZE);
|
||||
result = handleTm(packet, versionSet, startracker::VersionSet::SIZE, "REQ_VERSION");
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
@ -906,23 +910,23 @@ ReturnValue_t StarTrackerHandler::interpretDeviceReply(DeviceCommandId_t id,
|
||||
break;
|
||||
}
|
||||
case (startracker::REQ_INTERFACE): {
|
||||
result = handleTm(packet, interfaceSet, startracker::InterfaceSet::SIZE);
|
||||
result = handleTm(packet, interfaceSet, startracker::InterfaceSet::SIZE, "REQ_INTERFACE");
|
||||
break;
|
||||
}
|
||||
case (startracker::REQ_POWER): {
|
||||
result = handleTm(packet, powerSet, startracker::PowerSet::SIZE);
|
||||
result = handleTm(packet, powerSet, startracker::PowerSet::SIZE, "REQ_POWER");
|
||||
break;
|
||||
}
|
||||
case (startracker::REQ_SOLUTION): {
|
||||
result = handleTm(packet, solutionSet, startracker::SolutionSet::SIZE);
|
||||
result = handleTm(packet, solutionSet, startracker::SolutionSet::SIZE, "REQ_SOLUTION");
|
||||
break;
|
||||
}
|
||||
case (startracker::REQ_TEMPERATURE): {
|
||||
result = handleTm(packet, temperatureSet, startracker::TemperatureSet::SIZE);
|
||||
result = handleTm(packet, temperatureSet, startracker::TemperatureSet::SIZE, "REQ_TEMP");
|
||||
break;
|
||||
}
|
||||
case (startracker::REQ_HISTOGRAM): {
|
||||
result = handleTm(packet, histogramSet, startracker::HistogramSet::SIZE);
|
||||
result = handleTm(packet, histogramSet, startracker::HistogramSet::SIZE, "REQ_HISTO");
|
||||
break;
|
||||
}
|
||||
case (startracker::SUBSCRIPTION):
|
||||
@ -1084,6 +1088,7 @@ ReturnValue_t StarTrackerHandler::initializeLocalDataPool(localpool::DataPool& l
|
||||
localDataPoolMap.emplace(startracker::LISA_QZ, new PoolEntry<float>({0}));
|
||||
localDataPoolMap.emplace(startracker::LISA_PERC_CLOSE, new PoolEntry<float>({0}));
|
||||
localDataPoolMap.emplace(startracker::LISA_NR_CLOSE, new PoolEntry<uint8_t>({0}));
|
||||
localDataPoolMap.emplace(startracker::STR_MODE, new PoolEntry<uint8_t>({0}));
|
||||
localDataPoolMap.emplace(startracker::TRUST_WORTHY, new PoolEntry<uint8_t>({0}));
|
||||
localDataPoolMap.emplace(startracker::STABLE_COUNT, new PoolEntry<uint32_t>({0}));
|
||||
localDataPoolMap.emplace(startracker::SOLUTION_STRATEGY, new PoolEntry<uint8_t>({0}));
|
||||
@ -1971,7 +1976,7 @@ ReturnValue_t StarTrackerHandler::checkProgram() {
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::handleTm(const uint8_t* rawFrame, LocalPoolDataSetBase& dataset,
|
||||
size_t size) {
|
||||
size_t size, const char* context) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
uint8_t status = startracker::getStatusField(rawFrame);
|
||||
if (status != startracker::STATUS_OK) {
|
||||
@ -1987,7 +1992,8 @@ ReturnValue_t StarTrackerHandler::handleTm(const uint8_t* rawFrame, LocalPoolDat
|
||||
dataset.setValidityBufferGeneration(false);
|
||||
result = dataset.deSerialize(&reply, &size, SerializeIF::Endianness::LITTLE);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "StarTrackerHandler::handleTm: Deserialization failed" << std::endl;
|
||||
sif::warning << "StarTrackerHandler::handleTm: Deserialization failed for " << context
|
||||
<< std::endl;
|
||||
}
|
||||
dataset.setValidityBufferGeneration(true);
|
||||
dataset.setValidity(true, true);
|
||||
|
@ -10,12 +10,15 @@
|
||||
#include <thread>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "arcsec/common/SLIP.h"
|
||||
#include "devices/powerSwitcherList.h"
|
||||
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
|
||||
#include "fsfw/src/fsfw/serialize/SerializeAdapter.h"
|
||||
#include "fsfw/timemanager/Countdown.h"
|
||||
|
||||
extern "C" {
|
||||
#include <wire/common/SLIP.h>
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This is the device handler for the star tracker from arcsec.
|
||||
*
|
||||
@ -478,7 +481,8 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
*
|
||||
* @return returnvalue::OK if successful, otherwise error return value
|
||||
*/
|
||||
ReturnValue_t handleTm(const uint8_t* rawFrame, LocalPoolDataSetBase& dataset, size_t size);
|
||||
ReturnValue_t handleTm(const uint8_t* rawFrame, LocalPoolDataSetBase& dataset, size_t size,
|
||||
const char* context);
|
||||
|
||||
/**
|
||||
* @brief Checks if star tracker is in valid mode for executing the received command.
|
||||
|
@ -9,7 +9,7 @@ static const char PROPERTIES[] = "properties";
|
||||
static const char NAME[] = "name";
|
||||
static const char VALUE[] = "value";
|
||||
|
||||
static const char LIMITS[] = "limits";
|
||||
static const char LIMITS[] = "Limits";
|
||||
static const char ACTION[] = "action";
|
||||
static const char FPGA18CURRENT[] = "FPGA18Current";
|
||||
static const char FPGA25CURRENT[] = "FPGA25Current";
|
||||
@ -22,20 +22,20 @@ static const char CMOSVRESCURRENT[] = "CMOSVResCurrent";
|
||||
static const char CMOS_TEMPERATURE[] = "CMOSTemperature";
|
||||
static const char MCU_TEMPERATURE[] = "MCUTemperature";
|
||||
|
||||
static const char MOUNTING[] = "mounting";
|
||||
static const char MOUNTING[] = "Mounting";
|
||||
static const char qw[] = "qw";
|
||||
static const char qx[] = "qx";
|
||||
static const char qy[] = "qy";
|
||||
static const char qz[] = "qz";
|
||||
|
||||
static const char IMAGE_PROCESSOR[] = "imageprocessor";
|
||||
static const char IMAGE_PROCESSOR[] = "ImageProcessor";
|
||||
static const char IMAGE_PROCESSOR_MODE[] = "mode";
|
||||
static const char STORE[] = "store";
|
||||
static const char SIGNAL_THRESHOLD[] = "signalThreshold";
|
||||
static const char IMAGE_PROCESSOR_DARK_THRESHOLD[] = "darkThreshold";
|
||||
static const char BACKGROUND_COMPENSATION[] = "backgroundcompensation";
|
||||
|
||||
static const char CAMERA[] = "camera";
|
||||
static const char CAMERA[] = "Camera";
|
||||
static const char MODE[] = "mode";
|
||||
static const char FOCALLENGTH[] = "focallength";
|
||||
static const char EXPOSURE[] = "exposure";
|
||||
@ -77,7 +77,7 @@ static const char ENABLE_HISTOGRAM[] = "enableHistogram";
|
||||
static const char ENABLE_CONTRAST[] = "enableContrast";
|
||||
static const char BIN_MODE[] = "binMode";
|
||||
|
||||
static const char CENTROIDING[] = "centroiding";
|
||||
static const char CENTROIDING[] = "Centroiding";
|
||||
static const char ENABLE_FILTER[] = "enableFilter";
|
||||
static const char MAX_QUALITY[] = "maxquality";
|
||||
static const char DARK_THRESHOLD[] = "darkthreshold";
|
||||
@ -92,7 +92,7 @@ static const char TRANSMATRIX_01[] = "transmatrix01";
|
||||
static const char TRANSMATRIX_10[] = "transmatrix10";
|
||||
static const char TRANSMATRIX_11[] = "transmatrix11";
|
||||
|
||||
static const char LISA[] = "lisa";
|
||||
static const char LISA[] = "LISA";
|
||||
static const char LISA_MODE[] = "mode";
|
||||
static const char PREFILTER_DIST_THRESHOLD[] = "prefilterDistThreshold";
|
||||
static const char PREFILTER_ANGLE_THRESHOLD[] = "prefilterAngleThreshold";
|
||||
@ -108,29 +108,29 @@ static const char MAX_COMBINATIONS[] = "max_combinations";
|
||||
static const char NR_STARS_STOP[] = "nr_stars_stop";
|
||||
static const char FRACTION_CLOSE_STOP[] = "fraction_close_stop";
|
||||
|
||||
static const char MATCHING[] = "matching";
|
||||
static const char MATCHING[] = "Matching";
|
||||
static const char SQUARED_DISTANCE_LIMIT[] = "squaredDistanceLimit";
|
||||
static const char SQUARED_SHIFT_LIMIT[] = "squaredShiftLimit";
|
||||
|
||||
static const char VALIDATION[] = "validation";
|
||||
static const char VALIDATION[] = "Validation";
|
||||
static const char STABLE_COUNT[] = "stable_count";
|
||||
static const char MAX_DIFFERENCE[] = "max_difference";
|
||||
static const char MIN_TRACKER_CONFIDENCE[] = "min_trackerConfidence";
|
||||
static const char MIN_MATCHED_STARS[] = "min_matchedStars";
|
||||
|
||||
static const char TRACKING[] = "tracking";
|
||||
static const char TRACKING[] = "Tracking";
|
||||
static const char THIN_LIMIT[] = "thinLimit";
|
||||
static const char OUTLIER_THRESHOLD[] = "outlierThreshold";
|
||||
static const char OUTLIER_THRESHOLD_QUEST[] = "outlierThresholdQUEST";
|
||||
static const char TRACKER_CHOICE[] = "trackerChoice";
|
||||
|
||||
static const char ALGO[] = "algo";
|
||||
static const char ALGO[] = "Algo";
|
||||
static const char L2T_MIN_CONFIDENCE[] = "l2t_minConfidence";
|
||||
static const char L2T_MIN_MATCHED[] = "l2t_minMatched";
|
||||
static const char T2L_MIN_CONFIDENCE[] = "t2l_minConfidence";
|
||||
static const char T2L_MIN_MATCHED[] = "t2l_minMatched";
|
||||
|
||||
static const char LOGLEVEL[] = "loglevel";
|
||||
static const char LOGLEVEL[] = "LogLevel";
|
||||
static const char LOGLEVEL1[] = "loglevel1";
|
||||
static const char LOGLEVEL2[] = "loglevel2";
|
||||
static const char LOGLEVEL3[] = "loglevel3";
|
||||
@ -148,7 +148,7 @@ static const char LOGLEVEL14[] = "loglevel14";
|
||||
static const char LOGLEVEL15[] = "loglevel15";
|
||||
static const char LOGLEVEL16[] = "loglevel16";
|
||||
|
||||
static const char SUBSCRIPTION[] = "subscription";
|
||||
static const char SUBSCRIPTION[] = "Subscription";
|
||||
static const char TELEMETRY_1[] = "telemetry1";
|
||||
static const char TELEMETRY_2[] = "telemetry2";
|
||||
static const char TELEMETRY_3[] = "telemetry3";
|
||||
@ -166,13 +166,13 @@ static const char TELEMETRY_14[] = "telemetry14";
|
||||
static const char TELEMETRY_15[] = "telemetry15";
|
||||
static const char TELEMETRY_16[] = "telemetry16";
|
||||
|
||||
static const char LOG_SUBSCRIPTION[] = "logsubscription";
|
||||
static const char LOG_SUBSCRIPTION[] = "LogSubscription";
|
||||
static const char LEVEL1[] = "level1";
|
||||
static const char MODULE1[] = "module1";
|
||||
static const char LEVEL2[] = "level2";
|
||||
static const char MODULE2[] = "module2";
|
||||
|
||||
static const char DEBUG_CAMERA[] = "debugcamera";
|
||||
static const char DEBUG_CAMERA[] = "DebugCamera";
|
||||
static const char TIMING[] = "timing";
|
||||
static const char TEST[] = "test";
|
||||
|
||||
|
@ -91,6 +91,7 @@ enum PoolIds : lp_id_t {
|
||||
LISA_QZ,
|
||||
LISA_PERC_CLOSE,
|
||||
LISA_NR_CLOSE,
|
||||
STR_MODE,
|
||||
TRUST_WORTHY,
|
||||
STABLE_COUNT,
|
||||
SOLUTION_STRATEGY,
|
||||
@ -358,7 +359,7 @@ static const uint8_t VERSION_SET_ENTRIES = 5;
|
||||
static const uint8_t INTERFACE_SET_ENTRIES = 4;
|
||||
static const uint8_t POWER_SET_ENTRIES = 18;
|
||||
static const uint8_t TIME_SET_ENTRIES = 4;
|
||||
static const uint8_t SOLUTION_SET_ENTRIES = 23;
|
||||
static const uint8_t SOLUTION_SET_ENTRIES = 25;
|
||||
static const uint8_t HISTOGRAM_SET_ENTRIES = 38;
|
||||
static const uint8_t CHECKSUM_SET_ENTRIES = 1;
|
||||
static const uint8_t CAMERA_SET_ENTRIES = 24;
|
||||
@ -640,7 +641,7 @@ class TimeSet : public StaticLocalDataSet<TIME_SET_ENTRIES> {
|
||||
*/
|
||||
class SolutionSet : public StaticLocalDataSet<SOLUTION_SET_ENTRIES> {
|
||||
public:
|
||||
static const size_t SIZE = 78;
|
||||
static const size_t SIZE = 79;
|
||||
|
||||
SolutionSet(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, SOLUTION_SET_ID) {}
|
||||
|
||||
@ -682,6 +683,7 @@ class SolutionSet : public StaticLocalDataSet<SOLUTION_SET_ENTRIES> {
|
||||
lp_var_t<float>(sid.objectId, PoolIds::LISA_PERC_CLOSE, this);
|
||||
// Number of close stars in LISA solution
|
||||
lp_var_t<uint8_t> lisaNrClose = lp_var_t<uint8_t>(sid.objectId, PoolIds::LISA_NR_CLOSE, this);
|
||||
lp_var_t<uint8_t> strMode = lp_var_t<uint8_t>(sid.objectId, PoolIds::STR_MODE, this);
|
||||
// Gives a combined overview of the validation parameters (1 for valid solution, otherwise 0)
|
||||
lp_var_t<uint8_t> isTrustWorthy = lp_var_t<uint8_t>(sid.objectId, PoolIds::TRUST_WORTHY, this);
|
||||
// Number of times the validation criteria was met
|
||||
|
@ -1,3 +1 @@
|
||||
|
||||
target_sources(
|
||||
${LIB_EIVE_MISSION} PRIVATE CfdpHandler.cpp)
|
||||
target_sources(${LIB_EIVE_MISSION} PRIVATE CfdpHandler.cpp)
|
||||
|
@ -151,49 +151,60 @@ void AcsController::performSafe() {
|
||||
if (result != MultiplicativeKalmanFilter::MEKF_RUNNING &&
|
||||
result != MultiplicativeKalmanFilter::MEKF_INITIALIZED) {
|
||||
if (not mekfInvalidFlag) {
|
||||
triggerEvent(acs::MEKF_INVALID_INFO);
|
||||
triggerEvent(acs::MEKF_INVALID_INFO, (uint32_t)mekfData.mekfStatus.value);
|
||||
mekfInvalidFlag = true;
|
||||
}
|
||||
if (result == MultiplicativeKalmanFilter::MEKF_NOT_FINITE && !mekfLost) {
|
||||
triggerEvent(acs::MEKF_AUTOMATIC_RESET);
|
||||
navigation.resetMekf(&mekfData);
|
||||
mekfLost = true;
|
||||
}
|
||||
} else {
|
||||
} else if (mekfInvalidFlag) {
|
||||
triggerEvent(acs::MEKF_RECOVERY);
|
||||
mekfInvalidFlag = false;
|
||||
}
|
||||
// get desired satellite rate and sun direction to align
|
||||
double satRateSafe[3] = {0, 0, 0}, sunTargetDir[3] = {0, 0, 0};
|
||||
guidance.getTargetParamsSafe(sunTargetDir, satRateSafe);
|
||||
// if MEKF is working
|
||||
|
||||
// get desired satellite rate, sun direction to align to and inertia
|
||||
double sunTargetDir[3] = {0, 0, 0};
|
||||
guidance.getTargetParamsSafe(sunTargetDir);
|
||||
|
||||
double magMomMtq[3] = {0, 0, 0}, errAng = 0.0;
|
||||
if (result == MultiplicativeKalmanFilter::MEKF_RUNNING) {
|
||||
result = safeCtrl.safeMekf(now, mekfData.quatMekf.value, mekfData.quatMekf.isValid(),
|
||||
mgmDataProcessed.magIgrfModel.value,
|
||||
mgmDataProcessed.magIgrfModel.isValid(),
|
||||
susDataProcessed.sunIjkModel.value, susDataProcessed.isValid(),
|
||||
mekfData.satRotRateMekf.value, mekfData.satRotRateMekf.isValid(),
|
||||
sunTargetDir, satRateSafe, &errAng, magMomMtq);
|
||||
} else {
|
||||
result = safeCtrl.safeNoMekf(
|
||||
now, susDataProcessed.susVecTot.value, susDataProcessed.susVecTot.isValid(),
|
||||
susDataProcessed.susVecTotDerivative.value, susDataProcessed.susVecTotDerivative.isValid(),
|
||||
mgmDataProcessed.mgmVecTot.value, mgmDataProcessed.mgmVecTot.isValid(),
|
||||
mgmDataProcessed.mgmVecTotDerivative.value, mgmDataProcessed.mgmVecTotDerivative.isValid(),
|
||||
sunTargetDir, satRateSafe, &errAng, magMomMtq);
|
||||
}
|
||||
if (result == returnvalue::FAILED) {
|
||||
if (not safeCtrlFailureFlag) {
|
||||
triggerEvent(acs::SAFE_MODE_CONTROLLER_FAILURE);
|
||||
safeCtrlFailureFlag = true;
|
||||
}
|
||||
safeCtrlFailureCounter++;
|
||||
if (safeCtrlFailureCounter > 150) {
|
||||
uint8_t safeCtrlStrat = safeCtrl.safeCtrlStrategy(
|
||||
mgmDataProcessed.mgmVecTot.isValid(), not mekfInvalidFlag,
|
||||
gyrDataProcessed.gyrVecTot.isValid(), susDataProcessed.susVecTot.isValid(),
|
||||
acsParameters.safeModeControllerParameters.useMekf,
|
||||
acsParameters.safeModeControllerParameters.dampingDuringEclipse);
|
||||
switch (safeCtrlStrat) {
|
||||
case (acs::SafeModeStrategy::SAFECTRL_ACTIVE_MEKF):
|
||||
safeCtrl.safeMekf(mgmDataProcessed.mgmVecTot.value, mekfData.satRotRateMekf.value,
|
||||
susDataProcessed.sunIjkModel.value, mekfData.quatMekf.value, sunTargetDir,
|
||||
magMomMtq, errAng);
|
||||
safeCtrlFailureFlag = false;
|
||||
safeCtrlFailureCounter = 0;
|
||||
}
|
||||
} else {
|
||||
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);
|
||||
safeCtrlFailureFlag = false;
|
||||
safeCtrlFailureCounter = 0;
|
||||
break;
|
||||
case (acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING):
|
||||
safeCtrl.safeRateDamping(mgmDataProcessed.mgmVecTot.value, gyrDataProcessed.gyrVecTot.value,
|
||||
sunTargetDir, magMomMtq, errAng);
|
||||
safeCtrlFailureFlag = false;
|
||||
safeCtrlFailureCounter = 0;
|
||||
break;
|
||||
case (acs::SafeModeStrategy::SAFECTRL_ECLIPSE_IDELING):
|
||||
errAng = NAN;
|
||||
safeCtrlFailureFlag = false;
|
||||
safeCtrlFailureCounter = 0;
|
||||
break;
|
||||
case (acs::SafeModeStrategy::SAFECTRL_NO_MAG_FIELD_FOR_CONTROL):
|
||||
safeCtrlFailure(1, 0);
|
||||
break;
|
||||
case (acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL):
|
||||
safeCtrlFailure(0, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
actuatorCmd.cmdDipolMtq(magMomMtq, cmdDipolMtqs,
|
||||
@ -201,7 +212,7 @@ void AcsController::performSafe() {
|
||||
acsParameters.magnetorquerParameter.dipolMax);
|
||||
|
||||
// detumble check and switch
|
||||
if (mekfData.satRotRateMekf.isValid() &&
|
||||
if (mekfData.satRotRateMekf.isValid() && acsParameters.safeModeControllerParameters.useMekf &&
|
||||
VectorOperations<double>::norm(mekfData.satRotRateMekf.value, 3) >
|
||||
acsParameters.detumbleParameter.omegaDetumbleStart) {
|
||||
detumbleCounter++;
|
||||
@ -219,10 +230,10 @@ void AcsController::performSafe() {
|
||||
startTransition(mode, acs::SafeSubmode::DETUMBLE);
|
||||
}
|
||||
|
||||
updateCtrlValData(errAng);
|
||||
updateCtrlValData(errAng, safeCtrlStrat);
|
||||
updateActuatorCmdData(cmdDipolMtqs);
|
||||
// commandActuators(cmdDipolMtqs[0], cmdDipolMtqs[1], cmdDipolMtqs[2],
|
||||
// acsParameters.magnetorquerParameter.torqueDuration);
|
||||
commandActuators(cmdDipolMtqs[0], cmdDipolMtqs[1], cmdDipolMtqs[2],
|
||||
acsParameters.magnetorquerParameter.torqueDuration);
|
||||
}
|
||||
|
||||
void AcsController::performDetumble() {
|
||||
@ -236,20 +247,40 @@ void AcsController::performDetumble() {
|
||||
if (result != MultiplicativeKalmanFilter::MEKF_RUNNING &&
|
||||
result != MultiplicativeKalmanFilter::MEKF_INITIALIZED) {
|
||||
if (not mekfInvalidFlag) {
|
||||
triggerEvent(acs::MEKF_INVALID_INFO);
|
||||
triggerEvent(acs::MEKF_INVALID_INFO, (uint32_t)mekfData.mekfStatus.value);
|
||||
mekfInvalidFlag = true;
|
||||
}
|
||||
if (result == MultiplicativeKalmanFilter::MEKF_NOT_FINITE && !mekfLost) {
|
||||
triggerEvent(acs::MEKF_AUTOMATIC_RESET);
|
||||
navigation.resetMekf(&mekfData);
|
||||
mekfLost = true;
|
||||
}
|
||||
} else {
|
||||
} else if (mekfInvalidFlag) {
|
||||
triggerEvent(acs::MEKF_RECOVERY);
|
||||
mekfInvalidFlag = false;
|
||||
}
|
||||
uint8_t safeCtrlStrat = detumble.detumbleStrategy(
|
||||
mgmDataProcessed.mgmVecTot.isValid(), gyrDataProcessed.gyrVecTot.isValid(),
|
||||
mgmDataProcessed.mgmVecTotDerivative.isValid(),
|
||||
acsParameters.detumbleParameter.useFullDetumbleLaw);
|
||||
double magMomMtq[3] = {0, 0, 0};
|
||||
detumble.bDotLaw(mgmDataProcessed.mgmVecTotDerivative.value,
|
||||
mgmDataProcessed.mgmVecTotDerivative.isValid(), mgmDataProcessed.mgmVecTot.value,
|
||||
mgmDataProcessed.mgmVecTot.isValid(), magMomMtq,
|
||||
acsParameters.detumbleParameter.gainD);
|
||||
switch (safeCtrlStrat) {
|
||||
case (acs::SafeModeStrategy::SAFECTRL_DETUMBLE_FULL):
|
||||
detumble.bDotLawFull(gyrDataProcessed.gyrVecTot.value, mgmDataProcessed.mgmVecTot.value,
|
||||
magMomMtq, acsParameters.detumbleParameter.gainFull);
|
||||
break;
|
||||
case (acs::SafeModeStrategy::SAFECTRL_DETUMBLE_DETERIORATED):
|
||||
detumble.bDotLaw(mgmDataProcessed.mgmVecTotDerivative.value, mgmDataProcessed.mgmVecTot.value,
|
||||
magMomMtq, acsParameters.detumbleParameter.gainBdot);
|
||||
break;
|
||||
case (acs::SafeModeStrategy::SAFECTRL_NO_MAG_FIELD_FOR_CONTROL):
|
||||
safeCtrlFailure(1, 0);
|
||||
break;
|
||||
case (acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL):
|
||||
safeCtrlFailure(0, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
actuatorCmd.cmdDipolMtq(magMomMtq, cmdDipolMtqs,
|
||||
*acsParameters.magnetorquerParameter.inverseAlignment,
|
||||
acsParameters.magnetorquerParameter.dipolMax);
|
||||
@ -274,9 +305,8 @@ void AcsController::performDetumble() {
|
||||
|
||||
disableCtrlValData();
|
||||
updateActuatorCmdData(cmdDipolMtqs);
|
||||
// commandActuators(cmdDipolMtqs[0], cmdDipolMtqs[1], cmdDipolMtqs[2],
|
||||
// acsParameters.magnetorquesParameter.torqueDuration, 0, 0, 0, 0,
|
||||
// acsParameters.rwHandlingParameters.rampTime);
|
||||
commandActuators(cmdDipolMtqs[0], cmdDipolMtqs[1], cmdDipolMtqs[2],
|
||||
acsParameters.magnetorquerParameter.torqueDuration);
|
||||
}
|
||||
|
||||
void AcsController::performPointingCtrl() {
|
||||
@ -291,21 +321,22 @@ void AcsController::performPointingCtrl() {
|
||||
result != MultiplicativeKalmanFilter::MEKF_INITIALIZED) {
|
||||
mekfInvalidCounter++;
|
||||
if (not mekfInvalidFlag) {
|
||||
triggerEvent(acs::MEKF_INVALID_INFO);
|
||||
triggerEvent(acs::MEKF_INVALID_INFO, (uint32_t)mekfData.mekfStatus.value);
|
||||
mekfInvalidFlag = true;
|
||||
}
|
||||
if (result == MultiplicativeKalmanFilter::MEKF_NOT_FINITE && !mekfLost) {
|
||||
triggerEvent(acs::MEKF_AUTOMATIC_RESET);
|
||||
navigation.resetMekf(&mekfData);
|
||||
mekfLost = true;
|
||||
}
|
||||
if (mekfInvalidCounter > acsParameters.onBoardParams.mekfViolationTimer) {
|
||||
// Trigger this so STR FDIR can set the device faulty.
|
||||
EventManagerIF::triggerEvent(objects::STAR_TRACKER, acs::MEKF_INVALID_MODE_VIOLATION, 0, 0);
|
||||
mekfInvalidCounter = 0;
|
||||
}
|
||||
// commandActuators(0, 0, 0, acsParameters.magnetorquesParameter.torqueDuration,
|
||||
// cmdSpeedRws[0],
|
||||
// cmdSpeedRws[1], cmdSpeedRws[2], cmdSpeedRws[3],
|
||||
// acsParameters.rwHandlingParameters.rampTime);
|
||||
commandActuators(0, 0, 0, acsParameters.magnetorquerParameter.torqueDuration, cmdSpeedRws[0],
|
||||
cmdSpeedRws[1], cmdSpeedRws[2], cmdSpeedRws[3],
|
||||
acsParameters.rwHandlingParameters.rampTime);
|
||||
return;
|
||||
} else {
|
||||
if (mekfInvalidFlag) {
|
||||
@ -465,10 +496,22 @@ void AcsController::performPointingCtrl() {
|
||||
|
||||
updateCtrlValData(targetQuat, errorQuat, errorAngle, targetSatRotRate);
|
||||
updateActuatorCmdData(torqueRws, cmdSpeedRws, cmdDipolMtqs);
|
||||
// commandActuators(cmdDipolMtqs[0], cmdDipolMtqs[1], cmdDipolMtqs[2],
|
||||
// acsParameters.magnetorquesParameter.torqueDuration, cmdSpeedRws[0],
|
||||
// cmdSpeedRws[1], cmdSpeedRws[2], cmdSpeedRws[3],
|
||||
// acsParameters.rwHandlingParameters.rampTime);
|
||||
commandActuators(cmdDipolMtqs[0], cmdDipolMtqs[1], cmdDipolMtqs[2],
|
||||
acsParameters.magnetorquerParameter.torqueDuration, cmdSpeedRws[0],
|
||||
cmdSpeedRws[1], cmdSpeedRws[2], cmdSpeedRws[3],
|
||||
acsParameters.rwHandlingParameters.rampTime);
|
||||
}
|
||||
|
||||
void AcsController::safeCtrlFailure(uint8_t mgmFailure, uint8_t sensorFailure) {
|
||||
if (not safeCtrlFailureFlag) {
|
||||
triggerEvent(acs::SAFE_MODE_CONTROLLER_FAILURE, mgmFailure, sensorFailure);
|
||||
safeCtrlFailureFlag = true;
|
||||
}
|
||||
safeCtrlFailureCounter++;
|
||||
if (safeCtrlFailureCounter > 150) {
|
||||
safeCtrlFailureFlag = false;
|
||||
safeCtrlFailureCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t AcsController::commandActuators(int16_t xDipole, int16_t yDipole, int16_t zDipole,
|
||||
@ -529,17 +572,19 @@ void AcsController::updateActuatorCmdData(const double *rwTargetTorque,
|
||||
}
|
||||
}
|
||||
|
||||
void AcsController::updateCtrlValData(double errAng) {
|
||||
void AcsController::updateCtrlValData(double errAng, uint8_t safeModeStrat) {
|
||||
PoolReadGuard pg(&ctrlValData);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(ctrlValData.tgtQuat.value, UNIT_QUAT, 4 * sizeof(double));
|
||||
std::memcpy(ctrlValData.tgtQuat.value, ZERO_VEC4, 4 * sizeof(double));
|
||||
ctrlValData.tgtQuat.setValid(false);
|
||||
std::memcpy(ctrlValData.errQuat.value, UNIT_QUAT, 4 * sizeof(double));
|
||||
std::memcpy(ctrlValData.errQuat.value, ZERO_VEC4, 4 * sizeof(double));
|
||||
ctrlValData.errQuat.setValid(false);
|
||||
ctrlValData.errAng.value = errAng;
|
||||
ctrlValData.errAng.setValid(true);
|
||||
std::memcpy(ctrlValData.tgtRotRate.value, ZERO_VEC, 3 * sizeof(double));
|
||||
std::memcpy(ctrlValData.tgtRotRate.value, ZERO_VEC3, 3 * sizeof(double));
|
||||
ctrlValData.tgtRotRate.setValid(false);
|
||||
ctrlValData.safeStrat.value = safeModeStrat;
|
||||
ctrlValData.safeStrat.setValid(true);
|
||||
ctrlValData.setValidity(true, false);
|
||||
}
|
||||
}
|
||||
@ -552,6 +597,7 @@ void AcsController::updateCtrlValData(const double *tgtQuat, const double *errQu
|
||||
std::memcpy(ctrlValData.errQuat.value, errQuat, 4 * sizeof(double));
|
||||
ctrlValData.errAng.value = errAng;
|
||||
std::memcpy(ctrlValData.tgtRotRate.value, tgtRotRate, 3 * sizeof(double));
|
||||
ctrlValData.safeStrat.value = acs::SafeModeStrategy::SAFECTRL_OFF;
|
||||
ctrlValData.setValidity(true, true);
|
||||
}
|
||||
}
|
||||
@ -559,10 +605,10 @@ void AcsController::updateCtrlValData(const double *tgtQuat, const double *errQu
|
||||
void AcsController::disableCtrlValData() {
|
||||
PoolReadGuard pg(&ctrlValData);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
std::memcpy(ctrlValData.tgtQuat.value, UNIT_QUAT, 4 * sizeof(double));
|
||||
std::memcpy(ctrlValData.errQuat.value, UNIT_QUAT, 4 * sizeof(double));
|
||||
std::memcpy(ctrlValData.tgtQuat.value, ZERO_VEC4, 4 * sizeof(double));
|
||||
std::memcpy(ctrlValData.errQuat.value, ZERO_VEC4, 4 * sizeof(double));
|
||||
ctrlValData.errAng.value = 0;
|
||||
std::memcpy(ctrlValData.tgtRotRate.value, ZERO_VEC, 3 * sizeof(double));
|
||||
std::memcpy(ctrlValData.tgtRotRate.value, ZERO_VEC3, 3 * sizeof(double));
|
||||
ctrlValData.setValidity(false, true);
|
||||
}
|
||||
}
|
||||
@ -644,6 +690,7 @@ ReturnValue_t AcsController::initializeLocalDataPool(localpool::DataPool &localD
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::MEKF_STATUS, &mekfStatus);
|
||||
poolManager.subscribeForDiagPeriodicPacket({mekfData.getSid(), enableHkSets, 10.0});
|
||||
// Ctrl Values
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::SAFE_STRAT, &safeStrat);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::TGT_QUAT, &tgtQuat);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::ERROR_QUAT, &errQuat);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::ERROR_ANG, &errAng);
|
||||
|
@ -12,18 +12,17 @@
|
||||
#include <mission/acs/imtqHelpers.h>
|
||||
#include <mission/acs/rwHelpers.h>
|
||||
#include <mission/acs/susMax1227Helpers.h>
|
||||
#include <mission/controller/acs/ActuatorCmd.h>
|
||||
#include <mission/controller/acs/Guidance.h>
|
||||
#include <mission/controller/acs/MultiplicativeKalmanFilter.h>
|
||||
#include <mission/controller/acs/Navigation.h>
|
||||
#include <mission/controller/acs/SensorProcessing.h>
|
||||
#include <mission/controller/acs/control/Detumble.h>
|
||||
#include <mission/controller/acs/control/PtgCtrl.h>
|
||||
#include <mission/controller/acs/control/SafeCtrl.h>
|
||||
#include <mission/controller/controllerdefinitions/AcsCtrlDefinitions.h>
|
||||
#include <mission/utility/trace.h>
|
||||
|
||||
#include "acs/ActuatorCmd.h"
|
||||
#include "acs/Guidance.h"
|
||||
#include "acs/MultiplicativeKalmanFilter.h"
|
||||
#include "acs/Navigation.h"
|
||||
#include "acs/SensorProcessing.h"
|
||||
#include "acs/control/Detumble.h"
|
||||
#include "acs/control/PtgCtrl.h"
|
||||
#include "acs/control/SafeCtrl.h"
|
||||
#include "controllerdefinitions/AcsCtrlDefinitions.h"
|
||||
|
||||
class AcsController : public ExtendedControllerBase, public ReceivesParameterMessagesIF {
|
||||
public:
|
||||
static constexpr dur_millis_t INIT_DELAY = 500;
|
||||
@ -41,9 +40,9 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
void performPointingCtrl();
|
||||
|
||||
private:
|
||||
static constexpr double UNIT_QUAT[4] = {0, 0, 0, 1};
|
||||
static constexpr double ZERO_VEC[3] = {0, 0, 0};
|
||||
static constexpr double RW_OFF_TORQUE[4] = {0.0, 0.0, 0.0, 0.0};
|
||||
static constexpr double ZERO_VEC3[3] = {0, 0, 0};
|
||||
static constexpr double ZERO_VEC4[4] = {0, 0, 0, 0};
|
||||
static constexpr double RW_OFF_TORQUE[4] = {0, 0, 0, 0};
|
||||
static constexpr int32_t RW_OFF_SPEED[4] = {0, 0, 0, 0};
|
||||
|
||||
bool enableHkSets = false;
|
||||
@ -85,6 +84,7 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
static const DeviceCommandId_t RESTORE_MEKF_NONFINITE_RECOVERY = 0x2;
|
||||
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::ACS_CTRL;
|
||||
//! [EXPORT] : [COMMENT] File deletion failed and at least one file is still existent.
|
||||
static constexpr ReturnValue_t FILE_DELETION_FAILED = MAKE_RETURN_CODE(0);
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
@ -105,6 +105,8 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
void modeChanged(Mode_t mode, Submode_t submode);
|
||||
void announceMode(bool recursive);
|
||||
|
||||
void safeCtrlFailure(uint8_t mgmFailure, uint8_t sensorFailure);
|
||||
|
||||
ReturnValue_t commandActuators(int16_t xDipole, int16_t yDipole, int16_t zDipole,
|
||||
uint16_t dipoleTorqueDuration);
|
||||
ReturnValue_t commandActuators(int16_t xDipole, int16_t yDipole, int16_t zDipole,
|
||||
@ -113,7 +115,7 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
void updateActuatorCmdData(const int16_t* mtqTargetDipole);
|
||||
void updateActuatorCmdData(const double* rwTargetTorque, const int32_t* rwTargetSpeed,
|
||||
const int16_t* mtqTargetDipole);
|
||||
void updateCtrlValData(double errAng);
|
||||
void updateCtrlValData(double errAng, uint8_t safeModeStrat);
|
||||
void updateCtrlValData(const double* tgtQuat, const double* errQuat, double errAng,
|
||||
const double* tgtRotRate);
|
||||
void disableCtrlValData();
|
||||
@ -212,6 +214,7 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
|
||||
// Ctrl Values
|
||||
acsctrl::CtrlValData ctrlValData;
|
||||
PoolEntry<uint8_t> safeStrat = PoolEntry<uint8_t>();
|
||||
PoolEntry<double> tgtQuat = PoolEntry<double>(4);
|
||||
PoolEntry<double> errQuat = PoolEntry<double>(4);
|
||||
PoolEntry<double> errAng = PoolEntry<double>();
|
||||
|
@ -20,6 +20,8 @@
|
||||
#define LOWER_SYRLINKS_UPPER_LIMITS 0
|
||||
#define LOWER_EBAND_UPPER_LIMITS 0
|
||||
#define LOWER_PLOC_UPPER_LIMITS 0
|
||||
#define LOWER_MGT_UPPER_LIMITS 0
|
||||
#define LOWER_RW_UPPER_LIMITS 0
|
||||
|
||||
ThermalController::ThermalController(object_id_t objectId, HeaterHandler& heater,
|
||||
const std::atomic_bool& tcsBoardShortUnavailable)
|
||||
@ -111,7 +113,7 @@ void ThermalController::performControlOperation() {
|
||||
break;
|
||||
}
|
||||
|
||||
if (cycles == 50) {
|
||||
if (cycles == 40) {
|
||||
bool changedLimits = false;
|
||||
#if LOWER_SYRLINKS_UPPER_LIMITS == 1
|
||||
changedLimits = true;
|
||||
@ -130,9 +132,21 @@ void ThermalController::performControlOperation() {
|
||||
hpaLimits.cutOffLimit = 0;
|
||||
hpaLimits.opUpperLimit = 0;
|
||||
hpaLimits.nopUpperLimit = 0;
|
||||
#endif
|
||||
#if LOWER_MGT_UPPER_LIMITS == 1
|
||||
changedLimits = true;
|
||||
mgtLimits.cutOffLimit = 0;
|
||||
mgtLimits.opUpperLimit = 0;
|
||||
mgtLimits.nopUpperLimit = 0;
|
||||
#endif
|
||||
#if LOWER_RW_UPPER_LIMITS == 1
|
||||
changedLimits = true;
|
||||
rwLimits.cutOffLimit = 0;
|
||||
rwLimits.opUpperLimit = 0;
|
||||
rwLimits.nopUpperLimit = 0;
|
||||
#endif
|
||||
if (changedLimits) {
|
||||
sif::debug << "ThermalController: changing limits" << std::endl; // TODO: rausschmeissen
|
||||
sif::debug << "ThermalController: changing limits" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,26 +184,31 @@ void ThermalController::performControlOperation() {
|
||||
}
|
||||
}
|
||||
|
||||
if (transitionToOff) {
|
||||
for (const auto& switchState : heaterSwitchStateArray) {
|
||||
if (switchState != HeaterHandler::SwitchState::OFF) {
|
||||
transitionToOffCycles++;
|
||||
// if heater still ON after 10 cycles, switch OFF again
|
||||
if (transitionToOffCycles == 10) {
|
||||
for (uint8_t i = 0; i < heater::Switchers::NUMBER_OF_SWITCHES; i++) {
|
||||
heaterHandler.switchHeater(static_cast<heater::Switchers>(i),
|
||||
HeaterHandler::SwitchState::OFF);
|
||||
}
|
||||
cycles++;
|
||||
if (transitionWhenHeatersOff) {
|
||||
bool allSwitchersOff = true;
|
||||
for (size_t idx = 0; idx < heaterSwitchStateArray.size(); idx++) {
|
||||
if (heaterSwitchStateArray[idx] != HeaterHandler::SwitchState::OFF) {
|
||||
allSwitchersOff = false;
|
||||
// if heater still ON after 3 cycles, switch OFF again
|
||||
if (transitionWhenHeatersOffCycles == 3) {
|
||||
heaterHandler.switchHeater(static_cast<heater::Switch>(idx),
|
||||
HeaterHandler::SwitchState::OFF);
|
||||
triggerEvent(tcsCtrl::HEATER_NOT_OFF_FOR_OFF_MODE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
setMode(MODE_OFF);
|
||||
}
|
||||
if (allSwitchersOff or transitionWhenHeatersOffCycles == 6) {
|
||||
// Finish the transition
|
||||
transitionWhenHeatersOff = false;
|
||||
resetThermalStates();
|
||||
setMode(targetMode, targetSubmode);
|
||||
} else {
|
||||
transitionWhenHeatersOffCycles++;
|
||||
}
|
||||
} else if (mode != MODE_OFF and not tcsBrdShortlyUnavailable) {
|
||||
performThermalModuleCtrl(heaterSwitchStateArray);
|
||||
}
|
||||
cycles++;
|
||||
}
|
||||
|
||||
ReturnValue_t ThermalController::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
@ -292,12 +311,18 @@ LocalPoolDataSetBase* ThermalController::getDataSetHandle(sid_t sid) {
|
||||
|
||||
ReturnValue_t ThermalController::checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t* msToReachTheMode) {
|
||||
if ((mode != MODE_OFF) and (mode != MODE_ON)) {
|
||||
return INVALID_MODE;
|
||||
}
|
||||
if (mode == MODE_ON) {
|
||||
if (submode != SUBMODE_NONE and submode != SUBMODE_NO_HEATER_CTRL) {
|
||||
return HasModesIF::INVALID_SUBMODE;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
if (submode != SUBMODE_NONE) {
|
||||
return INVALID_SUBMODE;
|
||||
}
|
||||
if ((mode != MODE_OFF) && (mode != MODE_ON) && (mode != MODE_NORMAL)) {
|
||||
return INVALID_MODE;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
@ -976,8 +1001,8 @@ void ThermalController::copyDevices() {
|
||||
}
|
||||
|
||||
void ThermalController::ctrlAcsBoard() {
|
||||
heater::Switchers switchNr = heater::HEATER_2_ACS_BRD;
|
||||
heater::Switchers redSwitchNr = heater::HEATER_0_OBC_BRD;
|
||||
heater::Switch switchNr = heater::HEATER_2_ACS_BRD;
|
||||
heater::Switch redSwitchNr = heater::HEATER_0_OBC_BRD;
|
||||
|
||||
// A side
|
||||
thermalComponent = ACS_BOARD;
|
||||
@ -1023,7 +1048,9 @@ void ThermalController::ctrlAcsBoard() {
|
||||
} else {
|
||||
if (chooseHeater(switchNr, redSwitchNr)) {
|
||||
if (heaterHandler.getSwitchState(switchNr)) {
|
||||
heaterHandler.switchHeater(switchNr, HeaterHandler::SwitchState::OFF);
|
||||
if (submode != SUBMODE_NO_HEATER_CTRL) {
|
||||
heaterSwitchHelper(switchNr, HeaterHandler::SwitchState::OFF, thermalComponent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1042,7 +1069,12 @@ void ThermalController::ctrlMgt() {
|
||||
numSensors = 3;
|
||||
HeaterContext htrCtx(heater::HEATER_2_ACS_BRD, heater::HEATER_3_PCDU_PDU, mgtLimits);
|
||||
ctrlComponentTemperature(htrCtx);
|
||||
// TODO: trigger special event
|
||||
if (componentAboveUpperLimit and not mgtTooHotFlag) {
|
||||
triggerEvent(tcsCtrl::MGT_OVERHEATING, tempFloatToU32());
|
||||
mgtTooHotFlag = true;
|
||||
} else if (not componentAboveUpperLimit) {
|
||||
mgtTooHotFlag = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ThermalController::ctrlRw() {
|
||||
@ -1227,7 +1259,7 @@ void ThermalController::ctrlObcIfBoard() {
|
||||
triggerEvent(tcsCtrl::OBC_OVERHEATING, tempFloatToU32());
|
||||
obcTooHotFlag = true;
|
||||
} else if (not componentAboveUpperLimit) {
|
||||
obcTooHotFlag = false; // TODO: !!
|
||||
obcTooHotFlag = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1268,8 +1300,8 @@ void ThermalController::ctrlPcduP60Board() {
|
||||
|
||||
void ThermalController::ctrlPcduAcu() {
|
||||
thermalComponent = PCDUACU;
|
||||
heater::Switchers switchNr = heater::HEATER_3_PCDU_PDU;
|
||||
heater::Switchers redSwitchNr = heater::HEATER_2_ACS_BRD;
|
||||
heater::Switch switchNr = heater::HEATER_3_PCDU_PDU;
|
||||
heater::Switch redSwitchNr = heater::HEATER_2_ACS_BRD;
|
||||
|
||||
if (chooseHeater(switchNr, redSwitchNr)) {
|
||||
bool sensorTempAvailable = true;
|
||||
@ -1557,13 +1589,16 @@ void ThermalController::performThermalModuleCtrl(const HeaterSwitchStates& heate
|
||||
void ThermalController::ctrlComponentTemperature(HeaterContext& htrCtx) {
|
||||
if (selectAndReadSensorTemp(htrCtx)) {
|
||||
if (chooseHeater(htrCtx.switchNr, htrCtx.redSwitchNr)) {
|
||||
// Core loop for a thermal component, after sensors and heaters were selected.
|
||||
checkLimitsAndCtrlHeater(htrCtx);
|
||||
}
|
||||
} else {
|
||||
// TODO: muss der Heater dann wirklich abgeschalten werden?
|
||||
// No sensors available, so switch the heater off. We can not perform control tasks if we
|
||||
// are blind..
|
||||
if (chooseHeater(htrCtx.switchNr, htrCtx.redSwitchNr)) {
|
||||
if (heaterHandler.getSwitchState(htrCtx.switchNr)) {
|
||||
heaterHandler.switchHeater(htrCtx.switchNr, HeaterHandler::SwitchState::OFF);
|
||||
if (heaterCtrlAllowed() and
|
||||
(heaterHandler.getSwitchState(htrCtx.switchNr) == HeaterHandler::SwitchState::ON)) {
|
||||
heaterSwitchHelper(htrCtx.switchNr, HeaterHandler::SwitchState::OFF, thermalComponent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1593,7 +1628,7 @@ bool ThermalController::selectAndReadSensorTemp(HeaterContext& htrCtx) {
|
||||
|
||||
return false;
|
||||
}
|
||||
bool ThermalController::chooseHeater(heater::Switchers& switchNr, heater::Switchers redSwitchNr) {
|
||||
bool ThermalController::chooseHeater(heater::Switch& switchNr, heater::Switch redSwitchNr) {
|
||||
bool heaterAvailable = true;
|
||||
|
||||
if (heaterHandler.getHealth(switchNr) != HasHealthIF::HEALTHY) {
|
||||
@ -1611,15 +1646,18 @@ bool ThermalController::chooseHeater(heater::Switchers& switchNr, heater::Switch
|
||||
}
|
||||
|
||||
void ThermalController::heaterCtrlTempTooHighHandler(HeaterContext& htrCtx, const char* whatLimit) {
|
||||
if (not heaterCtrlAllowed()) {
|
||||
return;
|
||||
}
|
||||
if (htrCtx.switchState == HeaterHandler::SwitchState::ON) {
|
||||
sif::info << "TCS: Component " << static_cast<int>(thermalComponent) << " too warm, above "
|
||||
<< whatLimit << ", switching off heater" << std::endl;
|
||||
heaterHandler.switchHeater(htrCtx.switchNr, HeaterHandler::SwitchState::OFF);
|
||||
heaterSwitchHelper(htrCtx.switchNr, HeaterHandler::SwitchState::OFF, thermalComponent);
|
||||
heaterStates[htrCtx.switchNr].switchTransition = true;
|
||||
heaterStates[htrCtx.switchNr].target = HeaterHandler::SwitchState::OFF;
|
||||
}
|
||||
if (heaterHandler.getSwitchState(htrCtx.redSwitchNr) == HeaterHandler::SwitchState::ON) {
|
||||
heaterHandler.switchHeater(htrCtx.redSwitchNr, HeaterHandler::SwitchState::OFF);
|
||||
heaterSwitchHelper(htrCtx.redSwitchNr, HeaterHandler::SwitchState::OFF, thermalComponent);
|
||||
heaterStates[htrCtx.redSwitchNr].switchTransition = true;
|
||||
heaterStates[htrCtx.redSwitchNr].target = HeaterHandler::SwitchState::OFF;
|
||||
}
|
||||
@ -1634,43 +1672,44 @@ void ThermalController::checkLimitsAndCtrlHeater(HeaterContext& htrCtx) {
|
||||
if (heaterStates[htrCtx.switchNr].switchTransition) {
|
||||
htrCtx.doHeaterHandling = false;
|
||||
heaterCtrlCheckUpperLimits(htrCtx);
|
||||
} else {
|
||||
// Heater off
|
||||
htrCtx.switchState = heaterHandler.getSwitchState(htrCtx.switchNr);
|
||||
if (htrCtx.switchState == HeaterHandler::SwitchState::OFF) {
|
||||
if (sensorTemp < htrCtx.tempLimit.opLowerLimit) {
|
||||
heaterHandler.switchHeater(htrCtx.switchNr, HeaterHandler::SwitchState::ON);
|
||||
sif::info << "ThermalController::checkLimitsAndCtrlHeater: Heater "
|
||||
<< static_cast<int>(thermalComponent) << " ON" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
htrCtx.switchState = heaterHandler.getSwitchState(htrCtx.switchNr);
|
||||
// Heater off
|
||||
if (htrCtx.switchState == HeaterHandler::SwitchState::OFF) {
|
||||
if (sensorTemp < htrCtx.tempLimit.opLowerLimit and heaterCtrlAllowed()) {
|
||||
sif::info << "TCS: Heater " << static_cast<int>(thermalComponent) << " ON" << std::endl;
|
||||
heaterSwitchHelper(htrCtx.switchNr, HeaterHandler::SwitchState::ON, thermalComponent);
|
||||
heaterStates[htrCtx.switchNr].switchTransition = true;
|
||||
heaterStates[htrCtx.switchNr].target = HeaterHandler::SwitchState::ON;
|
||||
} else {
|
||||
// Even if heater control is now allowed, we can update the state.
|
||||
thermalStates[thermalComponent].heating = false;
|
||||
}
|
||||
heaterCtrlCheckUpperLimits(htrCtx);
|
||||
return;
|
||||
}
|
||||
|
||||
// Heater on
|
||||
if (htrCtx.switchState == HeaterHandler::SwitchState::ON) {
|
||||
if (thermalStates[thermalComponent].heating) {
|
||||
// We are already in a heating cycle, so need to check whether heating task is complete.
|
||||
if (sensorTemp >= htrCtx.tempLimit.opLowerLimit + TEMP_OFFSET and heaterCtrlAllowed()) {
|
||||
sif::info << "TCS: Heater " << static_cast<int>(thermalComponent) << " OFF" << std::endl;
|
||||
heaterSwitchHelper(htrCtx.switchNr, HeaterHandler::SwitchState::OFF, thermalComponent);
|
||||
heaterStates[htrCtx.switchNr].switchTransition = true;
|
||||
thermalStates[thermalComponent].heating = true;
|
||||
heaterStates[htrCtx.switchNr].target = HeaterHandler::SwitchState::ON;
|
||||
} else {
|
||||
thermalStates[thermalComponent].heating = false;
|
||||
heaterStates[htrCtx.switchNr].target = HeaterHandler::SwitchState::OFF;
|
||||
}
|
||||
heaterCtrlCheckUpperLimits(htrCtx);
|
||||
// Heater on
|
||||
} else if (heaterHandler.getSwitchState(htrCtx.switchNr) == HeaterHandler::SwitchState::ON) {
|
||||
if (thermalStates[thermalComponent].heating) {
|
||||
// We are already in a heating cycle, so need to check whether heating task is complete.
|
||||
if (sensorTemp >= htrCtx.tempLimit.opLowerLimit + TEMP_OFFSET) {
|
||||
heaterHandler.switchHeater(htrCtx.switchNr, HeaterHandler::SwitchState::OFF);
|
||||
sif::info << "ThermalController::checkLimitsAndCtrlHeater: Heater "
|
||||
<< static_cast<int>(thermalComponent) << " OFF" << std::endl;
|
||||
heaterStates[htrCtx.switchNr].switchTransition = true;
|
||||
heaterStates[htrCtx.switchNr].target = HeaterHandler::SwitchState::OFF;
|
||||
thermalStates[thermalComponent].heating = false;
|
||||
}
|
||||
} else {
|
||||
// This can happen if heater is used as alternative heater (no regular heating cycle), so we
|
||||
// should still check the upper limits.
|
||||
bool tooHighHandlerAlreadyCalled = heaterCtrlCheckUpperLimits(htrCtx);
|
||||
if (sensorTemp >= htrCtx.tempLimit.cutOffLimit) {
|
||||
componentAboveCutOffLimit = true;
|
||||
if (not tooHighHandlerAlreadyCalled) {
|
||||
heaterCtrlTempTooHighHandler(htrCtx, "CutOff-Limit");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// This can happen if heater is used as alternative heater (no regular heating cycle), so we
|
||||
// should still check the upper limits.
|
||||
bool tooHighHandlerAlreadyCalled = heaterCtrlCheckUpperLimits(htrCtx);
|
||||
if (sensorTemp >= htrCtx.tempLimit.cutOffLimit) {
|
||||
componentAboveCutOffLimit = true;
|
||||
if (not tooHighHandlerAlreadyCalled) {
|
||||
heaterCtrlTempTooHighHandler(htrCtx, "CutOff-Limit");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1702,8 +1741,8 @@ void ThermalController::resetSensorsArray() {
|
||||
}
|
||||
thermalComponent = NONE;
|
||||
}
|
||||
|
||||
void ThermalController::heaterTransitionControl(const HeaterSwitchStates& currentHeaterStates) {
|
||||
// TODO: Test
|
||||
for (unsigned i = 0; i < 7; i++) {
|
||||
if (heaterStates[i].switchTransition) {
|
||||
if (currentHeaterStates[i] == heaterStates[i].target) {
|
||||
@ -1727,11 +1766,12 @@ uint32_t ThermalController::tempFloatToU32() const {
|
||||
return tempRaw;
|
||||
}
|
||||
|
||||
void ThermalController::setMode(Mode_t mode) {
|
||||
void ThermalController::setMode(Mode_t mode, Submode_t submode) {
|
||||
if (mode == MODE_OFF) {
|
||||
transitionToOff = false;
|
||||
transitionWhenHeatersOff = false;
|
||||
}
|
||||
this->mode = mode;
|
||||
this->submode = submode;
|
||||
modeHelper.modeChanged(mode, submode);
|
||||
announceMode(false);
|
||||
}
|
||||
@ -1746,6 +1786,43 @@ bool ThermalController::tooHotHandler(object_id_t object, bool& oneShotFlag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ThermalController::heaterCtrlAllowed() const { return submode != SUBMODE_NO_HEATER_CTRL; }
|
||||
|
||||
void ThermalController::resetThermalStates() {
|
||||
for (auto& thermalState : thermalStates) {
|
||||
thermalState.heating = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ThermalController::heaterSwitchHelper(heater::Switch switchNr,
|
||||
HeaterHandler::SwitchState state,
|
||||
unsigned componentIdx) {
|
||||
timeval currentTime;
|
||||
Clock::getClockMonotonic(¤tTime);
|
||||
if (state == HeaterHandler::SwitchState::ON) {
|
||||
heaterHandler.switchHeater(switchNr, state);
|
||||
thermalStates[componentIdx].heating = true;
|
||||
thermalStates[componentIdx].heaterStartTime = currentTime.tv_sec;
|
||||
} else {
|
||||
heaterHandler.switchHeater(switchNr, state);
|
||||
thermalStates[componentIdx].heating = false;
|
||||
thermalStates[componentIdx].heaterEndTime = currentTime.tv_sec;
|
||||
}
|
||||
}
|
||||
|
||||
void ThermalController::heaterSwitchHelperAllOff() {
|
||||
timeval currentTime;
|
||||
Clock::getClockMonotonic(¤tTime);
|
||||
size_t idx = 0;
|
||||
for (; idx < heater::Switch::NUMBER_OF_SWITCHES; idx++) {
|
||||
heaterHandler.switchHeater(static_cast<heater::Switch>(idx), HeaterHandler::SwitchState::OFF);
|
||||
}
|
||||
for (idx = 0; idx < thermalStates.size(); idx++) {
|
||||
thermalStates[idx].heating = false;
|
||||
thermalStates[idx].heaterEndTime = currentTime.tv_sec;
|
||||
}
|
||||
}
|
||||
|
||||
void ThermalController::tooHotHandlerWhichClearsOneShotFlag(object_id_t object, bool& oneShotFlag) {
|
||||
// Clear the one shot flag is the component is in acceptable temperature range.
|
||||
if (not tooHotHandler(object, oneShotFlag) and not componentAboveUpperLimit) {
|
||||
@ -1755,14 +1832,15 @@ void ThermalController::tooHotHandlerWhichClearsOneShotFlag(object_id_t object,
|
||||
|
||||
void ThermalController::startTransition(Mode_t mode_, Submode_t submode_) {
|
||||
triggerEvent(CHANGING_MODE, mode_, submode_);
|
||||
if (mode_ == MODE_OFF) {
|
||||
for (uint8_t i = 0; i < heater::Switchers::NUMBER_OF_SWITCHES; i++) {
|
||||
heaterHandler.switchHeater(static_cast<heater::Switchers>(i),
|
||||
HeaterHandler::SwitchState::OFF);
|
||||
}
|
||||
transitionToOff = true;
|
||||
transitionToOffCycles = 0;
|
||||
// For MODE_OFF and the no heater control submode, we command all switches to off before
|
||||
// completing the transition. This ensures a consistent state when commanding these modes.
|
||||
if ((mode_ == MODE_OFF) or ((mode_ == MODE_ON) and (submode_ == SUBMODE_NO_HEATER_CTRL))) {
|
||||
heaterSwitchHelperAllOff();
|
||||
transitionWhenHeatersOff = true;
|
||||
targetMode = mode_;
|
||||
targetSubmode = submode_;
|
||||
transitionWhenHeatersOffCycles = 0;
|
||||
} else {
|
||||
setMode(mode_);
|
||||
setMode(mode_, submode_);
|
||||
}
|
||||
}
|
||||
|
@ -48,8 +48,13 @@ struct TempLimits {
|
||||
|
||||
struct ThermalState {
|
||||
uint8_t errorCounter;
|
||||
bool heating;
|
||||
uint32_t heaterStartTime;
|
||||
// Is heating on for that thermal module?
|
||||
bool heating = false;
|
||||
heater::Switch heaterSwitch = heater::Switch::NUMBER_OF_SWITCHES;
|
||||
// Heater start time and end times as UNIX seconds. Please note that these times will be updated
|
||||
// when a switch command is sent, with no guarantess that the heater actually went on.
|
||||
uint32_t heaterStartTime = 0;
|
||||
uint32_t heaterEndTime = 0;
|
||||
};
|
||||
|
||||
struct HeaterState {
|
||||
@ -90,6 +95,8 @@ enum ThermalComponents : uint8_t {
|
||||
|
||||
class ThermalController : public ExtendedControllerBase {
|
||||
public:
|
||||
static constexpr uint8_t SUBMODE_NO_HEATER_CTRL = 1;
|
||||
|
||||
static const uint16_t INVALID_TEMPERATURE = 999;
|
||||
static const uint8_t NUMBER_OF_SENSORS = 16;
|
||||
static constexpr int16_t SANITY_LIMIT_LOWER_TEMP = -80;
|
||||
@ -103,13 +110,13 @@ class ThermalController : public ExtendedControllerBase {
|
||||
protected:
|
||||
struct HeaterContext {
|
||||
public:
|
||||
HeaterContext(heater::Switchers switchNr, heater::Switchers redundantSwitchNr,
|
||||
HeaterContext(heater::Switch switchNr, heater::Switch redundantSwitchNr,
|
||||
const TempLimits& tempLimit)
|
||||
: switchNr(switchNr), redSwitchNr(redundantSwitchNr), tempLimit(tempLimit) {}
|
||||
bool doHeaterHandling = true;
|
||||
heater::Switchers switchNr;
|
||||
heater::Switch switchNr;
|
||||
HeaterHandler::SwitchState switchState = HeaterHandler::SwitchState::OFF;
|
||||
heater::Switchers redSwitchNr;
|
||||
heater::Switch redSwitchNr;
|
||||
const TempLimits& tempLimit;
|
||||
};
|
||||
|
||||
@ -260,14 +267,17 @@ class ThermalController : public ExtendedControllerBase {
|
||||
bool pcduSystemTooHotFlag = false;
|
||||
bool syrlinksTooHotFlag = false;
|
||||
bool obcTooHotFlag = false;
|
||||
bool mgtTooHotFlag = false;
|
||||
bool strTooHotFlag = false;
|
||||
bool rwTooHotFlag = false;
|
||||
|
||||
bool transitionToOff = false;
|
||||
uint32_t transitionToOffCycles = 0;
|
||||
bool transitionWhenHeatersOff = false;
|
||||
uint32_t transitionWhenHeatersOffCycles = 0;
|
||||
Mode_t targetMode = MODE_OFF;
|
||||
Submode_t targetSubmode = SUBMODE_NONE;
|
||||
uint32_t cycles = 0;
|
||||
std::array<ThermalState, 30> thermalStates{};
|
||||
std::array<HeaterState, 7> heaterStates{};
|
||||
std::array<ThermalState, ThermalComponents::NUM_ENTRIES> thermalStates{};
|
||||
std::array<HeaterState, heater::NUMBER_OF_SWITCHES> heaterStates{};
|
||||
|
||||
// Initial delay to make sure all pool variables have been initialized their owners.
|
||||
// Also, wait for system initialization to complete.
|
||||
@ -292,6 +302,9 @@ class ThermalController : public ExtendedControllerBase {
|
||||
|
||||
void startTransition(Mode_t mode, Submode_t submode) override;
|
||||
|
||||
bool heaterCtrlAllowed() const;
|
||||
void resetThermalStates();
|
||||
|
||||
void resetSensorsArray();
|
||||
void copySensors();
|
||||
void copySus();
|
||||
@ -302,9 +315,13 @@ class ThermalController : public ExtendedControllerBase {
|
||||
bool heaterCtrlCheckUpperLimits(HeaterContext& heaterContext);
|
||||
void heaterCtrlTempTooHighHandler(HeaterContext& heaterContext, const char* whatLimit);
|
||||
|
||||
bool chooseHeater(heater::Switchers& switchNr, heater::Switchers redSwitchNr);
|
||||
bool chooseHeater(heater::Switch& switchNr, heater::Switch redSwitchNr);
|
||||
bool selectAndReadSensorTemp(HeaterContext& htrCtx);
|
||||
|
||||
void heaterSwitchHelperAllOff();
|
||||
void heaterSwitchHelper(heater::Switch switchNr, HeaterHandler::SwitchState state,
|
||||
unsigned componentIdx);
|
||||
|
||||
void ctrlAcsBoard();
|
||||
void ctrlMgt();
|
||||
void ctrlRw();
|
||||
@ -329,7 +346,7 @@ class ThermalController : public ExtendedControllerBase {
|
||||
void ctrlMpa();
|
||||
void ctrlScexBoard();
|
||||
void heaterTransitionControl(const HeaterSwitchStates& currentHeaterStates);
|
||||
void setMode(Mode_t mode);
|
||||
void setMode(Mode_t mode, Submode_t submode);
|
||||
uint32_t tempFloatToU32() const;
|
||||
bool tooHotHandler(object_id_t object, bool& oneShotFlag);
|
||||
void tooHotHandlerWhichClearsOneShotFlag(object_id_t object, bool& oneShotFlag);
|
||||
|
@ -33,18 +33,15 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
case 0x2: // InertiaEIVE
|
||||
switch (parameterId) {
|
||||
case 0x0:
|
||||
parameterWrapper->setMatrix(inertiaEIVE.inertiaMatrix);
|
||||
break;
|
||||
case 0x1:
|
||||
parameterWrapper->setMatrix(inertiaEIVE.inertiaMatrixDeployed);
|
||||
break;
|
||||
case 0x2:
|
||||
case 0x1:
|
||||
parameterWrapper->setMatrix(inertiaEIVE.inertiaMatrixUndeployed);
|
||||
break;
|
||||
case 0x3:
|
||||
case 0x2:
|
||||
parameterWrapper->setMatrix(inertiaEIVE.inertiaMatrixPanel1);
|
||||
break;
|
||||
case 0x4:
|
||||
case 0x3:
|
||||
parameterWrapper->setMatrix(inertiaEIVE.inertiaMatrixPanel3);
|
||||
break;
|
||||
default:
|
||||
@ -107,6 +104,9 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
case 0x11:
|
||||
parameterWrapper->setVector(mgmHandlingParameters.mgm4variance);
|
||||
break;
|
||||
case 0x12:
|
||||
parameterWrapper->set(mgmHandlingParameters.mgmDerivativeFilterWeight);
|
||||
break;
|
||||
default:
|
||||
return INVALID_IDENTIFIER_ID;
|
||||
}
|
||||
@ -260,6 +260,9 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
case 0xA:
|
||||
parameterWrapper->set(gyrHandlingParameters.preferAdis);
|
||||
break;
|
||||
case 0xB:
|
||||
parameterWrapper->set(gyrHandlingParameters.gyrFilterWeight);
|
||||
break;
|
||||
default:
|
||||
return INVALID_IDENTIFIER_ID;
|
||||
}
|
||||
@ -321,28 +324,34 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
case (0x8): // SafeModeControllerParameters
|
||||
switch (parameterId) {
|
||||
case 0x0:
|
||||
parameterWrapper->set(safeModeControllerParameters.k_rate_mekf);
|
||||
parameterWrapper->set(safeModeControllerParameters.k_orthoMekf);
|
||||
break;
|
||||
case 0x1:
|
||||
parameterWrapper->set(safeModeControllerParameters.k_align_mekf);
|
||||
parameterWrapper->set(safeModeControllerParameters.k_alignMekf);
|
||||
break;
|
||||
case 0x2:
|
||||
parameterWrapper->set(safeModeControllerParameters.k_rate_no_mekf);
|
||||
parameterWrapper->set(safeModeControllerParameters.k_parallelMekf);
|
||||
break;
|
||||
case 0x3:
|
||||
parameterWrapper->set(safeModeControllerParameters.k_align_no_mekf);
|
||||
parameterWrapper->set(safeModeControllerParameters.k_orthoNonMekf);
|
||||
break;
|
||||
case 0x4:
|
||||
parameterWrapper->set(safeModeControllerParameters.sunMagAngleMin);
|
||||
parameterWrapper->set(safeModeControllerParameters.k_alignNonMekf);
|
||||
break;
|
||||
case 0x5:
|
||||
parameterWrapper->setVector(safeModeControllerParameters.sunTargetDirLeop);
|
||||
parameterWrapper->set(safeModeControllerParameters.k_parallelNonMekf);
|
||||
break;
|
||||
case 0x6:
|
||||
parameterWrapper->setVector(safeModeControllerParameters.sunTargetDir);
|
||||
parameterWrapper->setVector(safeModeControllerParameters.sunTargetDirLeop);
|
||||
break;
|
||||
case 0x7:
|
||||
parameterWrapper->setVector(safeModeControllerParameters.satRateRef);
|
||||
parameterWrapper->setVector(safeModeControllerParameters.sunTargetDir);
|
||||
break;
|
||||
case 0x8:
|
||||
parameterWrapper->set(safeModeControllerParameters.useMekf);
|
||||
break;
|
||||
case 0x9:
|
||||
parameterWrapper->set(safeModeControllerParameters.dampingDuringEclipse);
|
||||
break;
|
||||
default:
|
||||
return INVALID_IDENTIFIER_ID;
|
||||
@ -377,7 +386,6 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
case 0x8:
|
||||
parameterWrapper->set(idleModeControllerParameters.enableAntiStiction);
|
||||
break;
|
||||
|
||||
default:
|
||||
return INVALID_IDENTIFIER_ID;
|
||||
}
|
||||
@ -703,7 +711,13 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
parameterWrapper->set(detumbleParameter.omegaDetumbleEnd);
|
||||
break;
|
||||
case 0x3:
|
||||
parameterWrapper->set(detumbleParameter.gainD);
|
||||
parameterWrapper->set(detumbleParameter.gainBdot);
|
||||
break;
|
||||
case 0x4:
|
||||
parameterWrapper->set(detumbleParameter.gainFull);
|
||||
break;
|
||||
case 0x5:
|
||||
parameterWrapper->set(detumbleParameter.useFullDetumbleLaw);
|
||||
break;
|
||||
default:
|
||||
return INVALID_IDENTIFIER_ID;
|
||||
|
@ -22,22 +22,27 @@ class AcsParameters : public HasParametersIF {
|
||||
} onBoardParams;
|
||||
|
||||
struct InertiaEIVE {
|
||||
double inertiaMatrix[3][3] = {{0.1539829, -0.0001821456, -0.0050135},
|
||||
{-0.0001821456, 0.1701302, 0.0004748963},
|
||||
{-0.0050135, 0.0004748963, 0.08374296}}; // 19.11.2021
|
||||
// Possible inertia matrices
|
||||
double inertiaMatrixDeployed[3][3] = {{0.1539829, -0.0001821456, -0.0050135},
|
||||
{-0.0001821456, 0.1701302, 0.0004748963},
|
||||
{-0.0050135, 0.0004748963, 0.08374296}}; // 19.11.2021
|
||||
double inertiaMatrixUndeployed[3][3] = {{0.122485, -0.0001798426, -0.005008},
|
||||
{-0.0001798426, 0.162240, 0.000475596},
|
||||
{-0.005008, 0.000475596, 0.060136}}; // 19.11.2021
|
||||
double inertiaMatrixPanel1[3][3] = {{0.13823347, -0.0001836122, -0.00501207},
|
||||
{-0.0001836122, 0.16619787, 0.0083537},
|
||||
{-0.00501207, 0.0083537, 0.07192588}}; // 19.11.2021
|
||||
double inertiaMatrixPanel3[3][3] = {{0.13823487, -0.000178376, -0.005009767},
|
||||
{-0.000178376, 0.166172, -0.007403},
|
||||
{-0.005009767, -0.007403, 0.07195314}};
|
||||
/* Possible inertia matrices
|
||||
* 2023-04-14
|
||||
* all matrices derived from the CAD model with CAD mass of 8.72 kg
|
||||
* all matrices are scaled by final measured mass of 8.756 kg
|
||||
* all matrices are in [kg m^2]
|
||||
*/
|
||||
double inertiaMatrixDeployed[3][3] = {
|
||||
{0.128333461640235, -0.000151805020803, -0.004178414952517},
|
||||
{-0.000151805020803, 0.141791062870050, 0.000395791231451},
|
||||
{-0.004178414952517, 0.000395791231451, 0.069793610830099}};
|
||||
double inertiaMatrixUndeployed[3][3] = {
|
||||
{0.102082611845982, -0.000149885620646, -0.004174050971653},
|
||||
{-0.000149885620646, 0.135214836333048, 0.000396374487363},
|
||||
{-0.004174050971653, 0.000396374487363, 0.050118987572848}};
|
||||
double inertiaMatrixPanel1[3][3] = {{0.115207454653725, -0.000153027308288, -0.004177193002842},
|
||||
{-0.000153027308288, 0.138513727361148, 0.006962185987503},
|
||||
{-0.004177193002842, 0.006962185987503, 0.059944939352491}};
|
||||
double inertiaMatrixPanel3[3][3] = {
|
||||
{0.115208618832493, -0.000148663333161, -0.004175272921328},
|
||||
{-0.000148663333161, 0.138492171841952, -0.006170020268690},
|
||||
{-0.004175272921328, -0.006170020268690, 0.059967659050454}};
|
||||
} inertiaEIVE;
|
||||
|
||||
struct MgmHandlingParameters {
|
||||
@ -72,6 +77,7 @@ 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;
|
||||
} mgmHandlingParameters;
|
||||
|
||||
struct SusHandlingParameters {
|
||||
@ -779,7 +785,8 @@ class AcsParameters : public HasParametersIF {
|
||||
pow(3.0e-3, 2), // RND_y = 3.0e-3 deg/s/sqrt(Hz) rms
|
||||
pow(4.3e-3, 2)}; // RND_z = 4.3e-3 deg/s/sqrt(Hz) rms
|
||||
float gyr13variance[3] = {pow(11e-3, 2), pow(11e-3, 2), pow(11e-3, 2)};
|
||||
uint8_t preferAdis = true;
|
||||
uint8_t preferAdis = false;
|
||||
float gyrFilterWeight = 0.6;
|
||||
} gyrHandlingParameters;
|
||||
|
||||
struct RwHandlingParameters {
|
||||
@ -811,18 +818,19 @@ class AcsParameters : public HasParametersIF {
|
||||
} rwMatrices;
|
||||
|
||||
struct SafeModeControllerParameters {
|
||||
double k_rate_mekf = 0.00059437;
|
||||
double k_align_mekf = 0.000056875;
|
||||
double k_orthoMekf = 4.4e-3;
|
||||
double k_alignMekf = 4.0e-5;
|
||||
double k_parallelMekf = 3.75e-4;
|
||||
|
||||
double k_rate_no_mekf = 0.00059437;
|
||||
double k_align_no_mekf = 0.000056875;
|
||||
|
||||
double sunMagAngleMin = 5 * M_PI / 180;
|
||||
double k_orthoNonMekf = 4.4e-3;
|
||||
double k_alignNonMekf = 4.0e-5;
|
||||
double k_parallelNonMekf = 3.75e-4;
|
||||
|
||||
double sunTargetDirLeop[3] = {0, sqrt(.5), sqrt(.5)};
|
||||
double sunTargetDir[3] = {0, 0, 1};
|
||||
|
||||
double satRateRef[3] = {0, 0, 0};
|
||||
uint8_t useMekf = false;
|
||||
uint8_t dampingDuringEclipse = true;
|
||||
} safeModeControllerParameters;
|
||||
|
||||
struct PointingLawParameters {
|
||||
@ -931,8 +939,10 @@ class AcsParameters : public HasParametersIF {
|
||||
struct DetumbleParameter {
|
||||
uint8_t detumblecounter = 75; // 30 s
|
||||
double omegaDetumbleStart = 2 * M_PI / 180;
|
||||
double omegaDetumbleEnd = 0.4 * M_PI / 180;
|
||||
double gainD = pow(10.0, -3.3);
|
||||
double omegaDetumbleEnd = 1 * M_PI / 180;
|
||||
double gainBdot = pow(10.0, -3.3);
|
||||
double gainFull = pow(10.0, -2.3);
|
||||
uint8_t useFullDetumbleLaw = false;
|
||||
} detumbleParameter;
|
||||
};
|
||||
|
||||
|
@ -539,7 +539,7 @@ ReturnValue_t Guidance::getDistributionMatrixRw(ACS::SensorValues *sensorValues,
|
||||
}
|
||||
}
|
||||
|
||||
void Guidance::getTargetParamsSafe(double sunTargetSafe[3], double satRateSafe[3]) {
|
||||
void Guidance::getTargetParamsSafe(double sunTargetSafe[3]) {
|
||||
std::error_code e;
|
||||
if (not std::filesystem::exists(SD_0_SKEWED_PTG_FILE, e) or
|
||||
not std::filesystem::exists(SD_1_SKEWED_PTG_FILE, e)) {
|
||||
@ -549,8 +549,6 @@ void Guidance::getTargetParamsSafe(double sunTargetSafe[3], double satRateSafe[3
|
||||
std::memcpy(sunTargetSafe, acsParameters->safeModeControllerParameters.sunTargetDirLeop,
|
||||
3 * sizeof(double));
|
||||
}
|
||||
std::memcpy(satRateSafe, acsParameters->safeModeControllerParameters.satRateRef,
|
||||
3 * sizeof(double));
|
||||
}
|
||||
|
||||
ReturnValue_t Guidance::solarArrayDeploymentComplete() {
|
||||
|
@ -12,7 +12,7 @@ class Guidance {
|
||||
Guidance(AcsParameters *acsParameters_);
|
||||
virtual ~Guidance();
|
||||
|
||||
void getTargetParamsSafe(double sunTargetSafe[3], double satRateRef[3]);
|
||||
void getTargetParamsSafe(double sunTargetSafe[3]);
|
||||
ReturnValue_t solarArrayDeploymentComplete();
|
||||
|
||||
// Function to get the target quaternion and refence rotation rate from gps position and
|
||||
|
@ -1105,11 +1105,9 @@ void MultiplicativeKalmanFilter::updateDataSetWithoutData(acsctrl::MekfData *mek
|
||||
{
|
||||
PoolReadGuard pg(mekfData);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
double unitQuat[4] = {0.0, 0.0, 0.0, 1.0};
|
||||
double zeroVec[3] = {0.0, 0.0, 0.0};
|
||||
std::memcpy(mekfData->quatMekf.value, unitQuat, 4 * sizeof(double));
|
||||
std::memcpy(mekfData->quatMekf.value, ZERO_VEC4, 4 * sizeof(double));
|
||||
mekfData->quatMekf.setValid(false);
|
||||
std::memcpy(mekfData->satRotRateMekf.value, zeroVec, 3 * sizeof(double));
|
||||
std::memcpy(mekfData->satRotRateMekf.value, ZERO_VEC3, 3 * sizeof(double));
|
||||
mekfData->satRotRateMekf.setValid(false);
|
||||
mekfData->mekfStatus = mekfStatus;
|
||||
mekfData->setValidity(true, false);
|
||||
|
@ -80,6 +80,9 @@ class MultiplicativeKalmanFilter {
|
||||
static constexpr ReturnValue_t MEKF_RUNNING = returnvalue::makeCode(IF_MEKF_ID, 9);
|
||||
|
||||
private:
|
||||
static constexpr double ZERO_VEC3[3] = {0, 0, 0};
|
||||
static constexpr double ZERO_VEC4[4] = {0, 0, 0, 0};
|
||||
|
||||
/*Parameters*/
|
||||
double quaternion_STR_SB[4];
|
||||
|
||||
|
@ -141,7 +141,7 @@ void SensorProcessing::processMgm(const float *mgm0Value, bool mgm0valid, const
|
||||
double mgmVecTotDerivative[3] = {0.0, 0.0, 0.0};
|
||||
bool mgmVecTotDerivativeValid = false;
|
||||
double timeDiff = timevalOperations::toDouble(timeOfMgmMeasurement - timeOfSavedMagFieldEst);
|
||||
if (timeOfSavedMagFieldEst.tv_sec != 0) {
|
||||
if (timeOfSavedMagFieldEst.tv_sec != 0 and timeDiff > 0) {
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
mgmVecTotDerivative[i] = (mgmVecTot[i] - savedMgmVecTot[i]) / timeDiff;
|
||||
savedMgmVecTot[i] = mgmVecTot[i];
|
||||
@ -150,6 +150,12 @@ void SensorProcessing::processMgm(const float *mgm0Value, bool mgm0valid, const
|
||||
}
|
||||
timeOfSavedMagFieldEst = timeOfMgmMeasurement;
|
||||
|
||||
if (VectorOperations<double>::norm(mgmVecTotDerivative, 3) != 0 and
|
||||
mgmDataProcessed->mgmVecTotDerivative.isValid()) {
|
||||
lowPassFilter(mgmVecTotDerivative, mgmDataProcessed->mgmVecTotDerivative.value,
|
||||
mgmParameters->mgmDerivativeFilterWeight);
|
||||
}
|
||||
|
||||
{
|
||||
PoolReadGuard pg(mgmDataProcessed);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
@ -389,7 +395,7 @@ void SensorProcessing::processSus(
|
||||
double susVecTotDerivative[3] = {0.0, 0.0, 0.0};
|
||||
bool susVecTotDerivativeValid = false;
|
||||
double timeDiff = timevalOperations::toDouble(timeOfSusMeasurement - timeOfSavedSusDirEst);
|
||||
if (timeOfSavedSusDirEst.tv_sec != 0) {
|
||||
if (timeOfSavedSusDirEst.tv_sec != 0 and timeDiff > 0) {
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
susVecTotDerivative[i] = (susVecTot[i] - savedSusVecTot[i]) / timeDiff;
|
||||
savedSusVecTot[i] = susVecTot[i];
|
||||
@ -527,6 +533,11 @@ void SensorProcessing::processGyr(
|
||||
gyrVecTot[i] = sensorFusionNumerator[i] / sensorFusionDenominator[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (VectorOperations<double>::norm(gyrVecTot, 3) != 0 and gyrDataProcessed->gyrVecTot.isValid()) {
|
||||
lowPassFilter(gyrVecTot, gyrDataProcessed->gyrVecTot.value, gyrParameters->gyrFilterWeight);
|
||||
}
|
||||
|
||||
{
|
||||
PoolReadGuard pg(gyrDataProcessed);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
@ -571,8 +582,9 @@ void SensorProcessing::processGps(const double gpsLatitude, const double gpsLong
|
||||
// Calculation of the satellite velocity in earth fixed frame
|
||||
double deltaDistance[3] = {0, 0, 0};
|
||||
MathOperations<double>::cartesianFromLatLongAlt(latitudeRad, gdLongitude, altitude, posSatE);
|
||||
if (validSavedPosSatE &&
|
||||
(gpsUnixSeconds - timeOfSavedPosSatE) < (gpsParameters->timeDiffVelocityMax)) {
|
||||
if (validSavedPosSatE and
|
||||
(gpsUnixSeconds - timeOfSavedPosSatE) < (gpsParameters->timeDiffVelocityMax) and
|
||||
(gpsUnixSeconds - timeOfSavedPosSatE) > 0) {
|
||||
VectorOperations<double>::subtract(posSatE, savedPosSatE, deltaDistance, 3);
|
||||
double timeDiffGpsMeas = gpsUnixSeconds - timeOfSavedPosSatE;
|
||||
VectorOperations<double>::mulScalar(deltaDistance, 1. / timeDiffGpsMeas, gpsVelocityE, 3);
|
||||
@ -656,3 +668,10 @@ void SensorProcessing::process(timeval now, ACS::SensorValues *sensorValues,
|
||||
sensorValues->gyr3L3gSet.angVelocZ.value, sensorValues->gyr3L3gSet.angVelocZ.isValid(), now,
|
||||
&acsParameters->gyrHandlingParameters, gyrDataProcessed);
|
||||
}
|
||||
|
||||
void SensorProcessing::lowPassFilter(double *newValue, double *oldValue, const double weight) {
|
||||
double leftSide[3] = {0, 0, 0}, rightSide[3] = {0, 0, 0};
|
||||
VectorOperations<double>::mulScalar(newValue, (1 - weight), leftSide, 3);
|
||||
VectorOperations<double>::mulScalar(oldValue, weight, rightSide, 3);
|
||||
VectorOperations<double>::add(leftSide, rightSide, newValue, 3);
|
||||
}
|
||||
|
@ -13,8 +13,6 @@
|
||||
|
||||
class SensorProcessing {
|
||||
public:
|
||||
void reset();
|
||||
|
||||
SensorProcessing();
|
||||
virtual ~SensorProcessing();
|
||||
|
||||
@ -59,13 +57,13 @@ class SensorProcessing {
|
||||
const AcsParameters::GyrHandlingParameters *gyrParameters,
|
||||
acsctrl::GyrDataProcessed *gyrDataProcessed);
|
||||
|
||||
void processStr();
|
||||
|
||||
void processGps(const double gpsLatitude, const double gpsLongitude, const double gpsAltitude,
|
||||
const double gpsUnixSeconds, const bool validGps,
|
||||
const AcsParameters::GpsParameters *gpsParameters,
|
||||
acsctrl::GpsDataProcessed *gpsDataProcessed);
|
||||
|
||||
void lowPassFilter(double *newValue, double *oldValue, const double weight);
|
||||
|
||||
double savedMgmVecTot[3] = {0.0, 0.0, 0.0};
|
||||
timeval timeOfSavedMagFieldEst;
|
||||
double savedSusVecTot[3] = {0.0, 0.0, 0.0};
|
||||
|
@ -1,61 +1,45 @@
|
||||
#include "Detumble.h"
|
||||
|
||||
#include <fsfw/globalfunctions/constants.h>
|
||||
#include <fsfw/globalfunctions/math/MatrixOperations.h>
|
||||
#include <fsfw/globalfunctions/math/QuaternionOperations.h>
|
||||
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
||||
#include <fsfw/globalfunctions/sign.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "../util/MathOperations.h"
|
||||
|
||||
Detumble::Detumble() {}
|
||||
|
||||
Detumble::~Detumble() {}
|
||||
|
||||
ReturnValue_t Detumble::bDotLaw(const double *magRate, const bool magRateValid,
|
||||
const double *magField, const bool magFieldValid, double *magMom,
|
||||
double gain) {
|
||||
if (!magRateValid || !magFieldValid) {
|
||||
return DETUMBLE_NO_SENSORDATA;
|
||||
uint8_t Detumble::detumbleStrategy(const bool magFieldValid, const bool satRotRateValid,
|
||||
const bool magFieldRateValid, const bool useFullDetumbleLaw) {
|
||||
if (not magFieldValid) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_NO_MAG_FIELD_FOR_CONTROL;
|
||||
} else if (satRotRateValid and useFullDetumbleLaw) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_DETUMBLE_FULL;
|
||||
} else if (magFieldRateValid) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_DETUMBLE_DETERIORATED;
|
||||
} else {
|
||||
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
|
||||
}
|
||||
// convert uT to T
|
||||
double magFieldT[3], magRateT[3];
|
||||
VectorOperations<double>::mulScalar(magField, 1e-6, magFieldT, 3);
|
||||
VectorOperations<double>::mulScalar(magRate, 1e-6, magRateT, 3);
|
||||
// control law
|
||||
double factor = -gain / pow(VectorOperations<double>::norm(magFieldT, 3), 2);
|
||||
VectorOperations<double>::mulScalar(magRateT, factor, magMom, 3);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Detumble::bangbangLaw(const double *magRate, const bool magRateValid, double *magMom,
|
||||
double dipolMax) {
|
||||
if (!magRateValid) {
|
||||
return DETUMBLE_NO_SENSORDATA;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
magMom[i] = -dipolMax * sign(magRate[i]);
|
||||
}
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Detumble::bDotLawFull(const double *satRate, const bool *satRateValid,
|
||||
const double *magField, const bool *magFieldValid,
|
||||
double *magMom, double gain) {
|
||||
if (!satRateValid || !magFieldValid) {
|
||||
return DETUMBLE_NO_SENSORDATA;
|
||||
}
|
||||
void Detumble::bDotLawFull(const double *satRotRateB, const double *magFieldB, double *magMomB,
|
||||
double gain) {
|
||||
// convert uT to T
|
||||
double magFieldT[3];
|
||||
VectorOperations<double>::mulScalar(magField, 1e-6, magFieldT, 3);
|
||||
double magFieldBT[3];
|
||||
VectorOperations<double>::mulScalar(magFieldB, 1e-6, magFieldBT, 3);
|
||||
// control law
|
||||
double factor = gain / pow(VectorOperations<double>::norm(magField, 3), 2);
|
||||
double factor = gain / pow(VectorOperations<double>::norm(magFieldBT, 3), 2);
|
||||
double magFieldNormed[3] = {0, 0, 0}, crossProduct[3] = {0, 0, 0};
|
||||
VectorOperations<double>::normalize(magFieldT, magFieldNormed, 3);
|
||||
VectorOperations<double>::cross(satRate, magFieldNormed, crossProduct);
|
||||
VectorOperations<double>::mulScalar(crossProduct, factor, magMom, 3);
|
||||
return returnvalue::OK;
|
||||
VectorOperations<double>::normalize(magFieldBT, magFieldNormed, 3);
|
||||
VectorOperations<double>::cross(satRotRateB, magFieldNormed, crossProduct);
|
||||
VectorOperations<double>::mulScalar(crossProduct, factor, magMomB, 3);
|
||||
}
|
||||
|
||||
void Detumble::bDotLaw(const double *magRateB, const double *magFieldB, double *magMomB,
|
||||
double gain) {
|
||||
// convert uT to T
|
||||
double magFieldBT[3], magRateBT[3];
|
||||
VectorOperations<double>::mulScalar(magFieldB, 1e-6, magFieldBT, 3);
|
||||
VectorOperations<double>::mulScalar(magRateB, 1e-6, magRateBT, 3);
|
||||
// control law
|
||||
double factor = -gain / pow(VectorOperations<double>::norm(magFieldBT, 3), 2);
|
||||
VectorOperations<double>::mulScalar(magRateBT, factor, magMomB, 3);
|
||||
}
|
||||
|
@ -2,30 +2,22 @@
|
||||
#define ACS_CONTROL_DETUMBLE_H_
|
||||
|
||||
#include <fsfw/returnvalues/returnvalue.h>
|
||||
#include <mission/acs/defs.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "../AcsParameters.h"
|
||||
#include "../SensorValues.h"
|
||||
#include "eive/resultClassIds.h"
|
||||
|
||||
class Detumble {
|
||||
public:
|
||||
Detumble();
|
||||
virtual ~Detumble();
|
||||
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::ACS_DETUMBLE;
|
||||
static const ReturnValue_t DETUMBLE_NO_SENSORDATA = MAKE_RETURN_CODE(0x01);
|
||||
uint8_t detumbleStrategy(const bool magFieldValid, const bool satRotRateValid,
|
||||
const bool magFieldRateValid, const bool useFullDetumbleLaw);
|
||||
|
||||
ReturnValue_t bDotLaw(const double *magRate, const bool magRateValid, const double *magField,
|
||||
const bool magFieldValid, double *magMom, double gain);
|
||||
void bDotLawFull(const double *satRotRateB, const double *magFieldB, double *magMomB,
|
||||
double gain);
|
||||
|
||||
ReturnValue_t bangbangLaw(const double *magRate, const bool magRateValid, double *magMom,
|
||||
double dipolMax);
|
||||
|
||||
ReturnValue_t bDotLawFull(const double *satRate, const bool *satRateValid, const double *magField,
|
||||
const bool *magFieldValid, double *magMom, double gain);
|
||||
void bDotLaw(const double *magRateB, const double *magFieldB, double *magMomB, double gain);
|
||||
|
||||
private:
|
||||
};
|
||||
|
@ -49,8 +49,9 @@ void PtgCtrl::ptgLaw(AcsParameters::PointingLawParameters *pointingLawParameters
|
||||
gainMatrixDiagonal[0][0] = gainVector[0];
|
||||
gainMatrixDiagonal[1][1] = gainVector[1];
|
||||
gainMatrixDiagonal[2][2] = gainVector[2];
|
||||
MatrixOperations<double>::multiply(
|
||||
*gainMatrixDiagonal, *(acsParameters->inertiaEIVE.inertiaMatrix), *gainMatrix, 3, 3, 3);
|
||||
MatrixOperations<double>::multiply(*gainMatrixDiagonal,
|
||||
*(acsParameters->inertiaEIVE.inertiaMatrixDeployed),
|
||||
*gainMatrix, 3, 3, 3);
|
||||
|
||||
// Inverse of gainMatrix
|
||||
double gainMatrixInverse[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
@ -60,7 +61,7 @@ void PtgCtrl::ptgLaw(AcsParameters::PointingLawParameters *pointingLawParameters
|
||||
|
||||
double pMatrix[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
MatrixOperations<double>::multiply(
|
||||
*gainMatrixInverse, *(acsParameters->inertiaEIVE.inertiaMatrix), *pMatrix, 3, 3, 3);
|
||||
*gainMatrixInverse, *(acsParameters->inertiaEIVE.inertiaMatrixDeployed), *pMatrix, 3, 3, 3);
|
||||
MatrixOperations<double>::multiplyScalar(*pMatrix, kInt, *pMatrix, 3, 3);
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
@ -85,7 +86,7 @@ void PtgCtrl::ptgLaw(AcsParameters::PointingLawParameters *pointingLawParameters
|
||||
|
||||
// torque for rate error
|
||||
double torqueRate[3] = {0, 0, 0};
|
||||
MatrixOperations<double>::multiply(*(acsParameters->inertiaEIVE.inertiaMatrix), deltaRate,
|
||||
MatrixOperations<double>::multiply(*(acsParameters->inertiaEIVE.inertiaMatrixDeployed), deltaRate,
|
||||
torqueRate, 3, 3, 1);
|
||||
VectorOperations<double>::mulScalar(torqueRate, cInt, torqueRate, 3);
|
||||
VectorOperations<double>::mulScalar(torqueRate, -1, torqueRate, 3);
|
||||
@ -116,7 +117,7 @@ void PtgCtrl::ptgDesaturation(AcsParameters::PointingLawParameters *pointingLawP
|
||||
MatrixOperations<double>::multiply(*(acsParameters->rwMatrices.alignmentMatrix), momentumRwU,
|
||||
momentumRw, 3, 4, 1);
|
||||
double momentumSat[3] = {0, 0, 0}, momentumTotal[3] = {0, 0, 0};
|
||||
MatrixOperations<double>::multiply(*(acsParameters->inertiaEIVE.inertiaMatrix), satRate,
|
||||
MatrixOperations<double>::multiply(*(acsParameters->inertiaEIVE.inertiaMatrixDeployed), satRate,
|
||||
momentumSat, 3, 3, 1);
|
||||
VectorOperations<double>::add(momentumSat, momentumRw, momentumTotal, 3);
|
||||
// calculating momentum error
|
||||
|
@ -24,9 +24,6 @@ class PtgCtrl {
|
||||
PtgCtrl(AcsParameters *acsParameters_);
|
||||
virtual ~PtgCtrl();
|
||||
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::ACS_PTG;
|
||||
static const ReturnValue_t PTGCTRL_MEKF_INPUT_INVALID = MAKE_RETURN_CODE(0x01);
|
||||
|
||||
/* @brief: Calculates the needed torque for the pointing control mechanism
|
||||
*/
|
||||
void ptgLaw(AcsParameters::PointingLawParameters *pointingLawParameters, const double *qError,
|
||||
|
@ -1,158 +1,135 @@
|
||||
#include "SafeCtrl.h"
|
||||
|
||||
#include <fsfw/globalfunctions/constants.h>
|
||||
#include <fsfw/globalfunctions/math/MatrixOperations.h>
|
||||
#include <fsfw/globalfunctions/math/QuaternionOperations.h>
|
||||
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "../util/MathOperations.h"
|
||||
|
||||
SafeCtrl::SafeCtrl(AcsParameters *acsParameters_) { acsParameters = acsParameters_; }
|
||||
|
||||
SafeCtrl::~SafeCtrl() {}
|
||||
|
||||
ReturnValue_t SafeCtrl::safeMekf(timeval now, double *quatBJ, bool quatBJValid,
|
||||
double *magFieldModel, bool magFieldModelValid,
|
||||
double *sunDirModel, bool sunDirModelValid, double *satRateMekf,
|
||||
bool rateMekfValid, double *sunDirRef, double *satRatRef,
|
||||
double *outputAngle, double *outputMagMomB) {
|
||||
if (!quatBJValid || !magFieldModelValid || !sunDirModelValid || !rateMekfValid) {
|
||||
return SAFECTRL_MEKF_INPUT_INVALID;
|
||||
uint8_t SafeCtrl::safeCtrlStrategy(const bool magFieldValid, const bool mekfValid,
|
||||
const bool satRotRateValid, const bool sunDirValid,
|
||||
const uint8_t mekfEnabled, 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;
|
||||
} else {
|
||||
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
|
||||
}
|
||||
|
||||
double kRate = acsParameters->safeModeControllerParameters.k_rate_mekf;
|
||||
double kAlign = acsParameters->safeModeControllerParameters.k_align_mekf;
|
||||
|
||||
// Calc sunDirB ,magFieldB with mekf output and model
|
||||
double dcmBJ[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||
MathOperations<double>::dcmFromQuat(quatBJ, *dcmBJ);
|
||||
double sunDirB[3] = {0, 0, 0}, magFieldB[3] = {0, 0, 0};
|
||||
MatrixOperations<double>::multiply(*dcmBJ, sunDirModel, sunDirB, 3, 3, 1);
|
||||
MatrixOperations<double>::multiply(*dcmBJ, magFieldModel, magFieldB, 3, 3, 1);
|
||||
|
||||
// change unit from uT to T
|
||||
VectorOperations<double>::mulScalar(magFieldB, 1e-6, magFieldB, 3);
|
||||
|
||||
double crossSun[3] = {0, 0, 0};
|
||||
VectorOperations<double>::cross(sunDirRef, sunDirB, crossSun);
|
||||
double normCrossSun = VectorOperations<double>::norm(crossSun, 3);
|
||||
|
||||
// calc angle alpha between sunDirRef and sunDIr
|
||||
double dotSun = VectorOperations<double>::dot(sunDirRef, sunDirB);
|
||||
double alpha = acos(dotSun);
|
||||
|
||||
// Law Torque calculations
|
||||
double torqueCmd[3] = {0, 0, 0}, torqueAlign[3] = {0, 0, 0}, torqueRate[3] = {0, 0, 0},
|
||||
torqueAll[3] = {0, 0, 0};
|
||||
|
||||
double scalarFac = kAlign * alpha / normCrossSun;
|
||||
VectorOperations<double>::mulScalar(crossSun, scalarFac, torqueAlign, 3);
|
||||
|
||||
double rateSafeMode[3] = {0, 0, 0};
|
||||
VectorOperations<double>::subtract(satRateMekf, satRatRef, rateSafeMode, 3);
|
||||
VectorOperations<double>::mulScalar(rateSafeMode, -kRate, torqueRate, 3);
|
||||
|
||||
VectorOperations<double>::add(torqueRate, torqueAlign, torqueAll, 3);
|
||||
// Adding factor of inertia for axes
|
||||
MatrixOperations<double>::multiplyScalar(*(acsParameters->inertiaEIVE.inertiaMatrix), 10,
|
||||
*gainMatrixInertia, 3,
|
||||
3); // why only for mekf one and not for no mekf
|
||||
MatrixOperations<double>::multiply(*gainMatrixInertia, torqueAll, torqueCmd, 3, 3, 1);
|
||||
|
||||
// MagMom B (orthogonal torque)
|
||||
double torqueMgt[3] = {0, 0, 0};
|
||||
VectorOperations<double>::cross(magFieldB, torqueCmd, torqueMgt);
|
||||
double normMag = VectorOperations<double>::norm(magFieldB, 3);
|
||||
VectorOperations<double>::mulScalar(torqueMgt, 1 / pow(normMag, 2), outputMagMomB, 3);
|
||||
|
||||
*outputAngle = alpha;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
// Will be the version in worst case scenario in event of no working MEKF (nor GYRs)
|
||||
ReturnValue_t SafeCtrl::safeNoMekf(timeval now, double *susDirB, bool susDirBValid,
|
||||
double *sunRateB, bool sunRateBValid, double *magFieldB,
|
||||
bool magFieldBValid, double *magRateB, bool magRateBValid,
|
||||
double *sunDirRef, double *satRateRef, double *outputAngle,
|
||||
double *outputMagMomB) {
|
||||
// Check for invalid Inputs
|
||||
if (!susDirBValid || !magFieldBValid || !magRateBValid) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
// change unit from uT to T
|
||||
double magFieldBT[3] = {0, 0, 0};
|
||||
void SafeCtrl::safeMekf(const double *magFieldB, const double *satRotRateB,
|
||||
const double *sunDirModelI, const double *quatBI, const double *sunDirRefB,
|
||||
double *magMomB, double &errorAngle) {
|
||||
// convert magFieldB from uT to T
|
||||
VectorOperations<double>::mulScalar(magFieldB, 1e-6, magFieldBT, 3);
|
||||
|
||||
// normalize sunDir and magDir
|
||||
double magDirB[3] = {0, 0, 0};
|
||||
VectorOperations<double>::normalize(magFieldBT, magDirB, 3);
|
||||
VectorOperations<double>::normalize(susDirB, susDirB, 3);
|
||||
// convert sunDirModel to body rf
|
||||
double sunDirB[3] = {0, 0, 0};
|
||||
QuaternionOperations::multiplyVector(quatBI, sunDirModelI, sunDirB);
|
||||
|
||||
// Cosinus angle between sunDir and magDir
|
||||
double cosAngleSunMag = VectorOperations<double>::dot(magDirB, susDirB);
|
||||
// calculate angle alpha between sunDirRef and sunDir
|
||||
double dotSun = VectorOperations<double>::dot(sunDirRefB, sunDirB);
|
||||
errorAngle = acos(dotSun);
|
||||
|
||||
// Rate parallel to sun direction and magnetic field direction
|
||||
double dotSunRateMag = VectorOperations<double>::dot(sunRateB, magDirB);
|
||||
double dotmagRateSun = VectorOperations<double>::dot(magRateB, susDirB);
|
||||
double rateFactor = 1 - pow(cosAngleSunMag, 2);
|
||||
double rateParaSun = (dotmagRateSun + cosAngleSunMag * dotSunRateMag) / rateFactor;
|
||||
double rateParaMag = (dotSunRateMag + cosAngleSunMag * dotmagRateSun) / rateFactor;
|
||||
splitRotationalRate(satRotRateB, sunDirB);
|
||||
calculateRotationalRateTorque(sunDirB, sunDirRefB, errorAngle,
|
||||
acsParameters->safeModeControllerParameters.k_parallelMekf,
|
||||
acsParameters->safeModeControllerParameters.k_orthoMekf);
|
||||
calculateAngleErrorTorque(sunDirB, sunDirRefB,
|
||||
acsParameters->safeModeControllerParameters.k_alignMekf);
|
||||
|
||||
// Full rate or estimate
|
||||
double estSatRate[3] = {0, 0, 0};
|
||||
double estSatRateMag[3] = {0, 0, 0}, estSatRateSun[3] = {0, 0, 0};
|
||||
VectorOperations<double>::mulScalar(susDirB, rateParaSun, estSatRateSun, 3);
|
||||
VectorOperations<double>::add(sunRateB, estSatRateSun, estSatRateSun, 3);
|
||||
VectorOperations<double>::mulScalar(magDirB, rateParaMag, estSatRateMag, 3);
|
||||
VectorOperations<double>::add(magRateB, estSatRateMag, estSatRateMag, 3);
|
||||
VectorOperations<double>::add(estSatRateSun, estSatRateMag, estSatRate, 3);
|
||||
VectorOperations<double>::mulScalar(estSatRate, 0.5, estSatRate, 3);
|
||||
|
||||
/* Only valid if angle between sun direction and magnetic field direction
|
||||
* is sufficiently large */
|
||||
double angleSunMag = acos(cosAngleSunMag);
|
||||
if (angleSunMag < acsParameters->safeModeControllerParameters.sunMagAngleMin) {
|
||||
return returnvalue::FAILED;
|
||||
// sum of all torques
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
cmdTorque[i] = cmdAlign[i] + cmdOrtho[i] + cmdParallel[i];
|
||||
}
|
||||
|
||||
// Rate for Torque Calculation
|
||||
double diffRate[3] = {0, 0, 0}; /* ADD TO MONITORING */
|
||||
VectorOperations<double>::subtract(estSatRate, satRateRef, diffRate, 3);
|
||||
|
||||
// Torque Align calculation
|
||||
double kRateNoMekf = acsParameters->safeModeControllerParameters.k_rate_no_mekf;
|
||||
double kAlignNoMekf = acsParameters->safeModeControllerParameters.k_align_no_mekf;
|
||||
|
||||
double cosAngleAlignErr = VectorOperations<double>::dot(sunDirRef, susDirB);
|
||||
double crossSusSunRef[3] = {0, 0, 0};
|
||||
VectorOperations<double>::cross(sunDirRef, susDirB, crossSusSunRef);
|
||||
double sinAngleAlignErr = VectorOperations<double>::norm(crossSusSunRef, 3);
|
||||
|
||||
double torqueAlign[3] = {0, 0, 0};
|
||||
double angleAlignErr = acos(cosAngleAlignErr);
|
||||
double torqueAlignFactor = kAlignNoMekf * angleAlignErr / sinAngleAlignErr;
|
||||
VectorOperations<double>::mulScalar(crossSusSunRef, torqueAlignFactor, torqueAlign, 3);
|
||||
|
||||
// Torque Rate Calculations
|
||||
double torqueRate[3] = {0, 0, 0};
|
||||
VectorOperations<double>::mulScalar(diffRate, -kRateNoMekf, torqueRate, 3);
|
||||
|
||||
// Final torque
|
||||
double torqueB[3] = {0, 0, 0}, torqueAlignRate[3] = {0, 0, 0};
|
||||
VectorOperations<double>::add(torqueRate, torqueAlign, torqueAlignRate, 3);
|
||||
MatrixOperations<double>::multiply(*(acsParameters->inertiaEIVE.inertiaMatrix), torqueAlignRate,
|
||||
torqueB, 3, 3, 1);
|
||||
|
||||
// Magnetic moment
|
||||
double magMomB[3] = {0, 0, 0};
|
||||
double crossMagFieldTorque[3] = {0, 0, 0};
|
||||
VectorOperations<double>::cross(magFieldBT, torqueB, crossMagFieldTorque);
|
||||
double magMomFactor = pow(VectorOperations<double>::norm(magFieldBT, 3), 2);
|
||||
VectorOperations<double>::mulScalar(crossMagFieldTorque, 1 / magMomFactor, magMomB, 3);
|
||||
|
||||
std::memcpy(outputMagMomB, magMomB, 3 * sizeof(double));
|
||||
*outputAngle = angleAlignErr;
|
||||
return returnvalue::OK;
|
||||
calculateMagneticMoment(magMomB);
|
||||
}
|
||||
|
||||
void SafeCtrl::safeNonMekf(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);
|
||||
|
||||
// calculate error angle between sunDirRef and sunDir
|
||||
double dotSun = VectorOperations<double>::dot(sunDirRefB, sunDirB);
|
||||
errorAngle = acos(dotSun);
|
||||
|
||||
splitRotationalRate(satRotRateB, sunDirB);
|
||||
calculateRotationalRateTorque(sunDirB, sunDirRefB, errorAngle,
|
||||
acsParameters->safeModeControllerParameters.k_parallelNonMekf,
|
||||
acsParameters->safeModeControllerParameters.k_orthoNonMekf);
|
||||
calculateAngleErrorTorque(sunDirB, sunDirRefB,
|
||||
acsParameters->safeModeControllerParameters.k_alignNonMekf);
|
||||
|
||||
// sum of all torques
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
cmdTorque[i] = cmdAlign[i] + cmdOrtho[i] + cmdParallel[i];
|
||||
}
|
||||
|
||||
calculateMagneticMoment(magMomB);
|
||||
}
|
||||
|
||||
void SafeCtrl::safeRateDamping(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(sunDirRefB, sunDirRefB, errorAngle,
|
||||
acsParameters->safeModeControllerParameters.k_parallelNonMekf,
|
||||
acsParameters->safeModeControllerParameters.k_orthoNonMekf);
|
||||
|
||||
// sum of all torques
|
||||
VectorOperations<double>::add(cmdParallel, cmdOrtho, cmdTorque, 3);
|
||||
|
||||
// calculate magnetic moment to command
|
||||
calculateMagneticMoment(magMomB);
|
||||
}
|
||||
|
||||
void SafeCtrl::splitRotationalRate(const double *satRotRateB, const double *sunDirB) {
|
||||
// split rotational rate into parallel and orthogonal parts
|
||||
double parallelLength = VectorOperations<double>::dot(satRotRateB, sunDirB) *
|
||||
pow(VectorOperations<double>::norm(sunDirB, 3), -2);
|
||||
VectorOperations<double>::mulScalar(sunDirB, parallelLength, satRotRateParallelB, 3);
|
||||
VectorOperations<double>::subtract(satRotRateB, satRotRateParallelB, satRotRateOrthogonalB, 3);
|
||||
}
|
||||
|
||||
void SafeCtrl::calculateRotationalRateTorque(const double *sunDirB, const double *sunDirRefB,
|
||||
double &errorAngle, const double gainParallel,
|
||||
const double gainOrtho) {
|
||||
// calculate torque for parallel rotational rate
|
||||
VectorOperations<double>::mulScalar(satRotRateParallelB, -gainParallel, cmdParallel, 3);
|
||||
|
||||
// calculate torque for orthogonal rotational rate
|
||||
VectorOperations<double>::mulScalar(satRotRateOrthogonalB, -gainOrtho, cmdOrtho, 3);
|
||||
}
|
||||
|
||||
void SafeCtrl::calculateAngleErrorTorque(const double *sunDirB, const double *sunDirRefB,
|
||||
const double gainAlign) {
|
||||
// calculate torque for alignment
|
||||
double crossAlign[3] = {0, 0, 0};
|
||||
VectorOperations<double>::cross(sunDirRefB, sunDirB, crossAlign);
|
||||
VectorOperations<double>::mulScalar(crossAlign, gainAlign, cmdAlign, 3);
|
||||
}
|
||||
|
||||
void SafeCtrl::calculateMagneticMoment(double *magMomB) {
|
||||
double torqueMgt[3] = {0, 0, 0};
|
||||
VectorOperations<double>::cross(magFieldBT, cmdTorque, torqueMgt);
|
||||
double normMag = VectorOperations<double>::norm(magFieldBT, 3);
|
||||
VectorOperations<double>::mulScalar(torqueMgt, pow(normMag, -2), magMomB, 3);
|
||||
}
|
||||
|
@ -1,40 +1,52 @@
|
||||
#ifndef SAFECTRL_H_
|
||||
#define SAFECTRL_H_
|
||||
|
||||
#include <eive/resultClassIds.h>
|
||||
#include <mission/acs/defs.h>
|
||||
#include <mission/controller/acs/AcsParameters.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "../AcsParameters.h"
|
||||
#include "../SensorValues.h"
|
||||
#include "eive/resultClassIds.h"
|
||||
|
||||
class SafeCtrl {
|
||||
public:
|
||||
SafeCtrl(AcsParameters *acsParameters_);
|
||||
virtual ~SafeCtrl();
|
||||
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::ACS_SAFE;
|
||||
static const ReturnValue_t SAFECTRL_MEKF_INPUT_INVALID = MAKE_RETURN_CODE(0x01);
|
||||
uint8_t safeCtrlStrategy(const bool magFieldValid, const bool mekfValid,
|
||||
const bool satRotRateValid, const bool sunDirValid,
|
||||
const uint8_t mekfEnabled, const uint8_t dampingEnabled);
|
||||
|
||||
ReturnValue_t safeMekf(timeval now, double *quatBJ, bool quatBJValid, double *magFieldModel,
|
||||
bool magFieldModelValid, double *sunDirModel, bool sunDirModelValid,
|
||||
double *satRateMekf, bool rateMekfValid, double *sunDirRef,
|
||||
double *satRatRef, // From Guidance (!)
|
||||
double *outputAngle, double *outputMagMomB);
|
||||
void safeMekf(const double *magFieldB, const double *satRotRateB, const double *sunDirModelI,
|
||||
const double *quatBI, const double *sunDirRefB, double *magMomB,
|
||||
double &errorAngle);
|
||||
|
||||
ReturnValue_t safeNoMekf(timeval now, double *susDirB, bool susDirBValid, double *sunRateB,
|
||||
bool sunRateBValid, double *magFieldB, bool magFieldBValid,
|
||||
double *magRateB, bool magRateBValid, double *sunDirRef,
|
||||
double *satRateRef, double *outputAngle, double *outputMagMomB);
|
||||
void safeNonMekf(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 splitRotationalRate(const double *satRotRateB, const double *sunDirB);
|
||||
|
||||
void calculateRotationalRateTorque(const double *sunDirB, const double *sunDirRefB,
|
||||
double &errorAngle, const double gainParallel,
|
||||
const double gainOrtho);
|
||||
|
||||
void calculateAngleErrorTorque(const double *sunDirB, const double *sunDirRefB,
|
||||
const double gainAlign);
|
||||
|
||||
void calculateMagneticMoment(double *magMomB);
|
||||
|
||||
protected:
|
||||
private:
|
||||
AcsParameters *acsParameters;
|
||||
double gainMatrixInertia[3][3];
|
||||
|
||||
double magFieldBState[3];
|
||||
timeval magFieldBStateTime;
|
||||
double magFieldBT[3] = {0, 0, 0};
|
||||
double satRotRateParallelB[3] = {0, 0, 0};
|
||||
double satRotRateOrthogonalB[3] = {0, 0, 0};
|
||||
double cmdParallel[3] = {0, 0, 0};
|
||||
double cmdOrtho[3] = {0, 0, 0};
|
||||
double cmdAlign[3] = {0, 0, 0};
|
||||
double cmdTorque[3] = {0, 0, 0};
|
||||
};
|
||||
|
||||
#endif /* ACS_CONTROL_SAFECTRL_H_ */
|
||||
|
@ -94,6 +94,7 @@ enum PoolIds : lp_id_t {
|
||||
QUAT_MEKF,
|
||||
MEKF_STATUS,
|
||||
// Ctrl Values
|
||||
SAFE_STRAT,
|
||||
TGT_QUAT,
|
||||
ERROR_QUAT,
|
||||
ERROR_ANG,
|
||||
@ -112,7 +113,7 @@ static constexpr uint8_t GYR_SET_RAW_ENTRIES = 4;
|
||||
static constexpr uint8_t GYR_SET_PROCESSED_ENTRIES = 5;
|
||||
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 = 4;
|
||||
static constexpr uint8_t CTRL_VAL_SET_ENTRIES = 5;
|
||||
static constexpr uint8_t ACT_CMD_SET_ENTRIES = 3;
|
||||
|
||||
/**
|
||||
@ -251,6 +252,7 @@ class CtrlValData : public StaticLocalDataSet<CTRL_VAL_SET_ENTRIES> {
|
||||
public:
|
||||
CtrlValData(HasLocalDataPoolIF* hkOwner) : StaticLocalDataSet(hkOwner, CTRL_VAL_DATA) {}
|
||||
|
||||
lp_var_t<uint8_t> safeStrat = lp_var_t<uint8_t>(sid.objectId, SAFE_STRAT, this);
|
||||
lp_vec_t<double, 4> tgtQuat = lp_vec_t<double, 4>(sid.objectId, TGT_QUAT, this);
|
||||
lp_vec_t<double, 4> errQuat = lp_vec_t<double, 4>(sid.objectId, ERROR_QUAT, this);
|
||||
lp_var_t<double> errAng = lp_var_t<double>(sid.objectId, ERROR_ANG, this);
|
||||
|
@ -4,8 +4,8 @@
|
||||
#include <fsfw/datapoollocal/LocalPoolVariable.h>
|
||||
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
|
||||
|
||||
#include "devices/heaterSwitcherList.h"
|
||||
#include "eive/eventSubsystemIds.h"
|
||||
#include "mission/tcs/defs.h"
|
||||
|
||||
namespace tcsCtrl {
|
||||
|
||||
@ -17,6 +17,7 @@ static constexpr Event OBC_OVERHEATING = MAKE_EVENT(4, severity::HIGH);
|
||||
static constexpr Event CAMERA_OVERHEATING = MAKE_EVENT(5, severity::HIGH);
|
||||
static constexpr Event PCDU_SYSTEM_OVERHEATING = MAKE_EVENT(6, severity::HIGH);
|
||||
static constexpr Event HEATER_NOT_OFF_FOR_OFF_MODE = MAKE_EVENT(7, severity::MEDIUM);
|
||||
static constexpr Event MGT_OVERHEATING = MAKE_EVENT(8, severity::HIGH);
|
||||
|
||||
enum SetId : uint32_t {
|
||||
SENSOR_TEMPERATURES = 0,
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include <fsfw/cfdp/CfdpDistributor.h>
|
||||
#include <mission/cfdp/CfdpHandler.h>
|
||||
#include <fsfw/cfdp/handler/RemoteConfigTableIF.h>
|
||||
#include <fsfw/controller/ControllerBase.h>
|
||||
#include <fsfw/controller/ExtendedControllerBase.h>
|
||||
@ -23,6 +22,7 @@
|
||||
#include <fsfw/tcdistribution/PusDistributor.h>
|
||||
#include <fsfw/timemanager/CdsShortTimeStamper.h>
|
||||
#include <fsfw_hal/host/HostFilesystem.h>
|
||||
#include <mission/cfdp/CfdpHandler.h>
|
||||
#include <mission/controller/ThermalController.h>
|
||||
#include <mission/genericFactory.h>
|
||||
#include <mission/persistentTmStoreDefs.h>
|
||||
@ -30,7 +30,7 @@
|
||||
#include <mission/system/acs/AcsBoardAssembly.h>
|
||||
#include <mission/system/acs/RwAssembly.h>
|
||||
#include <mission/system/acs/SusAssembly.h>
|
||||
#include <mission/system/objects/TcsBoardAssembly.h>
|
||||
#include <mission/system/tcs/TcsBoardAssembly.h>
|
||||
#include <mission/tcs/HeaterHandler.h>
|
||||
#include <mission/tmtc/CfdpTmFunnel.h>
|
||||
#include <mission/tmtc/PersistentTmStore.h>
|
||||
@ -47,7 +47,7 @@
|
||||
#include "mission/cfdp/Config.h"
|
||||
#include "mission/system/acs/RwAssembly.h"
|
||||
#include "mission/system/acs/acsModeTree.h"
|
||||
#include "mission/system/tree/tcsModeTree.h"
|
||||
#include "mission/system/tcs/tcsModeTree.h"
|
||||
#include "mission/tcs/defs.h"
|
||||
#include "mission/tmtc/tmFilters.h"
|
||||
#include "objects/systemObjectList.h"
|
||||
@ -98,7 +98,7 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun
|
||||
StorageManagerIF** ipcStore, StorageManagerIF** tmStore,
|
||||
PersistentTmStores& stores) {
|
||||
// Framework objects
|
||||
new EventManager(objects::EVENT_MANAGER, 120);
|
||||
new EventManager(objects::EVENT_MANAGER, 160);
|
||||
auto healthTable = new HealthTable(objects::HEALTH_TABLE);
|
||||
if (healthTable_ != nullptr) {
|
||||
*healthTable_ = healthTable;
|
||||
@ -131,7 +131,7 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun
|
||||
#if OBSW_ADD_TCPIP_SERVERS == 1
|
||||
#if OBSW_ADD_TMTC_UDP_SERVER == 1
|
||||
auto udpBridge =
|
||||
new UdpTmTcBridge(objects::UDP_TMTC_SERVER, objects::CCSDS_PACKET_DISTRIBUTOR, 50);
|
||||
new UdpTmTcBridge(objects::UDP_TMTC_SERVER, objects::CCSDS_PACKET_DISTRIBUTOR, 120);
|
||||
new UdpTcPollingTask(objects::UDP_TMTC_POLLING_TASK, objects::UDP_TMTC_SERVER);
|
||||
sif::info << "Created UDP server for TMTC commanding with listener port "
|
||||
<< udpBridge->getUdpPort() << std::endl;
|
||||
@ -139,7 +139,7 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun
|
||||
#endif
|
||||
#if OBSW_ADD_TMTC_TCP_SERVER == 1
|
||||
auto tcpBridge =
|
||||
new TcpTmTcBridge(objects::TCP_TMTC_SERVER, objects::CCSDS_PACKET_DISTRIBUTOR, 50);
|
||||
new TcpTmTcBridge(objects::TCP_TMTC_SERVER, objects::CCSDS_PACKET_DISTRIBUTOR, 120);
|
||||
TcpTmTcServer::TcpConfig cfg(true, true);
|
||||
auto tcpServer = new TcpTmTcServer(objects::TCP_TMTC_POLLING_TASK, objects::TCP_TMTC_SERVER, cfg);
|
||||
// TCP is stream based. Use packet ID as start marker when parsing for space packets
|
||||
@ -240,7 +240,7 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun
|
||||
pus::PUS_SERVICE_3, config::HK_SERVICE_QUEUE_DEPTH);
|
||||
new Service5EventReporting(
|
||||
PsbParams(objects::PUS_SERVICE_5_EVENT_REPORTING, config::EIVE_PUS_APID, pus::PUS_SERVICE_5),
|
||||
40, 120);
|
||||
80, 160);
|
||||
new Service8FunctionManagement(objects::PUS_SERVICE_8_FUNCTION_MGMT, config::EIVE_PUS_APID,
|
||||
pus::PUS_SERVICE_8, 16, 60);
|
||||
new Service9TimeManagement(
|
||||
@ -287,15 +287,17 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun
|
||||
void ObjectFactory::createGenericHeaterComponents(GpioIF& gpioIF, PowerSwitchIF& pwrSwitcher,
|
||||
HeaterHandler*& heaterHandler) {
|
||||
HeaterHelper helper({{
|
||||
{new HealthDevice(objects::HEATER_0_PLOC_PROC_BRD, MessageQueueIF::NO_QUEUE),
|
||||
{new HeaterHealthDev(objects::HEATER_0_PLOC_PROC_BRD, MessageQueueIF::NO_QUEUE),
|
||||
gpioIds::HEATER_0},
|
||||
{new HealthDevice(objects::HEATER_1_PCDU_BRD, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_1},
|
||||
{new HealthDevice(objects::HEATER_2_ACS_BRD, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_2},
|
||||
{new HealthDevice(objects::HEATER_3_OBC_BRD, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_3},
|
||||
{new HealthDevice(objects::HEATER_4_CAMERA, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_4},
|
||||
{new HealthDevice(objects::HEATER_5_STR, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_5},
|
||||
{new HealthDevice(objects::HEATER_6_DRO, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_6},
|
||||
{new HealthDevice(objects::HEATER_7_SYRLINKS, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_7},
|
||||
{new HeaterHealthDev(objects::HEATER_1_PCDU_BRD, MessageQueueIF::NO_QUEUE),
|
||||
gpioIds::HEATER_1},
|
||||
{new HeaterHealthDev(objects::HEATER_2_ACS_BRD, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_2},
|
||||
{new HeaterHealthDev(objects::HEATER_3_OBC_BRD, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_3},
|
||||
{new HeaterHealthDev(objects::HEATER_4_CAMERA, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_4},
|
||||
{new HeaterHealthDev(objects::HEATER_5_STR, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_5},
|
||||
{new HeaterHealthDev(objects::HEATER_6_DRO, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_6},
|
||||
{new HeaterHealthDev(objects::HEATER_7_SYRLINKS, MessageQueueIF::NO_QUEUE),
|
||||
gpioIds::HEATER_7},
|
||||
}});
|
||||
heaterHandler = new HeaterHandler(objects::HEATER_HANDLER, &gpioIF, helper, &pwrSwitcher,
|
||||
power::Switches::PDU2_CH3_TCS_BOARD_HEATER_IN_8V);
|
||||
|
@ -13,8 +13,25 @@ enum Mode : Mode_t { BOOT = 5, SAFE = acs::AcsMode::SAFE, PTG_IDLE = acs::AcsMod
|
||||
|
||||
}
|
||||
|
||||
namespace xsc {
|
||||
|
||||
enum Chip : int { CHIP_0, CHIP_1, NO_CHIP, SELF_CHIP, ALL_CHIP };
|
||||
enum Copy : int { COPY_0, COPY_1, NO_COPY, SELF_COPY, ALL_COPY };
|
||||
|
||||
} // namespace xsc
|
||||
|
||||
namespace core {
|
||||
static constexpr ActionId_t LIST_DIRECTORY_INTO_FILE = 0;
|
||||
|
||||
// TODO: Support for status? Or maybe some command to quickly get information whether a unit
|
||||
// is running.
|
||||
enum SystemctlCmd : uint8_t { START = 0, STOP = 1, RESTART = 2, NUM_CMDS = 3 };
|
||||
|
||||
static constexpr char CONF_FOLDER[] = "conf";
|
||||
|
||||
static constexpr char VERSION_FILE_NAME[] = "version.txt";
|
||||
static constexpr char REBOOT_FILE_NAME[] = "reboot.txt";
|
||||
static constexpr char TIME_FILE_NAME[] = "time_backup.txt";
|
||||
|
||||
static constexpr ActionId_t ANNOUNCE_VERSION = 1;
|
||||
static constexpr ActionId_t ANNOUNCE_CURRENT_IMAGE = 2;
|
||||
static constexpr ActionId_t ANNOUNCE_BOOT_COUNTS = 3;
|
||||
@ -37,7 +54,16 @@ static constexpr ActionId_t MOUNT_OTHER_COPY = 33;
|
||||
//! Reboot using the reboot command
|
||||
static constexpr ActionId_t REBOOT_OBC = 34;
|
||||
|
||||
static constexpr ActionId_t EXECUTE_SHELL_CMD = 40;
|
||||
static constexpr ActionId_t EXECUTE_SHELL_CMD_BLOCKING = 40;
|
||||
static constexpr ActionId_t EXECUTE_SHELL_CMD_NON_BLOCKING = 41;
|
||||
static constexpr ActionId_t SYSTEMCTL_CMD_EXECUTOR = 42;
|
||||
|
||||
static constexpr ActionId_t LIST_DIRECTORY_INTO_FILE = 50;
|
||||
static constexpr ActionId_t LIST_DIRECTORY_DUMP_DIRECTLY = 51;
|
||||
static constexpr ActionId_t CP_HELPER = 52;
|
||||
static constexpr ActionId_t MV_HELPER = 53;
|
||||
static constexpr ActionId_t RM_HELPER = 54;
|
||||
static constexpr ActionId_t MKDIR_HELPER = 55;
|
||||
|
||||
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CORE;
|
||||
|
||||
@ -70,9 +96,203 @@ static constexpr Event REBOOT_COUNTER = event::makeEvent(SUBSYSTEM_ID, 7, severi
|
||||
static constexpr Event INDIVIDUAL_BOOT_COUNTS = event::makeEvent(SUBSYSTEM_ID, 8, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] I2C is unavailable. Trying recovery of I2C bus by power cycling all I2C
|
||||
//! devices.
|
||||
static constexpr Event TRYING_I2C_RECOVERY = event::makeEvent(SUBSYSTEM_ID, 10, severity::MEDIUM);
|
||||
static constexpr Event TRYING_I2C_RECOVERY = event::makeEvent(SUBSYSTEM_ID, 10, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] I2C is unavailable. Recovery did not work, performing full reboot.
|
||||
static constexpr Event I2C_REBOOT = event::makeEvent(SUBSYSTEM_ID, 11, severity::MEDIUM);
|
||||
static constexpr Event I2C_REBOOT = event::makeEvent(SUBSYSTEM_ID, 11, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] PDEC recovery through reset was not possible, performing full reboot.
|
||||
static constexpr Event PDEC_REBOOT = event::makeEvent(SUBSYSTEM_ID, 12, severity::HIGH);
|
||||
|
||||
class ListDirectoryCmdBase {
|
||||
public: // TODO: Packet definition for clean deserialization
|
||||
// 3 bytes for a and R flag, at least 5 bytes for minimum valid path /tmp with
|
||||
// null termination
|
||||
static constexpr size_t MIN_DATA_LEN = 8;
|
||||
|
||||
ListDirectoryCmdBase(const uint8_t* data, size_t maxSize) : data(data), maxSize(maxSize) {}
|
||||
virtual ~ListDirectoryCmdBase() = default;
|
||||
|
||||
virtual ReturnValue_t parse() {
|
||||
if (maxSize < MIN_DATA_LEN) {
|
||||
return SerializeIF::STREAM_TOO_SHORT;
|
||||
}
|
||||
aFlag = data[0];
|
||||
rFlag = data[1];
|
||||
compressOption = data[2];
|
||||
|
||||
repoNameLen = strnlen(reinterpret_cast<const char*>(data + 3), maxSize - 3);
|
||||
// Last byte MUST be null terminated!
|
||||
if (repoNameLen >= maxSize - 3) {
|
||||
return HasActionsIF::INVALID_PARAMETERS;
|
||||
}
|
||||
repoName = reinterpret_cast<const char*>(data + 3);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
bool aFlagSet() const { return this->aFlag; }
|
||||
bool rFlagSet() const { return this->rFlag; }
|
||||
|
||||
bool compressionOptionSet() const { return this->compressOption; }
|
||||
|
||||
const char* getRepoName(size_t& repoNameLen) const {
|
||||
repoNameLen = this->repoNameLen;
|
||||
return this->repoName;
|
||||
}
|
||||
|
||||
size_t getBaseSize() {
|
||||
// Include NULL termination
|
||||
if (repoName != nullptr) {
|
||||
return 3 + repoNameLen + 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
const uint8_t* data;
|
||||
size_t maxSize;
|
||||
|
||||
bool aFlag = false;
|
||||
bool rFlag = false;
|
||||
bool compressOption = false;
|
||||
const char* repoName = nullptr;
|
||||
size_t repoNameLen = 0;
|
||||
};
|
||||
|
||||
class ListDirectoryIntoFile : public ListDirectoryCmdBase {
|
||||
public:
|
||||
// TODO: Packet definition for clean deserialization
|
||||
// 3 bytes for a and R flag, at least 5 bytes for minimum valid path /tmp with
|
||||
// null termination, at least 7 bytes for minimum target file name /tmp/a with
|
||||
// null termination.
|
||||
static constexpr size_t MIN_DATA_LEN = 15;
|
||||
|
||||
ListDirectoryIntoFile(const uint8_t* data, size_t maxSize)
|
||||
: ListDirectoryCmdBase(data, maxSize) {}
|
||||
ReturnValue_t parse() override {
|
||||
if (maxSize < MIN_DATA_LEN) {
|
||||
return SerializeIF::STREAM_TOO_SHORT;
|
||||
}
|
||||
ReturnValue_t result = ListDirectoryCmdBase::parse();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
targetNameLen =
|
||||
strnlen(reinterpret_cast<const char*>(data + getBaseSize()), maxSize - getBaseSize());
|
||||
if (targetNameLen >= maxSize - getBaseSize()) {
|
||||
// Again: String MUST be null terminated.
|
||||
return HasActionsIF::INVALID_PARAMETERS;
|
||||
}
|
||||
targetName = reinterpret_cast<const char*>(data + getBaseSize());
|
||||
return result;
|
||||
}
|
||||
const char* getTargetName(size_t& targetNameLen) const {
|
||||
targetNameLen = this->targetNameLen;
|
||||
return this->targetName;
|
||||
}
|
||||
|
||||
private:
|
||||
const char* targetName = nullptr;
|
||||
size_t targetNameLen = 0;
|
||||
};
|
||||
|
||||
struct SourceTargetPair {
|
||||
const char* sourceName = nullptr;
|
||||
size_t sourceNameSize = 0;
|
||||
const char* targetName = nullptr;
|
||||
size_t targetNameSize = 0;
|
||||
};
|
||||
|
||||
static ReturnValue_t parseDestTargetString(const uint8_t* data, size_t maxLen,
|
||||
SourceTargetPair& destTgt) {
|
||||
if (maxLen < 4) {
|
||||
return SerializeIF::STREAM_TOO_SHORT;
|
||||
}
|
||||
destTgt.sourceNameSize = strnlen(reinterpret_cast<const char*>(data), maxLen);
|
||||
if (destTgt.sourceNameSize >= maxLen) {
|
||||
return HasActionsIF::INVALID_PARAMETERS;
|
||||
}
|
||||
destTgt.sourceName = reinterpret_cast<const char*>(data);
|
||||
size_t remainingLen = maxLen - destTgt.sourceNameSize - 1;
|
||||
if (remainingLen == 0) {
|
||||
return HasActionsIF::INVALID_PARAMETERS;
|
||||
}
|
||||
destTgt.targetNameSize =
|
||||
strnlen(reinterpret_cast<const char*>(data + destTgt.sourceNameSize + 1), remainingLen);
|
||||
if (destTgt.targetNameSize >= remainingLen) {
|
||||
return HasActionsIF::INVALID_PARAMETERS;
|
||||
}
|
||||
destTgt.targetName = reinterpret_cast<const char*>(data + destTgt.sourceNameSize + 1);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
class CpHelperParser {
|
||||
public:
|
||||
CpHelperParser(const uint8_t* data, size_t maxLen) : data(data), maxLen(maxLen) {}
|
||||
|
||||
ReturnValue_t parse() {
|
||||
if (maxLen < 1) {
|
||||
return SerializeIF::STREAM_TOO_SHORT;
|
||||
}
|
||||
recursiveOpt = data[0];
|
||||
return parseDestTargetString(data + 1, maxLen - 1, destTgt);
|
||||
}
|
||||
const SourceTargetPair& destTgtPair() const { return destTgt; }
|
||||
bool isRecursiveOptSet() const { return recursiveOpt; }
|
||||
|
||||
private:
|
||||
const uint8_t* data;
|
||||
size_t maxLen;
|
||||
bool recursiveOpt = false;
|
||||
SourceTargetPair destTgt;
|
||||
};
|
||||
|
||||
class MvHelperParser {
|
||||
public:
|
||||
MvHelperParser(const uint8_t* data, size_t maxLen) : data(data), maxLen(maxLen) {}
|
||||
|
||||
ReturnValue_t parse() { return parseDestTargetString(data, maxLen, destTgt); }
|
||||
const SourceTargetPair& destTgtPair() const { return destTgt; }
|
||||
|
||||
private:
|
||||
const uint8_t* data;
|
||||
size_t maxLen;
|
||||
SourceTargetPair destTgt;
|
||||
};
|
||||
|
||||
class RmHelperParser {
|
||||
public:
|
||||
RmHelperParser(const uint8_t* data, size_t maxLen) : data(data), maxLen(maxLen) {}
|
||||
|
||||
ReturnValue_t parse() {
|
||||
if (maxLen < 2) {
|
||||
return SerializeIF::STREAM_TOO_SHORT;
|
||||
}
|
||||
recursiveOpt = data[0];
|
||||
forceOpt = data[1];
|
||||
removeTargetSize = strnlen(reinterpret_cast<const char*>(data + 2), maxLen - 2);
|
||||
// Must be null-terminated
|
||||
if (removeTargetSize >= maxLen - 2) {
|
||||
return HasActionsIF::INVALID_PARAMETERS;
|
||||
}
|
||||
removeTarget = reinterpret_cast<const char*>(data + 2);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
bool isRecursiveOptSet() const { return recursiveOpt; }
|
||||
bool isForceOptSet() const { return forceOpt; }
|
||||
|
||||
const char* getRemoveTarget(size_t& removeTargetSize) {
|
||||
removeTargetSize = this->removeTargetSize;
|
||||
return removeTarget;
|
||||
}
|
||||
|
||||
private:
|
||||
const uint8_t* data;
|
||||
size_t maxLen;
|
||||
bool recursiveOpt = false;
|
||||
bool forceOpt = false;
|
||||
const char* removeTarget = nullptr;
|
||||
size_t removeTargetSize = 0;
|
||||
};
|
||||
|
||||
} // namespace core
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
add_subdirectory(objects)
|
||||
add_subdirectory(tree)
|
||||
add_subdirectory(acs)
|
||||
add_subdirectory(tcs)
|
||||
add_subdirectory(com)
|
||||
add_subdirectory(fdir)
|
||||
add_subdirectory(power)
|
||||
|
||||
target_sources(
|
||||
|
@ -4,10 +4,12 @@
|
||||
#include <fsfw/events/EventManager.h>
|
||||
#include <fsfw/ipc/QueueFactory.h>
|
||||
#include <fsfw/power/PowerSwitchIF.h>
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
#include <mission/acs/defs.h>
|
||||
#include <mission/com/defs.h>
|
||||
#include <mission/controller/tcsDefs.h>
|
||||
|
||||
#include "linux/ipcore/pdec.h"
|
||||
#include "mission/power/bpxBattDefs.h"
|
||||
#include "mission/power/defs.h"
|
||||
#include "mission/sysDefs.h"
|
||||
@ -62,6 +64,7 @@ void EiveSystem::performChildOperation() {
|
||||
performSafeRecovery = false;
|
||||
return;
|
||||
}
|
||||
pdecRecoveryLogic();
|
||||
i2cRecoveryLogic();
|
||||
}
|
||||
|
||||
@ -86,6 +89,12 @@ ReturnValue_t EiveSystem::initialize() {
|
||||
}
|
||||
coreCtrlQueueId = coreCtrl->getCommandQueue();
|
||||
|
||||
auto* pdecHandler = ObjectManager::instance()->get<HasActionsIF>(objects::PDEC_HANDLER);
|
||||
if (pdecHandler == nullptr) {
|
||||
return ObjectManager::CHILD_INIT_FAILED;
|
||||
}
|
||||
pdecHandlerQueueId = pdecHandler->getCommandQueue();
|
||||
|
||||
auto* manager = ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER);
|
||||
if (manager == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
@ -105,8 +114,8 @@ ReturnValue_t EiveSystem::initialize() {
|
||||
manager->subscribeToEvent(eventQueue->getId(),
|
||||
event::getEventId(tcsCtrl::PCDU_SYSTEM_OVERHEATING));
|
||||
manager->subscribeToEvent(eventQueue->getId(), event::getEventId(tcsCtrl::OBC_OVERHEATING));
|
||||
|
||||
// manager->subscribeToEvent(eventQueue->getId(), event::getEventId(CoreController::))
|
||||
manager->subscribeToEvent(eventQueue->getId(), event::getEventId(tcsCtrl::MGT_OVERHEATING));
|
||||
manager->subscribeToEvent(eventQueue->getId(), event::getEventId(pdec::INVALID_TC_FRAME));
|
||||
return Subsystem::initialize();
|
||||
}
|
||||
|
||||
@ -117,7 +126,14 @@ void EiveSystem::handleEventMessages() {
|
||||
switch (event.getMessageId()) {
|
||||
case EventMessage::EVENT_MESSAGE:
|
||||
switch (event.getEvent()) {
|
||||
case pdec::INVALID_TC_FRAME: {
|
||||
if (event.getParameter1() == pdec::FRAME_DIRTY_RETVAL) {
|
||||
frameDirtyErrorCounter++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case tcsCtrl::OBC_OVERHEATING:
|
||||
case tcsCtrl::MGT_OVERHEATING:
|
||||
case tcsCtrl::PCDU_SYSTEM_OVERHEATING: {
|
||||
if (isInTransition) {
|
||||
performSafeRecovery = true;
|
||||
@ -175,11 +191,11 @@ void EiveSystem::i2cRecoveryLogic() {
|
||||
// Try recovery.
|
||||
executeAction(EXECUTE_I2C_REBOOT, MessageQueueIF::NO_QUEUE, nullptr, 0);
|
||||
} else {
|
||||
triggerEvent(core::I2C_REBOOT);
|
||||
// We already tried an I2C recovery but the bus is still broken.
|
||||
// Send full reboot request to core controller.
|
||||
CommandMessage msg;
|
||||
ActionMessage::setCommand(&msg, core::REBOOT_OBC, store_address_t());
|
||||
result = commandQueue->sendMessage(coreCtrlQueueId, &msg);
|
||||
sendFullRebootCommand();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -258,6 +274,39 @@ void EiveSystem::i2cRecoveryLogic() {
|
||||
|
||||
void EiveSystem::commandSelfToSafe() { startTransition(satsystem::Mode::SAFE, 0); }
|
||||
|
||||
ReturnValue_t EiveSystem::sendFullRebootCommand() {
|
||||
CommandMessage msg;
|
||||
ActionMessage::setCommand(&msg, core::REBOOT_OBC, store_address_t());
|
||||
return commandQueue->sendMessage(coreCtrlQueueId, &msg);
|
||||
}
|
||||
|
||||
void EiveSystem::pdecRecoveryLogic() {
|
||||
if (ptmeResetWasAttempted and ptmeResetWasAttemptedCd.hasTimedOut()) {
|
||||
ptmeResetWasAttempted = false;
|
||||
}
|
||||
if (frameDirtyCheckCd.hasTimedOut()) {
|
||||
if (frameDirtyErrorCounter >= FRAME_DIRTY_COM_REBOOT_LIMIT) {
|
||||
// If a PTME reset was already attempted and there is still an issue receiving TC frames,
|
||||
// reboot the system.
|
||||
if (ptmeResetWasAttempted) {
|
||||
triggerEvent(core::PDEC_REBOOT);
|
||||
// Send reboot command.
|
||||
sendFullRebootCommand();
|
||||
} else {
|
||||
// Try one full PDEC reset.
|
||||
CommandMessage msg;
|
||||
store_address_t dummy{};
|
||||
ActionMessage::setCommand(&msg, pdec::RESET_PDEC_WITH_REINIITALIZATION, dummy);
|
||||
commandQueue->sendMessage(pdecHandlerQueueId, &msg);
|
||||
ptmeResetWasAttemptedCd.resetTimer();
|
||||
ptmeResetWasAttempted = true;
|
||||
}
|
||||
}
|
||||
frameDirtyErrorCounter = 0;
|
||||
frameDirtyCheckCd.resetTimer();
|
||||
}
|
||||
}
|
||||
|
||||
void EiveSystem::commonI2cRecoverySequenceFinish() {
|
||||
alreadyTriedI2cRecovery = true;
|
||||
performI2cReboot = false;
|
||||
|
@ -9,6 +9,8 @@
|
||||
|
||||
class EiveSystem : public Subsystem, public HasActionsIF {
|
||||
public:
|
||||
static constexpr uint8_t FRAME_DIRTY_COM_REBOOT_LIMIT = 4;
|
||||
|
||||
static constexpr ActionId_t EXECUTE_I2C_REBOOT = 10;
|
||||
|
||||
EiveSystem(object_id_t setObjectId, uint32_t maxNumberOfSequences, uint32_t maxNumberOfTables,
|
||||
@ -33,10 +35,19 @@ class EiveSystem : public Subsystem, public HasActionsIF {
|
||||
bool performI2cReboot = false;
|
||||
bool alreadyTriedI2cRecovery = false;
|
||||
|
||||
uint8_t frameDirtyErrorCounter = 0;
|
||||
Countdown frameDirtyCheckCd = Countdown(10000);
|
||||
// If the PDEC reset was already attempted in the last 2 minutes, there is a high chance that
|
||||
// only a full reboot will fix the issue.
|
||||
Countdown ptmeResetWasAttemptedCd = Countdown(120000);
|
||||
bool ptmeResetWasAttempted = false;
|
||||
|
||||
ActionHelper actionHelper;
|
||||
PowerSwitchIF* powerSwitcher = nullptr;
|
||||
std::atomic_uint16_t& i2cErrors;
|
||||
|
||||
MessageQueueId_t pdecHandlerQueueId = MessageQueueIF::NO_QUEUE;
|
||||
|
||||
MessageQueueId_t bpxBattQueueId = MessageQueueIF::NO_QUEUE;
|
||||
MessageQueueId_t coreCtrlQueueId = MessageQueueIF::NO_QUEUE;
|
||||
MessageQueueId_t actionCommandedBy = MessageQueueIF::NO_QUEUE;
|
||||
@ -51,6 +62,10 @@ class EiveSystem : public Subsystem, public HasActionsIF {
|
||||
const uint8_t* data, size_t size) override;
|
||||
ReturnValue_t handleCommandMessage(CommandMessage* message) override;
|
||||
|
||||
ReturnValue_t sendFullRebootCommand();
|
||||
|
||||
void pdecRecoveryLogic();
|
||||
|
||||
void i2cRecoveryLogic();
|
||||
void handleEventMessages();
|
||||
void commandSelfToSafe();
|
||||
|
@ -183,11 +183,11 @@ void DualLaneAssemblyBase::handleModeTransitionFailed(ReturnValue_t result) {
|
||||
// transition to dual mode.
|
||||
if (not tryingOtherSide) {
|
||||
triggerEvent(CANT_KEEP_MODE, mode, submode);
|
||||
startTransition(mode, nextSubmode);
|
||||
startTransition(targetMode, nextSubmode);
|
||||
tryingOtherSide = true;
|
||||
} else {
|
||||
triggerEvent(transitionOtherSideFailedEvent, mode, targetSubmode);
|
||||
startTransition(mode, Submodes::DUAL_MODE);
|
||||
triggerEvent(transitionOtherSideFailedEvent, targetMode, targetSubmode);
|
||||
startTransition(targetMode, Submodes::DUAL_MODE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,7 +205,8 @@ bool DualLaneAssemblyBase::checkAndHandleRecovery() {
|
||||
opCode = pwrStateMachine.fsm();
|
||||
if (opCode == OpCodes::TO_OFF_DONE or opCode == OpCodes::TIMEOUT_OCCURED) {
|
||||
customRecoveryStates = RecoveryCustomStates::POWER_SWITCHING_ON;
|
||||
pwrStateMachine.start(targetMode, targetSubmode);
|
||||
// Command power back on in any case.
|
||||
pwrStateMachine.start(HasModesIF::MODE_ON, targetSubmode);
|
||||
}
|
||||
}
|
||||
if (customRecoveryStates == POWER_SWITCHING_ON) {
|
||||
|
@ -105,9 +105,9 @@ ReturnValue_t ComSubsystem::initialize() {
|
||||
if (result != returnvalue::OK) {
|
||||
return ObjectManager::CHILD_INIT_FAILED;
|
||||
}
|
||||
result = manager->subscribeToEventRange(eventQueue->getId(),
|
||||
event::getEventId(PdecHandler::CARRIER_LOCK),
|
||||
event::getEventId(PdecHandler::BIT_LOCK_PDEC));
|
||||
result =
|
||||
manager->subscribeToEventRange(eventQueue->getId(), event::getEventId(pdec::CARRIER_LOCK),
|
||||
event::getEventId(pdec::BIT_LOCK_PDEC));
|
||||
if (result != returnvalue::OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "ComSubsystem::initialize: Failed to subscribe to events from PDEC "
|
||||
@ -167,11 +167,11 @@ void ComSubsystem::handleEventMessage(EventMessage *eventMessage) {
|
||||
startRxOnlyRecovery(true);
|
||||
break;
|
||||
}
|
||||
case PdecHandler::BIT_LOCK_PDEC: {
|
||||
case pdec::BIT_LOCK_PDEC: {
|
||||
handleBitLockEvent();
|
||||
break;
|
||||
}
|
||||
case PdecHandler::CARRIER_LOCK: {
|
||||
case pdec::CARRIER_LOCK: {
|
||||
handleCarrierLockEvent();
|
||||
break;
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
target_sources(${LIB_EIVE_MISSION} PRIVATE RtdFdir.cpp)
|
@ -1,4 +1,3 @@
|
||||
target_sources(
|
||||
${LIB_EIVE_MISSION}
|
||||
PRIVATE CamSwitcher.cpp TcsSubsystem.cpp PayloadSubsystem.cpp
|
||||
Stack5VHandler.cpp PowerStateMachineBase.cpp TcsBoardAssembly.cpp)
|
||||
${LIB_EIVE_MISSION} PRIVATE CamSwitcher.cpp PayloadSubsystem.cpp
|
||||
Stack5VHandler.cpp PowerStateMachineBase.cpp)
|
||||
|
@ -1,57 +0,0 @@
|
||||
#include "SyrlinksAssembly.h"
|
||||
|
||||
#include <eive/objects.h>
|
||||
|
||||
using namespace returnvalue;
|
||||
|
||||
SyrlinksAssembly::SyrlinksAssembly(object_id_t objectId) : AssemblyBase(objectId) {
|
||||
ModeListEntry entry;
|
||||
entry.setObject(objects::SYRLINKS_HANDLER);
|
||||
entry.setMode(MODE_OFF);
|
||||
entry.setSubmode(SUBMODE_NONE);
|
||||
commandTable.insert(entry);
|
||||
}
|
||||
|
||||
ReturnValue_t SyrlinksAssembly::commandChildren(Mode_t mode, Submode_t submode) {
|
||||
commandTable[0].setMode(mode);
|
||||
commandTable[0].setSubmode(submode);
|
||||
HybridIterator<ModeListEntry> iter(commandTable.begin(), commandTable.end());
|
||||
if (recoveryState == RECOVERY_IDLE) {
|
||||
ReturnValue_t result = checkAndHandleHealthState(mode, submode);
|
||||
if (result == NEED_TO_CHANGE_HEALTH) {
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
executeTable(iter);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t SyrlinksAssembly::checkChildrenStateOn(Mode_t wantedMode, Submode_t wantedSubmode) {
|
||||
if (childrenMap[objects::SYRLINKS_HANDLER].mode != wantedMode) {
|
||||
return NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t SyrlinksAssembly::isModeCombinationValid(Mode_t mode, Submode_t submode) {
|
||||
if (mode == MODE_ON or mode == DeviceHandlerIF::MODE_NORMAL or mode == MODE_OFF) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
ReturnValue_t SyrlinksAssembly::checkAndHandleHealthState(Mode_t deviceMode,
|
||||
Submode_t deviceSubmode) {
|
||||
HealthState health = healthHelper.healthTable->getHealth(objects::SYRLINKS_HANDLER);
|
||||
if (health == FAULTY or health == PERMANENT_FAULTY) {
|
||||
overwriteDeviceHealth(objects::SYRLINKS_HANDLER, health);
|
||||
return NEED_TO_CHANGE_HEALTH;
|
||||
} else if (health == EXTERNAL_CONTROL) {
|
||||
modeHelper.setForced(true);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
void SyrlinksAssembly::handleChildrenLostMode(ReturnValue_t result) {
|
||||
startTransition(mode, submode);
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
#ifndef MISSION_SYSTEM_OBJECTS_SYRLINKSASSEMBLY_H_
|
||||
#define MISSION_SYSTEM_OBJECTS_SYRLINKSASSEMBLY_H_
|
||||
#include <fsfw/devicehandlers/AssemblyBase.h>
|
||||
|
||||
class SyrlinksAssembly : public AssemblyBase {
|
||||
public:
|
||||
SyrlinksAssembly(object_id_t objectId);
|
||||
|
||||
private:
|
||||
FixedArrayList<ModeListEntry, 1> commandTable;
|
||||
|
||||
ReturnValue_t commandChildren(Mode_t mode, Submode_t submode) override;
|
||||
ReturnValue_t checkChildrenStateOn(Mode_t wantedMode, Submode_t wantedSubmode) override;
|
||||
ReturnValue_t isModeCombinationValid(Mode_t mode, Submode_t submode) override;
|
||||
void handleChildrenLostMode(ReturnValue_t result) override;
|
||||
|
||||
ReturnValue_t checkAndHandleHealthState(Mode_t deviceMode, Submode_t deviceSubmode);
|
||||
};
|
||||
|
||||
#endif /* MISSION_SYSTEM_OBJECTS_SYRLINKSASSEMBLY_H_ */
|
@ -11,8 +11,8 @@
|
||||
#include "eive/objects.h"
|
||||
#include "mission/com/defs.h"
|
||||
#include "mission/system/acs/acsModeTree.h"
|
||||
#include "mission/system/tcs/tcsModeTree.h"
|
||||
#include "mission/system/tree/payloadModeTree.h"
|
||||
#include "mission/system/tree/tcsModeTree.h"
|
||||
#include "treeUtil.h"
|
||||
|
||||
namespace {
|
||||
|
3
mission/system/tcs/CMakeLists.txt
Normal file
3
mission/system/tcs/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
target_sources(
|
||||
${LIB_EIVE_MISSION} PRIVATE tcsModeTree.cpp TcsSubsystem.cpp
|
||||
TcsBoardAssembly.cpp RtdFdir.cpp TmpDevFdir.cpp)
|
91
mission/system/tcs/TmpDevFdir.cpp
Normal file
91
mission/system/tcs/TmpDevFdir.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
#include "TmpDevFdir.h"
|
||||
|
||||
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
|
||||
#include <fsfw/modes/HasModesIF.h>
|
||||
#include <fsfw/power/Fuse.h>
|
||||
#include <fsfw/thermal/ThermalComponentIF.h>
|
||||
|
||||
TmpDevFdir::TmpDevFdir(object_id_t sensorId)
|
||||
: DeviceHandlerFailureIsolation(sensorId, objects::NO_OBJECT) {}
|
||||
|
||||
ReturnValue_t TmpDevFdir::eventReceived(EventMessage* event) {
|
||||
if (isFdirInActionOrAreWeFaulty(event)) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
ReturnValue_t result = returnvalue::FAILED;
|
||||
switch (event->getEvent()) {
|
||||
case HasModesIF::MODE_TRANSITION_FAILED:
|
||||
case HasModesIF::OBJECT_IN_INVALID_MODE:
|
||||
case DeviceHandlerIF::DEVICE_WANTS_HARD_REBOOT:
|
||||
// We'll try a recovery as long as defined in MAX_REBOOT.
|
||||
// Might cause some AssemblyBase cycles, so keep number low.
|
||||
// Ignored for TMP device, no way to power cycle it without going to OFF/BOOT mode.
|
||||
// handleRecovery(event->getEvent());
|
||||
break;
|
||||
case DeviceHandlerIF::DEVICE_INTERPRETING_REPLY_FAILED:
|
||||
case DeviceHandlerIF::DEVICE_READING_REPLY_FAILED:
|
||||
case DeviceHandlerIF::DEVICE_UNREQUESTED_REPLY:
|
||||
case DeviceHandlerIF::DEVICE_UNKNOWN_REPLY: // Some DH's generate generic reply-ids.
|
||||
case DeviceHandlerIF::DEVICE_BUILDING_COMMAND_FAILED:
|
||||
// These faults all mean that there were stupid replies from a device.
|
||||
// With now way to do a recovery, set the device to faulty immediately.
|
||||
setFaulty(event->getEvent());
|
||||
break;
|
||||
case DeviceHandlerIF::DEVICE_SENDING_COMMAND_FAILED:
|
||||
case DeviceHandlerIF::DEVICE_REQUESTING_REPLY_FAILED:
|
||||
// The two above should never be confirmed.
|
||||
case DeviceHandlerIF::DEVICE_MISSED_REPLY:
|
||||
result = sendConfirmationRequest(event);
|
||||
if (result == returnvalue::OK) {
|
||||
break;
|
||||
}
|
||||
// else
|
||||
setFaulty(event->getEvent());
|
||||
break;
|
||||
case StorageManagerIF::GET_DATA_FAILED:
|
||||
case StorageManagerIF::STORE_DATA_FAILED:
|
||||
// Rather strange bugs, occur in RAW mode only. Ignore.
|
||||
break;
|
||||
case DeviceHandlerIF::INVALID_DEVICE_COMMAND:
|
||||
// Ignore, is bad configuration. We can't do anything in flight.
|
||||
break;
|
||||
case HasHealthIF::HEALTH_INFO:
|
||||
case HasModesIF::MODE_INFO:
|
||||
case HasModesIF::CHANGING_MODE:
|
||||
// Do nothing, but mark as handled.
|
||||
break;
|
||||
//****Thermal*****
|
||||
case ThermalComponentIF::COMPONENT_TEMP_LOW:
|
||||
case ThermalComponentIF::COMPONENT_TEMP_HIGH:
|
||||
case ThermalComponentIF::COMPONENT_TEMP_OOL_LOW:
|
||||
case ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH:
|
||||
// Well, the device is not really faulty, but it is required to stay off as long as possible.
|
||||
setFaulty(event->getEvent());
|
||||
break;
|
||||
case ThermalComponentIF::TEMP_NOT_IN_OP_RANGE:
|
||||
// Ignore, is information only.
|
||||
break;
|
||||
//*******Default monitoring variables. Are currently not used.*****
|
||||
// case DeviceHandlerIF::MONITORING_LIMIT_EXCEEDED:
|
||||
// setFaulty(event->getEvent());
|
||||
// break;
|
||||
// case DeviceHandlerIF::MONITORING_AMBIGUOUS:
|
||||
// break;
|
||||
default:
|
||||
// We don't know the event, someone else should handle it.
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void TmpDevFdir::eventConfirmed(EventMessage* event) {
|
||||
switch (event->getEvent()) {
|
||||
case DeviceHandlerIF::DEVICE_SENDING_COMMAND_FAILED:
|
||||
case DeviceHandlerIF::DEVICE_REQUESTING_REPLY_FAILED:
|
||||
case DeviceHandlerIF::DEVICE_MISSED_REPLY:
|
||||
setFaulty(event->getEvent());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
20
mission/system/tcs/TmpDevFdir.h
Normal file
20
mission/system/tcs/TmpDevFdir.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef MISSION_SYSTEM_TCS_TMPDEVFDIR_H_
|
||||
#define MISSION_SYSTEM_TCS_TMPDEVFDIR_H_
|
||||
#include <fsfw/devicehandlers/DeviceHandlerFailureIsolation.h>
|
||||
|
||||
/**
|
||||
* Special FDIR because we can not simply power cycle the TMP devices which are powered by the
|
||||
* 3.3 V stack and there is also no way to logically reset or re-configure the TMP devices in
|
||||
* any way. In general, instead of doing a recovery, the TMP devices should be set faulty
|
||||
* immediately for the EIVE project.
|
||||
*/
|
||||
class TmpDevFdir : public DeviceHandlerFailureIsolation {
|
||||
public:
|
||||
TmpDevFdir(object_id_t sensorId);
|
||||
|
||||
private:
|
||||
ReturnValue_t eventReceived(EventMessage* event) override;
|
||||
void eventConfirmed(EventMessage* event) override;
|
||||
};
|
||||
|
||||
#endif /* MISSION_SYSTEM_TCS_TMPDEVFDIR_H_ */
|
@ -111,7 +111,7 @@ void buildNormalSequence(Subsystem& ss, ModeListEntry& eh) {
|
||||
ctxc);
|
||||
|
||||
// Transition 1
|
||||
iht(objects::THERMAL_CONTROLLER, NML, 0, TCS_TABLE_NORMAL_TRANS_1.second);
|
||||
iht(objects::THERMAL_CONTROLLER, HasModesIF::MODE_ON, 0, TCS_TABLE_NORMAL_TRANS_1.second);
|
||||
check(ss.addTable(TableEntry(TCS_TABLE_NORMAL_TRANS_1.first, &TCS_TABLE_NORMAL_TRANS_1.second)),
|
||||
ctxc);
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef MISSION_SYSTEM_TREE_TCSMODETREE_H_
|
||||
#define MISSION_SYSTEM_TREE_TCSMODETREE_H_
|
||||
|
||||
#include <mission/system/objects/TcsSubsystem.h>
|
||||
#include <mission/system/tcs/TcsSubsystem.h>
|
||||
|
||||
namespace satsystem {
|
||||
namespace tcs {
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user