diff --git a/.idea/cmake.xml b/.idea/cmake.xml
index 3be3a2b0..eff02c30 100644
--- a/.idea/cmake.xml
+++ b/.idea/cmake.xml
@@ -2,7 +2,7 @@
-
+
@@ -10,6 +10,7 @@
+
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 34e7fa34..3f151a03 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,9 +16,277 @@ will consitute of a breaking change warranting a new major release:
# [unreleased]
-# [v4.0.0] to be released
+## Changed
-# [v3.1.0] to be released
+- Relaxed SUS FDIR. The devices have shown to be glitchy in orbit, but still seem to deliver
+ sensible raw values most of the time. Some further testing is necessary, but some changes in the
+ code should cause the SUS devices to remain healthy for now.
+
+# [v6.3.0] 2023-08-03
+
+## Fixed
+
+- Small SCEX fix: The temperatur check option was not passed
+ on for commands with a user data size larger than 1.
+- SCEX: Properly check whether filesystem is usable for filesystem checks.
+- ACS Controller strategy is now actually written to the dataset for detumbling.
+- During detumble the fused rotation rate is now calculated.
+- Detumbling is now exited when its exit value is undercut and not its entry value.
+- Rotation rate of last cycle is now stored in all cases for the fused rotational rate
+ calculation.
+- Fused rotation rate estimation during eclipse can be disabled. This will also prevent
+ detumbling during eclipse, as no relevant rotational rate is available for now.
+- `EiveSystem`: Add a small delay between triggering an event for FDIR reboots and sending the
+ command to the core controller.
+- PL PDU: Fixed bounds checking logic. Bound checks will only be performed for modules which are
+ enabled.
+
+## Changed
+
+- SCEX: Only perform filesystem checks when not in OFF mode.
+- The `EiveSystem` now only sends reboot commands targetting the same image.
+- Added 200 ms delay between switching HPA/MPA/TX/X8 and DRO GPIO pin OFF.
+- PL PCDU ADC set is now automatically enabled for `NORMAL` mode transitions. It is automatically
+ disabled for `OFF` mode transitions.
+
+## Added
+
+- PL PCDU for EM build.
+- SCEX: Add warning event if filesystem is unusable.
+
+# [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.
+- Improvement in FSFW: HK generation is now countdown based.
+
+## 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
+
+- The firmware information event was not triggered even when possible because of an ordering
+ bug in the initializer function.
+- Empty dumps (no TM in time range) will now correctly be completed immediately
+
+## Changed
+
+- PTME was always reset on submode changes. The reset will now only be performed if the actual data
+ rate changes.
+- Add back ACS board code for the EM. Now that the radiation sensor was removed, the image switching
+ issue has disappeared and adding back the ACS board is worth it for the GPS timekeeping.
+
+# [v5.1.0] 2023-06-28
+
+- `eive-tmtc` version v5.1.0
+
+## Changed
+
+- Persistent TM store dumps are now performed in chronological order.
+- Increase Syrlinks RX HK rate to 5.0 seconds during a pass.
+- Various robustness improvements for the heater handler. The heater handler will now only
+ process the command queue if it is not busy with switch commanding which reduces the amount
+ of possible bugs.
+- The heater handler is only able to process messages stricly sequentially now but is scheduled
+ twice in a 0.5 second slot so something like a consecutive heater ON or OFF command can still
+ be handled relatively quickly.
+
+## Added
+
+- Sequence counters for PUS and CFDP packets are now stored persistently across graceful reboots.
+- The PUS packet message type counter will now be incremented properly for each PUS service.
+- Internal error reporter set is now enabled by default and generated every 120 seconds.
+
+# [v5.0.0] 2023-06-26
+
+v3.3.1 and all following version will now be moved to v5.0.0 with the additional changes listed
+here. This was done because the firmware update (v4.0.0) is not working right now and it is not
+known when and how it will be fixed. Because of that, all updates to make the SW work with the new
+firmware, which are limited to a few files will be moved to a dev branch so regular development
+compatible to the old firmware can continue.
+
+TLDR: This version is compatible to the old firmware and some changes which only work with the new
+firmware have been reverted.
+
+## Changed
+
+- Added `sync` syscall in graceful shutdown handler
+- Graceful shutdown is now performed by the reboot watchdog
+- There is now a separate file for the total reboot counter. The reboot watchdog has its own local
+ counters to determine whether a reboot is necessary.
+
+# [v4.0.1] 2023-06-24
+
+## Fixed
+
+- `PusLiveDemux` packet demultiplexing bugfix where the demultiplexing did not work when there was
+ only one destination available.
+
+# [v4.0.0] 2023-06-22
+
+- `eive-tmtc` version v5.0.0
+- `q7s-package` version v3.1.1
+
+## Fixed
+
+- Important bugfixes for PTME. See `q7s-package` CHANGELOG.
+- TCS fixes: Set temperature values to invalid value for MAX31865 RTD handler, SUS handler
+ and STR handler. Also set dataset to invakid for RTD handler.
+- Fixed H parameter in SUS converter from 1 mm to 2.5 mm.
+
+## Changed
+
+- Removed PTME busy/ready signals. Those were not used anyway because register reads are used now.
+- APB bus access busy checking is not done anymore as this is performed by the bus itself now.
+- Core controller will now announce version and image information event in addition to reboot
+ event in the `inititalize` function.
+- Core controller will now try to request and announce the firmware version in addition to the
+ OBSW version as well.
+- Added core controller action to read reboot mechansm information
+- GNSS reset pin will now only be asserted for 5 ms instead of 100 ms.
+
+## Added
+
+- Added PL I2C reset pin. It is not used/connected for now but could be used for FDIR procedures to
+ restore the PL I2C.
+- Core controller now announces firmware version as well when requesting a version info event
+
+# [v3.3.1] 2023-06-22
+
+## Fixed
+
+- `PusLiveDemux` packet demultiplexing bugfix where the demultiplexing did not work when there was
+ only one destination available.
+
+## Fixed
+
+- Fixed H parameter in SUS converter from 1 mm to 2.5 mm.
+
+# [v3.3.0] 2023-06-21
+
+Like v3.2.0 but without the custom FM changes related to VC0.
+
+# [v3.2.0] 2023-06-21
+
+## Fixed
+
+- Fix sun vector calculation
+- SUS total vector was not reset to being a zero vector during eclipse due to a wrong memcpy
+ length.
+
+## Changed
+
+- Reverted all changes related to VC0 handling to avoid FM bug possibly related to FPGA bug.
+
+# [v3.1.1] 2023-06-14
+
+## Fixed
+
+- TMP1075 bugfix where negative temperatures could not be measured because of a two's-complement
+ conversion bug.
+
+# [v3.1.0] 2023-06-14
+
+- `eive-tmtc` version v4.1.0
## Fixed
@@ -27,11 +295,12 @@ will consitute of a breaking change warranting a new major release:
## Changed
-- Relaxed SUS FDIR. The devices have shown to be glitchy in orbit, but still seem to deliver
- sensible raw values most of the time. Some further testing is necessary, but some changes in the
- code should cause the SUS devices to remain healthy for now.
- Increase number of allowed parallel HK commands to 16
+## Added
+
+- Added `CONFIG_SET`, `MAN_HEATER_ON` and `MAN_HEATER_OFF` support for the BPX battery handler
+
# [v3.0.0] 2023-06-11
- `eive-tmtc` version v4.0.0
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8256dc27..908c89ac 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -9,8 +9,8 @@
# ##############################################################################
cmake_minimum_required(VERSION 3.13)
-set(OBSW_VERSION_MAJOR 3)
-set(OBSW_VERSION_MINOR 0)
+set(OBSW_VERSION_MAJOR 6)
+set(OBSW_VERSION_MINOR 3)
set(OBSW_VERSION_REVISION 0)
# set(CMAKE_VERBOSE TRUE)
@@ -93,7 +93,7 @@ set(OBSW_ADD_BPX_BATTERY_HANDLER
1
CACHE STRING "Add BPX battery module")
set(OBSW_ADD_STAR_TRACKER
- ${INIT_VAL}
+ 1
CACHE STRING "Add Startracker module")
set(OBSW_ADD_SUN_SENSORS
${INIT_VAL}
@@ -105,7 +105,7 @@ set(OBSW_ADD_THERMAL_TEMP_INSERTER
${OBSW_Q7S_EM}
CACHE STRING "Add thermal sensor temperature inserter")
set(OBSW_ADD_ACS_BOARD
- ${INIT_VAL}
+ 1
CACHE STRING "Add ACS board module")
set(OBSW_ADD_GPS_CTRL
${INIT_VAL}
@@ -144,13 +144,13 @@ set(OBSW_ADD_RAD_SENSORS
${INIT_VAL}
CACHE STRING "Add Rad Sensor module")
set(OBSW_ADD_PL_PCDU
- ${INIT_VAL}
+ 1
CACHE STRING "Add Payload PCDU modukle")
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
diff --git a/README.md b/README.md
index 6b06283c..ce57c33f 100644
--- a/README.md
+++ b/README.md
@@ -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
diff --git a/bsp_hosted/ObjectFactory.cpp b/bsp_hosted/ObjectFactory.cpp
index dd88d552..4873bc58 100644
--- a/bsp_hosted/ObjectFactory.cpp
+++ b/bsp_hosted/ObjectFactory.cpp
@@ -68,7 +68,7 @@ void ObjectFactory::produce(void* args) {
#endif
auto sdcMan = new DummySdCardManager("/tmp");
ObjectFactory::produceGenericObjects(nullptr, &pusFunnel, &cfdpFunnel, *sdcMan, &ipcStore,
- &tmStore, persistentStores, 120);
+ &tmStore, persistentStores, 120, enableHkSets);
new TmFunnelHandler(objects::LIVE_TM_TASK, *pusFunnel, *cfdpFunnel);
auto* dummyGpioIF = new DummyGpioIF();
@@ -113,7 +113,7 @@ void ObjectFactory::produce(void* args) {
if (heaterHandler == nullptr) {
sif::error << "HeaterHandler could not be created" << std::endl;
} else {
- ObjectFactory::createThermalController(*heaterHandler);
+ ObjectFactory::createThermalController(*heaterHandler, true);
}
new TestTask(objects::TEST_TASK);
}
diff --git a/bsp_hosted/fsfwconfig/events/translateEvents.cpp b/bsp_hosted/fsfwconfig/events/translateEvents.cpp
index 79a828f2..98c5035f 100644
--- a/bsp_hosted/fsfwconfig/events/translateEvents.cpp
+++ b/bsp_hosted/fsfwconfig/events/translateEvents.cpp
@@ -1,7 +1,7 @@
/**
- * @brief Auto-generated event translation file. Contains 296 translations.
+ * @brief Auto-generated event translation file. Contains 303 translations.
* @details
- * Generated on: 2023-06-13 07:54:32
+ * Generated on: 2023-08-03 13:36:37
*/
#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";
@@ -260,6 +261,7 @@ const char *TX_OFF_STRING = "TX_OFF";
const char *MISSING_PACKET_STRING = "MISSING_PACKET";
const char *EXPERIMENT_TIMEDOUT_STRING = "EXPERIMENT_TIMEDOUT";
const char *MULTI_PACKET_COMMAND_DONE_STRING = "MULTI_PACKET_COMMAND_DONE";
+const char *FS_UNUSABLE_STRING = "FS_UNUSABLE";
const char *SET_CONFIGFILEVALUE_FAILED_STRING = "SET_CONFIGFILEVALUE_FAILED";
const char *GET_CONFIGFILEVALUE_FAILED_STRING = "GET_CONFIGFILEVALUE_FAILED";
const char *INSERT_CONFIGFILEVALUE_FAILED_STRING = "INSERT_CONFIGFILEVALUE_FAILED";
@@ -277,6 +279,8 @@ const char *INDIVIDUAL_BOOT_COUNTS_STRING = "INDIVIDUAL_BOOT_COUNTS";
const char *TRYING_I2C_RECOVERY_STRING = "TRYING_I2C_RECOVERY";
const char *I2C_REBOOT_STRING = "I2C_REBOOT";
const char *PDEC_REBOOT_STRING = "PDEC_REBOOT";
+const char *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";
@@ -285,6 +289,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 +579,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):
@@ -814,6 +823,8 @@ const char *translateEvents(Event event) {
return EXPERIMENT_TIMEDOUT_STRING;
case (13802):
return MULTI_PACKET_COMMAND_DONE_STRING;
+ case (13803):
+ return FS_UNUSABLE_STRING;
case (13901):
return SET_CONFIGFILEVALUE_FAILED_STRING;
case (13902):
@@ -848,6 +859,10 @@ const char *translateEvents(Event event) {
return I2C_REBOOT_STRING;
case (14012):
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):
@@ -864,6 +879,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):
diff --git a/bsp_hosted/fsfwconfig/objects/translateObjects.cpp b/bsp_hosted/fsfwconfig/objects/translateObjects.cpp
index 68b13d3b..bd5ef90f 100644
--- a/bsp_hosted/fsfwconfig/objects/translateObjects.cpp
+++ b/bsp_hosted/fsfwconfig/objects/translateObjects.cpp
@@ -2,7 +2,7 @@
* @brief Auto-generated object translation file.
* @details
* Contains 171 translations.
- * Generated on: 2023-06-13 07:54:32
+ * Generated on: 2023-08-03 13:36:37
*/
#include "translateObjects.h"
diff --git a/bsp_q7s/CMakeLists.txt b/bsp_q7s/CMakeLists.txt
index cf8fcacd..e3232363 100644
--- a/bsp_q7s/CMakeLists.txt
+++ b/bsp_q7s/CMakeLists.txt
@@ -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)
diff --git a/bsp_q7s/boardconfig/busConf.h b/bsp_q7s/boardconfig/busConf.h
index 4fd15258..dc3779a7 100644
--- a/bsp_q7s/boardconfig/busConf.h
+++ b/bsp_q7s/boardconfig/busConf.h
@@ -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";
@@ -23,6 +26,7 @@ static constexpr char UART_SCEX_DEV[] = "/dev/scex";
static constexpr char UIO_PDEC_REGISTERS[] = "/dev/uio_pdec_regs";
static constexpr char UIO_PTME[] = "/dev/uio_ptme";
static constexpr char UIO_PDEC_CONFIG_MEMORY[] = "/dev/uio_pdec_cfg_mem";
+static constexpr char UIO_SYS_ROM[] = "/dev/uio_sys_rom";
static constexpr char UIO_PDEC_RAM[] = "/dev/uio_pdec_ram";
static constexpr char UIO_PDEC_IRQ[] = "/dev/uio_pdec_irq";
static constexpr int MAP_ID_PTME_CONFIG = 3;
@@ -57,6 +61,7 @@ static constexpr char GYRO_0_ENABLE[] = "enable_gyro_0";
static constexpr char GYRO_2_ENABLE[] = "enable_gyro_2";
static constexpr char GNSS_SELECT[] = "gnss_mux_select";
static constexpr char GNSS_MUX_SELECT[] = "gnss_mux_select";
+static constexpr char PL_I2C_ARESETN[] = "pl_i2c_aresetn";
static constexpr char HEATER_0[] = "heater0";
static constexpr char HEATER_1[] = "heater1";
@@ -82,14 +87,12 @@ 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";
static constexpr char RS485_EN_TX_CLOCK[] = "tx_clock_enable_ltc2872";
diff --git a/bsp_q7s/boardtest/Q7STestTask.cpp b/bsp_q7s/boardtest/Q7STestTask.cpp
index 50a34284..03805fde 100644
--- a/bsp_q7s/boardtest/Q7STestTask.cpp
+++ b/bsp_q7s/boardtest/Q7STestTask.cpp
@@ -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;
}
diff --git a/bsp_q7s/core/CMakeLists.txt b/bsp_q7s/core/CMakeLists.txt
index b726885b..33550144 100644
--- a/bsp_q7s/core/CMakeLists.txt
+++ b/bsp_q7s/core/CMakeLists.txt
@@ -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)
diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp
index 76460aa5..e1b48fd2 100644
--- a/bsp_q7s/core/CoreController.cpp
+++ b/bsp_q7s/core/CoreController.cpp
@@ -4,6 +4,7 @@
#include
#include
#include
+#include
#include "commonConfig.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
@@ -22,6 +23,7 @@
#include
#include
+#include "bsp_q7s/boardconfig/busConf.h"
#include "bsp_q7s/fs/SdCardManager.h"
#include "bsp_q7s/memory/scratchApi.h"
#include "bsp_q7s/xadc/Xadc.h"
@@ -154,21 +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();
-
- triggerEvent(core::REBOOT_SW, CURRENT_CHIP, CURRENT_COPY);
EventManagerIF *eventManager =
ObjectManager::instance()->get(objects::EVENT_MANAGER);
if (eventManager == nullptr or eventQueue == nullptr) {
@@ -185,7 +178,20 @@ ReturnValue_t CoreController::initialize() {
if (result != returnvalue::OK) {
sif::warning << "Subscribing for GPS GPS_FIX_CHANGE event failed" << std::endl;
}
- return returnvalue::OK;
+ triggerEvent(core::REBOOT_SW, CURRENT_CHIP, CURRENT_COPY);
+ announceCurrentImageInfo();
+ announceVersionInfo();
+ SdCardManager::SdStatePair sdStates;
+ sdcMan->getSdCardsStatus(sdStates);
+ announceSdInfo(sdStates);
+ sdStateMachine();
+ result = scratch::writeNumber(scratch::ALLOC_FAILURE_COUNT, 0);
+ if (result != returnvalue::OK) {
+ sif::warning << "CoreController::initialize: Setting up alloc failure "
+ "count failed"
+ << std::endl;
+ }
+ return result;
}
ReturnValue_t CoreController::initializeAfterTaskCreation() {
@@ -210,19 +216,7 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_
using namespace core;
switch (actionId) {
case (ANNOUNCE_VERSION): {
- uint32_t p1 = (common::OBSW_VERSION_MAJOR << 24) | (common::OBSW_VERSION_MINOR << 16) |
- (common::OBSW_VERSION_REVISION << 8);
- uint32_t p2 = 0;
- if (strcmp("", common::OBSW_VERSION_CST_GIT_SHA1) != 0) {
- p1 |= 1;
- auto shaAsStr = std::string(common::OBSW_VERSION_CST_GIT_SHA1);
- size_t posDash = shaAsStr.find("-");
- auto gitHash = shaAsStr.substr(posDash + 2, 4);
- // Only copy first 4 letters of git hash
- memcpy(&p2, gitHash.c_str(), 4);
- }
-
- triggerEvent(VERSION_INFO, p1, p2);
+ announceVersionInfo();
return HasActionsIF::EXECUTION_FINISHED;
}
case (ANNOUNCE_BOOT_COUNTS): {
@@ -230,7 +224,7 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_
return HasActionsIF::EXECUTION_FINISHED;
}
case (ANNOUNCE_CURRENT_IMAGE): {
- triggerEvent(CURRENT_IMAGE_INFO, CURRENT_CHIP, CURRENT_COPY);
+ announceCurrentImageInfo();
return HasActionsIF::EXECUTION_FINISHED;
}
case (LIST_DIRECTORY_INTO_FILE): {
@@ -246,6 +240,9 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_
return result;
}
std::ostringstream oss("cp ", std::ostringstream::ate);
+ if (parser.isForceOptSet()) {
+ oss << "-f ";
+ }
if (parser.isRecursiveOptSet()) {
oss << "-r ";
}
@@ -318,28 +315,38 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_
if (size < 1) {
return HasActionsIF::INVALID_PARAMETERS;
}
- std::string path = sdcMan->getCurrentMountPrefix() + REBOOT_FILE;
- // Disable the reboot file mechanism
- parseRebootFile(path, rebootFile);
+ std::string path = sdcMan->getCurrentMountPrefix() + REBOOT_WATCHDOG_FILE;
+ parseRebootWatchdogFile(path, rebootWatchdogFile);
if (data[0] == 0) {
- rebootFile.enabled = false;
- rewriteRebootFile(rebootFile);
+ rebootWatchdogFile.enabled = false;
+ rewriteRebootWatchdogFile(rebootWatchdogFile);
} else if (data[0] == 1) {
- rebootFile.enabled = true;
- rewriteRebootFile(rebootFile);
+ rebootWatchdogFile.enabled = true;
+ rewriteRebootWatchdogFile(rebootWatchdogFile);
} else {
return HasActionsIF::INVALID_PARAMETERS;
}
return HasActionsIF::EXECUTION_FINISHED;
}
+ case (READ_REBOOT_MECHANISM_INFO): {
+ std::string path = sdcMan->getCurrentMountPrefix() + REBOOT_WATCHDOG_FILE;
+ parseRebootWatchdogFile(path, rebootWatchdogFile);
+ RebootWatchdogPacket packet(rebootWatchdogFile);
+ ReturnValue_t result = actionHelper.reportData(commandedBy, actionId, &packet);
+ if (result != returnvalue::OK) {
+ return result;
+ }
+ return HasActionsIF::EXECUTION_FINISHED;
+ }
case (RESET_REBOOT_COUNTERS): {
if (size == 0) {
- resetRebootCount(xsc::ALL_CHIP, xsc::ALL_COPY);
+ resetRebootWatchdogCounters(xsc::ALL_CHIP, xsc::ALL_COPY);
} else if (size == 2) {
if (data[0] > 1 or data[1] > 1) {
return HasActionsIF::INVALID_PARAMETERS;
}
- resetRebootCount(static_cast(data[0]), static_cast(data[1]));
+ resetRebootWatchdogCounters(static_cast(data[0]),
+ static_cast(data[1]));
}
return HasActionsIF::EXECUTION_FINISHED;
}
@@ -434,11 +441,11 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_
if (size < 1) {
return HasActionsIF::INVALID_PARAMETERS;
}
- std::string path = sdcMan->getCurrentMountPrefix() + REBOOT_FILE;
+ std::string path = sdcMan->getCurrentMountPrefix() + REBOOT_WATCHDOG_FILE;
// Disable the reboot file mechanism
- parseRebootFile(path, rebootFile);
- rebootFile.maxCount = data[0];
- rewriteRebootFile(rebootFile);
+ parseRebootWatchdogFile(path, rebootWatchdogFile);
+ rebootWatchdogFile.maxCount = data[0];
+ rewriteRebootWatchdogFile(rebootWatchdogFile);
return HasActionsIF::EXECUTION_FINISHED;
}
case (XSC_REBOOT_OBC): {
@@ -547,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) {
@@ -637,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.
@@ -665,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;
@@ -707,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);
}
@@ -723,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);
}
@@ -743,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 {
@@ -757,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);
}
@@ -794,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;
@@ -832,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);
@@ -866,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;
@@ -890,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;
@@ -1196,45 +1198,7 @@ ReturnValue_t CoreController::actionXscReboot(const uint8_t *data, size_t size)
auto tgtChip = static_cast(data[1]);
auto tgtCopy = static_cast(data[2]);
- // This function can not really fail
- gracefulShutdownTasks(tgtChip, tgtCopy, protOpPerformed);
-
- switch (tgtChip) {
- case (xsc::Chip::CHIP_0): {
- switch (tgtCopy) {
- case (xsc::Copy::COPY_0): {
- xsc_boot_copy(XSC_LIBNOR_CHIP_0, XSC_LIBNOR_COPY_NOMINAL);
- break;
- }
- case (xsc::Copy::COPY_1): {
- xsc_boot_copy(XSC_LIBNOR_CHIP_0, XSC_LIBNOR_COPY_GOLD);
- break;
- }
- default: {
- break;
- }
- }
- break;
- }
- case (xsc::Chip::CHIP_1): {
- switch (tgtCopy) {
- case (xsc::Copy::COPY_0): {
- xsc_boot_copy(XSC_LIBNOR_CHIP_1, XSC_LIBNOR_COPY_NOMINAL);
- break;
- }
- case (xsc::Copy::COPY_1): {
- xsc_boot_copy(XSC_LIBNOR_CHIP_1, XSC_LIBNOR_COPY_GOLD);
- break;
- }
- default: {
- break;
- }
- }
- break;
- }
- default:
- break;
- }
+ performGracefulShutdown(tgtChip, tgtCopy);
return returnvalue::FAILED;
}
@@ -1247,21 +1211,37 @@ ReturnValue_t CoreController::actionReboot(const uint8_t *data, size_t size) {
ReturnValue_t CoreController::gracefulShutdownTasks(xsc::Chip chip, xsc::Copy copy,
bool &protOpPerformed) {
+ // Store both sequence counters persistently.
+ core::SAVE_CFDP_SEQUENCE_COUNT = true;
+ core::SAVE_PUS_SEQUENCE_COUNT = true;
+
sdcMan->setBlocking(true);
sdcMan->markUnusable();
// Wait two seconds to ensure no one uses the SD cards
TaskFactory::delayTask(2000);
- // 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
- ReturnValue_t result = setBootCopyProtection(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, true,
- protOpPerformed, false);
- if (result == returnvalue::OK and protOpPerformed) {
+
+ // Ensure that all writes/reads do finish.
+ sync();
+
+ // 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;
}
@@ -1295,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) {
@@ -1477,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;
@@ -1489,28 +1374,11 @@ ReturnValue_t CoreController::handleProtInfoUpdateLine(std::string nextLine) {
currentCopy = static_cast(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++;
@@ -1543,7 +1411,8 @@ void CoreController::performMountedSdCardOperations() {
if (not timeFileInitDone) {
initClockFromTimeFile();
}
- performRebootFileHandling(false);
+ performRebootWatchdogHandling(false);
+ performRebootCountersHandling(false);
}
backupTimeFileHandler();
};
@@ -1615,118 +1484,127 @@ ReturnValue_t CoreController::performSdCardCheck() {
return returnvalue::OK;
}
-void CoreController::performRebootFileHandling(bool recreateFile) {
+void CoreController::performRebootWatchdogHandling(bool recreateFile) {
using namespace std;
- std::string path = currMntPrefix + REBOOT_FILE;
+ std::string path = currMntPrefix + REBOOT_WATCHDOG_FILE;
+ std::string legacyPath = currMntPrefix + LEGACY_REBOOT_WATCHDOG_FILE;
std::error_code e;
+ // TODO: Remove at some point in the future.
+ if (std::filesystem::exists(legacyPath, e)) {
+ // Old file might still exist, so copy it to new path
+ std::filesystem::copy(legacyPath, path, std::filesystem::copy_options::overwrite_existing, e);
+ if (e) {
+ sif::error << "File copy has failed: " << e.message() << std::endl;
+ }
+ }
if (not std::filesystem::exists(path, e) or recreateFile) {
#if OBSW_VERBOSE_LEVEL >= 1
- sif::info << "CoreController::performRebootFileHandling: Recreating reboot file" << std::endl;
+ sif::info << "CoreController::performRebootFileHandling: Recreating reboot watchdog file"
+ << std::endl;
#endif
- rebootFile.enabled = false;
- rebootFile.img00Cnt = 0;
- rebootFile.img01Cnt = 0;
- rebootFile.img10Cnt = 0;
- rebootFile.img11Cnt = 0;
- rebootFile.lastChip = xsc::Chip::CHIP_0;
- rebootFile.lastCopy = xsc::Copy::COPY_0;
- rebootFile.img00Lock = false;
- rebootFile.img01Lock = false;
- rebootFile.img10Lock = false;
- rebootFile.img11Lock = false;
- rebootFile.mechanismNextChip = xsc::Chip::NO_CHIP;
- rebootFile.mechanismNextCopy = xsc::Copy::NO_COPY;
- rebootFile.bootFlag = false;
- rewriteRebootFile(rebootFile);
+ rebootWatchdogFile.enabled = false;
+ rebootWatchdogFile.img00Cnt = 0;
+ rebootWatchdogFile.img01Cnt = 0;
+ rebootWatchdogFile.img10Cnt = 0;
+ rebootWatchdogFile.img11Cnt = 0;
+ rebootWatchdogFile.lastChip = xsc::Chip::CHIP_0;
+ rebootWatchdogFile.lastCopy = xsc::Copy::COPY_0;
+ rebootWatchdogFile.img00Lock = false;
+ rebootWatchdogFile.img01Lock = false;
+ rebootWatchdogFile.img10Lock = false;
+ rebootWatchdogFile.img11Lock = false;
+ rebootWatchdogFile.mechanismNextChip = xsc::Chip::NO_CHIP;
+ rebootWatchdogFile.mechanismNextCopy = xsc::Copy::NO_COPY;
+ rebootWatchdogFile.bootFlag = false;
+ rewriteRebootWatchdogFile(rebootWatchdogFile);
} else {
- if (not parseRebootFile(path, rebootFile)) {
- performRebootFileHandling(true);
+ if (not parseRebootWatchdogFile(path, rebootWatchdogFile)) {
+ performRebootWatchdogHandling(true);
+ return;
}
}
if (CURRENT_CHIP == xsc::CHIP_0) {
if (CURRENT_COPY == xsc::COPY_0) {
- rebootFile.img00Cnt++;
+ rebootWatchdogFile.img00Cnt++;
} else {
- rebootFile.img01Cnt++;
+ rebootWatchdogFile.img01Cnt++;
}
} else {
if (CURRENT_COPY == xsc::COPY_0) {
- rebootFile.img10Cnt++;
+ rebootWatchdogFile.img10Cnt++;
} else {
- rebootFile.img11Cnt++;
+ rebootWatchdogFile.img11Cnt++;
}
}
- if (rebootFile.bootFlag) {
+ if (rebootWatchdogFile.bootFlag) {
// Trigger event to inform ground that a reboot was triggered
- uint32_t p1 = rebootFile.lastChip << 16 | rebootFile.lastCopy;
+ uint32_t p1 = rebootWatchdogFile.lastChip << 16 | rebootWatchdogFile.lastCopy;
triggerEvent(core::REBOOT_MECHANISM_TRIGGERED, p1, 0);
// Clear the boot flag
- rebootFile.bootFlag = false;
+ rebootWatchdogFile.bootFlag = false;
}
- announceBootCounts();
-
- if (rebootFile.mechanismNextChip != xsc::NO_CHIP and
- rebootFile.mechanismNextCopy != xsc::NO_COPY) {
- if (CURRENT_CHIP != rebootFile.mechanismNextChip or
- CURRENT_COPY != rebootFile.mechanismNextCopy) {
- std::string infoString = std::to_string(rebootFile.mechanismNextChip) + " " +
- std::to_string(rebootFile.mechanismNextCopy);
+ if (rebootWatchdogFile.mechanismNextChip != xsc::NO_CHIP and
+ rebootWatchdogFile.mechanismNextCopy != xsc::NO_COPY) {
+ if (CURRENT_CHIP != rebootWatchdogFile.mechanismNextChip or
+ CURRENT_COPY != rebootWatchdogFile.mechanismNextCopy) {
+ std::string infoString = std::to_string(rebootWatchdogFile.mechanismNextChip) + " " +
+ std::to_string(rebootWatchdogFile.mechanismNextCopy);
sif::warning << "CoreController::performRebootFileHandling: Expected to be on image "
<< infoString << " but currently on other image. Locking " << infoString
<< std::endl;
// Firmware or other component might be corrupt and we are on another image then the target
// image specified by the mechanism. We can't really trust the target image anymore.
// Lock it for now
- if (rebootFile.mechanismNextChip == xsc::CHIP_0) {
- if (rebootFile.mechanismNextCopy == xsc::COPY_0) {
- rebootFile.img00Lock = true;
+ if (rebootWatchdogFile.mechanismNextChip == xsc::CHIP_0) {
+ if (rebootWatchdogFile.mechanismNextCopy == xsc::COPY_0) {
+ rebootWatchdogFile.img00Lock = true;
} else {
- rebootFile.img01Lock = true;
+ rebootWatchdogFile.img01Lock = true;
}
} else {
- if (rebootFile.mechanismNextCopy == xsc::COPY_0) {
- rebootFile.img10Lock = true;
+ if (rebootWatchdogFile.mechanismNextCopy == xsc::COPY_0) {
+ rebootWatchdogFile.img10Lock = true;
} else {
- rebootFile.img11Lock = true;
+ rebootWatchdogFile.img11Lock = true;
}
}
}
}
- rebootFile.lastChip = CURRENT_CHIP;
- rebootFile.lastCopy = CURRENT_COPY;
+ rebootWatchdogFile.lastChip = CURRENT_CHIP;
+ rebootWatchdogFile.lastCopy = CURRENT_COPY;
// Only reboot if the reboot functionality is enabled.
// The handler will still increment the boot counts
- if (rebootFile.enabled and (*rebootFile.relevantBootCnt >= rebootFile.maxCount)) {
+ if (rebootWatchdogFile.enabled and
+ (*rebootWatchdogFile.relevantBootCnt >= rebootWatchdogFile.maxCount)) {
// Reboot to other image
bool doReboot = false;
xsc::Chip tgtChip = xsc::NO_CHIP;
xsc::Copy tgtCopy = xsc::NO_COPY;
- determineAndExecuteReboot(rebootFile, doReboot, tgtChip, tgtCopy);
+ rebootWatchdogAlgorithm(rebootWatchdogFile, doReboot, tgtChip, tgtCopy);
if (doReboot) {
- rebootFile.bootFlag = true;
+ rebootWatchdogFile.bootFlag = true;
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "Boot counter for image " << CURRENT_CHIP << " " << CURRENT_COPY
<< " too high. Rebooting to " << tgtChip << " " << tgtCopy << std::endl;
#endif
- rebootFile.mechanismNextChip = tgtChip;
- rebootFile.mechanismNextCopy = tgtCopy;
- rewriteRebootFile(rebootFile);
- xsc_boot_copy(static_cast(tgtChip),
- static_cast(tgtCopy));
+ rebootWatchdogFile.mechanismNextChip = tgtChip;
+ rebootWatchdogFile.mechanismNextCopy = tgtCopy;
+ rewriteRebootWatchdogFile(rebootWatchdogFile);
+ performGracefulShutdown(tgtChip, tgtCopy);
}
} else {
- rebootFile.mechanismNextChip = xsc::NO_CHIP;
- rebootFile.mechanismNextCopy = xsc::NO_COPY;
+ rebootWatchdogFile.mechanismNextChip = xsc::NO_CHIP;
+ rebootWatchdogFile.mechanismNextCopy = xsc::NO_COPY;
}
- rewriteRebootFile(rebootFile);
+ rewriteRebootWatchdogFile(rebootWatchdogFile);
}
-void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot,
- xsc::Chip &tgtChip, xsc::Copy &tgtCopy) {
+void CoreController::rebootWatchdogAlgorithm(RebootWatchdogFile &rf, bool &needsReboot,
+ xsc::Chip &tgtChip, xsc::Copy &tgtCopy) {
tgtChip = xsc::CHIP_0;
tgtCopy = xsc::COPY_0;
needsReboot = false;
@@ -1814,7 +1692,7 @@ void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot
}
}
-bool CoreController::parseRebootFile(std::string path, RebootFile &rf) {
+bool CoreController::parseRebootWatchdogFile(std::string path, RebootWatchdogFile &rf) {
using namespace std;
std::string selfMatch;
if (CURRENT_CHIP == xsc::CHIP_0) {
@@ -1996,68 +1874,174 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) {
return true;
}
-void CoreController::resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy) {
- std::string path = currMntPrefix + REBOOT_FILE;
- // Disable the reboot file mechanism
- parseRebootFile(path, rebootFile);
+bool CoreController::parseRebootCountersFile(std::string path, RebootCountersFile &rf) {
+ using namespace std;
+ ifstream file(path);
+ string word;
+ string line;
+ uint8_t lineIdx = 0;
+ while (std::getline(file, line)) {
+ istringstream iss(line);
+ switch (lineIdx) {
+ case 0: {
+ iss >> word;
+ if (word.find("img00:") == string::npos) {
+ return false;
+ }
+ iss >> rf.img00Cnt;
+
+ break;
+ }
+ case 1: {
+ iss >> word;
+ if (word.find("img01:") == string::npos) {
+ return false;
+ }
+ iss >> rf.img01Cnt;
+
+ break;
+ }
+ case 2: {
+ iss >> word;
+ if (word.find("img10:") == string::npos) {
+ return false;
+ }
+ iss >> rf.img10Cnt;
+
+ break;
+ }
+ case 3: {
+ iss >> word;
+ if (word.find("img11:") == string::npos) {
+ return false;
+ }
+ iss >> rf.img11Cnt;
+ break;
+ }
+ }
+ lineIdx++;
+ }
+ return true;
+}
+
+void CoreController::resetRebootWatchdogCounters(xsc::Chip tgtChip, xsc::Copy tgtCopy) {
+ std::string path = currMntPrefix + REBOOT_WATCHDOG_FILE;
+ parseRebootWatchdogFile(path, rebootWatchdogFile);
if (tgtChip == xsc::ALL_CHIP and tgtCopy == xsc::ALL_COPY) {
- rebootFile.img00Cnt = 0;
- rebootFile.img01Cnt = 0;
- rebootFile.img10Cnt = 0;
- rebootFile.img11Cnt = 0;
+ rebootWatchdogFile.img00Cnt = 0;
+ rebootWatchdogFile.img01Cnt = 0;
+ rebootWatchdogFile.img10Cnt = 0;
+ rebootWatchdogFile.img11Cnt = 0;
} else {
if (tgtChip == xsc::CHIP_0) {
if (tgtCopy == xsc::COPY_0) {
- rebootFile.img00Cnt = 0;
+ rebootWatchdogFile.img00Cnt = 0;
} else {
- rebootFile.img01Cnt = 0;
+ rebootWatchdogFile.img01Cnt = 0;
}
} else {
if (tgtCopy == xsc::COPY_0) {
- rebootFile.img10Cnt = 0;
+ rebootWatchdogFile.img10Cnt = 0;
} else {
- rebootFile.img11Cnt = 0;
+ rebootWatchdogFile.img11Cnt = 0;
}
}
}
- rewriteRebootFile(rebootFile);
+ rewriteRebootWatchdogFile(rebootWatchdogFile);
}
-void CoreController::rewriteRebootFile(RebootFile file) {
- std::string path = currMntPrefix + REBOOT_FILE;
+void CoreController::performRebootCountersHandling(bool recreateFile) {
+ std::string path = currMntPrefix + REBOOT_COUNTERS_FILE;
+ std::error_code e;
+ if (not std::filesystem::exists(path, e) or recreateFile) {
+#if OBSW_VERBOSE_LEVEL >= 1
+ sif::info << "CoreController::performRebootFileHandling: Recreating reboot counters file"
+ << std::endl;
+#endif
+ rebootCountersFile.img00Cnt = 0;
+ rebootCountersFile.img01Cnt = 0;
+ rebootCountersFile.img10Cnt = 0;
+ rebootCountersFile.img11Cnt = 0;
+ rewriteRebootCountersFile(rebootCountersFile);
+ } else {
+ if (not parseRebootCountersFile(path, rebootCountersFile)) {
+ performRebootCountersHandling(true);
+ return;
+ }
+ }
+
+ if (CURRENT_CHIP == xsc::CHIP_0) {
+ if (CURRENT_COPY == xsc::COPY_0) {
+ rebootCountersFile.img00Cnt++;
+ } else {
+ rebootCountersFile.img01Cnt++;
+ }
+ } else {
+ if (CURRENT_COPY == xsc::COPY_0) {
+ rebootCountersFile.img10Cnt++;
+ } else {
+ rebootCountersFile.img11Cnt++;
+ }
+ }
+ announceBootCounts();
+ rewriteRebootCountersFile(rebootCountersFile);
+}
+void CoreController::rewriteRebootWatchdogFile(RebootWatchdogFile file) {
+ using namespace std::filesystem;
+ std::string path = currMntPrefix + REBOOT_WATCHDOG_FILE;
+ std::string legacyPath = currMntPrefix + LEGACY_REBOOT_WATCHDOG_FILE;
+ {
+ std::ofstream rebootFile(path);
+ if (rebootFile.is_open()) {
+ // Initiate reboot file first. Reboot handling will be on on initialization
+ rebootFile << "on: " << file.enabled << "\nmaxcnt: " << file.maxCount
+ << "\nimg00: " << file.img00Cnt << "\nimg01: " << file.img01Cnt
+ << "\nimg10: " << file.img10Cnt << "\nimg11: " << file.img11Cnt
+ << "\nimg00lock: " << file.img00Lock << "\nimg01lock: " << file.img01Lock
+ << "\nimg10lock: " << file.img10Lock << "\nimg11lock: " << file.img11Lock
+ << "\nbootflag: " << file.bootFlag << "\nlast: " << static_cast(file.lastChip)
+ << " " << static_cast(file.lastCopy)
+ << "\nnext: " << static_cast(file.mechanismNextChip) << " "
+ << static_cast(file.mechanismNextCopy) << "\n";
+ }
+ }
+ std::error_code e;
+ // TODO: Remove at some point in the future when all images have been updated.
+ if (std::filesystem::exists(legacyPath)) {
+ // Keep those two files in sync
+ std::filesystem::copy(path, legacyPath, std::filesystem::copy_options::overwrite_existing, e);
+ if (e) {
+ sif::error << "File copy has failed: " << e.message() << std::endl;
+ }
+ }
+}
+
+void CoreController::rewriteRebootCountersFile(RebootCountersFile file) {
+ std::string path = currMntPrefix + REBOOT_COUNTERS_FILE;
std::ofstream rebootFile(path);
if (rebootFile.is_open()) {
- // Initiate reboot file first. Reboot handling will be on on initialization
- rebootFile << "on: " << file.enabled << "\nmaxcnt: " << file.maxCount
- << "\nimg00: " << file.img00Cnt << "\nimg01: " << file.img01Cnt
- << "\nimg10: " << file.img10Cnt << "\nimg11: " << file.img11Cnt
- << "\nimg00lock: " << file.img00Lock << "\nimg01lock: " << file.img01Lock
- << "\nimg10lock: " << file.img10Lock << "\nimg11lock: " << file.img11Lock
- << "\nbootflag: " << file.bootFlag << "\nlast: " << static_cast(file.lastChip)
- << " " << static_cast(file.lastCopy)
- << "\nnext: " << static_cast(file.mechanismNextChip) << " "
- << static_cast(file.mechanismNextCopy) << "\n";
+ rebootFile << "img00: " << file.img00Cnt << "\nimg01: " << file.img01Cnt
+ << "\nimg10: " << file.img10Cnt << "\nimg11: " << file.img11Cnt << "\n";
}
}
void CoreController::setRebootMechanismLock(bool lock, xsc::Chip tgtChip, xsc::Copy tgtCopy) {
- std::string path = currMntPrefix + REBOOT_FILE;
- // Disable the reboot file mechanism
- parseRebootFile(path, rebootFile);
+ std::string path = currMntPrefix + REBOOT_WATCHDOG_FILE;
+ parseRebootWatchdogFile(path, rebootWatchdogFile);
if (tgtChip == xsc::CHIP_0) {
if (tgtCopy == xsc::COPY_0) {
- rebootFile.img00Lock = lock;
+ rebootWatchdogFile.img00Lock = lock;
} else {
- rebootFile.img01Lock = lock;
+ rebootWatchdogFile.img01Lock = lock;
}
} else {
if (tgtCopy == xsc::COPY_0) {
- rebootFile.img10Lock = lock;
+ rebootWatchdogFile.img10Lock = lock;
} else {
- rebootFile.img11Lock = lock;
+ rebootWatchdogFile.img11Lock = lock;
}
}
- rewriteRebootFile(rebootFile);
+ rewriteRebootWatchdogFile(rebootWatchdogFile);
}
ReturnValue_t CoreController::backupTimeFileHandler() {
@@ -2344,10 +2328,12 @@ bool CoreController::startSdStateMachine(sd::SdCard targetActiveSd, SdCfgMode mo
}
void CoreController::announceBootCounts() {
- uint64_t totalBootCount =
- rebootFile.img00Cnt + rebootFile.img01Cnt + rebootFile.img10Cnt + rebootFile.img11Cnt;
- uint32_t individualBootCountsP1 = (rebootFile.img00Cnt << 16) | rebootFile.img01Cnt;
- uint32_t individualBootCountsP2 = (rebootFile.img10Cnt << 16) | rebootFile.img11Cnt;
+ uint64_t totalBootCount = rebootCountersFile.img00Cnt + rebootCountersFile.img01Cnt +
+ rebootCountersFile.img10Cnt + rebootCountersFile.img11Cnt;
+ uint32_t individualBootCountsP1 =
+ (rebootCountersFile.img00Cnt << 16) | rebootCountersFile.img01Cnt;
+ uint32_t individualBootCountsP2 =
+ (rebootCountersFile.img10Cnt << 16) | rebootCountersFile.img11Cnt;
triggerEvent(core::INDIVIDUAL_BOOT_COUNTS, individualBootCountsP1, individualBootCountsP2);
triggerEvent(core::REBOOT_COUNTER, (totalBootCount >> 32) & 0xffffffff,
totalBootCount & 0xffffffff);
@@ -2405,6 +2391,138 @@ void CoreController::dirListingDumpHandler() {
}
}
+void CoreController::announceVersionInfo() {
+ using namespace core;
+ uint32_t p1 = (common::OBSW_VERSION_MAJOR << 24) | (common::OBSW_VERSION_MINOR << 16) |
+ (common::OBSW_VERSION_REVISION << 8);
+ uint32_t p2 = 0;
+ if (strcmp("", common::OBSW_VERSION_CST_GIT_SHA1) != 0) {
+ p1 |= 1;
+ auto shaAsStr = std::string(common::OBSW_VERSION_CST_GIT_SHA1);
+ size_t posDash = shaAsStr.find("-");
+ auto gitHash = shaAsStr.substr(posDash + 2, 4);
+ // Only copy first 4 letters of git hash
+ memcpy(&p2, gitHash.c_str(), 4);
+ }
+
+ triggerEvent(VERSION_INFO, p1, p2);
+ 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() {
+ using namespace core;
+ triggerEvent(CURRENT_IMAGE_INFO, CURRENT_CHIP, CURRENT_COPY);
+}
+
+ReturnValue_t CoreController::performGracefulShutdown(xsc::Chip tgtChip, xsc::Copy tgtCopy) {
+ bool protOpPerformed = false;
+ // This function can not really fail
+ gracefulShutdownTasks(tgtChip, tgtCopy, protOpPerformed);
+
+ switch (tgtChip) {
+ case (xsc::Chip::CHIP_0): {
+ switch (tgtCopy) {
+ case (xsc::Copy::COPY_0): {
+ xsc_boot_copy(XSC_LIBNOR_CHIP_0, XSC_LIBNOR_COPY_NOMINAL);
+ break;
+ }
+ case (xsc::Copy::COPY_1): {
+ xsc_boot_copy(XSC_LIBNOR_CHIP_0, XSC_LIBNOR_COPY_GOLD);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ break;
+ }
+ case (xsc::Chip::CHIP_1): {
+ switch (tgtCopy) {
+ case (xsc::Copy::COPY_0): {
+ xsc_boot_copy(XSC_LIBNOR_CHIP_1, XSC_LIBNOR_COPY_NOMINAL);
+ break;
+ }
+ case (xsc::Copy::COPY_1): {
+ xsc_boot_copy(XSC_LIBNOR_CHIP_1, XSC_LIBNOR_COPY_GOLD);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ 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(activeSdCard.value());
+ }
+ uint32_t p2 =
+ (static_cast(sdStates.first) << 16) | static_cast(sdStates.second);
+ triggerEvent(core::ACTIVE_SD_INFO, p1, p2);
+}
+
+ReturnValue_t CoreController::handleSwitchingSdCardsOffNonBlocking() {
+ sdcMan->setBlocking(false);
+ SdCardManager::Operations op;
+ std::pair 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();
diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h
index 05878d6d..79224ed2 100644
--- a/bsp_q7s/core/CoreController.h
+++ b/bsp_q7s/core/CoreController.h
@@ -1,11 +1,13 @@
#ifndef BSP_Q7S_CORE_CORECONTROLLER_H_
#define BSP_Q7S_CORE_CORECONTROLLER_H_
+#include
#include
#include
#include
#include
#include
+#include
#include
#include
#include
@@ -13,7 +15,6 @@
#include
#include
-#include "CoreDefinitions.h"
#include "OBSWConfig.h"
#include "bsp_q7s/fs/SdCardManager.h"
#include "events/subsystemIdRanges.h"
@@ -23,7 +24,7 @@
class Timer;
class SdCardManager;
-struct RebootFile {
+struct RebootWatchdogFile {
static constexpr uint8_t DEFAULT_MAX_BOOT_CNT = 10;
bool enabled = true;
@@ -44,6 +45,93 @@ struct RebootFile {
xsc::Copy mechanismNextCopy = xsc::Copy::NO_COPY;
};
+class RebootWatchdogPacket : public SerialLinkedListAdapter {
+ public:
+ RebootWatchdogPacket(RebootWatchdogFile& rf) {
+ enabled = rf.enabled;
+ maxCount = rf.maxCount;
+ img00Count = rf.img00Cnt;
+ img01Count = rf.img01Cnt;
+ img10Count = rf.img10Cnt;
+ img11Count = rf.img11Cnt;
+ img00Lock = rf.img00Lock;
+ img01Lock = rf.img01Lock;
+ img10Lock = rf.img10Lock;
+ img11Lock = rf.img11Lock;
+ lastChip = static_cast(rf.lastChip);
+ lastCopy = static_cast(rf.lastCopy);
+ nextChip = static_cast(rf.mechanismNextChip);
+ nextCopy = static_cast(rf.mechanismNextCopy);
+ setLinks();
+ }
+
+ private:
+ void setLinks() {
+ setStart(&enabled);
+ enabled.setNext(&maxCount);
+ maxCount.setNext(&img00Count);
+ img00Count.setNext(&img01Count);
+ img01Count.setNext(&img10Count);
+ img10Count.setNext(&img11Count);
+ img11Count.setNext(&img00Lock);
+ img00Lock.setNext(&img01Lock);
+ img01Lock.setNext(&img10Lock);
+ img10Lock.setNext(&img11Lock);
+ img11Lock.setNext(&lastChip);
+ lastChip.setNext(&lastCopy);
+ lastCopy.setNext(&nextChip);
+ nextChip.setNext(&nextCopy);
+ setLast(&nextCopy);
+ }
+
+ SerializeElement enabled = false;
+ SerializeElement maxCount = 0;
+ SerializeElement img00Count = 0;
+ SerializeElement img01Count = 0;
+ SerializeElement img10Count = 0;
+ SerializeElement img11Count = 0;
+ SerializeElement img00Lock = false;
+ SerializeElement img01Lock = false;
+ SerializeElement img10Lock = false;
+ SerializeElement img11Lock = false;
+ SerializeElement lastChip = 0;
+ SerializeElement lastCopy = 0;
+ SerializeElement nextChip = 0;
+ SerializeElement nextCopy = 0;
+};
+
+struct RebootCountersFile {
+ // 16 bit values so all boot counters fit into one event.
+ uint16_t img00Cnt = 0;
+ uint16_t img01Cnt = 0;
+ uint16_t img10Cnt = 0;
+ uint16_t img11Cnt = 0;
+};
+
+class RebootCountersPacket : public SerialLinkedListAdapter {
+ RebootCountersPacket(RebootCountersFile& rf) {
+ img00Count = rf.img00Cnt;
+ img01Count = rf.img01Cnt;
+ img10Count = rf.img10Cnt;
+ img11Count = rf.img11Cnt;
+ setLinks();
+ }
+
+ private:
+ void setLinks() {
+ setStart(&img00Count);
+ img00Count.setNext(&img01Count);
+ img01Count.setNext(&img10Count);
+ img10Count.setNext(&img11Count);
+ setLast(&img11Count);
+ }
+
+ SerializeElement img00Count = 0;
+ SerializeElement img01Count = 0;
+ SerializeElement img10Count = 0;
+ SerializeElement img11Count = 0;
+};
+
class CoreController : public ExtendedControllerBase, public ReceivesParameterMessagesIF {
public:
enum ParamId : uint8_t { PREF_SD = 0, NUM_IDS };
@@ -57,10 +145,15 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
const std::string VERSION_FILE =
"/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::VERSION_FILE_NAME);
- const std::string REBOOT_FILE =
- "/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::REBOOT_FILE_NAME);
+ const std::string LEGACY_REBOOT_WATCHDOG_FILE =
+ "/" + std::string(core::CONF_FOLDER) + "/" +
+ std::string(core::LEGACY_REBOOT_WATCHDOG_FILE_NAME);
+ const std::string REBOOT_WATCHDOG_FILE =
+ "/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::REBOOT_WATCHDOG_FILE_NAME);
const std::string BACKUP_TIME_FILE =
"/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::TIME_FILE_NAME);
+ const std::string REBOOT_COUNTERS_FILE =
+ "/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::REBOOT_COUNTER_FILE_NAME);
static constexpr char CHIP_0_COPY_0_MOUNT_DIR[] = "/tmp/mntupdate-xdi-qspi0-nom-rootfs";
static constexpr char CHIP_0_COPY_1_MOUNT_DIR[] = "/tmp/mntupdate-xdi-qspi0-gold-rootfs";
@@ -106,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;
@@ -142,6 +235,7 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
static constexpr bool BLOCKING_SD_INIT = false;
+ uint32_t* mappedSysRomAddr = nullptr;
SdCardManager* sdcMan = nullptr;
MessageQueueIF* eventQueue = nullptr;
@@ -191,7 +285,8 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
std::array dirListingBuf{};
DirListingDumpContext dumpContext{};
- RebootFile rebootFile = {};
+ RebootWatchdogFile rebootWatchdogFile = {};
+ RebootCountersFile rebootCountersFile = {};
CommandExecutor cmdExecutor;
SimpleRingBuffer cmdReplyBuf;
@@ -209,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 protArray;
+ bool protArray[2][2]{};
PeriodicOperationDivider opDivider5;
PeriodicOperationDivider opDivider10;
@@ -261,12 +354,14 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
void currentStateSetter(sd::SdCard sdCard, sd::SdState newState);
void executeNextExternalSdCommand();
void checkExternalSdCommandStatus();
- void performRebootFileHandling(bool recreateFile);
+ void performRebootWatchdogHandling(bool recreateFile);
+ void performRebootCountersHandling(bool recreateFile);
ReturnValue_t actionListDirectoryIntoFile(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size);
ReturnValue_t actionListDirectoryDumpDirectly(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size);
+ ReturnValue_t performGracefulShutdown(xsc::Chip targetChip, xsc::Copy targetCopy);
ReturnValue_t actionListDirectoryCommonCommandCreator(const uint8_t* data, size_t size,
std::ostringstream& oss);
@@ -277,16 +372,20 @@ 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);
- void determineAndExecuteReboot(RebootFile& rf, bool& needsReboot, xsc::Chip& tgtChip,
- xsc::Copy& tgtCopy);
- void resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy);
+ 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);
void setRebootMechanismLock(bool lock, xsc::Chip tgtChip, xsc::Copy tgtCopy);
- bool parseRebootFile(std::string path, RebootFile& file);
- void rewriteRebootFile(RebootFile file);
+ bool parseRebootWatchdogFile(std::string path, RebootWatchdogFile& file);
+ bool parseRebootCountersFile(std::string path, RebootCountersFile& file);
+ void rewriteRebootWatchdogFile(RebootWatchdogFile file);
+ void rewriteRebootCountersFile(RebootCountersFile file);
void announceBootCounts();
+ void announceVersionInfo();
+ void announceCurrentImageInfo();
+ void announceSdInfo(SdCardManager::SdStatePair sdStates);
void readHkData();
void dirListingDumpHandler();
bool isNumber(const std::string& s);
diff --git a/bsp_q7s/core/CoreDefinitions.h b/bsp_q7s/core/defs.h
similarity index 81%
rename from bsp_q7s/core/CoreDefinitions.h
rename to bsp_q7s/core/defs.h
index 91896301..a82c1c56 100644
--- a/bsp_q7s/core/CoreDefinitions.h
+++ b/bsp_q7s/core/defs.h
@@ -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
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 {
} // namespace core
-#endif /* BSP_Q7S_CORE_COREDEFINITIONS_H_ */
+#endif /* BSP_Q7S_CORE_DEFS_H_ */
diff --git a/bsp_q7s/em/emObjectFactory.cpp b/bsp_q7s/em/emObjectFactory.cpp
index 5270e887..3c3ba290 100644
--- a/bsp_q7s/em/emObjectFactory.cpp
+++ b/bsp_q7s/em/emObjectFactory.cpp
@@ -1,4 +1,5 @@
#include
+#include
#include
#include
#include
@@ -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,18 +36,20 @@ void ObjectFactory::produce(void* args) {
#endif
PersistentTmStores stores;
+ readFirmwareVersion();
ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel,
- *SdCardManager::instance(), &ipcStore, &tmStore, stores,
- 200);
+ *SdCardManager::instance(), &ipcStore, &tmStore, stores, 200,
+ enableHkSets);
LinuxLibgpioIF* gpioComIF = nullptr;
SerialComIF* uartComIF = nullptr;
SpiComIF* spiMainComIF = nullptr;
I2cComIF* i2cComIF = nullptr;
createCommunicationInterfaces(&gpioComIF, &uartComIF, &spiMainComIF, &i2cComIF);
- /* Adding gpios for chip select decoding to the gpioComIf */
+ // Adding GPIOs for chip select decoding and initializing them.
q7s::gpioCallbacks::initSpiCsDecoder(gpioComIF);
gpioCallbacks::disableAllDecoder(gpioComIF);
+ createPlI2cResetGpio(gpioComIF);
// Hardware is usually not connected to EM, so we need to create dummies which replace lower
// level components.
@@ -59,17 +62,41 @@ 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> 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
#if OBSW_ADD_ACS_BOARD == 1
dummyCfg.addAcsBoardDummies = false;
#endif
+#if OBSW_ADD_PL_PCDU == 0
+ dummyCfg.addPlPcduDummy = true;
+#endif
PowerSwitchIF* pwrSwitcher = nullptr;
#if OBSW_ADD_GOMSPACE_PCDU == 0
@@ -83,24 +110,12 @@ void ObjectFactory::produce(void* args) {
new CoreController(objects::CORE_CONTROLLER, enableHkSets);
- // Regular FM code, does not work for EM if the hardware is not connected
- // createPcduComponents(gpioComIF, &pwrSwitcher);
- // createPlPcduComponents(gpioComIF, spiMainComIF, pwrSwitcher);
- // createSyrlinksComponents(pwrSwitcher);
- // createSunSensorComponents(gpioComIF, spiMainComIF, pwrSwitcher, q7s::SPI_DEFAULT_DEV);
- // createRtdComponents(q7s::SPI_DEFAULT_DEV, gpioComIF, pwrSwitcher, spiMainComIF);
- // createTmpComponents();
- // createSolarArrayDeploymentComponents();
- // createPayloadComponents(gpioComIF);
- // createHeaterComponents(gpioComIF, pwrSwitcher, healthTable);
+ auto* stackHandler = new Stack5VHandler(*pwrSwitcher);
- // TODO: Careful! Switching this on somehow messes with the communication with the ProASIC
- // and will cause xsc_boot_copy commands to always boot to 0 0
- // createRadSensorComponent(gpioComIF);
+ // Initialize chip select to avoid SPI bus issues.
+ createRadSensorChipSelect(gpioComIF);
#if OBSW_ADD_ACS_BOARD == 1
- // Still initialize chip select to avoid SPI bus issues.
- createRadSensorChipSelect(gpioComIF);
createAcsBoardComponents(*spiMainComIF, gpioComIF, uartComIF, *pwrSwitcher, true,
adis1650x::Type::ADIS16507);
#else
@@ -110,8 +125,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(battAndImtqI2cDev);
+
#if OBSW_ADD_MGT == 1
- createImtqComponents(pwrSwitcher, enableHkSets);
+ createImtqComponents(pwrSwitcher, enableHkSets, battAndImtqI2cDev);
#endif
#if OBSW_ADD_SYRLINKS == 1
@@ -123,13 +144,16 @@ 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
createStrComponents(pwrSwitcher);
#endif /* OBSW_ADD_STAR_TRACKER == 1 */
+#if OBSW_ADD_PL_PCDU == 1
+ createPlPcduComponents(gpioComIF, spiMainComIF, pwrSwitcher, *stackHandler);
+#endif
createPayloadComponents(gpioComIF, *pwrSwitcher);
#if OBSW_ADD_CCSDS_IP_CORES == 1
@@ -155,6 +179,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);
}
diff --git a/bsp_q7s/fmObjectFactory.cpp b/bsp_q7s/fmObjectFactory.cpp
index 5eeeef59..a3ab6bba 100644
--- a/bsp_q7s/fmObjectFactory.cpp
+++ b/bsp_q7s/fmObjectFactory.cpp
@@ -1,4 +1,5 @@
#include
+#include
#include
#include
#include
@@ -7,9 +8,9 @@
#include "OBSWConfig.h"
#include "bsp_q7s/core/CoreController.h"
-#include "bsp_q7s/core/ObjectFactory.h"
#include "busConf.h"
#include "devConf.h"
+#include "devices/addresses.h"
#include "eive/objects.h"
#include "fsfw_hal/linux/gpio/LinuxLibgpioIF.h"
#include "linux/ObjectFactory.h"
@@ -32,9 +33,10 @@ void ObjectFactory::produce(void* args) {
#endif
PersistentTmStores stores;
+ readFirmwareVersion();
ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel,
- *SdCardManager::instance(), &ipcStore, &tmStore, stores,
- 200);
+ *SdCardManager::instance(), &ipcStore, &tmStore, stores, 200,
+ true);
LinuxLibgpioIF* gpioComIF = nullptr;
SerialComIF* uartComIF = nullptr;
@@ -45,6 +47,7 @@ void ObjectFactory::produce(void* args) {
/* Adding gpios for chip select decoding to the gpioComIf */
q7s::gpioCallbacks::initSpiCsDecoder(gpioComIF);
gpioCallbacks::disableAllDecoder(gpioComIF);
+ createPlI2cResetGpio(gpioComIF);
new CoreController(objects::CORE_CONTROLLER, enableHkSets);
createPcduComponents(gpioComIF, &pwrSwitcher, enableHkSets);
@@ -66,23 +69,38 @@ void ObjectFactory::produce(void* args) {
HeaterHandler* heaterHandler;
createHeaterComponents(gpioComIF, pwrSwitcher, healthTable, heaterHandler);
#if OBSW_ADD_TMP_DEVICES == 1
- createTmpComponents();
+ std::vector> 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);
+#if OBSW_ADD_PL_PCDU == 1
createPlPcduComponents(gpioComIF, spiMainComIF, pwrSwitcher, *stackHandler);
+#endif
#if OBSW_ADD_SYRLINKS == 1
createSyrlinksComponents(pwrSwitcher);
#endif /* OBSW_ADD_SYRLINKS == 1 */
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
@@ -112,7 +130,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);
}
diff --git a/bsp_q7s/fs/SdCardManager.cpp b/bsp_q7s/fs/SdCardManager.cpp
index 14e3e6aa..ffbed668 100644
--- a/bsp_q7s/fs/SdCardManager.cpp
+++ b/bsp_q7s/fs/SdCardManager.cpp
@@ -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 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) {
diff --git a/bsp_q7s/fs/SdCardManager.h b/bsp_q7s/fs/SdCardManager.h
index 7a4a7cbe..23a3d193 100644
--- a/bsp_q7s/fs/SdCardManager.h
+++ b/bsp_q7s/fs/SdCardManager.h
@@ -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
diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/objectFactory.cpp
similarity index 92%
rename from bsp_q7s/core/ObjectFactory.cpp
rename to bsp_q7s/objectFactory.cpp
index cea90bf2..39271628 100644
--- a/bsp_q7s/core/ObjectFactory.cpp
+++ b/bsp_q7s/objectFactory.cpp
@@ -1,7 +1,9 @@
-#include "ObjectFactory.h"
+#include "objectFactory.h"
#include
#include
+#include
+#include
#include
#include
#include
@@ -31,6 +33,9 @@
#include
#include
+#include
+#include
+
#include "OBSWConfig.h"
#include "bsp_q7s/boardtest/Q7STestTask.h"
#include "bsp_q7s/callbacks/gnssCallback.h"
@@ -99,6 +104,7 @@
#include
+#include "bsp_q7s/core/defs.h"
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
#include "fsfw/tmtcpacket/pus/tm.h"
#include "fsfw/tmtcservices/CommandingServiceBase.h"
@@ -129,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;
@@ -150,28 +161,23 @@ void Factory::setStaticFrameworkObjectIds() {
void ObjectFactory::setStatics() { Factory::setStaticFrameworkObjectIds(); }
-void ObjectFactory::createTmpComponents() {
- std::vector> 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> 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 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();
}
}
@@ -243,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,
@@ -505,7 +511,7 @@ void ObjectFactory::createAcsBoardComponents(SpiComIF& spiComIF, LinuxLibgpioIF*
debugGps = true;
#endif
RESET_ARGS_GNSS.gpioComIF = gpioComIF;
- RESET_ARGS_GNSS.waitPeriodMs = 100;
+ RESET_ARGS_GNSS.waitPeriodMs = 5;
auto gpsCtrl = new GpsHyperionLinuxController(objects::GPS_CONTROLLER, objects::NO_OBJECT,
enableHkSets, debugGps);
gpsCtrl->setResetPinTriggerFunction(gps::triggerGpioResetPin, &RESET_ARGS_GNSS);
@@ -730,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",
@@ -752,18 +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);
@@ -908,8 +902,6 @@ void ObjectFactory::createPlPcduComponents(LinuxLibgpioIF* gpioComIF, SpiComIF*
new PayloadPcduHandler(objects::PLPCDU_HANDLER, objects::SPI_MAIN_COM_IF, spiCookie,
gpioComIF, SdCardManager::instance(), stackHandler, false);
spiCookie->setCallbackMode(PayloadPcduHandler::extConvAsTwoCallback, plPcduHandler);
-// plPcduHandler->enablePeriodicPrintout(true, 5);
-// static_cast(plPcduHandler);
#if OBSW_TEST_PL_PCDU == 1
plPcduHandler->setStartUpImmediately();
#endif
@@ -943,16 +935,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;
}
@@ -965,12 +948,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());
@@ -986,8 +970,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();
@@ -1025,3 +1009,50 @@ void ObjectFactory::createRadSensorChipSelect(LinuxLibgpioIF* gpioIF) {
gpioCookieRadSensor->addGpio(gpioIds::ENABLE_RADFET, gpio);
gpioChecker(gpioIF->addGpios(gpioCookieRadSensor), "RAD sensor");
}
+
+void ObjectFactory::createPlI2cResetGpio(LinuxLibgpioIF* gpioIF) {
+ using namespace gpio;
+ if (common::OBSW_VERSION_MAJOR >= 6 or common::OBSW_VERSION_MAJOR == 4) {
+ if (gpioIF == nullptr) {
+ return;
+ }
+ GpioCookie* gpioI2cResetnCookie = new GpioCookie;
+ GpiodRegularByLineName* gpioI2cResetn = new GpiodRegularByLineName(
+ q7s::gpioNames::PL_I2C_ARESETN, "PL_I2C_ARESETN", Direction::OUT, Levels::HIGH);
+ gpioI2cResetnCookie->addGpio(gpioIds::PL_I2C_ARESETN, gpioI2cResetn);
+ gpioChecker(gpioIF->addGpios(gpioI2cResetnCookie), "PL I2C ARESETN");
+ // Reset I2C explicitely again.
+ gpioIF->pullLow(gpioIds::PL_I2C_ARESETN);
+ TaskFactory::delayTask(1);
+ 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(mappedSysRomAddr));
+ uint32_t secondEntry = *(reinterpret_cast(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;
+}
diff --git a/bsp_q7s/core/ObjectFactory.h b/bsp_q7s/objectFactory.h
similarity index 92%
rename from bsp_q7s/core/ObjectFactory.h
rename to bsp_q7s/objectFactory.h
index df65e1ae..491720ac 100644
--- a/bsp_q7s/core/ObjectFactory.h
+++ b/bsp_q7s/objectFactory.h
@@ -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> tmpDevsToAdd);
void createRadSensorChipSelect(LinuxLibgpioIF* gpioIF);
ReturnValue_t createRadSensorComponent(LinuxLibgpioIF* gpioComIF, Stack5VHandler& handler);
void createAcsBoardGpios(GpioCookie& cookie);
@@ -67,17 +67,19 @@ 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);
+void createPlI2cResetGpio(LinuxLibgpioIF* gpioComIF);
void testAcsBrdAss(AcsBoardAssembly* assAss);
diff --git a/bsp_q7s/obsw.cpp b/bsp_q7s/obsw.cpp
index dc547b03..fc49c369 100644
--- a/bsp_q7s/obsw.cpp
+++ b/bsp_q7s/obsw.cpp
@@ -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;
diff --git a/bsp_q7s/core/scheduling.cpp b/bsp_q7s/scheduling.cpp
similarity index 98%
rename from bsp_q7s/core/scheduling.cpp
rename to bsp_q7s/scheduling.cpp
index 71da5bdc..d7c179ad 100644
--- a/bsp_q7s/core/scheduling.cpp
+++ b/bsp_q7s/scheduling.cpp
@@ -9,7 +9,6 @@
#include
#include "OBSWConfig.h"
-#include "bsp_q7s/core/ObjectFactory.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/objectmanager/ObjectManagerIF.h"
#include "fsfw/platform.h"
@@ -21,6 +20,8 @@
#include "mission/pollingSeqTables.h"
#include "mission/scheduling.h"
#include "mission/utility/InitMission.h"
+#include "objectFactory.h"
+#include "q7sConfig.h"
/* This is configured for linux without CR */
#ifdef PLATFORM_UNIX
@@ -324,6 +325,10 @@ void scheduling::initTasks() {
if (result != returnvalue::OK) {
scheduling::printAddObjectError("HEATER_HANDLER", objects::HEATER_HANDLER);
}
+ result = tcsSystemTask->addComponent(objects::HEATER_HANDLER);
+ if (result != returnvalue::OK) {
+ scheduling::printAddObjectError("HEATER_HANDLER", objects::HEATER_HANDLER);
+ }
#if OBSW_ADD_SYRLINKS == 1
PeriodicTaskIF* syrlinksCom = factory->createPeriodicTask(
@@ -527,7 +532,15 @@ void scheduling::createPstTasks(TaskFactory& factory, TaskDeadlineMissedFunction
FixedTimeslotTaskIF* i2cPst =
factory.createFixedTimeslotTask("I2C_PS_PST", 60, PeriodicTaskIF::MINIMUM_STACK_SIZE * 4, 0.6,
missedDeadlineFunc, &RR_SCHEDULING);
- result = pst::pstI2cProcessingSystem(i2cPst);
+ pst::TmpSchedConfig tmpSchedConf;
+#if OBSW_Q7S_EM == 1
+ tmpSchedConf.scheduleTmpDev0 = true;
+ tmpSchedConf.scheduleTmpDev1 = true;
+ tmpSchedConf.schedulePlPcduDev0 = true;
+ tmpSchedConf.schedulePlPcduDev1 = true;
+ tmpSchedConf.scheduleIfBoardDev = true;
+#endif
+ result = pst::pstI2c(tmpSchedConf, i2cPst);
if (result != returnvalue::OK) {
if (result == FixedTimeslotTaskIF::SLOT_LIST_EMPTY) {
sif::warning << "scheduling::initTasks: I2C PST is empty" << std::endl;
diff --git a/bsp_q7s/core/scheduling.h b/bsp_q7s/scheduling.h
similarity index 100%
rename from bsp_q7s/core/scheduling.h
rename to bsp_q7s/scheduling.h
diff --git a/bsp_q7s/xadc/Xadc.cpp b/bsp_q7s/xadc/Xadc.cpp
index 34a4e159..da3fbf7f 100644
--- a/bsp_q7s/xadc/Xadc.cpp
+++ b/bsp_q7s/xadc/Xadc.cpp
@@ -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;
}
diff --git a/common/config/devices/gpioIds.h b/common/config/devices/gpioIds.h
index 640f4ead..bed82142 100644
--- a/common/config/devices/gpioIds.h
+++ b/common/config/devices/gpioIds.h
@@ -77,6 +77,8 @@ enum gpioId_t {
CS_RAD_SENSOR,
ENABLE_RADFET,
+ PL_I2C_ARESETN,
+
PAPB_BUSY_N,
PAPB_EMPTY,
@@ -93,15 +95,10 @@ enum gpioId_t {
EN_RW_CS,
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,
diff --git a/common/config/eive/definitions.h b/common/config/eive/definitions.h
index 2083962a..b369f512 100644
--- a/common/config/eive/definitions.h
+++ b/common/config/eive/definitions.h
@@ -11,6 +11,8 @@ static constexpr char SD_1_MOUNT_POINT[] = "/mnt/sd1";
static constexpr char OBSW_UPDATE_ARCHIVE_FILE_NAME[] = "eive-sw-update.tar.xz";
static constexpr char STRIPPED_OBSW_BINARY_FILE_NAME[] = "eive-obsw-stripped";
static constexpr char OBSW_VERSION_FILE_NAME[] = "obsw_version.txt";
+static constexpr char PUS_SEQUENCE_COUNT_FILE[] = "pus-sequence-count.txt";
+static constexpr char CFDP_SEQUENCE_COUNT_FILE[] = "cfdp-sequence-count.txt";
static constexpr char OBSW_PATH[] = "/usr/bin/eive-obsw";
static constexpr char OBSW_VERSION_FILE_PATH[] = "/usr/share/eive-obsw/obsw_version.txt";
diff --git a/dummies/CMakeLists.txt b/dummies/CMakeLists.txt
index 6a49fcc6..bc8ab837 100644
--- a/dummies/CMakeLists.txt
+++ b/dummies/CMakeLists.txt
@@ -19,6 +19,7 @@ target_sources(
GpsCtrlDummy.cpp
GyroAdisDummy.cpp
GyroL3GD20Dummy.cpp
+ RadSensorDummy.cpp
MgmLIS3MDLDummy.cpp
PlPcduDummy.cpp
ExecutableComIfDummy.cpp
diff --git a/dummies/CoreControllerDummy.cpp b/dummies/CoreControllerDummy.cpp
index 8a027dbf..df2bef03 100644
--- a/dummies/CoreControllerDummy.cpp
+++ b/dummies/CoreControllerDummy.cpp
@@ -1,6 +1,6 @@
#include "CoreControllerDummy.h"
-#include
+#include
#include
#include
diff --git a/dummies/ImtqDummy.cpp b/dummies/ImtqDummy.cpp
index 0c8f9076..8570a9be 100644
--- a/dummies/ImtqDummy.cpp
+++ b/dummies/ImtqDummy.cpp
@@ -5,14 +5,19 @@
ImtqDummy::ImtqDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie,
power::Switch_t pwrSwitcher, bool enableHkSets)
: DeviceHandlerBase(objectId, comif, comCookie),
- setNoTorque(this),
- setWithTorque(this),
enableHkSets(enableHkSets),
+ statusSet(this),
+ dipoleSet(*this),
+ rawMtmNoTorque(this),
+ hkDatasetNoTorque(this),
+ rawMtmWithTorque(this),
+ hkDatasetWithTorque(this),
+ calMtmMeasurementSet(this),
switcher(pwrSwitcher) {}
ImtqDummy::~ImtqDummy() = default;
-void ImtqDummy::doStartUp() { setMode(MODE_NORMAL); }
+void ImtqDummy::doStartUp() { setMode(MODE_ON); }
void ImtqDummy::doShutDown() { setMode(_MODE_POWER_DOWN); }
@@ -79,17 +84,37 @@ ReturnValue_t ImtqDummy::initializeLocalDataPool(localpool::DataPool &localDataP
localDataPoolMap.emplace(imtq::MCU_TEMPERATURE_WT, new PoolEntry({0}));
poolManager.subscribeForDiagPeriodicPacket(
- subdp::DiagnosticsHkPeriodicParams(setNoTorque.getSid(), enableHkSets, 30.0));
+ subdp::DiagnosticsHkPeriodicParams(hkDatasetNoTorque.getSid(), enableHkSets, 30.0));
poolManager.subscribeForDiagPeriodicPacket(
- subdp::DiagnosticsHkPeriodicParams(setWithTorque.getSid(), enableHkSets, 30.0));
+ subdp::DiagnosticsHkPeriodicParams(hkDatasetWithTorque.getSid(), enableHkSets, 30.0));
+ poolManager.subscribeForDiagPeriodicPacket(
+ subdp::DiagnosticsHkPeriodicParams(rawMtmNoTorque.getSid(), false, 10.0));
+ poolManager.subscribeForDiagPeriodicPacket(
+ subdp::DiagnosticsHkPeriodicParams(rawMtmWithTorque.getSid(), false, 10.0));
+ poolManager.subscribeForDiagPeriodicPacket(
+ subdp::DiagnosticsHkPeriodicParams(calMtmMeasurementSet.getSid(), false, 10.0));
+ poolManager.subscribeForRegularPeriodicPacket(
+ subdp::RegularHkPeriodicParams(statusSet.getSid(), false, 10.0));
+ poolManager.subscribeForDiagPeriodicPacket(
+ subdp::DiagnosticsHkPeriodicParams(dipoleSet.getSid(), false, 10.0));
return DeviceHandlerBase::initializeLocalDataPool(localDataPoolMap, poolManager);
}
LocalPoolDataSetBase *ImtqDummy::getDataSetHandle(sid_t sid) {
- if (sid == setNoTorque.getSid()) {
- return &setNoTorque;
- } else if (sid == setWithTorque.getSid()) {
- return &setWithTorque;
+ if (sid == hkDatasetNoTorque.getSid()) {
+ return &hkDatasetNoTorque;
+ } else if (sid == dipoleSet.getSid()) {
+ return &dipoleSet;
+ } else if (sid == statusSet.getSid()) {
+ return &statusSet;
+ } else if (sid == hkDatasetWithTorque.getSid()) {
+ return &hkDatasetWithTorque;
+ } else if (sid == rawMtmWithTorque.getSid()) {
+ return &rawMtmWithTorque;
+ } else if (sid == calMtmMeasurementSet.getSid()) {
+ return &calMtmMeasurementSet;
+ } else if (sid == rawMtmNoTorque.getSid()) {
+ return &rawMtmNoTorque;
}
return nullptr;
}
diff --git a/dummies/ImtqDummy.h b/dummies/ImtqDummy.h
index 990df6e0..8c76affc 100644
--- a/dummies/ImtqDummy.h
+++ b/dummies/ImtqDummy.h
@@ -18,11 +18,18 @@ class ImtqDummy : public DeviceHandlerBase {
~ImtqDummy() override;
protected:
- ReturnValue_t getSwitches(const uint8_t **switches, uint8_t *numberOfSwitches) override;
- imtq::HkDatasetNoTorque setNoTorque;
- imtq::HkDatasetWithTorque setWithTorque;
bool enableHkSets;
+ imtq::StatusDataset statusSet;
+ imtq::DipoleActuationSet dipoleSet;
+ imtq::RawMtmMeasurementNoTorque rawMtmNoTorque;
+ imtq::HkDatasetNoTorque hkDatasetNoTorque;
+
+ imtq::RawMtmMeasurementWithTorque rawMtmWithTorque;
+ imtq::HkDatasetWithTorque hkDatasetWithTorque;
+
+ imtq::CalibratedMtmMeasurementSet calMtmMeasurementSet;
+
PoolEntry statusMode = PoolEntry({0});
PoolEntry statusError = PoolEntry({0});
PoolEntry statusConfig = PoolEntry({0});
@@ -42,6 +49,8 @@ class ImtqDummy : public DeviceHandlerBase {
power::Switch_t switcher = power::NO_SWITCH;
+ ReturnValue_t getSwitches(const uint8_t **switches, uint8_t *numberOfSwitches) override;
+
void doStartUp() override;
void doShutDown() override;
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;
diff --git a/dummies/Max31865Dummy.cpp b/dummies/Max31865Dummy.cpp
index 6ec1a716..99fc336a 100644
--- a/dummies/Max31865Dummy.cpp
+++ b/dummies/Max31865Dummy.cpp
@@ -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) {
diff --git a/dummies/PlPcduDummy.cpp b/dummies/PlPcduDummy.cpp
index 6bfc271f..7dfa4464 100644
--- a/dummies/PlPcduDummy.cpp
+++ b/dummies/PlPcduDummy.cpp
@@ -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); }
diff --git a/dummies/RadSensorDummy.cpp b/dummies/RadSensorDummy.cpp
new file mode 100644
index 00000000..5c42c594
--- /dev/null
+++ b/dummies/RadSensorDummy.cpp
@@ -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({0.0}));
+ localDataPoolMap.emplace(radSens::AIN0, new PoolEntry({0}));
+ localDataPoolMap.emplace(radSens::AIN1, new PoolEntry({0}));
+ localDataPoolMap.emplace(radSens::AIN4, new PoolEntry({0}));
+ localDataPoolMap.emplace(radSens::AIN5, new PoolEntry({0}));
+ localDataPoolMap.emplace(radSens::AIN6, new PoolEntry({0}));
+ localDataPoolMap.emplace(radSens::AIN7, new PoolEntry({0}));
+ poolManager.subscribeForRegularPeriodicPacket(
+ subdp::RegularHkPeriodicParams(sensorSet.getSid(), false, 20.0));
+ return returnvalue::OK;
+
+ return returnvalue::OK;
+}
+
+LocalPoolDataSetBase *RadSensorDummy::getDataSetHandle(sid_t sid) { return &sensorSet; }
diff --git a/dummies/RadSensorDummy.h b/dummies/RadSensorDummy.h
new file mode 100644
index 00000000..a3edf4f8
--- /dev/null
+++ b/dummies/RadSensorDummy.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include
+
+#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;
+};
diff --git a/dummies/RwDummy.cpp b/dummies/RwDummy.cpp
index 60652ef7..0bf4db42 100644
--- a/dummies/RwDummy.cpp
+++ b/dummies/RwDummy.cpp
@@ -3,13 +3,24 @@
#include
RwDummy::RwDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
- : DeviceHandlerBase(objectId, comif, comCookie) {}
+ : DeviceHandlerBase(objectId, comif, comCookie),
+
+ statusSet(this),
+ lastResetStatusSet(this),
+ tmDataset(this),
+ rwSpeedActuationSet(*this) {}
RwDummy::~RwDummy() {}
-void RwDummy::doStartUp() { setMode(MODE_ON); }
+void RwDummy::doStartUp() {
+ statusSet.setReportingEnabled(true);
+ setMode(MODE_ON);
+}
-void RwDummy::doShutDown() { setMode(MODE_OFF); }
+void RwDummy::doShutDown() {
+ statusSet.setReportingEnabled(false);
+ setMode(MODE_OFF);
+}
ReturnValue_t RwDummy::buildNormalDeviceCommand(DeviceCommandId_t *id) { return NOTHING_TO_SEND; }
@@ -74,5 +85,11 @@ ReturnValue_t RwDummy::initializeLocalDataPool(localpool::DataPool &localDataPoo
localDataPoolMap.emplace(rws::SPI_BYTES_READ, new PoolEntry({0}));
localDataPoolMap.emplace(rws::SPI_REG_OVERRUN_ERRORS, new PoolEntry({0}));
localDataPoolMap.emplace(rws::SPI_TOTAL_ERRORS, new PoolEntry({0}));
+ poolManager.subscribeForDiagPeriodicPacket(
+ subdp::DiagnosticsHkPeriodicParams(statusSet.getSid(), false, 12.0));
+ poolManager.subscribeForRegularPeriodicPacket(
+ subdp::RegularHkPeriodicParams(tmDataset.getSid(), false, 30.0));
+ poolManager.subscribeForRegularPeriodicPacket(
+ subdp::RegularHkPeriodicParams(lastResetStatusSet.getSid(), false, 30.0));
return returnvalue::OK;
}
diff --git a/dummies/RwDummy.h b/dummies/RwDummy.h
index 5673717a..03629937 100644
--- a/dummies/RwDummy.h
+++ b/dummies/RwDummy.h
@@ -2,6 +2,7 @@
#define DUMMIES_RWDUMMY_H_
#include
+#include
class RwDummy : public DeviceHandlerBase {
public:
@@ -15,6 +16,11 @@ class RwDummy : public DeviceHandlerBase {
virtual ~RwDummy();
protected:
+ rws::StatusSet statusSet;
+ rws::LastResetSatus lastResetStatusSet;
+ rws::TmDataset tmDataset;
+ rws::RwSpeedActuationSet rwSpeedActuationSet;
+
PoolEntry rwSpeed = PoolEntry({0});
PoolEntry rampTime = PoolEntry({10});
diff --git a/dummies/SusDummy.cpp b/dummies/SusDummy.cpp
index 75e36676..3e03f198 100644
--- a/dummies/SusDummy.cpp
+++ b/dummies/SusDummy.cpp
@@ -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); }
diff --git a/dummies/TemperatureSensorInserter.cpp b/dummies/TemperatureSensorInserter.cpp
index 14a005aa..942231f5 100644
--- a/dummies/TemperatureSensorInserter.cpp
+++ b/dummies/TemperatureSensorInserter.cpp
@@ -7,9 +7,9 @@
#include
#include
-TemperatureSensorInserter::TemperatureSensorInserter(object_id_t objectId,
- Max31865DummyMap tempSensorDummies_,
- Tmp1075DummyMap tempTmpSensorDummies_)
+TemperatureSensorInserter::TemperatureSensorInserter(
+ object_id_t objectId, Max31865DummyMap tempSensorDummies_,
+ std::optional tempTmpSensorDummies_)
: SystemObject(objectId),
max31865DummyMap(std::move(tempSensorDummies_)),
tmp1075DummyMap(std::move(tempTmpSensorDummies_)) {}
@@ -25,8 +25,10 @@ ReturnValue_t TemperatureSensorInserter::performOperation(uint8_t opCode) {
for (auto& rtdDummy : max31865DummyMap) {
rtdDummy.second->setTemperature(10, true);
}
- for (auto& tmpDummy : tmp1075DummyMap) {
- tmpDummy.second->setTemperature(10, true);
+ if (tmp1075DummyMap.has_value()) {
+ for (auto& tmpDummy : tmp1075DummyMap.value()) {
+ tmpDummy.second->setTemperature(10, true);
+ }
}
tempsWereInitialized = true;
}
@@ -96,6 +98,25 @@ ReturnValue_t TemperatureSensorInserter::performOperation(uint8_t opCode) {
}
break;
}
+ case (TestCase::COLD_PLOC_CONSECUTIVE): {
+ if (cycles == 15) {
+ sif::debug << "Setting cold PLOC temperature" << std::endl;
+ max31865DummyMap[objects::RTD_0_IC3_PLOC_HEATSPREADER]->setTemperature(-15, true);
+ }
+ if (cycles == 30) {
+ sif::debug << "Setting warmer PLOC temperature" << std::endl;
+ max31865DummyMap[objects::RTD_0_IC3_PLOC_HEATSPREADER]->setTemperature(0, true);
+ }
+ if (cycles == 45) {
+ sif::debug << "Setting cold PLOC temperature again" << std::endl;
+ max31865DummyMap[objects::RTD_0_IC3_PLOC_HEATSPREADER]->setTemperature(-15, true);
+ }
+ if (cycles == 60) {
+ sif::debug << "Setting warmer PLOC temperature again" << std::endl;
+ max31865DummyMap[objects::RTD_0_IC3_PLOC_HEATSPREADER]->setTemperature(0, true);
+ }
+ break;
+ }
case (TestCase::COLD_CAMERA): {
if (cycles == 15) {
sif::debug << "Setting cold CAM temperature" << std::endl;
@@ -105,6 +126,21 @@ ReturnValue_t TemperatureSensorInserter::performOperation(uint8_t opCode) {
sif::debug << "Setting CAM temperature back to normal" << std::endl;
max31865DummyMap[objects::RTD_2_IC5_4K_CAMERA]->setTemperature(0, true);
}
+ break;
+ }
+ case (TestCase::COLD_PLOC_STAYS_COLD): {
+ if (cycles == 15) {
+ sif::debug << "Setting cold PLOC temperature" << std::endl;
+ max31865DummyMap[objects::RTD_0_IC3_PLOC_HEATSPREADER]->setTemperature(-40, true);
+ }
+ break;
+ }
+ case (TestCase::COLD_CAMERA_STAYS_COLD): {
+ if (cycles == 15) {
+ sif::debug << "Setting cold PLOC temperature" << std::endl;
+ max31865DummyMap[objects::RTD_2_IC5_4K_CAMERA]->setTemperature(-40, true);
+ }
+ break;
}
}
cycles++;
diff --git a/dummies/TemperatureSensorInserter.h b/dummies/TemperatureSensorInserter.h
index eb6cc1ba..9ca3c936 100644
--- a/dummies/TemperatureSensorInserter.h
+++ b/dummies/TemperatureSensorInserter.h
@@ -12,7 +12,7 @@ class TemperatureSensorInserter : public ExecutableObjectIF, public SystemObject
using Max31865DummyMap = std::map;
using Tmp1075DummyMap = std::map;
explicit TemperatureSensorInserter(object_id_t objectId, Max31865DummyMap tempSensorDummies_,
- Tmp1075DummyMap tempTmpSensorDummies_);
+ std::optional 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;
enum TestCase {
NONE = 0,
@@ -32,6 +32,9 @@ class TemperatureSensorInserter : public ExecutableObjectIF, public SystemObject
COLD_STR = 4,
COLD_STR_CONSECUTIVE = 5,
COLD_CAMERA = 6,
+ COLD_PLOC_CONSECUTIVE = 7,
+ COLD_PLOC_STAYS_COLD = 8,
+ COLD_CAMERA_STAYS_COLD = 9
};
int iteration = 0;
uint32_t cycles = 0;
diff --git a/dummies/Tmp1075Dummy.cpp b/dummies/Tmp1075Dummy.cpp
index 91a50774..7e61acef 100644
--- a/dummies/Tmp1075Dummy.cpp
+++ b/dummies/Tmp1075Dummy.cpp
@@ -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({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; }
diff --git a/dummies/Tmp1075Dummy.h b/dummies/Tmp1075Dummy.h
index 570fcd42..feab4f98 100644
--- a/dummies/Tmp1075Dummy.h
+++ b/dummies/Tmp1075Dummy.h
@@ -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;
diff --git a/dummies/helperFactory.cpp b/dummies/helperFactory.cpp
index 157d11d3..b23720b4 100644
--- a/dummies/helperFactory.cpp
+++ b/dummies/helperFactory.cpp
@@ -18,6 +18,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -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 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 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,11 +244,15 @@ 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);
- auto* plPcduDummy =
- new PlPcduDummy(objects::PLPCDU_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
- plPcduDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
+ if (cfg.addScexDummy) {
+ auto* scexDummy = new ScexDummy(objects::SCEX, objects::DUMMY_COM_IF, comCookieDummy);
+ scexDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
+ }
+ if (cfg.addPlPcduDummy) {
+ auto* plPcduDummy =
+ new PlPcduDummy(objects::PLPCDU_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
+ plPcduDummy->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
+ }
if (cfg.addPlocDummies) {
auto* plocMpsocDummy =
new PlocMpsocDummy(objects::PLOC_MPSOC_HANDLER, objects::DUMMY_COM_IF, comCookieDummy);
@@ -239,4 +261,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);
+ }
}
diff --git a/dummies/helperFactory.h b/dummies/helperFactory.h
index bab9d8d8..34d167f0 100644
--- a/dummies/helperFactory.h
+++ b/dummies/helperFactory.h
@@ -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,13 @@ struct DummyCfg {
bool addTempSensorDummies = true;
bool addRtdComIFDummy = true;
bool addPlocDummies = true;
+ bool addStrDummy = true;
+ bool addTmpDummies = true;
+ bool addRadSensorDummy = true;
+ bool addPlPcduDummy = false;
+ Tmp1075Cfg tmp1075Cfg;
bool addCamSwitcherDummy = false;
+ bool addScexDummy = false;
};
void createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitch, GpioIF* gpioIF, bool enableHkSets);
diff --git a/fsfw b/fsfw
index 0a977ea6..d575da85 160000
--- a/fsfw
+++ b/fsfw
@@ -1 +1 @@
-Subproject commit 0a977ea688cd78585aabb9ba511eaf8030452712
+Subproject commit d575da85407e029dabecaffa5368f0c9f1034941
diff --git a/generators/bsp_hosted_events.csv b/generators/bsp_hosted_events.csv
index e6a320b8..99ea0670 100644
--- a/generators/bsp_hosted_events.csv
+++ b/generators/bsp_hosted_events.csv
@@ -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
@@ -254,6 +255,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
13800;0x35e8;MISSING_PACKET;LOW;No description;mission/payload/scexHelpers.h
13801;0x35e9;EXPERIMENT_TIMEDOUT;LOW;No description;mission/payload/scexHelpers.h
13802;0x35ea;MULTI_PACKET_COMMAND_DONE;INFO;No description;mission/payload/scexHelpers.h
+13803;0x35eb;FS_UNUSABLE;LOW;No description;mission/payload/scexHelpers.h
13901;0x364d;SET_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
13902;0x364e;GET_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
13903;0x364f;INSERT_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
@@ -271,6 +273,8 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
14010;0x36ba;TRYING_I2C_RECOVERY;HIGH;I2C is unavailable. Trying recovery of I2C bus by power cycling all I2C devices.;mission/sysDefs.h
14011;0x36bb;I2C_REBOOT;HIGH;I2C is unavailable. Recovery did not work, performing full reboot.;mission/sysDefs.h
14012;0x36bc;PDEC_REBOOT;HIGH;PDEC recovery through reset was not possible, performing full reboot.;mission/sysDefs.h
+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
@@ -279,6 +283,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
diff --git a/generators/bsp_q7s_events.csv b/generators/bsp_q7s_events.csv
index e6a320b8..99ea0670 100644
--- a/generators/bsp_q7s_events.csv
+++ b/generators/bsp_q7s_events.csv
@@ -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
@@ -254,6 +255,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
13800;0x35e8;MISSING_PACKET;LOW;No description;mission/payload/scexHelpers.h
13801;0x35e9;EXPERIMENT_TIMEDOUT;LOW;No description;mission/payload/scexHelpers.h
13802;0x35ea;MULTI_PACKET_COMMAND_DONE;INFO;No description;mission/payload/scexHelpers.h
+13803;0x35eb;FS_UNUSABLE;LOW;No description;mission/payload/scexHelpers.h
13901;0x364d;SET_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
13902;0x364e;GET_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
13903;0x364f;INSERT_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
@@ -271,6 +273,8 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
14010;0x36ba;TRYING_I2C_RECOVERY;HIGH;I2C is unavailable. Trying recovery of I2C bus by power cycling all I2C devices.;mission/sysDefs.h
14011;0x36bb;I2C_REBOOT;HIGH;I2C is unavailable. Recovery did not work, performing full reboot.;mission/sysDefs.h
14012;0x36bc;PDEC_REBOOT;HIGH;PDEC recovery through reset was not possible, performing full reboot.;mission/sysDefs.h
+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
@@ -279,6 +283,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
diff --git a/generators/events/event_parser.py b/generators/events/event_parser.py
index 94c1580c..f7463cf9 100644
--- a/generators/events/event_parser.py
+++ b/generators/events/event_parser.py
@@ -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
diff --git a/generators/events/translateEvents.cpp b/generators/events/translateEvents.cpp
index 79a828f2..98c5035f 100644
--- a/generators/events/translateEvents.cpp
+++ b/generators/events/translateEvents.cpp
@@ -1,7 +1,7 @@
/**
- * @brief Auto-generated event translation file. Contains 296 translations.
+ * @brief Auto-generated event translation file. Contains 303 translations.
* @details
- * Generated on: 2023-06-13 07:54:32
+ * Generated on: 2023-08-03 13:36:37
*/
#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";
@@ -260,6 +261,7 @@ const char *TX_OFF_STRING = "TX_OFF";
const char *MISSING_PACKET_STRING = "MISSING_PACKET";
const char *EXPERIMENT_TIMEDOUT_STRING = "EXPERIMENT_TIMEDOUT";
const char *MULTI_PACKET_COMMAND_DONE_STRING = "MULTI_PACKET_COMMAND_DONE";
+const char *FS_UNUSABLE_STRING = "FS_UNUSABLE";
const char *SET_CONFIGFILEVALUE_FAILED_STRING = "SET_CONFIGFILEVALUE_FAILED";
const char *GET_CONFIGFILEVALUE_FAILED_STRING = "GET_CONFIGFILEVALUE_FAILED";
const char *INSERT_CONFIGFILEVALUE_FAILED_STRING = "INSERT_CONFIGFILEVALUE_FAILED";
@@ -277,6 +279,8 @@ const char *INDIVIDUAL_BOOT_COUNTS_STRING = "INDIVIDUAL_BOOT_COUNTS";
const char *TRYING_I2C_RECOVERY_STRING = "TRYING_I2C_RECOVERY";
const char *I2C_REBOOT_STRING = "I2C_REBOOT";
const char *PDEC_REBOOT_STRING = "PDEC_REBOOT";
+const char *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";
@@ -285,6 +289,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 +579,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):
@@ -814,6 +823,8 @@ const char *translateEvents(Event event) {
return EXPERIMENT_TIMEDOUT_STRING;
case (13802):
return MULTI_PACKET_COMMAND_DONE_STRING;
+ case (13803):
+ return FS_UNUSABLE_STRING;
case (13901):
return SET_CONFIGFILEVALUE_FAILED_STRING;
case (13902):
@@ -848,6 +859,10 @@ const char *translateEvents(Event event) {
return I2C_REBOOT_STRING;
case (14012):
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):
@@ -864,6 +879,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):
diff --git a/generators/objects/translateObjects.cpp b/generators/objects/translateObjects.cpp
index f1e7f6c6..ce21a66f 100644
--- a/generators/objects/translateObjects.cpp
+++ b/generators/objects/translateObjects.cpp
@@ -2,7 +2,7 @@
* @brief Auto-generated object translation file.
* @details
* Contains 175 translations.
- * Generated on: 2023-06-13 07:54:32
+ * Generated on: 2023-08-03 13:36:37
*/
#include "translateObjects.h"
diff --git a/linux/acs/StrComHandler.cpp b/linux/acs/StrComHandler.cpp
index 5ae00c94..2db73f35 100644
--- a/linux/acs/StrComHandler.cpp
+++ b/linux/acs/StrComHandler.cpp
@@ -2,6 +2,7 @@
#include
#include
+#include
#include
#include
#include
@@ -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(state));
+ readOneReply(static_cast(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(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);
diff --git a/linux/fsfwconfig/events/translateEvents.cpp b/linux/fsfwconfig/events/translateEvents.cpp
index 79a828f2..98c5035f 100644
--- a/linux/fsfwconfig/events/translateEvents.cpp
+++ b/linux/fsfwconfig/events/translateEvents.cpp
@@ -1,7 +1,7 @@
/**
- * @brief Auto-generated event translation file. Contains 296 translations.
+ * @brief Auto-generated event translation file. Contains 303 translations.
* @details
- * Generated on: 2023-06-13 07:54:32
+ * Generated on: 2023-08-03 13:36:37
*/
#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";
@@ -260,6 +261,7 @@ const char *TX_OFF_STRING = "TX_OFF";
const char *MISSING_PACKET_STRING = "MISSING_PACKET";
const char *EXPERIMENT_TIMEDOUT_STRING = "EXPERIMENT_TIMEDOUT";
const char *MULTI_PACKET_COMMAND_DONE_STRING = "MULTI_PACKET_COMMAND_DONE";
+const char *FS_UNUSABLE_STRING = "FS_UNUSABLE";
const char *SET_CONFIGFILEVALUE_FAILED_STRING = "SET_CONFIGFILEVALUE_FAILED";
const char *GET_CONFIGFILEVALUE_FAILED_STRING = "GET_CONFIGFILEVALUE_FAILED";
const char *INSERT_CONFIGFILEVALUE_FAILED_STRING = "INSERT_CONFIGFILEVALUE_FAILED";
@@ -277,6 +279,8 @@ const char *INDIVIDUAL_BOOT_COUNTS_STRING = "INDIVIDUAL_BOOT_COUNTS";
const char *TRYING_I2C_RECOVERY_STRING = "TRYING_I2C_RECOVERY";
const char *I2C_REBOOT_STRING = "I2C_REBOOT";
const char *PDEC_REBOOT_STRING = "PDEC_REBOOT";
+const char *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";
@@ -285,6 +289,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 +579,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):
@@ -814,6 +823,8 @@ const char *translateEvents(Event event) {
return EXPERIMENT_TIMEDOUT_STRING;
case (13802):
return MULTI_PACKET_COMMAND_DONE_STRING;
+ case (13803):
+ return FS_UNUSABLE_STRING;
case (13901):
return SET_CONFIGFILEVALUE_FAILED_STRING;
case (13902):
@@ -848,6 +859,10 @@ const char *translateEvents(Event event) {
return I2C_REBOOT_STRING;
case (14012):
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):
@@ -864,6 +879,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):
diff --git a/linux/fsfwconfig/objects/translateObjects.cpp b/linux/fsfwconfig/objects/translateObjects.cpp
index f1e7f6c6..ce21a66f 100644
--- a/linux/fsfwconfig/objects/translateObjects.cpp
+++ b/linux/fsfwconfig/objects/translateObjects.cpp
@@ -2,7 +2,7 @@
* @brief Auto-generated object translation file.
* @details
* Contains 175 translations.
- * Generated on: 2023-06-13 07:54:32
+ * Generated on: 2023-08-03 13:36:37
*/
#include "translateObjects.h"
diff --git a/linux/ipcore/AxiPtmeConfig.cpp b/linux/ipcore/AxiPtmeConfig.cpp
index 6dee3e2f..b21edf5b 100644
--- a/linux/ipcore/AxiPtmeConfig.cpp
+++ b/linux/ipcore/AxiPtmeConfig.cpp
@@ -16,9 +16,9 @@ AxiPtmeConfig::AxiPtmeConfig(object_id_t objectId, std::string axiUio, int mapNu
AxiPtmeConfig::~AxiPtmeConfig() {}
ReturnValue_t AxiPtmeConfig::initialize() {
- ReturnValue_t result = returnvalue::OK;
UioMapper uioMapper(axiUio, mapNum);
- result = uioMapper.getMappedAdress(&baseAddress, UioMapper::Permissions::READ_WRITE);
+ ReturnValue_t result =
+ uioMapper.getMappedAdress(&baseAddress, UioMapper::Permissions::READ_WRITE);
if (result != returnvalue::OK) {
return result;
}
@@ -26,8 +26,7 @@ ReturnValue_t AxiPtmeConfig::initialize() {
}
ReturnValue_t AxiPtmeConfig::writeCaduRateReg(uint8_t rateVal) {
- ReturnValue_t result = returnvalue::OK;
- result = mutex->lockMutex(timeoutType, mutexTimeout);
+ ReturnValue_t result = mutex->lockMutex(timeoutType, mutexTimeout);
if (result != returnvalue::OK) {
sif::warning << "AxiPtmeConfig::writeCaduRateReg: Failed to lock mutex" << std::endl;
return returnvalue::FAILED;
@@ -41,6 +40,11 @@ ReturnValue_t AxiPtmeConfig::writeCaduRateReg(uint8_t rateVal) {
return returnvalue::OK;
}
+uint8_t AxiPtmeConfig::readCaduRateReg() {
+ MutexGuard mg(mutex);
+ return static_cast(*(baseAddress + CADU_BITRATE_REG));
+}
+
void AxiPtmeConfig::enableTxclockManipulator() {
writeBit(COMMON_CONFIG_REG, true, BitPos::EN_TX_CLK_MANIPULATOR);
}
diff --git a/linux/ipcore/AxiPtmeConfig.h b/linux/ipcore/AxiPtmeConfig.h
index 98188775..ebdf4d38 100644
--- a/linux/ipcore/AxiPtmeConfig.h
+++ b/linux/ipcore/AxiPtmeConfig.h
@@ -38,6 +38,7 @@ class AxiPtmeConfig : public SystemObject {
* frequency of the clock connected to the bit clock input of PTME.
*/
ReturnValue_t writeCaduRateReg(uint8_t rateVal);
+ uint8_t readCaduRateReg();
/**
* @brief Next to functions control the tx clock manipulator component
diff --git a/linux/ipcore/PapbVcInterface.cpp b/linux/ipcore/PapbVcInterface.cpp
index 60968cc6..5dcb4519 100644
--- a/linux/ipcore/PapbVcInterface.cpp
+++ b/linux/ipcore/PapbVcInterface.cpp
@@ -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(&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(data + idx);
- // // vcBaseReg + DATA_REG_OFFSET + 2 = static_cast(data + idx + 1);
- // // vcBaseReg + DATA_REG_OFFSET + 1 = static_cast(data + idx + 2);
- // // vcBaseReg + DATA_REG_OFFSET = static_cast(data + idx + 3);
- //
- // // std::memcpy((vcBaseReg + DATA_REG_OFFSET), data + idx , nextWriteSize);
- // *(vcBaseReg + DATA_REG_OFFSET) = *reinterpret_cast(data + idx);
- // //uint8_t* byteReg = reinterpret_cast(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(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(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];
diff --git a/linux/ipcore/PapbVcInterface.h b/linux/ipcore/PapbVcInterface.h
index e54def5d..b5160748 100644
--- a/linux/ipcore/PapbVcInterface.h
+++ b/linux/ipcore/PapbVcInterface.h
@@ -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)
diff --git a/linux/ipcore/PtmeConfig.cpp b/linux/ipcore/PtmeConfig.cpp
index 5f247b54..5b6b9343 100644
--- a/linux/ipcore/PtmeConfig.cpp
+++ b/linux/ipcore/PtmeConfig.cpp
@@ -26,6 +26,11 @@ ReturnValue_t PtmeConfig::setRate(uint32_t bitRate) {
return axiPtmeConfig->writeCaduRateReg(static_cast(rateVal));
}
+uint32_t PtmeConfig::getRate() {
+ uint8_t rateReg = axiPtmeConfig->readCaduRateReg();
+ return (BIT_CLK_FREQ / (rateReg + 1));
+}
+
void PtmeConfig::invertTxClock(bool invert) {
if (invert) {
axiPtmeConfig->enableTxclockInversion();
diff --git a/linux/ipcore/PtmeConfig.h b/linux/ipcore/PtmeConfig.h
index 87614187..11eeff7d 100644
--- a/linux/ipcore/PtmeConfig.h
+++ b/linux/ipcore/PtmeConfig.h
@@ -32,6 +32,7 @@ class PtmeConfig : public SystemObject {
* of the CADU clock due to the convolutional code added by the s-Band transceiver.
*/
ReturnValue_t setRate(uint32_t bitRate);
+ uint32_t getRate();
/**
* @brief Will change the time the tx data signal is updated with respect to the tx clock
diff --git a/misc/eclipse/.cproject b/misc/eclipse/.cproject
index 4cfe3fa1..154cb27e 100644
--- a/misc/eclipse/.cproject
+++ b/misc/eclipse/.cproject
@@ -57,7 +57,8 @@
-
+
+
@@ -119,7 +120,8 @@
-
+
+
@@ -187,7 +189,8 @@
-
+
+
@@ -255,7 +258,8 @@
-
+
+
@@ -418,7 +422,8 @@
-
+
+
@@ -580,7 +585,8 @@
-
+
+
@@ -750,7 +756,8 @@
-
+
+
@@ -917,7 +924,8 @@
-
+
+
@@ -1084,7 +1092,8 @@
-
+
+
@@ -1149,7 +1158,8 @@
-
+
+
@@ -1172,7 +1182,7 @@
-
+
@@ -1317,7 +1327,9 @@
-
+
+
+
@@ -1386,7 +1398,8 @@
-
+
+
diff --git a/mission/acs/SusHandler.cpp b/mission/acs/SusHandler.cpp
index 5fbbca4f..7a9e7d4f 100644
--- a/mission/acs/SusHandler.cpp
+++ b/mission/acs/SusHandler.cpp
@@ -30,6 +30,7 @@ void SusHandler::doStartUp() {
void SusHandler::doShutDown() {
if (internalState != InternalState::SHUTDOWN) {
PoolReadGuard pg(&dataset);
+ dataset.tempC = thermal::INVALID_TEMPERATURE;
dataset.setValidity(false, true);
internalState = InternalState::SHUTDOWN;
commandExecuted = false;
diff --git a/mission/acs/defs.h b/mission/acs/defs.h
index 41d09976..677ce37a 100644
--- a/mission/acs/defs.h
+++ b/mission/acs/defs.h
@@ -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,
};
diff --git a/mission/acs/str/StarTrackerHandler.cpp b/mission/acs/str/StarTrackerHandler.cpp
index cf2a5919..a6091d7c 100644
--- a/mission/acs/str/StarTrackerHandler.cpp
+++ b/mission/acs/str/StarTrackerHandler.cpp
@@ -1,3 +1,4 @@
+#include
#include
#include
#include
@@ -18,6 +19,7 @@ extern "C" {
#include "OBSWConfig.h"
#include "eive/definitions.h"
+#include "fsfw/thermal/tcsDefinitions.h"
std::atomic_bool JCFG_DONE(false);
@@ -87,7 +89,6 @@ void StarTrackerHandler::doStartUp() {
default:
return;
}
- solutionSet.setReportingEnabled(true);
startupState = StartupState::DONE;
internalState = InternalState::IDLE;
setMode(_MODE_TO_ON);
@@ -106,11 +107,14 @@ void StarTrackerHandler::doShutDown() {
solutionSet.caliQx.value = 0.0;
solutionSet.caliQy.value = 0.0;
solutionSet.caliQz.value = 0.0;
- solutionSet.isTrustWorthy = 0;
+ solutionSet.isTrustWorthy.value = 0;
solutionSet.setValidity(false, true);
}
{
PoolReadGuard pg(&temperatureSet);
+ temperatureSet.fpgaTemperature = thermal::INVALID_TEMPERATURE;
+ temperatureSet.cmosTemperature = thermal::INVALID_TEMPERATURE;
+ temperatureSet.mcuTemperature = thermal::INVALID_TEMPERATURE;
temperatureSet.setValidity(false, true);
}
reinitNextSetParam = false;
@@ -321,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) {
@@ -345,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(paramJsonFile.c_str()), paramJsonFile.size());
}
case (FwBootState::LIMITS): {
- bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::LIMITS;
return buildCommandFromCommand(
*id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size());
}
case (FwBootState::TRACKING): {
- bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::TRACKING;
return buildCommandFromCommand(
*id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size());
}
case FwBootState::MOUNTING:
- bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::MOUNTING;
return buildCommandFromCommand(
*id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::IMAGE_PROCESSOR:
- bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::IMAGE_PROCESSOR;
return buildCommandFromCommand(
*id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::CAMERA:
- bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::CAMERA;
return buildCommandFromCommand(
*id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::CENTROIDING:
- bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::CENTROIDING;
return buildCommandFromCommand(
*id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::LISA:
- bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::LISA;
return buildCommandFromCommand(
*id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::MATCHING:
- bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::MATCHING;
return buildCommandFromCommand(
*id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::VALIDATION:
- bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::VALIDATION;
return buildCommandFromCommand(
*id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::ALGO:
- bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::ALGO;
return buildCommandFromCommand(
*id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::LOG_SUBSCRIPTION:
- bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::LOGSUBSCRIPTION;
return buildCommandFromCommand(
*id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size());
case FwBootState::DEBUG_CAMERA:
- bootState = FwBootState::WAIT_FOR_EXECUTION;
*id = startracker::DEBUG_CAMERA;
return buildCommandFromCommand(
*id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size());
+ case FwBootState::AUTO_THRESHOLD:
+ *id = startracker::AUTO_THRESHOLD;
+ return buildCommandFromCommand(
+ *id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size());
default: {
sif::error << "STR: Unexpected boot state" << (int)bootState << std::endl;
return NOTHING_TO_SEND;
@@ -455,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(tv.tv_sec) * 1000 * 1000) + (static_cast(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;
@@ -547,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);
@@ -651,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);
@@ -810,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;
@@ -833,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;
}
@@ -856,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);
@@ -897,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;
@@ -956,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;
}
@@ -1363,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;
@@ -1430,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;
@@ -1857,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(*(rawFrame + PARAMETER_ID_OFFSET)) << std::endl;
if (internalState != InternalState::IDLE) {
internalState = InternalState::IDLE;
@@ -1865,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(*(rawFrame + ACTION_ID_OFFSET)) << " and status "
<< static_cast(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) {
@@ -1975,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;
@@ -2052,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;
@@ -2062,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;
}
@@ -2103,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;
diff --git a/mission/acs/str/StarTrackerHandler.h b/mission/acs/str/StarTrackerHandler.h
index 7bcc9f2a..1e790695 100644
--- a/mission/acs/str/StarTrackerHandler.h
+++ b/mission/acs/str/StarTrackerHandler.h
@@ -6,6 +6,7 @@
#include
#include
#include
+#include
#include
@@ -16,7 +17,7 @@
#include "fsfw/timemanager/Countdown.h"
extern "C" {
-#include
+#include
}
/**
@@ -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
diff --git a/mission/acs/str/arcsecJsonKeys.h b/mission/acs/str/arcsecJsonKeys.h
index f9e2f4f1..c44ece9f 100644
--- a/mission/acs/str/arcsecJsonKeys.h
+++ b/mission/acs/str/arcsecJsonKeys.h
@@ -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_ */
diff --git a/mission/acs/str/strHelpers.h b/mission/acs/str/strHelpers.h
index 69729df5..c6336186 100644
--- a/mission/acs/str/strHelpers.h
+++ b/mission/acs/str/strHelpers.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 {
// Ticks timestamp
lp_var_t ticks = lp_var_t(sid.objectId, PoolIds::TICKS_SOLUTION_SET, this);
/// Unix time stamp
- lp_var_t time = lp_var_t(sid.objectId, PoolIds::TIME_SOLUTION_SET, this);
+ lp_var_t timeUs = lp_var_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 caliQw = lp_var_t(sid.objectId, PoolIds::CALI_QW, this);
@@ -695,7 +712,7 @@ class SolutionSet : public StaticLocalDataSet {
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;
diff --git a/mission/acs/str/strJsonCommands.cpp b/mission/acs/str/strJsonCommands.cpp
index 134a00a0..5a910f87 100644
--- a/mission/acs/str/strJsonCommands.cpp
+++ b/mission/acs/str/strJsonCommands.cpp
@@ -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;
+}
diff --git a/mission/acs/str/strJsonCommands.h b/mission/acs/str/strJsonCommands.h
index 99588f9c..7e75c0b1 100644
--- a/mission/acs/str/strJsonCommands.h
+++ b/mission/acs/str/strJsonCommands.h
@@ -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
*
diff --git a/mission/cfdp/CfdpHandler.cpp b/mission/cfdp/CfdpHandler.cpp
index baf501e4..fa35535c 100644
--- a/mission/cfdp/CfdpHandler.cpp
+++ b/mission/cfdp/CfdpHandler.cpp
@@ -93,7 +93,8 @@ ReturnValue_t CfdpHandler::handleCfdpPacket(TmTcMessage& msg) {
return INVALID_PDU_FORMAT;
}
if (not FileDirectiveReader::checkFileDirective(pduDataField[0])) {
- sif::error << "CfdpHandler: Invalid PDU directive field " << pduDataField[0] << std::endl;
+ sif::error << "CfdpHandler: Invalid PDU directive field " << static_cast(pduDataField[0])
+ << std::endl;
return INVALID_DIRECTIVE_FIELD;
}
auto directive = static_cast(pduDataField[0]);
diff --git a/mission/com/CcsdsIpCoreHandler.cpp b/mission/com/CcsdsIpCoreHandler.cpp
index 625c90cd..19dd4f5a 100644
--- a/mission/com/CcsdsIpCoreHandler.cpp
+++ b/mission/com/CcsdsIpCoreHandler.cpp
@@ -246,7 +246,13 @@ ReturnValue_t CcsdsIpCoreHandler::checkModeCommand(Mode_t mode, Submode_t submod
void CcsdsIpCoreHandler::startTransition(Mode_t mode, Submode_t submode) {
triggerEvent(CHANGING_MODE, mode, submode);
if (mode == HasModesIF::MODE_ON) {
- if (this->submode != submode) {
+ uint32_t currentRate = ptmeConfig.getRate();
+ // Check whether the rate actually changes.
+ if ((this->submode != submode) and
+ (((submode == static_cast(com::CcsdsSubmode::DATARATE_LOW) and
+ (currentRate != RATE_100KBPS))) or
+ ((submode == static_cast(com::CcsdsSubmode::DATARATE_HIGH) and
+ (currentRate != RATE_500KBPS))))) {
initPtmeUpdateAfterXCycles();
updateContext.enableTransmitAfterPtmeUpdate = true;
updateContext.updateClockRate = true;
diff --git a/mission/com/LiveTmTask.cpp b/mission/com/LiveTmTask.cpp
index d09c6ced..39648c15 100644
--- a/mission/com/LiveTmTask.cpp
+++ b/mission/com/LiveTmTask.cpp
@@ -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;
}
diff --git a/mission/com/PersistentLogTmStoreTask.cpp b/mission/com/PersistentLogTmStoreTask.cpp
index 77f2bb7d..28545457 100644
--- a/mission/com/PersistentLogTmStoreTask.cpp
+++ b/mission/com/PersistentLogTmStoreTask.cpp
@@ -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);
}
}
}
diff --git a/mission/com/PersistentSingleTmStoreTask.cpp b/mission/com/PersistentSingleTmStoreTask.cpp
index 1b77365b..d6f43289 100644
--- a/mission/com/PersistentSingleTmStoreTask.cpp
+++ b/mission/com/PersistentSingleTmStoreTask.cpp
@@ -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);
}
}
}
diff --git a/mission/com/SyrlinksHandler.cpp b/mission/com/SyrlinksHandler.cpp
index 6fbc8dc2..50e6a56e 100644
--- a/mission/com/SyrlinksHandler.cpp
+++ b/mission/com/SyrlinksHandler.cpp
@@ -773,11 +773,13 @@ void SyrlinksHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) {
auto txStandbyHandler = [&]() {
txDataset.setReportingEnabled(false);
poolManager.changeCollectionInterval(temperatureSet.getSid(), 60.0);
+ poolManager.changeCollectionInterval(rxDataset.getSid(), 60.0);
transState = TransitionState::SET_TX_STANDBY;
internalState = InternalState::TX_TRANSITION;
};
auto txOnHandler = [&](TransitionState tgtTransitionState) {
txDataset.setReportingEnabled(true);
+ poolManager.changeCollectionInterval(rxDataset.getSid(), 5.0);
poolManager.changeCollectionInterval(txDataset.getSid(), 10.0);
poolManager.changeCollectionInterval(temperatureSet.getSid(), 5.0);
transState = tgtTransitionState;
diff --git a/mission/com/TmStoreTaskBase.cpp b/mission/com/TmStoreTaskBase.cpp
index 0470dc04..80900975 100644
--- a/mission/com/TmStoreTaskBase.cpp
+++ b/mission/com/TmStoreTaskBase.cpp
@@ -45,13 +45,19 @@ bool TmStoreTaskBase::handleOneStore(PersistentTmStoreWithTmQueue& store,
} else {
Command_t execCmd;
// Handle TC requests, for example deletion or retrieval requests.
+ // TODO: Not really clean here.. would be better if the executed command is returns as an
+ // enumeration.
result = store.handleCommandQueue(ipcStore, execCmd);
- if (result == returnvalue::OK) {
- if (execCmd == TmStoreMessage::DOWNLINK_STORE_CONTENT_TIME) {
+ if (execCmd == TmStoreMessage::DOWNLINK_STORE_CONTENT_TIME) {
+ if (result == PersistentTmStore::DUMP_DONE) {
+ dumpDoneHandler(store, dumpContext);
+ } else if (result == returnvalue::OK) {
cancelDumpCd.resetTimer();
tmSinkBusyCd.resetTimer();
dumpContext.reset();
}
+ }
+ if (execCmd != CommandMessageIF::CMD_NONE) {
tcRequestReceived = true;
}
}
@@ -119,21 +125,13 @@ ReturnValue_t TmStoreTaskBase::performDump(PersistentTmStoreWithTmQueue& store,
DumpContext& dumpContext, bool& dumpPerformed) {
size_t dumpedLen = 0;
- auto dumpDoneHandler = [&]() {
- uint32_t startTime;
- uint32_t endTime;
- store.getStartAndEndTimeCurrentOrLastDump(startTime, endTime);
- triggerEvent(dumpContext.eventIfDone, dumpContext.numberOfDumpedPackets,
- dumpContext.dumpedBytes);
- dumpContext.reset();
- };
// Dump the next packet into the PTME.
dumpContext.ptmeBusyCounter = 0;
tmSinkBusyCd.resetTimer();
ReturnValue_t result = store.getNextDumpPacket(tmReader, fileHasSwapped);
if (fileHasSwapped and result == PersistentTmStore::DUMP_DONE) {
// This can happen if a file is corrupted and the next file swap completes the dump.
- dumpDoneHandler();
+ dumpDoneHandler(store, dumpContext);
return returnvalue::OK;
} else if (result != returnvalue::OK) {
sif::error << "PersistentTmStore: Getting next dump packet failed" << std::endl;
@@ -157,7 +155,7 @@ ReturnValue_t TmStoreTaskBase::performDump(PersistentTmStoreWithTmQueue& store,
}
}
if (result == PersistentTmStore::DUMP_DONE) {
- dumpDoneHandler();
+ dumpDoneHandler(store, dumpContext);
}
return returnvalue::OK;
}
@@ -198,6 +196,14 @@ ReturnValue_t TmStoreTaskBase::connectModeTreeParent(HasModeTreeChildrenIF& pare
return modetree::connectModeTreeParent(parent, *this, nullptr, modeHelper);
}
+void TmStoreTaskBase::dumpDoneHandler(PersistentTmStore& store, DumpContext& dumpContext) {
+ uint32_t startTime;
+ uint32_t endTime;
+ store.getStartAndEndTimeCurrentOrLastDump(startTime, endTime);
+ triggerEvent(dumpContext.eventIfDone, dumpContext.numberOfDumpedPackets, dumpContext.dumpedBytes);
+ dumpContext.reset();
+}
+
ModeTreeChildIF& TmStoreTaskBase::getModeTreeChildIF() { return *this; }
void TmStoreTaskBase::readCommandQueue(void) {
diff --git a/mission/com/TmStoreTaskBase.h b/mission/com/TmStoreTaskBase.h
index ef61bd19..2bcd3b1e 100644
--- a/mission/com/TmStoreTaskBase.h
+++ b/mission/com/TmStoreTaskBase.h
@@ -96,6 +96,8 @@ class TmStoreTaskBase : public SystemObject,
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t* msToReachTheMode) override;
+ void dumpDoneHandler(PersistentTmStore& store, DumpContext& dumpContext);
+
void announceMode(bool recursive) override;
object_id_t getObjectId() const override;
const HasHealthIF* getOptHealthIF() const override;
diff --git a/mission/controller/AcsController.cpp b/mission/controller/AcsController.cpp
index 04009cb2..08e8760d 100644
--- a/mission/controller/AcsController.cpp
+++ b/mission/controller/AcsController.cpp
@@ -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::norm(mekfData.satRotRateMekf.value, 3) >
- acsParameters.detumbleParameter.omegaDetumbleStart) {
- detumbleCounter++;
- } else if (gyrDataProcessed.gyrVecTot.isValid() &&
- VectorOperations::norm(gyrDataProcessed.gyrVecTot.value, 3) >
+ if (acsParameters.safeModeControllerParameters.useMekf) {
+ if (mekfData.satRotRateMekf.isValid() and
+ VectorOperations::norm(mekfData.satRotRateMekf.value, 3) >
+ acsParameters.detumbleParameter.omegaDetumbleStart) {
+ detumbleCounter++;
+ }
+ } else if (acsParameters.safeModeControllerParameters.useGyr) {
+ if (gyrDataProcessed.gyrVecTot.isValid() and
+ VectorOperations::norm(gyrDataProcessed.gyrVecTot.value, 3) >
+ acsParameters.detumbleParameter.omegaDetumbleStart) {
+ detumbleCounter++;
+ }
+ } else if (fusedRotRateData.rotRateTotal.isValid() and
+ VectorOperations::norm(fusedRotRateData.rotRateTotal.value, 3) >
acsParameters.detumbleParameter.omegaDetumbleStart) {
detumbleCounter++;
} else if (detumbleCounter > 0) {
@@ -244,6 +273,8 @@ void AcsController::performDetumble() {
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 &&
@@ -289,17 +320,26 @@ void AcsController::performDetumble() {
actuatorCmd.cmdDipoleMtq(*acsParameters.magnetorquerParameter.inverseAlignment,
acsParameters.magnetorquerParameter.dipoleMax, magMomMtq, cmdDipoleMtqs);
- if (mekfData.satRotRateMekf.isValid() &&
- VectorOperations::norm(mekfData.satRotRateMekf.value, 3) <
- acsParameters.detumbleParameter.omegaDetumbleEnd) {
- detumbleCounter++;
- } else if (gyrDataProcessed.gyrVecTot.isValid() &&
- VectorOperations::norm(gyrDataProcessed.gyrVecTot.value, 3) <
+ if (acsParameters.safeModeControllerParameters.useMekf) {
+ if (mekfData.satRotRateMekf.isValid() and
+ VectorOperations::norm(mekfData.satRotRateMekf.value, 3) <
+ acsParameters.detumbleParameter.omegaDetumbleEnd) {
+ detumbleCounter++;
+ }
+ } else if (acsParameters.safeModeControllerParameters.useGyr) {
+ if (gyrDataProcessed.gyrVecTot.isValid() and
+ VectorOperations::norm(gyrDataProcessed.gyrVecTot.value, 3) <
+ acsParameters.detumbleParameter.omegaDetumbleEnd) {
+ detumbleCounter++;
+ }
+ } else if (fusedRotRateData.rotRateTotal.isValid() and
+ VectorOperations::norm(fusedRotRateData.rotRateTotal.value, 3) <
acsParameters.detumbleParameter.omegaDetumbleEnd) {
detumbleCounter++;
} else if (detumbleCounter > 0) {
detumbleCounter -= 1;
}
+
if (detumbleCounter > acsParameters.detumbleParameter.detumblecounter) {
detumbleCounter = 0;
// Triggers safe mode transition in subsystem
@@ -307,7 +347,7 @@ void AcsController::performDetumble() {
startTransition(mode, acs::SafeSubmode::DEFAULT);
}
- disableCtrlValData();
+ updateCtrlValData(safeCtrlStrat);
updateActuatorCmdData(cmdDipoleMtqs);
commandActuators(cmdDipoleMtqs[0], cmdDipoleMtqs[1], cmdDipoleMtqs[2],
acsParameters.magnetorquerParameter.torqueDuration);
@@ -578,6 +618,23 @@ void AcsController::updateActuatorCmdData(const double *rwTargetTorque,
}
}
+void AcsController::updateCtrlValData(uint8_t safeModeStrat) {
+ PoolReadGuard pg(&ctrlValData);
+ if (pg.getReadResult() == returnvalue::OK) {
+ std::memcpy(ctrlValData.tgtQuat.value, ZERO_VEC4, 4 * sizeof(double));
+ ctrlValData.tgtQuat.setValid(false);
+ std::memcpy(ctrlValData.errQuat.value, ZERO_VEC4, 4 * sizeof(double));
+ ctrlValData.errQuat.setValid(false);
+ ctrlValData.errAng.value = 0;
+ ctrlValData.errAng.setValid(false);
+ std::memcpy(ctrlValData.tgtRotRate.value, ZERO_VEC3, 3 * sizeof(double));
+ ctrlValData.tgtRotRate.setValid(false);
+ ctrlValData.safeStrat.value = safeModeStrat;
+ ctrlValData.safeStrat.setValid(true);
+ ctrlValData.setValidity(true, false);
+ }
+}
+
void AcsController::updateCtrlValData(double errAng, uint8_t safeModeStrat) {
PoolReadGuard pg(&ctrlValData);
if (pg.getReadResult() == returnvalue::OK) {
@@ -608,17 +665,6 @@ void AcsController::updateCtrlValData(const double *tgtQuat, const double *errQu
}
}
-void AcsController::disableCtrlValData() {
- PoolReadGuard pg(&ctrlValData);
- if (pg.getReadResult() == returnvalue::OK) {
- std::memcpy(ctrlValData.tgtQuat.value, ZERO_VEC4, 4 * sizeof(double));
- std::memcpy(ctrlValData.errQuat.value, ZERO_VEC4, 4 * sizeof(double));
- ctrlValData.errAng.value = 0;
- std::memcpy(ctrlValData.tgtRotRate.value, ZERO_VEC3, 3 * sizeof(double));
- ctrlValData.setValidity(false, true);
- }
-}
-
ReturnValue_t AcsController::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) {
// MGM Raw
@@ -707,6 +753,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 +783,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;
}
diff --git a/mission/controller/AcsController.h b/mission/controller/AcsController.h
index 0c8b94bb..a7dfbf6a 100644
--- a/mission/controller/AcsController.h
+++ b/mission/controller/AcsController.h
@@ -13,6 +13,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -49,6 +50,7 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
AcsParameters acsParameters;
SensorProcessing sensorProcessing;
+ FusedRotationEstimation fusedRotationEstimation;
Navigation navigation;
ActuatorCmd actuatorCmd;
Guidance guidance;
@@ -115,10 +117,10 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
void updateActuatorCmdData(const int16_t* mtqTargetDipole);
void updateActuatorCmdData(const double* rwTargetTorque, const int32_t* rwTargetSpeed,
const int16_t* mtqTargetDipole);
+ void updateCtrlValData(uint8_t safeModeStrat);
void updateCtrlValData(double errAng, uint8_t safeModeStrat);
void updateCtrlValData(const double* tgtQuat, const double* errQuat, double errAng,
const double* tgtRotRate);
- void disableCtrlValData();
/* ACS Sensor Values */
ACS::SensorValues sensorValues;
@@ -226,6 +228,12 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes
PoolEntry rwTargetSpeed = PoolEntry(4);
PoolEntry mtqTargetDipole = PoolEntry(3);
+ // Fused Rot Rate
+ acsctrl::FusedRotRateData fusedRotRateData;
+ PoolEntry rotRateOrthogonal = PoolEntry(3);
+ PoolEntry rotRateParallel = PoolEntry(3);
+ PoolEntry rotRateTotal = PoolEntry(3);
+
// Initial delay to make sure all pool variables have been initialized their owners
Countdown initialCountdown = Countdown(INIT_DELAY);
};
diff --git a/mission/controller/ThermalController.cpp b/mission/controller/ThermalController.cpp
index 53babbd5..5f2277a9 100644
--- a/mission/controller/ThermalController.cpp
+++ b/mission/controller/ThermalController.cpp
@@ -1,6 +1,6 @@
#include "ThermalController.h"
-#include
+#include
#include
#include
#include
@@ -24,13 +24,16 @@
#define LOWER_RW_UPPER_LIMITS 0
ThermalController::ThermalController(object_id_t objectId, HeaterHandler& heater,
- const std::atomic_bool& tcsBoardShortUnavailable)
+ const std::atomic_bool& tcsBoardShortUnavailable,
+ bool pollPcdu1Tmp)
: ExtendedControllerBase(objectId),
heaterHandler(heater),
+ pollPcdu1Tmp(pollPcdu1Tmp),
sensorTemperatures(this),
susTemperatures(this),
deviceTemperatures(this),
heaterInfo(this),
+ tcsCtrlInfo(this),
imtqThermalSet(objects::IMTQ_HANDLER, ThermalStateCfg()),
maxSet0PlocHspd(objects::RTD_0_IC3_PLOC_HEATSPREADER,
EiveMax31855::RtdCommands::EXCHANGE_SET_ID),
@@ -55,8 +58,6 @@ ThermalController::ThermalController(object_id_t objectId, HeaterHandler& heater
tmp1075SetTcs0(objects::TMP1075_HANDLER_TCS_0),
tmp1075SetTcs1(objects::TMP1075_HANDLER_TCS_1),
tmp1075SetPlPcdu0(objects::TMP1075_HANDLER_PLPCDU_0),
- // damaged
- // tmp1075SetPlPcdu1(objects::TMP1075_HANDLER_PLPCDU_1),
tmp1075SetIfBoard(objects::TMP1075_HANDLER_IF_BOARD),
susSet0(objects::SUS_0_N_LOC_XFYFZM_PT_XF),
susSet1(objects::SUS_1_N_LOC_XBYFZM_PT_XB),
@@ -71,6 +72,9 @@ ThermalController::ThermalController(object_id_t objectId, HeaterHandler& heater
susSet10(objects::SUS_10_N_LOC_XMYBZF_PT_ZF),
susSet11(objects::SUS_11_R_LOC_XBYMZB_PT_ZB),
tcsBrdShortlyUnavailable(tcsBoardShortUnavailable) {
+ if (pollPcdu1Tmp) {
+ tmp1075SetPlPcdu1 = new TMP1075::Tmp1075Dataset(objects::TMP1075_HANDLER_PLPCDU_1);
+ }
resetSensorsArray();
}
@@ -171,7 +175,7 @@ void ThermalController::performControlOperation() {
}
}
- HeaterSwitchStates heaterSwitchStateArray{};
+ tcsCtrl::HeaterSwitchStates heaterSwitchStateArray{};
heaterHandler.getAllSwitchStates(heaterSwitchStateArray);
{
PoolReadGuard pg(&heaterInfo);
@@ -188,12 +192,11 @@ void ThermalController::performControlOperation() {
if (transitionWhenHeatersOff) {
bool allSwitchersOff = true;
for (size_t idx = 0; idx < heaterSwitchStateArray.size(); idx++) {
- if (heaterSwitchStateArray[idx] != HeaterHandler::SwitchState::OFF) {
+ if (heaterSwitchStateArray[idx] != heater::SwitchState::OFF) {
allSwitchersOff = false;
// if heater still ON after 3 cycles, switch OFF again
if (transitionWhenHeatersOffCycles == 3) {
- heaterHandler.switchHeater(static_cast(idx),
- HeaterHandler::SwitchState::OFF);
+ heaterHandler.switchHeater(static_cast(idx), heater::SwitchState::OFF);
triggerEvent(tcsCtrl::HEATER_NOT_OFF_FOR_OFF_MODE);
}
}
@@ -206,8 +209,21 @@ void ThermalController::performControlOperation() {
} else {
transitionWhenHeatersOffCycles++;
}
- } else if (mode != MODE_OFF and not tcsBrdShortlyUnavailable) {
- performThermalModuleCtrl(heaterSwitchStateArray);
+ } else if (mode != MODE_OFF) {
+ if (not tcsBrdShortlyUnavailable) {
+ performThermalModuleCtrl(heaterSwitchStateArray);
+ }
+ heaterTransitionControl(heaterSwitchStateArray);
+ heaterMaxDurationControl(heaterSwitchStateArray);
+ // This dataset makes the TCS CTRL observable.
+ PoolReadGuard pg(&tcsCtrlInfo);
+ for (uint8_t i = 0; i < thermalStates.size(); i++) {
+ tcsCtrlInfo.heatingOnVec[i] = thermalStates[i].heating;
+ tcsCtrlInfo.sensorIdxUsedForTcsCtrl[i] = thermalStates[i].sensorIndex;
+ tcsCtrlInfo.heaterSwitchIdx[i] = thermalStates[i].heaterSwitch;
+ tcsCtrlInfo.heaterStartTimes[i] = thermalStates[i].heaterStartTime;
+ tcsCtrlInfo.heaterEndTimes[i] = thermalStates[i].heaterEndTime;
+ }
}
}
@@ -277,6 +293,11 @@ ReturnValue_t ThermalController::initializeLocalDataPool(localpool::DataPool& lo
localDataPoolMap.emplace(tcsCtrl::TEMP_ADC_PAYLOAD_PCDU, new PoolEntry({0.0}));
localDataPoolMap.emplace(tcsCtrl::HEATER_SWITCH_LIST, &heaterSwitchStates);
localDataPoolMap.emplace(tcsCtrl::HEATER_CURRENT, &heaterCurrent);
+ localDataPoolMap.emplace(tcsCtrl::HEATER_ON_FOR_COMPONENT_VEC, &tcsCtrlHeaterOn);
+ localDataPoolMap.emplace(tcsCtrl::SENSOR_USED_FOR_TCS_CTRL, &tcsCtrlSensorIdx);
+ localDataPoolMap.emplace(tcsCtrl::HEATER_IDX_USED_FOR_TCS_CTRL, &tcsCtrlHeaterIdx);
+ localDataPoolMap.emplace(tcsCtrl::HEATER_START_TIME, &tcsCtrlStartTimes);
+ localDataPoolMap.emplace(tcsCtrl::HEATER_END_TIME, &tcsCtrlEndTimes);
bool enableHkSets = false;
#if OBSW_ENABLE_PERIODIC_HK == 1
@@ -290,6 +311,8 @@ ReturnValue_t ThermalController::initializeLocalDataPool(localpool::DataPool& lo
subdp::RegularHkPeriodicParams(deviceTemperatures.getSid(), enableHkSets, 120.0));
poolManager.subscribeForDiagPeriodicPacket(
subdp::DiagnosticsHkPeriodicParams(heaterInfo.getSid(), enableHkSets, 120.0));
+ poolManager.subscribeForRegularPeriodicPacket(
+ subdp::RegularHkPeriodicParams(tcsCtrlInfo.getSid(), enableHkSets, 120.0));
return returnvalue::OK;
}
@@ -304,6 +327,8 @@ LocalPoolDataSetBase* ThermalController::getDataSetHandle(sid_t sid) {
return &deviceTemperatures;
case tcsCtrl::HEATER_SET:
return &heaterInfo;
+ case tcsCtrl::TCS_CTRL_INFO:
+ return &tcsCtrlInfo;
default:
return nullptr;
}
@@ -536,19 +561,19 @@ void ThermalController::copySensors() {
}
}
}
- // damaged
- /*
- {
- PoolReadGuard pg(&tmp1075SetPlPcdu1, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
- if (pg.getReadResult() == returnvalue::OK) {
- sensorTemperatures.tmp1075PlPcdu1.value = tmp1075SetPlPcdu1.temperatureCelcius.value;
- sensorTemperatures.tmp1075PlPcdu1.setValid(tmp1075SetPlPcdu1.temperatureCelcius.isValid());
- if (not tmp1075SetPlPcdu1.temperatureCelcius.isValid()) {
- sensorTemperatures.tmp1075PlPcdu1.value = INVALID_TEMPERATURE;
+ // damaged on FM, and no dummies for now
+ if (pollPcdu1Tmp) {
+ {
+ PoolReadGuard pg(tmp1075SetPlPcdu1, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
+ if (pg.getReadResult() == returnvalue::OK) {
+ sensorTemperatures.tmp1075PlPcdu1.value = tmp1075SetPlPcdu1->temperatureCelcius.value;
+ sensorTemperatures.tmp1075PlPcdu1.setValid(tmp1075SetPlPcdu1->temperatureCelcius.isValid());
+ if (not tmp1075SetPlPcdu1->temperatureCelcius.isValid()) {
+ sensorTemperatures.tmp1075PlPcdu1.value = INVALID_TEMPERATURE;
+ }
}
}
}
- */
{
PoolReadGuard pg(&tmp1075SetIfBoard, MutexIF::TimeoutType::WAITING, MUTEX_TIMEOUT);
if (pg.getReadResult() == returnvalue::OK) {
@@ -1005,7 +1030,7 @@ void ThermalController::ctrlAcsBoard() {
heater::Switch redSwitchNr = heater::HEATER_3_OBC_BRD;
// A side
- thermalComponent = ACS_BOARD;
+ ctrlCtx.thermalComponent = tcsCtrl::ACS_BOARD;
sensors[0].first = deviceTemperatures.gyro0SideA.isValid();
sensors[0].second = deviceTemperatures.gyro0SideA.value;
sensors[1].first = deviceTemperatures.gyro2SideB.isValid();
@@ -1049,7 +1074,7 @@ void ThermalController::ctrlAcsBoard() {
if (chooseHeater(switchNr, redSwitchNr)) {
if (heaterHandler.getSwitchState(switchNr)) {
if (submode != SUBMODE_NO_HEATER_CTRL) {
- heaterSwitchHelper(switchNr, HeaterHandler::SwitchState::OFF, thermalComponent);
+ heaterSwitchHelper(switchNr, heater::SwitchState::OFF, ctrlCtx.thermalComponent);
}
}
}
@@ -1059,7 +1084,7 @@ void ThermalController::ctrlAcsBoard() {
}
void ThermalController::ctrlMgt() {
- thermalComponent = MGT;
+ ctrlCtx.thermalComponent = tcsCtrl::MGT;
sensors[0].first = sensorTemperatures.mgt.isValid();
sensors[0].second = sensorTemperatures.mgt.value;
sensors[1].first = deviceTemperatures.mgt.isValid();
@@ -1069,11 +1094,11 @@ void ThermalController::ctrlMgt() {
numSensors = 3;
HeaterContext htrCtx(heater::HEATER_2_ACS_BRD, heater::HEATER_1_PCDU_PDU, mgtLimits);
ctrlComponentTemperature(htrCtx);
- if (componentAboveUpperLimit and not mgtTooHotFlag) {
+ if (ctrlCtx.componentAboveUpperLimit and not tooHotFlags.mgtTooHotFlag) {
triggerEvent(tcsCtrl::MGT_OVERHEATING, tempFloatToU32());
- mgtTooHotFlag = true;
- } else if (not componentAboveUpperLimit) {
- mgtTooHotFlag = false;
+ tooHotFlags.mgtTooHotFlag = true;
+ } else if (not ctrlCtx.componentAboveUpperLimit) {
+ tooHotFlags.mgtTooHotFlag = false;
}
}
@@ -1084,7 +1109,7 @@ void ThermalController::ctrlRw() {
std::array sensorTemps{};
// RW1
- thermalComponent = RW;
+ ctrlCtx.thermalComponent = tcsCtrl::RW;
sensors[0].first = sensorTemperatures.rw1.isValid();
sensors[0].second = sensorTemperatures.rw1.value;
sensors[1].first = deviceTemperatures.rw1.isValid();
@@ -1098,14 +1123,14 @@ void ThermalController::ctrlRw() {
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_6_DRO, rwLimits);
ctrlComponentTemperature(htrCtx);
sensorTemps[0] = tempFloatToU32();
- if (componentAboveUpperLimit) {
+ if (ctrlCtx.componentAboveUpperLimit) {
oneIsAboveLimit = true;
- eventToTrigger = overHeatEventToTrigger;
+ eventToTrigger = ctrlCtx.overHeatEventToTrigger;
}
}
// RW2
- thermalComponent = RW;
+ ctrlCtx.thermalComponent = tcsCtrl::RW;
sensors[0].first = deviceTemperatures.rw2.isValid();
sensors[0].second = deviceTemperatures.rw2.value;
sensors[1].first = deviceTemperatures.rw3.isValid();
@@ -1119,15 +1144,15 @@ void ThermalController::ctrlRw() {
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_6_DRO, rwLimits);
ctrlComponentTemperature(htrCtx);
sensorTemps[1] = tempFloatToU32();
- if (componentAboveUpperLimit) {
+ if (ctrlCtx.componentAboveUpperLimit) {
oneIsAboveLimit = true;
if (eventToTrigger != ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH) {
- eventToTrigger = overHeatEventToTrigger;
+ eventToTrigger = ctrlCtx.overHeatEventToTrigger;
}
}
}
// RW3
- thermalComponent = RW;
+ ctrlCtx.thermalComponent = tcsCtrl::RW;
sensors[0].first = deviceTemperatures.rw3.isValid();
sensors[0].second = deviceTemperatures.rw3.value;
sensors[1].first = deviceTemperatures.rw4.isValid();
@@ -1141,16 +1166,16 @@ void ThermalController::ctrlRw() {
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_6_DRO, rwLimits);
ctrlComponentTemperature(htrCtx);
sensorTemps[2] = tempFloatToU32();
- if (componentAboveUpperLimit) {
+ if (ctrlCtx.componentAboveUpperLimit) {
oneIsAboveLimit = true;
if (eventToTrigger != ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH) {
- eventToTrigger = overHeatEventToTrigger;
+ eventToTrigger = ctrlCtx.overHeatEventToTrigger;
}
}
}
// RW4
- thermalComponent = RW;
+ ctrlCtx.thermalComponent = tcsCtrl::RW;
sensors[0].first = deviceTemperatures.rw4.isValid();
sensors[0].second = deviceTemperatures.rw4.value;
sensors[1].first = deviceTemperatures.rw1.isValid();
@@ -1164,27 +1189,27 @@ void ThermalController::ctrlRw() {
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_6_DRO, rwLimits);
ctrlComponentTemperature(htrCtx);
sensorTemps[3] = tempFloatToU32();
- if (componentAboveUpperLimit) {
+ if (ctrlCtx.componentAboveUpperLimit) {
oneIsAboveLimit = true;
if (eventToTrigger != ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH) {
- eventToTrigger = overHeatEventToTrigger;
+ eventToTrigger = ctrlCtx.overHeatEventToTrigger;
}
}
}
- if (oneIsAboveLimit and not rwTooHotFlag) {
+ if (oneIsAboveLimit and not tooHotFlags.rwTooHotFlag) {
EventManagerIF::triggerEvent(objects::RW1, eventToTrigger, sensorTemps[0]);
EventManagerIF::triggerEvent(objects::RW2, eventToTrigger, sensorTemps[1]);
EventManagerIF::triggerEvent(objects::RW3, eventToTrigger, sensorTemps[2]);
EventManagerIF::triggerEvent(objects::RW4, eventToTrigger, sensorTemps[3]);
- rwTooHotFlag = true;
+ tooHotFlags.rwTooHotFlag = true;
} else if (not oneIsAboveLimit) {
- rwTooHotFlag = false;
+ tooHotFlags.rwTooHotFlag = false;
}
}
void ThermalController::ctrlStr() {
- thermalComponent = STR;
+ ctrlCtx.thermalComponent = tcsCtrl::STR;
sensors[0].first = sensorTemperatures.startracker.isValid();
sensors[0].second = sensorTemperatures.startracker.value;
sensors[1].first = deviceTemperatures.startracker.isValid();
@@ -1194,11 +1219,11 @@ void ThermalController::ctrlStr() {
numSensors = 3;
HeaterContext htrCtx(heater::HEATER_5_STR, heater::HEATER_6_DRO, strLimits);
ctrlComponentTemperature(htrCtx);
- tooHotHandlerWhichClearsOneShotFlag(objects::STAR_TRACKER, strTooHotFlag);
+ tooHotHandlerWhichClearsOneShotFlag(objects::STAR_TRACKER, tooHotFlags.strTooHotFlag);
}
void ThermalController::ctrlIfBoard() {
- thermalComponent = IF_BOARD;
+ ctrlCtx.thermalComponent = tcsCtrl::IF_BOARD;
sensors[0].first = sensorTemperatures.tmp1075IfBrd.isValid();
sensors[0].second = sensorTemperatures.tmp1075IfBrd.value;
sensors[1].first = sensorTemperatures.mgt.isValid();
@@ -1212,7 +1237,7 @@ void ThermalController::ctrlIfBoard() {
}
void ThermalController::ctrlTcsBoard() {
- thermalComponent = TCS_BOARD;
+ ctrlCtx.thermalComponent = tcsCtrl::TCS_BOARD;
sensors[0].first = sensorTemperatures.tcsBoard.isValid();
sensors[0].second = sensorTemperatures.tcsBoard.value;
sensors[1].first = sensorTemperatures.tmp1075Tcs0.isValid();
@@ -1226,7 +1251,7 @@ void ThermalController::ctrlTcsBoard() {
}
void ThermalController::ctrlObc() {
- thermalComponent = OBC;
+ ctrlCtx.thermalComponent = tcsCtrl::OBC;
sensors[0].first = deviceTemperatures.q7s.isValid();
sensors[0].second = deviceTemperatures.q7s.value;
sensors[1].first = sensorTemperatures.tmp1075Tcs1.isValid();
@@ -1236,35 +1261,16 @@ void ThermalController::ctrlObc() {
numSensors = 3;
HeaterContext htrCtx(heater::HEATER_3_OBC_BRD, heater::HEATER_2_ACS_BRD, obcLimits);
ctrlComponentTemperature(htrCtx);
- if (componentAboveUpperLimit and not obcTooHotFlag) {
+ if (ctrlCtx.componentAboveUpperLimit and not tooHotFlags.obcTooHotFlag) {
triggerEvent(tcsCtrl::OBC_OVERHEATING, tempFloatToU32());
- obcTooHotFlag = true;
- } else if (not componentAboveUpperLimit) {
- obcTooHotFlag = false;
- }
-}
-
-void ThermalController::ctrlObcIfBoard() {
- thermalComponent = OBCIF_BOARD;
- sensors[0].first = deviceTemperatures.q7s.isValid();
- sensors[0].second = deviceTemperatures.q7s.value;
- sensors[1].first = sensorTemperatures.tmp1075Tcs0.isValid();
- sensors[1].second = sensorTemperatures.tmp1075Tcs0.value;
- sensors[2].first = sensorTemperatures.tmp1075Tcs1.isValid();
- sensors[2].second = sensorTemperatures.tmp1075Tcs1.value;
- numSensors = 3;
- HeaterContext htrCtx(heater::HEATER_3_OBC_BRD, heater::HEATER_2_ACS_BRD, obcIfBoardLimits);
- ctrlComponentTemperature(htrCtx);
- if (componentAboveUpperLimit and not obcTooHotFlag) {
- triggerEvent(tcsCtrl::OBC_OVERHEATING, tempFloatToU32());
- obcTooHotFlag = true;
- } else if (not componentAboveUpperLimit) {
- obcTooHotFlag = false;
+ tooHotFlags.obcTooHotFlag = true;
+ } else if (not ctrlCtx.componentAboveUpperLimit) {
+ tooHotFlags.obcTooHotFlag = false;
}
}
void ThermalController::ctrlSBandTransceiver() {
- thermalComponent = SBAND_TRANSCEIVER;
+ ctrlCtx.thermalComponent = tcsCtrl::SBAND_TRANSCEIVER;
sensors[0].first = deviceTemperatures.syrlinksPowerAmplifier.isValid();
sensors[0].second = deviceTemperatures.syrlinksPowerAmplifier.value;
sensors[1].first = deviceTemperatures.syrlinksBasebandBoard.isValid();
@@ -1274,15 +1280,15 @@ void ThermalController::ctrlSBandTransceiver() {
numSensors = 3;
HeaterContext htrCtx(heater::HEATER_7_S_BAND, heater::HEATER_4_CAMERA, sBandTransceiverLimits);
ctrlComponentTemperature(htrCtx);
- if (componentAboveUpperLimit and not syrlinksTooHotFlag) {
+ if (ctrlCtx.componentAboveUpperLimit and not tooHotFlags.syrlinksTooHotFlag) {
triggerEvent(tcsCtrl::SYRLINKS_OVERHEATING, tempFloatToU32());
- syrlinksTooHotFlag = true;
- } else if (not componentAboveUpperLimit) {
- syrlinksTooHotFlag = false;
+ tooHotFlags.syrlinksTooHotFlag = true;
+ } else if (not ctrlCtx.componentAboveUpperLimit) {
+ tooHotFlags.syrlinksTooHotFlag = false;
}
}
void ThermalController::ctrlPcduP60Board() {
- thermalComponent = PCDUP60_BOARD;
+ ctrlCtx.thermalComponent = tcsCtrl::PCDUP60_BOARD;
sensors[0].first = deviceTemperatures.temp1P60dock.isValid();
sensors[0].second = deviceTemperatures.temp1P60dock.value;
sensors[1].first = deviceTemperatures.temp2P60dock.isValid();
@@ -1290,16 +1296,16 @@ void ThermalController::ctrlPcduP60Board() {
numSensors = 2;
HeaterContext htrCtx(heater::HEATER_1_PCDU_PDU, heater::HEATER_2_ACS_BRD, pcduP60BoardLimits);
ctrlComponentTemperature(htrCtx);
- if (componentAboveUpperLimit and not pcduSystemTooHotFlag) {
+ if (ctrlCtx.componentAboveUpperLimit and not tooHotFlags.pcduSystemTooHotFlag) {
triggerEvent(tcsCtrl::PCDU_SYSTEM_OVERHEATING, tempFloatToU32());
- pcduSystemTooHotFlag = true;
- } else if (not componentAboveUpperLimit) {
- pcduSystemTooHotFlag = false;
+ tooHotFlags.pcduSystemTooHotFlag = true;
+ } else if (not ctrlCtx.componentAboveUpperLimit) {
+ tooHotFlags.pcduSystemTooHotFlag = false;
} // TODO: !
}
void ThermalController::ctrlPcduAcu() {
- thermalComponent = PCDUACU;
+ ctrlCtx.thermalComponent = tcsCtrl::PCDUACU;
heater::Switch switchNr = heater::HEATER_1_PCDU_PDU;
heater::Switch redSwitchNr = heater::HEATER_2_ACS_BRD;
@@ -1307,15 +1313,15 @@ void ThermalController::ctrlPcduAcu() {
bool sensorTempAvailable = true;
// TODO: check
if (deviceTemperatures.acu.value[0] != INVALID_TEMPERATURE) {
- sensorTemp = deviceTemperatures.acu.value[0];
+ ctrlCtx.sensorTemp = deviceTemperatures.acu.value[0];
} else if (deviceTemperatures.acu.value[1] != INVALID_TEMPERATURE) {
- sensorTemp = deviceTemperatures.acu.value[1];
+ ctrlCtx.sensorTemp = deviceTemperatures.acu.value[1];
} else if (deviceTemperatures.acu.value[2] != INVALID_TEMPERATURE) {
- sensorTemp = deviceTemperatures.acu.value[2];
+ ctrlCtx.sensorTemp = deviceTemperatures.acu.value[2];
} else if (sensorTemperatures.acu.isValid()) {
- sensorTemp = sensorTemperatures.acu.value;
+ ctrlCtx.sensorTemp = sensorTemperatures.acu.value;
} else {
- triggerEvent(tcsCtrl::NO_VALID_SENSOR_TEMPERATURE, thermalComponent);
+ triggerEvent(tcsCtrl::NO_VALID_SENSOR_TEMPERATURE, ctrlCtx.thermalComponent);
sensorTempAvailable = false;
}
if (sensorTempAvailable) {
@@ -1323,16 +1329,16 @@ void ThermalController::ctrlPcduAcu() {
checkLimitsAndCtrlHeater(htrCtx);
}
}
- if (componentAboveUpperLimit and not pcduSystemTooHotFlag) {
+ if (ctrlCtx.componentAboveUpperLimit and not tooHotFlags.pcduSystemTooHotFlag) {
triggerEvent(tcsCtrl::PCDU_SYSTEM_OVERHEATING, tempFloatToU32());
- pcduSystemTooHotFlag = true;
- } else if (not componentAboveUpperLimit) {
- pcduSystemTooHotFlag = false;
+ tooHotFlags.pcduSystemTooHotFlag = true;
+ } else if (not ctrlCtx.componentAboveUpperLimit) {
+ tooHotFlags.pcduSystemTooHotFlag = false;
}
}
void ThermalController::ctrlPcduPdu() {
- thermalComponent = PCDUPDU;
+ ctrlCtx.thermalComponent = tcsCtrl::PCDUPDU;
sensors[0].first = deviceTemperatures.pdu1.isValid();
sensors[0].second = deviceTemperatures.pdu1.value;
sensors[1].first = deviceTemperatures.pdu2.isValid();
@@ -1342,16 +1348,16 @@ void ThermalController::ctrlPcduPdu() {
numSensors = 3;
HeaterContext htrCtx(heater::HEATER_1_PCDU_PDU, heater::HEATER_2_ACS_BRD, pcduPduLimits);
ctrlComponentTemperature(htrCtx);
- if (componentAboveUpperLimit and not pcduSystemTooHotFlag) {
+ if (ctrlCtx.componentAboveUpperLimit and not tooHotFlags.pcduSystemTooHotFlag) {
triggerEvent(tcsCtrl::PCDU_SYSTEM_OVERHEATING, tempFloatToU32());
- pcduSystemTooHotFlag = true;
- } else if (not componentAboveUpperLimit) {
- pcduSystemTooHotFlag = false;
+ tooHotFlags.pcduSystemTooHotFlag = true;
+ } else if (not ctrlCtx.componentAboveUpperLimit) {
+ tooHotFlags.pcduSystemTooHotFlag = false;
}
}
void ThermalController::ctrlPlPcduBoard() {
- thermalComponent = PLPCDU_BOARD;
+ ctrlCtx.thermalComponent = tcsCtrl::PLPCDU_BOARD;
sensors[0].first = sensorTemperatures.tmp1075PlPcdu0.isValid();
sensors[0].second = sensorTemperatures.tmp1075PlPcdu0.value;
sensors[1].first = sensorTemperatures.tmp1075PlPcdu1.isValid();
@@ -1363,11 +1369,11 @@ void ThermalController::ctrlPlPcduBoard() {
numSensors = 4;
HeaterContext htrCtx(heater::HEATER_1_PCDU_PDU, heater::HEATER_2_ACS_BRD, plPcduBoardLimits);
ctrlComponentTemperature(htrCtx);
- tooHotHandler(objects::PLPCDU_HANDLER, eBandTooHotFlag);
+ tooHotHandler(objects::PLPCDU_HANDLER, tooHotFlags.eBandTooHotFlag);
}
void ThermalController::ctrlPlocMissionBoard() {
- thermalComponent = PLOCMISSION_BOARD;
+ ctrlCtx.thermalComponent = tcsCtrl::PLOCMISSION_BOARD;
sensors[0].first = sensorTemperatures.plocHeatspreader.isValid();
sensors[0].second = sensorTemperatures.plocHeatspreader.value;
sensors[1].first = sensorTemperatures.plocMissionboard.isValid();
@@ -1378,11 +1384,11 @@ void ThermalController::ctrlPlocMissionBoard() {
HeaterContext htrCtx(heater::HEATER_0_PLOC_PROC_BRD, heater::HEATER_3_OBC_BRD,
plocMissionBoardLimits);
ctrlComponentTemperature(htrCtx);
- tooHotHandler(objects::PLOC_SUPERVISOR_HANDLER, plocTooHotFlag);
+ tooHotHandler(objects::PLOC_SUPERVISOR_HANDLER, tooHotFlags.plocTooHotFlag);
}
void ThermalController::ctrlPlocProcessingBoard() {
- thermalComponent = PLOCPROCESSING_BOARD;
+ ctrlCtx.thermalComponent = tcsCtrl::PLOCPROCESSING_BOARD;
sensors[0].first = sensorTemperatures.plocMissionboard.isValid();
sensors[0].second = sensorTemperatures.plocMissionboard.value;
sensors[1].first = sensorTemperatures.plocHeatspreader.isValid();
@@ -1393,11 +1399,11 @@ void ThermalController::ctrlPlocProcessingBoard() {
HeaterContext htrCtx(heater::HEATER_0_PLOC_PROC_BRD, heater::HEATER_3_OBC_BRD,
plocProcessingBoardLimits);
ctrlComponentTemperature(htrCtx);
- tooHotHandler(objects::PLOC_SUPERVISOR_HANDLER, plocTooHotFlag);
+ tooHotHandler(objects::PLOC_SUPERVISOR_HANDLER, tooHotFlags.plocTooHotFlag);
}
void ThermalController::ctrlDac() {
- thermalComponent = DAC;
+ ctrlCtx.thermalComponent = tcsCtrl::DAC;
sensors[0].first = sensorTemperatures.dacHeatspreader.isValid();
sensors[0].second = sensorTemperatures.dacHeatspreader.value;
sensors[1].first = sensorTemperatures.plocMissionboard.isValid();
@@ -1407,11 +1413,11 @@ void ThermalController::ctrlDac() {
numSensors = 3;
HeaterContext htrCtx(heater::HEATER_0_PLOC_PROC_BRD, heater::HEATER_3_OBC_BRD, dacLimits);
ctrlComponentTemperature(htrCtx);
- tooHotHandler(objects::PLPCDU_HANDLER, eBandTooHotFlag);
+ tooHotHandler(objects::PLPCDU_HANDLER, tooHotFlags.eBandTooHotFlag);
}
void ThermalController::ctrlCameraBody() {
- thermalComponent = CAMERA;
+ ctrlCtx.thermalComponent = tcsCtrl::CAMERA;
sensors[0].first = sensorTemperatures.payload4kCamera.isValid();
sensors[0].second = sensorTemperatures.payload4kCamera.value;
sensors[1].first = sensorTemperatures.dro.isValid();
@@ -1421,7 +1427,7 @@ void ThermalController::ctrlCameraBody() {
numSensors = 3;
HeaterContext htrCtx(heater::HEATER_4_CAMERA, heater::HEATER_6_DRO, cameraLimits);
ctrlComponentTemperature(htrCtx);
- if (componentAboveUpperLimit and not camTooHotOneShotFlag) {
+ if (ctrlCtx.componentAboveUpperLimit and not tooHotFlags.camTooHotOneShotFlag) {
triggerEvent(tcsCtrl::CAMERA_OVERHEATING, tempFloatToU32());
CommandMessage msg;
HealthMessage::setHealthMessage(&msg, HealthMessage::HEALTH_SET, HealthState::FAULTY);
@@ -1430,14 +1436,14 @@ void ThermalController::ctrlCameraBody() {
sif::error << "ThermalController::ctrlCameraBody(): Sending health message failed"
<< std::endl;
}
- camTooHotOneShotFlag = true;
- } else if (not componentAboveUpperLimit) {
- camTooHotOneShotFlag = false;
+ tooHotFlags.camTooHotOneShotFlag = true;
+ } else if (not ctrlCtx.componentAboveUpperLimit) {
+ tooHotFlags.camTooHotOneShotFlag = false;
}
}
void ThermalController::ctrlDro() {
- thermalComponent = DRO;
+ ctrlCtx.thermalComponent = tcsCtrl::DRO;
sensors[0].first = sensorTemperatures.dro.isValid();
sensors[0].second = sensorTemperatures.dro.value;
sensors[1].first = sensorTemperatures.payload4kCamera.isValid();
@@ -1447,11 +1453,11 @@ void ThermalController::ctrlDro() {
numSensors = 3;
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, droLimits);
ctrlComponentTemperature(htrCtx);
- tooHotHandler(objects::PLPCDU_HANDLER, eBandTooHotFlag);
+ tooHotHandler(objects::PLPCDU_HANDLER, tooHotFlags.eBandTooHotFlag);
}
void ThermalController::ctrlX8() {
- thermalComponent = X8;
+ ctrlCtx.thermalComponent = tcsCtrl::X8;
sensors[0].first = sensorTemperatures.x8.isValid();
sensors[0].second = sensorTemperatures.x8.value;
sensors[1].first = sensorTemperatures.hpa.isValid();
@@ -1461,11 +1467,11 @@ void ThermalController::ctrlX8() {
numSensors = 3;
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, x8Limits);
ctrlComponentTemperature(htrCtx);
- tooHotHandler(objects::PLPCDU_HANDLER, eBandTooHotFlag);
+ tooHotHandler(objects::PLPCDU_HANDLER, tooHotFlags.eBandTooHotFlag);
}
void ThermalController::ctrlTx() {
- thermalComponent = TX;
+ ctrlCtx.thermalComponent = tcsCtrl::TX;
sensors[0].first = sensorTemperatures.eBandTx.isValid();
sensors[0].second = sensorTemperatures.eBandTx.value;
sensors[1].first = sensorTemperatures.x8.isValid();
@@ -1475,11 +1481,11 @@ void ThermalController::ctrlTx() {
numSensors = 3;
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, txLimits);
ctrlComponentTemperature(htrCtx);
- tooHotHandler(objects::PLPCDU_HANDLER, eBandTooHotFlag);
+ tooHotHandler(objects::PLPCDU_HANDLER, tooHotFlags.eBandTooHotFlag);
}
void ThermalController::ctrlMpa() {
- thermalComponent = MPA;
+ ctrlCtx.thermalComponent = tcsCtrl::MPA;
sensors[0].first = sensorTemperatures.mpa.isValid();
sensors[0].second = sensorTemperatures.mpa.value;
sensors[1].first = sensorTemperatures.hpa.isValid();
@@ -1489,11 +1495,11 @@ void ThermalController::ctrlMpa() {
numSensors = 3;
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, mpaLimits);
ctrlComponentTemperature(htrCtx);
- tooHotHandler(objects::PLPCDU_HANDLER, eBandTooHotFlag);
+ tooHotHandler(objects::PLPCDU_HANDLER, tooHotFlags.eBandTooHotFlag);
}
void ThermalController::ctrlHpa() {
- thermalComponent = HPA;
+ ctrlCtx.thermalComponent = tcsCtrl::HPA;
sensors[0].first = sensorTemperatures.hpa.isValid();
sensors[0].second = sensorTemperatures.hpa.value;
sensors[1].first = sensorTemperatures.x8.isValid();
@@ -1503,11 +1509,11 @@ void ThermalController::ctrlHpa() {
numSensors = 3;
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_4_CAMERA, hpaLimits);
ctrlComponentTemperature(htrCtx);
- tooHotHandler(objects::PLPCDU_HANDLER, eBandTooHotFlag);
+ tooHotHandler(objects::PLPCDU_HANDLER, tooHotFlags.eBandTooHotFlag);
}
void ThermalController::ctrlScexBoard() {
- thermalComponent = SCEX_BOARD;
+ ctrlCtx.thermalComponent = tcsCtrl::SCEX_BOARD;
sensors[0].first = sensorTemperatures.scex.isValid();
sensors[0].second = sensorTemperatures.scex.value;
sensors[1].first = sensorTemperatures.x8.isValid();
@@ -1517,10 +1523,11 @@ void ThermalController::ctrlScexBoard() {
numSensors = 3;
HeaterContext htrCtx(heater::HEATER_6_DRO, heater::HEATER_5_STR, scexBoardLimits);
ctrlComponentTemperature(htrCtx);
- tooHotHandlerWhichClearsOneShotFlag(objects::SCEX, scexTooHotFlag);
+ tooHotHandlerWhichClearsOneShotFlag(objects::SCEX, tooHotFlags.scexTooHotFlag);
}
-void ThermalController::performThermalModuleCtrl(const HeaterSwitchStates& heaterSwitchStates) {
+void ThermalController::performThermalModuleCtrl(
+ const tcsCtrl::HeaterSwitchStates& heaterSwitchStates) {
ctrlAcsBoard();
ctrlMgt();
ctrlRw();
@@ -1528,7 +1535,6 @@ void ThermalController::performThermalModuleCtrl(const HeaterSwitchStates& heate
ctrlIfBoard();
ctrlTcsBoard();
ctrlObc();
- ctrlObcIfBoard();
ctrlSBandTransceiver();
ctrlPcduP60Board();
ctrlPcduAcu();
@@ -1537,11 +1543,11 @@ void ThermalController::performThermalModuleCtrl(const HeaterSwitchStates& heate
// Payload components
std::array plocInAllowedRange{};
ctrlPlocMissionBoard();
- plocInAllowedRange.at(0) = not componentAboveUpperLimit;
+ plocInAllowedRange.at(0) = not ctrlCtx.componentAboveUpperLimit;
ctrlPlocProcessingBoard();
- plocInAllowedRange.at(1) = not componentAboveUpperLimit;
+ plocInAllowedRange.at(1) = not ctrlCtx.componentAboveUpperLimit;
- if (plocTooHotFlag) {
+ if (tooHotFlags.plocTooHotFlag) {
bool clearFlag = true;
for (const auto& inRange : plocInAllowedRange) {
if (not inRange) {
@@ -1549,7 +1555,7 @@ void ThermalController::performThermalModuleCtrl(const HeaterSwitchStates& heate
}
}
if (clearFlag) {
- plocTooHotFlag = false;
+ tooHotFlags.plocTooHotFlag = false;
}
}
ctrlCameraBody();
@@ -1558,21 +1564,21 @@ void ThermalController::performThermalModuleCtrl(const HeaterSwitchStates& heate
// E-Band
std::array eBandInAllowedRange{};
ctrlPlPcduBoard();
- eBandInAllowedRange.at(0) = not componentAboveUpperLimit;
+ eBandInAllowedRange.at(0) = not ctrlCtx.componentAboveUpperLimit;
ctrlDac();
- eBandInAllowedRange.at(1) = not componentAboveUpperLimit;
+ eBandInAllowedRange.at(1) = not ctrlCtx.componentAboveUpperLimit;
ctrlDro();
- eBandInAllowedRange.at(2) = not componentAboveUpperLimit;
+ eBandInAllowedRange.at(2) = not ctrlCtx.componentAboveUpperLimit;
ctrlX8();
- eBandInAllowedRange.at(3) = not componentAboveUpperLimit;
+ eBandInAllowedRange.at(3) = not ctrlCtx.componentAboveUpperLimit;
ctrlHpa();
- eBandInAllowedRange.at(4) = not componentAboveUpperLimit;
+ eBandInAllowedRange.at(4) = not ctrlCtx.componentAboveUpperLimit;
ctrlTx();
- eBandInAllowedRange.at(5) = not componentAboveUpperLimit;
+ eBandInAllowedRange.at(5) = not ctrlCtx.componentAboveUpperLimit;
ctrlMpa();
- eBandInAllowedRange.at(6) = not componentAboveUpperLimit;
+ eBandInAllowedRange.at(6) = not ctrlCtx.componentAboveUpperLimit;
- if (eBandTooHotFlag) {
+ if (tooHotFlags.eBandTooHotFlag) {
bool clearFlag = true;
for (const auto& inRange : eBandInAllowedRange) {
if (not inRange) {
@@ -1580,12 +1586,11 @@ void ThermalController::performThermalModuleCtrl(const HeaterSwitchStates& heate
}
}
if (clearFlag) {
- eBandTooHotFlag = false;
+ tooHotFlags.eBandTooHotFlag = false;
}
}
-
- heaterTransitionControl(heaterSwitchStates);
}
+
void ThermalController::ctrlComponentTemperature(HeaterContext& htrCtx) {
if (selectAndReadSensorTemp(htrCtx)) {
if (chooseHeater(htrCtx.switchNr, htrCtx.redSwitchNr)) {
@@ -1596,9 +1601,11 @@ void ThermalController::ctrlComponentTemperature(HeaterContext& htrCtx) {
// No sensors available, so switch the heater off. We can not perform control tasks if we
// are blind..
if (chooseHeater(htrCtx.switchNr, htrCtx.redSwitchNr)) {
+ // Also track the counter to prevent heater handler message spam. The heater handle can only
+ // process 2 messages per cycle.
if (heaterCtrlAllowed() and
- (heaterHandler.getSwitchState(htrCtx.switchNr) == HeaterHandler::SwitchState::ON)) {
- heaterSwitchHelper(htrCtx.switchNr, HeaterHandler::SwitchState::OFF, thermalComponent);
+ (thermalStates[ctrlCtx.thermalComponent].noSensorAvailableCounter < 3)) {
+ heaterSwitchHelper(htrCtx.switchNr, heater::SwitchState::OFF, ctrlCtx.thermalComponent);
}
}
}
@@ -1609,20 +1616,21 @@ bool ThermalController::selectAndReadSensorTemp(HeaterContext& htrCtx) {
if (sensors[i].first and sensors[i].second != INVALID_TEMPERATURE and
sensors[i].second > SANITY_LIMIT_LOWER_TEMP and
sensors[i].second < SANITY_LIMIT_UPPER_TEMP) {
- sensorTemp = sensors[i].second;
- thermalStates[thermalComponent].errorCounter = 0;
+ ctrlCtx.sensorTemp = sensors[i].second;
+ ctrlCtx.currentSensorIndex = i;
+ thermalStates[ctrlCtx.thermalComponent].noSensorAvailableCounter = 0;
return true;
}
}
- thermalStates[thermalComponent].errorCounter++;
- if (thermalComponent != RW and thermalComponent != ACS_BOARD) {
- if (thermalStates[thermalComponent].errorCounter <= 3) {
- triggerEvent(tcsCtrl::NO_VALID_SENSOR_TEMPERATURE, thermalComponent);
+ thermalStates[ctrlCtx.thermalComponent].noSensorAvailableCounter++;
+ if (ctrlCtx.thermalComponent != tcsCtrl::RW and ctrlCtx.thermalComponent != tcsCtrl::ACS_BOARD) {
+ if (thermalStates[ctrlCtx.thermalComponent].noSensorAvailableCounter <= 3) {
+ triggerEvent(tcsCtrl::NO_VALID_SENSOR_TEMPERATURE, ctrlCtx.thermalComponent);
}
} else {
- if (thermalStates[thermalComponent].errorCounter <= 8) {
- triggerEvent(tcsCtrl::NO_VALID_SENSOR_TEMPERATURE, thermalComponent);
+ if (thermalStates[ctrlCtx.thermalComponent].noSensorAvailableCounter <= 8) {
+ triggerEvent(tcsCtrl::NO_VALID_SENSOR_TEMPERATURE, ctrlCtx.thermalComponent);
}
}
@@ -1636,7 +1644,7 @@ bool ThermalController::chooseHeater(heater::Switch& switchNr, heater::Switch re
if (mainHealth != HasHealthIF::HEALTHY) {
if (redHealth == HasHealthIF::HEALTHY) {
switchNr = redSwitchNr;
- redSwitchNrInUse = true;
+ ctrlCtx.redSwitchNrInUse = true;
} else {
heaterAvailable = false;
// Special case: Ground might command/do something with the heaters, so prevent spam.
@@ -1645,7 +1653,7 @@ bool ThermalController::chooseHeater(heater::Switch& switchNr, heater::Switch re
}
}
} else {
- redSwitchNrInUse = false;
+ ctrlCtx.redSwitchNrInUse = false;
}
return heaterAvailable;
}
@@ -1654,23 +1662,23 @@ void ThermalController::heaterCtrlTempTooHighHandler(HeaterContext& htrCtx, cons
if (not heaterCtrlAllowed()) {
return;
}
- if (htrCtx.switchState == HeaterHandler::SwitchState::ON) {
- sif::info << "TCS: Component " << static_cast(thermalComponent) << " too warm, above "
- << whatLimit << ", switching off heater" << std::endl;
- heaterSwitchHelper(htrCtx.switchNr, HeaterHandler::SwitchState::OFF, thermalComponent);
+ if (htrCtx.switchState == heater::SwitchState::ON) {
+ sif::info << "TCS: Component " << static_cast(ctrlCtx.thermalComponent)
+ << " too warm, above " << whatLimit << ", switching off heater" << std::endl;
+ heaterSwitchHelper(htrCtx.switchNr, heater::SwitchState::OFF, ctrlCtx.thermalComponent);
heaterStates[htrCtx.switchNr].switchTransition = true;
- heaterStates[htrCtx.switchNr].target = HeaterHandler::SwitchState::OFF;
+ heaterStates[htrCtx.switchNr].target = heater::SwitchState::OFF;
}
- if (heaterHandler.getSwitchState(htrCtx.redSwitchNr) == HeaterHandler::SwitchState::ON) {
- heaterSwitchHelper(htrCtx.redSwitchNr, HeaterHandler::SwitchState::OFF, thermalComponent);
+ if (heaterHandler.getSwitchState(htrCtx.redSwitchNr) == heater::SwitchState::ON) {
+ heaterSwitchHelper(htrCtx.redSwitchNr, heater::SwitchState::OFF, ctrlCtx.thermalComponent);
heaterStates[htrCtx.redSwitchNr].switchTransition = true;
- heaterStates[htrCtx.redSwitchNr].target = HeaterHandler::SwitchState::OFF;
+ heaterStates[htrCtx.redSwitchNr].target = heater::SwitchState::OFF;
}
}
void ThermalController::checkLimitsAndCtrlHeater(HeaterContext& htrCtx) {
- componentAboveCutOffLimit = false;
- componentAboveUpperLimit = false;
+ ctrlCtx.componentAboveCutOffLimit = false;
+ ctrlCtx.componentAboveUpperLimit = false;
// Stay passive during switch transitions, wait for heater switching to complete. Otherwise,
// still check whether components are out of range, which might be important information for the
// top level control loop.
@@ -1680,39 +1688,41 @@ void ThermalController::checkLimitsAndCtrlHeater(HeaterContext& htrCtx) {
return;
}
- htrCtx.switchState = heaterHandler.getSwitchState(htrCtx.switchNr);
+ htrCtx.switchState =
+ static_cast(heaterInfo.heaterSwitchState[htrCtx.switchNr]);
// Heater off
- if (htrCtx.switchState == HeaterHandler::SwitchState::OFF) {
- if (sensorTemp < htrCtx.tempLimit.opLowerLimit and heaterCtrlAllowed()) {
- sif::info << "TCS: Heater " << static_cast(thermalComponent) << " ON" << std::endl;
- heaterSwitchHelper(htrCtx.switchNr, HeaterHandler::SwitchState::ON, thermalComponent);
- heaterStates[htrCtx.switchNr].switchTransition = true;
- heaterStates[htrCtx.switchNr].target = HeaterHandler::SwitchState::ON;
+ if (htrCtx.switchState == heater::SwitchState::OFF) {
+ if (ctrlCtx.sensorTemp < htrCtx.tempLimit.opLowerLimit and heaterCtrlAllowed()) {
+ sif::info << "TCS: Heater " << static_cast