Merge remote-tracking branch 'origin/main' into swap-pl-ps-i2c
Some checks failed
EIVE/eive-obsw/pipeline/head There was a failure building this commit
Some checks failed
EIVE/eive-obsw/pipeline/head There was a failure building this commit
This commit is contained in:
commit
697a3e8577
139
CHANGELOG.md
139
CHANGELOG.md
@ -16,39 +16,143 @@ will consitute of a breaking change warranting a new major release:
|
|||||||
|
|
||||||
# [unreleased]
|
# [unreleased]
|
||||||
|
|
||||||
## Fixed
|
## Changed
|
||||||
|
|
||||||
- SUS total vector was not reset to being a zero vector during eclipse due to a wrong `memcpy`
|
- Swapped PL and PS I2C, BPX battery and MGT are connected to PS I2C now for firmware versions
|
||||||
length.
|
above v4. However, this software version ins compatible to both v3 and v4 of the firmware.
|
||||||
- TMP device FDIR
|
|
||||||
|
# [v6.0.0] 2023-07-02
|
||||||
|
|
||||||
|
- `q7s-package` version v3.2.0
|
||||||
|
- Important bugfixes for PTME. See `q7s-package` CHANGELOG.
|
||||||
|
|
||||||
## Changed
|
## Changed
|
||||||
|
|
||||||
- Swapped PL and PS I2C, BPX battery and MGT are connected to PS I2C now.
|
- Added back PTME busy bit polling. This is necessary due to changes to the AXI APB interface
|
||||||
|
to the PTME core.
|
||||||
## Added
|
|
||||||
|
## Fixed
|
||||||
- Added TMP devices for EM build.
|
|
||||||
|
- For the live channel (VC0), telemetry was still only dumped if the transmitter is active.
|
||||||
# [v4.0.0] to be released
|
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).
|
||||||
- `eive-tmtc` version v4.0.0
|
|
||||||
- `q7s-package` version v3.0.0
|
# [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
|
## Fixed
|
||||||
|
|
||||||
- CFDP low level protocol bugfix. Requires fsfw update and tmtc update.
|
|
||||||
- Important bugfixes for PTME. See `q7s-package` CHANGELOG.
|
- 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
|
## Changed
|
||||||
|
|
||||||
- Removed PTME busy/ready signals. Those were not used anyway because register reads are used now.
|
- 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.
|
- 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
|
||||||
|
|
||||||
- Added PL I2C reset pin. It is not used for now but could be used for FDIR procedures to restore
|
- Added PL I2C reset pin. It is not used/connected for now but could be used for FDIR procedures to
|
||||||
the PL I2C.
|
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
|
# [v3.1.1] 2023-06-14
|
||||||
|
|
||||||
@ -172,7 +276,6 @@ will consitute of a breaking change warranting a new major release:
|
|||||||
|
|
||||||
# [v2.0.5] 2023-05-11
|
# [v2.0.5] 2023-05-11
|
||||||
|
|
||||||
|
|
||||||
- The dual lane assembly transition failed handler started new transitions towards the current mode
|
- The dual lane assembly transition failed handler started new transitions towards the current mode
|
||||||
instead of the target mode. This means that if the dual lane assembly never reached the initial
|
instead of the target mode. This means that if the dual lane assembly never reached the initial
|
||||||
submode (e.g. mode normal and submode dual side), it will transition back to the current mode,
|
submode (e.g. mode normal and submode dual side), it will transition back to the current mode,
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
# ##############################################################################
|
# ##############################################################################
|
||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
set(OBSW_VERSION_MAJOR 4)
|
set(OBSW_VERSION_MAJOR 6)
|
||||||
set(OBSW_VERSION_MINOR 0)
|
set(OBSW_VERSION_MINOR 0)
|
||||||
set(OBSW_VERSION_REVISION 0)
|
set(OBSW_VERSION_REVISION 0)
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ set(OBSW_ADD_THERMAL_TEMP_INSERTER
|
|||||||
${OBSW_Q7S_EM}
|
${OBSW_Q7S_EM}
|
||||||
CACHE STRING "Add thermal sensor temperature inserter")
|
CACHE STRING "Add thermal sensor temperature inserter")
|
||||||
set(OBSW_ADD_ACS_BOARD
|
set(OBSW_ADD_ACS_BOARD
|
||||||
${INIT_VAL}
|
1
|
||||||
CACHE STRING "Add ACS board module")
|
CACHE STRING "Add ACS board module")
|
||||||
set(OBSW_ADD_GPS_CTRL
|
set(OBSW_ADD_GPS_CTRL
|
||||||
${INIT_VAL}
|
${INIT_VAL}
|
||||||
|
@ -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
|
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.
|
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
|
## PCDU
|
||||||
|
|
||||||
Connect to serial console of P60 Dock
|
Connect to serial console of P60 Dock
|
||||||
|
@ -68,7 +68,7 @@ void ObjectFactory::produce(void* args) {
|
|||||||
#endif
|
#endif
|
||||||
auto sdcMan = new DummySdCardManager("/tmp");
|
auto sdcMan = new DummySdCardManager("/tmp");
|
||||||
ObjectFactory::produceGenericObjects(nullptr, &pusFunnel, &cfdpFunnel, *sdcMan, &ipcStore,
|
ObjectFactory::produceGenericObjects(nullptr, &pusFunnel, &cfdpFunnel, *sdcMan, &ipcStore,
|
||||||
&tmStore, persistentStores, 120);
|
&tmStore, persistentStores, 120, enableHkSets);
|
||||||
|
|
||||||
new TmFunnelHandler(objects::LIVE_TM_TASK, *pusFunnel, *cfdpFunnel);
|
new TmFunnelHandler(objects::LIVE_TM_TASK, *pusFunnel, *cfdpFunnel);
|
||||||
auto* dummyGpioIF = new DummyGpioIF();
|
auto* dummyGpioIF = new DummyGpioIF();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @brief Auto-generated event translation file. Contains 295 translations.
|
* @brief Auto-generated event translation file. Contains 296 translations.
|
||||||
* @details
|
* @details
|
||||||
* Generated on: 2023-05-17 17:15:34
|
* Generated on: 2023-06-21 19:01:02
|
||||||
*/
|
*/
|
||||||
#include "translateEvents.h"
|
#include "translateEvents.h"
|
||||||
|
|
||||||
@ -277,6 +277,7 @@ const char *INDIVIDUAL_BOOT_COUNTS_STRING = "INDIVIDUAL_BOOT_COUNTS";
|
|||||||
const char *TRYING_I2C_RECOVERY_STRING = "TRYING_I2C_RECOVERY";
|
const char *TRYING_I2C_RECOVERY_STRING = "TRYING_I2C_RECOVERY";
|
||||||
const char *I2C_REBOOT_STRING = "I2C_REBOOT";
|
const char *I2C_REBOOT_STRING = "I2C_REBOOT";
|
||||||
const char *PDEC_REBOOT_STRING = "PDEC_REBOOT";
|
const char *PDEC_REBOOT_STRING = "PDEC_REBOOT";
|
||||||
|
const char *FIRMWARE_INFO_STRING = "FIRMWARE_INFO";
|
||||||
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
|
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
|
||||||
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
|
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
|
||||||
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
|
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
|
||||||
@ -847,6 +848,8 @@ const char *translateEvents(Event event) {
|
|||||||
return I2C_REBOOT_STRING;
|
return I2C_REBOOT_STRING;
|
||||||
case (14012):
|
case (14012):
|
||||||
return PDEC_REBOOT_STRING;
|
return PDEC_REBOOT_STRING;
|
||||||
|
case (14013):
|
||||||
|
return FIRMWARE_INFO_STRING;
|
||||||
case (14100):
|
case (14100):
|
||||||
return NO_VALID_SENSOR_TEMPERATURE_STRING;
|
return NO_VALID_SENSOR_TEMPERATURE_STRING;
|
||||||
case (14101):
|
case (14101):
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* @brief Auto-generated object translation file.
|
* @brief Auto-generated object translation file.
|
||||||
* @details
|
* @details
|
||||||
* Contains 171 translations.
|
* Contains 171 translations.
|
||||||
* Generated on: 2023-05-17 17:15:34
|
* Generated on: 2023-06-21 19:01:02
|
||||||
*/
|
*/
|
||||||
#include "translateObjects.h"
|
#include "translateObjects.h"
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ static constexpr char UART_SCEX_DEV[] = "/dev/scex";
|
|||||||
static constexpr char UIO_PDEC_REGISTERS[] = "/dev/uio_pdec_regs";
|
static constexpr char UIO_PDEC_REGISTERS[] = "/dev/uio_pdec_regs";
|
||||||
static constexpr char UIO_PTME[] = "/dev/uio_ptme";
|
static constexpr char UIO_PTME[] = "/dev/uio_ptme";
|
||||||
static constexpr char UIO_PDEC_CONFIG_MEMORY[] = "/dev/uio_pdec_cfg_mem";
|
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_RAM[] = "/dev/uio_pdec_ram";
|
||||||
static constexpr char UIO_PDEC_IRQ[] = "/dev/uio_pdec_irq";
|
static constexpr char UIO_PDEC_IRQ[] = "/dev/uio_pdec_irq";
|
||||||
static constexpr int MAP_ID_PTME_CONFIG = 3;
|
static constexpr int MAP_ID_PTME_CONFIG = 3;
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <fsfw/filesystem/HasFileSystemIF.h>
|
#include <fsfw/filesystem/HasFileSystemIF.h>
|
||||||
#include <fsfw/ipc/QueueFactory.h>
|
#include <fsfw/ipc/QueueFactory.h>
|
||||||
#include <fsfw/tasks/TaskFactory.h>
|
#include <fsfw/tasks/TaskFactory.h>
|
||||||
|
#include <fsfw_hal/linux/uio/UioMapper.h>
|
||||||
|
|
||||||
#include "commonConfig.h"
|
#include "commonConfig.h"
|
||||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||||
@ -22,6 +23,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
|
#include "bsp_q7s/boardconfig/busConf.h"
|
||||||
#include "bsp_q7s/fs/SdCardManager.h"
|
#include "bsp_q7s/fs/SdCardManager.h"
|
||||||
#include "bsp_q7s/memory/scratchApi.h"
|
#include "bsp_q7s/memory/scratchApi.h"
|
||||||
#include "bsp_q7s/xadc/Xadc.h"
|
#include "bsp_q7s/xadc/Xadc.h"
|
||||||
@ -168,7 +170,6 @@ ReturnValue_t CoreController::initialize() {
|
|||||||
|
|
||||||
sdStateMachine();
|
sdStateMachine();
|
||||||
|
|
||||||
triggerEvent(core::REBOOT_SW, CURRENT_CHIP, CURRENT_COPY);
|
|
||||||
EventManagerIF *eventManager =
|
EventManagerIF *eventManager =
|
||||||
ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER);
|
ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER);
|
||||||
if (eventManager == nullptr or eventQueue == nullptr) {
|
if (eventManager == nullptr or eventQueue == nullptr) {
|
||||||
@ -185,7 +186,22 @@ ReturnValue_t CoreController::initialize() {
|
|||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
sif::warning << "Subscribing for GPS GPS_FIX_CHANGE event failed" << std::endl;
|
sif::warning << "Subscribing for GPS GPS_FIX_CHANGE event failed" << std::endl;
|
||||||
}
|
}
|
||||||
return returnvalue::OK;
|
triggerEvent(core::REBOOT_SW, CURRENT_CHIP, CURRENT_COPY);
|
||||||
|
announceCurrentImageInfo();
|
||||||
|
// This has to come before the version announce because it might be required for retrieving
|
||||||
|
// the firmware version.
|
||||||
|
if (common::OBSW_VERSION_MAJOR >= 6 or common::OBSW_VERSION_MAJOR == 4) {
|
||||||
|
UioMapper sysRomMapper(q7s::UIO_SYS_ROM);
|
||||||
|
result = sysRomMapper.getMappedAdress(&mappedSysRomAddr, UioMapper::Permissions::READ_ONLY);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
// TODO: This might be a reason to switch to another image..
|
||||||
|
sif::error << "Getting mapped SYS ROM UIO address failed" << std::endl;
|
||||||
|
result = ObjectManager::CHILD_INIT_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
announceVersionInfo();
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CoreController::initializeAfterTaskCreation() {
|
ReturnValue_t CoreController::initializeAfterTaskCreation() {
|
||||||
@ -210,19 +226,7 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_
|
|||||||
using namespace core;
|
using namespace core;
|
||||||
switch (actionId) {
|
switch (actionId) {
|
||||||
case (ANNOUNCE_VERSION): {
|
case (ANNOUNCE_VERSION): {
|
||||||
uint32_t p1 = (common::OBSW_VERSION_MAJOR << 24) | (common::OBSW_VERSION_MINOR << 16) |
|
announceVersionInfo();
|
||||||
(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);
|
|
||||||
return HasActionsIF::EXECUTION_FINISHED;
|
return HasActionsIF::EXECUTION_FINISHED;
|
||||||
}
|
}
|
||||||
case (ANNOUNCE_BOOT_COUNTS): {
|
case (ANNOUNCE_BOOT_COUNTS): {
|
||||||
@ -230,7 +234,7 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_
|
|||||||
return HasActionsIF::EXECUTION_FINISHED;
|
return HasActionsIF::EXECUTION_FINISHED;
|
||||||
}
|
}
|
||||||
case (ANNOUNCE_CURRENT_IMAGE): {
|
case (ANNOUNCE_CURRENT_IMAGE): {
|
||||||
triggerEvent(CURRENT_IMAGE_INFO, CURRENT_CHIP, CURRENT_COPY);
|
announceCurrentImageInfo();
|
||||||
return HasActionsIF::EXECUTION_FINISHED;
|
return HasActionsIF::EXECUTION_FINISHED;
|
||||||
}
|
}
|
||||||
case (LIST_DIRECTORY_INTO_FILE): {
|
case (LIST_DIRECTORY_INTO_FILE): {
|
||||||
@ -246,6 +250,9 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
std::ostringstream oss("cp ", std::ostringstream::ate);
|
std::ostringstream oss("cp ", std::ostringstream::ate);
|
||||||
|
if (parser.isForceOptSet()) {
|
||||||
|
oss << "-f ";
|
||||||
|
}
|
||||||
if (parser.isRecursiveOptSet()) {
|
if (parser.isRecursiveOptSet()) {
|
||||||
oss << "-r ";
|
oss << "-r ";
|
||||||
}
|
}
|
||||||
@ -318,28 +325,38 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_
|
|||||||
if (size < 1) {
|
if (size < 1) {
|
||||||
return HasActionsIF::INVALID_PARAMETERS;
|
return HasActionsIF::INVALID_PARAMETERS;
|
||||||
}
|
}
|
||||||
std::string path = sdcMan->getCurrentMountPrefix() + REBOOT_FILE;
|
std::string path = sdcMan->getCurrentMountPrefix() + REBOOT_WATCHDOG_FILE;
|
||||||
// Disable the reboot file mechanism
|
parseRebootWatchdogFile(path, rebootWatchdogFile);
|
||||||
parseRebootFile(path, rebootFile);
|
|
||||||
if (data[0] == 0) {
|
if (data[0] == 0) {
|
||||||
rebootFile.enabled = false;
|
rebootWatchdogFile.enabled = false;
|
||||||
rewriteRebootFile(rebootFile);
|
rewriteRebootWatchdogFile(rebootWatchdogFile);
|
||||||
} else if (data[0] == 1) {
|
} else if (data[0] == 1) {
|
||||||
rebootFile.enabled = true;
|
rebootWatchdogFile.enabled = true;
|
||||||
rewriteRebootFile(rebootFile);
|
rewriteRebootWatchdogFile(rebootWatchdogFile);
|
||||||
} else {
|
} else {
|
||||||
return HasActionsIF::INVALID_PARAMETERS;
|
return HasActionsIF::INVALID_PARAMETERS;
|
||||||
}
|
}
|
||||||
return HasActionsIF::EXECUTION_FINISHED;
|
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): {
|
case (RESET_REBOOT_COUNTERS): {
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
resetRebootCount(xsc::ALL_CHIP, xsc::ALL_COPY);
|
resetRebootWatchdogCounters(xsc::ALL_CHIP, xsc::ALL_COPY);
|
||||||
} else if (size == 2) {
|
} else if (size == 2) {
|
||||||
if (data[0] > 1 or data[1] > 1) {
|
if (data[0] > 1 or data[1] > 1) {
|
||||||
return HasActionsIF::INVALID_PARAMETERS;
|
return HasActionsIF::INVALID_PARAMETERS;
|
||||||
}
|
}
|
||||||
resetRebootCount(static_cast<xsc::Chip>(data[0]), static_cast<xsc::Copy>(data[1]));
|
resetRebootWatchdogCounters(static_cast<xsc::Chip>(data[0]),
|
||||||
|
static_cast<xsc::Copy>(data[1]));
|
||||||
}
|
}
|
||||||
return HasActionsIF::EXECUTION_FINISHED;
|
return HasActionsIF::EXECUTION_FINISHED;
|
||||||
}
|
}
|
||||||
@ -434,11 +451,11 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_
|
|||||||
if (size < 1) {
|
if (size < 1) {
|
||||||
return HasActionsIF::INVALID_PARAMETERS;
|
return HasActionsIF::INVALID_PARAMETERS;
|
||||||
}
|
}
|
||||||
std::string path = sdcMan->getCurrentMountPrefix() + REBOOT_FILE;
|
std::string path = sdcMan->getCurrentMountPrefix() + REBOOT_WATCHDOG_FILE;
|
||||||
// Disable the reboot file mechanism
|
// Disable the reboot file mechanism
|
||||||
parseRebootFile(path, rebootFile);
|
parseRebootWatchdogFile(path, rebootWatchdogFile);
|
||||||
rebootFile.maxCount = data[0];
|
rebootWatchdogFile.maxCount = data[0];
|
||||||
rewriteRebootFile(rebootFile);
|
rewriteRebootWatchdogFile(rebootWatchdogFile);
|
||||||
return HasActionsIF::EXECUTION_FINISHED;
|
return HasActionsIF::EXECUTION_FINISHED;
|
||||||
}
|
}
|
||||||
case (XSC_REBOOT_OBC): {
|
case (XSC_REBOOT_OBC): {
|
||||||
@ -1196,45 +1213,7 @@ ReturnValue_t CoreController::actionXscReboot(const uint8_t *data, size_t size)
|
|||||||
auto tgtChip = static_cast<xsc::Chip>(data[1]);
|
auto tgtChip = static_cast<xsc::Chip>(data[1]);
|
||||||
auto tgtCopy = static_cast<xsc::Copy>(data[2]);
|
auto tgtCopy = static_cast<xsc::Copy>(data[2]);
|
||||||
|
|
||||||
// This function can not really fail
|
performGracefulShutdown(tgtChip, tgtCopy);
|
||||||
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::FAILED;
|
return returnvalue::FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1247,14 +1226,23 @@ ReturnValue_t CoreController::actionReboot(const uint8_t *data, size_t size) {
|
|||||||
|
|
||||||
ReturnValue_t CoreController::gracefulShutdownTasks(xsc::Chip chip, xsc::Copy copy,
|
ReturnValue_t CoreController::gracefulShutdownTasks(xsc::Chip chip, xsc::Copy copy,
|
||||||
bool &protOpPerformed) {
|
bool &protOpPerformed) {
|
||||||
|
// Store both sequence counters persistently.
|
||||||
|
core::SAVE_CFDP_SEQUENCE_COUNT = true;
|
||||||
|
core::SAVE_PUS_SEQUENCE_COUNT = true;
|
||||||
|
|
||||||
sdcMan->setBlocking(true);
|
sdcMan->setBlocking(true);
|
||||||
sdcMan->markUnusable();
|
sdcMan->markUnusable();
|
||||||
// Wait two seconds to ensure no one uses the SD cards
|
// Wait two seconds to ensure no one uses the SD cards
|
||||||
TaskFactory::delayTask(2000);
|
TaskFactory::delayTask(2000);
|
||||||
|
|
||||||
|
// Ensure that all writes/reads do finish.
|
||||||
|
sync();
|
||||||
|
|
||||||
// Attempt graceful shutdown by unmounting and switching off SD cards
|
// Attempt graceful shutdown by unmounting and switching off SD cards
|
||||||
sdcMan->switchOffSdCard(sd::SdCard::SLOT_0);
|
sdcMan->switchOffSdCard(sd::SdCard::SLOT_0);
|
||||||
sdcMan->switchOffSdCard(sd::SdCard::SLOT_1);
|
sdcMan->switchOffSdCard(sd::SdCard::SLOT_1);
|
||||||
// If any boot copies are unprotected
|
// If any boot copies are unprotected.
|
||||||
|
// Actually this function only ensures that reboots to the own image are protected..
|
||||||
ReturnValue_t result = setBootCopyProtection(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, true,
|
ReturnValue_t result = setBootCopyProtection(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, true,
|
||||||
protOpPerformed, false);
|
protOpPerformed, false);
|
||||||
if (result == returnvalue::OK and protOpPerformed) {
|
if (result == returnvalue::OK and protOpPerformed) {
|
||||||
@ -1543,7 +1531,8 @@ void CoreController::performMountedSdCardOperations() {
|
|||||||
if (not timeFileInitDone) {
|
if (not timeFileInitDone) {
|
||||||
initClockFromTimeFile();
|
initClockFromTimeFile();
|
||||||
}
|
}
|
||||||
performRebootFileHandling(false);
|
performRebootWatchdogHandling(false);
|
||||||
|
performRebootCountersHandling(false);
|
||||||
}
|
}
|
||||||
backupTimeFileHandler();
|
backupTimeFileHandler();
|
||||||
};
|
};
|
||||||
@ -1615,118 +1604,127 @@ ReturnValue_t CoreController::performSdCardCheck() {
|
|||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreController::performRebootFileHandling(bool recreateFile) {
|
void CoreController::performRebootWatchdogHandling(bool recreateFile) {
|
||||||
using namespace std;
|
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;
|
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 (not std::filesystem::exists(path, e) or recreateFile) {
|
||||||
#if OBSW_VERBOSE_LEVEL >= 1
|
#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
|
#endif
|
||||||
rebootFile.enabled = false;
|
rebootWatchdogFile.enabled = false;
|
||||||
rebootFile.img00Cnt = 0;
|
rebootWatchdogFile.img00Cnt = 0;
|
||||||
rebootFile.img01Cnt = 0;
|
rebootWatchdogFile.img01Cnt = 0;
|
||||||
rebootFile.img10Cnt = 0;
|
rebootWatchdogFile.img10Cnt = 0;
|
||||||
rebootFile.img11Cnt = 0;
|
rebootWatchdogFile.img11Cnt = 0;
|
||||||
rebootFile.lastChip = xsc::Chip::CHIP_0;
|
rebootWatchdogFile.lastChip = xsc::Chip::CHIP_0;
|
||||||
rebootFile.lastCopy = xsc::Copy::COPY_0;
|
rebootWatchdogFile.lastCopy = xsc::Copy::COPY_0;
|
||||||
rebootFile.img00Lock = false;
|
rebootWatchdogFile.img00Lock = false;
|
||||||
rebootFile.img01Lock = false;
|
rebootWatchdogFile.img01Lock = false;
|
||||||
rebootFile.img10Lock = false;
|
rebootWatchdogFile.img10Lock = false;
|
||||||
rebootFile.img11Lock = false;
|
rebootWatchdogFile.img11Lock = false;
|
||||||
rebootFile.mechanismNextChip = xsc::Chip::NO_CHIP;
|
rebootWatchdogFile.mechanismNextChip = xsc::Chip::NO_CHIP;
|
||||||
rebootFile.mechanismNextCopy = xsc::Copy::NO_COPY;
|
rebootWatchdogFile.mechanismNextCopy = xsc::Copy::NO_COPY;
|
||||||
rebootFile.bootFlag = false;
|
rebootWatchdogFile.bootFlag = false;
|
||||||
rewriteRebootFile(rebootFile);
|
rewriteRebootWatchdogFile(rebootWatchdogFile);
|
||||||
} else {
|
} else {
|
||||||
if (not parseRebootFile(path, rebootFile)) {
|
if (not parseRebootWatchdogFile(path, rebootWatchdogFile)) {
|
||||||
performRebootFileHandling(true);
|
performRebootWatchdogHandling(true);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CURRENT_CHIP == xsc::CHIP_0) {
|
if (CURRENT_CHIP == xsc::CHIP_0) {
|
||||||
if (CURRENT_COPY == xsc::COPY_0) {
|
if (CURRENT_COPY == xsc::COPY_0) {
|
||||||
rebootFile.img00Cnt++;
|
rebootWatchdogFile.img00Cnt++;
|
||||||
} else {
|
} else {
|
||||||
rebootFile.img01Cnt++;
|
rebootWatchdogFile.img01Cnt++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (CURRENT_COPY == xsc::COPY_0) {
|
if (CURRENT_COPY == xsc::COPY_0) {
|
||||||
rebootFile.img10Cnt++;
|
rebootWatchdogFile.img10Cnt++;
|
||||||
} else {
|
} else {
|
||||||
rebootFile.img11Cnt++;
|
rebootWatchdogFile.img11Cnt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rebootFile.bootFlag) {
|
if (rebootWatchdogFile.bootFlag) {
|
||||||
// Trigger event to inform ground that a reboot was triggered
|
// 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);
|
triggerEvent(core::REBOOT_MECHANISM_TRIGGERED, p1, 0);
|
||||||
// Clear the boot flag
|
// Clear the boot flag
|
||||||
rebootFile.bootFlag = false;
|
rebootWatchdogFile.bootFlag = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
announceBootCounts();
|
if (rebootWatchdogFile.mechanismNextChip != xsc::NO_CHIP and
|
||||||
|
rebootWatchdogFile.mechanismNextCopy != xsc::NO_COPY) {
|
||||||
if (rebootFile.mechanismNextChip != xsc::NO_CHIP and
|
if (CURRENT_CHIP != rebootWatchdogFile.mechanismNextChip or
|
||||||
rebootFile.mechanismNextCopy != xsc::NO_COPY) {
|
CURRENT_COPY != rebootWatchdogFile.mechanismNextCopy) {
|
||||||
if (CURRENT_CHIP != rebootFile.mechanismNextChip or
|
std::string infoString = std::to_string(rebootWatchdogFile.mechanismNextChip) + " " +
|
||||||
CURRENT_COPY != rebootFile.mechanismNextCopy) {
|
std::to_string(rebootWatchdogFile.mechanismNextCopy);
|
||||||
std::string infoString = std::to_string(rebootFile.mechanismNextChip) + " " +
|
|
||||||
std::to_string(rebootFile.mechanismNextCopy);
|
|
||||||
sif::warning << "CoreController::performRebootFileHandling: Expected to be on image "
|
sif::warning << "CoreController::performRebootFileHandling: Expected to be on image "
|
||||||
<< infoString << " but currently on other image. Locking " << infoString
|
<< infoString << " but currently on other image. Locking " << infoString
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
// Firmware or other component might be corrupt and we are on another image then the target
|
// 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.
|
// image specified by the mechanism. We can't really trust the target image anymore.
|
||||||
// Lock it for now
|
// Lock it for now
|
||||||
if (rebootFile.mechanismNextChip == xsc::CHIP_0) {
|
if (rebootWatchdogFile.mechanismNextChip == xsc::CHIP_0) {
|
||||||
if (rebootFile.mechanismNextCopy == xsc::COPY_0) {
|
if (rebootWatchdogFile.mechanismNextCopy == xsc::COPY_0) {
|
||||||
rebootFile.img00Lock = true;
|
rebootWatchdogFile.img00Lock = true;
|
||||||
} else {
|
} else {
|
||||||
rebootFile.img01Lock = true;
|
rebootWatchdogFile.img01Lock = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (rebootFile.mechanismNextCopy == xsc::COPY_0) {
|
if (rebootWatchdogFile.mechanismNextCopy == xsc::COPY_0) {
|
||||||
rebootFile.img10Lock = true;
|
rebootWatchdogFile.img10Lock = true;
|
||||||
} else {
|
} else {
|
||||||
rebootFile.img11Lock = true;
|
rebootWatchdogFile.img11Lock = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rebootFile.lastChip = CURRENT_CHIP;
|
rebootWatchdogFile.lastChip = CURRENT_CHIP;
|
||||||
rebootFile.lastCopy = CURRENT_COPY;
|
rebootWatchdogFile.lastCopy = CURRENT_COPY;
|
||||||
// Only reboot if the reboot functionality is enabled.
|
// Only reboot if the reboot functionality is enabled.
|
||||||
// The handler will still increment the boot counts
|
// 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
|
// Reboot to other image
|
||||||
bool doReboot = false;
|
bool doReboot = false;
|
||||||
xsc::Chip tgtChip = xsc::NO_CHIP;
|
xsc::Chip tgtChip = xsc::NO_CHIP;
|
||||||
xsc::Copy tgtCopy = xsc::NO_COPY;
|
xsc::Copy tgtCopy = xsc::NO_COPY;
|
||||||
determineAndExecuteReboot(rebootFile, doReboot, tgtChip, tgtCopy);
|
rebootWatchdogAlgorithm(rebootWatchdogFile, doReboot, tgtChip, tgtCopy);
|
||||||
if (doReboot) {
|
if (doReboot) {
|
||||||
rebootFile.bootFlag = true;
|
rebootWatchdogFile.bootFlag = true;
|
||||||
#if OBSW_VERBOSE_LEVEL >= 1
|
#if OBSW_VERBOSE_LEVEL >= 1
|
||||||
sif::info << "Boot counter for image " << CURRENT_CHIP << " " << CURRENT_COPY
|
sif::info << "Boot counter for image " << CURRENT_CHIP << " " << CURRENT_COPY
|
||||||
<< " too high. Rebooting to " << tgtChip << " " << tgtCopy << std::endl;
|
<< " too high. Rebooting to " << tgtChip << " " << tgtCopy << std::endl;
|
||||||
#endif
|
#endif
|
||||||
rebootFile.mechanismNextChip = tgtChip;
|
rebootWatchdogFile.mechanismNextChip = tgtChip;
|
||||||
rebootFile.mechanismNextCopy = tgtCopy;
|
rebootWatchdogFile.mechanismNextCopy = tgtCopy;
|
||||||
rewriteRebootFile(rebootFile);
|
rewriteRebootWatchdogFile(rebootWatchdogFile);
|
||||||
xsc_boot_copy(static_cast<xsc_libnor_chip_t>(tgtChip),
|
performGracefulShutdown(tgtChip, tgtCopy);
|
||||||
static_cast<xsc_libnor_copy_t>(tgtCopy));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rebootFile.mechanismNextChip = xsc::NO_CHIP;
|
rebootWatchdogFile.mechanismNextChip = xsc::NO_CHIP;
|
||||||
rebootFile.mechanismNextCopy = xsc::NO_COPY;
|
rebootWatchdogFile.mechanismNextCopy = xsc::NO_COPY;
|
||||||
}
|
}
|
||||||
rewriteRebootFile(rebootFile);
|
rewriteRebootWatchdogFile(rebootWatchdogFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot,
|
void CoreController::rebootWatchdogAlgorithm(RebootWatchdogFile &rf, bool &needsReboot,
|
||||||
xsc::Chip &tgtChip, xsc::Copy &tgtCopy) {
|
xsc::Chip &tgtChip, xsc::Copy &tgtCopy) {
|
||||||
tgtChip = xsc::CHIP_0;
|
tgtChip = xsc::CHIP_0;
|
||||||
tgtCopy = xsc::COPY_0;
|
tgtCopy = xsc::COPY_0;
|
||||||
needsReboot = false;
|
needsReboot = false;
|
||||||
@ -1814,7 +1812,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;
|
using namespace std;
|
||||||
std::string selfMatch;
|
std::string selfMatch;
|
||||||
if (CURRENT_CHIP == xsc::CHIP_0) {
|
if (CURRENT_CHIP == xsc::CHIP_0) {
|
||||||
@ -1996,68 +1994,174 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreController::resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy) {
|
bool CoreController::parseRebootCountersFile(std::string path, RebootCountersFile &rf) {
|
||||||
std::string path = currMntPrefix + REBOOT_FILE;
|
using namespace std;
|
||||||
// Disable the reboot file mechanism
|
ifstream file(path);
|
||||||
parseRebootFile(path, rebootFile);
|
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) {
|
if (tgtChip == xsc::ALL_CHIP and tgtCopy == xsc::ALL_COPY) {
|
||||||
rebootFile.img00Cnt = 0;
|
rebootWatchdogFile.img00Cnt = 0;
|
||||||
rebootFile.img01Cnt = 0;
|
rebootWatchdogFile.img01Cnt = 0;
|
||||||
rebootFile.img10Cnt = 0;
|
rebootWatchdogFile.img10Cnt = 0;
|
||||||
rebootFile.img11Cnt = 0;
|
rebootWatchdogFile.img11Cnt = 0;
|
||||||
} else {
|
} else {
|
||||||
if (tgtChip == xsc::CHIP_0) {
|
if (tgtChip == xsc::CHIP_0) {
|
||||||
if (tgtCopy == xsc::COPY_0) {
|
if (tgtCopy == xsc::COPY_0) {
|
||||||
rebootFile.img00Cnt = 0;
|
rebootWatchdogFile.img00Cnt = 0;
|
||||||
} else {
|
} else {
|
||||||
rebootFile.img01Cnt = 0;
|
rebootWatchdogFile.img01Cnt = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (tgtCopy == xsc::COPY_0) {
|
if (tgtCopy == xsc::COPY_0) {
|
||||||
rebootFile.img10Cnt = 0;
|
rebootWatchdogFile.img10Cnt = 0;
|
||||||
} else {
|
} else {
|
||||||
rebootFile.img11Cnt = 0;
|
rebootWatchdogFile.img11Cnt = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rewriteRebootFile(rebootFile);
|
rewriteRebootWatchdogFile(rebootWatchdogFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreController::rewriteRebootFile(RebootFile file) {
|
void CoreController::performRebootCountersHandling(bool recreateFile) {
|
||||||
std::string path = currMntPrefix + REBOOT_FILE;
|
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<int>(file.lastChip)
|
||||||
|
<< " " << static_cast<int>(file.lastCopy)
|
||||||
|
<< "\nnext: " << static_cast<int>(file.mechanismNextChip) << " "
|
||||||
|
<< static_cast<int>(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);
|
std::ofstream rebootFile(path);
|
||||||
if (rebootFile.is_open()) {
|
if (rebootFile.is_open()) {
|
||||||
// Initiate reboot file first. Reboot handling will be on on initialization
|
rebootFile << "img00: " << file.img00Cnt << "\nimg01: " << file.img01Cnt
|
||||||
rebootFile << "on: " << file.enabled << "\nmaxcnt: " << file.maxCount
|
<< "\nimg10: " << file.img10Cnt << "\nimg11: " << file.img11Cnt << "\n";
|
||||||
<< "\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<int>(file.lastChip)
|
|
||||||
<< " " << static_cast<int>(file.lastCopy)
|
|
||||||
<< "\nnext: " << static_cast<int>(file.mechanismNextChip) << " "
|
|
||||||
<< static_cast<int>(file.mechanismNextCopy) << "\n";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreController::setRebootMechanismLock(bool lock, xsc::Chip tgtChip, xsc::Copy tgtCopy) {
|
void CoreController::setRebootMechanismLock(bool lock, xsc::Chip tgtChip, xsc::Copy tgtCopy) {
|
||||||
std::string path = currMntPrefix + REBOOT_FILE;
|
std::string path = currMntPrefix + REBOOT_WATCHDOG_FILE;
|
||||||
// Disable the reboot file mechanism
|
parseRebootWatchdogFile(path, rebootWatchdogFile);
|
||||||
parseRebootFile(path, rebootFile);
|
|
||||||
if (tgtChip == xsc::CHIP_0) {
|
if (tgtChip == xsc::CHIP_0) {
|
||||||
if (tgtCopy == xsc::COPY_0) {
|
if (tgtCopy == xsc::COPY_0) {
|
||||||
rebootFile.img00Lock = lock;
|
rebootWatchdogFile.img00Lock = lock;
|
||||||
} else {
|
} else {
|
||||||
rebootFile.img01Lock = lock;
|
rebootWatchdogFile.img01Lock = lock;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (tgtCopy == xsc::COPY_0) {
|
if (tgtCopy == xsc::COPY_0) {
|
||||||
rebootFile.img10Lock = lock;
|
rebootWatchdogFile.img10Lock = lock;
|
||||||
} else {
|
} else {
|
||||||
rebootFile.img11Lock = lock;
|
rebootWatchdogFile.img11Lock = lock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rewriteRebootFile(rebootFile);
|
rewriteRebootWatchdogFile(rebootWatchdogFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CoreController::backupTimeFileHandler() {
|
ReturnValue_t CoreController::backupTimeFileHandler() {
|
||||||
@ -2344,10 +2448,12 @@ bool CoreController::startSdStateMachine(sd::SdCard targetActiveSd, SdCfgMode mo
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CoreController::announceBootCounts() {
|
void CoreController::announceBootCounts() {
|
||||||
uint64_t totalBootCount =
|
uint64_t totalBootCount = rebootCountersFile.img00Cnt + rebootCountersFile.img01Cnt +
|
||||||
rebootFile.img00Cnt + rebootFile.img01Cnt + rebootFile.img10Cnt + rebootFile.img11Cnt;
|
rebootCountersFile.img10Cnt + rebootCountersFile.img11Cnt;
|
||||||
uint32_t individualBootCountsP1 = (rebootFile.img00Cnt << 16) | rebootFile.img01Cnt;
|
uint32_t individualBootCountsP1 =
|
||||||
uint32_t individualBootCountsP2 = (rebootFile.img10Cnt << 16) | rebootFile.img11Cnt;
|
(rebootCountersFile.img00Cnt << 16) | rebootCountersFile.img01Cnt;
|
||||||
|
uint32_t individualBootCountsP2 =
|
||||||
|
(rebootCountersFile.img10Cnt << 16) | rebootCountersFile.img11Cnt;
|
||||||
triggerEvent(core::INDIVIDUAL_BOOT_COUNTS, individualBootCountsP1, individualBootCountsP2);
|
triggerEvent(core::INDIVIDUAL_BOOT_COUNTS, individualBootCountsP1, individualBootCountsP2);
|
||||||
triggerEvent(core::REBOOT_COUNTER, (totalBootCount >> 32) & 0xffffffff,
|
triggerEvent(core::REBOOT_COUNTER, (totalBootCount >> 32) & 0xffffffff,
|
||||||
totalBootCount & 0xffffffff);
|
totalBootCount & 0xffffffff);
|
||||||
@ -2405,6 +2511,80 @@ 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);
|
||||||
|
|
||||||
|
if (common::OBSW_VERSION_MAJOR >= 6 or common::OBSW_VERSION_MAJOR == 4) {
|
||||||
|
if (mappedSysRomAddr != nullptr) {
|
||||||
|
uint32_t p1Firmware = *(reinterpret_cast<uint32_t *>(mappedSysRomAddr));
|
||||||
|
uint32_t p2Firmware = *(reinterpret_cast<uint32_t *>(mappedSysRomAddr) + 1);
|
||||||
|
triggerEvent(FIRMWARE_INFO, p1Firmware, p2Firmware);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
bool CoreController::isNumber(const std::string &s) {
|
bool CoreController::isNumber(const std::string &s) {
|
||||||
return !s.empty() && std::find_if(s.begin(), s.end(),
|
return !s.empty() && std::find_if(s.begin(), s.end(),
|
||||||
[](unsigned char c) { return !std::isdigit(c); }) == s.end();
|
[](unsigned char c) { return !std::isdigit(c); }) == s.end();
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <fsfw/globalfunctions/PeriodicOperationDivider.h>
|
#include <fsfw/globalfunctions/PeriodicOperationDivider.h>
|
||||||
#include <fsfw/parameters/ParameterHelper.h>
|
#include <fsfw/parameters/ParameterHelper.h>
|
||||||
#include <fsfw/parameters/ReceivesParameterMessagesIF.h>
|
#include <fsfw/parameters/ReceivesParameterMessagesIF.h>
|
||||||
|
#include <fsfw_hal/linux/uio/UioMapper.h>
|
||||||
#include <libxiphos.h>
|
#include <libxiphos.h>
|
||||||
#include <mission/acs/archive/GPSDefinitions.h>
|
#include <mission/acs/archive/GPSDefinitions.h>
|
||||||
#include <mission/utility/trace.h>
|
#include <mission/utility/trace.h>
|
||||||
@ -23,7 +24,7 @@
|
|||||||
class Timer;
|
class Timer;
|
||||||
class SdCardManager;
|
class SdCardManager;
|
||||||
|
|
||||||
struct RebootFile {
|
struct RebootWatchdogFile {
|
||||||
static constexpr uint8_t DEFAULT_MAX_BOOT_CNT = 10;
|
static constexpr uint8_t DEFAULT_MAX_BOOT_CNT = 10;
|
||||||
|
|
||||||
bool enabled = true;
|
bool enabled = true;
|
||||||
@ -44,6 +45,93 @@ struct RebootFile {
|
|||||||
xsc::Copy mechanismNextCopy = xsc::Copy::NO_COPY;
|
xsc::Copy mechanismNextCopy = xsc::Copy::NO_COPY;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class RebootWatchdogPacket : public SerialLinkedListAdapter<SerializeIF> {
|
||||||
|
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<uint8_t>(rf.lastChip);
|
||||||
|
lastCopy = static_cast<uint8_t>(rf.lastCopy);
|
||||||
|
nextChip = static_cast<uint8_t>(rf.mechanismNextChip);
|
||||||
|
nextCopy = static_cast<uint8_t>(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<uint8_t> enabled = false;
|
||||||
|
SerializeElement<uint32_t> maxCount = 0;
|
||||||
|
SerializeElement<uint32_t> img00Count = 0;
|
||||||
|
SerializeElement<uint32_t> img01Count = 0;
|
||||||
|
SerializeElement<uint32_t> img10Count = 0;
|
||||||
|
SerializeElement<uint32_t> img11Count = 0;
|
||||||
|
SerializeElement<uint8_t> img00Lock = false;
|
||||||
|
SerializeElement<uint8_t> img01Lock = false;
|
||||||
|
SerializeElement<uint8_t> img10Lock = false;
|
||||||
|
SerializeElement<uint8_t> img11Lock = false;
|
||||||
|
SerializeElement<uint8_t> lastChip = 0;
|
||||||
|
SerializeElement<uint8_t> lastCopy = 0;
|
||||||
|
SerializeElement<uint8_t> nextChip = 0;
|
||||||
|
SerializeElement<uint8_t> 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<SerializeIF> {
|
||||||
|
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<uint16_t> img00Count = 0;
|
||||||
|
SerializeElement<uint16_t> img01Count = 0;
|
||||||
|
SerializeElement<uint16_t> img10Count = 0;
|
||||||
|
SerializeElement<uint16_t> img11Count = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class CoreController : public ExtendedControllerBase, public ReceivesParameterMessagesIF {
|
class CoreController : public ExtendedControllerBase, public ReceivesParameterMessagesIF {
|
||||||
public:
|
public:
|
||||||
enum ParamId : uint8_t { PREF_SD = 0, NUM_IDS };
|
enum ParamId : uint8_t { PREF_SD = 0, NUM_IDS };
|
||||||
@ -57,10 +145,15 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
|
|||||||
|
|
||||||
const std::string VERSION_FILE =
|
const std::string VERSION_FILE =
|
||||||
"/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::VERSION_FILE_NAME);
|
"/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::VERSION_FILE_NAME);
|
||||||
const std::string REBOOT_FILE =
|
const std::string LEGACY_REBOOT_WATCHDOG_FILE =
|
||||||
"/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::REBOOT_FILE_NAME);
|
"/" + 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 =
|
const std::string BACKUP_TIME_FILE =
|
||||||
"/" + std::string(core::CONF_FOLDER) + "/" + std::string(core::TIME_FILE_NAME);
|
"/" + 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_0_MOUNT_DIR[] = "/tmp/mntupdate-xdi-qspi0-nom-rootfs";
|
||||||
static constexpr char CHIP_0_COPY_1_MOUNT_DIR[] = "/tmp/mntupdate-xdi-qspi0-gold-rootfs";
|
static constexpr char CHIP_0_COPY_1_MOUNT_DIR[] = "/tmp/mntupdate-xdi-qspi0-gold-rootfs";
|
||||||
@ -142,6 +235,7 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
|
|||||||
|
|
||||||
static constexpr bool BLOCKING_SD_INIT = false;
|
static constexpr bool BLOCKING_SD_INIT = false;
|
||||||
|
|
||||||
|
uint32_t* mappedSysRomAddr = nullptr;
|
||||||
SdCardManager* sdcMan = nullptr;
|
SdCardManager* sdcMan = nullptr;
|
||||||
MessageQueueIF* eventQueue = nullptr;
|
MessageQueueIF* eventQueue = nullptr;
|
||||||
|
|
||||||
@ -191,7 +285,8 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
|
|||||||
std::array<uint8_t, 1024> dirListingBuf{};
|
std::array<uint8_t, 1024> dirListingBuf{};
|
||||||
DirListingDumpContext dumpContext{};
|
DirListingDumpContext dumpContext{};
|
||||||
|
|
||||||
RebootFile rebootFile = {};
|
RebootWatchdogFile rebootWatchdogFile = {};
|
||||||
|
RebootCountersFile rebootCountersFile = {};
|
||||||
|
|
||||||
CommandExecutor cmdExecutor;
|
CommandExecutor cmdExecutor;
|
||||||
SimpleRingBuffer cmdReplyBuf;
|
SimpleRingBuffer cmdReplyBuf;
|
||||||
@ -261,12 +356,14 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
|
|||||||
void currentStateSetter(sd::SdCard sdCard, sd::SdState newState);
|
void currentStateSetter(sd::SdCard sdCard, sd::SdState newState);
|
||||||
void executeNextExternalSdCommand();
|
void executeNextExternalSdCommand();
|
||||||
void checkExternalSdCommandStatus();
|
void checkExternalSdCommandStatus();
|
||||||
void performRebootFileHandling(bool recreateFile);
|
void performRebootWatchdogHandling(bool recreateFile);
|
||||||
|
void performRebootCountersHandling(bool recreateFile);
|
||||||
|
|
||||||
ReturnValue_t actionListDirectoryIntoFile(ActionId_t actionId, MessageQueueId_t commandedBy,
|
ReturnValue_t actionListDirectoryIntoFile(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||||
const uint8_t* data, size_t size);
|
const uint8_t* data, size_t size);
|
||||||
ReturnValue_t actionListDirectoryDumpDirectly(ActionId_t actionId, MessageQueueId_t commandedBy,
|
ReturnValue_t actionListDirectoryDumpDirectly(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||||
const uint8_t* data, size_t size);
|
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,
|
ReturnValue_t actionListDirectoryCommonCommandCreator(const uint8_t* data, size_t size,
|
||||||
std::ostringstream& oss);
|
std::ostringstream& oss);
|
||||||
@ -280,13 +377,17 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe
|
|||||||
int handleBootCopyProtAtIndex(xsc::Chip targetChip, xsc::Copy targetCopy, bool protect,
|
int handleBootCopyProtAtIndex(xsc::Chip targetChip, xsc::Copy targetCopy, bool protect,
|
||||||
bool& protOperationPerformed, bool selfChip, bool selfCopy,
|
bool& protOperationPerformed, bool selfChip, bool selfCopy,
|
||||||
bool allChips, bool allCopies, uint8_t arrIdx);
|
bool allChips, bool allCopies, uint8_t arrIdx);
|
||||||
void determineAndExecuteReboot(RebootFile& rf, bool& needsReboot, xsc::Chip& tgtChip,
|
void rebootWatchdogAlgorithm(RebootWatchdogFile& rf, bool& needsReboot, xsc::Chip& tgtChip,
|
||||||
xsc::Copy& tgtCopy);
|
xsc::Copy& tgtCopy);
|
||||||
void resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy);
|
void resetRebootWatchdogCounters(xsc::Chip tgtChip, xsc::Copy tgtCopy);
|
||||||
void setRebootMechanismLock(bool lock, xsc::Chip tgtChip, xsc::Copy tgtCopy);
|
void setRebootMechanismLock(bool lock, xsc::Chip tgtChip, xsc::Copy tgtCopy);
|
||||||
bool parseRebootFile(std::string path, RebootFile& file);
|
bool parseRebootWatchdogFile(std::string path, RebootWatchdogFile& file);
|
||||||
void rewriteRebootFile(RebootFile file);
|
bool parseRebootCountersFile(std::string path, RebootCountersFile& file);
|
||||||
|
void rewriteRebootWatchdogFile(RebootWatchdogFile file);
|
||||||
|
void rewriteRebootCountersFile(RebootCountersFile file);
|
||||||
void announceBootCounts();
|
void announceBootCounts();
|
||||||
|
void announceVersionInfo();
|
||||||
|
void announceCurrentImageInfo();
|
||||||
void readHkData();
|
void readHkData();
|
||||||
void dirListingDumpHandler();
|
void dirListingDumpHandler();
|
||||||
bool isNumber(const std::string& s);
|
bool isNumber(const std::string& s);
|
||||||
|
@ -499,7 +499,7 @@ void ObjectFactory::createAcsBoardComponents(SpiComIF& spiComIF, LinuxLibgpioIF*
|
|||||||
debugGps = true;
|
debugGps = true;
|
||||||
#endif
|
#endif
|
||||||
RESET_ARGS_GNSS.gpioComIF = gpioComIF;
|
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,
|
auto gpsCtrl = new GpsHyperionLinuxController(objects::GPS_CONTROLLER, objects::NO_OBJECT,
|
||||||
enableHkSets, debugGps);
|
enableHkSets, debugGps);
|
||||||
gpsCtrl->setResetPinTriggerFunction(gps::triggerGpioResetPin, &RESET_ARGS_GNSS);
|
gpsCtrl->setResetPinTriggerFunction(gps::triggerGpioResetPin, &RESET_ARGS_GNSS);
|
||||||
@ -1010,16 +1010,18 @@ void ObjectFactory::createRadSensorChipSelect(LinuxLibgpioIF* gpioIF) {
|
|||||||
|
|
||||||
void ObjectFactory::createPlI2cResetGpio(LinuxLibgpioIF* gpioIF) {
|
void ObjectFactory::createPlI2cResetGpio(LinuxLibgpioIF* gpioIF) {
|
||||||
using namespace gpio;
|
using namespace gpio;
|
||||||
if (gpioIF == nullptr) {
|
if (common::OBSW_VERSION_MAJOR >= 6 or common::OBSW_VERSION_MAJOR == 4) {
|
||||||
return;
|
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);
|
||||||
}
|
}
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
@ -325,6 +325,10 @@ void scheduling::initTasks() {
|
|||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
scheduling::printAddObjectError("HEATER_HANDLER", objects::HEATER_HANDLER);
|
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
|
#if OBSW_ADD_SYRLINKS == 1
|
||||||
PeriodicTaskIF* syrlinksCom = factory->createPeriodicTask(
|
PeriodicTaskIF* syrlinksCom = factory->createPeriodicTask(
|
||||||
|
@ -37,8 +37,8 @@ void ObjectFactory::produce(void* args) {
|
|||||||
|
|
||||||
PersistentTmStores stores;
|
PersistentTmStores stores;
|
||||||
ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel,
|
ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel,
|
||||||
*SdCardManager::instance(), &ipcStore, &tmStore, stores,
|
*SdCardManager::instance(), &ipcStore, &tmStore, stores, 200,
|
||||||
200);
|
enableHkSets);
|
||||||
|
|
||||||
LinuxLibgpioIF* gpioComIF = nullptr;
|
LinuxLibgpioIF* gpioComIF = nullptr;
|
||||||
SerialComIF* uartComIF = nullptr;
|
SerialComIF* uartComIF = nullptr;
|
||||||
@ -100,9 +100,10 @@ void ObjectFactory::produce(void* args) {
|
|||||||
|
|
||||||
new CoreController(objects::CORE_CONTROLLER, enableHkSets);
|
new CoreController(objects::CORE_CONTROLLER, enableHkSets);
|
||||||
|
|
||||||
#if OBSW_ADD_ACS_BOARD == 1
|
// Initialize chip select to avoid SPI bus issues.
|
||||||
// Still initialize chip select to avoid SPI bus issues.
|
|
||||||
createRadSensorChipSelect(gpioComIF);
|
createRadSensorChipSelect(gpioComIF);
|
||||||
|
|
||||||
|
#if OBSW_ADD_ACS_BOARD == 1
|
||||||
createAcsBoardComponents(*spiMainComIF, gpioComIF, uartComIF, *pwrSwitcher, true,
|
createAcsBoardComponents(*spiMainComIF, gpioComIF, uartComIF, *pwrSwitcher, true,
|
||||||
adis1650x::Type::ADIS16507);
|
adis1650x::Type::ADIS16507);
|
||||||
#else
|
#else
|
||||||
|
@ -33,8 +33,8 @@ void ObjectFactory::produce(void* args) {
|
|||||||
|
|
||||||
PersistentTmStores stores;
|
PersistentTmStores stores;
|
||||||
ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel,
|
ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel,
|
||||||
*SdCardManager::instance(), &ipcStore, &tmStore, stores,
|
*SdCardManager::instance(), &ipcStore, &tmStore, stores, 200,
|
||||||
200);
|
true);
|
||||||
|
|
||||||
LinuxLibgpioIF* gpioComIF = nullptr;
|
LinuxLibgpioIF* gpioComIF = nullptr;
|
||||||
SerialComIF* uartComIF = nullptr;
|
SerialComIF* uartComIF = nullptr;
|
||||||
|
@ -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 OBSW_UPDATE_ARCHIVE_FILE_NAME[] = "eive-sw-update.tar.xz";
|
||||||
static constexpr char STRIPPED_OBSW_BINARY_FILE_NAME[] = "eive-obsw-stripped";
|
static constexpr char STRIPPED_OBSW_BINARY_FILE_NAME[] = "eive-obsw-stripped";
|
||||||
static constexpr char OBSW_VERSION_FILE_NAME[] = "obsw_version.txt";
|
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_PATH[] = "/usr/bin/eive-obsw";
|
||||||
static constexpr char OBSW_VERSION_FILE_PATH[] = "/usr/share/eive-obsw/obsw_version.txt";
|
static constexpr char OBSW_VERSION_FILE_PATH[] = "/usr/share/eive-obsw/obsw_version.txt";
|
||||||
|
@ -5,14 +5,19 @@
|
|||||||
ImtqDummy::ImtqDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie,
|
ImtqDummy::ImtqDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie,
|
||||||
power::Switch_t pwrSwitcher, bool enableHkSets)
|
power::Switch_t pwrSwitcher, bool enableHkSets)
|
||||||
: DeviceHandlerBase(objectId, comif, comCookie),
|
: DeviceHandlerBase(objectId, comif, comCookie),
|
||||||
setNoTorque(this),
|
|
||||||
setWithTorque(this),
|
|
||||||
enableHkSets(enableHkSets),
|
enableHkSets(enableHkSets),
|
||||||
|
statusSet(this),
|
||||||
|
dipoleSet(*this),
|
||||||
|
rawMtmNoTorque(this),
|
||||||
|
hkDatasetNoTorque(this),
|
||||||
|
rawMtmWithTorque(this),
|
||||||
|
hkDatasetWithTorque(this),
|
||||||
|
calMtmMeasurementSet(this),
|
||||||
switcher(pwrSwitcher) {}
|
switcher(pwrSwitcher) {}
|
||||||
|
|
||||||
ImtqDummy::~ImtqDummy() = default;
|
ImtqDummy::~ImtqDummy() = default;
|
||||||
|
|
||||||
void ImtqDummy::doStartUp() { setMode(MODE_NORMAL); }
|
void ImtqDummy::doStartUp() { setMode(MODE_ON); }
|
||||||
|
|
||||||
void ImtqDummy::doShutDown() { setMode(_MODE_POWER_DOWN); }
|
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<int16_t>({0}));
|
localDataPoolMap.emplace(imtq::MCU_TEMPERATURE_WT, new PoolEntry<int16_t>({0}));
|
||||||
|
|
||||||
poolManager.subscribeForDiagPeriodicPacket(
|
poolManager.subscribeForDiagPeriodicPacket(
|
||||||
subdp::DiagnosticsHkPeriodicParams(setNoTorque.getSid(), enableHkSets, 30.0));
|
subdp::DiagnosticsHkPeriodicParams(hkDatasetNoTorque.getSid(), enableHkSets, 30.0));
|
||||||
poolManager.subscribeForDiagPeriodicPacket(
|
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);
|
return DeviceHandlerBase::initializeLocalDataPool(localDataPoolMap, poolManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalPoolDataSetBase *ImtqDummy::getDataSetHandle(sid_t sid) {
|
LocalPoolDataSetBase *ImtqDummy::getDataSetHandle(sid_t sid) {
|
||||||
if (sid == setNoTorque.getSid()) {
|
if (sid == hkDatasetNoTorque.getSid()) {
|
||||||
return &setNoTorque;
|
return &hkDatasetNoTorque;
|
||||||
} else if (sid == setWithTorque.getSid()) {
|
} else if (sid == dipoleSet.getSid()) {
|
||||||
return &setWithTorque;
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -18,11 +18,18 @@ class ImtqDummy : public DeviceHandlerBase {
|
|||||||
~ImtqDummy() override;
|
~ImtqDummy() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ReturnValue_t getSwitches(const uint8_t **switches, uint8_t *numberOfSwitches) override;
|
|
||||||
imtq::HkDatasetNoTorque setNoTorque;
|
|
||||||
imtq::HkDatasetWithTorque setWithTorque;
|
|
||||||
bool enableHkSets;
|
bool enableHkSets;
|
||||||
|
|
||||||
|
imtq::StatusDataset statusSet;
|
||||||
|
imtq::DipoleActuationSet dipoleSet;
|
||||||
|
imtq::RawMtmMeasurementNoTorque rawMtmNoTorque;
|
||||||
|
imtq::HkDatasetNoTorque hkDatasetNoTorque;
|
||||||
|
|
||||||
|
imtq::RawMtmMeasurementWithTorque rawMtmWithTorque;
|
||||||
|
imtq::HkDatasetWithTorque hkDatasetWithTorque;
|
||||||
|
|
||||||
|
imtq::CalibratedMtmMeasurementSet calMtmMeasurementSet;
|
||||||
|
|
||||||
PoolEntry<uint8_t> statusMode = PoolEntry<uint8_t>({0});
|
PoolEntry<uint8_t> statusMode = PoolEntry<uint8_t>({0});
|
||||||
PoolEntry<uint8_t> statusError = PoolEntry<uint8_t>({0});
|
PoolEntry<uint8_t> statusError = PoolEntry<uint8_t>({0});
|
||||||
PoolEntry<uint8_t> statusConfig = PoolEntry<uint8_t>({0});
|
PoolEntry<uint8_t> statusConfig = PoolEntry<uint8_t>({0});
|
||||||
@ -42,6 +49,8 @@ class ImtqDummy : public DeviceHandlerBase {
|
|||||||
|
|
||||||
power::Switch_t switcher = power::NO_SWITCH;
|
power::Switch_t switcher = power::NO_SWITCH;
|
||||||
|
|
||||||
|
ReturnValue_t getSwitches(const uint8_t **switches, uint8_t *numberOfSwitches) override;
|
||||||
|
|
||||||
void doStartUp() override;
|
void doStartUp() override;
|
||||||
void doShutDown() override;
|
void doShutDown() override;
|
||||||
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;
|
ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override;
|
||||||
|
@ -3,13 +3,24 @@
|
|||||||
#include <mission/acs/rwHelpers.h>
|
#include <mission/acs/rwHelpers.h>
|
||||||
|
|
||||||
RwDummy::RwDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie)
|
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() {}
|
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; }
|
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<uint32_t>({0}));
|
localDataPoolMap.emplace(rws::SPI_BYTES_READ, new PoolEntry<uint32_t>({0}));
|
||||||
localDataPoolMap.emplace(rws::SPI_REG_OVERRUN_ERRORS, new PoolEntry<uint32_t>({0}));
|
localDataPoolMap.emplace(rws::SPI_REG_OVERRUN_ERRORS, new PoolEntry<uint32_t>({0}));
|
||||||
localDataPoolMap.emplace(rws::SPI_TOTAL_ERRORS, new PoolEntry<uint32_t>({0}));
|
localDataPoolMap.emplace(rws::SPI_TOTAL_ERRORS, new PoolEntry<uint32_t>({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;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define DUMMIES_RWDUMMY_H_
|
#define DUMMIES_RWDUMMY_H_
|
||||||
|
|
||||||
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
||||||
|
#include <mission/acs/rwHelpers.h>
|
||||||
|
|
||||||
class RwDummy : public DeviceHandlerBase {
|
class RwDummy : public DeviceHandlerBase {
|
||||||
public:
|
public:
|
||||||
@ -15,6 +16,11 @@ class RwDummy : public DeviceHandlerBase {
|
|||||||
virtual ~RwDummy();
|
virtual ~RwDummy();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
rws::StatusSet statusSet;
|
||||||
|
rws::LastResetSatus lastResetStatusSet;
|
||||||
|
rws::TmDataset tmDataset;
|
||||||
|
rws::RwSpeedActuationSet rwSpeedActuationSet;
|
||||||
|
|
||||||
PoolEntry<int32_t> rwSpeed = PoolEntry<int32_t>({0});
|
PoolEntry<int32_t> rwSpeed = PoolEntry<int32_t>({0});
|
||||||
PoolEntry<uint16_t> rampTime = PoolEntry<uint16_t>({10});
|
PoolEntry<uint16_t> rampTime = PoolEntry<uint16_t>({10});
|
||||||
|
|
||||||
|
@ -98,6 +98,25 @@ ReturnValue_t TemperatureSensorInserter::performOperation(uint8_t opCode) {
|
|||||||
}
|
}
|
||||||
break;
|
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): {
|
case (TestCase::COLD_CAMERA): {
|
||||||
if (cycles == 15) {
|
if (cycles == 15) {
|
||||||
sif::debug << "Setting cold CAM temperature" << std::endl;
|
sif::debug << "Setting cold CAM temperature" << std::endl;
|
||||||
|
@ -32,6 +32,7 @@ class TemperatureSensorInserter : public ExecutableObjectIF, public SystemObject
|
|||||||
COLD_STR = 4,
|
COLD_STR = 4,
|
||||||
COLD_STR_CONSECUTIVE = 5,
|
COLD_STR_CONSECUTIVE = 5,
|
||||||
COLD_CAMERA = 6,
|
COLD_CAMERA = 6,
|
||||||
|
COLD_PLOC_CONSECUTIVE = 7,
|
||||||
};
|
};
|
||||||
int iteration = 0;
|
int iteration = 0;
|
||||||
uint32_t cycles = 0;
|
uint32_t cycles = 0;
|
||||||
|
2
fsfw
2
fsfw
@ -1 +1 @@
|
|||||||
Subproject commit 0a977ea688cd78585aabb9ba511eaf8030452712
|
Subproject commit 8da89eba80f73cb05e5c38fc012456f1d9569af5
|
@ -271,6 +271,7 @@ 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
|
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
|
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
|
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
|
||||||
14100;0x3714;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/tcsDefs.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
|
14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/tcsDefs.h
|
||||||
14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
|
14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
|
||||||
|
|
@ -271,6 +271,7 @@ 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
|
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
|
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
|
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
|
||||||
14100;0x3714;NO_VALID_SENSOR_TEMPERATURE;MEDIUM;No description;mission/controller/tcsDefs.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
|
14101;0x3715;NO_HEALTHY_HEATER_AVAILABLE;MEDIUM;No description;mission/controller/tcsDefs.h
|
||||||
14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
|
14102;0x3716;SYRLINKS_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @brief Auto-generated event translation file. Contains 295 translations.
|
* @brief Auto-generated event translation file. Contains 296 translations.
|
||||||
* @details
|
* @details
|
||||||
* Generated on: 2023-05-17 17:15:34
|
* Generated on: 2023-06-21 19:01:02
|
||||||
*/
|
*/
|
||||||
#include "translateEvents.h"
|
#include "translateEvents.h"
|
||||||
|
|
||||||
@ -277,6 +277,7 @@ const char *INDIVIDUAL_BOOT_COUNTS_STRING = "INDIVIDUAL_BOOT_COUNTS";
|
|||||||
const char *TRYING_I2C_RECOVERY_STRING = "TRYING_I2C_RECOVERY";
|
const char *TRYING_I2C_RECOVERY_STRING = "TRYING_I2C_RECOVERY";
|
||||||
const char *I2C_REBOOT_STRING = "I2C_REBOOT";
|
const char *I2C_REBOOT_STRING = "I2C_REBOOT";
|
||||||
const char *PDEC_REBOOT_STRING = "PDEC_REBOOT";
|
const char *PDEC_REBOOT_STRING = "PDEC_REBOOT";
|
||||||
|
const char *FIRMWARE_INFO_STRING = "FIRMWARE_INFO";
|
||||||
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
|
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
|
||||||
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
|
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
|
||||||
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
|
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
|
||||||
@ -847,6 +848,8 @@ const char *translateEvents(Event event) {
|
|||||||
return I2C_REBOOT_STRING;
|
return I2C_REBOOT_STRING;
|
||||||
case (14012):
|
case (14012):
|
||||||
return PDEC_REBOOT_STRING;
|
return PDEC_REBOOT_STRING;
|
||||||
|
case (14013):
|
||||||
|
return FIRMWARE_INFO_STRING;
|
||||||
case (14100):
|
case (14100):
|
||||||
return NO_VALID_SENSOR_TEMPERATURE_STRING;
|
return NO_VALID_SENSOR_TEMPERATURE_STRING;
|
||||||
case (14101):
|
case (14101):
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* @brief Auto-generated object translation file.
|
* @brief Auto-generated object translation file.
|
||||||
* @details
|
* @details
|
||||||
* Contains 175 translations.
|
* Contains 175 translations.
|
||||||
* Generated on: 2023-05-17 17:15:34
|
* Generated on: 2023-06-21 19:01:02
|
||||||
*/
|
*/
|
||||||
#include "translateObjects.h"
|
#include "translateObjects.h"
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* @brief Auto-generated event translation file. Contains 295 translations.
|
* @brief Auto-generated event translation file. Contains 296 translations.
|
||||||
* @details
|
* @details
|
||||||
* Generated on: 2023-05-17 17:15:34
|
* Generated on: 2023-06-21 19:01:02
|
||||||
*/
|
*/
|
||||||
#include "translateEvents.h"
|
#include "translateEvents.h"
|
||||||
|
|
||||||
@ -277,6 +277,7 @@ const char *INDIVIDUAL_BOOT_COUNTS_STRING = "INDIVIDUAL_BOOT_COUNTS";
|
|||||||
const char *TRYING_I2C_RECOVERY_STRING = "TRYING_I2C_RECOVERY";
|
const char *TRYING_I2C_RECOVERY_STRING = "TRYING_I2C_RECOVERY";
|
||||||
const char *I2C_REBOOT_STRING = "I2C_REBOOT";
|
const char *I2C_REBOOT_STRING = "I2C_REBOOT";
|
||||||
const char *PDEC_REBOOT_STRING = "PDEC_REBOOT";
|
const char *PDEC_REBOOT_STRING = "PDEC_REBOOT";
|
||||||
|
const char *FIRMWARE_INFO_STRING = "FIRMWARE_INFO";
|
||||||
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
|
const char *NO_VALID_SENSOR_TEMPERATURE_STRING = "NO_VALID_SENSOR_TEMPERATURE";
|
||||||
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
|
const char *NO_HEALTHY_HEATER_AVAILABLE_STRING = "NO_HEALTHY_HEATER_AVAILABLE";
|
||||||
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
|
const char *SYRLINKS_OVERHEATING_STRING = "SYRLINKS_OVERHEATING";
|
||||||
@ -847,6 +848,8 @@ const char *translateEvents(Event event) {
|
|||||||
return I2C_REBOOT_STRING;
|
return I2C_REBOOT_STRING;
|
||||||
case (14012):
|
case (14012):
|
||||||
return PDEC_REBOOT_STRING;
|
return PDEC_REBOOT_STRING;
|
||||||
|
case (14013):
|
||||||
|
return FIRMWARE_INFO_STRING;
|
||||||
case (14100):
|
case (14100):
|
||||||
return NO_VALID_SENSOR_TEMPERATURE_STRING;
|
return NO_VALID_SENSOR_TEMPERATURE_STRING;
|
||||||
case (14101):
|
case (14101):
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* @brief Auto-generated object translation file.
|
* @brief Auto-generated object translation file.
|
||||||
* @details
|
* @details
|
||||||
* Contains 175 translations.
|
* Contains 175 translations.
|
||||||
* Generated on: 2023-05-17 17:15:34
|
* Generated on: 2023-06-21 19:01:02
|
||||||
*/
|
*/
|
||||||
#include "translateObjects.h"
|
#include "translateObjects.h"
|
||||||
|
|
||||||
|
@ -16,9 +16,9 @@ AxiPtmeConfig::AxiPtmeConfig(object_id_t objectId, std::string axiUio, int mapNu
|
|||||||
AxiPtmeConfig::~AxiPtmeConfig() {}
|
AxiPtmeConfig::~AxiPtmeConfig() {}
|
||||||
|
|
||||||
ReturnValue_t AxiPtmeConfig::initialize() {
|
ReturnValue_t AxiPtmeConfig::initialize() {
|
||||||
ReturnValue_t result = returnvalue::OK;
|
|
||||||
UioMapper uioMapper(axiUio, mapNum);
|
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) {
|
if (result != returnvalue::OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -26,8 +26,7 @@ ReturnValue_t AxiPtmeConfig::initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t AxiPtmeConfig::writeCaduRateReg(uint8_t rateVal) {
|
ReturnValue_t AxiPtmeConfig::writeCaduRateReg(uint8_t rateVal) {
|
||||||
ReturnValue_t result = returnvalue::OK;
|
ReturnValue_t result = mutex->lockMutex(timeoutType, mutexTimeout);
|
||||||
result = mutex->lockMutex(timeoutType, mutexTimeout);
|
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
sif::warning << "AxiPtmeConfig::writeCaduRateReg: Failed to lock mutex" << std::endl;
|
sif::warning << "AxiPtmeConfig::writeCaduRateReg: Failed to lock mutex" << std::endl;
|
||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
@ -41,6 +40,11 @@ ReturnValue_t AxiPtmeConfig::writeCaduRateReg(uint8_t rateVal) {
|
|||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t AxiPtmeConfig::readCaduRateReg() {
|
||||||
|
MutexGuard mg(mutex);
|
||||||
|
return static_cast<uint8_t>(*(baseAddress + CADU_BITRATE_REG));
|
||||||
|
}
|
||||||
|
|
||||||
void AxiPtmeConfig::enableTxclockManipulator() {
|
void AxiPtmeConfig::enableTxclockManipulator() {
|
||||||
writeBit(COMMON_CONFIG_REG, true, BitPos::EN_TX_CLK_MANIPULATOR);
|
writeBit(COMMON_CONFIG_REG, true, BitPos::EN_TX_CLK_MANIPULATOR);
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ class AxiPtmeConfig : public SystemObject {
|
|||||||
* frequency of the clock connected to the bit clock input of PTME.
|
* frequency of the clock connected to the bit clock input of PTME.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t writeCaduRateReg(uint8_t rateVal);
|
ReturnValue_t writeCaduRateReg(uint8_t rateVal);
|
||||||
|
uint8_t readCaduRateReg();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Next to functions control the tx clock manipulator component
|
* @brief Next to functions control the tx clock manipulator component
|
||||||
|
@ -33,10 +33,21 @@ ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) {
|
|||||||
} else {
|
} else {
|
||||||
return DirectTmSinkIF::IS_BUSY;
|
return DirectTmSinkIF::IS_BUSY;
|
||||||
}
|
}
|
||||||
|
if (not pollReadyForOctet(MAX_BUSY_POLLS)) {
|
||||||
|
abortPacketTransfer();
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
for (size_t idx = 0; idx < size; idx++) {
|
for (size_t idx = 0; idx < size; idx++) {
|
||||||
// if (pollInterfaceReadiness(2, false) == returnvalue::OK) {
|
if (not pollReadyForOctet(MAX_BUSY_POLLS)) {
|
||||||
|
abortPacketTransfer();
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
*(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(data[idx]);
|
*(vcBaseReg + DATA_REG_OFFSET) = static_cast<uint32_t>(data[idx]);
|
||||||
}
|
}
|
||||||
|
if (not pollReadyForOctet(MAX_BUSY_POLLS)) {
|
||||||
|
abortPacketTransfer();
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
completePacketTransfer();
|
completePacketTransfer();
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
@ -51,7 +62,6 @@ bool PapbVcInterface::pollReadyForPacket() const {
|
|||||||
// Check if PAPB interface is ready to receive data. Use the configuration register for this.
|
// 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.
|
// Bit 5, see PTME ptme_001_01-0-7-r2 Table 31.
|
||||||
uint32_t reg = *vcBaseReg;
|
uint32_t reg = *vcBaseReg;
|
||||||
// bool busy = (reg >> 5) & 0b1;
|
|
||||||
return (reg >> 6) & 0b1;
|
return (reg >> 6) & 0b1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,6 +87,20 @@ bool PapbVcInterface::isBusy() const { return not pollReadyForPacket(); }
|
|||||||
|
|
||||||
void PapbVcInterface::cancelTransfer() { abortPacketTransfer(); }
|
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() {
|
ReturnValue_t PapbVcInterface::sendTestFrame() {
|
||||||
/** Size of one complete transfer frame data field amounts to 1105 bytes */
|
/** Size of one complete transfer frame data field amounts to 1105 bytes */
|
||||||
uint8_t testPacket[1105];
|
uint8_t testPacket[1105];
|
||||||
|
@ -80,6 +80,7 @@ class PapbVcInterface : public VirtualChannelIF {
|
|||||||
|
|
||||||
static constexpr long int FIRST_DELAY_PAPB_POLLING_NS = 10;
|
static constexpr long int FIRST_DELAY_PAPB_POLLING_NS = 10;
|
||||||
static constexpr long int MAX_DELAY_PAPB_POLLING_NS = 40;
|
static constexpr long int MAX_DELAY_PAPB_POLLING_NS = 40;
|
||||||
|
static constexpr uint32_t MAX_BUSY_POLLS = 1000;
|
||||||
|
|
||||||
LinuxLibgpioIF* gpioComIF = nullptr;
|
LinuxLibgpioIF* gpioComIF = nullptr;
|
||||||
/** High when external buffer memory of virtual channel is empty */
|
/** High when external buffer memory of virtual channel is empty */
|
||||||
@ -118,6 +119,8 @@ class PapbVcInterface : public VirtualChannelIF {
|
|||||||
*/
|
*/
|
||||||
inline bool pollReadyForPacket() 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
|
* @brief This function can be used for debugging to check whether there are packets in
|
||||||
* the packet buffer of the virtual channel or not.
|
* the packet buffer of the virtual channel or not.
|
||||||
|
@ -26,6 +26,11 @@ ReturnValue_t PtmeConfig::setRate(uint32_t bitRate) {
|
|||||||
return axiPtmeConfig->writeCaduRateReg(static_cast<uint8_t>(rateVal));
|
return axiPtmeConfig->writeCaduRateReg(static_cast<uint8_t>(rateVal));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t PtmeConfig::getRate() {
|
||||||
|
uint8_t rateReg = axiPtmeConfig->readCaduRateReg();
|
||||||
|
return (BIT_CLK_FREQ / (rateReg + 1));
|
||||||
|
}
|
||||||
|
|
||||||
void PtmeConfig::invertTxClock(bool invert) {
|
void PtmeConfig::invertTxClock(bool invert) {
|
||||||
if (invert) {
|
if (invert) {
|
||||||
axiPtmeConfig->enableTxclockInversion();
|
axiPtmeConfig->enableTxclockInversion();
|
||||||
|
@ -32,6 +32,7 @@ class PtmeConfig : public SystemObject {
|
|||||||
* of the CADU clock due to the convolutional code added by the s-Band transceiver.
|
* of the CADU clock due to the convolutional code added by the s-Band transceiver.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t setRate(uint32_t bitRate);
|
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
|
* @brief Will change the time the tx data signal is updated with respect to the tx clock
|
||||||
|
@ -57,7 +57,8 @@
|
|||||||
</toolChain>
|
</toolChain>
|
||||||
</folderInfo>
|
</folderInfo>
|
||||||
<sourceEntries>
|
<sourceEntries>
|
||||||
<entry excluding="cmake-build-debug-q7s-em|cmake-build-debug-q7s|bsp_q7s|cmake-build-debug/_deps|cmake-build-release-q7s-em|build-Debug-RPi|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|fsfwconfig" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
<entry excluding="unittest/rebootLogic|thirdparty/json|cmake-build-debug-q7s-em|cmake-build-debug-q7s|bsp_q7s|cmake-build-debug/_deps|cmake-build-release-q7s-em|build-Debug-RPi|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|fsfwconfig" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||||
|
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="thirdparty/json/include"/>
|
||||||
</sourceEntries>
|
</sourceEntries>
|
||||||
</configuration>
|
</configuration>
|
||||||
</storageModule>
|
</storageModule>
|
||||||
@ -119,7 +120,8 @@
|
|||||||
</toolChain>
|
</toolChain>
|
||||||
</folderInfo>
|
</folderInfo>
|
||||||
<sourceEntries>
|
<sourceEntries>
|
||||||
<entry excluding="cmake-build-debug-q7s-em|cmake-build-debug-q7s|bsp_q7s|cmake-build-debug/_deps|cmake-build-release-q7s-em|build-Debug-RPi|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|fsfwconfig" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
<entry excluding="unittest/rebootLogic|thirdparty/json|cmake-build-debug-q7s-em|cmake-build-debug-q7s|bsp_q7s|cmake-build-debug/_deps|cmake-build-release-q7s-em|build-Debug-RPi|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|fsfwconfig" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||||
|
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="thirdparty/json/include"/>
|
||||||
</sourceEntries>
|
</sourceEntries>
|
||||||
</configuration>
|
</configuration>
|
||||||
</storageModule>
|
</storageModule>
|
||||||
@ -187,7 +189,8 @@
|
|||||||
</toolChain>
|
</toolChain>
|
||||||
</folderInfo>
|
</folderInfo>
|
||||||
<sourceEntries>
|
<sourceEntries>
|
||||||
<entry excluding="cmake-build-debug-q7s-em|cmake-build-debug-q7s|bsp_q7s|cmake-build-debug/_deps|cmake-build-release-q7s-em|build-Debug-RPi|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|fsfwconfig" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
<entry excluding="unittest/rebootLogic|thirdparty/json|cmake-build-debug-q7s-em|cmake-build-debug-q7s|bsp_q7s|cmake-build-debug/_deps|cmake-build-release-q7s-em|build-Debug-RPi|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|fsfwconfig" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||||
|
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="thirdparty/json/include"/>
|
||||||
</sourceEntries>
|
</sourceEntries>
|
||||||
</configuration>
|
</configuration>
|
||||||
</storageModule>
|
</storageModule>
|
||||||
@ -255,7 +258,8 @@
|
|||||||
</toolChain>
|
</toolChain>
|
||||||
</folderInfo>
|
</folderInfo>
|
||||||
<sourceEntries>
|
<sourceEntries>
|
||||||
<entry excluding="cmake-build-debug-q7s-em|cmake-build-debug-q7s|bsp_q7s|cmake-build-debug/_deps|cmake-build-release-q7s-em|build-Debug-RPi|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|fsfwconfig" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
<entry excluding="unittest/rebootLogic|thirdparty/json|cmake-build-debug-q7s-em|cmake-build-debug-q7s|bsp_q7s|cmake-build-debug/_deps|cmake-build-release-q7s-em|build-Debug-RPi|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|fsfwconfig" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||||
|
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="thirdparty/json/include"/>
|
||||||
</sourceEntries>
|
</sourceEntries>
|
||||||
</configuration>
|
</configuration>
|
||||||
</storageModule>
|
</storageModule>
|
||||||
@ -418,7 +422,8 @@
|
|||||||
</toolChain>
|
</toolChain>
|
||||||
</folderInfo>
|
</folderInfo>
|
||||||
<sourceEntries>
|
<sourceEntries>
|
||||||
<entry excluding="build-Debug-RPi/_deps/etl-src/uml|build-Debug-RPi/_deps/etl-src/test|build-Debug-RPi/_deps/etl-src/temp|build-Debug-RPi/_deps/etl-src/support|build-Debug-RPi/_deps/etl-src/subprojects|build-Debug-RPi/_deps/etl-src/scripts|build-Debug-RPi/_deps/etl-src/images|build-Debug-RPi/_deps/etl-src/examples|build-Debug-RPi/_deps/etl-src/cmake|build-Debug-RPi/_deps/etl-src/arduino|cmake-build-debug-q7s|cmake-build-debug|cmake-build-debug-q7s-em|cmake-build-release-q7s-em|bsp_hosted|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
<entry excluding="unittest/rebootLogic|thirdparty/json|build-Debug-RPi/_deps/etl-src/uml|build-Debug-RPi/_deps/etl-src/test|build-Debug-RPi/_deps/etl-src/temp|build-Debug-RPi/_deps/etl-src/support|build-Debug-RPi/_deps/etl-src/subprojects|build-Debug-RPi/_deps/etl-src/scripts|build-Debug-RPi/_deps/etl-src/images|build-Debug-RPi/_deps/etl-src/examples|build-Debug-RPi/_deps/etl-src/cmake|build-Debug-RPi/_deps/etl-src/arduino|cmake-build-debug-q7s|cmake-build-debug|cmake-build-debug-q7s-em|cmake-build-release-q7s-em|bsp_hosted|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||||
|
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="thirdparty/json/include"/>
|
||||||
</sourceEntries>
|
</sourceEntries>
|
||||||
</configuration>
|
</configuration>
|
||||||
</storageModule>
|
</storageModule>
|
||||||
@ -580,7 +585,8 @@
|
|||||||
</toolChain>
|
</toolChain>
|
||||||
</folderInfo>
|
</folderInfo>
|
||||||
<sourceEntries>
|
<sourceEntries>
|
||||||
<entry excluding="build-Debug-RPi/_deps/etl-src/uml|build-Debug-RPi/_deps/etl-src/test|build-Debug-RPi/_deps/etl-src/temp|build-Debug-RPi/_deps/etl-src/support|build-Debug-RPi/_deps/etl-src/subprojects|build-Debug-RPi/_deps/etl-src/scripts|build-Debug-RPi/_deps/etl-src/images|build-Debug-RPi/_deps/etl-src/examples|build-Debug-RPi/_deps/etl-src/cmake|build-Debug-RPi/_deps/etl-src/arduino|cmake-build-debug-q7s|cmake-build-debug|cmake-build-debug-q7s-em|cmake-build-release-q7s-em|bsp_hosted|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
<entry excluding="unittest/rebootLogic|thirdparty/json|build-Debug-RPi/_deps/etl-src/uml|build-Debug-RPi/_deps/etl-src/test|build-Debug-RPi/_deps/etl-src/temp|build-Debug-RPi/_deps/etl-src/support|build-Debug-RPi/_deps/etl-src/subprojects|build-Debug-RPi/_deps/etl-src/scripts|build-Debug-RPi/_deps/etl-src/images|build-Debug-RPi/_deps/etl-src/examples|build-Debug-RPi/_deps/etl-src/cmake|build-Debug-RPi/_deps/etl-src/arduino|cmake-build-debug-q7s|cmake-build-debug|cmake-build-debug-q7s-em|cmake-build-release-q7s-em|bsp_hosted|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||||
|
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="thirdparty/json/include"/>
|
||||||
</sourceEntries>
|
</sourceEntries>
|
||||||
</configuration>
|
</configuration>
|
||||||
</storageModule>
|
</storageModule>
|
||||||
@ -750,7 +756,8 @@
|
|||||||
</toolChain>
|
</toolChain>
|
||||||
</folderInfo>
|
</folderInfo>
|
||||||
<sourceEntries>
|
<sourceEntries>
|
||||||
<entry excluding="cmake-build-release-q7s-em|build-Debug-RPi|bsp_hosted|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|cmake-build-debug|cmake-build-debug-q7s-em|build-Debug-Host|build-Watchdog-Debug" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
<entry excluding="unittest/rebootLogic|thirdparty/json|cmake-build-release-q7s-em|build-Debug-RPi|bsp_hosted|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|cmake-build-debug|cmake-build-debug-q7s-em|build-Debug-Host|build-Watchdog-Debug" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||||
|
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="thirdparty/json/include"/>
|
||||||
</sourceEntries>
|
</sourceEntries>
|
||||||
</configuration>
|
</configuration>
|
||||||
</storageModule>
|
</storageModule>
|
||||||
@ -917,7 +924,8 @@
|
|||||||
</toolChain>
|
</toolChain>
|
||||||
</folderInfo>
|
</folderInfo>
|
||||||
<sourceEntries>
|
<sourceEntries>
|
||||||
<entry excluding="cmake-build-debug-q7s|cmake-build-release-q7s-em|cmake-build-release-q7s/_deps/etl-src/uml|cmake-build-release-q7s/_deps/etl-src/test|cmake-build-release-q7s/_deps/etl-src/temp|cmake-build-release-q7s/_deps/etl-src/support|cmake-build-release-q7s/_deps/etl-src/subprojects|cmake-build-release-q7s/_deps/etl-src/scripts|cmake-build-release-q7s/_deps/etl-src/images|cmake-build-release-q7s/_deps/etl-src/examples|cmake-build-release-q7s/_deps/etl-src/cmake|cmake-build-release-q7s/_deps/etl-src/arduino|build-Debug-RPi|bsp_hosted|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|cmake-build-debug|cmake-build-debug-q7s-em|build-Debug-Host|build-Watchdog-Debug" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
<entry excluding="unittest/rebootLogic|thirdparty/json|cmake-build-debug-q7s|cmake-build-release-q7s-em|cmake-build-release-q7s/_deps/etl-src/uml|cmake-build-release-q7s/_deps/etl-src/test|cmake-build-release-q7s/_deps/etl-src/temp|cmake-build-release-q7s/_deps/etl-src/support|cmake-build-release-q7s/_deps/etl-src/subprojects|cmake-build-release-q7s/_deps/etl-src/scripts|cmake-build-release-q7s/_deps/etl-src/images|cmake-build-release-q7s/_deps/etl-src/examples|cmake-build-release-q7s/_deps/etl-src/cmake|cmake-build-release-q7s/_deps/etl-src/arduino|build-Debug-RPi|bsp_hosted|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|cmake-build-debug|cmake-build-debug-q7s-em|build-Debug-Host|build-Watchdog-Debug" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||||
|
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="thirdparty/json/include"/>
|
||||||
</sourceEntries>
|
</sourceEntries>
|
||||||
</configuration>
|
</configuration>
|
||||||
</storageModule>
|
</storageModule>
|
||||||
@ -1084,7 +1092,8 @@
|
|||||||
</toolChain>
|
</toolChain>
|
||||||
</folderInfo>
|
</folderInfo>
|
||||||
<sourceEntries>
|
<sourceEntries>
|
||||||
<entry excluding="cmake-build-debug/_deps/etl-src/uml|cmake-build-debug/_deps/etl-src/test|cmake-build-debug/_deps/etl-src/temp|cmake-build-debug/_deps/etl-src/support|cmake-build-debug/_deps/etl-src/subprojects|cmake-build-debug/_deps/etl-src/scripts|cmake-build-debug/_deps/etl-src/images|cmake-build-debug/_deps/etl-src/examples|cmake-build-debug/_deps/etl-src/cmake|cmake-build-debug/_deps/etl-src/arduino|cmake-build-release-q7s-em|build-Debug-RPi|bsp_hosted|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
<entry excluding="unittest/rebootLogic|thirdparty/json|cmake-build-debug-q7s-em/_deps/etl-src|cmake-build-debug/_deps/etl-src/uml|cmake-build-debug/_deps/etl-src/test|cmake-build-debug/_deps/etl-src/temp|cmake-build-debug/_deps/etl-src/support|cmake-build-debug/_deps/etl-src/subprojects|cmake-build-debug/_deps/etl-src/scripts|cmake-build-debug/_deps/etl-src/images|cmake-build-debug/_deps/etl-src/examples|cmake-build-debug/_deps/etl-src/cmake|cmake-build-debug/_deps/etl-src/arduino|cmake-build-release-q7s-em|build-Debug-RPi|bsp_hosted|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||||
|
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="thirdparty/json/include"/>
|
||||||
</sourceEntries>
|
</sourceEntries>
|
||||||
</configuration>
|
</configuration>
|
||||||
</storageModule>
|
</storageModule>
|
||||||
@ -1149,7 +1158,8 @@
|
|||||||
</toolChain>
|
</toolChain>
|
||||||
</folderInfo>
|
</folderInfo>
|
||||||
<sourceEntries>
|
<sourceEntries>
|
||||||
<entry excluding="cmake-build-debug/_deps/etl-src/uml|cmake-build-debug/_deps/etl-src/test|cmake-build-debug/_deps/etl-src/temp|cmake-build-debug/_deps/etl-src/support|cmake-build-debug/_deps/etl-src/subprojects|cmake-build-debug/_deps/etl-src/scripts|cmake-build-debug/_deps/etl-src/images|cmake-build-debug/_deps/etl-src/examples|cmake-build-debug/_deps/etl-src/cmake|cmake-build-debug/_deps/etl-src/arduino|cmake-build-release-q7s-em|build-Debug-RPi|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|fsfwconfig" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
<entry excluding="unittest/rebootLogic|thirdparty/json|cmake-build-debug-q7s-em/_deps/etl-src|cmake-build-debug/_deps/etl-src/uml|cmake-build-debug/_deps/etl-src/test|cmake-build-debug/_deps/etl-src/temp|cmake-build-debug/_deps/etl-src/support|cmake-build-debug/_deps/etl-src/subprojects|cmake-build-debug/_deps/etl-src/scripts|cmake-build-debug/_deps/etl-src/images|cmake-build-debug/_deps/etl-src/examples|cmake-build-debug/_deps/etl-src/cmake|cmake-build-debug/_deps/etl-src/arduino|cmake-build-release-q7s-em|build-Debug-RPi|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|fsfwconfig" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||||
|
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="thirdparty/json/include"/>
|
||||||
</sourceEntries>
|
</sourceEntries>
|
||||||
</configuration>
|
</configuration>
|
||||||
</storageModule>
|
</storageModule>
|
||||||
@ -1172,7 +1182,7 @@
|
|||||||
</extensions>
|
</extensions>
|
||||||
</storageModule>
|
</storageModule>
|
||||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||||
<configuration artifactName="${ProjName}" buildProperties="" description="" errorParsers="org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.CWDLocator;org.eclipse.cdt.core.GCCErrorParser" id="cdt.managedbuild.toolchain.gnu.mingw.base.1455833186.1840876443.2117915473.688890851.1707795689.1171630561" name="eive-q7s-debug-em" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.enablement=null,org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.image=null,org.eclipse.cdt.docker.launcher.containerbuild.property.connection=null" parent="org.eclipse.cdt.build.core.emptycfg">
|
<configuration artifactName="${ProjName}" buildProperties="" description="" errorParsers="org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.GLDErrorParser;org.eclipse.cdt.core.CWDLocator;org.eclipse.cdt.core.GCCErrorParser" id="cdt.managedbuild.toolchain.gnu.mingw.base.1455833186.1840876443.2117915473.688890851.1707795689.1171630561" name="eive-q7s-debug-em" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.enablement=null,org.eclipse.cdt.docker.launcher.containerbuild.property.dockerdpath=,org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.connection=unix:///var/run/docker.sock,org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.image=null" parent="org.eclipse.cdt.build.core.emptycfg">
|
||||||
<folderInfo id="cdt.managedbuild.toolchain.gnu.mingw.base.1455833186.1840876443.2117915473.688890851.1707795689.1171630561." name="/" resourcePath="">
|
<folderInfo id="cdt.managedbuild.toolchain.gnu.mingw.base.1455833186.1840876443.2117915473.688890851.1707795689.1171630561." name="/" resourcePath="">
|
||||||
<toolChain id="ilg.gnuarmeclipse.managedbuild.cross.toolchain.base.1640701365" name="Arm Cross GCC" superClass="ilg.gnuarmeclipse.managedbuild.cross.toolchain.base">
|
<toolChain id="ilg.gnuarmeclipse.managedbuild.cross.toolchain.base.1640701365" name="Arm Cross GCC" superClass="ilg.gnuarmeclipse.managedbuild.cross.toolchain.base">
|
||||||
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.architecture.564607779" name="Architecture" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.architecture" value="ilg.gnuarmeclipse.managedbuild.cross.option.architecture.arm" valueType="enumerated"/>
|
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.architecture.564607779" name="Architecture" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.architecture" value="ilg.gnuarmeclipse.managedbuild.cross.option.architecture.arm" valueType="enumerated"/>
|
||||||
@ -1317,7 +1327,9 @@
|
|||||||
</toolChain>
|
</toolChain>
|
||||||
</folderInfo>
|
</folderInfo>
|
||||||
<sourceEntries>
|
<sourceEntries>
|
||||||
<entry excluding="cmake-build-debug-q7s|cmake-build-release-q7s-em|build-Debug-RPi|bsp_hosted|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|cmake-build-debug|build-Debug-Host|build-Watchdog-Debug" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
<entry excluding="unittest/rebootLogic|thirdparty/json|cmake-build-debug-q7s-em/_deps/etl-src|cmake-build-debug-q7s|cmake-build-release-q7s-em|build-Debug-RPi|bsp_hosted|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|cmake-build-debug|build-Debug-Host|build-Watchdog-Debug" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||||
|
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="cmake-build-debug-q7s-em/_deps/etl-src/include"/>
|
||||||
|
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="thirdparty/json/include"/>
|
||||||
</sourceEntries>
|
</sourceEntries>
|
||||||
</configuration>
|
</configuration>
|
||||||
</storageModule>
|
</storageModule>
|
||||||
@ -1386,7 +1398,8 @@
|
|||||||
</toolChain>
|
</toolChain>
|
||||||
</folderInfo>
|
</folderInfo>
|
||||||
<sourceEntries>
|
<sourceEntries>
|
||||||
<entry excluding="cmake-build-debug/_deps/etl-src/uml|cmake-build-debug/_deps/etl-src/test|cmake-build-debug/_deps/etl-src/temp|cmake-build-debug/_deps/etl-src/support|cmake-build-debug/_deps/etl-src/subprojects|cmake-build-debug/_deps/etl-src/scripts|cmake-build-debug/_deps/etl-src/images|cmake-build-debug/_deps/etl-src/examples|cmake-build-debug/_deps/etl-src/cmake|cmake-build-debug/_deps/etl-src/arduino|cmake-build-release-q7s-em|build-Debug-RPi|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|fsfwconfig" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
<entry excluding="unittest/rebootLogic|thirdparty/json|cmake-build-debug-q7s-em/_deps/etl-src|cmake-build-debug/_deps/etl-src/uml|cmake-build-debug/_deps/etl-src/test|cmake-build-debug/_deps/etl-src/temp|cmake-build-debug/_deps/etl-src/support|cmake-build-debug/_deps/etl-src/subprojects|cmake-build-debug/_deps/etl-src/scripts|cmake-build-debug/_deps/etl-src/images|cmake-build-debug/_deps/etl-src/examples|cmake-build-debug/_deps/etl-src/cmake|cmake-build-debug/_deps/etl-src/arduino|cmake-build-release-q7s-em|build-Debug-RPi|bsp_linux_board|cmake-build-debug-q7s/_deps/etl-src/uml|cmake-build-debug-q7s/_deps/etl-src/temp|cmake-build-debug-q7s/_deps/etl-src/support|cmake-build-debug-q7s/_deps/etl-src/subprojects|cmake-build-debug-q7s/_deps/etl-src/scripts|cmake-build-debug-q7s/_deps/etl-src/images|cmake-build-debug-q7s/_deps/etl-src/examples|cmake-build-debug-q7s/_deps/etl-src/cmake|cmake-build-debug-q7s/_deps/etl-src/arduino|tmtc|scripts|bsp_te0720_1cfa|thirdparty/rapidcsv/tests|thirdparty/rapidcsv/examples|thirdparty/rapidcsv/doc|thirdparty/json/third_party|thirdparty/json/test|thirdparty/json/single_include|thirdparty/json/doc|thirdparty/json/cmake|thirdparty/json/benchmarks|archive|cmake-build-release-q7s|bsp_egse|cmake-build-debug-q7s/_deps/etl-src/test|fsfwconfig" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||||
|
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="thirdparty/json/include"/>
|
||||||
</sourceEntries>
|
</sourceEntries>
|
||||||
</configuration>
|
</configuration>
|
||||||
</storageModule>
|
</storageModule>
|
||||||
|
@ -30,6 +30,7 @@ void SusHandler::doStartUp() {
|
|||||||
void SusHandler::doShutDown() {
|
void SusHandler::doShutDown() {
|
||||||
if (internalState != InternalState::SHUTDOWN) {
|
if (internalState != InternalState::SHUTDOWN) {
|
||||||
PoolReadGuard pg(&dataset);
|
PoolReadGuard pg(&dataset);
|
||||||
|
dataset.tempC = thermal::INVALID_TEMPERATURE;
|
||||||
dataset.setValidity(false, true);
|
dataset.setValidity(false, true);
|
||||||
internalState = InternalState::SHUTDOWN;
|
internalState = InternalState::SHUTDOWN;
|
||||||
commandExecuted = false;
|
commandExecuted = false;
|
||||||
|
@ -18,6 +18,7 @@ extern "C" {
|
|||||||
|
|
||||||
#include "OBSWConfig.h"
|
#include "OBSWConfig.h"
|
||||||
#include "eive/definitions.h"
|
#include "eive/definitions.h"
|
||||||
|
#include "fsfw/thermal/tcsDefinitions.h"
|
||||||
|
|
||||||
std::atomic_bool JCFG_DONE(false);
|
std::atomic_bool JCFG_DONE(false);
|
||||||
|
|
||||||
@ -106,11 +107,14 @@ void StarTrackerHandler::doShutDown() {
|
|||||||
solutionSet.caliQx.value = 0.0;
|
solutionSet.caliQx.value = 0.0;
|
||||||
solutionSet.caliQy.value = 0.0;
|
solutionSet.caliQy.value = 0.0;
|
||||||
solutionSet.caliQz.value = 0.0;
|
solutionSet.caliQz.value = 0.0;
|
||||||
solutionSet.isTrustWorthy = 0;
|
solutionSet.isTrustWorthy.value = 0;
|
||||||
solutionSet.setValidity(false, true);
|
solutionSet.setValidity(false, true);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
PoolReadGuard pg(&temperatureSet);
|
PoolReadGuard pg(&temperatureSet);
|
||||||
|
temperatureSet.fpgaTemperature = thermal::INVALID_TEMPERATURE;
|
||||||
|
temperatureSet.cmosTemperature = thermal::INVALID_TEMPERATURE;
|
||||||
|
temperatureSet.mcuTemperature = thermal::INVALID_TEMPERATURE;
|
||||||
temperatureSet.setValidity(false, true);
|
temperatureSet.setValidity(false, true);
|
||||||
}
|
}
|
||||||
reinitNextSetParam = false;
|
reinitNextSetParam = false;
|
||||||
|
@ -93,7 +93,8 @@ ReturnValue_t CfdpHandler::handleCfdpPacket(TmTcMessage& msg) {
|
|||||||
return INVALID_PDU_FORMAT;
|
return INVALID_PDU_FORMAT;
|
||||||
}
|
}
|
||||||
if (not FileDirectiveReader::checkFileDirective(pduDataField[0])) {
|
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<int>(pduDataField[0])
|
||||||
|
<< std::endl;
|
||||||
return INVALID_DIRECTIVE_FIELD;
|
return INVALID_DIRECTIVE_FIELD;
|
||||||
}
|
}
|
||||||
auto directive = static_cast<FileDirective>(pduDataField[0]);
|
auto directive = static_cast<FileDirective>(pduDataField[0]);
|
||||||
|
@ -246,7 +246,13 @@ ReturnValue_t CcsdsIpCoreHandler::checkModeCommand(Mode_t mode, Submode_t submod
|
|||||||
void CcsdsIpCoreHandler::startTransition(Mode_t mode, Submode_t submode) {
|
void CcsdsIpCoreHandler::startTransition(Mode_t mode, Submode_t submode) {
|
||||||
triggerEvent(CHANGING_MODE, mode, submode);
|
triggerEvent(CHANGING_MODE, mode, submode);
|
||||||
if (mode == HasModesIF::MODE_ON) {
|
if (mode == HasModesIF::MODE_ON) {
|
||||||
if (this->submode != submode) {
|
uint32_t currentRate = ptmeConfig.getRate();
|
||||||
|
// Check whether the rate actually changes.
|
||||||
|
if ((this->submode != submode) and
|
||||||
|
(((submode == static_cast<Submode_t>(com::CcsdsSubmode::DATARATE_LOW) and
|
||||||
|
(currentRate != RATE_100KBPS))) or
|
||||||
|
((submode == static_cast<Submode_t>(com::CcsdsSubmode::DATARATE_HIGH) and
|
||||||
|
(currentRate != RATE_500KBPS))))) {
|
||||||
initPtmeUpdateAfterXCycles();
|
initPtmeUpdateAfterXCycles();
|
||||||
updateContext.enableTransmitAfterPtmeUpdate = true;
|
updateContext.enableTransmitAfterPtmeUpdate = true;
|
||||||
updateContext.updateClockRate = true;
|
updateContext.updateClockRate = true;
|
||||||
|
@ -19,13 +19,8 @@ LiveTmTask::LiveTmTask(object_id_t objectId, PusTmFunnel& pusFunnel, CfdpTmFunne
|
|||||||
ReturnValue_t LiveTmTask::performOperation(uint8_t opCode) {
|
ReturnValue_t LiveTmTask::performOperation(uint8_t opCode) {
|
||||||
readCommandQueue();
|
readCommandQueue();
|
||||||
while (true) {
|
while (true) {
|
||||||
bool performWriteOp = true;
|
|
||||||
if (mode == MODE_OFF or ptmeLocked) {
|
|
||||||
performWriteOp = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The funnel tasks are scheduled here directly as well.
|
// 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) {
|
if (result == DirectTmSinkIF::IS_BUSY) {
|
||||||
sif::error << "Lost live TM, PAPB busy" << std::endl;
|
sif::error << "Lost live TM, PAPB busy" << std::endl;
|
||||||
}
|
}
|
||||||
|
@ -773,11 +773,13 @@ void SyrlinksHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) {
|
|||||||
auto txStandbyHandler = [&]() {
|
auto txStandbyHandler = [&]() {
|
||||||
txDataset.setReportingEnabled(false);
|
txDataset.setReportingEnabled(false);
|
||||||
poolManager.changeCollectionInterval(temperatureSet.getSid(), 60.0);
|
poolManager.changeCollectionInterval(temperatureSet.getSid(), 60.0);
|
||||||
|
poolManager.changeCollectionInterval(rxDataset.getSid(), 60.0);
|
||||||
transState = TransitionState::SET_TX_STANDBY;
|
transState = TransitionState::SET_TX_STANDBY;
|
||||||
internalState = InternalState::TX_TRANSITION;
|
internalState = InternalState::TX_TRANSITION;
|
||||||
};
|
};
|
||||||
auto txOnHandler = [&](TransitionState tgtTransitionState) {
|
auto txOnHandler = [&](TransitionState tgtTransitionState) {
|
||||||
txDataset.setReportingEnabled(true);
|
txDataset.setReportingEnabled(true);
|
||||||
|
poolManager.changeCollectionInterval(rxDataset.getSid(), 5.0);
|
||||||
poolManager.changeCollectionInterval(txDataset.getSid(), 10.0);
|
poolManager.changeCollectionInterval(txDataset.getSid(), 10.0);
|
||||||
poolManager.changeCollectionInterval(temperatureSet.getSid(), 5.0);
|
poolManager.changeCollectionInterval(temperatureSet.getSid(), 5.0);
|
||||||
transState = tgtTransitionState;
|
transState = tgtTransitionState;
|
||||||
|
@ -45,13 +45,19 @@ bool TmStoreTaskBase::handleOneStore(PersistentTmStoreWithTmQueue& store,
|
|||||||
} else {
|
} else {
|
||||||
Command_t execCmd;
|
Command_t execCmd;
|
||||||
// Handle TC requests, for example deletion or retrieval requests.
|
// 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);
|
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();
|
cancelDumpCd.resetTimer();
|
||||||
tmSinkBusyCd.resetTimer();
|
tmSinkBusyCd.resetTimer();
|
||||||
dumpContext.reset();
|
dumpContext.reset();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (execCmd != CommandMessageIF::CMD_NONE) {
|
||||||
tcRequestReceived = true;
|
tcRequestReceived = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -119,21 +125,13 @@ ReturnValue_t TmStoreTaskBase::performDump(PersistentTmStoreWithTmQueue& store,
|
|||||||
DumpContext& dumpContext, bool& dumpPerformed) {
|
DumpContext& dumpContext, bool& dumpPerformed) {
|
||||||
size_t dumpedLen = 0;
|
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.
|
// Dump the next packet into the PTME.
|
||||||
dumpContext.ptmeBusyCounter = 0;
|
dumpContext.ptmeBusyCounter = 0;
|
||||||
tmSinkBusyCd.resetTimer();
|
tmSinkBusyCd.resetTimer();
|
||||||
ReturnValue_t result = store.getNextDumpPacket(tmReader, fileHasSwapped);
|
ReturnValue_t result = store.getNextDumpPacket(tmReader, fileHasSwapped);
|
||||||
if (fileHasSwapped and result == PersistentTmStore::DUMP_DONE) {
|
if (fileHasSwapped and result == PersistentTmStore::DUMP_DONE) {
|
||||||
// This can happen if a file is corrupted and the next file swap completes the dump.
|
// This can happen if a file is corrupted and the next file swap completes the dump.
|
||||||
dumpDoneHandler();
|
dumpDoneHandler(store, dumpContext);
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
} else if (result != returnvalue::OK) {
|
} else if (result != returnvalue::OK) {
|
||||||
sif::error << "PersistentTmStore: Getting next dump packet failed" << std::endl;
|
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) {
|
if (result == PersistentTmStore::DUMP_DONE) {
|
||||||
dumpDoneHandler();
|
dumpDoneHandler(store, dumpContext);
|
||||||
}
|
}
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
@ -198,6 +196,14 @@ ReturnValue_t TmStoreTaskBase::connectModeTreeParent(HasModeTreeChildrenIF& pare
|
|||||||
return modetree::connectModeTreeParent(parent, *this, nullptr, modeHelper);
|
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; }
|
ModeTreeChildIF& TmStoreTaskBase::getModeTreeChildIF() { return *this; }
|
||||||
|
|
||||||
void TmStoreTaskBase::readCommandQueue(void) {
|
void TmStoreTaskBase::readCommandQueue(void) {
|
||||||
|
@ -96,6 +96,8 @@ class TmStoreTaskBase : public SystemObject,
|
|||||||
|
|
||||||
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||||
uint32_t* msToReachTheMode) override;
|
uint32_t* msToReachTheMode) override;
|
||||||
|
void dumpDoneHandler(PersistentTmStore& store, DumpContext& dumpContext);
|
||||||
|
|
||||||
void announceMode(bool recursive) override;
|
void announceMode(bool recursive) override;
|
||||||
object_id_t getObjectId() const override;
|
object_id_t getObjectId() const override;
|
||||||
const HasHealthIF* getOptHealthIF() const override;
|
const HasHealthIF* getOptHealthIF() const override;
|
||||||
|
@ -221,6 +221,9 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId,
|
|||||||
case 0x23:
|
case 0x23:
|
||||||
parameterWrapper->setMatrix(susHandlingParameters.sus11coeffBeta);
|
parameterWrapper->setMatrix(susHandlingParameters.sus11coeffBeta);
|
||||||
break;
|
break;
|
||||||
|
case 0x24:
|
||||||
|
parameterWrapper->set(susHandlingParameters.susBrightnessThreshold);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return INVALID_IDENTIFIER_ID;
|
return INVALID_IDENTIFIER_ID;
|
||||||
}
|
}
|
||||||
|
@ -766,6 +766,7 @@ class AcsParameters : public HasParametersIF {
|
|||||||
{116.975421945286, -5.53022680362263, -5.61081660666997, 0.109754904982136,
|
{116.975421945286, -5.53022680362263, -5.61081660666997, 0.109754904982136,
|
||||||
0.167666815691513, 0.163137400730063, -0.000609874123906977, -0.00205336098697513,
|
0.167666815691513, 0.163137400730063, -0.000609874123906977, -0.00205336098697513,
|
||||||
-0.000889232196185857, -0.00168429567131815}};
|
-0.000889232196185857, -0.00168429567131815}};
|
||||||
|
float susBrightnessThreshold = 0.7;
|
||||||
} susHandlingParameters;
|
} susHandlingParameters;
|
||||||
|
|
||||||
struct GyrHandlingParameters {
|
struct GyrHandlingParameters {
|
||||||
|
@ -206,45 +206,51 @@ void SensorProcessing::processSus(
|
|||||||
sunIjkModel[0] = cos(eclipticLongitude);
|
sunIjkModel[0] = cos(eclipticLongitude);
|
||||||
sunIjkModel[1] = sin(eclipticLongitude) * cos(epsilon);
|
sunIjkModel[1] = sin(eclipticLongitude) * cos(epsilon);
|
||||||
sunIjkModel[2] = sin(eclipticLongitude) * sin(epsilon);
|
sunIjkModel[2] = sin(eclipticLongitude) * sin(epsilon);
|
||||||
|
|
||||||
|
uint64_t susBrightness[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
if (sus0valid) {
|
if (sus0valid) {
|
||||||
sus0valid = susConverter.checkSunSensorData(sus0Value);
|
susBrightness[0] = susConverter.checkSunSensorData(sus0Value);
|
||||||
}
|
}
|
||||||
if (sus1valid) {
|
if (sus1valid) {
|
||||||
sus1valid = susConverter.checkSunSensorData(sus1Value);
|
susBrightness[1] = susConverter.checkSunSensorData(sus1Value);
|
||||||
}
|
}
|
||||||
if (sus2valid) {
|
if (sus2valid) {
|
||||||
sus2valid = susConverter.checkSunSensorData(sus2Value);
|
susBrightness[2] = susConverter.checkSunSensorData(sus2Value);
|
||||||
}
|
}
|
||||||
if (sus3valid) {
|
if (sus3valid) {
|
||||||
sus3valid = susConverter.checkSunSensorData(sus3Value);
|
susBrightness[3] = susConverter.checkSunSensorData(sus3Value);
|
||||||
}
|
}
|
||||||
if (sus4valid) {
|
if (sus4valid) {
|
||||||
sus4valid = susConverter.checkSunSensorData(sus4Value);
|
susBrightness[4] = susConverter.checkSunSensorData(sus4Value);
|
||||||
}
|
}
|
||||||
if (sus5valid) {
|
if (sus5valid) {
|
||||||
sus5valid = susConverter.checkSunSensorData(sus5Value);
|
susBrightness[5] = susConverter.checkSunSensorData(sus5Value);
|
||||||
}
|
}
|
||||||
if (sus6valid) {
|
if (sus6valid) {
|
||||||
sus6valid = susConverter.checkSunSensorData(sus6Value);
|
susBrightness[6] = susConverter.checkSunSensorData(sus6Value);
|
||||||
}
|
}
|
||||||
if (sus7valid) {
|
if (sus7valid) {
|
||||||
sus7valid = susConverter.checkSunSensorData(sus7Value);
|
susBrightness[7] = susConverter.checkSunSensorData(sus7Value);
|
||||||
}
|
}
|
||||||
if (sus8valid) {
|
if (sus8valid) {
|
||||||
sus8valid = susConverter.checkSunSensorData(sus8Value);
|
susBrightness[8] = susConverter.checkSunSensorData(sus8Value);
|
||||||
}
|
}
|
||||||
if (sus9valid) {
|
if (sus9valid) {
|
||||||
sus9valid = susConverter.checkSunSensorData(sus9Value);
|
susBrightness[9] = susConverter.checkSunSensorData(sus9Value);
|
||||||
}
|
}
|
||||||
if (sus10valid) {
|
if (sus10valid) {
|
||||||
sus10valid = susConverter.checkSunSensorData(sus10Value);
|
susBrightness[10] = susConverter.checkSunSensorData(sus10Value);
|
||||||
}
|
}
|
||||||
if (sus11valid) {
|
if (sus11valid) {
|
||||||
sus11valid = susConverter.checkSunSensorData(sus11Value);
|
susBrightness[11] = susConverter.checkSunSensorData(sus11Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sus0valid && !sus1valid && !sus2valid && !sus3valid && !sus4valid && !sus5valid &&
|
bool susValid[12] = {sus0valid, sus1valid, sus2valid, sus3valid, sus4valid, sus5valid,
|
||||||
!sus6valid && !sus7valid && !sus8valid && !sus9valid && !sus10valid && !sus11valid) {
|
sus6valid, sus7valid, sus8valid, sus9valid, sus10valid, sus11valid};
|
||||||
|
bool allInvalid =
|
||||||
|
susConverter.checkValidity(susValid, susBrightness, susParameters->susBrightnessThreshold);
|
||||||
|
|
||||||
|
if (allInvalid) {
|
||||||
{
|
{
|
||||||
PoolReadGuard pg(susDataProcessed);
|
PoolReadGuard pg(susDataProcessed);
|
||||||
if (pg.getReadResult() == returnvalue::OK) {
|
if (pg.getReadResult() == returnvalue::OK) {
|
||||||
@ -269,117 +275,78 @@ void SensorProcessing::processSus(
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Transformation into Geomtry Frame
|
|
||||||
float sus0VecBody[3] = {0, 0, 0}, sus1VecBody[3] = {0, 0, 0}, sus2VecBody[3] = {0, 0, 0},
|
|
||||||
sus3VecBody[3] = {0, 0, 0}, sus4VecBody[3] = {0, 0, 0}, sus5VecBody[3] = {0, 0, 0},
|
|
||||||
sus6VecBody[3] = {0, 0, 0}, sus7VecBody[3] = {0, 0, 0}, sus8VecBody[3] = {0, 0, 0},
|
|
||||||
sus9VecBody[3] = {0, 0, 0}, sus10VecBody[3] = {0, 0, 0}, sus11VecBody[3] = {0, 0, 0};
|
|
||||||
|
|
||||||
if (sus0valid) {
|
float susVecSensor[12][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
|
||||||
MatrixOperations<float>::multiply(
|
{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||||
susParameters->sus0orientationMatrix[0],
|
float susVecBody[12][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
|
||||||
susConverter.getSunVectorSensorFrame(sus0Value, susParameters->sus0coeffAlpha,
|
{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
|
||||||
susParameters->sus0coeffBeta),
|
|
||||||
sus0VecBody, 3, 3, 1);
|
|
||||||
}
|
|
||||||
if (sus1valid) {
|
|
||||||
MatrixOperations<float>::multiply(
|
|
||||||
susParameters->sus1orientationMatrix[0],
|
|
||||||
susConverter.getSunVectorSensorFrame(sus1Value, susParameters->sus1coeffAlpha,
|
|
||||||
susParameters->sus1coeffBeta),
|
|
||||||
sus1VecBody, 3, 3, 1);
|
|
||||||
}
|
|
||||||
if (sus2valid) {
|
|
||||||
MatrixOperations<float>::multiply(
|
|
||||||
susParameters->sus2orientationMatrix[0],
|
|
||||||
susConverter.getSunVectorSensorFrame(sus2Value, susParameters->sus2coeffAlpha,
|
|
||||||
susParameters->sus2coeffBeta),
|
|
||||||
sus2VecBody, 3, 3, 1);
|
|
||||||
}
|
|
||||||
if (sus3valid) {
|
|
||||||
MatrixOperations<float>::multiply(
|
|
||||||
susParameters->sus3orientationMatrix[0],
|
|
||||||
susConverter.getSunVectorSensorFrame(sus3Value, susParameters->sus3coeffAlpha,
|
|
||||||
susParameters->sus3coeffBeta),
|
|
||||||
sus3VecBody, 3, 3, 1);
|
|
||||||
}
|
|
||||||
if (sus4valid) {
|
|
||||||
MatrixOperations<float>::multiply(
|
|
||||||
susParameters->sus4orientationMatrix[0],
|
|
||||||
susConverter.getSunVectorSensorFrame(sus4Value, susParameters->sus4coeffAlpha,
|
|
||||||
susParameters->sus4coeffBeta),
|
|
||||||
sus4VecBody, 3, 3, 1);
|
|
||||||
}
|
|
||||||
if (sus5valid) {
|
|
||||||
MatrixOperations<float>::multiply(
|
|
||||||
susParameters->sus5orientationMatrix[0],
|
|
||||||
susConverter.getSunVectorSensorFrame(sus5Value, susParameters->sus5coeffAlpha,
|
|
||||||
susParameters->sus5coeffBeta),
|
|
||||||
sus5VecBody, 3, 3, 1);
|
|
||||||
}
|
|
||||||
if (sus6valid) {
|
|
||||||
MatrixOperations<float>::multiply(
|
|
||||||
susParameters->sus6orientationMatrix[0],
|
|
||||||
susConverter.getSunVectorSensorFrame(sus6Value, susParameters->sus6coeffAlpha,
|
|
||||||
susParameters->sus6coeffBeta),
|
|
||||||
sus6VecBody, 3, 3, 1);
|
|
||||||
}
|
|
||||||
if (sus7valid) {
|
|
||||||
MatrixOperations<float>::multiply(
|
|
||||||
susParameters->sus7orientationMatrix[0],
|
|
||||||
susConverter.getSunVectorSensorFrame(sus7Value, susParameters->sus7coeffAlpha,
|
|
||||||
susParameters->sus7coeffBeta),
|
|
||||||
sus7VecBody, 3, 3, 1);
|
|
||||||
}
|
|
||||||
if (sus8valid) {
|
|
||||||
MatrixOperations<float>::multiply(
|
|
||||||
susParameters->sus8orientationMatrix[0],
|
|
||||||
susConverter.getSunVectorSensorFrame(sus8Value, susParameters->sus8coeffAlpha,
|
|
||||||
susParameters->sus8coeffBeta),
|
|
||||||
sus8VecBody, 3, 3, 1);
|
|
||||||
}
|
|
||||||
if (sus9valid) {
|
|
||||||
MatrixOperations<float>::multiply(
|
|
||||||
susParameters->sus9orientationMatrix[0],
|
|
||||||
susConverter.getSunVectorSensorFrame(sus9Value, susParameters->sus9coeffAlpha,
|
|
||||||
susParameters->sus9coeffBeta),
|
|
||||||
sus9VecBody, 3, 3, 1);
|
|
||||||
}
|
|
||||||
if (sus10valid) {
|
|
||||||
MatrixOperations<float>::multiply(
|
|
||||||
susParameters->sus10orientationMatrix[0],
|
|
||||||
susConverter.getSunVectorSensorFrame(sus10Value, susParameters->sus10coeffAlpha,
|
|
||||||
susParameters->sus10coeffBeta),
|
|
||||||
sus10VecBody, 3, 3, 1);
|
|
||||||
}
|
|
||||||
if (sus11valid) {
|
|
||||||
MatrixOperations<float>::multiply(
|
|
||||||
susParameters->sus11orientationMatrix[0],
|
|
||||||
susConverter.getSunVectorSensorFrame(sus11Value, susParameters->sus11coeffAlpha,
|
|
||||||
susParameters->sus11coeffBeta),
|
|
||||||
sus11VecBody, 3, 3, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------ Mean Value: susDirEst ------ */
|
if (susValid[0]) {
|
||||||
bool validIds[12] = {sus0valid, sus1valid, sus2valid, sus3valid, sus4valid, sus5valid,
|
susConverter.calculateSunVector(susVecSensor[0], sus0Value);
|
||||||
sus6valid, sus7valid, sus8valid, sus9valid, sus10valid, sus11valid};
|
MatrixOperations<float>::multiply(susParameters->sus0orientationMatrix[0], susVecSensor[0],
|
||||||
float susVecBody[3][12] = {{sus0VecBody[0], sus1VecBody[0], sus2VecBody[0], sus3VecBody[0],
|
susVecBody[0], 3, 3, 1);
|
||||||
sus4VecBody[0], sus5VecBody[0], sus6VecBody[0], sus7VecBody[0],
|
}
|
||||||
sus8VecBody[0], sus9VecBody[0], sus10VecBody[0], sus11VecBody[0]},
|
if (susValid[1]) {
|
||||||
{sus0VecBody[1], sus1VecBody[1], sus2VecBody[1], sus3VecBody[1],
|
susConverter.calculateSunVector(susVecSensor[1], sus1Value);
|
||||||
sus4VecBody[1], sus5VecBody[1], sus6VecBody[1], sus7VecBody[1],
|
MatrixOperations<float>::multiply(susParameters->sus1orientationMatrix[0], susVecSensor[1],
|
||||||
sus8VecBody[1], sus9VecBody[1], sus10VecBody[1], sus11VecBody[1]},
|
susVecBody[1], 3, 3, 1);
|
||||||
{sus0VecBody[2], sus1VecBody[2], sus2VecBody[2], sus3VecBody[2],
|
}
|
||||||
sus4VecBody[2], sus5VecBody[2], sus6VecBody[2], sus7VecBody[2],
|
if (susValid[2]) {
|
||||||
sus8VecBody[2], sus9VecBody[2], sus10VecBody[2], sus11VecBody[2]}};
|
susConverter.calculateSunVector(susVecSensor[2], sus2Value);
|
||||||
|
MatrixOperations<float>::multiply(susParameters->sus2orientationMatrix[0], susVecSensor[2],
|
||||||
|
susVecBody[2], 3, 3, 1);
|
||||||
|
}
|
||||||
|
if (susValid[3]) {
|
||||||
|
susConverter.calculateSunVector(susVecSensor[3], sus3Value);
|
||||||
|
MatrixOperations<float>::multiply(susParameters->sus3orientationMatrix[0], susVecSensor[3],
|
||||||
|
susVecBody[3], 3, 3, 1);
|
||||||
|
}
|
||||||
|
if (susValid[4]) {
|
||||||
|
susConverter.calculateSunVector(susVecSensor[4], sus4Value);
|
||||||
|
MatrixOperations<float>::multiply(susParameters->sus4orientationMatrix[0], susVecSensor[4],
|
||||||
|
susVecBody[4], 3, 3, 1);
|
||||||
|
}
|
||||||
|
if (susValid[5]) {
|
||||||
|
susConverter.calculateSunVector(susVecSensor[5], sus5Value);
|
||||||
|
MatrixOperations<float>::multiply(susParameters->sus5orientationMatrix[0], susVecSensor[5],
|
||||||
|
susVecBody[5], 3, 3, 1);
|
||||||
|
}
|
||||||
|
if (susValid[6]) {
|
||||||
|
susConverter.calculateSunVector(susVecSensor[6], sus6Value);
|
||||||
|
MatrixOperations<float>::multiply(susParameters->sus6orientationMatrix[0], susVecSensor[6],
|
||||||
|
susVecBody[6], 3, 3, 1);
|
||||||
|
}
|
||||||
|
if (susValid[7]) {
|
||||||
|
susConverter.calculateSunVector(susVecSensor[7], sus7Value);
|
||||||
|
MatrixOperations<float>::multiply(susParameters->sus7orientationMatrix[0], susVecSensor[7],
|
||||||
|
susVecBody[7], 3, 3, 1);
|
||||||
|
}
|
||||||
|
if (susValid[8]) {
|
||||||
|
susConverter.calculateSunVector(susVecSensor[8], sus8Value);
|
||||||
|
MatrixOperations<float>::multiply(susParameters->sus8orientationMatrix[0], susVecSensor[8],
|
||||||
|
susVecBody[8], 3, 3, 1);
|
||||||
|
}
|
||||||
|
if (susValid[9]) {
|
||||||
|
susConverter.calculateSunVector(susVecSensor[9], sus9Value);
|
||||||
|
MatrixOperations<float>::multiply(susParameters->sus9orientationMatrix[0], susVecSensor[9],
|
||||||
|
susVecBody[9], 3, 3, 1);
|
||||||
|
}
|
||||||
|
if (susValid[10]) {
|
||||||
|
susConverter.calculateSunVector(susVecSensor[10], sus10Value);
|
||||||
|
MatrixOperations<float>::multiply(susParameters->sus10orientationMatrix[0], susVecSensor[10],
|
||||||
|
susVecBody[10], 3, 3, 1);
|
||||||
|
}
|
||||||
|
if (susValid[11]) {
|
||||||
|
susConverter.calculateSunVector(susVecSensor[11], sus11Value);
|
||||||
|
MatrixOperations<float>::multiply(susParameters->sus11orientationMatrix[0], susVecSensor[11],
|
||||||
|
susVecBody[11], 3, 3, 1);
|
||||||
|
}
|
||||||
|
|
||||||
double susMeanValue[3] = {0, 0, 0};
|
double susMeanValue[3] = {0, 0, 0};
|
||||||
for (uint8_t i = 0; i < 12; i++) {
|
for (uint8_t i = 0; i < 12; i++) {
|
||||||
if (validIds[i]) {
|
susMeanValue[0] += susVecBody[i][0];
|
||||||
susMeanValue[0] += susVecBody[0][i];
|
susMeanValue[1] += susVecBody[i][1];
|
||||||
susMeanValue[1] += susVecBody[1][i];
|
susMeanValue[2] += susVecBody[i][2];
|
||||||
susMeanValue[2] += susVecBody[2][i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
double susVecTot[3] = {0.0, 0.0, 0.0};
|
double susVecTot[3] = {0.0, 0.0, 0.0};
|
||||||
VectorOperations<double>::normalize(susMeanValue, susVecTot, 3);
|
VectorOperations<double>::normalize(susMeanValue, susVecTot, 3);
|
||||||
@ -400,29 +367,29 @@ void SensorProcessing::processSus(
|
|||||||
{
|
{
|
||||||
PoolReadGuard pg(susDataProcessed);
|
PoolReadGuard pg(susDataProcessed);
|
||||||
if (pg.getReadResult() == returnvalue::OK) {
|
if (pg.getReadResult() == returnvalue::OK) {
|
||||||
std::memcpy(susDataProcessed->sus0vec.value, sus0VecBody, 3 * sizeof(float));
|
std::memcpy(susDataProcessed->sus0vec.value, susVecBody[0], 3 * sizeof(float));
|
||||||
susDataProcessed->sus0vec.setValid(sus0valid);
|
susDataProcessed->sus0vec.setValid(sus0valid);
|
||||||
std::memcpy(susDataProcessed->sus1vec.value, sus1VecBody, 3 * sizeof(float));
|
std::memcpy(susDataProcessed->sus1vec.value, susVecBody[1], 3 * sizeof(float));
|
||||||
susDataProcessed->sus1vec.setValid(sus1valid);
|
susDataProcessed->sus1vec.setValid(sus1valid);
|
||||||
std::memcpy(susDataProcessed->sus2vec.value, sus2VecBody, 3 * sizeof(float));
|
std::memcpy(susDataProcessed->sus2vec.value, susVecBody[2], 3 * sizeof(float));
|
||||||
susDataProcessed->sus2vec.setValid(sus2valid);
|
susDataProcessed->sus2vec.setValid(sus2valid);
|
||||||
std::memcpy(susDataProcessed->sus3vec.value, sus3VecBody, 3 * sizeof(float));
|
std::memcpy(susDataProcessed->sus3vec.value, susVecBody[3], 3 * sizeof(float));
|
||||||
susDataProcessed->sus3vec.setValid(sus3valid);
|
susDataProcessed->sus3vec.setValid(sus3valid);
|
||||||
std::memcpy(susDataProcessed->sus4vec.value, sus4VecBody, 3 * sizeof(float));
|
std::memcpy(susDataProcessed->sus4vec.value, susVecBody[4], 3 * sizeof(float));
|
||||||
susDataProcessed->sus4vec.setValid(sus4valid);
|
susDataProcessed->sus4vec.setValid(sus4valid);
|
||||||
std::memcpy(susDataProcessed->sus5vec.value, sus5VecBody, 3 * sizeof(float));
|
std::memcpy(susDataProcessed->sus5vec.value, susVecBody[5], 3 * sizeof(float));
|
||||||
susDataProcessed->sus5vec.setValid(sus5valid);
|
susDataProcessed->sus5vec.setValid(sus5valid);
|
||||||
std::memcpy(susDataProcessed->sus6vec.value, sus6VecBody, 3 * sizeof(float));
|
std::memcpy(susDataProcessed->sus6vec.value, susVecBody[6], 3 * sizeof(float));
|
||||||
susDataProcessed->sus6vec.setValid(sus6valid);
|
susDataProcessed->sus6vec.setValid(sus6valid);
|
||||||
std::memcpy(susDataProcessed->sus7vec.value, sus7VecBody, 3 * sizeof(float));
|
std::memcpy(susDataProcessed->sus7vec.value, susVecBody[7], 3 * sizeof(float));
|
||||||
susDataProcessed->sus7vec.setValid(sus7valid);
|
susDataProcessed->sus7vec.setValid(sus7valid);
|
||||||
std::memcpy(susDataProcessed->sus8vec.value, sus8VecBody, 3 * sizeof(float));
|
std::memcpy(susDataProcessed->sus8vec.value, susVecBody[8], 3 * sizeof(float));
|
||||||
susDataProcessed->sus8vec.setValid(sus8valid);
|
susDataProcessed->sus8vec.setValid(sus8valid);
|
||||||
std::memcpy(susDataProcessed->sus9vec.value, sus9VecBody, 3 * sizeof(float));
|
std::memcpy(susDataProcessed->sus9vec.value, susVecBody[9], 3 * sizeof(float));
|
||||||
susDataProcessed->sus9vec.setValid(sus9valid);
|
susDataProcessed->sus9vec.setValid(sus9valid);
|
||||||
std::memcpy(susDataProcessed->sus10vec.value, sus10VecBody, 3 * sizeof(float));
|
std::memcpy(susDataProcessed->sus10vec.value, susVecBody[10], 3 * sizeof(float));
|
||||||
susDataProcessed->sus10vec.setValid(sus10valid);
|
susDataProcessed->sus10vec.setValid(sus10valid);
|
||||||
std::memcpy(susDataProcessed->sus11vec.value, sus11VecBody, 3 * sizeof(float));
|
std::memcpy(susDataProcessed->sus11vec.value, susVecBody[11], 3 * sizeof(float));
|
||||||
susDataProcessed->sus11vec.setValid(sus11valid);
|
susDataProcessed->sus11vec.setValid(sus11valid);
|
||||||
std::memcpy(susDataProcessed->susVecTot.value, susVecTot, 3 * sizeof(double));
|
std::memcpy(susDataProcessed->susVecTot.value, susVecTot, 3 * sizeof(double));
|
||||||
susDataProcessed->susVecTot.setValid(true);
|
susDataProcessed->susVecTot.setValid(true);
|
||||||
|
@ -1,121 +1,64 @@
|
|||||||
#include "SusConverter.h"
|
#include "SusConverter.h"
|
||||||
|
|
||||||
#include <fsfw/datapoollocal/LocalPoolVariable.h>
|
|
||||||
#include <fsfw/datapoollocal/LocalPoolVector.h>
|
|
||||||
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include <iostream>
|
uint64_t SusConverter::checkSunSensorData(const uint16_t susChannel[6]) {
|
||||||
|
if (susChannel[0] <= SUS_CHANNEL_VALUE_LOW || susChannel[0] > SUS_CHANNEL_VALUE_HIGH ||
|
||||||
bool SusConverter::checkSunSensorData(const uint16_t susChannel[6]) {
|
|
||||||
if (susChannel[0] <= susChannelValueCheckLow || susChannel[0] > susChannelValueCheckHigh ||
|
|
||||||
susChannel[0] > susChannel[GNDREF]) {
|
susChannel[0] > susChannel[GNDREF]) {
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
if (susChannel[1] <= susChannelValueCheckLow || susChannel[1] > susChannelValueCheckHigh ||
|
if (susChannel[1] <= SUS_CHANNEL_VALUE_LOW || susChannel[1] > SUS_CHANNEL_VALUE_HIGH ||
|
||||||
susChannel[1] > susChannel[GNDREF]) {
|
susChannel[1] > susChannel[GNDREF]) {
|
||||||
return false;
|
return 0;
|
||||||
};
|
};
|
||||||
if (susChannel[2] <= susChannelValueCheckLow || susChannel[2] > susChannelValueCheckHigh ||
|
if (susChannel[2] <= SUS_CHANNEL_VALUE_LOW || susChannel[2] > SUS_CHANNEL_VALUE_HIGH ||
|
||||||
susChannel[2] > susChannel[GNDREF]) {
|
susChannel[2] > susChannel[GNDREF]) {
|
||||||
return false;
|
return 0;
|
||||||
};
|
};
|
||||||
if (susChannel[3] <= susChannelValueCheckLow || susChannel[3] > susChannelValueCheckHigh ||
|
if (susChannel[3] <= SUS_CHANNEL_VALUE_LOW || susChannel[3] > SUS_CHANNEL_VALUE_HIGH ||
|
||||||
susChannel[3] > susChannel[GNDREF]) {
|
susChannel[3] > susChannel[GNDREF]) {
|
||||||
return false;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
susChannelValueSum =
|
uint64_t susChannelValueSum =
|
||||||
4 * susChannel[GNDREF] - (susChannel[0] + susChannel[1] + susChannel[2] + susChannel[3]);
|
4 * susChannel[GNDREF] - (susChannel[0] + susChannel[1] + susChannel[2] + susChannel[3]);
|
||||||
if ((susChannelValueSum < susChannelValueSumHigh) &&
|
if (susChannelValueSum < SUS_ALBEDO_CHECK) {
|
||||||
(susChannelValueSum > susChannelValueSumLow)) {
|
return 0;
|
||||||
return false;
|
|
||||||
};
|
};
|
||||||
return true;
|
return susChannelValueSum;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SusConverter::calcAngle(const uint16_t susChannel[6]) {
|
bool SusConverter::checkValidity(bool* susValid, const uint64_t brightness[12],
|
||||||
float xout, yout;
|
const float threshold) {
|
||||||
float s = 0.03; // s=[mm] gap between diodes
|
uint8_t maxBrightness = 0;
|
||||||
uint8_t d = 5; // d=[mm] edge length of the quadratic aperture
|
VectorOperations<uint64_t>::maxValue(brightness, 12, &maxBrightness);
|
||||||
uint8_t h = 1; // h=[mm] distance between diodes and aperture
|
if (brightness[maxBrightness] == 0) {
|
||||||
int ch0, ch1, ch2, ch3;
|
return true;
|
||||||
|
}
|
||||||
|
for (uint8_t idx = 0; idx < 12; idx++) {
|
||||||
|
if ((idx != maxBrightness) and (brightness[idx] < threshold * brightness[maxBrightness])) {
|
||||||
|
susValid[idx] = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
susValid[idx] = true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SusConverter::calculateSunVector(float* sunVectorSensorFrame, const uint16_t susChannel[6]) {
|
||||||
// Substract measurement values from GNDREF zero current threshold
|
// Substract measurement values from GNDREF zero current threshold
|
||||||
ch0 = susChannel[GNDREF] - susChannel[0];
|
float ch0 = susChannel[GNDREF] - susChannel[0];
|
||||||
ch1 = susChannel[GNDREF] - susChannel[1];
|
float ch1 = susChannel[GNDREF] - susChannel[1];
|
||||||
ch2 = susChannel[GNDREF] - susChannel[2];
|
float ch2 = susChannel[GNDREF] - susChannel[2];
|
||||||
ch3 = susChannel[GNDREF] - susChannel[3];
|
float ch3 = susChannel[GNDREF] - susChannel[3];
|
||||||
|
|
||||||
// Calculation of x and y
|
// Calculation of x and y
|
||||||
xout = ((d - s) / 2) * (ch2 - ch3 - ch0 + ch1) / (ch0 + ch1 + ch2 + ch3); //[mm]
|
float xout = ((D - S) / 2) * (ch2 - ch3 - ch0 + ch1) / (ch0 + ch1 + ch2 + ch3); //[mm]
|
||||||
yout = ((d - s) / 2) * (ch2 + ch3 - ch0 - ch1) / (ch0 + ch1 + ch2 + ch3); //[mm]
|
float yout = ((D - S) / 2) * (ch2 + ch3 - ch0 - ch1) / (ch0 + ch1 + ch2 + ch3); //[mm]
|
||||||
|
|
||||||
// Calculation of the angles
|
// Calculation of the angles
|
||||||
alphaBetaRaw[0] = atan2(xout, h) * (180 / M_PI); //[°]
|
sunVectorSensorFrame[0] = -xout;
|
||||||
alphaBetaRaw[1] = atan2(yout, h) * (180 / M_PI); //[°]
|
sunVectorSensorFrame[1] = -yout;
|
||||||
}
|
sunVectorSensorFrame[2] = H;
|
||||||
|
VectorOperations<float>::normalize(sunVectorSensorFrame, sunVectorSensorFrame, 3);
|
||||||
void SusConverter::calibration(const float coeffAlpha[9][10], const float coeffBeta[9][10]) {
|
|
||||||
uint8_t index, k, l;
|
|
||||||
|
|
||||||
// while loop iterates above all calibration cells to use the different calibration functions in
|
|
||||||
// each cell
|
|
||||||
k = 0;
|
|
||||||
while (k < 3) {
|
|
||||||
k++;
|
|
||||||
l = 0;
|
|
||||||
while (l < 3) {
|
|
||||||
l++;
|
|
||||||
// if-condition to check in which cell the data point has to be
|
|
||||||
if ((alphaBetaRaw[0] > ((completeCellWidth * ((k - 1) / 3.)) - halfCellWidth) &&
|
|
||||||
alphaBetaRaw[0] < ((completeCellWidth * (k / 3.)) - halfCellWidth)) &&
|
|
||||||
(alphaBetaRaw[1] > ((completeCellWidth * ((l - 1) / 3.)) - halfCellWidth) &&
|
|
||||||
alphaBetaRaw[1] < ((completeCellWidth * (l / 3.)) - halfCellWidth))) {
|
|
||||||
index = (3 * (k - 1) + l) - 1; // calculate the index of the datapoint for the right cell
|
|
||||||
alphaBetaCalibrated[0] =
|
|
||||||
coeffAlpha[index][0] + coeffAlpha[index][1] * alphaBetaRaw[0] +
|
|
||||||
coeffAlpha[index][2] * alphaBetaRaw[1] +
|
|
||||||
coeffAlpha[index][3] * alphaBetaRaw[0] * alphaBetaRaw[0] +
|
|
||||||
coeffAlpha[index][4] * alphaBetaRaw[0] * alphaBetaRaw[1] +
|
|
||||||
coeffAlpha[index][5] * alphaBetaRaw[1] * alphaBetaRaw[1] +
|
|
||||||
coeffAlpha[index][6] * alphaBetaRaw[0] * alphaBetaRaw[0] * alphaBetaRaw[0] +
|
|
||||||
coeffAlpha[index][7] * alphaBetaRaw[0] * alphaBetaRaw[0] * alphaBetaRaw[1] +
|
|
||||||
coeffAlpha[index][8] * alphaBetaRaw[0] * alphaBetaRaw[1] * alphaBetaRaw[1] +
|
|
||||||
coeffAlpha[index][9] * alphaBetaRaw[1] * alphaBetaRaw[1] * alphaBetaRaw[1]; //[°]
|
|
||||||
alphaBetaCalibrated[1] =
|
|
||||||
coeffBeta[index][0] + coeffBeta[index][1] * alphaBetaRaw[0] +
|
|
||||||
coeffBeta[index][2] * alphaBetaRaw[1] +
|
|
||||||
coeffBeta[index][3] * alphaBetaRaw[0] * alphaBetaRaw[0] +
|
|
||||||
coeffBeta[index][4] * alphaBetaRaw[0] * alphaBetaRaw[1] +
|
|
||||||
coeffBeta[index][5] * alphaBetaRaw[1] * alphaBetaRaw[1] +
|
|
||||||
coeffBeta[index][6] * alphaBetaRaw[0] * alphaBetaRaw[0] * alphaBetaRaw[0] +
|
|
||||||
coeffBeta[index][7] * alphaBetaRaw[0] * alphaBetaRaw[0] * alphaBetaRaw[1] +
|
|
||||||
coeffBeta[index][8] * alphaBetaRaw[0] * alphaBetaRaw[1] * alphaBetaRaw[1] +
|
|
||||||
coeffBeta[index][9] * alphaBetaRaw[1] * alphaBetaRaw[1] * alphaBetaRaw[1]; //[°]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float* SusConverter::calculateSunVector() {
|
|
||||||
// Calculate the normalized Sun Vector
|
|
||||||
sunVectorSensorFrame[0] = -(tan(alphaBetaCalibrated[0] * (M_PI / 180)) /
|
|
||||||
(sqrt((powf(tan(alphaBetaCalibrated[0] * (M_PI / 180)), 2)) +
|
|
||||||
powf(tan((alphaBetaCalibrated[1] * (M_PI / 180))), 2) + (1))));
|
|
||||||
sunVectorSensorFrame[1] = -(tan(alphaBetaCalibrated[1] * (M_PI / 180)) /
|
|
||||||
(sqrt(powf((tan(alphaBetaCalibrated[0] * (M_PI / 180))), 2) +
|
|
||||||
powf(tan((alphaBetaCalibrated[1] * (M_PI / 180))), 2) + (1))));
|
|
||||||
sunVectorSensorFrame[2] =
|
|
||||||
-(-1 / (sqrt(powf((tan(alphaBetaCalibrated[0] * (M_PI / 180))), 2) +
|
|
||||||
powf((tan(alphaBetaCalibrated[1] * (M_PI / 180))), 2) + (1))));
|
|
||||||
|
|
||||||
return sunVectorSensorFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
float* SusConverter::getSunVectorSensorFrame(const uint16_t susChannel[6],
|
|
||||||
const float coeffAlpha[9][10],
|
|
||||||
const float coeffBeta[9][10]) {
|
|
||||||
calcAngle(susChannel);
|
|
||||||
calibration(coeffAlpha, coeffBeta);
|
|
||||||
return calculateSunVector();
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,4 @@
|
|||||||
#ifndef MISSION_CONTROLLER_ACS_SUSCONVERTER_H_
|
#include <fsfw/globalfunctions/math/VectorOperations.h>
|
||||||
#define MISSION_CONTROLLER_ACS_SUSCONVERTER_H_
|
|
||||||
|
|
||||||
#include <fsfw/datapoollocal/LocalPoolVector.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "AcsParameters.h"
|
#include "AcsParameters.h"
|
||||||
|
|
||||||
@ -10,41 +6,26 @@ class SusConverter {
|
|||||||
public:
|
public:
|
||||||
SusConverter() {}
|
SusConverter() {}
|
||||||
|
|
||||||
bool checkSunSensorData(const uint16_t susChannel[6]);
|
uint64_t checkSunSensorData(const uint16_t susChannel[6]);
|
||||||
|
bool checkValidity(bool* susValid, const uint64_t brightness[12], const float threshold);
|
||||||
void calcAngle(const uint16_t susChannel[6]);
|
void calculateSunVector(float* sunVectorSensorFrame, const uint16_t susChannel[6]);
|
||||||
void calibration(const float coeffAlpha[9][10], const float coeffBeta[9][10]);
|
|
||||||
float* calculateSunVector();
|
|
||||||
|
|
||||||
float* getSunVectorSensorFrame(const uint16_t susChannel[6], const float coeffAlpha[9][10],
|
|
||||||
const float coeffBeta[9][10]);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float alphaBetaRaw[2]; //[°]
|
|
||||||
float alphaBetaCalibrated[2]; //[°]
|
|
||||||
float sunVectorSensorFrame[3]; //[-]
|
|
||||||
|
|
||||||
bool validFlag[12] = {returnvalue::OK, returnvalue::OK, returnvalue::OK, returnvalue::OK,
|
|
||||||
returnvalue::OK, returnvalue::OK, returnvalue::OK, returnvalue::OK,
|
|
||||||
returnvalue::OK, returnvalue::OK, returnvalue::OK, returnvalue::OK};
|
|
||||||
|
|
||||||
static const uint8_t GNDREF = 4;
|
static const uint8_t GNDREF = 4;
|
||||||
uint16_t susChannelValueCheckHigh =
|
// =2^12[Bit]high borderline for the channel values of one sun sensor for validity Check
|
||||||
4096; //=2^12[Bit]high borderline for the channel values of one sun sensor for validity Check
|
static constexpr uint16_t SUS_CHANNEL_VALUE_HIGH = 4096;
|
||||||
uint8_t susChannelValueCheckLow =
|
// [Bit]low borderline for the channel values of one sun sensor for validity Check
|
||||||
0; //[Bit]low borderline for the channel values of one sun sensor for validity Check
|
static constexpr uint8_t SUS_CHANNEL_VALUE_LOW = 0;
|
||||||
uint16_t susChannelValueSumHigh =
|
// 4096[Bit]high borderline for check if the sun sensor is illuminated by the sun or by the
|
||||||
100; // 4096[Bit]high borderline for check if the sun sensor is illuminated by the sun or by
|
// reflection of sunlight from the moon/earth
|
||||||
// the reflection of sunlight from the moon/earth
|
static constexpr uint16_t SUS_ALBEDO_CHECK = 1000;
|
||||||
uint8_t susChannelValueSumLow =
|
// [Bit]low borderline for check if the sun sensor is illuminated by the sun or by the reflection
|
||||||
0; //[Bit]low borderline for check if the sun sensor is illuminated
|
// of sunlight from the moon/earth
|
||||||
// by the sun or by the reflection of sunlight from the moon/earth
|
static constexpr uint8_t SUS_CHANNEL_SUM_LOW = 0;
|
||||||
uint8_t completeCellWidth = 140,
|
|
||||||
halfCellWidth = 70; //[°] Width of the calibration cells --> necessary for checking in
|
static constexpr float S = 0.03; // S=[mm] gap between diodes
|
||||||
// which cell a data point should be
|
static constexpr float D = 5; // D=[mm] edge length of the quadratic aperture
|
||||||
uint16_t susChannelValueSum = 0;
|
static constexpr float H = 2.5; // H=[mm] distance between diodes and aperture
|
||||||
|
|
||||||
AcsParameters acsParameters;
|
AcsParameters acsParameters;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* MISSION_CONTROLLER_ACS_SUSCONVERTER_H_ */
|
|
||||||
|
@ -91,19 +91,21 @@ EiveFaultHandler EIVE_FAULT_HANDLER;
|
|||||||
} // namespace cfdp
|
} // namespace cfdp
|
||||||
|
|
||||||
std::atomic_bool tcs::TCS_BOARD_SHORTLY_UNAVAILABLE = false;
|
std::atomic_bool tcs::TCS_BOARD_SHORTLY_UNAVAILABLE = false;
|
||||||
|
std::atomic_bool core::SAVE_PUS_SEQUENCE_COUNT = false;
|
||||||
|
std::atomic_bool core::SAVE_CFDP_SEQUENCE_COUNT = false;
|
||||||
|
|
||||||
void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFunnel** pusFunnel,
|
void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFunnel** pusFunnel,
|
||||||
CfdpTmFunnel** cfdpFunnel, SdCardMountedIF& sdcMan,
|
CfdpTmFunnel** cfdpFunnel, SdCardMountedIF& sdcMan,
|
||||||
StorageManagerIF** ipcStore, StorageManagerIF** tmStore,
|
StorageManagerIF** ipcStore, StorageManagerIF** tmStore,
|
||||||
PersistentTmStores& stores,
|
PersistentTmStores& stores,
|
||||||
uint32_t eventManagerQueueDepth) {
|
uint32_t eventManagerQueueDepth, bool enableHkSets) {
|
||||||
// Framework objects
|
// Framework objects
|
||||||
new EventManager(objects::EVENT_MANAGER, eventManagerQueueDepth);
|
new EventManager(objects::EVENT_MANAGER, eventManagerQueueDepth);
|
||||||
auto healthTable = new HealthTable(objects::HEALTH_TABLE);
|
auto healthTable = new HealthTable(objects::HEALTH_TABLE);
|
||||||
if (healthTable_ != nullptr) {
|
if (healthTable_ != nullptr) {
|
||||||
*healthTable_ = healthTable;
|
*healthTable_ = healthTable;
|
||||||
}
|
}
|
||||||
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER);
|
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER, 5, enableHkSets, 120);
|
||||||
new VerificationReporter();
|
new VerificationReporter();
|
||||||
auto* timeStamper = new CdsShortTimeStamper(objects::TIME_STAMPER);
|
auto* timeStamper = new CdsShortTimeStamper(objects::TIME_STAMPER);
|
||||||
StorageManagerIF* tcStore;
|
StorageManagerIF* tcStore;
|
||||||
@ -155,9 +157,11 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun
|
|||||||
new PusDistributor(config::EIVE_PUS_APID, objects::PUS_PACKET_DISTRIBUTOR, ccsdsDistrib);
|
new PusDistributor(config::EIVE_PUS_APID, objects::PUS_PACKET_DISTRIBUTOR, ccsdsDistrib);
|
||||||
|
|
||||||
PusTmFunnel::FunnelCfg pusFunnelCfg(objects::PUS_TM_FUNNEL, "PusTmFunnel", **tmStore, **ipcStore,
|
PusTmFunnel::FunnelCfg pusFunnelCfg(objects::PUS_TM_FUNNEL, "PusTmFunnel", **tmStore, **ipcStore,
|
||||||
config::MAX_PUS_FUNNEL_QUEUE_DEPTH);
|
config::MAX_PUS_FUNNEL_QUEUE_DEPTH, sdcMan,
|
||||||
|
config::PUS_SEQUENCE_COUNT_FILE,
|
||||||
|
core::SAVE_PUS_SEQUENCE_COUNT);
|
||||||
// The PUS funnel routes all live TM to the live destinations and to the TM stores.
|
// The PUS funnel routes all live TM to the live destinations and to the TM stores.
|
||||||
*pusFunnel = new PusTmFunnel(pusFunnelCfg, *ramToFileStore, *timeStamper, sdcMan);
|
*pusFunnel = new PusTmFunnel(pusFunnelCfg, *ramToFileStore, *timeStamper);
|
||||||
|
|
||||||
// MISC store and PUS funnel to MISC store routing
|
// MISC store and PUS funnel to MISC store routing
|
||||||
{
|
{
|
||||||
@ -216,7 +220,9 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun
|
|||||||
stores.cfdpStore->getReportReceptionQueue(0));
|
stores.cfdpStore->getReportReceptionQueue(0));
|
||||||
}
|
}
|
||||||
PusTmFunnel::FunnelCfg cfdpFunnelCfg(objects::CFDP_TM_FUNNEL, "CfdpTmFunnel", **tmStore,
|
PusTmFunnel::FunnelCfg cfdpFunnelCfg(objects::CFDP_TM_FUNNEL, "CfdpTmFunnel", **tmStore,
|
||||||
**ipcStore, config::MAX_CFDP_FUNNEL_QUEUE_DEPTH);
|
**ipcStore, config::MAX_CFDP_FUNNEL_QUEUE_DEPTH, sdcMan,
|
||||||
|
config::CFDP_SEQUENCE_COUNT_FILE,
|
||||||
|
core::SAVE_CFDP_SEQUENCE_COUNT);
|
||||||
*cfdpFunnel = new CfdpTmFunnel(cfdpFunnelCfg, stores.cfdpStore->getReportReceptionQueue(0),
|
*cfdpFunnel = new CfdpTmFunnel(cfdpFunnelCfg, stores.cfdpStore->getReportReceptionQueue(0),
|
||||||
*ramToFileStore, config::EIVE_CFDP_APID);
|
*ramToFileStore, config::EIVE_CFDP_APID);
|
||||||
|
|
||||||
|
@ -45,7 +45,8 @@ namespace ObjectFactory {
|
|||||||
void produceGenericObjects(HealthTableIF** healthTable, PusTmFunnel** pusFunnel,
|
void produceGenericObjects(HealthTableIF** healthTable, PusTmFunnel** pusFunnel,
|
||||||
CfdpTmFunnel** cfdpFunnel, SdCardMountedIF& sdcMan,
|
CfdpTmFunnel** cfdpFunnel, SdCardMountedIF& sdcMan,
|
||||||
StorageManagerIF** ipcStore, StorageManagerIF** tmStore,
|
StorageManagerIF** ipcStore, StorageManagerIF** tmStore,
|
||||||
PersistentTmStores& stores, uint32_t eventManagerQueueDepth);
|
PersistentTmStores& stores, uint32_t eventManagerQueueDepth,
|
||||||
|
bool enableHkSets);
|
||||||
void createGenericHeaterComponents(GpioIF& gpioIF, PowerSwitchIF& pwrSwitcher,
|
void createGenericHeaterComponents(GpioIF& gpioIF, PowerSwitchIF& pwrSwitcher,
|
||||||
HeaterHandler*& heaterHandler);
|
HeaterHandler*& heaterHandler);
|
||||||
|
|
||||||
|
@ -34,6 +34,9 @@ enum Copy : int { COPY_0, COPY_1, NO_COPY, SELF_COPY, ALL_COPY };
|
|||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
|
|
||||||
|
extern std::atomic_bool SAVE_PUS_SEQUENCE_COUNT;
|
||||||
|
extern std::atomic_bool SAVE_CFDP_SEQUENCE_COUNT;
|
||||||
|
|
||||||
// TODO: Support for status? Or maybe some command to quickly get information whether a unit
|
// TODO: Support for status? Or maybe some command to quickly get information whether a unit
|
||||||
// is running.
|
// is running.
|
||||||
enum SystemctlCmd : uint8_t { START = 0, STOP = 1, RESTART = 2, NUM_CMDS = 3 };
|
enum SystemctlCmd : uint8_t { START = 0, STOP = 1, RESTART = 2, NUM_CMDS = 3 };
|
||||||
@ -41,9 +44,13 @@ enum SystemctlCmd : uint8_t { START = 0, STOP = 1, RESTART = 2, NUM_CMDS = 3 };
|
|||||||
static constexpr char CONF_FOLDER[] = "conf";
|
static constexpr char CONF_FOLDER[] = "conf";
|
||||||
|
|
||||||
static constexpr char VERSION_FILE_NAME[] = "version.txt";
|
static constexpr char VERSION_FILE_NAME[] = "version.txt";
|
||||||
static constexpr char REBOOT_FILE_NAME[] = "reboot.txt";
|
static constexpr char LEGACY_REBOOT_WATCHDOG_FILE_NAME[] = "reboot.txt";
|
||||||
|
static constexpr char REBOOT_WATCHDOG_FILE_NAME[] = "reboot_watchdog.txt";
|
||||||
|
static constexpr char REBOOT_COUNTER_FILE_NAME[] = "reboot_counters.txt";
|
||||||
static constexpr char TIME_FILE_NAME[] = "time_backup.txt";
|
static constexpr char TIME_FILE_NAME[] = "time_backup.txt";
|
||||||
|
|
||||||
|
static constexpr uint32_t SYS_ROM_BASE_ADDR = 0x80000000;
|
||||||
|
|
||||||
static constexpr ActionId_t ANNOUNCE_VERSION = 1;
|
static constexpr ActionId_t ANNOUNCE_VERSION = 1;
|
||||||
static constexpr ActionId_t ANNOUNCE_CURRENT_IMAGE = 2;
|
static constexpr ActionId_t ANNOUNCE_CURRENT_IMAGE = 2;
|
||||||
static constexpr ActionId_t ANNOUNCE_BOOT_COUNTS = 3;
|
static constexpr ActionId_t ANNOUNCE_BOOT_COUNTS = 3;
|
||||||
@ -51,6 +58,7 @@ static constexpr ActionId_t SWITCH_REBOOT_FILE_HANDLING = 5;
|
|||||||
static constexpr ActionId_t RESET_REBOOT_COUNTERS = 6;
|
static constexpr ActionId_t RESET_REBOOT_COUNTERS = 6;
|
||||||
static constexpr ActionId_t SWITCH_IMG_LOCK = 7;
|
static constexpr ActionId_t SWITCH_IMG_LOCK = 7;
|
||||||
static constexpr ActionId_t SET_MAX_REBOOT_CNT = 8;
|
static constexpr ActionId_t SET_MAX_REBOOT_CNT = 8;
|
||||||
|
static constexpr ActionId_t READ_REBOOT_MECHANISM_INFO = 9;
|
||||||
|
|
||||||
static constexpr ActionId_t OBSW_UPDATE_FROM_SD_0 = 10;
|
static constexpr ActionId_t OBSW_UPDATE_FROM_SD_0 = 10;
|
||||||
static constexpr ActionId_t OBSW_UPDATE_FROM_SD_1 = 11;
|
static constexpr ActionId_t OBSW_UPDATE_FROM_SD_1 = 11;
|
||||||
@ -113,6 +121,10 @@ static constexpr Event TRYING_I2C_RECOVERY = event::makeEvent(SUBSYSTEM_ID, 10,
|
|||||||
static constexpr Event I2C_REBOOT = event::makeEvent(SUBSYSTEM_ID, 11, severity::HIGH);
|
static constexpr Event I2C_REBOOT = event::makeEvent(SUBSYSTEM_ID, 11, severity::HIGH);
|
||||||
//! [EXPORT] : [COMMENT] PDEC recovery through reset was not possible, performing full reboot.
|
//! [EXPORT] : [COMMENT] PDEC recovery through reset was not possible, performing full reboot.
|
||||||
static constexpr Event PDEC_REBOOT = event::makeEvent(SUBSYSTEM_ID, 12, severity::HIGH);
|
static constexpr Event PDEC_REBOOT = event::makeEvent(SUBSYSTEM_ID, 12, severity::HIGH);
|
||||||
|
//! [EXPORT] : [COMMENT] 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.
|
||||||
|
static constexpr Event FIRMWARE_INFO = event::makeEvent(SUBSYSTEM_ID, 13, severity::INFO);
|
||||||
|
|
||||||
class ListDirectoryCmdBase {
|
class ListDirectoryCmdBase {
|
||||||
public: // TODO: Packet definition for clean deserialization
|
public: // TODO: Packet definition for clean deserialization
|
||||||
@ -242,19 +254,22 @@ class CpHelperParser {
|
|||||||
CpHelperParser(const uint8_t* data, size_t maxLen) : data(data), maxLen(maxLen) {}
|
CpHelperParser(const uint8_t* data, size_t maxLen) : data(data), maxLen(maxLen) {}
|
||||||
|
|
||||||
ReturnValue_t parse() {
|
ReturnValue_t parse() {
|
||||||
if (maxLen < 1) {
|
if (maxLen < 2) {
|
||||||
return SerializeIF::STREAM_TOO_SHORT;
|
return SerializeIF::STREAM_TOO_SHORT;
|
||||||
}
|
}
|
||||||
recursiveOpt = data[0];
|
recursiveOpt = data[0];
|
||||||
return parseDestTargetString(data + 1, maxLen - 1, destTgt);
|
forceOpt = data[1];
|
||||||
|
return parseDestTargetString(data + 2, maxLen - 2, destTgt);
|
||||||
}
|
}
|
||||||
const SourceTargetPair& destTgtPair() const { return destTgt; }
|
const SourceTargetPair& destTgtPair() const { return destTgt; }
|
||||||
bool isRecursiveOptSet() const { return recursiveOpt; }
|
bool isRecursiveOptSet() const { return recursiveOpt; }
|
||||||
|
bool isForceOptSet() const { return forceOpt; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const uint8_t* data;
|
const uint8_t* data;
|
||||||
size_t maxLen;
|
size_t maxLen;
|
||||||
bool recursiveOpt = false;
|
bool recursiveOpt = false;
|
||||||
|
bool forceOpt = false;
|
||||||
SourceTargetPair destTgt;
|
SourceTargetPair destTgt;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -51,9 +51,13 @@ ReturnValue_t HeaterHandler::performOperation(uint8_t operationCode) {
|
|||||||
if (mainLineSwitcher->getSwitchState(mainLineSwitch) == SWITCH_OFF) {
|
if (mainLineSwitcher->getSwitchState(mainLineSwitch) == SWITCH_OFF) {
|
||||||
waitForSwitchOff = false;
|
waitForSwitchOff = false;
|
||||||
mode = MODE_OFF;
|
mode = MODE_OFF;
|
||||||
|
busyWithSwitchCommanding = false;
|
||||||
modeHelper.modeChanged(mode, submode);
|
modeHelper.modeChanged(mode, submode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (busyWithSwitchCommanding and heaterCmdBusyCd.hasTimedOut()) {
|
||||||
|
busyWithSwitchCommanding = false;
|
||||||
|
}
|
||||||
} catch (const std::out_of_range& e) {
|
} catch (const std::out_of_range& e) {
|
||||||
sif::warning << "HeaterHandler::performOperation: "
|
sif::warning << "HeaterHandler::performOperation: "
|
||||||
"Out of range error | "
|
"Out of range error | "
|
||||||
@ -101,23 +105,23 @@ ReturnValue_t HeaterHandler::initializeHeaterMap() {
|
|||||||
void HeaterHandler::readCommandQueue() {
|
void HeaterHandler::readCommandQueue() {
|
||||||
ReturnValue_t result = returnvalue::OK;
|
ReturnValue_t result = returnvalue::OK;
|
||||||
CommandMessage command;
|
CommandMessage command;
|
||||||
do {
|
if (not busyWithSwitchCommanding) {
|
||||||
result = commandQueue->receiveMessage(&command);
|
result = commandQueue->receiveMessage(&command);
|
||||||
if (result == MessageQueueIF::EMPTY) {
|
if (result == MessageQueueIF::EMPTY) {
|
||||||
break;
|
return;
|
||||||
} else if (result != returnvalue::OK) {
|
} else if (result != returnvalue::OK) {
|
||||||
sif::warning << "HeaterHandler::readCommandQueue: Message reception error" << std::endl;
|
sif::warning << "HeaterHandler::readCommandQueue: Message reception error" << std::endl;
|
||||||
break;
|
return;
|
||||||
}
|
|
||||||
result = actionHelper.handleActionMessage(&command);
|
|
||||||
if (result == returnvalue::OK) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
result = modeHelper.handleModeCommand(&command);
|
result = modeHelper.handleModeCommand(&command);
|
||||||
if (result == returnvalue::OK) {
|
if (result == returnvalue::OK) {
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
} while (result == returnvalue::OK);
|
result = actionHelper.handleActionMessage(&command);
|
||||||
|
if (result == returnvalue::OK) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t HeaterHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
ReturnValue_t HeaterHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||||
@ -167,6 +171,8 @@ ReturnValue_t HeaterHandler::executeAction(ActionId_t actionId, MessageQueueId_t
|
|||||||
heater.action = action;
|
heater.action = action;
|
||||||
heater.cmdActive = true;
|
heater.cmdActive = true;
|
||||||
heater.replyQueue = commandedBy;
|
heater.replyQueue = commandedBy;
|
||||||
|
busyWithSwitchCommanding = true;
|
||||||
|
heaterCmdBusyCd.resetTimer();
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,6 +255,7 @@ void HeaterHandler::handleSwitchOnCommand(heater::Switch heaterIdx) {
|
|||||||
sif::error << "HeaterHandler::handleSwitchOnCommand: Main switch setting on timeout"
|
sif::error << "HeaterHandler::handleSwitchOnCommand: Main switch setting on timeout"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
heater.cmdActive = false;
|
heater.cmdActive = false;
|
||||||
|
busyWithSwitchCommanding = false;
|
||||||
heater.waitMainSwitchOn = false;
|
heater.waitMainSwitchOn = false;
|
||||||
if (heater.replyQueue != commandQueue->getId()) {
|
if (heater.replyQueue != commandQueue->getId()) {
|
||||||
actionHelper.finish(false, heater.replyQueue, heater.action, MAIN_SWITCH_SET_TIMEOUT);
|
actionHelper.finish(false, heater.replyQueue, heater.action, MAIN_SWITCH_SET_TIMEOUT);
|
||||||
@ -259,27 +266,25 @@ void HeaterHandler::handleSwitchOnCommand(heater::Switch heaterIdx) {
|
|||||||
// Check state of main line switch
|
// Check state of main line switch
|
||||||
ReturnValue_t mainSwitchState = mainLineSwitcher->getSwitchState(mainLineSwitch);
|
ReturnValue_t mainSwitchState = mainLineSwitcher->getSwitchState(mainLineSwitch);
|
||||||
if (mainSwitchState == PowerSwitchIF::SWITCH_ON) {
|
if (mainSwitchState == PowerSwitchIF::SWITCH_ON) {
|
||||||
if (getSwitchState(heaterIdx) == SwitchState::OFF) {
|
gpioId_t gpioId = heater.gpioId;
|
||||||
gpioId_t gpioId = heater.gpioId;
|
result = gpioInterface->pullHigh(gpioId);
|
||||||
result = gpioInterface->pullHigh(gpioId);
|
if (result != returnvalue::OK) {
|
||||||
if (result != returnvalue::OK) {
|
sif::error << "HeaterHandler::handleSwitchOnCommand: Failed to pull GPIO with ID " << gpioId
|
||||||
sif::error << "HeaterHandler::handleSwitchOnCommand: Failed to pull gpio with id " << gpioId
|
<< " high" << std::endl;
|
||||||
<< " high" << std::endl;
|
triggerEvent(GPIO_PULL_HIGH_FAILED, result);
|
||||||
triggerEvent(GPIO_PULL_HIGH_FAILED, result);
|
}
|
||||||
} else {
|
if (result == returnvalue::OK) {
|
||||||
triggerEvent(HEATER_WENT_ON, heaterIdx, 0);
|
triggerEvent(HEATER_WENT_ON, heaterIdx, 0);
|
||||||
EventManagerIF::triggerEvent(helper.heaters[heaterIdx].first->getObjectId(), MODE_INFO,
|
{
|
||||||
MODE_ON, 0);
|
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||||
{
|
heater.switchState = ON;
|
||||||
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
}
|
||||||
heater.switchState = ON;
|
EventManagerIF::triggerEvent(helper.heaters[heaterIdx].first->getObjectId(), MODE_INFO,
|
||||||
}
|
MODE_ON, 0);
|
||||||
}
|
busyWithSwitchCommanding = false;
|
||||||
} else {
|
mode = HasModesIF::MODE_ON;
|
||||||
triggerEvent(SWITCH_ALREADY_ON, heaterIdx);
|
modeHelper.modeChanged(mode, submode);
|
||||||
}
|
}
|
||||||
mode = HasModesIF::MODE_ON;
|
|
||||||
modeHelper.modeChanged(mode, submode);
|
|
||||||
// There is no need to send action finish replies if the sender was the
|
// There is no need to send action finish replies if the sender was the
|
||||||
// HeaterHandler itself
|
// HeaterHandler itself
|
||||||
if (heater.replyQueue != commandQueue->getId()) {
|
if (heater.replyQueue != commandQueue->getId()) {
|
||||||
@ -312,30 +317,33 @@ void HeaterHandler::handleSwitchOnCommand(heater::Switch heaterIdx) {
|
|||||||
void HeaterHandler::handleSwitchOffCommand(heater::Switch heaterIdx) {
|
void HeaterHandler::handleSwitchOffCommand(heater::Switch heaterIdx) {
|
||||||
ReturnValue_t result = returnvalue::OK;
|
ReturnValue_t result = returnvalue::OK;
|
||||||
auto& heater = heaterVec.at(heaterIdx);
|
auto& heater = heaterVec.at(heaterIdx);
|
||||||
// Check whether switch is already off
|
gpioId_t gpioId = heater.gpioId;
|
||||||
if (getSwitchState(heaterIdx)) {
|
result = gpioInterface->pullLow(gpioId);
|
||||||
gpioId_t gpioId = heater.gpioId;
|
if (result != returnvalue::OK) {
|
||||||
result = gpioInterface->pullLow(gpioId);
|
sif::error << "HeaterHandler::handleSwitchOffCommand: Failed to pull gpio with id" << gpioId
|
||||||
if (result != returnvalue::OK) {
|
<< " low" << std::endl;
|
||||||
sif::error << "HeaterHandler::handleSwitchOffCommand: Failed to pull gpio with id" << gpioId
|
triggerEvent(GPIO_PULL_LOW_FAILED, result);
|
||||||
<< " low" << std::endl;
|
}
|
||||||
triggerEvent(GPIO_PULL_LOW_FAILED, result);
|
if (result == returnvalue::OK) {
|
||||||
} else {
|
// Check whether switch is already off
|
||||||
|
if (getSwitchState(heaterIdx) == SwitchState::ON) {
|
||||||
{
|
{
|
||||||
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||||
heater.switchState = OFF;
|
heater.switchState = OFF;
|
||||||
}
|
}
|
||||||
triggerEvent(HEATER_WENT_OFF, heaterIdx, 0);
|
triggerEvent(HEATER_WENT_OFF, heaterIdx, 0);
|
||||||
EventManagerIF::triggerEvent(helper.heaters[heaterIdx].first->getObjectId(), MODE_INFO,
|
} else {
|
||||||
MODE_OFF, 0);
|
triggerEvent(SWITCH_ALREADY_OFF, heaterIdx);
|
||||||
// When all switches are off, also main line switch will be turned off
|
}
|
||||||
if (allSwitchesOff()) {
|
EventManagerIF::triggerEvent(helper.heaters[heaterIdx].first->getObjectId(), MODE_INFO,
|
||||||
mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
|
MODE_OFF, 0);
|
||||||
waitForSwitchOff = true;
|
// When all switches are off, also main line switch will be turned off
|
||||||
}
|
if (allSwitchesOff()) {
|
||||||
|
mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
|
||||||
|
waitForSwitchOff = true;
|
||||||
|
} else {
|
||||||
|
busyWithSwitchCommanding = false;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
triggerEvent(SWITCH_ALREADY_OFF, heaterIdx);
|
|
||||||
}
|
}
|
||||||
if (heater.replyQueue != NO_COMMANDER) {
|
if (heater.replyQueue != NO_COMMANDER) {
|
||||||
// Report back switch command reply if necessary
|
// Report back switch command reply if necessary
|
||||||
|
@ -148,6 +148,7 @@ class HeaterHandler : public ExecutableObjectIF,
|
|||||||
/** Size of command queue */
|
/** Size of command queue */
|
||||||
size_t cmdQueueSize = 20;
|
size_t cmdQueueSize = 20;
|
||||||
bool waitForSwitchOff = true;
|
bool waitForSwitchOff = true;
|
||||||
|
bool busyWithSwitchCommanding = false;
|
||||||
|
|
||||||
GpioIF* gpioInterface = nullptr;
|
GpioIF* gpioInterface = nullptr;
|
||||||
|
|
||||||
@ -163,6 +164,7 @@ class HeaterHandler : public ExecutableObjectIF,
|
|||||||
power::Switch_t mainLineSwitch;
|
power::Switch_t mainLineSwitch;
|
||||||
|
|
||||||
ActionHelper actionHelper;
|
ActionHelper actionHelper;
|
||||||
|
Countdown heaterCmdBusyCd = Countdown(2000);
|
||||||
|
|
||||||
StorageManagerIF* ipcStore = nullptr;
|
StorageManagerIF* ipcStore = nullptr;
|
||||||
|
|
||||||
|
@ -37,6 +37,8 @@ void Max31865EiveHandler::doShutDown() {
|
|||||||
transitionOk = false;
|
transitionOk = false;
|
||||||
}
|
}
|
||||||
if (state == InternalState::INACTIVE and transitionOk) {
|
if (state == InternalState::INACTIVE and transitionOk) {
|
||||||
|
sensorDataset.temperatureCelcius = thermal::INVALID_TEMPERATURE;
|
||||||
|
sensorDataset.setValidity(false, true);
|
||||||
updatePeriodicReply(false, EiveMax31855::RtdCommands::EXCHANGE_SET_ID);
|
updatePeriodicReply(false, EiveMax31855::RtdCommands::EXCHANGE_SET_ID);
|
||||||
setMode(MODE_OFF);
|
setMode(MODE_OFF);
|
||||||
}
|
}
|
||||||
|
@ -15,8 +15,16 @@ const char* CfdpTmFunnel::getName() const { return "CFDP TM Funnel"; }
|
|||||||
|
|
||||||
ReturnValue_t CfdpTmFunnel::performOperation(uint8_t) {
|
ReturnValue_t CfdpTmFunnel::performOperation(uint8_t) {
|
||||||
TmTcMessage currentMessage;
|
TmTcMessage currentMessage;
|
||||||
|
ReturnValue_t status;
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
ReturnValue_t status = tmQueue->receiveMessage(¤tMessage);
|
if (saveSequenceCount) {
|
||||||
|
status = saveSequenceCountToFile();
|
||||||
|
if (status != returnvalue::OK) {
|
||||||
|
sif::error << "CfdpTmFunnel: Storing sequence count to file has failed" << std::endl;
|
||||||
|
}
|
||||||
|
saveSequenceCount = false;
|
||||||
|
}
|
||||||
|
status = tmQueue->receiveMessage(¤tMessage);
|
||||||
while (status == returnvalue::OK) {
|
while (status == returnvalue::OK) {
|
||||||
status = handlePacket(currentMessage);
|
status = handlePacket(currentMessage);
|
||||||
if (status != returnvalue::OK) {
|
if (status != returnvalue::OK) {
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <mission/tmtc/TmFunnelBase.h>
|
#include <mission/tmtc/TmFunnelBase.h>
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "fsfw/objectmanager/SystemObject.h"
|
#include "fsfw/objectmanager/SystemObject.h"
|
||||||
@ -23,7 +24,6 @@ class CfdpTmFunnel : public TmFunnelBase {
|
|||||||
|
|
||||||
MessageQueueId_t fileStoreDest;
|
MessageQueueId_t fileStoreDest;
|
||||||
StorageManagerIF& ramToFileStore;
|
StorageManagerIF& ramToFileStore;
|
||||||
uint16_t sourceSequenceCount = 0;
|
|
||||||
uint16_t cfdpInCcsdsApid;
|
uint16_t cfdpInCcsdsApid;
|
||||||
};
|
};
|
||||||
#endif // FSFW_EXAMPLE_COMMON_CFDPTMFUNNEL_H
|
#endif // FSFW_EXAMPLE_COMMON_CFDPTMFUNNEL_H
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
using namespace returnvalue;
|
using namespace returnvalue;
|
||||||
|
|
||||||
|
static constexpr bool DEBUG_DUMPS = false;
|
||||||
|
|
||||||
PersistentTmStore::PersistentTmStore(PersistentTmStoreArgs args)
|
PersistentTmStore::PersistentTmStore(PersistentTmStoreArgs args)
|
||||||
: SystemObject(args.objectId),
|
: SystemObject(args.objectId),
|
||||||
tmStore(args.tmStore),
|
tmStore(args.tmStore),
|
||||||
@ -32,6 +34,91 @@ ReturnValue_t PersistentTmStore::cancelDump() {
|
|||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PersistentTmStore::buildDumpSet(uint32_t fromUnixSeconds, uint32_t upToUnixSeconds) {
|
||||||
|
using namespace std::filesystem;
|
||||||
|
std::error_code e;
|
||||||
|
dumpParams.orderedDumpFilestamps.clear();
|
||||||
|
for (auto const& fileOrDir : directory_iterator(basePath)) {
|
||||||
|
if (not fileOrDir.is_regular_file(e)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
dumpParams.fileSize = std::filesystem::file_size(fileOrDir.path(), e);
|
||||||
|
if (e) {
|
||||||
|
sif::error << "PersistentTmStore: Could not retrieve file size: " << e.message() << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// File empty or can't even read CCSDS header.
|
||||||
|
if (dumpParams.fileSize <= 6) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (dumpParams.fileSize > fileBuf.size()) {
|
||||||
|
sif::error << "PersistentTmStore: File too large, is deleted" << std::endl;
|
||||||
|
triggerEvent(persTmStore::FILE_TOO_LARGE, dumpParams.fileSize, fileBuf.size());
|
||||||
|
std::filesystem::remove(fileOrDir.path(), e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const path& file = fileOrDir.path();
|
||||||
|
struct tm fileTime {};
|
||||||
|
if (pathToTime(file, fileTime) != returnvalue::OK) {
|
||||||
|
sif::error << "Time extraction for file " << file << "failed" << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto fileEpoch = static_cast<uint32_t>(timegm(&fileTime));
|
||||||
|
if ((fileEpoch > dumpParams.fromUnixTime) and
|
||||||
|
(fileEpoch + rolloverDiffSeconds <= dumpParams.untilUnixTime)) {
|
||||||
|
std::ifstream ifile(file, std::ios::binary);
|
||||||
|
if (ifile.bad()) {
|
||||||
|
sif::error << "PersistentTmStore: File is bad" << std::endl;
|
||||||
|
// TODO: Consider deleting file here?
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEBUG_DUMPS) {
|
||||||
|
sif::debug << "Inserting file " << fileOrDir.path() << std::endl;
|
||||||
|
}
|
||||||
|
DumpIndex dumpIndex;
|
||||||
|
dumpIndex.epoch = fileEpoch;
|
||||||
|
// Multiple files for the same time are supported via a special suffix. We simply count the
|
||||||
|
// number of copies and later try to dump the same number of files with the additional
|
||||||
|
// suffixes
|
||||||
|
auto iter = dumpParams.orderedDumpFilestamps.find(dumpIndex);
|
||||||
|
if (iter != dumpParams.orderedDumpFilestamps.end()) {
|
||||||
|
dumpIndex.epoch = iter->epoch;
|
||||||
|
dumpIndex.additionalFiles = iter->additionalFiles + 1;
|
||||||
|
dumpParams.orderedDumpFilestamps.erase(dumpIndex);
|
||||||
|
} else {
|
||||||
|
dumpIndex.additionalFiles = 0;
|
||||||
|
}
|
||||||
|
dumpParams.orderedDumpFilestamps.emplace(dumpIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<uint8_t> PersistentTmStore::extractSuffix(const std::string& pathStr) {
|
||||||
|
std::string numberStr;
|
||||||
|
// Find the position of the dot at the end of the file path
|
||||||
|
size_t dotPos = pathStr.find_last_of('.');
|
||||||
|
if ((dotPos < pathStr.length()) and not std::isdigit(pathStr[dotPos + 1])) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
// Extract the substring after the dot
|
||||||
|
numberStr = pathStr.substr(dotPos + 1);
|
||||||
|
std::optional<uint8_t> number;
|
||||||
|
try {
|
||||||
|
number = std::stoi(numberStr);
|
||||||
|
if (number.value() > std::numeric_limits<uint8_t>::max()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (std::invalid_argument& exception) {
|
||||||
|
sif::error << "PersistentTmStore::extractSuffix: Exception " << exception.what()
|
||||||
|
<< ", invald input string: " << numberStr << std::endl;
|
||||||
|
}
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
ReturnValue_t PersistentTmStore::assignAndOrCreateMostRecentFile() {
|
ReturnValue_t PersistentTmStore::assignAndOrCreateMostRecentFile() {
|
||||||
if (not activeFile.has_value()) {
|
if (not activeFile.has_value()) {
|
||||||
return createMostRecentFile(std::nullopt);
|
return createMostRecentFile(std::nullopt);
|
||||||
@ -41,6 +128,7 @@ ReturnValue_t PersistentTmStore::assignAndOrCreateMostRecentFile() {
|
|||||||
|
|
||||||
ReturnValue_t PersistentTmStore::handleCommandQueue(StorageManagerIF& ipcStore,
|
ReturnValue_t PersistentTmStore::handleCommandQueue(StorageManagerIF& ipcStore,
|
||||||
Command_t& execCmd) {
|
Command_t& execCmd) {
|
||||||
|
execCmd = CommandMessageIF::CMD_NONE;
|
||||||
CommandMessage cmdMessage;
|
CommandMessage cmdMessage;
|
||||||
ReturnValue_t result = tcQueue->receiveMessage(&cmdMessage);
|
ReturnValue_t result = tcQueue->receiveMessage(&cmdMessage);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
@ -75,9 +163,9 @@ ReturnValue_t PersistentTmStore::handleCommandQueue(StorageManagerIF& ipcStore,
|
|||||||
result = startDumpFromUpTo(dumpFromUnixSeconds, dumpUntilUnixSeconds);
|
result = startDumpFromUpTo(dumpFromUnixSeconds, dumpUntilUnixSeconds);
|
||||||
if (result == BUSY_DUMPING) {
|
if (result == BUSY_DUMPING) {
|
||||||
triggerEvent(persTmStore::BUSY_DUMPING_EVENT);
|
triggerEvent(persTmStore::BUSY_DUMPING_EVENT);
|
||||||
} else {
|
return result;
|
||||||
execCmd = cmd;
|
|
||||||
}
|
}
|
||||||
|
execCmd = cmd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -159,6 +247,12 @@ bool PersistentTmStore::updateBaseDir() {
|
|||||||
if (not exists(basePath, e)) {
|
if (not exists(basePath, e)) {
|
||||||
create_directories(basePath);
|
create_directories(basePath);
|
||||||
}
|
}
|
||||||
|
// Each file will have the base name as a prefix again
|
||||||
|
path preparedFullFilePath = basePath / baseName;
|
||||||
|
basePathSize = preparedFullFilePath.string().length();
|
||||||
|
std::memcpy(filePathBuf.data(), preparedFullFilePath.c_str(), basePathSize);
|
||||||
|
filePathBuf[basePathSize] = '_';
|
||||||
|
basePathSize += 1;
|
||||||
baseDirUninitialized = false;
|
baseDirUninitialized = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -189,12 +283,20 @@ ReturnValue_t PersistentTmStore::startDumpFromUpTo(uint32_t fromUnixSeconds,
|
|||||||
if (state == State::DUMPING) {
|
if (state == State::DUMPING) {
|
||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
}
|
}
|
||||||
dumpParams.dirIter = directory_iterator(basePath);
|
auto dirIter = directory_iterator(basePath);
|
||||||
if (dumpParams.dirIter == directory_iterator()) {
|
// Directory empty case.
|
||||||
|
if (dirIter == directory_iterator()) {
|
||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
}
|
}
|
||||||
dumpParams.fromUnixTime = fromUnixSeconds;
|
dumpParams.fromUnixTime = fromUnixSeconds;
|
||||||
dumpParams.untilUnixTime = upToUnixSeconds;
|
dumpParams.untilUnixTime = upToUnixSeconds;
|
||||||
|
buildDumpSet(fromUnixSeconds, upToUnixSeconds);
|
||||||
|
// No files in time window found.
|
||||||
|
if (dumpParams.orderedDumpFilestamps.empty()) {
|
||||||
|
return DUMP_DONE;
|
||||||
|
}
|
||||||
|
dumpParams.dumpIter = dumpParams.orderedDumpFilestamps.begin();
|
||||||
|
dumpParams.currentSameFileIdx = std::nullopt;
|
||||||
state = State::DUMPING;
|
state = State::DUMPING;
|
||||||
return loadNextDumpFile();
|
return loadNextDumpFile();
|
||||||
}
|
}
|
||||||
@ -203,49 +305,54 @@ ReturnValue_t PersistentTmStore::loadNextDumpFile() {
|
|||||||
using namespace std::filesystem;
|
using namespace std::filesystem;
|
||||||
dumpParams.currentSize = 0;
|
dumpParams.currentSize = 0;
|
||||||
std::error_code e;
|
std::error_code e;
|
||||||
for (; dumpParams.dirIter != directory_iterator(); dumpParams.dirIter++) {
|
// Handle iteration, which does not necessarily have to increment the set iterator
|
||||||
dumpParams.dirEntry = *dumpParams.dirIter;
|
// if there are multiple files for a given timestamp.
|
||||||
if (dumpParams.dirEntry.is_directory(e)) {
|
auto handleIteration = [&](DumpIndex& dumpIndex) {
|
||||||
continue;
|
if (dumpIndex.additionalFiles > 0) {
|
||||||
}
|
if (not dumpParams.currentSameFileIdx.has_value()) {
|
||||||
dumpParams.fileSize = std::filesystem::file_size(dumpParams.dirEntry.path(), e);
|
// Initialize the file index and stay on same file
|
||||||
if (e) {
|
dumpParams.currentSameFileIdx = 0;
|
||||||
sif::error << "PersistentTmStore: Could not retrieve file size: " << e.message() << std::endl;
|
return;
|
||||||
continue;
|
} else if (dumpParams.currentSameFileIdx.value() < dumpIndex.additionalFiles - 1) {
|
||||||
}
|
dumpParams.currentSameFileIdx = dumpParams.currentSameFileIdx.value() + 1;
|
||||||
// sif::debug << "Path: " << dumpParams.dirEntry.path() << std::endl;
|
return;
|
||||||
|
|
||||||
// File empty or can't even read CCSDS header.
|
|
||||||
if (dumpParams.fileSize <= 6) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (dumpParams.fileSize > fileBuf.size()) {
|
|
||||||
sif::error << "PersistentTmStore: File too large, is deleted" << std::endl;
|
|
||||||
triggerEvent(persTmStore::FILE_TOO_LARGE, dumpParams.fileSize, fileBuf.size());
|
|
||||||
std::filesystem::remove(dumpParams.dirEntry.path(), e);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const path& file = dumpParams.dirEntry.path();
|
|
||||||
struct tm fileTime {};
|
|
||||||
if (pathToTime(file, fileTime) != returnvalue::OK) {
|
|
||||||
sif::error << "Time extraction for file " << file << "failed" << std::endl;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto fileEpoch = static_cast<uint32_t>(timegm(&fileTime));
|
|
||||||
if ((fileEpoch > dumpParams.fromUnixTime) and
|
|
||||||
(fileEpoch + rolloverDiffSeconds <= dumpParams.untilUnixTime)) {
|
|
||||||
dumpParams.currentFileUnixStamp = fileEpoch;
|
|
||||||
std::ifstream ifile(file, std::ios::binary);
|
|
||||||
if (ifile.bad()) {
|
|
||||||
sif::error << "PersistentTmStore: File is bad" << std::endl;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
ifile.read(reinterpret_cast<char*>(fileBuf.data()),
|
|
||||||
static_cast<std::streamsize>(dumpParams.fileSize));
|
|
||||||
// Increment iterator for next cycle.
|
|
||||||
dumpParams.dirIter++;
|
|
||||||
return returnvalue::OK;
|
|
||||||
}
|
}
|
||||||
|
// File will change, reset this field for correct state-keeping.
|
||||||
|
dumpParams.currentSameFileIdx = std::nullopt;
|
||||||
|
// Increment iterator for next cycle.
|
||||||
|
dumpParams.dumpIter++;
|
||||||
|
};
|
||||||
|
while (dumpParams.dumpIter != dumpParams.orderedDumpFilestamps.end()) {
|
||||||
|
DumpIndex dumpIndex = *dumpParams.dumpIter;
|
||||||
|
timeval tv{};
|
||||||
|
tv.tv_sec = dumpIndex.epoch;
|
||||||
|
size_t fullPathLength = 0;
|
||||||
|
createFileName(tv, dumpParams.currentSameFileIdx, fullPathLength);
|
||||||
|
dumpParams.currentFile =
|
||||||
|
path(std::string(reinterpret_cast<const char*>(filePathBuf.data()), fullPathLength));
|
||||||
|
if (DEBUG_DUMPS) {
|
||||||
|
sif::debug << baseName << " dump: Loading " << dumpParams.currentFile << std::endl;
|
||||||
|
}
|
||||||
|
dumpParams.fileSize = std::filesystem::file_size(dumpParams.currentFile, e);
|
||||||
|
if (e) {
|
||||||
|
// TODO: Event?
|
||||||
|
sif::error << "PersistentTmStore: Could not load next dump file: " << e.message()
|
||||||
|
<< std::endl;
|
||||||
|
handleIteration(dumpIndex);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::ifstream ifile(dumpParams.currentFile, std::ios::binary);
|
||||||
|
if (ifile.bad()) {
|
||||||
|
sif::error << "PersistentTmStore: File is bad. Loading next file" << std::endl;
|
||||||
|
handleIteration(dumpIndex);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ifile.read(reinterpret_cast<char*>(fileBuf.data()),
|
||||||
|
static_cast<std::streamsize>(dumpParams.fileSize));
|
||||||
|
// Next file is loaded, exit the loop.
|
||||||
|
handleIteration(dumpIndex);
|
||||||
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
// Directory iterator was consumed and we are done.
|
// Directory iterator was consumed and we are done.
|
||||||
state = State::IDLE;
|
state = State::IDLE;
|
||||||
@ -253,7 +360,10 @@ ReturnValue_t PersistentTmStore::loadNextDumpFile() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PersistentTmStore::getNextDumpPacket(PusTmReader& reader, bool& fileHasSwapped) {
|
ReturnValue_t PersistentTmStore::getNextDumpPacket(PusTmReader& reader, bool& fileHasSwapped) {
|
||||||
if (state == State::IDLE or dumpParams.pendingPacketDump) {
|
if (state == State::IDLE) {
|
||||||
|
return DUMP_DONE;
|
||||||
|
}
|
||||||
|
if (dumpParams.pendingPacketDump) {
|
||||||
return returnvalue::FAILED;
|
return returnvalue::FAILED;
|
||||||
}
|
}
|
||||||
fileHasSwapped = false;
|
fileHasSwapped = false;
|
||||||
@ -267,7 +377,11 @@ ReturnValue_t PersistentTmStore::getNextDumpPacket(PusTmReader& reader, bool& fi
|
|||||||
// Delete the file and load next. Could use better algorithm to partially
|
// Delete the file and load next. Could use better algorithm to partially
|
||||||
// restore the file dump, but for now do not trust the file.
|
// restore the file dump, but for now do not trust the file.
|
||||||
std::error_code e;
|
std::error_code e;
|
||||||
std::filesystem::remove(dumpParams.dirEntry.path().c_str(), e);
|
std::filesystem::remove(dumpParams.currentFile.c_str(), e);
|
||||||
|
if (dumpParams.currentFile == activeFile) {
|
||||||
|
activeFile == std::nullopt;
|
||||||
|
assignAndOrCreateMostRecentFile();
|
||||||
|
}
|
||||||
fileHasSwapped = true;
|
fileHasSwapped = true;
|
||||||
return loadNextDumpFile();
|
return loadNextDumpFile();
|
||||||
}
|
}
|
||||||
@ -298,37 +412,9 @@ ReturnValue_t PersistentTmStore::pathToTime(const std::filesystem::path& path, s
|
|||||||
|
|
||||||
ReturnValue_t PersistentTmStore::createMostRecentFile(std::optional<uint8_t> suffix) {
|
ReturnValue_t PersistentTmStore::createMostRecentFile(std::optional<uint8_t> suffix) {
|
||||||
using namespace std::filesystem;
|
using namespace std::filesystem;
|
||||||
unsigned currentIdx = 0;
|
size_t currentIdx;
|
||||||
path pathStart = basePath / baseName;
|
createFileName(currentTv, suffix, currentIdx);
|
||||||
memcpy(fileBuf.data() + currentIdx, pathStart.c_str(), pathStart.string().length());
|
path newPath(std::string(reinterpret_cast<const char*>(filePathBuf.data()), currentIdx));
|
||||||
currentIdx += pathStart.string().length();
|
|
||||||
fileBuf[currentIdx] = '_';
|
|
||||||
currentIdx += 1;
|
|
||||||
time_t epoch = currentTv.tv_sec;
|
|
||||||
struct tm* time = gmtime(&epoch);
|
|
||||||
size_t writtenBytes = strftime(reinterpret_cast<char*>(fileBuf.data() + currentIdx),
|
|
||||||
fileBuf.size(), config::FILE_DATE_FORMAT, time);
|
|
||||||
if (writtenBytes == 0) {
|
|
||||||
sif::error << "PersistentTmStore::createMostRecentFile: Could not create file timestamp"
|
|
||||||
<< std::endl;
|
|
||||||
return returnvalue::FAILED;
|
|
||||||
}
|
|
||||||
currentIdx += writtenBytes;
|
|
||||||
char* res = strcpy(reinterpret_cast<char*>(fileBuf.data() + currentIdx), ".bin");
|
|
||||||
if (res == nullptr) {
|
|
||||||
return returnvalue::FAILED;
|
|
||||||
}
|
|
||||||
currentIdx += 4;
|
|
||||||
if (suffix.has_value()) {
|
|
||||||
std::string fullSuffix = "." + std::to_string(suffix.value());
|
|
||||||
res = strcpy(reinterpret_cast<char*>(fileBuf.data() + currentIdx), fullSuffix.c_str());
|
|
||||||
if (res == nullptr) {
|
|
||||||
return returnvalue::FAILED;
|
|
||||||
}
|
|
||||||
currentIdx += fullSuffix.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
path newPath(std::string(reinterpret_cast<const char*>(fileBuf.data()), currentIdx));
|
|
||||||
std::ofstream of(newPath, std::ios::binary);
|
std::ofstream of(newPath, std::ios::binary);
|
||||||
activeFile = newPath;
|
activeFile = newPath;
|
||||||
activeFileTv = currentTv;
|
activeFileTv = currentTv;
|
||||||
@ -350,3 +436,33 @@ void PersistentTmStore::getStartAndEndTimeCurrentOrLastDump(uint32_t& startTime,
|
|||||||
startTime = dumpParams.fromUnixTime;
|
startTime = dumpParams.fromUnixTime;
|
||||||
endTime = dumpParams.untilUnixTime;
|
endTime = dumpParams.untilUnixTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PersistentTmStore::createFileName(timeval& tv, std::optional<uint8_t> suffix,
|
||||||
|
size_t& fullPathLength) {
|
||||||
|
unsigned currentIdx = basePathSize;
|
||||||
|
time_t epoch = tv.tv_sec;
|
||||||
|
struct tm* time = gmtime(&epoch);
|
||||||
|
size_t writtenBytes = strftime(reinterpret_cast<char*>(filePathBuf.data() + currentIdx),
|
||||||
|
filePathBuf.size(), config::FILE_DATE_FORMAT, time);
|
||||||
|
if (writtenBytes == 0) {
|
||||||
|
sif::error << "PersistentTmStore::createMostRecentFile: Could not create file timestamp"
|
||||||
|
<< std::endl;
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
currentIdx += writtenBytes;
|
||||||
|
char* res = strcpy(reinterpret_cast<char*>(filePathBuf.data() + currentIdx), ".bin");
|
||||||
|
if (res == nullptr) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
currentIdx += 4;
|
||||||
|
if (suffix.has_value()) {
|
||||||
|
std::string fullSuffix = "." + std::to_string(suffix.value());
|
||||||
|
res = strcpy(reinterpret_cast<char*>(filePathBuf.data() + currentIdx), fullSuffix.c_str());
|
||||||
|
if (res == nullptr) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
currentIdx += fullSuffix.size();
|
||||||
|
}
|
||||||
|
fullPathLength = currentIdx;
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <mission/memory/SdCardMountedIF.h>
|
#include <mission/memory/SdCardMountedIF.h>
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include "eive/eventSubsystemIds.h"
|
#include "eive/eventSubsystemIds.h"
|
||||||
#include "eive/resultClassIds.h"
|
#include "eive/resultClassIds.h"
|
||||||
@ -37,6 +38,14 @@ struct PersistentTmStoreArgs {
|
|||||||
SdCardMountedIF& sdcMan;
|
SdCardMountedIF& sdcMan;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DumpIndex {
|
||||||
|
uint32_t epoch = 0;
|
||||||
|
// Number of additional files with a suffix like .0, .1 etc.
|
||||||
|
uint8_t additionalFiles = 0;
|
||||||
|
// Define a custom comparison function based on the epoch variable
|
||||||
|
bool operator<(const DumpIndex& other) const { return epoch < other.epoch; }
|
||||||
|
};
|
||||||
|
|
||||||
class PersistentTmStore : public TmStoreFrontendSimpleIF, public SystemObject {
|
class PersistentTmStore : public TmStoreFrontendSimpleIF, public SystemObject {
|
||||||
public:
|
public:
|
||||||
enum class State { IDLE, DUMPING };
|
enum class State { IDLE, DUMPING };
|
||||||
@ -96,7 +105,10 @@ class PersistentTmStore : public TmStoreFrontendSimpleIF, public SystemObject {
|
|||||||
std::string baseName;
|
std::string baseName;
|
||||||
uint8_t currentSameSecNumber = 0;
|
uint8_t currentSameSecNumber = 0;
|
||||||
std::filesystem::path basePath;
|
std::filesystem::path basePath;
|
||||||
|
// std::filesystem::path pathStart = basePath / baseName;
|
||||||
uint32_t rolloverDiffSeconds = 0;
|
uint32_t rolloverDiffSeconds = 0;
|
||||||
|
std::array<uint8_t, 524> filePathBuf{};
|
||||||
|
size_t basePathSize;
|
||||||
std::array<uint8_t, MAX_FILESIZE> fileBuf{};
|
std::array<uint8_t, MAX_FILESIZE> fileBuf{};
|
||||||
timeval currentTv;
|
timeval currentTv;
|
||||||
timeval activeFileTv{};
|
timeval activeFileTv{};
|
||||||
@ -106,8 +118,10 @@ class PersistentTmStore : public TmStoreFrontendSimpleIF, public SystemObject {
|
|||||||
uint32_t fromUnixTime = 0;
|
uint32_t fromUnixTime = 0;
|
||||||
uint32_t untilUnixTime = 0;
|
uint32_t untilUnixTime = 0;
|
||||||
uint32_t currentFileUnixStamp = 0;
|
uint32_t currentFileUnixStamp = 0;
|
||||||
std::filesystem::directory_iterator dirIter;
|
std::filesystem::path currentFile;
|
||||||
std::filesystem::directory_entry dirEntry;
|
std::set<DumpIndex> orderedDumpFilestamps{};
|
||||||
|
std::set<DumpIndex>::iterator dumpIter;
|
||||||
|
std::optional<uint8_t> currentSameFileIdx = 0;
|
||||||
size_t fileSize = 0;
|
size_t fileSize = 0;
|
||||||
size_t currentSize = 0;
|
size_t currentSize = 0;
|
||||||
};
|
};
|
||||||
@ -122,10 +136,13 @@ class PersistentTmStore : public TmStoreFrontendSimpleIF, public SystemObject {
|
|||||||
[[nodiscard]] MessageQueueId_t getCommandQueue() const override;
|
[[nodiscard]] MessageQueueId_t getCommandQueue() const override;
|
||||||
|
|
||||||
void calcDiffSeconds(RolloverInterval intervalUnit, uint32_t intervalCount);
|
void calcDiffSeconds(RolloverInterval intervalUnit, uint32_t intervalCount);
|
||||||
|
ReturnValue_t buildDumpSet(uint32_t fromUnixSeconds, uint32_t upToUnixSeconds);
|
||||||
ReturnValue_t createMostRecentFile(std::optional<uint8_t> suffix);
|
ReturnValue_t createMostRecentFile(std::optional<uint8_t> suffix);
|
||||||
static ReturnValue_t pathToTime(const std::filesystem::path& path, struct tm& time);
|
static ReturnValue_t pathToTime(const std::filesystem::path& path, struct tm& time);
|
||||||
void fileToPackets(const std::filesystem::path& path, uint32_t unixStamp);
|
void fileToPackets(const std::filesystem::path& path, uint32_t unixStamp);
|
||||||
ReturnValue_t loadNextDumpFile();
|
ReturnValue_t loadNextDumpFile();
|
||||||
|
ReturnValue_t createFileName(timeval& tv, std::optional<uint8_t> suffix, size_t& fullPathLength);
|
||||||
|
std::optional<uint8_t> extractSuffix(const std::string& pathStr);
|
||||||
bool updateBaseDir();
|
bool updateBaseDir();
|
||||||
ReturnValue_t assignAndOrCreateMostRecentFile();
|
ReturnValue_t assignAndOrCreateMostRecentFile();
|
||||||
};
|
};
|
||||||
|
@ -11,23 +11,20 @@ ReturnValue_t PusLiveDemux::demultiplexPackets(StorageManagerIF& tmStore,
|
|||||||
ReturnValue_t result = returnvalue::OK;
|
ReturnValue_t result = returnvalue::OK;
|
||||||
for (unsigned int idx = 0; idx < destinations.size(); idx++) {
|
for (unsigned int idx = 0; idx < destinations.size(); idx++) {
|
||||||
const auto& dest = destinations[idx];
|
const auto& dest = destinations[idx];
|
||||||
if (destinations.size() > 1) {
|
if ((destinations.size() > 1) and (idx < (destinations.size() - 1))) {
|
||||||
if (idx < destinations.size() - 1) {
|
// Create copy of data to ensure each TM recipient has its own copy. That way, we don't need
|
||||||
// Create copy of data to ensure each TM recipient has its own copy. That way, we don't need
|
// to bother with send order and where the data is deleted.
|
||||||
// to bother with send order and where the data is deleted.
|
store_address_t storeId;
|
||||||
store_address_t storeId;
|
result = tmStore.addData(&storeId, tmData, tmSize);
|
||||||
result = tmStore.addData(&storeId, tmData, tmSize);
|
if (result == returnvalue::OK) {
|
||||||
if (result == returnvalue::OK) {
|
message.setStorageId(storeId);
|
||||||
message.setStorageId(storeId);
|
|
||||||
} else {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "PusLiveDemux::handlePacket: Store too full to create data copy"
|
|
||||||
<< std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
message.setStorageId(origStoreId);
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "PusLiveDemux::handlePacket: Store too full to create data copy" << std::endl;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
message.setStorageId(origStoreId);
|
||||||
}
|
}
|
||||||
result = ownerQueue.sendMessage(dest.queueId, &message);
|
result = ownerQueue.sendMessage(dest.queueId, &message);
|
||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "PusTmFunnel.h"
|
#include "PusTmFunnel.h"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
#include "eive/definitions.h"
|
#include "eive/definitions.h"
|
||||||
#include "eive/objects.h"
|
#include "eive/objects.h"
|
||||||
#include "fsfw/ipc/CommandMessage.h"
|
#include "fsfw/ipc/CommandMessage.h"
|
||||||
@ -11,8 +13,8 @@
|
|||||||
#include "tmtc/pusIds.h"
|
#include "tmtc/pusIds.h"
|
||||||
|
|
||||||
PusTmFunnel::PusTmFunnel(TmFunnelBase::FunnelCfg cfg, StorageManagerIF &ramToFileStore,
|
PusTmFunnel::PusTmFunnel(TmFunnelBase::FunnelCfg cfg, StorageManagerIF &ramToFileStore,
|
||||||
TimeReaderIF &timeReader, SdCardMountedIF &sdcMan)
|
TimeReaderIF &timeReader)
|
||||||
: TmFunnelBase(cfg), ramToFileStore(ramToFileStore), timeReader(timeReader), sdcMan(sdcMan) {}
|
: TmFunnelBase(cfg), ramToFileStore(ramToFileStore), timeReader(timeReader) {}
|
||||||
|
|
||||||
PusTmFunnel::~PusTmFunnel() = default;
|
PusTmFunnel::~PusTmFunnel() = default;
|
||||||
|
|
||||||
@ -21,6 +23,13 @@ ReturnValue_t PusTmFunnel::performOperation(uint8_t) {
|
|||||||
ReturnValue_t result;
|
ReturnValue_t result;
|
||||||
TmTcMessage currentMessage;
|
TmTcMessage currentMessage;
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
|
if (saveSequenceCount) {
|
||||||
|
result = saveSequenceCountToFile();
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
sif::error << "PusTmFunnel: Storing sequence count to file has failed" << std::endl;
|
||||||
|
}
|
||||||
|
saveSequenceCount = false;
|
||||||
|
}
|
||||||
result = tmQueue->receiveMessage(¤tMessage);
|
result = tmQueue->receiveMessage(¤tMessage);
|
||||||
while (result == returnvalue::OK) {
|
while (result == returnvalue::OK) {
|
||||||
result = handleTmPacket(currentMessage);
|
result = handleTmPacket(currentMessage);
|
||||||
@ -59,7 +68,33 @@ ReturnValue_t PusTmFunnel::handleTmPacket(TmTcMessage &message) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
packet.setSequenceCount(sourceSequenceCount++);
|
packet.setSequenceCount(sourceSequenceCount++);
|
||||||
|
// NOTE: This only works because the limit value bit width is below 16 bits!
|
||||||
sourceSequenceCount = sourceSequenceCount % ccsds::LIMIT_SEQUENCE_COUNT;
|
sourceSequenceCount = sourceSequenceCount % ccsds::LIMIT_SEQUENCE_COUNT;
|
||||||
|
|
||||||
|
// Message type counter handling.
|
||||||
|
uint8_t service = packet.getService();
|
||||||
|
bool insertionFailed = false;
|
||||||
|
auto mapIter = msgCounterMap.find(service);
|
||||||
|
if (mapIter == msgCounterMap.end()) {
|
||||||
|
auto iterPair = msgCounterMap.emplace(service, 0);
|
||||||
|
if (iterPair.second) {
|
||||||
|
mapIter = iterPair.first;
|
||||||
|
} else {
|
||||||
|
// Should really never never happen but you never know..
|
||||||
|
insertionFailed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (not insertionFailed) {
|
||||||
|
packet.setMessageCount(mapIter->second);
|
||||||
|
// Sane overflow handling.
|
||||||
|
if (mapIter->second == std::numeric_limits<uint16_t>::max()) {
|
||||||
|
mapIter->second = 0;
|
||||||
|
} else {
|
||||||
|
mapIter->second++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-calculate CRC after changing the fields. This operation HAS to come last!
|
||||||
packet.updateErrorControl();
|
packet.updateErrorControl();
|
||||||
|
|
||||||
// Send to persistent TM store if the packet matches some filter.
|
// Send to persistent TM store if the packet matches some filter.
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
#include <mission/tmtc/PusTmRouteByFilterHelper.h>
|
#include <mission/tmtc/PusTmRouteByFilterHelper.h>
|
||||||
#include <mission/tmtc/TmFunnelBase.h>
|
#include <mission/tmtc/TmFunnelBase.h>
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "PersistentTmStore.h"
|
#include "PersistentTmStore.h"
|
||||||
@ -25,7 +27,7 @@
|
|||||||
class PusTmFunnel : public TmFunnelBase {
|
class PusTmFunnel : public TmFunnelBase {
|
||||||
public:
|
public:
|
||||||
PusTmFunnel(TmFunnelBase::FunnelCfg cfg, StorageManagerIF &ramToFileStore,
|
PusTmFunnel(TmFunnelBase::FunnelCfg cfg, StorageManagerIF &ramToFileStore,
|
||||||
TimeReaderIF &timeReader, SdCardMountedIF &sdcMan);
|
TimeReaderIF &timeReader);
|
||||||
[[nodiscard]] const char *getName() const override;
|
[[nodiscard]] const char *getName() const override;
|
||||||
~PusTmFunnel() override;
|
~PusTmFunnel() override;
|
||||||
|
|
||||||
@ -36,11 +38,10 @@ class PusTmFunnel : public TmFunnelBase {
|
|||||||
// Update TV stamp every 5 minutes
|
// Update TV stamp every 5 minutes
|
||||||
static constexpr dur_millis_t TV_UPDATE_INTERVAL_SECS = 60 * 5;
|
static constexpr dur_millis_t TV_UPDATE_INTERVAL_SECS = 60 * 5;
|
||||||
|
|
||||||
uint16_t sourceSequenceCount = 0;
|
std::map<uint8_t, uint16_t> msgCounterMap;
|
||||||
StorageManagerIF &ramToFileStore;
|
StorageManagerIF &ramToFileStore;
|
||||||
TimeReaderIF &timeReader;
|
TimeReaderIF &timeReader;
|
||||||
bool storesInitialized = false;
|
bool storesInitialized = false;
|
||||||
SdCardMountedIF &sdcMan;
|
|
||||||
PusTmRouteByFilterHelper persistentTmMap;
|
PusTmRouteByFilterHelper persistentTmMap;
|
||||||
|
|
||||||
ReturnValue_t handleTmPacket(TmTcMessage &message);
|
ReturnValue_t handleTmPacket(TmTcMessage &message);
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
#include <fsfw/tmtcservices/TmTcMessage.h>
|
#include <fsfw/tmtcservices/TmTcMessage.h>
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
#include "fsfw/ipc/QueueFactory.h"
|
#include "fsfw/ipc/QueueFactory.h"
|
||||||
|
|
||||||
TmFunnelBase::TmFunnelBase(FunnelCfg cfg)
|
TmFunnelBase::TmFunnelBase(FunnelCfg cfg)
|
||||||
@ -10,7 +14,10 @@ TmFunnelBase::TmFunnelBase(FunnelCfg cfg)
|
|||||||
tmStore(cfg.tmStore),
|
tmStore(cfg.tmStore),
|
||||||
ipcStore(cfg.ipcStore),
|
ipcStore(cfg.ipcStore),
|
||||||
tmQueue(QueueFactory::instance()->createMessageQueue(cfg.tmMsgDepth)),
|
tmQueue(QueueFactory::instance()->createMessageQueue(cfg.tmMsgDepth)),
|
||||||
liveDemux(*tmQueue) {}
|
liveDemux(*tmQueue),
|
||||||
|
sdcMan(cfg.sdcMan),
|
||||||
|
sequenceCounterFilename(cfg.sequenceCounterFilename),
|
||||||
|
saveSequenceCount(cfg.saveSequenceCount) {}
|
||||||
|
|
||||||
ReturnValue_t TmFunnelBase::demultiplexLivePackets(store_address_t origStoreId,
|
ReturnValue_t TmFunnelBase::demultiplexLivePackets(store_address_t origStoreId,
|
||||||
const uint8_t *tmData, size_t tmSize) {
|
const uint8_t *tmData, size_t tmSize) {
|
||||||
@ -27,3 +34,38 @@ void TmFunnelBase::addLiveDestination(const char *name,
|
|||||||
const AcceptsTelemetryIF &downlinkDestination, uint8_t vcid) {
|
const AcceptsTelemetryIF &downlinkDestination, uint8_t vcid) {
|
||||||
liveDemux.addDestination(name, downlinkDestination, vcid);
|
liveDemux.addDestination(name, downlinkDestination, vcid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReturnValue_t TmFunnelBase::initialize() {
|
||||||
|
using namespace std::filesystem;
|
||||||
|
// The filesystem should always be available at the start.. Let's assume it always is, otherwise
|
||||||
|
// we just live with a regular 0 initialization. It simplifies a lot.
|
||||||
|
std::error_code e;
|
||||||
|
path filePath =
|
||||||
|
path(path(sdcMan.getCurrentMountPrefix()) / path("conf") / path(sequenceCounterFilename));
|
||||||
|
if (exists(filePath, e)) {
|
||||||
|
std::ifstream ifile(filePath);
|
||||||
|
if (ifile.bad()) {
|
||||||
|
sif::error << "TmFunnelBase::initialize: Faulty file open for sequence counter initialization"
|
||||||
|
<< std::endl;
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
if (not(ifile >> sourceSequenceCount)) {
|
||||||
|
// Initialize to 0 in any case if reading a number failed.
|
||||||
|
sourceSequenceCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t TmFunnelBase::saveSequenceCountToFile() {
|
||||||
|
using namespace std::filesystem;
|
||||||
|
std::error_code e;
|
||||||
|
path filePath =
|
||||||
|
path(path(sdcMan.getCurrentMountPrefix()) / path("conf") / path(sequenceCounterFilename));
|
||||||
|
std::ofstream ofile(filePath);
|
||||||
|
if (ofile.bad()) {
|
||||||
|
return returnvalue::FAILED;
|
||||||
|
}
|
||||||
|
ofile << sourceSequenceCount << "\n";
|
||||||
|
return returnvalue::OK;
|
||||||
|
}
|
||||||
|
@ -6,25 +6,34 @@
|
|||||||
#include <fsfw/tmstorage/TmStoreFrontendSimpleIF.h>
|
#include <fsfw/tmstorage/TmStoreFrontendSimpleIF.h>
|
||||||
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
|
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
|
||||||
#include <fsfw/tmtcservices/TmTcMessage.h>
|
#include <fsfw/tmtcservices/TmTcMessage.h>
|
||||||
|
#include <mission/memory/SdCardMountedIF.h>
|
||||||
#include <mission/tmtc/PusLiveDemux.h>
|
#include <mission/tmtc/PusLiveDemux.h>
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class TmFunnelBase : public AcceptsTelemetryIF, public SystemObject {
|
class TmFunnelBase : public AcceptsTelemetryIF, public SystemObject {
|
||||||
public:
|
public:
|
||||||
struct FunnelCfg {
|
struct FunnelCfg {
|
||||||
FunnelCfg(object_id_t objId, const char* name, StorageManagerIF& tmStore,
|
FunnelCfg(object_id_t objId, const char* name, StorageManagerIF& tmStore,
|
||||||
StorageManagerIF& ipcStore, uint32_t tmMsgDepth)
|
StorageManagerIF& ipcStore, uint32_t tmMsgDepth, SdCardMountedIF& sdcMan,
|
||||||
|
const char* sequenceCounterFilename, std::atomic_bool& saveSequenceCount)
|
||||||
: objectId(objId),
|
: objectId(objId),
|
||||||
name(name),
|
name(name),
|
||||||
tmStore(tmStore),
|
tmStore(tmStore),
|
||||||
ipcStore(ipcStore),
|
ipcStore(ipcStore),
|
||||||
tmMsgDepth(tmMsgDepth) {}
|
tmMsgDepth(tmMsgDepth),
|
||||||
|
sdcMan(sdcMan),
|
||||||
|
sequenceCounterFilename(sequenceCounterFilename),
|
||||||
|
saveSequenceCount(saveSequenceCount) {}
|
||||||
object_id_t objectId;
|
object_id_t objectId;
|
||||||
const char* name;
|
const char* name;
|
||||||
StorageManagerIF& tmStore;
|
StorageManagerIF& tmStore;
|
||||||
StorageManagerIF& ipcStore;
|
StorageManagerIF& ipcStore;
|
||||||
uint32_t tmMsgDepth;
|
uint32_t tmMsgDepth;
|
||||||
|
SdCardMountedIF& sdcMan;
|
||||||
|
const char* sequenceCounterFilename;
|
||||||
|
std::atomic_bool& saveSequenceCount;
|
||||||
};
|
};
|
||||||
explicit TmFunnelBase(FunnelCfg cfg);
|
explicit TmFunnelBase(FunnelCfg cfg);
|
||||||
[[nodiscard]] MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const override;
|
[[nodiscard]] MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const override;
|
||||||
@ -32,6 +41,9 @@ class TmFunnelBase : public AcceptsTelemetryIF, public SystemObject {
|
|||||||
uint8_t vcid = 0);
|
uint8_t vcid = 0);
|
||||||
ReturnValue_t demultiplexLivePackets(store_address_t origStoreId, const uint8_t* tmData,
|
ReturnValue_t demultiplexLivePackets(store_address_t origStoreId, const uint8_t* tmData,
|
||||||
size_t tmSize);
|
size_t tmSize);
|
||||||
|
ReturnValue_t initialize() override;
|
||||||
|
|
||||||
|
ReturnValue_t saveSequenceCountToFile();
|
||||||
|
|
||||||
~TmFunnelBase() override;
|
~TmFunnelBase() override;
|
||||||
|
|
||||||
@ -41,6 +53,10 @@ class TmFunnelBase : public AcceptsTelemetryIF, public SystemObject {
|
|||||||
StorageManagerIF& ipcStore;
|
StorageManagerIF& ipcStore;
|
||||||
MessageQueueIF* tmQueue = nullptr;
|
MessageQueueIF* tmQueue = nullptr;
|
||||||
PusLiveDemux liveDemux;
|
PusLiveDemux liveDemux;
|
||||||
|
SdCardMountedIF& sdcMan;
|
||||||
|
const char* sequenceCounterFilename;
|
||||||
|
std::atomic_bool& saveSequenceCount;
|
||||||
|
uint16_t sourceSequenceCount = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* MISSION_TMTC_TMFUNNELBASE_H_ */
|
#endif /* MISSION_TMTC_TMFUNNELBASE_H_ */
|
||||||
|
2
tmtc
2
tmtc
@ -1 +1 @@
|
|||||||
Subproject commit 79060acfb688a8896cf56c27d83da14e5630f091
|
Subproject commit 18304c31fa423b1af6ff47764d4be81c7f20c8f2
|
@ -4,7 +4,7 @@ add_subdirectory(mocks)
|
|||||||
target_sources(${UNITTEST_NAME} PRIVATE
|
target_sources(${UNITTEST_NAME} PRIVATE
|
||||||
main.cpp
|
main.cpp
|
||||||
testEnvironment.cpp
|
testEnvironment.cpp
|
||||||
testStampInFilename.cpp
|
testGenericFilesystem.cpp
|
||||||
hdlcEncodingRw.cpp
|
hdlcEncodingRw.cpp
|
||||||
printChar.cpp
|
printChar.cpp
|
||||||
)
|
)
|
@ -19,116 +19,117 @@ CoreController::CoreController() {
|
|||||||
setCurrentBootCopy(xsc::CHIP_0, xsc::COPY_0);
|
setCurrentBootCopy(xsc::CHIP_0, xsc::COPY_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreController::performRebootFileHandling(bool recreateFile) {
|
void CoreController::performRebootWatchdogHandling(bool recreateFile) {
|
||||||
using namespace std;
|
using namespace std;
|
||||||
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.active) + REBOOT_FILE;
|
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.active) + REBOOT_WATCHDOG_FILE;
|
||||||
if (not std::filesystem::exists(path) or recreateFile) {
|
if (not std::filesystem::exists(path) or recreateFile) {
|
||||||
#if OBSW_VERBOSE_LEVEL >= 1
|
#if OBSW_VERBOSE_LEVEL >= 1
|
||||||
sif::info << "CoreController::performRebootFileHandling: Recreating reboot file" << std::endl;
|
sif::info << "CoreController::performRebootFileHandling: Recreating reboot file" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
rebootFile.enabled = true;
|
rebootWatchdogFile.enabled = true;
|
||||||
rebootFile.img00Cnt = 0;
|
rebootWatchdogFile.img00Cnt = 0;
|
||||||
rebootFile.img01Cnt = 0;
|
rebootWatchdogFile.img01Cnt = 0;
|
||||||
rebootFile.img10Cnt = 0;
|
rebootWatchdogFile.img10Cnt = 0;
|
||||||
rebootFile.img11Cnt = 0;
|
rebootWatchdogFile.img11Cnt = 0;
|
||||||
rebootFile.lastChip = xsc::Chip::CHIP_0;
|
rebootWatchdogFile.lastChip = xsc::Chip::CHIP_0;
|
||||||
rebootFile.lastCopy = xsc::Copy::COPY_0;
|
rebootWatchdogFile.lastCopy = xsc::Copy::COPY_0;
|
||||||
rebootFile.img00Lock = false;
|
rebootWatchdogFile.img00Lock = false;
|
||||||
rebootFile.img01Lock = false;
|
rebootWatchdogFile.img01Lock = false;
|
||||||
rebootFile.img10Lock = false;
|
rebootWatchdogFile.img10Lock = false;
|
||||||
rebootFile.img11Lock = false;
|
rebootWatchdogFile.img11Lock = false;
|
||||||
rebootFile.mechanismNextChip = xsc::Chip::NO_CHIP;
|
rebootWatchdogFile.mechanismNextChip = xsc::Chip::NO_CHIP;
|
||||||
rebootFile.mechanismNextCopy = xsc::Copy::NO_COPY;
|
rebootWatchdogFile.mechanismNextCopy = xsc::Copy::NO_COPY;
|
||||||
rebootFile.bootFlag = false;
|
rebootWatchdogFile.bootFlag = false;
|
||||||
rewriteRebootFile(rebootFile);
|
rewriteRebootWatchdogFile(rebootWatchdogFile);
|
||||||
} else {
|
} else {
|
||||||
if (not parseRebootFile(path, rebootFile)) {
|
if (not parseRebootWatchdogFile(path, rebootWatchdogFile)) {
|
||||||
performRebootFileHandling(true);
|
performRebootWatchdogHandling(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CURRENT_CHIP == xsc::CHIP_0) {
|
if (CURRENT_CHIP == xsc::CHIP_0) {
|
||||||
if (CURRENT_COPY == xsc::COPY_0) {
|
if (CURRENT_COPY == xsc::COPY_0) {
|
||||||
rebootFile.img00Cnt++;
|
rebootWatchdogFile.img00Cnt++;
|
||||||
} else {
|
} else {
|
||||||
rebootFile.img01Cnt++;
|
rebootWatchdogFile.img01Cnt++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (CURRENT_COPY == xsc::COPY_0) {
|
if (CURRENT_COPY == xsc::COPY_0) {
|
||||||
rebootFile.img10Cnt++;
|
rebootWatchdogFile.img10Cnt++;
|
||||||
} else {
|
} else {
|
||||||
rebootFile.img11Cnt++;
|
rebootWatchdogFile.img11Cnt++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rebootFile.bootFlag) {
|
if (rebootWatchdogFile.bootFlag) {
|
||||||
// Trigger event to inform ground that a reboot was triggered
|
// 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;
|
||||||
uint32_t p2 = rebootFile.img00Cnt << 24 | rebootFile.img01Cnt << 16 | rebootFile.img10Cnt << 8 |
|
uint32_t p2 = rebootWatchdogFile.img00Cnt << 24 | rebootWatchdogFile.img01Cnt << 16 |
|
||||||
rebootFile.img11Cnt;
|
rebootWatchdogFile.img10Cnt << 8 | rebootWatchdogFile.img11Cnt;
|
||||||
triggerEvent(REBOOT_MECHANISM_TRIGGERED, p1, p2);
|
triggerEvent(REBOOT_MECHANISM_TRIGGERED, p1, p2);
|
||||||
// Clear the boot flag
|
// Clear the boot flag
|
||||||
rebootFile.bootFlag = false;
|
rebootWatchdogFile.bootFlag = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rebootFile.mechanismNextChip != xsc::NO_CHIP and
|
if (rebootWatchdogFile.mechanismNextChip != xsc::NO_CHIP and
|
||||||
rebootFile.mechanismNextCopy != xsc::NO_COPY) {
|
rebootWatchdogFile.mechanismNextCopy != xsc::NO_COPY) {
|
||||||
if (CURRENT_CHIP != rebootFile.mechanismNextChip or
|
if (CURRENT_CHIP != rebootWatchdogFile.mechanismNextChip or
|
||||||
CURRENT_COPY != rebootFile.mechanismNextCopy) {
|
CURRENT_COPY != rebootWatchdogFile.mechanismNextCopy) {
|
||||||
std::string infoString = std::to_string(rebootFile.mechanismNextChip) + " " +
|
std::string infoString = std::to_string(rebootWatchdogFile.mechanismNextChip) + " " +
|
||||||
std::to_string(rebootFile.mechanismNextCopy);
|
std::to_string(rebootWatchdogFile.mechanismNextCopy);
|
||||||
sif::warning << "CoreController::performRebootFileHandling: Expected to be on image "
|
sif::warning << "CoreController::performRebootFileHandling: Expected to be on image "
|
||||||
<< infoString << " but currently on other image. Locking " << infoString
|
<< infoString << " but currently on other image. Locking " << infoString
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
// Firmware or other component might be corrupt and we are on another image then the target
|
// 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.
|
// image specified by the mechanism. We can't really trust the target image anymore.
|
||||||
// Lock it for now
|
// Lock it for now
|
||||||
if (rebootFile.mechanismNextChip == xsc::CHIP_0) {
|
if (rebootWatchdogFile.mechanismNextChip == xsc::CHIP_0) {
|
||||||
if (rebootFile.mechanismNextCopy == xsc::COPY_0) {
|
if (rebootWatchdogFile.mechanismNextCopy == xsc::COPY_0) {
|
||||||
rebootFile.img00Lock = true;
|
rebootWatchdogFile.img00Lock = true;
|
||||||
} else {
|
} else {
|
||||||
rebootFile.img01Lock = true;
|
rebootWatchdogFile.img01Lock = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (rebootFile.mechanismNextCopy == xsc::COPY_0) {
|
if (rebootWatchdogFile.mechanismNextCopy == xsc::COPY_0) {
|
||||||
rebootFile.img10Lock = true;
|
rebootWatchdogFile.img10Lock = true;
|
||||||
} else {
|
} else {
|
||||||
rebootFile.img11Lock = true;
|
rebootWatchdogFile.img11Lock = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rebootFile.lastChip = CURRENT_CHIP;
|
rebootWatchdogFile.lastChip = CURRENT_CHIP;
|
||||||
rebootFile.lastCopy = CURRENT_COPY;
|
rebootWatchdogFile.lastCopy = CURRENT_COPY;
|
||||||
// Only reboot if the reboot functionality is enabled.
|
// Only reboot if the reboot functionality is enabled.
|
||||||
// The handler will still increment the boot counts
|
// 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
|
// Reboot to other image
|
||||||
bool doReboot = false;
|
bool doReboot = false;
|
||||||
xsc::Chip tgtChip = xsc::NO_CHIP;
|
xsc::Chip tgtChip = xsc::NO_CHIP;
|
||||||
xsc::Copy tgtCopy = xsc::NO_COPY;
|
xsc::Copy tgtCopy = xsc::NO_COPY;
|
||||||
determineAndExecuteReboot(rebootFile, doReboot, tgtChip, tgtCopy);
|
determineAndExecuteReboot(rebootWatchdogFile, doReboot, tgtChip, tgtCopy);
|
||||||
if (doReboot) {
|
if (doReboot) {
|
||||||
rebootFile.bootFlag = true;
|
rebootWatchdogFile.bootFlag = true;
|
||||||
#if OBSW_VERBOSE_LEVEL >= 1
|
#if OBSW_VERBOSE_LEVEL >= 1
|
||||||
sif::info << "Boot counter for image " << CURRENT_CHIP << " " << CURRENT_COPY
|
sif::info << "Boot counter for image " << CURRENT_CHIP << " " << CURRENT_COPY
|
||||||
<< " too high. Rebooting to " << tgtChip << " " << tgtCopy << std::endl;
|
<< " too high. Rebooting to " << tgtChip << " " << tgtCopy << std::endl;
|
||||||
#endif
|
#endif
|
||||||
rebootFile.mechanismNextChip = tgtChip;
|
rebootWatchdogFile.mechanismNextChip = tgtChip;
|
||||||
rebootFile.mechanismNextCopy = tgtCopy;
|
rebootWatchdogFile.mechanismNextCopy = tgtCopy;
|
||||||
rewriteRebootFile(rebootFile);
|
rewriteRebootWatchdogFile(rebootWatchdogFile);
|
||||||
xsc_boot_copy(static_cast<xsc_libnor_chip_t>(tgtChip),
|
xsc_boot_copy(static_cast<xsc_libnor_chip_t>(tgtChip),
|
||||||
static_cast<xsc_libnor_copy_t>(tgtCopy));
|
static_cast<xsc_libnor_copy_t>(tgtCopy));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rebootFile.mechanismNextChip = xsc::NO_CHIP;
|
rebootWatchdogFile.mechanismNextChip = xsc::NO_CHIP;
|
||||||
rebootFile.mechanismNextCopy = xsc::NO_COPY;
|
rebootWatchdogFile.mechanismNextCopy = xsc::NO_COPY;
|
||||||
}
|
}
|
||||||
rewriteRebootFile(rebootFile);
|
rewriteRebootWatchdogFile(rebootWatchdogFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot,
|
void CoreController::determineAndExecuteReboot(RebootWatchdogFile &rf, bool &needsReboot,
|
||||||
xsc::Chip &tgtChip, xsc::Copy &tgtCopy) {
|
xsc::Chip &tgtChip, xsc::Copy &tgtCopy) {
|
||||||
tgtChip = xsc::CHIP_0;
|
tgtChip = xsc::CHIP_0;
|
||||||
tgtCopy = xsc::COPY_0;
|
tgtCopy = xsc::COPY_0;
|
||||||
@ -217,7 +218,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;
|
using namespace std;
|
||||||
std::string selfMatch;
|
std::string selfMatch;
|
||||||
if (CURRENT_CHIP == xsc::CHIP_0) {
|
if (CURRENT_CHIP == xsc::CHIP_0) {
|
||||||
@ -400,34 +401,34 @@ bool CoreController::parseRebootFile(std::string path, RebootFile &rf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CoreController::resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy) {
|
void CoreController::resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy) {
|
||||||
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.active) + REBOOT_FILE;
|
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.active) + REBOOT_WATCHDOG_FILE;
|
||||||
// Disable the reboot file mechanism
|
// Disable the reboot file mechanism
|
||||||
parseRebootFile(path, rebootFile);
|
parseRebootWatchdogFile(path, rebootWatchdogFile);
|
||||||
if (tgtChip == xsc::ALL_CHIP and tgtCopy == xsc::ALL_COPY) {
|
if (tgtChip == xsc::ALL_CHIP and tgtCopy == xsc::ALL_COPY) {
|
||||||
rebootFile.img00Cnt = 0;
|
rebootWatchdogFile.img00Cnt = 0;
|
||||||
rebootFile.img01Cnt = 0;
|
rebootWatchdogFile.img01Cnt = 0;
|
||||||
rebootFile.img10Cnt = 0;
|
rebootWatchdogFile.img10Cnt = 0;
|
||||||
rebootFile.img11Cnt = 0;
|
rebootWatchdogFile.img11Cnt = 0;
|
||||||
} else {
|
} else {
|
||||||
if (tgtChip == xsc::CHIP_0) {
|
if (tgtChip == xsc::CHIP_0) {
|
||||||
if (tgtCopy == xsc::COPY_0) {
|
if (tgtCopy == xsc::COPY_0) {
|
||||||
rebootFile.img00Cnt = 0;
|
rebootWatchdogFile.img00Cnt = 0;
|
||||||
} else {
|
} else {
|
||||||
rebootFile.img01Cnt = 0;
|
rebootWatchdogFile.img01Cnt = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (tgtCopy == xsc::COPY_0) {
|
if (tgtCopy == xsc::COPY_0) {
|
||||||
rebootFile.img10Cnt = 0;
|
rebootWatchdogFile.img10Cnt = 0;
|
||||||
} else {
|
} else {
|
||||||
rebootFile.img11Cnt = 0;
|
rebootWatchdogFile.img11Cnt = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rewriteRebootFile(rebootFile);
|
rewriteRebootWatchdogFile(rebootWatchdogFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreController::rewriteRebootFile(RebootFile file) {
|
void CoreController::rewriteRebootWatchdogFile(RebootWatchdogFile file) {
|
||||||
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.active) + REBOOT_FILE;
|
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.active) + REBOOT_WATCHDOG_FILE;
|
||||||
std::ofstream rebootFile(path);
|
std::ofstream rebootFile(path);
|
||||||
if (rebootFile.is_open()) {
|
if (rebootFile.is_open()) {
|
||||||
// Initiate reboot file first. Reboot handling will be on on initialization
|
// Initiate reboot file first. Reboot handling will be on on initialization
|
||||||
@ -450,15 +451,15 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_
|
|||||||
if (size < 1) {
|
if (size < 1) {
|
||||||
return HasActionsIF::INVALID_PARAMETERS;
|
return HasActionsIF::INVALID_PARAMETERS;
|
||||||
}
|
}
|
||||||
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.active) + REBOOT_FILE;
|
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.active) + REBOOT_WATCHDOG_FILE;
|
||||||
// Disable the reboot file mechanism
|
// Disable the reboot file mechanism
|
||||||
parseRebootFile(path, rebootFile);
|
parseRebootWatchdogFile(path, rebootWatchdogFile);
|
||||||
if (data[0] == 0) {
|
if (data[0] == 0) {
|
||||||
rebootFile.enabled = false;
|
rebootWatchdogFile.enabled = false;
|
||||||
rewriteRebootFile(rebootFile);
|
rewriteRebootWatchdogFile(rebootWatchdogFile);
|
||||||
} else if (data[0] == 1) {
|
} else if (data[0] == 1) {
|
||||||
rebootFile.enabled = true;
|
rebootWatchdogFile.enabled = true;
|
||||||
rewriteRebootFile(rebootFile);
|
rewriteRebootWatchdogFile(rebootWatchdogFile);
|
||||||
} else {
|
} else {
|
||||||
return HasActionsIF::INVALID_PARAMETERS;
|
return HasActionsIF::INVALID_PARAMETERS;
|
||||||
}
|
}
|
||||||
@ -490,11 +491,11 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_
|
|||||||
if (size < 1) {
|
if (size < 1) {
|
||||||
return HasActionsIF::INVALID_PARAMETERS;
|
return HasActionsIF::INVALID_PARAMETERS;
|
||||||
}
|
}
|
||||||
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.active) + REBOOT_FILE;
|
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.active) + REBOOT_WATCHDOG_FILE;
|
||||||
// Disable the reboot file mechanism
|
// Disable the reboot file mechanism
|
||||||
parseRebootFile(path, rebootFile);
|
parseRebootWatchdogFile(path, rebootWatchdogFile);
|
||||||
rebootFile.maxCount = data[0];
|
rebootWatchdogFile.maxCount = data[0];
|
||||||
rewriteRebootFile(rebootFile);
|
rewriteRebootWatchdogFile(rebootWatchdogFile);
|
||||||
return HasActionsIF::EXECUTION_FINISHED;
|
return HasActionsIF::EXECUTION_FINISHED;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
@ -504,23 +505,23 @@ ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CoreController::setRebootMechanismLock(bool lock, xsc::Chip tgtChip, xsc::Copy tgtCopy) {
|
void CoreController::setRebootMechanismLock(bool lock, xsc::Chip tgtChip, xsc::Copy tgtCopy) {
|
||||||
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.active) + REBOOT_FILE;
|
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.active) + REBOOT_WATCHDOG_FILE;
|
||||||
// Disable the reboot file mechanism
|
// Disable the reboot file mechanism
|
||||||
parseRebootFile(path, rebootFile);
|
parseRebootWatchdogFile(path, rebootWatchdogFile);
|
||||||
if (tgtChip == xsc::CHIP_0) {
|
if (tgtChip == xsc::CHIP_0) {
|
||||||
if (tgtCopy == xsc::COPY_0) {
|
if (tgtCopy == xsc::COPY_0) {
|
||||||
rebootFile.img00Lock = lock;
|
rebootWatchdogFile.img00Lock = lock;
|
||||||
} else {
|
} else {
|
||||||
rebootFile.img01Lock = lock;
|
rebootWatchdogFile.img01Lock = lock;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (tgtCopy == xsc::COPY_0) {
|
if (tgtCopy == xsc::COPY_0) {
|
||||||
rebootFile.img10Lock = lock;
|
rebootWatchdogFile.img10Lock = lock;
|
||||||
} else {
|
} else {
|
||||||
rebootFile.img11Lock = lock;
|
rebootWatchdogFile.img11Lock = lock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rewriteRebootFile(rebootFile);
|
rewriteRebootWatchdogFile(rebootWatchdogFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoreController::setCurrentBootCopy(xsc::Chip chip, xsc::Copy copy) {
|
void CoreController::setCurrentBootCopy(xsc::Chip chip, xsc::Copy copy) {
|
||||||
|
@ -14,7 +14,7 @@ enum Copy : int { COPY_0, COPY_1, NO_COPY, SELF_COPY, ALL_COPY };
|
|||||||
|
|
||||||
} // namespace xsc
|
} // namespace xsc
|
||||||
|
|
||||||
struct RebootFile {
|
struct RebootWatchdogFile {
|
||||||
static constexpr uint8_t DEFAULT_MAX_BOOT_CNT = 10;
|
static constexpr uint8_t DEFAULT_MAX_BOOT_CNT = 10;
|
||||||
|
|
||||||
bool enabled = true;
|
bool enabled = true;
|
||||||
@ -39,7 +39,7 @@ class SdCardManager;
|
|||||||
|
|
||||||
class CoreController {
|
class CoreController {
|
||||||
public:
|
public:
|
||||||
static constexpr char REBOOT_FILE[] = "/conf/reboot.txt";
|
static constexpr char REBOOT_WATCHDOG_FILE[] = "/conf/reboot.txt";
|
||||||
//! [EXPORT] : [COMMENT] The reboot mechanism was triggered.
|
//! [EXPORT] : [COMMENT] The reboot mechanism was triggered.
|
||||||
//! P1: First 16 bits: Last Chip, Last 16 bits: Last Copy,
|
//! P1: First 16 bits: Last Chip, Last 16 bits: Last Copy,
|
||||||
//! P2: Each byte is the respective reboot count for the slots
|
//! P2: Each byte is the respective reboot count for the slots
|
||||||
@ -57,13 +57,13 @@ class CoreController {
|
|||||||
static void setCurrentBootCopy(xsc::Chip chip, xsc::Copy copy);
|
static void setCurrentBootCopy(xsc::Chip chip, xsc::Copy copy);
|
||||||
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||||
const uint8_t* data, size_t size);
|
const uint8_t* data, size_t size);
|
||||||
void performRebootFileHandling(bool recreateFile);
|
void performRebootWatchdogHandling(bool recreateFile);
|
||||||
void determineAndExecuteReboot(RebootFile& rf, bool& needsReboot, xsc::Chip& tgtChip,
|
void determineAndExecuteReboot(RebootWatchdogFile& rf, bool& needsReboot, xsc::Chip& tgtChip,
|
||||||
xsc::Copy& tgtCopy);
|
xsc::Copy& tgtCopy);
|
||||||
void setRebootMechanismLock(bool lock, xsc::Chip tgtChip, xsc::Copy tgtCopy);
|
void setRebootMechanismLock(bool lock, xsc::Chip tgtChip, xsc::Copy tgtCopy);
|
||||||
void resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy);
|
void resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy);
|
||||||
bool parseRebootFile(std::string path, RebootFile& file);
|
bool parseRebootWatchdogFile(std::string path, RebootWatchdogFile& file);
|
||||||
void rewriteRebootFile(RebootFile file);
|
void rewriteRebootWatchdogFile(RebootWatchdogFile file);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct SdFsmParams {
|
struct SdFsmParams {
|
||||||
@ -74,6 +74,6 @@ class CoreController {
|
|||||||
} sdInfo;
|
} sdInfo;
|
||||||
|
|
||||||
SdCardManager* sdcMan = nullptr;
|
SdCardManager* sdcMan = nullptr;
|
||||||
RebootFile rebootFile = {};
|
RebootWatchdogFile rebootWatchdogFile = {};
|
||||||
bool doPerformRebootFileHandling = true;
|
bool doPerformRebootFileHandling = true;
|
||||||
};
|
};
|
@ -27,7 +27,7 @@ void factory(void* args) {
|
|||||||
new HouseKeepingMock();
|
new HouseKeepingMock();
|
||||||
eventManager = new EventManagerMock();
|
eventManager = new EventManagerMock();
|
||||||
new HealthTable(objects::HEALTH_TABLE);
|
new HealthTable(objects::HEALTH_TABLE);
|
||||||
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER);
|
new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER, 5, false, 60.0);
|
||||||
new CdsShortTimeStamper(objects::TIME_STAMPER);
|
new CdsShortTimeStamper(objects::TIME_STAMPER);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
43
unittest/testGenericFilesystem.cpp
Normal file
43
unittest/testGenericFilesystem.cpp
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
|
||||||
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
#include <cinttypes>
|
||||||
|
|
||||||
|
#include "fsfw/timemanager/Clock.h"
|
||||||
|
|
||||||
|
uint8_t extractSuffix(const std::string& pathStr) {
|
||||||
|
std::string numberStr;
|
||||||
|
// Find the position of the dot at the end of the file path
|
||||||
|
size_t dotPos = pathStr.find_last_of('.');
|
||||||
|
if (dotPos != std::string::npos && dotPos < pathStr.length() - 1) {
|
||||||
|
// Extract the substring after the dot
|
||||||
|
numberStr = pathStr.substr(dotPos + 1);
|
||||||
|
}
|
||||||
|
int number = std::stoi(numberStr);
|
||||||
|
if (number < 0 or number > std::numeric_limits<uint8_t>::max()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return static_cast<uint8_t>(number);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Stamp in Filename", "[Stamp In Filename]") {
|
||||||
|
Clock::TimeOfDay_t tod;
|
||||||
|
std::string baseName = "verif";
|
||||||
|
std::string pathStr = "verif_2022-05-25T16:55:23Z.bin";
|
||||||
|
unsigned int underscorePos = pathStr.find_last_of('_');
|
||||||
|
std::string stampStr = pathStr.substr(underscorePos + 1);
|
||||||
|
float seconds = 0.0;
|
||||||
|
char* prefix = nullptr;
|
||||||
|
int count =
|
||||||
|
sscanf(stampStr.c_str(),
|
||||||
|
"%4" SCNu32 "-%2" SCNu32 "-%2" SCNu32 "T%2" SCNu32 ":%2" SCNu32 ":%2" SCNu32 "Z",
|
||||||
|
&tod.year, &tod.month, &tod.day, &tod.hour, &tod.minute, &tod.second);
|
||||||
|
static_cast<void>(count);
|
||||||
|
CHECK(count == 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Suffix Extraction") {
|
||||||
|
std::string pathStr = "/mnt/sd0/tm/hk/hk-some-stamp.bin.0";
|
||||||
|
CHECK(extractSuffix(pathStr) == 0);
|
||||||
|
pathStr = "/mnt/sd0/tm/hk/hk-some-stamp.bin.2";
|
||||||
|
CHECK(extractSuffix(pathStr) == 2);
|
||||||
|
}
|
@ -1,21 +0,0 @@
|
|||||||
|
|
||||||
#include <catch2/catch_test_macros.hpp>
|
|
||||||
#include <cinttypes>
|
|
||||||
|
|
||||||
#include "fsfw/timemanager/Clock.h"
|
|
||||||
|
|
||||||
TEST_CASE("Stamp in Filename", "[Stamp In Filename]") {
|
|
||||||
Clock::TimeOfDay_t tod;
|
|
||||||
std::string baseName = "verif";
|
|
||||||
std::string pathStr = "verif_2022-05-25T16:55:23Z.bin";
|
|
||||||
unsigned int underscorePos = pathStr.find_last_of('_');
|
|
||||||
std::string stampStr = pathStr.substr(underscorePos + 1);
|
|
||||||
float seconds = 0.0;
|
|
||||||
char* prefix = nullptr;
|
|
||||||
int count =
|
|
||||||
sscanf(stampStr.c_str(),
|
|
||||||
"%4" SCNu32 "-%2" SCNu32 "-%2" SCNu32 "T%2" SCNu32 ":%2" SCNu32 ":%2" SCNu32 "Z",
|
|
||||||
&tod.year, &tod.month, &tod.day, &tod.hour, &tod.minute, &tod.second);
|
|
||||||
static_cast<void>(count);
|
|
||||||
CHECK(count == 6);
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user