diff --git a/CHANGELOG.md b/CHANGELOG.md index ec47364f..7a79325c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ list yields a list of all related PRs for each release. # [unreleased] +## Changed + +- 5V stack is now off by default + ## Fixed - PLOC SUPV: Minor adaptions and important bugfix for UART manager @@ -23,6 +27,8 @@ list yields a list of all related PRs for each release. PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/329 - Allow commanding the 5V stack internally in software PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/334 +- Add automatic 5V stack commanding for all connected devices + PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/335 # [v1.18.0] 01.12.2022 diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp index 5a0c6367..7219b96d 100644 --- a/bsp_q7s/core/ObjectFactory.cpp +++ b/bsp_q7s/core/ObjectFactory.cpp @@ -54,6 +54,7 @@ #include "linux/boardtest/LibgpiodTest.h" #endif #include +#include #include @@ -80,7 +81,6 @@ #include "mission/devices/HeaterHandler.h" #include "mission/devices/Max31865PT1000Handler.h" #include "mission/devices/P60DockHandler.h" -#include "mission/devices/PCDUHandler.h" #include "mission/devices/PDU1Handler.h" #include "mission/devices/PDU2Handler.h" #include "mission/devices/PayloadPcduHandler.h" @@ -205,7 +205,8 @@ void ObjectFactory::createPcduComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchI #endif } -ReturnValue_t ObjectFactory::createRadSensorComponent(LinuxLibgpioIF* gpioComIF) { +ReturnValue_t ObjectFactory::createRadSensorComponent(LinuxLibgpioIF* gpioComIF, + Stack5VHandler& stackHandler) { using namespace gpio; if (gpioComIF == nullptr) { return returnvalue::FAILED; @@ -226,12 +227,8 @@ ReturnValue_t ObjectFactory::createRadSensorComponent(LinuxLibgpioIF* gpioComIF) spi::DEFAULT_MAX_1227_MODE, spi::DEFAULT_MAX_1227_SPEED); spiCookieRadSensor->setMutexParams(MutexIF::TimeoutType::WAITING, spi::RAD_SENSOR_CS_TIMEOUT); auto radSensor = new RadiationSensorHandler(objects::RAD_SENSOR, objects::SPI_MAIN_COM_IF, - spiCookieRadSensor, gpioComIF); + spiCookieRadSensor, gpioComIF, stackHandler); static_cast(radSensor); - // The radiation sensor ADC is powered by the 5V stack connector which should always be on - radSensor->setStartUpImmediately(); - // It's a simple sensor, so just to to normal mode immediately - radSensor->setToGoToNormalModeImmediately(); #if OBSW_DEBUG_RAD_SENSOR == 1 radSensor->enablePeriodicDataPrint(true); #endif @@ -834,7 +831,8 @@ ReturnValue_t ObjectFactory::createCcsdsComponents(LinuxLibgpioIF* gpioComIF, } void ObjectFactory::createPlPcduComponents(LinuxLibgpioIF* gpioComIF, SpiComIF* spiComIF, - PowerSwitchIF* pwrSwitcher) { + PowerSwitchIF* pwrSwitcher, + Stack5VHandler& stackHandler) { using namespace gpio; // Create all GPIO components first GpioCookie* plPcduGpios = new GpioCookie; @@ -880,10 +878,9 @@ void ObjectFactory::createPlPcduComponents(LinuxLibgpioIF* gpioComIF, SpiComIF* new SpiCookie(addresses::PLPCDU_ADC, gpioIds::PLPCDU_ADC_CS, plpcdu::MAX_ADC_REPLY_SIZE, spi::DEFAULT_MAX_1227_MODE, spi::PL_PCDU_MAX_1227_SPEED); // Create device handler components - auto plPcduHandler = new PayloadPcduHandler( - objects::PLPCDU_HANDLER, objects::SPI_MAIN_COM_IF, spiCookie, gpioComIF, - SdCardManager::instance(), pwrSwitcher, pcdu::Switches::PDU2_CH1_PL_PCDU_BATT_0_14V8, - pcdu::Switches::PDU2_CH6_PL_PCDU_BATT_1_14V8, false); + auto plPcduHandler = + new PayloadPcduHandler(objects::PLPCDU_HANDLER, objects::SPI_MAIN_COM_IF, spiCookie, + gpioComIF, SdCardManager::instance(), stackHandler, false); spiCookie->setCallbackMode(PayloadPcduHandler::extConvAsTwoCallback, plPcduHandler); // plPcduHandler->enablePeriodicPrintout(true, 5); // static_cast(plPcduHandler); diff --git a/bsp_q7s/core/ObjectFactory.h b/bsp_q7s/core/ObjectFactory.h index c67353c4..c55e8452 100644 --- a/bsp_q7s/core/ObjectFactory.h +++ b/bsp_q7s/core/ObjectFactory.h @@ -2,6 +2,7 @@ #define BSP_Q7S_OBJECTFACTORY_H_ #include +#include #include #include #include @@ -27,9 +28,9 @@ void createCommunicationInterfaces(LinuxLibgpioIF** gpioComIF, SerialComIF** uar SpiComIF** spiRwComIF); void createPcduComponents(LinuxLibgpioIF* gpioComIF, PowerSwitchIF** pwrSwitcher); void createPlPcduComponents(LinuxLibgpioIF* gpioComIF, SpiComIF* spiComIF, - PowerSwitchIF* pwrSwitcher); + PowerSwitchIF* pwrSwitcher, Stack5VHandler& stackHandler); void createTmpComponents(); -ReturnValue_t createRadSensorComponent(LinuxLibgpioIF* gpioComIF); +ReturnValue_t createRadSensorComponent(LinuxLibgpioIF* gpioComIF, Stack5VHandler& handler); void createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, SerialComIF* uartComIF, PowerSwitchIF* pwrSwitcher); void createHeaterComponents(GpioIF* gpioIF, PowerSwitchIF* pwrSwitcher, HealthTableIF* healthTable); diff --git a/bsp_q7s/fmObjectFactory.cpp b/bsp_q7s/fmObjectFactory.cpp index 2814c3f9..239b3639 100644 --- a/bsp_q7s/fmObjectFactory.cpp +++ b/bsp_q7s/fmObjectFactory.cpp @@ -33,8 +33,10 @@ void ObjectFactory::produce(void* args) { new CoreController(objects::CORE_CONTROLLER); createPcduComponents(gpioComIF, &pwrSwitcher); + auto* stackHandler = new Stack5VHandler(*pwrSwitcher); + #if OBSW_ADD_RAD_SENSORS == 1 - createRadSensorComponent(gpioComIF); + createRadSensorComponent(gpioComIF, *stackHandler); #endif #if OBSW_ADD_SUN_SENSORS == 1 createSunSensorComponents(gpioComIF, spiMainComIF, pwrSwitcher, q7s::SPI_DEFAULT_DEV); @@ -48,7 +50,7 @@ void ObjectFactory::produce(void* args) { createTmpComponents(); #endif createSolarArrayDeploymentComponents(*pwrSwitcher, *gpioComIF); - createPlPcduComponents(gpioComIF, spiMainComIF, pwrSwitcher); + createPlPcduComponents(gpioComIF, spiMainComIF, pwrSwitcher, *stackHandler); #if OBSW_ADD_SYRLINKS == 1 createSyrlinksComponents(pwrSwitcher); #endif /* OBSW_ADD_SYRLINKS == 1 */ diff --git a/mission/devices/CMakeLists.txt b/mission/devices/CMakeLists.txt index b8fb326c..1589a460 100644 --- a/mission/devices/CMakeLists.txt +++ b/mission/devices/CMakeLists.txt @@ -3,7 +3,7 @@ target_sources( PRIVATE GomspaceDeviceHandler.cpp BpxBatteryHandler.cpp Tmp1075Handler.cpp - PCDUHandler.cpp + PcduHandler.cpp P60DockHandler.cpp PDU1Handler.cpp PDU2Handler.cpp diff --git a/mission/devices/PayloadPcduHandler.cpp b/mission/devices/PayloadPcduHandler.cpp index f4aba7ef..0f691c75 100644 --- a/mission/devices/PayloadPcduHandler.cpp +++ b/mission/devices/PayloadPcduHandler.cpp @@ -16,29 +16,37 @@ PayloadPcduHandler::PayloadPcduHandler(object_id_t objectId, object_id_t comIF, CookieIF* cookie, GpioIF* gpioIF, SdCardMountedIF* sdcMan, - PowerSwitchIF* pwrSwitcher, power::Switch_t switchA, - power::Switch_t switchB, bool periodicPrintout) + Stack5VHandler& stackHandler, bool periodicPrintout) : DeviceHandlerBase(objectId, comIF, cookie), adcSet(this), + stackHandler(stackHandler), periodicPrintout(periodicPrintout), gpioIF(gpioIF), - sdcMan(sdcMan), - pwrStateMachine(switchA, switchB, pwrSwitcher) {} + sdcMan(sdcMan) {} void PayloadPcduHandler::doStartUp() { - if ((state != States::PL_PCDU_OFF) and (state != States::ON_TRANS_SSR)) { + if (state > States::STACK_5V_CORRECT) { // Config error sif::error << "PayloadPcduHandler::doStartUp: Invalid state" << std::endl; } - if (pwrStateMachine.getState() == power::States::IDLE) { - pwrStateMachine.start(MODE_ON, pwrSubmode); - } clearSetOnOffFlag = true; - auto opCode = pwrStateMachine.fsm(); - if (opCode == power::OpCodes::TO_NOT_OFF_DONE or opCode == power::OpCodes::TIMEOUT_OCCURED) { - pwrStateMachine.reset(); + if (state == States::PL_PCDU_OFF) { + state = States::STACK_5V_SWITCHING; + } + if (state == States::STACK_5V_SWITCHING) { + ReturnValue_t retval = stackHandler.deviceToOn(StackCommander::PL_PCDU, true); + if (retval == BUSY) { + return; + } + state = States::STACK_5V_PENDING; + } + if (state == States::STACK_5V_PENDING) { + if (stackHandler.isSwitchOn()) { + state = States::STACK_5V_CORRECT; + } + } + if (state == States::STACK_5V_CORRECT) { quickTransitionAlreadyCalled = false; - state = States::POWER_CHANNELS_ON; setMode(_MODE_TO_ON); } } @@ -48,21 +56,17 @@ void PayloadPcduHandler::doShutDown() { quickTransitionBackToOff(false, false); quickTransitionAlreadyCalled = true; } - if (pwrStateMachine.getState() == power::States::IDLE) { - pwrStateMachine.start(MODE_OFF, 0); - } if (clearSetOnOffFlag) { std::memset(adcSet.processed.value, 0, adcSet.processed.getSerializedSize()); clearSetOnOffFlag = false; } - - auto opCode = pwrStateMachine.fsm(); - if (opCode == power::OpCodes::TO_OFF_DONE or opCode == power::OpCodes::TIMEOUT_OCCURED) { - pwrStateMachine.reset(); - state = States::PL_PCDU_OFF; - // No need to set mode _MODE_POWER_DOWN, power switching was already handled - setMode(MODE_OFF); + ReturnValue_t retval = stackHandler.deviceToOff(StackCommander::PL_PCDU, true); + if (retval == BUSY) { + return; } + state = States::PL_PCDU_OFF; + // No need to set mode _MODE_POWER_DOWN, power switching was already handled + setMode(MODE_OFF); } void PayloadPcduHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) { @@ -78,7 +82,7 @@ void PayloadPcduHandler::doTransition(Mode_t modeFrom, Submode_t subModeFrom) { gpioIF->pullLow(gpioIds::PLPCDU_ENB_TX); gpioIF->pullLow(gpioIds::PLPCDU_ENB_VBAT0); gpioIF->pullLow(gpioIds::PLPCDU_ENB_VBAT1); - state = States::POWER_CHANNELS_ON; + state = States::STACK_5V_CORRECT; } DeviceHandlerBase::doTransition(modeFrom, subModeFrom); } @@ -93,7 +97,7 @@ ReturnValue_t PayloadPcduHandler::stateMachineToNormal(Mode_t modeFrom, Submode_ setMode(MODE_OFF); return returnvalue::FAILED; } - if (state == States::POWER_CHANNELS_ON) { + if (state == States::STACK_5V_CORRECT) { #if OBSW_VERBOSE_LEVEL >= 1 sif::info << "Switching on SSR VBAT0 & VBAT1 GPIOs" << std::endl; #endif @@ -372,7 +376,7 @@ void PayloadPcduHandler::quickTransitionBackToOff(bool startTransitionToOff, boo gpioIF->pullLow(gpioIds::PLPCDU_ENB_TX); gpioIF->pullLow(gpioIds::PLPCDU_ENB_VBAT0); gpioIF->pullLow(gpioIds::PLPCDU_ENB_VBAT1); - state = States::PL_PCDU_OFF; + state = States::STACK_5V_SWITCHING; adcState = AdcStates::OFF; if (startTransitionToOff) { startTransition(MODE_OFF, 0); diff --git a/mission/devices/PayloadPcduHandler.h b/mission/devices/PayloadPcduHandler.h index 137a9a0b..0fd78887 100644 --- a/mission/devices/PayloadPcduHandler.h +++ b/mission/devices/PayloadPcduHandler.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "events/subsystemIdRanges.h" #include "fsfw/FSFW.h" @@ -62,8 +63,7 @@ class PayloadPcduHandler : public DeviceHandlerBase { static constexpr Event I_HPA_OUT_OF_BOUNDS = event::makeEvent(SUBSYSTEM_ID, 11, severity::MEDIUM); PayloadPcduHandler(object_id_t objectId, object_id_t comIF, CookieIF* cookie, GpioIF* gpioIF, - SdCardMountedIF* sdcMan, PowerSwitchIF* pwrSwitcher, power::Switch_t switchCh0, - power::Switch_t switchCh1, bool periodicPrintout); + SdCardMountedIF* sdcMan, Stack5VHandler& stackHandler, bool periodicPrintout); void setToGoToNormalModeImmediately(bool enable); void enablePeriodicPrintout(bool enable, uint8_t divider); @@ -78,7 +78,9 @@ class PayloadPcduHandler : public DeviceHandlerBase { private: enum class States : uint8_t { PL_PCDU_OFF, - POWER_CHANNELS_ON, + STACK_5V_SWITCHING, + STACK_5V_PENDING, + STACK_5V_CORRECT, // Solid State Relay, enable battery voltages VBAT0 and VBAT1. This will also switch on // the ADC ON_TRANS_SSR, @@ -108,6 +110,7 @@ class PayloadPcduHandler : public DeviceHandlerBase { bool goToNormalMode = false; plpcdu::PlPcduAdcSet adcSet; + Stack5VHandler& stackHandler; std::array cmdBuf = {}; // This variable is tied to DRO +6 V voltage. Voltages, currents are monitored and the experiment // is shut down immediately if there is a negative voltage. @@ -140,7 +143,6 @@ class PayloadPcduHandler : public DeviceHandlerBase { PoolEntry processedValues = PoolEntry({0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}); PoolEntry tempC = PoolEntry({0.0}); - DualLanePowerStateMachine pwrStateMachine; void updateSwitchGpio(gpioId_t id, gpio::Levels level); diff --git a/mission/devices/PCDUHandler.cpp b/mission/devices/PcduHandler.cpp similarity index 71% rename from mission/devices/PCDUHandler.cpp rename to mission/devices/PcduHandler.cpp index 71b4734e..29b8dc6e 100644 --- a/mission/devices/PCDUHandler.cpp +++ b/mission/devices/PcduHandler.cpp @@ -1,16 +1,16 @@ -#include "PCDUHandler.h" - #include #include #include #include #include #include +#include #include PCDUHandler::PCDUHandler(object_id_t setObjectId, size_t cmdQueueSize) : SystemObject(setObjectId), poolManager(this, nullptr), + p60CoreHk(objects::P60DOCK_HANDLER), pdu1CoreHk(this), pdu2CoreHk(this), switcherSet(this), @@ -26,7 +26,27 @@ PCDUHandler::~PCDUHandler() {} ReturnValue_t PCDUHandler::performOperation(uint8_t counter) { if (counter == DeviceHandlerIF::PERFORM_OPERATION) { readCommandQueue(); - return returnvalue::OK; + } + uint8_t switchState = 0; + { + PoolReadGuard pg(&p60CoreHk.outputEnables); + if (pg.getReadResult() == returnvalue::OK) { + switchState = p60CoreHk.outputEnables.value[10]; + } else { + return returnvalue::OK; + } + } + { + PoolReadGuard pg(&switcherSet.p60Dock5VStack); + if (pg.getReadResult() == returnvalue::OK) { + if (switcherSet.p60Dock5VStack.value != switchState) { + triggerEvent(power::SWITCH_HAS_CHANGED, switchState, pcdu::Switches::P60_DOCK_5V_STACK); + MutexGuard mg(pwrMutex); + switchStates[pcdu::P60_DOCK_5V_STACK] = switchState; + } + switcherSet.p60Dock5VStack.setValid(true); + switcherSet.p60Dock5VStack.value = switchState; + } } return returnvalue::OK; } @@ -85,8 +105,10 @@ void PCDUHandler::initializeSwitchStates() { for (uint8_t idx = 0; idx < NUMBER_OF_SWITCHES; idx++) { if (idx < PDU::CHANNELS_LEN) { switchStates[idx] = INIT_SWITCHES_PDU1.at(idx); - } else { + } else if (idx < PDU::CHANNELS_LEN * 2) { switchStates[idx] = INIT_SWITCHES_PDU2.at(idx - PDU::CHANNELS_LEN); + } else { + switchStates[idx] = OFF; } } } catch (const std::out_of_range& err) { @@ -156,24 +178,25 @@ void PCDUHandler::updatePdu2SwitchStates() { for (uint8_t idx = 0; idx < PDU::CHANNELS_LEN; idx++) { switcherSet.pdu2Switches[idx] = pdu2CoreHk.outputEnables[idx]; } + switcherSet.pdu2Switches.setValid(true); MutexGuard mg(pwrMutex); - checkAndUpdateSwitch(pdu, Switches::PDU2_CH0_Q7S, pdu2CoreHk.outputEnables[Channels::Q7S]); + checkAndUpdatePduSwitch(pdu, Switches::PDU2_CH0_Q7S, pdu2CoreHk.outputEnables[Channels::Q7S]); - checkAndUpdateSwitch(pdu, Switches::PDU2_CH1_PL_PCDU_BATT_0_14V8, - pdu2CoreHk.outputEnables[Channels::PAYLOAD_PCDU_CH1]); - checkAndUpdateSwitch(pdu, Switches::PDU2_CH2_RW_5V, pdu2CoreHk.outputEnables[Channels::RW]); - checkAndUpdateSwitch(pdu, Switches::PDU2_CH3_TCS_BOARD_HEATER_IN_8V, - pdu2CoreHk.outputEnables[Channels::TCS_HEATER_IN]); - checkAndUpdateSwitch(pdu, Switches::PDU2_CH4_SUS_REDUNDANT_3V3, - pdu2CoreHk.outputEnables[Channels::SUS_REDUNDANT]); - checkAndUpdateSwitch(pdu, Switches::PDU2_CH5_DEPLOYMENT_MECHANISM_8V, - pdu2CoreHk.outputEnables[Channels::DEPY_MECHANISM]); - checkAndUpdateSwitch(pdu, Switches::PDU2_CH6_PL_PCDU_BATT_1_14V8, - pdu2CoreHk.outputEnables[Channels::PAYLOAD_PCDU_CH6]); - checkAndUpdateSwitch(pdu, Switches::PDU2_CH7_ACS_BOARD_SIDE_B_3V3, - pdu2CoreHk.outputEnables[Channels::ACS_B_SIDE]); - checkAndUpdateSwitch(pdu, Switches::PDU2_CH8_PAYLOAD_CAMERA, - pdu2CoreHk.outputEnables[Channels::PAYLOAD_CAMERA]); + checkAndUpdatePduSwitch(pdu, Switches::PDU2_CH1_PL_PCDU_BATT_0_14V8, + pdu2CoreHk.outputEnables[Channels::PAYLOAD_PCDU_CH1]); + checkAndUpdatePduSwitch(pdu, Switches::PDU2_CH2_RW_5V, pdu2CoreHk.outputEnables[Channels::RW]); + checkAndUpdatePduSwitch(pdu, Switches::PDU2_CH3_TCS_BOARD_HEATER_IN_8V, + pdu2CoreHk.outputEnables[Channels::TCS_HEATER_IN]); + checkAndUpdatePduSwitch(pdu, Switches::PDU2_CH4_SUS_REDUNDANT_3V3, + pdu2CoreHk.outputEnables[Channels::SUS_REDUNDANT]); + checkAndUpdatePduSwitch(pdu, Switches::PDU2_CH5_DEPLOYMENT_MECHANISM_8V, + pdu2CoreHk.outputEnables[Channels::DEPY_MECHANISM]); + checkAndUpdatePduSwitch(pdu, Switches::PDU2_CH6_PL_PCDU_BATT_1_14V8, + pdu2CoreHk.outputEnables[Channels::PAYLOAD_PCDU_CH6]); + checkAndUpdatePduSwitch(pdu, Switches::PDU2_CH7_ACS_BOARD_SIDE_B_3V3, + pdu2CoreHk.outputEnables[Channels::ACS_B_SIDE]); + checkAndUpdatePduSwitch(pdu, Switches::PDU2_CH8_PAYLOAD_CAMERA, + pdu2CoreHk.outputEnables[Channels::PAYLOAD_CAMERA]); if (firstSwitchInfoPdu2) { firstSwitchInfoPdu2 = false; } @@ -192,24 +215,26 @@ void PCDUHandler::updatePdu1SwitchStates() { for (uint8_t idx = 0; idx < PDU::CHANNELS_LEN; idx++) { switcherSet.pdu1Switches[idx] = pdu1CoreHk.outputEnables[idx]; } + switcherSet.pdu1Switches.setValid(true); MutexGuard mg(pwrMutex); - checkAndUpdateSwitch(pdu, Switches::PDU1_CH0_TCS_BOARD_3V3, - pdu1CoreHk.outputEnables[Channels::TCS_BOARD_3V3]); - checkAndUpdateSwitch(pdu, Switches::PDU1_CH1_SYRLINKS_12V, - pdu1CoreHk.outputEnables[Channels::SYRLINKS]); - checkAndUpdateSwitch(pdu, Switches::PDU1_CH2_STAR_TRACKER_5V, - pdu1CoreHk.outputEnables[Channels::STR]); - checkAndUpdateSwitch(pdu, Switches::PDU1_CH3_MGT_5V, pdu1CoreHk.outputEnables[Channels::MGT]); - checkAndUpdateSwitch(pdu, Switches::PDU1_CH4_SUS_NOMINAL_3V3, - pdu1CoreHk.outputEnables[Channels::SUS_NOMINAL]); - checkAndUpdateSwitch(pdu, Switches::PDU1_CH5_SOLAR_CELL_EXP_5V, - pdu1CoreHk.outputEnables[Channels::SOL_CELL_EXPERIMENT]); - checkAndUpdateSwitch(pdu, Switches::PDU1_CH6_PLOC_12V, - pdu1CoreHk.outputEnables[Channels::PLOC]); - checkAndUpdateSwitch(pdu, Switches::PDU1_CH7_ACS_A_SIDE_3V3, - pdu1CoreHk.outputEnables[Channels::ACS_A_SIDE]); - checkAndUpdateSwitch(pdu, Switches::PDU1_CH8_UNOCCUPIED, - pdu1CoreHk.outputEnables[Channels::UNUSED]); + checkAndUpdatePduSwitch(pdu, Switches::PDU1_CH0_TCS_BOARD_3V3, + pdu1CoreHk.outputEnables[Channels::TCS_BOARD_3V3]); + checkAndUpdatePduSwitch(pdu, Switches::PDU1_CH1_SYRLINKS_12V, + pdu1CoreHk.outputEnables[Channels::SYRLINKS]); + checkAndUpdatePduSwitch(pdu, Switches::PDU1_CH2_STAR_TRACKER_5V, + pdu1CoreHk.outputEnables[Channels::STR]); + checkAndUpdatePduSwitch(pdu, Switches::PDU1_CH3_MGT_5V, + pdu1CoreHk.outputEnables[Channels::MGT]); + checkAndUpdatePduSwitch(pdu, Switches::PDU1_CH4_SUS_NOMINAL_3V3, + pdu1CoreHk.outputEnables[Channels::SUS_NOMINAL]); + checkAndUpdatePduSwitch(pdu, Switches::PDU1_CH5_SOLAR_CELL_EXP_5V, + pdu1CoreHk.outputEnables[Channels::SOL_CELL_EXPERIMENT]); + checkAndUpdatePduSwitch(pdu, Switches::PDU1_CH6_PLOC_12V, + pdu1CoreHk.outputEnables[Channels::PLOC]); + checkAndUpdatePduSwitch(pdu, Switches::PDU1_CH7_ACS_A_SIDE_3V3, + pdu1CoreHk.outputEnables[Channels::ACS_A_SIDE]); + checkAndUpdatePduSwitch(pdu, Switches::PDU1_CH8_UNOCCUPIED, + pdu1CoreHk.outputEnables[Channels::UNUSED]); if (firstSwitchInfoPdu1) { firstSwitchInfoPdu1 = false; } @@ -226,52 +251,52 @@ ReturnValue_t PCDUHandler::sendSwitchCommand(uint8_t switchNr, ReturnValue_t onO uint16_t memoryAddress = 0; size_t parameterValueSize = sizeof(uint8_t); uint8_t parameterValue = 0; - GomspaceDeviceHandler* pdu = nullptr; + GomspaceDeviceHandler* module = nullptr; switch (switchNr) { case pcdu::PDU1_CH0_TCS_BOARD_3V3: { memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_TCS_BOARD_3V3; - pdu = ObjectManager::instance()->get(objects::PDU1_HANDLER); + module = ObjectManager::instance()->get(objects::PDU1_HANDLER); break; } case pcdu::PDU1_CH1_SYRLINKS_12V: { memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_SYRLINKS; - pdu = ObjectManager::instance()->get(objects::PDU1_HANDLER); + module = ObjectManager::instance()->get(objects::PDU1_HANDLER); break; } case pcdu::PDU1_CH2_STAR_TRACKER_5V: { memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_STAR_TRACKER; - pdu = ObjectManager::instance()->get(objects::PDU1_HANDLER); + module = ObjectManager::instance()->get(objects::PDU1_HANDLER); break; } case pcdu::PDU1_CH3_MGT_5V: { memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_MGT; - pdu = ObjectManager::instance()->get(objects::PDU1_HANDLER); + module = ObjectManager::instance()->get(objects::PDU1_HANDLER); break; } case pcdu::PDU1_CH4_SUS_NOMINAL_3V3: { memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_SUS_NOMINAL; - pdu = ObjectManager::instance()->get(objects::PDU1_HANDLER); + module = ObjectManager::instance()->get(objects::PDU1_HANDLER); break; } case pcdu::PDU1_CH5_SOLAR_CELL_EXP_5V: { memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_SOLAR_CELL_EXP; - pdu = ObjectManager::instance()->get(objects::PDU1_HANDLER); + module = ObjectManager::instance()->get(objects::PDU1_HANDLER); break; } case pcdu::PDU1_CH6_PLOC_12V: { memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_PLOC; - pdu = ObjectManager::instance()->get(objects::PDU1_HANDLER); + module = ObjectManager::instance()->get(objects::PDU1_HANDLER); break; } case pcdu::PDU1_CH7_ACS_A_SIDE_3V3: { memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_ACS_BOARD_SIDE_A; - pdu = ObjectManager::instance()->get(objects::PDU1_HANDLER); + module = ObjectManager::instance()->get(objects::PDU1_HANDLER); break; } case pcdu::PDU1_CH8_UNOCCUPIED: { memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_CHANNEL8; - pdu = ObjectManager::instance()->get(objects::PDU1_HANDLER); + module = ObjectManager::instance()->get(objects::PDU1_HANDLER); break; } // This is a dangerous command. Reject/Igore it for now @@ -283,47 +308,47 @@ ReturnValue_t PCDUHandler::sendSwitchCommand(uint8_t switchNr, ReturnValue_t onO } case pcdu::PDU2_CH1_PL_PCDU_BATT_0_14V8: { memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_PAYLOAD_PCDU_CH1; - pdu = ObjectManager::instance()->get(objects::PDU2_HANDLER); + module = ObjectManager::instance()->get(objects::PDU2_HANDLER); break; } case pcdu::PDU2_CH2_RW_5V: { memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_RW; - pdu = ObjectManager::instance()->get(objects::PDU2_HANDLER); + module = ObjectManager::instance()->get(objects::PDU2_HANDLER); break; } case pcdu::PDU2_CH3_TCS_BOARD_HEATER_IN_8V: { memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_TCS_BOARD_HEATER_IN; - pdu = ObjectManager::instance()->get(objects::PDU2_HANDLER); + module = ObjectManager::instance()->get(objects::PDU2_HANDLER); break; } case pcdu::PDU2_CH4_SUS_REDUNDANT_3V3: { memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_SUS_REDUNDANT; - pdu = ObjectManager::instance()->get(objects::PDU2_HANDLER); + module = ObjectManager::instance()->get(objects::PDU2_HANDLER); break; } case pcdu::PDU2_CH5_DEPLOYMENT_MECHANISM_8V: { memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_DEPLOYMENT_MECHANISM; - pdu = ObjectManager::instance()->get(objects::PDU2_HANDLER); + module = ObjectManager::instance()->get(objects::PDU2_HANDLER); break; } case pcdu::PDU2_CH6_PL_PCDU_BATT_1_14V8: { memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_PAYLOAD_PCDU_CH6; - pdu = ObjectManager::instance()->get(objects::PDU2_HANDLER); + module = ObjectManager::instance()->get(objects::PDU2_HANDLER); break; } case pcdu::PDU2_CH7_ACS_BOARD_SIDE_B_3V3: { memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_ACS_BOARD_SIDE_B; - pdu = ObjectManager::instance()->get(objects::PDU2_HANDLER); + module = ObjectManager::instance()->get(objects::PDU2_HANDLER); break; } case pcdu::PDU2_CH8_PAYLOAD_CAMERA: { memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_PAYLOAD_CAMERA; - pdu = ObjectManager::instance()->get(objects::PDU2_HANDLER); + module = ObjectManager::instance()->get(objects::PDU2_HANDLER); break; } case pcdu::P60_DOCK_5V_STACK: { memoryAddress = P60Dock::CONFIG_ADDRESS_OUT_EN_5V_STACK; - pdu = ObjectManager::instance()->get(objects::P60DOCK_HANDLER); + module = ObjectManager::instance()->get(objects::P60DOCK_HANDLER); break; } @@ -359,7 +384,7 @@ ReturnValue_t PCDUHandler::sendSwitchCommand(uint8_t switchNr, ReturnValue_t onO CommandMessage message; ActionMessage::setCommand(&message, GOMSPACE::PARAM_SET, storeAddress); - result = commandQueue->sendMessage(pdu->getCommandQueue(), &message, 0); + result = commandQueue->sendMessage(module->getCommandQueue(), &message, 0); if (result != returnvalue::OK) { sif::debug << "PCDUHandler::sendSwitchCommand: Failed to send message to PDU Handler" << std::endl; @@ -398,6 +423,7 @@ ReturnValue_t PCDUHandler::initializeLocalDataPool(localpool::DataPool& localDat using namespace pcdu; localDataPoolMap.emplace(PoolIds::PDU1_SWITCHES, &pdu1Switches); localDataPoolMap.emplace(PoolIds::PDU2_SWITCHES, &pdu2Switches); + localDataPoolMap.emplace(PoolIds::P60DOCK_SWITCHES, &p60Dock5VSwitch); poolManager.subscribeForRegularPeriodicPacket( subdp::RegularHkPeriodicParams(switcherSet.getSid(), false, 5.0)); return returnvalue::OK; @@ -427,8 +453,8 @@ LocalPoolDataSetBase* PCDUHandler::getDataSetHandle(sid_t sid) { } } -void PCDUHandler::checkAndUpdateSwitch(GOMSPACE::Pdu pdu, pcdu::Switches switchIdx, - uint8_t setValue) { +void PCDUHandler::checkAndUpdatePduSwitch(GOMSPACE::Pdu pdu, pcdu::Switches switchIdx, + uint8_t setValue) { using namespace pcdu; if (switchStates[switchIdx] != setValue) { #if OBSW_INITIALIZE_SWITCHES == 1 diff --git a/mission/devices/PCDUHandler.h b/mission/devices/PcduHandler.h similarity index 96% rename from mission/devices/PCDUHandler.h rename to mission/devices/PcduHandler.h index 21bb869d..d1f3996b 100644 --- a/mission/devices/PCDUHandler.h +++ b/mission/devices/PcduHandler.h @@ -56,6 +56,8 @@ class PCDUHandler : public PowerSwitchIF, /** Housekeeping manager. Handles updates of local pool variables. */ LocalDataPoolManager poolManager; + P60Dock::CoreHkSet p60CoreHk; + /** Hk table dataset of PDU1 */ PDU1::Pdu1CoreHk pdu1CoreHk; /** @@ -71,6 +73,7 @@ class PCDUHandler : public PowerSwitchIF, PoolEntry(pcdu::INIT_SWITCHES_PDU1.data(), pcdu::INIT_SWITCHES_PDU1.size()); PoolEntry pdu2Switches = PoolEntry(pcdu::INIT_SWITCHES_PDU2.data(), pcdu::INIT_SWITCHES_PDU2.size()); + PoolEntry p60Dock5VSwitch = PoolEntry(); /** The timeStamp of the current pdu2HkTableDataset */ CCSDSTime::CDS_short timeStampPdu2HkDataset; @@ -127,7 +130,7 @@ class PCDUHandler : public PowerSwitchIF, */ void updateHkTableDataset(store_address_t storeId, LocalPoolDataSetBase* dataset, CCSDSTime::CDS_short* datasetTimeStamp); - void checkAndUpdateSwitch(GOMSPACE::Pdu pdu, pcdu::Switches switchIdx, uint8_t setValue); + void checkAndUpdatePduSwitch(GOMSPACE::Pdu pdu, pcdu::Switches switchIdx, uint8_t setValue); }; #endif /* MISSION_DEVICES_PCDUHANDLER_H_ */ diff --git a/mission/devices/RadiationSensorHandler.cpp b/mission/devices/RadiationSensorHandler.cpp index bc11bb45..0520daec 100644 --- a/mission/devices/RadiationSensorHandler.cpp +++ b/mission/devices/RadiationSensorHandler.cpp @@ -2,11 +2,16 @@ #include #include #include +#include #include RadiationSensorHandler::RadiationSensorHandler(object_id_t objectId, object_id_t comIF, - CookieIF *comCookie, GpioIF *gpioIF) - : DeviceHandlerBase(objectId, comIF, comCookie), dataset(this), gpioIF(gpioIF) { + CookieIF *comCookie, GpioIF *gpioIF, + Stack5VHandler &stackHandler) + : DeviceHandlerBase(objectId, comIF, comCookie), + dataset(this), + gpioIF(gpioIF), + stackHandler(stackHandler) { if (comCookie == nullptr) { sif::error << "RadiationSensorHandler: Invalid com cookie" << std::endl; } @@ -15,18 +20,35 @@ RadiationSensorHandler::RadiationSensorHandler(object_id_t objectId, object_id_t RadiationSensorHandler::~RadiationSensorHandler() {} void RadiationSensorHandler::doStartUp() { + if (internalState == InternalState::OFF) { + ReturnValue_t retval = stackHandler.deviceToOn(StackCommander::RAD_SENSOR, true); + if (retval == BUSY) { + return; + } + internalState = InternalState::POWER_SWITCHING; + } + if (internalState == InternalState::POWER_SWITCHING) { + if (stackHandler.isSwitchOn()) { + internalState = InternalState::SETUP; + } + } if (internalState == InternalState::CONFIGURED) { if (goToNormalMode) { setMode(MODE_NORMAL); - } - - else { + } else { setMode(_MODE_TO_ON); } } } -void RadiationSensorHandler::doShutDown() { setMode(_MODE_POWER_DOWN); } +void RadiationSensorHandler::doShutDown() { + ReturnValue_t retval = stackHandler.deviceToOff(StackCommander::RAD_SENSOR, true); + if (retval == BUSY) { + return; + } + internalState = InternalState::OFF; + setMode(_MODE_POWER_DOWN); +} ReturnValue_t RadiationSensorHandler::buildNormalDeviceCommand(DeviceCommandId_t *id) { switch (communicationStep) { @@ -73,9 +95,10 @@ ReturnValue_t RadiationSensorHandler::buildCommandFromCommand(DeviceCommandId_t ReturnValue_t result = gpioIF->pullHigh(gpioIds::ENABLE_RADFET); if (result != returnvalue::OK) { #if OBSW_VERBOSE_LEVEL >= 1 - sif::warning << "RadiationSensorHandler::buildCommandFromCommand; Pulling RADFET Enale pin " - "high failed" - << std::endl; + sif::warning + << "RadiationSensorHandler::buildCommandFromCommand: Pulling RADFET Enable pin " + "high failed" + << std::endl; #endif } /* First the fifo will be reset here */ diff --git a/mission/devices/RadiationSensorHandler.h b/mission/devices/RadiationSensorHandler.h index d16cc624..b4ad39de 100644 --- a/mission/devices/RadiationSensorHandler.h +++ b/mission/devices/RadiationSensorHandler.h @@ -4,6 +4,7 @@ #include #include #include +#include /** * @brief This is the device handler class for radiation sensor on the OBC IF Board. The @@ -16,7 +17,7 @@ class RadiationSensorHandler : public DeviceHandlerBase { public: RadiationSensorHandler(object_id_t objectId, object_id_t comIF, CookieIF *comCookie, - GpioIF *gpioIF); + GpioIF *gpioIF, Stack5VHandler &handler); virtual ~RadiationSensorHandler(); void setToGoToNormalModeImmediately(); void enablePeriodicDataPrint(bool enable); @@ -39,16 +40,17 @@ class RadiationSensorHandler : public DeviceHandlerBase { private: enum class CommunicationStep { START_CONVERSION, READ_CONVERSIONS }; - enum class InternalState { SETUP, CONFIGURED }; + enum class InternalState { OFF, POWER_SWITCHING, SETUP, CONFIGURED }; bool printPeriodicData = false; RAD_SENSOR::RadSensorDataset dataset; static const uint8_t MAX_CMD_LEN = RAD_SENSOR::READ_SIZE; GpioIF *gpioIF = nullptr; + Stack5VHandler &stackHandler; bool goToNormalMode = false; uint8_t cmdBuffer[MAX_CMD_LEN]; - InternalState internalState = InternalState::SETUP; + InternalState internalState = InternalState::OFF; CommunicationStep communicationStep = CommunicationStep::START_CONVERSION; }; diff --git a/mission/devices/devicedefinitions/GomspaceDefinitions.h b/mission/devices/devicedefinitions/GomspaceDefinitions.h index ca92f5e4..75a81d8f 100644 --- a/mission/devices/devicedefinitions/GomspaceDefinitions.h +++ b/mission/devices/devicedefinitions/GomspaceDefinitions.h @@ -713,7 +713,7 @@ class AuxHk : public StaticLocalDataSet<12> { namespace pcdu { -enum PoolIds : uint32_t { PDU1_SWITCHES, PDU2_SWITCHES }; +enum PoolIds : uint32_t { PDU1_SWITCHES, PDU2_SWITCHES, P60DOCK_SWITCHES }; /* Switches are uint8_t datatype and go from 0 to 255 */ enum Switches : power::Switch_t { @@ -737,11 +737,10 @@ enum Switches : power::Switch_t { PDU2_CH7_ACS_BOARD_SIDE_B_3V3, PDU2_CH8_PAYLOAD_CAMERA, - P60_DOCK_5V_STACK + P60_DOCK_5V_STACK, + NUMBER_OF_SWITCHES }; -static constexpr uint8_t NUMBER_OF_SWITCHES = 18; - static const uint8_t ON = 1; static const uint8_t OFF = 0; @@ -771,6 +770,7 @@ class SwitcherStates : public StaticLocalDataSet { lp_vec_t(sid.objectId, PDU1_SWITCHES, this); lp_vec_t pdu2Switches = lp_vec_t(sid.objectId, PDU2_SWITCHES, this); + lp_var_t p60Dock5VStack = lp_var_t(sid.objectId, P60DOCK_SWITCHES, this); }; } // namespace pcdu diff --git a/mission/system/objects/CMakeLists.txt b/mission/system/objects/CMakeLists.txt index 23e97047..75526486 100644 --- a/mission/system/objects/CMakeLists.txt +++ b/mission/system/objects/CMakeLists.txt @@ -6,6 +6,7 @@ target_sources( ComSubsystem.cpp PayloadSubsystem.cpp AcsBoardAssembly.cpp + Stack5VHandler.cpp SusAssembly.cpp RwAssembly.cpp DualLanePowerStateMachine.cpp diff --git a/mission/system/objects/Stack5VHandler.cpp b/mission/system/objects/Stack5VHandler.cpp new file mode 100644 index 00000000..1a3141c4 --- /dev/null +++ b/mission/system/objects/Stack5VHandler.cpp @@ -0,0 +1,81 @@ +#include "Stack5VHandler.h" + +Stack5VHandler::Stack5VHandler(PowerSwitchIF& switcher) : switcher(switcher) { + stackLock = MutexFactory::instance()->createMutex(); +} + +ReturnValue_t Stack5VHandler::deviceToOn(StackCommander commander, bool updateStates) { + MutexGuard mg(stackLock); + if (updateStates) { + updateInternalStates(); + } + if (handlerState == HandlerState::SWITCH_PENDING) { + return BUSY; + } + if (switchIsOn) { + if (commander == StackCommander::PL_PCDU) { + plPcduIsOn = true; + } else { + radSensorIsOn = true; + } + return returnvalue::OK; + } + + handlerState = HandlerState::SWITCH_PENDING; + targetState = true; + return switcher.sendSwitchCommand(stackSwitch, PowerSwitchIF::SWITCH_ON); +} + +ReturnValue_t Stack5VHandler::deviceToOff(StackCommander commander, bool updateStates) { + MutexGuard mg(stackLock); + if (updateStates) { + updateInternalStates(); + } + // wait for our turn + if (handlerState == HandlerState::SWITCH_PENDING) { + return BUSY; + } + // If the switch is already off, we are done + if (not switchIsOn) { + if (commander == StackCommander::PL_PCDU) { + plPcduIsOn = false; + } else { + radSensorIsOn = false; + } + return returnvalue::OK; + } + // If one device is still on, do not turn off the switch + if ((commander == StackCommander::PL_PCDU and radSensorIsOn) or + (commander == StackCommander::RAD_SENSOR and plPcduIsOn)) { + return returnvalue::OK; + } + handlerState = HandlerState::SWITCH_PENDING; + targetState = false; + return switcher.sendSwitchCommand(stackSwitch, PowerSwitchIF::SWITCH_OFF); +} + +bool Stack5VHandler::isSwitchOn() { + MutexGuard mg(stackLock); + return updateInternalStates(); +} + +void Stack5VHandler::update() { + MutexGuard mg(stackLock); + updateInternalStates(); +} + +bool Stack5VHandler::updateInternalStates() { + if (switcher.getSwitchState(stackSwitch) == PowerSwitchIF::SWITCH_ON) { + if (handlerState == HandlerState::SWITCH_PENDING and targetState) { + handlerState = HandlerState::IDLE; + switchIsOn = true; + } + return true; + } else if (handlerState == HandlerState::SWITCH_PENDING and not targetState) { + handlerState = HandlerState::IDLE; + switchIsOn = false; + radSensorIsOn = false; + plPcduIsOn = false; + } + return false; +} diff --git a/mission/system/objects/Stack5VHandler.h b/mission/system/objects/Stack5VHandler.h new file mode 100644 index 00000000..7ade81e5 --- /dev/null +++ b/mission/system/objects/Stack5VHandler.h @@ -0,0 +1,35 @@ +#ifndef MISSION_SYSTEM_OBJECTS_STACK5VHANDLER_H_ +#define MISSION_SYSTEM_OBJECTS_STACK5VHANDLER_H_ + +#include + +#include "mission/devices/devicedefinitions/GomspaceDefinitions.h" + +enum class StackCommander { RAD_SENSOR = 0, PL_PCDU = 1 }; +enum class HandlerState { SWITCH_PENDING, IDLE }; + +class Stack5VHandler { + public: + static constexpr ReturnValue_t BUSY = returnvalue::makeCode(1, 0); + Stack5VHandler(PowerSwitchIF& switcher); + + ReturnValue_t deviceToOn(StackCommander commander, bool updateStates); + ReturnValue_t deviceToOff(StackCommander commander, bool updateStates); + + bool isSwitchOn(); + void update(); + + private: + MutexIF* stackLock; + PowerSwitchIF& switcher; + bool switchIsOn = false; + bool targetState = false; + HandlerState handlerState = HandlerState::IDLE; + bool radSensorIsOn = false; + bool plPcduIsOn = false; + pcdu::Switches stackSwitch = pcdu::Switches::P60_DOCK_5V_STACK; + + bool updateInternalStates(); +}; + +#endif /* MISSION_SYSTEM_OBJECTS_STACK5VHANDLER_H_ */ diff --git a/tmtc b/tmtc index c4dbf3d8..b032defa 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit c4dbf3d8bedc7be1848945629c6367586390c4f4 +Subproject commit b032defa7c6450cbbf21ffe8cfc50f6d5d5bc614