From 5f6f85a7781ebb4b9908481bfc6230dad51958a4 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 30 Mar 2023 17:16:59 +0200 Subject: [PATCH] done --- CHANGELOG.md | 11 ++ bsp_q7s/core/ObjectFactory.cpp | 5 +- bsp_q7s/core/scheduling.cpp | 8 ++ common/config/eive/objects.h | 2 + linux/acs/GpsHyperionLinuxController.cpp | 1 + mission/acs/GyrAdis1650XHandler.cpp | 3 +- mission/acs/GyrL3gCustomHandler.cpp | 5 +- mission/genericFactory.cpp | 3 +- mission/system/acs/AcsBoardAssembly.cpp | 107 +++++++++++--------- mission/system/acs/AcsBoardAssembly.h | 12 ++- mission/system/acs/DualLaneAssemblyBase.cpp | 13 +-- mission/system/acs/DualLaneAssemblyBase.h | 4 +- tmtc | 2 +- 13 files changed, 108 insertions(+), 68 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 85b96c32..3d982765 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,17 @@ will consitute of a breaking change warranting a new major release: - SCEX filename updates. Also use T as the file ID / date separator between date and time. +## Fixed + +- Bugfix for side lane transitions of the dual lane assemblies, which only worked when the + assembly was directly commanded + +## Added + +- Added GPS0 and GPS1 health device which are used by the ACS board assembly when deciding whether + to change to the other side or to go to dual side directly. Setting the health devices to faulty + should also trigger a side switch or a switch to dual mode. + # [v1.41.0] 2023-03-28 eive-tmtc: v2.20.0 diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp index 00e87330..e7a5fca0 100644 --- a/bsp_q7s/core/ObjectFactory.cpp +++ b/bsp_q7s/core/ObjectFactory.cpp @@ -1,5 +1,6 @@ #include "ObjectFactory.h" +#include #include #include #include @@ -21,9 +22,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -516,6 +517,8 @@ void ObjectFactory::createAcsBoardComponents(SpiComIF& spiComIF, LinuxLibgpioIF* new GpsHyperionLinuxController(objects::GPS_CONTROLLER, objects::NO_OBJECT, debugGps); gpsCtrl->setResetPinTriggerFunction(gps::triggerGpioResetPin, &RESET_ARGS_GNSS); + new HealthDevice(objects::GPS_0_HEALTH_DEV, objects::ACS_BOARD_ASS); + new HealthDevice(objects::GPS_1_HEALTH_DEV, objects::ACS_BOARD_ASS); ObjectFactory::createAcsBoardAssy(pwrSwitcher, assemblyChildren, gpsCtrl, gpioComIF); #endif /* OBSW_ADD_ACS_HANDLERS == 1 */ } diff --git a/bsp_q7s/core/scheduling.cpp b/bsp_q7s/core/scheduling.cpp index 25f8ede4..2d767687 100644 --- a/bsp_q7s/core/scheduling.cpp +++ b/bsp_q7s/core/scheduling.cpp @@ -291,6 +291,14 @@ void scheduling::initTasks() { if (result != returnvalue::OK) { scheduling::printAddObjectError("STR_ASSY", objects::STR_ASSY); } + result = acsSysTask->addComponent(objects::GPS_0_HEALTH_DEV); + if (result != returnvalue::OK) { + scheduling::printAddObjectError("GPS_0_HEALTH_DEV", objects::GPS_0_HEALTH_DEV); + } + result = acsSysTask->addComponent(objects::GPS_1_HEALTH_DEV); + if (result != returnvalue::OK) { + scheduling::printAddObjectError("GPS_1_HEALTH_DEV", objects::GPS_1_HEALTH_DEV); + } PeriodicTaskIF* tcsSystemTask = factory->createPeriodicTask( "TCS_TASK", 50, PeriodicTaskIF::MINIMUM_STACK_SIZE, 0.5, missedDeadlineFunc, &RR_SCHEDULING); diff --git a/common/config/eive/objects.h b/common/config/eive/objects.h index 667067bb..0cc4b9d9 100644 --- a/common/config/eive/objects.h +++ b/common/config/eive/objects.h @@ -43,6 +43,8 @@ enum commonObjects : uint32_t { RW4 = 0x44120350, STAR_TRACKER = 0x44130001, GPS_CONTROLLER = 0x44130045, + GPS_0_HEALTH_DEV = 0x44130046, + GPS_1_HEALTH_DEV = 0x44130047, IMTQ_POLLING = 0x44140013, IMTQ_HANDLER = 0x44140014, diff --git a/linux/acs/GpsHyperionLinuxController.cpp b/linux/acs/GpsHyperionLinuxController.cpp index 0b971f49..b5dc8a1f 100644 --- a/linux/acs/GpsHyperionLinuxController.cpp +++ b/linux/acs/GpsHyperionLinuxController.cpp @@ -99,6 +99,7 @@ void GpsHyperionLinuxController::setResetPinTriggerFunction(gpioResetFunction_t ReturnValue_t GpsHyperionLinuxController::performOperation(uint8_t opCode) { handleQueue(); poolManager.performHkOperation(); + while (true) { #if OBSW_THREAD_TRACING == 1 trace::threadTrace(opCounter, "GPS CTRL"); diff --git a/mission/acs/GyrAdis1650XHandler.cpp b/mission/acs/GyrAdis1650XHandler.cpp index 63a28366..57033e80 100644 --- a/mission/acs/GyrAdis1650XHandler.cpp +++ b/mission/acs/GyrAdis1650XHandler.cpp @@ -87,12 +87,11 @@ ReturnValue_t GyrAdis1650XHandler::scanForReply(const uint8_t *start, size_t rem getMode() == _MODE_POWER_DOWN) { return IGNORE_FULL_PACKET; } + *foundLen = remainingSize; if (remainingSize != sizeof(acs::Adis1650XReply)) { - *foundLen = remainingSize; return returnvalue::FAILED; } *foundId = adis1650x::REPLY; - *foundLen = remainingSize; if (internalState == InternalState::SHUTDOWN) { commandExecuted = true; } diff --git a/mission/acs/GyrL3gCustomHandler.cpp b/mission/acs/GyrL3gCustomHandler.cpp index fd576791..934fba99 100644 --- a/mission/acs/GyrL3gCustomHandler.cpp +++ b/mission/acs/GyrL3gCustomHandler.cpp @@ -99,12 +99,11 @@ ReturnValue_t GyrL3gCustomHandler::scanForReply(const uint8_t *start, size_t len if (getMode() == _MODE_WAIT_OFF or getMode() == _MODE_WAIT_ON or getMode() == _MODE_POWER_DOWN) { return IGNORE_FULL_PACKET; } + *foundLen = len; if (len != sizeof(acs::GyroL3gReply)) { - *foundLen = len; return returnvalue::FAILED; } - *foundId = l3gd20h::REPLY; - *foundLen = len; + *foundId = adis1650x::REPLY; if (internalState == InternalState::SHUTDOWN) { commandExecuted = true; } diff --git a/mission/genericFactory.cpp b/mission/genericFactory.cpp index f93e4df6..e29d1b0f 100644 --- a/mission/genericFactory.cpp +++ b/mission/genericFactory.cpp @@ -347,7 +347,8 @@ void ObjectFactory::createAcsBoardAssy(PowerSwitchIF& pwrSwitcher, AcsBoardHelper acsBoardHelper = AcsBoardHelper( objects::MGM_0_LIS3_HANDLER, objects::MGM_1_RM3100_HANDLER, objects::MGM_2_LIS3_HANDLER, objects::MGM_3_RM3100_HANDLER, objects::GYRO_0_ADIS_HANDLER, objects::GYRO_1_L3G_HANDLER, - objects::GYRO_2_ADIS_HANDLER, objects::GYRO_3_L3G_HANDLER, objects::GPS_CONTROLLER); + objects::GYRO_2_ADIS_HANDLER, objects::GYRO_3_L3G_HANDLER, objects::GPS_CONTROLLER, + objects::GPS_0_HEALTH_DEV, objects::GPS_1_HEALTH_DEV); auto acsAss = new AcsBoardAssembly(objects::ACS_BOARD_ASS, &pwrSwitcher, acsBoardHelper, gpioComIF); for (auto& assChild : assemblyDhbs) { diff --git a/mission/system/acs/AcsBoardAssembly.cpp b/mission/system/acs/AcsBoardAssembly.cpp index 08711f76..6c4023f8 100644 --- a/mission/system/acs/AcsBoardAssembly.cpp +++ b/mission/system/acs/AcsBoardAssembly.cpp @@ -77,14 +77,16 @@ ReturnValue_t AcsBoardAssembly::checkChildrenStateOn(Mode_t wantedMode, Submode_ if (wantedSubmode == A_SIDE) { if ((helper.gyro0SideAMode != wantedMode and helper.gyro1SideAMode != wantedMode) or (helper.mgm0SideAMode != wantedMode and helper.mgm1SideAMode != wantedMode) or - helper.gpsMode != MODE_ON) { + (helper.gpsMode != MODE_ON) or + (healthHelper.healthTable->getHealth(helper.healthDevGps0) == FAULTY)) { return NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE; } return returnvalue::OK; } else if (wantedSubmode == B_SIDE) { if ((helper.gyro2SideBMode != wantedMode and helper.gyro3SideBMode != wantedMode) or (helper.mgm2SideBMode != wantedMode and helper.mgm3SideBMode != wantedMode) or - helper.gpsMode != MODE_ON) { + (helper.gpsMode != MODE_ON) or + (healthHelper.healthTable->getHealth(helper.healthDevGps1) == FAULTY)) { return NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE; } return returnvalue::OK; @@ -126,12 +128,33 @@ ReturnValue_t AcsBoardAssembly::handleNormalOrOnModeCmd(Mode_t mode, Submode_t s auto cmdSeq = [&](object_id_t objectId, Mode_t devMode, ModeTableIdx tableIdx) { if (mode == devMode) { modeTable[tableIdx].setMode(mode); - } else if (isUseable(objectId, devMode)) { + } else if (isModeCommandable(objectId, devMode)) { modeTable[tableIdx].setMode(mode); modeTable[tableIdx].setSubmode(SUBMODE_NONE); } }; - bool gpsUsable = isUseable(helper.gpsId, helper.gpsMode); + bool gpsUsable = isModeCommandable(helper.gpsId, helper.gpsMode); + auto gpsCmd = [&](bool gnss0NReset, bool gnss1NReset, uint8_t gnssSelect) { + if (gpsUsable) { + if (mode == MODE_ON or mode == DeviceHandlerIF::MODE_NORMAL) { + modeTable[ModeTableIdx::GPS].setMode(MODE_ON); + } else if (mode == MODE_OFF) { + gnss0NReset = true; + gnss1NReset = true; + modeTable[ModeTableIdx::GPS].setMode(MODE_OFF); + } + modeTable[ModeTableIdx::GPS].setSubmode(SUBMODE_NONE); + + gpioHandler(gpioIds::GNSS_0_NRESET, gnss0NReset, + "AcsBoardAssembly::handleNormalOrOnModeCmd: Could not pull nReset pin" + "of GNSS 0"); + gpioHandler(gpioIds::GNSS_1_NRESET, gnss1NReset, + "AcsBoardAssembly::handleNormalOrOnModeCmd: Could not pull nReset pin" + "of GNSS 1"); + gpioHandler(gpioIds::GNSS_SELECT, gnssSelect, + "AcsBoardAssembly::handleNormalOrOnModeCmd: Could not pull GNSS select"); + } + }; switch (submode) { case (A_SIDE): { modeTable[ModeTableIdx::GYRO_2_B].setMode(MODE_OFF); @@ -146,16 +169,7 @@ ReturnValue_t AcsBoardAssembly::handleNormalOrOnModeCmd(Mode_t mode, Submode_t s cmdSeq(helper.gyro1L3gIdSideA, helper.gyro1SideAMode, ModeTableIdx::GYRO_1_A); cmdSeq(helper.mgm0Lis3IdSideA, helper.mgm0SideAMode, ModeTableIdx::MGM_0_A); cmdSeq(helper.mgm1Rm3100IdSideA, helper.mgm1SideAMode, ModeTableIdx::MGM_1_A); - if (gpsUsable) { - gpioHandler(gpioIds::GNSS_0_NRESET, true, - "AcsBoardAssembly::handleNormalOrOnModeCmd: Could not pull nReset pin" - "of GNSS 0 high (used GNSS)"); - gpioHandler(gpioIds::GNSS_1_NRESET, false, - "AcsBoardAssembly::handleNormalOrOnModeCmd: Could not pull nReset pin" - "of GNSS 1 low (unused GNSS)"); - gpioHandler(gpioIds::GNSS_SELECT, false, - "AcsBoardAssembly::handleNormalOrOnModeCmd: Could not pull GNSS select low"); - } + gpsCmd(true, false, 0); break; } case (B_SIDE): { @@ -171,20 +185,10 @@ ReturnValue_t AcsBoardAssembly::handleNormalOrOnModeCmd(Mode_t mode, Submode_t s cmdSeq(helper.gyro3L3gIdSideB, helper.gyro3SideBMode, ModeTableIdx::GYRO_3_B); cmdSeq(helper.mgm2Lis3IdSideB, helper.mgm2SideBMode, ModeTableIdx::MGM_2_B); cmdSeq(helper.mgm3Rm3100IdSideB, helper.mgm3SideBMode, ModeTableIdx::MGM_3_B); - if (gpsUsable) { - gpioHandler(gpioIds::GNSS_0_NRESET, false, - "AcsBoardAssembly::handleNormalOrOnModeCmd: Could not pull nReset pin" - "of GNSS 0 low (unused GNSS)"); - gpioHandler(gpioIds::GNSS_1_NRESET, true, - "AcsBoardAssembly::handleNormalOrOnModeCmd: Could not pull nReset pin" - "of GNSS 1 high (used GNSS)"); - gpioHandler(gpioIds::GNSS_SELECT, true, - "AcsBoardAssembly::handleNormalOrOnModeCmd: Could not pull GNSS select high"); - } + gpsCmd(false, true, 1); break; } case (DUAL_MODE): { - cmdSeq(helper.gpsId, helper.gpsMode, ModeTableIdx::GPS); cmdSeq(helper.gyro0AdisIdSideA, helper.gyro0SideAMode, ModeTableIdx::GYRO_0_A); cmdSeq(helper.gyro1L3gIdSideA, helper.gyro1SideAMode, ModeTableIdx::GYRO_1_A); cmdSeq(helper.mgm0Lis3IdSideA, helper.mgm0SideAMode, ModeTableIdx::MGM_0_A); @@ -193,26 +197,10 @@ ReturnValue_t AcsBoardAssembly::handleNormalOrOnModeCmd(Mode_t mode, Submode_t s cmdSeq(helper.gyro3L3gIdSideB, helper.gyro3SideBMode, ModeTableIdx::GYRO_3_B); cmdSeq(helper.mgm2Lis3IdSideB, helper.mgm2SideBMode, ModeTableIdx::MGM_2_B); cmdSeq(helper.mgm3Rm3100IdSideB, helper.mgm3SideBMode, ModeTableIdx::MGM_3_B); - ReturnValue_t status = returnvalue::OK; - if (gpsUsable) { - gpioHandler(gpioIds::GNSS_0_NRESET, true, - "AcsBoardAssembly::handleNormalOrOnModeCmd: Could not pull nReset pin" - "of GNSS 0 high (used GNSS)"); - gpioHandler(gpioIds::GNSS_1_NRESET, true, - "AcsBoardAssembly::handleNormalOrOnModeCmd: Could not pull nReset pin" - "of GNSS 1 high (used GNSS)"); - if (defaultSubmode == Submodes::A_SIDE) { - status = gpioIF->pullLow(gpioIds::GNSS_SELECT); - } else { - status = gpioIF->pullHigh(gpioIds::GNSS_SELECT); - } - if (status != returnvalue::OK) { -#if OBSW_VERBOSE_LEVEL >= 1 - sif::error << "AcsBoardAssembly::handleNormalOrOnModeCmd: Could not pull GNSS select to" - "default side for dual mode" - << std::endl; -#endif - } + if (defaultSubmode == Submodes::A_SIDE) { + gpsCmd(true, true, 0); + } else { + gpsCmd(true, true, 1); } break; } @@ -220,10 +208,6 @@ ReturnValue_t AcsBoardAssembly::handleNormalOrOnModeCmd(Mode_t mode, Submode_t s sif::error << "AcsBoardAssembly::handleNormalModeCmd: Unknown submode" << std::endl; } } - if (gpsUsable) { - modeTable[ModeTableIdx::GPS].setMode(MODE_ON); - modeTable[ModeTableIdx::GPS].setSubmode(SUBMODE_NONE); - } if (needsSecondStep) { result = NEED_SECOND_STEP; } @@ -307,6 +291,9 @@ ReturnValue_t AcsBoardAssembly::checkAndHandleHealthStates(Mode_t deviceMode, modeHelper.setForced(true); } }; + if (healthHelper.healthTable->getHealth(helper.gpsId) == EXTERNAL_CONTROL) { + modeHelper.setForced(true); + } if (deviceSubmode == duallane::DUAL_MODE) { checkAcsBoardSensorGroup(helper.mgm0Lis3IdSideA, helper.mgm1Rm3100IdSideA, helper.mgm2Lis3IdSideB, helper.mgm3Rm3100IdSideB); @@ -315,3 +302,25 @@ ReturnValue_t AcsBoardAssembly::checkAndHandleHealthStates(Mode_t deviceMode, } return status; } + +void AcsBoardAssembly::handleChildrenLostMode(ReturnValue_t result) { + using namespace duallane; + // Special handling to account for GPS devices being faulty. If the GPS device on the other + // side is marked faulty, directly to to dual side. + if (submode == Submodes::A_SIDE) { + if (healthHelper.healthTable->getHealth(helper.healthDevGps1) == FAULTY or + healthHelper.healthTable->getHealth(helper.healthDevGps1) == PERMANENT_FAULTY) { + triggerEvent(DIRECT_TRANSITION_TO_DUAL_OTHER_GPS_FAULTY, submode, 0); + startTransition(mode, Submodes::DUAL_MODE); + return; + } + } else if (submode == Submodes::B_SIDE) { + if (healthHelper.healthTable->getHealth(helper.healthDevGps0) == FAULTY or + healthHelper.healthTable->getHealth(helper.healthDevGps0) == PERMANENT_FAULTY) { + triggerEvent(DIRECT_TRANSITION_TO_DUAL_OTHER_GPS_FAULTY, submode, 0); + startTransition(mode, Submodes::DUAL_MODE); + return; + } + } + DualLaneAssemblyBase::handleChildrenLostMode(result); +} diff --git a/mission/system/acs/AcsBoardAssembly.h b/mission/system/acs/AcsBoardAssembly.h index 7427e808..b9255704 100644 --- a/mission/system/acs/AcsBoardAssembly.h +++ b/mission/system/acs/AcsBoardAssembly.h @@ -12,7 +12,7 @@ struct AcsBoardHelper { AcsBoardHelper(object_id_t mgm0Id, object_id_t mgm1Id, object_id_t mgm2Id, object_id_t mgm3Id, object_id_t gyro0Id, object_id_t gyro1Id, object_id_t gyro2Id, object_id_t gyro3Id, - object_id_t gpsId) + object_id_t gpsId, object_id_t gps0HealthDev, object_id_t gps1HealthDev) : mgm0Lis3IdSideA(mgm0Id), mgm1Rm3100IdSideA(mgm1Id), mgm2Lis3IdSideB(mgm2Id), @@ -35,6 +35,9 @@ struct AcsBoardHelper { object_id_t gpsId = objects::NO_OBJECT; + object_id_t healthDevGps0 = objects::NO_OBJECT; + object_id_t healthDevGps1 = objects::NO_OBJECT; + Mode_t gyro0SideAMode = HasModesIF::MODE_OFF; Mode_t gyro1SideAMode = HasModesIF::MODE_OFF; Mode_t gyro2SideBMode = HasModesIF::MODE_OFF; @@ -91,6 +94,11 @@ class AcsBoardAssembly : public DualLaneAssemblyBase { //! desired mode/submode combination static constexpr Event SIDE_SWITCH_TRANSITION_NOT_ALLOWED = event::makeEvent(SUBSYSTEM_ID, 3, severity::LOW); + //! [EXPORT] : [COMMENT] This is triggered when the assembly would have normally switched + //! the board side, but the GPS device of the other side was marked faulty. + //! P1: Current submode. + static constexpr Event DIRECT_TRANSITION_TO_DUAL_OTHER_GPS_FAULTY = + event::makeEvent(SUBSYSTEM_ID, 4, severity::MEDIUM); static constexpr uint8_t NUMBER_DEVICES_MODE_TABLE = 9; @@ -120,6 +128,8 @@ class AcsBoardAssembly : public DualLaneAssemblyBase { ReturnValue_t commandChildren(Mode_t mode, Submode_t submode) override; ReturnValue_t checkChildrenStateOn(Mode_t wantedMode, Submode_t wantedSubmode) override; + void handleChildrenLostMode(ReturnValue_t result) override; + ReturnValue_t handleNormalOrOnModeCmd(Mode_t mode, Submode_t submode); ReturnValue_t checkAndHandleHealthStates(Mode_t deviceMode, Submode_t deviceSubmode); void refreshHelperModes(); diff --git a/mission/system/acs/DualLaneAssemblyBase.cpp b/mission/system/acs/DualLaneAssemblyBase.cpp index 18369924..e32717de 100644 --- a/mission/system/acs/DualLaneAssemblyBase.cpp +++ b/mission/system/acs/DualLaneAssemblyBase.cpp @@ -46,6 +46,9 @@ void DualLaneAssemblyBase::startTransition(Mode_t mode, Submode_t submode) { AssemblyBase::startTransition(mode, submode); return; } + if (sideSwitchState == SideSwitchState::NONE and sideSwitchTransition(mode, submode)) { + sideSwitchState = SideSwitchState::REQUESTED; + } uint8_t pwrSubmode = submode; if (sideSwitchState == SideSwitchState::REQUESTED) { pwrSubmode = duallane::DUAL_MODE; @@ -61,7 +64,7 @@ void DualLaneAssemblyBase::startTransition(Mode_t mode, Submode_t submode) { } } -bool DualLaneAssemblyBase::isUseable(object_id_t object, Mode_t mode) { +bool DualLaneAssemblyBase::isModeCommandable(object_id_t object, Mode_t mode) { if (healthHelper.healthTable->isFaulty(object)) { return false; } @@ -70,10 +73,7 @@ bool DualLaneAssemblyBase::isUseable(object_id_t object, Mode_t mode) { if (childrenMap[object].mode == mode) { return true; } - - if (healthHelper.healthTable->isCommandable(object)) { - return true; - } + // Check for external control health state is done by base class. return false; } @@ -115,9 +115,6 @@ ReturnValue_t DualLaneAssemblyBase::isModeCombinationValid(Mode_t mode, Submode_ if (submode != A_SIDE and submode != B_SIDE and submode != DUAL_MODE) { return returnvalue::FAILED; } - if (sideSwitchTransition(mode, submode)) { - sideSwitchState = SideSwitchState::REQUESTED; - } return returnvalue::OK; } diff --git a/mission/system/acs/DualLaneAssemblyBase.h b/mission/system/acs/DualLaneAssemblyBase.h index d7ea31aa..fb17365c 100644 --- a/mission/system/acs/DualLaneAssemblyBase.h +++ b/mission/system/acs/DualLaneAssemblyBase.h @@ -49,12 +49,12 @@ class DualLaneAssemblyBase : public AssemblyBase, public ConfirmsFailuresIF { MessageQueueIF* eventQueue = nullptr; /** - * Check whether it makes sense to send mode commands to the device + * Check whether it makes sense to send mode commands to the device. * @param object * @param mode * @return */ - bool isUseable(object_id_t object, Mode_t mode); + bool isModeCommandable(object_id_t object, Mode_t mode); /** * Thin wrapper function which is required because the helper class diff --git a/tmtc b/tmtc index e8ccb470..1f491a72 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit e8ccb4700a34c549eb7d943ee4a401258c69d8cb +Subproject commit 1f491a72a346eb7801d20eb56b2aafd1dea2d6f0