1
0
forked from fsfw/fsfw

Today's the day. Renamed platform to framework.

This commit is contained in:
Bastian Baetz
2016-06-15 23:48:41 +02:00
committed by Ulrich Mohr
parent 40987d0b27
commit 1d22a6c97e
356 changed files with 33946 additions and 3 deletions

636
subsystem/Subsystem.cpp Normal file
View File

@ -0,0 +1,636 @@
/*
* Subsystem.cpp
*
* Created on: 12.07.2013
* Author: tod
*/
#include <framework/health/HealthMessage.h>
#include <framework/objectmanager/ObjectManagerIF.h>
#include <framework/serialize/SerialArrayListAdapter.h>
#include <framework/serialize/SerialFixedArrayListAdapter.h>
#include <framework/serialize/SerializeElement.h>
#include <framework/serialize/SerialLinkedListAdapter.h>
#include <framework/subsystem/Subsystem.h>
#include <string>
Subsystem::Subsystem(object_id_t setObjectId, object_id_t parent,
uint32_t maxNumberOfSequences, uint32_t maxNumberOfTables) :
SubsystemBase(setObjectId, parent, 0), isInTransition(false), childrenChangedHealth(
false), uptimeStartTable(0), currentTargetTable(), targetMode(
0), targetSubmode(SUBMODE_NONE), initialMode(0), currentSequenceIterator(), modeTables(
maxNumberOfTables), modeSequences(maxNumberOfSequences), IPCStore(
NULL), modeStore(NULL) {
}
Subsystem::~Subsystem() {
//Auto-generated destructor stub
}
ReturnValue_t Subsystem::checkSequence(HybridIterator<ModeListEntry> iter,
Mode_t fallbackSequence) {
//only check for existence, checking the fallback would lead to a (possibly infinite) recursion.
//the fallback sequence will be checked when it is needed.
if (!existsModeSequence(fallbackSequence)) {
return FALLBACK_SEQUENCE_DOES_NOT_EXIST;
}
if (iter.value == NULL) {
return NO_TARGET_TABLE;
}
for (; iter.value != NULL; ++iter) {
if (!existsModeTable(iter->getTableId())) {
return TABLE_DOES_NOT_EXIST;
} else {
ReturnValue_t result = checkTable(getTable(iter->getTableId()));
if (result != RETURN_OK) {
return result;
}
}
}
return RETURN_OK;
}
ReturnValue_t Subsystem::checkSequence(Mode_t sequence) {
if (!existsModeSequence(sequence)) {
return SEQUENCE_DOES_NOT_EXIST;
}
HybridIterator<ModeListEntry> iter = getSequence(sequence);
return checkSequence(iter, getFallbackSequence(sequence));
}
bool Subsystem::existsModeSequence(Mode_t id) {
return modeSequences.exists(id) == RETURN_OK;
}
bool Subsystem::existsModeTable(Mode_t id) {
return modeTables.exists(id) == RETURN_OK;
}
HybridIterator<ModeListEntry> Subsystem::getCurrentTable() {
return getTable(currentSequenceIterator->getTableId());
}
void Subsystem::performChildOperation() {
if (isInTransition) {
if (commandsOutstanding <= 0) { //all children of the current table were commanded and replied
if (currentSequenceIterator.value == NULL) { //we're through with this sequence
if (checkStateAgainstTable(currentTargetTable) == RETURN_OK) {
setMode(targetMode, targetSubmode);
isInTransition = false;
return;
} else {
transitionFailed(TARGET_TABLE_NOT_REACHED,
getSequence(targetMode)->getTableId());
return;
}
}
if (currentSequenceIterator->checkSuccess()) {
if (checkStateAgainstTable(getCurrentTable()) != RETURN_OK) {
transitionFailed(TABLE_CHECK_FAILED,
currentSequenceIterator->getTableId());
return;
}
}
if (currentSequenceIterator->getWaitSeconds() != 0) {
if (uptimeStartTable != 0) {
OSAL::getUptime(&uptimeStartTable);
return;
} else {
uint32_t uptimeNow;
OSAL::getUptime(&uptimeNow);
if ((uptimeNow - uptimeStartTable)
< (currentSequenceIterator->getWaitSeconds() * 1000)) {
return;
}
}
}
uptimeStartTable = 0;
//next Table, but only if there is one
if ((++currentSequenceIterator).value != NULL) { //we're through with this sequence
executeTable(getCurrentTable());
}
}
} else {
if (childrenChangedHealth) {
triggerEvent(CHILD_CHANGED_HEALTH, 0, 0);
childrenChangedHealth = false;
startTransition(mode, submode);
} else if (childrenChangedMode) {
if (checkStateAgainstTable(currentTargetTable) != RETURN_OK) {
triggerEvent(CANT_KEEP_MODE, mode, submode);
cantKeepMode();
}
}
}
}
HybridIterator<ModeListEntry> Subsystem::getSequence(Mode_t id) {
SequenceInfo *sequenceInfo = modeSequences.findValue(id);
if (sequenceInfo->entries.islinked) {
return HybridIterator<ModeListEntry>(
sequenceInfo->entries.firstLinkedElement);
} else {
return HybridIterator<ModeListEntry>(
sequenceInfo->entries.array->front(),
sequenceInfo->entries.array->back());
}
}
HybridIterator<ModeListEntry> Subsystem::getTable(Mode_t id) {
EntryPointer *entry = modeTables.findValue(id);
if (entry->islinked) {
return HybridIterator<ModeListEntry>(entry->firstLinkedElement);
} else {
return HybridIterator<ModeListEntry>(entry->array->front(),
entry->array->back());
}
}
ReturnValue_t Subsystem::handleCommandMessage(CommandMessage* message) {
ReturnValue_t result;
switch (message->getCommand()) {
case HealthMessage::HEALTH_INFO: {
HealthState health = HealthMessage::getHealth(message);
if (health != EXTERNAL_CONTROL) {
//Ignore external control, as it has an effect only if the mode changes,
//which is communicated with an additional mode info event.
childrenChangedHealth = true;
}
}
break;
case ModeSequenceMessage::ADD_SEQUENCE: {
FixedArrayList<ModeListEntry, MAX_LENGTH_OF_TABLE_OR_SEQUENCE> sequence;
const uint8_t *pointer;
uint32_t sizeRead;
result = IPCStore->getData(
ModeSequenceMessage::getStoreAddress(message), &pointer,
&sizeRead);
if (result == RETURN_OK) {
Mode_t fallbackId;
int32_t size = sizeRead;
result = SerializeAdapter<Mode_t>::deSerialize(&fallbackId,
&pointer, &size, true);
if (result == RETURN_OK) {
result = SerialArrayListAdapter<ModeListEntry>::deSerialize(
&sequence, &pointer, &size, true);
if (result == RETURN_OK) {
result = addSequence(&sequence,
ModeSequenceMessage::getSequenceId(message),
fallbackId);
}
}
IPCStore->deleteData(ModeSequenceMessage::getStoreAddress(message));
}
replyToCommand(result, 0);
}
break;
case ModeSequenceMessage::ADD_TABLE: {
FixedArrayList<ModeListEntry, MAX_LENGTH_OF_TABLE_OR_SEQUENCE> table;
const uint8_t *pointer;
uint32_t sizeRead;
result = IPCStore->getData(
ModeSequenceMessage::getStoreAddress(message), &pointer,
&sizeRead);
if (result == RETURN_OK) {
int32_t size = sizeRead;
result = SerialArrayListAdapter<ModeListEntry>::deSerialize(&table,
&pointer, &size, true);
if (result == RETURN_OK) {
result = addTable(&table,
ModeSequenceMessage::getSequenceId(message));
}
IPCStore->deleteData(ModeSequenceMessage::getStoreAddress(message));
}
replyToCommand(result, 0);
}
break;
case ModeSequenceMessage::DELETE_SEQUENCE:
if (isInTransition) {
replyToCommand(IN_TRANSITION, 0);
break;
}
result = deleteSequence(ModeSequenceMessage::getSequenceId(message));
replyToCommand(result, 0);
break;
case ModeSequenceMessage::DELETE_TABLE:
if (isInTransition) {
replyToCommand(IN_TRANSITION, 0);
break;
}
result = deleteTable(ModeSequenceMessage::getTableId(message));
replyToCommand(result, 0);
break;
case ModeSequenceMessage::LIST_SEQUENCES: {
SerialFixedArrayListAdapter<Mode_t, MAX_NUMBER_OF_TABLES_OR_SEQUENCES> sequences;
FixedMap<Mode_t, SequenceInfo>::Iterator iter;
for (iter = modeSequences.begin(); iter != modeSequences.end();
++iter) {
sequences.insert(iter.value->first);
}
SerializeIF *pointer = &sequences;
sendSerializablesAsCommandMessage(ModeSequenceMessage::SEQUENCE_LIST,
&pointer, 1);
}
break;
case ModeSequenceMessage::LIST_TABLES: {
SerialFixedArrayListAdapter<Mode_t, MAX_NUMBER_OF_TABLES_OR_SEQUENCES> tables;
FixedMap<Mode_t, EntryPointer>::Iterator iter;
for (iter = modeTables.begin(); iter != modeTables.end(); ++iter) {
tables.insert(iter.value->first);
}
SerializeIF *pointer = &tables;
sendSerializablesAsCommandMessage(ModeSequenceMessage::TABLE_LIST,
&pointer, 1);
}
break;
case ModeSequenceMessage::READ_SEQUENCE: {
ReturnValue_t result;
Mode_t sequence = ModeSequenceMessage::getSequenceId(message);
SequenceInfo *sequenceInfo = NULL;
result = modeSequences.find(sequence, &sequenceInfo);
if (result != RETURN_OK) {
replyToCommand(result, 0);
}
SerializeIF *elements[3];
SerializeElement<Mode_t> sequenceId(sequence);
SerializeElement<Mode_t> fallbackSequenceId(
getFallbackSequence(sequence));
elements[0] = &sequenceId;
elements[1] = &fallbackSequenceId;
if (sequenceInfo->entries.islinked) {
SerialLinkedListAdapter<ModeListEntry> list(
sequenceInfo->entries.firstLinkedElement, true);
elements[2] = &list;
sendSerializablesAsCommandMessage(ModeSequenceMessage::SEQUENCE,
elements, 3);
} else {
SerialArrayListAdapter<ModeListEntry> serializableArray(
sequenceInfo->entries.array);
elements[2] = &serializableArray;
sendSerializablesAsCommandMessage(ModeSequenceMessage::SEQUENCE,
elements, 3);
}
}
break;
case ModeSequenceMessage::READ_TABLE: {
ReturnValue_t result;
Mode_t table = ModeSequenceMessage::getSequenceId(message);
EntryPointer *entry = NULL;
result = modeTables.find(table, &entry);
if (result != RETURN_OK) {
replyToCommand(result, 0);
}
SerializeIF *elements[2];
SerializeElement<Mode_t> tableId(table);
elements[0] = &tableId;
if (entry->islinked) {
SerialLinkedListAdapter<ModeListEntry> list(
entry->firstLinkedElement, true);
elements[1] = &list;
sendSerializablesAsCommandMessage(ModeSequenceMessage::TABLE,
elements, 2);
} else {
SerialArrayListAdapter<ModeListEntry> serializableArray(
entry->array);
elements[1] = &serializableArray;
sendSerializablesAsCommandMessage(ModeSequenceMessage::TABLE,
elements, 2);
}
}
break;
case ModeSequenceMessage::READ_FREE_SEQUENCE_SLOTS: {
uint32_t freeSlots = modeSequences.maxSize() - modeSequences.size();
CommandMessage reply;
ModeSequenceMessage::setModeSequenceMessage(&reply,
ModeSequenceMessage::FREE_SEQUENCE_SLOTS, freeSlots);
commandQueue.reply(&reply);
}
break;
case ModeSequenceMessage::READ_FREE_TABLE_SLOTS: {
uint32_t free = modeTables.maxSize() - modeTables.size();
CommandMessage reply;
ModeSequenceMessage::setModeSequenceMessage(&reply,
ModeSequenceMessage::FREE_TABLE_SLOTS, free);
commandQueue.reply(&reply);
}
break;
default:
return RETURN_FAILED;
}
return RETURN_OK;
}
void Subsystem::replyToCommand(ReturnValue_t status, uint32_t parameter) {
if (status == RETURN_OK) {
CommandMessage reply(CommandMessage::REPLY_COMMAND_OK, 0, 0);
commandQueue.reply(&reply);
} else {
CommandMessage reply(CommandMessage::REPLY_REJECTED, status, 0);
commandQueue.reply(&reply);
}
}
ReturnValue_t Subsystem::addSequence(ArrayList<ModeListEntry>* sequence,
Mode_t id, Mode_t fallbackSequence, bool inStore, bool preInit) {
ReturnValue_t result;
//Before initialize() is called, tables must not be checked as the children are not added yet.
//Sequences added before are checked by initialize()
if (!preInit) {
result = checkSequence(
HybridIterator<ModeListEntry>(sequence->front(),
sequence->back()), fallbackSequence);
if (result != RETURN_OK) {
return result;
}
}
SequenceInfo info;
info.fallbackSequence = fallbackSequence;
info.entries.islinked = inStore;
info.entries.array = sequence;
result = modeSequences.insert(id, info);
if (result != RETURN_OK) {
return result;
}
if (inStore) {
result = modeStore->storeArray(sequence,
&(modeSequences.find(id)->entries.firstLinkedElement));
if (result != RETURN_OK) {
modeSequences.erase(id);
}
}
return result;
}
ReturnValue_t Subsystem::addTable(ArrayList<ModeListEntry> *table, Mode_t id,
bool inStore, bool preInit) {
ReturnValue_t result;
//Before initialize() is called, tables must not be checked as the children are not added yet.
//Tables added before are checked by initialize()
if (!preInit) {
result = checkTable(
HybridIterator<ModeListEntry>(table->front(), table->back()));
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
}
EntryPointer pointer;
pointer.islinked = inStore;
pointer.array = table;
result = modeTables.insert(id, pointer);
if (result != RETURN_OK) {
return result;
}
if (inStore) {
result = modeStore->storeArray(table,
&(modeTables.find(id)->firstLinkedElement));
if (result != RETURN_OK) {
modeTables.erase(id);
}
}
return result;
}
ReturnValue_t Subsystem::deleteSequence(Mode_t id) {
if (isFallbackSequence(id)) {
return IS_FALLBACK_SEQUENCE;
}
SequenceInfo *sequenceInfo;
ReturnValue_t result;
result = modeSequences.find(id, &sequenceInfo);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if (!sequenceInfo->entries.islinked) {
return ACCESS_DENIED;
}
modeStore->deleteList(sequenceInfo->entries.firstLinkedElement);
modeSequences.erase(id);
return RETURN_OK;
}
ReturnValue_t Subsystem::deleteTable(Mode_t id) {
if (isTableUsed(id)) {
return TABLE_IN_USE;
}
EntryPointer *pointer;
ReturnValue_t result;
result = modeTables.find(id, &pointer);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if (!pointer->islinked) {
return ACCESS_DENIED;
}
modeStore->deleteList(pointer->firstLinkedElement);
modeSequences.erase(id);
return RETURN_OK;
}
ReturnValue_t Subsystem::initialize() {
ReturnValue_t result = SubsystemBase::initialize();
if (result != RETURN_OK) {
return result;
}
IPCStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
modeStore = objectManager->get<ModeStoreIF>(objects::MODE_STORE);
if ((IPCStore == NULL) || (modeStore == NULL)) {
return RETURN_FAILED;
}
if ((modeSequences.maxSize() > MAX_NUMBER_OF_TABLES_OR_SEQUENCES)
|| (modeTables.maxSize() > MAX_NUMBER_OF_TABLES_OR_SEQUENCES)) {
return TABLE_OR_SEQUENCE_LENGTH_INVALID;
}
mode = initialMode;
return RETURN_OK;
}
MessageQueueId_t Subsystem::getSequenceCommandQueue() const {
return SubsystemBase::getCommandQueue();
}
ReturnValue_t Subsystem::checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t* msToReachTheMode) {
if (submode != SUBMODE_NONE) {
return INVALID_SUBMODE;
}
if (isInTransition && (mode != getFallbackSequence(targetMode))) {
return HasModesIF::IN_TRANSITION;
} else {
return checkSequence(mode);
}
}
void Subsystem::startTransition(Mode_t sequence, Submode_t submode) {
if (modeHelper.isForced()) {
triggerEvent(FORCING_MODE, sequence, submode);
} else {
triggerEvent(CHANGING_MODE, sequence, submode);
}
targetMode = sequence;
targetSubmode = submode;
isInTransition = true;
commandsOutstanding = 0;
currentSequenceIterator = getSequence(sequence);
currentTargetTable = getTable(currentSequenceIterator->getTableId());
++currentSequenceIterator;
if (currentSequenceIterator.value != NULL) {
executeTable(getCurrentTable());
}
}
Mode_t Subsystem::getFallbackSequence(Mode_t sequence) {
for (FixedMap<Mode_t, SequenceInfo>::Iterator iter = modeSequences.begin();
iter != modeSequences.end(); ++iter) {
if (iter.value->first == sequence) {
return iter->fallbackSequence;
}
}
return -1;
}
bool Subsystem::isFallbackSequence(Mode_t SequenceId) {
for (FixedMap<Mode_t, SequenceInfo>::Iterator iter = modeSequences.begin();
iter != modeSequences.end(); iter++) {
if (iter->fallbackSequence == SequenceId) {
return true;
}
}
return false;
}
bool Subsystem::isTableUsed(Mode_t tableId) {
for (FixedMap<Mode_t, SequenceInfo>::Iterator sequence =
modeSequences.begin(); sequence != modeSequences.end();
sequence++) {
HybridIterator<ModeListEntry> sequenceIterator = getSequence(
sequence.value->first);
while (sequenceIterator.value != NULL) {
if (sequenceIterator->getTableId() == tableId) {
return true;
}
++sequenceIterator;
}
}
return false;
}
void Subsystem::transitionFailed(ReturnValue_t failureCode,
uint32_t parameter) {
triggerEvent(MODE_TRANSITION_FAILED, failureCode, parameter);
if (mode == targetMode) {
//already tried going back to the current mode
//go into fallback mode, also set current mode to fallback mode, so we come here at the next fail
modeHelper.setForced(true);
ReturnValue_t result;
if ((result = checkSequence(getFallbackSequence(mode))) != RETURN_OK) {
triggerEvent(FALLBACK_FAILED, result, getFallbackSequence(mode));
isInTransition = false; //keep still and allow arbitrary mode commands to recover
return;
}
mode = getFallbackSequence(mode);
startTransition(mode, submode);
} else {
//try to go back to the current mode
startTransition(mode, submode);
}
}
void Subsystem::sendSerializablesAsCommandMessage(Command_t command,
SerializeIF** elements, uint8_t count) {
ReturnValue_t result;
uint32_t maxSize = 0;
for (uint8_t i = 0; i < count; i++) {
maxSize += elements[i]->getSerializedSize();
}
uint8_t *storeBuffer;
store_address_t address;
uint32_t size = 0;
result = IPCStore->getFreeElement(&address, maxSize, &storeBuffer);
if (result != HasReturnvaluesIF::RETURN_OK) {
replyToCommand(result, 0);
return;
}
for (uint8_t i = 0; i < count; i++) {
elements[i]->serialize(&storeBuffer, &size, maxSize, true);
}
CommandMessage reply;
ModeSequenceMessage::setModeSequenceMessage(&reply, command, address);
if (commandQueue.reply(&reply) != RETURN_OK) {
IPCStore->deleteData(address);
}
}
ReturnValue_t Subsystem::checkObjectConnections() {
ReturnValue_t result = RETURN_OK;
for (FixedMap<Mode_t, SequenceInfo>::Iterator iter = modeSequences.begin();
iter != modeSequences.end(); iter++) {
result = checkSequence(iter.value->first);
if (result != RETURN_OK) {
return result;
}
}
return RETURN_OK;
}
void Subsystem::setInitialMode(Mode_t mode) {
initialMode = mode;
}
void Subsystem::cantKeepMode() {
ReturnValue_t result;
if ((result = checkSequence(getFallbackSequence(mode))) != RETURN_OK) {
triggerEvent(FALLBACK_FAILED, result, getFallbackSequence(mode));
return;
}
modeHelper.setForced(true);
//already set the mode, so that we do not try to go back in our old mode when the transition fails
mode = getFallbackSequence(mode);
//SHOULDDO: We should store submodes for fallback sequence as well, otherwise we should get rid of submodes completely.
startTransition(mode, SUBMODE_NONE);
}

