diff --git a/CHANGELOG.md b/CHANGELOG.md index 41d1b480..5357e831 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,27 +16,41 @@ will consitute of a breaking change warranting a new major release: # [unreleased] -- `eive-tmtc`: +# [v6.4.0] 2023-08-16 -## Added - -- SGP4 Propagator is now used for propagating the position of EIVE. It will only work once - a TLE has been uploaded with the newly added action command for the ACS Controller. In - return the actual GPS data will be ignored once SPG4 is running. However, by setting the - according parameter, the ACS Controller can be directed to ignore the SGP4 solution. -- Skyview dataset for more GPS TM has been added +- `eive-tmtc`: v5.4.3 ## Fixed - The handling function of the GPS data is only called once per GPS read. This should remove the fake fix-has-changed events. - + ## Changed +- PDEC FDIR rework: A full PDEC reboot will now only be performed after a regular PDEC reset has + failed 10 times. The mechanism will reset after no PDEC reset has happended for 2 minutes. + The PDEC reset will be performed when counting 4 dirty frame events 10 seconds after the count + was incremented initially. - GPS Fix has changed event is no longer triggered for the EM - MGM and SUS rates now will only be calculated, if 2 valid consecutive datapoints are available. The stored value of the last timestep will now be reset, if no actual value is available. +## Added + +- The PLOC SUPV HK set is requested and downlinked periodically if the SUPV is on now. +- SGP4 Propagator is now used for propagating the position of EIVE. It will only work once + a TLE has been uploaded with the newly added action command for the ACS Controller. In + return the actual GPS data will be ignored once SPG4 is running. However, by setting the + according parameter, the ACS Controller can be directed to ignore the SGP4 solution. +- Skyview dataset for more GPS TM has been added +- `PDEC_CONFIG_CORRUPTED` event which is triggered when the PDEC configuration does not match the + expected configuration. P1 will contain the readback of the first word and P2 will contain the + readback of the second word. +- The MGM and SUS vectors being too close together does not prevent the usage of the safe + mode controller anymore. +- Parameter to disable usage of MGM4, which is part of the MTQ and therefore cannot be + disabled without disabling the MTQ itself. + # [v6.3.0] 2023-08-03 ## Fixed diff --git a/CMakeLists.txt b/CMakeLists.txt index 6610b0a6..058c99fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ cmake_minimum_required(VERSION 3.13) set(OBSW_VERSION_MAJOR 6) -set(OBSW_VERSION_MINOR 3) +set(OBSW_VERSION_MINOR 4) set(OBSW_VERSION_REVISION 0) # set(CMAKE_VERBOSE TRUE) diff --git a/bsp_hosted/fsfwconfig/events/translateEvents.cpp b/bsp_hosted/fsfwconfig/events/translateEvents.cpp index 3a53a4fb..55158be2 100644 --- a/bsp_hosted/fsfwconfig/events/translateEvents.cpp +++ b/bsp_hosted/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 302 translations. + * @brief Auto-generated event translation file. Contains 304 translations. * @details - * Generated on: 2023-08-02 09:40:31 + * Generated on: 2023-08-15 13:27:11 */ #include "translateEvents.h" @@ -100,6 +100,7 @@ const char *MEKF_RECOVERY_STRING = "MEKF_RECOVERY"; const char *MEKF_AUTOMATIC_RESET_STRING = "MEKF_AUTOMATIC_RESET"; const char *MEKF_INVALID_MODE_VIOLATION_STRING = "MEKF_INVALID_MODE_VIOLATION"; const char *SAFE_MODE_CONTROLLER_FAILURE_STRING = "SAFE_MODE_CONTROLLER_FAILURE"; +const char *TLE_TOO_OLD_STRING = "TLE_TOO_OLD"; const char *SWITCH_CMD_SENT_STRING = "SWITCH_CMD_SENT"; const char *SWITCH_HAS_CHANGED_STRING = "SWITCH_HAS_CHANGED"; const char *SWITCHING_Q7S_DENIED_STRING = "SWITCHING_Q7S_DENIED"; @@ -167,6 +168,7 @@ const char *PDEC_TRYING_RESET_NO_INIT_STRING = "PDEC_TRYING_RESET_NO_INIT"; const char *PDEC_RESET_FAILED_STRING = "PDEC_RESET_FAILED"; const char *OPEN_IRQ_FILE_FAILED_STRING = "OPEN_IRQ_FILE_FAILED"; const char *PDEC_INIT_FAILED_STRING = "PDEC_INIT_FAILED"; +const char *PDEC_CONFIG_CORRUPTED_STRING = "PDEC_CONFIG_CORRUPTED"; const char *IMAGE_UPLOAD_FAILED_STRING = "IMAGE_UPLOAD_FAILED"; const char *IMAGE_DOWNLOAD_FAILED_STRING = "IMAGE_DOWNLOAD_FAILED"; const char *IMAGE_UPLOAD_SUCCESSFUL_STRING = "IMAGE_UPLOAD_SUCCESSFUL"; @@ -500,6 +502,8 @@ const char *translateEvents(Event event) { return MEKF_INVALID_MODE_VIOLATION_STRING; case (11207): return SAFE_MODE_CONTROLLER_FAILURE_STRING; + case (11208): + return TLE_TOO_OLD_STRING; case (11300): return SWITCH_CMD_SENT_STRING; case (11301): @@ -634,6 +638,8 @@ const char *translateEvents(Event event) { return OPEN_IRQ_FILE_FAILED_STRING; case (12414): return PDEC_INIT_FAILED_STRING; + case (12415): + return PDEC_CONFIG_CORRUPTED_STRING; case (12500): return IMAGE_UPLOAD_FAILED_STRING; case (12501): diff --git a/bsp_hosted/fsfwconfig/objects/translateObjects.cpp b/bsp_hosted/fsfwconfig/objects/translateObjects.cpp index 8a6f23a0..c7eb075d 100644 --- a/bsp_hosted/fsfwconfig/objects/translateObjects.cpp +++ b/bsp_hosted/fsfwconfig/objects/translateObjects.cpp @@ -2,7 +2,7 @@ * @brief Auto-generated object translation file. * @details * Contains 171 translations. - * Generated on: 2023-08-02 09:40:31 + * Generated on: 2023-08-15 13:27:11 */ #include "translateObjects.h" diff --git a/generators/bsp_hosted_events.csv b/generators/bsp_hosted_events.csv index 1c6f646d..b00c56b2 100644 --- a/generators/bsp_hosted_events.csv +++ b/generators/bsp_hosted_events.csv @@ -94,6 +94,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path 11205;0x2bc5;MEKF_AUTOMATIC_RESET;INFO;MEKF performed an automatic reset after detection of nonfinite values.;mission/acs/defs.h 11206;0x2bc6;MEKF_INVALID_MODE_VIOLATION;HIGH;MEKF was not able to compute a solution during any pointing ACS mode for a prolonged time.;mission/acs/defs.h 11207;0x2bc7;SAFE_MODE_CONTROLLER_FAILURE;HIGH;The ACS safe mode controller was not able to compute a solution and has failed. P1: Missing information about magnetic field, P2: Missing information about rotational rate;mission/acs/defs.h +11208;0x2bc8;TLE_TOO_OLD;INFO;The TLE for the SGP4 Propagator has become too old.;mission/acs/defs.h 11300;0x2c24;SWITCH_CMD_SENT;INFO;Indicates that a FSFW object requested setting a switch P1: 1 if on was requested, 0 for off | P2: Switch Index;mission/power/defs.h 11301;0x2c25;SWITCH_HAS_CHANGED;INFO;Indicated that a switch state has changed P1: New switch state, 1 for on, 0 for off | P2: Switch Index;mission/power/defs.h 11302;0x2c26;SWITCHING_Q7S_DENIED;MEDIUM;No description;mission/power/defs.h @@ -161,6 +162,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path 12412;0x307c;PDEC_RESET_FAILED;HIGH;Failed to pull PDEC reset to low;linux/ipcore/pdec.h 12413;0x307d;OPEN_IRQ_FILE_FAILED;HIGH;Failed to open the IRQ uio file;linux/ipcore/pdec.h 12414;0x307e;PDEC_INIT_FAILED;HIGH;PDEC initialization failed. This might also be due to the persistent confiuration never becoming available, for example due to SD card issues.;linux/ipcore/pdec.h +12415;0x307f;PDEC_CONFIG_CORRUPTED;HIGH;The PDEC configuration area has been corrupted P1: The first configuration word P2: The second configuration word;linux/ipcore/pdec.h 12500;0x30d4;IMAGE_UPLOAD_FAILED;LOW;Image upload failed;linux/acs/StrComHandler.h 12501;0x30d5;IMAGE_DOWNLOAD_FAILED;LOW;Image download failed;linux/acs/StrComHandler.h 12502;0x30d6;IMAGE_UPLOAD_SUCCESSFUL;LOW;Uploading image to star tracker was successfulop;linux/acs/StrComHandler.h diff --git a/generators/bsp_q7s_events.csv b/generators/bsp_q7s_events.csv index 1c6f646d..b00c56b2 100644 --- a/generators/bsp_q7s_events.csv +++ b/generators/bsp_q7s_events.csv @@ -94,6 +94,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path 11205;0x2bc5;MEKF_AUTOMATIC_RESET;INFO;MEKF performed an automatic reset after detection of nonfinite values.;mission/acs/defs.h 11206;0x2bc6;MEKF_INVALID_MODE_VIOLATION;HIGH;MEKF was not able to compute a solution during any pointing ACS mode for a prolonged time.;mission/acs/defs.h 11207;0x2bc7;SAFE_MODE_CONTROLLER_FAILURE;HIGH;The ACS safe mode controller was not able to compute a solution and has failed. P1: Missing information about magnetic field, P2: Missing information about rotational rate;mission/acs/defs.h +11208;0x2bc8;TLE_TOO_OLD;INFO;The TLE for the SGP4 Propagator has become too old.;mission/acs/defs.h 11300;0x2c24;SWITCH_CMD_SENT;INFO;Indicates that a FSFW object requested setting a switch P1: 1 if on was requested, 0 for off | P2: Switch Index;mission/power/defs.h 11301;0x2c25;SWITCH_HAS_CHANGED;INFO;Indicated that a switch state has changed P1: New switch state, 1 for on, 0 for off | P2: Switch Index;mission/power/defs.h 11302;0x2c26;SWITCHING_Q7S_DENIED;MEDIUM;No description;mission/power/defs.h @@ -161,6 +162,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path 12412;0x307c;PDEC_RESET_FAILED;HIGH;Failed to pull PDEC reset to low;linux/ipcore/pdec.h 12413;0x307d;OPEN_IRQ_FILE_FAILED;HIGH;Failed to open the IRQ uio file;linux/ipcore/pdec.h 12414;0x307e;PDEC_INIT_FAILED;HIGH;PDEC initialization failed. This might also be due to the persistent confiuration never becoming available, for example due to SD card issues.;linux/ipcore/pdec.h +12415;0x307f;PDEC_CONFIG_CORRUPTED;HIGH;The PDEC configuration area has been corrupted P1: The first configuration word P2: The second configuration word;linux/ipcore/pdec.h 12500;0x30d4;IMAGE_UPLOAD_FAILED;LOW;Image upload failed;linux/acs/StrComHandler.h 12501;0x30d5;IMAGE_DOWNLOAD_FAILED;LOW;Image download failed;linux/acs/StrComHandler.h 12502;0x30d6;IMAGE_UPLOAD_SUCCESSFUL;LOW;Uploading image to star tracker was successfulop;linux/acs/StrComHandler.h diff --git a/generators/events/translateEvents.cpp b/generators/events/translateEvents.cpp index 3a53a4fb..55158be2 100644 --- a/generators/events/translateEvents.cpp +++ b/generators/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 302 translations. + * @brief Auto-generated event translation file. Contains 304 translations. * @details - * Generated on: 2023-08-02 09:40:31 + * Generated on: 2023-08-15 13:27:11 */ #include "translateEvents.h" @@ -100,6 +100,7 @@ const char *MEKF_RECOVERY_STRING = "MEKF_RECOVERY"; const char *MEKF_AUTOMATIC_RESET_STRING = "MEKF_AUTOMATIC_RESET"; const char *MEKF_INVALID_MODE_VIOLATION_STRING = "MEKF_INVALID_MODE_VIOLATION"; const char *SAFE_MODE_CONTROLLER_FAILURE_STRING = "SAFE_MODE_CONTROLLER_FAILURE"; +const char *TLE_TOO_OLD_STRING = "TLE_TOO_OLD"; const char *SWITCH_CMD_SENT_STRING = "SWITCH_CMD_SENT"; const char *SWITCH_HAS_CHANGED_STRING = "SWITCH_HAS_CHANGED"; const char *SWITCHING_Q7S_DENIED_STRING = "SWITCHING_Q7S_DENIED"; @@ -167,6 +168,7 @@ const char *PDEC_TRYING_RESET_NO_INIT_STRING = "PDEC_TRYING_RESET_NO_INIT"; const char *PDEC_RESET_FAILED_STRING = "PDEC_RESET_FAILED"; const char *OPEN_IRQ_FILE_FAILED_STRING = "OPEN_IRQ_FILE_FAILED"; const char *PDEC_INIT_FAILED_STRING = "PDEC_INIT_FAILED"; +const char *PDEC_CONFIG_CORRUPTED_STRING = "PDEC_CONFIG_CORRUPTED"; const char *IMAGE_UPLOAD_FAILED_STRING = "IMAGE_UPLOAD_FAILED"; const char *IMAGE_DOWNLOAD_FAILED_STRING = "IMAGE_DOWNLOAD_FAILED"; const char *IMAGE_UPLOAD_SUCCESSFUL_STRING = "IMAGE_UPLOAD_SUCCESSFUL"; @@ -500,6 +502,8 @@ const char *translateEvents(Event event) { return MEKF_INVALID_MODE_VIOLATION_STRING; case (11207): return SAFE_MODE_CONTROLLER_FAILURE_STRING; + case (11208): + return TLE_TOO_OLD_STRING; case (11300): return SWITCH_CMD_SENT_STRING; case (11301): @@ -634,6 +638,8 @@ const char *translateEvents(Event event) { return OPEN_IRQ_FILE_FAILED_STRING; case (12414): return PDEC_INIT_FAILED_STRING; + case (12415): + return PDEC_CONFIG_CORRUPTED_STRING; case (12500): return IMAGE_UPLOAD_FAILED_STRING; case (12501): diff --git a/generators/objects/translateObjects.cpp b/generators/objects/translateObjects.cpp index f4779490..53be3a34 100644 --- a/generators/objects/translateObjects.cpp +++ b/generators/objects/translateObjects.cpp @@ -2,7 +2,7 @@ * @brief Auto-generated object translation file. * @details * Contains 175 translations. - * Generated on: 2023-08-02 09:40:31 + * Generated on: 2023-08-15 13:27:11 */ #include "translateObjects.h" diff --git a/linux/fsfwconfig/events/translateEvents.cpp b/linux/fsfwconfig/events/translateEvents.cpp index 3a53a4fb..55158be2 100644 --- a/linux/fsfwconfig/events/translateEvents.cpp +++ b/linux/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 302 translations. + * @brief Auto-generated event translation file. Contains 304 translations. * @details - * Generated on: 2023-08-02 09:40:31 + * Generated on: 2023-08-15 13:27:11 */ #include "translateEvents.h" @@ -100,6 +100,7 @@ const char *MEKF_RECOVERY_STRING = "MEKF_RECOVERY"; const char *MEKF_AUTOMATIC_RESET_STRING = "MEKF_AUTOMATIC_RESET"; const char *MEKF_INVALID_MODE_VIOLATION_STRING = "MEKF_INVALID_MODE_VIOLATION"; const char *SAFE_MODE_CONTROLLER_FAILURE_STRING = "SAFE_MODE_CONTROLLER_FAILURE"; +const char *TLE_TOO_OLD_STRING = "TLE_TOO_OLD"; const char *SWITCH_CMD_SENT_STRING = "SWITCH_CMD_SENT"; const char *SWITCH_HAS_CHANGED_STRING = "SWITCH_HAS_CHANGED"; const char *SWITCHING_Q7S_DENIED_STRING = "SWITCHING_Q7S_DENIED"; @@ -167,6 +168,7 @@ const char *PDEC_TRYING_RESET_NO_INIT_STRING = "PDEC_TRYING_RESET_NO_INIT"; const char *PDEC_RESET_FAILED_STRING = "PDEC_RESET_FAILED"; const char *OPEN_IRQ_FILE_FAILED_STRING = "OPEN_IRQ_FILE_FAILED"; const char *PDEC_INIT_FAILED_STRING = "PDEC_INIT_FAILED"; +const char *PDEC_CONFIG_CORRUPTED_STRING = "PDEC_CONFIG_CORRUPTED"; const char *IMAGE_UPLOAD_FAILED_STRING = "IMAGE_UPLOAD_FAILED"; const char *IMAGE_DOWNLOAD_FAILED_STRING = "IMAGE_DOWNLOAD_FAILED"; const char *IMAGE_UPLOAD_SUCCESSFUL_STRING = "IMAGE_UPLOAD_SUCCESSFUL"; @@ -500,6 +502,8 @@ const char *translateEvents(Event event) { return MEKF_INVALID_MODE_VIOLATION_STRING; case (11207): return SAFE_MODE_CONTROLLER_FAILURE_STRING; + case (11208): + return TLE_TOO_OLD_STRING; case (11300): return SWITCH_CMD_SENT_STRING; case (11301): @@ -634,6 +638,8 @@ const char *translateEvents(Event event) { return OPEN_IRQ_FILE_FAILED_STRING; case (12414): return PDEC_INIT_FAILED_STRING; + case (12415): + return PDEC_CONFIG_CORRUPTED_STRING; case (12500): return IMAGE_UPLOAD_FAILED_STRING; case (12501): diff --git a/linux/fsfwconfig/objects/translateObjects.cpp b/linux/fsfwconfig/objects/translateObjects.cpp index f4779490..53be3a34 100644 --- a/linux/fsfwconfig/objects/translateObjects.cpp +++ b/linux/fsfwconfig/objects/translateObjects.cpp @@ -2,7 +2,7 @@ * @brief Auto-generated object translation file. * @details * Contains 175 translations. - * Generated on: 2023-08-02 09:40:31 + * Generated on: 2023-08-15 13:27:11 */ #include "translateObjects.h" diff --git a/linux/ipcore/PdecConfig.cpp b/linux/ipcore/PdecConfig.cpp index a41c5ba6..19423862 100644 --- a/linux/ipcore/PdecConfig.cpp +++ b/linux/ipcore/PdecConfig.cpp @@ -22,11 +22,11 @@ ReturnValue_t PdecConfig::write() { if (result != returnvalue::OK) { return result; } - result = writeFrameHeaderFirstOctet(); + result = writeFrameHeaderFirstWord(); if (result != returnvalue::OK) { return result; } - result = writeFrameHeaderSecondOctet(); + result = writeFrameHeaderSecondWord(); if (result != returnvalue::OK) { return result; } @@ -77,7 +77,7 @@ ReturnValue_t PdecConfig::setPositiveWindow(uint8_t pw) { return result; } // Rewrite second config word which contains the positive window parameter - writeFrameHeaderSecondOctet(); + writeFrameHeaderSecondWord(); return returnvalue::OK; } @@ -92,7 +92,7 @@ ReturnValue_t PdecConfig::setNegativeWindow(uint8_t nw) { return result; } // Rewrite second config word which contains the negative window parameter - writeFrameHeaderSecondOctet(); + writeFrameHeaderSecondWord(); return returnvalue::OK; } @@ -114,43 +114,23 @@ ReturnValue_t PdecConfig::getNegativeWindow(uint8_t& negativeWindow) { return returnvalue::OK; } -ReturnValue_t PdecConfig::writeFrameHeaderFirstOctet() { +ReturnValue_t PdecConfig::writeFrameHeaderFirstWord() { uint32_t word = 0; - word |= (VERSION_ID << 30); - - // Setting the bypass flag and the control command flag should not have any - // implication on the operation of the PDEC IP Core - word |= (BYPASS_FLAG << 29); - word |= (CONTROL_COMMAND_FLAG << 28); - - word |= (RESERVED_FIELD_A << 26); - word |= (SPACECRAFT_ID << 16); - word |= (VIRTUAL_CHANNEL << 10); - word |= (DUMMY_BITS << 8); - uint8_t positiveWindow = 0; - ReturnValue_t result = - localParameterHandler.getValue(pdecconfigdefs::paramkeys::POSITIVE_WINDOW, positiveWindow); + ReturnValue_t result = createFirstWord(&word); if (result != returnvalue::OK) { return result; } - word |= static_cast(positiveWindow); - *(memoryBaseAddress + FRAME_HEADER_OFFSET) = word; + *(memoryBaseAddress + FRAME_HEADER_OFFSET + OFFSET_FIRST_CONFIG_WORD) = word; return returnvalue::OK; } -ReturnValue_t PdecConfig::writeFrameHeaderSecondOctet() { - uint8_t negativeWindow = 0; - ReturnValue_t result = - localParameterHandler.getValue(pdecconfigdefs::paramkeys::NEGATIVE_WINDOW, negativeWindow); +ReturnValue_t PdecConfig::writeFrameHeaderSecondWord() { + uint32_t word = 0; + ReturnValue_t result = createSecondWord(&word); if (result != returnvalue::OK) { return result; } - uint32_t word = 0; - word = 0; - word |= (static_cast(negativeWindow) << 24); - word |= (HIGH_AU_MAP_ID << 16); - word |= (ENABLE_DERANDOMIZER << 8); - *(memoryBaseAddress + FRAME_HEADER_OFFSET + 1) = word; + *(memoryBaseAddress + FRAME_HEADER_OFFSET + OFFSET_SECOND_CONFIG_WORD) = word; return returnvalue::OK; } @@ -189,3 +169,49 @@ uint8_t PdecConfig::getOddParity(uint8_t number) { parityBit = ~(countBits & 0x1) & 0x1; return parityBit; } + +ReturnValue_t PdecConfig::createFirstWord(uint32_t* word) { + *word = 0; + *word |= (VERSION_ID << 30); + + // Setting the bypass flag and the control command flag should not have any + // implication on the operation of the PDEC IP Core + *word |= (BYPASS_FLAG << 29); + *word |= (CONTROL_COMMAND_FLAG << 28); + + *word |= (RESERVED_FIELD_A << 26); + *word |= (SPACECRAFT_ID << 16); + *word |= (VIRTUAL_CHANNEL << 10); + *word |= (DUMMY_BITS << 8); + uint8_t positiveWindow = 0; + ReturnValue_t result = + localParameterHandler.getValue(pdecconfigdefs::paramkeys::POSITIVE_WINDOW, positiveWindow); + if (result != returnvalue::OK) { + return result; + } + *word |= static_cast(positiveWindow); + return returnvalue::OK; +} + +ReturnValue_t PdecConfig::createSecondWord(uint32_t* word) { + uint8_t negativeWindow = 0; + ReturnValue_t result = + localParameterHandler.getValue(pdecconfigdefs::paramkeys::NEGATIVE_WINDOW, negativeWindow); + if (result != returnvalue::OK) { + return result; + } + *word = 0; + *word = 0; + *word |= (static_cast(negativeWindow) << 24); + *word |= (HIGH_AU_MAP_ID << 16); + *word |= (ENABLE_DERANDOMIZER << 8); + return returnvalue::OK; +} + +uint32_t PdecConfig::readbackFirstWord() { + return *(memoryBaseAddress + FRAME_HEADER_OFFSET + OFFSET_FIRST_CONFIG_WORD); +} + +uint32_t PdecConfig::readbackSecondWord() { + return *(memoryBaseAddress + FRAME_HEADER_OFFSET + OFFSET_SECOND_CONFIG_WORD); +} diff --git a/linux/ipcore/PdecConfig.h b/linux/ipcore/PdecConfig.h index f7203eec..1f2ed9c8 100644 --- a/linux/ipcore/PdecConfig.h +++ b/linux/ipcore/PdecConfig.h @@ -48,6 +48,39 @@ class PdecConfig { ReturnValue_t getPositiveWindow(uint8_t& positiveWindow); ReturnValue_t getNegativeWindow(uint8_t& negativeWindow); + /** + * @brief Creates the first word of the PDEC configuration + * + * @param word The created word will be written to this pointer + * + * @return OK if successful, otherwise error return value + * + */ + ReturnValue_t createFirstWord(uint32_t* word); + + /** + * @brief Creates the second word of the PDEC configuration + * + * @param word The created word will be written to this pointer + * + * @return OK if successful, otherwise error return value + */ + ReturnValue_t createSecondWord(uint32_t* word); + + /** + * @brief Reads first config word from the config memory + * + * @return The config word + */ + uint32_t readbackFirstWord(); + + /** + * @brief Reads the second config word from the config memory + * + * @return The config word + */ + uint32_t readbackSecondWord(); + private: // TC transfer frame configuration parameters static const uint8_t VERSION_ID = 0; @@ -66,6 +99,8 @@ class PdecConfig { // 0x200 / 4 = 0x80 static const uint32_t FRAME_HEADER_OFFSET = 0x80; + static const uint32_t OFFSET_FIRST_CONFIG_WORD = 0; + static const uint32_t OFFSET_SECOND_CONFIG_WORD = 1; static const uint32_t MAP_ADDR_LUT_OFFSET = 0xA0; static const uint32_t MAP_CLK_FREQ_OFFSET = 0x90; @@ -102,8 +137,8 @@ class PdecConfig { */ ReturnValue_t createPersistentConfig(); - ReturnValue_t writeFrameHeaderFirstOctet(); - ReturnValue_t writeFrameHeaderSecondOctet(); + ReturnValue_t writeFrameHeaderFirstWord(); + ReturnValue_t writeFrameHeaderSecondWord(); void writeMapConfig(); /** diff --git a/linux/ipcore/PdecHandler.cpp b/linux/ipcore/PdecHandler.cpp index cc074ddd..189dfca8 100644 --- a/linux/ipcore/PdecHandler.cpp +++ b/linux/ipcore/PdecHandler.cpp @@ -478,6 +478,7 @@ bool PdecHandler::checkFrameAna(uint32_t pdecFar) { } case (FrameAna_t::FRAME_DIRTY): { triggerEvent(INVALID_TC_FRAME, FRAME_DIRTY_RETVAL); + checkConfig(); sif::warning << "PdecHandler::checkFrameAna: Frame dirty" << std::endl; break; } @@ -577,6 +578,29 @@ void PdecHandler::handleIReason(uint32_t pdecFar, ReturnValue_t parameter1) { } } +void PdecHandler::checkConfig() { + uint32_t firstWord = 0; + ReturnValue_t result = pdecConfig.createFirstWord(&firstWord); + if (result != returnvalue::OK) { + // This should normally never happen during runtime. So here is just + // output a warning + sif::warning << "PdecHandler::checkConfig: Failed to create first word" << std::endl; + return; + } + uint32_t secondWord = 0; + result = pdecConfig.createSecondWord(&secondWord); + if (result != returnvalue::OK) { + // This should normally never happen during runtime. So here is just + // output a warning + sif::warning << "PdecHandler::checkConfig: Failed to create second word" << std::endl; + return; + } + if (firstWord != pdecConfig.readbackFirstWord() or + secondWord != pdecConfig.readbackSecondWord()) { + triggerEvent(PDEC_CONFIG_CORRUPTED, firstWord, secondWord); + } +} + void PdecHandler::handleNewTc() { ReturnValue_t result = returnvalue::OK; diff --git a/linux/ipcore/PdecHandler.h b/linux/ipcore/PdecHandler.h index 882dca50..11ae4de3 100644 --- a/linux/ipcore/PdecHandler.h +++ b/linux/ipcore/PdecHandler.h @@ -282,6 +282,11 @@ class PdecHandler : public SystemObject, */ void handleIReason(uint32_t pdecFar, ReturnValue_t parameter1); + /** + * @brief Checks if PDEC configuration is still correct + */ + void checkConfig(); + /** * @brief Handles the reception of new TCs. Reads the pointer to the storage location of the * new TC segment, extracts the PUS packet and forwards the data to the object diff --git a/linux/ipcore/pdec.h b/linux/ipcore/pdec.h index 0574ee73..de703c5a 100644 --- a/linux/ipcore/pdec.h +++ b/linux/ipcore/pdec.h @@ -71,6 +71,10 @@ static constexpr Event OPEN_IRQ_FILE_FAILED = event::makeEvent(SUBSYSTEM_ID, 13, //! [EXPORT] : [COMMENT] PDEC initialization failed. This might also be due to the persistent //! confiuration never becoming available, for example due to SD card issues. static constexpr Event PDEC_INIT_FAILED = event::makeEvent(SUBSYSTEM_ID, 14, severity::HIGH); +//! [EXPORT] : [COMMENT] The PDEC configuration area has been corrupted +//! P1: The first configuration word +//! P2: The second configuration word +static constexpr Event PDEC_CONFIG_CORRUPTED = event::makeEvent(SUBSYSTEM_ID, 15, severity::HIGH); // Action IDs static constexpr ActionId_t PRINT_CLCW = 0; diff --git a/linux/payload/PlocSupervisorHandler.cpp b/linux/payload/PlocSupervisorHandler.cpp index 682b8020..940785af 100644 --- a/linux/payload/PlocSupervisorHandler.cpp +++ b/linux/payload/PlocSupervisorHandler.cpp @@ -155,12 +155,15 @@ void PlocSupervisorHandler::doStartUp() { startupState = StartupState::ON; } if (startupState == StartupState::ON) { + hkset.setReportingEnabled(true); setMode(_MODE_TO_ON); } } void PlocSupervisorHandler::doShutDown() { setMode(_MODE_POWER_DOWN); + hkset.setReportingEnabled(false); + hkset.setValidity(false, true); shutdownCmdSent = false; packetInBuffer = false; nextReplyId = supv::NONE; @@ -170,6 +173,10 @@ void PlocSupervisorHandler::doShutDown() { } ReturnValue_t PlocSupervisorHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) { + if (not commandIsExecuting(GET_HK_REPORT)) { + *id = GET_HK_REPORT; + return buildCommandFromCommand(*id, nullptr, 0); + } return NOTHING_TO_SEND; } @@ -430,7 +437,7 @@ void PlocSupervisorHandler::fillCommandAndReplyMap() { insertInReplyMap(MEMORY_CHECK, 5, nullptr, 0, false); // TM replies - insertInReplyMap(HK_REPORT, 3, &hkset, SIZE_HK_REPORT); + insertInReplyMap(HK_REPORT, 3, &hkset); insertInReplyMap(BOOT_STATUS_REPORT, 3, &bootStatusReport, SIZE_BOOT_STATUS_REPORT); insertInReplyMap(LATCHUP_REPORT, 3, &latchupStatusReport, SIZE_LATCHUP_STATUS_REPORT); insertInReplyMap(LOGGING_REPORT, 3, &loggingReport, SIZE_LOGGING_REPORT); @@ -790,6 +797,8 @@ ReturnValue_t PlocSupervisorHandler::initializeLocalDataPool(localpool::DataPool localDataPoolMap.emplace(supv::ADC_ENG_14, new PoolEntry({0})); localDataPoolMap.emplace(supv::ADC_ENG_15, new PoolEntry({0})); + poolManager.subscribeForRegularPeriodicPacket( + subdp::RegularHkPeriodicParams(hkset.getSid(), false, 10.0)); return returnvalue::OK; } @@ -918,7 +927,7 @@ ReturnValue_t PlocSupervisorHandler::handleExecutionReport(const uint8_t* data) ReturnValue_t PlocSupervisorHandler::handleHkReport(const uint8_t* data) { ReturnValue_t result = returnvalue::OK; - result = verifyPacket(data, supv::SIZE_HK_REPORT); + result = verifyPacket(data, tmReader.getFullPacketLen()); if (result == result::CRC_FAILURE) { sif::error << "PlocSupervisorHandler::handleHkReport: Hk report has invalid crc" << std::endl; diff --git a/linux/payload/plocSupvDefs.h b/linux/payload/plocSupvDefs.h index d3fda3da..907bfe0c 100644 --- a/linux/payload/plocSupvDefs.h +++ b/linux/payload/plocSupvDefs.h @@ -139,7 +139,6 @@ enum ReplyId : DeviceCommandId_t { // Size of complete space packet (6 byte header + size of data + 2 byte CRC) static const uint16_t SIZE_ACK_REPORT = 14; static const uint16_t SIZE_EXE_REPORT = 14; -static const uint16_t SIZE_HK_REPORT = 52; static const uint16_t SIZE_BOOT_STATUS_REPORT = 24; static const uint16_t SIZE_LATCHUP_STATUS_REPORT = 31; static const uint16_t SIZE_LOGGING_REPORT = 73; diff --git a/mission/controller/AcsController.cpp b/mission/controller/AcsController.cpp index febe385a..1350bcf0 100644 --- a/mission/controller/AcsController.cpp +++ b/mission/controller/AcsController.cpp @@ -204,8 +204,7 @@ void AcsController::performSafe() { acs::SafeModeStrategy safeCtrlStrat = safeCtrl.safeCtrlStrategy( mgmDataProcessed.mgmVecTot.isValid(), not mekfInvalidFlag, gyrDataProcessed.gyrVecTot.isValid(), susDataProcessed.susVecTot.isValid(), - fusedRotRateData.rotRateOrthogonal.isValid(), fusedRotRateData.rotRateTotal.isValid(), - acsParameters.safeModeControllerParameters.useMekf, + fusedRotRateData.rotRateTotal.isValid(), acsParameters.safeModeControllerParameters.useMekf, acsParameters.safeModeControllerParameters.useGyr, acsParameters.safeModeControllerParameters.dampingDuringEclipse); switch (safeCtrlStrat) { @@ -223,7 +222,8 @@ void AcsController::performSafe() { safeCtrlFailureCounter = 0; break; case (acs::SafeModeStrategy::SAFECTRL_SUSMGM): - safeCtrl.safeSusMgm(mgmDataProcessed.mgmVecTot.value, fusedRotRateData.rotRateParallel.value, + safeCtrl.safeSusMgm(mgmDataProcessed.mgmVecTot.value, fusedRotRateData.rotRateTotal.value, + fusedRotRateData.rotRateParallel.value, fusedRotRateData.rotRateOrthogonal.value, susDataProcessed.susVecTot.value, sunTargetDir, magMomMtq, errAng); safeCtrlFailureFlag = false; diff --git a/mission/controller/acs/AcsParameters.cpp b/mission/controller/acs/AcsParameters.cpp index 2c97fa99..7b867a46 100644 --- a/mission/controller/acs/AcsParameters.cpp +++ b/mission/controller/acs/AcsParameters.cpp @@ -113,6 +113,9 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId, case 0x13: parameterWrapper->set(mgmHandlingParameters.mgmDerivativeFilterWeight); break; + case 0x14: + parameterWrapper->set(mgmHandlingParameters.useMgm4); + break; default: return INVALID_IDENTIFIER_ID; } diff --git a/mission/controller/acs/AcsParameters.h b/mission/controller/acs/AcsParameters.h index ae33ac43..0fb1daa9 100644 --- a/mission/controller/acs/AcsParameters.h +++ b/mission/controller/acs/AcsParameters.h @@ -80,6 +80,7 @@ class AcsParameters : public HasParametersIF { float mgm4variance[3] = {pow(1.7e-6, 2), pow(1.7e-6, 2), pow(1.7e-6, 2)}; float mgmVectorFilterWeight = 0.85; float mgmDerivativeFilterWeight = 0.85; + uint8_t useMgm4 = false; } mgmHandlingParameters; struct SusHandlingParameters { diff --git a/mission/controller/acs/SensorProcessing.cpp b/mission/controller/acs/SensorProcessing.cpp index a683aada..686a2fcf 100644 --- a/mission/controller/acs/SensorProcessing.cpp +++ b/mission/controller/acs/SensorProcessing.cpp @@ -101,7 +101,7 @@ void SensorProcessing::processMgm(const float *mgm0Value, bool mgm0valid, const sensorFusionDenominator[i] += 1 / mgmParameters->mgm13variance[i]; } } - if (mgm4valid) { + if (mgm4valid and mgmParameters->useMgm4) { float mgm4ValueUT[3]; VectorOperations::mulScalar(mgm4Value, 1e-3, mgm4ValueUT, 3); // nT to uT MatrixOperations::multiply(mgmParameters->mgm4orientationMatrix[0], mgm4ValueUT, diff --git a/mission/controller/acs/control/SafeCtrl.cpp b/mission/controller/acs/control/SafeCtrl.cpp index 8ad8b578..de0cd197 100644 --- a/mission/controller/acs/control/SafeCtrl.cpp +++ b/mission/controller/acs/control/SafeCtrl.cpp @@ -9,10 +9,12 @@ SafeCtrl::SafeCtrl(AcsParameters *acsParameters_) { acsParameters = acsParameter SafeCtrl::~SafeCtrl() {} -acs::SafeModeStrategy SafeCtrl::safeCtrlStrategy( - const bool magFieldValid, const bool mekfValid, const bool satRotRateValid, - const bool sunDirValid, const bool fusedRateSplitValid, const bool fusedRateTotalValid, - const uint8_t mekfEnabled, const uint8_t gyrEnabled, const uint8_t dampingEnabled) { +acs::SafeModeStrategy SafeCtrl::safeCtrlStrategy(const bool magFieldValid, const bool mekfValid, + const bool satRotRateValid, const bool sunDirValid, + const bool fusedRateTotalValid, + const uint8_t mekfEnabled, + const uint8_t gyrEnabled, + const uint8_t dampingEnabled) { if (not magFieldValid) { return acs::SafeModeStrategy::SAFECTRL_NO_MAG_FIELD_FOR_CONTROL; } else if (mekfEnabled and mekfValid) { @@ -20,7 +22,7 @@ acs::SafeModeStrategy SafeCtrl::safeCtrlStrategy( } else if (sunDirValid) { if (gyrEnabled and satRotRateValid) { return acs::SafeModeStrategy::SAFECTRL_GYR; - } else if (not gyrEnabled and fusedRateSplitValid) { + } else if (not gyrEnabled and fusedRateTotalValid) { return acs::SafeModeStrategy::SAFECTRL_SUSMGM; } else { return acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL; @@ -95,9 +97,10 @@ void SafeCtrl::safeGyr(const double *magFieldB, const double *satRotRateB, const calculateMagneticMoment(magMomB); } -void SafeCtrl::safeSusMgm(const double *magFieldB, const double *rotRateParallelB, - const double *rotRateOrthogonalB, const double *sunDirB, - const double *sunDirRefB, double *magMomB, double &errorAngle) { +void SafeCtrl::safeSusMgm(const double *magFieldB, const double *rotRateTotalB, + const double *rotRateParallelB, const double *rotRateOrthogonalB, + const double *sunDirB, const double *sunDirRefB, double *magMomB, + double &errorAngle) { // convert magFieldB from uT to T VectorOperations::mulScalar(magFieldB, 1e-6, magFieldBT, 3); @@ -105,8 +108,14 @@ void SafeCtrl::safeSusMgm(const double *magFieldB, const double *rotRateParallel double dotSun = VectorOperations::dot(sunDirRefB, sunDirB); errorAngle = acos(dotSun); - std::memcpy(satRotRateParallelB, rotRateParallelB, sizeof(satRotRateParallelB)); - std::memcpy(satRotRateOrthogonalB, rotRateOrthogonalB, sizeof(satRotRateOrthogonalB)); + if (VectorOperations::norm(rotRateParallelB, 3) != 0 and + VectorOperations::norm(rotRateOrthogonalB, 3) != 0) { + std::memcpy(satRotRateParallelB, rotRateParallelB, sizeof(satRotRateParallelB)); + std::memcpy(satRotRateOrthogonalB, rotRateOrthogonalB, sizeof(satRotRateOrthogonalB)); + } else { + splitRotationalRate(rotRateTotalB, sunDirB); + } + calculateRotationalRateTorque(acsParameters->safeModeControllerParameters.k_parallelSusMgm, acsParameters->safeModeControllerParameters.k_orthoSusMgm); calculateAngleErrorTorque(sunDirB, sunDirRefB, diff --git a/mission/controller/acs/control/SafeCtrl.h b/mission/controller/acs/control/SafeCtrl.h index 55bcbf08..d35d5d04 100644 --- a/mission/controller/acs/control/SafeCtrl.h +++ b/mission/controller/acs/control/SafeCtrl.h @@ -14,7 +14,6 @@ class SafeCtrl { acs::SafeModeStrategy safeCtrlStrategy(const bool magFieldValid, const bool mekfValid, const bool satRotRateValid, const bool sunDirValid, - const bool fusedRateSplitValid, const bool fusedRateTotalValid, const uint8_t mekfEnabled, const uint8_t gyrEnabled, const uint8_t dampingEnabled); @@ -25,9 +24,10 @@ class SafeCtrl { void safeGyr(const double *magFieldB, const double *satRotRateB, const double *sunDirB, const double *sunDirRefB, double *magMomB, double &errorAngle); - void safeSusMgm(const double *magFieldB, const double *rotRateParallelB, - const double *rotRateOrthogonalB, const double *sunDirB, const double *sunDirRefB, - double *magMomB, double &errorAngle); + void safeSusMgm(const double *magFieldB, const double *rotRateTotalB, + const double *rotRateParallelB, const double *rotRateOrthogonalB, + const double *sunDirB, const double *sunDirRefB, double *magMomB, + double &errorAngle); void safeRateDampingGyr(const double *magFieldB, const double *satRotRateB, const double *sunDirRefB, double *magMomB, double &errorAngle); diff --git a/mission/system/EiveSystem.cpp b/mission/system/EiveSystem.cpp index 41f52cde..6519806e 100644 --- a/mission/system/EiveSystem.cpp +++ b/mission/system/EiveSystem.cpp @@ -133,6 +133,10 @@ void EiveSystem::handleEventMessages() { case pdec::INVALID_TC_FRAME: { if (event.getParameter1() == pdec::FRAME_DIRTY_RETVAL) { frameDirtyErrorCounter++; + // Check whether threshold was reached after 10 seconds. + if (frameDirtyErrorCounter == 1) { + frameDirtyCheckCd.resetTimer(); + } } break; } @@ -296,42 +300,39 @@ ReturnValue_t EiveSystem::sendFullRebootCommand() { } void EiveSystem::pdecRecoveryLogic() { - if (pdecResetWasAttempted and pdecResetWasAttemptedCd.hasTimedOut()) { - pdecResetWasAttempted = false; + // PDEC reset has happened too often in the last time. Perform reboot to same image. + if (pdecResetCounter >= PDEC_RESET_MAX_COUNT_BEFORE_REBOOT) { + if (waitingForPdecReboot) { + return; + } + triggerEvent(core::PDEC_REBOOT); + // Some delay to ensure that the event is stored in the persistent TM store as well. + TaskFactory::delayTask(500); + // Send reboot command. + ReturnValue_t result = sendSelfRebootCommand(); + if (result != returnvalue::OK) { + sif::error << "Sending a reboot command has failed" << std::endl; + // If the previous operation failed, it should be re-attempted the next task cycle. + pdecResetCounterResetCd.resetTimer(); + return; + } + waitingForPdecReboot = true; + return; } - if (frameDirtyCheckCd.hasTimedOut()) { + if (pdecResetCounterResetCd.hasTimedOut()) { + pdecResetCounter = 0; + } + if (frameDirtyCheckCd.hasTimedOut() and frameDirtyErrorCounter > 0) { if (frameDirtyErrorCounter >= FRAME_DIRTY_COM_REBOOT_LIMIT) { - // If a PTME reset was already attempted and there is still an issue receiving TC frames, - // reboot the system. - if (pdecResetWasAttempted) { - if (waitingForPdecReboot) { - return; - } - triggerEvent(core::PDEC_REBOOT); - // Some delay to ensure that the event is stored in the persistent TM store as well. - TaskFactory::delayTask(500); - // Send reboot command. - ReturnValue_t result = sendSelfRebootCommand(); - if (result != returnvalue::OK) { - sif::error << "Sending a reboot command has failed" << std::endl; - // If the previous operation failed, it should be re-attempted the next task cycle. - pdecResetWasAttemptedCd.resetTimer(); - return; - } - waitingForPdecReboot = true; - return; - } else { - // Try one full PDEC reset. - CommandMessage msg; - store_address_t dummy{}; - ActionMessage::setCommand(&msg, pdec::RESET_PDEC_WITH_REINIITALIZATION, dummy); - commandQueue->sendMessage(pdecHandlerQueueId, &msg); - pdecResetWasAttemptedCd.resetTimer(); - pdecResetWasAttempted = true; - } + // Try one full PDEC reset. + CommandMessage msg; + store_address_t dummy{}; + ActionMessage::setCommand(&msg, pdec::RESET_PDEC_WITH_REINIITALIZATION, dummy); + commandQueue->sendMessage(pdecHandlerQueueId, &msg); + pdecResetCounterResetCd.resetTimer(); + pdecResetCounter++; } frameDirtyErrorCounter = 0; - frameDirtyCheckCd.resetTimer(); } } diff --git a/mission/system/EiveSystem.h b/mission/system/EiveSystem.h index c724ba34..e6ff19b9 100644 --- a/mission/system/EiveSystem.h +++ b/mission/system/EiveSystem.h @@ -10,6 +10,7 @@ class EiveSystem : public Subsystem, public HasActionsIF { public: static constexpr uint8_t FRAME_DIRTY_COM_REBOOT_LIMIT = 4; + static constexpr uint32_t PDEC_RESET_MAX_COUNT_BEFORE_REBOOT = 10; static constexpr ActionId_t EXECUTE_I2C_REBOOT = 10; @@ -39,11 +40,11 @@ class EiveSystem : public Subsystem, public HasActionsIF { Countdown frameDirtyCheckCd = Countdown(10000); // If the PDEC reset was already attempted in the last 2 minutes, there is a high chance that // only a full reboot will fix the issue. - Countdown pdecResetWasAttemptedCd = Countdown(120000); - bool pdecResetWasAttempted = false; + Countdown pdecResetCounterResetCd = Countdown(120000); bool waitingForI2cReboot = false; bool waitingForPdecReboot = false; + uint32_t pdecResetCounter = 0; ActionHelper actionHelper; PowerSwitchIF* powerSwitcher = nullptr; std::atomic_uint16_t& i2cErrors;