From 2f993cf39a91bce9cbebc3845476578ba39727e5 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 2 Nov 2020 15:51:52 +0100 Subject: [PATCH 01/23] some minor form stuff --- action/ActionHelper.cpp | 1 + action/ActionMessage.h | 18 +++++++++++------- action/CommandsActionsIF.h | 15 +++++++++------ 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/action/ActionHelper.cpp b/action/ActionHelper.cpp index 0d3baa88..28557916 100644 --- a/action/ActionHelper.cpp +++ b/action/ActionHelper.cpp @@ -1,5 +1,6 @@ #include "ActionHelper.h" #include "HasActionsIF.h" + #include "../ipc/MessageQueueSenderIF.h" #include "../objectmanager/ObjectManagerIF.h" diff --git a/action/ActionMessage.h b/action/ActionMessage.h index 0a718aab..7a859de0 100644 --- a/action/ActionMessage.h +++ b/action/ActionMessage.h @@ -1,5 +1,5 @@ -#ifndef ACTIONMESSAGE_H_ -#define ACTIONMESSAGE_H_ +#ifndef FSFW_ACTION_ACTIONMESSAGE_H_ +#define FSFW_ACTION_ACTIONMESSAGE_H_ #include "../ipc/CommandMessage.h" #include "../objectmanager/ObjectManagerIF.h" @@ -18,15 +18,19 @@ public: static const Command_t COMPLETION_SUCCESS = MAKE_COMMAND_ID(5); static const Command_t COMPLETION_FAILED = MAKE_COMMAND_ID(6); virtual ~ActionMessage(); - static void setCommand(CommandMessage* message, ActionId_t fid, store_address_t parameters); + static void setCommand(CommandMessage* message, ActionId_t fid, + store_address_t parameters); static ActionId_t getActionId(const CommandMessage* message ); static store_address_t getStoreId(const CommandMessage* message ); - static void setStepReply(CommandMessage* message, ActionId_t fid, uint8_t step, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); + static void setStepReply(CommandMessage* message, ActionId_t fid, + uint8_t step, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); static uint8_t getStep(const CommandMessage* message ); static ReturnValue_t getReturnCode(const CommandMessage* message ); - static void setDataReply(CommandMessage* message, ActionId_t actionId, store_address_t data); - static void setCompletionReply(CommandMessage* message, ActionId_t fid, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); + static void setDataReply(CommandMessage* message, ActionId_t actionId, + store_address_t data); + static void setCompletionReply(CommandMessage* message, ActionId_t fid, + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); static void clear(CommandMessage* message); }; -#endif /* ACTIONMESSAGE_H_ */ +#endif /* FSFW_ACTION_ACTIONMESSAGE_H_ */ diff --git a/action/CommandsActionsIF.h b/action/CommandsActionsIF.h index 3d04015d..491bfc70 100644 --- a/action/CommandsActionsIF.h +++ b/action/CommandsActionsIF.h @@ -1,5 +1,5 @@ -#ifndef COMMANDSACTIONSIF_H_ -#define COMMANDSACTIONSIF_H_ +#ifndef FSFW_ACTION_COMMANDSACTIONSIF_H_ +#define FSFW_ACTION_COMMANDSACTIONSIF_H_ #include "CommandActionHelper.h" #include "../returnvalues/HasReturnvaluesIF.h" @@ -24,11 +24,14 @@ public: virtual MessageQueueIF* getCommandQueuePtr() = 0; protected: virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step) = 0; - virtual void stepFailedReceived(ActionId_t actionId, uint8_t step, ReturnValue_t returnCode) = 0; - virtual void dataReceived(ActionId_t actionId, const uint8_t* data, uint32_t size) = 0; + virtual void stepFailedReceived(ActionId_t actionId, uint8_t step, + ReturnValue_t returnCode) = 0; + virtual void dataReceived(ActionId_t actionId, const uint8_t* data, + uint32_t size) = 0; virtual void completionSuccessfulReceived(ActionId_t actionId) = 0; - virtual void completionFailedReceived(ActionId_t actionId, ReturnValue_t returnCode) = 0; + virtual void completionFailedReceived(ActionId_t actionId, + ReturnValue_t returnCode) = 0; }; -#endif /* COMMANDSACTIONSIF_H_ */ +#endif /* FSFW_ACTION_COMMANDSACTIONSIF_H_ */ From 3067259a9b266fed39e8333fd9a29439718b68e0 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 2 Nov 2020 17:19:24 +0100 Subject: [PATCH 02/23] include added --- fsfw.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fsfw.mk b/fsfw.mk index 3639717b..f2cdd7ab 100644 --- a/fsfw.mk +++ b/fsfw.mk @@ -70,3 +70,5 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/packetmatcher/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/pus/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcservices/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/pus/*.cpp) + +INCLUDES += $(CURRENTPATH) From cc51d9ace922fa0a0d141345a6de33ae84cd97f6 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 2 Nov 2020 17:21:25 +0100 Subject: [PATCH 03/23] small fix so that it compiles --- devicehandlers/DeviceHandlerIF.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/devicehandlers/DeviceHandlerIF.h b/devicehandlers/DeviceHandlerIF.h index 52a3be4d..10c9b89a 100644 --- a/devicehandlers/DeviceHandlerIF.h +++ b/devicehandlers/DeviceHandlerIF.h @@ -18,6 +18,8 @@ public: static const uint8_t TRANSITION_MODE_CHILD_ACTION_MASK = 0x20; static const uint8_t TRANSITION_MODE_BASE_ACTION_MASK = 0x10; + static constexpr DeviceCommandId_t NO_COMMAND = 0xffffffff; + /** * @brief This is the mode the device handler is in. * From 113397c6c6ae4c46341f4880710e4e4d9b6e7630 Mon Sep 17 00:00:00 2001 From: "Jakob.Meier" Date: Sat, 7 Nov 2020 20:30:42 +0100 Subject: [PATCH 04/23] udp bridge for embedded linux --- osal/linux/TcUnixUdpPollingTask.cpp | 6 +++--- osal/linux/TmTcUnixUdpBridge.cpp | 22 +++++++++++++++------- osal/linux/TmTcUnixUdpBridge.h | 5 ++++- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/osal/linux/TcUnixUdpPollingTask.cpp b/osal/linux/TcUnixUdpPollingTask.cpp index 670ba804..7df56a95 100644 --- a/osal/linux/TcUnixUdpPollingTask.cpp +++ b/osal/linux/TcUnixUdpPollingTask.cpp @@ -33,7 +33,7 @@ ReturnValue_t TcUnixUdpPollingTask::performOperation(uint8_t opCode) { while(1) { //! Sender Address is cached here. struct sockaddr_in senderAddress; - socklen_t senderSockLen = 0; + socklen_t senderSockLen = sizeof(senderAddress); ssize_t bytesReceived = recvfrom(serverUdpSocket, receptionBuffer.data(), frameSize, receptionFlags, reinterpret_cast(&senderAddress), &senderSockLen); @@ -45,8 +45,8 @@ ReturnValue_t TcUnixUdpPollingTask::performOperation(uint8_t opCode) { continue; } -// sif::debug << "TcSocketPollingTask::performOperation: " << bytesReceived -// << " bytes received" << std::endl; + sif::debug << "TcSocketPollingTask::performOperation: " << bytesReceived + << " bytes received" << std::endl; ReturnValue_t result = handleSuccessfullTcRead(bytesReceived); if(result != HasReturnvaluesIF::RETURN_FAILED) { diff --git a/osal/linux/TmTcUnixUdpBridge.cpp b/osal/linux/TmTcUnixUdpBridge.cpp index b55291b3..71a39384 100644 --- a/osal/linux/TmTcUnixUdpBridge.cpp +++ b/osal/linux/TmTcUnixUdpBridge.cpp @@ -65,13 +65,17 @@ TmTcUnixUdpBridge::~TmTcUnixUdpBridge() { ReturnValue_t TmTcUnixUdpBridge::sendTm(const uint8_t *data, size_t dataLen) { int flags = 0; - clientAddress.sin_addr.s_addr = htons(INADDR_ANY); - //clientAddress.sin_addr.s_addr = inet_addr("127.73.73.1"); - clientAddressLen = sizeof(serverAddress); + MutexHelper lock(mutex, MutexIF::TimeoutType::WAITING, 10); -// char ipAddress [15]; -// sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET, -// &clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl; + if(ipAddrAnySet){ + clientAddress.sin_addr.s_addr = htons(INADDR_ANY); + //clientAddress.sin_addr.s_addr = inet_addr("127.73.73.1"); + clientAddressLen = sizeof(serverAddress); + } + + char ipAddress [15]; + sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET, + &clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl; ssize_t bytesSent = sendto(serverSocket, data, dataLen, flags, reinterpret_cast(&clientAddress), clientAddressLen); @@ -85,7 +89,7 @@ ReturnValue_t TmTcUnixUdpBridge::sendTm(const uint8_t *data, size_t dataLen) { return HasReturnvaluesIF::RETURN_OK; } -void TmTcUnixUdpBridge::checkAndSetClientAddress(sockaddr_in newAddress) { +void TmTcUnixUdpBridge::checkAndSetClientAddress(sockaddr_in& newAddress) { MutexHelper lock(mutex, MutexIF::TimeoutType::WAITING, 10); // char ipAddress [15]; @@ -168,3 +172,7 @@ void TmTcUnixUdpBridge::handleSendError() { } } +void TmTcUnixUdpBridge::setClientAddressToAny(bool ipAddrAnySet){ + this->ipAddrAnySet = ipAddrAnySet; +} + diff --git a/osal/linux/TmTcUnixUdpBridge.h b/osal/linux/TmTcUnixUdpBridge.h index 5245c44c..ae6f6adc 100644 --- a/osal/linux/TmTcUnixUdpBridge.h +++ b/osal/linux/TmTcUnixUdpBridge.h @@ -20,8 +20,9 @@ public: uint16_t serverPort = 0xFFFF,uint16_t clientPort = 0xFFFF); virtual~ TmTcUnixUdpBridge(); - void checkAndSetClientAddress(sockaddr_in clientAddress); + void checkAndSetClientAddress(sockaddr_in& clientAddress); + void setClientAddressToAny(bool ipAddrAnySet); protected: virtual ReturnValue_t sendTm(const uint8_t * data, size_t dataLen) override; @@ -36,6 +37,8 @@ private: struct sockaddr_in serverAddress; socklen_t serverAddressLen = 0; + bool ipAddrAnySet = false; + //! Access to the client address is mutex protected as it is set //! by another task. MutexIF* mutex; From 83568e11d11e66f023ede3b7701df884c2129317 Mon Sep 17 00:00:00 2001 From: "Jakob.Meier" Date: Sat, 7 Nov 2020 20:37:48 +0100 Subject: [PATCH 05/23] removed unwanted changes --- devicehandlers/DeviceHandlerIF.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/devicehandlers/DeviceHandlerIF.h b/devicehandlers/DeviceHandlerIF.h index 10c9b89a..52a3be4d 100644 --- a/devicehandlers/DeviceHandlerIF.h +++ b/devicehandlers/DeviceHandlerIF.h @@ -18,8 +18,6 @@ public: static const uint8_t TRANSITION_MODE_CHILD_ACTION_MASK = 0x20; static const uint8_t TRANSITION_MODE_BASE_ACTION_MASK = 0x10; - static constexpr DeviceCommandId_t NO_COMMAND = 0xffffffff; - /** * @brief This is the mode the device handler is in. * From 210d2de11e25bc2d521687aef35cf5f764df08ce Mon Sep 17 00:00:00 2001 From: "Jakob.Meier" Date: Sat, 7 Nov 2020 20:40:01 +0100 Subject: [PATCH 06/23] fetched fsfw.mk from upstream master --- fsfw.mk | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/fsfw.mk b/fsfw.mk index f2cdd7ab..c2c6e747 100644 --- a/fsfw.mk +++ b/fsfw.mk @@ -28,25 +28,12 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/*.cpp) # select the OS ifeq ($(OS_FSFW),rtems) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/rtems/*.cpp) - else ifeq ($(OS_FSFW),linux) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/linux/*.cpp) - else ifeq ($(OS_FSFW),freeRTOS) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/FreeRTOS/*.cpp) - else ifeq ($(OS_FSFW),host) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/host/*.cpp) -ifeq ($(OS),Windows_NT) -CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/windows/*.cpp) -else -# For now, the linux UDP bridge sources needs to be included manually by upper makefile -# for host OS because we can't be sure the OS is linux. -# Following lines can be used to do this: -# CXXSRC += $(FRAMEWORK_PATH)/osal/linux/TcUnixUdpPollingTask.cpp -# CXXSRC += $(FRAMEWORK_PATH)/osal/linux/TmTcUnixUdpBridge.cpp -endif - else $(error invalid OS_FSFW specified, valid OS_FSFW are rtems, linux, freeRTOS, host) endif @@ -70,5 +57,3 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/packetmatcher/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/pus/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcservices/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/pus/*.cpp) - -INCLUDES += $(CURRENTPATH) From 3eefcd3a2d52b7420c33dd34bc334093a37c3b03 Mon Sep 17 00:00:00 2001 From: "Jakob.Meier" Date: Sat, 7 Nov 2020 20:45:00 +0100 Subject: [PATCH 07/23] fsfw.mk adjusted to upstream master --- fsfw.mk | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/fsfw.mk b/fsfw.mk index c2c6e747..3639717b 100644 --- a/fsfw.mk +++ b/fsfw.mk @@ -28,12 +28,25 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/*.cpp) # select the OS ifeq ($(OS_FSFW),rtems) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/rtems/*.cpp) + else ifeq ($(OS_FSFW),linux) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/linux/*.cpp) + else ifeq ($(OS_FSFW),freeRTOS) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/FreeRTOS/*.cpp) + else ifeq ($(OS_FSFW),host) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/host/*.cpp) +ifeq ($(OS),Windows_NT) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/windows/*.cpp) +else +# For now, the linux UDP bridge sources needs to be included manually by upper makefile +# for host OS because we can't be sure the OS is linux. +# Following lines can be used to do this: +# CXXSRC += $(FRAMEWORK_PATH)/osal/linux/TcUnixUdpPollingTask.cpp +# CXXSRC += $(FRAMEWORK_PATH)/osal/linux/TmTcUnixUdpBridge.cpp +endif + else $(error invalid OS_FSFW specified, valid OS_FSFW are rtems, linux, freeRTOS, host) endif From bc81b5893c93cd6a68361bb2f1235220edc055da Mon Sep 17 00:00:00 2001 From: "Jakob.Meier" Date: Mon, 9 Nov 2020 17:34:53 +0100 Subject: [PATCH 08/23] removed debug output --- osal/linux/TmTcUnixUdpBridge.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osal/linux/TmTcUnixUdpBridge.cpp b/osal/linux/TmTcUnixUdpBridge.cpp index 71a39384..ab28623e 100644 --- a/osal/linux/TmTcUnixUdpBridge.cpp +++ b/osal/linux/TmTcUnixUdpBridge.cpp @@ -73,9 +73,9 @@ ReturnValue_t TmTcUnixUdpBridge::sendTm(const uint8_t *data, size_t dataLen) { clientAddressLen = sizeof(serverAddress); } - char ipAddress [15]; - sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET, - &clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl; +// char ipAddress [15]; +// sif::debug << "IP Address Sender: "<< inet_ntop(AF_INET, +// &clientAddress.sin_addr.s_addr, ipAddress, 15) << std::endl; ssize_t bytesSent = sendto(serverSocket, data, dataLen, flags, reinterpret_cast(&clientAddress), clientAddressLen); From 37fc22a11785d6363954169ba6bae3d40a4be493 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 9 Nov 2020 21:21:56 +0100 Subject: [PATCH 09/23] config folder renamed and improved --- .../{config => fsfwconfig}/FSFWConfig.h | 1 + .../{config => fsfwconfig}/OBSWConfig.h | 0 .../{config => fsfwconfig}/OBSWVersion.h | 0 .../devices/logicalAddresses.cpp | 0 .../devices/logicalAddresses.h | 2 +- .../devices/powerSwitcherList.cpp | 0 .../devices/powerSwitcherList.h | 0 .../events/subsystemIdRanges.h | 0 .../config.mk => fsfwconfig/fsfwconfig.mk} | 0 .../ipc/missionMessageTypes.cpp | 3 +- .../ipc/missionMessageTypes.h | 0 .../objects/Factory.cpp | 14 +- .../{config => fsfwconfig}/objects/Factory.h | 0 .../objects/systemObjectList.h | 0 .../fsfwconfig/objects/translateObjects.cpp | 271 ++++++++++++++++++ .../fsfwconfig/objects/translateObjects.h | 9 + .../PollingSequenceFactory.cpp | 0 .../pollingsequence/PollingSequenceFactory.h | 0 .../returnvalues/classIds.h | 0 defaultcfg/{config => fsfwconfig}/tmtc/apid.h | 0 .../{config => fsfwconfig}/tmtc/pusIds.h | 0 21 files changed, 291 insertions(+), 9 deletions(-) rename defaultcfg/{config => fsfwconfig}/FSFWConfig.h (98%) rename defaultcfg/{config => fsfwconfig}/OBSWConfig.h (100%) rename defaultcfg/{config => fsfwconfig}/OBSWVersion.h (100%) rename defaultcfg/{config => fsfwconfig}/devices/logicalAddresses.cpp (100%) rename defaultcfg/{config => fsfwconfig}/devices/logicalAddresses.h (89%) rename defaultcfg/{config => fsfwconfig}/devices/powerSwitcherList.cpp (100%) rename defaultcfg/{config => fsfwconfig}/devices/powerSwitcherList.h (100%) rename defaultcfg/{config => fsfwconfig}/events/subsystemIdRanges.h (100%) rename defaultcfg/{config/config.mk => fsfwconfig/fsfwconfig.mk} (100%) rename defaultcfg/{config => fsfwconfig}/ipc/missionMessageTypes.cpp (79%) rename defaultcfg/{config => fsfwconfig}/ipc/missionMessageTypes.h (100%) rename defaultcfg/{config => fsfwconfig}/objects/Factory.cpp (75%) rename defaultcfg/{config => fsfwconfig}/objects/Factory.h (100%) rename defaultcfg/{config => fsfwconfig}/objects/systemObjectList.h (100%) create mode 100644 defaultcfg/fsfwconfig/objects/translateObjects.cpp create mode 100644 defaultcfg/fsfwconfig/objects/translateObjects.h rename defaultcfg/{config => fsfwconfig}/pollingsequence/PollingSequenceFactory.cpp (100%) rename defaultcfg/{config => fsfwconfig}/pollingsequence/PollingSequenceFactory.h (100%) rename defaultcfg/{config => fsfwconfig}/returnvalues/classIds.h (100%) rename defaultcfg/{config => fsfwconfig}/tmtc/apid.h (100%) rename defaultcfg/{config => fsfwconfig}/tmtc/pusIds.h (100%) diff --git a/defaultcfg/config/FSFWConfig.h b/defaultcfg/fsfwconfig/FSFWConfig.h similarity index 98% rename from defaultcfg/config/FSFWConfig.h rename to defaultcfg/fsfwconfig/FSFWConfig.h index ea86152c..be3717b4 100644 --- a/defaultcfg/config/FSFWConfig.h +++ b/defaultcfg/fsfwconfig/FSFWConfig.h @@ -3,6 +3,7 @@ #include #include +#include //! Used to determine whether C++ ostreams are used //! Those can lead to code bloat. diff --git a/defaultcfg/config/OBSWConfig.h b/defaultcfg/fsfwconfig/OBSWConfig.h similarity index 100% rename from defaultcfg/config/OBSWConfig.h rename to defaultcfg/fsfwconfig/OBSWConfig.h diff --git a/defaultcfg/config/OBSWVersion.h b/defaultcfg/fsfwconfig/OBSWVersion.h similarity index 100% rename from defaultcfg/config/OBSWVersion.h rename to defaultcfg/fsfwconfig/OBSWVersion.h diff --git a/defaultcfg/config/devices/logicalAddresses.cpp b/defaultcfg/fsfwconfig/devices/logicalAddresses.cpp similarity index 100% rename from defaultcfg/config/devices/logicalAddresses.cpp rename to defaultcfg/fsfwconfig/devices/logicalAddresses.cpp diff --git a/defaultcfg/config/devices/logicalAddresses.h b/defaultcfg/fsfwconfig/devices/logicalAddresses.h similarity index 89% rename from defaultcfg/config/devices/logicalAddresses.h rename to defaultcfg/fsfwconfig/devices/logicalAddresses.h index 174fa788..e0827ba3 100644 --- a/defaultcfg/config/devices/logicalAddresses.h +++ b/defaultcfg/fsfwconfig/devices/logicalAddresses.h @@ -1,8 +1,8 @@ #ifndef CONFIG_DEVICES_LOGICALADDRESSES_H_ #define CONFIG_DEVICES_LOGICALADDRESSES_H_ -#include #include +#include "../objects/systemObjectList.h" #include /** diff --git a/defaultcfg/config/devices/powerSwitcherList.cpp b/defaultcfg/fsfwconfig/devices/powerSwitcherList.cpp similarity index 100% rename from defaultcfg/config/devices/powerSwitcherList.cpp rename to defaultcfg/fsfwconfig/devices/powerSwitcherList.cpp diff --git a/defaultcfg/config/devices/powerSwitcherList.h b/defaultcfg/fsfwconfig/devices/powerSwitcherList.h similarity index 100% rename from defaultcfg/config/devices/powerSwitcherList.h rename to defaultcfg/fsfwconfig/devices/powerSwitcherList.h diff --git a/defaultcfg/config/events/subsystemIdRanges.h b/defaultcfg/fsfwconfig/events/subsystemIdRanges.h similarity index 100% rename from defaultcfg/config/events/subsystemIdRanges.h rename to defaultcfg/fsfwconfig/events/subsystemIdRanges.h diff --git a/defaultcfg/config/config.mk b/defaultcfg/fsfwconfig/fsfwconfig.mk similarity index 100% rename from defaultcfg/config/config.mk rename to defaultcfg/fsfwconfig/fsfwconfig.mk diff --git a/defaultcfg/config/ipc/missionMessageTypes.cpp b/defaultcfg/fsfwconfig/ipc/missionMessageTypes.cpp similarity index 79% rename from defaultcfg/config/ipc/missionMessageTypes.cpp rename to defaultcfg/fsfwconfig/ipc/missionMessageTypes.cpp index e2edbf9c..b41b87ba 100644 --- a/defaultcfg/config/ipc/missionMessageTypes.cpp +++ b/defaultcfg/fsfwconfig/ipc/missionMessageTypes.cpp @@ -1,4 +1,5 @@ -#include +#include "missionMessageTypes.h" + #include void messagetypes::clearMissionMessage(CommandMessage* message) { diff --git a/defaultcfg/config/ipc/missionMessageTypes.h b/defaultcfg/fsfwconfig/ipc/missionMessageTypes.h similarity index 100% rename from defaultcfg/config/ipc/missionMessageTypes.h rename to defaultcfg/fsfwconfig/ipc/missionMessageTypes.h diff --git a/defaultcfg/config/objects/Factory.cpp b/defaultcfg/fsfwconfig/objects/Factory.cpp similarity index 75% rename from defaultcfg/config/objects/Factory.cpp rename to defaultcfg/fsfwconfig/objects/Factory.cpp index 51dd6130..41333b1c 100644 --- a/defaultcfg/config/objects/Factory.cpp +++ b/defaultcfg/fsfwconfig/objects/Factory.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -31,15 +32,15 @@ void Factory::produce(void) { setStaticFrameworkObjectIds(); new EventManager(objects::EVENT_MANAGER); new HealthTable(objects::HEALTH_TABLE); - //new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER); + new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER); } void Factory::setStaticFrameworkObjectIds() { - PusServiceBase::packetSource = objects::PUS_PACKET_DISTRIBUTOR; - PusServiceBase::packetDestination = objects::TM_FUNNEL; + PusServiceBase::packetSource = objects::NO_OBJECT; + PusServiceBase::packetDestination = objects::NO_OBJECT; - CommandingServiceBase::defaultPacketSource = objects::PUS_PACKET_DISTRIBUTOR; - CommandingServiceBase::defaultPacketDestination = objects::TM_FUNNEL; + CommandingServiceBase::defaultPacketSource = objects::NO_OBJECT; + CommandingServiceBase::defaultPacketDestination = objects::NO_OBJECT; VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION; @@ -48,7 +49,6 @@ void Factory::setStaticFrameworkObjectIds() { DeviceHandlerFailureIsolation::powerConfirmationId = objects::NO_OBJECT; - TmPacketStored::timeStamperId = objects::PUS_TIME; - //TmFunnel::downlinkDestination = objects::NO_OBJECT; + TmPacketStored::timeStamperId = objects::NO_OBJECT; } diff --git a/defaultcfg/config/objects/Factory.h b/defaultcfg/fsfwconfig/objects/Factory.h similarity index 100% rename from defaultcfg/config/objects/Factory.h rename to defaultcfg/fsfwconfig/objects/Factory.h diff --git a/defaultcfg/config/objects/systemObjectList.h b/defaultcfg/fsfwconfig/objects/systemObjectList.h similarity index 100% rename from defaultcfg/config/objects/systemObjectList.h rename to defaultcfg/fsfwconfig/objects/systemObjectList.h diff --git a/defaultcfg/fsfwconfig/objects/translateObjects.cpp b/defaultcfg/fsfwconfig/objects/translateObjects.cpp new file mode 100644 index 00000000..73cd02bf --- /dev/null +++ b/defaultcfg/fsfwconfig/objects/translateObjects.cpp @@ -0,0 +1,271 @@ +/** + * @brief Auto-generated object translation file. Contains 86 translations. + * Generated on: 2020-08-25 00:57:14 + **/ +#include "translateObjects.h" + +const char *AT91_UART2_TEST_TASK_STRING = "AT91_UART2_TEST_TASK"; +const char *ARDUINO_0_STRING = "ARDUINO_0"; +const char *ARDUINO_1_STRING = "ARDUINO_1"; +const char *ARDUINO_2_STRING = "ARDUINO_2"; +const char *ARDUINO_3_STRING = "ARDUINO_3"; +const char *ARDUINO_4_STRING = "ARDUINO_4"; +const char *AT91_I2C_TEST_TASK_STRING = "AT91_I2C_TEST_TASK"; +const char *LED_TASK_STRING = "LED_TASK"; +const char *TEST_TASK_STRING = "TEST_TASK"; +const char *PCDU_HANDLER_STRING = "PCDU_HANDLER"; +const char *DUMMY_HANDLER_STRING = "DUMMY_HANDLER"; +const char *SuS_ADC1_DEC2_STRING = "SuS_ADC1_DEC2"; +const char *GPS0_HANDLER_STRING = "GPS0_HANDLER"; +const char *DLR_PVCH_STRING = "DLR_PVCH"; +const char *GYRO1_STRING = "GYRO1"; +const char *DLR_IRAS_STRING = "DLR_IRAS"; +const char *SPI_Test_PT1000_STRING = "SPI_Test_PT1000"; +const char *PT1000_Syrlinks_DEC1_O1_STRING = "PT1000_Syrlinks_DEC1_O1"; +const char *PT1000_Camera_DEC1_O2_STRING = "PT1000_Camera_DEC1_O2"; +const char *PT1000_SuS1_DEC1_O3_STRING = "PT1000_SuS1_DEC1_O3"; +const char *PT1000_SuS2_DEC1_O4_STRING = "PT1000_SuS2_DEC1_O4"; +const char *PT1000_SuS3_DEC1_O5_STRING = "PT1000_SuS3_DEC1_O5"; +const char *PT1000_PVHC_DEC1_O6_STRING = "PT1000_PVHC_DEC1_O6"; +const char *SPI_Test_Gyro_STRING = "SPI_Test_Gyro"; +const char *PT1000_CCSDS1_DEC2_STRING = "PT1000_CCSDS1_DEC2"; +const char *PT1000_MGT1_DEC2_STRING = "PT1000_MGT1_DEC2"; +const char *PT1000_SuS4_DEC2_STRING = "PT1000_SuS4_DEC2"; +const char *PT1000_SuS5_DEC2_STRING = "PT1000_SuS5_DEC2"; +const char *PT1000_SuS6_DEC2_STRING = "PT1000_SuS6_DEC2"; +const char *PT1000_PVCH_DEC2_STRING = "PT1000_PVCH_DEC2"; +const char *PT1000_Iridium_DEC3_STRING = "PT1000_Iridium_DEC3"; +const char *PT1000_CCSDS2_DEC3_STRING = "PT1000_CCSDS2_DEC3"; +const char *PT1000_SuS7_DEC3_STRING = "PT1000_SuS7_DEC3"; +const char *PT1000_SuS8_DEC3_STRING = "PT1000_SuS8_DEC3"; +const char *PT1000_PVCH_DEC3_STRING = "PT1000_PVCH_DEC3"; +const char *GYRO2_STRING = "GYRO2"; +const char *PT1000_PLOC_DEC4_STRING = "PT1000_PLOC_DEC4"; +const char *PT1000_SuS9_DEC4_STRING = "PT1000_SuS9_DEC4"; +const char *PT1000_SuS10_DEC4_STRING = "PT1000_SuS10_DEC4"; +const char *PT1000_PVHC_DEC4_STRING = "PT1000_PVHC_DEC4"; +const char *SuS_ADC_DEC4_STRING = "SuS_ADC_DEC4"; +const char *GPS1_HANDLER_STRING = "GPS1_HANDLER"; +const char *DUMMY_GPS_COM_IF_STRING = "DUMMY_GPS_COM_IF"; +const char *RS232_DEVICE_COM_IF_STRING = "RS232_DEVICE_COM_IF"; +const char *I2C_DEVICE_COM_IF_STRING = "I2C_DEVICE_COM_IF"; +const char *GPIO_DEVICE_COM_IF_STRING = "GPIO_DEVICE_COM_IF"; +const char *SPI_POLLING_TASK_STRING = "SPI_POLLING_TASK"; +const char *SPI_DEVICE_COM_IF_STRING = "SPI_DEVICE_COM_IF"; +const char *DUMMY_ECHO_COM_IF_STRING = "DUMMY_ECHO_COM_IF"; +const char *SD_CARD_HANDLER_STRING = "SD_CARD_HANDLER"; +const char *CCSDS_PACKET_DISTRIBUTOR_STRING = "CCSDS_PACKET_DISTRIBUTOR"; +const char *PUS_PACKET_DISTRIBUTOR_STRING = "PUS_PACKET_DISTRIBUTOR"; +const char *UDP_TMTC_BRIDGE_STRING = "UDP_TMTC_BRIDGE"; +const char *EMAC_POLLING_TASK_STRING = "EMAC_POLLING_TASK"; +const char *SERIAL_TMTC_BRIDGE_STRING = "SERIAL_TMTC_BRIDGE"; +const char *SERIAL_RING_BUFFER_STRING = "SERIAL_RING_BUFFER"; +const char *SERIAL_POLLING_TASK_STRING = "SERIAL_POLLING_TASK"; +const char *PUS_SERVICE_1_STRING = "PUS_SERVICE_1"; +const char *PUS_SERVICE_2_STRING = "PUS_SERVICE_2"; +const char *PUS_SERVICE_3_STRING = "PUS_SERVICE_3"; +const char *PUS_SERVICE_3_PSB_STRING = "PUS_SERVICE_3_PSB"; +const char *PUS_SERVICE_5_STRING = "PUS_SERVICE_5"; +const char *PUS_SERVICE_6_STRING = "PUS_SERVICE_6"; +const char *PUS_SERVICE_8_STRING = "PUS_SERVICE_8"; +const char *PUS_SERVICE_9_STRING = "PUS_SERVICE_9"; +const char *PUS_SERVICE_17_STRING = "PUS_SERVICE_17"; +const char *PUS_SERVICE_20_STRING = "PUS_SERVICE_20"; +const char *PUS_SERVICE_23_STRING = "PUS_SERVICE_23"; +const char *PUS_SERVICE_200_STRING = "PUS_SERVICE_200"; +const char *PUS_SERVICE_201_STRING = "PUS_SERVICE_201"; +const char *PUS_TIME_STRING = "PUS_TIME"; +const char *PUS_FUNNEL_STRING = "PUS_FUNNEL"; +const char *FREERTOS_TASK_MONITOR_STRING = "FREERTOS_TASK_MONITOR"; +const char *HEALTH_TABLE_STRING = "HEALTH_TABLE"; +const char *MODE_STORE_STRING = "MODE_STORE"; +const char *EVENT_MANAGER_STRING = "EVENT_MANAGER"; +const char *INTERNAL_ERROR_REPORTER_STRING = "INTERNAL_ERROR_REPORTER"; +const char *TC_STORE_STRING = "TC_STORE"; +const char *TM_STORE_STRING = "TM_STORE"; +const char *IPC_STORE_STRING = "IPC_STORE"; +const char *AT91_SPI_TEST_TASK_STRING = "AT91_SPI_TEST_TASK"; +const char *STM32_TEST_TASK_STRING = "STM32_TEST_TASK"; +const char *AT91_UART0_TEST_TASK_STRING = "AT91_UART0_TEST_TASK"; +const char *TC_INJECTOR_STRING = "TC_INJECTOR"; +const char *NO_OBJECT_STRING = "NO_OBJECT"; + +const char* translateObject(object_id_t object){ + switch((object&0xFFFFFFFF)){ + case 0x000123336: + return AT91_UART2_TEST_TASK_STRING; + case 0x01010100: + return ARDUINO_0_STRING; + case 0x01010101: + return ARDUINO_1_STRING; + case 0x01010102: + return ARDUINO_2_STRING; + case 0x01010103: + return ARDUINO_3_STRING; + case 0x01010104: + return ARDUINO_4_STRING; + case 0x12345678: + return AT91_I2C_TEST_TASK_STRING; + case 0x12345777: + return LED_TASK_STRING; + case 0x42694269: + return TEST_TASK_STRING; + case 0x44003200: + return PCDU_HANDLER_STRING; + case 0x4400AFFE: + return DUMMY_HANDLER_STRING; + case 0x44020108: + return SuS_ADC1_DEC2_STRING; + case 0x44101F00: + return GPS0_HANDLER_STRING; + case 0x44104000: + return DLR_PVCH_STRING; + case 0x44105000: + return GYRO1_STRING; + case 0x44106000: + return DLR_IRAS_STRING; + case 0x44115400: + return SPI_Test_PT1000_STRING; + case 0x44115401: + return PT1000_Syrlinks_DEC1_O1_STRING; + case 0x44115402: + return PT1000_Camera_DEC1_O2_STRING; + case 0x44115404: + return PT1000_SuS1_DEC1_O3_STRING; + case 0x44115405: + return PT1000_SuS2_DEC1_O4_STRING; + case 0x44115406: + return PT1000_SuS3_DEC1_O5_STRING; + case 0x44115407: + return PT1000_PVHC_DEC1_O6_STRING; + case 0x44115500: + return SPI_Test_Gyro_STRING; + case 0x44125401: + return PT1000_CCSDS1_DEC2_STRING; + case 0x44125403: + return PT1000_MGT1_DEC2_STRING; + case 0x44125404: + return PT1000_SuS4_DEC2_STRING; + case 0x44125405: + return PT1000_SuS5_DEC2_STRING; + case 0x44125406: + return PT1000_SuS6_DEC2_STRING; + case 0x44125407: + return PT1000_PVCH_DEC2_STRING; + case 0x44130301: + return PT1000_Iridium_DEC3_STRING; + case 0x44130302: + return PT1000_CCSDS2_DEC3_STRING; + case 0x44130305: + return PT1000_SuS7_DEC3_STRING; + case 0x44130306: + return PT1000_SuS8_DEC3_STRING; + case 0x44130307: + return PT1000_PVCH_DEC3_STRING; + case 0x44130308: + return GYRO2_STRING; + case 0x44145401: + return PT1000_PLOC_DEC4_STRING; + case 0x44145404: + return PT1000_SuS9_DEC4_STRING; + case 0x44145405: + return PT1000_SuS10_DEC4_STRING; + case 0x44145406: + return PT1000_PVHC_DEC4_STRING; + case 0x44145407: + return SuS_ADC_DEC4_STRING; + case 0x44202000: + return GPS1_HANDLER_STRING; + case 0x49001F00: + return DUMMY_GPS_COM_IF_STRING; + case 0x49005200: + return RS232_DEVICE_COM_IF_STRING; + case 0x49005300: + return I2C_DEVICE_COM_IF_STRING; + case 0x49005400: + return GPIO_DEVICE_COM_IF_STRING; + case 0x49005410: + return SPI_POLLING_TASK_STRING; + case 0x49005600: + return SPI_DEVICE_COM_IF_STRING; + case 0x4900AFFE: + return DUMMY_ECHO_COM_IF_STRING; + case 0x4D0073AD: + return SD_CARD_HANDLER_STRING; + case 0x50000100: + return CCSDS_PACKET_DISTRIBUTOR_STRING; + case 0x50000200: + return PUS_PACKET_DISTRIBUTOR_STRING; + case 0x50000300: + return UDP_TMTC_BRIDGE_STRING; + case 0x50000400: + return EMAC_POLLING_TASK_STRING; + case 0x50000500: + return SERIAL_TMTC_BRIDGE_STRING; + case 0x50000550: + return SERIAL_RING_BUFFER_STRING; + case 0x50000600: + return SERIAL_POLLING_TASK_STRING; + case 0x51000100: + return PUS_SERVICE_1_STRING; + case 0x51000200: + return PUS_SERVICE_2_STRING; + case 0x51000300: + return PUS_SERVICE_3_STRING; + case 0x51000310: + return PUS_SERVICE_3_PSB_STRING; + case 0x51000400: + return PUS_SERVICE_5_STRING; + case 0x51000500: + return PUS_SERVICE_6_STRING; + case 0x51000800: + return PUS_SERVICE_8_STRING; + case 0x51000900: + return PUS_SERVICE_9_STRING; + case 0x51001700: + return PUS_SERVICE_17_STRING; + case 0x51002000: + return PUS_SERVICE_20_STRING; + case 0x51002300: + return PUS_SERVICE_23_STRING; + case 0x51020000: + return PUS_SERVICE_200_STRING; + case 0x51020100: + return PUS_SERVICE_201_STRING; + case 0x52000001: + return PUS_TIME_STRING; + case 0x52000002: + return PUS_FUNNEL_STRING; + case 0x53000000: + return PUS_SERVICE_1_STRING; + case 0x53000003: + return FREERTOS_TASK_MONITOR_STRING; + case 0x53010000: + return HEALTH_TABLE_STRING; + case 0x53010100: + return MODE_STORE_STRING; + case 0x53030000: + return EVENT_MANAGER_STRING; + case 0x53040000: + return INTERNAL_ERROR_REPORTER_STRING; + case 0x534f0100: + return TC_STORE_STRING; + case 0x534f0200: + return TM_STORE_STRING; + case 0x534f0300: + return IPC_STORE_STRING; + case 0x66666666: + return AT91_SPI_TEST_TASK_STRING; + case 0x77777777: + return STM32_TEST_TASK_STRING; + case 0x87654321: + return AT91_UART0_TEST_TASK_STRING; + case 0x99000001: + return TC_INJECTOR_STRING; + case 0xFFFFFFFF: + return NO_OBJECT_STRING; + default: + return "UNKNOWN_OBJECT"; + } + return 0; +} diff --git a/defaultcfg/fsfwconfig/objects/translateObjects.h b/defaultcfg/fsfwconfig/objects/translateObjects.h new file mode 100644 index 00000000..5b656940 --- /dev/null +++ b/defaultcfg/fsfwconfig/objects/translateObjects.h @@ -0,0 +1,9 @@ +#ifndef CONFIG_OBJECTS_TRANSLATEOBJECTS_H_ +#define CONFIG_OBJECTS_TRANSLATEOBJECTS_H_ + +#include + +const char* translateObject(object_id_t object); + + +#endif /* CONFIG_OBJECTS_TRANSLATEOBJECTS_H_ */ diff --git a/defaultcfg/config/pollingsequence/PollingSequenceFactory.cpp b/defaultcfg/fsfwconfig/pollingsequence/PollingSequenceFactory.cpp similarity index 100% rename from defaultcfg/config/pollingsequence/PollingSequenceFactory.cpp rename to defaultcfg/fsfwconfig/pollingsequence/PollingSequenceFactory.cpp diff --git a/defaultcfg/config/pollingsequence/PollingSequenceFactory.h b/defaultcfg/fsfwconfig/pollingsequence/PollingSequenceFactory.h similarity index 100% rename from defaultcfg/config/pollingsequence/PollingSequenceFactory.h rename to defaultcfg/fsfwconfig/pollingsequence/PollingSequenceFactory.h diff --git a/defaultcfg/config/returnvalues/classIds.h b/defaultcfg/fsfwconfig/returnvalues/classIds.h similarity index 100% rename from defaultcfg/config/returnvalues/classIds.h rename to defaultcfg/fsfwconfig/returnvalues/classIds.h diff --git a/defaultcfg/config/tmtc/apid.h b/defaultcfg/fsfwconfig/tmtc/apid.h similarity index 100% rename from defaultcfg/config/tmtc/apid.h rename to defaultcfg/fsfwconfig/tmtc/apid.h diff --git a/defaultcfg/config/tmtc/pusIds.h b/defaultcfg/fsfwconfig/tmtc/pusIds.h similarity index 100% rename from defaultcfg/config/tmtc/pusIds.h rename to defaultcfg/fsfwconfig/tmtc/pusIds.h From 136f04a5c6ce99b15a6f2c9d9c8c7eb409dafd43 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 9 Nov 2020 21:23:51 +0100 Subject: [PATCH 10/23] trnaslation files removed --- .../fsfwconfig/objects/translateObjects.cpp | 271 ------------------ .../fsfwconfig/objects/translateObjects.h | 9 - 2 files changed, 280 deletions(-) delete mode 100644 defaultcfg/fsfwconfig/objects/translateObjects.cpp delete mode 100644 defaultcfg/fsfwconfig/objects/translateObjects.h diff --git a/defaultcfg/fsfwconfig/objects/translateObjects.cpp b/defaultcfg/fsfwconfig/objects/translateObjects.cpp deleted file mode 100644 index 73cd02bf..00000000 --- a/defaultcfg/fsfwconfig/objects/translateObjects.cpp +++ /dev/null @@ -1,271 +0,0 @@ -/** - * @brief Auto-generated object translation file. Contains 86 translations. - * Generated on: 2020-08-25 00:57:14 - **/ -#include "translateObjects.h" - -const char *AT91_UART2_TEST_TASK_STRING = "AT91_UART2_TEST_TASK"; -const char *ARDUINO_0_STRING = "ARDUINO_0"; -const char *ARDUINO_1_STRING = "ARDUINO_1"; -const char *ARDUINO_2_STRING = "ARDUINO_2"; -const char *ARDUINO_3_STRING = "ARDUINO_3"; -const char *ARDUINO_4_STRING = "ARDUINO_4"; -const char *AT91_I2C_TEST_TASK_STRING = "AT91_I2C_TEST_TASK"; -const char *LED_TASK_STRING = "LED_TASK"; -const char *TEST_TASK_STRING = "TEST_TASK"; -const char *PCDU_HANDLER_STRING = "PCDU_HANDLER"; -const char *DUMMY_HANDLER_STRING = "DUMMY_HANDLER"; -const char *SuS_ADC1_DEC2_STRING = "SuS_ADC1_DEC2"; -const char *GPS0_HANDLER_STRING = "GPS0_HANDLER"; -const char *DLR_PVCH_STRING = "DLR_PVCH"; -const char *GYRO1_STRING = "GYRO1"; -const char *DLR_IRAS_STRING = "DLR_IRAS"; -const char *SPI_Test_PT1000_STRING = "SPI_Test_PT1000"; -const char *PT1000_Syrlinks_DEC1_O1_STRING = "PT1000_Syrlinks_DEC1_O1"; -const char *PT1000_Camera_DEC1_O2_STRING = "PT1000_Camera_DEC1_O2"; -const char *PT1000_SuS1_DEC1_O3_STRING = "PT1000_SuS1_DEC1_O3"; -const char *PT1000_SuS2_DEC1_O4_STRING = "PT1000_SuS2_DEC1_O4"; -const char *PT1000_SuS3_DEC1_O5_STRING = "PT1000_SuS3_DEC1_O5"; -const char *PT1000_PVHC_DEC1_O6_STRING = "PT1000_PVHC_DEC1_O6"; -const char *SPI_Test_Gyro_STRING = "SPI_Test_Gyro"; -const char *PT1000_CCSDS1_DEC2_STRING = "PT1000_CCSDS1_DEC2"; -const char *PT1000_MGT1_DEC2_STRING = "PT1000_MGT1_DEC2"; -const char *PT1000_SuS4_DEC2_STRING = "PT1000_SuS4_DEC2"; -const char *PT1000_SuS5_DEC2_STRING = "PT1000_SuS5_DEC2"; -const char *PT1000_SuS6_DEC2_STRING = "PT1000_SuS6_DEC2"; -const char *PT1000_PVCH_DEC2_STRING = "PT1000_PVCH_DEC2"; -const char *PT1000_Iridium_DEC3_STRING = "PT1000_Iridium_DEC3"; -const char *PT1000_CCSDS2_DEC3_STRING = "PT1000_CCSDS2_DEC3"; -const char *PT1000_SuS7_DEC3_STRING = "PT1000_SuS7_DEC3"; -const char *PT1000_SuS8_DEC3_STRING = "PT1000_SuS8_DEC3"; -const char *PT1000_PVCH_DEC3_STRING = "PT1000_PVCH_DEC3"; -const char *GYRO2_STRING = "GYRO2"; -const char *PT1000_PLOC_DEC4_STRING = "PT1000_PLOC_DEC4"; -const char *PT1000_SuS9_DEC4_STRING = "PT1000_SuS9_DEC4"; -const char *PT1000_SuS10_DEC4_STRING = "PT1000_SuS10_DEC4"; -const char *PT1000_PVHC_DEC4_STRING = "PT1000_PVHC_DEC4"; -const char *SuS_ADC_DEC4_STRING = "SuS_ADC_DEC4"; -const char *GPS1_HANDLER_STRING = "GPS1_HANDLER"; -const char *DUMMY_GPS_COM_IF_STRING = "DUMMY_GPS_COM_IF"; -const char *RS232_DEVICE_COM_IF_STRING = "RS232_DEVICE_COM_IF"; -const char *I2C_DEVICE_COM_IF_STRING = "I2C_DEVICE_COM_IF"; -const char *GPIO_DEVICE_COM_IF_STRING = "GPIO_DEVICE_COM_IF"; -const char *SPI_POLLING_TASK_STRING = "SPI_POLLING_TASK"; -const char *SPI_DEVICE_COM_IF_STRING = "SPI_DEVICE_COM_IF"; -const char *DUMMY_ECHO_COM_IF_STRING = "DUMMY_ECHO_COM_IF"; -const char *SD_CARD_HANDLER_STRING = "SD_CARD_HANDLER"; -const char *CCSDS_PACKET_DISTRIBUTOR_STRING = "CCSDS_PACKET_DISTRIBUTOR"; -const char *PUS_PACKET_DISTRIBUTOR_STRING = "PUS_PACKET_DISTRIBUTOR"; -const char *UDP_TMTC_BRIDGE_STRING = "UDP_TMTC_BRIDGE"; -const char *EMAC_POLLING_TASK_STRING = "EMAC_POLLING_TASK"; -const char *SERIAL_TMTC_BRIDGE_STRING = "SERIAL_TMTC_BRIDGE"; -const char *SERIAL_RING_BUFFER_STRING = "SERIAL_RING_BUFFER"; -const char *SERIAL_POLLING_TASK_STRING = "SERIAL_POLLING_TASK"; -const char *PUS_SERVICE_1_STRING = "PUS_SERVICE_1"; -const char *PUS_SERVICE_2_STRING = "PUS_SERVICE_2"; -const char *PUS_SERVICE_3_STRING = "PUS_SERVICE_3"; -const char *PUS_SERVICE_3_PSB_STRING = "PUS_SERVICE_3_PSB"; -const char *PUS_SERVICE_5_STRING = "PUS_SERVICE_5"; -const char *PUS_SERVICE_6_STRING = "PUS_SERVICE_6"; -const char *PUS_SERVICE_8_STRING = "PUS_SERVICE_8"; -const char *PUS_SERVICE_9_STRING = "PUS_SERVICE_9"; -const char *PUS_SERVICE_17_STRING = "PUS_SERVICE_17"; -const char *PUS_SERVICE_20_STRING = "PUS_SERVICE_20"; -const char *PUS_SERVICE_23_STRING = "PUS_SERVICE_23"; -const char *PUS_SERVICE_200_STRING = "PUS_SERVICE_200"; -const char *PUS_SERVICE_201_STRING = "PUS_SERVICE_201"; -const char *PUS_TIME_STRING = "PUS_TIME"; -const char *PUS_FUNNEL_STRING = "PUS_FUNNEL"; -const char *FREERTOS_TASK_MONITOR_STRING = "FREERTOS_TASK_MONITOR"; -const char *HEALTH_TABLE_STRING = "HEALTH_TABLE"; -const char *MODE_STORE_STRING = "MODE_STORE"; -const char *EVENT_MANAGER_STRING = "EVENT_MANAGER"; -const char *INTERNAL_ERROR_REPORTER_STRING = "INTERNAL_ERROR_REPORTER"; -const char *TC_STORE_STRING = "TC_STORE"; -const char *TM_STORE_STRING = "TM_STORE"; -const char *IPC_STORE_STRING = "IPC_STORE"; -const char *AT91_SPI_TEST_TASK_STRING = "AT91_SPI_TEST_TASK"; -const char *STM32_TEST_TASK_STRING = "STM32_TEST_TASK"; -const char *AT91_UART0_TEST_TASK_STRING = "AT91_UART0_TEST_TASK"; -const char *TC_INJECTOR_STRING = "TC_INJECTOR"; -const char *NO_OBJECT_STRING = "NO_OBJECT"; - -const char* translateObject(object_id_t object){ - switch((object&0xFFFFFFFF)){ - case 0x000123336: - return AT91_UART2_TEST_TASK_STRING; - case 0x01010100: - return ARDUINO_0_STRING; - case 0x01010101: - return ARDUINO_1_STRING; - case 0x01010102: - return ARDUINO_2_STRING; - case 0x01010103: - return ARDUINO_3_STRING; - case 0x01010104: - return ARDUINO_4_STRING; - case 0x12345678: - return AT91_I2C_TEST_TASK_STRING; - case 0x12345777: - return LED_TASK_STRING; - case 0x42694269: - return TEST_TASK_STRING; - case 0x44003200: - return PCDU_HANDLER_STRING; - case 0x4400AFFE: - return DUMMY_HANDLER_STRING; - case 0x44020108: - return SuS_ADC1_DEC2_STRING; - case 0x44101F00: - return GPS0_HANDLER_STRING; - case 0x44104000: - return DLR_PVCH_STRING; - case 0x44105000: - return GYRO1_STRING; - case 0x44106000: - return DLR_IRAS_STRING; - case 0x44115400: - return SPI_Test_PT1000_STRING; - case 0x44115401: - return PT1000_Syrlinks_DEC1_O1_STRING; - case 0x44115402: - return PT1000_Camera_DEC1_O2_STRING; - case 0x44115404: - return PT1000_SuS1_DEC1_O3_STRING; - case 0x44115405: - return PT1000_SuS2_DEC1_O4_STRING; - case 0x44115406: - return PT1000_SuS3_DEC1_O5_STRING; - case 0x44115407: - return PT1000_PVHC_DEC1_O6_STRING; - case 0x44115500: - return SPI_Test_Gyro_STRING; - case 0x44125401: - return PT1000_CCSDS1_DEC2_STRING; - case 0x44125403: - return PT1000_MGT1_DEC2_STRING; - case 0x44125404: - return PT1000_SuS4_DEC2_STRING; - case 0x44125405: - return PT1000_SuS5_DEC2_STRING; - case 0x44125406: - return PT1000_SuS6_DEC2_STRING; - case 0x44125407: - return PT1000_PVCH_DEC2_STRING; - case 0x44130301: - return PT1000_Iridium_DEC3_STRING; - case 0x44130302: - return PT1000_CCSDS2_DEC3_STRING; - case 0x44130305: - return PT1000_SuS7_DEC3_STRING; - case 0x44130306: - return PT1000_SuS8_DEC3_STRING; - case 0x44130307: - return PT1000_PVCH_DEC3_STRING; - case 0x44130308: - return GYRO2_STRING; - case 0x44145401: - return PT1000_PLOC_DEC4_STRING; - case 0x44145404: - return PT1000_SuS9_DEC4_STRING; - case 0x44145405: - return PT1000_SuS10_DEC4_STRING; - case 0x44145406: - return PT1000_PVHC_DEC4_STRING; - case 0x44145407: - return SuS_ADC_DEC4_STRING; - case 0x44202000: - return GPS1_HANDLER_STRING; - case 0x49001F00: - return DUMMY_GPS_COM_IF_STRING; - case 0x49005200: - return RS232_DEVICE_COM_IF_STRING; - case 0x49005300: - return I2C_DEVICE_COM_IF_STRING; - case 0x49005400: - return GPIO_DEVICE_COM_IF_STRING; - case 0x49005410: - return SPI_POLLING_TASK_STRING; - case 0x49005600: - return SPI_DEVICE_COM_IF_STRING; - case 0x4900AFFE: - return DUMMY_ECHO_COM_IF_STRING; - case 0x4D0073AD: - return SD_CARD_HANDLER_STRING; - case 0x50000100: - return CCSDS_PACKET_DISTRIBUTOR_STRING; - case 0x50000200: - return PUS_PACKET_DISTRIBUTOR_STRING; - case 0x50000300: - return UDP_TMTC_BRIDGE_STRING; - case 0x50000400: - return EMAC_POLLING_TASK_STRING; - case 0x50000500: - return SERIAL_TMTC_BRIDGE_STRING; - case 0x50000550: - return SERIAL_RING_BUFFER_STRING; - case 0x50000600: - return SERIAL_POLLING_TASK_STRING; - case 0x51000100: - return PUS_SERVICE_1_STRING; - case 0x51000200: - return PUS_SERVICE_2_STRING; - case 0x51000300: - return PUS_SERVICE_3_STRING; - case 0x51000310: - return PUS_SERVICE_3_PSB_STRING; - case 0x51000400: - return PUS_SERVICE_5_STRING; - case 0x51000500: - return PUS_SERVICE_6_STRING; - case 0x51000800: - return PUS_SERVICE_8_STRING; - case 0x51000900: - return PUS_SERVICE_9_STRING; - case 0x51001700: - return PUS_SERVICE_17_STRING; - case 0x51002000: - return PUS_SERVICE_20_STRING; - case 0x51002300: - return PUS_SERVICE_23_STRING; - case 0x51020000: - return PUS_SERVICE_200_STRING; - case 0x51020100: - return PUS_SERVICE_201_STRING; - case 0x52000001: - return PUS_TIME_STRING; - case 0x52000002: - return PUS_FUNNEL_STRING; - case 0x53000000: - return PUS_SERVICE_1_STRING; - case 0x53000003: - return FREERTOS_TASK_MONITOR_STRING; - case 0x53010000: - return HEALTH_TABLE_STRING; - case 0x53010100: - return MODE_STORE_STRING; - case 0x53030000: - return EVENT_MANAGER_STRING; - case 0x53040000: - return INTERNAL_ERROR_REPORTER_STRING; - case 0x534f0100: - return TC_STORE_STRING; - case 0x534f0200: - return TM_STORE_STRING; - case 0x534f0300: - return IPC_STORE_STRING; - case 0x66666666: - return AT91_SPI_TEST_TASK_STRING; - case 0x77777777: - return STM32_TEST_TASK_STRING; - case 0x87654321: - return AT91_UART0_TEST_TASK_STRING; - case 0x99000001: - return TC_INJECTOR_STRING; - case 0xFFFFFFFF: - return NO_OBJECT_STRING; - default: - return "UNKNOWN_OBJECT"; - } - return 0; -} diff --git a/defaultcfg/fsfwconfig/objects/translateObjects.h b/defaultcfg/fsfwconfig/objects/translateObjects.h deleted file mode 100644 index 5b656940..00000000 --- a/defaultcfg/fsfwconfig/objects/translateObjects.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef CONFIG_OBJECTS_TRANSLATEOBJECTS_H_ -#define CONFIG_OBJECTS_TRANSLATEOBJECTS_H_ - -#include - -const char* translateObject(object_id_t object); - - -#endif /* CONFIG_OBJECTS_TRANSLATEOBJECTS_H_ */ From 520409822e58c07c77bbdc163b232e4ac1c6ed76 Mon Sep 17 00:00:00 2001 From: "Jakob.Meier" Date: Tue, 10 Nov 2020 15:06:51 +0100 Subject: [PATCH 11/23] now all debug output removed --- osal/linux/TcUnixUdpPollingTask.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osal/linux/TcUnixUdpPollingTask.cpp b/osal/linux/TcUnixUdpPollingTask.cpp index 7df56a95..af99ec91 100644 --- a/osal/linux/TcUnixUdpPollingTask.cpp +++ b/osal/linux/TcUnixUdpPollingTask.cpp @@ -45,8 +45,8 @@ ReturnValue_t TcUnixUdpPollingTask::performOperation(uint8_t opCode) { continue; } - sif::debug << "TcSocketPollingTask::performOperation: " << bytesReceived - << " bytes received" << std::endl; +// sif::debug << "TcSocketPollingTask::performOperation: " << bytesReceived +// << " bytes received" << std::endl; ReturnValue_t result = handleSuccessfullTcRead(bytesReceived); if(result != HasReturnvaluesIF::RETURN_FAILED) { From 752601e85f6d3d182c0f7b35e784e3226aa18db4 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Fri, 13 Nov 2020 14:31:30 +0100 Subject: [PATCH 12/23] WIP readme --- README.md | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 149 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fc86fca7..c75af4ee 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,152 @@ Flight Software Framework (FSFW) ====== -I want to be written! +The Flight Software Framework is a C++ Object Oriented Framework for unmanned, +automated systems like Satellites. + +The initial version of the Flight Software Framework was developed during +the Flying Laptop Project by the University of Stuttgart in cooperation +with Airbus Defence and Space GmbH. + +## Intended Use + +The framework is designed for systems which communicate with external devices, perform control loops, receive telecommands and send telemetry, and need to maintain a high level of availability. Therefore, a mode and health system provides control over the states of the software and the controlled devices. In addition, a simple mechanism of event based fault detection, isolation and recovery is implemented as well. + + +## Structure + +The general structure is driven by the usage of interfaces provided by objects. The FSFW uses C++11 as baseline. The intention behind this is that this C++ Standard should be widely available, even with older compilers. +The FSFW uses dynamic allocation during the initialization but provides static containers during runtime. +This simplifies the instantiation of objects and allows the usage of some standard containers. +Dynamic Allocation after initialization is discouraged and different solutions are provided in the FSFW to achieve that. +The fsfw uses Run-time type information. +Exceptions are not allowed. + +### Failure Handling + +Functions should return a defined ReturnValue_t to signal to the caller that something is gone wrong. +Returnvalues must be unique. For this the function HasReturnvaluesIF::makeReturnCode or the Macro MAKE_RETURN can be used. +The CLASS_ID is a unique id for that type of object. See returnvalues/FwClassIds. + +### OSAL +The FSFW provides operation system abstraction layers for Linux, FreeRTOS and RTEMS. A independent OSAL called "host" is currently not finished. This aims to be running on windows as well. +The OSAL provides periodic tasks, message queues, clocks and Semaphores as well as Mutexes. + +### Core Components + +Clock: + * This is a class of static functions that can be used at anytime + * Leap Seconds must be set if any time conversions from UTC to other times is used + +ObjectManager (must be created): + +* The component which handles all references. All SystemObjects register at this component. +* Any SystemObject needs to have a unique ObjectId. Those can be managed like objects::framework_objects. +* A reference to an object can be get by calling the following function. T must be the specific Interface you want to call. +A nullptr check of the returning Pointer must be done. This function is based on Run-time type information. + +``` c++ + template T* ObjectManagerIF::get( object_id_t id ) + +``` +* A typical way to create all objects on startup is a handing a static produce function to the ObjectManager on creation. +By calling objectManager->initialize() the produce function will be called and all SystemObjects will be initialized afterwards. + +Event Manager: + +* Component which allows routing of events +* Other objects can subscribe to specific events, ranges of events or all events of an object. +* Subscriptions can be done during runtime but should be done during initialization +* Amounts of allowed subscriptions must be configured by setting this parameters: + +``` c++ +namespace fsfwconfig { +//! Configure the allocated pool sizes for the event manager. +static constexpr size_t FSFW_EVENTMGMR_MATCHTREE_NODES = 240; +static constexpr size_t FSFW_EVENTMGMT_EVENTIDMATCHERS = 120; +static constexpr size_t FSFW_EVENTMGMR_RANGEMATCHERS = 120; +} +``` + + +Health Table: + +* A component which holds every health state +* Provides a thread safe way to access all health states without the need of message exchanges + +Stores + +* The message based communication can only exchange a few bytes of information inside the message itself. Therefore, additional information can be exchanged with Stores. With this, only the store address must be exchanged in the message. +* Internally, the FSFW uses an IPC Store to exchange data between processes. For incoming TCs a TC Store is used. For outgoing TM a TM store is used. +* All of them should use the Thread Safe Class storagemanager/PoolManager + +Tasks + +* There are two different types of tasks +** The PeriodicTask just executes objects that are of type ExecutableObjectIF in the order of the insertion to the Tasks. +** FixedTimeslotTask executes a list of calls in the order of the given list. This is intended for DeviceHandlers, where polling should be in a defined order. An example can be found in defaultcfg/fsfwconfig/pollingSequence + + +### Static Ids in the framework + +Some parts of the framework use a static routing address for communication. +An example setup of ids can be found in the example config in "defaultcft/fsfwconfig/objects/Factory::setStaticFrameworkObjectIds()". + +### Events + +Events are tied to objects. EventIds can be generated by calling the Macro MAKE_EVENT. This works analog to the returnvalues. +Every object that needs own EventIds has to get a unique SUBSYSTEM_ID. +Every SystemObject can call triggerEvent from the parent class. +Therefore, event messages contain the specific EventId and the objectId of the object that has triggered. + +### Internal Communication + +Components communicate mostly over Message through Queues. +Those queues are created by calling the singleton QueueFactory::instance()->create(). + +### External Communication + +The external communication with the mission control system is mostly up to the user implementation. +The FSFW provides PUS Services which can be used to but don't need to be used. +The services can be seen as a conversion from a TC to a message based communication and back. + +#### CCSDS Frames, CCSDS Space Packets and PUS + +If the communication is based on CCSDS Frames and Space Packets, several classes can be used to distributed the packets to the corresponding services. Those can be found in tcdistribution. +If Space Packets are used, a timestamper must be created. +An example can be found in the timemanager folder, this uses CCSDSTime::CDS_short. + +#### DeviceHandling + +DeviceHandlers are a core component of the FSFW. +The idea is, to have a software counterpart of every physical device to provide a simple mode, health and commanding interface. +By separating the underlying Communication Interface with DeviceCommunicationIF, a DH can be tested on different hardware. +The DH has mechanisms to monitor the communication with the physical device which allow for FDIR reaction. +A standard FDIR component for the DH will be created automatically but can be overwritten by the user. + +#### Modes, Health + +The two interfaces HasModesIF and HasHealthIF provide access for commanding and monitoring of components. +On-board Modemangement is implement in hierarchy system. +DeviceHandlers and Controllers are the lowest part of the hierarchy. +The next layer are Assemblies. Those assemblies act as a component which handle redunandcies of handlers. +Assemblies share a common core with the next level which are the Subsystems. +Those are intended to act as auto-generated components from a database which describes the subsystem modes. +The definitions contain transition and target tables which contain the DH, Assembly and Controller Modes to be commanded. +Transition tables contain as many steps as needed to reach the mode from any other mode, e.g. a switch into any higher AOCS mode might first turn on the sensors, than the actuators and the controller as last component. +The target table is used to describe the state that is check continuously by the subsystem. +All of this allows System Modes to be generated as Subsystem object as well from the same database. +This System contains list of subsystem modes in the transition and target tables. +Therefore, it allows a modular system to create system modes and easy commanding of those, because only the highest components must be command. +The health state represents if the component is able to perform its tasks. +This can be used to signal the system to avoid using this component instead of a redundant one. +The on-board FDIR uses the health state for isolation and recovery. + +## Example config + +A example config can be found in defaultcfg/fsfwconfig. + +## Unit Tests + +Unit Tests are provided in the unittest folder. Those use the catch2 framework but do not include catch2 itself. +See README.md in the unittest Folder. \ No newline at end of file From 8aef4b9b997fbd7f4be929384e4d5695c6796be1 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Fri, 13 Nov 2020 14:36:32 +0100 Subject: [PATCH 13/23] Updated formatting --- README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c75af4ee..91383d48 100644 --- a/README.md +++ b/README.md @@ -82,9 +82,9 @@ Stores Tasks -* There are two different types of tasks -** The PeriodicTask just executes objects that are of type ExecutableObjectIF in the order of the insertion to the Tasks. -** FixedTimeslotTask executes a list of calls in the order of the given list. This is intended for DeviceHandlers, where polling should be in a defined order. An example can be found in defaultcfg/fsfwconfig/pollingSequence +There are two different types of tasks: + * The PeriodicTask just executes objects that are of type ExecutableObjectIF in the order of the insertion to the Tasks. + * FixedTimeslotTask executes a list of calls in the order of the given list. This is intended for DeviceHandlers, where polling should be in a defined order. An example can be found in defaultcfg/fsfwconfig/pollingSequence ### Static Ids in the framework @@ -127,17 +127,19 @@ A standard FDIR component for the DH will be created automatically but can be ov #### Modes, Health The two interfaces HasModesIF and HasHealthIF provide access for commanding and monitoring of components. -On-board Modemangement is implement in hierarchy system. +On-board Mode Management is implement in hierarchy system. DeviceHandlers and Controllers are the lowest part of the hierarchy. The next layer are Assemblies. Those assemblies act as a component which handle redunandcies of handlers. Assemblies share a common core with the next level which are the Subsystems. -Those are intended to act as auto-generated components from a database which describes the subsystem modes. + +Those Assemblies are intended to act as auto-generated components from a database which describes the subsystem modes. The definitions contain transition and target tables which contain the DH, Assembly and Controller Modes to be commanded. Transition tables contain as many steps as needed to reach the mode from any other mode, e.g. a switch into any higher AOCS mode might first turn on the sensors, than the actuators and the controller as last component. The target table is used to describe the state that is check continuously by the subsystem. All of this allows System Modes to be generated as Subsystem object as well from the same database. This System contains list of subsystem modes in the transition and target tables. Therefore, it allows a modular system to create system modes and easy commanding of those, because only the highest components must be command. + The health state represents if the component is able to perform its tasks. This can be used to signal the system to avoid using this component instead of a redundant one. The on-board FDIR uses the health state for isolation and recovery. From 51443d7a68afc4fed57bc236a47815eec313c534 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Fri, 13 Nov 2020 15:09:00 +0100 Subject: [PATCH 14/23] Version number --- FSFWVersion.h | 3 ++- README.md | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/FSFWVersion.h b/FSFWVersion.h index dcb592dc..11a60891 100644 --- a/FSFWVersion.h +++ b/FSFWVersion.h @@ -1,10 +1,11 @@ #ifndef FSFW_DEFAULTCFG_VERSION_H_ #define FSFW_DEFAULTCFG_VERSION_H_ -const char* const FSFW_VERSION_NAME = "fsfw"; +const char* const FSFW_VERSION_NAME = "ASTP"; #define FSFW_VERSION 0 #define FSFW_SUBVERSION 0 +#define FSFW_REVISION 1 diff --git a/README.md b/README.md index 91383d48..13f7b95d 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ with Airbus Defence and Space GmbH. ## Intended Use -The framework is designed for systems which communicate with external devices, perform control loops, receive telecommands and send telemetry, and need to maintain a high level of availability. Therefore, a mode and health system provides control over the states of the software and the controlled devices. In addition, a simple mechanism of event based fault detection, isolation and recovery is implemented as well. +The framework is designed for systems, which communicate with external devices, perform control loops, receive telecommands and send telemetry, and need to maintain a high level of availability. Therefore, a mode and health system provides control over the states of the software and the controlled devices. In addition, a simple mechanism of event based fault detection, isolation and recovery is implemented as well. ## Structure From 5b5f2f3e1d40b3109821ff334483e8a02701a963 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Tue, 17 Nov 2020 09:42:38 +0100 Subject: [PATCH 15/23] Added hardware recommendations --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 13f7b95d..b4db3c19 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,12 @@ with Airbus Defence and Space GmbH. ## Intended Use -The framework is designed for systems, which communicate with external devices, perform control loops, receive telecommands and send telemetry, and need to maintain a high level of availability. Therefore, a mode and health system provides control over the states of the software and the controlled devices. In addition, a simple mechanism of event based fault detection, isolation and recovery is implemented as well. +The framework is designed for systems, which communicate with external devices, perform control loops, receive telecommands and send telemetry, and need to maintain a high level of availability. +Therefore, a mode and health system provides control over the states of the software and the controlled devices. +In addition, a simple mechanism of event based fault detection, isolation and recovery is implemented as well. + +The recommended hardware is a microprocessor with more than 2 MB of RAM and 1 MB of non-volatile Memory. +For reference, current Applications use a Cobham Gaisler UT699 (LEON3FT), a ISISPACE IOBC or a Zync 7000 SoC. ## Structure From 273ddf9061c53e5ab73a7ce39443b81773fef57b Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Tue, 17 Nov 2020 19:25:57 +0100 Subject: [PATCH 16/23] Rtems compiles again fixes #176 --- events/Event.h | 2 +- osal/rtems/Clock.cpp | 18 +++---- osal/rtems/CpuUsage.cpp | 2 +- osal/rtems/InternalErrorCodes.cpp | 4 +- osal/rtems/Interrupt.cpp | 86 ------------------------------- osal/rtems/Interrupt.h | 50 ------------------ osal/rtems/MessageQueue.cpp | 27 +++++----- osal/rtems/MessageQueue.h | 14 ++--- osal/rtems/MultiObjectTask.cpp | 4 +- osal/rtems/Mutex.cpp | 11 ++-- osal/rtems/PollingTask.cpp | 21 ++++---- osal/rtems/PollingTask.h | 2 +- osal/rtems/QueueFactory.cpp | 5 +- osal/rtems/TaskBase.cpp | 2 +- timemanager/Clock.h | 2 +- 15 files changed, 57 insertions(+), 193 deletions(-) delete mode 100644 osal/rtems/Interrupt.cpp delete mode 100644 osal/rtems/Interrupt.h diff --git a/events/Event.h b/events/Event.h index f8410f32..aba156f2 100644 --- a/events/Event.h +++ b/events/Event.h @@ -4,7 +4,7 @@ #include #include "fwSubsystemIdRanges.h" //could be move to more suitable location -#include +#include typedef uint16_t EventId_t; typedef uint8_t EventSeverity_t; diff --git a/osal/rtems/Clock.cpp b/osal/rtems/Clock.cpp index eeffd7f3..9460fd2d 100644 --- a/osal/rtems/Clock.cpp +++ b/osal/rtems/Clock.cpp @@ -157,30 +157,24 @@ ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) { if(checkOrCreateClockMutex()!=HasReturnvaluesIF::RETURN_OK){ return HasReturnvaluesIF::RETURN_FAILED; } - ReturnValue_t result = timeMutex->lockMutex(MutexIF::NO_TIMEOUT); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } + MutexHelper helper(timeMutex); + leapSeconds = leapSeconds_; - result = timeMutex->unlockMutex(); - return result; + + return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) { if(timeMutex==NULL){ return HasReturnvaluesIF::RETURN_FAILED; } - ReturnValue_t result = timeMutex->lockMutex(MutexIF::NO_TIMEOUT); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } + MutexHelper helper(timeMutex); *leapSeconds_ = leapSeconds; - result = timeMutex->unlockMutex(); - return result; + return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t Clock::checkOrCreateClockMutex(){ diff --git a/osal/rtems/CpuUsage.cpp b/osal/rtems/CpuUsage.cpp index d49de4ad..6655c69b 100644 --- a/osal/rtems/CpuUsage.cpp +++ b/osal/rtems/CpuUsage.cpp @@ -158,7 +158,7 @@ uint32_t CpuUsage::ThreadData::getSerializedSize() const { } ReturnValue_t CpuUsage::ThreadData::deSerialize(const uint8_t** buffer, - int32_t* size, Endianness streamEndianness) { + size_t* size, Endianness streamEndianness) { ReturnValue_t result = SerializeAdapter::deSerialize(&id, buffer, size, streamEndianness); if (result != HasReturnvaluesIF::RETURN_OK) { diff --git a/osal/rtems/InternalErrorCodes.cpp b/osal/rtems/InternalErrorCodes.cpp index 9346cf15..ddf365d5 100644 --- a/osal/rtems/InternalErrorCodes.cpp +++ b/osal/rtems/InternalErrorCodes.cpp @@ -12,8 +12,8 @@ ReturnValue_t InternalErrorCodes::translate(uint8_t code) { // return INVALID_WORKSPACE_ADDRESS; case INTERNAL_ERROR_TOO_LITTLE_WORKSPACE: return TOO_LITTLE_WORKSPACE; - case INTERNAL_ERROR_WORKSPACE_ALLOCATION: - return WORKSPACE_ALLOCATION; +// case INTERNAL_ERROR_WORKSPACE_ALLOCATION: +// return WORKSPACE_ALLOCATION; // case INTERNAL_ERROR_INTERRUPT_STACK_TOO_SMALL: // return INTERRUPT_STACK_TOO_SMALL; case INTERNAL_ERROR_THREAD_EXITTED: diff --git a/osal/rtems/Interrupt.cpp b/osal/rtems/Interrupt.cpp deleted file mode 100644 index b740f1ca..00000000 --- a/osal/rtems/Interrupt.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "Interrupt.h" -extern "C" { -#include -#include -} -#include "RtemsBasic.h" - - -ReturnValue_t Interrupt::enableInterrupt(InterruptNumber_t interruptNumber) { - volatile uint32_t* irqMask = hw_irq_mask; - uint32_t expectedValue = *irqMask | (1 << interruptNumber); - *irqMask = expectedValue; - uint32_t tempValue = *irqMask; - if (tempValue == expectedValue) { - return HasReturnvaluesIF::RETURN_OK; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } -} - -ReturnValue_t Interrupt::setInterruptServiceRoutine(IsrHandler_t handler, - InterruptNumber_t interrupt, IsrHandler_t* oldHandler) { - IsrHandler_t oldHandler_local; - if (oldHandler == NULL) { - oldHandler = &oldHandler_local; - } - //+ 0x10 comes because of trap type assignment to IRQs in UT699 processor - rtems_status_code status = rtems_interrupt_catch(handler, interrupt + 0x10, - oldHandler); - switch(status){ - case RTEMS_SUCCESSFUL: - //ISR established successfully - return HasReturnvaluesIF::RETURN_OK; - case RTEMS_INVALID_NUMBER: - //illegal vector number - return HasReturnvaluesIF::RETURN_FAILED; - case RTEMS_INVALID_ADDRESS: - //illegal ISR entry point or invalid old_isr_handler - return HasReturnvaluesIF::RETURN_FAILED; - default: - return HasReturnvaluesIF::RETURN_FAILED; - } - -} - -ReturnValue_t Interrupt::disableInterrupt(InterruptNumber_t interruptNumber) { - //TODO Not implemented - return HasReturnvaluesIF::RETURN_FAILED; -} - -//SHOULDDO: Make default values (edge, polarity) settable? -ReturnValue_t Interrupt::enableGpioInterrupt(InterruptNumber_t interrupt) { - volatile uint32_t* irqMask = hw_irq_mask; - uint32_t expectedValue = *irqMask | (1 << interrupt); - *irqMask = expectedValue; - uint32_t tempValue = *irqMask; - if (tempValue == expectedValue) { - volatile hw_gpio_port_t* ioPorts = hw_gpio_port; - ioPorts->direction &= ~(1 << interrupt); //Direction In - ioPorts->interrupt_edge |= 1 << interrupt; //Edge triggered - ioPorts->interrupt_polarity |= 1 << interrupt; //Trigger on rising edge - ioPorts->interrupt_mask |= 1 << interrupt; //Enable - return HasReturnvaluesIF::RETURN_OK; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } -} - -ReturnValue_t Interrupt::disableGpioInterrupt(InterruptNumber_t interrupt) { - volatile uint32_t* irqMask = hw_irq_mask; - uint32_t expectedValue = *irqMask & ~(1 << interrupt); - *irqMask = expectedValue; - uint32_t tempValue = *irqMask; - if (tempValue == expectedValue) { - //Disable gpio IRQ - volatile hw_gpio_port_t* ioPorts = hw_gpio_port; - ioPorts->interrupt_mask &= ~(1 << interrupt); - return HasReturnvaluesIF::RETURN_OK; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } -} - -bool Interrupt::isInterruptInProgress() { - return rtems_interrupt_is_in_progress(); -} diff --git a/osal/rtems/Interrupt.h b/osal/rtems/Interrupt.h deleted file mode 100644 index 2152e2f0..00000000 --- a/osal/rtems/Interrupt.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef OS_RTEMS_INTERRUPT_H_ -#define OS_RTEMS_INTERRUPT_H_ - -#include "../../returnvalues/HasReturnvaluesIF.h" -#include -#include - -typedef rtems_isr_entry IsrHandler_t; -typedef rtems_isr IsrReturn_t; -typedef rtems_vector_number InterruptNumber_t; - -class Interrupt { -public: - virtual ~Interrupt(){}; - - /** - * Establishes a new interrupt service routine. - * @param handler The service routine to establish - * @param interrupt The interrupt (NOT trap type) the routine shall react to. - * @return RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t setInterruptServiceRoutine(IsrHandler_t handler, - InterruptNumber_t interrupt, IsrHandler_t *oldHandler = NULL); - static ReturnValue_t enableInterrupt(InterruptNumber_t interruptNumber); - static ReturnValue_t disableInterrupt(InterruptNumber_t interruptNumber); - /** - * Enables the interrupt given. - * The function tests, if the InterruptMask register was written successfully. - * @param interrupt The interrupt to enable. - * @return RETURN_OK if the interrupt was set successfully. RETURN_FAILED else. - */ - static ReturnValue_t enableGpioInterrupt(InterruptNumber_t interrupt); - /** - * Disables the interrupt given. - * @param interrupt The interrupt to disable. - * @return RETURN_OK if the interrupt was set successfully. RETURN_FAILED else. - */ - static ReturnValue_t disableGpioInterrupt(InterruptNumber_t interrupt); - - - /** - * Checks if the current executing context is an ISR. - * @return true if handling an interrupt, false else. - */ - static bool isInterruptInProgress(); - -}; - - -#endif /* OS_RTEMS_INTERRUPT_H_ */ diff --git a/osal/rtems/MessageQueue.cpp b/osal/rtems/MessageQueue.cpp index 700db444..bc7e864d 100644 --- a/osal/rtems/MessageQueue.cpp +++ b/osal/rtems/MessageQueue.cpp @@ -1,4 +1,5 @@ #include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../objectmanager/ObjectManagerIF.h" #include "MessageQueue.h" #include "RtemsBasic.h" #include @@ -8,7 +9,7 @@ MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size) : rtems_status_code status = rtems_message_queue_create(name, message_depth, max_message_size, 0, &(this->id)); if (status != RTEMS_SUCCESSFUL) { - error << "MessageQueue::MessageQueue: Creating Queue " << std::hex + sif::error << "MessageQueue::MessageQueue: Creating Queue " << std::hex << name << std::dec << " failed with status:" << (uint32_t) status << std::endl; this->id = 0; @@ -20,15 +21,15 @@ MessageQueue::~MessageQueue() { } ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, bool ignoreFault) { + MessageQueueMessageIF* message, bool ignoreFault) { return sendMessageFrom(sendTo, message, this->getId(), ignoreFault); } -ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message) { +ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) { return sendToDefaultFrom(message, this->getId()); } -ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) { +ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) { if (this->lastPartner != 0) { return sendMessage(this->lastPartner, message, this->getId()); } else { @@ -36,27 +37,29 @@ ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) { } } -ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message, +ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message, MessageQueueId_t* receivedFrom) { ReturnValue_t status = this->receiveMessage(message); *receivedFrom = this->lastPartner; return status; } -ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) { +ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) { + size_t size = 0; rtems_status_code status = rtems_message_queue_receive(id, - message->getBuffer(), &(message->messageSize), + message->getBuffer(),&size, RTEMS_NO_WAIT, 1); if (status == RTEMS_SUCCESSFUL) { + message->setMessageSize(size); this->lastPartner = message->getSender(); //Check size of incoming message. - if (message->messageSize < message->getMinimumMessageSize()) { + if (message->getMessageSize() < message->getMinimumMessageSize()) { return HasReturnvaluesIF::RETURN_FAILED; } } else { //No message was received. Keep lastPartner anyway, I might send something later. //But still, delete packet content. - memset(message->getData(), 0, message->MAX_DATA_SIZE); + memset(message->getData(), 0, message->getMaximumMessageSize()); } return convertReturnCode(status); } @@ -79,12 +82,12 @@ void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) { } ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, - MessageQueueMessage* message, MessageQueueId_t sentFrom, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, bool ignoreFault) { message->setSender(sentFrom); rtems_status_code result = rtems_message_queue_send(sendTo, - message->getBuffer(), message->messageSize); + message->getBuffer(), message->getMessageSize()); //TODO: Check if we're in ISR. if (result != RTEMS_SUCCESSFUL && !ignoreFault) { @@ -105,7 +108,7 @@ ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, return returnCode; } -ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessage* message, +ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message, MessageQueueId_t sentFrom, bool ignoreFault) { return sendMessageFrom(defaultDestination, message, sentFrom, ignoreFault); } diff --git a/osal/rtems/MessageQueue.h b/osal/rtems/MessageQueue.h index c6fc62d5..78a1e5ca 100644 --- a/osal/rtems/MessageQueue.h +++ b/osal/rtems/MessageQueue.h @@ -60,14 +60,14 @@ public: * @param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. */ ReturnValue_t sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, bool ignoreFault = false ); + MessageQueueMessageIF* message, bool ignoreFault = false ); /** * @brief This operation sends a message to the default destination. * @details As in the sendMessage method, this function uses the sendToDefault call of the * MessageQueueSender parent class and adds its queue id as "sentFrom" information. * @param message A pointer to a previously created message, which is sent. */ - ReturnValue_t sendToDefault( MessageQueueMessage* message ); + 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 @@ -75,7 +75,7 @@ public: * (i.e. lastPartner is zero), an error code is returned. * @param message A pointer to a previously created message, which is sent. */ - ReturnValue_t reply( MessageQueueMessage* message ); + ReturnValue_t reply( MessageQueueMessageIF* message ); /** * @brief This function reads available messages from the message queue and returns the sender. @@ -84,7 +84,7 @@ public: * @param message A pointer to a message in which the received data is stored. * @param receivedFrom A pointer to a queue id in which the sender's id is stored. */ - ReturnValue_t receiveMessage(MessageQueueMessage* message, + ReturnValue_t receiveMessage(MessageQueueMessageIF* message, MessageQueueId_t *receivedFrom); /** @@ -95,7 +95,7 @@ public: * message's content is cleared and the function returns immediately. * @param message A pointer to a message in which the received data is stored. */ - ReturnValue_t receiveMessage(MessageQueueMessage* message); + ReturnValue_t receiveMessage(MessageQueueMessageIF* message); /** * Deletes all pending messages in the queue. * @param count The number of flushed messages. @@ -121,7 +121,7 @@ public: * This variable is set to zero by default. * \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. */ - virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ); + virtual 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. @@ -129,7 +129,7 @@ public: * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. * This variable is set to zero by default. */ - virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ); + virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ); /** * \brief This method is a simple setter for the default destination. */ diff --git a/osal/rtems/MultiObjectTask.cpp b/osal/rtems/MultiObjectTask.cpp index 2342c24c..a239d9cb 100644 --- a/osal/rtems/MultiObjectTask.cpp +++ b/osal/rtems/MultiObjectTask.cpp @@ -30,7 +30,7 @@ ReturnValue_t MultiObjectTask::startTask() { rtems_status_code status = rtems_task_start(id, MultiObjectTask::taskEntryPoint, rtems_task_argument((void *) this)); if (status != RTEMS_SUCCESSFUL) { - error << "ObjectTask::startTask for " << std::hex << this->getId() + sif::error << "ObjectTask::startTask for " << std::hex << this->getId() << std::dec << " failed." << std::endl; } switch(status){ @@ -63,7 +63,7 @@ void MultiObjectTask::taskFunctionality() { char nameSpace[8] = { 0 }; char* ptr = rtems_object_get_name(getId(), sizeof(nameSpace), nameSpace); - error << "ObjectTask: " << ptr << " Deadline missed." << std::endl; + sif::error << "ObjectTask: " << ptr << " Deadline missed." << std::endl; if (this->deadlineMissedFunc != NULL) { this->deadlineMissedFunc(); } diff --git a/osal/rtems/Mutex.cpp b/osal/rtems/Mutex.cpp index 9553ac79..a5ec9635 100644 --- a/osal/rtems/Mutex.cpp +++ b/osal/rtems/Mutex.cpp @@ -10,7 +10,7 @@ Mutex::Mutex() : RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY, 0, &mutexId); if (status != RTEMS_SUCCESSFUL) { - error << "Mutex: creation with name, id " << mutexName << ", " << mutexId + sif::error << "Mutex: creation with name, id " << mutexName << ", " << mutexId << " failed with " << status << std::endl; } } @@ -18,24 +18,25 @@ Mutex::Mutex() : Mutex::~Mutex() { rtems_status_code status = rtems_semaphore_delete(mutexId); if (status != RTEMS_SUCCESSFUL) { - error << "Mutex: deletion for id " << mutexId + sif::error << "Mutex: deletion for id " << mutexId << " failed with " << status << std::endl; } } ReturnValue_t Mutex::lockMutex(TimeoutType timeoutType = TimeoutType::BLOCKING, uint32_t timeoutMs) { + rtems_status_code status = RTEMS_INVALID_ID; if(timeoutMs == MutexIF::TimeoutType::BLOCKING) { - rtems_status_code status = rtems_semaphore_obtain(mutexId, + status = rtems_semaphore_obtain(mutexId, RTEMS_WAIT, RTEMS_NO_TIMEOUT); } else if(timeoutMs == MutexIF::TimeoutType::POLLING) { timeoutMs = RTEMS_NO_TIMEOUT; - rtems_status_code status = rtems_semaphore_obtain(mutexId, + status = rtems_semaphore_obtain(mutexId, RTEMS_NO_WAIT, 0); } else { - rtems_status_code status = rtems_semaphore_obtain(mutexId, + status = rtems_semaphore_obtain(mutexId, RTEMS_WAIT, timeoutMs); } diff --git a/osal/rtems/PollingTask.cpp b/osal/rtems/PollingTask.cpp index 04191515..1329638d 100644 --- a/osal/rtems/PollingTask.cpp +++ b/osal/rtems/PollingTask.cpp @@ -1,5 +1,6 @@ -#include "../../devicehandlers/FixedSequenceSlot.h" +#include "../../tasks/FixedSequenceSlot.h" #include "../../objectmanager/SystemObjectIF.h" +#include "../../objectmanager/ObjectManagerIF.h" #include "PollingTask.h" #include "RtemsBasic.h" #include "../../returnvalues/HasReturnvaluesIF.h" @@ -34,14 +35,14 @@ rtems_task PollingTask::taskEntryPoint(rtems_task_argument argument) { PollingTask *originalTask(reinterpret_cast(argument)); //The task's functionality is called. originalTask->taskFunctionality(); - debug << "Polling task " << originalTask->getId() + sif::debug << "Polling task " << originalTask->getId() << " returned from taskFunctionality." << std::endl; } void PollingTask::missedDeadlineCounter() { PollingTask::deadlineMissedCount++; if (PollingTask::deadlineMissedCount % 10 == 0) { - error << "PST missed " << PollingTask::deadlineMissedCount + sif::error << "PST missed " << PollingTask::deadlineMissedCount << " deadlines." << std::endl; } } @@ -50,7 +51,7 @@ ReturnValue_t PollingTask::startTask() { rtems_status_code status = rtems_task_start(id, PollingTask::taskEntryPoint, rtems_task_argument((void *) this)); if (status != RTEMS_SUCCESSFUL) { - error << "PollingTask::startTask for " << std::hex << this->getId() + sif::error << "PollingTask::startTask for " << std::hex << this->getId() << std::dec << " failed." << std::endl; } switch(status){ @@ -68,12 +69,13 @@ ReturnValue_t PollingTask::startTask() { ReturnValue_t PollingTask::addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep) { - if (objectManager->get(componentId) != nullptr) { - pst.addSlot(componentId, slotTimeMs, executionStep, this); + ExecutableObjectIF* object = objectManager->get(componentId); + if (object != nullptr) { + pst.addSlot(componentId, slotTimeMs, executionStep, object, this); return HasReturnvaluesIF::RETURN_OK; } - error << "Component " << std::hex << componentId << + sif::error << "Component " << std::hex << componentId << " not found, not adding it to pst" << std::endl; return HasReturnvaluesIF::RETURN_FAILED; } @@ -90,11 +92,10 @@ ReturnValue_t PollingTask::checkSequence() const { void PollingTask::taskFunctionality() { // A local iterator for the Polling Sequence Table is created to find the start time for the first entry. - std::list::iterator it = pst.current; + FixedSlotSequence::SlotListIter it = pst.current; //The start time for the first entry is read. - rtems_interval interval = RtemsBasic::convertMsToTicks( - (*it)->pollingTimeMs); + rtems_interval interval = RtemsBasic::convertMsToTicks(it->pollingTimeMs); TaskBase::setAndStartPeriod(interval,&periodId); //The task's "infinite" inner loop is entered. while (1) { diff --git a/osal/rtems/PollingTask.h b/osal/rtems/PollingTask.h index 199c34e7..5656e354 100644 --- a/osal/rtems/PollingTask.h +++ b/osal/rtems/PollingTask.h @@ -1,7 +1,7 @@ #ifndef POLLINGTASK_H_ #define POLLINGTASK_H_ -#include "../../devicehandlers/FixedSlotSequence.h" +#include "../../tasks/FixedSlotSequence.h" #include "../../tasks/FixedTimeslotTaskIF.h" #include "TaskBase.h" diff --git a/osal/rtems/QueueFactory.cpp b/osal/rtems/QueueFactory.cpp index fce55a0e..b35e7a39 100644 --- a/osal/rtems/QueueFactory.cpp +++ b/osal/rtems/QueueFactory.cpp @@ -1,4 +1,5 @@ #include "../../ipc/QueueFactory.h" +#include "../../ipc/MessageQueueSenderIF.h" #include "MessageQueue.h" #include "RtemsBasic.h" @@ -6,11 +7,11 @@ QueueFactory* QueueFactory::factoryInstance = NULL; ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, MessageQueueId_t sentFrom,bool ignoreFault) { + MessageQueueMessageIF* message, MessageQueueId_t sentFrom,bool ignoreFault) { //TODO add ignoreFault functionality message->setSender(sentFrom); rtems_status_code result = rtems_message_queue_send(sendTo, message->getBuffer(), - message->messageSize); + message->getMessageSize()); switch(result){ case RTEMS_SUCCESSFUL: //message sent successfully diff --git a/osal/rtems/TaskBase.cpp b/osal/rtems/TaskBase.cpp index adf6ee70..4e0c8f00 100644 --- a/osal/rtems/TaskBase.cpp +++ b/osal/rtems/TaskBase.cpp @@ -22,7 +22,7 @@ TaskBase::TaskBase(rtems_task_priority set_priority, size_t stack_size, } ReturnValue_t result = convertReturnCode(status); if (result != HasReturnvaluesIF::RETURN_OK) { - error << "TaskBase::TaskBase: createTask with name " << std::hex + sif::error << "TaskBase::TaskBase: createTask with name " << std::hex << osalName << std::dec << " failed with return code " << (uint32_t) status << std::endl; this->id = 0; diff --git a/timemanager/Clock.h b/timemanager/Clock.h index acb68e2e..bc112388 100644 --- a/timemanager/Clock.h +++ b/timemanager/Clock.h @@ -2,7 +2,7 @@ #define FRAMEWORK_TIMEMANAGER_CLOCK_H_ #include "../returnvalues/HasReturnvaluesIF.h" -#include "../ipc/MutexFactory.h" +#include "../ipc/MutexHelper.h" #include "../globalfunctions/timevalOperations.h" #include From 6489246c4b52d57b0a1fce6368787adea0115128 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Tue, 17 Nov 2020 19:35:37 +0100 Subject: [PATCH 17/23] Updated include guards --- osal/rtems/Clock.cpp | 14 +++++++------- osal/rtems/MessageQueue.cpp | 6 +++--- osal/rtems/MessageQueue.h | 15 +++------------ osal/rtems/MultiObjectTask.cpp | 4 ++-- osal/rtems/MultiObjectTask.h | 2 +- osal/rtems/Mutex.h | 6 +++--- osal/rtems/MutexFactory.cpp | 1 - osal/rtems/PollingTask.cpp | 2 +- osal/rtems/PollingTask.h | 6 +++--- osal/rtems/QueueFactory.cpp | 4 ++-- osal/rtems/RtemsBasic.h | 6 +++--- osal/rtems/TaskBase.h | 6 +++--- 12 files changed, 31 insertions(+), 41 deletions(-) diff --git a/osal/rtems/Clock.cpp b/osal/rtems/Clock.cpp index 9460fd2d..e5f37ec6 100644 --- a/osal/rtems/Clock.cpp +++ b/osal/rtems/Clock.cpp @@ -3,7 +3,7 @@ #include uint16_t Clock::leapSeconds = 0; -MutexIF* Clock::timeMutex = NULL; +MutexIF* Clock::timeMutex = nullptr; uint32_t Clock::getTicksPerSecond(void){ rtems_interval ticks_per_second = rtems_clock_get_ticks_per_second(); @@ -40,7 +40,7 @@ ReturnValue_t Clock::setClock(const timeval* time) { //SHOULDDO: Not sure if we need to protect this call somehow (by thread lock or something). //Uli: rtems docu says you can call this from an ISR, not sure if this means no protetion needed //TODO Second parameter is ISR_lock_Context - _TOD_Set(&newTime,NULL); + _TOD_Set(&newTime,nullptr); return HasReturnvaluesIF::RETURN_OK; } @@ -131,7 +131,7 @@ ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) { ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) { //SHOULDDO: works not for dates in the past (might have less leap seconds) - if (timeMutex == NULL) { + if (timeMutex == nullptr) { return HasReturnvaluesIF::RETURN_FAILED; } @@ -167,7 +167,7 @@ ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) { } ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) { - if(timeMutex==NULL){ + if(timeMutex==nullptr){ return HasReturnvaluesIF::RETURN_FAILED; } MutexHelper helper(timeMutex); @@ -178,13 +178,13 @@ ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) { } ReturnValue_t Clock::checkOrCreateClockMutex(){ - if(timeMutex==NULL){ + if(timeMutex==nullptr){ MutexFactory* mutexFactory = MutexFactory::instance(); - if (mutexFactory == NULL) { + if (mutexFactory == nullptr) { return HasReturnvaluesIF::RETURN_FAILED; } timeMutex = mutexFactory->createMutex(); - if (timeMutex == NULL) { + if (timeMutex == nullptr) { return HasReturnvaluesIF::RETURN_FAILED; } } diff --git a/osal/rtems/MessageQueue.cpp b/osal/rtems/MessageQueue.cpp index bc7e864d..839182a6 100644 --- a/osal/rtems/MessageQueue.cpp +++ b/osal/rtems/MessageQueue.cpp @@ -4,7 +4,7 @@ #include "RtemsBasic.h" #include MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size) : - id(0), lastPartner(0), defaultDestination(NO_QUEUE), internalErrorReporter(NULL) { + id(0), lastPartner(0), defaultDestination(NO_QUEUE), 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)); @@ -91,11 +91,11 @@ ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, //TODO: Check if we're in ISR. if (result != RTEMS_SUCCESSFUL && !ignoreFault) { - if (internalErrorReporter == NULL) { + if (internalErrorReporter == nullptr) { internalErrorReporter = objectManager->get( objects::INTERNAL_ERROR_REPORTER); } - if (internalErrorReporter != NULL) { + if (internalErrorReporter != nullptr) { internalErrorReporter->queueMessageNotSent(); } } diff --git a/osal/rtems/MessageQueue.h b/osal/rtems/MessageQueue.h index 78a1e5ca..342f1e30 100644 --- a/osal/rtems/MessageQueue.h +++ b/osal/rtems/MessageQueue.h @@ -1,14 +1,5 @@ -/** - * @file MessageQueue.h - * - * @date 10/02/2012 - * @author Bastian Baetz - * - * @brief This file contains the definition of the MessageQueue class. - */ - -#ifndef MESSAGEQUEUE_H_ -#define MESSAGEQUEUE_H_ +#ifndef FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_ +#define FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_ #include "../../internalError/InternalErrorReporterIF.h" #include "../../ipc/MessageQueueIF.h" @@ -178,4 +169,4 @@ private: static ReturnValue_t convertReturnCode(rtems_status_code inValue); }; -#endif /* MESSAGEQUEUE_H_ */ +#endif /* FSFW_OSAL_RTEMS_MESSAGEQUEUE_H_ */ diff --git a/osal/rtems/MultiObjectTask.cpp b/osal/rtems/MultiObjectTask.cpp index a239d9cb..970d01e1 100644 --- a/osal/rtems/MultiObjectTask.cpp +++ b/osal/rtems/MultiObjectTask.cpp @@ -64,7 +64,7 @@ void MultiObjectTask::taskFunctionality() { char* ptr = rtems_object_get_name(getId(), sizeof(nameSpace), nameSpace); sif::error << "ObjectTask: " << ptr << " Deadline missed." << std::endl; - if (this->deadlineMissedFunc != NULL) { + if (this->deadlineMissedFunc != nullptr) { this->deadlineMissedFunc(); } } @@ -74,7 +74,7 @@ void MultiObjectTask::taskFunctionality() { ReturnValue_t MultiObjectTask::addComponent(object_id_t object) { ExecutableObjectIF* newObject = objectManager->get( object); - if (newObject == NULL) { + if (newObject == nullptr) { return HasReturnvaluesIF::RETURN_FAILED; } objectList.push_back(newObject); diff --git a/osal/rtems/MultiObjectTask.h b/osal/rtems/MultiObjectTask.h index 736e79dd..04d122a3 100644 --- a/osal/rtems/MultiObjectTask.h +++ b/osal/rtems/MultiObjectTask.h @@ -80,7 +80,7 @@ protected: /** * @brief The pointer to the deadline-missed function. * @details This pointer stores the function that is executed if the task's deadline is missed. - * So, each may react individually on a timing failure. The pointer may be NULL, + * So, each may react individually on a timing failure. The pointer may be nullptr, * then nothing happens on missing the deadline. The deadline is equal to the next execution * of the periodic task. */ diff --git a/osal/rtems/Mutex.h b/osal/rtems/Mutex.h index 72368210..4c861318 100644 --- a/osal/rtems/Mutex.h +++ b/osal/rtems/Mutex.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_OSAL_RTEMS_MUTEX_H_ -#define FRAMEWORK_OSAL_RTEMS_MUTEX_H_ +#ifndef FSFW_OSAL_RTEMS_MUTEX_H_ +#define FSFW_OSAL_RTEMS_MUTEX_H_ #include "../../ipc/MutexIF.h" #include "RtemsBasic.h" @@ -15,4 +15,4 @@ private: static uint8_t count; }; -#endif /* OS_RTEMS_MUTEX_H_ */ +#endif /* FSFW_OSAL_RTEMS_MUTEX_H_ */ diff --git a/osal/rtems/MutexFactory.cpp b/osal/rtems/MutexFactory.cpp index ea594789..24af5fa9 100644 --- a/osal/rtems/MutexFactory.cpp +++ b/osal/rtems/MutexFactory.cpp @@ -2,7 +2,6 @@ #include "Mutex.h" #include "RtemsBasic.h" -//TODO: Different variant than the lazy loading in QueueFactory. What's better and why? MutexFactory* MutexFactory::factoryInstance = new MutexFactory(); MutexFactory::MutexFactory() { diff --git a/osal/rtems/PollingTask.cpp b/osal/rtems/PollingTask.cpp index 1329638d..db7864fe 100644 --- a/osal/rtems/PollingTask.cpp +++ b/osal/rtems/PollingTask.cpp @@ -108,7 +108,7 @@ void PollingTask::taskFunctionality() { //If the deadline was missed, the deadlineMissedFunc is called. rtems_status_code status = TaskBase::restartPeriod(interval,periodId); if (status == RTEMS_TIMEOUT) { - if (this->deadlineMissedFunc != NULL) { + if (this->deadlineMissedFunc != nullptr) { this->deadlineMissedFunc(); } } diff --git a/osal/rtems/PollingTask.h b/osal/rtems/PollingTask.h index 5656e354..42deaf09 100644 --- a/osal/rtems/PollingTask.h +++ b/osal/rtems/PollingTask.h @@ -1,5 +1,5 @@ -#ifndef POLLINGTASK_H_ -#define POLLINGTASK_H_ +#ifndef FSFW_OSAL_RTEMS_POLLINGTASK_H_ +#define FSFW_OSAL_RTEMS_POLLINGTASK_H_ #include "../../tasks/FixedSlotSequence.h" #include "../../tasks/FixedTimeslotTaskIF.h" @@ -82,4 +82,4 @@ protected: void taskFunctionality( void ); }; -#endif /* POLLINGTASK_H_ */ +#endif /* FSFW_OSAL_RTEMS_POLLINGTASK_H_ */ diff --git a/osal/rtems/QueueFactory.cpp b/osal/rtems/QueueFactory.cpp index b35e7a39..ff561304 100644 --- a/osal/rtems/QueueFactory.cpp +++ b/osal/rtems/QueueFactory.cpp @@ -3,7 +3,7 @@ #include "MessageQueue.h" #include "RtemsBasic.h" -QueueFactory* QueueFactory::factoryInstance = NULL; +QueueFactory* QueueFactory::factoryInstance = nullptr; ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, @@ -38,7 +38,7 @@ ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, } QueueFactory* QueueFactory::instance() { - if (factoryInstance == NULL) { + if (factoryInstance == nullptr) { factoryInstance = new QueueFactory; } return factoryInstance; diff --git a/osal/rtems/RtemsBasic.h b/osal/rtems/RtemsBasic.h index 78e0d46e..d0ca5aba 100644 --- a/osal/rtems/RtemsBasic.h +++ b/osal/rtems/RtemsBasic.h @@ -1,5 +1,5 @@ -#ifndef OS_RTEMS_RTEMSBASIC_H_ -#define OS_RTEMS_RTEMSBASIC_H_ +#ifndef FSFW_OSAL_RTEMS_RTEMSBASIC_H_ +#define FSFW_OSAL_RTEMS_RTEMSBASIC_H_ #include "../../returnvalues/HasReturnvaluesIF.h" #include @@ -22,4 +22,4 @@ public: } }; -#endif /* OS_RTEMS_RTEMSBASIC_H_ */ +#endif /* FSFW_OSAL_RTEMS_RTEMSBASIC_H_ */ diff --git a/osal/rtems/TaskBase.h b/osal/rtems/TaskBase.h index 410d9110..0e186e67 100644 --- a/osal/rtems/TaskBase.h +++ b/osal/rtems/TaskBase.h @@ -1,5 +1,5 @@ -#ifndef TASKBASE_H_ -#define TASKBASE_H_ +#ifndef FSFW_OSAL_RTEMS_TASKBASE_H_ +#define FSFW_OSAL_RTEMS_TASKBASE_H_ #include "RtemsBasic.h" #include "../../tasks/PeriodicTaskIF.h" @@ -44,4 +44,4 @@ private: }; -#endif /* TASKBASE_H_ */ +#endif /* FSFW_OSAL_RTEMS_TASKBASE_H_ */ From 227ec25e89c9f95e3bb16f1efe856761cdd7dc4e Mon Sep 17 00:00:00 2001 From: "Jakob.Meier" Date: Fri, 27 Nov 2020 11:44:11 +0100 Subject: [PATCH 18/23] some minor corrections in readme --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b4db3c19..52fec27e 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Therefore, a mode and health system provides control over the states of the soft In addition, a simple mechanism of event based fault detection, isolation and recovery is implemented as well. The recommended hardware is a microprocessor with more than 2 MB of RAM and 1 MB of non-volatile Memory. -For reference, current Applications use a Cobham Gaisler UT699 (LEON3FT), a ISISPACE IOBC or a Zync 7000 SoC. +For reference, current Applications use a Cobham Gaisler UT699 (LEON3FT), a ISISPACE IOBC or a Zynq-7020 SoC. ## Structure @@ -134,16 +134,16 @@ A standard FDIR component for the DH will be created automatically but can be ov The two interfaces HasModesIF and HasHealthIF provide access for commanding and monitoring of components. On-board Mode Management is implement in hierarchy system. DeviceHandlers and Controllers are the lowest part of the hierarchy. -The next layer are Assemblies. Those assemblies act as a component which handle redunandcies of handlers. +The next layer are Assemblies. Those assemblies act as a component which handle redundancies of handlers. Assemblies share a common core with the next level which are the Subsystems. Those Assemblies are intended to act as auto-generated components from a database which describes the subsystem modes. The definitions contain transition and target tables which contain the DH, Assembly and Controller Modes to be commanded. Transition tables contain as many steps as needed to reach the mode from any other mode, e.g. a switch into any higher AOCS mode might first turn on the sensors, than the actuators and the controller as last component. -The target table is used to describe the state that is check continuously by the subsystem. +The target table is used to describe the state that is checked continuously by the subsystem. All of this allows System Modes to be generated as Subsystem object as well from the same database. This System contains list of subsystem modes in the transition and target tables. -Therefore, it allows a modular system to create system modes and easy commanding of those, because only the highest components must be command. +Therefore, it allows a modular system to create system modes and easy commanding of those, because only the highest components must be commanded. The health state represents if the component is able to perform its tasks. This can be used to signal the system to avoid using this component instead of a redundant one. From 4241c00448e57c7a05b5ba26248cbb23bc72a4c0 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Mon, 30 Nov 2020 18:30:58 +0100 Subject: [PATCH 19/23] Added the new logos, colors are WIP at the moment --- NOTICE | 2 + README.md | 3 +- logo/FSFW_Logo_V3.png | Bin 0 -> 137423 bytes logo/FSFW_Logo_V3.svg | 711 +++++++++++++++++++++++++++++++++++++++ logo/FSFW_Logo_V3_bw.png | Bin 0 -> 13369 bytes 5 files changed, 715 insertions(+), 1 deletion(-) create mode 100644 logo/FSFW_Logo_V3.png create mode 100644 logo/FSFW_Logo_V3.svg create mode 100644 logo/FSFW_Logo_V3_bw.png diff --git a/NOTICE b/NOTICE index e1663282..be1a37c4 100644 --- a/NOTICE +++ b/NOTICE @@ -4,6 +4,8 @@ The initial version of the Flight Software Framework was developed during the Flying Laptop Project by the Universität Stuttgart in coorporation with Airbus Defence and Space GmbH. +The supreme FSFW Logo was designed by Markus Koller and Luise Trilsbach. + Copyrights in the Flight Software Framework are retained by their contributors. No copyright assignment is required to contribute to the Flight Software Framework. diff --git a/README.md b/README.md index 52fec27e..a59f4ddd 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ -Flight Software Framework (FSFW) +![FSFW Logo](logo/FSFW_Logo_V3_bw.png) +# Flight Software Framework (FSFW) ====== The Flight Software Framework is a C++ Object Oriented Framework for unmanned, diff --git a/logo/FSFW_Logo_V3.png b/logo/FSFW_Logo_V3.png new file mode 100644 index 0000000000000000000000000000000000000000..2ac710dd2069446e8f10108716f4c0e97bc961b9 GIT binary patch literal 137423 zcmYIv1yI!A_ckHYDcy}UOCzN;E1^qwcY}1N^s+Qk(t;pe(%mJ}-AKa%OY>j-&hLGh zVRqSJKlj`d&wWnZs1GXg*cjv(2nYz+iV89y1cVn+2nZ;gXfNTPcqtGP!e3svNhzwM z!GHYF%p>7{qdP0;xFH}Y&HVjE{BhAW0{@WgldSe9H7CnYo+hpq2%esvTsDq&Ze}LV z7F9r0{eMZUDyUYGtPQ?bn>1YWG3Su{O_wqRx+|6r^$lL76+cbcKK z1m;XStlyt#O2}2f6B{ynjDU)YHw_4>d$wX^ ziA2;d5uL_y*v-!?ByY#sg?7H{#6!>@eB#Uw1n%X|KgnUtx3VWJ)OD#i}D zS`$Evc}Gk)etP?KCOUk+_gZ60KdF0=2digaTdbz$5Gz=neffFy-k8|b9G^ahXPmwl zzKb4u9Ga?cs5M$Z)*^ywdI$(udH`@6QV3fC_z~PNR#8+DWsG;@QuV#sBFTF*n!chi zozR01rCK-ccC3tvmJLTnE{>VRCB?NAlbc1>WdvQZJL?P!k|G=hSD}(7#9NeeBEvdh z#Bzo*qcO&YjMHba*J5yOXkgbV6vC~;TdxoeOFNDqI*I|@(;Xq(ll^#NK*_dLa{nEt zYv{095Fl?nN*G2ZMOo_e3Jgy|CHb~!gFZjc$J>!hO+2Z!CS=^iN8;$)E^6 zjuw6F18{53h>~tle-?Zi#;^pf3Ml_&(mP@ zKY@e6)FSW#^GHG63(Q=UT=^mU0w_ox4LLiY$CqBiLpTvtSK z#8L3Y+&lh^L~PYj#cj0IHE%7hU9u}h4vb_qL>-bDh8H;Uy8WRRcECkokgn$*Rug-} zE>o!Wl{KY@(~HW)1Wlvo%HcN}FMfKYu$IenSzz$P%d~qD*BFb9qz`b@Cr#EV6hJHqv%{^s=`h&4Znwz>EYWmWe7*-yNHIR_ybeQ=4tAdhfOQ1&9ixKsQ_tOXq zRP$7yzc)R%4d6TOga&t*CECQLhW&rRQ|89r3$g6vbRP7vgf0mBawMM(vrf>OLVwlq zerevOXmX{QMEkUz!LyM6$HoGQT_ezsBs+aXz2^Ni<+>ZG#6XaSlgsmP<`Dl%zA8`+ z?mS#@M}xmm^X+1XM9{q3RbQkbQeM~bW{0VAMH)rH%yXLUNn(9*vr*{x2WuI0C{PNr zoDBfq>qk;R;-jA8iN+|eD$}M?jk%a+e5hfSt*@q?1;&tx<)5A5<{Zxbr|$*#tq|ou zGtSh5;NbQrZ2$3Ly%za+!UtW%wpd4>5*kYb%*mxjWydbGx-o$zwaehYumE`uvqFbX|)B6N%IH6(;q z(^T%a-SJGP3Zx(ZEmE;ErEH#$sp)Ht9Y2zh7bAAxKGw#O11_kPb_GrXPknSHNJ$@& z|9ZLKKV_sWSHyUl&2R1n86istKZIrv4ge(>Sfc;DDum8;e(RR*4i35VWY) z;%EDkvmyXUE(5e57QbMx_)vgBt4v!$R{?Ey+5u-U`4k1gpFICBe%RW{Muav}!{@es z*1ls7JHRG9^cu3-mH}Xzr8Vz^ z$;L$*KEFA6mIp<@Te__ci*GUgfCv7n4Mc&pNL{RvgEXexmsl9PmD-AC6XCTBn05&; zV!oRQq5bU9Hl;IP{UG9hiCiM=SfOzWQx zh*mDcS?I=N(6-(S;kfKB!!05M7}-Sia&&X^L9__u@Y6NHW#FV_B~o4W=>^X9o&4ml zKxDA0wuF*2d(Lp36KKG_3Viv+0`3JHMOFelpL(x4!8NDu)FU!JZ#APJrhOa$*Zg$! z!oJ|5HB8Bnpihisl3IwXFEmYW5C9Z-I>^5a%Uu7&0F z&OCZ%qk@q~SVwR7cIw01f}&F=Ui4+R;zenO(Ox2E4EdibcajNbSk?l3OyPiWAnTc{ z`d3?V#T|ebURY;M_H^CFj2D_Ly=be-tH@8-mN=W^h`Ut{e>BDwJ_twI^(SKT=)crn zJs=M%aUNB_1K&`LF`M!I1Px1%)JT~7fO}F5f(>|LQ9Y0axozzVtO?)9%+FsCD!1Wm zQDnBKiIKsLQm+sr17AHvIai1>t0QDVq{*aLIeH~z$`ngA#GAk+$NZOIrJ0h&a+uZb zCJP=kqZO9u-lNDVK45DZEUcX?5M(tEF z{J)FH{afT=EL|v4>42s)y%i?yAU>?i?}M5pi4<5YaHSg1s_e~0^q!3qN00LsZJseO z2;EPon~lwRc0sOe$qPL&f;ITpUA6Rm5 z;)Ie&glvpJ2I`katOW-R_y?u4ci$jILO8O(3g(Wc-V{7RWq2d zTiZ4f6sY0{A)P__f-8$7gWgesIP2-05_Qmba6^=3OROlt!??Q3N#9VP7Q?#=v>9x% z8s|ze?CKm4V|TKi4B-yHp9Jp2M+GFXP;=J;idj??S!djszX+~7b*?p;os;oji4&Ts zyby^TM`>Hi`SNo8L=M?ADYX(J=y=%)U&Qvm^KYlc=1GVrOHJ%6^fkjKBCu(Smy{Zb zFR4-fvBCpKbJY0-W;WuBuS71-3BpW8>K4L|+dk`v>xd@?&3yfj)ZOQuUt2w74=2+P zO`p?0*FanL5Yq;5zx}0%`#YBKb$%-43T4GYF(QIxdlJQ!2b}8SIv<5g+0*%59b0LM z?ECZALT}6Vs`ja3pT-IyEi9^V|F1srYvGP7eT9FE&eLk{>zh_=frqpCtxJ^=Js*5wm2bnFQG2s{51`X=NLBnT4iygML>rZi3basEeK)B@SahD z|9|w=iV2O|_WB{&S=Tjf2?9IP(q4r;eWki<5zq2?wi7Il;w@b74wL`RZ4YVUoRE!L zrX|HL)tg`hiXc0M4E(H`p3F2~k{c}cG4SueT+D$_souh@0t2$64ha0@w`BB=b zIG75r`Gq#gyo3`Kflm?0nlNr$quNaqzO`5X;2*=XwSkE~t)E=T9+zQ5bv=G(n`+$h z*ELP=UHQTEQs9TqFeq1NMNLv7sLYlhSEpx6dRmy5dV@P}fW7QhI45~VQj^t=Av*8h zNACRh$VKu>)CG?Ij6JR=mdZ7G;Z!w`8w{4yra@r)48vE2->mE9flqqhE38VA%W&ke z3WpI@r6#gZ1 zWu9Dfn^)Rd`I~aRwx2g}%TFI|n8AkD3}b9F$uKsLHszq$@K4Dgjni+OMnxt)5~SY4 zz}Eb$#2{xf&cqr5Be+#G{;{cim&_epm`w!2L}y`zu=%Q&ZiV5kTaLD_d{rJauR0! zWxzq{i=hMBN9QUsz=X_tmzxDW^2;YrHMbVbgqf80c z+-@248#5I3{ye&gh3`uhw#6ocOayQr5JopTza05y_vJ6=diA@VwiwkU6v5TO_K(|^ zY0+DeP$@BfS3-+8J>SaS)g7tcMG;#luZmhtRAAlN*{8$garH6I%+LS0?>q9y;~nxB z7NY(#s50tDzY`T>38Tw^De=$w2`wTP1D_LFw4_aEmh0{lKy3L15i1c2@At2pS(?eD0+!cm8&(Fz27&KqoH&Cam;Tg7l|W{F8={IBRU|CqD|%9 zx^5_k<9Oipp6oB!A^iorQlG!D*jWu3z&x;E)b9s-8s>;KzsawsDN0tBcc>@Wxaf6> zb`0WNo1xH#1Ks1lD4NLx3;7X|lKMVu8p=7H86HkJ6lv*6sfW}}CxC`ii&LiYR;viu z^*Br^PIS&$*#UoTB=%3zHhdBK=ZlcA^VsHyI*AjBbSLuh@4o(XQkKlYytg!`!Bq0tknuN}dctPCZ(0;*(?5uZ)E&a5B`|wo zR*WLVroX0UTVE>xE58Y=r~E4~$A6l28Pm#-!_($i44U?-4KF`YDn6d*5Y$(4-;lHAwdhzHv^W(`kqB1f zFny-L%6X-d2xNj2I7tm)YisM!Scu3C!#e40E1qG)3xUexCEDCqDPG z#vw&l3a=cneGyd|m6hSawe#yQ>ds)AJTH^nb`VpFB)>`E5$hjnDQ`&DIld6%VL#$3 zoXLGF#Jw1mEP|JgMv3Mi4T!k@Gk+UM3c9JGNe}2$2y0uCMqhtRQ8B82fpI1l!7{}E z7_O*SQ3pk3or%N3rRSx)Upz##_^A2r#{%v@vnfxDtHF1U%4aE5(|&6E)#*=vKXlIT zLYf(zVM13s3~+cV6{aLuetl5!uubb)V!E!`xXpYkVC>!cv4=k~O~mFiUylr13mN8s znG#=jWAIdPv))1ys}7@k*XT>wNBtACUxUqp5*np7Er;1uw6$No-Y%O$ypzo$0z_k_yQLqapc{xj%hTeCz>Pru3Ltg-xI|0K(G%eXXBH`DBKu<;+9_ zfCE=b-(?ugKsnVdBNM4tc}`27Zv(LW=p|Qz(5;HhG)=e*^7A3cH6-b6&Q0kVF-8b` zj=Ie;NsTkq?q#n2R)ZAF^$!+2ExWj9+Qrd(zTCbHraW?|#g)k*0bs6UaWd$t)BHMG z(sg{gelgHs$fn@1mPK|dw4X!FdsIkfXdtIA(uTENxsj7%FjiLW&(cpq^Ot8)&J1_k zjytMs>4LIJ!$;_@$Z;3Ud?ag~mwii2k1|EW0}ma}#~8%a6B=Rmkz!`q`ebWiSY{NK{xQPR7@54qXr*OF!{^fLwhn8h}_++_#{kvb_WlJ>! zYfADUCMmQhot#|B5+Yv2| zjBBssJWgy@BYi6%xr>x$mGhp-Xf!A8%%ZMv=^_dF%%2p&ZM_T%n_D8_Wd}+I;vb1h zQ`|#D;RH3{J$K6exsjbkk@tXIGJS8#$~oxx5XcuGAVCWu>n%~LwkG<1OZH)t9618Nq=HG1{E37 zWXRQ6^(c3JV1yT}q$m@xwws${{7wS)X4aJNJ1gP|zc)xl2uYC(YwiP?FU81dH{X5S z94m}+p(F;hSEM_3$p|zck@R2s;pgmKDz#U~OV~!qLE2%U+stdhAJb3bk0vVvVl~$q z>!-pe9OQRTN!;mRX-2AO;wU!7yNqLJP|0+E6zR{OC0ZlFGW*H&yVN2nq^JatS-N1< zNr2g1FBbx&&R7|9#)yK>V7tB6h%aVTTR+^7;cu}> zh@{RnaaWO4k^FEIq?mJ9htz|Ey%Bt#Q>B&jzjLxx8EI1e+}&wc^51xq^&82U_ru*2 zO3qw7%TI_@)Rb92j<{~vO*M!W0P0rUYeTHU7ZOSsOK;vN+8VGN&7#pm_kB8+b&BnC z2H;>e?WV{#dyMZT1v+En)uzDidv#KGnUqV4(Y0IBJ{pd83UTyug#N+A9T-%KzHS(4 zZpQ^k9d(G)!kht(B^4X*9Q8jOC>XHb$5Y%&aIxou_xapJV}V&oAcPKYPb9OoOzaDu z?wk!djAnY(*7im+KHA6`2UmHXrTgoJGmH7)K}?(5rY`7M`uY2Kat4pWk4O|SBpk$B zf%1E9aCuvz{45SQRf&X?;Hs{4!vBl=;WM)9OBWvxbZU5>mx*q6haKBgVB}hdc5YS# zGA&FGG#rAw3Si24_eSe!c6KHk;1<9UK1MC0ma^vu zd;w{u$G;yp9lMuh=##klfDuHj=(0A}ltrrvI~5JFI6XIKu(aAAH+wk}T>IIE z80HcJrr_x3pd{R0dVFeI{weabJ4_mW$BB4~W?k8{V~hR)%K^5Vx^_EK*A@^0-4k^zF>f zfb+RA#HGX^?^vB33uHa!N~B9qn4S;s#5W#WV!gPxfGNK&W{qW@UdDo387ND=2m5Dd zVTdq5G~pbJ!iIk=yj~e;;5C}?+R|}9WVvE>;M-Q*N%OPK<%Z|#Lrao!xh zSnIWU`_G}!A_-88jQB?4UI{I)K$Y@Fu#7l2T5v(%GC~-zNam=Q0s(xZDaeL$K2nW% z_9m#oBeXTk=!oP!wljSxw$b{Rw2ld#771!e=als8e%i3&qeBG>VlX~siH9$N$c1Px z$2qljlbCzF8hvs420~~BIrzo_0~6TGKaD9fBA@`*7ujlDQ$H8nwhgrFFL~DU_R-mi z(psklw)%w?6V{Y`2}<`*{Cv?Id$u}-X>VPm^UYr7_E*ornBaquOd{3KuWINkOvu66dS37dD?c2xURN%~~}++Nt~T+VqN5r=HGmd>=M zM9OFKFj*iINp(2E0RZJI?(x;sS1wsr53>7ZXtFo7R5ob+EOy=HO8Z2~I9r_CCPBTd z1^03>R?&v!%<|*DLi7q^-tV~6yAEOTBR}%lbmua+Zm0Imm%y$+&0L&jEeuf?ejJXy z7_oo)_S~JW_~3l+EXzw#%)N-&QyH9%ywvyjD%|RJ+%F_>CtYhus1-sS4HDA&F&b>zfD%;G=rRyq|AT1&I=cbd=q6LVdYR1TsuHo!8=c<+m03lK@-j^{(|TqlFq#*x`ytpm(_TDLVjH? zp(*LvlHmhb=$pO~ieApMwa~}wrd=CqoqPAn;GeFiTxpV`gxl0I^mF3WVguax^h!&~J)g^_gPp=1X>6(Enx3t!+Eq#U zWbD6(XFJo7iMC&vy*wh0sR5k7{;xq2l8(NKDs+l^fe@(eX1{^JN#OoDHI=Yp8TAuY zxyF?lGJ__+bRU+jF@t674a8KAlyzzwN+zQDgK1Om)IyzSVu_8CXdHUJdylL=cg-`` zx;!T(mm;h5JjfRrIE}rdP~DJX(_YCR+W16n2z!m5bp^yCgo>+>JuY1^QogGlGQOk4 zZv7%j+sms_76p+$Vk%Qdw-X|k^rC%l-3|TUEWj_1_OIu1RtY;;8l1K|%_L1){i}H# zBH;dcbQRt;y{JDzi7#;DM;Y3W{qI{JDJcM=(j-Ts3usxeMiOei-q_Q7qW*MlhPW@z zIj7`I;pt1>USlxVOgqRo(bo23vd-XO2Y3^(#zi#1o~u4s^sd2FH|M`yux=A+Pu1nWMeLFoIs$TfJNM>CV)hStA3oiSc3M8;r83L zR9Scu8iLlC|I)O>hx&J3IT4y>uo+r_t?qc?4C;XS`&_C$fsLqBgF<3l8FHZRWK8S> zhAZ_~L~W7R+zW#qqmglDG}I`u=0#0gwN6eJjfJ(==6rB)cBN(~X{#dS`yKQG@T&KO zyssIqHu+QC8Sz+46Z%{MhS{C1fN)eKn>q46HGzCp8w_Z-K*#?wd`|+&v z8pl3ABpdGuT>wIhZY5N~QTAV*EWP17cD%0X{&b{UlM%Ibwvgh^tDo$3Bvbft-sjc}y)6Pf$ZWIzS zWBecd4riKy#V7wRiR6^@X313MFst;iYK93|yWqfB9nX96It6tV5^-PQGo5?UI}yyZ zovLF1C-V{6@UL#7j^O9ld0J0`W^$3aUMuRR1&NUpa(!PMGf%Mxu^ja$M=n^dutJ~L z@b5$qtiPpYy4NmKmF0{x1vxtpJfnE`>!S-hbO3YIGqQvaSl7q$VXrC<>lF%r&iFjP z!?)VTf>*kpdT&J%FxGMiP@7y_(fDk8Zy;YjFVn?8vP1|wDlo1$(E-3)FEj10d58N) zv8`A=)~j8+Z&y7pgI-3gXxBQ{5JwH~3AD-R% zA;*b1mh3mJ<+2w|4o?c+`73_`2?o8ppLWLWYmh6N``pJe=Kj+h8IkVsae8rRSgEb0 zyH%O#aVm^$;b#CBOPmfUg7TP0u5Xf-kOkXrE-8;`$j~lLubdM2Mq^>*8=qx&nDhh;eJjF- z))ih)9=3oYS_P45h;^E6)Ra=f8qSs%8c7>3;b#(aES1mym_6Kwtd32N4^N73SJ~X& z{OK#g%bxu1%kFK(luVu9Pl3He1%YmDx0MGf zWNUPJg0GsFTuS3cYEleNojjPUq@OZ30g`?5H@D*je@#&_%+L?6^F|{Ry>9n<>&Jc% zW4d-R?YoRL@>(`FTPrN==)9f)xh)r=?Y=(R6_!;IhH1%W@6xDa7v0m3X;FOTl#QZTH zs8NtBzVaFSv7xu=-gtY&7$;O1RqL1g2SeLiLa2?dE{I>~KG(a#i#ZUw+Ki7T)>%=^ zCR;I>aXoV>&~!O~FDeQ`=M;dKMigi>7iVoVLH_X$a4azml2BJ9s%&(#fBO9(Pxnk=COM& zQF>x1B(<#)UkFoV#&1NUJLwFnlpeVEOB@EtQb~Hcjg3eddcVR39>b@tj>v-seU2IUz9 zZMGcuH|Oo>N;m`j5)qGeeL_~FQKe?{&iZ<9RoyEZyoLXQBKU~!@;XbPhE;xaWl)f~ zhOJT%DoLJ>H_!ZgGx3c=CL;1xJk1({`-{q*^K1%7+8+~v*4p77RcC5m(>#lP?S6&m3;+ zb-UQd?u-%7jsR&gHselKsv zupzMtPuo^?w27L}G60d3WIw9C9tc}U&lrBp`^u8R8P#=`=mzp4=yOQ9%_%;kY>bv) ze5P1e&Te&k6rT^aQq;*F-!Z(jLDZ8DW&kHWwuq+AJVfy%5IG$=aY`1c^GmdRLqtwS z8fZh2`DrLME)>znZ!bLI5e=Lv?-BGTZ4$olYXANT-a{0S`-N6|voyNwG$__n zw|NAxNUlG*nq{YX}pJ7kP&nD(0yZe!n;PJm|{K63%qZH>{DvstQJJ z&+yOwWX9&Oce88)AAeH_pyDY%WbvD_rds0Gw+D3P?0NHQgAsh>Ix}ud+}@?&X?Trl;teLDbWYQwbY~1xA)+4 z-ymDaAO?&8Z@{x#{$Ay&zv%vPTE!4JL)LhHd=}?MtkhxgJH2CaS-%-3SKU{TSxSv~ zNtg@oKrxL+v49N_xAk2uE3_}|irXY4TnLNQ0TVezz&_`R=#OXv3z^~OWfDV5rRiat zTVK=fZ*&=fY>%TS#_h9La&POolmHVhzbuB-N`J09lK5wRrIvHe?AvBDf_F`Rt`X}T z4QVk=uab6E!J9B$J1;(B%1Z@0KhaF@zLb50H@_@OJ1p$(SQ08%SEAr)b}4RG)Xzhzz; z3*`3(X()k-j^6W&vsbg@(~7-nFqukn3UNRY>xzSRd{(Fs!&NCAE@}g65OxH3$|smb zqY`F$VUDD{uOoqg0QCwq>vl{_I~PY9i%${oHPbJC=b#y(HzIMkc*r5Ra93yKfZTT$ z7eeuv5j|8QqV;uNrG05Owvaah6PaS@?j`w2RG<+Y6Z}ySj~!(uZ4NaWeP$7AZI{pI zPXTQti*4!8uya_vXLAEg;w=xF`Jam1r;`XRI&7-gBL2SjTo_BPv9@q6lPp`lmy2pxyb114OsJm|M zJp~S;D3gXVz&`ieBhKKYR@Bt}p$$%DpJh3UQjNm=+McreaA5``PNNB%Ev@y7^fvua zAF`ofQYZq&eMe87Hw@r#0#FJxi>y%9EW6gx{SY3XQ&z^+tR!o10HIfPxtx?-iYij4 zvORJqpRDIjwx#=>>^)6T6u^uE-`97GaiPp~{_Wx{dN zRvmZ9YKU!Ks9 zco{5(#Xuf9-26A>7#+LA{=17q%B4R)0Ve04>>^QknucPsTJBHnnKX4=9bc6H)aj)_ z)f^csYb#`FfVj3Jmt#tT#%b&yolci$eO3@Mt2>7xn{(9LGSK?8U>9xL>hNK0Bxn7U>ei^u7)~3D7}r`%dL50K zWBbyBeSvG438jMnXBvERtMrZgA52j?N*ys;85mZj#qSR^U?Wa8LY)JPLSW>)!|SP? zB=P+L(XpL~Ip)v|G6xyfoBAckpp~JHl8MEo& zyaD@C+~bdIKhzIzja{i1)x5|844n>)yD98fpXZvLY#^`8o$3qUa-H}vbdyirGdngy zRs%m?^d^_7vAU5ZV9YgbXA|b`F0ari=co$|H{(0k6Vltt^`cU%kHFjx=9g}64;gqE zo91M?s46SgMq0N0)&dyp0W8z0_>NgZs5k7a-myxy#7Xi_XO!dMmsD?HuzSNtV~fYB!RbzfZ8Y~Ew|M)cG&RPz%Bxnty=jIIp4cAm%5>V8aqaH8 z`37et!QdIq_pG+qRv&4?VFs7jgl^1a@8qcru#g=MNk6dmj-stTS@ zi4)rm=Tz!E>q3;G>NJZ5>iQ0GB*^~VU_7sh{yFQV%l2--WsZzVmT(Jx(`(-fqZ8Gf z&fw;;;-uC4jvWP!(w_;uX5>MGX%=#ZE*seU)quoHw*4v(W(-C; zUiuCD8h6T#`F?oGdpAj4w0YMtvqa~|t&_0qD>&T8pQ&Vm$w?3n@LF-{yw2&7I^N#9 zB_;n+lkx@RzE=~dj3C0OzQltXAKyGFr+f8I@cPqB0akSv=^!@0vsD{2%gvwn!5n7~ z3>AbP7{s3r-RrYLcQ>1m@%b`hy)$f}IotgxpXtNFXCKSRZMqZ?>5IRUeB6heW!uOE z^m#^1y#JC4avyQ$Li|#mMfqx%$Ex;o>q{HRx8%$3%8??K<}GL9vBfTZt9RcFiZ*#q zh|HZp1bLXjT53H7@OYFQPPLPDhT=LW*(cqY2^5@&W2dj+hyI@60<%qVJrLeY63nrptyfSV?uRi4+mm>UopK*YFBjYWI~{)7Uk7yVJyOVM zi((|WOb;cM5lc`cDbUHBwh_D^MK^rkm#@}ev2p2=gjY*rYIs7v4wYZzI!eB2k~xpT z{Q^U>BA(tA@4l*ZvVu-0mtj#s+sYg`6Or6prtV$lCgdzHR!m|X3X9bZT$hSLpHywY z;ech{H<^{N=YqAjoCGL}69?F?Dw}E$g95{elw6+)+j!ti+WQ{P=sX{?M;elo+t%Y3 z>_%OmqJE7G3d3=wtTU$w-xN*5yIuz}Js{R|mJNHm?X^Dk0}*kgJZ1GQ`tE(zdCbX1 zA05B2Te{%$fDihYGSU#cMzrs?vp=7yka?M%Ezvsy48ag~POER~k6zX@ES-KM9l;X; z$!ol}!Zc=nX}WO97SitkrV%8n^V+`Ur_;Z$-3~?AG`P94{dt^?SAFwr-{r&^fOZpI z3w5%QaB|#AO0OBC2Ry0c_>t%0EtB9XYpm7D&F0}H)81U+*~S6KbwjS+Pw&Sr;kr0& z_ut~WJ#Hcj=Ch^5+K=YKN=IfA*i8D5`7Q&LwHvGRzugKVQEl((2cj+g^+t zz%WD@P4YAAG<#v2==H0$i`N48fF@5o=%lJ(^`%>zDBtWD3iMb+<;7dgV?{aI6Q;l#CcXFn2pH%z4A_4J}q}^DY5_T=hxX z0)Mhp`hAfJJT$CgSG^=_vTSIq>h!NZnaI};Ap{=Y1Rol%;mhN6556;IMnZm+zt-WF zF*FE+cP1qdoB^n&S(0v#hxe{`=}ay)AJ_!x`rCHIxa50+;1%QgVhbIb+2I8^adym< z`LTz}pvg22r>!X)zcwv6j6XA5lMzwxX6lJi?3&fHe9X%oB@c79y~kuPq2b=S^PgqH z&Q~|EwNczi9QWmRuI5-cy-3Sy+@pWLppn-r&beCuMa7^L#wCURXg=zvLL-_z-S3|S z8^G#!zkcDyoc=jDrHjE+9+%US5RRbv)F(ZOUWyX0pR(?1bR9ukYF=u+PdWxk3>MGFY;Av{7$Tn1w7AzYV# z28u2hH`7vi)ykemX}k&L`h9TNy#>F28*Zmwh9^9l%3>-ndyi~3e*T4;d>h?UgD?&S z3X=4db2lpb2%E~dE{i}O_^mmx${$U_m;nC(?zmswnfF4 zU?vrwkyLw_jo-cA!~!ipu*FmSM^j>_-En6o53M?OG^xLOufI1bu!g*z)2WRx5nk|Y zB77v!7v{BO`{UwMpjEVKZKDVPW75aHs*^NJ??UnAe4nK?15pM#>G;Jb#;nce$S8WN z*s{;Po8dNl;Z?C^^%7yOqk&288re!R!9Q3Pq|Sr=4JT#iS6#^4mz`O|anKX<3zfS% z*%|Rzukryi5~X`aRRxV$uuzW5iL@`!5Pk*k+jL8vz=}N+chSMek+MpJ-0}AKHY0ij zGG50w!vl7Z*ILpCelmhl{3_QTuTWswc*K+6k5%lNSv8z?9epX~JZu9YH&4d!y!q+3 zl;(`Q(waGHlL&*AQq+i#I)`l1n_d4{^|a}Mb`-J6b7Y~88W9S$d$Z9lG*sk*Hu=kp z>t<1_sP@$S`_Ll1TQcVliQj#&VOw#`Po+-jt#B}oTBWRNTV~JbN^2?zt_?&S!d~(_5UoQ}z8v#2O zU(n4%LG{ZTk3DTMimdYfvLI@K8Bi!d}^{Tdk?F5ND&(dCam-Zs!g#`S#objiO7 zHHHttP*!l144&yY`Z+i;gR$ND6pILa1_D3y-mX@q6lJNaCiU|H!VkN~O;9Su z=e)h+Qm5y#P5!#-hmkTT<9WVI9C_zjEXUo8Z>;-q-)k4SUid6TF;)J$%(y@51(o55 z*r~pdvo!Kujp4k^7Me={8d$N{moZ#Iy|~AfeYKLP8~as2Y{_10Nf=v~)lM#p^P(aS zN_={8WU+vIdRO!_tb}vw(paI+)DXTKU`h-+8-X`^)+s8VnMXlfojUH9YCpV)p}eKE zMM3nmUt&^!*#o7G3y=P`IQ+npf8zBK9Shx)RhIT8K+F=g6Ad%N2S+)YX3_KS=Eqam zu@&V5|DN7I_IM_M-a~Bn?pYnakE`zo1}#yXwmYzv*rl|M;ZutAzr0T~!dwtm%98(r zld9)KVe``(GLQ0SV{5rllAsWlgz)yyT49wdl>M>cnE;!6+-{a1>R1lDRFsvzcBz}q z)y~!wJXqg)?jL6oF>Y9Qs?yBDCkt;faUbm51aq29-4$#2)E-B5>}5&}xZ^|D!~JfcSSI z9**a+d~{;5ro%)@PJ%urLVNi--w(2)k4dL)i%l&e?#o&(Y6W zF;^5FiHr_KQh;qEpX0`H?$QDmX&|@AcT2uhdvw>tK&Ru#rSGxLVV3^ZU{H0P0tSOx zO(g?oL{6Mjk$2~&aH%z9zcuhA(%F3fnkhzhmp+%`+v_4=GklD!Qzy!Fn@Dg}Agl5D zpwLF6qIgX1qpLWL>B#hI%ntT@oznb};xcWkqf1E@8a^`lYXm9DH-hT;4fAPc=HJx$ z_3RsCL9!FCzcVu|F)J%xeeM5!`}SVi7ims4&oUaNwRy&XxK^#KeXz_dIQ!xAtD=Ms z>P^YN$%x}FXj9)qYrf}OoAV`-*6}mT5-XdA(CiOMYzUn}8z%vt=C3A`FDb2MDeOz1 z*S;o;WtYp+FV!UJ`jTn14s99s*ep|QfT!AXf-K6KNVZo6K^klyYKMY2u-v2HjOrYX zkI<`MHM`vkcB1F>_;uWWb^p?wUN`lZ?+jqs$TZRZmM~7I{u*I4DYhTzGF^H~KP93X zi`s6(nUg7^>Wj}xG_7jo^fC+LpFKBCKW@sTb@Gu3 zW97xJCQNTcxzwk2!I$OJapSpc?jii^M1Ym* zCZPyuE2`Y`l(o~fTRVVbGl>H_;{@4X9)KZ;)IG|MhfSO$ymBa+aOdWDp97o;WzShc z8ZA9em%shrEI{63M2pNG@2^+0x)Zf`e$2lXOrE*EJ2|g%UHLkdFurMIDf7q@@nDtv z!RdWQS+bW?l^u?if?=6XaxR02$agh6I!Wz3Gtfo~=?_ae@t}X+Y|(ojH+6;6_tngt zuqyW^|HwpaiB5j~T>hdvPJ-rLSESt2bk7XgGat2^Kz--}%MnwFdbZ6DrSbIq)}B#5 zlo?s@xhT80Y+hr+5xW^R3*Q4FCR4(S_4}I?y-9Te6NW}43I-yR9_Kg-R-ijFRCjem z7-ei3f4NwkgAqOsUGcnvZx)Xr)_zagM{ibaeCa^}>~q~)@&~xapPnVgn12jCv|hE> z_*HjMtMF-d>mJDnZBAH*yC6A}OF9)e^Z63mgD27l1jk(OxU#|hrV65~Vdo%5yG#}t zRH3@}HI_K4{M=_hm>66(v9PuJGUwQbq1Sb1j%g}wl2e#~R`d9N4+?^DIi$+VsOO zG^M*P+bDM4tWJqg*}hCz%bdHL+_uSw4bI!_=Su?Zu0bf~B zdt;guDw#u^25hghM~|u{o$fY-V+Z}k`u@1_?*>f$$F-*TI4}s1 zb{tLp9t={K{E=}Z>iu#wk#p9g@p;5^;`meWIpvsTtG`cXn-LAGvc^`cZk`xLJPQ>2 z)%x`)`?ss;ba|)=n!z$p@aTjmaVgp{cR=X`$$A-$fLNm>mVI%vnWsU&-SvxNR_iu7 ze`#qgIyj3`H9>Oy{Cx*bQ#gl*rtnCa+K~^8dOB3;VTet?USxaxL*)uY!orQ|YN5w{ zVW!c1RL7zTVPyZz+Oba3D9x;n2)4C_oIDcBgex~WM~6aXCR^cJw3+J6j@)|yhaTID zy|iv(_Fu5{x9OD^BB|dq-WTtkhwz6K1O-c#oZ0v2-u=-{O`v4ycdUt&Vjp)iG3|Ea zn&AXVZt?^n^z*FJqZMgB5t>+3i z)}#3^dYQh9a*CyYrheZN1wrNX1l*6b!7>i0yJn8v9F<5?!Zw$P62_9AH~F=IpZpd^ z;z}TQHAGJuQ6&r#J`0>E^EE17OP@{5hs7>zsW2!AS?{=UUSnbU~G*Zw!BREdF8E zConO33@jrtAoIEbR}pSYAgF(u{~?cY7lhzgzEjBOmgQF>j{la)Bfho4QmgqlZA~gG zU|??GpiOmX2g`foWy~Oxa=-=jofSFM6W4tHN@n(%VJj z1CsBethJHF>H+Krs$A2<%A{f-r{%6>I(zw&rV+x&&y~Dpd25u(Wi)3>zsPLC5oy zu^Tz$&k|?m=vIO&XE!F(4aFE1&H@DE?#f z9MZo*)(tQDzaeb7d77)13=LWhx|B~UGKkx92<4Mvbes4#Tg8~EYU99CJ_BZo**`Q& z@{u%BzE4%gQgzE(mnUjLnBSUEwayVb-_5kyM^rrM5p&&zXX@15(=zYr->uluU7h$0 zjACk%wbWlv3b#5dA%;MCSXeHPY?Ghv8?|ND1|$))&lP4b0i>$atBqEA7m{TwtBp4b zcK74Hn-V8x_(7%ra&NWHOEcd*m^9xD!&$mn}>gIRX z+87n^AAxXsWw;`N7P!hsi`IA~9BK5y=BEc`zj_{{EKL!QzOw*etNowoo8DS0w0Wm4eDaX<&s0JmJmu(~TY z=%wZ@0nNkGPol`=ByC|1NaFE`60Y{$F8|`nhJqW20NIN`b9U>5@A~VTaKmv_3ddp~ zOjGUvN0Gx2GOmErK;N!gxYr3FBuB`=QL6)0)cT{jV5eLfMoQ&ZV4b|!;zCP{ML9xt zSHW3zd?zcOB4yzv52>)HCa&|Y{`i;H)b0sOaJH1)8@Cy znPLAciu2YR+``h3WuASNey8GrcMCXtMMi6DQrAb#hirS@_*(bCLFi19Y7yoSA^mR{ zZ3~{qhjnkcDeTJhM65Fr8x(qX%)IB^`pwZd<*>iq%Pyw>emP4zpzyc>SiDEr?mw?E z*Jc&~oke#rLd@ArO5M;W-zgO`Lr^i-Y zZq_RbwK?ba#6?Eq&CSH^ZAHzCs1O4-p9RlDXbPLHXMV=I#4Mn*WLBx$oVI|ca;lzN zM1IJN@CqGH*%ez^qtq`Ao0p6Z|WQ=fB{6@EFV zCH*gbJzQNkkMovsaH3lgB`U-1@y(qY)F~5YOFI>E{ev{vT`ELX|K9wW(t+UN^vIki z#O}AD&rWp|rh{>i1FN?XS9@t#de&OnV%Zn?ccbAP-&#yrC9w~YYR&>?W&Ygl6 zKN^y3?>*)xz$oR_w=M^4U&_MBUSDn% z>~Om3S}dZ7y+R>`X{mtd!Qv6=uW$Tr;8F&JR)1$m@eKy&TX#OfEwnoEFHEensn?=w zT~>8zT@P1ulCrY#C{B%cgidulnys!4B`OaGknyiZTv+&=PY3lK-6@7r?9tg|bYvFF zCg-9)<$Q=@TmvYv*L9BBZ+#6BrLZLDm@;#Dt+AV!_-6WXH=WEGI&*I7OOw- zKy_j5r(cX56RrKoE=_eUi}$NgoyU7?N}Qzy2R1Z z;DDRFr+W0lzmk#PSAOE^^WoNa2UqJsF@mEqR=`#r?(SANszx@#w%LMvY58;Tc$w_HCK z(~WET1e~#>yuH^kz~24pO}|)H>npZLdZ97l7~Pjg)YI@*rXe4y^O?Pu)qkA!KM8sE zHe}~@VLV7%9A*bYvou&yQw*e&1ygH&z-chqo_#@0$UR#BpPEN=J&KN37wH>_Ceg3` zgNuAT*#+Y_+u=U-*A-j)u|^d{IN(JjR8&?kjAvCfnszXT`T9MPmi_qi4u;Ru70ef5 z`K;e=FPH1A5)^wxagJ&m63tJ$h458|M(F*mkr$u4HKNRgmkhN6d7vR4R6vj4R_8b) zCqHy%???k+u39%MU7pm@qI^QBY*lvqQu3Ig^WF5kb-RML67DVA8wRbHMCK#{qy{qh zPIXl$S|dhLkS3ZRu8qZk6QNZ`toXIhOcqompcw^Y2>|s5h#Pi(w3uD2`AKr#*0O&; zVA*tXw#Ihfra69p4Zb)#8wH!Xnwpr7XQkKW*k&vmlfpq#p6T)PLYpI7G34qHeXEPm zSdTh~zQ=61rkliBi*uQ=( z$aMV_zHRQ#3f9hujXk8Ywjdj%gxf=4@wLCo`8H0Su)-|&K`QW>eSGCGct`jbt=LYv^}b#jF@vqj66(pP za@5tX@;($<-w_)68erU#Z6#FHl@R`g+$BGi*09tor&%nhx6e8j3qQ3{dTE*FkzH8* zeS>Q@;+rvE__(hTMO-3(JKWv*w;Q!+aN6tzwI?FIG`9U!0G}2M7dc2saED8Dm`#z(#wCANZcZoCBLkc@=NV&-e{EA{^`?aJC4b{@XS14 zMdm(G4XuO~NYa0u4Q5Aad_}#DI_c_H;{>>~E_`=KIlmRUr$mOuWIiF>8Wxobv744H z@D5AzWTmo!Z^R}7GhQa(_Ebfj*k6O~-7$$GF#DM)?PXQeka`wVoFhc|e zK05TFl1nb!c^OX3#&u%!pTa7gH*t_7=>{?ntI~1+s`v+2#!@n-A?%+?^pu=UG|lsl`p@i#h`I3b7d8}u2)V$}UvqYr{4O|LQ$xacF^_)7sF z!Fs7H=#E5_C%GkQI^tpgJmat!Ge!*<2crG+5>GGM-GTHK?+_k1vR2&u6S(cUGkkSI zBY|knb5_eCPOba?6c?ZJZ>5^fLX%C~o*>uo){!z3P9p|sEt}VeP(7D%p#w#_p1CQL zsC0v$ZL~=p@wC};{yXPO=s_J~=h#o<9U~x@2%vWTY<5Um^ed()pb$w{(Xg_yMEfw# z!^E@y-4WJXr8QQc;GzQLsZl@dBr?A9SJ1~)1cZ?hHY0gynk5|>*?x^n({??PhwG4CPs{akp3U6dFkgd?@ZuDj6J~!+FqtpB zYVp`I9UXrj7z__PK@B>n-yP*MTJJsZPs{Mz#_ve|tkQx(X0(Lr_G{OQmhYYa-tkZd z8vQLyzt}GQ3Ym$L@%i!U+NNV{(ByPoaS!S!)2DCHpOhN6l6Gx0%v#rEp742-4Q`R~ zSj%Q9w9zBumyUCU1KQ`%n=P-}2ggd!SEyca;Bpno-z0yioCsw<3S6k)4L%5$atLRc zO#T!9YTkHPLby-A#Vj4tqNCIHWKL*tVz0O`cx69W)U7G8V}>n=2;%@we?2pr7tzj1 zc%P%!i_>3HJ2_+dO_cm@n~%_0ld|agQ;-=FfFH7@Co5VtAi!n=vTfNPa)?4Ud|7u) zcx}gsR4^7^hGt@5ei{E(G`100q@xN|+=q$LauSM_OC}8A(^wt2_RqaE4WuG~(pfcQ zzqQ)TY%MHFJ_H0ZNUjJ=MT;$!M_c-Y#OF>;yVBLIKM-EvjWzi0XE6yk-clHMMY(c! zbG#1=iww%CntJm2|NOmrP(*8=&g7gH+b_m0_(0|d&dIfT>DY7%JNPu&`aOPdla#ZG3^IS6OQ};WdnM8XDj@!q`6&%ZDxAb$BP2sHJQU9 z%Z2hweG46sBX`$mh1m;@+OQPK(giYNEW6VNq$+{|7L(GOPDSl6o>BZLc(X9Z!Z|Mw zI^sXzxi>Sga8F;vfIqMbDe=Ltp;~v#uIgi8=p9d(8JPj$inLZ?&p-d>hZiJw_!2eXbYU*)4|aci7aE&`6E^ravNSRryQ{>tj?%MtDJ(q4 zYeA|tc=HN9eq)W@)=TKD(14QgDgQgx`!{y&&e#Honoqj1!T&{aTwwe3N zasCH@Ad@@AFDxT{m%rcP6Oo3{xz|VcEM;sGVT*ZW%cv1zE3s8vvBS@m+N;n#Y4a>FPfsMpR{#elVfBs`L5h(XNshl; zYXC1{Ac^kxKYnR7T(iKWGD=R@9~nF=8)!&*9?aPx(WM2jDdG=vvyOyuHoO=QT-_#k z?I>2rRw8_B6qfy89QGM8M|8wPZ0*MIWf!mKc`%Zgsc-74;)J}0n>$G*hpca2?)Ag? zKk`&>d!4Wvc9Q6X?=+5#-Wsr-8#ae$?4@UM+nIkmi~#D?6JRs%F884tuC73CO&Phk zVUt!<4qT_528fc7?;!jnLQUfW2Q}vl0gui{z*~(`+ zZ_G;uDN$M83SsLfo&-W||Jo#*R-G-bf&h(=!!wdbX`c+1J9>+5$pnXQ0&^rQlR!#z zV-2_;EMd7l@;sT(FXvRbHKrMPZDyGDOrS}QU`H|BiXeifBT;()DwKl|=KYf`7D|!< zS#08MB?`V0$Ndt&A8T@h7idn+iPVntC(cR4_RFWy8p-jZW<7KDBJBJrIK4N-)gRk( zjw_WSie;(juWxIT{pD<6Y zyDoTt)T?JU!+PSMNogFd3z5ltFWvm}K^z45l_n3=ROt1^FHxctBqX1RmJgld?BHYu zu;7)8X(L#01;HfU_&NKCDnD3KWz$Ea@{BQj8vJ}+LB=dX+$?H)k$A3@rQSJF*OAik zcrDL)YZc$r0VbP~osnTL86&#u+4V%h`haTw$)0tSxYHn=j7DTPoGtUH^q%4DoEfNO z&qLu1#?3PS;)$SpK0ZfV@D6l=?>Bw#;HWoZ*@2vdDzmw5(!T{8Z-=%+KH} zHn#Udo6`;TsWKTlz>icn{PfV5lkYNqLp+{qWr3=NC#>Rr`^!Rc87ql7mM8u^o`E+5 z#-7M4A1$5s!mq!(%glUogL8x4;v~}P+f{G$*xo>f9PvDU!73cgnt6BD<6+lbBV5oz zK(57Nt!8MAlFmI&J@Eq&(E=Xl<+{e?#hV(y5g^gRtwf=6D_+PjKf#7M#ouM~sp(6_ z;i&uOjvp>AR8PwMt_sl3NsX76u~1+k7YiRbpyB@HC|%x~BPYt1GwWB>>#~b#{o~G8 zK>u0DmGwK^{VfBMKE`QVf|5Xp`53gk^?MA-J+2;4UdO zevmVfqA)c}xRxXV9BB^sIuf7~0nCQq223+N>-EZM6wke)9BICpiTwVH?jG_b2ublq zJ=9q5tkb@Viu0f_pcK0hh|hlUeY59G<+~ylsfM7^8Qj@^hS)1$JRP0}s%-_s=oL3} zwcRIl6p@`kyUB=qv!r!9?+IP!6@BVINRg_!u7kOirGO1sjR=5T$hgj};#4R42m#k# z4+?sAC>#XSA$Kf%4gRIr&m_^fdHZpv&J3w(r)G&_w4BaT(lxvgHejC zKew1TPQaw2-qL5zYL&O}xWK>@BhqOG!IcOd96C~pc#6^}v?Zy+*Lcg%udYC{2w+3= z;pL}b-P?7?LHT9hl8t>i&9Wt${*bt#)S|Y}Y^a7LJA@>EEwo|tX(K>Myv64?Fm~*A z>Mv_+ZtEuz-MlR7If0eR|BZ? zg;L|SjVQrsQpg(xJ5P_h`jiB$`(}EvG3N<}g^?y4(t(85OBo>A?5I}>;prDfKy)$L z+CXIg;NsPy9dGw?wb{sEh6s*-dgzu^*0OuS-2-jPzu*8r*Aqnfz`evkw#WHpJyW7O zmTsXhaOB{+o4zYHdbq&&ohVI%v$z!tzn0jUrul#W6*coGmDqMrCwmWn`Q77~%1y28 zAz?U>E_C8Yb)P0V=UvBk#&=!$@>Gx#gE$W42yE$AqN;1Zb9AvJm{o39lCx(e|gP^gxbSmN!clCLR`G?dlv$~@U7rkw7%n~ zz)4(H6}YF`w_%}zJ?7cA5G=@}!Qk0UcS2g_sK#RG-tsBn><+JvW^f9g(9N{`D|AA< zSAL9bl@y{@ha*j~b%ls078Ubh2J4sK#-zw#b!VTeKC8y53Ky(8d2_<>5YAaW*(<

