Merge branch 'master' of egit.irs.uni-stuttgart.de:fsfw/fsfw into PLOC_SOURCE

This commit is contained in:
petriVM18 2020-10-07 15:09:24 +02:00
commit 5c2b4cf783
113 changed files with 6537 additions and 5449 deletions

View File

@ -1,5 +1,6 @@
#include "ActionHelper.h"
#include "HasActionsIF.h"
#include "../ipc/MessageQueueSenderIF.h"
#include "../objectmanager/ObjectManagerIF.h"
ActionHelper::ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue) :

View File

@ -1,15 +1,15 @@
#ifndef ARRAYLIST_H_
#define ARRAYLIST_H_
#ifndef FSFW_CONTAINER_ARRAYLIST_H_
#define FSFW_CONTAINER_ARRAYLIST_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../serialize/SerializeAdapter.h"
#include "../serialize/SerializeIF.h"
/**
* A List that stores its values in an array.
*
* The backend is an array that can be allocated by the class itself or supplied via ctor.
*
* @brief A List that stores its values in an array.
* @details
* The underlying storage is an array that can be allocated by the class
* itself or supplied via ctor.
*
* @ingroup container
*/
@ -20,6 +20,53 @@ public:
static const uint8_t INTERFACE_ID = CLASS_ID::ARRAY_LIST;
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
*
@ -31,10 +78,7 @@ public:
/**
* Empty ctor, points to NULL
*/
Iterator() :
value(0) {
}
Iterator(): value(0) {}
/**
* Initializes the Iterator to point to an element
@ -87,56 +131,16 @@ public:
const T *operator->() const {
return value;
}
};
//SHOULDDO this should be implemented as non-member
bool operator==(const typename ArrayList<T, count_t>::Iterator& other) const{
return (value == other.value);
friend bool operator==(const ArrayList::Iterator& lhs,
const ArrayList::Iterator& rhs) {
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];
}
/**
* 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) {
}
/**
* Destructor, if the allocating constructor was used, it deletes the array.
*/
virtual ~ArrayList() {
if (allocated) {
delete[] entries;
}
friend bool operator!=(const ArrayList::Iterator& lhs,
const ArrayList::Iterator& rhs) {
return not (lhs.value == rhs.value);
}
/**
@ -192,7 +196,7 @@ public:
*
* @return maximum number of elements
*/
uint32_t maxSize() const {
size_t maxSize() const {
return this->maxSize_;
}
@ -227,19 +231,7 @@ public:
count_t remaining() {
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:
/**
* pointer to the array in which the entries are stored
@ -248,12 +240,14 @@ protected:
/**
* remembering the maximum size
*/
uint32_t maxSize_;
size_t maxSize_;
/**
* true if the array was allocated and needs to be deleted in the destructor.
*/
bool allocated;
};
#endif /* ARRAYLIST_H_ */
#endif /* FSFW_CONTAINER_ARRAYLIST_H_ */

View File

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

View File

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

View File

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

View File

@ -7,14 +7,21 @@
#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 A User is not allowed to change the key, otherwise the map is corrupted.
* @ingroup container
*/
template<typename key_t, typename T>
class FixedMap: public SerializeIF {
static_assert (std::is_trivially_copyable<T>::value or 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");
static_assert (std::is_trivially_copyable<T>::value or
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:
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP;
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 {
return Iterator(&theMap[0]);
}
@ -136,6 +153,24 @@ public:
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() {
_size = 0;
}

View File

@ -1,166 +1,206 @@
#ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_
#define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_
#ifndef FSFW_CONTAINER_FIXEDORDEREDMULTIMAP_H_
#define FSFW_CONTAINER_FIXEDORDEREDMULTIMAP_H_
#include "ArrayList.h"
#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
*/
template<typename key_t, typename T, typename KEY_COMPARE = std::less<key_t>>
class FixedOrderedMultimap {
public:
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 MAP_FULL = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MULTIMAP;
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x02);
private:
typedef KEY_COMPARE compare;
compare myComp;
ArrayList<std::pair<key_t, T>, uint32_t> theMap;
uint32_t _size;
uint32_t findFirstIndex(key_t key, uint32_t startAt = 0) const {
if (startAt >= _size) {
return startAt + 1;
}
uint32_t i = startAt;
for (i = startAt; i < _size; ++i) {
if (theMap[i].first == key) {
return i;
}
}
return i;
/***
* Constructor which needs a size_t for the maximum allowed size
*
* Can not be resized during runtime
*
* Allocates memory at construction
* @param maxSize size_t of Maximum allowed size
*/
FixedOrderedMultimap(size_t maxSize):theMap(maxSize), _size(0){
}
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 destructor frees Memory by deleting its member
*/
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:
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) :
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 {
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 {
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;
}
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr) {
if (_size == theMap.maxSize()) {
return MAP_FULL;
}
uint32_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;
/**
* Clears the map, does not deallocate any memory
*/
void clear(){
_size = 0;
}
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;
if (findFirstIndex(key) < _size) {
result = HasReturnvaluesIF::RETURN_OK;
}
return result;
}
/***
* Used to insert a key and value separately.
*
* @param[in] key Key of the new element
* @param[in] value Value of the new element
* @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;
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;
}
/***
* Used to insert new pair instead of single values
*
* @param pair Pair to be inserted
* @return RETURN_OK if insert was successful, MAP_FULL if no space is available
*/
ReturnValue_t insert(std::pair<key_t, T> pair);
ReturnValue_t erase(key_t key) {
uint32_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;
}
/***
* Can be used to check if a certain key is in the map
* @param key Key to be checked
* @return RETURN_OK if the key exists KEY_DOES_NOT_EXIST otherwise
*/
ReturnValue_t exists(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);
if (result != HasReturnvaluesIF::RETURN_OK) {
return end();
}
return Iterator(&theMap[findFirstIndex(key)]);
}
ReturnValue_t 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;
}
void clear() {
_size = 0;
}
uint32_t maxSize() const {
return theMap.maxSize();
}
};
#endif /* FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ */
/***
* 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);
}
friend bool operator!=(const typename FixedOrderedMultimap::Iterator& lhs,
const typename FixedOrderedMultimap::Iterator& rhs) {
return not (lhs.value == rhs.value);
}
private:
typedef KEY_COMPARE compare;
compare myComp;
ArrayList<std::pair<key_t, T>, size_t> theMap;
size_t _size;
size_t findFirstIndex(key_t key, size_t startAt = 0) const;
size_t findNicePlace(key_t key) const;
void removeFromPosition(size_t position);
};
#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 <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 {
public:
PlacementFactory(StorageManagerIF* 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>
T* generate(Args&&... args) {
store_address_t tempId;
uint8_t* pData = NULL;
uint8_t* pData = nullptr;
ReturnValue_t result = dataBackend->getFreeElement(&tempId, sizeof(T),
&pData);
if (result != HasReturnvaluesIF::RETURN_OK) {
return NULL;
return nullptr;
}
T* temp = new (pData) T(std::forward<Args>(args)...);
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>
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).
thisElement->~T();
uint8_t* pointer = (uint8_t*) (thisElement);

View File

@ -1,96 +1,113 @@
#ifndef FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_
#define FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_
#ifndef FSFW_CONTAINER_RINGBUFFERBASE_H_
#define FSFW_CONTAINER_RINGBUFFERBASE_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include <cstddef>
template<uint8_t N_READ_PTRS = 1>
class RingBufferBase {
public:
RingBufferBase(uint32_t startAddress, uint32_t size, bool overwriteOld) :
start(startAddress), write(startAddress), size(size), overwriteOld(overwriteOld) {
RingBufferBase(size_t startAddress, const size_t size, bool overwriteOld) :
start(startAddress), write(startAddress), size(size),
overwriteOld(overwriteOld) {
for (uint8_t count = 0; count < N_READ_PTRS; count++) {
read[count] = startAddress;
}
}
ReturnValue_t readData(uint32_t amount, uint8_t n = 0) {
if (availableReadData(n) >= amount) {
incrementRead(amount, n);
return HasReturnvaluesIF::RETURN_OK;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
ReturnValue_t writeData(uint32_t amount) {
if (availableWriteSpace() >= amount || overwriteOld) {
incrementWrite(amount);
return HasReturnvaluesIF::RETURN_OK;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
uint32_t availableReadData(uint8_t n = 0) const {
return ((write + size) - read[n]) % size;
}
uint32_t availableWriteSpace(uint8_t n = 0) const {
//One less to avoid ambiguous full/empty problem.
return (((read[n] + size) - write - 1) % size);
}
virtual ~RingBufferBase() {}
bool isFull(uint8_t n = 0) {
return (availableWriteSpace(n) == 0);
}
bool isEmpty(uint8_t n = 0) {
return (availableReadData(n) == 0);
return (getAvailableReadData(n) == 0);
}
virtual ~RingBufferBase() {
size_t getAvailableReadData(uint8_t n = 0) const {
return ((write + size) - read[n]) % size;
}
uint32_t getRead(uint8_t n = 0) const {
return read[n];
size_t availableWriteSpace(uint8_t n = 0) const {
//One less to avoid ambiguous full/empty problem.
return (((read[n] + size) - write - 1) % size);
}
void setRead(uint32_t read, uint8_t n = 0) {
if (read >= start && read < (start+size)) {
this->read[n] = read;
bool overwritesOld() const {
return overwriteOld;
}
size_t getMaxSize() const {
return size - 1;
}
uint32_t getWrite() const {
return write;
}
void setWrite(uint32_t write) {
this->write = write;
}
void clear() {
write = start;
for (uint8_t count = 0; count < N_READ_PTRS; count++) {
read[count] = start;
}
}
uint32_t writeTillWrap() {
size_t writeTillWrap() {
return (start + size) - write;
}
uint32_t readTillWrap(uint8_t n = 0) {
size_t readTillWrap(uint8_t n = 0) {
return (start + size) - read[n];
}
uint32_t getStart() const {
size_t getStart() const {
return start;
}
bool overwritesOld() const {
return overwriteOld;
}
uint32_t maxSize() const {
return size - 1;
}
protected:
const uint32_t start;
uint32_t write;
uint32_t read[N_READ_PTRS];
const uint32_t size;
const size_t start;
size_t write;
size_t read[N_READ_PTRS];
const size_t size;
const bool overwriteOld;
void incrementWrite(uint32_t amount) {
write = ((write + amount - start) % size) + start;
}
void incrementRead(uint32_t amount, uint8_t n = 0) {
read[n] = ((read[n] + amount - start) % size) + start;
}
ReturnValue_t readData(uint32_t amount, uint8_t n = 0) {
if (getAvailableReadData(n) >= amount) {
incrementRead(amount, n);
return HasReturnvaluesIF::RETURN_OK;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
ReturnValue_t writeData(uint32_t amount) {
if (availableWriteSpace() >= amount or overwriteOld) {
incrementWrite(amount);
return HasReturnvaluesIF::RETURN_OK;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
size_t getRead(uint8_t n = 0) const {
return read[n];
}
void setRead(uint32_t read, uint8_t n = 0) {
if (read >= start && read < (start+size)) {
this->read[n] = read;
}
}
uint32_t getWrite() const {
return write;
}
void setWrite(uint32_t write) {
this->write = write;
}
};
#endif /* FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_ */
#endif /* FSFW_CONTAINER_RINGBUFFERBASE_H_ */

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

@ -0,0 +1,30 @@
#include "SharedRingBuffer.h"
#include "../ipc/MutexFactory.h"
#include "../ipc/MutexHelper.h"
SharedRingBuffer::SharedRingBuffer(object_id_t objectId, const size_t size,
bool overwriteOld, size_t maxExcessBytes):
SystemObject(objectId), SimpleRingBuffer(size, overwriteOld,
maxExcessBytes) {
mutex = MutexFactory::instance()->createMutex();
}
SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer,
const size_t size, bool overwriteOld, size_t maxExcessBytes):
SystemObject(objectId), SimpleRingBuffer(buffer, size, overwriteOld,
maxExcessBytes) {
mutex = MutexFactory::instance()->createMutex();
}
ReturnValue_t SharedRingBuffer::lockRingBufferMutex(
MutexIF::TimeoutType timeoutType, dur_millis_t timeout) {
return mutex->lockMutex(timeoutType, timeout);
}
ReturnValue_t SharedRingBuffer::unlockRingBufferMutex() {
return mutex->unlockMutex();
}
MutexIF* SharedRingBuffer::getMutexHandle() const {
return mutex;
}

View File

@ -0,0 +1,68 @@
#ifndef FSFW_CONTAINER_SHAREDRINGBUFFER_H_
#define FSFW_CONTAINER_SHAREDRINGBUFFER_H_
#include "SimpleRingBuffer.h"
#include "../ipc/MutexIF.h"
#include "../objectmanager/SystemObject.h"
#include "../timemanager/Clock.h"
/**
* @brief Ring buffer which can be shared among multiple objects
* @details
* This class offers a mutex to perform thread-safe operation on the ring
* buffer. It is still up to the developer to actually perform the lock
* and unlock operations.
*/
class SharedRingBuffer: public SystemObject,
public SimpleRingBuffer {
public:
/**
* This constructor allocates a new internal buffer with the supplied size.
* @param size
* @param overwriteOld
* If the ring buffer is overflowing at a write operartion, the oldest data
* will be overwritten.
*/
SharedRingBuffer(object_id_t objectId, const size_t size,
bool overwriteOld, size_t maxExcessBytes);
/**
* This constructor takes an external buffer with the specified size.
* @param buffer
* @param size
* @param overwriteOld
* If the ring buffer is overflowing at a write operartion, the oldest data
* will be overwritten.
*/
SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const size_t size,
bool overwriteOld, size_t maxExcessBytes);
/**
* Unless a read-only constant value is read, all operations on the
* shared ring buffer should be protected by calling this function.
* @param timeoutType
* @param timeout
* @return
*/
virtual ReturnValue_t lockRingBufferMutex(MutexIF::TimeoutType timeoutType,
dur_millis_t timeout);
/**
* Any locked mutex also has to be unlocked, otherwise, access to the
* shared ring buffer will be blocked.
* @return
*/
virtual ReturnValue_t unlockRingBufferMutex();
/**
* The mutex handle can be accessed directly, for example to perform
* the lock with the #MutexHelper for a RAII compliant lock operation.
* @return
*/
MutexIF* getMutexHandle() const;
private:
MutexIF* mutex = nullptr;
};
#endif /* FSFW_CONTAINER_SHAREDRINGBUFFER_H_ */

View File

