Merge pull request '5V stack commanding for device handlers' (#335) from mueller_5v_stack_cmd_for_devices into develop
EIVE/eive-obsw/pipeline/head This commit looks good Details

Reviewed-on: #335
Reviewed-by: Jakob Meier <meierj@irs.uni-stuttgart.de>
This commit is contained in:
Jakob Meier 2023-01-10 15:49:08 +01:00
commit 5910527d5e
16 changed files with 306 additions and 123 deletions

View File

@ -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

View File

@ -54,6 +54,7 @@
#include "linux/boardtest/LibgpiodTest.h"
#endif
#include <mission/devices/ImtqHandler.h>
#include <mission/devices/PcduHandler.h>
#include <sstream>
@ -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<void>(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<void>(plPcduHandler);

View File

@ -2,6 +2,7 @@
#define BSP_Q7S_OBJECTFACTORY_H_
#include <fsfw/returnvalues/returnvalue.h>
#include <mission/system/objects/Stack5VHandler.h>
#include <mission/tmtc/CcsdsIpCoreHandler.h>
#include <mission/tmtc/CfdpTmFunnel.h>
#include <mission/tmtc/PusTmFunnel.h>
@ -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);

View File

@ -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 */

View File

@ -3,7 +3,7 @@ target_sources(
PRIVATE GomspaceDeviceHandler.cpp
BpxBatteryHandler.cpp
Tmp1075Handler.cpp
PCDUHandler.cpp
PcduHandler.cpp
P60DockHandler.cpp
PDU1Handler.cpp
PDU2Handler.cpp

View File

@ -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);

View File

@ -4,6 +4,7 @@
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include <fsfw/globalfunctions/PeriodicOperationDivider.h>
#include <fsfw/timemanager/Countdown.h>
#include <mission/system/objects/Stack5VHandler.h>
#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<uint8_t, plpcdu::MAX_ADC_REPLY_SIZE> 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<float> processedValues =
PoolEntry<float>({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<float> tempC = PoolEntry<float>({0.0});
DualLanePowerStateMachine pwrStateMachine;
void updateSwitchGpio(gpioId_t id, gpio::Levels level);

View File

@ -1,16 +1,16 @@
#include "PCDUHandler.h"
#include <OBSWConfig.h>
#include <devices/powerSwitcherList.h>
#include <fsfw/datapool/PoolReadGuard.h>
#include <fsfw/housekeeping/HousekeepingSnapshot.h>
#include <fsfw/ipc/MutexFactory.h>
#include <fsfw/ipc/QueueFactory.h>
#include <mission/devices/PcduHandler.h>
#include <mission/devices/devicedefinitions/GomSpacePackets.h>
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<GomspaceDeviceHandler>(objects::PDU1_HANDLER);
module = ObjectManager::instance()->get<GomspaceDeviceHandler>(objects::PDU1_HANDLER);
break;
}
case pcdu::PDU1_CH1_SYRLINKS_12V: {
memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_SYRLINKS;
pdu = ObjectManager::instance()->get<GomspaceDeviceHandler>(objects::PDU1_HANDLER);
module = ObjectManager::instance()->get<GomspaceDeviceHandler>(objects::PDU1_HANDLER);
break;
}
case pcdu::PDU1_CH2_STAR_TRACKER_5V: {
memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_STAR_TRACKER;
pdu = ObjectManager::instance()->get<GomspaceDeviceHandler>(objects::PDU1_HANDLER);
module = ObjectManager::instance()->get<GomspaceDeviceHandler>(objects::PDU1_HANDLER);
break;
}
case pcdu::PDU1_CH3_MGT_5V: {
memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_MGT;
pdu = ObjectManager::instance()->get<GomspaceDeviceHandler>(objects::PDU1_HANDLER);
module = ObjectManager::instance()->get<GomspaceDeviceHandler>(objects::PDU1_HANDLER);
break;
}
case pcdu::PDU1_CH4_SUS_NOMINAL_3V3: {
memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_SUS_NOMINAL;
pdu = ObjectManager::instance()->get<GomspaceDeviceHandler>(objects::PDU1_HANDLER);
module = ObjectManager::instance()->get<GomspaceDeviceHandler>(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<GomspaceDeviceHandler>(objects::PDU1_HANDLER);
module = ObjectManager::instance()->get<GomspaceDeviceHandler>(objects::PDU1_HANDLER);
break;
}
case pcdu::PDU1_CH6_PLOC_12V: {
memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_PLOC;
pdu = ObjectManager::instance()->get<GomspaceDeviceHandler>(objects::PDU1_HANDLER);
module = ObjectManager::instance()->get<GomspaceDeviceHandler>(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<GomspaceDeviceHandler>(objects::PDU1_HANDLER);
module = ObjectManager::instance()->get<GomspaceDeviceHandler>(objects::PDU1_HANDLER);
break;
}
case pcdu::PDU1_CH8_UNOCCUPIED: {
memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_CHANNEL8;
pdu = ObjectManager::instance()->get<GomspaceDeviceHandler>(objects::PDU1_HANDLER);
module = ObjectManager::instance()->get<GomspaceDeviceHandler>(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<GomspaceDeviceHandler>(objects::PDU2_HANDLER);
module = ObjectManager::instance()->get<GomspaceDeviceHandler>(objects::PDU2_HANDLER);
break;
}
case pcdu::PDU2_CH2_RW_5V: {
memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_RW;
pdu = ObjectManager::instance()->get<GomspaceDeviceHandler>(objects::PDU2_HANDLER);
module = ObjectManager::instance()->get<GomspaceDeviceHandler>(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<GomspaceDeviceHandler>(objects::PDU2_HANDLER);
module = ObjectManager::instance()->get<GomspaceDeviceHandler>(objects::PDU2_HANDLER);
break;
}
case pcdu::PDU2_CH4_SUS_REDUNDANT_3V3: {
memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_SUS_REDUNDANT;
pdu = ObjectManager::instance()->get<GomspaceDeviceHandler>(objects::PDU2_HANDLER);
module = ObjectManager::instance()->get<GomspaceDeviceHandler>(objects::PDU2_HANDLER);
break;
}
case pcdu::PDU2_CH5_DEPLOYMENT_MECHANISM_8V: {
memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_DEPLOYMENT_MECHANISM;
pdu = ObjectManager::instance()->get<GomspaceDeviceHandler>(objects::PDU2_HANDLER);
module = ObjectManager::instance()->get<GomspaceDeviceHandler>(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<GomspaceDeviceHandler>(objects::PDU2_HANDLER);
module = ObjectManager::instance()->get<GomspaceDeviceHandler>(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<GomspaceDeviceHandler>(objects::PDU2_HANDLER);
module = ObjectManager::instance()->get<GomspaceDeviceHandler>(objects::PDU2_HANDLER);
break;
}
case pcdu::PDU2_CH8_PAYLOAD_CAMERA: {
memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_PAYLOAD_CAMERA;
pdu = ObjectManager::instance()->get<GomspaceDeviceHandler>(objects::PDU2_HANDLER);
module = ObjectManager::instance()->get<GomspaceDeviceHandler>(objects::PDU2_HANDLER);
break;
}
case pcdu::P60_DOCK_5V_STACK: {
memoryAddress = P60Dock::CONFIG_ADDRESS_OUT_EN_5V_STACK;
pdu = ObjectManager::instance()->get<GomspaceDeviceHandler>(objects::P60DOCK_HANDLER);
module = ObjectManager::instance()->get<GomspaceDeviceHandler>(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

View File

@ -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<uint8_t>(pcdu::INIT_SWITCHES_PDU1.data(), pcdu::INIT_SWITCHES_PDU1.size());
PoolEntry<uint8_t> pdu2Switches =
PoolEntry<uint8_t>(pcdu::INIT_SWITCHES_PDU2.data(), pcdu::INIT_SWITCHES_PDU2.size());
PoolEntry<uint8_t> p60Dock5VSwitch = PoolEntry<uint8_t>();
/** 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_ */

View File

@ -2,11 +2,16 @@
#include <devices/gpioIds.h>
#include <fsfw/datapool/PoolReadGuard.h>
#include <mission/devices/RadiationSensorHandler.h>
#include <mission/devices/devicedefinitions/GomspaceDefinitions.h>
#include <mission/devices/max1227.h>
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 */

View File

@ -4,6 +4,7 @@
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include <fsfw_hal/common/gpio/GpioIF.h>
#include <mission/devices/devicedefinitions/RadSensorDefinitions.h>
#include <mission/system/objects/Stack5VHandler.h>
/**
* @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;
};

View File

@ -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<NUMBER_OF_SWITCHES> {
lp_vec_t<uint8_t, PDU::CHANNELS_LEN>(sid.objectId, PDU1_SWITCHES, this);
lp_vec_t<uint8_t, PDU::CHANNELS_LEN> pdu2Switches =
lp_vec_t<uint8_t, PDU::CHANNELS_LEN>(sid.objectId, PDU2_SWITCHES, this);
lp_var_t<uint8_t> p60Dock5VStack = lp_var_t<uint8_t>(sid.objectId, P60DOCK_SWITCHES, this);
};
} // namespace pcdu

View File

@ -6,6 +6,7 @@ target_sources(
ComSubsystem.cpp
PayloadSubsystem.cpp
AcsBoardAssembly.cpp
Stack5VHandler.cpp
SusAssembly.cpp
RwAssembly.cpp
DualLanePowerStateMachine.cpp

View File

@ -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;
}

View File

@ -0,0 +1,35 @@
#ifndef MISSION_SYSTEM_OBJECTS_STACK5VHANDLER_H_
#define MISSION_SYSTEM_OBJECTS_STACK5VHANDLER_H_
#include <fsfw/power/PowerSwitchIF.h>
#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_ */

2
tmtc

@ -1 +1 @@
Subproject commit c4dbf3d8bedc7be1848945629c6367586390c4f4
Subproject commit b032defa7c6450cbbf21ffe8cfc50f6d5d5bc614