Merge branch 'development' into mueller/cmake-init
This commit is contained in:
commit
03cc343527
29
CHANGELOG
29
CHANGELOG
@ -15,6 +15,35 @@ a C file without issues
|
||||
- The same is possible for the event reporting service (PUS5)
|
||||
- PUS Health Service added, which allows to command and retrieve health via PUS packets
|
||||
|
||||
### Local Pool
|
||||
|
||||
- Interface of LocalPools has changed. LocalPool is not a template anymore. Instead the size and bucket number of the pools per page and the number of pages are passed to the ctor instead of two ctor arguments and a template parameter
|
||||
|
||||
### Parameter Service
|
||||
|
||||
- The API of the parameter service has been changed to prevent inconsistencies
|
||||
between documentation and actual code and to clarify usage.
|
||||
- The parameter ID now consists of:
|
||||
1. Domain ID (1 byte)
|
||||
2. Unique Identifier (1 byte)
|
||||
3. Linear Index (2 bytes)
|
||||
The linear index can be used for arrays as well as matrices.
|
||||
The parameter load command now explicitely expects the ECSS PTC and PFC
|
||||
information as well as the rows and column number. Rows and column will
|
||||
default to one, which is equivalent to one scalar parameter (the most
|
||||
important use-case)
|
||||
|
||||
### File System Interface
|
||||
|
||||
- A new interfaces specifies the functions for a software object which exposes the file system of a given hardware to use message based file handling (e.g. PUS commanding)
|
||||
|
||||
### Internal Error Reporter
|
||||
|
||||
- The new internal error reporter uses the local data pools. The pool IDs for
|
||||
the exisiting three error values and the new error set will be hardcoded for
|
||||
now, the the constructor for the internal error reporter just takes an object
|
||||
ID for now.
|
||||
|
||||
### Device Handler Base
|
||||
|
||||
- There is an additional `PERFORM_OPERATION` step for the device handler base. It is important
|
||||
|
@ -1,16 +1,16 @@
|
||||
#include "../subsystem/SubsystemBase.h"
|
||||
#include "ControllerBase.h"
|
||||
|
||||
#include "../subsystem/SubsystemBase.h"
|
||||
#include "../ipc/QueueFactory.h"
|
||||
#include "../action/HasActionsIF.h"
|
||||
|
||||
ControllerBase::ControllerBase(uint32_t setObjectId, uint32_t parentId,
|
||||
ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
|
||||
size_t commandQueueDepth) :
|
||||
SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF), submode(
|
||||
SUBMODE_NONE), commandQueue(NULL), modeHelper(
|
||||
this), healthHelper(this, setObjectId),hkSwitcher(this),executingTask(NULL) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth);
|
||||
|
||||
SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF),
|
||||
submode(SUBMODE_NONE), modeHelper(this),
|
||||
healthHelper(this, setObjectId) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
||||
commandQueueDepth);
|
||||
}
|
||||
|
||||
ControllerBase::~ControllerBase() {
|
||||
@ -24,9 +24,9 @@ ReturnValue_t ControllerBase::initialize() {
|
||||
}
|
||||
|
||||
MessageQueueId_t parentQueue = 0;
|
||||
if (parentId != 0) {
|
||||
if (parentId != objects::NO_OBJECT) {
|
||||
SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId);
|
||||
if (parent == NULL) {
|
||||
if (parent == nullptr) {
|
||||
return RETURN_FAILED;
|
||||
}
|
||||
parentQueue = parent->getCommandQueue();
|
||||
@ -44,10 +44,6 @@ ReturnValue_t ControllerBase::initialize() {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = hkSwitcher.initialize();
|
||||
if (result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
@ -56,26 +52,27 @@ MessageQueueId_t ControllerBase::getCommandQueue() const {
|
||||
}
|
||||
|
||||
void ControllerBase::handleQueue() {
|
||||
CommandMessage message;
|
||||
ReturnValue_t result;
|
||||
for (result = commandQueue->receiveMessage(&message); result == RETURN_OK;
|
||||
result = commandQueue->receiveMessage(&message)) {
|
||||
CommandMessage command;
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
for (result = commandQueue->receiveMessage(&command);
|
||||
result == RETURN_OK;
|
||||
result = commandQueue->receiveMessage(&command)) {
|
||||
|
||||
result = modeHelper.handleModeCommand(&message);
|
||||
result = modeHelper.handleModeCommand(&command);
|
||||
if (result == RETURN_OK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
result = healthHelper.handleHealthCommand(&message);
|
||||
result = healthHelper.handleHealthCommand(&command);
|
||||
if (result == RETURN_OK) {
|
||||
continue;
|
||||
}
|
||||
result = handleCommandMessage(&message);
|
||||
result = handleCommandMessage(&command);
|
||||
if (result == RETURN_OK) {
|
||||
continue;
|
||||
}
|
||||
message.setToUnknownCommand();
|
||||
commandQueue->reply(&message);
|
||||
command.setToUnknownCommand();
|
||||
commandQueue->reply(&command);
|
||||
}
|
||||
|
||||
}
|
||||
@ -106,7 +103,6 @@ void ControllerBase::announceMode(bool recursive) {
|
||||
|
||||
ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
|
||||
handleQueue();
|
||||
hkSwitcher.performOperation();
|
||||
performControlOperation();
|
||||
return RETURN_OK;
|
||||
}
|
||||
@ -135,3 +131,7 @@ void ControllerBase::setTaskIF(PeriodicTaskIF* task_){
|
||||
|
||||
void ControllerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {
|
||||
}
|
||||
|
||||
ReturnValue_t ControllerBase::initializeAfterTaskCreation() {
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
#ifndef CONTROLLERBASE_H_
|
||||
#define CONTROLLERBASE_H_
|
||||
#ifndef FSFW_CONTROLLER_CONTROLLERBASE_H_
|
||||
#define FSFW_CONTROLLER_CONTROLLERBASE_H_
|
||||
|
||||
#include "../health/HasHealthIF.h"
|
||||
#include "../health/HealthHelper.h"
|
||||
@ -7,73 +7,88 @@
|
||||
#include "../modes/ModeHelper.h"
|
||||
#include "../objectmanager/SystemObject.h"
|
||||
#include "../tasks/ExecutableObjectIF.h"
|
||||
#include "../tasks/PeriodicTaskIF.h"
|
||||
#include "../datapool/HkSwitchHelper.h"
|
||||
|
||||
|
||||
/**
|
||||
* @brief Generic base class for controller classes
|
||||
* @details
|
||||
* Implements common interfaces for controllers, which generally have
|
||||
* a mode and a health state. This avoids boilerplate code.
|
||||
*/
|
||||
class ControllerBase: public HasModesIF,
|
||||
public HasHealthIF,
|
||||
public ExecutableObjectIF,
|
||||
public SystemObject,
|
||||
public HasReturnvaluesIF {
|
||||
public:
|
||||
|
||||
static const Mode_t MODE_NORMAL = 2;
|
||||
|
||||
ControllerBase(uint32_t setObjectId, uint32_t parentId,
|
||||
ControllerBase(object_id_t setObjectId, object_id_t parentId,
|
||||
size_t commandQueueDepth = 3);
|
||||
virtual ~ControllerBase();
|
||||
|
||||
ReturnValue_t initialize();
|
||||
/** SystemObject override */
|
||||
virtual ReturnValue_t initialize() override;
|
||||
|
||||
virtual MessageQueueId_t getCommandQueue() const;
|
||||
virtual MessageQueueId_t getCommandQueue() const override;
|
||||
|
||||
virtual ReturnValue_t performOperation(uint8_t opCode);
|
||||
|
||||
virtual ReturnValue_t setHealth(HealthState health);
|
||||
|
||||
virtual HasHealthIF::HealthState getHealth();
|
||||
|
||||
/**
|
||||
* Implementation of ExecutableObjectIF function
|
||||
*
|
||||
* Used to setup the reference of the task, that executes this component
|
||||
* @param task_ Pointer to the taskIF of this task
|
||||
*/
|
||||
virtual void setTaskIF(PeriodicTaskIF* task_);
|
||||
/** HasHealthIF overrides */
|
||||
virtual ReturnValue_t setHealth(HealthState health) override;
|
||||
virtual HasHealthIF::HealthState getHealth() override;
|
||||
|
||||
/** ExecutableObjectIF overrides */
|
||||
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
virtual void setTaskIF(PeriodicTaskIF* task) override;
|
||||
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
||||
|
||||
protected:
|
||||
const uint32_t parentId;
|
||||
|
||||
/**
|
||||
* Implemented by child class. Handle command messages which are not
|
||||
* mode or health messages.
|
||||
* @param message
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0;
|
||||
|
||||
/**
|
||||
* Periodic helper, implemented by child class.
|
||||
*/
|
||||
virtual void performControlOperation() = 0;
|
||||
|
||||
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t *msToReachTheMode) = 0;
|
||||
|
||||
const object_id_t parentId;
|
||||
|
||||
Mode_t mode;
|
||||
|
||||
Submode_t submode;
|
||||
|
||||
MessageQueueIF* commandQueue;
|
||||
MessageQueueIF* commandQueue = nullptr;
|
||||
|
||||
ModeHelper modeHelper;
|
||||
|
||||
HealthHelper healthHelper;
|
||||
|
||||
HkSwitchHelper hkSwitcher;
|
||||
|
||||
/**
|
||||
* Pointer to the task which executes this component, is invalid before setTaskIF was called.
|
||||
* Pointer to the task which executes this component,
|
||||
* is invalid before setTaskIF was called.
|
||||
*/
|
||||
PeriodicTaskIF* executingTask;
|
||||
PeriodicTaskIF* executingTask = nullptr;
|
||||
|
||||
void handleQueue();
|
||||
/** Handle mode and health messages */
|
||||
virtual void handleQueue();
|
||||
|
||||
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0;
|
||||
virtual void performControlOperation() = 0;
|
||||
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||
uint32_t *msToReachTheMode) = 0;
|
||||
/** Mode helpers */
|
||||
virtual void modeChanged(Mode_t mode, Submode_t submode);
|
||||
virtual void startTransition(Mode_t mode, Submode_t submode);
|
||||
virtual void getMode(Mode_t *mode, Submode_t *submode);
|
||||
virtual void setToExternalControl();
|
||||
virtual void announceMode(bool recursive);
|
||||
/** HK helpers */
|
||||
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
|
||||
};
|
||||
|
||||
#endif /* CONTROLLERBASE_H_ */
|
||||
#endif /* FSFW_CONTROLLER_CONTROLLERBASE_H_ */
|
||||
|
@ -1,10 +1,3 @@
|
||||
/**
|
||||
* @file MapPacketExtraction.cpp
|
||||
* @brief This file defines the MapPacketExtraction class.
|
||||
* @date 26.03.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#include "MapPacketExtraction.h"
|
||||
#include "../ipc/QueueFactory.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
@ -12,14 +5,14 @@
|
||||
#include "../tmtcpacket/SpacePacketBase.h"
|
||||
#include "../tmtcservices/AcceptsTelecommandsIF.h"
|
||||
#include "../tmtcservices/TmTcMessage.h"
|
||||
#include <string.h>
|
||||
#include <cstring>
|
||||
|
||||
MapPacketExtraction::MapPacketExtraction(uint8_t setMapId,
|
||||
object_id_t setPacketDestination) :
|
||||
lastSegmentationFlag(NO_SEGMENTATION), mapId(setMapId), packetLength(0), bufferPosition(
|
||||
packetBuffer), packetDestination(setPacketDestination), packetStore(
|
||||
NULL), tcQueueId(MessageQueueIF::NO_QUEUE) {
|
||||
memset(packetBuffer, 0, sizeof(packetBuffer));
|
||||
lastSegmentationFlag(NO_SEGMENTATION), mapId(setMapId),
|
||||
bufferPosition(packetBuffer), packetDestination(setPacketDestination),
|
||||
tcQueueId(MessageQueueIF::NO_QUEUE) {
|
||||
std::memset(packetBuffer, 0, sizeof(packetBuffer));
|
||||
}
|
||||
|
||||
ReturnValue_t MapPacketExtraction::extractPackets(TcTransferFrame* frame) {
|
||||
|
@ -1,12 +1,5 @@
|
||||
/**
|
||||
* @file MapPacketExtraction.h
|
||||
* @brief This file defines the MapPacketExtraction class.
|
||||
* @date 26.03.2013
|
||||
* @author baetz
|
||||
*/
|
||||
|
||||
#ifndef MAPPACKETEXTRACTION_H_
|
||||
#define MAPPACKETEXTRACTION_H_
|
||||
#ifndef FSFW_DATALINKLAYER_MAPPACKETEXTRACTION_H_
|
||||
#define FSFW_DATALINKLAYER_MAPPACKETEXTRACTION_H_
|
||||
|
||||
#include "MapPacketExtractionIF.h"
|
||||
#include "../objectmanager/ObjectManagerIF.h"
|
||||
@ -20,17 +13,19 @@ class StorageManagerIF;
|
||||
* The class implements the full MAP Packet Extraction functionality as described in the CCSDS
|
||||
* TC Space Data Link Protocol. It internally stores incomplete segmented packets until they are
|
||||
* fully received. All found packets are forwarded to a single distribution entity.
|
||||
* @author B. Baetz
|
||||
*/
|
||||
class MapPacketExtraction: public MapPacketExtractionIF {
|
||||
private:
|
||||
static const uint32_t MAX_PACKET_SIZE = 4096;
|
||||
uint8_t lastSegmentationFlag; //!< The segmentation flag of the last received frame.
|
||||
uint8_t mapId; //!< MAP ID of this MAP Channel.
|
||||
uint32_t packetLength; //!< Complete length of the current Space Packet.
|
||||
uint32_t packetLength = 0; //!< Complete length of the current Space Packet.
|
||||
uint8_t* bufferPosition; //!< Position to write to in the internal Packet buffer.
|
||||
uint8_t packetBuffer[MAX_PACKET_SIZE]; //!< The internal Space Packet Buffer.
|
||||
object_id_t packetDestination;
|
||||
StorageManagerIF* packetStore; //!< Pointer to the store where full TC packets are stored.
|
||||
//!< Pointer to the store where full TC packets are stored.
|
||||
StorageManagerIF* packetStore = nullptr;
|
||||
MessageQueueId_t tcQueueId; //!< QueueId to send found packets to the distributor.
|
||||
/**
|
||||
* Debug method to print the packet Buffer's content.
|
||||
@ -75,4 +70,4 @@ public:
|
||||
uint8_t getMapId() const;
|
||||
};
|
||||
|
||||
#endif /* MAPPACKETEXTRACTION_H_ */
|
||||
#endif /* FSFW_DATALINKLAYER_MAPPACKETEXTRACTION_H_ */
|
||||
|
@ -3,8 +3,6 @@
|
||||
#include "DeviceTmReportingWrapper.h"
|
||||
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "../datapoolglob/GlobalDataSet.h"
|
||||
#include "../datapoolglob/GlobalPoolVariable.h"
|
||||
#include "../objectmanager/ObjectManager.h"
|
||||
#include "../storagemanager/StorageManagerIF.h"
|
||||
#include "../thermal/ThermalComponentIF.h"
|
||||
@ -13,9 +11,11 @@
|
||||
#include "../ipc/MessageQueueMessage.h"
|
||||
#include "../ipc/QueueFactory.h"
|
||||
#include "../subsystem/SubsystemBase.h"
|
||||
#include "../datapoollocal/LocalPoolVariable.h"
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
|
||||
object_id_t DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT;
|
||||
object_id_t DeviceHandlerBase::rawDataReceiverId = objects::NO_OBJECT;
|
||||
object_id_t DeviceHandlerBase::defaultFdirParentId = objects::NO_OBJECT;
|
||||
@ -56,9 +56,10 @@ void DeviceHandlerBase::setHkDestination(object_id_t hkDestination) {
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::setThermalStateRequestPoolIds(
|
||||
uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId) {
|
||||
this->deviceThermalRequestPoolId = thermalStatePoolId;
|
||||
this->deviceThermalRequestPoolId = thermalRequestPoolId;
|
||||
lp_id_t thermalStatePoolId, lp_id_t heaterRequestPoolId,
|
||||
uint32_t thermalSetId) {
|
||||
thermalSet = new DeviceHandlerThermalSet(this, thermalSetId,
|
||||
thermalStatePoolId, heaterRequestPoolId);
|
||||
}
|
||||
|
||||
|
||||
@ -86,7 +87,6 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
|
||||
decrementDeviceReplyMap();
|
||||
fdirInstance->checkForFailures();
|
||||
hkSwitcher.performOperation();
|
||||
hkManager.performHkOperation();
|
||||
performOperationHook();
|
||||
return RETURN_OK;
|
||||
}
|
||||
@ -111,6 +111,9 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
|
||||
break;
|
||||
case CommunicationAction::GET_READ:
|
||||
doGetRead();
|
||||
// This will be performed after datasets have been updated by the
|
||||
// custom device implementation.
|
||||
hkManager.performHkOperation();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -208,16 +211,18 @@ ReturnValue_t DeviceHandlerBase::initialize() {
|
||||
|
||||
fillCommandAndReplyMap();
|
||||
|
||||
//Set temperature target state to NON_OP.
|
||||
GlobDataSet mySet;
|
||||
gp_uint8_t thermalRequest(deviceThermalRequestPoolId, &mySet,
|
||||
PoolVariableIF::VAR_WRITE);
|
||||
mySet.read();
|
||||
thermalRequest = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
|
||||
mySet.commit(PoolVariableIF::VALID);
|
||||
if(thermalSet != nullptr) {
|
||||
//Set temperature target state to NON_OP.
|
||||
result = thermalSet->read();
|
||||
if(result == HasReturnvaluesIF::RETURN_OK) {
|
||||
thermalSet->heaterRequest.value =
|
||||
ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
|
||||
thermalSet->commit(PoolVariableIF::VALID);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return RETURN_OK;
|
||||
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::decrementDeviceReplyMap() {
|
||||
@ -505,15 +510,17 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
|
||||
}
|
||||
Clock::getUptime(&timeoutStart);
|
||||
|
||||
if (mode == MODE_OFF) {
|
||||
GlobDataSet mySet;
|
||||
gp_uint8_t thermalRequest(deviceThermalRequestPoolId, &mySet,
|
||||
PoolVariableIF::VAR_READ_WRITE);
|
||||
mySet.read();
|
||||
if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) {
|
||||
thermalRequest = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
|
||||
if (mode == MODE_OFF and thermalSet != nullptr) {
|
||||
ReturnValue_t result = thermalSet->read();
|
||||
if(result == HasReturnvaluesIF::RETURN_OK) {
|
||||
if (thermalSet->heaterRequest.value !=
|
||||
ThermalComponentIF::STATE_REQUEST_IGNORE) {
|
||||
thermalSet->heaterRequest.value = ThermalComponentIF::
|
||||
STATE_REQUEST_NON_OPERATIONAL;
|
||||
}
|
||||
thermalSet->heaterRequest.commit(PoolVariableIF::VALID);
|
||||
}
|
||||
mySet.commit(PoolVariableIF::VALID);
|
||||
|
||||
}
|
||||
changeHK(mode, submode, true);
|
||||
}
|
||||
@ -976,17 +983,15 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode,
|
||||
}
|
||||
|
||||
if ((commandedMode == MODE_ON) && (mode == MODE_OFF)
|
||||
&& (deviceThermalStatePoolId != PoolVariableIF::NO_PARAMETER)) {
|
||||
GlobDataSet mySet;
|
||||
gp_uint8_t thermalState(deviceThermalStatePoolId, &mySet,
|
||||
PoolVariableIF::VAR_READ);
|
||||
gp_uint8_t thermalRequest(deviceThermalRequestPoolId, &mySet,
|
||||
PoolVariableIF::VAR_READ);
|
||||
mySet.read();
|
||||
if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) {
|
||||
if (!ThermalComponentIF::isOperational(thermalState)) {
|
||||
and (thermalSet != nullptr)) {
|
||||
ReturnValue_t result = thermalSet->read();
|
||||
if(result == HasReturnvaluesIF::RETURN_OK) {
|
||||
if((thermalSet->heaterRequest.value !=
|
||||
ThermalComponentIF::STATE_REQUEST_IGNORE) and (not
|
||||
ThermalComponentIF::isOperational(
|
||||
thermalSet->thermalState.value))) {
|
||||
triggerEvent(ThermalComponentIF::TEMP_NOT_IN_OP_RANGE,
|
||||
thermalState);
|
||||
thermalSet->thermalState.value);
|
||||
return NON_OP_TEMPERATURE;
|
||||
}
|
||||
}
|
||||
@ -999,32 +1004,15 @@ void DeviceHandlerBase::startTransition(Mode_t commandedMode,
|
||||
Submode_t commandedSubmode) {
|
||||
switch (commandedMode) {
|
||||
case MODE_ON:
|
||||
if (mode == MODE_OFF) {
|
||||
transitionSourceMode = _MODE_POWER_DOWN;
|
||||
transitionSourceSubMode = SUBMODE_NONE;
|
||||
setMode(_MODE_POWER_ON, commandedSubmode);
|
||||
//already set the delay for the child transition so we don't need to call it twice
|
||||
childTransitionDelay = getTransitionDelayMs(_MODE_START_UP,
|
||||
MODE_ON);
|
||||
triggerEvent(CHANGING_MODE, commandedMode, commandedSubmode);
|
||||
GlobDataSet mySet;
|
||||
gp_int8_t thermalRequest(deviceThermalRequestPoolId,
|
||||
&mySet, PoolVariableIF::VAR_READ_WRITE);
|
||||
mySet.read();
|
||||
if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) {
|
||||
thermalRequest = ThermalComponentIF::STATE_REQUEST_OPERATIONAL;
|
||||
mySet.commit(PoolVariableIF::VALID);
|
||||
}
|
||||
} else {
|
||||
setTransition(MODE_ON, commandedSubmode);
|
||||
}
|
||||
handleTransitionToOnMode(commandedMode, commandedSubmode);
|
||||
break;
|
||||
case MODE_OFF:
|
||||
if (mode == MODE_OFF) {
|
||||
triggerEvent(CHANGING_MODE, commandedMode, commandedSubmode);
|
||||
setMode(_MODE_POWER_DOWN, commandedSubmode);
|
||||
} else {
|
||||
//already set the delay for the child transition so we don't need to call it twice
|
||||
// already set the delay for the child transition
|
||||
// so we don't need to call it twice
|
||||
childTransitionDelay = getTransitionDelayMs(mode, _MODE_POWER_DOWN);
|
||||
transitionSourceMode = _MODE_POWER_DOWN;
|
||||
transitionSourceSubMode = commandedSubmode;
|
||||
@ -1050,6 +1038,33 @@ void DeviceHandlerBase::startTransition(Mode_t commandedMode,
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::handleTransitionToOnMode(Mode_t commandedMode,
|
||||
Submode_t commandedSubmode) {
|
||||
if (mode == MODE_OFF) {
|
||||
transitionSourceMode = _MODE_POWER_DOWN;
|
||||
transitionSourceSubMode = SUBMODE_NONE;
|
||||
setMode(_MODE_POWER_ON, commandedSubmode);
|
||||
// already set the delay for the child transition so we don't
|
||||
// need to call it twice
|
||||
childTransitionDelay = getTransitionDelayMs(_MODE_START_UP,
|
||||
MODE_ON);
|
||||
triggerEvent(CHANGING_MODE, commandedMode, commandedSubmode);
|
||||
if(thermalSet != nullptr) {
|
||||
ReturnValue_t result = thermalSet->read();
|
||||
if(result == HasReturnvaluesIF::RETURN_OK) {
|
||||
if(thermalSet->heaterRequest !=
|
||||
ThermalComponentIF::STATE_REQUEST_IGNORE) {
|
||||
thermalSet->heaterRequest =
|
||||
ThermalComponentIF::STATE_REQUEST_OPERATIONAL;
|
||||
thermalSet->commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setTransition(MODE_ON, commandedSubmode);
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::getMode(Mode_t* mode, Submode_t* submode) {
|
||||
*mode = this->mode;
|
||||
*submode = this->submode;
|
||||
@ -1222,10 +1237,12 @@ void DeviceHandlerBase::handleDeviceTM(SerializeIF* data,
|
||||
}
|
||||
}
|
||||
//Try to cast to GlobDataSet and commit data.
|
||||
if (!neverInDataPool) {
|
||||
GlobDataSet* dataSet = dynamic_cast<GlobDataSet*>(data);
|
||||
if (dataSet != NULL) {
|
||||
dataSet->commit(PoolVariableIF::VALID);
|
||||
if (not neverInDataPool) {
|
||||
LocalPoolDataSetBase* dataSet =
|
||||
dynamic_cast<LocalPoolDataSetBase*>(data);
|
||||
if (dataSet != nullptr) {
|
||||
dataSet->setValidity(true, true);
|
||||
dataSet->commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1262,7 +1279,8 @@ void DeviceHandlerBase::buildInternalCommand(void) {
|
||||
if (result == BUSY) {
|
||||
//so we can track misconfigurations
|
||||
sif::debug << std::hex << getObjectId()
|
||||
<< ": DHB::buildInternalCommand: Busy" << std::dec << std::endl;
|
||||
<< ": DHB::buildInternalCommand: Busy" << std::dec
|
||||
<< std::endl;
|
||||
result = NOTHING_TO_SEND; //no need to report this
|
||||
}
|
||||
}
|
||||
@ -1371,8 +1389,8 @@ bool DeviceHandlerBase::commandIsExecuting(DeviceCommandId_t commandId) {
|
||||
void DeviceHandlerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task_){
|
||||
executingTask = task_;
|
||||
void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task){
|
||||
executingTask = task;
|
||||
}
|
||||
|
||||
// Default implementations empty.
|
||||
@ -1385,6 +1403,12 @@ void DeviceHandlerBase::performOperationHook() {
|
||||
ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(
|
||||
LocalDataPool &localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) {
|
||||
if(thermalSet != nullptr) {
|
||||
localDataPoolMap.emplace(thermalSet->thermalStatePoolId,
|
||||
new PoolEntry<DeviceHandlerIF::dh_thermal_state_t>);
|
||||
localDataPoolMap.emplace(thermalSet->heaterRequestPoolId,
|
||||
new PoolEntry<DeviceHandlerIF::dh_heater_request_t>);
|
||||
}
|
||||
return RETURN_OK;
|
||||
}
|
||||
|
||||
@ -1429,3 +1453,9 @@ dur_millis_t DeviceHandlerBase::getPeriodicOperationFrequency() const {
|
||||
return pstIntervalMs;
|
||||
}
|
||||
|
||||
DeviceCommandId_t DeviceHandlerBase::getPendingCommand() const {
|
||||
if(cookieInfo.pendingCommand != deviceCommandMap.end()) {
|
||||
return cookieInfo.pendingCommand->first;
|
||||
}
|
||||
return DeviceHandlerIF::NO_COMMAND;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "DeviceHandlerIF.h"
|
||||
#include "DeviceCommunicationIF.h"
|
||||
#include "DeviceHandlerFailureIsolation.h"
|
||||
#include "DeviceHandlerThermalSet.h"
|
||||
|
||||
#include "../objectmanager/SystemObject.h"
|
||||
#include "../tasks/ExecutableObjectIF.h"
|
||||
@ -103,8 +104,21 @@ public:
|
||||
size_t cmdQueueSize = 20);
|
||||
|
||||
void setHkDestination(object_id_t hkDestination);
|
||||
void setThermalStateRequestPoolIds(uint32_t thermalStatePoolId,
|
||||
uint32_t thermalRequestPoolId);
|
||||
|
||||
/**
|
||||
* If the device handler is controlled by the FSFW thermal building blocks,
|
||||
* this function should be called to initialize all required components.
|
||||
* The device handler will then take care of creating local pool entries
|
||||
* for the device thermal state and device heating request.
|
||||
* Custom local pool IDs can be assigned as well.
|
||||
* @param thermalStatePoolId
|
||||
* @param thermalRequestPoolId
|
||||
*/
|
||||
void setThermalStateRequestPoolIds(lp_id_t thermalStatePoolId =
|
||||
DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID,
|
||||
lp_id_t thermalRequestPoolId =
|
||||
DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID,
|
||||
uint32_t thermalSetId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID);
|
||||
/**
|
||||
* @brief Helper function to ease device handler development.
|
||||
* This will instruct the transition to MODE_ON immediately
|
||||
@ -694,19 +708,7 @@ protected:
|
||||
//! and to send replies.
|
||||
MessageQueueIF* commandQueue = nullptr;
|
||||
|
||||
/**
|
||||
* this is the datapool variable with the thermal state of the device
|
||||
*
|
||||
* can be set to PoolVariableIF::NO_PARAMETER to deactivate thermal checking
|
||||
*/
|
||||
uint32_t deviceThermalStatePoolId = PoolVariableIF::NO_PARAMETER;
|
||||
|
||||
/**
|
||||
* this is the datapool variable with the thermal request of the device
|
||||
*
|
||||
* can be set to PoolVariableIF::NO_PARAMETER to deactivate thermal checking
|
||||
*/
|
||||
uint32_t deviceThermalRequestPoolId = PoolVariableIF::NO_PARAMETER;
|
||||
DeviceHandlerThermalSet* thermalSet = nullptr;
|
||||
|
||||
/**
|
||||
* Optional Error code. Can be set in doStartUp(), doShutDown() and
|
||||
@ -732,15 +734,28 @@ protected:
|
||||
//! before setTaskIF was called.
|
||||
PeriodicTaskIF* executingTask = nullptr;
|
||||
|
||||
static object_id_t powerSwitcherId; //!< Object which switches power on and off.
|
||||
//!< Object which switches power on and off.
|
||||
static object_id_t powerSwitcherId;
|
||||
|
||||
static object_id_t rawDataReceiverId; //!< Object which receives RAW data by default.
|
||||
//!< Object which receives RAW data by default.
|
||||
static object_id_t rawDataReceiverId;
|
||||
|
||||
//!< Object which may be the root cause of an identified fault.
|
||||
static object_id_t defaultFdirParentId;
|
||||
|
||||
/**
|
||||
* Helper function to get pending command. This is useful for devices
|
||||
* like SPI sensors to identify the last sent command.
|
||||
* This only returns the command sent in the last SEND_WRITE cycle.
|
||||
* @return
|
||||
*/
|
||||
DeviceCommandId_t getPendingCommand() const;
|
||||
|
||||
static object_id_t defaultFdirParentId; //!< Object which may be the root cause of an identified fault.
|
||||
/**
|
||||
* Helper function to report a missed reply
|
||||
*
|
||||
* Can be overwritten by children to act on missed replies or to fake reporting Id.
|
||||
* Can be overwritten by children to act on missed replies or to fake
|
||||
* reporting Id.
|
||||
*
|
||||
* @param id of the missed reply
|
||||
*/
|
||||
@ -847,15 +862,18 @@ protected:
|
||||
/**
|
||||
* Build the device command to send for raw mode.
|
||||
*
|
||||
* This is only called in @c MODE_RAW. It is for the rare case that in raw mode packets
|
||||
* are to be sent by the handler itself. It is NOT needed for the raw commanding service.
|
||||
* Its only current use is in the STR handler which gets its raw packets from a different
|
||||
* source.
|
||||
* Also it can be used for transitional commands, to get the device ready for @c MODE_RAW
|
||||
* This is only called in @c MODE_RAW. It is for the rare case that in
|
||||
* raw mode packets are to be sent by the handler itself. It is NOT needed
|
||||
* for the raw commanding service. Its only current use is in the STR
|
||||
* handler which gets its raw packets from a different source.
|
||||
* Also it can be used for transitional commands, to get the device ready
|
||||
* for @c MODE_RAW
|
||||
*
|
||||
* As it is almost never used, there is a default implementation returning @c NOTHING_TO_SEND.
|
||||
* As it is almost never used, there is a default implementation
|
||||
* returning @c NOTHING_TO_SEND.
|
||||
*
|
||||
* #rawPacket and #rawPacketLen must be set by this method to the packet to be sent.
|
||||
* #rawPacket and #rawPacketLen must be set by this method to the packet
|
||||
* to be sent.
|
||||
*
|
||||
* @param[out] id the device command id built
|
||||
* @return
|
||||
@ -868,7 +886,9 @@ protected:
|
||||
* Returns the delay cycle count of a reply.
|
||||
* A count != 0 indicates that the command is already executed.
|
||||
* @param deviceCommand The command to look for
|
||||
* @return The current delay count. If the command does not exist (should never happen) it returns 0.
|
||||
* @return
|
||||
* The current delay count. If the command does not exist (should never
|
||||
* happen) it returns 0.
|
||||
*/
|
||||
uint8_t getReplyDelayCycles(DeviceCommandId_t deviceCommand);
|
||||
|
||||
@ -878,20 +898,22 @@ protected:
|
||||
* It gets space in the #IPCStore, copies data there, then sends a raw reply
|
||||
* containing the store address.
|
||||
*
|
||||
* This method is virtual, as the STR has a different channel to send raw replies
|
||||
* and overwrites it accordingly.
|
||||
* This method is virtual, as the STR has a different channel to send
|
||||
* raw replies and overwrites it accordingly.
|
||||
*
|
||||
* @param data data to send
|
||||
* @param len length of @c data
|
||||
* @param sendTo the messageQueueId of the one to send to
|
||||
* @param isCommand marks the raw data as a command, the message then will be of type raw_command
|
||||
* @param isCommand marks the raw data as a command, the message then
|
||||
* will be of type raw_command
|
||||
*/
|
||||
virtual void replyRawData(const uint8_t *data, size_t len,
|
||||
MessageQueueId_t sendTo, bool isCommand = false);
|
||||
|
||||
/**
|
||||
* Calls replyRawData() with #defaultRawReceiver, but checks if wiretapping is active and if so,
|
||||
* does not send the Data as the wiretapping will have sent it already
|
||||
* Calls replyRawData() with #defaultRawReceiver, but checks if wiretapping
|
||||
* is active and if so, does not send the data as the wiretapping will have
|
||||
* sent it already
|
||||
*/
|
||||
void replyRawReplyIfnotWiretapped(const uint8_t *data, size_t len);
|
||||
|
||||
@ -903,17 +925,19 @@ protected:
|
||||
/**
|
||||
* Enable the reply checking for a command
|
||||
*
|
||||
* Is only called, if the command was sent (ie the getWriteReply was successful).
|
||||
* Must ensure that all replies are activated and correctly linked to the command that initiated it.
|
||||
* The default implementation looks for a reply with the same id as the command id in the replyMap or
|
||||
* uses the alternativeReplyId if flagged so.
|
||||
* When found, copies maxDelayCycles to delayCycles in the reply information and sets the command to
|
||||
* expect one reply.
|
||||
* Is only called, if the command was sent (i.e. the getWriteReply was
|
||||
* successful). Must ensure that all replies are activated and correctly
|
||||
* linked to the command that initiated it.
|
||||
* The default implementation looks for a reply with the same id as the
|
||||
* command id in the replyMap or uses the alternativeReplyId if flagged so.
|
||||
* When found, copies maxDelayCycles to delayCycles in the reply information
|
||||
* and sets the command to expect one reply.
|
||||
*
|
||||
* Can be overwritten by the child, if a command activates multiple replies
|
||||
* or replyId differs from commandId.
|
||||
* Notes for child implementations:
|
||||
* - If the command was not found in the reply map, NO_REPLY_EXPECTED MUST be returned.
|
||||
* - If the command was not found in the reply map,
|
||||
* NO_REPLY_EXPECTED MUST be returned.
|
||||
* - A failure code may be returned if something went fundamentally wrong.
|
||||
*
|
||||
* @param deviceCommand
|
||||
@ -929,17 +953,20 @@ protected:
|
||||
* get the state of the PCDU switches in the datapool
|
||||
*
|
||||
* @return
|
||||
* - @c PowerSwitchIF::SWITCH_ON if all switches specified by #switches are on
|
||||
* - @c PowerSwitchIF::SWITCH_OFF one of the switches specified by #switches are off
|
||||
* - @c PowerSwitchIF::RETURN_FAILED if an error occured
|
||||
* - @c PowerSwitchIF::SWITCH_ON if all switches specified
|
||||
* by #switches are on
|
||||
* - @c PowerSwitchIF::SWITCH_OFF one of the switches specified by
|
||||
* #switches are off
|
||||
* - @c PowerSwitchIF::RETURN_FAILED if an error occured
|
||||
*/
|
||||
ReturnValue_t getStateOfSwitches(void);
|
||||
|
||||
/**
|
||||
* set all datapool variables that are update periodically in normal mode invalid
|
||||
*
|
||||
* Child classes should provide an implementation which sets all those variables invalid
|
||||
* which are set periodically during any normal mode.
|
||||
* @brief Set all datapool variables that are update periodically in
|
||||
* normal mode invalid
|
||||
* @details TODO: Use local pools
|
||||
* Child classes should provide an implementation which sets all those
|
||||
* variables invalid which are set periodically during any normal mode.
|
||||
*/
|
||||
virtual void setNormalDatapoolEntriesInvalid() = 0;
|
||||
|
||||
@ -949,11 +976,12 @@ protected:
|
||||
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
|
||||
|
||||
/**
|
||||
* Children can overwrite this function to suppress checking of the command Queue
|
||||
* Children can overwrite this function to suppress checking of the
|
||||
* command Queue
|
||||
*
|
||||
* This can be used when the child does not want to receive a command in a certain
|
||||
* situation. Care must be taken that checking is not permanentely disabled as this
|
||||
* would render the handler unusable.
|
||||
* This can be used when the child does not want to receive a command in
|
||||
* a certain situation. Care must be taken that checking is not
|
||||
* permanentely disabled as this would render the handler unusable.
|
||||
*
|
||||
* @return whether checking the queue should NOT be done
|
||||
*/
|
||||
@ -992,17 +1020,20 @@ protected:
|
||||
virtual void forwardEvent(Event event, uint32_t parameter1 = 0,
|
||||
uint32_t parameter2 = 0) const;
|
||||
/**
|
||||
* Checks state of switches in conjunction with mode and triggers an event if they don't fit.
|
||||
* Checks state of switches in conjunction with mode and triggers an event
|
||||
* if they don't fit.
|
||||
*/
|
||||
virtual void checkSwitchState();
|
||||
|
||||
/**
|
||||
* Reserved for the rare case where a device needs to perform additional operation cyclically in OFF mode.
|
||||
* Reserved for the rare case where a device needs to perform additional
|
||||
* operation cyclically in OFF mode.
|
||||
*/
|
||||
virtual void doOffActivity();
|
||||
|
||||
/**
|
||||
* Reserved for the rare case where a device needs to perform additional operation cyclically in ON mode.
|
||||
* Reserved for the rare case where a device needs to perform additional
|
||||
* operation cyclically in ON mode.
|
||||
*/
|
||||
virtual void doOnActivity();
|
||||
|
||||
@ -1043,9 +1074,10 @@ private:
|
||||
/**
|
||||
* Information about a cookie.
|
||||
*
|
||||
* This is stored in a map for each cookie, to not only track the state, but also information
|
||||
* about the sent command. Tracking this information is needed as
|
||||
* the state of a commandId (waiting for reply) is done when a RMAP write reply is received.
|
||||
* This is stored in a map for each cookie, to not only track the state,
|
||||
* but also information about the sent command. Tracking this information
|
||||
* is needed as the state of a commandId (waiting for reply) is done when a
|
||||
* write reply is received.
|
||||
*/
|
||||
struct CookieInfo {
|
||||
CookieState_t state;
|
||||
@ -1102,10 +1134,14 @@ private:
|
||||
/**
|
||||
* Handle the device handler mode.
|
||||
*
|
||||
* - checks whether commands are valid for the current mode, rejects them accordingly
|
||||
* - checks whether commanded mode transitions are required and calls handleCommandedModeTransition()
|
||||
* - does the necessary action for the current mode or calls doChildStateMachine in modes @c MODE_TO_ON and @c MODE_TO_OFF
|
||||
* - actions that happen in transitions (eg setting a timeout) are handled in setMode()
|
||||
* - checks whether commands are valid for the current mode, rejects
|
||||
* them accordingly
|
||||
* - checks whether commanded mode transitions are required and calls
|
||||
* handleCommandedModeTransition()
|
||||
* - does the necessary action for the current mode or calls
|
||||
* doChildStateMachine in modes @c MODE_TO_ON and @c MODE_TO_OFF
|
||||
* - actions that happen in transitions (e.g. setting a timeout) are
|
||||
* handled in setMode()
|
||||
*/
|
||||
void doStateMachine(void);
|
||||
|
||||
@ -1115,16 +1151,17 @@ private:
|
||||
/**
|
||||
* Decrement the counter for the timout of replies.
|
||||
*
|
||||
* This is called at the beginning of each cycle. It checks whether a reply has timed out (that means a reply was expected
|
||||
* but not received).
|
||||
* This is called at the beginning of each cycle. It checks whether a
|
||||
* reply has timed out (that means a reply was expected but not received).
|
||||
*/
|
||||
void decrementDeviceReplyMap(void);
|
||||
|
||||
/**
|
||||
* Convenience function to handle a reply.
|
||||
*
|
||||
* Called after scanForReply() has found a packet. Checks if the found id is in the #deviceCommandMap, if so,
|
||||
* calls interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) for further action.
|
||||
* Called after scanForReply() has found a packet. Checks if the found ID
|
||||
* is in the #deviceCommandMap, if so, calls
|
||||
* #interpretDeviceReply for further action.
|
||||
*
|
||||
* It also resets the timeout counter for the command id.
|
||||
*
|
||||
@ -1184,7 +1221,7 @@ private:
|
||||
* @param[out] len
|
||||
* @return
|
||||
* - @c RETURN_OK @c data is valid
|
||||
* - @c RETURN_FAILED IPCStore is NULL
|
||||
* - @c RETURN_FAILED IPCStore is nullptr
|
||||
* - the return value from the IPCStore if it was not @c RETURN_OK
|
||||
*/
|
||||
ReturnValue_t getStorageData(store_address_t storageAddress, uint8_t **data,
|
||||
@ -1208,6 +1245,9 @@ private:
|
||||
|
||||
void parseReply(const uint8_t* receivedData,
|
||||
size_t receivedDataLen);
|
||||
|
||||
void handleTransitionToOnMode(Mode_t commandedMode,
|
||||
Submode_t commandedSubmode);
|
||||
};
|
||||
|
||||
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ */
|
||||
|
@ -7,21 +7,22 @@
|
||||
#include "../ipc/MutexFactory.h"
|
||||
|
||||
|
||||
const uint16_t EventManager::POOL_SIZES[N_POOLS] = {
|
||||
sizeof(EventMatchTree::Node), sizeof(EventIdRangeMatcher),
|
||||
sizeof(ReporterRangeMatcher) };
|
||||
// If one checks registerListener calls, there are around 40 (to max 50)
|
||||
// objects registering for certain events.
|
||||
// Each listener requires 1 or 2 EventIdMatcher and 1 or 2 ReportRangeMatcher.
|
||||
// So a good guess is 75 to a max of 100 pools required for each, which fits well.
|
||||
const uint16_t EventManager::N_ELEMENTS[N_POOLS] = {
|
||||
fsfwconfig::FSFW_EVENTMGMR_MATCHTREE_NODES ,
|
||||
fsfwconfig::FSFW_EVENTMGMT_EVENTIDMATCHERS,
|
||||
fsfwconfig::FSFW_EVENTMGMR_RANGEMATCHERS };
|
||||
const LocalPool::LocalPoolConfig EventManager::poolConfig = {
|
||||
{fsfwconfig::FSFW_EVENTMGMR_MATCHTREE_NODES,
|
||||
sizeof(EventMatchTree::Node)},
|
||||
{fsfwconfig::FSFW_EVENTMGMT_EVENTIDMATCHERS,
|
||||
sizeof(EventIdRangeMatcher)},
|
||||
{fsfwconfig::FSFW_EVENTMGMR_RANGEMATCHERS,
|
||||
sizeof(ReporterRangeMatcher)}
|
||||
};
|
||||
|
||||
EventManager::EventManager(object_id_t setObjectId) :
|
||||
SystemObject(setObjectId),
|
||||
factoryBackend(0, POOL_SIZES, N_ELEMENTS, false, true) {
|
||||
factoryBackend(0, poolConfig, false, true) {
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
eventReportQueue = QueueFactory::instance()->createMessageQueue(
|
||||
MAX_EVENTS_PER_CYCLE, EventMessage::EVENT_MESSAGE_SIZE);
|
||||
@ -113,7 +114,7 @@ ReturnValue_t EventManager::unsubscribeFromEventRange(MessageQueueId_t listener,
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
#if FSFW_DEBUG_OUTPUT == 1
|
||||
|
||||
void EventManager::printEvent(EventMessage* message) {
|
||||
const char *string = 0;
|
||||
|
@ -8,9 +8,11 @@
|
||||
#include "../tasks/ExecutableObjectIF.h"
|
||||
#include "../ipc/MessageQueueIF.h"
|
||||
#include "../ipc/MutexIF.h"
|
||||
#include <FSFWConfig.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
#ifdef DEBUG
|
||||
#if FSFW_DEBUG_OUTPUT == 1
|
||||
// forward declaration, should be implemented by mission
|
||||
extern const char* translateObject(object_id_t object);
|
||||
extern const char* translateEvents(Event event);
|
||||
@ -49,13 +51,15 @@ protected:
|
||||
MutexIF* mutex = nullptr;
|
||||
|
||||
static const uint8_t N_POOLS = 3;
|
||||
LocalPool<N_POOLS> factoryBackend;
|
||||
LocalPool factoryBackend;
|
||||
static const LocalPool::LocalPoolConfig poolConfig;
|
||||
|
||||
static const uint16_t POOL_SIZES[N_POOLS];
|
||||
static const uint16_t N_ELEMENTS[N_POOLS];
|
||||
|
||||
void notifyListeners(EventMessage *message);
|
||||
|
||||
#ifdef DEBUG
|
||||
#if FSFW_DEBUG_OUTPUT == 1
|
||||
void printEvent(EventMessage *message);
|
||||
#endif
|
||||
|
||||
|
34
internalError/InternalErrorDataset.h
Normal file
34
internalError/InternalErrorDataset.h
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef FSFW_INTERNALERROR_INTERNALERRORDATASET_H_
|
||||
#define FSFW_INTERNALERROR_INTERNALERRORDATASET_H_
|
||||
|
||||
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
|
||||
#include <fsfw/datapoollocal/LocalPoolVariable.h>
|
||||
|
||||
enum errorPoolIds {
|
||||
TM_HITS,
|
||||
QUEUE_HITS,
|
||||
STORE_HITS
|
||||
};
|
||||
|
||||
|
||||
class InternalErrorDataset: public StaticLocalDataSet<3 * sizeof(uint32_t)> {
|
||||
public:
|
||||
static constexpr uint8_t ERROR_SET_ID = 0;
|
||||
|
||||
InternalErrorDataset(HasLocalDataPoolIF* owner):
|
||||
StaticLocalDataSet(owner, ERROR_SET_ID) {}
|
||||
|
||||
InternalErrorDataset(object_id_t objectId):
|
||||
StaticLocalDataSet(sid_t(objectId , ERROR_SET_ID)) {}
|
||||
|
||||
lp_var_t<uint32_t> tmHits = lp_var_t<uint32_t>(hkManager->getOwner(),
|
||||
TM_HITS, this);
|
||||
lp_var_t<uint32_t> queueHits = lp_var_t<uint32_t>(hkManager->getOwner(),
|
||||
QUEUE_HITS, this);
|
||||
lp_var_t<uint32_t> storeHits = lp_var_t<uint32_t>(hkManager->getOwner(),
|
||||
STORE_HITS, this);
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /* FSFW_INTERNALERROR_INTERNALERRORDATASET_H_ */
|
@ -1,16 +1,16 @@
|
||||
#include "../datapoolglob/GlobalDataSet.h"
|
||||
#include "InternalErrorReporter.h"
|
||||
|
||||
#include "../datapoolglob/GlobalPoolVariable.h"
|
||||
#include "../ipc/QueueFactory.h"
|
||||
#include "../ipc/MutexFactory.h"
|
||||
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
|
||||
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId,
|
||||
uint32_t queuePoolId, uint32_t tmPoolId, uint32_t storePoolId) :
|
||||
SystemObject(setObjectId), mutex(NULL), queuePoolId(queuePoolId),
|
||||
tmPoolId(tmPoolId),storePoolId(storePoolId), queueHits(0), tmHits(0),
|
||||
storeHits(0) {
|
||||
uint32_t messageQueueDepth): SystemObject(setObjectId),
|
||||
commandQueue(QueueFactory::instance()->
|
||||
createMessageQueue(messageQueueDepth)),
|
||||
poolManager(this, commandQueue),
|
||||
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
|
||||
internalErrorDataset(this) {
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
|
||||
@ -18,28 +18,42 @@ InternalErrorReporter::~InternalErrorReporter() {
|
||||
MutexFactory::instance()->deleteMutex(mutex);
|
||||
}
|
||||
|
||||
void InternalErrorReporter::setDiagnosticPrintout(bool enable) {
|
||||
this->diagnosticPrintout = enable;
|
||||
}
|
||||
|
||||
ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
|
||||
|
||||
GlobDataSet mySet;
|
||||
gp_uint32_t queueHitsInPool(queuePoolId, &mySet,
|
||||
PoolVariableIF::VAR_READ_WRITE);
|
||||
gp_uint32_t tmHitsInPool(tmPoolId, &mySet,
|
||||
PoolVariableIF::VAR_READ_WRITE);
|
||||
|
||||
gp_uint32_t storeHitsInPool(storePoolId, &mySet,
|
||||
PoolVariableIF::VAR_READ_WRITE);
|
||||
mySet.read();
|
||||
internalErrorDataset.read(INTERNAL_ERROR_MUTEX_TIMEOUT);
|
||||
|
||||
uint32_t newQueueHits = getAndResetQueueHits();
|
||||
uint32_t newTmHits = getAndResetTmHits();
|
||||
uint32_t newStoreHits = getAndResetStoreHits();
|
||||
|
||||
queueHitsInPool.value += newQueueHits;
|
||||
tmHitsInPool.value += newTmHits;
|
||||
storeHitsInPool.value += newStoreHits;
|
||||
#ifdef DEBUG
|
||||
if(diagnosticPrintout) {
|
||||
if((newQueueHits > 0) or (newTmHits > 0) or (newStoreHits > 0)) {
|
||||
sif::debug << "InternalErrorReporter::performOperation: Errors "
|
||||
<< "occured!" << std::endl;
|
||||
sif::debug << "Queue errors: " << newQueueHits << std::endl;
|
||||
sif::debug << "TM errors: " << newTmHits << std::endl;
|
||||
sif::debug << "Store errors: " << newStoreHits << std::endl;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
mySet.commit(PoolVariableIF::VALID);
|
||||
internalErrorDataset.queueHits.value += newQueueHits;
|
||||
internalErrorDataset.storeHits.value += newStoreHits;
|
||||
internalErrorDataset.tmHits.value += newTmHits;
|
||||
|
||||
internalErrorDataset.commit(INTERNAL_ERROR_MUTEX_TIMEOUT);
|
||||
|
||||
poolManager.performHkOperation();
|
||||
|
||||
CommandMessage message;
|
||||
ReturnValue_t result = commandQueue->receiveMessage(&message);
|
||||
if(result != MessageQueueIF::EMPTY) {
|
||||
poolManager.handleHousekeepingMessage(&message);
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
@ -53,7 +67,7 @@ void InternalErrorReporter::lostTm() {
|
||||
|
||||
uint32_t InternalErrorReporter::getAndResetQueueHits() {
|
||||
uint32_t value;
|
||||
mutex->lockMutex(MutexIF::BLOCKING);
|
||||
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
|
||||
value = queueHits;
|
||||
queueHits = 0;
|
||||
mutex->unlockMutex();
|
||||
@ -62,21 +76,21 @@ uint32_t InternalErrorReporter::getAndResetQueueHits() {
|
||||
|
||||
uint32_t InternalErrorReporter::getQueueHits() {
|
||||
uint32_t value;
|
||||
mutex->lockMutex(MutexIF::BLOCKING);
|
||||
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
|
||||
value = queueHits;
|
||||
mutex->unlockMutex();
|
||||
return value;
|
||||
}
|
||||
|
||||
void InternalErrorReporter::incrementQueueHits() {
|
||||
mutex->lockMutex(MutexIF::BLOCKING);
|
||||
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
|
||||
queueHits++;
|
||||
mutex->unlockMutex();
|
||||
}
|
||||
|
||||
uint32_t InternalErrorReporter::getAndResetTmHits() {
|
||||
uint32_t value;
|
||||
mutex->lockMutex(MutexIF::BLOCKING);
|
||||
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
|
||||
value = tmHits;
|
||||
tmHits = 0;
|
||||
mutex->unlockMutex();
|
||||
@ -85,14 +99,14 @@ uint32_t InternalErrorReporter::getAndResetTmHits() {
|
||||
|
||||
uint32_t InternalErrorReporter::getTmHits() {
|
||||
uint32_t value;
|
||||
mutex->lockMutex(MutexIF::BLOCKING);
|
||||
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
|
||||
value = tmHits;
|
||||
mutex->unlockMutex();
|
||||
return value;
|
||||
}
|
||||
|
||||
void InternalErrorReporter::incrementTmHits() {
|
||||
mutex->lockMutex(MutexIF::BLOCKING);
|
||||
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
|
||||
tmHits++;
|
||||
mutex->unlockMutex();
|
||||
}
|
||||
@ -103,7 +117,7 @@ void InternalErrorReporter::storeFull() {
|
||||
|
||||
uint32_t InternalErrorReporter::getAndResetStoreHits() {
|
||||
uint32_t value;
|
||||
mutex->lockMutex(MutexIF::BLOCKING);
|
||||
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
|
||||
value = storeHits;
|
||||
storeHits = 0;
|
||||
mutex->unlockMutex();
|
||||
@ -112,14 +126,65 @@ uint32_t InternalErrorReporter::getAndResetStoreHits() {
|
||||
|
||||
uint32_t InternalErrorReporter::getStoreHits() {
|
||||
uint32_t value;
|
||||
mutex->lockMutex(MutexIF::BLOCKING);
|
||||
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
|
||||
value = storeHits;
|
||||
mutex->unlockMutex();
|
||||
return value;
|
||||
}
|
||||
|
||||
void InternalErrorReporter::incrementStoreHits() {
|
||||
mutex->lockMutex(MutexIF::BLOCKING);
|
||||
mutex->lockMutex(MutexIF::WAITING, INTERNAL_ERROR_MUTEX_TIMEOUT);
|
||||
storeHits++;
|
||||
mutex->unlockMutex();
|
||||
}
|
||||
|
||||
object_id_t InternalErrorReporter::getObjectId() const {
|
||||
return SystemObject::getObjectId();
|
||||
}
|
||||
|
||||
MessageQueueId_t InternalErrorReporter::getCommandQueue() const {
|
||||
return this->commandQueue->getId();
|
||||
}
|
||||
|
||||
ReturnValue_t InternalErrorReporter::initializeLocalDataPool(
|
||||
LocalDataPool &localDataPoolMap, LocalDataPoolManager &poolManager) {
|
||||
localDataPoolMap.emplace(errorPoolIds::TM_HITS,
|
||||
new PoolEntry<uint32_t>());
|
||||
localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS,
|
||||
new PoolEntry<uint32_t>());
|
||||
localDataPoolMap.emplace(errorPoolIds::STORE_HITS,
|
||||
new PoolEntry<uint32_t>());
|
||||
poolManager.subscribeForPeriodicPacket(internalErrorSid, false,
|
||||
getPeriodicOperationFrequency(), true);
|
||||
internalErrorDataset.setValidity(true, true);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
LocalDataPoolManager* InternalErrorReporter::getHkManagerHandle() {
|
||||
return &poolManager;
|
||||
}
|
||||
|
||||
dur_millis_t InternalErrorReporter::getPeriodicOperationFrequency() const {
|
||||
return this->executingTask->getPeriodMs();
|
||||
}
|
||||
|
||||
LocalPoolDataSetBase* InternalErrorReporter::getDataSetHandle(sid_t sid) {
|
||||
return &internalErrorDataset;
|
||||
}
|
||||
|
||||
void InternalErrorReporter::setTaskIF(PeriodicTaskIF *task) {
|
||||
this->executingTask = task;
|
||||
}
|
||||
|
||||
ReturnValue_t InternalErrorReporter::initialize() {
|
||||
ReturnValue_t result = poolManager.initialize(commandQueue);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return SystemObject::initialize();
|
||||
}
|
||||
|
||||
ReturnValue_t InternalErrorReporter::initializeAfterTaskCreation() {
|
||||
return poolManager.initializeAfterTaskCreation();
|
||||
}
|
||||
|
||||
|
@ -1,37 +1,75 @@
|
||||
#ifndef INTERNALERRORREPORTER_H_
|
||||
#define INTERNALERRORREPORTER_H_
|
||||
#ifndef FSFW_INTERNALERROR_INTERNALERRORREPORTER_H_
|
||||
#define FSFW_INTERNALERROR_INTERNALERRORREPORTER_H_
|
||||
|
||||
#include "InternalErrorReporterIF.h"
|
||||
|
||||
#include "../tasks/PeriodicTaskIF.h"
|
||||
#include "../internalError/InternalErrorDataset.h"
|
||||
#include "../datapoollocal/LocalDataPoolManager.h"
|
||||
#include "../tasks/ExecutableObjectIF.h"
|
||||
#include "../objectmanager/SystemObject.h"
|
||||
#include "../ipc/MutexIF.h"
|
||||
|
||||
/**
|
||||
* @brief This class is used to track internal errors like lost telemetry,
|
||||
* failed message sending or a full store.
|
||||
* @details
|
||||
* All functions were kept virtual so this class can be extended easily
|
||||
* to store custom internal errors (e.g. communication interface errors).
|
||||
*/
|
||||
class InternalErrorReporter: public SystemObject,
|
||||
public ExecutableObjectIF,
|
||||
public InternalErrorReporterIF {
|
||||
public InternalErrorReporterIF,
|
||||
public HasLocalDataPoolIF {
|
||||
public:
|
||||
InternalErrorReporter(object_id_t setObjectId, uint32_t queuePoolId,
|
||||
uint32_t tmPoolId, uint32_t storePoolId);
|
||||
static constexpr uint8_t INTERNAL_ERROR_MUTEX_TIMEOUT = 20;
|
||||
|
||||
InternalErrorReporter(object_id_t setObjectId,
|
||||
uint32_t messageQueueDepth = 5);
|
||||
|
||||
/**
|
||||
* Enable diagnostic printout. Please note that this feature will
|
||||
* only work if DEBUG has been supplied to the build defines.
|
||||
* @param enable
|
||||
*/
|
||||
void setDiagnosticPrintout(bool enable);
|
||||
|
||||
virtual ~InternalErrorReporter();
|
||||
|
||||
virtual ReturnValue_t performOperation(uint8_t opCode);
|
||||
virtual object_id_t getObjectId() const override;
|
||||
virtual MessageQueueId_t getCommandQueue() const override;
|
||||
virtual ReturnValue_t initializeLocalDataPool(
|
||||
LocalDataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) override;
|
||||
virtual LocalDataPoolManager* getHkManagerHandle() override;
|
||||
virtual dur_millis_t getPeriodicOperationFrequency() const override;
|
||||
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
|
||||
|
||||
virtual ReturnValue_t initialize() override;
|
||||
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
||||
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
|
||||
virtual void queueMessageNotSent();
|
||||
|
||||
virtual void lostTm();
|
||||