Merge branch 'master' into mueller_tcPacketBase

This commit is contained in:
Steffen Gaisser 2020-10-27 12:24:12 +01:00
commit 342a70d109
43 changed files with 1387 additions and 1423 deletions

View File

@ -1,15 +1,15 @@
#ifndef ARRAYLIST_H_ #ifndef FSFW_CONTAINER_ARRAYLIST_H_
#define ARRAYLIST_H_ #define FSFW_CONTAINER_ARRAYLIST_H_
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
#include "../serialize/SerializeAdapter.h" #include "../serialize/SerializeAdapter.h"
#include "../serialize/SerializeIF.h" #include "../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 by the class itself or supplied via ctor. * The underlying storage is an array that can be allocated by the class
* * itself or supplied via ctor.
* *
* @ingroup container * @ingroup container
*/ */
@ -20,6 +20,53 @@ public:
static const uint8_t INTERFACE_ID = CLASS_ID::ARRAY_LIST; static const uint8_t INTERFACE_ID = CLASS_ID::ARRAY_LIST;
static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01); static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01);
/**
* This is the allocating constructor.
* It allocates an array of the specified size.
* @param maxSize
*/
ArrayList(count_t maxSize) :
size(0), maxSize_(maxSize), allocated(true) {
entries = new T[maxSize];
}
/**
* This is the non-allocating constructor
*
* It expects a pointer to an array of a certain size and initializes
* itself to it.
*
* @param storage the array to use as backend
* @param maxSize size of storage
* @param size size of data already present in storage
*/
ArrayList(T *storage, count_t maxSize, count_t size = 0) :
size(size), entries(storage), maxSize_(maxSize), allocated(false) {
}
/**
* Copying is forbiden by declaring copy ctor and copy assignment deleted
* It is too ambigous in this case.
* (Allocate a new backend? Use the same? What to do in an modifying call?)
*/
ArrayList(const ArrayList& other) = delete;
const ArrayList& operator=(const ArrayList& other) = delete;
/**
* Number of Elements stored in this List
*/
count_t size;
/**
* Destructor, if the allocating constructor was used, it deletes the array.
*/
virtual ~ArrayList() {
if (allocated) {
delete[] entries;
}
}
/** /**
* An Iterator to go trough an ArrayList * An Iterator to go trough an ArrayList
* *
@ -31,10 +78,7 @@ public:
/** /**
* Empty ctor, points to NULL * Empty ctor, points to NULL
*/ */
Iterator() : Iterator(): value(0) {}
value(0) {
}
/** /**
* Initializes the Iterator to point to an element * Initializes the Iterator to point to an element
@ -72,71 +116,31 @@ public:
return tmp; return tmp;
} }
T& operator*(){ T& operator*() {
return *value; return *value;
} }
const T& operator*() const{ const T& operator*() const {
return *value; return *value;
} }
T *operator->(){ T *operator->() {
return value; return value;
} }
const T *operator->() const{ const T *operator->() const {
return value; return value;
} }
};
//SHOULDDO this should be implemented as non-member friend bool operator==(const ArrayList::Iterator& lhs,
bool operator==(const typename ArrayList<T, count_t>::Iterator& other) const{ const ArrayList::Iterator& rhs) {
return (value == other.value); return (lhs.value == rhs.value);
}
//SHOULDDO this should be implemented as non-member
bool operator!=(const typename ArrayList<T, count_t>::Iterator& other) const {
return !(*this == other);
}
}
;
/**
* Number of Elements stored in this List
*/
count_t size;
/**
* This is the allocating constructor;
*
* It allocates an array of the specified size.
*
* @param maxSize
*/
ArrayList(count_t maxSize) :
size(0), maxSize_(maxSize), allocated(true) {
entries = new T[maxSize];
} }
/** friend bool operator!=(const ArrayList::Iterator& lhs,
* This is the non-allocating constructor const ArrayList::Iterator& rhs) {
* return not (lhs.value == rhs.value);
* It expects a pointer to an array of a certain size and initializes itself to it.
*
* @param storage the array to use as backend
* @param maxSize size of storage
* @param size size of data already present in storage
*/
ArrayList(T *storage, count_t maxSize, count_t size = 0) :
size(size), entries(storage), maxSize_(maxSize), allocated(false) {
}
/**
* Destructor, if the allocating constructor was used, it deletes the array.
*/
virtual ~ArrayList() {
if (allocated) {
delete[] entries;
}
} }
/** /**
@ -192,7 +196,7 @@ public:
* *
* @return maximum number of elements * @return maximum number of elements
*/ */
uint32_t maxSize() const { size_t maxSize() const {
return this->maxSize_; return this->maxSize_;
} }
@ -227,19 +231,7 @@ public:
count_t remaining() { count_t remaining() {
return (maxSize_ - size); return (maxSize_ - size);
} }
private:
/**
* This is the copy constructor
*
* It is private, as copying is too ambigous in this case. (Allocate a new backend? Use the same?
* What to do in an modifying call?)
*
* @param other
*/
ArrayList(const ArrayList& other) :
size(other.size), entries(other.entries), maxSize_(other.maxSize_), allocated(
false) {
}
protected: protected:
/** /**
* pointer to the array in which the entries are stored * pointer to the array in which the entries are stored
@ -248,12 +240,14 @@ protected:
/** /**
* remembering the maximum size * remembering the maximum size
*/ */
uint32_t maxSize_; size_t maxSize_;
/** /**
* true if the array was allocated and needs to be deleted in the destructor. * true if the array was allocated and needs to be deleted in the destructor.
*/ */
bool allocated; bool allocated;
}; };
#endif /* ARRAYLIST_H_ */
#endif /* FSFW_CONTAINER_ARRAYLIST_H_ */

View File

@ -19,32 +19,46 @@ public:
/** /**
* Insert value into FIFO * Insert value into FIFO
* @param value * @param value
* @return * @return RETURN_OK on success, FULL if full
*/ */
ReturnValue_t insert(T value); ReturnValue_t insert(T value);
/** /**
* Retrieve item from FIFO. This removes the item from the FIFO. * Retrieve item from FIFO. This removes the item from the FIFO.
* @param value * @param value Must point to a valid T
* @return * @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed
*/ */
ReturnValue_t retrieve(T *value); ReturnValue_t retrieve(T *value);
/** /**
* Retrieve item from FIFO without removing it from FIFO. * Retrieve item from FIFO without removing it from FIFO.
* @param value * @param value Must point to a valid T
* @return * @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed
*/ */
ReturnValue_t peek(T * value); ReturnValue_t peek(T * value);
/** /**
* Remove item from FIFO. * Remove item from FIFO.
* @return * @return RETURN_OK on success, EMPTY if empty
*/ */
ReturnValue_t pop(); ReturnValue_t pop();
/***
* Check if FIFO is empty
* @return True if empty, False if not
*/
bool empty(); bool empty();
/***
* Check if FIFO is Full
* @return True if full, False if not
*/
bool full(); bool full();
/***
* Current used size (elements) used
* @return size_t in elements
*/
size_t size(); size_t size();
/***
* Get maximal capacity of fifo
* @return size_t with max capacity of this fifo
*/
size_t getMaxCapacity() const; size_t getMaxCapacity() const;
protected: protected:

View File

@ -26,6 +26,9 @@ inline ReturnValue_t FIFOBase<T>::retrieve(T* value) {
if (empty()) { if (empty()) {
return EMPTY; return EMPTY;
} else { } else {
if (value == nullptr){
return HasReturnvaluesIF::RETURN_FAILED;
}
*value = values[readIndex]; *value = values[readIndex];
readIndex = next(readIndex); readIndex = next(readIndex);
--currentSize; --currentSize;
@ -38,6 +41,9 @@ inline ReturnValue_t FIFOBase<T>::peek(T* value) {
if(empty()) { if(empty()) {
return EMPTY; return EMPTY;
} else { } else {
if (value == nullptr){
return HasReturnvaluesIF::RETURN_FAILED;
}
*value = values[readIndex]; *value = values[readIndex];
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -2,11 +2,13 @@
#define FIXEDARRAYLIST_H_ #define FIXEDARRAYLIST_H_
#include "ArrayList.h" #include "ArrayList.h"
#include <cmath>
/** /**
* \ingroup container * \ingroup container
*/ */
template<typename T, uint32_t MAX_SIZE, typename count_t = uint8_t> template<typename T, size_t MAX_SIZE, typename count_t = uint8_t>
class FixedArrayList: public ArrayList<T, count_t> { class FixedArrayList: public ArrayList<T, count_t> {
static_assert(MAX_SIZE <= (pow(2,sizeof(count_t)*8)-1), "count_t is not large enough to hold MAX_SIZE");
private: private:
T data[MAX_SIZE]; T data[MAX_SIZE];
public: public:
@ -18,11 +20,13 @@ public:
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));
this->entries = data; this->entries = data;
this->size = other.size;
} }
FixedArrayList& operator=(FixedArrayList other) { FixedArrayList& operator=(FixedArrayList other) {
memcpy(this->data, other.data, sizeof(this->data)); memcpy(this->data, other.data, sizeof(this->data));
this->entries = data; this->entries = data;
this->size = other.size;
return *this; return *this;
} }

View File

@ -7,14 +7,21 @@
#include <type_traits> #include <type_traits>
/** /**
* @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).
* @warning Iterators return a non-const key_t in the pair. * @warning Iterators return a non-const key_t in the pair.
* @warning A User is not allowed to change the key, otherwise the map is corrupted. * @warning A User is not allowed to change the key, otherwise the map is corrupted.
* @ingroup container * @ingroup container
*/ */
template<typename key_t, typename T> template<typename key_t, typename T>
class FixedMap: public SerializeIF { class FixedMap: public SerializeIF {
static_assert (std::is_trivially_copyable<T>::value or std::is_base_of<SerializeIF, T>::value, static_assert (std::is_trivially_copyable<T>::value or
"Types used in FixedMap must either be trivial copy-able or a derived Class from SerializeIF to be serialize-able"); std::is_base_of<SerializeIF, T>::value,
"Types used in FixedMap must either be trivial copy-able or a "
"derived class from SerializeIF to be serialize-able");
public: public:
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP; static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP;
static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01); static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01);
@ -54,6 +61,16 @@ public:
} }
}; };
friend bool operator==(const typename FixedMap::Iterator& lhs,
const typename FixedMap::Iterator& rhs) {
return (lhs.value == rhs.value);
}
friend bool operator!=(const typename FixedMap::Iterator& lhs,
const typename FixedMap::Iterator& rhs) {
return not (lhs.value == rhs.value);
}
Iterator begin() const { Iterator begin() const {
return Iterator(&theMap[0]); return Iterator(&theMap[0]);
} }
@ -136,6 +153,24 @@ public:
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
bool empty() {
if(_size == 0) {
return true;
}
else {
return false;
}
}
bool full() {
if(_size >= theMap.maxSize()) {
return true;
}
else {
return false;
}
}
void clear() { void clear() {
_size = 0; _size = 0;
} }

View File

@ -1,166 +1,206 @@
#ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ #ifndef FSFW_CONTAINER_FIXEDORDEREDMULTIMAP_H_
#define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ #define FSFW_CONTAINER_FIXEDORDEREDMULTIMAP_H_
#include "ArrayList.h" #include "ArrayList.h"
#include <cstring> #include <cstring>
#include <set>
/** /**
* @brief An associative container which allows multiple entries of the same key.
* @details
* Same keys are ordered by KEY_COMPARE function which is std::less<key_t> > by default.
*
* It uses the ArrayList, so technically this is not a real map, it is an array of pairs
* of type key_t, T. It is ordered by key_t as FixedMap but allows same keys. Thus it has a linear
* complexity O(n). As long as the number of entries remains low, this
* should not be an issue.
* The number of insertion and deletion operation should be minimized
* as those incur extensive memory move operations (the underlying container
* is not node based).
*
* Its of fixed size so no allocations are performed after the construction.
*
* The maximum size is given as first parameter of the constructor.
*
* It provides an iterator to do list iterations.
*
* The type T must have a copy constructor if it is not trivial copy-able.
*
* @warning Iterators return a non-const key_t in the pair.
* @warning A User is not allowed to change the key, otherwise the map is corrupted.
*
* \ingroup container * \ingroup container
*/ */
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 MAP_FULL = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02); static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);
private: /***
typedef KEY_COMPARE compare; * Constructor which needs a size_t for the maximum allowed size
compare myComp; *
ArrayList<std::pair<key_t, T>, uint32_t> theMap; * Can not be resized during runtime
uint32_t _size; *
* Allocates memory at construction
* @param maxSize size_t of Maximum allowed size
*/
FixedOrderedMultimap(size_t maxSize):theMap(maxSize), _size(0){
}
uint32_t findFirstIndex(key_t key, uint32_t startAt = 0) const { /***
if (startAt >= _size) { * Virtual destructor frees Memory by deleting its member
return startAt + 1; */
}
uint32_t i = startAt;
for (i = startAt; i < _size; ++i) {
if (theMap[i].first == key) {
return i;
}
}
return i;
}
uint32_t findNicePlace(key_t key) const {
uint32_t i = 0;
for (i = 0; i < _size; ++i) {
if (myComp(key, theMap[i].first)) {
return i;
}
}
return i;
}
void removeFromPosition(uint32_t position) {
if (_size <= position) {
return;
}
memmove(static_cast<void*>(&theMap[position]), static_cast<void*>(&theMap[position + 1]),
(_size - position - 1) * sizeof(std::pair<key_t,T>));
--_size;
}
public:
FixedOrderedMultimap(uint32_t maxSize) :
theMap(maxSize), _size(0) {
}
virtual ~FixedOrderedMultimap() { virtual ~FixedOrderedMultimap() {
} }
class Iterator: public ArrayList<std::pair<key_t, T>, uint32_t>::Iterator { /***
* Special iterator for FixedOrderedMultimap
*/
class Iterator: public ArrayList<std::pair<key_t, T>, size_t>::Iterator {
public: public:
Iterator() : Iterator() :
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator() { ArrayList<std::pair<key_t, T>, size_t>::Iterator() {
} }
Iterator(std::pair<key_t, T> *pair) : Iterator(std::pair<key_t, T> *pair) :
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator(pair) { ArrayList<std::pair<key_t, T>, size_t>::Iterator(pair) {
} }
}; };
/***
* Returns an iterator pointing to the first element
* @return Iterator pointing to first element
*/
Iterator begin() const { Iterator begin() const {
return Iterator(&theMap[0]); return Iterator(&theMap[0]);
} }
/**
* Returns an iterator pointing to one element past the end
* @return Iterator pointing to one element past the end
*/
Iterator end() const { Iterator end() const {
return Iterator(&theMap[_size]); return Iterator(&theMap[_size]);
} }
uint32_t size() const { /***
* Returns the current size of the map (not maximum size!)
* @return Current size
*/
size_t size() const{
return _size; return _size;
} }
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr) { /**
if (_size == theMap.maxSize()) { * Clears the map, does not deallocate any memory
return MAP_FULL; */
} void clear(){
uint32_t position = findNicePlace(key); _size = 0;
memmove(static_cast<void*>(&theMap[position + 1]),static_cast<void*>(&theMap[position]),
(_size - position) * sizeof(std::pair<key_t,T>));
theMap[position].first = key;
theMap[position].second = value;
++_size;
if (storedValue != nullptr) {
*storedValue = Iterator(&theMap[position]);
}
return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t insert(std::pair<key_t, T> pair) { /**
return insert(pair.fist, pair.second); * Returns the maximum size of the map
* @return Maximum size of the map
*/
size_t maxSize() const{
return theMap.maxSize();
} }
ReturnValue_t exists(key_t key) const { /***
ReturnValue_t result = KEY_DOES_NOT_EXIST; * Used to insert a key and value separately.
if (findFirstIndex(key) < _size) { *
result = HasReturnvaluesIF::RETURN_OK; * @param[in] key Key of the new element
} * @param[in] value Value of the new element
return result; * @param[in/out] (optional) storedValue On success this points to the new value, otherwise a nullptr
} * @return RETURN_OK if insert was successful, MAP_FULL if no space is available
*/
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr);
ReturnValue_t erase(Iterator *iter) { /***
uint32_t i; * Used to insert new pair instead of single values
if ((i = findFirstIndex((*iter).value->first)) >= _size) { *
return KEY_DOES_NOT_EXIST; * @param pair Pair to be inserted
} * @return RETURN_OK if insert was successful, MAP_FULL if no space is available
removeFromPosition(i); */
if (*iter != begin()) { ReturnValue_t insert(std::pair<key_t, T> pair);
(*iter)--;
} else {
*iter = begin();
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t erase(key_t key) { /***
uint32_t i; * Can be used to check if a certain key is in the map
if ((i = findFirstIndex(key)) >= _size) { * @param key Key to be checked
return KEY_DOES_NOT_EXIST; * @return RETURN_OK if the key exists KEY_DOES_NOT_EXIST otherwise
} */
do { ReturnValue_t exists(key_t key) const;
removeFromPosition(i);
i = findFirstIndex(key, i);
} while (i < _size);
return HasReturnvaluesIF::RETURN_OK;
}
Iterator find(key_t key) const { /***
* Used to delete the element in the iterator
*
* The iterator will point to the element before or begin(),
* but never to one element in front of the map.
*
* @warning The iterator needs to be valid and dereferenceable
* @param[in/out] iter Pointer to iterator to the element that needs to be ereased
* @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this
*/
ReturnValue_t erase(Iterator *iter);
/***
* Used to erase by key
* @param key Key to be erased
* @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this
*/
ReturnValue_t erase(key_t key);
/***
* Find returns the first appearance of the key
*
* If the key does not exist, it points to end()
*
* @param key Key to search for
* @return Iterator pointing to the first entry of key
*/
Iterator find(key_t key) const{
ReturnValue_t result = exists(key); ReturnValue_t result = exists(key);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return end(); return end();
} }
return Iterator(&theMap[findFirstIndex(key)]); return Iterator(&theMap[findFirstIndex(key)]);
};
/***
* Finds first entry of the given key and returns a
* pointer to the value
*
* @param key Key to search for
* @param value Found value
* @return RETURN_OK if it points to the value,
* KEY_DOES_NOT_EXIST if the key is not in the map
*/
ReturnValue_t find(key_t key, T **value) const;
friend bool operator==(const typename FixedOrderedMultimap::Iterator& lhs,
const typename FixedOrderedMultimap::Iterator& rhs) {
return (lhs.value == rhs.value);
} }
ReturnValue_t find(key_t key, T **value) const { friend bool operator!=(const typename FixedOrderedMultimap::Iterator& lhs,
ReturnValue_t result = exists(key); const typename FixedOrderedMultimap::Iterator& rhs) {
if (result != HasReturnvaluesIF::RETURN_OK) { return not (lhs.value == rhs.value);
return result;
}
*value = &theMap[findFirstIndex(key)].second;
return HasReturnvaluesIF::RETURN_OK;
} }
void clear() { private:
_size = 0; typedef KEY_COMPARE compare;
} compare myComp;
ArrayList<std::pair<key_t, T>, size_t> theMap;
size_t _size;
uint32_t maxSize() const { size_t findFirstIndex(key_t key, size_t startAt = 0) const;
return theMap.maxSize();
}
size_t findNicePlace(key_t key) const;
void removeFromPosition(size_t position);
}; };
#endif /* FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ */ #include "FixedOrderedMultimap.tpp"
#endif /* FSFW_CONTAINER_FIXEDORDEREDMULTIMAP_H_ */