169
subsystem/Subsystem.h Normal file
View File

@ -0,0 +1,169 @@
/*
* Subsystem.h
*
* Created on: 12.07.2013
* Author: tod
*/
#ifndef SUBSYSTEM_H_
#define SUBSYSTEM_H_
#include <framework/container/FixedArrayList.h>
#include <framework/container/FixedMap.h>
#include <framework/container/HybridIterator.h>
#include <framework/container/SinglyLinkedList.h>
#include <framework/serialize/SerialArrayListAdapter.h>
#include <framework/subsystem/modes/ModeDefinitions.h>
#include <framework/subsystem/SubsystemBase.h>
class Subsystem: public SubsystemBase, public HasModeSequenceIF {
public:
static const uint8_t INTERFACE_ID = SUBSYSTEM;
static const ReturnValue_t SEQUENCE_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t TABLE_ALREADY_EXISTS = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t TABLE_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);
static const ReturnValue_t TABLE_OR_SEQUENCE_LENGTH_INVALID = MAKE_RETURN_CODE(0x04);
static const ReturnValue_t SEQUENCE_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x05);
static const ReturnValue_t TABLE_CONTAINS_INVALID_OBJECT_ID =
MAKE_RETURN_CODE(0x06);
static const ReturnValue_t FALLBACK_SEQUENCE_DOES_NOT_EXIST =
MAKE_RETURN_CODE(0x07);
static const ReturnValue_t NO_TARGET_TABLE = MAKE_RETURN_CODE(0x08);
static const ReturnValue_t SEQUENCE_OR_TABLE_TOO_LONG = MAKE_RETURN_CODE(0x09);
static const ReturnValue_t IS_FALLBACK_SEQUENCE = MAKE_RETURN_CODE(0x0B);
static const ReturnValue_t ACCESS_DENIED = MAKE_RETURN_CODE(0x0C);
static const ReturnValue_t TABLE_IN_USE = MAKE_RETURN_CODE(0x0E);
static const ReturnValue_t TARGET_TABLE_NOT_REACHED = MAKE_RETURN_CODE(0xA1);
static const ReturnValue_t TABLE_CHECK_FAILED = MAKE_RETURN_CODE(0xA2);
Subsystem(object_id_t setObjectId, object_id_t parent,
uint32_t maxNumberOfSequences, uint32_t maxNumberOfTables);
virtual ~Subsystem();
ReturnValue_t addSequence(ArrayList<ModeListEntry>* sequence, Mode_t id,
Mode_t fallbackSequence, bool inStore = true, bool preInit = true);
ReturnValue_t addTable(ArrayList<ModeListEntry> *table, Mode_t id,
bool inStore = true, bool preInit = true);
void setInitialMode(Mode_t mode);
virtual ReturnValue_t initialize();
virtual ReturnValue_t checkObjectConnections();
virtual MessageQueueId_t getSequenceCommandQueue() const;
/**
*
*
* IMPORTANT: Do not call on non existing sequence! Use existsSequence() first
*
* @param sequence
* @return
*/
ReturnValue_t checkSequence(Mode_t sequence);
/**
*
*
* IMPORTANT: Do not call on non existing sequence! Use existsSequence() first
*
* @param iter
* @return
*/
ReturnValue_t checkSequence(HybridIterator<ModeListEntry> iter, Mode_t fallbackSequence);
protected:
struct EntryPointer {
bool islinked;
union {
ModeListEntry *firstLinkedElement;
ArrayList<ModeListEntry> *array;
};
};
struct SequenceInfo {
Mode_t fallbackSequence;
EntryPointer entries;
};
static const uint8_t MAX_NUMBER_OF_TABLES_OR_SEQUENCES = 60;
static const uint8_t MAX_LENGTH_OF_TABLE_OR_SEQUENCE = 20;
bool isInTransition;
bool childrenChangedHealth;
uint32_t uptimeStartTable;
HybridIterator<ModeListEntry> currentTargetTable;
Mode_t targetMode;
Submode_t targetSubmode;
Mode_t initialMode;
HybridIterator<ModeListEntry> currentSequenceIterator;
FixedMap<Mode_t, EntryPointer> modeTables;
FixedMap<Mode_t, SequenceInfo> modeSequences;
StorageManagerIF *IPCStore;
ModeStoreIF *modeStore;
bool existsModeSequence(Mode_t id);
HybridIterator<ModeListEntry> getSequence(Mode_t id);
bool existsModeTable(Mode_t id);
HybridIterator<ModeListEntry> getTable(Mode_t id);
HybridIterator<ModeListEntry> getCurrentTable();
// void startSequence(Mode_t sequence);
/**
* DO NOT USE ON NON EXISTING SEQUENCE
*
* @param a sequence
* @return the fallback sequence's Id
*/
Mode_t getFallbackSequence(Mode_t sequence);
void replyToCommand(ReturnValue_t status, uint32_t parameter);
ReturnValue_t deleteSequence(Mode_t id);
ReturnValue_t deleteTable(Mode_t id);
virtual void performChildOperation();
virtual ReturnValue_t handleCommandMessage(CommandMessage *message);
bool isFallbackSequence(Mode_t SequenceId);
bool isTableUsed(Mode_t tableId);
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode);
virtual void startTransition(Mode_t mode, Submode_t submode);
void sendSerializablesAsCommandMessage(Command_t command, SerializeIF **elements, uint8_t count);
void transitionFailed(ReturnValue_t failureCode, uint32_t parameter);
void cantKeepMode();
};
#endif /* SUBSYSTEM_H_ */

