Merge branch 'mueller_framework' into front_branch

This commit is contained in:
Robin Müller 2020-06-19 20:48:35 +02:00
commit 65c775b83c
43 changed files with 720 additions and 379 deletions

View File

@ -1,5 +1,5 @@
#ifndef ARRAYLIST_H_ #ifndef FRAMEWORK_CONTAINER_ARRAYLIST_H_
#define ARRAYLIST_H_ #define FRAMEWORK_CONTAINER_ARRAYLIST_H_
#include <framework/returnvalues/HasReturnvaluesIF.h> #include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/serialize/SerializeAdapter.h> #include <framework/serialize/SerializeAdapter.h>
@ -7,8 +7,9 @@
/** /**
* @brief A List that stores its values in an array. * @brief A List that stores its values in an array.
* @details The backend is an array that can be allocated * @details
* by the class itself or supplied via ctor. * The underlying storage is an array that can be allocated by the class
* itself or supplied via ctor.
* *
* @ingroup container * @ingroup container
*/ */
@ -19,81 +20,13 @@ public:
static const uint8_t INTERFACE_ID = CLASS_ID::ARRAY_LIST; static const uint8_t INTERFACE_ID = CLASS_ID::ARRAY_LIST;
static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01); static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01);
/** /**
* An Iterator to go trough an ArrayList * Copying is forbiden by declaring copy ctor and copy assignment deleted
* * It is too ambigous in this case.
* It stores a pointer to an element and increments the * (Allocate a new backend? Use the same? What to do in an modifying call?)
* pointer when incremented itself. */
*/ ArrayList(const ArrayList& other) = delete;
class Iterator { const ArrayList& operator=(const ArrayList& other) = delete;
public:
/**
* Empty ctor, points to NULL
*/
Iterator() :
value(0) {
}
/**
* Initializes the Iterator to point to an element
*
* @param initialize
*/
Iterator(T *initialize) {
value = initialize;
}
/**
* The current element the iterator points to
*/
T *value;
Iterator& operator++() {
value++;
return *this;
}
Iterator operator++(int) {
Iterator tmp(*this);
operator++();
return tmp;
}
Iterator& operator--() {
value--;
return *this;
}
Iterator operator--(int) {
Iterator tmp(*this);
operator--();
return tmp;
}
T operator*() {
return *value;
}
T *operator->() {
return value;
}
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);
}
//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 * Number of Elements stored in this List
@ -134,6 +67,78 @@ public:
} }
} }
/**
* An Iterator to go trough an ArrayList
*
* It stores a pointer to an element and increments the
* pointer when incremented itself.
*/
class Iterator {
public:
/**
* Empty ctor, points to NULL
*/
Iterator(): value(0) {}
/**
* Initializes the Iterator to point to an element
*
* @param initialize
*/
Iterator(T *initialize) {
value = initialize;
}
/**
* The current element the iterator points to
*/
T *value;
Iterator& operator++() {
value++;
return *this;
}
Iterator operator++(int) {
Iterator tmp(*this);
operator++();
return tmp;
}
Iterator& operator--() {
value--;
return *this;
}
Iterator operator--(int) {
Iterator tmp(*this);
operator--();
return tmp;
}
T operator*() {
return *value;
}
T *operator->() {
return value;
}
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);
}
//SHOULDDO this should be implemented as non-member
bool operator!=(const typename ArrayList<T, count_t>::Iterator& other) const {
return !(*this == other);
}
};
/** /**
* Iterator pointing to the first stored elmement * Iterator pointing to the first stored elmement
* *
@ -223,19 +228,6 @@ public:
return (maxSize_ - size); return (maxSize_ - size);
} }
private:
/**
* This is the copy constructor
*
* It is private, as copying is too ambigous in this case. (Allocate a new backend? Use the same?
* What to do in an modifying call?)
*
* @param other
*/
ArrayList(const ArrayList& other) :
size(other.size), entries(other.entries), maxSize_(other.maxSize_),
allocated(false) {}
protected: protected:
/** /**
* pointer to the array in which the entries are stored * pointer to the array in which the entries are stored

View File

@ -8,13 +8,11 @@ template<typename T, typename count_t = uint8_t>
class HybridIterator: public LinkedElement<T>::Iterator, class HybridIterator: public LinkedElement<T>::Iterator,
public ArrayList<T, count_t>::Iterator { public ArrayList<T, count_t>::Iterator {
public: public:
HybridIterator() : HybridIterator() {}
value(NULL), linked(NULL), end(NULL) {
}
HybridIterator(typename LinkedElement<T>::Iterator *iter) : HybridIterator(typename LinkedElement<T>::Iterator *iter) :
LinkedElement<T>::Iterator(*iter), value( LinkedElement<T>::Iterator(*iter), value(iter->value),
iter->value), linked(true), end(NULL) { linked(true) {
} }
@ -66,11 +64,11 @@ public:
return tmp; return tmp;
} }
bool operator==(HybridIterator other) { bool operator==(const HybridIterator& other) {
return value == other.value; return value == other.value;
} }
bool operator!=(HybridIterator other) { bool operator!=(const HybridIterator& other) {
return !(*this == other); return !(*this == other);
} }
@ -82,11 +80,11 @@ public:
return value; return value;
} }
T* value; T* value = nullptr;
private: private:
bool linked; bool linked = false;
T *end; T *end = nullptr;
}; };
#endif /* HYBRIDITERATOR_H_ */ #endif /* HYBRIDITERATOR_H_ */

View File