View File

@ -0,0 +1,109 @@
#ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_
#define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_
template<typename key_t, typename T, typename KEY_COMPARE>
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(key_t key, T value, Iterator *storedValue) {
if (_size == theMap.maxSize()) {
return MAP_FULL;
}
size_t position = findNicePlace(key);
memmove(static_cast<void*>(&theMap[position + 1]),static_cast<void*>(&theMap[position]),
(_size - position) * sizeof(std::pair<key_t,T>));
theMap[position].first = key;
theMap[position].second = value;
++_size;
if (storedValue != nullptr) {
*storedValue = Iterator(&theMap[position]);
}
return HasReturnvaluesIF::RETURN_OK;
}
template<typename key_t, typename T, typename KEY_COMPARE>
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(std::pair<key_t, T> pair) {
return insert(pair.first, pair.second);
}
template<typename key_t, typename T, typename KEY_COMPARE>
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::exists(key_t key) const {
ReturnValue_t result = KEY_DOES_NOT_EXIST;
if (findFirstIndex(key) < _size) {
result = HasReturnvaluesIF::RETURN_OK;
}
return result;
}
template<typename key_t, typename T, typename KEY_COMPARE>
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(Iterator *iter) {
size_t i;
if ((i = findFirstIndex((*iter).value->first)) >= _size) {
return KEY_DOES_NOT_EXIST;
}
removeFromPosition(i);
if (*iter != begin()) {
(*iter)--;
} else {
*iter = begin();
}
return HasReturnvaluesIF::RETURN_OK;
}
template<typename key_t, typename T, typename KEY_COMPARE>
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(key_t key) {
size_t i;
if ((i = findFirstIndex(key)) >= _size) {
return KEY_DOES_NOT_EXIST;
}
do {
removeFromPosition(i);
i = findFirstIndex(key, i);
} while (i < _size);
return HasReturnvaluesIF::RETURN_OK;
}
template<typename key_t, typename T, typename KEY_COMPARE>
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::find(key_t key, T **value) const {
ReturnValue_t result = exists(key);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
*value = &theMap[findFirstIndex(key)].second;
return HasReturnvaluesIF::RETURN_OK;
}
template<typename key_t, typename T, typename KEY_COMPARE>
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findFirstIndex(key_t key, size_t startAt) const {
if (startAt >= _size) {
return startAt + 1;
}
size_t i = startAt;
for (i = startAt; i < _size; ++i) {
if (theMap[i].first == key) {
return i;
}
}
return i;
}
template<typename key_t, typename T, typename KEY_COMPARE>
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findNicePlace(key_t key) const {
size_t i = 0;
for (i = 0; i < _size; ++i) {
if (myComp(key, theMap[i].first)) {
return i;
}
}
return i;
}
template<typename key_t, typename T, typename KEY_COMPARE>
inline void FixedOrderedMultimap<key_t, T, KEY_COMPARE>::removeFromPosition(size_t position) {
if (_size <= position) {
return;
}
memmove(static_cast<void*>(&theMap[position]), static_cast<void*>(&theMap[position + 1]),
(_size - position - 1) * sizeof(std::pair<key_t,T>));
--_size;
}
#endif /* FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ */

View File

@ -3,26 +3,62 @@
#include "../storagemanager/StorageManagerIF.h" #include "../storagemanager/StorageManagerIF.h"
#include <utility> #include <utility>
/**
* The Placement Factory is used to create objects at runtime in a specific pool.
* In general, this should be avoided and it should only be used if you know what you are doing.
* You are not allowed to use this container with a type that allocates memory internally like ArrayList.
*
* Also, you have to check the returned pointer in generate against nullptr!
*
* A backend of Type StorageManagerIF must be given as a place to store the new objects.
* Therefore ThreadSafety is only provided by your StorageManager Implementation.
*
* Objects must be destroyed by the user with "destroy"! Otherwise the pool will not be cleared.
*
* The concept is based on the placement new operator.
*
* @warning Do not use with any Type that allocates memory internally!
* @ingroup container
*/
class PlacementFactory { class PlacementFactory {
public: public:
PlacementFactory(StorageManagerIF* backend) : PlacementFactory(StorageManagerIF* backend) :
dataBackend(backend) { dataBackend(backend) {
} }
/***
* Generates an object of type T in the backend storage.
*
* @warning Do not use with any Type that allocates memory internally!
*
* @tparam T Type of Object
* @param args Constructor Arguments to be passed
* @return A pointer to the new object or a nullptr in case of failure
*/
template<typename T, typename ... Args> template<typename T, typename ... Args>
T* generate(Args&&... args) { T* generate(Args&&... args) {
store_address_t tempId; store_address_t tempId;
uint8_t* pData = NULL; uint8_t* pData = nullptr;
ReturnValue_t result = dataBackend->getFreeElement(&tempId, sizeof(T), ReturnValue_t result = dataBackend->getFreeElement(&tempId, sizeof(T),
&pData); &pData);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return NULL; return nullptr;
} }
T* temp = new (pData) T(std::forward<Args>(args)...); T* temp = new (pData) T(std::forward<Args>(args)...);
return temp; return temp;
} }
/***
* Function to destroy the object allocated with generate and free space in backend.
* This must be called by the user.
*
* @param thisElement Element to be destroyed
* @return RETURN_OK if the element was destroyed, different errors on failure
*/
template<typename T> template<typename T>
ReturnValue_t destroy(T* thisElement) { ReturnValue_t destroy(T* thisElement) {
if (thisElement == nullptr){
return HasReturnvaluesIF::RETURN_FAILED;
}
//Need to call destructor first, in case something was allocated by the object (shouldn't do that, however). //Need to call destructor first, in case something was allocated by the object (shouldn't do that, however).
thisElement->~T(); thisElement->~T();
uint8_t* pointer = (uint8_t*) (thisElement); uint8_t* pointer = (uint8_t*) (thisElement);

View File

@ -1,79 +0,0 @@
#include <iostream>
#include "SimpleRingBuffer.h"
int main() {
using namespace std;
SimpleRingBuffer buffer(64, false);
uint8_t data[8] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};
ReturnValue_t result = buffer.writeData(data, 8);
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "writeData failed." << endl;
}
result = buffer.writeData(data, 8);
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "writeData failed." << endl;
}
uint8_t buffer2[47] = {0};
for (uint8_t count = 0; count<sizeof(buffer2); count++) {
buffer2[count] = count;
}
result = buffer.writeData(buffer2, sizeof(buffer2));
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "writeData failed." << endl;
}
result = buffer.writeData(buffer2, sizeof(buffer2));
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "writeData failed." << endl;
}
uint8_t readBuffer[64] = {0};
uint32_t writtenData = 0;
result = buffer.readData(readBuffer, 12, true, &writtenData);
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "readData failed." << endl;
} else {
cout << "Read data: " << writtenData << endl;
for (uint32_t count = 0; count < writtenData; count++) {
cout << hex << (uint16_t)readBuffer[count] << " ";
}
cout << dec << endl;
}
result = buffer.readData(readBuffer, 60, true, &writtenData);
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "readData failed." << endl;
} else {
cout << "Read data: " << writtenData << endl;
for (uint32_t count = 0; count < writtenData; count++) {
cout << hex << (uint16_t)readBuffer[count] << " ";
}
cout << dec << endl;
}
result = buffer.writeData(data, sizeof(data));
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "writeData failed." << endl;
}
result = buffer.readData(readBuffer, 60, true, &writtenData);
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "readData failed." << endl;
} else {
cout << "Read data: " << writtenData << endl;
for (uint32_t count = 0; count < writtenData; count++) {
cout << hex << (uint16_t)readBuffer[count] << " ";
}
cout << dec << endl;
}
result = buffer.writeData(readBuffer, sizeof(readBuffer));
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "writeData failed." << endl;
}
result = buffer.writeData(readBuffer, sizeof(readBuffer)-1);
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "writeData failed." << endl;
} else {
cout << "write done." << endl;
}
}

View File

@ -1,365 +0,0 @@
#include "FixedArrayList.h"
#include "SinglyLinkedList.h"
#include "HybridIterator.h"
#include "FixedMap.h"
#include <stdio.h>
/*
class Packet: public SinglyLinkedList {
public:
SinglyLinkedList::Element<uint32_t> element1;
SinglyLinkedList::Element<uint32_t> element2;
Packet() {
this->start = &element1;
element1.next = &element2;
}
};
class Packet2: public SinglyLinkedList {
public:
SinglyLinkedList::Element<uint32_t> element1;
SinglyLinkedList::Element<FixedArrayList<FixedArrayList<uint8_t, 5>, 2>> element2;
SinglyLinkedList::Element<uint32_t> element3;
Packet2() {
this->start = &element1;
element1.next = &element2;
element2.next = &element3;
}
};
class Packet3: public SinglyLinkedList {
public:
SinglyLinkedList::TypedElement<uint32_t> element1;
SinglyLinkedList::TypedElement<uint32_t> element2;
Packet3() {
this->start = &element1;
element1.next = &element2;
}
};
void arrayList() {
puts("** Array List **");
FixedArrayList<uint32_t, 10, uint32_t> list;
FixedArrayList<uint32_t, 10, uint32_t> list2;
list.size = 2;
list[0] = 0xcafecafe;
list[1] = 0x12345678;
uint8_t buffer[100];
uint8_t *pointer = buffer;
uint32_t size = 0;
uint32_t maxSize = 100;
uint32_t i;
int32_t size2;
printf("printsize: %i\n", list.getPrintSize());
list.print(&pointer, &size, 100, true);
printf("buffer(%i):", size);
for (i = 0; i < size; ++i) {
printf("%02x", buffer[i]);
}
printf("\n");
pointer = buffer;
size2 = size;
printf("list2 read: %x\n", list2.read(&pointer, &size2, true));
printf("list2(%i):", list2.size);
for (ArrayList<uint32_t, uint32_t>::Iterator iter = list2.begin();
iter != list2.end(); iter++) {
printf("0x%04x ", *iter);
}
printf("\n");
HybridIterator<uint32_t, uint32_t> hiter(list.begin(),list.end());
printf("hybrid1: 0x%04x\n", *(hiter++));
printf("hybrid2: 0x%04x\n", *hiter);
}
void allocatingList() {
puts("** Allocating List **");
ArrayList<uint8_t> myList(3), myList2(2);
myList[0] = 0xab;
myList[1] = 0xcd;
myList.size = 2;
uint8_t buffer[100];
uint8_t *pointer = buffer;
uint32_t size = 0;
uint32_t maxSize = 100;
uint32_t i;
int32_t size2;
myList.print(&pointer, &size, 100, true);
pointer = buffer;
size2 = size;
printf("Read %x\n", myList2.read(&pointer, &size2, true));
printf("%x,%x\n", myList2[0], myList2[1]);
}
void linkedList() {
puts("** Linked List **");
uint8_t buffer[100];
uint8_t *pointer = buffer;
uint32_t size = 0;
uint32_t maxSize = 100;
uint32_t i;
int32_t size2;
Packet myPacket;
myPacket.element1.entry = 0x12345678;
myPacket.element2.entry = 0x9abcdef0;
pointer = buffer;
size = 0;
ReturnValue_t result = myPacket.print(&pointer, &size, 100, true);
printf("result %02x\n", result);
printf("printsize: %i\n", myPacket.getPrintSize());
printf("buffer(%i):", size);
for (i = 0; i < size; ++i) {
printf("%02x", buffer[i]);
}
printf("\n");
Packet3 myPacket3;
myPacket3.element1.entry = 0x12345678;
myPacket3.element2.entry = 0xabcdeff;
SinglyLinkedList::TypedIterator<uint32_t> titer(&myPacket3.element1);
printf("0x%04x\n", *titer);
HybridIterator<uint32_t, uint32_t> hiter(&myPacket3.element1);
printf("hybrid1: 0x%04x\n", *hiter);
hiter++;
printf("hybrid2: 0x%04x\n", *hiter);
}
void complex() {
puts("** complex **");
uint8_t buffer[100];
uint8_t *pointer = buffer;
uint32_t size = 0;
uint32_t maxSize = 100;
uint32_t i;
int32_t size2 = size;
Packet myPacket2;
size2 = size;
pointer = buffer;
myPacket2.read(&pointer, &size2, true);
printf("packet: 0x%04x, 0x%04x\n", myPacket2.element1.entry,
myPacket2.element2.entry);
buffer[0] = 0x12;
buffer[1] = 0x34;
buffer[2] = 0x56;
buffer[3] = 0x78;
buffer[4] = 0x2;
buffer[5] = 0x3;
buffer[6] = 0xab;
buffer[7] = 0xcd;
buffer[8] = 0xef;
buffer[9] = 0x2;
buffer[10] = 0x11;
buffer[11] = 0x22;
buffer[12] = 0xca;
buffer[13] = 0xfe;
buffer[14] = 0x5a;
buffer[15] = 0xfe;
pointer = buffer;
size2 = 23;
Packet2 p2;
ReturnValue_t result = p2.read(&pointer, &size2, true);
printf("result is %02x\n", result);
printf("%04x; %i: %i: %x %x %x; %i: %x %x;; %04x\n", p2.element1.entry,
p2.element2.entry.size, p2.element2.entry[0].size,
p2.element2.entry[0][0], p2.element2.entry[0][1],
p2.element2.entry[0][2], p2.element2.entry[1].size,
p2.element2.entry[1][0], p2.element2.entry[1][1],
p2.element3.entry);
}
*/
struct Test {
uint32_t a;
uint32_t b;
};
template<typename key_t, typename T>
void printMap(FixedMap<key_t, T> *map) {
typename FixedMap<key_t, T>::Iterator iter;
printf("Map (%i): ", map->getSize());
for (iter = map->begin(); iter != map->end(); ++iter) {
printf("%x:%08x,%08x ", iter.value->first, (*iter).a, (*iter).b);
}
printf("\n");
}
template<typename T>
void map() {
puts("** Map **");
typename FixedMap<T, Test>::Iterator iter;
ReturnValue_t result;
FixedMap<T, Test> myMap(5);
printMap<T, Test>(&myMap);
Test a;
a.a = 0x01234567;
a.b = 0xabcdef89;
myMap.insert(1, a);
printMap<T, Test>(&myMap);
a.a = 0;
myMap.insert(2, a);
printMap<T, Test>(&myMap);
printf("2 exists: %x\n", myMap.exists(0x02));
printf("ff exists: %x\n", myMap.exists(0xff));
a.a = 1;
printf("insert 0x2: %x\n", myMap.insert(2, a));
result = myMap.insert(0xff, a);
a.a = 0x44;
result = myMap.insert(0xab, a);
result = myMap.insert(0xa, a);
printMap<T, Test>(&myMap);
printf("insert 0x5: %x\n", myMap.insert(5, a));
printf("erase 0xfe: %x\n", myMap.erase(0xfe));
printf("erase 0x2: %x\n", myMap.erase(0x2));
printMap<T, Test>(&myMap);
printf("erase 0xab: %x\n", myMap.erase(0xab));
printMap<T, Test>(&myMap);
printf("insert 0x5: %x\n", myMap.insert(5, a));
printMap<T, Test>(&myMap);
iter = myMap.begin();
++iter;
++iter;
++iter;
printf("iter: %i: %x,%x\n",iter.value->first, iter->a, iter->b);
myMap.erase(&iter);
printf("iter: %i: %x,%x\n",iter.value->first, iter->a, iter->b);
printMap<T, Test>(&myMap);
}
/*
void mapPrint() {
puts("** Map Print **");
FixedMap<uint16_t, Packet2> myMap(5);
Packet2 myPacket;
myPacket.element1.entry = 0x12345678;
myPacket.element2.entry[0][0] = 0xab;
myPacket.element2.entry[0][1] = 0xcd;
myPacket.element2.entry[0].size = 2;
myPacket.element2.entry.size = 1;
myPacket.element3.entry = 0xabcdef90;
myMap.insert(0x1234, myPacket);
uint8_t buffer[100];
uint32_t size = 0, i;
uint8_t *pointer = buffer;
printf("printsize: %i\n", myMap.getPrintSize());
SerializeAdapter<FixedMap<uint16_t, Packet2>>::print(&myMap, &pointer,
&size, 100, false);
printf("buffer(%i):", size);
for (i = 0; i < size; ++i) {
printf("%02x", buffer[i]);
}
printf("\n");
int32_t size2 = size;
pointer = buffer;
FixedMap<uint16_t, Packet2> myMap2(5);
ReturnValue_t result = SerializeAdapter<FixedMap<uint16_t, Packet2>>::read(
&myMap2, &pointer, &size2, false);
Packet2 *myPacket2 = myMap2.find(0x1234);
printf("Map (%i): Packet2: %x, Array (%i): Array (%i): %x, %x; %x\n",
myMap2.getSize(), myPacket2->element1.entry,
myPacket2->element2.entry.size, myPacket2->element2.entry[0].size,
myPacket2->element2.entry[0][0], myPacket2->element2.entry[0][1],
myPacket2->element3.entry);
}
void empty() {
puts("** Empty **");
ArrayList<uint32_t> list(0);
printf("%p %p\n", list.front(), list.back());
}
*/
int main(void) {
// arrayList();
// linkedList();
// allocatingList();
// complex();
map<uint32_t>();
//
// mapPrint();
// empty();
return 0;
}

View File

