Merge branch 'ksat_master' of KSat/fsfw into master

This commit is contained in:
Robin Müller 2020-04-08 19:35:26 +02:00 committed by Gitea
commit 35eff6dfba
150 changed files with 4097 additions and 1751 deletions

View File

@ -49,7 +49,7 @@ void ActionHelper::setQueueToUse(MessageQueueIF* queue) {
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
store_address_t dataAddress) { store_address_t dataAddress) {
const uint8_t* dataPtr = NULL; const uint8_t* dataPtr = NULL;
uint32_t size = 0; size_t size = 0;
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size); ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
CommandMessage reply; CommandMessage reply;
@ -67,16 +67,17 @@ void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t act
} }
} }
ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, ActionId_t replyId, SerializeIF* data, bool hideSender) { ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
ActionId_t replyId, SerializeIF* data, bool hideSender) {
CommandMessage reply; CommandMessage reply;
store_address_t storeAddress; store_address_t storeAddress;
uint8_t *dataPtr; uint8_t *dataPtr;
uint32_t maxSize = data->getSerializedSize(); size_t maxSize = data->getSerializedSize();
if (maxSize == 0) { if (maxSize == 0) {
//No error, there's simply nothing to report. //No error, there's simply nothing to report.
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
uint32_t size = 0; size_t size = 0;
ReturnValue_t result = ipcStore->getFreeElement(&storeAddress, maxSize, ReturnValue_t result = ipcStore->getFreeElement(&storeAddress, maxSize,
&dataPtr); &dataPtr);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {

View File

@ -20,13 +20,13 @@ ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo,
} }
store_address_t storeId; store_address_t storeId;
uint8_t* storePointer; uint8_t* storePointer;
uint32_t maxSize = data->getSerializedSize(); size_t maxSize = data->getSerializedSize();
ReturnValue_t result = ipcStore->getFreeElement(&storeId, maxSize, ReturnValue_t result = ipcStore->getFreeElement(&storeId, maxSize,
&storePointer); &storePointer);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
uint32_t size = 0; size_t size = 0;
result = data->serialize(&storePointer, &size, maxSize, true); result = data->serialize(&storePointer, &size, maxSize, true);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
@ -113,7 +113,7 @@ uint8_t CommandActionHelper::getCommandCount() const {
void CommandActionHelper::extractDataForOwner(ActionId_t actionId, store_address_t storeId) { void CommandActionHelper::extractDataForOwner(ActionId_t actionId, store_address_t storeId) {
const uint8_t * data = NULL; const uint8_t * data = NULL;
uint32_t size = 0; size_t size = 0;
ReturnValue_t result = ipcStore->getData(storeId, &data, &size); ReturnValue_t result = ipcStore->getData(storeId, &data, &size);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return; return;

View File

@ -7,8 +7,10 @@
#include <framework/returnvalues/HasReturnvaluesIF.h> #include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/ipc/MessageQueueIF.h> #include <framework/ipc/MessageQueueIF.h>
/** /**
* \brief Interface for component which uses actions * @brief
* Interface for component which uses actions
* *
* @details
* This interface is used to execute actions in the component. Actions, in the sense of this interface, are activities with a well-defined beginning and * This interface is used to execute actions in the component. Actions, in the sense of this interface, are activities with a well-defined beginning and
* end in time. They may adjust sub-states of components, but are not supposed to change * end in time. They may adjust sub-states of components, but are not supposed to change
* the main mode of operation, which is handled with the HasModesIF described below. * the main mode of operation, which is handled with the HasModesIF described below.
@ -23,6 +25,8 @@
* parameters and immediately start execution of the action. It is, however, not required to * parameters and immediately start execution of the action. It is, however, not required to
* immediately finish execution. Instead, this may be deferred to a later point in time, at * immediately finish execution. Instead, this may be deferred to a later point in time, at
* which the component needs to inform the caller about finished or failed execution. * which the component needs to inform the caller about finished or failed execution.
*
* \ingroup interfaces
*/ */
class HasActionsIF { class HasActionsIF {
public: public:
@ -40,10 +44,11 @@ public:
/** /**
* Execute or initialize the execution of a certain function. * Execute or initialize the execution of a certain function.
* Returning #EXECUTION_FINISHED or a failure code, nothing else needs to be done. * Returning #EXECUTION_FINISHED or a failure code, nothing else needs to be done.
* When needing more steps, return RETURN_OK and issue steps and completion manually. One "step failed" or completion report must * When needing more steps, return RETURN_OK and issue steps and completion manually.
* be issued! * One "step failed" or completion report must be issued!
*/ */
virtual ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t* data, uint32_t size) = 0; virtual ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) = 0;
}; };

View File

@ -44,7 +44,7 @@ void SimpleActionHelper::prepareExecution(MessageQueueId_t commandedBy,
queueToUse->sendMessage(commandedBy, &reply); queueToUse->sendMessage(commandedBy, &reply);
} }
const uint8_t* dataPtr = NULL; const uint8_t* dataPtr = NULL;
uint32_t size = 0; size_t size = 0;
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size); ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
ActionMessage::setStepReply(&reply, actionId, 0, result); ActionMessage::setStepReply(&reply, actionId, 0, result);

View File

@ -6,10 +6,9 @@
#include <framework/serialize/SerializeIF.h> #include <framework/serialize/SerializeIF.h>
/** /**
* A List that stores its values in an array. * @brief A List that stores its values in an array.
* * @details The backend is an array that can be allocated
* The backend is an array that can be allocated by the class itself or supplied via ctor. * by the class itself or supplied via ctor.
*
* *
* @ingroup container * @ingroup container
*/ */
@ -223,6 +222,7 @@ public:
count_t remaining() { count_t remaining() {
return (maxSize_ - size); return (maxSize_ - size);
} }
private: private:
/** /**
* This is the copy constructor * This is the copy constructor
@ -233,9 +233,9 @@ private:
* @param other * @param other
*/ */
ArrayList(const ArrayList& other) : ArrayList(const ArrayList& other) :
size(other.size), entries(other.entries), maxSize_(other.maxSize_), allocated( size(other.size), entries(other.entries), maxSize_(other.maxSize_),
false) { allocated(false) {}
}
protected: protected:
/** /**
* pointer to the array in which the entries are stored * pointer to the array in which the entries are stored
@ -251,5 +251,24 @@ protected:
*/ */
bool allocated; bool allocated;
/**
* Swap the endianness of the Array list (not the length field !)
* Useful if the case the buffer type is larger than uint8_t
* @param list
*/
void swapArrayListEndianness() {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
count_t i = 0;
// uint8_t buffer does not require swapping of entries.
if(sizeof(T) == 1) {
return;
}
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < size)) {
T newEntry = EndianSwapper::swap(entries[i]);
entries[i] = newEntry;
++i;
}
}
}; };
#endif /* ARRAYLIST_H_ */ #endif /* ARRAYLIST_H_ */

View File

