ipc update #176

Merged
gaisser merged 16 commits from KSat/fsfw:mueller/ipc-updates into master 2020-09-29 14:20:20 +02:00
18 changed files with 574 additions and 314 deletions

View File

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

View File

@ -18,7 +18,7 @@ MapPacketExtraction::MapPacketExtraction(uint8_t setMapId,
object_id_t setPacketDestination) :
lastSegmentationFlag(NO_SEGMENTATION), mapId(setMapId), packetLength(0), bufferPosition(
packetBuffer), packetDestination(setPacketDestination), packetStore(
NULL), tcQueueId(MessageQueueSenderIF::NO_QUEUE) {
NULL), tcQueueId(MessageQueueIF::NO_QUEUE) {
memset(packetBuffer, 0, sizeof(packetBuffer));
}

View File

@ -5,7 +5,7 @@ HealthDevice::HealthDevice(object_id_t setObjectId,
MessageQueueId_t parentQueue) :
SystemObject(setObjectId), lastHealth(HEALTHY), parentQueue(
parentQueue), commandQueue(), healthHelper(this, setObjectId) {
commandQueue = QueueFactory::instance()->createMessageQueue(3, CommandMessage::COMMAND_MESSAGE_SIZE);
commandQueue = QueueFactory::instance()->createMessageQueue(3);
}
HealthDevice::~HealthDevice() {

View File

@ -1,124 +1,96 @@
/**
* @file CommandMessage.cpp
* @brief This file defines the CommandMessage class.
* @date 20.06.2013
* @author baetz
*/
#include "../devicehandlers/DeviceHandlerMessage.h"
#include "../health/HealthMessage.h"
#include "CommandMessage.h"
#include "../memory/MemoryMessage.h"
#include "../modes/ModeMessage.h"
#include "../monitoring/MonitoringMessage.h"
#include "../subsystem/modes/ModeSequenceMessage.h"
#include "../tmstorage/TmStoreMessage.h"
#include "../parameters/ParameterMessage.h"
namespace messagetypes {
void clearMissionMessage(CommandMessage* message);
}
#include "CommandMessageCleaner.h"
#include <cstring>
CommandMessage::CommandMessage() {
this->messageSize = COMMAND_MESSAGE_SIZE;
setCommand(CMD_NONE);
MessageQueueMessage::setMessageSize(DEFAULT_COMMAND_MESSAGE_SIZE);
setCommand(CMD_NONE);
}
CommandMessage::CommandMessage(Command_t command, uint32_t parameter1,
uint32_t parameter2) {
this->messageSize = COMMAND_MESSAGE_SIZE;
setCommand(command);
setParameter(parameter1);
setParameter2(parameter2);
uint32_t parameter2) {
MessageQueueMessage::setMessageSize(DEFAULT_COMMAND_MESSAGE_SIZE);
setCommand(command);
setParameter(parameter1);
setParameter2(parameter2);
}
Command_t CommandMessage::getCommand() const {
Command_t command;
memcpy(&command, getData(), sizeof(Command_t));
return command;
Command_t command;
std::memcpy(&command, MessageQueueMessage::getData(), sizeof(Command_t));
return command;
}
void CommandMessage::setCommand(Command_t command) {
memcpy(getData(), &command, sizeof(command));
std::memcpy(MessageQueueMessage::getData(), &command, sizeof(Command_t));
}
uint8_t CommandMessage::getMessageType() const {
// first byte of command ID.
return getCommand() >> 8 & 0xff;
}
uint32_t CommandMessage::getParameter() const {
uint32_t parameter1;
memcpy(&parameter1, getData() + sizeof(Command_t), sizeof(parameter1));
return parameter1;
uint32_t parameter1;
std::memcpy(&parameter1, this->getData(), sizeof(parameter1));
return parameter1;
}
void CommandMessage::setParameter(uint32_t parameter1) {
memcpy(getData() + sizeof(Command_t), &parameter1, sizeof(parameter1));
std::memcpy(this->getData(), &parameter1, sizeof(parameter1));
}
uint32_t CommandMessage::getParameter2() const {
uint32_t parameter2;
memcpy(&parameter2, getData() + sizeof(Command_t) + sizeof(uint32_t),
sizeof(parameter2));
return parameter2;
uint32_t parameter2;
std::memcpy(&parameter2, this->getData() + sizeof(uint32_t),
sizeof(parameter2));
return parameter2;
}
void CommandMessage::setParameter2(uint32_t parameter2) {
memcpy(getData() + sizeof(Command_t) + sizeof(uint32_t), &parameter2,
sizeof(parameter2));
std::memcpy(this->getData() + sizeof(uint32_t), &parameter2,
sizeof(parameter2));
}
void CommandMessage::clearCommandMessage() {
switch((getCommand()>>8) & 0xff){
case messagetypes::MODE_COMMAND:
ModeMessage::clear(this);
break;
case messagetypes::HEALTH_COMMAND:
HealthMessage::clear(this);
break;
case messagetypes::MODE_SEQUENCE:
ModeSequenceMessage::clear(this);
break;
case messagetypes::ACTION:
ActionMessage::clear(this);
break;
case messagetypes::DEVICE_HANDLER_COMMAND:
DeviceHandlerMessage::clear(this);
break;
case messagetypes::MEMORY:
MemoryMessage::clear(this);
break;
case messagetypes::MONITORING:
MonitoringMessage::clear(this);
break;
case messagetypes::TM_STORE:
TmStoreMessage::clear(this);
break;
case messagetypes::PARAMETER:
ParameterMessage::clear(this);
break;
default:
messagetypes::clearMissionMessage(this);
break;
}
uint32_t CommandMessage::getParameter3() const {
uint32_t parameter3;
std::memcpy(&parameter3, this->getData() + 2 * sizeof(uint32_t),
sizeof(parameter3));
return parameter3;
}
bool CommandMessage::isClearedCommandMessage() {
return getCommand() == CMD_NONE;
void CommandMessage::setParameter3(uint32_t parameter3) {
std::memcpy(this->getData() + 2 * sizeof(uint32_t), &parameter3,
sizeof(parameter3));
}
size_t CommandMessage::getMinimumMessageSize() const {
return COMMAND_MESSAGE_SIZE;
return MINIMUM_COMMAND_MESSAGE_SIZE;
}
void CommandMessage::clearCommandMessage() {
clear();
}
void CommandMessage::clear() {
CommandMessageCleaner::clearCommandMessage(this);
}
bool CommandMessage::isClearedCommandMessage() {
return getCommand() == CMD_NONE;
}
void CommandMessage::setToUnknownCommand() {
Command_t initialCommand = getCommand();
clearCommandMessage();
setReplyRejected(UNKNOWN_COMMAND, initialCommand);
Command_t initialCommand = getCommand();
this->clear();
setReplyRejected(UNKNOWN_COMMAND, initialCommand);
}
void CommandMessage::setReplyRejected(ReturnValue_t reason,
Command_t initialCommand) {
Command_t initialCommand) {
setCommand(REPLY_REJECTED);
setParameter(reason);
setParameter2(initialCommand);
setParameter(reason);
setParameter2(initialCommand);
}
ReturnValue_t CommandMessage::getReplyRejectedReason(
@ -129,3 +101,11 @@ ReturnValue_t CommandMessage::getReplyRejectedReason(
}
return reason;
}
uint8_t* CommandMessage::getData() {
return MessageQueueMessage::getData() + sizeof(Command_t);
}
const uint8_t* CommandMessage::getData() const {
return MessageQueueMessage::getData() + sizeof(Command_t);
}

View File

@ -1,114 +1,87 @@
/**
* @file CommandMessage.h
* @brief This file defines the CommandMessage class.
* @date 20.06.2013
* @author baetz
*/
#ifndef COMMANDMESSAGE_H_
#define COMMANDMESSAGE_H_
#include "FwMessageTypes.h"
#include <config/ipc/MissionMessageTypes.h>
#ifndef FSFW_IPC_COMMANDMESSAGE_H_
#define FSFW_IPC_COMMANDMESSAGE_H_
#include "CommandMessageIF.h"
#include "MessageQueueMessage.h"
#include "FwMessageTypes.h"
#define MAKE_COMMAND_ID( number ) ((MESSAGE_ID << 8) + (number))
typedef ReturnValue_t Command_t;
class CommandMessage : public MessageQueueMessage {
/**
* @brief Default command message used to pass command messages between tasks.
* Primary message type for IPC. Contains sender, 2-byte command ID
* field, and 3 4-byte parameter

3 4-byte Parameters?

3 4-byte Parameters?
* @details
* It operates on an external memory which is contained inside a
* class implementing MessageQueueMessageIF by taking its address.
* This allows for a more flexible designs of message implementations.
* The pointer can be passed to different message implementations without
* the need of unnecessary copying.
*
* The command message is based of the generic MessageQueueMessage which
* currently has an internal message size of 28 bytes.
* @author Bastian Baetz
*/
class CommandMessage: public MessageQueueMessage, public CommandMessageIF {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_MESSAGE;
static const ReturnValue_t UNKNOWN_COMMAND = MAKE_RETURN_CODE(0x01);
static const uint8_t MESSAGE_ID = messagetypes::COMMAND;
static const Command_t CMD_NONE = MAKE_COMMAND_ID( 0 );//!< Used internally, will be ignored
static const Command_t REPLY_COMMAND_OK = MAKE_COMMAND_ID( 3 );
static const Command_t REPLY_REJECTED = MAKE_COMMAND_ID( 0xD1 );//!< Reply indicating that the current command was rejected, par1 should contain the error code
/**
* Default size can accomodate 3 4-byte parameters.
*/
static constexpr size_t DEFAULT_COMMAND_MESSAGE_SIZE =
CommandMessageIF::MINIMUM_COMMAND_MESSAGE_SIZE +

3*sizeof(uint32_t)?

3*sizeof(uint32_t)?
3 * sizeof(uint32_t);
/**
* This is the size of a message as it is seen by the MessageQueue
*/
static const size_t COMMAND_MESSAGE_SIZE = HEADER_SIZE
+ sizeof(Command_t) + 2 * sizeof(uint32_t);
/**
* Default Constructor, does not initialize anything.
*
* This constructor should be used when receiving a Message, as the content is filled by the MessageQueue.
* @brief Default Constructor, does not initialize anything.
* @details
* This constructor should be used when receiving a Message, as the
* content is filled by the MessageQueue.
*/
CommandMessage();
/**
* This constructor creates a new message with all message content initialized
* This constructor creates a new message with all message content
* initialized
*
* @param command The DeviceHandlerCommand_t that will be sent
* @param parameter1 The first parameter
* @param parameter2 The second parameter
*/
CommandMessage(Command_t command,
uint32_t parameter1, uint32_t parameter2);
CommandMessage(Command_t command, uint32_t parameter1, uint32_t parameter2);
/**
* Default Destructor
* @brief Default Destructor
*/
virtual ~CommandMessage() {
}
virtual ~CommandMessage() {}
/**
* Read the DeviceHandlerCommand_t that is stored in the message, usually used after receiving
*
* @return the Command stored in the Message
*/
Command_t getCommand() const;
/**
* Read the DeviceHandlerCommand_t that is stored in the message,
* usually used after receiving.
*
* @return the Command stored in the Message
*/
virtual Command_t getCommand() const override;
/**
* Set the command type of the message. Default implementation also
* sets the message type, which will be the first byte of the command ID.
* @param the Command to be sent
*/
virtual void setCommand(Command_t command);
/**
* Set the DeviceHandlerCOmmand_t of the message
*
* @param the Command to be sent
*/
void setCommand(Command_t command);
virtual uint8_t* getData() override;
virtual const uint8_t* getData() const override;
/**
* Get the first parameter of the message
*
* @return the first Parameter of the message
*/
uint32_t getParameter() const;
/**
* Set the first parameter of the message
*
* @param the first parameter of the message
*/
void setParameter(uint32_t parameter1);
/**
* Get the second parameter of the message
*
* @return the second Parameter of the message
*/
uint32_t getParameter2() const;
/**
* Set the second parameter of the message
*
* @param the second parameter of the message
*/
void setParameter2(uint32_t parameter2);
/**
* Set the command to CMD_NONE and try to find
* the correct class to handle a more detailed
* clear.
* Also, calls a mission-specific clearMissionMessage
* function to separate between framework and mission
* messages. Not optimal, may be replaced by totally
* different auto-delete solution (e.g. smart pointers).
*
*/
void clearCommandMessage();
uint32_t getParameter3() const;
void setParameter3(uint32_t parameter3);
/**
* check if a message was cleared
@ -117,18 +90,41 @@ public:
*/
bool isClearedCommandMessage();
/**
* Sets the command to REPLY_REJECTED with parameter UNKNOWN_COMMAND.
* Is needed quite often, so we better code it once only.
*/
void setToUnknownCommand();
void setReplyRejected(ReturnValue_t reason, Command_t initialCommand = CMD_NONE);
ReturnValue_t getReplyRejectedReason(
Command_t *initialCommand = nullptr) const;
void setToUnknownCommand() override;
size_t getMinimumMessageSize() const;
/**
* A command message can be rejected and needs to offer a function
* to set a rejected reply
* @param reason
* @param initialCommand
*/
void setReplyRejected(ReturnValue_t reason,
Command_t initialCommand) override;
/**
* Corrensonding getter function.
* @param initialCommand
* @return
*/
ReturnValue_t getReplyRejectedReason(
Command_t* initialCommand = nullptr) const override;
virtual void clear() override;
void clearCommandMessage();
/**
* Extract message ID, which is the first byte of the command ID for the
* default implementation.
* @return
*/
virtual uint8_t getMessageType() const override;
/** MessageQueueMessageIF functions used for minimum size check. */
size_t getMinimumMessageSize() const override;
};
#endif /* COMMANDMESSAGE_H_ */
#endif /* FSFW_IPC_COMMANDMESSAGE_H_ */

View File

@ -0,0 +1,45 @@
#include "../ipc/CommandMessageCleaner.h"
#include "../devicehandlers/DeviceHandlerMessage.h"
#include "../health/HealthMessage.h"
#include "../memory/MemoryMessage.h"
#include "../modes/ModeMessage.h"
#include "../monitoring/MonitoringMessage.h"
#include "../subsystem/modes/ModeSequenceMessage.h"
#include "../tmstorage/TmStoreMessage.h"
#include "../parameters/ParameterMessage.h"
void CommandMessageCleaner::clearCommandMessage(CommandMessage* message) {
switch(message->getMessageType()){
case messagetypes::MODE_COMMAND:
ModeMessage::clear(message);
break;
case messagetypes::HEALTH_COMMAND:
HealthMessage::clear(message);
break;
case messagetypes::MODE_SEQUENCE:
ModeSequenceMessage::clear(message);
break;
case messagetypes::ACTION:
ActionMessage::clear(message);
break;
case messagetypes::DEVICE_HANDLER_COMMAND:
DeviceHandlerMessage::clear(message);
break;
case messagetypes::MEMORY:
MemoryMessage::clear(message);
break;
case messagetypes::MONITORING:
MonitoringMessage::clear(message);
break;
case messagetypes::TM_STORE:
TmStoreMessage::clear(message);
break;
case messagetypes::PARAMETER:
ParameterMessage::clear(message);
break;
default:
messagetypes::clearMissionMessage(message);
break;
}
}

View File

@ -0,0 +1,16 @@
#ifndef FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_
#define FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_
#include "../ipc/CommandMessage.h"
namespace messagetypes {
// Implemented in config.
void clearMissionMessage(CommandMessage* message);
}
class CommandMessageCleaner {
public:
static void clearCommandMessage(CommandMessage* message);
};
#endif /* FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_ */

73
ipc/CommandMessageIF.h Normal file
View File

@ -0,0 +1,73 @@
#ifndef FSFW_IPC_COMMANDMESSAGEIF_H_
#define FSFW_IPC_COMMANDMESSAGEIF_H_
#include "MessageQueueMessageIF.h"
#include "FwMessageTypes.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#define MAKE_COMMAND_ID( number ) ((MESSAGE_ID << 8) + (number))
typedef uint16_t Command_t;
class CommandMessageIF {
public:
/**
* Header consists of sender ID and command ID.
*/
static constexpr size_t HEADER_SIZE = MessageQueueMessageIF::HEADER_SIZE +
sizeof(Command_t);
/**
* This minimum size is derived from the interface requirement to be able
* to set a rejected reply, which contains a returnvalue and the initial
* command.
*/
static constexpr size_t MINIMUM_COMMAND_MESSAGE_SIZE =
CommandMessageIF::HEADER_SIZE + sizeof(ReturnValue_t) +
sizeof(Command_t);
static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_MESSAGE;
static const ReturnValue_t UNKNOWN_COMMAND = MAKE_RETURN_CODE(0x01);
static const uint8_t MESSAGE_ID = messagetypes::COMMAND;
//! Used internally, shall be ignored
static const Command_t CMD_NONE = MAKE_COMMAND_ID( 0 );
static const Command_t REPLY_COMMAND_OK = MAKE_COMMAND_ID( 1 );
//! Reply indicating that the current command was rejected,
//! par1 should contain the error code
static const Command_t REPLY_REJECTED = MAKE_COMMAND_ID( 2 );
virtual ~CommandMessageIF() {};
/**
* A command message shall have a uint16_t command ID field.
* @return
*/
virtual Command_t getCommand() const = 0;
/**
* A command message shall have a uint8_t message type ID field.
* @return
*/
virtual uint8_t getMessageType() const = 0;
/**
* A command message can be rejected and needs to offer a function
* to set a rejected reply
* @param reason
* @param initialCommand
*/
virtual void setReplyRejected(ReturnValue_t reason,
Command_t initialCommand) = 0;
/**
* Corrensonding getter function.
* @param initialCommand
* @return
*/
virtual ReturnValue_t getReplyRejectedReason(
Command_t* initialCommand = nullptr) const = 0;
virtual void setToUnknownCommand() = 0;
virtual void clear() = 0;
};
#endif /* FSFW_IPC_COMMANDMESSAGEIF_H_ */

View File

@ -1,15 +1,15 @@
#ifndef FRAMEWORK_IPC_MESSAGEQUEUEIF_H_
#define FRAMEWORK_IPC_MESSAGEQUEUEIF_H_
#ifndef FSFW_IPC_MESSAGEQUEUEIF_H_
#define FSFW_IPC_MESSAGEQUEUEIF_H_
// COULDDO: We could support blocking calls
#include "messageQueueDefinitions.h"
#include "MessageQueueMessage.h"
#include "MessageQueueSenderIF.h"
#include "../returnvalues/HasReturnvaluesIF.h"
class MessageQueueIF {
public:
static const MessageQueueId_t NO_QUEUE = MessageQueueSenderIF::NO_QUEUE; //!< Ugly hack.
static const MessageQueueId_t NO_QUEUE = 0;
static const uint8_t INTERFACE_ID = CLASS_ID::MESSAGE_QUEUE_IF;
/**

View File

@ -1,13 +1,27 @@
#include "MessageQueueMessage.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include <string.h>
#include "../globalfunctions/arrayprinter.h"
#include <cstring>
MessageQueueMessage::MessageQueueMessage() :
messageSize(this->HEADER_SIZE) {
messageSize(getMinimumMessageSize()) {
memset(this->internalBuffer, 0, sizeof(this->internalBuffer));
}
MessageQueueMessage::MessageQueueMessage(uint8_t* data, size_t size) :
messageSize(this->HEADER_SIZE + size) {
if (size <= this->MAX_DATA_SIZE) {
memcpy(this->getData(), data, size);
this->messageSize = this->HEADER_SIZE + size;
}
else {
sif::warning << "MessageQueueMessage: Passed size larger than maximum"
"allowed size! Setting content to 0" << std::endl;
memset(this->internalBuffer, 0, sizeof(this->internalBuffer));
this->messageSize = this->HEADER_SIZE;
}
}
MessageQueueMessage::~MessageQueueMessage() {
}
@ -37,29 +51,34 @@ void MessageQueueMessage::setSender(MessageQueueId_t setId) {
memcpy(this->internalBuffer, &setId, sizeof(MessageQueueId_t));
}
MessageQueueMessage::MessageQueueMessage(uint8_t* data, uint32_t size) :
messageSize(this->HEADER_SIZE + size) {
if (size <= this->MAX_DATA_SIZE) {
memcpy(this->getData(), data, size);
} else {
memset(this->internalBuffer, 0, sizeof(this->internalBuffer));
this->messageSize = this->HEADER_SIZE;
void MessageQueueMessage::print(bool printWholeMessage) {
sif::debug << "MessageQueueMessage content: " << std::endl;
if(printWholeMessage) {
arrayprinter::print(getData(), getMaximumMessageSize());
}
}
size_t MessageQueueMessage::getMinimumMessageSize() {
return this->HEADER_SIZE;
}
void MessageQueueMessage::print() {
sif::debug << "MessageQueueMessage has size: " << this->messageSize << std::hex
<< std::endl;
for (uint8_t count = 0; count < this->messageSize; count++) {
sif::debug << (uint32_t) this->internalBuffer[count] << ":";
else {
arrayprinter::print(getData(), getMessageSize());
}
sif::debug << std::dec << std::endl;
}
void MessageQueueMessage::clear() {
memset(this->getBuffer(), 0, this->MAX_MESSAGE_SIZE);
}
size_t MessageQueueMessage::getMessageSize() const {
return this->messageSize;
}
void MessageQueueMessage::setMessageSize(size_t messageSize) {
this->messageSize = messageSize;
}
size_t MessageQueueMessage::getMinimumMessageSize() const {
return this->MIN_MESSAGE_SIZE;
}
size_t MessageQueueMessage::getMaximumMessageSize() const {
return this->MAX_MESSAGE_SIZE;
}

View File

@ -1,118 +1,149 @@
#ifndef MESSAGEQUEUEMESSAGE_H_
#define MESSAGEQUEUEMESSAGE_H_
#ifndef FSFW_IPC_MESSAGEQUEUEMESSAGE_H_
#define FSFW_IPC_MESSAGEQUEUEMESSAGE_H_
#include "MessageQueueSenderIF.h"
#include <stddef.h>
#include "../ipc/MessageQueueMessageIF.h"
#include <cstddef>
/**
* \brief This class is the representation and data organizer for interprocess messages.
* @brief This class is the representation and data organizer
* for interprocess messages.
* @details
* To facilitate and standardize interprocess communication, this class was
* created to handle a lightweight "interprocess message protocol".
*
* \details To facilitate and standardize interprocess communication, this class was created
* to handle a lightweight "interprocess message protocol". It adds a header with the
* sender's queue id to every sent message and defines the maximum total message size.
* Specialized messages, such as device commanding messages, can be created by inheriting
* from this class and filling the buffer provided by getData with additional content.
* If larger amounts of data must be sent between processes, the data shall be stored in
* the IPC Store object and only the storage id is passed in a queue message.
* The class is used both to generate and send messages and to receive messages from
* other tasks.
* \ingroup message_queue
* It adds a header with the sender's queue id to every sent message and
* defines the maximum total message size. Specialized messages, such as
* device commanding messages, can be created by inheriting from this class
* and filling the buffer provided by getData with additional content.
*
* If larger amounts of data must be sent between processes, the data shall
* be stored in the IPC Store object and only the storage id is passed in a
* queue message.The class is used both to generate and send messages and to
* receive messages from other tasks.
* @ingroup message_queue
*/
class MessageQueueMessage {
class MessageQueueMessage: public MessageQueueMessageIF {
public:
/**
* \brief This constant defines the maximum size of the data content, excluding the header.
* \details It may be changed if necessary, but in general should be kept as small as possible.
* @brief The class is initialized empty with this constructor.
* @details
* The messageSize attribute is set to the header's size and the whole
* content is set to zero.
*/
MessageQueueMessage();
/**
* @brief With this constructor the class is initialized with
* the given content.
* @details
* If the passed message size fits into the buffer, the passed data is
* copied to the internal buffer and the messageSize information is set.
* Otherwise, messageSize is set to the header's size and the whole
* content is set to zero.
* @param data The data to be put in the message.
* @param size Size of the data to be copied. Must be smaller than
* MAX_MESSAGE_SIZE and larger than MIN_MESSAGE_SIZE.
*/
MessageQueueMessage(uint8_t* data, size_t size);
/**
* @brief As no memory is allocated in this class,
* the destructor is empty.
*/
virtual ~MessageQueueMessage();
/**
* @brief The size information of each message is stored in
* this attribute.
* @details
* It is public to simplify usage and to allow for passing the size
* address as a pointer. Care must be taken when inheriting from this class,
* as every child class is responsible for managing the size information by
* itself. When using the class to receive a message, the size information
* is updated automatically.
*
* Please note that the minimum size is limited by the size of the header
* while the maximum size is limited by the maximum allowed message size.
*/
size_t messageSize;
/**
* @brief This constant defines the maximum size of the data content,
* excluding the header.
* @details
* It may be changed if necessary, but in general should be kept
* as small as possible.
*/
static const size_t MAX_DATA_SIZE = 24;
/**
* \brief This constants defines the size of the header, which is added to every message.
* @brief This constant defines the maximum total size in bytes
* of a sent message.
* @details
* It is the sum of the maximum data and the header size. Be aware that
* this constant is used to define the buffer sizes for every message
* queue in the system. So, a change here may have significant impact on
* the required resources.
*/
static const size_t HEADER_SIZE = sizeof(MessageQueueId_t);
static constexpr size_t MAX_MESSAGE_SIZE = MAX_DATA_SIZE + HEADER_SIZE;
/**
* \brief This constant defines the maximum total size in bytes of a sent message.
* \details It is the sum of the maximum data and the header size. Be aware that this constant
* is used to define the buffer sizes for every message queue in the system. So, a change
* here may have significant impact on the required resources.
* @brief Defines the minimum size of a message where only the
* header is included
*/
static const size_t MAX_MESSAGE_SIZE = MAX_DATA_SIZE + HEADER_SIZE;
static constexpr size_t MIN_MESSAGE_SIZE = HEADER_SIZE;
private:
/**
* \brief This is the internal buffer that contains the actual message data.
* @brief This is the internal buffer that contains the
* actual message data.
*/
uint8_t internalBuffer[MAX_MESSAGE_SIZE];
public:
/**
* \brief The size information of each message is stored in this attribute.
* \details It is public to simplify usage and to allow for passing the variable's address as a
* pointer. Care must be taken when inheriting from this class, as every child class is
* responsible for managing the size information by itself. When using the class to
* receive a message, the size information is updated automatically.
* @brief This method is used to get the complete data of the message.
*/
size_t messageSize;
const uint8_t* getBuffer() const override;
/**
* \brief The class is initialized empty with this constructor.
* \details The messageSize attribute is set to the header's size and the whole content is set to
* zero.
* @brief This method is used to get the complete data of the message.
*/
MessageQueueMessage();
uint8_t* getBuffer() override;
/**
* \brief With this constructor the class is initialized with the given content.
* \details If the passed message size fits into the buffer, the passed data is copied to the
* internal buffer and the messageSize information is set. Otherwise, messageSize
* is set to the header's size and the whole content is set to zero.
* \param data The data to be put in the message.
* \param size Size of the data to be copied. Must be smaller than MAX_MESSAGE_SIZE.
* @brief This method is used to fetch the data content of the message.
* @details
* It shall be used by child classes to add data at the right position.
*/
MessageQueueMessage(uint8_t* data, uint32_t size);
const uint8_t* getData() const override;
/**
* \brief As no memory is allocated in this class, the destructor is empty.
* @brief This method is used to fetch the data content of the message.
* @details
* It shall be used by child classes to add data at the right position.
*/
virtual ~MessageQueueMessage();
uint8_t* getData() override;
/**
* \brief This method is used to get the complete data of the message.
* @brief This method is used to extract the sender's message
* queue id information from a received message.
*/
const uint8_t* getBuffer() const;
MessageQueueId_t getSender() const override;
/**
* \brief This method is used to get the complete data of the message.
* @brief With this method, the whole content
* and the message size is set to zero.
*/
uint8_t* getBuffer();
void clear() override;
/**
* \brief This method is used to fetch the data content of the message.
* \details It shall be used by child classes to add data at the right position.
* @brief This method is used to set the sender's message queue id
* information prior to ing the message.
* @param setId
* The message queue id that identifies the sending message queue.
*/
const uint8_t* getData() const;
void setSender(MessageQueueId_t setId) override;
virtual size_t getMessageSize() const override;
virtual void setMessageSize(size_t messageSize) override;
virtual size_t getMinimumMessageSize() const override;
virtual size_t getMaximumMessageSize() const override;
/**
* \brief This method is used to fetch the data content of the message.
* \details It shall be used by child classes to add data at the right position.
* @brief This is a debug method that prints the content.
*/
uint8_t* getData();
/**
* \brief This method is used to extract the sender's message queue id information from a
* received message.
*/
MessageQueueId_t getSender() const;
/**
* \brief With this method, the whole content and the message size is set to zero.
*/
void clear();
/**
* \brief This is a debug method that prints the content (till messageSize) to the debug output.
*/
void print();
/**
* \brief This method is used to set the sender's message queue id information prior to
* sending the message.
* \param setId The message queue id that identifies the sending message queue.
*/
void setSender(MessageQueueId_t setId);
/**
* \brief This helper function is used by the MessageQueue class to check the size of an
* incoming message.
* \details The method must be overwritten by child classes if size checks shall be more strict.
* @return The default implementation returns HEADER_SIZE.
*/
virtual size_t getMinimumMessageSize();
void print(bool printWholeMessage);
};
#endif /* MESSAGEQUEUEMESSAGE_H_ */
#endif /* FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ */

View File

@ -0,0 +1,80 @@
#ifndef FRAMEWORK_IPC_MESSAGEQUEUEMESSAGEIF_H_
#define FRAMEWORK_IPC_MESSAGEQUEUEMESSAGEIF_H_
#include <fsfw/ipc/messageQueueDefinitions.h>
#include <cstddef>
#include <cstdint>
class MessageQueueMessageIF {
public:
/**
* @brief This constants defines the size of the header,
* which is added to every message.
*/
static const size_t HEADER_SIZE = sizeof(MessageQueueId_t);
virtual ~MessageQueueMessageIF() {};
gaisser marked this conversation as resolved
Review

This is part of MessageQueueIF and should not be here

This is part of MessageQueueIF and should not be here
/**
* @brief With this method, the whole content and the message
* size is set to zero.
gaisser marked this conversation as resolved
Review

This is part of MessageQueueIF and should not be here

This is part of MessageQueueIF and should not be here
* @details
* Implementations should also take care to clear data which is stored
* indirectly (e.g. storage data).
*/
virtual void clear() = 0;
/**
* @brief Get read-only pointer to the complete data of the message.
* @return
*/
virtual const uint8_t* getBuffer() const = 0;
/**
* @brief This method is used to get the complete data of the message.
*/
virtual uint8_t* getBuffer() = 0;
/**
* @brief This method is used to set the sender's message queue id
* information prior to sending the message.
* @param setId
* The message queue id that identifies the sending message queue.
*/
virtual void setSender(MessageQueueId_t setId) = 0;
/**
* @brief This method is used to extract the sender's message queue id
* information from a received message.
*/
virtual MessageQueueId_t getSender() const = 0;
/**
* @brief This method is used to fetch the data content of the message.
* @details
* It shall be used by child classes to add data at the right position.
*/
virtual const uint8_t* getData() const = 0;
/**
* @brief This method is used to fetch the data content of the message.
* @details
* It shall be used by child classes to add data at the right position.
*/
virtual uint8_t* getData() = 0;
/**
* Get constant message size of current message implementation.
* @return
*/
virtual size_t getMessageSize() const = 0;
virtual void setMessageSize(size_t messageSize) = 0;
virtual size_t getMinimumMessageSize() const = 0;
virtual size_t getMaximumMessageSize() const = 0;
};
#endif /* FRAMEWORK_IPC_MESSAGEQUEUEMESSAGEIF_H_ */

View File

@ -1,37 +1,26 @@
#ifndef FRAMEWORK_IPC_MESSAGEQUEUESENDERIF_H_
#define FRAMEWORK_IPC_MESSAGEQUEUESENDERIF_H_
#ifndef FSFW_IPC_MESSAGEQUEUESENDERIF_H_
#define FSFW_IPC_MESSAGEQUEUESENDERIF_H_
#include "../ipc/MessageQueueIF.h"
#include "../ipc/MessageQueueMessageIF.h"
#include "../objectmanager/ObjectManagerIF.h"
class MessageQueueMessage;
//TODO: Actually, the definition of this ID to be a uint32_t is not ideal and breaks layering.
//However, it is difficult to keep layering, as the ID is stored in many places and sent around in
//MessageQueueMessage.
//Ideally, one would use the (current) object_id_t only, however, doing a lookup of queueIDs for every
//call does not sound ideal.
//In a first step, I'll circumvent the issue by not touching it, maybe in a second step.
//This also influences Interface design (getCommandQueue) and some other issues..
typedef uint32_t MessageQueueId_t;
class MessageQueueSenderIF {
public:
static const MessageQueueId_t NO_QUEUE = 0;
virtual ~MessageQueueSenderIF() {}
/**
* Allows sending messages without actually "owing" a message queue.
* Allows sending messages without actually "owning" a message queue.
* Not sure whether this is actually a good idea.
* Must be implemented by a subclass.
*/
static ReturnValue_t sendMessage(MessageQueueId_t sendTo,
MessageQueueMessage* message, MessageQueueId_t sentFrom =
MessageQueueSenderIF::NO_QUEUE, bool ignoreFault=false);
MessageQueueMessage* message,
MessageQueueId_t sentFrom = MessageQueueIF::NO_QUEUE,
bool ignoreFault = false);
private:
MessageQueueSenderIF() {}
};
#endif /* FRAMEWORK_IPC_MESSAGEQUEUESENDERIF_H_ */
#endif /* FSFW_IPC_MESSAGEQUEUESENDERIF_H_ */

View File

@ -0,0 +1,19 @@
#ifndef FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_
#define FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_
#include <cstdint>
/*
* TODO: Actually, the definition of this ID to be a uint32_t is not ideal and
* breaks layering. However, it is difficult to keep layering, as the ID is
* stored in many places and sent around in MessageQueueMessage.
* Ideally, one would use the (current) object_id_t only, however, doing a
* lookup of queueIDs for every call does not sound ideal.
* In a first step, I'll circumvent the issue by not touching it,
* maybe in a second step. This also influences Interface design
* (getCommandQueue) and some other issues..
*/
using MessageQueueId_t = uint32_t;
#endif /* FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ */

View File

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

View File

@ -1,5 +1,6 @@
#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
@ -101,7 +102,8 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
reinterpret_cast<const void*>(message->getBuffer()), 0);
if (result != pdPASS) {
if (!ignoreFault) {
InternalErrorReporterIF* internalErrorReporter = objectManager->get<InternalErrorReporterIF>(
InternalErrorReporterIF* internalErrorReporter =
objectManager->get<InternalErrorReporterIF>(
objects::INTERNAL_ERROR_REPORTER);
if (internalErrorReporter != NULL) {
internalErrorReporter->queueMessageNotSent();

View File

@ -1,18 +1,21 @@
#include "../../ipc/MessageQueueSenderIF.h"
#include "../../ipc/QueueFactory.h"
#include "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);
MessageQueueMessage* 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) {

View File

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