@ -1,61 +1,77 @@
#ifndef FSFW_IPC_MESSAGEQUEUEIF_H_ #ifndef FSFW_IPC_MESSAGEQUEUEIF_H_
#define FSFW_IPC_MESSAGEQUEUEIF_H_ #define FSFW_IPC_MESSAGEQUEUEIF_H_
// COULDDO: We could support blocking calls
#include "messageQueueDefinitions.h" #include "messageQueueDefinitions.h"
#include "MessageQueueMessage.h" #include "MessageQueueMessageIF.h"
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
#include <cstdint>
// COULDDO: We could support blocking calls
// semaphores are being implemented, which makes this idea even more iteresting.
/**
* @defgroup message_queue Message Queue
* @brief Message Queue related software components
*/
class MessageQueueIF { class MessageQueueIF {
public: public:
static const MessageQueueId_t NO_QUEUE = 0; static const MessageQueueId_t NO_QUEUE = 0;
static const uint8_t INTERFACE_ID = CLASS_ID::MESSAGE_QUEUE_IF; static const uint8_t INTERFACE_ID = CLASS_ID::MESSAGE_QUEUE_IF;
/** //! No new messages on the queue
* No new messages on the queue
*/
static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(1); static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(1);
/** //! No space left for more messages
* No space left for more messages
*/
static const ReturnValue_t FULL = MAKE_RETURN_CODE(2); static const ReturnValue_t FULL = MAKE_RETURN_CODE(2);
/** //! Returned if a reply method was called without partner
* Returned if a reply method was called without partner
*/
static const ReturnValue_t NO_REPLY_PARTNER = MAKE_RETURN_CODE(3); static const ReturnValue_t NO_REPLY_PARTNER = MAKE_RETURN_CODE(3);
//! Returned if the target destination is invalid.
static constexpr ReturnValue_t DESTINVATION_INVALID = MAKE_RETURN_CODE(4);
virtual ~MessageQueueIF() {} virtual ~MessageQueueIF() {}
/** /**
* @brief This operation sends a message to the last communication partner. * @brief This operation sends a message to the last communication partner.
* @details This operation simplifies answering an incoming message by using the stored * @details
* lastParnter information as destination. If there was no message received yet * This operation simplifies answering an incoming message by using the
* (i.e. lastPartner is zero), an error code is returned. * stored lastParnter information as destination. If there was no message
* @param message A pointer to a previously created message, which is sent. * received yet (i.e. lastPartner is zero), an error code is returned.
* \return RETURN_OK if ok * @param message
* \return NO_REPLY_PARTNER Should return NO_REPLY_PARTNER if partner was found * A pointer to a previously created message, which is sent.
* @return
* -@c RETURN_OK if ok
* -@c NO_REPLY_PARTNER Should return NO_REPLY_PARTNER if partner was found.
*/ */
virtual ReturnValue_t reply( MessageQueueMessage* message ) = 0; virtual ReturnValue_t reply(MessageQueueMessageIF* message) = 0;
/** /**
* @brief This function reads available messages from the message queue and returns the sender. * @brief This function reads available messages from the message queue
* @details It works identically to the other receiveMessage call, but in addition returns the * and returns the sender.
* sender's queue id. * @details
* @param message A pointer to a message in which the received data is stored. * It works identically to the other receiveMessage call, but in addition
* @param receivedFrom A pointer to a queue id in which the sender's id is stored. * returns the sender's queue id.
* @param message
* A pointer to a message in which the received data is stored.
* @param receivedFrom
* A pointer to a queue id in which the sender's id is stored.
*/ */
virtual ReturnValue_t receiveMessage(MessageQueueMessage* message, virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t *receivedFrom) = 0; MessageQueueId_t *receivedFrom) = 0;
/** /**
* @brief This function reads available messages from the message queue. * @brief This function reads available messages from the message queue.
* @details If data is available it is stored in the passed message pointer. The message's * @details
* original content is overwritten and the sendFrom information is stored in the * If data is available it is stored in the passed message pointer.
* lastPartner attribute. Else, the lastPartner information remains untouched, the * The message's original content is overwritten and the sendFrom
* message's content is cleared and the function returns immediately. * information is stored in theblastPartner attribute. Else, the lastPartner
* @param message A pointer to a message in which the received data is stored. * information remains untouched, the message's content is cleared and the
* function returns immediately.
* @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(MessageQueueMessageIF* message) = 0;
/** /**
* Deletes all pending messages in the queue. * Deletes all pending messages in the queue.
* @param count The number of flushed messages. * @param count The number of flushed messages.
@ -63,57 +79,89 @@ public:
*/ */
virtual ReturnValue_t flush(uint32_t* count) = 0; virtual ReturnValue_t flush(uint32_t* count) = 0;
/** /**
* @brief This method returns the message queue id of the last communication partner. * @brief This method returns the message queue
* id of the last communication partner.
*/ */
virtual MessageQueueId_t getLastPartner() const = 0; virtual MessageQueueId_t getLastPartner() const = 0;
/** /**
* @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.
*/ */
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
* \details This method takes the message provided, adds the sentFrom information and passes * is sent to a receiving queue.
* it on to the destination provided with an operating system call. The OS's return * @details
* value is returned. * This method takes the message provided, adds the sentFrom information
* \param sendTo This parameter specifies the message queue id to send the message to. * and passes it on to the destination provided with an operating system
* \param message This is a pointer to a previously created message, which is sent. * call. The OS's returnvalue is returned.
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. * @param sendTo
* This variable is set to zero by default. * This parameter specifies the message queue id to send the message to.
* \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full (if implemented). * @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 (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,
/** MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
* @brief This operation sends a message to the given destination. bool ignoreFault = false ) = 0;
* @details It directly uses the sendMessage call of the MessageQueueSender parent, but passes its
* queue id as "sentFrom" parameter.
* @param sendTo This parameter specifies the message queue id of the destination message queue.
* @param message A pointer to a previously created message, which is sent.
* @param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
*/
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 This operation sends a message to the given destination.
* \details In all other aspects, it works identical to the sendMessage method. * @details
* \param message This is a pointer to a previously created message, which is sent. * It directly uses the sendMessage call of the MessageQueueSender parent,
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. * but passes its queue id as "sentFrom" parameter.
* This variable is set to zero by default. * @param sendTo
* This parameter specifies the message queue id of the destination
* message queue.
* @param message
* A pointer to a previously created message, which is sent.
* @param ignoreFault
* If set to true, the internal software fault counter is not incremented
* if queue is full.
*/ */
virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0; virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo,
MessageQueueMessageIF* message, bool ignoreFault = false ) = 0;
/**
* @brief The sendToDefaultFrom 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.
* @return -@c RETURN_OK on success
* -@c MessageQueueIF::FULL if queue is full
*/
virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0;
/** /**
* @brief This operation sends a message to the default destination. * @brief This operation sends a message to the default destination.
* @details As in the sendMessage method, this function uses the sendToDefault call of the * @details
* Implementation class and adds its queue id as "sentFrom" information. * As in the sendMessage method, this function uses the sendToDefault
* call of the 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( MessageQueueMessageIF* message ) = 0;
/** /**
* \brief This method is a simple setter for the default destination. * @brief This method is a simple setter for the default destination.
*/ */
virtual void setDefaultDestination(MessageQueueId_t defaultDestination) = 0; virtual void setDefaultDestination(MessageQueueId_t defaultDestination) = 0;
/** /**
* \brief This method is a simple getter for the default destination. * @brief This method is a simple getter for the default destination.
*/ */
virtual MessageQueueId_t getDefaultDestination() const = 0; virtual MessageQueueId_t getDefaultDestination() const = 0;
@ -122,4 +170,4 @@ public:
#endif /* FRAMEWORK_IPC_MESSAGEQUEUEIF_H_ */ #endif /* FSFW_IPC_MESSAGEQUEUEIF_H_ */

View File

@ -1,8 +1,8 @@
#ifndef FSFW_IPC_MESSAGEQUEUESENDERIF_H_ #ifndef FSFW_IPC_MESSAGEQUEUESENDERIF_H_
#define FSFW_IPC_MESSAGEQUEUESENDERIF_H_ #define FSFW_IPC_MESSAGEQUEUESENDERIF_H_
#include "../ipc/MessageQueueIF.h" #include "MessageQueueIF.h"
#include "../ipc/MessageQueueMessageIF.h" #include "MessageQueueMessageIF.h"
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
class MessageQueueSenderIF { class MessageQueueSenderIF {
@ -15,7 +15,7 @@ public:
* Not sure whether this is actually a good idea. * Not sure whether this is actually a good idea.
*/ */
static ReturnValue_t sendMessage(MessageQueueId_t sendTo, static ReturnValue_t sendMessage(MessageQueueId_t sendTo,
MessageQueueMessage* message, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom = MessageQueueIF::NO_QUEUE, MessageQueueId_t sentFrom = MessageQueueIF::NO_QUEUE,
bool ignoreFault = false); bool ignoreFault = false);
private: private:

View File

@ -1,8 +1,10 @@
#ifndef FRAMEWORK_IPC_QUEUEFACTORY_H_ #ifndef FSFW_IPC_QUEUEFACTORY_H_
#define FRAMEWORK_IPC_QUEUEFACTORY_H_ #define FSFW_IPC_QUEUEFACTORY_H_
#include "MessageQueueIF.h" #include "MessageQueueIF.h"
#include <stdint.h> #include "MessageQueueMessage.h"
#include <cstdint>
/** /**
* Creates message queues. * Creates message queues.
* This class is a "singleton" interface, i.e. it provides an * This class is a "singleton" interface, i.e. it provides an
@ -30,4 +32,4 @@ private:
static QueueFactory* factoryInstance; static QueueFactory* factoryInstance;
}; };
#endif /* FRAMEWORK_IPC_QUEUEFACTORY_H_ */ #endif /* FSFW_IPC_QUEUEFACTORY_H_ */

View File

@ -1,12 +1,5 @@
/** #ifndef FSFW_MEMORY_ACCEPTSMEMORYMESSAGESIF_H_
* @file AcceptsMemoryMessagesIF.h #define FSFW_MEMORY_ACCEPTSMEMORYMESSAGESIF_H_
* @brief This file defines the AcceptsMemoryMessagesIF class.
* @date 11.07.2013
* @author baetz
*/
#ifndef ACCEPTSMEMORYMESSAGESIF_H_
#define ACCEPTSMEMORYMESSAGESIF_H_
#include "HasMemoryIF.h" #include "HasMemoryIF.h"
#include "MemoryMessage.h" #include "MemoryMessage.h"
@ -18,4 +11,4 @@ public:
}; };
#endif /* ACCEPTSMEMORYMESSAGESIF_H_ */ #endif /* FSFW_MEMORY_ACCEPTSMEMORYMESSAGESIF_H_ */

View File

@ -1,14 +1,15 @@
#include "../globalfunctions/CRC.h"
#include "MemoryHelper.h" #include "MemoryHelper.h"
#include "MemoryMessage.h" #include "MemoryMessage.h"
#include "../globalfunctions/CRC.h"
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
#include "../serialize/EndianConverter.h" #include "../serialize/EndianConverter.h"
#include "../serviceinterface/ServiceInterfaceStream.h" #include "../serviceinterface/ServiceInterfaceStream.h"
MemoryHelper::MemoryHelper(HasMemoryIF* workOnThis, MessageQueueIF* useThisQueue) : MemoryHelper::MemoryHelper(HasMemoryIF* workOnThis,
workOnThis(workOnThis), queueToUse(useThisQueue), ipcStore(NULL), ipcAddress(), lastCommand( MessageQueueIF* useThisQueue):
CommandMessage::CMD_NONE), lastSender(0), reservedSpaceInIPC( workOnThis(workOnThis), queueToUse(useThisQueue), ipcAddress(),
NULL), busy(false) { lastCommand(CommandMessage::CMD_NONE), busy(false) {
} }
ReturnValue_t MemoryHelper::handleMemoryCommand(CommandMessage* message) { ReturnValue_t MemoryHelper::handleMemoryCommand(CommandMessage* message) {
@ -33,17 +34,8 @@ ReturnValue_t MemoryHelper::handleMemoryCommand(CommandMessage* message) {
} }
} }
ReturnValue_t MemoryHelper::initialize() {
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
if (ipcStore != NULL) {
return RETURN_OK;
} else {
return RETURN_FAILED;
}
}
void MemoryHelper::completeLoad(ReturnValue_t errorCode, void MemoryHelper::completeLoad(ReturnValue_t errorCode,
const uint8_t* dataToCopy, const uint32_t size, uint8_t* copyHere) { const uint8_t* dataToCopy, const size_t size, uint8_t* copyHere) {
busy = false; busy = false;
switch (errorCode) { switch (errorCode) {
case HasMemoryIF::DO_IT_MYSELF: case HasMemoryIF::DO_IT_MYSELF:
@ -67,13 +59,13 @@ void MemoryHelper::completeLoad(ReturnValue_t errorCode,
return; return;
} }
//Only reached on success //Only reached on success
CommandMessage reply(CommandMessage::REPLY_COMMAND_OK, 0, 0); CommandMessage reply( CommandMessage::REPLY_COMMAND_OK, 0, 0);
queueToUse->sendMessage(lastSender, &reply); queueToUse->sendMessage(lastSender, &reply);
ipcStore->deleteData(ipcAddress); ipcStore->deleteData(ipcAddress);
} }
void MemoryHelper::completeDump(ReturnValue_t errorCode, void MemoryHelper::completeDump(ReturnValue_t errorCode,
const uint8_t* dataToCopy, const uint32_t size) { const uint8_t* dataToCopy, const size_t size) {
busy = false; busy = false;
CommandMessage reply; CommandMessage reply;
MemoryMessage::setMemoryReplyFailed(&reply, errorCode, lastCommand); MemoryMessage::setMemoryReplyFailed(&reply, errorCode, lastCommand);
@ -125,12 +117,12 @@ void MemoryHelper::completeDump(ReturnValue_t errorCode,
break; break;
} }
if (queueToUse->sendMessage(lastSender, &reply) != RETURN_OK) { if (queueToUse->sendMessage(lastSender, &reply) != RETURN_OK) {
reply.clearCommandMessage(); reply.clear();
} }
} }
void MemoryHelper::swapMatrixCopy(uint8_t* out, const uint8_t *in, void MemoryHelper::swapMatrixCopy(uint8_t* out, const uint8_t *in,
uint32_t totalSize, uint8_t datatypeSize) { size_t totalSize, uint8_t datatypeSize) {
if (totalSize % datatypeSize != 0){ if (totalSize % datatypeSize != 0){
return; return;
} }
@ -185,11 +177,18 @@ void MemoryHelper::handleMemoryCheckOrDump(CommandMessage* message) {
} }
ReturnValue_t MemoryHelper::initialize(MessageQueueIF* queueToUse_) { ReturnValue_t MemoryHelper::initialize(MessageQueueIF* queueToUse_) {
if(queueToUse_!=NULL){ if(queueToUse_ == nullptr) {
this->queueToUse = queueToUse_; return HasReturnvaluesIF::RETURN_FAILED;
}else{
return MessageQueueIF::NO_QUEUE;
} }
this->queueToUse = queueToUse_;
return initialize(); return initialize();
} }
ReturnValue_t MemoryHelper::initialize() {
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
if (ipcStore != nullptr) {
return RETURN_OK;
} else {
return RETURN_FAILED;
}
}

View File

@ -1,11 +1,16 @@
#ifndef MEMORYHELPER_H_ #ifndef FSFW_MEMORY_MEMORYHELPER_H_
#define MEMORYHELPER_H_ #define FSFW_MEMORY_MEMORYHELPER_H_
#include "../ipc/CommandMessage.h"
#include "AcceptsMemoryMessagesIF.h" #include "AcceptsMemoryMessagesIF.h"
#include "../ipc/CommandMessage.h"
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
#include "../storagemanager/StorageManagerIF.h" #include "../storagemanager/StorageManagerIF.h"
#include "../ipc/MessageQueueIF.h" #include "../ipc/MessageQueueIF.h"
/**
* @brief TODO: documentation.
*/
class MemoryHelper : public HasReturnvaluesIF { class MemoryHelper : public HasReturnvaluesIF {
public: public:
static const uint8_t INTERFACE_ID = CLASS_ID::MEMORY_HELPER; static const uint8_t INTERFACE_ID = CLASS_ID::MEMORY_HELPER;
@ -13,25 +18,32 @@ public:
static const ReturnValue_t INVALID_ADDRESS = MAKE_RETURN_CODE(0xE1); static const ReturnValue_t INVALID_ADDRESS = MAKE_RETURN_CODE(0xE1);
static const ReturnValue_t INVALID_SIZE = MAKE_RETURN_CODE(0xE2); static const ReturnValue_t INVALID_SIZE = MAKE_RETURN_CODE(0xE2);
static const ReturnValue_t STATE_MISMATCH = MAKE_RETURN_CODE(0xE3); static const ReturnValue_t STATE_MISMATCH = MAKE_RETURN_CODE(0xE3);
MemoryHelper(HasMemoryIF* workOnThis, MessageQueueIF* useThisQueue);
~MemoryHelper();
ReturnValue_t handleMemoryCommand(CommandMessage* message);
void completeLoad(ReturnValue_t errorCode,
const uint8_t* dataToCopy = nullptr, const size_t size = 0,
uint8_t* copyHere = nullptr);
void completeDump(ReturnValue_t errorCode,
const uint8_t* dataToCopy = nullptr, const size_t size = 0);
void swapMatrixCopy(uint8_t *out, const uint8_t *in, size_t totalSize,
uint8_t datatypeSize);
ReturnValue_t initialize(MessageQueueIF* queueToUse_);
private: private:
HasMemoryIF* workOnThis; HasMemoryIF* workOnThis;
MessageQueueIF* queueToUse; MessageQueueIF* queueToUse;
StorageManagerIF* ipcStore; StorageManagerIF* ipcStore = nullptr;
store_address_t ipcAddress; store_address_t ipcAddress;
Command_t lastCommand; Command_t lastCommand;
MessageQueueId_t lastSender; MessageQueueId_t lastSender = MessageQueueIF::NO_QUEUE;
uint8_t* reservedSpaceInIPC; uint8_t* reservedSpaceInIPC = nullptr;
bool busy; bool busy;
void handleMemoryLoad(CommandMessage* message); void handleMemoryLoad(CommandMessage* message);
void handleMemoryCheckOrDump(CommandMessage* message); void handleMemoryCheckOrDump(CommandMessage* message);
ReturnValue_t initialize(); ReturnValue_t initialize();
public:
ReturnValue_t handleMemoryCommand(CommandMessage* message);
void completeLoad( ReturnValue_t errorCode, const uint8_t* dataToCopy = NULL, const uint32_t size = 0, uint8_t* copyHere = NULL );
void completeDump( ReturnValue_t errorCode, const uint8_t* dataToCopy = NULL, const uint32_t size = 0);
void swapMatrixCopy( uint8_t *out, const uint8_t *in, uint32_t totalSize, uint8_t datatypeSize);
ReturnValue_t initialize(MessageQueueIF* queueToUse_);
MemoryHelper( HasMemoryIF* workOnThis, MessageQueueIF* useThisQueue );
~MemoryHelper();
}; };
#endif /* MEMORYHELPER_H_ */ #endif /* FSFW_MEMORY_MEMORYHELPER_H_ */

View File

@ -1,7 +1,6 @@
#include "MemoryMessage.h" #include "MemoryMessage.h"
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
MemoryMessage::MemoryMessage() {
}
uint32_t MemoryMessage::getAddress(const CommandMessage* message) { uint32_t MemoryMessage::getAddress(const CommandMessage* message) {
return message->getParameter(); return message->getParameter();
@ -17,26 +16,24 @@ uint32_t MemoryMessage::getLength(const CommandMessage* message) {
return message->getParameter2(); return message->getParameter2();
} }
ReturnValue_t MemoryMessage::setMemoryDumpCommand(CommandMessage* message, void MemoryMessage::setMemoryDumpCommand(CommandMessage* message,
uint32_t address, uint32_t length) { uint32_t address, uint32_t length) {
message->setCommand(CMD_MEMORY_DUMP); message->setCommand(CMD_MEMORY_DUMP);
message->setParameter( address ); message->setParameter( address );
message->setParameter2( length ); message->setParameter2( length );
return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t MemoryMessage::setMemoryDumpReply(CommandMessage* message, store_address_t storageID) { void MemoryMessage::setMemoryDumpReply(CommandMessage* message,
store_address_t storageID) {
message->setCommand(REPLY_MEMORY_DUMP); message->setCommand(REPLY_MEMORY_DUMP);
message->setParameter2( storageID.raw ); message->setParameter2( storageID.raw );
return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t MemoryMessage::setMemoryLoadCommand(CommandMessage* message, void MemoryMessage::setMemoryLoadCommand(CommandMessage* message,
uint32_t address, store_address_t storageID) { uint32_t address, store_address_t storageID) {
message->setCommand(CMD_MEMORY_LOAD); message->setCommand(CMD_MEMORY_LOAD);
message->setParameter( address ); message->setParameter( address );
message->setParameter2( storageID.raw ); message->setParameter2( storageID.raw );
return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t MemoryMessage::getErrorCode(const CommandMessage* message) { ReturnValue_t MemoryMessage::getErrorCode(const CommandMessage* message) {
@ -65,22 +62,21 @@ void MemoryMessage::clear(CommandMessage* message) {
} }
} }
ReturnValue_t MemoryMessage::setMemoryCheckCommand(CommandMessage* message, void MemoryMessage::setMemoryCheckCommand(CommandMessage* message,
uint32_t address, uint32_t length) { uint32_t address, uint32_t length) {
message->setCommand(CMD_MEMORY_CHECK); message->setCommand(CMD_MEMORY_CHECK);
message->setParameter( address ); message->setParameter( address );
message->setParameter2( length ); message->setParameter2( length );
return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t MemoryMessage::setMemoryCheckReply(CommandMessage* message, void MemoryMessage::setMemoryCheckReply(CommandMessage* message,
uint16_t crc) { uint16_t crc) {
message->setCommand(REPLY_MEMORY_CHECK); message->setCommand(REPLY_MEMORY_CHECK);
message->setParameter( crc ); message->setParameter( crc );
return HasReturnvaluesIF::RETURN_OK;
} }
void MemoryMessage::setCrcReturnValue(CommandMessage* message, ReturnValue_t returnValue){ void MemoryMessage::setCrcReturnValue(CommandMessage* message,
ReturnValue_t returnValue){
message->setParameter(returnValue<<16); message->setParameter(returnValue<<16);
}; };
@ -96,18 +92,16 @@ Command_t MemoryMessage::getInitialCommand(const CommandMessage* message) {
return message->getParameter2(); return message->getParameter2();
} }
ReturnValue_t MemoryMessage::setMemoryReplyFailed(CommandMessage* message, void MemoryMessage::setMemoryReplyFailed(CommandMessage* message,
ReturnValue_t errorCode, Command_t initialCommand) { ReturnValue_t errorCode, Command_t initialCommand) {
message->setCommand(REPLY_MEMORY_FAILED); message->setCommand(REPLY_MEMORY_FAILED);
message->setParameter(errorCode); message->setParameter(errorCode);
message->setParameter2(initialCommand); message->setParameter2(initialCommand);
return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t MemoryMessage::setMemoryCopyEnd(CommandMessage* message) { void MemoryMessage::setMemoryCopyEnd(CommandMessage* message) {
message->setCommand(END_OF_MEMORY_COPY); message->setCommand(END_OF_MEMORY_COPY);
message->setParameter(0); message->setParameter(0);
message->setParameter2(0); message->setParameter2(0);
return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -1,14 +1,15 @@
#ifndef MEMORYMESSAGE_H_ #ifndef FSFW_MEMORY_MEMORYMESSAGE_H_
#define MEMORYMESSAGE_H_ #define FSFW_MEMORY_MEMORYMESSAGE_H_
#include "../ipc/CommandMessage.h" #include "../ipc/CommandMessage.h"
#include "../storagemanager/StorageManagerIF.h" #include "../storagemanager/StorageManagerIF.h"
class MemoryMessage { class MemoryMessage {
private:
MemoryMessage(); //A private ctor inhibits instantiation
public: public:
// Instantiation forbidden.
MemoryMessage() = delete;
static const uint8_t MESSAGE_ID = messagetypes::MEMORY; static const uint8_t MESSAGE_ID = messagetypes::MEMORY;
static const Command_t CMD_MEMORY_LOAD = MAKE_COMMAND_ID( 0x01 ); static const Command_t CMD_MEMORY_LOAD = MAKE_COMMAND_ID( 0x01 );
static const Command_t CMD_MEMORY_DUMP = MAKE_COMMAND_ID( 0x02 ); static const Command_t CMD_MEMORY_DUMP = MAKE_COMMAND_ID( 0x02 );
@ -19,21 +20,29 @@ public:
static const Command_t END_OF_MEMORY_COPY = MAKE_COMMAND_ID(0xF0); static const Command_t END_OF_MEMORY_COPY = MAKE_COMMAND_ID(0xF0);
static uint32_t getAddress( const CommandMessage* message ); static uint32_t getAddress( const CommandMessage* message );
static store_address_t getStoreID( const CommandMessage* message ); static store_address_t getStoreID(const CommandMessage* message);
static uint32_t getLength( const CommandMessage* message ); static uint32_t getLength( const CommandMessage* message );
static ReturnValue_t getErrorCode( const CommandMessage* message ); static ReturnValue_t getErrorCode(const CommandMessage* message);
static ReturnValue_t setMemoryDumpCommand( CommandMessage* message, uint32_t address, uint32_t length ); static uint16_t getCrc(const CommandMessage* message );
static ReturnValue_t setMemoryDumpReply( CommandMessage* message, store_address_t storageID ); static ReturnValue_t getCrcReturnValue(const CommandMessage* message);
static ReturnValue_t setMemoryLoadCommand( CommandMessage* message, uint32_t address, store_address_t storageID ); static Command_t getInitialCommand(const CommandMessage* message);
static ReturnValue_t setMemoryCheckCommand( CommandMessage* message, uint32_t address, uint32_t length );
static ReturnValue_t setMemoryCheckReply( CommandMessage* message, uint16_t crc ); static void setMemoryDumpCommand(CommandMessage* message,
static ReturnValue_t setMemoryReplyFailed( CommandMessage* message, ReturnValue_t errorCode, Command_t initialCommand ); uint32_t address, uint32_t length );
static ReturnValue_t setMemoryCopyEnd( CommandMessage* message); static void setMemoryDumpReply(CommandMessage* message,
store_address_t storageID);
static void setMemoryLoadCommand(CommandMessage* message,
uint32_t address, store_address_t storageID );
static void setMemoryCheckCommand(CommandMessage* message,
uint32_t address, uint32_t length);
static void setMemoryCheckReply(CommandMessage* message,
uint16_t crc);
static void setMemoryReplyFailed(CommandMessage* message,
ReturnValue_t errorCode, Command_t initialCommand);
static void setMemoryCopyEnd(CommandMessage* message);
static void setCrcReturnValue(CommandMessage*, ReturnValue_t returnValue); static void setCrcReturnValue(CommandMessage*, ReturnValue_t returnValue);
static uint16_t getCrc( const CommandMessage* message );
static ReturnValue_t getCrcReturnValue(const CommandMessage* message);
static Command_t getInitialCommand( const CommandMessage* message );
static void clear(CommandMessage* message); static void clear(CommandMessage* message);
}; };
#endif /* MEMORYMESSAGE_H_ */ #endif /* FSFW_MEMORY_MEMORYMESSAGE_H_ */

View File

@ -1,22 +0,0 @@
#ifndef FRAMEWORK_MEMORY_MEMORYPROXYIF_H_
#define FRAMEWORK_MEMORY_MEMORYPROXYIF_H_
#include "AcceptsMemoryMessagesIF.h"
/**
* This was a nice idea to transparently forward incoming messages to another object.
* But it doesn't work like that.
*/
class MemoryProxyIF : public AcceptsMemoryMessagesIF {
public:
virtual MessageQueueId_t getProxyQueue() const = 0;
MessageQueueId_t getCommandQueue() const {
return getProxyQueue();
}
virtual ~MemoryProxyIF() {}
};
#endif /* FRAMEWORK_MEMORY_MEMORYPROXYIF_H_ */

View File

@ -1,18 +1,11 @@
/** #ifndef FSFW_MODES_HASMODESIF_H_
* @file HasModesIF.h #define FSFW_MODES_HASMODESIF_H_
* @brief This file defines the HasModesIF class.
* @date 20.06.2013
* @author baetz
*/
#ifndef HASMODESIF_H_
#define HASMODESIF_H_
#include "../events/Event.h"
#include "ModeHelper.h" #include "ModeHelper.h"
#include "ModeMessage.h" #include "ModeMessage.h"
#include "../events/Event.h"
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
#include <stdint.h> #include <cstdint>
class HasModesIF { class HasModesIF {
@ -37,21 +30,22 @@ public:
static const Mode_t MODE_ON = 1; //!< 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 static const Mode_t MODE_ON = 1; //!< 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
static const Mode_t MODE_OFF = 0; //!< The device is powered off. The only command accepted in this mode is a mode change to on. static const Mode_t MODE_OFF = 0; //!< The device is powered off. The only command accepted in this mode is a mode change to on.
static const Submode_t SUBMODE_NONE = 0; //!< To avoid checks against magic number "0". static const Submode_t SUBMODE_NONE = 0; //!< To avoid checks against magic number "0".
virtual ~HasModesIF() {
} virtual ~HasModesIF() {}
virtual MessageQueueId_t getCommandQueue() const = 0; virtual MessageQueueId_t getCommandQueue() const = 0;
virtual void getMode(Mode_t *mode, Submode_t *submode) = 0; virtual void getMode(Mode_t *mode, Submode_t *submode) = 0;
protected: protected:
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) { uint32_t *msToReachTheMode) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
virtual void startTransition(Mode_t mode, Submode_t submode) {
} virtual void startTransition(Mode_t mode, Submode_t submode) {}
virtual void setToExternalControl() {
} virtual void setToExternalControl() {}
virtual void announceMode(bool recursive) {
} virtual void announceMode(bool recursive) {}
}; };
#endif /* HASMODESIF_H_ */ #endif /*FSFW_MODES_HASMODESIF_H_ */

View File

@ -1,38 +1,39 @@
#include "HasModesIF.h" #include "HasModesIF.h"
#include "ModeHelper.h" #include "ModeHelper.h"
#include "../ipc/MessageQueueSenderIF.h" #include "../ipc/MessageQueueSenderIF.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
ModeHelper::ModeHelper(HasModesIF *owner) : ModeHelper::ModeHelper(HasModesIF *owner) :
theOneWhoCommandedAMode(0), commandedMode(HasModesIF::MODE_OFF), commandedSubmode( commandedMode(HasModesIF::MODE_OFF),
HasModesIF::SUBMODE_NONE), owner(owner), parentQueueId(0), forced( commandedSubmode(HasModesIF::SUBMODE_NONE),
false) { owner(owner), forced(false) {}
}
ModeHelper::~ModeHelper() { ModeHelper::~ModeHelper() {
} }
ReturnValue_t ModeHelper::handleModeCommand(CommandMessage* message) { ReturnValue_t ModeHelper::handleModeCommand(CommandMessage* command) {
CommandMessage reply; CommandMessage reply;
Mode_t mode; Mode_t mode;
Submode_t submode; Submode_t submode;
switch (message->getCommand()) { switch (command->getCommand()) {
case ModeMessage::CMD_MODE_COMMAND_FORCED: case ModeMessage::CMD_MODE_COMMAND_FORCED:
forced = true; forced = true;
/* NO BREAK falls through*/ /* NO BREAK falls through*/
case ModeMessage::CMD_MODE_COMMAND: { case ModeMessage::CMD_MODE_COMMAND: {
mode = ModeMessage::getMode(message); mode = ModeMessage::getMode(command);
submode = ModeMessage::getSubmode(message); submode = ModeMessage::getSubmode(command);
uint32_t timeout; uint32_t timeout;
ReturnValue_t result = owner->checkModeCommand(mode, submode, &timeout); ReturnValue_t result = owner->checkModeCommand(mode, submode, &timeout);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
ModeMessage::cantReachMode(&reply, result); ModeMessage::setCantReachMode(&reply, result);
MessageQueueSenderIF::sendMessage(message->getSender(), &reply, MessageQueueSenderIF::sendMessage(command->getSender(), &reply,
owner->getCommandQueue()); owner->getCommandQueue());
break; break;
} }
//Free to start transition //Free to start transition
theOneWhoCommandedAMode = message->getSender(); theOneWhoCommandedAMode = command->getSender();
commandedMode = mode; commandedMode = mode;
commandedSubmode = submode; commandedSubmode = submode;
@ -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;
@ -50,8 +50,8 @@ ReturnValue_t ModeHelper::handleModeCommand(CommandMessage* message) {
owner->getMode(&mode, &submode); owner->getMode(&mode, &submode);
ModeMessage::setModeMessage(&reply, ModeMessage::REPLY_MODE_REPLY, mode, ModeMessage::setModeMessage(&reply, ModeMessage::REPLY_MODE_REPLY, mode,
submode); submode);
MessageQueueSenderIF::sendMessage(message->getSender(), &reply, MessageQueueSenderIF::sendMessage(command->getSender(), &reply,
owner->getCommandQueue()); owner->getCommandQueue());
} }
break; break;
case ModeMessage::CMD_MODE_ANNOUNCE: case ModeMessage::CMD_MODE_ANNOUNCE:
@ -71,27 +71,45 @@ ReturnValue_t ModeHelper::initialize(MessageQueueId_t parentQueueId) {
return initialize(); return initialize();
} }
void ModeHelper::modeChanged(Mode_t mode, Submode_t submode) { void ModeHelper::modeChanged(Mode_t ownerMode, Submode_t ownerSubmode) {
forced = false; forced = false;
sendModeReplyMessage(ownerMode, ownerSubmode);
sendModeInfoMessage(ownerMode, ownerSubmode);
theOneWhoCommandedAMode = MessageQueueIF::NO_QUEUE;
}
void ModeHelper::sendModeReplyMessage(Mode_t ownerMode,
Submode_t ownerSubmode) {
CommandMessage reply; CommandMessage reply;
if (theOneWhoCommandedAMode != MessageQueueIF::NO_QUEUE) { if (theOneWhoCommandedAMode != MessageQueueIF::NO_QUEUE)
if ((mode != commandedMode) || (submode != commandedSubmode)) { {
if (ownerMode != commandedMode or ownerSubmode != commandedSubmode)
{
ModeMessage::setModeMessage(&reply, ModeMessage::setModeMessage(&reply,
ModeMessage::REPLY_WRONG_MODE_REPLY, mode, submode); ModeMessage::REPLY_WRONG_MODE_REPLY, ownerMode,
} else { ownerSubmode);
}
else
{
ModeMessage::setModeMessage(&reply, ModeMessage::REPLY_MODE_REPLY, ModeMessage::setModeMessage(&reply, ModeMessage::REPLY_MODE_REPLY,
mode, submode); ownerMode, ownerSubmode);
} }
MessageQueueSenderIF::sendMessage(theOneWhoCommandedAMode, &reply, MessageQueueSenderIF::sendMessage(theOneWhoCommandedAMode, &reply,
owner->getCommandQueue()); owner->getCommandQueue());
} }
}
void ModeHelper::sendModeInfoMessage(Mode_t ownerMode,
Submode_t ownerSubmode) {
CommandMessage reply;
if (theOneWhoCommandedAMode != parentQueueId if (theOneWhoCommandedAMode != parentQueueId
&& parentQueueId != MessageQueueIF::NO_QUEUE) { and parentQueueId != MessageQueueIF::NO_QUEUE)
ModeMessage::setModeMessage(&reply, ModeMessage::REPLY_MODE_INFO, mode, {
submode); ModeMessage::setModeMessage(&reply, ModeMessage::REPLY_MODE_INFO,
MessageQueueSenderIF::sendMessage(parentQueueId, &reply, owner->getCommandQueue()); ownerMode, ownerSubmode);
MessageQueueSenderIF::sendMessage(parentQueueId, &reply,
owner->getCommandQueue());
} }
theOneWhoCommandedAMode = MessageQueueIF::NO_QUEUE;
} }
void ModeHelper::startTimer(uint32_t timeoutMs) { void ModeHelper::startTimer(uint32_t timeoutMs) {

View File

@ -1,7 +1,8 @@
#ifndef MODEHELPER_H_ #ifndef FSFW_MODES_MODEHELPER_H_
#define MODEHELPER_H_ #define FSFW_MODES_MODEHELPER_H_
#include "ModeMessage.h" #include "ModeMessage.h"
#include "../ipc/MessageQueueIF.h"
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
#include "../timemanager/Countdown.h" #include "../timemanager/Countdown.h"
@ -9,7 +10,7 @@ class HasModesIF;
class ModeHelper { class ModeHelper {
public: public:
MessageQueueId_t theOneWhoCommandedAMode; MessageQueueId_t theOneWhoCommandedAMode = MessageQueueIF::NO_QUEUE;
Mode_t commandedMode; Mode_t commandedMode;
Submode_t commandedSubmode; Submode_t commandedSubmode;
@ -19,14 +20,14 @@ public:
ReturnValue_t handleModeCommand(CommandMessage *message); ReturnValue_t handleModeCommand(CommandMessage *message);
/** /**
* * @param parentQueue the Queue id of the parent object.
* @param parentQueue the Queue id of the parent object. Set to 0 if no parent present * Set to 0 if no parent present
*/ */
void setParentQueue(MessageQueueId_t parentQueueId); void setParentQueue(MessageQueueId_t parentQueueId);
ReturnValue_t initialize(MessageQueueId_t parentQueueId); ReturnValue_t initialize(MessageQueueId_t parentQueueId);
ReturnValue_t initialize(void); //void is there to stop eclipse CODAN from falsely reporting an error ReturnValue_t initialize(void);
void modeChanged(Mode_t mode, Submode_t submode); void modeChanged(Mode_t mode, Submode_t submode);
@ -39,11 +40,14 @@ public:
void setForced(bool forced); void setForced(bool forced);
protected: protected:
HasModesIF *owner; HasModesIF *owner;
MessageQueueId_t parentQueueId; MessageQueueId_t parentQueueId = MessageQueueIF::NO_QUEUE;
Countdown countdown; Countdown countdown;
bool forced; bool forced;
private:
void sendModeReplyMessage(Mode_t ownerMode, Submode_t ownerSubmode);
void sendModeInfoMessage(Mode_t ownerMode, Submode_t ownerSubmode);
}; };
#endif /* MODEHELPER_H_ */ #endif /* FSFW_MODES_MODEHELPER_H_ */

View File

@ -8,12 +8,11 @@ Submode_t ModeMessage::getSubmode(const CommandMessage* message) {
return message->getParameter2(); return message->getParameter2();
} }
ReturnValue_t ModeMessage::setModeMessage(CommandMessage* message, Command_t command, void ModeMessage::setModeMessage(CommandMessage* message,
Mode_t mode, Submode_t submode) { Command_t command, Mode_t mode, Submode_t submode) {
message->setCommand( command ); message->setCommand( command );
message->setParameter( mode ); message->setParameter( mode );
message->setParameter2( submode ); message->setParameter2( submode );
return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t ModeMessage::getCantReachModeReason(const CommandMessage* message) { ReturnValue_t ModeMessage::getCantReachModeReason(const CommandMessage* message) {
@ -24,7 +23,8 @@ void ModeMessage::clear(CommandMessage* message) {
message->setCommand(CommandMessage::CMD_NONE); message->setCommand(CommandMessage::CMD_NONE);
} }
void ModeMessage::cantReachMode(CommandMessage* message, ReturnValue_t reason) { void ModeMessage::setCantReachMode(CommandMessage* message,
ReturnValue_t reason) {
message->setCommand(REPLY_CANT_REACH_MODE); message->setCommand(REPLY_CANT_REACH_MODE);
message->setParameter(reason); message->setParameter(reason);
message->setParameter2(0); message->setParameter2(0);

View File

@ -1,12 +1,5 @@
/** #ifndef FSFW_MODES_MODEMESSAGE_H_
* @file ModeMessage.h #define FSFW_MODES_MODEMESSAGE_H_
* @brief This file defines the ModeMessage class.
* @date 17.07.2013
* @author baetz
*/
#ifndef MODEMESSAGE_H_
#define MODEMESSAGE_H_
#include "../ipc/CommandMessage.h" #include "../ipc/CommandMessage.h"
@ -30,11 +23,12 @@ public:
static Mode_t getMode(const CommandMessage* message); static Mode_t getMode(const CommandMessage* message);
static Submode_t getSubmode(const CommandMessage* message); static Submode_t getSubmode(const CommandMessage* message);
static ReturnValue_t setModeMessage(CommandMessage* message, static ReturnValue_t getCantReachModeReason(const CommandMessage* message);
static void 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 setCantReachMode(CommandMessage* message, ReturnValue_t reason);
static ReturnValue_t getCantReachModeReason(const CommandMessage* message);
static void clear(CommandMessage* message); static void clear(CommandMessage* message);
}; };
#endif /* MODEMESSAGE_H_ */ #endif /* FSFW_MODES_MODEMESSAGE_H_ */

View File

@ -1,42 +1,76 @@
#include "MessageQueue.h" #include "MessageQueue.h"
#include "../../objectmanager/ObjectManagerIF.h" #include "../../objectmanager/ObjectManagerIF.h"
#include "../../serviceinterface/ServiceInterfaceStream.h" #include "../../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
MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size) : // As a first step towards this, introduces system context variable which needs
defaultDestination(0),lastPartner(0) { // to be switched manually
handle = xQueueCreate(message_depth, max_message_size); // Haven't found function to find system context.
if (handle == NULL) { MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize):
sif::error << "MessageQueue creation failed" << std::endl; maxMessageSize(maxMessageSize) {
handle = xQueueCreate(messageDepth, maxMessageSize);
if (handle == nullptr) {
sif::error << "MessageQueue::MessageQueue Creation failed" << std::endl;
} }
} }
MessageQueue::~MessageQueue() { MessageQueue::~MessageQueue() {
if (handle != NULL) { if (handle != nullptr) {
vQueueDelete(handle); vQueueDelete(handle);
} }
} }
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) { MessageQueueMessageIF* message, bool ignoreFault) {
return sendMessageFrom(sendTo, message, this->getId(), ignoreFault); return sendMessageFrom(sendTo, message, this->getId(), ignoreFault);
} }
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message) { ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) {
return sendToDefaultFrom(message, this->getId()); return sendToDefaultFrom(message, this->getId());
} }
ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) { ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message,
if (this->lastPartner != 0) { MessageQueueId_t sentFrom, bool ignoreFault) {
return sendMessageFrom(defaultDestination,message,sentFrom,ignoreFault);
}
ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) {
if (this->lastPartner != MessageQueueIF::NO_QUEUE) {
return sendMessageFrom(this->lastPartner, message, this->getId()); return sendMessageFrom(this->lastPartner, message, this->getId());
} else { } else {
return NO_REPLY_PARTNER; return NO_REPLY_PARTNER;
} }
} }
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message, ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo,
MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault) {
return sendMessageFromMessageQueue(sendTo, message, sentFrom, ignoreFault,
callContext);
}
ReturnValue_t MessageQueue::handleSendResult(BaseType_t result, bool ignoreFault) {
if (result != pdPASS) {
if (not ignoreFault) {
InternalErrorReporterIF* internalErrorReporter = objectManager->
get<InternalErrorReporterIF>(
objects::INTERNAL_ERROR_REPORTER);
if (internalErrorReporter != nullptr) {
internalErrorReporter->queueMessageNotSent();
}
}
return MessageQueueIF::FULL;
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) { MessageQueueId_t* receivedFrom) {
ReturnValue_t status = this->receiveMessage(message); ReturnValue_t status = this->receiveMessage(message);
if(status == HasReturnvaluesIF::RETURN_OK) { if(status == HasReturnvaluesIF::RETURN_OK) {
@ -45,8 +79,9 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message,
return status; return status;
} }
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) { ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
BaseType_t result = xQueueReceive(handle,reinterpret_cast<void*>(message->getBuffer()), 0); BaseType_t result = xQueueReceive(handle,reinterpret_cast<void*>(
message->getBuffer()), 0);
if (result == pdPASS){ if (result == pdPASS){
this->lastPartner = message->getSender(); this->lastPartner = message->getSender();
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
@ -67,51 +102,55 @@ ReturnValue_t MessageQueue::flush(uint32_t* count) {
} }
MessageQueueId_t MessageQueue::getId() const { MessageQueueId_t MessageQueue::getId() const {
return (MessageQueueId_t) handle; return reinterpret_cast<MessageQueueId_t>(handle);
} }
void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) { void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
defaultDestinationSet = true;
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;
} }
bool MessageQueue::isDefaultDestinationSet() const { bool MessageQueue::isDefaultDestinationSet() const {
return 0; return defaultDestinationSet;
} }
// static core function to send messages.
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
MessageQueueMessage *message, MessageQueueId_t sentFrom, MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault) { bool ignoreFault, CallContext callContext) {
message->setSender(sentFrom); BaseType_t result = pdFALSE;
QueueHandle_t destination = nullptr;
BaseType_t result = xQueueSendToBack(reinterpret_cast<QueueHandle_t>(sendTo), if(sendTo == MessageQueueIF::NO_QUEUE or sendTo == 0x00) {
reinterpret_cast<const void*>(message->getBuffer()), 0); return MessageQueueIF::DESTINVATION_INVALID;
if (result != pdPASS) { }
if (!ignoreFault) { else {
InternalErrorReporterIF* internalErrorReporter = destination = reinterpret_cast<QueueHandle_t>(sendTo);
objectManager->get<InternalErrorReporterIF>(
objects::INTERNAL_ERROR_REPORTER);
if (internalErrorReporter != NULL) {
internalErrorReporter->queueMessageNotSent();
}
}
return MessageQueueIF::FULL;
} }
return HasReturnvaluesIF::RETURN_OK;
message->setSender(sentFrom);
if(callContext == CallContext::TASK) {
result = xQueueSendToBack(destination,
static_cast<const void*>(message->getBuffer()), 0);
}
else {
/* If the call context is from an interrupt,
* request a context switch if a higher priority task
* was blocked by the interrupt. */
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
result = xQueueSendFromISR(reinterpret_cast<QueueHandle_t>(sendTo),
static_cast<const void*>(message->getBuffer()),
&xHigherPriorityTaskWoken);
if(xHigherPriorityTaskWoken == pdTRUE) {
TaskManagement::requestContextSwitch(callContext);
}
}
return handleSendResult(result, ignoreFault);
} }

View File

@ -1,159 +1,150 @@
#ifndef MESSAGEQUEUE_H_ #ifndef FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_
#define MESSAGEQUEUE_H_ #define FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_
#include "../../internalError/InternalErrorReporterIF.h" #include "../../internalError/InternalErrorReporterIF.h"
#include "../../ipc/MessageQueueIF.h" #include "../../ipc/MessageQueueIF.h"
#include "../../ipc/MessageQueueMessage.h" #include "../../ipc/MessageQueueMessageIF.h"
#include "../../osal/FreeRTOS/TaskManagement.h"
#include <FreeRTOS.h> #include <freertos/FreeRTOS.h>
#include <queue.h> #include <freertos/queue.h>
#include <fsfw/ipc/MessageQueueMessage.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/
/** /**
* @brief This class manages sending and receiving of message queue messages. * @brief This class manages sending and receiving of
* message queue messages.
* @details
* Message queues are used to pass asynchronous messages between processes.
* They work like post boxes, where all incoming messages are stored in FIFO
* order. This class creates a new receiving queue and provides methods to fetch
* received messages. Being a child of MessageQueueSender, this class also
* provides 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 from.
* *
* @details Message queues are used to pass asynchronous messages between processes. * The MessageQueue should be used as "post box" for a single owning object.
* They work like post boxes, where all incoming messages are stored in FIFO * So all message queue communication is "n-to-one".
* order. This class creates a new receiving queue and provides methods to fetch * For creating the queue, as well as sending and receiving messages, the class
* received messages. Being a child of MessageQueueSender, this class also provides * makes use of the operating system calls provided.
* 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 * Please keep in mind that FreeRTOS offers different calls for message queue
* from. * operations if called from an ISR.
* The MessageQueue should be used as "post box" for a single owning object. So all * For now, the system context needs to be switched manually.
* message queue communication is "n-to-one". * @ingroup osal
* For creating the queue, as well as sending and receiving messages, the class makes * @ingroup message_queue
* use of the operating system calls provided.
* \ingroup message_queue
*/ */
class MessageQueue : public MessageQueueIF { class MessageQueue : public MessageQueueIF {
friend class MessageQueueSenderIF; friend class MessageQueueSenderIF;
public: public:
/** /**
* @brief The constructor initializes and configures the message queue. * @brief The constructor initializes and configures the message queue.
* @details By making use of the according operating system call, a message queue is created * @details
* and initialized. The message depth - the maximum number of messages to be * By making use of the according operating system call, a message queue
* buffered - may be set with the help of a parameter, whereas the message size is * is created and initialized. The message depth - the maximum number of
* automatically set to the maximum message queue message size. The operating system * messages to be buffered - may be set with the help of a parameter,
* sets the message queue id, or i case of failure, it is set to zero. * whereas the message size is automatically set to the maximum message
* @param message_depth The number of messages to be buffered before passing an error to the * queue message size. The operating system sets the message queue id, or
* sender. Default is three. * in case of failure, it is set to zero.
* @param max_message_size With this parameter, the maximum message size can be adjusted. * @param message_depth
* This should be left default. * The number of messages to be buffered before passing an error to the
* sender. Default is three.
* @param max_message_size
* With this parameter, the maximum message size can be adjusted.
* This should be left default.
*/ */
MessageQueue( size_t message_depth = 3, size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE ); MessageQueue( size_t messageDepth = 3,
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE );
/** Copying message queues forbidden */
MessageQueue(const MessageQueue&) = delete;
MessageQueue& operator=(const MessageQueue&) = delete;
/** /**
* @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();
/** /**
* @brief This operation sends a message to the given destination. * This function is used to switch the call context. This has to be called
* @details It directly uses the sendMessage call of the MessageQueueSender parent, but passes its * if a message is sent or received from an ISR!
* queue id as "sentFrom" parameter. * @param callContext
* @param sendTo This parameter specifies the message queue id of the destination message queue.
* @param message A pointer to a previously created message, which is sent.
* @param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full.
*/ */
void switchSystemContext(CallContext callContext);
/** MessageQueueIF implementation */
ReturnValue_t sendMessage(MessageQueueId_t sendTo, ReturnValue_t sendMessage(MessageQueueId_t sendTo,
MessageQueueMessage* message, bool ignoreFault = false ); MessageQueueMessageIF* message, bool ignoreFault = false) override;
/**
* @brief This operation sends a message to the default destination.
* @details As in the sendMessage method, this function uses the sendToDefault call of the
* MessageQueueSender parent class and adds its queue id as "sentFrom" information.
* @param message A pointer to a previously created message, which is sent.
*/
ReturnValue_t sendToDefault( MessageQueueMessage* message );
/**
* @brief This operation sends a message to the last communication partner.
* @details This operation simplifies answering an incoming message by using the stored
* lastParnter information as destination. If there was no message received yet
* (i.e. lastPartner is zero), an error code is returned.
* @param message A pointer to a previously created message, which is sent.
*/
ReturnValue_t reply( MessageQueueMessage* message );
/** ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override;
* @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
* sender's queue id.
* @param message A pointer to a message in which the received data is stored.
* @param receivedFrom A pointer to a queue id in which the sender's id is stored.
*/
ReturnValue_t receiveMessage(MessageQueueMessage* message,
MessageQueueId_t *receivedFrom);
/** ReturnValue_t reply(MessageQueueMessageIF* message) override;
* @brief This function reads available messages from the message queue. virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo,
* @details If data is available it is stored in the passed message pointer. The message's MessageQueueMessageIF* message,
* original content is overwritten and the sendFrom information is stored in the MessageQueueId_t sentFrom = NO_QUEUE,
* lastPartner attribute. Else, the lastPartner information remains untouched, the bool ignoreFault = false) override;
* message's content is cleared and the function returns immediately.
* @param message A pointer to a message in which the received data is stored. virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message,
*/ MessageQueueId_t sentFrom = NO_QUEUE,
ReturnValue_t receiveMessage(MessageQueueMessage* message); bool ignoreFault = false) override;
/**
* Deletes all pending messages in the queue. ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
* @param count The number of flushed messages. MessageQueueId_t *receivedFrom) override;
* @return RETURN_OK on success.
*/ ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override;
ReturnValue_t flush(uint32_t* count);
/** ReturnValue_t flush(uint32_t* count) override;
* @brief This method returns the message queue id of the last communication partner.
*/ MessageQueueId_t getLastPartner() const override;
MessageQueueId_t getLastPartner() const;
/** MessageQueueId_t getId() const override;
* @brief This method returns the message queue id of this class's message queue.
*/ void setDefaultDestination(MessageQueueId_t defaultDestination) override;
MessageQueueId_t getId() const;
/** MessageQueueId_t getDefaultDestination() const override;
* \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 bool isDefaultDestinationSet() const override;
* 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.
*/
void setDefaultDestination(MessageQueueId_t defaultDestination);
/**
* \brief This method is a simple getter for the default destination.
*/
MessageQueueId_t getDefaultDestination() const;
bool isDefaultDestinationSet() const;
protected: protected:
/** /**
* Implementation to be called from any send Call within MessageQueue and MessageQueueSenderIF * @brief Implementation to be called from any send Call within
* \details This method takes the message provided, adds the sentFrom information and passes * MessageQueue and MessageQueueSenderIF.
* it on to the destination provided with an operating system call. The OS's return * @details
* value is returned. * This method takes the message provided, adds the sentFrom information and
* \param sendTo This parameter specifies the message queue id to send the message to. * passes it on to the destination provided with an operating system call.
* \param message This is a pointer to a previously created message, which is sent. * The OS's return value is returned.
* \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. * @param sendTo
* This variable is set to zero by default. * This parameter specifies the message queue id to send the message to.
* \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. * @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.
* @param context Specify whether call is made from task or from an ISR.
*/ */
static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo,MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE,bool ignoreFault=false); static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo,
MessageQueueMessageIF* message, MessageQueueId_t sentFrom = NO_QUEUE,
bool ignoreFault=false, CallContext callContext = CallContext::TASK);
static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault);
private: private:
bool defaultDestinationSet = false;
QueueHandle_t handle; QueueHandle_t handle;
MessageQueueId_t defaultDestination; MessageQueueId_t defaultDestination = MessageQueueIF::NO_QUEUE;
MessageQueueId_t lastPartner; MessageQueueId_t lastPartner = MessageQueueIF::NO_QUEUE;
const size_t maxMessageSize;
//! Stores the current system context
CallContext callContext = CallContext::TASK;
}; };
#endif /* MESSAGEQUEUE_H_ */ #endif /* FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_ */

View File

@ -1,14 +1,14 @@
#include "MessageQueue.h"
#include "../../ipc/MessageQueueSenderIF.h" #include "../../ipc/MessageQueueSenderIF.h"
#include "../../ipc/QueueFactory.h" #include "../../ipc/QueueFactory.h"
#include "MessageQueue.h"
QueueFactory* QueueFactory::factoryInstance = nullptr; QueueFactory* QueueFactory::factoryInstance = nullptr;
ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo,
MessageQueueMessage* message, MessageQueueId_t sentFrom, MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault) { bool ignoreFault) {
return MessageQueue::sendMessageFromMessageQueue(sendTo,message, return MessageQueue::sendMessageFromMessageQueue(sendTo,message,
sentFrom,ignoreFault); sentFrom,ignoreFault);

View File

@ -1,17 +1,19 @@
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include "MessageQueue.h" #include "MessageQueue.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include "../../objectmanager/ObjectManagerIF.h"
#include <fstream> #include <fstream>
#include <fcntl.h> /* For O_* constants */ #include <fcntl.h> /* For O_* constants */
#include <sys/stat.h> /* For mode constants */ #include <sys/stat.h> /* For mode constants */
#include <cstring> #include <cstring>
#include <errno.h> #include <errno.h>
MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize): MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize):
id(MessageQueueIF::NO_QUEUE),lastPartner(MessageQueueIF::NO_QUEUE), id(MessageQueueIF::NO_QUEUE),lastPartner(MessageQueueIF::NO_QUEUE),
defaultDestination(MessageQueueIF::NO_QUEUE) { defaultDestination(MessageQueueIF::NO_QUEUE),
maxMessageSize(maxMessageSize) {
//debug << "MessageQueue::MessageQueue: Creating a queue" << std::endl; //debug << "MessageQueue::MessageQueue: Creating a queue" << std::endl;
mq_attr attributes; mq_attr attributes;
this->id = 0; this->id = 0;
@ -46,7 +48,7 @@ MessageQueue::~MessageQueue() {
status = mq_unlink(name); status = mq_unlink(name);
if(status != 0){ if(status != 0){
sif::error << "MessageQueue::Destructor: mq_unlink Failed with status: " sif::error << "MessageQueue::Destructor: mq_unlink Failed with status: "
<< strerror(errno) <<std::endl; << strerror(errno) << std::endl;
} }
} }
@ -61,22 +63,27 @@ ReturnValue_t MessageQueue::handleError(mq_attr* attributes,
// Just an additional helpful printout :-) // Just an additional helpful printout :-)
if(std::ifstream("/proc/sys/fs/mqueue/msg_max",std::ios::in) >> if(std::ifstream("/proc/sys/fs/mqueue/msg_max",std::ios::in) >>
defaultMqMaxMsg and defaultMqMaxMsg < messageDepth) { defaultMqMaxMsg and defaultMqMaxMsg < messageDepth) {
// See: https://www.man7.org/linux/man-pages/man3/mq_open.3.html /*
// This happens if the msg_max value is not large enough See: https://www.man7.org/linux/man-pages/man3/mq_open.3.html
// It is ignored if the executable is run in privileged mode. This happens if the msg_max value is not large enough
// Run the unlockRealtime script or grant the mode manually by using: It is ignored if the executable is run in privileged mode.
// sudo setcap 'CAP_SYS_RESOURCE=+ep' <pathToBinary> Run the unlockRealtime script or grant the mode manually by using:
sudo setcap 'CAP_SYS_RESOURCE=+ep' <pathToBinary>
// Persistent solution for session: Persistent solution for session:
// echo <newMsgMax> | sudo tee /proc/sys/fs/mqueue/msg_max echo <newMsgMax> | sudo tee /proc/sys/fs/mqueue/msg_max
// Permanent solution: Permanent solution:
// sudo nano /etc/sysctl.conf sudo nano /etc/sysctl.conf
// Append at end: fs/mqueue/msg_max = <newMsgMaxLen> Append at end: fs/mqueue/msg_max = <newMsgMaxLen>
// Apply changes with: sudo sysctl -p Apply changes with: sudo sysctl -p
*/
sif::error << "MessageQueue::MessageQueue: Default MQ size " sif::error << "MessageQueue::MessageQueue: Default MQ size "
<< defaultMqMaxMsg << " is too small for requested size " << defaultMqMaxMsg << " is too small for requested size "
<< messageDepth << std::endl; << messageDepth << std::endl;
sif::error << "This error can be fixed by setting the maximum "
"allowed message size higher!" << std::endl;
} }
break; break;
} }
@ -118,15 +125,15 @@ ReturnValue_t MessageQueue::handleError(mq_attr* attributes,
} }
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
MessageQueueMessage* message, bool ignoreFault) { MessageQueueMessageIF* message, bool ignoreFault) {
return sendMessageFrom(sendTo, message, this->getId(), false); return sendMessageFrom(sendTo, message, this->getId(), false);
} }
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message) { ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) {
return sendToDefaultFrom(message, this->getId()); return sendToDefaultFrom(message, this->getId());
} }
ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) { ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) {
if (this->lastPartner != 0) { if (this->lastPartner != 0) {
return sendMessageFrom(this->lastPartner, message, this->getId()); return sendMessageFrom(this->lastPartner, message, this->getId());
} else { } else {
@ -134,21 +141,34 @@ ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) {
} }
} }
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message, ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) { MessageQueueId_t* receivedFrom) {
ReturnValue_t status = this->receiveMessage(message); ReturnValue_t status = this->receiveMessage(message);
*receivedFrom = this->lastPartner; *receivedFrom = this->lastPartner;
return status; return status;
} }
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) { ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
if(message == nullptr) {
sif::error << "MessageQueue::receiveMessage: Message is "
"nullptr!" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
if(message->getMaximumMessageSize() < maxMessageSize) {
sif::error << "MessageQueue::receiveMessage: Message size "
<< message->getMaximumMessageSize()
<< " too small to receive data!" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
unsigned int messagePriority = 0; unsigned int messagePriority = 0;
int status = mq_receive(id,reinterpret_cast<char*>(message->getBuffer()), int status = mq_receive(id,reinterpret_cast<char*>(message->getBuffer()),
message->MAX_MESSAGE_SIZE,&messagePriority); message->getMaximumMessageSize(),&messagePriority);
if (status > 0) { if (status > 0) {
this->lastPartner = message->getSender(); this->lastPartner = message->getSender();
//Check size of incoming message. //Check size of incoming message.
if (message->messageSize < message->getMinimumMessageSize()) { if (message->getMessageSize() < message->getMinimumMessageSize()) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
@ -158,7 +178,7 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) {
} else { } else {
//No message was received. Keep lastPartner anyway, I might send //No message was received. Keep lastPartner anyway, I might send
//something later. But still, delete packet content. //something later. But still, delete packet content.
memset(message->getData(), 0, message->MAX_DATA_SIZE); memset(message->getData(), 0, message->getMaximumMessageSize());
switch(errno){ switch(errno){
case EAGAIN: case EAGAIN:
//O_NONBLOCK or MQ_NONBLOCK was set and there are no messages //O_NONBLOCK or MQ_NONBLOCK was set and there are no messages
@ -258,18 +278,19 @@ void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
this->defaultDestination = defaultDestination; this->defaultDestination = defaultDestination;
} }
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message,
MessageQueueMessage* message, MessageQueueId_t sentFrom,
bool ignoreFault) {
return sendMessageFromMessageQueue(sendTo,message,sentFrom,ignoreFault);
}
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessage* message,
MessageQueueId_t sentFrom, bool ignoreFault) { MessageQueueId_t sentFrom, bool ignoreFault) {
return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault); return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault);
} }
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo,
MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault) {
return sendMessageFromMessageQueue(sendTo,message, sentFrom,ignoreFault);
}
MessageQueueId_t MessageQueue::getDefaultDestination() const { MessageQueueId_t MessageQueue::getDefaultDestination() const {
return this->defaultDestination; return this->defaultDestination;
} }
@ -281,11 +302,18 @@ bool MessageQueue::isDefaultDestinationSet() const {
uint16_t MessageQueue::queueCounter = 0; uint16_t MessageQueue::queueCounter = 0;
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
MessageQueueMessage *message, MessageQueueId_t sentFrom, MessageQueueMessageIF *message, MessageQueueId_t sentFrom,
bool ignoreFault) { bool ignoreFault) {
if(message == nullptr) {
sif::error << "MessageQueue::sendMessageFromMessageQueue: Message is "
"nullptr!" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
message->setSender(sentFrom); message->setSender(sentFrom);
int result = mq_send(sendTo, int result = mq_send(sendTo,
reinterpret_cast<const char*>(message->getBuffer()), message->messageSize,0); reinterpret_cast<const char*>(message->getBuffer()),
message->getMessageSize(),0);
//TODO: Check if we're in ISR. //TODO: Check if we're in ISR.
if (result != 0) { if (result != 0) {
@ -303,13 +331,16 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
//MQ_NONBLOCK flag was set in its attributes, and the //MQ_NONBLOCK flag was set in its attributes, and the
//specified queue is full. //specified queue is full.
return MessageQueueIF::FULL; return MessageQueueIF::FULL;
case EBADF: case EBADF: {
//mq_des doesn't represent a valid message queue descriptor, //mq_des doesn't represent a valid message queue descriptor,
//or mq_des wasn't opened for writing. //or mq_des wasn't opened for writing.
sif::error << "MessageQueue::sendMessage: Configuration error " sif::error << "MessageQueue::sendMessage: Configuration error, MQ"
<< strerror(errno) << " in mq_send mqSendTo: " << sendTo << " destination invalid." << std::endl;
<< " sent from " << sentFrom << std::endl; sif::error << strerror(errno) << " in "
/*NO BREAK*/ <<"mq_send to: " << sendTo << " sent from "
<< sentFrom << std::endl;
return DESTINVATION_INVALID;
}
case EINTR: case EINTR:
//The call was interrupted by a signal. //The call was interrupted by a signal.
case EINVAL: case EINVAL:

View File

@ -1,5 +1,5 @@
#ifndef MESSAGEQUEUE_H_ #ifndef FSFW_OSAL_LINUX_MESSAGEQUEUE_H_
#define MESSAGEQUEUE_H_ #define FSFW_OSAL_LINUX_MESSAGEQUEUE_H_
#include "../../internalError/InternalErrorReporterIF.h" #include "../../internalError/InternalErrorReporterIF.h"
#include "../../ipc/MessageQueueIF.h" #include "../../ipc/MessageQueueIF.h"
@ -56,14 +56,14 @@ public:
* @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.
*/ */
virtual ReturnValue_t sendMessage(MessageQueueId_t sendTo, virtual ReturnValue_t sendMessage(MessageQueueId_t sendTo,
MessageQueueMessage* message, bool ignoreFault = false ); MessageQueueMessageIF* message, bool ignoreFault = false );
/** /**
* @brief This operation sends a message to the default destination. * @brief This operation sends a message to the default destination.
* @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
* MessageQueueSender parent class and adds its queue id as "sentFrom" information. * MessageQueueSender parent 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.
*/ */
virtual ReturnValue_t sendToDefault( MessageQueueMessage* message ); virtual ReturnValue_t sendToDefault( MessageQueueMessageIF* message );
/** /**
* @brief This operation sends a message to the last communication partner. * @brief This operation sends a message to the last communication partner.
* @details This operation simplifies answering an incoming message by using the stored * @details This operation simplifies answering an incoming message by using the stored
@ -71,7 +71,7 @@ public:
* (i.e. lastPartner is zero), an error code is returned. * (i.e. lastPartner is zero), an error code is returned.
* @param message A pointer to a previously created message, which is sent. * @param message A pointer to a previously created message, which is sent.
*/ */
ReturnValue_t reply( MessageQueueMessage* message ); ReturnValue_t reply( MessageQueueMessageIF* message );
/** /**
* @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.
@ -80,7 +80,7 @@ public:
* @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.
* @param receivedFrom A pointer to a queue id in which the sender's id is stored. * @param receivedFrom A pointer to a queue id in which the sender's id is stored.
*/ */
ReturnValue_t receiveMessage(MessageQueueMessage* message, ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t *receivedFrom); MessageQueueId_t *receivedFrom);
/** /**
@ -91,7 +91,7 @@ public:
* 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.
*/ */
ReturnValue_t receiveMessage(MessageQueueMessage* message); ReturnValue_t receiveMessage(MessageQueueMessageIF* message);
/** /**
* Deletes all pending messages in the queue. * Deletes all pending messages in the queue.
* @param count The number of flushed messages. * @param count The number of flushed messages.
@ -114,7 +114,9 @@ public:
* 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.
*/ */
virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault = false ); virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo,
MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault = false );
/** /**
* \brief The sendToDefault method sends a queue message to the default destination. * \brief The sendToDefault 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.
@ -122,7 +124,8 @@ public:
* \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.
*/ */
virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ); virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* 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.
*/ */
@ -145,7 +148,9 @@ protected:
* 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.
*/ */
static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo,MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE,bool ignoreFault=false); static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo,
MessageQueueMessageIF* message, MessageQueueId_t sentFrom = NO_QUEUE,
bool ignoreFault=false);
private: private:
/** /**
* @brief The class stores the queue id it got assigned from the operating system in this attribute. * @brief The class stores the queue id it got assigned from the operating system in this attribute.
@ -171,11 +176,12 @@ private:
/** /**
* The name of the message queue, stored for unlinking * The name of the message queue, stored for unlinking
*/ */
char name[5]; char name[16];
static uint16_t queueCounter; static uint16_t queueCounter;
const size_t maxMessageSize;
ReturnValue_t handleError(mq_attr* attributes, uint32_t messageDepth); ReturnValue_t handleError(mq_attr* attributes, uint32_t messageDepth);
}; };
#endif /* MESSAGEQUEUE_H_ */ #endif /* FSFW_OSAL_LINUX_MESSAGEQUEUE_H_ */