@ -3,6 +3,11 @@
#include <framework/returnvalues/HasReturnvaluesIF.h> #include <framework/returnvalues/HasReturnvaluesIF.h>
/**
* @brief Simple First-In-First-Out data structure
* @tparam T Entry Type
* @tparam capacity Maximum capacity
*/
template<typename T, uint8_t capacity> template<typename T, uint8_t capacity>
class FIFO { class FIFO {
private: private:
@ -21,7 +26,7 @@ public:
readIndex(0), writeIndex(0), currentSize(0) { readIndex(0), writeIndex(0), currentSize(0) {
} }
bool emtpy() { bool empty() {
return (currentSize == 0); return (currentSize == 0);
} }
@ -45,7 +50,7 @@ public:
} }
ReturnValue_t retrieve(T *value) { ReturnValue_t retrieve(T *value) {
if (emtpy()) { if (empty()) {
return EMPTY; return EMPTY;
} else { } else {
*value = data[readIndex]; *value = data[readIndex];

View File

@ -2,8 +2,10 @@
#define FIXEDARRAYLIST_H_ #define FIXEDARRAYLIST_H_
#include <framework/container/ArrayList.h> #include <framework/container/ArrayList.h>
/** /**
* \ingroup container * @brief Array List with a fixed maximum size
* @ingroup container
*/ */
template<typename T, uint32_t MAX_SIZE, typename count_t = uint8_t> template<typename T, uint32_t MAX_SIZE, typename count_t = uint8_t>
class FixedArrayList: public ArrayList<T, count_t> { class FixedArrayList: public ArrayList<T, count_t> {
@ -14,6 +16,18 @@ public:
ArrayList<T, count_t>(data, MAX_SIZE) { ArrayList<T, count_t>(data, MAX_SIZE) {
} }
//We could create a constructor to initialize the fixed array list with data and the known size field
//so it can be used for serialization too (with SerialFixedArrrayListAdapter)
//is this feasible?
FixedArrayList(T * data_, count_t count, bool swapArrayListEndianess = false):
ArrayList<T, count_t>(data, MAX_SIZE) {
memcpy(this->data, data_, count * sizeof(T));
this->size = count;
if(swapArrayListEndianess) {
ArrayList<T, count_t>::swapArrayListEndianness();
}
}
FixedArrayList(const FixedArrayList& other) : FixedArrayList(const FixedArrayList& other) :
ArrayList<T, count_t>(data, MAX_SIZE) { ArrayList<T, count_t>(data, MAX_SIZE) {
memcpy(this->data, other.data, sizeof(this->data)); memcpy(this->data, other.data, sizeof(this->data));

View File

@ -6,7 +6,11 @@
#include <utility> #include <utility>
/** /**
* \ingroup container * @brief Map implementation for maps with a pre-defined size.
* @details Can be initialized with desired maximum size.
* Iterator is used to access <key,value> pair and
* iterate through map entries. Complexity O(n).
* @ingroup container
*/ */
template<typename key_t, typename T> template<typename key_t, typename T>
class FixedMap: public SerializeIF { class FixedMap: public SerializeIF {
@ -52,12 +56,24 @@ public:
return ArrayList<std::pair<key_t, T>, uint32_t>::Iterator::value->second; return ArrayList<std::pair<key_t, T>, uint32_t>::Iterator::value->second;
} }
// -> operator overloaded, can be used to access value
T *operator->() { T *operator->() {
return &ArrayList<std::pair<key_t, T>, uint32_t>::Iterator::value->second; return &ArrayList<std::pair<key_t, T>, uint32_t>::Iterator::value->second;
} }
// Can be used to access the key of the iterator
key_t first() {
return ArrayList<std::pair<key_t, T>, uint32_t>::Iterator::value->first;
}
// Alternative to access value, similar to std::map implementation
T second() {
return ArrayList<std::pair<key_t, T>, uint32_t>::Iterator::value->second;
}
}; };
Iterator begin() const { Iterator begin() const {
return Iterator(&theMap[0]); return Iterator(&theMap[0]);
} }
@ -72,10 +88,10 @@ public:
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = NULL) { ReturnValue_t insert(key_t key, T value, Iterator *storedValue = NULL) {
if (exists(key) == HasReturnvaluesIF::RETURN_OK) { if (exists(key) == HasReturnvaluesIF::RETURN_OK) {
return KEY_ALREADY_EXISTS; return FixedMap::KEY_ALREADY_EXISTS;
} }
if (_size == theMap.maxSize()) { if (_size == theMap.maxSize()) {
return MAP_FULL; return FixedMap::MAP_FULL;
} }
theMap[_size].first = key; theMap[_size].first = key;
theMap[_size].second = value; theMap[_size].second = value;
@ -87,7 +103,7 @@ public:
} }
ReturnValue_t insert(std::pair<key_t, T> pair) { ReturnValue_t insert(std::pair<key_t, T> pair) {
return insert(pair.fist, pair.second); return insert(pair.first, pair.second);
} }
ReturnValue_t exists(key_t key) const { ReturnValue_t exists(key_t key) const {
@ -148,8 +164,17 @@ public:
return theMap.maxSize(); return theMap.maxSize();
} }
virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, bool full() {
const uint32_t max_size, bool bigEndian) const { if(_size == theMap.maxSize()) {
return true;
}
else {
return false;
}
}
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
const size_t max_size, bool bigEndian) const {
ReturnValue_t result = SerializeAdapter<uint32_t>::serialize(&this->_size, ReturnValue_t result = SerializeAdapter<uint32_t>::serialize(&this->_size,
buffer, size, max_size, bigEndian); buffer, size, max_size, bigEndian);
uint32_t i = 0; uint32_t i = 0;
@ -163,7 +188,7 @@ public:
return result; return result;
} }
virtual uint32_t getSerializedSize() const { virtual size_t getSerializedSize() const {
uint32_t printSize = sizeof(_size); uint32_t printSize = sizeof(_size);
uint32_t i = 0; uint32_t i = 0;
@ -176,7 +201,7 @@ public:
return printSize; return printSize;
} }
virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size,
bool bigEndian) { bool bigEndian) {
ReturnValue_t result = SerializeAdapter<uint32_t>::deSerialize(&this->_size, ReturnValue_t result = SerializeAdapter<uint32_t>::deSerialize(&this->_size,
buffer, size, bigEndian); buffer, size, bigEndian);

View File

@ -10,7 +10,7 @@
template<typename key_t, typename T, typename KEY_COMPARE = std::less<key_t>> template<typename key_t, typename T, typename KEY_COMPARE = std::less<key_t>>
class FixedOrderedMultimap { class FixedOrderedMultimap {
public: public:
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP; static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MULTIMAP;
static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01); static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02); static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03); static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);

View File

@ -67,7 +67,7 @@ public:
} }
bool operator==(HybridIterator other) { bool operator==(HybridIterator other) {
return value == other->value; return value == other.value;
} }
bool operator!=(HybridIterator other) { bool operator!=(HybridIterator other) {

View File

@ -8,20 +8,27 @@
#include <framework/globalfunctions/crc_ccitt.h> #include <framework/globalfunctions/crc_ccitt.h>
#include <cmath> #include <cmath>
/**
* Index is the Type used for the list of indices.
*
* @tparam T Type which destribes the index. Needs to be a child of SerializeIF
* to be able to make it persistent
*/
template<typename T> template<typename T>
class Index: public SerializeIF{ class Index: public SerializeIF{
/** /**
* Index is the Type used for the list of indices. The template parameter is the type which describes the index, it needs to be a child of SerializeIF to be able to make it persistent *
*/ */
static_assert(std::is_base_of<SerializeIF,T>::value,"Wrong Type for Index, Type must implement SerializeIF"); static_assert(std::is_base_of<SerializeIF,T>::value,
"Wrong Type for Index, Type must implement SerializeIF");
public: public:
Index():blockStartAddress(0),size(0),storedPackets(0){} Index():blockStartAddress(0),size(0),storedPackets(0){}
Index(uint32_t startAddress):blockStartAddress(startAddress),size(0),storedPackets(0){ Index(uint32_t startAddress):blockStartAddress(startAddress),
size(0),storedPackets(0) {
} }
void setBlockStartAddress(uint32_t newAddress){ void setBlockStartAddress(uint32_t newAddress) {
this->blockStartAddress = newAddress; this->blockStartAddress = newAddress;
} }
@ -33,7 +40,7 @@ public:
return &indexType; return &indexType;
} }
T* modifyIndexType(){ T* modifyIndexType() {
return &indexType; return &indexType;
} }
/** /**
@ -128,26 +135,35 @@ private:
}; };
/**
* @brief Indexed Ring Memory Array is a class for a ring memory with indices.
* @details
* It assumes that the newest data comes in last
* It uses the currentWriteBlock as pointer to the current writing position
* The currentReadBlock must be set manually
* @tparam T
*/
template<typename T> template<typename T>
class IndexedRingMemoryArray: public SerializeIF, public ArrayList<Index<T>, uint32_t>{ class IndexedRingMemoryArray: public SerializeIF, public ArrayList<Index<T>, uint32_t>{
/** /**
* Indexed Ring Memory Array is a class for a ring memory with indices. It assumes that the newest data comes in last *
* It uses the currentWriteBlock as pointer to the current writing position
* The currentReadBlock must be set manually
*/ */
public: public:
IndexedRingMemoryArray(uint32_t startAddress, uint32_t size, uint32_t bytesPerBlock, SerializeIF* additionalInfo, IndexedRingMemoryArray(uint32_t startAddress, uint32_t size, uint32_t bytesPerBlock,
bool overwriteOld) :ArrayList<Index<T>,uint32_t>(NULL,(uint32_t)10,(uint32_t)0),totalSize(size),indexAddress(startAddress),currentReadSize(0),currentReadBlockSizeCached(0),lastBlockToReadSize(0), additionalInfo(additionalInfo),overwriteOld(overwriteOld){ SerializeIF* additionalInfo, bool overwriteOld):
ArrayList<Index<T>,uint32_t>(NULL,(uint32_t)10,(uint32_t)0),totalSize(size),
indexAddress(startAddress),currentReadSize(0),currentReadBlockSizeCached(0),
lastBlockToReadSize(0), additionalInfo(additionalInfo),overwriteOld(overwriteOld)
{
//Calculate the maximum number of indices needed for this blocksize //Calculate the maximum number of indices needed for this blocksize
uint32_t maxNrOfIndices = floor(static_cast<double>(size)/static_cast<double>(bytesPerBlock)); uint32_t maxNrOfIndices = floor(static_cast<double>(size)/static_cast<double>(bytesPerBlock));
//Calculate the Size needeed for the index itself //Calculate the Size needeed for the index itself
uint32_t serializedSize = 0; size_t serializedSize = 0;
if(additionalInfo!=NULL){ if(additionalInfo!=NULL) {
serializedSize += additionalInfo->getSerializedSize(); serializedSize += additionalInfo->getSerializedSize();
} }
//Size of current iterator type //Size of current iterator type
Index<T> tempIndex; Index<T> tempIndex;
serializedSize += tempIndex.getSerializedSize(); serializedSize += tempIndex.getSerializedSize();
@ -162,6 +178,7 @@ public:
error << "IndexedRingMemory: Store is too small for index" << std::endl; error << "IndexedRingMemory: Store is too small for index" << std::endl;
} }
uint32_t useableSize = totalSize - serializedSize; uint32_t useableSize = totalSize - serializedSize;
//Update the totalSize for calculations //Update the totalSize for calculations
totalSize = useableSize; totalSize = useableSize;
@ -178,12 +195,10 @@ public:
this->allocated = true; this->allocated = true;
//Check trueNumberOfBlocks //Check trueNumberOfBlocks
if(trueNumberOfBlocks<1){ if(trueNumberOfBlocks<1) {
error << "IndexedRingMemory: Invalid Number of Blocks: " << trueNumberOfBlocks; error << "IndexedRingMemory: Invalid Number of Blocks: " << trueNumberOfBlocks;
} }
//Fill address into index //Fill address into index
uint32_t address = trueStartAddress; uint32_t address = trueStartAddress;
for (typename IndexedRingMemoryArray<T>::Iterator it = this->begin();it!=this->end();++it) { for (typename IndexedRingMemoryArray<T>::Iterator it = this->begin();it!=this->end();++it) {
@ -193,7 +208,6 @@ public:
address += bytesPerBlock; address += bytesPerBlock;
} }
//Initialize iterators //Initialize iterators
currentWriteBlock = this->begin(); currentWriteBlock = this->begin();
currentReadBlock = this->begin(); currentReadBlock = this->begin();
@ -232,10 +246,10 @@ public:
(*typeResetFnc)(it->modifyIndexType()); (*typeResetFnc)(it->modifyIndexType());
} }
/* /**
* Reading * Reading
* @param it
*/ */
void setCurrentReadBlock(typename IndexedRingMemoryArray<T>::Iterator it){ void setCurrentReadBlock(typename IndexedRingMemoryArray<T>::Iterator it){
currentReadBlock = it; currentReadBlock = it;
currentReadBlockSizeCached = it->getSize(); currentReadBlockSizeCached = it->getSize();
@ -248,6 +262,7 @@ public:
lastBlockToRead = currentWriteBlock; lastBlockToRead = currentWriteBlock;
lastBlockToReadSize = currentWriteBlock->getSize(); lastBlockToReadSize = currentWriteBlock->getSize();
} }
/** /**
* Sets the last block to read to this iterator. * Sets the last block to read to this iterator.
* Can be used to dump until block x * Can be used to dump until block x
@ -292,33 +307,39 @@ public:
uint32_t getCurrentReadAddress() const { uint32_t getCurrentReadAddress() const {
return getAddressOfCurrentReadBlock() + currentReadSize; return getAddressOfCurrentReadBlock() + currentReadSize;
} }
/** /**
* Adds readSize to the current size and checks if the read has no more data left and advances the read block * Adds readSize to the current size and checks if the read has no more data
* left and advances the read block.
* @param readSize The size that was read * @param readSize The size that was read
* @return Returns true if the read can go on * @return Returns true if the read can go on
*/ */
bool addReadSize(uint32_t readSize) { bool addReadSize(uint32_t readSize) {
if(currentReadBlock == lastBlockToRead){ if(currentReadBlock == lastBlockToRead) {
//The current read block is the last to read //The current read block is the last to read
if((currentReadSize+readSize)<lastBlockToReadSize){ if((currentReadSize+readSize)<lastBlockToReadSize) {
//the block has more data -> return true //the block has more data -> return true
currentReadSize += readSize; currentReadSize += readSize;
return true; return true;
}else{ }
else {
//Reached end of read -> return false //Reached end of read -> return false
currentReadSize = lastBlockToReadSize; currentReadSize = lastBlockToReadSize;
return false; return false;
} }
}else{ }
else {
//We are not in the last Block //We are not in the last Block
if((currentReadSize + readSize)<currentReadBlockSizeCached){ if((currentReadSize + readSize)<currentReadBlockSizeCached) {
//The current Block has more data //The current Block has more data
currentReadSize += readSize; currentReadSize += readSize;
return true; return true;
}else{ }
// TODO: Maybe some logic blocks should be extracted
else {
//The current block is written completely //The current block is written completely
readNext(); readNext();
if(currentReadBlockSizeCached==0){ if(currentReadBlockSizeCached==0) {
//Next block is empty //Next block is empty
typename IndexedRingMemoryArray<T>::Iterator it(currentReadBlock); typename IndexedRingMemoryArray<T>::Iterator it(currentReadBlock);
//Search if any block between this and the last block is not empty //Search if any block between this and the last block is not empty
@ -421,13 +442,13 @@ public:
T* modifyCurrentWriteBlockIndexType(){ T* modifyCurrentWriteBlockIndexType(){
return currentWriteBlock->modifyIndexType(); return currentWriteBlock->modifyIndexType();
} }
void updatePreviousWriteSize(uint32_t size, uint32_t storedPackets){ void updatePreviousWriteSize(uint32_t size, uint32_t storedPackets){
typename IndexedRingMemoryArray<T>::Iterator it = getPreviousBlock(currentWriteBlock); typename IndexedRingMemoryArray<T>::Iterator it = getPreviousBlock(currentWriteBlock);
it->addSize(size); it->addSize(size);
it->addStoredPackets(storedPackets); it->addStoredPackets(storedPackets);
} }
/** /**
* Checks if the block has enough space for sizeToWrite * Checks if the block has enough space for sizeToWrite
* @param sizeToWrite The data to be written in the Block * @param sizeToWrite The data to be written in the Block
@ -436,7 +457,10 @@ public:
bool hasCurrentWriteBlockEnoughSpace(uint32_t sizeToWrite){ bool hasCurrentWriteBlockEnoughSpace(uint32_t sizeToWrite){
typename IndexedRingMemoryArray<T>::Iterator next = getNextWrite(); typename IndexedRingMemoryArray<T>::Iterator next = getNextWrite();
uint32_t addressOfNextBlock = next->getBlockStartAddress(); uint32_t addressOfNextBlock = next->getBlockStartAddress();
uint32_t availableSize = ((addressOfNextBlock+totalSize) - (getAddressOfCurrentWriteBlock()+getSizeOfCurrentWriteBlock()))%totalSize; uint32_t availableSize =
( ( addressOfNextBlock + totalSize ) -
(getAddressOfCurrentWriteBlock() + getSizeOfCurrentWriteBlock()))
% totalSize;
return (sizeToWrite < availableSize); return (sizeToWrite < availableSize);
} }
@ -524,9 +548,9 @@ public:
* Get the serialized Size of the index * Get the serialized Size of the index
* @return The serialized size of the index * @return The serialized size of the index
*/ */
uint32_t getSerializedSize() const { size_t getSerializedSize() const {
uint32_t size = 0; size_t size = 0;
if(additionalInfo!=NULL){ if(additionalInfo!=NULL){
size += additionalInfo->getSerializedSize(); size += additionalInfo->getSerializedSize();
} }
@ -694,7 +718,4 @@ private:
}; };
#endif /* FRAMEWORK_CONTAINER_INDEXEDRINGMEMORY_H_ */ #endif /* FRAMEWORK_CONTAINER_INDEXEDRINGMEMORY_H_ */

View File

@ -4,12 +4,41 @@
#include <framework/container/RingBufferBase.h> #include <framework/container/RingBufferBase.h>
#include <stddef.h> #include <stddef.h>
/**
* @brief Circular buffer implementation, useful for buffering into data streams.
* @details Note that the deleteData() has to be called to increment the read pointer
* @ingroup containers
*/
class SimpleRingBuffer: public RingBufferBase<> { class SimpleRingBuffer: public RingBufferBase<> {
public: public:
SimpleRingBuffer(uint32_t size, bool overwriteOld); SimpleRingBuffer(uint32_t size, bool overwriteOld);
virtual ~SimpleRingBuffer(); virtual ~SimpleRingBuffer();
/**
* Write to circular buffer and increment write pointer by amount
* @param data
* @param amount
* @return
*/
ReturnValue_t writeData(const uint8_t* data, uint32_t amount); ReturnValue_t writeData(const uint8_t* data, uint32_t amount);
/**
* Read from circular buffer at read pointer
* @param data
* @param amount
* @param readRemaining
* @param trueAmount
* @return
*/
ReturnValue_t readData(uint8_t* data, uint32_t amount, bool readRemaining = false, uint32_t* trueAmount = NULL); ReturnValue_t readData(uint8_t* data, uint32_t amount, bool readRemaining = false, uint32_t* trueAmount = NULL);
/**
* Delete data starting by incrementing read pointer
* @param amount
* @param deleteRemaining
* @param trueAmount
* @return
*/
ReturnValue_t deleteData(uint32_t amount, bool deleteRemaining = false, uint32_t* trueAmount = NULL); ReturnValue_t deleteData(uint32_t amount, bool deleteRemaining = false, uint32_t* trueAmount = NULL);
private: private:
// static const uint8_t TEMP_READ_PTR = 1; // static const uint8_t TEMP_READ_PTR = 1;

View File

@ -4,7 +4,9 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
/** /**
* \ingroup container * @brief Linked list data structure,
* each entry has a pointer to the next entry (singly)
* @ingroup container
*/ */
template<typename T> template<typename T>
class LinkedElement { class LinkedElement {
@ -58,6 +60,11 @@ public:
virtual void setNext(LinkedElement* next) { virtual void setNext(LinkedElement* next) {
this->next = next; this->next = next;
} }
void setEnd() {
this->next = NULL;
}
LinkedElement* begin() { LinkedElement* begin() {
return this; return this;
} }

View File

@ -4,11 +4,9 @@
/** /**
* @defgroup container Container * @defgroup container Container
* *
* General Purpose Container to store various elements. * General Purpose Containers to store various elements.
* * As opposed to the STL library implementation, these implementations
* Also contains Adapter classes to print elements to a * don't allocate memory dynamically.
* bytestream and to read them from a bytestream, as well
* as an Adapter to swap the endianness.
*/ */

View File

@ -79,6 +79,7 @@ void DataPool::print() {
} }
} }
template PoolEntry<bool>* DataPool::getData<bool>( uint32_t data_pool_id, uint8_t size );
template PoolEntry<uint8_t>* DataPool::getData<uint8_t>( uint32_t data_pool_id, uint8_t size ); template PoolEntry<uint8_t>* DataPool::getData<uint8_t>( uint32_t data_pool_id, uint8_t size );
template PoolEntry<uint16_t>* DataPool::getData<uint16_t>( uint32_t data_pool_id, uint8_t size ); template PoolEntry<uint16_t>* DataPool::getData<uint16_t>( uint32_t data_pool_id, uint8_t size );
template PoolEntry<uint32_t>* DataPool::getData<uint32_t>( uint32_t data_pool_id, uint8_t size ); template PoolEntry<uint32_t>* DataPool::getData<uint32_t>( uint32_t data_pool_id, uint8_t size );

View File

@ -29,7 +29,7 @@
* \brief This class represents the OBSW global data-pool. * \brief This class represents the OBSW global data-pool.
* *
* \details All variables are registered and space is allocated in an initialization * \details All variables are registered and space is allocated in an initialization
* function, which is passed do the constructor. * function, which is passed to the constructor.
* Space for the variables is allocated on the heap (with a new call). * Space for the variables is allocated on the heap (with a new call).
* The data is found by a data pool id, which uniquely represents a variable. * The data is found by a data pool id, which uniquely represents a variable.
* Data pool variables should be used with a blackboard logic in mind, * Data pool variables should be used with a blackboard logic in mind,

View File

@ -26,7 +26,7 @@ MessageQueueId_t DataPoolAdmin::getCommandQueue() const {
} }
ReturnValue_t DataPoolAdmin::executeAction(ActionId_t actionId, ReturnValue_t DataPoolAdmin::executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t* data, uint32_t size) { MessageQueueId_t commandedBy, const uint8_t* data, size_t size) {
if (actionId != SET_VALIDITY) { if (actionId != SET_VALIDITY) {
return INVALID_ACTION_ID; return INVALID_ACTION_ID;
} }
@ -215,7 +215,7 @@ ReturnValue_t DataPoolAdmin::handleParameterCommand(CommandMessage* command) {
ParameterMessage::getParameterId(command)); ParameterMessage::getParameterId(command));
const uint8_t *storedStream; const uint8_t *storedStream;
uint32_t storedStreamSize; size_t storedStreamSize;
result = storage->getData(ParameterMessage::getStoreId(command), result = storage->getData(ParameterMessage::getStoreId(command),
&storedStream, &storedStreamSize); &storedStream, &storedStreamSize);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
@ -272,7 +272,7 @@ ReturnValue_t DataPoolAdmin::sendParameter(MessageQueueId_t to, uint32_t id,
return result; return result;
} }
uint32_t storeElementSize = 0; size_t storeElementSize = 0;
result = wrapper->serialize(&storeElement, &storeElementSize, result = wrapper->serialize(&storeElement, &storeElementSize,
serializedSize, true); serializedSize, true);

View File

@ -33,8 +33,8 @@ public:
ReturnValue_t handleMemoryDump(uint32_t address, uint32_t size, ReturnValue_t handleMemoryDump(uint32_t address, uint32_t size,
uint8_t** dataPointer, uint8_t* copyHere); uint8_t** dataPointer, uint8_t* copyHere);
ReturnValue_t executeAction(ActionId_t actionId, virtual ReturnValue_t executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t* data, uint32_t size); MessageQueueId_t commandedBy, const uint8_t* data, size_t size);
//not implemented as ParameterHelper is no used //not implemented as ParameterHelper is no used
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,

View File

@ -36,7 +36,7 @@ ReturnValue_t DataPoolParameterWrapper::set(uint8_t domainId,
} }
ReturnValue_t DataPoolParameterWrapper::serialize(uint8_t** buffer, ReturnValue_t DataPoolParameterWrapper::serialize(uint8_t** buffer,
uint32_t* size, const uint32_t max_size, bool bigEndian) const { size_t* size, const size_t max_size, bool bigEndian) const {
ReturnValue_t result; ReturnValue_t result;
result = SerializeAdapter<Type>::serialize(&type, buffer, size, max_size, result = SerializeAdapter<Type>::serialize(&type, buffer, size, max_size,
@ -69,7 +69,7 @@ ReturnValue_t DataPoolParameterWrapper::serialize(uint8_t** buffer,
} }
//same as ParameterWrapper //same as ParameterWrapper
uint32_t DataPoolParameterWrapper::getSerializedSize() const { size_t DataPoolParameterWrapper::getSerializedSize() const {
uint32_t serializedSize = 0; uint32_t serializedSize = 0;
serializedSize += type.getSerializedSize(); serializedSize += type.getSerializedSize();
serializedSize += sizeof(rows); serializedSize += sizeof(rows);
@ -80,7 +80,7 @@ uint32_t DataPoolParameterWrapper::getSerializedSize() const {
} }
ReturnValue_t DataPoolParameterWrapper::deSerialize(const uint8_t** buffer, ReturnValue_t DataPoolParameterWrapper::deSerialize(const uint8_t** buffer,
int32_t* size, bool bigEndian) { ssize_t* size, bool bigEndian) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }

View File

@ -11,12 +11,12 @@ public:
ReturnValue_t set(uint8_t domainId, uint16_t parameterId); ReturnValue_t set(uint8_t domainId, uint16_t parameterId);
virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
const uint32_t max_size, bool bigEndian) const; const size_t max_size, bool bigEndian) const;
virtual uint32_t getSerializedSize() const; virtual size_t getSerializedSize() const;
virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size,
bool bigEndian); bool bigEndian);
ReturnValue_t copyFrom(const ParameterWrapper *from, ReturnValue_t copyFrom(const ParameterWrapper *from,

View File

@ -106,8 +106,8 @@ uint8_t DataSet::lockDataPool() {
return ::dataPool.lockDataPool(); return ::dataPool.lockDataPool();
} }
ReturnValue_t DataSet::serialize(uint8_t** buffer, uint32_t* size, ReturnValue_t DataSet::serialize(uint8_t** buffer, size_t* size,
const uint32_t max_size, bool bigEndian) const { const size_t max_size, bool bigEndian) const {
ReturnValue_t result = RETURN_FAILED; ReturnValue_t result = RETURN_FAILED;
for (uint16_t count = 0; count < fill_count; count++) { for (uint16_t count = 0; count < fill_count; count++) {
result = registeredVariables[count]->serialize(buffer, size, max_size, result = registeredVariables[count]->serialize(buffer, size, max_size,
@ -119,8 +119,8 @@ ReturnValue_t DataSet::serialize(uint8_t** buffer, uint32_t* size,
return result; return result;
} }
uint32_t DataSet::getSerializedSize() const { size_t DataSet::getSerializedSize() const {
uint32_t size = 0; size_t size = 0;
for (uint16_t count = 0; count < fill_count; count++) { for (uint16_t count = 0; count < fill_count; count++) {
size += registeredVariables[count]->getSerializedSize(); size += registeredVariables[count]->getSerializedSize();
} }
@ -136,7 +136,7 @@ void DataSet::setValid(uint8_t valid) {
} }
} }
ReturnValue_t DataSet::deSerialize(const uint8_t** buffer, int32_t* size, ReturnValue_t DataSet::deSerialize(const uint8_t** buffer, ssize_t* size,
bool bigEndian) { bool bigEndian) {
ReturnValue_t result = RETURN_FAILED; ReturnValue_t result = RETURN_FAILED;
for (uint16_t count = 0; count < fill_count; count++) { for (uint16_t count = 0; count < fill_count; count++) {

View File

@ -37,44 +37,11 @@
* \ingroup data_pool * \ingroup data_pool
*/ */
class DataSet: public DataSetIF, public HasReturnvaluesIF, public SerializeIF { class DataSet: public DataSetIF, public HasReturnvaluesIF, public SerializeIF {
private:
public:
//SHOULDDO we could use a linked list of datapool variables //SHOULDDO we could use a linked list of datapool variables
static const uint8_t DATA_SET_MAX_SIZE = 63; //!< This definition sets the maximum number of variables to register in one DataSet. static const uint8_t DATA_SET_MAX_SIZE = 63; //!< This definition sets the maximum number of variables to register in one DataSet.
/**
* \brief This array represents all pool variables registered in this set.
* \details It has a maximum size of DATA_SET_MAX_SIZE.
*/
PoolVariableIF* registeredVariables[DATA_SET_MAX_SIZE];
/**
* \brief The fill_count attribute ensures that the variables register in the correct array
* position and that the maximum number of variables is not exceeded.
*/
uint16_t fill_count;
/**
* States of the seet.
*/
enum States {
DATA_SET_UNINITIALISED, //!< DATA_SET_UNINITIALISED
DATA_SET_WAS_READ //!< DATA_SET_WAS_READ
};
/**
* \brief state manages the internal state of the data set, which is important e.g. for the
* behavior on destruction.
*/
States state;
/**
* \brief This is a small helper function to facilitate locking the global data pool.
* \details It makes use of the lockDataPool method offered by the DataPool class.
*/
uint8_t lockDataPool();
/**
* \brief This is a small helper function to facilitate unlocking the global data pool.
* \details It makes use of the freeDataPoolLock method offered by the DataPool class.
*/
uint8_t freeDataPoolLock();
public:
static const uint8_t INTERFACE_ID = CLASS_ID::DATA_SET_CLASS; static const uint8_t INTERFACE_ID = CLASS_ID::DATA_SET_CLASS;
static const ReturnValue_t INVALID_PARAMETER_DEFINITION = static const ReturnValue_t INVALID_PARAMETER_DEFINITION =
MAKE_RETURN_CODE( 0x01 ); MAKE_RETURN_CODE( 0x01 );
@ -146,14 +113,56 @@ public:
*/ */
void setValid(uint8_t valid); void setValid(uint8_t valid);
ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, /**
const uint32_t max_size, bool bigEndian) const; * Serialize all registered pool variables into the provided buffer
* @param buffer
* @param size Is incremented by serialized size
* @param max_size
* @param bigEndian
* @return
*/
ReturnValue_t serialize(uint8_t** buffer, size_t* size,
const size_t max_size, bool bigEndian) const;
uint32_t getSerializedSize() const; virtual size_t getSerializedSize() const;
ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size,
bool bigEndian); bool bigEndian);
private:
/**
* \brief This array represents all pool variables registered in this set.
* \details It has a maximum size of DATA_SET_MAX_SIZE.
*/
PoolVariableIF* registeredVariables[DATA_SET_MAX_SIZE];
/**
* \brief The fill_count attribute ensures that the variables register in the correct array
* position and that the maximum number of variables is not exceeded.
*/
uint16_t fill_count;
/**
* States of the seet.
*/
enum States {
DATA_SET_UNINITIALISED, //!< DATA_SET_UNINITIALISED
DATA_SET_WAS_READ //!< DATA_SET_WAS_READ
};
/**
* \brief state manages the internal state of the data set, which is important e.g. for the
* behavior on destruction.
*/
States state;
/**
* \brief This is a small helper function to facilitate locking the global data pool.
* \details It makes use of the lockDataPool method offered by the DataPool class.
*/
uint8_t lockDataPool();
/**
* \brief This is a small helper function to facilitate unlocking the global data pool.
* \details It makes use of the freeDataPoolLock method offered by the DataPool class.
*/
uint8_t freeDataPoolLock();
}; };
#endif /* DATASET_H_ */ #endif /* DATASET_H_ */

View File

@ -126,17 +126,17 @@ public:
return *this; return *this;
} }
virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
const uint32_t max_size, bool bigEndian) const { const size_t max_size, bool bigEndian) const {
return SerializeAdapter<T>::serialize(&value, buffer, size, max_size, return SerializeAdapter<T>::serialize(&value, buffer, size, max_size,
bigEndian); bigEndian);
} }
virtual uint32_t getSerializedSize() const { virtual size_t getSerializedSize() const {
return SerializeAdapter<T>::getSerializedSize(&value); return SerializeAdapter<T>::getSerializedSize(&value);
} }
virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size,
bool bigEndian) { bool bigEndian) {
return SerializeAdapter<T>::deSerialize(&value, buffer, size, bigEndian); return SerializeAdapter<T>::deSerialize(&value, buffer, size, bigEndian);
} }

View File

@ -2,7 +2,20 @@
#include <framework/serviceinterface/ServiceInterfaceStream.h> #include <framework/serviceinterface/ServiceInterfaceStream.h>
template <typename T> template <typename T>
PoolEntry<T>::PoolEntry( T* initValue, uint8_t set_length, uint8_t set_valid ) : length(set_length), valid(set_valid) { PoolEntry<T>::PoolEntry(std::initializer_list<T> initValue, uint8_t set_length,
uint8_t set_valid ) : length(set_length), valid(set_valid) {
this->address = new T[this->length];
if(initValue.size() == 0) {
memset(this->address, 0, this->getByteSize());
}
else {
memcpy(this->address, initValue.begin(), this->getByteSize());
}
}
template <typename T>
PoolEntry<T>::PoolEntry( T* initValue, uint8_t set_length, uint8_t set_valid ) :
length(set_length), valid(set_valid) {
this->address = new T[this->length]; this->address = new T[this->length];
if (initValue != NULL) { if (initValue != NULL) {
memcpy(this->address, initValue, this->getByteSize() ); memcpy(this->address, initValue, this->getByteSize() );
@ -11,6 +24,7 @@ PoolEntry<T>::PoolEntry( T* initValue, uint8_t set_length, uint8_t set_valid ) :
} }
} }
//As the data pool is global, this dtor is only be called on program exit. //As the data pool is global, this dtor is only be called on program exit.
//Warning! Never copy pool entries! //Warning! Never copy pool entries!
template <typename T> template <typename T>
@ -56,6 +70,7 @@ Type PoolEntry<T>::getType() {
return PodTypeConversion<T>::type; return PodTypeConversion<T>::type;
} }
template class PoolEntry<bool>;
template class PoolEntry<uint8_t>; template class PoolEntry<uint8_t>;
template class PoolEntry<uint16_t>; template class PoolEntry<uint16_t>;
template class PoolEntry<uint32_t>; template class PoolEntry<uint32_t>;

View File

@ -5,6 +5,7 @@
#include <framework/datapool/PoolEntryIF.h> #include <framework/datapool/PoolEntryIF.h>
#include <stddef.h> #include <stddef.h>
#include <cstring> #include <cstring>
#include <initializer_list>
/** /**
* \brief This is a small helper class that defines a single data pool entry. * \brief This is a small helper class that defines a single data pool entry.
* *
@ -31,6 +32,7 @@ public:
* \param set_length Defines the array length of this entry. * \param set_length Defines the array length of this entry.
* \param set_valid Sets the initialization flag. It is invalid (0) by default. * \param set_valid Sets the initialization flag. It is invalid (0) by default.
*/ */
PoolEntry( std::initializer_list<T> initValue = {}, uint8_t set_length = 1, uint8_t set_valid = 0 );
PoolEntry( T* initValue = NULL, uint8_t set_length = 1, uint8_t set_valid = 0 ); PoolEntry( T* initValue = NULL, uint8_t set_length = 1, uint8_t set_valid = 0 );
/** /**
* \brief The allocated memory for the variable is freed in the destructor. * \brief The allocated memory for the variable is freed in the destructor.

View File

@ -14,13 +14,25 @@ PoolRawAccess::PoolRawAccess(uint32_t set_id, uint8_t setArrayEntry,
} }
} }
PoolRawAccess::~PoolRawAccess() { PoolRawAccess::~PoolRawAccess() {}
}
ReturnValue_t PoolRawAccess::read() { ReturnValue_t PoolRawAccess::read() {
ReturnValue_t result = RETURN_FAILED;
PoolEntryIF* read_out = ::dataPool.getRawData(dataPoolId); PoolEntryIF* read_out = ::dataPool.getRawData(dataPoolId);
if (read_out != NULL) { if (read_out != NULL) {
result = handleReadOut(read_out);
if(result == RETURN_OK) {
return result;
}
} else {
result = READ_ENTRY_NON_EXISTENT;
}
handleReadError(result);
return result;
}
ReturnValue_t PoolRawAccess::handleReadOut(PoolEntryIF* read_out) {
ReturnValue_t result = RETURN_FAILED;
valid = read_out->getValid(); valid = read_out->getValid();
if (read_out->getSize() > arrayEntry) { if (read_out->getSize() > arrayEntry) {
arraySize = read_out->getSize(); arraySize = read_out->getSize();
@ -29,26 +41,35 @@ ReturnValue_t PoolRawAccess::read() {
if (typeSize <= sizeof(value)) { if (typeSize <= sizeof(value)) {
uint16_t arrayPosition = arrayEntry * typeSize; uint16_t arrayPosition = arrayEntry * typeSize;
sizeTillEnd = read_out->getByteSize() - arrayPosition; sizeTillEnd = read_out->getByteSize() - arrayPosition;
uint8_t* ptr = uint8_t* ptr = &((uint8_t*) read_out->getRawData())[arrayPosition];
&((uint8_t*) read_out->getRawData())[arrayPosition];
memcpy(value, ptr, typeSize); memcpy(value, ptr, typeSize);
return HasReturnvaluesIF::RETURN_OK; return RETURN_OK;
} else { } else {
//Error value type too large. result = READ_TYPE_TOO_LARGE;
} }
} else { } else {
//Error index requested too large //debug << "PoolRawAccess: Size: " << (int)read_out->getSize() << std::endl;
} result = READ_INDEX_TOO_LARGE;
} else {
//Error entry does not exist.
} }
return result;
}
void PoolRawAccess::handleReadError(ReturnValue_t result) {
error << "PoolRawAccess: read of DP Variable 0x" << std::hex << dataPoolId error << "PoolRawAccess: read of DP Variable 0x" << std::hex << dataPoolId
<< std::dec << " failed." << std::endl; << std::dec << " failed, ";
if(result == READ_TYPE_TOO_LARGE) {
error << "type too large." << std::endl;
}
else if(result == READ_INDEX_TOO_LARGE) {
error << "index too large." << std::endl;
}
else if(result == READ_ENTRY_NON_EXISTENT) {
error << "entry does not exist." << std::endl;
}
valid = INVALID; valid = INVALID;
typeSize = 0; typeSize = 0;
sizeTillEnd = 0; sizeTillEnd = 0;
memset(value, 0, sizeof(value)); memset(value, 0, sizeof(value));
return HasReturnvaluesIF::RETURN_FAILED;
} }
ReturnValue_t PoolRawAccess::commit() { ReturnValue_t PoolRawAccess::commit() {
@ -89,6 +110,32 @@ ReturnValue_t PoolRawAccess::getEntryEndianSafe(uint8_t* buffer,
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t PoolRawAccess::serialize(uint8_t** buffer, size_t* size,
const size_t max_size, bool bigEndian) const {
if (typeSize + *size <= max_size) {
if (bigEndian) {
#ifndef BYTE_ORDER_SYSTEM
#error BYTE_ORDER_SYSTEM not defined
#elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
for (uint8_t count = 0; count < typeSize; count++) {
(*buffer)[count] = value[typeSize - count - 1];
}
#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
memcpy(*buffer, value, typeSize);
#endif
} else {
memcpy(*buffer, value, typeSize);
}
*size += typeSize;
(*buffer) += typeSize;
return HasReturnvaluesIF::RETURN_OK;
} else {
return SerializeIF::BUFFER_TOO_SHORT;
}
}
Type PoolRawAccess::getType() { Type PoolRawAccess::getType() {
return type; return type;
} }
@ -145,35 +192,12 @@ uint16_t PoolRawAccess::getSizeTillEnd() const {
return sizeTillEnd; return sizeTillEnd;
} }
ReturnValue_t PoolRawAccess::serialize(uint8_t** buffer, uint32_t* size,
const uint32_t max_size, bool bigEndian) const {
if (typeSize + *size <= max_size) {
if (bigEndian) {
#ifndef BYTE_ORDER_SYSTEM
#error BYTE_ORDER_SYSTEM not defined
#elif BYTE_ORDER_SYSTEM == LITTLE_ENDIAN
for (uint8_t count = 0; count < typeSize; count++) {
(*buffer)[count] = value[typeSize - count - 1];
}
#elif BYTE_ORDER_SYSTEM == BIG_ENDIAN
memcpy(*buffer, value, typeSize);
#endif
} else {
memcpy(*buffer, value, typeSize);
}
*size += typeSize;
(*buffer) += typeSize;
return HasReturnvaluesIF::RETURN_OK;
} else {
return SerializeIF::BUFFER_TOO_SHORT;
}
}
uint32_t PoolRawAccess::getSerializedSize() const { size_t PoolRawAccess::getSerializedSize() const {
return typeSize; return typeSize;
} }
ReturnValue_t PoolRawAccess::deSerialize(const uint8_t** buffer, int32_t* size, ReturnValue_t PoolRawAccess::deSerialize(const uint8_t** buffer, ssize_t* size,
bool bigEndian) { bool bigEndian) {
*size -= typeSize; *size -= typeSize;
if (*size >= 0) { if (*size >= 0) {

View File

@ -3,72 +3,44 @@
#include <framework/datapool/DataSetIF.h> #include <framework/datapool/DataSetIF.h>
#include <framework/datapool/PoolVariableIF.h> #include <framework/datapool/PoolVariableIF.h>
#include <framework/globalfunctions/Type.h>
/** /**
* This class allows accessing Data Pool variables as raw bytes. * @brief This class allows accessing Data Pool variables as raw bytes.
* @details
* This is necessary to have an access method for HK data, as the PID's alone do not * This is necessary to have an access method for HK data, as the PID's alone do not
* provide a type information. * provide a type information. Please note that the the raw pool access read() and commit()
* \ingroup data_pool * calls are not thread-safe.
* Please supply a data set and use the data set read(), commit() calls for thread-safe
* data pool access.
* @ingroup data_pool
*/ */
class PoolRawAccess: public PoolVariableIF { class PoolRawAccess: public PoolVariableIF, HasReturnvaluesIF {
private:
/**
* \brief To access the correct data pool entry on read and commit calls, the data pool id
* is stored.
*/
uint32_t dataPoolId;
/**
* \brief The array entry that is fetched from the data pool.
*/
uint8_t arrayEntry;
/**
* \brief The valid information as it was stored in the data pool is copied to this attribute.
*/
uint8_t valid;
/**
* \brief This value contains the type of the data pool entry.
*/
Type type;
/**
* \brief This value contains the size of the data pool entry in bytes.
*/
uint8_t typeSize;
/**
* The size of the DP array (single values return 1)
*/
uint8_t arraySize;
/**
* The size (in bytes) from the selected entry till the end of this DataPool variable.
*/
uint16_t sizeTillEnd;
/**
* \brief The information whether the class is read-write or read-only is stored here.
*/
ReadWriteMode_t readWriteMode;
static const uint8_t RAW_MAX_SIZE = sizeof(double);
protected:
/**
* \brief This is a call to read the value from the global data pool.
* \details When executed, this operation tries to fetch the pool entry with matching
* data pool id from the global data pool and copies the value and the valid
* information to its local attributes. In case of a failure (wrong type or
* pool id not found), the variable is set to zero and invalid.
* The operation does NOT provide any mutual exclusive protection by itself.
*/
ReturnValue_t read();
/**
* \brief The commit call writes back the variable's value to the data pool.
* \details It checks type and size, as well as if the variable is writable. If so,
* the value is copied and the valid flag is automatically set to "valid".
* The operation does NOT provide any mutual exclusive protection by itself.
*
*/
ReturnValue_t commit();
public: public:
static const uint8_t INTERFACE_ID = CLASS_ID::POOL_RAW_ACCESS_CLASS; static const uint8_t INTERFACE_ID = CLASS_ID::POOL_RAW_ACCESS_CLASS;
static const ReturnValue_t INCORRECT_SIZE = MAKE_RETURN_CODE(0x01); static const ReturnValue_t INCORRECT_SIZE = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t DATA_POOL_ACCESS_FAILED = MAKE_RETURN_CODE(0x02); static const ReturnValue_t DATA_POOL_ACCESS_FAILED = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t READ_TYPE_TOO_LARGE = MAKE_RETURN_CODE(0x03);
static const ReturnValue_t READ_INDEX_TOO_LARGE = MAKE_RETURN_CODE(0x04);
static const ReturnValue_t READ_ENTRY_NON_EXISTENT = MAKE_RETURN_CODE(0x05);
static const uint8_t RAW_MAX_SIZE = sizeof(double);
uint8_t value[RAW_MAX_SIZE]; uint8_t value[RAW_MAX_SIZE];
/**
* This constructor is used to access a data pool entry with a
* given ID if the target type is not known. A DataSet object is supplied
* and the data pool entry with the given ID is registered to that data set.
* Please note that a pool raw access buffer only has a buffer
* with a size of double. As such, for vector entries which have
* @param data_pool_id Target data pool entry ID
* @param arrayEntry
* @param data_set Dataset to register data pool entry to
* @param setReadWriteMode
* @param registerVectors If set to true, the constructor checks if
* there are multiple vector entries to registers
* and registers all of them recursively into the data_set
*
*/
PoolRawAccess(uint32_t data_pool_id, uint8_t arrayEntry, PoolRawAccess(uint32_t data_pool_id, uint8_t arrayEntry,
DataSetIF* data_set, ReadWriteMode_t setReadWriteMode = DataSetIF* data_set, ReadWriteMode_t setReadWriteMode =
PoolVariableIF::VAR_READ); PoolVariableIF::VAR_READ);
@ -77,11 +49,11 @@ public:
* discarded and not written back to the data pool. * discarded and not written back to the data pool.
*/ */
~PoolRawAccess(); ~PoolRawAccess();
/** /**
* \brief This operation returns a pointer to the entry fetched. * \brief This operation returns a pointer to the entry fetched.
* \details This means, it does not return a pointer to byte "index", but to the start byte of * \details Return pointer to the buffer containing the raw data
* array entry "index". Example: If the original data pool array consists of an double * Size and number of data can be retrieved by other means.
* array of size four, getEntry(1) returns &(this->value[8]).
*/ */
uint8_t* getEntry(); uint8_t* getEntry();
/** /**
@ -99,6 +71,19 @@ public:
*/ */
ReturnValue_t getEntryEndianSafe(uint8_t* buffer, uint32_t* size, ReturnValue_t getEntryEndianSafe(uint8_t* buffer, uint32_t* size,
uint32_t max_size); uint32_t max_size);
/**
* @brief Serialize raw pool entry into provided buffer directly
* @param buffer Provided buffer. Raw pool data will be copied here
* @param size [out] Increment provided size value by serialized size
* @param max_size Maximum allowed serialization size
* @param bigEndian Specify endianess
* @return - @c RETURN_OK if serialization was successfull
* - @c SerializeIF::BUFFER_TOO_SHORT if range check failed
*/
ReturnValue_t serialize(uint8_t** buffer, size_t* size,
const size_t max_size, bool bigEndian) const;
/** /**
* With this method, the content can be set from a big endian buffer safely. * With this method, the content can be set from a big endian buffer safely.
* @param buffer Pointer to the data to set * @param buffer Pointer to the data to set
@ -140,13 +125,73 @@ public:
*/ */
uint16_t getSizeTillEnd() const; uint16_t getSizeTillEnd() const;
ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, size_t getSerializedSize() const;
const uint32_t max_size, bool bigEndian) const;
uint32_t getSerializedSize() const; ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size,
ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size,
bool bigEndian); bool bigEndian);
protected:
/**
* \brief This is a call to read the value from the global data pool.
* \details When executed, this operation tries to fetch the pool entry with matching
* data pool id from the global data pool and copies the value and the valid
* information to its local attributes. In case of a failure (wrong type or
* pool id not found), the variable is set to zero and invalid.
* The operation does NOT provide any mutual exclusive protection by itself !
* If reading from the data pool without information about the type is desired,
* initialize the raw pool access by supplying a data set and using the data set
* read function, which calls this read function.
* @return -@c RETURN_OK Read successfull
* -@c READ_TYPE_TOO_LARGE
* -@c READ_INDEX_TOO_LARGE
* -@c READ_ENTRY_NON_EXISTENT
*/
ReturnValue_t read();
/**
* \brief The commit call writes back the variable's value to the data pool.
* \details It checks type and size, as well as if the variable is writable. If so,
* the value is copied and the valid flag is automatically set to "valid".
* The operation does NOT provide any mutual exclusive protection by itself.
*
*/
ReturnValue_t commit();
ReturnValue_t handleReadOut(PoolEntryIF* read_out);
void handleReadError(ReturnValue_t result);
private:
/**
* \brief To access the correct data pool entry on read and commit calls, the data pool id
* is stored.
*/
uint32_t dataPoolId;
/**
* \brief The array entry that is fetched from the data pool.
*/
uint8_t arrayEntry;
/**
* \brief The valid information as it was stored in the data pool is copied to this attribute.
*/
uint8_t valid;
/**
* \brief This value contains the type of the data pool entry.
*/
Type type;
/**
* \brief This value contains the size of the data pool entry type in bytes.
*/
uint8_t typeSize;
/**
* The size of the DP array (single values return 1)
*/
uint8_t arraySize;
/**
* The size (in bytes) from the selected entry till the end of this DataPool variable.
*/
uint16_t sizeTillEnd;
/**
* \brief The information whether the class is read-write or read-only is stored here.
*/
ReadWriteMode_t readWriteMode;
}; };
#endif /* POOLRAWACCESS_H_ */ #endif /* POOLRAWACCESS_H_ */

View File

@ -0,0 +1,169 @@
/**
* @file PoolRawAccessHelper.cpp
*
* @date 22.12.2019
* @author R. Mueller
*/
#include <framework/datapool/PoolRawAccessHelper.h>
#include <cmath>
#include <framework/datapool/DataSet.h>
PoolRawAccessHelper::PoolRawAccessHelper(uint32_t * poolIdBuffer_,
uint8_t numberOfParameters_):
poolIdBuffer(reinterpret_cast<uint8_t * >(poolIdBuffer_)),
numberOfParameters(numberOfParameters_), validBufferIndex(0),
validBufferIndexBit(1) {
}
PoolRawAccessHelper::~PoolRawAccessHelper() {
}
ReturnValue_t PoolRawAccessHelper::serialize(uint8_t **buffer, size_t *size,
const size_t max_size, bool bigEndian) {
SerializationArgs serializationArgs = {buffer, size, max_size, bigEndian};
ReturnValue_t result;
ssize_t remainingParametersSize = numberOfParameters * 4;
for(uint8_t count=0; count < numberOfParameters; count++) {
result = serializeCurrentPoolEntryIntoBuffer(serializationArgs,
&remainingParametersSize, false);
if(result != RETURN_OK) {
return result;
}
}
if(remainingParametersSize != 0) {
debug << "Pool Raw Access: Remaining parameters size not 0 !" << std::endl;
result = RETURN_FAILED;
}
return result;
}
ReturnValue_t PoolRawAccessHelper::serializeWithValidityMask(uint8_t ** buffer,
size_t * size, const size_t max_size, bool bigEndian) {
ReturnValue_t result;
SerializationArgs argStruct = {buffer, size, max_size, bigEndian};
ssize_t remainingParametersSize = numberOfParameters * 4;
uint8_t validityMaskSize = ceil((float)numberOfParameters/8.0);
uint8_t validityMask[validityMaskSize];
memset(validityMask,0, validityMaskSize);
for(uint8_t count = 0; count < numberOfParameters; count++) {
result = serializeCurrentPoolEntryIntoBuffer(argStruct,
&remainingParametersSize,true,validityMask);
if (result != RETURN_OK) {
return result;
}
}
if(remainingParametersSize != 0) {
debug << "Pool Raw Access: Remaining parameters size not 0 !" << std::endl;
result = RETURN_FAILED;
}
memcpy(*argStruct.buffer, validityMask, validityMaskSize);
*size += validityMaskSize;
validBufferIndex = 1;
validBufferIndexBit = 0;
return result;
}
ReturnValue_t PoolRawAccessHelper::serializeCurrentPoolEntryIntoBuffer(SerializationArgs argStruct,
ssize_t * remainingParameters, bool withValidMask, uint8_t * validityMask) {
uint32_t currentPoolId;
// Deserialize current pool ID from pool ID buffer
ReturnValue_t result = AutoSerializeAdapter::deSerialize(&currentPoolId,
&poolIdBuffer,remainingParameters,true);
if(result != RETURN_OK) {
debug << std::hex << "Pool Raw Access Helper: Error deSeralizing pool IDs" << std::dec << std::endl;
return result;
}
result = handlePoolEntrySerialization(currentPoolId, argStruct, withValidMask, validityMask);
return result;
}
ReturnValue_t PoolRawAccessHelper::handlePoolEntrySerialization(uint32_t currentPoolId,SerializationArgs argStruct,
bool withValidMask, uint8_t * validityMask) {
ReturnValue_t result = RETURN_FAILED;
uint8_t arrayPosition = 0;
uint8_t counter = 0;
bool poolEntrySerialized = false;
//debug << "Pool Raw Access Helper: Handling Pool ID: " << std::hex << currentPoolId << std::endl;
while(not poolEntrySerialized) {
if(counter > DataSet::DATA_SET_MAX_SIZE) {
error << "Pool Raw Access Helper: Config error, max. number of possible data set variables exceeded" << std::endl;
return result;
}
counter ++;
DataSet currentDataSet = DataSet();
//debug << "Current array position: " << (int)arrayPosition << std::endl;
PoolRawAccess currentPoolRawAccess(currentPoolId,arrayPosition,&currentDataSet,PoolVariableIF::VAR_READ);
result = currentDataSet.read();
if (result != RETURN_OK) {
debug << std::hex << "Pool Raw Access Helper: Error reading raw dataset with returncode 0x"
<< result << std::dec << std::endl;
return result;
}
result = checkRemainingSize(&currentPoolRawAccess, &poolEntrySerialized, &arrayPosition);
if(result != RETURN_OK) {
error << "Pool Raw Access Helper: Configuration Error at pool ID " << std::hex << currentPoolId
<< ". Size till end smaller than 0" << std::dec << std::endl;
return result;
}
// set valid mask bit if necessary
if(withValidMask) {
if(currentPoolRawAccess.isValid()) {
handleMaskModification(validityMask);
}
validBufferIndexBit ++;
}
result = currentDataSet.serialize(argStruct.buffer, argStruct.size,
argStruct.max_size, argStruct.bigEndian);
if (result != RETURN_OK) {
debug << "Pool Raw Access Helper: Error serializing pool data with ID 0x" << std::hex <<
currentPoolId << " into send buffer with return code " << result << std::dec << std::endl;
return result;
}
}
return result;
}
ReturnValue_t PoolRawAccessHelper::checkRemainingSize(PoolRawAccess * currentPoolRawAccess,
bool * isSerialized, uint8_t * arrayPosition) {
int8_t remainingSize = currentPoolRawAccess->getSizeTillEnd() - currentPoolRawAccess->getSizeOfType();
if(remainingSize == 0) {
*isSerialized = true;
}
else if(remainingSize > 0) {
*arrayPosition += 1;
}
else {
return RETURN_FAILED;
}
return RETURN_OK;
}
void PoolRawAccessHelper::handleMaskModification(uint8_t * validityMask) {
validityMask[validBufferIndex] =
bitSetter(validityMask[validBufferIndex], validBufferIndexBit, true);
if(validBufferIndexBit == 8) {
validBufferIndex ++;
validBufferIndexBit = 1;
}
}
uint8_t PoolRawAccessHelper::bitSetter(uint8_t byte, uint8_t position, bool value) {
if(position < 1 or position > 8) {
debug << "Pool Raw Access: Bit setting invalid position" << std::endl;
return byte;
}
uint8_t shiftNumber = position + (6 - 2 * (position - 1));
byte |= 1UL << shiftNumber;
return byte;
}

View File

@ -0,0 +1,108 @@
/**
* @file PoolRawAccessHelper.h
*
* @date 22.12.2019
*/
#ifndef FRAMEWORK_DATAPOOL_POOLRAWACCESSHELPER_H_
#define FRAMEWORK_DATAPOOL_POOLRAWACCESSHELPER_H_
#include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/datapool/DataSet.h>
/**
* @brief This helper function simplifies accessing data pool entries
* via PoolRawAccess
* @details Can be used for a Housekeeping Service
* like ECSS PUS Service 3 if the type of the datapool entries is unknown.
* The provided dataset can be serialized into a provided buffer automatically by
* providing a buffer of pool IDs
* @ingroup data_pool
*/
class PoolRawAccessHelper: public HasReturnvaluesIF {
public:
/**
* Call this constructor if a dataset needs to be serialized via
* Pool Raw Access
* @param dataSet_ This dataset will be used to perform thread-safe reading
* @param poolIdBuffer_ A buffer of uint32_t pool IDs
* @param numberOfParameters_ The number of parameters / pool IDs
*/
PoolRawAccessHelper(uint32_t * poolIdBuffer_, uint8_t numberOfParameters_);
virtual ~PoolRawAccessHelper();
/**
* Serialize the datapool entries derived from the pool ID buffer
* directly into a provided buffer
* @param [out] buffer
* @param [out] size Size of the serialized buffer
* @param max_size
* @param bigEndian
* @return @c RETURN_OK On success
* @c RETURN_FAILED on failure
*/
ReturnValue_t serialize(uint8_t ** buffer, size_t * size,
const size_t max_size, bool bigEndian);
/**
* Serializes data pool entries into provided buffer with the validity mask buffer
* at the end of the buffer. Every bit of the validity mask denotes
* the validity of a corresponding data pool entry from left to right.
* @param [out] buffer
* @param [out] size Size of the serialized buffer plus size
* of the validity mask
* @return @c RETURN_OK On success
* @c RETURN_FAILED on failure
*/
ReturnValue_t serializeWithValidityMask(uint8_t ** buffer, size_t * size,
const size_t max_size, bool bigEndian);
private:
// DataSet * dataSet;
const uint8_t * poolIdBuffer;
uint8_t numberOfParameters;
uint8_t validBufferIndex;
uint8_t validBufferIndexBit;
struct SerializationArgs {
uint8_t ** buffer;
size_t * size;
const uint32_t max_size;
bool bigEndian;
};
/**
* Helper function to serialize single pool entries
* @param pPoolIdBuffer
* @param buffer
* @param remainingParameters
* @param hkDataSize
* @param max_size
* @param bigEndian
* @param withValidMask Can be set optionally to set a provided validity mask
* @param validityMask Can be supplied and will be set if @c withValidMask is set to true
* @return
*/
ReturnValue_t serializeCurrentPoolEntryIntoBuffer(SerializationArgs argStruct,
ssize_t * remainingParameters, bool withValidMask = false,
uint8_t * validityMask = nullptr);
ReturnValue_t handlePoolEntrySerialization(uint32_t currentPoolId,
SerializationArgs argStruct, bool withValidMask = false,
uint8_t * validityMask = nullptr);
ReturnValue_t checkRemainingSize(PoolRawAccess * currentPoolRawAccess,
bool * isSerialized, uint8_t * arrayPosition);
void handleMaskModification(uint8_t * validityMask);
/**
* Sets specific bit of a byte
* @param byte
* @param position Position of byte to set from 1 to 8
* @param value Binary value to set
* @return
*/
uint8_t bitSetter(uint8_t byte, uint8_t position, bool value);
};
#endif /* FRAMEWORK_DATAPOOL_POOLRAWACCESSHELPER_H_ */

View File

@ -112,8 +112,7 @@ public:
* corresponds to. * corresponds to.
* \param dataSet The data set in which the variable shall register itself. If NULL, * \param dataSet The data set in which the variable shall register itself. If NULL,
* the variable is not registered. * the variable is not registered.
* \param setWritable If this flag is set to true, changes in the value attribute can be * \param setReadWriteMode
* written back to the data pool, otherwise not.
*/ */
PoolVariable(uint32_t set_id, DataSetIF* dataSet, PoolVariable(uint32_t set_id, DataSetIF* dataSet,
ReadWriteMode_t setReadWriteMode) : ReadWriteMode_t setReadWriteMode) :
@ -194,17 +193,17 @@ public:
return *this; return *this;
} }
virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
const uint32_t max_size, bool bigEndian) const { const size_t max_size, bool bigEndian) const {
return SerializeAdapter<T>::serialize(&value, buffer, size, max_size, return SerializeAdapter<T>::serialize(&value, buffer, size, max_size,
bigEndian); bigEndian);
} }
virtual uint32_t getSerializedSize() const { virtual size_t getSerializedSize() const {
return SerializeAdapter<T>::getSerializedSize(&value); return SerializeAdapter<T>::getSerializedSize(&value);
} }
virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size,
bool bigEndian) { bool bigEndian) {
return SerializeAdapter<T>::deSerialize(&value, buffer, size, bigEndian); return SerializeAdapter<T>::deSerialize(&value, buffer, size, bigEndian);
} }

View File

@ -197,8 +197,8 @@ public:
return *this; return *this;
} }
virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
const uint32_t max_size, bool bigEndian) const { const size_t max_size, bool bigEndian) const {
uint16_t i; uint16_t i;
ReturnValue_t result; ReturnValue_t result;
for (i = 0; i < vector_size; i++) { for (i = 0; i < vector_size; i++) {
@ -211,11 +211,11 @@ public:
return result; return result;
} }
virtual uint32_t getSerializedSize() const { virtual size_t getSerializedSize() const {
return vector_size * SerializeAdapter<T>::getSerializedSize(value); return vector_size * SerializeAdapter<T>::getSerializedSize(value);
} }
virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size,
bool bigEndian) { bool bigEndian) {
uint16_t i; uint16_t i;
ReturnValue_t result; ReturnValue_t result;

View File

@ -15,9 +15,8 @@ public:
/** /**
* Default empty virtual destructor. * Default empty virtual destructor.
*/ */
virtual ~AcceptsDeviceResponsesIF() { virtual ~AcceptsDeviceResponsesIF() {}
} virtual MessageQueueId_t getDeviceQueue() = 0;
virtual MessageQueueId_t getDeviceQueue() = 0;
}; };
#endif /* ACCEPTSDEVICERESPONSESIF_H_ */ #endif /* ACCEPTSDEVICERESPONSESIF_H_ */

View File

@ -2,10 +2,10 @@
AssemblyBase::AssemblyBase(object_id_t objectId, object_id_t parentId, AssemblyBase::AssemblyBase(object_id_t objectId, object_id_t parentId,
uint16_t commandQueueDepth) : uint16_t commandQueueDepth) :
SubsystemBase(objectId, parentId, MODE_OFF, commandQueueDepth), internalState( SubsystemBase(objectId, parentId, MODE_OFF, commandQueueDepth),
STATE_NONE), recoveryState(RECOVERY_IDLE), recoveringDevice( internalState(STATE_NONE), recoveryState(RECOVERY_IDLE),
childrenMap.end()), targetMode(MODE_OFF), targetSubmode( recoveringDevice(childrenMap.end()), targetMode(MODE_OFF),
SUBMODE_NONE) { targetSubmode(SUBMODE_NONE) {
recoveryOffTimer.setTimeout(POWER_OFF_TIME_MS); recoveryOffTimer.setTimeout(POWER_OFF_TIME_MS);
} }

View File

@ -2,15 +2,16 @@
#include <framework/devicehandlers/ChildHandlerBase.h> #include <framework/devicehandlers/ChildHandlerBase.h>
#include <framework/subsystem/SubsystemBase.h> #include <framework/subsystem/SubsystemBase.h>
ChildHandlerBase::ChildHandlerBase(uint32_t ioBoardAddress, ChildHandlerBase::ChildHandlerBase(object_id_t setObjectId,
object_id_t setObjectId, object_id_t deviceCommunication, object_id_t deviceCommunication, CookieIF * cookie,
uint32_t maxDeviceReplyLen, uint8_t setDeviceSwitch, uint32_t maxDeviceReplyLen, uint8_t setDeviceSwitch,
uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId, uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId,
uint32_t parent, FailureIsolationBase* customFdir, uint32_t cmdQueueSize) : uint32_t parent, FailureIsolationBase* customFdir, size_t cmdQueueSize) :
DeviceHandlerBase(ioBoardAddress, setObjectId, maxDeviceReplyLen, DeviceHandlerBase(setObjectId, deviceCommunication, cookie,
setDeviceSwitch, deviceCommunication, thermalStatePoolId, setDeviceSwitch, thermalStatePoolId,
thermalRequestPoolId, (customFdir == NULL? &childHandlerFdir : customFdir), cmdQueueSize), parentId( thermalRequestPoolId, (customFdir == NULL? &childHandlerFdir : customFdir),
parent), childHandlerFdir(setObjectId) { cmdQueueSize),
parentId(parent), childHandlerFdir(setObjectId) {
} }
ChildHandlerBase::~ChildHandlerBase() { ChildHandlerBase::~ChildHandlerBase() {

View File

@ -6,12 +6,11 @@
class ChildHandlerBase: public DeviceHandlerBase { class ChildHandlerBase: public DeviceHandlerBase {
public: public:
ChildHandlerBase(uint32_t ioBoardAddress, object_id_t setObjectId, ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication,
object_id_t deviceCommunication, uint32_t maxDeviceReplyLen, CookieIF * cookie, uint32_t maxDeviceReplyLen, uint8_t setDeviceSwitch,
uint8_t setDeviceSwitch, uint32_t thermalStatePoolId, uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId,
uint32_t thermalRequestPoolId, uint32_t parent, uint32_t parent, FailureIsolationBase* customFdir = nullptr,
FailureIsolationBase* customFdir = NULL, size_t cmdQueueSize = 20);
uint32_t cmdQueueSize = 20);
virtual ~ChildHandlerBase(); virtual ~ChildHandlerBase();
virtual ReturnValue_t initialize(); virtual ReturnValue_t initialize();

View File

@ -0,0 +1,201 @@
/**
* @file CommunicationMessage.cpp
*
* @date 28.02.2020
*/
#include <framework/devicehandlers/CommunicationMessage.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <cstring>
CommunicationMessage::CommunicationMessage(): uninitialized(true) {
}
CommunicationMessage::~CommunicationMessage() {}
void CommunicationMessage::setSendRequestFromPointer(uint32_t address,
uint32_t dataLen, const uint8_t * data) {
setMessageType(SEND_DATA_FROM_POINTER);
setAddress(address);
setDataLen(dataLen);
setDataPointer(data);
}
void CommunicationMessage::setSendRequestFromIpcStore(uint32_t address, store_address_t storeId) {
setMessageType(SEND_DATA_FROM_IPC_STORE);
setAddress(address);
setStoreId(storeId.raw);
}
void CommunicationMessage::setSendRequestRaw(uint32_t address, uint32_t length,
uint16_t sendBufferPosition) {
setMessageType(SEND_DATA_RAW);
setAddress(address);
setDataLen(length);
if(sendBufferPosition != 0) {
setBufferPosition(sendBufferPosition);
}
}
void CommunicationMessage::setDataReplyFromIpcStore(uint32_t address, store_address_t storeId) {
setMessageType(REPLY_DATA_IPC_STORE);
setAddress(address);
setStoreId(storeId.raw);
}
void CommunicationMessage::setDataReplyFromPointer(uint32_t address,
uint32_t dataLen, uint8_t *data) {
setMessageType(REPLY_DATA_FROM_POINTER);
setAddress(address);
setDataLen(dataLen);
setDataPointer(data);
}
void CommunicationMessage::setDataReplyRaw(uint32_t address,
uint32_t length, uint16_t receiveBufferPosition) {
setMessageType(REPLY_DATA_RAW);
setAddress(address);
setDataLen(length);
if(receiveBufferPosition != 0) {
setBufferPosition(receiveBufferPosition);
}
}
void CommunicationMessage::setMessageType(messageType status) {
uint8_t status_uint8 = status;
memcpy(getData() + sizeof(uint32_t), &status_uint8, sizeof(status_uint8));
}
void CommunicationMessage::setAddress(address_t address) {
memcpy(getData(),&address,sizeof(address));
}
address_t CommunicationMessage::getAddress() const {
address_t address;
memcpy(&address,getData(),sizeof(address));
return address;
}
void CommunicationMessage::setBufferPosition(uint16_t bufferPosition) {
memcpy(getData() + sizeof(uint32_t) + sizeof(uint16_t),
&bufferPosition, sizeof(bufferPosition));
}
uint16_t CommunicationMessage::getBufferPosition() const {
uint16_t bufferPosition;
memcpy(&bufferPosition,
getData() + sizeof(uint32_t) + sizeof(uint16_t), sizeof(bufferPosition));
return bufferPosition;
}
void CommunicationMessage::setDataPointer(const void * data) {
memcpy(getData() + 3 * sizeof(uint32_t), &data, sizeof(uint32_t));
}
void CommunicationMessage::setStoreId(store_address_t storeId) {
memcpy(getData() + 2 * sizeof(uint32_t), &storeId.raw, sizeof(uint32_t));
}
store_address_t CommunicationMessage::getStoreId() const{
store_address_t temp;
memcpy(&temp.raw,getData() + 2 * sizeof(uint32_t), sizeof(uint32_t));
return temp;
}
void CommunicationMessage::setDataLen(uint32_t length) {
memcpy(getData() + 2 * sizeof(uint32_t), &length, sizeof(length));
}
uint32_t CommunicationMessage::getDataLen() const {
uint32_t len;
memcpy(&len, getData() + 2 * sizeof(uint32_t), sizeof(len));
return len;
}
void CommunicationMessage::setUint32Data(uint32_t data) {
memcpy(getData() + 3 * sizeof(uint32_t), &data, sizeof(data));
}
uint32_t CommunicationMessage::getUint32Data() const{
uint32_t data;
memcpy(&data,getData() + 3 * sizeof(uint32_t), sizeof(data));
return data;
}
void CommunicationMessage::setDataByte(uint8_t byte, uint8_t position) {
if(0 <= position && position <= 3) {
memcpy(getData() + 3 * sizeof(uint32_t) + position * sizeof(uint8_t), &byte, sizeof(byte));
}
else {
error << "Comm Message: Invalid byte position" << std::endl;
}
}
uint8_t CommunicationMessage::getDataByte(uint8_t position) const {
if(0 <= position && position <= 3) {
uint8_t byte;
memcpy(&byte, getData() + 3 * sizeof(uint32_t) + position * sizeof(uint8_t), sizeof(byte));
return byte;
}
else {
return 0;
error << "Comm Message: Invalid byte position" << std::endl;
}
}
void CommunicationMessage::setDataUint16(uint16_t data, uint8_t position) {
if(position == 0 || position == 1) {
memcpy(getData() + 3 * sizeof(uint32_t) + position * sizeof(uint16_t), &data, sizeof(data));
}
else {
error << "Comm Message: Invalid byte position" << std::endl;
}
}
uint16_t CommunicationMessage::getDataUint16(uint8_t position) const{
if(position == 0 || position == 1) {
uint16_t data;
memcpy(&data, getData() + 3 * sizeof(uint32_t) + position * sizeof(uint16_t), sizeof(data));
return data;
}
else {
return 0;
error << "Comm Message: Invalid byte position" << std::endl;
}
}
CommunicationMessage::messageType CommunicationMessage::getMessageType() const{
messageType messageType;
memcpy(&messageType, getData() + sizeof(uint32_t),sizeof(uint8_t));
return messageType;
}
void CommunicationMessage::setMessageId(uint8_t messageId) {
memcpy(getData() + sizeof(uint32_t) + sizeof(uint8_t), &messageId, sizeof(messageId));
}
uint8_t CommunicationMessage::getMessageId() const {
uint8_t messageId;
memcpy(&messageId, getData() + sizeof(uint32_t) + sizeof(uint8_t), sizeof(messageId));
return messageId;
}
void CommunicationMessage::clearCommunicationMessage() {
messageType messageType = getMessageType();
switch(messageType) {
case(messageType::REPLY_DATA_IPC_STORE):
case(messageType::SEND_DATA_FROM_IPC_STORE): {
store_address_t storeId = getStoreId();
StorageManagerIF *ipcStore = objectManager->
get<StorageManagerIF>(objects::IPC_STORE);
if (ipcStore != NULL) {
ipcStore->deleteData(storeId);
}
}
/* NO BREAK falls through*/
default:
memset(getData(),0,4*sizeof(uint32_t));
break;
}
}

View File

@ -0,0 +1,177 @@
/**
* @file CommunicationMessage.h
*
* @date 28.02.2020
*/
#ifndef FRAMEWORK_DEVICEHANDLERS_COMMUNICATIONMESSAGE_H_
#define FRAMEWORK_DEVICEHANDLERS_COMMUNICATIONMESSAGE_H_
#include <framework/devicehandlers/CommunicationMessage.h>
#include <framework/ipc/MessageQueueMessage.h>
#include <framework/storagemanager/StorageManagerIF.h>
#include <framework/devicehandlers/DeviceHandlerBase.h>
/**
* @brief Used to pass communication information between tasks
*
* @details
* Can be used to pass information like data pointers and
* data sizes between communication tasks
* like the Device Handler Comm Interfaces and Polling Tasks.
*
* Can also be used to exchange actual data if its not too large
* (e.g. Sensor values).
*
*/
class CommunicationMessage: public MessageQueueMessage {
public:
enum messageType {
NONE,
SEND_DATA_FROM_POINTER,
SEND_DATA_FROM_IPC_STORE,
SEND_DATA_RAW,
REPLY_DATA_FROM_POINTER,
REPLY_DATA_IPC_STORE,
REPLY_DATA_RAW,
FAULTY,
};
//Add other messageIDs here if necessary.
static const uint8_t COMMUNICATION_MESSAGE_SIZE = HEADER_SIZE + 4 * sizeof(uint32_t);
CommunicationMessage();
virtual ~CommunicationMessage();
/**
* Message Type is stored as the fifth byte of the message data
* @param status
*/
void setMessageType(messageType status);
messageType getMessageType() const;
/**
* This is a unique ID which can be used to handle different kinds of messages.
* For example, the same interface (e.g. SPI) could be used to exchange raw data
* (e.g. sensor values) and data stored in the IPC store.
* The ID can be used to distinguish the messages in child implementations.
* The message ID is stored as the sixth byte of the message data.
* @param messageId
*/
void setMessageId(uint8_t messageId);
uint8_t getMessageId() const;
/**
* Send requests with pointer to the data to be sent and send data length
* @param address Target Address, first four bytes
* @param dataLen Length of data to send, next four bytes
* @param data Pointer to data to send
*
*/
void setSendRequestFromPointer(uint32_t address, uint32_t dataLen, const uint8_t * data);
/**
* Send requests with a store ID, using the IPC store
* @param address Target Address, first four bytes
* @param storeId Store ID in the IPC store
*
*/
void setSendRequestFromIpcStore(uint32_t address, store_address_t storeId);
/**
* Send requests with data length and data in message (max. 4 bytes)
* @param address Target Address, first four bytes
* @param dataLen Length of data to send, next four bytes
* @param data Pointer to data to send
*
*/
void setSendRequestRaw(uint32_t address, uint32_t length,
uint16_t sendBufferPosition = 0);
/**
* Data message with data stored in IPC store
* @param address Target Address, first four bytes
* @param length
* @param storeId
*/
void setDataReplyFromIpcStore(uint32_t address, store_address_t storeId);
/**
* Data reply with data stored in buffer, passing the pointer to
* the buffer and the data size
* @param address Target Address, first four bytes
* @param dataLen Length of data to send, next four bytes
* @param data Pointer to the data
*/
void setDataReplyFromPointer(uint32_t address, uint32_t dataLen, uint8_t * data);
/**
* Data message with data stored in actual message.
* 4 byte datafield is intialized with 0.
* Set data with specific setter functions below.
* Can also be used to supply information at which position the raw data should be stored
* in a receive buffer.
*/
void setDataReplyRaw(uint32_t address, uint32_t length, uint16_t receiveBufferPosition = 0);
/**
* First four bytes of message data
* @param address
*/
void setAddress(address_t address);
address_t getAddress() const;
/**
* Set byte as position of 4 byte data field
* @param byte
* @param position Position, 0 to 3 possible
*/
void setDataByte(uint8_t byte, uint8_t position);
uint8_t getDataByte(uint8_t position) const;
/**
* Set 2 byte value at position 1 or 2 of data field
* @param data
* @param position 0 or 1 possible
*/
void setDataUint16(uint16_t data, uint8_t position);
uint16_t getDataUint16(uint8_t position) const;
void setUint32Data(uint32_t data);
uint32_t getUint32Data() const;
/**
* Stored in Bytes 13-16 of message data
* @param length
*/
void setDataLen(uint32_t length);
uint32_t getDataLen() const;
/**
* Stored in last four bytes (Bytes 17-20) of message data
* @param sendData
*/
void setDataPointer(const void * data);
/**
* In case the send request data or reply data is to be stored in a buffer,
* a buffer Position can be stored here as the seventh and eigth byte of
* the message, so the receive buffer can't be larger than sizeof(uint16_t) for now.
* @param bufferPosition In case the data is stored in a buffer, the position can be supplied here
*/
void setBufferPosition(uint16_t bufferPosition);
uint16_t getBufferPosition() const;
void setStoreId(store_address_t storeId);
store_address_t getStoreId() const;
/**
* Clear the message. Deletes IPC Store data
* and sets all data to 0. Also sets message type to NONE
*/
void clearCommunicationMessage();
private:
bool uninitialized; //!< Could be used to warn if data has not been set.
};
#endif /* FRAMEWORK_DEVICEHANDLERS_COMMUNICATIONMESSAGE_H_ */

View File

@ -1,10 +0,0 @@
#ifndef COOKIE_H_
#define COOKIE_H_
class Cookie{
public:
virtual ~Cookie(){}
};
#endif /* COOKIE_H_ */

33
devicehandlers/CookieIF.h Normal file
View File

@ -0,0 +1,33 @@
#ifndef COOKIE_H_
#define COOKIE_H_
#include <framework/devicehandlers/CookieIF.h>
#include <stdint.h>
/**
* @brief Physical address type
*/
typedef uint32_t address_t;
/**
* @brief This datatype is used to identify different connection over a
* single interface (like RMAP or I2C)
* @details
* To use this class, implement a communication specific child cookie which
* inherits Cookie. Cookie instances are created in config/ Factory.cpp by calling
* CookieIF* childCookie = new ChildCookie(...).
*
* This cookie is then passed to the child device handlers, which stores the
* pointer and passes it to the communication interface functions.
*
* The cookie can be used to store all kinds of information
* about the communication, like slave addresses, communication status,
* communication parameters etc.
*
* @ingroup comm
*/
class CookieIF {
public:
virtual ~CookieIF() {};
};
#endif /* COOKIE_H_ */

View File

@ -1,63 +1,126 @@
#ifndef DEVICECOMMUNICATIONIF_H_ #ifndef DEVICECOMMUNICATIONIF_H_
#define DEVICECOMMUNICATIONIF_H_ #define DEVICECOMMUNICATIONIF_H_
#include <framework/devicehandlers/Cookie.h> #include <framework/devicehandlers/CookieIF.h>
#include <framework/devicehandlers/DeviceHandlerIF.h>
#include <framework/returnvalues/HasReturnvaluesIF.h> #include <framework/returnvalues/HasReturnvaluesIF.h>
/**
* @defgroup interfaces Interfaces
* @brief Interfaces for flight software objects
*/
/**
* @defgroup comm Communication
* @brief Communication software components.
*/
/**
* @brief This is an interface to decouple device communication from
* the device handler to allow reuse of these components.
* @details
* Documentation: Dissertation Baetz p.138.
* It works with the assumption that received data
* is polled by a component. There are four generic steps of device communication:
*
* 1. Send data to a device
* 2. Get acknowledgement for sending
* 3. Request reading data from a device
* 4. Read received data
*
* To identify different connection over a single interface can return
* so-called cookies to components.
* The CommunicationMessage message type can be used to extend the
* functionality of the ComIF if a separate polling task is required.
* @ingroup interfaces
* @ingroup comm
*/
class DeviceCommunicationIF: public HasReturnvaluesIF { class DeviceCommunicationIF: public HasReturnvaluesIF {
public: public:
static const uint8_t INTERFACE_ID = CLASS_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); //! This is returned in readReceivedMessage() if no reply was reived.
static const ReturnValue_t NOT_ACTIVE = MAKE_RETURN_CODE(0x02); static const ReturnValue_t NO_REPLY_RECEIVED = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t INVALID_ADDRESS = MAKE_RETURN_CODE(0x03);
static const ReturnValue_t TOO_MUCH_DATA = MAKE_RETURN_CODE(0x04);
static const ReturnValue_t NULLPOINTER = MAKE_RETURN_CODE(0x05);
static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0x06);
static const ReturnValue_t CANT_CHANGE_REPLY_LEN = MAKE_RETURN_CODE(0x07);
virtual ~DeviceCommunicationIF() { //! General protocol error. Define more concrete errors in child handler
static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0x02);
//! If cookie is a null pointer
static const ReturnValue_t NULLPOINTER = MAKE_RETURN_CODE(0x03);
static const ReturnValue_t INVALID_COOKIE_TYPE = MAKE_RETURN_CODE(0x04);
// is this needed if there is no open/close call?
static const ReturnValue_t NOT_ACTIVE = MAKE_RETURN_CODE(0x05);
static const ReturnValue_t TOO_MUCH_DATA = MAKE_RETURN_CODE(0x06);
} virtual ~DeviceCommunicationIF() {}
virtual ReturnValue_t open(Cookie **cookie, uint32_t address,
uint32_t maxReplyLen) = 0;
/** /**
* Use an existing cookie to open a connection to a new DeviceCommunication. * @brief Device specific initialization, using the cookie.
* The previous connection must not be closed. * @details
* If the returnvalue is not RETURN_OK, the cookie is unchanged and * The cookie is already prepared in the factory. If the communication
* can be used with the previous connection. * interface needs to be set up in some way and requires cookie information,
* this can be performed in this function, which is called on device handler
* initialization.
* @param cookie
* @return -@c RETURN_OK if initialization was successfull
* - Everything else triggers failure event with
* returnvalue as parameter 1
*/
virtual ReturnValue_t initializeInterface(CookieIF * cookie) = 0;
/**
* Called by DHB in the SEND_WRITE doSendWrite().
* This function is used to send data to the physical device
* by implementing and calling related drivers or wrapper functions.
* @param cookie
* @param data
* @param len
* @return -@c RETURN_OK for successfull send
* - Everything else triggers failure event with
* returnvalue as parameter 1
*/
virtual ReturnValue_t sendMessage(CookieIF *cookie, const uint8_t * sendData,
size_t sendLen) = 0;
/**
* Called by DHB in the GET_WRITE doGetWrite().
* Get send confirmation that the data in sendMessage() was sent successfully.
* @param cookie
* @return -@c RETURN_OK if data was sent successfull
* - Everything else triggers falure event with
* returnvalue as parameter 1
*/
virtual ReturnValue_t getSendSuccess(CookieIF *cookie) = 0;
/**
* Called by DHB in the SEND_WRITE doSendRead().
* It is assumed that it is always possible to request a reply
* from a device. If a requestLen of 0 is supplied, no reply was enabled
* and communication specific action should be taken (e.g. read nothing
* or read everything).
* *
* @param cookie * @param cookie
* @param address * @param requestLen Size of data to read
* @param maxReplyLen * @return -@c RETURN_OK to confirm the request for data has been sent.
* @return * - Everything else triggers failure event with
* returnvalue as parameter 1
*/ */
virtual ReturnValue_t reOpen(Cookie *cookie, uint32_t address, virtual ReturnValue_t requestReceiveMessage(CookieIF *cookie, size_t requestLen) = 0;
uint32_t maxReplyLen) = 0;
virtual void close(Cookie *cookie) = 0;
//SHOULDDO can data be const?
virtual ReturnValue_t sendMessage(Cookie *cookie, uint8_t *data,
uint32_t len) = 0;
virtual ReturnValue_t getSendSuccess(Cookie *cookie) = 0;
virtual ReturnValue_t requestReceiveMessage(Cookie *cookie) = 0;
virtual ReturnValue_t readReceivedMessage(Cookie *cookie, uint8_t **buffer,
uint32_t *size) = 0;
virtual ReturnValue_t setAddress(Cookie *cookie, uint32_t address) = 0;
virtual uint32_t getAddress(Cookie *cookie) = 0;
virtual ReturnValue_t setParameter(Cookie *cookie, uint32_t parameter) = 0;
virtual uint32_t getParameter(Cookie *cookie) = 0;
/**
* Called by DHB in the GET_WRITE doGetRead().
* This function is used to receive data from the physical device
* by implementing and calling related drivers or wrapper functions.
* @param cookie
* @param buffer [out] Set reply here (by using *buffer = ...)
* @param size [out] size pointer to set (by using *size = ...).
* Set to 0 if no reply was received
* @return -@c RETURN_OK for successfull receive
* -@c NO_REPLY_RECEIVED if not reply was received. Setting size to
* 0 has the same effect
* - Everything else triggers failure event with
* returnvalue as parameter 1
*/
virtual ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **buffer,
size_t *size) = 0;
}; };
#endif /* DEVICECOMMUNICATIONIF_H_ */ #endif /* DEVICECOMMUNICATIONIF_H_ */

