diff --git a/CHANGELOG.md b/CHANGELOG.md index 8841cd0c..099ab2e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,9 +16,24 @@ will consitute of a breaking change warranting a new major release: # [unreleased] -# [v2.2.0] to be released +# [v4.0.0] to be released -# [v2.1.0] to be released +- `eive-tmtc` version v4.0.0 +TODO: New firmware package version. + +## Fixed + +- CFDP low level protocol bugfix. Requires fsfw update and tmtc update. +- Important bugfixes for PTME. See `q7s-package` CHANGELOG. + +## Changed + +- Removed PTME busy/ready signals. Those were not used anyway because register reads are used now. +- APB bus access busy checking is not done anymore as this is performed by the bus itself now. + +# [v3.0.0] 2023-06-11 + +- `eive-tmtc` version v4.0.0 ## Changed @@ -36,14 +51,46 @@ will consitute of a breaking change warranting a new major release: - Add support for MPSoC HK packet. - Add support for MPSoC Flash Directory Content Report. - Dynamically enable and disable HK packets for MPSoC on `ON` and `OFF` commands. +- Add support for MPSoC Flash Directory Content Report. +- Larger allowed path and file sizes for STR and PLOC MPSoC modules. +- More robust MPSoC flash read and write command data handling. - Increase frequency of payload handlers from 0.8 seconds to 0.5 seconds. +- Disable missed deadlines per default. Not useful in orbit, and triggers all the time on the EM + build after a number of subsequent runs, without any apparent reason (deadlines are not actually + missed, thread usage displayed is nominal) +- TM store dumpes will not be cancelled anymore if the transmitter is off. The dump can be cancelled + with an OFF command, and the PTME is perfectly capable of dumping without the transmitter being + on. +- Transmitter state is not taken into account anymore for writing into the PTME. The PTME should + be perfectly capable of generating a valid CADU, even when the transmitter is not ON for any + reason. +- OFF mode is ignores in TM store for determining whether a store will be written. The modes will + only be used to cancel a transfer. +- Handling of multiple RWs in the ACS Controller is improved and can be changed by parameter + commands. +- The Directory Listing direct dumper now has a state machine to stagger the directory listing dump. + This is required because very large dumps will overload the queue capacities in the framework. +- The PUS Service 8 now has larger queue sizes to handle more action replies. The PUS Service 1 + also has a larger queue size to handle a lot of step replies now. +- Moved PDU `vcc` and `vbat` variable from auxiliary dataset to core dataset. +- Tweak TCP/IP configuration: Only the TCP server will be included on the EM. For the FM, no + TCP/IP servers will be included by default. ## Added - Add the remaining system modes. +- PLOC MPSoC flash read command working. +- BPX battery handler is added for EM by default. +- ACU dummy HK sets +- IMTQ HK sets +- IMTQ dummy now handles power switch +- Added some new ACS parameters +- Enabled decimation filter for the ADIS GYRs +- Enabled second low-pass filter for L3GD20H GYRs ## Fixed +- CFDP low level protocol bugfix. Requires `fsfw` update and `tmtc` update. - Compile fix if SCEX is compiled for the EM. - Set up Rad Sensor chip select even for EM to avoid SPI bus issues. - Correct ADIS Gyroscope type configuration for the EM, where the 16507 type is used instead of the @@ -57,9 +104,32 @@ will consitute of a breaking change warranting a new major release: - The PLOC MPSoC now waits 10 cycles before going to on. These wait cycles are necessary because the MPSoC is not ready to process commands without this additional boot time. - Fixed correction for `GPS Altitude` in case the sensor data is out of the expected bonds. +- PLOC MPSoC special communication is now scheduled, which allows flash read and flash write + commands to work. +- Fixed the MPSoC flash write command. +- Added missing ACS parameter. +- HK TM store: The HK store dump success event was triggered for cancelled HK dumps. +- When a PUS parsing error occured while parsing a TM store file, the dump completion procedure + was always executed. +- Some smaller logic fixes in the TM store base class +- Fixed usage of C `abs` instead of C++ `std::abs`, which results in MTQ commands not being + scaled correctly between 1Am² and 0.2Am². +- TCS Heater Handler: Always trigger mode event if a heater goes `OFF` or `ON`. This event might + soon replace the `HEATER_WENT_ON` and `HEATER_WENT_OFF` events. +- Prevent spam of TCS controller heater unavailability event if all heaters are in external control. +- TCS heater switch info set contained invalid values because of a faulty `memcpy` in the TCS + controller. There is not crash risk but the heater states were invalid. +- STR datasets were not set to invalid on shutdown. +- Fixed usage of quaternion valid flag, which does not actually represent the validity of the + quaternion. +- Various fixes for the pointing modes of the `ACS Controller`. All modes should work now as + intended. +- The variance for the ADIS GYRs now represents the used `-3` version and not the `-1` version +- CFDP funnel did not route packets to live channel VC0 # [v2.0.5] 2023-05-11 + - The dual lane assembly transition failed handler started new transitions towards the current mode instead of the target mode. This means that if the dual lane assembly never reached the initial submode (e.g. mode normal and submode dual side), it will transition back to the current mode, diff --git a/CMakeLists.txt b/CMakeLists.txt index c2a9482e..3c7e1c1e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,9 +9,9 @@ # ############################################################################## cmake_minimum_required(VERSION 3.13) -set(OBSW_VERSION_MAJOR 2) +set(OBSW_VERSION_MAJOR 4) set(OBSW_VERSION_MINOR 0) -set(OBSW_VERSION_REVISION 5) +set(OBSW_VERSION_REVISION 0) # set(CMAKE_VERBOSE TRUE) @@ -79,12 +79,19 @@ else() set(INIT_VAL 1) set(OBSW_STAR_TRACKER_GROUND_CONFIG 0) endif() + +set(OBSW_ADD_TMTC_TCP_SERVER + ${OBSW_Q7S_EM} + CACHE STRING "Add TCP TMTC Server") +set(OBSW_ADD_TMTC_UDP_SERVER + 0 + CACHE STRING "Add UDP TMTC Server") set(OBSW_ADD_MGT ${INIT_VAL} CACHE STRING "Add MGT module") set(OBSW_ADD_BPX_BATTERY_HANDLER - ${INIT_VAL} - CACHE STRING "Add MGT module") + 1 + CACHE STRING "Add BPX battery module") set(OBSW_ADD_STAR_TRACKER ${INIT_VAL} CACHE STRING "Add Startracker module") @@ -98,7 +105,7 @@ set(OBSW_ADD_THERMAL_TEMP_INSERTER ${OBSW_Q7S_EM} CACHE STRING "Add thermal sensor temperature inserter") set(OBSW_ADD_ACS_BOARD - 1 + ${INIT_VAL} CACHE STRING "Add ACS board module") set(OBSW_ADD_GPS_CTRL ${INIT_VAL} diff --git a/bsp_hosted/ObjectFactory.cpp b/bsp_hosted/ObjectFactory.cpp index d792b57b..dd88d552 100644 --- a/bsp_hosted/ObjectFactory.cpp +++ b/bsp_hosted/ObjectFactory.cpp @@ -39,7 +39,7 @@ #include "devices/gpioIds.h" #include "fsfw_hal/linux/gpio/Gpio.h" #include "linux/payload/PlocMpsocHandler.h" -#include "linux/payload/PlocMpsocHelper.h" +#include "linux/payload/PlocMpsocSpecialComHelper.h" #include "linux/payload/PlocSupervisorHandler.h" #include "linux/payload/PlocSupvUartMan.h" #include "test/gpio/DummyGpioIF.h" @@ -62,6 +62,10 @@ void ObjectFactory::produce(void* args) { StorageManagerIF* tmStore; StorageManagerIF* ipcStore; PersistentTmStores persistentStores; + bool enableHkSets = false; +#if OBSW_ENABLE_PERIODIC_HK == 1 + enableHkSets = true; +#endif auto sdcMan = new DummySdCardManager("/tmp"); ObjectFactory::produceGenericObjects(nullptr, &pusFunnel, &cfdpFunnel, *sdcMan, &ipcStore, &tmStore, persistentStores, 120); @@ -82,8 +86,8 @@ void ObjectFactory::produce(void* args) { auto mpsocCookie = new UartCookie(objects::PLOC_MPSOC_HANDLER, mpscoDev, uart::PLOC_MPSOC_BAUD, mpsoc::MAX_REPLY_SIZE, UartModes::NON_CANONICAL); mpsocCookie->setNoFixedSizeReply(); - auto plocMpsocHelper = new PlocMPSoCHelper(objects::PLOC_MPSOC_HELPER); - new PlocMPSoCHandler(objects::PLOC_MPSOC_HANDLER, objects::UART_COM_IF, mpsocCookie, + auto plocMpsocHelper = new PlocMpsocSpecialComHelper(objects::PLOC_MPSOC_HELPER); + new PlocMpsocHandler(objects::PLOC_MPSOC_HANDLER, objects::UART_COM_IF, mpsocCookie, plocMpsocHelper, Gpio(gpioIds::ENABLE_MPSOC_UART, dummyGpioIF), objects::PLOC_SUPERVISOR_HANDLER); #endif /* OBSW_ADD_PLOC_MPSOC == 1 */ @@ -101,7 +105,7 @@ void ObjectFactory::produce(void* args) { #endif dummy::DummyCfg cfg; - dummy::createDummies(cfg, *dummySwitcher, dummyGpioIF); + dummy::createDummies(cfg, *dummySwitcher, dummyGpioIF, enableHkSets); HeaterHandler* heaterHandler = nullptr; // new ThermalController(objects::THERMAL_CONTROLLER); diff --git a/bsp_hosted/fsfwconfig/events/translateEvents.cpp b/bsp_hosted/fsfwconfig/events/translateEvents.cpp index f7850a99..9a93fe4c 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 291 translations. + * @brief Auto-generated event translation file. Contains 295 translations. * @details - * Generated on: 2023-04-17 11:34:19 + * Generated on: 2023-05-17 17:15:34 */ #include "translateEvents.h" @@ -197,6 +197,10 @@ const char *MPSOC_EXE_INVALID_APID_STRING = "MPSOC_EXE_INVALID_APID"; const char *MPSOC_HELPER_SEQ_CNT_MISMATCH_STRING = "MPSOC_HELPER_SEQ_CNT_MISMATCH"; const char *MPSOC_TM_SIZE_ERROR_STRING = "MPSOC_TM_SIZE_ERROR"; const char *MPSOC_TM_CRC_MISSMATCH_STRING = "MPSOC_TM_CRC_MISSMATCH"; +const char *MPSOC_FLASH_READ_PACKET_ERROR_STRING = "MPSOC_FLASH_READ_PACKET_ERROR"; +const char *MPSOC_FLASH_READ_FAILED_STRING = "MPSOC_FLASH_READ_FAILED"; +const char *MPSOC_FLASH_READ_SUCCESSFUL_STRING = "MPSOC_FLASH_READ_SUCCESSFUL"; +const char *MPSOC_READ_TIMEOUT_STRING = "MPSOC_READ_TIMEOUT"; const char *TRANSITION_BACK_TO_OFF_STRING = "TRANSITION_BACK_TO_OFF"; const char *NEG_V_OUT_OF_BOUNDS_STRING = "NEG_V_OUT_OF_BOUNDS"; const char *U_DRO_OUT_OF_BOUNDS_STRING = "U_DRO_OUT_OF_BOUNDS"; @@ -683,6 +687,14 @@ const char *translateEvents(Event event) { return MPSOC_TM_SIZE_ERROR_STRING; case (12613): return MPSOC_TM_CRC_MISSMATCH_STRING; + case (12614): + return MPSOC_FLASH_READ_PACKET_ERROR_STRING; + case (12615): + return MPSOC_FLASH_READ_FAILED_STRING; + case (12616): + return MPSOC_FLASH_READ_SUCCESSFUL_STRING; + case (12617): + return MPSOC_READ_TIMEOUT_STRING; case (12700): return TRANSITION_BACK_TO_OFF_STRING; case (12701): diff --git a/bsp_hosted/fsfwconfig/objects/translateObjects.cpp b/bsp_hosted/fsfwconfig/objects/translateObjects.cpp index 16235835..34edfa41 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-04-17 11:34:19 + * Generated on: 2023-05-17 17:15:34 */ #include "translateObjects.h" diff --git a/bsp_q7s/OBSWConfig.h.in b/bsp_q7s/OBSWConfig.h.in index 51ed8828..2555d7cd 100644 --- a/bsp_q7s/OBSWConfig.h.in +++ b/bsp_q7s/OBSWConfig.h.in @@ -67,12 +67,12 @@ // because UDP packets are not allowed in the VPN // This will cause the OBSW to initialize the TMTC bridge responsible for exchanging data with the // CCSDS IP Cores. -#define OBSW_ADD_TMTC_TCP_SERVER 1 -#define OBSW_ADD_TMTC_UDP_SERVER 1 +#define OBSW_ADD_TMTC_TCP_SERVER @OBSW_ADD_TMTC_TCP_SERVER@ +#define OBSW_ADD_TMTC_UDP_SERVER @OBSW_ADD_TMTC_UDP_SERVER@ // Can be used to switch device to NORMAL mode immediately #define OBSW_SWITCH_TO_NORMAL_MODE_AFTER_STARTUP 0 -#define OBSW_PRINT_MISSED_DEADLINES 1 +#define OBSW_PRINT_MISSED_DEADLINES 0 #define OBSW_MPSOC_JTAG_BOOT 0 #define OBSW_STAR_TRACKER_GROUND_CONFIG @OBSW_STAR_TRACKER_GROUND_CONFIG@ diff --git a/bsp_q7s/boardconfig/busConf.h b/bsp_q7s/boardconfig/busConf.h index 4fd15258..304113d2 100644 --- a/bsp_q7s/boardconfig/busConf.h +++ b/bsp_q7s/boardconfig/busConf.h @@ -82,14 +82,12 @@ static constexpr char EN_RW_4[] = "enable_rw_4"; static constexpr char RAD_SENSOR_CHIP_SELECT[] = "rad_sensor_chip_select"; static constexpr char ENABLE_RADFET[] = "enable_radfet"; -static constexpr char PAPB_BUSY_SIGNAL_VC0[] = "papb_busy_signal_vc0"; + static constexpr char PAPB_EMPTY_SIGNAL_VC0[] = "papb_empty_signal_vc0"; -static constexpr char PAPB_BUSY_SIGNAL_VC1[] = "papb_busy_signal_vc1"; static constexpr char PAPB_EMPTY_SIGNAL_VC1[] = "papb_empty_signal_vc1"; -static constexpr char PAPB_BUSY_SIGNAL_VC2[] = "papb_busy_signal_vc2"; static constexpr char PAPB_EMPTY_SIGNAL_VC2[] = "papb_empty_signal_vc2"; -static constexpr char PAPB_BUSY_SIGNAL_VC3[] = "papb_busy_signal_vc3"; static constexpr char PAPB_EMPTY_SIGNAL_VC3[] = "papb_empty_signal_vc3"; + static constexpr char PTME_RESETN[] = "ptme_resetn"; static constexpr char RS485_EN_TX_CLOCK[] = "tx_clock_enable_ltc2872"; diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index 5c4c4d62..76460aa5 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -112,6 +112,9 @@ void CoreController::performControlOperation() { sdStateMachine(); performMountedSdCardOperations(); readHkData(); + if (dumpContext.active) { + dirListingDumpHandler(); + } if (shellCmdIsExecuting) { bool replyReceived = false; @@ -1038,7 +1041,6 @@ ReturnValue_t CoreController::actionListDirectoryDumpDirectly(ActionId_t actionI return returnvalue::FAILED; } } - std::array dirListingBuf{}; dirListingBuf[8] = parser.compressionOptionSet(); // First four bytes reserved for segment index. One byte for compression option information std::strcpy(reinterpret_cast(dirListingBuf.data() + 2 * sizeof(uint32_t) + 1), repoName); @@ -1047,38 +1049,47 @@ ReturnValue_t CoreController::actionListDirectoryDumpDirectly(ActionId_t actionI return returnvalue::FAILED; } std::error_code e; - size_t totalFileSize = std::filesystem::file_size(LIST_DIR_DUMP_WORK_FILE, e); - uint32_t segmentIdx = 0; - size_t dumpedBytes = 0; + dumpContext.totalFileSize = std::filesystem::file_size(LIST_DIR_DUMP_WORK_FILE, e); + dumpContext.segmentIdx = 0; + dumpContext.dumpedBytes = 0; size_t nextDumpLen = 0; size_t dummy = 0; - size_t maxDumpLen = dirListingBuf.size() - 2 * sizeof(uint32_t) - 1 - repoNameLen - 1; - size_t listingDataOffset = 2 * sizeof(uint32_t) + 1 + repoNameLen + 1; - uint32_t chunks = totalFileSize / maxDumpLen; - if (totalFileSize % maxDumpLen != 0) { + dumpContext.maxDumpLen = dirListingBuf.size() - 2 * sizeof(uint32_t) - 1 - repoNameLen - 1; + dumpContext.listingDataOffset = 2 * sizeof(uint32_t) + 1 + repoNameLen + 1; + uint32_t chunks = dumpContext.totalFileSize / dumpContext.maxDumpLen; + if (dumpContext.totalFileSize % dumpContext.maxDumpLen != 0) { chunks++; } SerializeAdapter::serialize(&chunks, dirListingBuf.data() + sizeof(uint32_t), &dummy, dirListingBuf.size() - sizeof(uint32_t), SerializeIF::Endianness::NETWORK); - while (dumpedBytes < totalFileSize) { - ifile.seekg(dumpedBytes, std::ios::beg); - nextDumpLen = maxDumpLen; - if (totalFileSize - dumpedBytes < maxDumpLen) { - nextDumpLen = totalFileSize - dumpedBytes; + while (dumpContext.dumpedBytes < dumpContext.totalFileSize) { + ifile.seekg(dumpContext.dumpedBytes, std::ios::beg); + nextDumpLen = dumpContext.maxDumpLen; + if (dumpContext.totalFileSize - dumpContext.dumpedBytes < dumpContext.maxDumpLen) { + nextDumpLen = dumpContext.totalFileSize - dumpContext.dumpedBytes; } - SerializeAdapter::serialize(&segmentIdx, dirListingBuf.data(), &dummy, dirListingBuf.size(), - SerializeIF::Endianness::NETWORK); - ifile.read(reinterpret_cast(dirListingBuf.data() + listingDataOffset), nextDumpLen); + SerializeAdapter::serialize(&dumpContext.segmentIdx, dirListingBuf.data(), &dummy, + dirListingBuf.size(), SerializeIF::Endianness::NETWORK); + ifile.read(reinterpret_cast(dirListingBuf.data() + dumpContext.listingDataOffset), + nextDumpLen); result = actionHelper.reportData(commandedBy, actionId, dirListingBuf.data(), - listingDataOffset + nextDumpLen); + dumpContext.listingDataOffset + nextDumpLen); if (result != returnvalue::OK) { // Remove work file when we are done std::filesystem::remove(LIST_DIR_DUMP_WORK_FILE, e); return result; } - segmentIdx++; - dumpedBytes += nextDumpLen; + dumpContext.segmentIdx++; + dumpContext.dumpedBytes += nextDumpLen; + // Dump takes multiple task cycles, so cache the dump state and continue dump the next cycles. + if (dumpContext.segmentIdx == 10) { + dumpContext.active = true; + dumpContext.firstDump = true; + dumpContext.commander = commandedBy; + dumpContext.actionId = actionId; + return returnvalue::OK; + } } // Remove work file when we are done std::filesystem::remove(LIST_DIR_DUMP_WORK_FILE, e); @@ -2346,6 +2357,54 @@ MessageQueueId_t CoreController::getCommandQueue() const { return ExtendedControllerBase::getCommandQueue(); } +void CoreController::dirListingDumpHandler() { + if (dumpContext.firstDump) { + dumpContext.firstDump = false; + return; + } + size_t nextDumpLen = 0; + size_t dummy = 0; + ReturnValue_t result; + std::error_code e; + std::ifstream ifile(LIST_DIR_DUMP_WORK_FILE, std::ios::binary); + if (ifile.bad()) { + return; + } + while (dumpContext.dumpedBytes < dumpContext.totalFileSize) { + ifile.seekg(dumpContext.dumpedBytes, std::ios::beg); + nextDumpLen = dumpContext.maxDumpLen; + if (dumpContext.totalFileSize - dumpContext.dumpedBytes < dumpContext.maxDumpLen) { + nextDumpLen = dumpContext.totalFileSize - dumpContext.dumpedBytes; + } + SerializeAdapter::serialize(&dumpContext.segmentIdx, dirListingBuf.data(), &dummy, + dirListingBuf.size(), SerializeIF::Endianness::NETWORK); + ifile.read(reinterpret_cast(dirListingBuf.data() + dumpContext.listingDataOffset), + nextDumpLen); + result = + actionHelper.reportData(dumpContext.commander, dumpContext.actionId, dirListingBuf.data(), + dumpContext.listingDataOffset + nextDumpLen); + if (result != returnvalue::OK) { + // Remove work file when we are done + std::filesystem::remove(LIST_DIR_DUMP_WORK_FILE, e); + dumpContext.active = false; + actionHelper.finish(false, dumpContext.commander, dumpContext.actionId, result); + return; + } + dumpContext.segmentIdx++; + dumpContext.dumpedBytes += nextDumpLen; + // Dump takes multiple task cycles, so cache the dump state and continue dump the next cycles. + if (dumpContext.segmentIdx == 10) { + break; + } + } + if (dumpContext.dumpedBytes >= dumpContext.totalFileSize) { + actionHelper.finish(true, dumpContext.commander, dumpContext.actionId, result); + dumpContext.active = false; + // Remove work file when we are done + std::filesystem::remove(LIST_DIR_DUMP_WORK_FILE, e); + } +} + bool CoreController::isNumber(const std::string &s) { return !s.empty() && std::find_if(s.begin(), s.end(), [](unsigned char c) { return !std::isdigit(c); }) == s.end(); diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index d44907e8..05878d6d 100644 --- a/bsp_q7s/core/CoreController.h +++ b/bsp_q7s/core/CoreController.h @@ -177,6 +177,20 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe DeviceCommandId_t actionId; } sdCommandingInfo; + struct DirListingDumpContext { + bool active; + bool firstDump; + size_t dumpedBytes; + size_t totalFileSize; + size_t listingDataOffset; + size_t maxDumpLen; + uint32_t segmentIdx; + MessageQueueId_t commander = MessageQueueIF::NO_QUEUE; + DeviceCommandId_t actionId; + }; + std::array dirListingBuf{}; + DirListingDumpContext dumpContext{}; + RebootFile rebootFile = {}; CommandExecutor cmdExecutor; @@ -274,6 +288,7 @@ class CoreController : public ExtendedControllerBase, public ReceivesParameterMe void rewriteRebootFile(RebootFile file); void announceBootCounts(); void readHkData(); + void dirListingDumpHandler(); bool isNumber(const std::string& s); }; diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp index 8fcace4e..6e1bffdf 100644 --- a/bsp_q7s/core/ObjectFactory.cpp +++ b/bsp_q7s/core/ObjectFactory.cpp @@ -10,10 +10,10 @@ #include #include #include -#include +#include #include #include -#include +#include #include #include #include @@ -623,8 +623,8 @@ void ObjectFactory::createPayloadComponents(LinuxLibgpioIF* gpioComIF, PowerSwit new SerialCookie(objects::PLOC_MPSOC_HANDLER, q7s::UART_PLOC_MPSOC_DEV, serial::PLOC_MPSOC_BAUD, mpsoc::MAX_REPLY_SIZE, UartModes::NON_CANONICAL); mpsocCookie->setNoFixedSizeReply(); - auto plocMpsocHelper = new PlocMPSoCHelper(objects::PLOC_MPSOC_HELPER); - auto* mpsocHandler = new PlocMPSoCHandler( + auto plocMpsocHelper = new PlocMpsocSpecialComHelper(objects::PLOC_MPSOC_HELPER); + auto* mpsocHandler = new PlocMpsocHandler( objects::PLOC_MPSOC_HANDLER, objects::UART_COM_IF, mpsocCookie, plocMpsocHelper, Gpio(gpioIds::ENABLE_MPSOC_UART, gpioComIF), objects::PLOC_SUPERVISOR_HANDLER); mpsocHandler->connectModeTreeParent(satsystem::payload::SUBSYSTEM); @@ -730,20 +730,12 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(CcsdsComponentArgs& args) { // GPIO definitions of signals connected to the virtual channel interfaces of the PTME IP Core GpioCookie* gpioCookiePtmeIp = new GpioCookie; GpiodRegularByLineName* gpio = nullptr; - gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC0, "PAPB VC0"); - gpioCookiePtmeIp->addGpio(gpioIds::VC0_PAPB_BUSY, gpio); gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC0, "PAPB VC0"); gpioCookiePtmeIp->addGpio(gpioIds::VC0_PAPB_EMPTY, gpio); - gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC1, "PAPB VC1"); - gpioCookiePtmeIp->addGpio(gpioIds::VC1_PAPB_BUSY, gpio); gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC1, "PAPB VC1"); gpioCookiePtmeIp->addGpio(gpioIds::VC1_PAPB_EMPTY, gpio); - gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC2, "PAPB VC2"); - gpioCookiePtmeIp->addGpio(gpioIds::VC2_PAPB_BUSY, gpio); gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC2, "PAPB VC2"); gpioCookiePtmeIp->addGpio(gpioIds::VC2_PAPB_EMPTY, gpio); - gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_BUSY_SIGNAL_VC3, "PAPB VC3"); - gpioCookiePtmeIp->addGpio(gpioIds::VC3_PAPB_BUSY, gpio); gpio = new GpiodRegularByLineName(q7s::gpioNames::PAPB_EMPTY_SIGNAL_VC3, "PAPB VC3"); gpioCookiePtmeIp->addGpio(gpioIds::VC3_PAPB_EMPTY, gpio); gpio = new GpiodRegularByLineName(q7s::gpioNames::PTME_RESETN, "PTME RESETN", @@ -752,18 +744,14 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(CcsdsComponentArgs& args) { gpioChecker(args.gpioComIF.addGpios(gpioCookiePtmeIp), "PTME PAPB VCs"); // Creating virtual channel interfaces - VirtualChannelIF* vc0 = - new PapbVcInterface(&args.gpioComIF, gpioIds::VC0_PAPB_BUSY, gpioIds::VC0_PAPB_EMPTY, - q7s::UIO_PTME, q7s::uiomapids::PTME_VC0); - VirtualChannelIF* vc1 = - new PapbVcInterface(&args.gpioComIF, gpioIds::VC1_PAPB_BUSY, gpioIds::VC1_PAPB_EMPTY, - q7s::UIO_PTME, q7s::uiomapids::PTME_VC1); - VirtualChannelIF* vc2 = - new PapbVcInterface(&args.gpioComIF, gpioIds::VC2_PAPB_BUSY, gpioIds::VC2_PAPB_EMPTY, - q7s::UIO_PTME, q7s::uiomapids::PTME_VC2); - VirtualChannelIF* vc3 = - new PapbVcInterface(&args.gpioComIF, gpioIds::VC3_PAPB_BUSY, gpioIds::VC3_PAPB_EMPTY, - q7s::UIO_PTME, q7s::uiomapids::PTME_VC3); + VirtualChannelIF* vc0 = new PapbVcInterface(&args.gpioComIF, gpioIds::VC0_PAPB_EMPTY, + q7s::UIO_PTME, q7s::uiomapids::PTME_VC0); + VirtualChannelIF* vc1 = new PapbVcInterface(&args.gpioComIF, gpioIds::VC1_PAPB_EMPTY, + q7s::UIO_PTME, q7s::uiomapids::PTME_VC1); + VirtualChannelIF* vc2 = new PapbVcInterface(&args.gpioComIF, gpioIds::VC2_PAPB_EMPTY, + q7s::UIO_PTME, q7s::uiomapids::PTME_VC2); + VirtualChannelIF* vc3 = new PapbVcInterface(&args.gpioComIF, gpioIds::VC3_PAPB_EMPTY, + q7s::UIO_PTME, q7s::uiomapids::PTME_VC3); // Creating ptme object and adding virtual channel interfaces Ptme* ptme = new Ptme(objects::PTME); ptme->addVcInterface(ccsds::VC0, vc0); @@ -805,7 +793,7 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(CcsdsComponentArgs& args) { // Core task which handles the HK store and takes care of dumping it as TM using a VC directly auto* hkStore = new PersistentSingleTmStoreTask( objects::HK_STORE_AND_TM_TASK, args.ipcStore, *args.stores.hkStore, *vc, - persTmStore::DUMP_HK_STORE_DONE, persTmStore::DUMP_HK_STORE_DONE, *SdCardManager::instance(), + persTmStore::DUMP_HK_STORE_DONE, persTmStore::DUMP_HK_CANCELLED, *SdCardManager::instance(), PTME_LOCKED); hkStore->connectModeTreeParent(satsystem::com::SUBSYSTEM); diff --git a/bsp_q7s/core/scheduling.cpp b/bsp_q7s/core/scheduling.cpp index 5866ce8c..71da5bdc 100644 --- a/bsp_q7s/core/scheduling.cpp +++ b/bsp_q7s/core/scheduling.cpp @@ -345,7 +345,6 @@ void scheduling::initTasks() { } #endif /* OBSW_ADD_STAR_TRACKER == 1 */ - // TODO: Use regular scheduler for this task #if OBSW_ADD_PLOC_MPSOC == 1 PeriodicTaskIF* mpsocHelperTask = factory->createPeriodicTask( "PLOC_MPSOC_HELPER", 0, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.2, missedDeadlineFunc); @@ -472,6 +471,9 @@ void scheduling::initTasks() { #if OBSW_ADD_PLOC_SUPERVISOR == 1 supvHelperTask->startTask(); #endif /* OBSW_ADD_PLOC_SUPERVISOR == 1 */ +#if OBSW_ADD_PLOC_MPSOC == 1 + mpsocHelperTask->startTask(); +#endif plTask->startTask(); #if OBSW_ADD_TEST_CODE == 1 diff --git a/bsp_q7s/em/emObjectFactory.cpp b/bsp_q7s/em/emObjectFactory.cpp index 36863b89..5270e887 100644 --- a/bsp_q7s/em/emObjectFactory.cpp +++ b/bsp_q7s/em/emObjectFactory.cpp @@ -79,7 +79,7 @@ void ObjectFactory::produce(void* args) { #endif satsystem::EIVE_SYSTEM.setI2cRecoveryParams(pwrSwitcher); - dummy::createDummies(dummyCfg, *pwrSwitcher, gpioComIF); + dummy::createDummies(dummyCfg, *pwrSwitcher, gpioComIF, enableHkSets); new CoreController(objects::CORE_CONTROLLER, enableHkSets); @@ -97,10 +97,10 @@ void ObjectFactory::produce(void* args) { // TODO: Careful! Switching this on somehow messes with the communication with the ProASIC // and will cause xsc_boot_copy commands to always boot to 0 0 // createRadSensorComponent(gpioComIF); - // Still initialize chip select to avoid SPI bus issues. - createRadSensorChipSelect(gpioComIF); #if OBSW_ADD_ACS_BOARD == 1 + // Still initialize chip select to avoid SPI bus issues. + createRadSensorChipSelect(gpioComIF); createAcsBoardComponents(*spiMainComIF, gpioComIF, uartComIF, *pwrSwitcher, true, adis1650x::Type::ADIS16507); #else @@ -140,6 +140,7 @@ void ObjectFactory::produce(void* args) { #if OBSW_TM_TO_PTME == 1 if (ccsdsArgs.liveDestination != nullptr) { pusFunnel->addLiveDestination("VC0 LIVE TM", *ccsdsArgs.liveDestination, 0); + cfdpFunnel->addLiveDestination("VC0 LIVE TM", *ccsdsArgs.liveDestination, 0); } #endif #endif /* OBSW_ADD_CCSDS_IP_CORES == 1 */ diff --git a/bsp_q7s/fmObjectFactory.cpp b/bsp_q7s/fmObjectFactory.cpp index df0bbc91..5eeeef59 100644 --- a/bsp_q7s/fmObjectFactory.cpp +++ b/bsp_q7s/fmObjectFactory.cpp @@ -97,6 +97,7 @@ void ObjectFactory::produce(void* args) { #if OBSW_TM_TO_PTME == 1 if (ccsdsArgs.liveDestination != nullptr) { pusFunnel->addLiveDestination("VC0 LIVE TM", *ccsdsArgs.liveDestination, 0); + cfdpFunnel->addLiveDestination("VC0 LIVE TM", *ccsdsArgs.liveDestination, 0); } #endif #endif /* OBSW_ADD_CCSDS_IP_CORES == 1 */ diff --git a/common/config/devices/gpioIds.h b/common/config/devices/gpioIds.h index 640f4ead..573327fa 100644 --- a/common/config/devices/gpioIds.h +++ b/common/config/devices/gpioIds.h @@ -93,15 +93,10 @@ enum gpioId_t { EN_RW_CS, SPI_MUX, - VC0_PAPB_EMPTY, - VC0_PAPB_BUSY, VC1_PAPB_EMPTY, - VC1_PAPB_BUSY, VC2_PAPB_EMPTY, - VC2_PAPB_BUSY, VC3_PAPB_EMPTY, - VC3_PAPB_BUSY, PTME_RESETN, PDEC_RESET, diff --git a/common/config/eive/definitions.h b/common/config/eive/definitions.h index 8c460f53..2083962a 100644 --- a/common/config/eive/definitions.h +++ b/common/config/eive/definitions.h @@ -34,8 +34,8 @@ static constexpr uint32_t STR_IMG_HELPER_QUEUE_SIZE = 50; static constexpr uint8_t LIVE_TM = 0; /* Limits for filename and path checks */ -static constexpr uint32_t MAX_PATH_SIZE = 100; -static constexpr uint32_t MAX_FILENAME_SIZE = 50; +static constexpr uint32_t MAX_PATH_SIZE = 200; +static constexpr uint32_t MAX_FILENAME_SIZE = 100; static constexpr uint32_t SA_DEPL_INIT_BUFFER_SECS = 120; // Burn time for autonomous deployment @@ -58,7 +58,9 @@ static constexpr uint32_t CFDP_STORE_QUEUE_SIZE = 300; static constexpr uint32_t MAX_PUS_FUNNEL_QUEUE_DEPTH = 100; static constexpr uint32_t MAX_CFDP_FUNNEL_QUEUE_DEPTH = 80; +static constexpr uint32_t VERIFICATION_SERVICE_QUEUE_DEPTH = 120; static constexpr uint32_t HK_SERVICE_QUEUE_DEPTH = 60; +static constexpr uint32_t ACTION_SERVICE_QUEUE_DEPTH = 60; static constexpr uint32_t MAX_STORED_CMDS_UDP = 150; static constexpr uint32_t MAX_STORED_CMDS_TCP = 180; diff --git a/dummies/AcuDummy.cpp b/dummies/AcuDummy.cpp index 7c18f6bf..c9844eb1 100644 --- a/dummies/AcuDummy.cpp +++ b/dummies/AcuDummy.cpp @@ -2,8 +2,11 @@ #include -AcuDummy::AcuDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie) - : DeviceHandlerBase(objectId, comif, comCookie) {} +AcuDummy::AcuDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie, bool enableHkSets) + : DeviceHandlerBase(objectId, comif, comCookie), + coreHk(this), + auxHk(this), + enableHkSets(enableHkSets) {} AcuDummy::~AcuDummy() {} @@ -37,7 +40,49 @@ uint32_t AcuDummy::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return ReturnValue_t AcuDummy::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) { + using namespace ACU; + localDataPoolMap.emplace(pool::ACU_CURRENT_IN_CHANNELS, new PoolEntry(6)); + localDataPoolMap.emplace(pool::ACU_VOLTAGE_IN_CHANNELS, new PoolEntry(6)); + + localDataPoolMap.emplace(pool::ACU_VCC, new PoolEntry({0})); + localDataPoolMap.emplace(pool::ACU_VBAT, new PoolEntry({0})); + localDataPoolMap.emplace(ACU::pool::ACU_TEMPERATURES, new PoolEntry({10.0, 10.0, 10.0}, true)); + + localDataPoolMap.emplace(pool::ACU_MPPT_MODE, new PoolEntry({0})); + + localDataPoolMap.emplace(pool::ACU_VBOOST_IN_CHANNELS, new PoolEntry(6)); + localDataPoolMap.emplace(pool::ACU_POWER_IN_CHANNELS, new PoolEntry(6)); + + localDataPoolMap.emplace(pool::ACU_DAC_ENABLES, new PoolEntry(3)); + localDataPoolMap.emplace(pool::ACU_DAC_RAW_CHANNELS, new PoolEntry(6)); + + localDataPoolMap.emplace(pool::ACU_BOOTCAUSE, new PoolEntry({0})); + localDataPoolMap.emplace(pool::ACU_BOOTCNT, new PoolEntry({0})); + localDataPoolMap.emplace(pool::ACU_UPTIME, new PoolEntry({0})); + localDataPoolMap.emplace(pool::ACU_RESET_CAUSE, new PoolEntry({0})); + localDataPoolMap.emplace(pool::ACU_MPPT_TIME, new PoolEntry({0})); + localDataPoolMap.emplace(pool::ACU_MPPT_PERIOD, new PoolEntry({0})); + + localDataPoolMap.emplace(pool::ACU_DEVICES, new PoolEntry(8)); + localDataPoolMap.emplace(pool::ACU_DEVICES_STATUS, new PoolEntry(8)); + + localDataPoolMap.emplace(pool::ACU_WDT_CNT_GND, new PoolEntry({0})); + localDataPoolMap.emplace(pool::ACU_WDT_GND_LEFT, new PoolEntry({0})); + + poolManager.subscribeForDiagPeriodicPacket( + subdp::DiagnosticsHkPeriodicParams(coreHk.getSid(), enableHkSets, 30.0)); + poolManager.subscribeForRegularPeriodicPacket( + subdp::RegularHkPeriodicParams(auxHk.getSid(), enableHkSets, 6000.0)); return returnvalue::OK; } + +LocalPoolDataSetBase *AcuDummy::getDataSetHandle(sid_t sid) { + if (sid == coreHk.getSid()) { + return &coreHk; + } else if (sid == auxHk.getSid()) { + return &auxHk; + } + return nullptr; +} diff --git a/dummies/AcuDummy.h b/dummies/AcuDummy.h index d5527222..8d855281 100644 --- a/dummies/AcuDummy.h +++ b/dummies/AcuDummy.h @@ -2,6 +2,7 @@ #define DUMMIES_ACUDUMMY_H_ #include +#include class AcuDummy : public DeviceHandlerBase { public: @@ -11,10 +12,14 @@ class AcuDummy : public DeviceHandlerBase { static const uint8_t SIMPLE_COMMAND_DATA = 1; static const uint8_t PERIODIC_REPLY_DATA = 2; - AcuDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie); + AcuDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie, bool enableHkSets); virtual ~AcuDummy(); protected: + ACU::CoreHk coreHk; + ACU::AuxHk auxHk; + bool enableHkSets; + void doStartUp() override; void doShutDown() override; ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override; @@ -28,6 +33,7 @@ class AcuDummy : public DeviceHandlerBase { uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override; ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) override; + LocalPoolDataSetBase *getDataSetHandle(sid_t sid) override; }; #endif /* DUMMIES_ACUDUMMY_H_ */ diff --git a/dummies/ImtqDummy.cpp b/dummies/ImtqDummy.cpp index b2f61bb3..0c8f9076 100644 --- a/dummies/ImtqDummy.cpp +++ b/dummies/ImtqDummy.cpp @@ -2,8 +2,13 @@ #include -ImtqDummy::ImtqDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie) - : DeviceHandlerBase(objectId, comif, comCookie) {} +ImtqDummy::ImtqDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie, + power::Switch_t pwrSwitcher, bool enableHkSets) + : DeviceHandlerBase(objectId, comif, comCookie), + setNoTorque(this), + setWithTorque(this), + enableHkSets(enableHkSets), + switcher(pwrSwitcher) {} ImtqDummy::~ImtqDummy() = default; @@ -11,6 +16,15 @@ void ImtqDummy::doStartUp() { setMode(MODE_NORMAL); } void ImtqDummy::doShutDown() { setMode(_MODE_POWER_DOWN); } +ReturnValue_t ImtqDummy::getSwitches(const uint8_t **switches, uint8_t *numberOfSwitches) { + if (switcher != power::NO_SWITCH) { + *numberOfSwitches = 1; + *switches = &switcher; + return returnvalue::OK; + } + return DeviceHandlerBase::NO_SWITCH; +} + ReturnValue_t ImtqDummy::buildNormalDeviceCommand(DeviceCommandId_t *id) { return NOTHING_TO_SEND; } ReturnValue_t ImtqDummy::buildTransitionDeviceCommand(DeviceCommandId_t *id) { @@ -45,5 +59,37 @@ ReturnValue_t ImtqDummy::initializeLocalDataPool(localpool::DataPool &localDataP localDataPoolMap.emplace(imtq::ACTUATION_RAW_STATUS, new PoolEntry({0})); localDataPoolMap.emplace(imtq::DIPOLES_ID, new PoolEntry({0, 0, 0})); localDataPoolMap.emplace(imtq::CURRENT_TORQUE_DURATION, new PoolEntry({0})); + + // ENG HK No Torque + localDataPoolMap.emplace(imtq::DIGITAL_VOLTAGE_MV, new PoolEntry({0})); + localDataPoolMap.emplace(imtq::ANALOG_VOLTAGE_MV, new PoolEntry({0})); + localDataPoolMap.emplace(imtq::DIGITAL_CURRENT, new PoolEntry({0})); + localDataPoolMap.emplace(imtq::ANALOG_CURRENT, new PoolEntry({0})); + localDataPoolMap.emplace(imtq::COIL_CURRENTS, &coilCurrentsMilliampsNoTorque); + localDataPoolMap.emplace(imtq::COIL_TEMPERATURES, &coilTempsNoTorque); + localDataPoolMap.emplace(imtq::MCU_TEMPERATURE, new PoolEntry({0})); + + // ENG HK With Torque + localDataPoolMap.emplace(imtq::DIGITAL_VOLTAGE_MV_WT, new PoolEntry({0})); + localDataPoolMap.emplace(imtq::ANALOG_VOLTAGE_MV_WT, new PoolEntry({0})); + localDataPoolMap.emplace(imtq::DIGITAL_CURRENT_WT, new PoolEntry({0})); + localDataPoolMap.emplace(imtq::ANALOG_CURRENT_WT, new PoolEntry({0})); + localDataPoolMap.emplace(imtq::COIL_CURRENTS_WT, &coilCurrentsMilliampsWithTorque); + localDataPoolMap.emplace(imtq::COIL_TEMPERATURES_WT, &coilTempsWithTorque); + localDataPoolMap.emplace(imtq::MCU_TEMPERATURE_WT, new PoolEntry({0})); + + poolManager.subscribeForDiagPeriodicPacket( + subdp::DiagnosticsHkPeriodicParams(setNoTorque.getSid(), enableHkSets, 30.0)); + poolManager.subscribeForDiagPeriodicPacket( + subdp::DiagnosticsHkPeriodicParams(setWithTorque.getSid(), enableHkSets, 30.0)); return DeviceHandlerBase::initializeLocalDataPool(localDataPoolMap, poolManager); } + +LocalPoolDataSetBase *ImtqDummy::getDataSetHandle(sid_t sid) { + if (sid == setNoTorque.getSid()) { + return &setNoTorque; + } else if (sid == setWithTorque.getSid()) { + return &setWithTorque; + } + return nullptr; +} diff --git a/dummies/ImtqDummy.h b/dummies/ImtqDummy.h index 0cfdf518..990df6e0 100644 --- a/dummies/ImtqDummy.h +++ b/dummies/ImtqDummy.h @@ -3,6 +3,8 @@ #include +#include "mission/acs/imtqHelpers.h" + class ImtqDummy : public DeviceHandlerBase { public: static const DeviceCommandId_t SIMPLE_COMMAND = 1; @@ -11,10 +13,35 @@ class ImtqDummy : public DeviceHandlerBase { static const uint8_t SIMPLE_COMMAND_DATA = 1; static const uint8_t PERIODIC_REPLY_DATA = 2; - ImtqDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie); + ImtqDummy(object_id_t objectId, object_id_t comif, CookieIF *comCookie, + power::Switch_t pwrSwitcher, bool enableHkSets); ~ImtqDummy() override; protected: + ReturnValue_t getSwitches(const uint8_t **switches, uint8_t *numberOfSwitches) override; + imtq::HkDatasetNoTorque setNoTorque; + imtq::HkDatasetWithTorque setWithTorque; + bool enableHkSets; + + PoolEntry statusMode = PoolEntry({0}); + PoolEntry statusError = PoolEntry({0}); + PoolEntry statusConfig = PoolEntry({0}); + PoolEntry statusUptime = PoolEntry({0}); + + PoolEntry mgmCalEntry = PoolEntry(3); + PoolEntry dipolesPoolEntry = PoolEntry({0, 0, 0}, false); + PoolEntry torqueDurationEntry = PoolEntry({0}, false); + PoolEntry coilCurrentsMilliampsNoTorque = PoolEntry(3); + PoolEntry coilCurrentsMilliampsWithTorque = PoolEntry(3); + PoolEntry coilTempsNoTorque = PoolEntry(3); + PoolEntry coilTempsWithTorque = PoolEntry(3); + PoolEntry mtmRawNoTorque = PoolEntry(3); + PoolEntry actStatusNoTorque = PoolEntry(1); + PoolEntry mtmRawWithTorque = PoolEntry(3); + PoolEntry actStatusWithTorque = PoolEntry(1); + + power::Switch_t switcher = power::NO_SWITCH; + void doStartUp() override; void doShutDown() override; ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t *id) override; @@ -28,6 +55,7 @@ class ImtqDummy : public DeviceHandlerBase { uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override; ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap, LocalDataPoolManager &poolManager) override; + LocalPoolDataSetBase *getDataSetHandle(sid_t sid) override; }; #endif /* DUMMIES_IMTQDUMMY_H_ */ diff --git a/dummies/helperFactory.cpp b/dummies/helperFactory.cpp index d7fdafbd..157d11d3 100644 --- a/dummies/helperFactory.cpp +++ b/dummies/helperFactory.cpp @@ -42,7 +42,8 @@ #include "mission/system/tree/payloadModeTree.h" #include "mission/tcs/defs.h" -void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpioIF) { +void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpioIF, + bool enableHkSets) { new ComIFDummy(objects::DUMMY_COM_IF); auto* comCookieDummy = new ComCookieDummy(); if (cfg.addBpxBattDummy) { @@ -74,13 +75,15 @@ void dummy::createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitcher, GpioIF* gpio } auto* imtqAssy = new ImtqAssembly(objects::IMTQ_ASSY); imtqAssy->connectModeTreeParent(satsystem::acs::ACS_SUBSYSTEM); - auto* imtqDummy = new ImtqDummy(objects::IMTQ_HANDLER, objects::DUMMY_COM_IF, comCookieDummy); + auto* imtqDummy = new ImtqDummy(objects::IMTQ_HANDLER, objects::DUMMY_COM_IF, comCookieDummy, + power::Switches::PDU1_CH3_MGT_5V, enableHkSets); imtqDummy->enableThermalModule(ThermalStateCfg()); + imtqDummy->setPowerSwitcher(&pwrSwitcher); imtqDummy->connectModeTreeParent(*imtqAssy); if (cfg.addOnlyAcuDummy) { - new AcuDummy(objects::ACU_HANDLER, objects::DUMMY_COM_IF, comCookieDummy); + new AcuDummy(objects::ACU_HANDLER, objects::DUMMY_COM_IF, comCookieDummy, enableHkSets); } else if (cfg.addPowerDummies) { - new AcuDummy(objects::ACU_HANDLER, objects::DUMMY_COM_IF, comCookieDummy); + new AcuDummy(objects::ACU_HANDLER, objects::DUMMY_COM_IF, comCookieDummy, enableHkSets); new PduDummy(objects::PDU1_HANDLER, objects::DUMMY_COM_IF, comCookieDummy); new PduDummy(objects::PDU2_HANDLER, objects::DUMMY_COM_IF, comCookieDummy); new P60DockDummy(objects::P60DOCK_HANDLER, objects::DUMMY_COM_IF, comCookieDummy); diff --git a/dummies/helperFactory.h b/dummies/helperFactory.h index e3809404..bab9d8d8 100644 --- a/dummies/helperFactory.h +++ b/dummies/helperFactory.h @@ -19,9 +19,9 @@ struct DummyCfg { bool addTempSensorDummies = true; bool addRtdComIFDummy = true; bool addPlocDummies = true; - bool addCamSwitcherDummy = true; + bool addCamSwitcherDummy = false; }; -void createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitch, GpioIF* gpioIF); +void createDummies(DummyCfg cfg, PowerSwitchIF& pwrSwitch, GpioIF* gpioIF, bool enableHkSets); } // namespace dummy diff --git a/fsfw b/fsfw index 5eb9ee8b..5322de05 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 5eb9ee8bc1e6f8640cbea46febd11e4b92241881 +Subproject commit 5322de059916efcf874b10ccc766b46e53d2470b diff --git a/generators/bsp_hosted_events.csv b/generators/bsp_hosted_events.csv index 2d5f5693..9dc26e07 100644 --- a/generators/bsp_hosted_events.csv +++ b/generators/bsp_hosted_events.csv @@ -177,20 +177,24 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path 12515;0x30e3;STR_HELPER_FILE_NOT_EXISTS;LOW;Specified file does not exist P1: Internal state of str helper;linux/acs/StrComHandler.h 12516;0x30e4;STR_HELPER_SENDING_PACKET_FAILED;LOW;No description;linux/acs/StrComHandler.h 12517;0x30e5;STR_HELPER_REQUESTING_MSG_FAILED;LOW;No description;linux/acs/StrComHandler.h -12600;0x3138;MPSOC_FLASH_WRITE_FAILED;LOW;Flash write fails;linux/payload/PlocMpsocHelper.h -12601;0x3139;MPSOC_FLASH_WRITE_SUCCESSFUL;LOW;Flash write successful;linux/payload/PlocMpsocHelper.h -12602;0x313a;MPSOC_SENDING_COMMAND_FAILED;LOW;No description;linux/payload/PlocMpsocHelper.h -12603;0x313b;MPSOC_HELPER_REQUESTING_REPLY_FAILED;LOW;Request receive message of communication interface failed P1: Return value returned by the communication interface requestReceiveMessage function P2: Internal state of MPSoC helper;linux/payload/PlocMpsocHelper.h -12604;0x313c;MPSOC_HELPER_READING_REPLY_FAILED;LOW;Reading receive message of communication interface failed P1: Return value returned by the communication interface readingReceivedMessage function P2: Internal state of MPSoC helper;linux/payload/PlocMpsocHelper.h -12605;0x313d;MPSOC_MISSING_ACK;LOW;Did not receive acknowledgment report P1: Number of bytes missing P2: Internal state of MPSoC helper;linux/payload/PlocMpsocHelper.h -12606;0x313e;MPSOC_MISSING_EXE;LOW;Did not receive execution report P1: Number of bytes missing P2: Internal state of MPSoC helper;linux/payload/PlocMpsocHelper.h -12607;0x313f;MPSOC_ACK_FAILURE_REPORT;LOW;Received acknowledgment failure report P1: Internal state of MPSoC;linux/payload/PlocMpsocHelper.h -12608;0x3140;MPSOC_EXE_FAILURE_REPORT;LOW;Received execution failure report P1: Internal state of MPSoC;linux/payload/PlocMpsocHelper.h -12609;0x3141;MPSOC_ACK_INVALID_APID;LOW;Expected acknowledgment report but received space packet with other apid P1: Apid of received space packet P2: Internal state of MPSoC;linux/payload/PlocMpsocHelper.h -12610;0x3142;MPSOC_EXE_INVALID_APID;LOW;Expected execution report but received space packet with other apid P1: Apid of received space packet P2: Internal state of MPSoC;linux/payload/PlocMpsocHelper.h -12611;0x3143;MPSOC_HELPER_SEQ_CNT_MISMATCH;LOW;Received sequence count does not match expected sequence count P1: Expected sequence count P2: Received sequence count;linux/payload/PlocMpsocHelper.h -12612;0x3144;MPSOC_TM_SIZE_ERROR;LOW;No description;linux/payload/PlocMpsocHelper.h -12613;0x3145;MPSOC_TM_CRC_MISSMATCH;LOW;No description;linux/payload/PlocMpsocHelper.h +12600;0x3138;MPSOC_FLASH_WRITE_FAILED;LOW;Flash write fails;linux/payload/PlocMpsocSpecialComHelper.h +12601;0x3139;MPSOC_FLASH_WRITE_SUCCESSFUL;INFO;Flash write successful;linux/payload/PlocMpsocSpecialComHelper.h +12602;0x313a;MPSOC_SENDING_COMMAND_FAILED;LOW;No description;linux/payload/PlocMpsocSpecialComHelper.h +12603;0x313b;MPSOC_HELPER_REQUESTING_REPLY_FAILED;LOW;Request receive message of communication interface failed P1: Return value returned by the communication interface requestReceiveMessage function P2: Internal state of MPSoC helper;linux/payload/PlocMpsocSpecialComHelper.h +12604;0x313c;MPSOC_HELPER_READING_REPLY_FAILED;LOW;Reading receive message of communication interface failed P1: Return value returned by the communication interface readingReceivedMessage function P2: Internal state of MPSoC helper;linux/payload/PlocMpsocSpecialComHelper.h +12605;0x313d;MPSOC_MISSING_ACK;LOW;Did not receive acknowledgment report P1: Number of bytes missing P2: Internal state of MPSoC helper;linux/payload/PlocMpsocSpecialComHelper.h +12606;0x313e;MPSOC_MISSING_EXE;LOW;Did not receive execution report P1: Number of bytes missing P2: Internal state of MPSoC helper;linux/payload/PlocMpsocSpecialComHelper.h +12607;0x313f;MPSOC_ACK_FAILURE_REPORT;LOW;Received acknowledgment failure report P1: Internal state of MPSoC;linux/payload/PlocMpsocSpecialComHelper.h +12608;0x3140;MPSOC_EXE_FAILURE_REPORT;LOW;Received execution failure report P1: Internal state of MPSoC;linux/payload/PlocMpsocSpecialComHelper.h +12609;0x3141;MPSOC_ACK_INVALID_APID;LOW;Expected acknowledgment report but received space packet with other apid P1: Apid of received space packet P2: Internal state of MPSoC;linux/payload/PlocMpsocSpecialComHelper.h +12610;0x3142;MPSOC_EXE_INVALID_APID;LOW;Expected execution report but received space packet with other apid P1: Apid of received space packet P2: Internal state of MPSoC;linux/payload/PlocMpsocSpecialComHelper.h +12611;0x3143;MPSOC_HELPER_SEQ_CNT_MISMATCH;LOW;Received sequence count does not match expected sequence count P1: Expected sequence count P2: Received sequence count;linux/payload/PlocMpsocSpecialComHelper.h +12612;0x3144;MPSOC_TM_SIZE_ERROR;LOW;No description;linux/payload/PlocMpsocSpecialComHelper.h +12613;0x3145;MPSOC_TM_CRC_MISSMATCH;LOW;No description;linux/payload/PlocMpsocSpecialComHelper.h +12614;0x3146;MPSOC_FLASH_READ_PACKET_ERROR;LOW;No description;linux/payload/PlocMpsocSpecialComHelper.h +12615;0x3147;MPSOC_FLASH_READ_FAILED;LOW;No description;linux/payload/PlocMpsocSpecialComHelper.h +12616;0x3148;MPSOC_FLASH_READ_SUCCESSFUL;INFO;No description;linux/payload/PlocMpsocSpecialComHelper.h +12617;0x3149;MPSOC_READ_TIMEOUT;LOW;No description;linux/payload/PlocMpsocSpecialComHelper.h 12700;0x319c;TRANSITION_BACK_TO_OFF;MEDIUM;Could not transition properly and went back to ALL OFF;mission/payload/PayloadPcduHandler.h 12701;0x319d;NEG_V_OUT_OF_BOUNDS;MEDIUM;P1: 0 -> too low, 1 -> too high P2: Float value;mission/payload/PayloadPcduHandler.h 12702;0x319e;U_DRO_OUT_OF_BOUNDS;MEDIUM;P1: 0 -> too low, 1 -> too high P2: Float value;mission/payload/PayloadPcduHandler.h @@ -274,7 +278,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path 14105;0x3719;CAMERA_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h 14106;0x371a;PCDU_SYSTEM_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h 14107;0x371b;HEATER_NOT_OFF_FOR_OFF_MODE;MEDIUM;No description;mission/controller/tcsDefs.h -14108;0x371c;MGT_OVERHEATING;MEDIUM;No description;mission/controller/tcsDefs.h +14108;0x371c;MGT_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h 14201;0x3779;TX_TIMER_EXPIRED;INFO;The transmit timer to protect the Syrlinks expired P1: The current timer value;mission/system/com/ComSubsystem.h 14202;0x377a;BIT_LOCK_TX_ON;INFO;Transmitter will be turned on due to detection of bitlock;mission/system/com/ComSubsystem.h 14300;0x37dc;POSSIBLE_FILE_CORRUPTION;LOW;P1: Result code of TM packet parser. P2: Timestamp of possibly corrupt file as a unix timestamp.;mission/persistentTmStoreDefs.h diff --git a/generators/bsp_q7s_events.csv b/generators/bsp_q7s_events.csv index 2d5f5693..9dc26e07 100644 --- a/generators/bsp_q7s_events.csv +++ b/generators/bsp_q7s_events.csv @@ -177,20 +177,24 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path 12515;0x30e3;STR_HELPER_FILE_NOT_EXISTS;LOW;Specified file does not exist P1: Internal state of str helper;linux/acs/StrComHandler.h 12516;0x30e4;STR_HELPER_SENDING_PACKET_FAILED;LOW;No description;linux/acs/StrComHandler.h 12517;0x30e5;STR_HELPER_REQUESTING_MSG_FAILED;LOW;No description;linux/acs/StrComHandler.h -12600;0x3138;MPSOC_FLASH_WRITE_FAILED;LOW;Flash write fails;linux/payload/PlocMpsocHelper.h -12601;0x3139;MPSOC_FLASH_WRITE_SUCCESSFUL;LOW;Flash write successful;linux/payload/PlocMpsocHelper.h -12602;0x313a;MPSOC_SENDING_COMMAND_FAILED;LOW;No description;linux/payload/PlocMpsocHelper.h -12603;0x313b;MPSOC_HELPER_REQUESTING_REPLY_FAILED;LOW;Request receive message of communication interface failed P1: Return value returned by the communication interface requestReceiveMessage function P2: Internal state of MPSoC helper;linux/payload/PlocMpsocHelper.h -12604;0x313c;MPSOC_HELPER_READING_REPLY_FAILED;LOW;Reading receive message of communication interface failed P1: Return value returned by the communication interface readingReceivedMessage function P2: Internal state of MPSoC helper;linux/payload/PlocMpsocHelper.h -12605;0x313d;MPSOC_MISSING_ACK;LOW;Did not receive acknowledgment report P1: Number of bytes missing P2: Internal state of MPSoC helper;linux/payload/PlocMpsocHelper.h -12606;0x313e;MPSOC_MISSING_EXE;LOW;Did not receive execution report P1: Number of bytes missing P2: Internal state of MPSoC helper;linux/payload/PlocMpsocHelper.h -12607;0x313f;MPSOC_ACK_FAILURE_REPORT;LOW;Received acknowledgment failure report P1: Internal state of MPSoC;linux/payload/PlocMpsocHelper.h -12608;0x3140;MPSOC_EXE_FAILURE_REPORT;LOW;Received execution failure report P1: Internal state of MPSoC;linux/payload/PlocMpsocHelper.h -12609;0x3141;MPSOC_ACK_INVALID_APID;LOW;Expected acknowledgment report but received space packet with other apid P1: Apid of received space packet P2: Internal state of MPSoC;linux/payload/PlocMpsocHelper.h -12610;0x3142;MPSOC_EXE_INVALID_APID;LOW;Expected execution report but received space packet with other apid P1: Apid of received space packet P2: Internal state of MPSoC;linux/payload/PlocMpsocHelper.h -12611;0x3143;MPSOC_HELPER_SEQ_CNT_MISMATCH;LOW;Received sequence count does not match expected sequence count P1: Expected sequence count P2: Received sequence count;linux/payload/PlocMpsocHelper.h -12612;0x3144;MPSOC_TM_SIZE_ERROR;LOW;No description;linux/payload/PlocMpsocHelper.h -12613;0x3145;MPSOC_TM_CRC_MISSMATCH;LOW;No description;linux/payload/PlocMpsocHelper.h +12600;0x3138;MPSOC_FLASH_WRITE_FAILED;LOW;Flash write fails;linux/payload/PlocMpsocSpecialComHelper.h +12601;0x3139;MPSOC_FLASH_WRITE_SUCCESSFUL;INFO;Flash write successful;linux/payload/PlocMpsocSpecialComHelper.h +12602;0x313a;MPSOC_SENDING_COMMAND_FAILED;LOW;No description;linux/payload/PlocMpsocSpecialComHelper.h +12603;0x313b;MPSOC_HELPER_REQUESTING_REPLY_FAILED;LOW;Request receive message of communication interface failed P1: Return value returned by the communication interface requestReceiveMessage function P2: Internal state of MPSoC helper;linux/payload/PlocMpsocSpecialComHelper.h +12604;0x313c;MPSOC_HELPER_READING_REPLY_FAILED;LOW;Reading receive message of communication interface failed P1: Return value returned by the communication interface readingReceivedMessage function P2: Internal state of MPSoC helper;linux/payload/PlocMpsocSpecialComHelper.h +12605;0x313d;MPSOC_MISSING_ACK;LOW;Did not receive acknowledgment report P1: Number of bytes missing P2: Internal state of MPSoC helper;linux/payload/PlocMpsocSpecialComHelper.h +12606;0x313e;MPSOC_MISSING_EXE;LOW;Did not receive execution report P1: Number of bytes missing P2: Internal state of MPSoC helper;linux/payload/PlocMpsocSpecialComHelper.h +12607;0x313f;MPSOC_ACK_FAILURE_REPORT;LOW;Received acknowledgment failure report P1: Internal state of MPSoC;linux/payload/PlocMpsocSpecialComHelper.h +12608;0x3140;MPSOC_EXE_FAILURE_REPORT;LOW;Received execution failure report P1: Internal state of MPSoC;linux/payload/PlocMpsocSpecialComHelper.h +12609;0x3141;MPSOC_ACK_INVALID_APID;LOW;Expected acknowledgment report but received space packet with other apid P1: Apid of received space packet P2: Internal state of MPSoC;linux/payload/PlocMpsocSpecialComHelper.h +12610;0x3142;MPSOC_EXE_INVALID_APID;LOW;Expected execution report but received space packet with other apid P1: Apid of received space packet P2: Internal state of MPSoC;linux/payload/PlocMpsocSpecialComHelper.h +12611;0x3143;MPSOC_HELPER_SEQ_CNT_MISMATCH;LOW;Received sequence count does not match expected sequence count P1: Expected sequence count P2: Received sequence count;linux/payload/PlocMpsocSpecialComHelper.h +12612;0x3144;MPSOC_TM_SIZE_ERROR;LOW;No description;linux/payload/PlocMpsocSpecialComHelper.h +12613;0x3145;MPSOC_TM_CRC_MISSMATCH;LOW;No description;linux/payload/PlocMpsocSpecialComHelper.h +12614;0x3146;MPSOC_FLASH_READ_PACKET_ERROR;LOW;No description;linux/payload/PlocMpsocSpecialComHelper.h +12615;0x3147;MPSOC_FLASH_READ_FAILED;LOW;No description;linux/payload/PlocMpsocSpecialComHelper.h +12616;0x3148;MPSOC_FLASH_READ_SUCCESSFUL;INFO;No description;linux/payload/PlocMpsocSpecialComHelper.h +12617;0x3149;MPSOC_READ_TIMEOUT;LOW;No description;linux/payload/PlocMpsocSpecialComHelper.h 12700;0x319c;TRANSITION_BACK_TO_OFF;MEDIUM;Could not transition properly and went back to ALL OFF;mission/payload/PayloadPcduHandler.h 12701;0x319d;NEG_V_OUT_OF_BOUNDS;MEDIUM;P1: 0 -> too low, 1 -> too high P2: Float value;mission/payload/PayloadPcduHandler.h 12702;0x319e;U_DRO_OUT_OF_BOUNDS;MEDIUM;P1: 0 -> too low, 1 -> too high P2: Float value;mission/payload/PayloadPcduHandler.h @@ -274,7 +278,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path 14105;0x3719;CAMERA_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h 14106;0x371a;PCDU_SYSTEM_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h 14107;0x371b;HEATER_NOT_OFF_FOR_OFF_MODE;MEDIUM;No description;mission/controller/tcsDefs.h -14108;0x371c;MGT_OVERHEATING;MEDIUM;No description;mission/controller/tcsDefs.h +14108;0x371c;MGT_OVERHEATING;HIGH;No description;mission/controller/tcsDefs.h 14201;0x3779;TX_TIMER_EXPIRED;INFO;The transmit timer to protect the Syrlinks expired P1: The current timer value;mission/system/com/ComSubsystem.h 14202;0x377a;BIT_LOCK_TX_ON;INFO;Transmitter will be turned on due to detection of bitlock;mission/system/com/ComSubsystem.h 14300;0x37dc;POSSIBLE_FILE_CORRUPTION;LOW;P1: Result code of TM packet parser. P2: Timestamp of possibly corrupt file as a unix timestamp.;mission/persistentTmStoreDefs.h diff --git a/generators/bsp_q7s_returnvalues.csv b/generators/bsp_q7s_returnvalues.csv index 20b76df6..1bc91860 100644 --- a/generators/bsp_q7s_returnvalues.csv +++ b/generators/bsp_q7s_returnvalues.csv @@ -478,8 +478,8 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path 0x53b6;STRH_StartrackerAlreadyBooted;Star tracker is already in firmware mode;182;STR_HANDLER;mission/acs/str/StarTrackerHandler.h 0x53b7;STRH_StartrackerNotRunningFirmware;Star tracker must be in firmware mode to run this command;183;STR_HANDLER;mission/acs/str/StarTrackerHandler.h 0x53b8;STRH_StartrackerNotRunningBootloader;Star tracker must be in bootloader mode to run this command;184;STR_HANDLER;mission/acs/str/StarTrackerHandler.h -0x54e0;DWLPWRON_InvalidMode;Received command has invalid JESD mode (valid modes are 0 - 5);224;DWLPWRON_CMD;linux/payload/plocMpscoDefs.h -0x54e1;DWLPWRON_InvalidLaneRate;Received command has invalid lane rate (valid lane rate are 0 - 9);225;DWLPWRON_CMD;linux/payload/plocMpscoDefs.h +0x54e0;DWLPWRON_InvalidMode;Received command has invalid JESD mode (valid modes are 0 - 5);224;DWLPWRON_CMD;linux/payload/plocMpsocHelpers.h +0x54e1;DWLPWRON_InvalidLaneRate;Received command has invalid lane rate (valid lane rate are 0 - 9);225;DWLPWRON_CMD;linux/payload/plocMpsocHelpers.h 0x5700;PLSPVhLP_RequestDone;No description;0;PLOC_SUPV_HELPER;linux/payload/PlocSupvUartMan.h 0x5701;PLSPVhLP_NoPacketFound;No description;1;PLOC_SUPV_HELPER;linux/payload/PlocSupvUartMan.h 0x5702;PLSPVhLP_DecodeBufTooSmall;No description;2;PLOC_SUPV_HELPER;linux/payload/PlocSupvUartMan.h @@ -543,7 +543,8 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path 0x63a0;NVMB_KeyNotExists;Specified key does not exist in json file;160;NVM_PARAM_BASE;mission/memory/NvmParameterBase.h 0x64a0;FSHLP_SdNotMounted;SD card specified with path string not mounted;160;FILE_SYSTEM_HELPER;bsp_q7s/fs/FilesystemHelper.h 0x64a1;FSHLP_FileNotExists;Specified file does not exist on filesystem;161;FILE_SYSTEM_HELPER;bsp_q7s/fs/FilesystemHelper.h -0x65a0;PLMPHLP_FileClosedAccidentally;File accidentally close;160;PLOC_MPSOC_HELPER;linux/payload/PlocMpsocHelper.h +0x65a0;PLMPHLP_FileWriteError;File error occured for file transfers from OBC to the MPSoC.;160;PLOC_MPSOC_HELPER;linux/payload/PlocMpsocSpecialComHelper.h +0x65a1;PLMPHLP_FileReadError;File error occured for file transfers from MPSoC to OBC.;161;PLOC_MPSOC_HELPER;linux/payload/PlocMpsocSpecialComHelper.h 0x66a0;SADPL_CommandNotSupported;No description;160;SA_DEPL_HANDLER;mission/SolarArrayDeploymentHandler.h 0x66a1;SADPL_DeploymentAlreadyExecuting;No description;161;SA_DEPL_HANDLER;mission/SolarArrayDeploymentHandler.h 0x66a2;SADPL_MainSwitchTimeoutFailure;No description;162;SA_DEPL_HANDLER;mission/SolarArrayDeploymentHandler.h diff --git a/generators/events/translateEvents.cpp b/generators/events/translateEvents.cpp index f7850a99..9a93fe4c 100644 --- a/generators/events/translateEvents.cpp +++ b/generators/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 291 translations. + * @brief Auto-generated event translation file. Contains 295 translations. * @details - * Generated on: 2023-04-17 11:34:19 + * Generated on: 2023-05-17 17:15:34 */ #include "translateEvents.h" @@ -197,6 +197,10 @@ const char *MPSOC_EXE_INVALID_APID_STRING = "MPSOC_EXE_INVALID_APID"; const char *MPSOC_HELPER_SEQ_CNT_MISMATCH_STRING = "MPSOC_HELPER_SEQ_CNT_MISMATCH"; const char *MPSOC_TM_SIZE_ERROR_STRING = "MPSOC_TM_SIZE_ERROR"; const char *MPSOC_TM_CRC_MISSMATCH_STRING = "MPSOC_TM_CRC_MISSMATCH"; +const char *MPSOC_FLASH_READ_PACKET_ERROR_STRING = "MPSOC_FLASH_READ_PACKET_ERROR"; +const char *MPSOC_FLASH_READ_FAILED_STRING = "MPSOC_FLASH_READ_FAILED"; +const char *MPSOC_FLASH_READ_SUCCESSFUL_STRING = "MPSOC_FLASH_READ_SUCCESSFUL"; +const char *MPSOC_READ_TIMEOUT_STRING = "MPSOC_READ_TIMEOUT"; const char *TRANSITION_BACK_TO_OFF_STRING = "TRANSITION_BACK_TO_OFF"; const char *NEG_V_OUT_OF_BOUNDS_STRING = "NEG_V_OUT_OF_BOUNDS"; const char *U_DRO_OUT_OF_BOUNDS_STRING = "U_DRO_OUT_OF_BOUNDS"; @@ -683,6 +687,14 @@ const char *translateEvents(Event event) { return MPSOC_TM_SIZE_ERROR_STRING; case (12613): return MPSOC_TM_CRC_MISSMATCH_STRING; + case (12614): + return MPSOC_FLASH_READ_PACKET_ERROR_STRING; + case (12615): + return MPSOC_FLASH_READ_FAILED_STRING; + case (12616): + return MPSOC_FLASH_READ_SUCCESSFUL_STRING; + case (12617): + return MPSOC_READ_TIMEOUT_STRING; case (12700): return TRANSITION_BACK_TO_OFF_STRING; case (12701): diff --git a/generators/objects/translateObjects.cpp b/generators/objects/translateObjects.cpp index 1c252ec5..eb2125b4 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-04-17 11:34:19 + * Generated on: 2023-05-17 17:15:34 */ #include "translateObjects.h" diff --git a/linux/acs/AcsBoardPolling.cpp b/linux/acs/AcsBoardPolling.cpp index e525bf53..1ba55357 100644 --- a/linux/acs/AcsBoardPolling.cpp +++ b/linux/acs/AcsBoardPolling.cpp @@ -113,6 +113,7 @@ ReturnValue_t AcsBoardPolling::sendMessage(CookieIF* cookie, const uint8_t* send if (req->mode != adis.mode) { if (req->mode == acs::SimpleSensorMode::NORMAL) { adis.type = req->type; + adis.decRate = req->cfg.decRateReg; // The initial countdown is handled by the device handler now. // adis.countdown.setTimeout(adis1650x::START_UP_TIME); if (adis.type == adis1650x::Type::ADIS16507) { @@ -376,6 +377,80 @@ void AcsBoardPolling::gyroL3gHandler(GyroL3g& l3g) { } } +ReturnValue_t AcsBoardPolling::writeAdisReg(SpiCookie& cookie) { + ReturnValue_t result = returnvalue::OK; + int retval = 0; + // Prepare transfer + int fileDescriptor = 0; + std::string device = spiComIF.getSpiDev(); + UnixFileGuard fileHelper(device, fileDescriptor, O_RDWR, "SpiComIF::sendMessage"); + if (fileHelper.getOpenResult() != returnvalue::OK) { + return spi::OPENING_FILE_FAILED; + } + spi::SpiModes spiMode = spi::SpiModes::MODE_0; + uint32_t spiSpeed = 0; + cookie.getSpiParameters(spiMode, spiSpeed, nullptr); + spiComIF.setSpiSpeedAndMode(fileDescriptor, spiMode, spiSpeed); + cookie.assignWriteBuffer(cmdBuf.data()); + cookie.setTransferSize(2); + + gpioId_t gpioId = cookie.getChipSelectPin(); + MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING; + uint32_t timeoutMs = 0; + MutexIF* mutex = spiComIF.getCsMutex(); + cookie.getMutexParams(timeoutType, timeoutMs); + if (mutex == nullptr) { + sif::warning << "GyroADIS16507Handler::spiSendCallback: " + "Mutex or GPIO interface invalid" + << std::endl; + return returnvalue::FAILED; + } + + size_t idx = 0; + spi_ioc_transfer* transferStruct = cookie.getTransferStructHandle(); + uint64_t origTx = transferStruct->tx_buf; + uint64_t origRx = transferStruct->rx_buf; + for (idx = 0; idx < 4; idx += 2) { + result = mutex->lockMutex(timeoutType, timeoutMs); + if (result != returnvalue::OK) { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::error << "AcsBoardPolling: Failed to lock mutex" << std::endl; +#endif + return result; + } + // Pull SPI CS low. For now, no support for active high given + if (gpioId != gpio::NO_GPIO) { + gpioIF.pullLow(gpioId); + } + + // Execute transfer + // Initiate a full duplex SPI transfer. + retval = ioctl(fileDescriptor, SPI_IOC_MESSAGE(1), cookie.getTransferStructHandle()); + if (retval < 0) { + utility::handleIoctlError("SpiComIF::sendMessage: ioctl error."); + result = spi::FULL_DUPLEX_TRANSFER_FAILED; + } +#if FSFW_HAL_SPI_WIRETAPPING == 1 + comIf->performSpiWiretapping(cookie); +#endif /* FSFW_LINUX_SPI_WIRETAPPING == 1 */ + + if (gpioId != gpio::NO_GPIO) { + gpioIF.pullHigh(gpioId); + } + mutex->unlockMutex(); + + transferStruct->tx_buf += 2; + transferStruct->rx_buf += 2; + if (idx < 4) { + usleep(adis1650x::STALL_TIME_MICROSECONDS); + } + } + transferStruct->tx_buf = origTx; + transferStruct->rx_buf = origRx; + cookie.setTransferSize(0); + return returnvalue::OK; +} + ReturnValue_t AcsBoardPolling::readAdisCfg(SpiCookie& cookie, size_t transferLen) { ReturnValue_t result = returnvalue::OK; int retval = 0; @@ -455,15 +530,20 @@ void AcsBoardPolling::gyroAdisHandler(GyroAdis& gyro) { ReturnValue_t result; acs::SimpleSensorMode mode = acs::SimpleSensorMode::OFF; bool mustPerformStartup = false; + uint16_t decRate = 0; { MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX); mode = gyro.mode; + decRate = gyro.decRate; mustPerformStartup = gyro.performStartup; } if (mode == acs::SimpleSensorMode::OFF) { return; } if (mustPerformStartup) { + adis1650x::prepareWriteRegCommand(adis1650x::DEC_RATE_REG, decRate, cmdBuf.data(), + cmdBuf.size()); + writeAdisReg(*gyro.cookie); uint8_t regList[6]; // Read configuration regList[0] = adis1650x::DIAG_STAT_REG; @@ -491,13 +571,19 @@ void AcsBoardPolling::gyroAdisHandler(GyroAdis& gyro) { gyro.replyResult = returnvalue::FAILED; return; } + uint16_t decRateReadBack = (rawReply[10] << 8) | rawReply[11]; + if (decRateReadBack != decRate) { + sif::warning << "AcsPollingTask: DEC rate configuration failed. Read " << decRateReadBack + << ", expected " << decRate << std::endl; + gyro.replyResult = returnvalue::FAILED; + } MutexGuard mg(ipcLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX); gyro.ownReply.cfgWasSet = true; gyro.ownReply.cfg.diagStat = (rawReply[2] << 8) | rawReply[3]; gyro.ownReply.cfg.filterSetting = (rawReply[4] << 8) | rawReply[5]; gyro.ownReply.cfg.rangMdl = (rawReply[6] << 8) | rawReply[7]; gyro.ownReply.cfg.mscCtrlReg = (rawReply[8] << 8) | rawReply[9]; - gyro.ownReply.cfg.decRateReg = (rawReply[10] << 8) | rawReply[11]; + gyro.ownReply.cfg.decRateReg = decRateReadBack; gyro.ownReply.cfg.prodId = prodId; gyro.ownReply.data.sensitivity = adis1650x::rangMdlToSensitivity(gyro.ownReply.cfg.rangMdl); gyro.performStartup = false; diff --git a/linux/acs/AcsBoardPolling.h b/linux/acs/AcsBoardPolling.h index 794c9c47..5b4d0390 100644 --- a/linux/acs/AcsBoardPolling.h +++ b/linux/acs/AcsBoardPolling.h @@ -37,6 +37,7 @@ class AcsBoardPolling : public SystemObject, struct GyroAdis : public DevBase { adis1650x::Type type; + uint16_t decRate; Countdown countdown; acs::Adis1650XReply ownReply; acs::Adis1650XReply readerReply; @@ -84,6 +85,8 @@ class AcsBoardPolling : public SystemObject, void gyroAdisHandler(GyroAdis& gyro); void mgmLis3Handler(MgmLis3& mgm); void mgmRm3100Handler(MgmRm3100& mgm); + // This fumction configures the register as specified on p.21 of the datasheet. + ReturnValue_t writeAdisReg(SpiCookie& cookie); // Special readout: 16us stall time between small 2 byte transfers. ReturnValue_t readAdisCfg(SpiCookie& spiCookie, size_t transferLen); }; diff --git a/linux/fsfwconfig/events/translateEvents.cpp b/linux/fsfwconfig/events/translateEvents.cpp index f7850a99..9a93fe4c 100644 --- a/linux/fsfwconfig/events/translateEvents.cpp +++ b/linux/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 291 translations. + * @brief Auto-generated event translation file. Contains 295 translations. * @details - * Generated on: 2023-04-17 11:34:19 + * Generated on: 2023-05-17 17:15:34 */ #include "translateEvents.h" @@ -197,6 +197,10 @@ const char *MPSOC_EXE_INVALID_APID_STRING = "MPSOC_EXE_INVALID_APID"; const char *MPSOC_HELPER_SEQ_CNT_MISMATCH_STRING = "MPSOC_HELPER_SEQ_CNT_MISMATCH"; const char *MPSOC_TM_SIZE_ERROR_STRING = "MPSOC_TM_SIZE_ERROR"; const char *MPSOC_TM_CRC_MISSMATCH_STRING = "MPSOC_TM_CRC_MISSMATCH"; +const char *MPSOC_FLASH_READ_PACKET_ERROR_STRING = "MPSOC_FLASH_READ_PACKET_ERROR"; +const char *MPSOC_FLASH_READ_FAILED_STRING = "MPSOC_FLASH_READ_FAILED"; +const char *MPSOC_FLASH_READ_SUCCESSFUL_STRING = "MPSOC_FLASH_READ_SUCCESSFUL"; +const char *MPSOC_READ_TIMEOUT_STRING = "MPSOC_READ_TIMEOUT"; const char *TRANSITION_BACK_TO_OFF_STRING = "TRANSITION_BACK_TO_OFF"; const char *NEG_V_OUT_OF_BOUNDS_STRING = "NEG_V_OUT_OF_BOUNDS"; const char *U_DRO_OUT_OF_BOUNDS_STRING = "U_DRO_OUT_OF_BOUNDS"; @@ -683,6 +687,14 @@ const char *translateEvents(Event event) { return MPSOC_TM_SIZE_ERROR_STRING; case (12613): return MPSOC_TM_CRC_MISSMATCH_STRING; + case (12614): + return MPSOC_FLASH_READ_PACKET_ERROR_STRING; + case (12615): + return MPSOC_FLASH_READ_FAILED_STRING; + case (12616): + return MPSOC_FLASH_READ_SUCCESSFUL_STRING; + case (12617): + return MPSOC_READ_TIMEOUT_STRING; case (12700): return TRANSITION_BACK_TO_OFF_STRING; case (12701): diff --git a/linux/fsfwconfig/objects/translateObjects.cpp b/linux/fsfwconfig/objects/translateObjects.cpp index 1c252ec5..eb2125b4 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-04-17 11:34:19 + * Generated on: 2023-05-17 17:15:34 */ #include "translateObjects.h" diff --git a/linux/ipcore/PapbVcInterface.cpp b/linux/ipcore/PapbVcInterface.cpp index 60968cc6..404f3653 100644 --- a/linux/ipcore/PapbVcInterface.cpp +++ b/linux/ipcore/PapbVcInterface.cpp @@ -7,20 +7,16 @@ #include "fsfw/serviceinterface/ServiceInterface.h" -PapbVcInterface::PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbBusyId, - gpioId_t papbEmptyId, std::string uioFile, int mapNum) - : gpioComIF(gpioComIF), - papbBusyId(papbBusyId), - papbEmptyId(papbEmptyId), - uioFile(std::move(uioFile)), - mapNum(mapNum) {} +PapbVcInterface::PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbEmptyId, + std::string uioFile, int mapNum) + : gpioComIF(gpioComIF), papbEmptyId(papbEmptyId), uioFile(std::move(uioFile)), mapNum(mapNum) {} PapbVcInterface::~PapbVcInterface() {} ReturnValue_t PapbVcInterface::initialize() { UioMapper uioMapper(uioFile, mapNum); ReturnValue_t result = uioMapper.getMappedAdress(const_cast(&vcBaseReg), - UioMapper::Permissions::WRITE_ONLY); + UioMapper::Permissions::READ_WRITE); if (result != returnvalue::OK) { return result; } @@ -32,63 +28,16 @@ ReturnValue_t PapbVcInterface::write(const uint8_t* data, size_t size) { if (size < 4) { return returnvalue::FAILED; } - if (pollInterfaceReadiness(0, true) == returnvalue::OK) { + if (pollReadyForPacket()) { startPacketTransfer(ByteWidthCfg::ONE); } else { return DirectTmSinkIF::IS_BUSY; } - // TODO: This should work but does not.. :( - // size_t idx = 0; - // while (idx < size) { - // - // nanosleep(&BETWEEN_POLL_DELAY, &remDelay); - // if ((size - idx) < 4) { - // *vcBaseReg = CONFIG_DATA_INPUT | (size - idx - 1); - // usleep(1); - // } - // if (pollPapbBusySignal(2) == returnvalue::OK) { - // // vcBaseReg + DATA_REG_OFFSET + 3 = static_cast(data + idx); - // // vcBaseReg + DATA_REG_OFFSET + 2 = static_cast(data + idx + 1); - // // vcBaseReg + DATA_REG_OFFSET + 1 = static_cast(data + idx + 2); - // // vcBaseReg + DATA_REG_OFFSET = static_cast(data + idx + 3); - // - // // std::memcpy((vcBaseReg + DATA_REG_OFFSET), data + idx , nextWriteSize); - // *(vcBaseReg + DATA_REG_OFFSET) = *reinterpret_cast(data + idx); - // //uint8_t* byteReg = reinterpret_cast(vcBaseReg + DATA_REG_OFFSET); - // - // //byteReg[0] = data[idx]; - // //byteReg[1] = data[idx]; - // } else { - // abortPacketTransfer(); - // return returnvalue::FAILED; - // } - // // TODO: Change this after the bugfix. Right now, the PAPB ignores the content of the byte - // // width configuration.5 - // // It's okay to increment by a larger amount for the last segment here, loop will be over - // // in any case. - // idx += 4; - // } for (size_t idx = 0; idx < size; idx++) { - // This delay is super-important, DO NOT REMOVE! - // Polling the GPIO or the config register too often messes up the scheduler. - // TODO: Maybe this should not be done like this. It would be better if there was a custom - // FPGA module which can accept packets and then takes care of dumping that packet into - // the PTME. DMA would be an ideal solution for this. - nanosleep(&BETWEEN_POLL_DELAY, &remDelay); - if (pollInterfaceReadiness(2, false) == returnvalue::OK) { - *(vcBaseReg + DATA_REG_OFFSET) = static_cast(data[idx]); - } else { - abortPacketTransfer(); - return returnvalue::FAILED; - } - } - nanosleep(&BETWEEN_POLL_DELAY, &remDelay); - if (pollInterfaceReadiness(2, false) == returnvalue::OK) { - completePacketTransfer(); - } else { - abortPacketTransfer(); - return returnvalue::FAILED; + // if (pollInterfaceReadiness(2, false) == returnvalue::OK) { + *(vcBaseReg + DATA_REG_OFFSET) = static_cast(data[idx]); } + completePacketTransfer(); return returnvalue::OK; } @@ -98,60 +47,33 @@ void PapbVcInterface::startPacketTransfer(ByteWidthCfg initWidth) { void PapbVcInterface::completePacketTransfer() { *vcBaseReg = CONFIG_END; } -ReturnValue_t PapbVcInterface::pollInterfaceReadiness(uint32_t maxPollRetries, - bool checkReadyState) const { - uint32_t busyIdx = 0; - nextDelay.tv_nsec = FIRST_DELAY_PAPB_POLLING_NS; - - while (true) { - // Check if PAPB interface is ready to receive data. Use the configuration register for this. - // Bit 5, see PTME ptme_001_01-0-7-r2 Table 31. - uint32_t reg = *vcBaseReg; - bool busy = (reg >> 5) & 0b1; - bool ready = (reg >> 6) & 0b1; - if (not busy) { - return returnvalue::OK; - } - if (checkReadyState and not ready) { - return PAPB_BUSY; - } - - busyIdx++; - if (busyIdx >= maxPollRetries) { - return PAPB_BUSY; - } - - // Ignore signal handling here for now. - nanosleep(&nextDelay, &remDelay); - // Adaptive delay. - if (nextDelay.tv_nsec * 2 <= MAX_DELAY_PAPB_POLLING_NS) { - nextDelay.tv_nsec *= 2; - } - } - return returnvalue::OK; +bool PapbVcInterface::pollReadyForPacket() const { + // Check if PAPB interface is ready to receive data. Use the configuration register for this. + // Bit 5, see PTME ptme_001_01-0-7-r2 Table 31. + uint32_t reg = *vcBaseReg; + // bool busy = (reg >> 5) & 0b1; + return (reg >> 6) & 0b1; } -void PapbVcInterface::isVcInterfaceBufferEmpty() { +bool PapbVcInterface::isVcInterfaceBufferEmpty() { ReturnValue_t result = returnvalue::OK; gpio::Levels papbEmptyState = gpio::Levels::HIGH; result = gpioComIF->readGpio(papbEmptyId, papbEmptyState); if (result != returnvalue::OK) { - sif::warning << "PapbVcInterface::isVcInterfaceBufferEmpty: Failed to read papb empty signal" - << std::endl; - return; + sif::error << "PapbVcInterface::isVcInterfaceBufferEmpty: Failed to read papb empty signal" + << std::endl; + return true; } if (papbEmptyState == gpio::Levels::HIGH) { - sif::debug << "PapbVcInterface::isVcInterfaceBufferEmpty: Buffer is empty" << std::endl; - } else { - sif::debug << "PapbVcInterface::isVcInterfaceBufferEmpty: Buffer is not empty" << std::endl; + return true; } - return; + return false; } -bool PapbVcInterface::isBusy() const { return pollInterfaceReadiness(0, true) == PAPB_BUSY; } +bool PapbVcInterface::isBusy() const { return not pollReadyForPacket(); } void PapbVcInterface::cancelTransfer() { abortPacketTransfer(); } diff --git a/linux/ipcore/PapbVcInterface.h b/linux/ipcore/PapbVcInterface.h index e54def5d..ba6063b5 100644 --- a/linux/ipcore/PapbVcInterface.h +++ b/linux/ipcore/PapbVcInterface.h @@ -30,8 +30,7 @@ class PapbVcInterface : public VirtualChannelIF { * @param uioFile UIO file providing access to the PAPB bus * @param mapNum Map number of UIO map associated with this virtual channel */ - PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbBusyId, gpioId_t papbEmptyId, - std::string uioFile, int mapNum); + PapbVcInterface(LinuxLibgpioIF* gpioComIF, gpioId_t papbEmptyId, std::string uioFile, int mapNum); virtual ~PapbVcInterface(); bool isBusy() const override; @@ -83,9 +82,6 @@ class PapbVcInterface : public VirtualChannelIF { static constexpr long int MAX_DELAY_PAPB_POLLING_NS = 40; LinuxLibgpioIF* gpioComIF = nullptr; - - /** Pulled to low when virtual channel not ready to receive data */ - gpioId_t papbBusyId = gpio::NO_GPIO; /** High when external buffer memory of virtual channel is empty */ gpioId_t papbEmptyId = gpio::NO_GPIO; @@ -120,13 +116,13 @@ class PapbVcInterface : public VirtualChannelIF { * * @return returnvalue::OK when ready to receive data else PAPB_BUSY. */ - inline ReturnValue_t pollInterfaceReadiness(uint32_t maxPollRetries, bool checkReadyState) const; + inline bool pollReadyForPacket() const; /** * @brief This function can be used for debugging to check whether there are packets in * the packet buffer of the virtual channel or not. */ - void isVcInterfaceBufferEmpty(); + bool isVcInterfaceBufferEmpty(); /** * @brief This function sends a complete telemetry transfer frame data field (1105 bytes) diff --git a/linux/payload/CMakeLists.txt b/linux/payload/CMakeLists.txt index 7b2c4486..e697fac6 100644 --- a/linux/payload/CMakeLists.txt +++ b/linux/payload/CMakeLists.txt @@ -2,7 +2,8 @@ target_sources( ${OBSW_NAME} PUBLIC PlocMemoryDumper.cpp PlocMpsocHandler.cpp - PlocMpsocHelper.cpp + PlocMpsocSpecialComHelper.cpp + plocMpsocHelpers.cpp PlocSupervisorHandler.cpp PlocSupvUartMan.cpp ScexDleParser.cpp diff --git a/linux/payload/PlocMpsocHandler.cpp b/linux/payload/PlocMpsocHandler.cpp index 07f7759d..cdf59c52 100644 --- a/linux/payload/PlocMpsocHandler.cpp +++ b/linux/payload/PlocMpsocHandler.cpp @@ -8,12 +8,12 @@ #include "fsfw/datapool/PoolReadGuard.h" #include "fsfw/globalfunctions/CRC.h" -PlocMPSoCHandler::PlocMPSoCHandler(object_id_t objectId, object_id_t uartComIFid, - CookieIF* comCookie, PlocMPSoCHelper* plocMPSoCHelper, +PlocMpsocHandler::PlocMpsocHandler(object_id_t objectId, object_id_t uartComIFid, + CookieIF* comCookie, PlocMpsocSpecialComHelper* plocMPSoCHelper, Gpio uartIsolatorSwitch, object_id_t supervisorHandler) : DeviceHandlerBase(objectId, uartComIFid, comCookie), hkReport(this), - plocMPSoCHelper(plocMPSoCHelper), + specialComHelper(plocMPSoCHelper), uartIsolatorSwitch(uartIsolatorSwitch), supervisorHandler(supervisorHandler), commandActionHelper(this) { @@ -27,9 +27,9 @@ PlocMPSoCHandler::PlocMPSoCHandler(object_id_t objectId, object_id_t uartComIFid spParams.buf = commandBuffer; } -PlocMPSoCHandler::~PlocMPSoCHandler() {} +PlocMpsocHandler::~PlocMpsocHandler() {} -ReturnValue_t PlocMPSoCHandler::initialize() { +ReturnValue_t PlocMpsocHandler::initialize() { ReturnValue_t result = returnvalue::OK; result = DeviceHandlerBase::initialize(); if (result != returnvalue::OK) { @@ -53,24 +53,35 @@ ReturnValue_t PlocMPSoCHandler::initialize() { if (result != returnvalue::OK) { return result; } - result = manager->subscribeToEventRange( - eventQueue->getId(), event::getEventId(PlocMPSoCHelper::MPSOC_FLASH_WRITE_FAILED), - event::getEventId(PlocMPSoCHelper::MPSOC_FLASH_WRITE_SUCCESSFUL)); + result = manager->subscribeToEvent( + eventQueue->getId(), event::getEventId(PlocMpsocSpecialComHelper::MPSOC_FLASH_WRITE_FAILED)); + if (result != returnvalue::OK) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + result = manager->subscribeToEvent( + eventQueue->getId(), + event::getEventId(PlocMpsocSpecialComHelper::MPSOC_FLASH_WRITE_SUCCESSFUL)); + if (result != returnvalue::OK) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + result = manager->subscribeToEvent( + eventQueue->getId(), + event::getEventId(PlocMpsocSpecialComHelper::MPSOC_FLASH_READ_SUCCESSFUL)); + if (result != returnvalue::OK) { + return ObjectManagerIF::CHILD_INIT_FAILED; + } + result = manager->subscribeToEvent( + eventQueue->getId(), event::getEventId(PlocMpsocSpecialComHelper::MPSOC_FLASH_READ_FAILED)); if (result != returnvalue::OK) { -#if FSFW_CPP_OSTREAM_ENABLED == 1 - sif::warning << "PlocMPSoCHandler::initialize: Failed to subscribe to events from " - " ploc mpsoc helper" - << std::endl; -#endif return ObjectManagerIF::CHILD_INIT_FAILED; } - result = plocMPSoCHelper->setComIF(communicationInterface); + result = specialComHelper->setComIF(communicationInterface); if (result != returnvalue::OK) { return ObjectManagerIF::CHILD_INIT_FAILED; } - plocMPSoCHelper->setComCookie(comCookie); - plocMPSoCHelper->setSequenceCount(&sequenceCount); + specialComHelper->setComCookie(comCookie); + specialComHelper->setSequenceCount(&sequenceCount); result = commandActionHelper.initialize(); if (result != returnvalue::OK) { return ObjectManagerIF::CHILD_INIT_FAILED; @@ -78,7 +89,12 @@ ReturnValue_t PlocMPSoCHandler::initialize() { return result; } -void PlocMPSoCHandler::performOperationHook() { +void PlocMpsocHandler::performOperationHook() { + if (commandIsPending and cmdCountdown.hasTimedOut()) { + commandIsPending = false; + // TODO: Better returnvalue? + cmdDoneHandler(false, returnvalue::FAILED); + } EventMessage event; for (ReturnValue_t result = eventQueue->receiveMessage(&event); result == returnvalue::OK; result = eventQueue->receiveMessage(&event)) { @@ -102,10 +118,9 @@ void PlocMPSoCHandler::performOperationHook() { } } -ReturnValue_t PlocMPSoCHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, +ReturnValue_t PlocMpsocHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t* data, size_t size) { ReturnValue_t result = returnvalue::OK; - commandIsPending = true; switch (actionId) { case mpsoc::SET_UART_TX_TRISTATE: { uartIsolatorSwitch.pullLow(); @@ -121,26 +136,38 @@ ReturnValue_t PlocMPSoCHandler::executeAction(ActionId_t actionId, MessageQueueI } } - if (plocMPSoCHelperExecuting) { + if (specialComHelperExecuting) { return MPSoCReturnValuesIF::MPSOC_HELPER_EXECUTING; } switch (actionId) { - case mpsoc::TC_FLASHWRITE: { - if (size > config::MAX_PATH_SIZE + config::MAX_FILENAME_SIZE) { - return MPSoCReturnValuesIF::FILENAME_TOO_LONG; - } - mpsoc::FlashWritePusCmd flashWritePusCmd; + case mpsoc::TC_FLASH_WRITE_FULL_FILE: { + mpsoc::FlashBasePusCmd flashWritePusCmd; result = flashWritePusCmd.extractFields(data, size); if (result != returnvalue::OK) { return result; } - result = plocMPSoCHelper->startFlashWrite(flashWritePusCmd.getObcFile(), - flashWritePusCmd.getMPSoCFile()); + result = specialComHelper->startFlashWrite(flashWritePusCmd.getObcFile(), + flashWritePusCmd.getMPSoCFile()); if (result != returnvalue::OK) { return result; } - plocMPSoCHelperExecuting = true; + specialComHelperExecuting = true; + return EXECUTION_FINISHED; + } + case mpsoc::TC_FLASH_READ_FULL_FILE: { + mpsoc::FlashReadPusCmd flashReadPusCmd; + result = flashReadPusCmd.extractFields(data, size); + if (result != returnvalue::OK) { + return result; + } + result = specialComHelper->startFlashRead(flashReadPusCmd.getObcFile(), + flashReadPusCmd.getMPSoCFile(), + flashReadPusCmd.getReadSize()); + if (result != returnvalue::OK) { + return result; + } + specialComHelperExecuting = true; return EXECUTION_FINISHED; } case (mpsoc::OBSW_RESET_SEQ_COUNT): { @@ -150,10 +177,13 @@ ReturnValue_t PlocMPSoCHandler::executeAction(ActionId_t actionId, MessageQueueI default: break; } + // For longer commands, do not set these. + commandIsPending = true; + cmdCountdown.resetTimer(); return DeviceHandlerBase::executeAction(actionId, commandedBy, data, size); } -void PlocMPSoCHandler::doStartUp() { +void PlocMpsocHandler::doStartUp() { if (startupState == StartupState::IDLE) { startupState = StartupState::HW_INIT; } @@ -197,48 +227,50 @@ void PlocMPSoCHandler::doStartUp() { } } -void PlocMPSoCHandler::doShutDown() { +void PlocMpsocHandler::doShutDown() { #ifdef XIPHOS_Q7S #if not OBSW_MPSOC_JTAG_BOOT == 1 - switch (powerState) { - case PowerState::ON: - uartIsolatorSwitch.pullLow(); - commandActionHelper.commandAction(supervisorHandler, supv::SHUTDOWN_MPSOC); - powerState = PowerState::SHUTDOWN; - break; - case PowerState::OFF: - sequenceCount = 0; - hkReport.setReportingEnabled(false); - setMode(_MODE_POWER_DOWN); - break; - default: - break; + if (powerState == PowerState::ON) { + uartIsolatorSwitch.pullLow(); + commandActionHelper.commandAction(supervisorHandler, supv::SHUTDOWN_MPSOC); + powerState = PowerState::SHUTDOWN; + return; + } else if (powerState == PowerState::SHUTDOWN) { + // Wait till power state is OFF. + return; } #else - sequenceCount = 0; uartIsolatorSwitch.pullLow(); - hkReport.setReportingEnabled(false); - setMode(_MODE_POWER_DOWN); powerState = PowerState::OFF; #endif #endif + + if (specialComHelper != nullptr) { + specialComHelper->stopProcess(); + } + hkReport.setReportingEnabled(false); + setMode(_MODE_POWER_DOWN); + commandIsPending = false; + sequenceCount = 0; + specialComHelperExecuting = false; startupState = StartupState::IDLE; } -ReturnValue_t PlocMPSoCHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) { - if (not commandIsPending) { +ReturnValue_t PlocMpsocHandler::buildNormalDeviceCommand(DeviceCommandId_t* id) { + if (not commandIsPending and not specialComHelperExecuting) { *id = mpsoc::TC_GET_HK_REPORT; commandIsPending = true; + cmdCountdown.resetTimer(); return buildCommandFromCommand(*id, nullptr, 0); } return NOTHING_TO_SEND; } -ReturnValue_t PlocMPSoCHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) { +ReturnValue_t PlocMpsocHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) { return NOTHING_TO_SEND; } -ReturnValue_t PlocMPSoCHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand, +ReturnValue_t PlocMpsocHandler::buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t* commandData, size_t commandDataLen) { spParams.buf = commandBuffer; @@ -329,10 +361,12 @@ ReturnValue_t PlocMPSoCHandler::buildCommandFromCommand(DeviceCommandId_t device return result; } -void PlocMPSoCHandler::fillCommandAndReplyMap() { +void PlocMpsocHandler::fillCommandAndReplyMap() { this->insertInCommandMap(mpsoc::TC_MEM_WRITE); this->insertInCommandMap(mpsoc::TC_MEM_READ); this->insertInCommandMap(mpsoc::TC_FLASHDELETE); + insertInCommandMap(mpsoc::TC_FLASH_WRITE_FULL_FILE); + insertInCommandMap(mpsoc::TC_FLASH_READ_FULL_FILE); this->insertInCommandMap(mpsoc::TC_REPLAY_START); this->insertInCommandMap(mpsoc::TC_REPLAY_STOP); this->insertInCommandMap(mpsoc::TC_DOWNLINK_PWR_ON); @@ -357,7 +391,7 @@ void PlocMPSoCHandler::fillCommandAndReplyMap() { this->insertInReplyMap(mpsoc::TM_FLASH_DIRECTORY_CONTENT, 2, nullptr, mpsoc::SP_MAX_SIZE); } -ReturnValue_t PlocMPSoCHandler::scanForReply(const uint8_t* start, size_t remainingSize, +ReturnValue_t PlocMpsocHandler::scanForReply(const uint8_t* start, size_t remainingSize, DeviceCommandId_t* foundId, size_t* foundLen) { ReturnValue_t result = returnvalue::OK; @@ -424,10 +458,11 @@ ReturnValue_t PlocMPSoCHandler::scanForReply(const uint8_t* start, size_t remain } // This sequence count ping pong does not make any sense but it is how the MPSoC expects it. sequenceCount++; + return result; } -ReturnValue_t PlocMPSoCHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) { +ReturnValue_t PlocMpsocHandler::interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) { ReturnValue_t result = returnvalue::OK; switch (id) { @@ -472,14 +507,14 @@ ReturnValue_t PlocMPSoCHandler::interpretDeviceReply(DeviceCommandId_t id, const return result; } -void PlocMPSoCHandler::setNormalDatapoolEntriesInvalid() { +void PlocMpsocHandler::setNormalDatapoolEntriesInvalid() { PoolReadGuard pg(&hkReport); hkReport.setValidity(false, true); } -uint32_t PlocMPSoCHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return 10000; } +uint32_t PlocMpsocHandler::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return 10000; } -ReturnValue_t PlocMPSoCHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, +ReturnValue_t PlocMpsocHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, LocalDataPoolManager& poolManager) { localDataPoolMap.emplace(mpsoc::poolid::STATUS, &peStatus); localDataPoolMap.emplace(mpsoc::poolid::MODE, &peMode); @@ -520,11 +555,11 @@ ReturnValue_t PlocMPSoCHandler::initializeLocalDataPool(localpool::DataPool& loc return returnvalue::OK; } -void PlocMPSoCHandler::handleEvent(EventMessage* eventMessage) { +void PlocMpsocHandler::handleEvent(EventMessage* eventMessage) { object_id_t objectId = eventMessage->getReporter(); switch (objectId) { case objects::PLOC_MPSOC_HELPER: { - plocMPSoCHelperExecuting = false; + specialComHelperExecuting = false; break; } default: @@ -533,219 +568,194 @@ void PlocMPSoCHandler::handleEvent(EventMessage* eventMessage) { } } -ReturnValue_t PlocMPSoCHandler::prepareTcMemWrite(const uint8_t* commandData, +ReturnValue_t PlocMpsocHandler::prepareTcMemWrite(const uint8_t* commandData, size_t commandDataLen) { ReturnValue_t result = returnvalue::OK; mpsoc::TcMemWrite tcMemWrite(spParams, sequenceCount); - result = tcMemWrite.buildPacket(commandData, commandDataLen); + result = tcMemWrite.setPayload(commandData, commandDataLen); if (result != returnvalue::OK) { return result; } - finishTcPrep(tcMemWrite.getFullPacketLen()); + finishTcPrep(tcMemWrite); return returnvalue::OK; } -ReturnValue_t PlocMPSoCHandler::prepareTcMemRead(const uint8_t* commandData, +ReturnValue_t PlocMpsocHandler::prepareTcMemRead(const uint8_t* commandData, size_t commandDataLen) { ReturnValue_t result = returnvalue::OK; mpsoc::TcMemRead tcMemRead(spParams, sequenceCount); - result = tcMemRead.buildPacket(commandData, commandDataLen); + result = tcMemRead.setPayload(commandData, commandDataLen); if (result != returnvalue::OK) { return result; } - finishTcPrep(tcMemRead.getFullPacketLen()); + finishTcPrep(tcMemRead); tmMemReadReport.rememberRequestedSize = tcMemRead.getMemLen() * 4 + TmMemReadReport::FIX_SIZE; return returnvalue::OK; } -ReturnValue_t PlocMPSoCHandler::prepareTcFlashDelete(const uint8_t* commandData, +ReturnValue_t PlocMpsocHandler::prepareTcFlashDelete(const uint8_t* commandData, size_t commandDataLen) { if (commandDataLen > config::MAX_PATH_SIZE + config::MAX_FILENAME_SIZE) { return MPSoCReturnValuesIF::NAME_TOO_LONG; } ReturnValue_t result = returnvalue::OK; mpsoc::TcFlashDelete tcFlashDelete(spParams, sequenceCount); - result = tcFlashDelete.buildPacket( - std::string(reinterpret_cast(commandData), commandDataLen)); + std::string filename = std::string(reinterpret_cast(commandData), commandDataLen); + result = tcFlashDelete.setPayload(filename); if (result != returnvalue::OK) { return result; } - finishTcPrep(tcFlashDelete.getFullPacketLen()); + finishTcPrep(tcFlashDelete); return returnvalue::OK; } -ReturnValue_t PlocMPSoCHandler::prepareTcReplayStart(const uint8_t* commandData, +ReturnValue_t PlocMpsocHandler::prepareTcReplayStart(const uint8_t* commandData, size_t commandDataLen) { ReturnValue_t result = returnvalue::OK; mpsoc::TcReplayStart tcReplayStart(spParams, sequenceCount); - result = tcReplayStart.buildPacket(commandData, commandDataLen); + result = tcReplayStart.setPayload(commandData, commandDataLen); if (result != returnvalue::OK) { return result; } - finishTcPrep(tcReplayStart.getFullPacketLen()); + finishTcPrep(tcReplayStart); return returnvalue::OK; } -ReturnValue_t PlocMPSoCHandler::prepareTcReplayStop() { - ReturnValue_t result = returnvalue::OK; +ReturnValue_t PlocMpsocHandler::prepareTcReplayStop() { mpsoc::TcReplayStop tcReplayStop(spParams, sequenceCount); - result = tcReplayStop.buildPacket(); - if (result != returnvalue::OK) { - return result; - } - finishTcPrep(tcReplayStop.getFullPacketLen()); + finishTcPrep(tcReplayStop); return returnvalue::OK; } -ReturnValue_t PlocMPSoCHandler::prepareTcDownlinkPwrOn(const uint8_t* commandData, +ReturnValue_t PlocMpsocHandler::prepareTcDownlinkPwrOn(const uint8_t* commandData, size_t commandDataLen) { ReturnValue_t result = returnvalue::OK; mpsoc::TcDownlinkPwrOn tcDownlinkPwrOn(spParams, sequenceCount); - result = tcDownlinkPwrOn.buildPacket(commandData, commandDataLen); + result = tcDownlinkPwrOn.setPayload(commandData, commandDataLen); if (result != returnvalue::OK) { return result; } - finishTcPrep(tcDownlinkPwrOn.getFullPacketLen()); + finishTcPrep(tcDownlinkPwrOn); return returnvalue::OK; } -ReturnValue_t PlocMPSoCHandler::prepareTcDownlinkPwrOff() { - ReturnValue_t result = returnvalue::OK; +ReturnValue_t PlocMpsocHandler::prepareTcDownlinkPwrOff() { mpsoc::TcDownlinkPwrOff tcDownlinkPwrOff(spParams, sequenceCount); - result = tcDownlinkPwrOff.buildPacket(); - if (result != returnvalue::OK) { - return result; - } - finishTcPrep(tcDownlinkPwrOff.getFullPacketLen()); + finishTcPrep(tcDownlinkPwrOff); return returnvalue::OK; } -ReturnValue_t PlocMPSoCHandler::prepareTcGetHkReport() { +ReturnValue_t PlocMpsocHandler::prepareTcGetHkReport() { mpsoc::TcGetHkReport tcGetHkReport(spParams, sequenceCount); - ReturnValue_t result = tcGetHkReport.buildPacket(); - if (result != returnvalue::OK) { - return result; - } - finishTcPrep(tcGetHkReport.getFullPacketLen()); + finishTcPrep(tcGetHkReport); return returnvalue::OK; } -ReturnValue_t PlocMPSoCHandler::prepareTcReplayWriteSequence(const uint8_t* commandData, +ReturnValue_t PlocMpsocHandler::prepareTcReplayWriteSequence(const uint8_t* commandData, size_t commandDataLen) { - ReturnValue_t result = returnvalue::OK; mpsoc::TcReplayWriteSeq tcReplayWriteSeq(spParams, sequenceCount); - result = tcReplayWriteSeq.buildPacket(commandData, commandDataLen); + ReturnValue_t result = tcReplayWriteSeq.setPayload(commandData, commandDataLen); if (result != returnvalue::OK) { return result; } - finishTcPrep(tcReplayWriteSeq.getFullPacketLen()); + finishTcPrep(tcReplayWriteSeq); return returnvalue::OK; } -ReturnValue_t PlocMPSoCHandler::prepareTcModeReplay() { - ReturnValue_t result = returnvalue::OK; +ReturnValue_t PlocMpsocHandler::prepareTcModeReplay() { mpsoc::TcModeReplay tcModeReplay(spParams, sequenceCount); - result = tcModeReplay.buildPacket(); - if (result != returnvalue::OK) { - return result; - } - finishTcPrep(tcModeReplay.getFullPacketLen()); + finishTcPrep(tcModeReplay); return returnvalue::OK; } -ReturnValue_t PlocMPSoCHandler::prepareTcModeIdle() { - ReturnValue_t result = returnvalue::OK; +ReturnValue_t PlocMpsocHandler::prepareTcModeIdle() { mpsoc::TcModeIdle tcModeIdle(spParams, sequenceCount); - result = tcModeIdle.buildPacket(); - if (result != returnvalue::OK) { - return result; - } - finishTcPrep(tcModeIdle.getFullPacketLen()); + finishTcPrep(tcModeIdle); return returnvalue::OK; } -ReturnValue_t PlocMPSoCHandler::prepareTcCamCmdSend(const uint8_t* commandData, +ReturnValue_t PlocMpsocHandler::prepareTcCamCmdSend(const uint8_t* commandData, size_t commandDataLen) { - ReturnValue_t result = returnvalue::OK; mpsoc::TcCamcmdSend tcCamCmdSend(spParams, sequenceCount); - result = tcCamCmdSend.buildPacket(commandData, commandDataLen); + ReturnValue_t result = tcCamCmdSend.setPayload(commandData, commandDataLen); if (result != returnvalue::OK) { return result; } - finishTcPrep(tcCamCmdSend.getFullPacketLen()); + finishTcPrep(tcCamCmdSend); nextReplyId = mpsoc::TM_CAM_CMD_RPT; return returnvalue::OK; } -ReturnValue_t PlocMPSoCHandler::prepareTcCamTakePic(const uint8_t* commandData, +ReturnValue_t PlocMpsocHandler::prepareTcCamTakePic(const uint8_t* commandData, size_t commandDataLen) { mpsoc::TcCamTakePic tcCamTakePic(spParams, sequenceCount); - ReturnValue_t result = tcCamTakePic.buildPacket(commandData, commandDataLen); + ReturnValue_t result = tcCamTakePic.setPayload(commandData, commandDataLen); if (result != returnvalue::OK) { return result; } - finishTcPrep(tcCamTakePic.getFullPacketLen()); + finishTcPrep(tcCamTakePic); return returnvalue::OK; } -ReturnValue_t PlocMPSoCHandler::prepareTcSimplexSendFile(const uint8_t* commandData, +ReturnValue_t PlocMpsocHandler::prepareTcSimplexSendFile(const uint8_t* commandData, size_t commandDataLen) { mpsoc::TcSimplexSendFile tcSimplexSendFile(spParams, sequenceCount); - ReturnValue_t result = tcSimplexSendFile.buildPacket(commandData, commandDataLen); + ReturnValue_t result = tcSimplexSendFile.setPayload(commandData, commandDataLen); if (result != returnvalue::OK) { return result; } - finishTcPrep(tcSimplexSendFile.getFullPacketLen()); + finishTcPrep(tcSimplexSendFile); return returnvalue::OK; } -ReturnValue_t PlocMPSoCHandler::prepareTcGetDirContent(const uint8_t* commandData, +ReturnValue_t PlocMpsocHandler::prepareTcGetDirContent(const uint8_t* commandData, size_t commandDataLen) { mpsoc::TcGetDirContent tcGetDirContent(spParams, sequenceCount); - ReturnValue_t result = tcGetDirContent.buildPacket(commandData, commandDataLen); + ReturnValue_t result = tcGetDirContent.setPayload(commandData, commandDataLen); if (result != returnvalue::OK) { return result; } - finishTcPrep(tcGetDirContent.getFullPacketLen()); + finishTcPrep(tcGetDirContent); return returnvalue::OK; } -ReturnValue_t PlocMPSoCHandler::prepareTcDownlinkDataModulate(const uint8_t* commandData, +ReturnValue_t PlocMpsocHandler::prepareTcDownlinkDataModulate(const uint8_t* commandData, size_t commandDataLen) { mpsoc::TcDownlinkDataModulate tcDownlinkDataModulate(spParams, sequenceCount); - ReturnValue_t result = tcDownlinkDataModulate.buildPacket(commandData, commandDataLen); + ReturnValue_t result = tcDownlinkDataModulate.setPayload(commandData, commandDataLen); if (result != returnvalue::OK) { return result; } - finishTcPrep(tcDownlinkDataModulate.getFullPacketLen()); + finishTcPrep(tcDownlinkDataModulate); return returnvalue::OK; } -ReturnValue_t PlocMPSoCHandler::prepareTcModeSnapshot() { +ReturnValue_t PlocMpsocHandler::prepareTcModeSnapshot() { mpsoc::TcModeSnapshot tcModeSnapshot(spParams, sequenceCount); - ReturnValue_t result = tcModeSnapshot.buildPacket(); - if (result != returnvalue::OK) { - return result; - } - finishTcPrep(tcModeSnapshot.getFullPacketLen()); + finishTcPrep(tcModeSnapshot); return returnvalue::OK; } -void PlocMPSoCHandler::finishTcPrep(size_t packetLen) { +ReturnValue_t PlocMpsocHandler::finishTcPrep(mpsoc::TcBase& tcBase) { nextReplyId = mpsoc::ACK_REPORT; + ReturnValue_t result = tcBase.finishPacket(); + if (result != returnvalue::OK) { + return result; + } rawPacket = commandBuffer; - rawPacketLen = packetLen; + rawPacketLen = tcBase.getFullPacketLen(); sequenceCount++; + return returnvalue::OK; } -ReturnValue_t PlocMPSoCHandler::verifyPacket(const uint8_t* start, size_t foundLen) { +ReturnValue_t PlocMpsocHandler::verifyPacket(const uint8_t* start, size_t foundLen) { if (CRC::crc16ccitt(start, foundLen) != 0) { return MPSoCReturnValuesIF::CRC_FAILURE; } return returnvalue::OK; } -ReturnValue_t PlocMPSoCHandler::handleAckReport(const uint8_t* data) { +ReturnValue_t PlocMpsocHandler::handleAckReport(const uint8_t* data) { ReturnValue_t result = returnvalue::OK; result = verifyPacket(data, mpsoc::SIZE_ACK_REPORT); @@ -763,10 +773,9 @@ ReturnValue_t PlocMPSoCHandler::handleAckReport(const uint8_t* data) { switch (apid) { case mpsoc::apid::ACK_FAILURE: { - sif::debug << "PlocMPSoCHandler::handleAckReport: Received Ack failure report" << std::endl; DeviceCommandId_t commandId = getPendingCommand(); - uint16_t status = getStatus(data); - printStatus(data); + uint16_t status = mpsoc::getStatusFromRawData(data); + sif::warning << "MPSoC ACK Failure: " << mpsoc::getStatusString(status) << std::endl; if (commandId != DeviceHandlerIF::NO_COMMAND_ID) { triggerEvent(ACK_FAILURE, commandId, status); } @@ -790,7 +799,7 @@ ReturnValue_t PlocMPSoCHandler::handleAckReport(const uint8_t* data) { return result; } -ReturnValue_t PlocMPSoCHandler::handleExecutionReport(const uint8_t* data) { +ReturnValue_t PlocMpsocHandler::handleExecutionReport(const uint8_t* data) { ReturnValue_t result = returnvalue::OK; result = verifyPacket(data, mpsoc::SIZE_EXE_REPORT); @@ -802,40 +811,22 @@ ReturnValue_t PlocMPSoCHandler::handleExecutionReport(const uint8_t* data) { uint16_t apid = (*(data) << 8 | *(data + 1)) & APID_MASK; - auto cmdDoneHandler = [&](bool success) { - if (normalCmdPending) { - normalCmdPending = false; - } - commandIsPending = false; - auto commandIter = deviceCommandMap.find(getPendingCommand()); - if (commandIter != deviceCommandMap.end()) { - commandIter->second.isExecuting = false; - if (commandIter->second.sendReplyTo != MessageQueueIF::NO_QUEUE) { - actionHelper.finish(success, commandIter->second.sendReplyTo, getPendingCommand(), result); - } - } - disableAllReplies(); - }; switch (apid) { case (mpsoc::apid::EXE_SUCCESS): { - cmdDoneHandler(true); + cmdDoneHandler(true, result); break; } case (mpsoc::apid::EXE_FAILURE): { - // TODO: Interpretation of status field in execution report - sif::warning << "PlocMPSoCHandler::handleExecutionReport: Received execution failure report" - << std::endl; DeviceCommandId_t commandId = getPendingCommand(); - if (commandId != DeviceHandlerIF::NO_COMMAND_ID) { - uint16_t status = getStatus(data); - triggerEvent(EXE_FAILURE, commandId, status); - } else { + if (commandId == DeviceHandlerIF::NO_COMMAND_ID) { sif::debug << "PlocMPSoCHandler::handleExecutionReport: Unknown command id" << std::endl; } - printStatus(data); + uint16_t status = mpsoc::getStatusFromRawData(data); + sif::warning << "MPSoC EXE Failure: " << mpsoc::getStatusString(status) << std::endl; + triggerEvent(EXE_FAILURE, commandId, status); sendFailureReport(mpsoc::EXE_REPORT, MPSoCReturnValuesIF::RECEIVED_EXE_FAILURE); result = IGNORE_REPLY_DATA; - cmdDoneHandler(false); + cmdDoneHandler(false, MPSoCReturnValuesIF::RECEIVED_EXE_FAILURE); break; } default: { @@ -848,7 +839,7 @@ ReturnValue_t PlocMPSoCHandler::handleExecutionReport(const uint8_t* data) { return result; } -ReturnValue_t PlocMPSoCHandler::handleMemoryReadReport(const uint8_t* data) { +ReturnValue_t PlocMpsocHandler::handleMemoryReadReport(const uint8_t* data) { ReturnValue_t result = returnvalue::OK; result = verifyPacket(data, tmMemReadReport.rememberRequestedSize); if (result == MPSoCReturnValuesIF::CRC_FAILURE) { @@ -864,7 +855,7 @@ ReturnValue_t PlocMPSoCHandler::handleMemoryReadReport(const uint8_t* data) { return result; } -ReturnValue_t PlocMPSoCHandler::handleGetHkReport(const uint8_t* data) { +ReturnValue_t PlocMpsocHandler::handleGetHkReport(const uint8_t* data) { ReturnValue_t result = verifyPacket(data, foundPacketLen); if (result != returnvalue::OK) { return result; @@ -1042,7 +1033,7 @@ ReturnValue_t PlocMPSoCHandler::handleGetHkReport(const uint8_t* data) { return returnvalue::OK; } -ReturnValue_t PlocMPSoCHandler::handleCamCmdRpt(const uint8_t* data) { +ReturnValue_t PlocMpsocHandler::handleCamCmdRpt(const uint8_t* data) { ReturnValue_t result = verifyPacket(data, foundPacketLen); if (result == MPSoCReturnValuesIF::CRC_FAILURE) { sif::warning << "PlocMPSoCHandler::handleCamCmdRpt: CRC failure" << std::endl; @@ -1062,7 +1053,7 @@ ReturnValue_t PlocMPSoCHandler::handleCamCmdRpt(const uint8_t* data) { return result; } -ReturnValue_t PlocMPSoCHandler::enableReplyInReplyMap(DeviceCommandMap::iterator command, +ReturnValue_t PlocMpsocHandler::enableReplyInReplyMap(DeviceCommandMap::iterator command, uint8_t expectedReplies, bool useAlternateId, DeviceCommandId_t alternateReplyID) { ReturnValue_t result = returnvalue::OK; @@ -1178,7 +1169,7 @@ ReturnValue_t PlocMPSoCHandler::enableReplyInReplyMap(DeviceCommandMap::iterator return returnvalue::OK; } -void PlocMPSoCHandler::setNextReplyId() { +void PlocMpsocHandler::setNextReplyId() { switch (getPendingCommand()) { case mpsoc::TC_MEM_READ: nextReplyId = mpsoc::TM_MEMORY_READ_REPORT; @@ -1198,7 +1189,7 @@ void PlocMPSoCHandler::setNextReplyId() { } } -size_t PlocMPSoCHandler::getNextReplyLength(DeviceCommandId_t commandId) { +size_t PlocMpsocHandler::getNextReplyLength(DeviceCommandId_t commandId) { size_t replyLen = 0; if (nextReplyId == mpsoc::NONE) { @@ -1239,19 +1230,19 @@ size_t PlocMPSoCHandler::getNextReplyLength(DeviceCommandId_t commandId) { return replyLen; } -ReturnValue_t PlocMPSoCHandler::doSendReadHook() { +ReturnValue_t PlocMpsocHandler::doSendReadHook() { // Prevent DHB from polling UART during commands executed by the mpsoc helper task - if (plocMPSoCHelperExecuting) { + if (specialComHelperExecuting) { return returnvalue::FAILED; } return returnvalue::OK; } -MessageQueueIF* PlocMPSoCHandler::getCommandQueuePtr() { return commandActionHelperQueue; } +MessageQueueIF* PlocMpsocHandler::getCommandQueuePtr() { return commandActionHelperQueue; } -void PlocMPSoCHandler::stepSuccessfulReceived(ActionId_t actionId, uint8_t step) { return; } +void PlocMpsocHandler::stepSuccessfulReceived(ActionId_t actionId, uint8_t step) { return; } -void PlocMPSoCHandler::stepFailedReceived(ActionId_t actionId, uint8_t step, +void PlocMpsocHandler::stepFailedReceived(ActionId_t actionId, uint8_t step, ReturnValue_t returnCode) { switch (actionId) { case supv::START_MPSOC: { @@ -1274,11 +1265,11 @@ void PlocMPSoCHandler::stepFailedReceived(ActionId_t actionId, uint8_t step, } } -void PlocMPSoCHandler::dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) { +void PlocMpsocHandler::dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) { return; } -void PlocMPSoCHandler::completionSuccessfulReceived(ActionId_t actionId) { +void PlocMpsocHandler::completionSuccessfulReceived(ActionId_t actionId) { if (actionId != supv::EXE_REPORT) { sif::debug << "PlocMPSoCHandler::completionSuccessfulReceived: Did not expect this action " << "ID" << std::endl; @@ -1299,11 +1290,11 @@ void PlocMPSoCHandler::completionSuccessfulReceived(ActionId_t actionId) { } } -void PlocMPSoCHandler::completionFailedReceived(ActionId_t actionId, ReturnValue_t returnCode) { +void PlocMpsocHandler::completionFailedReceived(ActionId_t actionId, ReturnValue_t returnCode) { handleActionCommandFailure(actionId); } -void PlocMPSoCHandler::handleDeviceTm(const uint8_t* data, size_t dataSize, +void PlocMpsocHandler::handleDeviceTm(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId) { ReturnValue_t result = returnvalue::OK; @@ -1329,7 +1320,7 @@ void PlocMPSoCHandler::handleDeviceTm(const uint8_t* data, size_t dataSize, } } -void PlocMPSoCHandler::disableAllReplies() { +void PlocMpsocHandler::disableAllReplies() { using namespace mpsoc; DeviceReplyMap::iterator iter; @@ -1392,7 +1383,7 @@ void PlocMPSoCHandler::disableAllReplies() { nextReplyId = mpsoc::NONE; } -void PlocMPSoCHandler::sendFailureReport(DeviceCommandId_t replyId, ReturnValue_t status) { +void PlocMpsocHandler::sendFailureReport(DeviceCommandId_t replyId, ReturnValue_t status) { DeviceReplyIter iter = deviceReplyMap.find(replyId); if (iter == deviceReplyMap.end()) { sif::debug << "PlocMPSoCHandler::sendFailureReport: Reply not in reply map" << std::endl; @@ -1409,7 +1400,7 @@ void PlocMPSoCHandler::sendFailureReport(DeviceCommandId_t replyId, ReturnValue_ info->isExecuting = false; } -void PlocMPSoCHandler::disableExeReportReply() { +void PlocMpsocHandler::disableExeReportReply() { DeviceReplyIter iter = deviceReplyMap.find(mpsoc::EXE_REPORT); DeviceReplyInfo* info = &(iter->second); info->delayCycles = 0; @@ -1418,16 +1409,7 @@ void PlocMPSoCHandler::disableExeReportReply() { info->command->second.expectedReplies = 0; } -void PlocMPSoCHandler::printStatus(const uint8_t* data) { - uint16_t status = (*(data + STATUS_OFFSET) << 8) | *(data + STATUS_OFFSET + 1); - sif::info << "Verification report status: " << getStatusString(status) << std::endl; -} - -uint16_t PlocMPSoCHandler::getStatus(const uint8_t* data) { - return (*(data + STATUS_OFFSET) << 8) | *(data + STATUS_OFFSET + 1); -} - -void PlocMPSoCHandler::handleActionCommandFailure(ActionId_t actionId) { +void PlocMpsocHandler::handleActionCommandFailure(ActionId_t actionId) { switch (actionId) { case supv::ACK_REPORT: case supv::EXE_REPORT: @@ -1460,96 +1442,27 @@ void PlocMPSoCHandler::handleActionCommandFailure(ActionId_t actionId) { return; } -LocalPoolDataSetBase* PlocMPSoCHandler::getDataSetHandle(sid_t sid) { +LocalPoolDataSetBase* PlocMpsocHandler::getDataSetHandle(sid_t sid) { if (sid == hkReport.getSid()) { return &hkReport; } return nullptr; } -std::string PlocMPSoCHandler::getStatusString(uint16_t status) { - switch (status) { - case (mpsoc::status_code::UNKNOWN_APID): { - return "Unknown APID"; - break; - } - case (mpsoc::status_code::INCORRECT_LENGTH): { - return "Incorrect length"; - break; - } - case (mpsoc::status_code::INCORRECT_CRC): { - return "Incorrect crc"; - break; - } - case (mpsoc::status_code::INCORRECT_PKT_SEQ_CNT): { - return "Incorrect packet sequence count"; - break; - } - case (mpsoc::status_code::TC_NOT_ALLOWED_IN_MODE): { - return "TC not allowed in this mode"; - break; - } - case (mpsoc::status_code::TC_EXEUTION_DISABLED): { - return "TC execution disabled"; - break; - } - case (mpsoc::status_code::FLASH_MOUNT_FAILED): { - return "Flash mount failed"; - break; - } - case (mpsoc::status_code::FLASH_FILE_ALREADY_CLOSED): { - return "Flash file already closed"; - break; - } - case (mpsoc::status_code::FLASH_FILE_OPEN_FAILED): { - return "Flash file open failed"; - break; - } - case (mpsoc::status_code::FLASH_FILE_NOT_OPEN): { - return "Flash file not open"; - break; - } - case (mpsoc::status_code::FLASH_UNMOUNT_FAILED): { - return "Flash unmount failed"; - break; - } - case (mpsoc::status_code::HEAP_ALLOCATION_FAILED): { - return "Heap allocation failed"; - break; - } - case (mpsoc::status_code::INVALID_PARAMETER): { - return "Invalid parameter"; - break; - } - case (mpsoc::status_code::NOT_INITIALIZED): { - return "Not initialized"; - break; - } - case (mpsoc::status_code::REBOOT_IMMINENT): { - return "Reboot imminent"; - break; - } - case (mpsoc::status_code::CORRUPT_DATA): { - return "Corrupt data"; - break; - } - case (mpsoc::status_code::FLASH_CORRECTABLE_MISMATCH): { - return "Flash correctable mismatch"; - break; - } - case (mpsoc::status_code::FLASH_UNCORRECTABLE_MISMATCH): { - return "Flash uncorrectable mismatch"; - break; - } - case (mpsoc::status_code::DEFAULT_ERROR_CODE): { - return "Default error code"; - break; - } - default: - std::stringstream ss; - ss << "0x" << std::hex << status; - return ss.str(); - break; - } - return ""; +bool PlocMpsocHandler::dontCheckQueue() { + // The TC and TMs need to be handled strictly sequentially, so while a command is pending, + // more specifically while replies are still expected, do not check the queue.s + return commandIsPending; +} + +void PlocMpsocHandler::cmdDoneHandler(bool success, ReturnValue_t result) { + commandIsPending = false; + auto commandIter = deviceCommandMap.find(getPendingCommand()); + if (commandIter != deviceCommandMap.end()) { + commandIter->second.isExecuting = false; + if (commandIter->second.sendReplyTo != MessageQueueIF::NO_QUEUE) { + actionHelper.finish(success, commandIter->second.sendReplyTo, getPendingCommand(), result); + } + } + disableAllReplies(); } diff --git a/linux/payload/PlocMpsocHandler.h b/linux/payload/PlocMpsocHandler.h index a6af8156..a82623b0 100644 --- a/linux/payload/PlocMpsocHandler.h +++ b/linux/payload/PlocMpsocHandler.h @@ -1,9 +1,9 @@ #ifndef BSP_Q7S_DEVICES_PLOC_PLOCMPSOCHANDLER_H_ #define BSP_Q7S_DEVICES_PLOC_PLOCMPSOCHANDLER_H_ -#include +#include #include -#include +#include #include #include @@ -28,9 +28,10 @@ * @note The sequence count in the space packets must be incremented with each received and sent * packet otherwise the MPSoC will reply with an acknowledgment failure report. * - * @author J. Meier + * NOTE: This is not an example for a good device handler, DO NOT USE THIS AS A REFERENCE HANDLER. + * @author J. Meier, R. Mueller */ -class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF { +class PlocMpsocHandler : public DeviceHandlerBase, public CommandsActionsIF { public: /** * @brief Constructor @@ -43,10 +44,10 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF { * module in the programmable logic * @param supervisorHandler Object ID of the supervisor handler */ - PlocMPSoCHandler(object_id_t objectId, object_id_t uartComIFid, CookieIF* comCookie, - PlocMPSoCHelper* plocMPSoCHelper, Gpio uartIsolatorSwitch, + PlocMpsocHandler(object_id_t objectId, object_id_t uartComIFid, CookieIF* comCookie, + PlocMpsocSpecialComHelper* plocMPSoCHelper, Gpio uartIsolatorSwitch, object_id_t supervisorHandler); - virtual ~PlocMPSoCHandler(); + virtual ~PlocMpsocHandler(); virtual ReturnValue_t initialize() override; ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t* data, size_t size) override; @@ -79,6 +80,7 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF { size_t getNextReplyLength(DeviceCommandId_t deviceCommand) override; ReturnValue_t doSendReadHook() override; LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override; + bool dontCheckQueue() override; private: static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_MPSOC_HANDLER; @@ -104,11 +106,9 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF { static const uint16_t APID_MASK = 0x7FF; static const uint16_t PACKET_SEQUENCE_COUNT_MASK = 0x3FFF; - static const uint8_t STATUS_OFFSET = 10; mpsoc::HkReport hkReport; - bool normalCmdPending = false; MessageQueueIF* eventQueue = nullptr; MessageQueueIF* commandActionHelperQueue = nullptr; @@ -162,13 +162,13 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF { SerialComIF* uartComIf = nullptr; - PlocMPSoCHelper* plocMPSoCHelper = nullptr; + PlocMpsocSpecialComHelper* specialComHelper = nullptr; Gpio uartIsolatorSwitch; object_id_t supervisorHandler = 0; CommandActionHelper commandActionHelper; // Used to block incoming commands when MPSoC helper class is currently executing a command - bool plocMPSoCHelperExecuting = false; + bool specialComHelperExecuting = false; bool commandIsPending = false; struct TmMemReadReport { @@ -177,6 +177,7 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF { }; TmMemReadReport tmMemReadReport; + Countdown cmdCountdown = Countdown(10000); struct TelemetryBuffer { uint16_t length = 0; @@ -213,7 +214,7 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF { ReturnValue_t prepareTcSimplexSendFile(const uint8_t* commandData, size_t commandDataLen); ReturnValue_t prepareTcDownlinkDataModulate(const uint8_t* commandData, size_t commandDataLen); ReturnValue_t prepareTcModeSnapshot(); - void finishTcPrep(size_t packetLen); + ReturnValue_t finishTcPrep(mpsoc::TcBase& tcBase); /** * @brief This function checks the crc of the received PLOC reply. @@ -295,15 +296,11 @@ class PlocMPSoCHandler : public DeviceHandlerBase, public CommandsActionsIF { */ void disableExeReportReply(); - void printStatus(const uint8_t* data); - ReturnValue_t prepareTcModeReplay(); - uint16_t getStatus(const uint8_t* data); + void cmdDoneHandler(bool success, ReturnValue_t result); void handleActionCommandFailure(ActionId_t actionId); - - std::string getStatusString(uint16_t status); }; #endif /* BSP_Q7S_DEVICES_PLOC_PLOCMPSOCHANDLER_H_ */ diff --git a/linux/payload/PlocMpsocHelper.cpp b/linux/payload/PlocMpsocHelper.cpp deleted file mode 100644 index a22462e2..00000000 --- a/linux/payload/PlocMpsocHelper.cpp +++ /dev/null @@ -1,355 +0,0 @@ -#include - -#include -#include - -#ifdef XIPHOS_Q7S -#include "bsp_q7s/fs/FilesystemHelper.h" -#endif - -#include "mission/utility/Timestamp.h" - -using namespace ploc; - -PlocMPSoCHelper::PlocMPSoCHelper(object_id_t objectId) : SystemObject(objectId) { - spParams.buf = commandBuffer; - spParams.maxSize = sizeof(commandBuffer); -} - -PlocMPSoCHelper::~PlocMPSoCHelper() {} - -ReturnValue_t PlocMPSoCHelper::initialize() { -#ifdef XIPHOS_Q7S - sdcMan = SdCardManager::instance(); - if (sdcMan == nullptr) { - sif::warning << "PlocMPSoCHelper::initialize: Invalid SD Card Manager" << std::endl; - return returnvalue::FAILED; - } -#endif - return returnvalue::OK; -} - -ReturnValue_t PlocMPSoCHelper::performOperation(uint8_t operationCode) { - ReturnValue_t result = returnvalue::OK; - semaphore.acquire(); - while (true) { -#if OBSW_THREAD_TRACING == 1 - trace::threadTrace(opCounter, "PLOC MPSOC Helper"); -#endif - switch (internalState) { - case InternalState::IDLE: { - semaphore.acquire(); - break; - } - case InternalState::FLASH_WRITE: { - result = performFlashWrite(); - if (result == returnvalue::OK) { - triggerEvent(MPSOC_FLASH_WRITE_SUCCESSFUL); - } else { - triggerEvent(MPSOC_FLASH_WRITE_FAILED); - } - internalState = InternalState::IDLE; - break; - } - default: - sif::debug << "PlocMPSoCHelper::performOperation: Invalid state" << std::endl; - break; - } - } -} - -ReturnValue_t PlocMPSoCHelper::setComIF(DeviceCommunicationIF* communicationInterface_) { - uartComIF = dynamic_cast(communicationInterface_); - if (uartComIF == nullptr) { - sif::warning << "PlocMPSoCHelper::initialize: Invalid uart com if" << std::endl; - return returnvalue::FAILED; - } - return returnvalue::OK; -} - -void PlocMPSoCHelper::setComCookie(CookieIF* comCookie_) { comCookie = comCookie_; } - -void PlocMPSoCHelper::setSequenceCount(SourceSequenceCounter* sequenceCount_) { - sequenceCount = sequenceCount_; -} - -ReturnValue_t PlocMPSoCHelper::startFlashWrite(std::string obcFile, std::string mpsocFile) { - ReturnValue_t result = returnvalue::OK; -#ifdef XIPHOS_Q7S - result = FilesystemHelper::checkPath(obcFile); - if (result != returnvalue::OK) { - return result; - } - result = FilesystemHelper::fileExists(mpsocFile); - if (result != returnvalue::OK) { - return result; - } -#endif -#ifdef TE0720_1CFA - if (not std::filesystem::exists(obcFile)) { - sif::warning << "PlocMPSoCHelper::startFlashWrite: File " << obcFile << "does not exist" - << std::endl; - return returnvalue::FAILED; - } -#endif - - flashWrite.obcFile = obcFile; - flashWrite.mpsocFile = mpsocFile; - internalState = InternalState::FLASH_WRITE; - result = resetHelper(); - if (result != returnvalue::OK) { - return result; - } - return result; -} - -ReturnValue_t PlocMPSoCHelper::resetHelper() { - ReturnValue_t result = returnvalue::OK; - semaphore.release(); - spParams.buf = commandBuffer; - terminate = false; - result = uartComIF->flushUartRxBuffer(comCookie); - return result; -} - -void PlocMPSoCHelper::stopProcess() { terminate = true; } - -ReturnValue_t PlocMPSoCHelper::performFlashWrite() { - ReturnValue_t result = returnvalue::OK; - result = flashfopen(); - if (result != returnvalue::OK) { - return result; - } - uint8_t tempData[mpsoc::MAX_DATA_SIZE]; - std::ifstream file(flashWrite.obcFile, std::ifstream::binary); - // Set position of next character to end of file input stream - file.seekg(0, file.end); - // tellg returns position of character in input stream - size_t remainingSize = file.tellg(); - size_t dataLength = 0; - size_t bytesRead = 0; - while (remainingSize > 0) { - if (terminate) { - return returnvalue::OK; - } - if (remainingSize > mpsoc::MAX_DATA_SIZE) { - dataLength = mpsoc::MAX_DATA_SIZE; - } else { - dataLength = remainingSize; - } - if (file.is_open()) { - file.seekg(bytesRead, file.beg); - file.read(reinterpret_cast(tempData), dataLength); - bytesRead += dataLength; - remainingSize -= dataLength; - } else { - return FILE_CLOSED_ACCIDENTALLY; - } - (*sequenceCount)++; - mpsoc::TcFlashWrite tc(spParams, *sequenceCount); - result = tc.buildPacket(tempData, dataLength); - if (result != returnvalue::OK) { - return result; - } - result = handlePacketTransmission(tc); - if (result != returnvalue::OK) { - return result; - } - } - result = flashfclose(); - if (result != returnvalue::OK) { - return result; - } - return result; -} - -ReturnValue_t PlocMPSoCHelper::flashfopen() { - ReturnValue_t result = returnvalue::OK; - spParams.buf = commandBuffer; - (*sequenceCount)++; - mpsoc::FlashFopen flashFopen(spParams, *sequenceCount); - result = flashFopen.createPacket(flashWrite.mpsocFile, mpsoc::FlashFopen::APPEND); - if (result != returnvalue::OK) { - return result; - } - result = handlePacketTransmission(flashFopen); - if (result != returnvalue::OK) { - return result; - } - return returnvalue::OK; -} - -ReturnValue_t PlocMPSoCHelper::flashfclose() { - ReturnValue_t result = returnvalue::OK; - spParams.buf = commandBuffer; - (*sequenceCount)++; - mpsoc::FlashFclose flashFclose(spParams, *sequenceCount); - result = flashFclose.createPacket(flashWrite.mpsocFile); - if (result != returnvalue::OK) { - return result; - } - result = handlePacketTransmission(flashFclose); - if (result != returnvalue::OK) { - return result; - } - return returnvalue::OK; -} - -ReturnValue_t PlocMPSoCHelper::handlePacketTransmission(ploc::SpTcBase& tc) { - ReturnValue_t result = returnvalue::OK; - result = sendCommand(tc); - if (result != returnvalue::OK) { - return result; - } - result = handleAck(); - if (result != returnvalue::OK) { - return result; - } - result = handleExe(); - if (result != returnvalue::OK) { - return result; - } - return returnvalue::OK; -} - -ReturnValue_t PlocMPSoCHelper::sendCommand(ploc::SpTcBase& tc) { - ReturnValue_t result = returnvalue::OK; - result = uartComIF->sendMessage(comCookie, tc.getFullPacket(), tc.getFullPacketLen()); - if (result != returnvalue::OK) { - sif::warning << "PlocMPSoCHelper::sendCommand: Failed to send command" << std::endl; - triggerEvent(MPSOC_SENDING_COMMAND_FAILED, result, static_cast(internalState)); - return result; - } - return result; -} - -ReturnValue_t PlocMPSoCHelper::handleAck() { - ReturnValue_t result = returnvalue::OK; - result = handleTmReception(mpsoc::SIZE_ACK_REPORT); - if (result != returnvalue::OK) { - return result; - } - SpTmReader tmPacket(tmBuf.data(), tmBuf.size()); - result = checkReceivedTm(tmPacket); - if (result != returnvalue::OK) { - return result; - } - uint16_t apid = tmPacket.getApid(); - if (apid != mpsoc::apid::ACK_SUCCESS) { - handleAckApidFailure(apid); - return returnvalue::FAILED; - } - return returnvalue::OK; -} - -void PlocMPSoCHelper::handleAckApidFailure(uint16_t apid) { - if (apid == mpsoc::apid::ACK_FAILURE) { - triggerEvent(MPSOC_ACK_FAILURE_REPORT, static_cast(internalState)); - sif::warning << "PlocMPSoCHelper::handleAckApidFailure: Received acknowledgement failure " - << "report" << std::endl; - } else { - triggerEvent(MPSOC_ACK_INVALID_APID, apid, static_cast(internalState)); - sif::warning << "PlocMPSoCHelper::handleAckApidFailure: Expected acknowledgement report " - << "but received space packet with apid " << std::hex << apid << std::endl; - } -} - -ReturnValue_t PlocMPSoCHelper::handleExe() { - ReturnValue_t result = returnvalue::OK; - - result = handleTmReception(mpsoc::SIZE_EXE_REPORT); - if (result != returnvalue::OK) { - return result; - } - ploc::SpTmReader tmPacket(tmBuf.data(), tmBuf.size()); - result = checkReceivedTm(tmPacket); - if (result != returnvalue::OK) { - return result; - } - uint16_t apid = tmPacket.getApid(); - if (apid != mpsoc::apid::EXE_SUCCESS) { - handleExeApidFailure(apid); - return returnvalue::FAILED; - } - return returnvalue::OK; -} - -void PlocMPSoCHelper::handleExeApidFailure(uint16_t apid) { - if (apid == mpsoc::apid::EXE_FAILURE) { - triggerEvent(MPSOC_EXE_FAILURE_REPORT, static_cast(internalState)); - sif::warning << "PlocMPSoCHelper::handleExeApidFailure: Received execution failure " - << "report" << std::endl; - } else { - triggerEvent(MPSOC_EXE_INVALID_APID, apid, static_cast(internalState)); - sif::warning << "PlocMPSoCHelper::handleExeApidFailure: Expected execution report " - << "but received space packet with apid " << std::hex << apid << std::endl; - } -} - -ReturnValue_t PlocMPSoCHelper::handleTmReception(size_t remainingBytes) { - ReturnValue_t result = returnvalue::OK; - size_t readBytes = 0; - size_t currentBytes = 0; - for (int retries = 0; retries < RETRIES; retries++) { - result = receive(tmBuf.data() + readBytes, ¤tBytes, remainingBytes); - if (result != returnvalue::OK) { - return result; - } - readBytes += currentBytes; - remainingBytes = remainingBytes - currentBytes; - if (remainingBytes == 0) { - break; - } - } - if (remainingBytes != 0) { - sif::warning << "PlocMPSoCHelper::handleTmReception: Failed to receive reply" << std::endl; - triggerEvent(MPSOC_MISSING_EXE, remainingBytes, static_cast(internalState)); - return returnvalue::FAILED; - } - return result; -} - -ReturnValue_t PlocMPSoCHelper::checkReceivedTm(SpTmReader& reader) { - ReturnValue_t result = reader.checkSize(); - if (result != returnvalue::OK) { - sif::error << "PlocMPSoCHelper::handleTmReception: Size check on received TM failed" - << std::endl; - triggerEvent(MPSOC_TM_SIZE_ERROR); - return result; - } - reader.checkCrc(); - if (result != returnvalue::OK) { - sif::warning << "PlocMPSoCHelper::handleTmReception: CRC check failed" << std::endl; - triggerEvent(MPSOC_TM_CRC_MISSMATCH, *sequenceCount); - return result; - } - (*sequenceCount)++; - uint16_t recvSeqCnt = reader.getSequenceCount(); - if (recvSeqCnt != *sequenceCount) { - triggerEvent(MPSOC_HELPER_SEQ_CNT_MISMATCH, *sequenceCount, recvSeqCnt); - *sequenceCount = recvSeqCnt; - } - return returnvalue::OK; -} - -ReturnValue_t PlocMPSoCHelper::receive(uint8_t* data, size_t* readBytes, size_t requestBytes) { - ReturnValue_t result = returnvalue::OK; - uint8_t* buffer = nullptr; - result = uartComIF->requestReceiveMessage(comCookie, requestBytes); - if (result != returnvalue::OK) { - sif::warning << "PlocMPSoCHelper::receive: Failed to request reply" << std::endl; - triggerEvent(MPSOC_HELPER_REQUESTING_REPLY_FAILED, result, - static_cast(static_cast(internalState))); - return returnvalue::FAILED; - } - result = uartComIF->readReceivedMessage(comCookie, &buffer, readBytes); - if (result != returnvalue::OK) { - sif::warning << "PlocMPSoCHelper::receive: Failed to read received message" << std::endl; - triggerEvent(MPSOC_HELPER_READING_REPLY_FAILED, result, static_cast(internalState)); - return returnvalue::FAILED; - } - if (*readBytes > 0) { - std::memcpy(data, buffer, *readBytes); - } - return result; -} diff --git a/linux/payload/PlocMpsocSpecialComHelper.cpp b/linux/payload/PlocMpsocSpecialComHelper.cpp new file mode 100644 index 00000000..acf88abd --- /dev/null +++ b/linux/payload/PlocMpsocSpecialComHelper.cpp @@ -0,0 +1,544 @@ +#include +#include +#include +#include + +#include +#include + +#ifdef XIPHOS_Q7S +#include "bsp_q7s/fs/FilesystemHelper.h" +#endif + +#include "mission/utility/Timestamp.h" + +using namespace ploc; + +PlocMpsocSpecialComHelper::PlocMpsocSpecialComHelper(object_id_t objectId) + : SystemObject(objectId) { + spParams.buf = commandBuffer; + spParams.maxSize = sizeof(commandBuffer); +} + +PlocMpsocSpecialComHelper::~PlocMpsocSpecialComHelper() {} + +ReturnValue_t PlocMpsocSpecialComHelper::initialize() { +#ifdef XIPHOS_Q7S + sdcMan = SdCardManager::instance(); + if (sdcMan == nullptr) { + sif::warning << "PlocMPSoCHelper::initialize: Invalid SD Card Manager" << std::endl; + return returnvalue::FAILED; + } +#endif + return returnvalue::OK; +} + +ReturnValue_t PlocMpsocSpecialComHelper::performOperation(uint8_t operationCode) { + ReturnValue_t result = returnvalue::OK; + semaphore.acquire(); + while (true) { +#if OBSW_THREAD_TRACING == 1 + trace::threadTrace(opCounter, "PLOC MPSOC Helper"); +#endif + switch (internalState) { + case InternalState::IDLE: { + semaphore.acquire(); + break; + } + case InternalState::FLASH_WRITE: { + result = performFlashWrite(); + if (result == returnvalue::OK) { + triggerEvent(MPSOC_FLASH_WRITE_SUCCESSFUL, sequenceCount->get()); + } else { + triggerEvent(MPSOC_FLASH_WRITE_FAILED, sequenceCount->get()); + } + internalState = InternalState::IDLE; + break; + } + case InternalState::FLASH_READ: { + result = performFlashRead(); + if (result == returnvalue::OK) { + triggerEvent(MPSOC_FLASH_READ_SUCCESSFUL, sequenceCount->get()); + } else { + triggerEvent(MPSOC_FLASH_READ_FAILED, sequenceCount->get()); + } + internalState = InternalState::IDLE; + break; + } + default: + sif::debug << "PlocMPSoCHelper::performOperation: Invalid state" << std::endl; + break; + } + } +} + +ReturnValue_t PlocMpsocSpecialComHelper::setComIF(DeviceCommunicationIF* communicationInterface_) { + uartComIF = dynamic_cast(communicationInterface_); + if (uartComIF == nullptr) { + sif::warning << "PlocMPSoCHelper::initialize: Invalid uart com if" << std::endl; + return returnvalue::FAILED; + } + return returnvalue::OK; +} + +void PlocMpsocSpecialComHelper::setComCookie(CookieIF* comCookie_) { comCookie = comCookie_; } + +void PlocMpsocSpecialComHelper::setSequenceCount(SourceSequenceCounter* sequenceCount_) { + sequenceCount = sequenceCount_; +} + +ReturnValue_t PlocMpsocSpecialComHelper::startFlashWrite(std::string obcFile, + std::string mpsocFile) { + if (internalState != InternalState::IDLE) { + return returnvalue::FAILED; + } + ReturnValue_t result = startFlashReadOrWriteBase(std::move(obcFile), std::move(mpsocFile)); + if (result != returnvalue::OK) { + return result; + } + internalState = InternalState::FLASH_WRITE; + return semaphore.release(); +} + +ReturnValue_t PlocMpsocSpecialComHelper::startFlashRead(std::string obcFile, std::string mpsocFile, + size_t readFileSize) { + if (internalState != InternalState::IDLE) { + return returnvalue::FAILED; + } + ReturnValue_t result = startFlashReadOrWriteBase(std::move(obcFile), std::move(mpsocFile)); + if (result != returnvalue::OK) { + return result; + } + flashReadAndWrite.totalReadSize = readFileSize; + internalState = InternalState::FLASH_READ; + return semaphore.release(); +} + +void PlocMpsocSpecialComHelper::resetHelper() { + spParams.buf = commandBuffer; + terminate = false; + uartComIF->flushUartRxBuffer(comCookie); +} + +void PlocMpsocSpecialComHelper::stopProcess() { terminate = true; } + +ReturnValue_t PlocMpsocSpecialComHelper::performFlashWrite() { + ReturnValue_t result = returnvalue::OK; + std::ifstream file(flashReadAndWrite.obcFile, std::ifstream::binary); + if (file.bad()) { + return returnvalue::FAILED; + } + result = flashfopen(mpsoc::FileAccessModes::WRITE | mpsoc::FileAccessModes::OPEN_ALWAYS); + if (result != returnvalue::OK) { + return result; + } + // Set position of next character to end of file input stream + file.seekg(0, file.end); + // tellg returns position of character in input stream + size_t remainingSize = file.tellg(); + size_t dataLength = 0; + size_t bytesRead = 0; + while (remainingSize > 0) { + if (terminate) { + return returnvalue::OK; + } + // The minus 4 is necessary for unknown reasons. Maybe some bug in the ILH software? + if (remainingSize > mpsoc::MAX_FLASH_WRITE_DATA_SIZE - 4) { + dataLength = mpsoc::MAX_FLASH_WRITE_DATA_SIZE - 4; + } else { + dataLength = remainingSize; + } + if (file.bad() or not file.is_open()) { + return FILE_WRITE_ERROR; + } + file.seekg(bytesRead, file.beg); + file.read(reinterpret_cast(fileBuf.data()), dataLength); + bytesRead += dataLength; + remainingSize -= dataLength; + mpsoc::TcFlashWrite tc(spParams, *sequenceCount); + result = tc.setPayload(fileBuf.data(), dataLength); + if (result != returnvalue::OK) { + return result; + } + result = tc.finishPacket(); + if (result != returnvalue::OK) { + return result; + } + (*sequenceCount)++; + result = handlePacketTransmissionNoReply(tc); + if (result != returnvalue::OK) { + return result; + } + } + result = flashfclose(); + if (result != returnvalue::OK) { + return result; + } + return result; +} + +ReturnValue_t PlocMpsocSpecialComHelper::performFlashRead() { + std::error_code e; + std::ofstream ofile(flashReadAndWrite.obcFile, std::ios::trunc | std::ios::binary); + if (ofile.bad()) { + return returnvalue::FAILED; + } + ReturnValue_t result = flashfopen(mpsoc::FileAccessModes::READ); + if (result != returnvalue::OK) { + std::filesystem::remove(flashReadAndWrite.obcFile, e); + return result; + } + size_t readSoFar = 0; + size_t nextReadSize = mpsoc::MAX_FLASH_READ_DATA_SIZE; + while (readSoFar < flashReadAndWrite.totalReadSize) { + if (terminate) { + std::filesystem::remove(flashReadAndWrite.obcFile, e); + return returnvalue::OK; + } + nextReadSize = mpsoc::MAX_FLASH_READ_DATA_SIZE; + if (flashReadAndWrite.totalReadSize - readSoFar < mpsoc::MAX_FLASH_READ_DATA_SIZE) { + nextReadSize = flashReadAndWrite.totalReadSize - readSoFar; + } + if (ofile.bad() or not ofile.is_open()) { + std::filesystem::remove(flashReadAndWrite.obcFile, e); + return FILE_READ_ERROR; + } + mpsoc::TcFlashRead flashReadRequest(spParams, *sequenceCount); + result = flashReadRequest.setPayload(nextReadSize); + if (result != returnvalue::OK) { + std::filesystem::remove(flashReadAndWrite.obcFile, e); + return result; + } + result = flashReadRequest.finishPacket(); + if (result != returnvalue::OK) { + std::filesystem::remove(flashReadAndWrite.obcFile, e); + return result; + } + (*sequenceCount)++; + result = handlePacketTransmissionFlashRead(flashReadRequest, ofile, nextReadSize); + if (result != returnvalue::OK) { + std::filesystem::remove(flashReadAndWrite.obcFile, e); + return result; + } + readSoFar += nextReadSize; + } + result = flashfclose(); + if (result != returnvalue::OK) { + return result; + } + return result; +} + +ReturnValue_t PlocMpsocSpecialComHelper::flashfopen(uint8_t mode) { + spParams.buf = commandBuffer; + mpsoc::FlashFopen flashFopen(spParams, *sequenceCount); + ReturnValue_t result = flashFopen.setPayload(flashReadAndWrite.mpsocFile, mode); + if (result != returnvalue::OK) { + return result; + } + result = flashFopen.finishPacket(); + if (result != returnvalue::OK) { + return result; + } + (*sequenceCount)++; + result = handlePacketTransmissionNoReply(flashFopen); + if (result != returnvalue::OK) { + return result; + } + return returnvalue::OK; +} + +ReturnValue_t PlocMpsocSpecialComHelper::flashfclose() { + spParams.buf = commandBuffer; + mpsoc::FlashFclose flashFclose(spParams, *sequenceCount); + ReturnValue_t result = flashFclose.finishPacket(); + if (result != returnvalue::OK) { + return result; + } + (*sequenceCount)++; + result = handlePacketTransmissionNoReply(flashFclose); + if (result != returnvalue::OK) { + return result; + } + return result; +} + +ReturnValue_t PlocMpsocSpecialComHelper::handlePacketTransmissionFlashRead(mpsoc::TcFlashRead& tc, + std::ofstream& ofile, + size_t expectedReadLen) { + ReturnValue_t result = sendCommand(tc); + if (result != returnvalue::OK) { + return result; + } + result = handleAck(); + if (result != returnvalue::OK) { + return result; + } + result = handleTmReception(); + if (result != returnvalue::OK) { + return result; + } + + // We have the nominal case where the flash read report appears first, or the case where we + // get an EXE failure immediately. + if (spReader.getApid() == mpsoc::apid::TM_FLASH_READ_REPORT) { + result = handleFlashReadReply(ofile, expectedReadLen); + if (result != returnvalue::OK) { + return result; + } + return handleExe(); + } else if (spReader.getApid() == mpsoc::apid::EXE_FAILURE) { + handleExeFailure(); + } else { + triggerEvent(MPSOC_EXE_INVALID_APID, spReader.getApid(), static_cast(internalState)); + sif::warning << "PLOC MPSoC: Expected execution report " + << "but received space packet with apid " << std::hex << spReader.getApid() + << std::endl; + } + return returnvalue::FAILED; +} + +ReturnValue_t PlocMpsocSpecialComHelper::handlePacketTransmissionNoReply(ploc::SpTcBase& tc) { + ReturnValue_t result = sendCommand(tc); + if (result != returnvalue::OK) { + return result; + } + result = handleAck(); + if (result != returnvalue::OK) { + return result; + } + return handleExe(); +} + +ReturnValue_t PlocMpsocSpecialComHelper::sendCommand(ploc::SpTcBase& tc) { + ReturnValue_t result = returnvalue::OK; + result = uartComIF->sendMessage(comCookie, tc.getFullPacket(), tc.getFullPacketLen()); + if (result != returnvalue::OK) { + sif::warning << "PlocMPSoCHelper::sendCommand: Failed to send command" << std::endl; + triggerEvent(MPSOC_SENDING_COMMAND_FAILED, result, static_cast(internalState)); + return result; + } + return result; +} + +ReturnValue_t PlocMpsocSpecialComHelper::handleAck() { + ReturnValue_t result = returnvalue::OK; + result = handleTmReception(); + if (result != returnvalue::OK) { + return result; + } + result = checkReceivedTm(); + if (result != returnvalue::OK) { + return result; + } + uint16_t apid = spReader.getApid(); + if (apid != mpsoc::apid::ACK_SUCCESS) { + handleAckApidFailure(spReader); + return returnvalue::FAILED; + } + return returnvalue::OK; +} + +void PlocMpsocSpecialComHelper::handleAckApidFailure(const ploc::SpTmReader& reader) { + uint16_t apid = reader.getApid(); + if (apid == mpsoc::apid::ACK_FAILURE) { + uint16_t status = mpsoc::getStatusFromRawData(reader.getFullData()); + sif::warning << "PLOC MPSoC ACK Failure: " << mpsoc::getStatusString(status) << std::endl; + triggerEvent(MPSOC_ACK_FAILURE_REPORT, static_cast(internalState), status); + } else { + triggerEvent(MPSOC_ACK_INVALID_APID, apid, static_cast(internalState)); + sif::warning << "PlocMPSoCHelper::handleAckApidFailure: Expected acknowledgement report " + << "but received space packet with apid " << std::hex << apid << std::endl; + } +} + +ReturnValue_t PlocMpsocSpecialComHelper::handleExe() { + ReturnValue_t result = returnvalue::OK; + + result = handleTmReception(); + if (result != returnvalue::OK) { + return result; + } + result = checkReceivedTm(); + if (result != returnvalue::OK) { + return result; + } + uint16_t apid = spReader.getApid(); + if (apid == mpsoc::apid::EXE_FAILURE) { + handleExeFailure(); + return returnvalue::FAILED; + } else if (apid != mpsoc::apid::EXE_SUCCESS) { + triggerEvent(MPSOC_EXE_INVALID_APID, apid, static_cast(internalState)); + sif::warning << "PLOC MPSoC: Expected execution report " + << "but received space packet with apid " << std::hex << apid << std::endl; + } + return returnvalue::OK; +} + +void PlocMpsocSpecialComHelper::handleExeFailure() { + uint16_t status = mpsoc::getStatusFromRawData(spReader.getFullData()); + sif::warning << "PLOC MPSoC EXE Failure: " << mpsoc::getStatusString(status) << std::endl; + triggerEvent(MPSOC_EXE_FAILURE_REPORT, static_cast(internalState)); +} + +ReturnValue_t PlocMpsocSpecialComHelper::handleTmReception() { + ReturnValue_t result = returnvalue::OK; + tmCountdown.resetTimer(); + size_t readBytes = 0; + size_t currentBytes = 0; + uint32_t usleepDelay = 5; + size_t fullPacketLen = 0; + while (true) { + if (tmCountdown.hasTimedOut()) { + triggerEvent(MPSOC_READ_TIMEOUT, tmCountdown.getTimeoutMs()); + return returnvalue::FAILED; + } + result = receive(tmBuf.data() + readBytes, 6, ¤tBytes); + if (result != returnvalue::OK) { + return result; + } + spReader.setReadOnlyData(tmBuf.data(), tmBuf.size()); + fullPacketLen = spReader.getFullPacketLen(); + readBytes += currentBytes; + if (readBytes == 6) { + break; + } + usleep(usleepDelay); + if (usleepDelay < 200000) { + usleepDelay *= 4; + } + } + while (true) { + if (tmCountdown.hasTimedOut()) { + triggerEvent(MPSOC_READ_TIMEOUT, tmCountdown.getTimeoutMs()); + return returnvalue::FAILED; + } + result = receive(tmBuf.data() + readBytes, fullPacketLen - readBytes, ¤tBytes); + readBytes += currentBytes; + if (fullPacketLen == readBytes) { + break; + } + usleep(usleepDelay); + if (usleepDelay < 200000) { + usleepDelay *= 4; + } + } + // arrayprinter::print(tmBuf.data(), readBytes); + return result; +} + +ReturnValue_t PlocMpsocSpecialComHelper::handleFlashReadReply(std::ofstream& ofile, + size_t expectedReadLen) { + ReturnValue_t result = checkReceivedTm(); + if (result != returnvalue::OK) { + return result; + } + uint16_t apid = spReader.getApid(); + if (apid != mpsoc::apid::TM_FLASH_READ_REPORT) { + triggerEvent(MPSOC_FLASH_READ_PACKET_ERROR, FlashReadErrorType::FLASH_READ_APID_ERROR); + sif::warning << "PLOC MPSoC Flash Read: Unexpected APID" << std::endl; + return result; + } + const uint8_t* packetData = spReader.getPacketData(); + size_t deserDummy = spReader.getPacketDataLen() - mpsoc::CRC_SIZE; + uint32_t receivedReadLen = 0; + // I think this is buggy, weird stuff in the short name field. + // std::string receivedShortName = std::string(reinterpret_cast(packetData), 12); + // if (receivedShortName != flashReadAndWrite.mpsocFile.substr(0, 11)) { + // sif::warning << "PLOC MPSoC Flash Read: Missmatch between request file name and " + // "received file name" + // << std::endl; + // triggerEvent(MPSOC_FLASH_READ_PACKET_ERROR, FlashReadErrorType::FLASH_READ_FILENAME_ERROR); + // return returnvalue::FAILED; + // } + packetData += 12; + result = SerializeAdapter::deSerialize(&receivedReadLen, &packetData, &deserDummy, + SerializeIF::Endianness::NETWORK); + if (result != returnvalue::OK) { + return result; + } + if (receivedReadLen != expectedReadLen) { + sif::warning << "PLOC MPSoC Flash Read: Missmatch between request read length and " + "received read length" + << std::endl; + triggerEvent(MPSOC_FLASH_READ_PACKET_ERROR, FlashReadErrorType::FLASH_READ_READLEN_ERROR); + return returnvalue::FAILED; + } + ofile.write(reinterpret_cast(packetData), receivedReadLen); + return returnvalue::OK; +} + +ReturnValue_t PlocMpsocSpecialComHelper::fileCheck(std::string obcFile) { +#ifdef XIPHOS_Q7S + ReturnValue_t result = FilesystemHelper::checkPath(obcFile); + if (result != returnvalue::OK) { + return result; + } +#elif defined(TE0720_1CFA) + if (not std::filesystem::exists(obcFile)) { + sif::warning << "PlocMPSoCHelper::startFlashWrite: File " << obcFile << "does not exist" + << std::endl; + return returnvalue::FAILED; + } +#endif + return returnvalue::OK; +} + +ReturnValue_t PlocMpsocSpecialComHelper::startFlashReadOrWriteBase(std::string obcFile, + std::string mpsocFile) { + ReturnValue_t result = fileCheck(obcFile); + if (result != returnvalue::OK) { + return result; + } + + flashReadAndWrite.obcFile = std::move(obcFile); + flashReadAndWrite.mpsocFile = std::move(mpsocFile); + resetHelper(); + return returnvalue::OK; +} + +ReturnValue_t PlocMpsocSpecialComHelper::checkReceivedTm() { + ReturnValue_t result = spReader.checkSize(); + if (result != returnvalue::OK) { + sif::error << "PLOC MPSoC: Size check on received TM failed" << std::endl; + triggerEvent(MPSOC_TM_SIZE_ERROR); + return result; + } + spReader.checkCrc(); + if (result != returnvalue::OK) { + sif::warning << "PLOC MPSoC: CRC check failed" << std::endl; + triggerEvent(MPSOC_TM_CRC_MISSMATCH, *sequenceCount); + return result; + } + uint16_t recvSeqCnt = spReader.getSequenceCount(); + 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; +} + +ReturnValue_t PlocMpsocSpecialComHelper::receive(uint8_t* data, size_t requestBytes, + size_t* readBytes) { + ReturnValue_t result = returnvalue::OK; + uint8_t* buffer = nullptr; + result = uartComIF->requestReceiveMessage(comCookie, requestBytes); + if (result != returnvalue::OK) { + sif::warning << "PlocMPSoCHelper::receive: Failed to request reply" << std::endl; + triggerEvent(MPSOC_HELPER_REQUESTING_REPLY_FAILED, result, + static_cast(static_cast(internalState))); + return returnvalue::FAILED; + } + result = uartComIF->readReceivedMessage(comCookie, &buffer, readBytes); + if (result != returnvalue::OK) { + sif::warning << "PlocMPSoCHelper::receive: Failed to read received message" << std::endl; + triggerEvent(MPSOC_HELPER_READING_REPLY_FAILED, result, static_cast(internalState)); + return returnvalue::FAILED; + } + if (*readBytes > 0) { + std::memcpy(data, buffer, *readBytes); + } + return result; +} diff --git a/linux/payload/PlocMpsocHelper.h b/linux/payload/PlocMpsocSpecialComHelper.h similarity index 69% rename from linux/payload/PlocMpsocHelper.h rename to linux/payload/PlocMpsocSpecialComHelper.h index b74c0844..bc6bec8c 100644 --- a/linux/payload/PlocMpsocHelper.h +++ b/linux/payload/PlocMpsocSpecialComHelper.h @@ -1,11 +1,12 @@ #ifndef BSP_Q7S_DEVICES_PLOCMPSOCHELPER_H_ #define BSP_Q7S_DEVICES_PLOCMPSOCHELPER_H_ -#include +#include #include #include +#include "OBSWConfig.h" #include "fsfw/devicehandlers/CookieIF.h" #include "fsfw/objectmanager/SystemObject.h" #include "fsfw/osal/linux/BinarySemaphore.h" @@ -22,14 +23,14 @@ * MPSoC and OBC. * @author J. Meier */ -class PlocMPSoCHelper : public SystemObject, public ExecutableObjectIF { +class PlocMpsocSpecialComHelper : public SystemObject, public ExecutableObjectIF { public: static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_MPSOC_HELPER; //! [EXPORT] : [COMMENT] Flash write fails static const Event MPSOC_FLASH_WRITE_FAILED = MAKE_EVENT(0, severity::LOW); //! [EXPORT] : [COMMENT] Flash write successful - static const Event MPSOC_FLASH_WRITE_SUCCESSFUL = MAKE_EVENT(1, severity::LOW); + static const Event MPSOC_FLASH_WRITE_SUCCESSFUL = MAKE_EVENT(1, severity::INFO); //! [EXPORT] : [COMMENT] Communication interface returned failure when trying to send the command //! to the MPSoC //! P1: Return value returned by the communication interface sendMessage function @@ -71,9 +72,19 @@ class PlocMPSoCHelper : public SystemObject, public ExecutableObjectIF { static const Event MPSOC_HELPER_SEQ_CNT_MISMATCH = MAKE_EVENT(11, severity::LOW); static const Event MPSOC_TM_SIZE_ERROR = MAKE_EVENT(12, severity::LOW); static const Event MPSOC_TM_CRC_MISSMATCH = MAKE_EVENT(13, severity::LOW); + static const Event MPSOC_FLASH_READ_PACKET_ERROR = MAKE_EVENT(14, severity::LOW); + static const Event MPSOC_FLASH_READ_FAILED = MAKE_EVENT(15, severity::LOW); + static const Event MPSOC_FLASH_READ_SUCCESSFUL = MAKE_EVENT(16, severity::INFO); + static const Event MPSOC_READ_TIMEOUT = MAKE_EVENT(17, severity::LOW); - PlocMPSoCHelper(object_id_t objectId); - virtual ~PlocMPSoCHelper(); + enum FlashReadErrorType : uint32_t { + FLASH_READ_APID_ERROR = 0, + FLASH_READ_FILENAME_ERROR = 1, + FLASH_READ_READLEN_ERROR = 2 + }; + + PlocMpsocSpecialComHelper(object_id_t objectId); + virtual ~PlocMpsocSpecialComHelper(); ReturnValue_t initialize() override; ReturnValue_t performOperation(uint8_t operationCode = 0) override; @@ -90,6 +101,14 @@ class PlocMPSoCHelper : public SystemObject, public ExecutableObjectIF { * @return returnvalue::OK if successful, otherwise error return value */ ReturnValue_t startFlashWrite(std::string obcFile, std::string mpsocFile); + /** + * + * @param obcFile Full target file name on OBC + * @param mpsocFile The file on the MPSoC which should be copied ot the OBC + * @param readFileSize The size of the file on the MPSoC. + * @return + */ + ReturnValue_t startFlashRead(std::string obcFile, std::string mpsocFile, size_t readFileSize); /** * @brief Can be used to interrupt a running data transfer. @@ -104,20 +123,25 @@ class PlocMPSoCHelper : public SystemObject, public ExecutableObjectIF { private: static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_MPSOC_HELPER; - //! [EXPORT] : [COMMENT] File accidentally close - static const ReturnValue_t FILE_CLOSED_ACCIDENTALLY = MAKE_RETURN_CODE(0xA0); + //! [EXPORT] : [COMMENT] File error occured for file transfers from OBC to the MPSoC. + static const ReturnValue_t FILE_WRITE_ERROR = MAKE_RETURN_CODE(0xA0); + //! [EXPORT] : [COMMENT] File error occured for file transfers from MPSoC to OBC. + static const ReturnValue_t FILE_READ_ERROR = MAKE_RETURN_CODE(0xA1); // Maximum number of times the communication interface retries polling data from the reply // buffer static const int RETRIES = 10000; - struct FlashWrite { + struct FlashInfo { std::string obcFile; std::string mpsocFile; }; - struct FlashWrite flashWrite; + struct FlashRead : public FlashInfo { + size_t totalReadSize = 0; + }; + struct FlashRead flashReadAndWrite; #if OBSW_THREAD_TRACING == 1 uint32_t opCounter = 0; #endif @@ -134,7 +158,10 @@ class PlocMPSoCHelper : public SystemObject, public ExecutableObjectIF { SpacePacketCreator creator; ploc::SpTcParams spParams = ploc::SpTcParams(creator); - std::array tmBuf; + Countdown tmCountdown = Countdown(5000); + + std::array fileBuf{}; + std::array tmBuf{}; bool terminate = false; @@ -147,20 +174,27 @@ class PlocMPSoCHelper : public SystemObject, public ExecutableObjectIF { CookieIF* comCookie = nullptr; // Sequence count, must be set by Ploc MPSoC Handler SourceSequenceCounter* sequenceCount = nullptr; + ploc::SpTmReader spReader; - ReturnValue_t resetHelper(); + void resetHelper(); ReturnValue_t performFlashWrite(); - ReturnValue_t flashfopen(); + ReturnValue_t performFlashRead(); + ReturnValue_t flashfopen(uint8_t accessMode); ReturnValue_t flashfclose(); - ReturnValue_t handlePacketTransmission(ploc::SpTcBase& tc); + ReturnValue_t handlePacketTransmissionNoReply(ploc::SpTcBase& tc); + ReturnValue_t handlePacketTransmissionFlashRead(mpsoc::TcFlashRead& tc, std::ofstream& ofile, + size_t expectedReadLen); + ReturnValue_t handleFlashReadReply(std::ofstream& ofile, size_t expectedReadLen); ReturnValue_t sendCommand(ploc::SpTcBase& tc); - ReturnValue_t receive(uint8_t* data, size_t* readBytes, size_t requestBytes); + ReturnValue_t receive(uint8_t* data, size_t requestBytes, size_t* readBytes); ReturnValue_t handleAck(); ReturnValue_t handleExe(); - void handleAckApidFailure(uint16_t apid); - void handleExeApidFailure(uint16_t apid); - ReturnValue_t handleTmReception(size_t remainingBytes); - ReturnValue_t checkReceivedTm(ploc::SpTmReader& reader); + ReturnValue_t startFlashReadOrWriteBase(std::string obcFile, std::string mpsocFile); + ReturnValue_t fileCheck(std::string obcFile); + void handleAckApidFailure(const ploc::SpTmReader& reader); + void handleExeFailure(); + ReturnValue_t handleTmReception(); + ReturnValue_t checkReceivedTm(); }; #endif /* BSP_Q7S_DEVICES_PLOCMPSOCHELPER_H_ */ diff --git a/linux/payload/plocMpsocHelpers.cpp b/linux/payload/plocMpsocHelpers.cpp new file mode 100644 index 00000000..9e5b11c9 --- /dev/null +++ b/linux/payload/plocMpsocHelpers.cpp @@ -0,0 +1,95 @@ +#include "plocMpsocHelpers.h" + +uint16_t mpsoc::getStatusFromRawData(const uint8_t* data) { + return (*(data + STATUS_OFFSET) << 8) | *(data + STATUS_OFFSET + 1); +} +std::string mpsoc::getStatusString(uint16_t status) { + switch (status) { + case (mpsoc::status_code::UNKNOWN_APID): { + return "Unknown APID"; + break; + } + case (mpsoc::status_code::INCORRECT_LENGTH): { + return "Incorrect length"; + break; + } + case (mpsoc::status_code::INCORRECT_CRC): { + return "Incorrect crc"; + break; + } + case (mpsoc::status_code::INCORRECT_PKT_SEQ_CNT): { + return "Incorrect packet sequence count"; + break; + } + case (mpsoc::status_code::TC_NOT_ALLOWED_IN_MODE): { + return "TC not allowed in this mode"; + break; + } + case (mpsoc::status_code::TC_EXEUTION_DISABLED): { + return "TC execution disabled"; + break; + } + case (mpsoc::status_code::FLASH_MOUNT_FAILED): { + return "Flash mount failed"; + break; + } + case (mpsoc::status_code::FLASH_FILE_ALREADY_OPEN): { + return "Flash file already open"; + break; + } + case (mpsoc::status_code::FLASH_FILE_ALREADY_CLOSED): { + return "Flash file already closed"; + break; + } + case (mpsoc::status_code::FLASH_FILE_OPEN_FAILED): { + return "Flash file open failed"; + break; + } + case (mpsoc::status_code::FLASH_FILE_NOT_OPEN): { + return "Flash file not open"; + break; + } + case (mpsoc::status_code::FLASH_UNMOUNT_FAILED): { + return "Flash unmount failed"; + break; + } + case (mpsoc::status_code::HEAP_ALLOCATION_FAILED): { + return "Heap allocation failed"; + break; + } + case (mpsoc::status_code::INVALID_PARAMETER): { + return "Invalid parameter"; + break; + } + case (mpsoc::status_code::NOT_INITIALIZED): { + return "Not initialized"; + break; + } + case (mpsoc::status_code::REBOOT_IMMINENT): { + return "Reboot imminent"; + break; + } + case (mpsoc::status_code::CORRUPT_DATA): { + return "Corrupt data"; + break; + } + case (mpsoc::status_code::FLASH_CORRECTABLE_MISMATCH): { + return "Flash correctable mismatch"; + break; + } + case (mpsoc::status_code::FLASH_UNCORRECTABLE_MISMATCH): { + return "Flash uncorrectable mismatch"; + break; + } + case (mpsoc::status_code::DEFAULT_ERROR_CODE): { + return "Default error code"; + break; + } + default: + std::stringstream ss; + ss << "0x" << std::hex << status; + return ss.str().c_str(); + break; + } + return ""; +} diff --git a/linux/payload/plocMpscoDefs.h b/linux/payload/plocMpsocHelpers.h similarity index 81% rename from linux/payload/plocMpscoDefs.h rename to linux/payload/plocMpsocHelpers.h index c5d53e6f..c9b08a28 100644 --- a/linux/payload/plocMpscoDefs.h +++ b/linux/payload/plocMpsocHelpers.h @@ -13,6 +13,20 @@ namespace mpsoc { +enum FileAccessModes : uint8_t { + // Opens a file, fails if the file does not exist. + OPEN_EXISTING = 0x00, + READ = 0x01, + WRITE = 0x02, + // Creates a new file, fails if it already exists. + CREATE_NEW = 0x04, + // Creates a new file, existing file is truncated and overwritten. + CREATE_ALWAYS = 0x08, + // Opens the file if it is existing. If not, a new file is created. + OPEN_ALWAYS = 0x10, + OPEN_APPEND = 0x30 +}; + static constexpr uint32_t HK_SET_ID = 0; namespace poolid { @@ -62,7 +76,7 @@ static const DeviceCommandId_t EXE_REPORT = 5; static const DeviceCommandId_t TM_MEMORY_READ_REPORT = 6; static const DeviceCommandId_t TC_FLASHFOPEN = 7; static const DeviceCommandId_t TC_FLASHFCLOSE = 8; -static const DeviceCommandId_t TC_FLASHWRITE = 9; +static const DeviceCommandId_t TC_FLASH_WRITE_FULL_FILE = 9; static const DeviceCommandId_t TC_FLASHDELETE = 10; static const DeviceCommandId_t TC_REPLAY_START = 11; static const DeviceCommandId_t TC_REPLAY_STOP = 12; @@ -83,6 +97,7 @@ static const DeviceCommandId_t TC_GET_HK_REPORT = 26; static const DeviceCommandId_t TM_GET_HK_REPORT = 27; static const DeviceCommandId_t TC_FLASH_GET_DIRECTORY_CONTENT = 28; static const DeviceCommandId_t TM_FLASH_DIRECTORY_CONTENT = 29; +static constexpr DeviceCommandId_t TC_FLASH_READ_FULL_FILE = 30; // Will reset the sequence count of the OBSW static const DeviceCommandId_t OBSW_RESET_SEQ_COUNT = 50; @@ -104,7 +119,8 @@ static const uint16_t TC_DOWNLINK_PWR_ON = 0x113; static const uint16_t TC_MEM_WRITE = 0x114; static const uint16_t TC_MEM_READ = 0x115; static const uint16_t TC_CAM_TAKE_PIC = 0x116; -static const uint16_t TC_FLASHWRITE = 0x117; +static constexpr uint16_t TC_FLASHWRITE = 0x117; +static constexpr uint16_t TC_FLASHREAD = 0x118; static const uint16_t TC_FLASHFOPEN = 0x119; static const uint16_t TC_FLASHFCLOSE = 0x11A; static constexpr uint16_t TC_FLASH_GET_DIRECTORY_CONTENT = 0x11B; @@ -125,6 +141,7 @@ static const uint16_t ACK_FAILURE = 0x401; static const uint16_t EXE_SUCCESS = 0x402; static const uint16_t EXE_FAILURE = 0x403; static const uint16_t TM_MEMORY_READ_REPORT = 0x404; +static const uint16_t TM_FLASH_READ_REPORT = 0x405; static constexpr uint16_t TM_FLASH_DIRECTORY_CONTENT = 0x406; static const uint16_t TM_CAM_CMD_RPT = 0x407; static constexpr uint16_t TM_HK_GET_REPORT = 0x408; @@ -137,6 +154,8 @@ static const char NULL_TERMINATOR = '\0'; static const uint8_t MIN_SPACE_PACKET_LENGTH = 7; static const uint8_t SPACE_PACKET_HEADER_SIZE = 6; +static const uint8_t STATUS_OFFSET = 10; + static constexpr size_t CRC_SIZE = 2; /** @@ -160,9 +179,15 @@ static const uint16_t LENGTH_TC_MEM_READ = 8; * at sheet README */ static constexpr size_t SP_MAX_SIZE = 1024; -static const size_t MAX_REPLY_SIZE = SP_MAX_SIZE * 3; -static const size_t MAX_COMMAND_SIZE = SP_MAX_SIZE; -static const size_t MAX_DATA_SIZE = 1016; +static constexpr size_t MAX_REPLY_SIZE = SP_MAX_SIZE * 3; +static constexpr size_t MAX_COMMAND_SIZE = SP_MAX_SIZE; +// 1016 bytes. +static constexpr size_t SP_MAX_DATA_SIZE = SP_MAX_SIZE - ccsds::HEADER_LEN - CRC_SIZE; +static constexpr size_t FLASH_READ_MIN_OVERHEAD = 16; +// 1000 bytes. +static const size_t MAX_FLASH_READ_DATA_SIZE = SP_MAX_DATA_SIZE - FLASH_READ_MIN_OVERHEAD; +// 1012 bytes, 4 bytes for the write length. +static constexpr size_t MAX_FLASH_WRITE_DATA_SIZE = SP_MAX_DATA_SIZE - sizeof(uint32_t); /** * The replay write sequence command has a maximum delay for the execution report which amounts to @@ -185,7 +210,7 @@ static const uint16_t TC_EXEUTION_DISABLED = 0x5E2; static const uint16_t FLASH_MOUNT_FAILED = 0x5E3; static const uint16_t FLASH_FILE_ALREADY_CLOSED = 0x5E4; static const uint16_t FLASH_FILE_OPEN_FAILED = 0x5E5; -static const uint16_t FLASH_FILE_ALREDY_OPEN = 0x5E6; +static const uint16_t FLASH_FILE_ALREADY_OPEN = 0x5E6; static const uint16_t FLASH_FILE_NOT_OPEN = 0x5E7; static const uint16_t FLASH_UNMOUNT_FAILED = 0x5E8; static const uint16_t HEAP_ALLOCATION_FAILED = 0x5E9; @@ -210,7 +235,7 @@ class TcBase : public ploc::SpTcBase, public MPSoCReturnValuesIF { virtual ~TcBase() = default; // Initial length field of space packet. Will always be updated when packet is created. - static const uint16_t INIT_LENGTH = 2; + static const uint16_t INIT_LENGTH = CRC_SIZE; /** * @brief Constructor @@ -220,47 +245,23 @@ class TcBase : public ploc::SpTcBase, public MPSoCReturnValuesIF { */ 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); } - ReturnValue_t buildPacket() { return buildPacket(nullptr, 0); } - /** - * @brief Function to initialize the space packet - * - * @param commandData Pointer to command specific data - * @param commandDataLen Length of command data - * + * @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 buildPacket(const uint8_t* commandData, size_t commandDataLen) { - payloadStart = spParams.buf + ccsds::HEADER_LEN; - ReturnValue_t res; - if (commandData != nullptr and commandDataLen > 0) { - res = initPacket(commandData, commandDataLen); - if (res != returnvalue::OK) { - return res; - } - } - + ReturnValue_t finishPacket() { updateSpFields(); - res = checkSizeAndSerializeHeader(); + ReturnValue_t res = checkSizeAndSerializeHeader(); if (res != returnvalue::OK) { return res; } return calcAndSetCrc(); } - - protected: - /** - * @brief Must be overwritten by the child class to define the command specific parameters - * - * @param commandData Pointer to received command data - * @param commandDataLen Length of received command data - */ - virtual ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) { - return returnvalue::OK; - } }; /** @@ -278,8 +279,7 @@ class TcMemRead : public TcBase { uint16_t getMemLen() const { return memLen; } - protected: - ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) override { + ReturnValue_t setPayload(const uint8_t* commandData, size_t commandDataLen) { ReturnValue_t result = returnvalue::OK; result = lengthCheck(commandDataLen); if (result != returnvalue::OK) { @@ -325,8 +325,7 @@ class TcMemWrite : public TcBase { TcMemWrite(ploc::SpTcParams params, uint16_t sequenceCount) : TcBase(params, apid::TC_MEM_WRITE, sequenceCount) {} - protected: - ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) override { + ReturnValue_t setPayload(const uint8_t* commandData, size_t commandDataLen) { ReturnValue_t result = returnvalue::OK; result = lengthCheck(commandDataLen); if (result != returnvalue::OK) { @@ -368,72 +367,58 @@ class TcMemWrite : public TcBase { /** * @brief Class to help creation of flash fopen command. */ -class FlashFopen : public ploc::SpTcBase { +class FlashFopen : public TcBase { public: FlashFopen(ploc::SpTcParams params, uint16_t sequenceCount) - : ploc::SpTcBase(params, apid::TC_FLASHFOPEN, sequenceCount) {} + : TcBase(params, apid::TC_FLASHFOPEN, sequenceCount) {} - static const char APPEND = 'a'; - static const char WRITE = 'w'; - static const char READ = 'r'; - - ReturnValue_t createPacket(std::string filename, char accessMode_) { - accessMode = accessMode_; + ReturnValue_t setPayload(std::string filename, uint8_t mode) { + accessMode = mode; size_t nameSize = filename.size(); - spParams.setFullPayloadLen(nameSize + sizeof(NULL_TERMINATOR) + sizeof(accessMode) + CRC_SIZE); + spParams.setFullPayloadLen(256 + sizeof(uint8_t) + CRC_SIZE); ReturnValue_t result = checkPayloadLen(); if (result != returnvalue::OK) { return result; } std::memcpy(payloadStart, filename.c_str(), nameSize); - *(spParams.buf + nameSize) = NULL_TERMINATOR; - std::memcpy(payloadStart + nameSize + sizeof(NULL_TERMINATOR), &accessMode, sizeof(accessMode)); - updateSpFields(); - return calcAndSetCrc(); + // payloadStart[nameSize] = NULL_TERMINATOR; + std::memset(payloadStart + nameSize, 0, 256 - nameSize); + // payloadStart[255] = NULL_TERMINATOR; + payloadStart[256] = accessMode; + return returnvalue::OK; } private: - char accessMode = APPEND; + uint8_t accessMode = FileAccessModes::OPEN_EXISTING; }; /** * @brief Class to help creation of flash fclose command. */ -class FlashFclose : public ploc::SpTcBase { +class FlashFclose : public TcBase { public: FlashFclose(ploc::SpTcParams params, uint16_t sequenceCount) - : ploc::SpTcBase(params, apid::TC_FLASHFCLOSE, sequenceCount) {} - - ReturnValue_t createPacket(std::string filename) { - size_t nameSize = filename.size(); - spParams.setFullPayloadLen(nameSize + sizeof(NULL_TERMINATOR) + CRC_SIZE); - ReturnValue_t result = checkPayloadLen(); - if (result != returnvalue::OK) { - return result; - } - std::memcpy(payloadStart, filename.c_str(), nameSize); - *(payloadStart + nameSize) = NULL_TERMINATOR; - return calcAndSetCrc(); + : TcBase(params, apid::TC_FLASHFCLOSE, sequenceCount) { + spParams.setFullPayloadLen(CRC_SIZE); } }; /** * @brief Class to build flash write space packet. */ -class TcFlashWrite : public ploc::SpTcBase { +class TcFlashWrite : public TcBase { public: TcFlashWrite(ploc::SpTcParams params, uint16_t sequenceCount) - : ploc::SpTcBase(params, apid::TC_FLASHWRITE, sequenceCount) {} + : TcBase(params, apid::TC_FLASHWRITE, sequenceCount) {} - ReturnValue_t buildPacket(const uint8_t* writeData, uint32_t writeLen_) { - ReturnValue_t result = returnvalue::OK; + ReturnValue_t setPayload(const uint8_t* writeData, uint32_t writeLen_) { writeLen = writeLen_; - if (writeLen > MAX_DATA_SIZE) { - sif::debug << "FlashWrite::createPacket: Command data too big" << std::endl; + if (writeLen > MAX_FLASH_WRITE_DATA_SIZE) { + sif::error << "TcFlashWrite: Command data too big" << std::endl; return returnvalue::FAILED; } - spParams.setFullPayloadLen(static_cast(writeLen) + 4 + CRC_SIZE); - result = checkPayloadLen(); + spParams.setFullPayloadLen(sizeof(uint32_t) + static_cast(writeLen) + CRC_SIZE); + ReturnValue_t result = checkPayloadLen(); if (result != returnvalue::OK) { return result; } @@ -443,11 +428,11 @@ class TcFlashWrite : public ploc::SpTcBase { if (result != returnvalue::OK) { return result; } - std::memcpy(payloadStart + sizeof(writeLen), writeData, writeLen); + std::memcpy(payloadStart + sizeof(uint32_t), writeData, writeLen); updateSpFields(); - auto res = checkSizeAndSerializeHeader(); - if (res != returnvalue::OK) { - return res; + result = checkSizeAndSerializeHeader(); + if (result != returnvalue::OK) { + return result; } return calcAndSetCrc(); } @@ -456,15 +441,52 @@ class TcFlashWrite : public ploc::SpTcBase { uint32_t writeLen = 0; }; +class TcFlashRead : public TcBase { + public: + TcFlashRead(ploc::SpTcParams params, uint16_t sequenceCount) + : TcBase(params, apid::TC_FLASHREAD, sequenceCount) {} + + ReturnValue_t setPayload(uint32_t readLen) { + if (readLen > MAX_FLASH_READ_DATA_SIZE) { + sif::error << "TcFlashRead: Read length " << readLen << " too large" << std::endl; + return returnvalue::FAILED; + } + spParams.setFullPayloadLen(sizeof(uint32_t) + CRC_SIZE); + ReturnValue_t result = checkPayloadLen(); + if (result != returnvalue::OK) { + return result; + } + size_t serializedSize = ccsds::HEADER_LEN; + result = SerializeAdapter::serialize(&readLen, payloadStart, &serializedSize, spParams.maxSize, + SerializeIF::Endianness::NETWORK); + if (result != returnvalue::OK) { + return result; + } + updateSpFields(); + result = checkSizeAndSerializeHeader(); + if (result != returnvalue::OK) { + return result; + } + result = calcAndSetCrc(); + if (result != returnvalue::OK) { + return result; + } + readSize = readLen; + return result; + } + + uint32_t readSize = 0; +}; + /** * @brief Class to help creation of flash delete command. */ -class TcFlashDelete : public ploc::SpTcBase { +class TcFlashDelete : public TcBase { public: TcFlashDelete(ploc::SpTcParams params, uint16_t sequenceCount) - : ploc::SpTcBase(params, apid::TC_FLASHDELETE, sequenceCount) {} + : TcBase(params, apid::TC_FLASHDELETE, sequenceCount) {} - ReturnValue_t buildPacket(std::string filename) { + ReturnValue_t setPayload(std::string filename) { size_t nameSize = filename.size(); spParams.setFullPayloadLen(nameSize + sizeof(NULL_TERMINATOR) + CRC_SIZE); auto res = checkPayloadLen(); @@ -503,8 +525,7 @@ class TcReplayStart : public TcBase { TcReplayStart(ploc::SpTcParams params, uint16_t sequenceCount) : TcBase(params, apid::TC_REPLAY_START, sequenceCount) {} - protected: - ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) override { + ReturnValue_t setPayload(const uint8_t* commandData, size_t commandDataLen) { ReturnValue_t result = returnvalue::OK; spParams.setFullPayloadLen(commandDataLen + CRC_SIZE); result = lengthCheck(commandDataLen); @@ -552,8 +573,7 @@ class TcDownlinkPwrOn : public TcBase { TcDownlinkPwrOn(ploc::SpTcParams params, uint16_t sequenceCount) : TcBase(params, apid::TC_DOWNLINK_PWR_ON, sequenceCount) {} - protected: - ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) override { + ReturnValue_t setPayload(const uint8_t* commandData, size_t commandDataLen) { ReturnValue_t result = returnvalue::OK; result = lengthCheck(commandDataLen); if (result != returnvalue::OK) { @@ -626,7 +646,7 @@ class TcGetDirContent : public TcBase { TcGetDirContent(ploc::SpTcParams params, uint16_t sequenceCount) : TcBase(params, apid::TC_FLASH_GET_DIRECTORY_CONTENT, sequenceCount) {} - ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) { + ReturnValue_t setPayload(const uint8_t* commandData, size_t commandDataLen) { ReturnValue_t result = returnvalue::OK; // Yeah it needs to be 256.. even if the path is shorter. spParams.setFullPayloadLen(256 + CRC_SIZE); @@ -659,8 +679,7 @@ class TcReplayWriteSeq : public TcBase { TcReplayWriteSeq(ploc::SpTcParams params, uint16_t sequenceCount) : TcBase(params, apid::TC_REPLAY_WRITE_SEQUENCE, sequenceCount) {} - protected: - ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) override { + ReturnValue_t setPayload(const uint8_t* commandData, size_t commandDataLen) { ReturnValue_t result = returnvalue::OK; spParams.setFullPayloadLen(commandDataLen + sizeof(NULL_TERMINATOR) + CRC_SIZE); result = lengthCheck(commandDataLen); @@ -689,36 +708,69 @@ class TcReplayWriteSeq : public TcBase { /** * @brief Helps to extract the fields of the flash write command from the PUS packet. */ -class FlashWritePusCmd : public MPSoCReturnValuesIF { +class FlashBasePusCmd : public MPSoCReturnValuesIF { public: - FlashWritePusCmd(){}; + FlashBasePusCmd() = default; + virtual ~FlashBasePusCmd() = default; - 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)) { return INVALID_LENGTH; } - obcFile = std::string(reinterpret_cast(commandData)); - if (obcFile.size() > (config::MAX_PATH_SIZE + config::MAX_FILENAME_SIZE)) { + size_t fileLen = strnlen(reinterpret_cast(commandData), commandDataLen); + if (fileLen > (config::MAX_PATH_SIZE + config::MAX_FILENAME_SIZE)) { return FILENAME_TOO_LONG; } - mpsocFile = std::string( - reinterpret_cast(commandData + obcFile.size() + SIZE_NULL_TERMINATOR)); - if (mpsocFile.size() > MAX_FILENAME_SIZE) { + obcFile = std::string(reinterpret_cast(commandData), fileLen); + fileLen = + strnlen(reinterpret_cast(commandData + obcFile.size() + SIZE_NULL_TERMINATOR), + commandDataLen - obcFile.size() - 1); + if (fileLen > MAX_FILENAME_SIZE) { return MPSOC_FILENAME_TOO_LONG; } + mpsocFile = std::string( + reinterpret_cast(commandData + obcFile.size() + SIZE_NULL_TERMINATOR), + fileLen); return returnvalue::OK; } - std::string getObcFile() { return obcFile; } + const std::string& getObcFile() const { return obcFile; } - std::string getMPSoCFile() { return mpsocFile; } + const std::string& getMPSoCFile() const { return mpsocFile; } + + protected: + size_t getParsedSize() const { + return getObcFile().size() + getMPSoCFile().size() + 2 * SIZE_NULL_TERMINATOR; + } + static const size_t SIZE_NULL_TERMINATOR = 1; private: - static const size_t SIZE_NULL_TERMINATOR = 1; - std::string obcFile = ""; - std::string mpsocFile = ""; + std::string obcFile; + std::string mpsocFile; }; +class FlashReadPusCmd : public FlashBasePusCmd { + public: + FlashReadPusCmd(){}; + + ReturnValue_t extractFields(const uint8_t* commandData, size_t commandDataLen) override { + ReturnValue_t result = FlashBasePusCmd::extractFields(commandData, commandDataLen); + if (result != returnvalue::OK) { + return result; + } + if (commandDataLen < (getParsedSize() + 4)) { + return returnvalue::FAILED; + } + size_t deserDummy = 4; + return SerializeAdapter::deSerialize(&readSize, commandData + getParsedSize(), &deserDummy, + SerializeIF::Endianness::NETWORK); + } + + size_t getReadSize() const { return readSize; } + + private: + size_t readSize = 0; +}; /** * @brief Class to build replay stop space packet. */ @@ -754,7 +806,7 @@ class TcCamTakePic : public TcBase { TcCamTakePic(ploc::SpTcParams params, uint16_t sequenceCount) : TcBase(params, apid::TC_CAM_TAKE_PIC, sequenceCount) {} - ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) override { + ReturnValue_t setPayload(const uint8_t* commandData, size_t commandDataLen) { if (commandDataLen > MAX_DATA_LENGTH) { return INVALID_LENGTH; } @@ -783,7 +835,7 @@ class TcSimplexSendFile : public TcBase { TcSimplexSendFile(ploc::SpTcParams params, uint16_t sequenceCount) : TcBase(params, apid::TC_SIMPLEX_SEND_FILE, sequenceCount) {} - ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) override { + ReturnValue_t setPayload(const uint8_t* commandData, size_t commandDataLen) { if (commandDataLen > MAX_DATA_LENGTH) { return INVALID_LENGTH; } @@ -808,7 +860,7 @@ class TcDownlinkDataModulate : public TcBase { TcDownlinkDataModulate(ploc::SpTcParams params, uint16_t sequenceCount) : TcBase(params, apid::TC_DOWNLINK_DATA_MODULATE, sequenceCount) {} - ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) override { + ReturnValue_t setPayload(const uint8_t* commandData, size_t commandDataLen) { if (commandDataLen > MAX_DATA_LENGTH) { return INVALID_LENGTH; } @@ -826,8 +878,7 @@ class TcCamcmdSend : public TcBase { TcCamcmdSend(ploc::SpTcParams params, uint16_t sequenceCount) : TcBase(params, apid::TC_CAM_CMD_SEND, sequenceCount) {} - protected: - ReturnValue_t initPacket(const uint8_t* commandData, size_t commandDataLen) override { + ReturnValue_t setPayload(const uint8_t* commandData, size_t commandDataLen) { if (commandDataLen > MAX_DATA_LENGTH) { return INVALID_LENGTH; } @@ -912,6 +963,9 @@ class HkReport : public StaticLocalDataSet<36> { lp_var_t(sid.objectId, mpsoc::poolid::REBOOT_MPSOC_REQUIRED, this); }; +uint16_t getStatusFromRawData(const uint8_t* data); +std::string getStatusString(uint16_t status); + } // namespace mpsoc #endif /* MISSION_DEVICES_DEVICEDEFINITIONS_PLOCMPSOCDEFINITIONS_H_ */ diff --git a/mission/acs/GyrAdis1650XHandler.cpp b/mission/acs/GyrAdis1650XHandler.cpp index c61187ce..fe10c214 100644 --- a/mission/acs/GyrAdis1650XHandler.cpp +++ b/mission/acs/GyrAdis1650XHandler.cpp @@ -15,7 +15,7 @@ GyrAdis1650XHandler::GyrAdis1650XHandler(object_id_t objectId, object_id_t devic } void GyrAdis1650XHandler::doStartUp() { - if (internalState != InternalState::STARTUP) { + if (internalState == InternalState::NONE) { internalState = InternalState::STARTUP; commandExecuted = false; } @@ -24,13 +24,14 @@ void GyrAdis1650XHandler::doStartUp() { if (not commandExecuted) { warningSwitch = true; breakCountdown.setTimeout(adis1650x::START_UP_TIME); + updatePeriodicReply(true, adis1650x::REPLY); commandExecuted = true; } - if (breakCountdown.hasTimedOut()) { - updatePeriodicReply(true, adis1650x::REPLY); - setMode(MODE_ON); - internalState = InternalState::NONE; - } + } + if (internalState == InternalState::STARTUP_DONE) { + setMode(MODE_ON); + commandExecuted = false; + internalState = InternalState::NONE; } } @@ -61,6 +62,7 @@ ReturnValue_t GyrAdis1650XHandler::buildTransitionDeviceCommand(DeviceCommandId_ return NOTHING_TO_SEND; } *id = adis1650x::REQUEST; + adisRequest.cfg.decRateReg = adis1650x::DEC_RATE; return preparePeriodicRequest(acs::SimpleSensorMode::NORMAL); } case (InternalState::SHUTDOWN): { @@ -91,6 +93,9 @@ ReturnValue_t GyrAdis1650XHandler::scanForReply(const uint8_t *start, size_t rem getMode() == _MODE_POWER_DOWN) { return IGNORE_FULL_PACKET; } + if (internalState == InternalState::STARTUP) { + internalState = InternalState::STARTUP_DONE; + } *foundLen = remainingSize; if (remainingSize != sizeof(acs::Adis1650XReply)) { return returnvalue::FAILED; diff --git a/mission/acs/GyrAdis1650XHandler.h b/mission/acs/GyrAdis1650XHandler.h index 5d906f61..308d472b 100644 --- a/mission/acs/GyrAdis1650XHandler.h +++ b/mission/acs/GyrAdis1650XHandler.h @@ -48,7 +48,7 @@ class GyrAdis1650XHandler : public DeviceHandlerBase { bool warningSwitch = true; - enum class InternalState { NONE, STARTUP, SHUTDOWN }; + enum class InternalState { NONE, STARTUP, STARTUP_DONE, SHUTDOWN }; InternalState internalState = InternalState::STARTUP; bool commandExecuted = false; diff --git a/mission/acs/acsBoardPolling.h b/mission/acs/acsBoardPolling.h index 90f0f19c..9f794fb0 100644 --- a/mission/acs/acsBoardPolling.h +++ b/mission/acs/acsBoardPolling.h @@ -8,11 +8,6 @@ namespace acs { -struct Adis1650XRequest { - SimpleSensorMode mode; - adis1650x::Type type; -}; - struct Adis1650XConfig { uint16_t diagStat; uint16_t filterSetting; @@ -22,6 +17,12 @@ struct Adis1650XConfig { uint16_t prodId; }; +struct Adis1650XRequest { + SimpleSensorMode mode; + adis1650x::Type type; + Adis1650XConfig cfg; +}; + struct Adis1650XData { double sensitivity = 0.0; // Angular velocities in all axes (X, Y and Z) diff --git a/mission/acs/gyroAdisHelpers.cpp b/mission/acs/gyroAdisHelpers.cpp index 0f41b058..5c1446cc 100644 --- a/mission/acs/gyroAdisHelpers.cpp +++ b/mission/acs/gyroAdisHelpers.cpp @@ -52,3 +52,14 @@ double adis1650x::rangMdlToSensitivity(uint16_t rangMdl) { } } } + +void adis1650x::prepareWriteRegCommand(uint8_t regStart, uint16_t val, uint8_t* outBuf, + size_t maxLen) { + if (maxLen < 4) { + return; + } + outBuf[0] = regStart | adis1650x::WRITE_MASK; + outBuf[1] = val & 0xff; + outBuf[2] = (regStart + 1) | adis1650x::WRITE_MASK; + outBuf[3] = (val >> 8) & 0xff; +} diff --git a/mission/acs/gyroAdisHelpers.h b/mission/acs/gyroAdisHelpers.h index 09f0aa1e..f360db76 100644 --- a/mission/acs/gyroAdisHelpers.h +++ b/mission/acs/gyroAdisHelpers.h @@ -16,6 +16,8 @@ enum class BurstModes { }; size_t prepareReadCommand(const uint8_t* regList, size_t len, uint8_t* outBuf, size_t maxLen); +void prepareWriteRegCommand(uint8_t regStart, uint16_t val, uint8_t* outBuf, size_t maxLen); + BurstModes burstModeFromMscCtrl(uint16_t mscCtrl); double rangMdlToSensitivity(uint16_t rangMdl); @@ -92,6 +94,9 @@ static constexpr size_t SENSOR_READOUT_SIZE = 20 + 2; static constexpr uint32_t ADIS_DATASET_ID = READ_SENSOR_DATA; static constexpr uint32_t ADIS_CFG_DATASET_ID = READ_OUT_CONFIG; +static constexpr uint16_t FILT_CTRL = 0x0000; +static constexpr uint16_t DEC_RATE = 0x00C7; + enum GlobCmds : uint8_t { FACTORY_CALIBRATION = 0b0000'0010, SENSOR_SELF_TEST = 0b0000'0100, diff --git a/mission/acs/str/StarTrackerHandler.cpp b/mission/acs/str/StarTrackerHandler.cpp index d40e5fab..cf2a5919 100644 --- a/mission/acs/str/StarTrackerHandler.cpp +++ b/mission/acs/str/StarTrackerHandler.cpp @@ -17,6 +17,7 @@ extern "C" { #include #include "OBSWConfig.h" +#include "eive/definitions.h" std::atomic_bool JCFG_DONE(false); @@ -99,6 +100,19 @@ void StarTrackerHandler::doShutDown() { startupState = StartupState::IDLE; bootState = FwBootState::NONE; solutionSet.setReportingEnabled(false); + { + PoolReadGuard pg(&solutionSet); + solutionSet.caliQw.value = 0.0; + solutionSet.caliQx.value = 0.0; + solutionSet.caliQy.value = 0.0; + solutionSet.caliQz.value = 0.0; + solutionSet.isTrustWorthy = 0; + solutionSet.setValidity(false, true); + } + { + PoolReadGuard pg(&temperatureSet); + temperatureSet.setValidity(false, true); + } reinitNextSetParam = false; setMode(_MODE_POWER_DOWN); } @@ -152,7 +166,7 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu return EXECUTION_FINISHED; } case (startracker::SET_JSON_FILE_NAME): { - if (size > MAX_PATH_SIZE) { + if (size > config::MAX_PATH_SIZE) { return FILE_PATH_TOO_LONG; } paramJsonFile = std::string(reinterpret_cast(data), size); @@ -189,7 +203,7 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu if (result != returnvalue::OK) { return result; } - if (size > MAX_PATH_SIZE + MAX_FILE_NAME) { + if (size > config::MAX_PATH_SIZE + config::MAX_FILENAME_SIZE) { return FILE_PATH_TOO_LONG; } result = strHelper->startImageUpload(std::string(reinterpret_cast(data), size)); @@ -204,7 +218,7 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu if (result != returnvalue::OK) { return result; } - if (size > MAX_PATH_SIZE) { + if (size > config::MAX_PATH_SIZE) { return FILE_PATH_TOO_LONG; } result = @@ -228,14 +242,14 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu return EXECUTION_FINISHED; } case (startracker::CHANGE_IMAGE_DOWNLOAD_FILE): { - if (size > MAX_FILE_NAME) { + if (size > config::MAX_FILENAME_SIZE) { return FILENAME_TOO_LONG; } strHelper->setDownloadImageName(std::string(reinterpret_cast(data), size)); return EXECUTION_FINISHED; } case (startracker::SET_FLASH_READ_FILENAME): { - if (size > MAX_FILE_NAME) { + if (size > config::MAX_FILENAME_SIZE) { return FILENAME_TOO_LONG; } strHelper->setFlashReadFilename(std::string(reinterpret_cast(data), size)); @@ -246,7 +260,7 @@ ReturnValue_t StarTrackerHandler::executeAction(ActionId_t actionId, MessageQueu if (result != returnvalue::OK) { return result; } - if (size > MAX_PATH_SIZE + MAX_FILE_NAME) { + if (size > config::MAX_PATH_SIZE + config::MAX_FILENAME_SIZE) { return FILE_PATH_TOO_LONG; } result = @@ -1568,7 +1582,7 @@ ReturnValue_t StarTrackerHandler::executeFlashReadCommand(const uint8_t* command << std::endl; return result; } - if (commandDataLen - sizeof(startRegion) - sizeof(length) > MAX_PATH_SIZE) { + if (commandDataLen - sizeof(startRegion) - sizeof(length) > config::MAX_PATH_SIZE) { sif::warning << "StarTrackerHandler::executeFlashReadCommand: Received command with invalid" << " path and filename" << std::endl; return FILE_PATH_TOO_LONG; @@ -1708,7 +1722,7 @@ ReturnValue_t StarTrackerHandler::prepareParamCommand(const uint8_t* commandData bool reinitSet) { // Stopwatch watch; ReturnValue_t result = returnvalue::OK; - if (commandDataLen > MAX_PATH_SIZE) { + if (commandDataLen > config::MAX_PATH_SIZE) { return FILE_PATH_TOO_LONG; } if (reinitSet) { diff --git a/mission/acs/str/StarTrackerHandler.h b/mission/acs/str/StarTrackerHandler.h index a74bff44..7bcc9f2a 100644 --- a/mission/acs/str/StarTrackerHandler.h +++ b/mission/acs/str/StarTrackerHandler.h @@ -144,9 +144,6 @@ class StarTrackerHandler : public DeviceHandlerBase { //! [EXPORT] : [COMMENT] Failed to boot star tracker into bootloader mode static const Event BOOTING_BOOTLOADER_FAILED_EVENT = MAKE_EVENT(2, severity::LOW); - static const size_t MAX_PATH_SIZE = 50; - static const size_t MAX_FILE_NAME = 30; - static const uint8_t STATUS_OFFSET = 2; static const uint8_t PARAMS_OFFSET = 2; static const uint8_t TICKS_OFFSET = 3; diff --git a/mission/cfdp/CfdpHandler.cpp b/mission/cfdp/CfdpHandler.cpp index 902097b6..baf501e4 100644 --- a/mission/cfdp/CfdpHandler.cpp +++ b/mission/cfdp/CfdpHandler.cpp @@ -93,6 +93,7 @@ ReturnValue_t CfdpHandler::handleCfdpPacket(TmTcMessage& msg) { return INVALID_PDU_FORMAT; } if (not FileDirectiveReader::checkFileDirective(pduDataField[0])) { + sif::error << "CfdpHandler: Invalid PDU directive field " << pduDataField[0] << std::endl; return INVALID_DIRECTIVE_FIELD; } auto directive = static_cast(pduDataField[0]); diff --git a/mission/com/PersistentLogTmStoreTask.cpp b/mission/com/PersistentLogTmStoreTask.cpp index 77f2bb7d..28545457 100644 --- a/mission/com/PersistentLogTmStoreTask.cpp +++ b/mission/com/PersistentLogTmStoreTask.cpp @@ -42,13 +42,7 @@ ReturnValue_t PersistentLogTmStoreTask::performOperation(uint8_t opCode) { if (not someonesBusy) { TaskFactory::delayTask(100); } else if (vcBusyDuringDump) { - // TODO: Might not be necessary - sif::debug << "VC busy, delaying" << std::endl; TaskFactory::delayTask(10); - } else { - // TODO: Would be best to remove this, but not delaying here can lead to evil issues. - // Polling the PAPB of the PTME core too often leads to scheuduling issues. - TaskFactory::delayTask(2); } } } diff --git a/mission/com/PersistentSingleTmStoreTask.cpp b/mission/com/PersistentSingleTmStoreTask.cpp index 1b77365b..d6f43289 100644 --- a/mission/com/PersistentSingleTmStoreTask.cpp +++ b/mission/com/PersistentSingleTmStoreTask.cpp @@ -24,13 +24,7 @@ ReturnValue_t PersistentSingleTmStoreTask::performOperation(uint8_t opCode) { if (not busy) { TaskFactory::delayTask(100); } else if (dumpContext.vcBusyDuringDump) { - sif::debug << "VC busy, delaying" << std::endl; - // TODO: Might not be necessary TaskFactory::delayTask(10); - } else { - // TODO: Would be best to remove this, but not delaying here can lead to evil issues. - // Polling the PAPB of the PTME core too often leads to scheuduling issues. - TaskFactory::delayTask(2); } } } diff --git a/mission/com/TmStoreTaskBase.cpp b/mission/com/TmStoreTaskBase.cpp index 6598225d..0470dc04 100644 --- a/mission/com/TmStoreTaskBase.cpp +++ b/mission/com/TmStoreTaskBase.cpp @@ -94,13 +94,6 @@ void TmStoreTaskBase::cancelDump(DumpContext& ctx, PersistentTmStore& store, boo ReturnValue_t TmStoreTaskBase::handleOneDump(PersistentTmStoreWithTmQueue& store, DumpContext& dumpContext, bool& dumpPerformed) { ReturnValue_t result = returnvalue::OK; - // The PTME might have been reset an transmitter state change, so there is no point in continuing - // the dump. - // TODO: Will be solved in a cleaner way, this is kind of a hack. - if (not channel.isTxOn()) { - cancelDump(dumpContext, store, false); - return returnvalue::FAILED; - } // It is assumed that the PTME will only be locked for a short period (e.g. to change datarate). if (not channel.isBusy() and not ptmeLocked) { performDump(store, dumpContext, dumpPerformed); @@ -138,25 +131,22 @@ ReturnValue_t TmStoreTaskBase::performDump(PersistentTmStoreWithTmQueue& store, dumpContext.ptmeBusyCounter = 0; tmSinkBusyCd.resetTimer(); ReturnValue_t result = store.getNextDumpPacket(tmReader, fileHasSwapped); - if (result != returnvalue::OK) { - sif::error << "PersistentTmStore: Getting next dump packet failed" << std::endl; - } else if (fileHasSwapped or result == PersistentTmStore::DUMP_DONE) { + if (fileHasSwapped and result == PersistentTmStore::DUMP_DONE) { // This can happen if a file is corrupted and the next file swap completes the dump. dumpDoneHandler(); return returnvalue::OK; + } else if (result != returnvalue::OK) { + sif::error << "PersistentTmStore: Getting next dump packet failed" << std::endl; + return result; } dumpedLen = tmReader.getFullPacketLen(); - // Only write to VC if mode is on, but always confirm the dump. - // If the mode is OFF, it is assumed the PTME is not usable and is not allowed to be written - // (e.g. to confirm a reset or the transmitter is off anyway). - if (mode == MODE_ON) { - result = channel.write(tmReader.getFullData(), dumpedLen); - if (result == DirectTmSinkIF::IS_BUSY) { - sif::warning << "PersistentTmStore: Unexpected VC channel busy" << std::endl; - } else if (result != returnvalue::OK) { - sif::warning << "PersistentTmStore: Unexpected VC channel write failure" << std::endl; - } + result = channel.write(tmReader.getFullData(), dumpedLen); + if (result == DirectTmSinkIF::IS_BUSY) { + sif::warning << "PersistentTmStore: Unexpected VC channel busy" << std::endl; + } else if (result != returnvalue::OK) { + sif::warning << "PersistentTmStore: Unexpected VC channel write failure" << std::endl; } + result = store.confirmDump(tmReader, fileHasSwapped); if ((result == PersistentTmStore::DUMP_DONE or result == returnvalue::OK)) { dumpPerformed = true; diff --git a/mission/com/VirtualChannel.cpp b/mission/com/VirtualChannel.cpp index 8e225674..ff3749a9 100644 --- a/mission/com/VirtualChannel.cpp +++ b/mission/com/VirtualChannel.cpp @@ -11,23 +11,14 @@ ReturnValue_t VirtualChannel::sendNextTm(const uint8_t* data, size_t size) { } ReturnValue_t VirtualChannel::write(const uint8_t* data, size_t size) { - if (txOn) { - return ptme.writeToVc(vcId, data, size); - } - return returnvalue::OK; + return ptme.writeToVc(vcId, data, size); } uint8_t VirtualChannel::getVcid() const { return vcId; } const char* VirtualChannel::getName() const { return vcName.c_str(); } -bool VirtualChannel::isBusy() const { - // Data is discarded, so channel is not busy. - if (not txOn) { - return false; - } - return ptme.isBusy(vcId); -} +bool VirtualChannel::isBusy() const { return ptme.isBusy(vcId); } void VirtualChannel::cancelTransfer() { ptme.cancelTransfer(vcId); } diff --git a/mission/controller/AcsController.cpp b/mission/controller/AcsController.cpp index 0b49de04..04009cb2 100644 --- a/mission/controller/AcsController.cpp +++ b/mission/controller/AcsController.cpp @@ -169,7 +169,7 @@ void AcsController::performSafe() { guidance.getTargetParamsSafe(sunTargetDir); double magMomMtq[3] = {0, 0, 0}, errAng = 0.0; - uint8_t safeCtrlStrat = safeCtrl.safeCtrlStrategy( + acs::SafeModeStrategy safeCtrlStrat = safeCtrl.safeCtrlStrategy( mgmDataProcessed.mgmVecTot.isValid(), not mekfInvalidFlag, gyrDataProcessed.gyrVecTot.isValid(), susDataProcessed.susVecTot.isValid(), acsParameters.safeModeControllerParameters.useMekf, @@ -205,11 +205,13 @@ void AcsController::performSafe() { case (acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL): safeCtrlFailure(0, 1); break; + default: + sif::error << "AcsController: Invalid safe mode strategy for performSafe" << std::endl; + break; } - actuatorCmd.cmdDipolMtq(magMomMtq, cmdDipolMtqs, - *acsParameters.magnetorquerParameter.inverseAlignment, - acsParameters.magnetorquerParameter.dipolMax); + actuatorCmd.cmdDipoleMtq(*acsParameters.magnetorquerParameter.inverseAlignment, + acsParameters.magnetorquerParameter.dipoleMax, magMomMtq, cmdDipoleMtqs); // detumble check and switch if (mekfData.satRotRateMekf.isValid() && acsParameters.safeModeControllerParameters.useMekf && @@ -231,8 +233,8 @@ void AcsController::performSafe() { } updateCtrlValData(errAng, safeCtrlStrat); - updateActuatorCmdData(cmdDipolMtqs); - commandActuators(cmdDipolMtqs[0], cmdDipolMtqs[1], cmdDipolMtqs[2], + updateActuatorCmdData(cmdDipoleMtqs); + commandActuators(cmdDipoleMtqs[0], cmdDipoleMtqs[1], cmdDipoleMtqs[2], acsParameters.magnetorquerParameter.torqueDuration); } @@ -259,7 +261,7 @@ void AcsController::performDetumble() { triggerEvent(acs::MEKF_RECOVERY); mekfInvalidFlag = false; } - uint8_t safeCtrlStrat = detumble.detumbleStrategy( + acs::SafeModeStrategy safeCtrlStrat = detumble.detumbleStrategy( mgmDataProcessed.mgmVecTot.isValid(), gyrDataProcessed.gyrVecTot.isValid(), mgmDataProcessed.mgmVecTotDerivative.isValid(), acsParameters.detumbleParameter.useFullDetumbleLaw); @@ -279,11 +281,13 @@ void AcsController::performDetumble() { case (acs::SafeModeStrategy::SAFECTRL_NO_SENSORS_FOR_CONTROL): safeCtrlFailure(0, 1); break; + default: + sif::error << "AcsController: Invalid safe mode strategy for performDetumble" << std::endl; + break; } - actuatorCmd.cmdDipolMtq(magMomMtq, cmdDipolMtqs, - *acsParameters.magnetorquerParameter.inverseAlignment, - acsParameters.magnetorquerParameter.dipolMax); + actuatorCmd.cmdDipoleMtq(*acsParameters.magnetorquerParameter.inverseAlignment, + acsParameters.magnetorquerParameter.dipoleMax, magMomMtq, cmdDipoleMtqs); if (mekfData.satRotRateMekf.isValid() && VectorOperations::norm(mekfData.satRotRateMekf.value, 3) < @@ -304,8 +308,8 @@ void AcsController::performDetumble() { } disableCtrlValData(); - updateActuatorCmdData(cmdDipolMtqs); - commandActuators(cmdDipolMtqs[0], cmdDipolMtqs[1], cmdDipolMtqs[2], + updateActuatorCmdData(cmdDipoleMtqs); + commandActuators(cmdDipoleMtqs[0], cmdDipoleMtqs[1], cmdDipoleMtqs[2], acsParameters.magnetorquerParameter.torqueDuration); } @@ -349,8 +353,10 @@ void AcsController::performPointingCtrl() { double rwPseudoInv[4][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; result = guidance.getDistributionMatrixRw(&sensorValues, *rwPseudoInv); if (result == returnvalue::FAILED) { - if (multipleRwUnavailableCounter == 5) { + if (multipleRwUnavailableCounter >= + acsParameters.rwHandlingParameters.multipleRwInvalidTimeout) { triggerEvent(acs::MULTIPLE_RW_INVALID); + multipleRwUnavailableCounter = 0; } multipleRwUnavailableCounter++; return; @@ -364,24 +370,26 @@ void AcsController::performPointingCtrl() { // Variables required for setting actuators double torquePtgRws[4] = {0, 0, 0, 0}, rwTrqNs[4] = {0, 0, 0, 0}, torqueRws[4] = {0, 0, 0, 0}, mgtDpDes[3] = {0, 0, 0}; + switch (mode) { case acs::PTG_IDLE: - guidance.targetQuatPtgSun(susDataProcessed.sunIjkModel.value, targetQuat, targetSatRotRate); + guidance.targetQuatPtgSun(now, susDataProcessed.sunIjkModel.value, targetQuat, + targetSatRotRate); guidance.comparePtg(mekfData.quatMekf.value, mekfData.satRotRateMekf.value, targetQuat, targetSatRotRate, errorQuat, errorSatRotRate, errorAngle); ptgCtrl.ptgLaw(&acsParameters.idleModeControllerParameters, errorQuat, errorSatRotRate, *rwPseudoInv, torquePtgRws); - ptgCtrl.ptgNullspace( - &acsParameters.idleModeControllerParameters, &(sensorValues.rw1Set.currSpeed.value), - &(sensorValues.rw2Set.currSpeed.value), &(sensorValues.rw3Set.currSpeed.value), - &(sensorValues.rw4Set.currSpeed.value), rwTrqNs); + ptgCtrl.ptgNullspace(&acsParameters.idleModeControllerParameters, + sensorValues.rw1Set.currSpeed.value, sensorValues.rw2Set.currSpeed.value, + sensorValues.rw3Set.currSpeed.value, sensorValues.rw4Set.currSpeed.value, + rwTrqNs); VectorOperations::add(torquePtgRws, rwTrqNs, torqueRws, 4); actuatorCmd.scalingTorqueRws(torqueRws, acsParameters.rwHandlingParameters.maxTrq); ptgCtrl.ptgDesaturation( &acsParameters.idleModeControllerParameters, mgmDataProcessed.mgmVecTot.value, mgmDataProcessed.mgmVecTot.isValid(), mekfData.satRotRateMekf.value, - &(sensorValues.rw1Set.currSpeed.value), &(sensorValues.rw2Set.currSpeed.value), - &(sensorValues.rw3Set.currSpeed.value), &(sensorValues.rw4Set.currSpeed.value), mgtDpDes); + sensorValues.rw1Set.currSpeed.value, sensorValues.rw2Set.currSpeed.value, + sensorValues.rw3Set.currSpeed.value, sensorValues.rw4Set.currSpeed.value, mgtDpDes); enableAntiStiction = acsParameters.idleModeControllerParameters.enableAntiStiction; break; @@ -395,17 +403,17 @@ void AcsController::performPointingCtrl() { errorSatRotRate, errorAngle); ptgCtrl.ptgLaw(&acsParameters.targetModeControllerParameters, errorQuat, errorSatRotRate, *rwPseudoInv, torquePtgRws); - ptgCtrl.ptgNullspace( - &acsParameters.targetModeControllerParameters, &(sensorValues.rw1Set.currSpeed.value), - &(sensorValues.rw2Set.currSpeed.value), &(sensorValues.rw3Set.currSpeed.value), - &(sensorValues.rw4Set.currSpeed.value), rwTrqNs); + ptgCtrl.ptgNullspace(&acsParameters.targetModeControllerParameters, + sensorValues.rw1Set.currSpeed.value, sensorValues.rw2Set.currSpeed.value, + sensorValues.rw3Set.currSpeed.value, sensorValues.rw4Set.currSpeed.value, + rwTrqNs); VectorOperations::add(torquePtgRws, rwTrqNs, torqueRws, 4); actuatorCmd.scalingTorqueRws(torqueRws, acsParameters.rwHandlingParameters.maxTrq); ptgCtrl.ptgDesaturation( &acsParameters.targetModeControllerParameters, mgmDataProcessed.mgmVecTot.value, mgmDataProcessed.mgmVecTot.isValid(), mekfData.satRotRateMekf.value, - &(sensorValues.rw1Set.currSpeed.value), &(sensorValues.rw2Set.currSpeed.value), - &(sensorValues.rw3Set.currSpeed.value), &(sensorValues.rw4Set.currSpeed.value), mgtDpDes); + sensorValues.rw1Set.currSpeed.value, sensorValues.rw2Set.currSpeed.value, + sensorValues.rw3Set.currSpeed.value, sensorValues.rw4Set.currSpeed.value, mgtDpDes); enableAntiStiction = acsParameters.targetModeControllerParameters.enableAntiStiction; break; @@ -416,17 +424,17 @@ void AcsController::performPointingCtrl() { targetSatRotRate, errorQuat, errorSatRotRate, errorAngle); ptgCtrl.ptgLaw(&acsParameters.gsTargetModeControllerParameters, errorQuat, errorSatRotRate, *rwPseudoInv, torquePtgRws); - ptgCtrl.ptgNullspace( - &acsParameters.gsTargetModeControllerParameters, &(sensorValues.rw1Set.currSpeed.value), - &(sensorValues.rw2Set.currSpeed.value), &(sensorValues.rw3Set.currSpeed.value), - &(sensorValues.rw4Set.currSpeed.value), rwTrqNs); + ptgCtrl.ptgNullspace(&acsParameters.gsTargetModeControllerParameters, + sensorValues.rw1Set.currSpeed.value, sensorValues.rw2Set.currSpeed.value, + sensorValues.rw3Set.currSpeed.value, sensorValues.rw4Set.currSpeed.value, + rwTrqNs); VectorOperations::add(torquePtgRws, rwTrqNs, torqueRws, 4); actuatorCmd.scalingTorqueRws(torqueRws, acsParameters.rwHandlingParameters.maxTrq); ptgCtrl.ptgDesaturation( &acsParameters.gsTargetModeControllerParameters, mgmDataProcessed.mgmVecTot.value, mgmDataProcessed.mgmVecTot.isValid(), mekfData.satRotRateMekf.value, - &(sensorValues.rw1Set.currSpeed.value), &(sensorValues.rw2Set.currSpeed.value), - &(sensorValues.rw3Set.currSpeed.value), &(sensorValues.rw4Set.currSpeed.value), mgtDpDes); + sensorValues.rw1Set.currSpeed.value, sensorValues.rw2Set.currSpeed.value, + sensorValues.rw3Set.currSpeed.value, sensorValues.rw4Set.currSpeed.value, mgtDpDes); enableAntiStiction = acsParameters.gsTargetModeControllerParameters.enableAntiStiction; break; @@ -440,63 +448,61 @@ void AcsController::performPointingCtrl() { errorSatRotRate, errorAngle); ptgCtrl.ptgLaw(&acsParameters.nadirModeControllerParameters, errorQuat, errorSatRotRate, *rwPseudoInv, torquePtgRws); - ptgCtrl.ptgNullspace( - &acsParameters.nadirModeControllerParameters, &(sensorValues.rw1Set.currSpeed.value), - &(sensorValues.rw2Set.currSpeed.value), &(sensorValues.rw3Set.currSpeed.value), - &(sensorValues.rw4Set.currSpeed.value), rwTrqNs); + ptgCtrl.ptgNullspace(&acsParameters.nadirModeControllerParameters, + sensorValues.rw1Set.currSpeed.value, sensorValues.rw2Set.currSpeed.value, + sensorValues.rw3Set.currSpeed.value, sensorValues.rw4Set.currSpeed.value, + rwTrqNs); VectorOperations::add(torquePtgRws, rwTrqNs, torqueRws, 4); actuatorCmd.scalingTorqueRws(torqueRws, acsParameters.rwHandlingParameters.maxTrq); ptgCtrl.ptgDesaturation( &acsParameters.nadirModeControllerParameters, mgmDataProcessed.mgmVecTot.value, mgmDataProcessed.mgmVecTot.isValid(), mekfData.satRotRateMekf.value, - &(sensorValues.rw1Set.currSpeed.value), &(sensorValues.rw2Set.currSpeed.value), - &(sensorValues.rw3Set.currSpeed.value), &(sensorValues.rw4Set.currSpeed.value), mgtDpDes); + sensorValues.rw1Set.currSpeed.value, sensorValues.rw2Set.currSpeed.value, + sensorValues.rw3Set.currSpeed.value, sensorValues.rw4Set.currSpeed.value, mgtDpDes); enableAntiStiction = acsParameters.nadirModeControllerParameters.enableAntiStiction; break; case acs::PTG_INERTIAL: std::memcpy(targetQuat, acsParameters.inertialModeControllerParameters.tgtQuat, - 4 * sizeof(double)); + sizeof(targetQuat)); guidance.comparePtg(mekfData.quatMekf.value, mekfData.satRotRateMekf.value, targetQuat, targetSatRotRate, acsParameters.inertialModeControllerParameters.quatRef, acsParameters.inertialModeControllerParameters.refRotRate, errorQuat, errorSatRotRate, errorAngle); ptgCtrl.ptgLaw(&acsParameters.inertialModeControllerParameters, errorQuat, errorSatRotRate, *rwPseudoInv, torquePtgRws); - ptgCtrl.ptgNullspace( - &acsParameters.inertialModeControllerParameters, &(sensorValues.rw1Set.currSpeed.value), - &(sensorValues.rw2Set.currSpeed.value), &(sensorValues.rw3Set.currSpeed.value), - &(sensorValues.rw4Set.currSpeed.value), rwTrqNs); + ptgCtrl.ptgNullspace(&acsParameters.inertialModeControllerParameters, + sensorValues.rw1Set.currSpeed.value, sensorValues.rw2Set.currSpeed.value, + sensorValues.rw3Set.currSpeed.value, sensorValues.rw4Set.currSpeed.value, + rwTrqNs); VectorOperations::add(torquePtgRws, rwTrqNs, torqueRws, 4); actuatorCmd.scalingTorqueRws(torqueRws, acsParameters.rwHandlingParameters.maxTrq); ptgCtrl.ptgDesaturation( &acsParameters.inertialModeControllerParameters, mgmDataProcessed.mgmVecTot.value, mgmDataProcessed.mgmVecTot.isValid(), mekfData.satRotRateMekf.value, - &(sensorValues.rw1Set.currSpeed.value), &(sensorValues.rw2Set.currSpeed.value), - &(sensorValues.rw3Set.currSpeed.value), &(sensorValues.rw4Set.currSpeed.value), mgtDpDes); + sensorValues.rw1Set.currSpeed.value, sensorValues.rw2Set.currSpeed.value, + sensorValues.rw3Set.currSpeed.value, sensorValues.rw4Set.currSpeed.value, mgtDpDes); enableAntiStiction = acsParameters.inertialModeControllerParameters.enableAntiStiction; break; default: - sif::error << "AcsController: Invalid mode for performPointingCtrl"; + sif::error << "AcsController: Invalid mode for performPointingCtrl" << std::endl; break; } actuatorCmd.cmdSpeedToRws( sensorValues.rw1Set.currSpeed.value, sensorValues.rw2Set.currSpeed.value, - sensorValues.rw3Set.currSpeed.value, sensorValues.rw4Set.currSpeed.value, torqueRws, - cmdSpeedRws, acsParameters.onBoardParams.sampleTime, - acsParameters.rwHandlingParameters.maxRwSpeed, - acsParameters.rwHandlingParameters.inertiaWheel); + sensorValues.rw3Set.currSpeed.value, sensorValues.rw4Set.currSpeed.value, + acsParameters.onBoardParams.sampleTime, acsParameters.rwHandlingParameters.inertiaWheel, + acsParameters.rwHandlingParameters.maxRwSpeed, torqueRws, cmdSpeedRws); if (enableAntiStiction) { ptgCtrl.rwAntistiction(&sensorValues, cmdSpeedRws); } - actuatorCmd.cmdDipolMtq(mgtDpDes, cmdDipolMtqs, - *acsParameters.magnetorquerParameter.inverseAlignment, - acsParameters.magnetorquerParameter.dipolMax); + actuatorCmd.cmdDipoleMtq(*acsParameters.magnetorquerParameter.inverseAlignment, + acsParameters.magnetorquerParameter.dipoleMax, mgtDpDes, cmdDipoleMtqs); updateCtrlValData(targetQuat, errorQuat, errorAngle, targetSatRotRate); - updateActuatorCmdData(torqueRws, cmdSpeedRws, cmdDipolMtqs); - commandActuators(cmdDipolMtqs[0], cmdDipolMtqs[1], cmdDipolMtqs[2], + updateActuatorCmdData(torqueRws, cmdSpeedRws, cmdDipoleMtqs); + commandActuators(cmdDipoleMtqs[0], cmdDipoleMtqs[1], cmdDipoleMtqs[2], acsParameters.magnetorquerParameter.torqueDuration, cmdSpeedRws[0], cmdSpeedRws[1], cmdSpeedRws[2], cmdSpeedRws[3], acsParameters.rwHandlingParameters.rampTime); diff --git a/mission/controller/AcsController.h b/mission/controller/AcsController.h index 6ec26c57..0c8b94bb 100644 --- a/mission/controller/AcsController.h +++ b/mission/controller/AcsController.h @@ -69,7 +69,7 @@ class AcsController : public ExtendedControllerBase, public ReceivesParameterMes bool mekfLost = false; int32_t cmdSpeedRws[4] = {0, 0, 0, 0}; - int16_t cmdDipolMtqs[3] = {0, 0, 0}; + int16_t cmdDipoleMtqs[3] = {0, 0, 0}; #if OBSW_THREAD_TRACING == 1 uint32_t opCounter = 0; diff --git a/mission/controller/ThermalController.cpp b/mission/controller/ThermalController.cpp index 7133dd88..6205ce44 100644 --- a/mission/controller/ThermalController.cpp +++ b/mission/controller/ThermalController.cpp @@ -175,7 +175,7 @@ void ThermalController::performControlOperation() { heaterHandler.getAllSwitchStates(heaterSwitchStateArray); { PoolReadGuard pg(&heaterInfo); - std::memcpy(heaterInfo.heaterSwitchState.value, heaterStates.data(), 8); + std::memcpy(heaterInfo.heaterSwitchState.value, heaterSwitchStateArray.data(), 8); { PoolReadGuard pg2(¤tVecPdu2); if (pg.getReadResult() == returnvalue::OK and pg2.getReadResult() == returnvalue::OK) { @@ -1631,13 +1631,18 @@ bool ThermalController::selectAndReadSensorTemp(HeaterContext& htrCtx) { bool ThermalController::chooseHeater(heater::Switch& switchNr, heater::Switch redSwitchNr) { bool heaterAvailable = true; - if (heaterHandler.getHealth(switchNr) != HasHealthIF::HEALTHY) { - if (heaterHandler.getHealth(redSwitchNr) == HasHealthIF::HEALTHY) { + HasHealthIF::HealthState mainHealth = heaterHandler.getHealth(switchNr); + HasHealthIF::HealthState redHealth = heaterHandler.getHealth(redSwitchNr); + if (mainHealth != HasHealthIF::HEALTHY) { + if (redHealth == HasHealthIF::HEALTHY) { switchNr = redSwitchNr; redSwitchNrInUse = true; } else { heaterAvailable = false; - triggerEvent(tcsCtrl::NO_HEALTHY_HEATER_AVAILABLE, switchNr, redSwitchNr); + // Special case: Ground might command/do something with the heaters, so prevent spam. + if (not(mainHealth == EXTERNAL_CONTROL and redHealth == EXTERNAL_CONTROL)) { + triggerEvent(tcsCtrl::NO_HEALTHY_HEATER_AVAILABLE, switchNr, redSwitchNr); + } } } else { redSwitchNrInUse = false; diff --git a/mission/controller/acs/AcsParameters.cpp b/mission/controller/acs/AcsParameters.cpp index 03500cc3..16e46631 100644 --- a/mission/controller/acs/AcsParameters.cpp +++ b/mission/controller/acs/AcsParameters.cpp @@ -290,6 +290,9 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId, case 0x6: parameterWrapper->set(rwHandlingParameters.rampTime); break; + case 0x7: + parameterWrapper->set(rwHandlingParameters.multipleRwInvalidTimeout); + break; default: return INVALID_IDENTIFIER_ID; } @@ -315,7 +318,7 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId, parameterWrapper->setMatrix(rwMatrices.without4); break; case 0x6: - parameterWrapper->setVector(rwMatrices.nullspace); + parameterWrapper->setVector(rwMatrices.nullspaceVector); break; default: return INVALID_IDENTIFIER_ID; @@ -375,15 +378,18 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId, parameterWrapper->set(idleModeControllerParameters.gainNullspace); break; case 0x5: - parameterWrapper->setVector(idleModeControllerParameters.desatMomentumRef); + parameterWrapper->set(idleModeControllerParameters.nullspaceSpeed); break; case 0x6: - parameterWrapper->set(idleModeControllerParameters.deSatGainFactor); + parameterWrapper->setVector(idleModeControllerParameters.desatMomentumRef); break; case 0x7: - parameterWrapper->set(idleModeControllerParameters.desatOn); + parameterWrapper->set(idleModeControllerParameters.deSatGainFactor); break; case 0x8: + parameterWrapper->set(idleModeControllerParameters.desatOn); + break; + case 0x9: parameterWrapper->set(idleModeControllerParameters.enableAntiStiction); break; default: @@ -408,48 +414,51 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId, parameterWrapper->set(targetModeControllerParameters.gainNullspace); break; case 0x5: - parameterWrapper->setVector(targetModeControllerParameters.desatMomentumRef); + parameterWrapper->set(targetModeControllerParameters.nullspaceSpeed); break; case 0x6: - parameterWrapper->set(targetModeControllerParameters.deSatGainFactor); + parameterWrapper->setVector(targetModeControllerParameters.desatMomentumRef); break; case 0x7: - parameterWrapper->set(targetModeControllerParameters.desatOn); + parameterWrapper->set(targetModeControllerParameters.deSatGainFactor); break; case 0x8: - parameterWrapper->set(targetModeControllerParameters.enableAntiStiction); + parameterWrapper->set(targetModeControllerParameters.desatOn); break; case 0x9: - parameterWrapper->setVector(targetModeControllerParameters.refDirection); + parameterWrapper->set(targetModeControllerParameters.enableAntiStiction); break; case 0xA: - parameterWrapper->setVector(targetModeControllerParameters.refRotRate); + parameterWrapper->setVector(targetModeControllerParameters.refDirection); break; case 0xB: - parameterWrapper->setVector(targetModeControllerParameters.quatRef); + parameterWrapper->setVector(targetModeControllerParameters.refRotRate); break; case 0xC: - parameterWrapper->set(targetModeControllerParameters.timeElapsedMax); + parameterWrapper->setVector(targetModeControllerParameters.quatRef); break; case 0xD: - parameterWrapper->set(targetModeControllerParameters.latitudeTgt); + parameterWrapper->set(targetModeControllerParameters.timeElapsedMax); break; case 0xE: - parameterWrapper->set(targetModeControllerParameters.longitudeTgt); + parameterWrapper->set(targetModeControllerParameters.latitudeTgt); break; case 0xF: - parameterWrapper->set(targetModeControllerParameters.altitudeTgt); + parameterWrapper->set(targetModeControllerParameters.longitudeTgt); break; case 0x10: - parameterWrapper->set(targetModeControllerParameters.avoidBlindStr); + parameterWrapper->set(targetModeControllerParameters.altitudeTgt); break; case 0x11: - parameterWrapper->set(targetModeControllerParameters.blindAvoidStart); + parameterWrapper->set(targetModeControllerParameters.avoidBlindStr); break; case 0x12: - parameterWrapper->set(targetModeControllerParameters.blindAvoidStop); + parameterWrapper->set(targetModeControllerParameters.blindAvoidStart); break; case 0x13: + parameterWrapper->set(targetModeControllerParameters.blindAvoidStop); + break; + case 0x14: parameterWrapper->set(targetModeControllerParameters.blindRotRate); break; default: @@ -474,30 +483,33 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId, parameterWrapper->set(gsTargetModeControllerParameters.gainNullspace); break; case 0x5: - parameterWrapper->setVector(gsTargetModeControllerParameters.desatMomentumRef); + parameterWrapper->set(gsTargetModeControllerParameters.nullspaceSpeed); break; case 0x6: - parameterWrapper->set(gsTargetModeControllerParameters.deSatGainFactor); + parameterWrapper->setVector(gsTargetModeControllerParameters.desatMomentumRef); break; case 0x7: - parameterWrapper->set(gsTargetModeControllerParameters.desatOn); + parameterWrapper->set(gsTargetModeControllerParameters.deSatGainFactor); break; case 0x8: - parameterWrapper->set(gsTargetModeControllerParameters.enableAntiStiction); + parameterWrapper->set(gsTargetModeControllerParameters.desatOn); break; case 0x9: - parameterWrapper->setVector(gsTargetModeControllerParameters.refDirection); + parameterWrapper->set(gsTargetModeControllerParameters.enableAntiStiction); break; case 0xA: - parameterWrapper->set(gsTargetModeControllerParameters.timeElapsedMax); + parameterWrapper->setVector(gsTargetModeControllerParameters.refDirection); break; case 0xB: - parameterWrapper->set(gsTargetModeControllerParameters.latitudeTgt); + parameterWrapper->set(gsTargetModeControllerParameters.timeElapsedMax); break; case 0xC: - parameterWrapper->set(gsTargetModeControllerParameters.longitudeTgt); + parameterWrapper->set(gsTargetModeControllerParameters.latitudeTgt); break; case 0xD: + parameterWrapper->set(gsTargetModeControllerParameters.longitudeTgt); + break; + case 0xE: parameterWrapper->set(gsTargetModeControllerParameters.altitudeTgt); break; default: @@ -522,24 +534,30 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId, parameterWrapper->set(nadirModeControllerParameters.gainNullspace); break; case 0x5: - parameterWrapper->setVector(nadirModeControllerParameters.desatMomentumRef); + parameterWrapper->set(nadirModeControllerParameters.nullspaceSpeed); break; case 0x6: - parameterWrapper->set(nadirModeControllerParameters.deSatGainFactor); + parameterWrapper->setVector(nadirModeControllerParameters.desatMomentumRef); break; case 0x7: - parameterWrapper->set(nadirModeControllerParameters.desatOn); + parameterWrapper->set(nadirModeControllerParameters.deSatGainFactor); break; case 0x8: - parameterWrapper->set(nadirModeControllerParameters.enableAntiStiction); + parameterWrapper->set(nadirModeControllerParameters.desatOn); break; case 0x9: - parameterWrapper->setVector(nadirModeControllerParameters.refDirection); + parameterWrapper->set(nadirModeControllerParameters.enableAntiStiction); break; case 0xA: + parameterWrapper->setVector(nadirModeControllerParameters.refDirection); + break; + case 0xB: parameterWrapper->setVector(nadirModeControllerParameters.quatRef); break; case 0xC: + parameterWrapper->setVector(nadirModeControllerParameters.refRotRate); + break; + case 0xD: parameterWrapper->set(nadirModeControllerParameters.timeElapsedMax); break; default: @@ -564,21 +582,24 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId, parameterWrapper->set(inertialModeControllerParameters.gainNullspace); break; case 0x5: - parameterWrapper->setVector(inertialModeControllerParameters.desatMomentumRef); + parameterWrapper->set(inertialModeControllerParameters.nullspaceSpeed); break; case 0x6: - parameterWrapper->set(inertialModeControllerParameters.deSatGainFactor); + parameterWrapper->setVector(inertialModeControllerParameters.desatMomentumRef); break; case 0x7: - parameterWrapper->set(inertialModeControllerParameters.desatOn); + parameterWrapper->set(inertialModeControllerParameters.deSatGainFactor); break; case 0x8: - parameterWrapper->set(inertialModeControllerParameters.enableAntiStiction); + parameterWrapper->set(inertialModeControllerParameters.desatOn); break; case 0x9: - parameterWrapper->setVector(inertialModeControllerParameters.tgtQuat); + parameterWrapper->set(inertialModeControllerParameters.enableAntiStiction); break; case 0xA: + parameterWrapper->setVector(inertialModeControllerParameters.tgtQuat); + break; + case 0xB: parameterWrapper->setVector(inertialModeControllerParameters.refRotRate); break; case 0xC: @@ -690,7 +711,7 @@ ReturnValue_t AcsParameters::getParameter(uint8_t domainId, uint8_t parameterId, parameterWrapper->setMatrix(magnetorquerParameter.inverseAlignment); break; case 0x5: - parameterWrapper->set(magnetorquerParameter.dipolMax); + parameterWrapper->set(magnetorquerParameter.dipoleMax); break; case 0x6: parameterWrapper->set(magnetorquerParameter.torqueDuration); diff --git a/mission/controller/acs/AcsParameters.h b/mission/controller/acs/AcsParameters.h index 9600ca7e..15725f2f 100644 --- a/mission/controller/acs/AcsParameters.h +++ b/mission/controller/acs/AcsParameters.h @@ -781,9 +781,9 @@ class AcsParameters : public HasParametersIF { /* var = sigma^2, sigma = RND*sqrt(freq), following values are RND^2 and not var as freq is * assumed to be equal for the same class of sensors */ - float gyr02variance[3] = {pow(3.0e-3, 2), // RND_x = 3.0e-3 deg/s/sqrt(Hz) rms - pow(3.0e-3, 2), // RND_y = 3.0e-3 deg/s/sqrt(Hz) rms - pow(4.3e-3, 2)}; // RND_z = 4.3e-3 deg/s/sqrt(Hz) rms + float gyr02variance[3] = {pow(4.6e-3, 2), // RND_x = 3.0e-3 deg/s/sqrt(Hz) rms + pow(4.6e-3, 2), // RND_y = 3.0e-3 deg/s/sqrt(Hz) rms + pow(6.1e-3, 2)}; // RND_z = 4.3e-3 deg/s/sqrt(Hz) rms float gyr13variance[3] = {pow(11e-3, 2), pow(11e-3, 2), pow(11e-3, 2)}; uint8_t preferAdis = false; float gyrFilterWeight = 0.6; @@ -798,6 +798,8 @@ class AcsParameters : public HasParametersIF { double stictionTorque = 0.0006; uint16_t rampTime = 10; + + uint32_t multipleRwInvalidTimeout = 25; } rwHandlingParameters; struct RwMatrices { @@ -814,7 +816,7 @@ class AcsParameters : public HasParametersIF { {1.0864, 0, 0}, {-0.5432, -0.5432, 1.2797}, {0, 0, 0}, {-0.5432, 0.5432, 1.2797}}; double without4[4][3] = { {0.5432, 0.5432, 1.2797}, {0, -1.0864, 0}, {-0.5432, 0.5432, 1.2797}, {0, 0, 0}}; - double nullspace[4] = {-0.5000, 0.5000, -0.5000, 0.5000}; + double nullspaceVector[4] = {-1, 1, -1, 1}; } rwMatrices; struct SafeModeControllerParameters { @@ -838,7 +840,9 @@ class AcsParameters : public HasParametersIF { double om = 0.3; double omMax = 1 * M_PI / 180; double qiMin = 0.1; + double gainNullspace = 0.01; + double nullspaceSpeed = 32500; // 0.1 RPM double desatMomentumRef[3] = {0, 0, 0}; double deSatGainFactor = 1000; @@ -931,7 +935,7 @@ class AcsParameters : public HasParametersIF { double mtq2orientationMatrix[3][3] = {{0, 0, 1}, {0, 1, 0}, {-1, 0, 0}}; double alignmentMatrixMtq[3][3] = {{0, 0, -1}, {-1, 0, 0}, {0, 1, 0}}; double inverseAlignment[3][3] = {{0, -1, 0}, {0, 0, 1}, {-1, 0, 0}}; - double dipolMax = 0.2; // [Am^2] + double dipoleMax = 0.2; // [Am^2] uint16_t torqueDuration = 300; // [ms] } magnetorquerParameter; diff --git a/mission/controller/acs/ActuatorCmd.cpp b/mission/controller/acs/ActuatorCmd.cpp index d2fe2d65..0fb8bdf5 100644 --- a/mission/controller/acs/ActuatorCmd.cpp +++ b/mission/controller/acs/ActuatorCmd.cpp @@ -5,11 +5,6 @@ #include #include -#include - -#include "util/CholeskyDecomposition.h" -#include "util/MathOperations.h" - ActuatorCmd::ActuatorCmd() {} ActuatorCmd::~ActuatorCmd() {} @@ -25,24 +20,30 @@ void ActuatorCmd::scalingTorqueRws(double *rwTrq, double maxTorque) { } } -void ActuatorCmd::cmdSpeedToRws(int32_t speedRw0, int32_t speedRw1, int32_t speedRw2, - int32_t speedRw3, const double *rwTorque, int32_t *rwCmdSpeed, - double sampleTime, int32_t maxRwSpeed, double inertiaWheel) { - using namespace Math; - - // Calculating the commanded speed in RPM for every reaction wheel +void ActuatorCmd::cmdSpeedToRws(const int32_t speedRw0, const int32_t speedRw1, + const int32_t speedRw2, const int32_t speedRw3, + const double sampleTime, const double inertiaWheel, + const int32_t maxRwSpeed, const double *rwTorque, + int32_t *rwCmdSpeed) { + // group RW speed values (in 0.1 [RPM]) in vector int32_t speedRws[4] = {speedRw0, speedRw1, speedRw2, speedRw3}; + + // calculate required RW speed as sum of current RW speed and RW speed delta + // delta w_rw = delta t / I_RW * torque_RW [rad/s] double deltaSpeed[4] = {0, 0, 0, 0}; - double radToRpm = 60 / (2 * PI); // factor for conversion to RPM - // W_RW = Torque_RW / I_RW * delta t [rad/s] - double factor = sampleTime / inertiaWheel * radToRpm; - int32_t deltaSpeedInt[4] = {0, 0, 0, 0}; + const double factor = sampleTime / inertiaWheel * RAD_PER_SEC_TO_RPM * 10; VectorOperations::mulScalar(rwTorque, factor, deltaSpeed, 4); + + // convert double to int32 + int32_t deltaSpeedInt[4] = {0, 0, 0, 0}; for (int i = 0; i < 4; i++) { deltaSpeedInt[i] = std::round(deltaSpeed[i]); } + + // sum of current RW speed and RW speed delta VectorOperations::add(speedRws, deltaSpeedInt, rwCmdSpeed, 4); - VectorOperations::mulScalar(rwCmdSpeed, 10, rwCmdSpeed, 4); + + // crop values which would exceed the maximum possible RPM for (uint8_t i = 0; i < 4; i++) { if (rwCmdSpeed[i] > maxRwSpeed) { rwCmdSpeed[i] = maxRwSpeed; @@ -52,24 +53,25 @@ void ActuatorCmd::cmdSpeedToRws(int32_t speedRw0, int32_t speedRw1, int32_t spee } } -void ActuatorCmd::cmdDipolMtq(const double *dipolMoment, int16_t *dipolMomentActuator, - const double *inverseAlignment, double maxDipol) { - // Convert to actuator frame - double dipolMomentActuatorDouble[3] = {0, 0, 0}; - MatrixOperations::multiply(inverseAlignment, dipolMoment, dipolMomentActuatorDouble, 3, 3, - 1); - // Scaling along largest element if dipol exceeds maximum +void ActuatorCmd::cmdDipoleMtq(const double *inverseAlignment, const double maxDipole, + const double *dipoleMoment, int16_t *dipoleMomentActuator) { + // convert to actuator frame + double dipoleMomentActuatorDouble[3] = {0, 0, 0}; + MatrixOperations::multiply(inverseAlignment, dipoleMoment, dipoleMomentActuatorDouble, 3, + 3, 1); + // scaling along largest element if dipole exceeds maximum uint8_t maxIdx = 0; - VectorOperations::maxAbsValue(dipolMomentActuatorDouble, 3, &maxIdx); - double maxAbsValue = abs(dipolMomentActuatorDouble[maxIdx]); - if (maxAbsValue > maxDipol) { - double scalingFactor = maxDipol / maxAbsValue; - VectorOperations::mulScalar(dipolMomentActuatorDouble, scalingFactor, - dipolMomentActuatorDouble, 3); + VectorOperations::maxAbsValue(dipoleMomentActuatorDouble, 3, &maxIdx); + double maxAbsValue = std::abs(dipoleMomentActuatorDouble[maxIdx]); + if (maxAbsValue > maxDipole) { + double scalingFactor = maxDipole / maxAbsValue; + VectorOperations::mulScalar(dipoleMomentActuatorDouble, scalingFactor, + dipoleMomentActuatorDouble, 3); } // scale dipole from 1 Am^2 to 1e^-4 Am^2 - VectorOperations::mulScalar(dipolMomentActuatorDouble, 1e4, dipolMomentActuatorDouble, 3); + VectorOperations::mulScalar(dipoleMomentActuatorDouble, 1e4, dipoleMomentActuatorDouble, + 3); for (int i = 0; i < 3; i++) { - dipolMomentActuator[i] = std::round(dipolMomentActuatorDouble[i]); + dipoleMomentActuator[i] = std::round(dipoleMomentActuatorDouble[i]); } } diff --git a/mission/controller/acs/ActuatorCmd.h b/mission/controller/acs/ActuatorCmd.h index 5d5d47f3..b14a4a25 100644 --- a/mission/controller/acs/ActuatorCmd.h +++ b/mission/controller/acs/ActuatorCmd.h @@ -1,9 +1,7 @@ #ifndef ACTUATORCMD_H_ #define ACTUATORCMD_H_ -#include "MultiplicativeKalmanFilter.h" -#include "SensorProcessing.h" -#include "SensorValues.h" +#include class ActuatorCmd { public: @@ -19,29 +17,30 @@ class ActuatorCmd { void scalingTorqueRws(double *rwTrq, double maxTorque); /* - * @brief: cmdSpeedToRws() will set the maximum possible torque for the reaction - * wheels, also will calculate the needed revolutions per minute for the RWs, which will be given - * as Input to the RWs - * @param: rwTrqIn given torque from pointing controller - * rwTrqNS Nullspace torque + * @brief: cmdSpeedToRws() Calculates the RPM for the reaction wheel configuration, + * given the required torque calculated by the controller. Will also scale down the RPM of the + * wheels if they exceed the maximum possible RPM + * @param: rwTrq given torque from pointing controller * rwCmdSpeed output revolutions per minute for every * reaction wheel */ - void cmdSpeedToRws(int32_t speedRw0, int32_t speedRw1, int32_t speedRw2, int32_t speedRw3, - const double *rwTorque, int32_t *rwCmdSpeed, double sampleTime, - int32_t maxRwSpeed, double inertiaWheel); + void cmdSpeedToRws(const int32_t speedRw0, const int32_t speedRw1, const int32_t speedRw2, + const int32_t speedRw3, const double sampleTime, const double inertiaWheel, + const int32_t maxRwSpeed, const double *rwTorque, int32_t *rwCmdSpeed); /* - * @brief: cmdDipolMtq() gives the commanded dipol moment for the magnetorques + * @brief: cmdDipoleMtq() gives the commanded dipole moment for the + * magnetorquer * - * @param: dipolMoment given dipol moment in spacecraft frame - * dipolMomentActuator resulting dipol moment in actuator reference frame + * @param: dipoleMoment given dipole moment in spacecraft frame + * dipoleMomentActuator resulting dipole moment in actuator reference frame */ - void cmdDipolMtq(const double *dipolMoment, int16_t *dipolMomentActuator, - const double *inverseAlignment, double maxDipol); + void cmdDipoleMtq(const double *inverseAlignment, const double maxDipole, + const double *dipoleMoment, int16_t *dipoleMomentActuator); protected: private: + static constexpr double RAD_PER_SEC_TO_RPM = 60 / (2 * M_PI); }; #endif /* ACTUATORCMD_H_ */ diff --git a/mission/controller/acs/Guidance.cpp b/mission/controller/acs/Guidance.cpp index 79c6b416..1d82d317 100644 --- a/mission/controller/acs/Guidance.cpp +++ b/mission/controller/acs/Guidance.cpp @@ -266,7 +266,8 @@ void Guidance::targetQuatPtgGs(timeval now, double posSatE[3], double sunDirI[3] targetRotationRate(timeElapsedMax, now, targetQuat, targetSatRotRate); } -void Guidance::targetQuatPtgSun(double sunDirI[3], double targetQuat[4], double refSatRate[3]) { +void Guidance::targetQuatPtgSun(timeval now, double sunDirI[3], double targetQuat[4], + double targetSatRotRate[3]) { //------------------------------------------------------------------------------------- // Calculation of target quaternion to sun //------------------------------------------------------------------------------------- @@ -296,9 +297,8 @@ void Guidance::targetQuatPtgSun(double sunDirI[3], double targetQuat[4], double //---------------------------------------------------------------------------- // Calculation of reference rotation rate //---------------------------------------------------------------------------- - refSatRate[0] = 0; - refSatRate[1] = 0; - refSatRate[2] = 0; + int8_t timeElapsedMax = acsParameters->gsTargetModeControllerParameters.timeElapsedMax; + targetRotationRate(timeElapsedMax, now, targetQuat, targetSatRotRate); } void Guidance::targetQuatPtgNadirSingleAxis(timeval now, double posSatE[3], double quatBI[4], @@ -412,7 +412,7 @@ void Guidance::targetQuatPtgNadirThreeAxes(timeval now, double posSatE[3], doubl void Guidance::comparePtg(double currentQuat[4], double currentSatRotRate[3], double targetQuat[4], double targetSatRotRate[3], double refQuat[4], double refSatRotRate[3], - double errorQuat[4], double errorSatRotRate[3], double errorAngle) { + double errorQuat[4], double errorSatRotRate[3], double &errorAngle) { // First calculate error quaternion between current and target orientation QuaternionOperations::multiply(currentQuat, targetQuat, errorQuat); // Last calculate add rotation from reference quaternion @@ -424,26 +424,17 @@ void Guidance::comparePtg(double currentQuat[4], double currentSatRotRate[3], do // Calculate error angle errorAngle = QuaternionOperations::getAngle(errorQuat, true); - // Only give back error satellite rotational rate if orientation has already been aquired - if (errorAngle < 2. / 180. * M_PI) { - // First combine the target and reference satellite rotational rates - double combinedRefSatRotRate[3] = {0, 0, 0}; - VectorOperations::add(targetSatRotRate, refSatRotRate, combinedRefSatRotRate, 3); - // Then substract the combined required satellite rotational rates from the actual rate - VectorOperations::subtract(currentSatRotRate, combinedRefSatRotRate, errorSatRotRate, - 3); - } else { - // If orientation has not been aquired yet set satellite rotational rate to zero - errorSatRotRate = 0; - } - - // target flag in matlab, importance, does look like it only gives feedback if pointing control is - // under 150 arcsec ?? + // Calculate error satellite rotational rate + // First combine the target and reference satellite rotational rates + double combinedRefSatRotRate[3] = {0, 0, 0}; + VectorOperations::add(targetSatRotRate, refSatRotRate, combinedRefSatRotRate, 3); + // Then subtract the combined required satellite rotational rates from the actual rate + VectorOperations::subtract(currentSatRotRate, combinedRefSatRotRate, errorSatRotRate, 3); } void Guidance::comparePtg(double currentQuat[4], double currentSatRotRate[3], double targetQuat[4], double targetSatRotRate[3], double errorQuat[4], - double errorSatRotRate[3], double errorAngle) { + double errorSatRotRate[3], double &errorAngle) { // First calculate error quaternion between current and target orientation QuaternionOperations::multiply(currentQuat, targetQuat, errorQuat); // Keep scalar part of quaternion positive @@ -453,17 +444,8 @@ void Guidance::comparePtg(double currentQuat[4], double currentSatRotRate[3], do // Calculate error angle errorAngle = QuaternionOperations::getAngle(errorQuat, true); - // Only give back error satellite rotational rate if orientation has already been aquired - if (errorAngle < 2. / 180. * M_PI) { - // Then substract the combined required satellite rotational rates from the actual rate - VectorOperations::subtract(currentSatRotRate, targetSatRotRate, errorSatRotRate, 3); - } else { - // If orientation has not been aquired yet set satellite rotational rate to zero - errorSatRotRate = 0; - } - - // target flag in matlab, importance, does look like it only gives feedback if pointing control is - // under 150 arcsec ?? + // Calculate error satellite rotational rate + VectorOperations::subtract(currentSatRotRate, targetSatRotRate, errorSatRotRate, 3); } void Guidance::targetRotationRate(int8_t timeElapsedMax, timeval now, double quatInertialTarget[4], @@ -471,20 +453,25 @@ void Guidance::targetRotationRate(int8_t timeElapsedMax, timeval now, double qua //------------------------------------------------------------------------------------- // Calculation of target rotation rate //------------------------------------------------------------------------------------- - double timeElapsed = now.tv_sec + now.tv_usec * pow(10, -6) - - (timeSavedQuaternion.tv_sec + - timeSavedQuaternion.tv_usec * pow((double)timeSavedQuaternion.tv_usec, -6)); + double timeElapsed = now.tv_sec + now.tv_usec * 1e-6 - + (timeSavedQuaternion.tv_sec + timeSavedQuaternion.tv_usec * 1e-6); + if (VectorOperations::norm(savedQuaternion, 4) == 0) { + std::memcpy(savedQuaternion, quatInertialTarget, sizeof(savedQuaternion)); + } if (timeElapsed < timeElapsedMax) { + double q[4] = {0, 0, 0, 0}, qS[4] = {0, 0, 0, 0}; + QuaternionOperations::inverse(quatInertialTarget, q); + QuaternionOperations::inverse(savedQuaternion, qS); double qDiff[4] = {0, 0, 0, 0}; - VectorOperations::subtract(quatInertialTarget, savedQuaternion, qDiff, 4); + VectorOperations::subtract(q, qS, qDiff, 4); VectorOperations::mulScalar(qDiff, 1 / timeElapsed, qDiff, 4); - double tgtQuatVec[3] = {quatInertialTarget[0], quatInertialTarget[1], quatInertialTarget[2]}, - qDiffVec[3] = {qDiff[0], qDiff[1], qDiff[2]}; + double tgtQuatVec[3] = {q[0], q[1], q[2]}; + double qDiffVec[3] = {qDiff[0], qDiff[1], qDiff[2]}; double sum1[3] = {0, 0, 0}, sum2[3] = {0, 0, 0}, sum3[3] = {0, 0, 0}, sum[3] = {0, 0, 0}; - VectorOperations::cross(quatInertialTarget, qDiff, sum1); + VectorOperations::cross(tgtQuatVec, qDiffVec, sum1); VectorOperations::mulScalar(tgtQuatVec, qDiff[3], sum2, 3); - VectorOperations::mulScalar(qDiffVec, quatInertialTarget[3], sum3, 3); + VectorOperations::mulScalar(qDiffVec, q[3], sum3, 3); VectorOperations::add(sum1, sum2, sum, 3); VectorOperations::subtract(sum, sum3, sum, 3); double omegaRefNew[3] = {0, 0, 0}; @@ -531,10 +518,6 @@ ReturnValue_t Guidance::getDistributionMatrixRw(ACS::SensorValues *sensorValues, std::memcpy(rwPseudoInv, acsParameters->rwMatrices.without4, 12 * sizeof(double)); return returnvalue::OK; } else { - // @note: This one takes the normal pseudoInverse of all four raction wheels valid. - // Does not make sense, but is implemented that way in MATLAB ?! - // Thought: It does not really play a role, because in case there are more then one - // reaction wheel invalid the pointing control is destined to fail. return returnvalue::FAILED; } } diff --git a/mission/controller/acs/Guidance.h b/mission/controller/acs/Guidance.h index a52c476a..7b81e411 100644 --- a/mission/controller/acs/Guidance.h +++ b/mission/controller/acs/Guidance.h @@ -15,7 +15,7 @@ class Guidance { void getTargetParamsSafe(double sunTargetSafe[3]); ReturnValue_t solarArrayDeploymentComplete(); - // Function to get the target quaternion and refence rotation rate from gps position and + // Function to get the target quaternion and reference rotation rate from gps position and // position of the ground station void targetQuatPtgSingleAxis(timeval now, double posSatE[3], double velSatE[3], double sunDirI[3], double refDirB[3], double quatBI[4], double targetQuat[4], @@ -25,9 +25,10 @@ class Guidance { void targetQuatPtgGs(timeval now, double posSatE[3], double sunDirI[3], double quatIX[4], double targetSatRotRate[3]); - // Function to get the target quaternion and refence rotation rate for sun pointing after ground + // Function to get the target quaternion and reference rotation rate for sun pointing after ground // station - void targetQuatPtgSun(double sunDirI[3], double targetQuat[4], double refSatRate[3]); + void targetQuatPtgSun(timeval now, double sunDirI[3], double targetQuat[4], + double targetSatRotRate[3]); // Function to get the target quaternion and refence rotation rate from gps position for Nadir // pointing @@ -37,15 +38,15 @@ class Guidance { double targetQuat[4], double refSatRate[3]); // @note: Calculates the error quaternion between the current orientation and the target - // quaternion, considering a reference quaternion. Additionally the difference between the actual + // quaternion, considering a reference quaternion. Additionally the difference between the actual // and a desired satellite rotational rate is calculated, again considering a reference rotational // rate. Lastly gives back the error angle of the error quaternion. void comparePtg(double currentQuat[4], double currentSatRotRate[3], double targetQuat[4], double targetSatRotRate[3], double refQuat[4], double refSatRotRate[3], - double errorQuat[4], double errorSatRotRate[3], double errorAngle); + double errorQuat[4], double errorSatRotRate[3], double &errorAngle); void comparePtg(double currentQuat[4], double currentSatRotRate[3], double targetQuat[4], double targetSatRotRate[3], double errorQuat[4], double errorSatRotRate[3], - double errorAngle); + double &errorAngle); void targetRotationRate(int8_t timeElapsedMax, timeval now, double quatInertialTarget[4], double *targetSatRotRate); diff --git a/mission/controller/acs/Navigation.cpp b/mission/controller/acs/Navigation.cpp index 9e8b3719..7c822409 100644 --- a/mission/controller/acs/Navigation.cpp +++ b/mission/controller/acs/Navigation.cpp @@ -19,9 +19,7 @@ ReturnValue_t Navigation::useMekf(ACS::SensorValues *sensorValues, acsctrl::MekfData *mekfData, AcsParameters *acsParameters) { double quatIB[4] = {sensorValues->strSet.caliQx.value, sensorValues->strSet.caliQy.value, sensorValues->strSet.caliQz.value, sensorValues->strSet.caliQw.value}; - bool quatIBValid = sensorValues->strSet.caliQx.isValid() && - sensorValues->strSet.caliQy.isValid() && - sensorValues->strSet.caliQz.isValid() && sensorValues->strSet.caliQw.isValid(); + bool quatIBValid = sensorValues->strSet.isTrustWorthy.value; if (mekfStatus == MultiplicativeKalmanFilter::MEKF_UNINITIALIZED) { mekfStatus = multiplicativeKalmanFilter.init( diff --git a/mission/controller/acs/control/Detumble.cpp b/mission/controller/acs/control/Detumble.cpp index 9ca20862..8f422ec1 100644 --- a/mission/controller/acs/control/Detumble.cpp +++ b/mission/controller/acs/control/Detumble.cpp @@ -7,8 +7,10 @@ Detumble::Detumble() {} Detumble::~Detumble() {} -uint8_t Detumble::detumbleStrategy(const bool magFieldValid, const bool satRotRateValid, - const bool magFieldRateValid, const bool useFullDetumbleLaw) { +acs::SafeModeStrategy Detumble::detumbleStrategy(const bool magFieldValid, + const bool satRotRateValid, + const bool magFieldRateValid, + const bool useFullDetumbleLaw) { if (not magFieldValid) { return acs::SafeModeStrategy::SAFECTRL_NO_MAG_FIELD_FOR_CONTROL; } else if (satRotRateValid and useFullDetumbleLaw) { diff --git a/mission/controller/acs/control/Detumble.h b/mission/controller/acs/control/Detumble.h index 4424896e..9fca77e6 100644 --- a/mission/controller/acs/control/Detumble.h +++ b/mission/controller/acs/control/Detumble.h @@ -11,8 +11,9 @@ class Detumble { Detumble(); virtual ~Detumble(); - uint8_t detumbleStrategy(const bool magFieldValid, const bool satRotRateValid, - const bool magFieldRateValid, const bool useFullDetumbleLaw); + acs::SafeModeStrategy detumbleStrategy(const bool magFieldValid, const bool satRotRateValid, + const bool magFieldRateValid, + const bool useFullDetumbleLaw); void bDotLawFull(const double *satRotRateB, const double *magFieldB, double *magMomB, double gain); diff --git a/mission/controller/acs/control/PtgCtrl.cpp b/mission/controller/acs/control/PtgCtrl.cpp index 1b20efb9..2f5847cc 100644 --- a/mission/controller/acs/control/PtgCtrl.cpp +++ b/mission/controller/acs/control/PtgCtrl.cpp @@ -5,9 +5,6 @@ #include #include #include -#include - -#include "../util/MathOperations.h" PtgCtrl::PtgCtrl(AcsParameters *acsParameters_) { acsParameters = acsParameters_; } @@ -32,12 +29,13 @@ void PtgCtrl::ptgLaw(AcsParameters::PointingLawParameters *pointingLawParameters double qErrorLaw[3] = {0, 0, 0}; for (int i = 0; i < 3; i++) { - if (abs(qError[i]) < qErrorMin) { + if (std::abs(qError[i]) < qErrorMin) { qErrorLaw[i] = qErrorMin; } else { - qErrorLaw[i] = abs(qError[i]); + qErrorLaw[i] = std::abs(qError[i]); } } + double qErrorLawNorm = VectorOperations::norm(qErrorLaw, 3); double gain1 = cInt * omMax / qErrorLawNorm; @@ -73,7 +71,7 @@ void PtgCtrl::ptgLaw(AcsParameters::PointingLawParameters *pointingLawParameters double pErrorSign[3] = {0, 0, 0}; for (int i = 0; i < 3; i++) { - if (abs(pError[i]) > 1) { + if (std::abs(pError[i]) > 1) { pErrorSign[i] = sign(pError[i]); } else { pErrorSign[i] = pError[i]; @@ -98,61 +96,92 @@ void PtgCtrl::ptgLaw(AcsParameters::PointingLawParameters *pointingLawParameters VectorOperations::mulScalar(torqueRws, -1, torqueRws, 4); } +void PtgCtrl::ptgNullspace(AcsParameters::PointingLawParameters *pointingLawParameters, + const int32_t speedRw0, const int32_t speedRw1, const int32_t speedRw2, + const int32_t speedRw3, double *rwTrqNs) { + // concentrate RW speeds as vector and convert to double + double speedRws[4] = {static_cast(speedRw0), static_cast(speedRw1), + static_cast(speedRw2), static_cast(speedRw3)}; + VectorOperations::mulScalar(speedRws, 1e-1, speedRws, 4); + VectorOperations::mulScalar(speedRws, RPM_TO_RAD_PER_SEC, speedRws, 4); + + // calculate RPM offset utilizing the nullspace + double rpmOffset[4] = {0, 0, 0, 0}; + double rpmOffsetSpeed = pointingLawParameters->nullspaceSpeed / 10 * RPM_TO_RAD_PER_SEC; + VectorOperations::mulScalar(acsParameters->rwMatrices.nullspaceVector, rpmOffsetSpeed, + rpmOffset, 4); + + // calculate resulting angular momentum + double rwAngMomentum[4] = {0, 0, 0, 0}, diffRwSpeed[4] = {0, 0, 0, 0}; + VectorOperations::subtract(speedRws, rpmOffset, diffRwSpeed, 4); + VectorOperations::mulScalar(diffRwSpeed, acsParameters->rwHandlingParameters.inertiaWheel, + rwAngMomentum, 4); + + // calculate resulting torque + double nullspaceMatrix[4][4] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; + MatrixOperations::multiply(acsParameters->rwMatrices.nullspaceVector, + acsParameters->rwMatrices.nullspaceVector, *nullspaceMatrix, 4, + 1, 4); + MatrixOperations::multiply(*nullspaceMatrix, rwAngMomentum, rwTrqNs, 4, 4, 1); + VectorOperations::mulScalar(rwTrqNs, -1 * pointingLawParameters->gainNullspace, rwTrqNs, + 4); +} + void PtgCtrl::ptgDesaturation(AcsParameters::PointingLawParameters *pointingLawParameters, - double *magFieldEst, bool magFieldEstValid, double *satRate, - int32_t *speedRw0, int32_t *speedRw1, int32_t *speedRw2, - int32_t *speedRw3, double *mgtDpDes) { - if (!(magFieldEstValid) || !(pointingLawParameters->desatOn)) { - mgtDpDes[0] = 0; - mgtDpDes[1] = 0; - mgtDpDes[2] = 0; + const double *magFieldB, const bool magFieldBValid, + const double *satRate, const int32_t speedRw0, const int32_t speedRw1, + const int32_t speedRw2, const int32_t speedRw3, double *mgtDpDes) { + if (not magFieldBValid or not pointingLawParameters->desatOn) { return; } - // calculating momentum of satellite and momentum of reaction wheels - double speedRws[4] = {(double)*speedRw0, (double)*speedRw1, (double)*speedRw2, (double)*speedRw3}; - double momentumRwU[4] = {0, 0, 0, 0}, momentumRw[3] = {0, 0, 0}; - VectorOperations::mulScalar(speedRws, acsParameters->rwHandlingParameters.inertiaWheel, - momentumRwU, 4); - MatrixOperations::multiply(*(acsParameters->rwMatrices.alignmentMatrix), momentumRwU, - momentumRw, 3, 4, 1); - double momentumSat[3] = {0, 0, 0}, momentumTotal[3] = {0, 0, 0}; - MatrixOperations::multiply(*(acsParameters->inertiaEIVE.inertiaMatrixDeployed), satRate, - momentumSat, 3, 3, 1); - VectorOperations::add(momentumSat, momentumRw, momentumTotal, 3); - // calculating momentum error - double deltaMomentum[3] = {0, 0, 0}; - VectorOperations::subtract(momentumTotal, pointingLawParameters->desatMomentumRef, - deltaMomentum, 3); - // resulting magnetic dipole command - double crossMomentumMagField[3] = {0, 0, 0}; - VectorOperations::cross(deltaMomentum, magFieldEst, crossMomentumMagField); - double normMag = VectorOperations::norm(magFieldEst, 3), factor = 0; - factor = (pointingLawParameters->deSatGainFactor) / normMag; - VectorOperations::mulScalar(crossMomentumMagField, factor, mgtDpDes, 3); -} + // concentrate RW speeds as vector and convert to double + double speedRws[4] = {static_cast(speedRw0), static_cast(speedRw1), + static_cast(speedRw2), static_cast(speedRw3)}; -void PtgCtrl::ptgNullspace(AcsParameters::PointingLawParameters *pointingLawParameters, - const int32_t *speedRw0, const int32_t *speedRw1, - const int32_t *speedRw2, const int32_t *speedRw3, double *rwTrqNs) { - double speedRws[4] = {(double)*speedRw0, (double)*speedRw1, (double)*speedRw2, (double)*speedRw3}; - double wheelMomentum[4] = {0, 0, 0, 0}; - double rpmOffset[4] = {1, 1, 1, -1}, factor = 350 * 2 * Math::PI / 60; - // conversion to [rad/s] for further calculations - VectorOperations::mulScalar(rpmOffset, factor, rpmOffset, 4); - VectorOperations::mulScalar(speedRws, 2 * Math::PI / 60, speedRws, 4); - double diffRwSpeed[4] = {0, 0, 0, 0}; - VectorOperations::subtract(speedRws, rpmOffset, diffRwSpeed, 4); - VectorOperations::mulScalar(diffRwSpeed, acsParameters->rwHandlingParameters.inertiaWheel, - wheelMomentum, 4); - double gainNs = pointingLawParameters->gainNullspace; - double nullSpaceMatrix[4][4] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}; - MathOperations::vecTransposeVecMatrix(acsParameters->rwMatrices.nullspace, - acsParameters->rwMatrices.nullspace, - *nullSpaceMatrix, 4); - MatrixOperations::multiply(*nullSpaceMatrix, wheelMomentum, rwTrqNs, 4, 4, 1); - VectorOperations::mulScalar(rwTrqNs, gainNs, rwTrqNs, 4); - VectorOperations::mulScalar(rwTrqNs, -1, rwTrqNs, 4); + // convert magFieldB from uT to T + double magFieldBT[3] = {0, 0, 0}; + VectorOperations::mulScalar(magFieldB, 1e-6, magFieldBT, 3); + + // calculate angular momentum of the satellite + double angMomentumSat[3] = {0, 0, 0}; + MatrixOperations::multiply(*(acsParameters->inertiaEIVE.inertiaMatrixDeployed), satRate, + angMomentumSat, 3, 3, 1); + + // calculate angular momentum of the reaction wheels with respect to the nullspace RW speed + // relocate RW speed zero to nullspace RW speed + double refSpeedRws[4] = {0, 0, 0, 0}; + VectorOperations::mulScalar(acsParameters->rwMatrices.nullspaceVector, + pointingLawParameters->nullspaceSpeed, refSpeedRws, 4); + VectorOperations::subtract(speedRws, refSpeedRws, speedRws, 4); + // convert speed from 10 RPM to 1 RPM + VectorOperations::mulScalar(speedRws, 1e-1, speedRws, 4); + // convert to rad/s + VectorOperations::mulScalar(speedRws, RPM_TO_RAD_PER_SEC, speedRws, 4); + // calculate angular momentum of each RW + double angMomentumRwU[4] = {0, 0, 0, 0}; + VectorOperations::mulScalar(speedRws, acsParameters->rwHandlingParameters.inertiaWheel, + angMomentumRwU, 4); + // convert RW angular momentum to body RF + double angMomentumRw[3] = {0, 0, 0}; + MatrixOperations::multiply(*(acsParameters->rwMatrices.alignmentMatrix), angMomentumRwU, + angMomentumRw, 3, 4, 1); + + // calculate total angular momentum + double angMomentumTotal[3] = {0, 0, 0}; + VectorOperations::add(angMomentumSat, angMomentumRw, angMomentumTotal, 3); + + // calculating momentum error + double deltaAngMomentum[3] = {0, 0, 0}; + VectorOperations::subtract(angMomentumTotal, pointingLawParameters->desatMomentumRef, + deltaAngMomentum, 3); + + // resulting magnetic dipole command + double crossAngMomentumMagField[3] = {0, 0, 0}; + VectorOperations::cross(deltaAngMomentum, magFieldBT, crossAngMomentumMagField); + double factor = + pointingLawParameters->deSatGainFactor / VectorOperations::norm(magFieldBT, 3); + VectorOperations::mulScalar(crossAngMomentumMagField, factor, mgtDpDes, 3); } void PtgCtrl::rwAntistiction(ACS::SensorValues *sensorValues, int32_t *rwCmdSpeeds) { @@ -169,15 +198,9 @@ void PtgCtrl::rwAntistiction(ACS::SensorValues *sensorValues, int32_t *rwCmdSpee if (rwCmdSpeeds[i] != 0) { if (rwCmdSpeeds[i] > -acsParameters->rwHandlingParameters.stictionSpeed && rwCmdSpeeds[i] < acsParameters->rwHandlingParameters.stictionSpeed) { - if (currRwSpeed[i] == 0) { - if (rwCmdSpeeds[i] > 0) { - rwCmdSpeeds[i] = acsParameters->rwHandlingParameters.stictionSpeed; - } else if (rwCmdSpeeds[i] < 0) { - rwCmdSpeeds[i] = -acsParameters->rwHandlingParameters.stictionSpeed; - } - } else if (currRwSpeed[i] < -acsParameters->rwHandlingParameters.stictionSpeed) { + if (rwCmdSpeeds[i] > currRwSpeed[i]) { rwCmdSpeeds[i] = acsParameters->rwHandlingParameters.stictionSpeed; - } else if (currRwSpeed[i] > acsParameters->rwHandlingParameters.stictionSpeed) { + } else if (rwCmdSpeeds[i] < currRwSpeed[i]) { rwCmdSpeeds[i] = -acsParameters->rwHandlingParameters.stictionSpeed; } } diff --git a/mission/controller/acs/control/PtgCtrl.h b/mission/controller/acs/control/PtgCtrl.h index fad72e6b..5f731e6b 100644 --- a/mission/controller/acs/control/PtgCtrl.h +++ b/mission/controller/acs/control/PtgCtrl.h @@ -1,13 +1,10 @@ #ifndef PTGCTRL_H_ #define PTGCTRL_H_ +#include +#include +#include #include -#include -#include - -#include "../AcsParameters.h" -#include "../SensorValues.h" -#include "eive/resultClassIds.h" class PtgCtrl { /* @@ -29,14 +26,14 @@ class PtgCtrl { void ptgLaw(AcsParameters::PointingLawParameters *pointingLawParameters, const double *qError, const double *deltaRate, const double *rwPseudoInv, double *torqueRws); - void ptgDesaturation(AcsParameters::PointingLawParameters *pointingLawParameters, - double *magFieldEst, bool magFieldEstValid, double *satRate, - int32_t *speedRw0, int32_t *speedRw1, int32_t *speedRw2, int32_t *speedRw3, - double *mgtDpDes); - void ptgNullspace(AcsParameters::PointingLawParameters *pointingLawParameters, - const int32_t *speedRw0, const int32_t *speedRw1, const int32_t *speedRw2, - const int32_t *speedRw3, double *rwTrqNs); + const int32_t speedRw0, const int32_t speedRw1, const int32_t speedRw2, + const int32_t speedRw3, double *rwTrqNs); + + void ptgDesaturation(AcsParameters::PointingLawParameters *pointingLawParameters, + const double *magFieldB, const bool magFieldBValid, const double *satRate, + const int32_t speedRw0, const int32_t speedRw1, const int32_t speedRw2, + const int32_t speedRw3, double *mgtDpDes); /* @brief: Commands the stiction torque in case wheel speed is to low * torqueCommand modified torque after antistiction @@ -45,6 +42,7 @@ class PtgCtrl { private: const AcsParameters *acsParameters; + static constexpr double RPM_TO_RAD_PER_SEC = (2 * M_PI) / 60; }; #endif /* ACS_CONTROL_PTGCTRL_H_ */ diff --git a/mission/controller/acs/control/SafeCtrl.cpp b/mission/controller/acs/control/SafeCtrl.cpp index f0ebd5a0..43677ccf 100644 --- a/mission/controller/acs/control/SafeCtrl.cpp +++ b/mission/controller/acs/control/SafeCtrl.cpp @@ -9,9 +9,10 @@ SafeCtrl::SafeCtrl(AcsParameters *acsParameters_) { acsParameters = acsParameter SafeCtrl::~SafeCtrl() {} -uint8_t SafeCtrl::safeCtrlStrategy(const bool magFieldValid, const bool mekfValid, - const bool satRotRateValid, const bool sunDirValid, - const uint8_t mekfEnabled, const uint8_t dampingEnabled) { +acs::SafeModeStrategy SafeCtrl::safeCtrlStrategy(const bool magFieldValid, const bool mekfValid, + const bool satRotRateValid, const bool sunDirValid, + const uint8_t mekfEnabled, + const uint8_t dampingEnabled) { if (not magFieldValid) { return acs::SafeModeStrategy::SAFECTRL_NO_MAG_FIELD_FOR_CONTROL; } else if (mekfEnabled and mekfValid) { diff --git a/mission/controller/acs/control/SafeCtrl.h b/mission/controller/acs/control/SafeCtrl.h index 91625360..12f9ddb0 100644 --- a/mission/controller/acs/control/SafeCtrl.h +++ b/mission/controller/acs/control/SafeCtrl.h @@ -12,9 +12,9 @@ class SafeCtrl { SafeCtrl(AcsParameters *acsParameters_); virtual ~SafeCtrl(); - uint8_t safeCtrlStrategy(const bool magFieldValid, const bool mekfValid, - const bool satRotRateValid, const bool sunDirValid, - const uint8_t mekfEnabled, const uint8_t dampingEnabled); + acs::SafeModeStrategy safeCtrlStrategy(const bool magFieldValid, const bool mekfValid, + const bool satRotRateValid, const bool sunDirValid, + const uint8_t mekfEnabled, const uint8_t dampingEnabled); void safeMekf(const double *magFieldB, const double *satRotRateB, const double *sunDirModelI, const double *quatBI, const double *sunDirRefB, double *magMomB, diff --git a/mission/genericFactory.cpp b/mission/genericFactory.cpp index 2dd00ee6..421d6fa9 100644 --- a/mission/genericFactory.cpp +++ b/mission/genericFactory.cpp @@ -49,6 +49,7 @@ #include "mission/system/acs/acsModeTree.h" #include "mission/system/tcs/tcsModeTree.h" #include "mission/tcs/defs.h" +#include "mission/tmtc/Service15TmStorage.h" #include "mission/tmtc/tmFilters.h" #include "objects/systemObjectList.h" #include "tmtc/pusIds.h" @@ -58,15 +59,13 @@ using persTmStore::PersistentTmStores; #if OBSW_ADD_TCPIP_SERVERS == 1 #if OBSW_ADD_TMTC_UDP_SERVER == 1 // UDP server includes -#include "devices/gpioIds.h" -#include "fsfw/osal/common/UdpTcPollingTask.h" -#include "fsfw/osal/common/UdpTmTcBridge.h" +#include +#include #endif #if OBSW_ADD_TMTC_TCP_SERVER == 1 // TCP server includes -#include "fsfw/osal/common/TcpTmTcBridge.h" -#include "fsfw/osal/common/TcpTmTcServer.h" -#include "mission/tmtc/Service15TmStorage.h" +#include +#include #endif #endif @@ -234,7 +233,8 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun // PUS service stack new Service1TelecommandVerification(objects::PUS_SERVICE_1_VERIFICATION, config::EIVE_PUS_APID, - pus::PUS_SERVICE_1, objects::PUS_TM_FUNNEL, 40); + pus::PUS_SERVICE_1, objects::PUS_TM_FUNNEL, + config::VERIFICATION_SERVICE_QUEUE_DEPTH); new Service2DeviceAccess(objects::PUS_SERVICE_2_DEVICE_ACCESS, config::EIVE_PUS_APID, pus::PUS_SERVICE_2, 3, 10); new Service3Housekeeping(objects::PUS_SERVICE_3_HOUSEKEEPING, config::EIVE_PUS_APID, @@ -243,7 +243,7 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun PsbParams(objects::PUS_SERVICE_5_EVENT_REPORTING, config::EIVE_PUS_APID, pus::PUS_SERVICE_5), 80, 160); new Service8FunctionManagement(objects::PUS_SERVICE_8_FUNCTION_MGMT, config::EIVE_PUS_APID, - pus::PUS_SERVICE_8, 16, 60); + pus::PUS_SERVICE_8, config::ACTION_SERVICE_QUEUE_DEPTH, 16, 60); new Service9TimeManagement( PsbParams(objects::PUS_SERVICE_9_TIME_MGMT, config::EIVE_PUS_APID, pus::PUS_SERVICE_9)); diff --git a/mission/power/GomspaceDeviceHandler.cpp b/mission/power/GomspaceDeviceHandler.cpp index 89fca8ee..c20ac4e9 100644 --- a/mission/power/GomspaceDeviceHandler.cpp +++ b/mission/power/GomspaceDeviceHandler.cpp @@ -595,8 +595,8 @@ ReturnValue_t GomspaceDeviceHandler::parsePduHkTable(PDU::PduCoreHk& coreHk, PDU for (uint8_t idx = 0; idx < PDU::CHANNELS_LEN; idx++) { coreHk.voltages[idx] = as(packet + 0x12 + (idx * 2)); } - auxHk.vcc.value = as(packet + 0x24); - auxHk.vbat.value = as(packet + 0x26); + coreHk.vcc.value = as(packet + 0x24); + coreHk.vbat.value = as(packet + 0x26); coreHk.temperature = as(packet + 0x28) * 0.1; for (uint8_t idx = 0; idx < 3; idx++) { diff --git a/mission/power/gsDefs.h b/mission/power/gsDefs.h index bbe9911f..1ad000d1 100644 --- a/mission/power/gsDefs.h +++ b/mission/power/gsDefs.h @@ -405,6 +405,11 @@ class PduCoreHk : public StaticLocalDataSet<9> { /** Battery mode: 1 = Critical, 2 = Safe, 3 = Normal, 4 = Full */ lp_var_t battMode = lp_var_t(sid.objectId, pool::PDU_BATT_MODE, this); lp_var_t temperature = lp_var_t(sid.objectId, pool::PDU_TEMPERATURE, this); + + /** Measured VCC */ + lp_var_t vcc = lp_var_t(sid.objectId, pool::PDU_VCC, this); + /** Measured VBAT */ + lp_var_t vbat = lp_var_t(sid.objectId, pool::PDU_VBAT, this); }; class PduConfig : public StaticLocalDataSet<32> { @@ -452,11 +457,6 @@ class PduAuxHk : public StaticLocalDataSet<36> { PduAuxHk(object_id_t objectId, uint32_t setId) : StaticLocalDataSet(sid_t(objectId, setId)) {} - /** Measured VCC */ - lp_var_t vcc = lp_var_t(sid.objectId, pool::PDU_VCC, this); - /** Measured VBAT */ - lp_var_t vbat = lp_var_t(sid.objectId, pool::PDU_VBAT, this); - /** Output converter enable status */ lp_vec_t converterEnable = lp_vec_t(sid.objectId, pool::PDU_CONV_EN, this); diff --git a/mission/tcs/HeaterHandler.cpp b/mission/tcs/HeaterHandler.cpp index 630dc92c..de4b600d 100644 --- a/mission/tcs/HeaterHandler.cpp +++ b/mission/tcs/HeaterHandler.cpp @@ -268,6 +268,8 @@ void HeaterHandler::handleSwitchOnCommand(heater::Switch heaterIdx) { triggerEvent(GPIO_PULL_HIGH_FAILED, result); } else { triggerEvent(HEATER_WENT_ON, heaterIdx, 0); + EventManagerIF::triggerEvent(helper.heaters[heaterIdx].first->getObjectId(), MODE_INFO, + MODE_ON, 0); { MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX); heater.switchState = ON; @@ -324,6 +326,8 @@ void HeaterHandler::handleSwitchOffCommand(heater::Switch heaterIdx) { heater.switchState = OFF; } triggerEvent(HEATER_WENT_OFF, heaterIdx, 0); + EventManagerIF::triggerEvent(helper.heaters[heaterIdx].first->getObjectId(), MODE_INFO, + MODE_OFF, 0); // When all switches are off, also main line switch will be turned off if (allSwitchesOff()) { mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF); diff --git a/mission/tmtc/PersistentTmStore.cpp b/mission/tmtc/PersistentTmStore.cpp index 7c3738fc..8174f8a0 100644 --- a/mission/tmtc/PersistentTmStore.cpp +++ b/mission/tmtc/PersistentTmStore.cpp @@ -256,6 +256,7 @@ ReturnValue_t PersistentTmStore::getNextDumpPacket(PusTmReader& reader, bool& fi if (state == State::IDLE or dumpParams.pendingPacketDump) { return returnvalue::FAILED; } + fileHasSwapped = false; reader.setReadOnlyData(fileBuf.data() + dumpParams.currentSize, fileBuf.size() - dumpParams.currentSize); // CRC check to fully ensure this is a valid TM @@ -270,7 +271,6 @@ ReturnValue_t PersistentTmStore::getNextDumpPacket(PusTmReader& reader, bool& fi fileHasSwapped = true; return loadNextDumpFile(); } - fileHasSwapped = false; dumpParams.pendingPacketDump = true; return returnvalue::OK; } diff --git a/tmtc b/tmtc index 280c7243..522f273c 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit 280c72439effa1b4290dc500dade2c62a9d6e3f7 +Subproject commit 522f273c99845f9c50aaf135b1c6f52676b975dd