View File

@ -15,7 +15,7 @@ QueueFactory* QueueFactory::factoryInstance = nullptr;
ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo,
MessageQueueMessage* message, MessageQueueId_t sentFrom, MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault) { bool ignoreFault) {
return MessageQueue::sendMessageFromMessageQueue(sendTo,message, return MessageQueue::sendMessageFromMessageQueue(sendTo,message,
sentFrom,ignoreFault); sentFrom,ignoreFault);

View File

@ -107,13 +107,23 @@ ReturnValue_t CService200ModeCommanding::prepareWrongModeReply(
const CommandMessage *reply, object_id_t objectId) { const CommandMessage *reply, object_id_t objectId) {
ModePacket wrongModeReply(objectId, ModeMessage::getMode(reply), ModePacket wrongModeReply(objectId, ModeMessage::getMode(reply),
ModeMessage::getSubmode(reply)); ModeMessage::getSubmode(reply));
return sendTmPacket(Subservice::REPLY_WRONG_MODE_REPLY, &wrongModeReply); ReturnValue_t result = sendTmPacket(Subservice::REPLY_WRONG_MODE_REPLY, &wrongModeReply);
if(result == RETURN_OK){
// We want to produce an error here in any case because the mode was not correct
return RETURN_FAILED;
}
return result;
} }
ReturnValue_t CService200ModeCommanding::prepareCantReachModeReply( ReturnValue_t CService200ModeCommanding::prepareCantReachModeReply(
const CommandMessage *reply, object_id_t objectId) { const CommandMessage *reply, object_id_t objectId) {
CantReachModePacket cantReachModePacket(objectId, CantReachModePacket cantReachModePacket(objectId,
ModeMessage::getCantReachModeReason(reply)); ModeMessage::getCantReachModeReason(reply));
return sendTmPacket(Subservice::REPLY_CANT_REACH_MODE, ReturnValue_t result = sendTmPacket(Subservice::REPLY_CANT_REACH_MODE,
&cantReachModePacket); &cantReachModePacket);
if(result == RETURN_OK){
// We want to produce an error here in any case because the mode was not reached
return RETURN_FAILED;
}
return result;
} }

