1
0
forked from fsfw/fsfw

improved DHB error handling

This commit is contained in:
2021-01-08 16:14:11 +01:00
parent 541478e4d5
commit c0fd981360
7 changed files with 152 additions and 87 deletions

View File

@ -39,13 +39,8 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId,
cookieInfo.state = COOKIE_UNUSED;
cookieInfo.pendingCommand = deviceCommandMap.end();
if (comCookie == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DeviceHandlerBase: ObjectID 0x" << std::hex
<< std::setw(8) << std::setfill('0') << this->getObjectId()
<< std::dec << ": Do not pass nullptr as a cookie, consider "
<< std::setfill(' ') << "passing a dummy cookie instead!"
<< std::endl;
#endif
printWarningOrError(fsfw::OutputTypes::OUT_ERROR, "DeviceHandlerBase",
HasReturnvaluesIF::RETURN_FAILED, "Invalid cookie");
}
if (this->fdirInstance == nullptr) {
this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId,
@ -132,30 +127,24 @@ ReturnValue_t DeviceHandlerBase::initialize() {
communicationInterface = objectManager->get<DeviceCommunicationIF>(
deviceCommunicationId);
if (communicationInterface == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DeviceHandlerBase::initialize: Communication interface "
"invalid." << std::endl;
sif::error << "Make sure it is set up properly and implements"
" DeviceCommunicationIF" << std::endl;
#endif
printWarningOrError(fsfw::OutputTypes::OUT_ERROR, "initialize",
ObjectManagerIF::CHILD_INIT_FAILED,
"Passed communication IF invalid");
return ObjectManagerIF::CHILD_INIT_FAILED;
}
result = communicationInterface->initializeInterface(comCookie);
if (result != RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DeviceHandlerBase::initialize: Initializing "
"communication interface failed!" << std::endl;
#endif
printWarningOrError(fsfw::OutputTypes::OUT_ERROR, "initialize",
ObjectManagerIF::CHILD_INIT_FAILED,
"ComIF initialization failed");
return result;
}
IPCStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
if (IPCStore == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DeviceHandlerBase::initialize: IPC store not set up in "
"factory." << std::endl;
#endif
printWarningOrError(fsfw::OutputTypes::OUT_ERROR, "initialize",
ObjectManagerIF::CHILD_INIT_FAILED, "IPC Store not set up");
return ObjectManagerIF::CHILD_INIT_FAILED;
}
@ -164,11 +153,15 @@ ReturnValue_t DeviceHandlerBase::initialize() {
AcceptsDeviceResponsesIF>(rawDataReceiverId);
if (rawReceiver == nullptr) {
printWarningOrError(fsfw::OutputTypes::OUT_ERROR,
"initialize", ObjectManagerIF::CHILD_INIT_FAILED,
"Raw receiver object ID set but no valid object found.");
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DeviceHandlerBase::initialize: Raw receiver object "
"ID set but no valid object found." << std::endl;
sif::error << "Make sure the raw receiver object is set up properly"
" and implements AcceptsDeviceResponsesIF" << std::endl;
#else
fsfw::printError("Make sure the raw receiver object is set up "
"properly and implements AcceptsDeviceResponsesIF\n");
#endif
return ObjectManagerIF::CHILD_INIT_FAILED;
}
@ -178,11 +171,15 @@ ReturnValue_t DeviceHandlerBase::initialize() {
if(powerSwitcherId != objects::NO_OBJECT) {
powerSwitcher = objectManager->get<PowerSwitchIF>(powerSwitcherId);
if (powerSwitcher == nullptr) {
printWarningOrError(fsfw::OutputTypes::OUT_ERROR,
"initialize", ObjectManagerIF::CHILD_INIT_FAILED,
"Power switcher set but no valid object found.");
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DeviceHandlerBase::initialize: Power switcher "
<< "object ID set but no valid object found." << std::endl;
sif::error << "Make sure the raw receiver object is set up properly"
<< " and implements PowerSwitchIF" << std::endl;
sif::error << "Make sure the power switcher object is set up "
<< "properly and implements PowerSwitchIF" << std::endl;
#else
fsfw::printError("Make sure the power switcher object is set up "
"properly and implements PowerSwitchIF\n");
#endif
return ObjectManagerIF::CHILD_INIT_FAILED;
}
@ -556,17 +553,17 @@ void DeviceHandlerBase::replyReturnvalueToCommand(ReturnValue_t status,
void DeviceHandlerBase::replyToCommand(ReturnValue_t status,
uint32_t parameter) {
//Check if we reply to a raw command.
// Check if we reply to a raw command.
if (cookieInfo.pendingCommand->first == RAW_COMMAND_ID) {
if (status == NO_REPLY_EXPECTED) {
status = RETURN_OK;
}
replyReturnvalueToCommand(status, parameter);
//Always delete data from a raw command.
// Always delete data from a raw command.
IPCStore->deleteData(storedRawData);
return;
}
//Check if we were externally commanded.
// Check if we were externally commanded.
if (cookieInfo.pendingCommand->second.sendReplyTo != NO_COMMANDER) {
MessageQueueId_t queueId = cookieInfo.pendingCommand->second.sendReplyTo;
if (status == NO_REPLY_EXPECTED) {
@ -581,15 +578,17 @@ void DeviceHandlerBase::replyToCommand(ReturnValue_t status,
void DeviceHandlerBase::replyToReply(DeviceReplyMap::iterator iter,
ReturnValue_t status) {
//No need to check if iter exists, as this is checked by callers. If someone else uses the method, add check.
// No need to check if iter exists, as this is checked by callers.
// If someone else uses the method, add check.
if (iter->second.command == deviceCommandMap.end()) {
//Is most likely periodic reply. Silent return.
return;
}
//Check if more replies are expected. If so, do nothing.
// Check if more replies are expected. If so, do nothing.
DeviceCommandInfo* info = &(iter->second.command->second);
if (--info->expectedReplies == 0) {
//Check if it was transition or internal command. Don't send any replies in that case.
// Check if it was transition or internal command.
// Don't send any replies in that case.
if (info->sendReplyTo != NO_COMMANDER) {
actionHelper.finish(info->sendReplyTo, iter->first, status);
}
@ -606,7 +605,7 @@ void DeviceHandlerBase::doSendWrite() {
if (result == RETURN_OK) {
cookieInfo.state = COOKIE_WRITE_SENT;
} else {
//always generate a failure event, so that FDIR knows what's up
// always generate a failure event, so that FDIR knows what's up
triggerEvent(DEVICE_SENDING_COMMAND_FAILED, result,
cookieInfo.pendingCommand->first);
replyToCommand(result);
@ -735,6 +734,9 @@ void DeviceHandlerBase::parseReply(const uint8_t* receivedData,
foundId);
}
if(foundLen == 0) {
printWarningOrError(fsfw::OutputTypes::OUT_ERROR,
"parseReply", ObjectManagerIF::CHILD_INIT_FAILED,
"Power switcher set but no valid object found.");
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "DeviceHandlerBase::parseReply: foundLen is 0!"
" Packet parsing will be stuck." << std::endl;
@ -968,7 +970,8 @@ ReturnValue_t DeviceHandlerBase::getStateOfSwitches(void) {
}
Mode_t DeviceHandlerBase::getBaseMode(Mode_t transitionMode) {
//only child action special modes are handled, as a child should never see any base action modes
// only child action special modes are handled, as a child should
// never see any base action modes
if (transitionMode == _MODE_START_UP) {
return _MODE_TO_ON;
}
@ -1291,12 +1294,11 @@ void DeviceHandlerBase::buildInternalCommand(void) {
if (mode == MODE_NORMAL) {
result = buildNormalDeviceCommand(&deviceCommandId);
if (result == BUSY) {
//so we can track misconfigurations
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << std::hex << getObjectId()
<< ": DHB::buildInternalCommand: Busy" << std::dec
<< std::endl;
#endif
// so we can track misconfigurations
printWarningOrError(fsfw::OutputTypes::OUT_WARNING,
"buildInternalCommand",
HasReturnvaluesIF::RETURN_FAILED,
"Busy.");
result = NOTHING_TO_SEND; //no need to report this
}
}
@ -1320,13 +1322,13 @@ void DeviceHandlerBase::buildInternalCommand(void) {
if (iter == deviceCommandMap.end()) {
result = COMMAND_NOT_SUPPORTED;
} else if (iter->second.isExecuting) {
//so we can track misconfigurations
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << std::hex << getObjectId()
<< ": DHB::buildInternalCommand: Command "
<< deviceCommandId << " isExecuting" << std::dec
<< std::endl;
#endif
char* output = nullptr;
sprintf(output, "Command %lu is executing", deviceCommandId);
// so we can track misconfigurations
printWarningOrError(fsfw::OutputTypes::OUT_WARNING,
"buildInternalCommand",
HasReturnvaluesIF::RETURN_FAILED,
output);
// this is an internal command, no need to report a failure here,
// missed reply will track if a reply is too late, otherwise, it's ok
return;
@ -1485,3 +1487,48 @@ void DeviceHandlerBase::setNormalDatapoolEntriesInvalid() {
}
}
}
void DeviceHandlerBase::printWarningOrError(fsfw::OutputTypes errorType,
const char *functionName, ReturnValue_t errorCode,
const char *errorPrint) {
if(errorPrint == nullptr) {
if(errorCode == ObjectManagerIF::CHILD_INIT_FAILED) {
errorPrint = "Initialization error";
}
if(errorCode == HasReturnvaluesIF::RETURN_FAILED) {
if(errorType == fsfw::OutputTypes::OUT_WARNING) {
errorPrint = "Generic Warning";
}
else {
errorPrint = "Generic Error";
}
}
else {
errorPrint = "Unknown error";
}
}
if(errorType == fsfw::OutputTypes::OUT_WARNING) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "DeviceHandlerBase::" << functionName << ": Object ID "
<< std::hex << std::setw(8) << std::setfill('0')
<< this->getObjectId() << " | " << errorPrint << std::dec
<< std::setfill(' ') << std::endl;
#else
fsfw::printWarning("DeviceHandlerBase::%s: Object ID 0x%08x | %s\n",
this->getObjectId(), errorPrint);
#endif
}
else if(errorType == fsfw::OutputTypes::OUT_ERROR) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DeviceHandlerBase::" << functionName << ": Object ID "
<< std::hex << std::setw(8) << std::setfill('0')
<< this->getObjectId() << " | " << errorPrint << std::dec
<< std::setfill(' ') << std::endl;
#else
fsfw::printError("DeviceHandlerBase::%s: Object ID 0x%08x | %s\n",
this->getObjectId(), errorPrint);
#endif
}
}

View File

@ -6,6 +6,8 @@
#include "DeviceHandlerFailureIsolation.h"
#include "DeviceHandlerThermalSet.h"
#include "../serviceinterface/ServiceInterface.h"
#include "../serviceinterface/serviceInterfaceDefintions.h"
#include "../objectmanager/SystemObject.h"
#include "../tasks/ExecutableObjectIF.h"
#include "../returnvalues/HasReturnvaluesIF.h"
@ -1111,7 +1113,7 @@ private:
/**
* @brief The mode the current transition originated from
*
* This is private so the child can not change it and fuck up the timeouts
* This is private so the child can not change it and mess up the timeouts
*
* IMPORTANT: This is not valid during _MODE_SHUT_DOWN and _MODE_START_UP!!
* (it is _MODE_POWER_DOWN during this modes)
@ -1190,7 +1192,8 @@ private:
* Check if the RMAP sendWrite action was successful.
*
* Depending on the result, the following is done
* - if the device command was external commanded, a reply is sent indicating the result
* - if the device command was external commanded, a reply is sent
* indicating the result
* - if the action was successful, the reply timout counter is initialized
*/
void doGetWrite(void);
@ -1206,9 +1209,9 @@ private:
/**
* Check the getRead reply and the contained data.
*
* If data was received scanForReply() and, if successful, handleReply() are called.
* If the current mode is @c MODE_RAW, the received packet is sent to the commanding object
* via commandQueue.
* If data was received scanForReply() and, if successful, handleReply()
* are called. If the current mode is @c MODE_RAW, the received packet
* is sent to the commanding object via commandQueue.
*/
void doGetRead(void);
@ -1227,7 +1230,7 @@ private:
uint32_t *len);
/**
* @param modeTo either @c MODE_ON, MODE_NORMAL or MODE_RAW NOTHING ELSE!!!
* @param modeTo either @c MODE_ON, MODE_NORMAL or MODE_RAW, nothing else!
*/
void setTransition(Mode_t modeTo, Submode_t submodeTo);
@ -1247,6 +1250,11 @@ private:
void handleTransitionToOnMode(Mode_t commandedMode,
Submode_t commandedSubmode);
void printWarningOrError(fsfw::OutputTypes errorType,
const char* functionName,
ReturnValue_t errorCode = HasReturnvaluesIF::RETURN_FAILED,
const char* errorPrint = nullptr);
};
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ */