Merge branch 'master' into mueller/feature/windowsUdpBridge

This commit is contained in:
Steffen Gaisser 2020-09-29 14:59:50 +02:00
commit ea29b272bf
72 changed files with 5519 additions and 4490 deletions

View File

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

View File

@ -1,96 +1,113 @@
#ifndef FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_ #ifndef FSFW_CONTAINER_RINGBUFFERBASE_H_
#define FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_ #define FSFW_CONTAINER_RINGBUFFERBASE_H_
#include "../returnvalues/HasReturnvaluesIF.h" #include "../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(size_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;
} }
} }
ReturnValue_t readData(uint32_t amount, uint8_t n = 0) {
if (availableReadData(n) >= amount) { virtual ~RingBufferBase() {}
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);
}
bool isFull(uint8_t n = 0) { bool isFull(uint8_t n = 0) {
return (availableWriteSpace(n) == 0); return (availableWriteSpace(n) == 0);
} }
bool isEmpty(uint8_t 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 { size_t availableWriteSpace(uint8_t n = 0) const {
return read[n]; //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)) { bool overwritesOld() const {
this->read[n] = read; return overwriteOld;
}
} }
uint32_t getWrite() const {
return write; size_t getMaxSize() const {
} return size - 1;
void setWrite(uint32_t write) {
this->write = write;
} }
void clear() { void clear() {
write = start; write = start;
for (uint8_t count = 0; count < N_READ_PTRS; count++) { for (uint8_t count = 0; count < N_READ_PTRS; count++) {
read[count] = start; read[count] = start;
} }
} }
uint32_t writeTillWrap() {
size_t writeTillWrap() {
return (start + size) - write; return (start + size) - write;
} }
uint32_t readTillWrap(uint8_t n = 0) {
size_t readTillWrap(uint8_t n = 0) {
return (start + size) - read[n]; return (start + size) - read[n];
} }
uint32_t getStart() const {
size_t getStart() const {
return start; return start;
} }
bool overwritesOld() const {
return overwriteOld;
}
uint32_t maxSize() const {
return size - 1;
}
protected: protected:
const uint32_t start; const size_t start;
uint32_t write; size_t write;
uint32_t read[N_READ_PTRS]; size_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;
} }
void incrementRead(uint32_t amount, uint8_t n = 0) { void incrementRead(uint32_t amount, uint8_t n = 0) {
read[n] = ((read[n] + amount - start) % size) + start; 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

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

@ -1,8 +1,8 @@
#ifndef FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ #ifndef FSFW_CONTAINER_SIMPLERINGBUFFER_H_
#define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ #define FSFW_CONTAINER_SIMPLERINGBUFFER_H_
#include "RingBufferBase.h" #include "RingBufferBase.h"
#include <stddef.h> #include <cstddef>
/** /**
* @brief Circular buffer implementation, useful for buffering * @brief Circular buffer implementation, useful for buffering
@ -16,53 +16,114 @@ class SimpleRingBuffer: public RingBufferBase<> {
public: public:
/** /**
* This constructor allocates a new internal buffer with the supplied size. * This constructor allocates a new internal buffer with the supplied size.
*
* @param 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. * This constructor takes an external buffer with the specified size.
* @param buffer * @param buffer
* @param size * @param size
* @param overwriteOld * @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(); 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 data
* @param amount * @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 * @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 data
* @param amount * @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 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 * @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, ReturnValue_t readData(uint8_t* data, size_t amount,
bool readRemaining = false, uint32_t* trueAmount = nullptr); 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 amount
* @param deleteRemaining * @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 * @return
*/ */
ReturnValue_t deleteData(uint32_t amount, bool deleteRemaining = false, ReturnValue_t deleteData(size_t amount, bool deleteRemaining = false,
uint32_t* trueAmount = nullptr); size_t* trueAmount = nullptr);
private: private:
// 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 = nullptr; uint8_t* buffer = nullptr;
size_t maxExcessBytes;
size_t excessBytes = 0;
}; };
#endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */ #endif /* FSFW_CONTAINER_SIMPLERINGBUFFER_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,117 +1,117 @@
#ifndef _sgp4unit_ #ifndef _sgp4unit_
#define _sgp4unit_ #define _sgp4unit_
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* *
* sgp4unit.h * sgp4unit.h
* *
* this file contains the sgp4 procedures for analytical propagation * this file contains the sgp4 procedures for analytical propagation
* of a satellite. the code was originally released in the 1980 and 1986 * of a satellite. the code was originally released in the 1980 and 1986
* spacetrack papers. a detailed discussion of the theory and history * spacetrack papers. a detailed discussion of the theory and history
* may be found in the 2006 aiaa paper by vallado, crawford, hujsak, * may be found in the 2006 aiaa paper by vallado, crawford, hujsak,
* and kelso. * and kelso.
* *
* companion code for * companion code for
* fundamentals of astrodynamics and applications * fundamentals of astrodynamics and applications
* 2007 * 2007
* by david vallado * by david vallado
* *
* (w) 719-573-2600, email dvallado@agi.com * (w) 719-573-2600, email dvallado@agi.com
* *
* current : * current :
* 20 apr 07 david vallado * 20 apr 07 david vallado
* misc fixes for constants * misc fixes for constants
* changes : * changes :
* 11 aug 06 david vallado * 11 aug 06 david vallado
* chg lyddane choice back to strn3, constants, misc doc * chg lyddane choice back to strn3, constants, misc doc
* 15 dec 05 david vallado * 15 dec 05 david vallado
* misc fixes * misc fixes
* 26 jul 05 david vallado * 26 jul 05 david vallado
* fixes for paper * fixes for paper
* note that each fix is preceded by a * note that each fix is preceded by a
* comment with "sgp4fix" and an explanation of * comment with "sgp4fix" and an explanation of
* what was changed * what was changed
* 10 aug 04 david vallado * 10 aug 04 david vallado
* 2nd printing baseline working * 2nd printing baseline working
* 14 may 01 david vallado * 14 may 01 david vallado
* 2nd edition baseline * 2nd edition baseline
* 80 norad * 80 norad
* original baseline * original baseline
* ---------------------------------------------------------------- */ * ---------------------------------------------------------------- */
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
// -------------------------- structure declarations ---------------------------- // -------------------------- structure declarations ----------------------------
typedef enum typedef enum
{ {
wgs72old, wgs72old,
wgs72, wgs72,
wgs84 wgs84
} gravconsttype; } gravconsttype;
typedef struct elsetrec typedef struct elsetrec
{ {
long int satnum; long int satnum;
int epochyr, epochtynumrev; int epochyr, epochtynumrev;
int error; int error;
char init, method; char init, method;
/* Near Earth */ /* Near Earth */
int isimp; int isimp;
double aycof , con41 , cc1 , cc4 , cc5 , d2 , d3 , d4 , double aycof , con41 , cc1 , cc4 , cc5 , d2 , d3 , d4 ,
delmo , eta , argpdot, omgcof , sinmao , t , t2cof, t3cof , delmo , eta , argpdot, omgcof , sinmao , t , t2cof, t3cof ,
t4cof , t5cof , x1mth2 , x7thm1 , mdot , nodedot, xlcof , xmcof , t4cof , t5cof , x1mth2 , x7thm1 , mdot , nodedot, xlcof , xmcof ,
nodecf; nodecf;
/* Deep Space */ /* Deep Space */
int irez; int irez;
double d2201 , d2211 , d3210 , d3222 , d4410 , d4422 , d5220 , d5232 , double d2201 , d2211 , d3210 , d3222 , d4410 , d4422 , d5220 , d5232 ,
d5421 , d5433 , dedt , del1 , del2 , del3 , didt , dmdt , d5421 , d5433 , dedt , del1 , del2 , del3 , didt , dmdt ,
dnodt , domdt , e3 , ee2 , peo , pgho , pho , pinco , dnodt , domdt , e3 , ee2 , peo , pgho , pho , pinco ,
plo , se2 , se3 , sgh2 , sgh3 , sgh4 , sh2 , sh3 , plo , se2 , se3 , sgh2 , sgh3 , sgh4 , sh2 , sh3 ,
si2 , si3 , sl2 , sl3 , sl4 , gsto , xfact , xgh2 , si2 , si3 , sl2 , sl3 , sl4 , gsto , xfact , xgh2 ,
xgh3 , xgh4 , xh2 , xh3 , xi2 , xi3 , xl2 , xl3 , xgh3 , xgh4 , xh2 , xh3 , xi2 , xi3 , xl2 , xl3 ,
xl4 , xlamo , zmol , zmos , atime , xli , xni; xl4 , xlamo , zmol , zmos , atime , xli , xni;
double a , altp , alta , epochdays, jdsatepoch , nddot , ndot , double a , altp , alta , epochdays, jdsatepoch , nddot , ndot ,
bstar , rcse , inclo , nodeo , ecco , argpo , mo , bstar , rcse , inclo , nodeo , ecco , argpo , mo ,
no; no;
} elsetrec; } elsetrec;
// --------------------------- function declarations ---------------------------- // --------------------------- function declarations ----------------------------
int sgp4init int sgp4init
( (
gravconsttype whichconst, const int satn, const double epoch, gravconsttype whichconst, const int satn, const double epoch,
const double xbstar, const double xecco, const double xargpo, const double xbstar, const double xecco, const double xargpo,
const double xinclo, const double xmo, const double xno, const double xinclo, const double xmo, const double xno,
const double xnodeo, const double xnodeo,
elsetrec& satrec elsetrec& satrec
); );
int sgp4 int sgp4
( (
gravconsttype whichconst, gravconsttype whichconst,
elsetrec& satrec, double tsince, elsetrec& satrec, double tsince,
double r[], double v[] double r[], double v[]
); );
double gstime double gstime
( (
double double
); );
void getgravconst void getgravconst
( (
gravconsttype, gravconsttype,
double&, double&,
double&, double&,
double&, double&,
double&, double&,
double&, double&,
double&, double&,
double&, double&,
double& double&
); );
#endif #endif

View File

