Merge branch 'development' into mueller/clock-addition

This commit is contained in:
Robin Müller 2022-04-25 14:54:22 +02:00
commit ff98c42514
27 changed files with 353 additions and 724 deletions

View File

@ -24,6 +24,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- `oneShotAction` flag in the `TestTask` class is not static anymore
- HAL Linux Uart: Baudrate and bits per word are enums now, avoiding misconfigurations
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/585
- IPC Message Queue Handling: Allow passing an optional `MqArgs` argument into the MessageQueue
creation call. It allows passing context information and an arbitrary user argument into
the message queue. Also streamlined and simplified `MessageQueue` implementation for all OSALs
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/583
## Removed
@ -38,6 +42,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
inside `fsfw/version.h`
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
## Fixed
- Small bugfix in STM32 HAL for SPI
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/599
# [v4.0.0]
## Additions

View File

@ -48,9 +48,10 @@ add_library(${LIB_FSFW_NAME})
if(FSFW_BUILD_UNITTESTS)
message(STATUS "Building the FSFW unittests in addition to the static library")
# Check whether the user has already installed Catch2 first
find_package(Catch2 3)
find_package(Catch2 3 QUIET)
# Not installed, so use FetchContent to download and provide Catch2
if(NOT Catch2_FOUND)
message(STATUS "Catch2 installation not found. Downloading Catch2 library with FetchContent")
include(FetchContent)
FetchContent_Declare(

View File

@ -21,7 +21,7 @@ using mspCb = void (*)(void);
namespace spi {
struct MspCfgBase {
MspCfgBase();
MspCfgBase() {}
MspCfgBase(stm32h7::GpioCfg sck, stm32h7::GpioCfg mosi, stm32h7::GpioCfg miso,
mspCb cleanupCb = nullptr, mspCb setupCb = nullptr)
: sck(sck), mosi(mosi), miso(miso), cleanupCb(cleanupCb), setupCb(setupCb) {}

View File

@ -787,6 +787,10 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, bool i
// Serialize set packet into store.
size_t size = 0;
result = setPacket.serialize(&storePtr, &size, expectedSize, SerializeIF::Endianness::BIG);
if(result != HasReturnvaluesIF::RETURN_OK) {
ipcStore->deleteData(storeId);
return result;
}
if (expectedSize != size) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "generateSetStructurePacket",
HasReturnvaluesIF::RETURN_FAILED,
@ -801,7 +805,10 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, bool i
HousekeepingMessage::setHkStuctureReportReply(&reply, sid, storeId);
}
hkQueue->reply(&reply);
result = hkQueue->reply(&reply);
if(result != HasReturnvaluesIF::RETURN_OK) {
ipcStore->deleteData(storeId);
}
return result;
}

View File

@ -410,7 +410,7 @@ ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(
DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, LocalPoolDataSetBase* replyDataSet,
size_t replyLen, bool periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId) {
// No need to check, as we may try to insert multiple times.
insertInCommandMap(deviceCommand);
insertInCommandMap(deviceCommand, hasDifferentReplyId, replyId);
if (hasDifferentReplyId) {
return insertInReplyMap(replyId, maxDelayCycles, replyDataSet, replyLen, periodic);
} else {
@ -437,11 +437,15 @@ ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
}
}
ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceCommand) {
ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceCommand,
bool useAlternativeReply,
DeviceCommandId_t alternativeReplyId) {
DeviceCommandInfo info;
info.expectedReplies = 0;
info.isExecuting = false;
info.sendReplyTo = NO_COMMANDER;
info.useAlternativeReplyId = alternativeReplyId;
info.alternativeReplyId = alternativeReplyId;
auto resultPair = deviceCommandMap.emplace(deviceCommand, info);
if (resultPair.second) {
return RETURN_OK;
@ -451,12 +455,21 @@ ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceComm
}
size_t DeviceHandlerBase::getNextReplyLength(DeviceCommandId_t commandId) {
DeviceReplyIter iter = deviceReplyMap.find(commandId);
if (iter != deviceReplyMap.end()) {
return iter->second.replyLen;
} else {
return 0;
DeviceCommandId_t replyId = NO_COMMAND_ID;
DeviceCommandMap::iterator command = cookieInfo.pendingCommand;
if (command->second.useAlternativeReplyId) {
replyId = command->second.alternativeReplyId;
}
else {
replyId = commandId;
}
DeviceReplyIter iter = deviceReplyMap.find(replyId);
if (iter != deviceReplyMap.end()) {
if (iter->second.delayCycles != 0) {
return iter->second.replyLen;
}
}
return 0;
}
ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceReply,
@ -651,7 +664,9 @@ void DeviceHandlerBase::doGetWrite() {
// We need to distinguish here, because a raw command never expects a reply.
//(Could be done in eRIRM, but then child implementations need to be careful.
result = enableReplyInReplyMap(cookieInfo.pendingCommand);
DeviceCommandMap::iterator command = cookieInfo.pendingCommand;
result = enableReplyInReplyMap(command, 1, command->second.useAlternativeReplyId,
command->second.alternativeReplyId);
} else {
// always generate a failure event, so that FDIR knows what's up
triggerEvent(DEVICE_SENDING_COMMAND_FAILED, result, cookieInfo.pendingCommand->first);

View File

@ -478,7 +478,9 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* @return - @c RETURN_OK when the command was successfully inserted,
* - @c RETURN_FAILED else.
*/
ReturnValue_t insertInCommandMap(DeviceCommandId_t deviceCommand);
ReturnValue_t insertInCommandMap(DeviceCommandId_t deviceCommand,
bool useAlternativeReply = false,
DeviceCommandId_t alternativeReplyId = 0);
/**
* Enables a periodic reply for a given command. It sets to delay cycles to the specified
@ -751,6 +753,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
//! if this is != NO_COMMANDER, DHB was commanded externally and shall
//! report everything to commander.
MessageQueueId_t sendReplyTo;
bool useAlternativeReplyId;
DeviceCommandId_t alternativeReplyId;
};
using DeviceCommandMap = std::map<DeviceCommandId_t, DeviceCommandInfo>;
/**

View File

@ -1,6 +1,6 @@
target_sources(${LIB_FSFW_NAME}
PRIVATE
CommandMessage.cpp
CommandMessageCleaner.cpp
MessageQueueMessage.cpp
target_sources(${LIB_FSFW_NAME} PRIVATE
CommandMessage.cpp
CommandMessageCleaner.cpp
MessageQueueMessage.cpp
MessageQueueBase.cpp
)

View File

@ -0,0 +1,64 @@
#include "MessageQueueBase.h"
MessageQueueBase::MessageQueueBase(MessageQueueId_t id, MessageQueueId_t defaultDest,
MqArgs* args): id(id) {
this->defaultDest = defaultDest;
if(args != nullptr) {
this->args = *args;
}
}
MessageQueueBase::~MessageQueueBase() {}
ReturnValue_t MessageQueueBase::sendToDefault(MessageQueueMessageIF* message) {
return sendToDefaultFrom(message, this->getId(), false);
}
ReturnValue_t MessageQueueBase::reply(MessageQueueMessageIF* message) {
if (this->last != MessageQueueIF::NO_QUEUE) {
return sendMessageFrom(this->last, message, this->getId());
} else {
return NO_REPLY_PARTNER;
}
}
ReturnValue_t MessageQueueBase::receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) {
ReturnValue_t status = this->receiveMessage(message);
*receivedFrom = this->last;
return status;
}
MessageQueueId_t MessageQueueBase::getLastPartner() const {
return last;
}
MessageQueueId_t MessageQueueBase::getId() const {
return id;
}
MqArgs& MessageQueueBase::getMqArgs() {
return args;
}
void MessageQueueBase::setDefaultDestination(MessageQueueId_t defaultDestination) {
this->defaultDest = defaultDestination;
}
MessageQueueId_t MessageQueueBase::getDefaultDestination() const {
return defaultDest;
}
bool MessageQueueBase::isDefaultDestinationSet() const {
return (defaultDest != NO_QUEUE);
}
ReturnValue_t MessageQueueBase::sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault) {
return sendMessageFrom(sendTo, message, this->getId(), false);
}
ReturnValue_t MessageQueueBase::sendToDefaultFrom(MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault) {
return sendMessageFrom(defaultDest, message, sentFrom, ignoreFault);
}

View File

@ -0,0 +1,41 @@
#ifndef FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_
#define FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_
#include <fsfw/ipc/definitions.h>
#include <fsfw/ipc/MessageQueueIF.h>
class MessageQueueBase: public MessageQueueIF {
public:
MessageQueueBase(MessageQueueId_t id, MessageQueueId_t defaultDest, MqArgs* mqArgs);
virtual ~MessageQueueBase();
// Default implementations for MessageQueueIF where possible
virtual MessageQueueId_t getLastPartner() const override;
virtual MessageQueueId_t getId() const override;
virtual MqArgs& getMqArgs() override;
virtual void setDefaultDestination(MessageQueueId_t defaultDestination) override;
virtual MessageQueueId_t getDefaultDestination() const override;
virtual bool isDefaultDestinationSet() const override;
virtual ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault) override;
virtual ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override;
virtual ReturnValue_t reply(MessageQueueMessageIF* message) override;
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) override;
virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault = false) override;
// OSAL specific, forward the abstract function
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) = 0;
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault = false) = 0;
protected:
MessageQueueId_t id = MessageQueueIF::NO_QUEUE;
MessageQueueId_t last = MessageQueueIF::NO_QUEUE;
MessageQueueId_t defaultDest = MessageQueueIF::NO_QUEUE;
MqArgs args = {};
};
#endif /* FSFW_SRC_FSFW_IPC_MESSAGEQUEUEBASE_H_ */

View File

@ -1,6 +1,7 @@
#ifndef FSFW_IPC_MESSAGEQUEUEIF_H_
#define FSFW_IPC_MESSAGEQUEUEIF_H_
#include <fsfw/ipc/definitions.h>
#include <cstdint>
#include "../returnvalues/HasReturnvaluesIF.h"
@ -44,8 +45,7 @@ class MessageQueueIF {
virtual ReturnValue_t reply(MessageQueueMessageIF* message) = 0;
/**
* @brief This function reads available messages from the message queue
* and returns the sender.
* @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.
@ -78,19 +78,16 @@ class MessageQueueIF {
*/
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.
* @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
@ -129,8 +126,7 @@ class MessageQueueIF {
bool ignoreFault = false) = 0;
/**
* @brief The sendToDefaultFrom method sends a queue message
* to the default destination.
* @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
@ -164,6 +160,8 @@ class MessageQueueIF {
virtual MessageQueueId_t getDefaultDestination() const = 0;
virtual bool isDefaultDestinationSet() const = 0;
virtual MqArgs& getMqArgs() = 0;
};
#endif /* FSFW_IPC_MESSAGEQUEUEIF_H_ */

View File

@ -5,6 +5,7 @@
#include "MessageQueueIF.h"
#include "MessageQueueMessage.h"
#include "definitions.h"
/**
* Creates message queues.
@ -22,7 +23,8 @@ class QueueFactory {
static QueueFactory* instance();
MessageQueueIF* createMessageQueue(uint32_t messageDepth = 3,
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE);
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE,
MqArgs* args = nullptr);
void deleteMessageQueue(MessageQueueIF* queue);

View File

@ -0,0 +1,14 @@
#ifndef FSFW_SRC_FSFW_IPC_DEFINITIONS_H_
#define FSFW_SRC_FSFW_IPC_DEFINITIONS_H_
#include <fsfw/objectmanager/SystemObjectIF.h>
#include <fsfw/objectmanager/frameworkObjects.h>
struct MqArgs {
MqArgs(){};
MqArgs(object_id_t objectId, void* args = nullptr) : objectId(objectId), args(args) {}
object_id_t objectId = objects::NO_OBJECT;
void* args = nullptr;
};
#endif /* FSFW_SRC_FSFW_IPC_DEFINITIONS_H_ */

View File

@ -4,8 +4,9 @@
#include "fsfw/osal/freertos/QueueMapManager.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize)
: maxMessageSize(maxMessageSize) {
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize, MqArgs* args)
: MessageQueueBase(MessageQueueIF::NO_QUEUE, MessageQueueIF::NO_QUEUE, args),
maxMessageSize(maxMessageSize) {
handle = xQueueCreate(messageDepth, maxMessageSize);
if (handle == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
@ -15,10 +16,10 @@ MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize)
#else
sif::printError("MessageQueue::MessageQueue: Creation failed\n");
sif::printError("Specified Message Depth: %d\n", messageDepth);
sif::printError("Specified MAximum Message Size: %d\n", maxMessageSize);
sif::printError("Specified Maximum Message Size: %d\n", maxMessageSize);
#endif
}
QueueMapManager::instance()->addMessageQueue(handle, &queueId);
QueueMapManager::instance()->addMessageQueue(handle, &id);
}
MessageQueue::~MessageQueue() {
@ -29,28 +30,6 @@ MessageQueue::~MessageQueue() {
void MessageQueue::switchSystemContext(CallContext callContext) { this->callContext = callContext; }
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault) {
return sendMessageFrom(sendTo, message, this->getId(), ignoreFault);
}
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) {
return sendToDefaultFrom(message, this->getId());
}
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::sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault) {
return sendMessageFromMessageQueue(sendTo, message, sentFrom, ignoreFault, callContext);
@ -72,27 +51,16 @@ ReturnValue_t MessageQueue::handleSendResult(BaseType_t result, bool ignoreFault
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) {
ReturnValue_t status = this->receiveMessage(message);
if (status == HasReturnvaluesIF::RETURN_OK) {
*receivedFrom = this->lastPartner;
}
return status;
}
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
BaseType_t result = xQueueReceive(handle, reinterpret_cast<void*>(message->getBuffer()), 0);
if (result == pdPASS) {
this->lastPartner = message->getSender();
this->last = message->getSender();
return HasReturnvaluesIF::RETURN_OK;
} else {
return MessageQueueIF::EMPTY;
}
}
MessageQueueId_t MessageQueue::getLastPartner() const { return lastPartner; }
ReturnValue_t MessageQueue::flush(uint32_t* count) {
// TODO FreeRTOS does not support flushing partially
// Is always successful
@ -100,17 +68,6 @@ ReturnValue_t MessageQueue::flush(uint32_t* count) {
return HasReturnvaluesIF::RETURN_OK;
}
MessageQueueId_t MessageQueue::getId() const { return queueId; }
void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
defaultDestinationSet = true;
this->defaultDestination = defaultDestination;
}
MessageQueueId_t MessageQueue::getDefaultDestination() const { return defaultDestination; }
bool MessageQueue::isDefaultDestinationSet() const { return defaultDestinationSet; }
// static core function to send messages.
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
MessageQueueMessageIF* message,

View File

@ -1,12 +1,14 @@
#ifndef FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_
#define FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_
#include <fsfw/ipc/MessageQueueBase.h>
#include "FreeRTOS.h"
#include "TaskManagement.h"
#include "fsfw/internalerror/InternalErrorReporterIF.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/ipc/MessageQueueMessage.h"
#include "fsfw/ipc/MessageQueueMessageIF.h"
#include "fsfw/ipc/definitions.h"
#include "queue.h"
/**
@ -32,7 +34,7 @@
* @ingroup osal
* @ingroup message_queue
*/
class MessageQueue : public MessageQueueIF {
class MessageQueue : public MessageQueueBase {
friend class MessageQueueSenderIF;
public:
@ -53,7 +55,8 @@ class MessageQueue : public MessageQueueIF {
* This should be left default.
*/
MessageQueue(size_t messageDepth = 3,
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE);
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE,
MqArgs* args = nullptr);
/** Copying message queues forbidden */
MessageQueue(const MessageQueue&) = delete;
@ -73,40 +76,15 @@ class MessageQueue : public MessageQueueIF {
*/
void switchSystemContext(CallContext callContext);
/** MessageQueueIF implementation */
ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault = false) override;
QueueHandle_t getNativeQueueHandle();
ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override;
ReturnValue_t reply(MessageQueueMessageIF* message) override;
// Implement non-generic MessageQueueIF functions not handled by MessageQueueBase
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;
QueueHandle_t getNativeQueueHandle();
protected:
/**
* @brief Implementation to be called from any send Call within
@ -136,12 +114,8 @@ class MessageQueue : public MessageQueueIF {
static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault);
private:
bool defaultDestinationSet = false;
QueueHandle_t handle;
MessageQueueId_t queueId = MessageQueueIF::NO_QUEUE;
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;

View File

@ -22,8 +22,9 @@ QueueFactory::QueueFactory() {}
QueueFactory::~QueueFactory() {}
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize) {
return new MessageQueue(messageDepth, maxMessageSize);
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize,
MqArgs* args) {
return new MessageQueue(messageDepth, maxMessageSize, args);
}
void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { delete queue; }

View File

@ -8,10 +8,12 @@
#include "fsfw/osal/host/QueueMapManager.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize)
: messageSize(maxMessageSize), messageDepth(messageDepth) {
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize, MqArgs* args)
: MessageQueueBase(MessageQueueIF::NO_QUEUE, MessageQueueIF::NO_QUEUE, args),
messageSize(maxMessageSize),
messageDepth(messageDepth) {
queueLock = MutexFactory::instance()->createMutex();
auto result = QueueMapManager::instance()->addMessageQueue(this, &mqId);
auto result = QueueMapManager::instance()->addMessageQueue(this, &id);
if (result != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MessageQueue::MessageQueue: Could not be created" << std::endl;
@ -23,42 +25,11 @@ MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize)
MessageQueue::~MessageQueue() { MutexFactory::instance()->deleteMutex(queueLock); }
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault) {
return sendMessageFrom(sendTo, message, this->getId(), ignoreFault);
}
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) {
return sendToDefaultFrom(message, this->getId());
}
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 MessageQueueIF::NO_REPLY_PARTNER;
}
}
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault) {
return sendMessageFromMessageQueue(sendTo, message, sentFrom, ignoreFault);
}
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) {
ReturnValue_t status = this->receiveMessage(message);
if (status == HasReturnvaluesIF::RETURN_OK) {
*receivedFrom = this->lastPartner;
}
return status;
}
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
if (messageQueue.empty()) {
return MessageQueueIF::EMPTY;
@ -68,12 +39,10 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
message->getBuffer());
messageQueue.pop();
// The last partner is the first uint32_t field in the message
this->lastPartner = message->getSender();
this->last = message->getSender();
return HasReturnvaluesIF::RETURN_OK;
}
MessageQueueId_t MessageQueue::getLastPartner() const { return lastPartner; }
ReturnValue_t MessageQueue::flush(uint32_t* count) {
*count = messageQueue.size();
// Clears the queue.
@ -81,17 +50,6 @@ ReturnValue_t MessageQueue::flush(uint32_t* count) {
return HasReturnvaluesIF::RETURN_OK;
}
MessageQueueId_t MessageQueue::getId() const { return mqId; }
void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
defaultDestinationSet = true;
this->defaultDestination = defaultDestination;
}
MessageQueueId_t MessageQueue::getDefaultDestination() const { return defaultDestination; }
bool MessageQueue::isDefaultDestinationSet() const { return defaultDestinationSet; }
// static core function to send messages.
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
MessageQueueMessageIF* message,

View File

@ -1,15 +1,17 @@
#ifndef FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_
#define FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_
#include <memory>
#include <queue>
#include "fsfw/ipc/MessageQueueBase.h"
#include "fsfw/internalerror/InternalErrorReporterIF.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/ipc/MessageQueueMessage.h"
#include "fsfw/ipc/MutexIF.h"
#include "fsfw/ipc/definitions.h"
#include "fsfw/timemanager/Clock.h"
#include <memory>
#include <queue>
/**
* @brief This class manages sending and receiving of
* message queue messages.
@ -33,7 +35,7 @@
* @ingroup osal
* @ingroup message_queue
*/
class MessageQueue : public MessageQueueIF {
class MessageQueue : public MessageQueueBase {
friend class MessageQueueSenderIF;
public:
@ -54,7 +56,8 @@ class MessageQueue : public MessageQueueIF {
* This should be left default.
*/
MessageQueue(size_t messageDepth = 3,
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE);
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE,
MqArgs* args = nullptr);
/** Copying message queues forbidden */
MessageQueue(const MessageQueue&) = delete;
@ -67,121 +70,12 @@ class MessageQueue : public MessageQueueIF {
*/
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.
*/
ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault = false) override;
/**
* @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(MessageQueueMessageIF* message) override;
/**
* @brief This operation sends a message to the last communication partner.
* @details This operation simplifies answering an incoming message by using
* the stored lastPartner 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(MessageQueueMessageIF* message) override;
/**
* @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.
*/
// Implement non-generic MessageQueueIF functions not handled by MessageQueueBase
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom = NO_QUEUE,
bool ignoreFault = false) override;
/**
* @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(MessageQueueMessageIF* message,
MessageQueueId_t sentFrom = NO_QUEUE,
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(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) 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(MessageQueueMessageIF* message) override;
/**
* 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) override;
/**
* @brief This method returns the message queue id of the last
* communication partner.
*/
MessageQueueId_t getLastPartner() const override;
/**
* @brief This method returns the message queue id of this class's
* message queue.
*/
MessageQueueId_t getId() const override;
/**
* @brief This method is a simple setter for the default destination.
*/
void setDefaultDestination(MessageQueueId_t defaultDestination) override;
/**
* @brief This method is a simple getter for the default destination.
*/
MessageQueueId_t getDefaultDestination() const override;
bool isDefaultDestinationSet() const override;
ReturnValue_t lockQueue(MutexIF::TimeoutType timeoutType, dur_millis_t lockTimeout);
ReturnValue_t unlockQueue();
@ -211,23 +105,14 @@ class MessageQueue : public MessageQueueIF {
MessageQueueId_t sentFrom = NO_QUEUE,
bool ignoreFault = false);
// static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault);
private:
std::queue<std::vector<uint8_t>> messageQueue;
/**
* @brief The class stores the queue id it got assigned.
* If initialization fails, the queue id is set to zero.
*/
MessageQueueId_t mqId = MessageQueueIF::NO_QUEUE;
size_t messageSize = 0;
size_t messageDepth = 0;
MutexIF* queueLock;
bool defaultDestinationSet = false;
MessageQueueId_t defaultDestination = MessageQueueIF::NO_QUEUE;
MessageQueueId_t lastPartner = MessageQueueIF::NO_QUEUE;
};
#endif /* FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ */

View File

@ -27,12 +27,13 @@ QueueFactory::QueueFactory() {}
QueueFactory::~QueueFactory() {}
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize) {
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize,
MqArgs* args) {
// A thread-safe queue can be implemented by using a combination
// of std::queue and std::mutex. This uses dynamic memory allocation
// which could be alleviated by using a custom allocator, external library
// (etl::queue) or simply using std::queue, we're on a host machine anyway.
return new MessageQueue(messageDepth, maxMessageSize);
return new MessageQueue(messageDepth, maxMessageSize, args);
}
void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { delete queue; }

View File

@ -1,29 +1,29 @@
target_sources(${LIB_FSFW_NAME} PRIVATE
Clock.cpp
BinarySemaphore.cpp
CountingSemaphore.cpp
FixedTimeslotTask.cpp
InternalErrorCodes.cpp
MessageQueue.cpp
Mutex.cpp
MutexFactory.cpp
PeriodicPosixTask.cpp
PosixThread.cpp
QueueFactory.cpp
SemaphoreFactory.cpp
TaskFactory.cpp
tcpipHelpers.cpp
unixUtility.cpp
BinarySemaphore.cpp
CountingSemaphore.cpp
FixedTimeslotTask.cpp
InternalErrorCodes.cpp
MessageQueue.cpp
Mutex.cpp
MutexFactory.cpp
PeriodicPosixTask.cpp
PosixThread.cpp
QueueFactory.cpp
SemaphoreFactory.cpp
TaskFactory.cpp
tcpipHelpers.cpp
unixUtility.cpp
)
find_package(Threads REQUIRED)
target_link_libraries(${LIB_FSFW_NAME} PRIVATE
${CMAKE_THREAD_LIBS_INIT}
rt
${CMAKE_THREAD_LIBS_INIT}
rt
)
target_link_libraries(${LIB_FSFW_NAME} INTERFACE
${CMAKE_THREAD_LIBS_INIT}
${CMAKE_THREAD_LIBS_INIT}
)

View File

@ -11,13 +11,10 @@
#include "fsfw/osal/linux/unixUtility.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize)
: id(MessageQueueIF::NO_QUEUE),
lastPartner(MessageQueueIF::NO_QUEUE),
defaultDestination(MessageQueueIF::NO_QUEUE),
MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize, MqArgs* args)
: MessageQueueBase(MessageQueueIF::NO_QUEUE, MessageQueueIF::NO_QUEUE, args),
maxMessageSize(maxMessageSize) {
mq_attr attributes;
this->id = 0;
// Set attributes
attributes.mq_curmsgs = 0;
attributes.mq_maxmsg = messageDepth;
@ -50,30 +47,6 @@ MessageQueue::~MessageQueue() {
}
}
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault) {
return sendMessageFrom(sendTo, message, this->getId(), false);
}
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) {
return sendToDefaultFrom(message, this->getId());
}
ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) {
if (this->lastPartner != 0) {
return sendMessageFrom(this->lastPartner, message, this->getId());
} else {
return NO_REPLY_PARTNER;
}
}
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) {
ReturnValue_t status = this->receiveMessage(message);
*receivedFrom = this->lastPartner;
return status;
}
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
if (message == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
@ -96,7 +69,7 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
int status = mq_receive(id, reinterpret_cast<char*>(message->getBuffer()),
message->getMaximumMessageSize(), &messagePriority);
if (status > 0) {
this->lastPartner = message->getSender();
this->last = message->getSender();
// Check size of incoming message.
if (message->getMessageSize() < message->getMinimumMessageSize()) {
return HasReturnvaluesIF::RETURN_FAILED;
@ -164,8 +137,6 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
}
}
MessageQueueId_t MessageQueue::getLastPartner() const { return this->lastPartner; }
ReturnValue_t MessageQueue::flush(uint32_t* count) {
mq_attr attrib;
int status = mq_getattr(id, &attrib);
@ -212,26 +183,11 @@ ReturnValue_t MessageQueue::flush(uint32_t* count) {
return HasReturnvaluesIF::RETURN_OK;
}
MessageQueueId_t MessageQueue::getId() const { return this->id; }
void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
this->defaultDestination = defaultDestination;
}
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; }
bool MessageQueue::isDefaultDestinationSet() const { return (defaultDestination != NO_QUEUE); }
uint16_t MessageQueue::queueCounter = 0;
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
@ -240,9 +196,9 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
bool ignoreFault) {
if (message == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MessageQueue::sendMessageFromMessageQueue: Message is nullptr!" << std::endl;
sif::error << "MessageQueue::sendMessageFromMessageQueue: Message is nullptr" << std::endl;
#else
sif::printError("MessageQueue::sendMessageFromMessageQueue: Message is nullptr!\n");
sif::printError("MessageQueue::sendMessageFromMessageQueue: Message is nullptr\n");
#endif
return HasReturnvaluesIF::RETURN_FAILED;
}
@ -256,7 +212,7 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
if (!ignoreFault) {
InternalErrorReporterIF* internalErrorReporter =
ObjectManager::instance()->get<InternalErrorReporterIF>(objects::INTERNAL_ERROR_REPORTER);
if (internalErrorReporter != NULL) {
if (internalErrorReporter != nullptr) {
internalErrorReporter->queueMessageNotSent();
}
}

View File

@ -1,11 +1,13 @@
#ifndef FSFW_OSAL_LINUX_MESSAGEQUEUE_H_
#define FSFW_OSAL_LINUX_MESSAGEQUEUE_H_
#include <fsfw/ipc/MessageQueueBase.h>
#include <mqueue.h>
#include "fsfw/internalerror/InternalErrorReporterIF.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/ipc/MessageQueueMessage.h"
#include "fsfw/ipc/definitions.h"
/**
* @brief This class manages sending and receiving of message queue messages.
*
@ -25,7 +27,7 @@
* makes use of the operating system calls provided.
* @ingroup message_queue
*/
class MessageQueue : public MessageQueueIF {
class MessageQueue : public MessageQueueBase {
friend class MessageQueueSenderIF;
public:
@ -42,104 +44,25 @@ class MessageQueue : public MessageQueueIF {
* This should be left default.
*/
MessageQueue(uint32_t messageDepth = 3,
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE);
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE,
MqArgs* args = nullptr);
/** 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.
*/
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.
*/
virtual ReturnValue_t sendMessage(MessageQueueId_t sendTo, 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(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
* 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(MessageQueueMessageIF* message);
/**
* @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(MessageQueueMessageIF* message, MessageQueueId_t* receivedFrom);
/**
* @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(MessageQueueMessageIF* 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.
* \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, 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.
* \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(MessageQueueMessageIF* 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;
bool isDefaultDestinationSet() const;
// Implement non-generic MessageQueueIF functions not handled by MessageQueueBase
ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override;
ReturnValue_t flush(uint32_t* count) override;
ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom,
bool ignoreFault = false) override;
protected:
/**
@ -158,31 +81,10 @@ class MessageQueue : public MessageQueueIF {
bool ignoreFault = false);
private:
/**
* @brief The class stores the queue id it got assigned from the operating system in this
* attribute. If initialization fails, the queue id is set to zero.
*/
MessageQueueId_t id;
/**
* @brief In this attribute, the queue id of the last communication partner is stored
* to allow for replying.
*/
MessageQueueId_t lastPartner;
/**
* @brief The message queue's name -a user specific information for the operating system- is
* generated automatically with the help of this static counter.
*/
/**
* \brief This attribute stores a default destination to send messages to.
* \details It is stored to simplify sending to always-the-same receiver. The attribute may
* be set in the constructor or by a setter call to setDefaultDestination.
*/
MessageQueueId_t defaultDestination;
/**
* The name of the message queue, stored for unlinking
*/
char name[16];
char name[16] = {};
static uint16_t queueCounter;
const size_t maxMessageSize;

View File

@ -28,8 +28,9 @@ QueueFactory::QueueFactory() {}
QueueFactory::~QueueFactory() {}
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize) {
return new MessageQueue(messageDepth, maxMessageSize);
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize,
MqArgs* args) {
return new MessageQueue(messageDepth, maxMessageSize, args);
}
void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { delete queue; }

View File

@ -6,8 +6,9 @@
#include "fsfw/osal/rtems/RtemsBasic.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size)
: id(0), lastPartner(0), defaultDestination(NO_QUEUE), internalErrorReporter(nullptr) {
MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size, MqArgs* args)
: MessageQueueBase(MessageQueueIF::NO_QUEUE, MessageQueueIF::NO_QUEUE, args),
internalErrorReporter(nullptr) {
rtems_name name = ('Q' << 24) + (queueCounter++ << 8);
rtems_status_code status =
rtems_message_queue_create(name, message_depth, max_message_size, 0, &(this->id));
@ -16,43 +17,19 @@ MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size)
sif::error << "MessageQueue::MessageQueue: Creating Queue " << std::hex << name << std::dec
<< " failed with status:" << (uint32_t)status << std::endl;
#endif
this->id = 0;
this->id = MessageQueueIF::NO_QUEUE;
}
}
MessageQueue::~MessageQueue() { rtems_message_queue_delete(id); }
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault) {
return sendMessageFrom(sendTo, message, this->getId(), ignoreFault);
}
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) {
return sendToDefaultFrom(message, this->getId());
}
ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) {
if (this->lastPartner != 0) {
return sendMessage(this->lastPartner, message, this->getId());
} else {
return NO_REPLY_PARTNER;
}
}
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) {
ReturnValue_t status = this->receiveMessage(message);
*receivedFrom = this->lastPartner;
return status;
}
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
size_t size = 0;
rtems_status_code status =
rtems_message_queue_receive(id, message->getBuffer(), &size, RTEMS_NO_WAIT, 1);
if (status == RTEMS_SUCCESSFUL) {
message->setMessageSize(size);
this->lastPartner = message->getSender();
this->last = message->getSender();
// Check size of incoming message.
if (message->getMessageSize() < message->getMinimumMessageSize()) {
return HasReturnvaluesIF::RETURN_FAILED;
@ -65,19 +42,11 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
return convertReturnCode(status);
}
MessageQueueId_t MessageQueue::getLastPartner() const { return this->lastPartner; }
ReturnValue_t MessageQueue::flush(uint32_t* count) {
rtems_status_code status = rtems_message_queue_flush(id, count);
return convertReturnCode(status);
}
MessageQueueId_t MessageQueue::getId() const { return this->id; }
void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
this->defaultDestination = defaultDestination;
}
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault) {
message->setSender(sentFrom);
@ -103,15 +72,6 @@ ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueu
return returnCode;
}
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault) {
return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault);
}
MessageQueueId_t MessageQueue::getDefaultDestination() const { return this->defaultDestination; }
bool MessageQueue::isDefaultDestinationSet() const { return (defaultDestination != NO_QUEUE); }
ReturnValue_t MessageQueue::convertReturnCode(rtems_status_code inValue) {
switch (inValue) {
case RTEMS_SUCCESSFUL:

View File

@ -1,10 +1,12 @@
#ifndef FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_
#define FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_
#include <fsfw/ipc/MessageQueueBase.h>
#include "RtemsBasic.h"
#include "fsfw/internalerror/InternalErrorReporterIF.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/ipc/MessageQueueMessage.h"
#include "fsfw/ipc/definitions.h"
/**
* @brief This class manages sending and receiving of message queue messages.
@ -19,7 +21,7 @@
*as well as sending and receiving messages, the class makes use of the operating system calls
*provided. \ingroup message_queue
*/
class MessageQueue : public MessageQueueIF {
class MessageQueue : public MessageQueueBase {
public:
/**
* @brief The constructor initializes and configures the message queue.
@ -34,131 +36,26 @@ class MessageQueue : public MessageQueueIF {
* This should be left default.
*/
MessageQueue(size_t message_depth = 3,
size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE);
size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE,
MqArgs* args = nullptr);
/** 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.
*/
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.
*/
ReturnValue_t sendMessage(MessageQueueId_t sendTo, 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.
*/
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
* 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(MessageQueueMessageIF* message);
/**
* @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(MessageQueueMessageIF* message, MessageQueueId_t* receivedFrom);
/**
* @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(MessageQueueMessageIF* 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, MessageQueueMessageIF* message,
// Implement non-generic MessageQueueIF functions not handled by MessageQueueBase
ReturnValue_t flush(uint32_t* count) override;
ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* 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(MessageQueueMessageIF* 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;
bool isDefaultDestinationSet() const;
bool ignoreFault = false) override;
private:
/**
* @brief The class stores the queue id it got assigned from the operating system in this
* attribute. If initialization fails, the queue id is set to zero.
*/
MessageQueueId_t id;
/**
* @brief In this attribute, the queue id of the last communication partner is stored
* to allow for replying.
*/
MessageQueueId_t lastPartner;
/**
* @brief The message queue's name -a user specific information for the operating system- is
* generated automatically with the help of this static counter.
*/
/**
* \brief This attribute stores a default destination to send messages to.
* \details It is stored to simplify sending to always-the-same receiver. The attribute may
* be set in the constructor or by a setter call to setDefaultDestination.
*/
MessageQueueId_t defaultDestination;
/**
* \brief This attribute stores a reference to the internal error reporter for reporting full
* queues. \details In the event of a full destination queue, the reporter will be notified. The

View File

@ -49,8 +49,9 @@ QueueFactory::QueueFactory() {}
QueueFactory::~QueueFactory() {}
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize) {
return new MessageQueue(messageDepth, maxMessageSize);
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize,
MqArgs* args) {
return new MessageQueue(messageDepth, maxMessageSize, args);
}
void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { delete queue; }

View File

@ -21,8 +21,10 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
REQUIRE(poolOwner->initializeHkManager() == retval::CATCH_OK);
REQUIRE(poolOwner->initializeHkManagerAfterTaskCreation() == retval::CATCH_OK);
MessageQueueMockBase* mqMock = poolOwner->getMockQueueHandle();
REQUIRE(mqMock != nullptr);
MessageQueueMockBase* poolOwnerMock = poolOwner->getMockQueueHandle();
REQUIRE(poolOwnerMock != nullptr);
// MessageQueueIF* hkCommander = QueueFactory::instance()->createMessageQueue();
CommandMessage messageSent;
uint8_t messagesSent = 0;
@ -41,9 +43,9 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
poolOwner->dataset.setChanged(true);
/* Now the update message should be generated. */
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent() == true);
REQUIRE(poolOwnerMock->wasMessageSent() == true);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() ==
static_cast<int>(HousekeepingMessage::UPDATE_NOTIFICATION_SET));
@ -53,9 +55,9 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
poolOwner->dataset.setChanged(true);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() ==
static_cast<int>(HousekeepingMessage::UPDATE_NOTIFICATION_SET));
@ -63,15 +65,15 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
REQUIRE(poolOwner->subscribeWrapperSetUpdateHk() == retval::CATCH_OK);
poolOwner->dataset.setChanged(true);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 2);
/* first message sent should be the update notification, considering
the internal list is a vector checked in insertion order. */
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() ==
static_cast<int>(HousekeepingMessage::UPDATE_NOTIFICATION_SET));
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() == static_cast<int>(HousekeepingMessage::HK_REPORT));
/* Clear message to avoid memory leak, our mock won't do it for us (yet) */
CommandMessageCleaner::clearCommandMessage(&messageSent);
@ -99,9 +101,9 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
/* Trigger generation of snapshot */
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK);
/* Check that snapshot was generated */
CHECK(messageSent.getCommand() == static_cast<int>(HousekeepingMessage::UPDATE_SNAPSHOT_SET));
/* Now we deserialize the snapshot into a new dataset instance */
@ -162,12 +164,12 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
/* Check update snapshot was sent. */
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
/* Should have been reset. */
CHECK(poolVar->hasChanged() == false);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() ==
static_cast<int>(HousekeepingMessage::UPDATE_SNAPSHOT_VARIABLE));
/* Now we deserialize the snapshot into a new dataset instance */
@ -209,11 +211,11 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
/* Check update notification was sent. */
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
/* Should have been reset. */
CHECK(poolVar->hasChanged() == false);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() ==
static_cast<int>(HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE));
/* Now subscribe for the dataset update (HK and update) again with subscription interface */
@ -225,26 +227,26 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
poolOwner->dataset.setChanged(true);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
/* Now two messages should be sent. */
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 2);
mqMock->clearMessages(true);
poolOwnerMock->clearMessages(true);
poolOwner->dataset.setChanged(true);
poolVar->setChanged(true);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
/* Now three messages should be sent. */
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 3);
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() ==
static_cast<int>(HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE));
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() ==
static_cast<int>(HousekeepingMessage::UPDATE_NOTIFICATION_SET));
REQUIRE(mqMock->receiveMessage(&messageSent) == retval::CATCH_OK);
REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == retval::CATCH_OK);
CHECK(messageSent.getCommand() == static_cast<int>(HousekeepingMessage::HK_REPORT));
CommandMessageCleaner::clearCommandMessage(&messageSent);
REQUIRE(mqMock->receiveMessage(&messageSent) == static_cast<int>(MessageQueueIF::EMPTY));
REQUIRE(poolOwnerMock->receiveMessage(&messageSent) == static_cast<int>(MessageQueueIF::EMPTY));
}
SECTION("PeriodicHKAndMessaging") {
@ -255,38 +257,38 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
REQUIRE(poolOwner->subscribePeriodicHk(true) == retval::CATCH_OK);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
/* Now HK packet should be sent as message immediately. */
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
LocalPoolDataSetBase* setHandle = poolOwner->getDataSetHandle(lpool::testSid);
REQUIRE(setHandle != nullptr);
CHECK(poolOwner->poolManager.generateHousekeepingPacket(lpool::testSid, setHandle, false) ==
retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
CHECK(setHandle->getReportingEnabled() == true);
CommandMessage hkCmd;
HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, false, false);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
CHECK(setHandle->getReportingEnabled() == false);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, true, false);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
CHECK(setHandle->getReportingEnabled() == true);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, false, false);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
CHECK(setHandle->getReportingEnabled() == false);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4,
false);
@ -294,23 +296,23 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
/* For non-diagnostics and a specified minimum frequency of 0.2 seconds, the
resulting collection interval should be 1.0 second */
CHECK(poolOwner->dataset.getCollectionInterval() == 1.0);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, false);
REQUIRE(poolOwner->poolManager.performHkOperation() == retval::CATCH_OK);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
/* Now HK packet should be sent as message. */
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setOneShotReportCommand(&hkCmd, lpool::testSid, false);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setUpdateNotificationSetCommand(&hkCmd, lpool::testSid);
sid_t sidToCheck;
@ -326,62 +328,62 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) ==
static_cast<int>(LocalDataPoolManager::WRONG_HK_PACKET_TYPE));
/* We still expect a failure message being sent */
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4,
false);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) ==
static_cast<int>(LocalDataPoolManager::WRONG_HK_PACKET_TYPE));
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, false);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) ==
static_cast<int>(LocalDataPoolManager::WRONG_HK_PACKET_TYPE));
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setStructureReportingCommand(&hkCmd, lpool::testSid, true);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setCollectionIntervalModificationCommand(&hkCmd, lpool::testSid, 0.4,
true);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, true, true);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setToggleReportingCommand(&hkCmd, lpool::testSid, false, true);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setOneShotReportCommand(&hkCmd, lpool::testSid, false);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) ==
static_cast<int>(LocalDataPoolManager::WRONG_HK_PACKET_TYPE));
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setOneShotReportCommand(&hkCmd, lpool::testSid, true);
CHECK(poolOwner->poolManager.handleHousekeepingMessage(&hkCmd) == retval::CATCH_OK);
REQUIRE(mqMock->wasMessageSent(&messagesSent) == true);
REQUIRE(poolOwnerMock->wasMessageSent(&messagesSent) == true);
CHECK(messagesSent == 1);
CHECK(mqMock->popMessage() == retval::CATCH_OK);
CHECK(poolOwnerMock->popMessage() == retval::CATCH_OK);
HousekeepingMessage::setUpdateNotificationVariableCommand(&hkCmd, lpool::uint8VarGpid);
gp_id_t gpidToCheck;
@ -407,5 +409,5 @@ TEST_CASE("LocalPoolManagerTest", "[LocManTest]") {
/* we need to reset the subscription list because the pool owner
is a global object. */
CHECK(poolOwner->reset() == retval::CATCH_OK);
mqMock->clearMessages(true);
poolOwnerMock->clearMessages(true);
}