@ -1,27 +1,69 @@
#include "SimpleRingBuffer.h"
#include <string.h>
#include <cstring>
SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld) :
RingBufferBase<>(0, size, overwriteOld) {
buffer = new uint8_t[size];
SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld,
size_t maxExcessBytes) :
RingBufferBase<>(0, size, overwriteOld),
maxExcessBytes(maxExcessBytes) {
if(maxExcessBytes > size) {
this->maxExcessBytes = size;
}
else {
this->maxExcessBytes = maxExcessBytes;
}
buffer = new uint8_t[size + maxExcessBytes];
}
SimpleRingBuffer::SimpleRingBuffer(uint8_t *buffer, const size_t size,
bool overwriteOld):
RingBufferBase<>(0, size, overwriteOld), buffer(buffer) {}
bool overwriteOld, size_t maxExcessBytes):
RingBufferBase<>(0, size, overwriteOld), buffer(buffer) {
if(maxExcessBytes > size) {
this->maxExcessBytes = size;
}
else {
this->maxExcessBytes = maxExcessBytes;
}
}
SimpleRingBuffer::~SimpleRingBuffer() {
delete[] buffer;
}
ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data,
uint32_t amount) {
ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer,
size_t amount) {
if (availableWriteSpace() >= amount or overwriteOld) {
uint32_t amountTillWrap = writeTillWrap();
size_t amountTillWrap = writeTillWrap();
if (amountTillWrap < amount) {
if((amount - amountTillWrap + excessBytes) > maxExcessBytes) {
return HasReturnvaluesIF::RETURN_FAILED;
}
excessBytes = amount - amountTillWrap;
}
*writePointer = &buffer[write];
return HasReturnvaluesIF::RETURN_OK;
}
else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
void SimpleRingBuffer::confirmBytesWritten(size_t amount) {
if(getExcessBytes() > 0) {
moveExcessBytesToStart();
}
incrementWrite(amount);
}
ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data,
size_t amount) {
if (availableWriteSpace() >= amount or overwriteOld) {
size_t amountTillWrap = writeTillWrap();
if (amountTillWrap >= amount) {
// remaining size in buffer is sufficient to fit full amount.
memcpy(&buffer[write], data, amount);
} else {
}
else {
memcpy(&buffer[write], data, amountTillWrap);
memcpy(buffer, data + amountTillWrap, amount - amountTillWrap);
}
@ -32,12 +74,13 @@ ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data,
}
}
ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, uint32_t amount,
bool readRemaining, uint32_t* trueAmount) {
uint32_t availableData = availableReadData(READ_PTR);
uint32_t amountTillWrap = readTillWrap(READ_PTR);
ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, size_t amount,
bool incrementReadPtr, bool readRemaining, size_t* trueAmount) {
size_t availableData = getAvailableReadData(READ_PTR);
size_t amountTillWrap = readTillWrap(READ_PTR);
if (availableData < amount) {
if (readRemaining) {
// more data available than amount specified.
amount = availableData;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
@ -52,12 +95,27 @@ ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, uint32_t amount,
memcpy(data, &buffer[read[READ_PTR]], amountTillWrap);
memcpy(data + amountTillWrap, buffer, amount - amountTillWrap);
}
if(incrementReadPtr) {
deleteData(amount, readRemaining);
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t SimpleRingBuffer::deleteData(uint32_t amount,
bool deleteRemaining, uint32_t* trueAmount) {
uint32_t availableData = availableReadData(READ_PTR);
size_t SimpleRingBuffer::getExcessBytes() const {
return excessBytes;
}
void SimpleRingBuffer::moveExcessBytesToStart() {
if(excessBytes > 0) {
std::memcpy(buffer, &buffer[size], excessBytes);
excessBytes = 0;
}
}
ReturnValue_t SimpleRingBuffer::deleteData(size_t amount,
bool deleteRemaining, size_t* trueAmount) {
size_t availableData = getAvailableReadData(READ_PTR);
if (availableData < amount) {
if (deleteRemaining) {
amount = availableData;
@ -71,4 +129,3 @@ ReturnValue_t SimpleRingBuffer::deleteData(uint32_t amount,
incrementRead(amount, READ_PTR);
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -1,8 +1,8 @@
#ifndef FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_
#define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_
#ifndef FSFW_CONTAINER_SIMPLERINGBUFFER_H_
#define FSFW_CONTAINER_SIMPLERINGBUFFER_H_
#include "RingBufferBase.h"
#include <stddef.h>
#include <cstddef>
/**
* @brief Circular buffer implementation, useful for buffering
@ -16,53 +16,114 @@ class SimpleRingBuffer: public RingBufferBase<> {
public:
/**
* This constructor allocates a new internal buffer with the supplied size.
*
* @param size
* @param overwriteOld
* @param overwriteOld If the ring buffer is overflowing at a write
* operation, the oldest data will be overwritten.
* @param maxExcessBytes These additional bytes will be allocated in addtion
* to the specified size to accomodate contiguous write operations
* with getFreeElement.
*
*/
SimpleRingBuffer(const size_t size, bool overwriteOld);
SimpleRingBuffer(const size_t size, bool overwriteOld,
size_t maxExcessBytes = 0);
/**
* This constructor takes an external buffer with the specified size.
* @param buffer
* @param size
* @param overwriteOld
* If the ring buffer is overflowing at a write operartion, the oldest data
* will be overwritten.
* @param maxExcessBytes
* If the buffer can accomodate additional bytes for contigous write
* operations with getFreeElement, this is the maximum allowed additional
* size
*/
SimpleRingBuffer(uint8_t* buffer, const size_t size, bool overwriteOld);
SimpleRingBuffer(uint8_t* buffer, const size_t size, bool overwriteOld,
size_t maxExcessBytes = 0);
virtual ~SimpleRingBuffer();
/**
* Write to circular buffer and increment write pointer by amount
* Write to circular buffer and increment write pointer by amount.
* @param data
* @param amount
* @return -@c RETURN_OK if write operation was successfull
* -@c RETURN_FAILED if
*/
ReturnValue_t writeData(const uint8_t* data, size_t amount);
/**
* Returns a pointer to a free element. If the remaining buffer is
* not large enough, the data will be written past the actual size
* and the amount of excess bytes will be cached. This function
* does not increment the write pointer!
* @param writePointer Pointer to a pointer which can be used to write
* contiguous blocks into the ring buffer
* @param amount
* @return
*/
ReturnValue_t writeData(const uint8_t* data, uint32_t amount);
ReturnValue_t getFreeElement(uint8_t** writePointer, size_t amount);
/**
* Read from circular buffer at read pointer
* This increments the write pointer and also copies the excess bytes
* to the beginning. It should be called if the write operation
* conducted after calling getFreeElement() was performed.
* @return
*/
void confirmBytesWritten(size_t amount);
virtual size_t getExcessBytes() const;
/**
* Helper functions which moves any excess bytes to the start
* of the ring buffer.
* @return
*/
virtual void moveExcessBytesToStart();
/**
* Read from circular buffer at read pointer.
* @param data
* @param amount
* @param incrementReadPtr
* If this is set to true, the read pointer will be incremented.
* If readRemaining is set to true, the read pointer will be incremented
* accordingly.
* @param readRemaining
* @param trueAmount
* If this is set to true, the data will be read even if the amount
* specified exceeds the read data available.
* @param trueAmount [out]
* If readRemaining was set to true, the true amount read will be assigned
* to the passed value.
* @return
* - @c RETURN_OK if data was read successfully
* - @c RETURN_FAILED if not enough data was available and readRemaining
* was set to false.
*/
ReturnValue_t readData(uint8_t* data, uint32_t amount,
bool readRemaining = false, uint32_t* trueAmount = nullptr);
ReturnValue_t readData(uint8_t* data, size_t amount,
bool incrementReadPtr = false, bool readRemaining = false,
size_t* trueAmount = nullptr);
/**
* Delete data starting by incrementing read pointer
* Delete data by incrementing read pointer.
* @param amount
* @param deleteRemaining
* @param trueAmount
* If the amount specified is larger than the remaing size to read and this
* is set to true, the remaining amount will be deleted as well
* @param trueAmount [out]
* If deleteRemaining was set to true, the amount deleted will be assigned
* to the passed value.
* @return
*/
ReturnValue_t deleteData(uint32_t amount, bool deleteRemaining = false,
uint32_t* trueAmount = nullptr);
ReturnValue_t deleteData(size_t amount, bool deleteRemaining = false,
size_t* trueAmount = nullptr);
private:
// static const uint8_t TEMP_READ_PTR = 1;
static const uint8_t READ_PTR = 0;
uint8_t* buffer = nullptr;
size_t maxExcessBytes;
size_t excessBytes = 0;
};
#endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */
#endif /* FSFW_CONTAINER_SIMPLERINGBUFFER_H_ */

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

@ -18,7 +18,7 @@ MapPacketExtraction::MapPacketExtraction(uint8_t setMapId,
object_id_t setPacketDestination) :
lastSegmentationFlag(NO_SEGMENTATION), mapId(setMapId), packetLength(0), bufferPosition(
packetBuffer), packetDestination(setPacketDestination), packetStore(
NULL), tcQueueId(MessageQueueSenderIF::NO_QUEUE) {
NULL), tcQueueId(MessageQueueIF::NO_QUEUE) {
memset(packetBuffer, 0, sizeof(packetBuffer));
}

View File

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

View File

@ -5,7 +5,7 @@ HealthDevice::HealthDevice(object_id_t setObjectId,
MessageQueueId_t parentQueue) :
SystemObject(setObjectId), lastHealth(HEALTHY), parentQueue(
parentQueue), commandQueue(), healthHelper(this, setObjectId) {
commandQueue = QueueFactory::instance()->createMessageQueue(3, CommandMessage::COMMAND_MESSAGE_SIZE);
commandQueue = QueueFactory::instance()->createMessageQueue(3);
}
HealthDevice::~HealthDevice() {

View File

@ -1,5 +1,5 @@
#ifndef FRAMEWORK_EVENTS_FWSUBSYSTEMIDRANGES_H_
#define FRAMEWORK_EVENTS_FWSUBSYSTEMIDRANGES_H_
#ifndef FSFW_EVENTS_FWSUBSYSTEMIDRANGES_H_
#define FSFW_EVENTS_FWSUBSYSTEMIDRANGES_H_
namespace SUBSYSTEM_ID {
enum {
@ -19,10 +19,12 @@ enum {
SYSTEM_MANAGER_1 = 75,
SYSTEM_1 = 79,
PUS_SERVICE_1 = 80,
PUS_SERVICE_9 = 89,
PUS_SERVICE_17 = 97,
FW_SUBSYSTEM_ID_RANGE
};
}
#endif /* FRAMEWORK_EVENTS_FWSUBSYSTEMIDRANGES_H_ */
#endif /* FSFW_EVENTS_FWSUBSYSTEMIDRANGES_H_ */

View File

@ -1,33 +1,15 @@
/**
* @file CommandMessage.cpp
* @brief This file defines the CommandMessage class.
* @date 20.06.2013
* @author baetz
*/
#include "../devicehandlers/DeviceHandlerMessage.h"
#include "../health/HealthMessage.h"
#include "CommandMessage.h"
#include "../memory/MemoryMessage.h"
#include "../modes/ModeMessage.h"
#include "../monitoring/MonitoringMessage.h"
#include "../subsystem/modes/ModeSequenceMessage.h"
#include "../tmstorage/TmStoreMessage.h"
#include "../parameters/ParameterMessage.h"
namespace messagetypes {
void clearMissionMessage(CommandMessage* message);
}
#include "CommandMessageCleaner.h"
#include <cstring>
CommandMessage::CommandMessage() {
this->messageSize = COMMAND_MESSAGE_SIZE;
MessageQueueMessage::setMessageSize(DEFAULT_COMMAND_MESSAGE_SIZE);
setCommand(CMD_NONE);
}
CommandMessage::CommandMessage(Command_t command, uint32_t parameter1,
uint32_t parameter2) {
this->messageSize = COMMAND_MESSAGE_SIZE;
MessageQueueMessage::setMessageSize(DEFAULT_COMMAND_MESSAGE_SIZE);
setCommand(command);
setParameter(parameter1);
setParameter2(parameter2);
@ -35,82 +17,72 @@ CommandMessage::CommandMessage(Command_t command, uint32_t parameter1,
Command_t CommandMessage::getCommand() const {
Command_t command;
memcpy(&command, getData(), sizeof(Command_t));
std::memcpy(&command, MessageQueueMessage::getData(), sizeof(Command_t));
return command;
}
void CommandMessage::setCommand(Command_t command) {
memcpy(getData(), &command, sizeof(command));
std::memcpy(MessageQueueMessage::getData(), &command, sizeof(Command_t));
}
uint8_t CommandMessage::getMessageType() const {
// first byte of command ID.
return getCommand() >> 8 & 0xff;
}
uint32_t CommandMessage::getParameter() const {
uint32_t parameter1;
memcpy(&parameter1, getData() + sizeof(Command_t), sizeof(parameter1));
std::memcpy(&parameter1, this->getData(), sizeof(parameter1));
return parameter1;
}
void CommandMessage::setParameter(uint32_t parameter1) {
memcpy(getData() + sizeof(Command_t), &parameter1, sizeof(parameter1));
std::memcpy(this->getData(), &parameter1, sizeof(parameter1));
}
uint32_t CommandMessage::getParameter2() const {
uint32_t parameter2;
memcpy(&parameter2, getData() + sizeof(Command_t) + sizeof(uint32_t),
std::memcpy(&parameter2, this->getData() + sizeof(uint32_t),
sizeof(parameter2));
return parameter2;
}
void CommandMessage::setParameter2(uint32_t parameter2) {
memcpy(getData() + sizeof(Command_t) + sizeof(uint32_t), &parameter2,
std::memcpy(this->getData() + sizeof(uint32_t), &parameter2,
sizeof(parameter2));
}
void CommandMessage::clearCommandMessage() {
switch((getCommand()>>8) & 0xff){
case messagetypes::MODE_COMMAND:
ModeMessage::clear(this);
break;
case messagetypes::HEALTH_COMMAND:
HealthMessage::clear(this);
break;
case messagetypes::MODE_SEQUENCE:
ModeSequenceMessage::clear(this);
break;
case messagetypes::ACTION:
ActionMessage::clear(this);
break;
case messagetypes::DEVICE_HANDLER_COMMAND:
DeviceHandlerMessage::clear(this);
break;
case messagetypes::MEMORY:
MemoryMessage::clear(this);
break;
case messagetypes::MONITORING:
MonitoringMessage::clear(this);
break;
case messagetypes::TM_STORE:
TmStoreMessage::clear(this);
break;
case messagetypes::PARAMETER:
ParameterMessage::clear(this);
break;
default:
messagetypes::clearMissionMessage(this);
break;
uint32_t CommandMessage::getParameter3() const {
uint32_t parameter3;
std::memcpy(&parameter3, this->getData() + 2 * sizeof(uint32_t),
sizeof(parameter3));
return parameter3;
}
void CommandMessage::setParameter3(uint32_t parameter3) {
std::memcpy(this->getData() + 2 * sizeof(uint32_t), &parameter3,
sizeof(parameter3));
}
size_t CommandMessage::getMinimumMessageSize() const {
return MINIMUM_COMMAND_MESSAGE_SIZE;
}
void CommandMessage::clearCommandMessage() {
clear();
}
void CommandMessage::clear() {
CommandMessageCleaner::clearCommandMessage(this);
}
bool CommandMessage::isClearedCommandMessage() {
return getCommand() == CMD_NONE;
}
size_t CommandMessage::getMinimumMessageSize() const {
return COMMAND_MESSAGE_SIZE;
}
void CommandMessage::setToUnknownCommand() {
Command_t initialCommand = getCommand();
clearCommandMessage();
this->clear();
setReplyRejected(UNKNOWN_COMMAND, initialCommand);
}
@ -129,3 +101,11 @@ ReturnValue_t CommandMessage::getReplyRejectedReason(
}
return reason;
}
uint8_t* CommandMessage::getData() {
return MessageQueueMessage::getData() + sizeof(Command_t);
}
const uint8_t* CommandMessage::getData() const {
return MessageQueueMessage::getData() + sizeof(Command_t);
}

View File

@ -1,114 +1,88 @@
/**
* @file CommandMessage.h
* @brief This file defines the CommandMessage class.
* @date 20.06.2013
* @author baetz
*/
#ifndef FSFW_IPC_COMMANDMESSAGE_H_
#define FSFW_IPC_COMMANDMESSAGE_H_
#ifndef COMMANDMESSAGE_H_
#define COMMANDMESSAGE_H_
#include "FwMessageTypes.h"
#include <config/ipc/MissionMessageTypes.h>
#include "CommandMessageIF.h"
#include "MessageQueueMessage.h"
#define MAKE_COMMAND_ID( number ) ((MESSAGE_ID << 8) + (number))
typedef ReturnValue_t Command_t;
class CommandMessage : public MessageQueueMessage {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_MESSAGE;
static const ReturnValue_t UNKNOWN_COMMAND = MAKE_RETURN_CODE(0x01);
static const uint8_t MESSAGE_ID = messagetypes::COMMAND;
static const Command_t CMD_NONE = MAKE_COMMAND_ID( 0 );//!< Used internally, will be ignored
static const Command_t REPLY_COMMAND_OK = MAKE_COMMAND_ID( 3 );
static const Command_t REPLY_REJECTED = MAKE_COMMAND_ID( 0xD1 );//!< Reply indicating that the current command was rejected, par1 should contain the error code
#include "FwMessageTypes.h"
/**
* This is the size of a message as it is seen by the MessageQueue
*/
static const size_t COMMAND_MESSAGE_SIZE = HEADER_SIZE
+ sizeof(Command_t) + 2 * sizeof(uint32_t);
/**
* Default Constructor, does not initialize anything.
* @brief Default command message used to pass command messages between tasks.
* Primary message type for IPC. Contains sender, 2-byte command ID
* field, and 3 4-byte parameter
* @details
* It operates on an external memory which is contained inside a
* class implementing MessageQueueMessageIF by taking its address.
* This allows for a more flexible designs of message implementations.
* The pointer can be passed to different message implementations without
* the need of unnecessary copying.
*
* This constructor should be used when receiving a Message, as the content is filled by the MessageQueue.
* The command message is based of the generic MessageQueueMessage which
* currently has an internal message size of 28 bytes.
* @author Bastian Baetz
*/
class CommandMessage: public MessageQueueMessage, public CommandMessageIF {
public:
/**
* Default size can accomodate 3 4-byte parameters.
*/
static constexpr size_t DEFAULT_COMMAND_MESSAGE_SIZE =
CommandMessageIF::MINIMUM_COMMAND_MESSAGE_SIZE +
3 * sizeof(uint32_t);
/**
* @brief Default Constructor, does not initialize anything.
* @details
* This constructor should be used when receiving a Message, as the
* content is filled by the MessageQueue.
*/
CommandMessage();
/**
* This constructor creates a new message with all message content initialized
* This constructor creates a new message with all message content
* initialized
*
* @param command The DeviceHandlerCommand_t that will be sent
* @param parameter1 The first parameter
* @param parameter2 The second parameter
*/
CommandMessage(Command_t command,
uint32_t parameter1, uint32_t parameter2);
CommandMessage(Command_t command, uint32_t parameter1, uint32_t parameter2);
/**
* Default Destructor
* @brief Default Destructor
*/
virtual ~CommandMessage() {
}
virtual ~CommandMessage() {}
/**
* Read the DeviceHandlerCommand_t that is stored in the message, usually used after receiving
* Read the DeviceHandlerCommand_t that is stored in the message,
* usually used after receiving.
*
* @return the Command stored in the Message
*/
Command_t getCommand() const;
virtual Command_t getCommand() const override;
/**
* Set the DeviceHandlerCOmmand_t of the message
*
* Set the command type of the message. Default implementation also
* sets the message type, which will be the first byte of the command ID.
* @param the Command to be sent
*/
void setCommand(Command_t command);
virtual void setCommand(Command_t command);
virtual uint8_t* getData() override;
virtual const uint8_t* getData() const override;
/**
* Get the first parameter of the message
*
* @return the first Parameter of the message
*/
uint32_t getParameter() const;
/**
* Set the first parameter of the message
*
* @param the first parameter of the message
*/
void setParameter(uint32_t parameter1);
/**
* Get the second parameter of the message
*
* @return the second Parameter of the message
*/
uint32_t getParameter2() const;
/**
* Set the second parameter of the message
*
* @param the second parameter of the message
*/
void setParameter2(uint32_t parameter2);
/**
* Set the command to CMD_NONE and try to find
* the correct class to handle a more detailed
* clear.
* Also, calls a mission-specific clearMissionMessage
* function to separate between framework and mission
* messages. Not optimal, may be replaced by totally
* different auto-delete solution (e.g. smart pointers).
*
*/
void clearCommandMessage();
uint32_t getParameter3() const;
void setParameter3(uint32_t parameter3);
/**
* check if a message was cleared
@ -117,18 +91,41 @@ public:
*/
bool isClearedCommandMessage();
/**
* Sets the command to REPLY_REJECTED with parameter UNKNOWN_COMMAND.
* Is needed quite often, so we better code it once only.
*/
void setToUnknownCommand();
void setReplyRejected(ReturnValue_t reason, Command_t initialCommand = CMD_NONE);
ReturnValue_t getReplyRejectedReason(
Command_t *initialCommand = nullptr) const;
void setToUnknownCommand() override;
size_t getMinimumMessageSize() const;
/**
* A command message can be rejected and needs to offer a function
* to set a rejected reply
* @param reason
* @param initialCommand
*/
void setReplyRejected(ReturnValue_t reason,
Command_t initialCommand) override;
/**
* Corrensonding getter function.
* @param initialCommand
* @return
*/
ReturnValue_t getReplyRejectedReason(
Command_t* initialCommand = nullptr) const override;
virtual void clear() override;
void clearCommandMessage();
/**
* Extract message ID, which is the first byte of the command ID for the
* default implementation.
* @return
*/
virtual uint8_t getMessageType() const override;
/** MessageQueueMessageIF functions used for minimum size check. */
size_t getMinimumMessageSize() const override;
};
#endif /* COMMANDMESSAGE_H_ */
#endif /* FSFW_IPC_COMMANDMESSAGE_H_ */

View File

@ -0,0 +1,45 @@
#include "../ipc/CommandMessageCleaner.h"
#include "../devicehandlers/DeviceHandlerMessage.h"
#include "../health/HealthMessage.h"
#include "../memory/MemoryMessage.h"
#include "../modes/ModeMessage.h"
#include "../monitoring/MonitoringMessage.h"
#include "../subsystem/modes/ModeSequenceMessage.h"
#include "../tmstorage/TmStoreMessage.h"
#include "../parameters/ParameterMessage.h"
void CommandMessageCleaner::clearCommandMessage(CommandMessage* message) {
switch(message->getMessageType()){
case messagetypes::MODE_COMMAND:
ModeMessage::clear(message);
break;
case messagetypes::HEALTH_COMMAND:
HealthMessage::clear(message);
break;
case messagetypes::MODE_SEQUENCE:
ModeSequenceMessage::clear(message);
break;
case messagetypes::ACTION:
ActionMessage::clear(message);
break;
case messagetypes::DEVICE_HANDLER_COMMAND:
DeviceHandlerMessage::clear(message);
break;
case messagetypes::MEMORY:
MemoryMessage::clear(message);
break;
case messagetypes::MONITORING:
MonitoringMessage::clear(message);
break;
case messagetypes::TM_STORE:
TmStoreMessage::clear(message);
break;
case messagetypes::PARAMETER:
ParameterMessage::clear(message);
break;
default:
messagetypes::clearMissionMessage(message);
break;
}
}

View File

@ -0,0 +1,16 @@
#ifndef FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_
#define FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_
#include "../ipc/CommandMessage.h"
namespace messagetypes {
// Implemented in config.
void clearMissionMessage(CommandMessage* message);
}
class CommandMessageCleaner {
public:
static void clearCommandMessage(CommandMessage* message);
};
#endif /* FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_ */

73
ipc/CommandMessageIF.h Normal file
View File

@ -0,0 +1,73 @@
#ifndef FSFW_IPC_COMMANDMESSAGEIF_H_
#define FSFW_IPC_COMMANDMESSAGEIF_H_
#include "MessageQueueMessageIF.h"
#include "FwMessageTypes.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#define MAKE_COMMAND_ID( number ) ((MESSAGE_ID << 8) + (number))
typedef uint16_t Command_t;
class CommandMessageIF {
public:
/**
* Header consists of sender ID and command ID.
*/
static constexpr size_t HEADER_SIZE = MessageQueueMessageIF::HEADER_SIZE +
sizeof(Command_t);
/**
* This minimum size is derived from the interface requirement to be able
* to set a rejected reply, which contains a returnvalue and the initial
* command.
*/
static constexpr size_t MINIMUM_COMMAND_MESSAGE_SIZE =
CommandMessageIF::HEADER_SIZE + sizeof(ReturnValue_t) +
sizeof(Command_t);
static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_MESSAGE;
static const ReturnValue_t UNKNOWN_COMMAND = MAKE_RETURN_CODE(0x01);
static const uint8_t MESSAGE_ID = messagetypes::COMMAND;
//! Used internally, shall be ignored
static const Command_t CMD_NONE = MAKE_COMMAND_ID( 0 );
static const Command_t REPLY_COMMAND_OK = MAKE_COMMAND_ID( 1 );
//! Reply indicating that the current command was rejected,
//! par1 should contain the error code
static const Command_t REPLY_REJECTED = MAKE_COMMAND_ID( 2 );
virtual ~CommandMessageIF() {};
/**
* A command message shall have a uint16_t command ID field.
* @return
*/
virtual Command_t getCommand() const = 0;
/**
* A command message shall have a uint8_t message type ID field.
* @return
*/
virtual uint8_t getMessageType() const = 0;
/**
* A command message can be rejected and needs to offer a function
* to set a rejected reply
* @param reason
* @param initialCommand
*/
virtual void setReplyRejected(ReturnValue_t reason,
Command_t initialCommand) = 0;
/**
* Corrensonding getter function.
* @param initialCommand
* @return
*/
virtual ReturnValue_t getReplyRejectedReason(
Command_t* initialCommand = nullptr) const = 0;
virtual void setToUnknownCommand() = 0;
virtual void clear() = 0;
};
#endif /* FSFW_IPC_COMMANDMESSAGEIF_H_ */

View File

@ -1,15 +1,15 @@
#ifndef FRAMEWORK_IPC_MESSAGEQUEUEIF_H_
#define FRAMEWORK_IPC_MESSAGEQUEUEIF_H_
#ifndef FSFW_IPC_MESSAGEQUEUEIF_H_
#define FSFW_IPC_MESSAGEQUEUEIF_H_
// COULDDO: We could support blocking calls
#include "messageQueueDefinitions.h"
#include "MessageQueueMessage.h"
#include "MessageQueueSenderIF.h"
#include "../returnvalues/HasReturnvaluesIF.h"
class MessageQueueIF {
public:
static const MessageQueueId_t NO_QUEUE = MessageQueueSenderIF::NO_QUEUE; //!< Ugly hack.
static const MessageQueueId_t NO_QUEUE = 0;
static const uint8_t INTERFACE_ID = CLASS_ID::MESSAGE_QUEUE_IF;
/**

View File

@ -1,13 +1,27 @@
#include "MessageQueueMessage.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include <string.h>
#include "../globalfunctions/arrayprinter.h"
#include <cstring>
MessageQueueMessage::MessageQueueMessage() :
messageSize(this->HEADER_SIZE) {
messageSize(getMinimumMessageSize()) {
memset(this->internalBuffer, 0, sizeof(this->internalBuffer));
}
MessageQueueMessage::MessageQueueMessage(uint8_t* data, size_t size) :
messageSize(this->HEADER_SIZE + size) {
if (size <= this->MAX_DATA_SIZE) {
memcpy(this->getData(), data, size);
this->messageSize = this->HEADER_SIZE + size;
}
else {
sif::warning << "MessageQueueMessage: Passed size larger than maximum"
"allowed size! Setting content to 0" << std::endl;
memset(this->internalBuffer, 0, sizeof(this->internalBuffer));
this->messageSize = this->HEADER_SIZE;
}
}
MessageQueueMessage::~MessageQueueMessage() {
}
@ -37,29 +51,34 @@ void MessageQueueMessage::setSender(MessageQueueId_t setId) {
memcpy(this->internalBuffer, &setId, sizeof(MessageQueueId_t));
}
MessageQueueMessage::MessageQueueMessage(uint8_t* data, uint32_t size) :
messageSize(this->HEADER_SIZE + size) {
if (size <= this->MAX_DATA_SIZE) {
memcpy(this->getData(), data, size);
} else {
memset(this->internalBuffer, 0, sizeof(this->internalBuffer));
this->messageSize = this->HEADER_SIZE;
void MessageQueueMessage::print(bool printWholeMessage) {
sif::debug << "MessageQueueMessage content: " << std::endl;
if(printWholeMessage) {
arrayprinter::print(getData(), getMaximumMessageSize());
}
else {
arrayprinter::print(getData(), getMessageSize());
}
size_t MessageQueueMessage::getMinimumMessageSize() {
return this->HEADER_SIZE;
}
void MessageQueueMessage::print() {
sif::debug << "MessageQueueMessage has size: " << this->messageSize << std::hex
<< std::endl;
for (uint8_t count = 0; count < this->messageSize; count++) {
sif::debug << (uint32_t) this->internalBuffer[count] << ":";
}
sif::debug << std::dec << std::endl;
}
void MessageQueueMessage::clear() {
memset(this->getBuffer(), 0, this->MAX_MESSAGE_SIZE);
}
size_t MessageQueueMessage::getMessageSize() const {
return this->messageSize;
}
void MessageQueueMessage::setMessageSize(size_t messageSize) {
this->messageSize = messageSize;
}
size_t MessageQueueMessage::getMinimumMessageSize() const {
return this->MIN_MESSAGE_SIZE;
}
size_t MessageQueueMessage::getMaximumMessageSize() const {
return this->MAX_MESSAGE_SIZE;
}

View File

@ -1,118 +1,149 @@
#ifndef MESSAGEQUEUEMESSAGE_H_
#define MESSAGEQUEUEMESSAGE_H_
#ifndef FSFW_IPC_MESSAGEQUEUEMESSAGE_H_
#define FSFW_IPC_MESSAGEQUEUEMESSAGE_H_
#include "MessageQueueSenderIF.h"
#include <stddef.h>
#include "../ipc/MessageQueueMessageIF.h"
#include <cstddef>
/**
* \brief This class is the representation and data organizer for interprocess messages.
* @brief This class is the representation and data organizer
* for interprocess messages.
* @details
* To facilitate and standardize interprocess communication, this class was
* created to handle a lightweight "interprocess message protocol".
*
* \details To facilitate and standardize interprocess communication, this class was created
* to handle a lightweight "interprocess message protocol". It adds a header with the
* sender's queue id to every sent message and defines the maximum total message size.
* Specialized messages, such as device commanding messages, can be created by inheriting
* from this class and filling the buffer provided by getData with additional content.
* If larger amounts of data must be sent between processes, the data shall be stored in
* the IPC Store object and only the storage id is passed in a queue message.
* The class is used both to generate and send messages and to receive messages from
* other tasks.
* \ingroup message_queue
* It adds a header with the sender's queue id to every sent message and
* defines the maximum total message size. Specialized messages, such as
* device commanding messages, can be created by inheriting from this class
* and filling the buffer provided by getData with additional content.
*
* If larger amounts of data must be sent between processes, the data shall
* be stored in the IPC Store object and only the storage id is passed in a
* queue message.The class is used both to generate and send messages and to
* receive messages from other tasks.
* @ingroup message_queue
*/
class MessageQueueMessage {
class MessageQueueMessage: public MessageQueueMessageIF {
public:
/**
* \brief This constant defines the maximum size of the data content, excluding the header.
* \details It may be changed if necessary, but in general should be kept as small as possible.
* @brief The class is initialized empty with this constructor.
* @details
* The messageSize attribute is set to the header's size and the whole
* content is set to zero.
*/
MessageQueueMessage();
/**
* @brief With this constructor the class is initialized with
* the given content.
* @details
* If the passed message size fits into the buffer, the passed data is
* copied to the internal buffer and the messageSize information is set.
* Otherwise, messageSize is set to the header's size and the whole
* content is set to zero.
* @param data The data to be put in the message.
* @param size Size of the data to be copied. Must be smaller than
* MAX_MESSAGE_SIZE and larger than MIN_MESSAGE_SIZE.
*/
MessageQueueMessage(uint8_t* data, size_t size);
/**
* @brief As no memory is allocated in this class,
* the destructor is empty.
*/
virtual ~MessageQueueMessage();
/**
* @brief The size information of each message is stored in
* this attribute.
* @details
* It is public to simplify usage and to allow for passing the size
* address as a pointer. Care must be taken when inheriting from this class,
* as every child class is responsible for managing the size information by
* itself. When using the class to receive a message, the size information
* is updated automatically.
*
* Please note that the minimum size is limited by the size of the header
* while the maximum size is limited by the maximum allowed message size.
*/
size_t messageSize;
/**
* @brief This constant defines the maximum size of the data content,
* excluding the header.
* @details
* It may be changed if necessary, but in general should be kept
* as small as possible.
*/
static const size_t MAX_DATA_SIZE = 24;
/**
* \brief This constants defines the size of the header, which is added to every message.
* @brief This constant defines the maximum total size in bytes
* of a sent message.
* @details
* It is the sum of the maximum data and the header size. Be aware that
* this constant is used to define the buffer sizes for every message
* queue in the system. So, a change here may have significant impact on
* the required resources.
*/
static const size_t HEADER_SIZE = sizeof(MessageQueueId_t);
static constexpr size_t MAX_MESSAGE_SIZE = MAX_DATA_SIZE + HEADER_SIZE;
/**
* \brief This constant defines the maximum total size in bytes of a sent message.
* \details It is the sum of the maximum data and the header size. Be aware that this constant
* is used to define the buffer sizes for every message queue in the system. So, a change
* here may have significant impact on the required resources.
* @brief Defines the minimum size of a message where only the
* header is included
*/
static const size_t MAX_MESSAGE_SIZE = MAX_DATA_SIZE + HEADER_SIZE;
static constexpr size_t MIN_MESSAGE_SIZE = HEADER_SIZE;
private:
/**
* \brief This is the internal buffer that contains the actual message data.
* @brief This is the internal buffer that contains the
* actual message data.
*/
uint8_t internalBuffer[MAX_MESSAGE_SIZE];
public:
/**
* \brief The size information of each message is stored in this attribute.
* \details It is public to simplify usage and to allow for passing the variable's address as a
* pointer. Care must be taken when inheriting from this class, as every child class is
* responsible for managing the size information by itself. When using the class to
* receive a message, the size information is updated automatically.
* @brief This method is used to get the complete data of the message.
*/
size_t messageSize;
const uint8_t* getBuffer() const override;
/**
* \brief The class is initialized empty with this constructor.
* \details The messageSize attribute is set to the header's size and the whole content is set to
* zero.
* @brief This method is used to get the complete data of the message.
*/
MessageQueueMessage();
uint8_t* getBuffer() override;
/**
* \brief With this constructor the class is initialized with the given content.
* \details If the passed message size fits into the buffer, the passed data is copied to the
* internal buffer and the messageSize information is set. Otherwise, messageSize
* is set to the header's size and the whole content is set to zero.
* \param data The data to be put in the message.
* \param size Size of the data to be copied. Must be smaller than MAX_MESSAGE_SIZE.
* @brief This method is used to fetch the data content of the message.
* @details
* It shall be used by child classes to add data at the right position.
*/
MessageQueueMessage(uint8_t* data, uint32_t size);
const uint8_t* getData() const override;
/**
* \brief As no memory is allocated in this class, the destructor is empty.
* @brief This method is used to fetch the data content of the message.
* @details
* It shall be used by child classes to add data at the right position.
*/
virtual ~MessageQueueMessage();
uint8_t* getData() override;
/**
* \brief This method is used to get the complete data of the message.
* @brief This method is used to extract the sender's message
* queue id information from a received message.
*/
const uint8_t* getBuffer() const;
MessageQueueId_t getSender() const override;
/**
* \brief This method is used to get the complete data of the message.
* @brief With this method, the whole content
* and the message size is set to zero.
*/
uint8_t* getBuffer();
void clear() override;
/**
* \brief This method is used to fetch the data content of the message.
* \details It shall be used by child classes to add data at the right position.
* @brief This method is used to set the sender's message queue id
* information prior to ing the message.
* @param setId
* The message queue id that identifies the sending message queue.
*/
const uint8_t* getData() const;
void setSender(MessageQueueId_t setId) override;
virtual size_t getMessageSize() const override;
virtual void setMessageSize(size_t messageSize) override;
virtual size_t getMinimumMessageSize() const override;
virtual size_t getMaximumMessageSize() const override;
/**
* \brief This method is used to fetch the data content of the message.
* \details It shall be used by child classes to add data at the right position.
* @brief This is a debug method that prints the content.
*/
uint8_t* getData();
/**
* \brief This method is used to extract the sender's message queue id information from a
* received message.
*/
MessageQueueId_t getSender() const;
/**
* \brief With this method, the whole content and the message size is set to zero.
*/
void clear();
/**
* \brief This is a debug method that prints the content (till messageSize) to the debug output.
*/
void print();
/**
* \brief This method is used to set the sender's message queue id information prior to
* sending the message.
* \param setId The message queue id that identifies the sending message queue.
*/
void setSender(MessageQueueId_t setId);
/**
* \brief This helper function is used by the MessageQueue class to check the size of an
* incoming message.
* \details The method must be overwritten by child classes if size checks shall be more strict.
* @return The default implementation returns HEADER_SIZE.
*/
virtual size_t getMinimumMessageSize();
void print(bool printWholeMessage);
};
#endif /* MESSAGEQUEUEMESSAGE_H_ */
#endif /* FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ */

View File

@ -0,0 +1,80 @@
#ifndef FRAMEWORK_IPC_MESSAGEQUEUEMESSAGEIF_H_
#define FRAMEWORK_IPC_MESSAGEQUEUEMESSAGEIF_H_
#include <fsfw/ipc/messageQueueDefinitions.h>
#include <cstddef>
#include <cstdint>
class MessageQueueMessageIF {
public:
/**
* @brief This constants defines the size of the header,
* which is added to every message.
*/
static const size_t HEADER_SIZE = sizeof(MessageQueueId_t);
virtual ~MessageQueueMessageIF() {};
/**
* @brief With this method, the whole content and the message
* size is set to zero.
* @details
* Implementations should also take care to clear data which is stored
* indirectly (e.g. storage data).
*/
virtual void clear() = 0;
/**
* @brief Get read-only pointer to the complete data of the message.
* @return
*/
virtual const uint8_t* getBuffer() const = 0;
/**
* @brief This method is used to get the complete data of the message.
*/
virtual uint8_t* getBuffer() = 0;
/**
* @brief This method is used to set the sender's message queue id
* information prior to sending the message.
* @param setId
* The message queue id that identifies the sending message queue.
*/
virtual void setSender(MessageQueueId_t setId) = 0;
/**
* @brief This method is used to extract the sender's message queue id
* information from a received message.
*/
virtual MessageQueueId_t getSender() const = 0;
/**
* @brief This method is used to fetch the data content of the message.
* @details
* It shall be used by child classes to add data at the right position.
*/
virtual const uint8_t* getData() const = 0;
/**
* @brief This method is used to fetch the data content of the message.
* @details
* It shall be used by child classes to add data at the right position.
*/
virtual uint8_t* getData() = 0;
/**
* Get constant message size of current message implementation.
* @return
*/
virtual size_t getMessageSize() const = 0;
virtual void setMessageSize(size_t messageSize) = 0;
virtual size_t getMinimumMessageSize() const = 0;
virtual size_t getMaximumMessageSize() const = 0;
};
#endif /* FRAMEWORK_IPC_MESSAGEQUEUEMESSAGEIF_H_ */

View File

@ -1,37 +1,26 @@
#ifndef FRAMEWORK_IPC_MESSAGEQUEUESENDERIF_H_
#define FRAMEWORK_IPC_MESSAGEQUEUESENDERIF_H_
#ifndef FSFW_IPC_MESSAGEQUEUESENDERIF_H_
#define FSFW_IPC_MESSAGEQUEUESENDERIF_H_
#include "../ipc/MessageQueueIF.h"
#include "../ipc/MessageQueueMessageIF.h"
#include "../objectmanager/ObjectManagerIF.h"
class MessageQueueMessage;
//TODO: Actually, the definition of this ID to be a uint32_t is not ideal and breaks layering.
//However, it is difficult to keep layering, as the ID is stored in many places and sent around in
//MessageQueueMessage.
//Ideally, one would use the (current) object_id_t only, however, doing a lookup of queueIDs for every
//call does not sound ideal.
//In a first step, I'll circumvent the issue by not touching it, maybe in a second step.
//This also influences Interface design (getCommandQueue) and some other issues..
typedef uint32_t MessageQueueId_t;
class MessageQueueSenderIF {
public:
static const MessageQueueId_t NO_QUEUE = 0;
virtual ~MessageQueueSenderIF() {}
/**
* Allows sending messages without actually "owing" a message queue.
* Allows sending messages without actually "owning" a message queue.
* Not sure whether this is actually a good idea.
* Must be implemented by a subclass.
*/
static ReturnValue_t sendMessage(MessageQueueId_t sendTo,
MessageQueueMessage* message, MessageQueueId_t sentFrom =
MessageQueueSenderIF::NO_QUEUE, bool ignoreFault=false);
MessageQueueMessage* message,
MessageQueueId_t sentFrom = MessageQueueIF::NO_QUEUE,
bool ignoreFault = false);
private:
MessageQueueSenderIF() {}
};
#endif /* FRAMEWORK_IPC_MESSAGEQUEUESENDERIF_H_ */
#endif /* FSFW_IPC_MESSAGEQUEUESENDERIF_H_ */

View File

@ -0,0 +1,18 @@
#ifndef FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_
#define FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_
#include <cstdint>
/*
* TODO: Actually, the definition of this ID to be a uint32_t is not ideal and
* breaks layering. However, it is difficult to keep layering, as the ID is
* stored in many places and sent around in MessageQueueMessage.
* Ideally, one would use the (current) object_id_t only, however, doing a
* lookup of queueIDs for every call does not sound ideal.
* In a first step, I'll circumvent the issue by not touching it,
* maybe in a second step. This also influences Interface design
* (getCommandQueue) and some other issues..
*/
using MessageQueueId_t = uint32_t;
#endif /* FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ */

View File

@ -1,12 +1,5 @@
/**
* @file AcceptsMemoryMessagesIF.h
* @brief This file defines the AcceptsMemoryMessagesIF class.
* @date 11.07.2013
* @author baetz
*/
#ifndef ACCEPTSMEMORYMESSAGESIF_H_
#define ACCEPTSMEMORYMESSAGESIF_H_
#ifndef FSFW_MEMORY_ACCEPTSMEMORYMESSAGESIF_H_
#define FSFW_MEMORY_ACCEPTSMEMORYMESSAGESIF_H_
#include "HasMemoryIF.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 "MemoryMessage.h"
#include "../globalfunctions/CRC.h"
#include "../objectmanager/ObjectManagerIF.h"
#include "../serialize/EndianConverter.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
MemoryHelper::MemoryHelper(HasMemoryIF* workOnThis, MessageQueueIF* useThisQueue) :
workOnThis(workOnThis), queueToUse(useThisQueue), ipcStore(NULL), ipcAddress(), lastCommand(
CommandMessage::CMD_NONE), lastSender(0), reservedSpaceInIPC(
NULL), busy(false) {
MemoryHelper::MemoryHelper(HasMemoryIF* workOnThis,
MessageQueueIF* useThisQueue):
workOnThis(workOnThis), queueToUse(useThisQueue), ipcAddress(),
lastCommand(CommandMessage::CMD_NONE), busy(false) {
}
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,
const uint8_t* dataToCopy, const uint32_t size, uint8_t* copyHere) {
const uint8_t* dataToCopy, const size_t size, uint8_t* copyHere) {
busy = false;
switch (errorCode) {
case HasMemoryIF::DO_IT_MYSELF:
@ -73,7 +65,7 @@ void MemoryHelper::completeLoad(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;
CommandMessage reply;
MemoryMessage::setMemoryReplyFailed(&reply, errorCode, lastCommand);
@ -125,12 +117,12 @@ void MemoryHelper::completeDump(ReturnValue_t errorCode,
break;
}
if (queueToUse->sendMessage(lastSender, &reply) != RETURN_OK) {
reply.clearCommandMessage();
reply.clear();
}
}
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){
return;
}
@ -185,11 +177,18 @@ void MemoryHelper::handleMemoryCheckOrDump(CommandMessage* message) {
}
ReturnValue_t MemoryHelper::initialize(MessageQueueIF* queueToUse_) {
if(queueToUse_!=NULL){
this->queueToUse = queueToUse_;
}else{
return MessageQueueIF::NO_QUEUE;
if(queueToUse_ == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED;
}
this->queueToUse = queueToUse_;
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_
#define MEMORYHELPER_H_
#include "../ipc/CommandMessage.h"
#ifndef FSFW_MEMORY_MEMORYHELPER_H_
#define FSFW_MEMORY_MEMORYHELPER_H_
#include "AcceptsMemoryMessagesIF.h"
#include "../ipc/CommandMessage.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../storagemanager/StorageManagerIF.h"
#include "../ipc/MessageQueueIF.h"
/**
* @brief TODO: documentation.
*/
class MemoryHelper : public HasReturnvaluesIF {
public:
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_SIZE = MAKE_RETURN_CODE(0xE2);
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:
HasMemoryIF* workOnThis;
MessageQueueIF* queueToUse;
StorageManagerIF* ipcStore;
StorageManagerIF* ipcStore = nullptr;
store_address_t ipcAddress;
Command_t lastCommand;
MessageQueueId_t lastSender;
uint8_t* reservedSpaceInIPC;
MessageQueueId_t lastSender = MessageQueueIF::NO_QUEUE;
uint8_t* reservedSpaceInIPC = nullptr;
bool busy;
void handleMemoryLoad(CommandMessage* message);
void handleMemoryCheckOrDump(CommandMessage* message);
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 "../objectmanager/ObjectManagerIF.h"
MemoryMessage::MemoryMessage() {
}
uint32_t MemoryMessage::getAddress(const CommandMessage* message) {
return message->getParameter();
@ -17,26 +16,24 @@ uint32_t MemoryMessage::getLength(const CommandMessage* message) {
return message->getParameter2();
}
ReturnValue_t MemoryMessage::setMemoryDumpCommand(CommandMessage* message,
void MemoryMessage::setMemoryDumpCommand(CommandMessage* message,
uint32_t address, uint32_t length) {
message->setCommand(CMD_MEMORY_DUMP);
message->setParameter( address );
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->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) {
message->setCommand(CMD_MEMORY_LOAD);
message->setParameter( address );
message->setParameter2( storageID.raw );
return HasReturnvaluesIF::RETURN_OK;
}
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) {
message->setCommand(CMD_MEMORY_CHECK);
message->setParameter( address );
message->setParameter2( length );
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t MemoryMessage::setMemoryCheckReply(CommandMessage* message,
void MemoryMessage::setMemoryCheckReply(CommandMessage* message,
uint16_t crc) {
message->setCommand(REPLY_MEMORY_CHECK);
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);
};
@ -96,18 +92,16 @@ Command_t MemoryMessage::getInitialCommand(const CommandMessage* message) {
return message->getParameter2();
}
ReturnValue_t MemoryMessage::setMemoryReplyFailed(CommandMessage* message,
void MemoryMessage::setMemoryReplyFailed(CommandMessage* message,
ReturnValue_t errorCode, Command_t initialCommand) {
message->setCommand(REPLY_MEMORY_FAILED);
message->setParameter(errorCode);
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->setParameter(0);
message->setParameter2(0);
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -1,14 +1,15 @@
#ifndef MEMORYMESSAGE_H_
#define MEMORYMESSAGE_H_
#ifndef FSFW_MEMORY_MEMORYMESSAGE_H_
#define FSFW_MEMORY_MEMORYMESSAGE_H_
#include "../ipc/CommandMessage.h"
#include "../storagemanager/StorageManagerIF.h"
class MemoryMessage {
private:
MemoryMessage(); //A private ctor inhibits instantiation
public:
// Instantiation forbidden.
MemoryMessage() = delete;
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_DUMP = MAKE_COMMAND_ID( 0x02 );
@ -22,18 +23,26 @@ public:
static store_address_t getStoreID(const CommandMessage* message);
static uint32_t getLength( const CommandMessage* message );
static ReturnValue_t getErrorCode(const CommandMessage* message);
static ReturnValue_t setMemoryDumpCommand( CommandMessage* message, uint32_t address, uint32_t length );
static ReturnValue_t setMemoryDumpReply( CommandMessage* message, store_address_t storageID );
static ReturnValue_t setMemoryLoadCommand( CommandMessage* message, uint32_t address, store_address_t storageID );
static ReturnValue_t setMemoryCheckCommand( CommandMessage* message, uint32_t address, uint32_t length );
static ReturnValue_t setMemoryCheckReply( CommandMessage* message, uint16_t crc );
static ReturnValue_t setMemoryReplyFailed( CommandMessage* message, ReturnValue_t errorCode, Command_t initialCommand );
static ReturnValue_t setMemoryCopyEnd( CommandMessage* message);
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 setMemoryDumpCommand(CommandMessage* message,
uint32_t address, uint32_t length );
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 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 @@
/**
* @file HasModesIF.h
* @brief This file defines the HasModesIF class.
* @date 20.06.2013
* @author baetz
*/
#ifndef FSFW_MODES_HASMODESIF_H_
#define FSFW_MODES_HASMODESIF_H_
#ifndef HASMODESIF_H_
#define HASMODESIF_H_
#include "../events/Event.h"
#include "ModeHelper.h"
#include "ModeMessage.h"
#include "../events/Event.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#include <stdint.h>
#include <cstdint>
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_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".
virtual ~HasModesIF() {
}
virtual ~HasModesIF() {}
virtual MessageQueueId_t getCommandQueue() const = 0;
virtual void getMode(Mode_t *mode, Submode_t *submode) = 0;
protected:
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) {
return HasReturnvaluesIF::RETURN_FAILED;
}
virtual void startTransition(Mode_t mode, Submode_t submode) {
}
virtual void setToExternalControl() {
}
virtual void announceMode(bool recursive) {
}
virtual void startTransition(Mode_t mode, Submode_t submode) {}
virtual void setToExternalControl() {}
virtual void announceMode(bool recursive) {}
};
#endif /* HASMODESIF_H_ */
#endif /*FSFW_MODES_HASMODESIF_H_ */

View File

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

View File

@ -1,7 +1,8 @@
#ifndef MODEHELPER_H_
#define MODEHELPER_H_
#ifndef FSFW_MODES_MODEHELPER_H_
#define FSFW_MODES_MODEHELPER_H_
#include "ModeMessage.h"
#include "../ipc/MessageQueueIF.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../timemanager/Countdown.h"
@ -9,7 +10,7 @@ class HasModesIF;
class ModeHelper {
public:
MessageQueueId_t theOneWhoCommandedAMode;
MessageQueueId_t theOneWhoCommandedAMode = MessageQueueIF::NO_QUEUE;
Mode_t commandedMode;
Submode_t commandedSubmode;
@ -19,14 +20,14 @@ public:
ReturnValue_t handleModeCommand(CommandMessage *message);
/**
*
* @param parentQueue the Queue id of the parent object. Set to 0 if no parent present
* @param parentQueue the Queue id of the parent object.
* Set to 0 if no parent present
*/
void setParentQueue(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);
@ -39,11 +40,14 @@ public:
void setForced(bool forced);
protected:
HasModesIF *owner;
MessageQueueId_t parentQueueId;
MessageQueueId_t parentQueueId = MessageQueueIF::NO_QUEUE;
Countdown countdown;
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();
}
ReturnValue_t ModeMessage::setModeMessage(CommandMessage* message, Command_t command,
Mode_t mode, Submode_t submode) {
void ModeMessage::setModeMessage(CommandMessage* message,
Command_t command, Mode_t mode, Submode_t submode) {
message->setCommand( command );
message->setParameter( mode );
message->setParameter2( submode );
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t ModeMessage::getCantReachModeReason(const CommandMessage* message) {
@ -24,7 +23,8 @@ void ModeMessage::clear(CommandMessage* message) {
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->setParameter(reason);
message->setParameter2(0);

View File

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

View File

@ -1,12 +1,5 @@
/**
* @file ObjectManager.h
* @brief This file contains the implementation of the ObjectManager class
* @date 18.09.2012
* @author Bastian Baetz
*/
#ifndef OBJECTMANAGER_H_
#define OBJECTMANAGER_H_
#ifndef FSFW_OBJECTMANAGER_OBJECTMANAGER_H_
#define FSFW_OBJECTMANAGER_OBJECTMANAGER_H_
#include "ObjectManagerIF.h"
#include "SystemObjectIF.h"
@ -22,14 +15,15 @@
* most of the system initialization.
* As the system is static after initialization, no new objects are
* created or inserted into the list after startup.
* \ingroup system_objects
* @ingroup system_objects
* @author Bastian Baetz
*/
class ObjectManager : public ObjectManagerIF {
private:
//comparison?
/**
* \brief This is the map of all initialized objects in the manager.
* \details Objects in the List must inherit the SystemObjectIF.
* @brief This is the map of all initialized objects in the manager.
* @details Objects in the List must inherit the SystemObjectIF.
*/
std::map<object_id_t, SystemObjectIF*> objectList;
protected:
@ -54,7 +48,8 @@ public:
/**
* @brief In the class's destructor, all objects in the list are deleted.
*/
//SHOULDDO: If, for some reason, deleting an ObjectManager instance is required, check if this works.
// SHOULDDO: If, for some reason, deleting an ObjectManager instance is
// required, check if this works.
virtual ~ObjectManager( void );
ReturnValue_t insert( object_id_t id, SystemObjectIF* object );
ReturnValue_t remove( object_id_t id );
@ -64,4 +59,4 @@ public:
#endif /* OBJECTMANAGER_H_ */
#endif /* FSFW_OBJECTMANAGER_OBJECTMANAGER_H_ */

View File

@ -1,5 +1,5 @@
#ifndef FRAMEWORK_OBJECTMANAGER_OBJECTMANAGERIF_H_
#define FRAMEWORK_OBJECTMANAGER_OBJECTMANAGERIF_H_
#ifndef FSFW_OBJECTMANAGER_OBJECTMANAGERIF_H_
#define FSFW_OBJECTMANAGER_OBJECTMANAGERIF_H_
#include "frameworkObjects.h"
#include "SystemObjectIF.h"
@ -21,7 +21,6 @@ public:
static constexpr uint8_t INTERFACE_ID = CLASS_ID::OBJECT_MANAGER_IF;
static constexpr ReturnValue_t INSERTION_FAILED = MAKE_RETURN_CODE( 1 );
static constexpr ReturnValue_t NOT_FOUND = MAKE_RETURN_CODE( 2 );
static constexpr ReturnValue_t CHILD_INIT_FAILED = MAKE_RETURN_CODE( 3 ); //!< Can be used if the initialization of a SystemObject failed.
static constexpr ReturnValue_t INTERNAL_ERR_REPORTER_UNINIT = MAKE_RETURN_CODE( 4 );
@ -80,6 +79,7 @@ public:
/**
* @brief This is the forward declaration of the global objectManager instance.
*/
// SHOULDDO: maybe put this in the glob namespace to explicitely mark it global?
extern ObjectManagerIF *objectManager;
/*Documentation can be found in the class method declaration above.*/

View File

@ -1,6 +1,6 @@
#include "../events/EventManagerIF.h"
#include "ObjectManager.h"
#include "SystemObject.h"
#include "../events/EventManagerIF.h"
SystemObject::SystemObject(object_id_t setObjectId, bool doRegister) :
objectId(setObjectId), registered(doRegister) {

View File

@ -1,16 +1,9 @@
/**
* @file SystemObject.h
* @brief This file contains the definition of the SystemObject class.
* @date 07.11.2012
* @author Ulrich Mohr
*/
#ifndef SYSTEMOBJECT_H_
#define SYSTEMOBJECT_H_
#ifndef FSFW_OBJECTMANAGER_SYSTEMOBJECT_H_
#define FSFW_OBJECTMANAGER_SYSTEMOBJECT_H_
#include "SystemObjectIF.h"
#include "../events/Event.h"
#include "../events/EventReportingProxyIF.h"
#include "SystemObjectIF.h"
#include "../timemanager/Clock.h"
/**
@ -20,7 +13,8 @@
* class that is announced to ObjectManager. It automatically includes
* itself (and therefore the inheriting class) in the object manager's
* list.
* \ingroup system_objects
* @author Ulrich Mohr
* @ingroup system_objects
*/
class SystemObject: public SystemObjectIF {
private:
@ -37,25 +31,28 @@ public:
* @param parameter1
* @param parameter2
*/
virtual void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0);
virtual void triggerEvent(Event event, uint32_t parameter1 = 0,
uint32_t parameter2 = 0);
/**
* @brief The class's constructor.
* @details In the constructor, the object id is set and the class is
* inserted in the object manager.
* @param setObjectId The id the object shall have.
* @param doRegister Determines if the object is registered in the global object manager.
* @param doRegister Determines if the object is registered in
* the global object manager.
*/
SystemObject(object_id_t setObjectId, bool doRegister = true);
/**
* @brief On destruction, the object removes itself from the list.
*/
virtual ~SystemObject();
object_id_t getObjectId() const;
virtual ReturnValue_t initialize();
object_id_t getObjectId() const override;
virtual ReturnValue_t initialize() override;
virtual ReturnValue_t checkObjectConnections();
virtual void forwardEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) const;
virtual void forwardEvent(Event event, uint32_t parameter1 = 0,
uint32_t parameter2 = 0) const;
};
#endif /* SYSTEMOBJECT_H_ */
#endif /* FSFW_OBJECTMANAGER_SYSTEMOBJECT_H_ */

View File

@ -1,26 +1,19 @@
/**
* @file SystemObjectIF.h
* @brief This file contains the definition of the SystemObjectIF interface.
* @date 18.09.2012
* @author Bastian Baetz
*/
#ifndef SYSTEMOBJECTIF_H_
#define SYSTEMOBJECTIF_H_
#ifndef FSFW_OBJECTMANAGER_SYSTEMOBJECTIF_H_
#define FSFW_OBJECTMANAGER_SYSTEMOBJECTIF_H_
#include "../events/EventReportingProxyIF.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#include <stdint.h>
#include <cstdint>
/**
* \defgroup system_objects Software System Object Management
* The classes to create System Objects and classes to manage these are contained in this group.
* System Objects are software elements that can be controlled externally. They all have a unique
* object identifier.
* @defgroup system_objects Software System Object Management
* The classes to create System Objects and classes to manage these are
* contained in this group. System Objects are software elements that can be
* controlled externally. They all have a unique object identifier.
*/
/**
* This is the typedef for object identifiers.
* \ingroup system_objects
* @ingroup system_objects
*/
typedef uint32_t object_id_t;
@ -29,7 +22,8 @@ typedef uint32_t object_id_t;
* list.
* It does not provide any method definitions, still it is required to
* perform a type check with dynamic_cast.
* \ingroup system_objects
* @author Bastian Baetz
* @ingroup system_objects
*/
class SystemObjectIF : public EventReportingProxyIF {
public:
@ -41,24 +35,28 @@ public:
/**
* The empty virtual destructor as required for C++ interfaces.
*/
virtual ~SystemObjectIF() {
}
virtual ~SystemObjectIF() {}
/**
* Initializes all inter-object dependencies.
* This is necessary to avoid circular dependencies of not-fully
* initialized objects on start up.
* @return - \c RETURN_OK in case the initialization was successful
* - \c RETURN_FAILED otherwise
* @brief Initializes the object.
* There are initialization steps which can also be done in the constructor.
* However, there is no clean way to get a returnvalue from a constructor.
* Furthermore some components require other system object to be created
* which might not have been built yet.
* Therefore, a two-step initialization resolves this problem and prevents
* circular dependencies of not-fully initialized objects on start up.
* @return - @c RETURN_OK in case the initialization was successful
* - @c RETURN_FAILED otherwise
*/
virtual ReturnValue_t initialize() = 0;
/**
* Checks, if all object-object interconnections are satisfying for operation.
* Some objects need certain other objects (or a certain number), to be registered as children.
* These checks can be done in this method.
* @return - \c RETURN_OK in case the check was successful
* - \c any other code otherwise
* @brief Checks if all object-object interconnections are satisfying
* for operation.
* Some objects need certain other objects (or a certain number), to be
* registered as children. These checks can be done in this method.
* @return - @c RETURN_OK in case the check was successful
* - @c any other code otherwise
*/
virtual ReturnValue_t checkObjectConnections() = 0;
};
#endif /* SYSTEMOBJECTIF_H_ */
#endif /* #ifndef FSFW_OBJECTMANAGER_SYSTEMOBJECTIF_H_ */

View File

@ -1,8 +1,17 @@
#ifndef FRAMEWORK_OBJECTMANAGER_FRAMEWORKOBJECTS_H_
#define FRAMEWORK_OBJECTMANAGER_FRAMEWORKOBJECTS_H_
#ifndef FSFW_OBJECTMANAGER_FRAMEWORKOBJECTS_H_
#define FSFW_OBJECTMANAGER_FRAMEWORKOBJECTS_H_
namespace objects {
enum framework_objects {
// Default verification reporter.
PUS_SERVICE_1_VERIFICATION = 0x53000001,
PUS_SERVICE_2_DEVICE_ACCESS = 0x53000002,
PUS_SERVICE_5_EVENT_REPORTING = 0x53000005,
PUS_SERVICE_8_FUNCTION_MGMT = 0x53000008,
PUS_SERVICE_9_TIME_MGMT = 0x53000009,
PUS_SERVICE_17_TEST = 0x53000017,
PUS_SERVICE_200_MODE_MGMT = 0x53000200,
//Generic IDs for IPC, modes, health, events
HEALTH_TABLE = 0x53010000,
// MODE_STORE = 0x53010100,
@ -12,10 +21,11 @@ enum framework_objects {
//IDs for PUS Packet Communication
TC_STORE = 0x534f0100,
TM_STORE = 0x534f0200,
NO_OBJECT = 0xFFFFFFFF
};
}
#endif /* FRAMEWORK_OBJECTMANAGER_FRAMEWORKOBJECTS_H_ */
#endif /* FSFW_OBJECTMANAGER_FRAMEWORKOBJECTS_H_ */

View File

@ -8,7 +8,7 @@ const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE;
FixedTimeslotTask::FixedTimeslotTask(TaskName name, TaskPriority setPriority,
TaskStackSize setStack, TaskPeriod overallPeriod,
void (*setDeadlineMissedFunc)()) :
started(false), handle(NULL), pst(overallPeriod * 1000) {
started(false), handle(nullptr), pst(overallPeriod * 1000) {
configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE);
xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle);
// All additional attributes are applied to the object.
@ -62,8 +62,10 @@ ReturnValue_t FixedTimeslotTask::startTask() {
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId,
uint32_t slotTimeMs, int8_t executionStep) {
if (objectManager->get<ExecutableObjectIF>(componentId) != nullptr) {
pst.addSlot(componentId, slotTimeMs, executionStep, this);
ExecutableObjectIF* handler =
objectManager->get<ExecutableObjectIF>(componentId);
if (handler != nullptr) {
pst.addSlot(componentId, slotTimeMs, executionStep, handler, this);
return HasReturnvaluesIF::RETURN_OK;
}
@ -85,6 +87,8 @@ void FixedTimeslotTask::taskFunctionality() {
// start time for the first entry.
auto slotListIter = pst.current;
pst.intializeSequenceAfterTaskCreation();
//The start time for the first entry is read.
uint32_t intervalMs = slotListIter->pollingTimeMs;
TickType_t interval = pdMS_TO_TICKS(intervalMs);
@ -143,10 +147,6 @@ void FixedTimeslotTask::checkMissedDeadline(const TickType_t xLastWakeTime,
}
void FixedTimeslotTask::handleMissedDeadline() {
#ifdef DEBUG
sif::warning << "FixedTimeslotTask: " << pcTaskGetName(NULL) <<
" missed deadline!\n" << std::flush;
#endif
if(deadlineMissedFunc != nullptr) {
this->deadlineMissedFunc();
}

View File

@ -1,12 +1,11 @@
#ifndef FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_
#define FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_
#ifndef FSFW_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_
#define FSFW_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_
#include "FreeRTOSTaskIF.h"
#include "../../devicehandlers/FixedSlotSequence.h"
#include "../../tasks/FixedSlotSequence.h"
#include "../../tasks/FixedTimeslotTaskIF.h"
#include "../../tasks/Typedef.h"
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
@ -99,4 +98,4 @@ protected:
void handleMissedDeadline();
};
#endif /* FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ */
#endif /* FSFW_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ */

View File

@ -1,5 +1,6 @@
#include "MessageQueue.h"
#include "../../objectmanager/ObjectManagerIF.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
@ -101,7 +102,8 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
reinterpret_cast<const void*>(message->getBuffer()), 0);
if (result != pdPASS) {
if (!ignoreFault) {
InternalErrorReporterIF* internalErrorReporter = objectManager->get<InternalErrorReporterIF>(
InternalErrorReporterIF* internalErrorReporter =
objectManager->get<InternalErrorReporterIF>(
objects::INTERNAL_ERROR_REPORTER);
if (internalErrorReporter != NULL) {
internalErrorReporter->queueMessageNotSent();

View File

@ -133,10 +133,6 @@ TaskHandle_t PeriodicTask::getTaskHandle() {
}
void PeriodicTask::handleMissedDeadline() {
#ifdef DEBUG
sif::warning << "PeriodicTask: " << pcTaskGetName(NULL) <<
" missed deadline!\n" << std::flush;
#endif
if(deadlineMissedFunc != nullptr) {
this->deadlineMissedFunc();
}

View File

@ -1,18 +1,21 @@
#include "../../ipc/MessageQueueSenderIF.h"
#include "../../ipc/QueueFactory.h"
#include "MessageQueue.h"
QueueFactory* QueueFactory::factoryInstance = NULL;
QueueFactory* QueueFactory::factoryInstance = nullptr;
ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo,
MessageQueueMessage* message, MessageQueueId_t sentFrom,bool ignoreFault) {
return MessageQueue::sendMessageFromMessageQueue(sendTo,message,sentFrom,ignoreFault);
MessageQueueMessage* message, MessageQueueId_t sentFrom,
bool ignoreFault) {
return MessageQueue::sendMessageFromMessageQueue(sendTo,message,
sentFrom,ignoreFault);
}
QueueFactory* QueueFactory::instance() {
if (factoryInstance == NULL) {
if (factoryInstance == nullptr) {
factoryInstance = new QueueFactory;
}
return factoryInstance;
@ -24,9 +27,9 @@ QueueFactory::QueueFactory() {
QueueFactory::~QueueFactory() {
}
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t message_depth,
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth,
size_t maxMessageSize) {
return new MessageQueue(message_depth, maxMessageSize);
return new MessageQueue(messageDepth, maxMessageSize);
}
void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) {

View File

@ -6,8 +6,8 @@
#include <linux/sysinfo.h>
#include <time.h>
#include <unistd.h>
#include <fstream>
//#include <fstream>
uint16_t Clock::leapSeconds = 0;
MutexIF* Clock::timeMutex = NULL;
@ -76,22 +76,23 @@ timeval Clock::getUptime() {
ReturnValue_t Clock::getUptime(timeval* uptime) {
//TODO This is not posix compatible and delivers only seconds precision
struct sysinfo sysInfo;
int result = sysinfo(&sysInfo);
if(result != 0){
return HasReturnvaluesIF::RETURN_FAILED;
}
uptime->tv_sec = sysInfo.uptime;
uptime->tv_usec = 0;
// is the OS not called Linux?
//Linux specific file read but more precise
// double uptimeSeconds;
// if(std::ifstream("/proc/uptime",std::ios::in) >> uptimeSeconds){
// uptime->tv_sec = uptimeSeconds;
// uptime->tv_usec = uptimeSeconds *(double) 1e6 - (uptime->tv_sec *1e6);
// }
double uptimeSeconds;
if(std::ifstream("/proc/uptime",std::ios::in) >> uptimeSeconds){
uptime->tv_sec = uptimeSeconds;
uptime->tv_usec = uptimeSeconds *(double) 1e6 - (uptime->tv_sec *1e6);
}
//TODO This is not posix compatible and delivers only seconds precision
// I suggest this is moved into another clock function which will
// deliver second precision later.
// struct sysinfo sysInfo;
// int result = sysinfo(&sysInfo);
// if(result != 0){
// return HasReturnvaluesIF::RETURN_FAILED;
// }
// return sysInfo.uptime;
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -1,5 +1,5 @@
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include "FixedTimeslotTask.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include <limits.h>
@ -39,13 +39,16 @@ uint32_t FixedTimeslotTask::getPeriodMs() const {
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId,
uint32_t slotTimeMs, int8_t executionStep) {
if (objectManager->get<ExecutableObjectIF>(componentId) != nullptr) {
pst.addSlot(componentId, slotTimeMs, executionStep, this);
ExecutableObjectIF* executableObject =
objectManager->get<ExecutableObjectIF>(componentId);
if (executableObject != nullptr) {
pst.addSlot(componentId, slotTimeMs, executionStep,
executableObject,this);
return HasReturnvaluesIF::RETURN_OK;
}
sif::error << "Component " << std::hex << componentId <<
" not found, not adding it to pst" << std::endl;
" not found, not adding it to pst" << std::dec << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
@ -58,6 +61,9 @@ void FixedTimeslotTask::taskFunctionality() {
if (!started) {
suspend();
}
pst.intializeSequenceAfterTaskCreation();
//The start time for the first entry is read.
uint64_t lastWakeTime = getCurrentMonotonicTimeMs();
uint64_t interval = pst.getIntervalToNextSlotMs();

View File

@ -1,9 +1,9 @@
#ifndef FRAMEWORK_OSAL_LINUX_FIXEDTIMESLOTTASK_H_
#define FRAMEWORK_OSAL_LINUX_FIXEDTIMESLOTTASK_H_
#ifndef FSFW_OSAL_LINUX_FIXEDTIMESLOTTASK_H_
#define FSFW_OSAL_LINUX_FIXEDTIMESLOTTASK_H_
#include "../../tasks/FixedTimeslotTaskIF.h"
#include "../../devicehandlers/FixedSlotSequence.h"
#include "PosixThread.h"
#include "../../tasks/FixedTimeslotTaskIF.h"
#include "../../tasks/FixedSlotSequence.h"
#include <pthread.h>
class FixedTimeslotTask: public FixedTimeslotTaskIF, public PosixThread {
@ -74,4 +74,4 @@ private:
bool started;
};
#endif /* FRAMEWORK_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ */
#endif /* FSFW_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ */

View File

@ -1,8 +1,8 @@
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include "MessageQueue.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include "../../objectmanager/ObjectManagerIF.h"
#include <fstream>
#include <fcntl.h> /* For O_* constants */
#include <sys/stat.h> /* For mode constants */
#include <cstring>

View File

@ -1,8 +1,14 @@
#include "../../ipc/QueueFactory.h"
#include "MessageQueue.h"
#include "../../ipc/messageQueueDefinitions.h"
#include "../../ipc/MessageQueueSenderIF.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include <mqueue.h>
#include <errno.h>
#include "MessageQueue.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include <cstring>
QueueFactory* QueueFactory::factoryInstance = nullptr;

View File

@ -107,13 +107,23 @@ ReturnValue_t CService200ModeCommanding::prepareWrongModeReply(
const CommandMessage *reply, object_id_t objectId) {
ModePacket wrongModeReply(objectId, ModeMessage::getMode(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(
const CommandMessage *reply, object_id_t objectId) {
CantReachModePacket cantReachModePacket(objectId,
ModeMessage::getCantReachModeReason(reply));
return sendTmPacket(Subservice::REPLY_CANT_REACH_MODE,
ReturnValue_t result = sendTmPacket(Subservice::REPLY_CANT_REACH_MODE,
&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;
}

41
pus/Service17Test.cpp Normal file
View File

@ -0,0 +1,41 @@
#include "Service17Test.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../objectmanager/SystemObject.h"
#include "../tmtcpacket/pus/TmPacketStored.h"
Service17Test::Service17Test(object_id_t objectId,
uint16_t apid, uint8_t serviceId):
PusServiceBase(objectId, apid, serviceId),
packetSubCounter(0) {
}
Service17Test::~Service17Test() {
}
ReturnValue_t Service17Test::handleRequest(uint8_t subservice) {
switch(subservice){
case Subservice::CONNECTION_TEST: {
TmPacketStored connectionPacket(apid, serviceId,
Subservice::CONNECTION_TEST_REPORT, packetSubCounter++);
connectionPacket.sendPacket(requestQueue->getDefaultDestination(),
requestQueue->getId());
return HasReturnvaluesIF::RETURN_OK;
}
case Subservice::EVENT_TRIGGER_TEST: {
TmPacketStored connectionPacket(apid, serviceId,
Subservice::CONNECTION_TEST_REPORT, packetSubCounter++);
connectionPacket.sendPacket(requestQueue->getDefaultDestination(),
requestQueue->getId());
triggerEvent(TEST, 1234, 5678);
return RETURN_OK;
}
default:
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
}
}
ReturnValue_t Service17Test::performService() {
return HasReturnvaluesIF::RETURN_OK;
}

44
pus/Service17Test.h Normal file
View File

@ -0,0 +1,44 @@
#ifndef FSFW_PUS_SERVICE17TEST_H_
#define FSFW_PUS_SERVICE17TEST_H_
#include "../tmtcservices/PusServiceBase.h"
#include "../objectmanager/SystemObject.h"
/**
* @brief Test Service
* Full Documentation: ECSS-E70-41A p.167
*
* The test service provides the capability to activate test functions
* implemented on-board and to report the results of such tests.
* Service capability:
* - TC[17,1]: Perform connection test
* - TM[17,2]: Send Connection Test Report
* - TC[17,128]: Perform connection test and trigger event
*
* @ingroup pus_services
*/
class Service17Test: public PusServiceBase {
public:
// Custom events which can be triggered
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_17;
static constexpr Event TEST = MAKE_EVENT(0, SEVERITY::INFO);
enum Subservice: uint8_t {
//! [EXPORT] : [COMMAND] Perform connection test
CONNECTION_TEST = 1,
//! [EXPORT] : [REPLY] Connection test reply
CONNECTION_TEST_REPORT = 2,
//! [EXPORT] : [COMMAND] Trigger test reply and test event
EVENT_TRIGGER_TEST = 128,
};
Service17Test(object_id_t objectId, uint16_t apid, uint8_t serviceId);
virtual ~Service17Test();
virtual ReturnValue_t handleRequest(uint8_t subservice) override;
virtual ReturnValue_t performService() override;
protected:
uint16_t packetSubCounter = 0;
};
#endif /* FSFW_PUS_SERVICE17TEST_H_ */

View File

@ -0,0 +1,58 @@
#include "Service9TimeManagement.h"
#include "servicepackets/Service9Packets.h"
#include "../timemanager/CCSDSTime.h"
#include "../events/EventManagerIF.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
Service9TimeManagement::Service9TimeManagement(object_id_t objectId,
uint16_t apid, uint8_t serviceId) :
PusServiceBase(objectId, apid , serviceId) {
}
Service9TimeManagement::~Service9TimeManagement() {}
ReturnValue_t Service9TimeManagement::performService() {
return RETURN_OK;
}
ReturnValue_t Service9TimeManagement::handleRequest(uint8_t subservice) {
switch(subservice){
case SUBSERVICE::SET_TIME:{
return setTime();
}
default:
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
}
}
ReturnValue_t Service9TimeManagement::setTime() {
Clock::TimeOfDay_t timeToSet;
TimePacket timePacket(currentPacket.getApplicationData(),
currentPacket.getApplicationDataSize());
ReturnValue_t result = CCSDSTime::convertFromCcsds(&timeToSet,
timePacket.getTime(), timePacket.getTimeSize());
if(result != RETURN_OK) {
triggerEvent(CLOCK_SET_FAILURE, result, 0);
return result;
}
uint32_t formerUptime;
Clock::getUptime(&formerUptime);
result = Clock::setClock(&timeToSet);
if(result == RETURN_OK) {
uint32_t newUptime;
Clock::getUptime(&newUptime);
triggerEvent(CLOCK_SET,newUptime,formerUptime);
return RETURN_OK;
}
else {
triggerEvent(CLOCK_SET_FAILURE, result, 0);
return RETURN_FAILED;
}
}

View File

@ -0,0 +1,41 @@
#ifndef FSFW_PUS_SERVICE9TIMEMANAGEMENT_H_
#define FSFW_PUS_SERVICE9TIMEMANAGEMENT_H_
#include "../tmtcservices/PusServiceBase.h"
class Service9TimeManagement: public PusServiceBase {
public:
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_9;
static constexpr Event CLOCK_SET = MAKE_EVENT(0, SEVERITY::INFO); //!< Clock has been set. P1: New Uptime. P2: Old Uptime
static constexpr Event CLOCK_SET_FAILURE = MAKE_EVENT(1, SEVERITY::LOW); //!< Clock could not be set. P1: Returncode.
static constexpr uint8_t CLASS_ID = CLASS_ID::PUS_SERVICE_9;
/**
* @brief This service provides the capability to set the on-board time.
*/
Service9TimeManagement(object_id_t objectId, uint16_t apid,
uint8_t serviceId);
virtual ~Service9TimeManagement();
virtual ReturnValue_t performService() override;
/**
* @brief Sets the onboard-time by retrieving the time to set from TC[9,128].
*/
virtual ReturnValue_t handleRequest(uint8_t subservice) override;
virtual ReturnValue_t setTime();
private:
enum SUBSERVICE {
SET_TIME = 128 //!< [EXPORT] : [COMMAND] Time command in ASCII, CUC or CDS format
};
};
#endif /* FSFW_PUS_SERVICE9TIMEMANAGEMENT_H_ */

View File

@ -0,0 +1,32 @@
#ifndef FSFW_PUS_SERVICEPACKETS_SERVICE9PACKETS_H_
#define FSFW_PUS_SERVICEPACKETS_SERVICE9PACKETS_H_
#include "../../serialize/SerialLinkedListAdapter.h"
/**
* @brief Subservice 128
* @details
* It only contains the time encoded as ASCII, CRC, CUC or CDS
* @ingroup spacepackets
*/
class TimePacket : SerialLinkedListAdapter<SerializeIF> { //!< [EXPORT] : [SUBSERVICE] 128
public:
TimePacket(const uint8_t * timeBuffer_, uint32_t timeSize_) {
timeBuffer = timeBuffer_;
timeSize = timeSize_;
}
const uint8_t* getTime() {
return timeBuffer;
}
uint32_t getTimeSize() const {
return timeSize;
}
private:
TimePacket(const TimePacket &command);
const uint8_t * timeBuffer;
uint32_t timeSize; //!< [EXPORT] : [IGNORE]
};
#endif /* FSFW_PUS_SERVICEPACKETS_SERVICE9PACKETS_H_ */

View File

@ -1,5 +1,5 @@
#ifndef FRAMEWORK_RETURNVALUES_FWCLASSIDS_H_
#define FRAMEWORK_RETURNVALUES_FWCLASSIDS_H_
#ifndef FSFW_RETURNVALUES_FWCLASSIDS_H_
#define FSFW_RETURNVALUES_FWCLASSIDS_H_
namespace CLASS_ID {
enum {
@ -56,7 +56,6 @@ enum {
DEVICE_COMMUNICATION_IF, //DC
BSP, //BSP
TIME_STAMPER_IF, //TSI 53
//TODO This will shift all IDs for FLP
SGP4PROPAGATOR_CLASS, //SGP4 54
MUTEX_IF, //MUX 55
MESSAGE_QUEUE_IF,//MQI 56
@ -65,9 +64,10 @@ enum {
POOL_VARIABLE_IF, //PVA 59
HOUSEKEEPING_MANAGER, //HKM 60
DLE_ENCODER, //DLEE 61
PUS_SERVICE_9, //PUS9 62
FW_CLASS_ID_COUNT //is actually count + 1 !
};
}
#endif /* FRAMEWORK_RETURNVALUES_FWCLASSIDS_H_ */
#endif /* FSFW_RETURNVALUES_FWCLASSIDS_H_ */

View File

@ -0,0 +1,88 @@
#include "ConstStorageAccessor.h"
#include "StorageManagerIF.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../globalfunctions/arrayprinter.h"
ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId):
storeId(storeId) {}
ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId,
StorageManagerIF* store):
storeId(storeId), store(store) {
internalState = AccessState::ASSIGNED;
}
ConstStorageAccessor::~ConstStorageAccessor() {
if(deleteData and store != nullptr) {
store->deleteData(storeId);
}
}
ConstStorageAccessor::ConstStorageAccessor(ConstStorageAccessor&& other):
constDataPointer(other.constDataPointer), storeId(other.storeId),
size_(other.size_), store(other.store), deleteData(other.deleteData),
internalState(other.internalState) {
// This prevent premature deletion
other.store = nullptr;
}
ConstStorageAccessor& ConstStorageAccessor::operator=(
ConstStorageAccessor&& other) {
constDataPointer = other.constDataPointer;
storeId = other.storeId;
store = other.store;
size_ = other.size_;
deleteData = other.deleteData;
this->store = other.store;
// This prevents premature deletion
other.store = nullptr;
return *this;
}
const uint8_t* ConstStorageAccessor::data() const {
return constDataPointer;
}
size_t ConstStorageAccessor::size() const {
if(internalState == AccessState::UNINIT) {
sif::warning << "StorageAccessor: Not initialized!" << std::endl;
}
return size_;
}
ReturnValue_t ConstStorageAccessor::getDataCopy(uint8_t *pointer,
size_t maxSize) {
if(internalState == AccessState::UNINIT) {
sif::warning << "StorageAccessor: Not initialized!" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
if(size_ > maxSize) {
sif::error << "StorageAccessor: Supplied buffer not large enough"
<< std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
std::copy(constDataPointer, constDataPointer + size_, pointer);
return HasReturnvaluesIF::RETURN_OK;
}
void ConstStorageAccessor::release() {
deleteData = false;
}
store_address_t ConstStorageAccessor::getId() const {
return storeId;
}
void ConstStorageAccessor::print() const {
if(internalState == AccessState::UNINIT or constDataPointer == nullptr) {
sif::warning << "StorageAccessor: Not initialized!" << std::endl;
return;
}
arrayprinter::print(constDataPointer, size_);
}
void ConstStorageAccessor::assignStore(StorageManagerIF* store) {
internalState = AccessState::ASSIGNED;
this->store = store;
}

View File

@ -0,0 +1,116 @@
#ifndef FSFW_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_
#define FSFW_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_
#include "storeAddress.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#include <cstddef>
class StorageManagerIF;
/**
* @brief Helper classes to facilitate safe access to storages which is also
* conforming to RAII principles
* @details
* Accessor class which can be returned by pool manager or passed and set by
* pool managers to have safe access to the pool resources.
*
* These helper can be used together with the StorageManager classes to manage
* access to a storage. It can take care of thread-safety while also providing
* mechanisms to automatically clear storage data.
*/
class ConstStorageAccessor {
//! StorageManager classes have exclusive access to private variables.
template<uint8_t NUMBER_OF_POOLS>
friend class PoolManager;
template<uint8_t NUMBER_OF_POOLS>
friend class LocalPool;
public:
/**
* @brief Simple constructor which takes the store ID of the storage
* entry to access.
* @param storeId
*/
ConstStorageAccessor(store_address_t storeId);
ConstStorageAccessor(store_address_t storeId, StorageManagerIF* store);
/**
* @brief The destructor in default configuration takes care of
* deleting the accessed pool entry and unlocking the mutex
*/
virtual ~ConstStorageAccessor();
/**
* @brief Returns a pointer to the read-only data
* @return
*/
const uint8_t* data() const;
/**
* @brief Copies the read-only data to the supplied pointer
* @param pointer
*/
virtual ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize);
/**
* @brief Calling this will prevent the Accessor from deleting the data
* when the destructor is called.
*/
void release();
/**
* Get the size of the data
* @return
*/
size_t size() const;
/**
* Get the storage ID.
* @return
*/
store_address_t getId() const;
void print() const;
/**
* @brief Move ctor and move assignment allow returning accessors as
* a returnvalue. They prevent resource being free prematurely.
* Refer to: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/
* move-constructors-and-move-assignment-operators-cpp.md
* @param
* @return
*/
ConstStorageAccessor& operator= (ConstStorageAccessor&&);
ConstStorageAccessor(ConstStorageAccessor&&);
//! The copy ctor and copy assignemnt should be deleted implicitely
//! according to https://foonathan.net/2019/02/special-member-functions/
//! but I still deleted them to make it more explicit. (remember rule of 5).
ConstStorageAccessor& operator=(const ConstStorageAccessor&) = delete;
ConstStorageAccessor(const ConstStorageAccessor&) = delete;
protected:
const uint8_t* constDataPointer = nullptr;
store_address_t storeId;
size_t size_ = 0;
//! Managing pool, has to assign itself.
StorageManagerIF* store = nullptr;
bool deleteData = true;
enum class AccessState {
UNINIT,
ASSIGNED
};
//! Internal state for safety reasons.
AccessState internalState = AccessState::UNINIT;
/**
* Used by the pool manager instances to assign themselves to the
* accessor. This is necessary to delete the data when the acessor
* exits the scope ! The internal state will be considered read
* when this function is called, so take care all data is set properly as
* well.
* @param
*/
void assignStore(StorageManagerIF*);
};
#endif /* FSFW_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ */

View File

@ -1,18 +1,14 @@
/**
* @file LocalPool
* @date 02.02.2012
* @author Bastian Baetz
* @brief This file contains the definition of the LocalPool class.
*/
#ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_
#define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_
#ifndef FSFW_STORAGEMANAGER_LOCALPOOL_H_
#define FSFW_STORAGEMANAGER_LOCALPOOL_H_
#include "../objectmanager/SystemObject.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "StorageManagerIF.h"
#include "../objectmanager/SystemObject.h"
#include "../objectmanager/ObjectManagerIF.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../internalError/InternalErrorReporterIF.h"
#include <string.h>
#include "../storagemanager/StorageAccessor.h"
#include <cstring>
/**
* @brief The LocalPool class provides an intermediate data storage with
@ -27,6 +23,7 @@
* 0xFFFF-1 bytes.
* It is possible to store empty packets in the pool.
* The local pool is NOT thread-safe.
* @author Bastian Baetz
*/
template<uint8_t NUMBER_OF_POOLS = 5>
class LocalPool: public SystemObject, public StorageManagerIF {
@ -39,7 +36,7 @@ public:
/**
* @brief This is the default constructor for a pool manager instance.
* @details By passing two arrays of size NUMBER_OF_POOLS, the constructor
* allocates memory (with \c new) for store and size_list. These
* allocates memory (with @c new) for store and size_list. These
* regions are all set to zero on start up.
* @param setObjectId The object identifier to be set. This allows for
* multiple instances of LocalPool in the system.
@ -73,10 +70,17 @@ public:
size_t size, bool ignoreFault = false) override;
ReturnValue_t getFreeElement(store_address_t* storageId,const size_t size,
uint8_t** p_data, bool ignoreFault = false) override;
ConstAccessorPair getData(store_address_t packet_id) override;
ReturnValue_t getData(store_address_t packet_id, ConstStorageAccessor&) override;
ReturnValue_t getData(store_address_t packet_id, const uint8_t** packet_ptr,
size_t * size) override;
AccessorPair modifyData(store_address_t packet_id) override;
ReturnValue_t modifyData(store_address_t packet_id, StorageAccessor&) override;
ReturnValue_t modifyData(store_address_t packet_id, uint8_t** packet_ptr,
size_t * size) override;
virtual ReturnValue_t deleteData(store_address_t) override;
virtual ReturnValue_t deleteData(uint8_t* ptr, size_t size,
store_address_t* storeId = NULL) override;
@ -84,7 +88,7 @@ public:
ReturnValue_t initialize() override;
protected:
/**
* With this helper method, a free element of \c size is reserved.
* With this helper method, a free element of @c size is reserved.
* @param size The minimum packet size that shall be reserved.
* @param[out] address Storage ID of the reserved data.
* @return - #RETURN_OK on success,
@ -97,7 +101,8 @@ protected:
private:
/**
* Indicates that this element is free.
* This value limits the maximum size of a pool. Change to larger data type if increase is required.
* This value limits the maximum size of a pool. Change to larger data type
* if increase is required.
*/
static const uint32_t STORAGE_FREE = 0xFFFFFFFF;
/**
@ -123,7 +128,9 @@ private:
* is also dynamically allocated there.
*/
uint32_t* size_list[NUMBER_OF_POOLS];
bool spillsToHigherPools; //!< A variable to determine whether higher n pools are used if the store is full.
//! A variable to determine whether higher n pools are used if
//! the store is full.
bool spillsToHigherPools;
/**
* @brief This method safely stores the given data in the given packet_id.
* @details It also sets the size in size_list. The method does not perform
@ -180,4 +187,4 @@ private:
#include "LocalPool.tpp"
#endif /* FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ */
#endif /* FSFW_STORAGEMANAGER_LOCALPOOL_H_ */

View File

@ -1,5 +1,9 @@
#ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_
#define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_
#ifndef FSFW_STORAGEMANAGER_LOCALPOOL_TPP_
#define FSFW_STORAGEMANAGER_LOCALPOOL_TPP_
#ifndef FSFW_STORAGEMANAGER_LOCALPOOL_H_
#error Include LocalPool.h before LocalPool.tpp!
#endif
template<uint8_t NUMBER_OF_POOLS>
inline LocalPool<NUMBER_OF_POOLS>::LocalPool(object_id_t setObjectId,
@ -122,8 +126,9 @@ inline LocalPool<NUMBER_OF_POOLS>::~LocalPool(void) {
}
template<uint8_t NUMBER_OF_POOLS>
inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::addData(store_address_t* storageId,
const uint8_t* data, size_t size, bool ignoreFault) {
inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::addData(
store_address_t* storageId, const uint8_t* data, size_t size,
bool ignoreFault) {
ReturnValue_t status = reserveSpace(size, storageId, ignoreFault);
if (status == RETURN_OK) {
write(*storageId, data, size);
@ -144,15 +149,55 @@ inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::getFreeElement(
return status;
}
template<uint8_t NUMBER_OF_POOLS>
inline ConstAccessorPair LocalPool<NUMBER_OF_POOLS>::getData(
store_address_t storeId) {
uint8_t* tempData = nullptr;
ConstStorageAccessor constAccessor(storeId, this);
ReturnValue_t status = modifyData(storeId, &tempData, &constAccessor.size_);
constAccessor.constDataPointer = tempData;
return ConstAccessorPair(status, std::move(constAccessor));
}
template<uint8_t NUMBER_OF_POOLS>
inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::getData(store_address_t storeId,
ConstStorageAccessor& storeAccessor) {
uint8_t* tempData = nullptr;
ReturnValue_t status = modifyData(storeId, &tempData, &storeAccessor.size_);
storeAccessor.assignStore(this);
storeAccessor.constDataPointer = tempData;
return status;
}
template<uint8_t NUMBER_OF_POOLS>
inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::getData(
store_address_t packet_id, const uint8_t** packet_ptr, size_t* size) {
uint8_t* tempData = NULL;
uint8_t* tempData = nullptr;
ReturnValue_t status = modifyData(packet_id, &tempData, size);
*packet_ptr = tempData;
return status;
}
template<uint8_t NUMBER_OF_POOLS>
inline AccessorPair LocalPool<NUMBER_OF_POOLS>::modifyData(
store_address_t storeId) {
StorageAccessor accessor(storeId, this);
ReturnValue_t status = modifyData(storeId, &accessor.dataPointer,
&accessor.size_);
accessor.assignConstPointer();
return AccessorPair(status, std::move(accessor));
}
template<uint8_t NUMBER_OF_POOLS>
inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::modifyData(
store_address_t storeId, StorageAccessor& storeAccessor) {
storeAccessor.assignStore(this);
ReturnValue_t status = modifyData(storeId, &storeAccessor.dataPointer,
&storeAccessor.size_);
storeAccessor.assignConstPointer();
return status;
}
template<uint8_t NUMBER_OF_POOLS>
inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::modifyData(
store_address_t packet_id, uint8_t** packet_ptr, size_t* size) {
@ -242,8 +287,8 @@ inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::initialize() {
}
internalErrorReporter = objectManager->get<InternalErrorReporterIF>(
objects::INTERNAL_ERROR_REPORTER);
if (internalErrorReporter == NULL){
return RETURN_FAILED;
if (internalErrorReporter == nullptr){
return ObjectManagerIF::INTERNAL_ERR_REPORTER_UNINIT;
}
//Check if any pool size is large than the maximum allowed.
@ -251,10 +296,10 @@ inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::initialize() {
if (element_sizes[count] >= STORAGE_FREE) {
sif::error << "LocalPool::initialize: Pool is too large! "
"Max. allowed size is: " << (STORAGE_FREE - 1) << std::endl;
return RETURN_FAILED;
return StorageManagerIF::POOL_TOO_LARGE;
}
}
return RETURN_OK;
}
#endif
#endif /* FSFW_STORAGEMANAGER_LOCALPOOL_TPP_ */

View File

@ -1,17 +1,18 @@
#ifndef POOLMANAGER_H_
#define POOLMANAGER_H_
#ifndef FSFW_STORAGEMANAGER_POOLMANAGER_H_
#define FSFW_STORAGEMANAGER_POOLMANAGER_H_
#include "LocalPool.h"
#include "StorageAccessor.h"
#include "../ipc/MutexHelper.h"
/**
* @brief The PoolManager class provides an intermediate data storage with
* a fixed pool size policy for inter-process communication.
* @details Uses local pool calls but is thread safe by protecting the call
* with a lock.
* @author Bastian Baetz
*/
template <uint8_t NUMBER_OF_POOLS = 5>
class PoolManager : public LocalPool<NUMBER_OF_POOLS> {
public:
@ -19,16 +20,25 @@ public:
const uint16_t element_sizes[NUMBER_OF_POOLS],
const uint16_t n_elements[NUMBER_OF_POOLS]);
//! @brief In the PoolManager's destructor all allocated memory is freed.
/**
* @brief In the PoolManager's destructor all allocated memory
* is freed.
*/
virtual ~PoolManager();
//! @brief LocalPool overrides for thread-safety.
/**
* @brief LocalPool overrides for thread-safety. Decorator function
* which wraps LocalPool calls with a mutex protection.
*/
ReturnValue_t deleteData(store_address_t) override;
ReturnValue_t deleteData(uint8_t* buffer, size_t size,
store_address_t* storeId = NULL) override;
ReturnValue_t modifyData(store_address_t packet_id, uint8_t** packet_ptr,
size_t* size) override;
store_address_t* storeId = nullptr) override;
void setMutexTimeout(uint32_t mutexTimeoutMs);
protected:
//! Default mutex timeout value to prevent permanent blocking.
uint32_t mutexTimeoutMs = 20;
ReturnValue_t reserveSpace(const uint32_t size, store_address_t* address,
bool ignoreFault) override;
@ -43,4 +53,4 @@ protected:
#include "PoolManager.tpp"
#endif /* POOLMANAGER_H_ */
#endif /* FSFW_STORAGEMANAGER_POOLMANAGER_H_ */

View File

@ -1,6 +1,10 @@
#ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_
#define FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_
#ifndef FSFW_STORAGEMANAGER_POOLMANAGER_H_
#error Include PoolManager.h before PoolManager.tpp!
#endif
template<uint8_t NUMBER_OF_POOLS>
inline PoolManager<NUMBER_OF_POOLS>::PoolManager(object_id_t setObjectId,
const uint16_t element_sizes[NUMBER_OF_POOLS],
@ -17,7 +21,7 @@ inline PoolManager<NUMBER_OF_POOLS>::~PoolManager(void) {
template<uint8_t NUMBER_OF_POOLS>
inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::reserveSpace(
const uint32_t size, store_address_t* address, bool ignoreFault) {
MutexHelper mutexHelper(mutex,MutexIF::BLOCKING);
MutexHelper mutexHelper(mutex,MutexIF::WAITING, mutexTimeoutMs);
ReturnValue_t status = LocalPool<NUMBER_OF_POOLS>::reserveSpace(size,
address,ignoreFault);
return status;
@ -29,7 +33,7 @@ inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::deleteData(
// debug << "PoolManager( " << translateObject(getObjectId()) <<
// " )::deleteData from store " << packet_id.pool_index <<
// ". id is "<< packet_id.packet_index << std::endl;
MutexHelper mutexHelper(mutex,MutexIF::BLOCKING);
MutexHelper mutexHelper(mutex,MutexIF::WAITING, mutexTimeoutMs);
ReturnValue_t status = LocalPool<NUMBER_OF_POOLS>::deleteData(packet_id);
return status;
}
@ -37,19 +41,16 @@ inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::deleteData(
template<uint8_t NUMBER_OF_POOLS>
inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::deleteData(uint8_t* buffer,
size_t size, store_address_t* storeId) {
MutexHelper mutexHelper(mutex,MutexIF::BLOCKING);
MutexHelper mutexHelper(mutex,MutexIF::WAITING, mutexTimeoutMs);
ReturnValue_t status = LocalPool<NUMBER_OF_POOLS>::deleteData(buffer,
size, storeId);
return status;
}
template<uint8_t NUMBER_OF_POOLS>
inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::modifyData(
store_address_t packet_id, uint8_t** packet_ptr, size_t* size) {
MutexHelper mutexHelper(mutex,MutexIF::BLOCKING);
ReturnValue_t status = LocalPool<NUMBER_OF_POOLS>::modifyData(packet_id,
packet_ptr, size);
return status;
inline void PoolManager<NUMBER_OF_POOLS>::setMutexTimeout(
uint32_t mutexTimeoutMs) {
this->mutexTimeout = mutexTimeoutMs;
}
#endif
#endif /* FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ */

View File

@ -0,0 +1,67 @@
#include "StorageAccessor.h"
#include "StorageManagerIF.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
StorageAccessor::StorageAccessor(store_address_t storeId):
ConstStorageAccessor(storeId) {
}
StorageAccessor::StorageAccessor(store_address_t storeId,
StorageManagerIF* store):
ConstStorageAccessor(storeId, store) {
}
StorageAccessor& StorageAccessor::operator =(
StorageAccessor&& other) {
// Call the parent move assignment and also assign own member.
dataPointer = other.dataPointer;
StorageAccessor::operator=(std::move(other));
return * this;
}
// Call the parent move ctor and also transfer own member.
StorageAccessor::StorageAccessor(StorageAccessor&& other):
ConstStorageAccessor(std::move(other)), dataPointer(other.dataPointer) {
}
ReturnValue_t StorageAccessor::getDataCopy(uint8_t *pointer, size_t maxSize) {
if(internalState == AccessState::UNINIT) {
sif::warning << "StorageAccessor: Not initialized!" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
if(size_ > maxSize) {
sif::error << "StorageAccessor: Supplied buffer not large "
"enough" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
std::copy(dataPointer, dataPointer + size_, pointer);
return HasReturnvaluesIF::RETURN_OK;
}
uint8_t* StorageAccessor::data() {
if(internalState == AccessState::UNINIT) {
sif::warning << "StorageAccessor: Not initialized!" << std::endl;
}
return dataPointer;
}
ReturnValue_t StorageAccessor::write(uint8_t *data, size_t size,
uint16_t offset) {
if(internalState == AccessState::UNINIT) {
sif::warning << "StorageAccessor: Not initialized!" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
if(offset + size > size_) {
sif::error << "StorageAccessor: Data too large for pool "
"entry!" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
std::copy(data, data + size, dataPointer + offset);
return HasReturnvaluesIF::RETURN_OK;
}
void StorageAccessor::assignConstPointer() {
constDataPointer = dataPointer;
}

View File

@ -0,0 +1,45 @@
#ifndef FSFW_STORAGEMANAGER_STORAGEACCESSOR_H_
#define FSFW_STORAGEMANAGER_STORAGEACCESSOR_H_
#include "ConstStorageAccessor.h"
class StorageManagerIF;
/**
* @brief Child class for modifyable data. Also has a normal pointer member.
*/
class StorageAccessor: public ConstStorageAccessor {
//! StorageManager classes have exclusive access to private variables.
template<uint8_t NUMBER_OF_POOLS>
friend class PoolManager;
template<uint8_t NUMBER_OF_POOLS>
friend class LocalPool;
public:
StorageAccessor(store_address_t storeId);
StorageAccessor(store_address_t storeId, StorageManagerIF* store);
/**
* @brief Move ctor and move assignment allow returning accessors as
* a returnvalue. They prevent resource being freed prematurely.
* See: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/
* move-constructors-and-move-assignment-operators-cpp.md
* @param
* @return
*/
StorageAccessor& operator=(StorageAccessor&&);
StorageAccessor(StorageAccessor&&);
ReturnValue_t write(uint8_t *data, size_t size,
uint16_t offset = 0);
uint8_t* data();
ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize) override;
private:
//! Non-const pointer for modifyable data.
uint8_t* dataPointer = nullptr;
//! For modifyable data, the const pointer is assigned to the normal
//! pointer by the pool manager so both access functions can be used safely
void assignConstPointer();
};
#endif /* FSFW_STORAGEMANAGER_STORAGEACCESSOR_H_ */

View File

@ -1,60 +1,17 @@
#ifndef STORAGEMANAGERIF_H_H
#define STORAGEMANAGERIF_H_H
#ifndef FSFW_STORAGEMANAGER_STORAGEMANAGERIF_H_
#define FSFW_STORAGEMANAGER_STORAGEMANAGERIF_H_
#include "StorageAccessor.h"
#include "storeAddress.h"
#include "../events/Event.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#include <stddef.h>
/**
* @brief This union defines the type that identifies where a data packet is
* stored in the store.
* It consists of a raw part to read it as raw value and
* a structured part to use it in pool-like stores.
*/
union store_address_t {
/**
* Default Constructor, initializing to INVALID_ADDRESS
*/
store_address_t():raw(0xFFFFFFFF){}
#include <utility>
#include <cstddef>
/**
* Constructor to create an address object using the raw address
* @param rawAddress
*/
store_address_t(uint32_t rawAddress):raw(rawAddress){}
/**
* Constructor to create an address object using pool
* and packet indices
*
* @param poolIndex
* @param packetIndex
*/
store_address_t(uint16_t poolIndex, uint16_t packetIndex):
pool_index(poolIndex),packet_index(packetIndex) {}
/**
* A structure with two elements to access the store address pool-like.
*/
struct {
/**
* The index in which pool the packet lies.
*/
uint16_t pool_index;
/**
* The position in the chosen pool.
*/
uint16_t packet_index;
};
/**
* Alternative access to the raw value.
*/
uint32_t raw;
bool operator==(const store_address_t& other) const {
return raw == other.raw;
}
};
using AccessorPair = std::pair<ReturnValue_t, StorageAccessor>;
using ConstAccessorPair = std::pair<ReturnValue_t, ConstStorageAccessor>;
/**
* @brief This class provides an interface for intermediate data storage.
@ -77,6 +34,7 @@ public:
static const ReturnValue_t ILLEGAL_STORAGE_ID = MAKE_RETURN_CODE(3); //!< This return code indicates that data was requested with an illegal storage ID.
static const ReturnValue_t DATA_DOES_NOT_EXIST = MAKE_RETURN_CODE(4); //!< This return code indicates that the requested ID was valid, but no data is stored there.
static const ReturnValue_t ILLEGAL_ADDRESS = MAKE_RETURN_CODE(5);
static const ReturnValue_t POOL_TOO_LARGE = MAKE_RETURN_CODE(6); //!< Pool size too large on initialization.
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::OBSW;
static const Event GET_DATA_FAILED = MAKE_EVENT(0, SEVERITY::LOW);
@ -122,6 +80,29 @@ public:
*/
virtual ReturnValue_t deleteData(uint8_t* buffer, size_t size,
store_address_t* storeId = nullptr) = 0;
/**
* @brief Access the data by supplying a store ID.
* @details
* A pair consisting of the retrieval result and an instance of a
* ConstStorageAccessor class is returned
* @param storeId
* @return Pair of return value and a ConstStorageAccessor instance
*/
virtual ConstAccessorPair getData(store_address_t storeId) = 0;
/**
* @brief Access the data by supplying a store ID and a helper
* instance
* @param storeId
* @param constAccessor Wrapper function to access store data.
* @return
*/
virtual ReturnValue_t getData(store_address_t storeId,
ConstStorageAccessor& constAccessor) = 0;
/**
* @brief getData returns an address to data and the size of the data
* for a given packet_id.
@ -135,8 +116,30 @@ public:
*/
virtual ReturnValue_t getData(store_address_t packet_id,
const uint8_t** packet_ptr, size_t* size) = 0;
/**
* Same as above, but not const and therefore modifiable.
* Modify data by supplying a store ID
* @param storeId
* @return Pair of return value and StorageAccessor helper
*/
virtual AccessorPair modifyData(store_address_t storeId) = 0;
/**
* Modify data by supplying a store ID and a StorageAccessor helper instance.
* @param storeId
* @param accessor Helper class to access the modifiable data.
* @return
*/
virtual ReturnValue_t modifyData(store_address_t storeId,
StorageAccessor& accessor) = 0;
/**
* Get pointer and size of modifiable data by supplying the storeId
* @param packet_id
* @param packet_ptr [out] Pointer to pointer of data to set
* @param size [out] Pointer to size to set
* @return
*/
virtual ReturnValue_t modifyData(store_address_t packet_id,
uint8_t** packet_ptr, size_t* size) = 0;
@ -155,6 +158,7 @@ public:
*/
virtual ReturnValue_t getFreeElement(store_address_t* storageId,
const size_t size, uint8_t** p_data, bool ignoreFault = false ) = 0;
/**
* Clears the whole store.
* Use with care!
@ -162,4 +166,4 @@ public:
virtual void clearStore() = 0;
};
#endif /* STORAGEMANAGERIF_H_ */
#endif /* FSFW_STORAGEMANAGER_STORAGEMANAGERIF_H_ */

View File

@ -0,0 +1,55 @@
#ifndef FSFW_STORAGEMANAGER_STOREADDRESS_H_
#define FSFW_STORAGEMANAGER_STOREADDRESS_H_
#include <cstdint>
/**
* This union defines the type that identifies where a data packet is
* stored in the store. It comprises of a raw part to read it as raw value and
* a structured part to use it in pool-like stores.
*/
union store_address_t {
/**
* Default Constructor, initializing to INVALID_ADDRESS
*/
store_address_t():raw(0xFFFFFFFF){}
/**
* Constructor to create an address object using the raw address
*
* @param rawAddress
*/
store_address_t(uint32_t rawAddress):raw(rawAddress){}
/**
* Constructor to create an address object using pool
* and packet indices
*
* @param poolIndex
* @param packetIndex
*/
store_address_t(uint16_t poolIndex, uint16_t packetIndex):
pool_index(poolIndex),packet_index(packetIndex){}
/**
* A structure with two elements to access the store address pool-like.
*/
struct {
/**
* The index in which pool the packet lies.
*/
uint16_t pool_index;
/**
* The position in the chosen pool.
*/
uint16_t packet_index;
};
/**
* Alternative access to the raw value.
*/
uint32_t raw;
bool operator==(const store_address_t& other) const {
return raw == other.raw;
}
};
#endif /* FSFW_STORAGEMANAGER_STOREADDRESS_H_ */

View File

@ -0,0 +1,17 @@
#include "FixedSequenceSlot.h"
#include "PeriodicTaskIF.h"
#include <cstddef>
FixedSequenceSlot::FixedSequenceSlot(object_id_t handlerId, uint32_t setTime,
int8_t setSequenceId, ExecutableObjectIF* executableObject,
PeriodicTaskIF* executingTask) : handlerId(handlerId),
pollingTimeMs(setTime), opcode(setSequenceId) {
if(executableObject == nullptr) {
return;
}
this->executableObject = executableObject;
this->executableObject->setTaskIF(executingTask);
}
FixedSequenceSlot::~FixedSequenceSlot() {}

View File

@ -1,39 +1,39 @@
/**
* @file FixedSequenceSlot.h
* @brief This file defines the PollingSlot class.
* @date 19.12.2012
* @author baetz
*/
#ifndef FIXEDSEQUENCESLOT_H_
#define FIXEDSEQUENCESLOT_H_
#ifndef FSFW_TASKS_FIXEDSEQUENCESLOT_H_
#define FSFW_TASKS_FIXEDSEQUENCESLOT_H_
#include "ExecutableObjectIF.h"
#include "../objectmanager/ObjectManagerIF.h"
#include "../tasks/ExecutableObjectIF.h"
class PeriodicTaskIF;
/**
* @brief This class is the representation of a single polling sequence table entry.
*
* @details The PollingSlot class is the representation of a single polling
* @brief This class is the representation of a single polling sequence
* table entry.
* @details
* The PollingSlot class is the representation of a single polling
* sequence table entry.
* @author baetz
*/
class FixedSequenceSlot {
public:
FixedSequenceSlot( object_id_t handlerId, uint32_t setTimeMs,
int8_t setSequenceId, PeriodicTaskIF* executingTask );
int8_t setSequenceId, ExecutableObjectIF* executableObject,
PeriodicTaskIF* executingTask);
virtual ~FixedSequenceSlot();
object_id_t handlerId;
/**
* @brief Handler identifies which device handler object is executed in this slot.
* @brief Handler identifies which object is executed in this slot.
*/
ExecutableObjectIF* handler;
ExecutableObjectIF* executableObject = nullptr;
/**
* @brief This attribute defines when a device handler object is executed.
*
* @details The pollingTime attribute identifies the time the handler is executed in ms.
* It must be smaller than the period length of the polling sequence.
* @details
* The pollingTime attribute identifies the time the handler is
* executed in ms. It must be smaller than the period length of the
* polling sequence.
*/
uint32_t pollingTimeMs;
@ -57,4 +57,4 @@ public:
};
#endif /* FIXEDSEQUENCESLOT_H_ */
#endif /* FSFW_TASKS_FIXEDSEQUENCESLOT_H_ */

View File

@ -1,5 +1,6 @@
#include "FixedSlotSequence.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include <cstdlib>
FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) :
lengthMs(setLengthMs) {
@ -12,7 +13,7 @@ FixedSlotSequence::~FixedSlotSequence() {
}
void FixedSlotSequence::executeAndAdvance() {
current->handler->performOperation(current->opcode);
current->executableObject->performOperation(current->opcode);
// if (returnValue != RETURN_OK) {
// this->sendErrorMessage( returnValue );
// }
@ -80,44 +81,82 @@ uint32_t FixedSlotSequence::getLengthMs() const {
return this->lengthMs;
}
void FixedSlotSequence::addSlot(object_id_t componentId, uint32_t slotTimeMs,
int8_t executionStep, ExecutableObjectIF* executableObject,
PeriodicTaskIF* executingTask) {
this->slotList.insert(FixedSequenceSlot(componentId, slotTimeMs,
executionStep, executableObject, executingTask));
this->current = slotList.begin();
}
ReturnValue_t FixedSlotSequence::checkSequence() const {
if(slotList.empty()) {
sif::error << "Fixed Slot Sequence: Slot list is empty!" << std::endl;
sif::error << "FixedSlotSequence::checkSequence:"
<< " Slot list is empty!" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
auto slotIt = slotList.begin();
uint32_t count = 0;
if(customCheckFunction != nullptr) {
ReturnValue_t result = customCheckFunction(slotList);
if(result != HasReturnvaluesIF::RETURN_OK) {
// Continue for now but print error output.
sif::error << "FixedSlotSequence::checkSequence:"
<< " Custom check failed!" << std::endl;
}
}
uint32_t errorCount = 0;
uint32_t time = 0;
while (slotIt != slotList.end()) {
if (slotIt->handler == nullptr) {
sif::error << "FixedSlotSequene::initialize: ObjectId does not exist!"
<< std::endl;
count++;
} else if (slotIt->pollingTimeMs < time) {
sif::error << "FixedSlotSequence::initialize: Time: "
<< slotIt->pollingTimeMs
<< " is smaller than previous with " << time << std::endl;
count++;
} else {
for(const auto& slot: slotList) {
if (slot.executableObject == nullptr) {
errorCount++;
}
else if (slot.pollingTimeMs < time) {
sif::error << "FixedSlotSequence::checkSequence: Time: "
<< slot.pollingTimeMs << " is smaller than previous with "
<< time << std::endl;
errorCount++;
}
else {
// All ok, print slot.
//info << "Current slot polling time: " << std::endl;
//info << std::dec << slotIt->pollingTimeMs << std::endl;
//sif::info << "Current slot polling time: " << std::endl;
//sif::info << std::dec << slotIt->pollingTimeMs << std::endl;
}
time = slotIt->pollingTimeMs;
slotIt++;
time = slot.pollingTimeMs;
}
//info << "Number of elements in slot list: "
//sif::info << "Number of elements in slot list: "
// << slotList.size() << std::endl;
if (count > 0) {
if (errorCount > 0) {
return HasReturnvaluesIF::RETURN_FAILED;
}
return HasReturnvaluesIF::RETURN_OK;
}
void FixedSlotSequence::addSlot(object_id_t componentId, uint32_t slotTimeMs,
int8_t executionStep, PeriodicTaskIF* executingTask) {
this->slotList.insert(FixedSequenceSlot(componentId, slotTimeMs, executionStep,
executingTask));
this->current = slotList.begin();
ReturnValue_t FixedSlotSequence::intializeSequenceAfterTaskCreation() const {
std::set<ExecutableObjectIF*> uniqueObjects;
uint32_t count = 0;
for(const auto& slot: slotList) {
// Ensure that each unique object is initialized once.
if(uniqueObjects.find(slot.executableObject) == uniqueObjects.end()) {
ReturnValue_t result =
slot.executableObject->initializeAfterTaskCreation();
if(result != HasReturnvaluesIF::RETURN_OK) {
count++;
}
uniqueObjects.emplace(slot.executableObject);
}
}
if (count > 0) {
sif::error << "FixedSlotSequence::intializeSequenceAfterTaskCreation:"
"Counted " << count << " failed initializations!" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
return HasReturnvaluesIF::RETURN_OK;
}
void FixedSlotSequence::addCustomCheck(ReturnValue_t
(*customCheckFunction)(const SlotList&)) {
this->customCheckFunction = customCheckFunction;
}

View File

@ -1,26 +1,30 @@
#ifndef FRAMEWORK_DEVICEHANDLERS_FIXEDSLOTSEQUENCE_H_
#define FRAMEWORK_DEVICEHANDLERS_FIXEDSLOTSEQUENCE_H_
#ifndef FSFW_TASKS_FIXEDSLOTSEQUENCE_H_
#define FSFW_TASKS_FIXEDSLOTSEQUENCE_H_
#include "FixedSequenceSlot.h"
#include "../objectmanager/SystemObject.h"
#include <set>
/**
* @brief This class is the representation of a Polling Sequence Table in software.
*
* @brief This class is the representation of a
* Polling Sequence Table in software.
* @details
* The FixedSlotSequence object maintains the dynamic execution of
* device handler objects.
* objects with stricter timing requirements for the FixedTimeslotTask.
*
* The main idea is to create a list of device handlers, to announce all
* handlers to thepolling sequence and to maintain a list of
* polling slot objects. This slot list represents the Polling Sequence Table
* in software.
* The main idea is to create a list of executable objects (for example
* device handlers), to announce all handlers to the polling sequence and to
* maintain a list of polling slot objects.
* This slot list represents the Polling Sequence Table in software.
*
* Each polling slot contains information to indicate when and
* which device handler shall be executed within a given polling period.
* The sequence is then executed by iterating through this slot list.
* Handlers are invoking by calling a certain function stored in the handler list.
* which executable object shall be executed within a given polling period.
* When adding a slot, a pointer to the executing task, a pointer to the
* executable object and a step number can be passed. The step number will be
* passed to the periodic handler.
* The sequence is executed by iterating through the slot sequence and
* executing the executable object in the correct timeslot.
*/
class FixedSlotSequence {
public:
@ -29,41 +33,44 @@ public:
/**
* @brief The constructor of the FixedSlotSequence object.
*
* @details The constructor takes two arguments, the period length and the init function.
*
* @param setLength The period length, expressed in ms.
*/
FixedSlotSequence(uint32_t setLengthMs);
/**
* @brief The destructor of the FixedSlotSequence object.
*
* @details The destructor frees all allocated memory by iterating through the slotList
* and deleting all allocated resources.
* @details
* The destructor frees all allocated memory by iterating through the
* slotList and deleting all allocated resources.
*/
virtual ~FixedSlotSequence();
/**
* @brief This is a method to add an PollingSlot object to slotList.
*
* @details Here, a polling slot object is added to the slot list. It is appended
* @details
* Here, a polling slot object is added to the slot list. It is appended
* to the end of the list. The list is currently NOT reordered.
* Afterwards, the iterator current is set to the beginning of the list.
* @param Object ID of the object to add
* @param setTime Value between (0 to 1) * slotLengthMs, when a FixedTimeslotTask
* @param handlerId ID of the object to add
* @param setTime
* Value between (0 to 1) * slotLengthMs, when a FixedTimeslotTask
* will be called inside the slot period.
* @param setSequenceId ID which can be used to distinguish
* different task operations
* @param setSequenceId
* ID which can be used to distinguish different task operations. This
* value will be passed to the executable function.
* @param
* @param
*/
void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId,
ExecutableObjectIF* executableObject,
PeriodicTaskIF* executingTask);
/**
* Checks if the current slot shall be executed immediately after the one before.
* This allows to distinguish between grouped and not grouped handlers.
* @brief Checks if the current slot shall be executed immediately
* after the one before.
* @details
* This allows to distinguish between grouped and separated handlers.
* @return - @c true if the slot has the same polling time as the previous
* - @c false else
*/
@ -125,12 +132,32 @@ public:
SlotListIter current;
/**
* Iterate through slotList and check successful creation.
* @brief Check and initialize slot list.
* @details
* Checks if timing is ok (must be ascending) and if all handlers were found.
* @return
*/
ReturnValue_t checkSequence() const;
/**
* @brief A custom check can be injected for the respective slot list.
* @details
* This can be used by the developer to check the validity of a certain
* sequence. The function will be run in the #checkSequence function.
* The general check will be continued for now if the custom check function
* fails but a diagnostic debug output will be given.
* @param customCheckFunction
*/
void addCustomCheck(ReturnValue_t (*customCheckFunction)(const SlotList &));
/**
* @brief Perform any initialization steps required after the executing
* task has been created. This function should be called from the
* executing task!
* @return
*/
ReturnValue_t intializeSequenceAfterTaskCreation() const;
protected:
/**
@ -146,7 +173,9 @@ protected:
*/
SlotList slotList;
ReturnValue_t (*customCheckFunction)(const SlotList&) = nullptr;
uint32_t lengthMs;
};
#endif /* FIXEDSLOTSEQUENCE_H_ */
#endif /* FSFW_TASKS_FIXEDSLOTSEQUENCE_H_ */

View File

@ -9,8 +9,7 @@
#include <sys/time.h>
//! Don't use these for time points, type is not large enough for UNIX epoch.
typedef uint32_t dur_millis_t;
typedef double dur_seconds_t;
using dur_millis_t = uint32_t;
class Clock {
public:

View File

@ -6,19 +6,22 @@ Stopwatch::Stopwatch(bool displayOnDestruction,
StopwatchDisplayMode displayMode): displayOnDestruction(
displayOnDestruction), displayMode(displayMode) {
// Measures start time on initialization.
Clock::getClock_timeval(&startTime);
Clock::getUptime(&startTime);
}
void Stopwatch::start() {
Clock::getClock_timeval(&startTime);
Clock::getUptime(&startTime);
}
dur_millis_t Stopwatch::stop() {
dur_millis_t Stopwatch::stop(bool display) {
stopInternal();
if(display) {
this->display();
}
return elapsedTime.tv_sec * 1000 + elapsedTime.tv_usec / 1000;
}
dur_seconds_t Stopwatch::stopSeconds() {
double Stopwatch::stopSeconds() {
stopInternal();
return timevalOperations::toDouble(elapsedTime);
}
@ -52,6 +55,6 @@ StopwatchDisplayMode Stopwatch::getDisplayMode() const {
void Stopwatch::stopInternal() {
timeval endTime;
Clock::getClock_timeval(&endTime);
Clock::getUptime(&endTime);
elapsedTime = endTime - startTime;
}

View File

@ -1,5 +1,6 @@
#ifndef FRAMEWORK_TIMEMANAGER_STOPWATCH_H_
#define FRAMEWORK_TIMEMANAGER_STOPWATCH_H_
#ifndef FSFW_TIMEMANAGER_STOPWATCH_H_
#define FSFW_TIMEMANAGER_STOPWATCH_H_
#include "Clock.h"
enum class StopwatchDisplayMode {
@ -40,12 +41,12 @@ public:
* Calculates the elapsed time since start and returns it
* @return elapsed time in milliseconds (rounded)
*/
dur_millis_t stop();
dur_millis_t stop(bool display = false);
/**
* Calculates the elapsed time since start and returns it
* @return elapsed time in seconds (double precision)
*/
dur_seconds_t stopSeconds();
double stopSeconds();
/**
* Displays the elapsed times on the osstream, depending on internal display
@ -66,6 +67,4 @@ private:
};
#endif /* FRAMEWORK_TIMEMANAGER_STOPWATCH_H_ */
#endif /* FSFW_TIMEMANAGER_STOPWATCH_H_ */

View File

@ -0,0 +1,23 @@
#include "TimeStamper.h"
#include "Clock.h"
#include <cstring>
TimeStamper::TimeStamper(object_id_t objectId): SystemObject(objectId) {}
ReturnValue_t TimeStamper::addTimeStamp(uint8_t* buffer,
const uint8_t maxSize) {
if(maxSize < TimeStamperIF::MISSION_TIMESTAMP_SIZE){
return HasReturnvaluesIF::RETURN_FAILED;
}
timeval now;
Clock::getClock_timeval(&now);
CCSDSTime::CDS_short cds;
ReturnValue_t result = CCSDSTime::convertToCcsds(&cds,&now);
if(result != HasReturnvaluesIF::RETURN_OK){
return result;
}
std::memcpy(buffer,&cds,sizeof(cds));
return result;
}

36
timemanager/TimeStamper.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef FSFW_TIMEMANAGER_TIMESTAMPER_H_
#define FSFW_TIMEMANAGER_TIMESTAMPER_H_
#include "TimeStamperIF.h"
#include "CCSDSTime.h"
#include "../objectmanager/SystemObject.h"
/**
* @brief Time stamper which can be used to add any timestamp to a
* given buffer.
* @details
* This time stamper uses the CCSDS CDC short timestamp as a fault timestamp.
* This timestamp has a size of 8 bytes. A custom timestamp can be used by
* overriding the #addTimeStamp function.
* @ingroup utility
*/
class TimeStamper: public TimeStamperIF, public SystemObject {
public:
/**
* @brief Default constructor which also registers the time stamper as a
* system object so it can be found with the #objectManager.
* @param objectId
*/
TimeStamper(object_id_t objectId);
/**
* Adds a CCSDS CDC short 8 byte timestamp to the given buffer.
* This function can be overriden to use a custom timestamp.
* @param buffer
* @param maxSize
* @return
*/
virtual ReturnValue_t addTimeStamp(uint8_t* buffer, const uint8_t maxSize);
};
#endif /* FSFW_TIMEMANAGER_TIMESTAMPER_H_ */

View File

@ -384,7 +384,7 @@ void CommandingServiceBase::acceptPacket(uint8_t reportId,
}
void CommandingServiceBase::checkAndExecuteFifo(CommandMapIter iter) {
void CommandingServiceBase::checkAndExecuteFifo(CommandMapIter& iter) {
store_address_t address;
if (iter->second.fifo.retrieve(&address) != RETURN_OK) {
commandMap.erase(&iter);

View File

@ -39,7 +39,11 @@ class CommandingServiceBase: public SystemObject,
public HasReturnvaluesIF {
friend void (Factory::setStaticFrameworkObjectIds)();
public:
// We could make this configurable via preprocessor and the FSFWConfig file.
static constexpr uint8_t COMMAND_INFO_FIFO_DEPTH = 3;
static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_SERVICE_BASE;
static const ReturnValue_t EXECUTION_COMPLETE = MAKE_RETURN_CODE(1);
static const ReturnValue_t NO_STEP_MESSAGE = MAKE_RETURN_CODE(2);
static const ReturnValue_t OBJECT_BUSY = MAKE_RETURN_CODE(3);
@ -223,7 +227,7 @@ protected:
uint32_t state;
Command_t command;
object_id_t objectId;
FIFO<store_address_t, 3> fifo;
FIFO<store_address_t, COMMAND_INFO_FIFO_DEPTH> fifo;
virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size,
size_t maxSize, Endianness streamEndianness) const override{
@ -312,7 +316,7 @@ protected:
ReturnValue_t sendTmPacket(uint8_t subservice, SerializeIF* content,
SerializeIF* header = nullptr);
void checkAndExecuteFifo(CommandMapIter iter);
void checkAndExecuteFifo(CommandMapIter& iter);
private:
/**

View File

@ -4,31 +4,6 @@
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,
uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl,
ReturnValue_t set_error_code, uint8_t set_step, uint32_t parameter1,

View File

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

View File

@ -1,55 +1,59 @@
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "VerificationReporter.h"
#include "AcceptsVerifyMessageIF.h"
#include "PusVerificationReport.h"
#include "VerificationReporter.h"
object_id_t VerificationReporter::messageReceiver = 0;
#include "../ipc/MessageQueueIF.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../objectmanager/frameworkObjects.h"
object_id_t VerificationReporter::messageReceiver =
objects::PUS_SERVICE_1_VERIFICATION;
VerificationReporter::VerificationReporter() :
acknowledgeQueue() {
acknowledgeQueue(MessageQueueIF::NO_QUEUE) {
}
VerificationReporter::~VerificationReporter() {
//Default, empty
}
VerificationReporter::~VerificationReporter() {}
void VerificationReporter::sendSuccessReport(uint8_t set_report_id,
TcPacketBase* current_packet, uint8_t set_step) {
if (this->acknowledgeQueue == 0) {
if (acknowledgeQueue == MessageQueueIF::NO_QUEUE) {
this->initialize();
}
PusVerificationMessage message(set_report_id,
current_packet->getAcknowledgeFlags(),
current_packet->getPacketId(),
current_packet->getPacketSequenceControl(), 0, set_step);
ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, &message);
ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue,
&message);
if (status != HasReturnvaluesIF::RETURN_OK) {
sif::error
<< "VerificationReporter::sendSuccessReport: Error writing to queue. Code: "
<< (uint16_t) status << std::endl;
sif::error << "VerificationReporter::sendSuccessReport: Error writing "
<< "to queue. Code: " << std::hex << status << std::dec
<< std::endl;
}
}
void VerificationReporter::sendSuccessReport(uint8_t set_report_id,
uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl,
uint8_t set_step) {
if (this->acknowledgeQueue == 0) {
if (acknowledgeQueue == MessageQueueIF::NO_QUEUE) {
this->initialize();
}
PusVerificationMessage message(set_report_id, ackFlags, tcPacketId,
tcSequenceControl, 0, set_step);
ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, &message);
ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue,
&message);
if (status != HasReturnvaluesIF::RETURN_OK) {
sif::error
<< "VerificationReporter::sendSuccessReport: Error writing to queue. Code: "
<< (uint16_t) status << std::endl;
sif::error << "VerificationReporter::sendSuccessReport: Error writing "
<< "to queue. Code: " << std::hex << status << std::dec
<< std::endl;
}
}
void VerificationReporter::sendFailureReport(uint8_t report_id,
TcPacketBase* current_packet, ReturnValue_t error_code, uint8_t step,
uint32_t parameter1, uint32_t parameter2) {
if (this->acknowledgeQueue == 0) {
if (acknowledgeQueue == MessageQueueIF::NO_QUEUE) {
this->initialize();
}
PusVerificationMessage message(report_id,
@ -57,11 +61,12 @@ void VerificationReporter::sendFailureReport(uint8_t report_id,
current_packet->getPacketId(),
current_packet->getPacketSequenceControl(), error_code, step,
parameter1, parameter2);
ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, &message);
ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue,
&message);
if (status != HasReturnvaluesIF::RETURN_OK) {
sif::error
<< "VerificationReporter::sendFailureReport Error writing to queue. Code: "
<< (uint16_t) status << std::endl;
sif::error << "VerificationReporter::sendFailureReport: Error writing "
<< "to queue. Code: " << std::hex << "0x" << status << std::dec
<< std::endl;
}
}
@ -69,27 +74,33 @@ void VerificationReporter::sendFailureReport(uint8_t report_id,
uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl,
ReturnValue_t error_code, uint8_t step, uint32_t parameter1,
uint32_t parameter2) {
if (this->acknowledgeQueue == 0) {
if (acknowledgeQueue == MessageQueueIF::NO_QUEUE) {
this->initialize();
}
PusVerificationMessage message(report_id, ackFlags, tcPacketId,
tcSequenceControl, error_code, step, parameter1, parameter2);
ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, &message);
ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue,
&message);
if (status != HasReturnvaluesIF::RETURN_OK) {
sif::error
<< "VerificationReporter::sendFailureReport Error writing to queue. Code: "
<< (uint16_t) status << std::endl;
sif::error << "VerificationReporter::sendFailureReport: Error writing "
<< "to queue. Code: " << std::hex << "0x" << status << std::dec
<< std::endl;
}
}
void VerificationReporter::initialize() {
if(messageReceiver == objects::NO_OBJECT) {
sif::warning << "VerificationReporter::initialize: Verification message"
" receiver object ID not set yet in Factory!" << std::endl;
return;
}
AcceptsVerifyMessageIF* temp = objectManager->get<AcceptsVerifyMessageIF>(
messageReceiver);
if (temp != NULL) {
if (temp == nullptr) {
sif::error << "VerificationReporter::initialize: Message "
<< "receiver invalid. Make sure it is set up properly and "
<< "implementsAcceptsVerifyMessageIF" << std::endl;
return;
}
this->acknowledgeQueue = temp->getVerificationQueue();
} else {
sif::error
<< "VerificationReporter::VerificationReporter: Configuration error."
<< std::endl;
}
}

View File

@ -1,31 +1,50 @@
#ifndef VERIFICATIONREPORTER_H_
#define VERIFICATIONREPORTER_H_
#ifndef FSFW_TMTCSERVICES_VERIFICATIONREPORTER_H_
#define FSFW_TMTCSERVICES_VERIFICATIONREPORTER_H_
#include "../objectmanager/ObjectManagerIF.h"
#include "PusVerificationReport.h"
#include "../objectmanager/ObjectManagerIF.h"
namespace Factory{
void setStaticFrameworkObjectIds();
}
/**
* @brief This helper object is used to forward verification messages
* which are generated by the Flight Software Framework.
* @details
* The messages can be relayed to an arbitrary object, for example a dedicated
* Verification Reporter. The destination is set by setting the static framework
* Id VerificationReporter::messageReceiver. The default verification reporter
* will be the PUS service 1, which sends verification messages according
* to the PUS standard.
*
*/
class VerificationReporter {
friend void (Factory::setStaticFrameworkObjectIds)();
public:
VerificationReporter();
virtual ~VerificationReporter();
void sendSuccessReport( uint8_t set_report_id, TcPacketBase* current_packet, uint8_t set_step = 0 );
void sendSuccessReport(uint8_t set_report_id, uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, uint8_t set_step = 0);
void sendFailureReport( uint8_t report_id, TcPacketBase* current_packet, ReturnValue_t error_code = 0,
uint8_t step = 0, uint32_t parameter1 = 0, uint32_t parameter2 = 0 );
void sendSuccessReport( uint8_t set_report_id, TcPacketBase* current_packet,
uint8_t set_step = 0 );
void sendSuccessReport(uint8_t set_report_id, uint8_t ackFlags,
uint16_t tcPacketId, uint16_t tcSequenceControl,
uint8_t set_step = 0);
void sendFailureReport( uint8_t report_id, TcPacketBase* current_packet,
ReturnValue_t error_code = 0,
uint8_t step = 0, uint32_t parameter1 = 0,
uint32_t parameter2 = 0 );
void sendFailureReport(uint8_t report_id,
uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, ReturnValue_t error_code = 0, uint8_t step = 0,
uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl,
ReturnValue_t error_code = 0, uint8_t step = 0,
uint32_t parameter1 = 0, uint32_t parameter2 = 0);
void initialize();
private:
static object_id_t messageReceiver;
MessageQueueId_t acknowledgeQueue;
};
#endif /* VERIFICATIONREPORTER_H_ */
#endif /* FSFW_TMTCSERVICES_VERIFICATIONREPORTER_H_ */