all fixed slot sequence improvenements #24

Merged
gaisser merged 13 commits from KSat/fsfw:mueller_FixedSequenceImprovements into master 2020-07-02 14:28:54 +02:00
5 changed files with 121 additions and 92 deletions

View File

@ -16,6 +16,5 @@ FixedSequenceSlot::FixedSequenceSlot(object_id_t handlerId, uint32_t setTime,
handler->setTaskIF(executingTask); handler->setTaskIF(executingTask);
} }
FixedSequenceSlot::~FixedSequenceSlot() { FixedSequenceSlot::~FixedSequenceSlot() {}
}

View File

@ -13,35 +13,47 @@
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 sequence table entry. * @details The PollingSlot class is the representation of a single polling
* sequence table entry.
*/ */
class FixedSequenceSlot { class FixedSequenceSlot {
public: public:
FixedSequenceSlot( object_id_t handlerId, uint32_t setTimeMs, int8_t setSequenceId, PeriodicTaskIF* executingTask ); FixedSequenceSlot( object_id_t handlerId, uint32_t setTimeMs,
int8_t setSequenceId, PeriodicTaskIF* executingTask );
virtual ~FixedSequenceSlot(); virtual ~FixedSequenceSlot();
/** /**
* \brief \c handler identifies which device handler object is executed in this slot. * @brief Handler identifies which device handler object is executed in this slot.
*/ */
ExecutableObjectIF* handler; ExecutableObjectIF* handler;
/** /**
* \brief This attribute defines when a device handler object is executed. * @brief This attribute defines when a device handler object is executed.
* *
* \details The pollingTime attribute identifies the time the handler is executed in ms. It must be * @details The pollingTime attribute identifies the time the handler is executed in ms.
* smaller than the period length of the polling sequence, what is ensured by automated calculation * It must be smaller than the period length of the polling sequence.
* from a database.
*/ */
uint32_t pollingTimeMs; uint32_t pollingTimeMs;
/** /**
* \brief This value defines the type of device communication. * @brief This value defines the type of device communication.
* *
* \details The state of this value decides what communication routine is called in the PST executable or the device handler object. * @details The state of this value decides what communication routine is
* called in the PST executable or the device handler object.
*/ */
uint8_t opcode; uint8_t opcode;
/**
* @brief Operator overload for the comparison operator to
* allow sorting by polling time.
* @param fixedSequenceSlot
* @return
*/
bool operator <(const FixedSequenceSlot & fixedSequenceSlot) const {
return pollingTimeMs < fixedSequenceSlot.pollingTimeMs;
}
}; };

View File

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

View File

@ -1,9 +1,9 @@
#ifndef FIXEDSLOTSEQUENCE_H_ #ifndef FRAMEWORK_DEVICEHANDLERS_FIXEDSLOTSEQUENCE_H_
#define FIXEDSLOTSEQUENCE_H_ #define FRAMEWORK_DEVICEHANDLERS_FIXEDSLOTSEQUENCE_H_
#include <framework/devicehandlers/FixedSequenceSlot.h> #include <framework/devicehandlers/FixedSequenceSlot.h>
#include <framework/objectmanager/SystemObject.h> #include <framework/objectmanager/SystemObject.h>
#include <list> #include <set>
/** /**

This is in global namespace or?

This is in global namespace or?

Yes, maybe it woould be better to put it in the class..

Yes, maybe it woould be better to put it in the class..
* @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.
@ -24,30 +24,39 @@
*/ */
class FixedSlotSequence { class FixedSlotSequence {
public: public:
using SlotList = std::multiset<FixedSequenceSlot>;
using SlotListIter = std::multiset<FixedSequenceSlot>::iterator;
/** /**
* \brief The constructor of the FixedSlotSequence object. * @brief The constructor of the FixedSlotSequence object.
* *
* \details The constructor takes two arguments, the period length and the init function. * @details The constructor takes two arguments, the period length and the init function.
* *
* \param setLength The period length, expressed in ms. * @param setLength The period length, expressed in ms.
*/ */
FixedSlotSequence(uint32_t setLengthMs); FixedSlotSequence(uint32_t setLengthMs);
/** /**
* \brief The destructor of the FixedSlotSequence object. * @brief The destructor of the FixedSlotSequence object.
* *
* \details The destructor frees all allocated memory by iterating through the slotList * @details The destructor frees all allocated memory by iterating through the slotList
* and deleting all allocated resources. * and deleting all allocated resources.
*/ */
virtual ~FixedSlotSequence(); virtual ~FixedSlotSequence();
/** /**
* \brief This is a method to add an PollingSlot object to slotList. * @brief This is a method to add an PollingSlot object to slotList.
* *
* \details Here, a polling slot object is added to the slot list. It is appended * @details Here, a polling slot object is added to the slot list. It is appended
* to the end of the list. The list is currently NOT reordered. * to the end of the list. The list is currently NOT reordered.
* Afterwards, the iterator current is set to the beginning of the list. * Afterwards, the iterator current is set to the beginning of the list.
* @param Object ID of the object to add
* @param setTime Value between (0 to 1) * slotLengthMs, when a FixedTimeslotTask
* will be called inside the slot period.
* @param setSequenceId ID which can be used to distinguish
* different task operations
* @param
* @param
*/ */
void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId, void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId,
PeriodicTaskIF* executingTask); PeriodicTaskIF* executingTask);
@ -61,47 +70,59 @@ public:
bool slotFollowsImmediately(); bool slotFollowsImmediately();
/** /**
* \brief This method returns the time until the next software component is invoked. * @brief This method returns the time until the next software
* component is invoked.
* *
* \details This method is vitally important for the operation of the PST. By fetching the polling time * @details
* of the current slot and that of the next one (or the first one, if the list end is reached) * This method is vitally important for the operation of the PST.
* it calculates and returns the interval in milliseconds within which the handler execution * By fetching the polling time of the current slot and that of the
* shall take place. If the next slot has the same time as the current one, it is ignored until * next one (or the first one, if the list end is reached)
* a slot with different time or the end of the PST is found. * it calculates and returns the interval in milliseconds within
* which the handler execution shall take place.
* If the next slot has the same time as the current one, it is ignored
* until a slot with different time or the end of the PST is found.
*/ */
uint32_t getIntervalToNextSlotMs(); uint32_t getIntervalToNextSlotMs();
/** /**
* \brief This method returns the time difference between the current slot and the previous slot * @brief This method returns the time difference between the current
* slot and the previous slot
* *
* \details This method is vitally important for the operation of the PST. By fetching the polling time * @details
* of the current slot and that of the prevous one (or the last one, if the slot is the first one) * This method is vitally important for the operation of the PST.
* it calculates and returns the interval in milliseconds that the handler execution shall be delayed. * By fetching the polling time of the current slot and that of the previous
* one (or the last one, if the slot is the first one) it calculates and
* returns the interval in milliseconds that the handler execution shall
* be delayed.
*/ */
uint32_t getIntervalToPreviousSlotMs(); uint32_t getIntervalToPreviousSlotMs();
/** /**
* \brief This method returns the length of this FixedSlotSequence instance. * @brief This method returns the length of this FixedSlotSequence instance.
*/ */
uint32_t getLengthMs() const; uint32_t getLengthMs() const;
/** /**
* \brief The method to execute the device handler entered in the current OPUSPollingSlot object. * @brief The method to execute the device handler entered in the current
* PollingSlot object.
* *
* \details Within this method the device handler object to be executed is chosen by looking up the * @details
* handler address of the current slot in the handlerMap. Either the device handler's * Within this method the device handler object to be executed is chosen by
* talkToInterface or its listenToInterface method is invoked, depending on the isTalking flag * looking up the handler address of the current slot in the handlerMap.
* of the polling slot. After execution the iterator current is increased or, by reaching the * Either the device handler's talkToInterface or its listenToInterface
* end of slotList, reset to the beginning. * method is invoked, depending on the isTalking flag of the polling slot.
* After execution the iterator current is increased or, by reaching the
* end of slotList, reset to the beginning.
*/ */
void executeAndAdvance(); void executeAndAdvance();
/** /**
* \brief An iterator that indicates the current polling slot to execute. * @brief An iterator that indicates the current polling slot to execute.
* *
* \details This is an iterator for slotList and always points to the polling slot which is executed next. * @details This is an iterator for slotList and always points to the
* polling slot which is executed next.
*/ */
std::list<FixedSequenceSlot*>::iterator current; SlotListIter current;
/** /**
* Iterate through slotList and check successful creation. * Iterate through slotList and check successful creation.
@ -109,18 +130,21 @@ public:
* @return * @return
*/ */
ReturnValue_t checkSequence() const; ReturnValue_t checkSequence() const;
protected: protected:
/** /**
* \brief This list contains all OPUSPollingSlot objects, defining order and execution time of the * @brief This list contains all PollingSlot objects, defining order and
* device handler objects. * execution time of the device handler objects.
* *
* \details The slot list is a std:list object that contains all created OPUSPollingSlot instances. * @details
* They are NOT ordered automatically, so by adding entries, the correct order needs to be ensured. * The slot list is a std:list object that contains all created
* By iterating through this list the polling sequence is executed. Two entries with identical * PollingSlot instances. They are NOT ordered automatically, so by
* polling times are executed immediately one after another. * adding entries, the correct order needs to be ensured. By iterating
* through this list the polling sequence is executed. Two entries with
* identical polling times are executed immediately one after another.
*/ */
std::list<FixedSequenceSlot*> slotList; SlotList slotList;
uint32_t lengthMs; uint32_t lengthMs;
}; };

View File

@ -82,10 +82,10 @@ ReturnValue_t FixedTimeslotTask::checkSequence() const {
void FixedTimeslotTask::taskFunctionality() { void FixedTimeslotTask::taskFunctionality() {
// A local iterator for the Polling Sequence Table is created to find the start time for the first entry. // A local iterator for the Polling Sequence Table is created to find the start time for the first entry.
std::list<FixedSequenceSlot*>::iterator it = pst.current; auto slotListIter = pst.current;
//The start time for the first entry is read. //The start time for the first entry is read.
uint32_t intervalMs = (*it)->pollingTimeMs; uint32_t intervalMs = slotListIter->pollingTimeMs;
TickType_t interval = pdMS_TO_TICKS(intervalMs); TickType_t interval = pdMS_TO_TICKS(intervalMs);
TickType_t xLastWakeTime; TickType_t xLastWakeTime;
@ -120,4 +120,3 @@ ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) {
vTaskDelay(pdMS_TO_TICKS(ms)); vTaskDelay(pdMS_TO_TICKS(ms));
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }