Compare commits
280 Commits
Author | SHA1 | Date | |
---|---|---|---|
3f73ad86eb | |||
a0735b4fff
|
|||
a71f773f63 | |||
f7dccdc4c6
|
|||
3ebb83b4c0
|
|||
ee43c0fbd7 | |||
91208c2808
|
|||
1dc545c5f0 | |||
55c5df0519
|
|||
e74ae18763 | |||
e5b19a4463 | |||
1f658ceee3
|
|||
6ef05767c5
|
|||
9726c283ef | |||
2110c54d96 | |||
7c0ee9114b
|
|||
e52195e195
|
|||
4d195a1b8e
|
|||
8c54802e7a
|
|||
8cd959f55a | |||
001630cece
|
|||
dbb3434cd9 | |||
61e73a4be9
|
|||
81bb47a6d8
|
|||
a5c799180e
|
|||
f5a9a4973c | |||
f60c754c61
|
|||
ff05181dd3
|
|||
7014ab517d
|
|||
d59ea6eb3d
|
|||
abbf170ce2
|
|||
6767e9a543
|
|||
bf730060b5
|
|||
011f4bf5d9 | |||
942b459066 | |||
10dfa07cd9 | |||
61b3ef790a | |||
c6294cadbd | |||
e2926e25f6 | |||
7e1e02c2bc | |||
afc72c0d97 | |||
4539d25518 | |||
f989af51f2 | |||
566c1534ee
|
|||
5f75b22cec
|
|||
7bedb1d307
|
|||
f736489430 | |||
7ac19c8ea8
|
|||
8251f28cda
|
|||
4e2989d2bd
|
|||
6efee8d4da | |||
59e07d9b47 | |||
880c09c510
|
|||
7cc95be900
|
|||
5e9fd332d9 | |||
753b9f8a0e | |||
07e002ccd2 | |||
53d2e7965a | |||
d618e913af | |||
5f481fd4d0 | |||
b26600ac64 | |||
0d501e5064 | |||
32e2d87143 | |||
7b0a47b010 | |||
300a6c5ff2 | |||
d90fd07ba3 | |||
800e29bcb9 | |||
beaacc251b | |||
b80c96a02c | |||
a52d116857
|
|||
1c8fea409a | |||
f61301db13
|
|||
c48be8f37b | |||
9dfc8a0e93 | |||
8db131f4ab | |||
e50aa2b620
|
|||
8451a2f8ef | |||
ebedb59929 | |||
0f532e8511 | |||
fbff57dd45 | |||
910addc27a
|
|||
b2d2c38c58
|
|||
a4a5800cba
|
|||
2c9df747e8 | |||
4fe921b2cc | |||
e5f8b08e4b | |||
ba0fe5f7da
|
|||
c9a4cf53ca
|
|||
fa10b6fd95
|
|||
5102bd4d69
|
|||
ba6f55b93b
|
|||
2b8a44f390
|
|||
08c98bd354
|
|||
0587f40874
|
|||
320b460179 | |||
1510de19a6
|
|||
6ae72db32d | |||
88d1f9940f
|
|||
8c4a35fc42
|
|||
e7c8d15773
|
|||
19a86ac29e | |||
1d4e2a70a2
|
|||
f1028eb1d9
|
|||
c028a696ce | |||
f832c4522e | |||
4e58614c56
|
|||
93ea8519b0
|
|||
16dbba6545
|
|||
9a451e3d5f
|
|||
7870a2015e
|
|||
80155285c8
|
|||
c61b0f55a4
|
|||
6d220692d5
|
|||
db61358639 | |||
fec85ffa6c
|
|||
462da5228a
|
|||
e9d4104f88
|
|||
39022ce2f6
|
|||
0cefef8a35
|
|||
d3f3a3efd0 | |||
6398532462
|
|||
16f26d7758
|
|||
0e3980dc37
|
|||
cc7e39c484
|
|||
448e24e69f | |||
70c4f8f3fd | |||
1f44533b3e
|
|||
863c0af2a1
|
|||
0fb85883a5
|
|||
965c8d21cc | |||
546053f95a | |||
608eecb091
|
|||
ff432a4194
|
|||
e9d48687d7
|
|||
735c60d4c2 | |||
770d9b7ad3 | |||
86f7d05526
|
|||
8cc5220dd0
|
|||
a800ad6c9a
|
|||
887bfc87c3 | |||
54309b512f
|
|||
74859dd5c6 | |||
13e965948c
|
|||
46bb602c96
|
|||
72dbc34936
|
|||
55affe5a42 | |||
914a22f642 | |||
ed7d75a777
|
|||
9443d3844a | |||
8800b20409
|
|||
690f8cb49a
|
|||
dbc3868f47 | |||
852f1203c6
|
|||
643f8c5b54 | |||
3fb083fd87 | |||
fdf1c7a611
|
|||
cf582dd6a4 | |||
c7f716c433
|
|||
d2dfc22373 | |||
53d53e8771
|
|||
84e37d8b7b
|
|||
7c4f98ec22
|
|||
a61d7901bf
|
|||
7e01a9602e
|
|||
be1d1cf5bf
|
|||
ce2755e161
|
|||
33de08eafc
|
|||
106d73238b | |||
3f4a34d616 | |||
268f10ced5
|
|||
647f3d00bb
|
|||
2210ec3737
|
|||
df3755d6cc
|
|||
a351dcf99e
|
|||
06fe113d7f
|
|||
43d86c9aad
|
|||
c0ae25a973 | |||
fa85cc4d78
|
|||
f7c49adea5 | |||
b662e220e1
|
|||
7337595d47
|
|||
f2f73b088d
|
|||
fce16cc695
|
|||
ff7d0b3989
|
|||
6bf9fd5969
|
|||
a7ab26d804
|
|||
977e9f366f
|
|||
b3d2fdc277 | |||
7388c4f661
|
|||
a6461fcaf8
|
|||
6ae0fdf191 | |||
3087049726 | |||
8255869f2d | |||
603ddcef9c
|
|||
0b673fcdec
|
|||
908cf8dcc3
|
|||
ec39dc05ae
|
|||
bd33a51bf1
|
|||
06a24da2b9 | |||
2bad2a142b
|
|||
b0b43b3ecc | |||
c1a23e0d73 | |||
377cc64d0f
|
|||
351c33e504
|
|||
a7a530cb59 | |||
f1ca4b174f
|
|||
027955597f
|
|||
c558a117b0
|
|||
fc697732b4 | |||
ce19f30325
|
|||
faffca0c2c
|
|||
7b611810df
|
|||
3e92d175d5
|
|||
64ca329d5a
|
|||
12ff365433
|
|||
5ea3bfeb7b | |||
785c1c65a0
|
|||
3c9eec7b3f
|
|||
5630ae4962
|
|||
61ea80f92c
|
|||
6182218813
|
|||
b7e4953126
|
|||
ee4285075a | |||
bda2ba79bf
|
|||
0c47513e98 | |||
f4f365b110
|
|||
1d4b815452
|
|||
1e98fcbbd5
|
|||
52eba5cae6
|
|||
cd9cb48b04
|
|||
5c430212e7
|
|||
d8ab6abc49
|
|||
d1b9608a14
|
|||
25c7058da5
|
|||
9ece676313
|
|||
697a3e8577
|
|||
dea3077f29
|
|||
d687715bcb | |||
e2cd822e9c
|
|||
add079a7c6 | |||
9cdcd47b1a
|
|||
d14e256901 | |||
dd5270e974 | |||
56ea9af615 | |||
4fc999e102 | |||
04d24e74b1 | |||
8137c9ea25 | |||
723b4bba3f | |||
8cff2fd6f7 | |||
a1f7f77e01 | |||
ba36b5f091 | |||
4f5903227e
|
|||
2173d89047
|
|||
03e772246f
|
|||
25da131653
|
|||
4c6b098f42 | |||
b57283101b | |||
9dfdf38822 | |||
c6240285e2 | |||
c881b36630 | |||
a380ff5ac9 | |||
d8efd05a88 | |||
27f77799a6 | |||
9080e7cbe4 | |||
6c39e7dd0c | |||
df4e657ec3 | |||
8f7d3dd815 | |||
97268af555 | |||
322151acf8 | |||
ecb8de1550 | |||
0cd5526de4 | |||
07bb293816 | |||
727050520b | |||
269d5f6a0a | |||
d6dd943ebf | |||
31fdbac8c0 | |||
3e9accfa7b | |||
1b919ceaec | |||
3aad452357 | |||
67351d5ada |
3
.idea/cmake.xml
generated
3
.idea/cmake.xml
generated
@ -2,7 +2,7 @@
|
||||
<project version="4">
|
||||
<component name="CMakeSharedSettings">
|
||||
<configurations>
|
||||
<configuration PROFILE_NAME="Debug Q7S" ENABLED="true" CONFIG_NAME="Debug" TOOLCHAIN_NAME="Q7S" GENERATION_OPTIONS="-DTGT_BSP="arm/q7s"" NO_GENERATOR="true">
|
||||
<configuration PROFILE_NAME="Debug Q7S" ENABLED="true" CONFIG_NAME="Debug" TOOLCHAIN_NAME="Default" GENERATION_OPTIONS="-DTGT_BSP="arm/q7s"" NO_GENERATOR="true">
|
||||
<ADDITIONAL_GENERATION_ENVIRONMENT>
|
||||
<envs>
|
||||
<env name="ZYNQ_7020_ROOTFS" value="/opt/xiphos/sdk/ark/sysroots/cortexa9hf-neon-xiphos-linux-gnueabi" />
|
||||
@ -10,6 +10,7 @@
|
||||
</envs>
|
||||
</ADDITIONAL_GENERATION_ENVIRONMENT>
|
||||
</configuration>
|
||||
<configuration PROFILE_NAME="Debug" ENABLED="true" CONFIG_NAME="Debug" NO_GENERATOR="true" />
|
||||
</configurations>
|
||||
</component>
|
||||
</project>
|
103
CHANGELOG.md
103
CHANGELOG.md
@ -16,10 +16,111 @@ will consitute of a breaking change warranting a new major release:
|
||||
|
||||
# [unreleased]
|
||||
|
||||
# [v6.0.0] to be released
|
||||
# [v6.2.0] 2023-07-26
|
||||
|
||||
- `eive-tmtc`: v5.3.1
|
||||
|
||||
## Changed
|
||||
|
||||
- STR missed reply handling is now moved to DHB rather than the COM interface. The COM IF will
|
||||
still trigger an event if a reply is taking too long, and FDIR should still work via reply
|
||||
timeouts.
|
||||
- Re-ordered some functions of the core controller in the initialize function.
|
||||
- Rad sensor is now only polled every 30 minutes instead of every device cycle to reduce wear of
|
||||
the RADFET electronics.
|
||||
- The SD cards will still be switched OFF on a reboot, but this is done in a non-blocking manner
|
||||
now with a timeout of 10 seconds where the reboot will be performed in any case.
|
||||
- ACS Controller now includes the safe mode from FLP, which will calculate its rotational rate
|
||||
from SUS and MGM measurements. To accommodate these changes, low-pass filters for SUS
|
||||
measurements and rates as well as MGM measurements and rates are included. Usage of the new
|
||||
controller as well as settings of the low-pass filters can be handled via parameter commands.
|
||||
- Simplify and fix the chip and copy protection functions in the core controller. This mechanism
|
||||
now is always performed for the target chip and target copy in the reboot handlers.
|
||||
|
||||
## Added
|
||||
|
||||
- 5 ms delay after pulling RADFET enable pin high before starting
|
||||
the ADC conversion.
|
||||
- Set STR time in configuration sequence to firmware mode.
|
||||
- The STR `AutoThreshold` parameters are now set from the configuration JSON file at STR
|
||||
startup.
|
||||
- The STR handler can now handle the COM error reply and triggers an low severity event accordingly.
|
||||
- Add SCEX handler for EM.
|
||||
- Radiation sensor handler dummy for the EM.
|
||||
- Added event for SD card information in core controller initialize function. This event will also
|
||||
be triggered after the SD state machine has run, so the event will generally be triggered twice
|
||||
at system boot, and once after commanding SD card switches.
|
||||
|
||||
## Fixed
|
||||
|
||||
- General bugs in the SD card state machine. This might fix some other known bugs for certain
|
||||
combinations of switching ON and OFF SD cards and also makes the whole state machine a lot more
|
||||
robust against hanging up.
|
||||
- SUS dummy handler went to `MODE_NORMAL` for ON commands.
|
||||
- PL PCDU dummy went to `MODE_NORMAL` for ON commands.
|
||||
|
||||
# [v6.1.0] 2023-07-13
|
||||
|
||||
- `eive-tmtc`: v5.2.0
|
||||
|
||||
## Changed
|
||||
|
||||
- TCS: Remove OBC IF board thermal module, which is exactly identical to OBC module and therefore
|
||||
obsolete.
|
||||
- Swapped PL and PS I2C, BPX battery and MGT are connected to PS I2C now for firmware versions
|
||||
equal or above v4. However, this software version is compatible to both v3 and v4 of the firmware.
|
||||
- The firmware version variables are global statics inititalized early during the program
|
||||
runtime now. This makes it possible to check the firmware version earlier.
|
||||
- The TCS controller will now always command heaters OFF when being blind for thermal
|
||||
components (no sensors available), irrespective of current switch state.
|
||||
- Make OBSW compatible to prospective FW version v5.0.0, where the Q7 I2C devices were
|
||||
moved to a PL I2C block and the TMP sensor devices were moved to the PS I2C0.
|
||||
- Made `Xadc` code a little bit more robust against errors.
|
||||
|
||||
## Fixed
|
||||
|
||||
- TMP1075: Set dataset invalid on shutdown explicitely
|
||||
- Small fixes for TMP1075 FDIR: Use strange and missed reply counters.
|
||||
- TCS controller: Last heater (S-band heater) was skipped for transition completion
|
||||
checks.
|
||||
- TCS controller: A helper member to track the elapsed heater control cycles was not reset
|
||||
properly, which could lead to switch transitions being completed immediately. This can
|
||||
lead to weird bugs like heaters being commanded ON twice and can potentially lead to
|
||||
other bugs.
|
||||
- TMP1075: Devices did not go to OFF mode when being set faulty.
|
||||
- Update PL PCDU 1 in TCS mode tree on the EM.
|
||||
- TMP1075: Possibly ignored health commands.
|
||||
- Bugfix in FSFW where certain packet types could only be sent with source data fields with a
|
||||
maximum size of 255 bytes.
|
||||
- TCS CTRL: Limit number of heater handler messages sent in case there are not sensors available
|
||||
anymore.
|
||||
- Fix to allow adding real STR device for EM.
|
||||
|
||||
# Added
|
||||
|
||||
- Two events for heaters being commanded ON and OFF by the TCS controller
|
||||
- Upper limit for burn time of TCS heaters. Currently set to 1 hour for each heater.
|
||||
This mechanism will only track the burn time for heaters which were commanded by the
|
||||
TCS controller.
|
||||
- TCS controller is now observable by introducing a new HK dataset which exposes some internal
|
||||
fields related to TCS control.
|
||||
|
||||
# [v6.0.0] 2023-07-02
|
||||
|
||||
- `q7s-package` version v3.2.0
|
||||
- Important bugfixes for PTME. See `q7s-package` CHANGELOG.
|
||||
|
||||
## Changed
|
||||
|
||||
- Added back PTME busy bit polling. This is necessary due to changes to the AXI APB interface
|
||||
to the PTME core.
|
||||
|
||||
## Fixed
|
||||
|
||||
- For the live channel (VC0), telemetry was still only dumped if the transmitter is active.
|
||||
Please note that this fix will lead to crashes for FW versions below v3.2.
|
||||
However, it might not be an issue for the oldest firmware on the satellite (v2.5.1).
|
||||
|
||||
# [v5.2.0] 2023-07-02
|
||||
|
||||
## Fixed
|
||||
|
@ -9,7 +9,7 @@
|
||||
# ##############################################################################
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
set(OBSW_VERSION_MAJOR 5)
|
||||
set(OBSW_VERSION_MAJOR 6)
|
||||
set(OBSW_VERSION_MINOR 2)
|
||||
set(OBSW_VERSION_REVISION 0)
|
||||
|
||||
@ -93,7 +93,7 @@ set(OBSW_ADD_BPX_BATTERY_HANDLER
|
||||
1
|
||||
CACHE STRING "Add BPX battery module")
|
||||
set(OBSW_ADD_STAR_TRACKER
|
||||
${INIT_VAL}
|
||||
1
|
||||
CACHE STRING "Add Startracker module")
|
||||
set(OBSW_ADD_SUN_SENSORS
|
||||
${INIT_VAL}
|
||||
@ -150,7 +150,7 @@ set(OBSW_ADD_SYRLINKS
|
||||
1
|
||||
CACHE STRING "Add Syrlinks module")
|
||||
set(OBSW_ADD_TMP_DEVICES
|
||||
${INIT_VAL}
|
||||
1
|
||||
CACHE STRING "Add TMP devices")
|
||||
set(OBSW_ADD_GOMSPACE_PCDU
|
||||
1
|
||||
@ -162,7 +162,7 @@ set(OBSW_ADD_RW
|
||||
${INIT_VAL}
|
||||
CACHE STRING "Add RW modules")
|
||||
set(OBSW_ADD_SCEX_DEVICE
|
||||
${INIT_VAL}
|
||||
1
|
||||
CACHE STRING "Add Solar Cell Experiment module")
|
||||
set(OBSW_SYRLINKS_SIMULATED
|
||||
0
|
||||
|
@ -964,6 +964,12 @@ used by other software components to read the current chip and copy.
|
||||
This is a configuration scripts which runs after the Network Time Protocol has run. This script
|
||||
currently sets the static IP address `192.168.133.10` and starts the `can` interface.
|
||||
|
||||
## Initial boot delay
|
||||
|
||||
You can create a file named `boot_delays_secs.txt` inside the home folder to delay the OBSW boot
|
||||
for 6 seconds if the file is empty of for the number of seconds specified inside the file. This
|
||||
can be helpful if something inside the OBSW leads to an immediate crash of the OBC.
|
||||
|
||||
## PCDU
|
||||
|
||||
Connect to serial console of P60 Dock
|
||||
|
@ -113,7 +113,7 @@ void ObjectFactory::produce(void* args) {
|
||||
if (heaterHandler == nullptr) {
|
||||
sif::error << "HeaterHandler could not be created" << std::endl;
|
||||
} else {
|
||||
ObjectFactory::createThermalController(*heaterHandler);
|
||||
ObjectFactory::createThermalController(*heaterHandler, true);
|
||||
}
|
||||
new TestTask(objects::TEST_TASK);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @brief Auto-generated event translation file. Contains 296 translations.
|
||||
* @brief Auto-generated event translation file. Contains 301 translations.
|
||||
* @details
|
||||
* Generated on: 2023-06-21 19:01:02
|
||||
* Generated on: 2023-07-26 12:51:20
|
||||
*/
|
||||
#include "translateEvents.h"
|
||||
|
||||
@ -139,6 +139,7 @@ const char *ERROR_STATE_STRING = "ERROR_STATE";
|
||||
const char *RESET_OCCURED_STRING = "RESET_OCCURED";
|
||||
const char *BOOTING_FIRMWARE_FAILED_EVENT_STRING = "BOOTING_FIRMWARE_FAILED_EVENT";
|
||||
const char *BOOTING_BOOTLOADER_FAILED_EVENT_STRING = "BOOTING_BOOTLOADER_FAILED_EVENT";
|
||||
const char *COM_ERROR_REPLY_RECEIVED_STRING = "COM_ERROR_REPLY_RECEIVED";
|
||||
const char *SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING = "SUPV_MEMORY_READ_RPT_CRC_FAILURE";
|
||||
const char *SUPV_UNKNOWN_TM_STRING = "SUPV_UNKNOWN_TM";
|
||||
const char *SUPV_UNINIMPLEMENTED_TM_STRING = "SUPV_UNINIMPLEMENTED_TM";
|
||||
@ -278,6 +279,7 @@ const char *TRYING_I2C_RECOVERY_STRING = "TRYING_I2C_RECOVERY";
|
||||
const char *I2C_REBOOT_STRING = "I2C_REBOOT";
|
||||
const char *PDEC_REBOOT_STRING = "PDEC_REBOOT";
|
||||
const char *FIRMWARE_INFO_STRING = "FIRMWARE_INFO";
|
||||
const char *ACTIVE_SD_INFO_STRING = "ACTIVE_SD_INFO";
|
||||
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
|
||||
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
|
||||
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
|
||||
@ -286,6 +288,9 @@ const char *CAMERA_OVERHEATING_STRING = "CAMERA_OVERHEATING";
|
||||
const char *PCDU_SYSTEM_OVERHEATING_STRING = "PCDU_SYSTEM_OVERHEATING";
|
||||
const char *HEATER_NOT_OFF_FOR_OFF_MODE_STRING = "HEATER_NOT_OFF_FOR_OFF_MODE";
|
||||
const char *MGT_OVERHEATING_STRING = "MGT_OVERHEATING";
|
||||
const char *TCS_SWITCHING_HEATER_ON_STRING = "TCS_SWITCHING_HEATER_ON";
|
||||
const char *TCS_SWITCHING_HEATER_OFF_STRING = "TCS_SWITCHING_HEATER_OFF";
|
||||
const char *TCS_HEATER_MAX_BURN_TIME_REACHED_STRING = "TCS_HEATER_MAX_BURN_TIME_REACHED";
|
||||
const char *TX_TIMER_EXPIRED_STRING = "TX_TIMER_EXPIRED";
|
||||
const char *BIT_LOCK_TX_ON_STRING = "BIT_LOCK_TX_ON";
|
||||
const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION";
|
||||
@ -572,6 +577,8 @@ const char *translateEvents(Event event) {
|
||||
return BOOTING_FIRMWARE_FAILED_EVENT_STRING;
|
||||
case (11902):
|
||||
return BOOTING_BOOTLOADER_FAILED_EVENT_STRING;
|
||||
case (11903):
|
||||
return COM_ERROR_REPLY_RECEIVED_STRING;
|
||||
case (12001):
|
||||
return SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING;
|
||||
case (12002):
|
||||
@ -850,6 +857,8 @@ const char *translateEvents(Event event) {
|
||||
return PDEC_REBOOT_STRING;
|
||||
case (14013):
|
||||
return FIRMWARE_INFO_STRING;
|
||||
case (14014):
|
||||
return ACTIVE_SD_INFO_STRING;
|
||||
case (14100):
|
||||
return NO_VALID_SENSOR_TEMPERATURE_STRING;
|
||||
case (14101):
|
||||
@ -866,6 +875,12 @@ const char *translateEvents(Event event) {
|
||||
return HEATER_NOT_OFF_FOR_OFF_MODE_STRING;
|
||||
case (14108):
|
||||
return MGT_OVERHEATING_STRING;
|
||||
case (14109):
|
||||
return TCS_SWITCHING_HEATER_ON_STRING;
|
||||
case (14110):
|
||||
return TCS_SWITCHING_HEATER_OFF_STRING;
|
||||
case (14111):
|
||||
return TCS_HEATER_MAX_BURN_TIME_REACHED_STRING;
|
||||
case (14201):
|
||||
return TX_TIMER_EXPIRED_STRING;
|
||||
case (14202):
|
||||
|
@ -2,7 +2,7 @@
|
||||
* @brief Auto-generated object translation file.
|
||||
* @details
|
||||
* Contains 171 translations.
|
||||
* Generated on: 2023-06-21 19:01:02
|
||||
* Generated on: 2023-07-26 12:51:20
|
||||
*/
|
||||
#include "translateObjects.h"
|
||||
|
||||
|
@ -7,7 +7,8 @@ target_link_libraries(${SIMPLE_OBSW_NAME} PUBLIC ${LIB_FSFW_NAME})
|
||||
target_compile_definitions(${SIMPLE_OBSW_NAME} PRIVATE "Q7S_SIMPLE_MODE")
|
||||
add_subdirectory(simple)
|
||||
|
||||
target_sources(${OBSW_NAME} PUBLIC main.cpp obsw.cpp)
|
||||
target_sources(${OBSW_NAME} PUBLIC main.cpp obsw.cpp scheduling.cpp
|
||||
objectFactory.cpp)
|
||||
|
||||
add_subdirectory(boardtest)
|
||||
|
||||
|
@ -12,6 +12,9 @@ static constexpr char SPI_RW_DEV[] = "/dev/spi_rw";
|
||||
static constexpr char I2C_PL_EIVE[] = "/dev/i2c_pl";
|
||||
//! I2C bus using the I2C peripheral of the ARM processing system (PS)
|
||||
static constexpr char I2C_PS_EIVE[] = "/dev/i2c_ps";
|
||||
//! I2C bus using the first I2C peripheral of the ARM processing system (PS).
|
||||
//! Named like this because it is used by default for the Q7 devices.
|
||||
static constexpr char I2C_Q7_EIVE[] = "/dev/i2c_q7";
|
||||
|
||||
static constexpr char UART_GNSS_DEV[] = "/dev/gps0";
|
||||
static constexpr char UART_PLOC_MPSOC_DEV[] = "/dev/ul_plmpsoc";
|
||||
@ -85,13 +88,9 @@ static constexpr char EN_RW_4[] = "enable_rw_4";
|
||||
static constexpr char RAD_SENSOR_CHIP_SELECT[] = "rad_sensor_chip_select";
|
||||
static constexpr char ENABLE_RADFET[] = "enable_radfet";
|
||||
|
||||
static constexpr char PAPB_BUSY_SIGNAL_VC0[] = "papb_busy_signal_vc0";
|
||||
static constexpr char PAPB_EMPTY_SIGNAL_VC0[] = "papb_empty_signal_vc0";
|
||||
static constexpr char PAPB_BUSY_SIGNAL_VC1[] = "papb_busy_signal_vc1";
|
||||
static constexpr char PAPB_EMPTY_SIGNAL_VC1[] = "papb_empty_signal_vc1";
|
||||
static constexpr char PAPB_BUSY_SIGNAL_VC2[] = "papb_busy_signal_vc2";
|
||||
static constexpr char PAPB_EMPTY_SIGNAL_VC2[] = "papb_empty_signal_vc2";
|
||||
static constexpr char PAPB_BUSY_SIGNAL_VC3[] = "papb_busy_signal_vc3";
|
||||
static constexpr char PAPB_EMPTY_SIGNAL_VC3[] = "papb_empty_signal_vc3";
|
||||
|
||||
static constexpr char PTME_RESETN[] = "ptme_resetn";
|
||||
|
@ -218,15 +218,30 @@ void Q7STestTask::testProtHandler() {
|
||||
bool opPerformed = false;
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
// If any chips are unlocked, lock them here
|
||||
result = coreController->setBootCopyProtection(xsc::Chip::ALL_CHIP, xsc::Copy::ALL_COPY, true,
|
||||
opPerformed, true);
|
||||
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::CHIP_0, xsc::Copy::COPY_0,
|
||||
true);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
|
||||
}
|
||||
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::CHIP_0, xsc::Copy::COPY_1,
|
||||
true);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
|
||||
}
|
||||
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::CHIP_1, xsc::Copy::COPY_0,
|
||||
true);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
|
||||
}
|
||||
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::CHIP_1, xsc::Copy::COPY_1,
|
||||
true);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
|
||||
}
|
||||
|
||||
// unlock own copy
|
||||
result = coreController->setBootCopyProtection(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, false,
|
||||
opPerformed, true);
|
||||
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::SELF_CHIP,
|
||||
xsc::Copy::SELF_COPY, false);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
|
||||
}
|
||||
@ -239,8 +254,8 @@ void Q7STestTask::testProtHandler() {
|
||||
}
|
||||
|
||||
// lock own copy
|
||||
result = coreController->setBootCopyProtection(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, true,
|
||||
opPerformed, true);
|
||||
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::SELF_CHIP,
|
||||
xsc::Copy::SELF_COPY, true);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
|
||||
}
|
||||
@ -253,8 +268,8 @@ void Q7STestTask::testProtHandler() {
|
||||
}
|
||||
|
||||
// unlock specific copy
|
||||
result = coreController->setBootCopyProtection(xsc::Chip::CHIP_1, xsc::Copy::COPY_1, false,
|
||||
opPerformed, true);
|
||||
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::CHIP_1, xsc::Copy::COPY_1,
|
||||
false);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
|
||||
}
|
||||
@ -267,8 +282,8 @@ void Q7STestTask::testProtHandler() {
|
||||
}
|
||||
|
||||
// lock specific copy
|
||||
result = coreController->setBootCopyProtection(xsc::Chip::CHIP_1, xsc::Copy::COPY_1, true,
|
||||
opPerformed, true);
|
||||
result = coreController->setBootCopyProtectionAndUpdateFile(xsc::Chip::CHIP_1, xsc::Copy::COPY_1,
|
||||
true);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
|
||||
}
|
||||
|
@ -1,4 +1 @@
|
||||
target_sources(${OBSW_NAME} PRIVATE CoreController.cpp scheduling.cpp
|
||||
ObjectFactory.cpp WatchdogHandler.cpp)
|
||||
|
||||
target_sources(${SIMPLE_OBSW_NAME} PRIVATE scheduling.cpp)
|
||||
target_sources(${OBSW_NAME} PRIVATE CoreController.cpp WatchdogHandler.cpp)
|
||||
|
@ -156,20 +156,12 @@ ReturnValue_t CoreController::initialize() {
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "CoreController::initialize: Base init failed" << std::endl;
|
||||
}
|
||||
result = scratch::writeNumber(scratch::ALLOC_FAILURE_COUNT, 0);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "CoreController::initialize: Setting up alloc failure "
|
||||
"count failed"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
result = paramHelper.initialize();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
sdStateMachine();
|
||||
|
||||
EventManagerIF *eventManager =
|
||||
ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER);
|
||||
if (eventManager == nullptr or eventQueue == nullptr) {
|
||||
@ -188,19 +180,17 @@ ReturnValue_t CoreController::initialize() {
|
||||
}
|
||||
triggerEvent(core::REBOOT_SW, CURRENT_CHIP, CURRENT_COPY);
|
||||
announceCurrentImageInfo();
|
||||
// This has to come before the version announce because it might be required for retrieving
|
||||
// the firmware version.
|
||||
if (common::OBSW_VERSION_MAJOR >= 6 or common::OBSW_VERSION_MAJOR == 4) {
|
||||
UioMapper sysRomMapper(q7s::UIO_SYS_ROM);
|
||||
result = sysRomMapper.getMappedAdress(&mappedSysRomAddr, UioMapper::Permissions::READ_ONLY);
|
||||
if (result != returnvalue::OK) {
|
||||
// TODO: This might be a reason to switch to another image..
|
||||
sif::error << "Getting mapped SYS ROM UIO address failed" << std::endl;
|
||||
result = ObjectManager::CHILD_INIT_FAILED;
|
||||
}
|
||||
}
|
||||
announceVersionInfo();
|
||||
|
||||
SdCardManager::SdStatePair sdStates;
|
||||
sdcMan->getSdCardsStatus(sdStates);
|
||||
announceSdInfo(sdStates);
|
||||
sdStateMachine();
|
||||
result = scratch::writeNumber(scratch::ALLOC_FAILURE_COUNT, 0);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "CoreController::initialize: Setting up alloc failure "
|
||||
"count failed"
|
||||
<< std::endl;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -564,21 +554,24 @@ ReturnValue_t CoreController::sdStateMachine() {
|
||||
}
|
||||
|
||||
// This lambda checks the non-blocking operation of the SD card manager and assigns the new
|
||||
// state on success. It returns true for an operation success and false otherwise
|
||||
// state on success. It returns 0 for an operation success, -1 for failed operations, and 1
|
||||
// for pending operations
|
||||
auto nonBlockingSdcOpChecking = [&](SdStates newStateOnSuccess, uint16_t maxCycleCount,
|
||||
std::string opPrintout) {
|
||||
SdCardManager::OpStatus status = sdcMan->checkCurrentOp(operation);
|
||||
if (status == SdCardManager::OpStatus::SUCCESS) {
|
||||
if (status == SdCardManager::OpStatus::SUCCESS or sdInfo.cycleCount > maxCycleCount) {
|
||||
sdFsmState = newStateOnSuccess;
|
||||
sdInfo.commandPending = false;
|
||||
if (sdInfo.cycleCount > maxCycleCount) {
|
||||
sif::warning << "CoreController::sdStateMachine: " << opPrintout << " takes too long"
|
||||
<< std::endl;
|
||||
sdInfo.cycleCount = 0;
|
||||
return -1;
|
||||
}
|
||||
sdInfo.cycleCount = 0;
|
||||
return true;
|
||||
} else if (sdInfo.cycleCount > 4) {
|
||||
sif::warning << "CoreController::sdStateMachine: " << opPrintout << " takes too long"
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
return 0;
|
||||
};
|
||||
return 1;
|
||||
};
|
||||
|
||||
if (sdFsmState == SdStates::UPDATE_SD_INFO_START) {
|
||||
@ -654,7 +647,7 @@ ReturnValue_t CoreController::sdStateMachine() {
|
||||
sdFsmState = tgtState;
|
||||
}
|
||||
} else {
|
||||
if (nonBlockingSdcOpChecking(SdStates::MOUNT_SELF, 10, "Setting SDC state")) {
|
||||
if (nonBlockingSdcOpChecking(SdStates::MOUNT_SELF, 10, "Setting SDC state") <= 0) {
|
||||
sdInfo.activeState = sd::SdState::ON;
|
||||
currentStateSetter(sdInfo.active, sd::SdState::ON);
|
||||
// Skip the two cycles now.
|
||||
@ -682,7 +675,7 @@ ReturnValue_t CoreController::sdStateMachine() {
|
||||
result = sdCardSetup(sdInfo.active, sd::SdState::MOUNTED, sdInfo.activeChar);
|
||||
sdInfo.commandPending = true;
|
||||
} else {
|
||||
if (nonBlockingSdcOpChecking(SdStates::DETERMINE_OTHER, 5, "Mounting SD card")) {
|
||||
if (nonBlockingSdcOpChecking(SdStates::DETERMINE_OTHER, 5, "Mounting SD card") <= 0) {
|
||||
sdcMan->setActiveSdCard(sdInfo.active);
|
||||
currMntPrefix = sdcMan->getCurrentMountPrefix();
|
||||
sdInfo.activeState = sd::SdState::MOUNTED;
|
||||
@ -724,12 +717,7 @@ ReturnValue_t CoreController::sdStateMachine() {
|
||||
sdInfo.commandPending = true;
|
||||
} else {
|
||||
if (nonBlockingSdcOpChecking(SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE, 10,
|
||||
"Switching off other SD card")) {
|
||||
sdInfo.otherState = sd::SdState::OFF;
|
||||
currentStateSetter(sdInfo.other, sd::SdState::OFF);
|
||||
} else {
|
||||
// Continue.. avoid being stuck here..
|
||||
sdFsmState = SdStates::SKIP_CYCLE_BEFORE_INFO_UPDATE;
|
||||
"Switching off other SD card") <= 0) {
|
||||
sdInfo.otherState = sd::SdState::OFF;
|
||||
currentStateSetter(sdInfo.other, sd::SdState::OFF);
|
||||
}
|
||||
@ -740,12 +728,7 @@ ReturnValue_t CoreController::sdStateMachine() {
|
||||
sdInfo.commandPending = true;
|
||||
} else {
|
||||
if (nonBlockingSdcOpChecking(SdStates::MOUNT_UNMOUNT_OTHER, 10,
|
||||
"Switching on other SD card")) {
|
||||
sdInfo.otherState = sd::SdState::ON;
|
||||
currentStateSetter(sdInfo.other, sd::SdState::ON);
|
||||
} else {
|
||||
// Contnue.. avoid being stuck here.
|
||||
sdFsmState = SdStates::MOUNT_UNMOUNT_OTHER;
|
||||
"Switching on other SD card") <= 0) {
|
||||
sdInfo.otherState = sd::SdState::ON;
|
||||
currentStateSetter(sdInfo.other, sd::SdState::ON);
|
||||
}
|
||||
@ -760,7 +743,8 @@ ReturnValue_t CoreController::sdStateMachine() {
|
||||
result = sdCardSetup(sdInfo.other, sd::SdState::ON, sdInfo.otherChar);
|
||||
sdInfo.commandPending = true;
|
||||
} else {
|
||||
if (nonBlockingSdcOpChecking(SdStates::SET_STATE_OTHER, 10, "Unmounting other SD card")) {
|
||||
if (nonBlockingSdcOpChecking(SdStates::SET_STATE_OTHER, 10, "Unmounting other SD card") <=
|
||||
0) {
|
||||
sdInfo.otherState = sd::SdState::ON;
|
||||
currentStateSetter(sdInfo.other, sd::SdState::ON);
|
||||
} else {
|
||||
@ -774,7 +758,8 @@ ReturnValue_t CoreController::sdStateMachine() {
|
||||
result = sdCardSetup(sdInfo.other, sd::SdState::MOUNTED, sdInfo.otherChar);
|
||||
sdInfo.commandPending = true;
|
||||
} else {
|
||||
if (nonBlockingSdcOpChecking(SdStates::UPDATE_SD_INFO_END, 4, "Mounting other SD card")) {
|
||||
if (nonBlockingSdcOpChecking(SdStates::UPDATE_SD_INFO_END, 4, "Mounting other SD card") <=
|
||||
0) {
|
||||
sdInfo.otherState = sd::SdState::MOUNTED;
|
||||
currentStateSetter(sdInfo.other, sd::SdState::MOUNTED);
|
||||
}
|
||||
@ -811,6 +796,7 @@ ReturnValue_t CoreController::sdStateMachine() {
|
||||
}
|
||||
sif::info << "SD card update into " << modeStr
|
||||
<< " mode finished. Active SD: " << sdInfo.activeChar << std::endl;
|
||||
announceSdInfo(sdInfo.currentState);
|
||||
if (not sdInfo.initFinished) {
|
||||
updateInternalSdInfo();
|
||||
sdInfo.initFinished = true;
|
||||
@ -849,7 +835,7 @@ ReturnValue_t CoreController::sdCardSetup(sd::SdCard sdCard, sd::SdState targetS
|
||||
if (state == sd::SdState::MOUNTED) {
|
||||
if (targetState == sd::SdState::OFF) {
|
||||
sif::info << "Switching off SD card " << sdChar << std::endl;
|
||||
return sdcMan->switchOffSdCard(sdCard, true, &sdInfo.currentState);
|
||||
return sdcMan->switchOffSdCard(sdCard, sdInfo.currentState, true);
|
||||
} else if (targetState == sd::SdState::ON) {
|
||||
sif::info << "Unmounting SD card " << sdChar << std::endl;
|
||||
return sdcMan->unmountSdCard(sdCard);
|
||||
@ -883,7 +869,7 @@ ReturnValue_t CoreController::sdCardSetup(sd::SdCard sdCard, sd::SdState targetS
|
||||
return sdcMan->mountSdCard(sdCard);
|
||||
} else if (targetState == sd::SdState::OFF) {
|
||||
sif::info << "Switching off SD card " << sdChar << std::endl;
|
||||
return sdcMan->switchOffSdCard(sdCard, false, &sdInfo.currentState);
|
||||
return sdcMan->switchOffSdCard(sdCard, sdInfo.currentState, false);
|
||||
}
|
||||
} else {
|
||||
sif::warning << "CoreController::sdCardSetup: Invalid state for this call" << std::endl;
|
||||
@ -907,8 +893,7 @@ ReturnValue_t CoreController::sdColdRedundantBlockingInit() {
|
||||
sif::info << "Switching off secondary SD card " << sdInfo.otherChar << std::endl;
|
||||
// Switch off other SD card in cold redundant mode if setting up preferred one worked
|
||||
// without issues
|
||||
ReturnValue_t result2 =
|
||||
sdcMan->switchOffSdCard(sdInfo.other, sdInfo.otherState, &sdInfo.currentState);
|
||||
ReturnValue_t result2 = sdcMan->switchOffSdCard(sdInfo.other, sdInfo.currentState, true);
|
||||
if (result2 != returnvalue::OK and result2 != SdCardManager::ALREADY_OFF) {
|
||||
sif::warning << "Switching off secondary SD card " << sdInfo.otherChar
|
||||
<< " in cold redundant mode failed" << std::endl;
|
||||
@ -1238,18 +1223,25 @@ ReturnValue_t CoreController::gracefulShutdownTasks(xsc::Chip chip, xsc::Copy co
|
||||
// Ensure that all writes/reads do finish.
|
||||
sync();
|
||||
|
||||
// Attempt graceful shutdown by unmounting and switching off SD cards
|
||||
sdcMan->switchOffSdCard(sd::SdCard::SLOT_0);
|
||||
sdcMan->switchOffSdCard(sd::SdCard::SLOT_1);
|
||||
// If any boot copies are unprotected.
|
||||
// Actually this function only ensures that reboots to the own image are protected..
|
||||
ReturnValue_t result = setBootCopyProtection(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, true,
|
||||
protOpPerformed, false);
|
||||
if (result == returnvalue::OK and protOpPerformed) {
|
||||
// Unmount and switch off SD cards. This could possibly fix issues with the SD card and is
|
||||
// the more graceful way to reboot the system. This function takes around 400 ms.
|
||||
ReturnValue_t result = handleSwitchingSdCardsOffNonBlocking();
|
||||
if (result != returnvalue::OK) {
|
||||
sif::error
|
||||
<< "CoreController::gracefulShutdownTasks: Issues unmounting or switching SD cards off"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
// Ensure that the target chip is writeprotected in any case.
|
||||
bool wasProtected = handleBootCopyProt(chip, copy, true);
|
||||
if (wasProtected) {
|
||||
// TODO: Would be nice to notify operator. But we can't use the filesystem anymore
|
||||
// and a reboot is imminent. Use scratch buffer?
|
||||
sif::info << "Running slot was writeprotected before reboot" << std::endl;
|
||||
}
|
||||
sif::info << "Graceful shutdown handling done" << std::endl;
|
||||
// Ensure that all diagnostic prinouts arrive.
|
||||
TaskFactory::delayTask(50);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -1283,144 +1275,50 @@ ReturnValue_t CoreController::generateChipStateFile() {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t CoreController::setBootCopyProtection(xsc::Chip targetChip, xsc::Copy targetCopy,
|
||||
bool protect, bool &protOperationPerformed,
|
||||
bool updateProtFile) {
|
||||
bool allChips = false;
|
||||
bool allCopies = false;
|
||||
bool selfChip = false;
|
||||
bool selfCopy = false;
|
||||
protOperationPerformed = false;
|
||||
|
||||
switch (targetChip) {
|
||||
case (xsc::Chip::ALL_CHIP): {
|
||||
allChips = true;
|
||||
break;
|
||||
}
|
||||
case (xsc::Chip::NO_CHIP): {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (xsc::Chip::SELF_CHIP): {
|
||||
selfChip = true;
|
||||
targetChip = CURRENT_CHIP;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (targetCopy) {
|
||||
case (xsc::Copy::ALL_COPY): {
|
||||
allCopies = true;
|
||||
break;
|
||||
}
|
||||
case (xsc::Copy::NO_COPY): {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (xsc::Copy::SELF_COPY): {
|
||||
selfCopy = true;
|
||||
targetCopy = CURRENT_COPY;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
ReturnValue_t CoreController::setBootCopyProtectionAndUpdateFile(xsc::Chip targetChip,
|
||||
xsc::Copy targetCopy,
|
||||
bool protect) {
|
||||
if (targetChip == xsc::Chip::ALL_CHIP or targetCopy == xsc::Copy::ALL_COPY) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
for (uint8_t arrIdx = 0; arrIdx < protArray.size(); arrIdx++) {
|
||||
int result = handleBootCopyProtAtIndex(targetChip, targetCopy, protect, protOperationPerformed,
|
||||
selfChip, selfCopy, allChips, allCopies, arrIdx);
|
||||
if (result != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (protOperationPerformed and updateProtFile) {
|
||||
bool protOperationPerformed = handleBootCopyProt(targetChip, targetCopy, protect);
|
||||
if (protOperationPerformed) {
|
||||
updateProtInfo();
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
int CoreController::handleBootCopyProtAtIndex(xsc::Chip targetChip, xsc::Copy targetCopy,
|
||||
bool protect, bool &protOperationPerformed,
|
||||
bool selfChip, bool selfCopy, bool allChips,
|
||||
bool allCopies, uint8_t arrIdx) {
|
||||
bool currentProt = protArray[arrIdx];
|
||||
bool CoreController::handleBootCopyProt(xsc::Chip targetChip, xsc::Copy targetCopy, bool protect) {
|
||||
std::ostringstream oss;
|
||||
bool performOp = false;
|
||||
if (protect == currentProt) {
|
||||
return 0;
|
||||
}
|
||||
if (protOperationPerformed) {
|
||||
if ((selfChip and selfCopy) or (not allCopies and not allChips)) {
|
||||
// No need to continue, only one operation was requested
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
xsc::Chip currentChip;
|
||||
xsc::Copy currentCopy;
|
||||
oss << "writeprotect ";
|
||||
if (arrIdx == 0 or arrIdx == 1) {
|
||||
oss << "0 ";
|
||||
currentChip = xsc::Chip::CHIP_0;
|
||||
} else {
|
||||
oss << "1 ";
|
||||
currentChip = xsc::Chip::CHIP_1;
|
||||
if (targetChip == xsc::Chip::SELF_CHIP) {
|
||||
targetChip = CURRENT_CHIP;
|
||||
}
|
||||
if (arrIdx == 0 or arrIdx == 2) {
|
||||
if (targetCopy == xsc::Copy::SELF_COPY) {
|
||||
targetCopy = CURRENT_COPY;
|
||||
}
|
||||
if (targetChip == xsc::Chip::CHIP_0) {
|
||||
oss << "0 ";
|
||||
currentCopy = xsc::Copy::COPY_0;
|
||||
} else {
|
||||
} else if (targetChip == xsc::Chip::CHIP_1) {
|
||||
oss << "1 ";
|
||||
}
|
||||
if (targetCopy == xsc::Copy::COPY_0) {
|
||||
oss << "0 ";
|
||||
} else if (targetCopy == xsc::Copy::COPY_1) {
|
||||
oss << "1 ";
|
||||
currentCopy = xsc::Copy::COPY_1;
|
||||
}
|
||||
if (protect) {
|
||||
oss << "1";
|
||||
} else {
|
||||
oss << "0";
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
if (allChips and allCopies) {
|
||||
performOp = true;
|
||||
} else if (allChips) {
|
||||
if ((selfCopy and CURRENT_COPY == targetCopy) or (currentCopy == targetCopy)) {
|
||||
performOp = true;
|
||||
}
|
||||
} else if (allCopies) {
|
||||
if ((selfChip and CURRENT_COPY == targetCopy) or (currentChip == targetChip)) {
|
||||
performOp = true;
|
||||
}
|
||||
} else if (selfChip and (currentChip == targetChip)) {
|
||||
if (selfCopy) {
|
||||
if (currentCopy == targetCopy) {
|
||||
performOp = true;
|
||||
}
|
||||
} else {
|
||||
performOp = true;
|
||||
}
|
||||
|
||||
} else if (selfCopy and (currentCopy == targetCopy)) {
|
||||
if (selfChip) {
|
||||
if (currentChip == targetChip) {
|
||||
performOp = true;
|
||||
}
|
||||
} else {
|
||||
performOp = true;
|
||||
}
|
||||
} else if ((targetChip == currentChip) and (targetCopy == currentCopy)) {
|
||||
performOp = true;
|
||||
sif::info << "Executing command: " << oss.str() << std::endl;
|
||||
int result = std::system(oss.str().c_str());
|
||||
if (result == 0) {
|
||||
return true;
|
||||
}
|
||||
if (result != 0) {
|
||||
utility::handleSystemError(result, "CoreController::checkAndSetBootCopyProtection");
|
||||
}
|
||||
if (performOp) {
|
||||
// TODO: Lock operation take a long time. Use command executor? That would require a
|
||||
// new state machine..
|
||||
protOperationPerformed = true;
|
||||
sif::info << "Executing command: " << oss.str() << std::endl;
|
||||
result = std::system(oss.str().c_str());
|
||||
}
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
ReturnValue_t CoreController::updateProtInfo(bool regenerateChipStateFile) {
|
||||
@ -1465,7 +1363,6 @@ ReturnValue_t CoreController::handleProtInfoUpdateLine(std::string nextLine) {
|
||||
using namespace std;
|
||||
string word;
|
||||
uint8_t wordIdx = 0;
|
||||
uint8_t arrayIdx = 0;
|
||||
istringstream iss(nextLine);
|
||||
xsc::Chip currentChip = xsc::Chip::CHIP_0;
|
||||
xsc::Copy currentCopy = xsc::Copy::COPY_0;
|
||||
@ -1477,28 +1374,11 @@ ReturnValue_t CoreController::handleProtInfoUpdateLine(std::string nextLine) {
|
||||
currentCopy = static_cast<xsc::Copy>(stoi(word));
|
||||
}
|
||||
|
||||
if (wordIdx == 3) {
|
||||
if (currentChip == xsc::Chip::CHIP_0) {
|
||||
if (currentCopy == xsc::Copy::COPY_0) {
|
||||
arrayIdx = 0;
|
||||
} else if (currentCopy == xsc::Copy::COPY_1) {
|
||||
arrayIdx = 1;
|
||||
}
|
||||
}
|
||||
|
||||
else if (currentChip == xsc::Chip::CHIP_1) {
|
||||
if (currentCopy == xsc::Copy::COPY_0) {
|
||||
arrayIdx = 2;
|
||||
} else if (currentCopy == xsc::Copy::COPY_1) {
|
||||
arrayIdx = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (wordIdx == 5) {
|
||||
if (word == "unlocked.") {
|
||||
protArray[arrayIdx] = false;
|
||||
protArray[currentChip][currentCopy] = false;
|
||||
} else {
|
||||
protArray[arrayIdx] = true;
|
||||
protArray[currentChip][currentCopy] = true;
|
||||
}
|
||||
}
|
||||
wordIdx++;
|
||||
@ -2526,14 +2406,10 @@ void CoreController::announceVersionInfo() {
|
||||
}
|
||||
|
||||
triggerEvent(VERSION_INFO, p1, p2);
|
||||
|
||||
if (common::OBSW_VERSION_MAJOR >= 6 or common::OBSW_VERSION_MAJOR == 4) {
|
||||
if (mappedSysRomAddr != nullptr) {
|
||||
uint32_t p1Firmware = *(reinterpret_cast<uint32_t *>(mappedSysRomAddr));
|
||||
uint32_t p2Firmware = *(reinterpret_cast<uint32_t *>(mappedSysRomAddr) + 1);
|
||||
triggerEvent(FIRMWARE_INFO, p1Firmware, p2Firmware);
|
||||
}
|
||||
}
|
||||
p1 = (core::FW_VERSION_MAJOR << 24) | (core::FW_VERSION_MINOR << 16) |
|
||||
(core::FW_VERSION_REVISION << 8) | (core::FW_VERSION_HAS_SHA);
|
||||
std::memcpy(&p2, core::FW_VERSION_GIT_SHA, 4);
|
||||
triggerEvent(FIRMWARE_INFO, p1, p2);
|
||||
}
|
||||
|
||||
void CoreController::announceCurrentImageInfo() {
|
||||
@ -2585,6 +2461,68 @@ ReturnValue_t CoreController::performGracefulShutdown(xsc::Chip tgtChip, xsc::Co
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void CoreController::announceSdInfo(SdCardManager::SdStatePair sdStates) {
|
||||
auto activeSdCard = sdcMan->getActiveSdCard();
|
||||
uint32_t p1 = sd::SdCard::NONE;
|
||||
if (activeSdCard.has_value()) {
|
||||
p1 = static_cast<uint32_t>(activeSdCard.value());
|
||||
}
|
||||
uint32_t p2 =
|
||||
(static_cast<uint32_t>(sdStates.first) << 16) | static_cast<uint32_t>(sdStates.second);
|
||||
triggerEvent(core::ACTIVE_SD_INFO, p1, p2);
|
||||
}
|
||||
|
||||
ReturnValue_t CoreController::handleSwitchingSdCardsOffNonBlocking() {
|
||||
sdcMan->setBlocking(false);
|
||||
SdCardManager::Operations op;
|
||||
std::pair<sd::SdState, sd::SdState> sdStatus;
|
||||
ReturnValue_t result = sdcMan->getSdCardsStatus(sdStatus);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
Countdown maxWaitTimeCd(10000);
|
||||
// Stopwatch watch;
|
||||
auto waitingForFinish = [&]() {
|
||||
auto currentState = sdcMan->checkCurrentOp(op);
|
||||
if (currentState == SdCardManager::OpStatus::IDLE) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
while (currentState == SdCardManager::OpStatus::ONGOING) {
|
||||
if (maxWaitTimeCd.hasTimedOut()) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
TaskFactory::delayTask(50);
|
||||
currentState = sdcMan->checkCurrentOp(op);
|
||||
}
|
||||
return returnvalue::OK;
|
||||
};
|
||||
if (sdStatus.first != sd::SdState::OFF) {
|
||||
sdcMan->unmountSdCard(sd::SdCard::SLOT_0);
|
||||
result = waitingForFinish();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
sdcMan->switchOffSdCard(sd::SdCard::SLOT_0, sdStatus, false);
|
||||
result = waitingForFinish();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (sdStatus.second != sd::SdState::OFF) {
|
||||
sdcMan->unmountSdCard(sd::SdCard::SLOT_1);
|
||||
result = waitingForFinish();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
sdcMan->switchOffSdCard(sd::SdCard::SLOT_1, sdStatus, false);
|
||||
result = waitingForFinish();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool CoreController::isNumber(const std::string &s) {
|
||||
return !s.empty() && std::find_if(s.begin(), s.end(),
|
||||
[](unsigned char c) { return !std::isdigit(c); }) == s.end();
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef BSP_Q7S_CORE_CORECONTROLLER_H_
|
||||
#define BSP_Q7S_CORE_CORECONTROLLER_H_
|
||||
|
||||
#include <bsp_q7s/core/defs.h>
|
||||
#include <fsfw/container/DynamicFIFO.h>
|
||||
#include <fsfw/container/SimpleRingBuffer.h>
|
||||
#include <fsfw/globalfunctions/PeriodicOperationDivider.h>
|
||||
@ -14,7 +15,6 @@
|
||||
#include <atomic>
|
||||
#include <cstddef>
|
||||
|
||||
#include "CoreDefinitions.h"
|
||||
#include "OBSWConfig.h"
|
||||
#include "bsp_q7s/fs/SdCardManager.h"
|
||||
#include "events/subsystemIdRanges.h"
|
||||
@ -199,8 +199,8 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
|
||||
* @param updateProtFile Specify whether the protection info file is updated
|
||||
* @return
|
||||
*/
|
||||
ReturnValue_t setBootCopyProtection(xsc::Chip targetChip, xsc::Copy targetCopy, bool protect,
|
||||
bool& protOperationPerformed, bool updateProtFile = true);
|
||||
ReturnValue_t setBootCopyProtectionAndUpdateFile(xsc::Chip targetChip, xsc::Copy targetCopy,
|
||||
bool protect);
|
||||
|
||||
bool sdInitFinished() const;
|
||||
|
||||
@ -304,12 +304,10 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
|
||||
Countdown sdCardCheckCd = Countdown(INIT_SD_CARD_CHECK_TIMEOUT);
|
||||
|
||||
/**
|
||||
* Index 0: Chip 0 Copy 0
|
||||
* Index 1: Chip 0 Copy 1
|
||||
* Index 2: Chip 1 Copy 0
|
||||
* Index 3: Chip 1 Copy 1
|
||||
* First index: Chip.
|
||||
* Second index: Copy.
|
||||
*/
|
||||
std::array<bool, 4> protArray;
|
||||
bool protArray[2][2]{};
|
||||
PeriodicOperationDivider opDivider5;
|
||||
PeriodicOperationDivider opDivider10;
|
||||
|
||||
@ -374,9 +372,8 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
|
||||
ReturnValue_t gracefulShutdownTasks(xsc::Chip chip, xsc::Copy copy, bool& protOpPerformed);
|
||||
|
||||
ReturnValue_t handleProtInfoUpdateLine(std::string nextLine);
|
||||
int handleBootCopyProtAtIndex(xsc::Chip targetChip, xsc::Copy targetCopy, bool protect,
|
||||
bool& protOperationPerformed, bool selfChip, bool selfCopy,
|
||||
bool allChips, bool allCopies, uint8_t arrIdx);
|
||||
ReturnValue_t handleSwitchingSdCardsOffNonBlocking();
|
||||
bool handleBootCopyProt(xsc::Chip targetChip, xsc::Copy targetCopy, bool protect);
|
||||
void rebootWatchdogAlgorithm(RebootWatchdogFile& rf, bool& needsReboot, xsc::Chip& tgtChip,
|
||||
xsc::Copy& tgtCopy);
|
||||
void resetRebootWatchdogCounters(xsc::Chip tgtChip, xsc::Copy tgtCopy);
|
||||
@ -388,6 +385,7 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
|
||||
void announceBootCounts();
|
||||
void announceVersionInfo();
|
||||
void announceCurrentImageInfo();
|
||||
void announceSdInfo(SdCardManager::SdStatePair sdStates);
|
||||
void readHkData();
|
||||
void dirListingDumpHandler();
|
||||
bool isNumber(const std::string& s);
|
||||
|
@ -1,10 +1,16 @@
|
||||
#ifndef BSP_Q7S_CORE_COREDEFINITIONS_H_
|
||||
#define BSP_Q7S_CORE_COREDEFINITIONS_H_
|
||||
#ifndef BSP_Q7S_CORE_DEFS_H_
|
||||
#define BSP_Q7S_CORE_DEFS_H_
|
||||
|
||||
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
|
||||
|
||||
namespace core {
|
||||
|
||||
extern uint8_t FW_VERSION_MAJOR;
|
||||
extern uint8_t FW_VERSION_MINOR;
|
||||
extern uint8_t FW_VERSION_REVISION;
|
||||
extern bool FW_VERSION_HAS_SHA;
|
||||
extern char FW_VERSION_GIT_SHA[4];
|
||||
|
||||
static const uint8_t HK_SET_ENTRIES = 3;
|
||||
static const uint32_t HK_SET_ID = 5;
|
||||
|
||||
@ -36,4 +42,4 @@ class HkSet : public StaticLocalDataSet<HK_SET_ENTRIES> {
|
||||
|
||||
} // namespace core
|
||||
|
||||
#endif /* BSP_Q7S_CORE_COREDEFINITIONS_H_ */
|
||||
#endif /* BSP_Q7S_CORE_DEFS_H_ */
|
@ -1,4 +1,5 @@
|
||||
#include <bsp_q7s/callbacks/q7sGpioCallbacks.h>
|
||||
#include <bsp_q7s/objectFactory.h>
|
||||
#include <dummies/ComCookieDummy.h>
|
||||
#include <dummies/PcduHandlerDummy.h>
|
||||
#include <fsfw/health/HealthTableIF.h>
|
||||
@ -10,8 +11,8 @@
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "bsp_q7s/core/CoreController.h"
|
||||
#include "bsp_q7s/core/ObjectFactory.h"
|
||||
#include "busConf.h"
|
||||
#include "common/config/devices/addresses.h"
|
||||
#include "devConf.h"
|
||||
#include "dummies/helperFactory.h"
|
||||
#include "eive/objects.h"
|
||||
@ -35,6 +36,7 @@ void ObjectFactory::produce(void* args) {
|
||||
#endif
|
||||
|
||||
PersistentTmStores stores;
|
||||
readFirmwareVersion();
|
||||
ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel,
|
||||
*SdCardManager::instance(), &ipcStore, &tmStore, stores, 200,
|
||||
enableHkSets);
|
||||
@ -44,7 +46,7 @@ void ObjectFactory::produce(void* args) {
|
||||
SpiComIF* spiMainComIF = nullptr;
|
||||
I2cComIF* i2cComIF = nullptr;
|
||||
createCommunicationInterfaces(&gpioComIF, &uartComIF, &spiMainComIF, &i2cComIF);
|
||||
/* Adding gpios for chip select decoding to the gpioComIf */
|
||||
// Adding GPIOs for chip select decoding and initializing them.
|
||||
q7s::gpioCallbacks::initSpiCsDecoder(gpioComIF);
|
||||
gpioCallbacks::disableAllDecoder(gpioComIF);
|
||||
createPlI2cResetGpio(gpioComIF);
|
||||
@ -60,11 +62,32 @@ void ObjectFactory::produce(void* args) {
|
||||
#if OBSW_ADD_PLOC_SUPERVISOR == 1 || OBSW_ADD_PLOC_MPSOC == 1
|
||||
dummyCfg.addPlocDummies = false;
|
||||
#endif
|
||||
#if OBSW_ADD_TMP_DEVICES == 1
|
||||
std::vector<std::pair<object_id_t, address_t>> tmpDevsToAdd = {{
|
||||
{objects::TMP1075_HANDLER_PLPCDU_0, addresses::TMP1075_PLPCDU_0},
|
||||
{objects::TMP1075_HANDLER_PLPCDU_1, addresses::TMP1075_PLPCDU_1},
|
||||
{objects::TMP1075_HANDLER_IF_BOARD, addresses::TMP1075_IF_BOARD},
|
||||
}};
|
||||
createTmpComponents(tmpDevsToAdd);
|
||||
dummy::Tmp1075Cfg tmpCfg{};
|
||||
tmpCfg.addTcsBrd0 = true;
|
||||
tmpCfg.addTcsBrd1 = true;
|
||||
tmpCfg.addPlPcdu0 = false;
|
||||
tmpCfg.addPlPcdu1 = false;
|
||||
tmpCfg.addIfBrd = false;
|
||||
dummyCfg.tmp1075Cfg = tmpCfg;
|
||||
#endif
|
||||
#if OBSW_ADD_GOMSPACE_PCDU == 1
|
||||
dummyCfg.addPowerDummies = false;
|
||||
// The ACU broke.
|
||||
dummyCfg.addOnlyAcuDummy = true;
|
||||
#endif
|
||||
#if OBSW_ADD_STAR_TRACKER == 1
|
||||
dummyCfg.addStrDummy = false;
|
||||
#endif
|
||||
#if OBSW_ADD_SCEX_DEVICE == 0
|
||||
dummyCfg.addScexDummy = true;
|
||||
#endif
|
||||
#if OBSW_ADD_BPX_BATTERY_HANDLER == 1
|
||||
dummyCfg.addBpxBattDummy = false;
|
||||
#endif
|
||||
@ -97,8 +120,14 @@ void ObjectFactory::produce(void* args) {
|
||||
gpioChecker(gpioComIF->addGpios(acsBoardGpios), "ACS Board");
|
||||
#endif
|
||||
|
||||
const char* battAndImtqI2cDev = q7s::I2C_PL_EIVE;
|
||||
if (core::FW_VERSION_MAJOR >= 4) {
|
||||
battAndImtqI2cDev = q7s::I2C_PS_EIVE;
|
||||
}
|
||||
static_cast<void>(battAndImtqI2cDev);
|
||||
|
||||
#if OBSW_ADD_MGT == 1
|
||||
createImtqComponents(pwrSwitcher, enableHkSets);
|
||||
createImtqComponents(pwrSwitcher, enableHkSets, battAndImtqI2cDev);
|
||||
#endif
|
||||
|
||||
#if OBSW_ADD_SYRLINKS == 1
|
||||
@ -110,7 +139,7 @@ void ObjectFactory::produce(void* args) {
|
||||
#endif
|
||||
|
||||
#if OBSW_ADD_BPX_BATTERY_HANDLER == 1
|
||||
createBpxBatteryComponent(enableHkSets);
|
||||
createBpxBatteryComponent(enableHkSets, battAndImtqI2cDev);
|
||||
#endif
|
||||
|
||||
#if OBSW_ADD_STAR_TRACKER == 1
|
||||
@ -142,6 +171,6 @@ void ObjectFactory::produce(void* args) {
|
||||
createAcsController(true, enableHkSets);
|
||||
HeaterHandler* heaterHandler;
|
||||
createHeaterComponents(gpioComIF, pwrSwitcher, healthTable, heaterHandler);
|
||||
createThermalController(*heaterHandler);
|
||||
satsystem::init();
|
||||
createThermalController(*heaterHandler, true);
|
||||
satsystem::init(true);
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <bsp_q7s/callbacks/q7sGpioCallbacks.h>
|
||||
#include <bsp_q7s/objectFactory.h>
|
||||
#include <devices/gpioIds.h>
|
||||
#include <fsfw/storagemanager/LocalPool.h>
|
||||
#include <fsfw/storagemanager/PoolManager.h>
|
||||
@ -7,9 +8,9 @@
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "bsp_q7s/core/CoreController.h"
|
||||
#include "bsp_q7s/core/ObjectFactory.h"
|
||||
#include "busConf.h"
|
||||
#include "devConf.h"
|
||||
#include "devices/addresses.h"
|
||||
#include "eive/objects.h"
|
||||
#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h"
|
||||
#include "linux/ObjectFactory.h"
|
||||
@ -32,6 +33,7 @@ void ObjectFactory::produce(void* args) {
|
||||
#endif
|
||||
|
||||
PersistentTmStores stores;
|
||||
readFirmwareVersion();
|
||||
ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel,
|
||||
*SdCardManager::instance(), &ipcStore, &tmStore, stores, 200,
|
||||
true);
|
||||
@ -67,7 +69,16 @@ void ObjectFactory::produce(void* args) {
|
||||
HeaterHandler* heaterHandler;
|
||||
createHeaterComponents(gpioComIF, pwrSwitcher, healthTable, heaterHandler);
|
||||
#if OBSW_ADD_TMP_DEVICES == 1
|
||||
createTmpComponents();
|
||||
std::vector<std::pair<object_id_t, address_t>> tmpDevsToAdd = {{
|
||||
{objects::TMP1075_HANDLER_TCS_0, addresses::TMP1075_TCS_0},
|
||||
{objects::TMP1075_HANDLER_TCS_1, addresses::TMP1075_TCS_1},
|
||||
{objects::TMP1075_HANDLER_PLPCDU_0, addresses::TMP1075_PLPCDU_0},
|
||||
// damaged
|
||||
// {objects::TMP1075_HANDLER_PLPCDU_1, addresses::TMP1075_PLPCDU_1},
|
||||
{objects::TMP1075_HANDLER_IF_BOARD, addresses::TMP1075_IF_BOARD},
|
||||
}};
|
||||
|
||||
createTmpComponents(tmpDevsToAdd);
|
||||
#endif
|
||||
createSolarArrayDeploymentComponents(*pwrSwitcher, *gpioComIF);
|
||||
createPlPcduComponents(gpioComIF, spiMainComIF, pwrSwitcher, *stackHandler);
|
||||
@ -77,13 +88,17 @@ void ObjectFactory::produce(void* args) {
|
||||
createRtdComponents(q7s::SPI_DEFAULT_DEV, gpioComIF, pwrSwitcher, spiMainComIF);
|
||||
createPayloadComponents(gpioComIF, *pwrSwitcher);
|
||||
|
||||
const char* battAndImtqI2cDev = q7s::I2C_PL_EIVE;
|
||||
if (core::FW_VERSION_MAJOR >= 4) {
|
||||
battAndImtqI2cDev = q7s::I2C_PS_EIVE;
|
||||
}
|
||||
#if OBSW_ADD_MGT == 1
|
||||
createImtqComponents(pwrSwitcher, enableHkSets);
|
||||
createImtqComponents(pwrSwitcher, enableHkSets, battAndImtqI2cDev);
|
||||
#endif
|
||||
createReactionWheelComponents(gpioComIF, pwrSwitcher);
|
||||
|
||||
#if OBSW_ADD_BPX_BATTERY_HANDLER == 1
|
||||
createBpxBatteryComponent(enableHkSets);
|
||||
createBpxBatteryComponent(enableHkSets, battAndImtqI2cDev);
|
||||
#endif
|
||||
|
||||
#if OBSW_ADD_STAR_TRACKER == 1
|
||||
@ -113,7 +128,7 @@ void ObjectFactory::produce(void* args) {
|
||||
#endif /* OBSW_ADD_TEST_CODE == 1 */
|
||||
|
||||
createMiscComponents();
|
||||
createThermalController(*heaterHandler);
|
||||
createThermalController(*heaterHandler, false);
|
||||
createAcsController(true, enableHkSets);
|
||||
satsystem::init();
|
||||
satsystem::init(false);
|
||||
}
|
||||
|
@ -125,13 +125,8 @@ ReturnValue_t SdCardManager::switchOnSdCard(sd::SdCard sdCard, bool doMountSdCar
|
||||
return mountSdCard(sdCard);
|
||||
}
|
||||
|
||||
ReturnValue_t SdCardManager::switchOffSdCard(sd::SdCard sdCard, bool doUnmountSdCard,
|
||||
SdStatePair* statusPair) {
|
||||
std::pair<sd::SdState, sd::SdState> active;
|
||||
ReturnValue_t result = getSdCardsStatus(active);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
ReturnValue_t SdCardManager::switchOffSdCard(sd::SdCard sdCard, SdStatePair& sdStates,
|
||||
bool doUnmountSdCard) {
|
||||
if (doUnmountSdCard) {
|
||||
if (not blocking) {
|
||||
sif::warning << "SdCardManager::switchOffSdCard: Two-step command but manager is"
|
||||
@ -147,17 +142,17 @@ ReturnValue_t SdCardManager::switchOffSdCard(sd::SdCard sdCard, bool doUnmountSd
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (sdCard == sd::SdCard::SLOT_0) {
|
||||
if (active.first == sd::SdState::OFF) {
|
||||
if (sdStates.first == sd::SdState::OFF) {
|
||||
return ALREADY_OFF;
|
||||
}
|
||||
} else if (sdCard == sd::SdCard::SLOT_1) {
|
||||
if (active.second == sd::SdState::OFF) {
|
||||
if (sdStates.second == sd::SdState::OFF) {
|
||||
return ALREADY_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
if (doUnmountSdCard) {
|
||||
result = unmountSdCard(sdCard);
|
||||
ReturnValue_t result = unmountSdCard(sdCard);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
@ -189,7 +184,7 @@ ReturnValue_t SdCardManager::setSdCardState(sd::SdCard sdCard, bool on) {
|
||||
command << "q7hw sd set " << sdstring << " " << statestring;
|
||||
cmdExecutor.load(command.str(), blocking, printCmdOutput);
|
||||
ReturnValue_t result = cmdExecutor.execute();
|
||||
if (blocking and result != returnvalue::OK) {
|
||||
if (result != returnvalue::OK) {
|
||||
utility::handleSystemError(cmdExecutor.getLastError(), "SdCardManager::setSdCardState");
|
||||
}
|
||||
return result;
|
||||
@ -204,6 +199,7 @@ ReturnValue_t SdCardManager::getSdCardsStatus(SdStatePair& sdStates) {
|
||||
ReturnValue_t SdCardManager::mountSdCard(sd::SdCard sdCard) {
|
||||
using namespace std;
|
||||
if (cmdExecutor.getCurrentState() == CommandExecutor::States::PENDING) {
|
||||
sif::warning << "SdCardManager::mountSdCard: Command still pending" << std::endl;
|
||||
return CommandExecutor::COMMAND_PENDING;
|
||||
}
|
||||
if (sdCard == sd::SdCard::BOTH) {
|
||||
|
@ -114,8 +114,7 @@ class SdCardManager : public SystemObject, public SdCardMountedIF {
|
||||
* @return - returnvalue::OK on success, ALREADY_ON if it is already on,
|
||||
* SYSTEM_CALL_ERROR on system error
|
||||
*/
|
||||
ReturnValue_t switchOffSdCard(sd::SdCard sdCard, bool doUnmountSdCard = true,
|
||||
SdStatePair* statusPair = nullptr);
|
||||
ReturnValue_t switchOffSdCard(sd::SdCard sdCard, SdStatePair& sdStates, bool doUnmountSdCard);
|
||||
|
||||
/**
|
||||
* Get the state of the SD cards. If the state file does not exist, this function will
|
||||
|
@ -1,8 +1,9 @@
|
||||
#include "ObjectFactory.h"
|
||||
#include "objectFactory.h"
|
||||
|
||||
#include <fsfw/devicehandlers/HealthDevice.h>
|
||||
#include <fsfw/subsystem/Subsystem.h>
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
#include <fsfw_hal/linux/uio/UioMapper.h>
|
||||
#include <linux/acs/AcsBoardPolling.h>
|
||||
#include <linux/acs/GpsHyperionLinuxController.h>
|
||||
#include <linux/acs/ImtqPollingTask.h>
|
||||
@ -32,6 +33,9 @@
|
||||
#include <mission/system/objects/CamSwitcher.h>
|
||||
#include <mission/system/tcs/TmpDevFdir.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "bsp_q7s/boardtest/Q7STestTask.h"
|
||||
#include "bsp_q7s/callbacks/gnssCallback.h"
|
||||
@ -100,6 +104,7 @@
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "bsp_q7s/core/defs.h"
|
||||
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
|
||||
#include "fsfw/tmtcpacket/pus/tm.h"
|
||||
#include "fsfw/tmtcservices/CommandingServiceBase.h"
|
||||
@ -130,6 +135,11 @@ ResetArgs RESET_ARGS_GNSS;
|
||||
std::atomic_bool LINK_STATE = CcsdsIpCoreHandler::LINK_DOWN;
|
||||
std::atomic_bool PTME_LOCKED = false;
|
||||
std::atomic_uint16_t I2C_FATAL_ERRORS = 0;
|
||||
uint8_t core::FW_VERSION_MAJOR = 0;
|
||||
uint8_t core::FW_VERSION_MINOR = 0;
|
||||
uint8_t core::FW_VERSION_REVISION = 0;
|
||||
bool core::FW_VERSION_HAS_SHA = false;
|
||||
char core::FW_VERSION_GIT_SHA[4] = {};
|
||||
|
||||
void Factory::setStaticFrameworkObjectIds() {
|
||||
PusServiceBase::PUS_DISTRIBUTOR = objects::PUS_PACKET_DISTRIBUTOR;
|
||||
@ -151,28 +161,23 @@ void Factory::setStaticFrameworkObjectIds() {
|
||||
|
||||
void ObjectFactory::setStatics() { Factory::setStaticFrameworkObjectIds(); }
|
||||
|
||||
void ObjectFactory::createTmpComponents() {
|
||||
std::vector<std::pair<object_id_t, address_t>> tmpDevIds = {{
|
||||
{objects::TMP1075_HANDLER_TCS_0, addresses::TMP1075_TCS_0},
|
||||
{objects::TMP1075_HANDLER_TCS_1, addresses::TMP1075_TCS_1},
|
||||
{objects::TMP1075_HANDLER_PLPCDU_0, addresses::TMP1075_PLPCDU_0},
|
||||
// damaged
|
||||
// {objects::TMP1075_HANDLER_PLPCDU_1, addresses::TMP1075_PLPCDU_1},
|
||||
{objects::TMP1075_HANDLER_IF_BOARD, addresses::TMP1075_IF_BOARD},
|
||||
}};
|
||||
void ObjectFactory::createTmpComponents(
|
||||
std::vector<std::pair<object_id_t, address_t>> tmpDevsToAdd) {
|
||||
const char* tmpI2cDev = q7s::I2C_PS_EIVE;
|
||||
if (core::FW_VERSION_MAJOR == 4) {
|
||||
tmpI2cDev = q7s::I2C_PL_EIVE;
|
||||
} else if (core::FW_VERSION_MAJOR >= 5) {
|
||||
tmpI2cDev = q7s::I2C_Q7_EIVE;
|
||||
}
|
||||
std::vector<I2cCookie*> tmpDevCookies;
|
||||
|
||||
for (size_t idx = 0; idx < tmpDevIds.size(); idx++) {
|
||||
for (size_t idx = 0; idx < tmpDevsToAdd.size(); idx++) {
|
||||
tmpDevCookies.push_back(
|
||||
new I2cCookie(tmpDevIds[idx].second, TMP1075::MAX_REPLY_LENGTH, q7s::I2C_PS_EIVE));
|
||||
new I2cCookie(tmpDevsToAdd[idx].second, TMP1075::MAX_REPLY_LENGTH, tmpI2cDev));
|
||||
auto* tmpDevHandler =
|
||||
new Tmp1075Handler(tmpDevIds[idx].first, objects::I2C_COM_IF, tmpDevCookies[idx]);
|
||||
tmpDevHandler->setCustomFdir(new TmpDevFdir(tmpDevIds[idx].first));
|
||||
new Tmp1075Handler(tmpDevsToAdd[idx].first, objects::I2C_COM_IF, tmpDevCookies[idx]);
|
||||
tmpDevHandler->setCustomFdir(new TmpDevFdir(tmpDevsToAdd[idx].first));
|
||||
tmpDevHandler->connectModeTreeParent(satsystem::tcs::SUBSYSTEM);
|
||||
// TODO: Remove this after TCS subsystem was added
|
||||
// These devices are connected to the 3V3 stack and should be powered permanently. Therefore,
|
||||
// we set them to normal mode immediately here.
|
||||
tmpDevHandler->setModeNormal();
|
||||
}
|
||||
}
|
||||
|
||||
@ -244,7 +249,7 @@ ReturnValue_t ObjectFactory::createRadSensorComponent(LinuxLibgpioIF* gpioComIF,
|
||||
createRadSensorChipSelect(gpioComIF);
|
||||
|
||||
SpiCookie* spiCookieRadSensor =
|
||||
new SpiCookie(addresses::RAD_SENSOR, gpioIds::CS_RAD_SENSOR, RAD_SENSOR::READ_SIZE,
|
||||
new SpiCookie(addresses::RAD_SENSOR, gpioIds::CS_RAD_SENSOR, radSens::READ_SIZE,
|
||||
spi::DEFAULT_MAX_1227_MODE, spi::DEFAULT_MAX_1227_SPEED);
|
||||
spiCookieRadSensor->setMutexParams(MutexIF::TimeoutType::WAITING, spi::RAD_SENSOR_CS_TIMEOUT);
|
||||
auto radSensor = new RadiationSensorHandler(objects::RAD_SENSOR, objects::SPI_MAIN_COM_IF,
|
||||
@ -731,20 +736,12 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(CcsdsComponentArgs& args) {
|
||||
// GPIO definitions of signals connected to the virtual channel interfaces of the PTME IP Core
|
||||
GpioCookie* gpioCookiePtmeIp = new GpioCookie;
|
||||
GpiodRegularByLineName* gpio = nullptr;
|
||||
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC0, "PAPB VC0");
|
||||
gpioCookiePtmeIp->addGpio(gpioIds::VC0_PAPB_BUSY, gpio);
|
||||
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC0, "PAPB VC0");
|
||||
gpioCookiePtmeIp->addGpio(gpioIds::VC0_PAPB_EMPTY, gpio);
|
||||
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC1, "PAPB VC1");
|
||||
gpioCookiePtmeIp->addGpio(gpioIds::VC1_PAPB_BUSY, gpio);
|
||||
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC1, "PAPB VC1");
|
||||
gpioCookiePtmeIp->addGpio(gpioIds::VC1_PAPB_EMPTY, gpio);
|
||||
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC2, "PAPB VC2");
|
||||
gpioCookiePtmeIp->addGpio(gpioIds::VC2_PAPB_BUSY, gpio);
|
||||
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC2, "PAPB VC2");
|
||||
gpioCookiePtmeIp->addGpio(gpioIds::VC2_PAPB_EMPTY, gpio);
|
||||
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC3, "PAPB VC3");
|
||||
gpioCookiePtmeIp->addGpio(gpioIds::VC3_PAPB_BUSY, gpio);
|
||||
gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC3, "PAPB VC3");
|
||||
gpioCookiePtmeIp->addGpio(gpioIds::VC3_PAPB_EMPTY, gpio);
|
||||
gpio = new GpiodRegularByLineName(q7s::gpioNames::PTME_RESETN, "PTME RESETN",
|
||||
@ -753,19 +750,14 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(CcsdsComponentArgs& args) {
|
||||
gpioChecker(args.gpioComIF.addGpios(gpioCookiePtmeIp), "PTME PAPB VCs");
|
||||
|
||||
// Creating virtual channel interfaces
|
||||
VirtualChannelIF* vc0 =
|
||||
new PapbVcInterface(&args.gpioComIF, gpioIds::VC0_PAPB_BUSY, gpioIds::VC0_PAPB_EMPTY,
|
||||
q7s::UIO_PTME, q7s::uiomapids::PTME_VC0);
|
||||
VirtualChannelIF* vc1 =
|
||||
new PapbVcInterface(&args.gpioComIF, gpioIds::VC1_PAPB_BUSY, gpioIds::VC1_PAPB_EMPTY,
|
||||
q7s::UIO_PTME, q7s::uiomapids::PTME_VC1);
|
||||
VirtualChannelIF* vc2 =
|
||||
new PapbVcInterface(&args.gpioComIF, gpioIds::VC2_PAPB_BUSY, gpioIds::VC2_PAPB_EMPTY,
|
||||
q7s::UIO_PTME, q7s::uiomapids::PTME_VC2);
|
||||
VirtualChannelIF* vc3 =
|
||||
new PapbVcInterface(&args.gpioComIF, gpioIds::VC3_PAPB_BUSY, gpioIds::VC3_PAPB_EMPTY,
|
||||
q7s::UIO_PTME, q7s::uiomapids::PTME_VC3);
|
||||
|
||||
VirtualChannelIF* vc0 = new PapbVcInterface(&args.gpioComIF, gpioIds::VC0_PAPB_EMPTY,
|
||||
q7s::UIO_PTME, q7s::uiomapids::PTME_VC0);
|
||||
VirtualChannelIF* vc1 = new PapbVcInterface(&args.gpioComIF, gpioIds::VC1_PAPB_EMPTY,
|
||||
q7s::UIO_PTME, q7s::uiomapids::PTME_VC1);
|
||||
VirtualChannelIF* vc2 = new PapbVcInterface(&args.gpioComIF, gpioIds::VC2_PAPB_EMPTY,
|
||||
q7s::UIO_PTME, q7s::uiomapids::PTME_VC2);
|
||||
VirtualChannelIF* vc3 = new PapbVcInterface(&args.gpioComIF, gpioIds::VC3_PAPB_EMPTY,
|
||||
q7s::UIO_PTME, q7s::uiomapids::PTME_VC3);
|
||||
// Creating ptme object and adding virtual channel interfaces
|
||||
Ptme* ptme = new Ptme(objects::PTME);
|
||||
ptme->addVcInterface(ccsds::VC0, vc0);
|
||||
@ -945,16 +937,7 @@ void ObjectFactory::createStrComponents(PowerSwitchIF* pwrSwitcher) {
|
||||
starTrackerCookie->setNoFixedSizeReply();
|
||||
StrComHandler* strComIF = new StrComHandler(objects::STR_COM_IF);
|
||||
|
||||
const char* paramJsonFile = nullptr;
|
||||
#ifdef EGSE
|
||||
paramJsonFile = "/home/pi/arcsec/json/flight-config.json";
|
||||
#else
|
||||
#if OBSW_STAR_TRACKER_GROUND_CONFIG == 1
|
||||
paramJsonFile = "/mnt/sd0/startracker/ground-config.json";
|
||||
#else
|
||||
paramJsonFile = "/mnt/sd0/startracker/flight-config.json";
|
||||
#endif
|
||||
#endif
|
||||
const char* paramJsonFile = "/mnt/sd0/startracker/flight-config.json";
|
||||
if (paramJsonFile == nullptr) {
|
||||
sif::error << "No valid Star Tracker parameter JSON file" << std::endl;
|
||||
}
|
||||
@ -967,12 +950,13 @@ void ObjectFactory::createStrComponents(PowerSwitchIF* pwrSwitcher) {
|
||||
starTracker->setCustomFdir(strFdir);
|
||||
}
|
||||
|
||||
void ObjectFactory::createImtqComponents(PowerSwitchIF* pwrSwitcher, bool enableHkSets) {
|
||||
void ObjectFactory::createImtqComponents(PowerSwitchIF* pwrSwitcher, bool enableHkSets,
|
||||
const char* i2cDev) {
|
||||
auto* imtqAssy = new ImtqAssembly(objects::IMTQ_ASSY);
|
||||
imtqAssy->connectModeTreeParent(satsystem::acs::ACS_SUBSYSTEM);
|
||||
|
||||
new ImtqPollingTask(objects::IMTQ_POLLING, I2C_FATAL_ERRORS);
|
||||
I2cCookie* imtqI2cCookie = new I2cCookie(addresses::IMTQ, imtq::MAX_REPLY_SIZE, q7s::I2C_PL_EIVE);
|
||||
I2cCookie* imtqI2cCookie = new I2cCookie(addresses::IMTQ, imtq::MAX_REPLY_SIZE, i2cDev);
|
||||
auto imtqHandler = new ImtqHandler(objects::IMTQ_HANDLER, objects::IMTQ_POLLING, imtqI2cCookie,
|
||||
power::Switches::PDU1_CH3_MGT_5V, enableHkSets);
|
||||
imtqHandler->enableThermalModule(ThermalStateCfg());
|
||||
@ -988,8 +972,8 @@ void ObjectFactory::createImtqComponents(PowerSwitchIF* pwrSwitcher, bool enable
|
||||
#endif
|
||||
}
|
||||
|
||||
void ObjectFactory::createBpxBatteryComponent(bool enableHkSets) {
|
||||
I2cCookie* bpxI2cCookie = new I2cCookie(addresses::BPX_BATTERY, 100, q7s::I2C_PL_EIVE);
|
||||
void ObjectFactory::createBpxBatteryComponent(bool enableHkSets, const char* i2cDev) {
|
||||
I2cCookie* bpxI2cCookie = new I2cCookie(addresses::BPX_BATTERY, 100, i2cDev);
|
||||
BpxBatteryHandler* bpxHandler = new BpxBatteryHandler(
|
||||
objects::BPX_BATT_HANDLER, objects::I2C_COM_IF, bpxI2cCookie, enableHkSets);
|
||||
bpxHandler->setStartUpImmediately();
|
||||
@ -1045,3 +1029,32 @@ void ObjectFactory::createPlI2cResetGpio(LinuxLibgpioIF* gpioIF) {
|
||||
gpioIF->pullHigh(gpioIds::PL_I2C_ARESETN);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t ObjectFactory::readFirmwareVersion() {
|
||||
uint32_t* mappedSysRomAddr = nullptr;
|
||||
// The SYS ROM FPGA block is only available in those versions.
|
||||
if (not(common::OBSW_VERSION_MAJOR >= 6) or (common::OBSW_VERSION_MAJOR == 4)) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
// This has to come before the version announce because it might be required for retrieving
|
||||
// the firmware version.
|
||||
UioMapper sysRomMapper(q7s::UIO_SYS_ROM);
|
||||
ReturnValue_t result =
|
||||
sysRomMapper.getMappedAdress(&mappedSysRomAddr, UioMapper::Permissions::READ_ONLY);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::error << "Getting mapped SYS ROM UIO address failed" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (mappedSysRomAddr != nullptr) {
|
||||
uint32_t firstEntry = *(reinterpret_cast<uint32_t*>(mappedSysRomAddr));
|
||||
uint32_t secondEntry = *(reinterpret_cast<uint32_t*>(mappedSysRomAddr) + 1);
|
||||
core::FW_VERSION_MAJOR = (firstEntry >> 24) & 0xff;
|
||||
core::FW_VERSION_MINOR = (firstEntry >> 16) & 0xff;
|
||||
core::FW_VERSION_REVISION = (firstEntry >> 8) & 0xff;
|
||||
bool hasGitSha = (firstEntry & 0x0b1);
|
||||
if (hasGitSha) {
|
||||
std::memcpy(core::FW_VERSION_GIT_SHA, &secondEntry, 4);
|
||||
}
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
@ -58,7 +58,7 @@ void createPcduComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchIF** pwrSwitcher
|
||||
bool enableHkSets);
|
||||
void createPlPcduComponents(LinuxLibgpioIF* gpioComIF, SpiComIF* spiComIF,
|
||||
PowerSwitchIF* pwrSwitcher, Stack5VHandler& stackHandler);
|
||||
void createTmpComponents();
|
||||
void createTmpComponents(std::vector<std::pair<object_id_t, address_t>> tmpDevsToAdd);
|
||||
void createRadSensorChipSelect(LinuxLibgpioIF* gpioIF);
|
||||
ReturnValue_t createRadSensorComponent(LinuxLibgpioIF* gpioComIF, Stack5VHandler& handler);
|
||||
void createAcsBoardGpios(GpioCookie& cookie);
|
||||
@ -67,14 +67,15 @@ void createAcsBoardComponents(SpiComIF& spiComIF, LinuxLibgpioIF* gpioComIF, Ser
|
||||
adis1650x::Type adisType);
|
||||
void createHeaterComponents(GpioIF* gpioIF, PowerSwitchIF* pwrSwitcher, HealthTableIF* healthTable,
|
||||
HeaterHandler*& heaterHandler);
|
||||
void createImtqComponents(PowerSwitchIF* pwrSwitcher, bool enableHkSets);
|
||||
void createBpxBatteryComponent(bool enableHkSets);
|
||||
void createImtqComponents(PowerSwitchIF* pwrSwitcher, bool enableHkSets, const char* i2cDev);
|
||||
void createBpxBatteryComponent(bool enableHkSets, const char* i2cDev);
|
||||
void createStrComponents(PowerSwitchIF* pwrSwitcher);
|
||||
void createSolarArrayDeploymentComponents(PowerSwitchIF& pwrSwitcher, GpioIF& gpioIF);
|
||||
void createSyrlinksComponents(PowerSwitchIF* pwrSwitcher);
|
||||
void createPayloadComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchIF& pwrSwitcher);
|
||||
void createReactionWheelComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchIF* pwrSwitcher);
|
||||
ReturnValue_t createCcsdsComponents(CcsdsComponentArgs& args);
|
||||
ReturnValue_t readFirmwareVersion();
|
||||
void createMiscComponents();
|
||||
|
||||
void createTestComponents(LinuxLibgpioIF* gpioComIF);
|
@ -11,13 +11,13 @@
|
||||
#include "OBSWConfig.h"
|
||||
#include "bsp_q7s/core/WatchdogHandler.h"
|
||||
#include "commonConfig.h"
|
||||
#include "core/scheduling.h"
|
||||
#include "fsfw/tasks/TaskFactory.h"
|
||||
#include "fsfw/version.h"
|
||||
#include "mission/acs/defs.h"
|
||||
#include "mission/com/defs.h"
|
||||
#include "mission/system/systemTree.h"
|
||||
#include "q7sConfig.h"
|
||||
#include "scheduling.h"
|
||||
#include "watchdog/definitions.h"
|
||||
|
||||
static constexpr int OBSW_ALREADY_RUNNING = -2;
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include <vector>
|
||||
|
||||
#include "OBSWConfig.h"
|
||||
#include "bsp_q7s/core/ObjectFactory.h"
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
#include "fsfw/objectmanager/ObjectManagerIF.h"
|
||||
#include "fsfw/platform.h"
|
||||
@ -21,6 +20,8 @@
|
||||
#include "mission/pollingSeqTables.h"
|
||||
#include "mission/scheduling.h"
|
||||
#include "mission/utility/InitMission.h"
|
||||
#include "objectFactory.h"
|
||||
#include "q7sConfig.h"
|
||||
|
||||
/* This is configured for linux without CR */
|
||||
#ifdef PLATFORM_UNIX
|
||||
@ -531,7 +532,15 @@ void scheduling::createPstTasks(TaskFactory& factory, TaskDeadlineMissedFunction
|
||||
FixedTimeslotTaskIF* i2cPst =
|
||||
factory.createFixedTimeslotTask("I2C_PS_PST", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.6,
|
||||
missedDeadlineFunc, &RR_SCHEDULING);
|
||||
result = pst::pstI2cProcessingSystem(i2cPst);
|
||||
pst::TmpSchedConfig tmpSchedConf;
|
||||
#if OBSW_Q7S_EM == 1
|
||||
tmpSchedConf.scheduleTmpDev0 = true;
|
||||
tmpSchedConf.scheduleTmpDev1 = true;
|
||||
tmpSchedConf.schedulePlPcduDev0 = true;
|
||||
tmpSchedConf.schedulePlPcduDev1 = true;
|
||||
tmpSchedConf.scheduleIfBoardDev = true;
|
||||
#endif
|
||||
result = pst::pstI2c(tmpSchedConf, i2cPst);
|
||||
if (result != returnvalue::OK) {
|
||||
if (result == FixedTimeslotTaskIF::SLOT_LIST_EMPTY) {
|
||||
sif::warning << "scheduling::initTasks: I2C PST is empty" << std::endl;
|
@ -129,7 +129,7 @@ ReturnValue_t Xadc::readValFromFile(const char* filename, T& val) {
|
||||
sif::warning << "Xadc::readValFromFile: Failed to open file " << filename << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
char valstring[MAX_STR_LENGTH] = "";
|
||||
char valstring[MAX_STR_LENGTH]{};
|
||||
char* returnVal = fgets(valstring, MAX_STR_LENGTH, fp);
|
||||
if (returnVal == nullptr) {
|
||||
sif::warning << "Xadc::readValFromFile: Failed to read string from file " << filename
|
||||
@ -139,6 +139,11 @@ ReturnValue_t Xadc::readValFromFile(const char* filename, T& val) {
|
||||
}
|
||||
std::istringstream valSstream(valstring);
|
||||
valSstream >> val;
|
||||
if (valSstream.bad()) {
|
||||
sif::warning << "Xadc: Conversion of value to target type failed" << std::endl;
|
||||
fclose(fp);
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
fclose(fp);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
@ -96,13 +96,9 @@ enum gpioId_t {
|
||||
|
||||
SPI_MUX,
|
||||
VC0_PAPB_EMPTY,
|
||||
VC0_PAPB_BUSY,
|
||||
VC1_PAPB_EMPTY,
|
||||
VC1_PAPB_BUSY,
|
||||
VC2_PAPB_EMPTY,
|
||||
VC2_PAPB_BUSY,
|
||||
VC3_PAPB_EMPTY,
|
||||
VC3_PAPB_BUSY,
|
||||
PTME_RESETN,
|
||||
|
||||
PDEC_RESET,
|
||||
|
@ -19,6 +19,7 @@ target_sources(
|
||||
GpsCtrlDummy.cpp
|
||||
GyroAdisDummy.cpp
|
||||
GyroL3GD20Dummy.cpp
|
||||
RadSensorDummy.cpp
|
||||
MgmLIS3MDLDummy.cpp
|
||||
PlPcduDummy.cpp
|
||||
ExecutableComIfDummy.cpp
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "CoreControllerDummy.h"
|
||||
|
||||
#include <bsp_q7s/core/CoreDefinitions.h>
|
||||
#include <bsp_q7s/core/defs.h>
|
||||
#include <objects/systemObjectList.h>
|
||||
|
||||
#include <cmath>
|
||||
|
@ -7,15 +7,21 @@ using namespace returnvalue;
|
||||
Max31865Dummy::Max31865Dummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
|
||||
: DeviceHandlerBase(objectId, comif, comCookie), set(this, EiveMax31855::EXCHANGE_SET_ID) {}
|
||||
void Max31865Dummy::doStartUp() { setMode(MODE_ON); }
|
||||
void Max31865Dummy::doShutDown() { setMode(_MODE_POWER_DOWN); }
|
||||
void Max31865Dummy::doShutDown() {
|
||||
PoolReadGuard pg(&set);
|
||||
set.setValidity(false, true);
|
||||
setMode(MODE_OFF);
|
||||
}
|
||||
ReturnValue_t Max31865Dummy::buildNormalDeviceCommand(DeviceCommandId_t *id) {
|
||||
return NOTHING_TO_SEND;
|
||||
}
|
||||
ReturnValue_t Max31865Dummy::buildTransitionDeviceCommand(DeviceCommandId_t *id) { return OK; }
|
||||
ReturnValue_t Max31865Dummy::buildTransitionDeviceCommand(DeviceCommandId_t *id) {
|
||||
return NOTHING_TO_SEND;
|
||||
}
|
||||
ReturnValue_t Max31865Dummy::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
|
||||
const uint8_t *commandData,
|
||||
size_t commandDataLen) {
|
||||
return 0;
|
||||
return NOTHING_TO_SEND;
|
||||
}
|
||||
ReturnValue_t Max31865Dummy::scanForReply(const uint8_t *start, size_t len,
|
||||
DeviceCommandId_t *foundId, size_t *foundLen) {
|
||||
|
@ -7,7 +7,7 @@ PlPcduDummy::PlPcduDummy(object_id_t objectId, object_id_t comif, CookieIF *comC
|
||||
|
||||
PlPcduDummy::~PlPcduDummy() {}
|
||||
|
||||
void PlPcduDummy::doStartUp() { setMode(MODE_NORMAL); }
|
||||
void PlPcduDummy::doStartUp() { setMode(MODE_ON); }
|
||||
|
||||
void PlPcduDummy::doShutDown() { setMode(MODE_OFF); }
|
||||
|
||||
|
55
dummies/RadSensorDummy.cpp
Normal file
55
dummies/RadSensorDummy.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#include "RadSensorDummy.h"
|
||||
|
||||
RadSensorDummy::RadSensorDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
|
||||
: DeviceHandlerBase(objectId, comif, comCookie), sensorSet(this) {}
|
||||
|
||||
RadSensorDummy::~RadSensorDummy() {}
|
||||
|
||||
void RadSensorDummy::doStartUp() { setMode(MODE_ON); }
|
||||
|
||||
void RadSensorDummy::doShutDown() { setMode(MODE_OFF); }
|
||||
|
||||
ReturnValue_t RadSensorDummy::buildNormalDeviceCommand(DeviceCommandId_t *id) {
|
||||
return NOTHING_TO_SEND;
|
||||
}
|
||||
|
||||
ReturnValue_t RadSensorDummy::buildTransitionDeviceCommand(DeviceCommandId_t *id) {
|
||||
return NOTHING_TO_SEND;
|
||||
}
|
||||
|
||||
ReturnValue_t RadSensorDummy::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
|
||||
const uint8_t *commandData,
|
||||
size_t commandDataLen) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t RadSensorDummy::scanForReply(const uint8_t *start, size_t len,
|
||||
DeviceCommandId_t *foundId, size_t *foundLen) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t RadSensorDummy::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void RadSensorDummy::fillCommandAndReplyMap() {}
|
||||
|
||||
uint32_t RadSensorDummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return 500; }
|
||||
|
||||
ReturnValue_t RadSensorDummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) {
|
||||
localDataPoolMap.emplace(radSens::TEMPERATURE_C, new PoolEntry<float>({0.0}));
|
||||
localDataPoolMap.emplace(radSens::AIN0, new PoolEntry<uint16_t>({0}));
|
||||
localDataPoolMap.emplace(radSens::AIN1, new PoolEntry<uint16_t>({0}));
|
||||
localDataPoolMap.emplace(radSens::AIN4, new PoolEntry<uint16_t>({0}));
|
||||
localDataPoolMap.emplace(radSens::AIN5, new PoolEntry<uint16_t>({0}));
|
||||
localDataPoolMap.emplace(radSens::AIN6, new PoolEntry<uint16_t>({0}));
|
||||
localDataPoolMap.emplace(radSens::AIN7, new PoolEntry<uint16_t>({0}));
|
||||
poolManager.subscribeForRegularPeriodicPacket(
|
||||
subdp::RegularHkPeriodicParams(sensorSet.getSid(), false, 20.0));
|
||||
return returnvalue::OK;
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
LocalPoolDataSetBase *RadSensorDummy::getDataSetHandle(sid_t sid) { return &sensorSet; }
|
35
dummies/RadSensorDummy.h
Normal file
35
dummies/RadSensorDummy.h
Normal file
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
||||
|
||||
#include "mission/payload/radSensorDefinitions.h"
|
||||
|
||||
class RadSensorDummy : public DeviceHandlerBase {
|
||||
public:
|
||||
static const DeviceCommandId_t SIMPLE_COMMAND = 1;
|
||||
static const DeviceCommandId_t PERIODIC_REPLY = 2;
|
||||
|
||||
static const uint8_t SIMPLE_COMMAND_DATA = 1;
|
||||
static const uint8_t PERIODIC_REPLY_DATA = 2;
|
||||
|
||||
RadSensorDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie);
|
||||
virtual ~RadSensorDummy();
|
||||
|
||||
protected:
|
||||
radSens::RadSensorDataset sensorSet;
|
||||
|
||||
void doStartUp() override;
|
||||
void doShutDown() override;
|
||||
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;
|
||||
ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t *id) override;
|
||||
ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t *commandData,
|
||||
size_t commandDataLen) override;
|
||||
ReturnValue_t scanForReply(const uint8_t *start, size_t len, DeviceCommandId_t *foundId,
|
||||
size_t *foundLen) override;
|
||||
ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) override;
|
||||
void fillCommandAndReplyMap() override;
|
||||
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
|
||||
ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) override;
|
||||
LocalPoolDataSetBase *getDataSetHandle(sid_t sid) override;
|
||||
};
|
@ -5,7 +5,7 @@ SusDummy::SusDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
|
||||
|
||||
SusDummy::~SusDummy() {}
|
||||
|
||||
void SusDummy::doStartUp() { setMode(MODE_NORMAL); }
|
||||
void SusDummy::doStartUp() { setMode(MODE_ON); }
|
||||
|
||||
void SusDummy::doShutDown() { setMode(MODE_OFF); }
|
||||
|
||||
|
@ -7,9 +7,9 @@
|
||||
#include <cstdlib>
|
||||
#include <utility>
|
||||
|
||||
TemperatureSensorInserter::TemperatureSensorInserter(object_id_t objectId,
|
||||
Max31865DummyMap tempSensorDummies_,
|
||||
Tmp1075DummyMap tempTmpSensorDummies_)
|
||||
TemperatureSensorInserter::TemperatureSensorInserter(
|
||||
object_id_t objectId, Max31865DummyMap tempSensorDummies_,
|
||||
std::optional<Tmp1075DummyMap> tempTmpSensorDummies_)
|
||||
: SystemObject(objectId),
|
||||
max31865DummyMap(std::move(tempSensorDummies_)),
|
||||
tmp1075DummyMap(std::move(tempTmpSensorDummies_)) {}
|
||||
@ -25,8 +25,10 @@ ReturnValue_t TemperatureSensorInserter::performOperation(uint8_t opCode) {
|
||||
for (auto& rtdDummy : max31865DummyMap) {
|
||||
rtdDummy.second->setTemperature(10, true);
|
||||
}
|
||||
for (auto& tmpDummy : tmp1075DummyMap) {
|
||||
tmpDummy.second->setTemperature(10, true);
|
||||
if (tmp1075DummyMap.has_value()) {
|
||||
for (auto& tmpDummy : tmp1075DummyMap.value()) {
|
||||
tmpDummy.second->setTemperature(10, true);
|
||||
}
|
||||
}
|
||||
tempsWereInitialized = true;
|
||||
}
|
||||
@ -124,6 +126,21 @@ ReturnValue_t TemperatureSensorInserter::performOperation(uint8_t opCode) {
|
||||
sif::debug << "Setting CAM temperature back to normal" << std::endl;
|
||||
max31865DummyMap[objects::RTD_2_IC5_4K_CAMERA]->setTemperature(0, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (TestCase::COLD_PLOC_STAYS_COLD): {
|
||||
if (cycles == 15) {
|
||||
sif::debug << "Setting cold PLOC temperature" << std::endl;
|
||||
max31865DummyMap[objects::RTD_0_IC3_PLOC_HEATSPREADER]->setTemperature(-40, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case (TestCase::COLD_CAMERA_STAYS_COLD): {
|
||||
if (cycles == 15) {
|
||||
sif::debug << "Setting cold PLOC temperature" << std::endl;
|
||||
max31865DummyMap[objects::RTD_2_IC5_4K_CAMERA]->setTemperature(-40, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
cycles++;
|
||||
|
@ -12,7 +12,7 @@ class TemperatureSensorInserter : public ExecutableObjectIF, public SystemObject
|
||||
using Max31865DummyMap = std::map<object_id_t, Max31865Dummy*>;
|
||||
using Tmp1075DummyMap = std::map<object_id_t, Tmp1075Dummy*>;
|
||||
explicit TemperatureSensorInserter(object_id_t objectId, Max31865DummyMap tempSensorDummies_,
|
||||
Tmp1075DummyMap tempTmpSensorDummies_);
|
||||
std::optional<Tmp1075DummyMap> tempTmpSensorDummies_);
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
ReturnValue_t initializeAfterTaskCreation() override;
|
||||
@ -22,7 +22,7 @@ class TemperatureSensorInserter : public ExecutableObjectIF, public SystemObject
|
||||
|
||||
private:
|
||||
Max31865DummyMap max31865DummyMap;
|
||||
Tmp1075DummyMap tmp1075DummyMap;
|
||||
std::optional<Tmp1075DummyMap> tmp1075DummyMap;
|
||||
|
||||
enum TestCase {
|
||||
NONE = 0,
|
||||
@ -33,6 +33,8 @@ class TemperatureSensorInserter : public ExecutableObjectIF, public SystemObject
|
||||
COLD_STR_CONSECUTIVE = 5,
|
||||
COLD_CAMERA = 6,
|
||||
COLD_PLOC_CONSECUTIVE = 7,
|
||||
COLD_PLOC_STAYS_COLD = 8,
|
||||
COLD_CAMERA_STAYS_COLD = 9
|
||||
};
|
||||
int iteration = 0;
|
||||
uint32_t cycles = 0;
|
||||
|
@ -8,35 +8,57 @@ using namespace returnvalue;
|
||||
Tmp1075Dummy::Tmp1075Dummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
|
||||
: DeviceHandlerBase(objectId, comif, comCookie), set(this) {}
|
||||
|
||||
void Tmp1075Dummy::doStartUp() { setMode(MODE_NORMAL); }
|
||||
void Tmp1075Dummy::doShutDown() { setMode(MODE_OFF); }
|
||||
void Tmp1075Dummy::doStartUp() { setMode(MODE_ON); }
|
||||
void Tmp1075Dummy::doShutDown() {
|
||||
PoolReadGuard pg(&set);
|
||||
set.setValidity(false, true);
|
||||
setMode(MODE_OFF);
|
||||
}
|
||||
|
||||
ReturnValue_t Tmp1075Dummy::buildNormalDeviceCommand(DeviceCommandId_t *id) {
|
||||
return NOTHING_TO_SEND;
|
||||
}
|
||||
ReturnValue_t Tmp1075Dummy::buildTransitionDeviceCommand(DeviceCommandId_t *id) { return OK; }
|
||||
|
||||
ReturnValue_t Tmp1075Dummy::buildTransitionDeviceCommand(DeviceCommandId_t *id) {
|
||||
return NOTHING_TO_SEND;
|
||||
}
|
||||
|
||||
ReturnValue_t Tmp1075Dummy::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
|
||||
const uint8_t *commandData,
|
||||
size_t commandDataLen) {
|
||||
return 0;
|
||||
return NOTHING_TO_SEND;
|
||||
}
|
||||
|
||||
ReturnValue_t Tmp1075Dummy::scanForReply(const uint8_t *start, size_t len,
|
||||
DeviceCommandId_t *foundId, size_t *foundLen) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ReturnValue_t Tmp1075Dummy::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Tmp1075Dummy::setTemperature(float temperature, bool valid) {
|
||||
PoolReadGuard pg(&set);
|
||||
set.temperatureCelcius.value = temperature;
|
||||
set.setValidity(valid, true);
|
||||
}
|
||||
|
||||
void Tmp1075Dummy::fillCommandAndReplyMap() {}
|
||||
|
||||
uint32_t Tmp1075Dummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return 1000; }
|
||||
|
||||
ReturnValue_t Tmp1075Dummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) {
|
||||
localDataPoolMap.emplace(TMP1075::TEMPERATURE_C_TMP1075, new PoolEntry<float>({10.0}, true));
|
||||
return OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Tmp1075Dummy::setHealth(HealthState health) {
|
||||
if (health == FAULTY or health == PERMANENT_FAULTY) {
|
||||
setMode(_MODE_SHUT_DOWN);
|
||||
}
|
||||
return DeviceHandlerBase::setHealth(health);
|
||||
}
|
||||
|
||||
LocalPoolDataSetBase *Tmp1075Dummy::getDataSetHandle(sid_t sid) { return &set; }
|
||||
|
@ -26,6 +26,7 @@ class Tmp1075Dummy : public DeviceHandlerBase {
|
||||
uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
|
||||
ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) override;
|
||||
ReturnValue_t setHealth(HealthState health) override;
|
||||
|
||||
protected:
|
||||
LocalPoolDataSetBase *getDataSetHandle(sid_t sid) override;
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <dummies/PlPcduDummy.h>
|
||||
#include <dummies/PlocMpsocDummy.h>
|
||||
#include <dummies/PlocSupervisorDummy.h>
|
||||
#include <dummies/RadSensorDummy.h>
|
||||
#include <dummies/RwDummy.h>
|
||||
#include <dummies/SaDeploymentDummy.h>
|
||||
#include <dummies/ScexDummy.h>
|
||||
@ -34,6 +35,7 @@
|
||||
|
||||
#include "TemperatureSensorInserter.h"
|
||||
#include "dummies/Max31865Dummy.h"
|
||||
#include "dummies/SusDummy.h"
|
||||
#include "dummies/Tmp1075Dummy.h"
|
||||
#include "mission/genericFactory.h"
|
||||
#include "mission/system/acs/acsModeTree.h"
|
||||
@ -63,11 +65,14 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
|
||||
rws[3] = new RwDummy(objects::RW4, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
ObjectFactory::createRwAssy(pwrSwitcher, power::Switches::PDU2_CH2_RW_5V, rws, rwIds);
|
||||
new SaDeplDummy(objects::SOLAR_ARRAY_DEPL_HANDLER);
|
||||
auto* strAssy = new StrAssembly(objects::STR_ASSY);
|
||||
strAssy->connectModeTreeParent(satsystem::acs::ACS_SUBSYSTEM);
|
||||
auto* strDummy =
|
||||
new StarTrackerDummy(objects::STAR_TRACKER, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
strDummy->connectModeTreeParent(*strAssy);
|
||||
|
||||
if (cfg.addStrDummy) {
|
||||
auto* strAssy = new StrAssembly(objects::STR_ASSY);
|
||||
strAssy->connectModeTreeParent(satsystem::acs::ACS_SUBSYSTEM);
|
||||
auto* strDummy =
|
||||
new StarTrackerDummy(objects::STAR_TRACKER, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
strDummy->connectModeTreeParent(*strAssy);
|
||||
}
|
||||
if (cfg.addSyrlinksDummies) {
|
||||
auto* syrlinksDummy =
|
||||
new SyrlinksDummy(objects::SYRLINKS_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
@ -191,25 +196,36 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
|
||||
objects::RTD_15_IC18_IMTQ,
|
||||
new Max31865Dummy(objects::RTD_15_IC18_IMTQ, objects::DUMMY_COM_IF, comCookieDummy));
|
||||
|
||||
std::map<object_id_t, Tmp1075Dummy*> tmpSensorDummies;
|
||||
tmpSensorDummies.emplace(
|
||||
objects::TMP1075_HANDLER_TCS_0,
|
||||
new Tmp1075Dummy(objects::TMP1075_HANDLER_TCS_0, objects::DUMMY_COM_IF, comCookieDummy));
|
||||
tmpSensorDummies.emplace(
|
||||
objects::TMP1075_HANDLER_TCS_1,
|
||||
new Tmp1075Dummy(objects::TMP1075_HANDLER_TCS_1, objects::DUMMY_COM_IF, comCookieDummy));
|
||||
tmpSensorDummies.emplace(
|
||||
objects::TMP1075_HANDLER_PLPCDU_0,
|
||||
new Tmp1075Dummy(objects::TMP1075_HANDLER_PLPCDU_0, objects::DUMMY_COM_IF, comCookieDummy));
|
||||
// damaged.
|
||||
// tmpSensorDummies.emplace(
|
||||
// objects::TMP1075_HANDLER_PLPCDU_1,
|
||||
// new Tmp1075Dummy(objects::TMP1075_HANDLER_PLPCDU_1, objects::DUMMY_COM_IF,
|
||||
// comCookieDummy));
|
||||
tmpSensorDummies.emplace(
|
||||
objects::TMP1075_HANDLER_IF_BOARD,
|
||||
new Tmp1075Dummy(objects::TMP1075_HANDLER_IF_BOARD, objects::DUMMY_COM_IF, comCookieDummy));
|
||||
|
||||
std::optional<TemperatureSensorInserter::Tmp1075DummyMap> tmpSensorDummies;
|
||||
if (cfg.addTmpDummies) {
|
||||
TemperatureSensorInserter::Tmp1075DummyMap tmpDummyMap;
|
||||
if (cfg.tmp1075Cfg.addTcsBrd0) {
|
||||
tmpDummyMap.emplace(objects::TMP1075_HANDLER_TCS_0,
|
||||
new Tmp1075Dummy(objects::TMP1075_HANDLER_TCS_0, objects::DUMMY_COM_IF,
|
||||
comCookieDummy));
|
||||
}
|
||||
if (cfg.tmp1075Cfg.addTcsBrd1) {
|
||||
tmpDummyMap.emplace(objects::TMP1075_HANDLER_TCS_1,
|
||||
new Tmp1075Dummy(objects::TMP1075_HANDLER_TCS_1, objects::DUMMY_COM_IF,
|
||||
comCookieDummy));
|
||||
}
|
||||
if (cfg.tmp1075Cfg.addPlPcdu0) {
|
||||
tmpDummyMap.emplace(objects::TMP1075_HANDLER_PLPCDU_0,
|
||||
new Tmp1075Dummy(objects::TMP1075_HANDLER_PLPCDU_0,
|
||||
objects::DUMMY_COM_IF, comCookieDummy));
|
||||
}
|
||||
if (cfg.tmp1075Cfg.addPlPcdu1) {
|
||||
tmpDummyMap.emplace(objects::TMP1075_HANDLER_PLPCDU_1,
|
||||
new Tmp1075Dummy(objects::TMP1075_HANDLER_PLPCDU_1,
|
||||
objects::DUMMY_COM_IF, comCookieDummy));
|
||||
}
|
||||
if (cfg.tmp1075Cfg.addIfBrd) {
|
||||
tmpDummyMap.emplace(objects::TMP1075_HANDLER_IF_BOARD,
|
||||
new Tmp1075Dummy(objects::TMP1075_HANDLER_IF_BOARD,
|
||||
objects::DUMMY_COM_IF, comCookieDummy));
|
||||
}
|
||||
tmpSensorDummies = std::move(tmpDummyMap);
|
||||
}
|
||||
new TemperatureSensorInserter(objects::THERMAL_TEMP_INSERTER, rtdSensorDummies,
|
||||
tmpSensorDummies);
|
||||
TcsBoardAssembly* tcsBoardAssy =
|
||||
@ -217,8 +233,10 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
|
||||
for (auto& rtd : rtdSensorDummies) {
|
||||
rtd.second->connectModeTreeParent(*tcsBoardAssy);
|
||||
}
|
||||
for (auto& tmp : tmpSensorDummies) {
|
||||
tmp.second->connectModeTreeParent(satsystem::tcs::SUBSYSTEM);
|
||||
if (tmpSensorDummies.has_value()) {
|
||||
for (auto& tmp : tmpSensorDummies.value()) {
|
||||
tmp.second->connectModeTreeParent(satsystem::tcs::SUBSYSTEM);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cfg.addCamSwitcherDummy) {
|
||||
@ -226,8 +244,10 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
|
||||
power::Switches::PDU2_CH8_PAYLOAD_CAMERA);
|
||||
camSwitcher->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
|
||||
}
|
||||
auto* scexDummy = new ScexDummy(objects::SCEX, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
scexDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
|
||||
if (cfg.addScexDummy) {
|
||||
auto* scexDummy = new ScexDummy(objects::SCEX, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
scexDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
|
||||
}
|
||||
auto* plPcduDummy =
|
||||
new PlPcduDummy(objects::PLPCDU_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
plPcduDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
|
||||
@ -239,4 +259,9 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio
|
||||
objects::PLOC_SUPERVISOR_HANDLER, objects::DUMMY_COM_IF, comCookieDummy, pwrSwitcher);
|
||||
plocSupervisorDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
|
||||
}
|
||||
if (cfg.addRadSensorDummy) {
|
||||
auto* radSensorDummy =
|
||||
new RadSensorDummy(objects::RAD_SENSOR, objects::DUMMY_COM_IF, comCookieDummy);
|
||||
radSensorDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,14 @@ class GpioIF;
|
||||
|
||||
namespace dummy {
|
||||
|
||||
struct Tmp1075Cfg {
|
||||
bool addTcsBrd0 = true;
|
||||
bool addTcsBrd1 = true;
|
||||
bool addPlPcdu0 = true;
|
||||
bool addPlPcdu1 = true;
|
||||
bool addIfBrd = true;
|
||||
};
|
||||
|
||||
// Default values targeted towards EM.
|
||||
struct DummyCfg {
|
||||
bool addCoreCtrlCfg = true;
|
||||
@ -19,7 +27,12 @@ struct DummyCfg {
|
||||
bool addTempSensorDummies = true;
|
||||
bool addRtdComIFDummy = true;
|
||||
bool addPlocDummies = true;
|
||||
bool addStrDummy = true;
|
||||
bool addTmpDummies = true;
|
||||
bool addRadSensorDummy = true;
|
||||
Tmp1075Cfg tmp1075Cfg;
|
||||
bool addCamSwitcherDummy = false;
|
||||
bool addScexDummy = false;
|
||||
};
|
||||
|
||||
void createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitch, GpioIF* gpioIF, bool enableHkSets);
|
||||
|
2
fsfw
2
fsfw
Submodule fsfw updated: 8da89eba80...d575da8540
@ -133,6 +133,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
11802;0x2e1a;RESET_OCCURED;LOW;No description;mission/acs/rwHelpers.h
|
||||
11901;0x2e7d;BOOTING_FIRMWARE_FAILED_EVENT;LOW;Failed to boot firmware;mission/acs/str/StarTrackerHandler.h
|
||||
11902;0x2e7e;BOOTING_BOOTLOADER_FAILED_EVENT;LOW;Failed to boot star tracker into bootloader mode;mission/acs/str/StarTrackerHandler.h
|
||||
11903;0x2e7f;COM_ERROR_REPLY_RECEIVED;LOW;Received COM error. P1: Communication Error ID (datasheet p32);mission/acs/str/StarTrackerHandler.h
|
||||
12001;0x2ee1;SUPV_MEMORY_READ_RPT_CRC_FAILURE;LOW;PLOC supervisor crc failure in telemetry packet;linux/payload/PlocSupervisorHandler.h
|
||||
12002;0x2ee2;SUPV_UNKNOWN_TM;LOW;Unhandled event. P1: APID, P2: Service ID;linux/payload/PlocSupervisorHandler.h
|
||||
12003;0x2ee3;SUPV_UNINIMPLEMENTED_TM;LOW;No description;linux/payload/PlocSupervisorHandler.h
|
||||
@ -272,6 +273,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
14011;0x36bb;I2C_REBOOT;HIGH;I2C is unavailable. Recovery did not work, performing full reboot.;mission/sysDefs.h
|
||||
14012;0x36bc;PDEC_REBOOT;HIGH;PDEC recovery through reset was not possible, performing full reboot.;mission/sysDefs.h
|
||||
14013;0x36bd;FIRMWARE_INFO;INFO;Version information of the firmware (not OBSW). P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash P2: First four letters of Git SHA is the last byte of P1 is set.;mission/sysDefs.h
|
||||
14014;0x36be;ACTIVE_SD_INFO;INFO;Active SD card info. SD States: 0: OFF, 1: ON, 2: MOUNTED. P1: Active SD Card Index, 0 if none is active P2: First two bytes: SD state of SD card 0, last two bytes SD state of SD card 1;mission/sysDefs.h
|
||||
14100;0x3714;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/tcsDefs.h
|
||||
14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/tcsDefs.h
|
||||
14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
|
||||
@ -280,6 +282,9 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
14106;0x371a;PCDU_SYSTEM_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
|
||||
14107;0x371b;HEATER_NOT_OFF_FOR_OFF_MODE;MEDIUM;No description;mission/controller/tcsDefs.h
|
||||
14108;0x371c;MGT_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
|
||||
14109;0x371d;TCS_SWITCHING_HEATER_ON;INFO;P1: Module index. P2: Heater index;mission/controller/tcsDefs.h
|
||||
14110;0x371e;TCS_SWITCHING_HEATER_OFF;INFO;P1: Module index. P2: Heater index;mission/controller/tcsDefs.h
|
||||
14111;0x371f;TCS_HEATER_MAX_BURN_TIME_REACHED;MEDIUM;P1: Heater index. P2: Maximum burn time for heater.;mission/controller/tcsDefs.h
|
||||
14201;0x3779;TX_TIMER_EXPIRED;INFO;The transmit timer to protect the Syrlinks expired P1: The current timer value;mission/system/com/ComSubsystem.h
|
||||
14202;0x377a;BIT_LOCK_TX_ON;INFO;Transmitter will be turned on due to detection of bitlock;mission/system/com/ComSubsystem.h
|
||||
14300;0x37dc;POSSIBLE_FILE_CORRUPTION;LOW;P1: Result code of TM packet parser. P2: Timestamp of possibly corrupt file as a unix timestamp.;mission/persistentTmStoreDefs.h
|
||||
|
|
@ -133,6 +133,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
11802;0x2e1a;RESET_OCCURED;LOW;No description;mission/acs/rwHelpers.h
|
||||
11901;0x2e7d;BOOTING_FIRMWARE_FAILED_EVENT;LOW;Failed to boot firmware;mission/acs/str/StarTrackerHandler.h
|
||||
11902;0x2e7e;BOOTING_BOOTLOADER_FAILED_EVENT;LOW;Failed to boot star tracker into bootloader mode;mission/acs/str/StarTrackerHandler.h
|
||||
11903;0x2e7f;COM_ERROR_REPLY_RECEIVED;LOW;Received COM error. P1: Communication Error ID (datasheet p32);mission/acs/str/StarTrackerHandler.h
|
||||
12001;0x2ee1;SUPV_MEMORY_READ_RPT_CRC_FAILURE;LOW;PLOC supervisor crc failure in telemetry packet;linux/payload/PlocSupervisorHandler.h
|
||||
12002;0x2ee2;SUPV_UNKNOWN_TM;LOW;Unhandled event. P1: APID, P2: Service ID;linux/payload/PlocSupervisorHandler.h
|
||||
12003;0x2ee3;SUPV_UNINIMPLEMENTED_TM;LOW;No description;linux/payload/PlocSupervisorHandler.h
|
||||
@ -272,6 +273,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
14011;0x36bb;I2C_REBOOT;HIGH;I2C is unavailable. Recovery did not work, performing full reboot.;mission/sysDefs.h
|
||||
14012;0x36bc;PDEC_REBOOT;HIGH;PDEC recovery through reset was not possible, performing full reboot.;mission/sysDefs.h
|
||||
14013;0x36bd;FIRMWARE_INFO;INFO;Version information of the firmware (not OBSW). P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash P2: First four letters of Git SHA is the last byte of P1 is set.;mission/sysDefs.h
|
||||
14014;0x36be;ACTIVE_SD_INFO;INFO;Active SD card info. SD States: 0: OFF, 1: ON, 2: MOUNTED. P1: Active SD Card Index, 0 if none is active P2: First two bytes: SD state of SD card 0, last two bytes SD state of SD card 1;mission/sysDefs.h
|
||||
14100;0x3714;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/tcsDefs.h
|
||||
14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/tcsDefs.h
|
||||
14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
|
||||
@ -280,6 +282,9 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
14106;0x371a;PCDU_SYSTEM_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
|
||||
14107;0x371b;HEATER_NOT_OFF_FOR_OFF_MODE;MEDIUM;No description;mission/controller/tcsDefs.h
|
||||
14108;0x371c;MGT_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
|
||||
14109;0x371d;TCS_SWITCHING_HEATER_ON;INFO;P1: Module index. P2: Heater index;mission/controller/tcsDefs.h
|
||||
14110;0x371e;TCS_SWITCHING_HEATER_OFF;INFO;P1: Module index. P2: Heater index;mission/controller/tcsDefs.h
|
||||
14111;0x371f;TCS_HEATER_MAX_BURN_TIME_REACHED;MEDIUM;P1: Heater index. P2: Maximum burn time for heater.;mission/controller/tcsDefs.h
|
||||
14201;0x3779;TX_TIMER_EXPIRED;INFO;The transmit timer to protect the Syrlinks expired P1: The current timer value;mission/system/com/ComSubsystem.h
|
||||
14202;0x377a;BIT_LOCK_TX_ON;INFO;Transmitter will be turned on due to detection of bitlock;mission/system/com/ComSubsystem.h
|
||||
14300;0x37dc;POSSIBLE_FILE_CORRUPTION;LOW;P1: Result code of TM packet parser. P2: Timestamp of possibly corrupt file as a unix timestamp.;mission/persistentTmStoreDefs.h
|
||||
|
|
@ -54,9 +54,13 @@ class BspConfig:
|
||||
|
||||
# Store this file in the root of the generators folder
|
||||
self.csv_filename = Path(f"{ROOT_DIR}/{self.bsp_dir_name}_events.csv")
|
||||
self.subsystems_csv_filename = Path(f"{ROOT_DIR}/{self.bsp_dir_name}_subsystems.csv")
|
||||
self.subsystems_csv_filename = Path(
|
||||
f"{ROOT_DIR}/{self.bsp_dir_name}_subsystems.csv"
|
||||
)
|
||||
self.csv_copy_dest = Path(f"{OBSW_ROOT_DIR}/tmtc/eive_tmtc/config/events.csv")
|
||||
self.subsystem_csv_copy_dest = Path(f"{OBSW_ROOT_DIR}/tmtc/eive_tmtc/config/subsystems.csv")
|
||||
self.subsystem_csv_copy_dest = Path(
|
||||
f"{OBSW_ROOT_DIR}/tmtc/eive_tmtc/config/subsystems.csv"
|
||||
)
|
||||
|
||||
if (
|
||||
self.bsp_select == BspType.BSP_Q7S
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @brief Auto-generated event translation file. Contains 296 translations.
|
||||
* @brief Auto-generated event translation file. Contains 301 translations.
|
||||
* @details
|
||||
* Generated on: 2023-06-21 19:01:02
|
||||
* Generated on: 2023-07-26 12:51:20
|
||||
*/
|
||||
#include "translateEvents.h"
|
||||
|
||||
@ -139,6 +139,7 @@ const char *ERROR_STATE_STRING = "ERROR_STATE";
|
||||
const char *RESET_OCCURED_STRING = "RESET_OCCURED";
|
||||
const char *BOOTING_FIRMWARE_FAILED_EVENT_STRING = "BOOTING_FIRMWARE_FAILED_EVENT";
|
||||
const char *BOOTING_BOOTLOADER_FAILED_EVENT_STRING = "BOOTING_BOOTLOADER_FAILED_EVENT";
|
||||
const char *COM_ERROR_REPLY_RECEIVED_STRING = "COM_ERROR_REPLY_RECEIVED";
|
||||
const char *SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING = "SUPV_MEMORY_READ_RPT_CRC_FAILURE";
|
||||
const char *SUPV_UNKNOWN_TM_STRING = "SUPV_UNKNOWN_TM";
|
||||
const char *SUPV_UNINIMPLEMENTED_TM_STRING = "SUPV_UNINIMPLEMENTED_TM";
|
||||
@ -278,6 +279,7 @@ const char *TRYING_I2C_RECOVERY_STRING = "TRYING_I2C_RECOVERY";
|
||||
const char *I2C_REBOOT_STRING = "I2C_REBOOT";
|
||||
const char *PDEC_REBOOT_STRING = "PDEC_REBOOT";
|
||||
const char *FIRMWARE_INFO_STRING = "FIRMWARE_INFO";
|
||||
const char *ACTIVE_SD_INFO_STRING = "ACTIVE_SD_INFO";
|
||||
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
|
||||
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
|
||||
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
|
||||
@ -286,6 +288,9 @@ const char *CAMERA_OVERHEATING_STRING = "CAMERA_OVERHEATING";
|
||||
const char *PCDU_SYSTEM_OVERHEATING_STRING = "PCDU_SYSTEM_OVERHEATING";
|
||||
const char *HEATER_NOT_OFF_FOR_OFF_MODE_STRING = "HEATER_NOT_OFF_FOR_OFF_MODE";
|
||||
const char *MGT_OVERHEATING_STRING = "MGT_OVERHEATING";
|
||||
const char *TCS_SWITCHING_HEATER_ON_STRING = "TCS_SWITCHING_HEATER_ON";
|
||||
const char *TCS_SWITCHING_HEATER_OFF_STRING = "TCS_SWITCHING_HEATER_OFF";
|
||||
const char *TCS_HEATER_MAX_BURN_TIME_REACHED_STRING = "TCS_HEATER_MAX_BURN_TIME_REACHED";
|
||||
const char *TX_TIMER_EXPIRED_STRING = "TX_TIMER_EXPIRED";
|
||||
const char *BIT_LOCK_TX_ON_STRING = "BIT_LOCK_TX_ON";
|
||||
const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION";
|
||||
@ -572,6 +577,8 @@ const char *translateEvents(Event event) {
|
||||
return BOOTING_FIRMWARE_FAILED_EVENT_STRING;
|
||||
case (11902):
|
||||
return BOOTING_BOOTLOADER_FAILED_EVENT_STRING;
|
||||
case (11903):
|
||||
return COM_ERROR_REPLY_RECEIVED_STRING;
|
||||
case (12001):
|
||||
return SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING;
|
||||
case (12002):
|
||||
@ -850,6 +857,8 @@ const char *translateEvents(Event event) {
|
||||
return PDEC_REBOOT_STRING;
|
||||
case (14013):
|
||||
return FIRMWARE_INFO_STRING;
|
||||
case (14014):
|
||||
return ACTIVE_SD_INFO_STRING;
|
||||
case (14100):
|
||||
return NO_VALID_SENSOR_TEMPERATURE_STRING;
|
||||
case (14101):
|
||||
@ -866,6 +875,12 @@ const char *translateEvents(Event event) {
|
||||
return HEATER_NOT_OFF_FOR_OFF_MODE_STRING;
|
||||
case (14108):
|
||||
return MGT_OVERHEATING_STRING;
|
||||
case (14109):
|
||||
return TCS_SWITCHING_HEATER_ON_STRING;
|
||||
case (14110):
|
||||
return TCS_SWITCHING_HEATER_OFF_STRING;
|
||||
case (14111):
|
||||
return TCS_HEATER_MAX_BURN_TIME_REACHED_STRING;
|
||||
case (14201):
|
||||
return TX_TIMER_EXPIRED_STRING;
|
||||
case (14202):
|
||||
|
@ -2,7 +2,7 @@
|
||||
* @brief Auto-generated object translation file.
|
||||
* @details
|
||||
* Contains 175 translations.
|
||||
* Generated on: 2023-06-21 19:01:02
|
||||
* Generated on: 2023-07-26 12:51:20
|
||||
*/
|
||||
#include "translateObjects.h"
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <fsfw/filesystem/HasFileSystemIF.h>
|
||||
#include <fsfw/globalfunctions/arrayprinter.h>
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
#include <fsfw/timemanager/Stopwatch.h>
|
||||
#include <mission/acs/str/strHelpers.h>
|
||||
@ -23,6 +24,8 @@ extern "C" {
|
||||
|
||||
using namespace returnvalue;
|
||||
|
||||
static constexpr bool PACKET_WIRETAPPING = false;
|
||||
|
||||
StrComHandler::StrComHandler(object_id_t objectId) : SystemObject(objectId) {
|
||||
lock = MutexFactory::instance()->createMutex();
|
||||
semaphore.acquire();
|
||||
@ -52,7 +55,7 @@ ReturnValue_t StrComHandler::performOperation(uint8_t operationCode) {
|
||||
case InternalState::POLL_ONE_REPLY: {
|
||||
// Stopwatch watch;
|
||||
replyTimeout.setTimeout(200);
|
||||
replyResult = readOneReply(static_cast<uint32_t>(state));
|
||||
readOneReply(static_cast<uint32_t>(state));
|
||||
{
|
||||
MutexGuard mg(lock);
|
||||
replyWasReceived = true;
|
||||
@ -680,6 +683,10 @@ ReturnValue_t StrComHandler::sendMessage(CookieIF* cookie, const uint8_t* sendDa
|
||||
const uint8_t* txFrame;
|
||||
size_t frameLen;
|
||||
datalinkLayer.encodeFrame(sendData, sendLen, &txFrame, frameLen);
|
||||
if (PACKET_WIRETAPPING) {
|
||||
sif::debug << "Sending STR frame" << std::endl;
|
||||
arrayprinter::print(txFrame, frameLen);
|
||||
}
|
||||
ssize_t bytesWritten = write(serialPort, txFrame, frameLen);
|
||||
if (bytesWritten != static_cast<ssize_t>(frameLen)) {
|
||||
sif::warning << "StrComHandler: Sending packet failed" << std::endl;
|
||||
@ -709,13 +716,11 @@ ReturnValue_t StrComHandler::requestReceiveMessage(CookieIF* cookie, size_t requ
|
||||
}
|
||||
|
||||
ReturnValue_t StrComHandler::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) {
|
||||
// Consider it a configuration error if the task is not done with a command -> reply cycle
|
||||
// in time.
|
||||
bool replyWasReceived = false;
|
||||
{
|
||||
MutexGuard mg(lock);
|
||||
if (state != InternalState::SLEEPING) {
|
||||
return BUSY;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
replyWasReceived = this->replyWasReceived;
|
||||
}
|
||||
@ -728,7 +733,7 @@ ReturnValue_t StrComHandler::readReceivedMessage(CookieIF* cookie, uint8_t** buf
|
||||
*size = replyLen;
|
||||
}
|
||||
replyLen = 0;
|
||||
return replyResult;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StrComHandler::unlockAndEraseRegions(uint32_t from, uint32_t to) {
|
||||
@ -782,8 +787,10 @@ ReturnValue_t StrComHandler::handleSerialReception() {
|
||||
<< std::endl;
|
||||
return FAILED;
|
||||
} else if (bytesRead > 0) {
|
||||
// sif::info << "Received " << bytesRead << " bytes from the STR" << std::endl;
|
||||
// arrayprinter::print(recBuf.data(), bytesRead);
|
||||
if (PACKET_WIRETAPPING) {
|
||||
sif::info << "Received " << bytesRead << " bytes from the STR" << std::endl;
|
||||
arrayprinter::print(recBuf.data(), bytesRead);
|
||||
}
|
||||
datalinkLayer.feedData(recBuf.data(), bytesRead);
|
||||
}
|
||||
return OK;
|
||||
@ -797,6 +804,10 @@ ReturnValue_t StrComHandler::readOneReply(uint32_t failParameter) {
|
||||
handleSerialReception();
|
||||
result = datalinkLayer.checkRingBufForFrame(&replyPtr, replyLen);
|
||||
if (result == returnvalue::OK) {
|
||||
if (PACKET_WIRETAPPING) {
|
||||
sif::debug << "Received STR reply frame" << std::endl;
|
||||
arrayprinter::print(replyPtr, replyLen);
|
||||
}
|
||||
return returnvalue::OK;
|
||||
} else if (result != ArcsecDatalinkLayer::DEC_IN_PROGRESS) {
|
||||
triggerEvent(STR_HELPER_DEC_ERROR, result, failParameter);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @brief Auto-generated event translation file. Contains 296 translations.
|
||||
* @brief Auto-generated event translation file. Contains 301 translations.
|
||||
* @details
|
||||
* Generated on: 2023-06-21 19:01:02
|
||||
* Generated on: 2023-07-26 12:51:20
|
||||
*/
|
||||
#include "translateEvents.h"
|
||||
|
||||
@ -139,6 +139,7 @@ const char *ERROR_STATE_STRING = "ERROR_STATE";
|
||||
const char *RESET_OCCURED_STRING = "RESET_OCCURED";
|
||||
const char *BOOTING_FIRMWARE_FAILED_EVENT_STRING = "BOOTING_FIRMWARE_FAILED_EVENT";
|
||||
const char *BOOTING_BOOTLOADER_FAILED_EVENT_STRING = "BOOTING_BOOTLOADER_FAILED_EVENT";
|
||||
const char *COM_ERROR_REPLY_RECEIVED_STRING = "COM_ERROR_REPLY_RECEIVED";
|
||||
const char *SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING = "SUPV_MEMORY_READ_RPT_CRC_FAILURE";
|
||||
const char *SUPV_UNKNOWN_TM_STRING = "SUPV_UNKNOWN_TM";
|
||||
const char *SUPV_UNINIMPLEMENTED_TM_STRING = "SUPV_UNINIMPLEMENTED_TM";
|
||||
@ -278,6 +279,7 @@ const char *TRYING_I2C_RECOVERY_STRING = "TRYING_I2C_RECOVERY";
|
||||
const char *I2C_REBOOT_STRING = "I2C_REBOOT";
|
||||
const char *PDEC_REBOOT_STRING = "PDEC_REBOOT";
|
||||
const char *FIRMWARE_INFO_STRING = "FIRMWARE_INFO";
|
||||
const char *ACTIVE_SD_INFO_STRING = "ACTIVE_SD_INFO";
|
||||
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
|
||||
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
|
||||
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
|
||||
@ -286,6 +288,9 @@ const char *CAMERA_OVERHEATING_STRING = "CAMERA_OVERHEATING";
|
||||
const char *PCDU_SYSTEM_OVERHEATING_STRING = "PCDU_SYSTEM_OVERHEATING";
|
||||
const char *HEATER_NOT_OFF_FOR_OFF_MODE_STRING = "HEATER_NOT_OFF_FOR_OFF_MODE";
|
||||
const char *MGT_OVERHEATING_STRING = "MGT_OVERHEATING";
|
||||
const char *TCS_SWITCHING_HEATER_ON_STRING = "TCS_SWITCHING_HEATER_ON";
|
||||
const char *TCS_SWITCHING_HEATER_OFF_STRING = "TCS_SWITCHING_HEATER_OFF";
|
||||
const char *TCS_HEATER_MAX_BURN_TIME_REACHED_STRING = "TCS_HEATER_MAX_BURN_TIME_REACHED";
|
||||
const char *TX_TIMER_EXPIRED_STRING = "TX_TIMER_EXPIRED";
|
||||
const char *BIT_LOCK_TX_ON_STRING = "BIT_LOCK_TX_ON";
|
||||
const char *POSSIBLE_FILE_CORRUPTION_STRING = "POSSIBLE_FILE_CORRUPTION";
|
||||
@ -572,6 +577,8 @@ const char *translateEvents(Event event) {
|
||||
return BOOTING_FIRMWARE_FAILED_EVENT_STRING;
|
||||
case (11902):
|
||||
return BOOTING_BOOTLOADER_FAILED_EVENT_STRING;
|
||||
case (11903):
|
||||
return COM_ERROR_REPLY_RECEIVED_STRING;
|
||||
case (12001):
|
||||
return SUPV_MEMORY_READ_RPT_CRC_FAILURE_STRING;
|
||||
case (12002):
|
||||
@ -850,6 +857,8 @@ const char *translateEvents(Event event) {
|
||||
return PDEC_REBOOT_STRING;
|
||||
case (14013):
|
||||
return FIRMWARE_INFO_STRING;
|
||||
case (14014):
|
||||
return ACTIVE_SD_INFO_STRING;
|
||||
case (14100):
|
||||
return NO_VALID_SENSOR_TEMPERATURE_STRING;
|
||||
case (14101):
|
||||
@ -866,6 +875,12 @@ const char *translateEvents(Event event) {
|
||||
return HEATER_NOT_OFF_FOR_OFF_MODE_STRING;
|
||||
case (14108):
|
||||
return MGT_OVERHEATING_STRING;
|
||||
case (14109):
|
||||
return TCS_SWITCHING_HEATER_ON_STRING;
|
||||
case (14110):
|
||||
return TCS_SWITCHING_HEATER_OFF_STRING;
|
||||
case (14111):
|
||||
return TCS_HEATER_MAX_BURN_TIME_REACHED_STRING;
|
||||
case (14201):
|
||||
return TX_TIMER_EXPIRED_STRING;
|
||||
case (14202):
|
||||
|
@ -2,7 +2,7 @@
|
||||
* @brief Auto-generated object translation file.
|
||||
* @details
|
||||
* Contains 175 translations.
|
||||
* Generated on: 2023-06-21 19:01:02
|
||||
* Generated on: 2023-07-26 12:51:20
|
||||
*/
|
||||
#include "translateObjects.h"
|
||||
|
||||
|
@ -7,20 +7,16 @@
|
||||
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
PapbVcInterface::PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbBusyId,
|
||||
gpioId_t papbEmptyId, std::string uioFile, int mapNum)
|
||||
: gpioComIF(gpioComIF),
|
||||
papbBusyId(papbBusyId),
|
||||
papbEmptyId(papbEmptyId),
|
||||
uioFile(std::move(uioFile)),
|
||||
mapNum(mapNum) {}
|
||||
PapbVcInterface::PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbEmptyId,
|
||||
std::string uioFile, int mapNum)
|
||||
: gpioComIF(gpioComIF), papbEmptyId(papbEmptyId), uioFile(std::move(uioFile)), mapNum(mapNum) {}
|
||||
|
||||
PapbVcInterface::~PapbVcInterface() {}
|
||||
|
||||
ReturnValue_t PapbVcInterface::initialize() {
|
||||
UioMapper uioMapper(uioFile, mapNum);
|
||||
ReturnValue_t result = uioMapper.getMappedAdress(const_cast<uint32_t**>(&vcBaseReg),
|
||||
UioMapper::Permissions::WRITE_ONLY);
|
||||
UioMapper::Permissions::READ_WRITE);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
@ -32,63 +28,27 @@ ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) {
|
||||
if (size < 4) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (pollInterfaceReadiness(0, true) == returnvalue::OK) {
|
||||
if (pollReadyForPacket()) {
|
||||
startPacketTransfer(ByteWidthCfg::ONE);
|
||||
} else {
|
||||
return DirectTmSinkIF::IS_BUSY;
|
||||
}
|
||||
// TODO: This should work but does not.. :(
|
||||
// size_t idx = 0;
|
||||
// while (idx < size) {
|
||||
//
|
||||
// nanosleep(&BETWEEN_POLL_DELAY, &remDelay);
|
||||
// if ((size - idx) < 4) {
|
||||
// *vcBaseReg = CONFIG_DATA_INPUT | (size - idx - 1);
|
||||
// usleep(1);
|
||||
// }
|
||||
// if (pollPapbBusySignal(2) == returnvalue::OK) {
|
||||
// // vcBaseReg + DATA_REG_OFFSET + 3 = static_cast<uint8_t>(data + idx);
|
||||
// // vcBaseReg + DATA_REG_OFFSET + 2 = static_cast<uint8_t>(data + idx + 1);
|
||||
// // vcBaseReg + DATA_REG_OFFSET + 1 = static_cast<uint8_t>(data + idx + 2);
|
||||
// // vcBaseReg + DATA_REG_OFFSET = static_cast<uint8_t>(data + idx + 3);
|
||||
//
|
||||
// // std::memcpy((vcBaseReg + DATA_REG_OFFSET), data + idx , nextWriteSize);
|
||||
// *(vcBaseReg + DATA_REG_OFFSET) = *reinterpret_cast<const uint32_t*>(data + idx);
|
||||
// //uint8_t* byteReg = reinterpret_cast<uint8_t*>(vcBaseReg + DATA_REG_OFFSET);
|
||||
//
|
||||
// //byteReg[0] = data[idx];
|
||||
// //byteReg[1] = data[idx];
|
||||
// } else {
|
||||
// abortPacketTransfer();
|
||||
// return returnvalue::FAILED;
|
||||
// }
|
||||
// // TODO: Change this after the bugfix. Right now, the PAPB ignores the content of the byte
|
||||
// // width configuration.5
|
||||
// // It's okay to increment by a larger amount for the last segment here, loop will be over
|
||||
// // in any case.
|
||||
// idx += 4;
|
||||
// }
|
||||
for (size_t idx = 0; idx < size; idx++) {
|
||||
// This delay is super-important, DO NOT REMOVE!
|
||||
// Polling the GPIO or the config register too often messes up the scheduler.
|
||||
// TODO: Maybe this should not be done like this. It would be better if there was a custom
|
||||
// FPGA module which can accept packets and then takes care of dumping that packet into
|
||||
// the PTME. DMA would be an ideal solution for this.
|
||||
nanosleep(&BETWEEN_POLL_DELAY, &remDelay);
|
||||
if (pollInterfaceReadiness(2, false) == returnvalue::OK) {
|
||||
*(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(data[idx]);
|
||||
} else {
|
||||
abortPacketTransfer();
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
}
|
||||
nanosleep(&BETWEEN_POLL_DELAY, &remDelay);
|
||||
if (pollInterfaceReadiness(2, false) == returnvalue::OK) {
|
||||
completePacketTransfer();
|
||||
} else {
|
||||
if (not pollReadyForOctet(MAX_BUSY_POLLS)) {
|
||||
abortPacketTransfer();
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
for (size_t idx = 0; idx < size; idx++) {
|
||||
if (not pollReadyForOctet(MAX_BUSY_POLLS)) {
|
||||
abortPacketTransfer();
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
*(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(data[idx]);
|
||||
}
|
||||
if (not pollReadyForOctet(MAX_BUSY_POLLS)) {
|
||||
abortPacketTransfer();
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
completePacketTransfer();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
@ -98,63 +58,49 @@ void PapbVcInterface::startPacketTransfer(ByteWidthCfg initWidth) {
|
||||
|
||||
void PapbVcInterface::completePacketTransfer() { *vcBaseReg = CONFIG_END; }
|
||||
|
||||
ReturnValue_t PapbVcInterface::pollInterfaceReadiness(uint32_t maxPollRetries,
|
||||
bool checkReadyState) const {
|
||||
uint32_t busyIdx = 0;
|
||||
nextDelay.tv_nsec = FIRST_DELAY_PAPB_POLLING_NS;
|
||||
|
||||
while (true) {
|
||||
// Check if PAPB interface is ready to receive data. Use the configuration register for this.
|
||||
// Bit 5, see PTME ptme_001_01-0-7-r2 Table 31.
|
||||
uint32_t reg = *vcBaseReg;
|
||||
bool busy = (reg >> 5) & 0b1;
|
||||
bool ready = (reg >> 6) & 0b1;
|
||||
if (not busy) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
if (checkReadyState and not ready) {
|
||||
return PAPB_BUSY;
|
||||
}
|
||||
|
||||
busyIdx++;
|
||||
if (busyIdx >= maxPollRetries) {
|
||||
return PAPB_BUSY;
|
||||
}
|
||||
|
||||
// Ignore signal handling here for now.
|
||||
nanosleep(&nextDelay, &remDelay);
|
||||
// Adaptive delay.
|
||||
if (nextDelay.tv_nsec * 2 <= MAX_DELAY_PAPB_POLLING_NS) {
|
||||
nextDelay.tv_nsec *= 2;
|
||||
}
|
||||
}
|
||||
return returnvalue::OK;
|
||||
bool PapbVcInterface::pollReadyForPacket() const {
|
||||
// Check if PAPB interface is ready to receive data. Use the configuration register for this.
|
||||
// Bit 5, see PTME ptme_001_01-0-7-r2 Table 31.
|
||||
uint32_t reg = *vcBaseReg;
|
||||
return (reg >> 6) & 0b1;
|
||||
}
|
||||
|
||||
void PapbVcInterface::isVcInterfaceBufferEmpty() {
|
||||
bool PapbVcInterface::isVcInterfaceBufferEmpty() {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
gpio::Levels papbEmptyState = gpio::Levels::HIGH;
|
||||
|
||||
result = gpioComIF->readGpio(papbEmptyId, papbEmptyState);
|
||||
|
||||
if (result != returnvalue::OK) {
|
||||
sif::warning << "PapbVcInterface::isVcInterfaceBufferEmpty: Failed to read papb empty signal"
|
||||
<< std::endl;
|
||||
return;
|
||||
sif::error << "PapbVcInterface::isVcInterfaceBufferEmpty: Failed to read papb empty signal"
|
||||
<< std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (papbEmptyState == gpio::Levels::HIGH) {
|
||||
sif::debug << "PapbVcInterface::isVcInterfaceBufferEmpty: Buffer is empty" << std::endl;
|
||||
} else {
|
||||
sif::debug << "PapbVcInterface::isVcInterfaceBufferEmpty: Buffer is not empty" << std::endl;
|
||||
return true;
|
||||
}
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PapbVcInterface::isBusy() const { return pollInterfaceReadiness(0, true) == PAPB_BUSY; }
|
||||
bool PapbVcInterface::isBusy() const { return not pollReadyForPacket(); }
|
||||
|
||||
void PapbVcInterface::cancelTransfer() { abortPacketTransfer(); }
|
||||
|
||||
inline bool PapbVcInterface::pollReadyForOctet(uint32_t maxCycles) const {
|
||||
uint32_t reg;
|
||||
uint32_t idx = 0;
|
||||
while (idx < maxCycles) {
|
||||
reg = *vcBaseReg;
|
||||
// Busy bit.
|
||||
if (not((reg >> 5) & 0b1)) {
|
||||
return true;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ReturnValue_t PapbVcInterface::sendTestFrame() {
|
||||
/** Size of one complete transfer frame data field amounts to 1105 bytes */
|
||||
uint8_t testPacket[1105];
|
||||
|
@ -30,8 +30,7 @@ class PapbVcInterface : public VirtualChannelIF {
|
||||
* @param uioFile UIO file providing access to the PAPB bus
|
||||
* @param mapNum Map number of UIO map associated with this virtual channel
|
||||
*/
|
||||
PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbBusyId, gpioId_t papbEmptyId,
|
||||
std::string uioFile, int mapNum);
|
||||
PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbEmptyId, std::string uioFile, int mapNum);
|
||||
virtual ~PapbVcInterface();
|
||||
|
||||
bool isBusy() const override;
|
||||
@ -81,11 +80,9 @@ class PapbVcInterface : public VirtualChannelIF {
|
||||
|
||||
static constexpr long int FIRST_DELAY_PAPB_POLLING_NS = 10;
|
||||
static constexpr long int MAX_DELAY_PAPB_POLLING_NS = 40;
|
||||
static constexpr uint32_t MAX_BUSY_POLLS = 1000;
|
||||
|
||||
LinuxLibgpioIF* gpioComIF = nullptr;
|
||||
|
||||
/** Pulled to low when virtual channel not ready to receive data */
|
||||
gpioId_t papbBusyId = gpio::NO_GPIO;
|
||||
/** High when external buffer memory of virtual channel is empty */
|
||||
gpioId_t papbEmptyId = gpio::NO_GPIO;
|
||||
|
||||
@ -120,13 +117,15 @@ class PapbVcInterface : public VirtualChannelIF {
|
||||
*
|
||||
* @return returnvalue::OK when ready to receive data else PAPB_BUSY.
|
||||
*/
|
||||
inline ReturnValue_t pollInterfaceReadiness(uint32_t maxPollRetries, bool checkReadyState) const;
|
||||
inline bool pollReadyForPacket() const;
|
||||
|
||||
inline bool pollReadyForOctet(uint32_t maxCycles) const;
|
||||
|
||||
/**
|
||||
* @brief This function can be used for debugging to check whether there are packets in
|
||||
* the packet buffer of the virtual channel or not.
|
||||
*/
|
||||
void isVcInterfaceBufferEmpty();
|
||||
bool isVcInterfaceBufferEmpty();
|
||||
|
||||
/**
|
||||
* @brief This function sends a complete telemetry transfer frame data field (1105 bytes)
|
||||
|
@ -26,10 +26,18 @@ enum SafeModeStrategy : uint8_t {
|
||||
SAFECTRL_OFF = 0,
|
||||
SAFECTRL_NO_MAG_FIELD_FOR_CONTROL = 1,
|
||||
SAFECTRL_NO_SENSORS_FOR_CONTROL = 2,
|
||||
SAFECTRL_ACTIVE_MEKF = 10,
|
||||
SAFECTRL_WITHOUT_MEKF = 11,
|
||||
SAFECTRL_ECLIPSE_DAMPING = 12,
|
||||
SAFECTRL_ECLIPSE_IDELING = 13,
|
||||
// OBSW version <= v6.1.0
|
||||
LEGACY_SAFECTRL_ACTIVE_MEKF = 10,
|
||||
LEGACY_SAFECTRL_WITHOUT_MEKF = 11,
|
||||
LEGACY_SAFECTRL_ECLIPSE_DAMPING = 12,
|
||||
LEGACY_SAFECTRL_ECLIPSE_IDELING = 13,
|
||||
// Added in v6.2.0
|
||||
SAFECTRL_MEKF = 14,
|
||||
SAFECTRL_GYR = 15,
|
||||
SAFECTRL_SUSMGM = 16,
|
||||
SAFECTRL_ECLIPSE_DAMPING_GYR = 17,
|
||||
SAFECTRL_ECLIPSE_DAMPING_SUSMGM = 18,
|
||||
SAFECTRL_ECLIPSE_IDELING = 19,
|
||||
SAFECTRL_DETUMBLE_FULL = 20,
|
||||
SAFECTRL_DETUMBLE_DETERIORATED = 21,
|
||||
};
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <fsfw/globalfunctions/arrayprinter.h>
|
||||
#include <fsfw/ipc/QueueFactory.h>
|
||||
#include <fsfw/timemanager/Stopwatch.h>
|
||||
#include <mission/acs/str/StarTrackerHandler.h>
|
||||
@ -88,7 +89,6 @@ void StarTrackerHandler::doStartUp() {
|
||||
default:
|
||||
return;
|
||||
}
|
||||
solutionSet.setReportingEnabled(true);
|
||||
startupState = StartupState::DONE;
|
||||
internalState = InternalState::IDLE;
|
||||
setMode(_MODE_TO_ON);
|
||||
@ -325,7 +325,7 @@ ReturnValue_t StarTrackerHandler::buildNormalDeviceCommand(DeviceCommandId_t* id
|
||||
ReturnValue_t StarTrackerHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) {
|
||||
switch (internalState) {
|
||||
case InternalState::BOOT_FIRMWARE: {
|
||||
if (bootState == FwBootState::WAIT_FOR_EXECUTION or bootState == FwBootState::VERIFY_BOOT) {
|
||||
if (bootState == FwBootState::VERIFY_BOOT or isAwaitingReply()) {
|
||||
return NOTHING_TO_SEND;
|
||||
}
|
||||
if (bootState == FwBootState::NONE) {
|
||||
@ -349,74 +349,69 @@ ReturnValue_t StarTrackerHandler::buildTransitionDeviceCommand(DeviceCommandId_t
|
||||
*id = startracker::REQ_VERSION;
|
||||
return buildCommandFromCommand(*id, nullptr, 0);
|
||||
}
|
||||
case (FwBootState::SET_TIME): {
|
||||
*id = startracker::SET_TIME_FROM_SYS_TIME;
|
||||
return buildCommandFromCommand(*id, nullptr, 0);
|
||||
}
|
||||
case (FwBootState::LOGLEVEL): {
|
||||
bootState = FwBootState::WAIT_FOR_EXECUTION;
|
||||
*id = startracker::LOGLEVEL;
|
||||
return buildCommandFromCommand(
|
||||
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
|
||||
}
|
||||
case (FwBootState::LIMITS): {
|
||||
bootState = FwBootState::WAIT_FOR_EXECUTION;
|
||||
*id = startracker::LIMITS;
|
||||
return buildCommandFromCommand(
|
||||
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
|
||||
}
|
||||
case (FwBootState::TRACKING): {
|
||||
bootState = FwBootState::WAIT_FOR_EXECUTION;
|
||||
*id = startracker::TRACKING;
|
||||
return buildCommandFromCommand(
|
||||
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
|
||||
}
|
||||
case FwBootState::MOUNTING:
|
||||
bootState = FwBootState::WAIT_FOR_EXECUTION;
|
||||
*id = startracker::MOUNTING;
|
||||
return buildCommandFromCommand(
|
||||
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
|
||||
case FwBootState::IMAGE_PROCESSOR:
|
||||
bootState = FwBootState::WAIT_FOR_EXECUTION;
|
||||
*id = startracker::IMAGE_PROCESSOR;
|
||||
return buildCommandFromCommand(
|
||||
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
|
||||
case FwBootState::CAMERA:
|
||||
bootState = FwBootState::WAIT_FOR_EXECUTION;
|
||||
*id = startracker::CAMERA;
|
||||
return buildCommandFromCommand(
|
||||
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
|
||||
case FwBootState::CENTROIDING:
|
||||
bootState = FwBootState::WAIT_FOR_EXECUTION;
|
||||
*id = startracker::CENTROIDING;
|
||||
return buildCommandFromCommand(
|
||||
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
|
||||
case FwBootState::LISA:
|
||||
bootState = FwBootState::WAIT_FOR_EXECUTION;
|
||||
*id = startracker::LISA;
|
||||
return buildCommandFromCommand(
|
||||
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
|
||||
case FwBootState::MATCHING:
|
||||
bootState = FwBootState::WAIT_FOR_EXECUTION;
|
||||
*id = startracker::MATCHING;
|
||||
return buildCommandFromCommand(
|
||||
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
|
||||
case FwBootState::VALIDATION:
|
||||
bootState = FwBootState::WAIT_FOR_EXECUTION;
|
||||
*id = startracker::VALIDATION;
|
||||
return buildCommandFromCommand(
|
||||
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
|
||||
case FwBootState::ALGO:
|
||||
bootState = FwBootState::WAIT_FOR_EXECUTION;
|
||||
*id = startracker::ALGO;
|
||||
return buildCommandFromCommand(
|
||||
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
|
||||
case FwBootState::LOG_SUBSCRIPTION:
|
||||
bootState = FwBootState::WAIT_FOR_EXECUTION;
|
||||
*id = startracker::LOGSUBSCRIPTION;
|
||||
return buildCommandFromCommand(
|
||||
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
|
||||
case FwBootState::DEBUG_CAMERA:
|
||||
bootState = FwBootState::WAIT_FOR_EXECUTION;
|
||||
*id = startracker::DEBUG_CAMERA;
|
||||
return buildCommandFromCommand(
|
||||
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
|
||||
case FwBootState::AUTO_THRESHOLD:
|
||||
*id = startracker::AUTO_THRESHOLD;
|
||||
return buildCommandFromCommand(
|
||||
*id, reinterpret_cast<const uint8_t*>(paramJsonFile.c_str()), paramJsonFile.size());
|
||||
default: {
|
||||
sif::error << "STR: Unexpected boot state" << (int)bootState << std::endl;
|
||||
return NOTHING_TO_SEND;
|
||||
@ -459,6 +454,20 @@ ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t devi
|
||||
preparePingRequest();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (startracker::SET_TIME_FROM_SYS_TIME): {
|
||||
SetTimeActionRequest setTimeRequest{};
|
||||
timeval tv;
|
||||
Clock::getClock(&tv);
|
||||
setTimeRequest.unixTime =
|
||||
(static_cast<uint64_t>(tv.tv_sec) * 1000 * 1000) + (static_cast<uint64_t>(tv.tv_usec));
|
||||
arc_pack_settime_action_req(&setTimeRequest, commandBuffer, &rawPacketLen);
|
||||
size_t serLen = 0;
|
||||
// Time in milliseconds. Manual serialization because arcsec API ignores endianness.
|
||||
SerializeAdapter::serialize(&setTimeRequest.unixTime, commandBuffer + 2, &serLen,
|
||||
sizeof(commandBuffer) - 2, SerializeIF::Endianness::LITTLE);
|
||||
rawPacket = commandBuffer;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (startracker::REQ_TIME): {
|
||||
prepareTimeRequest();
|
||||
return returnvalue::OK;
|
||||
@ -551,6 +560,11 @@ ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t devi
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.logLevel, reinitNextSetParam);
|
||||
return result;
|
||||
}
|
||||
case (startracker::AUTO_THRESHOLD): {
|
||||
result =
|
||||
prepareParamCommand(commandData, commandDataLen, jcfgs.autoThreshold, reinitNextSetParam);
|
||||
return result;
|
||||
}
|
||||
case (startracker::LOGSUBSCRIPTION): {
|
||||
result = prepareParamCommand(commandData, commandDataLen, jcfgs.logSubscription,
|
||||
reinitNextSetParam);
|
||||
@ -655,19 +669,23 @@ void StarTrackerHandler::fillCommandAndReplyMap() {
|
||||
startracker::MAX_FRAME_SIZE * 2 + 2);
|
||||
this->insertInCommandAndReplyMap(startracker::LOGLEVEL, 3, nullptr,
|
||||
startracker::MAX_FRAME_SIZE * 2 + 2);
|
||||
this->insertInCommandAndReplyMap(startracker::SET_TIME_FROM_SYS_TIME, 2, nullptr,
|
||||
startracker::MAX_FRAME_SIZE * 2 + 2);
|
||||
this->insertInCommandAndReplyMap(startracker::LOGSUBSCRIPTION, 3, nullptr,
|
||||
startracker::MAX_FRAME_SIZE * 2 + 2);
|
||||
this->insertInCommandAndReplyMap(startracker::DEBUG_CAMERA, 3, nullptr,
|
||||
startracker::MAX_FRAME_SIZE * 2 + 2);
|
||||
this->insertInCommandAndReplyMap(startracker::LIMITS, 3, nullptr,
|
||||
startracker::MAX_FRAME_SIZE * 2 + 2);
|
||||
this->insertInCommandAndReplyMap(startracker::AUTO_THRESHOLD, 2, nullptr,
|
||||
startracker::MAX_FRAME_SIZE * 2 + 2);
|
||||
this->insertInCommandAndReplyMap(startracker::MOUNTING, 3, nullptr,
|
||||
startracker::MAX_FRAME_SIZE * 2 + 2);
|
||||
this->insertInCommandAndReplyMap(startracker::IMAGE_PROCESSOR, 3, nullptr,
|
||||
startracker::MAX_FRAME_SIZE * 2 + 2);
|
||||
this->insertInCommandAndReplyMap(startracker::CAMERA, 3, nullptr,
|
||||
startracker::MAX_FRAME_SIZE * 2 + 2);
|
||||
this->insertInCommandAndReplyMap(startracker::CENTROIDING, 3, nullptr,
|
||||
this->insertInCommandAndReplyMap(startracker::CENTROIDING, 2, nullptr,
|
||||
startracker::MAX_FRAME_SIZE * 2 + 2);
|
||||
this->insertInCommandAndReplyMap(startracker::LISA, 3, nullptr,
|
||||
startracker::MAX_FRAME_SIZE * 2 + 2);
|
||||
@ -814,6 +832,7 @@ void StarTrackerHandler::bootFirmware(Mode_t toMode) {
|
||||
setMode(toMode, startracker::SUBMODE_FIRMWARE);
|
||||
}
|
||||
sif::info << "STR: Firmware boot success" << std::endl;
|
||||
solutionSet.setReportingEnabled(true);
|
||||
internalState = InternalState::IDLE;
|
||||
startupState = StartupState::IDLE;
|
||||
break;
|
||||
@ -837,6 +856,7 @@ void StarTrackerHandler::setUpJsonCfgs(JsonConfigs& cfgs, const char* paramJsonF
|
||||
cfgs.mounting.init(paramJsonFile);
|
||||
cfgs.limits.init(paramJsonFile);
|
||||
cfgs.subscription.init(paramJsonFile);
|
||||
cfgs.autoThreshold.init(paramJsonFile);
|
||||
JCFG_DONE = true;
|
||||
}
|
||||
|
||||
@ -860,13 +880,20 @@ ReturnValue_t StarTrackerHandler::scanForReply(const uint8_t* start, size_t rema
|
||||
*foundLen = remainingSize;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
if (remainingSize < 3) {
|
||||
sif::error << "StarTrackerHandler: Reply packet with length less than 3 is invalid"
|
||||
if (remainingSize < 2) {
|
||||
sif::error << "StarTrackerHandler: Reply packet with length " << remainingSize
|
||||
<< " less than "
|
||||
"2 is invalid"
|
||||
<< std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
switch (startracker::getReplyFrameType(start)) {
|
||||
case TMTC_COMM_ERROR: {
|
||||
*foundLen = remainingSize;
|
||||
triggerEvent(COM_ERROR_REPLY_RECEIVED, start[1]);
|
||||
break;
|
||||
}
|
||||
case TMTC_ACTIONREPLY: {
|
||||
*foundLen = remainingSize;
|
||||
return scanForActionReply(startracker::getId(start), foundId);
|
||||
@ -901,6 +928,10 @@ ReturnValue_t StarTrackerHandler::interpretDeviceReply(DeviceCommandId_t id,
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
|
||||
switch (id) {
|
||||
case (startracker::SET_TIME_FROM_SYS_TIME): {
|
||||
result = handleActionReply(packet);
|
||||
break;
|
||||
}
|
||||
case (startracker::REQ_TIME): {
|
||||
result = handleTm(packet, timeSet, startracker::TimeSet::SIZE, "REQ_TIME");
|
||||
break;
|
||||
@ -960,7 +991,8 @@ ReturnValue_t StarTrackerHandler::interpretDeviceReply(DeviceCommandId_t id,
|
||||
case (startracker::TRACKING):
|
||||
case (startracker::VALIDATION):
|
||||
case (startracker::IMAGE_PROCESSOR):
|
||||
case (startracker::ALGO): {
|
||||
case (startracker::ALGO):
|
||||
case (startracker::AUTO_THRESHOLD): {
|
||||
result = handleSetParamReply(packet);
|
||||
break;
|
||||
}
|
||||
@ -1367,6 +1399,10 @@ ReturnValue_t StarTrackerHandler::scanForActionReply(uint8_t replyId, DeviceComm
|
||||
*foundId = startracker::UPLOAD_IMAGE;
|
||||
break;
|
||||
}
|
||||
case (ARC_ACTION_REQ_SETTIME_ID): {
|
||||
*foundId = startracker::SET_TIME_FROM_SYS_TIME;
|
||||
break;
|
||||
}
|
||||
case (startracker::ID::CHECKSUM): {
|
||||
*foundId = startracker::CHECKSUM;
|
||||
break;
|
||||
@ -1434,6 +1470,10 @@ ReturnValue_t StarTrackerHandler::scanForSetParameterReply(uint8_t replyId,
|
||||
*foundId = startracker::DEBUG_CAMERA;
|
||||
break;
|
||||
}
|
||||
case (startracker::ID::AUTO_THRESHOLD): {
|
||||
*foundId = startracker::AUTO_THRESHOLD;
|
||||
break;
|
||||
}
|
||||
case (startracker::ID::LOG_SUBSCRIPTION): {
|
||||
*foundId = startracker::LOGSUBSCRIPTION;
|
||||
break;
|
||||
@ -1861,7 +1901,7 @@ ReturnValue_t StarTrackerHandler::handleSetParamReply(const uint8_t* rawFrame) {
|
||||
uint8_t status = startracker::getStatusField(rawFrame);
|
||||
if (status != startracker::STATUS_OK) {
|
||||
sif::warning << "StarTrackerHandler::handleSetParamReply: Failed to execute parameter set "
|
||||
" command with parameter ID"
|
||||
"command with parameter ID "
|
||||
<< static_cast<unsigned int>(*(rawFrame + PARAMETER_ID_OFFSET)) << std::endl;
|
||||
if (internalState != InternalState::IDLE) {
|
||||
internalState = InternalState::IDLE;
|
||||
@ -1869,21 +1909,25 @@ ReturnValue_t StarTrackerHandler::handleSetParamReply(const uint8_t* rawFrame) {
|
||||
return SET_PARAM_FAILED;
|
||||
}
|
||||
if (internalState != InternalState::IDLE) {
|
||||
handleStartup(*(rawFrame + PARAMETER_ID_OFFSET));
|
||||
handleStartup(*rawFrame, *(rawFrame + PARAMETER_ID_OFFSET));
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::handleActionReply(const uint8_t* rawFrame) {
|
||||
uint8_t status = startracker::getStatusField(rawFrame);
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
if (status != startracker::STATUS_OK) {
|
||||
sif::warning << "StarTrackerHandler::handleActionReply: Failed to execute action "
|
||||
<< "command with action ID "
|
||||
<< static_cast<unsigned int>(*(rawFrame + ACTION_ID_OFFSET)) << " and status "
|
||||
<< static_cast<unsigned int>(status) << std::endl;
|
||||
return ACTION_FAILED;
|
||||
result = ACTION_FAILED;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
if (internalState != InternalState::IDLE) {
|
||||
handleStartup(*rawFrame, *(rawFrame + PARAMETER_ID_OFFSET));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t StarTrackerHandler::handleChecksumReply(const uint8_t* rawFrame) {
|
||||
@ -1979,7 +2023,7 @@ ReturnValue_t StarTrackerHandler::checkProgram() {
|
||||
startupState = StartupState::BOOT_BOOTLOADER;
|
||||
}
|
||||
if (bootState == FwBootState::VERIFY_BOOT) {
|
||||
bootState = FwBootState::LOGLEVEL;
|
||||
bootState = FwBootState::SET_TIME;
|
||||
} else if (internalState == InternalState::BOOTLOADER_CHECK) {
|
||||
triggerEvent(BOOTING_BOOTLOADER_FAILED_EVENT);
|
||||
internalState = InternalState::FAILED_BOOTLOADER_BOOT;
|
||||
@ -2056,7 +2100,18 @@ ReturnValue_t StarTrackerHandler::handleActionReplySet(const uint8_t* rawFrame,
|
||||
return result;
|
||||
}
|
||||
|
||||
void StarTrackerHandler::handleStartup(uint8_t parameterId) {
|
||||
void StarTrackerHandler::handleStartup(uint8_t tmType, uint8_t parameterId) {
|
||||
switch (tmType) {
|
||||
case (TMTC_ACTIONREPLY): {
|
||||
case (ARC_ACTION_REQ_SETTIME_ID): {
|
||||
bootState = FwBootState::LOGLEVEL;
|
||||
return;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (parameterId) {
|
||||
case (startracker::ID::LOG_LEVEL): {
|
||||
bootState = FwBootState::LIMITS;
|
||||
@ -2066,7 +2121,7 @@ void StarTrackerHandler::handleStartup(uint8_t parameterId) {
|
||||
bootState = FwBootState::TRACKING;
|
||||
break;
|
||||
}
|
||||
case (startracker::ID::TRACKING): {
|
||||
case (ARC_PARAM_TRACKING_ID): {
|
||||
bootState = FwBootState::MOUNTING;
|
||||
break;
|
||||
}
|
||||
@ -2107,6 +2162,10 @@ void StarTrackerHandler::handleStartup(uint8_t parameterId) {
|
||||
break;
|
||||
}
|
||||
case (startracker::ID::DEBUG_CAMERA): {
|
||||
bootState = FwBootState::AUTO_THRESHOLD;
|
||||
break;
|
||||
}
|
||||
case (startracker::ID::AUTO_THRESHOLD): {
|
||||
bootState = FwBootState::NONE;
|
||||
internalState = InternalState::DONE;
|
||||
break;
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <mission/acs/str/ArcsecJsonParamBase.h>
|
||||
#include <mission/acs/str/strHelpers.h>
|
||||
#include <mission/acs/str/strJsonCommands.h>
|
||||
#include <thirdparty/sagittactl/wire/common/genericstructs.h>
|
||||
|
||||
#include <thread>
|
||||
|
||||
@ -16,7 +17,7 @@
|
||||
#include "fsfw/timemanager/Countdown.h"
|
||||
|
||||
extern "C" {
|
||||
#include <wire/common/SLIP.h>
|
||||
#include <wire/common/genericstructs.h>
|
||||
}
|
||||
|
||||
/**
|
||||
@ -143,6 +144,8 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
static const Event BOOTING_FIRMWARE_FAILED_EVENT = MAKE_EVENT(1, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Failed to boot star tracker into bootloader mode
|
||||
static const Event BOOTING_BOOTLOADER_FAILED_EVENT = MAKE_EVENT(2, severity::LOW);
|
||||
//! [EXPORT] : [COMMENT] Received COM error. P1: Communication Error ID (datasheet p32)
|
||||
static constexpr Event COM_ERROR_REPLY_RECEIVED = MAKE_EVENT(3, severity::LOW);
|
||||
|
||||
static const uint8_t STATUS_OFFSET = 2;
|
||||
static const uint8_t PARAMS_OFFSET = 2;
|
||||
@ -226,6 +229,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
Mounting mounting;
|
||||
Limits limits;
|
||||
Subscription subscription;
|
||||
AutoThreshold autoThreshold;
|
||||
};
|
||||
JsonConfigs jcfgs;
|
||||
Countdown jcfgCountdown = Countdown(250);
|
||||
@ -264,6 +268,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
BOOT_DELAY,
|
||||
REQ_VERSION,
|
||||
VERIFY_BOOT,
|
||||
SET_TIME,
|
||||
LOGLEVEL,
|
||||
LIMITS,
|
||||
TRACKING,
|
||||
@ -278,7 +283,9 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
ALGO,
|
||||
LOG_SUBSCRIPTION,
|
||||
DEBUG_CAMERA,
|
||||
AUTO_THRESHOLD,
|
||||
WAIT_FOR_EXECUTION,
|
||||
RETRY_CFG_CMD
|
||||
};
|
||||
FwBootState bootState = FwBootState::NONE;
|
||||
|
||||
@ -468,7 +475,7 @@ class StarTrackerHandler : public DeviceHandlerBase {
|
||||
/**
|
||||
* @brief Handles the startup state machine
|
||||
*/
|
||||
void handleStartup(uint8_t parameterId);
|
||||
void handleStartup(uint8_t tmType, uint8_t parameterId);
|
||||
|
||||
/**
|
||||
* @brief Handles telemtry replies and fills the appropriate dataset
|
||||
|
@ -176,6 +176,13 @@ static const char DEBUG_CAMERA[] = "DebugCamera";
|
||||
static const char TIMING[] = "timing";
|
||||
static const char TEST[] = "test";
|
||||
|
||||
static constexpr char AUTO_THRESHOLD[] = "AutoThreshold";
|
||||
static constexpr char AT_MODE[] = "mode";
|
||||
static constexpr char AT_DESIRED_BLOB_COUNTS[] = "desiredBlobsCount";
|
||||
static constexpr char AT_MIN_THRESHOLD[] = "minThreshold";
|
||||
static constexpr char AT_MAX_THRESHOLD[] = "maxThreshold";
|
||||
static constexpr char AT_THRESHOLD_KP[] = "thresholdKp";
|
||||
|
||||
} // namespace arcseckeys
|
||||
|
||||
#endif /* BSP_Q7S_DEVICES_DEVICEDEFINITIONS_ARCSECJSONKEYS_H_ */
|
||||
|
@ -326,6 +326,8 @@ static const DeviceCommandId_t DEBUG_CAMERA = 83;
|
||||
static const DeviceCommandId_t FIRMWARE_UPDATE = 84;
|
||||
static const DeviceCommandId_t DISABLE_TIMESTAMP_GENERATION = 85;
|
||||
static const DeviceCommandId_t ENABLE_TIMESTAMP_GENERATION = 86;
|
||||
static constexpr DeviceCommandId_t SET_TIME_FROM_SYS_TIME = 87;
|
||||
static constexpr DeviceCommandId_t AUTO_THRESHOLD = 88;
|
||||
static const DeviceCommandId_t NONE = 0xFFFFFFFF;
|
||||
|
||||
static const uint32_t VERSION_SET_ID = REQ_VERSION;
|
||||
@ -396,7 +398,6 @@ static const uint8_t ALGO = 16;
|
||||
static const uint8_t REBOOT = 7;
|
||||
static const uint8_t UPLOAD_IMAGE = 10;
|
||||
static const uint8_t POWER = 11;
|
||||
static const uint8_t SET_TIME = 14;
|
||||
static const uint8_t SUBSCRIPTION = 18;
|
||||
static const uint8_t SOLUTION = 24;
|
||||
static const uint8_t TEMPERATURE = 27;
|
||||
@ -410,6 +411,7 @@ static const uint8_t TAKE_IMAGE = 15;
|
||||
static const uint8_t LOG_LEVEL = 3;
|
||||
static const uint8_t LOG_SUBSCRIPTION = 19;
|
||||
static const uint8_t DEBUG_CAMERA = 20;
|
||||
static const uint8_t AUTO_THRESHOLD = 23;
|
||||
} // namespace ID
|
||||
|
||||
namespace Program {
|
||||
@ -441,6 +443,21 @@ static const uint32_t secret[16]{
|
||||
REGION_12_SECRET, REGION_13_SECRET, REGION_14_SECRET, REGION_15_SECRET};
|
||||
} // namespace region_secrets
|
||||
|
||||
namespace comError {
|
||||
enum Id {
|
||||
BAD_CRC = 1,
|
||||
UNKNOWN_TM_ID = 2,
|
||||
UNKNOWN_PARAM_ID = 3,
|
||||
UNKNOWN_ACTION_REQ = 4,
|
||||
INVALID_TM_SIZE = 5,
|
||||
INVALID_PARAM_SIZE = 6,
|
||||
INVALID_ACTION_REQ_SIZE = 7,
|
||||
FRAME_TOO_SHORT = 8,
|
||||
INVALID_FRAME_TYPE = 9,
|
||||
UNKNOWN_ERROR = 10
|
||||
};
|
||||
}
|
||||
|
||||
enum class FlashSections : uint8_t {
|
||||
BOOTLOADER_SECTION = 0,
|
||||
MAIN_FIRMWARE_SECTION = 1,
|
||||
@ -650,7 +667,7 @@ class SolutionSet : public StaticLocalDataSet<SOLUTION_SET_ENTRIES> {
|
||||
// Ticks timestamp
|
||||
lp_var_t<uint32_t> ticks = lp_var_t<uint32_t>(sid.objectId, PoolIds::TICKS_SOLUTION_SET, this);
|
||||
/// Unix time stamp
|
||||
lp_var_t<uint64_t> time = lp_var_t<uint64_t>(sid.objectId, PoolIds::TIME_SOLUTION_SET, this);
|
||||
lp_var_t<uint64_t> timeUs = lp_var_t<uint64_t>(sid.objectId, PoolIds::TIME_SOLUTION_SET, this);
|
||||
// Calibrated quaternion (takes into account the mounting quaternion), typically same as
|
||||
// track q values
|
||||
lp_var_t<float> caliQw = lp_var_t<float>(sid.objectId, PoolIds::CALI_QW, this);
|
||||
@ -695,7 +712,7 @@ class SolutionSet : public StaticLocalDataSet<SOLUTION_SET_ENTRIES> {
|
||||
void printSet() {
|
||||
PoolReadGuard rg(this);
|
||||
sif::info << "SolutionSet::printSet: Ticks: " << this->ticks << std::endl;
|
||||
sif::info << "SolutionSet::printSet: Time: " << this->time << std::endl;
|
||||
sif::info << "SolutionSet::printSet: Time: " << this->timeUs << std::endl;
|
||||
sif::info << "SolutionSet::printSet: Calibrated quaternion Qw: " << this->caliQw << std::endl;
|
||||
sif::info << "SolutionSet::printSet: Calibrated quaternion Qx: " << this->caliQx << std::endl;
|
||||
sif::info << "SolutionSet::printSet: Calibrated quaternion Qy: " << this->caliQy << std::endl;
|
||||
|
@ -916,3 +916,45 @@ ReturnValue_t DebugCamera::createCommand(uint8_t* buffer) {
|
||||
adduint32(param, buffer + offset);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
AutoThreshold::AutoThreshold() : ArcsecJsonParamBase(arcseckeys::AUTO_THRESHOLD) {}
|
||||
|
||||
size_t AutoThreshold::getSize() { return COMMAND_SIZE; }
|
||||
|
||||
ReturnValue_t AutoThreshold::createCommand(uint8_t* buffer) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
uint8_t offset = 0;
|
||||
std::string param;
|
||||
addSetParamHeader(buffer, startracker::ID::AUTO_THRESHOLD);
|
||||
offset = 2;
|
||||
result = getParam(arcseckeys::AT_MODE, param);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
adduint8(param, buffer + offset);
|
||||
offset += 1;
|
||||
result = getParam(arcseckeys::AT_DESIRED_BLOB_COUNTS, param);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
adduint8(param, buffer + offset);
|
||||
offset += 1;
|
||||
result = getParam(arcseckeys::AT_MIN_THRESHOLD, param);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
adduint16(param, buffer + offset);
|
||||
offset += 2;
|
||||
result = getParam(arcseckeys::AT_MAX_THRESHOLD, param);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
adduint16(param, buffer + offset);
|
||||
offset += 2;
|
||||
result = getParam(arcseckeys::AT_THRESHOLD_KP, param);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
addfloat(param, buffer + offset);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
@ -222,6 +222,22 @@ class LogSubscription : public ArcsecJsonParamBase {
|
||||
ReturnValue_t createCommand(uint8_t* buffer) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Generates command to set log subscription parameters.
|
||||
*
|
||||
*/
|
||||
class AutoThreshold : public ArcsecJsonParamBase {
|
||||
public:
|
||||
AutoThreshold();
|
||||
|
||||
size_t getSize();
|
||||
|
||||
private:
|
||||
static const size_t COMMAND_SIZE = 12;
|
||||
|
||||
ReturnValue_t createCommand(uint8_t* buffer) override;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Generates command to set debug camera parameters
|
||||
*
|
||||
|
@ -19,13 +19,8 @@ LiveTmTask::LiveTmTask(object_id_t objectId, PusTmFunnel& pusFunnel, CfdpTmFunne
|
||||
ReturnValue_t LiveTmTask::performOperation(uint8_t opCode) {
|
||||
readCommandQueue();
|
||||
while (true) {
|
||||
bool performWriteOp = true;
|
||||
if (mode == MODE_OFF or ptmeLocked) {
|
||||
performWriteOp = false;
|
||||
}
|
||||
|
||||
// The funnel tasks are scheduled here directly as well.
|
||||
ReturnValue_t result = channel.handleNextTm(performWriteOp);
|
||||
ReturnValue_t result = channel.handleNextTm(!ptmeLocked);
|
||||
if (result == DirectTmSinkIF::IS_BUSY) {
|
||||
sif::error << "Lost live TM, PAPB busy" << std::endl;
|
||||
}
|
||||
|
@ -42,13 +42,7 @@ ReturnValue_t PersistentLogTmStoreTask::performOperation(uint8_t opCode) {
|
||||
if (not someonesBusy) {
|
||||
TaskFactory::delayTask(100);
|
||||
} else if (vcBusyDuringDump) {
|
||||
// TODO: Might not be necessary
|
||||
sif::debug << "VC busy, delaying" << std::endl;
|
||||
TaskFactory::delayTask(10);
|
||||
} else {
|
||||
// TODO: Would be best to remove this, but not delaying here can lead to evil issues.
|
||||
// Polling the PAPB of the PTME core too often leads to scheuduling issues.
|
||||
TaskFactory::delayTask(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,13 +24,7 @@ ReturnValue_t PersistentSingleTmStoreTask::performOperation(uint8_t opCode) {
|
||||
if (not busy) {
|
||||
TaskFactory::delayTask(100);
|
||||
} else if (dumpContext.vcBusyDuringDump) {
|
||||
sif::debug << "VC busy, delaying" << std::endl;
|
||||
// TODO: Might not be necessary
|
||||
TaskFactory::delayTask(10);
|
||||
} else {
|
||||
// TODO: Would be best to remove this, but not delaying here can lead to evil issues.
|
||||
// Polling the PAPB of the PTME core too often leads to scheuduling issues.
|
||||
TaskFactory::delayTask(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
AcsController::AcsController(object_id_t objectId, bool enableHkSets)
|
||||
: ExtendedControllerBase(objectId),
|
||||
enableHkSets(enableHkSets),
|
||||
fusedRotationEstimation(&acsParameters),
|
||||
guidance(&acsParameters),
|
||||
safeCtrl(&acsParameters),
|
||||
ptgCtrl(&acsParameters),
|
||||
@ -20,7 +21,8 @@ AcsController::AcsController(object_id_t objectId, bool enableHkSets)
|
||||
gpsDataProcessed(this),
|
||||
mekfData(this),
|
||||
ctrlValData(this),
|
||||
actuatorCmdData(this) {}
|
||||
actuatorCmdData(this),
|
||||
fusedRotRateData(this) {}
|
||||
|
||||
ReturnValue_t AcsController::initialize() {
|
||||
ReturnValue_t result = parameterHelper.initialize();
|
||||
@ -146,6 +148,8 @@ void AcsController::performSafe() {
|
||||
|
||||
sensorProcessing.process(now, &sensorValues, &mgmDataProcessed, &susDataProcessed,
|
||||
&gyrDataProcessed, &gpsDataProcessed, &acsParameters);
|
||||
fusedRotationEstimation.estimateFusedRotationRateSafe(&susDataProcessed, &mgmDataProcessed,
|
||||
&gyrDataProcessed, &fusedRotRateData);
|
||||
ReturnValue_t result = navigation.useMekf(&sensorValues, &gyrDataProcessed, &mgmDataProcessed,
|
||||
&susDataProcessed, &mekfData, &acsParameters);
|
||||
if (result != MultiplicativeKalmanFilter::MEKF_RUNNING &&
|
||||
@ -172,25 +176,42 @@ void AcsController::performSafe() {
|
||||
acs::SafeModeStrategy safeCtrlStrat = safeCtrl.safeCtrlStrategy(
|
||||
mgmDataProcessed.mgmVecTot.isValid(), not mekfInvalidFlag,
|
||||
gyrDataProcessed.gyrVecTot.isValid(), susDataProcessed.susVecTot.isValid(),
|
||||
fusedRotRateData.rotRateOrthogonal.isValid(), fusedRotRateData.rotRateTotal.isValid(),
|
||||
acsParameters.safeModeControllerParameters.useMekf,
|
||||
acsParameters.safeModeControllerParameters.useGyr,
|
||||
acsParameters.safeModeControllerParameters.dampingDuringEclipse);
|
||||
switch (safeCtrlStrat) {
|
||||
case (acs::SafeModeStrategy::SAFECTRL_ACTIVE_MEKF):
|
||||
case (acs::SafeModeStrategy::SAFECTRL_MEKF):
|
||||
safeCtrl.safeMekf(mgmDataProcessed.mgmVecTot.value, mekfData.satRotRateMekf.value,
|
||||
susDataProcessed.sunIjkModel.value, mekfData.quatMekf.value, sunTargetDir,
|
||||
magMomMtq, errAng);
|
||||
safeCtrlFailureFlag = false;
|
||||
safeCtrlFailureCounter = 0;
|
||||
break;
|
||||
case (acs::SafeModeStrategy::SAFECTRL_WITHOUT_MEKF):
|
||||
safeCtrl.safeNonMekf(mgmDataProcessed.mgmVecTot.value, gyrDataProcessed.gyrVecTot.value,
|
||||
susDataProcessed.susVecTot.value, sunTargetDir, magMomMtq, errAng);
|
||||
case (acs::SafeModeStrategy::SAFECTRL_GYR):
|
||||
safeCtrl.safeGyr(mgmDataProcessed.mgmVecTot.value, gyrDataProcessed.gyrVecTot.value,
|
||||
susDataProcessed.susVecTot.value, sunTargetDir, magMomMtq, errAng);
|
||||
safeCtrlFailureFlag = false;
|
||||
safeCtrlFailureCounter = 0;
|
||||
break;
|
||||
case (acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING):
|
||||
safeCtrl.safeRateDamping(mgmDataProcessed.mgmVecTot.value, gyrDataProcessed.gyrVecTot.value,
|
||||
sunTargetDir, magMomMtq, errAng);
|
||||
case (acs::SafeModeStrategy::SAFECTRL_SUSMGM):
|
||||
safeCtrl.safeSusMgm(mgmDataProcessed.mgmVecTot.value, fusedRotRateData.rotRateParallel.value,
|
||||
fusedRotRateData.rotRateOrthogonal.value,
|
||||
susDataProcessed.susVecTot.value, sunTargetDir, magMomMtq, errAng);
|
||||
safeCtrlFailureFlag = false;
|
||||
safeCtrlFailureCounter = 0;
|
||||
break;
|
||||
case (acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING_GYR):
|
||||
safeCtrl.safeRateDampingGyr(mgmDataProcessed.mgmVecTot.value,
|
||||
gyrDataProcessed.gyrVecTot.value, sunTargetDir, magMomMtq,
|
||||
errAng);
|
||||
safeCtrlFailureFlag = false;
|
||||
safeCtrlFailureCounter = 0;
|
||||
break;
|
||||
case (acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING_SUSMGM):
|
||||
safeCtrl.safeRateDampingSusMgm(mgmDataProcessed.mgmVecTot.value,
|
||||
fusedRotRateData.rotRateTotal.value, sunTargetDir, magMomMtq,
|
||||
errAng);
|
||||
safeCtrlFailureFlag = false;
|
||||
safeCtrlFailureCounter = 0;
|
||||
break;
|
||||
@ -214,12 +235,20 @@ void AcsController::performSafe() {
|
||||
acsParameters.magnetorquerParameter.dipoleMax, magMomMtq, cmdDipoleMtqs);
|
||||
|
||||
// detumble check and switch
|
||||
if (mekfData.satRotRateMekf.isValid() && acsParameters.safeModeControllerParameters.useMekf &&
|
||||
VectorOperations<double>::norm(mekfData.satRotRateMekf.value, 3) >
|
||||
acsParameters.detumbleParameter.omegaDetumbleStart) {
|
||||
detumbleCounter++;
|
||||
} else if (gyrDataProcessed.gyrVecTot.isValid() &&
|
||||
VectorOperations<double>::norm(gyrDataProcessed.gyrVecTot.value, 3) >
|
||||
if (acsParameters.safeModeControllerParameters.useMekf) {
|
||||
if (mekfData.satRotRateMekf.isValid() and
|
||||
VectorOperations<double>::norm(mekfData.satRotRateMekf.value, 3) >
|
||||
acsParameters.detumbleParameter.omegaDetumbleStart) {
|
||||
detumbleCounter++;
|
||||
}
|
||||
} else if (acsParameters.safeModeControllerParameters.useGyr) {
|
||||
if (gyrDataProcessed.gyrVecTot.isValid() and
|
||||
VectorOperations<double>::norm(gyrDataProcessed.gyrVecTot.value, 3) >
|
||||
acsParameters.detumbleParameter.omegaDetumbleStart) {
|
||||
detumbleCounter++;
|
||||
}
|
||||
} else if (fusedRotRateData.rotRateTotal.isValid() and
|
||||
VectorOperations<double>::norm(fusedRotRateData.rotRateTotal.value, 3) >
|
||||
acsParameters.detumbleParameter.omegaDetumbleStart) {
|
||||
detumbleCounter++;
|
||||
} else if (detumbleCounter > 0) {
|
||||
@ -289,17 +318,26 @@ void AcsController::performDetumble() {
|
||||
actuatorCmd.cmdDipoleMtq(*acsParameters.magnetorquerParameter.inverseAlignment,
|
||||
acsParameters.magnetorquerParameter.dipoleMax, magMomMtq, cmdDipoleMtqs);
|
||||
|
||||
if (mekfData.satRotRateMekf.isValid() &&
|
||||
VectorOperations<double>::norm(mekfData.satRotRateMekf.value, 3) <
|
||||
acsParameters.detumbleParameter.omegaDetumbleEnd) {
|
||||
detumbleCounter++;
|
||||
} else if (gyrDataProcessed.gyrVecTot.isValid() &&
|
||||
VectorOperations<double>::norm(gyrDataProcessed.gyrVecTot.value, 3) <
|
||||
acsParameters.detumbleParameter.omegaDetumbleEnd) {
|
||||
if (acsParameters.safeModeControllerParameters.useMekf) {
|
||||
if (mekfData.satRotRateMekf.isValid() and
|
||||
VectorOperations<double>::norm(mekfData.satRotRateMekf.value, 3) <
|
||||
acsParameters.detumbleParameter.omegaDetumbleStart) {
|
||||
detumbleCounter++;
|
||||
}
|
||||
} else if (acsParameters.safeModeControllerParameters.useGyr) {
|
||||
if (gyrDataProcessed.gyrVecTot.isValid() and
|
||||
VectorOperations<double>::norm(gyrDataProcessed.gyrVecTot.value, 3) <
|
||||
acsParameters.detumbleParameter.omegaDetumbleStart) {
|
||||
detumbleCounter++;
|
||||
}
|
||||
} else if (fusedRotRateData.rotRateTotal.isValid() and
|
||||
VectorOperations<double>::norm(fusedRotRateData.rotRateTotal.value, 3) <
|
||||
acsParameters.detumbleParameter.omegaDetumbleStart) {
|
||||
detumbleCounter++;
|
||||
} else if (detumbleCounter > 0) {
|
||||
detumbleCounter -= 1;
|
||||
}
|
||||
|
||||
if (detumbleCounter > acsParameters.detumbleParameter.detumblecounter) {
|
||||
detumbleCounter = 0;
|
||||
// Triggers safe mode transition in subsystem
|
||||
@ -707,6 +745,11 @@ ReturnValue_t AcsController::initializeLocalDataPool(localpool::DataPool &localD
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::RW_TARGET_SPEED, &rwTargetSpeed);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::MTQ_TARGET_DIPOLE, &mtqTargetDipole);
|
||||
poolManager.subscribeForRegularPeriodicPacket({actuatorCmdData.getSid(), enableHkSets, 10.0});
|
||||
// Fused Rot Rate
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::ROT_RATE_ORTHOGONAL, &rotRateOrthogonal);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::ROT_RATE_PARALLEL, &rotRateParallel);
|
||||
localDataPoolMap.emplace(acsctrl::PoolIds::ROT_RATE_TOTAL, &rotRateTotal);
|
||||
poolManager.subscribeForRegularPeriodicPacket({fusedRotRateData.getSid(), enableHkSets, 10.0});
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
@ -732,6 +775,8 @@ LocalPoolDataSetBase *AcsController::getDataSetHandle(sid_t sid) {
|
||||
return &ctrlValData;
|
||||
case acsctrl::ACTUATOR_CMD_DATA:
|
||||
return &actuatorCmdData;
|
||||
case acsctrl::FUSED_ROTATION_RATE_DATA:
|
||||
return &fusedRotRateData;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <mission/acs/rwHelpers.h>
|
||||
#include <mission/acs/susMax1227Helpers.h>
|
||||
#include <mission/controller/acs/ActuatorCmd.h>
|
||||
#include <mission/controller/acs/FusedRotationEstimation.h>
|
||||
#include <mission/controller/acs/Guidance.h>
|
||||
#include <mission/controller/acs/MultiplicativeKalmanFilter.h>
|
||||
#include <mission/controller/acs/Navigation.h>
|
||||
@ -49,6 +50,7 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
|
||||
AcsParameters acsParameters;
|
||||
SensorProcessing sensorProcessing;
|
||||
FusedRotationEstimation fusedRotationEstimation;
|
||||
Navigation navigation;
|
||||
ActuatorCmd actuatorCmd;
|
||||
Guidance guidance;
|
||||
@ -226,6 +228,12 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
|
||||
PoolEntry<int32_t> rwTargetSpeed = PoolEntry<int32_t>(4);
|
||||
PoolEntry<int16_t> mtqTargetDipole = PoolEntry<int16_t>(3);
|
||||
|
||||
// Fused Rot Rate
|
||||
acsctrl::FusedRotRateData fusedRotRateData;
|
||||
PoolEntry<double> rotRateOrthogonal = PoolEntry<double>(3);
|
||||
PoolEntry<double> rotRateParallel = PoolEntry<double>(3);
|
||||
PoolEntry<double> rotRateTotal = PoolEntry<double>(3);
|
||||
|
||||
// Initial delay to make sure all pool variables have been initialized their owners
|
||||
Countdown initialCountdown = Countdown(INIT_DELAY);
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
#ifndef MISSION_CONTROLLER_THERMALCONTROLLER_H_
|
||||
#define MISSION_CONTROLLER_THERMALCONTROLLER_H_
|
||||
|
||||
#include <bsp_q7s/core/CoreDefinitions.h>
|
||||
#include <bsp_q7s/core/defs.h>
|
||||
#include <fsfw/controller/ExtendedControllerBase.h>
|
||||
#include <fsfw/devicehandlers/DeviceHandlerThermalSet.h>
|
||||
#include <fsfw/timemanager/Countdown.h>
|
||||
@ -24,74 +24,7 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <list>
|
||||
|
||||
/**
|
||||
* NOP Limit: Hard limit for device, usually from datasheet. Device damage is possible lif NOP limit
|
||||
* is exceeded.
|
||||
* OP Limit: Soft limit. Device should be switched off or TCS controller should take action if the
|
||||
* limit is exceeded to avoid reaching NOP limit
|
||||
*/
|
||||
struct TempLimits {
|
||||
TempLimits(float nopLowerLimit, float opLowerLimit, float cutOffLimit, float opUpperLimit,
|
||||
float nopUpperLimit)
|
||||
: opLowerLimit(opLowerLimit),
|
||||
opUpperLimit(opUpperLimit),
|
||||
cutOffLimit(cutOffLimit),
|
||||
nopLowerLimit(nopLowerLimit),
|
||||
nopUpperLimit(nopUpperLimit) {}
|
||||
float opLowerLimit;
|
||||
float opUpperLimit;
|
||||
float cutOffLimit;
|
||||
float nopLowerLimit;
|
||||
float nopUpperLimit;
|
||||
};
|
||||
|
||||
struct ThermalState {
|
||||
uint8_t errorCounter;
|
||||
// Is heating on for that thermal module?
|
||||
bool heating = false;
|
||||
heater::Switch heaterSwitch = heater::Switch::NUMBER_OF_SWITCHES;
|
||||
// Heater start time and end times as UNIX seconds. Please note that these times will be updated
|
||||
// when a switch command is sent, with no guarantess that the heater actually went on.
|
||||
uint32_t heaterStartTime = 0;
|
||||
uint32_t heaterEndTime = 0;
|
||||
};
|
||||
|
||||
struct HeaterState {
|
||||
bool switchTransition;
|
||||
HeaterHandler::SwitchState target;
|
||||
uint8_t heaterSwitchControlCycles;
|
||||
};
|
||||
|
||||
using HeaterSwitchStates = std::array<HeaterHandler::SwitchState, heater::NUMBER_OF_SWITCHES>;
|
||||
|
||||
enum ThermalComponents : uint8_t {
|
||||
NONE = 0,
|
||||
ACS_BOARD = 1,
|
||||
MGT = 2,
|
||||
RW = 3,
|
||||
STR = 4,
|
||||
IF_BOARD = 5,
|
||||
TCS_BOARD = 6,
|
||||
OBC = 7,
|
||||
OBCIF_BOARD = 8,
|
||||
SBAND_TRANSCEIVER = 9,
|
||||
PCDUP60_BOARD = 10,
|
||||
PCDUACU = 11,
|
||||
PCDUPDU = 12,
|
||||
PLPCDU_BOARD = 13,
|
||||
PLOCMISSION_BOARD = 14,
|
||||
PLOCPROCESSING_BOARD = 15,
|
||||
DAC = 16,
|
||||
CAMERA = 17,
|
||||
DRO = 18,
|
||||
X8 = 19,
|
||||
HPA = 20,
|
||||
TX = 21,
|
||||
MPA = 22,
|
||||
SCEX_BOARD = 23,
|
||||
NUM_ENTRIES
|
||||
};
|
||||
#include <optional>
|
||||
|
||||
class ThermalController : public ExtendedControllerBase {
|
||||
public:
|
||||
@ -102,8 +35,28 @@ class ThermalController : public ExtendedControllerBase {
|
||||
static constexpr int16_t SANITY_LIMIT_LOWER_TEMP = -80;
|
||||
static constexpr int16_t SANITY_LIMIT_UPPER_TEMP = 160;
|
||||
|
||||
// 1 hour
|
||||
static constexpr uint32_t DEFAULT_MAX_HEATER_ON_DURATION_MS = 60 * 60 * 1000;
|
||||
static constexpr uint32_t MAX_HEATER_ON_DURATIONS_MS[8] = {// PLOC PROC board
|
||||
DEFAULT_MAX_HEATER_ON_DURATION_MS,
|
||||
// PCDU PDU
|
||||
DEFAULT_MAX_HEATER_ON_DURATION_MS,
|
||||
// ACS Board
|
||||
DEFAULT_MAX_HEATER_ON_DURATION_MS,
|
||||
// OBC Board
|
||||
DEFAULT_MAX_HEATER_ON_DURATION_MS,
|
||||
// Camera
|
||||
DEFAULT_MAX_HEATER_ON_DURATION_MS,
|
||||
// STR
|
||||
DEFAULT_MAX_HEATER_ON_DURATION_MS,
|
||||
// DRO
|
||||
DEFAULT_MAX_HEATER_ON_DURATION_MS,
|
||||
// S-Band
|
||||
DEFAULT_MAX_HEATER_ON_DURATION_MS};
|
||||
|
||||
ThermalController(object_id_t objectId, HeaterHandler& heater,
|
||||
const std::atomic_bool& tcsBoardShortUnavailable);
|
||||
const std::atomic_bool& tcsBoardShortUnavailable, bool pollPcdu1Tmp);
|
||||
virtual ~ThermalController();
|
||||
|
||||
ReturnValue_t initialize() override;
|
||||
|
||||
@ -111,16 +64,16 @@ class ThermalController : public ExtendedControllerBase {
|
||||
struct HeaterContext {
|
||||
public:
|
||||
HeaterContext(heater::Switch switchNr, heater::Switch redundantSwitchNr,
|
||||
const TempLimits& tempLimit)
|
||||
const tcsCtrl::TempLimits& tempLimit)
|
||||
: switchNr(switchNr), redSwitchNr(redundantSwitchNr), tempLimit(tempLimit) {}
|
||||
bool doHeaterHandling = true;
|
||||
heater::Switch switchNr;
|
||||
HeaterHandler::SwitchState switchState = HeaterHandler::SwitchState::OFF;
|
||||
heater::SwitchState switchState = heater::SwitchState::OFF;
|
||||
heater::Switch redSwitchNr;
|
||||
const TempLimits& tempLimit;
|
||||
const tcsCtrl::TempLimits& tempLimit;
|
||||
};
|
||||
|
||||
void performThermalModuleCtrl(const HeaterSwitchStates& heaterSwitchStates);
|
||||
void performThermalModuleCtrl(const tcsCtrl::HeaterSwitchStates& heaterSwitchStates);
|
||||
ReturnValue_t handleCommandMessage(CommandMessage* message) override;
|
||||
void performControlOperation() override;
|
||||
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
@ -142,12 +95,12 @@ class ThermalController : public ExtendedControllerBase {
|
||||
|
||||
HeaterHandler& heaterHandler;
|
||||
|
||||
bool pollPcdu1Tmp;
|
||||
tcsCtrl::SensorTemperatures sensorTemperatures;
|
||||
tcsCtrl::SusTemperatures susTemperatures;
|
||||
tcsCtrl::DeviceTemperatures deviceTemperatures;
|
||||
tcsCtrl::HeaterInfo heaterInfo;
|
||||
lp_vec_t<int16_t, 9> currentVecPdu2 =
|
||||
lp_vec_t<int16_t, 9>(gp_id_t(objects::PDU2_HANDLER, PDU::pool::PDU_CURRENTS));
|
||||
tcsCtrl::TcsCtrlInfo tcsCtrlInfo;
|
||||
|
||||
DeviceHandlerThermalSet imtqThermalSet;
|
||||
|
||||
@ -173,7 +126,7 @@ class ThermalController : public ExtendedControllerBase {
|
||||
TMP1075::Tmp1075Dataset tmp1075SetTcs1;
|
||||
TMP1075::Tmp1075Dataset tmp1075SetPlPcdu0;
|
||||
// damaged
|
||||
// TMP1075::Tmp1075Dataset tmp1075SetPlPcdu1;
|
||||
TMP1075::Tmp1075Dataset* tmp1075SetPlPcdu1;
|
||||
TMP1075::Tmp1075Dataset tmp1075SetIfBoard;
|
||||
|
||||
// SUS
|
||||
@ -227,57 +180,67 @@ class ThermalController : public ExtendedControllerBase {
|
||||
lp_var_t<float> tempMgm2 =
|
||||
lp_var_t<float>(objects::MGM_2_LIS3_HANDLER, mgmLis3::TEMPERATURE_CELCIUS);
|
||||
lp_var_t<float> tempAdcPayloadPcdu = lp_var_t<float>(objects::PLPCDU_HANDLER, plpcdu::TEMP);
|
||||
lp_vec_t<int16_t, 9> currentVecPdu2 =
|
||||
lp_vec_t<int16_t, 9>(gp_id_t(objects::PDU2_HANDLER, PDU::pool::PDU_CURRENTS));
|
||||
|
||||
// TempLimits
|
||||
TempLimits acsBoardLimits = TempLimits(-40.0, -40.0, 80.0, 85.0, 85.0);
|
||||
TempLimits mgtLimits = TempLimits(-40.0, -40.0, 65.0, 70.0, 70.0);
|
||||
TempLimits rwLimits = TempLimits(-40.0, -40.0, 80.0, 85.0, 85.0);
|
||||
TempLimits strLimits = TempLimits(-30.0, -20.0, 65.0, 70.0, 80.0);
|
||||
TempLimits ifBoardLimits = TempLimits(-65.0, -40.0, 80.0, 85.0, 150.0);
|
||||
TempLimits tcsBoardLimits = TempLimits(-60.0, -40.0, 80.0, 85.0, 130.0);
|
||||
TempLimits obcLimits = TempLimits(-40.0, -40.0, 80.0, 85.0, 85.0);
|
||||
TempLimits obcIfBoardLimits = TempLimits(-65.0, -40.0, 80.0, 85.0, 125.0);
|
||||
TempLimits sBandTransceiverLimits = TempLimits(-40.0, -25.0, 35.0, 40.0, 65.0);
|
||||
TempLimits pcduP60BoardLimits = TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0);
|
||||
TempLimits pcduAcuLimits = TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0);
|
||||
TempLimits pcduPduLimits = TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0);
|
||||
TempLimits plPcduBoardLimits = TempLimits(-55.0, -40.0, 80.0, 85.0, 125.0);
|
||||
TempLimits plocMissionBoardLimits = TempLimits(-30.0, -10.0, 40.0, 45.0, 60);
|
||||
TempLimits plocProcessingBoardLimits = TempLimits(-30.0, -10.0, 40.0, 45.0, 60.0);
|
||||
TempLimits dacLimits = TempLimits(-65.0, -40.0, 113.0, 118.0, 150.0);
|
||||
TempLimits cameraLimits = TempLimits(-40.0, -30.0, 60.0, 65.0, 85.0);
|
||||
TempLimits droLimits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
|
||||
TempLimits x8Limits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
|
||||
TempLimits hpaLimits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
|
||||
TempLimits txLimits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
|
||||
TempLimits mpaLimits = TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
|
||||
TempLimits scexBoardLimits = TempLimits(-60.0, -40.0, 80.0, 85.0, 150.0);
|
||||
tcsCtrl::TempLimits acsBoardLimits = tcsCtrl::TempLimits(-40.0, -40.0, 80.0, 85.0, 85.0);
|
||||
tcsCtrl::TempLimits mgtLimits = tcsCtrl::TempLimits(-40.0, -40.0, 65.0, 70.0, 70.0);
|
||||
tcsCtrl::TempLimits rwLimits = tcsCtrl::TempLimits(-40.0, -40.0, 80.0, 85.0, 85.0);
|
||||
tcsCtrl::TempLimits strLimits = tcsCtrl::TempLimits(-30.0, -20.0, 65.0, 70.0, 80.0);
|
||||
tcsCtrl::TempLimits ifBoardLimits = tcsCtrl::TempLimits(-65.0, -40.0, 80.0, 85.0, 150.0);
|
||||
tcsCtrl::TempLimits tcsBoardLimits = tcsCtrl::TempLimits(-60.0, -40.0, 80.0, 85.0, 130.0);
|
||||
tcsCtrl::TempLimits obcLimits = tcsCtrl::TempLimits(-40.0, -40.0, 80.0, 85.0, 85.0);
|
||||
tcsCtrl::TempLimits obcIfBoardLimits = tcsCtrl::TempLimits(-65.0, -40.0, 80.0, 85.0, 125.0);
|
||||
tcsCtrl::TempLimits sBandTransceiverLimits = tcsCtrl::TempLimits(-40.0, -25.0, 35.0, 40.0, 65.0);
|
||||
tcsCtrl::TempLimits pcduP60BoardLimits = tcsCtrl::TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0);
|
||||
tcsCtrl::TempLimits pcduAcuLimits = tcsCtrl::TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0);
|
||||
tcsCtrl::TempLimits pcduPduLimits = tcsCtrl::TempLimits(-35.0, -35.0, 80.0, 85.0, 85.0);
|
||||
tcsCtrl::TempLimits plPcduBoardLimits = tcsCtrl::TempLimits(-55.0, -40.0, 80.0, 85.0, 125.0);
|
||||
tcsCtrl::TempLimits plocMissionBoardLimits = tcsCtrl::TempLimits(-30.0, -10.0, 40.0, 45.0, 60);
|
||||
tcsCtrl::TempLimits plocProcessingBoardLimits =
|
||||
tcsCtrl::TempLimits(-30.0, -10.0, 40.0, 45.0, 60.0);
|
||||
tcsCtrl::TempLimits dacLimits = tcsCtrl::TempLimits(-65.0, -40.0, 113.0, 118.0, 150.0);
|
||||
tcsCtrl::TempLimits cameraLimits = tcsCtrl::TempLimits(-40.0, -30.0, 60.0, 65.0, 85.0);
|
||||
tcsCtrl::TempLimits droLimits = tcsCtrl::TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
|
||||
tcsCtrl::TempLimits x8Limits = tcsCtrl::TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
|
||||
tcsCtrl::TempLimits hpaLimits = tcsCtrl::TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
|
||||
tcsCtrl::TempLimits txLimits = tcsCtrl::TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
|
||||
tcsCtrl::TempLimits mpaLimits = tcsCtrl::TempLimits(-40.0, -30.0, 75.0, 80.0, 90.0);
|
||||
tcsCtrl::TempLimits scexBoardLimits = tcsCtrl::TempLimits(-60.0, -40.0, 80.0, 85.0, 150.0);
|
||||
|
||||
struct CtrlContext {
|
||||
double sensorTemp = INVALID_TEMPERATURE;
|
||||
uint8_t currentSensorIndex = 0;
|
||||
tcsCtrl::ThermalComponents thermalComponent = tcsCtrl::NONE;
|
||||
bool redSwitchNrInUse = false;
|
||||
bool componentAboveCutOffLimit = false;
|
||||
bool componentAboveUpperLimit = false;
|
||||
Event overHeatEventToTrigger;
|
||||
} ctrlCtx;
|
||||
|
||||
double sensorTemp = INVALID_TEMPERATURE;
|
||||
ThermalComponents thermalComponent = NONE;
|
||||
bool redSwitchNrInUse = false;
|
||||
MessageQueueId_t camId = MessageQueueIF::NO_QUEUE;
|
||||
bool componentAboveCutOffLimit = false;
|
||||
bool componentAboveUpperLimit = false;
|
||||
Event overHeatEventToTrigger;
|
||||
bool eBandTooHotFlag = false;
|
||||
bool camTooHotOneShotFlag = false;
|
||||
bool scexTooHotFlag = false;
|
||||
bool plocTooHotFlag = false;
|
||||
bool pcduSystemTooHotFlag = false;
|
||||
bool syrlinksTooHotFlag = false;
|
||||
bool obcTooHotFlag = false;
|
||||
bool mgtTooHotFlag = false;
|
||||
bool strTooHotFlag = false;
|
||||
bool rwTooHotFlag = false;
|
||||
|
||||
struct TooHotFlags {
|
||||
bool eBandTooHotFlag = false;
|
||||
bool camTooHotOneShotFlag = false;
|
||||
bool scexTooHotFlag = false;
|
||||
bool plocTooHotFlag = false;
|
||||
bool pcduSystemTooHotFlag = false;
|
||||
bool syrlinksTooHotFlag = false;
|
||||
bool obcTooHotFlag = false;
|
||||
bool mgtTooHotFlag = false;
|
||||
bool strTooHotFlag = false;
|
||||
bool rwTooHotFlag = false;
|
||||
} tooHotFlags;
|
||||
|
||||
bool transitionWhenHeatersOff = false;
|
||||
uint32_t transitionWhenHeatersOffCycles = 0;
|
||||
Mode_t targetMode = MODE_OFF;
|
||||
Submode_t targetSubmode = SUBMODE_NONE;
|
||||
uint32_t cycles = 0;
|
||||
std::array<ThermalState, ThermalComponents::NUM_ENTRIES> thermalStates{};
|
||||
std::array<HeaterState, heater::NUMBER_OF_SWITCHES> heaterStates{};
|
||||
std::array<tcsCtrl::ThermalState, tcsCtrl::NUM_THERMAL_COMPONENTS> thermalStates{};
|
||||
std::array<tcsCtrl::HeaterState, heater::NUMBER_OF_SWITCHES> heaterStates{};
|
||||
|
||||
// Initial delay to make sure all pool variables have been initialized their owners.
|
||||
// Also, wait for system initialization to complete.
|
||||
@ -298,6 +261,12 @@ class ThermalController : public ExtendedControllerBase {
|
||||
PoolEntry<uint8_t> heaterSwitchStates = PoolEntry<uint8_t>(heater::NUMBER_OF_SWITCHES);
|
||||
PoolEntry<int16_t> heaterCurrent = PoolEntry<int16_t>();
|
||||
|
||||
PoolEntry<uint8_t> tcsCtrlHeaterOn = PoolEntry<uint8_t>(tcsCtrl::NUM_THERMAL_COMPONENTS);
|
||||
PoolEntry<uint8_t> tcsCtrlSensorIdx = PoolEntry<uint8_t>(tcsCtrl::NUM_THERMAL_COMPONENTS);
|
||||
PoolEntry<uint8_t> tcsCtrlHeaterIdx = PoolEntry<uint8_t>(tcsCtrl::NUM_THERMAL_COMPONENTS);
|
||||
PoolEntry<uint32_t> tcsCtrlStartTimes = PoolEntry<uint32_t>(tcsCtrl::NUM_THERMAL_COMPONENTS);
|
||||
PoolEntry<uint32_t> tcsCtrlEndTimes = PoolEntry<uint32_t>(tcsCtrl::NUM_THERMAL_COMPONENTS);
|
||||
|
||||
static constexpr dur_millis_t MUTEX_TIMEOUT = 50;
|
||||
|
||||
void startTransition(Mode_t mode, Submode_t submode) override;
|
||||
@ -319,8 +288,8 @@ class ThermalController : public ExtendedControllerBase {
|
||||
bool selectAndReadSensorTemp(HeaterContext& htrCtx);
|
||||
|
||||
void heaterSwitchHelperAllOff();
|
||||
void heaterSwitchHelper(heater::Switch switchNr, HeaterHandler::SwitchState state,
|
||||
unsigned componentIdx);
|
||||
void heaterSwitchHelper(heater::Switch switchNr, heater::SwitchState state,
|
||||
std::optional<unsigned> componentIdx);
|
||||
|
||||
void ctrlAcsBoard();
|
||||
void ctrlMgt();
|
||||
@ -329,7 +298,6 @@ class ThermalController : public ExtendedControllerBase {
|
||||
void ctrlIfBoard();
|
||||
void ctrlTcsBoard();
|
||||
void ctrlObc();
|
||||
void ctrlObcIfBoard();
|
||||
void ctrlSBandTransceiver();
|
||||
void ctrlPcduP60Board();
|
||||
void ctrlPcduAcu();
|
||||
@ -345,7 +313,22 @@ class ThermalController : public ExtendedControllerBase {
|
||||
void ctrlTx();
|
||||
void ctrlMpa();
|
||||
void ctrlScexBoard();
|
||||
void heaterTransitionControl(const HeaterSwitchStates& currentHeaterStates);
|
||||
|
||||
/**
|
||||
* The transition of heaters might take some time. As long as a transition is
|
||||
* going on, the TCS controller works in a reduced form. This function takes care
|
||||
* of tracking transition and capturing their completion.
|
||||
* @param currentHeaterStates
|
||||
*/
|
||||
void heaterTransitionControl(const tcsCtrl::HeaterSwitchStates& currentHeaterStates);
|
||||
/**
|
||||
* Control tasks to prevent heaters being on for prolonged periods. Ideally, this
|
||||
* should never happen, but this task prevents bugs from causing heaters to stay on
|
||||
* for a long time, which draws a lot of power.
|
||||
* @param currentHeaterStates
|
||||
*/
|
||||
void heaterMaxDurationControl(const tcsCtrl::HeaterSwitchStates& currentHeaterStates);
|
||||
void crossCheckHeaterStateOfComponentsWhenHeaterGoesOff(heater::Switch switchIdx);
|
||||
void setMode(Mode_t mode, Submode_t submode);
|
||||
uint32_t tempFloatToU32() const;
|
||||
bool tooHotHandler(object_id_t object, bool& oneShotFlag);
|
||||
|
@ -105,6 +105,9 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
parameterWrapper->setVector(mgmHandlingParameters.mgm4variance);
|
||||
break;
|
||||
case 0x12:
|
||||
parameterWrapper->set(mgmHandlingParameters.mgmVectorFilterWeight);
|
||||
break;
|
||||
case 0x13:
|
||||
parameterWrapper->set(mgmHandlingParameters.mgmDerivativeFilterWeight);
|
||||
break;
|
||||
default:
|
||||
@ -224,6 +227,12 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
case 0x24:
|
||||
parameterWrapper->set(susHandlingParameters.susBrightnessThreshold);
|
||||
break;
|
||||
case 0x25:
|
||||
parameterWrapper->set(susHandlingParameters.susVectorFilterWeight);
|
||||
break;
|
||||
case 0x26:
|
||||
parameterWrapper->set(susHandlingParameters.susRateFilterWeight);
|
||||
break;
|
||||
default:
|
||||
return INVALID_IDENTIFIER_ID;
|
||||
}
|
||||
@ -339,26 +348,41 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
parameterWrapper->set(safeModeControllerParameters.k_parallelMekf);
|
||||
break;
|
||||
case 0x3:
|
||||
parameterWrapper->set(safeModeControllerParameters.k_orthoNonMekf);
|
||||
parameterWrapper->set(safeModeControllerParameters.k_orthoGyr);
|
||||
break;
|
||||
case 0x4:
|
||||
parameterWrapper->set(safeModeControllerParameters.k_alignNonMekf);
|
||||
parameterWrapper->set(safeModeControllerParameters.k_alignGyr);
|
||||
break;
|
||||
case 0x5:
|
||||
parameterWrapper->set(safeModeControllerParameters.k_parallelNonMekf);
|
||||
parameterWrapper->set(safeModeControllerParameters.k_parallelGyr);
|
||||
break;
|
||||
case 0x6:
|
||||
parameterWrapper->setVector(safeModeControllerParameters.sunTargetDirLeop);
|
||||
parameterWrapper->set(safeModeControllerParameters.k_orthoSusMgm);
|
||||
break;
|
||||
case 0x7:
|
||||
parameterWrapper->setVector(safeModeControllerParameters.sunTargetDir);
|
||||
parameterWrapper->set(safeModeControllerParameters.k_alignSusMgm);
|
||||
break;
|
||||
case 0x8:
|
||||
parameterWrapper->set(safeModeControllerParameters.useMekf);
|
||||
parameterWrapper->set(safeModeControllerParameters.k_parallelSusMgm);
|
||||
break;
|
||||
case 0x9:
|
||||
parameterWrapper->setVector(safeModeControllerParameters.sunTargetDirLeop);
|
||||
break;
|
||||
case 0xA:
|
||||
parameterWrapper->setVector(safeModeControllerParameters.sunTargetDir);
|
||||
break;
|
||||
case 0xB:
|
||||
parameterWrapper->set(safeModeControllerParameters.useMekf);
|
||||
break;
|
||||
case 0xC:
|
||||
parameterWrapper->set(safeModeControllerParameters.useGyr);
|
||||
break;
|
||||
case 0xD:
|
||||
parameterWrapper->set(safeModeControllerParameters.dampingDuringEclipse);
|
||||
break;
|
||||
case 0xE:
|
||||
parameterWrapper->set(safeModeControllerParameters.sineLimitSunRotRate);
|
||||
break;
|
||||
default:
|
||||
return INVALID_IDENTIFIER_ID;
|
||||
}
|
||||
|
@ -77,7 +77,8 @@ class AcsParameters : public HasParametersIF {
|
||||
float mgm02variance[3] = {pow(3.2e-7, 2), pow(3.2e-7, 2), pow(4.1e-7, 2)};
|
||||
float mgm13variance[3] = {pow(1.5e-8, 2), pow(1.5e-8, 2), pow(1.5e-8, 2)};
|
||||
float mgm4variance[3] = {pow(1.7e-6, 2), pow(1.7e-6, 2), pow(1.7e-6, 2)};
|
||||
float mgmDerivativeFilterWeight = 0.5;
|
||||
float mgmVectorFilterWeight = 0.85;
|
||||
float mgmDerivativeFilterWeight = 0.85;
|
||||
} mgmHandlingParameters;
|
||||
|
||||
struct SusHandlingParameters {
|
||||
@ -767,6 +768,8 @@ class AcsParameters : public HasParametersIF {
|
||||
0.167666815691513, 0.163137400730063, -0.000609874123906977, -0.00205336098697513,
|
||||
-0.000889232196185857, -0.00168429567131815}};
|
||||
float susBrightnessThreshold = 0.7;
|
||||
float susVectorFilterWeight = .85;
|
||||
float susRateFilterWeight = .85;
|
||||
} susHandlingParameters;
|
||||
|
||||
struct GyrHandlingParameters {
|
||||
@ -825,15 +828,22 @@ class AcsParameters : public HasParametersIF {
|
||||
double k_alignMekf = 4.0e-5;
|
||||
double k_parallelMekf = 3.75e-4;
|
||||
|
||||
double k_orthoNonMekf = 4.4e-3;
|
||||
double k_alignNonMekf = 4.0e-5;
|
||||
double k_parallelNonMekf = 3.75e-4;
|
||||
double k_orthoGyr = 4.4e-3;
|
||||
double k_alignGyr = 4.0e-5;
|
||||
double k_parallelGyr = 3.75e-4;
|
||||
|
||||
double k_orthoSusMgm = 1.1e-2;
|
||||
double k_alignSusMgm = 2.0e-5;
|
||||
double k_parallelSusMgm = 4.4e-4;
|
||||
|
||||
double sunTargetDirLeop[3] = {0, sqrt(.5), sqrt(.5)};
|
||||
double sunTargetDir[3] = {0, 0, 1};
|
||||
|
||||
uint8_t useMekf = false;
|
||||
uint8_t useGyr = true;
|
||||
uint8_t dampingDuringEclipse = true;
|
||||
|
||||
float sineLimitSunRotRate = 0.24;
|
||||
} safeModeControllerParameters;
|
||||
|
||||
struct PointingLawParameters {
|
||||
|
@ -2,6 +2,7 @@ target_sources(
|
||||
${LIB_EIVE_MISSION}
|
||||
PRIVATE AcsParameters.cpp
|
||||
ActuatorCmd.cpp
|
||||
FusedRotationEstimation.cpp
|
||||
Guidance.cpp
|
||||
Igrf13Model.cpp
|
||||
MultiplicativeKalmanFilter.cpp
|
||||
|
103
mission/controller/acs/FusedRotationEstimation.cpp
Normal file
103
mission/controller/acs/FusedRotationEstimation.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
#include "FusedRotationEstimation.h"
|
||||
|
||||
FusedRotationEstimation::FusedRotationEstimation(AcsParameters *acsParameters_) {
|
||||
acsParameters = acsParameters_;
|
||||
}
|
||||
|
||||
void FusedRotationEstimation::estimateFusedRotationRateSafe(
|
||||
acsctrl::SusDataProcessed *susDataProcessed, acsctrl::MgmDataProcessed *mgmDataProcessed,
|
||||
acsctrl::GyrDataProcessed *gyrDataProcessed, acsctrl::FusedRotRateData *fusedRotRateData) {
|
||||
if ((not mgmDataProcessed->mgmVecTot.isValid() and not susDataProcessed->susVecTot.isValid() and
|
||||
not fusedRotRateData->rotRateTotal.isValid()) or
|
||||
(not susDataProcessed->susVecTotDerivative.isValid() and
|
||||
not mgmDataProcessed->mgmVecTotDerivative.isValid())) {
|
||||
{
|
||||
PoolReadGuard pg(fusedRotRateData);
|
||||
std::memcpy(fusedRotRateData->rotRateOrthogonal.value, ZERO_VEC, 3 * sizeof(double));
|
||||
std::memcpy(fusedRotRateData->rotRateParallel.value, ZERO_VEC, 3 * sizeof(double));
|
||||
std::memcpy(fusedRotRateData->rotRateTotal.value, ZERO_VEC, 3 * sizeof(double));
|
||||
fusedRotRateData->setValidity(false, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (not susDataProcessed->susVecTot.isValid()) {
|
||||
estimateFusedRotationRateEclipse(gyrDataProcessed, fusedRotRateData);
|
||||
return;
|
||||
}
|
||||
|
||||
// calculate rotation around the sun
|
||||
double magSunCross[3] = {0, 0, 0};
|
||||
|
||||
VectorOperations<double>::cross(mgmDataProcessed->mgmVecTot.value,
|
||||
susDataProcessed->susVecTot.value, magSunCross);
|
||||
double magSunCrossNorm = VectorOperations<double>::norm(magSunCross, 3);
|
||||
double magNorm = VectorOperations<double>::norm(mgmDataProcessed->mgmVecTot.value, 3);
|
||||
double fusedRotRateParallel[3] = {0, 0, 0};
|
||||
if (magSunCrossNorm >
|
||||
(acsParameters->safeModeControllerParameters.sineLimitSunRotRate * magNorm)) {
|
||||
double omegaParallel =
|
||||
VectorOperations<double>::dot(mgmDataProcessed->mgmVecTotDerivative.value, magSunCross) *
|
||||
pow(magSunCrossNorm, -2);
|
||||
VectorOperations<double>::mulScalar(susDataProcessed->susVecTot.value, omegaParallel,
|
||||
fusedRotRateParallel, 3);
|
||||
} else {
|
||||
estimateFusedRotationRateEclipse(gyrDataProcessed, fusedRotRateData);
|
||||
return;
|
||||
}
|
||||
|
||||
// calculate rotation orthogonal to the sun
|
||||
double fusedRotRateOrthogonal[3] = {0, 0, 0};
|
||||
VectorOperations<double>::cross(susDataProcessed->susVecTotDerivative.value,
|
||||
susDataProcessed->susVecTot.value, fusedRotRateOrthogonal);
|
||||
VectorOperations<double>::mulScalar(
|
||||
fusedRotRateOrthogonal,
|
||||
pow(VectorOperations<double>::norm(susDataProcessed->susVecTot.value, 3), -2),
|
||||
fusedRotRateOrthogonal, 3);
|
||||
|
||||
// calculate total rotation rate
|
||||
double fusedRotRateTotal[3] = {0, 0, 0};
|
||||
VectorOperations<double>::add(fusedRotRateParallel, fusedRotRateOrthogonal, fusedRotRateTotal);
|
||||
|
||||
// store for calculation of angular acceleration
|
||||
if (gyrDataProcessed->gyrVecTot.isValid()) {
|
||||
std::memcpy(rotRateOldB, gyrDataProcessed->gyrVecTot.value, 3 * sizeof(double));
|
||||
}
|
||||
|
||||
{
|
||||
PoolReadGuard pg(fusedRotRateData);
|
||||
std::memcpy(fusedRotRateData->rotRateOrthogonal.value, fusedRotRateOrthogonal,
|
||||
3 * sizeof(double));
|
||||
std::memcpy(fusedRotRateData->rotRateParallel.value, fusedRotRateParallel, 3 * sizeof(double));
|
||||
std::memcpy(fusedRotRateData->rotRateTotal.value, fusedRotRateTotal, 3 * sizeof(double));
|
||||
fusedRotRateData->setValidity(true, true);
|
||||
}
|
||||
}
|
||||
|
||||
void FusedRotationEstimation::estimateFusedRotationRateEclipse(
|
||||
acsctrl::GyrDataProcessed *gyrDataProcessed, acsctrl::FusedRotRateData *fusedRotRateData) {
|
||||
if (not gyrDataProcessed->gyrVecTot.isValid() or
|
||||
VectorOperations<double>::norm(fusedRotRateData->rotRateTotal.value, 3) == 0) {
|
||||
{
|
||||
PoolReadGuard pg(fusedRotRateData);
|
||||
std::memcpy(fusedRotRateData->rotRateOrthogonal.value, ZERO_VEC, 3 * sizeof(double));
|
||||
std::memcpy(fusedRotRateData->rotRateParallel.value, ZERO_VEC, 3 * sizeof(double));
|
||||
std::memcpy(fusedRotRateData->rotRateTotal.value, ZERO_VEC, 3 * sizeof(double));
|
||||
fusedRotRateData->setValidity(false, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
double angAccelB[3] = {0, 0, 0};
|
||||
VectorOperations<double>::subtract(gyrDataProcessed->gyrVecTot.value, rotRateOldB, angAccelB, 3);
|
||||
double fusedRotRateTotal[3] = {0, 0, 0};
|
||||
VectorOperations<double>::add(fusedRotRateData->rotRateTotal.value, angAccelB, fusedRotRateTotal,
|
||||
3);
|
||||
{
|
||||
PoolReadGuard pg(fusedRotRateData);
|
||||
std::memcpy(fusedRotRateData->rotRateOrthogonal.value, ZERO_VEC, 3 * sizeof(double));
|
||||
fusedRotRateData->rotRateOrthogonal.setValid(false);
|
||||
std::memcpy(fusedRotRateData->rotRateParallel.value, ZERO_VEC, 3 * sizeof(double));
|
||||
fusedRotRateData->rotRateParallel.setValid(false);
|
||||
std::memcpy(fusedRotRateData->rotRateTotal.value, fusedRotRateTotal, 3 * sizeof(double));
|
||||
fusedRotRateData->rotRateTotal.setValid(true);
|
||||
}
|
||||
}
|
29
mission/controller/acs/FusedRotationEstimation.h
Normal file
29
mission/controller/acs/FusedRotationEstimation.h
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef MISSION_CONTROLLER_ACS_FUSEDROTATIONESTIMATION_H_
|
||||
#define MISSION_CONTROLLER_ACS_FUSEDROTATIONESTIMATION_H_
|
||||
|
||||
#include <fsfw/datapool/PoolReadGuard.h>
|
||||
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
||||
#include <mission/controller/acs/AcsParameters.h>
|
||||
#include <mission/controller/controllerdefinitions/AcsCtrlDefinitions.h>
|
||||
|
||||
class FusedRotationEstimation {
|
||||
public:
|
||||
FusedRotationEstimation(AcsParameters *acsParameters_);
|
||||
|
||||
void estimateFusedRotationRateSafe(acsctrl::SusDataProcessed *susDataProcessed,
|
||||
acsctrl::MgmDataProcessed *mgmDataProcessed,
|
||||
acsctrl::GyrDataProcessed *gyrDataProcessed,
|
||||
acsctrl::FusedRotRateData *fusedRotRateData);
|
||||
|
||||
protected:
|
||||
private:
|
||||
static constexpr double ZERO_VEC[3] = {0, 0, 0};
|
||||
|
||||
AcsParameters *acsParameters;
|
||||
double rotRateOldB[3] = {0, 0, 0};
|
||||
|
||||
void estimateFusedRotationRateEclipse(acsctrl::GyrDataProcessed *gyrDataProcessed,
|
||||
acsctrl::FusedRotRateData *fusedRotRateData);
|
||||
};
|
||||
|
||||
#endif /* MISSION_CONTROLLER_ACS_FUSEDROTATIONESTIMATION_H_ */
|
@ -132,6 +132,10 @@ void SensorProcessing::processMgm(const float *mgm0Value, bool mgm0valid, const
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
mgmVecTot[i] = sensorFusionNumerator[i] / sensorFusionDenominator[i];
|
||||
}
|
||||
if (VectorOperations<double>::norm(mgmVecTot, 3) != 0 and mgmDataProcessed->mgmVecTot.isValid()) {
|
||||
lowPassFilter(mgmVecTot, mgmDataProcessed->mgmVecTot.value,
|
||||
mgmParameters->mgmVectorFilterWeight);
|
||||
}
|
||||
|
||||
//-----------------------Mgm Rate Computation ---------------------------------------------------
|
||||
double mgmVecTotDerivative[3] = {0.0, 0.0, 0.0};
|
||||
@ -351,6 +355,11 @@ void SensorProcessing::processSus(
|
||||
double susVecTot[3] = {0.0, 0.0, 0.0};
|
||||
VectorOperations<double>::normalize(susMeanValue, susVecTot, 3);
|
||||
|
||||
if (VectorOperations<double>::norm(susVecTot, 3) != 0 and susDataProcessed->susVecTot.isValid()) {
|
||||
lowPassFilter(susVecTot, susDataProcessed->susVecTot.value,
|
||||
susParameters->susVectorFilterWeight);
|
||||
}
|
||||
|
||||
/* -------- Sun Derivatiative --------------------- */
|
||||
|
||||
double susVecTotDerivative[3] = {0.0, 0.0, 0.0};
|
||||
@ -363,6 +372,11 @@ void SensorProcessing::processSus(
|
||||
susVecTotDerivativeValid = true;
|
||||
}
|
||||
}
|
||||
if (VectorOperations<double>::norm(susVecTotDerivative, 3) != 0 and
|
||||
susDataProcessed->susVecTotDerivative.isValid()) {
|
||||
lowPassFilter(susVecTotDerivative, susDataProcessed->susVecTotDerivative.value,
|
||||
susParameters->susRateFilterWeight);
|
||||
}
|
||||
timeOfSavedSusDirEst = timeOfSusMeasurement;
|
||||
{
|
||||
PoolReadGuard pg(susDataProcessed);
|
||||
|
@ -9,20 +9,36 @@ SafeCtrl::SafeCtrl(AcsParameters *acsParameters_) { acsParameters = acsParameter
|
||||
|
||||
SafeCtrl::~SafeCtrl() {}
|
||||
|
||||
acs::SafeModeStrategy SafeCtrl::safeCtrlStrategy(const bool magFieldValid, const bool mekfValid,
|
||||
const bool satRotRateValid, const bool sunDirValid,
|
||||
const uint8_t mekfEnabled,
|
||||
const uint8_t dampingEnabled) {
|
||||
acs::SafeModeStrategy SafeCtrl::safeCtrlStrategy(
|
||||
const bool magFieldValid, const bool mekfValid, const bool satRotRateValid,
|
||||
const bool sunDirValid, const bool fusedRateSplitValid, const bool fusedRateTotalValid,
|
||||
const uint8_t mekfEnabled, const uint8_t gyrEnabled, const uint8_t dampingEnabled) {
|
||||
if (not magFieldValid) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_NO_MAG_FIELD_FOR_CONTROL;
|
||||
} else if (mekfEnabled and mekfValid) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_ACTIVE_MEKF;
|
||||
} else if (satRotRateValid and sunDirValid) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_WITHOUT_MEKF;
|
||||
} else if (dampingEnabled and satRotRateValid and not sunDirValid) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING;
|
||||
} else if (not dampingEnabled and satRotRateValid and not sunDirValid) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_ECLIPSE_IDELING;
|
||||
return acs::SafeModeStrategy::SAFECTRL_MEKF;
|
||||
} else if (sunDirValid) {
|
||||
if (gyrEnabled and satRotRateValid) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_GYR;
|
||||
} else if (not gyrEnabled and fusedRateSplitValid) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_SUSMGM;
|
||||
} else {
|
||||
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
|
||||
}
|
||||
} else if (not sunDirValid) {
|
||||
if (dampingEnabled) {
|
||||
if (gyrEnabled and satRotRateValid) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING_GYR;
|
||||
} else if (not gyrEnabled and satRotRateValid and fusedRateTotalValid) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_ECLIPSE_DAMPING_SUSMGM;
|
||||
} else {
|
||||
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
|
||||
}
|
||||
} else if (not dampingEnabled and satRotRateValid) {
|
||||
return acs::SafeModeStrategy::SAFECTRL_ECLIPSE_IDELING;
|
||||
} else {
|
||||
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
|
||||
}
|
||||
} else {
|
||||
return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL;
|
||||
}
|
||||
@ -43,8 +59,7 @@ void SafeCtrl::safeMekf(const double *magFieldB, const double *satRotRateB,
|
||||
errorAngle = acos(dotSun);
|
||||
|
||||
splitRotationalRate(satRotRateB, sunDirB);
|
||||
calculateRotationalRateTorque(sunDirB, sunDirRefB, errorAngle,
|
||||
acsParameters->safeModeControllerParameters.k_parallelMekf,
|
||||
calculateRotationalRateTorque(acsParameters->safeModeControllerParameters.k_parallelMekf,
|
||||
acsParameters->safeModeControllerParameters.k_orthoMekf);
|
||||
calculateAngleErrorTorque(sunDirB, sunDirRefB,
|
||||
acsParameters->safeModeControllerParameters.k_alignMekf);
|
||||
@ -57,9 +72,8 @@ void SafeCtrl::safeMekf(const double *magFieldB, const double *satRotRateB,
|
||||
calculateMagneticMoment(magMomB);
|
||||
}
|
||||
|
||||
void SafeCtrl::safeNonMekf(const double *magFieldB, const double *satRotRateB,
|
||||
const double *sunDirB, const double *sunDirRefB, double *magMomB,
|
||||
double &errorAngle) {
|
||||
void SafeCtrl::safeGyr(const double *magFieldB, const double *satRotRateB, const double *sunDirB,
|
||||
const double *sunDirRefB, double *magMomB, double &errorAngle) {
|
||||
// convert magFieldB from uT to T
|
||||
VectorOperations<double>::mulScalar(magFieldB, 1e-6, magFieldBT, 3);
|
||||
|
||||
@ -68,11 +82,10 @@ void SafeCtrl::safeNonMekf(const double *magFieldB, const double *satRotRateB,
|
||||
errorAngle = acos(dotSun);
|
||||
|
||||
splitRotationalRate(satRotRateB, sunDirB);
|
||||
calculateRotationalRateTorque(sunDirB, sunDirRefB, errorAngle,
|
||||
acsParameters->safeModeControllerParameters.k_parallelNonMekf,
|
||||
acsParameters->safeModeControllerParameters.k_orthoNonMekf);
|
||||
calculateRotationalRateTorque(acsParameters->safeModeControllerParameters.k_parallelGyr,
|
||||
acsParameters->safeModeControllerParameters.k_orthoGyr);
|
||||
calculateAngleErrorTorque(sunDirB, sunDirRefB,
|
||||
acsParameters->safeModeControllerParameters.k_alignNonMekf);
|
||||
acsParameters->safeModeControllerParameters.k_alignGyr);
|
||||
|
||||
// sum of all torques
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
@ -82,8 +95,33 @@ void SafeCtrl::safeNonMekf(const double *magFieldB, const double *satRotRateB,
|
||||
calculateMagneticMoment(magMomB);
|
||||
}
|
||||
|
||||
void SafeCtrl::safeRateDamping(const double *magFieldB, const double *satRotRateB,
|
||||
const double *sunDirRefB, double *magMomB, double &errorAngle) {
|
||||
void SafeCtrl::safeSusMgm(const double *magFieldB, const double *rotRateParallelB,
|
||||
const double *rotRateOrthogonalB, const double *sunDirB,
|
||||
const double *sunDirRefB, double *magMomB, double &errorAngle) {
|
||||
// convert magFieldB from uT to T
|
||||
VectorOperations<double>::mulScalar(magFieldB, 1e-6, magFieldBT, 3);
|
||||
|
||||
// calculate error angle between sunDirRef and sunDir
|
||||
double dotSun = VectorOperations<double>::dot(sunDirRefB, sunDirB);
|
||||
errorAngle = acos(dotSun);
|
||||
|
||||
std::memcpy(satRotRateParallelB, rotRateParallelB, sizeof(satRotRateParallelB));
|
||||
std::memcpy(satRotRateOrthogonalB, rotRateOrthogonalB, sizeof(satRotRateOrthogonalB));
|
||||
calculateRotationalRateTorque(acsParameters->safeModeControllerParameters.k_parallelSusMgm,
|
||||
acsParameters->safeModeControllerParameters.k_orthoSusMgm);
|
||||
calculateAngleErrorTorque(sunDirB, sunDirRefB,
|
||||
acsParameters->safeModeControllerParameters.k_alignSusMgm);
|
||||
|
||||
// sum of all torques
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
cmdTorque[i] = cmdAlign[i] + cmdOrtho[i] + cmdParallel[i];
|
||||
}
|
||||
|
||||
calculateMagneticMoment(magMomB);
|
||||
}
|
||||
|
||||
void SafeCtrl::safeRateDampingGyr(const double *magFieldB, const double *satRotRateB,
|
||||
const double *sunDirRefB, double *magMomB, double &errorAngle) {
|
||||
// convert magFieldB from uT to T
|
||||
VectorOperations<double>::mulScalar(magFieldB, 1e-6, magFieldBT, 3);
|
||||
|
||||
@ -91,9 +129,28 @@ void SafeCtrl::safeRateDamping(const double *magFieldB, const double *satRotRate
|
||||
errorAngle = NAN;
|
||||
|
||||
splitRotationalRate(satRotRateB, sunDirRefB);
|
||||
calculateRotationalRateTorque(sunDirRefB, sunDirRefB, errorAngle,
|
||||
acsParameters->safeModeControllerParameters.k_parallelNonMekf,
|
||||
acsParameters->safeModeControllerParameters.k_orthoNonMekf);
|
||||
calculateRotationalRateTorque(acsParameters->safeModeControllerParameters.k_parallelGyr,
|
||||
acsParameters->safeModeControllerParameters.k_orthoGyr);
|
||||
|
||||
// sum of all torques
|
||||
VectorOperations<double>::add(cmdParallel, cmdOrtho, cmdTorque, 3);
|
||||
|
||||
// calculate magnetic moment to command
|
||||
calculateMagneticMoment(magMomB);
|
||||
}
|
||||
|
||||
void SafeCtrl::safeRateDampingSusMgm(const double *magFieldB, const double *satRotRateB,
|
||||
const double *sunDirRefB, double *magMomB,
|
||||
double &errorAngle) {
|
||||
// convert magFieldB from uT to T
|
||||
VectorOperations<double>::mulScalar(magFieldB, 1e-6, magFieldBT, 3);
|
||||
|
||||
// no error angle available for eclipse
|
||||
errorAngle = NAN;
|
||||
|
||||
splitRotationalRate(satRotRateB, sunDirRefB);
|
||||
calculateRotationalRateTorque(acsParameters->safeModeControllerParameters.k_parallelSusMgm,
|
||||
acsParameters->safeModeControllerParameters.k_orthoSusMgm);
|
||||
|
||||
// sum of all torques
|
||||
VectorOperations<double>::add(cmdParallel, cmdOrtho, cmdTorque, 3);
|
||||
@ -110,9 +167,7 @@ void SafeCtrl::splitRotationalRate(const double *satRotRateB, const double *sunD
|
||||
VectorOperations<double>::subtract(satRotRateB, satRotRateParallelB, satRotRateOrthogonalB, 3);
|
||||
}
|
||||
|
||||
void SafeCtrl::calculateRotationalRateTorque(const double *sunDirB, const double *sunDirRefB,
|
||||
double &errorAngle, const double gainParallel,
|
||||
const double gainOrtho) {
|
||||
void SafeCtrl::calculateRotationalRateTorque(const double gainParallel, const double gainOrtho) {
|
||||
// calculate torque for parallel rotational rate
|
||||
VectorOperations<double>::mulScalar(satRotRateParallelB, -gainParallel, cmdParallel, 3);
|
||||
|
||||
|
@ -14,23 +14,34 @@ class SafeCtrl {
|
||||
|
||||
acs::SafeModeStrategy safeCtrlStrategy(const bool magFieldValid, const bool mekfValid,
|
||||
const bool satRotRateValid, const bool sunDirValid,
|
||||
const uint8_t mekfEnabled, const uint8_t dampingEnabled);
|
||||
const bool fusedRateSplitValid,
|
||||
const bool fusedRateTotalValid, const uint8_t mekfEnabled,
|
||||
const uint8_t gyrEnabled, const uint8_t dampingEnabled);
|
||||
|
||||
void safeMekf(const double *magFieldB, const double *satRotRateB, const double *sunDirModelI,
|
||||
const double *quatBI, const double *sunDirRefB, double *magMomB,
|
||||
double &errorAngle);
|
||||
|
||||
void safeNonMekf(const double *magFieldB, const double *satRotRateB, const double *sunDirB,
|
||||
const double *sunDirRefB, double *magMomB, double &errorAngle);
|
||||
void safeGyr(const double *magFieldB, const double *satRotRateB, const double *sunDirB,
|
||||
const double *sunDirRefB, double *magMomB, double &errorAngle);
|
||||
|
||||
void safeRateDamping(const double *magFieldB, const double *satRotRateB, const double *sunDirRefB,
|
||||
double *magMomB, double &errorAngle);
|
||||
void safeSusMgm(const double *magFieldB, const double *rotRateParallelB,
|
||||
const double *rotRateOrthogonalB, const double *sunDirB, const double *sunDirRefB,
|
||||
double *magMomB, double &errorAngle);
|
||||
|
||||
void safeRateDampingGyr(const double *magFieldB, const double *satRotRateB,
|
||||
const double *sunDirRefB, double *magMomB, double &errorAngle);
|
||||
|
||||
void safeRateDampingSusMgm(const double *magFieldB, const double *satRotRateB,
|
||||
const double *sunDirRefB, double *magMomB, double &errorAngle);
|
||||
|
||||
void splitRotationalRate(const double *satRotRateB, const double *sunDirB);
|
||||
|
||||
void calculateRotationalRateTorque(const double *sunDirB, const double *sunDirRefB,
|
||||
double &errorAngle, const double gainParallel,
|
||||
const double gainOrtho);
|
||||
void calculateRotationalRates(const double *magFieldB, const double *magRateB,
|
||||
const double *sunDirB, const double *sunRateB,
|
||||
double *fusedRotRate);
|
||||
|
||||
void calculateRotationalRateTorque(const double gainParallel, const double gainOrtho);
|
||||
|
||||
void calculateAngleErrorTorque(const double *sunDirB, const double *sunDirRefB,
|
||||
const double gainAlign);
|
||||
|
@ -18,7 +18,8 @@ enum SetIds : uint32_t {
|
||||
GPS_PROCESSED_DATA,
|
||||
MEKF_DATA,
|
||||
CTRL_VAL_DATA,
|
||||
ACTUATOR_CMD_DATA
|
||||
ACTUATOR_CMD_DATA,
|
||||
FUSED_ROTATION_RATE_DATA,
|
||||
};
|
||||
|
||||
enum PoolIds : lp_id_t {
|
||||
@ -103,6 +104,10 @@ enum PoolIds : lp_id_t {
|
||||
RW_TARGET_TORQUE,
|
||||
RW_TARGET_SPEED,
|
||||
MTQ_TARGET_DIPOLE,
|
||||
// Fused Rotation Rate
|
||||
ROT_RATE_ORTHOGONAL,
|
||||
ROT_RATE_PARALLEL,
|
||||
ROT_RATE_TOTAL,
|
||||
};
|
||||
|
||||
static constexpr uint8_t MGM_SET_RAW_ENTRIES = 6;
|
||||
@ -115,6 +120,7 @@ static constexpr uint8_t GPS_SET_PROCESSED_ENTRIES = 5;
|
||||
static constexpr uint8_t MEKF_SET_ENTRIES = 3;
|
||||
static constexpr uint8_t CTRL_VAL_SET_ENTRIES = 5;
|
||||
static constexpr uint8_t ACT_CMD_SET_ENTRIES = 3;
|
||||
static constexpr uint8_t FUSED_ROT_RATE_SET_ENTRIES = 3;
|
||||
|
||||
/**
|
||||
* @brief Raw MGM sensor data. Includes the IMTQ sensor data and actuator status.
|
||||
@ -273,6 +279,19 @@ class ActuatorCmdData : public StaticLocalDataSet<ACT_CMD_SET_ENTRIES> {
|
||||
private:
|
||||
};
|
||||
|
||||
class FusedRotRateData : public StaticLocalDataSet<FUSED_ROT_RATE_SET_ENTRIES> {
|
||||
public:
|
||||
FusedRotRateData(HasLocalDataPoolIF* hkOwner)
|
||||
: StaticLocalDataSet(hkOwner, FUSED_ROTATION_RATE_DATA) {}
|
||||
|
||||
lp_vec_t<double, 3> rotRateOrthogonal =
|
||||
lp_vec_t<double, 3>(sid.objectId, ROT_RATE_ORTHOGONAL, this);
|
||||
lp_vec_t<double, 3> rotRateParallel = lp_vec_t<double, 3>(sid.objectId, ROT_RATE_PARALLEL, this);
|
||||
lp_vec_t<double, 3> rotRateTotal = lp_vec_t<double, 3>(sid.objectId, ROT_RATE_TOTAL, this);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
} // namespace acsctrl
|
||||
|
||||
#endif /* MISSION_CONTROLLER_CONTROLLERDEFINITIONS_ACSCTRLDEFINITIONS_H_ */
|
||||
|
@ -9,6 +9,85 @@
|
||||
|
||||
namespace tcsCtrl {
|
||||
|
||||
/**
|
||||
* NOP Limit: Hard limit for device, usually from datasheet. Device damage is possible lif NOP limit
|
||||
* is exceeded.
|
||||
* OP Limit: Soft limit. Device should be switched off or TCS controller should take action if the
|
||||
* limit is exceeded to avoid reaching NOP limit
|
||||
*/
|
||||
struct TempLimits {
|
||||
TempLimits(float nopLowerLimit, float opLowerLimit, float cutOffLimit, float opUpperLimit,
|
||||
float nopUpperLimit)
|
||||
: opLowerLimit(opLowerLimit),
|
||||
opUpperLimit(opUpperLimit),
|
||||
cutOffLimit(cutOffLimit),
|
||||
nopLowerLimit(nopLowerLimit),
|
||||
nopUpperLimit(nopUpperLimit) {}
|
||||
float opLowerLimit;
|
||||
float opUpperLimit;
|
||||
float cutOffLimit;
|
||||
float nopLowerLimit;
|
||||
float nopUpperLimit;
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstraction for the state of a single thermal component
|
||||
*/
|
||||
struct ThermalState {
|
||||
uint8_t noSensorAvailableCounter;
|
||||
// Which sensor is used for this component?
|
||||
uint8_t sensorIndex = 0;
|
||||
// Is heating on for that thermal module?
|
||||
bool heating = false;
|
||||
// Which switch is being used for heating the component
|
||||
heater::Switch heaterSwitch = heater::Switch::HEATER_NONE;
|
||||
// Heater start time and end times as UNIX seconds. Please note that these times will be updated
|
||||
// when a switch command is sent, with no guarantess that the heater actually went on.
|
||||
uint32_t heaterStartTime = 0;
|
||||
uint32_t heaterEndTime = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstraction for the state of a single heater.
|
||||
*/
|
||||
struct HeaterState {
|
||||
bool switchTransition = false;
|
||||
heater::SwitchState target = heater::SwitchState::OFF;
|
||||
uint8_t heaterSwitchControlCycles = 0;
|
||||
bool trackHeaterMaxBurnTime = false;
|
||||
Countdown heaterOnMaxBurnTime;
|
||||
};
|
||||
|
||||
using HeaterSwitchStates = std::array<heater::SwitchState, heater::NUMBER_OF_SWITCHES>;
|
||||
|
||||
enum ThermalComponents : uint8_t {
|
||||
NONE = 0,
|
||||
ACS_BOARD = 1,
|
||||
MGT = 2,
|
||||
RW = 3,
|
||||
STR = 4,
|
||||
IF_BOARD = 5,
|
||||
TCS_BOARD = 6,
|
||||
OBC = 7,
|
||||
LEGACY_OBCIF_BOARD = 8,
|
||||
SBAND_TRANSCEIVER = 9,
|
||||
PCDUP60_BOARD = 10,
|
||||
PCDUACU = 11,
|
||||
PCDUPDU = 12,
|
||||
PLPCDU_BOARD = 13,
|
||||
PLOCMISSION_BOARD = 14,
|
||||
PLOCPROCESSING_BOARD = 15,
|
||||
DAC = 16,
|
||||
CAMERA = 17,
|
||||
DRO = 18,
|
||||
X8 = 19,
|
||||
HPA = 20,
|
||||
TX = 21,
|
||||
MPA = 22,
|
||||
SCEX_BOARD = 23,
|
||||
NUM_THERMAL_COMPONENTS
|
||||
};
|
||||
|
||||
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::TCS_CONTROLLER;
|
||||
static constexpr Event NO_VALID_SENSOR_TEMPERATURE = MAKE_EVENT(0, severity::MEDIUM);
|
||||
static constexpr Event NO_HEALTHY_HEATER_AVAILABLE = MAKE_EVENT(1, severity::MEDIUM);
|
||||
@ -18,6 +97,12 @@ static constexpr Event CAMERA_OVERHEATING = MAKE_EVENT(5, severity::HIGH);
|
||||
static constexpr Event PCDU_SYSTEM_OVERHEATING = MAKE_EVENT(6, severity::HIGH);
|
||||
static constexpr Event HEATER_NOT_OFF_FOR_OFF_MODE = MAKE_EVENT(7, severity::MEDIUM);
|
||||
static constexpr Event MGT_OVERHEATING = MAKE_EVENT(8, severity::HIGH);
|
||||
//! [EXPORT] : [COMMENT] P1: Module index. P2: Heater index
|
||||
static constexpr Event TCS_SWITCHING_HEATER_ON = MAKE_EVENT(9, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] P1: Module index. P2: Heater index
|
||||
static constexpr Event TCS_SWITCHING_HEATER_OFF = MAKE_EVENT(10, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] P1: Heater index. P2: Maximum burn time for heater.
|
||||
static constexpr Event TCS_HEATER_MAX_BURN_TIME_REACHED = MAKE_EVENT(11, severity::MEDIUM);
|
||||
|
||||
enum SetId : uint32_t {
|
||||
SENSOR_TEMPERATURES = 0,
|
||||
@ -25,6 +110,7 @@ enum SetId : uint32_t {
|
||||
SUS_TEMPERATURES = 2,
|
||||
COMPONENT_TEMPERATURES = 3,
|
||||
HEATER_SET = 4,
|
||||
TCS_CTRL_INFO = 5
|
||||
};
|
||||
|
||||
enum PoolIds : lp_id_t {
|
||||
@ -92,7 +178,13 @@ enum PoolIds : lp_id_t {
|
||||
TEMP_ADC_PAYLOAD_PCDU,
|
||||
|
||||
HEATER_SWITCH_LIST,
|
||||
HEATER_CURRENT
|
||||
HEATER_CURRENT,
|
||||
|
||||
HEATER_ON_FOR_COMPONENT_VEC,
|
||||
SENSOR_USED_FOR_TCS_CTRL,
|
||||
HEATER_IDX_USED_FOR_TCS_CTRL,
|
||||
HEATER_START_TIME,
|
||||
HEATER_END_TIME
|
||||
};
|
||||
|
||||
static const uint8_t ENTRIES_SENSOR_TEMPERATURE_SET = 25;
|
||||
@ -232,6 +324,29 @@ class HeaterInfo : public StaticLocalDataSet<3> {
|
||||
lp_var_t<int16_t> heaterCurrent = lp_var_t<int16_t>(sid.objectId, PoolIds::HEATER_CURRENT, this);
|
||||
};
|
||||
|
||||
class TcsCtrlInfo : public StaticLocalDataSet<6> {
|
||||
public:
|
||||
explicit TcsCtrlInfo(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, TCS_CTRL_INFO) {}
|
||||
|
||||
explicit TcsCtrlInfo(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, TCS_CTRL_INFO)) {}
|
||||
|
||||
lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS> heatingOnVec =
|
||||
lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS>(
|
||||
sid.objectId, PoolIds::HEATER_ON_FOR_COMPONENT_VEC, this);
|
||||
lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS> sensorIdxUsedForTcsCtrl =
|
||||
lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS>(sid.objectId,
|
||||
PoolIds::SENSOR_USED_FOR_TCS_CTRL, this);
|
||||
lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS> heaterSwitchIdx =
|
||||
lp_vec_t<uint8_t, tcsCtrl::NUM_THERMAL_COMPONENTS>(
|
||||
sid.objectId, PoolIds::HEATER_IDX_USED_FOR_TCS_CTRL, this);
|
||||
lp_vec_t<uint32_t, tcsCtrl::NUM_THERMAL_COMPONENTS> heaterStartTimes =
|
||||
lp_vec_t<uint32_t, tcsCtrl::NUM_THERMAL_COMPONENTS>(sid.objectId, PoolIds::HEATER_START_TIME,
|
||||
this);
|
||||
lp_vec_t<uint32_t, tcsCtrl::NUM_THERMAL_COMPONENTS> heaterEndTimes =
|
||||
lp_vec_t<uint32_t, tcsCtrl::NUM_THERMAL_COMPONENTS>(sid.objectId, PoolIds::HEATER_END_TIME,
|
||||
this);
|
||||
};
|
||||
|
||||
} // namespace tcsCtrl
|
||||
|
||||
#endif /* MISSION_CONTROLLER_CONTROLLERDEFINITIONS_THERMALCONTROLLERDEFINITIONS_H_ */
|
||||
|
@ -311,9 +311,9 @@ void ObjectFactory::createGenericHeaterComponents(GpioIF& gpioIF, PowerSwitchIF&
|
||||
heaterHandler->connectModeTreeParent(satsystem::tcs::SUBSYSTEM);
|
||||
}
|
||||
|
||||
void ObjectFactory::createThermalController(HeaterHandler& heaterHandler) {
|
||||
void ObjectFactory::createThermalController(HeaterHandler& heaterHandler, bool pollPlPcduTmp1) {
|
||||
auto* tcsCtrl = new ThermalController(objects::THERMAL_CONTROLLER, heaterHandler,
|
||||
tcs::TCS_BOARD_SHORTLY_UNAVAILABLE);
|
||||
tcs::TCS_BOARD_SHORTLY_UNAVAILABLE, pollPlPcduTmp1);
|
||||
tcsCtrl->connectModeTreeParent(satsystem::tcs::SUBSYSTEM);
|
||||
}
|
||||
void ObjectFactory::createRwAssy(PowerSwitchIF& pwrSwitcher, power::Switch_t theSwitch,
|
||||
|
@ -50,7 +50,7 @@ void produceGenericObjects(HealthTableIF** healthTable, PusTmFunnel** pusFunnel,
|
||||
void createGenericHeaterComponents(GpioIF& gpioIF, PowerSwitchIF& pwrSwitcher,
|
||||
HeaterHandler*& heaterHandler);
|
||||
|
||||
void createThermalController(HeaterHandler& heaterHandler);
|
||||
void createThermalController(HeaterHandler& heaterHandler, bool pollPlPcduTmp1);
|
||||
void createRwAssy(PowerSwitchIF& pwrSwitcher, power::Switch_t theSwitch,
|
||||
std::array<DeviceHandlerBase*, 4> rws, std::array<object_id_t, 4> rwIds);
|
||||
void createSusAssy(PowerSwitchIF& pwrSwitcher, std::array<DeviceHandlerBase*, 12> suses);
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <OBSWConfig.h>
|
||||
#include <devices/gpioIds.h>
|
||||
#include <fsfw/datapool/PoolReadGuard.h>
|
||||
#include <fsfw/tasks/TaskFactory.h>
|
||||
#include <mission/payload/RadiationSensorHandler.h>
|
||||
#include <mission/power/gsDefs.h>
|
||||
#include <mission/tcs/max1227.h>
|
||||
@ -15,6 +16,8 @@ RadiationSensorHandler::RadiationSensorHandler(object_id_t objectId, object_id_t
|
||||
if (comCookie == nullptr) {
|
||||
sif::error << "RadiationSensorHandler: Invalid com cookie" << std::endl;
|
||||
}
|
||||
// Time out immediately so we get an immediate measurement at device startup.
|
||||
measurementCd.timeOut();
|
||||
}
|
||||
|
||||
RadiationSensorHandler::~RadiationSensorHandler() {}
|
||||
@ -51,14 +54,17 @@ void RadiationSensorHandler::doShutDown() {
|
||||
}
|
||||
|
||||
ReturnValue_t RadiationSensorHandler::buildNormalDeviceCommand(DeviceCommandId_t *id) {
|
||||
if (measurementCd.isBusy()) {
|
||||
return NOTHING_TO_SEND;
|
||||
}
|
||||
switch (communicationStep) {
|
||||
case CommunicationStep::START_CONVERSION: {
|
||||
*id = RAD_SENSOR::START_CONVERSION;
|
||||
*id = radSens::START_CONVERSION;
|
||||
communicationStep = CommunicationStep::READ_CONVERSIONS;
|
||||
break;
|
||||
}
|
||||
case CommunicationStep::READ_CONVERSIONS: {
|
||||
*id = RAD_SENSOR::READ_CONVERSIONS;
|
||||
*id = radSens::READ_CONVERSIONS;
|
||||
communicationStep = CommunicationStep::START_CONVERSION;
|
||||
break;
|
||||
}
|
||||
@ -73,7 +79,7 @@ ReturnValue_t RadiationSensorHandler::buildNormalDeviceCommand(DeviceCommandId_t
|
||||
|
||||
ReturnValue_t RadiationSensorHandler::buildTransitionDeviceCommand(DeviceCommandId_t *id) {
|
||||
if (internalState == InternalState::SETUP) {
|
||||
*id = RAD_SENSOR::WRITE_SETUP;
|
||||
*id = radSens::WRITE_SETUP;
|
||||
} else {
|
||||
return NOTHING_TO_SEND;
|
||||
}
|
||||
@ -84,15 +90,19 @@ ReturnValue_t RadiationSensorHandler::buildCommandFromCommand(DeviceCommandId_t
|
||||
const uint8_t *commandData,
|
||||
size_t commandDataLen) {
|
||||
switch (deviceCommand) {
|
||||
case (RAD_SENSOR::WRITE_SETUP): {
|
||||
cmdBuffer[0] = RAD_SENSOR::SETUP_DEFINITION;
|
||||
case (radSens::WRITE_SETUP): {
|
||||
cmdBuffer[0] = radSens::SETUP_DEFINITION;
|
||||
rawPacket = cmdBuffer;
|
||||
rawPacketLen = 1;
|
||||
internalState = InternalState::CONFIGURED;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (RAD_SENSOR::START_CONVERSION): {
|
||||
case (radSens::START_CONVERSION): {
|
||||
ReturnValue_t result = gpioIF->pullHigh(gpioIds::ENABLE_RADFET);
|
||||
// Test a small delay between pulling the RADFET high and reading the sensor. As long as this
|
||||
// delay remains small enough, this should not cause scheduling issues. Do not make this
|
||||
// delay large, this device might be scheduled inside the ACS PST!
|
||||
TaskFactory::delayTask(5);
|
||||
if (result != returnvalue::OK) {
|
||||
#if OBSW_VERBOSE_LEVEL >= 1
|
||||
sif::warning
|
||||
@ -102,25 +112,25 @@ ReturnValue_t RadiationSensorHandler::buildCommandFromCommand(DeviceCommandId_t
|
||||
#endif
|
||||
}
|
||||
/* First the fifo will be reset here */
|
||||
cmdBuffer[0] = RAD_SENSOR::RESET_DEFINITION;
|
||||
cmdBuffer[1] = RAD_SENSOR::CONVERSION_DEFINITION;
|
||||
cmdBuffer[0] = radSens::RESET_DEFINITION;
|
||||
cmdBuffer[1] = radSens::CONVERSION_DEFINITION;
|
||||
rawPacket = cmdBuffer;
|
||||
rawPacketLen = 2;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case (RAD_SENSOR::READ_CONVERSIONS): {
|
||||
cmdBuffer[0] = RAD_SENSOR::DUMMY_BYTE;
|
||||
std::memset(cmdBuffer, RAD_SENSOR::DUMMY_BYTE, RAD_SENSOR::READ_SIZE);
|
||||
case (radSens::READ_CONVERSIONS): {
|
||||
cmdBuffer[0] = radSens::DUMMY_BYTE;
|
||||
std::memset(cmdBuffer, radSens::DUMMY_BYTE, radSens::READ_SIZE);
|
||||
rawPacket = cmdBuffer;
|
||||
rawPacketLen = RAD_SENSOR::READ_SIZE;
|
||||
rawPacketLen = radSens::READ_SIZE;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case RAD_SENSOR::ENABLE_DEBUG_OUTPUT: {
|
||||
case radSens::ENABLE_DEBUG_OUTPUT: {
|
||||
printPeriodicData = true;
|
||||
rawPacketLen = 0;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
case RAD_SENSOR::DISABLE_DEBUG_OUTPUT: {
|
||||
case radSens::DISABLE_DEBUG_OUTPUT: {
|
||||
rawPacketLen = 0;
|
||||
printPeriodicData = false;
|
||||
return returnvalue::OK;
|
||||
@ -132,12 +142,11 @@ ReturnValue_t RadiationSensorHandler::buildCommandFromCommand(DeviceCommandId_t
|
||||
}
|
||||
|
||||
void RadiationSensorHandler::fillCommandAndReplyMap() {
|
||||
this->insertInCommandMap(RAD_SENSOR::WRITE_SETUP);
|
||||
this->insertInCommandMap(RAD_SENSOR::START_CONVERSION);
|
||||
this->insertInCommandMap(RAD_SENSOR::ENABLE_DEBUG_OUTPUT);
|
||||
this->insertInCommandMap(RAD_SENSOR::DISABLE_DEBUG_OUTPUT);
|
||||
this->insertInCommandAndReplyMap(RAD_SENSOR::READ_CONVERSIONS, 1, &dataset,
|
||||
RAD_SENSOR::READ_SIZE);
|
||||
this->insertInCommandMap(radSens::WRITE_SETUP);
|
||||
this->insertInCommandMap(radSens::START_CONVERSION);
|
||||
this->insertInCommandMap(radSens::ENABLE_DEBUG_OUTPUT);
|
||||
this->insertInCommandMap(radSens::DISABLE_DEBUG_OUTPUT);
|
||||
this->insertInCommandAndReplyMap(radSens::READ_CONVERSIONS, 1, &dataset, radSens::READ_SIZE);
|
||||
}
|
||||
|
||||
ReturnValue_t RadiationSensorHandler::scanForReply(const uint8_t *start, size_t remainingSize,
|
||||
@ -145,11 +154,11 @@ ReturnValue_t RadiationSensorHandler::scanForReply(const uint8_t *start, size_t
|
||||
*foundId = this->getPendingCommand();
|
||||
|
||||
switch (*foundId) {
|
||||
case RAD_SENSOR::START_CONVERSION:
|
||||
case RAD_SENSOR::WRITE_SETUP:
|
||||
case radSens::START_CONVERSION:
|
||||
case radSens::WRITE_SETUP:
|
||||
*foundLen = remainingSize;
|
||||
return IGNORE_REPLY_DATA;
|
||||
case RAD_SENSOR::READ_CONVERSIONS: {
|
||||
case radSens::READ_CONVERSIONS: {
|
||||
ReturnValue_t result = gpioIF->pullLow(gpioIds::ENABLE_RADFET);
|
||||
if (result != returnvalue::OK) {
|
||||
#if OBSW_VERBOSE_LEVEL >= 1
|
||||
@ -160,8 +169,8 @@ ReturnValue_t RadiationSensorHandler::scanForReply(const uint8_t *start, size_t
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RAD_SENSOR::ENABLE_DEBUG_OUTPUT:
|
||||
case RAD_SENSOR::DISABLE_DEBUG_OUTPUT:
|
||||
case radSens::ENABLE_DEBUG_OUTPUT:
|
||||
case radSens::DISABLE_DEBUG_OUTPUT:
|
||||
sif::info << "RadiationSensorHandler::scanForReply: " << remainingSize << std::endl;
|
||||
break;
|
||||
default:
|
||||
@ -176,24 +185,27 @@ ReturnValue_t RadiationSensorHandler::scanForReply(const uint8_t *start, size_t
|
||||
ReturnValue_t RadiationSensorHandler::interpretDeviceReply(DeviceCommandId_t id,
|
||||
const uint8_t *packet) {
|
||||
switch (id) {
|
||||
case RAD_SENSOR::READ_CONVERSIONS: {
|
||||
case radSens::READ_CONVERSIONS: {
|
||||
uint8_t offset = 0;
|
||||
PoolReadGuard readSet(&dataset);
|
||||
uint16_t tempRaw = ((packet[offset] & 0x0f) << 8) | packet[offset + 1];
|
||||
dataset.temperatureCelcius = max1227::getTemperature(tempRaw);
|
||||
offset += 2;
|
||||
dataset.ain0 = (*(packet + offset) << 8) | *(packet + offset + 1);
|
||||
offset += 2;
|
||||
dataset.ain1 = (*(packet + offset) << 8) | *(packet + offset + 1);
|
||||
offset += 6;
|
||||
dataset.ain4 = (*(packet + offset) << 8) | *(packet + offset + 1);
|
||||
offset += 2;
|
||||
dataset.ain5 = (*(packet + offset) << 8) | *(packet + offset + 1);
|
||||
offset += 2;
|
||||
dataset.ain6 = (*(packet + offset) << 8) | *(packet + offset + 1);
|
||||
offset += 2;
|
||||
dataset.ain7 = (*(packet + offset) << 8) | *(packet + offset + 1);
|
||||
dataset.setValidity(true, true);
|
||||
measurementCd.resetTimer();
|
||||
{
|
||||
PoolReadGuard readSet(&dataset);
|
||||
uint16_t tempRaw = ((packet[offset] & 0x0f) << 8) | packet[offset + 1];
|
||||
dataset.temperatureCelcius = max1227::getTemperature(tempRaw);
|
||||
offset += 2;
|
||||
dataset.ain0 = (*(packet + offset) << 8) | *(packet + offset + 1);
|
||||
offset += 2;
|
||||
dataset.ain1 = (*(packet + offset) << 8) | *(packet + offset + 1);
|
||||
offset += 6;
|
||||
dataset.ain4 = (*(packet + offset) << 8) | *(packet + offset + 1);
|
||||
offset += 2;
|
||||
dataset.ain5 = (*(packet + offset) << 8) | *(packet + offset + 1);
|
||||
offset += 2;
|
||||
dataset.ain6 = (*(packet + offset) << 8) | *(packet + offset + 1);
|
||||
offset += 2;
|
||||
dataset.ain7 = (*(packet + offset) << 8) | *(packet + offset + 1);
|
||||
dataset.setValidity(true, true);
|
||||
}
|
||||
if (printPeriodicData) {
|
||||
sif::info << "Radiation sensor temperature: " << dataset.temperatureCelcius << " °C"
|
||||
<< std::dec << std::endl;
|
||||
@ -204,6 +216,12 @@ ReturnValue_t RadiationSensorHandler::interpretDeviceReply(DeviceCommandId_t id,
|
||||
sif::info << "Radiation sensor ADC value channel 6: " << dataset.ain6 << std::endl;
|
||||
sif::info << "Radiation sensor ADC value channel 7: " << dataset.ain7 << std::endl;
|
||||
}
|
||||
ReturnValue_t result =
|
||||
getHkManagerHandle()->generateHousekeepingPacket(dataset.getSid(), &dataset, true);
|
||||
if (result != returnvalue::OK) {
|
||||
// TODO: Maybe add event?
|
||||
sif::error << "Generating HK set for radiation sensor failed" << std::endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@ -220,15 +238,18 @@ uint32_t RadiationSensorHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t mo
|
||||
|
||||
ReturnValue_t RadiationSensorHandler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) {
|
||||
localDataPoolMap.emplace(RAD_SENSOR::TEMPERATURE_C, new PoolEntry<float>({0.0}));
|
||||
localDataPoolMap.emplace(RAD_SENSOR::AIN0, new PoolEntry<uint16_t>({0}));
|
||||
localDataPoolMap.emplace(RAD_SENSOR::AIN1, new PoolEntry<uint16_t>({0}));
|
||||
localDataPoolMap.emplace(RAD_SENSOR::AIN4, new PoolEntry<uint16_t>({0}));
|
||||
localDataPoolMap.emplace(RAD_SENSOR::AIN5, new PoolEntry<uint16_t>({0}));
|
||||
localDataPoolMap.emplace(RAD_SENSOR::AIN6, new PoolEntry<uint16_t>({0}));
|
||||
localDataPoolMap.emplace(RAD_SENSOR::AIN7, new PoolEntry<uint16_t>({0}));
|
||||
localDataPoolMap.emplace(radSens::TEMPERATURE_C, new PoolEntry<float>({0.0}));
|
||||
localDataPoolMap.emplace(radSens::AIN0, new PoolEntry<uint16_t>({0}));
|
||||
localDataPoolMap.emplace(radSens::AIN1, new PoolEntry<uint16_t>({0}));
|
||||
localDataPoolMap.emplace(radSens::AIN4, new PoolEntry<uint16_t>({0}));
|
||||
localDataPoolMap.emplace(radSens::AIN5, new PoolEntry<uint16_t>({0}));
|
||||
localDataPoolMap.emplace(radSens::AIN6, new PoolEntry<uint16_t>({0}));
|
||||
localDataPoolMap.emplace(radSens::AIN7, new PoolEntry<uint16_t>({0}));
|
||||
// It should normally not be necessary to enable this set, as a sample TM will be generated
|
||||
// after a measurement. If this is still enabled, sample with double the measurement frequency
|
||||
// to ensure we get all measurements.
|
||||
poolManager.subscribeForRegularPeriodicPacket(
|
||||
subdp::RegularHkPeriodicParams(dataset.getSid(), false, 20.0));
|
||||
subdp::RegularHkPeriodicParams(dataset.getSid(), false, DEFAULT_MEASUREMENT_CD_MS / 2));
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
|
@ -38,13 +38,16 @@ class RadiationSensorHandler : public DeviceHandlerBase {
|
||||
LocalDataPoolManager &poolManager) override;
|
||||
|
||||
private:
|
||||
static constexpr uint32_t DEFAULT_MEASUREMENT_CD_MS = 30 * 60 * 1000;
|
||||
|
||||
enum class CommunicationStep { START_CONVERSION, READ_CONVERSIONS };
|
||||
|
||||
enum class InternalState { OFF, POWER_SWITCHING, SETUP, CONFIGURED };
|
||||
|
||||
bool printPeriodicData = false;
|
||||
RAD_SENSOR::RadSensorDataset dataset;
|
||||
static const uint8_t MAX_CMD_LEN = RAD_SENSOR::READ_SIZE;
|
||||
radSens::RadSensorDataset dataset;
|
||||
Countdown measurementCd = Countdown(DEFAULT_MEASUREMENT_CD_MS);
|
||||
static const uint8_t MAX_CMD_LEN = radSens::READ_SIZE;
|
||||
GpioIF *gpioIF = nullptr;
|
||||
Stack5VHandler &stackHandler;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_RADSENSOR_H_
|
||||
#define MISSION_DEVICES_DEVICEDEFINITIONS_RADSENSOR_H_
|
||||
|
||||
namespace RAD_SENSOR {
|
||||
namespace radSens {
|
||||
|
||||
static const DeviceCommandId_t NONE = 0x0; // Set when no command is pending
|
||||
|
||||
@ -78,6 +78,6 @@ class RadSensorDataset : public StaticLocalDataSet<DATASET_ENTRIES> {
|
||||
lp_var_t<uint16_t> ain6 = lp_var_t<uint16_t>(sid.objectId, AIN6, this);
|
||||
lp_var_t<uint16_t> ain7 = lp_var_t<uint16_t>(sid.objectId, AIN7, this);
|
||||
};
|
||||
} // namespace RAD_SENSOR
|
||||
} // namespace radSens
|
||||
|
||||
#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_RADSENSOR_H_ */
|
||||
|
@ -39,56 +39,67 @@ ReturnValue_t pst::pstSyrlinks(FixedTimeslotTaskIF *thisSequence) {
|
||||
|
||||
// I don't think this needs to be in a PST because linux takes care of bus serialization, but
|
||||
// keep it like this for now, it works
|
||||
ReturnValue_t pst::pstI2cProcessingSystem(FixedTimeslotTaskIF *thisSequence) {
|
||||
ReturnValue_t pst::pstI2c(TmpSchedConfig schedConf, FixedTimeslotTaskIF *thisSequence) {
|
||||
// Length of a communication cycle
|
||||
uint32_t length = thisSequence->getPeriodMs();
|
||||
static_cast<void>(length);
|
||||
|
||||
// These are actually part of another bus, but this works, so keep it like this for now
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_0, length * 0.2,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_0, length * 0.2, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_0, length * 0.2, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_0, length * 0.3, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_0, length * 0.3, DeviceHandlerIF::GET_READ);
|
||||
if (schedConf.scheduleTmpDev0) {
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_0, length * 0,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_0, length * 0, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_0, length * 0.1, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_0, length * 0.1, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_0, length * 0.1, DeviceHandlerIF::GET_READ);
|
||||
}
|
||||
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_1, length * 0.4,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_1, length * 0.4, DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_1, length * 0.4, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_1, length * 0.5, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_1, length * 0.5, DeviceHandlerIF::GET_READ);
|
||||
if (schedConf.scheduleTmpDev1) {
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_1, length * 0.2,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_1, length * 0.2,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_1, length * 0.2, DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_1, length * 0.3, DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_TCS_1, length * 0.3, DeviceHandlerIF::GET_READ);
|
||||
}
|
||||
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_0, length * 0.6,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_0, length * 0.6,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_0, length * 0.6,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_0, length * 0.7,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_0, length * 0.7, DeviceHandlerIF::GET_READ);
|
||||
// damaged
|
||||
/*
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_1, length * 0.4,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_1, length * 0.4,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_1, length * 0.4,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_1, length * 0.4,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_1, length * 0.4, DeviceHandlerIF::GET_READ);
|
||||
*/
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_IF_BOARD, length * 0.8,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_IF_BOARD, length * 0.8,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_IF_BOARD, length * 0.8,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_IF_BOARD, length * 0.9,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_IF_BOARD, length * 0.9, DeviceHandlerIF::GET_READ);
|
||||
if (schedConf.schedulePlPcduDev0) {
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_0, length * 0.4,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_0, length * 0.4,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_0, length * 0.4,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_0, length * 0.5,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_0, length * 0.5,
|
||||
DeviceHandlerIF::GET_READ);
|
||||
}
|
||||
if (schedConf.schedulePlPcduDev1) {
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_1, length * 0.6,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_1, length * 0.6,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_1, length * 0.6,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_1, length * 0.7,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_PLPCDU_1, length * 0.7,
|
||||
DeviceHandlerIF::GET_READ);
|
||||
}
|
||||
|
||||
if (schedConf.scheduleIfBoardDev) {
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_IF_BOARD, length * 0.8,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_IF_BOARD, length * 0.8,
|
||||
DeviceHandlerIF::SEND_WRITE);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_IF_BOARD, length * 0.8,
|
||||
DeviceHandlerIF::GET_WRITE);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_IF_BOARD, length * 0.9,
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::TMP1075_HANDLER_IF_BOARD, length * 0.9,
|
||||
DeviceHandlerIF::GET_READ);
|
||||
}
|
||||
static_cast<void>(length);
|
||||
return thisSequence->checkSequence();
|
||||
}
|
||||
@ -580,7 +591,6 @@ ReturnValue_t pst::pstTcsAndAcs(FixedTimeslotTaskIF *thisSequence, AcsPstCfg cfg
|
||||
thisSequence->addSlot(objects::BPX_BATT_HANDLER, length * config::spiSched::SCHED_BLOCK_9_PERIOD,
|
||||
DeviceHandlerIF::GET_READ);
|
||||
|
||||
#if OBSW_ADD_RAD_SENSORS == 1
|
||||
/* Radiation sensor */
|
||||
thisSequence->addSlot(objects::RAD_SENSOR, length * config::spiSched::SCHED_BLOCK_9_PERIOD,
|
||||
DeviceHandlerIF::PERFORM_OPERATION);
|
||||
@ -592,6 +602,5 @@ ReturnValue_t pst::pstTcsAndAcs(FixedTimeslotTaskIF *thisSequence, AcsPstCfg cfg
|
||||
DeviceHandlerIF::SEND_READ);
|
||||
thisSequence->addSlot(objects::RAD_SENSOR, length * config::spiSched::SCHED_BLOCK_9_PERIOD,
|
||||
DeviceHandlerIF::GET_READ);
|
||||
#endif
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
@ -39,6 +39,16 @@ struct AcsPstCfg {
|
||||
bool scheduleStr = true;
|
||||
};
|
||||
|
||||
// Default config is for FM.
|
||||
struct TmpSchedConfig {
|
||||
bool scheduleTmpDev0 = true;
|
||||
bool scheduleTmpDev1 = true;
|
||||
bool schedulePlPcduDev0 = true;
|
||||
// damaged on FM
|
||||
bool schedulePlPcduDev1 = false;
|
||||
bool scheduleIfBoardDev = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This function creates the PST for all gomspace devices.
|
||||
* @details
|
||||
@ -51,7 +61,7 @@ ReturnValue_t pstSyrlinks(FixedTimeslotTaskIF* thisSequence);
|
||||
|
||||
ReturnValue_t pstTcsAndAcs(FixedTimeslotTaskIF* thisSequence, AcsPstCfg cfg);
|
||||
|
||||
ReturnValue_t pstI2cProcessingSystem(FixedTimeslotTaskIF* thisSequence);
|
||||
ReturnValue_t pstI2c(TmpSchedConfig schedConf, FixedTimeslotTaskIF* thisSequence);
|
||||
|
||||
/**
|
||||
* Generic test PST
|
||||
|
@ -125,6 +125,10 @@ static constexpr Event PDEC_REBOOT = event::makeEvent(SUBSYSTEM_ID, 12, severity
|
||||
//! P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash
|
||||
//! P2: First four letters of Git SHA is the last byte of P1 is set.
|
||||
static constexpr Event FIRMWARE_INFO = event::makeEvent(SUBSYSTEM_ID, 13, severity::INFO);
|
||||
//! [EXPORT] : [COMMENT] Active SD card info. SD States: 0: OFF, 1: ON, 2: MOUNTED.
|
||||
//! P1: Active SD Card Index, 0 if none is active
|
||||
//! P2: First two bytes: SD state of SD card 0, last two bytes SD state of SD card 1
|
||||
static constexpr Event ACTIVE_SD_INFO = event::makeEvent(SUBSYSTEM_ID, 14, severity::INFO);
|
||||
|
||||
class ListDirectoryCmdBase {
|
||||
public: // TODO: Packet definition for clean deserialization
|
||||
|
@ -31,12 +31,12 @@ void buildPtgInertialSequence(Subsystem& ss, ModeListEntry& eh);
|
||||
static const auto OFF = HasModesIF::MODE_OFF;
|
||||
static const auto NML = DeviceHandlerIF::MODE_NORMAL;
|
||||
|
||||
void satsystem::init() {
|
||||
void satsystem::init(bool commandPlPcdu1) {
|
||||
auto& acsSubsystem = acs::init();
|
||||
acsSubsystem.connectModeTreeParent(EIVE_SYSTEM);
|
||||
auto& payloadSubsystem = payload::init();
|
||||
payloadSubsystem.connectModeTreeParent(EIVE_SYSTEM);
|
||||
auto& tcsSubsystem = tcs::init();
|
||||
auto& tcsSubsystem = tcs::init(commandPlPcdu1);
|
||||
tcsSubsystem.connectModeTreeParent(EIVE_SYSTEM);
|
||||
auto& comSubsystem = com::init();
|
||||
comSubsystem.connectModeTreeParent(EIVE_SYSTEM);
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
namespace satsystem {
|
||||
|
||||
void init();
|
||||
void init(bool commandPlPcdu1);
|
||||
|
||||
extern EiveSystem EIVE_SYSTEM;
|
||||
|
||||
|
@ -20,7 +20,7 @@ ReturnValue_t TmpDevFdir::eventReceived(EventMessage* event) {
|
||||
// We'll try a recovery as long as defined in MAX_REBOOT.
|
||||
// Might cause some AssemblyBase cycles, so keep number low.
|
||||
// Ignored for TMP device, no way to power cycle it without going to OFF/BOOT mode.
|
||||
// handleRecovery(event->getEvent());
|
||||
setFaulty(event->getEvent());
|
||||
break;
|
||||
case DeviceHandlerIF::DEVICE_INTERPRETING_REPLY_FAILED:
|
||||
case DeviceHandlerIF::DEVICE_READING_REPLY_FAILED:
|
||||
@ -28,8 +28,10 @@ ReturnValue_t TmpDevFdir::eventReceived(EventMessage* event) {
|
||||
case DeviceHandlerIF::DEVICE_UNKNOWN_REPLY: // Some DH's generate generic reply-ids.
|
||||
case DeviceHandlerIF::DEVICE_BUILDING_COMMAND_FAILED:
|
||||
// These faults all mean that there were stupid replies from a device.
|
||||
// With now way to do a recovery, set the device to faulty immediately.
|
||||
setFaulty(event->getEvent());
|
||||
// With no way to do a recovery, set the device to faulty instead of trying a recovery.
|
||||
if (strangeReplyCount.incrementAndCheck()) {
|
||||
setFaulty(event->getEvent());
|
||||
}
|
||||
break;
|
||||
case DeviceHandlerIF::DEVICE_SENDING_COMMAND_FAILED:
|
||||
case DeviceHandlerIF::DEVICE_REQUESTING_REPLY_FAILED:
|
||||
@ -40,7 +42,9 @@ ReturnValue_t TmpDevFdir::eventReceived(EventMessage* event) {
|
||||
break;
|
||||
}
|
||||
// else
|
||||
setFaulty(event->getEvent());
|
||||
if (missedReplyCount.incrementAndCheck()) {
|
||||
setFaulty(event->getEvent());
|
||||
}
|
||||
break;
|
||||
case StorageManagerIF::GET_DATA_FAILED:
|
||||
case StorageManagerIF::STORE_DATA_FAILED:
|
||||
|
@ -10,8 +10,8 @@ TcsSubsystem satsystem::tcs::SUBSYSTEM(objects::TCS_SUBSYSTEM, 12, 24);
|
||||
namespace {
|
||||
// Alias for checker function
|
||||
const auto check = subsystem::checkInsert;
|
||||
void buildOffSequence(Subsystem& ss, ModeListEntry& eh);
|
||||
void buildNormalSequence(Subsystem& ss, ModeListEntry& eh);
|
||||
void buildOffSequence(Subsystem& ss, ModeListEntry& eh, bool commandPlPcdu1);
|
||||
void buildNormalSequence(Subsystem& ss, ModeListEntry& eh, bool commandPlPcdu1);
|
||||
} // namespace
|
||||
|
||||
static const auto OFF = HasModesIF::MODE_OFF;
|
||||
@ -27,17 +27,17 @@ auto TCS_TABLE_NORMAL_TGT = std::make_pair((NML << 24) | 1, FixedArrayList<ModeL
|
||||
auto TCS_TABLE_NORMAL_TRANS_0 = std::make_pair((NML << 24) | 2, FixedArrayList<ModeListEntry, 7>());
|
||||
auto TCS_TABLE_NORMAL_TRANS_1 = std::make_pair((NML << 24) | 3, FixedArrayList<ModeListEntry, 2>());
|
||||
|
||||
Subsystem& satsystem::tcs::init() {
|
||||
Subsystem& satsystem::tcs::init(bool commandPlPcdu1) {
|
||||
ModeListEntry entry;
|
||||
buildOffSequence(SUBSYSTEM, entry);
|
||||
buildNormalSequence(SUBSYSTEM, entry);
|
||||
buildOffSequence(SUBSYSTEM, entry, commandPlPcdu1);
|
||||
buildNormalSequence(SUBSYSTEM, entry, commandPlPcdu1);
|
||||
SUBSYSTEM.setInitialMode(OFF);
|
||||
return SUBSYSTEM;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
void buildOffSequence(Subsystem& ss, ModeListEntry& eh) {
|
||||
void buildOffSequence(Subsystem& ss, ModeListEntry& eh, bool commandPlPcdu1) {
|
||||
std::string context = "satsystem::tcs::buildOffSequence";
|
||||
auto ctxc = context.c_str();
|
||||
// Insert Helper Table
|
||||
@ -67,7 +67,9 @@ void buildOffSequence(Subsystem& ss, ModeListEntry& eh) {
|
||||
iht(objects::TMP1075_HANDLER_TCS_0, OFF, 0, TCS_TABLE_OFF_TRANS_1.second);
|
||||
iht(objects::TMP1075_HANDLER_TCS_1, OFF, 0, TCS_TABLE_OFF_TRANS_1.second);
|
||||
iht(objects::TMP1075_HANDLER_PLPCDU_0, OFF, 0, TCS_TABLE_OFF_TRANS_1.second);
|
||||
// TMP PL PCDU 1 is damaged
|
||||
if (commandPlPcdu1) {
|
||||
iht(objects::TMP1075_HANDLER_PLPCDU_1, OFF, 0, TCS_TABLE_OFF_TRANS_1.second);
|
||||
}
|
||||
iht(objects::TMP1075_HANDLER_IF_BOARD, OFF, 0, TCS_TABLE_OFF_TRANS_1.second);
|
||||
check(ss.addTable(TableEntry(TCS_TABLE_OFF_TRANS_1.first, &TCS_TABLE_OFF_TRANS_1.second)), ctxc);
|
||||
|
||||
@ -79,7 +81,7 @@ void buildOffSequence(Subsystem& ss, ModeListEntry& eh) {
|
||||
ctxc);
|
||||
}
|
||||
|
||||
void buildNormalSequence(Subsystem& ss, ModeListEntry& eh) {
|
||||
void buildNormalSequence(Subsystem& ss, ModeListEntry& eh, bool commandPlPcdu1) {
|
||||
std::string context = "satsystem::tcs::buildNormalSequence";
|
||||
auto ctxc = context.c_str();
|
||||
// Insert Helper Table
|
||||
@ -105,7 +107,9 @@ void buildNormalSequence(Subsystem& ss, ModeListEntry& eh) {
|
||||
iht(objects::TMP1075_HANDLER_TCS_0, NML, 0, TCS_TABLE_NORMAL_TRANS_0.second);
|
||||
iht(objects::TMP1075_HANDLER_TCS_1, NML, 0, TCS_TABLE_NORMAL_TRANS_0.second);
|
||||
iht(objects::TMP1075_HANDLER_PLPCDU_0, NML, 0, TCS_TABLE_NORMAL_TRANS_0.second);
|
||||
// TMP PL PCDU 1 is damaged
|
||||
if (commandPlPcdu1) {
|
||||
iht(objects::TMP1075_HANDLER_PLPCDU_1, NML, 0, TCS_TABLE_NORMAL_TRANS_0.second);
|
||||
}
|
||||
iht(objects::TMP1075_HANDLER_IF_BOARD, NML, 0, TCS_TABLE_NORMAL_TRANS_0.second);
|
||||
check(ss.addTable(TableEntry(TCS_TABLE_NORMAL_TRANS_0.first, &TCS_TABLE_NORMAL_TRANS_0.second)),
|
||||
ctxc);
|
||||
|
@ -7,7 +7,7 @@ namespace satsystem {
|
||||
namespace tcs {
|
||||
|
||||
extern TcsSubsystem SUBSYSTEM;
|
||||
Subsystem& init();
|
||||
Subsystem& init(bool commandPlPcdu1);
|
||||
|
||||
} // namespace tcs
|
||||
} // namespace satsystem
|
||||
|
@ -97,7 +97,7 @@ ReturnValue_t HeaterHandler::initialize() {
|
||||
|
||||
ReturnValue_t HeaterHandler::initializeHeaterMap() {
|
||||
for (power::Switch_t switchNr = 0; switchNr < heater::NUMBER_OF_SWITCHES; switchNr++) {
|
||||
heaterVec.push_back(HeaterWrapper(helper.heaters[switchNr], SwitchState::OFF));
|
||||
heaterVec.push_back(HeaterWrapper(helper.heaters[switchNr], heater::SwitchState::OFF));
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
@ -214,7 +214,7 @@ ReturnValue_t HeaterHandler::sendSwitchCommand(uint8_t switchNr, ReturnValue_t o
|
||||
void HeaterHandler::handleSwitchHandling() {
|
||||
for (uint8_t idx = 0; idx < heater::NUMBER_OF_SWITCHES; idx++) {
|
||||
auto health = heaterVec[idx].healthDevice->getHealth();
|
||||
if (heaterVec[idx].switchState == SwitchState::ON) {
|
||||
if (heaterVec[idx].switchState == heater::SwitchState::ON) {
|
||||
// If a heater is still on but the device was marked faulty by the operator, the SW
|
||||
// will shut down the heater
|
||||
if (health == HasHealthIF::FAULTY or health == HasHealthIF::PERMANENT_FAULTY) {
|
||||
@ -277,7 +277,7 @@ void HeaterHandler::handleSwitchOnCommand(heater::Switch heaterIdx) {
|
||||
triggerEvent(HEATER_WENT_ON, heaterIdx, 0);
|
||||
{
|
||||
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
heater.switchState = ON;
|
||||
heater.switchState = heater::SwitchState::ON;
|
||||
}
|
||||
EventManagerIF::triggerEvent(helper.heaters[heaterIdx].first->getObjectId(), MODE_INFO,
|
||||
MODE_ON, 0);
|
||||
@ -326,10 +326,10 @@ void HeaterHandler::handleSwitchOffCommand(heater::Switch heaterIdx) {
|
||||
}
|
||||
if (result == returnvalue::OK) {
|
||||
// Check whether switch is already off
|
||||
if (getSwitchState(heaterIdx) == SwitchState::ON) {
|
||||
if (getSwitchState(heaterIdx) == heater::SwitchState::ON) {
|
||||
{
|
||||
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
heater.switchState = OFF;
|
||||
heater.switchState = heater::SwitchState::OFF;
|
||||
}
|
||||
triggerEvent(HEATER_WENT_OFF, heaterIdx, 0);
|
||||
} else {
|
||||
@ -356,15 +356,15 @@ void HeaterHandler::handleSwitchOffCommand(heater::Switch heaterIdx) {
|
||||
heater.cmdActive = false;
|
||||
}
|
||||
|
||||
HeaterHandler::SwitchState HeaterHandler::getSwitchState(heater::Switch switchNr) const {
|
||||
heater::SwitchState HeaterHandler::getSwitchState(heater::Switch switchNr) const {
|
||||
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
return heaterVec.at(switchNr).switchState;
|
||||
}
|
||||
|
||||
ReturnValue_t HeaterHandler::switchHeater(heater::Switch heater, SwitchState switchState) {
|
||||
if (switchState == SwitchState::ON) {
|
||||
ReturnValue_t HeaterHandler::switchHeater(heater::Switch heater, heater::SwitchState switchState) {
|
||||
if (switchState == heater::SwitchState::ON) {
|
||||
return sendSwitchCommand(heater, PowerSwitchIF::SWITCH_ON);
|
||||
} else if (switchState == SwitchState::OFF) {
|
||||
} else if (switchState == heater::SwitchState::OFF) {
|
||||
return sendSwitchCommand(heater, PowerSwitchIF::SWITCH_OFF);
|
||||
}
|
||||
return returnvalue::FAILED;
|
||||
@ -373,10 +373,10 @@ ReturnValue_t HeaterHandler::switchHeater(heater::Switch heater, SwitchState swi
|
||||
void HeaterHandler::announceMode(bool recursive) {
|
||||
triggerEvent(MODE_INFO, mode, submode);
|
||||
|
||||
std::array<SwitchState, 8> states;
|
||||
std::array<heater::SwitchState, 8> states;
|
||||
getAllSwitchStates(states);
|
||||
for (unsigned idx = 0; idx < helper.heaters.size(); idx++) {
|
||||
if (states[idx] == ON) {
|
||||
if (states[idx] == heater::SwitchState::ON) {
|
||||
EventManagerIF::triggerEvent(helper.heaters[idx].first->getObjectId(), MODE_INFO, MODE_ON, 0);
|
||||
} else {
|
||||
EventManagerIF::triggerEvent(helper.heaters[idx].first->getObjectId(), MODE_INFO, MODE_OFF,
|
||||
@ -405,7 +405,7 @@ ModeTreeChildIF& HeaterHandler::getModeTreeChildIF() { return *this; }
|
||||
|
||||
object_id_t HeaterHandler::getObjectId() const { return SystemObject::getObjectId(); }
|
||||
|
||||
ReturnValue_t HeaterHandler::getAllSwitchStates(std::array<SwitchState, 8>& statesBuf) {
|
||||
ReturnValue_t HeaterHandler::getAllSwitchStates(std::array<heater::SwitchState, 8>& statesBuf) {
|
||||
{
|
||||
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
if (mg.getLockResult() != returnvalue::OK) {
|
||||
@ -419,13 +419,13 @@ ReturnValue_t HeaterHandler::getAllSwitchStates(std::array<SwitchState, 8>& stat
|
||||
}
|
||||
|
||||
bool HeaterHandler::allSwitchesOff() {
|
||||
bool allSwitchesOrd = false;
|
||||
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||
/* Or all switches. As soon one switch is on, allSwitchesOrd will be true */
|
||||
for (power::Switch_t switchNr = 0; switchNr < heater::NUMBER_OF_SWITCHES; switchNr++) {
|
||||
allSwitchesOrd = allSwitchesOrd || heaterVec.at(switchNr).switchState;
|
||||
if (heaterVec.at(switchNr).switchState == heater::SwitchState::ON) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return !allSwitchesOrd;
|
||||
return true;
|
||||
}
|
||||
|
||||
MessageQueueId_t HeaterHandler::getCommandQueue() const { return commandQueue->getId(); }
|
||||
@ -440,7 +440,7 @@ ReturnValue_t HeaterHandler::getSwitchState(uint8_t switchNr) const {
|
||||
if (switchNr > 7) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (getSwitchState(static_cast<heater::Switch>(switchNr)) == SwitchState::ON) {
|
||||
if (getSwitchState(static_cast<heater::Switch>(switchNr)) == heater::SwitchState::ON) {
|
||||
return PowerSwitchIF::SWITCH_ON;
|
||||
}
|
||||
return PowerSwitchIF::SWITCH_OFF;
|
||||
|
@ -60,7 +60,6 @@ class HeaterHandler : public ExecutableObjectIF,
|
||||
static const ReturnValue_t COMMAND_ALREADY_WAITING = MAKE_RETURN_CODE(0xA5);
|
||||
|
||||
enum CmdSourceParam : uint8_t { INTERNAL = 0, EXTERNAL = 1 };
|
||||
enum SwitchState : uint8_t { ON = 1, OFF = 0 };
|
||||
|
||||
/** Device command IDs */
|
||||
static const DeviceCommandId_t SWITCH_HEATER = 0x0;
|
||||
@ -69,14 +68,14 @@ class HeaterHandler : public ExecutableObjectIF,
|
||||
PowerSwitchIF* mainLineSwitcherObjectId, power::Switch_t mainLineSwitch);
|
||||
|
||||
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent) override;
|
||||
ReturnValue_t getAllSwitchStates(std::array<SwitchState, 8>& statesBuf);
|
||||
ReturnValue_t getAllSwitchStates(std::array<heater::SwitchState, 8>& statesBuf);
|
||||
|
||||
virtual ~HeaterHandler();
|
||||
|
||||
protected:
|
||||
enum SwitchAction : uint8_t { SET_SWITCH_OFF, SET_SWITCH_ON, NONE };
|
||||
|
||||
ReturnValue_t switchHeater(heater::Switch heater, SwitchState switchState);
|
||||
ReturnValue_t switchHeater(heater::Switch heater, heater::SwitchState switchState);
|
||||
HasHealthIF::HealthState getHealth(heater::Switch heater);
|
||||
|
||||
ReturnValue_t performOperation(uint8_t operationCode = 0) override;
|
||||
@ -121,14 +120,14 @@ class HeaterHandler : public ExecutableObjectIF,
|
||||
* @param mainSwitchCountdown Sets timeout to wait for main switch being set on.
|
||||
*/
|
||||
struct HeaterWrapper {
|
||||
HeaterWrapper(HeaterPair pair, SwitchState initState)
|
||||
HeaterWrapper(HeaterPair pair, heater::SwitchState initState)
|
||||
: healthDevice(pair.first), gpioId(pair.second), switchState(initState) {}
|
||||
HealthDevice* healthDevice = nullptr;
|
||||
gpioId_t gpioId = gpio::NO_GPIO;
|
||||
SwitchAction action = SwitchAction::NONE;
|
||||
MessageQueueId_t replyQueue = MessageQueueIF::NO_QUEUE;
|
||||
bool cmdActive = false;
|
||||
SwitchState switchState = SwitchState::OFF;
|
||||
heater::SwitchState switchState = heater::SwitchState::OFF;
|
||||
bool waitMainSwitchOn = false;
|
||||
Countdown mainSwitchCountdown;
|
||||
};
|
||||
@ -177,7 +176,7 @@ class HeaterHandler : public ExecutableObjectIF,
|
||||
* @brief Returns the state of a switch (ON - true, or OFF - false).
|
||||
* @param switchNr The number of the switch to check.
|
||||
*/
|
||||
SwitchState getSwitchState(heater::Switch switchNr) const;
|
||||
heater::SwitchState getSwitchState(heater::Switch switchNr) const;
|
||||
|
||||
/**
|
||||
* @brief This function runs commands waiting for execution.
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <OBSWConfig.h>
|
||||
#include <fsfw/datapool/PoolReadGuard.h>
|
||||
#include <mission/tcs/Tmp1075Definitions.h>
|
||||
#include <mission/tcs/Tmp1075Handler.h>
|
||||
|
||||
@ -11,14 +12,12 @@ Tmp1075Handler::Tmp1075Handler(object_id_t objectId, object_id_t comIF, CookieIF
|
||||
|
||||
Tmp1075Handler::~Tmp1075Handler() {}
|
||||
|
||||
void Tmp1075Handler::doStartUp() {
|
||||
if (getMode() == _MODE_START_UP) {
|
||||
setMode(MODE_ON);
|
||||
}
|
||||
}
|
||||
void Tmp1075Handler::doStartUp() { setMode(MODE_ON); }
|
||||
|
||||
void Tmp1075Handler::doShutDown() {
|
||||
communicationStep = CommunicationStep::START_ADC_CONVERSION;
|
||||
PoolReadGuard pg(&dataset);
|
||||
dataset.setValidity(false, true);
|
||||
setMode(_MODE_POWER_DOWN);
|
||||
}
|
||||
|
||||
@ -134,12 +133,14 @@ ReturnValue_t Tmp1075Handler::initializeLocalDataPool(localpool::DataPool &local
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void Tmp1075Handler::setModeNormal() { setMode(_MODE_TO_NORMAL); }
|
||||
|
||||
ReturnValue_t Tmp1075Handler::setHealth(HealthState health) {
|
||||
if (health != FAULTY and health != PERMANENT_FAULTY and health != HEALTHY and
|
||||
health != EXTERNAL_CONTROL) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
// Required because we do not have an assembly.
|
||||
if (health == FAULTY or health == PERMANENT_FAULTY) {
|
||||
setMode(_MODE_SHUT_DOWN);
|
||||
}
|
||||
return DeviceHandlerBase::setHealth(health);
|
||||
}
|
||||
|
@ -20,8 +20,6 @@ class Tmp1075Handler : public DeviceHandlerBase {
|
||||
Tmp1075Handler(object_id_t objectId, object_id_t comIF, CookieIF *comCookie);
|
||||
virtual ~Tmp1075Handler();
|
||||
|
||||
void setModeNormal();
|
||||
|
||||
protected:
|
||||
void doStartUp() override;
|
||||
void doShutDown() override;
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <cstdint>
|
||||
|
||||
namespace heater {
|
||||
|
||||
enum Switch : uint8_t {
|
||||
HEATER_0_PLOC_PROC_BRD,
|
||||
HEATER_1_PCDU_PDU,
|
||||
@ -13,9 +14,13 @@ enum Switch : uint8_t {
|
||||
HEATER_5_STR,
|
||||
HEATER_6_DRO,
|
||||
HEATER_7_S_BAND,
|
||||
NUMBER_OF_SWITCHES
|
||||
NUMBER_OF_SWITCHES = 8,
|
||||
HEATER_NONE = 0xff
|
||||
};
|
||||
}
|
||||
|
||||
enum SwitchState : uint8_t { ON = 1, OFF = 0 };
|
||||
|
||||
} // namespace heater
|
||||
|
||||
namespace tcs {
|
||||
|
||||
|
2
tmtc
2
tmtc
Submodule tmtc updated: 18304c31fa...cbcc06ede7
@ -30,7 +30,8 @@ TEST_CASE("Thermal Controller", "[ThermalController]") {
|
||||
|
||||
// testEnvironment::initialize();
|
||||
|
||||
ThermalController controller(THERMAL_CONTROLLER_ID, *heaterHandler, tcsBrdShortlyUnavailable);
|
||||
ThermalController controller(THERMAL_CONTROLLER_ID, *heaterHandler, tcsBrdShortlyUnavailable,
|
||||
true);
|
||||
ReturnValue_t result = controller.initialize();
|
||||
REQUIRE(result == returnvalue::OK);
|
||||
|
||||
|
Reference in New Issue
Block a user