336
subsystem/SubsystemBase.cpp Normal file
View File

@ -0,0 +1,336 @@
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <framework/subsystem/SubsystemBase.h>
SubsystemBase::~SubsystemBase() {
}
ReturnValue_t SubsystemBase::registerChild(object_id_t objectId) {
ChildInfo info;
HasModesIF *child = objectManager->get<HasModesIF>(objectId);
//This is a rather ugly hack to have the changedHealth info for all children available. (needed for FOGs).
HasHealthIF* healthChild = objectManager->get<HasHealthIF>(objectId);
if (child == NULL) {
if (healthChild == NULL) {
return CHILD_DOESNT_HAVE_MODES;
} else {
info.commandQueue = healthChild->getCommandQueue();
info.mode = MODE_OFF;
}
} else {
info.commandQueue = child->getCommandQueue();
info.mode = -1; //intentional to force an initial command during system startup
}
info.submode = SUBMODE_NONE;
info.healthChanged = false;
std::pair<std::map<object_id_t, ChildInfo>::iterator, bool> returnValue =
childrenMap.insert(
std::pair<object_id_t, ChildInfo>(objectId, info));
if (!(returnValue.second)) {
return COULD_NOT_INSERT_CHILD;
} else {
return RETURN_OK;
}
}
ReturnValue_t SubsystemBase::checkStateAgainstTable(
HybridIterator<ModeListEntry> tableIter) {
std::map<object_id_t, ChildInfo>::iterator childIter;
for (; tableIter.value != NULL; ++tableIter) {
object_id_t object = tableIter.value->getObject();
if ((childIter = childrenMap.find(object)) == childrenMap.end()) {
return RETURN_FAILED;
}
if (childIter->second.mode != tableIter.value->getMode()) {
return RETURN_FAILED;
}
if (childIter->second.submode != tableIter.value->getSubmode()) {
return RETURN_FAILED;
}
}
return RETURN_OK;
}
void SubsystemBase::executeTable(HybridIterator<ModeListEntry> tableIter) {
CommandMessage message;
std::map<object_id_t, ChildInfo>::iterator iter;
commandsOutstanding = 0;
for (; tableIter.value != NULL; ++tableIter) {
object_id_t object = tableIter.value->getObject();
if ((iter = childrenMap.find(object)) == childrenMap.end()) {
//illegal table entry
//TODO: software error
continue;
}
if (healthHelper.healthTable->hasHealth(object)) {
if (healthHelper.healthTable->isFaulty(object)) {
ModeMessage::setModeMessage(&message,
ModeMessage::CMD_MODE_COMMAND, HasModesIF::MODE_OFF,
SUBMODE_NONE);
} else {
if (modeHelper.isForced()) {
ModeMessage::setModeMessage(&message,
ModeMessage::CMD_MODE_COMMAND_FORCED,
tableIter.value->getMode(),
tableIter.value->getSubmode());
} else {
if (healthHelper.healthTable->isCommandable(object)) {
ModeMessage::setModeMessage(&message,
ModeMessage::CMD_MODE_COMMAND,
tableIter.value->getMode(),
tableIter.value->getSubmode());
} else {
continue;
}
}
}
} else {
ModeMessage::setModeMessage(&message, ModeMessage::CMD_MODE_COMMAND,
tableIter.value->getMode(), tableIter.value->getSubmode());
}
//TODO: This may causes trouble with more than two layers, sys commands subsys off, which is already off, but children are on (external).
// So, they stay on. Might only be an issue if mode is forced, so we do
if ((iter->second.mode == ModeMessage::getMode(&message))
&& (iter->second.submode == ModeMessage::getSubmode(&message)) && !modeHelper.isForced()) {
continue; //don't send redundant mode commands (produces event spam)
}
ReturnValue_t result = commandQueue.sendMessage(
iter->second.commandQueue, &message);
if (result != RETURN_OK) {
//TODO OBSW internal error
}
++commandsOutstanding;
}
}
ReturnValue_t SubsystemBase::updateChildMode(MessageQueueId_t queue,
Mode_t mode, Submode_t submode) {
std::map<object_id_t, ChildInfo>::iterator iter;
for (iter = childrenMap.begin(); iter != childrenMap.end(); iter++) {
if (iter->second.commandQueue == queue) {
iter->second.mode = mode;
iter->second.submode = submode;
return RETURN_OK;
}
}
return CHILD_NOT_FOUND;
}
ReturnValue_t SubsystemBase::updateChildChangedHealth(MessageQueueId_t queue,
bool changedHealth) {
for (auto iter = childrenMap.begin(); iter != childrenMap.end(); iter++) {
if (iter->second.commandQueue == queue) {
iter->second.healthChanged = changedHealth;
return RETURN_OK;
}
}
return CHILD_NOT_FOUND;
}
SubsystemBase::SubsystemBase(object_id_t setObjectId, object_id_t parent,
Mode_t initialMode, uint16_t commandQueueDepth) :
SystemObject(setObjectId), mode(initialMode), submode(SUBMODE_NONE), childrenChangedMode(
false), commandsOutstanding(0), commandQueue(commandQueueDepth,
CommandMessage::MAX_MESSAGE_SIZE), healthHelper(this, setObjectId), modeHelper(this), parentId(parent) {
}
MessageQueueId_t SubsystemBase::getCommandQueue() const {
return commandQueue.getId();
}
ReturnValue_t SubsystemBase::initialize() {
MessageQueueId_t parentQueue = 0;
ReturnValue_t result = SystemObject::initialize();
if (result != RETURN_OK) {
return result;
}
if (parentId != 0) {
SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId);
if (parent == NULL) {
return RETURN_FAILED;
}
parentQueue = parent->getCommandQueue();
parent->registerChild(getObjectId());
}
result = healthHelper.initialize(parentQueue);
if (result != RETURN_OK) {
return result;
}
result = modeHelper.initialize(parentQueue);
if (result != RETURN_OK) {
return result;
}
return RETURN_OK;
}
ReturnValue_t SubsystemBase::performOperation() {
childrenChangedMode = false;
checkCommandQueue();
performChildOperation();
return RETURN_OK;
}
ReturnValue_t SubsystemBase::handleModeReply(CommandMessage* message) {
switch (message->getCommand()) {
case ModeMessage::REPLY_MODE_INFO:
updateChildMode(message->getSender(), ModeMessage::getMode(message),
ModeMessage::getSubmode(message));
childrenChangedMode = true;
return RETURN_OK;
case ModeMessage::REPLY_MODE_REPLY:
case ModeMessage::REPLY_WRONG_MODE_REPLY:
updateChildMode(message->getSender(), ModeMessage::getMode(message),
ModeMessage::getSubmode(message));
childrenChangedMode = true;
commandsOutstanding--;
return RETURN_OK;
case ModeMessage::REPLY_CANT_REACH_MODE:
commandsOutstanding--;
{
for (auto iter = childrenMap.begin(); iter != childrenMap.end();
iter++) {
if (iter->second.commandQueue == message->getSender()) {
triggerEvent(MODE_CMD_REJECTED, iter->first, message->getParameter());
}
}
}
return RETURN_OK;
// case ModeMessage::CMD_MODE_COMMAND:
// handleCommandedMode(message);
// return RETURN_OK;
// case ModeMessage::CMD_MODE_ANNOUNCE:
// triggerEvent(MODE_INFO, mode, submode);
// return RETURN_OK;
// case ModeMessage::CMD_MODE_ANNOUNCE_RECURSIVELY:
// triggerEvent(MODE_INFO, mode, submode);
// commandAllChildren(message);
// return RETURN_OK;
default:
return RETURN_FAILED;
}
}
ReturnValue_t SubsystemBase::checkTable(
HybridIterator<ModeListEntry> tableIter) {
for (; tableIter.value != NULL; ++tableIter) {
if (childrenMap.find(tableIter.value->getObject())
== childrenMap.end()) {
return TABLE_CONTAINS_INVALID_OBJECT_ID;
}
}
return RETURN_OK;
}
void SubsystemBase::replyToCommand(CommandMessage* message) {
commandQueue.reply(message);
}
void SubsystemBase::setMode(Mode_t newMode, Submode_t newSubmode) {
modeHelper.modeChanged(newMode, newSubmode);
mode = newMode;
submode = newSubmode;
announceMode(false);
}
void SubsystemBase::setMode(Mode_t newMode) {
setMode(newMode, submode);
}
void SubsystemBase::commandAllChildren(CommandMessage* message) {
std::map<object_id_t, ChildInfo>::iterator iter;
for (iter = childrenMap.begin(); iter != childrenMap.end(); ++iter) {
commandQueue.sendMessage(iter->second.commandQueue, message);
}
}
void SubsystemBase::getMode(Mode_t* mode, Submode_t* submode) {
*mode = this->mode;
*submode = this->submode;
}
void SubsystemBase::setToExternalControl() {
healthHelper.setHealth(EXTERNAL_CONTROL);
}
void SubsystemBase::announceMode(bool recursive) {
triggerEvent(MODE_INFO, mode, submode);
if (recursive) {
CommandMessage command;
ModeMessage::setModeMessage(&command,
ModeMessage::CMD_MODE_ANNOUNCE_RECURSIVELY, 0, 0);
commandAllChildren(&command);
}
}
void SubsystemBase::checkCommandQueue() {
ReturnValue_t result;
CommandMessage message;
for (result = commandQueue.receiveMessage(&message); result == RETURN_OK;
result = commandQueue.receiveMessage(&message)) {
result = healthHelper.handleHealthCommand(&message);
if (result == RETURN_OK) {
continue;
}
result = modeHelper.handleModeCommand(&message);
if (result == RETURN_OK) {
continue;
}
result = handleModeReply(&message);
if (result == RETURN_OK) {
continue;
}
result = handleCommandMessage(&message);
if (result != RETURN_OK) {
CommandMessage reply;
reply.setReplyRejected(CommandMessage::UNKNOW_COMMAND, message.getCommand());
replyToCommand(&reply);
}
}
}
ReturnValue_t SubsystemBase::setHealth(HealthState health) {
switch (health) {
case HEALTHY:
case EXTERNAL_CONTROL:
healthHelper.setHealth(health);
return RETURN_OK;
default:
return INVALID_HEALTH_STATE;
}
}
HasHealthIF::HealthState SubsystemBase::getHealth() {
return healthHelper.getHealth();
}

