Merge remote-tracking branch 'upstream/mueller/master' into mueller/master
This commit is contained in:
commit
8c5e261a0d
@ -6,120 +6,120 @@
|
|||||||
|
|
||||||
ActionHelper::ActionHelper(HasActionsIF* setOwner,
|
ActionHelper::ActionHelper(HasActionsIF* setOwner,
|
||||||
MessageQueueIF* useThisQueue) :
|
MessageQueueIF* useThisQueue) :
|
||||||
owner(setOwner), queueToUse(useThisQueue) {
|
owner(setOwner), queueToUse(useThisQueue) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ActionHelper::~ActionHelper() {
|
ActionHelper::~ActionHelper() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t ActionHelper::handleActionMessage(CommandMessage* command) {
|
ReturnValue_t ActionHelper::handleActionMessage(CommandMessage* command) {
|
||||||
if (command->getCommand() == ActionMessage::EXECUTE_ACTION) {
|
if (command->getCommand() == ActionMessage::EXECUTE_ACTION) {
|
||||||
ActionId_t currentAction = ActionMessage::getActionId(command);
|
ActionId_t currentAction = ActionMessage::getActionId(command);
|
||||||
prepareExecution(command->getSender(), currentAction,
|
prepareExecution(command->getSender(), currentAction,
|
||||||
ActionMessage::getStoreId(command));
|
ActionMessage::getStoreId(command));
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
} else {
|
} else {
|
||||||
return CommandMessage::UNKNOWN_COMMAND;
|
return CommandMessage::UNKNOWN_COMMAND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t ActionHelper::initialize(MessageQueueIF* queueToUse_) {
|
ReturnValue_t ActionHelper::initialize(MessageQueueIF* queueToUse_) {
|
||||||
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
||||||
if (ipcStore == nullptr) {
|
if (ipcStore == nullptr) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
if(queueToUse_ != nullptr) {
|
if(queueToUse_ != nullptr) {
|
||||||
setQueueToUse(queueToUse_);
|
setQueueToUse(queueToUse_);
|
||||||
}
|
}
|
||||||
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionHelper::step(uint8_t step, MessageQueueId_t reportTo,
|
void ActionHelper::step(uint8_t step, MessageQueueId_t reportTo,
|
||||||
ActionId_t commandId, ReturnValue_t result) {
|
ActionId_t commandId, ReturnValue_t result) {
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
ActionMessage::setStepReply(&reply, commandId, step + STEP_OFFSET, result);
|
ActionMessage::setStepReply(&reply, commandId, step + STEP_OFFSET, result);
|
||||||
queueToUse->sendMessage(reportTo, &reply);
|
queueToUse->sendMessage(reportTo, &reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionHelper::finish(MessageQueueId_t reportTo, ActionId_t commandId,
|
void ActionHelper::finish(MessageQueueId_t reportTo, ActionId_t commandId,
|
||||||
ReturnValue_t result) {
|
ReturnValue_t result) {
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
ActionMessage::setCompletionReply(&reply, commandId, result);
|
ActionMessage::setCompletionReply(&reply, commandId, result);
|
||||||
queueToUse->sendMessage(reportTo, &reply);
|
queueToUse->sendMessage(reportTo, &reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionHelper::setQueueToUse(MessageQueueIF* queue) {
|
void ActionHelper::setQueueToUse(MessageQueueIF* queue) {
|
||||||
queueToUse = queue;
|
queueToUse = queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy,
|
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy,
|
||||||
ActionId_t actionId, store_address_t dataAddress) {
|
ActionId_t actionId, store_address_t dataAddress) {
|
||||||
const uint8_t* dataPtr = NULL;
|
const uint8_t* dataPtr = NULL;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||||
queueToUse->sendMessage(commandedBy, &reply);
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
||||||
ipcStore->deleteData(dataAddress);
|
ipcStore->deleteData(dataAddress);
|
||||||
if(result == HasActionsIF::EXECUTION_FINISHED) {
|
if(result == HasActionsIF::EXECUTION_FINISHED) {
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
ActionMessage::setCompletionReply(&reply, actionId, result);
|
ActionMessage::setCompletionReply(&reply, actionId, result);
|
||||||
queueToUse->sendMessage(commandedBy, &reply);
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
}
|
}
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||||
queueToUse->sendMessage(commandedBy, &reply);
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
|
ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
|
||||||
ActionId_t replyId, SerializeIF* data, bool hideSender) {
|
ActionId_t replyId, SerializeIF* data, bool hideSender) {
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
store_address_t storeAddress;
|
store_address_t storeAddress;
|
||||||
uint8_t *dataPtr;
|
uint8_t *dataPtr;
|
||||||
size_t maxSize = data->getSerializedSize();
|
size_t maxSize = data->getSerializedSize();
|
||||||
if (maxSize == 0) {
|
if (maxSize == 0) {
|
||||||
//No error, there's simply nothing to report.
|
//No error, there's simply nothing to report.
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
ReturnValue_t result = ipcStore->getFreeElement(&storeAddress, maxSize,
|
ReturnValue_t result = ipcStore->getFreeElement(&storeAddress, maxSize,
|
||||||
&dataPtr);
|
&dataPtr);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = data->serialize(&dataPtr, &size, maxSize,
|
result = data->serialize(&dataPtr, &size, maxSize,
|
||||||
SerializeIF::Endianness::BIG);
|
SerializeIF::Endianness::BIG);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
ipcStore->deleteData(storeAddress);
|
ipcStore->deleteData(storeAddress);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
// We don't need to report the objectId, as we receive REQUESTED data
|
// We don't need to report the objectId, as we receive REQUESTED data
|
||||||
// before the completion success message.
|
// before the completion success message.
|
||||||
// True aperiodic replies need to be reported with
|
// True aperiodic replies need to be reported with
|
||||||
// another dedicated message.
|
// another dedicated message.
|
||||||
ActionMessage::setDataReply(&reply, replyId, storeAddress);
|
ActionMessage::setDataReply(&reply, replyId, storeAddress);
|
||||||
|
|
||||||
// If the sender needs to be hidden, for example to handle packet
|
// If the sender needs to be hidden, for example to handle packet
|
||||||
// as unrequested reply, this will be done here.
|
// as unrequested reply, this will be done here.
|
||||||
if (hideSender) {
|
if (hideSender) {
|
||||||
result = MessageQueueSenderIF::sendMessage(reportTo, &reply);
|
result = MessageQueueSenderIF::sendMessage(reportTo, &reply);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = queueToUse->sendMessage(reportTo, &reply);
|
result = queueToUse->sendMessage(reportTo, &reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK){
|
if (result != HasReturnvaluesIF::RETURN_OK){
|
||||||
ipcStore->deleteData(storeAddress);
|
ipcStore->deleteData(storeAddress);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionHelper::resetHelper() {
|
void ActionHelper::resetHelper() {
|
||||||
@ -155,7 +155,7 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
|
|||||||
result = queueToUse->sendMessage(reportTo, &reply);
|
result = queueToUse->sendMessage(reportTo, &reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK){
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
ipcStore->deleteData(storeAddress);
|
ipcStore->deleteData(storeAddress);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -18,68 +18,68 @@ class HasActionsIF;
|
|||||||
|
|
||||||
class ActionHelper {
|
class ActionHelper {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Constructor of the action helper
|
* Constructor of the action helper
|
||||||
* @param setOwner Pointer to the owner of the interface
|
* @param setOwner Pointer to the owner of the interface
|
||||||
* @param useThisQueue messageQueue to be used, can be set during
|
* @param useThisQueue messageQueue to be used, can be set during
|
||||||
* initialize function as well.
|
* initialize function as well.
|
||||||
*/
|
*/
|
||||||
ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
||||||
|
|
||||||
virtual ~ActionHelper();
|
virtual ~ActionHelper();
|
||||||
/**
|
/**
|
||||||
* Function to be called from the owner with a new command message
|
* Function to be called from the owner with a new command message
|
||||||
*
|
*
|
||||||
* If the message is a valid action message the helper will use the
|
* If the message is a valid action message the helper will use the
|
||||||
* executeAction function from HasActionsIF.
|
* executeAction function from HasActionsIF.
|
||||||
* If the message is invalid or the callback fails a message reply will be
|
* If the message is invalid or the callback fails a message reply will be
|
||||||
* send to the sender of the message automatically.
|
* send to the sender of the message automatically.
|
||||||
*
|
*
|
||||||
* @param command Pointer to a command message received by the owner
|
* @param command Pointer to a command message received by the owner
|
||||||
* @return HasReturnvaluesIF::RETURN_OK if the message is a action message,
|
* @return HasReturnvaluesIF::RETURN_OK if the message is a action message,
|
||||||
* CommandMessage::UNKNOW_COMMAND if this message ID is unkown
|
* CommandMessage::UNKNOW_COMMAND if this message ID is unkown
|
||||||
*/
|
*/
|
||||||
ReturnValue_t handleActionMessage(CommandMessage* command);
|
ReturnValue_t handleActionMessage(CommandMessage* command);
|
||||||
/**
|
/**
|
||||||
* Helper initialize function. Must be called before use of any other
|
* Helper initialize function. Must be called before use of any other
|
||||||
* helper function
|
* helper function
|
||||||
* @param queueToUse_ Pointer to the messageQueue to be used, optional
|
* @param queueToUse_ Pointer to the messageQueue to be used, optional
|
||||||
* if queue was set in constructor
|
* if queue was set in constructor
|
||||||
* @return Returns RETURN_OK if successful
|
* @return Returns RETURN_OK if successful
|
||||||
*/
|
*/
|
||||||
ReturnValue_t initialize(MessageQueueIF* queueToUse_ = nullptr);
|
ReturnValue_t initialize(MessageQueueIF* queueToUse_ = nullptr);
|
||||||
/**
|
/**
|
||||||
* Function to be called from the owner to send a step message.
|
* Function to be called from the owner to send a step message.
|
||||||
* Success or failure will be determined by the result value.
|
* Success or failure will be determined by the result value.
|
||||||
*
|
*
|
||||||
* @param step Number of steps already done
|
* @param step Number of steps already done
|
||||||
* @param reportTo The messageQueueId to report the step message to
|
* @param reportTo The messageQueueId to report the step message to
|
||||||
* @param commandId ID of the executed command
|
* @param commandId ID of the executed command
|
||||||
* @param result Result of the execution
|
* @param result Result of the execution
|
||||||
*/
|
*/
|
||||||
void step(uint8_t step, MessageQueueId_t reportTo,
|
void step(uint8_t step, MessageQueueId_t reportTo,
|
||||||
ActionId_t commandId,
|
ActionId_t commandId,
|
||||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||||
/**
|
/**
|
||||||
* Function to be called by the owner to send a action completion message
|
* Function to be called by the owner to send a action completion message
|
||||||
*
|
*
|
||||||
* @param reportTo MessageQueueId_t to report the action completion message to
|
* @param reportTo MessageQueueId_t to report the action completion message to
|
||||||
* @param commandId ID of the executed command
|
* @param commandId ID of the executed command
|
||||||
* @param result Result of the execution
|
* @param result Result of the execution
|
||||||
*/
|
*/
|
||||||
void finish(MessageQueueId_t reportTo, ActionId_t commandId,
|
void finish(MessageQueueId_t reportTo, ActionId_t commandId,
|
||||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||||
/**
|
/**
|
||||||
* Function to be called by the owner if an action does report data.
|
* Function to be called by the owner if an action does report data.
|
||||||
* Takes a SerializeIF* pointer and serializes it into the IPC store.
|
* Takes a SerializeIF* pointer and serializes it into the IPC store.
|
||||||
* @param reportTo MessageQueueId_t to report the action completion
|
* @param reportTo MessageQueueId_t to report the action completion
|
||||||
* message to
|
* message to
|
||||||
* @param replyId ID of the executed command
|
* @param replyId ID of the executed command
|
||||||
* @param data Pointer to the data
|
* @param data Pointer to the data
|
||||||
* @return Returns RETURN_OK if successful, otherwise failure code
|
* @return Returns RETURN_OK if successful, otherwise failure code
|
||||||
*/
|
*/
|
||||||
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId,
|
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId,
|
||||||
SerializeIF* data, bool hideSender = false);
|
SerializeIF* data, bool hideSender = false);
|
||||||
/**
|
/**
|
||||||
* Function to be called by the owner if an action does report data.
|
* Function to be called by the owner if an action does report data.
|
||||||
* Takes the raw data and writes it into the IPC store.
|
* Takes the raw data and writes it into the IPC store.
|
||||||
@ -91,35 +91,35 @@ public:
|
|||||||
*/
|
*/
|
||||||
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId,
|
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId,
|
||||||
const uint8_t* data, size_t dataSize, bool hideSender = false);
|
const uint8_t* data, size_t dataSize, bool hideSender = false);
|
||||||
/**
|
/**
|
||||||
* Function to setup the MessageQueueIF* of the helper. Can be used to
|
* Function to setup the MessageQueueIF* of the helper. Can be used to
|
||||||
* set the MessageQueueIF* if message queue is unavailable at construction
|
* set the MessageQueueIF* if message queue is unavailable at construction
|
||||||
* and initialize but must be setup before first call of other functions.
|
* and initialize but must be setup before first call of other functions.
|
||||||
* @param queue Queue to be used by the helper
|
* @param queue Queue to be used by the helper
|
||||||
*/
|
*/
|
||||||
void setQueueToUse(MessageQueueIF *queue);
|
void setQueueToUse(MessageQueueIF *queue);
|
||||||
protected:
|
protected:
|
||||||
//!< Increase of value of this per step
|
//! Increase of value of this per step
|
||||||
static const uint8_t STEP_OFFSET = 1;
|
static const uint8_t STEP_OFFSET = 1;
|
||||||
HasActionsIF* owner;//!< Pointer to the owner
|
HasActionsIF* owner;//!< Pointer to the owner
|
||||||
//! Queue to be used as response sender, has to be set in ctor or with
|
//! Queue to be used as response sender, has to be set in ctor or with
|
||||||
//! setQueueToUse
|
//! setQueueToUse
|
||||||
MessageQueueIF* queueToUse;
|
MessageQueueIF* queueToUse;
|
||||||
//! Pointer to an IPC Store, initialized during construction or
|
//! Pointer to an IPC Store, initialized during construction or
|
||||||
StorageManagerIF* ipcStore = nullptr;
|
StorageManagerIF* ipcStore = nullptr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal function called by handleActionMessage
|
* Internal function called by handleActionMessage
|
||||||
* @param commandedBy MessageQueueID of Commander
|
* @param commandedBy MessageQueueID of Commander
|
||||||
* @param actionId ID of action to be done
|
* @param actionId ID of action to be done
|
||||||
* @param dataAddress Address of additional data in IPC Store
|
* @param dataAddress Address of additional data in IPC Store
|
||||||
*/
|
*/
|
||||||
virtual void prepareExecution(MessageQueueId_t commandedBy,
|
virtual void prepareExecution(MessageQueueId_t commandedBy,
|
||||||
ActionId_t actionId, store_address_t dataAddress);
|
ActionId_t actionId, store_address_t dataAddress);
|
||||||
/**
|
/**
|
||||||
* @brief Default implementation is empty.
|
* @brief Default implementation is empty.
|
||||||
*/
|
*/
|
||||||
virtual void resetHelper();
|
virtual void resetHelper();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_ACTION_ACTIONHELPER_H_ */
|
#endif /* FSFW_ACTION_ACTIONHELPER_H_ */
|
||||||
|
@ -11,71 +11,71 @@ ActionMessage::~ActionMessage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ActionMessage::setCommand(CommandMessage* message, ActionId_t fid,
|
void ActionMessage::setCommand(CommandMessage* message, ActionId_t fid,
|
||||||
store_address_t parameters) {
|
store_address_t parameters) {
|
||||||
message->setCommand(EXECUTE_ACTION);
|
message->setCommand(EXECUTE_ACTION);
|
||||||
message->setParameter(fid);
|
message->setParameter(fid);
|
||||||
message->setParameter2(parameters.raw);
|
message->setParameter2(parameters.raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
ActionId_t ActionMessage::getActionId(const CommandMessage* message) {
|
ActionId_t ActionMessage::getActionId(const CommandMessage* message) {
|
||||||
return ActionId_t(message->getParameter());
|
return ActionId_t(message->getParameter());
|
||||||
}
|
}
|
||||||
|
|
||||||
store_address_t ActionMessage::getStoreId(const CommandMessage* message) {
|
store_address_t ActionMessage::getStoreId(const CommandMessage* message) {
|
||||||
store_address_t temp;
|
store_address_t temp;
|
||||||
temp.raw = message->getParameter2();
|
temp.raw = message->getParameter2();
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionMessage::setStepReply(CommandMessage* message, ActionId_t fid, uint8_t step,
|
void ActionMessage::setStepReply(CommandMessage* message, ActionId_t fid, uint8_t step,
|
||||||
ReturnValue_t result) {
|
ReturnValue_t result) {
|
||||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||||
message->setCommand(STEP_SUCCESS);
|
message->setCommand(STEP_SUCCESS);
|
||||||
} else {
|
} else {
|
||||||
message->setCommand(STEP_FAILED);
|
message->setCommand(STEP_FAILED);
|
||||||
}
|
}
|
||||||
message->setParameter(fid);
|
message->setParameter(fid);
|
||||||
message->setParameter2((step << 16) + result);
|
message->setParameter2((step << 16) + result);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ActionMessage::getStep(const CommandMessage* message) {
|
uint8_t ActionMessage::getStep(const CommandMessage* message) {
|
||||||
return uint8_t((message->getParameter2() >> 16) & 0xFF);
|
return uint8_t((message->getParameter2() >> 16) & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t ActionMessage::getReturnCode(const CommandMessage* message) {
|
ReturnValue_t ActionMessage::getReturnCode(const CommandMessage* message) {
|
||||||
return message->getParameter2() & 0xFFFF;
|
return message->getParameter2() & 0xFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionMessage::setDataReply(CommandMessage* message, ActionId_t actionId,
|
void ActionMessage::setDataReply(CommandMessage* message, ActionId_t actionId,
|
||||||
store_address_t data) {
|
store_address_t data) {
|
||||||
message->setCommand(DATA_REPLY);
|
message->setCommand(DATA_REPLY);
|
||||||
message->setParameter(actionId);
|
message->setParameter(actionId);
|
||||||
message->setParameter2(data.raw);
|
message->setParameter2(data.raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionMessage::setCompletionReply(CommandMessage* message,
|
void ActionMessage::setCompletionReply(CommandMessage* message,
|
||||||
ActionId_t fid, ReturnValue_t result) {
|
ActionId_t fid, ReturnValue_t result) {
|
||||||
if (result == HasReturnvaluesIF::RETURN_OK or result == HasActionsIF::EXECUTION_FINISHED) {
|
if (result == HasReturnvaluesIF::RETURN_OK or result == HasActionsIF::EXECUTION_FINISHED) {
|
||||||
message->setCommand(COMPLETION_SUCCESS);
|
message->setCommand(COMPLETION_SUCCESS);
|
||||||
} else {
|
} else {
|
||||||
message->setCommand(COMPLETION_FAILED);
|
message->setCommand(COMPLETION_FAILED);
|
||||||
}
|
}
|
||||||
message->setParameter(fid);
|
message->setParameter(fid);
|
||||||
message->setParameter2(result);
|
message->setParameter2(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActionMessage::clear(CommandMessage* message) {
|
void ActionMessage::clear(CommandMessage* message) {
|
||||||
switch(message->getCommand()) {
|
switch(message->getCommand()) {
|
||||||
case EXECUTE_ACTION:
|
case EXECUTE_ACTION:
|
||||||
case DATA_REPLY: {
|
case DATA_REPLY: {
|
||||||
StorageManagerIF *ipcStore = objectManager->get<StorageManagerIF>(
|
StorageManagerIF *ipcStore = objectManager->get<StorageManagerIF>(
|
||||||
objects::IPC_STORE);
|
objects::IPC_STORE);
|
||||||
if (ipcStore != NULL) {
|
if (ipcStore != NULL) {
|
||||||
ipcStore->deleteData(getStoreId(message));
|
ipcStore->deleteData(getStoreId(message));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,29 +15,29 @@ using ActionId_t = uint32_t;
|
|||||||
*/
|
*/
|
||||||
class ActionMessage {
|
class ActionMessage {
|
||||||
private:
|
private:
|
||||||
ActionMessage();
|
ActionMessage();
|
||||||
public:
|
public:
|
||||||
static const uint8_t MESSAGE_ID = messagetypes::ACTION;
|
static const uint8_t MESSAGE_ID = messagetypes::ACTION;
|
||||||
static const Command_t EXECUTE_ACTION = MAKE_COMMAND_ID(1);
|
static const Command_t EXECUTE_ACTION = MAKE_COMMAND_ID(1);
|
||||||
static const Command_t STEP_SUCCESS = MAKE_COMMAND_ID(2);
|
static const Command_t STEP_SUCCESS = MAKE_COMMAND_ID(2);
|
||||||
static const Command_t STEP_FAILED = MAKE_COMMAND_ID(3);
|
static const Command_t STEP_FAILED = MAKE_COMMAND_ID(3);
|
||||||
static const Command_t DATA_REPLY = MAKE_COMMAND_ID(4);
|
static const Command_t DATA_REPLY = MAKE_COMMAND_ID(4);
|
||||||
static const Command_t COMPLETION_SUCCESS = MAKE_COMMAND_ID(5);
|
static const Command_t COMPLETION_SUCCESS = MAKE_COMMAND_ID(5);
|
||||||
static const Command_t COMPLETION_FAILED = MAKE_COMMAND_ID(6);
|
static const Command_t COMPLETION_FAILED = MAKE_COMMAND_ID(6);
|
||||||
virtual ~ActionMessage();
|
virtual ~ActionMessage();
|
||||||
static void setCommand(CommandMessage* message, ActionId_t fid,
|
static void setCommand(CommandMessage* message, ActionId_t fid,
|
||||||
store_address_t parameters);
|
store_address_t parameters);
|
||||||
static ActionId_t getActionId(const CommandMessage* message );
|
static ActionId_t getActionId(const CommandMessage* message );
|
||||||
static store_address_t getStoreId(const CommandMessage* message );
|
static store_address_t getStoreId(const CommandMessage* message );
|
||||||
static void setStepReply(CommandMessage* message, ActionId_t fid,
|
static void setStepReply(CommandMessage* message, ActionId_t fid,
|
||||||
uint8_t step, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
uint8_t step, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||||
static uint8_t getStep(const CommandMessage* message );
|
static uint8_t getStep(const CommandMessage* message );
|
||||||
static ReturnValue_t getReturnCode(const CommandMessage* message );
|
static ReturnValue_t getReturnCode(const CommandMessage* message );
|
||||||
static void setDataReply(CommandMessage* message, ActionId_t actionId,
|
static void setDataReply(CommandMessage* message, ActionId_t actionId,
|
||||||
store_address_t data);
|
store_address_t data);
|
||||||
static void setCompletionReply(CommandMessage* message, ActionId_t fid,
|
static void setCompletionReply(CommandMessage* message, ActionId_t fid,
|
||||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||||
static void clear(CommandMessage* message);
|
static void clear(CommandMessage* message);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_ACTION_ACTIONMESSAGE_H_ */
|
#endif /* FSFW_ACTION_ACTIONMESSAGE_H_ */
|
||||||
|
@ -5,123 +5,123 @@
|
|||||||
#include "../objectmanager/ObjectManagerIF.h"
|
#include "../objectmanager/ObjectManagerIF.h"
|
||||||
|
|
||||||
CommandActionHelper::CommandActionHelper(CommandsActionsIF *setOwner) :
|
CommandActionHelper::CommandActionHelper(CommandsActionsIF *setOwner) :
|
||||||
owner(setOwner), queueToUse(NULL), ipcStore(
|
owner(setOwner), queueToUse(NULL), ipcStore(
|
||||||
NULL), commandCount(0), lastTarget(0) {
|
NULL), commandCount(0), lastTarget(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandActionHelper::~CommandActionHelper() {
|
CommandActionHelper::~CommandActionHelper() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo,
|
ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo,
|
||||||
ActionId_t actionId, SerializeIF *data) {
|
ActionId_t actionId, SerializeIF *data) {
|
||||||
HasActionsIF *receiver = objectManager->get<HasActionsIF>(commandTo);
|
HasActionsIF *receiver = objectManager->get<HasActionsIF>(commandTo);
|
||||||
if (receiver == NULL) {
|
if (receiver == NULL) {
|
||||||
return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS;
|
return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS;
|
||||||
}
|
}
|
||||||
store_address_t storeId;
|
store_address_t storeId;
|
||||||
uint8_t *storePointer;
|
uint8_t *storePointer;
|
||||||
size_t maxSize = data->getSerializedSize();
|
size_t maxSize = data->getSerializedSize();
|
||||||
ReturnValue_t result = ipcStore->getFreeElement(&storeId, maxSize,
|
ReturnValue_t result = ipcStore->getFreeElement(&storeId, maxSize,
|
||||||
&storePointer);
|
&storePointer);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
result = data->serialize(&storePointer, &size, maxSize,
|
result = data->serialize(&storePointer, &size, maxSize,
|
||||||
SerializeIF::Endianness::BIG);
|
SerializeIF::Endianness::BIG);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return sendCommand(receiver->getCommandQueue(), actionId, storeId);
|
return sendCommand(receiver->getCommandQueue(), actionId, storeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo,
|
ReturnValue_t CommandActionHelper::commandAction(object_id_t commandTo,
|
||||||
ActionId_t actionId, const uint8_t *data, uint32_t size) {
|
ActionId_t actionId, const uint8_t *data, uint32_t size) {
|
||||||
// if (commandCount != 0) {
|
// if (commandCount != 0) {
|
||||||
// return CommandsFunctionsIF::ALREADY_COMMANDING;
|
// return CommandsFunctionsIF::ALREADY_COMMANDING;
|
||||||
// }
|
// }
|
||||||
HasActionsIF *receiver = objectManager->get<HasActionsIF>(commandTo);
|
HasActionsIF *receiver = objectManager->get<HasActionsIF>(commandTo);
|
||||||
if (receiver == NULL) {
|
if (receiver == NULL) {
|
||||||
return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS;
|
return CommandsActionsIF::OBJECT_HAS_NO_FUNCTIONS;
|
||||||
}
|
}
|
||||||
store_address_t storeId;
|
store_address_t storeId;
|
||||||
ReturnValue_t result = ipcStore->addData(&storeId, data, size);
|
ReturnValue_t result = ipcStore->addData(&storeId, data, size);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return sendCommand(receiver->getCommandQueue(), actionId, storeId);
|
return sendCommand(receiver->getCommandQueue(), actionId, storeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CommandActionHelper::sendCommand(MessageQueueId_t queueId,
|
ReturnValue_t CommandActionHelper::sendCommand(MessageQueueId_t queueId,
|
||||||
ActionId_t actionId, store_address_t storeId) {
|
ActionId_t actionId, store_address_t storeId) {
|
||||||
CommandMessage command;
|
CommandMessage command;
|
||||||
ActionMessage::setCommand(&command, actionId, storeId);
|
ActionMessage::setCommand(&command, actionId, storeId);
|
||||||
ReturnValue_t result = queueToUse->sendMessage(queueId, &command);
|
ReturnValue_t result = queueToUse->sendMessage(queueId, &command);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
ipcStore->deleteData(storeId);
|
ipcStore->deleteData(storeId);
|
||||||
}
|
}
|
||||||
lastTarget = queueId;
|
lastTarget = queueId;
|
||||||
commandCount++;
|
commandCount++;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CommandActionHelper::initialize() {
|
ReturnValue_t CommandActionHelper::initialize() {
|
||||||
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
||||||
if (ipcStore == NULL) {
|
if (ipcStore == NULL) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
queueToUse = owner->getCommandQueuePtr();
|
queueToUse = owner->getCommandQueuePtr();
|
||||||
if (queueToUse == NULL) {
|
if (queueToUse == NULL) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t CommandActionHelper::handleReply(CommandMessage *reply) {
|
ReturnValue_t CommandActionHelper::handleReply(CommandMessage *reply) {
|
||||||
if (reply->getSender() != lastTarget) {
|
if (reply->getSender() != lastTarget) {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
switch (reply->getCommand()) {
|
switch (reply->getCommand()) {
|
||||||
case ActionMessage::COMPLETION_SUCCESS:
|
case ActionMessage::COMPLETION_SUCCESS:
|
||||||
commandCount--;
|
commandCount--;
|
||||||
owner->completionSuccessfulReceived(ActionMessage::getActionId(reply));
|
owner->completionSuccessfulReceived(ActionMessage::getActionId(reply));
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
case ActionMessage::COMPLETION_FAILED:
|
case ActionMessage::COMPLETION_FAILED:
|
||||||
commandCount--;
|
commandCount--;
|
||||||
owner->completionFailedReceived(ActionMessage::getActionId(reply),
|
owner->completionFailedReceived(ActionMessage::getActionId(reply),
|
||||||
ActionMessage::getReturnCode(reply));
|
ActionMessage::getReturnCode(reply));
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
case ActionMessage::STEP_SUCCESS:
|
case ActionMessage::STEP_SUCCESS:
|
||||||
owner->stepSuccessfulReceived(ActionMessage::getActionId(reply),
|
owner->stepSuccessfulReceived(ActionMessage::getActionId(reply),
|
||||||
ActionMessage::getStep(reply));
|
ActionMessage::getStep(reply));
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
case ActionMessage::STEP_FAILED:
|
case ActionMessage::STEP_FAILED:
|
||||||
commandCount--;
|
commandCount--;
|
||||||
owner->stepFailedReceived(ActionMessage::getActionId(reply),
|
owner->stepFailedReceived(ActionMessage::getActionId(reply),
|
||||||
ActionMessage::getStep(reply),
|
ActionMessage::getStep(reply),
|
||||||
ActionMessage::getReturnCode(reply));
|
ActionMessage::getReturnCode(reply));
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
case ActionMessage::DATA_REPLY:
|
case ActionMessage::DATA_REPLY:
|
||||||
extractDataForOwner(ActionMessage::getActionId(reply),
|
extractDataForOwner(ActionMessage::getActionId(reply),
|
||||||
ActionMessage::getStoreId(reply));
|
ActionMessage::getStoreId(reply));
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
default:
|
default:
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t CommandActionHelper::getCommandCount() const {
|
uint8_t CommandActionHelper::getCommandCount() const {
|
||||||
return commandCount;
|
return commandCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandActionHelper::extractDataForOwner(ActionId_t actionId, store_address_t storeId) {
|
void CommandActionHelper::extractDataForOwner(ActionId_t actionId, store_address_t storeId) {
|
||||||
const uint8_t * data = NULL;
|
const uint8_t * data = NULL;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
ReturnValue_t result = ipcStore->getData(storeId, &data, &size);
|
ReturnValue_t result = ipcStore->getData(storeId, &data, &size);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
owner->dataReceived(actionId, data, size);
|
owner->dataReceived(actionId, data, size);
|
||||||
ipcStore->deleteData(storeId);
|
ipcStore->deleteData(storeId);
|
||||||
}
|
}
|
||||||
|
@ -11,26 +11,26 @@
|
|||||||
class CommandsActionsIF;
|
class CommandsActionsIF;
|
||||||
|
|
||||||
class CommandActionHelper {
|
class CommandActionHelper {
|
||||||
friend class CommandsActionsIF;
|
friend class CommandsActionsIF;
|
||||||
public:
|
public:
|
||||||
CommandActionHelper(CommandsActionsIF* owner);
|
CommandActionHelper(CommandsActionsIF* owner);
|
||||||
virtual ~CommandActionHelper();
|
virtual ~CommandActionHelper();
|
||||||
ReturnValue_t commandAction(object_id_t commandTo,
|
ReturnValue_t commandAction(object_id_t commandTo,
|
||||||
ActionId_t actionId, const uint8_t* data, uint32_t size);
|
ActionId_t actionId, const uint8_t* data, uint32_t size);
|
||||||
ReturnValue_t commandAction(object_id_t commandTo,
|
ReturnValue_t commandAction(object_id_t commandTo,
|
||||||
ActionId_t actionId, SerializeIF* data);
|
ActionId_t actionId, SerializeIF* data);
|
||||||
ReturnValue_t initialize();
|
ReturnValue_t initialize();
|
||||||
ReturnValue_t handleReply(CommandMessage* reply);
|
ReturnValue_t handleReply(CommandMessage* reply);
|
||||||
uint8_t getCommandCount() const;
|
uint8_t getCommandCount() const;
|
||||||
private:
|
private:
|
||||||
CommandsActionsIF* owner;
|
CommandsActionsIF* owner;
|
||||||
MessageQueueIF* queueToUse;
|
MessageQueueIF* queueToUse;
|
||||||
StorageManagerIF* ipcStore;
|
StorageManagerIF* ipcStore;
|
||||||
uint8_t commandCount;
|
uint8_t commandCount;
|
||||||
MessageQueueId_t lastTarget;
|
MessageQueueId_t lastTarget;
|
||||||
void extractDataForOwner(ActionId_t actionId, store_address_t storeId);
|
void extractDataForOwner(ActionId_t actionId, store_address_t storeId);
|
||||||
ReturnValue_t sendCommand(MessageQueueId_t queueId, ActionId_t actionId,
|
ReturnValue_t sendCommand(MessageQueueId_t queueId, ActionId_t actionId,
|
||||||
store_address_t storeId);
|
store_address_t storeId);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* COMMANDACTIONHELPER_H_ */
|
#endif /* COMMANDACTIONHELPER_H_ */
|
||||||
|
@ -15,22 +15,22 @@
|
|||||||
* - replyReceived(id, step, cause) (if cause == OK, it's a success).
|
* - replyReceived(id, step, cause) (if cause == OK, it's a success).
|
||||||
*/
|
*/
|
||||||
class CommandsActionsIF {
|
class CommandsActionsIF {
|
||||||
friend class CommandActionHelper;
|
friend class CommandActionHelper;
|
||||||
public:
|
public:
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::COMMANDS_ACTIONS_IF;
|
static const uint8_t INTERFACE_ID = CLASS_ID::COMMANDS_ACTIONS_IF;
|
||||||
static const ReturnValue_t OBJECT_HAS_NO_FUNCTIONS = MAKE_RETURN_CODE(1);
|
static const ReturnValue_t OBJECT_HAS_NO_FUNCTIONS = MAKE_RETURN_CODE(1);
|
||||||
static const ReturnValue_t ALREADY_COMMANDING = MAKE_RETURN_CODE(2);
|
static const ReturnValue_t ALREADY_COMMANDING = MAKE_RETURN_CODE(2);
|
||||||
virtual ~CommandsActionsIF() {}
|
virtual ~CommandsActionsIF() {}
|
||||||
virtual MessageQueueIF* getCommandQueuePtr() = 0;
|
virtual MessageQueueIF* getCommandQueuePtr() = 0;
|
||||||
protected:
|
protected:
|
||||||
virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step) = 0;
|
virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step) = 0;
|
||||||
virtual void stepFailedReceived(ActionId_t actionId, uint8_t step,
|
virtual void stepFailedReceived(ActionId_t actionId, uint8_t step,
|
||||||
ReturnValue_t returnCode) = 0;
|
ReturnValue_t returnCode) = 0;
|
||||||
virtual void dataReceived(ActionId_t actionId, const uint8_t* data,
|
virtual void dataReceived(ActionId_t actionId, const uint8_t* data,
|
||||||
uint32_t size) = 0;
|
uint32_t size) = 0;
|
||||||
virtual void completionSuccessfulReceived(ActionId_t actionId) = 0;
|
virtual void completionSuccessfulReceived(ActionId_t actionId) = 0;
|
||||||
virtual void completionFailedReceived(ActionId_t actionId,
|
virtual void completionFailedReceived(ActionId_t actionId,
|
||||||
ReturnValue_t returnCode) = 0;
|
ReturnValue_t returnCode) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,28 +35,28 @@
|
|||||||
*/
|
*/
|
||||||
class HasActionsIF {
|
class HasActionsIF {
|
||||||
public:
|
public:
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_ACTIONS_IF;
|
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_ACTIONS_IF;
|
||||||
static const ReturnValue_t IS_BUSY = MAKE_RETURN_CODE(1);
|
static const ReturnValue_t IS_BUSY = MAKE_RETURN_CODE(1);
|
||||||
static const ReturnValue_t INVALID_PARAMETERS = MAKE_RETURN_CODE(2);
|
static const ReturnValue_t INVALID_PARAMETERS = MAKE_RETURN_CODE(2);
|
||||||
static const ReturnValue_t EXECUTION_FINISHED = MAKE_RETURN_CODE(3);
|
static const ReturnValue_t EXECUTION_FINISHED = MAKE_RETURN_CODE(3);
|
||||||
static const ReturnValue_t INVALID_ACTION_ID = MAKE_RETURN_CODE(4);
|
static const ReturnValue_t INVALID_ACTION_ID = MAKE_RETURN_CODE(4);
|
||||||
virtual ~HasActionsIF() { }
|
virtual ~HasActionsIF() { }
|
||||||
/**
|
/**
|
||||||
* Function to get the MessageQueueId_t of the implementing object
|
* Function to get the MessageQueueId_t of the implementing object
|
||||||
* @return MessageQueueId_t of the object
|
* @return MessageQueueId_t of the object
|
||||||
*/
|
*/
|
||||||
virtual MessageQueueId_t getCommandQueue() const = 0;
|
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||||
/**
|
/**
|
||||||
* Execute or initialize the execution of a certain function.
|
* Execute or initialize the execution of a certain function.
|
||||||
* The ActionHelpers will execute this function and behave differently
|
* The ActionHelpers will execute this function and behave differently
|
||||||
* depending on the returnvalue.
|
* depending on the returnvalue.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* -@c EXECUTION_FINISHED Finish reply will be generated
|
* -@c EXECUTION_FINISHED Finish reply will be generated
|
||||||
* -@c Not RETURN_OK Step failure reply will be generated
|
* -@c Not RETURN_OK Step failure reply will be generated
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t executeAction(ActionId_t actionId,
|
virtual ReturnValue_t executeAction(ActionId_t actionId,
|
||||||
MessageQueueId_t commandedBy, const uint8_t* data, size_t size) = 0;
|
MessageQueueId_t commandedBy, const uint8_t* data, size_t size) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,74 +2,74 @@
|
|||||||
#include "SimpleActionHelper.h"
|
#include "SimpleActionHelper.h"
|
||||||
|
|
||||||
SimpleActionHelper::SimpleActionHelper(HasActionsIF* setOwner,
|
SimpleActionHelper::SimpleActionHelper(HasActionsIF* setOwner,
|
||||||
MessageQueueIF* useThisQueue) :
|
MessageQueueIF* useThisQueue) :
|
||||||
ActionHelper(setOwner, useThisQueue), isExecuting(false) {
|
ActionHelper(setOwner, useThisQueue), isExecuting(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleActionHelper::~SimpleActionHelper() {
|
SimpleActionHelper::~SimpleActionHelper() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleActionHelper::step(ReturnValue_t result) {
|
void SimpleActionHelper::step(ReturnValue_t result) {
|
||||||
// STEP_OFFESET is subtracted to compensate for adding offset in base
|
// STEP_OFFESET is subtracted to compensate for adding offset in base
|
||||||
// method, which is not necessary here.
|
// method, which is not necessary here.
|
||||||
ActionHelper::step(stepCount - STEP_OFFSET, lastCommander, lastAction,
|
ActionHelper::step(stepCount - STEP_OFFSET, lastCommander, lastAction,
|
||||||
result);
|
result);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
resetHelper();
|
resetHelper();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleActionHelper::finish(ReturnValue_t result) {
|
void SimpleActionHelper::finish(ReturnValue_t result) {
|
||||||
ActionHelper::finish(lastCommander, lastAction, result);
|
ActionHelper::finish(lastCommander, lastAction, result);
|
||||||
resetHelper();
|
resetHelper();
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t SimpleActionHelper::reportData(SerializeIF* data) {
|
ReturnValue_t SimpleActionHelper::reportData(SerializeIF* data) {
|
||||||
return ActionHelper::reportData(lastCommander, lastAction, data);
|
return ActionHelper::reportData(lastCommander, lastAction, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleActionHelper::resetHelper() {
|
void SimpleActionHelper::resetHelper() {
|
||||||
stepCount = 0;
|
stepCount = 0;
|
||||||
isExecuting = false;
|
isExecuting = false;
|
||||||
lastAction = 0;
|
lastAction = 0;
|
||||||
lastCommander = 0;
|
lastCommander = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleActionHelper::prepareExecution(MessageQueueId_t commandedBy,
|
void SimpleActionHelper::prepareExecution(MessageQueueId_t commandedBy,
|
||||||
ActionId_t actionId, store_address_t dataAddress) {
|
ActionId_t actionId, store_address_t dataAddress) {
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
if (isExecuting) {
|
if (isExecuting) {
|
||||||
ipcStore->deleteData(dataAddress);
|
ipcStore->deleteData(dataAddress);
|
||||||
ActionMessage::setStepReply(&reply, actionId, 0,
|
ActionMessage::setStepReply(&reply, actionId, 0,
|
||||||
HasActionsIF::IS_BUSY);
|
HasActionsIF::IS_BUSY);
|
||||||
queueToUse->sendMessage(commandedBy, &reply);
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
}
|
}
|
||||||
const uint8_t* dataPtr = NULL;
|
const uint8_t* dataPtr = NULL;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||||
queueToUse->sendMessage(commandedBy, &reply);
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lastCommander = commandedBy;
|
lastCommander = commandedBy;
|
||||||
lastAction = actionId;
|
lastAction = actionId;
|
||||||
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
||||||
ipcStore->deleteData(dataAddress);
|
ipcStore->deleteData(dataAddress);
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case HasReturnvaluesIF::RETURN_OK:
|
case HasReturnvaluesIF::RETURN_OK:
|
||||||
isExecuting = true;
|
isExecuting = true;
|
||||||
stepCount++;
|
stepCount++;
|
||||||
break;
|
break;
|
||||||
case HasActionsIF::EXECUTION_FINISHED:
|
case HasActionsIF::EXECUTION_FINISHED:
|
||||||
ActionMessage::setCompletionReply(&reply, actionId,
|
ActionMessage::setCompletionReply(&reply, actionId,
|
||||||
HasReturnvaluesIF::RETURN_OK);
|
HasReturnvaluesIF::RETURN_OK);
|
||||||
queueToUse->sendMessage(commandedBy, &reply);
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||||
queueToUse->sendMessage(commandedBy, &reply);
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,27 +4,27 @@
|
|||||||
#include "ActionHelper.h"
|
#include "ActionHelper.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This is an action helper which is only able to service one action
|
* @brief This is an action helper which is only able to service one action
|
||||||
* at a time but remembers last commander and last action which
|
* at a time but remembers last commander and last action which
|
||||||
* simplifies usage
|
* simplifies usage
|
||||||
*/
|
*/
|
||||||
class SimpleActionHelper: public ActionHelper {
|
class SimpleActionHelper: public ActionHelper {
|
||||||
public:
|
public:
|
||||||
SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
|
||||||
virtual ~SimpleActionHelper();
|
virtual ~SimpleActionHelper();
|
||||||
void step(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
void step(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||||
void finish(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
void finish(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
|
||||||
ReturnValue_t reportData(SerializeIF* data);
|
ReturnValue_t reportData(SerializeIF* data);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
|
void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
|
||||||
store_address_t dataAddress);
|
store_address_t dataAddress);
|
||||||
virtual void resetHelper();
|
virtual void resetHelper();
|
||||||
private:
|
private:
|
||||||
bool isExecuting;
|
bool isExecuting;
|
||||||
MessageQueueId_t lastCommander = MessageQueueIF::NO_QUEUE;
|
MessageQueueId_t lastCommander = MessageQueueIF::NO_QUEUE;
|
||||||
ActionId_t lastAction = 0;
|
ActionId_t lastAction = 0;
|
||||||
uint8_t stepCount = 0;
|
uint8_t stepCount = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SIMPLEACTIONHELPER_H_ */
|
#endif /* SIMPLEACTIONHELPER_H_ */
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include "../serialize/SerializeIF.h"
|
#include "../serialize/SerializeIF.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A List that stores its values in an array.
|
* @brief A List that stores its values in an array.
|
||||||
* @details
|
* @details
|
||||||
* The underlying storage is an array that can be allocated by the class
|
* The underlying storage is an array that can be allocated by the class
|
||||||
* itself or supplied via ctor.
|
* itself or supplied via ctor.
|
||||||
@ -15,237 +15,237 @@
|
|||||||
*/
|
*/
|
||||||
template<typename T, typename count_t = uint8_t>
|
template<typename T, typename count_t = uint8_t>
|
||||||
class ArrayList {
|
class ArrayList {
|
||||||
template<typename U, typename count> friend class SerialArrayListAdapter;
|
template<typename U, typename count> friend class SerialArrayListAdapter;
|
||||||
public:
|
public:
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::ARRAY_LIST;
|
static const uint8_t INTERFACE_ID = CLASS_ID::ARRAY_LIST;
|
||||||
static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01);
|
static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the allocating constructor.
|
* This is the allocating constructor.
|
||||||
* It allocates an array of the specified size.
|
* It allocates an array of the specified size.
|
||||||
* @param maxSize
|
* @param maxSize
|
||||||
*/
|
*/
|
||||||
ArrayList(count_t maxSize) :
|
ArrayList(count_t maxSize) :
|
||||||
size(0), maxSize_(maxSize), allocated(true) {
|
size(0), maxSize_(maxSize), allocated(true) {
|
||||||
entries = new T[maxSize];
|
entries = new T[maxSize];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the non-allocating constructor
|
* This is the non-allocating constructor
|
||||||
*
|
*
|
||||||
* It expects a pointer to an array of a certain size and initializes
|
* It expects a pointer to an array of a certain size and initializes
|
||||||
* itself to it.
|
* itself to it.
|
||||||
*
|
*
|
||||||
* @param storage the array to use as backend
|
* @param storage the array to use as backend
|
||||||
* @param maxSize size of storage
|
* @param maxSize size of storage
|
||||||
* @param size size of data already present in storage
|
* @param size size of data already present in storage
|
||||||
*/
|
*/
|
||||||
ArrayList(T *storage, count_t maxSize, count_t size = 0) :
|
ArrayList(T *storage, count_t maxSize, count_t size = 0) :
|
||||||
size(size), entries(storage), maxSize_(maxSize), allocated(false) {
|
size(size), entries(storage), maxSize_(maxSize), allocated(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copying is forbiden by declaring copy ctor and copy assignment deleted
|
* Copying is forbiden by declaring copy ctor and copy assignment deleted
|
||||||
* It is too ambigous in this case.
|
* It is too ambigous in this case.
|
||||||
* (Allocate a new backend? Use the same? What to do in an modifying call?)
|
* (Allocate a new backend? Use the same? What to do in an modifying call?)
|
||||||
*/
|
*/
|
||||||
ArrayList(const ArrayList& other) = delete;
|
ArrayList(const ArrayList& other) = delete;
|
||||||
const ArrayList& operator=(const ArrayList& other) = delete;
|
const ArrayList& operator=(const ArrayList& other) = delete;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of Elements stored in this List
|
* Number of Elements stored in this List
|
||||||
*/
|
*/
|
||||||
count_t size;
|
count_t size;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destructor, if the allocating constructor was used, it deletes the array.
|
* Destructor, if the allocating constructor was used, it deletes the array.
|
||||||
*/
|
*/
|
||||||
virtual ~ArrayList() {
|
virtual ~ArrayList() {
|
||||||
if (allocated) {
|
if (allocated) {
|
||||||
delete[] entries;
|
delete[] entries;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An Iterator to go trough an ArrayList
|
* An Iterator to go trough an ArrayList
|
||||||
*
|
*
|
||||||
* It stores a pointer to an element and increments the
|
* It stores a pointer to an element and increments the
|
||||||
* pointer when incremented itself.
|
* pointer when incremented itself.
|
||||||
*/
|
*/
|
||||||
class Iterator {
|
class Iterator {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Empty ctor, points to NULL
|
* Empty ctor, points to NULL
|
||||||
*/
|
*/
|
||||||
Iterator(): value(0) {}
|
Iterator(): value(0) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the Iterator to point to an element
|
* Initializes the Iterator to point to an element
|
||||||
*
|
*
|
||||||
* @param initialize
|
* @param initialize
|
||||||
*/
|
*/
|
||||||
Iterator(T *initialize) {
|
Iterator(T *initialize) {
|
||||||
value = initialize;
|
value = initialize;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current element the iterator points to
|
* The current element the iterator points to
|
||||||
*/
|
*/
|
||||||
T *value;
|
T *value;
|
||||||
|
|
||||||
Iterator& operator++() {
|
Iterator& operator++() {
|
||||||
value++;
|
value++;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator operator++(int) {
|
Iterator operator++(int) {
|
||||||
Iterator tmp(*this);
|
Iterator tmp(*this);
|
||||||
operator++();
|
operator++();
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator& operator--() {
|
Iterator& operator--() {
|
||||||
value--;
|
value--;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator operator--(int) {
|
Iterator operator--(int) {
|
||||||
Iterator tmp(*this);
|
Iterator tmp(*this);
|
||||||
operator--();
|
operator--();
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
T& operator*() {
|
T& operator*() {
|
||||||
return *value;
|
return *value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const T& operator*() const {
|
const T& operator*() const {
|
||||||
return *value;
|
return *value;
|
||||||
}
|
}
|
||||||
|
|
||||||
T *operator->() {
|
T *operator->() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const T *operator->() const {
|
const T *operator->() const {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
friend bool operator==(const ArrayList::Iterator& lhs,
|
friend bool operator==(const ArrayList::Iterator& lhs,
|
||||||
const ArrayList::Iterator& rhs) {
|
const ArrayList::Iterator& rhs) {
|
||||||
return (lhs.value == rhs.value);
|
return (lhs.value == rhs.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator!=(const ArrayList::Iterator& lhs,
|
friend bool operator!=(const ArrayList::Iterator& lhs,
|
||||||
const ArrayList::Iterator& rhs) {
|
const ArrayList::Iterator& rhs) {
|
||||||
return not (lhs.value == rhs.value);
|
return not (lhs.value == rhs.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterator pointing to the first stored elmement
|
* Iterator pointing to the first stored elmement
|
||||||
*
|
*
|
||||||
* @return Iterator to the first element
|
* @return Iterator to the first element
|
||||||
*/
|
*/
|
||||||
Iterator begin() const {
|
Iterator begin() const {
|
||||||
return Iterator(&entries[0]);
|
return Iterator(&entries[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns an Iterator pointing to the element after the last stored entry
|
* returns an Iterator pointing to the element after the last stored entry
|
||||||
*
|
*
|
||||||
* @return Iterator to the element after the last entry
|
* @return Iterator to the element after the last entry
|
||||||
*/
|
*/
|
||||||
Iterator end() const {
|
Iterator end() const {
|
||||||
return Iterator(&entries[size]);
|
return Iterator(&entries[size]);
|
||||||
}
|
}
|
||||||
|
|
||||||
T & operator[](count_t i) const {
|
T & operator[](count_t i) const {
|
||||||
return entries[i];
|
return entries[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The first element
|
* The first element
|
||||||
*
|
*
|
||||||
* @return pointer to the first stored element
|
* @return pointer to the first stored element
|
||||||
*/
|
*/
|
||||||
T *front() {
|
T *front() {
|
||||||
return entries;
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The last element
|
* The last element
|
||||||
*
|
*
|
||||||
* does not return a valid pointer if called on an empty list.
|
* does not return a valid pointer if called on an empty list.
|
||||||
*
|
*
|
||||||
* @return pointer to the last stored element
|
* @return pointer to the last stored element
|
||||||
*/
|
*/
|
||||||
T *back() {
|
T *back() {
|
||||||
return &entries[size - 1];
|
return &entries[size - 1];
|
||||||
//Alternative solution
|
//Alternative solution
|
||||||
//return const_cast<T*>(static_cast<const T*>(*this).back());
|
//return const_cast<T*>(static_cast<const T*>(*this).back());
|
||||||
}
|
}
|
||||||
|
|
||||||
const T* back() const{
|
const T* back() const{
|
||||||
return &entries[size-1];
|
return &entries[size-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum number of elements this List can contain
|
* The maximum number of elements this List can contain
|
||||||
*
|
*
|
||||||
* @return maximum number of elements
|
* @return maximum number of elements
|
||||||
*/
|
*/
|
||||||
size_t maxSize() const {
|
size_t maxSize() const {
|
||||||
return this->maxSize_;
|
return this->maxSize_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert a new element into the list.
|
* Insert a new element into the list.
|
||||||
*
|
*
|
||||||
* The new element is inserted after the last stored element.
|
* The new element is inserted after the last stored element.
|
||||||
*
|
*
|
||||||
* @param entry
|
* @param entry
|
||||||
* @return
|
* @return
|
||||||
* -@c FULL if the List is full
|
* -@c FULL if the List is full
|
||||||
* -@c RETURN_OK else
|
* -@c RETURN_OK else
|
||||||
*/
|
*/
|
||||||
ReturnValue_t insert(T entry) {
|
ReturnValue_t insert(T entry) {
|
||||||
if (size >= maxSize_) {
|
if (size >= maxSize_) {
|
||||||
return FULL;
|
return FULL;
|
||||||
}
|
}
|
||||||
entries[size] = entry;
|
entries[size] = entry;
|
||||||
++size;
|
++size;
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clear the List
|
* clear the List
|
||||||
*
|
*
|
||||||
* This does not actually clear all entries, it only sets the size to 0.
|
* This does not actually clear all entries, it only sets the size to 0.
|
||||||
*/
|
*/
|
||||||
void clear() {
|
void clear() {
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
count_t remaining() {
|
count_t remaining() {
|
||||||
return (maxSize_ - size);
|
return (maxSize_ - size);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* pointer to the array in which the entries are stored
|
* pointer to the array in which the entries are stored
|
||||||
*/
|
*/
|
||||||
T *entries;
|
T *entries;
|
||||||
/**
|
/**
|
||||||
* remembering the maximum size
|
* remembering the maximum size
|
||||||
*/
|
*/
|
||||||
size_t maxSize_;
|
size_t maxSize_;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* true if the array was allocated and needs to be deleted in the destructor.
|
* true if the array was allocated and needs to be deleted in the destructor.
|
||||||
*/
|
*/
|
||||||
bool allocated;
|
bool allocated;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,65 +7,65 @@
|
|||||||
template<typename Tp>
|
template<typename Tp>
|
||||||
class BinaryNode {
|
class BinaryNode {
|
||||||
public:
|
public:
|
||||||
BinaryNode(Tp* setValue) :
|
BinaryNode(Tp* setValue) :
|
||||||
value(setValue), left(NULL), right(NULL), parent(NULL) {
|
value(setValue), left(NULL), right(NULL), parent(NULL) {
|
||||||
}
|
}
|
||||||
Tp *value;
|
Tp *value;
|
||||||
BinaryNode* left;
|
BinaryNode* left;
|
||||||
BinaryNode* right;
|
BinaryNode* right;
|
||||||
BinaryNode* parent;
|
BinaryNode* parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Tp>
|
template<typename Tp>
|
||||||
class ExplicitNodeIterator {
|
class ExplicitNodeIterator {
|
||||||
public:
|
public:
|
||||||
typedef ExplicitNodeIterator<Tp> _Self;
|
typedef ExplicitNodeIterator<Tp> _Self;
|
||||||
typedef BinaryNode<Tp> _Node;
|
typedef BinaryNode<Tp> _Node;
|
||||||
typedef Tp value_type;
|
typedef Tp value_type;
|
||||||
typedef Tp* pointer;
|
typedef Tp* pointer;
|
||||||
typedef Tp& reference;
|
typedef Tp& reference;
|
||||||
ExplicitNodeIterator() :
|
ExplicitNodeIterator() :
|
||||||
element(NULL) {
|
element(NULL) {
|
||||||
}
|
}
|
||||||
ExplicitNodeIterator(_Node* node) :
|
ExplicitNodeIterator(_Node* node) :
|
||||||
element(node) {
|
element(node) {
|
||||||
}
|
}
|
||||||
BinaryNode<Tp>* element;
|
BinaryNode<Tp>* element;
|
||||||
_Self up() {
|
_Self up() {
|
||||||
return _Self(element->parent);
|
return _Self(element->parent);
|
||||||
}
|
}
|
||||||
_Self left() {
|
_Self left() {
|
||||||
if (element != NULL) {
|
if (element != NULL) {
|
||||||
return _Self(element->left);
|
return _Self(element->left);
|
||||||
} else {
|
} else {
|
||||||
return _Self(NULL);
|
return _Self(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
_Self right() {
|
_Self right() {
|
||||||
if (element != NULL) {
|
if (element != NULL) {
|
||||||
return _Self(element->right);
|
return _Self(element->right);
|
||||||
} else {
|
} else {
|
||||||
return _Self(NULL);
|
return _Self(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
bool operator==(const _Self& __x) const {
|
bool operator==(const _Self& __x) const {
|
||||||
return element == __x.element;
|
return element == __x.element;
|
||||||
}
|
}
|
||||||
bool operator!=(const _Self& __x) const {
|
bool operator!=(const _Self& __x) const {
|
||||||
return element != __x.element;
|
return element != __x.element;
|
||||||
}
|
}
|
||||||
pointer
|
pointer
|
||||||
operator->() const {
|
operator->() const {
|
||||||
if (element != NULL) {
|
if (element != NULL) {
|
||||||
return element->value;
|
return element->value;
|
||||||
} else {
|
} else {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pointer operator*() const {
|
pointer operator*() const {
|
||||||
return this->operator->();
|
return this->operator->();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -75,77 +75,77 @@ public:
|
|||||||
template<typename Tp>
|
template<typename Tp>
|
||||||
class BinaryTree {
|
class BinaryTree {
|
||||||
public:
|
public:
|
||||||
typedef ExplicitNodeIterator<Tp> iterator;
|
typedef ExplicitNodeIterator<Tp> iterator;
|
||||||
typedef BinaryNode<Tp> Node;
|
typedef BinaryNode<Tp> Node;
|
||||||
typedef std::pair<iterator, iterator> children;
|
typedef std::pair<iterator, iterator> children;
|
||||||
BinaryTree() :
|
BinaryTree() :
|
||||||
rootNode(NULL) {
|
rootNode(NULL) {
|
||||||
}
|
}
|
||||||
BinaryTree(Node* rootNode) :
|
BinaryTree(Node* rootNode) :
|
||||||
rootNode(rootNode) {
|
rootNode(rootNode) {
|
||||||
}
|
}
|
||||||
iterator begin() const {
|
iterator begin() const {
|
||||||
return iterator(rootNode);
|
return iterator(rootNode);
|
||||||
}
|
}
|
||||||
static iterator end() {
|
static iterator end() {
|
||||||
return iterator(NULL);
|
return iterator(NULL);
|
||||||
}
|
}
|
||||||
iterator insert(bool insertLeft, iterator parentNode, Node* newNode ) {
|
iterator insert(bool insertLeft, iterator parentNode, Node* newNode ) {
|
||||||
newNode->parent = parentNode.element;
|
newNode->parent = parentNode.element;
|
||||||
if (parentNode.element != NULL) {
|
if (parentNode.element != NULL) {
|
||||||
if (insertLeft) {
|
if (insertLeft) {
|
||||||
parentNode.element->left = newNode;
|
parentNode.element->left = newNode;
|
||||||
} else {
|
} else {
|
||||||
parentNode.element->right = newNode;
|
parentNode.element->right = newNode;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//Insert first element.
|
//Insert first element.
|
||||||
rootNode = newNode;
|
rootNode = newNode;
|
||||||
}
|
}
|
||||||
return iterator(newNode);
|
return iterator(newNode);
|
||||||
}
|
}
|
||||||
//No recursion to children. Needs to be done externally.
|
//No recursion to children. Needs to be done externally.
|
||||||
children erase(iterator node) {
|
children erase(iterator node) {
|
||||||
if (node.element == rootNode) {
|
if (node.element == rootNode) {
|
||||||
//We're root node
|
//We're root node
|
||||||
rootNode = NULL;
|
rootNode = NULL;
|
||||||
} else {
|
} else {
|
||||||
//Delete parent's reference
|
//Delete parent's reference
|
||||||
if (node.up().left() == node) {
|
if (node.up().left() == node) {
|
||||||
node.up().element->left = NULL;
|
node.up().element->left = NULL;
|
||||||
} else {
|
} else {
|
||||||
node.up().element->right = NULL;
|
node.up().element->right = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return children(node.element->left, node.element->right);
|
return children(node.element->left, node.element->right);
|
||||||
}
|
}
|
||||||
static uint32_t countLeft(iterator start) {
|
static uint32_t countLeft(iterator start) {
|
||||||
if (start == end()) {
|
if (start == end()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
//We also count the start node itself.
|
//We also count the start node itself.
|
||||||
uint32_t count = 1;
|
uint32_t count = 1;
|
||||||
while (start.left() != end()) {
|
while (start.left() != end()) {
|
||||||
count++;
|
count++;
|
||||||
start = start.left();
|
start = start.left();
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
static uint32_t countRight(iterator start) {
|
static uint32_t countRight(iterator start) {
|
||||||
if (start == end()) {
|
if (start == end()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
//We also count the start node itself.
|
//We also count the start node itself.
|
||||||
uint32_t count = 1;
|
uint32_t count = 1;
|
||||||
while (start.right() != end()) {
|
while (start.right() != end()) {
|
||||||
count++;
|
count++;
|
||||||
start = start.right();
|
start = start.right();
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Node* rootNode;
|
Node* rootNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Simple First-In-First-Out data structure. The maximum size
|
* @brief Simple First-In-First-Out data structure. The maximum size
|
||||||
* can be set in the constructor.
|
* can be set in the constructor.
|
||||||
* @details
|
* @details
|
||||||
* The maximum capacity can be determined at run-time, so this container
|
* The maximum capacity can be determined at run-time, so this container
|
||||||
* performs dynamic memory allocation!
|
* performs dynamic memory allocation!
|
||||||
@ -17,39 +17,39 @@
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
class DynamicFIFO: public FIFOBase<T> {
|
class DynamicFIFO: public FIFOBase<T> {
|
||||||
public:
|
public:
|
||||||
DynamicFIFO(size_t maxCapacity): FIFOBase<T>(nullptr, maxCapacity),
|
DynamicFIFO(size_t maxCapacity): FIFOBase<T>(nullptr, maxCapacity),
|
||||||
fifoVector(maxCapacity) {
|
fifoVector(maxCapacity) {
|
||||||
// trying to pass the pointer of the uninitialized vector
|
// trying to pass the pointer of the uninitialized vector
|
||||||
// to the FIFOBase constructor directly lead to a super evil bug.
|
// to the FIFOBase constructor directly lead to a super evil bug.
|
||||||
// So we do it like this now.
|
// So we do it like this now.
|
||||||
this->setContainer(fifoVector.data());
|
this->setContainer(fifoVector.data());
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Custom copy constructor which prevents setting the
|
* @brief Custom copy constructor which prevents setting the
|
||||||
* underlying pointer wrong. This function allocates memory!
|
* underlying pointer wrong. This function allocates memory!
|
||||||
* @details This is a very heavy operation so try to avoid this!
|
* @details This is a very heavy operation so try to avoid this!
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
DynamicFIFO(const DynamicFIFO& other): FIFOBase<T>(other),
|
DynamicFIFO(const DynamicFIFO& other): FIFOBase<T>(other),
|
||||||
fifoVector(other.maxCapacity) {
|
fifoVector(other.maxCapacity) {
|
||||||
this->fifoVector = other.fifoVector;
|
this->fifoVector = other.fifoVector;
|
||||||
this->setContainer(fifoVector.data());
|
this->setContainer(fifoVector.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Custom assignment operator
|
* @brief Custom assignment operator
|
||||||
* @details This is a very heavy operation so try to avoid this!
|
* @details This is a very heavy operation so try to avoid this!
|
||||||
* @param other DyamicFIFO to copy from
|
* @param other DyamicFIFO to copy from
|
||||||
*/
|
*/
|
||||||
DynamicFIFO& operator=(const DynamicFIFO& other){
|
DynamicFIFO& operator=(const DynamicFIFO& other){
|
||||||
FIFOBase<T>::operator=(other);
|
FIFOBase<T>::operator=(other);
|
||||||
this->fifoVector = other.fifoVector;
|
this->fifoVector = other.fifoVector;
|
||||||
this->setContainer(fifoVector.data());
|
this->setContainer(fifoVector.data());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
std::vector<T> fifoVector;
|
std::vector<T> fifoVector;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_CONTAINER_DYNAMICFIFO_H_ */
|
#endif /* FSFW_CONTAINER_DYNAMICFIFO_H_ */
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Simple First-In-First-Out data structure with size fixed at
|
* @brief Simple First-In-First-Out data structure with size fixed at
|
||||||
* compile time
|
* compile time
|
||||||
* @details
|
* @details
|
||||||
* Performs no dynamic memory allocation.
|
* Performs no dynamic memory allocation.
|
||||||
* The public interface of FIFOBase exposes the user interface for the FIFO.
|
* The public interface of FIFOBase exposes the user interface for the FIFO.
|
||||||
@ -16,32 +16,32 @@
|
|||||||
template<typename T, size_t capacity>
|
template<typename T, size_t capacity>
|
||||||
class FIFO: public FIFOBase<T> {
|
class FIFO: public FIFOBase<T> {
|
||||||
public:
|
public:
|
||||||
FIFO(): FIFOBase<T>(nullptr, capacity) {
|
FIFO(): FIFOBase<T>(nullptr, capacity) {
|
||||||
this->setContainer(fifoArray.data());
|
this->setContainer(fifoArray.data());
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Custom copy constructor to set pointer correctly.
|
* @brief Custom copy constructor to set pointer correctly.
|
||||||
* @param other
|
* @param other
|
||||||
*/
|
*/
|
||||||
FIFO(const FIFO& other): FIFOBase<T>(other) {
|
FIFO(const FIFO& other): FIFOBase<T>(other) {
|
||||||
this->fifoArray = other.fifoArray;
|
this->fifoArray = other.fifoArray;
|
||||||
this->setContainer(fifoArray.data());
|
this->setContainer(fifoArray.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Custom assignment operator
|
* @brief Custom assignment operator
|
||||||
* @param other
|
* @param other
|
||||||
*/
|
*/
|
||||||
FIFO& operator=(const FIFO& other){
|
FIFO& operator=(const FIFO& other){
|
||||||
FIFOBase<T>::operator=(other);
|
FIFOBase<T>::operator=(other);
|
||||||
this->fifoArray = other.fifoArray;
|
this->fifoArray = other.fifoArray;
|
||||||
this->setContainer(fifoArray.data());
|
this->setContainer(fifoArray.data());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::array<T, capacity> fifoArray;
|
std::array<T, capacity> fifoArray;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_CONTAINER_FIFO_H_ */
|
#endif /* FSFW_CONTAINER_FIFO_H_ */
|
||||||
|
@ -8,70 +8,70 @@
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
class FIFOBase {
|
class FIFOBase {
|
||||||
public:
|
public:
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::FIFO_CLASS;
|
static const uint8_t INTERFACE_ID = CLASS_ID::FIFO_CLASS;
|
||||||
static const ReturnValue_t FULL = MAKE_RETURN_CODE(1);
|
static const ReturnValue_t FULL = MAKE_RETURN_CODE(1);
|
||||||
static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(2);
|
static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(2);
|
||||||
|
|
||||||
/** Default ctor, takes pointer to first entry of underlying container
|
/** Default ctor, takes pointer to first entry of underlying container
|
||||||
* and maximum capacity */
|
* and maximum capacity */
|
||||||
FIFOBase(T* values, const size_t maxCapacity);
|
FIFOBase(T* values, const size_t maxCapacity);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert value into FIFO
|
* Insert value into FIFO
|
||||||
* @param value
|
* @param value
|
||||||
* @return RETURN_OK on success, FULL if full
|
* @return RETURN_OK on success, FULL if full
|
||||||
*/
|
*/
|
||||||
ReturnValue_t insert(T value);
|
ReturnValue_t insert(T value);
|
||||||
/**
|
/**
|
||||||
* Retrieve item from FIFO. This removes the item from the FIFO.
|
* Retrieve item from FIFO. This removes the item from the FIFO.
|
||||||
* @param value Must point to a valid T
|
* @param value Must point to a valid T
|
||||||
* @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed
|
* @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed
|
||||||
*/
|
*/
|
||||||
ReturnValue_t retrieve(T *value);
|
ReturnValue_t retrieve(T *value);
|
||||||
/**
|
/**
|
||||||
* Retrieve item from FIFO without removing it from FIFO.
|
* Retrieve item from FIFO without removing it from FIFO.
|
||||||
* @param value Must point to a valid T
|
* @param value Must point to a valid T
|
||||||
* @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed
|
* @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed
|
||||||
*/
|
*/
|
||||||
ReturnValue_t peek(T * value);
|
ReturnValue_t peek(T * value);
|
||||||
/**
|
/**
|
||||||
* Remove item from FIFO.
|
* Remove item from FIFO.
|
||||||
* @return RETURN_OK on success, EMPTY if empty
|
* @return RETURN_OK on success, EMPTY if empty
|
||||||
*/
|
*/
|
||||||
ReturnValue_t pop();
|
ReturnValue_t pop();
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Check if FIFO is empty
|
* Check if FIFO is empty
|
||||||
* @return True if empty, False if not
|
* @return True if empty, False if not
|
||||||
*/
|
*/
|
||||||
bool empty();
|
bool empty();
|
||||||
/***
|
/***
|
||||||
* Check if FIFO is Full
|
* Check if FIFO is Full
|
||||||
* @return True if full, False if not
|
* @return True if full, False if not
|
||||||
*/
|
*/
|
||||||
bool full();
|
bool full();
|
||||||
/***
|
/***
|
||||||
* Current used size (elements) used
|
* Current used size (elements) used
|
||||||
* @return size_t in elements
|
* @return size_t in elements
|
||||||
*/
|
*/
|
||||||
size_t size();
|
size_t size();
|
||||||
/***
|
/***
|
||||||
* Get maximal capacity of fifo
|
* Get maximal capacity of fifo
|
||||||
* @return size_t with max capacity of this fifo
|
* @return size_t with max capacity of this fifo
|
||||||
*/
|
*/
|
||||||
size_t getMaxCapacity() const;
|
size_t getMaxCapacity() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setContainer(T* data);
|
void setContainer(T* data);
|
||||||
size_t maxCapacity = 0;
|
size_t maxCapacity = 0;
|
||||||
|
|
||||||
T* values;
|
T* values;
|
||||||
|
|
||||||
size_t readIndex = 0;
|
size_t readIndex = 0;
|
||||||
size_t writeIndex = 0;
|
size_t writeIndex = 0;
|
||||||
size_t currentSize = 0;
|
size_t currentSize = 0;
|
||||||
|
|
||||||
size_t next(size_t current);
|
size_t next(size_t current);
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "FIFOBase.tpp"
|
#include "FIFOBase.tpp"
|
||||||
|
@ -7,87 +7,87 @@
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline FIFOBase<T>::FIFOBase(T* values, const size_t maxCapacity):
|
inline FIFOBase<T>::FIFOBase(T* values, const size_t maxCapacity):
|
||||||
maxCapacity(maxCapacity), values(values){};
|
maxCapacity(maxCapacity), values(values){};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline ReturnValue_t FIFOBase<T>::insert(T value) {
|
inline ReturnValue_t FIFOBase<T>::insert(T value) {
|
||||||
if (full()) {
|
if (full()) {
|
||||||
return FULL;
|
return FULL;
|
||||||
} else {
|
} else {
|
||||||
values[writeIndex] = value;
|
values[writeIndex] = value;
|
||||||
writeIndex = next(writeIndex);
|
writeIndex = next(writeIndex);
|
||||||
++currentSize;
|
++currentSize;
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline ReturnValue_t FIFOBase<T>::retrieve(T* value) {
|
inline ReturnValue_t FIFOBase<T>::retrieve(T* value) {
|
||||||
if (empty()) {
|
if (empty()) {
|
||||||
return EMPTY;
|
return EMPTY;
|
||||||
} else {
|
} else {
|
||||||
if (value == nullptr){
|
if (value == nullptr){
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
*value = values[readIndex];
|
*value = values[readIndex];
|
||||||
readIndex = next(readIndex);
|
readIndex = next(readIndex);
|
||||||
--currentSize;
|
--currentSize;
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline ReturnValue_t FIFOBase<T>::peek(T* value) {
|
inline ReturnValue_t FIFOBase<T>::peek(T* value) {
|
||||||
if(empty()) {
|
if(empty()) {
|
||||||
return EMPTY;
|
return EMPTY;
|
||||||
} else {
|
} else {
|
||||||
if (value == nullptr){
|
if (value == nullptr){
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
*value = values[readIndex];
|
*value = values[readIndex];
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline ReturnValue_t FIFOBase<T>::pop() {
|
inline ReturnValue_t FIFOBase<T>::pop() {
|
||||||
T value;
|
T value;
|
||||||
return this->retrieve(&value);
|
return this->retrieve(&value);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline bool FIFOBase<T>::empty() {
|
inline bool FIFOBase<T>::empty() {
|
||||||
return (currentSize == 0);
|
return (currentSize == 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline bool FIFOBase<T>::full() {
|
inline bool FIFOBase<T>::full() {
|
||||||
return (currentSize == maxCapacity);
|
return (currentSize == maxCapacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline size_t FIFOBase<T>::size() {
|
inline size_t FIFOBase<T>::size() {
|
||||||
return currentSize;
|
return currentSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline size_t FIFOBase<T>::next(size_t current) {
|
inline size_t FIFOBase<T>::next(size_t current) {
|
||||||
++current;
|
++current;
|
||||||
if (current == maxCapacity) {
|
if (current == maxCapacity) {
|
||||||
current = 0;
|
current = 0;
|
||||||
}
|
}
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline size_t FIFOBase<T>::getMaxCapacity() const {
|
inline size_t FIFOBase<T>::getMaxCapacity() const {
|
||||||
return maxCapacity;
|
return maxCapacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline void FIFOBase<T>::setContainer(T *data) {
|
inline void FIFOBase<T>::setContainer(T *data) {
|
||||||
this->values = data;
|
this->values = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -8,30 +8,30 @@
|
|||||||
*/
|
*/
|
||||||
template<typename T, size_t MAX_SIZE, typename count_t = uint8_t>
|
template<typename T, size_t MAX_SIZE, typename count_t = uint8_t>
|
||||||
class FixedArrayList: public ArrayList<T, count_t> {
|
class FixedArrayList: public ArrayList<T, count_t> {
|
||||||
static_assert(MAX_SIZE <= (pow(2,sizeof(count_t)*8)-1), "count_t is not large enough to hold MAX_SIZE");
|
static_assert(MAX_SIZE <= (pow(2,sizeof(count_t)*8)-1), "count_t is not large enough to hold MAX_SIZE");
|
||||||
private:
|
private:
|
||||||
T data[MAX_SIZE];
|
T data[MAX_SIZE];
|
||||||
public:
|
public:
|
||||||
FixedArrayList() :
|
FixedArrayList() :
|
||||||
ArrayList<T, count_t>(data, MAX_SIZE) {
|
ArrayList<T, count_t>(data, MAX_SIZE) {
|
||||||
}
|
}
|
||||||
|
|
||||||
FixedArrayList(const FixedArrayList& other) :
|
FixedArrayList(const FixedArrayList& other) :
|
||||||
ArrayList<T, count_t>(data, MAX_SIZE) {
|
ArrayList<T, count_t>(data, MAX_SIZE) {
|
||||||
memcpy(this->data, other.data, sizeof(this->data));
|
memcpy(this->data, other.data, sizeof(this->data));
|
||||||
this->entries = data;
|
this->entries = data;
|
||||||
this->size = other.size;
|
this->size = other.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
FixedArrayList& operator=(FixedArrayList other) {
|
FixedArrayList& operator=(FixedArrayList other) {
|
||||||
memcpy(this->data, other.data, sizeof(this->data));
|
memcpy(this->data, other.data, sizeof(this->data));
|
||||||
this->entries = data;
|
this->entries = data;
|
||||||
this->size = other.size;
|
this->size = other.size;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~FixedArrayList() {
|
virtual ~FixedArrayList() {
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,212 +18,212 @@
|
|||||||
*/
|
*/
|
||||||
template<typename key_t, typename T>
|
template<typename key_t, typename T>
|
||||||
class FixedMap: public SerializeIF {
|
class FixedMap: public SerializeIF {
|
||||||
static_assert (std::is_trivially_copyable<T>::value or
|
static_assert (std::is_trivially_copyable<T>::value or
|
||||||
std::is_base_of<SerializeIF, T>::value,
|
std::is_base_of<SerializeIF, T>::value,
|
||||||
"Types used in FixedMap must either be trivial copy-able or a "
|
"Types used in FixedMap must either be trivial copy-able or a "
|
||||||
"derived class from SerializeIF to be serialize-able");
|
"derived class from SerializeIF to be serialize-able");
|
||||||
public:
|
public:
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP;
|
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP;
|
||||||
static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01);
|
static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01);
|
||||||
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02);
|
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02);
|
||||||
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);
|
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const key_t EMPTY_SLOT = -1;
|
static const key_t EMPTY_SLOT = -1;
|
||||||
ArrayList<std::pair<key_t, T>, uint32_t> theMap;
|
ArrayList<std::pair<key_t, T>, uint32_t> theMap;
|
||||||
uint32_t _size;
|
uint32_t _size;
|
||||||
|
|
||||||
uint32_t findIndex(key_t key) const {
|
uint32_t findIndex(key_t key) const {
|
||||||
if (_size == 0) {
|
if (_size == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
for (i = 0; i < _size; ++i) {
|
for (i = 0; i < _size; ++i) {
|
||||||
if (theMap[i].first == key) {
|
if (theMap[i].first == key) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
FixedMap(uint32_t maxSize) :
|
FixedMap(uint32_t maxSize) :
|
||||||
theMap(maxSize), _size(0) {
|
theMap(maxSize), _size(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
class Iterator: public ArrayList<std::pair<key_t, T>, uint32_t>::Iterator {
|
class Iterator: public ArrayList<std::pair<key_t, T>, uint32_t>::Iterator {
|
||||||
public:
|
public:
|
||||||
Iterator() :
|
Iterator() :
|
||||||
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator() {
|
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator(std::pair<key_t, T> *pair) :
|
Iterator(std::pair<key_t, T> *pair) :
|
||||||
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator(pair) {
|
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator(pair) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
friend bool operator==(const typename FixedMap::Iterator& lhs,
|
friend bool operator==(const typename FixedMap::Iterator& lhs,
|
||||||
const typename FixedMap::Iterator& rhs) {
|
const typename FixedMap::Iterator& rhs) {
|
||||||
return (lhs.value == rhs.value);
|
return (lhs.value == rhs.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator!=(const typename FixedMap::Iterator& lhs,
|
friend bool operator!=(const typename FixedMap::Iterator& lhs,
|
||||||
const typename FixedMap::Iterator& rhs) {
|
const typename FixedMap::Iterator& rhs) {
|
||||||
return not (lhs.value == rhs.value);
|
return not (lhs.value == rhs.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator begin() const {
|
Iterator begin() const {
|
||||||
return Iterator(&theMap[0]);
|
return Iterator(&theMap[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator end() const {
|
Iterator end() const {
|
||||||
return Iterator(&theMap[_size]);
|
return Iterator(&theMap[_size]);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t size() const {
|
uint32_t size() const {
|
||||||
return _size;
|
return _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr) {
|
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr) {
|
||||||
if (exists(key) == HasReturnvaluesIF::RETURN_OK) {
|
if (exists(key) == HasReturnvaluesIF::RETURN_OK) {
|
||||||
return KEY_ALREADY_EXISTS;
|
return KEY_ALREADY_EXISTS;
|
||||||
}
|
}
|
||||||
if (_size == theMap.maxSize()) {
|
if (_size == theMap.maxSize()) {
|
||||||
return MAP_FULL;
|
return MAP_FULL;
|
||||||
}
|
}
|
||||||
theMap[_size].first = key;
|
theMap[_size].first = key;
|
||||||
theMap[_size].second = value;
|
theMap[_size].second = value;
|
||||||
if (storedValue != nullptr) {
|
if (storedValue != nullptr) {
|
||||||
*storedValue = Iterator(&theMap[_size]);
|
*storedValue = Iterator(&theMap[_size]);
|
||||||
}
|
}
|
||||||
++_size;
|
++_size;
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t insert(std::pair<key_t, T> pair) {
|
ReturnValue_t insert(std::pair<key_t, T> pair) {
|
||||||
return insert(pair.first, pair.second);
|
return insert(pair.first, pair.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t exists(key_t key) const {
|
ReturnValue_t exists(key_t key) const {
|
||||||
ReturnValue_t result = KEY_DOES_NOT_EXIST;
|
ReturnValue_t result = KEY_DOES_NOT_EXIST;
|
||||||
if (findIndex(key) < _size) {
|
if (findIndex(key) < _size) {
|
||||||
result = HasReturnvaluesIF::RETURN_OK;
|
result = HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t erase(Iterator *iter) {
|
ReturnValue_t erase(Iterator *iter) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
if ((i = findIndex((*iter).value->first)) >= _size) {
|
if ((i = findIndex((*iter).value->first)) >= _size) {
|
||||||
return KEY_DOES_NOT_EXIST;
|
return KEY_DOES_NOT_EXIST;
|
||||||
}
|
}
|
||||||
theMap[i] = theMap[_size - 1];
|
theMap[i] = theMap[_size - 1];
|
||||||
--_size;
|
--_size;
|
||||||
--((*iter).value);
|
--((*iter).value);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t erase(key_t key) {
|
ReturnValue_t erase(key_t key) {
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
if ((i = findIndex(key)) >= _size) {
|
if ((i = findIndex(key)) >= _size) {
|
||||||
return KEY_DOES_NOT_EXIST;
|
return KEY_DOES_NOT_EXIST;
|
||||||
}
|
}
|
||||||
theMap[i] = theMap[_size - 1];
|
theMap[i] = theMap[_size - 1];
|
||||||
--_size;
|
--_size;
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
T *findValue(key_t key) const {
|
T *findValue(key_t key) const {
|
||||||
return &theMap[findIndex(key)].second;
|
return &theMap[findIndex(key)].second;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator find(key_t key) const {
|
Iterator find(key_t key) const {
|
||||||
ReturnValue_t result = exists(key);
|
ReturnValue_t result = exists(key);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return end();
|
return end();
|
||||||
}
|
}
|
||||||
return Iterator(&theMap[findIndex(key)]);
|
return Iterator(&theMap[findIndex(key)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t find(key_t key, T **value) const {
|
ReturnValue_t find(key_t key, T **value) const {
|
||||||
ReturnValue_t result = exists(key);
|
ReturnValue_t result = exists(key);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
*value = &theMap[findIndex(key)].second;
|
*value = &theMap[findIndex(key)].second;
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool empty() {
|
bool empty() {
|
||||||
if(_size == 0) {
|
if(_size == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool full() {
|
bool full() {
|
||||||
if(_size >= theMap.maxSize()) {
|
if(_size >= theMap.maxSize()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
_size = 0;
|
_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t maxSize() const {
|
uint32_t maxSize() const {
|
||||||
return theMap.maxSize();
|
return theMap.maxSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
size_t maxSize, Endianness streamEndianness) const {
|
||||||
ReturnValue_t result = SerializeAdapter::serialize(&this->_size,
|
ReturnValue_t result = SerializeAdapter::serialize(&this->_size,
|
||||||
buffer, size, maxSize, streamEndianness);
|
buffer, size, maxSize, streamEndianness);
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) {
|
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) {
|
||||||
result = SerializeAdapter::serialize(&theMap[i].first, buffer,
|
result = SerializeAdapter::serialize(&theMap[i].first, buffer,
|
||||||
size, maxSize, streamEndianness);
|
size, maxSize, streamEndianness);
|
||||||
result = SerializeAdapter::serialize(&theMap[i].second, buffer, size,
|
result = SerializeAdapter::serialize(&theMap[i].second, buffer, size,
|
||||||
maxSize, streamEndianness);
|
maxSize, streamEndianness);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual size_t getSerializedSize() const {
|
virtual size_t getSerializedSize() const {
|
||||||
uint32_t printSize = sizeof(_size);
|
uint32_t printSize = sizeof(_size);
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
|
|
||||||
for (i = 0; i < _size; ++i) {
|
for (i = 0; i < _size; ++i) {
|
||||||
printSize += SerializeAdapter::getSerializedSize(
|
printSize += SerializeAdapter::getSerializedSize(
|
||||||
&theMap[i].first);
|
&theMap[i].first);
|
||||||
printSize += SerializeAdapter::getSerializedSize(&theMap[i].second);
|
printSize += SerializeAdapter::getSerializedSize(&theMap[i].second);
|
||||||
}
|
}
|
||||||
|
|
||||||
return printSize;
|
return printSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||||
Endianness streamEndianness) {
|
Endianness streamEndianness) {
|
||||||
ReturnValue_t result = SerializeAdapter::deSerialize(&this->_size,
|
ReturnValue_t result = SerializeAdapter::deSerialize(&this->_size,
|
||||||
buffer, size, streamEndianness);
|
buffer, size, streamEndianness);
|
||||||
if (this->_size > theMap.maxSize()) {
|
if (this->_size > theMap.maxSize()) {
|
||||||
return SerializeIF::TOO_MANY_ELEMENTS;
|
return SerializeIF::TOO_MANY_ELEMENTS;
|
||||||
}
|
}
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) {
|
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) {
|
||||||
result = SerializeAdapter::deSerialize(&theMap[i].first, buffer,
|
result = SerializeAdapter::deSerialize(&theMap[i].first, buffer,
|
||||||
size, streamEndianness);
|
size, streamEndianness);
|
||||||
result = SerializeAdapter::deSerialize(&theMap[i].second, buffer, size,
|
result = SerializeAdapter::deSerialize(&theMap[i].second, buffer, size,
|
||||||
streamEndianness);
|
streamEndianness);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -34,172 +34,172 @@
|
|||||||
template<typename key_t, typename T, typename KEY_COMPARE = std::less<key_t>>
|
template<typename key_t, typename T, typename KEY_COMPARE = std::less<key_t>>
|
||||||
class FixedOrderedMultimap {
|
class FixedOrderedMultimap {
|
||||||
public:
|
public:
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MULTIMAP;
|
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MULTIMAP;
|
||||||
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x01);
|
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x01);
|
||||||
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x02);
|
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x02);
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Constructor which needs a size_t for the maximum allowed size
|
* Constructor which needs a size_t for the maximum allowed size
|
||||||
*
|
*
|
||||||
* Can not be resized during runtime
|
* Can not be resized during runtime
|
||||||
*
|
*
|
||||||
* Allocates memory at construction
|
* Allocates memory at construction
|
||||||
* @param maxSize size_t of Maximum allowed size
|
* @param maxSize size_t of Maximum allowed size
|
||||||
*/
|
*/
|
||||||
FixedOrderedMultimap(size_t maxSize):theMap(maxSize), _size(0){
|
FixedOrderedMultimap(size_t maxSize):theMap(maxSize), _size(0){
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Virtual destructor frees Memory by deleting its member
|
* Virtual destructor frees Memory by deleting its member
|
||||||
*/
|
*/
|
||||||
virtual ~FixedOrderedMultimap() {
|
virtual ~FixedOrderedMultimap() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Special iterator for FixedOrderedMultimap
|
* Special iterator for FixedOrderedMultimap
|
||||||
*/
|
*/
|
||||||
class Iterator: public ArrayList<std::pair<key_t, T>, size_t>::Iterator {
|
class Iterator: public ArrayList<std::pair<key_t, T>, size_t>::Iterator {
|
||||||
public:
|
public:
|
||||||
Iterator() :
|
Iterator() :
|
||||||
ArrayList<std::pair<key_t, T>, size_t>::Iterator() {
|
ArrayList<std::pair<key_t, T>, size_t>::Iterator() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator(std::pair<key_t, T> *pair) :
|
Iterator(std::pair<key_t, T> *pair) :
|
||||||
ArrayList<std::pair<key_t, T>, size_t>::Iterator(pair) {
|
ArrayList<std::pair<key_t, T>, size_t>::Iterator(pair) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Returns an iterator pointing to the first element
|
* Returns an iterator pointing to the first element
|
||||||
* @return Iterator pointing to first element
|
* @return Iterator pointing to first element
|
||||||
*/
|
*/
|
||||||
Iterator begin() const {
|
Iterator begin() const {
|
||||||
return Iterator(&theMap[0]);
|
return Iterator(&theMap[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an iterator pointing to one element past the end
|
* Returns an iterator pointing to one element past the end
|
||||||
* @return Iterator pointing to one element past the end
|
* @return Iterator pointing to one element past the end
|
||||||
*/
|
*/
|
||||||
Iterator end() const {
|
Iterator end() const {
|
||||||
return Iterator(&theMap[_size]);
|
return Iterator(&theMap[_size]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Returns the current size of the map (not maximum size!)
|
* Returns the current size of the map (not maximum size!)
|
||||||
* @return Current size
|
* @return Current size
|
||||||
*/
|
*/
|
||||||
size_t size() const{
|
size_t size() const{
|
||||||
return _size;
|
return _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the map, does not deallocate any memory
|
* Clears the map, does not deallocate any memory
|
||||||
*/
|
*/
|
||||||
void clear(){
|
void clear(){
|
||||||
_size = 0;
|
_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the maximum size of the map
|
* Returns the maximum size of the map
|
||||||
* @return Maximum size of the map
|
* @return Maximum size of the map
|
||||||
*/
|
*/
|
||||||
size_t maxSize() const{
|
size_t maxSize() const{
|
||||||
return theMap.maxSize();
|
return theMap.maxSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Used to insert a key and value separately.
|
* Used to insert a key and value separately.
|
||||||
*
|
*
|
||||||
* @param[in] key Key of the new element
|
* @param[in] key Key of the new element
|
||||||
* @param[in] value Value of the new element
|
* @param[in] value Value of the new element
|
||||||
* @param[in/out] (optional) storedValue On success this points to the new value, otherwise a nullptr
|
* @param[in/out] (optional) storedValue On success this points to the new value, otherwise a nullptr
|
||||||
* @return RETURN_OK if insert was successful, MAP_FULL if no space is available
|
* @return RETURN_OK if insert was successful, MAP_FULL if no space is available
|
||||||
*/
|
*/
|
||||||
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr);
|
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr);
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Used to insert new pair instead of single values
|
* Used to insert new pair instead of single values
|
||||||
*
|
*
|
||||||
* @param pair Pair to be inserted
|
* @param pair Pair to be inserted
|
||||||
* @return RETURN_OK if insert was successful, MAP_FULL if no space is available
|
* @return RETURN_OK if insert was successful, MAP_FULL if no space is available
|
||||||
*/
|
*/
|
||||||
ReturnValue_t insert(std::pair<key_t, T> pair);
|
ReturnValue_t insert(std::pair<key_t, T> pair);
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Can be used to check if a certain key is in the map
|
* Can be used to check if a certain key is in the map
|
||||||
* @param key Key to be checked
|
* @param key Key to be checked
|
||||||
* @return RETURN_OK if the key exists KEY_DOES_NOT_EXIST otherwise
|
* @return RETURN_OK if the key exists KEY_DOES_NOT_EXIST otherwise
|
||||||
*/
|
*/
|
||||||
ReturnValue_t exists(key_t key) const;
|
ReturnValue_t exists(key_t key) const;
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Used to delete the element in the iterator
|
* Used to delete the element in the iterator
|
||||||
*
|
*
|
||||||
* The iterator will point to the element before or begin(),
|
* The iterator will point to the element before or begin(),
|
||||||
* but never to one element in front of the map.
|
* but never to one element in front of the map.
|
||||||
*
|
*
|
||||||
* @warning The iterator needs to be valid and dereferenceable
|
* @warning The iterator needs to be valid and dereferenceable
|
||||||
* @param[in/out] iter Pointer to iterator to the element that needs to be ereased
|
* @param[in/out] iter Pointer to iterator to the element that needs to be ereased
|
||||||
* @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this
|
* @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this
|
||||||
*/
|
*/
|
||||||
ReturnValue_t erase(Iterator *iter);
|
ReturnValue_t erase(Iterator *iter);
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Used to erase by key
|
* Used to erase by key
|
||||||
* @param key Key to be erased
|
* @param key Key to be erased
|
||||||
* @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this
|
* @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this
|
||||||
*/
|
*/
|
||||||
ReturnValue_t erase(key_t key);
|
ReturnValue_t erase(key_t key);
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Find returns the first appearance of the key
|
* Find returns the first appearance of the key
|
||||||
*
|
*
|
||||||
* If the key does not exist, it points to end()
|
* If the key does not exist, it points to end()
|
||||||
*
|
*
|
||||||
* @param key Key to search for
|
* @param key Key to search for
|
||||||
* @return Iterator pointing to the first entry of key
|
* @return Iterator pointing to the first entry of key
|
||||||
*/
|
*/
|
||||||
Iterator find(key_t key) const{
|
Iterator find(key_t key) const{
|
||||||
ReturnValue_t result = exists(key);
|
ReturnValue_t result = exists(key);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return end();
|
return end();
|
||||||
}
|
}
|
||||||
return Iterator(&theMap[findFirstIndex(key)]);
|
return Iterator(&theMap[findFirstIndex(key)]);
|
||||||
};
|
};
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Finds first entry of the given key and returns a
|
* Finds first entry of the given key and returns a
|
||||||
* pointer to the value
|
* pointer to the value
|
||||||
*
|
*
|
||||||
* @param key Key to search for
|
* @param key Key to search for
|
||||||
* @param value Found value
|
* @param value Found value
|
||||||
* @return RETURN_OK if it points to the value,
|
* @return RETURN_OK if it points to the value,
|
||||||
* KEY_DOES_NOT_EXIST if the key is not in the map
|
* KEY_DOES_NOT_EXIST if the key is not in the map
|
||||||
*/
|
*/
|
||||||
ReturnValue_t find(key_t key, T **value) const;
|
ReturnValue_t find(key_t key, T **value) const;
|
||||||
|
|
||||||
friend bool operator==(const typename FixedOrderedMultimap::Iterator& lhs,
|
friend bool operator==(const typename FixedOrderedMultimap::Iterator& lhs,
|
||||||
const typename FixedOrderedMultimap::Iterator& rhs) {
|
const typename FixedOrderedMultimap::Iterator& rhs) {
|
||||||
return (lhs.value == rhs.value);
|
return (lhs.value == rhs.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator!=(const typename FixedOrderedMultimap::Iterator& lhs,
|
friend bool operator!=(const typename FixedOrderedMultimap::Iterator& lhs,
|
||||||
const typename FixedOrderedMultimap::Iterator& rhs) {
|
const typename FixedOrderedMultimap::Iterator& rhs) {
|
||||||
return not (lhs.value == rhs.value);
|
return not (lhs.value == rhs.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef KEY_COMPARE compare;
|
typedef KEY_COMPARE compare;
|
||||||
compare myComp;
|
compare myComp;
|
||||||
ArrayList<std::pair<key_t, T>, size_t> theMap;
|
ArrayList<std::pair<key_t, T>, size_t> theMap;
|
||||||
size_t _size;
|
size_t _size;
|
||||||
|
|
||||||
size_t findFirstIndex(key_t key, size_t startAt = 0) const;
|
size_t findFirstIndex(key_t key, size_t startAt = 0) const;
|
||||||
|
|
||||||
size_t findNicePlace(key_t key) const;
|
size_t findNicePlace(key_t key) const;
|
||||||
|
|
||||||
void removeFromPosition(size_t position);
|
void removeFromPosition(size_t position);
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "FixedOrderedMultimap.tpp"
|
#include "FixedOrderedMultimap.tpp"
|
||||||
|
@ -4,105 +4,105 @@
|
|||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(key_t key, T value, Iterator *storedValue) {
|
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(key_t key, T value, Iterator *storedValue) {
|
||||||
if (_size == theMap.maxSize()) {
|
if (_size == theMap.maxSize()) {
|
||||||
return MAP_FULL;
|
return MAP_FULL;
|
||||||
}
|
}
|
||||||
size_t position = findNicePlace(key);
|
size_t position = findNicePlace(key);
|
||||||
memmove(static_cast<void*>(&theMap[position + 1]),static_cast<void*>(&theMap[position]),
|
memmove(static_cast<void*>(&theMap[position + 1]),static_cast<void*>(&theMap[position]),
|
||||||
(_size - position) * sizeof(std::pair<key_t,T>));
|
(_size - position) * sizeof(std::pair<key_t,T>));
|
||||||
theMap[position].first = key;
|
theMap[position].first = key;
|
||||||
theMap[position].second = value;
|
theMap[position].second = value;
|
||||||
++_size;
|
++_size;
|
||||||
if (storedValue != nullptr) {
|
if (storedValue != nullptr) {
|
||||||
*storedValue = Iterator(&theMap[position]);
|
*storedValue = Iterator(&theMap[position]);
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(std::pair<key_t, T> pair) {
|
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(std::pair<key_t, T> pair) {
|
||||||
return insert(pair.first, pair.second);
|
return insert(pair.first, pair.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::exists(key_t key) const {
|
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::exists(key_t key) const {
|
||||||
ReturnValue_t result = KEY_DOES_NOT_EXIST;
|
ReturnValue_t result = KEY_DOES_NOT_EXIST;
|
||||||
if (findFirstIndex(key) < _size) {
|
if (findFirstIndex(key) < _size) {
|
||||||
result = HasReturnvaluesIF::RETURN_OK;
|
result = HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(Iterator *iter) {
|
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(Iterator *iter) {
|
||||||
size_t i;
|
size_t i;
|
||||||
if ((i = findFirstIndex((*iter).value->first)) >= _size) {
|
if ((i = findFirstIndex((*iter).value->first)) >= _size) {
|
||||||
return KEY_DOES_NOT_EXIST;
|
return KEY_DOES_NOT_EXIST;
|
||||||
}
|
}
|
||||||
removeFromPosition(i);
|
removeFromPosition(i);
|
||||||
if (*iter != begin()) {
|
if (*iter != begin()) {
|
||||||
(*iter)--;
|
(*iter)--;
|
||||||
} else {
|
} else {
|
||||||
*iter = begin();
|
*iter = begin();
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(key_t key) {
|
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(key_t key) {
|
||||||
size_t i;
|
size_t i;
|
||||||
if ((i = findFirstIndex(key)) >= _size) {
|
if ((i = findFirstIndex(key)) >= _size) {
|
||||||
return KEY_DOES_NOT_EXIST;
|
return KEY_DOES_NOT_EXIST;
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
removeFromPosition(i);
|
removeFromPosition(i);
|
||||||
i = findFirstIndex(key, i);
|
i = findFirstIndex(key, i);
|
||||||
} while (i < _size);
|
} while (i < _size);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::find(key_t key, T **value) const {
|
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::find(key_t key, T **value) const {
|
||||||
ReturnValue_t result = exists(key);
|
ReturnValue_t result = exists(key);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
*value = &theMap[findFirstIndex(key)].second;
|
*value = &theMap[findFirstIndex(key)].second;
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findFirstIndex(key_t key, size_t startAt) const {
|
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findFirstIndex(key_t key, size_t startAt) const {
|
||||||
if (startAt >= _size) {
|
if (startAt >= _size) {
|
||||||
return startAt + 1;
|
return startAt + 1;
|
||||||
}
|
}
|
||||||
size_t i = startAt;
|
size_t i = startAt;
|
||||||
for (i = startAt; i < _size; ++i) {
|
for (i = startAt; i < _size; ++i) {
|
||||||
if (theMap[i].first == key) {
|
if (theMap[i].first == key) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findNicePlace(key_t key) const {
|
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findNicePlace(key_t key) const {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
for (i = 0; i < _size; ++i) {
|
for (i = 0; i < _size; ++i) {
|
||||||
if (myComp(key, theMap[i].first)) {
|
if (myComp(key, theMap[i].first)) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename key_t, typename T, typename KEY_COMPARE>
|
template<typename key_t, typename T, typename KEY_COMPARE>
|
||||||
inline void FixedOrderedMultimap<key_t, T, KEY_COMPARE>::removeFromPosition(size_t position) {
|
inline void FixedOrderedMultimap<key_t, T, KEY_COMPARE>::removeFromPosition(size_t position) {
|
||||||
if (_size <= position) {
|
if (_size <= position) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
memmove(static_cast<void*>(&theMap[position]), static_cast<void*>(&theMap[position + 1]),
|
memmove(static_cast<void*>(&theMap[position]), static_cast<void*>(&theMap[position + 1]),
|
||||||
(_size - position - 1) * sizeof(std::pair<key_t,T>));
|
(_size - position - 1) * sizeof(std::pair<key_t,T>));
|
||||||
--_size;
|
--_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,85 +6,85 @@
|
|||||||
|
|
||||||
template<typename T, typename count_t = uint8_t>
|
template<typename T, typename count_t = uint8_t>
|
||||||
class HybridIterator: public LinkedElement<T>::Iterator,
|
class HybridIterator: public LinkedElement<T>::Iterator,
|
||||||
public ArrayList<T, count_t>::Iterator {
|
public ArrayList<T, count_t>::Iterator {
|
||||||
public:
|
public:
|
||||||
HybridIterator() {}
|
HybridIterator() {}
|
||||||
|
|
||||||
HybridIterator(typename LinkedElement<T>::Iterator *iter) :
|
HybridIterator(typename LinkedElement<T>::Iterator *iter) :
|
||||||
LinkedElement<T>::Iterator(*iter), value(iter->value),
|
LinkedElement<T>::Iterator(*iter), value(iter->value),
|
||||||
linked(true) {
|
linked(true) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HybridIterator(LinkedElement<T> *start) :
|
HybridIterator(LinkedElement<T> *start) :
|
||||||
LinkedElement<T>::Iterator(start), value(start->value),
|
LinkedElement<T>::Iterator(start), value(start->value),
|
||||||
linked(true) {
|
linked(true) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HybridIterator(typename ArrayList<T, count_t>::Iterator start,
|
HybridIterator(typename ArrayList<T, count_t>::Iterator start,
|
||||||
typename ArrayList<T, count_t>::Iterator end) :
|
typename ArrayList<T, count_t>::Iterator end) :
|
||||||
ArrayList<T, count_t>::Iterator(start), value(start.value),
|
ArrayList<T, count_t>::Iterator(start), value(start.value),
|
||||||
linked(false), end(end.value) {
|
linked(false), end(end.value) {
|
||||||
if (value == this->end) {
|
if (value == this->end) {
|
||||||
value = NULL;
|
value = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HybridIterator(T *firstElement, T *lastElement) :
|
HybridIterator(T *firstElement, T *lastElement) :
|
||||||
ArrayList<T, count_t>::Iterator(firstElement), value(firstElement),
|
ArrayList<T, count_t>::Iterator(firstElement), value(firstElement),
|
||||||
linked(false), end(++lastElement) {
|
linked(false), end(++lastElement) {
|
||||||
if (value == end) {
|
if (value == end) {
|
||||||
value = NULL;
|
value = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HybridIterator& operator++() {
|
HybridIterator& operator++() {
|
||||||
if (linked) {
|
if (linked) {
|
||||||
LinkedElement<T>::Iterator::operator++();
|
LinkedElement<T>::Iterator::operator++();
|
||||||
if (LinkedElement<T>::Iterator::value != nullptr) {
|
if (LinkedElement<T>::Iterator::value != nullptr) {
|
||||||
value = LinkedElement<T>::Iterator::value->value;
|
value = LinkedElement<T>::Iterator::value->value;
|
||||||
} else {
|
} else {
|
||||||
value = nullptr;
|
value = nullptr;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ArrayList<T, count_t>::Iterator::operator++();
|
ArrayList<T, count_t>::Iterator::operator++();
|
||||||
value = ArrayList<T, count_t>::Iterator::value;
|
value = ArrayList<T, count_t>::Iterator::value;
|
||||||
|
|
||||||
if (value == end) {
|
if (value == end) {
|
||||||
value = nullptr;
|
value = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
HybridIterator operator++(int) {
|
HybridIterator operator++(int) {
|
||||||
HybridIterator tmp(*this);
|
HybridIterator tmp(*this);
|
||||||
operator++();
|
operator++();
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const HybridIterator& other) const {
|
bool operator==(const HybridIterator& other) const {
|
||||||
return value == other.value;
|
return value == other.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const HybridIterator& other) const {
|
bool operator!=(const HybridIterator& other) const {
|
||||||
return !(*this == other);
|
return !(*this == other);
|
||||||
}
|
}
|
||||||
|
|
||||||
T operator*() {
|
T operator*() {
|
||||||
return *value;
|
return *value;
|
||||||
}
|
}
|
||||||
|
|
||||||
T *operator->() {
|
T *operator->() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
T* value = nullptr;
|
T* value = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool linked = false;
|
bool linked = false;
|
||||||
T *end = nullptr;
|
T *end = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_ */
|
#endif /* FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_ */
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -22,50 +22,50 @@
|
|||||||
*/
|
*/
|
||||||
class PlacementFactory {
|
class PlacementFactory {
|
||||||
public:
|
public:
|
||||||
PlacementFactory(StorageManagerIF* backend) :
|
PlacementFactory(StorageManagerIF* backend) :
|
||||||
dataBackend(backend) {
|
dataBackend(backend) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/***
|
/***
|
||||||
* Generates an object of type T in the backend storage.
|
* Generates an object of type T in the backend storage.
|
||||||
*
|
*
|
||||||
* @warning Do not use with any Type that allocates memory internally!
|
* @warning Do not use with any Type that allocates memory internally!
|
||||||
*
|
*
|
||||||
* @tparam T Type of Object
|
* @tparam T Type of Object
|
||||||
* @param args Constructor Arguments to be passed
|
* @param args Constructor Arguments to be passed
|
||||||
* @return A pointer to the new object or a nullptr in case of failure
|
* @return A pointer to the new object or a nullptr in case of failure
|
||||||
*/
|
*/
|
||||||
template<typename T, typename ... Args>
|
template<typename T, typename ... Args>
|
||||||
T* generate(Args&&... args) {
|
T* generate(Args&&... args) {
|
||||||
store_address_t tempId;
|
store_address_t tempId;
|
||||||
uint8_t* pData = nullptr;
|
uint8_t* pData = nullptr;
|
||||||
ReturnValue_t result = dataBackend->getFreeElement(&tempId, sizeof(T),
|
ReturnValue_t result = dataBackend->getFreeElement(&tempId, sizeof(T),
|
||||||
&pData);
|
&pData);
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
T* temp = new (pData) T(std::forward<Args>(args)...);
|
T* temp = new (pData) T(std::forward<Args>(args)...);
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
/***
|
/***
|
||||||
* Function to destroy the object allocated with generate and free space in backend.
|
* Function to destroy the object allocated with generate and free space in backend.
|
||||||
* This must be called by the user.
|
* This must be called by the user.
|
||||||
*
|
*
|
||||||
* @param thisElement Element to be destroyed
|
* @param thisElement Element to be destroyed
|
||||||
* @return RETURN_OK if the element was destroyed, different errors on failure
|
* @return RETURN_OK if the element was destroyed, different errors on failure
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
ReturnValue_t destroy(T* thisElement) {
|
ReturnValue_t destroy(T* thisElement) {
|
||||||
if (thisElement == nullptr){
|
if (thisElement == nullptr){
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
//Need to call destructor first, in case something was allocated by the object (shouldn't do that, however).
|
//Need to call destructor first, in case something was allocated by the object (shouldn't do that, however).
|
||||||
thisElement->~T();
|
thisElement->~T();
|
||||||
uint8_t* pointer = (uint8_t*) (thisElement);
|
uint8_t* pointer = (uint8_t*) (thisElement);
|
||||||
return dataBackend->deleteData(pointer, sizeof(T));
|
return dataBackend->deleteData(pointer, sizeof(T));
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
StorageManagerIF* dataBackend;
|
StorageManagerIF* dataBackend;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_ */
|
#endif /* FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_ */
|
||||||
|
@ -7,107 +7,107 @@
|
|||||||
template<uint8_t N_READ_PTRS = 1>
|
template<uint8_t N_READ_PTRS = 1>
|
||||||
class RingBufferBase {
|
class RingBufferBase {
|
||||||
public:
|
public:
|
||||||
RingBufferBase(size_t startAddress, const size_t size, bool overwriteOld) :
|
RingBufferBase(size_t startAddress, const size_t size, bool overwriteOld) :
|
||||||
start(startAddress), write(startAddress), size(size),
|
start(startAddress), write(startAddress), size(size),
|
||||||
overwriteOld(overwriteOld) {
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~RingBufferBase() {}
|
virtual ~RingBufferBase() {}
|
||||||
|
|
||||||
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 (getAvailableReadData(n) == 0);
|
return (getAvailableReadData(n) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t getAvailableReadData(uint8_t n = 0) const {
|
size_t getAvailableReadData(uint8_t n = 0) const {
|
||||||
return ((write + size) - read[n]) % size;
|
return ((write + size) - read[n]) % size;
|
||||||
}
|
}
|
||||||
size_t availableWriteSpace(uint8_t n = 0) const {
|
size_t availableWriteSpace(uint8_t n = 0) const {
|
||||||
//One less to avoid ambiguous full/empty problem.
|
//One less to avoid ambiguous full/empty problem.
|
||||||
return (((read[n] + size) - write - 1) % size);
|
return (((read[n] + size) - write - 1) % size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool overwritesOld() const {
|
bool overwritesOld() const {
|
||||||
return overwriteOld;
|
return overwriteOld;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t getMaxSize() const {
|
size_t getMaxSize() const {
|
||||||
return size - 1;
|
return size - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t writeTillWrap() {
|
size_t writeTillWrap() {
|
||||||
return (start + size) - write;
|
return (start + size) - write;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t readTillWrap(uint8_t n = 0) {
|
size_t readTillWrap(uint8_t n = 0) {
|
||||||
return (start + size) - read[n];
|
return (start + size) - read[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t getStart() const {
|
size_t getStart() const {
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const size_t start;
|
const size_t start;
|
||||||
size_t write;
|
size_t write;
|
||||||
size_t read[N_READ_PTRS];
|
size_t read[N_READ_PTRS];
|
||||||
const size_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) {
|
ReturnValue_t readData(uint32_t amount, uint8_t n = 0) {
|
||||||
if (getAvailableReadData(n) >= amount) {
|
if (getAvailableReadData(n) >= amount) {
|
||||||
incrementRead(amount, n);
|
incrementRead(amount, n);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
} else {
|
} else {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t writeData(uint32_t amount) {
|
ReturnValue_t writeData(uint32_t amount) {
|
||||||
if (availableWriteSpace() >= amount or overwriteOld) {
|
if (availableWriteSpace() >= amount or overwriteOld) {
|
||||||
incrementWrite(amount);
|
incrementWrite(amount);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
} else {
|
} else {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t getRead(uint8_t n = 0) const {
|
size_t getRead(uint8_t n = 0) const {
|
||||||
return read[n];
|
return read[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
void setRead(uint32_t read, uint8_t n = 0) {
|
void setRead(uint32_t read, uint8_t n = 0) {
|
||||||
if (read >= start && read < (start+size)) {
|
if (read >= start && read < (start+size)) {
|
||||||
this->read[n] = read;
|
this->read[n] = read;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getWrite() const {
|
uint32_t getWrite() const {
|
||||||
return write;
|
return write;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setWrite(uint32_t write) {
|
void setWrite(uint32_t write) {
|
||||||
this->write = write;
|
this->write = write;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_CONTAINER_RINGBUFFERBASE_H_ */
|
#endif /* FSFW_CONTAINER_RINGBUFFERBASE_H_ */
|
||||||
|
@ -3,23 +3,23 @@
|
|||||||
#include "../ipc/MutexHelper.h"
|
#include "../ipc/MutexHelper.h"
|
||||||
|
|
||||||
SharedRingBuffer::SharedRingBuffer(object_id_t objectId, const size_t size,
|
SharedRingBuffer::SharedRingBuffer(object_id_t objectId, const size_t size,
|
||||||
bool overwriteOld, size_t maxExcessBytes):
|
bool overwriteOld, size_t maxExcessBytes):
|
||||||
SystemObject(objectId), SimpleRingBuffer(size, overwriteOld,
|
SystemObject(objectId), SimpleRingBuffer(size, overwriteOld,
|
||||||
maxExcessBytes) {
|
maxExcessBytes) {
|
||||||
mutex = MutexFactory::instance()->createMutex();
|
mutex = MutexFactory::instance()->createMutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer,
|
SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer,
|
||||||
const size_t size, bool overwriteOld, size_t maxExcessBytes):
|
const size_t size, bool overwriteOld, size_t maxExcessBytes):
|
||||||
SystemObject(objectId), SimpleRingBuffer(buffer, size, overwriteOld,
|
SystemObject(objectId), SimpleRingBuffer(buffer, size, overwriteOld,
|
||||||
maxExcessBytes) {
|
maxExcessBytes) {
|
||||||
mutex = MutexFactory::instance()->createMutex();
|
mutex = MutexFactory::instance()->createMutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SharedRingBuffer::setToUseReceiveSizeFIFO(size_t fifoDepth) {
|
void SharedRingBuffer::setToUseReceiveSizeFIFO(size_t fifoDepth) {
|
||||||
this->fifoDepth = fifoDepth;
|
this->fifoDepth = fifoDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t SharedRingBuffer::lockRingBufferMutex(
|
ReturnValue_t SharedRingBuffer::lockRingBufferMutex(
|
||||||
@ -38,20 +38,20 @@ MutexIF* SharedRingBuffer::getMutexHandle() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t SharedRingBuffer::initialize() {
|
ReturnValue_t SharedRingBuffer::initialize() {
|
||||||
if(fifoDepth > 0) {
|
if(fifoDepth > 0) {
|
||||||
receiveSizesFIFO = new DynamicFIFO<size_t>(fifoDepth);
|
receiveSizesFIFO = new DynamicFIFO<size_t>(fifoDepth);
|
||||||
}
|
}
|
||||||
return SystemObject::initialize();
|
return SystemObject::initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicFIFO<size_t>* SharedRingBuffer::getReceiveSizesFIFO() {
|
DynamicFIFO<size_t>* SharedRingBuffer::getReceiveSizesFIFO() {
|
||||||
if(receiveSizesFIFO == nullptr) {
|
if(receiveSizesFIFO == nullptr) {
|
||||||
// Configuration error.
|
// Configuration error.
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "SharedRingBuffer::getReceiveSizesFIFO: Ring buffer"
|
sif::warning << "SharedRingBuffer::getReceiveSizesFIFO: Ring buffer"
|
||||||
<< " was not configured to have sizes FIFO, returning nullptr!"
|
<< " was not configured to have sizes FIFO, returning nullptr!"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return receiveSizesFIFO;
|
return receiveSizesFIFO;
|
||||||
}
|
}
|
||||||
|
@ -15,76 +15,76 @@
|
|||||||
* and unlock operations.
|
* and unlock operations.
|
||||||
*/
|
*/
|
||||||
class SharedRingBuffer: public SystemObject,
|
class SharedRingBuffer: public SystemObject,
|
||||||
public SimpleRingBuffer {
|
public SimpleRingBuffer {
|
||||||
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 operartion, the oldest data
|
* If the ring buffer is overflowing at a write operartion, the oldest data
|
||||||
* will be overwritten.
|
* will be overwritten.
|
||||||
*/
|
*/
|
||||||
SharedRingBuffer(object_id_t objectId, const size_t size,
|
SharedRingBuffer(object_id_t objectId, const size_t size,
|
||||||
bool overwriteOld, size_t maxExcessBytes);
|
bool overwriteOld, size_t maxExcessBytes);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This function can be used to add an optional FIFO to the class
|
* @brief This function can be used to add an optional FIFO to the class
|
||||||
* @details
|
* @details
|
||||||
* This FIFO will be allocated in the initialize function (and will
|
* This FIFO will be allocated in the initialize function (and will
|
||||||
* have a fixed maximum size after that). It can be used to store
|
* have a fixed maximum size after that). It can be used to store
|
||||||
* values like packet sizes, for example for a shared ring buffer
|
* values like packet sizes, for example for a shared ring buffer
|
||||||
* used by producer/consumer tasks.
|
* used by producer/consumer tasks.
|
||||||
*/
|
*/
|
||||||
void setToUseReceiveSizeFIFO(size_t fifoDepth);
|
void setToUseReceiveSizeFIFO(size_t fifoDepth);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
* If the ring buffer is overflowing at a write operartion, the oldest data
|
||||||
* will be overwritten.
|
* will be overwritten.
|
||||||
*/
|
*/
|
||||||
SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const size_t size,
|
SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const size_t size,
|
||||||
bool overwriteOld, size_t maxExcessBytes);
|
bool overwriteOld, size_t maxExcessBytes);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unless a read-only constant value is read, all operations on the
|
* Unless a read-only constant value is read, all operations on the
|
||||||
* shared ring buffer should be protected by calling this function.
|
* shared ring buffer should be protected by calling this function.
|
||||||
* @param timeoutType
|
* @param timeoutType
|
||||||
* @param timeout
|
* @param timeout
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t lockRingBufferMutex(MutexIF::TimeoutType timeoutType,
|
virtual ReturnValue_t lockRingBufferMutex(MutexIF::TimeoutType timeoutType,
|
||||||
dur_millis_t timeout);
|
dur_millis_t timeout);
|
||||||
/**
|
/**
|
||||||
* Any locked mutex also has to be unlocked, otherwise, access to the
|
* Any locked mutex also has to be unlocked, otherwise, access to the
|
||||||
* shared ring buffer will be blocked.
|
* shared ring buffer will be blocked.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t unlockRingBufferMutex();
|
virtual ReturnValue_t unlockRingBufferMutex();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The mutex handle can be accessed directly, for example to perform
|
* The mutex handle can be accessed directly, for example to perform
|
||||||
* the lock with the #MutexHelper for a RAII compliant lock operation.
|
* the lock with the #MutexHelper for a RAII compliant lock operation.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
MutexIF* getMutexHandle() const;
|
MutexIF* getMutexHandle() const;
|
||||||
|
|
||||||
ReturnValue_t initialize() override;
|
ReturnValue_t initialize() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the shared ring buffer was configured to have a sizes FIFO, a handle
|
* If the shared ring buffer was configured to have a sizes FIFO, a handle
|
||||||
* to that FIFO can be retrieved with this function.
|
* to that FIFO can be retrieved with this function.
|
||||||
* Do not forget to protect access with a lock if required!
|
* Do not forget to protect access with a lock if required!
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
DynamicFIFO<size_t>* getReceiveSizesFIFO();
|
DynamicFIFO<size_t>* getReceiveSizesFIFO();
|
||||||
private:
|
private:
|
||||||
MutexIF* mutex = nullptr;
|
MutexIF* mutex = nullptr;
|
||||||
|
|
||||||
size_t fifoDepth = 0;
|
size_t fifoDepth = 0;
|
||||||
DynamicFIFO<size_t>* receiveSizesFIFO = nullptr;
|
DynamicFIFO<size_t>* receiveSizesFIFO = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,31 +2,31 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld,
|
SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld,
|
||||||
size_t maxExcessBytes) :
|
size_t maxExcessBytes) :
|
||||||
RingBufferBase<>(0, size, overwriteOld),
|
RingBufferBase<>(0, size, overwriteOld),
|
||||||
maxExcessBytes(maxExcessBytes) {
|
maxExcessBytes(maxExcessBytes) {
|
||||||
if(maxExcessBytes > size) {
|
if(maxExcessBytes > size) {
|
||||||
this->maxExcessBytes = size;
|
this->maxExcessBytes = size;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this->maxExcessBytes = maxExcessBytes;
|
this->maxExcessBytes = maxExcessBytes;
|
||||||
}
|
}
|
||||||
buffer = new uint8_t[size + 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, size_t maxExcessBytes):
|
bool overwriteOld, size_t maxExcessBytes):
|
||||||
RingBufferBase<>(0, size, overwriteOld), buffer(buffer) {
|
RingBufferBase<>(0, size, overwriteOld), buffer(buffer) {
|
||||||
if(maxExcessBytes > size) {
|
if(maxExcessBytes > size) {
|
||||||
this->maxExcessBytes = size;
|
this->maxExcessBytes = size;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this->maxExcessBytes = maxExcessBytes;
|
this->maxExcessBytes = maxExcessBytes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleRingBuffer::~SimpleRingBuffer() {
|
SimpleRingBuffer::~SimpleRingBuffer() {
|
||||||
delete[] buffer;
|
delete[] buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer,
|
ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer,
|
||||||
@ -48,58 +48,58 @@ ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SimpleRingBuffer::confirmBytesWritten(size_t amount) {
|
void SimpleRingBuffer::confirmBytesWritten(size_t amount) {
|
||||||
if(getExcessBytes() > 0) {
|
if(getExcessBytes() > 0) {
|
||||||
moveExcessBytesToStart();
|
moveExcessBytesToStart();
|
||||||
}
|
}
|
||||||
incrementWrite(amount);
|
incrementWrite(amount);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data,
|
ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data,
|
||||||
size_t amount) {
|
size_t amount) {
|
||||||
if (availableWriteSpace() >= amount or overwriteOld) {
|
if (availableWriteSpace() >= amount or overwriteOld) {
|
||||||
size_t amountTillWrap = writeTillWrap();
|
size_t amountTillWrap = writeTillWrap();
|
||||||
if (amountTillWrap >= amount) {
|
if (amountTillWrap >= amount) {
|
||||||
// remaining size in buffer is sufficient to fit full 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);
|
||||||
}
|
}
|
||||||
incrementWrite(amount);
|
incrementWrite(amount);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
} else {
|
} else {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, size_t amount,
|
ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, size_t amount,
|
||||||
bool incrementReadPtr, bool readRemaining, size_t* trueAmount) {
|
bool incrementReadPtr, bool readRemaining, size_t* trueAmount) {
|
||||||
size_t availableData = getAvailableReadData(READ_PTR);
|
size_t availableData = getAvailableReadData(READ_PTR);
|
||||||
size_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.
|
// more data available than amount specified.
|
||||||
amount = availableData;
|
amount = availableData;
|
||||||
} else {
|
} else {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (trueAmount != nullptr) {
|
if (trueAmount != nullptr) {
|
||||||
*trueAmount = amount;
|
*trueAmount = amount;
|
||||||
}
|
}
|
||||||
if (amountTillWrap >= amount) {
|
if (amountTillWrap >= amount) {
|
||||||
memcpy(data, &buffer[read[READ_PTR]], amount);
|
memcpy(data, &buffer[read[READ_PTR]], amount);
|
||||||
} else {
|
} else {
|
||||||
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) {
|
if(incrementReadPtr) {
|
||||||
deleteData(amount, readRemaining);
|
deleteData(amount, readRemaining);
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t SimpleRingBuffer::getExcessBytes() const {
|
size_t SimpleRingBuffer::getExcessBytes() const {
|
||||||
@ -114,18 +114,18 @@ void SimpleRingBuffer::moveExcessBytesToStart() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t SimpleRingBuffer::deleteData(size_t amount,
|
ReturnValue_t SimpleRingBuffer::deleteData(size_t amount,
|
||||||
bool deleteRemaining, size_t* trueAmount) {
|
bool deleteRemaining, size_t* trueAmount) {
|
||||||
size_t availableData = getAvailableReadData(READ_PTR);
|
size_t availableData = getAvailableReadData(READ_PTR);
|
||||||
if (availableData < amount) {
|
if (availableData < amount) {
|
||||||
if (deleteRemaining) {
|
if (deleteRemaining) {
|
||||||
amount = availableData;
|
amount = availableData;
|
||||||
} else {
|
} else {
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (trueAmount != nullptr) {
|
if (trueAmount != nullptr) {
|
||||||
*trueAmount = amount;
|
*trueAmount = amount;
|
||||||
}
|
}
|
||||||
incrementRead(amount, READ_PTR);
|
incrementRead(amount, READ_PTR);
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Circular buffer implementation, useful for buffering
|
* @brief Circular buffer implementation, useful for buffering
|
||||||
* into data streams.
|
* into data streams.
|
||||||
* @details
|
* @details
|
||||||
* Note that the deleteData() has to be called to increment the read pointer.
|
* Note that the deleteData() has to be called to increment the read pointer.
|
||||||
@ -25,104 +25,104 @@ public:
|
|||||||
* with getFreeElement.
|
* with getFreeElement.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
SimpleRingBuffer(const size_t size, bool overwriteOld,
|
SimpleRingBuffer(const size_t size, bool overwriteOld,
|
||||||
size_t maxExcessBytes = 0);
|
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
|
* If the ring buffer is overflowing at a write operartion, the oldest data
|
||||||
* will be overwritten.
|
* will be overwritten.
|
||||||
* @param maxExcessBytes
|
* @param maxExcessBytes
|
||||||
* If the buffer can accomodate additional bytes for contigous write
|
* If the buffer can accomodate additional bytes for contigous write
|
||||||
* operations with getFreeElement, this is the maximum allowed additional
|
* operations with getFreeElement, this is the maximum allowed additional
|
||||||
* size
|
* 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);
|
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
|
* @return -@c RETURN_OK if write operation was successfull
|
||||||
* -@c RETURN_FAILED if
|
* -@c RETURN_FAILED if
|
||||||
*/
|
*/
|
||||||
ReturnValue_t writeData(const uint8_t* data, size_t amount);
|
ReturnValue_t writeData(const uint8_t* data, size_t amount);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a pointer to a free element. If the remaining buffer is
|
* Returns a pointer to a free element. If the remaining buffer is
|
||||||
* not large enough, the data will be written past the actual size
|
* not large enough, the data will be written past the actual size
|
||||||
* and the amount of excess bytes will be cached. This function
|
* and the amount of excess bytes will be cached. This function
|
||||||
* does not increment the write pointer!
|
* does not increment the write pointer!
|
||||||
* @param writePointer Pointer to a pointer which can be used to write
|
* @param writePointer Pointer to a pointer which can be used to write
|
||||||
* contiguous blocks into the ring buffer
|
* contiguous blocks into the ring buffer
|
||||||
* @param amount
|
* @param amount
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t getFreeElement(uint8_t** writePointer, size_t amount);
|
ReturnValue_t getFreeElement(uint8_t** writePointer, size_t amount);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This increments the write pointer and also copies the excess bytes
|
* This increments the write pointer and also copies the excess bytes
|
||||||
* to the beginning. It should be called if the write operation
|
* to the beginning. It should be called if the write operation
|
||||||
* conducted after calling getFreeElement() was performed.
|
* conducted after calling getFreeElement() was performed.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
void confirmBytesWritten(size_t amount);
|
void confirmBytesWritten(size_t amount);
|
||||||
|
|
||||||
virtual size_t getExcessBytes() const;
|
virtual size_t getExcessBytes() const;
|
||||||
/**
|
/**
|
||||||
* Helper functions which moves any excess bytes to the start
|
* Helper functions which moves any excess bytes to the start
|
||||||
* of the ring buffer.
|
* of the ring buffer.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual void moveExcessBytesToStart();
|
virtual void moveExcessBytesToStart();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read from circular buffer at read pointer.
|
* Read from circular buffer at read pointer.
|
||||||
* @param data
|
* @param data
|
||||||
* @param amount
|
* @param amount
|
||||||
* @param incrementReadPtr
|
* @param incrementReadPtr
|
||||||
* If this is set to true, the read pointer will be incremented.
|
* If this is set to true, the read pointer will be incremented.
|
||||||
* If readRemaining is set to true, the read pointer will be incremented
|
* If readRemaining is set to true, the read pointer will be incremented
|
||||||
* accordingly.
|
* accordingly.
|
||||||
* @param readRemaining
|
* @param readRemaining
|
||||||
* If this is set to true, the data will be read even if the amount
|
* If this is set to true, the data will be read even if the amount
|
||||||
* specified exceeds the read data available.
|
* specified exceeds the read data available.
|
||||||
* @param trueAmount [out]
|
* @param trueAmount [out]
|
||||||
* If readRemaining was set to true, the true amount read will be assigned
|
* If readRemaining was set to true, the true amount read will be assigned
|
||||||
* to the passed value.
|
* to the passed value.
|
||||||
* @return
|
* @return
|
||||||
* - @c RETURN_OK if data was read successfully
|
* - @c RETURN_OK if data was read successfully
|
||||||
* - @c RETURN_FAILED if not enough data was available and readRemaining
|
* - @c RETURN_FAILED if not enough data was available and readRemaining
|
||||||
* was set to false.
|
* was set to false.
|
||||||
*/
|
*/
|
||||||
ReturnValue_t readData(uint8_t* data, size_t amount,
|
ReturnValue_t readData(uint8_t* data, size_t amount,
|
||||||
bool incrementReadPtr = false, bool readRemaining = false,
|
bool incrementReadPtr = false, bool readRemaining = false,
|
||||||
size_t* trueAmount = nullptr);
|
size_t* trueAmount = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete data by incrementing read pointer.
|
* Delete data by incrementing read pointer.
|
||||||
* @param amount
|
* @param amount
|
||||||
* @param deleteRemaining
|
* @param deleteRemaining
|
||||||
* If the amount specified is larger than the remaing size to read and this
|
* 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
|
* is set to true, the remaining amount will be deleted as well
|
||||||
* @param trueAmount [out]
|
* @param trueAmount [out]
|
||||||
* If deleteRemaining was set to true, the amount deleted will be assigned
|
* If deleteRemaining was set to true, the amount deleted will be assigned
|
||||||
* to the passed value.
|
* to the passed value.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t deleteData(size_t amount, bool deleteRemaining = false,
|
ReturnValue_t deleteData(size_t amount, bool deleteRemaining = false,
|
||||||
size_t* trueAmount = nullptr);
|
size_t* trueAmount = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
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 maxExcessBytes;
|
||||||
size_t excessBytes = 0;
|
size_t excessBytes = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_CONTAINER_SIMPLERINGBUFFER_H_ */
|
#endif /* FSFW_CONTAINER_SIMPLERINGBUFFER_H_ */
|
||||||
|
@ -5,71 +5,71 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Linked list data structure,
|
* @brief Linked list data structure,
|
||||||
* each entry has a pointer to the next entry (singly)
|
* each entry has a pointer to the next entry (singly)
|
||||||
* @ingroup container
|
* @ingroup container
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class LinkedElement {
|
class LinkedElement {
|
||||||
public:
|
public:
|
||||||
T *value;
|
T *value;
|
||||||
class Iterator {
|
class Iterator {
|
||||||
public:
|
public:
|
||||||
LinkedElement<T> *value = nullptr;
|
LinkedElement<T> *value = nullptr;
|
||||||
Iterator() {}
|
Iterator() {}
|
||||||
|
|
||||||
Iterator(LinkedElement<T> *element) :
|
Iterator(LinkedElement<T> *element) :
|
||||||
value(element) {
|
value(element) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator& operator++() {
|
Iterator& operator++() {
|
||||||
value = value->getNext();
|
value = value->getNext();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator operator++(int) {
|
Iterator operator++(int) {
|
||||||
Iterator tmp(*this);
|
Iterator tmp(*this);
|
||||||
operator++();
|
operator++();
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(Iterator other) {
|
bool operator==(Iterator other) {
|
||||||
return value == other.value;
|
return value == other.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(Iterator other) {
|
bool operator!=(Iterator other) {
|
||||||
return !(*this == other);
|
return !(*this == other);
|
||||||
}
|
}
|
||||||
T *operator->() {
|
T *operator->() {
|
||||||
return value->value;
|
return value->value;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
LinkedElement(T* setElement, LinkedElement<T>* setNext = nullptr):
|
LinkedElement(T* setElement, LinkedElement<T>* setNext = nullptr):
|
||||||
value(setElement), next(setNext) {}
|
value(setElement), next(setNext) {}
|
||||||
|
|
||||||
virtual ~LinkedElement(){}
|
virtual ~LinkedElement(){}
|
||||||
|
|
||||||
virtual LinkedElement* getNext() const {
|
virtual LinkedElement* getNext() const {
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void setNext(LinkedElement* next) {
|
virtual void setNext(LinkedElement* next) {
|
||||||
this->next = next;
|
this->next = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void setEnd() {
|
virtual void setEnd() {
|
||||||
this->next = nullptr;
|
this->next = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
LinkedElement* begin() {
|
LinkedElement* begin() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
LinkedElement* end() {
|
LinkedElement* end() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
LinkedElement *next;
|
LinkedElement *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -77,52 +77,52 @@ class SinglyLinkedList {
|
|||||||
public:
|
public:
|
||||||
using ElementIterator = typename LinkedElement<T>::Iterator;
|
using ElementIterator = typename LinkedElement<T>::Iterator;
|
||||||
|
|
||||||
SinglyLinkedList() {}
|
SinglyLinkedList() {}
|
||||||
|
|
||||||
SinglyLinkedList(ElementIterator start) :
|
SinglyLinkedList(ElementIterator start) :
|
||||||
start(start.value) {}
|
start(start.value) {}
|
||||||
|
|
||||||
SinglyLinkedList(LinkedElement<T>* startElement) :
|
SinglyLinkedList(LinkedElement<T>* startElement) :
|
||||||
start(startElement) {}
|
start(startElement) {}
|
||||||
|
|
||||||
ElementIterator begin() const {
|
ElementIterator begin() const {
|
||||||
return ElementIterator::Iterator(start);
|
return ElementIterator::Iterator(start);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns iterator to nulltr */
|
/** Returns iterator to nulltr */
|
||||||
ElementIterator end() const {
|
ElementIterator end() const {
|
||||||
return ElementIterator::Iterator();
|
return ElementIterator::Iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns last element in singly linked list.
|
* Returns last element in singly linked list.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ElementIterator back() const {
|
ElementIterator back() const {
|
||||||
LinkedElement<T> *element = start;
|
LinkedElement<T> *element = start;
|
||||||
while (element->getNext() != nullptr) {
|
while (element->getNext() != nullptr) {
|
||||||
element = element->getNext();
|
element = element->getNext();
|
||||||
}
|
}
|
||||||
return ElementIterator::Iterator(element);
|
return ElementIterator::Iterator(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t getSize() const {
|
size_t getSize() const {
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
LinkedElement<T> *element = start;
|
LinkedElement<T> *element = start;
|
||||||
while (element != nullptr) {
|
while (element != nullptr) {
|
||||||
size++;
|
size++;
|
||||||
element = element->getNext();
|
element = element->getNext();
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
void setStart(LinkedElement<T>* firstElement) {
|
void setStart(LinkedElement<T>* firstElement) {
|
||||||
start = firstElement;
|
start = firstElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setNext(LinkedElement<T>* currentElement,
|
void setNext(LinkedElement<T>* currentElement,
|
||||||
LinkedElement<T>* nextElement) {
|
LinkedElement<T>* nextElement) {
|
||||||
currentElement->setNext(nextElement);
|
currentElement->setNext(nextElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLast(LinkedElement<T>* lastElement) {
|
void setLast(LinkedElement<T>* lastElement) {
|
||||||
lastElement->setEnd();
|
lastElement->setEnd();
|
||||||
@ -148,7 +148,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
LinkedElement<T> *start = nullptr;
|
LinkedElement<T> *start = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SINGLYLINKEDLIST_H_ */
|
#endif /* SINGLYLINKEDLIST_H_ */
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(${LIB_FSFW_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
ControllerBase.cpp
|
ControllerBase.cpp
|
||||||
)
|
)
|
@ -5,128 +5,128 @@
|
|||||||
#include "../action/HasActionsIF.h"
|
#include "../action/HasActionsIF.h"
|
||||||
|
|
||||||
ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
|
ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
|
||||||
size_t commandQueueDepth) :
|
size_t commandQueueDepth) :
|
||||||
SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF),
|
SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF),
|
||||||
submode(SUBMODE_NONE), modeHelper(this),
|
submode(SUBMODE_NONE), modeHelper(this),
|
||||||
healthHelper(this, setObjectId) {
|
healthHelper(this, setObjectId) {
|
||||||
commandQueue = QueueFactory::instance()->createMessageQueue(
|
commandQueue = QueueFactory::instance()->createMessageQueue(
|
||||||
commandQueueDepth);
|
commandQueueDepth);
|
||||||
}
|
}
|
||||||
|
|
||||||
ControllerBase::~ControllerBase() {
|
ControllerBase::~ControllerBase() {
|
||||||
QueueFactory::instance()->deleteMessageQueue(commandQueue);
|
QueueFactory::instance()->deleteMessageQueue(commandQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t ControllerBase::initialize() {
|
ReturnValue_t ControllerBase::initialize() {
|
||||||
ReturnValue_t result = SystemObject::initialize();
|
ReturnValue_t result = SystemObject::initialize();
|
||||||
if (result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t parentQueue = 0;
|
MessageQueueId_t parentQueue = 0;
|
||||||
if (parentId != objects::NO_OBJECT) {
|
if (parentId != objects::NO_OBJECT) {
|
||||||
SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId);
|
SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId);
|
||||||
if (parent == nullptr) {
|
if (parent == nullptr) {
|
||||||
return RETURN_FAILED;
|
return RETURN_FAILED;
|
||||||
}
|
}
|
||||||
parentQueue = parent->getCommandQueue();
|
parentQueue = parent->getCommandQueue();
|
||||||
|
|
||||||
parent->registerChild(getObjectId());
|
parent->registerChild(getObjectId());
|
||||||
}
|
}
|
||||||
|
|
||||||
result = healthHelper.initialize(parentQueue);
|
result = healthHelper.initialize(parentQueue);
|
||||||
if (result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = modeHelper.initialize(parentQueue);
|
result = modeHelper.initialize(parentQueue);
|
||||||
if (result != RETURN_OK) {
|
if (result != RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageQueueId_t ControllerBase::getCommandQueue() const {
|
MessageQueueId_t ControllerBase::getCommandQueue() const {
|
||||||
return commandQueue->getId();
|
return commandQueue->getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerBase::handleQueue() {
|
void ControllerBase::handleQueue() {
|
||||||
CommandMessage command;
|
CommandMessage command;
|
||||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||||
for (result = commandQueue->receiveMessage(&command);
|
for (result = commandQueue->receiveMessage(&command);
|
||||||
result == RETURN_OK;
|
result == RETURN_OK;
|
||||||
result = commandQueue->receiveMessage(&command)) {
|
result = commandQueue->receiveMessage(&command)) {
|
||||||
|
|
||||||
result = modeHelper.handleModeCommand(&command);
|
result = modeHelper.handleModeCommand(&command);
|
||||||
if (result == RETURN_OK) {
|
if (result == RETURN_OK) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = healthHelper.handleHealthCommand(&command);
|
result = healthHelper.handleHealthCommand(&command);
|
||||||
if (result == RETURN_OK) {
|
if (result == RETURN_OK) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
result = handleCommandMessage(&command);
|
result = handleCommandMessage(&command);
|
||||||
if (result == RETURN_OK) {
|
if (result == RETURN_OK) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
command.setToUnknownCommand();
|
command.setToUnknownCommand();
|
||||||
commandQueue->reply(&command);
|
commandQueue->reply(&command);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerBase::startTransition(Mode_t mode, Submode_t submode) {
|
void ControllerBase::startTransition(Mode_t mode, Submode_t submode) {
|
||||||
changeHK(this->mode, this->submode, false);
|
changeHK(this->mode, this->submode, false);
|
||||||
triggerEvent(CHANGING_MODE, mode, submode);
|
triggerEvent(CHANGING_MODE, mode, submode);
|
||||||
this->mode = mode;
|
this->mode = mode;
|
||||||
this->submode = submode;
|
this->submode = submode;
|
||||||
modeHelper.modeChanged(mode, submode);
|
modeHelper.modeChanged(mode, submode);
|
||||||
modeChanged(mode, submode);
|
modeChanged(mode, submode);
|
||||||
announceMode(false);
|
announceMode(false);
|
||||||
changeHK(this->mode, this->submode, true);
|
changeHK(this->mode, this->submode, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerBase::getMode(Mode_t* mode, Submode_t* submode) {
|
void ControllerBase::getMode(Mode_t* mode, Submode_t* submode) {
|
||||||
*mode = this->mode;
|
*mode = this->mode;
|
||||||
*submode = this->submode;
|
*submode = this->submode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerBase::setToExternalControl() {
|
void ControllerBase::setToExternalControl() {
|
||||||
healthHelper.setHealth(EXTERNAL_CONTROL);
|
healthHelper.setHealth(EXTERNAL_CONTROL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerBase::announceMode(bool recursive) {
|
void ControllerBase::announceMode(bool recursive) {
|
||||||
triggerEvent(MODE_INFO, mode, submode);
|
triggerEvent(MODE_INFO, mode, submode);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
|
ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
|
||||||
handleQueue();
|
handleQueue();
|
||||||
performControlOperation();
|
performControlOperation();
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerBase::modeChanged(Mode_t mode, Submode_t submode) {
|
void ControllerBase::modeChanged(Mode_t mode, Submode_t submode) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t ControllerBase::setHealth(HealthState health) {
|
ReturnValue_t ControllerBase::setHealth(HealthState health) {
|
||||||
switch (health) {
|
switch (health) {
|
||||||
case HEALTHY:
|
case HEALTHY:
|
||||||
case EXTERNAL_CONTROL:
|
case EXTERNAL_CONTROL:
|
||||||
healthHelper.setHealth(health);
|
healthHelper.setHealth(health);
|
||||||
return RETURN_OK;
|
return RETURN_OK;
|
||||||
default:
|
default:
|
||||||
return INVALID_HEALTH_STATE;
|
return INVALID_HEALTH_STATE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HasHealthIF::HealthState ControllerBase::getHealth() {
|
HasHealthIF::HealthState ControllerBase::getHealth() {
|
||||||
return healthHelper.getHealth();
|
return healthHelper.getHealth();
|
||||||
}
|
}
|
||||||
void ControllerBase::setTaskIF(PeriodicTaskIF* task_){
|
void ControllerBase::setTaskIF(PeriodicTaskIF* task_){
|
||||||
executingTask = task_;
|
executingTask = task_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {
|
void ControllerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {
|
||||||
|
@ -17,39 +17,39 @@
|
|||||||
* a mode and a health state. This avoids boilerplate code.
|
* a mode and a health state. This avoids boilerplate code.
|
||||||
*/
|
*/
|
||||||
class ControllerBase: public HasModesIF,
|
class ControllerBase: public HasModesIF,
|
||||||
public HasHealthIF,
|
public HasHealthIF,
|
||||||
public ExecutableObjectIF,
|
public ExecutableObjectIF,
|
||||||
public SystemObject,
|
public SystemObject,
|
||||||
public HasReturnvaluesIF {
|
public HasReturnvaluesIF {
|
||||||
public:
|
public:
|
||||||
static const Mode_t MODE_NORMAL = 2;
|
static const Mode_t MODE_NORMAL = 2;
|
||||||
|
|
||||||
ControllerBase(object_id_t setObjectId, object_id_t parentId,
|
ControllerBase(object_id_t setObjectId, object_id_t parentId,
|
||||||
size_t commandQueueDepth = 3);
|
size_t commandQueueDepth = 3);
|
||||||
virtual ~ControllerBase();
|
virtual ~ControllerBase();
|
||||||
|
|
||||||
/** SystemObject override */
|
/** SystemObject override */
|
||||||
virtual ReturnValue_t initialize() override;
|
virtual ReturnValue_t initialize() override;
|
||||||
|
|
||||||
virtual MessageQueueId_t getCommandQueue() const override;
|
virtual MessageQueueId_t getCommandQueue() const override;
|
||||||
|
|
||||||
/** HasHealthIF overrides */
|
/** HasHealthIF overrides */
|
||||||
virtual ReturnValue_t setHealth(HealthState health) override;
|
virtual ReturnValue_t setHealth(HealthState health) override;
|
||||||
virtual HasHealthIF::HealthState getHealth() override;
|
virtual HasHealthIF::HealthState getHealth() override;
|
||||||
|
|
||||||
/** ExecutableObjectIF overrides */
|
/** ExecutableObjectIF overrides */
|
||||||
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
||||||
virtual void setTaskIF(PeriodicTaskIF* task) override;
|
virtual void setTaskIF(PeriodicTaskIF* task) override;
|
||||||
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implemented by child class. Handle command messages which are not
|
* Implemented by child class. Handle command messages which are not
|
||||||
* mode or health messages.
|
* mode or health messages.
|
||||||
* @param message
|
* @param message
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0;
|
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -60,35 +60,35 @@ protected:
|
|||||||
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
|
||||||
uint32_t *msToReachTheMode) = 0;
|
uint32_t *msToReachTheMode) = 0;
|
||||||
|
|
||||||
const object_id_t parentId;
|
const object_id_t parentId;
|
||||||
|
|
||||||
Mode_t mode;
|
Mode_t mode;
|
||||||
|
|
||||||
Submode_t submode;
|
Submode_t submode;
|
||||||
|
|
||||||
MessageQueueIF* commandQueue = nullptr;
|
MessageQueueIF* commandQueue = nullptr;
|
||||||
|
|
||||||
ModeHelper modeHelper;
|
ModeHelper modeHelper;
|
||||||
|
|
||||||
HealthHelper healthHelper;
|
HealthHelper healthHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pointer to the task which executes this component,
|
* Pointer to the task which executes this component,
|
||||||
* is invalid before setTaskIF was called.
|
* is invalid before setTaskIF was called.
|
||||||
*/
|
*/
|
||||||
PeriodicTaskIF* executingTask = nullptr;
|
PeriodicTaskIF* executingTask = nullptr;
|
||||||
|
|
||||||
/** Handle mode and health messages */
|
/** Handle mode and health messages */
|
||||||
virtual void handleQueue();
|
virtual void handleQueue();
|
||||||
|
|
||||||
/** Mode helpers */
|
/** Mode helpers */
|
||||||
virtual void modeChanged(Mode_t mode, Submode_t submode);
|
virtual void modeChanged(Mode_t mode, Submode_t submode);
|
||||||
virtual void startTransition(Mode_t mode, Submode_t submode);
|
virtual void startTransition(Mode_t mode, Submode_t submode);
|
||||||
virtual void getMode(Mode_t *mode, Submode_t *submode);
|
virtual void getMode(Mode_t *mode, Submode_t *submode);
|
||||||
virtual void setToExternalControl();
|
virtual void setToExternalControl();
|
||||||
virtual void announceMode(bool recursive);
|
virtual void announceMode(bool recursive);
|
||||||
/** HK helpers */
|
/** HK helpers */
|
||||||
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
|
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_CONTROLLER_CONTROLLERBASE_H_ */
|
#endif /* FSFW_CONTROLLER_CONTROLLERBASE_H_ */
|
||||||
|
@ -18,7 +18,7 @@ public:
|
|||||||
* This function is protected because it should only be used by the
|
* This function is protected because it should only be used by the
|
||||||
* class imlementing the interface.
|
* class imlementing the interface.
|
||||||
*/
|
*/
|
||||||
virtual LocalDataPoolManager* getHkManagerHandle() = 0;
|
virtual LocalDataPoolManager* getPoolManagerHandle() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
#include "internal/LocalPoolDataSetAttorney.h"
|
#include "internal/LocalPoolDataSetAttorney.h"
|
||||||
#include "internal/HasLocalDpIFManagerAttorney.h"
|
#include "internal/HasLocalDpIFManagerAttorney.h"
|
||||||
|
|
||||||
#include "../housekeeping/HousekeepingPacketUpdate.h"
|
|
||||||
#include "../housekeeping/HousekeepingSetPacket.h"
|
#include "../housekeeping/HousekeepingSetPacket.h"
|
||||||
|
#include "../housekeeping/HousekeepingSnapshot.h"
|
||||||
#include "../housekeeping/AcceptsHkPacketsIF.h"
|
#include "../housekeeping/AcceptsHkPacketsIF.h"
|
||||||
#include "../timemanager/CCSDSTime.h"
|
#include "../timemanager/CCSDSTime.h"
|
||||||
#include "../ipc/MutexFactory.h"
|
#include "../ipc/MutexFactory.h"
|
||||||
@ -226,7 +226,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
|
|||||||
Clock::getClock_timeval(&now);
|
Clock::getClock_timeval(&now);
|
||||||
CCSDSTime::CDS_short cds;
|
CCSDSTime::CDS_short cds;
|
||||||
CCSDSTime::convertToCcsds(&cds, &now);
|
CCSDSTime::convertToCcsds(&cds, &now);
|
||||||
HousekeepingPacketUpdate updatePacket(reinterpret_cast<uint8_t*>(&cds),
|
HousekeepingSnapshot updatePacket(reinterpret_cast<uint8_t*>(&cds),
|
||||||
sizeof(cds), HasLocalDpIFManagerAttorney::getPoolObjectHandle(owner,
|
sizeof(cds), HasLocalDpIFManagerAttorney::getPoolObjectHandle(owner,
|
||||||
receiver.dataId.localPoolId));
|
receiver.dataId.localPoolId));
|
||||||
|
|
||||||
@ -264,7 +264,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
|
|||||||
Clock::getClock_timeval(&now);
|
Clock::getClock_timeval(&now);
|
||||||
CCSDSTime::CDS_short cds;
|
CCSDSTime::CDS_short cds;
|
||||||
CCSDSTime::convertToCcsds(&cds, &now);
|
CCSDSTime::convertToCcsds(&cds, &now);
|
||||||
HousekeepingPacketUpdate updatePacket(reinterpret_cast<uint8_t*>(&cds),
|
HousekeepingSnapshot updatePacket(reinterpret_cast<uint8_t*>(&cds),
|
||||||
sizeof(cds), HasLocalDpIFManagerAttorney::getDataSetHandle(owner,
|
sizeof(cds), HasLocalDpIFManagerAttorney::getDataSetHandle(owner,
|
||||||
receiver.dataId.sid));
|
receiver.dataId.sid));
|
||||||
|
|
||||||
@ -292,7 +292,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t LocalDataPoolManager::addUpdateToStore(
|
ReturnValue_t LocalDataPoolManager::addUpdateToStore(
|
||||||
HousekeepingPacketUpdate& updatePacket, store_address_t& storeId) {
|
HousekeepingSnapshot& updatePacket, store_address_t& storeId) {
|
||||||
size_t updatePacketSize = updatePacket.getSerializedSize();
|
size_t updatePacketSize = updatePacket.getSerializedSize();
|
||||||
uint8_t *storePtr = nullptr;
|
uint8_t *storePtr = nullptr;
|
||||||
ReturnValue_t result = ipcStore->getFreeElement(&storeId,
|
ReturnValue_t result = ipcStore->getFreeElement(&storeId,
|
||||||
@ -890,7 +890,7 @@ void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
|
|||||||
<< std::dec << std::setfill(' ') << std::endl;
|
<< std::dec << std::setfill(' ') << std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printWarning("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n",
|
sif::printWarning("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n",
|
||||||
owner->getObjectId(), errorPrint);
|
functionName, owner->getObjectId(), errorPrint);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if(outputType == sif::OutputTypes::OUT_ERROR) {
|
else if(outputType == sif::OutputTypes::OUT_ERROR) {
|
||||||
@ -901,11 +901,11 @@ void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
|
|||||||
<< std::dec << std::setfill(' ') << std::endl;
|
<< std::dec << std::setfill(' ') << std::endl;
|
||||||
#else
|
#else
|
||||||
sif::printError("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n",
|
sif::printError("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n",
|
||||||
owner->getObjectId(), errorPrint);
|
functionName, owner->getObjectId(), errorPrint);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalDataPoolManager* LocalDataPoolManager::getHkManagerHandle() {
|
LocalDataPoolManager* LocalDataPoolManager::getPoolManagerHandle() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ void setStaticFrameworkObjectIds();
|
|||||||
}
|
}
|
||||||
|
|
||||||
class LocalPoolDataSetBase;
|
class LocalPoolDataSetBase;
|
||||||
class HousekeepingPacketUpdate;
|
class HousekeepingSnapshot;
|
||||||
class HasLocalDataPoolIF;
|
class HasLocalDataPoolIF;
|
||||||
class LocalDataPool;
|
class LocalDataPool;
|
||||||
|
|
||||||
@ -52,17 +52,17 @@ class LocalDataPool;
|
|||||||
* Each pool entry has a valid state too.
|
* Each pool entry has a valid state too.
|
||||||
* @author R. Mueller
|
* @author R. Mueller
|
||||||
*/
|
*/
|
||||||
class LocalDataPoolManager: public ProvidesDataPoolSubscriptionIF,
|
class LocalDataPoolManager:
|
||||||
public AccessPoolManagerIF {
|
public ProvidesDataPoolSubscriptionIF,
|
||||||
friend void (Factory::setStaticFrameworkObjectIds)();
|
public AccessPoolManagerIF {
|
||||||
//! Some classes using the pool manager directly need to access class internals of the
|
friend void (Factory::setStaticFrameworkObjectIds)();
|
||||||
//! manager. The attorney provides granular control of access to these internals.
|
//! Some classes using the pool manager directly need to access class internals of the
|
||||||
friend class LocalDpManagerAttorney;
|
//! manager. The attorney provides granular control of access to these internals.
|
||||||
|
friend class LocalDpManagerAttorney;
|
||||||
public:
|
public:
|
||||||
static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING_MANAGER;
|
static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING_MANAGER;
|
||||||
|
|
||||||
static constexpr ReturnValue_t QUEUE_OR_DESTINATION_INVALID = MAKE_RETURN_CODE(0);
|
static constexpr ReturnValue_t QUEUE_OR_DESTINATION_INVALID = MAKE_RETURN_CODE(0);
|
||||||
|
|
||||||
static constexpr ReturnValue_t WRONG_HK_PACKET_TYPE = MAKE_RETURN_CODE(1);
|
static constexpr ReturnValue_t WRONG_HK_PACKET_TYPE = MAKE_RETURN_CODE(1);
|
||||||
static constexpr ReturnValue_t REPORTING_STATUS_UNCHANGED = MAKE_RETURN_CODE(2);
|
static constexpr ReturnValue_t REPORTING_STATUS_UNCHANGED = MAKE_RETURN_CODE(2);
|
||||||
static constexpr ReturnValue_t PERIODIC_HELPER_INVALID = MAKE_RETURN_CODE(3);
|
static constexpr ReturnValue_t PERIODIC_HELPER_INVALID = MAKE_RETURN_CODE(3);
|
||||||
@ -81,29 +81,29 @@ public:
|
|||||||
* @param appendValidityBuffer Specify whether a buffer containing the
|
* @param appendValidityBuffer Specify whether a buffer containing the
|
||||||
* validity state is generated when serializing or deserializing packets.
|
* validity state is generated when serializing or deserializing packets.
|
||||||
*/
|
*/
|
||||||
LocalDataPoolManager(HasLocalDataPoolIF* owner, MessageQueueIF* queueToUse,
|
LocalDataPoolManager(HasLocalDataPoolIF* owner, MessageQueueIF* queueToUse,
|
||||||
bool appendValidityBuffer = true);
|
bool appendValidityBuffer = true);
|
||||||
virtual~ LocalDataPoolManager();
|
virtual~ LocalDataPoolManager();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assigns the queue to use. Make sure to call this in the #initialize
|
* Assigns the queue to use. Make sure to call this in the #initialize
|
||||||
* function of the owner.
|
* function of the owner.
|
||||||
* @param queueToUse
|
* @param queueToUse
|
||||||
* @param nonDiagInvlFactor See #setNonDiagnosticIntervalFactor doc
|
* @param nonDiagInvlFactor See #setNonDiagnosticIntervalFactor doc
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t initialize(MessageQueueIF* queueToUse);
|
ReturnValue_t initialize(MessageQueueIF* queueToUse);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the map by calling the map initialization function and
|
* Initializes the map by calling the map initialization function and
|
||||||
* setting the periodic factor for non-diagnostic packets.
|
* setting the periodic factor for non-diagnostic packets.
|
||||||
* Don't forget to call this in the #initializeAfterTaskCreation call of
|
* Don't forget to call this in the #initializeAfterTaskCreation call of
|
||||||
* the owner, otherwise the map will be invalid!
|
* the owner, otherwise the map will be invalid!
|
||||||
* @param nonDiagInvlFactor
|
* @param nonDiagInvlFactor
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t initializeAfterTaskCreation(
|
ReturnValue_t initializeAfterTaskCreation(
|
||||||
uint8_t nonDiagInvlFactor = 5);
|
uint8_t nonDiagInvlFactor = 5);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This should be called in the periodic handler of the owner.
|
* @brief This should be called in the periodic handler of the owner.
|
||||||
@ -116,49 +116,49 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual ReturnValue_t performHkOperation();
|
virtual ReturnValue_t performHkOperation();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Subscribe for the generation of periodic packets.
|
* @brief Subscribe for the generation of periodic packets.
|
||||||
* @details
|
* @details
|
||||||
* This subscription mechanism will generally be used by the data creator
|
* This subscription mechanism will generally be used by the data creator
|
||||||
* to generate housekeeping packets which are downlinked directly.
|
* to generate housekeeping packets which are downlinked directly.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t subscribeForPeriodicPacket(sid_t sid, bool enableReporting,
|
ReturnValue_t subscribeForPeriodicPacket(sid_t sid, bool enableReporting,
|
||||||
float collectionInterval, bool isDiagnostics,
|
float collectionInterval, bool isDiagnostics,
|
||||||
object_id_t packetDestination = defaultHkDestination) override;
|
object_id_t packetDestination = defaultHkDestination) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Subscribe for the generation of packets if the dataset
|
* @brief Subscribe for the generation of packets if the dataset
|
||||||
* is marked as changed.
|
* is marked as changed.
|
||||||
* @details
|
* @details
|
||||||
* This subscription mechanism will generally be used by the data creator.
|
* This subscription mechanism will generally be used by the data creator.
|
||||||
* @param sid
|
* @param sid
|
||||||
* @param isDiagnostics
|
* @param isDiagnostics
|
||||||
* @param packetDestination
|
* @param packetDestination
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t subscribeForUpdatePackets(sid_t sid, bool reportingEnabled,
|
ReturnValue_t subscribeForUpdatePackets(sid_t sid, bool reportingEnabled,
|
||||||
bool isDiagnostics,
|
bool isDiagnostics,
|
||||||
object_id_t packetDestination = defaultHkDestination) override;
|
object_id_t packetDestination = defaultHkDestination) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Subscribe for a notification message which will be sent
|
* @brief Subscribe for a notification message which will be sent
|
||||||
* if a dataset has changed.
|
* if a dataset has changed.
|
||||||
* @details
|
* @details
|
||||||
* This subscription mechanism will generally be used internally by
|
* This subscription mechanism will generally be used internally by
|
||||||
* other software components.
|
* other software components.
|
||||||
* @param setId Set ID of the set to receive update messages from.
|
* @param setId Set ID of the set to receive update messages from.
|
||||||
* @param destinationObject
|
* @param destinationObject
|
||||||
* @param targetQueueId
|
* @param targetQueueId
|
||||||
* @param generateSnapshot If this is set to true, a copy of the current
|
* @param generateSnapshot If this is set to true, a copy of the current
|
||||||
* data with a timestamp will be generated and sent via message.
|
* data with a timestamp will be generated and sent via message.
|
||||||
* Otherwise, only an notification message is sent.
|
* Otherwise, only an notification message is sent.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t subscribeForSetUpdateMessages(const uint32_t setId,
|
ReturnValue_t subscribeForSetUpdateMessages(const uint32_t setId,
|
||||||
object_id_t destinationObject,
|
object_id_t destinationObject,
|
||||||
MessageQueueId_t targetQueueId,
|
MessageQueueId_t targetQueueId,
|
||||||
bool generateSnapshot) override;
|
bool generateSnapshot) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Subscribe for an notification message which will be sent if a
|
* @brief Subscribe for an notification message which will be sent if a
|
||||||
@ -179,18 +179,16 @@ public:
|
|||||||
MessageQueueId_t targetQueueId,
|
MessageQueueId_t targetQueueId,
|
||||||
bool generateSnapshot) override;
|
bool generateSnapshot) override;
|
||||||
|
|
||||||
MutexIF* getLocalPoolMutex() override;
|
/**
|
||||||
|
* Non-Diagnostics packets usually have a lower minimum sampling frequency
|
||||||
/**
|
* than diagnostic packets.
|
||||||
* Non-Diagnostics packets usually have a lower minimum sampling frequency
|
* A factor can be specified to determine the minimum sampling frequency
|
||||||
* than diagnostic packets.
|
* for non-diagnostic packets. The minimum sampling frequency of the
|
||||||
* A factor can be specified to determine the minimum sampling frequency
|
* diagnostics packets,which is usually jusst the period of the
|
||||||
* for non-diagnostic packets. The minimum sampling frequency of the
|
* performOperation calls, is multiplied with that factor.
|
||||||
* diagnostics packets,which is usually jusst the period of the
|
* @param factor
|
||||||
* performOperation calls, is multiplied with that factor.
|
*/
|
||||||
* @param factor
|
void setNonDiagnosticIntervalFactor(uint8_t nonDiagInvlFactor);
|
||||||
*/
|
|
||||||
void setNonDiagnosticIntervalFactor(uint8_t nonDiagInvlFactor);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The manager is also able to handle housekeeping messages.
|
* @brief The manager is also able to handle housekeeping messages.
|
||||||
@ -206,18 +204,18 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual ReturnValue_t handleHousekeepingMessage(CommandMessage* message);
|
virtual ReturnValue_t handleHousekeepingMessage(CommandMessage* message);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a housekeeping packet with a given SID.
|
* Generate a housekeeping packet with a given SID.
|
||||||
* @param sid
|
* @param sid
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
ReturnValue_t generateHousekeepingPacket(sid_t sid,
|
ReturnValue_t generateHousekeepingPacket(sid_t sid,
|
||||||
LocalPoolDataSetBase* dataSet, bool forDownlink,
|
LocalPoolDataSetBase* dataSet, bool forDownlink,
|
||||||
MessageQueueId_t destination = MessageQueueIF::NO_QUEUE);
|
MessageQueueId_t destination = MessageQueueIF::NO_QUEUE);
|
||||||
|
|
||||||
HasLocalDataPoolIF* getOwner();
|
HasLocalDataPoolIF* getOwner();
|
||||||
|
|
||||||
ReturnValue_t printPoolEntry(lp_id_t localPoolId);
|
ReturnValue_t printPoolEntry(lp_id_t localPoolId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Different types of housekeeping reporting are possible.
|
* Different types of housekeeping reporting are possible.
|
||||||
@ -236,22 +234,19 @@ public:
|
|||||||
PERIODIC,
|
PERIODIC,
|
||||||
//! Housekeeping packet will be generated if values have changed.
|
//! Housekeeping packet will be generated if values have changed.
|
||||||
UPDATE_HK,
|
UPDATE_HK,
|
||||||
//! Update notification will be sent out as message.
|
//! Update notification will be sent out as message.
|
||||||
UPDATE_NOTIFICATION,
|
UPDATE_NOTIFICATION,
|
||||||
//! Notification will be sent out as message and a snapshot of the
|
//! Notification will be sent out as message and a snapshot of the
|
||||||
//! current data will be generated.
|
//! current data will be generated.
|
||||||
UPDATE_SNAPSHOT,
|
UPDATE_SNAPSHOT,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/** Different data types are possible in the HK receiver map. For example, updates can be
|
||||||
* Different data types are possible in the HK receiver map.
|
requested for full datasets or for single pool variables. Periodic reporting is only possible
|
||||||
* For example, updates can be requested for full datasets or
|
for data sets. */
|
||||||
* for single pool variables. Periodic reporting is only possible for
|
|
||||||
* data sets.
|
|
||||||
*/
|
|
||||||
enum class DataType: uint8_t {
|
enum class DataType: uint8_t {
|
||||||
LOCAL_POOL_VARIABLE,
|
LOCAL_POOL_VARIABLE,
|
||||||
DATA_SET
|
DATA_SET
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Copying forbidden */
|
/* Copying forbidden */
|
||||||
@ -267,11 +262,19 @@ public:
|
|||||||
|
|
||||||
object_id_t getCreatorObjectId() const;
|
object_id_t getCreatorObjectId() const;
|
||||||
|
|
||||||
virtual LocalDataPoolManager* getHkManagerHandle() override;
|
/**
|
||||||
|
* Get the pointer to the mutex. Can be used to lock the data pool
|
||||||
|
* externally. Use with care and don't forget to unlock locked mutexes!
|
||||||
|
* For now, only friend classes can accss this function.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
MutexIF* getMutexHandle();
|
||||||
|
|
||||||
|
virtual LocalDataPoolManager* getPoolManagerHandle() override;
|
||||||
private:
|
private:
|
||||||
localpool::DataPool localPoolMap;
|
localpool::DataPool localPoolMap;
|
||||||
//! Every housekeeping data manager has a mutex to protect access
|
/** Every housekeeping data manager has a mutex to protect access
|
||||||
//! to it's data pool.
|
to it's data pool. */
|
||||||
MutexIF* mutex = nullptr;
|
MutexIF* mutex = nullptr;
|
||||||
|
|
||||||
/** The class which actually owns the manager (and its datapool). */
|
/** The class which actually owns the manager (and its datapool). */
|
||||||
@ -279,9 +282,9 @@ private:
|
|||||||
|
|
||||||
uint8_t nonDiagnosticIntervalFactor = 0;
|
uint8_t nonDiagnosticIntervalFactor = 0;
|
||||||
|
|
||||||
/** Default receiver for periodic HK packets */
|
/** Default receiver for periodic HK packets */
|
||||||
static object_id_t defaultHkDestination;
|
static object_id_t defaultHkDestination;
|
||||||
MessageQueueId_t hkDestinationId = MessageQueueIF::NO_QUEUE;
|
MessageQueueId_t hkDestinationId = MessageQueueIF::NO_QUEUE;
|
||||||
|
|
||||||
union DataId {
|
union DataId {
|
||||||
DataId(): sid() {};
|
DataId(): sid() {};
|
||||||
@ -291,10 +294,10 @@ private:
|
|||||||
|
|
||||||
/** The data pool manager will keep an internal map of HK receivers. */
|
/** The data pool manager will keep an internal map of HK receivers. */
|
||||||
struct HkReceiver {
|
struct HkReceiver {
|
||||||
/** Object ID of receiver */
|
/** Object ID of receiver */
|
||||||
object_id_t objectId = objects::NO_OBJECT;
|
object_id_t objectId = objects::NO_OBJECT;
|
||||||
|
|
||||||
DataType dataType = DataType::DATA_SET;
|
DataType dataType = DataType::DATA_SET;
|
||||||
DataId dataId;
|
DataId dataId;
|
||||||
|
|
||||||
ReportingType reportingType = ReportingType::PERIODIC;
|
ReportingType reportingType = ReportingType::PERIODIC;
|
||||||
@ -324,37 +327,30 @@ private:
|
|||||||
* of generated housekeeping packets. */
|
* of generated housekeeping packets. */
|
||||||
bool appendValidityBuffer = true;
|
bool appendValidityBuffer = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Queue used for communication, for example commands.
|
* @brief Queue used for communication, for example commands.
|
||||||
* Is also used to send messages. Can be set either in the constructor
|
* Is also used to send messages. Can be set either in the constructor
|
||||||
* or in the initialize() function.
|
* or in the initialize() function.
|
||||||
*/
|
*/
|
||||||
MessageQueueIF* hkQueue = nullptr;
|
MessageQueueIF* hkQueue = nullptr;
|
||||||
|
|
||||||
/** Global IPC store is used to store all packets. */
|
/** Global IPC store is used to store all packets. */
|
||||||
StorageManagerIF* ipcStore = nullptr;
|
StorageManagerIF* ipcStore = nullptr;
|
||||||
/**
|
|
||||||
* Get the pointer to the mutex. Can be used to lock the data pool
|
|
||||||
* externally. Use with care and don't forget to unlock locked mutexes!
|
|
||||||
* For now, only friend classes can accss this function.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
MutexIF* getMutexHandle();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read a variable by supplying its local pool ID and assign the pool
|
* Read a variable by supplying its local pool ID and assign the pool
|
||||||
* entry to the supplied PoolEntry pointer. The type of the pool entry
|
* entry to the supplied PoolEntry pointer. The type of the pool entry
|
||||||
* is deduced automatically. This call is not thread-safe!
|
* is deduced automatically. This call is not thread-safe!
|
||||||
* For now, only friend classes like LocalPoolVar may access this
|
* For now, only friend classes like LocalPoolVar may access this
|
||||||
* function.
|
* function.
|
||||||
* @tparam T Type of the pool entry
|
* @tparam T Type of the pool entry
|
||||||
* @param localPoolId Pool ID of the variable to read
|
* @param localPoolId Pool ID of the variable to read
|
||||||
* @param poolVar [out] Corresponding pool entry will be assigned to the
|
* @param poolVar [out] Corresponding pool entry will be assigned to the
|
||||||
* supplied pointer.
|
* supplied pointer.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
template <class T> ReturnValue_t fetchPoolEntry(lp_id_t localPoolId,
|
template <class T> ReturnValue_t fetchPoolEntry(lp_id_t localPoolId,
|
||||||
PoolEntry<T> **poolEntry);
|
PoolEntry<T> **poolEntry);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is used to fill the local data pool map with pool
|
* This function is used to fill the local data pool map with pool
|
||||||
@ -364,55 +360,57 @@ private:
|
|||||||
*/
|
*/
|
||||||
ReturnValue_t initializeHousekeepingPoolEntriesOnce();
|
ReturnValue_t initializeHousekeepingPoolEntriesOnce();
|
||||||
|
|
||||||
ReturnValue_t serializeHkPacketIntoStore(
|
MutexIF* getLocalPoolMutex() override;
|
||||||
HousekeepingPacketDownlink& hkPacket,
|
|
||||||
store_address_t& storeId, bool forDownlink, size_t* serializedSize);
|
|
||||||
|
|
||||||
void performPeriodicHkGeneration(HkReceiver& hkReceiver);
|
ReturnValue_t serializeHkPacketIntoStore(
|
||||||
ReturnValue_t togglePeriodicGeneration(sid_t sid, bool enable,
|
HousekeepingPacketDownlink& hkPacket,
|
||||||
bool isDiagnostics);
|
store_address_t& storeId, bool forDownlink, size_t* serializedSize);
|
||||||
ReturnValue_t changeCollectionInterval(sid_t sid,
|
|
||||||
float newCollectionInterval, bool isDiagnostics);
|
|
||||||
ReturnValue_t generateSetStructurePacket(sid_t sid, bool isDiagnostics);
|
|
||||||
|
|
||||||
void handleHkUpdateResetListInsertion(DataType dataType, DataId dataId);
|
void performPeriodicHkGeneration(HkReceiver& hkReceiver);
|
||||||
void handleChangeResetLogic(DataType type,
|
ReturnValue_t togglePeriodicGeneration(sid_t sid, bool enable,
|
||||||
DataId dataId, MarkChangedIF* toReset);
|
bool isDiagnostics);
|
||||||
void resetHkUpdateResetHelper();
|
ReturnValue_t changeCollectionInterval(sid_t sid,
|
||||||
|
float newCollectionInterval, bool isDiagnostics);
|
||||||
|
ReturnValue_t generateSetStructurePacket(sid_t sid, bool isDiagnostics);
|
||||||
|
|
||||||
ReturnValue_t handleHkUpdate(HkReceiver& hkReceiver,
|
void handleHkUpdateResetListInsertion(DataType dataType, DataId dataId);
|
||||||
|
void handleChangeResetLogic(DataType type,
|
||||||
|
DataId dataId, MarkChangedIF* toReset);
|
||||||
|
void resetHkUpdateResetHelper();
|
||||||
|
|
||||||
|
ReturnValue_t handleHkUpdate(HkReceiver& hkReceiver,
|
||||||
ReturnValue_t& status);
|
ReturnValue_t& status);
|
||||||
ReturnValue_t handleNotificationUpdate(HkReceiver& hkReceiver,
|
ReturnValue_t handleNotificationUpdate(HkReceiver& hkReceiver,
|
||||||
ReturnValue_t& status);
|
|
||||||
ReturnValue_t handleNotificationSnapshot(HkReceiver& hkReceiver,
|
|
||||||
ReturnValue_t& status);
|
ReturnValue_t& status);
|
||||||
ReturnValue_t addUpdateToStore(HousekeepingPacketUpdate& updatePacket,
|
ReturnValue_t handleNotificationSnapshot(HkReceiver& hkReceiver,
|
||||||
store_address_t& storeId);
|
ReturnValue_t& status);
|
||||||
|
ReturnValue_t addUpdateToStore(HousekeepingSnapshot& updatePacket,
|
||||||
|
store_address_t& storeId);
|
||||||
|
|
||||||
void printWarningOrError(sif::OutputTypes outputType,
|
void printWarningOrError(sif::OutputTypes outputType,
|
||||||
const char* functionName,
|
const char* functionName,
|
||||||
ReturnValue_t errorCode = HasReturnvaluesIF::RETURN_FAILED,
|
ReturnValue_t errorCode = HasReturnvaluesIF::RETURN_FAILED,
|
||||||
const char* errorPrint = nullptr);
|
const char* errorPrint = nullptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template<class T> inline
|
template<class T> inline
|
||||||
ReturnValue_t LocalDataPoolManager::fetchPoolEntry(lp_id_t localPoolId,
|
ReturnValue_t LocalDataPoolManager::fetchPoolEntry(lp_id_t localPoolId,
|
||||||
PoolEntry<T> **poolEntry) {
|
PoolEntry<T> **poolEntry) {
|
||||||
auto poolIter = localPoolMap.find(localPoolId);
|
auto poolIter = localPoolMap.find(localPoolId);
|
||||||
if (poolIter == localPoolMap.end()) {
|
if (poolIter == localPoolMap.end()) {
|
||||||
printWarningOrError(sif::OutputTypes::OUT_ERROR, "fetchPoolEntry",
|
printWarningOrError(sif::OutputTypes::OUT_WARNING, "fetchPoolEntry",
|
||||||
localpool::POOL_ENTRY_NOT_FOUND);
|
localpool::POOL_ENTRY_NOT_FOUND);
|
||||||
return localpool::POOL_ENTRY_NOT_FOUND;
|
return localpool::POOL_ENTRY_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
*poolEntry = dynamic_cast< PoolEntry<T>* >(poolIter->second);
|
*poolEntry = dynamic_cast< PoolEntry<T>* >(poolIter->second);
|
||||||
if(*poolEntry == nullptr) {
|
if(*poolEntry == nullptr) {
|
||||||
printWarningOrError(sif::OutputTypes::OUT_ERROR, "fetchPoolEntry",
|
printWarningOrError(sif::OutputTypes::OUT_WARNING, "fetchPoolEntry",
|
||||||
localpool::POOL_ENTRY_TYPE_CONFLICT);
|
localpool::POOL_ENTRY_TYPE_CONFLICT);
|
||||||
return localpool::POOL_ENTRY_TYPE_CONFLICT;
|
return localpool::POOL_ENTRY_TYPE_CONFLICT;
|
||||||
}
|
}
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,11 +4,26 @@
|
|||||||
#include "LocalPoolDataSetBase.h"
|
#include "LocalPoolDataSetBase.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This dataset type can be used to group related pool variables if the number of
|
||||||
|
* variables should not be fixed.
|
||||||
|
* @details
|
||||||
|
* This will is the primary data structure to organize pool variables into
|
||||||
|
* sets which can be accessed via the housekeeping service interface or
|
||||||
|
* which can be sent to other software objects.
|
||||||
|
*
|
||||||
|
* It is recommended to read the documentation of the LocalPoolDataSetBase
|
||||||
|
* class for more information on how this class works and how to use it.
|
||||||
|
* @tparam capacity Capacity of the static dataset, which is usually known
|
||||||
|
* beforehand.
|
||||||
|
*/
|
||||||
class LocalDataSet: public LocalPoolDataSetBase {
|
class LocalDataSet: public LocalPoolDataSetBase {
|
||||||
public:
|
public:
|
||||||
LocalDataSet(HasLocalDataPoolIF* hkOwner, uint32_t setId,
|
LocalDataSet(HasLocalDataPoolIF* hkOwner, uint32_t setId,
|
||||||
const size_t maxSize);
|
const size_t maxSize);
|
||||||
|
|
||||||
LocalDataSet(sid_t sid, const size_t maxSize);
|
LocalDataSet(sid_t sid, const size_t maxSize);
|
||||||
|
|
||||||
virtual~ LocalDataSet();
|
virtual~ LocalDataSet();
|
||||||
|
|
||||||
//! Copying forbidden for now.
|
//! Copying forbidden for now.
|
||||||
|
@ -28,7 +28,7 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner,
|
|||||||
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
||||||
|
|
||||||
if(accessor != nullptr) {
|
if(accessor != nullptr) {
|
||||||
poolManager = accessor->getHkManagerHandle();
|
poolManager = accessor->getPoolManagerHandle();
|
||||||
mutexIfSingleDataCreator = accessor->getLocalPoolMutex();
|
mutexIfSingleDataCreator = accessor->getLocalPoolMutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ LocalPoolObjectBase::LocalPoolObjectBase(lp_id_t poolId, HasLocalDataPoolIF* hkO
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AccessPoolManagerIF* poolManAccessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
AccessPoolManagerIF* poolManAccessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
||||||
hkManager = poolManAccessor->getHkManagerHandle();
|
hkManager = poolManAccessor->getPoolManagerHandle();
|
||||||
|
|
||||||
if (dataSet != nullptr) {
|
if (dataSet != nullptr) {
|
||||||
dataSet->registerVariable(this);
|
dataSet->registerVariable(this);
|
||||||
@ -50,7 +50,7 @@ LocalPoolObjectBase::LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId,
|
|||||||
|
|
||||||
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
||||||
if(accessor != nullptr) {
|
if(accessor != nullptr) {
|
||||||
hkManager = accessor->getHkManagerHandle();
|
hkManager = accessor->getPoolManagerHandle();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dataSet != nullptr) {
|
if(dataSet != nullptr) {
|
||||||
|
@ -77,8 +77,7 @@ public:
|
|||||||
* @param dataSet
|
* @param dataSet
|
||||||
* @param setReadWriteMode
|
* @param setReadWriteMode
|
||||||
*/
|
*/
|
||||||
LocalPoolVector(gp_id_t globalPoolId,
|
LocalPoolVector(gp_id_t globalPoolId, DataSetIF* dataSet = nullptr,
|
||||||
DataSetIF* dataSet = nullptr,
|
|
||||||
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -87,7 +86,7 @@ public:
|
|||||||
* The user can work on this attribute just like he would on a local
|
* The user can work on this attribute just like he would on a local
|
||||||
* array of this type.
|
* array of this type.
|
||||||
*/
|
*/
|
||||||
T value[vectorSize];
|
T value[vectorSize]= {};
|
||||||
/**
|
/**
|
||||||
* @brief The classes destructor is empty.
|
* @brief The classes destructor is empty.
|
||||||
* @details If commit() was not called, the local value is
|
* @details If commit() was not called, the local value is
|
||||||
|
@ -16,7 +16,6 @@ inline LocalPoolVector<T, vectorSize>::LocalPoolVector(object_id_t poolOwner,
|
|||||||
lp_id_t poolId, DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
lp_id_t poolId, DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
||||||
LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
|
LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
|
||||||
|
|
||||||
|
|
||||||
template<typename T, uint16_t vectorSize>
|
template<typename T, uint16_t vectorSize>
|
||||||
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(gp_id_t globalPoolId,
|
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(gp_id_t globalPoolId,
|
||||||
DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
|
||||||
|
@ -2,11 +2,15 @@
|
|||||||
#define FSFW_DATAPOOLLOCAL_STATICLOCALDATASET_H_
|
#define FSFW_DATAPOOLLOCAL_STATICLOCALDATASET_H_
|
||||||
|
|
||||||
#include "LocalPoolDataSetBase.h"
|
#include "LocalPoolDataSetBase.h"
|
||||||
|
#include "LocalPoolVariable.h"
|
||||||
|
#include "LocalPoolVector.h"
|
||||||
|
|
||||||
#include "../objectmanager/SystemObjectIF.h"
|
#include "../objectmanager/SystemObjectIF.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This local dataset type is created on the stack.
|
* @brief This dataset type can be used to group related pool variables if the number of
|
||||||
|
* variables is fixed.
|
||||||
* @details
|
* @details
|
||||||
* This will is the primary data structure to organize pool variables into
|
* This will is the primary data structure to organize pool variables into
|
||||||
* sets which can be accessed via the housekeeping service interface or
|
* sets which can be accessed via the housekeeping service interface or
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -209,20 +209,20 @@ void DeviceHandlerFailureIsolation::startRecovery(Event reason) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t DeviceHandlerFailureIsolation::getParameter(uint8_t domainId,
|
ReturnValue_t DeviceHandlerFailureIsolation::getParameter(uint8_t domainId,
|
||||||
uint16_t parameterId, ParameterWrapper* parameterWrapper,
|
uint8_t uniqueId, ParameterWrapper* parameterWrapper,
|
||||||
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
||||||
ReturnValue_t result = strangeReplyCount.getParameter(domainId, parameterId,
|
ReturnValue_t result = strangeReplyCount.getParameter(domainId, uniqueId,
|
||||||
parameterWrapper, newValues, startAtIndex);
|
parameterWrapper, newValues, startAtIndex);
|
||||||
if (result != INVALID_DOMAIN_ID) {
|
if (result != INVALID_DOMAIN_ID) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = missedReplyCount.getParameter(domainId, parameterId,
|
result = missedReplyCount.getParameter(domainId, uniqueId, parameterWrapper, newValues,
|
||||||
parameterWrapper, newValues, startAtIndex);
|
startAtIndex);
|
||||||
if (result != INVALID_DOMAIN_ID) {
|
if (result != INVALID_DOMAIN_ID) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = recoveryCounter.getParameter(domainId, parameterId,
|
result = recoveryCounter.getParameter(domainId, uniqueId, parameterWrapper, newValues,
|
||||||
parameterWrapper, newValues, startAtIndex);
|
startAtIndex);
|
||||||
if (result != INVALID_DOMAIN_ID) {
|
if (result != INVALID_DOMAIN_ID) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,9 @@ public:
|
|||||||
ReturnValue_t initialize();
|
ReturnValue_t initialize();
|
||||||
void triggerEvent(Event event, uint32_t parameter1 = 0,
|
void triggerEvent(Event event, uint32_t parameter1 = 0,
|
||||||
uint32_t parameter2 = 0);bool isFdirActionInProgress();
|
uint32_t parameter2 = 0);bool isFdirActionInProgress();
|
||||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
uint16_t startAtIndex);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
FaultCounter strangeReplyCount;
|
FaultCounter strangeReplyCount;
|
||||||
|
3
doc/doxy/.gitignore
vendored
Normal file
3
doc/doxy/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
html
|
||||||
|
latex
|
||||||
|
rtf
|
2609
doc/doxy/OPUS.doxyfile
Normal file
2609
doc/doxy/OPUS.doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
@ -6,6 +6,7 @@
|
|||||||
#include "../ipc/QueueFactory.h"
|
#include "../ipc/QueueFactory.h"
|
||||||
#include "../ipc/MutexFactory.h"
|
#include "../ipc/MutexFactory.h"
|
||||||
|
|
||||||
|
MessageQueueId_t EventManagerIF::eventmanagerQueue = MessageQueueIF::NO_QUEUE;
|
||||||
|
|
||||||
// If one checks registerListener calls, there are around 40 (to max 50)
|
// If one checks registerListener calls, there are around 40 (to max 50)
|
||||||
// objects registering for certain events.
|
// objects registering for certain events.
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
#ifndef EVENTMANAGERIF_H_
|
#ifndef FSFW_EVENTS_EVENTMANAGERIF_H_
|
||||||
#define EVENTMANAGERIF_H_
|
#define FSFW_EVENTS_EVENTMANAGERIF_H_
|
||||||
|
|
||||||
#include "EventMessage.h"
|
#include "EventMessage.h"
|
||||||
#include "eventmatching/eventmatching.h"
|
#include "eventmatching/eventmatching.h"
|
||||||
#include "../objectmanager/ObjectManagerIF.h"
|
#include "../objectmanager/ObjectManagerIF.h"
|
||||||
#include "../ipc/MessageQueueSenderIF.h"
|
#include "../ipc/MessageQueueSenderIF.h"
|
||||||
#include "../ipc/MessageQueueIF.h"
|
#include "../ipc/MessageQueueIF.h"
|
||||||
|
#include "../serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
class EventManagerIF {
|
class EventManagerIF {
|
||||||
public:
|
public:
|
||||||
@ -41,11 +42,19 @@ public:
|
|||||||
|
|
||||||
static void triggerEvent(EventMessage* message,
|
static void triggerEvent(EventMessage* message,
|
||||||
MessageQueueId_t sentFrom = 0) {
|
MessageQueueId_t sentFrom = 0) {
|
||||||
static MessageQueueId_t eventmanagerQueue = MessageQueueIF::NO_QUEUE;
|
|
||||||
if (eventmanagerQueue == MessageQueueIF::NO_QUEUE) {
|
if (eventmanagerQueue == MessageQueueIF::NO_QUEUE) {
|
||||||
EventManagerIF *eventmanager = objectManager->get<EventManagerIF>(
|
EventManagerIF *eventmanager = objectManager->get<EventManagerIF>(
|
||||||
objects::EVENT_MANAGER);
|
objects::EVENT_MANAGER);
|
||||||
if (eventmanager == nullptr) {
|
if (eventmanager == nullptr) {
|
||||||
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "EventManagerIF::triggerEvent: EventManager invalid or not found!"
|
||||||
|
<< std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("EventManagerIF::triggerEvent: "
|
||||||
|
"EventManager invalid or not found!");
|
||||||
|
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||||
|
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
eventmanagerQueue = eventmanager->getEventReportQueue();
|
eventmanagerQueue = eventmanager->getEventReportQueue();
|
||||||
@ -53,6 +62,10 @@ public:
|
|||||||
MessageQueueSenderIF::sendMessage(eventmanagerQueue, message, sentFrom);
|
MessageQueueSenderIF::sendMessage(eventmanagerQueue, message, sentFrom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
//! Initialized by EventManager (C++11 does not allow header-only static member initialization).
|
||||||
|
static MessageQueueId_t eventmanagerQueue;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* EVENTMANAGERIF_H_ */
|
#endif /* FSFW_EVENTS_EVENTMANAGERIF_H_ */
|
||||||
|
@ -58,14 +58,14 @@ FaultCounter::FaultCounter() :
|
|||||||
parameterDomain(0), timer(), faultCount(0), failureThreshold(0) {
|
parameterDomain(0), timer(), faultCount(0), failureThreshold(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t FaultCounter::getParameter(uint8_t domainId, uint16_t parameterId,
|
ReturnValue_t FaultCounter::getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
||||||
uint16_t startAtIndex) {
|
uint16_t startAtIndex) {
|
||||||
if (domainId != parameterDomain) {
|
if (domainId != parameterDomain) {
|
||||||
return INVALID_DOMAIN_ID;
|
return INVALID_DOMAIN_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (parameterId) {
|
switch (uniqueId) {
|
||||||
case 0:
|
case 0:
|
||||||
parameterWrapper->set(failureThreshold);
|
parameterWrapper->set(failureThreshold);
|
||||||
break;
|
break;
|
||||||
|
@ -23,7 +23,7 @@ public:
|
|||||||
void setFailureThreshold(uint32_t failureThreshold);
|
void setFailureThreshold(uint32_t failureThreshold);
|
||||||
void setFaultDecrementTimeMs(uint32_t timeMs);
|
void setFaultDecrementTimeMs(uint32_t timeMs);
|
||||||
|
|
||||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper,
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ void HousekeepingMessage::setUpdateNotificationVariableCommand(
|
|||||||
|
|
||||||
void HousekeepingMessage::setUpdateSnapshotSetCommand(CommandMessage *command,
|
void HousekeepingMessage::setUpdateSnapshotSetCommand(CommandMessage *command,
|
||||||
sid_t sid, store_address_t storeId) {
|
sid_t sid, store_address_t storeId) {
|
||||||
command->setCommand(UPDATE_SNAPSHOT_VARIABLE);
|
command->setCommand(UPDATE_SNAPSHOT_SET);
|
||||||
setSid(command, sid);
|
setSid(command, sid);
|
||||||
command->setParameter3(storeId.raw);
|
command->setParameter3(storeId.raw);
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,37 @@
|
|||||||
#ifndef FSFW_HOUSEKEEPING_HOUSEKEEPINGPACKETUPDATE_H_
|
#ifndef FSFW_HOUSEKEEPING_HOUSEKEEPINGSNAPSHOT_H_
|
||||||
#define FSFW_HOUSEKEEPING_HOUSEKEEPINGPACKETUPDATE_H_
|
#define FSFW_HOUSEKEEPING_HOUSEKEEPINGSNAPSHOT_H_
|
||||||
|
|
||||||
#include "../serialize/SerialBufferAdapter.h"
|
#include "../serialize/SerialBufferAdapter.h"
|
||||||
#include "../serialize/SerialLinkedListAdapter.h"
|
#include "../serialize/SerialLinkedListAdapter.h"
|
||||||
#include "../datapoollocal/LocalPoolDataSetBase.h"
|
#include "../datapoollocal/LocalPoolDataSetBase.h"
|
||||||
|
#include "../datapoollocal/LocalPoolObjectBase.h"
|
||||||
|
#include "../timemanager/CCSDSTime.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This helper class will be used to serialize and deserialize
|
* @brief This helper class will be used to serialize and deserialize update housekeeping packets
|
||||||
* update housekeeping packets into the store.
|
* into the store.
|
||||||
*/
|
*/
|
||||||
class HousekeepingPacketUpdate: public SerializeIF {
|
class HousekeepingSnapshot: public SerializeIF {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update packet constructor for datasets
|
* Update packet constructor for datasets.
|
||||||
* @param timeStamp
|
* @param cdsShort If a CSD short timestamp is used, a reference should be
|
||||||
* @param timeStampSize
|
* supplied here
|
||||||
* @param hkData
|
* @param dataSetPtr Pointer to the dataset instance to serialize or deserialize the
|
||||||
* @param hkDataSize
|
* data into
|
||||||
*/
|
*/
|
||||||
HousekeepingPacketUpdate(uint8_t* timeStamp, size_t timeStampSize,
|
HousekeepingSnapshot(CCSDSTime::CDS_short* cdsShort, LocalPoolDataSetBase* dataSetPtr):
|
||||||
|
timeStamp(reinterpret_cast<uint8_t*>(cdsShort)),
|
||||||
|
timeStampSize(sizeof(CCSDSTime::CDS_short)), updateData(dataSetPtr) {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update packet constructor for datasets.
|
||||||
|
* @param timeStamp Pointer to the buffer where the timestamp will be stored.
|
||||||
|
* @param timeStampSize Size of the timestamp
|
||||||
|
* @param dataSetPtr Pointer to the dataset instance to deserialize the data into
|
||||||
|
*/
|
||||||
|
HousekeepingSnapshot(uint8_t* timeStamp, size_t timeStampSize,
|
||||||
LocalPoolDataSetBase* dataSetPtr):
|
LocalPoolDataSetBase* dataSetPtr):
|
||||||
timeStamp(timeStamp), timeStampSize(timeStampSize),
|
timeStamp(timeStamp), timeStampSize(timeStampSize),
|
||||||
updateData(dataSetPtr) {};
|
updateData(dataSetPtr) {};
|
||||||
@ -29,7 +42,7 @@ public:
|
|||||||
* @param timeStampSize
|
* @param timeStampSize
|
||||||
* @param dataSetPtr
|
* @param dataSetPtr
|
||||||
*/
|
*/
|
||||||
HousekeepingPacketUpdate(uint8_t* timeStamp, size_t timeStampSize,
|
HousekeepingSnapshot(uint8_t* timeStamp, size_t timeStampSize,
|
||||||
LocalPoolObjectBase* dataSetPtr):
|
LocalPoolObjectBase* dataSetPtr):
|
||||||
timeStamp(timeStamp), timeStampSize(timeStampSize),
|
timeStamp(timeStamp), timeStampSize(timeStampSize),
|
||||||
updateData(dataSetPtr) {};
|
updateData(dataSetPtr) {};
|
||||||
@ -89,4 +102,4 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* FSFW_HOUSEKEEPING_HOUSEKEEPINGPACKETUPDATE_H_ */
|
#endif /* FSFW_HOUSEKEEPING_HOUSEKEEPINGSNAPSHOT_H_ */
|
@ -37,16 +37,16 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex) {
|
uint16_t startAtIndex) {
|
||||||
ReturnValue_t result = this->MonitorBase<T>::getParameter(domainId,
|
ReturnValue_t result = this->MonitorBase<T>::getParameter(domainId,
|
||||||
parameterId, parameterWrapper, newValues, startAtIndex);
|
uniqueId, parameterWrapper, newValues, startAtIndex);
|
||||||
//We'll reuse the DOMAIN_ID of MonitorReporter, as we know the parameterIds used there.
|
//We'll reuse the DOMAIN_ID of MonitorReporter, as we know the parameterIds used there.
|
||||||
if (result != this->INVALID_IDENTIFIER_ID) {
|
if (result != this->INVALID_IDENTIFIER_ID) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
switch (parameterId) {
|
switch (uniqueId) {
|
||||||
case 10:
|
case 10:
|
||||||
parameterWrapper->set(this->lowerLimit);
|
parameterWrapper->set(this->lowerLimit);
|
||||||
break;
|
break;
|
||||||
|
@ -51,13 +51,13 @@ public:
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex) {
|
uint16_t startAtIndex) {
|
||||||
if (domainId != monitorId) {
|
if (domainId != monitorId) {
|
||||||
return INVALID_DOMAIN_ID;
|
return INVALID_DOMAIN_ID;
|
||||||
}
|
}
|
||||||
switch (parameterId) {
|
switch (uniqueId) {
|
||||||
case 0:
|
case 0:
|
||||||
parameterWrapper->set(this->confirmationLimit);
|
parameterWrapper->set(this->confirmationLimit);
|
||||||
break;
|
break;
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include "../serialize/SerialFixedArrayListAdapter.h"
|
#include "../serialize/SerialFixedArrayListAdapter.h"
|
||||||
#include "../serialize/SerializeElement.h"
|
#include "../serialize/SerializeElement.h"
|
||||||
#include "../serialize/SerialLinkedListAdapter.h"
|
#include "../serialize/SerialLinkedListAdapter.h"
|
||||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
#include "../serviceinterface/ServiceInterface.h"
|
||||||
#include "../timemanager/TimeStamperIF.h"
|
#include "../timemanager/TimeStamperIF.h"
|
||||||
|
|
||||||
namespace Factory{
|
namespace Factory{
|
||||||
|
@ -71,13 +71,13 @@ public:
|
|||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex) {
|
uint16_t startAtIndex) {
|
||||||
if (domainId != this->domainId) {
|
if (domainId != this->domainId) {
|
||||||
return INVALID_DOMAIN_ID;
|
return INVALID_DOMAIN_ID;
|
||||||
}
|
}
|
||||||
switch (parameterId) {
|
switch (uniqueId) {
|
||||||
case 0:
|
case 0:
|
||||||
parameterWrapper->set(limit);
|
parameterWrapper->set(limit);
|
||||||
break;
|
break;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include "ObjectManager.h"
|
#include "ObjectManager.h"
|
||||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
#include "../serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
@ -75,6 +75,8 @@ void ObjectManager::initialize() {
|
|||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "ObjectManager::initialize: Passed produceObjects "
|
sif::error << "ObjectManager::initialize: Passed produceObjects "
|
||||||
"functions is nullptr!" << std::endl;
|
"functions is nullptr!" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printError("ObjectManager::initialize: Passed produceObjects functions is nullptr!\n");
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,17 @@
|
|||||||
SystemObject::SystemObject(object_id_t setObjectId, bool doRegister) :
|
SystemObject::SystemObject(object_id_t setObjectId, bool doRegister) :
|
||||||
objectId(setObjectId), registered(doRegister) {
|
objectId(setObjectId), registered(doRegister) {
|
||||||
if (registered) {
|
if (registered) {
|
||||||
objectManager->insert(objectId, this);
|
if(objectManager != nullptr) {
|
||||||
|
objectManager->insert(objectId, this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemObject::~SystemObject() {
|
SystemObject::~SystemObject() {
|
||||||
if (registered) {
|
if (registered) {
|
||||||
objectManager->remove(objectId);
|
if(objectManager != nullptr) {
|
||||||
|
objectManager->remove(objectId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,30 +1,35 @@
|
|||||||
#ifndef FSFW_OBJECTMANAGER_FRAMEWORKOBJECTS_H_
|
#ifndef FSFW_OBJECTMANAGER_FRAMEWORKOBJECTS_H_
|
||||||
#define FSFW_OBJECTMANAGER_FRAMEWORKOBJECTS_H_
|
#define FSFW_OBJECTMANAGER_FRAMEWORKOBJECTS_H_
|
||||||
|
|
||||||
|
#include <fsfw/objectmanager/SystemObjectIF.h>
|
||||||
|
|
||||||
namespace objects {
|
namespace objects {
|
||||||
enum framework_objects {
|
enum framework_objects: object_id_t {
|
||||||
// Default verification reporter.
|
FSFW_OBJECTS_START = 0x53000000,
|
||||||
PUS_SERVICE_1_VERIFICATION = 0x53000001,
|
// Default verification reporter.
|
||||||
PUS_SERVICE_2_DEVICE_ACCESS = 0x53000002,
|
PUS_SERVICE_1_VERIFICATION = 0x53000001,
|
||||||
PUS_SERVICE_3_HOUSEKEEPING = 0x53000003,
|
PUS_SERVICE_2_DEVICE_ACCESS = 0x53000002,
|
||||||
PUS_SERVICE_5_EVENT_REPORTING = 0x53000005,
|
PUS_SERVICE_3_HOUSEKEEPING = 0x53000003,
|
||||||
PUS_SERVICE_8_FUNCTION_MGMT = 0x53000008,
|
PUS_SERVICE_5_EVENT_REPORTING = 0x53000005,
|
||||||
PUS_SERVICE_9_TIME_MGMT = 0x53000009,
|
PUS_SERVICE_8_FUNCTION_MGMT = 0x53000008,
|
||||||
PUS_SERVICE_17_TEST = 0x53000017,
|
PUS_SERVICE_9_TIME_MGMT = 0x53000009,
|
||||||
PUS_SERVICE_200_MODE_MGMT = 0x53000200,
|
PUS_SERVICE_17_TEST = 0x53000017,
|
||||||
|
PUS_SERVICE_20_PARAMETERS = 0x53000020,
|
||||||
|
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,
|
||||||
// MODE_STORE = 0x53010100,
|
// MODE_STORE = 0x53010100,
|
||||||
EVENT_MANAGER = 0x53030000,
|
EVENT_MANAGER = 0x53030000,
|
||||||
INTERNAL_ERROR_REPORTER = 0x53040000,
|
INTERNAL_ERROR_REPORTER = 0x53040000,
|
||||||
IPC_STORE = 0x534f0300,
|
IPC_STORE = 0x534f0300,
|
||||||
//IDs for PUS Packet Communication
|
//IDs for PUS Packet Communication
|
||||||
TC_STORE = 0x534f0100,
|
TC_STORE = 0x534f0100,
|
||||||
TM_STORE = 0x534f0200,
|
TM_STORE = 0x534f0200,
|
||||||
TIME_STAMPER = 0x53500010,
|
TIME_STAMPER = 0x53500010,
|
||||||
|
|
||||||
NO_OBJECT = 0xFFFFFFFF
|
FSFW_OBJECTS_END = 0x53ffffff,
|
||||||
|
NO_OBJECT = 0xFFFFFFFF
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,8 @@
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <Windows.h>
|
#include <winsock2.h>
|
||||||
|
#include <windows.h>
|
||||||
#if REG_DWORD == REG_DWORD_LITTLE_ENDIAN
|
#if REG_DWORD == REG_DWORD_LITTLE_ENDIAN
|
||||||
#define BYTE_ORDER_SYSTEM LITTLE_ENDIAN
|
#define BYTE_ORDER_SYSTEM LITTLE_ENDIAN
|
||||||
#else
|
#else
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
#include <windows.h>
|
#include <sysinfoapi.h>
|
||||||
#elif defined(LINUX)
|
#elif defined(LINUX)
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#endif
|
#endif
|
||||||
@ -15,35 +15,34 @@ using SystemClock = std::chrono::system_clock;
|
|||||||
|
|
||||||
uint32_t Clock::getTicksPerSecond(void){
|
uint32_t Clock::getTicksPerSecond(void){
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "Clock::getTicksPerSecond: not implemented yet" << std::endl;
|
sif::warning << "Clock::getTicksPerSecond: Not implemented for host OSAL" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("Clock::getTicksPerSecond: Not implemented for host OSAL\n");
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
/* To avoid division by zero */
|
||||||
//return CLOCKS_PER_SEC;
|
return 1;
|
||||||
//uint32_t ticks = sysconf(_SC_CLK_TCK);
|
|
||||||
//return ticks;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
|
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
|
||||||
// do some magic with chrono
|
/* I don't know why someone would need to set a clock which is probably perfectly fine on a
|
||||||
|
host system with internet access so this is not implemented for now. */
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "Clock::setClock: not implemented yet" << std::endl;
|
sif::warning << "Clock::setClock: Not implemented for host OSAL" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("Clock::setClock: Not implemented for host OSAL\n");
|
||||||
#endif
|
#endif
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Clock::setClock(const timeval* time) {
|
ReturnValue_t Clock::setClock(const timeval* time) {
|
||||||
// do some magic with chrono
|
/* I don't know why someone would need to set a clock which is probably perfectly fine on a
|
||||||
#if defined(WIN32)
|
host system with internet access so this is not implemented for now. */
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
#elif defined(LINUX)
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
#else
|
|
||||||
|
|
||||||
#endif
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl;
|
sif::warning << "Clock::setClock: Not implemented for host OSAL" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("Clock::setClock: Not implemented for host OSAL\n");
|
||||||
#endif
|
#endif
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
||||||
@ -53,8 +52,7 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
|||||||
auto epoch = now.time_since_epoch();
|
auto epoch = now.time_since_epoch();
|
||||||
time->tv_sec = std::chrono::duration_cast<std::chrono::seconds>(epoch).count();
|
time->tv_sec = std::chrono::duration_cast<std::chrono::seconds>(epoch).count();
|
||||||
auto fraction = now - secondsChrono;
|
auto fraction = now - secondsChrono;
|
||||||
time->tv_usec = std::chrono::duration_cast<std::chrono::microseconds>(
|
time->tv_usec = std::chrono::duration_cast<std::chrono::microseconds>(fraction).count();
|
||||||
fraction).count();
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
#elif defined(LINUX)
|
#elif defined(LINUX)
|
||||||
timespec timeUnix;
|
timespec timeUnix;
|
||||||
@ -67,7 +65,9 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
|||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
#else
|
#else
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::warning << "Clock::getUptime: Not implemented for found OS" << std::endl;
|
sif::warning << "Clock::getUptime: Not implemented for found OS!" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("Clock::getUptime: Not implemented for found OS!\n");
|
||||||
#endif
|
#endif
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
#endif
|
#endif
|
||||||
@ -75,10 +75,11 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
||||||
// do some magic with chrono
|
if(time == nullptr) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
sif::warning << "Clock::gerClock_usecs: not implemented yet" << std::endl;
|
}
|
||||||
#endif
|
using namespace std::chrono;
|
||||||
|
*time = duration_cast<microseconds>(system_clock::now().time_since_epoch()).count();
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,9 +121,9 @@ ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
|
|||||||
|
|
||||||
|
|
||||||
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
||||||
// do some magic with chrono (C++20!)
|
/* Do some magic with chrono (C++20!) */
|
||||||
// Right now, the library doesn't have the new features yet.
|
/* Right now, the library doesn't have the new features to get the required values yet.
|
||||||
// so we work around that for now.
|
so we work around that for now. */
|
||||||
auto now = SystemClock::now();
|
auto now = SystemClock::now();
|
||||||
auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(now);
|
auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(now);
|
||||||
auto fraction = now - seconds;
|
auto fraction = now - seconds;
|
||||||
@ -137,10 +138,6 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
|||||||
time->second = timeInfo->tm_sec;
|
time->second = timeInfo->tm_sec;
|
||||||
auto usecond = std::chrono::duration_cast<std::chrono::microseconds>(fraction);
|
auto usecond = std::chrono::duration_cast<std::chrono::microseconds>(fraction);
|
||||||
time->usecond = usecond.count();
|
time->usecond = usecond.count();
|
||||||
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
//sif::warning << "Clock::getDateAndTime: not implemented yet" << std::endl;
|
|
||||||
#endif
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
#include <windows.h>
|
#include <processthreadsapi.h>
|
||||||
#elif defined(LINUX)
|
#elif defined(LINUX)
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -5,13 +5,13 @@ target_sources(${LIB_FSFW_NAME}
|
|||||||
InitTask.cpp
|
InitTask.cpp
|
||||||
InternalErrorCodes.cpp
|
InternalErrorCodes.cpp
|
||||||
MessageQueue.cpp
|
MessageQueue.cpp
|
||||||
MultiObjectTask.cpp
|
PeriodicTask.cpp
|
||||||
Mutex.cpp
|
Mutex.cpp
|
||||||
MutexFactory.cpp
|
MutexFactory.cpp
|
||||||
PollingTask.cpp
|
FixedTimeslotTask.cpp
|
||||||
QueueFactory.cpp
|
QueueFactory.cpp
|
||||||
RtemsBasic.cpp
|
RtemsBasic.cpp
|
||||||
TaskBase.cpp
|
RTEMSTaskBase.cpp
|
||||||
TaskFactory.cpp
|
TaskFactory.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -104,9 +104,13 @@ ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
|
||||||
// TIsn't this a bug? Are RTEMS ticks always microseconds?
|
/* For all but the last field, the struct will be filled with the correct values */
|
||||||
rtems_time_of_day* timeRtems = reinterpret_cast<rtems_time_of_day*>(time);
|
rtems_time_of_day* timeRtems = reinterpret_cast<rtems_time_of_day*>(time);
|
||||||
rtems_status_code status = rtems_clock_get_tod(timeRtems);
|
rtems_status_code status = rtems_clock_get_tod(timeRtems);
|
||||||
|
/* The last field now contains the RTEMS ticks of the seconds from 0
|
||||||
|
to rtems_clock_get_ticks_per_second() minus one. We calculate the microseconds accordingly */
|
||||||
|
timeRtems->ticks = static_cast<float>(timeRtems->ticks) /
|
||||||
|
rtems_clock_get_ticks_per_second() * 1e6;
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case RTEMS_SUCCESSFUL:
|
case RTEMS_SUCCESSFUL:
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
@ -164,7 +164,7 @@ ReturnValue_t CpuUsage::ThreadData::deSerialize(const uint8_t** buffer,
|
|||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if ((*size = *size - MAX_LENGTH_OF_THREAD_NAME) < 0) {
|
if (*size < MAX_LENGTH_OF_THREAD_NAME) {
|
||||||
return STREAM_TOO_SHORT;
|
return STREAM_TOO_SHORT;
|
||||||
}
|
}
|
||||||
memcpy(name, *buffer, MAX_LENGTH_OF_THREAD_NAME);
|
memcpy(name, *buffer, MAX_LENGTH_OF_THREAD_NAME);
|
||||||
|
140
osal/rtems/FixedTimeslotTask.cpp
Normal file
140
osal/rtems/FixedTimeslotTask.cpp
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
#include "FixedTimeslotTask.h"
|
||||||
|
#include "RtemsBasic.h"
|
||||||
|
|
||||||
|
#include "../../tasks/FixedSequenceSlot.h"
|
||||||
|
#include "../../objectmanager/SystemObjectIF.h"
|
||||||
|
#include "../../objectmanager/ObjectManagerIF.h"
|
||||||
|
#include "../../returnvalues/HasReturnvaluesIF.h"
|
||||||
|
#include "../../serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
|
#include <rtems/bspIo.h>
|
||||||
|
#include <rtems/io.h>
|
||||||
|
#include <rtems/rtems/ratemon.h>
|
||||||
|
#include <rtems/rtems/status.h>
|
||||||
|
#include <rtems/rtems/tasks.h>
|
||||||
|
#include <rtems/rtems/types.h>
|
||||||
|
#include <sys/_stdint.h>
|
||||||
|
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
#include <iostream>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
uint32_t FixedTimeslotTask::deadlineMissedCount = 0;
|
||||||
|
|
||||||
|
FixedTimeslotTask::FixedTimeslotTask(const char *name, rtems_task_priority setPriority,
|
||||||
|
size_t setStack, uint32_t setOverallPeriod, void (*setDeadlineMissedFunc)(void)):
|
||||||
|
RTEMSTaskBase(setPriority, setStack, name), periodId(0), pst(setOverallPeriod) {
|
||||||
|
// All additional attributes are applied to the object.
|
||||||
|
this->deadlineMissedFunc = setDeadlineMissedFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedTimeslotTask::~FixedTimeslotTask() {
|
||||||
|
}
|
||||||
|
|
||||||
|
rtems_task FixedTimeslotTask::taskEntryPoint(rtems_task_argument argument) {
|
||||||
|
/* The argument is re-interpreted as a FixedTimeslotTask */
|
||||||
|
FixedTimeslotTask *originalTask(reinterpret_cast<FixedTimeslotTask*>(argument));
|
||||||
|
/* The task's functionality is called. */
|
||||||
|
return originalTask->taskFunctionality();
|
||||||
|
/* Should never be reached */
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "Polling task " << originalTask->getId() << " returned from taskFunctionality." <<
|
||||||
|
std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void FixedTimeslotTask::missedDeadlineCounter() {
|
||||||
|
FixedTimeslotTask::deadlineMissedCount++;
|
||||||
|
if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount
|
||||||
|
<< " deadlines." << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t FixedTimeslotTask::startTask() {
|
||||||
|
rtems_status_code status = rtems_task_start(id, FixedTimeslotTask::taskEntryPoint,
|
||||||
|
rtems_task_argument((void *) this));
|
||||||
|
if (status != RTEMS_SUCCESSFUL) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "PollingTask::startTask for " << std::hex << this->getId()
|
||||||
|
<< std::dec << " failed." << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
switch(status){
|
||||||
|
case RTEMS_SUCCESSFUL:
|
||||||
|
//ask started successfully
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
default:
|
||||||
|
/*
|
||||||
|
RTEMS_INVALID_ADDRESS - invalid task entry point
|
||||||
|
RTEMS_INVALID_ID - invalid task id
|
||||||
|
RTEMS_INCORRECT_STATE - task not in the dormant state
|
||||||
|
RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot start remote task */
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId,
|
||||||
|
uint32_t slotTimeMs, int8_t executionStep) {
|
||||||
|
ExecutableObjectIF* object = objectManager->get<ExecutableObjectIF>(componentId);
|
||||||
|
if (object != nullptr) {
|
||||||
|
pst.addSlot(componentId, slotTimeMs, executionStep, object, this);
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "Component " << std::hex << componentId <<
|
||||||
|
" not found, not adding it to pst" << std::endl;
|
||||||
|
#endif
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t FixedTimeslotTask::getPeriodMs() const {
|
||||||
|
return pst.getLengthMs();
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t FixedTimeslotTask::checkSequence() const {
|
||||||
|
return pst.checkSequence();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FixedTimeslotTask::taskFunctionality() {
|
||||||
|
/* A local iterator for the Polling Sequence Table is created to find the start time for
|
||||||
|
the first entry. */
|
||||||
|
FixedSlotSequence::SlotListIter it = pst.current;
|
||||||
|
|
||||||
|
/* Initialize the PST with the correct calling task */
|
||||||
|
pst.intializeSequenceAfterTaskCreation();
|
||||||
|
|
||||||
|
/* The start time for the first entry is read. */
|
||||||
|
rtems_interval interval = RtemsBasic::convertMsToTicks(it->pollingTimeMs);
|
||||||
|
RTEMSTaskBase::setAndStartPeriod(interval,&periodId);
|
||||||
|
//The task's "infinite" inner loop is entered.
|
||||||
|
while (1) {
|
||||||
|
if (pst.slotFollowsImmediately()) {
|
||||||
|
/* Do nothing */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* The interval for the next polling slot is selected. */
|
||||||
|
interval = RtemsBasic::convertMsToTicks(this->pst.getIntervalToNextSlotMs());
|
||||||
|
/* The period is checked and restarted with the new interval.
|
||||||
|
If the deadline was missed, the deadlineMissedFunc is called. */
|
||||||
|
rtems_status_code status = RTEMSTaskBase::restartPeriod(interval,periodId);
|
||||||
|
if (status == RTEMS_TIMEOUT) {
|
||||||
|
if (this->deadlineMissedFunc != nullptr) {
|
||||||
|
this->deadlineMissedFunc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* The device handler for this slot is executed and the next one is chosen. */
|
||||||
|
this->pst.executeAndAdvance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms){
|
||||||
|
return RTEMSTaskBase::sleepFor(ms);
|
||||||
|
};
|
81
osal/rtems/FixedTimeslotTask.h
Normal file
81
osal/rtems/FixedTimeslotTask.h
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#ifndef FSFW_OSAL_RTEMS_FIXEDTIMESLOTTASK_H_
|
||||||
|
#define FSFW_OSAL_RTEMS_FIXEDTIMESLOTTASK_H_
|
||||||
|
|
||||||
|
#include "RTEMSTaskBase.h"
|
||||||
|
#include "../../tasks/FixedSlotSequence.h"
|
||||||
|
#include "../../tasks/FixedTimeslotTaskIF.h"
|
||||||
|
|
||||||
|
class FixedTimeslotTask: public RTEMSTaskBase, public FixedTimeslotTaskIF {
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief The standard constructor of the class.
|
||||||
|
* @details
|
||||||
|
* This is the general constructor of the class. In addition to the TaskBase parameters,
|
||||||
|
* the following variables are passed:
|
||||||
|
* @param setDeadlineMissedFunc The function pointer to the deadline missed function
|
||||||
|
* that shall be assigned.
|
||||||
|
* @param getPst The object id of the completely initialized polling sequence.
|
||||||
|
*/
|
||||||
|
FixedTimeslotTask( const char *name, rtems_task_priority setPriority, size_t setStackSize,
|
||||||
|
uint32_t overallPeriod, void (*setDeadlineMissedFunc)());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The destructor of the class.
|
||||||
|
* @details
|
||||||
|
* The destructor frees all heap memory that was allocated on thread initialization
|
||||||
|
* for the PST andthe device handlers. This is done by calling the PST's destructor.
|
||||||
|
*/
|
||||||
|
virtual ~FixedTimeslotTask( void );
|
||||||
|
|
||||||
|
ReturnValue_t startTask( void );
|
||||||
|
/**
|
||||||
|
* This static function can be used as #deadlineMissedFunc.
|
||||||
|
* It counts missedDeadlines and prints the number of missed deadlines every 10th time.
|
||||||
|
*/
|
||||||
|
static void missedDeadlineCounter();
|
||||||
|
/**
|
||||||
|
* A helper variable to count missed deadlines.
|
||||||
|
*/
|
||||||
|
static uint32_t deadlineMissedCount;
|
||||||
|
|
||||||
|
ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep);
|
||||||
|
|
||||||
|
uint32_t getPeriodMs() const;
|
||||||
|
|
||||||
|
ReturnValue_t checkSequence() const;
|
||||||
|
|
||||||
|
ReturnValue_t sleepFor(uint32_t ms);
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* @brief id of the associated OS period
|
||||||
|
*/
|
||||||
|
rtems_id periodId;
|
||||||
|
|
||||||
|
FixedSlotSequence pst;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This attribute holds a function pointer that is executed when a deadline was missed.
|
||||||
|
*
|
||||||
|
* @details
|
||||||
|
* Another function may be announced to determine the actions to perform when a deadline
|
||||||
|
* was missed. Currently, only one function for missing any deadline is allowed.
|
||||||
|
* If not used, it shall be declared NULL.
|
||||||
|
*/
|
||||||
|
void ( *deadlineMissedFunc )( void ) = nullptr;
|
||||||
|
/**
|
||||||
|
* @brief This is the entry point in a new polling thread.
|
||||||
|
* @details This method is the entry point in the new thread
|
||||||
|
*/
|
||||||
|
static rtems_task taskEntryPoint( rtems_task_argument argument );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This function holds the main functionality of the thread.
|
||||||
|
* @details
|
||||||
|
* Holding the main functionality of the task, this method is most important.
|
||||||
|
* It links the functionalities provided by FixedSlotSequence with the OS's system calls to
|
||||||
|
* keep the timing of the periods.
|
||||||
|
*/
|
||||||
|
void taskFunctionality( void );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* FSFW_OSAL_RTEMS_FIXEDTIMESLOTTASK_H_ */
|
@ -1,92 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file MultiObjectTask.cpp
|
|
||||||
* @brief This file defines the MultiObjectTask class.
|
|
||||||
* @date 30.01.2014
|
|
||||||
* @author baetz
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
|
||||||
#include "../../tasks/ExecutableObjectIF.h"
|
|
||||||
#include "MultiObjectTask.h"
|
|
||||||
|
|
||||||
MultiObjectTask::MultiObjectTask(const char *name, rtems_task_priority setPriority,
|
|
||||||
size_t setStack, rtems_interval setPeriod, void (*setDeadlineMissedFunc)()) :
|
|
||||||
TaskBase(setPriority, setStack, name), periodTicks(
|
|
||||||
RtemsBasic::convertMsToTicks(setPeriod)), periodId(0), deadlineMissedFunc(
|
|
||||||
setDeadlineMissedFunc) {
|
|
||||||
}
|
|
||||||
|
|
||||||
MultiObjectTask::~MultiObjectTask(void) {
|
|
||||||
//Do not delete objects, we were responsible for ptrs only.
|
|
||||||
rtems_rate_monotonic_delete(periodId);
|
|
||||||
}
|
|
||||||
rtems_task MultiObjectTask::taskEntryPoint(rtems_task_argument argument) {
|
|
||||||
//The argument is re-interpreted as MultiObjectTask. The Task object is global, so it is found from any place.
|
|
||||||
MultiObjectTask *originalTask(reinterpret_cast<MultiObjectTask*>(argument));
|
|
||||||
originalTask->taskFunctionality();
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MultiObjectTask::startTask() {
|
|
||||||
rtems_status_code status = rtems_task_start(id, MultiObjectTask::taskEntryPoint,
|
|
||||||
rtems_task_argument((void *) this));
|
|
||||||
if (status != RTEMS_SUCCESSFUL) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "ObjectTask::startTask for " << std::hex << this->getId()
|
|
||||||
<< std::dec << " failed." << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
switch(status){
|
|
||||||
case RTEMS_SUCCESSFUL:
|
|
||||||
//ask started successfully
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
default:
|
|
||||||
/* RTEMS_INVALID_ADDRESS - invalid task entry point
|
|
||||||
RTEMS_INVALID_ID - invalid task id
|
|
||||||
RTEMS_INCORRECT_STATE - task not in the dormant state
|
|
||||||
RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot start remote task */
|
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MultiObjectTask::sleepFor(uint32_t ms) {
|
|
||||||
return TaskBase::sleepFor(ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MultiObjectTask::taskFunctionality() {
|
|
||||||
TaskBase::setAndStartPeriod(periodTicks,&periodId);
|
|
||||||
//The task's "infinite" inner loop is entered.
|
|
||||||
while (1) {
|
|
||||||
for (ObjectList::iterator it = objectList.begin();
|
|
||||||
it != objectList.end(); ++it) {
|
|
||||||
(*it)->performOperation();
|
|
||||||
}
|
|
||||||
rtems_status_code status = TaskBase::restartPeriod(periodTicks,periodId);
|
|
||||||
if (status == RTEMS_TIMEOUT) {
|
|
||||||
char nameSpace[8] = { 0 };
|
|
||||||
char* ptr = rtems_object_get_name(getId(), sizeof(nameSpace),
|
|
||||||
nameSpace);
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "ObjectTask: " << ptr << " Deadline missed." << std::endl;
|
|
||||||
#endif
|
|
||||||
if (this->deadlineMissedFunc != nullptr) {
|
|
||||||
this->deadlineMissedFunc();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t MultiObjectTask::addComponent(object_id_t object) {
|
|
||||||
ExecutableObjectIF* newObject = objectManager->get<ExecutableObjectIF>(
|
|
||||||
object);
|
|
||||||
if (newObject == nullptr) {
|
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
|
||||||
}
|
|
||||||
objectList.push_back(newObject);
|
|
||||||
newObject->setTaskIF(this);
|
|
||||||
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t MultiObjectTask::getPeriodMs() const {
|
|
||||||
return RtemsBasic::convertTicksToMs(periodTicks);
|
|
||||||
}
|
|
@ -1,18 +1,20 @@
|
|||||||
#include "Mutex.h"
|
#include "Mutex.h"
|
||||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
#include "../../serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
uint8_t Mutex::count = 0;
|
uint8_t Mutex::count = 0;
|
||||||
|
|
||||||
Mutex::Mutex() :
|
Mutex::Mutex() {
|
||||||
mutexId(0) {
|
|
||||||
rtems_name mutexName = ('M' << 24) + ('T' << 16) + ('X' << 8) + count++;
|
rtems_name mutexName = ('M' << 24) + ('T' << 16) + ('X' << 8) + count++;
|
||||||
rtems_status_code status = rtems_semaphore_create(mutexName, 1,
|
rtems_status_code status = rtems_semaphore_create(mutexName, 1,
|
||||||
RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY, 0,
|
RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY, 0,
|
||||||
&mutexId);
|
&mutexId);
|
||||||
if (status != RTEMS_SUCCESSFUL) {
|
if (status != RTEMS_SUCCESSFUL) {
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
sif::error << "Mutex: creation with name, id " << mutexName << ", " << mutexId
|
sif::error << "Mutex::Mutex: Creation with name, id " << mutexName << ", " << mutexId <<
|
||||||
<< " failed with " << status << std::endl;
|
" failed with " << status << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printError("Mutex::Mutex: Creation with name, id %s, %d failed with %d\n", mutexName,
|
||||||
|
static_cast<int>(mutexId), static_cast<int>(status));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ public:
|
|||||||
ReturnValue_t lockMutex(TimeoutType timeoutType, uint32_t timeoutMs = 0);
|
ReturnValue_t lockMutex(TimeoutType timeoutType, uint32_t timeoutMs = 0);
|
||||||
ReturnValue_t unlockMutex();
|
ReturnValue_t unlockMutex();
|
||||||
private:
|
private:
|
||||||
rtems_id mutexId;
|
rtems_id mutexId = 0;
|
||||||
static uint8_t count;
|
static uint8_t count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "../../ipc/MutexFactory.h"
|
|
||||||
#include "Mutex.h"
|
#include "Mutex.h"
|
||||||
#include "RtemsBasic.h"
|
|
||||||
|
#include "../../ipc/MutexFactory.h"
|
||||||
|
|
||||||
|
|
||||||
MutexFactory* MutexFactory::factoryInstance = new MutexFactory();
|
MutexFactory* MutexFactory::factoryInstance = new MutexFactory();
|
||||||
|
|
||||||
|
83
osal/rtems/PeriodicTask.cpp
Normal file
83
osal/rtems/PeriodicTask.cpp
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#include "PeriodicTask.h"
|
||||||
|
|
||||||
|
#include "../../serviceinterface/ServiceInterface.h"
|
||||||
|
#include "../../tasks/ExecutableObjectIF.h"
|
||||||
|
|
||||||
|
PeriodicTask::PeriodicTask(const char *name, rtems_task_priority setPriority,
|
||||||
|
size_t setStack, rtems_interval setPeriod, void (*setDeadlineMissedFunc)()) :
|
||||||
|
RTEMSTaskBase(setPriority, setStack, name),
|
||||||
|
periodTicks(RtemsBasic::convertMsToTicks(setPeriod)),
|
||||||
|
deadlineMissedFunc(setDeadlineMissedFunc) {
|
||||||
|
}
|
||||||
|
|
||||||
|
PeriodicTask::~PeriodicTask(void) {
|
||||||
|
/* Do not delete objects, we were responsible for pointers only. */
|
||||||
|
rtems_rate_monotonic_delete(periodId);
|
||||||
|
}
|
||||||
|
|
||||||
|
rtems_task PeriodicTask::taskEntryPoint(rtems_task_argument argument) {
|
||||||
|
/* The argument is re-interpreted as MultiObjectTask. The Task object is global,
|
||||||
|
so it is found from any place. */
|
||||||
|
PeriodicTask *originalTask(reinterpret_cast<PeriodicTask*>(argument));
|
||||||
|
return originalTask->taskFunctionality();;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PeriodicTask::startTask() {
|
||||||
|
rtems_status_code status = rtems_task_start(id, PeriodicTask::taskEntryPoint,
|
||||||
|
rtems_task_argument((void *) this));
|
||||||
|
if (status != RTEMS_SUCCESSFUL) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "ObjectTask::startTask for " << std::hex << this->getId()
|
||||||
|
<< std::dec << " failed." << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
switch(status){
|
||||||
|
case RTEMS_SUCCESSFUL:
|
||||||
|
/* Task started successfully */
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
default:
|
||||||
|
/* RTEMS_INVALID_ADDRESS - invalid task entry point
|
||||||
|
RTEMS_INVALID_ID - invalid task id
|
||||||
|
RTEMS_INCORRECT_STATE - task not in the dormant state
|
||||||
|
RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot start remote task */
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PeriodicTask::sleepFor(uint32_t ms) {
|
||||||
|
return RTEMSTaskBase::sleepFor(ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PeriodicTask::taskFunctionality() {
|
||||||
|
RTEMSTaskBase::setAndStartPeriod(periodTicks,&periodId);
|
||||||
|
for (const auto& object: objectList) {
|
||||||
|
object->initializeAfterTaskCreation();
|
||||||
|
}
|
||||||
|
/* The task's "infinite" inner loop is entered. */
|
||||||
|
while (1) {
|
||||||
|
for (const auto& object: objectList) {
|
||||||
|
object->performOperation();
|
||||||
|
}
|
||||||
|
rtems_status_code status = RTEMSTaskBase::restartPeriod(periodTicks,periodId);
|
||||||
|
if (status == RTEMS_TIMEOUT) {
|
||||||
|
if (this->deadlineMissedFunc != nullptr) {
|
||||||
|
this->deadlineMissedFunc();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t PeriodicTask::addComponent(object_id_t object) {
|
||||||
|
ExecutableObjectIF* newObject = objectManager->get<ExecutableObjectIF>(object);
|
||||||
|
if (newObject == nullptr) {
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
objectList.push_back(newObject);
|
||||||
|
newObject->setTaskIF(this);
|
||||||
|
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PeriodicTask::getPeriodMs() const {
|
||||||
|
return RtemsBasic::convertTicksToMs(periodTicks);
|
||||||
|
}
|
@ -1,10 +1,10 @@
|
|||||||
#ifndef FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_
|
#ifndef FSFW_OSAL_RTEMS_PERIODICTASK_H_
|
||||||
#define FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_
|
#define FSFW_OSAL_RTEMS_PERIODICTASK_H_
|
||||||
|
|
||||||
|
#include "RTEMSTaskBase.h"
|
||||||
#include "../../objectmanager/ObjectManagerIF.h"
|
#include "../../objectmanager/ObjectManagerIF.h"
|
||||||
#include "../../tasks/PeriodicTaskIF.h"
|
#include "../../tasks/PeriodicTaskIF.h"
|
||||||
|
|
||||||
#include "TaskBase.h"
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class ExecutableObjectIF;
|
class ExecutableObjectIF;
|
||||||
@ -18,7 +18,7 @@ class ExecutableObjectIF;
|
|||||||
* @author baetz
|
* @author baetz
|
||||||
* @ingroup task_handling
|
* @ingroup task_handling
|
||||||
*/
|
*/
|
||||||
class MultiObjectTask: public TaskBase, public PeriodicTaskIF {
|
class PeriodicTask: public RTEMSTaskBase, public PeriodicTaskIF {
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Standard constructor of the class.
|
* @brief Standard constructor of the class.
|
||||||
@ -35,13 +35,13 @@ public:
|
|||||||
* @param setDeadlineMissedFunc The function pointer to the deadline missed function
|
* @param setDeadlineMissedFunc The function pointer to the deadline missed function
|
||||||
* that shall be assigned.
|
* that shall be assigned.
|
||||||
*/
|
*/
|
||||||
MultiObjectTask(const char *name, rtems_task_priority setPriority, size_t setStack, rtems_interval setPeriod,
|
PeriodicTask(const char *name, rtems_task_priority setPriority, size_t setStack,
|
||||||
void (*setDeadlineMissedFunc)());
|
rtems_interval setPeriod, void (*setDeadlineMissedFunc)());
|
||||||
/**
|
/**
|
||||||
* @brief Currently, the executed object's lifetime is not coupled with the task object's
|
* @brief Currently, the executed object's lifetime is not coupled with the task object's
|
||||||
* lifetime, so the destructor is empty.
|
* lifetime, so the destructor is empty.
|
||||||
*/
|
*/
|
||||||
virtual ~MultiObjectTask(void);
|
virtual ~PeriodicTask(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The method to start the task.
|
* @brief The method to start the task.
|
||||||
@ -76,7 +76,7 @@ protected:
|
|||||||
/**
|
/**
|
||||||
* @brief id of the associated OS period
|
* @brief id of the associated OS period
|
||||||
*/
|
*/
|
||||||
rtems_id periodId;
|
rtems_id periodId = 0;
|
||||||
/**
|
/**
|
||||||
* @brief The pointer to the deadline-missed function.
|
* @brief The pointer to the deadline-missed function.
|
||||||
* @details This pointer stores the function that is executed if the task's deadline is missed.
|
* @details This pointer stores the function that is executed if the task's deadline is missed.
|
||||||
@ -104,4 +104,4 @@ protected:
|
|||||||
void taskFunctionality(void);
|
void taskFunctionality(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_OSAL_RTEMS_MULTIOBJECTTASK_H_ */
|
#endif /* FSFW_OSAL_RTEMS_PERIODICTASK_H_ */
|
@ -1,131 +0,0 @@
|
|||||||
#include "../../tasks/FixedSequenceSlot.h"
|
|
||||||
#include "../../objectmanager/SystemObjectIF.h"
|
|
||||||
#include "../../objectmanager/ObjectManagerIF.h"
|
|
||||||
#include "PollingTask.h"
|
|
||||||
#include "RtemsBasic.h"
|
|
||||||
#include "../../returnvalues/HasReturnvaluesIF.h"
|
|
||||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
|
||||||
#include <rtems/bspIo.h>
|
|
||||||
#include <rtems/rtems/ratemon.h>
|
|
||||||
#include <rtems/rtems/status.h>
|
|
||||||
#include <rtems/rtems/tasks.h>
|
|
||||||
#include <rtems/rtems/types.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <sys/_stdint.h>
|
|
||||||
#include <iostream>
|
|
||||||
#include <list>
|
|
||||||
|
|
||||||
uint32_t PollingTask::deadlineMissedCount = 0;
|
|
||||||
|
|
||||||
PollingTask::PollingTask(const char *name, rtems_task_priority setPriority,
|
|
||||||
size_t setStack, uint32_t setOverallPeriod,
|
|
||||||
void (*setDeadlineMissedFunc)()) :
|
|
||||||
TaskBase(setPriority, setStack, name), periodId(0), pst(
|
|
||||||
setOverallPeriod) {
|
|
||||||
// All additional attributes are applied to the object.
|
|
||||||
this->deadlineMissedFunc = setDeadlineMissedFunc;
|
|
||||||
}
|
|
||||||
|
|
||||||
PollingTask::~PollingTask() {
|
|
||||||
}
|
|
||||||
|
|
||||||
rtems_task PollingTask::taskEntryPoint(rtems_task_argument argument) {
|
|
||||||
|
|
||||||
//The argument is re-interpreted as PollingTask.
|
|
||||||
PollingTask *originalTask(reinterpret_cast<PollingTask*>(argument));
|
|
||||||
//The task's functionality is called.
|
|
||||||
originalTask->taskFunctionality();
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::debug << "Polling task " << originalTask->getId()
|
|
||||||
<< " returned from taskFunctionality." << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void PollingTask::missedDeadlineCounter() {
|
|
||||||
PollingTask::deadlineMissedCount++;
|
|
||||||
if (PollingTask::deadlineMissedCount % 10 == 0) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "PST missed " << PollingTask::deadlineMissedCount
|
|
||||||
<< " deadlines." << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t PollingTask::startTask() {
|
|
||||||
rtems_status_code status = rtems_task_start(id, PollingTask::taskEntryPoint,
|
|
||||||
rtems_task_argument((void *) this));
|
|
||||||
if (status != RTEMS_SUCCESSFUL) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "PollingTask::startTask for " << std::hex << this->getId()
|
|
||||||
<< std::dec << " failed." << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
switch(status){
|
|
||||||
case RTEMS_SUCCESSFUL:
|
|
||||||
//ask started successfully
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
default:
|
|
||||||
/* RTEMS_INVALID_ADDRESS - invalid task entry point
|
|
||||||
RTEMS_INVALID_ID - invalid task id
|
|
||||||
RTEMS_INCORRECT_STATE - task not in the dormant state
|
|
||||||
RTEMS_ILLEGAL_ON_REMOTE_OBJECT - cannot start remote task */
|
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t PollingTask::addSlot(object_id_t componentId,
|
|
||||||
uint32_t slotTimeMs, int8_t executionStep) {
|
|
||||||
ExecutableObjectIF* object = objectManager->get<ExecutableObjectIF>(componentId);
|
|
||||||
if (object != nullptr) {
|
|
||||||
pst.addSlot(componentId, slotTimeMs, executionStep, object, this);
|
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "Component " << std::hex << componentId <<
|
|
||||||
" not found, not adding it to pst" << std::endl;
|
|
||||||
#endif
|
|
||||||
return HasReturnvaluesIF::RETURN_FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t PollingTask::getPeriodMs() const {
|
|
||||||
return pst.getLengthMs();
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t PollingTask::checkSequence() const {
|
|
||||||
return pst.checkSequence();
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <rtems/io.h>
|
|
||||||
|
|
||||||
void PollingTask::taskFunctionality() {
|
|
||||||
// A local iterator for the Polling Sequence Table is created to find the start time for the first entry.
|
|
||||||
FixedSlotSequence::SlotListIter it = pst.current;
|
|
||||||
|
|
||||||
//The start time for the first entry is read.
|
|
||||||
rtems_interval interval = RtemsBasic::convertMsToTicks(it->pollingTimeMs);
|
|
||||||
TaskBase::setAndStartPeriod(interval,&periodId);
|
|
||||||
//The task's "infinite" inner loop is entered.
|
|
||||||
while (1) {
|
|
||||||
if (pst.slotFollowsImmediately()) {
|
|
||||||
//Do nothing
|
|
||||||
} else {
|
|
||||||
//The interval for the next polling slot is selected.
|
|
||||||
interval = RtemsBasic::convertMsToTicks(this->pst.getIntervalToNextSlotMs());
|
|
||||||
//The period is checked and restarted with the new interval.
|
|
||||||
//If the deadline was missed, the deadlineMissedFunc is called.
|
|
||||||
rtems_status_code status = TaskBase::restartPeriod(interval,periodId);
|
|
||||||
if (status == RTEMS_TIMEOUT) {
|
|
||||||
if (this->deadlineMissedFunc != nullptr) {
|
|
||||||
this->deadlineMissedFunc();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//The device handler for this slot is executed and the next one is chosen.
|
|
||||||
this->pst.executeAndAdvance();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t PollingTask::sleepFor(uint32_t ms){
|
|
||||||
return TaskBase::sleepFor(ms);
|
|
||||||
};
|
|
@ -1,85 +0,0 @@
|
|||||||
#ifndef FSFW_OSAL_RTEMS_POLLINGTASK_H_
|
|
||||||
#define FSFW_OSAL_RTEMS_POLLINGTASK_H_
|
|
||||||
|
|
||||||
#include "../../tasks/FixedSlotSequence.h"
|
|
||||||
#include "../../tasks/FixedTimeslotTaskIF.h"
|
|
||||||
#include "TaskBase.h"
|
|
||||||
|
|
||||||
class PollingTask: public TaskBase, public FixedTimeslotTaskIF {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief The standard constructor of the class.
|
|
||||||
*
|
|
||||||
* @details This is the general constructor of the class. In addition to the TaskBase parameters,
|
|
||||||
* the following variables are passed:
|
|
||||||
*
|
|
||||||
* @param (*setDeadlineMissedFunc)() The function pointer to the deadline missed function that shall be assigned.
|
|
||||||
*
|
|
||||||
* @param getPst The object id of the completely initialized polling sequence.
|
|
||||||
*/
|
|
||||||
PollingTask( const char *name, rtems_task_priority setPriority, size_t setStackSize, uint32_t overallPeriod, void (*setDeadlineMissedFunc)());
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The destructor of the class.
|
|
||||||
*
|
|
||||||
* @details The destructor frees all heap memory that was allocated on thread initialization for the PST and
|
|
||||||
* the device handlers. This is done by calling the PST's destructor.
|
|
||||||
*/
|
|
||||||
virtual ~PollingTask( void );
|
|
||||||
|
|
||||||
ReturnValue_t startTask( void );
|
|
||||||
/**
|
|
||||||
* This static function can be used as #deadlineMissedFunc.
|
|
||||||
* It counts missedDeadlines and prints the number of missed deadlines every 10th time.
|
|
||||||
*/
|
|
||||||
static void missedDeadlineCounter();
|
|
||||||
/**
|
|
||||||
* A helper variable to count missed deadlines.
|
|
||||||
*/
|
|
||||||
static uint32_t deadlineMissedCount;
|
|
||||||
|
|
||||||
ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep);
|
|
||||||
|
|
||||||
uint32_t getPeriodMs() const;
|
|
||||||
|
|
||||||
ReturnValue_t checkSequence() const;
|
|
||||||
|
|
||||||
ReturnValue_t sleepFor(uint32_t ms);
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* @brief id of the associated OS period
|
|
||||||
*/
|
|
||||||
rtems_id periodId;
|
|
||||||
|
|
||||||
FixedSlotSequence pst;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This attribute holds a function pointer that is executed when a deadline was missed.
|
|
||||||
*
|
|
||||||
* @details Another function may be announced to determine the actions to perform when a deadline was missed.
|
|
||||||
* Currently, only one function for missing any deadline is allowed.
|
|
||||||
* If not used, it shall be declared NULL.
|
|
||||||
*/
|
|
||||||
void ( *deadlineMissedFunc )( void );
|
|
||||||
/**
|
|
||||||
* @brief This is the entry point in a new polling thread.
|
|
||||||
*
|
|
||||||
* @details This method, that is the generalOSAL::checkAndRestartPeriod( this->periodId, interval ); entry point in the new thread, is here set to generate
|
|
||||||
* and link the Polling Sequence Table to the thread object and start taskFunctionality()
|
|
||||||
* on success. If operation of the task is ended for some reason,
|
|
||||||
* the destructor is called to free allocated memory.
|
|
||||||
*/
|
|
||||||
static rtems_task taskEntryPoint( rtems_task_argument argument );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This function holds the main functionality of the thread.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @details Holding the main functionality of the task, this method is most important.
|
|
||||||
* It links the functionalities provided by FixedSlotSequence with the OS's System Calls
|
|
||||||
* to keep the timing of the periods.
|
|
||||||
*/
|
|
||||||
void taskFunctionality( void );
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* FSFW_OSAL_RTEMS_POLLINGTASK_H_ */
|
|
@ -1,9 +1,9 @@
|
|||||||
#include "../../serviceinterface/ServiceInterfaceStream.h"
|
#include "RTEMSTaskBase.h"
|
||||||
#include "TaskBase.h"
|
#include "../../serviceinterface/ServiceInterface.h"
|
||||||
|
|
||||||
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE=RTEMS_MINIMUM_STACK_SIZE;
|
const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = RTEMS_MINIMUM_STACK_SIZE;
|
||||||
|
|
||||||
TaskBase::TaskBase(rtems_task_priority set_priority, size_t stack_size,
|
RTEMSTaskBase::RTEMSTaskBase(rtems_task_priority set_priority, size_t stack_size,
|
||||||
const char *name) {
|
const char *name) {
|
||||||
rtems_name osalName = 0;
|
rtems_name osalName = 0;
|
||||||
for (uint8_t i = 0; i < 4; i++) {
|
for (uint8_t i = 0; i < 4; i++) {
|
||||||
@ -14,7 +14,7 @@ TaskBase::TaskBase(rtems_task_priority set_priority, size_t stack_size,
|
|||||||
}
|
}
|
||||||
//The task is created with the operating system's system call.
|
//The task is created with the operating system's system call.
|
||||||
rtems_status_code status = RTEMS_UNSATISFIED;
|
rtems_status_code status = RTEMS_UNSATISFIED;
|
||||||
if (set_priority >= 0 && set_priority <= 99) {
|
if (set_priority <= 99) {
|
||||||
status = rtems_task_create(osalName,
|
status = rtems_task_create(osalName,
|
||||||
(0xFF - 2 * set_priority), stack_size,
|
(0xFF - 2 * set_priority), stack_size,
|
||||||
RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR,
|
RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR,
|
||||||
@ -31,21 +31,21 @@ TaskBase::TaskBase(rtems_task_priority set_priority, size_t stack_size,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TaskBase::~TaskBase() {
|
RTEMSTaskBase::~RTEMSTaskBase() {
|
||||||
rtems_task_delete(id);
|
rtems_task_delete(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
rtems_id TaskBase::getId() {
|
rtems_id RTEMSTaskBase::getId() {
|
||||||
return this->id;
|
return this->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t TaskBase::sleepFor(uint32_t ms) {
|
ReturnValue_t RTEMSTaskBase::sleepFor(uint32_t ms) {
|
||||||
rtems_status_code status = rtems_task_wake_after(RtemsBasic::convertMsToTicks(ms));
|
rtems_status_code status = rtems_task_wake_after(RtemsBasic::convertMsToTicks(ms));
|
||||||
return convertReturnCode(status);
|
return convertReturnCode(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ReturnValue_t TaskBase::convertReturnCode(rtems_status_code inValue) {
|
ReturnValue_t RTEMSTaskBase::convertReturnCode(rtems_status_code inValue) {
|
||||||
switch (inValue) {
|
switch (inValue) {
|
||||||
case RTEMS_SUCCESSFUL:
|
case RTEMS_SUCCESSFUL:
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
@ -68,7 +68,7 @@ ReturnValue_t TaskBase::convertReturnCode(rtems_status_code inValue) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ReturnValue_t TaskBase::setAndStartPeriod(rtems_interval period, rtems_id *periodId) {
|
ReturnValue_t RTEMSTaskBase::setAndStartPeriod(rtems_interval period, rtems_id *periodId) {
|
||||||
rtems_name periodName = (('P' << 24) + ('e' << 16) + ('r' << 8) + 'd');
|
rtems_name periodName = (('P' << 24) + ('e' << 16) + ('r' << 8) + 'd');
|
||||||
rtems_status_code status = rtems_rate_monotonic_create(periodName, periodId);
|
rtems_status_code status = rtems_rate_monotonic_create(periodName, periodId);
|
||||||
if (status == RTEMS_SUCCESSFUL) {
|
if (status == RTEMS_SUCCESSFUL) {
|
||||||
@ -77,7 +77,7 @@ ReturnValue_t TaskBase::setAndStartPeriod(rtems_interval period, rtems_id *perio
|
|||||||
return convertReturnCode(status);
|
return convertReturnCode(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
rtems_status_code TaskBase::restartPeriod(rtems_interval period, rtems_id periodId){
|
rtems_status_code RTEMSTaskBase::restartPeriod(rtems_interval period, rtems_id periodId){
|
||||||
//This is necessary to avoid a call with period = 0, which does not start the period.
|
//This is necessary to avoid a call with period = 0, which does not start the period.
|
||||||
rtems_status_code status = rtems_rate_monotonic_period(periodId, period + 1);
|
rtems_status_code status = rtems_rate_monotonic_period(periodId, period + 1);
|
||||||
return status;
|
return status;
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef FSFW_OSAL_RTEMS_TASKBASE_H_
|
#ifndef FSFW_OSAL_RTEMS_RTEMSTASKBASE_H_
|
||||||
#define FSFW_OSAL_RTEMS_TASKBASE_H_
|
#define FSFW_OSAL_RTEMS_RTEMSTASKBASE_H_
|
||||||
|
|
||||||
#include "RtemsBasic.h"
|
#include "RtemsBasic.h"
|
||||||
#include "../../tasks/PeriodicTaskIF.h"
|
#include "../../tasks/PeriodicTaskIF.h"
|
||||||
@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
* @details Task creation base class for rtems.
|
* @details Task creation base class for rtems.
|
||||||
*/
|
*/
|
||||||
class TaskBase {
|
class RTEMSTaskBase {
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* @brief The class stores the task id it got assigned from the operating system in this attribute.
|
* @brief The class stores the task id it got assigned from the operating system in this attribute.
|
||||||
@ -26,11 +26,11 @@ public:
|
|||||||
* @param stack_size The stack size reserved by the operating system for the task.
|
* @param stack_size The stack size reserved by the operating system for the task.
|
||||||
* @param nam The name of the Task, as a null-terminated String. Currently max 4 chars supported (excluding Null-terminator), rest will be truncated
|
* @param nam The name of the Task, as a null-terminated String. Currently max 4 chars supported (excluding Null-terminator), rest will be truncated
|
||||||
*/
|
*/
|
||||||
TaskBase( rtems_task_priority priority, size_t stack_size, const char *name);
|
RTEMSTaskBase( rtems_task_priority priority, size_t stack_size, const char *name);
|
||||||
/**
|
/**
|
||||||
* @brief In the destructor, the created task is deleted.
|
* @brief In the destructor, the created task is deleted.
|
||||||
*/
|
*/
|
||||||
virtual ~TaskBase();
|
virtual ~RTEMSTaskBase();
|
||||||
/**
|
/**
|
||||||
* @brief This method returns the task id of this class.
|
* @brief This method returns the task id of this class.
|
||||||
*/
|
*/
|
||||||
@ -44,4 +44,4 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* FSFW_OSAL_RTEMS_TASKBASE_H_ */
|
#endif /* FSFW_OSAL_RTEMS_RTEMSTASKBASE_H_ */
|
@ -1,5 +1,6 @@
|
|||||||
#include "RtemsBasic.h"
|
#include "RtemsBasic.h"
|
||||||
|
|
||||||
|
// TODO: Can this be removed?
|
||||||
|
|
||||||
//ReturnValue_t RtemsBasic::convertReturnCode(rtems_status_code inValue) {
|
//ReturnValue_t RtemsBasic::convertReturnCode(rtems_status_code inValue) {
|
||||||
// if (inValue == RTEMS_SUCCESSFUL) {
|
// if (inValue == RTEMS_SUCCESSFUL) {
|
||||||
|
@ -2,12 +2,13 @@
|
|||||||
#define FSFW_OSAL_RTEMS_RTEMSBASIC_H_
|
#define FSFW_OSAL_RTEMS_RTEMSBASIC_H_
|
||||||
|
|
||||||
#include "../../returnvalues/HasReturnvaluesIF.h"
|
#include "../../returnvalues/HasReturnvaluesIF.h"
|
||||||
|
|
||||||
#include <rtems.h>
|
#include <rtems.h>
|
||||||
#include <rtems/libio.h>
|
#include <rtems/libio.h>
|
||||||
#include <rtems/error.h>
|
#include <rtems/error.h>
|
||||||
#include <rtems/stackchk.h>
|
#include <rtems/stackchk.h>
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
class RtemsBasic {
|
class RtemsBasic {
|
||||||
public:
|
public:
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
#include "../../tasks/TaskFactory.h"
|
#include "FixedTimeslotTask.h"
|
||||||
#include "MultiObjectTask.h"
|
#include "PeriodicTask.h"
|
||||||
#include "PollingTask.h"
|
|
||||||
#include "InitTask.h"
|
#include "InitTask.h"
|
||||||
#include "RtemsBasic.h"
|
#include "RtemsBasic.h"
|
||||||
|
|
||||||
|
#include "../../tasks/TaskFactory.h"
|
||||||
#include "../../returnvalues/HasReturnvaluesIF.h"
|
#include "../../returnvalues/HasReturnvaluesIF.h"
|
||||||
|
|
||||||
//TODO: Different variant than the lazy loading in QueueFactory. What's better and why?
|
//TODO: Different variant than the lazy loading in QueueFactory. What's better and why?
|
||||||
@ -15,15 +16,21 @@ TaskFactory* TaskFactory::instance() {
|
|||||||
return TaskFactory::factoryInstance;
|
return TaskFactory::factoryInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_,TaskPriority taskPriority_,TaskStackSize stackSize_,TaskPeriod periodInSeconds_,TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_, TaskPriority taskPriority_,
|
||||||
|
TaskStackSize stackSize_,TaskPeriod periodInSeconds_,
|
||||||
|
TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
||||||
rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond();
|
rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond();
|
||||||
|
|
||||||
return static_cast<PeriodicTaskIF*>(new MultiObjectTask(name_,taskPriority_,stackSize_,taskPeriod,deadLineMissedFunction_));
|
return static_cast<PeriodicTaskIF*>(new PeriodicTask(name_, taskPriority_, stackSize_,
|
||||||
|
taskPeriod,deadLineMissedFunction_));
|
||||||
}
|
}
|
||||||
|
|
||||||
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(TaskName name_,TaskPriority taskPriority_,TaskStackSize stackSize_,TaskPeriod periodInSeconds_,TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(TaskName name_,
|
||||||
|
TaskPriority taskPriority_,TaskStackSize stackSize_,TaskPeriod periodInSeconds_,
|
||||||
|
TaskDeadlineMissedFunction deadLineMissedFunction_) {
|
||||||
rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond();
|
rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond();
|
||||||
return static_cast<FixedTimeslotTaskIF*>(new PollingTask(name_,taskPriority_,stackSize_,taskPeriod,deadLineMissedFunction_));
|
return static_cast<FixedTimeslotTaskIF*>(new FixedTimeslotTask(name_, taskPriority_,
|
||||||
|
stackSize_, taskPeriod, deadLineMissedFunction_));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) {
|
ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) {
|
||||||
|
@ -52,9 +52,8 @@ public:
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t getFullParameterId(uint8_t domainId,
|
static uint32_t getFullParameterId(uint8_t domainId, uint8_t uniqueId, uint16_t linearIndex) {
|
||||||
uint8_t uniqueIdentifier, uint16_t linearIndex) {
|
return (domainId << 24) + (uniqueId << 16) + linearIndex;
|
||||||
return (domainId << 24) + (uniqueIdentifier << 16) + linearIndex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~HasParametersIF() {}
|
virtual ~HasParametersIF() {}
|
||||||
@ -74,9 +73,9 @@ public:
|
|||||||
* matrix indexes.
|
* matrix indexes.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t getParameter(uint8_t domainId,
|
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
|
||||||
uint16_t uniqueIdentifier, ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex) = 0;
|
uint16_t startAtIndex) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_PARAMETERS_HASPARAMETERSIF_H_ */
|
#endif /* FSFW_PARAMETERS_HASPARAMETERSIF_H_ */
|
||||||
|
@ -90,7 +90,7 @@ ReturnValue_t ParameterHelper::sendParameter(MessageQueueId_t to, uint32_t id,
|
|||||||
const ParameterWrapper* description) {
|
const ParameterWrapper* description) {
|
||||||
size_t serializedSize = description->getSerializedSize();
|
size_t serializedSize = description->getSerializedSize();
|
||||||
|
|
||||||
uint8_t *storeElement;
|
uint8_t *storeElement = nullptr;
|
||||||
store_address_t address;
|
store_address_t address;
|
||||||
|
|
||||||
ReturnValue_t result = storage->getFreeElement(&address, serializedSize,
|
ReturnValue_t result = storage->getFreeElement(&address, serializedSize,
|
||||||
|
@ -38,7 +38,7 @@ void ParameterMessage::setParameterLoadCommand(CommandMessage* message,
|
|||||||
store_address_t ParameterMessage::getParameterLoadCommand(
|
store_address_t ParameterMessage::getParameterLoadCommand(
|
||||||
const CommandMessage *message, ParameterId_t* parameterId, uint8_t *ptc,
|
const CommandMessage *message, ParameterId_t* parameterId, uint8_t *ptc,
|
||||||
uint8_t *pfc, uint8_t *rows, uint8_t *columns) {
|
uint8_t *pfc, uint8_t *rows, uint8_t *columns) {
|
||||||
*parameterId = message->getParameter2();
|
*parameterId = message->getParameter();
|
||||||
uint32_t packedParamSettings = message->getParameter3();
|
uint32_t packedParamSettings = message->getParameter3();
|
||||||
*ptc = packedParamSettings >> 24 & 0xff;
|
*ptc = packedParamSettings >> 24 & 0xff;
|
||||||
*pfc = packedParamSettings >> 16 & 0xff;
|
*pfc = packedParamSettings >> 16 & 0xff;
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
#include "ParameterWrapper.h"
|
#include "ParameterWrapper.h"
|
||||||
|
#include <FSFWConfig.h>
|
||||||
|
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||||
|
|
||||||
ParameterWrapper::ParameterWrapper() :
|
ParameterWrapper::ParameterWrapper() :
|
||||||
pointsToStream(false), type(Type::UNKNOWN_TYPE) {
|
pointsToStream(false), type(Type::UNKNOWN_TYPE) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ParameterWrapper::ParameterWrapper(Type type, uint8_t rows, uint8_t columns,
|
ParameterWrapper::ParameterWrapper(Type type, uint8_t rows, uint8_t columns,
|
||||||
void *data) :
|
void *data):
|
||||||
pointsToStream(false), type(type), rows(rows), columns(columns),
|
pointsToStream(false), type(type), rows(rows), columns(columns),
|
||||||
data(data), readonlyData(data) {
|
data(data), readonlyData(data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ParameterWrapper::ParameterWrapper(Type type, uint8_t rows, uint8_t columns,
|
ParameterWrapper::ParameterWrapper(Type type, uint8_t rows, uint8_t columns,
|
||||||
const void *data) :
|
const void *data):
|
||||||
pointsToStream(false), type(type), rows(rows), columns(columns),
|
pointsToStream(false), type(type), rows(rows), columns(columns),
|
||||||
data(nullptr), readonlyData(data) {
|
data(nullptr), readonlyData(data) {
|
||||||
}
|
}
|
||||||
@ -40,8 +42,8 @@ ReturnValue_t ParameterWrapper::serialize(uint8_t **buffer, size_t *size,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//serialize uses readonlyData, as it is always valid
|
/* serialize uses readonlyData, as it is always valid */
|
||||||
if (readonlyData == NULL) {
|
if (readonlyData == nullptr) {
|
||||||
return NOT_SET;
|
return NOT_SET;
|
||||||
}
|
}
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -75,7 +77,7 @@ ReturnValue_t ParameterWrapper::serialize(uint8_t **buffer, size_t *size,
|
|||||||
result = serializeData<double>(buffer, size, maxSize, streamEndianness);
|
result = serializeData<double>(buffer, size, maxSize, streamEndianness);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
result = UNKNOW_DATATYPE;
|
result = UNKNOWN_DATATYPE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -220,22 +222,48 @@ ReturnValue_t ParameterWrapper::set(const uint8_t *stream, size_t streamSize,
|
|||||||
|
|
||||||
ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
|
ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
|
||||||
uint16_t startWritingAtIndex) {
|
uint16_t startWritingAtIndex) {
|
||||||
// TODO: Optional diagnostic output (which can be disabled in FSFWConfig)
|
|
||||||
// to determined faulty implementations and configuration errors quickly.
|
|
||||||
if (data == nullptr) {
|
if (data == nullptr) {
|
||||||
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "ParameterWrapper::copyFrom: Called on read-only variable!" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("ParameterWrapper::copyFrom: Called on read-only variable!\n");
|
||||||
|
#endif
|
||||||
|
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||||
return READONLY;
|
return READONLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (from->readonlyData == nullptr) {
|
if (from->readonlyData == nullptr) {
|
||||||
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "ParameterWrapper::copyFrom: Source not set!" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("ParameterWrapper::copyFrom: Source not set!\n");
|
||||||
|
#endif
|
||||||
|
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||||
return SOURCE_NOT_SET;
|
return SOURCE_NOT_SET;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type != from->type) {
|
if (type != from->type) {
|
||||||
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "ParameterWrapper::copyFrom: Datatype missmatch!" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("ParameterWrapper::copyFrom: Datatype missmatch!\n");
|
||||||
|
#endif
|
||||||
|
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||||
return DATATYPE_MISSMATCH;
|
return DATATYPE_MISSMATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The smallest allowed value for rows and columns is one.
|
// The smallest allowed value for rows and columns is one.
|
||||||
if(rows == 0 or columns == 0) {
|
if(rows == 0 or columns == 0) {
|
||||||
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "ParameterWrapper::copyFrom: Columns or rows zero!" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("ParameterWrapper::copyFrom: Columns or rows zero!\n");
|
||||||
|
#endif
|
||||||
|
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||||
return COLUMN_OR_ROWS_ZERO;
|
return COLUMN_OR_ROWS_ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,7 +317,7 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper *from,
|
|||||||
from->readonlyData, from->rows, from->columns);
|
from->readonlyData, from->rows, from->columns);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
result = UNKNOW_DATATYPE;
|
result = UNKNOWN_DATATYPE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,14 +8,23 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief This wrapper encapsulates the access to parameters provided by HasParametersIF.
|
||||||
* @details
|
* @details
|
||||||
|
* This wrapper is used by the ParameterHelper to interface with the on-board parameters
|
||||||
|
* exposed by the software via the HasParametersIF. A handle of this wrapper is passed
|
||||||
|
* to the user which then can be used to set or dump the parameters.
|
||||||
|
*
|
||||||
|
* The wrapper provides a set of setter functions. The user should call those setter functions,
|
||||||
|
* supplying an address to the local parameters. The user can also deserialize or
|
||||||
|
* serialize the parameter data. Please note that this will also serialize and deserialize
|
||||||
|
* the parameter information field (4 bytes) containing the ECSS PTC, PFC and rows and columns
|
||||||
|
* number.
|
||||||
*/
|
*/
|
||||||
class ParameterWrapper: public SerializeIF {
|
class ParameterWrapper: public SerializeIF {
|
||||||
friend class DataPoolParameterWrapper;
|
friend class DataPoolParameterWrapper;
|
||||||
public:
|
public:
|
||||||
static const uint8_t INTERFACE_ID = CLASS_ID::PARAMETER_WRAPPER;
|
static const uint8_t INTERFACE_ID = CLASS_ID::PARAMETER_WRAPPER;
|
||||||
static const ReturnValue_t UNKNOW_DATATYPE = MAKE_RETURN_CODE(0x01);
|
static const ReturnValue_t UNKNOWN_DATATYPE = MAKE_RETURN_CODE(0x01);
|
||||||
static const ReturnValue_t DATATYPE_MISSMATCH = MAKE_RETURN_CODE(0x02);
|
static const ReturnValue_t DATATYPE_MISSMATCH = MAKE_RETURN_CODE(0x02);
|
||||||
static const ReturnValue_t READONLY = MAKE_RETURN_CODE(0x03);
|
static const ReturnValue_t READONLY = MAKE_RETURN_CODE(0x03);
|
||||||
static const ReturnValue_t TOO_BIG = MAKE_RETURN_CODE(0x04);
|
static const ReturnValue_t TOO_BIG = MAKE_RETURN_CODE(0x04);
|
||||||
@ -26,8 +35,7 @@ public:
|
|||||||
|
|
||||||
ParameterWrapper();
|
ParameterWrapper();
|
||||||
ParameterWrapper(Type type, uint8_t rows, uint8_t columns, void *data);
|
ParameterWrapper(Type type, uint8_t rows, uint8_t columns, void *data);
|
||||||
ParameterWrapper(Type type, uint8_t rows, uint8_t columns,
|
ParameterWrapper(Type type, uint8_t rows, uint8_t columns, const void *data);
|
||||||
const void *data);
|
|
||||||
virtual ~ParameterWrapper();
|
virtual ~ParameterWrapper();
|
||||||
|
|
||||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
|
||||||
@ -77,11 +85,23 @@ public:
|
|||||||
this->pointsToStream = false;
|
this->pointsToStream = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter function for scalar non-const entries
|
||||||
|
* @tparam T
|
||||||
|
* @param member
|
||||||
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void set(T& member) {
|
void set(T& member) {
|
||||||
this->set(&member, 1, 1);
|
this->set(&member, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setter function for scalar const entries.
|
||||||
|
* TODO: This is confusing, it should not be called set. Maybe we should call all functions
|
||||||
|
* assign instead?
|
||||||
|
* @tparam T
|
||||||
|
* @param readonlyMember
|
||||||
|
*/
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void set(const T& readonlyMember) {
|
void set(const T& readonlyMember) {
|
||||||
this->set(&readonlyMember, 1, 1);
|
this->set(&readonlyMember, 1, 1);
|
||||||
@ -89,12 +109,16 @@ public:
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void setVector(T& member) {
|
void setVector(T& member) {
|
||||||
this->set(member, sizeof(member)/sizeof(member[0]), 1);
|
/* For a vector entry, the number of rows will be one
|
||||||
|
(left to right, top to bottom indexing) */
|
||||||
|
this->set(member, 1, sizeof(member) / sizeof(member[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void setVector(const T& member) {
|
void setVector(const T& member) {
|
||||||
this->set(member, 1, sizeof(member)/sizeof(member[0]));
|
/* For a vector entry, the number of rows will be one
|
||||||
|
(left to right, top to bottom indexing) */
|
||||||
|
this->set(member, 1, sizeof(member) / sizeof(member[0]));
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void setMatrix(T& member) {
|
void setMatrix(T& member) {
|
||||||
|
@ -210,15 +210,15 @@ void Fuse::setDataPoolEntriesInvalid() {
|
|||||||
set.commit();
|
set.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Fuse::getParameter(uint8_t domainId, uint16_t parameterId,
|
ReturnValue_t Fuse::getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
||||||
uint16_t startAtIndex) {
|
uint16_t startAtIndex) {
|
||||||
ReturnValue_t result = currentLimit.getParameter(domainId, parameterId,
|
ReturnValue_t result = currentLimit.getParameter(domainId, uniqueId,
|
||||||
parameterWrapper, newValues, startAtIndex);
|
parameterWrapper, newValues, startAtIndex);
|
||||||
if (result != INVALID_DOMAIN_ID) {
|
if (result != INVALID_DOMAIN_ID) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = powerMonitor.getParameter(domainId, parameterId, parameterWrapper,
|
result = powerMonitor.getParameter(domainId, uniqueId, parameterWrapper,
|
||||||
newValues, startAtIndex);
|
newValues, startAtIndex);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -62,9 +62,9 @@ public:
|
|||||||
ReturnValue_t setHealth(HealthState health);
|
ReturnValue_t setHealth(HealthState health);
|
||||||
HasHealthIF::HealthState getHealth();
|
HasHealthIF::HealthState getHealth();
|
||||||
|
|
||||||
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
uint16_t startAtIndex);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t oldFuseState;
|
uint8_t oldFuseState;
|
||||||
|
@ -61,13 +61,13 @@ ReturnValue_t PowerComponent::deSerialize(const uint8_t** buffer, size_t* size,
|
|||||||
return SerializeAdapter::deSerialize(&max, buffer, size, streamEndianness);
|
return SerializeAdapter::deSerialize(&max, buffer, size, streamEndianness);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PowerComponent::getParameter(uint8_t domainId,
|
ReturnValue_t PowerComponent::getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
uint16_t parameterId, ParameterWrapper* parameterWrapper,
|
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
||||||
const ParameterWrapper* newValues, uint16_t startAtIndex) {
|
uint16_t startAtIndex) {
|
||||||
if (domainId != moduleId) {
|
if (domainId != moduleId) {
|
||||||
return INVALID_DOMAIN_ID;
|
return INVALID_DOMAIN_ID;
|
||||||
}
|
}
|
||||||
switch (parameterId) {
|
switch (uniqueId) {
|
||||||
case 0:
|
case 0:
|
||||||
parameterWrapper->set<>(min);
|
parameterWrapper->set<>(min);
|
||||||
break;
|
break;
|
||||||
|
@ -31,9 +31,9 @@ public:
|
|||||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||||
Endianness streamEndianness) override;
|
Endianness streamEndianness) override;
|
||||||
|
|
||||||
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
uint16_t startAtIndex);
|
||||||
private:
|
private:
|
||||||
const object_id_t deviceObjectId = objects::NO_OBJECT;
|
const object_id_t deviceObjectId = objects::NO_OBJECT;
|
||||||
const uint8_t switchId1;
|
const uint8_t switchId1;
|
||||||
|
@ -119,15 +119,15 @@ HasHealthIF::HealthState PowerSensor::getHealth() {
|
|||||||
return healthHelper.getHealth();
|
return healthHelper.getHealth();
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PowerSensor::getParameter(uint8_t domainId, uint16_t parameterId,
|
ReturnValue_t PowerSensor::getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
|
||||||
uint16_t startAtIndex) {
|
uint16_t startAtIndex) {
|
||||||
ReturnValue_t result = currentLimit.getParameter(domainId, parameterId,
|
ReturnValue_t result = currentLimit.getParameter(domainId, uniqueId,
|
||||||
parameterWrapper, newValues, startAtIndex);
|
parameterWrapper, newValues, startAtIndex);
|
||||||
if (result != INVALID_DOMAIN_ID) {
|
if (result != INVALID_DOMAIN_ID) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result = voltageLimit.getParameter(domainId, parameterId, parameterWrapper,
|
result = voltageLimit.getParameter(domainId, uniqueId, parameterWrapper,
|
||||||
newValues, startAtIndex);
|
newValues, startAtIndex);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ public:
|
|||||||
float getPower();
|
float getPower();
|
||||||
ReturnValue_t setHealth(HealthState health);
|
ReturnValue_t setHealth(HealthState health);
|
||||||
HasHealthIF::HealthState getHealth();
|
HasHealthIF::HealthState getHealth();
|
||||||
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||||
ParameterWrapper *parameterWrapper,
|
ParameterWrapper *parameterWrapper,
|
||||||
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
const ParameterWrapper *newValues, uint16_t startAtIndex);
|
||||||
private:
|
private:
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
target_sources(${LIB_FSFW_NAME}
|
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||||
PRIVATE
|
Service1TelecommandVerification.cpp
|
||||||
CService200ModeCommanding.cpp
|
Service2DeviceAccess.cpp
|
||||||
CService201HealthCommanding.cpp
|
Service3Housekeeping.cpp
|
||||||
Service17Test.cpp
|
Service5EventReporting.cpp
|
||||||
Service1TelecommandVerification.cpp
|
Service8FunctionManagement.cpp
|
||||||
Service2DeviceAccess.cpp
|
Service9TimeManagement.cpp
|
||||||
Service3Housekeeping.cpp
|
Service17Test.cpp
|
||||||
Service5EventReporting.cpp
|
Service20ParameterManagement.cpp
|
||||||
Service8FunctionManagement.cpp
|
CService200ModeCommanding.cpp
|
||||||
Service9TimeManagement.cpp
|
CService201HealthCommanding.cpp
|
||||||
)
|
)
|
@ -15,7 +15,7 @@ Service17Test::~Service17Test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t Service17Test::handleRequest(uint8_t subservice) {
|
ReturnValue_t Service17Test::handleRequest(uint8_t subservice) {
|
||||||
switch(subservice){
|
switch(subservice) {
|
||||||
case Subservice::CONNECTION_TEST: {
|
case Subservice::CONNECTION_TEST: {
|
||||||
TmPacketStored connectionPacket(apid, serviceId,
|
TmPacketStored connectionPacket(apid, serviceId,
|
||||||
Subservice::CONNECTION_TEST_REPORT, packetSubCounter++);
|
Subservice::CONNECTION_TEST_REPORT, packetSubCounter++);
|
||||||
|
186
pus/Service20ParameterManagement.cpp
Normal file
186
pus/Service20ParameterManagement.cpp
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
#include "Service20ParameterManagement.h"
|
||||||
|
#include "servicepackets/Service20Packets.h"
|
||||||
|
|
||||||
|
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||||
|
#include <fsfw/parameters/HasParametersIF.h>
|
||||||
|
#include <fsfw/parameters/ParameterMessage.h>
|
||||||
|
#include <fsfw/parameters/ReceivesParameterMessagesIF.h>
|
||||||
|
#include <tmtc/pusIds.h>
|
||||||
|
|
||||||
|
|
||||||
|
Service20ParameterManagement::Service20ParameterManagement(object_id_t objectId, uint16_t apid,
|
||||||
|
uint8_t serviceId, uint8_t numberOfParallelCommands, uint16_t commandTimeoutSeconds) :
|
||||||
|
CommandingServiceBase(objectId, apid, serviceId,
|
||||||
|
numberOfParallelCommands,commandTimeoutSeconds) {}
|
||||||
|
|
||||||
|
Service20ParameterManagement::~Service20ParameterManagement() {}
|
||||||
|
|
||||||
|
|
||||||
|
ReturnValue_t Service20ParameterManagement::isValidSubservice(
|
||||||
|
uint8_t subservice) {
|
||||||
|
switch(static_cast<Subservice>(subservice)) {
|
||||||
|
case Subservice::PARAMETER_LOAD:
|
||||||
|
case Subservice::PARAMETER_DUMP:
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
default:
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "Invalid Subservice for Service 20" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printError("Invalid Subservice for Service 20\n");
|
||||||
|
#endif
|
||||||
|
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ReturnValue_t Service20ParameterManagement::getMessageQueueAndObject(
|
||||||
|
uint8_t subservice, const uint8_t* tcData, size_t tcDataLen,
|
||||||
|
MessageQueueId_t* id, object_id_t* objectId) {
|
||||||
|
ReturnValue_t result = checkAndAcquireTargetID(objectId,tcData,tcDataLen);
|
||||||
|
if(result != RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return checkInterfaceAndAcquireMessageQueue(id,objectId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ReturnValue_t Service20ParameterManagement::checkAndAcquireTargetID(
|
||||||
|
object_id_t* objectIdToSet, const uint8_t* tcData, size_t tcDataLen) {
|
||||||
|
if(SerializeAdapter::deSerialize(objectIdToSet, &tcData, &tcDataLen,
|
||||||
|
SerializeIF::Endianness::BIG) != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "Service20ParameterManagement::checkAndAcquireTargetID: "
|
||||||
|
<< "Invalid data." << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printError("Service20ParameterManagement::"
|
||||||
|
"checkAndAcquireTargetID: Invalid data.\n");
|
||||||
|
#endif
|
||||||
|
return CommandingServiceBase::INVALID_TC;
|
||||||
|
}
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ReturnValue_t Service20ParameterManagement::checkInterfaceAndAcquireMessageQueue(
|
||||||
|
MessageQueueId_t* messageQueueToSet, object_id_t* objectId) {
|
||||||
|
// check ReceivesParameterMessagesIF property of target
|
||||||
|
ReceivesParameterMessagesIF* possibleTarget =
|
||||||
|
objectManager->get<ReceivesParameterMessagesIF>(*objectId);
|
||||||
|
if(possibleTarget == nullptr) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "Service20ParameterManagement::checkInterfaceAndAcquire"
|
||||||
|
<<"MessageQueue: Can't access object" << std::endl;
|
||||||
|
sif::error << "Object ID: " << std::hex << objectId << std::dec << std::endl;
|
||||||
|
sif::error << "Make sure it implements ReceivesParameterMessagesIF!" << std::endl;
|
||||||
|
#else
|
||||||
|
sif::printError("Service20ParameterManagement::checkInterfaceAndAcquire"
|
||||||
|
"MessageQueue: Can't access object\n");
|
||||||
|
sif::printError("Object ID: 0x%08x\n", objectId);
|
||||||
|
sif::printError("Make sure it implements "
|
||||||
|
"ReceivesParameterMessagesIF!\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return CommandingServiceBase::INVALID_OBJECT;
|
||||||
|
}
|
||||||
|
*messageQueueToSet = possibleTarget->getCommandQueue();
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Service20ParameterManagement::prepareCommand(
|
||||||
|
CommandMessage* message, uint8_t subservice, const uint8_t* tcData,
|
||||||
|
size_t tcDataLen, uint32_t* state, object_id_t objectId) {
|
||||||
|
switch(static_cast<Subservice>(subservice)){
|
||||||
|
case Subservice::PARAMETER_DUMP: {
|
||||||
|
return prepareDumpCommand(message, tcData, tcDataLen);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Subservice::PARAMETER_LOAD: {
|
||||||
|
return prepareLoadCommand(message, tcData, tcDataLen);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Service20ParameterManagement::prepareDumpCommand(
|
||||||
|
CommandMessage* message, const uint8_t* tcData, size_t tcDataLen) {
|
||||||
|
/* the first part is the objectId, but we have extracted that earlier
|
||||||
|
and only need the parameterId */
|
||||||
|
tcData += sizeof(object_id_t);
|
||||||
|
tcDataLen -= sizeof(object_id_t);
|
||||||
|
ParameterId_t parameterId;
|
||||||
|
if(SerializeAdapter::deSerialize(¶meterId, &tcData, &tcDataLen,
|
||||||
|
SerializeIF::Endianness::BIG) != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return CommandingServiceBase::INVALID_TC;
|
||||||
|
}
|
||||||
|
/* The length should have been decremented to 0 by this point */
|
||||||
|
if(tcDataLen != 0) {
|
||||||
|
return CommandingServiceBase::INVALID_TC;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParameterMessage::setParameterDumpCommand(message, parameterId);
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Service20ParameterManagement::prepareLoadCommand(
|
||||||
|
CommandMessage* message, const uint8_t* tcData, size_t tcDataLen) {
|
||||||
|
if(tcDataLen < sizeof(object_id_t) + sizeof(ParameterId_t) +
|
||||||
|
sizeof(uint32_t)) {
|
||||||
|
return CommandingServiceBase::INVALID_TC;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* storePointer = nullptr;
|
||||||
|
store_address_t storeAddress;
|
||||||
|
size_t parameterDataLen = tcDataLen - sizeof(object_id_t) - sizeof(ParameterId_t) -
|
||||||
|
sizeof(uint32_t);
|
||||||
|
ReturnValue_t result = IPCStore->getFreeElement(&storeAddress,
|
||||||
|
parameterDataLen, &storePointer);
|
||||||
|
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Following format is expected: The first 4 bytes in the TC data are the 4 byte
|
||||||
|
parameter ID (ParameterId_t). The second 4 bytes are the parameter information field,
|
||||||
|
containing the following 1 byte fields:
|
||||||
|
1. ECSS PTC field
|
||||||
|
2. ECSS PFC field
|
||||||
|
3. Number of rows
|
||||||
|
4. Number of columns */
|
||||||
|
ParameterLoadCommand command(storePointer, parameterDataLen);
|
||||||
|
result = command.deSerialize(&tcData, &tcDataLen,
|
||||||
|
SerializeIF::Endianness::BIG);
|
||||||
|
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParameterMessage::setParameterLoadCommand(message, command.getParameterId(), storeAddress,
|
||||||
|
command.getPtc(), command.getPfc(), command.getRows(), command.getColumns());
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Service20ParameterManagement::handleReply(
|
||||||
|
const CommandMessage* reply, Command_t previousCommand, uint32_t* state,
|
||||||
|
CommandMessage* optionalNextCommand, object_id_t objectId,
|
||||||
|
bool* isStep) {
|
||||||
|
Command_t replyId = reply->getCommand();
|
||||||
|
|
||||||
|
switch(replyId) {
|
||||||
|
case ParameterMessage::REPLY_PARAMETER_DUMP: {
|
||||||
|
ConstAccessorPair parameterData = IPCStore->getData(
|
||||||
|
ParameterMessage::getStoreId(reply));
|
||||||
|
if(parameterData.first != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return HasReturnvaluesIF::RETURN_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParameterId_t parameterId = ParameterMessage::getParameterId(reply);
|
||||||
|
ParameterDumpReply parameterReply(objectId, parameterId,
|
||||||
|
parameterData.second.data(), parameterData.second.size());
|
||||||
|
sendTmPacket(static_cast<uint8_t>(
|
||||||
|
Subservice::PARAMETER_DUMP_REPLY), ¶meterReply);
|
||||||
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return CommandingServiceBase::INVALID_REPLY;
|
||||||
|
}
|
||||||
|
}
|
60
pus/Service20ParameterManagement.h
Normal file
60
pus/Service20ParameterManagement.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#ifndef FSFW_PUS_SERVICE20PARAMETERMANAGEMENT_H_
|
||||||
|
#define FSFW_PUS_SERVICE20PARAMETERMANAGEMENT_H_
|
||||||
|
|
||||||
|
#include <fsfw/tmtcservices/CommandingServiceBase.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief PUS Service 20 Parameter Service implementation
|
||||||
|
* @details
|
||||||
|
* This service handles PUS service requests related to parameter management and forwards
|
||||||
|
* them to the internal software bus.
|
||||||
|
* @author J. Gerhards
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class Service20ParameterManagement : public CommandingServiceBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Service20ParameterManagement(object_id_t objectId, uint16_t apid, uint8_t serviceId,
|
||||||
|
uint8_t numberOfParallelCommands = 4, uint16_t commandTimeoutSeconds = 60);
|
||||||
|
virtual ~Service20ParameterManagement();
|
||||||
|
|
||||||
|
static constexpr uint8_t NUM_OF_PARALLEL_COMMANDS = 4;
|
||||||
|
static constexpr uint16_t COMMAND_TIMEOUT_SECONDS = 60;
|
||||||
|
protected:
|
||||||
|
/* CommandingServiceBase (CSB) abstract functions. See CSB documentation. */
|
||||||
|
ReturnValue_t isValidSubservice(uint8_t subservice) override;
|
||||||
|
ReturnValue_t getMessageQueueAndObject(uint8_t subservice,
|
||||||
|
const uint8_t *tcData, size_t tcDataLen, MessageQueueId_t *id,
|
||||||
|
object_id_t *objectId) override;
|
||||||
|
ReturnValue_t prepareCommand(CommandMessage* message, uint8_t subservice,
|
||||||
|
const uint8_t *tcData, size_t tcDataLen, uint32_t *state,
|
||||||
|
object_id_t objectId) override;
|
||||||
|
ReturnValue_t handleReply(const CommandMessage* reply,
|
||||||
|
Command_t previousCommand, uint32_t *state,
|
||||||
|
CommandMessage* optionalNextCommand, object_id_t objectId,
|
||||||
|
bool *isStep) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
ReturnValue_t checkAndAcquireTargetID(object_id_t* objectIdToSet,
|
||||||
|
const uint8_t* tcData, size_t tcDataLen);
|
||||||
|
ReturnValue_t checkInterfaceAndAcquireMessageQueue(
|
||||||
|
MessageQueueId_t* messageQueueToSet, object_id_t* objectId);
|
||||||
|
ReturnValue_t prepareDirectCommand(CommandMessage* message,
|
||||||
|
const uint8_t* tcData, size_t tcDataLen);
|
||||||
|
|
||||||
|
ReturnValue_t prepareDumpCommand(CommandMessage* message,
|
||||||
|
const uint8_t* tcData, size_t tcDataLen);
|
||||||
|
ReturnValue_t prepareLoadCommand(CommandMessage* message,
|
||||||
|
const uint8_t* tcData, size_t tcDataLen);
|
||||||
|
|
||||||
|
enum class Subservice {
|
||||||
|
PARAMETER_LOAD = 128, //!< [EXPORT] : Load a Parameter
|
||||||
|
PARAMETER_DUMP = 129, //!< [EXPORT] : Dump a Parameter
|
||||||
|
PARAMETER_DUMP_REPLY = 130, //!< [EXPORT] : Dump a Parameter
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* FSFW_PUS_SERVICE20PARAMETERMANAGEMENT_H_ */
|
@ -104,12 +104,14 @@ ReturnValue_t Service8FunctionManagement::handleReply(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ActionMessage::DATA_REPLY: {
|
case ActionMessage::DATA_REPLY: {
|
||||||
|
/* Multiple data replies are possible, so declare data reply as step */
|
||||||
|
*isStep = true;
|
||||||
result = handleDataReply(reply, objectId, actionId);
|
result = handleDataReply(reply, objectId, actionId);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ActionMessage::STEP_FAILED:
|
case ActionMessage::STEP_FAILED:
|
||||||
*isStep = true;
|
*isStep = true;
|
||||||
/*No break, falls through*/
|
/* No break, falls through */
|
||||||
case ActionMessage::COMPLETION_FAILED:
|
case ActionMessage::COMPLETION_FAILED:
|
||||||
result = ActionMessage::getReturnCode(reply);
|
result = ActionMessage::getReturnCode(reply);
|
||||||
break;
|
break;
|
||||||
|
142
pus/servicepackets/Service20Packets.h
Normal file
142
pus/servicepackets/Service20Packets.h
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
#ifndef FSFW_PUS_SERVICEPACKETS_SERVICE20PACKETS_H_
|
||||||
|
#define FSFW_PUS_SERVICEPACKETS_SERVICE20PACKETS_H_
|
||||||
|
|
||||||
|
#include <FSFWConfig.h>
|
||||||
|
#include <fsfw/parameters/HasParametersIF.h>
|
||||||
|
#include <fsfw/serialize/SerialBufferAdapter.h>
|
||||||
|
#include <fsfw/serialize/SerializeElement.h>
|
||||||
|
#include <fsfw/serialize/SerialLinkedListAdapter.h>
|
||||||
|
#include <fsfw/serviceinterface/ServiceInterface.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief This class encapsulates the packets sent to the PUS service 20 or sent by the
|
||||||
|
* PUS service 20
|
||||||
|
* @details
|
||||||
|
* This command can be used to handle both load and dump commands as well.
|
||||||
|
* @author
|
||||||
|
*/
|
||||||
|
class ParameterCommand: public SerialLinkedListAdapter<SerializeIF> { //!< [EXPORT] : [SUBSERVICE] 128, 129, 130
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This constructor is used for load replies. The data is expected in the correct formast
|
||||||
|
* in the store pointer.
|
||||||
|
* @param storePointer
|
||||||
|
* @param parameterDataLen
|
||||||
|
*/
|
||||||
|
ParameterCommand(uint8_t* storePointer, size_t parameterDataLen):
|
||||||
|
parameterBuffer(storePointer, parameterDataLen) {
|
||||||
|
#if FSFW_VERBOSE_LEVEL >= 1
|
||||||
|
if(parameterDataLen < sizeof(object_id_t) + sizeof(ParameterId_t) + 4) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::warning << "ParameterCommand: Parameter data length is less than 12!"
|
||||||
|
<< std::endl;
|
||||||
|
#else
|
||||||
|
sif::printWarning("ParameterCommand: Parameter data length is less than 12!\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||||
|
setLoadLinks();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This constructor is used for dump replies. It is assumed the 4 byte parameter
|
||||||
|
* information field is located inside the parameter buffer.
|
||||||
|
* @param objectId
|
||||||
|
* @param parameterId
|
||||||
|
* @param parameterBuffer
|
||||||
|
* @param parameterBufferSize
|
||||||
|
*/
|
||||||
|
ParameterCommand(object_id_t objectId, ParameterId_t parameterId,
|
||||||
|
const uint8_t* parameterBuffer, size_t parameterBufferSize):
|
||||||
|
objectId(objectId), parameterId(parameterId),
|
||||||
|
parameterBuffer(parameterBuffer, parameterBufferSize) {
|
||||||
|
setDumpReplyLinks();
|
||||||
|
}
|
||||||
|
|
||||||
|
ParameterId_t getParameterId() const {
|
||||||
|
return parameterId.entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t* getParameterBuffer() {
|
||||||
|
return parameterBuffer.entry.getConstBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getParameterBufferLen() const {
|
||||||
|
return parameterBuffer.getSerializedSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t getDomainId() const {
|
||||||
|
return (parameterId.entry >> 24) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t getUniqueId() const {
|
||||||
|
return (parameterId.entry >> 16) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getLinearIndex() const {
|
||||||
|
return parameterId.entry & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t getPtc() const {
|
||||||
|
return ccsdsType.entry >> 8 & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t getPfc() const {
|
||||||
|
return ccsdsType.entry & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t getRows() const {
|
||||||
|
return rows.entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t getColumns() const {
|
||||||
|
return columns.entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setLoadLinks() {
|
||||||
|
setStart(&objectId);
|
||||||
|
objectId.setNext(¶meterId);
|
||||||
|
parameterId.setNext(&ccsdsType);
|
||||||
|
ccsdsType.setNext(&rows);
|
||||||
|
rows.setNext(&columns);
|
||||||
|
columns.setNext(¶meterBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setDumpReplyLinks() {
|
||||||
|
/* For a dump reply, the parameter information is contained in the parameter buffer
|
||||||
|
with the actual parameters */
|
||||||
|
setStart(&objectId);
|
||||||
|
objectId.setNext(¶meterId);
|
||||||
|
parameterId.setNext(¶meterBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setDumpRequestLinks() {
|
||||||
|
setStart(&objectId);
|
||||||
|
objectId.setNext(¶meterId);
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializeElement<object_id_t> objectId = 0;
|
||||||
|
SerializeElement<ParameterId_t> parameterId = 0;
|
||||||
|
//! [EXPORT] : [COMMENT] Type consisting of one byte PTC and one byte PFC.
|
||||||
|
SerializeElement<uint16_t> ccsdsType = 0;
|
||||||
|
SerializeElement<uint8_t> rows = 0;
|
||||||
|
SerializeElement<uint8_t> columns = 0;
|
||||||
|
SerializeElement<SerialBufferAdapter<uint8_t>> parameterBuffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ParameterLoadCommand: public ParameterCommand {
|
||||||
|
public:
|
||||||
|
ParameterLoadCommand(uint8_t* parameterPacket, size_t parameterDataLen):
|
||||||
|
ParameterCommand(parameterPacket, parameterDataLen) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ParameterDumpReply: public ParameterCommand {
|
||||||
|
public:
|
||||||
|
ParameterDumpReply(object_id_t objectId, ParameterId_t parameterId,
|
||||||
|
const uint8_t* parameterBuffer, size_t parameterBufferSize):
|
||||||
|
ParameterCommand(objectId, parameterId, parameterBuffer, parameterBufferSize) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* FSFW_PUS_SERVICEPACKETS_SERVICE20PACKETS_H_ */
|
@ -29,7 +29,7 @@ ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string setMessage,
|
|||||||
|
|
||||||
#if FSFW_COLORED_OUTPUT == 1
|
#if FSFW_COLORED_OUTPUT == 1
|
||||||
if(setMessage.find("DEBUG") != std::string::npos) {
|
if(setMessage.find("DEBUG") != std::string::npos) {
|
||||||
colorPrefix = sif::ANSI_COLOR_MAGENTA;
|
colorPrefix = sif::ANSI_COLOR_CYAN;
|
||||||
}
|
}
|
||||||
else if(setMessage.find("INFO") != std::string::npos) {
|
else if(setMessage.find("INFO") != std::string::npos) {
|
||||||
colorPrefix = sif::ANSI_COLOR_GREEN;
|
colorPrefix = sif::ANSI_COLOR_GREEN;
|
||||||
|
@ -45,7 +45,7 @@ void fsfwPrint(sif::PrintLevel printType, const char* fmt, va_list arg) {
|
|||||||
len += sprintf(bufferPosition, sif::ANSI_COLOR_GREEN);
|
len += sprintf(bufferPosition, sif::ANSI_COLOR_GREEN);
|
||||||
}
|
}
|
||||||
else if(printType == sif::PrintLevel::DEBUG_LEVEL) {
|
else if(printType == sif::PrintLevel::DEBUG_LEVEL) {
|
||||||
len += sprintf(bufferPosition, sif::ANSI_COLOR_MAGENTA);
|
len += sprintf(bufferPosition, sif::ANSI_COLOR_CYAN);
|
||||||
}
|
}
|
||||||
else if(printType == sif::PrintLevel::WARNING_LEVEL) {
|
else if(printType == sif::PrintLevel::WARNING_LEVEL) {
|
||||||
len += sprintf(bufferPosition, sif::ANSI_COLOR_YELLOW);
|
len += sprintf(bufferPosition, sif::ANSI_COLOR_YELLOW);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user