@ -2,12 +2,14 @@
#define FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_ #define FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_
#include <framework/returnvalues/HasReturnvaluesIF.h> #include <framework/returnvalues/HasReturnvaluesIF.h>
#include <cstddef>
template<uint8_t N_READ_PTRS = 1> template<uint8_t N_READ_PTRS = 1>
class RingBufferBase { class RingBufferBase {
public: public:
RingBufferBase(uint32_t startAddress, uint32_t size, bool overwriteOld) : RingBufferBase(uint32_t startAddress, const size_t size, bool overwriteOld) :
start(startAddress), write(startAddress), size(size), overwriteOld(overwriteOld) { start(startAddress), write(startAddress), size(size),
overwriteOld(overwriteOld) {
for (uint8_t count = 0; count < N_READ_PTRS; count++) { for (uint8_t count = 0; count < N_READ_PTRS; count++) {
read[count] = startAddress; read[count] = startAddress;
} }
@ -83,7 +85,7 @@ protected:
const uint32_t start; const uint32_t start;
uint32_t write; uint32_t write;
uint32_t read[N_READ_PTRS]; uint32_t read[N_READ_PTRS];
const uint32_t size; const size_t size;
const bool overwriteOld; const bool overwriteOld;
void incrementWrite(uint32_t amount) { void incrementWrite(uint32_t amount) {
write = ((write + amount - start) % size) + start; write = ((write + amount - start) % size) + start;

View File

@ -1,11 +1,16 @@
#include <framework/container/SimpleRingBuffer.h> #include <framework/container/SimpleRingBuffer.h>
#include <string.h> #include <cstring>
SimpleRingBuffer::SimpleRingBuffer(uint32_t size, bool overwriteOld) : SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld) :
RingBufferBase<>(0, size, overwriteOld), buffer(NULL) { RingBufferBase<>(0, size, overwriteOld) {
buffer = new uint8_t[size]; buffer = new uint8_t[size];
} }
SimpleRingBuffer::SimpleRingBuffer(uint8_t *buffer, const size_t size,
bool overwriteOld):
RingBufferBase<>(0, size, overwriteOld), buffer(buffer) {}
SimpleRingBuffer::~SimpleRingBuffer() { SimpleRingBuffer::~SimpleRingBuffer() {
delete[] buffer; delete[] buffer;
} }
@ -66,3 +71,4 @@ ReturnValue_t SimpleRingBuffer::deleteData(uint32_t amount,
incrementRead(amount, READ_PTR); incrementRead(amount, READ_PTR);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -5,13 +5,29 @@
#include <stddef.h> #include <stddef.h>
/** /**
* @brief Circular buffer implementation, useful for buffering into data streams. * @brief Circular buffer implementation, useful for buffering
* @details Note that the deleteData() has to be called to increment the read pointer * into data streams.
* @details
* Note that the deleteData() has to be called to increment the read pointer.
* This class allocated dynamically, so
* @ingroup containers * @ingroup containers
*/ */
class SimpleRingBuffer: public RingBufferBase<> { class SimpleRingBuffer: public RingBufferBase<> {
public: public:
SimpleRingBuffer(uint32_t size, bool overwriteOld); /**
* This constructor allocates a new internal buffer with the supplied size.
* @param size
* @param overwriteOld
*/
SimpleRingBuffer(const size_t size, bool overwriteOld);
/**
* This constructor takes an external buffer with the specified size.
* @param buffer
* @param size
* @param overwriteOld
*/
SimpleRingBuffer(uint8_t* buffer, const size_t size, bool overwriteOld);
virtual ~SimpleRingBuffer(); virtual ~SimpleRingBuffer();
/** /**
@ -30,7 +46,8 @@ public:
* @param trueAmount * @param trueAmount
* @return * @return
*/ */
ReturnValue_t readData(uint8_t* data, uint32_t amount, bool readRemaining = false, uint32_t* trueAmount = NULL); ReturnValue_t readData(uint8_t* data, uint32_t amount,
bool readRemaining = false, uint32_t* trueAmount = nullptr);
/** /**
* Delete data starting by incrementing read pointer * Delete data starting by incrementing read pointer
@ -39,11 +56,12 @@ public:
* @param trueAmount * @param trueAmount
* @return * @return
*/ */
ReturnValue_t deleteData(uint32_t amount, bool deleteRemaining = false, uint32_t* trueAmount = NULL); ReturnValue_t deleteData(uint32_t amount, bool deleteRemaining = false,
uint32_t* trueAmount = nullptr);
private: private:
// static const uint8_t TEMP_READ_PTR = 1; // static const uint8_t TEMP_READ_PTR = 1;
static const uint8_t READ_PTR = 0; static const uint8_t READ_PTR = 0;
uint8_t* buffer; uint8_t* buffer = nullptr;
}; };
#endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */ #endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */

View File

@ -1,8 +1,9 @@
#ifndef SINGLYLINKEDLIST_H_ #ifndef FRAMEWORK_CONTAINER_SINGLYLINKEDLIST_H_
#define SINGLYLINKEDLIST_H_ #define FRAMEWORK_CONTAINER_SINGLYLINKEDLIST_H_
#include <cstddef>
#include <cstdint>
#include <stddef.h>
#include <stdint.h>
/** /**
* @brief Linked list data structure, * @brief Linked list data structure,
* each entry has a pointer to the next entry (singly) * each entry has a pointer to the next entry (singly)
@ -14,11 +15,8 @@ public:
T *value; T *value;
class Iterator { class Iterator {
public: public:
LinkedElement<T> *value; LinkedElement<T> *value = nullptr;
Iterator() : Iterator() {}
value(NULL) {
}
Iterator(LinkedElement<T> *element) : Iterator(LinkedElement<T> *element) :
value(element) { value(element) {
@ -47,12 +45,11 @@ public:
} }
}; };
LinkedElement(T* setElement, LinkedElement<T>* setNext = NULL) : value(setElement), LinkedElement(T* setElement, LinkedElement<T>* setNext = nullptr):
next(setNext) { value(setElement), next(setNext) {}
}
virtual ~LinkedElement(){ virtual ~LinkedElement(){}
}
virtual LinkedElement* getNext() const { virtual LinkedElement* getNext() const {
return next; return next;
} }
@ -61,15 +58,15 @@ public:
this->next = next; this->next = next;
} }
void setEnd() { virtual void setEnd() {
this->next = nullptr; this->next = nullptr;
} }
LinkedElement* begin() { LinkedElement* begin() {
return this; return this;
} }
LinkedElement* end() { LinkedElement* end() {
return NULL; return nullptr;
} }
private: private:
LinkedElement *next; LinkedElement *next;
@ -78,21 +75,21 @@ private:
template<typename T> template<typename T>
class SinglyLinkedList { class SinglyLinkedList {
public: public:
SinglyLinkedList() : using ElementIterator = typename LinkedElement<T>::Iterator;
start(NULL) {
} SinglyLinkedList() {}
SinglyLinkedList(ElementIterator start) :
start(start.value) {}
SinglyLinkedList(typename LinkedElement<T>::Iterator start) :
start(start.value) {
}
SinglyLinkedList(LinkedElement<T>* startElement) : SinglyLinkedList(LinkedElement<T>* startElement) :
start(startElement) { start(startElement) {}
}
typename LinkedElement<T>::Iterator begin() const { ElementIterator begin() const {
return LinkedElement<T>::Iterator::Iterator(start); return ElementIterator::Iterator(start);
} }
typename LinkedElement<T>::Iterator::Iterator end() const { typename ElementIterator::Iterator end() const {
return LinkedElement<T>::Iterator::Iterator(); return ElementIterator::Iterator();
} }
uint32_t getSize() const { uint32_t getSize() const {
@ -107,8 +104,15 @@ public:
void setStart(LinkedElement<T>* setStart) { void setStart(LinkedElement<T>* setStart) {
start = setStart; start = setStart;
} }
void setEnd(LinkedElement<T>* setEnd) {
setEnd->setEnd();
}
// SHOULDDO: Insertion operation ?
protected: protected:
LinkedElement<T> *start; LinkedElement<T> *start = nullptr;
}; };
#endif /* SINGLYLINKEDLIST_H_ */ #endif /* SINGLYLINKEDLIST_H_ */

View File

@ -53,6 +53,10 @@ ReturnValue_t DataSetBase::read(uint32_t lockTimeout) {
return result; return result;
} }
uint16_t DataSetBase::getFillCount() const {
return fillCount;
}
ReturnValue_t DataSetBase::readVariable(uint16_t count) { ReturnValue_t DataSetBase::readVariable(uint16_t count) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
// These checks are often performed by the respective // These checks are often performed by the respective

View File

@ -101,8 +101,10 @@ public:
*/ */
virtual ReturnValue_t unlockDataPool() override; virtual ReturnValue_t unlockDataPool() override;
virtual uint16_t getFillCount() const;
/* SerializeIF implementations */ /* SerializeIF implementations */
ReturnValue_t serialize(uint8_t** buffer, size_t* size, virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
const size_t maxSize, bool bigEndian) const override; const size_t maxSize, bool bigEndian) const override;
virtual size_t getSerializedSize() const override; virtual size_t getSerializedSize() const override;
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,

View File

@ -43,6 +43,7 @@ public:
*/ */
virtual ReturnValue_t registerVariable(PoolVariableIF* variable) = 0; virtual ReturnValue_t registerVariable(PoolVariableIF* variable) = 0;
virtual uint16_t getFillCount() const = 0;
private: private:
/** /**
* @brief Most underlying data structures will have a pool like structure * @brief Most underlying data structures will have a pool like structure

View File

@ -1,16 +1,17 @@
#include <framework/datapoollocal/LocalDataPoolManager.h> #include <framework/datapoollocal/LocalDataPoolManager.h>
#include <framework/datapoollocal/LocalDataSet.h> #include <framework/datapoollocal/LocalDataSet.h>
#include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/objectmanager/frameworkObjects.h>
#include <framework/ipc/MutexFactory.h> #include <framework/ipc/MutexFactory.h>
#include <framework/ipc/MutexHelper.h> #include <framework/ipc/MutexHelper.h>
#include <framework/ipc/QueueFactory.h>
#include <array> #include <array>
LocalDataPoolManager::LocalDataPoolManager(OwnsLocalDataPoolIF* owner) { LocalDataPoolManager::LocalDataPoolManager(OwnsLocalDataPoolIF* owner,
uint32_t replyQueueDepth, bool appendValidityBuffer):
appendValidityBuffer(appendValidityBuffer) {
if(owner == nullptr) { if(owner == nullptr) {
sif::error << "HkManager: Invalid supplied owner!" << std::endl; sif::error << "HkManager: Invalid supplied owner!" << std::endl;
std::exit(0); return;
} }
this->owner = owner; this->owner = owner;
mutex = MutexFactory::instance()->createMutex(); mutex = MutexFactory::instance()->createMutex();
@ -23,6 +24,8 @@ LocalDataPoolManager::LocalDataPoolManager(OwnsLocalDataPoolIF* owner) {
sif::error << "LocalDataPoolManager::LocalDataPoolManager: " sif::error << "LocalDataPoolManager::LocalDataPoolManager: "
"Could not set IPC store." << std::endl; "Could not set IPC store." << std::endl;
} }
hkQueue = QueueFactory::instance()->createMessageQueue(replyQueueDepth,
HousekeepingMessage::HK_MESSAGE_SIZE);
} }
LocalDataPoolManager::~LocalDataPoolManager() {} LocalDataPoolManager::~LocalDataPoolManager() {}
@ -30,19 +33,35 @@ LocalDataPoolManager::~LocalDataPoolManager() {}
ReturnValue_t LocalDataPoolManager::initializeHousekeepingPoolEntriesOnce() { ReturnValue_t LocalDataPoolManager::initializeHousekeepingPoolEntriesOnce() {
if(not mapInitialized) { if(not mapInitialized) {
ReturnValue_t result = ReturnValue_t result =
owner->initializeHousekeepingPoolEntries(localDpMap); owner->initializePoolEntries(localDpMap);
if(result == HasReturnvaluesIF::RETURN_OK) { if(result == HasReturnvaluesIF::RETURN_OK) {
mapInitialized = true; mapInitialized = true;
} }
return result; return result;
} }
sif::warning << "HousekeepingManager: The map" << std::endl; sif::warning << "HousekeepingManager: The map should only be initialized "
"once!" << std::endl;
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage( ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(
HousekeepingMessage& message) { HousekeepingMessage& message) {
return HasReturnvaluesIF::RETURN_FAILED; Command_t command = message.getCommand();
switch(command) {
// I think those are the only commands which can be handled here..
case(HousekeepingMessage::ADD_HK_REPORT_STRUCT):
case(HousekeepingMessage::ADD_DIAGNOSTICS_REPORT_STRUCT):
// We should use OwnsLocalPoolDataIF to specify those functions..
return HasReturnvaluesIF::RETURN_OK;
case(HousekeepingMessage::REPORT_DIAGNOSTICS_REPORT_STRUCTURES):
case(HousekeepingMessage::REPORT_HK_REPORT_STRUCTURES):
return generateSetStructurePacket(message.getSid());
case(HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT):
case(HousekeepingMessage::GENERATE_ONE_DIAGNOSTICS_REPORT):
return generateHousekeepingPacket(message.getSid());
default:
return CommandMessageIF::UNKNOWN_COMMAND;
}
} }
ReturnValue_t LocalDataPoolManager::printPoolEntry( ReturnValue_t LocalDataPoolManager::printPoolEntry(
@ -51,7 +70,7 @@ ReturnValue_t LocalDataPoolManager::printPoolEntry(
if (poolIter == localDpMap.end()) { if (poolIter == localDpMap.end()) {
sif::debug << "HousekeepingManager::fechPoolEntry:" sif::debug << "HousekeepingManager::fechPoolEntry:"
" Pool entry not found." << std::endl; " Pool entry not found." << std::endl;
return OwnsLocalDataPoolIF::POOL_ENTRY_NOT_FOUND; return POOL_ENTRY_NOT_FOUND;
} }
poolIter->second->print(); poolIter->second->print();
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
@ -61,6 +80,15 @@ MutexIF* LocalDataPoolManager::getMutexHandle() {
return mutex; return mutex;
} }
void LocalDataPoolManager::setHkPacketDestination(
MessageQueueId_t destinationQueueId) {
this->currentHkPacketDestination = destinationQueueId;
}
const OwnsLocalDataPoolIF* LocalDataPoolManager::getOwner() const {
return owner;
}
ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid) { ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid) {
LocalDataSet* dataSetToSerialize = dynamic_cast<LocalDataSet*>( LocalDataSet* dataSetToSerialize = dynamic_cast<LocalDataSet*>(
owner->getDataSetHandle(sid)); owner->getDataSetHandle(sid));
@ -70,28 +98,84 @@ ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
store_address_t storeId; store_address_t storeId;
size_t hkSize = dataSetToSerialize->getSerializedSize(); ReturnValue_t result = serializeHkPacketIntoStore(&storeId,
uint8_t* storePtr = nullptr; dataSetToSerialize);
ReturnValue_t result = ipcStore->getFreeElement(&storeId, hkSize,&storePtr);
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "HousekeepingManager::generateHousekeepingPacket: "
"Could not get free element from IPC store." << std::endl;
return result; return result;
} }
size_t size = 0;
dataSetToSerialize->serialize(&storePtr, &size, hkSize, false); // and now we set a HK message and send it the HK packet destination.
// and now we have to set a HK message and send it the queue. MessageQueueMessage message;
return HasReturnvaluesIF::RETURN_OK; HousekeepingMessage hkMessage(&message);
hkMessage.setHkReportMessage(sid, storeId);
if(hkQueue == nullptr) {
return QUEUE_NOT_SET;
}
if(currentHkPacketDestination != MessageQueueIF::NO_QUEUE) {
result = hkQueue->sendMessage(currentHkPacketDestination, &hkMessage);
}
else {
result = hkQueue->sendToDefault(&hkMessage);
}
return result;
} }
void LocalDataPoolManager::setHkPacketQueue(MessageQueueIF *msgQueue) { ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid) {
this->hkPacketQueue = msgQueue; LocalDataSet* dataSet = dynamic_cast<LocalDataSet*>(
owner->getDataSetHandle(sid));
if(dataSet == nullptr) {
sif::warning << "HousekeepingManager::generateHousekeepingPacket:"
" Set ID not found" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
size_t expectedSize = dataSet->getFillCount() * sizeof(lp_id_t);
uint8_t* storePtr = nullptr;
store_address_t storeId;
ReturnValue_t result = ipcStore->getFreeElement(&storeId,
expectedSize,&storePtr);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "HousekeepingManager::generateHousekeepingPacket: "
"Could not get free element from IPC store." << std::endl;
return result;
}
size_t size = 0;
result = dataSet->serializeLocalPoolIds(&storePtr, &size,
expectedSize, false);
if(expectedSize != size) {
sif::error << "HousekeepingManager::generateSetStructurePacket: "
"Expected size is not equal to serialized size" << std::endl;
}
return result;
} }
void LocalDataPoolManager::setHkReplyQueue(MessageQueueIF *replyQueue) { ReturnValue_t LocalDataPoolManager::serializeHkPacketIntoStore(
this->hkReplyQueue = replyQueue; store_address_t *storeId, LocalDataSet* dataSet) {
size_t hkSize = dataSet->getSerializedSize();
uint8_t* storePtr = nullptr;
ReturnValue_t result = ipcStore->getFreeElement(storeId, hkSize,&storePtr);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "HousekeepingManager::generateHousekeepingPacket: "
"Could not get free element from IPC store." << std::endl;
return result;
}
size_t size = 0;
if(appendValidityBuffer) {
result = dataSet->serializeWithValidityBuffer(&storePtr,
&size, hkSize, false);
}
else {
result = dataSet->serialize(&storePtr, &size, hkSize, false);
}
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "HousekeepingManager::serializeHkPacketIntoStore: "
"Serialization proccess failed!" << std::endl;
}
return result;
} }
const OwnsLocalDataPoolIF* LocalDataPoolManager::getOwner() const {
return owner;
}

View File

@ -13,6 +13,8 @@
#include <map> #include <map>
class LocalDataSet;
/** /**
* @brief This class is the managing instance for local data pool. * @brief This class is the managing instance for local data pool.
* @details * @details
@ -37,8 +39,16 @@ class LocalDataPoolManager {
friend class LocalPoolVector; friend class LocalPoolVector;
friend class LocalDataSet; friend class LocalDataSet;
public: public:
static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING_MANAGER;
LocalDataPoolManager(OwnsLocalDataPoolIF* owner); static constexpr ReturnValue_t POOL_ENTRY_NOT_FOUND = MAKE_RETURN_CODE(0x0);
static constexpr ReturnValue_t POOL_ENTRY_TYPE_CONFLICT = MAKE_RETURN_CODE(0x1);
static constexpr ReturnValue_t QUEUE_NOT_SET = MAKE_RETURN_CODE(0x2);
//static constexpr ReturnValue_t SET_NOT_FOUND = MAKE_RETURN_CODE(0x3);
LocalDataPoolManager(OwnsLocalDataPoolIF* owner,
uint32_t replyQueueDepth = 20, bool appendValidityBuffer = true);
virtual~ LocalDataPoolManager(); virtual~ LocalDataPoolManager();
/* Copying forbidden */ /* Copying forbidden */
@ -46,6 +56,8 @@ public:
LocalDataPoolManager operator=(const LocalDataPoolManager&) = delete; LocalDataPoolManager operator=(const LocalDataPoolManager&) = delete;
ReturnValue_t generateHousekeepingPacket(sid_t sid); ReturnValue_t generateHousekeepingPacket(sid_t sid);
ReturnValue_t generateSetStructurePacket(sid_t sid);
ReturnValue_t handleHousekeepingMessage(HousekeepingMessage& message); ReturnValue_t handleHousekeepingMessage(HousekeepingMessage& message);
/** /**
@ -57,10 +69,7 @@ public:
ReturnValue_t initializeHousekeepingPoolEntriesOnce(); ReturnValue_t initializeHousekeepingPoolEntriesOnce();
//! Set the queue for HK packets, which are sent unrequested. //! Set the queue for HK packets, which are sent unrequested.
void setHkPacketQueue(MessageQueueIF* msgQueue); void setHkPacketDestination(MessageQueueId_t destinationQueueId);
//! Set the queue for replies. This can be set manually or by the owner
//! class if the manager if message are relayed by it.
void setHkReplyQueue(MessageQueueIF* replyQueue);
const OwnsLocalDataPoolIF* getOwner() const; const OwnsLocalDataPoolIF* getOwner() const;
@ -70,6 +79,10 @@ private:
//! This is the map holding the actual data. Should only be initialized //! This is the map holding the actual data. Should only be initialized
//! once ! //! once !
bool mapInitialized = false; bool mapInitialized = false;
//! This specifies whether a validity buffer is appended at the end
//! of generated housekeeping packets.
bool appendValidityBuffer = true;
LocalDataPool localDpMap; LocalDataPool localDpMap;
//! Every housekeeping data manager has a mutex to protect access //! Every housekeeping data manager has a mutex to protect access
@ -79,13 +92,14 @@ private:
//! The class which actually owns the manager (and its datapool). //! The class which actually owns the manager (and its datapool).
OwnsLocalDataPoolIF* owner = nullptr; OwnsLocalDataPoolIF* owner = nullptr;
//! Used for replies. //! Queue used for communication, for example commands.
//! (maybe we dont need this, the sender can be retrieved from command //! Is also used to send messages.
//! message..) MessageQueueIF* hkQueue = nullptr;
MessageQueueIF* hkReplyQueue = nullptr;
//! Used for HK packets, which are generated without requests. //! HK replies will always be a reply to the commander, but HK packet
//! Maybe this will just be the TM funnel. //! can be sent to another destination by specifying this message queue
MessageQueueIF* hkPacketQueue = nullptr; //! ID, for example to a dedicated housekeeping service implementation.
MessageQueueId_t currentHkPacketDestination = MessageQueueIF::NO_QUEUE;
//! Global IPC store is used to store all packets. //! Global IPC store is used to store all packets.
StorageManagerIF* ipcStore = nullptr; StorageManagerIF* ipcStore = nullptr;
@ -113,6 +127,8 @@ private:
PoolEntry<T> **poolEntry); PoolEntry<T> **poolEntry);
void setMinimalSamplingFrequency(float frequencySeconds); void setMinimalSamplingFrequency(float frequencySeconds);
ReturnValue_t serializeHkPacketIntoStore(store_address_t* storeId,
LocalDataSet* dataSet);
}; };
@ -123,14 +139,14 @@ ReturnValue_t LocalDataPoolManager::fetchPoolEntry(lp_id_t localPoolId,
if (poolIter == localDpMap.end()) { if (poolIter == localDpMap.end()) {
sif::debug << "HousekeepingManager::fechPoolEntry:" sif::debug << "HousekeepingManager::fechPoolEntry:"
" Pool entry not found." << std::endl; " Pool entry not found." << std::endl;
return OwnsLocalDataPoolIF::POOL_ENTRY_NOT_FOUND; return POOL_ENTRY_NOT_FOUND;
} }
*poolEntry = dynamic_cast< PoolEntry<T>* >(poolIter->second); *poolEntry = dynamic_cast< PoolEntry<T>* >(poolIter->second);
if(*poolEntry == nullptr) { if(*poolEntry == nullptr) {
sif::debug << "HousekeepingManager::fetchPoolEntry:" sif::debug << "HousekeepingManager::fetchPoolEntry:"
" Pool entry not found." << std::endl; " Pool entry not found." << std::endl;
return OwnsLocalDataPoolIF::POOL_ENTRY_TYPE_CONFLICT; return POOL_ENTRY_TYPE_CONFLICT;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -1,22 +1,26 @@
#include <framework/datapoollocal/LocalDataPoolManager.h> #include <framework/datapoollocal/LocalDataPoolManager.h>
#include <framework/datapoollocal/LocalDataSet.h> #include <framework/datapoollocal/LocalDataSet.h>
#include <framework/serialize/SerializeAdapter.h>
#include <cmath>
#include <cstring>
LocalDataSet::LocalDataSet(OwnsLocalDataPoolIF *hkOwner): DataSetBase() { LocalDataSet::LocalDataSet(OwnsLocalDataPoolIF *hkOwner): DataSetBase() {
if(hkOwner != nullptr) { if(hkOwner == nullptr) {
hkManager = hkOwner->getHkManagerHandle(); sif::error << "LocalDataSet::LocalDataSet: Owner can't be nullptr!"
} << std::endl;
else { }
// config error, error output here. hkManager = hkOwner->getHkManagerHandle();
}
} }
LocalDataSet::LocalDataSet(object_id_t ownerId): DataSetBase() { LocalDataSet::LocalDataSet(object_id_t ownerId): DataSetBase() {
OwnsLocalDataPoolIF* hkOwner = objectManager->get<OwnsLocalDataPoolIF>( OwnsLocalDataPoolIF* hkOwner = objectManager->get<OwnsLocalDataPoolIF>(
ownerId); ownerId);
if(hkOwner == nullptr) { if(hkOwner == nullptr) {
// config error, error output here. sif::error << "LocalDataSet::LocalDataSet: Owner can't be nullptr!"
} << std::endl;
hkManager = hkOwner->getHkManagerHandle(); }
hkManager = hkOwner->getHkManagerHandle();
} }
LocalDataSet::~LocalDataSet() { LocalDataSet::~LocalDataSet() {
@ -27,9 +31,65 @@ ReturnValue_t LocalDataSet::lockDataPool(uint32_t timeoutMs) {
return mutex->lockMutex(timeoutMs); return mutex->lockMutex(timeoutMs);
} }
ReturnValue_t LocalDataSet::serializeWithValidityBuffer(uint8_t **buffer,
size_t *size, const size_t maxSize, bool bigEndian) const {
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
uint8_t validityMaskSize = std::ceil(static_cast<float>(fillCount)/8.0);
uint8_t validityMask[validityMaskSize];
uint8_t validBufferIndex = 0;
uint8_t validBufferIndexBit = 0;
for (uint16_t count = 0; count < fillCount; count++) {
if(registeredVariables[count]->isValid()) {
// set validity buffer here.
this->bitSetter(validityMask + validBufferIndex,
validBufferIndexBit, true);
if(validBufferIndexBit == 7) {
validBufferIndex ++;
validBufferIndexBit = 0;
}
else {
validBufferIndexBit ++;
}
}
result = registeredVariables[count]->serialize(buffer, size, maxSize,
bigEndian);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
}
// copy validity buffer to end
std::memcpy(*buffer, validityMask, validityMaskSize);
*size += validityMaskSize;
return result;
}
ReturnValue_t LocalDataSet::unlockDataPool() { ReturnValue_t LocalDataSet::unlockDataPool() {
MutexIF* mutex = hkManager->getMutexHandle(); MutexIF* mutex = hkManager->getMutexHandle();
return mutex->unlockMutex(); return mutex->unlockMutex();
} }
ReturnValue_t LocalDataSet::serializeLocalPoolIds(uint8_t** buffer,
size_t* size, const size_t maxSize, bool bigEndian) const {
for (uint16_t count = 0; count < fillCount; count++) {
lp_id_t currentPoolId = registeredVariables[count]->getDataPoolId();
auto result = AutoSerializeAdapter::serialize(&currentPoolId, buffer,
size, maxSize, bigEndian);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "LocalDataSet::serializeLocalPoolIds: Serialization"
" error!" << std::endl;
return result;
}
}
return HasReturnvaluesIF::RETURN_OK;
}
void LocalDataSet::bitSetter(uint8_t* byte, uint8_t position,
bool value) const {
if(position > 7) {
sif::debug << "Pool Raw Access: Bit setting invalid position" << std::endl;
return;
}
uint8_t shiftNumber = position + (7 - 2 * position);
*byte |= 1UL << shiftNumber;
}

View File

@ -55,6 +55,23 @@ public:
*/ */
~LocalDataSet(); ~LocalDataSet();
/**
* Special version of the serilization function which appends a
* validity buffer at the end. Each bit of this validity buffer
* denotes whether the container data set entries are valid from left
* to right, MSB first.
* @param buffer
* @param size
* @param maxSize
* @param bigEndian
* @param withValidityBuffer
* @return
*/
ReturnValue_t serializeWithValidityBuffer(uint8_t** buffer,
size_t* size, const size_t maxSize, bool bigEndian) const;
ReturnValue_t serializeLocalPoolIds(uint8_t** buffer,
size_t* size, const size_t maxSize, bool bigEndian) const;
protected: protected:
private: private:
/** /**
@ -79,6 +96,16 @@ private:
ReturnValue_t unlockDataPool() override; ReturnValue_t unlockDataPool() override;
LocalDataPoolManager* hkManager; LocalDataPoolManager* hkManager;
/**
* Sets the bit at the bit-position of a byte provided by its address
* to the specified value (zero or one).
* @param byte Pointer to byte to bitset.
* @param position MSB first, 0 to 7 possible.
* @param value Value to set.
* @return
*/
void bitSetter(uint8_t* byte, uint8_t position, bool value) const;
}; };
#endif /* FRAMEWORK_DATAPOOLLOCAL_LOCALDATASET_H_ */ #endif /* FRAMEWORK_DATAPOOLLOCAL_LOCALDATASET_H_ */

View File

@ -40,16 +40,38 @@ class OwnsLocalDataPoolIF {
public: public:
virtual~ OwnsLocalDataPoolIF() {}; virtual~ OwnsLocalDataPoolIF() {};
static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING; static constexpr uint8_t INTERFACE_ID = CLASS_ID::LOCAL_POOL_OWNER_IF;
static constexpr ReturnValue_t POOL_ENTRY_NOT_FOUND = MAKE_RETURN_CODE(0XA0);
static constexpr ReturnValue_t POOL_ENTRY_TYPE_CONFLICT = MAKE_RETURN_CODE(0xA1);
/** Command queue for housekeeping messages. */
virtual MessageQueueId_t getCommandQueue() const = 0; virtual MessageQueueId_t getCommandQueue() const = 0;
virtual ReturnValue_t initializeHousekeepingPoolEntries(
LocalDataPool& localDataPoolMap) = 0; /** Is used by pool owner to initialize the pool map once */
//virtual float setMinimalHkSamplingFrequency() = 0; virtual ReturnValue_t initializePoolEntries(
LocalDataPool& localDataPoolMap) = 0;
/** Can be used to get a handle to the local data pool manager. */
virtual LocalDataPoolManager* getHkManagerHandle() = 0; virtual LocalDataPoolManager* getHkManagerHandle() = 0;
/**
* This function is used by the pool manager to get a valid dataset
* from a SID
* @param sid Corresponding structure ID
* @return
*/
virtual DataSetIF* getDataSetHandle(sid_t sid) = 0; virtual DataSetIF* getDataSetHandle(sid_t sid) = 0;
/* These function can be implemented by pool owner, as they are required
* by the housekeeping message interface */
virtual ReturnValue_t addDataSet(sid_t sid) {
return HasReturnvaluesIF::RETURN_FAILED;
};
virtual ReturnValue_t removeDataSet(sid_t sid) {
return HasReturnvaluesIF::RETURN_FAILED;
};
virtual ReturnValue_t changeCollectionInterval(sid_t sid,
dur_seconds_t newInterval) {
return HasReturnvaluesIF::RETURN_FAILED;
};
}; };
#endif /* FRAMEWORK_DATAPOOL_HASHKPOOLPARAMETERSIF_H_ */ #endif /* FRAMEWORK_DATAPOOL_HASHKPOOLPARAMETERSIF_H_ */

View File

@ -72,7 +72,7 @@ public:
* by implementing and calling related drivers or wrapper functions. * by implementing and calling related drivers or wrapper functions.
* @param cookie * @param cookie
* @param data * @param data
* @param len * @param len If this is 0, nothing shall be sent.
* @return * @return
* - @c RETURN_OK for successfull send * - @c RETURN_OK for successfull send
* - Everything else triggers failure event with returnvalue as parameter 1 * - Everything else triggers failure event with returnvalue as parameter 1

View File

@ -1350,7 +1350,7 @@ void DeviceHandlerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {
} }
void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task_){ void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task_){
executingTask = task_; executingTask = task_;
} }
// Default implementations empty. // Default implementations empty.
@ -1360,7 +1360,7 @@ void DeviceHandlerBase::debugInterface(uint8_t positionTracker,
void DeviceHandlerBase::performOperationHook() { void DeviceHandlerBase::performOperationHook() {
} }
ReturnValue_t DeviceHandlerBase::initializeHousekeepingPoolEntries( ReturnValue_t DeviceHandlerBase::initializePoolEntries(
LocalDataPool &localDataPoolMap) { LocalDataPool &localDataPoolMap) {
return RETURN_OK; return RETURN_OK;
} }
@ -1369,6 +1369,19 @@ LocalDataPoolManager* DeviceHandlerBase::getHkManagerHandle() {
return &hkManager; return &hkManager;
} }
ReturnValue_t DeviceHandlerBase::addDataSet(sid_t sid) {
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t DeviceHandlerBase::removeDataSet(sid_t sid) {
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t DeviceHandlerBase::changeCollectionInterval(sid_t sid,
dur_seconds_t newInterval) {
return HasReturnvaluesIF::RETURN_OK;
}
DataSetIF* DeviceHandlerBase::getDataSetHandle(sid_t sid) { DataSetIF* DeviceHandlerBase::getDataSetHandle(sid_t sid) {
auto iter = deviceReplyMap.find(sid.ownerSetId); auto iter = deviceReplyMap.find(sid.ownerSetId);
if(iter != deviceReplyMap.end()) { if(iter != deviceReplyMap.end()) {

View File

@ -477,12 +477,17 @@ protected:
* @param localDataPoolMap * @param localDataPoolMap
* @return * @return
*/ */
virtual ReturnValue_t initializeHousekeepingPoolEntries( virtual ReturnValue_t initializePoolEntries(
LocalDataPool& localDataPoolMap) override; LocalDataPool& localDataPoolMap) override;
/** Get the HK manager object handle */ /** Get the HK manager object handle */
virtual LocalDataPoolManager* getHkManagerHandle() override; virtual LocalDataPoolManager* getHkManagerHandle() override;
virtual ReturnValue_t addDataSet(sid_t sid) override;
virtual ReturnValue_t removeDataSet(sid_t sid) override;
virtual ReturnValue_t changeCollectionInterval(sid_t sid,
dur_seconds_t newInterval) override;
/** /**
* @brief Hook function for child handlers which is called once per * @brief Hook function for child handlers which is called once per
* performOperation(). Default implementation is empty. * performOperation(). Default implementation is empty.
@ -703,7 +708,9 @@ protected:
bool switchOffWasReported; //!< Indicates if SWITCH_WENT_OFF was already thrown. bool switchOffWasReported; //!< Indicates if SWITCH_WENT_OFF was already thrown.
PeriodicTaskIF* executingTask = nullptr;//!< Pointer to the task which executes this component, is invalid before setTaskIF was called. //! Pointer to the task which executes this component, is invalid
//! before setTaskIF was called.
PeriodicTaskIF* executingTask = nullptr;
static object_id_t powerSwitcherId; //!< Object which switches power on and off. static object_id_t powerSwitcherId; //!< Object which switches power on and off.

View File

@ -8,13 +8,16 @@
const uint16_t EventManager::POOL_SIZES[N_POOLS] = { const uint16_t EventManager::POOL_SIZES[N_POOLS] = {
sizeof(EventMatchTree::Node), sizeof(EventIdRangeMatcher), sizeof(EventMatchTree::Node), sizeof(EventIdRangeMatcher),
sizeof(ReporterRangeMatcher) }; sizeof(ReporterRangeMatcher) };
//If one checks registerListener calls, there are around 40 (to max 50) objects registering for certain events. // If one checks registerListener calls, there are around 40 (to max 50)
//Each listener requires 1 or 2 EventIdMatcher and 1 or 2 ReportRangeMatcher. So a good guess is 75 to a max of 100 pools required for each, which fits well. // objects registering for certain events.
// Each listener requires 1 or 2 EventIdMatcher and 1 or 2 ReportRangeMatcher.
// So a good guess is 75 to a max of 100 pools required for each, which fits well.
// SHOULDDO: Shouldn't this be in the config folder and passed via ctor?
const uint16_t EventManager::N_ELEMENTS[N_POOLS] = { 240, 120, 120 }; const uint16_t EventManager::N_ELEMENTS[N_POOLS] = { 240, 120, 120 };
EventManager::EventManager(object_id_t setObjectId) : EventManager::EventManager(object_id_t setObjectId) :
SystemObject(setObjectId), eventReportQueue(NULL), mutex(NULL), factoryBackend( SystemObject(setObjectId),
0, POOL_SIZES, N_ELEMENTS, false, true) { factoryBackend(0, POOL_SIZES, N_ELEMENTS, false, true) {
mutex = MutexFactory::instance()->createMutex(); mutex = MutexFactory::instance()->createMutex();
eventReportQueue = QueueFactory::instance()->createMessageQueue( eventReportQueue = QueueFactory::instance()->createMessageQueue(
MAX_EVENTS_PER_CYCLE, EventMessage::EVENT_MESSAGE_SIZE); MAX_EVENTS_PER_CYCLE, EventMessage::EVENT_MESSAGE_SIZE);
@ -130,20 +133,23 @@ void EventManager::printEvent(EventMessage* message) {
break; break;
default: default:
string = translateObject(message->getReporter()); string = translateObject(message->getReporter());
sif::error << "EVENT: "; sif::debug << "EventManager: ";
if (string != 0) { if (string != 0) {
sif::error << string; sif::debug << string;
} else {
sif::error << "0x" << std::hex << message->getReporter() << std::dec;
} }
sif::error << " reported " << translateEvents(message->getEvent()) << " (" else {
<< std::dec << message->getEventId() << ") " << std::endl; sif::debug << "0x" << std::hex << message->getReporter() << std::dec;
}
sif::error << std::hex << "P1 Hex: 0x" << message->getParameter1() << ", P1 Dec: " sif::debug << " reported " << translateEvents(message->getEvent())
<< std::dec << message->getParameter1() << std::endl; << " (" << std::dec << message->getEventId() << ") "
sif::error << std::hex << "P2 Hex: 0x" << message->getParameter2() << ", P2 Dec: " << std::endl;
<< std::dec << message->getParameter2() << std::endl;
sif::debug << std::hex << "P1 Hex: 0x" << message->getParameter1()
<< ", P1 Dec: " << std::dec << message->getParameter1()
<< std::endl;
sif::debug << std::hex << "P2 Hex: 0x" << message->getParameter2()
<< ", P2 Dec: " << std::dec << message->getParameter2()
<< std::endl;
break; break;
} }

View File

@ -36,11 +36,11 @@ public:
ReturnValue_t performOperation(uint8_t opCode); ReturnValue_t performOperation(uint8_t opCode);
protected: protected:
MessageQueueIF* eventReportQueue; MessageQueueIF* eventReportQueue = nullptr;
std::map<MessageQueueId_t, EventMatchTree> listenerList; std::map<MessageQueueId_t, EventMatchTree> listenerList;
MutexIF* mutex; MutexIF* mutex = nullptr;
static const uint8_t N_POOLS = 3; static const uint8_t N_POOLS = 3;
LocalPool<N_POOLS> factoryBackend; LocalPool<N_POOLS> factoryBackend;

View File

@ -4,8 +4,8 @@
HousekeepingMessage::HousekeepingMessage(MessageQueueMessageIF* message): HousekeepingMessage::HousekeepingMessage(MessageQueueMessageIF* message):
CommandMessageBase(message) { CommandMessageBase(message) {
if(message->getMaximumMessageSize() < HK_MESSAGE_SIZE) { if(message->getMaximumMessageSize() < HK_MESSAGE_SIZE) {
sif::error << "CommandMessage::ComandMessage: Passed message buffer" sif::error << "HousekeepingMessage::HousekeepingMessage: Passed "
" can not hold minimum "<< HK_MESSAGE_SIZE "message buffer can not hold minimum " << HK_MESSAGE_SIZE
<< " bytes!" << std::endl; << " bytes!" << std::endl;
return; return;
} }

View File

@ -36,8 +36,8 @@ union sid_t {
class HousekeepingMessage : public CommandMessageBase { class HousekeepingMessage : public CommandMessageBase {
public: public:
static constexpr size_t HK_MESSAGE_SIZE = sizeof(MessageQueueId_t) static constexpr size_t HK_MESSAGE_SIZE = CommandMessageIF::HEADER_SIZE +
+ sizeof(Command_t) + sizeof(sid_t) * sizeof(uint32_t); sizeof(sid_t) + sizeof(uint32_t);
/** /**
* The HK message is initialized with a pointer to a message which holds * The HK message is initialized with a pointer to a message which holds
@ -96,6 +96,7 @@ public:
void setParameter(uint32_t parameter); void setParameter(uint32_t parameter);
uint32_t getParameter() const; uint32_t getParameter() const;
sid_t getSid() const;
void setHkReportMessage(sid_t sid, store_address_t storeId); void setHkReportMessage(sid_t sid, store_address_t storeId);
void setHkDiagnosticsMessage(sid_t sid, store_address_t storeId); void setHkDiagnosticsMessage(sid_t sid, store_address_t storeId);
@ -106,7 +107,7 @@ public:
virtual size_t getMinimumMessageSize() const override; virtual size_t getMinimumMessageSize() const override;
virtual void clear() override; virtual void clear() override;
private: private:
sid_t getSid() const;
void setSid(sid_t sid); void setSid(sid_t sid);
virtual uint8_t* getData() override; virtual uint8_t* getData() override;

View File

@ -12,7 +12,7 @@ CommandMessage::CommandMessage(MessageQueueMessageIF* receiverMessage):
if(receiverMessage->getMaximumMessageSize() < if(receiverMessage->getMaximumMessageSize() <
getMinimumMessageSize()) { getMinimumMessageSize()) {
sif::error << "CommandMessage::ComandMessage: Passed message buffer" sif::error << "CommandMessage::ComandMessage: Passed message buffer"
" can not hold minimum "<< MINIMUM_COMMAND_MESSAGE_SIZE " can not hold minimum "<< getMinimumMessageSize()
<< " bytes!" << std::endl; << " bytes!" << std::endl;
return; return;
} }

View File

@ -1,6 +1,7 @@
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include "FixedTimeslotTask.h" #include "FixedTimeslotTask.h"
#include <framework/serviceinterface/ServiceInterfaceStream.h>
uint32_t FixedTimeslotTask::deadlineMissedCount = 0; uint32_t FixedTimeslotTask::deadlineMissedCount = 0;
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE; const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE;
@ -18,16 +19,19 @@ FixedTimeslotTask::~FixedTimeslotTask() {
void FixedTimeslotTask::taskEntryPoint(void* argument) { void FixedTimeslotTask::taskEntryPoint(void* argument) {
//The argument is re-interpreted as FixedTimeslotTask. The Task object is global, so it is found from any place. // The argument is re-interpreted as FixedTimeslotTask. The Task object is
// global, so it is found from any place.
FixedTimeslotTask *originalTask(reinterpret_cast<FixedTimeslotTask*>(argument)); FixedTimeslotTask *originalTask(reinterpret_cast<FixedTimeslotTask*>(argument));
// Task should not start until explicitly requested /* Task should not start until explicitly requested,
// in FreeRTOS, tasks start as soon as they are created if the scheduler is running * but in FreeRTOS, tasks start as soon as they are created if the scheduler
// but not if the scheduler is not running. * is running but not if the scheduler is not running.
// to be able to accommodate both cases we check a member which is set in #startTask() * To be able to accommodate both cases we check a member which is set in
// if it is not set and we get here, the scheduler was started before #startTask() was called and we need to suspend * #startTask(). If it is not set and we get here, the scheduler was started
// if it is set, the scheduler was not running before #startTask() was called and we can continue * before #startTask() was called and we need to suspend if it is set,
* the scheduler was not running before #startTask() was called and we
* can continue */
if (!originalTask->started) { if (not originalTask->started) {
vTaskSuspend(NULL); vTaskSuspend(NULL);
} }
@ -58,11 +62,6 @@ ReturnValue_t FixedTimeslotTask::startTask() {
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId,
uint32_t slotTimeMs, int8_t executionStep) { uint32_t slotTimeMs, int8_t executionStep) {
if (objectManager->get<ExecutableObjectIF>(componentId) != nullptr) { if (objectManager->get<ExecutableObjectIF>(componentId) != nullptr) {
if(slotTimeMs == 0) {
// FreeRTOS throws a sanity error for zero values, so we set
// the time to one millisecond.
slotTimeMs = 1;
}
pst.addSlot(componentId, slotTimeMs, executionStep, this); pst.addSlot(componentId, slotTimeMs, executionStep, this);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
@ -81,7 +80,8 @@ ReturnValue_t FixedTimeslotTask::checkSequence() const {
} }
void FixedTimeslotTask::taskFunctionality() { void FixedTimeslotTask::taskFunctionality() {
// A local iterator for the Polling Sequence Table is created to find the start time for the first entry. // A local iterator for the Polling Sequence Table is created to find the
// start time for the first entry.
SlotListIter slotListIter = pst.current; SlotListIter slotListIter = pst.current;
//The start time for the first entry is read. //The start time for the first entry is read.
@ -96,22 +96,37 @@ void FixedTimeslotTask::taskFunctionality() {
xLastWakeTime = xTaskGetTickCount(); xLastWakeTime = xTaskGetTickCount();
// wait for first entry's start time // wait for first entry's start time
vTaskDelayUntil(&xLastWakeTime, interval); if(interval > 0) {
vTaskDelayUntil(&xLastWakeTime, interval);
}
/* Enter the loop that defines the task behavior. */ /* Enter the loop that defines the task behavior. */
for (;;) { for (;;) {
//The component for this slot is executed and the next one is chosen. //The component for this slot is executed and the next one is chosen.
this->pst.executeAndAdvance(); this->pst.executeAndAdvance();
if (pst.slotFollowsImmediately()) { if (not pst.slotFollowsImmediately()) {
//Do nothing /* If all operations are finished and the difference of the
} else { * current time minus the last wake time is larger than the
// we need to wait before executing the current slot * expected wait period, a deadline was missed. */
//this gives us the time to wait: if(xTaskGetTickCount() - xLastWakeTime >=
intervalMs = this->pst.getIntervalToPreviousSlotMs(); pdMS_TO_TICKS(this->pst.getIntervalToPreviousSlotMs())) {
interval = pdMS_TO_TICKS(intervalMs); #ifdef DEBUG
vTaskDelayUntil(&xLastWakeTime, interval); sif::warning << "FixedTimeslotTask: " << pcTaskGetName(NULL) <<
//TODO deadline missed check " missed deadline!\n" << std::flush;
} #endif
if(deadlineMissedFunc != nullptr) {
this->deadlineMissedFunc();
}
// Continue immediately, no need to wait.
break;
}
// we need to wait before executing the current slot
//this gives us the time to wait:
intervalMs = this->pst.getIntervalToPreviousSlotMs();
interval = pdMS_TO_TICKS(intervalMs);
vTaskDelayUntil(&xLastWakeTime, interval);
}
} }
} }
@ -119,3 +134,4 @@ ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) {
vTaskDelay(pdMS_TO_TICKS(ms)); vTaskDelay(pdMS_TO_TICKS(ms));
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -1,12 +1,12 @@
#ifndef POLLINGTASK_H_ #ifndef FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_
#define POLLINGTASK_H_ #define FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_
#include <framework/devicehandlers/FixedSlotSequence.h> #include <framework/tasks/FixedSlotSequence.h>
#include <framework/tasks/FixedTimeslotTaskIF.h> #include <framework/tasks/FixedTimeslotTaskIF.h>
#include <framework/tasks/Typedef.h> #include <framework/tasks/Typedef.h>
#include <FreeRTOS.h> #include <freertos/FreeRTOS.h>
#include "task.h" #include <freertos/task.h>
class FixedTimeslotTask: public FixedTimeslotTaskIF { class FixedTimeslotTask: public FixedTimeslotTaskIF {
public: public:
@ -29,16 +29,18 @@ public:
/** /**
* @brief The destructor of the class. * @brief The destructor of the class.
* * @details
* @details The destructor frees all heap memory that was allocated on thread initialization for the PST and * The destructor frees all heap memory that was allocated on thread
* the device handlers. This is done by calling the PST's destructor. * initialization for the PST and the device handlers. This is done by
* calling the PST's destructor.
*/ */
virtual ~FixedTimeslotTask(void); virtual ~FixedTimeslotTask(void);
ReturnValue_t startTask(void); ReturnValue_t startTask(void);
/** /**
* This static function can be used as #deadlineMissedFunc. * This static function can be used as #deadlineMissedFunc.
* It counts missedDeadlines and prints the number of missed deadlines every 10th time. * It counts missedDeadlines and prints the number of missed deadlines
* every 10th time.
*/ */
static void missedDeadlineCounter(); static void missedDeadlineCounter();
/** /**
@ -47,13 +49,13 @@ public:
static uint32_t deadlineMissedCount; static uint32_t deadlineMissedCount;
ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs,
int8_t executionStep); int8_t executionStep) override;
uint32_t getPeriodMs() const; uint32_t getPeriodMs() const override;
ReturnValue_t checkSequence() const; ReturnValue_t checkSequence() const override;
ReturnValue_t sleepFor(uint32_t ms); ReturnValue_t sleepFor(uint32_t ms) override;
protected: protected:
bool started; bool started;
@ -62,30 +64,29 @@ protected:
FixedSlotSequence pst; FixedSlotSequence pst;
/** /**
* @brief This attribute holds a function pointer that is executed when a deadline was missed. * @brief This attribute holds a function pointer that is executed when
* * a deadline was missed.
* @details Another function may be announced to determine the actions to perform when a deadline was missed. * @details
* Currently, only one function for missing any deadline is allowed. * Another function may be announced to determine the actions to perform
* If not used, it shall be declared NULL. * when a deadline was missed. Currently, only one function for missing
* any deadline is allowed. If not used, it shall be declared NULL.
*/ */
void (*deadlineMissedFunc)(void); void (*deadlineMissedFunc)(void);
/** /**
* @brief This is the entry point in a new polling thread. * @brief This is the entry point for a new task.
* * @details
* @details This method, that is the generalOSAL::checkAndRestartPeriod( this->periodId, interval ); entry point in the new thread, is here set to generate * This method starts the task by calling taskFunctionality(), as soon as
* and link the Polling Sequence Table to the thread object and start taskFunctionality() * all requirements (task scheduler has started and startTask()
* on success. If operation of the task is ended for some reason, * has been called) are met.
* the destructor is called to free allocated memory.
*/ */
static void taskEntryPoint(void* argument); static void taskEntryPoint(void* argument);
/** /**
* @brief This function holds the main functionality of the thread. * @brief This function holds the main functionality of the thread.
* * @details
* * Core function holding the main functionality of the task
* @details Holding the main functionality of the task, this method is most important. * It links the functionalities provided by FixedSlotSequence with the
* It links the functionalities provided by FixedSlotSequence with the OS's System Calls * OS's System Calls to keep the timing of the periods.
* to keep the timing of the periods.
*/ */
void taskFunctionality(void); void taskFunctionality(void);
}; };

View File

@ -12,8 +12,8 @@ PeriodicTask::PeriodicTask(const char *name, TaskPriority setPriority,
BaseType_t status = xTaskCreate(taskEntryPoint, name, BaseType_t status = xTaskCreate(taskEntryPoint, name,
setStack, this, setPriority, &handle); setStack, this, setPriority, &handle);
if(status != pdPASS){ if(status != pdPASS){
sif::debug << "PeriodicTask Insufficient heap memory remaining. Status: " sif::debug << "PeriodicTask Insufficient heap memory remaining. "
<< status << std::endl; "Status: " << status << std::endl;
} }
} }
@ -23,14 +23,17 @@ PeriodicTask::~PeriodicTask(void) {
} }
void PeriodicTask::taskEntryPoint(void* argument) { void PeriodicTask::taskEntryPoint(void* argument) {
//The argument is re-interpreted as PeriodicTask. The Task object is global, so it is found from any place. // The argument is re-interpreted as PeriodicTask. The Task object is
// global, so it is found from any place.
PeriodicTask *originalTask(reinterpret_cast<PeriodicTask*>(argument)); PeriodicTask *originalTask(reinterpret_cast<PeriodicTask*>(argument));
// Task should not start until explicitly requested /* Task should not start until explicitly requested,
// in FreeRTOS, tasks start as soon as they are created if the scheduler is running * but in FreeRTOS, tasks start as soon as they are created if the scheduler
// but not if the scheduler is not running. * is running but not if the scheduler is not running.
// to be able to accommodate both cases we check a member which is set in #startTask() * To be able to accommodate both cases we check a member which is set in
// if it is not set and we get here, the scheduler was started before #startTask() was called and we need to suspend * #startTask(). If it is not set and we get here, the scheduler was started
// if it is set, the scheduler was not running before #startTask() was called and we can continue * before #startTask() was called and we need to suspend if it is set,
* the scheduler was not running before #startTask() was called and we
* can continue */
if (not originalTask->started) { if (not originalTask->started) {
vTaskSuspend(NULL); vTaskSuspend(NULL);
@ -61,38 +64,45 @@ void PeriodicTask::taskFunctionality() {
TickType_t xLastWakeTime; TickType_t xLastWakeTime;
const TickType_t xPeriod = pdMS_TO_TICKS(this->period * 1000.); const TickType_t xPeriod = pdMS_TO_TICKS(this->period * 1000.);
/* The xLastWakeTime variable needs to be initialized with the current tick /* The xLastWakeTime variable needs to be initialized with the current tick
count. Note that this is the only time the variable is written to explicitly. count. Note that this is the only time the variable is written to
After this assignment, xLastWakeTime is updated automatically internally within explicitly. After this assignment, xLastWakeTime is updated automatically
vTaskDelayUntil(). */ internally within vTaskDelayUntil(). */
xLastWakeTime = xTaskGetTickCount(); xLastWakeTime = xTaskGetTickCount();
/* Enter the loop that defines the task behavior. */ /* Enter the loop that defines the task behavior. */
for (;;) { for (;;) {
for (ObjectList::iterator it = objectList.begin(); for (auto const& object: objectList) {
it != objectList.end(); ++it) { object->performOperation();
(*it)->performOperation();
} }
/* If all operations are finished and the difference of the /* If all operations are finished and the difference of the
* current time minus the last wake time is larger than the * current time minus the last wake time is larger than the
* wait period, a deadline was missed. */ * wait period, a deadline was missed. */
if(xTaskGetTickCount() - xLastWakeTime >= xPeriod) { if(xTaskGetTickCount() - xLastWakeTime >= xPeriod) {
#ifdef DEBUG
sif::warning << "PeriodicTask: " << pcTaskGetName(NULL) << sif::warning << "PeriodicTask: " << pcTaskGetName(NULL) <<
" missed deadline!\n" << std::flush; " missed deadline!\n" << std::flush;
#endif
if(deadlineMissedFunc != nullptr) { if(deadlineMissedFunc != nullptr) {
this->deadlineMissedFunc(); this->deadlineMissedFunc();
} }
} }
vTaskDelayUntil(&xLastWakeTime, xPeriod); vTaskDelayUntil(&xLastWakeTime, xPeriod);
} }
} }
ReturnValue_t PeriodicTask::addComponent(object_id_t object) { ReturnValue_t PeriodicTask::addComponent(object_id_t object, bool setTaskIF) {
ExecutableObjectIF* newObject = objectManager->get<ExecutableObjectIF>( ExecutableObjectIF* newObject = objectManager->get<ExecutableObjectIF>(
object); object);
if (newObject == NULL) { if (newObject == nullptr) {
sif::error << "PeriodicTask::addComponent: Invalid object. Make sure"
"it implement ExecutableObjectIF" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
if(setTaskIF) {
newObject->setTaskIF(this);
}
objectList.push_back(newObject); objectList.push_back(newObject);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -5,10 +5,8 @@
#include <framework/tasks/PeriodicTaskIF.h> #include <framework/tasks/PeriodicTaskIF.h>
#include <framework/tasks/Typedef.h> #include <framework/tasks/Typedef.h>
extern "C" {
#include <freertos/FreeRTOS.h> #include <freertos/FreeRTOS.h>
#include <freertos/task.h> #include <freertos/task.h>
}
#include <vector> #include <vector>
@ -22,7 +20,9 @@ class ExecutableObjectIF;
class PeriodicTask: public PeriodicTaskIF { class PeriodicTask: public PeriodicTaskIF {
public: public:
/** /**
* @brief Standard constructor of the class. * Keep in Mind that you need to call before this vTaskStartScheduler()!
* A lot of task parameters are set in "FreeRTOSConfig.h".
* TODO: why does this need to be called before vTaskStartScheduler?
* @details * @details
* The class is initialized without allocated objects. * The class is initialized without allocated objects.
* These need to be added with #addComponent. * These need to be added with #addComponent.
@ -38,8 +38,9 @@ public:
* The function pointer to the deadline missed function that shall * The function pointer to the deadline missed function that shall
* be assigned. * be assigned.
*/ */
PeriodicTask(const char *name, TaskPriority setPriority, TaskStackSize setStack, PeriodicTask(const char *name, TaskPriority setPriority,
TaskPeriod setPeriod,void (*setDeadlineMissedFunc)()); TaskStackSize setStack, TaskPeriod setPeriod,
void (*setDeadlineMissedFunc)());
/** /**
* @brief Currently, the executed object's lifetime is not coupled with * @brief Currently, the executed object's lifetime is not coupled with
* the task object's lifetime, so the destructor is empty. * the task object's lifetime, so the destructor is empty.
@ -53,56 +54,66 @@ public:
* The address of the task object is passed as an argument * The address of the task object is passed as an argument
* to the system call. * to the system call.
*/ */
ReturnValue_t startTask(void); ReturnValue_t startTask() override;
/** /**
* Adds an object to the list of objects to be executed. * Adds an object to the list of objects to be executed.
* The objects are executed in the order added. * The objects are executed in the order added.
* @param object Id of the object to add. * @param object Id of the object to add.
* @return RETURN_OK on success, RETURN_FAILED if the object could not be added. * @return
* -@c RETURN_OK on success
* -@c RETURN_FAILED if the object could not be added.
*/ */
ReturnValue_t addComponent(object_id_t object); ReturnValue_t addComponent(object_id_t object,
bool setTaskIF = true) override;
uint32_t getPeriodMs() const; uint32_t getPeriodMs() const override;
ReturnValue_t sleepFor(uint32_t ms); ReturnValue_t sleepFor(uint32_t ms) override;
protected: protected:
bool started; bool started;
TaskHandle_t handle; TaskHandle_t handle;
typedef std::vector<ExecutableObjectIF*> ObjectList; //!< Typedef for the List of objects. //! Typedef for the List of objects.
typedef std::vector<ExecutableObjectIF*> ObjectList;
/** /**
* @brief This attribute holds a list of objects to be executed. * @brief This attribute holds a list of objects to be executed.
*/ */
ObjectList objectList; ObjectList objectList;
/** /**
* @brief The period of the task. * @brief The period of the task.
* @details The period determines the frequency of the task's execution. It is expressed in clock ticks. * @details
* The period determines the frequency of the task's execution.
* It is expressed in clock ticks.
*/ */
TaskPeriod period; TaskPeriod period;
/** /**
* @brief The pointer to the deadline-missed function. * @brief The pointer to the deadline-missed function.
* @details This pointer stores the function that is executed if the task's deadline is missed. * @details
* So, each may react individually on a timing failure. The pointer may be NULL, * This pointer stores the function that is executed if the task's deadline
* then nothing happens on missing the deadline. The deadline is equal to the next execution * is missed so each may react individually on a timing failure.
* of the periodic task. * The pointer may be NULL, then nothing happens on missing the deadline.
* The deadline is equal to the next execution of the periodic task.
*/ */
void (*deadlineMissedFunc)(void); void (*deadlineMissedFunc)(void);
/** /**
* @brief This is the function executed in the new task's context. * @brief This is the function executed in the new task's context.
* @details It converts the argument back to the thread object type and copies the class instance * @details
* to the task context. The taskFunctionality method is called afterwards. * It converts the argument back to the thread object type and copies the
* class instance to the task context. The taskFunctionality method is
* called afterwards.
* @param A pointer to the task object itself is passed as argument. * @param A pointer to the task object itself is passed as argument.
*/ */
static void taskEntryPoint(void* argument); static void taskEntryPoint(void* argument);
/** /**
* @brief The function containing the actual functionality of the task. * @brief The function containing the actual functionality of the task.
* @details The method sets and starts * @details
* the task's period, then enters a loop that is repeated as long as the isRunning * The method sets and starts the task's period, then enters a loop that is
* attribute is true. Within the loop, all performOperation methods of the added * repeated as long as the isRunning attribute is true. Within the loop,
* objects are called. Afterwards the checkAndRestartPeriod system call blocks the task * all performOperation methods of the added objects are called.
* until the next period. * Afterwards the checkAndRestartPeriod system call blocks the task until
* On missing the deadline, the deadlineMissedFunction is executed. * the next period.
* On missing the deadline, the deadlineMissedFunction is executed.
*/ */
void taskFunctionality(void); void taskFunctionality(void);
}; };

View File

@ -2,7 +2,7 @@
#define FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_ #define FRAMEWORK_OSAL_HOST_FIXEDTIMESLOTTASK_H_
#include <framework/objectmanager/ObjectManagerIF.h> #include <framework/objectmanager/ObjectManagerIF.h>
#include <framework/devicehandlers/FixedSlotSequence.h> #include <framework/tasks/FixedSlotSequence.h>
#include <framework/tasks/FixedTimeslotTaskIF.h> #include <framework/tasks/FixedTimeslotTaskIF.h>
#include <framework/tasks/Typedef.h> #include <framework/tasks/Typedef.h>

View File

@ -2,7 +2,7 @@
#define FRAMEWORK_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ #define FRAMEWORK_OSAL_LINUX_FIXEDTIMESLOTTASK_H_
#include <framework/tasks/FixedTimeslotTaskIF.h> #include <framework/tasks/FixedTimeslotTaskIF.h>
#include <framework/devicehandlers/FixedSlotSequence.h> #include <framework/tasks/FixedSlotSequence.h>
#include <framework/osal/linux/PosixThread.h> #include <framework/osal/linux/PosixThread.h>
#include <pthread.h> #include <pthread.h>

View File

@ -1,12 +1,13 @@
#include <framework/tasks/ExecutableObjectIF.h> #include <framework/tasks/ExecutableObjectIF.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h> #include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <errno.h>
#include <framework/osal/linux/PeriodicPosixTask.h> #include <framework/osal/linux/PeriodicPosixTask.h>
#include <errno.h>
PeriodicPosixTask::PeriodicPosixTask(const char* name_, int priority_, PeriodicPosixTask::PeriodicPosixTask(const char* name_, int priority_,
size_t stackSize_, uint32_t period_, void(deadlineMissedFunc_)()): size_t stackSize_, uint32_t period_, void(deadlineMissedFunc_)()):
PosixThread(name_,priority_,stackSize_),objectList(),started(false), PosixThread(name_, priority_, stackSize_), objectList(), started(false),
periodMs(period_),deadlineMissedFunc(deadlineMissedFunc_) { periodMs(period_), deadlineMissedFunc(deadlineMissedFunc_) {
} }
PeriodicPosixTask::~PeriodicPosixTask() { PeriodicPosixTask::~PeriodicPosixTask() {
@ -21,12 +22,18 @@ void* PeriodicPosixTask::taskEntryPoint(void* arg) {
return NULL; return NULL;
} }
ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object) { ReturnValue_t PeriodicPosixTask::addComponent(object_id_t object,
bool setTaskIF) {
ExecutableObjectIF* newObject = objectManager->get<ExecutableObjectIF>( ExecutableObjectIF* newObject = objectManager->get<ExecutableObjectIF>(
object); object);
if (newObject == NULL) { if (newObject == nullptr) {
sif::error << "PeriodicTask::addComponent: Invalid object. Make sure"
"it implements ExecutableObjectIF" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
if(setTaskIF) {
newObject->setTaskIF(this);
}
objectList.push_back(newObject); objectList.push_back(newObject);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -39,7 +39,8 @@ public:
* @param object Id of the object to add. * @param object Id of the object to add.
* @return RETURN_OK on success, RETURN_FAILED if the object could not be added. * @return RETURN_OK on success, RETURN_FAILED if the object could not be added.
*/ */
ReturnValue_t addComponent(object_id_t object); ReturnValue_t addComponent(object_id_t object,
bool setTaskIF = true) override;
uint32_t getPeriodMs() const; uint32_t getPeriodMs() const;

View File

@ -1,4 +1,4 @@
#include <framework/devicehandlers/FixedSequenceSlot.h> #include <framework/tasks/FixedSequenceSlot.h>
#include <framework/objectmanager/SystemObjectIF.h> #include <framework/objectmanager/SystemObjectIF.h>
#include <framework/osal/rtems/PollingTask.h> #include <framework/osal/rtems/PollingTask.h>
#include <framework/osal/rtems/RtemsBasic.h> #include <framework/osal/rtems/RtemsBasic.h>

View File

@ -1,7 +1,7 @@
#ifndef POLLINGTASK_H_ #ifndef POLLINGTASK_H_
#define POLLINGTASK_H_ #define POLLINGTASK_H_
#include <framework/devicehandlers/FixedSlotSequence.h> #include <framework/tasks/FixedSlotSequence.h>
#include <framework/tasks/FixedTimeslotTaskIF.h> #include <framework/tasks/FixedTimeslotTaskIF.h>
#include "TaskBase.h" #include "TaskBase.h"

View File

@ -61,8 +61,9 @@ enum {
MUTEX_IF, //MUX 55 MUTEX_IF, //MUX 55
MESSAGE_QUEUE_IF,//MQI 56 MESSAGE_QUEUE_IF,//MQI 56
SEMAPHORE_IF, //SPH 57 SEMAPHORE_IF, //SPH 57
HOUSEKEEPING, //HK 58 LOCAL_POOL_OWNER_IF, //LPIF 58
POOL_VARIABLE_IF, //PVA 59 POOL_VARIABLE_IF, //PVA 59
HOUSEKEEPING_MANAGER, //HKM 60
FW_CLASS_ID_COUNT //is actually count + 1 ! FW_CLASS_ID_COUNT //is actually count + 1 !
}; };

View File

@ -65,6 +65,21 @@
// No type specification necessary here. // No type specification necessary here.
class AutoSerializeAdapter { class AutoSerializeAdapter {
public: public:
/**
* Serialize object into buffer.
* @tparam T Type of object.
* @param object Object to serialize
* @param buffer
* Serialize into this buffer, pointer to pointer has to be passed,
* *buffer will be incremented automatically.
* @param size [out]
* Update passed size value, will be incremented by serialized size
* @param max_size
* Maximum size for range checking
* @param bigEndian
* Set to true if host-to-network conversion or vice-versa is needed
* @return
*/
template<typename T> template<typename T>
static ReturnValue_t serialize(const T* object, uint8_t** buffer, static ReturnValue_t serialize(const T* object, uint8_t** buffer,
size_t* size, const size_t max_size, bool bigEndian) { size_t* size, const size_t max_size, bool bigEndian) {

View File

@ -37,8 +37,10 @@ public:
/** /**
* @brief Function called during setup assignment of object to task * @brief Function called during setup assignment of object to task
* @details Has to be called from the function that assigns the object to a task and * @details
* enables the object implementation to overwrite this function and get a reference to the executing task * Has to be called from the function that assigns the object to a task and
* enables the object implementation to overwrite this function and get
* a reference to the executing task
* @param task_ Pointer to the taskIF of this task * @param task_ Pointer to the taskIF of this task
*/ */
virtual void setTaskIF(PeriodicTaskIF* task_) { virtual void setTaskIF(PeriodicTaskIF* task_) {

View File

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

View File

@ -1,22 +1,17 @@
/** #ifndef FRAMEWORK_TASKS_FIXEDSEQUENCESLOT_H_
* @file FixedSequenceSlot.h #define FRAMEWORK_TASKS_FIXEDSEQUENCESLOT_H_
* @brief This file defines the PollingSlot class.
* @date 19.12.2012
* @author baetz
*/
#ifndef FIXEDSEQUENCESLOT_H_
#define FIXEDSEQUENCESLOT_H_
#include <framework/objectmanager/ObjectManagerIF.h> #include <framework/objectmanager/ObjectManagerIF.h>
#include <framework/tasks/ExecutableObjectIF.h> #include <framework/tasks/ExecutableObjectIF.h>
class PeriodicTaskIF; class PeriodicTaskIF;
/** /**
* @brief This class is the representation of a single polling sequence table entry. * @brief This class is the representation of a single polling sequence
* * table entry.
* @details The PollingSlot class is the representation of a single polling * @details
* sequence table entry. * The PollingSlot class is the representation of a single polling
* sequence table entry.
* @author baetz
*/ */
class FixedSequenceSlot { class FixedSequenceSlot {
public: public:
@ -27,7 +22,7 @@ public:
/** /**
* @brief Handler identifies which device handler object is executed in this slot. * @brief Handler identifies which device handler object is executed in this slot.
*/ */
ExecutableObjectIF* handler; ExecutableObjectIF* handler = nullptr;
/** /**
* @brief This attribute defines when a device handler object is executed. * @brief This attribute defines when a device handler object is executed.
@ -43,7 +38,7 @@ public:
* @details The state of this value decides what communication routine is * @details The state of this value decides what communication routine is
* called in the PST executable or the device handler object. * called in the PST executable or the device handler object.
*/ */
uint8_t opcode; uint8_t opcode;
/** /**
* @brief Operator overload for the comparison operator to * @brief Operator overload for the comparison operator to

View File

@ -1,5 +1,5 @@
#include <framework/devicehandlers/FixedSlotSequence.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h> #include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <framework/tasks/FixedSlotSequence.h>
#include <cstdlib> #include <cstdlib>
FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) : FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) :

View File

@ -1,8 +1,8 @@
#ifndef FIXEDSLOTSEQUENCE_H_ #ifndef FRAMEWORK_TASKS_FIXEDSLOTSEQUENCE_H_
#define FIXEDSLOTSEQUENCE_H_ #define FRAMEWORK_TASKS_FIXEDSLOTSEQUENCE_H_
#include <framework/devicehandlers/FixedSequenceSlot.h>
#include <framework/objectmanager/SystemObject.h> #include <framework/objectmanager/SystemObject.h>
#include <framework/tasks/FixedSequenceSlot.h>
#include <set> #include <set>

View File

@ -12,11 +12,18 @@ class FixedTimeslotTaskIF : public PeriodicTaskIF {
public: public:
virtual ~FixedTimeslotTaskIF() {} virtual ~FixedTimeslotTaskIF() {}
/**
* Add an object with a slot time and the execution step to the task.
* The execution step shall be passed to the object.
* @param componentId
* @param slotTimeMs
* @param executionStep
* @return
*/
virtual ReturnValue_t addSlot(object_id_t componentId, virtual ReturnValue_t addSlot(object_id_t componentId,
uint32_t slotTimeMs, int8_t executionStep) = 0; uint32_t slotTimeMs, int8_t executionStep) = 0;
/** Check whether the sequence is valid */
virtual ReturnValue_t checkSequence() const = 0; virtual ReturnValue_t checkSequence() const = 0;
}; };
#endif /* FRAMEWORK_TASKS_FIXEDTIMESLOTTASKIF_H_ */ #endif /* FRAMEWORK_TASKS_FIXEDTIMESLOTTASKIF_H_ */

View File

@ -1,9 +1,11 @@
#ifndef PERIODICTASKIF_H_ #ifndef FRAMEWORK_TASK_PERIODICTASKIF_H_
#define PERIODICTASKIF_H_ #define FRAMEWORK_TASK_PERIODICTASKIF_H_
#include <framework/objectmanager/SystemObjectIF.h> #include <framework/objectmanager/SystemObjectIF.h>
#include <framework/timemanager/Clock.h>
#include <cstddef> #include <cstddef>
class ExecutableObjectIF; class ExecutableObjectIF;
/** /**
* New version of TaskIF * New version of TaskIF
* Follows RAII principles, i.e. there's no create or delete method. * Follows RAII principles, i.e. there's no create or delete method.
@ -17,11 +19,27 @@ public:
*/ */
virtual ~PeriodicTaskIF() { } virtual ~PeriodicTaskIF() { }
/** /**
* @brief With the startTask method, a created task can be started for the first time. * @brief With the startTask method, a created task can be started
* for the first time.
*/ */
virtual ReturnValue_t startTask() = 0; virtual ReturnValue_t startTask() = 0;
virtual ReturnValue_t addComponent(object_id_t object) {return HasReturnvaluesIF::RETURN_FAILED;}; /**
* Add a component (object) to a periodic task. The pointer to the
* task can be set optionally
* @param object
* Add an object to the task. The most important case is to add an
* executable object with a function which will be called regularly
* (see ExecutableObjectIF)
* @param setTaskIF
* Can be used to specify whether the task object pointer is passed
* to the component.
* @return
*/
virtual ReturnValue_t addComponent(object_id_t object,
bool setTaskIF = true) {
return HasReturnvaluesIF::RETURN_FAILED;
};
virtual ReturnValue_t sleepFor(uint32_t ms) = 0; virtual ReturnValue_t sleepFor(uint32_t ms) = 0;

View File

@ -412,5 +412,6 @@ void CommandingServiceBase::checkTimeout() {
} }
} }
void CommandingServiceBase::setTaskIF(PeriodicTaskIF* task_) {
executingTask = task_;
}

View File

@ -97,9 +97,7 @@ public:
* Used to setup the reference of the task, that executes this component * Used to setup the reference of the task, that executes this component
* @param task_ Pointer to the taskIF of this task * @param task_ Pointer to the taskIF of this task
*/ */
virtual void setTaskIF(PeriodicTaskIF* task_){ virtual void setTaskIF(PeriodicTaskIF* task_);
executingTask = task_;
};
protected: protected:
/** /**