diff --git a/CHANGELOG.md b/CHANGELOG.md index dd1adb9a..3db916c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,16 @@ will consitute of a breaking change warranting a new major release: # [unreleased] +## Changed + +- STR missed reply handling is now moved to DHB rather than the COM interface. The COM IF will + still trigger an event if a reply is taking too long, and FDIR should still work via reply + timeouts. + +## Added + +- Set STR time in configuration sequence to firmware mode. + # [v6.1.0] 2023-07-13 - `eive-tmtc`: v5.2.0 diff --git a/CMakeLists.txt b/CMakeLists.txt index 7db00824..485895cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -93,7 +93,7 @@ set(OBSW_ADD_BPX_BATTERY_HANDLER 1 CACHE STRING "Add BPX battery module") set(OBSW_ADD_STAR_TRACKER - ${INIT_VAL} + 1 CACHE STRING "Add Startracker module") set(OBSW_ADD_SUN_SENSORS ${INIT_VAL} diff --git a/fsfw b/fsfw index 88e86652..42e74d22 160000 --- a/fsfw +++ b/fsfw @@ -1 +1 @@ -Subproject commit 88e8665280a0381c41b724ab035a8c3eff1a23c1 +Subproject commit 42e74d22cc1b5d4060ce9923f674bdede0babaac diff --git a/linux/acs/StrComHandler.cpp b/linux/acs/StrComHandler.cpp index 5ae00c94..2db73f35 100644 --- a/linux/acs/StrComHandler.cpp +++ b/linux/acs/StrComHandler.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -23,6 +24,8 @@ extern "C" { using namespace returnvalue; +static constexpr bool PACKET_WIRETAPPING = false; + StrComHandler::StrComHandler(object_id_t objectId) : SystemObject(objectId) { lock = MutexFactory::instance()->createMutex(); semaphore.acquire(); @@ -52,7 +55,7 @@ ReturnValue_t StrComHandler::performOperation(uint8_t operationCode) { case InternalState::POLL_ONE_REPLY: { // Stopwatch watch; replyTimeout.setTimeout(200); - replyResult = readOneReply(static_cast(state)); + readOneReply(static_cast(state)); { MutexGuard mg(lock); replyWasReceived = true; @@ -680,6 +683,10 @@ ReturnValue_t StrComHandler::sendMessage(CookieIF* cookie, const uint8_t* sendDa const uint8_t* txFrame; size_t frameLen; datalinkLayer.encodeFrame(sendData, sendLen, &txFrame, frameLen); + if (PACKET_WIRETAPPING) { + sif::debug << "Sending STR frame" << std::endl; + arrayprinter::print(txFrame, frameLen); + } ssize_t bytesWritten = write(serialPort, txFrame, frameLen); if (bytesWritten != static_cast(frameLen)) { sif::warning << "StrComHandler: Sending packet failed" << std::endl; @@ -709,13 +716,11 @@ ReturnValue_t StrComHandler::requestReceiveMessage(CookieIF* cookie, size_t requ } ReturnValue_t StrComHandler::readReceivedMessage(CookieIF* cookie, uint8_t** buffer, size_t* size) { - // Consider it a configuration error if the task is not done with a command -> reply cycle - // in time. bool replyWasReceived = false; { MutexGuard mg(lock); if (state != InternalState::SLEEPING) { - return BUSY; + return returnvalue::OK; } replyWasReceived = this->replyWasReceived; } @@ -728,7 +733,7 @@ ReturnValue_t StrComHandler::readReceivedMessage(CookieIF* cookie, uint8_t** buf *size = replyLen; } replyLen = 0; - return replyResult; + return returnvalue::OK; } ReturnValue_t StrComHandler::unlockAndEraseRegions(uint32_t from, uint32_t to) { @@ -782,8 +787,10 @@ ReturnValue_t StrComHandler::handleSerialReception() { << std::endl; return FAILED; } else if (bytesRead > 0) { - // sif::info << "Received " << bytesRead << " bytes from the STR" << std::endl; - // arrayprinter::print(recBuf.data(), bytesRead); + if (PACKET_WIRETAPPING) { + sif::info << "Received " << bytesRead << " bytes from the STR" << std::endl; + arrayprinter::print(recBuf.data(), bytesRead); + } datalinkLayer.feedData(recBuf.data(), bytesRead); } return OK; @@ -797,6 +804,10 @@ ReturnValue_t StrComHandler::readOneReply(uint32_t failParameter) { handleSerialReception(); result = datalinkLayer.checkRingBufForFrame(&replyPtr, replyLen); if (result == returnvalue::OK) { + if (PACKET_WIRETAPPING) { + sif::debug << "Received STR reply frame" << std::endl; + arrayprinter::print(replyPtr, replyLen); + } return returnvalue::OK; } else if (result != ArcsecDatalinkLayer::DEC_IN_PROGRESS) { triggerEvent(STR_HELPER_DEC_ERROR, result, failParameter); diff --git a/mission/acs/str/StarTrackerHandler.cpp b/mission/acs/str/StarTrackerHandler.cpp index cc5b19b7..ca11a11c 100644 --- a/mission/acs/str/StarTrackerHandler.cpp +++ b/mission/acs/str/StarTrackerHandler.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -88,7 +89,6 @@ void StarTrackerHandler::doStartUp() { default: return; } - solutionSet.setReportingEnabled(true); startupState = StartupState::DONE; internalState = InternalState::IDLE; setMode(_MODE_TO_ON); @@ -325,7 +325,7 @@ ReturnValue_t StarTrackerHandler::buildNormalDeviceCommand(DeviceCommandId_t* id ReturnValue_t StarTrackerHandler::buildTransitionDeviceCommand(DeviceCommandId_t* id) { switch (internalState) { case InternalState::BOOT_FIRMWARE: { - if (bootState == FwBootState::WAIT_FOR_EXECUTION or bootState == FwBootState::VERIFY_BOOT) { + if (bootState == FwBootState::VERIFY_BOOT or isAwaitingReply()) { return NOTHING_TO_SEND; } if (bootState == FwBootState::NONE) { @@ -349,71 +349,62 @@ ReturnValue_t StarTrackerHandler::buildTransitionDeviceCommand(DeviceCommandId_t *id = startracker::REQ_VERSION; return buildCommandFromCommand(*id, nullptr, 0); } + case (FwBootState::SET_TIME): { + *id = startracker::SET_TIME_FROM_SYS_TIME; + return buildCommandFromCommand(*id, nullptr, 0); + } case (FwBootState::LOGLEVEL): { - bootState = FwBootState::WAIT_FOR_EXECUTION; *id = startracker::LOGLEVEL; return buildCommandFromCommand( *id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size()); } case (FwBootState::LIMITS): { - bootState = FwBootState::WAIT_FOR_EXECUTION; *id = startracker::LIMITS; return buildCommandFromCommand( *id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size()); } case (FwBootState::TRACKING): { - bootState = FwBootState::WAIT_FOR_EXECUTION; *id = startracker::TRACKING; return buildCommandFromCommand( *id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size()); } case FwBootState::MOUNTING: - bootState = FwBootState::WAIT_FOR_EXECUTION; *id = startracker::MOUNTING; return buildCommandFromCommand( *id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size()); case FwBootState::IMAGE_PROCESSOR: - bootState = FwBootState::WAIT_FOR_EXECUTION; *id = startracker::IMAGE_PROCESSOR; return buildCommandFromCommand( *id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size()); case FwBootState::CAMERA: - bootState = FwBootState::WAIT_FOR_EXECUTION; *id = startracker::CAMERA; return buildCommandFromCommand( *id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size()); case FwBootState::CENTROIDING: - bootState = FwBootState::WAIT_FOR_EXECUTION; *id = startracker::CENTROIDING; return buildCommandFromCommand( *id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size()); case FwBootState::LISA: - bootState = FwBootState::WAIT_FOR_EXECUTION; *id = startracker::LISA; return buildCommandFromCommand( *id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size()); case FwBootState::MATCHING: - bootState = FwBootState::WAIT_FOR_EXECUTION; *id = startracker::MATCHING; return buildCommandFromCommand( *id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size()); case FwBootState::VALIDATION: - bootState = FwBootState::WAIT_FOR_EXECUTION; *id = startracker::VALIDATION; return buildCommandFromCommand( *id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size()); case FwBootState::ALGO: - bootState = FwBootState::WAIT_FOR_EXECUTION; *id = startracker::ALGO; return buildCommandFromCommand( *id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size()); case FwBootState::LOG_SUBSCRIPTION: - bootState = FwBootState::WAIT_FOR_EXECUTION; *id = startracker::LOGSUBSCRIPTION; return buildCommandFromCommand( *id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size()); case FwBootState::DEBUG_CAMERA: - bootState = FwBootState::WAIT_FOR_EXECUTION; *id = startracker::DEBUG_CAMERA; return buildCommandFromCommand( *id, reinterpret_cast(paramJsonFile.c_str()), paramJsonFile.size()); @@ -459,6 +450,20 @@ ReturnValue_t StarTrackerHandler::buildCommandFromCommand(DeviceCommandId_t devi preparePingRequest(); return returnvalue::OK; } + case (startracker::SET_TIME_FROM_SYS_TIME): { + SetTimeActionRequest setTimeRequest{}; + timeval tv; + Clock::getClock(&tv); + setTimeRequest.unixTime = + (static_cast(tv.tv_sec) * 1000 * 1000) + (static_cast(tv.tv_usec)); + arc_pack_settime_action_req(&setTimeRequest, commandBuffer, &rawPacketLen); + size_t serLen = 0; + // Time in milliseconds. Manual serialization because arcsec API ignores endianness. + SerializeAdapter::serialize(&setTimeRequest.unixTime, commandBuffer + 2, &serLen, + sizeof(commandBuffer) - 2, SerializeIF::Endianness::LITTLE); + rawPacket = commandBuffer; + return returnvalue::OK; + } case (startracker::REQ_TIME): { prepareTimeRequest(); return returnvalue::OK; @@ -655,6 +660,8 @@ void StarTrackerHandler::fillCommandAndReplyMap() { startracker::MAX_FRAME_SIZE * 2 + 2); this->insertInCommandAndReplyMap(startracker::LOGLEVEL, 3, nullptr, startracker::MAX_FRAME_SIZE * 2 + 2); + this->insertInCommandAndReplyMap(startracker::SET_TIME_FROM_SYS_TIME, 2, nullptr, + startracker::MAX_FRAME_SIZE * 2 + 2); this->insertInCommandAndReplyMap(startracker::LOGSUBSCRIPTION, 3, nullptr, startracker::MAX_FRAME_SIZE * 2 + 2); this->insertInCommandAndReplyMap(startracker::DEBUG_CAMERA, 3, nullptr, @@ -667,7 +674,7 @@ void StarTrackerHandler::fillCommandAndReplyMap() { startracker::MAX_FRAME_SIZE * 2 + 2); this->insertInCommandAndReplyMap(startracker::CAMERA, 3, nullptr, startracker::MAX_FRAME_SIZE * 2 + 2); - this->insertInCommandAndReplyMap(startracker::CENTROIDING, 3, nullptr, + this->insertInCommandAndReplyMap(startracker::CENTROIDING, 2, nullptr, startracker::MAX_FRAME_SIZE * 2 + 2); this->insertInCommandAndReplyMap(startracker::LISA, 3, nullptr, startracker::MAX_FRAME_SIZE * 2 + 2); @@ -814,6 +821,7 @@ void StarTrackerHandler::bootFirmware(Mode_t toMode) { setMode(toMode, startracker::SUBMODE_FIRMWARE); } sif::info << "STR: Firmware boot success" << std::endl; + solutionSet.setReportingEnabled(true); internalState = InternalState::IDLE; startupState = StartupState::IDLE; break; @@ -901,6 +909,10 @@ ReturnValue_t StarTrackerHandler::interpretDeviceReply(DeviceCommandId_t id, ReturnValue_t result = returnvalue::OK; switch (id) { + case (startracker::SET_TIME_FROM_SYS_TIME): { + result = handleActionReply(packet); + break; + } case (startracker::REQ_TIME): { result = handleTm(packet, timeSet, startracker::TimeSet::SIZE, "REQ_TIME"); break; @@ -1367,6 +1379,10 @@ ReturnValue_t StarTrackerHandler::scanForActionReply(uint8_t replyId, DeviceComm *foundId = startracker::UPLOAD_IMAGE; break; } + case (ARC_ACTION_REQ_SETTIME_ID): { + *foundId = startracker::SET_TIME_FROM_SYS_TIME; + break; + } case (startracker::ID::CHECKSUM): { *foundId = startracker::CHECKSUM; break; @@ -1861,7 +1877,7 @@ ReturnValue_t StarTrackerHandler::handleSetParamReply(const uint8_t* rawFrame) { uint8_t status = startracker::getStatusField(rawFrame); if (status != startracker::STATUS_OK) { sif::warning << "StarTrackerHandler::handleSetParamReply: Failed to execute parameter set " - " command with parameter ID" + "command with parameter ID " << static_cast(*(rawFrame + PARAMETER_ID_OFFSET)) << std::endl; if (internalState != InternalState::IDLE) { internalState = InternalState::IDLE; @@ -1869,21 +1885,25 @@ ReturnValue_t StarTrackerHandler::handleSetParamReply(const uint8_t* rawFrame) { return SET_PARAM_FAILED; } if (internalState != InternalState::IDLE) { - handleStartup(*(rawFrame + PARAMETER_ID_OFFSET)); + handleStartup(*rawFrame, *(rawFrame + PARAMETER_ID_OFFSET)); } return returnvalue::OK; } ReturnValue_t StarTrackerHandler::handleActionReply(const uint8_t* rawFrame) { uint8_t status = startracker::getStatusField(rawFrame); + ReturnValue_t result = returnvalue::OK; if (status != startracker::STATUS_OK) { sif::warning << "StarTrackerHandler::handleActionReply: Failed to execute action " << "command with action ID " << static_cast(*(rawFrame + ACTION_ID_OFFSET)) << " and status " << static_cast(status) << std::endl; - return ACTION_FAILED; + result = ACTION_FAILED; } - return returnvalue::OK; + if (internalState != InternalState::IDLE) { + handleStartup(*rawFrame, *(rawFrame + PARAMETER_ID_OFFSET)); + } + return result; } ReturnValue_t StarTrackerHandler::handleChecksumReply(const uint8_t* rawFrame) { @@ -1979,7 +1999,7 @@ ReturnValue_t StarTrackerHandler::checkProgram() { startupState = StartupState::BOOT_BOOTLOADER; } if (bootState == FwBootState::VERIFY_BOOT) { - bootState = FwBootState::LOGLEVEL; + bootState = FwBootState::SET_TIME; } else if (internalState == InternalState::BOOTLOADER_CHECK) { triggerEvent(BOOTING_BOOTLOADER_FAILED_EVENT); internalState = InternalState::FAILED_BOOTLOADER_BOOT; @@ -2056,7 +2076,18 @@ ReturnValue_t StarTrackerHandler::handleActionReplySet(const uint8_t* rawFrame, return result; } -void StarTrackerHandler::handleStartup(uint8_t parameterId) { +void StarTrackerHandler::handleStartup(uint8_t tmType, uint8_t parameterId) { + switch (tmType) { + case (TMTC_ACTIONREPLY): { + case (ARC_ACTION_REQ_SETTIME_ID): { + bootState = FwBootState::LOGLEVEL; + return; + } + default: { + break; + } + } + } switch (parameterId) { case (startracker::ID::LOG_LEVEL): { bootState = FwBootState::LIMITS; @@ -2066,7 +2097,7 @@ void StarTrackerHandler::handleStartup(uint8_t parameterId) { bootState = FwBootState::TRACKING; break; } - case (startracker::ID::TRACKING): { + case (ARC_PARAM_TRACKING_ID): { bootState = FwBootState::MOUNTING; break; } diff --git a/mission/acs/str/StarTrackerHandler.h b/mission/acs/str/StarTrackerHandler.h index 7bcc9f2a..34a10746 100644 --- a/mission/acs/str/StarTrackerHandler.h +++ b/mission/acs/str/StarTrackerHandler.h @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -16,7 +17,7 @@ #include "fsfw/timemanager/Countdown.h" extern "C" { -#include +#include } /** @@ -264,6 +265,7 @@ class StarTrackerHandler : public DeviceHandlerBase { BOOT_DELAY, REQ_VERSION, VERIFY_BOOT, + SET_TIME, LOGLEVEL, LIMITS, TRACKING, @@ -279,6 +281,7 @@ class StarTrackerHandler : public DeviceHandlerBase { LOG_SUBSCRIPTION, DEBUG_CAMERA, WAIT_FOR_EXECUTION, + RETRY_CFG_CMD }; FwBootState bootState = FwBootState::NONE; @@ -468,7 +471,7 @@ class StarTrackerHandler : public DeviceHandlerBase { /** * @brief Handles the startup state machine */ - void handleStartup(uint8_t parameterId); + void handleStartup(uint8_t tmType, uint8_t parameterId); /** * @brief Handles telemtry replies and fills the appropriate dataset diff --git a/mission/acs/str/strHelpers.h b/mission/acs/str/strHelpers.h index 69729df5..894ceac5 100644 --- a/mission/acs/str/strHelpers.h +++ b/mission/acs/str/strHelpers.h @@ -326,6 +326,7 @@ static const DeviceCommandId_t DEBUG_CAMERA = 83; static const DeviceCommandId_t FIRMWARE_UPDATE = 84; static const DeviceCommandId_t DISABLE_TIMESTAMP_GENERATION = 85; static const DeviceCommandId_t ENABLE_TIMESTAMP_GENERATION = 86; +static constexpr DeviceCommandId_t SET_TIME_FROM_SYS_TIME = 87; static const DeviceCommandId_t NONE = 0xFFFFFFFF; static const uint32_t VERSION_SET_ID = REQ_VERSION; @@ -396,7 +397,6 @@ static const uint8_t ALGO = 16; static const uint8_t REBOOT = 7; static const uint8_t UPLOAD_IMAGE = 10; static const uint8_t POWER = 11; -static const uint8_t SET_TIME = 14; static const uint8_t SUBSCRIPTION = 18; static const uint8_t SOLUTION = 24; static const uint8_t TEMPERATURE = 27; @@ -650,7 +650,7 @@ class SolutionSet : public StaticLocalDataSet { // Ticks timestamp lp_var_t ticks = lp_var_t(sid.objectId, PoolIds::TICKS_SOLUTION_SET, this); /// Unix time stamp - lp_var_t time = lp_var_t(sid.objectId, PoolIds::TIME_SOLUTION_SET, this); + lp_var_t timeUs = lp_var_t(sid.objectId, PoolIds::TIME_SOLUTION_SET, this); // Calibrated quaternion (takes into account the mounting quaternion), typically same as // track q values lp_var_t caliQw = lp_var_t(sid.objectId, PoolIds::CALI_QW, this); @@ -695,7 +695,7 @@ class SolutionSet : public StaticLocalDataSet { void printSet() { PoolReadGuard rg(this); sif::info << "SolutionSet::printSet: Ticks: " << this->ticks << std::endl; - sif::info << "SolutionSet::printSet: Time: " << this->time << std::endl; + sif::info << "SolutionSet::printSet: Time: " << this->timeUs << std::endl; sif::info << "SolutionSet::printSet: Calibrated quaternion Qw: " << this->caliQw << std::endl; sif::info << "SolutionSet::printSet: Calibrated quaternion Qx: " << this->caliQx << std::endl; sif::info << "SolutionSet::printSet: Calibrated quaternion Qy: " << this->caliQy << std::endl; diff --git a/tmtc b/tmtc index eea76835..26cf1121 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit eea768358101a16912c0c49ad5e66a8c90826121 +Subproject commit 26cf112121782e730057cda0766d435ee2077b6d