1
0
forked from fsfw/fsfw

updating code from Flying Laptop

This is the framework of Flying Laptop OBSW version A.13.0.
This commit is contained in:
2018-07-12 16:29:32 +02:00
parent 1d22a6c97e
commit 575f70ba03
395 changed files with 12807 additions and 8404 deletions

View File

@ -0,0 +1,23 @@
/**
* @file AcceptsDeviceResponsesIF.h
* @brief This file defines the AcceptsDeviceResponsesIF class.
* @date 15.05.2013
* @author baetz
*/
#ifndef ACCEPTSDEVICERESPONSESIF_H_
#define ACCEPTSDEVICERESPONSESIF_H_
#include <framework/ipc/MessageQueueSenderIF.h>
class AcceptsDeviceResponsesIF {
public:
/**
* Default empty virtual destructor.
*/
virtual ~AcceptsDeviceResponsesIF() {
}
virtual MessageQueueId_t getDeviceQueue() = 0;
};
#endif /* ACCEPTSDEVICERESPONSESIF_H_ */

View File

@ -40,11 +40,6 @@ void AssemblyBase::doStartTransition(Mode_t mode, Submode_t submode) {
ReturnValue_t result = commandChildren(mode, submode);
if (result == NEED_SECOND_STEP) {
internalState = STATE_NEED_SECOND_STEP;
} else if (result != RETURN_OK) {
//TODO: Debug
debug << std::hex << getObjectId()
<< ": AssemblyBase::commandChildren returned: " << result
<< std::dec << std::endl;
}
}
@ -140,7 +135,6 @@ void AssemblyBase::handleModeTransitionFailed(ReturnValue_t result) {
if (targetMode == MODE_OFF) {
triggerEvent(CHILD_PROBLEMS, result);
internalState = STATE_NONE;
//TODO: Maybe go to ERROR_ON here. Does this cause problems in subsystem?
setMode(targetMode, targetSubmode);
} else {
if (handleChildrenChangedHealth()) {
@ -157,7 +151,7 @@ void AssemblyBase::sendHealthCommand(MessageQueueId_t sendTo,
CommandMessage command;
HealthMessage::setHealthMessage(&command, HealthMessage::HEALTH_SET,
health);
if (commandQueue.sendMessage(sendTo, &command) == RETURN_OK) {
if (commandQueue->sendMessage(sendTo, &command) == RETURN_OK) {
commandsOutstanding++;
}
}

View File

@ -7,7 +7,7 @@
class AssemblyBase: public SubsystemBase {
public:
static const uint8_t INTERFACE_ID = ASSEMBLY_BASE;
static const uint8_t INTERFACE_ID = CLASS_ID::ASSEMBLY_BASE;
static const ReturnValue_t NEED_SECOND_STEP = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t NEED_TO_RECONFIGURE = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t MODE_FALLBACK = MAKE_RETURN_CODE(0x03);

View File

@ -6,7 +6,7 @@ ChildHandlerBase::ChildHandlerBase(uint32_t ioBoardAddress,
object_id_t setObjectId, object_id_t deviceCommunication,
uint32_t maxDeviceReplyLen, uint8_t setDeviceSwitch,
uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId,
uint32_t parent, FDIRBase* customFdir, uint32_t cmdQueueSize) :
uint32_t parent, FailureIsolationBase* customFdir, uint32_t cmdQueueSize) :
DeviceHandlerBase(ioBoardAddress, setObjectId, maxDeviceReplyLen,
setDeviceSwitch, deviceCommunication, thermalStatePoolId,
thermalRequestPoolId, (customFdir == NULL? &childHandlerFdir : customFdir), cmdQueueSize), parentId(

View File

@ -10,7 +10,7 @@ public:
object_id_t deviceCommunication, uint32_t maxDeviceReplyLen,
uint8_t setDeviceSwitch, uint32_t thermalStatePoolId,
uint32_t thermalRequestPoolId, uint32_t parent,
FDIRBase* customFdir = NULL,
FailureIsolationBase* customFdir = NULL,
uint32_t cmdQueueSize = 20);
virtual ~ChildHandlerBase();

View File

@ -1,14 +1,7 @@
/*
* ChildHandlerFDIR.cpp
*
* Created on: 08.02.2016
* Author: baetz
*/
#include <framework/devicehandlers/ChildHandlerFDIR.h>
ChildHandlerFDIR::ChildHandlerFDIR(object_id_t owner, object_id_t faultTreeParent, uint32_t recoveryCount) :
DeviceHandlerFDIR(owner, faultTreeParent) {
DeviceHandlerFailureIsolation(owner, faultTreeParent) {
recoveryCounter.setFailureThreshold(recoveryCount);
}

View File

@ -1,25 +1,18 @@
/*
* ChildHandlerFDIR.h
*
* Created on: 08.02.2016
* Author: baetz
*/
#ifndef FRAMEWORK_DEVICEHANDLERS_CHILDHANDLERFDIR_H_
#define FRAMEWORK_DEVICEHANDLERS_CHILDHANDLERFDIR_H_
#include <framework/devicehandlers/DeviceHandlerFDIR.h>
#include <framework/devicehandlers/DeviceHandlerFailureIsolation.h>
/**
* Very simple extension to normal FDIR.
* Does not have a default fault tree parent and
* allows to make the recovery count settable to 0.
*/
class ChildHandlerFDIR: public DeviceHandlerFDIR {
class ChildHandlerFDIR: public DeviceHandlerFailureIsolation {
public:
ChildHandlerFDIR(object_id_t owner, object_id_t faultTreeParent =
NO_FAULT_TREE_PARENT, uint32_t recoveryCount = 0);
~ChildHandlerFDIR();
virtual ~ChildHandlerFDIR();
protected:
static const object_id_t NO_FAULT_TREE_PARENT = 0;
};

View File

@ -6,7 +6,7 @@
class DeviceCommunicationIF: public HasReturnvaluesIF {
public:
static const uint8_t INTERFACE_ID = DEVICE_COMMUNICATION_IF;
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_COMMUNICATION_IF;
static const ReturnValue_t INVALID_COOKIE_TYPE = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t NOT_ACTIVE = MAKE_RETURN_CODE(0x02);
@ -39,7 +39,7 @@ public:
virtual void close(Cookie *cookie) = 0;
//TODO can data be const?
//SHOULDDO can data be const?
virtual ReturnValue_t sendMessage(Cookie *cookie, uint8_t *data,
uint32_t len) = 0;

View File

@ -1,52 +1,58 @@
/*
* DeviceHandlerBase.cpp
*
* Created on: 30.10.2012
* Author: mohr
*/
#include <config/datapool/dataPoolInit.h>
#include <mission/devices/PCDUHandler.h>
#include <config/hardware/IoBoardAddresses.h>
#include <framework/datapool/DataSet.h>
#include <framework/datapool/PoolVariable.h>
#include <framework/datapool/PoolVector.h>
#include <framework/devicehandlers/AcceptsDeviceResponsesIF.h>
#include <framework/devicehandlers/DeviceHandlerBase.h>
#include <framework/devicehandlers/DeviceTmReportingWrapper.h>
#include <framework/globalfunctions/crc_ccitt.h>
#include <framework/objectmanager/ObjectManager.h>
#include <framework/rmap/RMAP.h>
#include <framework/rmap/RMAPChannelIF.h>
#include <framework/storagemanager/StorageManagerIF.h>
#include <framework/subsystem/SubsystemBase.h>
#include <mission/tmtcservices/AcceptsDeviceResponsesIF.h>
#include <mission/controllers/tcs/ThermalComponentIF.h>
#include <framework/thermal/ThermalComponentIF.h>
#include <framework/ipc/QueueFactory.h>
object_id_t DeviceHandlerBase::powerSwitcherId = 0;
object_id_t DeviceHandlerBase::rawDataReceiverId = 0;
object_id_t DeviceHandlerBase::defaultFDIRParentId = 0;
DeviceHandlerBase::DeviceHandlerBase(uint32_t ioBoardAddress,
object_id_t setObjectId, uint32_t maxDeviceReplyLen,
uint8_t setDeviceSwitch, object_id_t deviceCommunication,
uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId,
FDIRBase* fdirInstance, uint32_t cmdQueueSize) :
FailureIsolationBase* fdirInstance, uint32_t cmdQueueSize) :
SystemObject(setObjectId), rawPacket(0), rawPacketLen(0), mode(
MODE_OFF), submode(SUBMODE_NONE), pstStep(0), maxDeviceReplyLen(
maxDeviceReplyLen), wiretappingMode(OFF), theOneWhoReceivesRawTraffic(
0), storedRawData(StorageManagerIF::INVALID_ADDRESS), theOneWhoWantsToReadRawTraffic(
0), powerSwitcher(NULL), IPCStore(NULL), deviceCommunicationId(
deviceCommunication), communicationInterface(NULL), cookie(
NULL), commandQueue(cmdQueueSize, CommandMessage::MAX_MESSAGE_SIZE), deviceThermalStatePoolId(
thermalStatePoolId), deviceThermalRequestPoolId(
maxDeviceReplyLen), wiretappingMode(OFF), defaultRawReceiver(0), storedRawData(
StorageManagerIF::INVALID_ADDRESS), requestedRawTraffic(0), powerSwitcher(
NULL), IPCStore(NULL), deviceCommunicationId(deviceCommunication), communicationInterface(
NULL), cookie(
NULL), commandQueue(NULL), deviceThermalStatePoolId(thermalStatePoolId), deviceThermalRequestPoolId(
thermalRequestPoolId), healthHelper(this, setObjectId), modeHelper(
this), parameterHelper(this), childTransitionFailure(RETURN_OK), ignoreMissedRepliesCount(
0), fdirInstance(fdirInstance), defaultFDIRUsed(
fdirInstance == NULL), switchOffWasReported(
false), cookieInfo(), ioBoardAddress(ioBoardAddress), timeoutStart(0), childTransitionDelay(
5000), transitionSourceMode(_MODE_POWER_DOWN), transitionSourceSubMode(
SUBMODE_NONE), deviceSwitch(setDeviceSwitch), actionHelper(
this, &commandQueue) {
0), fdirInstance(fdirInstance), hkSwitcher(this), defaultFDIRUsed(
fdirInstance == NULL), switchOffWasReported(false), executingTask(
NULL), actionHelper(this, commandQueue), cookieInfo(), ioBoardAddress(
//=======
// NULL), IPCStore(NULL), deviceCommunicationId(deviceCommunication), communicationInterface(
// NULL), cookie(
// NULL), commandQueue(cmdQueueSize, CommandMessage::MAX_MESSAGE_SIZE), deviceThermalStatePoolId(
// thermalStatePoolId), deviceThermalRequestPoolId(
// thermalRequestPoolId), healthHelper(this, setObjectId), modeHelper(
// this), parameterHelper(this), childTransitionFailure(RETURN_OK), ignoreMissedRepliesCount(
// 0), fdirInstance(fdirInstance), defaultFDIRUsed(
// fdirInstance == NULL), switchOffWasReported(false), actionHelper(
// this, &commandQueue), cookieInfo(), ioBoardAddress(
//>>>>>>> makefile
ioBoardAddress), timeoutStart(0), childTransitionDelay(5000), transitionSourceMode(
_MODE_POWER_DOWN), transitionSourceSubMode(SUBMODE_NONE), deviceSwitch(
setDeviceSwitch) {
commandQueue = QueueFactory::instance()->createMessageQueue(cmdQueueSize,
CommandMessage::MAX_MESSAGE_SIZE);
cookieInfo.state = COOKIE_UNUSED;
insertInCommandMap(RAW_COMMAND_ID);
if (this->fdirInstance == NULL) {
this->fdirInstance = new DeviceHandlerFDIR(setObjectId);
this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId,
defaultFDIRParentId);
}
}
@ -55,10 +61,10 @@ DeviceHandlerBase::~DeviceHandlerBase() {
if (defaultFDIRUsed) {
delete fdirInstance;
}
QueueFactory::instance()->deleteMessageQueue(commandQueue);
}
void DeviceHandlerBase::performInPST(uint8_t counter) {
ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
this->pstStep = counter;
if (counter == 0) {
@ -68,9 +74,10 @@ void DeviceHandlerBase::performInPST(uint8_t counter) {
checkSwitchState();
decrementDeviceReplyMap();
fdirInstance->checkForFailures();
hkSwitcher.performOperation();
}
if (mode == MODE_OFF) {
return;
return RETURN_OK;
}
switch (getRmapAction()) {
case SEND_WRITE:
@ -92,7 +99,7 @@ void DeviceHandlerBase::performInPST(uint8_t counter) {
default:
break;
}
return RETURN_OK;
}
void DeviceHandlerBase::decrementDeviceReplyMap() {
@ -118,7 +125,7 @@ void DeviceHandlerBase::readCommandQueue() {
}
CommandMessage message;
ReturnValue_t result = commandQueue.receiveMessage(&message);
ReturnValue_t result = commandQueue->receiveMessage(&message);
if (result != RETURN_OK) {
return;
}
@ -171,7 +178,7 @@ void DeviceHandlerBase::doStateMachine() {
break;
}
uint32_t currentUptime;
OSAL::getUptime(&currentUptime);
Clock::getUptime(&currentUptime);
if (currentUptime - timeoutStart >= childTransitionDelay) {
triggerEvent(MODE_TRANSITION_FAILED, childTransitionFailure, 0);
setMode(transitionSourceMode, transitionSourceSubMode);
@ -189,7 +196,7 @@ void DeviceHandlerBase::doStateMachine() {
break;
case _MODE_WAIT_ON: {
uint32_t currentUptime;
OSAL::getUptime(&currentUptime);
Clock::getUptime(&currentUptime);
if (currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) {
triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT,
0);
@ -209,7 +216,7 @@ void DeviceHandlerBase::doStateMachine() {
break;
case _MODE_WAIT_OFF: {
uint32_t currentUptime;
OSAL::getUptime(&currentUptime);
Clock::getUptime(&currentUptime);
if (currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) {
triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT,
0);
@ -347,6 +354,7 @@ void DeviceHandlerBase::setTransition(Mode_t modeTo, Submode_t submodeTo) {
}
void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
changeHK(mode, submode, false);
submode = newSubmode;
mode = newMode;
modeChanged();
@ -355,7 +363,7 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
modeHelper.modeChanged(newMode, newSubmode);
announceMode(false);
}
OSAL::getUptime(&timeoutStart);
Clock::getUptime(&timeoutStart);
if (mode == MODE_OFF) {
DataSet mySet;
@ -367,6 +375,7 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
}
mySet.commit(PoolVariableIF::VALID);
}
changeHK(mode, submode, true);
}
void DeviceHandlerBase::setMode(Mode_t newMode) {
@ -378,10 +387,10 @@ void DeviceHandlerBase::replyReturnvalueToCommand(ReturnValue_t status,
//This is actually the reply protocol for raw and misc dh commands.
if (status == RETURN_OK) {
CommandMessage reply(CommandMessage::REPLY_COMMAND_OK, 0, parameter);
commandQueue.reply(&reply);
commandQueue->reply(&reply);
} else {
CommandMessage reply(CommandMessage::REPLY_REJECTED, status, parameter);
commandQueue.reply(&reply);
commandQueue->reply(&reply);
}
}
@ -455,8 +464,7 @@ void DeviceHandlerBase::doGetWrite() {
ReturnValue_t result = communicationInterface->getSendSuccess(cookie);
if (result == RETURN_OK) {
if (wiretappingMode == RAW) {
replyRawData(rawPacket, rawPacketLen,
theOneWhoWantsToReadRawTraffic, true);
replyRawData(rawPacket, rawPacketLen, requestedRawTraffic, true);
}
//We need to distinguish here, because a raw command never expects a reply. (Could be done in eRIRM, but then child implementations need to be careful.
result = enableReplyInReplyMap(cookieInfo.pendingCommand);
@ -515,19 +523,11 @@ void DeviceHandlerBase::doGetRead() {
return;
if (wiretappingMode == RAW) {
replyRawData(receivedData, receivedDataLen,
theOneWhoWantsToReadRawTraffic);
replyRawData(receivedData, receivedDataLen, requestedRawTraffic);
}
if (mode == MODE_RAW) {
if ((wiretappingMode == RAW)
&& (theOneWhoReceivesRawTraffic
== theOneWhoWantsToReadRawTraffic)) {
//The raw packet was already sent by the wiretapping service
} else {
replyRawData(receivedData, receivedDataLen,
theOneWhoReceivesRawTraffic);
}
replyRawReplyIfnotWiretapped(receivedData, receivedDataLen);
} else {
//The loop may not execute more often than the number of received bytes (worst case).
//This approach avoids infinite loops due to buggy scanForReply routines (seen in bug 1077).
@ -537,12 +537,12 @@ void DeviceHandlerBase::doGetRead() {
&foundLen);
switch (result) {
case RETURN_OK:
handleReply(receivedData, foundId);
handleReply(receivedData, foundId, foundLen);
break;
case APERIODIC_REPLY: {
DataSet dataSet;
result = interpretDeviceReply(foundId, receivedData);
if (result != RETURN_OK) {
replyRawReplyIfnotWiretapped(receivedData, foundLen);
triggerEvent(DEVICE_INTERPRETING_REPLY_FAILED, result,
foundId);
}
@ -552,6 +552,7 @@ void DeviceHandlerBase::doGetRead() {
break;
default:
//We need to wait for timeout.. don't know what command failed and who sent it.
replyRawReplyIfnotWiretapped(receivedData, foundLen);
triggerEvent(DEVICE_READING_REPLY_FAILED, result, foundLen);
break;
}
@ -613,15 +614,15 @@ ReturnValue_t DeviceHandlerBase::initialize() {
}
AcceptsDeviceResponsesIF *rawReceiver = objectManager->get<
AcceptsDeviceResponsesIF>(objects::PUS_DEVICE_COMMAND_SERVICE);
AcceptsDeviceResponsesIF>(rawDataReceiverId);
if (rawReceiver == NULL) {
return RETURN_FAILED;
}
theOneWhoReceivesRawTraffic = rawReceiver->getDeviceQueue();
defaultRawReceiver = rawReceiver->getDeviceQueue();
powerSwitcher = objectManager->get<PowerSwitchIF>(objects::PCDU_HANDLER);
powerSwitcher = objectManager->get<PowerSwitchIF>(powerSwitcherId);
if (powerSwitcher == NULL) {
return RETURN_FAILED;
}
@ -649,6 +650,11 @@ ReturnValue_t DeviceHandlerBase::initialize() {
return result;
}
result = hkSwitcher.initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
fillCommandAndReplyMap();
//Set temperature target state to NON_OP.
@ -676,12 +682,6 @@ void DeviceHandlerBase::replyRawData(const uint8_t *data, size_t len,
return;
}
Command_t handlerCommand = DeviceHandlerMessage::REPLY_RAW_REPLY;
if (isCommand) {
handlerCommand = DeviceHandlerMessage::REPLY_RAW_COMMAND;
}
CommandMessage message;
DeviceHandlerMessage::setDeviceHandlerRawReplayMessage(&message,
@ -689,11 +689,11 @@ void DeviceHandlerBase::replyRawData(const uint8_t *data, size_t len,
// this->DeviceHandlerCommand = CommandMessage::CMD_NONE;
result = commandQueue.sendMessage(sendTo, &message);
result = commandQueue->sendMessage(sendTo, &message);
if (result != RETURN_OK) {
IPCStore->deleteData(address);
triggerEvent(MessageQueue::SEND_MSG_FAILED, result, sendTo);
//Silently discard data, this indicates heavy TM traffic which should not be increased by additional events.
}
}
@ -714,23 +714,22 @@ DeviceHandlerBase::RmapAction_t DeviceHandlerBase::getRmapAction() {
return GET_READ;
break;
default:
break;
}
return NOTHING;
}
MessageQueueId_t DeviceHandlerBase::getCommandQueue() const {
return commandQueue.getId();
return commandQueue->getId();
}
void DeviceHandlerBase::handleReply(const uint8_t* receivedData,
DeviceCommandId_t foundId) {
DeviceCommandId_t foundId, uint32_t foundLen) {
ReturnValue_t result;
DataSet dataSet;
DeviceReplyMap::iterator iter = deviceReplyMap.find(foundId);
if (iter == deviceReplyMap.end()) {
replyRawReplyIfnotWiretapped(receivedData, foundLen);
triggerEvent(DEVICE_UNKNOWN_REPLY, foundId);
return;
}
@ -747,12 +746,13 @@ void DeviceHandlerBase::handleReply(const uint8_t* receivedData,
result = interpretDeviceReply(foundId, receivedData);
if (result != RETURN_OK) {
//Report failed interpretation to FDIR.
replyRawReplyIfnotWiretapped(receivedData, foundLen);
triggerEvent(DEVICE_INTERPRETING_REPLY_FAILED, result, foundId);
}
replyToReply(iter, result);
} else {
//Other completion failure messages are created by timeout.
//Powering down the device might take some time during which periodic replys may still come in.
//Powering down the device might take some time during which periodic replies may still come in.
if (mode != _MODE_WAIT_OFF) {
triggerEvent(DEVICE_UNREQUESTED_REPLY, foundId);
}
@ -899,7 +899,8 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode,
mySet.read();
if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) {
if (!ThermalComponentIF::isOperational(thermalState)) {
triggerEvent(ThermalComponentIF::TEMP_NOT_IN_OP_RANGE, thermalState);
triggerEvent(ThermalComponentIF::TEMP_NOT_IN_OP_RANGE,
thermalState);
return NON_OP_TEMPERATURE;
}
}
@ -1020,6 +1021,20 @@ ReturnValue_t DeviceHandlerBase::acceptExternalDeviceCommands() {
return RETURN_OK;
}
void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* interface) {
executingTask = interface;
}
void DeviceHandlerBase::replyRawReplyIfnotWiretapped(const uint8_t* data,
size_t len) {
if ((wiretappingMode == RAW)
&& (defaultRawReceiver == requestedRawTraffic)) {
//The raw packet was already sent by the wiretapping service
} else {
replyRawData(data, len, defaultRawReceiver);
}
}
ReturnValue_t DeviceHandlerBase::handleDeviceHandlerMessage(
CommandMessage * message) {
ReturnValue_t result;
@ -1028,11 +1043,11 @@ ReturnValue_t DeviceHandlerBase::handleDeviceHandlerMessage(
switch (DeviceHandlerMessage::getWiretappingMode(message)) {
case RAW:
wiretappingMode = RAW;
theOneWhoWantsToReadRawTraffic = commandQueue.getLastPartner();
requestedRawTraffic = commandQueue->getLastPartner();
break;
case TM:
wiretappingMode = TM;
theOneWhoWantsToReadRawTraffic = commandQueue.getLastPartner();
requestedRawTraffic = commandQueue->getLastPartner();
break;
case OFF:
wiretappingMode = OFF;
@ -1091,23 +1106,39 @@ ReturnValue_t DeviceHandlerBase::letChildHandleMessage(
}
void DeviceHandlerBase::handleDeviceTM(SerializeIF* data,
DeviceCommandId_t replyId, bool neverInDataPool) {
DeviceCommandId_t replyId, bool neverInDataPool, bool forceDirectTm) {
DeviceReplyMap::iterator iter = deviceReplyMap.find(replyId);
if (iter == deviceReplyMap.end()) {
triggerEvent(DEVICE_UNKNOWN_REPLY, replyId);
return;
}
if (iter->second.command != deviceCommandMap.end()) {
DeviceTmReportingWrapper wrapper(getObjectId(), replyId, data);
if (iter->second.command != deviceCommandMap.end()) {//replies to a command
MessageQueueId_t queueId = iter->second.command->second.sendReplyTo;
DeviceTmReportingWrapper wrapper(getObjectId(), replyId, data);
if (queueId != NO_COMMANDER) {
//This may fail, but we'll ignore the fault.
actionHelper.reportData(queueId, replyId, data);
}
//This check should make sure we get any TM but don't get anything doubled.
if (wiretappingMode == TM
&& (theOneWhoWantsToReadRawTraffic != queueId)) {
actionHelper.reportData(theOneWhoWantsToReadRawTraffic,
replyId, &wrapper);
if (wiretappingMode == TM && (requestedRawTraffic != queueId)) {
actionHelper.reportData(requestedRawTraffic, replyId, &wrapper);
} else if (forceDirectTm && (defaultRawReceiver != queueId)) {
// hiding of sender needed so the service will handle it as unexpected Data, no matter what state
//(progress or completed) it is in
actionHelper.reportData(defaultRawReceiver, replyId, &wrapper,
true);
}
} else { //unrequested/aperiodic replies
if (wiretappingMode == TM) {
actionHelper.reportData(requestedRawTraffic, replyId, &wrapper);
} else if (forceDirectTm) {
// hiding of sender needed so the service will handle it as unexpected Data, no matter what state
//(progress or completed) it is in
actionHelper.reportData(defaultRawReceiver, replyId, &wrapper,
true);
}
}
//Try to cast to DataSet and commit data.
@ -1171,7 +1202,8 @@ void DeviceHandlerBase::buildInternalCommand(void) {
result = COMMAND_NOT_SUPPORTED;
} else if (iter->second.isExecuting) {
debug << std::hex << getObjectId()
<< ": DHB::buildInternalCommand: Command " << deviceCommandId << " isExecuting" << std::endl; //so we can track misconfigurations
<< ": DHB::buildInternalCommand: Command "
<< deviceCommandId << " isExecuting" << std::endl; //so we can track misconfigurations
return; //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
} else {
iter->second.sendReplyTo = NO_COMMANDER;
@ -1232,7 +1264,9 @@ ReturnValue_t DeviceHandlerBase::getParameter(uint8_t domainId,
}
bool DeviceHandlerBase::isTransitionalMode() {
return ((mode & (TRANSITION_MODE_BASE_ACTION_MASK | TRANSITION_MODE_CHILD_ACTION_MASK)) != 0);
return ((mode
& (TRANSITION_MODE_BASE_ACTION_MASK
| TRANSITION_MODE_CHILD_ACTION_MASK)) != 0);
}
bool DeviceHandlerBase::commandIsExecuting(DeviceCommandId_t commandId) {
@ -1244,3 +1278,6 @@ bool DeviceHandlerBase::commandIsExecuting(DeviceCommandId_t commandId) {
}
}
void DeviceHandlerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {
}

View File

@ -6,9 +6,7 @@
#include <framework/datapool/DataSet.h>
#include <framework/datapool/PoolVariableIF.h>
#include <framework/devicehandlers/DeviceCommunicationIF.h>
#include <framework/devicehandlers/DeviceHandlerFDIR.h>
#include <framework/devicehandlers/DeviceHandlerIF.h>
#include <framework/devicehandlers/PollingSequenceExecutableIF.h>
#include <framework/health/HealthHelper.h>
#include <framework/modes/HasModesIF.h>
#include <framework/objectmanager/SystemObject.h>
@ -16,7 +14,17 @@
#include <framework/parameters/ParameterHelper.h>
#include <framework/power/PowerSwitchIF.h>
#include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/tasks/ExecutableObjectIF.h>
#include <framework/devicehandlers/DeviceHandlerFailureIsolation.h>
#include <framework/datapool/HkSwitchHelper.h>
#include <framework/serialize/SerialFixedArrayListAdapter.h>
#include <map>
#include <framework/ipc/MessageQueueIF.h>
#include <framework/tasks/PeriodicTaskIF.h>
namespace Factory{
void setStaticFrameworkObjectIds();
}
class StorageManagerIF;
@ -27,7 +35,7 @@ class StorageManagerIF;
* communication with commanding objects.
* It inherits SystemObject and thus can be created by the ObjectManagerIF.
*
* This class is called by the PollingSequenceTable periodically. Thus, the execution is divided into PST cycles and steps within a cycle.
* This class uses the opcode of ExecutableObjectIF to perform a step-wise execution.
* For each step an RMAP action is selected and executed. If data has been received (eg in case of an RMAP Read), the data will be interpreted.
* The action for each step can be defined by the child class but as most device handlers share a 4-call (Read-getRead-write-getWrite) structure,
* a default implementation is provided.
@ -36,12 +44,13 @@ class StorageManagerIF;
*/
class DeviceHandlerBase: public DeviceHandlerIF,
public HasReturnvaluesIF,
public PollingSequenceExecutableIF,
public ExecutableObjectIF,
public SystemObject,
public HasModesIF,
public HasHealthIF,
public HasActionsIF,
public ReceivesParameterMessagesIF {
friend void (Factory::setStaticFrameworkObjectIds)();
public:
/**
* The constructor passes the objectId to the SystemObject().
@ -54,16 +63,16 @@ public:
uint32_t maxDeviceReplyLen, uint8_t setDeviceSwitch,
object_id_t deviceCommunication, uint32_t thermalStatePoolId =
PoolVariableIF::NO_PARAMETER,
uint32_t thermalRequestPoolId = PoolVariableIF::NO_PARAMETER, FDIRBase* fdirInstance = NULL, uint32_t cmdQueueSize = 20);
uint32_t thermalRequestPoolId = PoolVariableIF::NO_PARAMETER,
FailureIsolationBase* fdirInstance = NULL, uint32_t cmdQueueSize = 20);
virtual MessageQueueId_t getCommandQueue(void) const;
virtual void performInPST(uint8_t counter);
virtual ReturnValue_t performOperation(uint8_t counter);
virtual ReturnValue_t initialize();
/**
* MUST be called after initialize(), not before! TODO: Is this statement still valid?
*
* @param parentQueueId
*/
@ -81,13 +90,15 @@ public:
HealthState getHealth();
ReturnValue_t setHealth(HealthState health);
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex);
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex);
void setTaskIF(PeriodicTaskIF* interface);
protected:
/**
* The Returnvalues id of this class, required by HasReturnvaluesIF
*/
static const uint8_t INTERFACE_ID = DEVICE_HANDLER_BASE;
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE;
static const ReturnValue_t INVALID_CHANNEL = MAKE_RETURN_CODE(4);
static const ReturnValue_t APERIODIC_REPLY = MAKE_RETURN_CODE(5);
@ -106,19 +117,6 @@ protected:
static const DeviceCommandId_t NO_COMMAND_ID = -2;
static const MessageQueueId_t NO_COMMANDER = 0;
/**
* RMAP Action that will be executed.
*
* This is used by the child class to tell the base class what to do.
*/
enum RmapAction_t {
SEND_WRITE, //!< RMAP send write
GET_WRITE, //!< RMAP get write
SEND_READ, //!< RMAP send read
GET_READ, //!< RMAP get read
NOTHING //!< Do nothing.
};
/**
* Pointer to the raw packet that will be sent.
*/
@ -143,7 +141,7 @@ protected:
Submode_t submode;
/**
* This is the counter value from performInPST().
* This is the counter value from performOperation().
*/
uint8_t pstStep;
@ -163,11 +161,12 @@ protected:
} wiretappingMode;
/**
* the message queue which commanded raw mode
* A message queue that accepts raw replies
*
* This is the one to receive raw replies
* Statically initialized in initialize() to a configurable object. Used when there is no method
* of finding a recipient, ie raw mode and reporting erreonous replies
*/
MessageQueueId_t theOneWhoReceivesRawTraffic;
MessageQueueId_t defaultRawReceiver;
store_address_t storedRawData;
@ -176,7 +175,7 @@ protected:
*
* if #isWiretappingActive all raw communication from and to the device will be sent to this queue
*/
MessageQueueId_t theOneWhoWantsToReadRawTraffic;
MessageQueueId_t requestedRawTraffic;
/**
* the object used to set power switches
@ -208,7 +207,7 @@ protected:
/**
* The MessageQueue used to receive device handler commands and to send replies.
*/
MessageQueue commandQueue;
MessageQueueIF* commandQueue;
/**
* this is the datapool variable with the thermal state of the device
@ -241,12 +240,21 @@ protected:
uint32_t ignoreMissedRepliesCount; //!< Counts if communication channel lost a reply, so some missed replys can be ignored.
FDIRBase* fdirInstance; //!< Pointer to the used FDIR instance. If not provided by child, default class is instantiated.
FailureIsolationBase* fdirInstance; //!< Pointer to the used FDIR instance. If not provided by child, default class is instantiated.
HkSwitchHelper hkSwitcher;
bool defaultFDIRUsed; //!< To correctly delete the default instance.
bool switchOffWasReported; //!< Indicates if SWITCH_WENT_OFF was already thrown.
static object_id_t powerSwitcherId; //!< Object which switches power on and off.
static object_id_t rawDataReceiverId; //!< Object which receives RAW data by default.
static object_id_t defaultFDIRParentId; //!< Object which may be the root cause of an identified fault.
PeriodicTaskIF* executingTask;
/**
* Helper function to report a missed reply
*
@ -593,6 +601,12 @@ protected:
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
*/
void replyRawReplyIfnotWiretapped(const uint8_t *data, size_t len);
/**
* Return the switches connected to the device.
*
@ -663,6 +677,11 @@ protected:
*/
virtual void setNormalDatapoolEntriesInvalid() = 0;
/**
* build a list of sids and pass it to the #hkSwitcher
*/
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
/**
* Children can overwrite this function to suppress checking of the command Queue
*
@ -679,7 +698,7 @@ protected:
bool isAwaitingReply();
void handleDeviceTM(SerializeIF *dataSet, DeviceCommandId_t commandId,
bool neverInDataPool = false);
bool neverInDataPool = false, bool forceDirectTm = false);
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode);
@ -732,12 +751,6 @@ protected:
virtual ReturnValue_t acceptExternalDeviceCommands();
bool commandIsExecuting(DeviceCommandId_t commandId);
private:
/**
* Information about commands
*/
DeviceCommandMap deviceCommandMap;
/**
* Information about expected replies
@ -750,6 +763,7 @@ private:
uint8_t periodic; //!< if this is !=0, the delayCycles will not be reset to 0 but to maxDelayCycles
DeviceCommandMap::iterator command; //!< The command that expects this reply.
};
/**
* Definition for the important reply Map.
*/
@ -767,6 +781,15 @@ private:
*/
DeviceReplyMap deviceReplyMap;
/**
* Information about commands
*/
DeviceCommandMap deviceCommandMap;
ActionHelper actionHelper;
private:
/**
* State a cookie is in.
*
@ -837,8 +860,6 @@ private:
*/
const uint8_t deviceSwitch;
ActionHelper actionHelper;
/**
* read the command queue
*/
@ -880,8 +901,9 @@ private:
*
* @param data the found packet
* @param id the found id
* @foundLen the length of the packet
*/
void handleReply(const uint8_t *data, DeviceCommandId_t id);
void handleReply(const uint8_t *data, DeviceCommandId_t id, uint32_t foundLen);
void replyToReply(DeviceReplyMap::iterator iter, ReturnValue_t status);
/**

View File

@ -1,20 +1,14 @@
/*
* DeviceHandlerFDIR.cpp
*
* Created on: 09.09.2015
* Author: baetz
*/
#include <framework/devicehandlers/DeviceHandlerBase.h>
#include <framework/devicehandlers/DeviceHandlerFDIR.h>
#include <framework/devicehandlers/DeviceHandlerFailureIsolation.h>
#include <framework/health/HealthTableIF.h>
#include <framework/power/Fuse.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <mission/controllers/power/Fuse.h>
#include <mission/controllers/tcs/ThermalComponentIF.h>
#include <framework/thermal/ThermalComponentIF.h>
//TODO: Mechanisms have no power FDIR..
DeviceHandlerFDIR::DeviceHandlerFDIR(object_id_t owner, object_id_t parent) :
FDIRBase(owner, parent), strangeReplyCount(MAX_STRANGE_REPLIES,
object_id_t DeviceHandlerFailureIsolation::powerConfirmationId = 0;
DeviceHandlerFailureIsolation::DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent) :
FailureIsolationBase(owner, parent), strangeReplyCount(MAX_STRANGE_REPLIES,
STRANGE_REPLIES_TIME_MS, parameterDomainBase++), missedReplyCount(
MAX_MISSED_REPLY_COUNT, MISSED_REPLY_TIME_MS,
parameterDomainBase++), recoveryCounter(MAX_REBOOT,
@ -22,25 +16,11 @@ DeviceHandlerFDIR::DeviceHandlerFDIR(object_id_t owner, object_id_t parent) :
0) {
}
DeviceHandlerFDIR::~DeviceHandlerFDIR() {
DeviceHandlerFailureIsolation::~DeviceHandlerFailureIsolation() {
}
ReturnValue_t DeviceHandlerFDIR::eventReceived(EventMessage* event) {
if (fdirState != NONE) {
//Only wait for those events, ignore all others.
if (event->getParameter1() == HasHealthIF::HEALTHY
&& event->getEvent() == HasHealthIF::HEALTH_INFO) {
setFdirState(NONE);
}
if (event->getEvent() == HasModesIF::MODE_INFO
&& fdirState != RECOVERY_ONGOING) {
setFdirState(NONE);
}
return RETURN_OK;
}
if (owner->getHealth() == HasHealthIF::FAULTY
|| owner->getHealth() == HasHealthIF::PERMANENT_FAULTY) {
//Ignore all events in case device is already faulty.
ReturnValue_t DeviceHandlerFailureIsolation::eventReceived(EventMessage* event) {
if(isFdirInActionOrAreWeFaulty(event)) {
return RETURN_OK;
}
ReturnValue_t result = RETURN_FAILED;
@ -76,13 +56,11 @@ ReturnValue_t DeviceHandlerFDIR::eventReceived(EventMessage* event) {
break;
case StorageManagerIF::GET_DATA_FAILED:
case StorageManagerIF::STORE_DATA_FAILED:
case MessageQueue::SEND_MSG_FAILED:
//Rather strange bugs, occur in RAW mode only. TODO:? By now: Ignore.
//Rather strange bugs, occur in RAW mode only. Ignore.
break;
case DeviceHandlerIF::INVALID_DEVICE_COMMAND:
//Ignore, is bad configuration. We can't do anything in flight.
break;
case DeviceHandlerIF::MONITORING_AMBIGUOUS:
case HasHealthIF::HEALTH_INFO:
case HasModesIF::MODE_INFO:
case HasModesIF::CHANGING_MODE:
@ -111,13 +89,17 @@ ReturnValue_t DeviceHandlerFDIR::eventReceived(EventMessage* event) {
case ThermalComponentIF::COMPONENT_TEMP_OOL_LOW:
case ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH:
//Well, the device is not really faulty, but it is required to stay off as long as possible.
//*******ACS*****
case DeviceHandlerIF::MONITORING_LIMIT_EXCEEDED:
setFaulty(event->getEvent());
break;
case ThermalComponentIF::TEMP_NOT_IN_OP_RANGE:
//Ignore, is information only.
break;
//*******Default monitoring variables. Are currently not used.*****
// case DeviceHandlerIF::MONITORING_LIMIT_EXCEEDED:
// setFaulty(event->getEvent());
// break;
// case DeviceHandlerIF::MONITORING_AMBIGUOUS:
// break;
default:
//We don't know the event, someone else should handle it.
return RETURN_FAILED;
@ -125,7 +107,7 @@ ReturnValue_t DeviceHandlerFDIR::eventReceived(EventMessage* event) {
return RETURN_OK;
}
void DeviceHandlerFDIR::eventConfirmed(EventMessage* event) {
void DeviceHandlerFailureIsolation::eventConfirmed(EventMessage* event) {
switch (event->getEvent()) {
case DeviceHandlerIF::DEVICE_SENDING_COMMAND_FAILED:
case DeviceHandlerIF::DEVICE_REQUESTING_REPLY_FAILED:
@ -143,13 +125,13 @@ void DeviceHandlerFDIR::eventConfirmed(EventMessage* event) {
}
}
void DeviceHandlerFDIR::decrementFaultCounters() {
void DeviceHandlerFailureIsolation::decrementFaultCounters() {
strangeReplyCount.checkForDecrement();
missedReplyCount.checkForDecrement();
recoveryCounter.checkForDecrement();
}
void DeviceHandlerFDIR::handleRecovery(Event reason) {
void DeviceHandlerFailureIsolation::handleRecovery(Event reason) {
clearFaultCounters();
if (!recoveryCounter.incrementAndCheck()) {
startRecovery(reason);
@ -158,7 +140,7 @@ void DeviceHandlerFDIR::handleRecovery(Event reason) {
}
}
void DeviceHandlerFDIR::wasParentsFault(EventMessage* event) {
void DeviceHandlerFailureIsolation::wasParentsFault(EventMessage* event) {
//We'll better ignore the SWITCH_WENT_OFF event and await a system-wide reset.
//This means, no fault message will come through until a MODE_ or HEALTH_INFO message comes through -> Is that ok?
//Same issue in TxFailureIsolation!
@ -168,18 +150,18 @@ void DeviceHandlerFDIR::wasParentsFault(EventMessage* event) {
// }
}
void DeviceHandlerFDIR::clearFaultCounters() {
void DeviceHandlerFailureIsolation::clearFaultCounters() {
strangeReplyCount.clear();
missedReplyCount.clear();
}
ReturnValue_t DeviceHandlerFDIR::initialize() {
ReturnValue_t result = FDIRBase::initialize();
ReturnValue_t DeviceHandlerFailureIsolation::initialize() {
ReturnValue_t result = FailureIsolationBase::initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
ConfirmsFailuresIF* power = objectManager->get<ConfirmsFailuresIF>(
objects::PCDU_HANDLER);
powerConfirmationId);
if (power == NULL) {
return RETURN_FAILED;
}
@ -187,31 +169,31 @@ ReturnValue_t DeviceHandlerFDIR::initialize() {
return RETURN_OK;
}
void DeviceHandlerFDIR::setFdirState(FDIRState state) {
FDIRBase::throwFdirEvent(FDIR_CHANGED_STATE, state, fdirState);
void DeviceHandlerFailureIsolation::setFdirState(FDIRState state) {
FailureIsolationBase::throwFdirEvent(FDIR_CHANGED_STATE, state, fdirState);
fdirState = state;
}
void DeviceHandlerFDIR::triggerEvent(Event event, uint32_t parameter1,
void DeviceHandlerFailureIsolation::triggerEvent(Event event, uint32_t parameter1,
uint32_t parameter2) {
//Do not throw error events if fdirState != none.
//This will still forward MODE and HEALTH INFO events in any case.
if (fdirState == NONE || EVENT::getSeverity(event) == SEVERITY::INFO) {
FDIRBase::triggerEvent(event, parameter1, parameter2);
FailureIsolationBase::triggerEvent(event, parameter1, parameter2);
}
}
bool DeviceHandlerFDIR::isFdirActionInProgress() {
bool DeviceHandlerFailureIsolation::isFdirActionInProgress() {
return (fdirState != NONE);
}
void DeviceHandlerFDIR::startRecovery(Event reason) {
void DeviceHandlerFailureIsolation::startRecovery(Event reason) {
throwFdirEvent(FDIR_STARTS_RECOVERY, EVENT::getEventId(reason));
setOwnerHealth(HasHealthIF::NEEDS_RECOVERY);
setFdirState(RECOVERY_ONGOING);
}
ReturnValue_t DeviceHandlerFDIR::getParameter(uint8_t domainId,
ReturnValue_t DeviceHandlerFailureIsolation::getParameter(uint8_t domainId,
uint16_t parameterId, ParameterWrapper* parameterWrapper,
const ParameterWrapper* newValues, uint16_t startAtIndex) {
ReturnValue_t result = strangeReplyCount.getParameter(domainId, parameterId,
@ -232,8 +214,30 @@ ReturnValue_t DeviceHandlerFDIR::getParameter(uint8_t domainId,
return INVALID_DOMAIN_ID;
}
void DeviceHandlerFDIR::setFaulty(Event reason) {
void DeviceHandlerFailureIsolation::setFaulty(Event reason) {
throwFdirEvent(FDIR_TURNS_OFF_DEVICE, EVENT::getEventId(reason));
setOwnerHealth(HasHealthIF::FAULTY);
setFdirState(AWAIT_SHUTDOWN);
}
bool DeviceHandlerFailureIsolation::isFdirInActionOrAreWeFaulty(
EventMessage* event) {
if (fdirState != NONE) {
//Only wait for those events, ignore all others.
if (event->getParameter1() == HasHealthIF::HEALTHY
&& event->getEvent() == HasHealthIF::HEALTH_INFO) {
setFdirState(NONE);
}
if (event->getEvent() == HasModesIF::MODE_INFO
&& fdirState != RECOVERY_ONGOING) {
setFdirState(NONE);
}
return true;
}
if (owner->getHealth() == HasHealthIF::FAULTY
|| owner->getHealth() == HasHealthIF::PERMANENT_FAULTY) {
//Ignore all events in case device is already faulty.
return true;
}
return false;
}

View File

@ -1,27 +1,22 @@
/*
* DeviceHandlerFDIR.h
*
* Created on: 09.09.2015
* Author: baetz
*/
#ifndef FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERFDIR_H_
#define FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERFDIR_H_
#ifndef FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERFAILUREISOLATION_H_
#define FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERFAILUREISOLATION_H_
#include <framework/fdir/FaultCounter.h>
#include <framework/fdir/FDIRBase.h>
#include <framework/fdir/FailureIsolationBase.h>
namespace Factory{
void setStaticFrameworkObjectIds();
}
class DeviceHandlerFDIR: public FDIRBase {
class DeviceHandlerFailureIsolation: public FailureIsolationBase {
friend void (Factory::setStaticFrameworkObjectIds)();
friend class Heater;
public:
DeviceHandlerFDIR(object_id_t owner, object_id_t parent = objects::IO_ASSEMBLY);
~DeviceHandlerFDIR();
virtual ReturnValue_t eventReceived(EventMessage* event);
void eventConfirmed(EventMessage* event);
void wasParentsFault(EventMessage* event);
void decrementFaultCounters();
DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent);
~DeviceHandlerFailureIsolation();
ReturnValue_t initialize();
void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0);
bool isFdirActionInProgress();
void triggerEvent(Event event, uint32_t parameter1 = 0,
uint32_t parameter2 = 0);bool isFdirActionInProgress();
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex);
@ -30,25 +25,28 @@ protected:
FaultCounter missedReplyCount;
FaultCounter recoveryCounter;
enum FDIRState {
NONE,
RECOVERY_ONGOING,
DEVICE_MIGHT_BE_OFF,
AWAIT_SHUTDOWN
NONE, RECOVERY_ONGOING, DEVICE_MIGHT_BE_OFF, AWAIT_SHUTDOWN
};
FDIRState fdirState;
MessageQueueId_t powerConfirmation;
//TODO: Arbitrary numbers! Adjust!
static object_id_t powerConfirmationId;
static const uint32_t MAX_REBOOT = 1;
static const uint32_t REBOOT_TIME_MS = 180000;
static const uint32_t MAX_STRANGE_REPLIES = 10;
static const uint32_t STRANGE_REPLIES_TIME_MS = 10000;
static const uint32_t MAX_MISSED_REPLY_COUNT = 5;
static const uint32_t MISSED_REPLY_TIME_MS = 10000;
virtual ReturnValue_t eventReceived(EventMessage* event);
virtual void eventConfirmed(EventMessage* event);
void wasParentsFault(EventMessage* event);
void decrementFaultCounters();
void handleRecovery(Event reason);
virtual void clearFaultCounters();
void setFdirState(FDIRState state);
void startRecovery(Event reason);
void setFaulty(Event reason);
bool isFdirInActionOrAreWeFaulty(EventMessage* event);
};
#endif /* FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERFDIR_H_ */
#endif /* FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERFAILUREISOLATION_H_ */

View File

@ -4,8 +4,8 @@
#include <framework/action/HasActionsIF.h>
#include <framework/devicehandlers/DeviceHandlerMessage.h>
#include <framework/events/Event.h>
#include <framework/ipc/MessageQueue.h>
#include <framework/modes/HasModesIF.h>
#include <framework/ipc/MessageQueueSenderIF.h>
/**
* This is the Interface used to communicate with a device handler.
@ -52,7 +52,7 @@ public:
static const Event MONITORING_LIMIT_EXCEEDED = MAKE_EVENT(9, SEVERITY::LOW);
static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, SEVERITY::HIGH);
static const uint8_t INTERFACE_ID = DEVICE_HANDLER_IF;
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF;
static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA0);
static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA1);
static const ReturnValue_t COMMAND_ALREADY_SENT = MAKE_RETURN_CODE(0xA2);
@ -63,6 +63,7 @@ public:
static const ReturnValue_t BUSY = MAKE_RETURN_CODE(0xA7);
static const ReturnValue_t NO_REPLY_EXPECTED = MAKE_RETURN_CODE(0xA8); //!< Used to indicate that this is a command-only command.
static const ReturnValue_t NON_OP_TEMPERATURE = MAKE_RETURN_CODE(0xA9);
static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xAA);
//standard codes used in scan for reply
// static const ReturnValue_t TOO_SHORT = MAKE_RETURN_CODE(0xB1);
@ -82,6 +83,19 @@ public:
0xD0);
static const ReturnValue_t INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS =
MAKE_RETURN_CODE(0xD1);
/**
* RMAP Action that will be executed.
*
* This is used by the child class to tell the base class what to do.
*/
enum RmapAction_t {
SEND_WRITE,//!< RMAP send write
GET_WRITE, //!< RMAP get write
SEND_READ, //!< RMAP send read
GET_READ, //!< RMAP get read
NOTHING //!< Do nothing.
};
/**
* Default Destructor
*/

View File

@ -89,7 +89,7 @@ void DeviceHandlerMessage::clear(CommandMessage* message) {
ipcStore->deleteData(getStoreAddress(message));
}
}
/* NO BREAK*/
/* NO BREAK falls through*/
case CMD_SWITCH_IOBOARD:
case CMD_WIRETAPPING:
message->setCommand(CommandMessage::CMD_NONE);

View File

@ -5,7 +5,7 @@
#include <framework/ipc/CommandMessage.h>
#include <framework/objectmanager/SystemObjectIF.h>
#include <framework/storagemanager/StorageManagerIF.h>
//TODO: rework the static constructors to name the type of command they are building, maybe even hide setting the commandID.
//SHOULDDO: rework the static constructors to name the type of command they are building, maybe even hide setting the commandID.
/**
* This is used to uniquely identify commands that are sent to a device
@ -25,7 +25,7 @@ public:
/**
* These are the commands that can be sent to a DeviceHandlerBase
*/
static const uint8_t MESSAGE_ID = DEVICE_HANDLER_COMMAND_MESSAGE_ID;
static const uint8_t MESSAGE_ID = MESSAGE_TYPE::DEVICE_HANDLER_COMMAND;
static const Command_t CMD_RAW = MAKE_COMMAND_ID( 1 ); //!< Sends a raw command, setParameter is a ::store_id_t containing the raw packet to send
// static const Command_t CMD_DIRECT = MAKE_COMMAND_ID( 2 ); //!< Sends a direct command, setParameter is a ::DeviceCommandId_t, setParameter2 is a ::store_id_t containing the data needed for the command
static const Command_t CMD_SWITCH_IOBOARD = MAKE_COMMAND_ID( 3 ); //!< Requests a IO-Board switch, setParameter() is the IO-Board identifier

View File

@ -0,0 +1,21 @@
/**
* @file PollingSlot.cpp
* @brief This file defines the PollingSlot class.
* @date 19.12.2012
* @author baetz
*/
#include <framework/devicehandlers/FixedSequenceSlot.h>
#include <framework/objectmanager/SystemObjectIF.h>
#include <cstddef>
FixedSequenceSlot::FixedSequenceSlot(object_id_t handlerId, uint32_t setTime,
int8_t setSequenceId, PeriodicTaskIF* executingTask) :
handler(NULL), pollingTimeMs(setTime), opcode(setSequenceId) {
handler = objectManager->get<ExecutableObjectIF>(handlerId);
handler->setTaskIF(executingTask);
}
FixedSequenceSlot::~FixedSequenceSlot() {
}

View File

@ -1,44 +1,40 @@
/**
* @file PollingSlot.h
* @file FixedSequenceSlot.h
* @brief This file defines the PollingSlot class.
* @date 19.12.2012
* @author baetz
*/
#ifndef POLLINGSLOT_H_
#define POLLINGSLOT_H_
#ifndef FIXEDSEQUENCESLOT_H_
#define FIXEDSEQUENCESLOT_H_
#include <framework/devicehandlers/PollingSequenceExecutableIF.h>
#include <framework/objectmanager/ObjectManagerIF.h>
#include <framework/osal/OSAL.h>
class PollingSequence;
#include <framework/tasks/ExecutableObjectIF.h>
class PeriodicTaskIF;
/**
* \brief This class is the representation of a single polling sequence table entry.
*
* \details The PollingSlot class is the representation of a single polling sequence table entry.
* It contains three attributes and a debug method to print its content.
*/
class PollingSlot {
friend class PollingSequence;
friend class PollingTask;
friend ReturnValue_t pollingSequenceInitFunction(PollingSequence *thisSequence);
friend ReturnValue_t payloadSequenceInitFunction(PollingSequence *thisSequence);
protected:
class FixedSequenceSlot {
public:
FixedSequenceSlot( object_id_t handlerId, uint32_t setTimeMs, int8_t setSequenceId, PeriodicTaskIF* executingTask );
virtual ~FixedSequenceSlot();
/**
* \brief \c handler identifies which device handler object is executed in this slot.
*/
PollingSequenceExecutableIF* handler;
ExecutableObjectIF* handler;
/**
* \brief This attribute defines when a device handler object is executed.
*
* \details The pollingTime attribute identifies the time the handler is executed in clock ticks. It must be
* \details The pollingTime attribute identifies the time the handler is executed in ms. It must be
* smaller than the period length of the polling sequence, what is ensured by automated calculation
* from a database.
*/
Interval_t pollingTime;
uint32_t pollingTimeMs;
/**
* \brief This value defines the type of device communication.
@ -46,16 +42,7 @@ protected:
* \details The state of this value decides what communication routine is called in the PST executable or the device handler object.
*/
uint8_t opcode;
public:
PollingSlot( object_id_t handlerId, Interval_t setTime, int8_t setSequenceId );
virtual ~PollingSlot();
/**
* \brief This is a small debug method to print the PollingSlot's content to a debug interface.
*/
void print() const;
};
#endif /* POLLINGSLOT_H_ */
#endif /* FIXEDSEQUENCESLOT_H_ */

View File

@ -0,0 +1,109 @@
#include <framework/devicehandlers/FixedSlotSequence.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) :
lengthMs(setLengthMs) {
current = slotList.begin();
}
FixedSlotSequence::~FixedSlotSequence() {
std::list<FixedSequenceSlot*>::iterator slotIt;
//Iterate through slotList and delete all entries.
slotIt = this->slotList.begin();
while (slotIt != this->slotList.end()) {
delete (*slotIt);
slotIt++;
}
}
void FixedSlotSequence::executeAndAdvance() {
// (*this->current)->print();
(*this->current)->handler->performOperation((*this->current)->opcode);
// if (returnValue != RETURN_OK) {
// this->sendErrorMessage( returnValue );
// }
//Increment the polling Sequence iterator
this->current++;
//Set it to the beginning, if the list's end is reached.
if (this->current == this->slotList.end()) {
this->current = this->slotList.begin();
}
}
uint32_t FixedSlotSequence::getIntervalMs() {
uint32_t oldTime;
std::list<FixedSequenceSlot*>::iterator it;
it = current;
// Get the pollingTimeMs of the current slot object.
oldTime = (*it)->pollingTimeMs;
// Advance to the next object.
it++;
// Find the next interval which is not 0.
while (it != slotList.end()) {
if (oldTime != (*it)->pollingTimeMs) {
return (*it)->pollingTimeMs - oldTime;
} else {
it++;
}
}
// If the list end is reached (this is definitely an interval != 0),
// the interval is calculated by subtracting the remaining time of the PST
// and adding the start time of the first handler in the list.
it = slotList.begin();
return lengthMs - oldTime + (*it)->pollingTimeMs;
}
bool FixedSlotSequence::slotFollowsImmediately() {
uint32_t currentTime = (*current)->pollingTimeMs;
std::list<FixedSequenceSlot*>::iterator it;
it = this->current;
// Get the pollingTimeMs of the current slot object.
if (it == slotList.begin())
return false;
it--;
if ((*it)->pollingTimeMs == currentTime) {
return true;
} else {
return false;
}
}
uint32_t FixedSlotSequence::getLengthMs() const {
return this->lengthMs;
}
ReturnValue_t FixedSlotSequence::checkSequence() const {
//Iterate through slotList and check successful creation. Checks if timing is ok (must be ascending) and if all handlers were found.
auto slotIt = slotList.begin();
uint32_t count = 0;
uint32_t time = 0;
while (slotIt != slotList.end()) {
if ((*slotIt)->handler == NULL) {
error << "FixedSlotSequene::initialize: ObjectId does not exist!"
<< std::endl;
count++;
} else if ((*slotIt)->pollingTimeMs < time) {
error << "FixedSlotSequence::initialize: Time: "
<< (*slotIt)->pollingTimeMs
<< " is smaller than previous with " << time << std::endl;
count++;
} else {
//All ok, print slot.
// (*slotIt)->print();
}
time = (*slotIt)->pollingTimeMs;
slotIt++;
}
if (count > 0) {
return HasReturnvaluesIF::RETURN_FAILED;
}
return HasReturnvaluesIF::RETURN_OK;
}
void FixedSlotSequence::addSlot(object_id_t componentId, uint32_t slotTimeMs,
int8_t executionStep, PeriodicTaskIF* executingTask) {
this->slotList.push_back(
new FixedSequenceSlot(componentId, slotTimeMs, executionStep,
executingTask));
this->current = slotList.begin();
}

View File

@ -1,24 +1,14 @@
/**
* @file PollingSequence.h
* @brief This file defines the PollingSequence class.
* @date 19.12.2012
* @author baetz
*/
#ifndef FIXEDSLOTSEQUENCE_H_
#define FIXEDSLOTSEQUENCE_H_
#ifndef POLLINGSEQUENCE_H_
#define POLLINGSEQUENCE_H_
#include <framework/devicehandlers/PollingSequenceExecutableIF.h>
#include <framework/devicehandlers/PollingSlot.h>
#include <framework/devicehandlers/FixedSequenceSlot.h>
#include <framework/objectmanager/SystemObject.h>
#include <framework/osal/OSAL.h>
#include<list>
#include <list>
/**
* \brief This class is the representation of a Polling Sequence Table in software.
*
* \details The PollingSequence object maintains the dynamic execution of device handler objects.
* \details The FixedSlotSequence object maintains the dynamic execution of device handler objects.
* The main idea is to create a list of device handlers, to announce all handlers to the
* polling sequence and to maintain a list of polling slot objects. This slot list represents the
* Polling Sequence Table in software. Each polling slot contains information to indicate when and
@ -26,10 +16,78 @@
* The sequence is then executed by iterating through this slot list.
* Handlers are invoking by calling a certain function stored in the handler list.
*/
class PollingSequence : public SystemObject {
friend class PollingTask;
friend ReturnValue_t pollingSequenceInitFunction(PollingSequence *thisSequence);
friend ReturnValue_t payloadSequenceInitFunction(PollingSequence *thisSequence);
class FixedSlotSequence {
public:
/**
* \brief The constructor of the FixedSlotSequence object.
*
* \details The constructor takes two arguments, the period length and the init function.
*
* \param setLength The period length, expressed in ms.
*/
FixedSlotSequence(uint32_t setLengthMs);
/**
* \brief The destructor of the FixedSlotSequence object.
*
* \details The destructor frees all allocated memory by iterating through the slotList
* and deleting all allocated resources.
*/
virtual ~FixedSlotSequence();
/**
* \brief This is a method to add an PollingSlot object to slotList.
*
* \details Here, a polling slot object is added to the slot list. It is appended
* to the end of the list. The list is currently NOT reordered.
* Afterwards, the iterator current is set to the beginning of the list.
*/
void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId,
PeriodicTaskIF* executingTask);
/**
* Checks if the current slot shall be executed immediately after the one before.
* This allows to distinguish between grouped and not grouped handlers.
* @return - @c true if the slot has the same polling time as the previous
* - @c false else
*/
bool slotFollowsImmediately();
/**
* \brief This method returns the time until the next software component is invoked.
*
* \details This method is vitally important for the operation of the PST. By fetching the polling time
* of the current slot and that of the next one (or the first one, if the list end is reached)
* it calculates and returns the interval in clock ticks within which the handler execution
* shall take place.
*/
uint32_t getIntervalMs();
/**
* \brief This method returns the length of this FixedSlotSequence instance.
*/
uint32_t getLengthMs() const;
/**
* \brief The method to execute the device handler entered in the current OPUSPollingSlot object.
*
* \details Within this method the device handler object to be executed is chosen by looking up the
* handler address of the current slot in the handlerMap. Either the device handler's
* talkToInterface or its listenToInterface method is invoked, depending on the isTalking flag
* of the polling slot. After execution the iterator current is increased or, by reaching the
* end of slotList, reset to the beginning.
*/
void executeAndAdvance();
/**
* \brief An iterator that indicates the current polling slot to execute.
*
* \details This is an iterator for slotList and always points to the polling slot which is executed next.
*/
std::list<FixedSequenceSlot*>::iterator current;
ReturnValue_t checkSequence() const;
protected:
/**
@ -41,109 +99,9 @@ protected:
* By iterating through this list the polling sequence is executed. Two entries with identical
* polling times are executed immediately one after another.
*/
std::list<PollingSlot*> slotList;
std::list<FixedSequenceSlot*> slotList;
/**
* \brief An iterator that indicates the current polling slot to execute.
*
* \details This is an iterator for slotList and always points to the polling slot which is executed next.
*/
std::list<PollingSlot*>::iterator current;
/**
* \brief The period of the Polling Sequence Table in clock ticks.
*
* \details This attribute is set within the constructor, defining the main period length of the
* Polling Sequence Table. The length is expressed in clock ticks.
*
*/
Interval_t length;
/**
* \brief The init function passed by the ctor
*
* \details This function will be called during initialize()
*
*/
ReturnValue_t (*initFunction)(PollingSequence *thisSequence);
public:
/**
* \brief The constructor of the PollingSequence object.
*
* \details The constructor takes two arguments, the period length and the init function.
*
* \param setLength The period length, expressed in clock ticks.
*/
PollingSequence( object_id_t setObjectId, Interval_t setLength, ReturnValue_t (*initFunction)(PollingSequence *thisSequence) );
/**
* \brief The destructor of the PollingSequence object.
*
* \details The destructor frees all allocated memory by iterating through
* handlerMap and slotList and deleting all allocated resources.
*/
virtual ~PollingSequence();
/**
* \brief This is a method to add an OPUSPollingSlot object to slotList.
*
* \details Here, a polling slot object is added to the slot list. It is appended
* to the end of the list. The list is currently NOT reordered.
* Afterwards, the iterator current is set to the beginning of the list.
*
* \param setSlot This is a pointer to a OPUSPollingSlot object.
*/
void addSlot( PollingSlot* setSlot );
/**
* Checks if the current slot shall be executed immediately after the one before.
* This allows to distinguish between grouped and not grouped handlers.
* @return - @c true if the slot has the same polling time as the previous
* - @c false else
*/
bool slotFollowsImmediately();
/**
* \brief This method returns the time until the next device handler object is invoked.
*
* \details This method is vitally important for the operation of the PST. By fetching the polling time
* of the current slot and that of the next one (or the first one, if the list end is reached)
* it calculates and returns the interval in clock ticks within which the handler execution
* shall take place.
*/
Interval_t getInterval();
/**
* \brief This method returns the length of this PollingSequence instance.
*/
Interval_t getLength();
/**
* \brief The method to execute the device handler entered in the current OPUSPollingSlot object.
*
* \details Within this method the device handler object to be executed is chosen by looking up the
* handler address of the current slot in the handlerMap. Either the device handler's
* talkToInterface or its listenToInterface method is invoked, depending on the isTalking flag
* of the polling slot. After execution the iterator current is increased or, by reaching the
* end of slotList, reset to the beginning.
*/
void pollAndAdvance();
/**
* \brief This is a method to print debug output.
*
* \details print is a simple debug method to print the whole polling sequence to the debug interface.
* It iterates through slotList and calls all print()} functions of the announced polling slot
* instances.
*
*/
void print();
ReturnValue_t initialize();
//std::string getObjectTypeAsString();
uint32_t lengthMs;
};
#endif /* POLLINGSEQUENCE_H_ */
#endif /* FIXEDSLOTSEQUENCE_H_ */

View File

@ -1,18 +1,20 @@
#include <framework/devicehandlers/HealthDevice.h>
#include <framework/ipc/QueueFactory.h>
HealthDevice::HealthDevice(object_id_t setObjectId,
MessageQueueId_t parentQueue) :
SystemObject(setObjectId), lastHealth(HEALTHY), parentQueue(
parentQueue), commandQueue(3,
CommandMessage::COMMAND_MESSAGE_SIZE), healthHelper(this, setObjectId) {
parentQueue), commandQueue(), healthHelper(this, setObjectId) {
commandQueue = QueueFactory::instance()->createMessageQueue(3, CommandMessage::COMMAND_MESSAGE_SIZE);
}
HealthDevice::~HealthDevice() {
QueueFactory::instance()->deleteMessageQueue(commandQueue);
}
ReturnValue_t HealthDevice::performOperation() {
ReturnValue_t HealthDevice::performOperation(uint8_t opCode) {
CommandMessage message;
ReturnValue_t result = commandQueue.receiveMessage(&message);
ReturnValue_t result = commandQueue->receiveMessage(&message);
if (result == HasReturnvaluesIF::RETURN_OK) {
healthHelper.handleHealthCommand(&message);
}
@ -32,7 +34,7 @@ ReturnValue_t HealthDevice::initialize() {
}
MessageQueueId_t HealthDevice::getCommandQueue() const {
return commandQueue.getId();
return commandQueue->getId();
}
void HealthDevice::setParentQueue(MessageQueueId_t parentQueue) {

View File

@ -5,6 +5,7 @@
#include <framework/health/HealthHelper.h>
#include <framework/objectmanager/SystemObject.h>
#include <framework/tasks/ExecutableObjectIF.h>
#include <framework/ipc/MessageQueueIF.h>
class HealthDevice: public SystemObject,
public ExecutableObjectIF,
@ -13,7 +14,7 @@ public:
HealthDevice(object_id_t setObjectId, MessageQueueId_t parentQueue);
virtual ~HealthDevice();
ReturnValue_t performOperation();
ReturnValue_t performOperation(uint8_t opCode);
ReturnValue_t initialize();
@ -31,7 +32,7 @@ protected:
HealthState lastHealth;
MessageQueueId_t parentQueue;
MessageQueue commandQueue;
MessageQueueIF* commandQueue;
public:
HealthHelper healthHelper;
};

View File

@ -1,28 +0,0 @@
#!/bin/bash
#
# OPUS makefile
#
# Created on: Mar 04, 2010
# Author: ziemke
# Author: Claas Ziemke
# Copyright 2010, Claas Ziemke <claas.ziemke@gmx.net>
#
BASEDIR=../../
include $(BASEDIR)options.mk
OBJ = $(BUILDDIR)/ChannelResetHandler.o \
$(BUILDDIR)/RawCommandHandler.o \
$(BUILDDIR)/RawDataHandler.o \
$(BUILDDIR)/OPUSPollingSequence.o \
$(BUILDDIR)/PollingTask.o \
$(BUILDDIR)/Device.o \
$(BUILDDIR)/RmapCookie.o \
all: $(OBJ)
$(BUILDDIR)/%.o: %.cpp %.h
$(CPP) $(CFLAGS) $(DEFINES) $(CCOPT) ${INCLUDE} -c $< -o $@
clean:
$(RM) *.o *.gcno *.gcda

View File

@ -1,115 +0,0 @@
/**
* @file PollingSequence.cpp
* @brief This file defines the PollingSequence class.
* @date 19.12.2012
* @author baetz
*/
#include <framework/devicehandlers/PollingSequence.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
uint32_t PollingSequenceExecutableIF::pollingSequenceLengthMs = 0;
uint32_t PollingSequenceExecutableIF::payloadSequenceLengthMs = 0;
PollingSequence::PollingSequence(object_id_t setObjectId, Interval_t setLength, ReturnValue_t (*initFunction)(PollingSequence *thisSequence)) : SystemObject( setObjectId ),
initFunction(initFunction){
this->length = setLength;
// PollingSequenceExecutableIF::pollingSequenceLengthMs = (setLength * 1000)
// / OSAL::getTicksPerSecond();
current = slotList.begin();
}
PollingSequence::~PollingSequence() {
std::list<PollingSlot*>::iterator slotIt;
//Iterate through slotList and delete all entries.
slotIt = this->slotList.begin();
while (slotIt != this->slotList.end()) {
delete (*slotIt);
slotIt++;
}
}
void PollingSequence::addSlot(PollingSlot* setSlot) {
//The slot is added to the end of the list.
this->slotList.push_back(setSlot);
this->current = slotList.begin();
}
void PollingSequence::pollAndAdvance() {
// (*this->current)->print();
(*this->current)->handler->performInPST( (*this->current)->opcode );
// if (returnValue != RETURN_OK) {
// this->sendErrorMessage( returnValue );
// }
//Increment the polling Sequence iterator
this->current++;
//Set it to the beginning, if the list's end is reached.
if (this->current == this->slotList.end()) {
this->current = this->slotList.begin();
}
}
Interval_t PollingSequence::getInterval() {
Interval_t oldTime;
std::list<PollingSlot*>::iterator it;
it = this->current;
// Get the pollingTime of the current slot object.
oldTime = (*it)->pollingTime;
// Advance to the next object.
it++;
// Find the next interval which is not 0.
while ( it != slotList.end() ) {
if ( oldTime != (*it)->pollingTime ) {
return (*it)->pollingTime - oldTime;
} else {
it++;
}
}
// If the list end is reached (this is definitely an interval != 0),
// the interval is calculated by subtracting the remaining time of the PST
// and adding the start time of the first handler in the list.
it = slotList.begin();
return this->length - oldTime + (*it)->pollingTime;
}
bool PollingSequence::slotFollowsImmediately() {
Interval_t currentTime = (*current)->pollingTime;
std::list<PollingSlot*>::iterator it;
it = this->current;
// Get the pollingTime of the current slot object.
if ( it == slotList.begin() ) return false;
it--;
if ( (*it)->pollingTime == currentTime ) {
return true;
} else {
return false;
}
}
Interval_t PollingSequence::getLength() {
return this->length;
}
void PollingSequence::print() {
debug << "Polling sequence contains:" << std::endl;
//Iterate through slotList and start all PollingSlot::print() methods.
do {
(*current)->print();
current++;
} while (current != slotList.end());
current = slotList.begin();
}
//std::string PollingSequence::getObjectTypeAsString() {
// return "PollingSequence";
//}
ReturnValue_t PollingSequence::initialize() {
ReturnValue_t result = SystemObject::initialize();
if (result != HasReturnvaluesIF::RETURN_OK){
return result;
}
return initFunction(this);
}

View File

@ -1,30 +0,0 @@
/*
* PollingSequenceExecutableIF.h
*
* Created on: Mar 30, 2012
* Author: baetz
*/
#ifndef POLLINGSEQUENCEEXECUTABLE_H_
#define POLLINGSEQUENCEEXECUTABLE_H_
//TODO clean this whole file up
//TODO maybe define a type to make it look cleaner and use it in the PST
#define SEND_WRITE_CMD 0
#define GET_WRITE_REPLY 1
#define SEND_READ_CMD 2
#define GET_READ_REPLY 3
#include <framework/osal/OSAL.h>
class PollingSequenceExecutableIF {
public:
static uint32_t pollingSequenceLengthMs;
static uint32_t payloadSequenceLengthMs;
virtual void performInPST( uint8_t ) = 0;
virtual ~PollingSequenceExecutableIF() { }
};
#endif /* POLLINGSEQUENCEEXECUTABLE_H_ */

View File

@ -1,29 +0,0 @@
/**
* @file PollingSlot.cpp
* @brief This file defines the PollingSlot class.
* @date 19.12.2012
* @author baetz
*/
#include <framework/devicehandlers/PollingSlot.h>
#include <framework/objectmanager/SystemObjectIF.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
PollingSlot::PollingSlot( object_id_t handlerId, Interval_t setTime, int8_t setSequenceId ) {
//Set all attributes directly on object creation.
this->handler = objectManager->get<PollingSequenceExecutableIF>( handlerId );
this->pollingTime = setTime;
this->opcode = setSequenceId;
}
PollingSlot::~PollingSlot() {
}
void PollingSlot::print() const {
SystemObjectIF * systemObject = dynamic_cast<SystemObjectIF *>(handler);
object_id_t id = (systemObject == NULL) ? 0xffffffff : systemObject->getObjectId();
debug << "HandlerID: " << std::hex << id << std::dec << "; Polling Time: "
<< this->pollingTime << "; Opcode: " << (uint16_t) this->opcode
<< std::endl;
}

View File

@ -1,103 +0,0 @@
/**
* \file OPUSPollingTask.cpp
*
* \brief This file contains the implementation for the OPUSPollingTask class.
*
* \author Bastian Baetz
*
* \date 17.03.2011
*
*/
#include <framework/devicehandlers/PollingTask.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
uint32_t PollingTask::deadlineMissedCount = 0;
PollingTask::PollingTask( const char *name, TaskPriority_t setPriority, size_t setStack, void (*setDeadlineMissedFunc)(), object_id_t getPst ) :
TaskBase( setPriority, setStack, name ), periodId(0) {
// All additional attributes are applied to the object.
this->deadlineMissedFunc = setDeadlineMissedFunc;
this->pst = objectManager->get<PollingSequence>( getPst );
}
PollingTask::~PollingTask() {
// The PollingSequence destructor is called, if a sequence is announced.
if ( this->pst != NULL ) {
this->pst->~PollingSequence();
} else {
// There was no memory allocation, so there's nothing to do.
}
}
TaskReturn_t PollingTask::taskEntryPoint( TaskArgument_t argument ) {
//The argument is re-interpreted as PollingTask.
PollingTask *originalTask( reinterpret_cast<PollingTask*>( argument ) );
if ( originalTask->pst != NULL ) {
//The task's functionality is called.
originalTask->taskFunctionality();
} else {
}
debug << "Polling task " << originalTask->getId() << " returned from taskFunctionality." << std::endl;
}
void PollingTask::missedDeadlineCounter() {
PollingTask::deadlineMissedCount++;
if (PollingTask::deadlineMissedCount%10 == 0) {
error << "PST missed " << PollingTask::deadlineMissedCount << " deadlines." << std::endl;
}
}
ReturnValue_t PollingTask::startTask() {
this->setRunning( true );
ReturnValue_t status;
status = OSAL::startTask( &( this->id ), PollingTask::taskEntryPoint, TaskArgument_t( ( void *)this ) );
if( status != RETURN_OK ) {
//TODO: Call any FDIR routine?
error << "PollingTask::startTask for " << std::hex << this->getId() << std::dec << " failed." << std::endl;
} else {
// debug << "PollingTask::startTask for " << std::hex << this->getId() << std::dec << " successful" << std::endl;
}
return status;
}
void PollingTask::taskFunctionality() {
ReturnValue_t status = OSAL::TIMEOUT;
Interval_t interval;
// A local iterator for the Polling Sequence Table is created to find the start time for the first entry.
std::list<PollingSlot*>::iterator it;
it = this->pst->current;
//The start time for the first entry is read.
interval = ( *it )->pollingTime;
//The period is set up and started with the system call.
status = OSAL::setAndStartPeriod( interval, &( this->periodId ) );
if( status == RETURN_OK ) {
//The task's "infinite" inner loop is entered.
while( this->isRunning ) {
if ( pst->slotFollowsImmediately() ) {
//Do nothing
} else {
//The interval for the next polling slot is selected.
interval = this->pst->getInterval();
//The period is checked and restarted with the new interval.
//If the deadline was missed, the deadlineMissedFunc is called.
status = OSAL::checkAndRestartPeriod( this->periodId, interval );
if( status == OSAL::TIMEOUT ) {
if( this->deadlineMissedFunc != NULL ) {
this->deadlineMissedFunc();
}
}
}
//The device handler for this slot is executed and the next one is chosen.
this->pst->pollAndAdvance();
}
} else {
error << "PollingTask::setAndStartPeriod failed with status "<< status << std::endl;
}
//Any operating system object for periodic execution is deleted.
debug << "Deleting the PollingTask's period." << std::endl;
OSAL::deletePeriod( &(this->id) );
}

View File

@ -1,115 +0,0 @@
/**
* @file PollingTask.h
*
* @brief This file contains the definition for the PollingTask class.
*
* @author Claas Ziemke, Bastian Baetz
*
* @date 17.03.2011
*
* Copyright 2009,2010, Claas Ziemke <claas.ziemke@gmx.net>
* All rights reserved
*
*/
#ifndef POLLINGTASK_H_
#define POLLINGTASK_H_
#include <framework/devicehandlers/PollingSequence.h>
#include <framework/tasks/TaskBase.h>
/**
*
* @brief This class represents a specialized thread to execute polling sequences.
*
* @image latex seq_PST_dynamic.eps "Sequence diagram of polling sequence operation" width=1@textwidth
* @image html seq_PST_dynamic.png "Sequence diagram of polling sequence operation"
*
* @details The Polling Sequence Table is executed in a task of special type, called PollingTask.
* After creation the polling task initializes the PST and starts taskFunctionality.
* An infinite loop is entered within which the iteration through the PST is done by repetitive calls of
* getInterval() and pollAndAdvance().
* @ingroup task_handling
*/
class PollingTask: public TaskBase {
protected:
/**
* @brief id of the associated OS period
*/
PeriodId_t periodId;
/**
* @brief This attribute is the pointer to the complete polling sequence table object.
*
* @details The most important attribute of the thread object.
* It holds a pointer to the complete polling sequence table object.
*/
PollingSequence* pst;
/**
* @brief This attribute holds a function pointer that is executed when a deadline was missed.
*
* @details Another function may be announced to determine the actions to perform when a deadline was missed.
* Currently, only one function for missing any deadline is allowed.
* If not used, it shall be declared NULL.
*/
void ( *deadlineMissedFunc )( void );
/**
* @brief This is the entry point in a new polling thread.
*
* @details This method, that is the general entry point in the new thread, is here set to generate
* and link the Polling Sequence Table to the thread object and start taskFunctionality()
* on success. If operation of the task is ended for some reason,
* the destructor is called to free allocated memory.
*/
static TaskReturn_t taskEntryPoint( TaskArgument_t argument );
/**
* @brief This function holds the main functionality of the thread.
*
*
* @details Holding the main functionality of the task, this method is most important.
* It links the functionalities provided by PollingSequence with the OS's System Calls
* to keep the timing of the periods.
*/
void taskFunctionality( void );
public:
/**
* @brief The standard constructor of the class.
*
* @details This is the general constructor of the class. In addition to the TaskBase parameters,
* the following variables are passed:
*
* @param (*setDeadlineMissedFunc)() The function pointer to the deadline missed function that shall be assigned.
*
* @param getPst The object id of the completely initialized polling sequence.
*/
PollingTask( const char *name, TaskPriority_t setPriority, size_t setStack, void (*setDeadlineMissedFunc)(), object_id_t getPst );
/**
* @brief The destructor of the class.
*
* @details The destructor frees all heap memory that was allocated on thread initialization for the PST and
* the device handlers. This is done by calling the PST's destructor.
*/
virtual ~PollingTask( void );
/**
* @brief The function to actually start a new task.
*
* @details As described in TaskBase this method invokes the operating systems method to start a new task.
* Entry point is taskEntryPoint().
*/
ReturnValue_t startTask( void );
/**
* This static function can be used as #deadlineMissedFunc.
* It counts missedDeadlines and prints the number of missed deadlines every 10th time.
*/
static void missedDeadlineCounter();
/**
* A helper variable to count missed deadlines.
*/
static uint32_t deadlineMissedCount;
};
#endif /* POLLINGTASK_H_ */