diff --git a/bsp_hosted/fsfwconfig/devices/powerSwitcherList.h b/bsp_hosted/fsfwconfig/devices/powerSwitcherList.h deleted file mode 100644 index ae259374..00000000 --- a/bsp_hosted/fsfwconfig/devices/powerSwitcherList.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef FSFWCONFIG_DEVICES_POWERSWITCHERLIST_H_ -#define FSFWCONFIG_DEVICES_POWERSWITCHERLIST_H_ - -#include - -namespace pcduSwitches { -/* Switches are uint8_t datatype and go from 0 to 255 */ -enum SwitcherList { - Q7S, - PAYLOAD_PCDU_CH1, - RW, - TCS_BOARD_8V_HEATER_IN, - SUS_REDUNDANT, - DEPLOYMENT_MECHANISM, - PAYLOAD_PCDU_CH6, - ACS_BOARD_SIDE_B, - PAYLOAD_CAMERA, - TCS_BOARD_3V3, - SYRLINKS, - STAR_TRACKER, - MGT, - SUS_NOMINAL, - SOLAR_CELL_EXP, - PLOC, - ACS_BOARD_SIDE_A, - NUMBER_OF_SWITCHES -}; - -static const uint8_t ON = 1; -static const uint8_t OFF = 0; - -/* Output states after reboot of the PDUs */ -static const uint8_t INIT_STATE_Q7S = ON; -static const uint8_t INIT_STATE_PAYLOAD_PCDU_CH1 = OFF; -static const uint8_t INIT_STATE_RW = OFF; -#if BOARD_TE0720 == 1 -/* Because the TE0720 is not connected to the PCDU, this switch is always on */ -static const uint8_t INIT_STATE_TCS_BOARD_8V_HEATER_IN = ON; -#else -static const uint8_t INIT_STATE_TCS_BOARD_8V_HEATER_IN = OFF; -#endif -static const uint8_t INIT_STATE_SUS_REDUNDANT = OFF; -static const uint8_t INIT_STATE_DEPLOYMENT_MECHANISM = OFF; -static const uint8_t INIT_STATE_PAYLOAD_PCDU_CH6 = OFF; -static const uint8_t INIT_STATE_ACS_BOARD_SIDE_B = OFF; -static const uint8_t INIT_STATE_PAYLOAD_CAMERA = OFF; -static const uint8_t INIT_STATE_TCS_BOARD_3V3 = OFF; -static const uint8_t INIT_STATE_SYRLINKS = OFF; -static const uint8_t INIT_STATE_STAR_TRACKER = OFF; -static const uint8_t INIT_STATE_MGT = OFF; -static const uint8_t INIT_STATE_SUS_NOMINAL = OFF; -static const uint8_t INIT_STATE_SOLAR_CELL_EXP = OFF; -static const uint8_t INIT_STATE_PLOC = OFF; -static const uint8_t INIT_STATE_ACS_BOARD_SIDE_A = OFF; -} // namespace pcduSwitches - -#endif /* FSFWCONFIG_DEVICES_POWERSWITCHERLIST_H_ */ diff --git a/bsp_q7s/core/CoreController.cpp b/bsp_q7s/core/CoreController.cpp index 805f932f..b0b7213c 100644 --- a/bsp_q7s/core/CoreController.cpp +++ b/bsp_q7s/core/CoreController.cpp @@ -4,9 +4,9 @@ #include "OBSWConfig.h" #include "OBSWVersion.h" -#include "fsfw/FSFWVersion.h" #include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/timemanager/Stopwatch.h" +#include "fsfw/version.h" #include "watchdogConf.h" #if OBSW_USE_TMTC_TCP_BRIDGE == 0 #include "fsfw/osal/common/UdpTmTcBridge.h" @@ -72,10 +72,10 @@ ReturnValue_t CoreController::initializeLocalDataPool(localpool::DataPool &local } LocalPoolDataSetBase *CoreController::getDataSetHandle(sid_t sid) { - if (sid.ownerSetId == core::HK_SET_ID) { - return &hkSet; - } - return nullptr; + if (sid.ownerSetId == core::HK_SET_ID) { + return &hkSet; + } + return nullptr; } ReturnValue_t CoreController::initialize() { @@ -618,6 +618,7 @@ ReturnValue_t CoreController::incrementAllocationFailureCount() { } ReturnValue_t CoreController::initVersionFile() { + using namespace fsfw; std::string unameFileName = "/tmp/uname_version.txt"; // TODO: No -v flag for now. If the kernel version is used, need to cut off first few letters std::string unameCmd = "uname -mnrso > " + unameFileName; @@ -634,9 +635,9 @@ ReturnValue_t CoreController::initVersionFile() { std::string fullObswVersionString = "OBSW: v" + std::to_string(SW_VERSION) + "." + std::to_string(SW_SUBVERSION) + "." + std::to_string(SW_REVISION); - std::string fullFsfwVersionString = "FSFW: v" + std::to_string(FSFW_VERSION) + "." + - std::to_string(FSFW_SUBVERSION) + "." + - std::to_string(FSFW_REVISION); + char versionString[16] = {}; + fsfw::FSFW_VERSION.getVersion(versionString, sizeof(versionString)); + std::string fullFsfwVersionString = "FSFW: v" + std::string(versionString); std::string systemString = "System: " + unameLine; std::string mountPrefix = SdCardManager::instance()->getCurrentMountPrefix(); std::string versionFilePath = mountPrefix + VERSION_FILE; diff --git a/bsp_q7s/core/CoreController.h b/bsp_q7s/core/CoreController.h index e890ae51..e31378ef 100644 --- a/bsp_q7s/core/CoreController.h +++ b/bsp_q7s/core/CoreController.h @@ -6,10 +6,10 @@ #include +#include "CoreDefinitions.h" #include "bsp_q7s/memory/SdCardManager.h" #include "events/subsystemIdRanges.h" #include "fsfw/controller/ExtendedControllerBase.h" -#include "CoreDefinitions.h" class Timer; class SdCardManager; diff --git a/bsp_q7s/core/CoreDefinitions.h b/bsp_q7s/core/CoreDefinitions.h index 6439af71..91896301 100644 --- a/bsp_q7s/core/CoreDefinitions.h +++ b/bsp_q7s/core/CoreDefinitions.h @@ -8,18 +8,13 @@ namespace core { static const uint8_t HK_SET_ENTRIES = 3; static const uint32_t HK_SET_ID = 5; -enum PoolIds { - TEMPERATURE, - PS_VOLTAGE, - PL_VOLTAGE -}; +enum PoolIds { TEMPERATURE, PS_VOLTAGE, PL_VOLTAGE }; /** * @brief Set storing OBC internal housekeeping data */ class HkSet : public StaticLocalDataSet { public: - HkSet(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, HK_SET_ID) {} HkSet(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, HK_SET_ID)) {} @@ -32,13 +27,13 @@ class HkSet : public StaticLocalDataSet { lp_var_t plVoltage = lp_var_t(sid.objectId, PoolIds::PL_VOLTAGE, this); void printSet() { - sif::info << "HkSet::printSet: On-chip temperature: " << this->temperature - << " °C" << std::endl; + sif::info << "HkSet::printSet: On-chip temperature: " << this->temperature << " °C" + << std::endl; sif::info << "HkSet::printSet: PS voltage: " << this->psVoltage << " mV" << std::endl; sif::info << "HkSet::printSet: PL voltage: " << this->plVoltage << " mV" << std::endl; } }; -} +} // namespace core #endif /* BSP_Q7S_CORE_COREDEFINITIONS_H_ */ diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp index de58e24e..240a4490 100644 --- a/bsp_q7s/core/ObjectFactory.cpp +++ b/bsp_q7s/core/ObjectFactory.cpp @@ -580,12 +580,13 @@ void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, UartComI MGMLIS3MDL::MAX_BUFFER_SIZE, spi::DEFAULT_LIS3_MODE, spi::DEFAULT_LIS3_SPEED); auto mgmLis3Handler = new MgmLIS3MDLHandler(objects::MGM_0_LIS3_HANDLER, objects::SPI_COM_IF, spiCookie, spi::LIS3_TRANSITION_DELAY); + static_cast(mgmLis3Handler); #if OBSW_TEST_ACS == 1 mgmLis3Handler->setStartUpImmediately(); mgmLis3Handler->setToGoToNormalMode(true); +#endif #if OBSW_DEBUG_ACS == 1 mgmLis3Handler->enablePeriodicPrintouts(true, 10); -#endif #endif spiCookie = @@ -593,25 +594,26 @@ void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, UartComI RM3100::MAX_BUFFER_SIZE, spi::DEFAULT_RM3100_MODE, spi::DEFAULT_RM3100_SPEED); auto mgmRm3100Handler = new MgmRM3100Handler(objects::MGM_1_RM3100_HANDLER, objects::SPI_COM_IF, spiCookie, spi::RM3100_TRANSITION_DELAY); + static_cast(mgmRm3100Handler); #if OBSW_TEST_ACS == 1 mgmRm3100Handler->setStartUpImmediately(); mgmRm3100Handler->setToGoToNormalMode(true); +#endif #if OBSW_DEBUG_ACS == 1 mgmRm3100Handler->enablePeriodicPrintouts(true, 10); -#endif #endif spiCookie = new SpiCookie(addresses::MGM_2_LIS3, gpioIds::MGM_2_LIS3_CS, spiDev, MGMLIS3MDL::MAX_BUFFER_SIZE, spi::DEFAULT_LIS3_MODE, spi::DEFAULT_LIS3_SPEED); - auto mgmLis3Handler2 = new MgmLIS3MDLHandler(objects::MGM_2_LIS3_HANDLER, objects::SPI_COM_IF, - spiCookie, spi::LIS3_TRANSITION_DELAY); + mgmLis3Handler = new MgmLIS3MDLHandler(objects::MGM_2_LIS3_HANDLER, objects::SPI_COM_IF, + spiCookie, spi::LIS3_TRANSITION_DELAY); #if OBSW_TEST_ACS == 1 - mgmLis3Handler2->setStartUpImmediately(); - mgmLis3Handler2->setToGoToNormalMode(true); -#if OBSW_DEBUG_ACS == 1 - mgmLis3Handler2->enablePeriodicPrintouts(true, 10); + mgmLis3Handler->setStartUpImmediately(); + mgmLis3Handler->setToGoToNormalMode(true); #endif +#if OBSW_DEBUG_ACS == 1 + mgmLis3Handler->enablePeriodicPrintouts(true, 10); #endif spiCookie = @@ -622,9 +624,9 @@ void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, UartComI #if OBSW_TEST_ACS == 1 mgmRm3100Handler->setStartUpImmediately(); mgmRm3100Handler->setToGoToNormalMode(true); +#endif #if OBSW_DEBUG_ACS == 1 mgmRm3100Handler->enablePeriodicPrintouts(true, 10); -#endif #endif // Commented until ACS board V2 in in clean room again @@ -634,12 +636,13 @@ void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, UartComI spi::DEFAULT_ADIS16507_SPEED); auto adisHandler = new GyroADIS1650XHandler(objects::GYRO_0_ADIS_HANDLER, objects::SPI_COM_IF, spiCookie, ADIS1650X::Type::ADIS16505); + static_cast(adisHandler); #if OBSW_TEST_ACS == 1 adisHandler->setStartUpImmediately(); adisHandler->setToGoToNormalModeImmediately(); +#endif #if OBSW_DEBUG_ACS == 1 adisHandler->enablePeriodicPrintouts(true, 10); -#endif #endif // Gyro 1 Side A @@ -648,13 +651,15 @@ void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, UartComI spi::DEFAULT_L3G_MODE, spi::DEFAULT_L3G_SPEED); auto gyroL3gHandler = new GyroHandlerL3GD20H(objects::GYRO_1_L3G_HANDLER, objects::SPI_COM_IF, spiCookie, spi::L3G_TRANSITION_DELAY); + static_cast(gyroL3gHandler); #if OBSW_TEST_ACS == 1 gyroL3gHandler->setStartUpImmediately(); gyroL3gHandler->setToGoToNormalMode(true); +#endif #if OBSW_DEBUG_ACS == 1 gyroL3gHandler->enablePeriodicPrintouts(true, 10); #endif -#endif + // Gyro 2 Side B spiCookie = new SpiCookie(addresses::GYRO_2_ADIS, gpioIds::GYRO_2_ADIS_CS, spiDev, ADIS1650X::MAXIMUM_REPLY_SIZE, spi::DEFAULT_ADIS16507_MODE, @@ -737,7 +742,7 @@ void ObjectFactory::createHeaterComponents() { heaterGpiosCookie->addGpio(gpioIds::HEATER_7, gpio); new HeaterHandler(objects::HEATER_HANDLER, objects::GPIO_IF, heaterGpiosCookie, - objects::PCDU_HANDLER, pcduSwitches::TCS_BOARD_8V_HEATER_IN); + objects::PCDU_HANDLER, pcduSwitches::Switches::PDU2_CH3_TCS_BOARD_HEATER_IN_8V); } void ObjectFactory::createSolarArrayDeploymentComponents() { @@ -757,8 +762,8 @@ void ObjectFactory::createSolarArrayDeploymentComponents() { // TODO: Find out burn time. For now set to 1000 ms. new SolarArrayDeploymentHandler(objects::SOLAR_ARRAY_DEPL_HANDLER, objects::GPIO_IF, solarArrayDeplCookie, objects::PCDU_HANDLER, - pcduSwitches::DEPLOYMENT_MECHANISM, gpioIds::DEPLSA1, - gpioIds::DEPLSA2, 1000); + pcduSwitches::Switches::PDU2_CH5_DEPLOYMENT_MECHANISM_8V, + gpioIds::DEPLSA1, gpioIds::DEPLSA2, 1000); } void ObjectFactory::createSyrlinksComponents() { diff --git a/bsp_q7s/core/obsw.cpp b/bsp_q7s/core/obsw.cpp index 04163a82..197ca66b 100644 --- a/bsp_q7s/core/obsw.cpp +++ b/bsp_q7s/core/obsw.cpp @@ -6,13 +6,14 @@ #include "InitMission.h" #include "OBSWConfig.h" #include "OBSWVersion.h" -#include "fsfw/FSFWVersion.h" #include "fsfw/tasks/TaskFactory.h" +#include "fsfw/version.h" #include "watchdogConf.h" static int OBSW_ALREADY_RUNNING = -2; int obsw::obsw() { + using namespace fsfw; std::cout << "-- EIVE OBSW --" << std::endl; #if BOARD_TE0720 == 0 std::cout << "-- Compiled for Linux (Xiphos Q7S) --" << std::endl; @@ -20,7 +21,7 @@ int obsw::obsw() { std::cout << "-- Compiled for Linux (TE0720) --" << std::endl; #endif std::cout << "-- OBSW v" << SW_VERSION << "." << SW_SUBVERSION << "." << SW_REVISION << ", FSFW v" - << FSFW_VERSION << "." << FSFW_SUBVERSION << "." << FSFW_REVISION << "--" << std::endl; + << FSFW_VERSION << "--" << std::endl; std::cout << "-- " << __DATE__ << " " << __TIME__ << " --" << std::endl; #if Q7S_CHECK_FOR_ALREADY_RUNNING_IMG == 1 diff --git a/bsp_q7s/devices/PlocSupervisorHandler.h b/bsp_q7s/devices/PlocSupervisorHandler.h new file mode 100644 index 00000000..b85b8ace --- /dev/null +++ b/bsp_q7s/devices/PlocSupervisorHandler.h @@ -0,0 +1,346 @@ +#ifndef MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_ +#define MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_ + +#include +#include +#include + +#include "OBSWConfig.h" +#include "devicedefinitions/PlocSupervisorDefinitions.h" + +/** + * @brief This is the device handler for the supervisor of the PLOC which is programmed by + * Thales. + * + * @details The PLOC uses the space packet protocol for communication. To each command the PLOC + * answers with at least one acknowledgment and one execution report. + * Flight manual: + * https://egit.irs.uni-stuttgart.de/redmine/projects/eive-flight-manual/wiki/PLOC_Commands + * ILH ICD: https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/ + * Arbeitsdaten/08_Used%20Components/PLOC&fileid=940960 + * @author J. Meier + */ +class PlocSupervisorHandler : public DeviceHandlerBase { + public: + PlocSupervisorHandler(object_id_t objectId, object_id_t uartComIFid, CookieIF* comCookie); + virtual ~PlocSupervisorHandler(); + + virtual ReturnValue_t initialize() override; + + protected: + void doStartUp() override; + void doShutDown() override; + ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t* id) override; + ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t* id) override; + void fillCommandAndReplyMap() override; + ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand, const uint8_t* commandData, + size_t commandDataLen) override; + ReturnValue_t scanForReply(const uint8_t* start, size_t remainingSize, DeviceCommandId_t* foundId, + size_t* foundLen) override; + ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t* packet) override; + void setNormalDatapoolEntriesInvalid() override; + uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override; + ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) override; + ReturnValue_t enableReplyInReplyMap(DeviceCommandMap::iterator command, + uint8_t expectedReplies = 1, bool useAlternateId = false, + DeviceCommandId_t alternateReplyID = 0) override; + size_t getNextReplyLength(DeviceCommandId_t deviceCommand) override; + + private: + static const uint8_t INTERFACE_ID = CLASS_ID::PLOC_SUPERVISOR_HANDLER; + + //! [EXPORT] : [COMMENT] Space Packet received from PLOC supervisor has invalid CRC + static const ReturnValue_t CRC_FAILURE = MAKE_RETURN_CODE(0xA0); + //! [EXPORT] : [COMMENT] Received ACK failure reply from PLOC supervisor + static const ReturnValue_t RECEIVED_ACK_FAILURE = MAKE_RETURN_CODE(0xA1); + //! [EXPORT] : [COMMENT] Received execution failure reply from PLOC supervisor + static const ReturnValue_t RECEIVED_EXE_FAILURE = MAKE_RETURN_CODE(0xA2); + //! [EXPORT] : [COMMENT] Received space packet with invalid APID from PLOC supervisor + static const ReturnValue_t INVALID_APID = MAKE_RETURN_CODE(0xA3); + //! [EXPORT] : [COMMENT] Failed to read current system time + static const ReturnValue_t GET_TIME_FAILURE = MAKE_RETURN_CODE(0xA4); + //! [EXPORT] : [COMMENT] Invalid communication interface specified + static const ReturnValue_t INVALID_UART_COM_IF = MAKE_RETURN_CODE(0xA5); + //! [EXPORT] : [COMMENT] Received command with invalid watchdog parameter. Valid watchdogs are 0 + //! for PS, 1 for PL and 2 for INT + static const ReturnValue_t INVALID_WATCHDOG = MAKE_RETURN_CODE(0xA6); + //! [EXPORT] : [COMMENT] Received watchdog timeout config command with invalid timeout. Valid + //! timeouts must be in the range between 1000 and 360000 ms. + static const ReturnValue_t INVALID_WATCHDOG_TIMEOUT = MAKE_RETURN_CODE(0xA7); + //! [EXPORT] : [COMMENT] Received latchup config command with invalid latchup ID + static const ReturnValue_t INVALID_LATCHUP_ID = MAKE_RETURN_CODE(0xA8); + //! [EXPORT] : [COMMENT] Received set adc sweep period command with invalid sweep period. Must be + //! larger than 21. + static const ReturnValue_t SWEEP_PERIOD_TOO_SMALL = MAKE_RETURN_CODE(0xA9); + //! [EXPORT] : [COMMENT] Receive auto EM test command with invalid test param. Valid params are 1 + //! and 2. + static const ReturnValue_t INVALID_TEST_PARAM = MAKE_RETURN_CODE(0xAA); + //! [EXPORT] : [COMMENT] Returned when scanning for MRAM dump packets failed. + static const ReturnValue_t MRAM_PACKET_PARSING_FAILURE = MAKE_RETURN_CODE(0xAB); + //! [EXPORT] : [COMMENT] Returned when the start and stop addresses of the MRAM dump or MRAM wipe + //! commands are invalid (e.g. start address bigger than stop address) + static const ReturnValue_t INVALID_MRAM_ADDRESSES = MAKE_RETURN_CODE(0xAC); + //! [EXPORT] : [COMMENT] Expect reception of an MRAM dump packet but received space packet with + //! other apid. + static const ReturnValue_t NO_MRAM_PACKET = MAKE_RETURN_CODE(0xAD); + //! [EXPORT] : [COMMENT] Path to PLOC directory on SD card does not exist + static const ReturnValue_t PATH_DOES_NOT_EXIST = MAKE_RETURN_CODE(0xAE); + //! [EXPORT] : [COMMENT] MRAM dump file does not exists. The file should actually already have + //! been created with the reception of the first dump packet. + static const ReturnValue_t MRAM_FILE_NOT_EXISTS = MAKE_RETURN_CODE(0xAF); + + static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PLOC_SUPERVISOR_HANDLER; + + //! [EXPORT] : [COMMENT] PLOC supervisor crc failure in telemetry packet + static const Event SUPV_MEMORY_READ_RPT_CRC_FAILURE = MAKE_EVENT(1, severity::LOW); + //! [EXPORT] : [COMMENT] PLOC supervisor received acknowledgment failure report + static const Event SUPV_ACK_FAILURE = MAKE_EVENT(2, severity::LOW); + //! [EXPORT] : [COMMENT] PLOC received execution failure report + static const Event SUPV_EXE_FAILURE = MAKE_EVENT(3, severity::LOW); + //! [EXPORT] : [COMMENT] PLOC supervisor reply has invalid crc + static const Event SUPV_CRC_FAILURE_EVENT = MAKE_EVENT(4, severity::LOW); + + static const uint16_t APID_MASK = 0x7FF; + static const uint16_t PACKET_SEQUENCE_COUNT_MASK = 0x3FFF; + + uint8_t commandBuffer[PLOC_SPV::MAX_COMMAND_SIZE]; + + /** + * This variable is used to store the id of the next reply to receive. This is necessary + * because the PLOC sends as reply to each command at least one acknowledgment and execution + * report. + */ + DeviceCommandId_t nextReplyId = PLOC_SPV::NONE; + + UartComIF* uartComIf = nullptr; + + PLOC_SPV::HkSet hkset; + PLOC_SPV::BootStatusReport bootStatusReport; + PLOC_SPV::LatchupStatusReport latchupStatusReport; + + /** Number of expected replies following the MRAM dump command */ + uint32_t expectedMramDumpPackets = 0; + uint32_t receivedMramDumpPackets = 0; + /** Set to true as soon as a complete space packet is present in the spacePacketBuffer */ + bool packetInBuffer = false; + /** Points to the next free position in the space packet buffer */ + uint16_t bufferTop = 0; + + /** This buffer is used to concatenate space packets received in two different read steps */ + uint8_t spacePacketBuffer[PLOC_SPV::MAX_PACKET_SIZE]; + +#if BOARD_TE0720 == 0 + SdCardManager* sdcMan = nullptr; +#endif /* BOARD_TE0720 == 0 */ + + /** Path to PLOC specific files on SD card */ + std::string plocFilePath = "ploc"; + std::string activeMramFile; + + /** Setting this variable to true will enable direct downlink of MRAM packets */ + bool downlinkMramDump = false; + + /** + * @brief This function checks the crc of the received PLOC reply. + * + * @param start Pointer to the first byte of the reply. + * @param foundLen Pointer to the length of the whole packet. + * + * @return RETURN_OK if CRC is ok, otherwise CRC_FAILURE. + */ + ReturnValue_t verifyPacket(const uint8_t* start, size_t foundLen); + + /** + * @brief This function handles the acknowledgment report. + * + * @param data Pointer to the data holding the acknowledgment report. + * + * @return RETURN_OK if successful, otherwise an error code. + */ + ReturnValue_t handleAckReport(const uint8_t* data); + + /** + * @brief This function handles the data of a execution report. + * + * @param data Pointer to the received data packet. + * + * @return RETURN_OK if successful, otherwise an error code. + */ + ReturnValue_t handleExecutionReport(const uint8_t* data); + + /** + * @brief This function handles the housekeeping report. This means verifying the CRC of the + * reply and filling the appropriate dataset. + * + * @param data Pointer to the data buffer holding the housekeeping read report. + * + * @return RETURN_OK if successful, otherwise an error code. + */ + ReturnValue_t handleHkReport(const uint8_t* data); + + /** + * @brief This function calls the function to check the CRC of the received boot status report + * and fills the associated dataset with the boot status information. + */ + ReturnValue_t handleBootStatusReport(const uint8_t* data); + + ReturnValue_t handleLatchupStatusReport(const uint8_t* data); + + /** + * @brief Depending on the current active command, this function sets the reply id of the + * next reply after a successful acknowledgment report has been received. This is + * required by the function getNextReplyLength() to identify the length of the next + * reply to read. + */ + void setNextReplyId(); + + /** + * @brief This function handles action message replies in case the telemetry has been + * requested by another object. + * + * @param data Pointer to the telemetry data. + * @param dataSize Size of telemetry in bytes. + * @param replyId Id of the reply. This will be added to the ActionMessage. + */ + void handleDeviceTM(const uint8_t* data, size_t dataSize, DeviceCommandId_t replyId); + + /** + * @brief This function prepares a space packet which does not transport any data in the + * packet data field apart from the crc. + */ + void prepareEmptyCmd(uint16_t apid); + + /** + * @brief This function initializes the space packet to select the boot image of the MPSoC. + */ + void prepareSelBootImageCmd(const uint8_t* commandData); + + void prepareDisableHk(); + + /** + * @brief This function fills the commandBuffer with the data to update the time of the + * PLOC supervisor. + */ + ReturnValue_t prepareSetTimeRefCmd(); + + /** + * @brief This function fills the commandBuffer with the data to change the boot timeout + * value in the PLOC supervisor. + */ + void prepareSetBootTimeoutCmd(const uint8_t* commandData); + + void prepareRestartTriesCmd(const uint8_t* commandData); + + /** + * @brief This function fills the command buffer with the packet to enable or disable the + * watchdogs on the PLOC. + */ + void prepareWatchdogsEnableCmd(const uint8_t* commandData); + + /** + * @brief This function fills the command buffer with the packet to set the watchdog timer + * of one of the three watchdogs (PS, PL, INT). + */ + ReturnValue_t prepareWatchdogsConfigTimeoutCmd(const uint8_t* commandData); + + ReturnValue_t prepareLatchupConfigCmd(const uint8_t* commandData, + DeviceCommandId_t deviceCommand); + ReturnValue_t prepareAutoCalibrateAlertCmd(const uint8_t* commandData); + ReturnValue_t prepareSetAlertLimitCmd(const uint8_t* commandData); + ReturnValue_t prepareSetAlertIrqFilterCmd(const uint8_t* commandData); + ReturnValue_t prepareSetAdcSweetPeriodCmd(const uint8_t* commandData); + void prepareSetAdcEnabledChannelsCmd(const uint8_t* commandData); + void prepareSetAdcWindowAndStrideCmd(const uint8_t* commandData); + void prepareSetAdcThresholdCmd(const uint8_t* commandData); + void prepareEnableNvmsCmd(const uint8_t* commandData); + void prepareSelectNvmCmd(const uint8_t* commandData); + ReturnValue_t prepareRunAutoEmTest(const uint8_t* commandData); + ReturnValue_t prepareWipeMramCmd(const uint8_t* commandData); + ReturnValue_t prepareDumpMramCmd(const uint8_t* commandData); + void preparePrintCpuStatsCmd(const uint8_t* commandData); + void prepareSetDbgVerbosityCmd(const uint8_t* commandData); + void prepareSetGpioCmd(const uint8_t* commandData); + void prepareReadGpioCmd(const uint8_t* commandData); + + /** + * @brief Copies the content of a space packet to the command buffer. + */ + void packetToOutBuffer(uint8_t* packetData, size_t fullSize); + + /** + * @brief In case an acknowledgment failure reply has been received this function disables + * all previously enabled commands and resets the exepected replies variable of an + * active command. + */ + void disableAllReplies(); + + /** + * @brief This function sends a failure report if the active action was commanded by an other + * object. + * + * @param replyId The id of the reply which signals a failure. + * @param status A status byte which gives information about the failure type. + */ + void sendFailureReport(DeviceCommandId_t replyId, ReturnValue_t status); + + /** + * @brief This function disables the execution report reply. Within this function also the + * the variable expectedReplies of an active command will be set to 0. + */ + void disableExeReportReply(); + + /** + * @brief Function is called in scanForReply and fills the spacePacketBuffer with the read + * data until a full packet has been received. + */ + ReturnValue_t parseMramPackets(const uint8_t* packet, size_t remainingSize, size_t* foundlen); + + /** + * @brief This function generates the Service 8 packets for the MRAM dump data. + */ + ReturnValue_t handleMramDumpPacket(DeviceCommandId_t id); + + /** + * @brief With this function the number of expected replies following an MRAM dump command + * will be increased. This is necessary to release the command in case not all replies + * have been received. + */ + void increaseExpectedMramReplies(DeviceCommandId_t id); + + /** + * @brief Function checks if the packet written to the space packet buffer is really a + * MRAM dump packet. + */ + ReturnValue_t checkMramPacketApid(); + + /** + * @brief Writes the data of the MRAM dump to a file. The file will be created when receiving + * the first packet. + */ + ReturnValue_t handleMramDumpFile(DeviceCommandId_t id); + + /** + * @brief Extracts the length field of a spacePacket referenced by the spacePacket pointer. + * + * @param spacePacket Pointer to the buffer holding the space packet. + * + * @return The value stored in the length field of the data field. + */ + uint16_t readSpacePacketLength(uint8_t* spacePacket); + + /** + * @brief Extracts the sequence flags from a space packet referenced by the spacePacket + * pointer. + * + * @param spacePacket Pointer to the buffer holding the space packet. + * + * @return uint8_t where the two least significant bits hold the sequence flags. + */ + uint8_t readSequenceFlags(uint8_t* spacePacket); + + ReturnValue_t createMramDumpFile(); + ReturnValue_t getTimeStampString(std::string& timeStamp); +}; + +#endif /* MISSION_DEVICES_PLOCSUPERVISORHANDLER_H_ */ diff --git a/bsp_q7s/memory/SdCardManager.cpp b/bsp_q7s/memory/SdCardManager.cpp index 06072253..4ca11787 100644 --- a/bsp_q7s/memory/SdCardManager.cpp +++ b/bsp_q7s/memory/SdCardManager.cpp @@ -1,6 +1,5 @@ #include "SdCardManager.h" -#include "OBSWConfig.h" #include #include #include @@ -10,6 +9,7 @@ #include #include +#include "OBSWConfig.h" #include "common/config/commonObjects.h" #include "fsfw/ipc/MutexFactory.h" #include "fsfw/serviceinterface/ServiceInterface.h" diff --git a/bsp_q7s/xadc/Xadc.h b/bsp_q7s/xadc/Xadc.h index f8c6e7b6..92ec2c0c 100644 --- a/bsp_q7s/xadc/Xadc.h +++ b/bsp_q7s/xadc/Xadc.h @@ -2,6 +2,7 @@ #define BSP_Q7S_XADC_XADC_H_ #include + #include "fsfw/returnvalues/HasReturnvaluesIF.h" namespace xadc { diff --git a/common/config/devices/powerSwitcherList.h b/common/config/devices/powerSwitcherList.h index 45428a2e..f99e0930 100644 --- a/common/config/devices/powerSwitcherList.h +++ b/common/config/devices/powerSwitcherList.h @@ -3,58 +3,67 @@ #include "OBSWConfig.h" +#include #include namespace pcduSwitches { - /* Switches are uint8_t datatype and go from 0 to 255 */ - enum SwitcherList: uint8_t { - Q7S, - PAYLOAD_PCDU_CH1, - RW, - TCS_BOARD_8V_HEATER_IN, - SUS_REDUNDANT, - DEPLOYMENT_MECHANISM, - PAYLOAD_PCDU_CH6, - ACS_BOARD_SIDE_B, - PAYLOAD_CAMERA, - TCS_BOARD_3V3, - SYRLINKS, - STAR_TRACKER, - MGT, - SUS_NOMINAL, - SOLAR_CELL_EXP, - PLOC, - ACS_BOARD_SIDE_A, - NUMBER_OF_SWITCHES - }; +/* Switches are uint8_t datatype and go from 0 to 255 */ +enum Switches: uint8_t { + PDU1_CH0_TCS_BOARD_3V3, + PDU1_CH1_SYRLINKS_12V, + PDU1_CH2_STAR_TRACKER_5V, + PDU1_CH3_MGT_5V, + PDU1_CH4_SUS_NOMINAL_3V3, + PDU1_CH5_SOLAR_CELL_EXP_5V, + PDU1_CH6_PLOC_12V, + PDU1_CH7_ACS_A_SIDE_3V3, + PDU1_CH8_UNOCCUPIED, - static const uint8_t ON = 1; - static const uint8_t OFF = 0; + PDU2_CH0_Q7S, + PDU2_CH1_PL_PCDU_BATT_0_14V8, + PDU2_CH2_RW_5V, + PDU2_CH3_TCS_BOARD_HEATER_IN_8V, + PDU2_CH4_SUS_REDUNDANT_3V3, + PDU2_CH5_DEPLOYMENT_MECHANISM_8V, + PDU2_CH6_PL_PCDU_BATT_1_14V8, + PDU2_CH7_ACS_BOARD_SIDE_B_3V3, + PDU2_CH8_PAYLOAD_CAMERA, + NUMBER_OF_SWITCHES +}; - /* Output states after reboot of the PDUs */ - static const uint8_t INIT_STATE_Q7S = ON; - static const uint8_t INIT_STATE_PAYLOAD_PCDU_CH1 = OFF; - static const uint8_t INIT_STATE_RW = OFF; +static const uint8_t ON = 1; +static const uint8_t OFF = 0; + +// Output states after reboot of the PDUs + +const std::array INIT_SWITCH_STATES = { + // PDU 1 +// Because the TE0720 is not connected to the PCDU, this switch is always on #if BOARD_TE0720 == 1 - /* Because the TE0720 is not connected to the PCDU, this switch is always on */ - static const uint8_t INIT_STATE_TCS_BOARD_8V_HEATER_IN = ON; + ON, #else - static const uint8_t INIT_STATE_TCS_BOARD_8V_HEATER_IN = OFF; + OFF, #endif - static const uint8_t INIT_STATE_SUS_REDUNDANT = OFF; - static const uint8_t INIT_STATE_DEPLOYMENT_MECHANISM = OFF; - static const uint8_t INIT_STATE_PAYLOAD_PCDU_CH6 = OFF; - static const uint8_t INIT_STATE_ACS_BOARD_SIDE_B = OFF; - static const uint8_t INIT_STATE_PAYLOAD_CAMERA = OFF; - static const uint8_t INIT_STATE_TCS_BOARD_3V3 = OFF; - static const uint8_t INIT_STATE_SYRLINKS = OFF; - static const uint8_t INIT_STATE_STAR_TRACKER = OFF; - static const uint8_t INIT_STATE_MGT = OFF; - static const uint8_t INIT_STATE_SUS_NOMINAL = OFF; - static const uint8_t INIT_STATE_SOLAR_CELL_EXP = OFF; - static const uint8_t INIT_STATE_PLOC = OFF; - static const uint8_t INIT_STATE_ACS_BOARD_SIDE_A = OFF; + OFF, + OFF, + OFF, + OFF, + OFF, + OFF, + OFF, + OFF, + + // PDU 2 + ON, + OFF, + OFF, + OFF, + OFF, + OFF, + OFF, + OFF, + OFF +}; } - #endif /* FSFWCONFIG_DEVICES_POWERSWITCHERLIST_H_ */ diff --git a/linux/fsfwconfig/OBSWConfig.h.in b/linux/fsfwconfig/OBSWConfig.h.in index 34e1998e..77e37189 100644 --- a/linux/fsfwconfig/OBSWConfig.h.in +++ b/linux/fsfwconfig/OBSWConfig.h.in @@ -51,18 +51,23 @@ debugging. */ #define OBSW_ADD_PLOC_MPSOC 0 #define OBSW_ADD_SUN_SENSORS 0 #define OBSW_ADD_ACS_BOARD 1 -#define OBSW_ADD_ACS_HANDLERS 0 +#define OBSW_ADD_ACS_HANDLERS 1 #define OBSW_ADD_RW 0 -#define OBSW_ADD_RTD_DEVICES 0 +#define OBSW_ADD_RTD_DEVICES 1 #define OBSW_ADD_TMP_DEVICES 0 #define OBSW_ADD_RAD_SENSORS 0 #define OBSW_ADD_PL_PCDU 0 #define OBSW_ADD_SYRLINKS 0 #define OBSW_ENABLE_SYRLINKS_TRANSMIT_TIMEOUT 0 -#define OBSW_SYRLINKS_SIMULATED 1 #define OBSW_STAR_TRACKER_GROUND_CONFIG 1 #define OBSW_ENABLE_PERIODIC_HK 0 -#define OBSW_PRINT_CORE_HK 0 + +// This is a really tricky switch.. It initializes the PCDU switches to their default states +// at powerup. I think it would be better +// to leave it off for now. It makes testing a lot more difficult and it might mess with +// something the operators might want to do by giving the software too much intelligence +// at the wrong place. The system component might command all the Switches accordingly anyway +#define OBSW_INITIALIZE_SWITCHES 0 #endif @@ -119,6 +124,7 @@ debugging. */ #define OBSW_ADD_UART_TEST_CODE 0 #define OBSW_TEST_ACS 0 +#define OBSW_TEST_ACS_BOARD_ASS 0 #define OBSW_DEBUG_ACS 0 #define OBSW_TEST_SUS 0 #define OBSW_DEBUG_SUS 0 @@ -128,16 +134,19 @@ debugging. */ #define OBSW_DEBUG_RAD_SENSOR 0 #define OBSW_TEST_PL_PCDU 0 #define OBSW_DEBUG_PL_PCDU 0 +#define OBSW_TEST_BPX_BATT 0 +#define OBSW_DEBUG_BPX_BATT 0 + #define OBSW_TEST_LIBGPIOD 0 #define OBSW_TEST_PLOC_HANDLER 0 -#define OBSW_TEST_BPX_BATT 0 #define OBSW_TEST_CCSDS_BRIDGE 0 #define OBSW_TEST_CCSDS_PTME 0 #define OBSW_TEST_TE7020_HEATER 0 #define OBSW_TEST_GPIO_OPEN_BY_LABEL 0 #define OBSW_TEST_GPIO_OPEN_BY_LINE_NAME 0 #define OBSW_DEBUG_P60DOCK 0 -#define OBSW_DEBUG_BPX_BATT 0 + +#define OBSW_PRINT_CORE_HK 0 #define OBSW_DEBUG_PDU1 0 #define OBSW_DEBUG_PDU2 0 #define OBSW_DEBUG_GPS 0 diff --git a/linux/fsfwconfig/devices/powerSwitcherList.h b/linux/fsfwconfig/devices/powerSwitcherList.h deleted file mode 100644 index cc6bc141..00000000 --- a/linux/fsfwconfig/devices/powerSwitcherList.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef FSFWCONFIG_DEVICES_POWERSWITCHERLIST_H_ -#define FSFWCONFIG_DEVICES_POWERSWITCHERLIST_H_ - -#include "OBSWConfig.h" - -namespace pcduSwitches { -/* Switches are uint8_t datatype and go from 0 to 255 */ -enum SwitcherList : uint8_t { - Q7S, - PAYLOAD_PCDU_CH1, - RW, - TCS_BOARD_8V_HEATER_IN, - SUS_REDUNDANT, - DEPLOYMENT_MECHANISM, - PAYLOAD_PCDU_CH6, - ACS_BOARD_SIDE_B, - PAYLOAD_CAMERA, - TCS_BOARD_3V3, - SYRLINKS, - STAR_TRACKER, - MGT, - SUS_NOMINAL, - SOLAR_CELL_EXP, - PLOC, - ACS_BOARD_SIDE_A, - NUMBER_OF_SWITCHES -}; - -static const uint8_t ON = 1; -static const uint8_t OFF = 0; - -/* Output states after reboot of the PDUs */ -static const uint8_t INIT_STATE_Q7S = ON; -static const uint8_t INIT_STATE_PAYLOAD_PCDU_CH1 = OFF; -static const uint8_t INIT_STATE_RW = OFF; -#if BOARD_TE0720 == 1 -/* Because the TE0720 is not connected to the PCDU, this switch is always on */ -static const uint8_t INIT_STATE_TCS_BOARD_8V_HEATER_IN = ON; -#else -static const uint8_t INIT_STATE_TCS_BOARD_8V_HEATER_IN = OFF; -#endif -static const uint8_t INIT_STATE_SUS_REDUNDANT = OFF; -static const uint8_t INIT_STATE_DEPLOYMENT_MECHANISM = OFF; -static const uint8_t INIT_STATE_PAYLOAD_PCDU_CH6 = OFF; -static const uint8_t INIT_STATE_ACS_BOARD_SIDE_B = OFF; -static const uint8_t INIT_STATE_PAYLOAD_CAMERA = OFF; -static const uint8_t INIT_STATE_TCS_BOARD_3V3 = OFF; -static const uint8_t INIT_STATE_SYRLINKS = OFF; -static const uint8_t INIT_STATE_STAR_TRACKER = OFF; -static const uint8_t INIT_STATE_MGT = OFF; -static const uint8_t INIT_STATE_SUS_NOMINAL = OFF; -static const uint8_t INIT_STATE_SOLAR_CELL_EXP = OFF; -static const uint8_t INIT_STATE_PLOC = OFF; -static const uint8_t INIT_STATE_ACS_BOARD_SIDE_A = OFF; -} // namespace pcduSwitches - -#endif /* FSFWCONFIG_DEVICES_POWERSWITCHERLIST_H_ */ diff --git a/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp b/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp index f512aad8..8cc272c2 100644 --- a/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp +++ b/linux/fsfwconfig/pollingsequence/pollingSequenceFactory.cpp @@ -32,6 +32,13 @@ ReturnValue_t pst::pstGpio(FixedTimeslotTaskIF *thisSequence) { ReturnValue_t pst::pstSpi(FixedTimeslotTaskIF *thisSequence) { uint32_t length = thisSequence->getPeriodMs(); static_cast(length); +#if OBSW_ADD_PL_PCDU == 1 + thisSequence->addSlot(objects::PLPCDU_HANDLER, length * 0, DeviceHandlerIF::PERFORM_OPERATION); + thisSequence->addSlot(objects::PLPCDU_HANDLER, length * 0.2, DeviceHandlerIF::SEND_WRITE); + thisSequence->addSlot(objects::PLPCDU_HANDLER, length * 0.4, DeviceHandlerIF::GET_WRITE); + thisSequence->addSlot(objects::PLPCDU_HANDLER, length * 0.6, DeviceHandlerIF::SEND_READ); + thisSequence->addSlot(objects::PLPCDU_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ); +#endif #if OBSW_ADD_TMP_DEVICES == 1 thisSequence->addSlot(objects::TMP1075_HANDLER_1, length * 0, DeviceHandlerIF::PERFORM_OPERATION); thisSequence->addSlot(objects::TMP1075_HANDLER_2, length * 0, DeviceHandlerIF::PERFORM_OPERATION); @@ -357,7 +364,7 @@ ReturnValue_t pst::pstSpi(FixedTimeslotTaskIF *thisSequence) { #endif #if OBSW_ADD_ACS_BOARD == 1 && OBSW_ADD_ACS_HANDLERS == 1 - bool enableAside = false; + bool enableAside = true; bool enableBside = true; if (enableAside) { // A side @@ -424,17 +431,7 @@ ReturnValue_t pst::pstSpi(FixedTimeslotTaskIF *thisSequence) { } #endif /* OBSW_ADD_ACS_BOARD == 1 && OBSW_ADD_ACS_HANDLERS == 1 */ - ReturnValue_t seqCheck = thisSequence->checkSequence(); - if (seqCheck != HasReturnvaluesIF::RETURN_OK) { - if (seqCheck == FixedTimeslotTaskIF::SLOT_LIST_EMPTY) { - sif::warning << "SPI PST is empty.." << std::endl; - } else { - sif::error << "SPI PST initialization failed" << std::endl; - } - - return seqCheck; - } - return HasReturnvaluesIF::RETURN_OK; + return thisSequence->checkSequence(); } ReturnValue_t pst::pstI2c(FixedTimeslotTaskIF *thisSequence) { @@ -456,11 +453,7 @@ ReturnValue_t pst::pstI2c(FixedTimeslotTaskIF *thisSequence) { thisSequence->addSlot(objects::BPX_BATT_HANDLER, length * 0.8, DeviceHandlerIF::GET_READ); #endif static_cast(length); - if (thisSequence->checkSequence() != HasReturnvaluesIF::RETURN_OK) { - sif::error << "I2C PST initialization failed" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - return HasReturnvaluesIF::RETURN_OK; + return thisSequence->checkSequence(); } ReturnValue_t pst::pstUart(FixedTimeslotTaskIF *thisSequence) { diff --git a/mission/devices/GomspaceDeviceHandler.cpp b/mission/devices/GomspaceDeviceHandler.cpp index 4cec651e..25bde5db 100644 --- a/mission/devices/GomspaceDeviceHandler.cpp +++ b/mission/devices/GomspaceDeviceHandler.cpp @@ -1,5 +1,9 @@ -#include -#include +#include "GomspaceDeviceHandler.h" + +#include + +#include "devicedefinitions/GomSpacePackets.h" +#include "devicedefinitions/powerDefinitions.h" GomspaceDeviceHandler::GomspaceDeviceHandler(object_id_t objectId, object_id_t comIF, CookieIF* comCookie, uint16_t maxConfigTableAddress, @@ -70,7 +74,8 @@ ReturnValue_t GomspaceDeviceHandler::buildCommandFromCommand(DeviceCommandId_t d } break; } - case (GOMSPACE::PRINT_SWITCH_V_I): { + case (GOMSPACE::PRINT_SWITCH_V_I): + case (GOMSPACE::PRINT_LATCHUPS): { result = printStatus(deviceCommand); break; } @@ -95,6 +100,7 @@ void GomspaceDeviceHandler::fillCommandAndReplyMap() { this->insertInCommandAndReplyMap(GOMSPACE::REQUEST_HK_TABLE, 3); this->insertInCommandMap(GOMSPACE::GNDWDT_RESET); this->insertInCommandMap(GOMSPACE::PRINT_SWITCH_V_I); + this->insertInCommandMap(GOMSPACE::PRINT_LATCHUPS); } ReturnValue_t GomspaceDeviceHandler::scanForReply(const uint8_t* start, size_t remainingSize, @@ -189,6 +195,12 @@ ReturnValue_t GomspaceDeviceHandler::generateSetParamCommand(const uint8_t* comm size_t commandDataLen) { ReturnValue_t result = setParamCacher.deSerialize(&commandData, &commandDataLen, SerializeIF::Endianness::BIG); + // This breaks layering but I really don't want to accept this command.. + if (setParamCacher.getAddress() == PDU2::CONFIG_ADDRESS_OUT_EN_Q7S and + this->getObjectId() == objects::PDU2_HANDLER) { + triggerEvent(power::SWITCHING_Q7S_DENIED, 0, 0); + return HasReturnvaluesIF::RETURN_FAILED; + } if (result != HasReturnvaluesIF::RETURN_OK) { sif::error << "GomspaceDeviceHandler: Failed to deserialize set parameter " "message" diff --git a/mission/devices/P60DockHandler.cpp b/mission/devices/P60DockHandler.cpp index a89debc6..b506a92b 100644 --- a/mission/devices/P60DockHandler.cpp +++ b/mission/devices/P60DockHandler.cpp @@ -217,9 +217,10 @@ void P60DockHandler::parseHkTableReply(const uint8_t *packet) { p60dockHkTableDataset.latchupsGS3V3 = *(packet + dataOffset) << 8 | *(packet + dataOffset + 1); dataOffset += 4; - p60dockHkTableDataset.vbatVoltageValue = *(packet + dataOffset) << 8 | *(packet + dataOffset + 1); + p60dockHkTableDataset.dockVbatVoltageValue = + *(packet + dataOffset) << 8 | *(packet + dataOffset + 1); dataOffset += 4; - p60dockHkTableDataset.vccCurrent = *(packet + dataOffset) << 8 | *(packet + dataOffset + 1); + p60dockHkTableDataset.dockVccCurrent = *(packet + dataOffset) << 8 | *(packet + dataOffset + 1); dataOffset += 4; p60dockHkTableDataset.batteryCurrent = *(packet + dataOffset) << 8 | *(packet + dataOffset + 1); dataOffset += 4; @@ -444,63 +445,113 @@ ReturnValue_t P60DockHandler::initializeLocalDataPool(localpool::DataPool &local } ReturnValue_t P60DockHandler::printStatus(DeviceCommandId_t cmd) { + ReturnValue_t result = RETURN_OK; switch (cmd) { case (GOMSPACE::PRINT_SWITCH_V_I): { PoolReadGuard pg(&p60dockHkTableDataset); - ReturnValue_t readResult = pg.getReadResult(); - if (readResult != HasReturnvaluesIF::RETURN_OK) { - sif::warning << "Reading PDU1 HK table failed!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; + result = pg.getReadResult(); + if (result != HasReturnvaluesIF::RETURN_OK) { + break; + } + printHkTableSwitchIV(); + return HasReturnvaluesIF::RETURN_OK; + } + case (GOMSPACE::PRINT_LATCHUPS): { + PoolReadGuard pg(&p60dockHkTableDataset); + result = pg.getReadResult(); + printHkTableLatchups(); + if (result != HasReturnvaluesIF::RETURN_OK) { + break; } - printHkTable(); return HasReturnvaluesIF::RETURN_OK; } default: { return HasReturnvaluesIF::RETURN_FAILED; } } + sif::warning << "Reading P60 Dock HK table failed" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; } -void P60DockHandler::printHkTable() { - sif::info << "P60 Dock Info: SwitchState, Currents [mA], Voltages [mV]" << std::endl; - - sif::info << std::setw(30) << std::left << "ACU VCC" << std::dec << "| " +void P60DockHandler::printHkTableSwitchIV() { + sif::info << "P60 Dock Info:" << std::endl; + sif::info << "Boot Cause: " << p60dockHkTableDataset.bootcause + << " | Boot Count: " << std::setw(4) << std::right << p60dockHkTableDataset.bootCount + << std::endl; + sif::info << "Reset Cause: " << p60dockHkTableDataset.resetcause + << " | Battery Mode: " << static_cast(p60dockHkTableDataset.battMode.value) + << std::endl; + sif::info << "SwitchState, Currents [mA], Voltages [mV]:" << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "Dock VBAT VCC" << std::dec + << "| -, " << std::setw(4) << std::right << p60dockHkTableDataset.dockVccCurrent << ", " + << std::setw(5) << p60dockHkTableDataset.dockVbatVoltageValue << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "BATT" << std::dec << "| -, " + << std::setw(4) << std::right << p60dockHkTableDataset.batteryCurrent.value << ", " + << std::setw(5) << p60dockHkTableDataset.batteryVoltage.value << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "ACU VCC" << std::dec << "| " << unsigned(p60dockHkTableDataset.outputEnableStateAcuVcc.value) << ", " << std::setw(4) << std::right << p60dockHkTableDataset.currentAcuVcc.value << ", " << std::setw(5) << p60dockHkTableDataset.voltageAcuVcc.value << std::endl; - sif::info << std::setw(30) << std::left << "ACU VBAT" << std::dec << "| " + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "ACU VBAT" << std::dec << "| " << unsigned(p60dockHkTableDataset.outputEnableStateAcuVbat.value) << ", " << std::setw(4) << std::right << p60dockHkTableDataset.currentAcuVbat.value << ", " << std::setw(5) << p60dockHkTableDataset.voltageAcuVbat.value << std::endl; - sif::info << std::setw(30) << std::left << "PDU1 VCC" << std::dec << "| " + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "PDU1 VCC" << std::dec << "| " << unsigned(p60dockHkTableDataset.outputEnableStatePdu1Vcc.value) << ", " << std::setw(4) << std::right << p60dockHkTableDataset.currentPdu1Vcc.value << ", " << std::setw(5) << p60dockHkTableDataset.voltagePdu1Vcc.value << std::endl; - sif::info << std::setw(30) << std::left << "PDU1 VBAT" << std::dec << "| " + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "PDU1 VBAT" << std::dec << "| " << unsigned(p60dockHkTableDataset.outputEnableStatePdu1Vbat.value) << ", " << std::setw(4) << std::right << p60dockHkTableDataset.currentPdu1Vbat.value << ", " << std::setw(5) << p60dockHkTableDataset.voltagePdu1Vbat.value << std::endl; - sif::info << std::setw(30) << std::left << "PDU2 VCC" << std::dec << "| " + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "PDU2 VCC" << std::dec << "| " << unsigned(p60dockHkTableDataset.outputEnableStatePdu2Vcc.value) << ", " << std::setw(4) << std::right << p60dockHkTableDataset.currentPdu2Vcc.value << ", " << std::setw(5) << p60dockHkTableDataset.voltagePdu2Vcc.value << std::endl; - sif::info << std::setw(30) << std::left << "PDU2 VBAT" << std::dec << "| " + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "PDU2 VBAT" << std::dec << "| " << unsigned(p60dockHkTableDataset.outputEnableStatePdu2Vbat.value) << ", " << std::setw(4) << std::right << p60dockHkTableDataset.currentPdu2Vbat.value << ", " << std::setw(5) << p60dockHkTableDataset.voltagePdu2Vbat.value << std::endl; - - sif::info << std::setw(30) << std::left << "Stack VBAT" << std::dec << "| " + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "Stack VBAT" << std::dec << "| " << unsigned(p60dockHkTableDataset.outputEnableStateStackVbat.value) << ", " << std::setw(4) << std::right << p60dockHkTableDataset.currentStackVbat.value << ", " << std::setw(5) << p60dockHkTableDataset.voltageStackVbat.value << std::endl; - sif::info << std::setw(30) << std::left << "Stack 3V3" << std::dec << "| " + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "Stack 3V3" << std::dec << "| " << unsigned(p60dockHkTableDataset.outputEnableStateStack3V3.value) << ", " << std::setw(4) << std::right << p60dockHkTableDataset.currentStack3V3.value << ", " << std::setw(5) << p60dockHkTableDataset.voltageStack3V3.value << std::endl; - sif::info << std::setw(30) << std::left << "Stack 5V" << std::dec << "| " + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "Stack 5V" << std::dec << "| " << unsigned(p60dockHkTableDataset.outputEnableStateStack5V.value) << ", " << std::setw(4) << std::right << p60dockHkTableDataset.currentStack5V.value << ", " << std::setw(5) << p60dockHkTableDataset.voltageStack5V.value << std::endl; } + +void P60DockHandler::printHkTableLatchups() { + sif::info << "P60 Latchup Information" << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "ACU VCC" << std::dec << "| " + << std::setw(4) << std::right << p60dockHkTableDataset.latchupsAcuVcc << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "ACU VBAT" << std::dec << "| " + << std::setw(4) << std::right << p60dockHkTableDataset.latchupsAcuVbat << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "PDU1 VCC" << std::dec << "| " + << std::setw(4) << std::right << p60dockHkTableDataset.latchupsPdu1Vcc << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "PDU1 VBAT" << std::dec << "| " + << std::setw(4) << std::right << p60dockHkTableDataset.latchupsPdu1Vbat << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "PDU2 VCC" << std::dec << "| " + << std::setw(4) << std::right << p60dockHkTableDataset.latchupsPdu2Vcc << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "PDU2 VBAT" << std::dec << "| " + << std::setw(4) << std::right << p60dockHkTableDataset.latchupsPdu2Vbat << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "Stack 3V3" << std::dec << "| " + << std::setw(4) << std::right << p60dockHkTableDataset.latchupsStack3V3 << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "Stack 5V" << std::dec << "| " + << std::setw(4) << std::right << p60dockHkTableDataset.latchupsStack5V << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "GS 3V3" << std::dec << "| " + << std::setw(4) << std::right << p60dockHkTableDataset.latchupsGS3V3 << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "GS 5V" << std::dec << "| " + << std::setw(4) << std::right << p60dockHkTableDataset.latchupsGS5V << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "X3 VBAT" << std::dec << "| " + << std::setw(4) << std::right << p60dockHkTableDataset.latchupsX3IdleVbat << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "X3 VCC" << std::dec << "| " + << std::setw(4) << std::right << p60dockHkTableDataset.latchupsX3IdleVcc << std::endl; +} diff --git a/mission/devices/P60DockHandler.h b/mission/devices/P60DockHandler.h index 937ef122..38ca391a 100644 --- a/mission/devices/P60DockHandler.h +++ b/mission/devices/P60DockHandler.h @@ -32,10 +32,12 @@ class P60DockHandler : public GomspaceDeviceHandler { */ ReturnValue_t printStatus(DeviceCommandId_t cmd) override; - void printHkTable(); + void printHkTableSwitchIV(); + void printHkTableLatchups(); private: P60Dock::HkTableDataset p60dockHkTableDataset; + static constexpr uint8_t MAX_CHANNEL_STR_WIDTH = 16; /** * @brief Function extracts the hk table information from the received csp packet and stores diff --git a/mission/devices/PCDUHandler.cpp b/mission/devices/PCDUHandler.cpp index 13bed074..e54222b1 100644 --- a/mission/devices/PCDUHandler.cpp +++ b/mission/devices/PCDUHandler.cpp @@ -1,10 +1,12 @@ #include "PCDUHandler.h" #include +#include +#include #include +#include #include #include -#include PCDUHandler::PCDUHandler(object_id_t setObjectId, size_t cmdQueueSize) : SystemObject(setObjectId), @@ -12,8 +14,10 @@ PCDUHandler::PCDUHandler(object_id_t setObjectId, size_t cmdQueueSize) pdu2HkTableDataset(this), pdu1HkTableDataset(this), cmdQueueSize(cmdQueueSize) { + auto mqArgs = MqArgs(setObjectId, static_cast(this)); commandQueue = QueueFactory::instance()->createMessageQueue( - cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE); + cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs); + pwrMutex = MutexFactory::instance()->createMutex(); } PCDUHandler::~PCDUHandler() {} @@ -23,7 +27,6 @@ ReturnValue_t PCDUHandler::performOperation(uint8_t counter) { readCommandQueue(); return RETURN_OK; } - return RETURN_OK; } @@ -74,24 +77,10 @@ ReturnValue_t PCDUHandler::initialize() { } void PCDUHandler::initializeSwitchStates() { - switchStates[pcduSwitches::Q7S] = pcduSwitches::INIT_STATE_Q7S; - switchStates[pcduSwitches::PAYLOAD_PCDU_CH1] = pcduSwitches::INIT_STATE_PAYLOAD_PCDU_CH1; - switchStates[pcduSwitches::RW] = pcduSwitches::INIT_STATE_RW; - switchStates[pcduSwitches::TCS_BOARD_8V_HEATER_IN] = - pcduSwitches::INIT_STATE_TCS_BOARD_8V_HEATER_IN; - switchStates[pcduSwitches::SUS_REDUNDANT] = pcduSwitches::INIT_STATE_SUS_REDUNDANT; - switchStates[pcduSwitches::DEPLOYMENT_MECHANISM] = pcduSwitches::INIT_STATE_DEPLOYMENT_MECHANISM; - switchStates[pcduSwitches::PAYLOAD_PCDU_CH6] = pcduSwitches::INIT_STATE_PAYLOAD_PCDU_CH6; - switchStates[pcduSwitches::ACS_BOARD_SIDE_B] = pcduSwitches::INIT_STATE_ACS_BOARD_SIDE_B; - switchStates[pcduSwitches::PAYLOAD_CAMERA] = pcduSwitches::INIT_STATE_PAYLOAD_CAMERA; - switchStates[pcduSwitches::TCS_BOARD_3V3] = pcduSwitches::INIT_STATE_TCS_BOARD_3V3; - switchStates[pcduSwitches::SYRLINKS] = pcduSwitches::INIT_STATE_SYRLINKS; - switchStates[pcduSwitches::STAR_TRACKER] = pcduSwitches::INIT_STATE_STAR_TRACKER; - switchStates[pcduSwitches::MGT] = pcduSwitches::INIT_STATE_MGT; - switchStates[pcduSwitches::SUS_NOMINAL] = pcduSwitches::INIT_STATE_SUS_NOMINAL; - switchStates[pcduSwitches::SOLAR_CELL_EXP] = pcduSwitches::INIT_STATE_SOLAR_CELL_EXP; - switchStates[pcduSwitches::PLOC] = pcduSwitches::INIT_STATE_PLOC; - switchStates[pcduSwitches::ACS_BOARD_SIDE_A] = pcduSwitches::INIT_STATE_ACS_BOARD_SIDE_A; + using namespace pcduSwitches; + for (uint8_t idx = 0; idx < Switches::NUMBER_OF_SWITCHES; idx++) { + switchStates[idx] = INIT_SWITCH_STATES[idx]; + } } void PCDUHandler::readCommandQueue() { @@ -111,7 +100,7 @@ void PCDUHandler::readCommandQueue() { MessageQueueId_t PCDUHandler::getCommandQueue() const { return commandQueue->getId(); } -void PCDUHandler::handleChangedDataset(sid_t sid, store_address_t storeId) { +void PCDUHandler::handleChangedDataset(sid_t sid, store_address_t storeId, bool* clearMessage) { if (sid == sid_t(objects::PDU2_HANDLER, PDU2::HK_TABLE_DATA_SET_ID)) { updateHkTableDataset(storeId, &pdu2HkTableDataset, &timeStampPdu2HkDataset); updatePdu2SwitchStates(); @@ -152,63 +141,176 @@ void PCDUHandler::updateHkTableDataset(store_address_t storeId, LocalPoolDataSet } void PCDUHandler::updatePdu2SwitchStates() { - // TODO: pool read helper - if (pdu2HkTableDataset.read() == RETURN_OK) { - switchStates[pcduSwitches::Q7S] = pdu2HkTableDataset.outEnabledQ7S.value; - switchStates[pcduSwitches::PAYLOAD_PCDU_CH1] = pdu2HkTableDataset.outEnabledPlPCDUCh1.value; - switchStates[pcduSwitches::RW] = pdu2HkTableDataset.outEnabledReactionWheels.value; - switchStates[pcduSwitches::TCS_BOARD_8V_HEATER_IN] = - pdu2HkTableDataset.outEnabledTCSBoardHeaterIn.value; - switchStates[pcduSwitches::SUS_REDUNDANT] = pdu2HkTableDataset.outEnabledSUSRedundant.value; - switchStates[pcduSwitches::DEPLOYMENT_MECHANISM] = - pdu2HkTableDataset.outEnabledDeplMechanism.value; - switchStates[pcduSwitches::PAYLOAD_PCDU_CH6] = pdu2HkTableDataset.outEnabledPlPCDUCh6.value; - switchStates[pcduSwitches::ACS_BOARD_SIDE_B] = pdu2HkTableDataset.outEnabledAcsBoardSideB.value; - switchStates[pcduSwitches::PAYLOAD_CAMERA] = pdu2HkTableDataset.outEnabledPayloadCamera.value; + using namespace pcduSwitches; + GOMSPACE::Pdu pdu = GOMSPACE::Pdu::PDU2; + PoolReadGuard rg(&pdu2HkTableDataset); + if (rg.getReadResult() == RETURN_OK) { + MutexGuard mg(pwrMutex); + checkAndUpdateSwitch(pdu, Switches::PDU2_CH0_Q7S, pdu2HkTableDataset.outEnabledQ7S.value); + + checkAndUpdateSwitch(pdu, Switches::PDU2_CH1_PL_PCDU_BATT_0_14V8, + pdu2HkTableDataset.outEnabledPlPCDUCh1.value); + checkAndUpdateSwitch(pdu, Switches::PDU2_CH2_RW_5V, + pdu2HkTableDataset.outEnabledReactionWheels.value); + checkAndUpdateSwitch(pdu, Switches::PDU2_CH3_TCS_BOARD_HEATER_IN_8V, + pdu2HkTableDataset.outEnabledTCSBoardHeaterIn.value); + checkAndUpdateSwitch(pdu, Switches::PDU2_CH4_SUS_REDUNDANT_3V3, + pdu2HkTableDataset.outEnabledSUSRedundant.value); + checkAndUpdateSwitch(pdu, Switches::PDU2_CH5_DEPLOYMENT_MECHANISM_8V, + pdu2HkTableDataset.outEnabledDeplMechanism.value); + checkAndUpdateSwitch(pdu, Switches::PDU2_CH6_PL_PCDU_BATT_1_14V8, + pdu2HkTableDataset.outEnabledPlPCDUCh6.value); + checkAndUpdateSwitch(pdu, Switches::PDU2_CH7_ACS_BOARD_SIDE_B_3V3, + pdu2HkTableDataset.outEnabledAcsBoardSideB.value); + checkAndUpdateSwitch(pdu, Switches::PDU2_CH8_PAYLOAD_CAMERA, + pdu2HkTableDataset.outEnabledPayloadCamera.value); + if (firstSwitchInfoPdu2) { + firstSwitchInfoPdu2 = false; + } } else { sif::debug << "PCDUHandler::updatePdu2SwitchStates: Failed to read PDU2 Hk Dataset" << std::endl; } - pdu2HkTableDataset.commit(); } void PCDUHandler::updatePdu1SwitchStates() { - if (pdu1HkTableDataset.read() == RETURN_OK) { - switchStates[pcduSwitches::TCS_BOARD_3V3] = pdu1HkTableDataset.voltageOutTCSBoard3V3.value; - switchStates[pcduSwitches::SYRLINKS] = pdu1HkTableDataset.voltageOutSyrlinks.value; - switchStates[pcduSwitches::STAR_TRACKER] = pdu1HkTableDataset.voltageOutStarTracker.value; - switchStates[pcduSwitches::MGT] = pdu1HkTableDataset.voltageOutMGT.value; - switchStates[pcduSwitches::SUS_NOMINAL] = pdu1HkTableDataset.voltageOutSUSNominal.value; - switchStates[pcduSwitches::SOLAR_CELL_EXP] = pdu1HkTableDataset.voltageOutSolarCellExp.value; - switchStates[pcduSwitches::PLOC] = pdu1HkTableDataset.voltageOutPLOC.value; - switchStates[pcduSwitches::ACS_BOARD_SIDE_A] = pdu1HkTableDataset.voltageOutACSBoardSideA.value; + using namespace pcduSwitches; + PoolReadGuard rg(&pdu1HkTableDataset); + GOMSPACE::Pdu pdu = GOMSPACE::Pdu::PDU1; + if (rg.getReadResult() == RETURN_OK) { + MutexGuard mg(pwrMutex); + checkAndUpdateSwitch(pdu, Switches::PDU1_CH0_TCS_BOARD_3V3, + pdu1HkTableDataset.outEnabledTCSBoard3V3.value); + checkAndUpdateSwitch(pdu, Switches::PDU1_CH1_SYRLINKS_12V, + pdu1HkTableDataset.outEnabledSyrlinks.value); + checkAndUpdateSwitch(pdu, Switches::PDU1_CH2_STAR_TRACKER_5V, + pdu1HkTableDataset.outEnabledStarTracker.value); + checkAndUpdateSwitch(pdu, Switches::PDU1_CH3_MGT_5V, pdu1HkTableDataset.outEnabledMGT.value); + checkAndUpdateSwitch(pdu, Switches::PDU1_CH4_SUS_NOMINAL_3V3, + pdu1HkTableDataset.outEnabledSUSNominal.value); + checkAndUpdateSwitch(pdu, Switches::PDU1_CH5_SOLAR_CELL_EXP_5V, + pdu1HkTableDataset.outEnabledSolarCellExp.value); + checkAndUpdateSwitch(pdu, Switches::PDU1_CH6_PLOC_12V, pdu1HkTableDataset.outEnabledPLOC.value); + checkAndUpdateSwitch(pdu, Switches::PDU1_CH7_ACS_A_SIDE_3V3, + pdu1HkTableDataset.outEnabledAcsBoardSideA.value); + checkAndUpdateSwitch(pdu, Switches::PDU1_CH8_UNOCCUPIED, + pdu1HkTableDataset.outEnabledChannel8.value); + if (firstSwitchInfoPdu1) { + firstSwitchInfoPdu1 = false; + } } else { sif::debug << "PCDUHandler::updatePdu1SwitchStates: Failed to read dataset" << std::endl; } - pdu1HkTableDataset.commit(); } LocalDataPoolManager* PCDUHandler::getHkManagerHandle() { return &poolManager; } void PCDUHandler::sendSwitchCommand(uint8_t switchNr, ReturnValue_t onOff) const { + using namespace pcduSwitches; ReturnValue_t result; - uint16_t memoryAddress; + uint16_t memoryAddress = 0; size_t parameterValueSize = sizeof(uint8_t); - uint8_t parameterValue; - GomspaceDeviceHandler* pdu; + uint8_t parameterValue = 0; + GomspaceDeviceHandler* pdu = nullptr; switch (switchNr) { - case pcduSwitches::TCS_BOARD_8V_HEATER_IN: + case pcduSwitches::PDU1_CH0_TCS_BOARD_3V3: { + memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_TCS_BOARD_3V3; + pdu = ObjectManager::instance()->get(objects::PDU1_HANDLER); + break; + } + case pcduSwitches::PDU1_CH1_SYRLINKS_12V: { + memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_SYRLINKS; + pdu = ObjectManager::instance()->get(objects::PDU1_HANDLER); + break; + } + case pcduSwitches::PDU1_CH2_STAR_TRACKER_5V: { + memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_STAR_TRACKER; + pdu = ObjectManager::instance()->get(objects::PDU1_HANDLER); + break; + } + case pcduSwitches::PDU1_CH3_MGT_5V: { + memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_MGT; + pdu = ObjectManager::instance()->get(objects::PDU1_HANDLER); + break; + } + case pcduSwitches::PDU1_CH4_SUS_NOMINAL_3V3: { + memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_SUS_NOMINAL; + pdu = ObjectManager::instance()->get(objects::PDU1_HANDLER); + break; + } + case pcduSwitches::PDU1_CH5_SOLAR_CELL_EXP_5V: { + memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_SOLAR_CELL_EXP; + pdu = ObjectManager::instance()->get(objects::PDU1_HANDLER); + break; + } + case pcduSwitches::PDU1_CH6_PLOC_12V: { + memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_PLOC; + pdu = ObjectManager::instance()->get(objects::PDU1_HANDLER); + break; + } + case pcduSwitches::PDU1_CH7_ACS_A_SIDE_3V3: { + memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_ACS_BOARD_SIDE_A; + pdu = ObjectManager::instance()->get(objects::PDU1_HANDLER); + break; + } + case pcduSwitches::PDU1_CH8_UNOCCUPIED: { + memoryAddress = PDU1::CONFIG_ADDRESS_OUT_EN_CHANNEL8; + pdu = ObjectManager::instance()->get(objects::PDU1_HANDLER); + break; + } + // This is a dangerous command. Reject/Igore it for now + case pcduSwitches::PDU2_CH0_Q7S: { + return; + // memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_Q7S; + // pdu = ObjectManager::instance()->get(objects::PDU2_HANDLER); + // break; + } + case pcduSwitches::PDU2_CH1_PL_PCDU_BATT_0_14V8: { + memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_PAYLOAD_PCDU_CH1; + pdu = ObjectManager::instance()->get(objects::PDU2_HANDLER); + break; + } + case pcduSwitches::PDU2_CH2_RW_5V: { + memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_RW; + pdu = ObjectManager::instance()->get(objects::PDU2_HANDLER); + break; + } + case pcduSwitches::PDU2_CH3_TCS_BOARD_HEATER_IN_8V: { memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_TCS_BOARD_HEATER_IN; pdu = ObjectManager::instance()->get(objects::PDU2_HANDLER); break; - case pcduSwitches::DEPLOYMENT_MECHANISM: + } + case pcduSwitches::PDU2_CH4_SUS_REDUNDANT_3V3: { + memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_SUS_REDUNDANT; + pdu = ObjectManager::instance()->get(objects::PDU2_HANDLER); + break; + } + case pcduSwitches::PDU2_CH5_DEPLOYMENT_MECHANISM_8V: { memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_DEPLOYMENT_MECHANISM; pdu = ObjectManager::instance()->get(objects::PDU2_HANDLER); break; - default: + } + case pcduSwitches::PDU2_CH6_PL_PCDU_BATT_1_14V8: { + memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_PAYLOAD_PCDU_CH6; + pdu = ObjectManager::instance()->get(objects::PDU2_HANDLER); + break; + } + case pcduSwitches::PDU2_CH7_ACS_BOARD_SIDE_B_3V3: { + memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_ACS_BOARD_SIDE_B; + pdu = ObjectManager::instance()->get(objects::PDU2_HANDLER); + break; + } + case pcduSwitches::PDU2_CH8_PAYLOAD_CAMERA: { + memoryAddress = PDU2::CONFIG_ADDRESS_OUT_EN_PAYLOAD_CAMERA; + pdu = ObjectManager::instance()->get(objects::PDU2_HANDLER); + break; + } + + default: { sif::error << "PCDUHandler::sendSwitchCommand: Invalid switch number " << std::endl; return; + } } switch (onOff) { @@ -241,6 +343,9 @@ void PCDUHandler::sendSwitchCommand(uint8_t switchNr, ReturnValue_t onOff) const if (result != RETURN_OK) { sif::debug << "PCDUHandler::sendSwitchCommand: Failed to send message to PDU Handler" << std::endl; + } else { + // Can't use trigger event because of const function constraint, but this hack seems to work + this->forwardEvent(power::SWITCH_CMD_SENT, parameterValue, switchNr); } } @@ -251,7 +356,10 @@ ReturnValue_t PCDUHandler::getSwitchState(uint8_t switchNr) const { sif::debug << "PCDUHandler::getSwitchState: Invalid switch number" << std::endl; return RETURN_FAILED; } - if (switchStates[switchNr] == 1) { + pwrMutex->lockMutex(); + uint8_t currentState = switchStates[switchNr]; + pwrMutex->unlockMutex(); + if (currentState == 1) { return PowerSwitchIF::SWITCH_ON; } else { return PowerSwitchIF::SWITCH_OFF; @@ -266,6 +374,7 @@ object_id_t PCDUHandler::getObjectId() const { return SystemObject::getObjectId( ReturnValue_t PCDUHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap, LocalDataPoolManager& poolManager) { + using namespace pcduSwitches; localDataPoolMap.emplace(P60System::PDU2_CURRENT_OUT_Q7S, new PoolEntry({0})); localDataPoolMap.emplace(P60System::PDU2_CURRENT_OUT_PAYLOAD_PCDU_CH1, new PoolEntry({0})); @@ -304,28 +413,34 @@ ReturnValue_t PCDUHandler::initializeLocalDataPool(localpool::DataPool& localDat localDataPoolMap.emplace(P60System::PDU2_CONV_EN_3, new PoolEntry({0})); localDataPoolMap.emplace(P60System::PDU2_OUT_EN_Q7S, - new PoolEntry({pcduSwitches::INIT_STATE_Q7S})); - localDataPoolMap.emplace(P60System::PDU2_OUT_EN_PAYLOAD_PCDU_CH1, - new PoolEntry({pcduSwitches::INIT_STATE_PAYLOAD_PCDU_CH1})); + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU2_CH0_Q7S]})); + localDataPoolMap.emplace( + P60System::PDU2_OUT_EN_PAYLOAD_PCDU_CH1, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU2_CH1_PL_PCDU_BATT_0_14V8]})); localDataPoolMap.emplace(P60System::PDU2_OUT_EN_RW, - new PoolEntry({pcduSwitches::INIT_STATE_RW})); + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU2_CH2_RW_5V]})); #if BOARD_TE0720 == 1 localDataPoolMap.emplace(P60System::PDU2_OUT_EN_TCS_BOARD_HEATER_IN, new PoolEntry({1})); #else localDataPoolMap.emplace( P60System::PDU2_OUT_EN_TCS_BOARD_HEATER_IN, - new PoolEntry({pcduSwitches::INIT_STATE_TCS_BOARD_8V_HEATER_IN})); + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU2_CH3_TCS_BOARD_HEATER_IN_8V]})); #endif - localDataPoolMap.emplace(P60System::PDU2_OUT_EN_SUS_REDUNDANT, - new PoolEntry({pcduSwitches::INIT_STATE_SUS_REDUNDANT})); - localDataPoolMap.emplace(P60System::PDU2_OUT_EN_DEPLOYMENT_MECHANISM, - new PoolEntry({pcduSwitches::INIT_STATE_DEPLOYMENT_MECHANISM})); - localDataPoolMap.emplace(P60System::PDU2_OUT_EN_PAYLOAD_PCDU_CH6, - new PoolEntry({pcduSwitches::INIT_STATE_PAYLOAD_PCDU_CH6})); - localDataPoolMap.emplace(P60System::PDU2_OUT_EN_ACS_BOARD_SIDE_B, - new PoolEntry({pcduSwitches::INIT_STATE_ACS_BOARD_SIDE_B})); - localDataPoolMap.emplace(P60System::PDU2_OUT_EN_PAYLOAD_CAMERA, - new PoolEntry({pcduSwitches::INIT_STATE_PAYLOAD_CAMERA})); + localDataPoolMap.emplace( + P60System::PDU2_OUT_EN_SUS_REDUNDANT, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU2_CH4_SUS_REDUNDANT_3V3]})); + localDataPoolMap.emplace( + P60System::PDU2_OUT_EN_DEPLOYMENT_MECHANISM, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU2_CH5_DEPLOYMENT_MECHANISM_8V]})); + localDataPoolMap.emplace( + P60System::PDU2_OUT_EN_PAYLOAD_PCDU_CH6, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU2_CH6_PL_PCDU_BATT_1_14V8]})); + localDataPoolMap.emplace( + P60System::PDU2_OUT_EN_ACS_BOARD_SIDE_B, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU2_CH7_ACS_BOARD_SIDE_B_3V3]})); + localDataPoolMap.emplace( + P60System::PDU2_OUT_EN_PAYLOAD_CAMERA, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU2_CH8_PAYLOAD_CAMERA]})); localDataPoolMap.emplace(P60System::PDU2_BOOTCAUSE, new PoolEntry({0})); localDataPoolMap.emplace(P60System::PDU2_BOOTCNT, new PoolEntry({0})); @@ -387,16 +502,32 @@ ReturnValue_t PCDUHandler::initializeLocalDataPool(localpool::DataPool& localDat new PoolEntry({0})); localDataPoolMap.emplace(P60System::PDU1_CURRENT_OUT_CHANNEL8, new PoolEntry({0})); - localDataPoolMap.emplace(P60System::PDU1_VOLTAGE_OUT_TCS_BOARD_3V3, new PoolEntry({0})); - localDataPoolMap.emplace(P60System::PDU1_VOLTAGE_OUT_SYRLINKS, new PoolEntry({0})); - localDataPoolMap.emplace(P60System::PDU1_VOLTAGE_OUT_STAR_TRACKER, new PoolEntry({0})); - localDataPoolMap.emplace(P60System::PDU1_VOLTAGE_OUT_MGT, new PoolEntry({0})); - localDataPoolMap.emplace(P60System::PDU1_VOLTAGE_OUT_SUS_NOMINAL, new PoolEntry({0})); - localDataPoolMap.emplace(P60System::PDU1_VOLTAGE_OUT_SOLAR_CELL_EXP, new PoolEntry({0})); - localDataPoolMap.emplace(P60System::PDU1_VOLTAGE_OUT_PLOC, new PoolEntry({0})); - localDataPoolMap.emplace(P60System::PDU1_VOLTAGE_OUT_ACS_BOARD_SIDE_A, - new PoolEntry({0})); - localDataPoolMap.emplace(P60System::PDU1_VOLTAGE_OUT_CHANNEL8, new PoolEntry({0})); + localDataPoolMap.emplace( + P60System::PDU1_VOLTAGE_OUT_TCS_BOARD_3V3, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU1_CH0_TCS_BOARD_3V3]})); + localDataPoolMap.emplace( + P60System::PDU1_VOLTAGE_OUT_SYRLINKS, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU1_CH1_SYRLINKS_12V]})); + localDataPoolMap.emplace( + P60System::PDU1_VOLTAGE_OUT_STAR_TRACKER, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU1_CH2_STAR_TRACKER_5V]})); + localDataPoolMap.emplace(P60System::PDU1_VOLTAGE_OUT_MGT, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU1_CH3_MGT_5V]})); + localDataPoolMap.emplace( + P60System::PDU1_VOLTAGE_OUT_SUS_NOMINAL, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU1_CH4_SUS_NOMINAL_3V3]})); + localDataPoolMap.emplace( + P60System::PDU1_VOLTAGE_OUT_SOLAR_CELL_EXP, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU1_CH5_SOLAR_CELL_EXP_5V]})); + localDataPoolMap.emplace( + P60System::PDU1_VOLTAGE_OUT_PLOC, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU1_CH6_PLOC_12V]})); + localDataPoolMap.emplace( + P60System::PDU1_VOLTAGE_OUT_ACS_BOARD_SIDE_A, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU1_CH7_ACS_A_SIDE_3V3]})); + localDataPoolMap.emplace( + P60System::PDU1_VOLTAGE_OUT_CHANNEL8, + new PoolEntry({INIT_SWITCH_STATES[Switches::PDU1_CH8_UNOCCUPIED]})); localDataPoolMap.emplace(P60System::PDU1_VCC, new PoolEntry({0})); localDataPoolMap.emplace(P60System::PDU1_VBAT, new PoolEntry({0})); @@ -486,3 +617,27 @@ LocalPoolDataSetBase* PCDUHandler::getDataSetHandle(sid_t sid) { return nullptr; } } + +void PCDUHandler::checkAndUpdateSwitch(GOMSPACE::Pdu pdu, pcduSwitches::Switches switchIdx, + uint8_t setValue) { + using namespace pcduSwitches; + if (switchStates[switchIdx] != setValue) { +#if OBSW_INITIALIZE_SWITCHES == 1 + // This code initializes the switches to the default init switch states on every reboot. + // This is not done by the PCDU unless it is power-cycled. + if (((pdu == GOMSPACE::Pdu::PDU1) and firstSwitchInfoPdu1) or + ((pdu == GOMSPACE::Pdu::PDU2) and firstSwitchInfoPdu2)) { + ReturnValue_t state = PowerSwitchIF::SWITCH_OFF; + if (INIT_SWITCH_STATES[switchIdx] == ON) { + state = PowerSwitchIF::SWITCH_ON; + } + sendSwitchCommand(switchIdx, state); + } else { + triggerEvent(power::SWITCH_HAS_CHANGED, setValue, switchIdx); + } +#else + triggerEvent(power::SWITCH_HAS_CHANGED, setValue, switchIdx); +#endif + } + switchStates[switchIdx] = setValue; +} diff --git a/mission/devices/PCDUHandler.h b/mission/devices/PCDUHandler.h index c045ed03..3d014205 100644 --- a/mission/devices/PCDUHandler.h +++ b/mission/devices/PCDUHandler.h @@ -8,13 +8,16 @@ #include #include #include -#include + +#include "devicedefinitions/GomspaceDefinitions.h" +#include "devicedefinitions/powerDefinitions.h" /** * @brief The PCDUHandler provides a compact interface to handle all devices related to the - * control of power. This is necessary because the fsfw manages all power - * related functionalities via one power object. This includes for example the switch on and off of - * devices. + * control of power. + * @details + * This is necessary because the FSFW manages all power related functionalities via one + * power object. This includes for example switching on and off of devices. */ class PCDUHandler : public PowerSwitchIF, public HasLocalDataPoolIF, @@ -27,7 +30,8 @@ class PCDUHandler : public PowerSwitchIF, virtual ReturnValue_t initialize() override; virtual ReturnValue_t performOperation(uint8_t counter) override; virtual void handleChangedDataset(sid_t sid, - store_address_t storeId = storeId::INVALID_STORE_ADDRESS); + store_address_t storeId = storeId::INVALID_STORE_ADDRESS, + bool* clearMessage = nullptr) override; virtual void sendSwitchCommand(uint8_t switchNr, ReturnValue_t onOff) const override; virtual void sendFuseOnCommand(uint8_t fuseNr) const override; @@ -47,6 +51,7 @@ class PCDUHandler : public PowerSwitchIF, private: uint32_t pstIntervalMs = 0; + MutexIF* pwrMutex = nullptr; /** Housekeeping manager. Handles updates of local pool variables. */ LocalDataPoolManager poolManager; @@ -79,6 +84,8 @@ class PCDUHandler : public PowerSwitchIF, MessageQueueIF* commandQueue = nullptr; size_t cmdQueueSize; + bool firstSwitchInfoPdu1 = true; + bool firstSwitchInfoPdu2 = true; PeriodicTaskIF* executingTask = nullptr; @@ -112,6 +119,7 @@ class PCDUHandler : public PowerSwitchIF, */ void updateHkTableDataset(store_address_t storeId, LocalPoolDataSetBase* dataset, CCSDSTime::CDS_short* datasetTimeStamp); + void checkAndUpdateSwitch(GOMSPACE::Pdu pdu, pcduSwitches::Switches switchIdx, uint8_t setValue); }; #endif /* MISSION_DEVICES_PCDUHANDLER_H_ */ diff --git a/mission/devices/PDU1Handler.cpp b/mission/devices/PDU1Handler.cpp index 48b79551..38256cf9 100644 --- a/mission/devices/PDU1Handler.cpp +++ b/mission/devices/PDU1Handler.cpp @@ -412,30 +412,51 @@ ReturnValue_t PDU1Handler::initializeLocalDataPool(localpool::DataPool &localDat localDataPoolMap.emplace(P60System::PDU1_WDT_CAN_LEFT, new PoolEntry({0})); localDataPoolMap.emplace(P60System::PDU1_WDT_CSP_LEFT1, new PoolEntry({0})); localDataPoolMap.emplace(P60System::PDU1_WDT_CSP_LEFT2, new PoolEntry({0})); - +#if OBSW_ENABLE_PERIODIC_HK == 1 + poolManager.subscribeForPeriodicPacket(pdu1HkTableDataset.getSid(), false, 0.4, true); +#endif return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t PDU1Handler::printStatus(DeviceCommandId_t cmd) { + ReturnValue_t result = RETURN_OK; switch (cmd) { case (GOMSPACE::PRINT_SWITCH_V_I): { PoolReadGuard pg(&pdu1HkTableDataset); - ReturnValue_t readResult = pg.getReadResult(); - if (readResult != HasReturnvaluesIF::RETURN_OK) { - sif::warning << "Reading PDU1 HK table failed!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; + result = pg.getReadResult(); + if (result != HasReturnvaluesIF::RETURN_OK) { + break; } - printHkTable(); - return HasReturnvaluesIF::RETURN_OK; + printHkTableSwitchVI(); + break; + } + case (GOMSPACE::PRINT_LATCHUPS): { + PoolReadGuard pg(&pdu1HkTableDataset); + result = pg.getReadResult(); + if (result != HasReturnvaluesIF::RETURN_OK) { + break; + } + printHkTableLatchups(); + break; } default: { return HasReturnvaluesIF::RETURN_FAILED; } } + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "Reading PDU1 HK table failed!" << std::endl; + } + return result; } -void PDU1Handler::printHkTable() { - sif::info << "PDU1 Info: SwitchState, Currents [mA], Voltages [mV]" << std::endl; +void PDU1Handler::printHkTableSwitchVI() { + sif::info << "PDU1 Info: " << std::endl; + sif::info << "Boot Cause: " << pdu1HkTableDataset.bootcause << " | Boot Count: " << std::setw(4) + << std::right << pdu1HkTableDataset.bootcount << std::endl; + sif::info << "Reset Cause: " << pdu1HkTableDataset.resetcause + << " | Battery Mode: " << static_cast(pdu1HkTableDataset.battMode.value) + << std::endl; + sif::info << "SwitchState, Currents [mA], Voltages [mV]:" << std::endl; sif::info << std::setw(30) << std::left << "TCS Board" << std::dec << "| " << unsigned(pdu1HkTableDataset.outEnabledTCSBoard3V3.value) << ", " << std::setw(4) << std::right << pdu1HkTableDataset.currentOutTCSBoard3V3.value << ", " << std::setw(4) @@ -475,3 +496,26 @@ void PDU1Handler::printHkTable() { << std::setw(4) << pdu1HkTableDataset.voltageOutChannel8.value << std::right << std::endl; } + +void PDU1Handler::printHkTableLatchups() { + sif::info << "PDU1 Latchup Information" << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "TCS Board" << std::dec << "| " + << std::setw(4) << std::right << pdu1HkTableDataset.latchupsTcsBoard3V3 << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "Syrlinks" << std::dec << "| " + << std::setw(4) << std::right << pdu1HkTableDataset.latchupsSyrlinks << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "Star Tracker" << std::dec << "| " + << std::setw(4) << std::right << pdu1HkTableDataset.latchupsStarTracker << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "MGT" << std::dec << "| " + << std::setw(4) << std::right << pdu1HkTableDataset.latchupsMgt << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "SuS Nominal" << std::dec << "| " + << std::setw(4) << std::right << pdu1HkTableDataset.latchupsSusNominal << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "Solar Cell Experiment" << std::dec + << "| " << std::setw(4) << std::right << pdu1HkTableDataset.latchupsSolarCellExp + << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "PLOC" << std::dec << "| " + << std::setw(4) << std::right << pdu1HkTableDataset.latchupsPloc << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "ACS A Side" << std::dec << "| " + << std::setw(4) << std::right << pdu1HkTableDataset.latchupsAcsBoardSideA << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "Channel 8" << std::dec << "| " + << std::setw(4) << std::right << pdu1HkTableDataset.latchupsChannel8 << std::endl; +} diff --git a/mission/devices/PDU1Handler.h b/mission/devices/PDU1Handler.h index c140648b..732c38d2 100644 --- a/mission/devices/PDU1Handler.h +++ b/mission/devices/PDU1Handler.h @@ -40,12 +40,15 @@ class PDU1Handler : public GomspaceDeviceHandler { ReturnValue_t setParamCallback(SetParamMessageUnpacker& unpacker, bool afterExectuion) override; private: + static constexpr uint8_t MAX_CHANNEL_STR_WIDTH = 24; + /** Dataset for the housekeeping table of the PDU1 */ PDU1::PDU1HkTableDataset pdu1HkTableDataset; GOMSPACE::ChannelSwitchHook channelSwitchHook = nullptr; void* hookArgs = nullptr; - void printHkTable(); + void printHkTableSwitchVI(); + void printHkTableLatchups(); void parseHkTableReply(const uint8_t* packet); }; diff --git a/mission/devices/PDU2Handler.cpp b/mission/devices/PDU2Handler.cpp index 776cae58..3d7e260d 100644 --- a/mission/devices/PDU2Handler.cpp +++ b/mission/devices/PDU2Handler.cpp @@ -364,30 +364,51 @@ ReturnValue_t PDU2Handler::initializeLocalDataPool(localpool::DataPool &localDat localDataPoolMap.emplace(P60System::PDU2_WDT_CAN_LEFT, new PoolEntry({0})); localDataPoolMap.emplace(P60System::PDU2_WDT_CSP_LEFT1, new PoolEntry({0})); localDataPoolMap.emplace(P60System::PDU2_WDT_CSP_LEFT2, new PoolEntry({0})); - +#if OBSW_ENABLE_PERIODIC_HK == 1 + poolManager.subscribeForPeriodicPacket(pdu2HkTableDataset.getSid(), false, 0.4, true); +#endif return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t PDU2Handler::printStatus(DeviceCommandId_t cmd) { + ReturnValue_t result = RETURN_OK; switch (cmd) { case (GOMSPACE::PRINT_SWITCH_V_I): { PoolReadGuard pg(&pdu2HkTableDataset); - ReturnValue_t readResult = pg.getReadResult(); - if (readResult != HasReturnvaluesIF::RETURN_OK) { - sif::warning << "Reading PDU1 HK table failed!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; + result = pg.getReadResult(); + if (result != HasReturnvaluesIF::RETURN_OK) { + break; } - printHkTable(); - return HasReturnvaluesIF::RETURN_OK; + printHkTableSwitchVI(); + break; + } + case (GOMSPACE::PRINT_LATCHUPS): { + PoolReadGuard pg(&pdu2HkTableDataset); + result = pg.getReadResult(); + if (result != HasReturnvaluesIF::RETURN_OK) { + break; + } + printHkTableLatchups(); + break; } default: { return HasReturnvaluesIF::RETURN_FAILED; } } + if (result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "Reading PDU1 HK table failed!" << std::endl; + } + return result; } -void PDU2Handler::printHkTable() { - sif::info << "PDU2 Info: SwitchState, Currents [mA], Voltages [mV]" << std::endl; +void PDU2Handler::printHkTableSwitchVI() { + sif::info << "PDU2 Info:" << std::endl; + sif::info << "Boot Cause: " << pdu2HkTableDataset.bootcause << " | Boot Count: " << std::setw(4) + << std::right << pdu2HkTableDataset.bootcount << std::endl; + sif::info << "Reset Cause: " << pdu2HkTableDataset.resetcause + << " | Battery Mode: " << static_cast(pdu2HkTableDataset.battMode.value) + << std::endl; + sif::info << "SwitchState, Currents [mA], Voltages [mV]: " << std::endl; sif::info << std::setw(30) << std::left << "Q7S" << std::dec << "| " << unsigned(pdu2HkTableDataset.outEnabledQ7S.value) << ", " << std::setw(4) << std::right << pdu2HkTableDataset.currentOutQ7S.value << ", " << std::setw(4) @@ -400,11 +421,11 @@ void PDU2Handler::printHkTable() { << unsigned(pdu2HkTableDataset.outEnabledReactionWheels.value) << ", " << std::setw(4) << std::right << pdu2HkTableDataset.currentOutReactionWheels.value << ", " << std::setw(4) << pdu2HkTableDataset.voltageOutReactionWheels.value << std::endl; - sif::info << std::setw(30) << std::left << "TCS Board 8V heater input" << std::dec << "| " + sif::info << std::setw(30) << std::left << "TCS Board Heater Input" << std::dec << "| " << unsigned(pdu2HkTableDataset.outEnabledTCSBoardHeaterIn.value) << ", " << std::setw(4) << std::right << pdu2HkTableDataset.currentOutTCSBoardHeaterIn.value << ", " << std::setw(4) << pdu2HkTableDataset.voltageOutTCSBoardHeaterIn.value << std::endl; - sif::info << std::setw(30) << std::left << "Redundant SUS group" << std::dec << "| " + sif::info << std::setw(30) << std::left << "SuS Redundant" << std::dec << "| " << unsigned(pdu2HkTableDataset.outEnabledSUSRedundant.value) << ", " << std::setw(4) << std::right << pdu2HkTableDataset.currentOutSUSRedundant.value << ", " << std::setw(4) << pdu2HkTableDataset.voltageOutSUSRedundant.value << std::endl; @@ -420,13 +441,40 @@ void PDU2Handler::printHkTable() { << unsigned(pdu2HkTableDataset.outEnabledAcsBoardSideB.value) << ", " << std::setw(4) << std::right << pdu2HkTableDataset.currentOutACSBoardSideB.value << ", " << std::setw(4) << pdu2HkTableDataset.voltageOutACSBoardSideB.value << std::endl; - sif::info << std::setw(30) << std::left << "Payload Camera enable state" << std::dec << "| " + sif::info << std::setw(30) << std::left << "Payload Camera" << std::dec << "| " << unsigned(pdu2HkTableDataset.outEnabledPayloadCamera.value) << ", " << std::setw(4) << std::right << pdu2HkTableDataset.currentOutPayloadCamera.value << ", " << std::setw(4) << pdu2HkTableDataset.voltageOutPayloadCamera.value << std::right << std::endl; } +void PDU2Handler::printHkTableLatchups() { + sif::info << "PDU2 Latchup Information" << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "Q7S" << std::dec << "| " + << std::setw(4) << std::right << pdu2HkTableDataset.latchupsQ7S << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "Payload PCDU Channel 1" << std::dec + << "| " << std::setw(4) << std::right << pdu2HkTableDataset.latchupsPayloadPcduCh1 + << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "Reaction Wheels" << std::dec + << "| " << std::setw(4) << std::right << pdu2HkTableDataset.latchupsRw << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "TCS Board Heater Input" << std::dec + << "| " << std::setw(4) << std::right << pdu2HkTableDataset.latchupsTcsBoardHeaterIn + << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "SuS Nominal" << std::dec << "| " + << std::setw(4) << std::right << pdu2HkTableDataset.latchupsSusRedundant << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "Deployment mechanism" << std::dec + << "| " << std::setw(4) << std::right << pdu2HkTableDataset.latchupsDeplMenchanism + << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "Payload PCDU Channel 6" << std::dec + << "| " << std::setw(4) << std::right << pdu2HkTableDataset.latchupsPayloadPcduCh6 + << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "ACS Board Side B" << std::dec + << "| " << std::setw(4) << std::right << pdu2HkTableDataset.latchupsAcsBoardSideB + << std::endl; + sif::info << std::setw(MAX_CHANNEL_STR_WIDTH) << std::left << "Payload Camera" << std::dec << "| " + << std::setw(4) << std::right << pdu2HkTableDataset.latchupsPayloadCamera << std::endl; +} + ReturnValue_t PDU2Handler::setParamCallback(SetParamMessageUnpacker &unpacker, bool afterExecution) { using namespace PDU2; @@ -460,7 +508,7 @@ ReturnValue_t PDU2Handler::setParamCallback(SetParamMessageUnpacker &unpacker, channelSwitchHook(pdu, 5, unpacker.getParameter()[0], hookArgs); break; } - case (CONFIG_ADDRESS_OUT_EN_PAYLOAD_PCDU_CH6PLOC): { + case (CONFIG_ADDRESS_OUT_EN_PAYLOAD_PCDU_CH6): { channelSwitchHook(pdu, 6, unpacker.getParameter()[0], hookArgs); break; } diff --git a/mission/devices/PDU2Handler.h b/mission/devices/PDU2Handler.h index f2323615..ca639568 100644 --- a/mission/devices/PDU2Handler.h +++ b/mission/devices/PDU2Handler.h @@ -38,12 +38,15 @@ class PDU2Handler : public GomspaceDeviceHandler { ReturnValue_t setParamCallback(SetParamMessageUnpacker& unpacker, bool afterExecution) override; private: + static constexpr uint8_t MAX_CHANNEL_STR_WIDTH = 24; + /** Dataset for the housekeeping table of the PDU2 */ PDU2::PDU2HkTableDataset pdu2HkTableDataset; GOMSPACE::ChannelSwitchHook channelSwitchHook = nullptr; void* hookArgs = nullptr; - void printHkTable(); + void printHkTableSwitchVI(); + void printHkTableLatchups(); void parseHkTableReply(const uint8_t* packet); }; diff --git a/mission/devices/RadiationSensorHandler.cpp b/mission/devices/RadiationSensorHandler.cpp index 57714d03..52d58fd8 100644 --- a/mission/devices/RadiationSensorHandler.cpp +++ b/mission/devices/RadiationSensorHandler.cpp @@ -156,6 +156,7 @@ ReturnValue_t RadiationSensorHandler::interpretDeviceReply(DeviceCommandId_t id, #if OBSW_VERBOSE_LEVEL >= 1 && OBSW_DEBUG_RAD_SENSOR == 1 sif::info << "Radiation sensor temperature: " << dataset.temperatureCelcius << " °C" << std::endl; + sif::info << std::dec; sif::info << "Radiation sensor ADC value channel 0: " << dataset.ain0 << std::endl; sif::info << "Radiation sensor ADC value channel 1: " << dataset.ain1 << std::endl; sif::info << "Radiation sensor ADC value channel 4: " << dataset.ain4 << std::endl; diff --git a/mission/devices/SolarArrayDeploymentHandler.cpp b/mission/devices/SolarArrayDeploymentHandler.cpp index 13b46171..9bb016b7 100644 --- a/mission/devices/SolarArrayDeploymentHandler.cpp +++ b/mission/devices/SolarArrayDeploymentHandler.cpp @@ -1,17 +1,14 @@ #include "SolarArrayDeploymentHandler.h" #include -#include #include #include #include -SolarArrayDeploymentHandler::SolarArrayDeploymentHandler(object_id_t setObjectId_, - object_id_t gpioDriverId_, - CookieIF* gpioCookie_, - object_id_t mainLineSwitcherObjectId_, - uint8_t mainLineSwitch_, gpioId_t deplSA1, - gpioId_t deplSA2, uint32_t burnTimeMs) +SolarArrayDeploymentHandler::SolarArrayDeploymentHandler( + object_id_t setObjectId_, object_id_t gpioDriverId_, CookieIF* gpioCookie_, + object_id_t mainLineSwitcherObjectId_, pcduSwitches::Switches mainLineSwitch_, gpioId_t deplSA1, + gpioId_t deplSA2, uint32_t burnTimeMs) : SystemObject(setObjectId_), gpioDriverId(gpioDriverId_), gpioCookie(gpioCookie_), diff --git a/mission/devices/SolarArrayDeploymentHandler.h b/mission/devices/SolarArrayDeploymentHandler.h index 90380ae2..e5d91d3d 100644 --- a/mission/devices/SolarArrayDeploymentHandler.h +++ b/mission/devices/SolarArrayDeploymentHandler.h @@ -1,6 +1,7 @@ #ifndef MISSION_DEVICES_SOLARARRAYDEPLOYMENT_H_ #define MISSION_DEVICES_SOLARARRAYDEPLOYMENT_H_ +#include #include #include #include @@ -42,8 +43,8 @@ class SolarArrayDeploymentHandler : public ExecutableObjectIF, */ SolarArrayDeploymentHandler(object_id_t setObjectId, object_id_t gpioDriverId, CookieIF* gpioCookie, object_id_t mainLineSwitcherObjectId, - uint8_t mainLineSwitch, gpioId_t deplSA1, gpioId_t deplSA2, - uint32_t burnTimeMs); + pcduSwitches::Switches mainLineSwitch, gpioId_t deplSA1, + gpioId_t deplSA2, uint32_t burnTimeMs); virtual ~SolarArrayDeploymentHandler(); diff --git a/mission/devices/devicedefinitions/GomspaceDefinitions.h b/mission/devices/devicedefinitions/GomspaceDefinitions.h index 995d9a7a..d06c7eef 100644 --- a/mission/devices/devicedefinitions/GomspaceDefinitions.h +++ b/mission/devices/devicedefinitions/GomspaceDefinitions.h @@ -34,8 +34,10 @@ static const DeviceCommandId_t GNDWDT_RESET = 9; //!< [EXPORT] : [COMMAND] static const DeviceCommandId_t PARAM_GET = 0; //!< [EXPORT] : [COMMAND] static const DeviceCommandId_t PARAM_SET = 255; //!< [EXPORT] : [COMMAND] static const DeviceCommandId_t REQUEST_HK_TABLE = 16; //!< [EXPORT] : [COMMAND] + //!< [EXPORT] : [COMMAND] Print switch states, voltages and currents to the console static const DeviceCommandId_t PRINT_SWITCH_V_I = 32; +static const DeviceCommandId_t PRINT_LATCHUPS = 33; } // namespace GOMSPACE @@ -535,10 +537,11 @@ class HkTableDataset : public StaticLocalDataSet { lp_var_t latchupsGS5V = lp_var_t(sid.objectId, P60System::P60DOCK_LATCHUP_GS5V, this); - lp_var_t vbatVoltageValue = + lp_var_t dockVbatVoltageValue = lp_var_t(sid.objectId, P60System::P60DOCK_VBAT_VALUE, this); - lp_var_t vccCurrent = + lp_var_t dockVccCurrent = lp_var_t(sid.objectId, P60System::P60DOCK_VCC_CURRENT_VALUE, this); + // Difference between charge and discharge current lp_var_t batteryCurrent = lp_var_t(sid.objectId, P60System::P60DOCK_BATTERY_CURRENT, this); lp_var_t batteryVoltage = @@ -848,7 +851,7 @@ static const uint16_t CONFIG_ADDRESS_OUT_EN_RW = 0x4A; static const uint16_t CONFIG_ADDRESS_OUT_EN_TCS_BOARD_HEATER_IN = 0x4B; static const uint16_t CONFIG_ADDRESS_OUT_EN_SUS_REDUNDANT = 0x4C; static const uint16_t CONFIG_ADDRESS_OUT_EN_DEPLOYMENT_MECHANISM = 0x4D; -static const uint16_t CONFIG_ADDRESS_OUT_EN_PAYLOAD_PCDU_CH6PLOC = 0x4E; +static const uint16_t CONFIG_ADDRESS_OUT_EN_PAYLOAD_PCDU_CH6 = 0x4E; static const uint16_t CONFIG_ADDRESS_OUT_EN_ACS_BOARD_SIDE_B = 0x4F; static const uint16_t CONFIG_ADDRESS_OUT_EN_PAYLOAD_CAMERA = 0x50; diff --git a/mission/devices/devicedefinitions/powerDefinitions.h b/mission/devices/devicedefinitions/powerDefinitions.h new file mode 100644 index 00000000..746bda34 --- /dev/null +++ b/mission/devices/devicedefinitions/powerDefinitions.h @@ -0,0 +1,20 @@ +#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_POWERDEFINITIONS_H_ +#define MISSION_DEVICES_DEVICEDEFINITIONS_POWERDEFINITIONS_H_ + +#include +#include + +namespace power { + +static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_HANDLER; +//! [EXPORT] : [COMMENT] Indicates that a FSFW object requested setting a switch +//! P1: 1 if on was requested, 0 for off | P2: Switch Index +static constexpr Event SWITCH_CMD_SENT = event::makeEvent(SUBSYSTEM_ID, 0, severity::INFO); +//! [EXPORT] : [COMMENT] Indicated that a swithc state has changed +//! P1: New switch state, 1 for on, 0 for off | P2: Switch Index +static constexpr Event SWITCH_HAS_CHANGED = event::makeEvent(SUBSYSTEM_ID, 1, severity::INFO); +static constexpr Event SWITCHING_Q7S_DENIED = event::makeEvent(SUBSYSTEM_ID, 2, severity::MEDIUM); + +} // namespace power + +#endif /* MISSION_DEVICES_DEVICEDEFINITIONS_POWERDEFINITIONS_H_ */ diff --git a/mission/devices/max1227.h b/mission/devices/max1227.h index 1a6082fb..fc317b39 100644 --- a/mission/devices/max1227.h +++ b/mission/devices/max1227.h @@ -65,7 +65,7 @@ void prepareExternallyClockedSingleChannelRead(uint8_t* spiBuf, uint8_t channel, * the first byte (first conversion byte) the the rest of the SPI buffer. * @param spiBuf * @param n Channel number. Example: If the ADC has 6 channels, n will be 5 - * @param sz + * @param sz Will be incremented by amount which should be sent */ void prepareExternallyClockedRead0ToN(uint8_t* spiBuf, uint8_t n, size_t& sz); @@ -73,7 +73,7 @@ void prepareExternallyClockedRead0ToN(uint8_t* spiBuf, uint8_t n, size_t& sz); * Prepare an externally clocked temperature read. 25 bytes have to be sent * and the raw temperature value will appear on the last 2 bytes of the reply. * @param spiBuf - * @param sz + * @param sz Will be incremented by amount which should be sent */ void prepareExternallyClockedTemperatureRead(uint8_t* spiBuf, size_t& sz);