2024-04-11 13:12:42 +02:00
|
|
|
#include "FreshMpsocHandler.h"
|
|
|
|
|
2024-04-11 13:44:35 +02:00
|
|
|
#include "fsfw/action/CommandActionHelper.h"
|
2024-04-11 13:12:42 +02:00
|
|
|
#include "fsfw/devicehandlers/FreshDeviceHandlerBase.h"
|
|
|
|
#include "fsfw/ipc/QueueFactory.h"
|
|
|
|
#include "fsfw/returnvalues/returnvalue.h"
|
|
|
|
#include "linux/payload/MpsocCommunication.h"
|
2024-04-11 13:44:35 +02:00
|
|
|
#include "linux/payload/plocSupvDefs.h"
|
2024-04-11 13:12:42 +02:00
|
|
|
|
|
|
|
FreshMpsocHandler::FreshMpsocHandler(DhbConfig cfg, MpsocCommunication& comInterface,
|
2024-04-11 16:23:09 +02:00
|
|
|
PlocMpsocSpecialComHelper* specialComHelper,
|
2024-04-11 13:12:42 +02:00
|
|
|
Gpio uartIsolatorSwitch, object_id_t supervisorHandler)
|
2024-04-11 13:44:35 +02:00
|
|
|
: FreshDeviceHandlerBase(cfg),
|
|
|
|
comInterface(comInterface),
|
2024-04-11 16:23:09 +02:00
|
|
|
specialComHelper(specialComHelper),
|
2024-04-11 13:44:35 +02:00
|
|
|
commandActionHelper(this),
|
|
|
|
uartIsolatorSwitch(uartIsolatorSwitch),
|
|
|
|
hkReport(this) {
|
|
|
|
commandActionHelperQueue = QueueFactory::instance()->createMessageQueue(10);
|
2024-04-11 13:12:42 +02:00
|
|
|
eventQueue = QueueFactory::instance()->createMessageQueue(10);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FreshMpsocHandler::performDeviceOperation(uint8_t opCode) {
|
|
|
|
if (not transitionActive and mode == MODE_OFF) {
|
|
|
|
// Nothing to do for now.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t FreshMpsocHandler::handleCommandMessage(CommandMessage* message) {
|
|
|
|
return FreshDeviceHandlerBase::handleCommandMessage(message);
|
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t FreshMpsocHandler::initialize() {
|
|
|
|
ReturnValue_t result = FreshDeviceHandlerBase::initialize();
|
|
|
|
if (result != returnvalue::OK) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
EventManagerIF* manager = ObjectManager::instance()->get<EventManagerIF>(objects::EVENT_MANAGER);
|
|
|
|
if (manager == nullptr) {
|
|
|
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
|
|
sif::error << "PlocMPSoCHandler::initialize: Invalid event manager" << std::endl;
|
|
|
|
#endif
|
|
|
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
|
|
|
;
|
|
|
|
}
|
|
|
|
result = manager->registerListener(eventQueue->getId());
|
|
|
|
if (result != returnvalue::OK) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
result = manager->subscribeToEvent(
|
|
|
|
eventQueue->getId(), event::getEventId(PlocMpsocSpecialComHelper::MPSOC_FLASH_WRITE_FAILED));
|
|
|
|
if (result != returnvalue::OK) {
|
|
|
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
|
|
|
}
|
|
|
|
result = manager->subscribeToEvent(
|
|
|
|
eventQueue->getId(),
|
|
|
|
event::getEventId(PlocMpsocSpecialComHelper::MPSOC_FLASH_WRITE_SUCCESSFUL));
|
|
|
|
if (result != returnvalue::OK) {
|
|
|
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
|
|
|
}
|
|
|
|
result = manager->subscribeToEvent(
|
|
|
|
eventQueue->getId(),
|
|
|
|
event::getEventId(PlocMpsocSpecialComHelper::MPSOC_FLASH_READ_SUCCESSFUL));
|
|
|
|
if (result != returnvalue::OK) {
|
|
|
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
|
|
|
}
|
|
|
|
result = manager->subscribeToEvent(
|
|
|
|
eventQueue->getId(), event::getEventId(PlocMpsocSpecialComHelper::MPSOC_FLASH_READ_FAILED));
|
|
|
|
if (result != returnvalue::OK) {
|
|
|
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
specialComHelper->setSequenceCount(&sequenceCount);
|
|
|
|
result = commandActionHelper.initialize();
|
|
|
|
if (result != returnvalue::OK) {
|
|
|
|
return ObjectManagerIF::CHILD_INIT_FAILED;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// HK manager abstract functions.
|
2024-04-11 13:44:35 +02:00
|
|
|
LocalPoolDataSetBase* FreshMpsocHandler::getDataSetHandle(sid_t sid) {
|
|
|
|
if (sid == hkReport.getSid()) {
|
|
|
|
return &hkReport;
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2024-04-11 13:12:42 +02:00
|
|
|
ReturnValue_t FreshMpsocHandler::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
|
|
|
LocalDataPoolManager& poolManager) {
|
2024-04-11 13:44:35 +02:00
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::STATUS, &peStatus);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::MODE, &peMode);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::DOWNLINK_PWR_ON, &peDownlinkPwrOn);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::DOWNLINK_REPLY_ACTIIVE, &peDownlinkReplyActive);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::DOWNLINK_JESD_SYNC_STATUS, &peDownlinkJesdSyncStatus);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::DOWNLINK_DAC_STATUS, &peDownlinkDacStatus);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::CAM_STATUS, &peCameraStatus);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::CAM_SDI_STATUS, &peCameraSdiStatus);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::CAM_FPGA_TEMP, &peCameraFpgaTemp);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::CAM_SOC_TEMP, &peCameraSocTemp);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::SYSMON_TEMP, &peSysmonTemp);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCCINT, &peSysmonVccInt);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCCAUX, &peSysmonVccAux);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCCBRAM, &peSysmonVccBram);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCCPAUX, &peSysmonVccPaux);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCCPINT, &peSysmonVccPint);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCCPDRO, &peSysmonVccPdro);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::SYSMON_MB12V, &peSysmonMb12V);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::SYSMON_MB3V3, &peSysmonMb3V3);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::SYSMON_MB1V8, &peSysmonMb1V8);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCC12V, &peSysmonVcc12V);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCC5V, &peSysmonVcc5V);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCC3V3, &peSysmonVcc3V3);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCC3V3VA, &peSysmonVcc3V3VA);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCC2V5DDR, &peSysmonVcc2V5DDR);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCC1V2DDR, &peSysmonVcc1V2DDR);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCC0V9, &peSysmonVcc0V9);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::SYSMON_VCC0V6VTT, &peSysmonVcc0V6VTT);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::SYSMON_SAFE_COTS_CUR, &peSysmonSafeCotsCur);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::SYSMON_NVM4_XO_CUR, &peSysmonNvm4XoCur);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::SEM_UNCORRECTABLE_ERRS, &peSemUncorrectableErrs);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::SEM_CORRECTABLE_ERRS, &peSemCorrectableErrs);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::SEM_STATUS, &peSemStatus);
|
|
|
|
localDataPoolMap.emplace(mpsoc::poolid::REBOOT_MPSOC_REQUIRED, &peRebootMpsocRequired);
|
|
|
|
poolManager.subscribeForRegularPeriodicPacket(
|
|
|
|
subdp::RegularHkPeriodicParams(hkReport.getSid(), false, 10.0));
|
2024-04-11 13:12:42 +02:00
|
|
|
return returnvalue::OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mode abstract functions
|
|
|
|
ReturnValue_t FreshMpsocHandler::checkModeCommand(Mode_t mode, Submode_t submode,
|
|
|
|
uint32_t* msToReachTheMode) {
|
|
|
|
return returnvalue::OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Action override. Forward to user.
|
|
|
|
ReturnValue_t FreshMpsocHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
|
|
|
const uint8_t* data, size_t size) {
|
2024-04-11 13:44:35 +02:00
|
|
|
ReturnValue_t result = returnvalue::OK;
|
|
|
|
switch (actionId) {
|
|
|
|
case mpsoc::SET_UART_TX_TRISTATE: {
|
|
|
|
uartIsolatorSwitch.pullLow();
|
|
|
|
return EXECUTION_FINISHED;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case mpsoc::RELEASE_UART_TX: {
|
|
|
|
uartIsolatorSwitch.pullHigh();
|
|
|
|
return EXECUTION_FINISHED;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (specialComHelperExecuting) {
|
|
|
|
return MPSoCReturnValuesIF::MPSOC_HELPER_EXECUTING;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (actionId) {
|
|
|
|
case mpsoc::TC_FLASH_WRITE_FULL_FILE: {
|
|
|
|
mpsoc::FlashBasePusCmd flashWritePusCmd;
|
|
|
|
result = flashWritePusCmd.extractFields(data, size);
|
|
|
|
if (result != returnvalue::OK) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
result = specialComHelper->startFlashWrite(flashWritePusCmd.getObcFile(),
|
|
|
|
flashWritePusCmd.getMPSoCFile());
|
|
|
|
if (result != returnvalue::OK) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
specialComHelperExecuting = true;
|
|
|
|
return EXECUTION_FINISHED;
|
|
|
|
}
|
|
|
|
case mpsoc::TC_FLASH_READ_FULL_FILE: {
|
|
|
|
mpsoc::FlashReadPusCmd flashReadPusCmd;
|
|
|
|
result = flashReadPusCmd.extractFields(data, size);
|
|
|
|
if (result != returnvalue::OK) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
result = specialComHelper->startFlashRead(flashReadPusCmd.getObcFile(),
|
|
|
|
flashReadPusCmd.getMPSoCFile(),
|
|
|
|
flashReadPusCmd.getReadSize());
|
|
|
|
if (result != returnvalue::OK) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
specialComHelperExecuting = true;
|
|
|
|
return EXECUTION_FINISHED;
|
|
|
|
}
|
|
|
|
case (mpsoc::OBSW_RESET_SEQ_COUNT): {
|
|
|
|
sequenceCount = 0;
|
|
|
|
return EXECUTION_FINISHED;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// For longer commands, do not set these.
|
|
|
|
commandIsPending = true;
|
|
|
|
cmdCountdown.resetTimer();
|
|
|
|
// TODO: Do all the stuff the form buildDeviceFromDevice blah did.
|
2024-04-11 13:12:42 +02:00
|
|
|
return returnvalue::OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @overload
|
|
|
|
* @param submode
|
|
|
|
*/
|
|
|
|
void FreshMpsocHandler::startTransition(Mode_t newMode, Submode_t submode) {}
|
|
|
|
|
|
|
|
ReturnValue_t FreshMpsocHandler::performDeviceOperationPreQueueHandling(uint8_t opCode) {
|
|
|
|
return returnvalue::OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FreshMpsocHandler::handleTransitionToOn() {}
|
|
|
|
|
|
|
|
void FreshMpsocHandler::handleTransitionToOff() {}
|
2024-04-11 13:44:35 +02:00
|
|
|
|
|
|
|
MessageQueueIF* FreshMpsocHandler::getCommandQueuePtr() { return commandActionHelperQueue; }
|
|
|
|
|
|
|
|
void FreshMpsocHandler::stepSuccessfulReceived(ActionId_t actionId, uint8_t step) { return; }
|
|
|
|
|
|
|
|
void FreshMpsocHandler::stepFailedReceived(ActionId_t actionId, uint8_t step,
|
|
|
|
ReturnValue_t returnCode) {
|
|
|
|
switch (actionId) {
|
|
|
|
case supv::START_MPSOC: {
|
|
|
|
sif::warning << "PlocMPSoCHandler::stepFailedReceived: Failed to start MPSoC" << std::endl;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case supv::SHUTDOWN_MPSOC: {
|
|
|
|
triggerEvent(MPSOC_SHUTDOWN_FAILED);
|
|
|
|
sif::warning << "PlocMPSoCHandler::stepFailedReceived: Failed to shutdown MPSoC" << std::endl;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
sif::debug << "PlocMPSoCHandler::stepFailedReceived: Received unexpected action reply"
|
|
|
|
<< std::endl;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
powerState = PowerState::SUPV_FAILED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FreshMpsocHandler::dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FreshMpsocHandler::completionSuccessfulReceived(ActionId_t actionId) {
|
|
|
|
if (actionId == supv::ACK_REPORT) {
|
|
|
|
// I seriously don't know why this happens..
|
|
|
|
// sif::warning
|
|
|
|
// << "PlocMpsocHandler::completionSuccessfulReceived: Only received ACK report. Consider
|
|
|
|
// "
|
|
|
|
// "increasing the MPSoC boot timer."
|
|
|
|
// << std::endl;
|
|
|
|
} else if (actionId != supv::EXE_REPORT) {
|
|
|
|
sif::warning << "PlocMpsocHandler::completionSuccessfulReceived: Did not expect the action "
|
|
|
|
<< "ID " << actionId << std::endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
switch (powerState) {
|
|
|
|
case PowerState::PENDING_STARTUP: {
|
|
|
|
mpsocBootTransitionCd.resetTimer();
|
|
|
|
powerState = PowerState::DONE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case PowerState::PENDING_SHUTDOWN: {
|
|
|
|
powerState = PowerState::DONE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void FreshMpsocHandler::completionFailedReceived(ActionId_t actionId, ReturnValue_t returnCode) {
|
|
|
|
handleActionCommandFailure(actionId);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FreshMpsocHandler::handleActionCommandFailure(ActionId_t actionId) {
|
|
|
|
switch (actionId) {
|
|
|
|
case supv::ACK_REPORT:
|
|
|
|
case supv::EXE_REPORT:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
sif::warning << "PlocMPSoCHandler::handleActionCommandFailure: Did not expect the action ID "
|
|
|
|
<< actionId << std::endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
switch (powerState) {
|
|
|
|
case PowerState::PENDING_STARTUP: {
|
|
|
|
sif::info << "PlocMPSoCHandler::handleActionCommandFailure: MPSoC boot command failed"
|
|
|
|
<< std::endl;
|
|
|
|
// This is commonly the case when the MPSoC is already operational. Thus the power state is
|
|
|
|
// set to on here
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case PowerState::PENDING_SHUTDOWN: {
|
|
|
|
// FDIR will intercept event and switch PLOC power off
|
|
|
|
triggerEvent(MPSOC_SHUTDOWN_FAILED);
|
|
|
|
sif::warning << "PlocMPSoCHandler::handleActionCommandFailure: Failed to shutdown MPSoC"
|
|
|
|
<< std::endl;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
powerState = PowerState::SUPV_FAILED;
|
|
|
|
return;
|
|
|
|
}
|