Compare commits

..

47 Commits

Author SHA1 Message Date
60922ccc0d Merge pull request 'prepare patch release' (#901) from prep-patch-release into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #901
2024-06-05 13:29:59 +02:00
3ec0509bd4 prepare patch release
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
2024-06-05 13:28:08 +02:00
a73c36c237 Merge pull request 'MPSoC Update Retry Logic' (#900) from supv-retry-logic into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #900
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2024-06-05 13:27:18 +02:00
5dd0c2a5cb let's not do that for now..
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2024-06-05 12:47:17 +02:00
1f8dc67922 some minor improvements
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2024-06-05 12:36:31 +02:00
e43a86432b start adding re-try logic for SUPV
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2024-06-04 15:10:54 +02:00
467ee0028a Merge pull request 'PLOC SUPV bugfix' (#898) from ploc-supv-bugfix into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #898
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2024-05-29 10:38:15 +02:00
98a92a6b88 Merge remote-tracking branch 'origin/main' into ploc-supv-bugfix
Some checks are pending
EIVE/eive-obsw/pipeline/pr-main Build queued...
2024-05-29 10:13:52 +02:00
e1f2514596 Merge pull request 'Fix MEKF Inits' (#896) from fix-mekf-inits into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #896
Reviewed-by: Robin Müller <muellerr@irs.uni-stuttgart.de>
2024-05-29 10:12:35 +02:00
f255feb819 Merge remote-tracking branch 'origin/main' into fix-mekf-inits 2024-05-29 10:11:53 +02:00
6d27da4939 Merge pull request 'small fix for MPSoC transition failure' (#897) from transition-failure-fix into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #897
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2024-05-29 10:11:01 +02:00
a3ac2505fe small tweak
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2024-05-28 15:38:16 +02:00
6350e0db0a changelog
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2024-05-28 15:36:49 +02:00
db9e83cbc8 PLOC SUPV bugfix
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2024-05-28 15:33:13 +02:00
42ae9eafb7 bump tmtc
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2024-05-23 14:45:18 +02:00
0475ab872d changelog
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2024-05-23 14:23:16 +02:00
225d037c66 small fix for MPSoC transition failure
Some checks are pending
EIVE/eive-obsw/pipeline/head Build queued...
2024-05-23 14:22:07 +02:00
aa5a148800 changelog
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2024-05-15 11:07:46 +02:00
4720ab9a35 corrected str sigma
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2024-05-15 11:07:12 +02:00
ba219fbe7d changelog
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2024-05-15 10:05:32 +02:00
32271a98ff go home compiler, you're drunk
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
2024-05-15 10:04:04 +02:00
6025ea5663 fixed ub with initalization 2024-05-14 15:35:20 +02:00
5af43ca29b Merge pull request 'prep v8.0.0' (#895) from prep_v8.0.0 into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #895
2024-05-13 14:19:59 +02:00
822df9658f prep v8.0.0
Some checks are pending
EIVE/eive-obsw/pipeline/head Build queued...
EIVE/eive-obsw/pipeline/pr-main Build started...
2024-05-13 14:08:35 +02:00
765e3d6b5b Merge pull request 'MPSoC Fixes' (#894) from mpsoc-fixes into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #894
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2024-05-13 14:03:11 +02:00
0b3c928886 combining those is acutally problematic..
Some checks are pending
EIVE/eive-obsw/pipeline/head Build started...
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2024-05-08 11:11:21 +02:00
73279a0bf3 minor fix for periodic HK generation
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2024-05-08 10:54:24 +02:00
4559d24c62 changelog
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2024-05-08 10:04:34 +02:00
b54f8e7738 some fixes for MPSoC 2024-05-08 10:03:32 +02:00
6bb12f28a1 Merge pull request 'MPSoC Overhaul' (#892) from mpsoc-overhaul into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #892
Reviewed-by: Marius Eggert <eggertm@irs.uni-stuttgart.de>
2024-05-06 14:20:46 +02:00
7e8d995b52 changelog and tmtc 2024-05-06 14:20:13 +02:00
215f2189a6 better name for split file command
Some checks are pending
EIVE/eive-obsw/pipeline/pr-main Build queued...
2024-05-06 14:17:25 +02:00
8103b2fa0d events
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2024-05-06 13:48:32 +02:00
b579cd86c1 make marius extremely happy
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2024-05-06 13:30:28 +02:00
4fdec7a74c impl proper NORMAL mode for MPSoC
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2024-05-06 13:19:15 +02:00
744a94704c removed TODOs which are done
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2024-05-02 15:42:14 +02:00
f7f14ff021 Merge branch 'main' into mpsoc-overhaul
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2024-04-30 15:57:34 +02:00
fe729f1df0 Merge pull request 'Fix Target Rotation Rate' (#893) from tgt-rot-rate-fix into main
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
Reviewed-on: #893
Reviewed-by: Robin Müller <muellerr@irs.uni-stuttgart.de>
2024-04-30 15:52:05 +02:00
7734d1066a Merge branch 'main' into tgt-rot-rate-fix 2024-04-30 15:51:39 +02:00
4a0acbf158 further reduce printout
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2024-04-30 15:37:53 +02:00
65476f4c98 reduce printouts
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2024-04-30 15:18:15 +02:00
aa2bfb7d0e Re-work MPSoC handler module
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2024-04-30 15:14:22 +02:00
fa01afe0fa fixed build after EM build was created
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
2024-04-30 11:37:46 +02:00
a6ce06e3f5 Merge branch 'main' into tgt-rot-rate-fix
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2024-04-29 11:47:07 +02:00
75070b5e66 i am smart
All checks were successful
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2024-04-29 10:42:52 +02:00
26341743a8 changelog
All checks were successful
EIVE/eive-obsw/pipeline/head This commit looks good
EIVE/eive-obsw/pipeline/pr-main This commit looks good
2024-04-29 10:26:12 +02:00
7c10f4b1cd fix calculation of target rotation 2024-04-29 10:24:53 +02:00
30 changed files with 564 additions and 304 deletions

View File

@@ -16,9 +16,42 @@ will consitute of a breaking change warranting a new major release:
# [unreleased] # [unreleased]
# [v8.1.1] 2024-06-05
## Added
- PLOC SUPV MPSoC update re-try logic for the `WRITE_MEMORY` command. These packets form > 98%
of all packets required for a software update, but the update mechanism is not tolerant against
occasional glitches on the RS485 communication to the PLOC SUPV. A simple re-try mechanism which
tries to re-attempt packet handling up to three times for those packets is introduced.
# [v8.1.0] 2024-05-29
## Fixed
- Small fix for transition failure handling of the MPSoC when the `START_MPSOC` action command
to the supervisor fails.
- Fixed inits of arrays within the `MEKF` not being zeros.
- Important bugfix for PLOC SUPV: The SUPV previously was able to steal packets from the special
communication helper, for example during software updates.
- Corrected sigma of STR for `MEKF`.
## Added
- Added new command to cancel the PLOC SUPV special communication helper.
# [v8.0.0] 2024-05-13
- `eive-tmtc` v7.0.0
## Fixed
- Fixed calculation for target rotation rate during pointing modes.
- Possible fix for MPSoC file read algorithm.
## Changed ## Changed
- Reworked MPSoC handler to be compatible to new MPSoC software image and use - Reworked MPSoC handler to be compatible to new MPSoC software image and use
new device handler base class. This should increase the reliability of the communication new device handler base class. This should increase the reliability of the communication
significantly. significantly.
- MPSoC device modes IDLE, SNAPSHOT and REPLAY are now modelled using submodes. - MPSoC device modes IDLE, SNAPSHOT and REPLAY are now modelled using submodes.
@@ -32,6 +65,8 @@ will consitute of a breaking change warranting a new major release:
# [v7.8.1] 2024-04-11 # [v7.8.1] 2024-04-11
## Fixed
- Reverted fix for wrong order in quaternion multiplication for computation of the error quaternion. - Reverted fix for wrong order in quaternion multiplication for computation of the error quaternion.
# [v7.8.0] 2024-04-10 # [v7.8.0] 2024-04-10
@@ -42,7 +77,7 @@ will consitute of a breaking change warranting a new major release:
- All pointing laws are now allowed to use the `MEKF` per default. - All pointing laws are now allowed to use the `MEKF` per default.
- Changed limits in `PWR Controller`. - Changed limits in `PWR Controller`.
- PUS time service: Now dumps the time before and after relative timeshift or setting absolute time - PUS time service: Now dumps the time before and after relative timeshift or setting absolute time
- The `GPS Controller` does not set itself to `OFF` anymore, if it has not detected a valid fix for - The `GPS Controller` does not set itself to `OFF` anymore, if it has not detected a valid fix for
some time. Instead it attempts to reset both GNSS devices once. some time. Instead it attempts to reset both GNSS devices once.
- The maximum time to reach a fix is shortened from 30min to 15min. - The maximum time to reach a fix is shortened from 30min to 15min.
- The time the reset pin of the GNSS devices is pulled is prolonged from 5ms to 10s. - The time the reset pin of the GNSS devices is pulled is prolonged from 5ms to 10s.
@@ -51,7 +86,7 @@ will consitute of a breaking change warranting a new major release:
of the controller is changed. As arguments it now displays the new fix and the numer of fix changes of the controller is changed. As arguments it now displays the new fix and the numer of fix changes
missed. missed.
- The number of satellites seen and used is reset to 0, in case they are set to invalid. - The number of satellites seen and used is reset to 0, in case they are set to invalid.
- Altitude, latitude and longitude messages are not checked anymore, in case the mode message was - Altitude, latitude and longitude messages are not checked anymore, in case the mode message was
already invalid. already invalid.
## Added ## Added
@@ -265,7 +300,7 @@ will consitute of a breaking change warranting a new major release:
- `ACS Controller` now has the function `performAttitudeControl` which is called prior to passing - `ACS Controller` now has the function `performAttitudeControl` which is called prior to passing
on to the relevant mode functions. It handles all telemetry relevant functions, which were on to the relevant mode functions. It handles all telemetry relevant functions, which were
always called, regardless of the mode. always called, regardless of the mode.
## Added ## Added
- Higher ACS modes can now be entered without a running `MEKF`. Higher modes will collect their - Higher ACS modes can now be entered without a running `MEKF`. Higher modes will collect their

View File

@@ -10,8 +10,8 @@
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.13)
set(OBSW_VERSION_MAJOR 8) set(OBSW_VERSION_MAJOR 8)
set(OBSW_VERSION_MINOR 0) set(OBSW_VERSION_MINOR 1)
set(OBSW_VERSION_REVISION 0) set(OBSW_VERSION_REVISION 1)
# set(CMAKE_VERBOSE TRUE) # set(CMAKE_VERBOSE TRUE)

View File

@@ -1,7 +1,7 @@
/** /**
* @brief Auto-generated event translation file. Contains 324 translations. * @brief Auto-generated event translation file. Contains 325 translations.
* @details * @details
* Generated on: 2024-04-17 11:22:10 * Generated on: 2024-05-06 13:47:38
*/ */
#include "translateEvents.h" #include "translateEvents.h"
@@ -142,6 +142,7 @@ const char *MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH_STRING = "MPSOC_HANDLER_SEQUEN
const char *MPSOC_SHUTDOWN_FAILED_STRING = "MPSOC_SHUTDOWN_FAILED"; const char *MPSOC_SHUTDOWN_FAILED_STRING = "MPSOC_SHUTDOWN_FAILED";
const char *SUPV_NOT_ON_STRING = "SUPV_NOT_ON"; const char *SUPV_NOT_ON_STRING = "SUPV_NOT_ON";
const char *SUPV_REPLY_TIMEOUT_STRING = "SUPV_REPLY_TIMEOUT"; const char *SUPV_REPLY_TIMEOUT_STRING = "SUPV_REPLY_TIMEOUT";
const char *CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE_STRING = "CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE";
const char *SELF_TEST_I2C_FAILURE_STRING = "SELF_TEST_I2C_FAILURE"; const char *SELF_TEST_I2C_FAILURE_STRING = "SELF_TEST_I2C_FAILURE";
const char *SELF_TEST_SPI_FAILURE_STRING = "SELF_TEST_SPI_FAILURE"; const char *SELF_TEST_SPI_FAILURE_STRING = "SELF_TEST_SPI_FAILURE";
const char *SELF_TEST_ADC_FAILURE_STRING = "SELF_TEST_ADC_FAILURE"; const char *SELF_TEST_ADC_FAILURE_STRING = "SELF_TEST_ADC_FAILURE";
@@ -606,6 +607,8 @@ const char *translateEvents(Event event) {
return SUPV_NOT_ON_STRING; return SUPV_NOT_ON_STRING;
case (11608): case (11608):
return SUPV_REPLY_TIMEOUT_STRING; return SUPV_REPLY_TIMEOUT_STRING;
case (11609):
return CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE_STRING;
case (11701): case (11701):
return SELF_TEST_I2C_FAILURE_STRING; return SELF_TEST_I2C_FAILURE_STRING;
case (11702): case (11702):

View File

@@ -2,7 +2,7 @@
* @brief Auto-generated object translation file. * @brief Auto-generated object translation file.
* @details * @details
* Contains 176 translations. * Contains 176 translations.
* Generated on: 2024-04-17 11:22:10 * Generated on: 2024-05-06 13:47:38
*/ */
#include "translateObjects.h" #include "translateObjects.h"

View File

@@ -65,6 +65,7 @@
#include "linux/payload/PlocMpsocSpecialComHelper.h" #include "linux/payload/PlocMpsocSpecialComHelper.h"
#include "linux/payload/SerialConfig.h" #include "linux/payload/SerialConfig.h"
#include "mission/config/configfile.h" #include "mission/config/configfile.h"
#include "mission/power/defs.h"
#include "mission/system/acs/AcsBoardFdir.h" #include "mission/system/acs/AcsBoardFdir.h"
#include "mission/system/acs/AcsSubsystem.h" #include "mission/system/acs/AcsSubsystem.h"
#include "mission/system/acs/RwAssembly.h" #include "mission/system/acs/RwAssembly.h"
@@ -635,9 +636,9 @@ void ObjectFactory::createPayloadComponents(LinuxLibgpioIF* gpioComIF, PowerSwit
auto specialComHelper = auto specialComHelper =
new PlocMpsocSpecialComHelper(objects::PLOC_MPSOC_HELPER, *mpsocCommunication); new PlocMpsocSpecialComHelper(objects::PLOC_MPSOC_HELPER, *mpsocCommunication);
DhbConfig dhbConf(objects::PLOC_MPSOC_HANDLER); DhbConfig dhbConf(objects::PLOC_MPSOC_HANDLER);
auto* mpsocHandler = new FreshMpsocHandler(dhbConf, *mpsocCommunication, *specialComHelper, auto* mpsocHandler = new FreshMpsocHandler(
Gpio(gpioIds::ENABLE_MPSOC_UART, gpioComIF), dhbConf, *mpsocCommunication, *specialComHelper, Gpio(gpioIds::ENABLE_MPSOC_UART, gpioComIF),
objects::PLOC_SUPERVISOR_HANDLER); objects::PLOC_SUPERVISOR_HANDLER, pwrSwitcher, power::PDU2_CH8_PAYLOAD_CAMERA);
mpsocHandler->connectModeTreeParent(satsystem::payload::SUBSYSTEM); mpsocHandler->connectModeTreeParent(satsystem::payload::SUBSYSTEM);
#endif /* OBSW_ADD_PLOC_MPSOC == 1 */ #endif /* OBSW_ADD_PLOC_MPSOC == 1 */
#if OBSW_ADD_PLOC_SUPERVISOR == 1 #if OBSW_ADD_PLOC_SUPERVISOR == 1

2
fsfw

Submodule fsfw updated: 0660457c92...42867ad0cb

View File

@@ -135,7 +135,8 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
11605;0x2d55;MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH;LOW;Packet sequence count in received space packet does not match expected count P1: Expected sequence count P2: Received sequence count;linux/payload/plocMpsocHelpers.h 11605;0x2d55;MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH;LOW;Packet sequence count in received space packet does not match expected count P1: Expected sequence count P2: Received sequence count;linux/payload/plocMpsocHelpers.h
11606;0x2d56;MPSOC_SHUTDOWN_FAILED;HIGH;Supervisor fails to shutdown MPSoC. Requires to power off the PLOC and thus also to shutdown the supervisor.;linux/payload/plocMpsocHelpers.h 11606;0x2d56;MPSOC_SHUTDOWN_FAILED;HIGH;Supervisor fails to shutdown MPSoC. Requires to power off the PLOC and thus also to shutdown the supervisor.;linux/payload/plocMpsocHelpers.h
11607;0x2d57;SUPV_NOT_ON;LOW;SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for ON transition.;linux/payload/plocMpsocHelpers.h 11607;0x2d57;SUPV_NOT_ON;LOW;SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for ON transition.;linux/payload/plocMpsocHelpers.h
11608;0x2d58;SUPV_REPLY_TIMEOUT;LOW;No description;linux/payload/plocMpsocHelpers.h 11608;0x2d58;SUPV_REPLY_TIMEOUT;LOW;SUPV reply timeout.;linux/payload/plocMpsocHelpers.h
11609;0x2d59;CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE;LOW;Camera must be commanded on first.;linux/payload/plocMpsocHelpers.h
11701;0x2db5;SELF_TEST_I2C_FAILURE;LOW;Get self test result returns I2C failure P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h 11701;0x2db5;SELF_TEST_I2C_FAILURE;LOW;Get self test result returns I2C failure P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h
11702;0x2db6;SELF_TEST_SPI_FAILURE;LOW;Get self test result returns SPI failure. This concerns the MTM connectivity. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h 11702;0x2db6;SELF_TEST_SPI_FAILURE;LOW;Get self test result returns SPI failure. This concerns the MTM connectivity. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h
11703;0x2db7;SELF_TEST_ADC_FAILURE;LOW;Get self test result returns failure in measurement of current and temperature. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h 11703;0x2db7;SELF_TEST_ADC_FAILURE;LOW;Get self test result returns failure in measurement of current and temperature. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h
1 Event ID (dec) Event ID (hex) Name Severity Description File Path
135 11605 0x2d55 MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH LOW Packet sequence count in received space packet does not match expected count P1: Expected sequence count P2: Received sequence count linux/payload/plocMpsocHelpers.h
136 11606 0x2d56 MPSOC_SHUTDOWN_FAILED HIGH Supervisor fails to shutdown MPSoC. Requires to power off the PLOC and thus also to shutdown the supervisor. linux/payload/plocMpsocHelpers.h
137 11607 0x2d57 SUPV_NOT_ON LOW SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for ON transition. linux/payload/plocMpsocHelpers.h
138 11608 0x2d58 SUPV_REPLY_TIMEOUT LOW No description SUPV reply timeout. linux/payload/plocMpsocHelpers.h
139 11609 0x2d59 CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE LOW Camera must be commanded on first. linux/payload/plocMpsocHelpers.h
140 11701 0x2db5 SELF_TEST_I2C_FAILURE LOW Get self test result returns I2C failure P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA mission/acs/ImtqHandler.h
141 11702 0x2db6 SELF_TEST_SPI_FAILURE LOW Get self test result returns SPI failure. This concerns the MTM connectivity. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA mission/acs/ImtqHandler.h
142 11703 0x2db7 SELF_TEST_ADC_FAILURE LOW Get self test result returns failure in measurement of current and temperature. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA mission/acs/ImtqHandler.h

View File

@@ -135,7 +135,8 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
11605;0x2d55;MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH;LOW;Packet sequence count in received space packet does not match expected count P1: Expected sequence count P2: Received sequence count;linux/payload/plocMpsocHelpers.h 11605;0x2d55;MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH;LOW;Packet sequence count in received space packet does not match expected count P1: Expected sequence count P2: Received sequence count;linux/payload/plocMpsocHelpers.h
11606;0x2d56;MPSOC_SHUTDOWN_FAILED;HIGH;Supervisor fails to shutdown MPSoC. Requires to power off the PLOC and thus also to shutdown the supervisor.;linux/payload/plocMpsocHelpers.h 11606;0x2d56;MPSOC_SHUTDOWN_FAILED;HIGH;Supervisor fails to shutdown MPSoC. Requires to power off the PLOC and thus also to shutdown the supervisor.;linux/payload/plocMpsocHelpers.h
11607;0x2d57;SUPV_NOT_ON;LOW;SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for ON transition.;linux/payload/plocMpsocHelpers.h 11607;0x2d57;SUPV_NOT_ON;LOW;SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for ON transition.;linux/payload/plocMpsocHelpers.h
11608;0x2d58;SUPV_REPLY_TIMEOUT;LOW;No description;linux/payload/plocMpsocHelpers.h 11608;0x2d58;SUPV_REPLY_TIMEOUT;LOW;SUPV reply timeout.;linux/payload/plocMpsocHelpers.h
11609;0x2d59;CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE;LOW;Camera must be commanded on first.;linux/payload/plocMpsocHelpers.h
11701;0x2db5;SELF_TEST_I2C_FAILURE;LOW;Get self test result returns I2C failure P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h 11701;0x2db5;SELF_TEST_I2C_FAILURE;LOW;Get self test result returns I2C failure P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h
11702;0x2db6;SELF_TEST_SPI_FAILURE;LOW;Get self test result returns SPI failure. This concerns the MTM connectivity. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h 11702;0x2db6;SELF_TEST_SPI_FAILURE;LOW;Get self test result returns SPI failure. This concerns the MTM connectivity. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h
11703;0x2db7;SELF_TEST_ADC_FAILURE;LOW;Get self test result returns failure in measurement of current and temperature. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h 11703;0x2db7;SELF_TEST_ADC_FAILURE;LOW;Get self test result returns failure in measurement of current and temperature. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h
1 Event ID (dec) Event ID (hex) Name Severity Description File Path
135 11605 0x2d55 MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH LOW Packet sequence count in received space packet does not match expected count P1: Expected sequence count P2: Received sequence count linux/payload/plocMpsocHelpers.h
136 11606 0x2d56 MPSOC_SHUTDOWN_FAILED HIGH Supervisor fails to shutdown MPSoC. Requires to power off the PLOC and thus also to shutdown the supervisor. linux/payload/plocMpsocHelpers.h
137 11607 0x2d57 SUPV_NOT_ON LOW SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for ON transition. linux/payload/plocMpsocHelpers.h
138 11608 0x2d58 SUPV_REPLY_TIMEOUT LOW No description SUPV reply timeout. linux/payload/plocMpsocHelpers.h
139 11609 0x2d59 CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE LOW Camera must be commanded on first. linux/payload/plocMpsocHelpers.h
140 11701 0x2db5 SELF_TEST_I2C_FAILURE LOW Get self test result returns I2C failure P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA mission/acs/ImtqHandler.h
141 11702 0x2db6 SELF_TEST_SPI_FAILURE LOW Get self test result returns SPI failure. This concerns the MTM connectivity. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA mission/acs/ImtqHandler.h
142 11703 0x2db7 SELF_TEST_ADC_FAILURE LOW Get self test result returns failure in measurement of current and temperature. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA mission/acs/ImtqHandler.h

View File

@@ -1,7 +1,7 @@
/** /**
* @brief Auto-generated event translation file. Contains 324 translations. * @brief Auto-generated event translation file. Contains 325 translations.
* @details * @details
* Generated on: 2024-04-17 11:22:10 * Generated on: 2024-05-06 13:47:38
*/ */
#include "translateEvents.h" #include "translateEvents.h"
@@ -142,6 +142,7 @@ const char *MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH_STRING = "MPSOC_HANDLER_SEQUEN
const char *MPSOC_SHUTDOWN_FAILED_STRING = "MPSOC_SHUTDOWN_FAILED"; const char *MPSOC_SHUTDOWN_FAILED_STRING = "MPSOC_SHUTDOWN_FAILED";
const char *SUPV_NOT_ON_STRING = "SUPV_NOT_ON"; const char *SUPV_NOT_ON_STRING = "SUPV_NOT_ON";
const char *SUPV_REPLY_TIMEOUT_STRING = "SUPV_REPLY_TIMEOUT"; const char *SUPV_REPLY_TIMEOUT_STRING = "SUPV_REPLY_TIMEOUT";
const char *CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE_STRING = "CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE";
const char *SELF_TEST_I2C_FAILURE_STRING = "SELF_TEST_I2C_FAILURE"; const char *SELF_TEST_I2C_FAILURE_STRING = "SELF_TEST_I2C_FAILURE";
const char *SELF_TEST_SPI_FAILURE_STRING = "SELF_TEST_SPI_FAILURE"; const char *SELF_TEST_SPI_FAILURE_STRING = "SELF_TEST_SPI_FAILURE";
const char *SELF_TEST_ADC_FAILURE_STRING = "SELF_TEST_ADC_FAILURE"; const char *SELF_TEST_ADC_FAILURE_STRING = "SELF_TEST_ADC_FAILURE";
@@ -606,6 +607,8 @@ const char *translateEvents(Event event) {
return SUPV_NOT_ON_STRING; return SUPV_NOT_ON_STRING;
case (11608): case (11608):
return SUPV_REPLY_TIMEOUT_STRING; return SUPV_REPLY_TIMEOUT_STRING;
case (11609):
return CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE_STRING;
case (11701): case (11701):
return SELF_TEST_I2C_FAILURE_STRING; return SELF_TEST_I2C_FAILURE_STRING;
case (11702): case (11702):

View File

@@ -2,7 +2,7 @@
* @brief Auto-generated object translation file. * @brief Auto-generated object translation file.
* @details * @details
* Contains 180 translations. * Contains 180 translations.
* Generated on: 2024-04-17 11:22:10 * Generated on: 2024-05-06 13:47:38
*/ */
#include "translateObjects.h" #include "translateObjects.h"

View File

@@ -1,7 +1,7 @@
/** /**
* @brief Auto-generated event translation file. Contains 324 translations. * @brief Auto-generated event translation file. Contains 325 translations.
* @details * @details
* Generated on: 2024-04-17 11:22:10 * Generated on: 2024-05-06 13:47:38
*/ */
#include "translateEvents.h" #include "translateEvents.h"
@@ -142,6 +142,7 @@ const char *MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH_STRING = "MPSOC_HANDLER_SEQUEN
const char *MPSOC_SHUTDOWN_FAILED_STRING = "MPSOC_SHUTDOWN_FAILED"; const char *MPSOC_SHUTDOWN_FAILED_STRING = "MPSOC_SHUTDOWN_FAILED";
const char *SUPV_NOT_ON_STRING = "SUPV_NOT_ON"; const char *SUPV_NOT_ON_STRING = "SUPV_NOT_ON";
const char *SUPV_REPLY_TIMEOUT_STRING = "SUPV_REPLY_TIMEOUT"; const char *SUPV_REPLY_TIMEOUT_STRING = "SUPV_REPLY_TIMEOUT";
const char *CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE_STRING = "CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE";
const char *SELF_TEST_I2C_FAILURE_STRING = "SELF_TEST_I2C_FAILURE"; const char *SELF_TEST_I2C_FAILURE_STRING = "SELF_TEST_I2C_FAILURE";
const char *SELF_TEST_SPI_FAILURE_STRING = "SELF_TEST_SPI_FAILURE"; const char *SELF_TEST_SPI_FAILURE_STRING = "SELF_TEST_SPI_FAILURE";
const char *SELF_TEST_ADC_FAILURE_STRING = "SELF_TEST_ADC_FAILURE"; const char *SELF_TEST_ADC_FAILURE_STRING = "SELF_TEST_ADC_FAILURE";
@@ -606,6 +607,8 @@ const char *translateEvents(Event event) {
return SUPV_NOT_ON_STRING; return SUPV_NOT_ON_STRING;
case (11608): case (11608):
return SUPV_REPLY_TIMEOUT_STRING; return SUPV_REPLY_TIMEOUT_STRING;
case (11609):
return CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE_STRING;
case (11701): case (11701):
return SELF_TEST_I2C_FAILURE_STRING; return SELF_TEST_I2C_FAILURE_STRING;
case (11702): case (11702):

View File

@@ -2,7 +2,7 @@
* @brief Auto-generated object translation file. * @brief Auto-generated object translation file.
* @details * @details
* Contains 180 translations. * Contains 180 translations.
* Generated on: 2024-04-17 11:22:10 * Generated on: 2024-05-06 13:47:38
*/ */
#include "translateObjects.h" #include "translateObjects.h"

View File

@@ -8,22 +8,29 @@
#include "fsfw/devicehandlers/FreshDeviceHandlerBase.h" #include "fsfw/devicehandlers/FreshDeviceHandlerBase.h"
#include "fsfw/ipc/MessageQueueIF.h" #include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/ipc/QueueFactory.h" #include "fsfw/ipc/QueueFactory.h"
#include "fsfw/ipc/messageQueueDefinitions.h"
#include "fsfw/power/PowerSwitchIF.h"
#include "fsfw/power/definitions.h"
#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/returnvalues/returnvalue.h"
#include "fsfw/serialize/SerializeAdapter.h" #include "fsfw/serialize/SerializeAdapter.h"
#include "linux/payload/MpsocCommunication.h" #include "linux/payload/MpsocCommunication.h"
#include "linux/payload/plocMpsocHelpers.h" #include "linux/payload/plocMpsocHelpers.h"
#include "linux/payload/plocSupvDefs.h" #include "linux/payload/plocSupvDefs.h"
#include "mission/power/gsDefs.h"
FreshMpsocHandler::FreshMpsocHandler(DhbConfig cfg, MpsocCommunication& comInterface, FreshMpsocHandler::FreshMpsocHandler(DhbConfig cfg, MpsocCommunication& comInterface,
PlocMpsocSpecialComHelper& specialComHelper, PlocMpsocSpecialComHelper& specialComHelper,
Gpio uartIsolatorSwitch, object_id_t supervisorHandler) Gpio uartIsolatorSwitch, object_id_t supervisorHandler,
PowerSwitchIF& powerSwitcher, power::Switch_t camSwitchId)
: FreshDeviceHandlerBase(cfg), : FreshDeviceHandlerBase(cfg),
comInterface(comInterface), comInterface(comInterface),
specialComHelper(specialComHelper), specialComHelper(specialComHelper),
commandActionHelper(this), commandActionHelper(this),
uartIsolatorSwitch(uartIsolatorSwitch), uartIsolatorSwitch(uartIsolatorSwitch),
hkReport(this), hkReport(this),
supervisorHandler(supervisorHandler) { supervisorHandler(supervisorHandler),
powerSwitcher(powerSwitcher),
camSwitchId(camSwitchId) {
commandActionHelperQueue = QueueFactory::instance()->createMessageQueue(10); commandActionHelperQueue = QueueFactory::instance()->createMessageQueue(10);
eventQueue = QueueFactory::instance()->createMessageQueue(10); eventQueue = QueueFactory::instance()->createMessageQueue(10);
spParams.maxSize = sizeof(commandBuffer); spParams.maxSize = sizeof(commandBuffer);
@@ -38,7 +45,7 @@ void FreshMpsocHandler::performDeviceOperation(uint8_t opCode) {
if (opCode == OpCode::DEFAULT_OPERATION) { if (opCode == OpCode::DEFAULT_OPERATION) {
performDefaultDeviceOperation(); performDefaultDeviceOperation();
} else if (opCode == OpCode::PARSE_TM) { } else if (opCode == OpCode::PARSE_TM and not specialComHelperExecuting) {
// Just need to call this once, this should take care of processing the whole received // Just need to call this once, this should take care of processing the whole received
// Linux UART RX buffer. // Linux UART RX buffer.
comInterface.readSerialInterface(); comInterface.readSerialInterface();
@@ -77,8 +84,13 @@ void FreshMpsocHandler::performDefaultDeviceOperation() {
} }
} }
if (mode == MODE_NORMAL and not activeCmdInfo.pending) { // We checked the action queue beforehand, so action commands should always be performed
// TODO: Take care of regular periodic commanding here. // before normal commands.
if (mode == MODE_NORMAL and not activeCmdInfo.pending and not specialComHelperExecuting) {
ReturnValue_t result = commandTcGetHkReport();
if (result == returnvalue::OK) {
commandInitHandling(mpsoc::TC_GET_HK_REPORT, MessageQueueIF::NO_QUEUE);
}
} }
if (activeCmdInfo.pending and activeCmdInfo.cmdCountdown.hasTimedOut()) { if (activeCmdInfo.pending and activeCmdInfo.cmdCountdown.hasTimedOut()) {
@@ -153,7 +165,6 @@ ReturnValue_t FreshMpsocHandler::initialize() {
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
} }
specialComHelper.setSequenceCount(&commandSequenceCount);
result = commandActionHelper.initialize(); result = commandActionHelper.initialize();
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
@@ -225,6 +236,11 @@ ReturnValue_t FreshMpsocHandler::checkModeCommand(Mode_t mode, Submode_t submode
return HasModesIF::INVALID_SUBMODE; return HasModesIF::INVALID_SUBMODE;
} }
} }
if (submode == mpsoc::Submode::SNAPSHOT and
powerSwitcher.getSwitchState(camSwitchId) != PowerSwitchIF::SWITCH_ON) {
triggerEvent(mpsoc::CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE);
return HasModesIF::TRANS_NOT_ALLOWED;
}
*msToReachTheMode = MPSOC_MODE_CMD_TIMEOUT_MS; *msToReachTheMode = MPSOC_MODE_CMD_TIMEOUT_MS;
return returnvalue::OK; return returnvalue::OK;
} }
@@ -265,11 +281,11 @@ ReturnValue_t FreshMpsocHandler::executeAction(ActionId_t actionId, MessageQueue
return result; return result;
} }
result = specialComHelper.startFlashWrite(flashWritePusCmd.getObcFile(), result = specialComHelper.startFlashWrite(flashWritePusCmd.getObcFile(),
flashWritePusCmd.getMPSoCFile()); flashWritePusCmd.getMpsocFile());
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
specialComHelperExecuting = true; commonSpecialComInit();
return EXECUTION_FINISHED; return EXECUTION_FINISHED;
} }
case mpsoc::TC_FLASH_READ_FULL_FILE: { case mpsoc::TC_FLASH_READ_FULL_FILE: {
@@ -279,12 +295,15 @@ ReturnValue_t FreshMpsocHandler::executeAction(ActionId_t actionId, MessageQueue
return result; return result;
} }
result = specialComHelper.startFlashRead(flashReadPusCmd.getObcFile(), result = specialComHelper.startFlashRead(flashReadPusCmd.getObcFile(),
flashReadPusCmd.getMPSoCFile(), flashReadPusCmd.getMpsocFile(),
flashReadPusCmd.getReadSize()); flashReadPusCmd.getReadSize());
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
specialComHelperExecuting = true; sif::info << "PLOC MPSoC: Reading " << flashReadPusCmd.getMpsocFile() << " with size "
<< flashReadPusCmd.getReadSize() << " to " << flashReadPusCmd.getObcFile()
<< std::endl;
commonSpecialComInit();
return EXECUTION_FINISHED; return EXECUTION_FINISHED;
} }
case (mpsoc::OBSW_RESET_SEQ_COUNT_LEGACY): { case (mpsoc::OBSW_RESET_SEQ_COUNT_LEGACY): {
@@ -294,12 +313,15 @@ ReturnValue_t FreshMpsocHandler::executeAction(ActionId_t actionId, MessageQueue
default: default:
break; break;
} }
// For longer commands, do not set these.
// TODO: Do all the stuff the form buildDeviceFromDevice blah did.
executeRegularCmd(actionId, commandedBy, data, size); executeRegularCmd(actionId, commandedBy, data, size);
return returnvalue::OK; return returnvalue::OK;
} }
void FreshMpsocHandler::commonSpecialComInit() {
specialComHelperExecuting = true;
specialComHelper.setCommandSequenceCount(commandSequenceCount.get());
}
/** /**
* @overload * @overload
* @param submode * @param submode
@@ -315,6 +337,10 @@ void FreshMpsocHandler::startTransition(Mode_t newMode, Submode_t submode) {
} else if ((newMode == MODE_ON or newMode == MODE_NORMAL) && } else if ((newMode == MODE_ON or newMode == MODE_NORMAL) &&
((mode == MODE_OFF) or (mode == MODE_UNDEFINED))) { ((mode == MODE_OFF) or (mode == MODE_UNDEFINED))) {
transitionState = TransitionState::TO_ON; transitionState = TransitionState::TO_ON;
} else if (mode == MODE_ON && newMode == MODE_NORMAL) {
hkReport.setReportingEnabled(true);
} else if (mode == MODE_NORMAL && newMode == MODE_ON) {
hkReport.setReportingEnabled(false);
} else if (newMode == MODE_OFF) { } else if (newMode == MODE_OFF) {
transitionState = TransitionState::TO_OFF; transitionState = TransitionState::TO_OFF;
} }
@@ -350,7 +376,9 @@ void FreshMpsocHandler::handleTransitionToOn() {
if (startupState == StartupState::DONE) { if (startupState == StartupState::DONE) {
setMode(targetMode, targetSubmode); setMode(targetMode, targetSubmode);
transitionState = TransitionState::NONE; transitionState = TransitionState::NONE;
hkReport.setReportingEnabled(true); if (targetMode == MODE_NORMAL) {
hkReport.setReportingEnabled(true);
}
powerState = PowerState::IDLE; powerState = PowerState::IDLE;
startupState = StartupState::IDLE; startupState = StartupState::IDLE;
} }
@@ -359,7 +387,7 @@ void FreshMpsocHandler::handleTransitionToOn() {
void FreshMpsocHandler::handleTransitionToOff() { void FreshMpsocHandler::handleTransitionToOff() {
if (handleHwShutdown()) { if (handleHwShutdown()) {
hkReport.setReportingEnabled(false); hkReport.setReportingEnabled(false);
setMode(MODE_OFF); setMode(MODE_OFF, 0);
transitionState = TransitionState::NONE; transitionState = TransitionState::NONE;
activeCmdInfo.reset(); activeCmdInfo.reset();
powerState = PowerState::IDLE; powerState = PowerState::IDLE;
@@ -428,7 +456,7 @@ void FreshMpsocHandler::handleActionCommandFailure(ActionId_t actionId, ReturnVa
if (actionId != supv::START_MPSOC) { if (actionId != supv::START_MPSOC) {
return; return;
} }
sif::info << "PlocMPSoCHandler::handleActionCommandFailure: MPSoC boot command failed" sif::info << "FreshMpsocHandler::handleActionCommandFailure: MPSoC boot command failed"
<< std::endl; << std::endl;
// This is commonly the case when the MPSoC is already operational. Thus the power state is // This is commonly the case when the MPSoC is already operational. Thus the power state is
// set to on here // set to on here
@@ -476,6 +504,23 @@ ReturnValue_t FreshMpsocHandler::executeRegularCmd(ActionId_t actionId,
result = commandTcMemRead(commandData, commandDataLen); result = commandTcMemRead(commandData, commandDataLen);
break; break;
} }
case (mpsoc::TC_FLASHFOPEN): {
mpsoc::TcFlashFopen cmd(spParams, commandSequenceCount);
// C string constructor.
std::string filename = std::string(reinterpret_cast<const char*>(commandData));
if (filename.size() > mpsoc::MAX_FILENAME_SIZE) {
return mpsoc::NAME_TOO_LONG;
}
uint8_t mode = commandData[filename.size() + 2];
cmd.setPayload(filename, mode);
result = finishAndSendTc(actionId, cmd);
break;
}
case (mpsoc::TC_FLASHFCLOSE): {
mpsoc::TcFlashFclose cmd(spParams, commandSequenceCount);
result = finishAndSendTc(actionId, cmd);
break;
}
case (mpsoc::TC_FLASHDELETE): { case (mpsoc::TC_FLASHDELETE): {
result = commandTcFlashDelete(commandData, commandDataLen); result = commandTcFlashDelete(commandData, commandDataLen);
break; break;
@@ -518,6 +563,7 @@ ReturnValue_t FreshMpsocHandler::executeRegularCmd(ActionId_t actionId,
} }
mpsoc::TcFlashMkfs cmd(spParams, commandSequenceCount, mpsoc::TcFlashMkfs cmd(spParams, commandSequenceCount,
static_cast<mpsoc::FlashId>(commandData[0])); static_cast<mpsoc::FlashId>(commandData[0]));
sif::info << "PLOC MPSoC: Formatting Flash " << (int)commandData[0] << std::endl;
result = finishAndSendTc(actionId, cmd, mpsoc::CMD_TIMEOUT_MKFS); result = finishAndSendTc(actionId, cmd, mpsoc::CMD_TIMEOUT_MKFS);
break; break;
} }
@@ -538,9 +584,16 @@ ReturnValue_t FreshMpsocHandler::executeRegularCmd(ActionId_t actionId,
break; break;
} }
case (mpsoc::TC_SIMPLEX_STREAM_FILE): { case (mpsoc::TC_SIMPLEX_STREAM_FILE): {
if (submode != mpsoc::Submode::SNAPSHOT) {
return HasModesIF::INVALID_SUBMODE;
}
result = commandTcSimplexStreamFile(commandData, commandDataLen); result = commandTcSimplexStreamFile(commandData, commandDataLen);
break; break;
} }
case (mpsoc::TC_SPLIT_FILE): {
result = commandTcSplitFile(commandData, commandDataLen);
break;
}
case (mpsoc::TC_DOWNLINK_DATA_MODULATE): { case (mpsoc::TC_DOWNLINK_DATA_MODULATE): {
result = commandTcDownlinkDataModulate(commandData, commandDataLen); result = commandTcDownlinkDataModulate(commandData, commandDataLen);
break; break;
@@ -553,16 +606,20 @@ ReturnValue_t FreshMpsocHandler::executeRegularCmd(ActionId_t actionId,
} }
if (result == returnvalue::OK) { if (result == returnvalue::OK) {
activeCmdInfo.start(actionId, commandedBy); commandInitHandling(actionId, commandedBy);
/**
* Flushing the receive buffer to make sure there are no data left from a faulty reply.
*/
comInterface.getComHelper().flushUartRxBuffer();
} }
return result; return result;
} }
void FreshMpsocHandler::commandInitHandling(ActionId_t actionId, MessageQueueId_t commandedBy) {
activeCmdInfo.start(actionId, commandedBy);
/**
* Flushing the receive buffer to make sure there are no data left from a faulty reply.
*/
comInterface.getComHelper().flushUartRxBuffer();
}
ReturnValue_t FreshMpsocHandler::commandTcMemWrite(const uint8_t* commandData, ReturnValue_t FreshMpsocHandler::commandTcMemWrite(const uint8_t* commandData,
size_t commandDataLen) { size_t commandDataLen) {
ReturnValue_t result = returnvalue::OK; ReturnValue_t result = returnvalue::OK;
@@ -590,7 +647,7 @@ ReturnValue_t FreshMpsocHandler::commandTcMemRead(const uint8_t* commandData,
ReturnValue_t FreshMpsocHandler::commandTcFlashDelete(const uint8_t* commandData, ReturnValue_t FreshMpsocHandler::commandTcFlashDelete(const uint8_t* commandData,
size_t commandDataLen) { size_t commandDataLen) {
if (commandDataLen > config::MAX_PATH_SIZE + config::MAX_FILENAME_SIZE) { if (commandDataLen > mpsoc::FILENAME_FIELD_SIZE) {
return mpsoc::NAME_TOO_LONG; return mpsoc::NAME_TOO_LONG;
} }
ReturnValue_t result = returnvalue::OK; ReturnValue_t result = returnvalue::OK;
@@ -687,6 +744,15 @@ ReturnValue_t FreshMpsocHandler::commandTcCamTakePic(const uint8_t* commandData,
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
sif::info << "PLOC MPSoC Take Picture Command" << std::endl;
sif::info << "filename: " << tcCamTakePic.fileName << std::endl;
sif::info << "encoder [Y, Cb, Cr]: [" << (int)tcCamTakePic.encoderSettingY << ", "
<< (int)tcCamTakePic.encoderSettingsCb << ", " << (int)tcCamTakePic.encoderSettingsCr
<< "]" << std::endl;
sif::info << "quantization [Y, Cb, Cr]: [" << tcCamTakePic.quantizationY << ", "
<< tcCamTakePic.quantizationCb << ", " << tcCamTakePic.quantizationCr << "]"
<< std::endl;
sif::info << "bypass compressor: " << (int)tcCamTakePic.bypassCompressor << std::endl;
finishAndSendTc(mpsoc::TC_CAM_TAKE_PIC, tcCamTakePic); finishAndSendTc(mpsoc::TC_CAM_TAKE_PIC, tcCamTakePic);
return returnvalue::OK; return returnvalue::OK;
} }
@@ -702,14 +768,14 @@ ReturnValue_t FreshMpsocHandler::commandTcSimplexStreamFile(const uint8_t* comma
return returnvalue::OK; return returnvalue::OK;
} }
ReturnValue_t FreshMpsocHandler::commandTcSimplexStoreFile(const uint8_t* commandData, ReturnValue_t FreshMpsocHandler::commandTcSplitFile(const uint8_t* commandData,
size_t commandDataLen) { size_t commandDataLen) {
mpsoc::TcSimplexStoreFile tcSimplexStoreFile(spParams, commandSequenceCount); mpsoc::TcSplitFile tcSplitFile(spParams, commandSequenceCount);
ReturnValue_t result = tcSimplexStoreFile.setPayload(commandData, commandDataLen); ReturnValue_t result = tcSplitFile.setPayload(commandData, commandDataLen);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
finishAndSendTc(mpsoc::TC_SIMPLEX_STORE_FILE, tcSimplexStoreFile); finishAndSendTc(mpsoc::TC_SPLIT_FILE, tcSplitFile);
return returnvalue::OK; return returnvalue::OK;
} }
@@ -743,18 +809,18 @@ ReturnValue_t FreshMpsocHandler::commandTcModeSnapshot() {
ReturnValue_t FreshMpsocHandler::finishAndSendTc(DeviceCommandId_t cmdId, mpsoc::TcBase& tcBase, ReturnValue_t FreshMpsocHandler::finishAndSendTc(DeviceCommandId_t cmdId, mpsoc::TcBase& tcBase,
uint32_t cmdCountdownMs) { uint32_t cmdCountdownMs) {
// Emit warning but still send command.
if (specialComHelperExecuting) {
sif::warning << "PLOC MPSoC: Sending command even though special COM helper is executing"
<< std::endl;
}
ReturnValue_t result = tcBase.finishPacket(); ReturnValue_t result = tcBase.finishPacket();
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
// TODO: We should find a way so this works with the old implementation.
commandSequenceCount++; commandSequenceCount++;
if (MPSOC_TX_WIRETAPPING) { mpsoc::printTxPacket(tcBase);
sif::debug << "SEND MPSOC packet. APID 0x" << std::hex << std::setw(3) << tcBase.getApid()
<< " Size " << std::dec << tcBase.getFullPacketLen() << " SSC "
<< tcBase.getSeqCount() << std::endl;
}
activeCmdInfo.cmdCountdown.setTimeout(cmdCountdownMs); activeCmdInfo.cmdCountdown.setTimeout(cmdCountdownMs);
activeCmdInfo.cmdCountdown.resetTimer(); activeCmdInfo.cmdCountdown.resetTimer();
activeCmdInfo.pending = true; activeCmdInfo.pending = true;
@@ -764,11 +830,10 @@ ReturnValue_t FreshMpsocHandler::finishAndSendTc(DeviceCommandId_t cmdId, mpsoc:
} }
void FreshMpsocHandler::handleEvent(EventMessage* eventMessage) { void FreshMpsocHandler::handleEvent(EventMessage* eventMessage) {
// TODO: Shouldn't we check for specific events?
object_id_t objectId = eventMessage->getReporter(); object_id_t objectId = eventMessage->getReporter();
switch (objectId) { switch (objectId) {
case objects::PLOC_MPSOC_HANDLER: { case objects::PLOC_MPSOC_HELPER: {
specialComHelperExecuting = false; commonSpecialComStop();
break; break;
} }
default: default:
@@ -776,6 +841,10 @@ void FreshMpsocHandler::handleEvent(EventMessage* eventMessage) {
break; break;
} }
} }
void FreshMpsocHandler::commonSpecialComStop() {
specialComHelperExecuting = false;
commandSequenceCount.set(specialComHelper.getCommandSequenceCount());
}
void FreshMpsocHandler::cmdDoneHandler(bool success, ReturnValue_t result) { void FreshMpsocHandler::cmdDoneHandler(bool success, ReturnValue_t result) {
if (transitionState == TransitionState::SUBMODE) { if (transitionState == TransitionState::SUBMODE) {
@@ -796,17 +865,11 @@ void FreshMpsocHandler::cmdDoneHandler(bool success, ReturnValue_t result) {
ReturnValue_t FreshMpsocHandler::handleDeviceReply() { ReturnValue_t FreshMpsocHandler::handleDeviceReply() {
ReturnValue_t result = returnvalue::OK; ReturnValue_t result = returnvalue::OK;
// SpacePacketReader spacePacket; const auto& replyReader = comInterface.getSpReader();
// spacePacket.setReadOnlyData(start, remainingSize);
auto& replyReader = comInterface.getSpReader();
if (replyReader.isNull()) { if (replyReader.isNull()) {
return returnvalue::FAILED; return returnvalue::FAILED;
} }
if (MPSOC_RX_WIRETAPPING) { mpsoc::printRxPacket(replyReader);
sif::debug << "RECV MPSOC packet. APID 0x" << std::hex << std::setw(3) << replyReader.getApid()
<< std::dec << " Size " << replyReader.getFullPacketLen() << " SSC "
<< replyReader.getSequenceCount() << std::endl;
}
uint16_t apid = replyReader.getApid(); uint16_t apid = replyReader.getApid();
switch (apid) { switch (apid) {
@@ -853,15 +916,14 @@ ReturnValue_t FreshMpsocHandler::handleDeviceReply() {
default: { default: {
sif::debug << "FreshMpsocHandler:: Reply has invalid APID 0x" << std::hex << std::setfill('0') sif::debug << "FreshMpsocHandler:: Reply has invalid APID 0x" << std::hex << std::setfill('0')
<< std::setw(2) << apid << std::dec << std::endl; << std::setw(2) << apid << std::dec << std::endl;
//*foundLen = remainingSize;
return mpsoc::INVALID_APID; return mpsoc::INVALID_APID;
} }
} }
// TODO: We should implement some way so this can also be used with the former implementation.
uint16_t sequenceCount = replyReader.getSequenceCount(); uint16_t sequenceCount = replyReader.getSequenceCount();
if (sequenceCount != lastReplySequenceCount + 1) { if (sequenceCount != lastReplySequenceCount + 1) {
// TODO: Trigger event for possible missing reply packet to inform operator. // We could trigger event for possible missing reply packet to inform operator, but I don't
// think this is properly implemented and used on the MPSoC side anymore.
} }
lastReplySequenceCount = sequenceCount; lastReplySequenceCount = sequenceCount;
@@ -916,7 +978,6 @@ ReturnValue_t FreshMpsocHandler::handleAckReport() {
switch (replyReader.getApid()) { switch (replyReader.getApid()) {
case mpsoc::apid::ACK_FAILURE: { case mpsoc::apid::ACK_FAILURE: {
// DeviceCommandId_t commandId = getPendingCommand();
uint16_t status = mpsoc::getStatusFromRawData(replyReader.getFullData()); uint16_t status = mpsoc::getStatusFromRawData(replyReader.getFullData());
sif::warning << "MPSoC ACK Failure: " << mpsoc::getStatusString(status) << std::endl; sif::warning << "MPSoC ACK Failure: " << mpsoc::getStatusString(status) << std::endl;
triggerEvent(mpsoc::ACK_FAILURE, activeCmdInfo.pendingCmd, status); triggerEvent(mpsoc::ACK_FAILURE, activeCmdInfo.pendingCmd, status);
@@ -1163,6 +1224,7 @@ bool FreshMpsocHandler::handleHwStartup() {
if (powerState == PowerState::SUPV_FAILED) { if (powerState == PowerState::SUPV_FAILED) {
setMode(MODE_OFF); setMode(MODE_OFF);
powerState = PowerState::IDLE; powerState = PowerState::IDLE;
transitionState = TransitionState::NONE;
return false; return false;
} }
if (powerState == PowerState::PENDING_STARTUP) { if (powerState == PowerState::PENDING_STARTUP) {
@@ -1200,7 +1262,9 @@ bool FreshMpsocHandler::handleHwShutdown() {
supvTransitionCd.resetTimer(); supvTransitionCd.resetTimer();
powerState = PowerState::PENDING_SHUTDOWN; powerState = PowerState::PENDING_SHUTDOWN;
} else { } else {
triggerEvent(mpsoc::SUPV_NOT_ON, 0); if ((this->mode != MODE_OFF) and (this->mode != MODE_UNDEFINED)) {
triggerEvent(mpsoc::SUPV_NOT_ON, 0);
}
powerState = PowerState::DONE; powerState = PowerState::DONE;
} }
} }

View File

@@ -1,3 +1,4 @@
#include "fsfw/action/ActionMessage.h"
#include "fsfw/action/CommandsActionsIF.h" #include "fsfw/action/CommandsActionsIF.h"
#include "fsfw/devicehandlers/DeviceHandlerIF.h" #include "fsfw/devicehandlers/DeviceHandlerIF.h"
#include "fsfw/devicehandlers/FreshDeviceHandlerBase.h" #include "fsfw/devicehandlers/FreshDeviceHandlerBase.h"
@@ -5,15 +6,14 @@
#include "fsfw/ipc/messageQueueDefinitions.h" #include "fsfw/ipc/messageQueueDefinitions.h"
#include "fsfw/modes/ModeMessage.h" #include "fsfw/modes/ModeMessage.h"
#include "fsfw/objectmanager/SystemObjectIF.h" #include "fsfw/objectmanager/SystemObjectIF.h"
#include "fsfw/power/PowerSwitchIF.h"
#include "fsfw/power/definitions.h"
#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/returnvalues/returnvalue.h"
#include "fsfw_hal/linux/gpio/Gpio.h" #include "fsfw_hal/linux/gpio/Gpio.h"
#include "linux/payload/MpsocCommunication.h" #include "linux/payload/MpsocCommunication.h"
#include "linux/payload/PlocMpsocSpecialComHelper.h" #include "linux/payload/PlocMpsocSpecialComHelper.h"
#include "linux/payload/plocMpsocHelpers.h" #include "linux/payload/plocMpsocHelpers.h"
static constexpr bool MPSOC_TX_WIRETAPPING = true;
static constexpr bool MPSOC_RX_WIRETAPPING = true;
class FreshMpsocHandler : public FreshDeviceHandlerBase, public CommandsActionsIF { class FreshMpsocHandler : public FreshDeviceHandlerBase, public CommandsActionsIF {
public: public:
enum OpCode { DEFAULT_OPERATION = 0, PARSE_TM = 1 }; enum OpCode { DEFAULT_OPERATION = 0, PARSE_TM = 1 };
@@ -21,7 +21,8 @@ class FreshMpsocHandler : public FreshDeviceHandlerBase, public CommandsActionsI
FreshMpsocHandler(DhbConfig cfg, MpsocCommunication& comInterface, FreshMpsocHandler(DhbConfig cfg, MpsocCommunication& comInterface,
PlocMpsocSpecialComHelper& specialComHelper, Gpio uartIsolatorSwitch, PlocMpsocSpecialComHelper& specialComHelper, Gpio uartIsolatorSwitch,
object_id_t supervisorHandler); object_id_t supervisorHandler, PowerSwitchIF& powerSwitcher,
power::Switch_t camSwitchId);
/** /**
* Periodic helper executed function, implemented by child class. * Periodic helper executed function, implemented by child class.
@@ -131,6 +132,8 @@ class FreshMpsocHandler : public FreshDeviceHandlerBase, public CommandsActionsI
TmMemReadReport tmMemReadReport; TmMemReadReport tmMemReadReport;
uint32_t lastReplySequenceCount = 0; uint32_t lastReplySequenceCount = 0;
uint8_t skipSupvCommandingToOn = false; uint8_t skipSupvCommandingToOn = false;
PowerSwitchIF& powerSwitcher;
power::Switch_t camSwitchId;
// HK manager abstract functions. // HK manager abstract functions.
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override; LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
@@ -184,7 +187,7 @@ class FreshMpsocHandler : public FreshDeviceHandlerBase, public CommandsActionsI
ReturnValue_t commandTcModeIdle(); ReturnValue_t commandTcModeIdle();
ReturnValue_t commandTcCamTakePic(const uint8_t* commandData, size_t commandDataLen); ReturnValue_t commandTcCamTakePic(const uint8_t* commandData, size_t commandDataLen);
ReturnValue_t commandTcSimplexStreamFile(const uint8_t* commandData, size_t commandDataLen); ReturnValue_t commandTcSimplexStreamFile(const uint8_t* commandData, size_t commandDataLen);
ReturnValue_t commandTcSimplexStoreFile(const uint8_t* commandData, size_t commandDataLen); ReturnValue_t commandTcSplitFile(const uint8_t* commandData, size_t commandDataLen);
ReturnValue_t commandTcDownlinkDataModulate(const uint8_t* commandData, size_t commandDataLen); ReturnValue_t commandTcDownlinkDataModulate(const uint8_t* commandData, size_t commandDataLen);
ReturnValue_t commandTcModeSnapshot(); ReturnValue_t commandTcModeSnapshot();
@@ -203,4 +206,7 @@ class FreshMpsocHandler : public FreshDeviceHandlerBase, public CommandsActionsI
void stopSpecialComHelper(); void stopSpecialComHelper();
void commandSubmodeTransition(); void commandSubmodeTransition();
void commonSpecialComInit();
void commonSpecialComStop();
void commandInitHandling(ActionId_t actionId, MessageQueueId_t commandedBy);
}; };

View File

@@ -241,6 +241,10 @@ ReturnValue_t FreshSupvHandler::executeAction(ActionId_t actionId, MessageQueueI
uartManager->initiateUpdateContinuation(); uartManager->initiateUpdateContinuation();
return EXECUTION_FINISHED; return EXECUTION_FINISHED;
} }
case ABORT_LONGER_REQUEST: {
uartManager->stop();
return EXECUTION_FINISHED;
}
case MEMORY_CHECK_WITH_FILE: { case MEMORY_CHECK_WITH_FILE: {
UpdateParams params; UpdateParams params;
result = extractBaseParams(&data, size, params); result = extractBaseParams(&data, size, params);
@@ -849,6 +853,10 @@ ReturnValue_t FreshSupvHandler::prepareWipeMramCmd(const uint8_t* commandData, s
ReturnValue_t FreshSupvHandler::parseTmPackets() { ReturnValue_t FreshSupvHandler::parseTmPackets() {
uint8_t* receivedData = nullptr; uint8_t* receivedData = nullptr;
size_t receivedSize = 0; size_t receivedSize = 0;
// We do not want to steal packets from the long request handler.
if (uartManager->longerRequestActive()) {
return returnvalue::OK;
}
while (true) { while (true) {
ReturnValue_t result = ReturnValue_t result =
uartManager->readReceivedMessage(comCookie, &receivedData, &receivedSize); uartManager->readReceivedMessage(comCookie, &receivedData, &receivedSize);

View File

@@ -13,6 +13,9 @@ MpsocCommunication::MpsocCommunication(object_id_t objectId, SerialConfig cfg)
ReturnValue_t MpsocCommunication::initialize() { return helper.initialize(); } ReturnValue_t MpsocCommunication::initialize() { return helper.initialize(); }
ReturnValue_t MpsocCommunication::send(const uint8_t* data, size_t dataLen) { ReturnValue_t MpsocCommunication::send(const uint8_t* data, size_t dataLen) {
if (MPSOC_LOW_LEVEL_TX_WIRETAPPING) {
sif::debug << "SEND MPSOC packet with size " << dataLen << std::endl;
}
return helper.send(data, dataLen); return helper.send(data, dataLen);
} }
@@ -27,7 +30,7 @@ ReturnValue_t MpsocCommunication::parseAndRetrieveNextPacket() {
return returnvalue::OK; return returnvalue::OK;
} }
readRingBuf.readData(readBuf, availableReadData); readRingBuf.readData(readBuf, availableReadData);
spReader.setReadOnlyData(readBuf, availableReadData); spReader.setReadOnlyData(readBuf, sizeof(readBuf));
auto res = spReader.checkSize(); auto res = spReader.checkSize();
if (res != returnvalue::OK) { if (res != returnvalue::OK) {
return res; return res;

View File

@@ -9,7 +9,8 @@
#include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h" #include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h"
#include "linux/payload/SerialCommunicationHelper.h" #include "linux/payload/SerialCommunicationHelper.h"
static constexpr bool MPSOC_LOW_LEVEL_RX_WIRETAPPING = true; static constexpr bool MPSOC_LOW_LEVEL_TX_WIRETAPPING = false;
static constexpr bool MPSOC_LOW_LEVEL_RX_WIRETAPPING = false;
class MpsocCommunication : public SystemObject { class MpsocCommunication : public SystemObject {
public: public:

View File

@@ -6,14 +6,16 @@
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
#include "fsfw/serviceinterface/ServiceInterfacePrinter.h"
#include "fsfw/serviceinterface/ServiceInterfaceStream.h"
#include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h"
#include "linux/payload/MpsocCommunication.h" #include "linux/payload/MpsocCommunication.h"
#include "linux/payload/plocMpsocHelpers.h"
#ifdef XIPHOS_Q7S #ifdef XIPHOS_Q7S
#include "bsp_q7s/fs/FilesystemHelper.h" #include "bsp_q7s/fs/FilesystemHelper.h"
#endif #endif
#include "mission/utility/Timestamp.h"
using namespace ploc; using namespace ploc;
PlocMpsocSpecialComHelper::PlocMpsocSpecialComHelper(object_id_t objectId, PlocMpsocSpecialComHelper::PlocMpsocSpecialComHelper(object_id_t objectId,
@@ -51,9 +53,9 @@ ReturnValue_t PlocMpsocSpecialComHelper::performOperation(uint8_t operationCode)
case InternalState::FLASH_WRITE: { case InternalState::FLASH_WRITE: {
result = performFlashWrite(); result = performFlashWrite();
if (result == returnvalue::OK) { if (result == returnvalue::OK) {
triggerEvent(MPSOC_FLASH_WRITE_SUCCESSFUL, sequenceCount->get()); triggerEvent(MPSOC_FLASH_WRITE_SUCCESSFUL, txSequenceCount.get());
} else { } else {
triggerEvent(MPSOC_FLASH_WRITE_FAILED, sequenceCount->get()); triggerEvent(MPSOC_FLASH_WRITE_FAILED, txSequenceCount.get());
} }
internalState = InternalState::IDLE; internalState = InternalState::IDLE;
break; break;
@@ -61,9 +63,10 @@ ReturnValue_t PlocMpsocSpecialComHelper::performOperation(uint8_t operationCode)
case InternalState::FLASH_READ: { case InternalState::FLASH_READ: {
result = performFlashRead(); result = performFlashRead();
if (result == returnvalue::OK) { if (result == returnvalue::OK) {
triggerEvent(MPSOC_FLASH_READ_SUCCESSFUL, sequenceCount->get()); triggerEvent(MPSOC_FLASH_READ_SUCCESSFUL, txSequenceCount.get());
} else { } else {
triggerEvent(MPSOC_FLASH_READ_FAILED, sequenceCount->get()); sif::printWarning("PLOC MPSoC Helper: Flash read failed with code %04x\n", result);
triggerEvent(MPSOC_FLASH_READ_FAILED, txSequenceCount.get(), result);
} }
internalState = InternalState::IDLE; internalState = InternalState::IDLE;
break; break;
@@ -75,8 +78,12 @@ ReturnValue_t PlocMpsocSpecialComHelper::performOperation(uint8_t operationCode)
} }
} }
void PlocMpsocSpecialComHelper::setSequenceCount(SourceSequenceCounter* sequenceCount_) { void PlocMpsocSpecialComHelper::setCommandSequenceCount(uint16_t sequenceCount_) {
sequenceCount = sequenceCount_; txSequenceCount.set(sequenceCount_);
}
uint16_t PlocMpsocSpecialComHelper::getCommandSequenceCount() const {
return txSequenceCount.get();
} }
ReturnValue_t PlocMpsocSpecialComHelper::startFlashWrite(std::string obcFile, ReturnValue_t PlocMpsocSpecialComHelper::startFlashWrite(std::string obcFile,
@@ -148,7 +155,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::performFlashWrite() {
file.read(reinterpret_cast<char*>(fileBuf.data()), dataLength); file.read(reinterpret_cast<char*>(fileBuf.data()), dataLength);
bytesRead += dataLength; bytesRead += dataLength;
remainingSize -= dataLength; remainingSize -= dataLength;
mpsoc::TcFlashWrite tc(spParams, *sequenceCount); mpsoc::TcFlashWrite tc(spParams, txSequenceCount);
result = tc.setPayload(fileBuf.data(), dataLength); result = tc.setPayload(fileBuf.data(), dataLength);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
@@ -157,7 +164,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::performFlashWrite() {
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
(*sequenceCount)++; txSequenceCount.increment();
result = handlePacketTransmissionNoReply(tc); result = handlePacketTransmissionNoReply(tc);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
@@ -172,8 +179,12 @@ ReturnValue_t PlocMpsocSpecialComHelper::performFlashWrite() {
ReturnValue_t PlocMpsocSpecialComHelper::performFlashRead() { ReturnValue_t PlocMpsocSpecialComHelper::performFlashRead() {
std::error_code e; std::error_code e;
std::ofstream ofile(flashReadAndWrite.obcFile, std::ios::trunc | std::ios::binary); if (std::filesystem::exists(flashReadAndWrite.obcFile)) {
if (ofile.bad()) { // Truncate the file first.
std::ofstream ofile(flashReadAndWrite.obcFile, std::ios::binary | std::ios::trunc);
}
std::ofstream ofile(flashReadAndWrite.obcFile, std::ios::binary | std::ios::app);
if (ofile.bad() or not ofile.is_open()) {
return returnvalue::FAILED; return returnvalue::FAILED;
} }
ReturnValue_t result = flashfopen(mpsoc::FileAccessModes::READ); ReturnValue_t result = flashfopen(mpsoc::FileAccessModes::READ);
@@ -196,7 +207,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::performFlashRead() {
std::filesystem::remove(flashReadAndWrite.obcFile, e); std::filesystem::remove(flashReadAndWrite.obcFile, e);
return FILE_READ_ERROR; return FILE_READ_ERROR;
} }
mpsoc::TcFlashRead flashReadRequest(spParams, *sequenceCount); mpsoc::TcFlashRead flashReadRequest(spParams, txSequenceCount);
result = flashReadRequest.setPayload(nextReadSize); result = flashReadRequest.setPayload(nextReadSize);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
std::filesystem::remove(flashReadAndWrite.obcFile, e); std::filesystem::remove(flashReadAndWrite.obcFile, e);
@@ -207,7 +218,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::performFlashRead() {
std::filesystem::remove(flashReadAndWrite.obcFile, e); std::filesystem::remove(flashReadAndWrite.obcFile, e);
return result; return result;
} }
(*sequenceCount)++; txSequenceCount.increment();
result = handlePacketTransmissionFlashRead(flashReadRequest, ofile, nextReadSize); result = handlePacketTransmissionFlashRead(flashReadRequest, ofile, nextReadSize);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
std::filesystem::remove(flashReadAndWrite.obcFile, e); std::filesystem::remove(flashReadAndWrite.obcFile, e);
@@ -224,7 +235,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::performFlashRead() {
ReturnValue_t PlocMpsocSpecialComHelper::flashfopen(uint8_t mode) { ReturnValue_t PlocMpsocSpecialComHelper::flashfopen(uint8_t mode) {
spParams.buf = commandBuffer; spParams.buf = commandBuffer;
mpsoc::FlashFopen flashFopen(spParams, *sequenceCount); mpsoc::TcFlashFopen flashFopen(spParams, txSequenceCount);
ReturnValue_t result = flashFopen.setPayload(flashReadAndWrite.mpsocFile, mode); ReturnValue_t result = flashFopen.setPayload(flashReadAndWrite.mpsocFile, mode);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
@@ -233,7 +244,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::flashfopen(uint8_t mode) {
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
(*sequenceCount)++; txSequenceCount.increment();
result = handlePacketTransmissionNoReply(flashFopen); result = handlePacketTransmissionNoReply(flashFopen);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
@@ -243,12 +254,12 @@ ReturnValue_t PlocMpsocSpecialComHelper::flashfopen(uint8_t mode) {
ReturnValue_t PlocMpsocSpecialComHelper::flashfclose() { ReturnValue_t PlocMpsocSpecialComHelper::flashfclose() {
spParams.buf = commandBuffer; spParams.buf = commandBuffer;
mpsoc::FlashFclose flashFclose(spParams, *sequenceCount); mpsoc::TcFlashFclose flashFclose(spParams, txSequenceCount);
ReturnValue_t result = flashFclose.finishPacket(); ReturnValue_t result = flashFclose.finishPacket();
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
(*sequenceCount)++; txSequenceCount.increment();
result = handlePacketTransmissionNoReply(flashFclose); result = handlePacketTransmissionNoReply(flashFclose);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
@@ -271,6 +282,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::handlePacketTransmissionFlashRead(mpsoc
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
auto& spReader = comInterface.getSpReader();
// We have the nominal case where the flash read report appears first, or the case where we // We have the nominal case where the flash read report appears first, or the case where we
// get an EXE failure immediately. // get an EXE failure immediately.
@@ -281,7 +293,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::handlePacketTransmissionFlashRead(mpsoc
} }
return handleExe(); return handleExe();
} else if (spReader.getApid() == mpsoc::apid::EXE_FAILURE) { } else if (spReader.getApid() == mpsoc::apid::EXE_FAILURE) {
handleExeFailure(); handleExeFailure(spReader);
} else { } else {
triggerEvent(MPSOC_EXE_INVALID_APID, spReader.getApid(), static_cast<uint32_t>(internalState)); triggerEvent(MPSOC_EXE_INVALID_APID, spReader.getApid(), static_cast<uint32_t>(internalState));
sif::warning << "PLOC MPSoC: Expected execution report " sif::warning << "PLOC MPSoC: Expected execution report "
@@ -305,6 +317,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::handlePacketTransmissionNoReply(ploc::S
ReturnValue_t PlocMpsocSpecialComHelper::sendCommand(ploc::SpTcBase& tc) { ReturnValue_t PlocMpsocSpecialComHelper::sendCommand(ploc::SpTcBase& tc) {
ReturnValue_t result = comInterface.send(tc.getFullPacket(), tc.getFullPacketLen()); ReturnValue_t result = comInterface.send(tc.getFullPacket(), tc.getFullPacketLen());
mpsoc::printTxPacket(tc);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
sif::warning << "PlocMPSoCHelper::sendCommand: Failed to send command" << std::endl; sif::warning << "PlocMPSoCHelper::sendCommand: Failed to send command" << std::endl;
triggerEvent(MPSOC_SENDING_COMMAND_FAILED, result, static_cast<uint32_t>(internalState)); triggerEvent(MPSOC_SENDING_COMMAND_FAILED, result, static_cast<uint32_t>(internalState));
@@ -323,6 +336,8 @@ ReturnValue_t PlocMpsocSpecialComHelper::handleAck() {
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
const auto& spReader = comInterface.getSpReader();
uint16_t apid = spReader.getApid(); uint16_t apid = spReader.getApid();
if (apid != mpsoc::apid::ACK_SUCCESS) { if (apid != mpsoc::apid::ACK_SUCCESS) {
handleAckApidFailure(spReader); handleAckApidFailure(spReader);
@@ -331,7 +346,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::handleAck() {
return returnvalue::OK; return returnvalue::OK;
} }
void PlocMpsocSpecialComHelper::handleAckApidFailure(const ploc::SpTmReader& reader) { void PlocMpsocSpecialComHelper::handleAckApidFailure(const SpacePacketReader& reader) {
uint16_t apid = reader.getApid(); uint16_t apid = reader.getApid();
if (apid == mpsoc::apid::ACK_FAILURE) { if (apid == mpsoc::apid::ACK_FAILURE) {
uint16_t status = mpsoc::getStatusFromRawData(reader.getFullData()); uint16_t status = mpsoc::getStatusFromRawData(reader.getFullData());
@@ -355,9 +370,10 @@ ReturnValue_t PlocMpsocSpecialComHelper::handleExe() {
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
const auto& spReader = comInterface.getSpReader();
uint16_t apid = spReader.getApid(); uint16_t apid = spReader.getApid();
if (apid == mpsoc::apid::EXE_FAILURE) { if (apid == mpsoc::apid::EXE_FAILURE) {
handleExeFailure(); handleExeFailure(spReader);
return returnvalue::FAILED; return returnvalue::FAILED;
} else if (apid != mpsoc::apid::EXE_SUCCESS) { } else if (apid != mpsoc::apid::EXE_SUCCESS) {
triggerEvent(MPSOC_EXE_INVALID_APID, apid, static_cast<uint32_t>(internalState)); triggerEvent(MPSOC_EXE_INVALID_APID, apid, static_cast<uint32_t>(internalState));
@@ -367,7 +383,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::handleExe() {
return returnvalue::OK; return returnvalue::OK;
} }
void PlocMpsocSpecialComHelper::handleExeFailure() { void PlocMpsocSpecialComHelper::handleExeFailure(const SpacePacketReader& spReader) {
uint16_t status = mpsoc::getStatusFromRawData(spReader.getFullData()); uint16_t status = mpsoc::getStatusFromRawData(spReader.getFullData());
sif::warning << "PLOC MPSoC EXE Failure: " << mpsoc::getStatusString(status) << std::endl; sif::warning << "PLOC MPSoC EXE Failure: " << mpsoc::getStatusString(status) << std::endl;
triggerEvent(MPSOC_EXE_FAILURE_REPORT, static_cast<uint32_t>(internalState)); triggerEvent(MPSOC_EXE_FAILURE_REPORT, static_cast<uint32_t>(internalState));
@@ -376,46 +392,32 @@ void PlocMpsocSpecialComHelper::handleExeFailure() {
ReturnValue_t PlocMpsocSpecialComHelper::handleTmReception() { ReturnValue_t PlocMpsocSpecialComHelper::handleTmReception() {
ReturnValue_t result = returnvalue::OK; ReturnValue_t result = returnvalue::OK;
tmCountdown.resetTimer(); tmCountdown.resetTimer();
size_t readBytes = 0;
size_t currentBytes = 0;
uint32_t usleepDelay = 5; uint32_t usleepDelay = 5;
size_t fullPacketLen = 0;
while (true) { while (true) {
if (tmCountdown.hasTimedOut()) { if (tmCountdown.hasTimedOut()) {
triggerEvent(MPSOC_READ_TIMEOUT, tmCountdown.getTimeoutMs()); triggerEvent(MPSOC_READ_TIMEOUT, tmCountdown.getTimeoutMs());
return returnvalue::FAILED; return returnvalue::FAILED;
} }
result = receive(tmBuf.data() + readBytes, 6, &currentBytes); result = tryReceiveNextReply();
if (result == MpsocCommunication::PACKET_RECEIVED) {
// Need to convert this, we are faking a synchronous API here.
result = returnvalue::OK;
break;
}
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
if (result == MpsocCommunication::FAULTY_PACKET_SIZE) {
sif::printWarning("PLOC MPSoC Helper: retrieving next reply failed: faulty packet size\n");
} else if (result == MpsocCommunication::CRC_CHECK_FAILED) {
sif::printWarning("PLOC MPSoC Helper: retrieving next reply failed: CRC check failed\n");
}
sif::printWarning("PLOC MPSoC Helper: retrieving next reply failed with code %d\n", result);
return result; return result;
} }
spReader.setReadOnlyData(tmBuf.data(), tmBuf.size());
fullPacketLen = spReader.getFullPacketLen();
readBytes += currentBytes;
if (readBytes == 6) {
break;
}
usleep(usleepDelay); usleep(usleepDelay);
if (usleepDelay < 200000) { if (usleepDelay < 200000) {
usleepDelay *= 4; usleepDelay *= 4;
} }
} }
while (true) {
if (tmCountdown.hasTimedOut()) {
triggerEvent(MPSOC_READ_TIMEOUT, tmCountdown.getTimeoutMs());
return returnvalue::FAILED;
}
result = receive(tmBuf.data() + readBytes, fullPacketLen - readBytes, &currentBytes);
readBytes += currentBytes;
if (fullPacketLen == readBytes) {
break;
}
usleep(usleepDelay);
if (usleepDelay < 200000) {
usleepDelay *= 4;
}
}
// arrayprinter::print(tmBuf.data(), readBytes);
return result; return result;
} }
@@ -425,6 +427,7 @@ ReturnValue_t PlocMpsocSpecialComHelper::handleFlashReadReply(std::ofstream& ofi
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
auto& spReader = comInterface.getSpReader();
uint16_t apid = spReader.getApid(); uint16_t apid = spReader.getApid();
if (apid != mpsoc::apid::TM_FLASH_READ_REPORT) { if (apid != mpsoc::apid::TM_FLASH_READ_REPORT) {
triggerEvent(MPSOC_FLASH_READ_PACKET_ERROR, FlashReadErrorType::FLASH_READ_APID_ERROR); triggerEvent(MPSOC_FLASH_READ_PACKET_ERROR, FlashReadErrorType::FLASH_READ_APID_ERROR);
@@ -490,25 +493,19 @@ ReturnValue_t PlocMpsocSpecialComHelper::startFlashReadOrWriteBase(std::string o
} }
ReturnValue_t PlocMpsocSpecialComHelper::checkReceivedTm() { ReturnValue_t PlocMpsocSpecialComHelper::checkReceivedTm() {
const auto& spReader = comInterface.getSpReader();
ReturnValue_t result = spReader.checkSize(); ReturnValue_t result = spReader.checkSize();
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
sif::error << "PLOC MPSoC: Size check on received TM failed" << std::endl; sif::error << "PLOC MPSoC: Size check on received TM failed" << std::endl;
triggerEvent(MPSOC_TM_SIZE_ERROR); triggerEvent(MPSOC_TM_SIZE_ERROR);
return result; return result;
} }
// No CRC check, this is already done by the communication interface.. rxSequenceCount = spReader.getSequenceCount();
uint16_t recvSeqCnt = spReader.getSequenceCount(); mpsoc::printRxPacket(spReader);
if (recvSeqCnt != *sequenceCount) {
triggerEvent(MPSOC_HELPER_SEQ_CNT_MISMATCH, *sequenceCount, recvSeqCnt);
*sequenceCount = recvSeqCnt;
}
// This sequence count ping pong does not make any sense but it is how the MPSoC expects it.
(*sequenceCount)++;
return returnvalue::OK; return returnvalue::OK;
} }
ReturnValue_t PlocMpsocSpecialComHelper::receive(uint8_t* data, size_t requestBytes, ReturnValue_t PlocMpsocSpecialComHelper::tryReceiveNextReply() {
size_t* readBytes) {
ReturnValue_t result = returnvalue::OK; ReturnValue_t result = returnvalue::OK;
result = comInterface.readSerialInterface(); result = comInterface.readSerialInterface();
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
@@ -516,11 +513,5 @@ ReturnValue_t PlocMpsocSpecialComHelper::receive(uint8_t* data, size_t requestBy
static_cast<uint32_t>(static_cast<uint32_t>(internalState))); static_cast<uint32_t>(static_cast<uint32_t>(internalState)));
return returnvalue::FAILED; return returnvalue::FAILED;
} }
result = comInterface.parseAndRetrieveNextPacket(); return comInterface.parseAndRetrieveNextPacket();
if (result == MpsocCommunication::PACKET_RECEIVED) {
auto& spReader = comInterface.getSpReader();
// Maybe unnecessary copy, but the easiest way to get this done for now..
std::memcpy(data, spReader.getFullData(), spReader.getFullPacketLen());
}
return result;
} }

View File

@@ -10,6 +10,7 @@
#include "fsfw/osal/linux/BinarySemaphore.h" #include "fsfw/osal/linux/BinarySemaphore.h"
#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/returnvalues/returnvalue.h"
#include "fsfw/tasks/ExecutableObjectIF.h" #include "fsfw/tasks/ExecutableObjectIF.h"
#include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h"
#include "fsfw/tmtcservices/SourceSequenceCounter.h" #include "fsfw/tmtcservices/SourceSequenceCounter.h"
#include "linux/payload/MpsocCommunication.h" #include "linux/payload/MpsocCommunication.h"
#ifdef XIPHOS_Q7S #ifdef XIPHOS_Q7S
@@ -113,7 +114,8 @@ class PlocMpsocSpecialComHelper : public SystemObject, public ExecutableObjectIF
/** /**
* @brief Sets the sequence count object responsible for the sequence count handling * @brief Sets the sequence count object responsible for the sequence count handling
*/ */
void setSequenceCount(SourceSequenceCounter* sequenceCount_); void setCommandSequenceCount(uint16_t sequenceCount_);
uint16_t getCommandSequenceCount() const;
private: private:
static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_MPSOC_HELPER; static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_MPSOC_HELPER;
@@ -169,8 +171,9 @@ class PlocMpsocSpecialComHelper : public SystemObject, public ExecutableObjectIF
// CookieIF* comCookie = nullptr; // CookieIF* comCookie = nullptr;
MpsocCommunication& comInterface; MpsocCommunication& comInterface;
// Sequence count, must be set by Ploc MPSoC Handler // Sequence count, must be set by Ploc MPSoC Handler
SourceSequenceCounter* sequenceCount = nullptr; // ploc::SpTmReader spReader;
ploc::SpTmReader spReader; uint16_t rxSequenceCount = 0;
SourceSequenceCounter txSequenceCount = 0;
void resetHelper(); void resetHelper();
ReturnValue_t performFlashWrite(); ReturnValue_t performFlashWrite();
@@ -182,13 +185,13 @@ class PlocMpsocSpecialComHelper : public SystemObject, public ExecutableObjectIF
size_t expectedReadLen); size_t expectedReadLen);
ReturnValue_t handleFlashReadReply(std::ofstream& ofile, size_t expectedReadLen); ReturnValue_t handleFlashReadReply(std::ofstream& ofile, size_t expectedReadLen);
ReturnValue_t sendCommand(ploc::SpTcBase& tc); ReturnValue_t sendCommand(ploc::SpTcBase& tc);
ReturnValue_t receive(uint8_t* data, size_t requestBytes, size_t* readBytes); ReturnValue_t tryReceiveNextReply();
ReturnValue_t handleAck(); ReturnValue_t handleAck();
ReturnValue_t handleExe(); ReturnValue_t handleExe();
ReturnValue_t startFlashReadOrWriteBase(std::string obcFile, std::string mpsocFile); ReturnValue_t startFlashReadOrWriteBase(std::string obcFile, std::string mpsocFile);
ReturnValue_t fileCheck(std::string obcFile); ReturnValue_t fileCheck(std::string obcFile);
void handleAckApidFailure(const ploc::SpTmReader& reader); void handleAckApidFailure(const SpacePacketReader& reader);
void handleExeFailure(); void handleExeFailure(const SpacePacketReader& reader);
ReturnValue_t handleTmReception(); ReturnValue_t handleTmReception();
ReturnValue_t checkReceivedTm(); ReturnValue_t checkReceivedTm();
}; };

View File

@@ -11,6 +11,8 @@
#include <fstream> #include <fstream>
#include "OBSWConfig.h" #include "OBSWConfig.h"
#include "fsfw/returnvalues/returnvalue.h"
#include "linux/payload/plocSupvDefs.h"
#include "tas/hdlc.h" #include "tas/hdlc.h"
#ifdef XIPHOS_Q7S #ifdef XIPHOS_Q7S
#include "bsp_q7s/fs/FilesystemHelper.h" #include "bsp_q7s/fs/FilesystemHelper.h"
@@ -21,9 +23,13 @@
#include "fsfw/tasks/TaskFactory.h" #include "fsfw/tasks/TaskFactory.h"
#include "fsfw/timemanager/Countdown.h" #include "fsfw/timemanager/Countdown.h"
#if OBSW_DEBUG_PLOC_SUPERVISOR == 1
#include "mission/utility/Filenaming.h" #include "mission/utility/Filenaming.h"
#include "mission/utility/ProgressPrinter.h" #include "mission/utility/ProgressPrinter.h"
#include "mission/utility/Timestamp.h" #include "mission/utility/Timestamp.h"
#endif
#include "tas/crc.h" #include "tas/crc.h"
using namespace returnvalue; using namespace returnvalue;
@@ -277,23 +283,6 @@ ReturnValue_t PlocSupvUartManager::initiateUpdateContinuation() {
return returnvalue::OK; return returnvalue::OK;
} }
// ReturnValue_t PlocSupvHelper::startEventBufferRequest(std::string path) {
// #ifdef XIPHOS_Q7S
// ReturnValue_t result = FilesystemHelper::checkPath(path);
// if (result != returnvalue::OK) {
// return result;
// }
// #endif
// if (not std::filesystem::exists(path)) {
// return PATH_NOT_EXISTS;
// }
// eventBufferReq.path = path;
// request = Request::REQUEST_EVENT_BUFFER;
// //uartComIF->flushUartTxAndRxBuf(comCookie);
// semaphore->release();
// return returnvalue::OK;
// }
void PlocSupvUartManager::stop() { void PlocSupvUartManager::stop() {
MutexGuard mg(lock); MutexGuard mg(lock);
if (state == InternalState::SLEEPING or state == InternalState::GO_TO_SLEEP) { if (state == InternalState::SLEEPING or state == InternalState::GO_TO_SLEEP) {
@@ -437,6 +426,8 @@ ReturnValue_t PlocSupvUartManager::writeUpdatePackets() {
// Useful to allow restarting the update // Useful to allow restarting the update
triggerEvent(SUPV_UPDATE_PROGRESS, buildProgParams1(progPercent, update.sequenceCount), triggerEvent(SUPV_UPDATE_PROGRESS, buildProgParams1(progPercent, update.sequenceCount),
update.bytesWritten); update.bytesWritten);
sif::info << "PLOC SUPV update progress " << (int)progPercent << " % at "
<< update.bytesWritten << " bytes" << std::endl;
} }
} }
supv::WriteMemory packet(spParams); supv::WriteMemory packet(spParams);
@@ -447,10 +438,8 @@ ReturnValue_t PlocSupvUartManager::writeUpdatePackets() {
update.bytesWritten); update.bytesWritten);
return result; return result;
} }
result = handlePacketTransmissionNoReply(packet, 5000); result = writeMemoryHandlingWithRetryLogic(packet, progPercent);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
triggerEvent(WRITE_MEMORY_FAILED, buildProgParams1(progPercent, update.sequenceCount),
update.bytesWritten);
return result; return result;
} }
@@ -461,7 +450,25 @@ ReturnValue_t PlocSupvUartManager::writeUpdatePackets() {
#if OBSW_DEBUG_PLOC_SUPERVISOR == 1 #if OBSW_DEBUG_PLOC_SUPERVISOR == 1
progressPrinter.print(update.bytesWritten); progressPrinter.print(update.bytesWritten);
#endif /* OBSW_DEBUG_PLOC_SUPERVISOR == 1 */ #endif /* OBSW_DEBUG_PLOC_SUPERVISOR == 1 */
// TaskFactory::delayTask(1); }
return result;
}
ReturnValue_t PlocSupvUartManager::writeMemoryHandlingWithRetryLogic(supv::WriteMemory& packet,
unsigned progPercent) {
ReturnValue_t result = returnvalue::OK;
// Simple re-try logic in place to deal with communication unreliability in orbit.
for (uint8_t retryCount = 0; retryCount < MAX_RETRY_COUNT; retryCount++) {
result = handlePacketTransmissionNoReply(packet, COM_TIMEOUT_MS);
if (result == returnvalue::OK) {
return result;
}
triggerEvent(WRITE_MEMORY_FAILED, buildProgParams1(progPercent, update.sequenceCount),
update.bytesWritten);
// Clear data structures related to reply handling.
serial::flushTxRxBuf(serialPort);
recRingBuf.clear();
decodedRingBuf.clear();
} }
return result; return result;
} }
@@ -570,7 +577,16 @@ ReturnValue_t PlocSupvUartManager::handlePacketTransmissionNoReply(
bool ackReceived = false; bool ackReceived = false;
bool packetWasHandled = false; bool packetWasHandled = false;
while (true) { while (true) {
handleUartReception(); ReturnValue_t status = handleUartReception();
if (status != returnvalue::OK) {
result = status;
if (result == HDLC_ERROR) {
// We could bail here immediately.. but I prefer to wait for the timeout, because we should
// ensure that all packets which might be related to the transfer are still received and
// cleared from all data structures related to reply handling.
// return result;
}
}
if (not decodedQueue.empty()) { if (not decodedQueue.empty()) {
size_t packetLen = 0; size_t packetLen = 0;
decodedQueue.retrieve(&packetLen); decodedQueue.retrieve(&packetLen);
@@ -613,7 +629,7 @@ ReturnValue_t PlocSupvUartManager::handlePacketTransmissionNoReply(
return result::NO_REPLY_TIMEOUT; return result::NO_REPLY_TIMEOUT;
} }
} }
return returnvalue::OK; return result;
} }
int PlocSupvUartManager::handleAckReception(supv::TcBase& tc, size_t packetLen) { int PlocSupvUartManager::handleAckReception(supv::TcBase& tc, size_t packetLen) {

View File

@@ -118,6 +118,7 @@ class PlocSupvUartManager : public DeviceCommunicationIF,
static constexpr Event HDLC_FRAME_REMOVAL_ERROR = MAKE_EVENT(31, severity::INFO); static constexpr Event HDLC_FRAME_REMOVAL_ERROR = MAKE_EVENT(31, severity::INFO);
static constexpr Event HDLC_CRC_ERROR = MAKE_EVENT(32, severity::INFO); static constexpr Event HDLC_CRC_ERROR = MAKE_EVENT(32, severity::INFO);
static constexpr unsigned MAX_RETRY_COUNT = 3;
PlocSupvUartManager(object_id_t objectId); PlocSupvUartManager(object_id_t objectId);
virtual ~PlocSupvUartManager(); virtual ~PlocSupvUartManager();
/** /**
@@ -199,6 +200,8 @@ class PlocSupvUartManager : public DeviceCommunicationIF,
static constexpr ReturnValue_t POSSIBLE_PACKET_LOSS_CONSECUTIVE_END = returnvalue::makeCode(1, 4); static constexpr ReturnValue_t POSSIBLE_PACKET_LOSS_CONSECUTIVE_END = returnvalue::makeCode(1, 4);
static constexpr ReturnValue_t HDLC_ERROR = returnvalue::makeCode(1, 5); static constexpr ReturnValue_t HDLC_ERROR = returnvalue::makeCode(1, 5);
static constexpr uint32_t COM_TIMEOUT_MS = 3000;
static const uint16_t CRC16_INIT = 0xFFFF; static const uint16_t CRC16_INIT = 0xFFFF;
// Event buffer reply will carry 24 space packets with 1016 bytes and one space packet with // Event buffer reply will carry 24 space packets with 1016 bytes and one space packet with
// 192 bytes // 192 bytes
@@ -369,6 +372,8 @@ class PlocSupvUartManager : public DeviceCommunicationIF,
*/ */
ReturnValue_t requestReceiveMessage(CookieIF* cookie, size_t requestLen) override; ReturnValue_t requestReceiveMessage(CookieIF* cookie, size_t requestLen) override;
ReturnValue_t writeMemoryHandlingWithRetryLogic(supv::WriteMemory& packet, unsigned progPercent);
void performUartShutdown(); void performUartShutdown();
void updateVtime(uint8_t vtime); void updateVtime(uint8_t vtime);
}; };

View File

@@ -1,5 +1,8 @@
#include "plocMpsocHelpers.h" #include "plocMpsocHelpers.h"
#include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h"
#include "mission/payload/plocSpBase.h"
uint16_t mpsoc::getStatusFromRawData(const uint8_t* data) { uint16_t mpsoc::getStatusFromRawData(const uint8_t* data) {
return (*(data + STATUS_OFFSET) << 8) | *(data + STATUS_OFFSET + 1); return (*(data + STATUS_OFFSET) << 8) | *(data + STATUS_OFFSET + 1);
} }
@@ -13,6 +16,10 @@ std::string mpsoc::getStatusString(uint16_t status) {
return "Incorrect length"; return "Incorrect length";
break; break;
} }
case (mpsoc::statusCode::FLASH_DRIVE_ERROR): {
return "flash drive error";
break;
}
case (mpsoc::statusCode::INCORRECT_CRC): { case (mpsoc::statusCode::INCORRECT_CRC): {
return "Incorrect crc"; return "Incorrect crc";
break; break;
@@ -93,3 +100,19 @@ std::string mpsoc::getStatusString(uint16_t status) {
} }
return ""; return "";
} }
void mpsoc::printRxPacket(const SpacePacketReader& spReader) {
if (mpsoc::MPSOC_RX_WIRETAPPING) {
sif::debug << "RECV MPSOC packet. APID 0x" << std::hex << std::setw(3) << spReader.getApid()
<< std::dec << " Size " << spReader.getFullPacketLen() << " SSC "
<< spReader.getSequenceCount() << std::endl;
}
}
void mpsoc::printTxPacket(const ploc::SpTcBase& tcBase) {
if (mpsoc::MPSOC_TX_WIRETAPPING) {
sif::debug << "SEND MPSOC packet. APID 0x" << std::hex << std::setw(3) << tcBase.getApid()
<< " Size " << std::dec << tcBase.getFullPacketLen() << " SSC "
<< tcBase.getSeqCount() << std::endl;
}
}

View File

@@ -5,20 +5,65 @@
#include <fsfw/devicehandlers/DeviceHandlerIF.h> #include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include <mission/payload/plocSpBase.h> #include <mission/payload/plocSpBase.h>
#include "eive/definitions.h"
#include "eive/eventSubsystemIds.h" #include "eive/eventSubsystemIds.h"
#include "eive/resultClassIds.h" #include "eive/resultClassIds.h"
#include "fsfw/action/HasActionsIF.h" #include "fsfw/action/HasActionsIF.h"
#include "fsfw/events/Event.h"
#include "fsfw/returnvalues/returnvalue.h" #include "fsfw/returnvalues/returnvalue.h"
#include "fsfw/serialize/SerializeAdapter.h" #include "fsfw/serialize/SerializeAdapter.h"
#include "fsfw/serialize/SerializeIF.h" #include "fsfw/serialize/SerializeIF.h"
namespace mpsoc { namespace mpsoc {
static constexpr bool MPSOC_TX_WIRETAPPING = false;
static constexpr bool MPSOC_RX_WIRETAPPING = false;
static constexpr size_t CRC_SIZE = 2;
/**
* @brief Abstract base class for TC space packet of MPSoC.
*/
class TcBase : public ploc::SpTcBase {
public:
virtual ~TcBase() = default;
// Initial length field of space packet. Will always be updated when packet is created.
static const uint16_t INIT_LENGTH = CRC_SIZE;
/**
* @brief Constructor
*
* @param sequenceCount Sequence count of space packet which will be incremented with each
* sent and received packets.
*/
TcBase(ploc::SpTcParams params, uint16_t apid, uint16_t sequenceCount)
: ploc::SpTcBase(params, apid, 0, sequenceCount) {
payloadStart = spParams.buf + ccsds::HEADER_LEN;
spParams.setFullPayloadLen(INIT_LENGTH);
}
/**
* @brief Function to finsh and write the space packet. It is expected that the user has
* set the payload fields in the child class*
* @return returnvalue::OK if packet creation was successful, otherwise error return value
*/
ReturnValue_t finishPacket() {
updateSpFields();
ReturnValue_t res = checkSizeAndSerializeHeader();
if (res != returnvalue::OK) {
return res;
}
return calcAndSetCrc();
}
};
void printRxPacket(const SpacePacketReader& spReader);
void printTxPacket(const ploc::SpTcBase& tcBase);
static constexpr uint32_t DEFAULT_CMD_TIMEOUT_MS = 5000; static constexpr uint32_t DEFAULT_CMD_TIMEOUT_MS = 5000;
static constexpr uint32_t CMD_TIMEOUT_MKFS = 15000; static constexpr uint32_t CMD_TIMEOUT_MKFS = 15000;
enum FlashId : uint8_t { FLASH_0 = 0, FLASH_1 = 0 }; enum FlashId : uint8_t { FLASH_0 = 0, FLASH_1 = 1 };
static const uint8_t INTERFACE_ID = CLASS_ID::MPSOC_RETURN_VALUES_IF; static const uint8_t INTERFACE_ID = CLASS_ID::MPSOC_RETURN_VALUES_IF;
@@ -68,7 +113,11 @@ static const Event MPSOC_SHUTDOWN_FAILED = MAKE_EVENT(6, severity::HIGH);
//! [EXPORT] : [COMMENT] SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for //! [EXPORT] : [COMMENT] SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for
//! ON transition. //! ON transition.
static constexpr Event SUPV_NOT_ON = event::makeEvent(SUBSYSTEM_ID, 7, severity::LOW); static constexpr Event SUPV_NOT_ON = event::makeEvent(SUBSYSTEM_ID, 7, severity::LOW);
//! [EXPORT] : [COMMENT] SUPV reply timeout.
static constexpr Event SUPV_REPLY_TIMEOUT = event::makeEvent(SUBSYSTEM_ID, 8, severity::LOW); static constexpr Event SUPV_REPLY_TIMEOUT = event::makeEvent(SUBSYSTEM_ID, 8, severity::LOW);
//! [EXPORT] : [COMMENT] Camera must be commanded on first.
static constexpr Event CAM_MUST_BE_ON_FOR_SNAPSHOT_MODE =
event::makeEvent(SUBSYSTEM_ID, 9, severity::LOW);
enum ParamId : uint8_t { SKIP_SUPV_ON_COMMANDING = 0x01 }; enum ParamId : uint8_t { SKIP_SUPV_ON_COMMANDING = 0x01 };
@@ -161,7 +210,7 @@ static const DeviceCommandId_t TC_FLASH_GET_DIRECTORY_CONTENT = 28;
static const DeviceCommandId_t TM_FLASH_DIRECTORY_CONTENT = 29; static const DeviceCommandId_t TM_FLASH_DIRECTORY_CONTENT = 29;
static constexpr DeviceCommandId_t TC_FLASH_READ_FULL_FILE = 30; static constexpr DeviceCommandId_t TC_FLASH_READ_FULL_FILE = 30;
// Store file on MPSoC. // Store file on MPSoC.
static const DeviceCommandId_t TC_SIMPLEX_STORE_FILE = 31; static const DeviceCommandId_t TC_SPLIT_FILE = 31;
static const DeviceCommandId_t TC_VERIFY_BOOT = 32; static const DeviceCommandId_t TC_VERIFY_BOOT = 32;
static const DeviceCommandId_t TC_ENABLE_TC_EXECTION = 33; static const DeviceCommandId_t TC_ENABLE_TC_EXECTION = 33;
static const DeviceCommandId_t TC_FLASH_MKFS = 34; static const DeviceCommandId_t TC_FLASH_MKFS = 34;
@@ -171,8 +220,6 @@ static const DeviceCommandId_t OBSW_RESET_SEQ_COUNT_LEGACY = 50;
static const uint16_t SIZE_ACK_REPORT = 14; static const uint16_t SIZE_ACK_REPORT = 14;
static const uint16_t SIZE_EXE_REPORT = 14; static const uint16_t SIZE_EXE_REPORT = 14;
// static const uint16_t SIZE_TM_MEM_READ_REPORT = 18;
// static const uint16_t SIZE_TM_CAM_CMD_RPT = 18;
static constexpr size_t SIZE_TM_HK_REPORT = 369; static constexpr size_t SIZE_TM_HK_REPORT = 369;
enum Submode : uint8_t { IDLE_OR_NONE = 0, REPLAY = 1, SNAPSHOT = 2 }; enum Submode : uint8_t { IDLE_OR_NONE = 0, REPLAY = 1, SNAPSHOT = 2 };
@@ -237,15 +284,15 @@ static const uint8_t SPACE_PACKET_HEADER_SIZE = 6;
static const uint8_t STATUS_OFFSET = 10; static const uint8_t STATUS_OFFSET = 10;
static constexpr size_t CRC_SIZE = 2;
/** /**
* The size of payload data which will be forwarded to the requesting object. e.g. PUS Service * The size of payload data which will be forwarded to the requesting object. e.g. PUS Service
* 8. * 8.
*/ */
static const uint8_t SIZE_MEM_READ_RPT_FIX = 6; static const uint8_t SIZE_MEM_READ_RPT_FIX = 6;
static const size_t MAX_FILENAME_SIZE = 256; static const size_t FILENAME_FIELD_SIZE = 256;
// Subtract size of NULL terminator.
static const size_t MAX_FILENAME_SIZE = FILENAME_FIELD_SIZE - 1;
/** /**
* PLOC space packet length for fixed size packets. This is the size of the whole packet data * PLOC space packet length for fixed size packets. This is the size of the whole packet data
@@ -282,6 +329,7 @@ static const uint16_t TC_SIMPLEX_SEND_FILE_DELAY = 80;
namespace statusCode { namespace statusCode {
static const uint16_t DEFAULT_ERROR_CODE = 0x1; static const uint16_t DEFAULT_ERROR_CODE = 0x1;
static constexpr uint16_t FLASH_DRIVE_ERROR = 0xb;
static const uint16_t UNKNOWN_APID = 0x5DD; static const uint16_t UNKNOWN_APID = 0x5DD;
static const uint16_t INCORRECT_LENGTH = 0x5DE; static const uint16_t INCORRECT_LENGTH = 0x5DE;
static const uint16_t INCORRECT_CRC = 0x5DF; static const uint16_t INCORRECT_CRC = 0x5DF;
@@ -308,47 +356,10 @@ static const uint16_t RESERVED_3 = 0x5F3;
static const uint16_t RESERVED_4 = 0x5F4; static const uint16_t RESERVED_4 = 0x5F4;
} // namespace statusCode } // namespace statusCode
/**
* @brief Abstract base class for TC space packet of MPSoC.
*/
class TcBase : public ploc::SpTcBase {
public:
virtual ~TcBase() = default;
// Initial length field of space packet. Will always be updated when packet is created.
static const uint16_t INIT_LENGTH = CRC_SIZE;
/**
* @brief Constructor
*
* @param sequenceCount Sequence count of space packet which will be incremented with each
* sent and received packets.
*/
TcBase(ploc::SpTcParams params, uint16_t apid, uint16_t sequenceCount)
: ploc::SpTcBase(params, apid, 0, sequenceCount) {
payloadStart = spParams.buf + ccsds::HEADER_LEN;
spParams.setFullPayloadLen(INIT_LENGTH);
}
/**
* @brief Function to finsh and write the space packet. It is expected that the user has
* set the payload fields in the child class*
* @return returnvalue::OK if packet creation was successful, otherwise error return value
*/
ReturnValue_t finishPacket() {
updateSpFields();
ReturnValue_t res = checkSizeAndSerializeHeader();
if (res != returnvalue::OK) {
return res;
}
return calcAndSetCrc();
}
};
/** /**
* @brief This class helps to build the memory read command for the PLOC. * @brief This class helps to build the memory read command for the PLOC.
*/ */
class TcMemRead : public TcBase { class TcMemRead : public mpsoc::TcBase {
public: public:
/** /**
* @brief Constructor * @brief Constructor
@@ -398,7 +409,7 @@ class TcMemRead : public TcBase {
* @brief This class helps to generate the space packet to write data to a memory address within * @brief This class helps to generate the space packet to write data to a memory address within
* the PLOC. * the PLOC.
*/ */
class TcMemWrite : public TcBase { class TcMemWrite : public mpsoc::TcBase {
public: public:
/** /**
* @brief Constructor * @brief Constructor
@@ -448,24 +459,21 @@ class TcMemWrite : public TcBase {
/** /**
* @brief Class to help creation of flash fopen command. * @brief Class to help creation of flash fopen command.
*/ */
class FlashFopen : public TcBase { class TcFlashFopen : public mpsoc::TcBase {
public: public:
FlashFopen(ploc::SpTcParams params, uint16_t sequenceCount) TcFlashFopen(ploc::SpTcParams params, uint16_t sequenceCount)
: TcBase(params, apid::TC_FLASHFOPEN, sequenceCount) {} : TcBase(params, apid::TC_FLASHFOPEN, sequenceCount) {}
ReturnValue_t setPayload(std::string filename, uint8_t mode) { ReturnValue_t setPayload(std::string filename, uint8_t mode) {
accessMode = mode; accessMode = mode;
size_t nameSize = filename.size();
spParams.setFullPayloadLen(256 + sizeof(uint8_t) + CRC_SIZE);
ReturnValue_t result = checkPayloadLen(); ReturnValue_t result = checkPayloadLen();
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
std::memcpy(payloadStart, filename.c_str(), nameSize); std::memset(payloadStart, 0, FILENAME_FIELD_SIZE);
// payloadStart[nameSize] = NULL_TERMINATOR; std::memcpy(payloadStart, filename.c_str(), filename.size());
std::memset(payloadStart + nameSize, 0, 256 - nameSize); payloadStart[FILENAME_FIELD_SIZE] = accessMode;
// payloadStart[255] = NULL_TERMINATOR; spParams.setFullPayloadLen(FILENAME_FIELD_SIZE + 1 + CRC_SIZE);
payloadStart[256] = accessMode;
return returnvalue::OK; return returnvalue::OK;
} }
@@ -476,9 +484,9 @@ class FlashFopen : public TcBase {
/** /**
* @brief Class to help creation of flash fclose command. * @brief Class to help creation of flash fclose command.
*/ */
class FlashFclose : public TcBase { class TcFlashFclose : public TcBase {
public: public:
FlashFclose(ploc::SpTcParams params, uint16_t sequenceCount) TcFlashFclose(ploc::SpTcParams params, uint16_t sequenceCount)
: TcBase(params, apid::TC_FLASHFCLOSE, sequenceCount) { : TcBase(params, apid::TC_FLASHFCLOSE, sequenceCount) {
spParams.setFullPayloadLen(CRC_SIZE); spParams.setFullPayloadLen(CRC_SIZE);
} }
@@ -505,8 +513,14 @@ class TcFlashMkfs : public TcBase {
public: public:
TcFlashMkfs(ploc::SpTcParams params, uint16_t sequenceCount, FlashId flashId) TcFlashMkfs(ploc::SpTcParams params, uint16_t sequenceCount, FlashId flashId)
: TcBase(params, apid::TC_FLASH_MKFS, sequenceCount) { : TcBase(params, apid::TC_FLASH_MKFS, sequenceCount) {
spParams.setFullPayloadLen(1 + CRC_SIZE); const char* flashIdStr = "0:\\";
payloadStart[0] = flashId; if (flashId == FlashId::FLASH_1) {
flashIdStr = "1:\\";
}
std::memcpy(payloadStart, flashIdStr, 3);
// Null terminator
payloadStart[3] = 0;
spParams.setFullPayloadLen(4 + CRC_SIZE);
} }
}; };
@@ -569,15 +583,6 @@ class TcFlashRead : public TcBase {
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
updateSpFields();
result = checkSizeAndSerializeHeader();
if (result != returnvalue::OK) {
return result;
}
result = calcAndSetCrc();
if (result != returnvalue::OK) {
return result;
}
readSize = readLen; readSize = readLen;
return result; return result;
} }
@@ -595,20 +600,14 @@ class TcFlashDelete : public TcBase {
ReturnValue_t setPayload(std::string filename) { ReturnValue_t setPayload(std::string filename) {
size_t nameSize = filename.size(); size_t nameSize = filename.size();
spParams.setFullPayloadLen(nameSize + sizeof(NULL_TERMINATOR) + CRC_SIZE); spParams.setFullPayloadLen(FILENAME_FIELD_SIZE + CRC_SIZE);
auto res = checkPayloadLen(); auto res = checkPayloadLen();
if (res != returnvalue::OK) { if (res != returnvalue::OK) {
return res; return res;
} }
std::memcpy(payloadStart, filename.c_str(), nameSize); std::memcpy(payloadStart, filename.c_str(), nameSize);
*(payloadStart + nameSize) = NULL_TERMINATOR; *(payloadStart + nameSize) = NULL_TERMINATOR;
return returnvalue::OK;
updateSpFields();
res = checkSizeAndSerializeHeader();
if (res != returnvalue::OK) {
return res;
}
return calcAndSetCrc();
} }
}; };
@@ -760,8 +759,9 @@ class TcGetDirContent : public TcBase {
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
return result; return result;
} }
std::memset(payloadStart, 0, 256);
std::memcpy(payloadStart, commandData, commandDataLen); std::memcpy(payloadStart, commandData, commandDataLen);
payloadStart[255] = '\0'; payloadStart[255] = 0;
return result; return result;
} }
}; };
@@ -802,7 +802,7 @@ class TcReplayWriteSeq : public TcBase {
static const size_t USE_DECODING_LENGTH = 1; static const size_t USE_DECODING_LENGTH = 1;
ReturnValue_t lengthCheck(size_t commandDataLen) { ReturnValue_t lengthCheck(size_t commandDataLen) {
if (commandDataLen > USE_DECODING_LENGTH + MAX_FILENAME_SIZE or if (commandDataLen > USE_DECODING_LENGTH + FILENAME_FIELD_SIZE or
checkPayloadLen() != returnvalue::OK) { checkPayloadLen() != returnvalue::OK) {
sif::warning << "TcReplayWriteSeq: Command has invalid length " << commandDataLen sif::warning << "TcReplayWriteSeq: Command has invalid length " << commandDataLen
<< std::endl; << std::endl;
@@ -821,18 +821,18 @@ class FlashBasePusCmd {
virtual ~FlashBasePusCmd() = default; virtual ~FlashBasePusCmd() = default;
virtual ReturnValue_t extractFields(const uint8_t* commandData, size_t commandDataLen) { virtual ReturnValue_t extractFields(const uint8_t* commandData, size_t commandDataLen) {
if (commandDataLen > (config::MAX_PATH_SIZE + config::MAX_FILENAME_SIZE + MAX_FILENAME_SIZE)) { if (commandDataLen > FILENAME_FIELD_SIZE) {
return INVALID_LENGTH; return INVALID_LENGTH;
} }
size_t fileLen = strnlen(reinterpret_cast<const char*>(commandData), commandDataLen); size_t fileLen = strnlen(reinterpret_cast<const char*>(commandData), commandDataLen);
if (fileLen > (config::MAX_PATH_SIZE + config::MAX_FILENAME_SIZE)) { if (fileLen > MAX_FILENAME_SIZE) {
return FILENAME_TOO_LONG; return FILENAME_TOO_LONG;
} }
obcFile = std::string(reinterpret_cast<const char*>(commandData), fileLen); obcFile = std::string(reinterpret_cast<const char*>(commandData), fileLen);
fileLen = fileLen =
strnlen(reinterpret_cast<const char*>(commandData + obcFile.size() + SIZE_NULL_TERMINATOR), strnlen(reinterpret_cast<const char*>(commandData + obcFile.size() + SIZE_NULL_TERMINATOR),
commandDataLen - obcFile.size() - 1); commandDataLen - obcFile.size() - 1);
if (fileLen > MAX_FILENAME_SIZE) { if (fileLen > FILENAME_FIELD_SIZE) {
return MPSOC_FILENAME_TOO_LONG; return MPSOC_FILENAME_TOO_LONG;
} }
mpsocFile = std::string( mpsocFile = std::string(
@@ -843,11 +843,11 @@ class FlashBasePusCmd {
const std::string& getObcFile() const { return obcFile; } const std::string& getObcFile() const { return obcFile; }
const std::string& getMPSoCFile() const { return mpsocFile; } const std::string& getMpsocFile() const { return mpsocFile; }
protected: protected:
size_t getParsedSize() const { size_t getParsedSize() const {
return getObcFile().size() + getMPSoCFile().size() + 2 * SIZE_NULL_TERMINATOR; return getObcFile().size() + getMpsocFile().size() + 2 * SIZE_NULL_TERMINATOR;
} }
static const size_t SIZE_NULL_TERMINATOR = 1; static const size_t SIZE_NULL_TERMINATOR = 1;
@@ -914,24 +914,115 @@ class TcCamTakePic : public TcBase {
: TcBase(params, apid::TC_CAM_TAKE_PIC, sequenceCount) {} : TcBase(params, apid::TC_CAM_TAKE_PIC, sequenceCount) {}
ReturnValue_t setPayload(const uint8_t* commandData, size_t commandDataLen) { ReturnValue_t setPayload(const uint8_t* commandData, size_t commandDataLen) {
if (commandDataLen > MAX_DATA_LENGTH) { const uint8_t** dataPtr = &commandData;
if (commandDataLen > FULL_PAYLOAD_SIZE) {
return INVALID_LENGTH; return INVALID_LENGTH;
} }
std::string fileName(reinterpret_cast<const char*>(commandData)); size_t deserLen = commandDataLen;
if (fileName.size() + sizeof(NULL_TERMINATOR) > MAX_FILENAME_SIZE) { size_t serLen = 0;
fileName = reinterpret_cast<const char*>(commandData);
if (fileName.size() > MAX_FILENAME_SIZE) {
return FILENAME_TOO_LONG; return FILENAME_TOO_LONG;
} }
if (commandDataLen - (fileName.size() + sizeof(NULL_TERMINATOR)) != PARAMETER_SIZE) { deserLen -= fileName.length() + 1;
return INVALID_LENGTH; *dataPtr += fileName.length() + 1;
uint8_t** payloadPtr = &payloadStart;
memcpy(payloadStart, fileName.data(), fileName.size());
*payloadPtr += FILENAME_FIELD_SIZE;
serLen += FILENAME_FIELD_SIZE;
ReturnValue_t result = SerializeAdapter::deSerialize(&encoderSettingY, dataPtr, &deserLen,
SerializeIF::Endianness::NETWORK);
if (result != returnvalue::OK) {
return result;
} }
spParams.setFullPayloadLen(commandDataLen + CRC_SIZE); result = SerializeAdapter::serialize(&encoderSettingY, payloadPtr, &serLen, FULL_PAYLOAD_SIZE,
std::memcpy(payloadStart, commandData, commandDataLen); SerializeIF::Endianness::NETWORK);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::deSerialize(&quantizationY, dataPtr, &deserLen,
SerializeIF::Endianness::NETWORK);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::serialize(&quantizationY, payloadPtr, &serLen, FULL_PAYLOAD_SIZE,
SerializeIF::Endianness::NETWORK);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::deSerialize(&encoderSettingsCb, dataPtr, &deserLen,
SerializeIF::Endianness::NETWORK);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::serialize(&encoderSettingsCb, payloadPtr, &serLen, FULL_PAYLOAD_SIZE,
SerializeIF::Endianness::NETWORK);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::deSerialize(&quantizationCb, dataPtr, &deserLen,
SerializeIF::Endianness::NETWORK);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::serialize(&quantizationCb, payloadPtr, &serLen, FULL_PAYLOAD_SIZE,
SerializeIF::Endianness::NETWORK);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::deSerialize(&encoderSettingsCr, dataPtr, &deserLen,
SerializeIF::Endianness::NETWORK);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::serialize(&encoderSettingsCr, payloadPtr, &serLen, FULL_PAYLOAD_SIZE,
SerializeIF::Endianness::NETWORK);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::deSerialize(&quantizationCr, dataPtr, &deserLen,
SerializeIF::Endianness::NETWORK);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::serialize(&quantizationCr, payloadPtr, &serLen, FULL_PAYLOAD_SIZE,
SerializeIF::Endianness::NETWORK);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::deSerialize(&bypassCompressor, dataPtr, &deserLen,
SerializeIF::Endianness::NETWORK);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::serialize(&bypassCompressor, payloadPtr, &serLen, FULL_PAYLOAD_SIZE,
SerializeIF::Endianness::NETWORK);
if (result != returnvalue::OK) {
return result;
}
spParams.setFullPayloadLen(FULL_PAYLOAD_SIZE + CRC_SIZE);
return returnvalue::OK; return returnvalue::OK;
} }
std::string fileName;
uint8_t encoderSettingY = 7;
uint64_t quantizationY = 0;
uint8_t encoderSettingsCb = 7;
uint64_t quantizationCb = 0;
uint8_t encoderSettingsCr = 7;
uint64_t quantizationCr = 0;
uint8_t bypassCompressor = 0;
private: private:
static const size_t MAX_DATA_LENGTH = 286;
static const size_t PARAMETER_SIZE = 28; static const size_t PARAMETER_SIZE = 28;
static constexpr size_t FULL_PAYLOAD_SIZE = FILENAME_FIELD_SIZE + PARAMETER_SIZE;
}; };
/** /**
@@ -943,30 +1034,31 @@ class TcSimplexStreamFile : public TcBase {
: TcBase(params, apid::TC_SIMPLEX_SEND_FILE, sequenceCount) {} : TcBase(params, apid::TC_SIMPLEX_SEND_FILE, sequenceCount) {}
ReturnValue_t setPayload(const uint8_t* commandData, size_t commandDataLen) { ReturnValue_t setPayload(const uint8_t* commandData, size_t commandDataLen) {
if (commandDataLen > MAX_DATA_LENGTH) { if (commandDataLen > MAX_FILENAME_SIZE) {
return INVALID_LENGTH; return INVALID_LENGTH;
} }
std::string fileName(reinterpret_cast<const char*>(commandData)); std::string fileName(reinterpret_cast<const char*>(commandData));
if (fileName.size() + sizeof(NULL_TERMINATOR) > MAX_FILENAME_SIZE) { if (fileName.size() > MAX_FILENAME_SIZE) {
return FILENAME_TOO_LONG; return FILENAME_TOO_LONG;
} }
std::memset(payloadStart, 0, FILENAME_FIELD_SIZE);
std::memcpy(payloadStart, fileName.data(), fileName.length()); std::memcpy(payloadStart, fileName.data(), fileName.length());
payloadStart[fileName.length()] = 0; payloadStart[fileName.length()] = 0;
spParams.setFullPayloadLen(fileName.length() + 1); spParams.setFullPayloadLen(FILENAME_FIELD_SIZE + CRC_SIZE);
;
return returnvalue::OK; return returnvalue::OK;
} }
private: private:
static constexpr size_t MAX_DATA_LENGTH = 256;
}; };
/** /**
* @brief Class to build simplex send file command * @brief Class to build simplex send file command
*/ */
class TcSimplexStoreFile : public TcBase { class TcSplitFile : public TcBase {
public: public:
TcSimplexStoreFile(ploc::SpTcParams params, uint16_t sequenceCount) TcSplitFile(ploc::SpTcParams params, uint16_t sequenceCount)
: TcBase(params, apid::TC_SIMPLEX_SEND_FILE, sequenceCount) {} : TcBase(params, apid::TC_SIMPLEX_SEND_FILE, sequenceCount) {}
ReturnValue_t setPayload(const uint8_t* commandData, size_t commandDataLen) { ReturnValue_t setPayload(const uint8_t* commandData, size_t commandDataLen) {
@@ -988,29 +1080,24 @@ class TcSimplexStoreFile : public TcBase {
return INVALID_PARAMETER; return INVALID_PARAMETER;
} }
std::string fileName(reinterpret_cast<const char*>(*dataPtr)); std::string fileName(reinterpret_cast<const char*>(*dataPtr));
if (fileName.size() + sizeof(NULL_TERMINATOR) > MAX_FILENAME_SIZE) { if (fileName.size() > MAX_FILENAME_SIZE) {
return FILENAME_TOO_LONG; return FILENAME_TOO_LONG;
} }
size_t currentCopyIdx = 0; char divStr[16]{};
size_t payloadLen = fileName.length() + sizeof(NULL_TERMINATOR) + CRC_SIZE; sprintf(divStr, "DIV%03u", chunkParameter);
if (chunkParameter > 1) { std::memcpy(payloadStart, divStr, DIV_STR_LEN);
char divStr[16]{}; payloadStart[DIV_STR_LEN] = 0;
sprintf(divStr, "DIV%03u", chunkParameter); std::memset(payloadStart + DIV_STR_LEN + 1, 0, FILENAME_FIELD_SIZE - DIV_STR_LEN - 1);
std::memcpy(payloadStart, divStr, DIV_STR_LEN); std::memcpy(payloadStart + DIV_STR_LEN + 1, fileName.data(), fileName.length());
payloadLen += DIV_STR_LEN; spParams.setFullPayloadLen(FILENAME_FIELD_SIZE + CRC_SIZE);
currentCopyIdx += DIV_STR_LEN;
}
std::memcpy(payloadStart + currentCopyIdx, *dataPtr, fileName.length());
spParams.setFullPayloadLen(payloadLen);
return returnvalue::OK; return returnvalue::OK;
} }
private: private:
uint32_t chunkParameter = 0; uint32_t chunkParameter = 0;
static constexpr size_t MAX_DATA_LENGTH = 256;
static constexpr size_t MIN_DATA_LENGTH = 4; static constexpr size_t MIN_DATA_LENGTH = 4;
static constexpr size_t DIV_STR_LEN = 6; static constexpr size_t DIV_STR_LEN = 6;
static constexpr size_t MAX_DATA_LENGTH = 4 + MAX_FILENAME_SIZE;
}; };
/** /**

View File

@@ -159,6 +159,7 @@ static const DeviceCommandId_t ENABLE_NVMS = 59;
static const DeviceCommandId_t CONTINUE_UPDATE = 60; static const DeviceCommandId_t CONTINUE_UPDATE = 60;
static const DeviceCommandId_t MEMORY_CHECK_WITH_FILE = 61; static const DeviceCommandId_t MEMORY_CHECK_WITH_FILE = 61;
static constexpr DeviceCommandId_t MEMORY_CHECK = 62; static constexpr DeviceCommandId_t MEMORY_CHECK = 62;
static constexpr DeviceCommandId_t ABORT_LONGER_REQUEST = 63;
/** Reply IDs */ /** Reply IDs */
enum ReplyId : DeviceCommandId_t { enum ReplyId : DeviceCommandId_t {
@@ -1145,14 +1146,14 @@ class WriteMemory : public TcBase {
: TcBase(params, Apid::MEM_MAN, static_cast<uint8_t>(tc::MemManId::WRITE), 1) {} : TcBase(params, Apid::MEM_MAN, static_cast<uint8_t>(tc::MemManId::WRITE), 1) {}
ReturnValue_t buildPacket(ccsds::SequenceFlags seqFlags, uint16_t sequenceCount, uint8_t memoryId, ReturnValue_t buildPacket(ccsds::SequenceFlags seqFlags, uint16_t sequenceCount, uint8_t memoryId,
uint32_t startAddress, uint16_t length, uint8_t* updateData) { uint32_t currentAddr, uint16_t length, uint8_t* updateData) {
if (length > CHUNK_MAX) { if (length > CHUNK_MAX) {
sif::error << "WriteMemory::WriteMemory: Invalid length" << std::endl; sif::error << "WriteMemory::WriteMemory: Invalid length" << std::endl;
return SerializeIF::BUFFER_TOO_SHORT; return SerializeIF::BUFFER_TOO_SHORT;
} }
spParams.creator.setSeqFlags(seqFlags); spParams.creator.setSeqFlags(seqFlags);
spParams.creator.setSeqCount(sequenceCount); spParams.creator.setSeqCount(sequenceCount);
auto res = initPacket(memoryId, startAddress, length, updateData); auto res = initPacket(memoryId, currentAddr, length, updateData);
if (res != returnvalue::OK) { if (res != returnvalue::OK) {
return res; return res;
} }
@@ -1170,7 +1171,7 @@ class WriteMemory : public TcBase {
static const uint16_t META_DATA_LENGTH = 8; static const uint16_t META_DATA_LENGTH = 8;
uint8_t n = 1; uint8_t n = 1;
ReturnValue_t initPacket(uint8_t memoryId, uint32_t startAddr, uint16_t updateDataLen, ReturnValue_t initPacket(uint8_t memoryId, uint32_t currentAddr, uint16_t updateDataLen,
uint8_t* updateData) { uint8_t* updateData) {
uint8_t* data = payloadStart; uint8_t* data = payloadStart;
if (updateDataLen % 2 != 0) { if (updateDataLen % 2 != 0) {
@@ -1188,7 +1189,7 @@ class WriteMemory : public TcBase {
SerializeIF::Endianness::BIG); SerializeIF::Endianness::BIG);
SerializeAdapter::serialize(&n, &data, &serializedSize, spParams.maxSize, SerializeAdapter::serialize(&n, &data, &serializedSize, spParams.maxSize,
SerializeIF::Endianness::BIG); SerializeIF::Endianness::BIG);
SerializeAdapter::serialize(&startAddr, &data, &serializedSize, spParams.maxSize, SerializeAdapter::serialize(&currentAddr, &data, &serializedSize, spParams.maxSize,
SerializeIF::Endianness::BIG); SerializeIF::Endianness::BIG);
SerializeAdapter::serialize(&updateDataLen, &data, &serializedSize, spParams.maxSize, SerializeAdapter::serialize(&updateDataLen, &data, &serializedSize, spParams.maxSize,
SerializeIF::Endianness::BIG); SerializeIF::Endianness::BIG);

View File

@@ -941,7 +941,7 @@ class AcsParameters : public HasParametersIF {
} sunModelParameters; } sunModelParameters;
struct KalmanFilterParameters { struct KalmanFilterParameters {
double sensorNoiseStr = 0.1 * DEG2RAD; double sensorNoiseStr = 0.0028 * DEG2RAD;
double sensorNoiseSus = 8. * DEG2RAD; double sensorNoiseSus = 8. * DEG2RAD;
double sensorNoiseMgm = 4. * DEG2RAD; double sensorNoiseMgm = 4. * DEG2RAD;
double sensorNoiseGyr = 0.1 * DEG2RAD; double sensorNoiseGyr = 0.1 * DEG2RAD;

View File

@@ -232,6 +232,7 @@ void Guidance::targetRotationRate(const double timeDelta, double quatIX[4], doub
} }
if (timeDelta != 0.0) { if (timeDelta != 0.0) {
QuaternionOperations::rotationFromQuaternions(quatIX, quatIXprev, timeDelta, refSatRate); QuaternionOperations::rotationFromQuaternions(quatIX, quatIXprev, timeDelta, refSatRate);
VectorOperations<double>::mulScalar(refSatRate, -1, refSatRate, 3);
} else { } else {
std::memcpy(refSatRate, ZERO_VEC3, 3 * sizeof(double)); std::memcpy(refSatRate, ZERO_VEC3, 3 * sizeof(double));
} }
@@ -315,9 +316,9 @@ void Guidance::comparePtg(double currentQuat[4], double currentSatRotRate[3], do
// Calculate error satellite rotational rate // Calculate error satellite rotational rate
// Convert target rotational rate into body RF // Convert target rotational rate into body RF
double errorQuatInv[4] = {0, 0, 0, 0}, targetSatRotRateB[3] = {0, 0, 0}; double targetSatRotRateB[3] = {0, 0, 0};
QuaternionOperations::inverse(errorQuat, errorQuatInv); QuaternionOperations::multiplyVector(currentQuat, targetSatRotRate, targetSatRotRateB);
QuaternionOperations::multiplyVector(errorQuatInv, targetSatRotRate, targetSatRotRateB); VectorOperations<double>::copy(targetSatRotRateB, targetSatRotRate, 3);
// Combine the target and reference satellite rotational rates // Combine the target and reference satellite rotational rates
double combinedRefSatRotRate[3] = {0, 0, 0}; double combinedRefSatRotRate[3] = {0, 0, 0};
VectorOperations<double>::add(targetSatRotRate, refSatRotRate, combinedRefSatRotRate, 3); VectorOperations<double>::add(targetSatRotRate, refSatRotRate, combinedRefSatRotRate, 3);

View File

@@ -114,12 +114,13 @@ ReturnValue_t MultiplicativeKalmanFilter::mekfEst(
return result; return result;
} }
double measSensMatrix[matrixDimensionFactor][6] = {{0}}, double measSensMatrix[matrixDimensionFactor][6] = {},
measCovMatrix[matrixDimensionFactor][matrixDimensionFactor] = {{0}}, measCovMatrix[matrixDimensionFactor][matrixDimensionFactor] = {},
measVec[matrixDimensionFactor] = {0}, estVec[matrixDimensionFactor] = {0}; measVec[matrixDimensionFactor] = {}, estVec[matrixDimensionFactor] = {};
kfUpdate(susData, mgmData, *measSensMatrix, *measCovMatrix, measVec, estVec); kfUpdate(susData, mgmData, *measSensMatrix, *measCovMatrix, measVec, estVec);
double kalmanGain[6][matrixDimensionFactor] = {{0}}; double kalmanGain[6][matrixDimensionFactor];
std::memset(kalmanGain, 0, sizeof(kalmanGain));
result = kfGain(*measSensMatrix, *measCovMatrix, *kalmanGain, attitudeEstimationData); result = kfGain(*measSensMatrix, *measCovMatrix, *kalmanGain, attitudeEstimationData);
if (result != returnvalue::OK) { if (result != returnvalue::OK) {
reset(attitudeEstimationData); reset(attitudeEstimationData);
@@ -342,10 +343,11 @@ ReturnValue_t MultiplicativeKalmanFilter::kfGain(
double *measSensMatrix, double *measCovMatrix, double *kalmanGain, double *measSensMatrix, double *measCovMatrix, double *kalmanGain,
acsctrl::AttitudeEstimationData *attitudeEstimationData) { acsctrl::AttitudeEstimationData *attitudeEstimationData) {
// Kalman Gain: K = P * H' / (H * P * H' + R) // Kalman Gain: K = P * H' / (H * P * H' + R)
double kalmanGainDen[matrixDimensionFactor][matrixDimensionFactor] = {{0}}, double kalmanGainDen[matrixDimensionFactor][matrixDimensionFactor] = {},
invKalmanGainDen[matrixDimensionFactor][matrixDimensionFactor] = {{0}}, invKalmanGainDen[matrixDimensionFactor][matrixDimensionFactor] = {};
residualCov[6][matrixDimensionFactor] = {{0}}, double residualCov[6][matrixDimensionFactor], measSensMatrixTransposed[6][matrixDimensionFactor];
measSensMatrixTransposed[6][matrixDimensionFactor] = {{0}}; std::memset(residualCov, 0, sizeof(residualCov));
std::memset(measSensMatrixTransposed, 0, sizeof(measSensMatrixTransposed));
MatrixOperations<double>::transpose(measSensMatrix, *measSensMatrixTransposed, MatrixOperations<double>::transpose(measSensMatrix, *measSensMatrixTransposed,
matrixDimensionFactor, 6); matrixDimensionFactor, 6);
@@ -382,8 +384,7 @@ void MultiplicativeKalmanFilter::kfCovAposteriori(double *kalmanGain, double *me
void MultiplicativeKalmanFilter::kfStateAposteriori(double *kalmanGain, double *measVec, void MultiplicativeKalmanFilter::kfStateAposteriori(double *kalmanGain, double *measVec,
double *estVec) { double *estVec) {
double stateVecErr[6] = {0, 0, 0, 0, 0, 0}; double stateVecErr[6] = {0, 0, 0, 0, 0, 0}, plantOutputDiff[matrixDimensionFactor] = {};
double plantOutputDiff[matrixDimensionFactor] = {0};
VectorOperations<double>::subtract(measVec, estVec, plantOutputDiff, matrixDimensionFactor); VectorOperations<double>::subtract(measVec, estVec, plantOutputDiff, matrixDimensionFactor);
MatrixOperations<double>::multiply(kalmanGain, plantOutputDiff, stateVecErr, 6, MatrixOperations<double>::multiply(kalmanGain, plantOutputDiff, stateVecErr, 6,
matrixDimensionFactor, 1); matrixDimensionFactor, 1);

View File

@@ -9,7 +9,7 @@ export ZYNQ_7020_SYSROOT="/opt/xiphos/sdk/ark/sysroots/cortexa9hf-neon-xiphos-li
export PATH=${CROSS_COMPILE_BIN_PATH}:$PATH export PATH=${CROSS_COMPILE_BIN_PATH}:$PATH
export CROSS_COMPILE="arm-linux-gnueabihf" export CROSS_COMPILE="arm-linux-gnueabihf"
# export EIVE_Q7S_EM=1 unset EIVE_Q7S_EM
if [[ -d "eive-obsw" ]]; then if [[ -d "eive-obsw" ]]; then
echo "Detected EIVE OBSW root directory at $(pwd)/eive-obsw. Setting to EIVE_OBSW_ROOT" echo "Detected EIVE OBSW root directory at $(pwd)/eive-obsw. Setting to EIVE_OBSW_ROOT"

View File

@@ -4,6 +4,9 @@ import os
import sys import sys
DEFAULT_PORT = 1539
def main(): def main():
args = handle_args() args = handle_args()
cmd = build_cmd(args) cmd = build_cmd(args)
@@ -20,7 +23,7 @@ def prompt_ssh_key_removal():
do_remove_key = input( do_remove_key = input(
"Do you want to remove problematic keys on localhost ([Y]/n)?: " "Do you want to remove problematic keys on localhost ([Y]/n)?: "
) )
if not do_remove_key.lower() in ["y", "yes", "1", ""]: if do_remove_key.lower() not in ["y", "yes", "1", ""]:
sys.exit(1) sys.exit(1)
port = 0 port = 0
while True: while True:
@@ -54,7 +57,7 @@ def handle_args():
"If files are copied back to host, will be current directory by default", "If files are copied back to host, will be current directory by default",
default="", default="",
) )
parser.add_argument("-P", "--port", help="Target port", default=1535) parser.add_argument("-P", "--port", help="Target port", default=DEFAULT_PORT)
parser.add_argument( parser.add_argument(
"-i", "-i",
"--invert", "--invert",

2
tmtc

Submodule tmtc updated: dfa45dbdba...9a06c64dfa