116
subsystem/SubsystemBase.h Normal file
View File

@ -0,0 +1,116 @@
#ifndef SUBSYSTEMBASE_H_
#define SUBSYSTEMBASE_H_
#include <framework/container/HybridIterator.h>
#include <framework/health/HasHealthIF.h>
#include <framework/health/HealthHelper.h>
#include <framework/ipc/MessageQueue.h>
#include <framework/modes/HasModesIF.h>
#include <framework/objectmanager/SystemObject.h>
#include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/subsystem/modes/HasModeSequenceIF.h>
#include <framework/tasks/ExecutableObjectIF.h>
#include <map>
class SubsystemBase: public SystemObject,
public HasModesIF,
public HasHealthIF,
public HasReturnvaluesIF,
public ExecutableObjectIF {
public:
static const uint8_t INTERFACE_ID = SUBSYSTEM_BASE;
static const ReturnValue_t CHILD_NOT_FOUND = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t CHILD_INFO_UPDATED = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t CHILD_DOESNT_HAVE_MODES = MAKE_RETURN_CODE(0x03);
static const ReturnValue_t COULD_NOT_INSERT_CHILD = MAKE_RETURN_CODE(0x04);
static const ReturnValue_t TABLE_CONTAINS_INVALID_OBJECT_ID =
MAKE_RETURN_CODE(0x05);
SubsystemBase(object_id_t setObjectId, object_id_t parent,
Mode_t initialMode = 0, uint16_t commandQueueDepth = 8);
virtual ~SubsystemBase();
virtual MessageQueueId_t getCommandQueue() const;
ReturnValue_t registerChild(object_id_t objectId);
virtual ReturnValue_t initialize();
virtual ReturnValue_t performOperation();
virtual ReturnValue_t setHealth(HealthState health);
virtual HasHealthIF::HealthState getHealth();
protected:
struct ChildInfo {
MessageQueueId_t commandQueue;
Mode_t mode;
Submode_t submode;
bool healthChanged;
};
Mode_t mode;
Submode_t submode;
bool childrenChangedMode;
/**
* Always check this against <=0, so you are robust against too many replies
*/
int32_t commandsOutstanding;
MessageQueue commandQueue;
HealthHelper healthHelper;
ModeHelper modeHelper;
const object_id_t parentId;
typedef std::map<object_id_t, ChildInfo> ChildrenMap;
ChildrenMap childrenMap;
void checkCommandQueue();
ReturnValue_t checkStateAgainstTable(
HybridIterator<ModeListEntry> tableIter);
void executeTable(HybridIterator<ModeListEntry> tableIter);
ReturnValue_t updateChildMode(MessageQueueId_t queue, Mode_t mode,
Submode_t submode);
ReturnValue_t updateChildChangedHealth(MessageQueueId_t queue, bool changedHealth = true);
virtual ReturnValue_t handleModeReply(CommandMessage *message);
void commandAllChildren(CommandMessage *message);
ReturnValue_t checkTable(HybridIterator<ModeListEntry> tableIter);
void replyToCommand(CommandMessage *message);
void setMode(Mode_t newMode, Submode_t newSubmode);
void setMode(Mode_t newMode);
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0;
virtual void performChildOperation() = 0;
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) = 0;
virtual void startTransition(Mode_t mode, Submode_t submode) = 0;
virtual void getMode(Mode_t *mode, Submode_t *submode);
virtual void setToExternalControl();
virtual void announceMode(bool recursive);
};
#endif /* SUBSYSTEMBASE_H_ */