e=h(U 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 + + + + + + + + + + + + + + + + + + + + + + + fs fw + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + fs fw + + + + + + + + + + + + + fs fw + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/logo/FSFW_Logo_V3_bw.png b/logo/FSFW_Logo_V3_bw.png new file mode 100644 index 0000000000000000000000000000000000000000..99b9b4f9608f4e53b86ff83747a114477004c9f1 GIT binary patch literal 13369 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 Date: Tue, 1 Dec 2020 13:32:50 +0100 Subject: [PATCH 20/23] Update 'README.md' --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index a59f4ddd..4aabe36a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ ![FSFW Logo](logo/FSFW_Logo_V3_bw.png) # Flight Software Framework (FSFW) -====== The Flight Software Framework is a C++ Object Oriented Framework for unmanned, automated systems like Satellites. From 98dae18430f6a19ee1047d5c0b47d16cf4ee6bc2 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 1 Dec 2020 13:46:29 +0100 Subject: [PATCH 21/23] update defaultcfg folder --- defaultcfg/{config => fsfwconfig}/FSFWConfig.h | 15 +++++++++------ defaultcfg/{config => fsfwconfig}/OBSWConfig.h | 0 defaultcfg/{config => fsfwconfig}/OBSWVersion.h | 0 .../devices/logicalAddresses.cpp | 0 .../devices/logicalAddresses.h | 2 +- .../devices/powerSwitcherList.cpp | 0 .../devices/powerSwitcherList.h | 0 .../events/subsystemIdRanges.h | 0 .../config.mk => fsfwconfig/fsfwconfig.mk} | 0 .../ipc/missionMessageTypes.cpp | 3 ++- .../ipc/missionMessageTypes.h | 0 .../{config => fsfwconfig}/objects/Factory.cpp | 14 +++++++------- .../{config => fsfwconfig}/objects/Factory.h | 0 .../objects/systemObjectList.h | 0 .../pollingsequence/PollingSequenceFactory.cpp | 0 .../pollingsequence/PollingSequenceFactory.h | 0 .../returnvalues/classIds.h | 0 defaultcfg/{config => fsfwconfig}/tmtc/apid.h | 0 defaultcfg/{config => fsfwconfig}/tmtc/pusIds.h | 0 19 files changed, 19 insertions(+), 15 deletions(-) rename defaultcfg/{config => fsfwconfig}/FSFWConfig.h (81%) rename defaultcfg/{config => fsfwconfig}/OBSWConfig.h (100%) rename defaultcfg/{config => fsfwconfig}/OBSWVersion.h (100%) rename defaultcfg/{config => fsfwconfig}/devices/logicalAddresses.cpp (100%) rename defaultcfg/{config => fsfwconfig}/devices/logicalAddresses.h (89%) rename defaultcfg/{config => fsfwconfig}/devices/powerSwitcherList.cpp (100%) rename defaultcfg/{config => fsfwconfig}/devices/powerSwitcherList.h (100%) rename defaultcfg/{config => fsfwconfig}/events/subsystemIdRanges.h (100%) rename defaultcfg/{config/config.mk => fsfwconfig/fsfwconfig.mk} (100%) rename defaultcfg/{config => fsfwconfig}/ipc/missionMessageTypes.cpp (79%) rename defaultcfg/{config => fsfwconfig}/ipc/missionMessageTypes.h (100%) rename defaultcfg/{config => fsfwconfig}/objects/Factory.cpp (75%) rename defaultcfg/{config => fsfwconfig}/objects/Factory.h (100%) rename defaultcfg/{config => fsfwconfig}/objects/systemObjectList.h (100%) rename defaultcfg/{config => fsfwconfig}/pollingsequence/PollingSequenceFactory.cpp (100%) rename defaultcfg/{config => fsfwconfig}/pollingsequence/PollingSequenceFactory.h (100%) rename defaultcfg/{config => fsfwconfig}/returnvalues/classIds.h (100%) rename defaultcfg/{config => fsfwconfig}/tmtc/apid.h (100%) rename defaultcfg/{config => fsfwconfig}/tmtc/pusIds.h (100%) diff --git a/defaultcfg/config/FSFWConfig.h b/defaultcfg/fsfwconfig/FSFWConfig.h similarity index 81% rename from defaultcfg/config/FSFWConfig.h rename to defaultcfg/fsfwconfig/FSFWConfig.h index ea86152c..1386bf66 100644 --- a/defaultcfg/config/FSFWConfig.h +++ b/defaultcfg/fsfwconfig/FSFWConfig.h @@ -1,19 +1,19 @@ #ifndef CONFIG_FSFWCONFIG_H_ #define CONFIG_FSFWCONFIG_H_ -#include #include +#include //! Used to determine whether C++ ostreams are used //! Those can lead to code bloat. #define FSFW_CPP_OSTREAM_ENABLED 1 -//! Reduced printout to further decrese code size +//! Reduced printout to further decrease code size //! Be careful, this also turns off most diagnostic prinouts! -#define FSFW_REDUCED_PRINTOUT 0 +#define FSFW_ENHANCED_PRINTOUT 0 -//! Can be used to enable debugging printouts for developing the FSFW -#define FSFW_DEBUGGING 0 +//! Can be used to enable additional debugging printouts for developing the FSFW +#define FSFW_PRINT_VERBOSITY_LEVEL 0 //! Defines the FIFO depth of each commanding service base which //! also determines how many commands a CSB service can handle in one cycle @@ -38,7 +38,10 @@ //! When using the newlib nano library, C99 support for stdio facilities //! will not be provided. This define should be set to 1 if this is the case. -#define FSFW_NO_C99_IO 1 +#define FSFW_NO_C99_IO 1 + +//! Specify whether a special mode store is used for Subsystem components. +#define FSFW_USE_MODESTORE 0 namespace fsfwconfig { //! Default timestamp size. The default timestamp will be an eight byte CDC diff --git a/defaultcfg/config/OBSWConfig.h b/defaultcfg/fsfwconfig/OBSWConfig.h similarity index 100% rename from defaultcfg/config/OBSWConfig.h rename to defaultcfg/fsfwconfig/OBSWConfig.h diff --git a/defaultcfg/config/OBSWVersion.h b/defaultcfg/fsfwconfig/OBSWVersion.h similarity index 100% rename from defaultcfg/config/OBSWVersion.h rename to defaultcfg/fsfwconfig/OBSWVersion.h diff --git a/defaultcfg/config/devices/logicalAddresses.cpp b/defaultcfg/fsfwconfig/devices/logicalAddresses.cpp similarity index 100% rename from defaultcfg/config/devices/logicalAddresses.cpp rename to defaultcfg/fsfwconfig/devices/logicalAddresses.cpp diff --git a/defaultcfg/config/devices/logicalAddresses.h b/defaultcfg/fsfwconfig/devices/logicalAddresses.h similarity index 89% rename from defaultcfg/config/devices/logicalAddresses.h rename to defaultcfg/fsfwconfig/devices/logicalAddresses.h index 174fa788..e0827ba3 100644 --- a/defaultcfg/config/devices/logicalAddresses.h +++ b/defaultcfg/fsfwconfig/devices/logicalAddresses.h @@ -1,8 +1,8 @@ #ifndef CONFIG_DEVICES_LOGICALADDRESSES_H_ #define CONFIG_DEVICES_LOGICALADDRESSES_H_ -#include #include +#include "../objects/systemObjectList.h" #include /** diff --git a/defaultcfg/config/devices/powerSwitcherList.cpp b/defaultcfg/fsfwconfig/devices/powerSwitcherList.cpp similarity index 100% rename from defaultcfg/config/devices/powerSwitcherList.cpp rename to defaultcfg/fsfwconfig/devices/powerSwitcherList.cpp diff --git a/defaultcfg/config/devices/powerSwitcherList.h b/defaultcfg/fsfwconfig/devices/powerSwitcherList.h similarity index 100% rename from defaultcfg/config/devices/powerSwitcherList.h rename to defaultcfg/fsfwconfig/devices/powerSwitcherList.h diff --git a/defaultcfg/config/events/subsystemIdRanges.h b/defaultcfg/fsfwconfig/events/subsystemIdRanges.h similarity index 100% rename from defaultcfg/config/events/subsystemIdRanges.h rename to defaultcfg/fsfwconfig/events/subsystemIdRanges.h diff --git a/defaultcfg/config/config.mk b/defaultcfg/fsfwconfig/fsfwconfig.mk similarity index 100% rename from defaultcfg/config/config.mk rename to defaultcfg/fsfwconfig/fsfwconfig.mk diff --git a/defaultcfg/config/ipc/missionMessageTypes.cpp b/defaultcfg/fsfwconfig/ipc/missionMessageTypes.cpp similarity index 79% rename from defaultcfg/config/ipc/missionMessageTypes.cpp rename to defaultcfg/fsfwconfig/ipc/missionMessageTypes.cpp index e2edbf9c..b41b87ba 100644 --- a/defaultcfg/config/ipc/missionMessageTypes.cpp +++ b/defaultcfg/fsfwconfig/ipc/missionMessageTypes.cpp @@ -1,4 +1,5 @@ -#include +#include "missionMessageTypes.h" + #include void messagetypes::clearMissionMessage(CommandMessage* message) { diff --git a/defaultcfg/config/ipc/missionMessageTypes.h b/defaultcfg/fsfwconfig/ipc/missionMessageTypes.h similarity index 100% rename from defaultcfg/config/ipc/missionMessageTypes.h rename to defaultcfg/fsfwconfig/ipc/missionMessageTypes.h diff --git a/defaultcfg/config/objects/Factory.cpp b/defaultcfg/fsfwconfig/objects/Factory.cpp similarity index 75% rename from defaultcfg/config/objects/Factory.cpp rename to defaultcfg/fsfwconfig/objects/Factory.cpp index 51dd6130..41333b1c 100644 --- a/defaultcfg/config/objects/Factory.cpp +++ b/defaultcfg/fsfwconfig/objects/Factory.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -31,15 +32,15 @@ void Factory::produce(void) { setStaticFrameworkObjectIds(); new EventManager(objects::EVENT_MANAGER); new HealthTable(objects::HEALTH_TABLE); - //new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER); + new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER); } void Factory::setStaticFrameworkObjectIds() { - PusServiceBase::packetSource = objects::PUS_PACKET_DISTRIBUTOR; - PusServiceBase::packetDestination = objects::TM_FUNNEL; + PusServiceBase::packetSource = objects::NO_OBJECT; + PusServiceBase::packetDestination = objects::NO_OBJECT; - CommandingServiceBase::defaultPacketSource = objects::PUS_PACKET_DISTRIBUTOR; - CommandingServiceBase::defaultPacketDestination = objects::TM_FUNNEL; + CommandingServiceBase::defaultPacketSource = objects::NO_OBJECT; + CommandingServiceBase::defaultPacketDestination = objects::NO_OBJECT; VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION; @@ -48,7 +49,6 @@ void Factory::setStaticFrameworkObjectIds() { DeviceHandlerFailureIsolation::powerConfirmationId = objects::NO_OBJECT; - TmPacketStored::timeStamperId = objects::PUS_TIME; - //TmFunnel::downlinkDestination = objects::NO_OBJECT; + TmPacketStored::timeStamperId = objects::NO_OBJECT; } diff --git a/defaultcfg/config/objects/Factory.h b/defaultcfg/fsfwconfig/objects/Factory.h similarity index 100% rename from defaultcfg/config/objects/Factory.h rename to defaultcfg/fsfwconfig/objects/Factory.h diff --git a/defaultcfg/config/objects/systemObjectList.h b/defaultcfg/fsfwconfig/objects/systemObjectList.h similarity index 100% rename from defaultcfg/config/objects/systemObjectList.h rename to defaultcfg/fsfwconfig/objects/systemObjectList.h diff --git a/defaultcfg/config/pollingsequence/PollingSequenceFactory.cpp b/defaultcfg/fsfwconfig/pollingsequence/PollingSequenceFactory.cpp similarity index 100% rename from defaultcfg/config/pollingsequence/PollingSequenceFactory.cpp rename to defaultcfg/fsfwconfig/pollingsequence/PollingSequenceFactory.cpp diff --git a/defaultcfg/config/pollingsequence/PollingSequenceFactory.h b/defaultcfg/fsfwconfig/pollingsequence/PollingSequenceFactory.h similarity index 100% rename from defaultcfg/config/pollingsequence/PollingSequenceFactory.h rename to defaultcfg/fsfwconfig/pollingsequence/PollingSequenceFactory.h diff --git a/defaultcfg/config/returnvalues/classIds.h b/defaultcfg/fsfwconfig/returnvalues/classIds.h similarity index 100% rename from defaultcfg/config/returnvalues/classIds.h rename to defaultcfg/fsfwconfig/returnvalues/classIds.h diff --git a/defaultcfg/config/tmtc/apid.h b/defaultcfg/fsfwconfig/tmtc/apid.h similarity index 100% rename from defaultcfg/config/tmtc/apid.h rename to defaultcfg/fsfwconfig/tmtc/apid.h diff --git a/defaultcfg/config/tmtc/pusIds.h b/defaultcfg/fsfwconfig/tmtc/pusIds.h similarity index 100% rename from defaultcfg/config/tmtc/pusIds.h rename to defaultcfg/fsfwconfig/tmtc/pusIds.h From 802e24e2933be81eb6f7a35af89692dfff5bc159 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 1 Dec 2020 14:43:36 +0100 Subject: [PATCH 22/23] change log update --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 96f5703c..d5e083dc 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,4 @@ -## Changes from ASTP 0.0.1 to 0.0.2 +## Changes from ASTP 1.0.0 to 1.1.0 ### FreeRTOS OSAL From 45df446ab80e1303738889c21e15921c4b807fd6 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 1 Dec 2020 14:44:03 +0100 Subject: [PATCH 23/23] change log update --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index d5e083dc..4937b5f8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,4 @@ -## Changes from ASTP 1.0.0 to 1.1.0 +## Changes from ASTP 0.0.1 to 1.0.0 ### FreeRTOS OSAL