From cea748676ea2f99343ec0f0dcbd5face9e114fe8 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 15:47:29 +0200 Subject: [PATCH 01/17] linux message queue update --- osal/linux/MessageQueue.cpp | 106 +++++++++++++++++++++++------------- osal/linux/MessageQueue.h | 30 ++++++---- 2 files changed, 87 insertions(+), 49 deletions(-) diff --git a/osal/linux/MessageQueue.cpp b/osal/linux/MessageQueue.cpp index e5c61cae..cfadb793 100644 --- a/osal/linux/MessageQueue.cpp +++ b/osal/linux/MessageQueue.cpp @@ -1,5 +1,6 @@ -#include "../../serviceinterface/ServiceInterfaceStream.h" #include "MessageQueue.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../objectmanager/ObjectManagerIF.h" #include @@ -9,9 +10,11 @@ #include + MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize): id(MessageQueueIF::NO_QUEUE),lastPartner(MessageQueueIF::NO_QUEUE), - defaultDestination(MessageQueueIF::NO_QUEUE) { + defaultDestination(MessageQueueIF::NO_QUEUE), + maxMessageSize(maxMessageSize) { //debug << "MessageQueue::MessageQueue: Creating a queue" << std::endl; mq_attr attributes; this->id = 0; @@ -46,7 +49,7 @@ MessageQueue::~MessageQueue() { status = mq_unlink(name); if(status != 0){ sif::error << "MessageQueue::Destructor: mq_unlink Failed with status: " - << strerror(errno) <> defaultMqMaxMsg and defaultMqMaxMsg < messageDepth) { - // See: https://www.man7.org/linux/man-pages/man3/mq_open.3.html - // This happens if the msg_max value is not large enough - // It is ignored if the executable is run in privileged mode. - // Run the unlockRealtime script or grant the mode manually by using: - // sudo setcap 'CAP_SYS_RESOURCE=+ep' + /* + See: https://www.man7.org/linux/man-pages/man3/mq_open.3.html + This happens if the msg_max value is not large enough + It is ignored if the executable is run in privileged mode. + Run the unlockRealtime script or grant the mode manually by using: + sudo setcap 'CAP_SYS_RESOURCE=+ep' - // Persistent solution for session: - // echo | sudo tee /proc/sys/fs/mqueue/msg_max + Persistent solution for session: + echo | sudo tee /proc/sys/fs/mqueue/msg_max - // Permanent solution: - // sudo nano /etc/sysctl.conf - // Append at end: fs/mqueue/msg_max = - // Apply changes with: sudo sysctl -p + Permanent solution: + sudo nano /etc/sysctl.conf + Append at end: fs/mqueue/msg_max = + Apply changes with: sudo sysctl -p + */ sif::error << "MessageQueue::MessageQueue: Default MQ size " << defaultMqMaxMsg << " is too small for requested size " << messageDepth << std::endl; + sif::error << "This error can be fixed by setting the maximum " + "allowed message size higher!" << std::endl; + } break; } @@ -118,15 +126,15 @@ ReturnValue_t MessageQueue::handleError(mq_attr* attributes, } ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, bool ignoreFault) { + MessageQueueMessageIF* message, bool ignoreFault) { return sendMessageFrom(sendTo, message, this->getId(), false); } -ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message) { +ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) { return sendToDefaultFrom(message, this->getId()); } -ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) { +ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) { if (this->lastPartner != 0) { return sendMessageFrom(this->lastPartner, message, this->getId()); } else { @@ -134,21 +142,34 @@ ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) { } } -ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message, +ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message, MessageQueueId_t* receivedFrom) { ReturnValue_t status = this->receiveMessage(message); *receivedFrom = this->lastPartner; return status; } -ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) { +ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) { + if(message == nullptr) { + sif::error << "MessageQueue::receiveMessage: Message is " + "nullptr!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + + if(message->getMaximumMessageSize() < maxMessageSize) { + sif::error << "MessageQueue::receiveMessage: Message size " + << message->getMaximumMessageSize() + << " too small to receive data!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + unsigned int messagePriority = 0; int status = mq_receive(id,reinterpret_cast(message->getBuffer()), - message->MAX_MESSAGE_SIZE,&messagePriority); + message->getMaximumMessageSize(),&messagePriority); if (status > 0) { this->lastPartner = message->getSender(); //Check size of incoming message. - if (message->messageSize < message->getMinimumMessageSize()) { + if (message->getMessageSize() < message->getMinimumMessageSize()) { return HasReturnvaluesIF::RETURN_FAILED; } return HasReturnvaluesIF::RETURN_OK; @@ -158,7 +179,7 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) { } else { //No message was received. Keep lastPartner anyway, I might send //something later. But still, delete packet content. - memset(message->getData(), 0, message->MAX_DATA_SIZE); + memset(message->getData(), 0, message->getMaximumMessageSize()); switch(errno){ case EAGAIN: //O_NONBLOCK or MQ_NONBLOCK was set and there are no messages @@ -258,18 +279,19 @@ void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) { this->defaultDestination = defaultDestination; } -ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, - MessageQueueMessage* message, MessageQueueId_t sentFrom, - bool ignoreFault) { - return sendMessageFromMessageQueue(sendTo,message,sentFrom,ignoreFault); - -} - -ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessage* message, +ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message, MessageQueueId_t sentFrom, bool ignoreFault) { return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault); } + +ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + bool ignoreFault) { + return sendMessageFromMessageQueue(sendTo,message, sentFrom,ignoreFault); + +} + MessageQueueId_t MessageQueue::getDefaultDestination() const { return this->defaultDestination; } @@ -281,11 +303,18 @@ bool MessageQueue::isDefaultDestinationSet() const { uint16_t MessageQueue::queueCounter = 0; ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, - MessageQueueMessage *message, MessageQueueId_t sentFrom, + MessageQueueMessageIF *message, MessageQueueId_t sentFrom, bool ignoreFault) { + if(message == nullptr) { + sif::error << "MessageQueue::sendMessageFromMessageQueue: Message is " + "nullptr!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + message->setSender(sentFrom); int result = mq_send(sendTo, - reinterpret_cast(message->getBuffer()), message->messageSize,0); + reinterpret_cast(message->getBuffer()), + message->getMessageSize(),0); //TODO: Check if we're in ISR. if (result != 0) { @@ -303,13 +332,16 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, //MQ_NONBLOCK flag was set in its attributes, and the //specified queue is full. return MessageQueueIF::FULL; - case EBADF: + case EBADF: { //mq_des doesn't represent a valid message queue descriptor, //or mq_des wasn't opened for writing. - sif::error << "MessageQueue::sendMessage: Configuration error " - << strerror(errno) << " in mq_send mqSendTo: " << sendTo - << " sent from " << sentFrom << std::endl; - /*NO BREAK*/ + sif::error << "MessageQueue::sendMessage: Configuration error, MQ" + << " destination invalid." << std::endl; + sif::error << strerror(errno) << " in " + <<"mq_send to: " << sendTo << " sent from " + << sentFrom << std::endl; + return DESTINVATION_INVALID; + } case EINTR: //The call was interrupted by a signal. case EINVAL: diff --git a/osal/linux/MessageQueue.h b/osal/linux/MessageQueue.h index 31cdca11..239bbbdb 100644 --- a/osal/linux/MessageQueue.h +++ b/osal/linux/MessageQueue.h @@ -1,5 +1,5 @@ -#ifndef MESSAGEQUEUE_H_ -#define MESSAGEQUEUE_H_ +#ifndef FSFW_OSAL_LINUX_MESSAGEQUEUE_H_ +#define FSFW_OSAL_LINUX_MESSAGEQUEUE_H_ #include "../../internalError/InternalErrorReporterIF.h" #include "../../ipc/MessageQueueIF.h" @@ -56,14 +56,14 @@ public: * @param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. */ virtual ReturnValue_t sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, bool ignoreFault = false ); + MessageQueueMessageIF* message, bool ignoreFault = false ); /** * @brief This operation sends a message to the default destination. * @details As in the sendMessage method, this function uses the sendToDefault call of the * MessageQueueSender parent class and adds its queue id as "sentFrom" information. * @param message A pointer to a previously created message, which is sent. */ - virtual ReturnValue_t sendToDefault( MessageQueueMessage* message ); + virtual ReturnValue_t sendToDefault( MessageQueueMessageIF* message ); /** * @brief This operation sends a message to the last communication partner. * @details This operation simplifies answering an incoming message by using the stored @@ -71,7 +71,7 @@ public: * (i.e. lastPartner is zero), an error code is returned. * @param message A pointer to a previously created message, which is sent. */ - ReturnValue_t reply( MessageQueueMessage* message ); + ReturnValue_t reply( MessageQueueMessageIF* message ); /** * @brief This function reads available messages from the message queue and returns the sender. @@ -80,7 +80,7 @@ public: * @param message A pointer to a message in which the received data is stored. * @param receivedFrom A pointer to a queue id in which the sender's id is stored. */ - ReturnValue_t receiveMessage(MessageQueueMessage* message, + ReturnValue_t receiveMessage(MessageQueueMessageIF* message, MessageQueueId_t *receivedFrom); /** @@ -91,7 +91,7 @@ public: * message's content is cleared and the function returns immediately. * @param message A pointer to a message in which the received data is stored. */ - ReturnValue_t receiveMessage(MessageQueueMessage* message); + ReturnValue_t receiveMessage(MessageQueueMessageIF* message); /** * Deletes all pending messages in the queue. * @param count The number of flushed messages. @@ -114,7 +114,9 @@ public: * This variable is set to zero by default. * \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. */ - virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault = false ); + virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + bool ignoreFault = false ); /** * \brief The sendToDefault method sends a queue message to the default destination. * \details In all other aspects, it works identical to the sendMessage method. @@ -122,7 +124,8 @@ public: * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. * This variable is set to zero by default. */ - virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ); + virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message, + MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ); /** * \brief This method is a simple setter for the default destination. */ @@ -145,7 +148,9 @@ protected: * This variable is set to zero by default. * \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. */ - static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo,MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE,bool ignoreFault=false); + static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom = NO_QUEUE, + bool ignoreFault=false); private: /** * @brief The class stores the queue id it got assigned from the operating system in this attribute. @@ -171,11 +176,12 @@ private: /** * The name of the message queue, stored for unlinking */ - char name[5]; + char name[16]; static uint16_t queueCounter; + const size_t maxMessageSize; ReturnValue_t handleError(mq_attr* attributes, uint32_t messageDepth); }; -#endif /* MESSAGEQUEUE_H_ */ +#endif /* FSFW_OSAL_LINUX_MESSAGEQUEUE_H_ */ From 8652f2f13f1ff7e358e6d0b803a04772b9b83e58 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 15:50:10 +0200 Subject: [PATCH 02/17] message queue IF update --- ipc/MessageQueueIF.h | 178 +++++++++++++++++++++++++++---------------- 1 file changed, 113 insertions(+), 65 deletions(-) diff --git a/ipc/MessageQueueIF.h b/ipc/MessageQueueIF.h index b0347db9..44b6f4c0 100644 --- a/ipc/MessageQueueIF.h +++ b/ipc/MessageQueueIF.h @@ -1,61 +1,77 @@ #ifndef FSFW_IPC_MESSAGEQUEUEIF_H_ #define FSFW_IPC_MESSAGEQUEUEIF_H_ -// COULDDO: We could support blocking calls - -#include "messageQueueDefinitions.h" -#include "MessageQueueMessage.h" +#include +#include "MessageQueueMessageIF.h" #include "../returnvalues/HasReturnvaluesIF.h" +#include + + +// COULDDO: We could support blocking calls +// semaphores are being implemented, which makes this idea even more iteresting. + +/** + * @defgroup message_queue Message Queue + * @brief Message Queue related software components + */ class MessageQueueIF { public: static const MessageQueueId_t NO_QUEUE = 0; static const uint8_t INTERFACE_ID = CLASS_ID::MESSAGE_QUEUE_IF; - /** - * No new messages on the queue - */ + //! No new messages on the queue static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(1); - /** - * No space left for more messages - */ + //! No space left for more messages static const ReturnValue_t FULL = MAKE_RETURN_CODE(2); - /** - * Returned if a reply method was called without partner - */ + //! Returned if a reply method was called without partner static const ReturnValue_t NO_REPLY_PARTNER = MAKE_RETURN_CODE(3); + //! Returned if the target destination is invalid. + static constexpr ReturnValue_t DESTINVATION_INVALID = MAKE_RETURN_CODE(4); virtual ~MessageQueueIF() {} /** * @brief This operation sends a message to the last communication partner. - * @details This operation simplifies answering an incoming message by using the stored - * lastParnter information as destination. If there was no message received yet - * (i.e. lastPartner is zero), an error code is returned. - * @param message A pointer to a previously created message, which is sent. - * \return RETURN_OK if ok - * \return NO_REPLY_PARTNER Should return NO_REPLY_PARTNER if partner was found + * @details + * This operation simplifies answering an incoming message by using the + * stored lastParnter information as destination. If there was no message + * received yet (i.e. lastPartner is zero), an error code is returned. + * @param message + * A pointer to a previously created message, which is sent. + * @return + * -@c RETURN_OK if ok + * -@c NO_REPLY_PARTNER Should return NO_REPLY_PARTNER if partner was found. */ - virtual ReturnValue_t reply( MessageQueueMessage* message ) = 0; + virtual ReturnValue_t reply(MessageQueueMessageIF* message) = 0; /** - * @brief This function reads available messages from the message queue and returns the sender. - * @details It works identically to the other receiveMessage call, but in addition returns the - * sender's queue id. - * @param message A pointer to a message in which the received data is stored. - * @param receivedFrom A pointer to a queue id in which the sender's id is stored. + * @brief This function reads available messages from the message queue + * and returns the sender. + * @details + * It works identically to the other receiveMessage call, but in addition + * returns the sender's queue id. + * @param message + * A pointer to a message in which the received data is stored. + * @param receivedFrom + * A pointer to a queue id in which the sender's id is stored. */ - virtual ReturnValue_t receiveMessage(MessageQueueMessage* message, + virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message, MessageQueueId_t *receivedFrom) = 0; /** * @brief This function reads available messages from the message queue. - * @details If data is available it is stored in the passed message pointer. The message's - * original content is overwritten and the sendFrom information is stored in the - * lastPartner attribute. Else, the lastPartner information remains untouched, the - * message's content is cleared and the function returns immediately. - * @param message A pointer to a message in which the received data is stored. + * @details + * If data is available it is stored in the passed message pointer. + * The message's original content is overwritten and the sendFrom + * information is stored in theblastPartner attribute. Else, the lastPartner + * information remains untouched, the message's content is cleared and the + * function returns immediately. + * @param message + * A pointer to a message in which the received data is stored. + * @return -@c RETURN_OK on success + * -@c MessageQueueIF::EMPTY if queue is empty */ - virtual ReturnValue_t receiveMessage(MessageQueueMessage* message) = 0; + virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) = 0; /** * Deletes all pending messages in the queue. * @param count The number of flushed messages. @@ -63,57 +79,89 @@ public: */ virtual ReturnValue_t flush(uint32_t* count) = 0; /** - * @brief This method returns the message queue id of the last communication partner. + * @brief This method returns the message queue + * id of the last communication partner. */ virtual MessageQueueId_t getLastPartner() const = 0; /** - * @brief This method returns the message queue id of this class's message queue. + * @brief This method returns the message queue + * id of this class's message queue. */ virtual MessageQueueId_t getId() const = 0; /** - * \brief With the sendMessage call, a queue message is sent to a receiving queue. - * \details This method takes the message provided, adds the sentFrom information and passes - * it on to the destination provided with an operating system call. The OS's return - * value is returned. - * \param sendTo This parameter specifies the message queue id to send the message to. - * \param message This is a pointer to a previously created message, which is sent. - * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. - * This variable is set to zero by default. - * \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full (if implemented). + * @brief With the sendMessage call, a queue message + * is sent to a receiving queue. + * @details + * This method takes the message provided, adds the sentFrom information + * and passes it on to the destination provided with an operating system + * call. The OS's returnvalue is returned. + * @param sendTo + * This parameter specifies the message queue id to send the message to. + * @param message + * This is a pointer to a previously created message, which is sent. + * @param sentFrom + * The sentFrom information can be set to inject the sender's queue id + * into the message. This variable is set to zero by default. + * @param ignoreFault + * If set to true, the internal software fault counter is not incremented + * if queue is full (if implemented). + * @return -@c RETURN_OK on success + * -@c MessageQueueIF::FULL if queue is full */ - virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0; - /** - * @brief This operation sends a message to the given destination. - * @details It directly uses the sendMessage call of the MessageQueueSender parent, but passes its - * queue id as "sentFrom" parameter. - * @param sendTo This parameter specifies the message queue id of the destination message queue. - * @param message A pointer to a previously created message, which is sent. - * @param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. - */ - virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo, MessageQueueMessage* message, bool ignoreFault = false ) = 0; + virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + bool ignoreFault = false ) = 0; /** - * \brief The sendToDefaultFrom method sends a queue message to the default destination. - * \details In all other aspects, it works identical to the sendMessage method. - * \param message This is a pointer to a previously created message, which is sent. - * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. - * This variable is set to zero by default. + * @brief This operation sends a message to the given destination. + * @details + * It directly uses the sendMessage call of the MessageQueueSender parent, + * but passes its queue id as "sentFrom" parameter. + * @param sendTo + * This parameter specifies the message queue id of the destination + * message queue. + * @param message + * A pointer to a previously created message, which is sent. + * @param ignoreFault + * If set to true, the internal software fault counter is not incremented + * if queue is full. */ - virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0; + virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo, + MessageQueueMessageIF* message, bool ignoreFault = false ) = 0; + + /** + * @brief The sendToDefaultFrom method sends a queue message + * to the default destination. + * @details + * In all other aspects, it works identical to the sendMessage method. + * @param message + * This is a pointer to a previously created message, which is sent. + * @param sentFrom + * The sentFrom information can be set to inject the sender's queue id + * into the message. This variable is set to zero by default. + * @return -@c RETURN_OK on success + * -@c MessageQueueIF::FULL if queue is full + */ + virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message, + MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0; /** * @brief This operation sends a message to the default destination. - * @details As in the sendMessage method, this function uses the sendToDefault call of the - * Implementation class and adds its queue id as "sentFrom" information. + * @details + * As in the sendMessage method, this function uses the sendToDefault + * call of the Implementation class and adds its queue id as + * "sentFrom" information. * @param message A pointer to a previously created message, which is sent. + * @return -@c RETURN_OK on success + * -@c MessageQueueIF::FULL if queue is full */ - virtual ReturnValue_t sendToDefault( MessageQueueMessage* message ) = 0; + virtual ReturnValue_t sendToDefault( MessageQueueMessageIF* message ) = 0; /** - * \brief This method is a simple setter for the default destination. + * @brief This method is a simple setter for the default destination. */ virtual void setDefaultDestination(MessageQueueId_t defaultDestination) = 0; /** - * \brief This method is a simple getter for the default destination. + * @brief This method is a simple getter for the default destination. */ virtual MessageQueueId_t getDefaultDestination() const = 0; @@ -122,4 +170,4 @@ public: -#endif /* FRAMEWORK_IPC_MESSAGEQUEUEIF_H_ */ +#endif /* FSFW_IPC_MESSAGEQUEUEIF_H_ */ From 87fb17f39a4320eb8b40517ae79e170950b1b3a5 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 15:52:26 +0200 Subject: [PATCH 03/17] IF replacements --- ipc/MessageQueueSenderIF.h | 2 +- osal/FreeRTOS/QueueFactory.cpp | 2 +- osal/linux/Clock.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ipc/MessageQueueSenderIF.h b/ipc/MessageQueueSenderIF.h index 7eea5146..42d4078f 100644 --- a/ipc/MessageQueueSenderIF.h +++ b/ipc/MessageQueueSenderIF.h @@ -15,7 +15,7 @@ public: * Not sure whether this is actually a good idea. */ static ReturnValue_t sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom = MessageQueueIF::NO_QUEUE, bool ignoreFault = false); private: diff --git a/osal/FreeRTOS/QueueFactory.cpp b/osal/FreeRTOS/QueueFactory.cpp index 153d9b51..493ec925 100644 --- a/osal/FreeRTOS/QueueFactory.cpp +++ b/osal/FreeRTOS/QueueFactory.cpp @@ -8,7 +8,7 @@ QueueFactory* QueueFactory::factoryInstance = nullptr; ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, MessageQueueId_t sentFrom, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, bool ignoreFault) { return MessageQueue::sendMessageFromMessageQueue(sendTo,message, sentFrom,ignoreFault); diff --git a/osal/linux/Clock.cpp b/osal/linux/Clock.cpp index b14f2a97..4de18f83 100644 --- a/osal/linux/Clock.cpp +++ b/osal/linux/Clock.cpp @@ -6,8 +6,8 @@ #include #include #include +#include -//#include uint16_t Clock::leapSeconds = 0; MutexIF* Clock::timeMutex = NULL; From de840dcf8df69d5b734951fa7128257fa472cd46 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 16:10:43 +0200 Subject: [PATCH 04/17] last fixes for linux --- ipc/QueueFactory.h | 8 +++++--- osal/linux/QueueFactory.cpp | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ipc/QueueFactory.h b/ipc/QueueFactory.h index 4f4d72c7..0310e534 100644 --- a/ipc/QueueFactory.h +++ b/ipc/QueueFactory.h @@ -1,7 +1,9 @@ -#ifndef FRAMEWORK_IPC_QUEUEFACTORY_H_ -#define FRAMEWORK_IPC_QUEUEFACTORY_H_ +#ifndef FSFW_IPC_QUEUEFACTORY_H_ +#define FSFW_IPC_QUEUEFACTORY_H_ + #include "MessageQueueIF.h" +#include "../ipc/MessageQueueMessage.h" #include /** * Creates message queues. @@ -30,4 +32,4 @@ private: static QueueFactory* factoryInstance; }; -#endif /* FRAMEWORK_IPC_QUEUEFACTORY_H_ */ +#endif /* FSFW_IPC_QUEUEFACTORY_H_ */ diff --git a/osal/linux/QueueFactory.cpp b/osal/linux/QueueFactory.cpp index 0860950c..44def48a 100644 --- a/osal/linux/QueueFactory.cpp +++ b/osal/linux/QueueFactory.cpp @@ -15,7 +15,7 @@ QueueFactory* QueueFactory::factoryInstance = nullptr; ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, MessageQueueId_t sentFrom, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, bool ignoreFault) { return MessageQueue::sendMessageFromMessageQueue(sendTo,message, sentFrom,ignoreFault); From 13b68f10a017adb82e5f9158af72a13eff3cf5cb Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 26 Sep 2020 14:24:09 +0200 Subject: [PATCH 05/17] added usage of new interface --- osal/FreeRTOS/MessageQueue.cpp | 131 ++++++++++++------ osal/FreeRTOS/MessageQueue.h | 243 ++++++++++++++++----------------- osal/FreeRTOS/QueueFactory.cpp | 17 ++- 3 files changed, 213 insertions(+), 178 deletions(-) diff --git a/osal/FreeRTOS/MessageQueue.cpp b/osal/FreeRTOS/MessageQueue.cpp index 3bbd4d9d..2dfe5ab6 100644 --- a/osal/FreeRTOS/MessageQueue.cpp +++ b/osal/FreeRTOS/MessageQueue.cpp @@ -1,41 +1,76 @@ #include "MessageQueue.h" - +#include "../../objectmanager/ObjectManagerIF.h" #include "../../serviceinterface/ServiceInterfaceStream.h" -// TODO I guess we should have a way of checking if we are in an ISR and then use the "fromISR" versions of all calls - -MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size) : -defaultDestination(0),lastPartner(0) { - handle = xQueueCreate(message_depth, max_message_size); - if (handle == NULL) { - sif::error << "MessageQueue creation failed" << std::endl; +// TODO I guess we should have a way of checking if we are in an ISR and then +// use the "fromISR" versions of all calls +// As a first step towards this, introduces system context variable which needs +// to be switched manually +// Haven't found function to find system context. +MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize): + maxMessageSize(maxMessageSize) { + handle = xQueueCreate(messageDepth, maxMessageSize); + if (handle == nullptr) { + sif::error << "MessageQueue::MessageQueue Creation failed" << std::endl; } } MessageQueue::~MessageQueue() { - if (handle != NULL) { + if (handle != nullptr) { vQueueDelete(handle); } } +void MessageQueue::switchSystemContext(CallContext callContext) { + this->callContext = callContext; +} + ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, bool ignoreFault) { + MessageQueueMessageIF* message, bool ignoreFault) { return sendMessageFrom(sendTo, message, this->getId(), ignoreFault); } -ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message) { +ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) { return sendToDefaultFrom(message, this->getId()); } -ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) { - if (this->lastPartner != 0) { +ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message, + MessageQueueId_t sentFrom, bool ignoreFault) { + return sendMessageFrom(defaultDestination,message,sentFrom,ignoreFault); +} + +ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) { + if (this->lastPartner != MessageQueueIF::NO_QUEUE) { return sendMessageFrom(this->lastPartner, message, this->getId()); } else { return NO_REPLY_PARTNER; } } -ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message, +ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + bool ignoreFault) { + return sendMessageFromMessageQueue(sendTo, message, sentFrom, ignoreFault, + callContext); +} + + +ReturnValue_t MessageQueue::handleSendResult(BaseType_t result, bool ignoreFault) { + if (result != pdPASS) { + if (not ignoreFault) { + InternalErrorReporterIF* internalErrorReporter = objectManager-> + get( + objects::INTERNAL_ERROR_REPORTER); + if (internalErrorReporter != nullptr) { + internalErrorReporter->queueMessageNotSent(); + } + } + return MessageQueueIF::FULL; + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message, MessageQueueId_t* receivedFrom) { ReturnValue_t status = this->receiveMessage(message); if(status == HasReturnvaluesIF::RETURN_OK) { @@ -44,8 +79,9 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message, return status; } -ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) { - BaseType_t result = xQueueReceive(handle,reinterpret_cast(message->getBuffer()), 0); +ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) { + BaseType_t result = xQueueReceive(handle,reinterpret_cast( + message->getBuffer()), 0); if (result == pdPASS){ this->lastPartner = message->getSender(); return HasReturnvaluesIF::RETURN_OK; @@ -66,50 +102,55 @@ ReturnValue_t MessageQueue::flush(uint32_t* count) { } MessageQueueId_t MessageQueue::getId() const { - return (MessageQueueId_t) handle; + return reinterpret_cast(handle); } void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) { + defaultDestinationSet = true; this->defaultDestination = defaultDestination; } -ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, - MessageQueueMessage* message, MessageQueueId_t sentFrom, - bool ignoreFault) { - return sendMessageFromMessageQueue(sendTo,message,sentFrom,ignoreFault); -} - -ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessage* message, - MessageQueueId_t sentFrom, bool ignoreFault) { - return sendMessageFrom(defaultDestination,message,sentFrom,ignoreFault); -} - MessageQueueId_t MessageQueue::getDefaultDestination() const { return defaultDestination; } bool MessageQueue::isDefaultDestinationSet() const { - return 0; + return defaultDestinationSet; } + +// static core function to send messages. ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, - MessageQueueMessage *message, MessageQueueId_t sentFrom, - bool ignoreFault) { - message->setSender(sentFrom); + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + bool ignoreFault, CallContext callContext) { + BaseType_t result = pdFALSE; + QueueHandle_t destination = nullptr; - BaseType_t result = xQueueSendToBack(reinterpret_cast(sendTo), - reinterpret_cast(message->getBuffer()), 0); - if (result != pdPASS) { - if (!ignoreFault) { - InternalErrorReporterIF* internalErrorReporter = objectManager->get( - objects::INTERNAL_ERROR_REPORTER); - if (internalErrorReporter != NULL) { - internalErrorReporter->queueMessageNotSent(); - } - } - return MessageQueueIF::FULL; + if(sendTo == MessageQueueIF::NO_QUEUE or sendTo == 0x00) { + return MessageQueueIF::DESTINVATION_INVALID; + } + else { + destination = reinterpret_cast(sendTo); } - return HasReturnvaluesIF::RETURN_OK; + message->setSender(sentFrom); + + + if(callContext == CallContext::TASK) { + result = xQueueSendToBack(destination, + static_cast(message->getBuffer()), 0); + } + else { + /* If the call context is from an interrupt, + * request a context switch if a higher priority task + * was blocked by the interrupt. */ + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + result = xQueueSendFromISR(reinterpret_cast(sendTo), + static_cast(message->getBuffer()), + &xHigherPriorityTaskWoken); + if(xHigherPriorityTaskWoken == pdTRUE) { + TaskManagement::requestContextSwitch(callContext); + } + } + return handleSendResult(result, ignoreFault); } - diff --git a/osal/FreeRTOS/MessageQueue.h b/osal/FreeRTOS/MessageQueue.h index aa3d54c1..b99bf7c8 100644 --- a/osal/FreeRTOS/MessageQueue.h +++ b/osal/FreeRTOS/MessageQueue.h @@ -1,159 +1,150 @@ -#ifndef MESSAGEQUEUE_H_ -#define MESSAGEQUEUE_H_ +#ifndef FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_ +#define FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_ #include "../../internalError/InternalErrorReporterIF.h" #include "../../ipc/MessageQueueIF.h" -#include "../../ipc/MessageQueueMessage.h" +#include "../../ipc/MessageQueueMessageIF.h" +#include "../../osal/FreeRTOS/TaskManagement.h" -#include -#include +#include +#include +#include -//TODO this class assumes that MessageQueueId_t is the same size as void* (the FreeRTOS handle type), compiler will catch this but it might be nice to have something checking or even an always working solution +// TODO: this class assumes that MessageQueueId_t is the same size as void* +// (the FreeRTOS handle type), compiler will catch this but it might be nice +// to have something checking or even an always working solution // https://scaryreasoner.wordpress.com/2009/02/28/checking-sizeof-at-compile-time/ /** - * @brief This class manages sending and receiving of message queue messages. + * @brief This class manages sending and receiving of + * message queue messages. + * @details + * Message queues are used to pass asynchronous messages between processes. + * They work like post boxes, where all incoming messages are stored in FIFO + * order. This class creates a new receiving queue and provides methods to fetch + * received messages. Being a child of MessageQueueSender, this class also + * provides methods to send a message to a user-defined or a default destination. + * In addition it also provides a reply method to answer to the queue it + * received its last message from. * - * @details Message queues are used to pass asynchronous messages between processes. - * They work like post boxes, where all incoming messages are stored in FIFO - * order. This class creates a new receiving queue and provides methods to fetch - * received messages. Being a child of MessageQueueSender, this class also provides - * methods to send a message to a user-defined or a default destination. In addition - * it also provides a reply method to answer to the queue it received its last message - * from. - * The MessageQueue should be used as "post box" for a single owning object. So all - * message queue communication is "n-to-one". - * For creating the queue, as well as sending and receiving messages, the class makes - * use of the operating system calls provided. - * \ingroup message_queue + * The MessageQueue should be used as "post box" for a single owning object. + * So all message queue communication is "n-to-one". + * For creating the queue, as well as sending and receiving messages, the class + * makes use of the operating system calls provided. + * + * Please keep in mind that FreeRTOS offers different calls for message queue + * operations if called from an ISR. + * For now, the system context needs to be switched manually. + * @ingroup osal + * @ingroup message_queue */ class MessageQueue : public MessageQueueIF { friend class MessageQueueSenderIF; public: /** * @brief The constructor initializes and configures the message queue. - * @details By making use of the according operating system call, a message queue is created - * and initialized. The message depth - the maximum number of messages to be - * buffered - may be set with the help of a parameter, whereas the message size is - * automatically set to the maximum message queue message size. The operating system - * sets the message queue id, or i case of failure, it is set to zero. - * @param message_depth The number of messages to be buffered before passing an error to the - * sender. Default is three. - * @param max_message_size With this parameter, the maximum message size can be adjusted. - * This should be left default. + * @details + * By making use of the according operating system call, a message queue + * is created and initialized. The message depth - the maximum number of + * messages to be buffered - may be set with the help of a parameter, + * whereas the message size is automatically set to the maximum message + * queue message size. The operating system sets the message queue id, or + * in case of failure, it is set to zero. + * @param message_depth + * The number of messages to be buffered before passing an error to the + * sender. Default is three. + * @param max_message_size + * With this parameter, the maximum message size can be adjusted. + * This should be left default. */ - MessageQueue( size_t message_depth = 3, size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE ); + MessageQueue( size_t messageDepth = 3, + size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE ); + + /** Copying message queues forbidden */ + MessageQueue(const MessageQueue&) = delete; + MessageQueue& operator=(const MessageQueue&) = delete; + /** * @brief The destructor deletes the formerly created message queue. - * @details This is accomplished by using the delete call provided by the operating system. + * @details This is accomplished by using the delete call provided + * by the operating system. */ virtual ~MessageQueue(); + /** - * @brief This operation sends a message to the given destination. - * @details It directly uses the sendMessage call of the MessageQueueSender parent, but passes its - * queue id as "sentFrom" parameter. - * @param sendTo This parameter specifies the message queue id of the destination message queue. - * @param message A pointer to a previously created message, which is sent. - * @param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. + * This function is used to switch the call context. This has to be called + * if a message is sent or received from an ISR! + * @param callContext */ + void switchSystemContext(CallContext callContext); + + /** MessageQueueIF implementation */ ReturnValue_t sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, bool ignoreFault = false ); - /** - * @brief This operation sends a message to the default destination. - * @details As in the sendMessage method, this function uses the sendToDefault call of the - * MessageQueueSender parent class and adds its queue id as "sentFrom" information. - * @param message A pointer to a previously created message, which is sent. - */ - ReturnValue_t sendToDefault( MessageQueueMessage* message ); - /** - * @brief This operation sends a message to the last communication partner. - * @details This operation simplifies answering an incoming message by using the stored - * lastParnter information as destination. If there was no message received yet - * (i.e. lastPartner is zero), an error code is returned. - * @param message A pointer to a previously created message, which is sent. - */ - ReturnValue_t reply( MessageQueueMessage* message ); + MessageQueueMessageIF* message, bool ignoreFault = false) override; - /** - * @brief This function reads available messages from the message queue and returns the sender. - * @details It works identically to the other receiveMessage call, but in addition returns the - * sender's queue id. - * @param message A pointer to a message in which the received data is stored. - * @param receivedFrom A pointer to a queue id in which the sender's id is stored. - */ - ReturnValue_t receiveMessage(MessageQueueMessage* message, - MessageQueueId_t *receivedFrom); + ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override; - /** - * @brief This function reads available messages from the message queue. - * @details If data is available it is stored in the passed message pointer. The message's - * original content is overwritten and the sendFrom information is stored in the - * lastPartner attribute. Else, the lastPartner information remains untouched, the - * message's content is cleared and the function returns immediately. - * @param message A pointer to a message in which the received data is stored. - */ - ReturnValue_t receiveMessage(MessageQueueMessage* message); - /** - * Deletes all pending messages in the queue. - * @param count The number of flushed messages. - * @return RETURN_OK on success. - */ - ReturnValue_t flush(uint32_t* count); - /** - * @brief This method returns the message queue id of the last communication partner. - */ - MessageQueueId_t getLastPartner() const; - /** - * @brief This method returns the message queue id of this class's message queue. - */ - MessageQueueId_t getId() const; - /** - * \brief With the sendMessage call, a queue message is sent to a receiving queue. - * \details This method takes the message provided, adds the sentFrom information and passes - * it on to the destination provided with an operating system call. The OS's return - * value is returned. - * \param sendTo This parameter specifies the message queue id to send the message to. - * \param message This is a pointer to a previously created message, which is sent. - * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. - * This variable is set to zero by default. - * \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. - */ - virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ); - /** - * \brief The sendToDefault method sends a queue message to the default destination. - * \details In all other aspects, it works identical to the sendMessage method. - * \param message This is a pointer to a previously created message, which is sent. - * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. - * This variable is set to zero by default. - */ - virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ); - /** - * \brief This method is a simple setter for the default destination. - */ - void setDefaultDestination(MessageQueueId_t defaultDestination); - /** - * \brief This method is a simple getter for the default destination. - */ - MessageQueueId_t getDefaultDestination() const; + ReturnValue_t reply(MessageQueueMessageIF* message) override; + virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, + MessageQueueId_t sentFrom = NO_QUEUE, + bool ignoreFault = false) override; + + virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message, + MessageQueueId_t sentFrom = NO_QUEUE, + bool ignoreFault = false) override; + + ReturnValue_t receiveMessage(MessageQueueMessageIF* message, + MessageQueueId_t *receivedFrom) override; + + ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override; + + ReturnValue_t flush(uint32_t* count) override; + + MessageQueueId_t getLastPartner() const override; + + MessageQueueId_t getId() const override; + + void setDefaultDestination(MessageQueueId_t defaultDestination) override; + + MessageQueueId_t getDefaultDestination() const override; + + bool isDefaultDestinationSet() const override; - bool isDefaultDestinationSet() const; protected: /** - * Implementation to be called from any send Call within MessageQueue and MessageQueueSenderIF - * \details This method takes the message provided, adds the sentFrom information and passes - * it on to the destination provided with an operating system call. The OS's return - * value is returned. - * \param sendTo This parameter specifies the message queue id to send the message to. - * \param message This is a pointer to a previously created message, which is sent. - * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. - * This variable is set to zero by default. - * \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. + * @brief Implementation to be called from any send Call within + * MessageQueue and MessageQueueSenderIF. + * @details + * This method takes the message provided, adds the sentFrom information and + * passes it on to the destination provided with an operating system call. + * The OS's return value is returned. + * @param sendTo + * This parameter specifies the message queue id to send the message to. + * @param message + * This is a pointer to a previously created message, which is sent. + * @param sentFrom + * The sentFrom information can be set to inject the sender's queue id into + * the message. This variable is set to zero by default. + * @param ignoreFault + * If set to true, the internal software fault counter is not incremented + * if queue is full. + * @param context Specify whether call is made from task or from an ISR. */ - static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo,MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE,bool ignoreFault=false); + static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom = NO_QUEUE, + bool ignoreFault=false, CallContext callContext = CallContext::TASK); + + static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault); + private: + bool defaultDestinationSet = false; QueueHandle_t handle; - MessageQueueId_t defaultDestination; - MessageQueueId_t lastPartner; + MessageQueueId_t defaultDestination = MessageQueueIF::NO_QUEUE; + MessageQueueId_t lastPartner = MessageQueueIF::NO_QUEUE; + const size_t maxMessageSize; + //! Stores the current system context + CallContext callContext = CallContext::TASK; }; -#endif /* MESSAGEQUEUE_H_ */ +#endif /* FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_ */ diff --git a/osal/FreeRTOS/QueueFactory.cpp b/osal/FreeRTOS/QueueFactory.cpp index e639179a..5b3c73dc 100644 --- a/osal/FreeRTOS/QueueFactory.cpp +++ b/osal/FreeRTOS/QueueFactory.cpp @@ -1,18 +1,21 @@ +#include "../../ipc/MessageQueueSenderIF.h" #include "../../ipc/QueueFactory.h" -#include "MessageQueue.h" +#include "../../osal/FreeRTOS/MessageQueue.h" -QueueFactory* QueueFactory::factoryInstance = NULL; +QueueFactory* QueueFactory::factoryInstance = nullptr; ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, MessageQueueId_t sentFrom,bool ignoreFault) { - return MessageQueue::sendMessageFromMessageQueue(sendTo,message,sentFrom,ignoreFault); + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + bool ignoreFault) { + return MessageQueue::sendMessageFromMessageQueue(sendTo,message, + sentFrom,ignoreFault); } QueueFactory* QueueFactory::instance() { - if (factoryInstance == NULL) { + if (factoryInstance == nullptr) { factoryInstance = new QueueFactory; } return factoryInstance; @@ -24,9 +27,9 @@ QueueFactory::QueueFactory() { QueueFactory::~QueueFactory() { } -MessageQueueIF* QueueFactory::createMessageQueue(uint32_t message_depth, +MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize) { - return new MessageQueue(message_depth, maxMessageSize); + return new MessageQueue(messageDepth, maxMessageSize); } void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { From a0bc6b3c1fb3a5f8ef268b2b71d731786d51b3c2 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 26 Sep 2020 14:34:49 +0200 Subject: [PATCH 06/17] MQM IF update --- ipc/MessageQueueIF.h | 176 +++++++++++++++++++++++++++---------------- 1 file changed, 112 insertions(+), 64 deletions(-) diff --git a/ipc/MessageQueueIF.h b/ipc/MessageQueueIF.h index b0347db9..1c06521c 100644 --- a/ipc/MessageQueueIF.h +++ b/ipc/MessageQueueIF.h @@ -1,61 +1,77 @@ #ifndef FSFW_IPC_MESSAGEQUEUEIF_H_ #define FSFW_IPC_MESSAGEQUEUEIF_H_ -// COULDDO: We could support blocking calls - #include "messageQueueDefinitions.h" -#include "MessageQueueMessage.h" +#include "MessageQueueMessageIF.h" #include "../returnvalues/HasReturnvaluesIF.h" +#include + + +// COULDDO: We could support blocking calls +// semaphores are being implemented, which makes this idea even more iteresting. + +/** + * @defgroup message_queue Message Queue + * @brief Message Queue related software components + */ class MessageQueueIF { public: static const MessageQueueId_t NO_QUEUE = 0; static const uint8_t INTERFACE_ID = CLASS_ID::MESSAGE_QUEUE_IF; - /** - * No new messages on the queue - */ + //! No new messages on the queue static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(1); - /** - * No space left for more messages - */ + //! No space left for more messages static const ReturnValue_t FULL = MAKE_RETURN_CODE(2); - /** - * Returned if a reply method was called without partner - */ + //! Returned if a reply method was called without partner static const ReturnValue_t NO_REPLY_PARTNER = MAKE_RETURN_CODE(3); + //! Returned if the target destination is invalid. + static constexpr ReturnValue_t DESTINVATION_INVALID = MAKE_RETURN_CODE(4); virtual ~MessageQueueIF() {} /** * @brief This operation sends a message to the last communication partner. - * @details This operation simplifies answering an incoming message by using the stored - * lastParnter information as destination. If there was no message received yet - * (i.e. lastPartner is zero), an error code is returned. - * @param message A pointer to a previously created message, which is sent. - * \return RETURN_OK if ok - * \return NO_REPLY_PARTNER Should return NO_REPLY_PARTNER if partner was found + * @details + * This operation simplifies answering an incoming message by using the + * stored lastParnter information as destination. If there was no message + * received yet (i.e. lastPartner is zero), an error code is returned. + * @param message + * A pointer to a previously created message, which is sent. + * @return + * -@c RETURN_OK if ok + * -@c NO_REPLY_PARTNER Should return NO_REPLY_PARTNER if partner was found. */ - virtual ReturnValue_t reply( MessageQueueMessage* message ) = 0; + virtual ReturnValue_t reply(MessageQueueMessageIF* message) = 0; /** - * @brief This function reads available messages from the message queue and returns the sender. - * @details It works identically to the other receiveMessage call, but in addition returns the - * sender's queue id. - * @param message A pointer to a message in which the received data is stored. - * @param receivedFrom A pointer to a queue id in which the sender's id is stored. + * @brief This function reads available messages from the message queue + * and returns the sender. + * @details + * It works identically to the other receiveMessage call, but in addition + * returns the sender's queue id. + * @param message + * A pointer to a message in which the received data is stored. + * @param receivedFrom + * A pointer to a queue id in which the sender's id is stored. */ - virtual ReturnValue_t receiveMessage(MessageQueueMessage* message, + virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message, MessageQueueId_t *receivedFrom) = 0; /** * @brief This function reads available messages from the message queue. - * @details If data is available it is stored in the passed message pointer. The message's - * original content is overwritten and the sendFrom information is stored in the - * lastPartner attribute. Else, the lastPartner information remains untouched, the - * message's content is cleared and the function returns immediately. - * @param message A pointer to a message in which the received data is stored. + * @details + * If data is available it is stored in the passed message pointer. + * The message's original content is overwritten and the sendFrom + * information is stored in theblastPartner attribute. Else, the lastPartner + * information remains untouched, the message's content is cleared and the + * function returns immediately. + * @param message + * A pointer to a message in which the received data is stored. + * @return -@c RETURN_OK on success + * -@c MessageQueueIF::EMPTY if queue is empty */ - virtual ReturnValue_t receiveMessage(MessageQueueMessage* message) = 0; + virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) = 0; /** * Deletes all pending messages in the queue. * @param count The number of flushed messages. @@ -63,57 +79,89 @@ public: */ virtual ReturnValue_t flush(uint32_t* count) = 0; /** - * @brief This method returns the message queue id of the last communication partner. + * @brief This method returns the message queue + * id of the last communication partner. */ virtual MessageQueueId_t getLastPartner() const = 0; /** - * @brief This method returns the message queue id of this class's message queue. + * @brief This method returns the message queue + * id of this class's message queue. */ virtual MessageQueueId_t getId() const = 0; /** - * \brief With the sendMessage call, a queue message is sent to a receiving queue. - * \details This method takes the message provided, adds the sentFrom information and passes - * it on to the destination provided with an operating system call. The OS's return - * value is returned. - * \param sendTo This parameter specifies the message queue id to send the message to. - * \param message This is a pointer to a previously created message, which is sent. - * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. - * This variable is set to zero by default. - * \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full (if implemented). + * @brief With the sendMessage call, a queue message + * is sent to a receiving queue. + * @details + * This method takes the message provided, adds the sentFrom information + * and passes it on to the destination provided with an operating system + * call. The OS's returnvalue is returned. + * @param sendTo + * This parameter specifies the message queue id to send the message to. + * @param message + * This is a pointer to a previously created message, which is sent. + * @param sentFrom + * The sentFrom information can be set to inject the sender's queue id + * into the message. This variable is set to zero by default. + * @param ignoreFault + * If set to true, the internal software fault counter is not incremented + * if queue is full (if implemented). + * @return -@c RETURN_OK on success + * -@c MessageQueueIF::FULL if queue is full */ - virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0; - /** - * @brief This operation sends a message to the given destination. - * @details It directly uses the sendMessage call of the MessageQueueSender parent, but passes its - * queue id as "sentFrom" parameter. - * @param sendTo This parameter specifies the message queue id of the destination message queue. - * @param message A pointer to a previously created message, which is sent. - * @param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. - */ - virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo, MessageQueueMessage* message, bool ignoreFault = false ) = 0; + virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + bool ignoreFault = false ) = 0; /** - * \brief The sendToDefaultFrom method sends a queue message to the default destination. - * \details In all other aspects, it works identical to the sendMessage method. - * \param message This is a pointer to a previously created message, which is sent. - * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. - * This variable is set to zero by default. + * @brief This operation sends a message to the given destination. + * @details + * It directly uses the sendMessage call of the MessageQueueSender parent, + * but passes its queue id as "sentFrom" parameter. + * @param sendTo + * This parameter specifies the message queue id of the destination + * message queue. + * @param message + * A pointer to a previously created message, which is sent. + * @param ignoreFault + * If set to true, the internal software fault counter is not incremented + * if queue is full. */ - virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0; + virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo, + MessageQueueMessageIF* message, bool ignoreFault = false ) = 0; + + /** + * @brief The sendToDefaultFrom method sends a queue message + * to the default destination. + * @details + * In all other aspects, it works identical to the sendMessage method. + * @param message + * This is a pointer to a previously created message, which is sent. + * @param sentFrom + * The sentFrom information can be set to inject the sender's queue id + * into the message. This variable is set to zero by default. + * @return -@c RETURN_OK on success + * -@c MessageQueueIF::FULL if queue is full + */ + virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message, + MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0; /** * @brief This operation sends a message to the default destination. - * @details As in the sendMessage method, this function uses the sendToDefault call of the - * Implementation class and adds its queue id as "sentFrom" information. + * @details + * As in the sendMessage method, this function uses the sendToDefault + * call of the Implementation class and adds its queue id as + * "sentFrom" information. * @param message A pointer to a previously created message, which is sent. + * @return -@c RETURN_OK on success + * -@c MessageQueueIF::FULL if queue is full */ - virtual ReturnValue_t sendToDefault( MessageQueueMessage* message ) = 0; + virtual ReturnValue_t sendToDefault( MessageQueueMessageIF* message ) = 0; /** - * \brief This method is a simple setter for the default destination. + * @brief This method is a simple setter for the default destination. */ virtual void setDefaultDestination(MessageQueueId_t defaultDestination) = 0; /** - * \brief This method is a simple getter for the default destination. + * @brief This method is a simple getter for the default destination. */ virtual MessageQueueId_t getDefaultDestination() const = 0; @@ -122,4 +170,4 @@ public: -#endif /* FRAMEWORK_IPC_MESSAGEQUEUEIF_H_ */ +#endif /* FSFW_IPC_MESSAGEQUEUEIF_H_ */ From bf5688c8d8399817d276b58ff22768c54d311df9 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 26 Sep 2020 14:36:56 +0200 Subject: [PATCH 07/17] last fixes --- ipc/MessageQueueSenderIF.h | 6 +++--- ipc/QueueFactory.h | 10 ++++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/ipc/MessageQueueSenderIF.h b/ipc/MessageQueueSenderIF.h index 7eea5146..683c2908 100644 --- a/ipc/MessageQueueSenderIF.h +++ b/ipc/MessageQueueSenderIF.h @@ -1,8 +1,8 @@ #ifndef FSFW_IPC_MESSAGEQUEUESENDERIF_H_ #define FSFW_IPC_MESSAGEQUEUESENDERIF_H_ -#include "../ipc/MessageQueueIF.h" -#include "../ipc/MessageQueueMessageIF.h" +#include "MessageQueueIF.h" +#include "MessageQueueMessageIF.h" #include "../objectmanager/ObjectManagerIF.h" class MessageQueueSenderIF { @@ -15,7 +15,7 @@ public: * Not sure whether this is actually a good idea. */ static ReturnValue_t sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom = MessageQueueIF::NO_QUEUE, bool ignoreFault = false); private: diff --git a/ipc/QueueFactory.h b/ipc/QueueFactory.h index 4f4d72c7..9853d256 100644 --- a/ipc/QueueFactory.h +++ b/ipc/QueueFactory.h @@ -1,8 +1,10 @@ -#ifndef FRAMEWORK_IPC_QUEUEFACTORY_H_ -#define FRAMEWORK_IPC_QUEUEFACTORY_H_ +#ifndef FSFW_IPC_QUEUEFACTORY_H_ +#define FSFW_IPC_QUEUEFACTORY_H_ #include "MessageQueueIF.h" -#include +#include "MessageQueueMessage.h" +#include + /** * Creates message queues. * This class is a "singleton" interface, i.e. it provides an @@ -30,4 +32,4 @@ private: static QueueFactory* factoryInstance; }; -#endif /* FRAMEWORK_IPC_QUEUEFACTORY_H_ */ +#endif /* FSFW_IPC_QUEUEFACTORY_H_ */ From 6879045ef3866e5631e617b2400ce1e8ce381573 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 15:21:33 +0200 Subject: [PATCH 08/17] include fix --- ipc/MessageQueueIF.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipc/MessageQueueIF.h b/ipc/MessageQueueIF.h index 44b6f4c0..1c06521c 100644 --- a/ipc/MessageQueueIF.h +++ b/ipc/MessageQueueIF.h @@ -1,7 +1,7 @@ #ifndef FSFW_IPC_MESSAGEQUEUEIF_H_ #define FSFW_IPC_MESSAGEQUEUEIF_H_ -#include +#include "messageQueueDefinitions.h" #include "MessageQueueMessageIF.h" #include "../returnvalues/HasReturnvaluesIF.h" From 47c21cfc6c693614c1ed0627d94643d08aeeba0a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 15:22:38 +0200 Subject: [PATCH 09/17] include fix --- ipc/QueueFactory.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ipc/QueueFactory.h b/ipc/QueueFactory.h index 0310e534..9853d256 100644 --- a/ipc/QueueFactory.h +++ b/ipc/QueueFactory.h @@ -1,10 +1,10 @@ #ifndef FSFW_IPC_QUEUEFACTORY_H_ #define FSFW_IPC_QUEUEFACTORY_H_ - #include "MessageQueueIF.h" -#include "../ipc/MessageQueueMessage.h" -#include +#include "MessageQueueMessage.h" +#include + /** * Creates message queues. * This class is a "singleton" interface, i.e. it provides an From adf528fce91412c43daf349c02cee9710bf54363 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 1 Oct 2020 11:01:52 +0200 Subject: [PATCH 10/17] DH IF and DH message form improved --- devicehandlers/DeviceHandlerIF.h | 20 +++++-- devicehandlers/DeviceHandlerMessage.cpp | 19 +----- devicehandlers/DeviceHandlerMessage.h | 78 ++++++++++--------------- 3 files changed, 48 insertions(+), 69 deletions(-) diff --git a/devicehandlers/DeviceHandlerIF.h b/devicehandlers/DeviceHandlerIF.h index 52a3be4d..9c8eb098 100644 --- a/devicehandlers/DeviceHandlerIF.h +++ b/devicehandlers/DeviceHandlerIF.h @@ -1,12 +1,19 @@ -#ifndef DEVICEHANDLERIF_H_ -#define DEVICEHANDLERIF_H_ +#ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ +#define FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ + +#include "DeviceHandlerMessage.h" #include "../action/HasActionsIF.h" -#include "DeviceHandlerMessage.h" #include "../events/Event.h" #include "../modes/HasModesIF.h" #include "../ipc/MessageQueueSenderIF.h" +/** + * This is used to uniquely identify commands that are sent to a device + * The values are defined in the device-specific implementations + */ +using DeviceCommandId_t = uint32_t; + /** * @brief This is the Interface used to communicate with a device handler. * @details Includes all expected return values, events and modes. @@ -15,6 +22,7 @@ class DeviceHandlerIF { public: + static const uint8_t TRANSITION_MODE_CHILD_ACTION_MASK = 0x20; static const uint8_t TRANSITION_MODE_BASE_ACTION_MASK = 0x10; @@ -47,6 +55,8 @@ public: //! This is a transitional state which can not be commanded. //! The device handler performs all actions and commands to get the device //! shut down. When the device is off, the mode changes to @c MODE_OFF. + //! It is possible to set the mode to _MODE_SHUT_DOWN to use the to off + //! transition if available. static const Mode_t _MODE_SHUT_DOWN = TRANSITION_MODE_CHILD_ACTION_MASK | 6; //! It is possible to set the mode to _MODE_TO_ON to use the to on //! transition if available. @@ -96,7 +106,7 @@ public: static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF; // Standard codes used when building commands. - static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA0); //!< If the command size is 0. Checked in DHB + static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA0); //!< If no command data was given when expected. static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA1); //!< Command ID not in commandMap. Checked in DHB static const ReturnValue_t COMMAND_ALREADY_SENT = MAKE_RETURN_CODE(0xA2); //!< Command was already executed. Checked in DHB static const ReturnValue_t COMMAND_WAS_NOT_SENT = MAKE_RETURN_CODE(0xA3); @@ -150,4 +160,4 @@ public: }; -#endif /* DEVICEHANDLERIF_H_ */ +#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ */ diff --git a/devicehandlers/DeviceHandlerMessage.cpp b/devicehandlers/DeviceHandlerMessage.cpp index 564fae21..cb9043db 100644 --- a/devicehandlers/DeviceHandlerMessage.cpp +++ b/devicehandlers/DeviceHandlerMessage.cpp @@ -1,10 +1,6 @@ -#include "../objectmanager/ObjectManagerIF.h" #include "DeviceHandlerMessage.h" #include "../objectmanager/ObjectManagerIF.h" -DeviceHandlerMessage::DeviceHandlerMessage() { -} - store_address_t DeviceHandlerMessage::getStoreAddress( const CommandMessage* message) { return store_address_t(message->getParameter2()); @@ -25,14 +21,6 @@ uint8_t DeviceHandlerMessage::getWiretappingMode( return message->getParameter(); } -//void DeviceHandlerMessage::setDeviceHandlerDirectCommandMessage( -// CommandMessage* message, DeviceCommandId_t deviceCommand, -// store_address_t commandParametersStoreId) { -// message->setCommand(CMD_DIRECT); -// message->setParameter(deviceCommand); -// message->setParameter2(commandParametersStoreId.raw); -//} - void DeviceHandlerMessage::setDeviceHandlerRawCommandMessage( CommandMessage* message, store_address_t rawPacketStoreId) { message->setCommand(CMD_RAW); @@ -47,7 +35,7 @@ void DeviceHandlerMessage::setDeviceHandlerWiretappingMessage( void DeviceHandlerMessage::setDeviceHandlerSwitchIoBoardMessage( CommandMessage* message, uint32_t ioBoardIdentifier) { - message->setCommand(CMD_SWITCH_IOBOARD); + message->setCommand(CMD_SWITCH_ADDRESS); message->setParameter(ioBoardIdentifier); } @@ -79,18 +67,17 @@ void DeviceHandlerMessage::setDeviceHandlerDirectCommandReply( void DeviceHandlerMessage::clear(CommandMessage* message) { switch (message->getCommand()) { case CMD_RAW: -// case CMD_DIRECT: case REPLY_RAW_COMMAND: case REPLY_RAW_REPLY: case REPLY_DIRECT_COMMAND_DATA: { StorageManagerIF *ipcStore = objectManager->get( objects::IPC_STORE); - if (ipcStore != NULL) { + if (ipcStore != nullptr) { ipcStore->deleteData(getStoreAddress(message)); } } /* NO BREAK falls through*/ - case CMD_SWITCH_IOBOARD: + case CMD_SWITCH_ADDRESS: case CMD_WIRETAPPING: message->setCommand(CommandMessage::CMD_NONE); message->setParameter(0); diff --git a/devicehandlers/DeviceHandlerMessage.h b/devicehandlers/DeviceHandlerMessage.h index 8d1c94f4..e5da01c8 100644 --- a/devicehandlers/DeviceHandlerMessage.h +++ b/devicehandlers/DeviceHandlerMessage.h @@ -1,69 +1,56 @@ -#ifndef DEVICEHANDLERMESSAGE_H_ -#define DEVICEHANDLERMESSAGE_H_ +#ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_ +#define FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_ #include "../action/ActionMessage.h" #include "../ipc/CommandMessage.h" #include "../objectmanager/SystemObjectIF.h" #include "../storagemanager/StorageManagerIF.h" -//SHOULDDO: rework the static constructors to name the type of command they are building, maybe even hide setting the commandID. +// SHOULDDO: rework the static constructors to name the type of command +// they are building, maybe even hide setting the commandID. + /** - * This is used to uniquely identify commands that are sent to a device - * - * The values are defined in the device-specific implementations - */ -typedef uint32_t DeviceCommandId_t; - -/** - * The DeviceHandlerMessage is used to send Commands to a DeviceHandlerIF + * @brief The DeviceHandlerMessage is used to send commands to classes + * implementing DeviceHandlerIF */ class DeviceHandlerMessage { -private: - DeviceHandlerMessage(); public: + /** + * Instantiation forbidden. Instead, use static functions to operate + * on messages. + */ + DeviceHandlerMessage() = delete; + virtual ~DeviceHandlerMessage() {} /** * These are the commands that can be sent to a DeviceHandlerBase */ static const uint8_t MESSAGE_ID = messagetypes::DEVICE_HANDLER_COMMAND; - static const Command_t CMD_RAW = MAKE_COMMAND_ID( 1 ); //!< Sends a raw command, setParameter is a ::store_id_t containing the raw packet to send -// static const Command_t CMD_DIRECT = MAKE_COMMAND_ID( 2 ); //!< Sends a direct command, setParameter is a ::DeviceCommandId_t, setParameter2 is a ::store_id_t containing the data needed for the command - static const Command_t CMD_SWITCH_IOBOARD = MAKE_COMMAND_ID( 3 ); //!< Requests a IO-Board switch, setParameter() is the IO-Board identifier - static const Command_t CMD_WIRETAPPING = MAKE_COMMAND_ID( 4 ); //!< (De)Activates the monitoring of all raw traffic in DeviceHandlers, setParameter is 0 to deactivate, 1 to activate + //! Sends a raw command, setParameter is a storeId containing the + //! raw packet to send + static const Command_t CMD_RAW = MAKE_COMMAND_ID(1); + //! Requests a IO-Board switch, setParameter() is the IO-Board identifier + static const Command_t CMD_SWITCH_ADDRESS = MAKE_COMMAND_ID(3); + //! (De)Activates the monitoring of all raw traffic in DeviceHandlers, + //! setParameter is 0 to deactivate, 1 to activate + static const Command_t CMD_WIRETAPPING = MAKE_COMMAND_ID(4); - /*static const Command_t REPLY_SWITCHED_IOBOARD = MAKE_COMMAND_ID(1 );//!< Reply to a @c CMD_SWITCH_IOBOARD, indicates switch was successful, getParameter() contains the board switched to (0: nominal, 1: redundant) - static const Command_t REPLY_CANT_SWITCH_IOBOARD = MAKE_COMMAND_ID( 2); //!< Reply to a @c CMD_SWITCH_IOBOARD, indicating the switch could not be performed, getParameter() contains the error message - static const Command_t REPLY_WIRETAPPING = MAKE_COMMAND_ID( 3); //!< Reply to a @c CMD_WIRETAPPING, getParameter() is the current state, 1 enabled, 0 disabled - - static const Command_t REPLY_COMMAND_WAS_SENT = MAKE_COMMAND_ID(4 );//!< Reply to a @c CMD_RAW or @c CMD_DIRECT, indicates the command was successfully sent to the device, getParameter() contains the ::DeviceCommandId_t - static const Command_t REPLY_COMMAND_NOT_SUPPORTED = MAKE_COMMAND_ID(5 );//!< Reply to a @c CMD_DIRECT, the requested ::DeviceCommand_t is not supported, getParameter() contains the requested ::DeviceCommand_t, getParameter2() contains the ::DeviceCommandId_t - static const Command_t REPLY_COMMAND_WAS_NOT_SENT = MAKE_COMMAND_ID(6 );//!< Reply to a @c CMD_RAW or @c CMD_DIRECT, indicates the command was not sent, getParameter contains the RMAP Return code (@see rmap.h), getParameter2() contains the ::DeviceCommandId_t - - static const Command_t REPLY_COMMAND_ALREADY_SENT = MAKE_COMMAND_ID(7 );//!< Reply to a @c CMD_DIRECT, the requested ::DeviceCommand_t has already been sent to the device and not ye been answered - static const Command_t REPLY_WRONG_MODE_FOR_CMD = MAKE_COMMAND_ID(8 );//!< Reply to a @c CMD_RAW or @c CMD_DIRECT, indicates that the requested command can not be sent in the curent mode, getParameter() contains the DeviceHandlerCommand_t - static const Command_t REPLY_NO_DATA = MAKE_COMMAND_ID(9 ); //!< Reply to a CMD_RAW or @c CMD_DIRECT, indicates that the ::store_id_t was invalid, getParameter() contains the ::DeviceCommandId_t, getPrameter2() contains the error code - */ - static const Command_t REPLY_DIRECT_COMMAND_SENT = ActionMessage::STEP_SUCCESS; //!< Signals that a direct command was sent - static const Command_t REPLY_RAW_COMMAND = MAKE_COMMAND_ID(0x11 ); //!< Contains a raw command sent to the Device - static const Command_t REPLY_RAW_REPLY = MAKE_COMMAND_ID( 0x12); //!< Contains a raw reply from the Device, getParameter() is the ObjcetId of the sender, getParameter2() is a ::store_id_t containing the raw packet received + //! Signals that a direct command was sent + static const Command_t REPLY_DIRECT_COMMAND_SENT = ActionMessage::STEP_SUCCESS; + //! Contains a raw command sent to the Device + static const Command_t REPLY_RAW_COMMAND = MAKE_COMMAND_ID(0x11); + //! Contains a raw reply from the Device, getParameter() is the ObjcetId + //! of the sender, getParameter2() is a ::store_id_t containing the + //! raw packet received + static const Command_t REPLY_RAW_REPLY = MAKE_COMMAND_ID(0x12); static const Command_t REPLY_DIRECT_COMMAND_DATA = ActionMessage::DATA_REPLY; - /** - * Default Destructor - */ - virtual ~DeviceHandlerMessage() { - } - static store_address_t getStoreAddress(const CommandMessage* message); static uint32_t getDeviceCommandId(const CommandMessage* message); static object_id_t getDeviceObjectId(const CommandMessage *message); static object_id_t getIoBoardObjectId(const CommandMessage* message); static uint8_t getWiretappingMode(const CommandMessage* message); -// static void setDeviceHandlerDirectCommandMessage(CommandMessage* message, -// DeviceCommandId_t deviceCommand, -// store_address_t commandParametersStoreId); - static void setDeviceHandlerDirectCommandReply(CommandMessage* message, object_id_t deviceObjectid, store_address_t commandParametersStoreId); @@ -75,11 +62,6 @@ public: object_id_t deviceObjectid, store_address_t rawPacketStoreId, bool isCommand); -// static void setDeviceHandlerMessage(CommandMessage* message, -// Command_t command, DeviceCommandId_t deviceCommand, -// store_address_t commandParametersStoreId); -// static void setDeviceHandlerMessage(CommandMessage* message, -// Command_t command, store_address_t rawPacketStoreId); static void setDeviceHandlerWiretappingMessage(CommandMessage* message, uint8_t wiretappingMode); static void setDeviceHandlerSwitchIoBoardMessage(CommandMessage* message, @@ -88,4 +70,4 @@ public: static void clear(CommandMessage* message); }; -#endif /* DEVICEHANDLERMESSAGE_H_ */ +#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_ */ From 7c3f99ed2d4beba650722e596a48abb9edb837c4 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 1 Oct 2020 11:06:46 +0200 Subject: [PATCH 11/17] Revert "DH IF and DH message form improved" This reverts commit adf528fce91412c43daf349c02cee9710bf54363. --- devicehandlers/DeviceHandlerIF.h | 20 ++----- devicehandlers/DeviceHandlerMessage.cpp | 19 +++++- devicehandlers/DeviceHandlerMessage.h | 78 +++++++++++++++---------- 3 files changed, 69 insertions(+), 48 deletions(-) diff --git a/devicehandlers/DeviceHandlerIF.h b/devicehandlers/DeviceHandlerIF.h index 9c8eb098..52a3be4d 100644 --- a/devicehandlers/DeviceHandlerIF.h +++ b/devicehandlers/DeviceHandlerIF.h @@ -1,19 +1,12 @@ -#ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ -#define FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ - -#include "DeviceHandlerMessage.h" +#ifndef DEVICEHANDLERIF_H_ +#define DEVICEHANDLERIF_H_ #include "../action/HasActionsIF.h" +#include "DeviceHandlerMessage.h" #include "../events/Event.h" #include "../modes/HasModesIF.h" #include "../ipc/MessageQueueSenderIF.h" -/** - * This is used to uniquely identify commands that are sent to a device - * The values are defined in the device-specific implementations - */ -using DeviceCommandId_t = uint32_t; - /** * @brief This is the Interface used to communicate with a device handler. * @details Includes all expected return values, events and modes. @@ -22,7 +15,6 @@ using DeviceCommandId_t = uint32_t; class DeviceHandlerIF { public: - static const uint8_t TRANSITION_MODE_CHILD_ACTION_MASK = 0x20; static const uint8_t TRANSITION_MODE_BASE_ACTION_MASK = 0x10; @@ -55,8 +47,6 @@ public: //! This is a transitional state which can not be commanded. //! The device handler performs all actions and commands to get the device //! shut down. When the device is off, the mode changes to @c MODE_OFF. - //! It is possible to set the mode to _MODE_SHUT_DOWN to use the to off - //! transition if available. static const Mode_t _MODE_SHUT_DOWN = TRANSITION_MODE_CHILD_ACTION_MASK | 6; //! It is possible to set the mode to _MODE_TO_ON to use the to on //! transition if available. @@ -106,7 +96,7 @@ public: static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF; // Standard codes used when building commands. - static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA0); //!< If no command data was given when expected. + static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA0); //!< If the command size is 0. Checked in DHB static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA1); //!< Command ID not in commandMap. Checked in DHB static const ReturnValue_t COMMAND_ALREADY_SENT = MAKE_RETURN_CODE(0xA2); //!< Command was already executed. Checked in DHB static const ReturnValue_t COMMAND_WAS_NOT_SENT = MAKE_RETURN_CODE(0xA3); @@ -160,4 +150,4 @@ public: }; -#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ */ +#endif /* DEVICEHANDLERIF_H_ */ diff --git a/devicehandlers/DeviceHandlerMessage.cpp b/devicehandlers/DeviceHandlerMessage.cpp index cb9043db..564fae21 100644 --- a/devicehandlers/DeviceHandlerMessage.cpp +++ b/devicehandlers/DeviceHandlerMessage.cpp @@ -1,6 +1,10 @@ +#include "../objectmanager/ObjectManagerIF.h" #include "DeviceHandlerMessage.h" #include "../objectmanager/ObjectManagerIF.h" +DeviceHandlerMessage::DeviceHandlerMessage() { +} + store_address_t DeviceHandlerMessage::getStoreAddress( const CommandMessage* message) { return store_address_t(message->getParameter2()); @@ -21,6 +25,14 @@ uint8_t DeviceHandlerMessage::getWiretappingMode( return message->getParameter(); } +//void DeviceHandlerMessage::setDeviceHandlerDirectCommandMessage( +// CommandMessage* message, DeviceCommandId_t deviceCommand, +// store_address_t commandParametersStoreId) { +// message->setCommand(CMD_DIRECT); +// message->setParameter(deviceCommand); +// message->setParameter2(commandParametersStoreId.raw); +//} + void DeviceHandlerMessage::setDeviceHandlerRawCommandMessage( CommandMessage* message, store_address_t rawPacketStoreId) { message->setCommand(CMD_RAW); @@ -35,7 +47,7 @@ void DeviceHandlerMessage::setDeviceHandlerWiretappingMessage( void DeviceHandlerMessage::setDeviceHandlerSwitchIoBoardMessage( CommandMessage* message, uint32_t ioBoardIdentifier) { - message->setCommand(CMD_SWITCH_ADDRESS); + message->setCommand(CMD_SWITCH_IOBOARD); message->setParameter(ioBoardIdentifier); } @@ -67,17 +79,18 @@ void DeviceHandlerMessage::setDeviceHandlerDirectCommandReply( void DeviceHandlerMessage::clear(CommandMessage* message) { switch (message->getCommand()) { case CMD_RAW: +// case CMD_DIRECT: case REPLY_RAW_COMMAND: case REPLY_RAW_REPLY: case REPLY_DIRECT_COMMAND_DATA: { StorageManagerIF *ipcStore = objectManager->get( objects::IPC_STORE); - if (ipcStore != nullptr) { + if (ipcStore != NULL) { ipcStore->deleteData(getStoreAddress(message)); } } /* NO BREAK falls through*/ - case CMD_SWITCH_ADDRESS: + case CMD_SWITCH_IOBOARD: case CMD_WIRETAPPING: message->setCommand(CommandMessage::CMD_NONE); message->setParameter(0); diff --git a/devicehandlers/DeviceHandlerMessage.h b/devicehandlers/DeviceHandlerMessage.h index e5da01c8..8d1c94f4 100644 --- a/devicehandlers/DeviceHandlerMessage.h +++ b/devicehandlers/DeviceHandlerMessage.h @@ -1,56 +1,69 @@ -#ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_ -#define FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_ +#ifndef DEVICEHANDLERMESSAGE_H_ +#define DEVICEHANDLERMESSAGE_H_ #include "../action/ActionMessage.h" #include "../ipc/CommandMessage.h" #include "../objectmanager/SystemObjectIF.h" #include "../storagemanager/StorageManagerIF.h" -// SHOULDDO: rework the static constructors to name the type of command -// they are building, maybe even hide setting the commandID. - +//SHOULDDO: rework the static constructors to name the type of command they are building, maybe even hide setting the commandID. /** - * @brief The DeviceHandlerMessage is used to send commands to classes - * implementing DeviceHandlerIF + * This is used to uniquely identify commands that are sent to a device + * + * The values are defined in the device-specific implementations + */ +typedef uint32_t DeviceCommandId_t; + +/** + * The DeviceHandlerMessage is used to send Commands to a DeviceHandlerIF */ class DeviceHandlerMessage { +private: + DeviceHandlerMessage(); public: - /** - * Instantiation forbidden. Instead, use static functions to operate - * on messages. - */ - DeviceHandlerMessage() = delete; - virtual ~DeviceHandlerMessage() {} /** * These are the commands that can be sent to a DeviceHandlerBase */ static const uint8_t MESSAGE_ID = messagetypes::DEVICE_HANDLER_COMMAND; - //! Sends a raw command, setParameter is a storeId containing the - //! raw packet to send - static const Command_t CMD_RAW = MAKE_COMMAND_ID(1); - //! Requests a IO-Board switch, setParameter() is the IO-Board identifier - static const Command_t CMD_SWITCH_ADDRESS = MAKE_COMMAND_ID(3); - //! (De)Activates the monitoring of all raw traffic in DeviceHandlers, - //! setParameter is 0 to deactivate, 1 to activate - static const Command_t CMD_WIRETAPPING = MAKE_COMMAND_ID(4); + static const Command_t CMD_RAW = MAKE_COMMAND_ID( 1 ); //!< Sends a raw command, setParameter is a ::store_id_t containing the raw packet to send +// static const Command_t CMD_DIRECT = MAKE_COMMAND_ID( 2 ); //!< Sends a direct command, setParameter is a ::DeviceCommandId_t, setParameter2 is a ::store_id_t containing the data needed for the command + static const Command_t CMD_SWITCH_IOBOARD = MAKE_COMMAND_ID( 3 ); //!< Requests a IO-Board switch, setParameter() is the IO-Board identifier + static const Command_t CMD_WIRETAPPING = MAKE_COMMAND_ID( 4 ); //!< (De)Activates the monitoring of all raw traffic in DeviceHandlers, setParameter is 0 to deactivate, 1 to activate - //! Signals that a direct command was sent - static const Command_t REPLY_DIRECT_COMMAND_SENT = ActionMessage::STEP_SUCCESS; - //! Contains a raw command sent to the Device - static const Command_t REPLY_RAW_COMMAND = MAKE_COMMAND_ID(0x11); - //! Contains a raw reply from the Device, getParameter() is the ObjcetId - //! of the sender, getParameter2() is a ::store_id_t containing the - //! raw packet received - static const Command_t REPLY_RAW_REPLY = MAKE_COMMAND_ID(0x12); + /*static const Command_t REPLY_SWITCHED_IOBOARD = MAKE_COMMAND_ID(1 );//!< Reply to a @c CMD_SWITCH_IOBOARD, indicates switch was successful, getParameter() contains the board switched to (0: nominal, 1: redundant) + static const Command_t REPLY_CANT_SWITCH_IOBOARD = MAKE_COMMAND_ID( 2); //!< Reply to a @c CMD_SWITCH_IOBOARD, indicating the switch could not be performed, getParameter() contains the error message + static const Command_t REPLY_WIRETAPPING = MAKE_COMMAND_ID( 3); //!< Reply to a @c CMD_WIRETAPPING, getParameter() is the current state, 1 enabled, 0 disabled + + static const Command_t REPLY_COMMAND_WAS_SENT = MAKE_COMMAND_ID(4 );//!< Reply to a @c CMD_RAW or @c CMD_DIRECT, indicates the command was successfully sent to the device, getParameter() contains the ::DeviceCommandId_t + static const Command_t REPLY_COMMAND_NOT_SUPPORTED = MAKE_COMMAND_ID(5 );//!< Reply to a @c CMD_DIRECT, the requested ::DeviceCommand_t is not supported, getParameter() contains the requested ::DeviceCommand_t, getParameter2() contains the ::DeviceCommandId_t + static const Command_t REPLY_COMMAND_WAS_NOT_SENT = MAKE_COMMAND_ID(6 );//!< Reply to a @c CMD_RAW or @c CMD_DIRECT, indicates the command was not sent, getParameter contains the RMAP Return code (@see rmap.h), getParameter2() contains the ::DeviceCommandId_t + + static const Command_t REPLY_COMMAND_ALREADY_SENT = MAKE_COMMAND_ID(7 );//!< Reply to a @c CMD_DIRECT, the requested ::DeviceCommand_t has already been sent to the device and not ye been answered + static const Command_t REPLY_WRONG_MODE_FOR_CMD = MAKE_COMMAND_ID(8 );//!< Reply to a @c CMD_RAW or @c CMD_DIRECT, indicates that the requested command can not be sent in the curent mode, getParameter() contains the DeviceHandlerCommand_t + static const Command_t REPLY_NO_DATA = MAKE_COMMAND_ID(9 ); //!< Reply to a CMD_RAW or @c CMD_DIRECT, indicates that the ::store_id_t was invalid, getParameter() contains the ::DeviceCommandId_t, getPrameter2() contains the error code + */ + static const Command_t REPLY_DIRECT_COMMAND_SENT = ActionMessage::STEP_SUCCESS; //!< Signals that a direct command was sent + static const Command_t REPLY_RAW_COMMAND = MAKE_COMMAND_ID(0x11 ); //!< Contains a raw command sent to the Device + static const Command_t REPLY_RAW_REPLY = MAKE_COMMAND_ID( 0x12); //!< Contains a raw reply from the Device, getParameter() is the ObjcetId of the sender, getParameter2() is a ::store_id_t containing the raw packet received static const Command_t REPLY_DIRECT_COMMAND_DATA = ActionMessage::DATA_REPLY; + /** + * Default Destructor + */ + virtual ~DeviceHandlerMessage() { + } + static store_address_t getStoreAddress(const CommandMessage* message); static uint32_t getDeviceCommandId(const CommandMessage* message); static object_id_t getDeviceObjectId(const CommandMessage *message); static object_id_t getIoBoardObjectId(const CommandMessage* message); static uint8_t getWiretappingMode(const CommandMessage* message); +// static void setDeviceHandlerDirectCommandMessage(CommandMessage* message, +// DeviceCommandId_t deviceCommand, +// store_address_t commandParametersStoreId); + static void setDeviceHandlerDirectCommandReply(CommandMessage* message, object_id_t deviceObjectid, store_address_t commandParametersStoreId); @@ -62,6 +75,11 @@ public: object_id_t deviceObjectid, store_address_t rawPacketStoreId, bool isCommand); +// static void setDeviceHandlerMessage(CommandMessage* message, +// Command_t command, DeviceCommandId_t deviceCommand, +// store_address_t commandParametersStoreId); +// static void setDeviceHandlerMessage(CommandMessage* message, +// Command_t command, store_address_t rawPacketStoreId); static void setDeviceHandlerWiretappingMessage(CommandMessage* message, uint8_t wiretappingMode); static void setDeviceHandlerSwitchIoBoardMessage(CommandMessage* message, @@ -70,4 +88,4 @@ public: static void clear(CommandMessage* message); }; -#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_ */ +#endif /* DEVICEHANDLERMESSAGE_H_ */ From 1f3a10b37554c1b8872a2dd82e0ebb4673e270f7 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Thu, 1 Oct 2020 13:30:28 +0200 Subject: [PATCH 12/17] Fixes and comments in FixedOrderedMultimap --- container/FixedOrderedMultimap.h | 208 +++++++++++++++++++++++-------- 1 file changed, 159 insertions(+), 49 deletions(-) diff --git a/container/FixedOrderedMultimap.h b/container/FixedOrderedMultimap.h index 717575d7..a9f093d6 100644 --- a/container/FixedOrderedMultimap.h +++ b/container/FixedOrderedMultimap.h @@ -5,6 +5,24 @@ #include #include /** + * @brief A "Map" which allows multiple entries of the same key. + * @details + * Same keys are ordered by KEY_COMPARE function which is std::less > by default. + * + * It uses the ArrayList, so technically this is not a real map, it is an array of pairs + * of type key_t, T. It is ordered by key_t as FixedMap but allows same keys. + * + * Its of fixed size so no allocations are performed after the construction. + * + * The maximum size is given as first parameter of the constructor. + * + * It provides an iterator to do list iterations. + * + * The type T must have a copy constructor if it is not trivial copy-able. + * + * @warning Iterators return a non-const key_t in the pair. + * @warning A User is not allowed to change the key, otherwise the map is corrupted. + * * \ingroup container */ template> @@ -14,78 +32,84 @@ public: static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x01); static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x02); -private: - typedef KEY_COMPARE compare; - compare myComp; - ArrayList, uint32_t> theMap; - uint32_t _size; - - uint32_t findFirstIndex(key_t key, uint32_t startAt = 0) const { - if (startAt >= _size) { - return startAt + 1; - } - uint32_t i = startAt; - for (i = startAt; i < _size; ++i) { - if (theMap[i].first == key) { - return i; - } - } - return i; - } - - uint32_t findNicePlace(key_t key) const { - uint32_t i = 0; - for (i = 0; i < _size; ++i) { - if (myComp(key, theMap[i].first)) { - return i; - } - } - return i; - } - - void removeFromPosition(uint32_t position) { - if (_size <= position) { - return; - } - memmove(static_cast(&theMap[position]), static_cast(&theMap[position + 1]), - (_size - position - 1) * sizeof(std::pair)); - --_size; - } -public: - FixedOrderedMultimap(uint32_t maxSize) : - theMap(maxSize), _size(0) { + /*** + * Constructor which needs a size_t for the maximum allowed size + * + * Can not be resized during runtime + * + * Allocates memory at construction + * @param maxSize size_t of Maximum allowed size + */ + FixedOrderedMultimap(size_t maxSize) : + theMap(maxSize), _size(0) { } + /*** + * Virtual destructor frees Memory by deleting its member + */ virtual ~FixedOrderedMultimap() { } - class Iterator: public ArrayList, uint32_t>::Iterator { + /*** + * Special iterator for FixedOrderedMultimap + */ + class Iterator: public ArrayList, size_t>::Iterator { public: Iterator() : - ArrayList, uint32_t>::Iterator() { + ArrayList, size_t>::Iterator() { } Iterator(std::pair *pair) : - ArrayList, uint32_t>::Iterator(pair) { + ArrayList, size_t>::Iterator(pair) { } }; + friend bool operator==(const typename FixedOrderedMultimap::Iterator& lhs, + const typename FixedOrderedMultimap::Iterator& rhs) { + return (lhs.value == rhs.value); + } + + friend bool operator!=(const typename FixedOrderedMultimap::Iterator& lhs, + const typename FixedOrderedMultimap::Iterator& rhs) { + return not (lhs.value == rhs.value); + } + + /*** + * Returns an iterator on the first element + * @return Iterator pointing to first element + */ Iterator begin() const { return Iterator(&theMap[0]); } + /** + * Returns an iterator pointing to one element past the end + * @return Iterator pointing to one element past the end + */ Iterator end() const { return Iterator(&theMap[_size]); } - uint32_t size() const { + /*** + * Returns the current size of the map (not maximum size!) + * @return Current size + */ + size_t size() const { return _size; } + /*** + * Used to insert a key and value separately. + * + * @param[in] key Key of the new element + * @param[in] value Value of the new element + * @param[in/out] (optional) storedValue On success this points to the new value, otherwise a nullptr + * @return RETURN_OK if insert was successful, MAP_FULL if no space is available + */ ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr) { if (_size == theMap.maxSize()) { return MAP_FULL; } - uint32_t position = findNicePlace(key); + size_t position = findNicePlace(key); memmove(static_cast(&theMap[position + 1]),static_cast(&theMap[position]), (_size - position) * sizeof(std::pair)); theMap[position].first = key; @@ -97,10 +121,21 @@ public: return HasReturnvaluesIF::RETURN_OK; } + /*** + * Used to insert new pair instead of single values + * + * @param pair Pair to be inserted + * @return RETURN_OK if insert was successful, MAP_FULL if no space is available + */ ReturnValue_t insert(std::pair pair) { return insert(pair.first, pair.second); } + /*** + * Can be used to check if a certain key is in the map + * @param key Key to be checked + * @return RETURN_OK if the key exists KEY_DOES_NOT_EXIST otherwise + */ ReturnValue_t exists(key_t key) const { ReturnValue_t result = KEY_DOES_NOT_EXIST; if (findFirstIndex(key) < _size) { @@ -109,8 +144,18 @@ public: return result; } + /*** + * Used to delete the element in the iterator + * + * The iterator will point to the element before or begin(), + * but never to one element in front of the map. + * + * @warning The iterator needs to be valid and dereferenceable + * @param[in/out] iter Pointer to iterator to the element that needs to be ereased + * @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this + */ ReturnValue_t erase(Iterator *iter) { - uint32_t i; + size_t i; if ((i = findFirstIndex((*iter).value->first)) >= _size) { return KEY_DOES_NOT_EXIST; } @@ -123,8 +168,13 @@ public: return HasReturnvaluesIF::RETURN_OK; } + /*** + * Used to erase by key + * @param key Key to be erased + * @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this + */ ReturnValue_t erase(key_t key) { - uint32_t i; + size_t i; if ((i = findFirstIndex(key)) >= _size) { return KEY_DOES_NOT_EXIST; } @@ -135,6 +185,14 @@ public: return HasReturnvaluesIF::RETURN_OK; } + /*** + * Find returns the first appearance of the key + * + * If the key does not exist, it points to end() + * + * @param key Key to search for + * @return Iterator pointing to the first entry of key + */ Iterator find(key_t key) const { ReturnValue_t result = exists(key); if (result != HasReturnvaluesIF::RETURN_OK) { @@ -143,6 +201,15 @@ public: return Iterator(&theMap[findFirstIndex(key)]); } + /*** + * Finds first entry of the given key and returns a + * pointer to the value + * + * @param key Key to search for + * @param value Found value + * @return RETURN_OK if it points to the value, + * KEY_DOES_NOT_EXIST if the key is not in the map + */ ReturnValue_t find(key_t key, T **value) const { ReturnValue_t result = exists(key); if (result != HasReturnvaluesIF::RETURN_OK) { @@ -151,15 +218,58 @@ public: *value = &theMap[findFirstIndex(key)].second; return HasReturnvaluesIF::RETURN_OK; } - + /** + * Clears the map, does not deallocate any memory + */ void clear() { _size = 0; } - uint32_t maxSize() const { + /** + * Returns the maximum size of the map + * @return Maximum size of the map + */ + size_t maxSize() const { return theMap.maxSize(); } +private: + typedef KEY_COMPARE compare; + compare myComp; + ArrayList, size_t> theMap; + size_t _size; + + size_t findFirstIndex(key_t key, size_t startAt = 0) const { + if (startAt >= _size) { + return startAt + 1; + } + size_t i = startAt; + for (i = startAt; i < _size; ++i) { + if (theMap[i].first == key) { + return i; + } + } + return i; + } + + size_t findNicePlace(key_t key) const { + size_t i = 0; + for (i = 0; i < _size; ++i) { + if (myComp(key, theMap[i].first)) { + return i; + } + } + return i; + } + + void removeFromPosition(size_t position) { + if (_size <= position) { + return; + } + memmove(static_cast(&theMap[position]), static_cast(&theMap[position + 1]), + (_size - position - 1) * sizeof(std::pair)); + --_size; + } }; #endif /* FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ */ From c86d654fdfedfb3319e9ace45dc83874ce8d5c6a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 1 Oct 2020 13:58:20 +0200 Subject: [PATCH 13/17] tpp file added --- container/FixedOrderedMultimap.h | 197 ++++++++++++----------------- container/FixedOrderedMultimap.tpp | 143 +++++++++++++++++++++ 2 files changed, 222 insertions(+), 118 deletions(-) create mode 100644 container/FixedOrderedMultimap.tpp diff --git a/container/FixedOrderedMultimap.h b/container/FixedOrderedMultimap.h index 717575d7..cb8ab10f 100644 --- a/container/FixedOrderedMultimap.h +++ b/container/FixedOrderedMultimap.h @@ -1,24 +1,91 @@ -#ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ -#define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ +#ifndef FSFW_CONTAINER_FIXEDORDEREDMULTIMAP_H_ +#define FSFW_CONTAINER_FIXEDORDEREDMULTIMAP_H_ #include "ArrayList.h" #include -#include + /** - * \ingroup container + * @brief Map implementation which allows entries with identical keys + * @details + * Performs no dynamic memory allocation except on initialization. + * Uses an ArrayList as the underlying container and thus has a linear + * complexity O(n). As long as the number of entries remains low, this + * should not be an issue. + * The number of insertion and deletion operation should be minimized + * as those incur exensive memory move operations (the underlying container + * is not node based). + * @ingroup container */ template> class FixedOrderedMultimap { public: static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MULTIMAP; - static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x01); - static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x02); + static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01); + static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02); + static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03); + + /** + * Initializes the ordered multimap with a fixed maximum size. + * @param maxSize + */ + FixedOrderedMultimap(size_t maxSize); + + virtual ~FixedOrderedMultimap() {} + + class Iterator: public ArrayList, uint32_t>::Iterator { + public: + /** Returns an iterator to nullptr */ + Iterator(); + /** Initializes iterator to given entry */ + Iterator(std::pair *pair); + }; + + /** Iterator to start of map */ + Iterator begin() const; + /** Iterator to end of map */ + Iterator end() const; + /** Current (variable) size of the map */ + size_t size() const; + + /** + * Insert a key/value pair inside the map. An iterator to the stored + * value might be returned optionally. + * @param key + * @param value + * @param storedValue + * @return + */ + ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr); + /** + * Insert a given std::pair + * @param pair + * @return + */ + ReturnValue_t insert(std::pair pair); + /** + * Checks existence of key in map. + * @param key + * @return + * - @c KEY_DOES_NOT_EXIST if key does not exists. + * - @c RETURN_OK otherwise. + */ + ReturnValue_t exists(key_t key) const; + + ReturnValue_t erase(Iterator *iter); + ReturnValue_t erase(key_t key); + + Iterator find(key_t key) const; + ReturnValue_t find(key_t key, T **value) const; + + void clear(); + + size_t maxSize() const; private: typedef KEY_COMPARE compare; compare myComp; ArrayList, uint32_t> theMap; - uint32_t _size; + size_t _size; uint32_t findFirstIndex(key_t key, uint32_t startAt = 0) const { if (startAt >= _size) { @@ -47,119 +114,13 @@ private: if (_size <= position) { return; } - memmove(static_cast(&theMap[position]), static_cast(&theMap[position + 1]), + std::memmove(static_cast(&theMap[position]), + static_cast(&theMap[position + 1]), (_size - position - 1) * sizeof(std::pair)); --_size; } -public: - FixedOrderedMultimap(uint32_t maxSize) : - theMap(maxSize), _size(0) { - } - virtual ~FixedOrderedMultimap() { - } - - class Iterator: public ArrayList, uint32_t>::Iterator { - public: - Iterator() : - ArrayList, uint32_t>::Iterator() { - } - - Iterator(std::pair *pair) : - ArrayList, uint32_t>::Iterator(pair) { - } - }; - - Iterator begin() const { - return Iterator(&theMap[0]); - } - - Iterator end() const { - return Iterator(&theMap[_size]); - } - - uint32_t size() const { - return _size; - } - - ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr) { - if (_size == theMap.maxSize()) { - return MAP_FULL; - } - uint32_t position = findNicePlace(key); - memmove(static_cast(&theMap[position + 1]),static_cast(&theMap[position]), - (_size - position) * sizeof(std::pair)); - theMap[position].first = key; - theMap[position].second = value; - ++_size; - if (storedValue != nullptr) { - *storedValue = Iterator(&theMap[position]); - } - return HasReturnvaluesIF::RETURN_OK; - } - - ReturnValue_t insert(std::pair pair) { - return insert(pair.first, pair.second); - } - - ReturnValue_t exists(key_t key) const { - ReturnValue_t result = KEY_DOES_NOT_EXIST; - if (findFirstIndex(key) < _size) { - result = HasReturnvaluesIF::RETURN_OK; - } - return result; - } - - ReturnValue_t erase(Iterator *iter) { - uint32_t i; - if ((i = findFirstIndex((*iter).value->first)) >= _size) { - return KEY_DOES_NOT_EXIST; - } - removeFromPosition(i); - if (*iter != begin()) { - (*iter)--; - } else { - *iter = begin(); - } - return HasReturnvaluesIF::RETURN_OK; - } - - ReturnValue_t erase(key_t key) { - uint32_t i; - if ((i = findFirstIndex(key)) >= _size) { - return KEY_DOES_NOT_EXIST; - } - do { - removeFromPosition(i); - i = findFirstIndex(key, i); - } while (i < _size); - return HasReturnvaluesIF::RETURN_OK; - } - - Iterator find(key_t key) const { - ReturnValue_t result = exists(key); - if (result != HasReturnvaluesIF::RETURN_OK) { - return end(); - } - return Iterator(&theMap[findFirstIndex(key)]); - } - - ReturnValue_t find(key_t key, T **value) const { - ReturnValue_t result = exists(key); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - *value = &theMap[findFirstIndex(key)].second; - return HasReturnvaluesIF::RETURN_OK; - } - - void clear() { - _size = 0; - } - - uint32_t maxSize() const { - return theMap.maxSize(); - } - }; -#endif /* FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ */ +#include "FixedOrderedMultimap.tpp" + +#endif /* FSFW_CONTAINER_FIXEDORDEREDMULTIMAP_H_ */ diff --git a/container/FixedOrderedMultimap.tpp b/container/FixedOrderedMultimap.tpp new file mode 100644 index 00000000..bc76c594 --- /dev/null +++ b/container/FixedOrderedMultimap.tpp @@ -0,0 +1,143 @@ +#ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ +#define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ + +template +inline FixedOrderedMultimap::Iterator::Iterator(): + ArrayList, uint32_t>::Iterator(){} + +template +inline FixedOrderedMultimap::Iterator::Iterator( + std::pair *pair): + ArrayList, uint32_t>::Iterator(pair){} + +template +inline typename FixedOrderedMultimap::Iterator +FixedOrderedMultimap::begin() const { + return Iterator(&theMap[0]); +} + +template +inline typename FixedOrderedMultimap::Iterator +FixedOrderedMultimap::end() const { + return Iterator(&theMap[_size]); +} + + +template +inline size_t FixedOrderedMultimap::size() const { + return _size; +} + +template +inline FixedOrderedMultimap::FixedOrderedMultimap( + size_t maxSize): theMap(maxSize), _size(0) {} + + +template +inline ReturnValue_t FixedOrderedMultimap::insert( + key_t key, T value, Iterator *storedValue) { + if (_size == theMap.maxSize()) { + return MAP_FULL; + } + uint32_t position = findNicePlace(key); + // Compiler might emitt warning because std::pair is not a POD type (yet..) + // See: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2342.htm#std::pair-example + // Circumvent warning by casting to void* + std::memmove(static_cast(&theMap[position + 1]), + static_cast(&theMap[position]), + (_size - position) * sizeof(std::pair)); + theMap[position].first = key; + theMap[position].second = value; + ++_size; + if (storedValue != nullptr) { + *storedValue = Iterator(&theMap[position]); + } + return HasReturnvaluesIF::RETURN_OK; +} + +template +inline ReturnValue_t FixedOrderedMultimap::insert( + std::pair pair) { + return insert(pair.fist, pair.second); +} + +template +inline ReturnValue_t FixedOrderedMultimap::exists( + key_t key) const { + ReturnValue_t result = KEY_DOES_NOT_EXIST; + if (findFirstIndex(key) < _size) { + result = HasReturnvaluesIF::RETURN_OK; + } + return result; +} + +template +inline ReturnValue_t FixedOrderedMultimap::erase( + Iterator *iter) +{ + uint32_t i; + if ((i = findFirstIndex((*iter).value->first)) >= _size) { + return KEY_DOES_NOT_EXIST; + } + removeFromPosition(i); + if (*iter != begin()) { + (*iter)--; + } else { + *iter = begin(); + } + return HasReturnvaluesIF::RETURN_OK; +} + +template +inline ReturnValue_t FixedOrderedMultimap::erase( + key_t key) +{ + uint32_t i; + if ((i = findFirstIndex(key)) >= _size) { + return KEY_DOES_NOT_EXIST; + } + do { + removeFromPosition(i); + i = findFirstIndex(key, i); + } while (i < _size); + return HasReturnvaluesIF::RETURN_OK; +} + +template +inline ReturnValue_t FixedOrderedMultimap::find( + key_t key, T **value) const +{ + ReturnValue_t result = exists(key); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + *value = &theMap[findFirstIndex(key)].second; + return HasReturnvaluesIF::RETURN_OK; +} + +template +inline typename FixedOrderedMultimap::Iterator +FixedOrderedMultimap::find( + key_t key) const +{ + ReturnValue_t result = exists(key); + if (result != HasReturnvaluesIF::RETURN_OK) { + return end(); + } + return Iterator(&theMap[findFirstIndex(key)]); +} + +template +inline void FixedOrderedMultimap::clear() +{ + _size = 0; +} + +template +inline size_t FixedOrderedMultimap::maxSize() const +{ + return theMap.maxSize(); +} + + +#endif /* FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ */ From 587f87d270b282726363f348467f130370d61f96 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Thu, 1 Oct 2020 17:27:24 +0200 Subject: [PATCH 14/17] Feedback from Robin --- container/FixedOrderedMultimap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/FixedOrderedMultimap.h b/container/FixedOrderedMultimap.h index 4bbea302..82d388c9 100644 --- a/container/FixedOrderedMultimap.h +++ b/container/FixedOrderedMultimap.h @@ -5,7 +5,7 @@ #include /** - * @brief A "Map" which allows multiple entries of the same key. + * @brief An associative container which allows multiple entries of the same key. * @details * Same keys are ordered by KEY_COMPARE function which is std::less > by default. * From f1bc9972f3217981b895a6e48e9aca816340512c Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Thu, 1 Oct 2020 17:36:46 +0200 Subject: [PATCH 15/17] Fixed bugs --- container/FixedOrderedMultimap.tpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/container/FixedOrderedMultimap.tpp b/container/FixedOrderedMultimap.tpp index 715bf474..16a7124b 100644 --- a/container/FixedOrderedMultimap.tpp +++ b/container/FixedOrderedMultimap.tpp @@ -2,8 +2,8 @@ #define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ -template> -ReturnValue_t FixedOrderedMultimap::insert(key_t key, T value, Iterator *storedValue = nullptr) { +template +ReturnValue_t FixedOrderedMultimap::insert(key_t key, T value, Iterator *storedValue) { if (_size == theMap.maxSize()) { return MAP_FULL; } @@ -18,12 +18,12 @@ ReturnValue_t FixedOrderedMultimap::insert(key_t key, T v } return HasReturnvaluesIF::RETURN_OK; } -template> +template ReturnValue_t FixedOrderedMultimap::insert(std::pair pair) { return insert(pair.first, pair.second); } -template> +template ReturnValue_t FixedOrderedMultimap::exists(key_t key) const { ReturnValue_t result = KEY_DOES_NOT_EXIST; if (findFirstIndex(key) < _size) { @@ -32,7 +32,7 @@ ReturnValue_t FixedOrderedMultimap::exists(key_t key) con return result; } -template> +template ReturnValue_t FixedOrderedMultimap::erase(Iterator *iter) { size_t i; if ((i = findFirstIndex((*iter).value->first)) >= _size) { @@ -47,7 +47,7 @@ ReturnValue_t FixedOrderedMultimap::erase(Iterator *iter) return HasReturnvaluesIF::RETURN_OK; } -template> +template ReturnValue_t FixedOrderedMultimap::erase(key_t key) { size_t i; if ((i = findFirstIndex(key)) >= _size) { @@ -60,7 +60,7 @@ ReturnValue_t FixedOrderedMultimap::erase(key_t key) { return HasReturnvaluesIF::RETURN_OK; } -template> +template FixedOrderedMultimap::Iterator FixedOrderedMultimap::find(key_t key) const { ReturnValue_t result = exists(key); if (result != HasReturnvaluesIF::RETURN_OK) { @@ -69,7 +69,7 @@ FixedOrderedMultimap::Iterator FixedOrderedMultimap> +template ReturnValue_t FixedOrderedMultimap::find(key_t key, T **value) const { ReturnValue_t result = exists(key); if (result != HasReturnvaluesIF::RETURN_OK) { @@ -79,8 +79,8 @@ ReturnValue_t FixedOrderedMultimap::find(key_t key, T **v return HasReturnvaluesIF::RETURN_OK; } -template> -size_t FixedOrderedMultimap::findFirstIndex(key_t key, size_t startAt = 0) const { +template +size_t FixedOrderedMultimap::findFirstIndex(key_t key, size_t startAt) const { if (startAt >= _size) { return startAt + 1; } @@ -93,7 +93,7 @@ size_t FixedOrderedMultimap::findFirstIndex(key_t key, si return i; } -template> +template size_t FixedOrderedMultimap::findNicePlace(key_t key) const { size_t i = 0; for (i = 0; i < _size; ++i) { @@ -104,7 +104,7 @@ size_t FixedOrderedMultimap::findNicePlace(key_t key) con return i; } -template> +template void FixedOrderedMultimap::removeFromPosition(size_t position) { if (_size <= position) { return; From 6776ca86eb0df44f2580139c48f6f394b5e6a727 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Thu, 1 Oct 2020 17:44:23 +0200 Subject: [PATCH 16/17] Made tpp file less cluttered and added inline qualifier --- container/FixedOrderedMultimap.h | 8 +++++++- container/FixedOrderedMultimap.tpp | 27 +++++++++------------------ 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/container/FixedOrderedMultimap.h b/container/FixedOrderedMultimap.h index 82d388c9..96bc0073 100644 --- a/container/FixedOrderedMultimap.h +++ b/container/FixedOrderedMultimap.h @@ -159,7 +159,13 @@ public: * @param key Key to search for * @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); + if (result != HasReturnvaluesIF::RETURN_OK) { + return end(); + } + return Iterator(&theMap[findFirstIndex(key)]); + }; /*** * Finds first entry of the given key and returns a diff --git a/container/FixedOrderedMultimap.tpp b/container/FixedOrderedMultimap.tpp index 16a7124b..4aa85e97 100644 --- a/container/FixedOrderedMultimap.tpp +++ b/container/FixedOrderedMultimap.tpp @@ -3,7 +3,7 @@ template -ReturnValue_t FixedOrderedMultimap::insert(key_t key, T value, Iterator *storedValue) { +inline ReturnValue_t FixedOrderedMultimap::insert(key_t key, T value, Iterator *storedValue) { if (_size == theMap.maxSize()) { return MAP_FULL; } @@ -19,12 +19,12 @@ ReturnValue_t FixedOrderedMultimap::insert(key_t key, T v return HasReturnvaluesIF::RETURN_OK; } template -ReturnValue_t FixedOrderedMultimap::insert(std::pair pair) { +inline ReturnValue_t FixedOrderedMultimap::insert(std::pair pair) { return insert(pair.first, pair.second); } template -ReturnValue_t FixedOrderedMultimap::exists(key_t key) const { +inline ReturnValue_t FixedOrderedMultimap::exists(key_t key) const { ReturnValue_t result = KEY_DOES_NOT_EXIST; if (findFirstIndex(key) < _size) { result = HasReturnvaluesIF::RETURN_OK; @@ -33,7 +33,7 @@ ReturnValue_t FixedOrderedMultimap::exists(key_t key) con } template -ReturnValue_t FixedOrderedMultimap::erase(Iterator *iter) { +inline ReturnValue_t FixedOrderedMultimap::erase(Iterator *iter) { size_t i; if ((i = findFirstIndex((*iter).value->first)) >= _size) { return KEY_DOES_NOT_EXIST; @@ -48,7 +48,7 @@ ReturnValue_t FixedOrderedMultimap::erase(Iterator *iter) } template -ReturnValue_t FixedOrderedMultimap::erase(key_t key) { +inline ReturnValue_t FixedOrderedMultimap::erase(key_t key) { size_t i; if ((i = findFirstIndex(key)) >= _size) { return KEY_DOES_NOT_EXIST; @@ -61,16 +61,7 @@ ReturnValue_t FixedOrderedMultimap::erase(key_t key) { } template -FixedOrderedMultimap::Iterator FixedOrderedMultimap::find(key_t key) const { - ReturnValue_t result = exists(key); - if (result != HasReturnvaluesIF::RETURN_OK) { - return end(); - } - return Iterator(&theMap[findFirstIndex(key)]); -} - -template -ReturnValue_t FixedOrderedMultimap::find(key_t key, T **value) const { +inline ReturnValue_t FixedOrderedMultimap::find(key_t key, T **value) const { ReturnValue_t result = exists(key); if (result != HasReturnvaluesIF::RETURN_OK) { return result; @@ -80,7 +71,7 @@ ReturnValue_t FixedOrderedMultimap::find(key_t key, T **v } template -size_t FixedOrderedMultimap::findFirstIndex(key_t key, size_t startAt) const { +inline size_t FixedOrderedMultimap::findFirstIndex(key_t key, size_t startAt) const { if (startAt >= _size) { return startAt + 1; } @@ -94,7 +85,7 @@ size_t FixedOrderedMultimap::findFirstIndex(key_t key, si } template -size_t FixedOrderedMultimap::findNicePlace(key_t key) const { +inline size_t FixedOrderedMultimap::findNicePlace(key_t key) const { size_t i = 0; for (i = 0; i < _size; ++i) { if (myComp(key, theMap[i].first)) { @@ -105,7 +96,7 @@ size_t FixedOrderedMultimap::findNicePlace(key_t key) con } template -void FixedOrderedMultimap::removeFromPosition(size_t position) { +inline void FixedOrderedMultimap::removeFromPosition(size_t position) { if (_size <= position) { return; } From 8cea7b05db428b80bc90abd1ae5440bd9e9562a7 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 20 Oct 2020 14:42:58 +0200 Subject: [PATCH 17/17] include improvement --- osal/FreeRTOS/QueueFactory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osal/FreeRTOS/QueueFactory.cpp b/osal/FreeRTOS/QueueFactory.cpp index 5b3c73dc..ed29e10c 100644 --- a/osal/FreeRTOS/QueueFactory.cpp +++ b/osal/FreeRTOS/QueueFactory.cpp @@ -1,8 +1,8 @@ +#include "MessageQueue.h" + #include "../../ipc/MessageQueueSenderIF.h" #include "../../ipc/QueueFactory.h" -#include "../../osal/FreeRTOS/MessageQueue.h" - QueueFactory* QueueFactory::factoryInstance = nullptr;