View File

@ -4,16 +4,18 @@
#include <cstring>
#include <queue>
#include "fsfw/ipc/MessageQueueBase.h"
#include "fsfw/ipc/CommandMessage.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/ipc/MessageQueueMessage.h"
#include "fsfw_tests/unit/CatchDefinitions.h"
class MessageQueueMockBase : public MessageQueueIF {
class MessageQueueMockBase : public MessageQueueBase {
public:
MessageQueueId_t myQueueId = tconst::testQueueId;
MessageQueueMockBase()
: MessageQueueBase(MessageQueueIF::NO_QUEUE, MessageQueueIF::NO_QUEUE, nullptr) {}
uint8_t messageSentCounter = 0;
bool defaultDestSet = false;
bool messageSent = false;
bool wasMessageSent(uint8_t* messageSentCounter = nullptr, bool resetCounter = true) {
@ -38,53 +40,30 @@ class MessageQueueMockBase : public MessageQueueIF {
return receiveMessage(&message);
}
virtual ReturnValue_t reply(MessageQueueMessageIF* message) {
return sendMessage(myQueueId, message);
};
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) {
return receiveMessage(message);
}
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) {
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override {
if (messagesSentQueue.empty()) {
return MessageQueueIF::EMPTY;
}
this->last = message->getSender();
std::memcpy(message->getBuffer(), messagesSentQueue.front().getBuffer(),
message->getMessageSize());
messagesSentQueue.pop();
return HasReturnvaluesIF::RETURN_OK;
}
virtual ReturnValue_t flush(uint32_t* count) { return HasReturnvaluesIF::RETURN_OK; }
virtual MessageQueueId_t getLastPartner() const { return myQueueId; }
virtual MessageQueueId_t getId() const { return myQueueId; }
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault = false) {
return sendMessage(sendTo, message);
}
virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault = false) {
return sendMessage(myQueueId, message);
}
virtual ReturnValue_t sendToDefault(MessageQueueMessageIF* message) {
return sendMessage(myQueueId, message);
}
virtual ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault = false) override {
MessageQueueId_t sentFrom,
bool ignoreFault = false) override {
messageSent = true;
messageSentCounter++;
MessageQueueMessage& messageRef = *(dynamic_cast<MessageQueueMessage*>(message));
messagesSentQueue.push(messageRef);
return HasReturnvaluesIF::RETURN_OK;
}
virtual void setDefaultDestination(MessageQueueId_t defaultDestination) {
myQueueId = defaultDestination;
defaultDestSet = true;
}
virtual MessageQueueId_t getDefaultDestination() const { return myQueueId; }
virtual bool isDefaultDestinationSet() const { return defaultDestSet; }
virtual ReturnValue_t reply(MessageQueueMessageIF* message) override {
return sendMessageFrom(MessageQueueIF::NO_QUEUE, message, this->getId(), false);
}
void clearMessages(bool clearCommandMessages = true) {
while (not messagesSentQueue.empty()) {