View File

@ -0,0 +1,20 @@
#ifndef HASMODESEQUENCEIF_H_
#define HASMODESEQUENCEIF_H_
#include <framework/subsystem/modes/ModeDefinitions.h>
#include <framework/subsystem/modes/ModeSequenceMessage.h>
#include <framework/subsystem/modes/ModeStoreIF.h>
class HasModeSequenceIF {
public:
virtual ~HasModeSequenceIF() {
}
virtual MessageQueueId_t getSequenceCommandQueue() const = 0;
};
#endif /* HASMODESEQUENCEIF_H_ */

View File

@ -0,0 +1,134 @@
/*
* ModeTable.h
*
* Created on: 12.07.2013
* Author: tod
*/
#ifndef MODEDEFINITIONS_H_
#define MODEDEFINITIONS_H_
#include <framework/modes/HasModesIF.h>
#include <framework/objectmanager/SystemObjectIF.h>
#include <framework/serialize/SerializeIF.h>
#include <framework/serialize/SerialLinkedListAdapter.h>
class ModeListEntry: public SerializeIF, public LinkedElement<ModeListEntry> {
public:
ModeListEntry() :
LinkedElement<ModeListEntry>(this), value1(0), value2(0), value3(0) {
}
uint32_t value1;
uint32_t value2;
uint8_t value3;
virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size,
const uint32_t max_size, bool bigEndian) const {
ReturnValue_t result;
result = SerializeAdapter<uint32_t>::serialize(&value1, buffer, size,
max_size, bigEndian);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter<uint32_t>::serialize(&value2, buffer, size,
max_size, bigEndian);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter<uint8_t>::serialize(&value3, buffer, size,
max_size, bigEndian);
return result;
}
virtual uint32_t getSerializedSize() const {
return sizeof(value1) + sizeof(value2) + sizeof(value3);
}
virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size,
bool bigEndian) {
ReturnValue_t result;
result = SerializeAdapter<uint32_t>::deSerialize(&value1, buffer, size,
bigEndian);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter<uint32_t>::deSerialize(&value2, buffer, size,
bigEndian);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter<uint8_t>::deSerialize(&value3, buffer, size,
bigEndian);
return result;
}
//for Sequences
Mode_t getTableId() const {
return value1;
}
void setTableId(Mode_t tableId) {
this->value1 = tableId;
}
uint8_t getWaitSeconds() const {
return value2;
}
void setWaitSeconds(uint8_t waitSeconds) {
this->value2 = waitSeconds;
}
bool checkSuccess() const {
return value3 == 1;
}
void setCheckSuccess(bool checkSuccess) {
this->value3 = checkSuccess;
}
//for Tables
object_id_t getObject() const {
return value1;
}
void setObject(object_id_t object) {
this->value1 = object;
}
//TODO no cast!
Mode_t getMode() const {
return value2;
}
void setMode(Mode_t mode) {
this->value2 = mode;
}
Submode_t getSubmode() const {
return value3;
}
void setSubmode(Submode_t submode) {
this->value3 = submode;
}
bool operator==(ModeListEntry other) {
return ((value1 == other.value1) && (value2 == other.value2)
&& (value3 == other.value3));
}
};
#endif //MODEDEFINITIONS_H_