View File

@ -16,37 +16,33 @@ object_id_t DeviceHandlerBase::powerSwitcherId = 0;
object_id_t DeviceHandlerBase::rawDataReceiverId = 0; object_id_t DeviceHandlerBase::rawDataReceiverId = 0;
object_id_t DeviceHandlerBase::defaultFDIRParentId = 0; object_id_t DeviceHandlerBase::defaultFDIRParentId = 0;
DeviceHandlerBase::DeviceHandlerBase(uint32_t ioBoardAddress, DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication,
object_id_t setObjectId, uint32_t maxDeviceReplyLen, CookieIF * comCookie_, uint8_t setDeviceSwitch,
uint8_t setDeviceSwitch, object_id_t deviceCommunication,
uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId, uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId,
FailureIsolationBase* fdirInstance, uint32_t cmdQueueSize) : FailureIsolationBase* fdirInstance, size_t cmdQueueSize) :
SystemObject(setObjectId), rawPacket(0), rawPacketLen(0), mode( SystemObject(setObjectId), mode(MODE_OFF), submode(SUBMODE_NONE),
MODE_OFF), submode(SUBMODE_NONE), pstStep(0), maxDeviceReplyLen( wiretappingMode(OFF), storedRawData(StorageManagerIF::INVALID_ADDRESS),
maxDeviceReplyLen), wiretappingMode(OFF), defaultRawReceiver(0), storedRawData( deviceCommunicationId(deviceCommunication), comCookie(comCookie_),
StorageManagerIF::INVALID_ADDRESS), requestedRawTraffic(0), powerSwitcher( deviceThermalStatePoolId(thermalStatePoolId), deviceThermalRequestPoolId(thermalRequestPoolId),
NULL), IPCStore(NULL), deviceCommunicationId(deviceCommunication), communicationInterface( healthHelper(this, setObjectId), modeHelper(this), parameterHelper(this),
NULL), cookie( fdirInstance(fdirInstance), hkSwitcher(this),
NULL), commandQueue(NULL), deviceThermalStatePoolId(thermalStatePoolId), deviceThermalRequestPoolId( defaultFDIRUsed(fdirInstance == nullptr), switchOffWasReported(false),
thermalRequestPoolId), healthHelper(this, setObjectId), modeHelper( executingTask(nullptr), actionHelper(this, nullptr), cookieInfo(),
this), parameterHelper(this), childTransitionFailure(RETURN_OK), ignoreMissedRepliesCount( childTransitionDelay(5000), transitionSourceMode(_MODE_POWER_DOWN),
0), fdirInstance(fdirInstance), hkSwitcher(this), defaultFDIRUsed( transitionSourceSubMode(SUBMODE_NONE), deviceSwitch(setDeviceSwitch)
fdirInstance == NULL), switchOffWasReported(false),executingTask(NULL), actionHelper(this, NULL), cookieInfo(), ioBoardAddress( {
ioBoardAddress), timeoutStart(0), childTransitionDelay(5000), transitionSourceMode( commandQueue = QueueFactory::instance()->
_MODE_POWER_DOWN), transitionSourceSubMode(SUBMODE_NONE), deviceSwitch( createMessageQueue(cmdQueueSize, CommandMessage::MAX_MESSAGE_SIZE);
setDeviceSwitch) {
commandQueue = QueueFactory::instance()->createMessageQueue(cmdQueueSize,
CommandMessage::MAX_MESSAGE_SIZE);
cookieInfo.state = COOKIE_UNUSED; cookieInfo.state = COOKIE_UNUSED;
insertInCommandMap(RAW_COMMAND_ID); insertInCommandMap(RAW_COMMAND_ID);
if (this->fdirInstance == NULL) { if (this->fdirInstance == nullptr) {
this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId, this->fdirInstance =
defaultFDIRParentId); new DeviceHandlerFailureIsolation(setObjectId, defaultFDIRParentId);
} }
} }
DeviceHandlerBase::~DeviceHandlerBase() { DeviceHandlerBase::~DeviceHandlerBase() {
communicationInterface->close(cookie); delete comCookie;
if (defaultFDIRUsed) { if (defaultFDIRUsed) {
delete fdirInstance; delete fdirInstance;
} }
@ -55,7 +51,6 @@ DeviceHandlerBase::~DeviceHandlerBase() {
ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
this->pstStep = counter; this->pstStep = counter;
if (counter == 0) { if (counter == 0) {
cookieInfo.state = COOKIE_UNUSED; cookieInfo.state = COOKIE_UNUSED;
readCommandQueue(); readCommandQueue();
@ -64,11 +59,13 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
decrementDeviceReplyMap(); decrementDeviceReplyMap();
fdirInstance->checkForFailures(); fdirInstance->checkForFailures();
hkSwitcher.performOperation(); hkSwitcher.performOperation();
performOperationHook();
} }
if (mode == MODE_OFF) { if (mode == MODE_OFF) {
return RETURN_OK; return RETURN_OK;
} }
switch (getRmapAction()) {
switch (getComAction()) {
case SEND_WRITE: case SEND_WRITE:
if ((cookieInfo.state == COOKIE_UNUSED)) { if ((cookieInfo.state == COOKIE_UNUSED)) {
buildInternalCommand(); buildInternalCommand();
@ -88,6 +85,84 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
default: default:
break; break;
} }
return RETURN_OK;
}
ReturnValue_t DeviceHandlerBase::initialize() {
ReturnValue_t result = SystemObject::initialize();
if (result != RETURN_OK) {
return result;
}
communicationInterface = objectManager->get<DeviceCommunicationIF>(
deviceCommunicationId);
if (communicationInterface == NULL) {
return RETURN_FAILED;
}
result = communicationInterface->initializeInterface(comCookie);
if (result != RETURN_OK) {
return result;
}
IPCStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
if (IPCStore == NULL) {
return RETURN_FAILED;
}
AcceptsDeviceResponsesIF *rawReceiver = objectManager->get<
AcceptsDeviceResponsesIF>(rawDataReceiverId);
if (rawReceiver == NULL) {
return RETURN_FAILED;
}
defaultRawReceiver = rawReceiver->getDeviceQueue();
powerSwitcher = objectManager->get<PowerSwitchIF>(powerSwitcherId);
if (powerSwitcher == NULL) {
return RETURN_FAILED;
}
result = healthHelper.initialize();
if (result != RETURN_OK) {
return result;
}
result = modeHelper.initialize();
if (result != RETURN_OK) {
return result;
}
result = actionHelper.initialize(commandQueue);
if (result != RETURN_OK) {
return result;
}
result = fdirInstance->initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = parameterHelper.initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = hkSwitcher.initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
fillCommandAndReplyMap();
//Set temperature target state to NON_OP.
DataSet mySet;
PoolVariable<int8_t> thermalRequest(deviceThermalRequestPoolId, &mySet,
PoolVariableIF::VAR_WRITE);
mySet.read();
thermalRequest = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
mySet.commit(PoolVariableIF::VALID);
return RETURN_OK; return RETURN_OK;
} }
@ -256,55 +331,49 @@ ReturnValue_t DeviceHandlerBase::isModeCombinationValid(Mode_t mode,
} }
} }
ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap( ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(DeviceCommandId_t deviceCommand,
DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, uint16_t maxDelayCycles, size_t replyLen, uint8_t periodic,
uint8_t periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId) { bool hasDifferentReplyId, DeviceCommandId_t replyId) {
//No need to check, as we may try to insert multiple times. //No need to check, as we may try to insert multiple times.
insertInCommandMap(deviceCommand); insertInCommandMap(deviceCommand);
if (hasDifferentReplyId) { if (hasDifferentReplyId) {
return insertInReplyMap(replyId, maxDelayCycles, periodic); return insertInReplyMap(replyId, maxDelayCycles, replyLen, periodic);
} else { } else {
return insertInReplyMap(deviceCommand, maxDelayCycles, periodic); return insertInReplyMap(deviceCommand, maxDelayCycles, replyLen, periodic);
} }
} }
ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId, ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
uint16_t maxDelayCycles, uint8_t periodic) { uint16_t maxDelayCycles, size_t replyLen, uint8_t periodic) {
DeviceReplyInfo info; DeviceReplyInfo info;
info.maxDelayCycles = maxDelayCycles; info.maxDelayCycles = maxDelayCycles;
info.periodic = periodic; info.periodic = periodic;
info.delayCycles = 0; info.delayCycles = 0;
info.replyLen = replyLen;
info.command = deviceCommandMap.end(); info.command = deviceCommandMap.end();
std::pair<std::map<DeviceCommandId_t, DeviceReplyInfo>::iterator, bool> returnValue; std::pair<DeviceReplyIter, bool> result = deviceReplyMap.emplace(replyId, info);
returnValue = deviceReplyMap.insert( if (result.second) {
std::pair<DeviceCommandId_t, DeviceReplyInfo>(replyId, info));
if (returnValue.second) {
return RETURN_OK; return RETURN_OK;
} else { } else {
return RETURN_FAILED; return RETURN_FAILED;
} }
} }
ReturnValue_t DeviceHandlerBase::insertInCommandMap( ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceCommand) {
DeviceCommandId_t deviceCommand) {
DeviceCommandInfo info; DeviceCommandInfo info;
info.expectedReplies = 0; info.expectedReplies = 0;
info.isExecuting = false; info.isExecuting = false;
info.sendReplyTo = NO_COMMANDER; info.sendReplyTo = NO_COMMANDER;
std::pair<std::map<DeviceCommandId_t, DeviceCommandInfo>::iterator, bool> returnValue; std::pair<DeviceCommandIter, bool> result = deviceCommandMap.emplace(deviceCommand,info);
returnValue = deviceCommandMap.insert( if (result.second) {
std::pair<DeviceCommandId_t, DeviceCommandInfo>(deviceCommand,
info));
if (returnValue.second) {
return RETURN_OK; return RETURN_OK;
} else { } else {
return RETURN_FAILED; return RETURN_FAILED;
} }
} }
ReturnValue_t DeviceHandlerBase::updateReplyMapEntry( ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceReply,
DeviceCommandId_t deviceReply, uint16_t delayCycles, uint16_t delayCycles, uint16_t maxDelayCycles, uint8_t periodic) {
uint16_t maxDelayCycles, uint8_t periodic) {
std::map<DeviceCommandId_t, DeviceReplyInfo>::iterator iter = std::map<DeviceCommandId_t, DeviceReplyInfo>::iterator iter =
deviceReplyMap.find(deviceReply); deviceReplyMap.find(deviceReply);
if (iter == deviceReplyMap.end()) { if (iter == deviceReplyMap.end()) {
@ -416,7 +485,7 @@ void DeviceHandlerBase::replyToReply(DeviceReplyMap::iterator iter,
return; return;
} }
//Check if more replies are expected. If so, do nothing. //Check if more replies are expected. If so, do nothing.
DeviceCommandInfo* info = &(iter->second.command->second); DeviceCommandInfo * info = &(iter->second.command->second);
if (--info->expectedReplies == 0) { if (--info->expectedReplies == 0) {
//Check if it was transition or internal command. Don't send any replies in that case. //Check if it was transition or internal command. Don't send any replies in that case.
if (info->sendReplyTo != NO_COMMANDER) { if (info->sendReplyTo != NO_COMMANDER) {
@ -429,7 +498,7 @@ void DeviceHandlerBase::replyToReply(DeviceReplyMap::iterator iter,
void DeviceHandlerBase::doSendWrite() { void DeviceHandlerBase::doSendWrite() {
if (cookieInfo.state == COOKIE_WRITE_READY) { if (cookieInfo.state == COOKIE_WRITE_READY) {
ReturnValue_t result = communicationInterface->sendMessage(cookie, ReturnValue_t result = communicationInterface->sendMessage(comCookie,
rawPacket, rawPacketLen); rawPacket, rawPacketLen);
if (result == RETURN_OK) { if (result == RETURN_OK) {
@ -450,12 +519,13 @@ void DeviceHandlerBase::doGetWrite() {
return; return;
} }
cookieInfo.state = COOKIE_UNUSED; cookieInfo.state = COOKIE_UNUSED;
ReturnValue_t result = communicationInterface->getSendSuccess(cookie); ReturnValue_t result = communicationInterface->getSendSuccess(comCookie);
if (result == RETURN_OK) { if (result == RETURN_OK) {
if (wiretappingMode == RAW) { if (wiretappingMode == RAW) {
replyRawData(rawPacket, rawPacketLen, requestedRawTraffic, 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. //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); result = enableReplyInReplyMap(cookieInfo.pendingCommand);
} else { } else {
//always generate a failure event, so that FDIR knows what's up //always generate a failure event, so that FDIR knows what's up
@ -469,12 +539,25 @@ void DeviceHandlerBase::doGetWrite() {
} }
void DeviceHandlerBase::doSendRead() { void DeviceHandlerBase::doSendRead() {
ReturnValue_t result; ReturnValue_t result = RETURN_FAILED;
size_t requestLen = 0;
// If the device handler can only request replies after a command
// has been sent, there should be only one reply enabled and the
// correct reply length will be mapped.
for(DeviceReplyIter iter = deviceReplyMap.begin();
iter != deviceReplyMap.end();iter++)
{
if(iter->second.delayCycles != 0) {
requestLen = iter->second.replyLen;
break;
}
}
result = communicationInterface->requestReceiveMessage(cookie); result = communicationInterface->requestReceiveMessage(comCookie, requestLen);
if (result == RETURN_OK) { if (result == RETURN_OK) {
cookieInfo.state = COOKIE_READ_SENT; cookieInfo.state = COOKIE_READ_SENT;
} else { }
else {
triggerEvent(DEVICE_REQUESTING_REPLY_FAILED, result); triggerEvent(DEVICE_REQUESTING_REPLY_FAILED, result);
//We can't inform anyone, because we don't know which command was sent last. //We can't inform anyone, because we don't know which command was sent last.
//So, we need to wait for a timeout. //So, we need to wait for a timeout.
@ -485,10 +568,10 @@ void DeviceHandlerBase::doSendRead() {
} }
void DeviceHandlerBase::doGetRead() { void DeviceHandlerBase::doGetRead() {
uint32_t receivedDataLen; size_t receivedDataLen;
uint8_t *receivedData; uint8_t *receivedData;
DeviceCommandId_t foundId = 0xFFFFFFFF; DeviceCommandId_t foundId = 0xFFFFFFFF;
uint32_t foundLen = 0; size_t foundLen = 0;
ReturnValue_t result; ReturnValue_t result;
if (cookieInfo.state != COOKIE_READ_SENT) { if (cookieInfo.state != COOKIE_READ_SENT) {
@ -498,7 +581,7 @@ void DeviceHandlerBase::doGetRead() {
cookieInfo.state = COOKIE_UNUSED; cookieInfo.state = COOKIE_UNUSED;
result = communicationInterface->readReceivedMessage(cookie, &receivedData, result = communicationInterface->readReceivedMessage(comCookie, &receivedData,
&receivedDataLen); &receivedDataLen);
if (result != RETURN_OK) { if (result != RETURN_OK) {
@ -508,7 +591,7 @@ void DeviceHandlerBase::doGetRead() {
return; return;
} }
if (receivedDataLen == 0) if (receivedDataLen == 0 or result == DeviceCommunicationIF::NO_REPLY_RECEIVED)
return; return;
if (wiretappingMode == RAW) { if (wiretappingMode == RAW) {
@ -539,6 +622,8 @@ void DeviceHandlerBase::doGetRead() {
break; break;
case IGNORE_REPLY_DATA: case IGNORE_REPLY_DATA:
break; break;
case IGNORE_FULL_PACKET:
return;
default: default:
//We need to wait for timeout.. don't know what command failed and who sent it. //We need to wait for timeout.. don't know what command failed and who sent it.
replyRawReplyIfnotWiretapped(receivedData, foundLen); replyRawReplyIfnotWiretapped(receivedData, foundLen);
@ -557,8 +642,8 @@ void DeviceHandlerBase::doGetRead() {
} }
ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress, ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress,
uint8_t * *data, uint32_t * len) { uint8_t ** data, size_t * len) {
uint32_t lenTmp; size_t lenTmp;
if (IPCStore == NULL) { if (IPCStore == NULL) {
*data = NULL; *data = NULL;
@ -579,84 +664,6 @@ ReturnValue_t DeviceHandlerBase::getStorageData(store_address_t storageAddress,
} }
ReturnValue_t DeviceHandlerBase::initialize() {
ReturnValue_t result = SystemObject::initialize();
if (result != RETURN_OK) {
return result;
}
communicationInterface = objectManager->get<DeviceCommunicationIF>(
deviceCommunicationId);
if (communicationInterface == NULL) {
return RETURN_FAILED;
}
result = communicationInterface->open(&cookie, ioBoardAddress,
maxDeviceReplyLen);
if (result != RETURN_OK) {
return result;
}
IPCStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
if (IPCStore == NULL) {
return RETURN_FAILED;
}
AcceptsDeviceResponsesIF *rawReceiver = objectManager->get<
AcceptsDeviceResponsesIF>(rawDataReceiverId);
if (rawReceiver == NULL) {
return RETURN_FAILED;
}
defaultRawReceiver = rawReceiver->getDeviceQueue();
powerSwitcher = objectManager->get<PowerSwitchIF>(powerSwitcherId);
if (powerSwitcher == NULL) {
return RETURN_FAILED;
}
result = healthHelper.initialize();
if (result != RETURN_OK) {
return result;
}
result = modeHelper.initialize();
if (result != RETURN_OK) {
return result;
}
result = actionHelper.initialize(commandQueue);
if (result != RETURN_OK) {
return result;
}
result = fdirInstance->initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = parameterHelper.initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = hkSwitcher.initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
fillCommandAndReplyMap();
//Set temperature target state to NON_OP.
DataSet mySet;
PoolVariable<int8_t> thermalRequest(deviceThermalRequestPoolId, &mySet,
PoolVariableIF::VAR_WRITE);
mySet.read();
thermalRequest = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
mySet.commit(PoolVariableIF::VALID);
return RETURN_OK;
}
void DeviceHandlerBase::replyRawData(const uint8_t *data, size_t len, void DeviceHandlerBase::replyRawData(const uint8_t *data, size_t len,
MessageQueueId_t sendTo, bool isCommand) { MessageQueueId_t sendTo, bool isCommand) {
@ -672,7 +679,6 @@ void DeviceHandlerBase::replyRawData(const uint8_t *data, size_t len,
} }
CommandMessage message; CommandMessage message;
DeviceHandlerMessage::setDeviceHandlerRawReplyMessage(&message, DeviceHandlerMessage::setDeviceHandlerRawReplyMessage(&message,
getObjectId(), address, isCommand); getObjectId(), address, isCommand);
@ -688,7 +694,7 @@ void DeviceHandlerBase::replyRawData(const uint8_t *data, size_t len,
//Default child implementations //Default child implementations
DeviceHandlerBase::RmapAction_t DeviceHandlerBase::getRmapAction() { DeviceHandlerBase::CommunicationAction_t DeviceHandlerBase::getComAction() {
switch (pstStep) { switch (pstStep) {
case 0: case 0:
return SEND_WRITE; return SEND_WRITE;
@ -748,20 +754,20 @@ void DeviceHandlerBase::handleReply(const uint8_t* receivedData,
} }
} }
ReturnValue_t DeviceHandlerBase::switchCookieChannel(object_id_t newChannelId) { //ReturnValue_t DeviceHandlerBase::switchCookieChannel(object_id_t newChannelId) {
DeviceCommunicationIF *newCommunication = objectManager->get< // DeviceCommunicationIF *newCommunication = objectManager->get<
DeviceCommunicationIF>(newChannelId); // DeviceCommunicationIF>(newChannelId);
//
if (newCommunication != NULL) { // if (newCommunication != NULL) {
ReturnValue_t result = newCommunication->reOpen(cookie, ioBoardAddress, // ReturnValue_t result = newCommunication->reOpen(cookie, logicalAddress,
maxDeviceReplyLen); // maxDeviceReplyLen, comParameter1, comParameter2);
if (result != RETURN_OK) { // if (result != RETURN_OK) {
return result; // return result;
} // }
return RETURN_OK; // return RETURN_OK;
} // }
return RETURN_FAILED; // return RETURN_FAILED;
} //}
void DeviceHandlerBase::buildRawDeviceCommand(CommandMessage* commandMessage) { void DeviceHandlerBase::buildRawDeviceCommand(CommandMessage* commandMessage) {
storedRawData = DeviceHandlerMessage::getStoreAddress(commandMessage); storedRawData = DeviceHandlerMessage::getStoreAddress(commandMessage);
@ -771,8 +777,8 @@ void DeviceHandlerBase::buildRawDeviceCommand(CommandMessage* commandMessage) {
replyReturnvalueToCommand(result, RAW_COMMAND_ID); replyReturnvalueToCommand(result, RAW_COMMAND_ID);
storedRawData.raw = StorageManagerIF::INVALID_ADDRESS; storedRawData.raw = StorageManagerIF::INVALID_ADDRESS;
} else { } else {
cookieInfo.pendingCommand = deviceCommandMap.find( cookieInfo.pendingCommand = deviceCommandMap.
(DeviceCommandId_t) RAW_COMMAND_ID); find((DeviceCommandId_t) RAW_COMMAND_ID);
cookieInfo.pendingCommand->second.isExecuting = true; cookieInfo.pendingCommand->second.isExecuting = true;
cookieInfo.state = COOKIE_WRITE_READY; cookieInfo.state = COOKIE_WRITE_READY;
} }
@ -811,7 +817,7 @@ ReturnValue_t DeviceHandlerBase::enableReplyInReplyMap(
iter = deviceReplyMap.find(command->first); iter = deviceReplyMap.find(command->first);
} }
if (iter != deviceReplyMap.end()) { if (iter != deviceReplyMap.end()) {
DeviceReplyInfo *info = &(iter->second); DeviceReplyInfo * info = &(iter->second);
info->delayCycles = info->maxDelayCycles; info->delayCycles = info->maxDelayCycles;
info->command = command; info->command = command;
command->second.expectedReplies = expectedReplies; command->second.expectedReplies = expectedReplies;
@ -837,8 +843,9 @@ ReturnValue_t DeviceHandlerBase::getStateOfSwitches(void) {
ReturnValue_t result = getSwitches(&switches, &numberOfSwitches); ReturnValue_t result = getSwitches(&switches, &numberOfSwitches);
if ((result == RETURN_OK) && (numberOfSwitches != 0)) { if ((result == RETURN_OK) && (numberOfSwitches != 0)) {
while (numberOfSwitches > 0) { while (numberOfSwitches > 0) {
if (powerSwitcher->getSwitchState(switches[numberOfSwitches - 1]) if (powerSwitcher-> getSwitchState(switches[numberOfSwitches - 1])
== PowerSwitchIF::SWITCH_OFF) { == PowerSwitchIF::SWITCH_OFF)
{
return PowerSwitchIF::SWITCH_OFF; return PowerSwitchIF::SWITCH_OFF;
} }
numberOfSwitches--; numberOfSwitches--;
@ -1044,16 +1051,18 @@ ReturnValue_t DeviceHandlerBase::handleDeviceHandlerMessage(
} }
replyReturnvalueToCommand(RETURN_OK); replyReturnvalueToCommand(RETURN_OK);
return RETURN_OK; return RETURN_OK;
case DeviceHandlerMessage::CMD_SWITCH_IOBOARD: case DeviceHandlerMessage::CMD_SWITCH_ADDRESS:
if (mode != MODE_OFF) { if (mode != MODE_OFF) {
replyReturnvalueToCommand(WRONG_MODE_FOR_COMMAND); replyReturnvalueToCommand(WRONG_MODE_FOR_COMMAND);
} else { } else {
result = switchCookieChannel( // rework in progress
DeviceHandlerMessage::getIoBoardObjectId(message)); result = RETURN_OK;
//result = switchCookieChannel(
// DeviceHandlerMessage::getIoBoardObjectId(message));
if (result == RETURN_OK) { if (result == RETURN_OK) {
replyReturnvalueToCommand(RETURN_OK); replyReturnvalueToCommand(RETURN_OK);
} else { } else {
replyReturnvalueToCommand(CANT_SWITCH_IOBOARD); replyReturnvalueToCommand(CANT_SWITCH_ADDRESS);
} }
} }
return RETURN_OK; return RETURN_OK;
@ -1112,8 +1121,7 @@ void DeviceHandlerBase::handleDeviceTM(SerializeIF* data,
// hiding of sender needed so the service will handle it as unexpected Data, no matter what state // hiding of sender needed so the service will handle it as unexpected Data, no matter what state
//(progress or completed) it is in //(progress or completed) it is in
actionHelper.reportData(defaultRawReceiver, replyId, &wrapper, actionHelper.reportData(defaultRawReceiver, replyId, &wrapper, true);
true);
} }
} else { //unrequested/aperiodic replies } else { //unrequested/aperiodic replies
@ -1136,11 +1144,12 @@ void DeviceHandlerBase::handleDeviceTM(SerializeIF* data,
} }
ReturnValue_t DeviceHandlerBase::executeAction(ActionId_t actionId, ReturnValue_t DeviceHandlerBase::executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t* data, uint32_t size) { MessageQueueId_t commandedBy, const uint8_t* data, size_t size) {
ReturnValue_t result = acceptExternalDeviceCommands(); ReturnValue_t result = acceptExternalDeviceCommands();
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
DeviceCommandMap::iterator iter = deviceCommandMap.find(actionId); DeviceCommandMap::iterator iter = deviceCommandMap.find(actionId);
if (iter == deviceCommandMap.end()) { if (iter == deviceCommandMap.end()) {
result = COMMAND_NOT_SUPPORTED; result = COMMAND_NOT_SUPPORTED;
@ -1159,7 +1168,7 @@ ReturnValue_t DeviceHandlerBase::executeAction(ActionId_t actionId,
} }
void DeviceHandlerBase::buildInternalCommand(void) { void DeviceHandlerBase::buildInternalCommand(void) {
//Neither Raw nor Direct could build a command // Neither Raw nor Direct could build a command
ReturnValue_t result = NOTHING_TO_SEND; ReturnValue_t result = NOTHING_TO_SEND;
DeviceCommandId_t deviceCommandId = NO_COMMAND_ID; DeviceCommandId_t deviceCommandId = NO_COMMAND_ID;
if (mode == MODE_NORMAL) { if (mode == MODE_NORMAL) {
@ -1177,12 +1186,13 @@ void DeviceHandlerBase::buildInternalCommand(void) {
} else { } else {
return; return;
} }
if (result == NOTHING_TO_SEND) { if (result == NOTHING_TO_SEND) {
return; return;
} }
if (result == RETURN_OK) { if (result == RETURN_OK) {
DeviceCommandMap::iterator iter = deviceCommandMap.find( DeviceCommandMap::iterator iter =
deviceCommandId); deviceCommandMap.find(deviceCommandId);
if (iter == deviceCommandMap.end()) { if (iter == deviceCommandMap.end()) {
result = COMMAND_NOT_SUPPORTED; result = COMMAND_NOT_SUPPORTED;
} else if (iter->second.isExecuting) { } else if (iter->second.isExecuting) {
@ -1197,6 +1207,7 @@ void DeviceHandlerBase::buildInternalCommand(void) {
cookieInfo.state = COOKIE_WRITE_READY; cookieInfo.state = COOKIE_WRITE_READY;
} }
} }
if (result != RETURN_OK) { if (result != RETURN_OK) {
triggerEvent(DEVICE_BUILDING_COMMAND_FAILED, result, deviceCommandId); triggerEvent(DEVICE_BUILDING_COMMAND_FAILED, result, deviceCommandId);
} }
@ -1270,3 +1281,9 @@ void DeviceHandlerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {
void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task_){ void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task_){
executingTask = task_; executingTask = task_;
} }
void DeviceHandlerBase::debugInterface(uint8_t positionTracker, object_id_t objectId, uint32_t parameter) {
}
void DeviceHandlerBase::performOperationHook() {
}

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,8 @@
#include <framework/ipc/MessageQueueSenderIF.h> #include <framework/ipc/MessageQueueSenderIF.h>
/** /**
* This is the Interface used to communicate with a device handler. * @brief This is the Interface used to communicate with a device handler.
* @details Includes all expected return values, events and modes.
* *
*/ */
class DeviceHandlerIF { class DeviceHandlerIF {
@ -22,15 +23,17 @@ public:
* *
* @details The mode of the device handler must not be confused with the mode the device is in. * @details The mode of the device handler must not be confused with the mode the device is in.
* The mode of the device itself is transparent to the user but related to the mode of the handler. * The mode of the device itself is transparent to the user but related to the mode of the handler.
* MODE_ON and MODE_OFF are included in hasModesIF.h
*/ */
// MODE_ON = 0, //!< The device is powered and ready to perform operations. In this mode, no commands are sent by the device handler itself, but direct commands van be commanded and will be interpreted
// MODE_OFF = 1, //!< The device is powered off. The only command accepted in this mode is a mode change to on. // MODE_ON = 0, //!< The device is powered and ready to perform operations. In this mode, no commands are sent by the device handler itself, but direct commands van be commanded and will be interpreted
// MODE_OFF = 1, //!< The device is powered off. The only command accepted in this mode is a mode change to on.
static const Mode_t MODE_NORMAL = 2; //!< The device is powered on and the device handler periodically sends commands. The commands to be sent are selected by the handler according to the submode. static const Mode_t MODE_NORMAL = 2; //!< The device is powered on and the device handler periodically sends commands. The commands to be sent are selected by the handler according to the submode.
static const Mode_t MODE_RAW = 3; //!< The device is powered on and ready to perform operations. In this mode, raw commands can be sent. The device handler will send all replies received from the command back to the commanding object. static const Mode_t MODE_RAW = 3; //!< The device is powered on and ready to perform operations. In this mode, raw commands can be sent. The device handler will send all replies received from the command back to the commanding object.
static const Mode_t MODE_ERROR_ON = 4; //!4< The device is shut down but the switch could not be turned off, so the device still is powered. In this mode, only a mode change to @c MODE_OFF can be commanded, which tries to switch off the device again. static const Mode_t MODE_ERROR_ON = 4; //!4< The device is shut down but the switch could not be turned off, so the device still is powered. In this mode, only a mode change to @c MODE_OFF can be commanded, which tries to switch off the device again.
static const Mode_t _MODE_START_UP = TRANSITION_MODE_CHILD_ACTION_MASK | 5; //!< This is a transitional state which can not be commanded. The device handler performs all commands to get the device in a state ready to perform commands. When this is completed, the mode changes to @c MODE_ON. static const Mode_t _MODE_START_UP = TRANSITION_MODE_CHILD_ACTION_MASK | 5; //!< This is a transitional state which can not be commanded. The device handler performs all commands to get the device in a state ready to perform commands. When this is completed, the mode changes to @c MODE_ON.
static const Mode_t _MODE_SHUT_DOWN = TRANSITION_MODE_CHILD_ACTION_MASK | 6; //!< This is a transitional state which can not be commanded. The device handler performs all actions and commands to get the device shut down. When the device is off, the mode changes to @c MODE_OFF. static const Mode_t _MODE_SHUT_DOWN = TRANSITION_MODE_CHILD_ACTION_MASK | 6; //!< This is a transitional state which can not be commanded. The device handler performs all actions and commands to get the device shut down. When the device is off, the mode changes to @c MODE_OFF.
static const Mode_t _MODE_TO_ON = TRANSITION_MODE_CHILD_ACTION_MASK | HasModesIF::MODE_ON; static const Mode_t _MODE_TO_ON = TRANSITION_MODE_CHILD_ACTION_MASK | HasModesIF::MODE_ON; //!< It is possible to set the mode to _MODE_TO_ON to use the to on transition if available.
static const Mode_t _MODE_TO_RAW = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_RAW; static const Mode_t _MODE_TO_RAW = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_RAW;
static const Mode_t _MODE_TO_NORMAL = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_NORMAL; static const Mode_t _MODE_TO_NORMAL = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_NORMAL;
static const Mode_t _MODE_POWER_DOWN = TRANSITION_MODE_BASE_ACTION_MASK | 1; //!< This is a transitional state which can not be commanded. The device is shut down and ready to be switched off. After the command to set the switch off has been sent, the mode changes to @c MODE_WAIT_OFF static const Mode_t _MODE_POWER_DOWN = TRANSITION_MODE_BASE_ACTION_MASK | 1; //!< This is a transitional state which can not be commanded. The device is shut down and ready to be switched off. After the command to set the switch off has been sent, the mode changes to @c MODE_WAIT_OFF
@ -53,49 +56,62 @@ public:
static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, SEVERITY::HIGH); static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, SEVERITY::HIGH);
static const uint8_t INTERFACE_ID = CLASS_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);
static const ReturnValue_t COMMAND_WAS_NOT_SENT = MAKE_RETURN_CODE(0xA3);
static const ReturnValue_t CANT_SWITCH_IOBOARD = MAKE_RETURN_CODE(0xA4);
static const ReturnValue_t WRONG_MODE_FOR_COMMAND = MAKE_RETURN_CODE(0xA5);
static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE(0xA6);
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 // Standard codes used when building commands.
// static const ReturnValue_t TOO_SHORT = MAKE_RETURN_CODE(0xB1); static const ReturnValue_t NOTHING_TO_SEND = MAKE_RETURN_CODE(0xA0); //!< Return this if no command sending in required
static const ReturnValue_t CHECKSUM_ERROR = MAKE_RETURN_CODE(0xB2); // Mostly used for internal handling.
static const ReturnValue_t LENGTH_MISSMATCH = MAKE_RETURN_CODE(0xB3); static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA2); //!< If the command size is 0. Checked in DHB
static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(0xB4); static const ReturnValue_t NO_REPLY_EXPECTED = MAKE_RETURN_CODE(0xA3); //!< Used to indicate that this is a command-only command.
static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0xB5); static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA4); //!< Command ID not in commandMap. Checked in DHB
static const ReturnValue_t COMMAND_ALREADY_SENT = MAKE_RETURN_CODE(0xA5); //!< Command was already executed. Checked in DHB
static const ReturnValue_t COMMAND_WAS_NOT_SENT = MAKE_RETURN_CODE(0xA6);
static const ReturnValue_t CANT_SWITCH_ADDRESS = MAKE_RETURN_CODE(0xA7);
static const ReturnValue_t WRONG_MODE_FOR_COMMAND = MAKE_RETURN_CODE(0xA8);
static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE(0xA9);
static const ReturnValue_t BUSY = MAKE_RETURN_CODE(0xAA);
static const ReturnValue_t NON_OP_TEMPERATURE = MAKE_RETURN_CODE(0xAB);
static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xAC);
//standard codes used in interpret device reply // Standard codes used in scanForReply
static const ReturnValue_t APERIODIC_REPLY = MAKE_RETURN_CODE(0xB1); //!< This is used to specify for replies from a device which are not replies to requests
static const ReturnValue_t LENGTH_MISSMATCH = MAKE_RETURN_CODE(0xB2);
static const ReturnValue_t IGNORE_REPLY_DATA = MAKE_RETURN_CODE(0xB3); //!< Ignore parts of the received packet
static const ReturnValue_t IGNORE_FULL_PACKET = MAKE_RETURN_CODE(0xB4); //!< Ignore full received packet
static const ReturnValue_t CHECKSUM_ERROR = MAKE_RETURN_CODE(0xB5);
static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(0xB6);
static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0xB7);
// Standard codes used in interpretDeviceReply
static const ReturnValue_t DEVICE_DID_NOT_EXECUTE = MAKE_RETURN_CODE(0xC1); //the device reported, that it did not execute the command static const ReturnValue_t DEVICE_DID_NOT_EXECUTE = MAKE_RETURN_CODE(0xC1); //the device reported, that it did not execute the command
static const ReturnValue_t DEVICE_REPORTED_ERROR = MAKE_RETURN_CODE(0xC2); static const ReturnValue_t DEVICE_REPORTED_ERROR = MAKE_RETURN_CODE(0xC2);
static const ReturnValue_t UNKNOW_DEVICE_REPLY = MAKE_RETURN_CODE(0xC3); //the deviceCommandId reported by scanforReply is unknown static const ReturnValue_t UNKNOW_DEVICE_REPLY = MAKE_RETURN_CODE(0xC3); //the deviceCommandId reported by scanforReply is unknown
static const ReturnValue_t DEVICE_REPLY_INVALID = MAKE_RETURN_CODE(0xC4); //syntax etc is correct but still not ok, eg parameters where none are expected static const ReturnValue_t DEVICE_REPLY_INVALID = MAKE_RETURN_CODE(0xC4); //syntax etc is correct but still not ok, eg parameters where none are expected
//Standard codes used in buildCommandFromCommand // Standard codes used in buildCommandFromCommand
static const ReturnValue_t INVALID_COMMAND_PARAMETER = MAKE_RETURN_CODE( static const ReturnValue_t INVALID_COMMAND_PARAMETER = MAKE_RETURN_CODE(0xD0);
0xD0); static const ReturnValue_t INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS = MAKE_RETURN_CODE(0xD1);
static const ReturnValue_t INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS =
MAKE_RETURN_CODE(0xD1); // Standard codes used in getSwitches
static const ReturnValue_t NO_SWITCH = MAKE_RETURN_CODE(0xE1); //!< Return in getSwitches() to specify there are no switches
// static const ReturnValue_t ONE_SWITCH = MAKE_RETURN_CODE(8);
// static const ReturnValue_t TWO_SWITCHES = MAKE_RETURN_CODE(9);
// where is this used?
// static const ReturnValue_t COMMAND_MAP_ERROR = MAKE_RETURN_CODE(11);
/** /**
* RMAP Action that will be executed. * Communication action that will be executed.
* *
* This is used by the child class to tell the base class what to do. * This is used by the child class to tell the base class what to do.
*/ */
enum RmapAction_t { enum CommunicationAction_t: uint8_t {
SEND_WRITE,//!< RMAP send write SEND_WRITE,//!< Send write
GET_WRITE, //!< RMAP get write GET_WRITE, //!< Get write
SEND_READ, //!< RMAP send read SEND_READ, //!< Send read
GET_READ, //!< RMAP get read GET_READ, //!< Get read
NOTHING //!< Do nothing. NOTHING //!< Do nothing.
}; };
/** /**
* Default Destructor * Default Destructor
*/ */

View File

@ -47,7 +47,7 @@ void DeviceHandlerMessage::setDeviceHandlerWiretappingMessage(
void DeviceHandlerMessage::setDeviceHandlerSwitchIoBoardMessage( void DeviceHandlerMessage::setDeviceHandlerSwitchIoBoardMessage(
CommandMessage* message, uint32_t ioBoardIdentifier) { CommandMessage* message, uint32_t ioBoardIdentifier) {
message->setCommand(CMD_SWITCH_IOBOARD); message->setCommand(CMD_SWITCH_ADDRESS);
message->setParameter(ioBoardIdentifier); message->setParameter(ioBoardIdentifier);
} }
@ -90,7 +90,7 @@ void DeviceHandlerMessage::clear(CommandMessage* message) {
} }
} }
/* NO BREAK falls through*/ /* NO BREAK falls through*/
case CMD_SWITCH_IOBOARD: case CMD_SWITCH_ADDRESS:
case CMD_WIRETAPPING: case CMD_WIRETAPPING:
message->setCommand(CommandMessage::CMD_NONE); message->setCommand(CommandMessage::CMD_NONE);
message->setParameter(0); message->setParameter(0);

View File

@ -28,7 +28,7 @@ public:
static const uint8_t MESSAGE_ID = MESSAGE_TYPE::DEVICE_HANDLER_COMMAND; 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_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_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 static const Command_t CMD_SWITCH_ADDRESS = MAKE_COMMAND_ID( 3 ); //!< Requests a IO-Board switch, setParameter() is the IO-Board identifier
static const Command_t CMD_WIRETAPPING = MAKE_COMMAND_ID( 4 ); //!< (De)Activates the monitoring of all raw traffic in DeviceHandlers, setParameter is 0 to deactivate, 1 to activate static const Command_t CMD_WIRETAPPING = MAKE_COMMAND_ID( 4 ); //!< (De)Activates the monitoring of all raw traffic in DeviceHandlers, setParameter is 0 to deactivate, 1 to activate
/*static const Command_t REPLY_SWITCHED_IOBOARD = MAKE_COMMAND_ID(1 );//!< Reply to a @c CMD_SWITCH_IOBOARD, indicates switch was successful, getParameter() contains the board switched to (0: nominal, 1: redundant) /*static const Command_t REPLY_SWITCHED_IOBOARD = MAKE_COMMAND_ID(1 );//!< Reply to a @c CMD_SWITCH_IOBOARD, indicates switch was successful, getParameter() contains the board switched to (0: nominal, 1: redundant)

View File

@ -12,7 +12,7 @@ DeviceTmReportingWrapper::~DeviceTmReportingWrapper() {
} }
ReturnValue_t DeviceTmReportingWrapper::serialize(uint8_t** buffer, ReturnValue_t DeviceTmReportingWrapper::serialize(uint8_t** buffer,
uint32_t* size, const uint32_t max_size, bool bigEndian) const { size_t* size, const size_t max_size, bool bigEndian) const {
ReturnValue_t result = SerializeAdapter<object_id_t>::serialize(&objectId, ReturnValue_t result = SerializeAdapter<object_id_t>::serialize(&objectId,
buffer, size, max_size, bigEndian); buffer, size, max_size, bigEndian);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
@ -26,12 +26,12 @@ ReturnValue_t DeviceTmReportingWrapper::serialize(uint8_t** buffer,
return data->serialize(buffer, size, max_size, bigEndian); return data->serialize(buffer, size, max_size, bigEndian);
} }
uint32_t DeviceTmReportingWrapper::getSerializedSize() const { size_t DeviceTmReportingWrapper::getSerializedSize() const {
return sizeof(objectId) + sizeof(ActionId_t) + data->getSerializedSize(); return sizeof(objectId) + sizeof(ActionId_t) + data->getSerializedSize();
} }
ReturnValue_t DeviceTmReportingWrapper::deSerialize(const uint8_t** buffer, ReturnValue_t DeviceTmReportingWrapper::deSerialize(const uint8_t** buffer,
int32_t* size, bool bigEndian) { ssize_t* size, bool bigEndian) {
ReturnValue_t result = SerializeAdapter<object_id_t>::deSerialize(&objectId, ReturnValue_t result = SerializeAdapter<object_id_t>::deSerialize(&objectId,
buffer, size, bigEndian); buffer, size, bigEndian);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {

View File

@ -11,12 +11,12 @@ public:
SerializeIF *data); SerializeIF *data);
virtual ~DeviceTmReportingWrapper(); virtual ~DeviceTmReportingWrapper();
virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
const uint32_t max_size, bool bigEndian) const; const size_t max_size, bool bigEndian) const;
virtual uint32_t getSerializedSize() const; virtual size_t getSerializedSize() const;
virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size,
bool bigEndian); bool bigEndian);
private: private:
object_id_t objectId; object_id_t objectId;

View File

@ -19,29 +19,34 @@ class PeriodicTaskIF;
*/ */
class FixedSequenceSlot { class FixedSequenceSlot {
public: public:
FixedSequenceSlot( object_id_t handlerId, uint32_t setTimeMs, int8_t setSequenceId, PeriodicTaskIF* executingTask ); FixedSequenceSlot( object_id_t handlerId, uint32_t setTimeMs,
int8_t setSequenceId, PeriodicTaskIF* executingTask );
virtual ~FixedSequenceSlot(); virtual ~FixedSequenceSlot();
/** /**
* \brief \c handler identifies which device handler object is executed in this slot. * @brief Handler identifies which device handler object is executed in this slot.
*/ */
ExecutableObjectIF* handler; ExecutableObjectIF* handler;
/** /**
* \brief This attribute defines when a device handler object is executed. * @brief This attribute defines when a device handler object is executed.
* *
* \details The pollingTime attribute identifies the time the handler is executed in ms. It must be * @details The pollingTime attribute identifies the time the handler is executed in ms.
* smaller than the period length of the polling sequence, what is ensured by automated calculation * It must be smaller than the period length of the polling sequence.
* from a database.
*/ */
uint32_t pollingTimeMs; uint32_t pollingTimeMs;
/** /**
* \brief This value defines the type of device communication. * \brief This value defines the type of device communication.
* *
* \details The state of this value decides what communication routine is called in the PST executable or the device handler object. * \details The state of this value decides what communication routine is
* called in the PST executable or the device handler object.
*/ */
uint8_t opcode; uint8_t opcode;
bool operator <(const FixedSequenceSlot & fixedSequenceSlot) const {
return pollingTimeMs < fixedSequenceSlot.pollingTimeMs;
}
}; };

View File

@ -2,22 +2,23 @@
#include <framework/serviceinterface/ServiceInterfaceStream.h> #include <framework/serviceinterface/ServiceInterfaceStream.h>
FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) : FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) :
lengthMs(setLengthMs) { slotLengthMs(setLengthMs) {
current = slotList.begin(); current = slotList.begin();
} }
FixedSlotSequence::~FixedSlotSequence() { FixedSlotSequence::~FixedSlotSequence() {
std::list<FixedSequenceSlot*>::iterator slotIt; // This should call the destructor on each list entry.
//Iterate through slotList and delete all entries. slotList.clear();
slotIt = this->slotList.begin(); // SlotListIter slotListIter = this->slotList.begin();
while (slotIt != this->slotList.end()) { // //Iterate through slotList and delete all entries.
delete (*slotIt); // while (slotListIter != this->slotList.end()) {
slotIt++; // delete (*slotIt);
} // slotIt++;
// }
} }
void FixedSlotSequence::executeAndAdvance() { void FixedSlotSequence::executeAndAdvance() {
(*this->current)->handler->performOperation((*this->current)->opcode); current->handler->performOperation(current->opcode);
// if (returnValue != RETURN_OK) { // if (returnValue != RETURN_OK) {
// this->sendErrorMessage( returnValue ); // this->sendErrorMessage( returnValue );
// } // }
@ -31,53 +32,50 @@ void FixedSlotSequence::executeAndAdvance() {
uint32_t FixedSlotSequence::getIntervalToNextSlotMs() { uint32_t FixedSlotSequence::getIntervalToNextSlotMs() {
uint32_t oldTime; uint32_t oldTime;
std::list<FixedSequenceSlot*>::iterator it; SlotListIter slotListIter = current;
it = current;
// Get the pollingTimeMs of the current slot object. // Get the pollingTimeMs of the current slot object.
oldTime = (*it)->pollingTimeMs; oldTime = slotListIter->pollingTimeMs;
// Advance to the next object. // Advance to the next object.
it++; slotListIter++;
// Find the next interval which is not 0. // Find the next interval which is not 0.
while (it != slotList.end()) { while (slotListIter != slotList.end()) {
if (oldTime != (*it)->pollingTimeMs) { if (oldTime != slotListIter->pollingTimeMs) {
return (*it)->pollingTimeMs - oldTime; return slotListIter->pollingTimeMs - oldTime;
} else { } else {
it++; slotListIter++;
} }
} }
// If the list end is reached (this is definitely an interval != 0), // If the list end is reached (this is definitely an interval != 0),
// the interval is calculated by subtracting the remaining time of the PST // the interval is calculated by subtracting the remaining time of the PST
// and adding the start time of the first handler in the list. // and adding the start time of the first handler in the list.
it = slotList.begin(); slotListIter = slotList.begin();
return lengthMs - oldTime + (*it)->pollingTimeMs; return slotLengthMs - oldTime + slotListIter->pollingTimeMs;
} }
uint32_t FixedSlotSequence::getIntervalToPreviousSlotMs() { uint32_t FixedSlotSequence::getIntervalToPreviousSlotMs() {
uint32_t currentTime; uint32_t currentTime;
std::list<FixedSequenceSlot*>::iterator it; SlotListIter slotListIter = current;
it = current;
// Get the pollingTimeMs of the current slot object. // Get the pollingTimeMs of the current slot object.
currentTime = (*it)->pollingTimeMs; currentTime = slotListIter->pollingTimeMs;
//if it is the first slot, calculate difference to last slot //if it is the first slot, calculate difference to last slot
if (it == slotList.begin()){ if (slotListIter == slotList.begin()){
return lengthMs - (*(--slotList.end()))->pollingTimeMs + currentTime; return slotLengthMs - (--slotList.end())->pollingTimeMs + currentTime;
} }
// get previous slot // get previous slot
it--; slotListIter--;
return currentTime - (*it)->pollingTimeMs; return currentTime - slotListIter->pollingTimeMs;
} }
bool FixedSlotSequence::slotFollowsImmediately() { bool FixedSlotSequence::slotFollowsImmediately() {
uint32_t currentTime = (*current)->pollingTimeMs; uint32_t currentTime = current->pollingTimeMs;
std::list<FixedSequenceSlot*>::iterator it; SlotListIter fixedSequenceIter = this->current;
it = this->current;
// Get the pollingTimeMs of the current slot object. // Get the pollingTimeMs of the current slot object.
if (it == slotList.begin()) if (fixedSequenceIter == slotList.begin())
return false; return false;
it--; fixedSequenceIter--;
if ((*it)->pollingTimeMs == currentTime) { if (fixedSequenceIter->pollingTimeMs == currentTime) {
return true; return true;
} else { } else {
return false; return false;
@ -85,31 +83,35 @@ bool FixedSlotSequence::slotFollowsImmediately() {
} }
uint32_t FixedSlotSequence::getLengthMs() const { uint32_t FixedSlotSequence::getLengthMs() const {
return this->lengthMs; return this->slotLengthMs;
} }
ReturnValue_t FixedSlotSequence::checkSequence() const { 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. // 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(); auto slotIt = slotList.begin();
uint32_t count = 0; uint32_t count = 0;
uint32_t time = 0; uint32_t time = 0;
while (slotIt != slotList.end()) { while (slotIt != slotList.end()) {
if ((*slotIt)->handler == NULL) { if (slotIt->handler == NULL) {
error << "FixedSlotSequene::initialize: ObjectId does not exist!" error << "FixedSlotSequene::initialize: ObjectId does not exist!"
<< std::endl; << std::endl;
count++; count++;
} else if ((*slotIt)->pollingTimeMs < time) { } else if (slotIt->pollingTimeMs < time) {
error << "FixedSlotSequence::initialize: Time: " error << "FixedSlotSequence::initialize: Time: "
<< (*slotIt)->pollingTimeMs << slotIt->pollingTimeMs
<< " is smaller than previous with " << time << std::endl; << " is smaller than previous with " << time << std::endl;
count++; count++;
} else { } else {
//All ok, print slot. // All ok, print slot.
// (*slotIt)->print(); //info << "Current slot polling time: " << std::endl;
//info << std::dec << slotIt->pollingTimeMs << std::endl;
} }
time = (*slotIt)->pollingTimeMs; time = slotIt->pollingTimeMs;
slotIt++; slotIt++;
} }
//info << "Number of elements in slot list: "
// << slotList.size() << std::endl;
if (count > 0) { if (count > 0) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
@ -118,8 +120,7 @@ ReturnValue_t FixedSlotSequence::checkSequence() const {
void FixedSlotSequence::addSlot(object_id_t componentId, uint32_t slotTimeMs, void FixedSlotSequence::addSlot(object_id_t componentId, uint32_t slotTimeMs,
int8_t executionStep, PeriodicTaskIF* executingTask) { int8_t executionStep, PeriodicTaskIF* executingTask) {
this->slotList.push_back( this->slotList.insert(FixedSequenceSlot(componentId, slotTimeMs, executionStep,
new FixedSequenceSlot(componentId, slotTimeMs, executionStep,
executingTask)); executingTask));
this->current = slotList.begin(); this->current = slotList.begin();
} }

View File

@ -4,11 +4,15 @@
#include <framework/devicehandlers/FixedSequenceSlot.h> #include <framework/devicehandlers/FixedSequenceSlot.h>
#include <framework/objectmanager/SystemObject.h> #include <framework/objectmanager/SystemObject.h>
#include <list> #include <list>
#include <set>
using SlotList = std::multiset<FixedSequenceSlot>;
using SlotListIter = std::multiset<FixedSequenceSlot>::iterator;
/** /**
* \brief This class is the representation of a Polling Sequence Table in software. * @brief This class is the representation of a Polling Sequence Table in software.
* *
* \details The FixedSlotSequence 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 * 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 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 * Polling Sequence Table in software. Each polling slot contains information to indicate when and
@ -19,29 +23,37 @@
class FixedSlotSequence { class FixedSlotSequence {
public: public:
/** /**
* \brief The constructor of the FixedSlotSequence object. * @brief The constructor of the FixedSlotSequence object.
* *
* \details The constructor takes two arguments, the period length and the init function. * @details The constructor takes two arguments, the period length and the init function.
* *
* \param setLength The period length, expressed in ms. * @param setLength The period length, expressed in ms.
*/ */
FixedSlotSequence(uint32_t setLengthMs); FixedSlotSequence(uint32_t setLengthMs);
/** /**
* \brief The destructor of the FixedSlotSequence object. * @brief The destructor of the FixedSlotSequence object.
* *
* \details The destructor frees all allocated memory by iterating through the slotList * @details The destructor frees all allocated memory by iterating through the slotList
* and deleting all allocated resources. * and deleting all allocated resources.
*/ */
virtual ~FixedSlotSequence(); virtual ~FixedSlotSequence();
/** /**
* \brief This is a method to add an PollingSlot object to slotList. * @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 * @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. * to the end of the list. The list is currently NOT reordered.
* Afterwards, the iterator current is set to the beginning of the list. * Afterwards, the iterator current is set to the beginning of the list.
* @param Object ID of the object to add
* @param setTime Value between (0 to 1) * slotLengthMs, when a FixedTimeslotTask
* will be called inside the slot period.
* @param setSequenceId ID which can be used to distinguish
* different task operations
* @param
* @param
*/ */
void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId, void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId,
PeriodicTaskIF* executingTask); PeriodicTaskIF* executingTask);
@ -57,11 +69,14 @@ public:
/** /**
* \brief This method returns the time until the next software component is invoked. * \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 * \details
* of the current slot and that of the next one (or the first one, if the list end is reached) * This method is vitally important for the operation of the PST.
* it calculates and returns the interval in milliseconds within which the handler execution * By fetching the polling time of the current slot and that of the
* shall take place. If the next slot has the same time as the current one, it is ignored until * next one (or the first one, if the list end is reached)
* a slot with different time or the end of the PST is found. * it calculates and returns the interval in milliseconds within
* which the handler execution shall take place.
* If the next slot has the same time as the current one, it is ignored
* until a slot with different time or the end of the PST is found.
*/ */
uint32_t getIntervalToNextSlotMs(); uint32_t getIntervalToNextSlotMs();
@ -75,12 +90,12 @@ public:
uint32_t getIntervalToPreviousSlotMs(); uint32_t getIntervalToPreviousSlotMs();
/** /**
* \brief This method returns the length of this FixedSlotSequence instance. * @brief This method returns the length of this FixedSlotSequence instance.
*/ */
uint32_t getLengthMs() const; uint32_t getLengthMs() const;
/** /**
* \brief The method to execute the device handler entered in the current OPUSPollingSlot object. * \brief The method to execute the device handler entered in the current PollingSlot object.
* *
* \details Within this method the device handler object to be executed is chosen by looking up the * \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 * handler address of the current slot in the handlerMap. Either the device handler's
@ -91,27 +106,27 @@ public:
void executeAndAdvance(); void executeAndAdvance();
/** /**
* \brief An iterator that indicates the current polling slot to execute. * @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. * @details This is an iterator for slotList and always points to the polling slot which is executed next.
*/ */
std::list<FixedSequenceSlot*>::iterator current; SlotListIter current;
ReturnValue_t checkSequence() const; virtual ReturnValue_t checkSequence() const;
protected: protected:
/** /**
* \brief This list contains all OPUSPollingSlot objects, defining order and execution time of the * @brief This list contains all PollingSlot objects, defining order and execution time of the
* device handler objects. * device handler objects.
* *
* \details The slot list is a std:list object that contains all created OPUSPollingSlot instances. * @details The slot list is a std:list object that contains all created PollingSlot instances.
* They are NOT ordered automatically, so by adding entries, the correct order needs to be ensured. * They are NOT ordered automatically, so by adding entries, the correct order needs to be ensured.
* By iterating through this list the polling sequence is executed. Two entries with identical * By iterating through this list the polling sequence is executed. Two entries with identical
* polling times are executed immediately one after another. * polling times are executed immediately one after another.
*/ */
std::list<FixedSequenceSlot*> slotList; SlotList slotList;
uint32_t lengthMs; uint32_t slotLengthMs;
}; };
#endif /* FIXEDSLOTSEQUENCE_H_ */ #endif /* FIXEDSLOTSEQUENCE_H_ */

View File

@ -137,9 +137,10 @@ void EventManager::printEvent(EventMessage* message) {
error << "0x" << std::hex << message->getReporter() << std::dec; error << "0x" << std::hex << message->getReporter() << std::dec;
} }
error << " reported " << translateEvents(message->getEvent()) << " (" error << " reported " << translateEvents(message->getEvent()) << " ("
<< std::dec << message->getEventId() << std::hex << ") P1: 0x" << std::dec << message->getEventId() << ") " << std::endl;
<< message->getParameter1() << " P2: 0x"
<< message->getParameter2() << std::dec << std::endl; error << std::hex << "P1 Hex: 0x" << message->getParameter1() << ", P1 Dec: " << std::dec << message->getParameter1() << std::endl;
error << std::hex << "P2 Hex: 0x" << message->getParameter2() << ", P2 Dec: " << std::dec << message->getParameter2() << std::endl;
break; break;
} }

View File

@ -11,14 +11,14 @@ class EventRangeMatcherBase: public SerializeableMatcherIF<EventMessage*> {
public: public:
EventRangeMatcherBase(T from, T till, bool inverted) : rangeMatcher(from, till, inverted) { } EventRangeMatcherBase(T from, T till, bool inverted) : rangeMatcher(from, till, inverted) { }
virtual ~EventRangeMatcherBase() { } virtual ~EventRangeMatcherBase() { }
ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, ReturnValue_t serialize(uint8_t** buffer, size_t* size,
const uint32_t max_size, bool bigEndian) const { const size_t max_size, bool bigEndian) const {
return rangeMatcher.serialize(buffer, size, max_size, bigEndian); return rangeMatcher.serialize(buffer, size, max_size, bigEndian);
} }
uint32_t getSerializedSize() const { size_t getSerializedSize() const {
return rangeMatcher.getSerializedSize(); return rangeMatcher.getSerializedSize();
} }
ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size,
bool bigEndian) { bool bigEndian) {
return rangeMatcher.deSerialize(buffer, size, bigEndian); return rangeMatcher.deSerialize(buffer, size, bigEndian);
} }

View File

@ -5,9 +5,10 @@
#include <framework/ipc/QueueFactory.h> #include <framework/ipc/QueueFactory.h>
#include <framework/objectmanager/ObjectManagerIF.h> #include <framework/objectmanager/ObjectManagerIF.h>
FailureIsolationBase::FailureIsolationBase(object_id_t owner, object_id_t parent, uint8_t messageDepth, uint8_t parameterDomainBase) : FailureIsolationBase::FailureIsolationBase(object_id_t owner,
eventQueue(NULL), ownerId( object_id_t parent, uint8_t messageDepth, uint8_t parameterDomainBase) :
owner), owner(NULL), faultTreeParent(parent), parameterDomainBase(parameterDomainBase) { eventQueue(NULL), ownerId(owner), owner(NULL),
faultTreeParent(parent), parameterDomainBase(parameterDomainBase) {
eventQueue = QueueFactory::instance()->createMessageQueue(messageDepth, EventMessage::EVENT_MESSAGE_SIZE); eventQueue = QueueFactory::instance()->createMessageQueue(messageDepth, EventMessage::EVENT_MESSAGE_SIZE);
} }

View File

@ -21,6 +21,10 @@ public:
uint8_t messageDepth = 10, uint8_t parameterDomainBase = 0xF0); uint8_t messageDepth = 10, uint8_t parameterDomainBase = 0xF0);
virtual ~FailureIsolationBase(); virtual ~FailureIsolationBase();
virtual ReturnValue_t initialize(); virtual ReturnValue_t initialize();
/**
* This is called by the DHB in performOperation()
*/
void checkForFailures(); void checkForFailures();
MessageQueueId_t getEventReceptionQueue(); MessageQueueId_t getEventReceptionQueue();
virtual void triggerEvent(Event event, uint32_t parameter1 = 0, virtual void triggerEvent(Event event, uint32_t parameter1 = 0,

View File

@ -1,4 +1,3 @@
#include <framework/serialize/SerializeAdapter.h>
#include <framework/globalfunctions/Type.h> #include <framework/globalfunctions/Type.h>
#include <framework/serialize/SerializeAdapter.h> #include <framework/serialize/SerializeAdapter.h>
@ -59,8 +58,8 @@ uint8_t Type::getSize() const {
} }
} }
ReturnValue_t Type::serialize(uint8_t** buffer, uint32_t* size, ReturnValue_t Type::serialize(uint8_t** buffer, size_t* size,
const uint32_t max_size, bool bigEndian) const { const size_t max_size, bool bigEndian) const {
uint8_t ptc; uint8_t ptc;
uint8_t pfc; uint8_t pfc;
ReturnValue_t result = getPtcPfc(&ptc, &pfc); ReturnValue_t result = getPtcPfc(&ptc, &pfc);
@ -81,12 +80,12 @@ ReturnValue_t Type::serialize(uint8_t** buffer, uint32_t* size,
} }
uint32_t Type::getSerializedSize() const { size_t Type::getSerializedSize() const {
uint8_t dontcare = 0; uint8_t dontcare = 0;
return 2 * SerializeAdapter<uint8_t>::getSerializedSize(&dontcare); return 2 * SerializeAdapter<uint8_t>::getSerializedSize(&dontcare);
} }
ReturnValue_t Type::deSerialize(const uint8_t** buffer, int32_t* size, ReturnValue_t Type::deSerialize(const uint8_t** buffer, ssize_t* size,
bool bigEndian) { bool bigEndian) {
uint8_t ptc; uint8_t ptc;
uint8_t pfc; uint8_t pfc;

View File

@ -39,12 +39,12 @@ public:
static ActualType_t getActualType(uint8_t ptc, uint8_t pfc); static ActualType_t getActualType(uint8_t ptc, uint8_t pfc);
virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
const uint32_t max_size, bool bigEndian) const; const size_t max_size, bool bigEndian) const;
virtual uint32_t getSerializedSize() const; virtual size_t getSerializedSize() const;
virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size,
bool bigEndian); bool bigEndian);
private: private:

View File

@ -45,8 +45,8 @@ public:
return matchSubtree(iter, number); return matchSubtree(iter, number);
} }
ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, ReturnValue_t serialize(uint8_t** buffer, size_t* size,
const uint32_t max_size, bool bigEndian) const { const size_t max_size, bool bigEndian) const {
iterator iter = this->begin(); iterator iter = this->begin();
uint8_t count = this->countRight(iter); uint8_t count = this->countRight(iter);
ReturnValue_t result = SerializeAdapter<uint8_t>::serialize(&count, ReturnValue_t result = SerializeAdapter<uint8_t>::serialize(&count,
@ -86,7 +86,7 @@ public:
return result; return result;
} }
uint32_t getSerializedSize() const { size_t getSerializedSize() const {
//Analogous to serialize! //Analogous to serialize!
uint32_t size = 1; //One for count uint32_t size = 1; //One for count
iterator iter = this->begin(); iterator iter = this->begin();
@ -115,7 +115,7 @@ public:
return size; return size;
} }
ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size,
bool bigEndian) { bool bigEndian) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -27,8 +27,8 @@ public:
} }
} }
ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, ReturnValue_t serialize(uint8_t** buffer, size_t* size,
const uint32_t max_size, bool bigEndian) const { const size_t max_size, bool bigEndian) const {
ReturnValue_t result = SerializeAdapter<T>::serialize(&lowerBound, buffer, size, max_size, bigEndian); ReturnValue_t result = SerializeAdapter<T>::serialize(&lowerBound, buffer, size, max_size, bigEndian);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
@ -40,11 +40,11 @@ public:
return SerializeAdapter<bool>::serialize(&inverted, buffer, size, max_size, bigEndian); return SerializeAdapter<bool>::serialize(&inverted, buffer, size, max_size, bigEndian);
} }
uint32_t getSerializedSize() const { size_t getSerializedSize() const {
return sizeof(lowerBound) + sizeof(upperBound) + sizeof(bool); return sizeof(lowerBound) + sizeof(upperBound) + sizeof(bool);
} }
ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size,
bool bigEndian) { bool bigEndian) {
ReturnValue_t result = SerializeAdapter<T>::deSerialize(&lowerBound, buffer, size, bigEndian); ReturnValue_t result = SerializeAdapter<T>::deSerialize(&lowerBound, buffer, size, bigEndian);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {

View File

@ -27,8 +27,8 @@ public:
/** /**
* ctor * ctor
* *
* @param owner
* @param objectId the object Id to use when communication with the HealthTable * @param objectId the object Id to use when communication with the HealthTable
* @param useAsFrom id to use as from id when sending replies, can be set to 0
*/ */
HealthHelper(HasHealthIF* owner, object_id_t objectId); HealthHelper(HasHealthIF* owner, object_id_t objectId);

View File

@ -65,7 +65,7 @@ bool HealthTable::hasHealth(object_id_t object) {
void HealthTable::printAll(uint8_t* pointer, uint32_t maxSize) { void HealthTable::printAll(uint8_t* pointer, uint32_t maxSize) {
mutex->lockMutex(MutexIF::NO_TIMEOUT); mutex->lockMutex(MutexIF::NO_TIMEOUT);
uint32_t size = 0; size_t size = 0;
uint16_t count = healthMap.size(); uint16_t count = healthMap.size();
ReturnValue_t result = SerializeAdapter<uint16_t>::serialize(&count, ReturnValue_t result = SerializeAdapter<uint16_t>::serialize(&count,
&pointer, &size, maxSize, true); &pointer, &size, maxSize, true);

View File

@ -8,10 +8,9 @@
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId,
uint32_t queuePoolId, uint32_t tmPoolId, uint32_t storePoolId) : uint32_t queuePoolId, uint32_t tmPoolId, uint32_t storePoolId) :
SystemObject(setObjectId), mutex(NULL), queuePoolId(queuePoolId), tmPoolId( SystemObject(setObjectId), mutex(NULL), queuePoolId(queuePoolId),
tmPoolId), storePoolId( tmPoolId(tmPoolId),storePoolId(storePoolId), queueHits(0), tmHits(0),
storePoolId), queueHits(0), tmHits(0), storeHits( storeHits(0) {
0) {
mutex = MutexFactory::instance()->createMutex(); mutex = MutexFactory::instance()->createMutex();
} }

View File

@ -17,6 +17,9 @@
#define MAKE_COMMAND_ID( number ) ((MESSAGE_ID << 8) + (number)) #define MAKE_COMMAND_ID( number ) ((MESSAGE_ID << 8) + (number))
typedef ReturnValue_t Command_t; typedef ReturnValue_t Command_t;
/**
* @brief Used to pass command messages between tasks
*/
class CommandMessage : public MessageQueueMessage { class CommandMessage : public MessageQueueMessage {
public: public:
static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_MESSAGE; static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_MESSAGE;

View File

@ -3,12 +3,16 @@
// COULDDO: We could support blocking calls // COULDDO: We could support blocking calls
/**
* @defgroup message_queue Message Queue
* @brief Message Queue related software components
*/
#include <framework/ipc/MessageQueueMessage.h> #include <framework/ipc/MessageQueueMessage.h>
#include <framework/ipc/MessageQueueSenderIF.h> #include <framework/ipc/MessageQueueSenderIF.h>
#include <framework/returnvalues/HasReturnvaluesIF.h> #include <framework/returnvalues/HasReturnvaluesIF.h>
class MessageQueueIF { class MessageQueueIF {
public: public:
static const MessageQueueId_t NO_QUEUE = MessageQueueSenderIF::NO_QUEUE; //!< Ugly hack. static const MessageQueueId_t NO_QUEUE = MessageQueueSenderIF::NO_QUEUE; //!< Ugly hack.
static const uint8_t INTERFACE_ID = CLASS_ID::MESSAGE_QUEUE_IF; static const uint8_t INTERFACE_ID = CLASS_ID::MESSAGE_QUEUE_IF;
@ -54,6 +58,8 @@ public:
* lastPartner attribute. Else, the lastPartner information remains untouched, the * lastPartner attribute. Else, the lastPartner information remains untouched, the
* message's content is cleared and the function returns immediately. * message's content is cleared and the function returns immediately.
* @param message A pointer to a message in which the received data is stored. * @param message A pointer to a message in which the received data is stored.
* @return -@c RETURN_OK on success
* -@c MessageQueueIF::EMPTY if queue is empty
*/ */
virtual ReturnValue_t receiveMessage(MessageQueueMessage* message) = 0; virtual ReturnValue_t receiveMessage(MessageQueueMessage* message) = 0;
/** /**
@ -72,17 +78,20 @@ public:
virtual MessageQueueId_t getId() const = 0; virtual MessageQueueId_t getId() const = 0;
/** /**
* \brief With the sendMessage call, a queue message is sent to a receiving queue. * @brief With the sendMessage call, a queue message is sent to a receiving queue.
* \details This method takes the message provided, adds the sentFrom information and passes * @details This method takes the message provided, adds the sentFrom information and passes
* it on to the destination provided with an operating system call. The OS's return * it on to the destination provided with an operating system call. The OS's return
* value is returned. * value is returned.
* \param sendTo This parameter specifies the message queue id to send the message to. * @param sendTo This parameter specifies the message queue id to send the message to.
* \param message This is a pointer to a previously created message, which is sent. * @param message This is a pointer to a previously created message, which is sent.
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. * @param sentFrom The sentFrom information can be set to inject the sender's queue id into the message.
* This variable is set to zero by default. * This variable is set to zero by default.
* \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full (if implemented). * @param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full (if implemented).
* @return -@c RETURN_OK on success
* -@c MessageQueueIF::FULL if queue is full
*/ */
virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0; virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0;
/** /**
* @brief This operation sends a message to the given destination. * @brief This operation sends a message to the given destination.
* @details It directly uses the sendMessage call of the MessageQueueSender parent, but passes its * @details It directly uses the sendMessage call of the MessageQueueSender parent, but passes its
@ -94,11 +103,13 @@ public:
virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo, MessageQueueMessage* message, bool ignoreFault = false ) = 0; virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo, MessageQueueMessage* message, bool ignoreFault = false ) = 0;
/** /**
* \brief The sendToDefaultFrom method sends a queue message to the default destination. * @brief The sendToDefaultFrom method sends a queue message to the default destination.
* \details In all other aspects, it works identical to the sendMessage method. * @details In all other aspects, it works identical to the sendMessage method.
* \param message This is a pointer to a previously created message, which is sent. * @param message This is a pointer to a previously created message, which is sent.
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. * @param sentFrom The sentFrom information can be set to inject the sender's queue id into the message.
* This variable is set to zero by default. * This variable is set to zero by default.
* @return -@c RETURN_OK on success
* -@c MessageQueueIF::FULL if queue is full
*/ */
virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0; virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0;
/** /**
@ -106,6 +117,8 @@ public:
* @details As in the sendMessage method, this function uses the sendToDefault call of the * @details As in the sendMessage method, this function uses the sendToDefault call of the
* Implementation class and adds its queue id as "sentFrom" information. * Implementation class and adds its queue id as "sentFrom" information.
* @param message A pointer to a previously created message, which is sent. * @param message A pointer to a previously created message, which is sent.
* @return -@c RETURN_OK on success
* -@c MessageQueueIF::FULL if queue is full
*/ */
virtual ReturnValue_t sendToDefault( MessageQueueMessage* message ) = 0; virtual ReturnValue_t sendToDefault( MessageQueueMessage* message ) = 0;
/** /**

View File

@ -26,8 +26,8 @@ public:
* Must be implemented by a subclass. * Must be implemented by a subclass.
*/ */
static ReturnValue_t sendMessage(MessageQueueId_t sendTo, static ReturnValue_t sendMessage(MessageQueueId_t sendTo,
MessageQueueMessage* message, MessageQueueId_t sentFrom = MessageQueueMessage* message, MessageQueueId_t sentFrom = MessageQueueSenderIF::NO_QUEUE,
MessageQueueSenderIF::NO_QUEUE, bool ignoreFault=false); bool ignoreFault=false);
private: private:
MessageQueueSenderIF() {} MessageQueueSenderIF() {}
}; };

View File

@ -3,6 +3,13 @@
#include <framework/returnvalues/HasReturnvaluesIF.h> #include <framework/returnvalues/HasReturnvaluesIF.h>
/**
* @brief Common interface for OS Mutex objects which provide MUTual EXclusion.
*
* @details https://en.wikipedia.org/wiki/Lock_(computer_science)
* @ingroup osal
* @ingroup interface
*/
class MutexIF { class MutexIF {
public: public:
static const uint32_t NO_TIMEOUT; //!< Needs to be defined in implementation. static const uint32_t NO_TIMEOUT; //!< Needs to be defined in implementation.

View File

@ -152,7 +152,7 @@ void MemoryHelper::handleMemoryLoad(CommandMessage* message) {
ipcAddress = MemoryMessage::getStoreID(message); ipcAddress = MemoryMessage::getStoreID(message);
const uint8_t* p_data = NULL; const uint8_t* p_data = NULL;
uint8_t* dataPointer = NULL; uint8_t* dataPointer = NULL;
uint32_t size = 0; size_t size = 0;
ReturnValue_t returnCode = ipcStore->getData(ipcAddress, &p_data, &size); ReturnValue_t returnCode = ipcStore->getData(ipcAddress, &p_data, &size);
if (returnCode == RETURN_OK) { if (returnCode == RETURN_OK) {
returnCode = workOnThis->handleMemoryLoad(address, p_data, size, returnCode = workOnThis->handleMemoryLoad(address, p_data, size,

View File

@ -1,6 +1,7 @@
#include <framework/modes/HasModesIF.h> #include <framework/modes/HasModesIF.h>
#include <framework/modes/ModeHelper.h> #include <framework/modes/ModeHelper.h>
#include <framework/ipc/MessageQueueSenderIF.h> #include <framework/ipc/MessageQueueSenderIF.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
ModeHelper::ModeHelper(HasModesIF *owner) : ModeHelper::ModeHelper(HasModesIF *owner) :
theOneWhoCommandedAMode(0), commandedMode(HasModesIF::MODE_OFF), commandedSubmode( theOneWhoCommandedAMode(0), commandedMode(HasModesIF::MODE_OFF), commandedSubmode(
@ -42,7 +43,6 @@ ReturnValue_t ModeHelper::handleModeCommand(CommandMessage* message) {
} }
countdown.setTimeout(timeout); countdown.setTimeout(timeout);
owner->startTransition(mode, submode); owner->startTransition(mode, submode);
} }
break; break;

View File

@ -16,6 +16,10 @@ ReturnValue_t ModeMessage::setModeMessage(CommandMessage* message, Command_t com
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t ModeMessage::getCantReachModeReason(const CommandMessage* message) {
return message->getParameter();
}
void ModeMessage::clear(CommandMessage* message) { void ModeMessage::clear(CommandMessage* message) {
message->setCommand(CommandMessage::CMD_NONE); message->setCommand(CommandMessage::CMD_NONE);
} }

View File

@ -24,6 +24,7 @@ public:
static const Command_t REPLY_MODE_INFO = MAKE_COMMAND_ID(0x03); //!> Unrequested info about the current mode (used for composites to inform their container of a changed mode) static const Command_t REPLY_MODE_INFO = MAKE_COMMAND_ID(0x03); //!> Unrequested info about the current mode (used for composites to inform their container of a changed mode)
static const Command_t REPLY_CANT_REACH_MODE = MAKE_COMMAND_ID(0x04); //!> Reply in case a mode command can't be executed. Par1: returnCode, Par2: 0 static const Command_t REPLY_CANT_REACH_MODE = MAKE_COMMAND_ID(0x04); //!> Reply in case a mode command can't be executed. Par1: returnCode, Par2: 0
//SHOULDDO is there a way we can transmit a returnvalue when responding that the mode is wrong, so we can give a nice failure code when commanded by PUS? //SHOULDDO is there a way we can transmit a returnvalue when responding that the mode is wrong, so we can give a nice failure code when commanded by PUS?
// shouldn't that possible with parameter 2 when submode only takes 1 byte?
static const Command_t REPLY_WRONG_MODE_REPLY = MAKE_COMMAND_ID(0x05);//!> Reply to a CMD_MODE_COMMAND, indicating that a mode was commanded and a transition started but was aborted; the parameters contain the mode that was reached static const Command_t REPLY_WRONG_MODE_REPLY = MAKE_COMMAND_ID(0x05);//!> Reply to a CMD_MODE_COMMAND, indicating that a mode was commanded and a transition started but was aborted; the parameters contain the mode that was reached
static const Command_t CMD_MODE_READ = MAKE_COMMAND_ID(0x06);//!> Command to read the current mode and reply with a REPLY_MODE_REPLY static const Command_t CMD_MODE_READ = MAKE_COMMAND_ID(0x06);//!> Command to read the current mode and reply with a REPLY_MODE_REPLY
static const Command_t CMD_MODE_ANNOUNCE = MAKE_COMMAND_ID(0x07);//!> Command to trigger an ModeInfo Event. This command does NOT have a reply. static const Command_t CMD_MODE_ANNOUNCE = MAKE_COMMAND_ID(0x07);//!> Command to trigger an ModeInfo Event. This command does NOT have a reply.
@ -34,6 +35,7 @@ public:
static ReturnValue_t setModeMessage(CommandMessage* message, static ReturnValue_t setModeMessage(CommandMessage* message,
Command_t command, Mode_t mode, Submode_t submode); Command_t command, Mode_t mode, Submode_t submode);
static void cantReachMode(CommandMessage* message, ReturnValue_t reason); static void cantReachMode(CommandMessage* message, ReturnValue_t reason);
static ReturnValue_t getCantReachModeReason(const CommandMessage* message);
static void clear(CommandMessage* message); static void clear(CommandMessage* message);
}; };

View File

@ -16,12 +16,13 @@ public:
uint16_t confirmationLimit, T lowerLimit, T upperLimit, uint16_t confirmationLimit, T lowerLimit, T upperLimit,
Event belowLowEvent = MonitoringIF::VALUE_BELOW_LOW_LIMIT, Event belowLowEvent = MonitoringIF::VALUE_BELOW_LOW_LIMIT,
Event aboveHighEvent = MonitoringIF::VALUE_ABOVE_HIGH_LIMIT) : Event aboveHighEvent = MonitoringIF::VALUE_ABOVE_HIGH_LIMIT) :
MonitorBase<T>(reporterId, monitorId, parameterId, confirmationLimit), lowerLimit( MonitorBase<T>(reporterId, monitorId, parameterId, confirmationLimit),
lowerLimit), upperLimit(upperLimit), belowLowEvent( lowerLimit(lowerLimit), upperLimit(upperLimit), belowLowEvent(belowLowEvent),
belowLowEvent), aboveHighEvent(aboveHighEvent) { aboveHighEvent(aboveHighEvent) {
}
virtual ~LimitMonitor() {
} }
virtual ~LimitMonitor() {}
virtual ReturnValue_t checkSample(T sample, T* crossedLimit) { virtual ReturnValue_t checkSample(T sample, T* crossedLimit) {
*crossedLimit = 0.0; *crossedLimit = 0.0;
if (sample > upperLimit) { if (sample > upperLimit) {

View File

@ -17,7 +17,7 @@ ReturnValue_t LimitViolationReporter::sendLimitViolationReport(const SerializeIF
} }
store_address_t storeId; store_address_t storeId;
uint8_t* dataTarget = NULL; uint8_t* dataTarget = NULL;
uint32_t maxSize = data->getSerializedSize(); size_t maxSize = data->getSerializedSize();
if (maxSize > MonitoringIF::VIOLATION_REPORT_MAX_SIZE) { if (maxSize > MonitoringIF::VIOLATION_REPORT_MAX_SIZE) {
return MonitoringIF::INVALID_SIZE; return MonitoringIF::INVALID_SIZE;
} }
@ -26,7 +26,7 @@ ReturnValue_t LimitViolationReporter::sendLimitViolationReport(const SerializeIF
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
uint32_t size = 0; size_t size = 0;
result = data->serialize(&dataTarget, &size, maxSize, true); result = data->serialize(&dataTarget, &size, maxSize, true);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;

View File

@ -78,6 +78,8 @@ public:
virtual void printList() = 0; virtual void printList() = 0;
}; };
/*Documentation can be found in the class method declaration above.*/
template <typename T> template <typename T>
T* ObjectManagerIF::get( object_id_t id ) { T* ObjectManagerIF::get( object_id_t id ) {
SystemObjectIF* temp = this->getSystemObject(id); SystemObjectIF* temp = this->getSystemObject(id);

View File

@ -1,6 +1,10 @@
#ifndef FRAMEWORK_OSAL_ENDINESS_H_ #ifndef FRAMEWORK_OSAL_ENDINESS_H_
#define FRAMEWORK_OSAL_ENDINESS_H_ #define FRAMEWORK_OSAL_ENDINESS_H_
/**
* @defgroup osal Operating System Abstraction Layer
* @brief Provides clean interfaces to use OS functionalities
*/
/* /*
* BSD-style endian declaration * BSD-style endian declaration

View File

@ -0,0 +1,109 @@
/**
* @file BinarySemaphore.cpp
*
* @date 25.02.2020
*/
#include <framework/osal/FreeRTOS/BinarySemaphore.h>
#include <framework/osal/FreeRTOS/TaskManagement.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include "portmacro.h"
#include "task.h"
BinarySemaphore::BinarySemaphore() {
xSemaphoreCreateBinary(handle);
if(handle == nullptr) {
error << "Binary semaphore creation failure" << std::endl;
}
}
BinarySemaphore::~BinarySemaphore() {
vSemaphoreDelete(handle);
}
ReturnValue_t BinarySemaphore::takeBinarySemaphore(uint32_t timeoutMs) {
if(handle == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
TickType_t timeout = portMAX_DELAY;
if(timeoutMs != 0) {
timeout = pdMS_TO_TICKS(timeoutMs);
}
BaseType_t returncode = xSemaphoreTake(handle, timeout);
if (returncode == pdPASS) {
return HasReturnvaluesIF::RETURN_OK;
} else {
return SEMAPHORE_NOT_FOUND;
}
}
ReturnValue_t BinarySemaphore::takeBinarySemaphoreTickTimeout(TickType_t timeoutTicks) {
if(handle == nullptr) {
return SEMAPHORE_NOT_FOUND;
}
BaseType_t returncode = xSemaphoreTake(handle, timeoutTicks);
if (returncode == pdPASS) {
return HasReturnvaluesIF::RETURN_OK;
} else {
return SEMAPHORE_TIMEOUT;
}
}
ReturnValue_t BinarySemaphore::giveBinarySemaphore() {
if (handle == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
BaseType_t returncode = xSemaphoreGive(handle);
if (returncode == pdPASS) {
return HasReturnvaluesIF::RETURN_OK;
} else {
return SEMAPHORE_NOT_OWNED;
}
}
SemaphoreHandle_t BinarySemaphore::getSemaphore() {
return handle;
}
ReturnValue_t BinarySemaphore::giveBinarySemaphore(SemaphoreHandle_t semaphore) {
if (semaphore == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
BaseType_t returncode = xSemaphoreGive(semaphore);
if (returncode == pdPASS) {
return HasReturnvaluesIF::RETURN_OK;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
void BinarySemaphore::resetSemaphore() {
if(handle != nullptr) {
vSemaphoreDelete(handle);
xSemaphoreCreateBinary(handle);
}
}
// Be careful with the stack size here. This is called from an ISR!
ReturnValue_t BinarySemaphore::giveBinarySemaphoreFromISR(SemaphoreHandle_t semaphore,
BaseType_t * higherPriorityTaskWoken) {
if (semaphore == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
BaseType_t returncode = xSemaphoreGiveFromISR(semaphore, higherPriorityTaskWoken);
if (returncode == pdPASS) {
if(*higherPriorityTaskWoken == pdPASS) {
// Request context switch
// TODO: I don't know if this will ever happen but if it does,
// I want to to know in case this causes issues. If it doesn't
// we should remove this.
TRACE_INFO("Binary Semaphore: Higher priority task unblocked!");
TaskManagement::requestContextSwitch(CallContext::isr);
}
return HasReturnvaluesIF::RETURN_OK;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}

View File

@ -0,0 +1,103 @@
/**
* @file BinarySempahore.h
*
* @date 25.02.2020
*/
#ifndef FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_
#define FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_
#include <framework/returnvalues/HasReturnvaluesIF.h>
#include <FreeRTOS.h>
#include "semphr.h"
/**
* @brief OS Tool to achieve synchronization of between tasks or between task and ISR
* @details
* Documentation: https://www.freertos.org/Embedded-RTOS-Binary-Semaphores.html
* @ingroup osal
*/
class BinarySemaphore: public HasReturnvaluesIF {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF;
/** Semaphore object not found */
static const ReturnValue_t SEMAPHORE_NOT_FOUND = MAKE_RETURN_CODE(1);
/** Semaphore timeout */
static const ReturnValue_t SEMAPHORE_TIMEOUT = MAKE_RETURN_CODE(2);
/** The current semaphore can not be given, because it is not owned */
static const ReturnValue_t SEMAPHORE_NOT_OWNED = MAKE_RETURN_CODE(3);
/**
* Create a binary semaphore
*/
BinarySemaphore();
/**
* Delete the binary semaphore to prevent a memory leak
*/
~BinarySemaphore();
/**
* Take the binary semaphore.
* If the semaphore has already been taken, the task will be blocked for a maximum
* of #timeoutMs or until the semaphore is given back,
* for example by an ISR or another task.
* @param timeoutMs
* @return -@c RETURN_OK on success
* -@c RETURN_FAILED on failure
*/
ReturnValue_t takeBinarySemaphore(uint32_t timeoutMs);
/**
* Same as lockBinarySemaphore() with timeout in FreeRTOS ticks.
* @param timeoutTicks
* @return -@c RETURN_OK on success
* -@c RETURN_FAILED on failure
*/
ReturnValue_t takeBinarySemaphoreTickTimeout(TickType_t timeoutTicks);
/**
* Give back the binary semaphore
* @return -@c RETURN_OK on success
* -@c RETURN_FAILED on failure
*/
ReturnValue_t giveBinarySemaphore();
/**
* Get Handle to the semaphore.
* @return
*/
SemaphoreHandle_t getSemaphore();
/**
* Reset the semaphore.
*/
void resetSemaphore();
/**
* Wrapper function to give back semaphore from handle
* @param semaphore
* @return -@c RETURN_OK on success
* -@c RETURN_FAILED on failure
*/
static ReturnValue_t giveBinarySemaphore(SemaphoreHandle_t semaphore);
/**
* Wrapper function to give back semaphore from handle when called from an ISR
* @param semaphore
* @param higherPriorityTaskWoken This will be set to pdPASS if a task with a higher priority
* was unblocked
* @return -@c RETURN_OK on success
* -@c RETURN_FAILED on failure
*/
static ReturnValue_t giveBinarySemaphoreFromISR(SemaphoreHandle_t semaphore,
BaseType_t * higherPriorityTaskWoken);
private:
SemaphoreHandle_t handle;
};
#endif /* FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */

View File

@ -19,8 +19,7 @@ FixedTimeslotTask::~FixedTimeslotTask() {
void FixedTimeslotTask::taskEntryPoint(void* argument) { void FixedTimeslotTask::taskEntryPoint(void* argument) {
//The argument is re-interpreted as FixedTimeslotTask. The Task object is global, so it is found from any place. //The argument is re-interpreted as FixedTimeslotTask. The Task object is global, so it is found from any place.
FixedTimeslotTask *originalTask( FixedTimeslotTask *originalTask(reinterpret_cast<FixedTimeslotTask*>(argument));
reinterpret_cast<FixedTimeslotTask*>(argument));
// Task should not start until explicitly requested // Task should not start until explicitly requested
// in FreeRTOS, tasks start as soon as they are created if the scheduler is running // in FreeRTOS, tasks start as soon as they are created if the scheduler is running
// but not if the scheduler is not running. // but not if the scheduler is not running.
@ -58,8 +57,19 @@ ReturnValue_t FixedTimeslotTask::startTask() {
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId,
uint32_t slotTimeMs, int8_t executionStep) { uint32_t slotTimeMs, int8_t executionStep) {
if (objectManager->get<ExecutableObjectIF>(componentId) != NULL) {
if(slotTimeMs == 0) {
// TODO: FreeRTOS throws errors for zero values.
// maybe there is a better solution than this.
slotTimeMs = 1;
}
pst.addSlot(componentId, slotTimeMs, executionStep, this); pst.addSlot(componentId, slotTimeMs, executionStep, this);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
}
error << "Component " << std::hex << componentId
<< " not found, not adding it to pst" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
} }
uint32_t FixedTimeslotTask::getPeriodMs() const { uint32_t FixedTimeslotTask::getPeriodMs() const {
@ -72,10 +82,10 @@ ReturnValue_t FixedTimeslotTask::checkSequence() const {
void FixedTimeslotTask::taskFunctionality() { void FixedTimeslotTask::taskFunctionality() {
// A local iterator for the Polling Sequence Table is created to find the start time for the first entry. // A local iterator for the Polling Sequence Table is created to find the start time for the first entry.
std::list<FixedSequenceSlot*>::iterator it = pst.current; SlotListIter slotListIter = pst.current;
//The start time for the first entry is read. //The start time for the first entry is read.
uint32_t intervalMs = (*it)->pollingTimeMs; uint32_t intervalMs = slotListIter->pollingTimeMs;
TickType_t interval = pdMS_TO_TICKS(intervalMs); TickType_t interval = pdMS_TO_TICKS(intervalMs);
TickType_t xLastWakeTime; TickType_t xLastWakeTime;
@ -110,4 +120,3 @@ ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) {
vTaskDelay(pdMS_TO_TICKS(ms)); vTaskDelay(pdMS_TO_TICKS(ms));
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -51,6 +51,7 @@ public:
ReturnValue_t checkSequence() const; ReturnValue_t checkSequence() const;
ReturnValue_t sleepFor(uint32_t ms); ReturnValue_t sleepFor(uint32_t ms);
protected: protected:
bool started; bool started;
TaskHandle_t handle; TaskHandle_t handle;

View File

@ -3,9 +3,10 @@
#include <framework/serviceinterface/ServiceInterfaceStream.h> #include <framework/serviceinterface/ServiceInterfaceStream.h>
// TODO I guess we should have a way of checking if we are in an ISR and then use the "fromISR" versions of all calls // TODO I guess we should have a way of checking if we are in an ISR and then use the "fromISR" versions of all calls
// As a first step towards this, introduces system context variable which needs to be switched manually
// Haven't found function to find system context.
MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size) : MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size) :
defaultDestination(0),lastPartner(0) { defaultDestination(0),lastPartner(0), callContext(CallContext::task) {
handle = xQueueCreate(message_depth, max_message_size); handle = xQueueCreate(message_depth, max_message_size);
if (handle == NULL) { if (handle == NULL) {
error << "MessageQueue creation failed" << std::endl; error << "MessageQueue creation failed" << std::endl;
@ -18,6 +19,10 @@ MessageQueue::~MessageQueue() {
} }
} }
void MessageQueue::switchSystemContext(CallContext callContext) {
this->callContext = callContext;
}
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
MessageQueueMessage* message, bool ignoreFault) { MessageQueueMessage* message, bool ignoreFault) {
return sendMessageFrom(sendTo, message, this->getId(), ignoreFault); return sendMessageFrom(sendTo, message, this->getId(), ignoreFault);
@ -27,6 +32,11 @@ ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message) {
return sendToDefaultFrom(message, this->getId()); return sendToDefaultFrom(message, this->getId());
} }
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessage* message,
MessageQueueId_t sentFrom, bool ignoreFault) {
return sendMessageFrom(defaultDestination,message,sentFrom,ignoreFault);
}
ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) { ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) {
if (this->lastPartner != 0) { if (this->lastPartner != 0) {
return sendMessageFrom(this->lastPartner, message, this->getId()); return sendMessageFrom(this->lastPartner, message, this->getId());
@ -35,10 +45,54 @@ ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) {
} }
} }
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo,
MessageQueueMessage* message, MessageQueueId_t sentFrom,
bool ignoreFault) {
return sendMessageFromMessageQueue(sendTo,message,sentFrom,ignoreFault, callContext);
}
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
MessageQueueMessage *message, MessageQueueId_t sentFrom,
bool ignoreFault, CallContext callContext) {
message->setSender(sentFrom);
BaseType_t result;
if(callContext == CallContext::task) {
result = xQueueSendToBack(reinterpret_cast<void*>(sendTo),
reinterpret_cast<const void*>(message->getBuffer()), 0);
}
else {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
result = xQueueSendFromISR(reinterpret_cast<void*>(sendTo),
reinterpret_cast<const void*>(message->getBuffer()), &xHigherPriorityTaskWoken);
if(xHigherPriorityTaskWoken == pdTRUE) {
TaskManagement::requestContextSwitch(callContext);
}
}
return handleSendResult(result, ignoreFault);
}
ReturnValue_t MessageQueue::handleSendResult(BaseType_t result, bool ignoreFault) {
if (result != pdPASS) {
if (!ignoreFault) {
InternalErrorReporterIF* internalErrorReporter = objectManager->get<InternalErrorReporterIF>(
objects::INTERNAL_ERROR_REPORTER);
if (internalErrorReporter != NULL) {
internalErrorReporter->queueMessageNotSent();
}
}
return MessageQueueIF::FULL;
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message, ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message,
MessageQueueId_t* receivedFrom) { MessageQueueId_t* receivedFrom) {
ReturnValue_t status = this->receiveMessage(message); ReturnValue_t status = this->receiveMessage(message);
if(status == HasReturnvaluesIF::RETURN_OK) {
*receivedFrom = this->lastPartner; *receivedFrom = this->lastPartner;
}
return status; return status;
} }
@ -71,17 +125,6 @@ void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
this->defaultDestination = defaultDestination; this->defaultDestination = defaultDestination;
} }
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo,
MessageQueueMessage* message, MessageQueueId_t sentFrom,
bool ignoreFault) {
return sendMessageFromMessageQueue(sendTo,message,sentFrom,ignoreFault);
}
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessage* message,
MessageQueueId_t sentFrom, bool ignoreFault) {
return sendMessageFrom(defaultDestination,message,sentFrom,ignoreFault);
}
MessageQueueId_t MessageQueue::getDefaultDestination() const { MessageQueueId_t MessageQueue::getDefaultDestination() const {
return defaultDestination; return defaultDestination;
} }
@ -89,23 +132,6 @@ MessageQueueId_t MessageQueue::getDefaultDestination() const {
bool MessageQueue::isDefaultDestinationSet() const { bool MessageQueue::isDefaultDestinationSet() const {
return 0; return 0;
} }
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
MessageQueueMessage *message, MessageQueueId_t sentFrom,
bool ignoreFault) {
message->setSender(sentFrom);
BaseType_t result = xQueueSendToBack(reinterpret_cast<void*>(sendTo),reinterpret_cast<const void*>(message->getBuffer()), 0);
if (result != pdPASS) {
if (!ignoreFault) {
InternalErrorReporterIF* internalErrorReporter = objectManager->get<InternalErrorReporterIF>(
objects::INTERNAL_ERROR_REPORTER);
if (internalErrorReporter != NULL) {
internalErrorReporter->queueMessageNotSent();
}
}
return MessageQueueIF::FULL;
}
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -4,9 +4,11 @@
#include <framework/internalError/InternalErrorReporterIF.h> #include <framework/internalError/InternalErrorReporterIF.h>
#include <framework/ipc/MessageQueueIF.h> #include <framework/ipc/MessageQueueIF.h>
#include <framework/ipc/MessageQueueMessage.h> #include <framework/ipc/MessageQueueMessage.h>
#include <framework/osal/FreeRTOS/TaskManagement.h>
#include <FreeRTOS.h> #include <FreeRTOS.h>
#include <queue.h> #include "queue.h"
//TODO this class assumes that MessageQueueId_t is the same size as void* (the FreeRTOS handle type), compiler will catch this but it might be nice to have something checking or even an always working solution //TODO this class assumes that MessageQueueId_t is the same size as void* (the FreeRTOS handle type), compiler will catch this but it might be nice to have something checking or even an always working solution
// https://scaryreasoner.wordpress.com/2009/02/28/checking-sizeof-at-compile-time/ // https://scaryreasoner.wordpress.com/2009/02/28/checking-sizeof-at-compile-time/
@ -21,11 +23,17 @@
* methods to send a message to a user-defined or a default destination. In addition * methods to send a message to a user-defined or a default destination. In addition
* it also provides a reply method to answer to the queue it received its last message * it also provides a reply method to answer to the queue it received its last message
* from. * from.
*
* The MessageQueue should be used as "post box" for a single owning object. So all * The MessageQueue should be used as "post box" for a single owning object. So all
* message queue communication is "n-to-one". * message queue communication is "n-to-one".
* For creating the queue, as well as sending and receiving messages, the class makes * For creating the queue, as well as sending and receiving messages, the class makes
* use of the operating system calls provided. * use of the operating system calls provided.
* \ingroup message_queue *
* Please keep in mind that FreeRTOS offers
* different calls for message queue operations if called from an ISR.
* For now, the system context needs to be switched manually.
* @ingroup osal
* @ingroup message_queue
*/ */
class MessageQueue : public MessageQueueIF { class MessageQueue : public MessageQueueIF {
friend class MessageQueueSenderIF; friend class MessageQueueSenderIF;
@ -43,11 +51,15 @@ public:
* This should be left default. * This should be left default.
*/ */
MessageQueue( size_t message_depth = 3, size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE ); MessageQueue( size_t message_depth = 3, size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE );
/** /**
* @brief The destructor deletes the formerly created message queue. * @brief The destructor deletes the formerly created message queue.
* @details This is accomplished by using the delete call provided by the operating system. * @details This is accomplished by using the delete call provided by the operating system.
*/ */
virtual ~MessageQueue(); virtual ~MessageQueue();
void switchSystemContext(CallContext callContext);
/** /**
* @brief This operation sends a message to the given destination. * @brief This operation sends a message to the given destination.
* @details It directly uses the sendMessage call of the MessageQueueSender parent, but passes its * @details It directly uses the sendMessage call of the MessageQueueSender parent, but passes its
@ -74,6 +86,29 @@ public:
*/ */
ReturnValue_t reply( MessageQueueMessage* message ); ReturnValue_t reply( MessageQueueMessage* message );
/**
* \brief With the sendMessage call, a queue message is sent to a receiving queue.
* \details This method takes the message provided, adds the sentFrom information and passes
* it on to the destination provided with an operating system call. The OS's return
* value is returned.
* \param sendTo This parameter specifies the message queue id to send the message to.
* \param message This is a pointer to a previously created message, which is sent.
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message.
* This variable is set to zero by default.
* \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
*/
virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message,
MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false );
/**
* \brief The sendToDefault method sends a queue message to the default destination.
* \details In all other aspects, it works identical to the sendMessage method.
* \param message This is a pointer to a previously created message, which is sent.
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message.
* This variable is set to zero by default.
*/
virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false );
/** /**
* @brief This function reads available messages from the message queue and returns the sender. * @brief This function reads available messages from the message queue and returns the sender.
* @details It works identically to the other receiveMessage call, but in addition returns the * @details It works identically to the other receiveMessage call, but in addition returns the
@ -107,26 +142,7 @@ public:
* @brief This method returns the message queue id of this class's message queue. * @brief This method returns the message queue id of this class's message queue.
*/ */
MessageQueueId_t getId() const; MessageQueueId_t getId() const;
/**
* \brief With the sendMessage call, a queue message is sent to a receiving queue.
* \details This method takes the message provided, adds the sentFrom information and passes
* it on to the destination provided with an operating system call. The OS's return
* value is returned.
* \param sendTo This parameter specifies the message queue id to send the message to.
* \param message This is a pointer to a previously created message, which is sent.
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message.
* This variable is set to zero by default.
* \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
*/
virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false );
/**
* \brief The sendToDefault method sends a queue message to the default destination.
* \details In all other aspects, it works identical to the sendMessage method.
* \param message This is a pointer to a previously created message, which is sent.
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message.
* This variable is set to zero by default.
*/
virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false );
/** /**
* \brief This method is a simple setter for the default destination. * \brief This method is a simple setter for the default destination.
*/ */
@ -148,12 +164,20 @@ protected:
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message.
* This variable is set to zero by default. * This variable is set to zero by default.
* \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. * \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
* \param context
*/ */
static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo,MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE,bool ignoreFault=false); static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo,
MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE,
bool ignoreFault=false, CallContext callContex = CallContext::task);
static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault);
private: private:
QueueHandle_t handle; QueueHandle_t handle;
MessageQueueId_t defaultDestination; MessageQueueId_t defaultDestination;
MessageQueueId_t lastPartner; MessageQueueId_t lastPartner;
CallContext callContext; //!< Stores the current system context
}; };
#endif /* MESSAGEQUEUE_H_ */ #endif /* MESSAGEQUEUE_H_ */

View File

@ -6,7 +6,9 @@ const uint32_t MutexIF::NO_TIMEOUT = 0;
Mutex::Mutex() { Mutex::Mutex() {
handle = xSemaphoreCreateMutex(); handle = xSemaphoreCreateMutex();
//TODO print error if(handle == NULL) {
error << "Mutex creation failure" << std::endl;
}
} }
Mutex::~Mutex() { Mutex::~Mutex() {
@ -18,8 +20,7 @@ Mutex::~Mutex() {
ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) { ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) {
if (handle == 0) { if (handle == 0) {
//TODO Does not exist return MutexIF::MUTEX_NOT_FOUND;
return HasReturnvaluesIF::RETURN_FAILED;
} }
TickType_t timeout = portMAX_DELAY; TickType_t timeout = portMAX_DELAY;
if (timeoutMs != NO_TIMEOUT) { if (timeoutMs != NO_TIMEOUT) {
@ -30,21 +31,18 @@ ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) {
if (returncode == pdPASS) { if (returncode == pdPASS) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} else { } else {
//TODO could not be acquired/timeout return MutexIF::MUTEX_TIMEOUT;
return HasReturnvaluesIF::RETURN_FAILED;
} }
} }
ReturnValue_t Mutex::unlockMutex() { ReturnValue_t Mutex::unlockMutex() {
if (handle == 0) { if (handle == 0) {
//TODO Does not exist return MutexIF::MUTEX_NOT_FOUND;
return HasReturnvaluesIF::RETURN_FAILED;
} }
BaseType_t returncode = xSemaphoreGive(handle); BaseType_t returncode = xSemaphoreGive(handle);
if (returncode == pdPASS) { if (returncode == pdPASS) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} else { } else {
//TODO is not owner return MutexIF::CURR_THREAD_DOES_NOT_OWN_MUTEX;
return HasReturnvaluesIF::RETURN_FAILED;
} }
} }

View File

@ -1,5 +1,5 @@
#ifndef OS_RTEMS_MUTEX_H_ #ifndef FRAMEWORK_FREERTOS_MUTEX_H_
#define OS_RTEMS_MUTEX_H_ #define FRAMEWORK_FREERTOS_MUTEX_H_
#include <framework/ipc/MutexIF.h> #include <framework/ipc/MutexIF.h>
@ -7,8 +7,14 @@
#include <FreeRTOS.h> #include <FreeRTOS.h>
#include "semphr.h" #include "semphr.h"
/**
* @brief OS component to implement MUTual EXclusion
*
* @details
* Mutexes are binary semaphores which include a priority inheritance mechanism.
* Documentation: https://www.freertos.org/Real-time-embedded-RTOS-mutexes.html
* @ingroup osal
*/
class Mutex : public MutexIF { class Mutex : public MutexIF {
public: public:
Mutex(); Mutex();
@ -19,4 +25,4 @@ private:
SemaphoreHandle_t handle; SemaphoreHandle_t handle;
}; };
#endif /* OS_RTEMS_MUTEX_H_ */ #endif /* FRAMEWORK_FREERTOS_MUTEX_H_ */

View File

@ -1,6 +1,5 @@
#include <framework/ipc/MutexFactory.h> #include <framework/ipc/MutexFactory.h>
#include <framework/osal/FreeRTOS/Mutex.h>
#include "../FreeRTOS/Mutex.h"
//TODO: Different variant than the lazy loading in QueueFactory. What's better and why? -> one is on heap the other on bss/data //TODO: Different variant than the lazy loading in QueueFactory. What's better and why? -> one is on heap the other on bss/data
//MutexFactory* MutexFactory::factoryInstance = new MutexFactory(); //MutexFactory* MutexFactory::factoryInstance = new MutexFactory();

View File

@ -1,5 +1,5 @@
#ifndef MULTIOBJECTTASK_H_ #ifndef PERIODICTASK_H_
#define MULTIOBJECTTASK_H_ #define PERIODICTASK_H_
#include <framework/objectmanager/ObjectManagerIF.h> #include <framework/objectmanager/ObjectManagerIF.h>
#include <framework/tasks/PeriodicTaskIF.h> #include <framework/tasks/PeriodicTaskIF.h>
@ -107,4 +107,4 @@ protected:
void taskFunctionality(void); void taskFunctionality(void);
}; };
#endif /* MULTIOBJECTTASK_H_ */ #endif /* PERIODICTASK_H_ */

View File

@ -1,6 +1,6 @@
#include <framework/ipc/QueueFactory.h> #include <framework/ipc/QueueFactory.h>
#include "../FreeRTOS/MessageQueue.h" #include <framework/osal/FreeRTOS/MessageQueue.h>
QueueFactory* QueueFactory::factoryInstance = NULL; QueueFactory* QueueFactory::factoryInstance = NULL;

View File

@ -15,6 +15,7 @@ TaskFactory* TaskFactory::instance() {
} }
/*** /***
* Keep in Mind that you need to call before this vTaskStartScheduler()! * Keep in Mind that you need to call before this vTaskStartScheduler()!
* High taskPriority_ number means high priority.
*/ */
PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_, PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_,
TaskPriority taskPriority_, TaskStackSize stackSize_, TaskPriority taskPriority_, TaskStackSize stackSize_,

View File

@ -0,0 +1,32 @@
/**
* @file TaskManagement.cpp
*
* @date 26.02.2020
*
*/
#include <framework/osal/FreeRTOS/TaskManagement.h>
#include <FreeRTOS.h>
#include "portmacro.h"
#include "task.h"
/**
* TODO: This stuff is hardware and architecture and mission dependant...
* Some FreeRTOS implementations might be able to determine their own task context for example.
* If not ISRs are used, or task preemption is enabled, some of this stuff might
* not be necessary anyway. Maybe there is a better solution?
*/
void TaskManagement::requestContextSwitchFromTask() {
vTaskDelay(0);
}
void TaskManagement::requestContextSwitch(CallContext callContext = CallContext::task) {
if(callContext == CallContext::isr) {
// This function depends on the partmacro.h definition for the specific device
portYIELD_FROM_ISR();
} else {
requestContextSwitchFromTask();
}
}

View File

@ -0,0 +1,38 @@
/**
* @file TaskManagement.h
*
* @date 26.02.2020
*/
#ifndef FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_
#define FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_
/*!
* Used by functions to tell if they are being called from
* within an ISR or from a regular task. This is required because FreeRTOS
* has different functions for handling semaphores and messages from within an ISR and task.
*/
enum CallContext {
task = 0x00,//!< task_context
isr = 0xFF //!< isr_context
};
class TaskManagement {
public:
/**
* In this function, a function dependant on the portmacro.h header function calls
* to request a context switch can be specified.
* This can be used if sending to the queue from an ISR caused a task to unblock
* and a context switch is required.
*/
static void requestContextSwitch(CallContext callContext);
/**
* If task preemption in FreeRTOS is disabled, a context switch
* can be requested manually by calling this function.
*/
static void requestContextSwitchFromTask(void);
};
#endif /* FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ */

View File

@ -40,6 +40,11 @@ uint32_t FixedTimeslotTask::getPeriodMs() const {
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId,
uint32_t slotTimeMs, int8_t executionStep) { uint32_t slotTimeMs, int8_t executionStep) {
if (!objectManager->get<ExecutableObjectIF>(componentId)) {
error << "Component " << std::hex << componentId << " not found, not adding it to pst" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
pst.addSlot(componentId, slotTimeMs, executionStep, this); pst.addSlot(componentId, slotTimeMs, executionStep, this);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -3,7 +3,7 @@
#include <framework/parameters/ParameterMessage.h> #include <framework/parameters/ParameterMessage.h>
ParameterHelper::ParameterHelper(ReceivesParameterMessagesIF* owner) : ParameterHelper::ParameterHelper(ReceivesParameterMessagesIF* owner) :
owner(owner), storage(NULL) { owner(owner), ownerQueueId(0), storage(NULL){
} }
@ -37,7 +37,7 @@ ReturnValue_t ParameterHelper::handleParameterMessage(CommandMessage *message) {
ParameterMessage::getParameterId(message)); ParameterMessage::getParameterId(message));
const uint8_t *storedStream; const uint8_t *storedStream;
uint32_t storedStreamSize; size_t storedStreamSize;
result = storage->getData( result = storage->getData(
ParameterMessage::getStoreId(message), &storedStream, ParameterMessage::getStoreId(message), &storedStream,
&storedStreamSize); &storedStreamSize);
@ -94,7 +94,7 @@ ReturnValue_t ParameterHelper::sendParameter(MessageQueueId_t to, uint32_t id,
return result; return result;
} }
uint32_t storeElementSize = 0; size_t storeElementSize = 0;
result = description->serialize(&storeElement, &storeElementSize, result = description->serialize(&storeElement, &storeElementSize,
serializedSize, true); serializedSize, true);

View File

@ -20,8 +20,8 @@ ParameterWrapper::ParameterWrapper(Type type, uint8_t rows, uint8_t columns,
ParameterWrapper::~ParameterWrapper() { ParameterWrapper::~ParameterWrapper() {
} }
ReturnValue_t ParameterWrapper::serialize(uint8_t** buffer, uint32_t* size, ReturnValue_t ParameterWrapper::serialize(uint8_t** buffer, size_t* size,
const uint32_t max_size, bool bigEndian) const { const size_t max_size, bool bigEndian) const {
ReturnValue_t result; ReturnValue_t result;
result = SerializeAdapter<Type>::serialize(&type, buffer, size, max_size, result = SerializeAdapter<Type>::serialize(&type, buffer, size, max_size,
@ -77,7 +77,7 @@ ReturnValue_t ParameterWrapper::serialize(uint8_t** buffer, uint32_t* size,
return result; return result;
} }
uint32_t ParameterWrapper::getSerializedSize() const { size_t ParameterWrapper::getSerializedSize() const {
uint32_t serializedSize = 0; uint32_t serializedSize = 0;
serializedSize += type.getSerializedSize(); serializedSize += type.getSerializedSize();
serializedSize += sizeof(rows); serializedSize += sizeof(rows);
@ -88,8 +88,8 @@ uint32_t ParameterWrapper::getSerializedSize() const {
} }
template<typename T> template<typename T>
ReturnValue_t ParameterWrapper::serializeData(uint8_t** buffer, uint32_t* size, ReturnValue_t ParameterWrapper::serializeData(uint8_t** buffer, size_t* size,
const uint32_t max_size, bool bigEndian) const { const size_t max_size, bool bigEndian) const {
const T *element = (const T*) readonlyData; const T *element = (const T*) readonlyData;
ReturnValue_t result; ReturnValue_t result;
uint16_t dataSize = columns * rows; uint16_t dataSize = columns * rows;
@ -112,7 +112,7 @@ ReturnValue_t ParameterWrapper::deSerializeData(uint8_t startingRow,
//treat from as a continuous Stream as we copy all of it //treat from as a continuous Stream as we copy all of it
const uint8_t *fromAsStream = (const uint8_t *) from; const uint8_t *fromAsStream = (const uint8_t *) from;
int32_t streamSize = fromRows * fromColumns * sizeof(T); ssize_t streamSize = fromRows * fromColumns * sizeof(T);
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
@ -137,12 +137,12 @@ ReturnValue_t ParameterWrapper::deSerializeData(uint8_t startingRow,
} }
ReturnValue_t ParameterWrapper::deSerialize(const uint8_t** buffer, ReturnValue_t ParameterWrapper::deSerialize(const uint8_t** buffer,
int32_t* size, bool bigEndian) { ssize_t* size, bool bigEndian) {
return deSerialize(buffer, size, bigEndian, 0); return deSerialize(buffer, size, bigEndian, 0);
} }
ReturnValue_t ParameterWrapper::deSerialize(const uint8_t** buffer, ReturnValue_t ParameterWrapper::deSerialize(const uint8_t** buffer,
int32_t* size, bool bigEndian, uint16_t startWritingAtIndex) { ssize_t* size, bool bigEndian, uint16_t startWritingAtIndex) {
ParameterWrapper streamDescription; ParameterWrapper streamDescription;
ReturnValue_t result = streamDescription.set(*buffer, *size, buffer, size); ReturnValue_t result = streamDescription.set(*buffer, *size, buffer, size);
@ -153,8 +153,8 @@ ReturnValue_t ParameterWrapper::deSerialize(const uint8_t** buffer,
return copyFrom(&streamDescription, startWritingAtIndex); return copyFrom(&streamDescription, startWritingAtIndex);
} }
ReturnValue_t ParameterWrapper::set(const uint8_t* stream, int32_t streamSize, ReturnValue_t ParameterWrapper::set(const uint8_t* stream, ssize_t streamSize,
const uint8_t **remainingStream, int32_t *remainingSize) { const uint8_t **remainingStream, ssize_t *remainingSize) {
ReturnValue_t result = SerializeAdapter<Type>::deSerialize(&type, &stream, ReturnValue_t result = SerializeAdapter<Type>::deSerialize(&type, &stream,
&streamSize, true); &streamSize, true);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {

View File

@ -25,15 +25,15 @@ public:
const void *data); const void *data);
virtual ~ParameterWrapper(); virtual ~ParameterWrapper();
virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
const uint32_t max_size, bool bigEndian) const; const size_t max_size, bool bigEndian) const;
virtual uint32_t getSerializedSize() const; virtual size_t getSerializedSize() const;
virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size,
bool bigEndian); bool bigEndian);
virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, virtual ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size,
bool bigEndian, uint16_t startWritingAtIndex = 0); bool bigEndian, uint16_t startWritingAtIndex = 0);
template<typename T> template<typename T>
@ -111,8 +111,8 @@ public:
void setMatrix(const T& member) { void setMatrix(const T& member) {
this->set(member[0], sizeof(member)/sizeof(member[0]), sizeof(member[0])/sizeof(member[0][0])); this->set(member[0], sizeof(member)/sizeof(member[0]), sizeof(member[0])/sizeof(member[0][0]));
} }
ReturnValue_t set(const uint8_t *stream, int32_t streamSize, ReturnValue_t set(const uint8_t *stream, ssize_t streamSize,
const uint8_t **remainingStream = NULL, int32_t *remainingSize = const uint8_t **remainingStream = NULL, ssize_t *remainingSize =
NULL); NULL);
ReturnValue_t copyFrom(const ParameterWrapper *from, ReturnValue_t copyFrom(const ParameterWrapper *from,
@ -128,8 +128,8 @@ private:
const void *readonlyData; const void *readonlyData;
template<typename T> template<typename T>
ReturnValue_t serializeData(uint8_t** buffer, uint32_t* size, ReturnValue_t serializeData(uint8_t** buffer, size_t* size,
const uint32_t max_size, bool bigEndian) const; const size_t max_size, bool bigEndian) const;
template<typename T> template<typename T>
ReturnValue_t deSerializeData(uint8_t startingRow, uint8_t startingColumn, ReturnValue_t deSerializeData(uint8_t startingRow, uint8_t startingColumn,

View File

@ -86,8 +86,8 @@ ReturnValue_t Fuse::check() {
return result; return result;
} }
ReturnValue_t Fuse::serialize(uint8_t** buffer, uint32_t* size, ReturnValue_t Fuse::serialize(uint8_t** buffer, size_t* size,
const uint32_t max_size, bool bigEndian) const { const size_t max_size, bool bigEndian) const {
ReturnValue_t result = RETURN_FAILED; ReturnValue_t result = RETURN_FAILED;
for (DeviceList::const_iterator iter = devices.begin(); for (DeviceList::const_iterator iter = devices.begin();
iter != devices.end(); iter++) { iter != devices.end(); iter++) {
@ -100,7 +100,7 @@ ReturnValue_t Fuse::serialize(uint8_t** buffer, uint32_t* size,
} }
uint32_t Fuse::getSerializedSize() const { uint32_t Fuse::getSerializedSize() const {
uint32_t size = 0; size_t size = 0;
for (DeviceList::const_iterator iter = devices.begin(); for (DeviceList::const_iterator iter = devices.begin();
iter != devices.end(); iter++) { iter != devices.end(); iter++) {
size += (*iter)->getSerializedSize(); size += (*iter)->getSerializedSize();
@ -108,7 +108,7 @@ uint32_t Fuse::getSerializedSize() const {
return size; return size;
} }
ReturnValue_t Fuse::deSerialize(const uint8_t** buffer, int32_t* size, ReturnValue_t Fuse::deSerialize(const uint8_t** buffer, ssize_t* size,
bool bigEndian) { bool bigEndian) {
ReturnValue_t result = RETURN_FAILED; ReturnValue_t result = RETURN_FAILED;
for (DeviceList::iterator iter = devices.begin(); iter != devices.end(); for (DeviceList::iterator iter = devices.begin(); iter != devices.end();

View File

@ -49,10 +49,10 @@ public:
uint8_t getFuseId() const; uint8_t getFuseId() const;
ReturnValue_t initialize(); ReturnValue_t initialize();
DeviceList devices; DeviceList devices;
ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, ReturnValue_t serialize(uint8_t** buffer, size_t* size,
const uint32_t max_size, bool bigEndian) const; const size_t max_size, bool bigEndian) const;
uint32_t getSerializedSize() const; uint32_t getSerializedSize() const;
ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size,
bool bigEndian); bool bigEndian);
void setAllMonitorsToUnchecked(); void setAllMonitorsToUnchecked();
ReturnValue_t performOperation(uint8_t opCode); ReturnValue_t performOperation(uint8_t opCode);

View File

@ -17,8 +17,8 @@ PowerComponent::PowerComponent(object_id_t setId, uint8_t moduleId, float min, f
twoSwitches), min(min), max(max), moduleId(moduleId) { twoSwitches), min(min), max(max), moduleId(moduleId) {
} }
ReturnValue_t PowerComponent::serialize(uint8_t** buffer, uint32_t* size, ReturnValue_t PowerComponent::serialize(uint8_t** buffer, size_t* size,
const uint32_t max_size, bool bigEndian) const { const size_t max_size, bool bigEndian) const {
ReturnValue_t result = SerializeAdapter<float>::serialize(&min, buffer, ReturnValue_t result = SerializeAdapter<float>::serialize(&min, buffer,
size, max_size, bigEndian); size, max_size, bigEndian);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
@ -28,7 +28,7 @@ ReturnValue_t PowerComponent::serialize(uint8_t** buffer, uint32_t* size,
bigEndian); bigEndian);
} }
uint32_t PowerComponent::getSerializedSize() const { size_t PowerComponent::getSerializedSize() const {
return sizeof(min) + sizeof(max); return sizeof(min) + sizeof(max);
} }
@ -56,8 +56,8 @@ float PowerComponent::getMax() {
return max; return max;
} }
ReturnValue_t PowerComponent::deSerialize(const uint8_t** buffer, int32_t* size, ReturnValue_t PowerComponent::deSerialize(const uint8_t** buffer, ssize_t* size,
bool bigEndian) { bool bigEndian) {
ReturnValue_t result = SerializeAdapter<float>::deSerialize(&min, buffer, ReturnValue_t result = SerializeAdapter<float>::deSerialize(&min, buffer,
size, bigEndian); size, bigEndian);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {

View File

@ -19,12 +19,12 @@ public:
float getMin(); float getMin();
float getMax(); float getMax();
ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, ReturnValue_t serialize(uint8_t** buffer, size_t* size,
const uint32_t max_size, bool bigEndian) const; const size_t max_size, bool bigEndian) const;
uint32_t getSerializedSize() const; size_t getSerializedSize() const;
ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, ReturnValue_t deSerialize(const uint8_t** buffer, ssize_t* size,
bool bigEndian); bool bigEndian);
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,

View File

@ -11,8 +11,13 @@
#include <framework/events/Event.h> #include <framework/events/Event.h>
#include <framework/returnvalues/HasReturnvaluesIF.h> #include <framework/returnvalues/HasReturnvaluesIF.h>
/** /**
* This interface defines a connection to a device that is capable of turning on and off *
* @brief This interface defines a connection to a device that is capable of turning on and off
* switches of devices identified by a switch ID. * switches of devices identified by a switch ID.
* @details The virtual functions of this interface do not allow to make any assignments
* because they can be called asynchronosuly (const ending).
*
* @ingroup interfaces
*/ */
class PowerSwitchIF : public HasReturnvaluesIF { class PowerSwitchIF : public HasReturnvaluesIF {
public: public:

View File

@ -24,6 +24,7 @@ enum {
MEMORY_HELPER, //MH MEMORY_HELPER, //MH
SERIALIZE_IF, //SE SERIALIZE_IF, //SE
FIXED_MAP, //FM FIXED_MAP, //FM
FIXED_MULTIMAP, //FMM
HAS_HEALTH_IF, //HHI HAS_HEALTH_IF, //HHI
FIFO_CLASS, //FF FIFO_CLASS, //FF
MESSAGE_PROXY, //MQP MESSAGE_PROXY, //MQP
@ -59,6 +60,7 @@ enum {
SGP4PROPAGATOR_CLASS, //SGP4 53 SGP4PROPAGATOR_CLASS, //SGP4 53
MUTEX_IF, //MUX 54 MUTEX_IF, //MUX 54
MESSAGE_QUEUE_IF,//MQI 55 MESSAGE_QUEUE_IF,//MQI 55
SEMAPHORE_IF, //SPH 56
FW_CLASS_ID_COUNT //is actually count + 1 ! FW_CLASS_ID_COUNT //is actually count + 1 !
}; };

View File

@ -1,27 +1,21 @@
#ifndef HASRETURNVALUESIF_H_ #ifndef HASRETURNVALUESIF_H_
#define HASRETURNVALUESIF_H_ #define HASRETURNVALUESIF_H_
#include <stdint.h>
#include <framework/returnvalues/FwClassIds.h> #include <framework/returnvalues/FwClassIds.h>
#include <config/returnvalues/classIds.h> #include <config/returnvalues/classIds.h>
#include <cstdint>
#define MAKE_RETURN_CODE( number ) ((INTERFACE_ID << 8) + (number)) #define MAKE_RETURN_CODE( number ) ((INTERFACE_ID << 8) + (number))
typedef uint16_t ReturnValue_t; typedef uint16_t ReturnValue_t;
class HasReturnvaluesIF { class HasReturnvaluesIF {
public: public:
static const ReturnValue_t RETURN_OK = 0; static const ReturnValue_t RETURN_OK = 0;
static const ReturnValue_t RETURN_FAILED = 1; static const ReturnValue_t RETURN_FAILED = 0xFFFF;
virtual ~HasReturnvaluesIF() { virtual ~HasReturnvaluesIF() {
} }
}; };
#endif /* HASRETURNVALUESIF_H_ */ #endif /* HASRETURNVALUESIF_H_ */

View File

@ -12,8 +12,8 @@ RMAP::RMAP(){
} }
ReturnValue_t RMAP::sendWriteCommand(RMAPCookie *cookie, uint8_t* buffer, ReturnValue_t RMAP::sendWriteCommand(RMAPCookie *cookie, const uint8_t* buffer,
uint32_t length) { size_t length) {
uint8_t instruction; uint8_t instruction;
if ((buffer == NULL) && (length != 0)) { if ((buffer == NULL) && (length != 0)) {
@ -61,7 +61,7 @@ ReturnValue_t RMAP::sendReadCommand(RMAPCookie *cookie, uint32_t expLength) {
} }
ReturnValue_t RMAP::getReadReply(RMAPCookie *cookie, uint8_t **buffer, ReturnValue_t RMAP::getReadReply(RMAPCookie *cookie, uint8_t **buffer,
uint32_t *size) { size_t *size) {
if (cookie->getChannel() == NULL) { if (cookie->getChannel() == NULL) {
return COMMAND_NO_CHANNEL; return COMMAND_NO_CHANNEL;
} }

View File

@ -153,8 +153,8 @@ public:
* - @c COMMAND_NULLPOINTER datalen was != 0 but data was == NULL in write command * - @c COMMAND_NULLPOINTER datalen was != 0 but data was == NULL in write command
* - return codes of RMAPChannelIF::sendCommand() * - return codes of RMAPChannelIF::sendCommand()
*/ */
static ReturnValue_t sendWriteCommand(RMAPCookie *cookie, uint8_t* buffer, static ReturnValue_t sendWriteCommand(RMAPCookie *cookie, const uint8_t* buffer,
uint32_t length); size_t length);
/** /**
* get the reply to a write command * get the reply to a write command
@ -204,7 +204,7 @@ public:
* - return codes of RMAPChannelIF::getReply() * - return codes of RMAPChannelIF::getReply()
*/ */
static ReturnValue_t getReadReply(RMAPCookie *cookie, uint8_t **buffer, static ReturnValue_t getReadReply(RMAPCookie *cookie, uint8_t **buffer,
uint32_t *size); size_t *size);
/** /**
* @see sendReadCommand() * @see sendReadCommand()

Some files were not shown because too many files have changed in this diff Show More