View File

@ -1,31 +1,39 @@
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "CCSDSDistributor.h" #include "CCSDSDistributor.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../tmtcpacket/SpacePacketBase.h" #include "../tmtcpacket/SpacePacketBase.h"
CCSDSDistributor::CCSDSDistributor( uint16_t setDefaultApid, object_id_t setObjectId ) : CCSDSDistributor::CCSDSDistributor(uint16_t setDefaultApid,
TcDistributor( setObjectId ), default_apid( setDefaultApid ), tcStore(NULL) { object_id_t setObjectId):
TcDistributor(setObjectId), defaultApid( setDefaultApid ) {
} }
CCSDSDistributor::~CCSDSDistributor() { CCSDSDistributor::~CCSDSDistributor() {}
} TcDistributor::TcMqMapIter CCSDSDistributor::selectDestination() {
// sif::debug << "CCSDSDistributor::selectDestination received: " <<
iterator_t CCSDSDistributor::selectDestination() { // this->currentMessage.getStorageId().pool_index << ", " <<
// debug << "CCSDSDistributor::selectDestination received: " << this->currentMessage.getStorageId().pool_index << ", " << this->currentMessage.getStorageId().packet_index << std::endl; // this->currentMessage.getStorageId().packet_index << std::endl;
const uint8_t* p_packet = NULL; const uint8_t* packet = nullptr;
size_t size = 0; size_t size = 0;
//TODO check returncode? ReturnValue_t result = this->tcStore->getData(currentMessage.getStorageId(),
this->tcStore->getData( this->currentMessage.getStorageId(), &p_packet, &size ); &packet, &size );
SpacePacketBase current_packet( p_packet ); if(result != HasReturnvaluesIF::RETURN_OK) {
// info << "CCSDSDistributor::selectDestination has packet with APID " << std::hex << current_packet.getAPID() << std::dec << std::endl; sif::error << "CCSDSDistributor::selectDestination: Getting data from"
iterator_t position = this->queueMap.find( current_packet.getAPID() ); " store failed!" << std::endl;
}
SpacePacketBase currentPacket(packet);
// sif:: info << "CCSDSDistributor::selectDestination has packet with APID "
// << std::hex << currentPacket.getAPID() << std::dec << std::endl;
TcMqMapIter position = this->queueMap.find(currentPacket.getAPID());
if ( position != this->queueMap.end() ) { if ( position != this->queueMap.end() ) {
return position; return position;
} else { } else {
//The APID was not found. Forward packet to main SW-APID anyway to create acceptance failure report. //The APID was not found. Forward packet to main SW-APID anyway to
return this->queueMap.find( this->default_apid ); // create acceptance failure report.
return this->queueMap.find( this->defaultApid );
} }
} }
MessageQueueId_t CCSDSDistributor::getRequestQueue() { MessageQueueId_t CCSDSDistributor::getRequestQueue() {
@ -35,9 +43,9 @@ MessageQueueId_t CCSDSDistributor::getRequestQueue() {
ReturnValue_t CCSDSDistributor::registerApplication( ReturnValue_t CCSDSDistributor::registerApplication(
AcceptsTelecommandsIF* application) { AcceptsTelecommandsIF* application) {
ReturnValue_t returnValue = RETURN_OK; ReturnValue_t returnValue = RETURN_OK;
bool errorCode = true; auto insertPair = this->queueMap.emplace(application->getIdentifier(),
errorCode = this->queueMap.insert( std::pair<uint32_t, MessageQueueId_t>( application->getIdentifier(), application->getRequestQueue() ) ).second; application->getRequestQueue());
if( errorCode == false ) { if(not insertPair.second) {
returnValue = RETURN_FAILED; returnValue = RETURN_FAILED;
} }
return returnValue; return returnValue;
@ -46,9 +54,8 @@ ReturnValue_t CCSDSDistributor::registerApplication(
ReturnValue_t CCSDSDistributor::registerApplication(uint16_t apid, ReturnValue_t CCSDSDistributor::registerApplication(uint16_t apid,
MessageQueueId_t id) { MessageQueueId_t id) {
ReturnValue_t returnValue = RETURN_OK; ReturnValue_t returnValue = RETURN_OK;
bool errorCode = true; auto insertPair = this->queueMap.emplace(apid, id);
errorCode = this->queueMap.insert( std::pair<uint32_t, MessageQueueId_t>( apid, id ) ).second; if(not insertPair.second) {
if( errorCode == false ) {
returnValue = RETURN_FAILED; returnValue = RETURN_FAILED;
} }
return returnValue; return returnValue;
@ -62,7 +69,11 @@ uint16_t CCSDSDistributor::getIdentifier() {
ReturnValue_t CCSDSDistributor::initialize() { ReturnValue_t CCSDSDistributor::initialize() {
ReturnValue_t status = this->TcDistributor::initialize(); ReturnValue_t status = this->TcDistributor::initialize();
this->tcStore = objectManager->get<StorageManagerIF>( objects::TC_STORE ); this->tcStore = objectManager->get<StorageManagerIF>( objects::TC_STORE );
if (this->tcStore == NULL) status = RETURN_FAILED; if (this->tcStore == nullptr) {
sif::error << "CCSDSDistributor::initialize: Could not initialize"
" TC store!" << std::endl;
status = RETURN_FAILED;
}
return status; return status;
} }

View File

@ -1,58 +1,71 @@
#ifndef CCSDSDISTRIBUTOR_H_ #ifndef FRAMEWORK_TCDISTRIBUTION_CCSDSDISTRIBUTOR_H_
#define CCSDSDISTRIBUTOR_H_ #define FRAMEWORK_TCDISTRIBUTION_CCSDSDISTRIBUTOR_H_
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
#include "../storagemanager/StorageManagerIF.h" #include "../storagemanager/StorageManagerIF.h"
#include "CCSDSDistributorIF.h" #include "../tcdistribution/CCSDSDistributorIF.h"
#include "TcDistributor.h" #include "../tcdistribution/TcDistributor.h"
#include "../tmtcservices/AcceptsTelecommandsIF.h" #include "../tmtcservices/AcceptsTelecommandsIF.h"
/** /**
* An instantiation of the CCSDSDistributorIF. * @brief An instantiation of the CCSDSDistributorIF.
* It receives Space Packets, and selects a destination depending on the APID of the telecommands. * @details
* It receives Space Packets, and selects a destination depending on the
* APID of the telecommands.
* The Secondary Header (with Service/Subservice) is ignored. * The Secondary Header (with Service/Subservice) is ignored.
* \ingroup tc_distribution * @ingroup tc_distribution
*/ */
class CCSDSDistributor : public TcDistributor, public CCSDSDistributorIF, public AcceptsTelecommandsIF { class CCSDSDistributor : public TcDistributor,
protected: public CCSDSDistributorIF,
/** public AcceptsTelecommandsIF {
* This implementation checks if an Application with fitting APID has registered and forwards the
* packet to the according message queue.
* If the packet is not found, it returns the queue to \c default_apid, where a Acceptance Failure
* message should be generated.
* @return Iterator to map entry of found APID or iterator to default APID.
*/
iterator_t selectDestination();
/**
* The default APID, where packets with unknown APID are sent to.
*/
uint16_t default_apid;
/**
* A reference to the TC storage must be maintained, as this class handles pure Space Packets and there
* exists no SpacePacketStored class.
*/
StorageManagerIF* tcStore;
/**
* The callback here handles the generation of acceptance success/failure messages.
*/
ReturnValue_t callbackAfterSending( ReturnValue_t queueStatus );
public: public:
/** /**
* The constructor sets the default APID and calls the TcDistributor ctor with a certain object id. * @brief The constructor sets the default APID and calls the
* \c tcStore is set in the \c initialize method. * TcDistributor ctor with a certain object id.
* @param set_default_apid The default APID, where packets with unknown destination are sent to. * @details
* @c tcStore is set in the @c initialize method.
* @param setDefaultApid The default APID, where packets with unknown
* destination are sent to.
*/ */
CCSDSDistributor( uint16_t setDefaultApid, object_id_t setObjectId ); CCSDSDistributor(uint16_t setDefaultApid, object_id_t setObjectId);
/** /**
* The destructor is empty. * The destructor is empty.
*/ */
~CCSDSDistributor(); virtual ~CCSDSDistributor();
MessageQueueId_t getRequestQueue();
ReturnValue_t registerApplication( uint16_t apid, MessageQueueId_t id ); MessageQueueId_t getRequestQueue() override;
ReturnValue_t registerApplication( AcceptsTelecommandsIF* application ); ReturnValue_t registerApplication( uint16_t apid,
uint16_t getIdentifier(); MessageQueueId_t id) override;
ReturnValue_t initialize(); ReturnValue_t registerApplication(
AcceptsTelecommandsIF* application) override;
uint16_t getIdentifier() override;
ReturnValue_t initialize() override;
protected:
/**
* This implementation checks if an application with fitting APID has
* registered and forwards the packet to the according message queue.
* If the packet is not found, it returns the queue to @c defaultApid,
* where a Acceptance Failure message should be generated.
* @return Iterator to map entry of found APID or iterator to default APID.
*/
TcMqMapIter selectDestination() override;
/**
* The callback here handles the generation of acceptance
* success/failure messages.
*/
ReturnValue_t callbackAfterSending( ReturnValue_t queueStatus ) override;
/**
* The default APID, where packets with unknown APID are sent to.
*/
uint16_t defaultApid;
/**
* A reference to the TC storage must be maintained, as this class handles
* pure Space Packets and there exists no SpacePacketStored class.
*/
StorageManagerIF* tcStore = nullptr;
}; };
#endif /* FRAMEWORK_TCDISTRIBUTION_CCSDSDISTRIBUTOR_H_ */
#endif /* CCSDSDISTRIBUTOR_H_ */

View File

@ -1,34 +1,38 @@
#ifndef CCSDSDISTRIBUTORIF_H_ #ifndef FSFW_TCDISTRIBUTION_CCSDSDISTRIBUTORIF_H_
#define CCSDSDISTRIBUTORIF_H_ #define FSFW_TCDISTRIBUTION_CCSDSDISTRIBUTORIF_H_
#include "../tmtcservices/AcceptsTelecommandsIF.h" #include "../tmtcservices/AcceptsTelecommandsIF.h"
#include "../ipc/MessageQueueSenderIF.h" #include "../ipc/MessageQueueSenderIF.h"
/** /**
* This is the Interface to a CCSDS Distributor. * This is the Interface to a CCSDS Distributor.
* On a CCSDS Distributor, Applications (in terms of CCSDS) may register themselves, * On a CCSDS Distributor, Applications (in terms of CCSDS) may register
* either by passing a pointer to themselves (and implementing the CCSDSApplicationIF, * themselves, either by passing a pointer to themselves (and implementing the
* or by explicitly passing an APID and a MessageQueueId to route the TC's to. * CCSDSApplicationIF), or by explicitly passing an APID and a MessageQueueId
* \ingroup tc_distribution * to route the TC's to.
* @ingroup tc_distribution
*/ */
class CCSDSDistributorIF { class CCSDSDistributorIF {
public: public:
/** /**
* With this call, a class implementing the CCSDSApplicationIF can register at the * With this call, a class implementing the CCSDSApplicationIF can register
* distributor. * at the distributor.
* @param application A pointer to the Application to register. * @param application A pointer to the Application to register.
* @return - \c RETURN_OK on success, * @return - @c RETURN_OK on success,
* - \c RETURN_FAILED on failure. * - @c RETURN_FAILED on failure.
*/ */
virtual ReturnValue_t registerApplication( AcceptsTelecommandsIF* application ) = 0; virtual ReturnValue_t registerApplication(
AcceptsTelecommandsIF* application) = 0;
/** /**
* With this call, other Applications can register to the CCSDS distributor. * With this call, other Applications can register to the CCSDS distributor.
* This is done by passing an APID and a MessageQueueId to the method. * This is done by passing an APID and a MessageQueueId to the method.
* @param apid The APID to register. * @param apid The APID to register.
* @param id The MessageQueueId of the message queue to send the TC Packets to. * @param id The MessageQueueId of the message queue to send the
* @return - \c RETURN_OK on success, * TC Packets to.
* - \c RETURN_FAILED on failure. * @return - @c RETURN_OK on success,
* - @c RETURN_FAILED on failure.
*/ */
virtual ReturnValue_t registerApplication( uint16_t apid, MessageQueueId_t id ) = 0; virtual ReturnValue_t registerApplication( uint16_t apid,
MessageQueueId_t id) = 0;
/** /**
* The empty virtual destructor. * The empty virtual destructor.
*/ */
@ -37,4 +41,4 @@ public:
}; };
#endif /* CCSDSDISTRIBUTORIF_H_ */ #endif /* FSFW_TCDISTRIBUTION_CCSDSDISTRIBUTORIF_H_ */

View File

@ -1,61 +1,71 @@
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "CCSDSDistributorIF.h" #include "CCSDSDistributorIF.h"
#include "PUSDistributor.h" #include "PUSDistributor.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../tmtcpacket/pus/TcPacketStored.h" #include "../tmtcpacket/pus/TcPacketStored.h"
#include "../tmtcservices/PusVerificationReport.h" #include "../tmtcservices/PusVerificationReport.h"
PUSDistributor::PUSDistributor(uint16_t setApid, object_id_t setObjectId, object_id_t setPacketSource) : PUSDistributor::PUSDistributor(uint16_t setApid, object_id_t setObjectId,
TcDistributor(setObjectId), checker(setApid), verifyChannel(), currentPacket(), tcStatus( object_id_t setPacketSource) :
RETURN_FAILED), packetSource(setPacketSource) { TcDistributor(setObjectId), checker(setApid), verifyChannel(),
tcStatus(RETURN_FAILED), packetSource(setPacketSource) {}
PUSDistributor::~PUSDistributor() {}
PUSDistributor::TcMqMapIter PUSDistributor::selectDestination() {
// sif:: debug << "PUSDistributor::handlePacket received: "
// << this->current_packet_id.store_index << ", "
// << this->current_packet_id.packet_index << std::endl;
TcMqMapIter queueMapIt = this->queueMap.end();
if(this->currentPacket == nullptr) {
return queueMapIt;
}
this->currentPacket->setStoreAddress(this->currentMessage.getStorageId());
if (currentPacket->getWholeData() != nullptr) {
tcStatus = checker.checkPacket(currentPacket);
#ifdef DEBUG
if(tcStatus != HasReturnvaluesIF::RETURN_OK) {
sif::debug << "PUSDistributor::handlePacket: Packet format "
<< "invalid, code "<< static_cast<int>(tcStatus)
<< std::endl;
}
#endif
uint32_t queue_id = currentPacket->getService();
queueMapIt = this->queueMap.find(queue_id);
}
else {
tcStatus = PACKET_LOST;
}
if (queueMapIt == this->queueMap.end()) {
tcStatus = DESTINATION_NOT_FOUND;
#ifdef DEBUG
sif::debug << "PUSDistributor::handlePacket: Destination not found, "
<< "code "<< static_cast<int>(tcStatus) << std::endl;
#endif
}
if (tcStatus != RETURN_OK) {
return this->queueMap.end();
}
else {
return queueMapIt;
}
} }
PUSDistributor::~PUSDistributor() {
}
iterator_t PUSDistributor::selectDestination() {
// debug << "PUSDistributor::handlePacket received: " << this->current_packet_id.store_index << ", " << this->current_packet_id.packet_index << std::endl;
iterator_t queueMapIt = this->queueMap.end();
this->currentPacket.setStoreAddress(this->currentMessage.getStorageId());
if (currentPacket.getWholeData() != NULL) {
tcStatus = checker.checkPacket(&currentPacket);
// info << "PUSDistributor::handlePacket: packetCheck returned with " << (int)tc_status << std::endl;
uint32_t queue_id = currentPacket.getService();
queueMapIt = this->queueMap.find(queue_id);
} else {
tcStatus = PACKET_LOST;
}
if (queueMapIt == this->queueMap.end()) {
tcStatus = DESTINATION_NOT_FOUND;
}
if (tcStatus != RETURN_OK) {
sif::debug << "PUSDistributor::handlePacket: error with " << (int) tcStatus
<< std::endl;
return this->queueMap.end();
} else {
return queueMapIt;
}
}
//uint16_t PUSDistributor::createDestination( uint8_t service_id, uint8_t subservice_id ) {
// return ( service_id << 8 ) + subservice_id;
//}
ReturnValue_t PUSDistributor::registerService(AcceptsTelecommandsIF* service) { ReturnValue_t PUSDistributor::registerService(AcceptsTelecommandsIF* service) {
ReturnValue_t returnValue = RETURN_OK;
bool errorCode = true;
uint16_t serviceId = service->getIdentifier(); uint16_t serviceId = service->getIdentifier();
// sif::info << "Service ID: " << (int)serviceId << std::endl;
MessageQueueId_t queue = service->getRequestQueue(); MessageQueueId_t queue = service->getRequestQueue();
errorCode = this->queueMap.insert( auto returnPair = queueMap.emplace(serviceId, queue);
std::pair<uint32_t, MessageQueueId_t>(serviceId, queue)).second; if (not returnPair.second) {
if (errorCode == false) { sif::error << "PUSDistributor::registerService: Service ID already"
//TODO Return Code " exists in map." << std::endl;
returnValue = MessageQueueIF::NO_QUEUE; return SERVICE_ID_ALREADY_EXISTS;
} }
return returnValue; return HasReturnvaluesIF::RETURN_OK;
} }
MessageQueueId_t PUSDistributor::getRequestQueue() { MessageQueueId_t PUSDistributor::getRequestQueue() {
@ -68,13 +78,14 @@ ReturnValue_t PUSDistributor::callbackAfterSending(ReturnValue_t queueStatus) {
} }
if (tcStatus != RETURN_OK) { if (tcStatus != RETURN_OK) {
this->verifyChannel.sendFailureReport(TC_VERIFY::ACCEPTANCE_FAILURE, this->verifyChannel.sendFailureReport(TC_VERIFY::ACCEPTANCE_FAILURE,
&currentPacket, tcStatus); currentPacket, tcStatus);
//A failed packet is deleted immediately after reporting, otherwise it will block memory. // A failed packet is deleted immediately after reporting,
currentPacket.deletePacket(); // otherwise it will block memory.
currentPacket->deletePacket();
return RETURN_FAILED; return RETURN_FAILED;
} else { } else {
this->verifyChannel.sendSuccessReport(TC_VERIFY::ACCEPTANCE_SUCCESS, this->verifyChannel.sendSuccessReport(TC_VERIFY::ACCEPTANCE_SUCCESS,
&currentPacket); currentPacket);
return RETURN_OK; return RETURN_OK;
} }
} }
@ -84,11 +95,19 @@ uint16_t PUSDistributor::getIdentifier() {
} }
ReturnValue_t PUSDistributor::initialize() { ReturnValue_t PUSDistributor::initialize() {
currentPacket = new TcPacketStored();
if(currentPacket == nullptr) {
// Should not happen, memory allocation failed!
return ObjectManagerIF::CHILD_INIT_FAILED;
}
CCSDSDistributorIF* ccsdsDistributor = CCSDSDistributorIF* ccsdsDistributor =
objectManager->get<CCSDSDistributorIF>(packetSource); objectManager->get<CCSDSDistributorIF>(packetSource);
if (ccsdsDistributor == NULL) { if (ccsdsDistributor == nullptr) {
return RETURN_FAILED; sif::error << "PUSDistributor::initialize: Packet source invalid."
} else { << " Make sure it exists and implements CCSDSDistributorIF!"
return ccsdsDistributor->registerApplication(this); << std::endl;
return RETURN_FAILED;
} }
return ccsdsDistributor->registerApplication(this);
} }

View File

@ -1,67 +1,79 @@
#ifndef PUSDISTRIBUTOR_H_ #ifndef FSFW_TCDISTRIBUTION_PUSDISTRIBUTOR_H_
#define PUSDISTRIBUTOR_H_ #define FSFW_TCDISTRIBUTION_PUSDISTRIBUTOR_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include "PUSDistributorIF.h" #include "PUSDistributorIF.h"
#include "TcDistributor.h" #include "TcDistributor.h"
#include "TcPacketCheck.h" #include "TcPacketCheck.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../tmtcservices/AcceptsTelecommandsIF.h" #include "../tmtcservices/AcceptsTelecommandsIF.h"
#include "../tmtcservices/VerificationReporter.h" #include "../tmtcservices/VerificationReporter.h"
/** /**
* This class accepts PUS Telecommands and forwards them to Application services. * This class accepts PUS Telecommands and forwards them to Application
* In addition, the class performs a formal packet check and sends acceptance success * services. In addition, the class performs a formal packet check and
* or failure messages. * sends acceptance success or failure messages.
* \ingroup tc_distribution * @ingroup tc_distribution
*/ */
class PUSDistributor: public TcDistributor, class PUSDistributor: public TcDistributor,
public PUSDistributorIF, public PUSDistributorIF,
public AcceptsTelecommandsIF { public AcceptsTelecommandsIF {
public: public:
/** /**
* The ctor passes \c set_apid to the checker class and calls the TcDistribution ctor with a certain object id. * The ctor passes @c set_apid to the checker class and calls the
* TcDistribution ctor with a certain object id.
* @param setApid The APID of this receiving Application. * @param setApid The APID of this receiving Application.
* @param setObjectId Object ID of the distributor itself * @param setObjectId Object ID of the distributor itself
* @param setPacketSource Object ID of the source of TC packets. Must implement CCSDSDistributorIF. * @param setPacketSource Object ID of the source of TC packets.
* Must implement CCSDSDistributorIF.
*/ */
PUSDistributor(uint16_t setApid, object_id_t setObjectId, object_id_t setPacketSource); PUSDistributor(uint16_t setApid, object_id_t setObjectId,
object_id_t setPacketSource);
/** /**
* The destructor is empty. * The destructor is empty.
*/ */
virtual ~PUSDistributor(); virtual ~PUSDistributor();
ReturnValue_t registerService(AcceptsTelecommandsIF* service); ReturnValue_t registerService(AcceptsTelecommandsIF* service) override;
MessageQueueId_t getRequestQueue(); MessageQueueId_t getRequestQueue() override;
uint16_t getIdentifier(); ReturnValue_t initialize() override;
ReturnValue_t initialize(); uint16_t getIdentifier() override;
protected: protected:
/** /**
* This attribute contains the class, that performs a formal packet check. * This attribute contains the class, that performs a formal packet check.
*/ */
TcPacketCheck checker; TcPacketCheck checker;
/** /**
* With this class, verification messages are sent to the TC Verification service. * With this class, verification messages are sent to the
* TC Verification service.
*/ */
VerificationReporter verifyChannel; VerificationReporter verifyChannel;
/** /**
* The currently handled packet is stored here. * The currently handled packet is stored here.
*/ */
TcPacketStored currentPacket; TcPacketStored* currentPacket = nullptr;
/** /**
* With this variable, the current check status is stored to generate acceptance messages later. * With this variable, the current check status is stored to generate
* acceptance messages later.
*/ */
ReturnValue_t tcStatus; ReturnValue_t tcStatus;
const object_id_t packetSource; const object_id_t packetSource;
/** /**
* This method reads the packet service, checks if such a service is registered and forwards the packet to the destination. * This method reads the packet service, checks if such a service is
* It also initiates the formal packet check and sending of verification messages. * registered and forwards the packet to the destination.
* @return Iterator to map entry of found service id or iterator to \c map.end(). * It also initiates the formal packet check and sending of verification
* messages.
* @return Iterator to map entry of found service id
* or iterator to @c map.end().
*/ */
iterator_t selectDestination(); TcMqMapIter selectDestination() override;
/** /**
* The callback here handles the generation of acceptance success/failure messages. * The callback here handles the generation of acceptance
* success/failure messages.
*/ */
ReturnValue_t callbackAfterSending(ReturnValue_t queueStatus); ReturnValue_t callbackAfterSending(ReturnValue_t queueStatus) override;
}; };
#endif /* PUSDISTRIBUTOR_H_ */ #endif /* FSFW_TCDISTRIBUTION_PUSDISTRIBUTOR_H_ */

View File

@ -1,11 +1,12 @@
#ifndef PUSDISTRIBUTORIF_H_ #ifndef FSFW_TCDISTRIBUTION_PUSDISTRIBUTORIF_H_
#define PUSDISTRIBUTORIF_H_ #define FSFW_TCDISTRIBUTION_PUSDISTRIBUTORIF_H_
#include "../tmtcservices/AcceptsTelecommandsIF.h" #include "../tmtcservices/AcceptsTelecommandsIF.h"
#include "../ipc/MessageQueueSenderIF.h" #include "../ipc/MessageQueueSenderIF.h"
/** /**
* This interface allows PUS Services to register themselves at a PUS Distributor. * This interface allows PUS Services to register themselves at a PUS Distributor.
* \ingroup tc_distribution * @ingroup tc_distribution
*/ */
class PUSDistributorIF { class PUSDistributorIF {
public: public:
@ -17,10 +18,10 @@ public:
/** /**
* With this method, Services can register themselves at the PUS Distributor. * With this method, Services can register themselves at the PUS Distributor.
* @param service A pointer to the registering Service. * @param service A pointer to the registering Service.
* @return - \c RETURN_OK on success, * @return - @c RETURN_OK on success,
* - \c RETURN_FAILED on failure. * - @c RETURN_FAILED on failure.
*/ */
virtual ReturnValue_t registerService( AcceptsTelecommandsIF* service ) = 0; virtual ReturnValue_t registerService( AcceptsTelecommandsIF* service ) = 0;
}; };
#endif /* PUSDISTRIBUTORIF_H_ */ #endif /* FSFW_TCDISTRIBUTION_PUSDISTRIBUTORIF_H_ */

View File

@ -1,12 +1,13 @@
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "TcDistributor.h" #include "TcDistributor.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../tmtcservices/TmTcMessage.h" #include "../tmtcservices/TmTcMessage.h"
#include "../ipc/QueueFactory.h" #include "../ipc/QueueFactory.h"
TcDistributor::TcDistributor(object_id_t set_object_id) : TcDistributor::TcDistributor(object_id_t objectId) :
SystemObject(set_object_id), tcQueue(NULL) { SystemObject(objectId) {
tcQueue = QueueFactory::instance()->createMessageQueue(DISTRIBUTER_MAX_PACKETS); tcQueue = QueueFactory::instance()->
createMessageQueue(DISTRIBUTER_MAX_PACKETS);
} }
TcDistributor::~TcDistributor() { TcDistributor::~TcDistributor() {
@ -15,7 +16,6 @@ TcDistributor::~TcDistributor() {
ReturnValue_t TcDistributor::performOperation(uint8_t opCode) { ReturnValue_t TcDistributor::performOperation(uint8_t opCode) {
ReturnValue_t status = RETURN_OK; ReturnValue_t status = RETURN_OK;
// debug << "TcDistributor: performing Operation." << std::endl;
for (status = tcQueue->receiveMessage(&currentMessage); status == RETURN_OK; for (status = tcQueue->receiveMessage(&currentMessage); status == RETURN_OK;
status = tcQueue->receiveMessage(&currentMessage)) { status = tcQueue->receiveMessage(&currentMessage)) {
status = handlePacket(); status = handlePacket();
@ -29,7 +29,7 @@ ReturnValue_t TcDistributor::performOperation(uint8_t opCode) {
ReturnValue_t TcDistributor::handlePacket() { ReturnValue_t TcDistributor::handlePacket() {
iterator_t queueMapIt = this->selectDestination(); TcMqMapIter queueMapIt = this->selectDestination();
ReturnValue_t returnValue = RETURN_FAILED; ReturnValue_t returnValue = RETURN_FAILED;
if (queueMapIt != this->queueMap.end()) { if (queueMapIt != this->queueMap.end()) {
returnValue = this->tcQueue->sendMessage(queueMapIt->second, returnValue = this->tcQueue->sendMessage(queueMapIt->second,
@ -39,14 +39,14 @@ ReturnValue_t TcDistributor::handlePacket() {
} }
void TcDistributor::print() { void TcDistributor::print() {
sif::debug << "Distributor content is: " << std::endl << "ID\t| message queue id" sif::debug << "Distributor content is: " << std::endl
<< std::endl; << "ID\t| Message Queue ID" << std::endl;
for (iterator_t it = this->queueMap.begin(); it != this->queueMap.end(); sif::debug << std::setfill('0') << std::setw(8) << std::hex;
it++) { for (const auto& queueMapIter: queueMap) {
sif::debug << it->first << "\t| 0x" << std::hex << it->second << std::dec sif::debug << queueMapIter.first << "\t| 0x" << queueMapIter.second
<< std::endl; << std::endl;
} }
sif::debug << std::dec; sif::debug << std::setfill(' ') << std::dec;
} }

View File

@ -1,5 +1,6 @@
#ifndef TCDISTRIBUTOR_H_ #ifndef FSFW_TMTCSERVICES_TCDISTRIBUTOR_H_
#define TCDISTRIBUTOR_H_ #define FSFW_TMTCSERVICES_TCDISTRIBUTOR_H_
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
#include "../objectmanager/SystemObject.h" #include "../objectmanager/SystemObject.h"
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
@ -9,16 +10,12 @@
#include "../ipc/MessageQueueIF.h" #include "../ipc/MessageQueueIF.h"
#include <map> #include <map>
/** /**
* \defgroup tc_distribution Telecommand Distribution * @defgroup tc_distribution Telecommand Distribution
* All classes associated with Routing and Distribution of Telecommands belong to this group. * All classes associated with Routing and Distribution of Telecommands
* belong to this group.
*/ */
/**
* This typedef simplifies writing down the \c map iterator.
*/
typedef std::map<uint32_t, MessageQueueId_t>::iterator iterator_t;
/** /**
* This is the base class to implement distributors for Space Packets. * This is the base class to implement distributors for Space Packets.
@ -28,62 +25,19 @@ typedef std::map<uint32_t, MessageQueueId_t>::iterator iterator_t;
* message queue ids to some identifier. The process of unpacking the * message queue ids to some identifier. The process of unpacking the
* destination information from the packet is handled by the child class * destination information from the packet is handled by the child class
* implementations. * implementations.
* \ingroup tc_distribution * @ingroup tc_distribution
*/ */
class TcDistributor : public SystemObject, public ExecutableObjectIF, public HasReturnvaluesIF { class TcDistributor : public SystemObject,
private: public ExecutableObjectIF,
/** public HasReturnvaluesIF {
* This constant sets the maximum number of packets distributed per call.
*/
static const uint8_t DISTRIBUTER_MAX_PACKETS = 128;
protected:
/**
* This is the receiving queue for incoming Telecommands.
* The child classes must make its queue id public.
*/
MessageQueueIF* tcQueue;
/**
* The last received incoming packet information is stored in this
* member.
* As different child classes unpack the incoming packet differently
* (i.e. as a CCSDS Space Packet or as a PUS Telecommand Packet), it
* is not tried to unpack the packet information within this class.
*/
TmTcMessage currentMessage;
/**
* The map that links certain packet information to a destination.
* The packet information may be the APID of the packet or the service
* identifier. Filling of the map is under control of the different child
* classes.
*/
std::map<uint32_t, MessageQueueId_t> queueMap;
/**
* This method shall unpack the routing information from the incoming
* packet and select the map entry which represents the packet's target.
* @return An iterator to the map element to forward to or queuMap.end().
*/
virtual iterator_t selectDestination() = 0;
/**
* The handlePacket method calls the child class's selectDestination method
* and forwards the packet to its destination, if found.
* @return The message queue return value or \c RETURN_FAILED, in case no
* destination was found.
*/
ReturnValue_t handlePacket();
/**
* This method gives the child class a chance to perform some kind of operation
* after the parent tried to forward the message.
* A typically application would be sending success/failure messages.
* The default implementation just returns \c RETURN_OK.
* @param queueStatus The status of the message queue after an attempt to send the TC.
* @return - \c RETURN_OK on success
* - \c RETURN_FAILED on failure
*/
virtual ReturnValue_t callbackAfterSending( ReturnValue_t queueStatus );
public: public:
static const uint8_t INTERFACE_ID = CLASS_ID::PACKET_DISTRIBUTION; using TcMessageQueueMap = std::map<uint32_t, MessageQueueId_t>;
static const ReturnValue_t PACKET_LOST = MAKE_RETURN_CODE( 1 ); using TcMqMapIter = std::map<uint32_t, MessageQueueId_t>::iterator;
static const ReturnValue_t DESTINATION_NOT_FOUND = MAKE_RETURN_CODE( 2 );
static constexpr uint8_t INTERFACE_ID = CLASS_ID::PACKET_DISTRIBUTION;
static constexpr ReturnValue_t PACKET_LOST = MAKE_RETURN_CODE( 1 );
static constexpr ReturnValue_t DESTINATION_NOT_FOUND = MAKE_RETURN_CODE( 2 );
static constexpr ReturnValue_t SERVICE_ID_ALREADY_EXISTS = MAKE_RETURN_CODE(3);
/** /**
* Within the default constructor, the SystemObject id is set and the * Within the default constructor, the SystemObject id is set and the
* message queue is initialized. * message queue is initialized.
@ -91,7 +45,7 @@ public:
* @param set_object_id This id is assigned to the distributor * @param set_object_id This id is assigned to the distributor
* implementation. * implementation.
*/ */
TcDistributor( object_id_t set_object_id ); TcDistributor(object_id_t objectId);
/** /**
* The destructor is empty, the message queues are not in the vicinity of * The destructor is empty, the message queues are not in the vicinity of
* this class. * this class.
@ -110,7 +64,59 @@ public:
* queueMap. * queueMap.
*/ */
void print(); void print();
protected:
/**
* This is the receiving queue for incoming Telecommands.
* The child classes must make its queue id public.
*/
MessageQueueIF* tcQueue = nullptr;
/**
* The last received incoming packet information is stored in this
* member.
* As different child classes unpack the incoming packet differently
* (i.e. as a CCSDS Space Packet or as a PUS Telecommand Packet), it
* is not tried to unpack the packet information within this class.
*/
TmTcMessage currentMessage;
/**
* The map that links certain packet information to a destination.
* The packet information may be the APID of the packet or the service
* identifier. Filling of the map is under control of the different child
* classes.
*/
TcMessageQueueMap queueMap;
/**
* This method shall unpack the routing information from the incoming
* packet and select the map entry which represents the packet's target.
* @return An iterator to the map element to forward to or queuMap.end().
*/
virtual TcMqMapIter selectDestination() = 0;
/**
* The handlePacket method calls the child class's selectDestination method
* and forwards the packet to its destination, if found.
* @return The message queue return value or @c RETURN_FAILED, in case no
* destination was found.
*/
ReturnValue_t handlePacket();
/**
* This method gives the child class a chance to perform some kind of
* operation after the parent tried to forward the message.
* A typically application would be sending success/failure messages.
* The default implementation just returns @c RETURN_OK.
* @param queueStatus The status of the message queue after an attempt
* to send the TC.
* @return - @c RETURN_OK on success
* - @c RETURN_FAILED on failure
*/
virtual ReturnValue_t callbackAfterSending( ReturnValue_t queueStatus );
private:
/**
* This constant sets the maximum number of packets distributed per call.
*/
static constexpr uint8_t DISTRIBUTER_MAX_PACKETS = 128;
}; };
#endif /* TCDISTRIBUTOR_H_ */ #endif /* FSFW_TMTCSERVICES_TCDISTRIBUTOR_H_ */

View File

@ -1,31 +1,33 @@
#include "TcPacketCheck.h"
#include "../globalfunctions/CRC.h" #include "../globalfunctions/CRC.h"
#include "../serviceinterface/ServiceInterfaceStream.h" #include "../serviceinterface/ServiceInterfaceStream.h"
#include "../storagemanager/StorageManagerIF.h" #include "../storagemanager/StorageManagerIF.h"
#include "TcPacketCheck.h"
#include "../tmtcservices/VerificationCodes.h" #include "../tmtcservices/VerificationCodes.h"
TcPacketCheck::TcPacketCheck( uint16_t set_apid ) : apid(set_apid) { TcPacketCheck::TcPacketCheck( uint16_t setApid ) : apid(setApid) {
} }
ReturnValue_t TcPacketCheck::checkPacket( TcPacketStored* current_packet ) { ReturnValue_t TcPacketCheck::checkPacket( TcPacketStored* currentPacket ) {
uint16_t calculated_crc = CRC::crc16ccitt( current_packet->getWholeData(), current_packet->getFullSize() ); uint16_t calculated_crc = CRC::crc16ccitt( currentPacket->getWholeData(),
currentPacket->getFullSize() );
if ( calculated_crc != 0 ) { if ( calculated_crc != 0 ) {
return INCORRECT_CHECKSUM; return INCORRECT_CHECKSUM;
} }
bool condition = !(current_packet->hasSecondaryHeader()) || bool condition = (not currentPacket->hasSecondaryHeader()) or
current_packet->getPacketVersionNumber() != CCSDS_VERSION_NUMBER || (currentPacket->getPacketVersionNumber() != CCSDS_VERSION_NUMBER) or
!(current_packet->isTelecommand()); (not currentPacket->isTelecommand());
if ( condition ) { if ( condition ) {
return INCORRECT_PRIMARY_HEADER; return INCORRECT_PRIMARY_HEADER;
} }
if ( current_packet->getAPID() != this->apid ) if ( currentPacket->getAPID() != this->apid )
return ILLEGAL_APID; return ILLEGAL_APID;
if ( !current_packet->isSizeCorrect() ) { if ( not currentPacket->isSizeCorrect() ) {
return INCOMPLETE_PACKET; return INCOMPLETE_PACKET;
} }
condition = (current_packet->getSecondaryHeaderFlag() != CCSDS_SECONDARY_HEADER_FLAG) || condition = (currentPacket->getSecondaryHeaderFlag() != CCSDS_SECONDARY_HEADER_FLAG) ||
(current_packet->getPusVersionNumber() != PUS_VERSION_NUMBER); (currentPacket->getPusVersionNumber() != PUS_VERSION_NUMBER);
if ( condition ) { if ( condition ) {
return INCORRECT_SECONDARY_HEADER; return INCORRECT_SECONDARY_HEADER;
} }

View File

@ -1,28 +1,29 @@
#ifndef TCPACKETCHECK_H_ #ifndef FSFW_TCDISTRIBUTION_TCPACKETCHECK_H_
#define TCPACKETCHECK_H_ #define FSFW_TCDISTRIBUTION_TCPACKETCHECK_H_
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
#include "../tmtcpacket/pus/TcPacketStored.h" #include "../tmtcpacket/pus/TcPacketStored.h"
#include "../tmtcservices/PusVerificationReport.h" #include "../tmtcservices/PusVerificationReport.h"
/** /**
* This class performs a formal packet check for incoming PUS Telecommand Packets. * This class performs a formal packet check for incoming PUS Telecommand Packets.
* Currently, it only checks if the APID and CRC are correct. * Currently, it only checks if the APID and CRC are correct.
* \ingroup tc_distribution * @ingroup tc_distribution
*/ */
class TcPacketCheck : public HasReturnvaluesIF { class TcPacketCheck : public HasReturnvaluesIF {
protected: protected:
/** /**
* Describes the version number a packet must have to pass. * Describes the version number a packet must have to pass.
*/ */
static const uint8_t CCSDS_VERSION_NUMBER = 0; static constexpr uint8_t CCSDS_VERSION_NUMBER = 0;
/** /**
* Describes the secondary header a packet must have to pass. * Describes the secondary header a packet must have to pass.
*/ */
static const uint8_t CCSDS_SECONDARY_HEADER_FLAG = 0; static constexpr uint8_t CCSDS_SECONDARY_HEADER_FLAG = 0;
/** /**
* Describes the TC Packet PUS Version Number a packet must have to pass. * Describes the TC Packet PUS Version Number a packet must have to pass.
*/ */
static const uint8_t PUS_VERSION_NUMBER = 1; static constexpr uint8_t PUS_VERSION_NUMBER = 1;
/** /**
* The packet id each correct packet should have. * The packet id each correct packet should have.
* It is composed of the APID and some static fields. * It is composed of the APID and some static fields.
@ -41,19 +42,19 @@ public:
* The constructor only sets the APID attribute. * The constructor only sets the APID attribute.
* @param set_apid The APID to set. * @param set_apid The APID to set.
*/ */
TcPacketCheck( uint16_t set_apid ); TcPacketCheck( uint16_t setApid );
/** /**
* This is the actual method to formally check a certain Telecommand Packet. * This is the actual method to formally check a certain Telecommand Packet.
* The packet's Application Data can not be checked here. * The packet's Application Data can not be checked here.
* @param current_packet The packt to check * @param current_packet The packt to check
* @return - \c RETURN_OK on success. * @return - @c RETURN_OK on success.
* - \c INCORRECT_CHECKSUM if checksum is invalid. * - @c INCORRECT_CHECKSUM if checksum is invalid.
* - \c ILLEGAL_APID if APID does not match. * - @c ILLEGAL_APID if APID does not match.
*/ */
ReturnValue_t checkPacket( TcPacketStored* current_packet ); ReturnValue_t checkPacket( TcPacketStored* currentPacket );
uint16_t getApid() const; uint16_t getApid() const;
}; };
#endif /* TCPACKETCHECK_H_ */ #endif /* FSFW_TCDISTRIBUTION_TCPACKETCHECK_H_ */

View File

@ -4,31 +4,6 @@
PusVerificationMessage::PusVerificationMessage() { PusVerificationMessage::PusVerificationMessage() {
} }
//PusVerificationMessage::PusVerificationMessage(uint8_t set_report_id,
// TcPacketBase* current_packet, ReturnValue_t set_error_code,
// uint8_t set_step, uint32_t parameter1, uint32_t parameter2) {
// uint8_t ackFlags = current_packet->getAcknowledgeFlags();
// uint16_t tcPacketId = current_packet->getPacketId();
// uint16_t tcSequenceControl = current_packet->getPacketSequenceControl();
// uint8_t* data = this->getBuffer();
// data[messageSize] = set_report_id;
// messageSize += sizeof(set_report_id);
// data[messageSize] = ackFlags;
// messageSize += sizeof(ackFlags);
// memcpy(&data[messageSize], &tcPacketId, sizeof(tcPacketId));
// messageSize += sizeof(tcPacketId);
// memcpy(&data[messageSize], &tcSequenceControl, sizeof(tcSequenceControl));
// messageSize += sizeof(tcSequenceControl);
// data[messageSize] = set_step;
// messageSize += sizeof(set_step);
// memcpy(&data[messageSize], &set_error_code, sizeof(set_error_code));
// messageSize += sizeof(set_error_code);
// memcpy(&data[messageSize], &parameter1, sizeof(parameter1));
// messageSize += sizeof(parameter1);
// memcpy(&data[messageSize], &parameter2, sizeof(parameter2));
// messageSize += sizeof(parameter2);
//}
PusVerificationMessage::PusVerificationMessage(uint8_t set_report_id, PusVerificationMessage::PusVerificationMessage(uint8_t set_report_id,
uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl,
ReturnValue_t set_error_code, uint8_t set_step, uint32_t parameter1, ReturnValue_t set_error_code, uint8_t set_step, uint32_t parameter1,

View File

@ -1,9 +1,13 @@
#ifndef PUSVERIFICATIONREPORT_H_ #ifndef FSFW_TMTCSERVICES_PUSVERIFICATIONREPORT_H_
#define PUSVERIFICATIONREPORT_H_ #define FSFW_TMTCSERVICES_PUSVERIFICATIONREPORT_H_
#include "VerificationCodes.h"
#include "../ipc/MessageQueueMessage.h" #include "../ipc/MessageQueueMessage.h"
#include "../tmtcpacket/pus/TcPacketBase.h" #include "../tmtcpacket/pus/TcPacketBase.h"
#include "VerificationCodes.h" #include "../returnvalues/HasReturnvaluesIF.h"
#include <cstdint>
class PusVerificationMessage: public MessageQueueMessage { class PusVerificationMessage: public MessageQueueMessage {
private: private:
@ -30,7 +34,7 @@ private:
public: public:
static const uint8_t VERIFICATION_MIN_SIZE = 6; static const uint8_t VERIFICATION_MIN_SIZE = 6;
PusVerificationMessage(); PusVerificationMessage();
// PusVerificationMessage( uint8_t set_report_id, TcPacketBase* current_packet, ReturnValue_t set_error_code = 0, uint8_t set_step = 0, uint32_t parameter1 = 0, uint32_t parameter2 = 0 );
PusVerificationMessage(uint8_t set_report_id, uint8_t ackFlags, PusVerificationMessage(uint8_t set_report_id, uint8_t ackFlags,
uint16_t tcPacketId, uint16_t tcSequenceControl, uint16_t tcPacketId, uint16_t tcSequenceControl,
ReturnValue_t set_error_code = 0, uint8_t set_step = 0, ReturnValue_t set_error_code = 0, uint8_t set_step = 0,
@ -74,4 +78,4 @@ public:
uint8_t* getReport(); uint8_t* getReport();
}; };
#endif /* PUSVERIFICATIONREPORT_H_ */ #endif /* FSFW_TMTCSERVICES_PUSVERIFICATIONREPORT_H_ */