View File

@ -0,0 +1,89 @@
#include <framework/objectmanager/ObjectManagerIF.h>
#include <framework/objectmanager/ObjectManagerIF.h>
#include <framework/objectmanager/ObjectManagerIF.h>
#include <framework/storagemanager/StorageManagerIF.h>
#include <framework/subsystem/modes/ModeSequenceMessage.h>
void ModeSequenceMessage::setModeSequenceMessage(CommandMessage* message,
Command_t command, Mode_t sequence, store_address_t storeAddress) {
message->setCommand(command);
message->setParameter(storeAddress.raw);
message->setParameter2(sequence);
}
//void ModeSequenceMessage::setModeSequenceMessage(CommandMessage* message,
// Command_t command, ModeTableId_t table, store_address_t storeAddress) {
// message->setCommand(command);
// message->setParameter(storeAddress.raw);
// message->setParameter2(table);
//}
void ModeSequenceMessage::setModeSequenceMessage(CommandMessage* message,
Command_t command, Mode_t sequence) {
message->setCommand(command);
message->setParameter2(sequence);
}
//void ModeSequenceMessage::setModeSequenceMessage(CommandMessage* message,
// Command_t command, ModeTableId_t table) {
// message->setCommand(command);
// message->setParameter2(table);
//}
void ModeSequenceMessage::setModeSequenceMessage(CommandMessage* message,
Command_t command, store_address_t storeAddress) {
message->setCommand(command);
message->setParameter(storeAddress.raw);
}
store_address_t ModeSequenceMessage::getStoreAddress(
const CommandMessage* message) {
store_address_t address;
address.raw = message->getParameter();
return address;
}
Mode_t ModeSequenceMessage::getSequenceId(const CommandMessage* message) {
return message->getParameter2();
}
Mode_t ModeSequenceMessage::getTableId(const CommandMessage* message) {
return message->getParameter2();
}
uint32_t ModeSequenceMessage::getNumber(const CommandMessage* message) {
return message->getParameter2();
}
void ModeSequenceMessage::clear(CommandMessage *message) {
switch (message->getCommand()) {
case ADD_SEQUENCE:
case ADD_TABLE:
case SEQUENCE_LIST:
case TABLE_LIST:
case TABLE:
case SEQUENCE:{
StorageManagerIF *ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
if (ipcStore != NULL){
ipcStore->deleteData(ModeSequenceMessage::getStoreAddress(message));
}
}
/*NO BREAK*/
case DELETE_SEQUENCE:
case DELETE_TABLE:
case READ_SEQUENCE:
case READ_TABLE:
case LIST_SEQUENCES:
case LIST_TABLES:
case READ_FREE_SEQUENCE_SLOTS:
case FREE_SEQUENCE_SLOTS:
case READ_FREE_TABLE_SLOTS:
case FREE_TABLE_SLOTS:
default:
message->setCommand(CommandMessage::CMD_NONE);
message->setParameter(0);
message->setParameter2(0);
break;
}
}