@ -18,7 +18,7 @@ MapPacketExtraction::MapPacketExtraction(uint8_t setMapId,
object_id_t setPacketDestination) : object_id_t setPacketDestination) :
lastSegmentationFlag(NO_SEGMENTATION), mapId(setMapId), packetLength(0), bufferPosition( lastSegmentationFlag(NO_SEGMENTATION), mapId(setMapId), packetLength(0), bufferPosition(
packetBuffer), packetDestination(setPacketDestination), packetStore( packetBuffer), packetDestination(setPacketDestination), packetStore(
NULL), tcQueueId(MessageQueueSenderIF::NO_QUEUE) { NULL), tcQueueId(MessageQueueIF::NO_QUEUE) {
memset(packetBuffer, 0, sizeof(packetBuffer)); 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) : MessageQueueId_t parentQueue) :
SystemObject(setObjectId), lastHealth(HEALTHY), parentQueue( SystemObject(setObjectId), lastHealth(HEALTHY), parentQueue(
parentQueue), commandQueue(), healthHelper(this, setObjectId) { parentQueue), commandQueue(), healthHelper(this, setObjectId) {
commandQueue = QueueFactory::instance()->createMessageQueue(3, CommandMessage::COMMAND_MESSAGE_SIZE); commandQueue = QueueFactory::instance()->createMessageQueue(3);
} }
HealthDevice::~HealthDevice() { HealthDevice::~HealthDevice() {

View File

@ -19,6 +19,7 @@ enum {
SYSTEM_MANAGER_1 = 75, SYSTEM_MANAGER_1 = 75,
SYSTEM_1 = 79, SYSTEM_1 = 79,
PUS_SERVICE_1 = 80, PUS_SERVICE_1 = 80,
PUS_SERVICE_9 = 89,
PUS_SERVICE_17 = 97, PUS_SERVICE_17 = 97,
FW_SUBSYSTEM_ID_RANGE FW_SUBSYSTEM_ID_RANGE
}; };

View File

@ -1,99 +1,99 @@
#include "timevalOperations.h" #include "timevalOperations.h"
timeval& operator+=(timeval& lhs, const timeval& rhs) { timeval& operator+=(timeval& lhs, const timeval& rhs) {
int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec; int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec;
sum += rhs.tv_sec * 1000000. + rhs.tv_usec; sum += rhs.tv_sec * 1000000. + rhs.tv_usec;
lhs.tv_sec = sum / 1000000; lhs.tv_sec = sum / 1000000;
lhs.tv_usec = sum - lhs.tv_sec * 1000000; lhs.tv_usec = sum - lhs.tv_sec * 1000000;
return lhs; return lhs;
} }
timeval operator+(timeval lhs, const timeval& rhs) { timeval operator+(timeval lhs, const timeval& rhs) {
lhs += rhs; lhs += rhs;
return lhs; return lhs;
} }
timeval& operator-=(timeval& lhs, const timeval& rhs) { timeval& operator-=(timeval& lhs, const timeval& rhs) {
int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec; int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec;
sum -= rhs.tv_sec * 1000000. + rhs.tv_usec; sum -= rhs.tv_sec * 1000000. + rhs.tv_usec;
lhs.tv_sec = sum / 1000000; lhs.tv_sec = sum / 1000000;
lhs.tv_usec = sum - lhs.tv_sec * 1000000; lhs.tv_usec = sum - lhs.tv_sec * 1000000;
return lhs; return lhs;
} }
timeval operator-(timeval lhs, const timeval& rhs) { timeval operator-(timeval lhs, const timeval& rhs) {
lhs -= rhs; lhs -= rhs;
return lhs; return lhs;
} }
double operator/(const timeval& lhs, const timeval& rhs) { double operator/(const timeval& lhs, const timeval& rhs) {
double lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; double lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec;
double rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; double rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec;
return lhs64 / rhs64; return lhs64 / rhs64;
} }
timeval& operator/=(timeval& lhs, double scalar) { timeval& operator/=(timeval& lhs, double scalar) {
int64_t product = lhs.tv_sec * 1000000. + lhs.tv_usec; int64_t product = lhs.tv_sec * 1000000. + lhs.tv_usec;
product /= scalar; product /= scalar;
lhs.tv_sec = product / 1000000; lhs.tv_sec = product / 1000000;
lhs.tv_usec = product - lhs.tv_sec * 1000000; lhs.tv_usec = product - lhs.tv_sec * 1000000;
return lhs; return lhs;
} }
timeval operator/(timeval lhs, double scalar) { timeval operator/(timeval lhs, double scalar) {
lhs /= scalar; lhs /= scalar;
return lhs; return lhs;
} }
timeval& operator*=(timeval& lhs, double scalar) { timeval& operator*=(timeval& lhs, double scalar) {
int64_t product = lhs.tv_sec * 1000000. + lhs.tv_usec; int64_t product = lhs.tv_sec * 1000000. + lhs.tv_usec;
product *= scalar; product *= scalar;
lhs.tv_sec = product / 1000000; lhs.tv_sec = product / 1000000;
lhs.tv_usec = product - lhs.tv_sec * 1000000; lhs.tv_usec = product - lhs.tv_sec * 1000000;
return lhs; return lhs;
} }
timeval operator*(timeval lhs, double scalar) { timeval operator*(timeval lhs, double scalar) {
lhs *= scalar; lhs *= scalar;
return lhs; return lhs;
} }
timeval operator*(double scalar, timeval rhs) { timeval operator*(double scalar, timeval rhs) {
rhs *= scalar; rhs *= scalar;
return rhs; return rhs;
} }
bool operator==(const timeval& lhs, const timeval& rhs) { bool operator==(const timeval& lhs, const timeval& rhs) {
int64_t lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; int64_t lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec;
int64_t rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; int64_t rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec;
return lhs64 == rhs64; return lhs64 == rhs64;
} }
bool operator!=(const timeval& lhs, const timeval& rhs) { bool operator!=(const timeval& lhs, const timeval& rhs) {
return !operator==(lhs, rhs); return !operator==(lhs, rhs);
} }
bool operator<(const timeval& lhs, const timeval& rhs) { bool operator<(const timeval& lhs, const timeval& rhs) {
int64_t lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; int64_t lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec;
int64_t rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; int64_t rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec;
return lhs64 < rhs64; return lhs64 < rhs64;
} }
bool operator>(const timeval& lhs, const timeval& rhs) { bool operator>(const timeval& lhs, const timeval& rhs) {
return operator<(rhs, lhs); return operator<(rhs, lhs);
} }
bool operator<=(const timeval& lhs, const timeval& rhs) { bool operator<=(const timeval& lhs, const timeval& rhs) {
return !operator>(lhs, rhs); return !operator>(lhs, rhs);
} }
bool operator>=(const timeval& lhs, const timeval& rhs) { bool operator>=(const timeval& lhs, const timeval& rhs) {
return !operator<(lhs, rhs); return !operator<(lhs, rhs);
} }
double timevalOperations::toDouble(const timeval timeval) { double timevalOperations::toDouble(const timeval timeval) {
double result = timeval.tv_sec * 1000000. + timeval.tv_usec; double result = timeval.tv_sec * 1000000. + timeval.tv_usec;
return result / 1000000.; return result / 1000000.;
} }
timeval timevalOperations::toTimeval(const double seconds) { timeval timevalOperations::toTimeval(const double seconds) {
timeval tval; timeval tval;
tval.tv_sec = seconds; tval.tv_sec = seconds;
tval.tv_usec = seconds *(double) 1e6 - (tval.tv_sec *1e6); tval.tv_usec = seconds *(double) 1e6 - (tval.tv_sec *1e6);
return tval; return tval;
} }

View File

@ -1,124 +1,96 @@
/**
* @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 "CommandMessage.h"
#include "../memory/MemoryMessage.h" #include "CommandMessageCleaner.h"
#include "../modes/ModeMessage.h" #include <cstring>
#include "../monitoring/MonitoringMessage.h"
#include "../subsystem/modes/ModeSequenceMessage.h"
#include "../tmstorage/TmStoreMessage.h"
#include "../parameters/ParameterMessage.h"
namespace messagetypes {
void clearMissionMessage(CommandMessage* message);
}
CommandMessage::CommandMessage() { CommandMessage::CommandMessage() {
this->messageSize = COMMAND_MESSAGE_SIZE; MessageQueueMessage::setMessageSize(DEFAULT_COMMAND_MESSAGE_SIZE);
setCommand(CMD_NONE); setCommand(CMD_NONE);
} }
CommandMessage::CommandMessage(Command_t command, uint32_t parameter1, CommandMessage::CommandMessage(Command_t command, uint32_t parameter1,
uint32_t parameter2) { uint32_t parameter2) {
this->messageSize = COMMAND_MESSAGE_SIZE; MessageQueueMessage::setMessageSize(DEFAULT_COMMAND_MESSAGE_SIZE);
setCommand(command); setCommand(command);
setParameter(parameter1); setParameter(parameter1);
setParameter2(parameter2); setParameter2(parameter2);
} }
Command_t CommandMessage::getCommand() const { Command_t CommandMessage::getCommand() const {
Command_t command; Command_t command;
memcpy(&command, getData(), sizeof(Command_t)); std::memcpy(&command, MessageQueueMessage::getData(), sizeof(Command_t));
return command; return command;
} }
void CommandMessage::setCommand(Command_t 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 CommandMessage::getParameter() const {
uint32_t parameter1; uint32_t parameter1;
memcpy(&parameter1, getData() + sizeof(Command_t), sizeof(parameter1)); std::memcpy(&parameter1, this->getData(), sizeof(parameter1));
return parameter1; return parameter1;
} }
void CommandMessage::setParameter(uint32_t 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 CommandMessage::getParameter2() const {
uint32_t parameter2; uint32_t parameter2;
memcpy(&parameter2, getData() + sizeof(Command_t) + sizeof(uint32_t), std::memcpy(&parameter2, this->getData() + sizeof(uint32_t),
sizeof(parameter2)); sizeof(parameter2));
return parameter2; return parameter2;
} }
void CommandMessage::setParameter2(uint32_t 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)); sizeof(parameter2));
} }
void CommandMessage::clearCommandMessage() { uint32_t CommandMessage::getParameter3() const {
switch((getCommand()>>8) & 0xff){ uint32_t parameter3;
case messagetypes::MODE_COMMAND: std::memcpy(&parameter3, this->getData() + 2 * sizeof(uint32_t),
ModeMessage::clear(this); sizeof(parameter3));
break; return parameter3;
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;
}
} }
bool CommandMessage::isClearedCommandMessage() { void CommandMessage::setParameter3(uint32_t parameter3) {
return getCommand() == CMD_NONE; std::memcpy(this->getData() + 2 * sizeof(uint32_t), &parameter3,
sizeof(parameter3));
} }
size_t CommandMessage::getMinimumMessageSize() const { size_t CommandMessage::getMinimumMessageSize() const {
return COMMAND_MESSAGE_SIZE; return MINIMUM_COMMAND_MESSAGE_SIZE;
}
void CommandMessage::clearCommandMessage() {
clear();
}
void CommandMessage::clear() {
CommandMessageCleaner::clearCommandMessage(this);
}
bool CommandMessage::isClearedCommandMessage() {
return getCommand() == CMD_NONE;
} }
void CommandMessage::setToUnknownCommand() { void CommandMessage::setToUnknownCommand() {
Command_t initialCommand = getCommand(); Command_t initialCommand = getCommand();
clearCommandMessage(); this->clear();
setReplyRejected(UNKNOWN_COMMAND, initialCommand); setReplyRejected(UNKNOWN_COMMAND, initialCommand);
} }
void CommandMessage::setReplyRejected(ReturnValue_t reason, void CommandMessage::setReplyRejected(ReturnValue_t reason,
Command_t initialCommand) { Command_t initialCommand) {
setCommand(REPLY_REJECTED); setCommand(REPLY_REJECTED);
setParameter(reason); setParameter(reason);
setParameter2(initialCommand); setParameter2(initialCommand);
} }
ReturnValue_t CommandMessage::getReplyRejectedReason( ReturnValue_t CommandMessage::getReplyRejectedReason(
@ -129,3 +101,11 @@ ReturnValue_t CommandMessage::getReplyRejectedReason(
} }
return reason; 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 @@
/** #ifndef FSFW_IPC_COMMANDMESSAGE_H_
* @file CommandMessage.h #define FSFW_IPC_COMMANDMESSAGE_H_
* @brief This file defines the CommandMessage class.
* @date 20.06.2013
* @author baetz
*/
#ifndef COMMANDMESSAGE_H_ #include "CommandMessageIF.h"
#define COMMANDMESSAGE_H_
#include "FwMessageTypes.h"
#include <config/ipc/MissionMessageTypes.h>
#include "MessageQueueMessage.h" #include "MessageQueueMessage.h"
#include "FwMessageTypes.h"
#define MAKE_COMMAND_ID( number ) ((MESSAGE_ID << 8) + (number)) /**
typedef ReturnValue_t Command_t; * @brief Default command message used to pass command messages between tasks.
* Primary message type for IPC. Contains sender, 2-byte command ID
class CommandMessage : public MessageQueueMessage { * 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.
*
* 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: public:
static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_MESSAGE; /**
static const ReturnValue_t UNKNOWN_COMMAND = MAKE_RETURN_CODE(0x01); * Default size can accomodate 3 4-byte parameters.
*/
static constexpr size_t DEFAULT_COMMAND_MESSAGE_SIZE =
static const uint8_t MESSAGE_ID = messagetypes::COMMAND; CommandMessageIF::MINIMUM_COMMAND_MESSAGE_SIZE +
static const Command_t CMD_NONE = MAKE_COMMAND_ID( 0 );//!< Used internally, will be ignored 3 * sizeof(uint32_t);
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
/** /**
* This is the size of a message as it is seen by the MessageQueue * @brief Default Constructor, does not initialize anything.
*/ * @details
static const size_t COMMAND_MESSAGE_SIZE = HEADER_SIZE * This constructor should be used when receiving a Message, as the
+ sizeof(Command_t) + 2 * sizeof(uint32_t); * content is filled by the MessageQueue.
/**
* Default Constructor, does not initialize anything.
*
* This constructor should be used when receiving a Message, as the content is filled by the MessageQueue.
*/ */
CommandMessage(); 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 command The DeviceHandlerCommand_t that will be sent
* @param parameter1 The first parameter * @param parameter1 The first parameter
* @param parameter2 The second parameter * @param parameter2 The second parameter
*/ */
CommandMessage(Command_t command, CommandMessage(Command_t command, uint32_t parameter1, uint32_t parameter2);
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 *
*/ * @return the Command stored in the Message
Command_t getCommand() const; */
virtual Command_t getCommand() const override;
/**
* 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
*/
virtual void setCommand(Command_t command);
/** virtual uint8_t* getData() override;
* Set the DeviceHandlerCOmmand_t of the message virtual const uint8_t* getData() const override;
*
* @param the Command to be sent
*/
void setCommand(Command_t command);
/** /**
* Get the first parameter of the message * Get the first parameter of the message
*
* @return the first Parameter of the message * @return the first Parameter of the message
*/ */
uint32_t getParameter() const; uint32_t getParameter() const;
/** /**
* Set the first parameter of the message * Set the first parameter of the message
*
* @param the first parameter of the message * @param the first parameter of the message
*/ */
void setParameter(uint32_t parameter1); void setParameter(uint32_t parameter1);
/**
* Get the second parameter of the message
*
* @return the second Parameter of the message
*/
uint32_t getParameter2() const; uint32_t getParameter2() const;
/**
* Set the second parameter of the message
*
* @param the second parameter of the message
*/
void setParameter2(uint32_t parameter2); void setParameter2(uint32_t parameter2);
uint32_t getParameter3() const;
/** void setParameter3(uint32_t parameter3);
* 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();
/** /**
* check if a message was cleared * check if a message was cleared
@ -117,18 +91,41 @@ public:
*/ */
bool isClearedCommandMessage(); bool isClearedCommandMessage();
/** /**
* Sets the command to REPLY_REJECTED with parameter UNKNOWN_COMMAND. * Sets the command to REPLY_REJECTED with parameter UNKNOWN_COMMAND.
* Is needed quite often, so we better code it once only. * Is needed quite often, so we better code it once only.
*/ */
void setToUnknownCommand(); void setToUnknownCommand() override;
void setReplyRejected(ReturnValue_t reason, Command_t initialCommand = CMD_NONE);
ReturnValue_t getReplyRejectedReason(
Command_t *initialCommand = nullptr) const;
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 /* FSFW_IPC_COMMANDMESSAGE_H_ */
#endif /* 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_ #ifndef FSFW_IPC_MESSAGEQUEUEIF_H_
#define FRAMEWORK_IPC_MESSAGEQUEUEIF_H_ #define FSFW_IPC_MESSAGEQUEUEIF_H_
// COULDDO: We could support blocking calls // COULDDO: We could support blocking calls
#include "messageQueueDefinitions.h"
#include "MessageQueueMessage.h" #include "MessageQueueMessage.h"
#include "MessageQueueSenderIF.h"
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
class MessageQueueIF { class MessageQueueIF {
public: public:
static const MessageQueueId_t NO_QUEUE = 0;
static const MessageQueueId_t NO_QUEUE = MessageQueueSenderIF::NO_QUEUE; //!< Ugly hack.
static const uint8_t INTERFACE_ID = CLASS_ID::MESSAGE_QUEUE_IF; static const uint8_t INTERFACE_ID = CLASS_ID::MESSAGE_QUEUE_IF;
/** /**

View File

@ -1,13 +1,27 @@
#include "MessageQueueMessage.h" #include "MessageQueueMessage.h"
#include "../serviceinterface/ServiceInterfaceStream.h" #include "../serviceinterface/ServiceInterfaceStream.h"
#include "../globalfunctions/arrayprinter.h"
#include <string.h> #include <cstring>
MessageQueueMessage::MessageQueueMessage() : MessageQueueMessage::MessageQueueMessage() :
messageSize(this->HEADER_SIZE) { messageSize(getMinimumMessageSize()) {
memset(this->internalBuffer, 0, sizeof(this->internalBuffer)); 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() { MessageQueueMessage::~MessageQueueMessage() {
} }
@ -37,29 +51,34 @@ void MessageQueueMessage::setSender(MessageQueueId_t setId) {
memcpy(this->internalBuffer, &setId, sizeof(MessageQueueId_t)); memcpy(this->internalBuffer, &setId, sizeof(MessageQueueId_t));
} }
MessageQueueMessage::MessageQueueMessage(uint8_t* data, uint32_t size) : void MessageQueueMessage::print(bool printWholeMessage) {
messageSize(this->HEADER_SIZE + size) { sif::debug << "MessageQueueMessage content: " << std::endl;
if (size <= this->MAX_DATA_SIZE) { if(printWholeMessage) {
memcpy(this->getData(), data, size); arrayprinter::print(getData(), getMaximumMessageSize());
} else {
memset(this->internalBuffer, 0, sizeof(this->internalBuffer));
this->messageSize = this->HEADER_SIZE;
} }
} 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() { void MessageQueueMessage::clear() {
memset(this->getBuffer(), 0, this->MAX_MESSAGE_SIZE); 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_ #ifndef FSFW_IPC_MESSAGEQUEUEMESSAGE_H_
#define MESSAGEQUEUEMESSAGE_H_ #define FSFW_IPC_MESSAGEQUEUEMESSAGE_H_
#include "MessageQueueSenderIF.h" #include "../ipc/MessageQueueMessageIF.h"
#include <stddef.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 * It adds a header with the sender's queue id to every sent message and
* to handle a lightweight "interprocess message protocol". It adds a header with the * defines the maximum total message size. Specialized messages, such as
* sender's queue id to every sent message and defines the maximum total message size. * device commanding messages, can be created by inheriting from this class
* Specialized messages, such as device commanding messages, can be created by inheriting * and filling the buffer provided by getData with additional content.
* 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 * If larger amounts of data must be sent between processes, the data shall
* the IPC Store object and only the storage id is passed in a queue message. * be stored in the IPC Store object and only the storage id is passed in a
* The class is used both to generate and send messages and to receive messages from * queue message.The class is used both to generate and send messages and to
* other tasks. * receive messages from other tasks.
* \ingroup message_queue * @ingroup message_queue
*/ */
class MessageQueueMessage { class MessageQueueMessage: public MessageQueueMessageIF {
public: public:
/** /**
* \brief This constant defines the maximum size of the data content, excluding the header. * @brief The class is initialized empty with this constructor.
* \details It may be changed if necessary, but in general should be kept as small as possible. * @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; 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. * @brief Defines the minimum size of a message where only the
* \details It is the sum of the maximum data and the header size. Be aware that this constant * header is included
* 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 MAX_MESSAGE_SIZE = MAX_DATA_SIZE + HEADER_SIZE; static constexpr size_t MIN_MESSAGE_SIZE = HEADER_SIZE;
private: 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]; uint8_t internalBuffer[MAX_MESSAGE_SIZE];
public: public:
/** /**
* \brief The size information of each message is stored in this attribute. * @brief This method is used to get the complete data of the message.
* \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.
*/ */
size_t messageSize; const uint8_t* getBuffer() const override;
/** /**
* \brief The class is initialized empty with this constructor. * @brief This method is used to get the complete data of the message.
* \details The messageSize attribute is set to the header's size and the whole content is set to
* zero.
*/ */
MessageQueueMessage(); uint8_t* getBuffer() override;
/** /**
* \brief With this constructor the class is initialized with the given content. * @brief This method is used to fetch the data content of the message.
* \details If the passed message size fits into the buffer, the passed data is copied to the * @details
* internal buffer and the messageSize information is set. Otherwise, messageSize * It shall be used by child classes to add data at the right position.
* 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.
*/ */
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. * @brief This method is used to set the sender's message queue id
* \details It shall be used by child classes to add data at the right position. * 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. * @brief This is a debug method that prints the content.
* \details It shall be used by child classes to add data at the right position.
*/ */
uint8_t* getData(); void print(bool printWholeMessage);
/**
* \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();
}; };
#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_ #ifndef FSFW_IPC_MESSAGEQUEUESENDERIF_H_
#define FRAMEWORK_IPC_MESSAGEQUEUESENDERIF_H_ #define FSFW_IPC_MESSAGEQUEUESENDERIF_H_
#include "../ipc/MessageQueueIF.h"
#include "../ipc/MessageQueueMessageIF.h"
#include "../objectmanager/ObjectManagerIF.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 { class MessageQueueSenderIF {
public: public:
static const MessageQueueId_t NO_QUEUE = 0;
virtual ~MessageQueueSenderIF() {} 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. * Not sure whether this is actually a good idea.
* Must be implemented by a subclass.
*/ */
static ReturnValue_t sendMessage(MessageQueueId_t sendTo, static ReturnValue_t sendMessage(MessageQueueId_t sendTo,
MessageQueueMessage* message, MessageQueueId_t sentFrom = MessageQueueMessage* message,
MessageQueueSenderIF::NO_QUEUE, bool ignoreFault=false); MessageQueueId_t sentFrom = MessageQueueIF::NO_QUEUE,
bool ignoreFault = false);
private: private:
MessageQueueSenderIF() {} MessageQueueSenderIF() {}
}; };
#endif /* FSFW_IPC_MESSAGEQUEUESENDERIF_H_ */
#endif /* FRAMEWORK_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

@ -36,7 +36,7 @@ ReturnValue_t ModeHelper::handleModeCommand(CommandMessage* message) {
commandedMode = mode; commandedMode = mode;
commandedSubmode = submode; commandedSubmode = submode;
if ((parentQueueId != MessageQueueSenderIF::NO_QUEUE) if ((parentQueueId != MessageQueueIF::NO_QUEUE)
&& (theOneWhoCommandedAMode != parentQueueId)) { && (theOneWhoCommandedAMode != parentQueueId)) {
owner->setToExternalControl(); owner->setToExternalControl();
} }
@ -74,7 +74,7 @@ ReturnValue_t ModeHelper::initialize(MessageQueueId_t parentQueueId) {
void ModeHelper::modeChanged(Mode_t mode, Submode_t submode) { void ModeHelper::modeChanged(Mode_t mode, Submode_t submode) {
forced = false; forced = false;
CommandMessage reply; CommandMessage reply;
if (theOneWhoCommandedAMode != MessageQueueSenderIF::NO_QUEUE) { if (theOneWhoCommandedAMode != MessageQueueIF::NO_QUEUE) {
if ((mode != commandedMode) || (submode != commandedSubmode)) { if ((mode != commandedMode) || (submode != commandedSubmode)) {
ModeMessage::setModeMessage(&reply, ModeMessage::setModeMessage(&reply,
ModeMessage::REPLY_WRONG_MODE_REPLY, mode, submode); ModeMessage::REPLY_WRONG_MODE_REPLY, mode, submode);
@ -86,12 +86,12 @@ void ModeHelper::modeChanged(Mode_t mode, Submode_t submode) {
owner->getCommandQueue()); owner->getCommandQueue());
} }
if (theOneWhoCommandedAMode != parentQueueId if (theOneWhoCommandedAMode != parentQueueId
&& parentQueueId != MessageQueueSenderIF::NO_QUEUE) { && parentQueueId != MessageQueueIF::NO_QUEUE) {
ModeMessage::setModeMessage(&reply, ModeMessage::REPLY_MODE_INFO, mode, ModeMessage::setModeMessage(&reply, ModeMessage::REPLY_MODE_INFO, mode,
submode); submode);
MessageQueueSenderIF::sendMessage(parentQueueId, &reply, owner->getCommandQueue()); MessageQueueSenderIF::sendMessage(parentQueueId, &reply, owner->getCommandQueue());
} }
theOneWhoCommandedAMode = MessageQueueSenderIF::NO_QUEUE; theOneWhoCommandedAMode = MessageQueueIF::NO_QUEUE;
} }
void ModeHelper::startTimer(uint32_t timeoutMs) { void ModeHelper::startTimer(uint32_t timeoutMs) {

View File

@ -4,11 +4,13 @@
namespace objects { namespace objects {
enum framework_objects { enum framework_objects {
// Default verification reporter. // Default verification reporter.
PUS_SERVICE_1 = 0x53000001, PUS_SERVICE_1_VERIFICATION = 0x53000001,
PUS_SERVICE_2 = 0x53000002, PUS_SERVICE_2_DEVICE_ACCESS = 0x53000002,
PUS_SERVICE_5 = 0x53000005, PUS_SERVICE_5_EVENT_REPORTING = 0x53000005,
PUS_SERVICE_8 = 0x53000008, PUS_SERVICE_8_FUNCTION_MGMT = 0x53000008,
PUS_SERVICE_200 = 0x53000200, PUS_SERVICE_9_TIME_MGMT = 0x53000009,
PUS_SERVICE_17_TEST = 0x53000017,
PUS_SERVICE_200_MODE_MGMT = 0x53000200,
//Generic IDs for IPC, modes, health, events //Generic IDs for IPC, modes, health, events
HEALTH_TABLE = 0x53010000, HEALTH_TABLE = 0x53010000,

View File

@ -1,95 +1,95 @@
#include "../../osal/FreeRTOS/BinSemaphUsingTask.h" #include "../../osal/FreeRTOS/BinSemaphUsingTask.h"
#include "../../osal/FreeRTOS/TaskManagement.h" #include "../../osal/FreeRTOS/TaskManagement.h"
#include "../../serviceinterface/ServiceInterfaceStream.h" #include "../../serviceinterface/ServiceInterfaceStream.h"
BinarySemaphoreUsingTask::BinarySemaphoreUsingTask() { BinarySemaphoreUsingTask::BinarySemaphoreUsingTask() {
handle = TaskManagement::getCurrentTaskHandle(); handle = TaskManagement::getCurrentTaskHandle();
if(handle == nullptr) { if(handle == nullptr) {
sif::error << "Could not retrieve task handle. Please ensure the" sif::error << "Could not retrieve task handle. Please ensure the"
"constructor was called inside a task." << std::endl; "constructor was called inside a task." << std::endl;
} }
xTaskNotifyGive(handle); xTaskNotifyGive(handle);
} }
BinarySemaphoreUsingTask::~BinarySemaphoreUsingTask() { BinarySemaphoreUsingTask::~BinarySemaphoreUsingTask() {
// Clear notification value on destruction. // Clear notification value on destruction.
xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, nullptr); xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, nullptr);
} }
ReturnValue_t BinarySemaphoreUsingTask::acquire(TimeoutType timeoutType, ReturnValue_t BinarySemaphoreUsingTask::acquire(TimeoutType timeoutType,
uint32_t timeoutMs) { uint32_t timeoutMs) {
TickType_t timeout = 0; TickType_t timeout = 0;
if(timeoutType == TimeoutType::POLLING) { if(timeoutType == TimeoutType::POLLING) {
timeout = 0; timeout = 0;
} }
else if(timeoutType == TimeoutType::WAITING){ else if(timeoutType == TimeoutType::WAITING){
timeout = pdMS_TO_TICKS(timeoutMs); timeout = pdMS_TO_TICKS(timeoutMs);
} }
else { else {
timeout = portMAX_DELAY; timeout = portMAX_DELAY;
} }
return acquireWithTickTimeout(timeoutType, timeout); return acquireWithTickTimeout(timeoutType, timeout);
} }
ReturnValue_t BinarySemaphoreUsingTask::acquireWithTickTimeout( ReturnValue_t BinarySemaphoreUsingTask::acquireWithTickTimeout(
TimeoutType timeoutType, TickType_t timeoutTicks) { TimeoutType timeoutType, TickType_t timeoutTicks) {
BaseType_t returncode = ulTaskNotifyTake(pdTRUE, timeoutTicks); BaseType_t returncode = ulTaskNotifyTake(pdTRUE, timeoutTicks);
if (returncode == pdPASS) { if (returncode == pdPASS) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
else { else {
return SemaphoreIF::SEMAPHORE_TIMEOUT; return SemaphoreIF::SEMAPHORE_TIMEOUT;
} }
} }
ReturnValue_t BinarySemaphoreUsingTask::release() { ReturnValue_t BinarySemaphoreUsingTask::release() {
return release(this->handle); return release(this->handle);
} }
ReturnValue_t BinarySemaphoreUsingTask::release( ReturnValue_t BinarySemaphoreUsingTask::release(
TaskHandle_t taskHandle) { TaskHandle_t taskHandle) {
if(getSemaphoreCounter(taskHandle) == 1) { if(getSemaphoreCounter(taskHandle) == 1) {
return SemaphoreIF::SEMAPHORE_NOT_OWNED; return SemaphoreIF::SEMAPHORE_NOT_OWNED;
} }
BaseType_t returncode = xTaskNotifyGive(taskHandle); BaseType_t returncode = xTaskNotifyGive(taskHandle);
if (returncode == pdPASS) { if (returncode == pdPASS) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
else { else {
// This should never happen. // This should never happen.
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
} }
TaskHandle_t BinarySemaphoreUsingTask::getTaskHandle() { TaskHandle_t BinarySemaphoreUsingTask::getTaskHandle() {
return handle; return handle;
} }
uint8_t BinarySemaphoreUsingTask::getSemaphoreCounter() const { uint8_t BinarySemaphoreUsingTask::getSemaphoreCounter() const {
return getSemaphoreCounter(this->handle); return getSemaphoreCounter(this->handle);
} }
uint8_t BinarySemaphoreUsingTask::getSemaphoreCounter( uint8_t BinarySemaphoreUsingTask::getSemaphoreCounter(
TaskHandle_t taskHandle) { TaskHandle_t taskHandle) {
uint32_t notificationValue; uint32_t notificationValue;
xTaskNotifyAndQuery(taskHandle, 0, eNoAction, &notificationValue); xTaskNotifyAndQuery(taskHandle, 0, eNoAction, &notificationValue);
return notificationValue; return notificationValue;
} }
// Be careful with the stack size here. This is called from an ISR! // Be careful with the stack size here. This is called from an ISR!
ReturnValue_t BinarySemaphoreUsingTask::releaseFromISR( ReturnValue_t BinarySemaphoreUsingTask::releaseFromISR(
TaskHandle_t taskHandle, BaseType_t * higherPriorityTaskWoken) { TaskHandle_t taskHandle, BaseType_t * higherPriorityTaskWoken) {
if(getSemaphoreCounterFromISR(taskHandle, higherPriorityTaskWoken) == 1) { if(getSemaphoreCounterFromISR(taskHandle, higherPriorityTaskWoken) == 1) {
return SemaphoreIF::SEMAPHORE_NOT_OWNED; return SemaphoreIF::SEMAPHORE_NOT_OWNED;
} }
vTaskNotifyGiveFromISR(taskHandle, higherPriorityTaskWoken); vTaskNotifyGiveFromISR(taskHandle, higherPriorityTaskWoken);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
uint8_t BinarySemaphoreUsingTask::getSemaphoreCounterFromISR( uint8_t BinarySemaphoreUsingTask::getSemaphoreCounterFromISR(
TaskHandle_t taskHandle, BaseType_t* higherPriorityTaskWoken) { TaskHandle_t taskHandle, BaseType_t* higherPriorityTaskWoken) {
uint32_t notificationValue = 0; uint32_t notificationValue = 0;
xTaskNotifyAndQueryFromISR(taskHandle, 0, eNoAction, &notificationValue, xTaskNotifyAndQueryFromISR(taskHandle, 0, eNoAction, &notificationValue,
higherPriorityTaskWoken); higherPriorityTaskWoken);
return notificationValue; return notificationValue;
} }

View File

@ -1,76 +1,76 @@
#ifndef FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ #ifndef FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_
#define FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ #define FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_
#include "../../returnvalues/HasReturnvaluesIF.h" #include "../../returnvalues/HasReturnvaluesIF.h"
#include "../../tasks/SemaphoreIF.h" #include "../../tasks/SemaphoreIF.h"
#include <freertos/FreeRTOS.h> #include <freertos/FreeRTOS.h>
#include <freertos/task.h> #include <freertos/task.h>
/** /**
* @brief Binary Semaphore implementation using the task notification value. * @brief Binary Semaphore implementation using the task notification value.
* The notification value should therefore not be used * The notification value should therefore not be used
* for other purposes. * for other purposes.
* @details * @details
* Additional information: https://www.freertos.org/RTOS-task-notifications.html * Additional information: https://www.freertos.org/RTOS-task-notifications.html
* and general semaphore documentation. * and general semaphore documentation.
*/ */
class BinarySemaphoreUsingTask: public SemaphoreIF, class BinarySemaphoreUsingTask: public SemaphoreIF,
public HasReturnvaluesIF { public HasReturnvaluesIF {
public: public:
static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF;
//! @brief Default ctor //! @brief Default ctor
BinarySemaphoreUsingTask(); BinarySemaphoreUsingTask();
//! @brief Default dtor //! @brief Default dtor
virtual~ BinarySemaphoreUsingTask(); virtual~ BinarySemaphoreUsingTask();
ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING, ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING,
uint32_t timeoutMs = portMAX_DELAY) override; uint32_t timeoutMs = portMAX_DELAY) override;
ReturnValue_t release() override; ReturnValue_t release() override;
uint8_t getSemaphoreCounter() const override; uint8_t getSemaphoreCounter() const override;
static uint8_t getSemaphoreCounter(TaskHandle_t taskHandle); static uint8_t getSemaphoreCounter(TaskHandle_t taskHandle);
static uint8_t getSemaphoreCounterFromISR(TaskHandle_t taskHandle, static uint8_t getSemaphoreCounterFromISR(TaskHandle_t taskHandle,
BaseType_t* higherPriorityTaskWoken); BaseType_t* higherPriorityTaskWoken);
/** /**
* Same as acquire() with timeout in FreeRTOS ticks. * Same as acquire() with timeout in FreeRTOS ticks.
* @param timeoutTicks * @param timeoutTicks
* @return - @c RETURN_OK on success * @return - @c RETURN_OK on success
* - @c RETURN_FAILED on failure * - @c RETURN_FAILED on failure
*/ */
ReturnValue_t acquireWithTickTimeout( ReturnValue_t acquireWithTickTimeout(
TimeoutType timeoutType = TimeoutType::BLOCKING, TimeoutType timeoutType = TimeoutType::BLOCKING,
TickType_t timeoutTicks = portMAX_DELAY); TickType_t timeoutTicks = portMAX_DELAY);
/** /**
* Get handle to the task related to the semaphore. * Get handle to the task related to the semaphore.
* @return * @return
*/ */
TaskHandle_t getTaskHandle(); TaskHandle_t getTaskHandle();
/** /**
* Wrapper function to give back semaphore from handle * Wrapper function to give back semaphore from handle
* @param semaphore * @param semaphore
* @return - @c RETURN_OK on success * @return - @c RETURN_OK on success
* - @c RETURN_FAILED on failure * - @c RETURN_FAILED on failure
*/ */
static ReturnValue_t release(TaskHandle_t taskToNotify); static ReturnValue_t release(TaskHandle_t taskToNotify);
/** /**
* Wrapper function to give back semaphore from handle when called from an ISR * Wrapper function to give back semaphore from handle when called from an ISR
* @param semaphore * @param semaphore
* @param higherPriorityTaskWoken This will be set to pdPASS if a task with * @param higherPriorityTaskWoken This will be set to pdPASS if a task with
* a higher priority was unblocked. A context switch should be requested * a higher priority was unblocked. A context switch should be requested
* from an ISR if this is the case (see TaskManagement functions) * from an ISR if this is the case (see TaskManagement functions)
* @return - @c RETURN_OK on success * @return - @c RETURN_OK on success
* - @c RETURN_FAILED on failure * - @c RETURN_FAILED on failure
*/ */
static ReturnValue_t releaseFromISR(TaskHandle_t taskToNotify, static ReturnValue_t releaseFromISR(TaskHandle_t taskToNotify,
BaseType_t * higherPriorityTaskWoken); BaseType_t * higherPriorityTaskWoken);
protected: protected:
TaskHandle_t handle; TaskHandle_t handle;
}; };
#endif /* FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ */ #endif /* FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ */

View File

@ -1,108 +1,108 @@
#include "../../osal/FreeRTOS/BinarySemaphore.h" #include "../../osal/FreeRTOS/BinarySemaphore.h"
#include "../../osal/FreeRTOS/TaskManagement.h" #include "../../osal/FreeRTOS/TaskManagement.h"
#include "../../serviceinterface/ServiceInterfaceStream.h" #include "../../serviceinterface/ServiceInterfaceStream.h"
BinarySemaphore::BinarySemaphore() { BinarySemaphore::BinarySemaphore() {
handle = xSemaphoreCreateBinary(); handle = xSemaphoreCreateBinary();
if(handle == nullptr) { if(handle == nullptr) {
sif::error << "Semaphore: Binary semaph creation failure" << std::endl; sif::error << "Semaphore: Binary semaph creation failure" << std::endl;
} }
// Initiated semaphore must be given before it can be taken. // Initiated semaphore must be given before it can be taken.
xSemaphoreGive(handle); xSemaphoreGive(handle);
} }
BinarySemaphore::~BinarySemaphore() { BinarySemaphore::~BinarySemaphore() {
vSemaphoreDelete(handle); vSemaphoreDelete(handle);
} }
BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) { BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) {
handle = xSemaphoreCreateBinary(); handle = xSemaphoreCreateBinary();
if(handle == nullptr) { if(handle == nullptr) {
sif::error << "Binary semaphore creation failure" << std::endl; sif::error << "Binary semaphore creation failure" << std::endl;
} }
xSemaphoreGive(handle); xSemaphoreGive(handle);
} }
BinarySemaphore& BinarySemaphore::operator =( BinarySemaphore& BinarySemaphore::operator =(
BinarySemaphore&& s) { BinarySemaphore&& s) {
if(&s != this) { if(&s != this) {
handle = xSemaphoreCreateBinary(); handle = xSemaphoreCreateBinary();
if(handle == nullptr) { if(handle == nullptr) {
sif::error << "Binary semaphore creation failure" << std::endl; sif::error << "Binary semaphore creation failure" << std::endl;
} }
xSemaphoreGive(handle); xSemaphoreGive(handle);
} }
return *this; return *this;
} }
ReturnValue_t BinarySemaphore::acquire(TimeoutType timeoutType, ReturnValue_t BinarySemaphore::acquire(TimeoutType timeoutType,
uint32_t timeoutMs) { uint32_t timeoutMs) {
TickType_t timeout = 0; TickType_t timeout = 0;
if(timeoutType == TimeoutType::POLLING) { if(timeoutType == TimeoutType::POLLING) {
timeout = 0; timeout = 0;
} }
else if(timeoutType == TimeoutType::WAITING){ else if(timeoutType == TimeoutType::WAITING){
timeout = pdMS_TO_TICKS(timeoutMs); timeout = pdMS_TO_TICKS(timeoutMs);
} }
else { else {
timeout = portMAX_DELAY; timeout = portMAX_DELAY;
} }
return acquireWithTickTimeout(timeoutType, timeout); return acquireWithTickTimeout(timeoutType, timeout);
} }
ReturnValue_t BinarySemaphore::acquireWithTickTimeout(TimeoutType timeoutType, ReturnValue_t BinarySemaphore::acquireWithTickTimeout(TimeoutType timeoutType,
TickType_t timeoutTicks) { TickType_t timeoutTicks) {
if(handle == nullptr) { if(handle == nullptr) {
return SemaphoreIF::SEMAPHORE_INVALID; return SemaphoreIF::SEMAPHORE_INVALID;
} }
BaseType_t returncode = xSemaphoreTake(handle, timeoutTicks); BaseType_t returncode = xSemaphoreTake(handle, timeoutTicks);
if (returncode == pdPASS) { if (returncode == pdPASS) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
else { else {
return SemaphoreIF::SEMAPHORE_TIMEOUT; return SemaphoreIF::SEMAPHORE_TIMEOUT;
} }
} }
ReturnValue_t BinarySemaphore::release() { ReturnValue_t BinarySemaphore::release() {
return release(handle); return release(handle);
} }
ReturnValue_t BinarySemaphore::release(SemaphoreHandle_t semaphore) { ReturnValue_t BinarySemaphore::release(SemaphoreHandle_t semaphore) {
if (semaphore == nullptr) { if (semaphore == nullptr) {
return SemaphoreIF::SEMAPHORE_INVALID; return SemaphoreIF::SEMAPHORE_INVALID;
} }
BaseType_t returncode = xSemaphoreGive(semaphore); BaseType_t returncode = xSemaphoreGive(semaphore);
if (returncode == pdPASS) { if (returncode == pdPASS) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
else { else {
return SemaphoreIF::SEMAPHORE_NOT_OWNED; return SemaphoreIF::SEMAPHORE_NOT_OWNED;
} }
} }
uint8_t BinarySemaphore::getSemaphoreCounter() const { uint8_t BinarySemaphore::getSemaphoreCounter() const {
return uxSemaphoreGetCount(handle); return uxSemaphoreGetCount(handle);
} }
SemaphoreHandle_t BinarySemaphore::getSemaphore() { SemaphoreHandle_t BinarySemaphore::getSemaphore() {
return handle; return handle;
} }
// Be careful with the stack size here. This is called from an ISR! // Be careful with the stack size here. This is called from an ISR!
ReturnValue_t BinarySemaphore::releaseFromISR( ReturnValue_t BinarySemaphore::releaseFromISR(
SemaphoreHandle_t semaphore, BaseType_t * higherPriorityTaskWoken) { SemaphoreHandle_t semaphore, BaseType_t * higherPriorityTaskWoken) {
if (semaphore == nullptr) { if (semaphore == nullptr) {
return SemaphoreIF::SEMAPHORE_INVALID; return SemaphoreIF::SEMAPHORE_INVALID;
} }
BaseType_t returncode = xSemaphoreGiveFromISR(semaphore, BaseType_t returncode = xSemaphoreGiveFromISR(semaphore,
higherPriorityTaskWoken); higherPriorityTaskWoken);
if (returncode == pdPASS) { if (returncode == pdPASS) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
else { else {
return SemaphoreIF::SEMAPHORE_NOT_OWNED; return SemaphoreIF::SEMAPHORE_NOT_OWNED;
} }
} }

View File

@ -1,107 +1,107 @@
#ifndef FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ #ifndef FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_
#define FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ #define FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_
#include "../../returnvalues/HasReturnvaluesIF.h" #include "../../returnvalues/HasReturnvaluesIF.h"
#include "../../tasks/SemaphoreIF.h" #include "../../tasks/SemaphoreIF.h"
#include <freertos/FreeRTOS.h> #include <freertos/FreeRTOS.h>
#include <freertos/semphr.h> #include <freertos/semphr.h>
/** /**
* @brief OS Tool to achieve synchronization of between tasks or between * @brief OS Tool to achieve synchronization of between tasks or between
* task and ISR. The default semaphore implementation creates a * task and ISR. The default semaphore implementation creates a
* binary semaphore, which can only be taken once. * binary semaphore, which can only be taken once.
* @details * @details
* Documentation: https://www.freertos.org/Embedded-RTOS-Binary-Semaphores.html * Documentation: https://www.freertos.org/Embedded-RTOS-Binary-Semaphores.html
* *
* Please note that if the semaphore implementation is only related to * Please note that if the semaphore implementation is only related to
* the synchronization of one task, the new task notifications can be used, * the synchronization of one task, the new task notifications can be used,
* also see the BinSemaphUsingTask and CountingSemaphUsingTask classes. * also see the BinSemaphUsingTask and CountingSemaphUsingTask classes.
* These use the task notification value instead of a queue and are * These use the task notification value instead of a queue and are
* faster and more efficient. * faster and more efficient.
* *
* @author R. Mueller * @author R. Mueller
* @ingroup osal * @ingroup osal
*/ */
class BinarySemaphore: public SemaphoreIF, class BinarySemaphore: public SemaphoreIF,
public HasReturnvaluesIF { public HasReturnvaluesIF {
public: public:
static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF;
//! @brief Default ctor //! @brief Default ctor
BinarySemaphore(); BinarySemaphore();
//! @brief Copy ctor, deleted explicitely. //! @brief Copy ctor, deleted explicitely.
BinarySemaphore(const BinarySemaphore&) = delete; BinarySemaphore(const BinarySemaphore&) = delete;
//! @brief Copy assignment, deleted explicitely. //! @brief Copy assignment, deleted explicitely.
BinarySemaphore& operator=(const BinarySemaphore&) = delete; BinarySemaphore& operator=(const BinarySemaphore&) = delete;
//! @brief Move ctor //! @brief Move ctor
BinarySemaphore (BinarySemaphore &&); BinarySemaphore (BinarySemaphore &&);
//! @brief Move assignment //! @brief Move assignment
BinarySemaphore & operator=(BinarySemaphore &&); BinarySemaphore & operator=(BinarySemaphore &&);
//! @brief Destructor //! @brief Destructor
virtual ~BinarySemaphore(); virtual ~BinarySemaphore();
uint8_t getSemaphoreCounter() const override; uint8_t getSemaphoreCounter() const override;
/** /**
* Take the binary semaphore. * Take the binary semaphore.
* If the semaphore has already been taken, the task will be blocked * If the semaphore has already been taken, the task will be blocked
* for a maximum of #timeoutMs or until the semaphore is given back, * for a maximum of #timeoutMs or until the semaphore is given back,
* for example by an ISR or another task. * for example by an ISR or another task.
* @param timeoutMs * @param timeoutMs
* @return -@c RETURN_OK on success * @return -@c RETURN_OK on success
* -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout
*/ */
ReturnValue_t acquire(TimeoutType timeoutType = ReturnValue_t acquire(TimeoutType timeoutType =
TimeoutType::BLOCKING, uint32_t timeoutMs = portMAX_DELAY) override; TimeoutType::BLOCKING, uint32_t timeoutMs = portMAX_DELAY) override;
/** /**
* Same as lockBinarySemaphore() with timeout in FreeRTOS ticks. * Same as lockBinarySemaphore() with timeout in FreeRTOS ticks.
* @param timeoutTicks * @param timeoutTicks
* @return -@c RETURN_OK on success * @return -@c RETURN_OK on success
* -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout
*/ */
ReturnValue_t acquireWithTickTimeout(TimeoutType timeoutType = ReturnValue_t acquireWithTickTimeout(TimeoutType timeoutType =
TimeoutType::BLOCKING, TickType_t timeoutTicks = portMAX_DELAY); TimeoutType::BLOCKING, TickType_t timeoutTicks = portMAX_DELAY);
/** /**
* Release the binary semaphore. * Release the binary semaphore.
* @return -@c RETURN_OK on success * @return -@c RETURN_OK on success
* -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is
* already available. * already available.
*/ */
ReturnValue_t release() override; ReturnValue_t release() override;
/** /**
* Get Handle to the semaphore. * Get Handle to the semaphore.
* @return * @return
*/ */
SemaphoreHandle_t getSemaphore(); SemaphoreHandle_t getSemaphore();
/** /**
* Wrapper function to give back semaphore from handle * Wrapper function to give back semaphore from handle
* @param semaphore * @param semaphore
* @return -@c RETURN_OK on success * @return -@c RETURN_OK on success
* -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is
* already available. * already available.
*/ */
static ReturnValue_t release(SemaphoreHandle_t semaphore); static ReturnValue_t release(SemaphoreHandle_t semaphore);
/** /**
* Wrapper function to give back semaphore from handle when called from an ISR * Wrapper function to give back semaphore from handle when called from an ISR
* @param semaphore * @param semaphore
* @param higherPriorityTaskWoken This will be set to pdPASS if a task with * @param higherPriorityTaskWoken This will be set to pdPASS if a task with
* a higher priority was unblocked. A context switch from an ISR should * a higher priority was unblocked. A context switch from an ISR should
* then be requested (see TaskManagement functions) * then be requested (see TaskManagement functions)
* @return -@c RETURN_OK on success * @return -@c RETURN_OK on success
* -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is
* already available. * already available.
*/ */
static ReturnValue_t releaseFromISR(SemaphoreHandle_t semaphore, static ReturnValue_t releaseFromISR(SemaphoreHandle_t semaphore,
BaseType_t * higherPriorityTaskWoken); BaseType_t * higherPriorityTaskWoken);
protected: protected:
SemaphoreHandle_t handle; SemaphoreHandle_t handle;
}; };
#endif /* FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */ #endif /* FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */

View File

@ -1,114 +1,114 @@
#include "../../osal/FreeRTOS/CountingSemaphUsingTask.h" #include "../../osal/FreeRTOS/CountingSemaphUsingTask.h"
#include "../../osal/FreeRTOS/TaskManagement.h" #include "../../osal/FreeRTOS/TaskManagement.h"
#include "../../serviceinterface/ServiceInterfaceStream.h" #include "../../serviceinterface/ServiceInterfaceStream.h"
CountingSemaphoreUsingTask::CountingSemaphoreUsingTask(const uint8_t maxCount, CountingSemaphoreUsingTask::CountingSemaphoreUsingTask(const uint8_t maxCount,
uint8_t initCount): maxCount(maxCount) { uint8_t initCount): maxCount(maxCount) {
if(initCount > maxCount) { if(initCount > maxCount) {
sif::error << "CountingSemaphoreUsingTask: Max count bigger than " sif::error << "CountingSemaphoreUsingTask: Max count bigger than "
"intial cout. Setting initial count to max count." << std::endl; "intial cout. Setting initial count to max count." << std::endl;
initCount = maxCount; initCount = maxCount;
} }
handle = TaskManagement::getCurrentTaskHandle(); handle = TaskManagement::getCurrentTaskHandle();
if(handle == nullptr) { if(handle == nullptr) {
sif::error << "CountingSemaphoreUsingTask: Could not retrieve task " sif::error << "CountingSemaphoreUsingTask: Could not retrieve task "
"handle. Please ensure the constructor was called inside a " "handle. Please ensure the constructor was called inside a "
"task." << std::endl; "task." << std::endl;
} }
uint32_t oldNotificationValue; uint32_t oldNotificationValue;
xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite,
&oldNotificationValue); &oldNotificationValue);
if(oldNotificationValue != 0) { if(oldNotificationValue != 0) {
sif::warning << "CountinSemaphoreUsingTask: Semaphore initiated but " sif::warning << "CountinSemaphoreUsingTask: Semaphore initiated but "
"current notification value is not 0. Please ensure the " "current notification value is not 0. Please ensure the "
"notification value is not used for other purposes!" << std::endl; "notification value is not used for other purposes!" << std::endl;
} }
for(int i = 0; i < initCount; i++) { for(int i = 0; i < initCount; i++) {
xTaskNotifyGive(handle); xTaskNotifyGive(handle);
} }
} }
CountingSemaphoreUsingTask::~CountingSemaphoreUsingTask() { CountingSemaphoreUsingTask::~CountingSemaphoreUsingTask() {
// Clear notification value on destruction. // Clear notification value on destruction.
// If this is not desired, don't call the destructor // If this is not desired, don't call the destructor
// (or implement a boolean which disables the reset) // (or implement a boolean which disables the reset)
xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, nullptr); xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, nullptr);
} }
ReturnValue_t CountingSemaphoreUsingTask::acquire(TimeoutType timeoutType, ReturnValue_t CountingSemaphoreUsingTask::acquire(TimeoutType timeoutType,
uint32_t timeoutMs) { uint32_t timeoutMs) {
TickType_t timeout = 0; TickType_t timeout = 0;
if(timeoutType == TimeoutType::POLLING) { if(timeoutType == TimeoutType::POLLING) {
timeout = 0; timeout = 0;
} }
else if(timeoutType == TimeoutType::WAITING){ else if(timeoutType == TimeoutType::WAITING){
timeout = pdMS_TO_TICKS(timeoutMs); timeout = pdMS_TO_TICKS(timeoutMs);
} }
else { else {
timeout = portMAX_DELAY; timeout = portMAX_DELAY;
} }
return acquireWithTickTimeout(timeoutType, timeout); return acquireWithTickTimeout(timeoutType, timeout);
} }
ReturnValue_t CountingSemaphoreUsingTask::acquireWithTickTimeout( ReturnValue_t CountingSemaphoreUsingTask::acquireWithTickTimeout(
TimeoutType timeoutType, TickType_t timeoutTicks) { TimeoutType timeoutType, TickType_t timeoutTicks) {
// Decrement notfication value without resetting it. // Decrement notfication value without resetting it.
BaseType_t oldCount = ulTaskNotifyTake(pdFALSE, timeoutTicks); BaseType_t oldCount = ulTaskNotifyTake(pdFALSE, timeoutTicks);
if (getSemaphoreCounter() == oldCount - 1) { if (getSemaphoreCounter() == oldCount - 1) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
else { else {
return SemaphoreIF::SEMAPHORE_TIMEOUT; return SemaphoreIF::SEMAPHORE_TIMEOUT;
} }
} }
ReturnValue_t CountingSemaphoreUsingTask::release() { ReturnValue_t CountingSemaphoreUsingTask::release() {
if(getSemaphoreCounter() == maxCount) { if(getSemaphoreCounter() == maxCount) {
return SemaphoreIF::SEMAPHORE_NOT_OWNED; return SemaphoreIF::SEMAPHORE_NOT_OWNED;
} }
return release(handle); return release(handle);
} }
ReturnValue_t CountingSemaphoreUsingTask::release( ReturnValue_t CountingSemaphoreUsingTask::release(
TaskHandle_t taskToNotify) { TaskHandle_t taskToNotify) {
BaseType_t returncode = xTaskNotifyGive(taskToNotify); BaseType_t returncode = xTaskNotifyGive(taskToNotify);
if (returncode == pdPASS) { if (returncode == pdPASS) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
else { else {
// This should never happen. // This should never happen.
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
} }
uint8_t CountingSemaphoreUsingTask::getSemaphoreCounter() const { uint8_t CountingSemaphoreUsingTask::getSemaphoreCounter() const {
uint32_t notificationValue = 0; uint32_t notificationValue = 0;
xTaskNotifyAndQuery(handle, 0, eNoAction, &notificationValue); xTaskNotifyAndQuery(handle, 0, eNoAction, &notificationValue);
return notificationValue; return notificationValue;
} }
TaskHandle_t CountingSemaphoreUsingTask::getTaskHandle() { TaskHandle_t CountingSemaphoreUsingTask::getTaskHandle() {
return handle; return handle;
} }
ReturnValue_t CountingSemaphoreUsingTask::releaseFromISR( ReturnValue_t CountingSemaphoreUsingTask::releaseFromISR(
TaskHandle_t taskToNotify, BaseType_t* higherPriorityTaskWoken) { TaskHandle_t taskToNotify, BaseType_t* higherPriorityTaskWoken) {
vTaskNotifyGiveFromISR(taskToNotify, higherPriorityTaskWoken); vTaskNotifyGiveFromISR(taskToNotify, higherPriorityTaskWoken);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
uint8_t CountingSemaphoreUsingTask::getSemaphoreCounterFromISR( uint8_t CountingSemaphoreUsingTask::getSemaphoreCounterFromISR(
TaskHandle_t task, BaseType_t* higherPriorityTaskWoken) { TaskHandle_t task, BaseType_t* higherPriorityTaskWoken) {
uint32_t notificationValue; uint32_t notificationValue;
xTaskNotifyAndQueryFromISR(task, 0, eNoAction, &notificationValue, xTaskNotifyAndQueryFromISR(task, 0, eNoAction, &notificationValue,
higherPriorityTaskWoken); higherPriorityTaskWoken);
return notificationValue; return notificationValue;
} }
uint8_t CountingSemaphoreUsingTask::getMaxCount() const { uint8_t CountingSemaphoreUsingTask::getMaxCount() const {
return maxCount; return maxCount;
} }

View File

@ -1,102 +1,102 @@
#ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ #ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_
#define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ #define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_
#include "../../osal/FreeRTOS/CountingSemaphUsingTask.h" #include "../../osal/FreeRTOS/CountingSemaphUsingTask.h"
#include "../../tasks/SemaphoreIF.h" #include "../../tasks/SemaphoreIF.h"
extern "C" { extern "C" {
#include <freertos/FreeRTOS.h> #include <freertos/FreeRTOS.h>
#include <freertos/task.h> #include <freertos/task.h>
} }
/** /**
* @brief Couting Semaphore implementation which uses the notification value * @brief Couting Semaphore implementation which uses the notification value
* of the task. The notification value should therefore not be used * of the task. The notification value should therefore not be used
* for other purposes. * for other purposes.
* @details * @details
* Additional information: https://www.freertos.org/RTOS-task-notifications.html * Additional information: https://www.freertos.org/RTOS-task-notifications.html
* and general semaphore documentation. * and general semaphore documentation.
*/ */
class CountingSemaphoreUsingTask: public SemaphoreIF { class CountingSemaphoreUsingTask: public SemaphoreIF {
public: public:
CountingSemaphoreUsingTask(const uint8_t maxCount, uint8_t initCount); CountingSemaphoreUsingTask(const uint8_t maxCount, uint8_t initCount);
virtual ~CountingSemaphoreUsingTask(); virtual ~CountingSemaphoreUsingTask();
/** /**
* Acquire the counting semaphore. * Acquire the counting semaphore.
* If no semaphores are available, the task will be blocked * If no semaphores are available, the task will be blocked
* for a maximum of #timeoutMs or until one is given back, * for a maximum of #timeoutMs or until one is given back,
* for example by an ISR or another task. * for example by an ISR or another task.
* @param timeoutMs * @param timeoutMs
* @return -@c RETURN_OK on success * @return -@c RETURN_OK on success
* -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout
*/ */
ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING, ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING,
uint32_t timeoutMs = portMAX_DELAY) override; uint32_t timeoutMs = portMAX_DELAY) override;
/** /**
* Release a semaphore, increasing the number of available counting * Release a semaphore, increasing the number of available counting
* semaphores up to the #maxCount value. * semaphores up to the #maxCount value.
* @return -@c RETURN_OK on success * @return -@c RETURN_OK on success
* -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are
* already available. * already available.
*/ */
ReturnValue_t release() override; ReturnValue_t release() override;
uint8_t getSemaphoreCounter() const override; uint8_t getSemaphoreCounter() const override;
/** /**
* Get the semaphore counter from an ISR. * Get the semaphore counter from an ISR.
* @param task * @param task
* @param higherPriorityTaskWoken This will be set to pdPASS if a task with * @param higherPriorityTaskWoken This will be set to pdPASS if a task with
* a higher priority was unblocked. A context switch should be requested * a higher priority was unblocked. A context switch should be requested
* from an ISR if this is the case (see TaskManagement functions) * from an ISR if this is the case (see TaskManagement functions)
* @return * @return
*/ */
static uint8_t getSemaphoreCounterFromISR(TaskHandle_t task, static uint8_t getSemaphoreCounterFromISR(TaskHandle_t task,
BaseType_t* higherPriorityTaskWoken); BaseType_t* higherPriorityTaskWoken);
/** /**
* Acquire with a timeout value in ticks * Acquire with a timeout value in ticks
* @param timeoutTicks * @param timeoutTicks
* @return -@c RETURN_OK on success * @return -@c RETURN_OK on success
* -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout
*/ */
ReturnValue_t acquireWithTickTimeout( ReturnValue_t acquireWithTickTimeout(
TimeoutType timeoutType = TimeoutType::BLOCKING, TimeoutType timeoutType = TimeoutType::BLOCKING,
TickType_t timeoutTicks = portMAX_DELAY); TickType_t timeoutTicks = portMAX_DELAY);
/** /**
* Get handle to the task related to the semaphore. * Get handle to the task related to the semaphore.
* @return * @return
*/ */
TaskHandle_t getTaskHandle(); TaskHandle_t getTaskHandle();
/** /**
* Release semaphore of task by supplying task handle * Release semaphore of task by supplying task handle
* @param taskToNotify * @param taskToNotify
* @return -@c RETURN_OK on success * @return -@c RETURN_OK on success
* -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are
* already available. * already available.
*/ */
static ReturnValue_t release(TaskHandle_t taskToNotify); static ReturnValue_t release(TaskHandle_t taskToNotify);
/** /**
* Release seamphore of a task from an ISR. * Release seamphore of a task from an ISR.
* @param taskToNotify * @param taskToNotify
* @param higherPriorityTaskWoken This will be set to pdPASS if a task with * @param higherPriorityTaskWoken This will be set to pdPASS if a task with
* a higher priority was unblocked. A context switch should be requested * a higher priority was unblocked. A context switch should be requested
* from an ISR if this is the case (see TaskManagement functions) * from an ISR if this is the case (see TaskManagement functions)
* @return -@c RETURN_OK on success * @return -@c RETURN_OK on success
* -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are
* already available. * already available.
*/ */
static ReturnValue_t releaseFromISR(TaskHandle_t taskToNotify, static ReturnValue_t releaseFromISR(TaskHandle_t taskToNotify,
BaseType_t* higherPriorityTaskWoken); BaseType_t* higherPriorityTaskWoken);
uint8_t getMaxCount() const; uint8_t getMaxCount() const;
private: private:
TaskHandle_t handle; TaskHandle_t handle;
const uint8_t maxCount; const uint8_t maxCount;
}; };
#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ */ #endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ */

View File

@ -1,43 +1,43 @@
#include "../../osal/FreeRTOS/CountingSemaphore.h" #include "../../osal/FreeRTOS/CountingSemaphore.h"
#include "../../serviceinterface/ServiceInterfaceStream.h" #include "../../serviceinterface/ServiceInterfaceStream.h"
#include "../../osal/FreeRTOS/TaskManagement.h" #include "../../osal/FreeRTOS/TaskManagement.h"
#include <freertos/semphr.h> #include <freertos/semphr.h>
// Make sure #define configUSE_COUNTING_SEMAPHORES 1 is set in // Make sure #define configUSE_COUNTING_SEMAPHORES 1 is set in
// free FreeRTOSConfig.h file. // free FreeRTOSConfig.h file.
CountingSemaphore::CountingSemaphore(const uint8_t maxCount, uint8_t initCount): CountingSemaphore::CountingSemaphore(const uint8_t maxCount, uint8_t initCount):
maxCount(maxCount), initCount(initCount) { maxCount(maxCount), initCount(initCount) {
if(initCount > maxCount) { if(initCount > maxCount) {
sif::error << "CountingSemaphoreUsingTask: Max count bigger than " sif::error << "CountingSemaphoreUsingTask: Max count bigger than "
"intial cout. Setting initial count to max count." << std::endl; "intial cout. Setting initial count to max count." << std::endl;
initCount = maxCount; initCount = maxCount;
} }
handle = xSemaphoreCreateCounting(maxCount, initCount); handle = xSemaphoreCreateCounting(maxCount, initCount);
if(handle == nullptr) { if(handle == nullptr) {
sif::error << "CountingSemaphore: Creation failure" << std::endl; sif::error << "CountingSemaphore: Creation failure" << std::endl;
} }
} }
CountingSemaphore::CountingSemaphore(CountingSemaphore&& other): CountingSemaphore::CountingSemaphore(CountingSemaphore&& other):
maxCount(other.maxCount), initCount(other.initCount) { maxCount(other.maxCount), initCount(other.initCount) {
handle = xSemaphoreCreateCounting(other.maxCount, other.initCount); handle = xSemaphoreCreateCounting(other.maxCount, other.initCount);
if(handle == nullptr) { if(handle == nullptr) {
sif::error << "CountingSemaphore: Creation failure" << std::endl; sif::error << "CountingSemaphore: Creation failure" << std::endl;
} }
} }
CountingSemaphore& CountingSemaphore::operator =( CountingSemaphore& CountingSemaphore::operator =(
CountingSemaphore&& other) { CountingSemaphore&& other) {
handle = xSemaphoreCreateCounting(other.maxCount, other.initCount); handle = xSemaphoreCreateCounting(other.maxCount, other.initCount);
if(handle == nullptr) { if(handle == nullptr) {
sif::error << "CountingSemaphore: Creation failure" << std::endl; sif::error << "CountingSemaphore: Creation failure" << std::endl;
} }
return * this; return * this;
} }
uint8_t CountingSemaphore::getMaxCount() const { uint8_t CountingSemaphore::getMaxCount() const {
return maxCount; return maxCount;
} }

View File

@ -1,34 +1,34 @@
#ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ #ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_
#define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ #define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_
#include "../../osal/FreeRTOS/BinarySemaphore.h" #include "../../osal/FreeRTOS/BinarySemaphore.h"
/** /**
* @brief Counting semaphores, which can be acquire more than once. * @brief Counting semaphores, which can be acquire more than once.
* @details * @details
* See: https://www.freertos.org/CreateCounting.html * See: https://www.freertos.org/CreateCounting.html
* API of counting semaphores is almost identical to binary semaphores, * API of counting semaphores is almost identical to binary semaphores,
* so we just inherit from binary semaphore and provide the respective * so we just inherit from binary semaphore and provide the respective
* constructors. * constructors.
*/ */
class CountingSemaphore: public BinarySemaphore { class CountingSemaphore: public BinarySemaphore {
public: public:
CountingSemaphore(const uint8_t maxCount, uint8_t initCount); CountingSemaphore(const uint8_t maxCount, uint8_t initCount);
//! @brief Copy ctor, disabled //! @brief Copy ctor, disabled
CountingSemaphore(const CountingSemaphore&) = delete; CountingSemaphore(const CountingSemaphore&) = delete;
//! @brief Copy assignment, disabled //! @brief Copy assignment, disabled
CountingSemaphore& operator=(const CountingSemaphore&) = delete; CountingSemaphore& operator=(const CountingSemaphore&) = delete;
//! @brief Move ctor //! @brief Move ctor
CountingSemaphore (CountingSemaphore &&); CountingSemaphore (CountingSemaphore &&);
//! @brief Move assignment //! @brief Move assignment
CountingSemaphore & operator=(CountingSemaphore &&); CountingSemaphore & operator=(CountingSemaphore &&);
/* Same API as binary semaphore otherwise. acquire() can be called /* Same API as binary semaphore otherwise. acquire() can be called
* until there are not semaphores left and release() can be called * until there are not semaphores left and release() can be called
* until maxCount is reached. */ * until maxCount is reached. */
uint8_t getMaxCount() const; uint8_t getMaxCount() const;
private: private:
const uint8_t maxCount; const uint8_t maxCount;
uint8_t initCount = 0; uint8_t initCount = 0;
}; };
#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ */ #endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ */

View File

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

View File

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

View File

@ -1,5 +1,6 @@
#include "MessageQueue.h" #include "MessageQueue.h"
#include "../../objectmanager/ObjectManagerIF.h"
#include "../../serviceinterface/ServiceInterfaceStream.h" #include "../../serviceinterface/ServiceInterfaceStream.h"
// TODO I guess we should have a way of checking if we are in an ISR and then use the "fromISR" versions of all calls // TODO I guess we should have a way of checking if we are in an ISR and then use the "fromISR" versions of all calls
@ -101,7 +102,8 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
reinterpret_cast<const void*>(message->getBuffer()), 0); reinterpret_cast<const void*>(message->getBuffer()), 0);
if (result != pdPASS) { if (result != pdPASS) {
if (!ignoreFault) { if (!ignoreFault) {
InternalErrorReporterIF* internalErrorReporter = objectManager->get<InternalErrorReporterIF>( InternalErrorReporterIF* internalErrorReporter =
objectManager->get<InternalErrorReporterIF>(
objects::INTERNAL_ERROR_REPORTER); objects::INTERNAL_ERROR_REPORTER);
if (internalErrorReporter != NULL) { if (internalErrorReporter != NULL) {
internalErrorReporter->queueMessageNotSent(); internalErrorReporter->queueMessageNotSent();

View File

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

View File

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

View File

@ -1,59 +1,59 @@
#include "../../osal/FreeRTOS/BinarySemaphore.h" #include "../../osal/FreeRTOS/BinarySemaphore.h"
#include "../../osal/FreeRTOS/BinSemaphUsingTask.h" #include "../../osal/FreeRTOS/BinSemaphUsingTask.h"
#include "../../osal/FreeRTOS/CountingSemaphore.h" #include "../../osal/FreeRTOS/CountingSemaphore.h"
#include "../../osal/FreeRTOS/CountingSemaphUsingTask.h" #include "../../osal/FreeRTOS/CountingSemaphUsingTask.h"
#include "../../tasks/SemaphoreFactory.h" #include "../../tasks/SemaphoreFactory.h"
#include "../../serviceinterface/ServiceInterfaceStream.h" #include "../../serviceinterface/ServiceInterfaceStream.h"
SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr;
static const uint32_t USE_REGULAR_SEMAPHORES = 0; static const uint32_t USE_REGULAR_SEMAPHORES = 0;
static const uint32_t USE_TASK_NOTIFICATIONS = 1; static const uint32_t USE_TASK_NOTIFICATIONS = 1;
SemaphoreFactory::SemaphoreFactory() { SemaphoreFactory::SemaphoreFactory() {
} }
SemaphoreFactory::~SemaphoreFactory() { SemaphoreFactory::~SemaphoreFactory() {
delete factoryInstance; delete factoryInstance;
} }
SemaphoreFactory* SemaphoreFactory::instance() { SemaphoreFactory* SemaphoreFactory::instance() {
if (factoryInstance == nullptr){ if (factoryInstance == nullptr){
factoryInstance = new SemaphoreFactory(); factoryInstance = new SemaphoreFactory();
} }
return SemaphoreFactory::factoryInstance; return SemaphoreFactory::factoryInstance;
} }
SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t argument) { SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t argument) {
if(argument == USE_REGULAR_SEMAPHORES) { if(argument == USE_REGULAR_SEMAPHORES) {
return new BinarySemaphore(); return new BinarySemaphore();
} }
else if(argument == USE_TASK_NOTIFICATIONS) { else if(argument == USE_TASK_NOTIFICATIONS) {
return new BinarySemaphoreUsingTask(); return new BinarySemaphoreUsingTask();
} }
else { else {
sif::warning << "SemaphoreFactory: Invalid argument, return regular" sif::warning << "SemaphoreFactory: Invalid argument, return regular"
"binary semaphore" << std::endl; "binary semaphore" << std::endl;
return new BinarySemaphore(); return new BinarySemaphore();
} }
} }
SemaphoreIF* SemaphoreFactory::createCountingSemaphore(uint8_t maxCount, SemaphoreIF* SemaphoreFactory::createCountingSemaphore(uint8_t maxCount,
uint8_t initCount, uint32_t argument) { uint8_t initCount, uint32_t argument) {
if(argument == USE_REGULAR_SEMAPHORES) { if(argument == USE_REGULAR_SEMAPHORES) {
return new CountingSemaphore(maxCount, initCount); return new CountingSemaphore(maxCount, initCount);
} }
else if(argument == USE_TASK_NOTIFICATIONS) { else if(argument == USE_TASK_NOTIFICATIONS) {
return new CountingSemaphoreUsingTask(maxCount, initCount); return new CountingSemaphoreUsingTask(maxCount, initCount);
} }
else { else {
sif::warning << "SemaphoreFactory: Invalid argument, return regular" sif::warning << "SemaphoreFactory: Invalid argument, return regular"
"binary semaphore" << std::endl; "binary semaphore" << std::endl;
return new CountingSemaphore(maxCount, initCount); return new CountingSemaphore(maxCount, initCount);
} }
} }
void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) { void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) {
delete semaphore; delete semaphore;
} }

View File

@ -1,24 +1,24 @@
#include "../../osal/FreeRTOS/TaskManagement.h" #include "../../osal/FreeRTOS/TaskManagement.h"
void TaskManagement::vRequestContextSwitchFromTask() { void TaskManagement::vRequestContextSwitchFromTask() {
vTaskDelay(0); vTaskDelay(0);
} }
void TaskManagement::requestContextSwitch( void TaskManagement::requestContextSwitch(
CallContext callContext = CallContext::TASK) { CallContext callContext = CallContext::TASK) {
if(callContext == CallContext::ISR) { if(callContext == CallContext::ISR) {
// This function depends on the partmacro.h definition for the specific device // This function depends on the partmacro.h definition for the specific device
vRequestContextSwitchFromISR(); vRequestContextSwitchFromISR();
} else { } else {
vRequestContextSwitchFromTask(); vRequestContextSwitchFromTask();
} }
} }
TaskHandle_t TaskManagement::getCurrentTaskHandle() { TaskHandle_t TaskManagement::getCurrentTaskHandle() {
return xTaskGetCurrentTaskHandle(); return xTaskGetCurrentTaskHandle();
} }
size_t TaskManagement::getTaskStackHighWatermark( size_t TaskManagement::getTaskStackHighWatermark(
TaskHandle_t task) { TaskHandle_t task) {
return uxTaskGetStackHighWaterMark(task) * sizeof(StackType_t); return uxTaskGetStackHighWaterMark(task) * sizeof(StackType_t);
} }

View File

@ -1,64 +1,64 @@
#ifndef FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ #ifndef FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_
#define FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ #define FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_
#include "../../returnvalues/HasReturnvaluesIF.h" #include "../../returnvalues/HasReturnvaluesIF.h"
extern "C" { extern "C" {
#include <freertos/FreeRTOS.h> #include <freertos/FreeRTOS.h>
#include <freertos/task.h> #include <freertos/task.h>
} }
#include <cstdint> #include <cstdint>
/** /**
* Architecture dependant portmacro.h function call. * Architecture dependant portmacro.h function call.
* Should be implemented in bsp. * Should be implemented in bsp.
*/ */
extern void vRequestContextSwitchFromISR(); extern void vRequestContextSwitchFromISR();
/*! /*!
* Used by functions to tell if they are being called from * Used by functions to tell if they are being called from
* within an ISR or from a regular task. This is required because FreeRTOS * within an ISR or from a regular task. This is required because FreeRTOS
* has different functions for handling semaphores and messages from within * has different functions for handling semaphores and messages from within
* an ISR and task. * an ISR and task.
*/ */
enum class CallContext { enum class CallContext {
TASK = 0x00,//!< task_context TASK = 0x00,//!< task_context
ISR = 0xFF //!< isr_context ISR = 0xFF //!< isr_context
}; };
class TaskManagement { class TaskManagement {
public: public:
/** /**
* @brief In this function, a function dependant on the portmacro.h header * @brief In this function, a function dependant on the portmacro.h header
* function calls to request a context switch can be specified. * function calls to request a context switch can be specified.
* This can be used if sending to the queue from an ISR caused a task * This can be used if sending to the queue from an ISR caused a task
* to unblock and a context switch is required. * to unblock and a context switch is required.
*/ */
static void requestContextSwitch(CallContext callContext); static void requestContextSwitch(CallContext callContext);
/** /**
* If task preemption in FreeRTOS is disabled, a context switch * If task preemption in FreeRTOS is disabled, a context switch
* can be requested manually by calling this function. * can be requested manually by calling this function.
*/ */
static void vRequestContextSwitchFromTask(void); static void vRequestContextSwitchFromTask(void);
/** /**
* @return The current task handle * @return The current task handle
*/ */
static TaskHandle_t getCurrentTaskHandle(); static TaskHandle_t getCurrentTaskHandle();
/** /**
* Get returns the minimum amount of remaining stack space in words * Get returns the minimum amount of remaining stack space in words
* that was a available to the task since the task started executing. * that was a available to the task since the task started executing.
* Please note that the actual value in bytes depends * Please note that the actual value in bytes depends
* on the stack depth type. * on the stack depth type.
* E.g. on a 32 bit machine, a value of 200 means 800 bytes. * E.g. on a 32 bit machine, a value of 200 means 800 bytes.
* @return Smallest value of stack remaining since the task was started in * @return Smallest value of stack remaining since the task was started in
* words. * words.
*/ */
static size_t getTaskStackHighWatermark( static size_t getTaskStackHighWatermark(
TaskHandle_t task = nullptr); TaskHandle_t task = nullptr);
}; };
#endif /* FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ */ #endif /* FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ */

View File

@ -1,149 +1,149 @@
#include "../../osal/linux/BinarySemaphore.h" #include "../../osal/linux/BinarySemaphore.h"
#include "../../serviceinterface/ServiceInterfaceStream.h" #include "../../serviceinterface/ServiceInterfaceStream.h"
extern "C" { extern "C" {
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
} }
BinarySemaphore::BinarySemaphore() { BinarySemaphore::BinarySemaphore() {
// Using unnamed semaphores for now // Using unnamed semaphores for now
initSemaphore(); initSemaphore();
} }
BinarySemaphore::~BinarySemaphore() { BinarySemaphore::~BinarySemaphore() {
sem_destroy(&handle); sem_destroy(&handle);
} }
BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) { BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) {
initSemaphore(); initSemaphore();
} }
BinarySemaphore& BinarySemaphore::operator =( BinarySemaphore& BinarySemaphore::operator =(
BinarySemaphore&& s) { BinarySemaphore&& s) {
initSemaphore(); initSemaphore();
return * this; return * this;
} }
ReturnValue_t BinarySemaphore::acquire(TimeoutType timeoutType, ReturnValue_t BinarySemaphore::acquire(TimeoutType timeoutType,
uint32_t timeoutMs) { uint32_t timeoutMs) {
int result = 0; int result = 0;
if(timeoutType == TimeoutType::POLLING) { if(timeoutType == TimeoutType::POLLING) {
result = sem_trywait(&handle); result = sem_trywait(&handle);
} }
else if(timeoutType == TimeoutType::BLOCKING) { else if(timeoutType == TimeoutType::BLOCKING) {
result = sem_wait(&handle); result = sem_wait(&handle);
} }
else if(timeoutType == TimeoutType::WAITING){ else if(timeoutType == TimeoutType::WAITING){
timespec timeOut; timespec timeOut;
clock_gettime(CLOCK_REALTIME, &timeOut); clock_gettime(CLOCK_REALTIME, &timeOut);
uint64_t nseconds = timeOut.tv_sec * 1000000000 + timeOut.tv_nsec; uint64_t nseconds = timeOut.tv_sec * 1000000000 + timeOut.tv_nsec;
nseconds += timeoutMs * 1000000; nseconds += timeoutMs * 1000000;
timeOut.tv_sec = nseconds / 1000000000; timeOut.tv_sec = nseconds / 1000000000;
timeOut.tv_nsec = nseconds - timeOut.tv_sec * 1000000000; timeOut.tv_nsec = nseconds - timeOut.tv_sec * 1000000000;
result = sem_timedwait(&handle, &timeOut); result = sem_timedwait(&handle, &timeOut);
if(result != 0 and errno == EINVAL) { if(result != 0 and errno == EINVAL) {
sif::debug << "BinarySemaphore::acquire: Invalid time value possible" sif::debug << "BinarySemaphore::acquire: Invalid time value possible"
<< std::endl; << std::endl;
} }
} }
if(result == 0) { if(result == 0) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
switch(errno) { switch(errno) {
case(EAGAIN): case(EAGAIN):
// Operation could not be performed without blocking (for sem_trywait) // Operation could not be performed without blocking (for sem_trywait)
case(ETIMEDOUT): case(ETIMEDOUT):
// Semaphore is 0 // Semaphore is 0
return SemaphoreIF::SEMAPHORE_TIMEOUT; return SemaphoreIF::SEMAPHORE_TIMEOUT;
case(EINVAL): case(EINVAL):
// Semaphore invalid // Semaphore invalid
return SemaphoreIF::SEMAPHORE_INVALID; return SemaphoreIF::SEMAPHORE_INVALID;
case(EINTR): case(EINTR):
// Call was interrupted by signal handler // Call was interrupted by signal handler
sif::debug << "BinarySemaphore::acquire: Signal handler interrupted." sif::debug << "BinarySemaphore::acquire: Signal handler interrupted."
"Code " << strerror(errno) << std::endl; "Code " << strerror(errno) << std::endl;
/* No break */ /* No break */
default: default:
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
} }
ReturnValue_t BinarySemaphore::release() { ReturnValue_t BinarySemaphore::release() {
return BinarySemaphore::release(&this->handle); return BinarySemaphore::release(&this->handle);
} }
ReturnValue_t BinarySemaphore::release(sem_t *handle) { ReturnValue_t BinarySemaphore::release(sem_t *handle) {
ReturnValue_t countResult = checkCount(handle, 1); ReturnValue_t countResult = checkCount(handle, 1);
if(countResult != HasReturnvaluesIF::RETURN_OK) { if(countResult != HasReturnvaluesIF::RETURN_OK) {
return countResult; return countResult;
} }
int result = sem_post(handle); int result = sem_post(handle);
if(result == 0) { if(result == 0) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
switch(errno) { switch(errno) {
case(EINVAL): case(EINVAL):
// Semaphore invalid // Semaphore invalid
return SemaphoreIF::SEMAPHORE_INVALID; return SemaphoreIF::SEMAPHORE_INVALID;
case(EOVERFLOW): case(EOVERFLOW):
// SEM_MAX_VALUE overflow. This should never happen // SEM_MAX_VALUE overflow. This should never happen
default: default:
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
} }
uint8_t BinarySemaphore::getSemaphoreCounter() const { uint8_t BinarySemaphore::getSemaphoreCounter() const {
// And another ugly cast :-D // And another ugly cast :-D
return getSemaphoreCounter(const_cast<sem_t*>(&this->handle)); return getSemaphoreCounter(const_cast<sem_t*>(&this->handle));
} }
uint8_t BinarySemaphore::getSemaphoreCounter(sem_t *handle) { uint8_t BinarySemaphore::getSemaphoreCounter(sem_t *handle) {
int value = 0; int value = 0;
int result = sem_getvalue(handle, &value); int result = sem_getvalue(handle, &value);
if (result == 0) { if (result == 0) {
return value; return value;
} }
else if(result != 0 and errno == EINVAL) { else if(result != 0 and errno == EINVAL) {
// Could be called from interrupt, use lightweight printf // Could be called from interrupt, use lightweight printf
printf("BinarySemaphore::getSemaphoreCounter: Invalid semaphore\n"); printf("BinarySemaphore::getSemaphoreCounter: Invalid semaphore\n");
return 0; return 0;
} }
else { else {
// This should never happen. // This should never happen.
return 0; return 0;
} }
} }
void BinarySemaphore::initSemaphore(uint8_t initCount) { void BinarySemaphore::initSemaphore(uint8_t initCount) {
auto result = sem_init(&handle, true, initCount); auto result = sem_init(&handle, true, initCount);
if(result == -1) { if(result == -1) {
switch(errno) { switch(errno) {
case(EINVAL): case(EINVAL):
// Value exceeds SEM_VALUE_MAX // Value exceeds SEM_VALUE_MAX
case(ENOSYS): case(ENOSYS):
// System does not support process-shared semaphores // System does not support process-shared semaphores
sif::error << "BinarySemaphore: Init failed with" << strerror(errno) sif::error << "BinarySemaphore: Init failed with" << strerror(errno)
<< std::endl; << std::endl;
} }
} }
} }
ReturnValue_t BinarySemaphore::checkCount(sem_t* handle, uint8_t maxCount) { ReturnValue_t BinarySemaphore::checkCount(sem_t* handle, uint8_t maxCount) {
int value = getSemaphoreCounter(handle); int value = getSemaphoreCounter(handle);
if(value >= maxCount) { if(value >= maxCount) {
if(maxCount == 1 and value > 1) { if(maxCount == 1 and value > 1) {
// Binary Semaphore special case. // Binary Semaphore special case.
// This is a config error use lightweight printf is this is called // This is a config error use lightweight printf is this is called
// from an interrupt // from an interrupt
printf("BinarySemaphore::release: Value of binary semaphore greater" printf("BinarySemaphore::release: Value of binary semaphore greater"
" than 1!\n"); " than 1!\n");
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
return SemaphoreIF::SEMAPHORE_NOT_OWNED; return SemaphoreIF::SEMAPHORE_NOT_OWNED;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -1,81 +1,81 @@
#ifndef FRAMEWORK_OSAL_LINUX_BINARYSEMPAHORE_H_ #ifndef FRAMEWORK_OSAL_LINUX_BINARYSEMPAHORE_H_
#define FRAMEWORK_OSAL_LINUX_BINARYSEMPAHORE_H_ #define FRAMEWORK_OSAL_LINUX_BINARYSEMPAHORE_H_
#include "../../returnvalues/HasReturnvaluesIF.h" #include "../../returnvalues/HasReturnvaluesIF.h"
#include "../../tasks/SemaphoreIF.h" #include "../../tasks/SemaphoreIF.h"
extern "C" { extern "C" {
#include <semaphore.h> #include <semaphore.h>
} }
/** /**
* @brief OS Tool to achieve synchronization of between tasks or between * @brief OS Tool to achieve synchronization of between tasks or between
* task and ISR. The default semaphore implementation creates a * task and ISR. The default semaphore implementation creates a
* binary semaphore, which can only be taken once. * binary semaphore, which can only be taken once.
* @details * @details
* See: http://www.man7.org/linux/man-pages/man7/sem_overview.7.html * See: http://www.man7.org/linux/man-pages/man7/sem_overview.7.html
* @author R. Mueller * @author R. Mueller
* @ingroup osal * @ingroup osal
*/ */
class BinarySemaphore: public SemaphoreIF, class BinarySemaphore: public SemaphoreIF,
public HasReturnvaluesIF { public HasReturnvaluesIF {
public: public:
static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF;
//! @brief Default ctor //! @brief Default ctor
BinarySemaphore(); BinarySemaphore();
//! @brief Copy ctor, deleted explicitely. //! @brief Copy ctor, deleted explicitely.
BinarySemaphore(const BinarySemaphore&) = delete; BinarySemaphore(const BinarySemaphore&) = delete;
//! @brief Copy assignment, deleted explicitely. //! @brief Copy assignment, deleted explicitely.
BinarySemaphore& operator=(const BinarySemaphore&) = delete; BinarySemaphore& operator=(const BinarySemaphore&) = delete;
//! @brief Move ctor //! @brief Move ctor
BinarySemaphore (BinarySemaphore &&); BinarySemaphore (BinarySemaphore &&);
//! @brief Move assignment //! @brief Move assignment
BinarySemaphore & operator=(BinarySemaphore &&); BinarySemaphore & operator=(BinarySemaphore &&);
//! @brief Destructor //! @brief Destructor
virtual ~BinarySemaphore(); virtual ~BinarySemaphore();
void initSemaphore(uint8_t initCount = 1); void initSemaphore(uint8_t initCount = 1);
uint8_t getSemaphoreCounter() const override; uint8_t getSemaphoreCounter() const override;
static uint8_t getSemaphoreCounter(sem_t* handle); static uint8_t getSemaphoreCounter(sem_t* handle);
/** /**
* Take the binary semaphore. * Take the binary semaphore.
* If the semaphore has already been taken, the task will be blocked * If the semaphore has already been taken, the task will be blocked
* for a maximum of #timeoutMs or until the semaphore is given back, * for a maximum of #timeoutMs or until the semaphore is given back,
* for example by an ISR or another task. * for example by an ISR or another task.
* @param timeoutMs * @param timeoutMs
* @return -@c RETURN_OK on success * @return -@c RETURN_OK on success
* -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout
*/ */
ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING, ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING,
uint32_t timeoutMs = 0) override; uint32_t timeoutMs = 0) override;
/** /**
* Release the binary semaphore. * Release the binary semaphore.
* @return -@c RETURN_OK on success * @return -@c RETURN_OK on success
* -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is
* already available. * already available.
*/ */
virtual ReturnValue_t release() override; virtual ReturnValue_t release() override;
/** /**
* This static function can be used to release a semaphore by providing * This static function can be used to release a semaphore by providing
* its handle. * its handle.
* @param handle * @param handle
* @return * @return
*/ */
static ReturnValue_t release(sem_t* handle); static ReturnValue_t release(sem_t* handle);
/** Checks the validity of the semaphore count against a specified /** Checks the validity of the semaphore count against a specified
* known maxCount * known maxCount
* @param handle * @param handle
* @param maxCount * @param maxCount
* @return * @return
*/ */
static ReturnValue_t checkCount(sem_t* handle, uint8_t maxCount); static ReturnValue_t checkCount(sem_t* handle, uint8_t maxCount);
protected: protected:
sem_t handle; sem_t handle;
}; };
#endif /* FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */ #endif /* FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */

View File

@ -6,8 +6,8 @@
#include <linux/sysinfo.h> #include <linux/sysinfo.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <fstream>
//#include <fstream>
uint16_t Clock::leapSeconds = 0; uint16_t Clock::leapSeconds = 0;
MutexIF* Clock::timeMutex = NULL; MutexIF* Clock::timeMutex = NULL;

View File

@ -1,54 +1,54 @@
#include "../../osal/linux/CountingSemaphore.h" #include "../../osal/linux/CountingSemaphore.h"
#include "../../serviceinterface/ServiceInterfaceStream.h" #include "../../serviceinterface/ServiceInterfaceStream.h"
CountingSemaphore::CountingSemaphore(const uint8_t maxCount, uint8_t initCount): CountingSemaphore::CountingSemaphore(const uint8_t maxCount, uint8_t initCount):
maxCount(maxCount), initCount(initCount) { maxCount(maxCount), initCount(initCount) {
if(initCount > maxCount) { if(initCount > maxCount) {
sif::error << "CountingSemaphoreUsingTask: Max count bigger than " sif::error << "CountingSemaphoreUsingTask: Max count bigger than "
"intial cout. Setting initial count to max count." << std::endl; "intial cout. Setting initial count to max count." << std::endl;
initCount = maxCount; initCount = maxCount;
} }
initSemaphore(initCount); initSemaphore(initCount);
} }
CountingSemaphore::CountingSemaphore(CountingSemaphore&& other): CountingSemaphore::CountingSemaphore(CountingSemaphore&& other):
maxCount(other.maxCount), initCount(other.initCount) { maxCount(other.maxCount), initCount(other.initCount) {
initSemaphore(initCount); initSemaphore(initCount);
} }
CountingSemaphore& CountingSemaphore::operator =( CountingSemaphore& CountingSemaphore::operator =(
CountingSemaphore&& other) { CountingSemaphore&& other) {
initSemaphore(other.initCount); initSemaphore(other.initCount);
return * this; return * this;
} }
ReturnValue_t CountingSemaphore::release() { ReturnValue_t CountingSemaphore::release() {
ReturnValue_t result = checkCount(&handle, maxCount); ReturnValue_t result = checkCount(&handle, maxCount);
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
return CountingSemaphore::release(&this->handle); return CountingSemaphore::release(&this->handle);
} }
ReturnValue_t CountingSemaphore::release(sem_t* handle) { ReturnValue_t CountingSemaphore::release(sem_t* handle) {
int result = sem_post(handle); int result = sem_post(handle);
if(result == 0) { if(result == 0) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
switch(errno) { switch(errno) {
case(EINVAL): case(EINVAL):
// Semaphore invalid // Semaphore invalid
return SemaphoreIF::SEMAPHORE_INVALID; return SemaphoreIF::SEMAPHORE_INVALID;
case(EOVERFLOW): case(EOVERFLOW):
// SEM_MAX_VALUE overflow. This should never happen // SEM_MAX_VALUE overflow. This should never happen
default: default:
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
} }
uint8_t CountingSemaphore::getMaxCount() const { uint8_t CountingSemaphore::getMaxCount() const {
return maxCount; return maxCount;
} }

View File

@ -1,37 +1,37 @@
#ifndef FRAMEWORK_OSAL_LINUX_COUNTINGSEMAPHORE_H_ #ifndef FRAMEWORK_OSAL_LINUX_COUNTINGSEMAPHORE_H_
#define FRAMEWORK_OSAL_LINUX_COUNTINGSEMAPHORE_H_ #define FRAMEWORK_OSAL_LINUX_COUNTINGSEMAPHORE_H_
#include "../../osal/linux/BinarySemaphore.h" #include "../../osal/linux/BinarySemaphore.h"
/** /**
* @brief Counting semaphores, which can be acquired more than once. * @brief Counting semaphores, which can be acquired more than once.
* @details * @details
* See: https://www.freertos.org/CreateCounting.html * See: https://www.freertos.org/CreateCounting.html
* API of counting semaphores is almost identical to binary semaphores, * API of counting semaphores is almost identical to binary semaphores,
* so we just inherit from binary semaphore and provide the respective * so we just inherit from binary semaphore and provide the respective
* constructors. * constructors.
*/ */
class CountingSemaphore: public BinarySemaphore { class CountingSemaphore: public BinarySemaphore {
public: public:
CountingSemaphore(const uint8_t maxCount, uint8_t initCount); CountingSemaphore(const uint8_t maxCount, uint8_t initCount);
//! @brief Copy ctor, disabled //! @brief Copy ctor, disabled
CountingSemaphore(const CountingSemaphore&) = delete; CountingSemaphore(const CountingSemaphore&) = delete;
//! @brief Copy assignment, disabled //! @brief Copy assignment, disabled
CountingSemaphore& operator=(const CountingSemaphore&) = delete; CountingSemaphore& operator=(const CountingSemaphore&) = delete;
//! @brief Move ctor //! @brief Move ctor
CountingSemaphore (CountingSemaphore &&); CountingSemaphore (CountingSemaphore &&);
//! @brief Move assignment //! @brief Move assignment
CountingSemaphore & operator=(CountingSemaphore &&); CountingSemaphore & operator=(CountingSemaphore &&);
ReturnValue_t release() override; ReturnValue_t release() override;
static ReturnValue_t release(sem_t* sem); static ReturnValue_t release(sem_t* sem);
/* Same API as binary semaphore otherwise. acquire() can be called /* Same API as binary semaphore otherwise. acquire() can be called
* until there are not semaphores left and release() can be called * until there are not semaphores left and release() can be called
* until maxCount is reached. */ * until maxCount is reached. */
uint8_t getMaxCount() const; uint8_t getMaxCount() const;
private: private:
const uint8_t maxCount; const uint8_t maxCount;
uint8_t initCount = 0; uint8_t initCount = 0;
}; };
#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ */ #endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ */

View File

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

View File

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

View File

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

View File

@ -1,33 +1,33 @@
#include "../../tasks/SemaphoreFactory.h" #include "../../tasks/SemaphoreFactory.h"
#include "BinarySemaphore.h" #include "BinarySemaphore.h"
#include "CountingSemaphore.h" #include "CountingSemaphore.h"
#include "../../serviceinterface/ServiceInterfaceStream.h" #include "../../serviceinterface/ServiceInterfaceStream.h"
SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr;
SemaphoreFactory::SemaphoreFactory() { SemaphoreFactory::SemaphoreFactory() {
} }
SemaphoreFactory::~SemaphoreFactory() { SemaphoreFactory::~SemaphoreFactory() {
delete factoryInstance; delete factoryInstance;
} }
SemaphoreFactory* SemaphoreFactory::instance() { SemaphoreFactory* SemaphoreFactory::instance() {
if (factoryInstance == nullptr){ if (factoryInstance == nullptr){
factoryInstance = new SemaphoreFactory(); factoryInstance = new SemaphoreFactory();
} }
return SemaphoreFactory::factoryInstance; return SemaphoreFactory::factoryInstance;
} }
SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t arguments) { SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t arguments) {
return new BinarySemaphore(); return new BinarySemaphore();
} }
SemaphoreIF* SemaphoreFactory::createCountingSemaphore(const uint8_t maxCount, SemaphoreIF* SemaphoreFactory::createCountingSemaphore(const uint8_t maxCount,
uint8_t initCount, uint32_t arguments) { uint8_t initCount, uint32_t arguments) {
return new CountingSemaphore(maxCount, initCount); return new CountingSemaphore(maxCount, initCount);
} }
void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) { void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) {
delete semaphore; delete semaphore;
} }

View File

@ -56,7 +56,6 @@ enum {
DEVICE_COMMUNICATION_IF, //DC DEVICE_COMMUNICATION_IF, //DC
BSP, //BSP BSP, //BSP
TIME_STAMPER_IF, //TSI 53 TIME_STAMPER_IF, //TSI 53
//TODO This will shift all IDs for FLP
SGP4PROPAGATOR_CLASS, //SGP4 54 SGP4PROPAGATOR_CLASS, //SGP4 54
MUTEX_IF, //MUX 55 MUTEX_IF, //MUX 55
MESSAGE_QUEUE_IF,//MQI 56 MESSAGE_QUEUE_IF,//MQI 56

View File

@ -1,129 +1,129 @@
#include "../serialize/SerialBufferAdapter.h" #include "../serialize/SerialBufferAdapter.h"
#include "../serviceinterface/ServiceInterfaceStream.h" #include "../serviceinterface/ServiceInterfaceStream.h"
#include <cstring> #include <cstring>
template<typename count_t> template<typename count_t>
SerialBufferAdapter<count_t>::SerialBufferAdapter(const uint8_t* buffer, SerialBufferAdapter<count_t>::SerialBufferAdapter(const uint8_t* buffer,
count_t bufferLength, bool serializeLength) : count_t bufferLength, bool serializeLength) :
serializeLength(serializeLength), serializeLength(serializeLength),
constBuffer(buffer), buffer(nullptr), constBuffer(buffer), buffer(nullptr),
bufferLength(bufferLength) {} bufferLength(bufferLength) {}
template<typename count_t> template<typename count_t>
SerialBufferAdapter<count_t>::SerialBufferAdapter(uint8_t* buffer, SerialBufferAdapter<count_t>::SerialBufferAdapter(uint8_t* buffer,
count_t bufferLength, bool serializeLength) : count_t bufferLength, bool serializeLength) :
serializeLength(serializeLength), constBuffer(buffer), buffer(buffer), serializeLength(serializeLength), constBuffer(buffer), buffer(buffer),
bufferLength(bufferLength) {} bufferLength(bufferLength) {}
template<typename count_t> template<typename count_t>
SerialBufferAdapter<count_t>::~SerialBufferAdapter() { SerialBufferAdapter<count_t>::~SerialBufferAdapter() {
} }
template<typename count_t> template<typename count_t>
ReturnValue_t SerialBufferAdapter<count_t>::serialize(uint8_t** buffer, ReturnValue_t SerialBufferAdapter<count_t>::serialize(uint8_t** buffer,
size_t* size, size_t maxSize, Endianness streamEndianness) const { size_t* size, size_t maxSize, Endianness streamEndianness) const {
if (serializeLength) { if (serializeLength) {
ReturnValue_t result = SerializeAdapter::serialize(&bufferLength, ReturnValue_t result = SerializeAdapter::serialize(&bufferLength,
buffer, size, maxSize, streamEndianness); buffer, size, maxSize, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
} }
if (*size + bufferLength > maxSize) { if (*size + bufferLength > maxSize) {
return BUFFER_TOO_SHORT; return BUFFER_TOO_SHORT;
} }
if (this->constBuffer != nullptr) { if (this->constBuffer != nullptr) {
std::memcpy(*buffer, this->constBuffer, bufferLength); std::memcpy(*buffer, this->constBuffer, bufferLength);
} }
else if (this->buffer != nullptr) { else if (this->buffer != nullptr) {
// This will propably be never reached, constBuffer should always be // This will propably be never reached, constBuffer should always be
// set if non-const buffer is set. // set if non-const buffer is set.
std::memcpy(*buffer, this->buffer, bufferLength); std::memcpy(*buffer, this->buffer, bufferLength);
} }
else { else {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
*size += bufferLength; *size += bufferLength;
(*buffer) += bufferLength; (*buffer) += bufferLength;
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
template<typename count_t> template<typename count_t>
size_t SerialBufferAdapter<count_t>::getSerializedSize() const { size_t SerialBufferAdapter<count_t>::getSerializedSize() const {
if (serializeLength) { if (serializeLength) {
return bufferLength + SerializeAdapter::getSerializedSize(&bufferLength); return bufferLength + SerializeAdapter::getSerializedSize(&bufferLength);
} else { } else {
return bufferLength; return bufferLength;
} }
} }
template<typename count_t> template<typename count_t>
ReturnValue_t SerialBufferAdapter<count_t>::deSerialize(const uint8_t** buffer, ReturnValue_t SerialBufferAdapter<count_t>::deSerialize(const uint8_t** buffer,
size_t* size, Endianness streamEndianness) { size_t* size, Endianness streamEndianness) {
if (this->buffer == nullptr) { if (this->buffer == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
if(serializeLength){ if(serializeLength){
count_t lengthField = 0; count_t lengthField = 0;
ReturnValue_t result = SerializeAdapter::deSerialize(&lengthField, ReturnValue_t result = SerializeAdapter::deSerialize(&lengthField,
buffer, size, streamEndianness); buffer, size, streamEndianness);
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
if(lengthField > bufferLength) { if(lengthField > bufferLength) {
return TOO_MANY_ELEMENTS; return TOO_MANY_ELEMENTS;
} }
bufferLength = lengthField; bufferLength = lengthField;
} }
if (bufferLength <= *size) { if (bufferLength <= *size) {
*size -= bufferLength; *size -= bufferLength;
std::memcpy(this->buffer, *buffer, bufferLength); std::memcpy(this->buffer, *buffer, bufferLength);
(*buffer) += bufferLength; (*buffer) += bufferLength;
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
else { else {
return STREAM_TOO_SHORT; return STREAM_TOO_SHORT;
} }
} }
template<typename count_t> template<typename count_t>
uint8_t * SerialBufferAdapter<count_t>::getBuffer() { uint8_t * SerialBufferAdapter<count_t>::getBuffer() {
if(buffer == nullptr) { if(buffer == nullptr) {
sif::error << "Wrong access function for stored type !" sif::error << "Wrong access function for stored type !"
" Use getConstBuffer()." << std::endl; " Use getConstBuffer()." << std::endl;
return nullptr; return nullptr;
} }
return buffer; return buffer;
} }
template<typename count_t> template<typename count_t>
const uint8_t * SerialBufferAdapter<count_t>::getConstBuffer() { const uint8_t * SerialBufferAdapter<count_t>::getConstBuffer() {
if(constBuffer == nullptr) { if(constBuffer == nullptr) {
sif::error << "SerialBufferAdapter::getConstBuffer:" sif::error << "SerialBufferAdapter::getConstBuffer:"
" Buffers are unitialized!" << std::endl; " Buffers are unitialized!" << std::endl;
return nullptr; return nullptr;
} }
return constBuffer; return constBuffer;
} }
template<typename count_t> template<typename count_t>
void SerialBufferAdapter<count_t>::setBuffer(uint8_t* buffer, void SerialBufferAdapter<count_t>::setBuffer(uint8_t* buffer,
count_t bufferLength) { count_t bufferLength) {
this->buffer = buffer; this->buffer = buffer;
this->constBuffer = buffer; this->constBuffer = buffer;
this->bufferLength = bufferLength; this->bufferLength = bufferLength;
} }
//forward Template declaration for linker //forward Template declaration for linker
template class SerialBufferAdapter<uint8_t>; template class SerialBufferAdapter<uint8_t>;
template class SerialBufferAdapter<uint16_t>; template class SerialBufferAdapter<uint16_t>;
template class SerialBufferAdapter<uint32_t>; template class SerialBufferAdapter<uint32_t>;
template class SerialBufferAdapter<uint64_t>; template class SerialBufferAdapter<uint64_t>;

View File

@ -1,78 +1,78 @@
#ifndef SERIALBUFFERADAPTER_H_ #ifndef SERIALBUFFERADAPTER_H_
#define SERIALBUFFERADAPTER_H_ #define SERIALBUFFERADAPTER_H_
#include "../serialize/SerializeIF.h" #include "../serialize/SerializeIF.h"
#include "../serialize/SerializeAdapter.h" #include "../serialize/SerializeAdapter.h"
/** /**
* This adapter provides an interface for SerializeIF to serialize or deserialize * This adapter provides an interface for SerializeIF to serialize or deserialize
* buffers with no length header but a known size. * buffers with no length header but a known size.
* *
* Additionally, the buffer length can be serialized too and will be put in * Additionally, the buffer length can be serialized too and will be put in
* front of the serialized buffer. * front of the serialized buffer.
* *
* Can be used with SerialLinkedListAdapter by declaring a SerializeElement with * Can be used with SerialLinkedListAdapter by declaring a SerializeElement with
* SerialElement<SerialBufferAdapter<bufferLengthType(will be uint8_t mostly)>>. * SerialElement<SerialBufferAdapter<bufferLengthType(will be uint8_t mostly)>>.
* Right now, the SerialBufferAdapter must always * Right now, the SerialBufferAdapter must always
* be initialized with the buffer and size ! * be initialized with the buffer and size !
* *
* \ingroup serialize * \ingroup serialize
*/ */
template<typename count_t> template<typename count_t>
class SerialBufferAdapter: public SerializeIF { class SerialBufferAdapter: public SerializeIF {
public: public:
/** /**
* Constructor for constant uint8_t buffer. Length field can be serialized optionally. * Constructor for constant uint8_t buffer. Length field can be serialized optionally.
* Type of length can be supplied as template type. * Type of length can be supplied as template type.
* @param buffer * @param buffer
* @param bufferLength * @param bufferLength
* @param serializeLength * @param serializeLength
*/ */
SerialBufferAdapter(const uint8_t* buffer, count_t bufferLength, SerialBufferAdapter(const uint8_t* buffer, count_t bufferLength,
bool serializeLength = false); bool serializeLength = false);
/** /**
* Constructor for non-constant uint8_t buffer. * Constructor for non-constant uint8_t buffer.
* Length field can be serialized optionally. * Length field can be serialized optionally.
* Type of length can be supplied as template type. * Type of length can be supplied as template type.
* @param buffer * @param buffer
* @param bufferLength * @param bufferLength
* @param serializeLength Length field will be serialized with size count_t * @param serializeLength Length field will be serialized with size count_t
*/ */
SerialBufferAdapter(uint8_t* buffer, count_t bufferLength, SerialBufferAdapter(uint8_t* buffer, count_t bufferLength,
bool serializeLength = false); bool serializeLength = false);
virtual ~SerialBufferAdapter(); virtual ~SerialBufferAdapter();
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
size_t maxSize, Endianness streamEndianness) const override; size_t maxSize, Endianness streamEndianness) const override;
virtual size_t getSerializedSize() const override; virtual size_t getSerializedSize() const override;
/** /**
* @brief This function deserializes a buffer into the member buffer. * @brief This function deserializes a buffer into the member buffer.
* @details * @details
* If a length field is present, it is ignored, as the size should have * If a length field is present, it is ignored, as the size should have
* been set in the constructor. If the size is not known beforehand, * been set in the constructor. If the size is not known beforehand,
* consider using SerialFixedArrayListAdapter instead. * consider using SerialFixedArrayListAdapter instead.
* @param buffer [out] Resulting buffer * @param buffer [out] Resulting buffer
* @param size remaining size to deserialize, should be larger than buffer * @param size remaining size to deserialize, should be larger than buffer
* + size field size * + size field size
* @param bigEndian * @param bigEndian
* @return * @return
*/ */
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override; Endianness streamEndianness) override;
uint8_t * getBuffer(); uint8_t * getBuffer();
const uint8_t * getConstBuffer(); const uint8_t * getConstBuffer();
void setBuffer(uint8_t* buffer, count_t bufferLength); void setBuffer(uint8_t* buffer, count_t bufferLength);
private: private:
bool serializeLength = false; bool serializeLength = false;
const uint8_t *constBuffer = nullptr; const uint8_t *constBuffer = nullptr;
uint8_t *buffer = nullptr; uint8_t *buffer = nullptr;
count_t bufferLength = 0; count_t bufferLength = 0;
}; };
#endif /* SERIALBUFFERADAPTER_H_ */ #endif /* SERIALBUFFERADAPTER_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 @@
/** #ifndef FSFW_STORAGEMANAGER_LOCALPOOL_H_
* @file LocalPool #define FSFW_STORAGEMANAGER_LOCALPOOL_H_
* @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_
#include "../objectmanager/SystemObject.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "StorageManagerIF.h" #include "StorageManagerIF.h"
#include "../objectmanager/SystemObject.h"
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../internalError/InternalErrorReporterIF.h" #include "../internalError/InternalErrorReporterIF.h"
#include <string.h> #include "../storagemanager/StorageAccessor.h"
#include <cstring>
/** /**
* @brief The LocalPool class provides an intermediate data storage with * @brief The LocalPool class provides an intermediate data storage with
@ -27,6 +23,7 @@
* 0xFFFF-1 bytes. * 0xFFFF-1 bytes.
* It is possible to store empty packets in the pool. * It is possible to store empty packets in the pool.
* The local pool is NOT thread-safe. * The local pool is NOT thread-safe.
* @author Bastian Baetz
*/ */
template<uint8_t NUMBER_OF_POOLS = 5> template<uint8_t NUMBER_OF_POOLS = 5>
class LocalPool: public SystemObject, public StorageManagerIF { class LocalPool: public SystemObject, public StorageManagerIF {
@ -39,7 +36,7 @@ public:
/** /**
* @brief This is the default constructor for a pool manager instance. * @brief This is the default constructor for a pool manager instance.
* @details By passing two arrays of size NUMBER_OF_POOLS, the constructor * @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. * regions are all set to zero on start up.
* @param setObjectId The object identifier to be set. This allows for * @param setObjectId The object identifier to be set. This allows for
* multiple instances of LocalPool in the system. * multiple instances of LocalPool in the system.
@ -73,10 +70,17 @@ public:
size_t size, bool ignoreFault = false) override; size_t size, bool ignoreFault = false) override;
ReturnValue_t getFreeElement(store_address_t* storageId,const size_t size, ReturnValue_t getFreeElement(store_address_t* storageId,const size_t size,
uint8_t** p_data, bool ignoreFault = false) override; 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, ReturnValue_t getData(store_address_t packet_id, const uint8_t** packet_ptr,
size_t * size) override; 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, ReturnValue_t modifyData(store_address_t packet_id, uint8_t** packet_ptr,
size_t * size) override; size_t * size) override;
virtual ReturnValue_t deleteData(store_address_t) override; virtual ReturnValue_t deleteData(store_address_t) override;
virtual ReturnValue_t deleteData(uint8_t* ptr, size_t size, virtual ReturnValue_t deleteData(uint8_t* ptr, size_t size,
store_address_t* storeId = NULL) override; store_address_t* storeId = NULL) override;
@ -84,7 +88,7 @@ public:
ReturnValue_t initialize() override; ReturnValue_t initialize() override;
protected: 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 size The minimum packet size that shall be reserved.
* @param[out] address Storage ID of the reserved data. * @param[out] address Storage ID of the reserved data.
* @return - #RETURN_OK on success, * @return - #RETURN_OK on success,
@ -97,7 +101,8 @@ protected:
private: private:
/** /**
* Indicates that this element is free. * 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; static const uint32_t STORAGE_FREE = 0xFFFFFFFF;
/** /**
@ -123,7 +128,9 @@ private:
* is also dynamically allocated there. * is also dynamically allocated there.
*/ */
uint32_t* size_list[NUMBER_OF_POOLS]; 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. * @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 * @details It also sets the size in size_list. The method does not perform
@ -180,4 +187,4 @@ private:
#include "LocalPool.tpp" #include "LocalPool.tpp"
#endif /* FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ */ #endif /* FSFW_STORAGEMANAGER_LOCALPOOL_H_ */

View File

@ -1,5 +1,9 @@
#ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_ #ifndef FSFW_STORAGEMANAGER_LOCALPOOL_TPP_
#define FRAMEWORK_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> template<uint8_t NUMBER_OF_POOLS>
inline LocalPool<NUMBER_OF_POOLS>::LocalPool(object_id_t setObjectId, 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> template<uint8_t NUMBER_OF_POOLS>
inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::addData(store_address_t* storageId, inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::addData(
const uint8_t* data, size_t size, bool ignoreFault) { store_address_t* storageId, const uint8_t* data, size_t size,
bool ignoreFault) {
ReturnValue_t status = reserveSpace(size, storageId, ignoreFault); ReturnValue_t status = reserveSpace(size, storageId, ignoreFault);
if (status == RETURN_OK) { if (status == RETURN_OK) {
write(*storageId, data, size); write(*storageId, data, size);
@ -144,15 +149,55 @@ inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::getFreeElement(
return status; 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> template<uint8_t NUMBER_OF_POOLS>
inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::getData( inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::getData(
store_address_t packet_id, const uint8_t** packet_ptr, size_t* size) { 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); ReturnValue_t status = modifyData(packet_id, &tempData, size);
*packet_ptr = tempData; *packet_ptr = tempData;
return status; 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> template<uint8_t NUMBER_OF_POOLS>
inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::modifyData( inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::modifyData(
store_address_t packet_id, uint8_t** packet_ptr, size_t* size) { 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>( internalErrorReporter = objectManager->get<InternalErrorReporterIF>(
objects::INTERNAL_ERROR_REPORTER); objects::INTERNAL_ERROR_REPORTER);
if (internalErrorReporter == NULL){ if (internalErrorReporter == nullptr){
return RETURN_FAILED; return ObjectManagerIF::INTERNAL_ERR_REPORTER_UNINIT;
} }
//Check if any pool size is large than the maximum allowed. //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) { if (element_sizes[count] >= STORAGE_FREE) {
sif::error << "LocalPool::initialize: Pool is too large! " sif::error << "LocalPool::initialize: Pool is too large! "
"Max. allowed size is: " << (STORAGE_FREE - 1) << std::endl; "Max. allowed size is: " << (STORAGE_FREE - 1) << std::endl;
return RETURN_FAILED; return StorageManagerIF::POOL_TOO_LARGE;
} }
} }
return RETURN_OK; return RETURN_OK;
} }
#endif #endif /* FSFW_STORAGEMANAGER_LOCALPOOL_TPP_ */

View File

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

View File

@ -1,6 +1,10 @@
#ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ #ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_
#define 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> template<uint8_t NUMBER_OF_POOLS>
inline PoolManager<NUMBER_OF_POOLS>::PoolManager(object_id_t setObjectId, inline PoolManager<NUMBER_OF_POOLS>::PoolManager(object_id_t setObjectId,
const uint16_t element_sizes[NUMBER_OF_POOLS], 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> template<uint8_t NUMBER_OF_POOLS>
inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::reserveSpace( inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::reserveSpace(
const uint32_t size, store_address_t* address, bool ignoreFault) { 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, ReturnValue_t status = LocalPool<NUMBER_OF_POOLS>::reserveSpace(size,
address,ignoreFault); address,ignoreFault);
return status; return status;
@ -29,7 +33,7 @@ inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::deleteData(
// debug << "PoolManager( " << translateObject(getObjectId()) << // debug << "PoolManager( " << translateObject(getObjectId()) <<
// " )::deleteData from store " << packet_id.pool_index << // " )::deleteData from store " << packet_id.pool_index <<
// ". id is "<< packet_id.packet_index << std::endl; // ". 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); ReturnValue_t status = LocalPool<NUMBER_OF_POOLS>::deleteData(packet_id);
return status; return status;
} }
@ -37,19 +41,16 @@ inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::deleteData(
template<uint8_t NUMBER_OF_POOLS> template<uint8_t NUMBER_OF_POOLS>
inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::deleteData(uint8_t* buffer, inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::deleteData(uint8_t* buffer,
size_t size, store_address_t* storeId) { 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, ReturnValue_t status = LocalPool<NUMBER_OF_POOLS>::deleteData(buffer,
size, storeId); size, storeId);
return status; return status;
} }
template<uint8_t NUMBER_OF_POOLS> template<uint8_t NUMBER_OF_POOLS>
inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::modifyData( inline void PoolManager<NUMBER_OF_POOLS>::setMutexTimeout(
store_address_t packet_id, uint8_t** packet_ptr, size_t* size) { uint32_t mutexTimeoutMs) {
MutexHelper mutexHelper(mutex,MutexIF::BLOCKING); this->mutexTimeout = mutexTimeoutMs;
ReturnValue_t status = LocalPool<NUMBER_OF_POOLS>::modifyData(packet_id,
packet_ptr, size);
return status;
} }
#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 #ifndef FSFW_STORAGEMANAGER_STORAGEMANAGERIF_H_
#define STORAGEMANAGERIF_H_H #define FSFW_STORAGEMANAGER_STORAGEMANAGERIF_H_
#include "StorageAccessor.h"
#include "storeAddress.h"
#include "../events/Event.h" #include "../events/Event.h"
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
#include <stddef.h>
/** #include <utility>
* @brief This union defines the type that identifies where a data packet is #include <cstddef>
* 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){}
/** using AccessorPair = std::pair<ReturnValue_t, StorageAccessor>;
* Constructor to create an address object using the raw address using ConstAccessorPair = std::pair<ReturnValue_t, ConstStorageAccessor>;
* @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;
}
};
/** /**
* @brief This class provides an interface for intermediate data storage. * @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 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 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 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 uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::OBSW;
static const Event GET_DATA_FAILED = MAKE_EVENT(0, SEVERITY::LOW); 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, virtual ReturnValue_t deleteData(uint8_t* buffer, size_t size,
store_address_t* storeId = nullptr) = 0; 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 * @brief getData returns an address to data and the size of the data
* for a given packet_id. * for a given packet_id.
@ -135,8 +116,30 @@ public:
*/ */
virtual ReturnValue_t getData(store_address_t packet_id, virtual ReturnValue_t getData(store_address_t packet_id,
const uint8_t** packet_ptr, size_t* size) = 0; 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, virtual ReturnValue_t modifyData(store_address_t packet_id,
uint8_t** packet_ptr, size_t* size) = 0; uint8_t** packet_ptr, size_t* size) = 0;
@ -155,6 +158,7 @@ public:
*/ */
virtual ReturnValue_t getFreeElement(store_address_t* storageId, virtual ReturnValue_t getFreeElement(store_address_t* storageId,
const size_t size, uint8_t** p_data, bool ignoreFault = false ) = 0; const size_t size, uint8_t** p_data, bool ignoreFault = false ) = 0;
/** /**
* Clears the whole store. * Clears the whole store.
* Use with care! * Use with care!
@ -162,4 +166,4 @@ public:
virtual void clearStore() = 0; 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,41 +1,41 @@
/** #ifndef FSFW_TASKS_FIXEDSEQUENCESLOT_H_
* @file FixedSequenceSlot.h #define FSFW_TASKS_FIXEDSEQUENCESLOT_H_
* @brief This file defines the PollingSlot class.
* @date 19.12.2012
* @author baetz
*/
#ifndef FIXEDSEQUENCESLOT_H_
#define FIXEDSEQUENCESLOT_H_
#include "ExecutableObjectIF.h"
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
#include "../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:
FixedSequenceSlot( object_id_t handlerId, uint32_t setTimeMs, FixedSequenceSlot( object_id_t handlerId, uint32_t setTimeMs,
int8_t setSequenceId, PeriodicTaskIF* executingTask ); int8_t setSequenceId, ExecutableObjectIF* executableObject,
PeriodicTaskIF* executingTask);
virtual ~FixedSequenceSlot(); 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. * @brief This attribute defines when a device handler object is executed.
* * @details
* @details The pollingTime attribute identifies the time the handler is executed in ms. * The pollingTime attribute identifies the time the handler is
* It must be smaller than the period length of the polling sequence. * executed in ms. It must be smaller than the period length of the
* polling sequence.
*/ */
uint32_t pollingTimeMs; uint32_t pollingTimeMs;
/** /**
* @brief This value defines the type of device communication. * @brief This value defines the type of device communication.
@ -43,7 +43,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
@ -57,4 +57,4 @@ public:
}; };
#endif /* FIXEDSEQUENCESLOT_H_ */ #endif /* FSFW_TASKS_FIXEDSEQUENCESLOT_H_ */

View File

@ -1,5 +1,6 @@
#include "FixedSlotSequence.h" #include "FixedSlotSequence.h"
#include "../serviceinterface/ServiceInterfaceStream.h" #include "../serviceinterface/ServiceInterfaceStream.h"
#include <cstdlib>
FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) : FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) :
lengthMs(setLengthMs) { lengthMs(setLengthMs) {
@ -12,7 +13,7 @@ FixedSlotSequence::~FixedSlotSequence() {
} }
void FixedSlotSequence::executeAndAdvance() { void FixedSlotSequence::executeAndAdvance() {
current->handler->performOperation(current->opcode); current->executableObject->performOperation(current->opcode);
// if (returnValue != RETURN_OK) { // if (returnValue != RETURN_OK) {
// this->sendErrorMessage( returnValue ); // this->sendErrorMessage( returnValue );
// } // }
@ -80,44 +81,82 @@ uint32_t FixedSlotSequence::getLengthMs() const {
return this->lengthMs; 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 { ReturnValue_t FixedSlotSequence::checkSequence() const {
if(slotList.empty()) { 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; return HasReturnvaluesIF::RETURN_FAILED;
} }
auto slotIt = slotList.begin(); if(customCheckFunction != nullptr) {
uint32_t count = 0; ReturnValue_t result = customCheckFunction(slotList);
uint32_t time = 0; if(result != HasReturnvaluesIF::RETURN_OK) {
while (slotIt != slotList.end()) { // Continue for now but print error output.
if (slotIt->handler == nullptr) { sif::error << "FixedSlotSequence::checkSequence:"
sif::error << "FixedSlotSequene::initialize: ObjectId does not exist!" << " Custom check failed!" << std::endl;
<< 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 {
// All ok, print slot.
//info << "Current slot polling time: " << std::endl;
//info << std::dec << slotIt->pollingTimeMs << std::endl;
} }
time = slotIt->pollingTimeMs;
slotIt++;
} }
//info << "Number of elements in slot list: "
uint32_t errorCount = 0;
uint32_t time = 0;
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.
//sif::info << "Current slot polling time: " << std::endl;
//sif::info << std::dec << slotIt->pollingTimeMs << std::endl;
}
time = slot.pollingTimeMs;
}
//sif::info << "Number of elements in slot list: "
// << slotList.size() << std::endl; // << slotList.size() << std::endl;
if (count > 0) { if (errorCount > 0) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
void FixedSlotSequence::addSlot(object_id_t componentId, uint32_t slotTimeMs,
int8_t executionStep, PeriodicTaskIF* executingTask) { ReturnValue_t FixedSlotSequence::intializeSequenceAfterTaskCreation() const {
this->slotList.insert(FixedSequenceSlot(componentId, slotTimeMs, executionStep, std::set<ExecutableObjectIF*> uniqueObjects;
executingTask)); uint32_t count = 0;
this->current = slotList.begin(); 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_ #ifndef FSFW_TASKS_FIXEDSLOTSEQUENCE_H_
#define FRAMEWORK_DEVICEHANDLERS_FIXEDSLOTSEQUENCE_H_ #define FSFW_TASKS_FIXEDSLOTSEQUENCE_H_
#include "FixedSequenceSlot.h" #include "FixedSequenceSlot.h"
#include "../objectmanager/SystemObject.h" #include "../objectmanager/SystemObject.h"
#include <set> #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 * @details
* The FixedSlotSequence object maintains the dynamic execution of * 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 * The main idea is to create a list of executable objects (for example
* handlers to thepolling sequence and to maintain a list of * device handlers), to announce all handlers to the polling sequence and to
* polling slot objects. This slot list represents the Polling Sequence Table * maintain a list of polling slot objects.
* in software. * This slot list represents the Polling Sequence Table in software.
* *
* Each polling slot contains information to indicate when and * Each polling slot contains information to indicate when and
* which device handler shall be executed within a given polling period. * which executable object shall be executed within a given polling period.
* The sequence is then executed by iterating through this slot list. * When adding a slot, a pointer to the executing task, a pointer to the
* Handlers are invoking by calling a certain function stored in the handler list. * 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 { class FixedSlotSequence {
public: public:
@ -29,41 +33,44 @@ public:
/** /**
* @brief The constructor of the FixedSlotSequence object. * @brief The constructor of the FixedSlotSequence object.
*
* @details The constructor takes two arguments, the period length and the init function.
*
* @param setLength The period length, expressed in ms. * @param setLength The period length, expressed in ms.
*/ */
FixedSlotSequence(uint32_t setLengthMs); FixedSlotSequence(uint32_t setLengthMs);
/** /**
* @brief The destructor of the FixedSlotSequence object. * @brief The destructor of the FixedSlotSequence object.
* * @details
* @details The destructor frees all allocated memory by iterating through the slotList * The destructor frees all allocated memory by iterating through the
* and deleting all allocated resources. * slotList and deleting all allocated resources.
*/ */
virtual ~FixedSlotSequence(); virtual ~FixedSlotSequence();
/** /**
* @brief This is a method to add an PollingSlot object to slotList. * @brief This is a method to add an PollingSlot object to slotList.
* *
* @details Here, a polling slot object is added to the slot list. It is appended * @details
* to the end of the list. The list is currently NOT reordered. * Here, a polling slot object is added to the slot list. It is appended
* Afterwards, the iterator current is set to the beginning of the list. * to the end of the list. The list is currently NOT reordered.
* @param Object ID of the object to add * Afterwards, the iterator current is set to the beginning of the list.
* @param setTime Value between (0 to 1) * slotLengthMs, when a FixedTimeslotTask * @param handlerId ID of the object to add
* will be called inside the slot period. * @param setTime
* @param setSequenceId ID which can be used to distinguish * Value between (0 to 1) * slotLengthMs, when a FixedTimeslotTask
* different task operations * will be called inside the slot period.
* @param setSequenceId
* ID which can be used to distinguish different task operations. This
* value will be passed to the executable function.
* @param * @param
* @param * @param
*/ */
void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId, void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId,
ExecutableObjectIF* executableObject,
PeriodicTaskIF* executingTask); PeriodicTaskIF* executingTask);
/** /**
* Checks if the current slot shall be executed immediately after the one before. * @brief Checks if the current slot shall be executed immediately
* This allows to distinguish between grouped and not grouped handlers. * 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 * @return - @c true if the slot has the same polling time as the previous
* - @c false else * - @c false else
*/ */
@ -125,12 +132,32 @@ public:
SlotListIter current; 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. * Checks if timing is ok (must be ascending) and if all handlers were found.
* @return * @return
*/ */
ReturnValue_t checkSequence() const; 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: protected:
/** /**
@ -146,7 +173,9 @@ protected:
*/ */
SlotList slotList; SlotList slotList;
ReturnValue_t (*customCheckFunction)(const SlotList&) = nullptr;
uint32_t lengthMs; uint32_t lengthMs;
}; };
#endif /* FIXEDSLOTSEQUENCE_H_ */ #endif /* FSFW_TASKS_FIXEDSLOTSEQUENCE_H_ */

View File

@ -1,50 +1,50 @@
#ifndef FSFW_TASKS_SEMAPHOREFACTORY_H_ #ifndef FSFW_TASKS_SEMAPHOREFACTORY_H_
#define FSFW_TASKS_SEMAPHOREFACTORY_H_ #define FSFW_TASKS_SEMAPHOREFACTORY_H_
#include "../tasks/SemaphoreIF.h" #include "../tasks/SemaphoreIF.h"
/** /**
* Creates Semaphore. * Creates Semaphore.
* This class is a "singleton" interface, i.e. it provides an * This class is a "singleton" interface, i.e. it provides an
* interface, but also is the base class for a singleton. * interface, but also is the base class for a singleton.
*/ */
class SemaphoreFactory { class SemaphoreFactory {
public: public:
virtual ~SemaphoreFactory(); virtual ~SemaphoreFactory();
/** /**
* Returns the single instance of SemaphoreFactory. * Returns the single instance of SemaphoreFactory.
* The implementation of #instance is found in its subclasses. * The implementation of #instance is found in its subclasses.
* Thus, we choose link-time variability of the instance. * Thus, we choose link-time variability of the instance.
*/ */
static SemaphoreFactory* instance(); static SemaphoreFactory* instance();
/** /**
* Create a binary semaphore. * Create a binary semaphore.
* Creator function for a binary semaphore which may only be acquired once * Creator function for a binary semaphore which may only be acquired once
* @param argument Can be used to pass implementation specific information. * @param argument Can be used to pass implementation specific information.
* @return Pointer to newly created semaphore class instance. * @return Pointer to newly created semaphore class instance.
*/ */
SemaphoreIF* createBinarySemaphore(uint32_t arguments = 0); SemaphoreIF* createBinarySemaphore(uint32_t arguments = 0);
/** /**
* Create a counting semaphore. * Create a counting semaphore.
* Creator functons for a counting semaphore which may be acquired multiple * Creator functons for a counting semaphore which may be acquired multiple
* times. * times.
* @param count Semaphore can be taken count times. * @param count Semaphore can be taken count times.
* @param initCount Initial count value. * @param initCount Initial count value.
* @param argument Can be used to pass implementation specific information. * @param argument Can be used to pass implementation specific information.
* @return * @return
*/ */
SemaphoreIF* createCountingSemaphore(const uint8_t maxCount, SemaphoreIF* createCountingSemaphore(const uint8_t maxCount,
uint8_t initCount, uint32_t arguments = 0); uint8_t initCount, uint32_t arguments = 0);
void deleteSemaphore(SemaphoreIF* semaphore); void deleteSemaphore(SemaphoreIF* semaphore);
private: private:
/** /**
* External instantiation is not allowed. * External instantiation is not allowed.
*/ */
SemaphoreFactory(); SemaphoreFactory();
static SemaphoreFactory* factoryInstance; static SemaphoreFactory* factoryInstance;
}; };
#endif /* FSFW_TASKS_SEMAPHOREFACTORY_H_ */ #endif /* FSFW_TASKS_SEMAPHOREFACTORY_H_ */

View File

@ -1,68 +1,68 @@
#ifndef FRAMEWORK_TASKS_SEMAPHOREIF_H_ #ifndef FRAMEWORK_TASKS_SEMAPHOREIF_H_
#define FRAMEWORK_TASKS_SEMAPHOREIF_H_ #define FRAMEWORK_TASKS_SEMAPHOREIF_H_
#include "../returnvalues/FwClassIds.h" #include "../returnvalues/FwClassIds.h"
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
#include <cstdint> #include <cstdint>
/** /**
* @brief Generic interface for semaphores, which can be used to achieve * @brief Generic interface for semaphores, which can be used to achieve
* task synchronization. This is a generic interface which can be * task synchronization. This is a generic interface which can be
* used for both binary semaphores and counting semaphores. * used for both binary semaphores and counting semaphores.
* @details * @details
* A semaphore is a synchronization primitive. * A semaphore is a synchronization primitive.
* See: https://en.wikipedia.org/wiki/Semaphore_(programming) * See: https://en.wikipedia.org/wiki/Semaphore_(programming)
* A semaphore can be used to achieve task synchonization and track the * A semaphore can be used to achieve task synchonization and track the
* availability of resources by using either the binary or the counting * availability of resources by using either the binary or the counting
* semaphore types. * semaphore types.
* *
* If mutual exlcusion of a resource is desired, a mutex should be used, * If mutual exlcusion of a resource is desired, a mutex should be used,
* which is a special form of a semaphore and has an own interface. * which is a special form of a semaphore and has an own interface.
*/ */
class SemaphoreIF { class SemaphoreIF {
public: public:
/** /**
* Different types of timeout for the mutex lock. * Different types of timeout for the mutex lock.
*/ */
enum TimeoutType { enum TimeoutType {
POLLING, //!< If mutex is not available, return immediately POLLING, //!< If mutex is not available, return immediately
WAITING, //!< Wait a specified time for the mutex to become available WAITING, //!< Wait a specified time for the mutex to become available
BLOCKING //!< Block indefinitely until the mutex becomes available. BLOCKING //!< Block indefinitely until the mutex becomes available.
}; };
virtual~ SemaphoreIF() {}; virtual~ SemaphoreIF() {};
static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF;
//! Semaphore timeout //! Semaphore timeout
static constexpr ReturnValue_t SEMAPHORE_TIMEOUT = MAKE_RETURN_CODE(1); static constexpr ReturnValue_t SEMAPHORE_TIMEOUT = MAKE_RETURN_CODE(1);
//! The current semaphore can not be given, because it is not owned //! The current semaphore can not be given, because it is not owned
static constexpr ReturnValue_t SEMAPHORE_NOT_OWNED = MAKE_RETURN_CODE(2); static constexpr ReturnValue_t SEMAPHORE_NOT_OWNED = MAKE_RETURN_CODE(2);
static constexpr ReturnValue_t SEMAPHORE_INVALID = MAKE_RETURN_CODE(3); static constexpr ReturnValue_t SEMAPHORE_INVALID = MAKE_RETURN_CODE(3);
/** /**
* Generic call to acquire a semaphore. * Generic call to acquire a semaphore.
* If there are no more semaphores to be taken (for a counting semaphore, * If there are no more semaphores to be taken (for a counting semaphore,
* a semaphore may be taken more than once), the taks will block * a semaphore may be taken more than once), the taks will block
* for a maximum of timeoutMs while trying to acquire the semaphore. * for a maximum of timeoutMs while trying to acquire the semaphore.
* This can be used to achieve task synchrnization. * This can be used to achieve task synchrnization.
* @param timeoutMs * @param timeoutMs
* @return - c RETURN_OK for successfull acquisition * @return - c RETURN_OK for successfull acquisition
*/ */
virtual ReturnValue_t acquire(TimeoutType timeoutType = virtual ReturnValue_t acquire(TimeoutType timeoutType =
TimeoutType::BLOCKING, uint32_t timeoutMs = 0) = 0; TimeoutType::BLOCKING, uint32_t timeoutMs = 0) = 0;
/** /**
* Corrensponding call to release a semaphore. * Corrensponding call to release a semaphore.
* @return -@c RETURN_OK for successfull release * @return -@c RETURN_OK for successfull release
*/ */
virtual ReturnValue_t release() = 0; virtual ReturnValue_t release() = 0;
/** /**
* If the semaphore is a counting semaphore then the semaphores current * If the semaphore is a counting semaphore then the semaphores current
* count value is returned. If the semaphore is a binary semaphore then 1 * count value is returned. If the semaphore is a binary semaphore then 1
* is returned if the semaphore is available, and 0 is returned if the * is returned if the semaphore is available, and 0 is returned if the
* semaphore is not available. * semaphore is not available.
*/ */
virtual uint8_t getSemaphoreCounter() const = 0; virtual uint8_t getSemaphoreCounter() const = 0;
}; };
#endif /* FRAMEWORK_TASKS_SEMAPHOREIF_H_ */ #endif /* FRAMEWORK_TASKS_SEMAPHOREIF_H_ */

View File

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

View File

@ -1,31 +1,50 @@
#ifndef VERIFICATIONREPORTER_H_ #ifndef FSFW_TMTCSERVICES_VERIFICATIONREPORTER_H_
#define VERIFICATIONREPORTER_H_ #define FSFW_TMTCSERVICES_VERIFICATIONREPORTER_H_
#include "../objectmanager/ObjectManagerIF.h"
#include "PusVerificationReport.h" #include "PusVerificationReport.h"
#include "../objectmanager/ObjectManagerIF.h"
namespace Factory{ namespace Factory{
void setStaticFrameworkObjectIds(); 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 { class VerificationReporter {
friend void (Factory::setStaticFrameworkObjectIds)(); friend void (Factory::setStaticFrameworkObjectIds)();
public: public:
VerificationReporter(); VerificationReporter();
virtual ~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 sendSuccessReport( uint8_t set_report_id, TcPacketBase* current_packet,
void sendFailureReport( uint8_t report_id, TcPacketBase* current_packet, ReturnValue_t error_code = 0, uint8_t set_step = 0 );
uint8_t step = 0, uint32_t parameter1 = 0, uint32_t parameter2 = 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, 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); uint32_t parameter1 = 0, uint32_t parameter2 = 0);
void initialize(); void initialize();
private: private:
static object_id_t messageReceiver; static object_id_t messageReceiver;
MessageQueueId_t acknowledgeQueue; MessageQueueId_t acknowledgeQueue;
}; };
#endif /* VERIFICATIONREPORTER_H_ */ #endif /* FSFW_TMTCSERVICES_VERIFICATIONREPORTER_H_ */