View File

@ -0,0 +1,48 @@
#ifndef MODESEQUENCEMESSAGE_H_
#define MODESEQUENCEMESSAGE_H_
#include <framework/ipc/CommandMessage.h>
#include <framework/storagemanager/StorageManagerIF.h>
#include <framework/subsystem/modes/ModeDefinitions.h>
class ModeSequenceMessage {
public:
static const uint8_t MESSAGE_ID = MODE_SEQUENCE_MESSAGE_ID;
static const Command_t ADD_SEQUENCE = MAKE_COMMAND_ID(0x01);
static const Command_t ADD_TABLE = MAKE_COMMAND_ID(0x02);
static const Command_t DELETE_SEQUENCE = MAKE_COMMAND_ID(0x03);
static const Command_t DELETE_TABLE = MAKE_COMMAND_ID(0x04);
static const Command_t READ_SEQUENCE = MAKE_COMMAND_ID(0x05);
static const Command_t READ_TABLE = MAKE_COMMAND_ID(0x06);
static const Command_t LIST_SEQUENCES = MAKE_COMMAND_ID(0x07);
static const Command_t LIST_TABLES = MAKE_COMMAND_ID(0x08);
static const Command_t SEQUENCE_LIST = MAKE_COMMAND_ID(0x09);
static const Command_t TABLE_LIST = MAKE_COMMAND_ID(0x0A);
static const Command_t TABLE = MAKE_COMMAND_ID(0x0B);
static const Command_t SEQUENCE = MAKE_COMMAND_ID(0x0C);
static const Command_t READ_FREE_SEQUENCE_SLOTS = MAKE_COMMAND_ID(0x0D);
static const Command_t FREE_SEQUENCE_SLOTS = MAKE_COMMAND_ID(0x0E);
static const Command_t READ_FREE_TABLE_SLOTS = MAKE_COMMAND_ID(0x0F);
static const Command_t FREE_TABLE_SLOTS = MAKE_COMMAND_ID(0x10);
static void setModeSequenceMessage(CommandMessage *message,
Command_t command, Mode_t sequenceOrTable,
store_address_t storeAddress);
static void setModeSequenceMessage(CommandMessage *message,
Command_t command, Mode_t sequenceOrTable);
static void setModeSequenceMessage(CommandMessage *message,
Command_t command, store_address_t storeAddress);
static store_address_t getStoreAddress(const CommandMessage *message);
static Mode_t getSequenceId(const CommandMessage *message);
static Mode_t getTableId(const CommandMessage *message);
static uint32_t getNumber(const CommandMessage *message);
static void clear(CommandMessage *message);
private:
ModeSequenceMessage();
};
#endif /* MODESEQUENCEMESSAGE_H_ */

View File

@ -0,0 +1,122 @@
#include <framework/subsystem/modes/ModeStore.h>
ModeStore::ModeStore(object_id_t objectId, uint32_t slots) :
SystemObject(objectId), store(slots), emptySlot(store.front()) {
mutex = new MutexId_t;
OSAL::createMutex(objectId + 1, mutex);
clear();
}
ModeStore::~ModeStore() {
delete mutex;
}
uint32_t ModeStore::getFreeSlots() {
OSAL::lockMutex(mutex, OSAL::NO_TIMEOUT);
uint32_t count = 0;
ArrayList<ModeListEntry, uint32_t>::Iterator iter;
for (iter = store.begin(); iter != store.end(); ++iter) {
if (iter->getNext() == emptySlot) {
++count;
}
}
OSAL::unlockMutex(mutex);
return count;
}
ReturnValue_t ModeStore::storeArray(ArrayList<ModeListEntry>* sequence,
ModeListEntry** storedFirstEntry) {
if (sequence->size == 0) {
return CANT_STORE_EMPTY;
}
OSAL::lockMutex(mutex, OSAL::NO_TIMEOUT);
*storedFirstEntry = findEmptySlotNoLock(store.front());
ModeListEntry* pointer =
*storedFirstEntry;
pointer->setNext(pointer);
ArrayList<ModeListEntry>::Iterator iter;
for (iter = sequence->begin(); iter != sequence->end(); ++iter) {
//TODO: I need to check this in detail. What is the idea? Why does it not work?
pointer = pointer->getNext()->value;
if (pointer == NULL) {
deleteListNoLock(*storedFirstEntry);
OSAL::unlockMutex(mutex);
return TOO_MANY_ELEMENTS;
}
pointer->value->value1 = iter->value1;
pointer->value->value2 = iter->value2;
pointer->value->value3 = iter->value3;
pointer->setNext(findEmptySlotNoLock(pointer + 1));
}
pointer->setNext(NULL);
OSAL::unlockMutex(mutex);
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t ModeStore::deleteList(ModeListEntry* sequence) {
ReturnValue_t result = isValidEntry(sequence);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
OSAL::lockMutex(mutex, OSAL::NO_TIMEOUT);
deleteListNoLock(sequence);
OSAL::unlockMutex(mutex);
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t ModeStore::readList(ModeListEntry* sequence,
ArrayList<ModeListEntry>* into) {
ReturnValue_t result = isValidEntry(sequence);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
OSAL::lockMutex(mutex, OSAL::NO_TIMEOUT);
result = into->insert(*sequence->value);
while ((result == HasReturnvaluesIF::RETURN_OK) && (sequence->getNext() != NULL)) {
result = into->insert(*sequence->value);
sequence = sequence->getNext()->value;
}
OSAL::unlockMutex(mutex);
return result;
}
void ModeStore::clear() {
OSAL::lockMutex(mutex, OSAL::NO_TIMEOUT);
store.size = store.maxSize();
ArrayList<ModeListEntry, uint32_t>::Iterator iter;
for (iter = store.begin(); iter != store.end(); ++iter) {
iter->setNext(emptySlot);
}
OSAL::unlockMutex(mutex);
}
ModeListEntry* ModeStore::findEmptySlotNoLock(ModeListEntry* startFrom) {
ArrayList<ModeListEntry, uint32_t>::Iterator iter(
startFrom);
for (; iter != store.end(); ++iter) {
if (iter.value->getNext() == emptySlot) {
OSAL::unlockMutex(mutex);
return iter.value;
}
}
return NULL;
}
void ModeStore::deleteListNoLock(ModeListEntry* sequence) {
ModeListEntry* next = sequence;
while (next != NULL) {
next = sequence->getNext()->value;
sequence->setNext(emptySlot);
sequence = next;
}
}
ReturnValue_t ModeStore::isValidEntry(ModeListEntry* sequence) {
if ((sequence < store.front()) || (sequence > store.back())
|| sequence->getNext() == emptySlot) {
return INVALID_ENTRY;
}
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -0,0 +1,41 @@
#ifndef MODESTORE_H_
#define MODESTORE_H_
#include <framework/container/ArrayList.h>
#include <framework/container/SinglyLinkedList.h>
#include <framework/objectmanager/SystemObject.h>
#include <framework/subsystem/modes/ModeStoreIF.h>
class ModeStore: public ModeStoreIF, public SystemObject {
public:
ModeStore(object_id_t objectId, uint32_t slots);
virtual ~ModeStore();
virtual ReturnValue_t storeArray(ArrayList<ModeListEntry> *sequence,
ModeListEntry **storedFirstEntry);
virtual ReturnValue_t deleteList(
ModeListEntry *sequence);
virtual ReturnValue_t readList(
ModeListEntry *sequence,
ArrayList<ModeListEntry> *into);
virtual uint32_t getFreeSlots();
private:
MutexId_t* mutex;
ArrayList<ModeListEntry, uint32_t> store;
ModeListEntry *emptySlot;
void clear();
ModeListEntry* findEmptySlotNoLock(
ModeListEntry* startFrom);
void deleteListNoLock(
ModeListEntry *sequence);
ReturnValue_t isValidEntry(ModeListEntry *sequence);
};
#endif /* MODESTORE_H_ */

View File

@ -0,0 +1,33 @@
#ifndef MODESTOREIF_H_
#define MODESTOREIF_H_
#include <framework/container/ArrayList.h>
#include <framework/container/SinglyLinkedList.h>
#include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/subsystem/modes/ModeDefinitions.h>
class ModeStoreIF {
public:
static const uint8_t INTERFACE_ID = MODE_STORE_IF;
static const ReturnValue_t INVALID_ENTRY = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t TOO_MANY_ELEMENTS = MAKE_RETURN_CODE(0x03);
static const ReturnValue_t CANT_STORE_EMPTY = MAKE_RETURN_CODE(0x04);
virtual ~ModeStoreIF() {
}
virtual ReturnValue_t storeArray(ArrayList<ModeListEntry> *sequence,
ModeListEntry **storedFirstEntry) = 0;
virtual ReturnValue_t deleteList(
ModeListEntry *sequence) = 0;
virtual ReturnValue_t readList(
ModeListEntry *sequence,
ArrayList<ModeListEntry> *into) = 0;
virtual uint32_t getFreeSlots() = 0;
};
#endif /* MODESTOREIF_H_ */