diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/NOTICE b/NOTICE new file mode 100644 index 00000000..e1663282 --- /dev/null +++ b/NOTICE @@ -0,0 +1,21 @@ +Flight Software Framework + +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. + +Copyrights in the Flight Software Framework are retained by their contributors. +No copyright assignment is required to contribute to the Flight Software Framework. + +Some files include explicit copyright notices and/or license notices. +For full authorship information, see the version control history. + +Except as otherwise noted (below and/or in individual files), the +Flight Software Framework is licensed under the Apache License, Version 2.0. + +The Flight Software Framework includes modules written by third parties. +The following third party modules are included, and carry +their own copyright notices and license terms: + +under contrib/: + * sgp4: sgp4 code developed by david vallado under public domain, see https://www.celestrak.com/publications/AIAA/2006-6753/ diff --git a/THANKYOU b/THANKYOU deleted file mode 100644 index 9df00689..00000000 --- a/THANKYOU +++ /dev/null @@ -1,5 +0,0 @@ -Besides Bastian Bätz and Ulrich Mohr, who were the main developers for Flying Laptop's Onboard Software, the following PhD Students contributed to the project: - -Rouven Witt, who developed the FDIR concept and kept morale high as the team's Spaßbeauftragter. -Marek Dittmar, who started work on the ACS code and later tried to keep the development in time. -Nico Bucher, who performed software tests and as such was invaluable during the development. diff --git a/action/ActionHelper.cpp b/action/ActionHelper.cpp index c85f8d01..fa1c904b 100644 --- a/action/ActionHelper.cpp +++ b/action/ActionHelper.cpp @@ -1,8 +1,7 @@ - #include #include #include -ActionHelper::ActionHelper(HasActionsIF* setOwner, MessageQueue* useThisQueue) : +ActionHelper::ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue) : owner(setOwner), queueToUse(useThisQueue), ipcStore( NULL) { } @@ -41,6 +40,10 @@ void ActionHelper::finish(MessageQueueId_t reportTo, ActionId_t commandId, Retur queueToUse->sendMessage(reportTo, &reply); } +void ActionHelper::setQueueToUse(MessageQueueIF* queue) { + queueToUse = queue; +} + void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, store_address_t dataAddress) { const uint8_t* dataPtr = NULL; @@ -62,31 +65,38 @@ void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t act } } -void ActionHelper::reportData(MessageQueueId_t reportTo, ActionId_t replyId, SerializeIF* data) { +ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, ActionId_t replyId, SerializeIF* data, bool hideSender) { CommandMessage reply; store_address_t storeAddress; uint8_t *dataPtr; uint32_t maxSize = data->getSerializedSize(); if (maxSize == 0) { - return; + //No error, there's simply nothing to report. + return HasReturnvaluesIF::RETURN_OK; } uint32_t size = 0; ReturnValue_t result = ipcStore->getFreeElement(&storeAddress, maxSize, &dataPtr); if (result != HasReturnvaluesIF::RETURN_OK) { - //TODO event? - return; + return result; } result = data->serialize(&dataPtr, &size, maxSize, true); if (result != HasReturnvaluesIF::RETURN_OK) { ipcStore->deleteData(storeAddress); - //TODO event? - return; + return result; } + //We don't need to report the objectId, as we receive REQUESTED data before the completion success message. + //True aperiodic replies need to be reported with another dedicated message. ActionMessage::setDataReply(&reply, replyId, storeAddress); - if (queueToUse->sendMessage(reportTo, &reply) != HasReturnvaluesIF::RETURN_OK){ + + //TODO Service Implementation sucks at the moment + if (hideSender){ + result = MessageQueueSenderIF::sendMessage(reportTo, &reply); + } else { + result = queueToUse->sendMessage(reportTo, &reply); + } + if ( result != HasReturnvaluesIF::RETURN_OK){ ipcStore->deleteData(storeAddress); } - //We don't neeed the objectId, as we receive REQUESTED data before the completion success message. - //True aperiodic replies need to be reported with dedicated DH message. + return result; } diff --git a/action/ActionHelper.h b/action/ActionHelper.h index c6965414..99ca4ce0 100644 --- a/action/ActionHelper.h +++ b/action/ActionHelper.h @@ -1,25 +1,26 @@ - #ifndef ACTIONHELPER_H_ #define ACTIONHELPER_H_ #include #include +#include class HasActionsIF; -//TODO: Change MessageQueueId usage. + class ActionHelper { public: - ActionHelper(HasActionsIF* setOwner, MessageQueue* useThisQueue); + ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue); virtual ~ActionHelper(); ReturnValue_t handleActionMessage(CommandMessage* command); ReturnValue_t initialize(); void step(uint8_t step, MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); void finish(MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); - void reportData(MessageQueueId_t reportTo, ActionId_t replyId, SerializeIF* data); + ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId, SerializeIF* data, bool hideSender = false); + void setQueueToUse(MessageQueueIF *queue); protected: static const uint8_t STEP_OFFSET = 1; HasActionsIF* owner; - MessageQueue* queueToUse; + MessageQueueIF* queueToUse; StorageManagerIF* ipcStore; virtual void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, store_address_t dataAddress); void resetHelper(); diff --git a/action/ActionMessage.cpp b/action/ActionMessage.cpp index f9af5e9b..96ff59b6 100644 --- a/action/ActionMessage.cpp +++ b/action/ActionMessage.cpp @@ -1,4 +1,3 @@ - #include #include #include diff --git a/action/ActionMessage.h b/action/ActionMessage.h index 5afcff76..5d8332cb 100644 --- a/action/ActionMessage.h +++ b/action/ActionMessage.h @@ -1,4 +1,3 @@ - #ifndef ACTIONMESSAGE_H_ #define ACTIONMESSAGE_H_ @@ -11,7 +10,7 @@ class ActionMessage { private: ActionMessage(); public: - static const uint8_t MESSAGE_ID = FUNCTION_MESSAGE_ID; + static const uint8_t MESSAGE_ID = MESSAGE_TYPE::ACTION; static const Command_t EXECUTE_ACTION = MAKE_COMMAND_ID(1); static const Command_t STEP_SUCCESS = MAKE_COMMAND_ID(2); static const Command_t STEP_FAILED = MAKE_COMMAND_ID(3); diff --git a/action/CommandActionHelper.cpp b/action/CommandActionHelper.cpp index ebd5fb88..b643c2e3 100644 --- a/action/CommandActionHelper.cpp +++ b/action/CommandActionHelper.cpp @@ -1,4 +1,3 @@ - #include #include #include diff --git a/action/CommandActionHelper.h b/action/CommandActionHelper.h index f3f574d3..24d0380c 100644 --- a/action/CommandActionHelper.h +++ b/action/CommandActionHelper.h @@ -1,13 +1,12 @@ - #ifndef COMMANDACTIONHELPER_H_ #define COMMANDACTIONHELPER_H_ #include -#include #include #include #include #include +#include class CommandsActionsIF; @@ -25,7 +24,7 @@ public: uint8_t getCommandCount() const; private: CommandsActionsIF* owner; - MessageQueue* queueToUse; + MessageQueueIF* queueToUse; StorageManagerIF* ipcStore; uint8_t commandCount; MessageQueueId_t lastTarget; diff --git a/action/CommandsActionsIF.h b/action/CommandsActionsIF.h index 633876a9..db76fb50 100644 --- a/action/CommandsActionsIF.h +++ b/action/CommandsActionsIF.h @@ -1,10 +1,9 @@ - #ifndef COMMANDSACTIONSIF_H_ #define COMMANDSACTIONSIF_H_ #include -#include #include +#include /** * Interface to separate commanding actions of other objects. @@ -18,11 +17,11 @@ class CommandsActionsIF { friend class CommandActionHelper; public: - static const uint8_t INTERFACE_ID = COMMANDS_ACTIONS_IF; + static const uint8_t INTERFACE_ID = CLASS_ID::COMMANDS_ACTIONS_IF; static const ReturnValue_t OBJECT_HAS_NO_FUNCTIONS = MAKE_RETURN_CODE(1); static const ReturnValue_t ALREADY_COMMANDING = MAKE_RETURN_CODE(2); virtual ~CommandsActionsIF() {} - virtual MessageQueue* getCommandQueuePtr() = 0; + 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; diff --git a/action/HasActionsIF.h b/action/HasActionsIF.h index cb62c522..fb86b790 100644 --- a/action/HasActionsIF.h +++ b/action/HasActionsIF.h @@ -1,21 +1,14 @@ -/* - * HasActionsIF.h - * - * Created on: 20.02.2014 - * Author: baetz - */ - #ifndef HASACTIONSIF_H_ #define HASACTIONSIF_H_ #include #include #include -#include #include +#include class HasActionsIF { public: - static const uint8_t INTERFACE_ID = HAS_ACTIONS_IF; + static const uint8_t INTERFACE_ID = CLASS_ID::HAS_ACTIONS_IF; static const ReturnValue_t IS_BUSY = MAKE_RETURN_CODE(1); static const ReturnValue_t INVALID_PARAMETERS = MAKE_RETURN_CODE(2); static const ReturnValue_t EXECUTION_FINISHED = MAKE_RETURN_CODE(3); diff --git a/action/SimpleActionHelper.cpp b/action/SimpleActionHelper.cpp index cb2bac6d..6de372fb 100644 --- a/action/SimpleActionHelper.cpp +++ b/action/SimpleActionHelper.cpp @@ -1,8 +1,7 @@ - #include #include SimpleActionHelper::SimpleActionHelper(HasActionsIF* setOwner, - MessageQueue* useThisQueue) : + MessageQueueIF* useThisQueue) : ActionHelper(setOwner, useThisQueue), isExecuting(false), lastCommander( 0), lastAction(0), stepCount(0) { } @@ -24,8 +23,8 @@ void SimpleActionHelper::finish(ReturnValue_t result) { resetHelper(); } -void SimpleActionHelper::reportData(SerializeIF* data) { - ActionHelper::reportData(lastCommander, lastAction, data); +ReturnValue_t SimpleActionHelper::reportData(SerializeIF* data) { + return ActionHelper::reportData(lastCommander, lastAction, data); } void SimpleActionHelper::resetHelper() { diff --git a/action/SimpleActionHelper.h b/action/SimpleActionHelper.h index 8615c486..953001d5 100644 --- a/action/SimpleActionHelper.h +++ b/action/SimpleActionHelper.h @@ -1,4 +1,3 @@ - #ifndef SIMPLEACTIONHELPER_H_ #define SIMPLEACTIONHELPER_H_ @@ -6,11 +5,11 @@ class SimpleActionHelper: public ActionHelper { public: - SimpleActionHelper(HasActionsIF* setOwner, MessageQueue* useThisQueue); + SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue); virtual ~SimpleActionHelper(); void step(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); void finish(ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); - void reportData(SerializeIF* data); + ReturnValue_t reportData(SerializeIF* data); void resetHelper(); protected: void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, store_address_t dataAddress); diff --git a/container/ArrayList.h b/container/ArrayList.h index 75917b0a..9c4c4ceb 100644 --- a/container/ArrayList.h +++ b/container/ArrayList.h @@ -17,7 +17,7 @@ template class ArrayList { template friend class SerialArrayListAdapter; public: - static const uint8_t INTERFACE_ID = ARRAY_LIST; + static const uint8_t INTERFACE_ID = CLASS_ID::ARRAY_LIST; static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01); /** @@ -80,13 +80,17 @@ public: return value; } + const T *operator->() const{ + return value; + } + //SHOULDDO this should be implemented as non-member - bool operator==(const typename ArrayList::Iterator& other) { + bool operator==(const typename ArrayList::Iterator& other) const{ return (value == other.value); } //SHOULDDO this should be implemented as non-member - bool operator!=(const typename ArrayList::Iterator& other) { + bool operator!=(const typename ArrayList::Iterator& other) const { return !(*this == other); } } @@ -116,9 +120,10 @@ public: * * @param storage the array to use as backend * @param maxSize size of storage + * @param size size of data already present in storage */ - ArrayList(T *storage, count_t maxSize) : - size(0), entries(storage), maxSize_(maxSize), allocated(false) { + ArrayList(T *storage, count_t maxSize, count_t size = 0) : + size(size), entries(storage), maxSize_(maxSize), allocated(false) { } /** @@ -170,6 +175,12 @@ public: */ T *back() { return &entries[size - 1]; + //Alternative solution + //return const_cast(static_cast(*this).back()); + } + + const T* back() const{ + return &entries[size-1]; } /** @@ -212,11 +223,6 @@ public: count_t remaining() { return (maxSize_ - size); } -protected: - /** - * pointer to the array in which the entries are stored - */ - T *entries; private: /** * This is the copy constructor @@ -230,7 +236,11 @@ private: size(other.size), entries(other.entries), maxSize_(other.maxSize_), allocated( false) { } -private: +protected: + /** + * pointer to the array in which the entries are stored + */ + T *entries; /** * remembering the maximum size */ diff --git a/container/BinaryTree.h b/container/BinaryTree.h index 137c826a..73073dea 100644 --- a/container/BinaryTree.h +++ b/container/BinaryTree.h @@ -1,10 +1,3 @@ -/* - * BinaryTree.h - * - * Created on: 09.03.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_CONTAINER_BINARYTREE_H_ #define FRAMEWORK_CONTAINER_BINARYTREE_H_ @@ -99,9 +92,6 @@ public: } iterator insert(bool insertLeft, iterator parentNode, Node* newNode ) { newNode->parent = parentNode.element; - //TODO: Why do I delete the child references of the node? This kills reconnection :-p -// newNode->left = NULL; -// newNode->right = NULL; if (parentNode.element != NULL) { if (insertLeft) { parentNode.element->left = newNode; diff --git a/container/FIFO.h b/container/FIFO.h index eda853bc..670a50d7 100644 --- a/container/FIFO.h +++ b/container/FIFO.h @@ -54,7 +54,7 @@ public: return HasReturnvaluesIF::RETURN_OK; } } - static const uint8_t INTERFACE_ID = FIFO_CLASS; + static const uint8_t INTERFACE_ID = CLASS_ID::FIFO_CLASS; static const ReturnValue_t FULL = MAKE_RETURN_CODE(1); static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(2); }; diff --git a/container/FixedMap.h b/container/FixedMap.h index 45660859..9b6a1b69 100644 --- a/container/FixedMap.h +++ b/container/FixedMap.h @@ -9,7 +9,7 @@ template class FixedMap: public SerializeIF { public: - static const uint8_t INTERFACE_ID = FIXED_MAP; + static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP; static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01); static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02); static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03); diff --git a/container/FixedOrderedMultimap.h b/container/FixedOrderedMultimap.h index 99a3fbc2..b5df0c3c 100644 --- a/container/FixedOrderedMultimap.h +++ b/container/FixedOrderedMultimap.h @@ -1,10 +1,3 @@ -/* - * FixedOrderedMultimap.h - * - * Created on: 22.01.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ #define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ @@ -15,7 +8,7 @@ template> class FixedOrderedMultimap { public: - static const uint8_t INTERFACE_ID = FIXED_MAP; + static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP; static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01); static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02); static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03); diff --git a/container/IndexedRingMemoryArray.h b/container/IndexedRingMemoryArray.h new file mode 100644 index 00000000..eacfe3e5 --- /dev/null +++ b/container/IndexedRingMemoryArray.h @@ -0,0 +1,700 @@ +#ifndef FRAMEWORK_CONTAINER_INDEXEDRINGMEMORY_H_ +#define FRAMEWORK_CONTAINER_INDEXEDRINGMEMORY_H_ + +#include +#include +#include +#include +#include +#include + +template +class Index: public SerializeIF{ + /** + * Index is the Type used for the list of indices. The template parameter is the type which describes the index, it needs to be a child of SerializeIF to be able to make it persistent + */ + static_assert(std::is_base_of::value,"Wrong Type for Index, Type must implement SerializeIF"); +public: + Index():blockStartAddress(0),size(0),storedPackets(0){} + + Index(uint32_t startAddress):blockStartAddress(startAddress),size(0),storedPackets(0){ + + } + + void setBlockStartAddress(uint32_t newAddress){ + this->blockStartAddress = newAddress; + } + + uint32_t getBlockStartAddress() const { + return blockStartAddress; + } + + const T* getIndexType() const { + return &indexType; + } + + T* modifyIndexType(){ + return &indexType; + } + /** + * Updates the index Type. Uses = operator + * @param indexType Type to copy from + */ + void setIndexType(T* indexType) { + this->indexType = *indexType; + } + + uint32_t getSize() const { + return size; + } + + void setSize(uint32_t size) { + this->size = size; + } + + void addSize(uint32_t size){ + this->size += size; + } + + void setStoredPackets(uint32_t newStoredPackets){ + this->storedPackets = newStoredPackets; + } + + void addStoredPackets(uint32_t packets){ + this->storedPackets += packets; + } + + uint32_t getStoredPackets() const{ + return this->storedPackets; + } + + ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, + const uint32_t max_size, bool bigEndian) const { + ReturnValue_t result = AutoSerializeAdapter::serialize(&blockStartAddress,buffer,size,max_size,bigEndian); + if(result != HasReturnvaluesIF::RETURN_OK){ + return result; + } + result = indexType.serialize(buffer,size,max_size,bigEndian); + if(result != HasReturnvaluesIF::RETURN_OK){ + return result; + } + result = AutoSerializeAdapter::serialize(&this->size,buffer,size,max_size,bigEndian); + if(result != HasReturnvaluesIF::RETURN_OK){ + return result; + } + result = AutoSerializeAdapter::serialize(&this->storedPackets,buffer,size,max_size,bigEndian); + return result; + } + + ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, + bool bigEndian){ + ReturnValue_t result = AutoSerializeAdapter::deSerialize(&blockStartAddress,buffer,size,bigEndian); + if(result != HasReturnvaluesIF::RETURN_OK){ + return result; + } + result = indexType.deSerialize(buffer,size,bigEndian); + if(result != HasReturnvaluesIF::RETURN_OK){ + return result; + } + result = AutoSerializeAdapter::deSerialize(&this->size,buffer,size,bigEndian); + if(result != HasReturnvaluesIF::RETURN_OK){ + return result; + } + result = AutoSerializeAdapter::deSerialize(&this->storedPackets,buffer,size,bigEndian); + if(result != HasReturnvaluesIF::RETURN_OK){ + return result; + } + return result; + } + + uint32_t getSerializedSize() const { + uint32_t size = AutoSerializeAdapter::getSerializedSize(&blockStartAddress); + size += indexType.getSerializedSize(); + size += AutoSerializeAdapter::getSerializedSize(&this->size); + size += AutoSerializeAdapter::getSerializedSize(&this->storedPackets); + return size; + } + + + bool operator==(const Index& other){ + return ((blockStartAddress == other.getBlockStartAddress()) && (size==other.getSize())) && (indexType == *(other.getIndexType())); + } + +private: + uint32_t blockStartAddress; + uint32_t size; + uint32_t storedPackets; + T indexType; +}; + + + +template +class IndexedRingMemoryArray: public SerializeIF, public ArrayList, uint32_t>{ + /** + * Indexed Ring Memory Array is a class for a ring memory with indices. It assumes that the newest data comes in last + * It uses the currentWriteBlock as pointer to the current writing position + * The currentReadBlock must be set manually + */ +public: + IndexedRingMemoryArray(uint32_t startAddress, uint32_t size, uint32_t bytesPerBlock, SerializeIF* additionalInfo, + bool overwriteOld) :ArrayList,uint32_t>(NULL,(uint32_t)10,(uint32_t)0),totalSize(size),indexAddress(startAddress),currentReadSize(0),currentReadBlockSizeCached(0),lastBlockToReadSize(0), additionalInfo(additionalInfo),overwriteOld(overwriteOld){ + + //Calculate the maximum number of indices needed for this blocksize + uint32_t maxNrOfIndices = floor(static_cast(size)/static_cast(bytesPerBlock)); + + //Calculate the Size needeed for the index itself + uint32_t serializedSize = 0; + if(additionalInfo!=NULL){ + serializedSize += additionalInfo->getSerializedSize(); + } + //Size of current iterator type + Index tempIndex; + serializedSize += tempIndex.getSerializedSize(); + + //Add Size of Array + serializedSize += sizeof(uint32_t); //size of array + serializedSize += (tempIndex.getSerializedSize() * maxNrOfIndices); //size of elements + serializedSize += sizeof(uint16_t); //size of crc + + //Calculate new size after index + if(serializedSize > totalSize){ + error << "IndexedRingMemory: Store is too small for index" << std::endl; + } + uint32_t useableSize = totalSize - serializedSize; + //Update the totalSize for calculations + totalSize = useableSize; + + //True StartAddress + uint32_t trueStartAddress = indexAddress + serializedSize; + + //Calculate True number of Blocks and reset size of true Number of Blocks + uint32_t trueNumberOfBlocks = floor(static_cast(totalSize) / static_cast(bytesPerBlock)); + + //allocate memory now + this->entries = new Index[trueNumberOfBlocks]; + this->size = trueNumberOfBlocks; + this->maxSize_ = trueNumberOfBlocks; + this->allocated = true; + + //Check trueNumberOfBlocks + if(trueNumberOfBlocks<1){ + error << "IndexedRingMemory: Invalid Number of Blocks: " << trueNumberOfBlocks; + } + + + + //Fill address into index + uint32_t address = trueStartAddress; + for (typename IndexedRingMemoryArray::Iterator it = this->begin();it!=this->end();++it) { + it->setBlockStartAddress(address); + it->setSize(0); + it->setStoredPackets(0); + address += bytesPerBlock; + } + + + //Initialize iterators + currentWriteBlock = this->begin(); + currentReadBlock = this->begin(); + lastBlockToRead = this->begin(); + + //Check last blockSize + uint32_t lastBlockSize = (trueStartAddress + useableSize) - (this->back()->getBlockStartAddress()); + if((lastBlockSizesize > 1)){ + //remove the last Block so the second last block has more size + this->size -= 1; + debug << "IndexedRingMemory: Last Block is smaller than bytesPerBlock, removed last block" << std::endl; + } + } + + /** + * Resets the whole index, the iterators and executes the given reset function on every index type + * @param typeResetFnc static reset function which accepts a pointer to the index Type + */ + void reset(void (*typeResetFnc)(T*)){ + currentReadBlock = this->begin(); + currentWriteBlock = this->begin(); + lastBlockToRead = this->begin(); + currentReadSize = 0; + currentReadBlockSizeCached = 0; + lastBlockToReadSize = 0; + for(typename IndexedRingMemoryArray::Iterator it = this->begin();it!=this->end();++it){ + it->setSize(0); + it->setStoredPackets(0); + (*typeResetFnc)(it->modifyIndexType()); + } + } + + void resetBlock(typename IndexedRingMemoryArray::Iterator it,void (*typeResetFnc)(T*)){ + it->setSize(0); + it->setStoredPackets(0); + (*typeResetFnc)(it->modifyIndexType()); + } + + /* + * Reading + */ + + void setCurrentReadBlock(typename IndexedRingMemoryArray::Iterator it){ + currentReadBlock = it; + currentReadBlockSizeCached = it->getSize(); + } + + void resetRead(){ + currentReadBlock = this->begin(); + currentReadSize = 0; + currentReadBlockSizeCached = this->begin()->getSize(); + lastBlockToRead = currentWriteBlock; + lastBlockToReadSize = currentWriteBlock->getSize(); + } + /** + * Sets the last block to read to this iterator. + * Can be used to dump until block x + * @param it The iterator for the last read block + */ + void setLastBlockToRead(typename IndexedRingMemoryArray::Iterator it){ + lastBlockToRead = it; + lastBlockToReadSize = it->getSize(); + } + + /** + * Set the read pointer to the first written Block, which is the first non empty block in front of the write block + * Can be the currentWriteBlock as well + */ + void readOldest(){ + resetRead(); + currentReadBlock = getNextNonEmptyBlock(); + currentReadBlockSizeCached = currentReadBlock->getSize(); + + } + + /** + * Sets the current read iterator to the next Block and resets the current read size + * The current size of the block will be cached to avoid race condition between write and read + * If the end of the ring is reached the read pointer will be set to the begin + */ + void readNext(){ + currentReadSize = 0; + if((this->size != 0) && (currentReadBlock.value ==this->back())){ + currentReadBlock = this->begin(); + }else{ + currentReadBlock++; + } + + currentReadBlockSizeCached = currentReadBlock->getSize(); + } + + /** + * Returns the address which is currently read from + * @return Address to read from + */ + uint32_t getCurrentReadAddress() const { + return getAddressOfCurrentReadBlock() + currentReadSize; + } + /** + * Adds readSize to the current size and checks if the read has no more data left and advances the read block + * @param readSize The size that was read + * @return Returns true if the read can go on + */ + bool addReadSize(uint32_t readSize) { + if(currentReadBlock == lastBlockToRead){ + //The current read block is the last to read + if((currentReadSize+readSize) return true + currentReadSize += readSize; + return true; + }else{ + //Reached end of read -> return false + currentReadSize = lastBlockToReadSize; + return false; + } + }else{ + //We are not in the last Block + if((currentReadSize + readSize)::Iterator it(currentReadBlock); + //Search if any block between this and the last block is not empty + for(;it!=lastBlockToRead;++it){ + if(it == this->end()){ + //This is the end, next block is the begin + it = this->begin(); + if(it == lastBlockToRead){ + //Break if the begin is the lastBlockToRead + break; + } + } + if(it->getSize()!=0){ + //This is a non empty block. Go on reading with this block + currentReadBlock = it; + currentReadBlockSizeCached = it->getSize(); + return true; + } + } + //reached lastBlockToRead and every block was empty, check if the last block is also empty + if(lastBlockToReadSize!=0){ + //go on with last Block + currentReadBlock = lastBlockToRead; + currentReadBlockSizeCached = lastBlockToReadSize; + return true; + } + //There is no non empty block left + return false; + } + //Size is larger than 0 + return true; + } + } + } + uint32_t getRemainigSizeOfCurrentReadBlock() const{ + if(currentReadBlock == lastBlockToRead){ + return (lastBlockToReadSize - currentReadSize); + }else{ + return (currentReadBlockSizeCached - currentReadSize); + } + } + + uint32_t getAddressOfCurrentReadBlock() const { + return currentReadBlock->getBlockStartAddress(); + } + + /** + * Gets the next non empty Block after the current write block, + * @return Returns the iterator to the block. If there is non, the current write block is returned + */ + typename IndexedRingMemoryArray::Iterator getNextNonEmptyBlock() const { + for(typename IndexedRingMemoryArray::Iterator it = getNextWrite();it!=currentWriteBlock;++it){ + if(it == this->end()){ + it = this->begin(); + if(it == currentWriteBlock){ + break; + } + } + if(it->getSize()!=0){ + return it; + } + } + return currentWriteBlock; + } + + /** + * Returns a copy of the oldest Index type + * @return Type of Index + */ + T* getOldest(){ + return (getNextNonEmptyBlock()->modifyIndexType()); + } + + + /* + * Writing + */ + uint32_t getAddressOfCurrentWriteBlock() const{ + return currentWriteBlock->getBlockStartAddress(); + } + + uint32_t getSizeOfCurrentWriteBlock() const{ + return currentWriteBlock->getSize(); + } + + uint32_t getCurrentWriteAddress() const{ + return getAddressOfCurrentWriteBlock() + getSizeOfCurrentWriteBlock(); + } + + void clearCurrentWriteBlock(){ + currentWriteBlock->setSize(0); + currentWriteBlock->setStoredPackets(0); + } + + void addCurrentWriteBlock(uint32_t size, uint32_t storedPackets){ + currentWriteBlock->addSize(size); + currentWriteBlock->addStoredPackets(storedPackets); + } + + T* modifyCurrentWriteBlockIndexType(){ + return currentWriteBlock->modifyIndexType(); + } + void updatePreviousWriteSize(uint32_t size, uint32_t storedPackets){ + typename IndexedRingMemoryArray::Iterator it = getPreviousBlock(currentWriteBlock); + it->addSize(size); + it->addStoredPackets(storedPackets); + } + + + /** + * Checks if the block has enough space for sizeToWrite + * @param sizeToWrite The data to be written in the Block + * @return Returns true if size to write is smaller the remaining size of the block + */ + bool hasCurrentWriteBlockEnoughSpace(uint32_t sizeToWrite){ + typename IndexedRingMemoryArray::Iterator next = getNextWrite(); + uint32_t addressOfNextBlock = next->getBlockStartAddress(); + uint32_t availableSize = ((addressOfNextBlock+totalSize) - (getAddressOfCurrentWriteBlock()+getSizeOfCurrentWriteBlock()))%totalSize; + return (sizeToWrite < availableSize); + } + + /** + * Checks if the store is full if overwrite old is false + * @return Returns true if it is writeable and false if not + */ + bool isNextBlockWritable(){ + //First check if this is the end of the list + typename IndexedRingMemoryArray::Iterator next; + next = getNextWrite(); + if((next->getSize()!=0) && (!overwriteOld)){ + return false; + } + return true; + } + + /** + * Updates current write Block Index Type + * @param infoOfNewBlock + */ + void updateCurrentBlock(T* infoOfNewBlock){ + currentWriteBlock->setIndexType(infoOfNewBlock); + } + + + /** + * Succeed to next block, returns FAILED if overwrite is false and the store is full + * @return + */ + ReturnValue_t writeNext(){ + //Check Next Block + if(!isNextBlockWritable()){ + //The Index is full and does not overwrite old + return HasReturnvaluesIF::RETURN_FAILED; + } + //Next block can be written, update Metadata + currentWriteBlock = getNextWrite(); + currentWriteBlock->setSize(0); + currentWriteBlock->setStoredPackets(0); + return HasReturnvaluesIF::RETURN_OK; + } + + /** + * Serializes the Index and calculates the CRC. + * Parameters according to HasSerializeIF + * @param buffer + * @param size + * @param max_size + * @param bigEndian + * @return + */ + ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, + const uint32_t max_size, bool bigEndian) const{ + uint8_t* crcBuffer = *buffer; + uint32_t oldSize = *size; + if(additionalInfo!=NULL){ + additionalInfo->serialize(buffer,size,max_size,bigEndian); + } + ReturnValue_t result = currentWriteBlock->serialize(buffer,size,max_size,bigEndian); + if(result != HasReturnvaluesIF::RETURN_OK){ + return result; + } + result = AutoSerializeAdapter::serialize(&this->size,buffer,size,max_size,bigEndian); + if(result != HasReturnvaluesIF::RETURN_OK){ + return result; + } + + uint32_t i = 0; + while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->size)) { + result = SerializeAdapter >::serialize(&this->entries[i], buffer, size, + max_size, bigEndian); + ++i; + } + if(result != HasReturnvaluesIF::RETURN_OK){ + return result; + } + uint16_t crc = Calculate_CRC(crcBuffer,(*size-oldSize)); + result = AutoSerializeAdapter::serialize(&crc,buffer,size,max_size,bigEndian); + return result; + } + + + /** + * Get the serialized Size of the index + * @return The serialized size of the index + */ + uint32_t getSerializedSize() const { + + uint32_t size = 0; + if(additionalInfo!=NULL){ + size += additionalInfo->getSerializedSize(); + } + size += currentWriteBlock->getSerializedSize(); + size += AutoSerializeAdapter::getSerializedSize(&this->size); + size += (this->entries[0].getSerializedSize()) * this->size; + uint16_t crc = 0; + size += AutoSerializeAdapter::getSerializedSize(&crc); + return size; + } + /** + * DeSerialize the Indexed Ring from a buffer, deSerializes the current write iterator + * CRC Has to be checked before! + * @param buffer + * @param size + * @param bigEndian + * @return + */ + + ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, + bool bigEndian){ + + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + if(additionalInfo!=NULL){ + result = additionalInfo->deSerialize(buffer,size,bigEndian); + } + if(result != HasReturnvaluesIF::RETURN_OK){ + return result; + } + + Index tempIndex; + result = tempIndex.deSerialize(buffer,size,bigEndian); + if(result != HasReturnvaluesIF::RETURN_OK){ + return result; + } + uint32_t tempSize = 0; + result = AutoSerializeAdapter::deSerialize(&tempSize,buffer,size,bigEndian); + if(result != HasReturnvaluesIF::RETURN_OK){ + return result; + } + if(this->size != tempSize){ + return HasReturnvaluesIF::RETURN_FAILED; + } + uint32_t i = 0; + while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->size)) { + result = SerializeAdapter >::deSerialize( + &this->entries[i], buffer, size, + bigEndian); + ++i; + } + if(result != HasReturnvaluesIF::RETURN_OK){ + return result; + } + typename IndexedRingMemoryArray::Iterator cmp(&tempIndex); + for(typename IndexedRingMemoryArray::Iterator it= this->begin();it!=this->end();++it){ + if(*(cmp.value) == *(it.value)){ + currentWriteBlock = it; + return HasReturnvaluesIF::RETURN_OK; + } + } + //Reached if current write block iterator is not found + return HasReturnvaluesIF::RETURN_FAILED; + } + + uint32_t getIndexAddress() const { + return indexAddress; + } + + + /* + * Statistics + */ + uint32_t getStoredPackets() const { + uint32_t size = 0; + for(typename IndexedRingMemoryArray::Iterator it= this->begin();it!=this->end();++it){ + size += it->getStoredPackets(); + } + return size; + } + + uint32_t getTotalSize() const { + return totalSize; + } + + uint32_t getCurrentSize() const{ + uint32_t size = 0; + for(typename IndexedRingMemoryArray::Iterator it= this->begin();it!=this->end();++it){ + size += it->getSize(); + } + return size; + } + + bool isEmpty() const{ + return getCurrentSize()==0; + } + + double getPercentageFilled() const{ + uint32_t filledSize = 0; + for(typename IndexedRingMemoryArray::Iterator it= this->begin();it!=this->end();++it){ + filledSize += it->getSize(); + } + + return (double)filledSize/(double)this->totalSize; + } + + typename IndexedRingMemoryArray::Iterator getCurrentWriteBlock() const{ + return currentWriteBlock; + } + /** + * Get the next block of the currentWriteBlock. + * Returns the first one if currentWriteBlock is the last one + * @return Iterator pointing to the next block after currentWriteBlock + */ + typename IndexedRingMemoryArray::Iterator getNextWrite() const{ + typename IndexedRingMemoryArray::Iterator next(currentWriteBlock); + if((this->size != 0) && (currentWriteBlock.value == this->back())){ + next = this->begin(); + }else{ + ++next; + } + return next; + } + /** + * Get the block in front of the Iterator + * Returns the last block if it is the first block + * @param it iterator which you want the previous block from + * @return pointing to the block before it + */ + typename IndexedRingMemoryArray::Iterator getPreviousBlock(typename IndexedRingMemoryArray::Iterator it) { + if(this->begin() == it){ + typename IndexedRingMemoryArray::Iterator next((this->back())); + return next; + } + typename IndexedRingMemoryArray::Iterator next(it); + --next; + return next; + } +private: + //The total size used by the blocks (without index) + uint32_t totalSize; + + //The address of the index + const uint32_t indexAddress; + + //The iterators for writing and reading + typename IndexedRingMemoryArray::Iterator currentWriteBlock; + typename IndexedRingMemoryArray::Iterator currentReadBlock; + + //How much of the current read block is read already + uint32_t currentReadSize; + + //Cached Size of current read block + uint32_t currentReadBlockSizeCached; + + //Last block of current write (should be write block) + typename IndexedRingMemoryArray::Iterator lastBlockToRead; + //current size of last Block to read + uint32_t lastBlockToReadSize; + + //Additional Info to be serialized with the index + SerializeIF* additionalInfo; + + //Does it overwrite old blocks? + const bool overwriteOld; + +}; + + + + +#endif /* FRAMEWORK_CONTAINER_INDEXEDRINGMEMORY_H_ */ diff --git a/container/LinkedElementDecorator.h b/container/LinkedElementDecorator.h deleted file mode 100644 index 9b7daa20..00000000 --- a/container/LinkedElementDecorator.h +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @file LinkedElementDecorator.h - * @brief This file defines the LinkedElementDecorator class. - * @date 22.07.2014 - * @author baetz - */ -#ifndef LINKEDELEMENTDECORATOR_H_ -#define LINKEDELEMENTDECORATOR_H_ - -#include -#include - -//TODO: This generates multiple inheritance from non-IF parents. -template -class LinkedElementDecorator : public LinkedElement, public T { -public: - template - LinkedElementDecorator(Args... args) : LinkedElement(this), T(std::forward(args)...) { - } - - virtual ~LinkedElementDecorator() { - } -}; - - - -#endif /* LINKEDELEMENTDECORATOR_H_ */ diff --git a/container/PlacementFactory.h b/container/PlacementFactory.h index cc92773e..daf4ee20 100644 --- a/container/PlacementFactory.h +++ b/container/PlacementFactory.h @@ -1,10 +1,3 @@ -/* - * PlacementFactory.h - * - * Created on: 10.03.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_ #define FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_ @@ -30,7 +23,8 @@ public: } template ReturnValue_t destroy(T* thisElement) { - //TODO: Shouldn't we call the destructor here first, in case something was allocated by the object (shouldn't do that, however). + //Need to call destructor first, in case something was allocated by the object (shouldn't do that, however). + thisElement->~T(); uint8_t* pointer = (uint8_t*) (thisElement); return dataBackend->deleteData(pointer, sizeof(T)); } diff --git a/container/RingBufferBase.h b/container/RingBufferBase.h index 2cd23afd..3ef782d8 100644 --- a/container/RingBufferBase.h +++ b/container/RingBufferBase.h @@ -1,10 +1,3 @@ -/* - * RingBufferBase.h - * - * Created on: 06.02.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_ #define FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_ @@ -77,16 +70,16 @@ public: uint32_t readTillWrap(uint8_t n = 0) { return (start + size) - read[n]; } - const uint32_t getStart() const { + uint32_t getStart() const { return start; } - const bool overwritesOld() const { + bool overwritesOld() const { return overwriteOld; } uint32_t maxSize() const { return size - 1; } -private: +protected: const uint32_t start; uint32_t write; uint32_t read[N_READ_PTRS]; diff --git a/container/RingBufferTest.cpp.ignore b/container/RingBufferTest.cpp.ignore new file mode 100644 index 00000000..d660e29c --- /dev/null +++ b/container/RingBufferTest.cpp.ignore @@ -0,0 +1,79 @@ + +#include +#include "SimpleRingBuffer.h" + + +int main() { + using namespace std; + SimpleRingBuffer buffer(64, false); + uint8_t data[8] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}; + ReturnValue_t result = buffer.writeData(data, 8); + if (result != HasReturnvaluesIF::RETURN_OK) { + cout << "writeData failed." << endl; + } + result = buffer.writeData(data, 8); + if (result != HasReturnvaluesIF::RETURN_OK) { + cout << "writeData failed." << endl; + } + uint8_t buffer2[47] = {0}; + for (uint8_t count = 0; count +#include + +SimpleRingBuffer::SimpleRingBuffer(uint32_t size, bool overwriteOld) : + RingBufferBase<>(0, size, overwriteOld), buffer(NULL) { + buffer = new uint8_t[size]; +} + +SimpleRingBuffer::~SimpleRingBuffer() { + delete[] buffer; +} + +ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data, + uint32_t amount) { + if (availableWriteSpace() >= amount || overwriteOld) { + uint32_t amountTillWrap = writeTillWrap(); + if (amountTillWrap >= amount) { + memcpy(&buffer[write], data, amount); + } else { + memcpy(&buffer[write], data, amountTillWrap); + memcpy(buffer, data + amountTillWrap, amount - amountTillWrap); + } + incrementWrite(amount); + return HasReturnvaluesIF::RETURN_OK; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, uint32_t amount, + bool readRemaining, uint32_t* trueAmount) { + uint32_t availableData = availableReadData(READ_PTR); + uint32_t amountTillWrap = readTillWrap(READ_PTR); + if (availableData < amount) { + if (readRemaining) { + amount = availableData; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + if (trueAmount != NULL) { + *trueAmount = amount; + } + if (amountTillWrap >= amount) { + memcpy(data, &buffer[read[READ_PTR]], amount); + } else { + memcpy(data, &buffer[read[READ_PTR]], amountTillWrap); + memcpy(data + amountTillWrap, buffer, amount - amountTillWrap); + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t SimpleRingBuffer::deleteData(uint32_t amount, + bool deleteRemaining, uint32_t* trueAmount) { + uint32_t availableData = availableReadData(READ_PTR); + if (availableData < amount) { + if (deleteRemaining) { + amount = availableData; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + if (trueAmount != NULL) { + *trueAmount = amount; + } + incrementRead(amount, READ_PTR); + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/container/SimpleRingBuffer.h b/container/SimpleRingBuffer.h new file mode 100644 index 00000000..6d7d67e1 --- /dev/null +++ b/container/SimpleRingBuffer.h @@ -0,0 +1,21 @@ +#ifndef FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ +#define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ + +#include +#include + +class SimpleRingBuffer: public RingBufferBase<> { +public: + SimpleRingBuffer(uint32_t size, bool overwriteOld); + virtual ~SimpleRingBuffer(); + ReturnValue_t writeData(const uint8_t* data, uint32_t amount); + ReturnValue_t readData(uint8_t* data, uint32_t amount, bool readRemaining = false, uint32_t* trueAmount = NULL); + ReturnValue_t deleteData(uint32_t amount, bool deleteRemaining = false, uint32_t* trueAmount = NULL); +private: +// static const uint8_t TEMP_READ_PTR = 1; + static const uint8_t READ_PTR = 0; + uint8_t* buffer; +}; + +#endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */ + diff --git a/container/SinglyLinkedList.h b/container/SinglyLinkedList.h index e4b3e8db..fd80a681 100644 --- a/container/SinglyLinkedList.h +++ b/container/SinglyLinkedList.h @@ -49,7 +49,7 @@ public: virtual ~LinkedElement(){ } - virtual LinkedElement* const getNext() const { + virtual LinkedElement* getNext() const { return next; } diff --git a/contrib/sgp4/LICENSE b/contrib/sgp4/LICENSE new file mode 100644 index 00000000..9672956b --- /dev/null +++ b/contrib/sgp4/LICENSE @@ -0,0 +1,4 @@ +There is no license associated with the code and you may use it for any purpose —personal or commercial— as you +wish. We ask only that you include citations in your documentation and source code to show the source of the code +and provide links to https://www.celestrak.com/publications/AIAA/2006-6753/, to facilitate communications +regarding any questions on the theory or source code. \ No newline at end of file diff --git a/contrib/sgp4/sgp4unit.cpp b/contrib/sgp4/sgp4unit.cpp new file mode 100644 index 00000000..24d63aa9 --- /dev/null +++ b/contrib/sgp4/sgp4unit.cpp @@ -0,0 +1,2090 @@ +/* ---------------------------------------------------------------- +* +* sgp4unit.cpp +* +* this file contains the sgp4 procedures for analytical propagation +* of a satellite. the code was originally released in the 1980 and 1986 +* spacetrack papers. a detailed discussion of the theory and history +* may be found in the 2006 aiaa paper by vallado, crawford, hujsak, +* and kelso. +* +* companion code for +* fundamentals of astrodynamics and applications +* 2007 +* by david vallado +* +* (w) 719-573-2600, email dvallado@agi.com +* +* current : +* 16 nov 07 david vallado +* misc fixes for better compliance +* changes : +* 20 apr 07 david vallado +* misc fixes for constants +* 11 aug 06 david vallado +* chg lyddane choice back to strn3, constants, misc doc +* 15 dec 05 david vallado +* misc fixes +* 26 jul 05 david vallado +* fixes for paper +* note that each fix is preceded by a +* comment with "sgp4fix" and an explanation of +* what was changed +* 10 aug 04 david vallado +* 2nd printing baseline working +* 14 may 01 david vallado +* 2nd edition baseline +* 80 norad +* original baseline +* ---------------------------------------------------------------- */ + +#include "sgp4unit.h" + +const char help = 'n'; +FILE *dbgfile; + +#define pi 3.14159265358979323846 + + +/* ----------- local functions - only ever used internally by sgp4 ---------- */ +static void dpper + ( + double e3, double ee2, double peo, double pgho, double pho, + double pinco, double plo, double se2, double se3, double sgh2, + double sgh3, double sgh4, double sh2, double sh3, double si2, + double si3, double sl2, double sl3, double sl4, double t, + double xgh2, double xgh3, double xgh4, double xh2, double xh3, + double xi2, double xi3, double xl2, double xl3, double xl4, + double zmol, double zmos, double inclo, + char init, + double& ep, double& inclp, double& nodep, double& argpp, double& mp + ); + +static void dscom + ( + double epoch, double ep, double argpp, double tc, double inclp, + double nodep, double np, + double& snodm, double& cnodm, double& sinim, double& cosim, double& sinomm, + double& cosomm,double& day, double& e3, double& ee2, double& em, + double& emsq, double& gam, double& peo, double& pgho, double& pho, + double& pinco, double& plo, double& rtemsq, double& se2, double& se3, + double& sgh2, double& sgh3, double& sgh4, double& sh2, double& sh3, + double& si2, double& si3, double& sl2, double& sl3, double& sl4, + double& s1, double& s2, double& s3, double& s4, double& s5, + double& s6, double& s7, double& ss1, double& ss2, double& ss3, + double& ss4, double& ss5, double& ss6, double& ss7, double& sz1, + double& sz2, double& sz3, double& sz11, double& sz12, double& sz13, + double& sz21, double& sz22, double& sz23, double& sz31, double& sz32, + double& sz33, double& xgh2, double& xgh3, double& xgh4, double& xh2, + double& xh3, double& xi2, double& xi3, double& xl2, double& xl3, + double& xl4, double& nm, double& z1, double& z2, double& z3, + double& z11, double& z12, double& z13, double& z21, double& z22, + double& z23, double& z31, double& z32, double& z33, double& zmol, + double& zmos + ); + +static void dsinit + ( + gravconsttype whichconst, + double cosim, double emsq, double argpo, double s1, double s2, + double s3, double s4, double s5, double sinim, double ss1, + double ss2, double ss3, double ss4, double ss5, double sz1, + double sz3, double sz11, double sz13, double sz21, double sz23, + double sz31, double sz33, double t, double tc, double gsto, + double mo, double mdot, double no, double nodeo, double nodedot, + double xpidot, double z1, double z3, double z11, double z13, + double z21, double z23, double z31, double z33, double ecco, + double eccsq, double& em, double& argpm, double& inclm, double& mm, + double& nm, double& nodem, + int& irez, + double& atime, double& d2201, double& d2211, double& d3210, double& d3222, + double& d4410, double& d4422, double& d5220, double& d5232, double& d5421, + double& d5433, double& dedt, double& didt, double& dmdt, double& dndt, + double& dnodt, double& domdt, double& del1, double& del2, double& del3, + double& xfact, double& xlamo, double& xli, double& xni + ); + +static void dspace + ( + int irez, + double d2201, double d2211, double d3210, double d3222, double d4410, + double d4422, double d5220, double d5232, double d5421, double d5433, + double dedt, double del1, double del2, double del3, double didt, + double dmdt, double dnodt, double domdt, double argpo, double argpdot, + double t, double tc, double gsto, double xfact, double xlamo, + double no, + double& atime, double& em, double& argpm, double& inclm, double& xli, + double& mm, double& xni, double& nodem, double& dndt, double& nm + ); + +static void initl + ( + int satn, gravconsttype whichconst, + double ecco, double epoch, double inclo, double& no, + char& method, + double& ainv, double& ao, double& con41, double& con42, double& cosio, + double& cosio2,double& eccsq, double& omeosq, double& posq, + double& rp, double& rteosq,double& sinio , double& gsto + ); + +/* ----------------------------------------------------------------------------- +* +* procedure dpper +* +* this procedure provides deep space long period periodic contributions +* to the mean elements. by design, these periodics are zero at epoch. +* this used to be dscom which included initialization, but it's really a +* recurring function. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* e3 - +* ee2 - +* peo - +* pgho - +* pho - +* pinco - +* plo - +* se2 , se3 , sgh2, sgh3, sgh4, sh2, sh3, si2, si3, sl2, sl3, sl4 - +* t - +* xh2, xh3, xi2, xi3, xl2, xl3, xl4 - +* zmol - +* zmos - +* ep - eccentricity 0.0 - 1.0 +* inclo - inclination - needed for lyddane modification +* nodep - right ascension of ascending node +* argpp - argument of perigee +* mp - mean anomaly +* +* outputs : +* ep - eccentricity 0.0 - 1.0 +* inclp - inclination +* nodep - right ascension of ascending node +* argpp - argument of perigee +* mp - mean anomaly +* +* locals : +* alfdp - +* betdp - +* cosip , sinip , cosop , sinop , +* dalf - +* dbet - +* dls - +* f2, f3 - +* pe - +* pgh - +* ph - +* pinc - +* pl - +* sel , ses , sghl , sghs , shl , shs , sil , sinzf , sis , +* sll , sls +* xls - +* xnoh - +* zf - +* zm - +* +* coupling : +* none. +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void dpper + ( + double e3, double ee2, double peo, double pgho, double pho, + double pinco, double plo, double se2, double se3, double sgh2, + double sgh3, double sgh4, double sh2, double sh3, double si2, + double si3, double sl2, double sl3, double sl4, double t, + double xgh2, double xgh3, double xgh4, double xh2, double xh3, + double xi2, double xi3, double xl2, double xl3, double xl4, + double zmol, double zmos, double inclo, + char init, + double& ep, double& inclp, double& nodep, double& argpp, double& mp + ) +{ + /* --------------------- local variables ------------------------ */ + const double twopi = 2.0 * pi; + double alfdp, betdp, cosip, cosop, dalf, dbet, dls, + f2, f3, pe, pgh, ph, pinc, pl , + sel, ses, sghl, sghs, shll, shs, sil, + sinip, sinop, sinzf, sis, sll, sls, xls, + xnoh, zf, zm, zel, zes, znl, zns; + + /* ---------------------- constants ----------------------------- */ + zns = 1.19459e-5; + zes = 0.01675; + znl = 1.5835218e-4; + zel = 0.05490; + + /* --------------- calculate time varying periodics ----------- */ + zm = zmos + zns * t; + // be sure that the initial call has time set to zero + if (init == 'y') + zm = zmos; + zf = zm + 2.0 * zes * sin(zm); + sinzf = sin(zf); + f2 = 0.5 * sinzf * sinzf - 0.25; + f3 = -0.5 * sinzf * cos(zf); + ses = se2* f2 + se3 * f3; + sis = si2 * f2 + si3 * f3; + sls = sl2 * f2 + sl3 * f3 + sl4 * sinzf; + sghs = sgh2 * f2 + sgh3 * f3 + sgh4 * sinzf; + shs = sh2 * f2 + sh3 * f3; + zm = zmol + znl * t; + if (init == 'y') + zm = zmol; + zf = zm + 2.0 * zel * sin(zm); + sinzf = sin(zf); + f2 = 0.5 * sinzf * sinzf - 0.25; + f3 = -0.5 * sinzf * cos(zf); + sel = ee2 * f2 + e3 * f3; + sil = xi2 * f2 + xi3 * f3; + sll = xl2 * f2 + xl3 * f3 + xl4 * sinzf; + sghl = xgh2 * f2 + xgh3 * f3 + xgh4 * sinzf; + shll = xh2 * f2 + xh3 * f3; + pe = ses + sel; + pinc = sis + sil; + pl = sls + sll; + pgh = sghs + sghl; + ph = shs + shll; + + if (init == 'n') + { + pe = pe - peo; + pinc = pinc - pinco; + pl = pl - plo; + pgh = pgh - pgho; + ph = ph - pho; + inclp = inclp + pinc; + ep = ep + pe; + sinip = sin(inclp); + cosip = cos(inclp); + + /* ----------------- apply periodics directly ------------ */ + // sgp4fix for lyddane choice + // strn3 used original inclination - this is technically feasible + // gsfc used perturbed inclination - also technically feasible + // probably best to readjust the 0.2 limit value and limit discontinuity + // 0.2 rad = 11.45916 deg + // use next line for original strn3 approach and original inclination + // if (inclo >= 0.2) + // use next line for gsfc version and perturbed inclination + if (inclp >= 0.2) + { + ph = ph / sinip; + pgh = pgh - cosip * ph; + argpp = argpp + pgh; + nodep = nodep + ph; + mp = mp + pl; + } + else + { + /* ---- apply periodics with lyddane modification ---- */ + sinop = sin(nodep); + cosop = cos(nodep); + alfdp = sinip * sinop; + betdp = sinip * cosop; + dalf = ph * cosop + pinc * cosip * sinop; + dbet = -ph * sinop + pinc * cosip * cosop; + alfdp = alfdp + dalf; + betdp = betdp + dbet; + nodep = fmod(nodep, twopi); + // sgp4fix for afspc written intrinsic functions + // nodep used without a trigonometric function ahead + if (nodep < 0.0) + nodep = nodep + twopi; + xls = mp + argpp + cosip * nodep; + dls = pl + pgh - pinc * nodep * sinip; + xls = xls + dls; + xnoh = nodep; + nodep = atan2(alfdp, betdp); + // sgp4fix for afspc written intrinsic functions + // nodep used without a trigonometric function ahead + if (nodep < 0.0) + nodep = nodep + twopi; + if (fabs(xnoh - nodep) > pi){ + if (nodep < xnoh) + nodep = nodep + twopi; + else + nodep = nodep - twopi; + } + mp = mp + pl; + argpp = xls - mp - cosip * nodep; + } + } // if init == 'n' + +//#include "debug1.cpp" +} // end dpper + +/*----------------------------------------------------------------------------- +* +* procedure dscom +* +* this procedure provides deep space common items used by both the secular +* and periodics subroutines. input is provided as shown. this routine +* used to be called dpper, but the functions inside weren't well organized. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* epoch - +* ep - eccentricity +* argpp - argument of perigee +* tc - +* inclp - inclination +* nodep - right ascension of ascending node +* np - mean motion +* +* outputs : +* sinim , cosim , sinomm , cosomm , snodm , cnodm +* day - +* e3 - +* ee2 - +* em - eccentricity +* emsq - eccentricity squared +* gam - +* peo - +* pgho - +* pho - +* pinco - +* plo - +* rtemsq - +* se2, se3 - +* sgh2, sgh3, sgh4 - +* sh2, sh3, si2, si3, sl2, sl3, sl4 - +* s1, s2, s3, s4, s5, s6, s7 - +* ss1, ss2, ss3, ss4, ss5, ss6, ss7, sz1, sz2, sz3 - +* sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33 - +* xgh2, xgh3, xgh4, xh2, xh3, xi2, xi3, xl2, xl3, xl4 - +* nm - mean motion +* z1, z2, z3, z11, z12, z13, z21, z22, z23, z31, z32, z33 - +* zmol - +* zmos - +* +* locals : +* a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 - +* betasq - +* cc - +* ctem, stem - +* x1, x2, x3, x4, x5, x6, x7, x8 - +* xnodce - +* xnoi - +* zcosg , zsing , zcosgl , zsingl , zcosh , zsinh , zcoshl , zsinhl , +* zcosi , zsini , zcosil , zsinil , +* zx - +* zy - +* +* coupling : +* none. +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void dscom + ( + double epoch, double ep, double argpp, double tc, double inclp, + double nodep, double np, + double& snodm, double& cnodm, double& sinim, double& cosim, double& sinomm, + double& cosomm,double& day, double& e3, double& ee2, double& em, + double& emsq, double& gam, double& peo, double& pgho, double& pho, + double& pinco, double& plo, double& rtemsq, double& se2, double& se3, + double& sgh2, double& sgh3, double& sgh4, double& sh2, double& sh3, + double& si2, double& si3, double& sl2, double& sl3, double& sl4, + double& s1, double& s2, double& s3, double& s4, double& s5, + double& s6, double& s7, double& ss1, double& ss2, double& ss3, + double& ss4, double& ss5, double& ss6, double& ss7, double& sz1, + double& sz2, double& sz3, double& sz11, double& sz12, double& sz13, + double& sz21, double& sz22, double& sz23, double& sz31, double& sz32, + double& sz33, double& xgh2, double& xgh3, double& xgh4, double& xh2, + double& xh3, double& xi2, double& xi3, double& xl2, double& xl3, + double& xl4, double& nm, double& z1, double& z2, double& z3, + double& z11, double& z12, double& z13, double& z21, double& z22, + double& z23, double& z31, double& z32, double& z33, double& zmol, + double& zmos + ) +{ + /* -------------------------- constants ------------------------- */ + const double zes = 0.01675; + const double zel = 0.05490; + const double c1ss = 2.9864797e-6; + const double c1l = 4.7968065e-7; + const double zsinis = 0.39785416; + const double zcosis = 0.91744867; + const double zcosgs = 0.1945905; + const double zsings = -0.98088458; + const double twopi = 2.0 * pi; + + /* --------------------- local variables ------------------------ */ + int lsflg; + double a1 , a2 , a3 , a4 , a5 , a6 , a7 , + a8 , a9 , a10 , betasq, cc , ctem , stem , + x1 , x2 , x3 , x4 , x5 , x6 , x7 , + x8 , xnodce, xnoi , zcosg , zcosgl, zcosh , zcoshl, + zcosi , zcosil, zsing , zsingl, zsinh , zsinhl, zsini , + zsinil, zx , zy; + + nm = np; + em = ep; + snodm = sin(nodep); + cnodm = cos(nodep); + sinomm = sin(argpp); + cosomm = cos(argpp); + sinim = sin(inclp); + cosim = cos(inclp); + emsq = em * em; + betasq = 1.0 - emsq; + rtemsq = sqrt(betasq); + + /* ----------------- initialize lunar solar terms --------------- */ + peo = 0.0; + pinco = 0.0; + plo = 0.0; + pgho = 0.0; + pho = 0.0; + day = epoch + 18261.5 + tc / 1440.0; + xnodce = fmod(4.5236020 - 9.2422029e-4 * day, twopi); + stem = sin(xnodce); + ctem = cos(xnodce); + zcosil = 0.91375164 - 0.03568096 * ctem; + zsinil = sqrt(1.0 - zcosil * zcosil); + zsinhl = 0.089683511 * stem / zsinil; + zcoshl = sqrt(1.0 - zsinhl * zsinhl); + gam = 5.8351514 + 0.0019443680 * day; + zx = 0.39785416 * stem / zsinil; + zy = zcoshl * ctem + 0.91744867 * zsinhl * stem; + zx = atan2(zx, zy); + zx = gam + zx - xnodce; + zcosgl = cos(zx); + zsingl = sin(zx); + + /* ------------------------- do solar terms --------------------- */ + zcosg = zcosgs; + zsing = zsings; + zcosi = zcosis; + zsini = zsinis; + zcosh = cnodm; + zsinh = snodm; + cc = c1ss; + xnoi = 1.0 / nm; + + for (lsflg = 1; lsflg <= 2; lsflg++) + { + a1 = zcosg * zcosh + zsing * zcosi * zsinh; + a3 = -zsing * zcosh + zcosg * zcosi * zsinh; + a7 = -zcosg * zsinh + zsing * zcosi * zcosh; + a8 = zsing * zsini; + a9 = zsing * zsinh + zcosg * zcosi * zcosh; + a10 = zcosg * zsini; + a2 = cosim * a7 + sinim * a8; + a4 = cosim * a9 + sinim * a10; + a5 = -sinim * a7 + cosim * a8; + a6 = -sinim * a9 + cosim * a10; + + x1 = a1 * cosomm + a2 * sinomm; + x2 = a3 * cosomm + a4 * sinomm; + x3 = -a1 * sinomm + a2 * cosomm; + x4 = -a3 * sinomm + a4 * cosomm; + x5 = a5 * sinomm; + x6 = a6 * sinomm; + x7 = a5 * cosomm; + x8 = a6 * cosomm; + + z31 = 12.0 * x1 * x1 - 3.0 * x3 * x3; + z32 = 24.0 * x1 * x2 - 6.0 * x3 * x4; + z33 = 12.0 * x2 * x2 - 3.0 * x4 * x4; + z1 = 3.0 * (a1 * a1 + a2 * a2) + z31 * emsq; + z2 = 6.0 * (a1 * a3 + a2 * a4) + z32 * emsq; + z3 = 3.0 * (a3 * a3 + a4 * a4) + z33 * emsq; + z11 = -6.0 * a1 * a5 + emsq * (-24.0 * x1 * x7-6.0 * x3 * x5); + z12 = -6.0 * (a1 * a6 + a3 * a5) + emsq * + (-24.0 * (x2 * x7 + x1 * x8) - 6.0 * (x3 * x6 + x4 * x5)); + z13 = -6.0 * a3 * a6 + emsq * (-24.0 * x2 * x8 - 6.0 * x4 * x6); + z21 = 6.0 * a2 * a5 + emsq * (24.0 * x1 * x5 - 6.0 * x3 * x7); + z22 = 6.0 * (a4 * a5 + a2 * a6) + emsq * + (24.0 * (x2 * x5 + x1 * x6) - 6.0 * (x4 * x7 + x3 * x8)); + z23 = 6.0 * a4 * a6 + emsq * (24.0 * x2 * x6 - 6.0 * x4 * x8); + z1 = z1 + z1 + betasq * z31; + z2 = z2 + z2 + betasq * z32; + z3 = z3 + z3 + betasq * z33; + s3 = cc * xnoi; + s2 = -0.5 * s3 / rtemsq; + s4 = s3 * rtemsq; + s1 = -15.0 * em * s4; + s5 = x1 * x3 + x2 * x4; + s6 = x2 * x3 + x1 * x4; + s7 = x2 * x4 - x1 * x3; + + /* ----------------------- do lunar terms ------------------- */ + if (lsflg == 1) + { + ss1 = s1; + ss2 = s2; + ss3 = s3; + ss4 = s4; + ss5 = s5; + ss6 = s6; + ss7 = s7; + sz1 = z1; + sz2 = z2; + sz3 = z3; + sz11 = z11; + sz12 = z12; + sz13 = z13; + sz21 = z21; + sz22 = z22; + sz23 = z23; + sz31 = z31; + sz32 = z32; + sz33 = z33; + zcosg = zcosgl; + zsing = zsingl; + zcosi = zcosil; + zsini = zsinil; + zcosh = zcoshl * cnodm + zsinhl * snodm; + zsinh = snodm * zcoshl - cnodm * zsinhl; + cc = c1l; + } + } + + zmol = fmod(4.7199672 + 0.22997150 * day - gam, twopi); + zmos = fmod(6.2565837 + 0.017201977 * day, twopi); + + /* ------------------------ do solar terms ---------------------- */ + se2 = 2.0 * ss1 * ss6; + se3 = 2.0 * ss1 * ss7; + si2 = 2.0 * ss2 * sz12; + si3 = 2.0 * ss2 * (sz13 - sz11); + sl2 = -2.0 * ss3 * sz2; + sl3 = -2.0 * ss3 * (sz3 - sz1); + sl4 = -2.0 * ss3 * (-21.0 - 9.0 * emsq) * zes; + sgh2 = 2.0 * ss4 * sz32; + sgh3 = 2.0 * ss4 * (sz33 - sz31); + sgh4 = -18.0 * ss4 * zes; + sh2 = -2.0 * ss2 * sz22; + sh3 = -2.0 * ss2 * (sz23 - sz21); + + /* ------------------------ do lunar terms ---------------------- */ + ee2 = 2.0 * s1 * s6; + e3 = 2.0 * s1 * s7; + xi2 = 2.0 * s2 * z12; + xi3 = 2.0 * s2 * (z13 - z11); + xl2 = -2.0 * s3 * z2; + xl3 = -2.0 * s3 * (z3 - z1); + xl4 = -2.0 * s3 * (-21.0 - 9.0 * emsq) * zel; + xgh2 = 2.0 * s4 * z32; + xgh3 = 2.0 * s4 * (z33 - z31); + xgh4 = -18.0 * s4 * zel; + xh2 = -2.0 * s2 * z22; + xh3 = -2.0 * s2 * (z23 - z21); + +//#include "debug2.cpp" +} // end dscom + +/*----------------------------------------------------------------------------- +* +* procedure dsinit +* +* this procedure provides deep space contributions to mean motion dot due +* to geopotential resonance with half day and one day orbits. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* cosim, sinim- +* emsq - eccentricity squared +* argpo - argument of perigee +* s1, s2, s3, s4, s5 - +* ss1, ss2, ss3, ss4, ss5 - +* sz1, sz3, sz11, sz13, sz21, sz23, sz31, sz33 - +* t - time +* tc - +* gsto - greenwich sidereal time rad +* mo - mean anomaly +* mdot - mean anomaly dot (rate) +* no - mean motion +* nodeo - right ascension of ascending node +* nodedot - right ascension of ascending node dot (rate) +* xpidot - +* z1, z3, z11, z13, z21, z23, z31, z33 - +* eccm - eccentricity +* argpm - argument of perigee +* inclm - inclination +* mm - mean anomaly +* xn - mean motion +* nodem - right ascension of ascending node +* +* outputs : +* em - eccentricity +* argpm - argument of perigee +* inclm - inclination +* mm - mean anomaly +* nm - mean motion +* nodem - right ascension of ascending node +* irez - flag for resonance 0-none, 1-one day, 2-half day +* atime - +* d2201, d2211, d3210, d3222, d4410, d4422, d5220, d5232, d5421, d5433 - +* dedt - +* didt - +* dmdt - +* dndt - +* dnodt - +* domdt - +* del1, del2, del3 - +* ses , sghl , sghs , sgs , shl , shs , sis , sls +* theta - +* xfact - +* xlamo - +* xli - +* xni +* +* locals : +* ainv2 - +* aonv - +* cosisq - +* eoc - +* f220, f221, f311, f321, f322, f330, f441, f442, f522, f523, f542, f543 - +* g200, g201, g211, g300, g310, g322, g410, g422, g520, g521, g532, g533 - +* sini2 - +* temp - +* temp1 - +* theta - +* xno2 - +* +* coupling : +* getgravconst +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void dsinit + ( + gravconsttype whichconst, + double cosim, double emsq, double argpo, double s1, double s2, + double s3, double s4, double s5, double sinim, double ss1, + double ss2, double ss3, double ss4, double ss5, double sz1, + double sz3, double sz11, double sz13, double sz21, double sz23, + double sz31, double sz33, double t, double tc, double gsto, + double mo, double mdot, double no, double nodeo, double nodedot, + double xpidot, double z1, double z3, double z11, double z13, + double z21, double z23, double z31, double z33, double ecco, + double eccsq, double& em, double& argpm, double& inclm, double& mm, + double& nm, double& nodem, + int& irez, + double& atime, double& d2201, double& d2211, double& d3210, double& d3222, + double& d4410, double& d4422, double& d5220, double& d5232, double& d5421, + double& d5433, double& dedt, double& didt, double& dmdt, double& dndt, + double& dnodt, double& domdt, double& del1, double& del2, double& del3, + double& xfact, double& xlamo, double& xli, double& xni + ) +{ + /* --------------------- local variables ------------------------ */ + const double twopi = 2.0 * pi; + + double ainv2 , aonv=0.0, cosisq, eoc, f220 , f221 , f311 , + f321 , f322 , f330 , f441 , f442 , f522 , f523 , + f542 , f543 , g200 , g201 , g211 , g300 , g310 , + g322 , g410 , g422 , g520 , g521 , g532 , g533 , + ses , sgs , sghl , sghs , shs , shll , sis , + sini2 , sls , temp , temp1 , theta , xno2 , q22 , + q31 , q33 , root22, root44, root54, rptim , root32, + root52, x2o3 , xke , znl , emo , zns , emsqo, + tumin, mu, radiusearthkm, j2, j3, j4, j3oj2; + + q22 = 1.7891679e-6; + q31 = 2.1460748e-6; + q33 = 2.2123015e-7; + root22 = 1.7891679e-6; + root44 = 7.3636953e-9; + root54 = 2.1765803e-9; + rptim = 4.37526908801129966e-3; // this equates to 7.29211514668855e-5 rad/sec + root32 = 3.7393792e-7; + root52 = 1.1428639e-7; + x2o3 = 2.0 / 3.0; + znl = 1.5835218e-4; + zns = 1.19459e-5; + + // sgp4fix identify constants and allow alternate values + getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); + + /* -------------------- deep space initialization ------------ */ + irez = 0; + if ((nm < 0.0052359877) && (nm > 0.0034906585)) + irez = 1; + if ((nm >= 8.26e-3) && (nm <= 9.24e-3) && (em >= 0.5)) + irez = 2; + + /* ------------------------ do solar terms ------------------- */ + ses = ss1 * zns * ss5; + sis = ss2 * zns * (sz11 + sz13); + sls = -zns * ss3 * (sz1 + sz3 - 14.0 - 6.0 * emsq); + sghs = ss4 * zns * (sz31 + sz33 - 6.0); + shs = -zns * ss2 * (sz21 + sz23); + // sgp4fix for 180 deg incl + if ((inclm < 5.2359877e-2) || (inclm > pi - 5.2359877e-2)) + shs = 0.0; + if (sinim != 0.0) + shs = shs / sinim; + sgs = sghs - cosim * shs; + + /* ------------------------- do lunar terms ------------------ */ + dedt = ses + s1 * znl * s5; + didt = sis + s2 * znl * (z11 + z13); + dmdt = sls - znl * s3 * (z1 + z3 - 14.0 - 6.0 * emsq); + sghl = s4 * znl * (z31 + z33 - 6.0); + shll = -znl * s2 * (z21 + z23); + // sgp4fix for 180 deg incl + if ((inclm < 5.2359877e-2) || (inclm > pi - 5.2359877e-2)) + shll = 0.0; + domdt = sgs + sghl; + dnodt = shs; + if (sinim != 0.0) + { + domdt = domdt - cosim / sinim * shll; + dnodt = dnodt + shll / sinim; + } + + /* ----------- calculate deep space resonance effects -------- */ + dndt = 0.0; + theta = fmod(gsto + tc * rptim, twopi); + em = em + dedt * t; + inclm = inclm + didt * t; + argpm = argpm + domdt * t; + nodem = nodem + dnodt * t; + mm = mm + dmdt * t; + // sgp4fix for negative inclinations + // the following if statement should be commented out + //if (inclm < 0.0) + // { + // inclm = -inclm; + // argpm = argpm - pi; + // nodem = nodem + pi; + // } + + /* -------------- initialize the resonance terms ------------- */ + if (irez != 0) + { + aonv = pow(nm / xke, x2o3); + + /* ---------- geopotential resonance for 12 hour orbits ------ */ + if (irez == 2) + { + cosisq = cosim * cosim; + emo = em; + em = ecco; + emsqo = emsq; + emsq = eccsq; + eoc = em * emsq; + g201 = -0.306 - (em - 0.64) * 0.440; + + if (em <= 0.65) + { + g211 = 3.616 - 13.2470 * em + 16.2900 * emsq; + g310 = -19.302 + 117.3900 * em - 228.4190 * emsq + 156.5910 * eoc; + g322 = -18.9068 + 109.7927 * em - 214.6334 * emsq + 146.5816 * eoc; + g410 = -41.122 + 242.6940 * em - 471.0940 * emsq + 313.9530 * eoc; + g422 = -146.407 + 841.8800 * em - 1629.014 * emsq + 1083.4350 * eoc; + g520 = -532.114 + 3017.977 * em - 5740.032 * emsq + 3708.2760 * eoc; + } + else + { + g211 = -72.099 + 331.819 * em - 508.738 * emsq + 266.724 * eoc; + g310 = -346.844 + 1582.851 * em - 2415.925 * emsq + 1246.113 * eoc; + g322 = -342.585 + 1554.908 * em - 2366.899 * emsq + 1215.972 * eoc; + g410 = -1052.797 + 4758.686 * em - 7193.992 * emsq + 3651.957 * eoc; + g422 = -3581.690 + 16178.110 * em - 24462.770 * emsq + 12422.520 * eoc; + if (em > 0.715) + g520 =-5149.66 + 29936.92 * em - 54087.36 * emsq + 31324.56 * eoc; + else + g520 = 1464.74 - 4664.75 * em + 3763.64 * emsq; + } + if (em < 0.7) + { + g533 = -919.22770 + 4988.6100 * em - 9064.7700 * emsq + 5542.21 * eoc; + g521 = -822.71072 + 4568.6173 * em - 8491.4146 * emsq + 5337.524 * eoc; + g532 = -853.66600 + 4690.2500 * em - 8624.7700 * emsq + 5341.4 * eoc; + } + else + { + g533 =-37995.780 + 161616.52 * em - 229838.20 * emsq + 109377.94 * eoc; + g521 =-51752.104 + 218913.95 * em - 309468.16 * emsq + 146349.42 * eoc; + g532 =-40023.880 + 170470.89 * em - 242699.48 * emsq + 115605.82 * eoc; + } + + sini2= sinim * sinim; + f220 = 0.75 * (1.0 + 2.0 * cosim+cosisq); + f221 = 1.5 * sini2; + f321 = 1.875 * sinim * (1.0 - 2.0 * cosim - 3.0 * cosisq); + f322 = -1.875 * sinim * (1.0 + 2.0 * cosim - 3.0 * cosisq); + f441 = 35.0 * sini2 * f220; + f442 = 39.3750 * sini2 * sini2; + f522 = 9.84375 * sinim * (sini2 * (1.0 - 2.0 * cosim- 5.0 * cosisq) + + 0.33333333 * (-2.0 + 4.0 * cosim + 6.0 * cosisq) ); + f523 = sinim * (4.92187512 * sini2 * (-2.0 - 4.0 * cosim + + 10.0 * cosisq) + 6.56250012 * (1.0+2.0 * cosim - 3.0 * cosisq)); + f542 = 29.53125 * sinim * (2.0 - 8.0 * cosim+cosisq * + (-12.0 + 8.0 * cosim + 10.0 * cosisq)); + f543 = 29.53125 * sinim * (-2.0 - 8.0 * cosim+cosisq * + (12.0 + 8.0 * cosim - 10.0 * cosisq)); + xno2 = nm * nm; + ainv2 = aonv * aonv; + temp1 = 3.0 * xno2 * ainv2; + temp = temp1 * root22; + d2201 = temp * f220 * g201; + d2211 = temp * f221 * g211; + temp1 = temp1 * aonv; + temp = temp1 * root32; + d3210 = temp * f321 * g310; + d3222 = temp * f322 * g322; + temp1 = temp1 * aonv; + temp = 2.0 * temp1 * root44; + d4410 = temp * f441 * g410; + d4422 = temp * f442 * g422; + temp1 = temp1 * aonv; + temp = temp1 * root52; + d5220 = temp * f522 * g520; + d5232 = temp * f523 * g532; + temp = 2.0 * temp1 * root54; + d5421 = temp * f542 * g521; + d5433 = temp * f543 * g533; + xlamo = fmod(mo + nodeo + nodeo-theta - theta, twopi); + xfact = mdot + dmdt + 2.0 * (nodedot + dnodt - rptim) - no; + em = emo; + emsq = emsqo; + } + + /* ---------------- synchronous resonance terms -------------- */ + if (irez == 1) + { + g200 = 1.0 + emsq * (-2.5 + 0.8125 * emsq); + g310 = 1.0 + 2.0 * emsq; + g300 = 1.0 + emsq * (-6.0 + 6.60937 * emsq); + f220 = 0.75 * (1.0 + cosim) * (1.0 + cosim); + f311 = 0.9375 * sinim * sinim * (1.0 + 3.0 * cosim) - 0.75 * (1.0 + cosim); + f330 = 1.0 + cosim; + f330 = 1.875 * f330 * f330 * f330; + del1 = 3.0 * nm * nm * aonv * aonv; + del2 = 2.0 * del1 * f220 * g200 * q22; + del3 = 3.0 * del1 * f330 * g300 * q33 * aonv; + del1 = del1 * f311 * g310 * q31 * aonv; + xlamo = fmod(mo + nodeo + argpo - theta, twopi); + xfact = mdot + xpidot - rptim + dmdt + domdt + dnodt - no; + } + + /* ------------ for sgp4, initialize the integrator ---------- */ + xli = xlamo; + xni = no; + atime = 0.0; + nm = no + dndt; + } + +//#include "debug3.cpp" +} // end dsinit + +/*----------------------------------------------------------------------------- +* +* procedure dspace +* +* this procedure provides deep space contributions to mean elements for +* perturbing third body. these effects have been averaged over one +* revolution of the sun and moon. for earth resonance effects, the +* effects have been averaged over no revolutions of the satellite. +* (mean motion) +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* d2201, d2211, d3210, d3222, d4410, d4422, d5220, d5232, d5421, d5433 - +* dedt - +* del1, del2, del3 - +* didt - +* dmdt - +* dnodt - +* domdt - +* irez - flag for resonance 0-none, 1-one day, 2-half day +* argpo - argument of perigee +* argpdot - argument of perigee dot (rate) +* t - time +* tc - +* gsto - gst +* xfact - +* xlamo - +* no - mean motion +* atime - +* em - eccentricity +* ft - +* argpm - argument of perigee +* inclm - inclination +* xli - +* mm - mean anomaly +* xni - mean motion +* nodem - right ascension of ascending node +* +* outputs : +* atime - +* em - eccentricity +* argpm - argument of perigee +* inclm - inclination +* xli - +* mm - mean anomaly +* xni - +* nodem - right ascension of ascending node +* dndt - +* nm - mean motion +* +* locals : +* delt - +* ft - +* theta - +* x2li - +* x2omi - +* xl - +* xldot - +* xnddt - +* xndt - +* xomi - +* +* coupling : +* none - +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void dspace + ( + int irez, + double d2201, double d2211, double d3210, double d3222, double d4410, + double d4422, double d5220, double d5232, double d5421, double d5433, + double dedt, double del1, double del2, double del3, double didt, + double dmdt, double dnodt, double domdt, double argpo, double argpdot, + double t, double tc, double gsto, double xfact, double xlamo, + double no, + double& atime, double& em, double& argpm, double& inclm, double& xli, + double& mm, double& xni, double& nodem, double& dndt, double& nm + ) +{ + const double twopi = 2.0 * pi; + int iretn , iret; + double delt, ft, theta, x2li, x2omi, xl, xldot , xnddt, xndt, xomi, g22, g32, + g44, g52, g54, fasx2, fasx4, fasx6, rptim , step2, stepn , stepp; + + ft = 0.0; + fasx2 = 0.13130908; + fasx4 = 2.8843198; + fasx6 = 0.37448087; + g22 = 5.7686396; + g32 = 0.95240898; + g44 = 1.8014998; + g52 = 1.0508330; + g54 = 4.4108898; + rptim = 4.37526908801129966e-3; // this equates to 7.29211514668855e-5 rad/sec + stepp = 720.0; + stepn = -720.0; + step2 = 259200.0; + + /* ----------- calculate deep space resonance effects ----------- */ + dndt = 0.0; + theta = fmod(gsto + tc * rptim, twopi); + em = em + dedt * t; + + inclm = inclm + didt * t; + argpm = argpm + domdt * t; + nodem = nodem + dnodt * t; + mm = mm + dmdt * t; + + // sgp4fix for negative inclinations + // the following if statement should be commented out + // if (inclm < 0.0) + // { + // inclm = -inclm; + // argpm = argpm - pi; + // nodem = nodem + pi; + // } + + /* - update resonances : numerical (euler-maclaurin) integration - */ + /* ------------------------- epoch restart ---------------------- */ + // sgp4fix for propagator problems + // the following integration works for negative time steps and periods + // the specific changes are unknown because the original code was so convoluted + + ft = 0.0; + atime = 0.0; + if (irez != 0) + { + if ((atime == 0.0) || ((t >= 0.0) && (atime < 0.0)) || + ((t < 0.0) && (atime >= 0.0))) + { + if (t >= 0.0) + delt = stepp; + else + delt = stepn; + atime = 0.0; + xni = no; + xli = xlamo; + } + iretn = 381; // added for do loop + iret = 0; // added for loop + while (iretn == 381) + { + if ((fabs(t) < fabs(atime)) || (iret == 351)) + { + if (t >= 0.0) + delt = stepn; + else + delt = stepp; + iret = 351; + iretn = 381; + } + else + { + if (t > 0.0) // error if prev if has atime:=0.0 and t:=0.0 (ge) + delt = stepp; + else + delt = stepn; + if (fabs(t - atime) >= stepp) + { + iret = 0; + iretn = 381; + } + else + { + ft = t - atime; + iretn = 0; + } + } + + /* ------------------- dot terms calculated ------------- */ + /* ----------- near - synchronous resonance terms ------- */ + if (irez != 2) + { + xndt = del1 * sin(xli - fasx2) + del2 * sin(2.0 * (xli - fasx4)) + + del3 * sin(3.0 * (xli - fasx6)); + xldot = xni + xfact; + xnddt = del1 * cos(xli - fasx2) + + 2.0 * del2 * cos(2.0 * (xli - fasx4)) + + 3.0 * del3 * cos(3.0 * (xli - fasx6)); + xnddt = xnddt * xldot; + } + else + { + /* --------- near - half-day resonance terms -------- */ + xomi = argpo + argpdot * atime; + x2omi = xomi + xomi; + x2li = xli + xli; + xndt = d2201 * sin(x2omi + xli - g22) + d2211 * sin(xli - g22) + + d3210 * sin(xomi + xli - g32) + d3222 * sin(-xomi + xli - g32)+ + d4410 * sin(x2omi + x2li - g44)+ d4422 * sin(x2li - g44) + + d5220 * sin(xomi + xli - g52) + d5232 * sin(-xomi + xli - g52)+ + d5421 * sin(xomi + x2li - g54) + d5433 * sin(-xomi + x2li - g54); + xldot = xni + xfact; + xnddt = d2201 * cos(x2omi + xli - g22) + d2211 * cos(xli - g22) + + d3210 * cos(xomi + xli - g32) + d3222 * cos(-xomi + xli - g32) + + d5220 * cos(xomi + xli - g52) + d5232 * cos(-xomi + xli - g52) + + 2.0 * (d4410 * cos(x2omi + x2li - g44) + + d4422 * cos(x2li - g44) + d5421 * cos(xomi + x2li - g54) + + d5433 * cos(-xomi + x2li - g54)); + xnddt = xnddt * xldot; + } + + /* ----------------------- integrator ------------------- */ + if (iretn == 381) + { + xli = xli + xldot * delt + xndt * step2; + xni = xni + xndt * delt + xnddt * step2; + atime = atime + delt; + } + } // while iretn = 381 + + nm = xni + xndt * ft + xnddt * ft * ft * 0.5; + xl = xli + xldot * ft + xndt * ft * ft * 0.5; + if (irez != 1) + { + mm = xl - 2.0 * nodem + 2.0 * theta; + dndt = nm - no; + } + else + { + mm = xl - nodem - argpm + theta; + dndt = nm - no; + } + nm = no + dndt; + } + +//#include "debug4.cpp" +} // end dsspace + +/*----------------------------------------------------------------------------- +* +* procedure initl +* +* this procedure initializes the spg4 propagator. all the initialization is +* consolidated here instead of having multiple loops inside other routines. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* ecco - eccentricity 0.0 - 1.0 +* epoch - epoch time in days from jan 0, 1950. 0 hr +* inclo - inclination of satellite +* no - mean motion of satellite +* satn - satellite number +* +* outputs : +* ainv - 1.0 / a +* ao - semi major axis +* con41 - +* con42 - 1.0 - 5.0 cos(i) +* cosio - cosine of inclination +* cosio2 - cosio squared +* eccsq - eccentricity squared +* method - flag for deep space 'd', 'n' +* omeosq - 1.0 - ecco * ecco +* posq - semi-parameter squared +* rp - radius of perigee +* rteosq - square root of (1.0 - ecco*ecco) +* sinio - sine of inclination +* gsto - gst at time of observation rad +* no - mean motion of satellite +* +* locals : +* ak - +* d1 - +* del - +* adel - +* po - +* +* coupling : +* getgravconst +* gstime - find greenwich sidereal time from the julian date +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void initl + ( + int satn, gravconsttype whichconst, + double ecco, double epoch, double inclo, double& no, + char& method, + double& ainv, double& ao, double& con41, double& con42, double& cosio, + double& cosio2,double& eccsq, double& omeosq, double& posq, + double& rp, double& rteosq,double& sinio , double& gsto + ) +{ + /* --------------------- local variables ------------------------ */ + double ak, d1, del, adel, po, x2o3, j2, xke, + tumin, mu, radiusearthkm, j3, j4, j3oj2; + + // sgp4fix use old way of finding gst + int ids70; + double ts70, ds70, tfrac, c1, thgr70, fk5r, c1p2p; + const double twopi = 2.0 * pi; + + /* ----------------------- earth constants ---------------------- */ + // sgp4fix identify constants and allow alternate values + getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); + x2o3 = 2.0 / 3.0; + + /* ------------- calculate auxillary epoch quantities ---------- */ + eccsq = ecco * ecco; + omeosq = 1.0 - eccsq; + rteosq = sqrt(omeosq); + cosio = cos(inclo); + cosio2 = cosio * cosio; + + /* ------------------ un-kozai the mean motion ----------------- */ + ak = pow(xke / no, x2o3); + d1 = 0.75 * j2 * (3.0 * cosio2 - 1.0) / (rteosq * omeosq); + del = d1 / (ak * ak); + adel = ak * (1.0 - del * del - del * + (1.0 / 3.0 + 134.0 * del * del / 81.0)); + del = d1/(adel * adel); + no = no / (1.0 + del); + + ao = pow(xke / no, x2o3); + sinio = sin(inclo); + po = ao * omeosq; + con42 = 1.0 - 5.0 * cosio2; + con41 = -con42-cosio2-cosio2; + ainv = 1.0 / ao; + posq = po * po; + rp = ao * (1.0 - ecco); + method = 'n'; + + // sgp4fix modern approach to finding sidereal timew + // gsto = gstime(epoch + 2433281.5); + + // sgp4fix use old way of finding gst + // count integer number of days from 0 jan 1970 + ts70 = epoch - 7305.0; + ids70 = floor(ts70 + 1.0e-8); + ds70 = ids70; + tfrac = ts70 - ds70; + // find greenwich location at epoch + c1 = 1.72027916940703639e-2; + thgr70= 1.7321343856509374; + fk5r = 5.07551419432269442e-15; + c1p2p = c1 + twopi; + gsto = fmod( thgr70 + c1*ds70 + c1p2p*tfrac + ts70*ts70*fk5r, twopi); + if ( gsto < 0.0 ) + gsto = gsto + twopi; + +//#include "debug5.cpp" +} // end initl + +/*----------------------------------------------------------------------------- +* +* procedure sgp4init +* +* this procedure initializes variables for sgp4. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* satn - satellite number +* bstar - sgp4 type drag coefficient kg/m2er +* ecco - eccentricity +* epoch - epoch time in days from jan 0, 1950. 0 hr +* argpo - argument of perigee (output if ds) +* inclo - inclination +* mo - mean anomaly (output if ds) +* no - mean motion +* nodeo - right ascension of ascending node +* +* outputs : +* satrec - common values for subsequent calls +* return code - non-zero on error. +* 1 - mean elements, ecc >= 1.0 or ecc < -0.001 or a < 0.95 er +* 2 - mean motion less than 0.0 +* 3 - pert elements, ecc < 0.0 or ecc > 1.0 +* 4 - semi-latus rectum < 0.0 +* 5 - epoch elements are sub-orbital +* 6 - satellite has decayed +* +* locals : +* cnodm , snodm , cosim , sinim , cosomm , sinomm +* cc1sq , cc2 , cc3 +* coef , coef1 +* cosio4 - +* day - +* dndt - +* em - eccentricity +* emsq - eccentricity squared +* eeta - +* etasq - +* gam - +* argpm - argument of perigee +* nodem - +* inclm - inclination +* mm - mean anomaly +* nm - mean motion +* perige - perigee +* pinvsq - +* psisq - +* qzms24 - +* rtemsq - +* s1, s2, s3, s4, s5, s6, s7 - +* sfour - +* ss1, ss2, ss3, ss4, ss5, ss6, ss7 - +* sz1, sz2, sz3 +* sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33 - +* tc - +* temp - +* temp1, temp2, temp3 - +* tsi - +* xpidot - +* xhdot1 - +* z1, z2, z3 - +* z11, z12, z13, z21, z22, z23, z31, z32, z33 - +* +* coupling : +* getgravconst- +* initl - +* dscom - +* dpper - +* dsinit - +* sgp4 - +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +int sgp4init + ( + gravconsttype whichconst, const int satn, const double epoch, + const double xbstar, const double xecco, const double xargpo, + const double xinclo, const double xmo, const double xno, + const double xnodeo, elsetrec& satrec + ) +{ + /* --------------------- local variables ------------------------ */ + double ao, ainv, con42, cosio, sinio, cosio2, eccsq, + omeosq, posq, rp, rteosq, + cnodm , snodm , cosim , sinim , cosomm, sinomm, cc1sq , + cc2 , cc3 , coef , coef1 , cosio4, day , dndt , + em , emsq , eeta , etasq , gam , argpm , nodem , + inclm , mm , nm , perige, pinvsq, psisq , qzms24, + rtemsq, s1 , s2 , s3 , s4 , s5 , s6 , + s7 , sfour , ss1 = 0 , ss2 = 0 , ss3 = 0 , ss4 = 0 , ss5 = 0 , + ss6 = 0 , ss7 = 0 , sz1 = 0 , sz2 = 0 , sz3 = 0 , sz11 = 0 , sz12 = 0 , + sz13 = 0 , sz21 = 0 , sz22 = 0 , sz23 = 0 , sz31 = 0 , sz32 = 0 , sz33 = 0 , + tc , temp , temp1 , temp2 , temp3 , tsi , xpidot, + xhdot1, z1 , z2 , z3 , z11 , z12 , z13 , + z21 , z22 , z23 , z31 , z32 , z33, + qzms2t, ss, j2, j3oj2, j4, x2o3, r[3], v[3], + tumin, mu, radiusearthkm, xke, j3; + + /* ------------------------ initialization --------------------- */ + // sgp4fix divisor for divide by zero check on inclination + const double temp4 = 1.0 + cos(pi-1.0e-9); + + /* ----------- set all near earth variables to zero ------------ */ + satrec.isimp = 0; satrec.method = 'n'; satrec.aycof = 0.0; + satrec.con41 = 0.0; satrec.cc1 = 0.0; satrec.cc4 = 0.0; + satrec.cc5 = 0.0; satrec.d2 = 0.0; satrec.d3 = 0.0; + satrec.d4 = 0.0; satrec.delmo = 0.0; satrec.eta = 0.0; + satrec.argpdot = 0.0; satrec.omgcof = 0.0; satrec.sinmao = 0.0; + satrec.t = 0.0; satrec.t2cof = 0.0; satrec.t3cof = 0.0; + satrec.t4cof = 0.0; satrec.t5cof = 0.0; satrec.x1mth2 = 0.0; + satrec.x7thm1 = 0.0; satrec.mdot = 0.0; satrec.nodedot = 0.0; + satrec.xlcof = 0.0; satrec.xmcof = 0.0; satrec.nodecf = 0.0; + + /* ----------- set all deep space variables to zero ------------ */ + satrec.irez = 0; satrec.d2201 = 0.0; satrec.d2211 = 0.0; + satrec.d3210 = 0.0; satrec.d3222 = 0.0; satrec.d4410 = 0.0; + satrec.d4422 = 0.0; satrec.d5220 = 0.0; satrec.d5232 = 0.0; + satrec.d5421 = 0.0; satrec.d5433 = 0.0; satrec.dedt = 0.0; + satrec.del1 = 0.0; satrec.del2 = 0.0; satrec.del3 = 0.0; + satrec.didt = 0.0; satrec.dmdt = 0.0; satrec.dnodt = 0.0; + satrec.domdt = 0.0; satrec.e3 = 0.0; satrec.ee2 = 0.0; + satrec.peo = 0.0; satrec.pgho = 0.0; satrec.pho = 0.0; + satrec.pinco = 0.0; satrec.plo = 0.0; satrec.se2 = 0.0; + satrec.se3 = 0.0; satrec.sgh2 = 0.0; satrec.sgh3 = 0.0; + satrec.sgh4 = 0.0; satrec.sh2 = 0.0; satrec.sh3 = 0.0; + satrec.si2 = 0.0; satrec.si3 = 0.0; satrec.sl2 = 0.0; + satrec.sl3 = 0.0; satrec.sl4 = 0.0; satrec.gsto = 0.0; + satrec.xfact = 0.0; satrec.xgh2 = 0.0; satrec.xgh3 = 0.0; + satrec.xgh4 = 0.0; satrec.xh2 = 0.0; satrec.xh3 = 0.0; + satrec.xi2 = 0.0; satrec.xi3 = 0.0; satrec.xl2 = 0.0; + satrec.xl3 = 0.0; satrec.xl4 = 0.0; satrec.xlamo = 0.0; + satrec.zmol = 0.0; satrec.zmos = 0.0; satrec.atime = 0.0; + satrec.xli = 0.0; satrec.xni = 0.0; + + // sgp4fix - note the following variables are also passed directly via satrec. + // it is possible to streamline the sgp4init call by deleting the "x" + // variables, but the user would need to set the satrec.* values first. we + // include the additional assignments in case twoline2rv is not used. + satrec.bstar = xbstar; + satrec.ecco = xecco; + satrec.argpo = xargpo; + satrec.inclo = xinclo; + satrec.mo = xmo; + satrec.no = xno; + satrec.nodeo = xnodeo; + + /* ------------------------ earth constants ----------------------- */ + // sgp4fix identify constants and allow alternate values + getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); + ss = 78.0 / radiusearthkm + 1.0; + qzms2t = pow(((120.0 - 78.0) / radiusearthkm), 4); + x2o3 = 2.0 / 3.0; + + satrec.init = 'y'; + satrec.t = 0.0; + + initl + ( + satn, whichconst, satrec.ecco, epoch, satrec.inclo, satrec.no, satrec.method, + ainv, ao, satrec.con41, con42, cosio, cosio2, eccsq, omeosq, + posq, rp, rteosq, sinio, satrec.gsto + ); + satrec.error = 0; + + if (rp < 1.0) + { +// printf("# *** satn%d epoch elts sub-orbital ***\n", satn); + satrec.error = 5; + } + + if ((omeosq >= 0.0 ) || ( satrec.no >= 0.0)) + { + satrec.isimp = 0; + if (rp < (220.0 / radiusearthkm + 1.0)) + satrec.isimp = 1; + sfour = ss; + qzms24 = qzms2t; + perige = (rp - 1.0) * radiusearthkm; + + /* - for perigees below 156 km, s and qoms2t are altered - */ + if (perige < 156.0) + { + sfour = perige - 78.0; + if (perige < 98.0) + sfour = 20.0; + qzms24 = pow(((120.0 - sfour) / radiusearthkm), 4.0); + sfour = sfour / radiusearthkm + 1.0; + } + pinvsq = 1.0 / posq; + + tsi = 1.0 / (ao - sfour); + satrec.eta = ao * satrec.ecco * tsi; + etasq = satrec.eta * satrec.eta; + eeta = satrec.ecco * satrec.eta; + psisq = fabs(1.0 - etasq); + coef = qzms24 * pow(tsi, 4.0); + coef1 = coef / pow(psisq, 3.5); + cc2 = coef1 * satrec.no * (ao * (1.0 + 1.5 * etasq + eeta * + (4.0 + etasq)) + 0.375 * j2 * tsi / psisq * satrec.con41 * + (8.0 + 3.0 * etasq * (8.0 + etasq))); + satrec.cc1 = satrec.bstar * cc2; + cc3 = 0.0; + if (satrec.ecco > 1.0e-4) + cc3 = -2.0 * coef * tsi * j3oj2 * satrec.no * sinio / satrec.ecco; + satrec.x1mth2 = 1.0 - cosio2; + satrec.cc4 = 2.0* satrec.no * coef1 * ao * omeosq * + (satrec.eta * (2.0 + 0.5 * etasq) + satrec.ecco * + (0.5 + 2.0 * etasq) - j2 * tsi / (ao * psisq) * + (-3.0 * satrec.con41 * (1.0 - 2.0 * eeta + etasq * + (1.5 - 0.5 * eeta)) + 0.75 * satrec.x1mth2 * + (2.0 * etasq - eeta * (1.0 + etasq)) * cos(2.0 * satrec.argpo))); + satrec.cc5 = 2.0 * coef1 * ao * omeosq * (1.0 + 2.75 * + (etasq + eeta) + eeta * etasq); + cosio4 = cosio2 * cosio2; + temp1 = 1.5 * j2 * pinvsq * satrec.no; + temp2 = 0.5 * temp1 * j2 * pinvsq; + temp3 = -0.46875 * j4 * pinvsq * pinvsq * satrec.no; + satrec.mdot = satrec.no + 0.5 * temp1 * rteosq * satrec.con41 + 0.0625 * + temp2 * rteosq * (13.0 - 78.0 * cosio2 + 137.0 * cosio4); + satrec.argpdot = -0.5 * temp1 * con42 + 0.0625 * temp2 * + (7.0 - 114.0 * cosio2 + 395.0 * cosio4) + + temp3 * (3.0 - 36.0 * cosio2 + 49.0 * cosio4); + xhdot1 = -temp1 * cosio; + satrec.nodedot = xhdot1 + (0.5 * temp2 * (4.0 - 19.0 * cosio2) + + 2.0 * temp3 * (3.0 - 7.0 * cosio2)) * cosio; + xpidot = satrec.argpdot+ satrec.nodedot; + satrec.omgcof = satrec.bstar * cc3 * cos(satrec.argpo); + satrec.xmcof = 0.0; + if (satrec.ecco > 1.0e-4) + satrec.xmcof = -x2o3 * coef * satrec.bstar / eeta; + satrec.nodecf = 3.5 * omeosq * xhdot1 * satrec.cc1; + satrec.t2cof = 1.5 * satrec.cc1; + // sgp4fix for divide by zero with xinco = 180 deg + if (fabs(cosio+1.0) > 1.5e-12) + satrec.xlcof = -0.25 * j3oj2 * sinio * (3.0 + 5.0 * cosio) / (1.0 + cosio); + else + satrec.xlcof = -0.25 * j3oj2 * sinio * (3.0 + 5.0 * cosio) / temp4; + satrec.aycof = -0.5 * j3oj2 * sinio; + satrec.delmo = pow((1.0 + satrec.eta * cos(satrec.mo)), 3); + satrec.sinmao = sin(satrec.mo); + satrec.x7thm1 = 7.0 * cosio2 - 1.0; + + /* --------------- deep space initialization ------------- */ + if ((2*pi / satrec.no) >= 225.0) + { + satrec.method = 'd'; + satrec.isimp = 1; + tc = 0.0; + inclm = satrec.inclo; + + dscom + ( + epoch, satrec.ecco, satrec.argpo, tc, satrec.inclo, satrec.nodeo, + satrec.no, snodm, cnodm, sinim, cosim,sinomm, cosomm, + day, satrec.e3, satrec.ee2, em, emsq, gam, + satrec.peo, satrec.pgho, satrec.pho, satrec.pinco, + satrec.plo, rtemsq, satrec.se2, satrec.se3, + satrec.sgh2, satrec.sgh3, satrec.sgh4, + satrec.sh2, satrec.sh3, satrec.si2, satrec.si3, + satrec.sl2, satrec.sl3, satrec.sl4, s1, s2, s3, s4, s5, + s6, s7, ss1, ss2, ss3, ss4, ss5, ss6, ss7, sz1, sz2, sz3, + sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33, + satrec.xgh2, satrec.xgh3, satrec.xgh4, satrec.xh2, + satrec.xh3, satrec.xi2, satrec.xi3, satrec.xl2, + satrec.xl3, satrec.xl4, nm, z1, z2, z3, z11, + z12, z13, z21, z22, z23, z31, z32, z33, + satrec.zmol, satrec.zmos + ); + dpper + ( + satrec.e3, satrec.ee2, satrec.peo, satrec.pgho, + satrec.pho, satrec.pinco, satrec.plo, satrec.se2, + satrec.se3, satrec.sgh2, satrec.sgh3, satrec.sgh4, + satrec.sh2, satrec.sh3, satrec.si2, satrec.si3, + satrec.sl2, satrec.sl3, satrec.sl4, satrec.t, + satrec.xgh2,satrec.xgh3,satrec.xgh4, satrec.xh2, + satrec.xh3, satrec.xi2, satrec.xi3, satrec.xl2, + satrec.xl3, satrec.xl4, satrec.zmol, satrec.zmos, inclm, satrec.init, + satrec.ecco, satrec.inclo, satrec.nodeo, satrec.argpo, satrec.mo + ); + + argpm = 0.0; + nodem = 0.0; + mm = 0.0; + + dsinit + ( + whichconst, + cosim, emsq, satrec.argpo, s1, s2, s3, s4, s5, sinim, ss1, ss2, ss3, ss4, + ss5, sz1, sz3, sz11, sz13, sz21, sz23, sz31, sz33, satrec.t, tc, + satrec.gsto, satrec.mo, satrec.mdot, satrec.no, satrec.nodeo, + satrec.nodedot, xpidot, z1, z3, z11, z13, z21, z23, z31, z33, + satrec.ecco, eccsq, em, argpm, inclm, mm, nm, nodem, + satrec.irez, satrec.atime, + satrec.d2201, satrec.d2211, satrec.d3210, satrec.d3222 , + satrec.d4410, satrec.d4422, satrec.d5220, satrec.d5232, + satrec.d5421, satrec.d5433, satrec.dedt, satrec.didt, + satrec.dmdt, dndt, satrec.dnodt, satrec.domdt , + satrec.del1, satrec.del2, satrec.del3, satrec.xfact, + satrec.xlamo, satrec.xli, satrec.xni + ); + } + + /* ----------- set variables if not deep space ----------- */ + if (satrec.isimp != 1) + { + cc1sq = satrec.cc1 * satrec.cc1; + satrec.d2 = 4.0 * ao * tsi * cc1sq; + temp = satrec.d2 * tsi * satrec.cc1 / 3.0; + satrec.d3 = (17.0 * ao + sfour) * temp; + satrec.d4 = 0.5 * temp * ao * tsi * (221.0 * ao + 31.0 * sfour) * + satrec.cc1; + satrec.t3cof = satrec.d2 + 2.0 * cc1sq; + satrec.t4cof = 0.25 * (3.0 * satrec.d3 + satrec.cc1 * + (12.0 * satrec.d2 + 10.0 * cc1sq)); + satrec.t5cof = 0.2 * (3.0 * satrec.d4 + + 12.0 * satrec.cc1 * satrec.d3 + + 6.0 * satrec.d2 * satrec.d2 + + 15.0 * cc1sq * (2.0 * satrec.d2 + cc1sq)); + } + } // if omeosq = 0 ... + + /* finally propogate to zero epoch to initialise all others. */ + if(satrec.error == 0) + sgp4(whichconst, satrec, 0.0, r, v); + + satrec.init = 'n'; + +//#include "debug6.cpp" + return satrec.error; +} // end sgp4init + +/*----------------------------------------------------------------------------- +* +* procedure sgp4 +* +* this procedure is the sgp4 prediction model from space command. this is an +* updated and combined version of sgp4 and sdp4, which were originally +* published separately in spacetrack report #3. this version follows the +* methodology from the aiaa paper (2006) describing the history and +* development of the code. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* satrec - initialised structure from sgp4init() call. +* tsince - time eince epoch (minutes) +* +* outputs : +* r - position vector km +* v - velocity km/sec +* return code - non-zero on error. +* 1 - mean elements, ecc >= 1.0 or ecc < -0.001 or a < 0.95 er +* 2 - mean motion less than 0.0 +* 3 - pert elements, ecc < 0.0 or ecc > 1.0 +* 4 - semi-latus rectum < 0.0 +* 5 - epoch elements are sub-orbital +* 6 - satellite has decayed +* +* locals : +* am - +* axnl, aynl - +* betal - +* cosim , sinim , cosomm , sinomm , cnod , snod , cos2u , +* sin2u , coseo1 , sineo1 , cosi , sini , cosip , sinip , +* cosisq , cossu , sinsu , cosu , sinu +* delm - +* delomg - +* dndt - +* eccm - +* emsq - +* ecose - +* el2 - +* eo1 - +* eccp - +* esine - +* argpm - +* argpp - +* omgadf - +* pl - +* r - +* rtemsq - +* rdotl - +* rl - +* rvdot - +* rvdotl - +* su - +* t2 , t3 , t4 , tc +* tem5, temp , temp1 , temp2 , tempa , tempe , templ +* u , ux , uy , uz , vx , vy , vz +* inclm - inclination +* mm - mean anomaly +* nm - mean motion +* nodem - right asc of ascending node +* xinc - +* xincp - +* xl - +* xlm - +* mp - +* xmdf - +* xmx - +* xmy - +* nodedf - +* xnode - +* nodep - +* np - +* +* coupling : +* getgravconst- +* dpper +* dpspace +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +int sgp4 + ( + gravconsttype whichconst, elsetrec& satrec, double tsince, + double r[3], double v[3] + ) +{ + double am , axnl , aynl , betal , cosim , cnod , + cos2u, coseo1, cosi , cosip , cosisq, cossu , cosu, + delm , delomg, em , emsq , ecose , el2 , eo1 , + ep , esine , argpm, argpp , argpdf, pl, mrt = 0.0, + mvt , rdotl , rl , rvdot , rvdotl, sinim , + sin2u, sineo1, sini , sinip , sinsu , sinu , + snod , su , t2 , t3 , t4 , tem5 , temp, + temp1, temp2 , tempa, tempe , templ , u , ux , + uy , uz , vx , vy , vz , inclm , mm , + nm , nodem, xinc , xincp , xl , xlm , mp , + xmdf , xmx , xmy , nodedf, xnode , nodep, tc , dndt, + twopi, x2o3 , j2 , j3 , tumin, j4 , xke , j3oj2, radiusearthkm, + mu, vkmpersec; + int ktr; + + /* ------------------ set mathematical constants --------------- */ + // sgp4fix divisor for divide by zero check on inclination + const double temp4 = 1.0 + cos(pi-1.0e-9); + twopi = 2.0 * pi; + x2o3 = 2.0 / 3.0; + // sgp4fix identify constants and allow alternate values + getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); + vkmpersec = radiusearthkm * xke/60.0; + + /* --------------------- clear sgp4 error flag ----------------- */ + satrec.t = tsince; + satrec.error = 0; + + /* ------- update for secular gravity and atmospheric drag ----- */ + xmdf = satrec.mo + satrec.mdot * satrec.t; + argpdf = satrec.argpo + satrec.argpdot * satrec.t; + nodedf = satrec.nodeo + satrec.nodedot * satrec.t; + argpm = argpdf; + mm = xmdf; + t2 = satrec.t * satrec.t; + nodem = nodedf + satrec.nodecf * t2; + tempa = 1.0 - satrec.cc1 * satrec.t; + tempe = satrec.bstar * satrec.cc4 * satrec.t; + templ = satrec.t2cof * t2; + + if (satrec.isimp != 1) + { + delomg = satrec.omgcof * satrec.t; + delm = satrec.xmcof * + (pow((1.0 + satrec.eta * cos(xmdf)), 3) - + satrec.delmo); + temp = delomg + delm; + mm = xmdf + temp; + argpm = argpdf - temp; + t3 = t2 * satrec.t; + t4 = t3 * satrec.t; + tempa = tempa - satrec.d2 * t2 - satrec.d3 * t3 - + satrec.d4 * t4; + tempe = tempe + satrec.bstar * satrec.cc5 * (sin(mm) - + satrec.sinmao); + templ = templ + satrec.t3cof * t3 + t4 * (satrec.t4cof + + satrec.t * satrec.t5cof); + } + + nm = satrec.no; + em = satrec.ecco; + inclm = satrec.inclo; + if (satrec.method == 'd') + { + tc = satrec.t; + dspace + ( + satrec.irez, + satrec.d2201, satrec.d2211, satrec.d3210, + satrec.d3222, satrec.d4410, satrec.d4422, + satrec.d5220, satrec.d5232, satrec.d5421, + satrec.d5433, satrec.dedt, satrec.del1, + satrec.del2, satrec.del3, satrec.didt, + satrec.dmdt, satrec.dnodt, satrec.domdt, + satrec.argpo, satrec.argpdot, satrec.t, tc, + satrec.gsto, satrec.xfact, satrec.xlamo, + satrec.no, satrec.atime, + em, argpm, inclm, satrec.xli, mm, satrec.xni, + nodem, dndt, nm + ); + } // if method = d + + if (nm <= 0.0) + { +// printf("# error nm %f\n", nm); + satrec.error = 2; + } + am = pow((xke / nm),x2o3) * tempa * tempa; + nm = xke / pow(am, 1.5); + em = em - tempe; + + // fix tolerance for error recognition + if ((em >= 1.0) || (em < -0.001) || (am < 0.95)) + { +// printf("# error em %f\n", em); + satrec.error = 1; + } + if (em < 0.0) + em = 1.0e-6; + mm = mm + satrec.no * templ; + xlm = mm + argpm + nodem; + emsq = em * em; + temp = 1.0 - emsq; + + nodem = fmod(nodem, twopi); + argpm = fmod(argpm, twopi); + xlm = fmod(xlm, twopi); + mm = fmod(xlm - argpm - nodem, twopi); + + /* ----------------- compute extra mean quantities ------------- */ + sinim = sin(inclm); + cosim = cos(inclm); + + /* -------------------- add lunar-solar periodics -------------- */ + ep = em; + xincp = inclm; + argpp = argpm; + nodep = nodem; + mp = mm; + sinip = sinim; + cosip = cosim; + if (satrec.method == 'd') + { + dpper + ( + satrec.e3, satrec.ee2, satrec.peo, + satrec.pgho, satrec.pho, satrec.pinco, + satrec.plo, satrec.se2, satrec.se3, + satrec.sgh2, satrec.sgh3, satrec.sgh4, + satrec.sh2, satrec.sh3, satrec.si2, + satrec.si3, satrec.sl2, satrec.sl3, + satrec.sl4, satrec.t, satrec.xgh2, + satrec.xgh3, satrec.xgh4, satrec.xh2, + satrec.xh3, satrec.xi2, satrec.xi3, + satrec.xl2, satrec.xl3, satrec.xl4, + satrec.zmol, satrec.zmos, satrec.inclo, + 'n', ep, xincp, nodep, argpp, mp + ); + if (xincp < 0.0) + { + xincp = -xincp; + nodep = nodep + pi; + argpp = argpp - pi; + } + if ((ep < 0.0 ) || ( ep > 1.0)) + { + // printf("# error ep %f\n", ep); + satrec.error = 3; + } + } // if method = d + + /* -------------------- long period periodics ------------------ */ + if (satrec.method == 'd') + { + sinip = sin(xincp); + cosip = cos(xincp); + satrec.aycof = -0.5*j3oj2*sinip; + // sgp4fix for divide by zero for xincp = 180 deg + if (fabs(cosip+1.0) > 1.5e-12) + satrec.xlcof = -0.25 * j3oj2 * sinip * (3.0 + 5.0 * cosip) / (1.0 + cosip); + else + satrec.xlcof = -0.25 * j3oj2 * sinip * (3.0 + 5.0 * cosip) / temp4; + } + axnl = ep * cos(argpp); + temp = 1.0 / (am * (1.0 - ep * ep)); + aynl = ep* sin(argpp) + temp * satrec.aycof; + xl = mp + argpp + nodep + temp * satrec.xlcof * axnl; + + /* --------------------- solve kepler's equation --------------- */ + u = fmod(xl - nodep, twopi); + eo1 = u; + tem5 = 9999.9; + ktr = 1; + // sgp4fix for kepler iteration + // the following iteration needs better limits on corrections + while (( fabs(tem5) >= 1.0e-12) && (ktr <= 10) ) + { + sineo1 = sin(eo1); + coseo1 = cos(eo1); + tem5 = 1.0 - coseo1 * axnl - sineo1 * aynl; + tem5 = (u - aynl * coseo1 + axnl * sineo1 - eo1) / tem5; + if(fabs(tem5) >= 0.95) + tem5 = tem5 > 0.0 ? 0.95 : -0.95; + eo1 = eo1 + tem5; + ktr = ktr + 1; + } + + /* ------------- short period preliminary quantities ----------- */ + ecose = axnl*coseo1 + aynl*sineo1; + esine = axnl*sineo1 - aynl*coseo1; + el2 = axnl*axnl + aynl*aynl; + pl = am*(1.0-el2); + if (pl < 0.0) + { +// printf("# error pl %f\n", pl); + satrec.error = 4; + } + else + { + rl = am * (1.0 - ecose); + rdotl = sqrt(am) * esine/rl; + rvdotl = sqrt(pl) / rl; + betal = sqrt(1.0 - el2); + temp = esine / (1.0 + betal); + sinu = am / rl * (sineo1 - aynl - axnl * temp); + cosu = am / rl * (coseo1 - axnl + aynl * temp); + su = atan2(sinu, cosu); + sin2u = (cosu + cosu) * sinu; + cos2u = 1.0 - 2.0 * sinu * sinu; + temp = 1.0 / pl; + temp1 = 0.5 * j2 * temp; + temp2 = temp1 * temp; + + /* -------------- update for short period periodics ------------ */ + if (satrec.method == 'd') + { + cosisq = cosip * cosip; + satrec.con41 = 3.0*cosisq - 1.0; + satrec.x1mth2 = 1.0 - cosisq; + satrec.x7thm1 = 7.0*cosisq - 1.0; + } + mrt = rl * (1.0 - 1.5 * temp2 * betal * satrec.con41) + + 0.5 * temp1 * satrec.x1mth2 * cos2u; + su = su - 0.25 * temp2 * satrec.x7thm1 * sin2u; + xnode = nodep + 1.5 * temp2 * cosip * sin2u; + xinc = xincp + 1.5 * temp2 * cosip * sinip * cos2u; + mvt = rdotl - nm * temp1 * satrec.x1mth2 * sin2u / xke; + rvdot = rvdotl + nm * temp1 * (satrec.x1mth2 * cos2u + + 1.5 * satrec.con41) / xke; + + /* --------------------- orientation vectors ------------------- */ + sinsu = sin(su); + cossu = cos(su); + snod = sin(xnode); + cnod = cos(xnode); + sini = sin(xinc); + cosi = cos(xinc); + xmx = -snod * cosi; + xmy = cnod * cosi; + ux = xmx * sinsu + cnod * cossu; + uy = xmy * sinsu + snod * cossu; + uz = sini * sinsu; + vx = xmx * cossu - cnod * sinsu; + vy = xmy * cossu - snod * sinsu; + vz = sini * cossu; + + /* --------- position and velocity (in km and km/sec) ---------- */ + r[0] = (mrt * ux)* radiusearthkm; + r[1] = (mrt * uy)* radiusearthkm; + r[2] = (mrt * uz)* radiusearthkm; + v[0] = (mvt * ux + rvdot * vx) * vkmpersec; + v[1] = (mvt * uy + rvdot * vy) * vkmpersec; + v[2] = (mvt * uz + rvdot * vz) * vkmpersec; + } // if pl > 0 + + // sgp4fix for decaying satellites + if (mrt < 1.0) + { +// printf("# decay condition %11.6f \n",mrt); + satrec.error = 6; + } + + +//#include "debug7.cpp" + return satrec.error; +} // end sgp4 + + +/* ----------------------------------------------------------------------------- +* +* function gstime +* +* this function finds the greenwich sidereal time. +* +* author : david vallado 719-573-2600 1 mar 2001 +* +* inputs description range / units +* jdut1 - julian date in ut1 days from 4713 bc +* +* outputs : +* gstime - greenwich sidereal time 0 to 2pi rad +* +* locals : +* temp - temporary variable for doubles rad +* tut1 - julian centuries from the +* jan 1, 2000 12 h epoch (ut1) +* +* coupling : +* none +* +* references : +* vallado 2004, 191, eq 3-45 +* --------------------------------------------------------------------------- */ + +double gstime + ( + double jdut1 + ) + { + const double twopi = 2.0 * pi; + const double deg2rad = pi / 180.0; + double temp, tut1; + + tut1 = (jdut1 - 2451545.0) / 36525.0; + temp = -6.2e-6* tut1 * tut1 * tut1 + 0.093104 * tut1 * tut1 + + (876600.0*3600 + 8640184.812866) * tut1 + 67310.54841; // sec + temp = fmod(temp * deg2rad / 240.0, twopi); //360/86400 = 1/240, to deg, to rad + + // ------------------------ check quadrants --------------------- + if (temp < 0.0) + temp += twopi; + + return temp; + } // end gstime + +/* ----------------------------------------------------------------------------- +* +* function getgravconst +* +* this function gets constants for the propagator. note that mu is identified to +* facilitiate comparisons with newer models. the common useage is wgs72. +* +* author : david vallado 719-573-2600 21 jul 2006 +* +* inputs : +* whichconst - which set of constants to use wgs72old, wgs72, wgs84 +* +* outputs : +* tumin - minutes in one time unit +* mu - earth gravitational parameter +* radiusearthkm - radius of the earth in km +* xke - reciprocal of tumin +* j2, j3, j4 - un-normalized zonal harmonic values +* j3oj2 - j3 divided by j2 +* +* locals : +* +* coupling : +* none +* +* references : +* norad spacetrack report #3 +* vallado, crawford, hujsak, kelso 2006 + --------------------------------------------------------------------------- */ + +void getgravconst + ( + gravconsttype whichconst, + double& tumin, + double& mu, + double& radiusearthkm, + double& xke, + double& j2, + double& j3, + double& j4, + double& j3oj2 + ) + { + + switch (whichconst) + { + // -- wgs-72 low precision str#3 constants -- + case wgs72old: + mu = 398600.79964; // in km3 / s2 + radiusearthkm = 6378.135; // km + xke = 0.0743669161; + tumin = 1.0 / xke; + j2 = 0.001082616; + j3 = -0.00000253881; + j4 = -0.00000165597; + j3oj2 = j3 / j2; + break; + // ------------ wgs-72 constants ------------ + case wgs72: + mu = 398600.8; // in km3 / s2 + radiusearthkm = 6378.135; // km + xke = 60.0 / sqrt(radiusearthkm*radiusearthkm*radiusearthkm/mu); + tumin = 1.0 / xke; + j2 = 0.001082616; + j3 = -0.00000253881; + j4 = -0.00000165597; + j3oj2 = j3 / j2; + break; + case wgs84: + // ------------ wgs-84 constants ------------ + mu = 398600.5; // in km3 / s2 + radiusearthkm = 6378.137; // km + xke = 60.0 / sqrt(radiusearthkm*radiusearthkm*radiusearthkm/mu); + tumin = 1.0 / xke; + j2 = 0.00108262998905; + j3 = -0.00000253215306; + j4 = -0.00000161098761; + j3oj2 = j3 / j2; + break; + default: + fprintf(stderr,"unknown gravity option (%d)\n",whichconst); + break; + } + + } // end getgravconst + + + + + diff --git a/contrib/sgp4/sgp4unit.h b/contrib/sgp4/sgp4unit.h new file mode 100644 index 00000000..48c113d7 --- /dev/null +++ b/contrib/sgp4/sgp4unit.h @@ -0,0 +1,117 @@ +#ifndef _sgp4unit_ +#define _sgp4unit_ +/* ---------------------------------------------------------------- +* +* sgp4unit.h +* +* this file contains the sgp4 procedures for analytical propagation +* of a satellite. the code was originally released in the 1980 and 1986 +* spacetrack papers. a detailed discussion of the theory and history +* may be found in the 2006 aiaa paper by vallado, crawford, hujsak, +* and kelso. +* +* companion code for +* fundamentals of astrodynamics and applications +* 2007 +* by david vallado +* +* (w) 719-573-2600, email dvallado@agi.com +* +* current : +* 20 apr 07 david vallado +* misc fixes for constants +* changes : +* 11 aug 06 david vallado +* chg lyddane choice back to strn3, constants, misc doc +* 15 dec 05 david vallado +* misc fixes +* 26 jul 05 david vallado +* fixes for paper +* note that each fix is preceded by a +* comment with "sgp4fix" and an explanation of +* what was changed +* 10 aug 04 david vallado +* 2nd printing baseline working +* 14 may 01 david vallado +* 2nd edition baseline +* 80 norad +* original baseline +* ---------------------------------------------------------------- */ + +#include +#include + +// -------------------------- structure declarations ---------------------------- +typedef enum +{ + wgs72old, + wgs72, + wgs84 +} gravconsttype; + +typedef struct elsetrec +{ + long int satnum; + int epochyr, epochtynumrev; + int error; + char init, method; + + /* Near Earth */ + int isimp; + double aycof , con41 , cc1 , cc4 , cc5 , d2 , d3 , d4 , + delmo , eta , argpdot, omgcof , sinmao , t , t2cof, t3cof , + t4cof , t5cof , x1mth2 , x7thm1 , mdot , nodedot, xlcof , xmcof , + nodecf; + + /* Deep Space */ + int irez; + double d2201 , d2211 , d3210 , d3222 , d4410 , d4422 , d5220 , d5232 , + d5421 , d5433 , dedt , del1 , del2 , del3 , didt , dmdt , + dnodt , domdt , e3 , ee2 , peo , pgho , pho , pinco , + plo , se2 , se3 , sgh2 , sgh3 , sgh4 , sh2 , sh3 , + si2 , si3 , sl2 , sl3 , sl4 , gsto , xfact , xgh2 , + xgh3 , xgh4 , xh2 , xh3 , xi2 , xi3 , xl2 , xl3 , + xl4 , xlamo , zmol , zmos , atime , xli , xni; + + double a , altp , alta , epochdays, jdsatepoch , nddot , ndot , + bstar , rcse , inclo , nodeo , ecco , argpo , mo , + no; +} elsetrec; + +// --------------------------- function declarations ---------------------------- +int sgp4init + ( + gravconsttype whichconst, const int satn, const double epoch, + const double xbstar, const double xecco, const double xargpo, + const double xinclo, const double xmo, const double xno, + const double xnodeo, + elsetrec& satrec + ); + +int sgp4 + ( + gravconsttype whichconst, + elsetrec& satrec, double tsince, + double r[], double v[] + ); + +double gstime + ( + double + ); + +void getgravconst + ( + gravconsttype, + double&, + double&, + double&, + double&, + double&, + double&, + double&, + double& + ); + +#endif + diff --git a/controller/ControllerBase.cpp b/controller/ControllerBase.cpp index 4b72af3b..a6d70088 100644 --- a/controller/ControllerBase.cpp +++ b/controller/ControllerBase.cpp @@ -1,15 +1,20 @@ #include #include #include +#include +#include ControllerBase::ControllerBase(uint32_t setObjectId, uint32_t parentId, size_t commandQueueDepth) : SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF), submode( - SUBMODE_NONE), commandQueue(commandQueueDepth), modeHelper( - this), healthHelper(this, setObjectId) { + SUBMODE_NONE), commandQueue(NULL), modeHelper( + this), healthHelper(this, setObjectId),hkSwitcher(this) { + commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth); + } ControllerBase::~ControllerBase() { + QueueFactory::instance()->deleteMessageQueue(commandQueue); } ReturnValue_t ControllerBase::initialize() { @@ -38,18 +43,23 @@ ReturnValue_t ControllerBase::initialize() { if (result != RETURN_OK) { return result; } + + result = hkSwitcher.initialize(); + if (result != RETURN_OK) { + return result; + } return RETURN_OK; } MessageQueueId_t ControllerBase::getCommandQueue() const { - return commandQueue.getId(); + return commandQueue->getId(); } void ControllerBase::handleQueue() { CommandMessage message; ReturnValue_t result; - for (result = commandQueue.receiveMessage(&message); result == RETURN_OK; - result = commandQueue.receiveMessage(&message)) { + for (result = commandQueue->receiveMessage(&message); result == RETURN_OK; + result = commandQueue->receiveMessage(&message)) { result = modeHelper.handleModeCommand(&message); if (result == RETURN_OK) { @@ -64,21 +74,21 @@ void ControllerBase::handleQueue() { if (result == RETURN_OK) { continue; } - message.clearCommandMessage(); - CommandMessage reply(CommandMessage::REPLY_REJECTED, - CommandMessage::UNKNOW_COMMAND, 0); - commandQueue.reply(&reply); + message.setToUnknownCommand(); + commandQueue->reply(&message); } } void ControllerBase::startTransition(Mode_t mode, Submode_t submode) { + changeHK(this->mode, this->submode, false); triggerEvent(CHANGING_MODE, mode, submode); - modeHelper.modeChanged(mode, submode); - modeChanged(mode, submode); this->mode = mode; this->submode = submode; + modeHelper.modeChanged(mode, submode); + modeChanged(mode, submode); announceMode(false); + changeHK(this->mode, this->submode, true); } void ControllerBase::getMode(Mode_t* mode, Submode_t* submode) { @@ -94,8 +104,9 @@ void ControllerBase::announceMode(bool recursive) { triggerEvent(MODE_INFO, mode, submode); } -ReturnValue_t ControllerBase::performOperation() { +ReturnValue_t ControllerBase::performOperation(uint8_t opCode) { handleQueue(); + hkSwitcher.performOperation(); performControlOperation(); return RETURN_OK; } @@ -118,3 +129,6 @@ ReturnValue_t ControllerBase::setHealth(HealthState health) { HasHealthIF::HealthState ControllerBase::getHealth() { return healthHelper.getHealth(); } + +void ControllerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) { +} diff --git a/controller/ControllerBase.h b/controller/ControllerBase.h index e1167a16..56e116ec 100644 --- a/controller/ControllerBase.h +++ b/controller/ControllerBase.h @@ -7,6 +7,8 @@ #include #include #include +#include + class ControllerBase: public HasModesIF, public HasHealthIF, @@ -17,14 +19,15 @@ public: static const Mode_t MODE_NORMAL = 2; - ControllerBase(uint32_t setObjectId, uint32_t parentId, size_t commandQueueDepth = 3); + ControllerBase(uint32_t setObjectId, uint32_t parentId, + size_t commandQueueDepth = 3); virtual ~ControllerBase(); ReturnValue_t initialize(); virtual MessageQueueId_t getCommandQueue() const; - virtual ReturnValue_t performOperation(); + virtual ReturnValue_t performOperation(uint8_t opCode); virtual ReturnValue_t setHealth(HealthState health); @@ -36,12 +39,14 @@ protected: Submode_t submode; - MessageQueue commandQueue; + MessageQueueIF* commandQueue; ModeHelper modeHelper; HealthHelper healthHelper; + HkSwitchHelper hkSwitcher; + void handleQueue(); virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0; @@ -53,6 +58,7 @@ protected: virtual void getMode(Mode_t *mode, Submode_t *submode); virtual void setToExternalControl(); virtual void announceMode(bool recursive); + virtual void changeHK(Mode_t mode, Submode_t submode, bool enable); }; #endif /* CONTROLLERBASE_H_ */ diff --git a/coordinates/CoordinateTransformations.cpp b/coordinates/CoordinateTransformations.cpp index ff906043..b57519a3 100644 --- a/coordinates/CoordinateTransformations.cpp +++ b/coordinates/CoordinateTransformations.cpp @@ -6,36 +6,31 @@ #include -//TODO move time stuff to OSAL - void CoordinateTransformations::positionEcfToEci(const double* ecfPosition, - double* eciPosition) { - ecfToEci(ecfPosition, eciPosition, NULL); + double* eciPosition, timeval *timeUTC) { + ecfToEci(ecfPosition, eciPosition, NULL, timeUTC); } void CoordinateTransformations::velocityEcfToEci(const double* ecfVelocity, - const double* ecfPosition, double* eciVelocity) { - ecfToEci(ecfVelocity, eciVelocity, ecfPosition); + const double* ecfPosition, double* eciVelocity, timeval *timeUTC) { + ecfToEci(ecfVelocity, eciVelocity, ecfPosition, timeUTC); } -double CoordinateTransformations::getEarthRotationAngle(timeval time) { +void CoordinateTransformations::positionEciToEcf(const double* eciCoordinates, double* ecfCoordinates,timeval *timeUTC){ + eciToEcf(eciCoordinates,ecfCoordinates,NULL,timeUTC); +}; - double jD2000UTC = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) - / 24. / 3600.; +void CoordinateTransformations::velocityEciToEcf(const double* eciVelocity,const double* eciPosition, double* ecfVelocity,timeval* timeUTC){ + eciToEcf(eciVelocity,ecfVelocity,eciPosition,timeUTC); +} - //value of unix time at J2000TT - static const double J2000TtUnix = 946727935.816; +double CoordinateTransformations::getEarthRotationAngle(timeval timeUTC) { - //TT does not have leap seconds - //so we need to add the leap seconds since J2000 to our UTC based clock - //Conveniently, GPS gives us access to the leap seconds since 1980 - //between 1980 and 2000 13 leap seconds happened - uint8_t leapSecondsSinceJ2000 = utcGpsOffset - 13; + double jD2000UTC; + Clock::convertTimevalToJD2000(timeUTC, &jD2000UTC); - //Julean centuries since J2000 //TODO fails for dates before now? - double TTt2000 = (time.tv_sec + time.tv_usec / 1000000. - J2000TtUnix - + leapSecondsSinceJ2000) / 24. / 3600. / 36525.; + double TTt2000 = getJuleanCenturiesTT(timeUTC); double theta = 2 * Math::PI * (0.779057273264 + 1.00273781191135448 * jD2000UTC); @@ -48,9 +43,9 @@ double CoordinateTransformations::getEarthRotationAngle(timeval time) { return theta; } -void CoordinateTransformations::getEarthRotationMatrix(timeval time, +void CoordinateTransformations::getEarthRotationMatrix(timeval timeUTC, double matrix[][3]) { - double theta = getEarthRotationAngle(time); + double theta = getEarthRotationAngle(timeUTC); matrix[0][0] = cos(theta); matrix[0][1] = sin(theta); @@ -65,120 +60,35 @@ void CoordinateTransformations::getEarthRotationMatrix(timeval time, void CoordinateTransformations::ecfToEci(const double* ecfCoordinates, double* eciCoordinates, - const double* ecfPositionIfCoordinatesAreVelocity) { - //TODO all calculations only work with a correct time + const double* ecfPositionIfCoordinatesAreVelocity, timeval *timeUTCin) { - timeval time; - OSAL::getClock_timeval(&time); - - //value of unix time at J2000TT - static const double J2000TtUnix = 946727935.816; - - //we need TT which does not have leap seconds - //so we need to add the leap seconds since J2000 to our UTC based clock - //Conveniently, GPS gives us access to the leap seconds since 1980 - //between 1980 and 2000 13 leap seconds happened - uint8_t leapSecondsSinceJ2000 = utcGpsOffset - 13; - - //Julean centuries since J2000 //TODO fails for dates before now? - double TTt2000 = (time.tv_sec + time.tv_usec / 1000000. - J2000TtUnix - + leapSecondsSinceJ2000) / 24. / 3600. / 36525.; - - ////////////////////////////////////////////////////////// - // Calculate Precession Matrix - - double zeta = 0.0111808609 * TTt2000 - + 1.46355554053347E-006 * TTt2000 * TTt2000 - + 8.72567663260943E-008 * TTt2000 * TTt2000 * TTt2000; - double theta_p = 0.0097171735 * TTt2000 - - 2.06845757045384E-006 * TTt2000 * TTt2000 - - 2.02812107218552E-007 * TTt2000 * TTt2000 * TTt2000; - double z = zeta + 3.8436028638364E-006 * TTt2000 * TTt2000 - + 0.000000001 * TTt2000 * TTt2000 * TTt2000; - - double mPrecession[3][3]; - - mPrecession[0][0] = -sin(z) * sin(zeta) + cos(z) * cos(theta_p) * cos(zeta); - mPrecession[1][0] = cos(z) * sin(zeta) + sin(z) * cos(theta_p) * cos(zeta); - mPrecession[2][0] = sin(theta_p) * cos(zeta); - - mPrecession[0][1] = -sin(z) * cos(zeta) - cos(z) * cos(theta_p) * sin(zeta); - mPrecession[1][1] = cos(z) * cos(zeta) - sin(z) * cos(theta_p) * sin(zeta); - mPrecession[2][1] = -sin(theta_p) * sin(zeta); - - mPrecession[0][2] = -cos(z) * sin(theta_p); - mPrecession[1][2] = -sin(z) * sin(theta_p); - mPrecession[2][2] = cos(theta_p); - - ////////////////////////////////////////////////////////// - // Calculate Nutation Matrix - - double omega_moon = 2.1824386244 - 33.7570459338 * TTt2000 - + 3.61428599267159E-005 * TTt2000 * TTt2000 - + 3.87850944887629E-008 * TTt2000 * TTt2000 * TTt2000; - - double deltaPsi = -0.000083388 * sin(omega_moon); - double deltaEpsilon = 4.46174030725106E-005 * cos(omega_moon); - - double epsilon = 0.4090928042 - 0.0002269655 * TTt2000 - - 2.86040071854626E-009 * TTt2000 * TTt2000 - + 8.78967203851589E-009 * TTt2000 * TTt2000 * TTt2000; - - double mNutation[3][3]; - - mNutation[0][0] = cos(deltaPsi); - mNutation[1][0] = cos(epsilon + deltaEpsilon) * sin(deltaPsi); - mNutation[2][0] = sin(epsilon + deltaEpsilon) * sin(deltaPsi); - - mNutation[0][1] = -cos(epsilon) * sin(deltaPsi); - mNutation[1][1] = cos(epsilon) * cos(epsilon + deltaEpsilon) * cos(deltaPsi) - + sin(epsilon) * sin(epsilon + deltaEpsilon); - mNutation[2][1] = cos(epsilon) * sin(epsilon + deltaEpsilon) * cos(deltaPsi) - - sin(epsilon) * cos(epsilon + deltaEpsilon); - - mNutation[0][2] = -sin(epsilon) * sin(deltaPsi); - mNutation[1][2] = sin(epsilon) * cos(epsilon + deltaEpsilon) * cos(deltaPsi) - - cos(epsilon) * sin(epsilon + deltaEpsilon); - mNutation[2][2] = sin(epsilon) * sin(epsilon + deltaEpsilon) * cos(deltaPsi) - + cos(epsilon) * cos(epsilon + deltaEpsilon); - - ////////////////////////////////////////////////////////// - // Calculate Earth rotation matrix - - //calculate theta - - double mTheta[3][3]; - getEarthRotationMatrix(time, mTheta); - - //polar motion is neglected + timeval timeUTC; + if (timeUTCin != NULL) { + timeUTC = *timeUTCin; + } else { + Clock::getClock_timeval(&timeUTC); + } double Tfi[3][3]; - double Ttemp[3][3]; double Tif[3][3]; - - MatrixOperations::multiply(mNutation[0], mPrecession[0], Ttemp[0], - 3, 3, 3); - MatrixOperations::multiply(mTheta[0], Ttemp[0], Tfi[0], 3, 3, 3); + getTransMatrixECITOECF(timeUTC,Tfi); MatrixOperations::transpose(Tfi[0], Tif[0], 3); MatrixOperations::multiply(Tif[0], ecfCoordinates, eciCoordinates, 3, 3, 1); + + + if (ecfPositionIfCoordinatesAreVelocity != NULL) { double Tdotfi[3][3]; double Tdotif[3][3]; double Trot[3][3] = { { 0, Earth::OMEGA, 0 }, { 0 - Earth::OMEGA, 0, 0 }, { 0, 0, 0 } }; - double Ttemp2[3][3]; - MatrixOperations::multiply(mNutation[0], mPrecession[0], - Ttemp[0], 3, 3, 3); - MatrixOperations::multiply(mTheta[0], Ttemp[0], Ttemp2[0], 3, 3, - 3); - - MatrixOperations::multiply(Trot[0], Ttemp2[0], Tdotfi[0], 3, 3, + MatrixOperations::multiply(Trot[0], Tfi[0], Tdotfi[0], 3, 3, 3); MatrixOperations::transpose(Tdotfi[0], Tdotif[0], 3); @@ -194,13 +104,124 @@ void CoordinateTransformations::ecfToEci(const double* ecfCoordinates, } } -CoordinateTransformations::CoordinateTransformations(uint8_t offset) : - utcGpsOffset(offset) { +double CoordinateTransformations::getJuleanCenturiesTT(timeval timeUTC) { + timeval timeTT; + Clock::convertUTCToTT(timeUTC, &timeTT); + double jD2000TT; + Clock::convertTimevalToJD2000(timeTT, &jD2000TT); + return jD2000TT / 36525.; } -CoordinateTransformations::~CoordinateTransformations() { -} +void CoordinateTransformations::eciToEcf(const double* eciCoordinates, + double* ecfCoordinates, + const double* eciPositionIfCoordinatesAreVelocity,timeval *timeUTCin){ + timeval timeUTC; + if (timeUTCin != NULL) { + timeUTC = *timeUTCin; + }else{ + Clock::getClock_timeval(&timeUTC); + } -void CoordinateTransformations::setUtcGpsOffset(uint8_t offset) { -} + double Tfi[3][3]; + + getTransMatrixECITOECF(timeUTC,Tfi); + + MatrixOperations::multiply(Tfi[0],eciCoordinates,ecfCoordinates,3,3,1); + + if (eciPositionIfCoordinatesAreVelocity != NULL) { + + double Tdotfi[3][3]; + double Trot[3][3] = { { 0, Earth::OMEGA, 0 }, + { 0 - Earth::OMEGA, 0, 0 }, { 0, 0, 0 } }; + + MatrixOperations::multiply(Trot[0], Tfi[0], Tdotfi[0], 3, 3, + 3); + + double velocityCorrection[3]; + + MatrixOperations::multiply(Tdotfi[0], + eciPositionIfCoordinatesAreVelocity, velocityCorrection, 3, 3, + 1); + + VectorOperations::add(ecfCoordinates, velocityCorrection, + ecfCoordinates, 3); + } +}; + +void CoordinateTransformations::getTransMatrixECITOECF(timeval timeUTC,double Tfi[3][3]){ + double TTt2000 = getJuleanCenturiesTT(timeUTC); + + ////////////////////////////////////////////////////////// + // Calculate Precession Matrix + + double zeta = 0.0111808609 * TTt2000 + + 1.46355554053347E-006 * TTt2000 * TTt2000 + + 8.72567663260943E-008 * TTt2000 * TTt2000 * TTt2000; + double theta_p = 0.0097171735 * TTt2000 + - 2.06845757045384E-006 * TTt2000 * TTt2000 + - 2.02812107218552E-007 * TTt2000 * TTt2000 * TTt2000; + double z = zeta + 3.8436028638364E-006 * TTt2000 * TTt2000 + + 0.000000001 * TTt2000 * TTt2000 * TTt2000; + + double mPrecession[3][3]; + + mPrecession[0][0] = -sin(z) * sin(zeta) + cos(z) * cos(theta_p) * cos(zeta); + mPrecession[1][0] = cos(z) * sin(zeta) + sin(z) * cos(theta_p) * cos(zeta); + mPrecession[2][0] = sin(theta_p) * cos(zeta); + + mPrecession[0][1] = -sin(z) * cos(zeta) - cos(z) * cos(theta_p) * sin(zeta); + mPrecession[1][1] = cos(z) * cos(zeta) - sin(z) * cos(theta_p) * sin(zeta); + mPrecession[2][1] = -sin(theta_p) * sin(zeta); + + mPrecession[0][2] = -cos(z) * sin(theta_p); + mPrecession[1][2] = -sin(z) * sin(theta_p); + mPrecession[2][2] = cos(theta_p); + + ////////////////////////////////////////////////////////// + // Calculate Nutation Matrix + + double omega_moon = 2.1824386244 - 33.7570459338 * TTt2000 + + 3.61428599267159E-005 * TTt2000 * TTt2000 + + 3.87850944887629E-008 * TTt2000 * TTt2000 * TTt2000; + + double deltaPsi = -0.000083388 * sin(omega_moon); + double deltaEpsilon = 4.46174030725106E-005 * cos(omega_moon); + + double epsilon = 0.4090928042 - 0.0002269655 * TTt2000 + - 2.86040071854626E-009 * TTt2000 * TTt2000 + + 8.78967203851589E-009 * TTt2000 * TTt2000 * TTt2000; + + + double mNutation[3][3]; + + mNutation[0][0] = cos(deltaPsi); + mNutation[1][0] = cos(epsilon + deltaEpsilon) * sin(deltaPsi); + mNutation[2][0] = sin(epsilon + deltaEpsilon) * sin(deltaPsi); + + mNutation[0][1] = -cos(epsilon) * sin(deltaPsi); + mNutation[1][1] = cos(epsilon) * cos(epsilon + deltaEpsilon) * cos(deltaPsi) + + sin(epsilon) * sin(epsilon + deltaEpsilon); + mNutation[2][1] = cos(epsilon) * sin(epsilon + deltaEpsilon) * cos(deltaPsi) + - sin(epsilon) * cos(epsilon + deltaEpsilon); + + mNutation[0][2] = -sin(epsilon) * sin(deltaPsi); + mNutation[1][2] = sin(epsilon) * cos(epsilon + deltaEpsilon) * cos(deltaPsi) + - cos(epsilon) * sin(epsilon + deltaEpsilon); + mNutation[2][2] = sin(epsilon) * sin(epsilon + deltaEpsilon) * cos(deltaPsi) + + cos(epsilon) * cos(epsilon + deltaEpsilon); + + ////////////////////////////////////////////////////////// + // Calculate Earth rotation matrix + //calculate theta + + double mTheta[3][3]; + double Ttemp[3][3]; + getEarthRotationMatrix(timeUTC, mTheta); + + //polar motion is neglected + MatrixOperations::multiply(mNutation[0], mPrecession[0], Ttemp[0], + 3, 3, 3); + + MatrixOperations::multiply(mTheta[0], Ttemp[0], Tfi[0], 3, 3, 3); +}; diff --git a/coordinates/CoordinateTransformations.h b/coordinates/CoordinateTransformations.h index d41192c5..b19c58f9 100644 --- a/coordinates/CoordinateTransformations.h +++ b/coordinates/CoordinateTransformations.h @@ -1,28 +1,32 @@ #ifndef COORDINATETRANSFORMATIONS_H_ #define COORDINATETRANSFORMATIONS_H_ -#include +#include class CoordinateTransformations { public: - CoordinateTransformations(uint8_t utcGpsOffset); + static void positionEcfToEci(const double* ecfCoordinates, double* eciCoordinates, timeval *timeUTC = NULL); - virtual ~CoordinateTransformations(); - - void positionEcfToEci(const double* ecfCoordinates, double* eciCoordinates); - - void velocityEcfToEci(const double* ecfVelocity, + static void velocityEcfToEci(const double* ecfVelocity, const double* ecfPosition, - double* eciVelocity); + double* eciVelocity, timeval *timeUTC = NULL); - double getEarthRotationAngle(timeval time); + static void positionEciToEcf(const double* eciCoordinates, double* ecfCoordinates,timeval *timeUTC = NULL); + static void velocityEciToEcf(const double* eciVelocity,const double* eciPosition, double* ecfVelocity,timeval* timeUTC = NULL); - void getEarthRotationMatrix(timeval time, double matrix[][3]); - void setUtcGpsOffset(uint8_t offset); + static double getEarthRotationAngle(timeval timeUTC); + + static void getEarthRotationMatrix(timeval timeUTC, double matrix[][3]); private: - uint8_t utcGpsOffset; - void ecfToEci(const double* ecfCoordinates, double* eciCoordinates, - const double* ecfPositionIfCoordinatesAreVelocity); + CoordinateTransformations(); + static void ecfToEci(const double* ecfCoordinates, double* eciCoordinates, + const double* ecfPositionIfCoordinatesAreVelocity, timeval *timeUTCin); + static void eciToEcf(const double* eciCoordinates, + double* ecfCoordinates, + const double* eciPositionIfCoordinatesAreVelocity,timeval *timeUTCin); + + static double getJuleanCenturiesTT(timeval timeUTC); + static void getTransMatrixECITOECF(timeval time,double Tfi[3][3]); }; diff --git a/coordinates/Jgm3Model.h b/coordinates/Jgm3Model.h new file mode 100644 index 00000000..8f0598f8 --- /dev/null +++ b/coordinates/Jgm3Model.h @@ -0,0 +1,180 @@ +#ifndef FRAMEWORK_COORDINATES_JGM3MODEL_H_ +#define FRAMEWORK_COORDINATES_JGM3MODEL_H_ + +#include +#include +#include +#include +#include +#include + + +template +class Jgm3Model { +public: + static const uint32_t factorialLookupTable[DEGREE+3]; //This table is used instead of factorial calculation, must be increased if order or degree is higher + + Jgm3Model() { + y0[0] = 0; + y0[1] = 0; + y0[2] = 0; + y0[3] = 0; + y0[4] = 0; + y0[5] = 0; + + lastExecutionTime.tv_sec = 0; + lastExecutionTime.tv_usec = 0; + } + virtual ~Jgm3Model(){}; + + //double acsNavOrbit(double posECF[3],double velECF[3],timeval gpsTime); + + double y0[6]; //position and velocity at beginning of RK step in EC + timeval lastExecutionTime; //Time of last execution + + + void accelDegOrd(const double pos[3],const double S[ORDER+1][DEGREE+1],const double C[ORDER+1][DEGREE+1],double* accel){ + //Get radius of this position + double r = VectorOperations::norm(pos,3); + + + + //Initialize the V and W matrix + double V[DEGREE+2][ORDER+2] = {{0}}; + double W[DEGREE+2][ORDER+2] = {{0}}; + + for(uint8_t m=0;m<(ORDER+2);m++){ + for(uint8_t n=m;n<(DEGREE+2);n++){ + if((n==0) && (m==0)){ + //Montenbruck "Satellite Orbits Eq.3.31" + V[0][0] = Earth::MEAN_RADIUS / r; + W[0][0] = 0; + }else{ + if(n==m){ + //Montenbruck "Satellite Orbits Eq.3.29" + V[m][m] = (2*m-1)* (pos[0]*Earth::MEAN_RADIUS/pow(r,2)*V[m-1][m-1] - pos[1]*Earth::MEAN_RADIUS/pow(r,2)*W[m-1][m-1]); + W[m][m] = (2*m-1)* (pos[0]*Earth::MEAN_RADIUS/pow(r,2)*W[m-1][m-1] + pos[1]*Earth::MEAN_RADIUS/pow(r,2)*V[m-1][m-1]); + }else{ + //Montenbruck "Satellite Orbits Eq.3.30" + V[n][m] = ((2*n-1)/(double)(n-m))*pos[2]*Earth::MEAN_RADIUS / pow(r,2)*V[n-1][m]; + W[n][m] = ((2*n-1)/(double)(n-m))*pos[2]*Earth::MEAN_RADIUS / pow(r,2)*W[n-1][m]; + if(n!=(m+1)){ + V[n][m] = V[n][m] - (((n+m-1)/(double)(n-m)) * (pow(Earth::MEAN_RADIUS,2) / pow(r,2)) * V[n-2][m]); + W[n][m] = W[n][m] - (((n+m-1)/(double)(n-m)) * (pow(Earth::MEAN_RADIUS,2) / pow(r,2)) * W[n-2][m]); + }//End of if(n!=(m+1)) + }//End of if(n==m){ + }//End of if(n==0 and m==0) + }//End of for(uint8_t n=0;n<(DEGREE+1);n++) + }//End of for(uint8_t m=0;m<(ORDER+1);m++) + + + //overwrite accel if not properly initialized + accel[0] = 0; + accel[1] = 0; + accel[2] = 0; + + for(uint8_t m=0;m<(ORDER+1);m++){ + for(uint8_t n=m;n<(DEGREE+1);n++){ + //Use table lookup to get factorial + double partAccel[3] = {0}; + double factor = Earth::STANDARD_GRAVITATIONAL_PARAMETER/pow(Earth::MEAN_RADIUS,2); + if(m==0){ + //Montenbruck "Satellite Orbits Eq.3.33" + partAccel[0] = factor * (-C[n][0]*V[n+1][1]); + partAccel[1] = factor * (-C[n][0]*W[n+1][1]); + }else{ + double factMN = static_cast(factorialLookupTable[n-m+2]) / static_cast(factorialLookupTable[n-m]); + partAccel[0] = factor * 0.5 * ((-C[n][m]*V[n+1][m+1]-S[n][m]*W[n+1][m+1])+factMN*(C[n][m]*V[n+1][m-1]+S[n][m]*W[n+1][m-1])); + partAccel[1] = factor * 0.5 * ((-C[n][m]*W[n+1][m+1]+S[n][m]*V[n+1][m+1])+factMN*(-C[n][m]*W[n+1][m-1]+S[n][m]*V[n+1][m-1])); + } + + partAccel[2] = factor * ((n-m+1)*(-C[n][m]*V[n+1][m]-S[n][m]*W[n+1][m])); + + + accel[0] += partAccel[0]; + accel[1] += partAccel[1]; + accel[2] += partAccel[2]; + }//End of for(uint8_t n=0;n::mulScalar(y0dot,deltaT/2,yA,6); + VectorOperations::add(y0,yA,yA,6); + rungeKuttaStep(yA,yAdot,lastExecutionTime,S,C); + + //Step Three + VectorOperations::mulScalar(yAdot,deltaT/2,yB,6); + VectorOperations::add(y0,yB,yB,6); + rungeKuttaStep(yB,yBdot,lastExecutionTime,S,C); + + //Step Four + VectorOperations::mulScalar(yBdot,deltaT,yC,6); + VectorOperations::add(y0,yC,yC,6); + rungeKuttaStep(yC,yCdot,lastExecutionTime,S,C); + + //Calc new State + VectorOperations::mulScalar(yAdot,2,yAdot,6); + VectorOperations::mulScalar(yBdot,2,yBdot,6); + VectorOperations::add(y0dot,yAdot,y0dot,6); + VectorOperations::add(y0dot,yBdot,y0dot,6); + VectorOperations::add(y0dot,yCdot,y0dot,6); + VectorOperations::mulScalar(y0dot,1./6.*deltaT,y0dot,6); + VectorOperations::add(y0,y0dot,y0,6); + + CoordinateTransformations::positionEciToEcf(&y0[0],outputPos,&timeUTC); + CoordinateTransformations::velocityEciToEcf(&y0[3],&y0[0],outputVel,&timeUTC); + + lastExecutionTime = timeUTC; + + + } + + + void rungeKuttaStep(const double* yIn,double* yOut,timeval time, const double S[ORDER+1][DEGREE+1],const double C[ORDER+1][DEGREE+1]){ + double rECF[3] = {0,0,0}; + double rDotECF[3] = {0,0,0}; + double accelECF[3] = {0,0,0}; + double accelECI[3] = {0,0,0}; + + + CoordinateTransformations::positionEciToEcf(&yIn[0],rECF,&time); + CoordinateTransformations::velocityEciToEcf(&yIn[3],&yIn[0],rDotECF,&time); + accelDegOrd(rECF,S,C,accelECF); + //This is not correct, as the acceleration would have derived terms but we don't know the velocity and position at that time + //Tests showed that a wrong velocity does make the equation worse than neglecting it + CoordinateTransformations::positionEcfToEci(accelECF,accelECI,&time); + memcpy(&yOut[0],&yIn[3],sizeof(yOut[0])*3); + memcpy(&yOut[3],accelECI,sizeof(yOut[0])*3); + } +}; + + + + + + +#endif /* FRAMEWORK_COORDINATES_JGM3MODEL_H_ */ diff --git a/coordinates/Sgp4Propagator.cpp b/coordinates/Sgp4Propagator.cpp index 4e1881ed..0eb20f08 100644 --- a/coordinates/Sgp4Propagator.cpp +++ b/coordinates/Sgp4Propagator.cpp @@ -1,14 +1,12 @@ -#include #include #include #include #include #include #include -#include - +#include Sgp4Propagator::Sgp4Propagator() : - whichconst(wgs84) { + initialized(false), epoch({0, 0}), whichconst(wgs84) { } @@ -16,7 +14,6 @@ Sgp4Propagator::~Sgp4Propagator() { } -//TODO move to OSAL void jday(int year, int mon, int day, int hr, int minute, double sec, double& jd) { jd = 367.0 * year - floor((7 * (year + floor((mon + 9) / 12.0))) * 0.25) @@ -25,7 +22,6 @@ void jday(int year, int mon, int day, int hr, int minute, double sec, // - 0.5*sgn(100.0*year + mon - 190002.5) + 0.5; } -//TODO move to OSAL void days2mdhms(int year, double days, int& mon, int& day, int& hr, int& minute, double& sec) { int i, inttemp, dayofyr; @@ -169,14 +165,14 @@ ReturnValue_t Sgp4Propagator::initialize(const uint8_t* line1, // ---------------- initialize the orbit at sgp4epoch ------------------- uint8_t result = sgp4init(whichconst, satrec.satnum, - satrec.jdsatepoch - - 2433282.5 /*TODO verify, source says it's 2433281.5*/, - satrec.bstar, satrec.ecco, satrec.argpo, satrec.inclo, satrec.mo, - satrec.no, satrec.nodeo, satrec); + satrec.jdsatepoch - 2433281.5, satrec.bstar, satrec.ecco, + satrec.argpo, satrec.inclo, satrec.mo, satrec.no, satrec.nodeo, + satrec); if (result != 00) { return MAKE_RETURN_CODE(result); } else { + initialized = true; return HasReturnvaluesIF::RETURN_OK; } @@ -185,9 +181,14 @@ ReturnValue_t Sgp4Propagator::initialize(const uint8_t* line1, ReturnValue_t Sgp4Propagator::propagate(double* position, double* velocity, timeval time, uint8_t gpsUtcOffset) { + if (!initialized) { + return TLE_NOT_INITIALIZED; + } + //Time since epoch in minutes timeval timeSinceEpoch = time - epoch; - double minutesSinceEpoch = timeSinceEpoch.tv_sec / 60. + timeSinceEpoch.tv_usec / 60000000.; + double minutesSinceEpoch = timeSinceEpoch.tv_sec / 60. + + timeSinceEpoch.tv_usec / 60000000.; double yearsSinceEpoch = minutesSinceEpoch / 60 / 24 / 365; @@ -206,8 +207,7 @@ ReturnValue_t Sgp4Propagator::propagate(double* position, double* velocity, //Transform to ECF double earthRotationMatrix[3][3]; - CoordinateTransformations transform(gpsUtcOffset); - transform.getEarthRotationMatrix(time, + CoordinateTransformations::getEarthRotationMatrix(time, earthRotationMatrix); MatrixOperations::multiply(earthRotationMatrix[0], positionTEME, @@ -221,7 +221,7 @@ ReturnValue_t Sgp4Propagator::propagate(double* position, double* velocity, VectorOperations::subtract(velocity, velocityCorrection, velocity); if (result != 0) { - return MAKE_RETURN_CODE(result); + return MAKE_RETURN_CODE(result || 0xB0); } else { return HasReturnvaluesIF::RETURN_OK; } diff --git a/coordinates/Sgp4Propagator.h b/coordinates/Sgp4Propagator.h index f512924e..781e17e1 100644 --- a/coordinates/Sgp4Propagator.h +++ b/coordinates/Sgp4Propagator.h @@ -7,14 +7,15 @@ class Sgp4Propagator { public: - static const uint8_t INTERFACE_ID = SGP4PROPAGATOR_CLASS; - static const ReturnValue_t INVALID_ECCENTRICITY = MAKE_RETURN_CODE(0x01); - static const ReturnValue_t INVALID_MEAN_MOTION = MAKE_RETURN_CODE(0x02); - static const ReturnValue_t INVALID_PERTURBATION_ELEMENTS = MAKE_RETURN_CODE(0x03); - static const ReturnValue_t INVALID_SEMI_LATUS_RECTUM = MAKE_RETURN_CODE(0x04); - static const ReturnValue_t INVALID_EPOCH_ELEMENTS = MAKE_RETURN_CODE(0x05); - static const ReturnValue_t SATELLITE_HAS_DECAYED = MAKE_RETURN_CODE(0x06); - static const ReturnValue_t TLE_TOO_OLD = MAKE_RETURN_CODE(0xA1); + static const uint8_t INTERFACE_ID = CLASS_ID::SGP4PROPAGATOR_CLASS; + static const ReturnValue_t INVALID_ECCENTRICITY = MAKE_RETURN_CODE(0xA1); + static const ReturnValue_t INVALID_MEAN_MOTION = MAKE_RETURN_CODE(0xA2); + static const ReturnValue_t INVALID_PERTURBATION_ELEMENTS = MAKE_RETURN_CODE(0xA3); + static const ReturnValue_t INVALID_SEMI_LATUS_RECTUM = MAKE_RETURN_CODE(0xA4); + static const ReturnValue_t INVALID_EPOCH_ELEMENTS = MAKE_RETURN_CODE(0xA5); + static const ReturnValue_t SATELLITE_HAS_DECAYED = MAKE_RETURN_CODE(0xA6); + static const ReturnValue_t TLE_TOO_OLD = MAKE_RETURN_CODE(0xB1); + static const ReturnValue_t TLE_NOT_INITIALIZED = MAKE_RETURN_CODE(0xB2); @@ -33,6 +34,7 @@ public: ReturnValue_t propagate(double *position, double *velocity, timeval time, uint8_t gpsUtcOffset); private: + bool initialized; timeval epoch; elsetrec satrec; gravconsttype whichconst; diff --git a/datalinklayer/CCSDSReturnValuesIF.h b/datalinklayer/CCSDSReturnValuesIF.h index 50361f26..4d4f4bde 100644 --- a/datalinklayer/CCSDSReturnValuesIF.h +++ b/datalinklayer/CCSDSReturnValuesIF.h @@ -15,8 +15,7 @@ */ class CCSDSReturnValuesIF: public HasReturnvaluesIF { public: - static const uint8_t INTERFACE_ID = CCSDS_HANDLER_IF; //!< Basic ID of the interface. - static const ReturnValue_t FRAME_OK = RETURN_OK; //!< A value to indicate that a frame is ok. + static const uint8_t INTERFACE_ID = CLASS_ID::CCSDS_HANDLER_IF; //!< Basic ID of the interface. static const ReturnValue_t BC_IS_SET_VR_COMMAND = MAKE_RETURN_CODE( 0x01 ); //!< A value to describe a BC frame. static const ReturnValue_t BC_IS_UNLOCK_COMMAND = MAKE_RETURN_CODE( 0x02 ); //!< A value to describe a BC frame. diff --git a/datalinklayer/DataLinkLayer.cpp b/datalinklayer/DataLinkLayer.cpp index de04ae59..1ee546c1 100644 --- a/datalinklayer/DataLinkLayer.cpp +++ b/datalinklayer/DataLinkLayer.cpp @@ -1,13 +1,5 @@ -/* - * DataLinkLayer.cpp - * - * Created on: 02.03.2012 - * Author: baetz - */ - #include #include -#include #include DataLinkLayer::DataLinkLayer(uint8_t* set_frame_buffer, ClcwIF* setClcw, @@ -25,15 +17,15 @@ ReturnValue_t DataLinkLayer::frameDelimitingAndFillRemoval() { if ((receivedDataLength - startSequenceLength) < FRAME_PRIMARY_HEADER_LENGTH) { return SHORTER_THAN_HEADER; } - //Removing start sequence - //TODO: What does the start sequence look like? Better search for the pattern. + //Removing start sequence. + //SHOULDDO: Not implemented here. while ( *frameBuffer == START_SEQUENCE_PATTERN ) { frameBuffer++; } TcTransferFrame frame_candidate(frameBuffer); this->currentFrame = frame_candidate; //should work with shallow copy. - return FRAME_OK; + return RETURN_OK; } ReturnValue_t DataLinkLayer::frameValidationCheck() { @@ -64,14 +56,14 @@ ReturnValue_t DataLinkLayer::frameValidationCheck() { if (USE_CRC) { return this->frameCheckCRC(); } - return FRAME_OK; + return RETURN_OK; } ReturnValue_t DataLinkLayer::frameCheckCRC() { uint16_t checkValue = ::Calculate_CRC(this->currentFrame.getFullFrame(), this->currentFrame.getFullSize()); if (checkValue == 0) { - return FRAME_OK; + return RETURN_OK; } else { return CRC_FAILED; } @@ -80,7 +72,7 @@ ReturnValue_t DataLinkLayer::frameCheckCRC() { ReturnValue_t DataLinkLayer::allFramesReception() { ReturnValue_t status = this->frameDelimitingAndFillRemoval(); - if (status != FRAME_OK) { + if (status != RETURN_OK) { return status; } return this->frameValidationCheck(); @@ -96,7 +88,7 @@ ReturnValue_t DataLinkLayer::virtualChannelDemultiplexing() { virtualChannelIterator iter = virtualChannels.find(vcId); if (iter == virtualChannels.end()) { //Do not report because passive board will get this error all the time. - return FRAME_OK; + return RETURN_OK; } else { return (iter->second)->frameAcceptanceAndReportingMechanism(¤tFrame, clcw); } @@ -105,7 +97,7 @@ ReturnValue_t DataLinkLayer::virtualChannelDemultiplexing() { ReturnValue_t DataLinkLayer::processFrame(uint16_t length) { receivedDataLength = length; ReturnValue_t status = allFramesReception(); - if (status != FRAME_OK) { + if (status != RETURN_OK) { error << "DataLinkLayer::processFrame: frame reception failed. Error code: " << std::hex << status << std::dec << std::endl; // currentFrame.print(); diff --git a/datalinklayer/DataLinkLayer.h b/datalinklayer/DataLinkLayer.h index a9ac825a..8a3bb8e5 100644 --- a/datalinklayer/DataLinkLayer.h +++ b/datalinklayer/DataLinkLayer.h @@ -1,10 +1,3 @@ -/* - * DataLinkLayer.h - * - * Created on: Feb 29, 2012 - * Author: baetz - */ - #ifndef DATALINKLAYER_H_ #define DATALINKLAYER_H_ @@ -26,11 +19,11 @@ class VirtualChannelReception; class DataLinkLayer : public CCSDSReturnValuesIF { public: static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_1; - static const Event RF_AVAILABLE = MAKE_EVENT(0, SEVERITY::INFO); //!< The CCSDS Board detected a RF available signal. - static const Event RF_LOST = MAKE_EVENT(1, SEVERITY::INFO); //!< The CCSDS Board lost a previously found RF available signal. - static const Event BIT_LOCK = MAKE_EVENT(2, SEVERITY::INFO); //!< The CCSDS Board detected a Bit Lock signal. - static const Event BIT_LOCK_LOST = MAKE_EVENT(3, SEVERITY::INFO); //!< The CCSDS Board lost a previously found Bit Lock signal. - static const Event RF_CHAIN_LOST = MAKE_EVENT(4, SEVERITY::INFO); //!< The CCSDS Board detected that either bit lock or RF available or both are lost. + static const Event RF_AVAILABLE = MAKE_EVENT(0, SEVERITY::INFO); //!< A RF available signal was detected. P1: raw RFA state, P2: 0 + static const Event RF_LOST = MAKE_EVENT(1, SEVERITY::INFO); //!< A previously found RF available signal was lost. P1: raw RFA state, P2: 0 + static const Event BIT_LOCK = MAKE_EVENT(2, SEVERITY::INFO); //!< A Bit Lock signal. Was detected. P1: raw BLO state, P2: 0 + static const Event BIT_LOCK_LOST = MAKE_EVENT(3, SEVERITY::INFO); //!< A previously found Bit Lock signal was lost. P1: raw BLO state, P2: 0 +// static const Event RF_CHAIN_LOST = MAKE_EVENT(4, SEVERITY::INFO); //!< The CCSDS Board detected that either bit lock or RF available or both are lost. No parameters. static const Event FRAME_PROCESSING_FAILED = MAKE_EVENT(5, SEVERITY::LOW); //!< The CCSDS Board could not interpret a TC /** * The Constructor sets the passed parameters and nothing else. @@ -80,19 +73,19 @@ private: std::map virtualChannels; //!< Map of all virtual channels assigned. /** * Method that performs all possible frame validity checks (as specified). - * @return Various error codes or @c FRAME_OK on success. + * @return Various error codes or @c RETURN_OK on success. */ ReturnValue_t frameValidationCheck(); /** * First method to call. * Removes start sequence bytes and checks if the complete frame was received. - * TODO: Maybe handling the start sequence must be done more variable. - * @return @c FRAME_OK or @c TOO_SHORT. + * SHOULDDO: Maybe handling the start sequence must be done more variable. + * @return @c RETURN_OK or @c TOO_SHORT. */ ReturnValue_t frameDelimitingAndFillRemoval(); /** * Small helper method to check the CRC of the Frame. - * @return @c FRAME_OK or @c CRC_FAILED. + * @return @c RETURN_OK or @c CRC_FAILED. */ ReturnValue_t frameCheckCRC(); /** diff --git a/datalinklayer/Farm1StateOpen.cpp b/datalinklayer/Farm1StateOpen.cpp index d0f847ae..b06cff48 100644 --- a/datalinklayer/Farm1StateOpen.cpp +++ b/datalinklayer/Farm1StateOpen.cpp @@ -22,7 +22,7 @@ ReturnValue_t Farm1StateOpen::handleADFrame(TcTransferFrame* frame, if (diff == 0 ) { myVC->vR++; clcw->setRetransmitFlag(false); - return FRAME_OK; + return RETURN_OK; } else if (diff < myVC->positiveWindow && diff > 0 ) { clcw->setRetransmitFlag(true); return NS_POSITIVE_W; diff --git a/datalinklayer/Farm1StateOpen.h b/datalinklayer/Farm1StateOpen.h index f3d9a66e..09caacbb 100644 --- a/datalinklayer/Farm1StateOpen.h +++ b/datalinklayer/Farm1StateOpen.h @@ -35,7 +35,7 @@ public: * change to Farm1StateLockout. * @param frame The frame to handle. * @param clcw Any changes to the CLCW shall be done with the help of this interface. - * @return If the Sequence Number is ok, it returns #FRAME_OK. Otherwise either #NS_POSITIVE_W, + * @return If the Sequence Number is ok, it returns #RETURN_OK. Otherwise either #NS_POSITIVE_W, * #NS_NEGATIVE_W or NS_LOCKOUT is returned. */ ReturnValue_t handleADFrame( TcTransferFrame* frame, ClcwIF* clcw ); diff --git a/datalinklayer/MapPacketExtraction.cpp b/datalinklayer/MapPacketExtraction.cpp index 99c47464..99a16186 100644 --- a/datalinklayer/MapPacketExtraction.cpp +++ b/datalinklayer/MapPacketExtraction.cpp @@ -6,17 +6,19 @@ */ #include +#include #include #include #include #include #include +#include MapPacketExtraction::MapPacketExtraction(uint8_t setMapId, object_id_t setPacketDestination) : lastSegmentationFlag(NO_SEGMENTATION), mapId(setMapId), packetLength(0), bufferPosition( packetBuffer), packetDestination(setPacketDestination), packetStore( - NULL) { + NULL), tcQueueId(MessageQueueSenderIF::NO_QUEUE) { memset(packetBuffer, 0, sizeof(packetBuffer)); } @@ -32,7 +34,7 @@ ReturnValue_t MapPacketExtraction::extractPackets(TcTransferFrame* frame) { if (packetLength <= MAX_PACKET_SIZE) { memcpy(packetBuffer, frame->getDataField(), packetLength); bufferPosition = &packetBuffer[packetLength]; - status = FRAME_OK; + status = RETURN_OK; } else { error << "MapPacketExtraction::extractPackets. Packet too large! Size: " @@ -54,7 +56,7 @@ ReturnValue_t MapPacketExtraction::extractPackets(TcTransferFrame* frame) { status = sendCompletePacket(packetBuffer, packetLength); clearBuffers(); } - status = FRAME_OK; + status = RETURN_OK; } else { error << "MapPacketExtraction::extractPackets. Packet too large! Size: " @@ -97,7 +99,7 @@ ReturnValue_t MapPacketExtraction::unpackBlockingPackets( packet.getFullSize()); totalLength -= packet.getFullSize(); position += packet.getFullSize(); - status = FRAME_OK; + status = RETURN_OK; } else { status = DATA_CORRUPTED; totalLength = 0; @@ -115,7 +117,7 @@ ReturnValue_t MapPacketExtraction::sendCompletePacket(uint8_t* data, ReturnValue_t status = this->packetStore->addData(&store_id, data, size); if (status == RETURN_OK) { TmTcMessage message(store_id); - status = this->tcQueue.sendToDefault(&message); + status = MessageQueueSenderIF::sendMessage(tcQueueId,&message); } return status; } @@ -132,7 +134,7 @@ ReturnValue_t MapPacketExtraction::initialize() { AcceptsTelecommandsIF* distributor = objectManager->get< AcceptsTelecommandsIF>(packetDestination); if ((packetStore != NULL) && (distributor != NULL)) { - tcQueue.setDefaultDestination(distributor->getRequestQueue()); + tcQueueId = distributor->getRequestQueue(); return RETURN_OK; } else { return RETURN_FAILED; diff --git a/datalinklayer/MapPacketExtraction.h b/datalinklayer/MapPacketExtraction.h index 1fc9d2a0..5a32366c 100644 --- a/datalinklayer/MapPacketExtraction.h +++ b/datalinklayer/MapPacketExtraction.h @@ -9,9 +9,10 @@ #define MAPPACKETEXTRACTION_H_ #include -#include #include #include +#include + class StorageManagerIF; /** @@ -30,7 +31,7 @@ private: uint8_t packetBuffer[MAX_PACKET_SIZE]; //!< The internal Space Packet Buffer. object_id_t packetDestination; StorageManagerIF* packetStore; //!< Pointer to the store where full TC packets are stored. - MessageQueueSender tcQueue; //!< Sender Queue to send found packets to the distributor. + MessageQueueId_t tcQueueId; //!< QueueId to send found packets to the distributor. /** * Debug method to print the packet Buffer's content. */ @@ -39,7 +40,7 @@ private: * Method that is called if the segmentation flag is @c NO_SEGMENTATION. * The method extracts one or more packets within the frame and forwards them to the OBSW. * @param frame The TC Transfer Frame to work on. - * @return @c FRAME_OK if all Packets were extracted. If something is entirely wrong, + * @return @c RETURN_OK if all Packets were extracted. If something is entirely wrong, * @c DATA_CORRUPTED is returned, if some bytes are left over @c RESIDUAL_DATA. */ ReturnValue_t unpackBlockingPackets(TcTransferFrame* frame); diff --git a/datalinklayer/VirtualChannelReception.cpp b/datalinklayer/VirtualChannelReception.cpp index a4b7eb92..cf2f9a5d 100644 --- a/datalinklayer/VirtualChannelReception.cpp +++ b/datalinklayer/VirtualChannelReception.cpp @@ -48,15 +48,22 @@ ReturnValue_t VirtualChannelReception::doFARM(TcTransferFrame* frame, ClcwIF* cl ReturnValue_t VirtualChannelReception::frameAcceptanceAndReportingMechanism(TcTransferFrame* frame, ClcwIF* clcw) { - ReturnValue_t status = FRAME_OK; - status = doFARM(frame, &internalClcw); + ReturnValue_t result = RETURN_OK; + result = doFARM(frame, &internalClcw); internalClcw.setReceiverFrameSequenceNumber(vR); internalClcw.setFarmBCount(farmBCounter); clcw->setWhole(internalClcw.getAsWhole()); - if (status == FRAME_OK) { - status = mapDemultiplexing(frame); + switch (result) { + case RETURN_OK: + return mapDemultiplexing(frame); + case BC_IS_SET_VR_COMMAND: + case BC_IS_UNLOCK_COMMAND: + //Need to catch these codes to avoid error reporting later. + return RETURN_OK; + default: + break; } - return status; + return result; } ReturnValue_t VirtualChannelReception::addMapChannel(uint8_t mapId, MapPacketExtractionIF* object) { @@ -71,7 +78,7 @@ ReturnValue_t VirtualChannelReception::addMapChannel(uint8_t mapId, MapPacketExt ReturnValue_t VirtualChannelReception::handleBDFrame(TcTransferFrame* frame, ClcwIF* clcw) { farmBCounter++; - return FRAME_OK; + return RETURN_OK; } ReturnValue_t VirtualChannelReception::handleBCFrame(TcTransferFrame* frame, ClcwIF* clcw) { diff --git a/datalinklayer/VirtualChannelReception.h b/datalinklayer/VirtualChannelReception.h index 2e9c2121..f364c6e5 100644 --- a/datalinklayer/VirtualChannelReception.h +++ b/datalinklayer/VirtualChannelReception.h @@ -67,7 +67,7 @@ protected: * required. * @param frame The Tc Transfer Frame to handle. * @param clcw Any changes on the CLCW shall be done with this method. - * @return Always returns @c FRAME_OK. + * @return Always returns @c RETURN_OK. */ ReturnValue_t handleBDFrame( TcTransferFrame* frame, ClcwIF* clcw ); /** diff --git a/datalinklayer/VirtualChannelReceptionIF.h b/datalinklayer/VirtualChannelReceptionIF.h index b010a9ee..98a9b72c 100644 --- a/datalinklayer/VirtualChannelReceptionIF.h +++ b/datalinklayer/VirtualChannelReceptionIF.h @@ -38,7 +38,7 @@ public: * Handling the Frame includes forwarding to higher-level procedures. * @param frame The Tc Transfer Frame that was received and checked. * @param clcw Any changes to the CLCW value are forwarded by using this parameter. - * @return The return Value shall indicate successful processing with @c FRAME_OK. + * @return The return Value shall indicate successful processing with @c RETURN_OK. */ virtual ReturnValue_t frameAcceptanceAndReportingMechanism( TcTransferFrame* frame, ClcwIF* clcw ) = 0; /** diff --git a/datapool/ControllerSet.cpp b/datapool/ControllerSet.cpp new file mode 100644 index 00000000..eb4f6d0f --- /dev/null +++ b/datapool/ControllerSet.cpp @@ -0,0 +1,14 @@ +#include + +ControllerSet::ControllerSet() { + +} + +ControllerSet::~ControllerSet() { +} + +void ControllerSet::setInvalid() { + read(); + setToDefault(); + commit(PoolVariableIF::INVALID); +} diff --git a/datapool/ControllerSet.h b/datapool/ControllerSet.h new file mode 100644 index 00000000..de06bf91 --- /dev/null +++ b/datapool/ControllerSet.h @@ -0,0 +1,15 @@ +#ifndef CONTROLLERSET_H_ +#define CONTROLLERSET_H_ + +#include + +class ControllerSet :public DataSet { +public: + ControllerSet(); + virtual ~ControllerSet(); + + virtual void setToDefault() = 0; + void setInvalid(); +}; + +#endif /* CONTROLLERSET_H_ */ diff --git a/datapool/DataPool.cpp b/datapool/DataPool.cpp index 268b29f0..89543d77 100644 --- a/datapool/DataPool.cpp +++ b/datapool/DataPool.cpp @@ -1,24 +1,16 @@ -/* - * DataPool.cpp - * - * Created on: 17.10.2012 - * Author: baetz - */ - - #include #include +#include + DataPool::DataPool( void ( *initFunction )( std::map* pool_map ) ) { - this->mutex = new MutexId_t; - OSAL::createMutex( OSAL::buildName('M','T','X','0'), ( this->mutex ) ); + mutex = MutexFactory::instance()->createMutex(); if (initFunction != NULL ) { initFunction( &this->data_pool ); } } DataPool::~DataPool() { - OSAL::deleteMutex( this->mutex ); - delete this->mutex; + MutexFactory::instance()->deleteMutex(mutex); for ( std::map::iterator it = this->data_pool.begin(); it != this->data_pool.end(); ++it ) { delete it->second; } @@ -61,7 +53,7 @@ PoolEntryIF* DataPool::getRawData( uint32_t data_pool_id ) { //} ReturnValue_t DataPool::freeDataPoolLock() { - ReturnValue_t status = OSAL::unlockMutex( this->mutex ); + ReturnValue_t status = mutex->unlockMutex(); if ( status != RETURN_OK ) { error << "DataPool::DataPool: unlock of mutex failed with error code: " << status << std::endl; } @@ -69,7 +61,7 @@ ReturnValue_t DataPool::freeDataPoolLock() { } ReturnValue_t DataPool::lockDataPool() { - ReturnValue_t status = OSAL::lockMutex( this->mutex, OSAL::NO_TIMEOUT ); + ReturnValue_t status = mutex->lockMutex(MutexIF::NO_TIMEOUT); if ( status != RETURN_OK ) { error << "DataPool::DataPool: lock of mutex failed with error code: " << status << std::endl; } @@ -112,14 +104,17 @@ uint32_t DataPool::poolIdAndPositionToPid(uint32_t poolId, uint8_t index) { return (poolId << 8) + index; } -//TODO: This is not 100% clean. Should return returnValue and type by passing... -//TODO: Do we need a mutex lock here... I don't think so, as we only check static const values of elements in a list that do not change. -Type DataPool::getType(uint32_t parameter_id) { + +//SHOULDDO: Do we need a mutex lock here... I don't think so, as we only check static const values of elements in a list that do not change. +//there is no guarantee in the standard, but it seems to me that the implementation is safe -UM +ReturnValue_t DataPool::getType(uint32_t parameter_id, Type* type) { std::map::iterator it = this->data_pool.find( PIDToDataPoolId(parameter_id)); if ( it != this->data_pool.end() ) { - return it->second->getType(); + *type = it->second->getType(); + return RETURN_OK; } else { - return Type::UNKNOWN_TYPE; + *type = Type::UNKNOWN_TYPE; + return RETURN_FAILED; } } diff --git a/datapool/DataPool.h b/datapool/DataPool.h index d3cceeed..6e38dc1b 100644 --- a/datapool/DataPool.h +++ b/datapool/DataPool.h @@ -13,7 +13,7 @@ #include #include -#include +#include #include /** @@ -50,7 +50,7 @@ public: * \brief The mutex is created in the constructor and makes access mutual exclusive. * \details Locking and unlocking the pool is only done by the DataSet class. */ - MutexId_t* mutex; + MutexIF* mutex; /** * \brief In the classes constructor, the passed initialization function is called. * \details To enable filling the pool, @@ -113,7 +113,14 @@ public: */ static uint32_t poolIdAndPositionToPid( uint32_t poolId, uint8_t index ); - Type getType( uint32_t parameter_id ); + /** + * Method to return the type of a pool variable. + * @param parameter_id A parameterID (not pool id) of a DP member. + * @param type Returns the type or TYPE::UNKNOWN_TYPE + * @return RETURN_OK if parameter exists, RETURN_FAILED else. + */ + ReturnValue_t getType( uint32_t parameter_id, Type* type ); + /** * Method to check if a PID exists. * Does not lock, as there's no possibility to alter the list that is checked during run-time. @@ -123,7 +130,6 @@ public: bool exists(uint32_t parameterId); }; -//TODO: Remove this, if data pool is get by Satellite Manager -//Better make clean Singleton. +//We assume someone globally instantiates a DataPool. extern DataPool dataPool; #endif /* DATAPOOL_H_ */ diff --git a/datapool/DataPoolAdmin.cpp b/datapool/DataPoolAdmin.cpp index 34a1cfde..71a347f9 100644 --- a/datapool/DataPoolAdmin.cpp +++ b/datapool/DataPoolAdmin.cpp @@ -1,67 +1,126 @@ -/* - * DataPoolAdmin.cpp - * - * Created on: 05.12.2013 - * Author: baetz - */ - - - #include #include #include #include #include +#include +#include - -DataPoolAdmin::DataPoolAdmin(object_id_t objectId ) : SystemObject(objectId), commandQueue(), memoryHelper(this, &commandQueue){ +DataPoolAdmin::DataPoolAdmin(object_id_t objectId) : + SystemObject(objectId), storage(NULL), commandQueue(NULL), memoryHelper( + this, commandQueue), actionHelper(this, commandQueue) { + commandQueue = QueueFactory::instance()->createMessageQueue(); } -ReturnValue_t DataPoolAdmin::performOperation() { +DataPoolAdmin::~DataPoolAdmin() { + QueueFactory::instance()->deleteMessageQueue(commandQueue); +} + +ReturnValue_t DataPoolAdmin::performOperation(uint8_t opCode) { handleCommand(); return RETURN_OK; } MessageQueueId_t DataPoolAdmin::getCommandQueue() const { - return commandQueue.getId(); + return commandQueue->getId(); +} + +ReturnValue_t DataPoolAdmin::executeAction(ActionId_t actionId, + MessageQueueId_t commandedBy, const uint8_t* data, uint32_t size) { + if (actionId != SET_VALIDITY) { + return INVALID_ACTION_ID; + } + + if (size != 5) { + return INVALID_PARAMETERS; + } + + uint32_t address = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) + | data[3]; + + uint8_t valid = data[4]; + + uint32_t poolId = ::dataPool.PIDToDataPoolId(address); + + DataSet mySet; + PoolRawAccess variable(poolId, 0, &mySet, PoolVariableIF::VAR_READ_WRITE); + ReturnValue_t status = mySet.read(); + if (status != RETURN_OK) { + return INVALID_ADDRESS; + } + if (valid != 0) { + variable.setValid(PoolVariableIF::VALID); + } else { + variable.setValid(PoolVariableIF::INVALID); + } + + mySet.commit(); + + return EXECUTION_FINISHED; +} + +ReturnValue_t DataPoolAdmin::getParameter(uint8_t domainId, + uint16_t parameterId, ParameterWrapper* parameterWrapper, + const ParameterWrapper* newValues, uint16_t startAtIndex) { + return HasReturnvaluesIF::RETURN_FAILED; } void DataPoolAdmin::handleCommand() { CommandMessage command; - ReturnValue_t result = commandQueue.receiveMessage(&command); + ReturnValue_t result = commandQueue->receiveMessage(&command); if (result != RETURN_OK) { return; } + + result = actionHelper.handleActionMessage(&command); + + if (result == HasReturnvaluesIF::RETURN_OK) { + return; + } + + result = handleParameterCommand(&command); + if (result == HasReturnvaluesIF::RETURN_OK) { + return; + } + result = memoryHelper.handleMemoryCommand(&command); if (result != RETURN_OK) { - command.setToUnknownCommand(command.getCommand()); - commandQueue.reply( &command ); + command.setToUnknownCommand(); + commandQueue->reply(&command); } } ReturnValue_t DataPoolAdmin::handleMemoryLoad(uint32_t address, const uint8_t* data, uint32_t size, uint8_t** dataPointer) { - uint32_t poolId = ::dataPool.PIDToDataPoolId( address ); - uint8_t arrayIndex = ::dataPool.PIDToArrayIndex( address ); + uint32_t poolId = ::dataPool.PIDToDataPoolId(address); + uint8_t arrayIndex = ::dataPool.PIDToArrayIndex(address); DataSet testSet; - PoolRawAccess varToGetSize( poolId, arrayIndex, &testSet, PoolVariableIF::VAR_READ ); + PoolRawAccess varToGetSize(poolId, arrayIndex, &testSet, + PoolVariableIF::VAR_READ); ReturnValue_t status = testSet.read(); if (status != RETURN_OK) { return INVALID_ADDRESS; } uint8_t typeSize = varToGetSize.getSizeOfType(); - if ( size > varToGetSize.getSizeTillEnd() ) { + + if (size % typeSize != 0) { + return INVALID_SIZE; + } + + if (size > varToGetSize.getSizeTillEnd()) { return INVALID_SIZE; } const uint8_t* readPosition = data; - for ( ; size > 0; size -= typeSize ) { + + for (; size > 0; size -= typeSize) { DataSet rawSet; - PoolRawAccess variable( poolId, arrayIndex, &rawSet, PoolVariableIF::VAR_READ_WRITE ); + PoolRawAccess variable(poolId, arrayIndex, &rawSet, + PoolVariableIF::VAR_READ_WRITE); status = rawSet.read(); if (status == RETURN_OK) { - status = variable.setEntryFromBigEndian( readPosition, typeSize ); + status = variable.setEntryFromBigEndian(readPosition, typeSize); if (status == RETURN_OK) { - status = rawSet.commit(PoolVariableIF::VALID); + status = rawSet.commit(); } } arrayIndex += 1; @@ -72,27 +131,29 @@ ReturnValue_t DataPoolAdmin::handleMemoryLoad(uint32_t address, ReturnValue_t DataPoolAdmin::handleMemoryDump(uint32_t address, uint32_t size, uint8_t** dataPointer, uint8_t* copyHere) { - uint32_t poolId = ::dataPool.PIDToDataPoolId( address ); - uint8_t arrayIndex = ::dataPool.PIDToArrayIndex( address ); + uint32_t poolId = ::dataPool.PIDToDataPoolId(address); + uint8_t arrayIndex = ::dataPool.PIDToArrayIndex(address); DataSet testSet; - PoolRawAccess varToGetSize( poolId, arrayIndex, &testSet, PoolVariableIF::VAR_READ ); + PoolRawAccess varToGetSize(poolId, arrayIndex, &testSet, + PoolVariableIF::VAR_READ); ReturnValue_t status = testSet.read(); if (status != RETURN_OK) { return INVALID_ADDRESS; } uint8_t typeSize = varToGetSize.getSizeOfType(); - if ( size > varToGetSize.getSizeTillEnd() ) { + if (size > varToGetSize.getSizeTillEnd()) { return INVALID_SIZE; } uint8_t* ptrToCopy = copyHere; - for ( ; size > 0; size -= typeSize ) { + for (; size > 0; size -= typeSize) { DataSet rawSet; - PoolRawAccess variable( poolId, arrayIndex, &rawSet, PoolVariableIF::VAR_READ ); + PoolRawAccess variable(poolId, arrayIndex, &rawSet, + PoolVariableIF::VAR_READ); status = rawSet.read(); if (status == RETURN_OK) { uint32_t temp = 0; - status = variable.getEntryEndianSafe( ptrToCopy, &temp, size); - if ( status != RETURN_OK ) { + status = variable.getEntryEndianSafe(ptrToCopy, &temp, size); + if (status != RETURN_OK) { return RETURN_FAILED; } } else { @@ -105,8 +166,135 @@ ReturnValue_t DataPoolAdmin::handleMemoryDump(uint32_t address, uint32_t size, } ReturnValue_t DataPoolAdmin::initialize() { - if (memoryHelper.initialize() == RETURN_OK) { - return SystemObject::initialize(); + ReturnValue_t result = SystemObject::initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; } - return RETURN_FAILED; + + result = memoryHelper.initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + storage = objectManager->get(objects::IPC_STORE); + if (storage == NULL) { + return HasReturnvaluesIF::RETURN_FAILED; + } + + result = actionHelper.initialize(); + + return result; +} + +//mostly identical to ParameterHelper::handleParameterMessage() +ReturnValue_t DataPoolAdmin::handleParameterCommand(CommandMessage* command) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + switch (command->getCommand()) { + case ParameterMessage::CMD_PARAMETER_DUMP: { + uint8_t domain = HasParametersIF::getDomain( + ParameterMessage::getParameterId(command)); + uint16_t parameterId = HasParametersIF::getMatrixId( + ParameterMessage::getParameterId(command)); + + DataPoolParameterWrapper wrapper; + result = wrapper.set(domain, parameterId); + + if (result == HasReturnvaluesIF::RETURN_OK) { + result = sendParameter(command->getSender(), + ParameterMessage::getParameterId(command), &wrapper); + } + } + break; + case ParameterMessage::CMD_PARAMETER_LOAD: { + + uint8_t domain = HasParametersIF::getDomain( + ParameterMessage::getParameterId(command)); + uint16_t parameterId = HasParametersIF::getMatrixId( + ParameterMessage::getParameterId(command)); + uint8_t index = HasParametersIF::getIndex( + ParameterMessage::getParameterId(command)); + + const uint8_t *storedStream; + uint32_t storedStreamSize; + result = storage->getData(ParameterMessage::getStoreId(command), + &storedStream, &storedStreamSize); + if (result != HasReturnvaluesIF::RETURN_OK) { + break; + } + + ParameterWrapper streamWrapper; + result = streamWrapper.set(storedStream, storedStreamSize); + if (result != HasReturnvaluesIF::RETURN_OK) { + storage->deleteData(ParameterMessage::getStoreId(command)); + break; + } + + DataPoolParameterWrapper poolWrapper; + result = poolWrapper.set(domain, parameterId); + if (result != HasReturnvaluesIF::RETURN_OK) { + storage->deleteData(ParameterMessage::getStoreId(command)); + break; + } + + result = poolWrapper.copyFrom(&streamWrapper, index); + + storage->deleteData(ParameterMessage::getStoreId(command)); + + if (result == HasReturnvaluesIF::RETURN_OK) { + result = sendParameter(command->getSender(), + ParameterMessage::getParameterId(command), &poolWrapper); + } + } + break; + default: + return HasReturnvaluesIF::RETURN_FAILED; + } + + if (result != HasReturnvaluesIF::RETURN_OK) { + rejectCommand(command->getSender(), result, command->getCommand()); + } + + return HasReturnvaluesIF::RETURN_OK; + +} + +//identical to ParameterHelper::sendParameter() +ReturnValue_t DataPoolAdmin::sendParameter(MessageQueueId_t to, uint32_t id, + const DataPoolParameterWrapper* wrapper) { + uint32_t serializedSize = wrapper->getSerializedSize(); + + uint8_t *storeElement; + store_address_t address; + + ReturnValue_t result = storage->getFreeElement(&address, serializedSize, + &storeElement); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + uint32_t storeElementSize = 0; + + result = wrapper->serialize(&storeElement, &storeElementSize, + serializedSize, true); + + if (result != HasReturnvaluesIF::RETURN_OK) { + storage->deleteData(address); + return result; + } + + CommandMessage reply; + + ParameterMessage::setParameterDumpReply(&reply, id, address); + + commandQueue->sendMessage(to, &reply); + + return HasReturnvaluesIF::RETURN_OK; +} + +//identical to ParameterHelper::rejectCommand() +void DataPoolAdmin::rejectCommand(MessageQueueId_t to, ReturnValue_t reason, + Command_t initialCommand) { + CommandMessage reply; + reply.setReplyRejected(reason, initialCommand); + commandQueue->sendMessage(to, &reply); } diff --git a/datapool/DataPoolAdmin.h b/datapool/DataPoolAdmin.h index 8a066c78..448d78fb 100644 --- a/datapool/DataPoolAdmin.h +++ b/datapool/DataPoolAdmin.h @@ -1,35 +1,58 @@ -/* - * DataPoolAdmin.h - * - * Created on: 05.12.2013 - * Author: baetz - */ - #ifndef DATAPOOLADMIN_H_ #define DATAPOOLADMIN_H_ -#include #include +#include +#include #include #include #include +#include +#include +#include -class DataPoolAdmin : public ExecutableObjectIF, public AcceptsMemoryMessagesIF, public HasReturnvaluesIF, public SystemObject { -private: - MessageQueue commandQueue; - MemoryHelper memoryHelper; - void handleCommand(); +class DataPoolAdmin: public HasActionsIF, + public ExecutableObjectIF, + public AcceptsMemoryMessagesIF, + public HasReturnvaluesIF, + public ReceivesParameterMessagesIF, + public SystemObject { public: + static const ActionId_t SET_VALIDITY = 1; + DataPoolAdmin(object_id_t objectId); - ReturnValue_t performOperation(); + ~DataPoolAdmin(); + + ReturnValue_t performOperation(uint8_t opCode); MessageQueueId_t getCommandQueue() const; - ReturnValue_t handleMemoryLoad(uint32_t address, const uint8_t* data, uint32_t size, uint8_t** dataPointer); - ReturnValue_t handleMemoryDump(uint32_t address, uint32_t size, uint8_t** dataPointer, uint8_t* copyHere ); + ReturnValue_t handleMemoryLoad(uint32_t address, const uint8_t* data, + uint32_t size, uint8_t** dataPointer); + ReturnValue_t handleMemoryDump(uint32_t address, uint32_t size, + uint8_t** dataPointer, uint8_t* copyHere); + + ReturnValue_t executeAction(ActionId_t actionId, + MessageQueueId_t commandedBy, const uint8_t* data, uint32_t size); + + //not implemented as ParameterHelper is no used + ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, + ParameterWrapper *parameterWrapper, + const ParameterWrapper *newValues, uint16_t startAtIndex); + ReturnValue_t initialize(); +private: + StorageManagerIF *storage; + MessageQueueIF* commandQueue; + MemoryHelper memoryHelper; + SimpleActionHelper actionHelper; + void handleCommand(); + ReturnValue_t handleParameterCommand(CommandMessage *command); + ReturnValue_t sendParameter(MessageQueueId_t to, uint32_t id, + const DataPoolParameterWrapper* wrapper); + void rejectCommand(MessageQueueId_t to, ReturnValue_t reason, + Command_t initialCommand); }; - #endif /* DATAPOOLADMIN_H_ */ diff --git a/datapool/DataPoolParameterWrapper.cpp b/datapool/DataPoolParameterWrapper.cpp new file mode 100644 index 00000000..0ff2121d --- /dev/null +++ b/datapool/DataPoolParameterWrapper.cpp @@ -0,0 +1,181 @@ +#include "DataPoolParameterWrapper.h" + +//for returncodes +#include + +#include +#include + +DataPoolParameterWrapper::DataPoolParameterWrapper() : + type(Type::UNKNOWN_TYPE), rows(0), columns(0), poolId( + PoolVariableIF::NO_PARAMETER) { + +} + +DataPoolParameterWrapper::~DataPoolParameterWrapper() { + +} + +ReturnValue_t DataPoolParameterWrapper::set(uint8_t domainId, + uint16_t parameterId) { + poolId = (domainId << 16) + parameterId; + + DataSet mySet; + PoolRawAccess raw(poolId, 0, &mySet, PoolVariableIF::VAR_READ); + ReturnValue_t status = mySet.read(); + if (status != HasReturnvaluesIF::RETURN_OK) { + //should only fail for invalid pool id + return HasParametersIF::INVALID_MATRIX_ID; + } + + type = raw.getType(); + rows = raw.getArraySize(); + columns = 1; + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t DataPoolParameterWrapper::serialize(uint8_t** buffer, + uint32_t* size, const uint32_t max_size, bool bigEndian) const { + ReturnValue_t result; + + result = SerializeAdapter::serialize(&type, buffer, size, max_size, + bigEndian); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + result = SerializeAdapter::serialize(&columns, buffer, size, + max_size, bigEndian); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = SerializeAdapter::serialize(&rows, buffer, size, max_size, + bigEndian); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + for (uint8_t index = 0; index < rows; index++){ + DataSet mySet; + PoolRawAccess raw(poolId, index, &mySet,PoolVariableIF::VAR_READ); + mySet.read(); + result = raw.serialize(buffer,size,max_size,bigEndian); + if (result != HasReturnvaluesIF::RETURN_OK){ + return result; + } + } + return HasReturnvaluesIF::RETURN_OK; +} + +//same as ParameterWrapper +uint32_t DataPoolParameterWrapper::getSerializedSize() const { + uint32_t serializedSize = 0; + serializedSize += type.getSerializedSize(); + serializedSize += sizeof(rows); + serializedSize += sizeof(columns); + serializedSize += rows * columns * type.getSize(); + + return serializedSize; +} + +ReturnValue_t DataPoolParameterWrapper::deSerialize(const uint8_t** buffer, + int32_t* size, bool bigEndian) { + return HasReturnvaluesIF::RETURN_FAILED; +} + +template +ReturnValue_t DataPoolParameterWrapper::deSerializeData(uint8_t startingRow, + uint8_t startingColumn, const void* from, uint8_t fromRows) { + //treat from as a continuous Stream as we copy all of it + const uint8_t *fromAsStream = (const uint8_t *) from; + + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + + for (uint8_t fromRow = 0; fromRow < fromRows; fromRow++) { + + DataSet mySet; + PoolRawAccess raw(poolId, startingRow + fromRow, &mySet, + PoolVariableIF::VAR_READ_WRITE); + mySet.read(); + + result = raw.setEntryFromBigEndian(fromAsStream, sizeof(T)); + + fromAsStream += sizeof(T); + + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + mySet.commit(); + } + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t DataPoolParameterWrapper::copyFrom(const ParameterWrapper* from, + uint16_t startWritingAtIndex) { + if (poolId == PoolVariableIF::NO_PARAMETER) { + return ParameterWrapper::NOT_SET; + } + + if (type != from->type) { + return ParameterWrapper::DATATYPE_MISSMATCH; + } + + //check if from fits into this + uint8_t startingRow = startWritingAtIndex / columns; + uint8_t startingColumn = startWritingAtIndex % columns; + + if ((from->rows > (rows - startingRow)) + || (from->columns > (columns - startingColumn))) { + return ParameterWrapper::TOO_BIG; + } + + ReturnValue_t result; + //copy data + if (from->pointsToStream) { + switch (type) { + case Type::UINT8_T: + result = deSerializeData(startingRow, startingColumn, + from->readonlyData, from->rows); + break; + case Type::INT8_T: + result = deSerializeData(startingRow, startingColumn, + from->readonlyData, from->rows); + break; + case Type::UINT16_T: + result = deSerializeData(startingRow, startingColumn, + from->readonlyData, from->rows); + break; + case Type::INT16_T: + result = deSerializeData(startingRow, startingColumn, + from->readonlyData, from->rows); + break; + case Type::UINT32_T: + result = deSerializeData(startingRow, startingColumn, + from->readonlyData, from->rows); + break; + case Type::INT32_T: + result = deSerializeData(startingRow, startingColumn, + from->readonlyData, from->rows); + break; + case Type::FLOAT: + result = deSerializeData(startingRow, startingColumn, + from->readonlyData, from->rows); + break; + case Type::DOUBLE: + result = deSerializeData(startingRow, startingColumn, + from->readonlyData, from->rows); + break; + default: + result = ParameterWrapper::UNKNOW_DATATYPE; + break; + } + } else { + //not supported + return HasReturnvaluesIF::RETURN_FAILED; + } + + return result; +} diff --git a/datapool/DataPoolParameterWrapper.h b/datapool/DataPoolParameterWrapper.h new file mode 100644 index 00000000..faadf659 --- /dev/null +++ b/datapool/DataPoolParameterWrapper.h @@ -0,0 +1,38 @@ +#ifndef DATAPOOLPARAMETERWRAPPER_H_ +#define DATAPOOLPARAMETERWRAPPER_H_ + +#include +#include + +class DataPoolParameterWrapper: public SerializeIF { +public: + DataPoolParameterWrapper(); + virtual ~DataPoolParameterWrapper(); + + ReturnValue_t set(uint8_t domainId, uint16_t parameterId); + + virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, + const uint32_t max_size, bool bigEndian) const; + + virtual uint32_t getSerializedSize() const; + + virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, + bool bigEndian); + + ReturnValue_t copyFrom(const ParameterWrapper *from, + uint16_t startWritingAtIndex); + +private: + Type type; + uint8_t rows; + uint8_t columns; + + uint32_t poolId; + + template + ReturnValue_t deSerializeData(uint8_t startingRow, uint8_t startingColumn, + const void *from, uint8_t fromRows); + +}; + +#endif /* DATAPOOLPARAMETERWRAPPER_H_ */ diff --git a/datapool/DataSet.cpp b/datapool/DataSet.cpp index 4f9e3792..b4725c73 100644 --- a/datapool/DataSet.cpp +++ b/datapool/DataSet.cpp @@ -1,10 +1,3 @@ -/* - * DataSet.cpp - * - * Created on: 24.10.2012 - * Author: baetz - */ - #include #include @@ -45,12 +38,7 @@ ReturnValue_t DataSet::read() { } ReturnValue_t DataSet::commit(uint8_t valid) { - for (uint16_t count = 0; count < fill_count; count++) { - if (registeredVariables[count]->getReadWriteMode() - != PoolVariableIF::VAR_READ) { - registeredVariables[count]->setValid(valid); - } - } + setValid(valid); return commit(); } @@ -139,6 +127,15 @@ uint32_t DataSet::getSerializedSize() const { return size; } +void DataSet::setValid(uint8_t valid) { + for (uint16_t count = 0; count < fill_count; count++) { + if (registeredVariables[count]->getReadWriteMode() + != PoolVariableIF::VAR_READ) { + registeredVariables[count]->setValid(valid); + } + } +} + ReturnValue_t DataSet::deSerialize(const uint8_t** buffer, int32_t* size, bool bigEndian) { ReturnValue_t result = RETURN_FAILED; diff --git a/datapool/DataSet.h b/datapool/DataSet.h index a15e023f..982be692 100644 --- a/datapool/DataSet.h +++ b/datapool/DataSet.h @@ -38,7 +38,7 @@ */ class DataSet: public DataSetIF, public HasReturnvaluesIF, public SerializeIF { private: - //TODO we could use a linked list of datapool variables + //SHOULDDO we could use a linked list of datapool variables static const uint8_t DATA_SET_MAX_SIZE = 63; //!< This definition sets the maximum number of variables to register in one DataSet. /** @@ -75,7 +75,7 @@ private: uint8_t freeDataPoolLock(); public: - static const uint8_t INTERFACE_ID = DATA_SET_CLASS; + static const uint8_t INTERFACE_ID = CLASS_ID::DATA_SET_CLASS; static const ReturnValue_t INVALID_PARAMETER_DEFINITION = MAKE_RETURN_CODE( 0x01 ); static const ReturnValue_t SET_WAS_ALREADY_READ = MAKE_RETURN_CODE( 0x02 ); @@ -139,6 +139,13 @@ public: */ void registerVariable(PoolVariableIF* variable); + /** + * Set the valid information of all variables contained in the set which are not readonly + * + * @param valid Validity information from PoolVariableIF. + */ + void setValid(uint8_t valid); + ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, const uint32_t max_size, bool bigEndian) const; diff --git a/datapool/DataSetIF.h b/datapool/DataSetIF.h index dfbafc2d..7741477d 100644 --- a/datapool/DataSetIF.h +++ b/datapool/DataSetIF.h @@ -12,9 +12,6 @@ #ifndef DATASETIF_H_ #define DATASETIF_H_ - -#include - class PoolVariableIF; /** diff --git a/datapool/HkSwitchHelper.cpp b/datapool/HkSwitchHelper.cpp new file mode 100644 index 00000000..f6e572ac --- /dev/null +++ b/datapool/HkSwitchHelper.cpp @@ -0,0 +1,75 @@ +#include +#include +#include + +HkSwitchHelper::HkSwitchHelper(EventReportingProxyIF* eventProxy) : + commandActionHelper(this), eventProxy(eventProxy) { + actionQueue = QueueFactory::instance()->createMessageQueue(); +} + +HkSwitchHelper::~HkSwitchHelper() { + // TODO Auto-generated destructor stub +} + +ReturnValue_t HkSwitchHelper::initialize() { + ReturnValue_t result = commandActionHelper.initialize(); + + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + return result; +} + +ReturnValue_t HkSwitchHelper::performOperation(uint8_t operationCode) { + CommandMessage message; + while (actionQueue->receiveMessage(&message) == HasReturnvaluesIF::RETURN_OK) { + ReturnValue_t result = commandActionHelper.handleReply(&message); + if (result == HasReturnvaluesIF::RETURN_OK) { + continue; + } + message.setToUnknownCommand(); + actionQueue->reply(&message); + } + + return HasReturnvaluesIF::RETURN_OK; +} + +void HkSwitchHelper::stepSuccessfulReceived(ActionId_t actionId, uint8_t step) { +} + +void HkSwitchHelper::stepFailedReceived(ActionId_t actionId, uint8_t step, + ReturnValue_t returnCode) { + eventProxy->forwardEvent(SWITCHING_TM_FAILED, returnCode, actionId); +} + +void HkSwitchHelper::dataReceived(ActionId_t actionId, const uint8_t* data, + uint32_t size) { +} + +void HkSwitchHelper::completionSuccessfulReceived(ActionId_t actionId) { +} + +void HkSwitchHelper::completionFailedReceived(ActionId_t actionId, + ReturnValue_t returnCode) { + eventProxy->forwardEvent(SWITCHING_TM_FAILED, returnCode, actionId); +} + +ReturnValue_t HkSwitchHelper::switchHK(SerializeIF* sids, bool enable) { + ActionId_t action = HKService::DISABLE_HK; + if (enable) { + action = HKService::ENABLE_HK; + } + + ReturnValue_t result = commandActionHelper.commandAction( + objects::PUS_HK_SERVICE, action, sids); + + if (result != HasReturnvaluesIF::RETURN_OK) { + eventProxy->forwardEvent(SWITCHING_TM_FAILED, result); + } + return result; +} + +MessageQueueIF* HkSwitchHelper::getCommandQueuePtr() { + return actionQueue; +} diff --git a/datapool/HkSwitchHelper.h b/datapool/HkSwitchHelper.h new file mode 100644 index 00000000..067ab88d --- /dev/null +++ b/datapool/HkSwitchHelper.h @@ -0,0 +1,44 @@ +#ifndef FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_ +#define FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_ + +#include +#include +#include + +//TODO this class violations separation between mission and framework +//but it is only a transitional solution until the Datapool is +//implemented decentrally + +class HkSwitchHelper: public ExecutableObjectIF, public CommandsActionsIF { +public: + + static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::HK; + static const Event SWITCHING_TM_FAILED = MAKE_EVENT(1, SEVERITY::LOW); //!< Commanding the HK Service failed, p1: error code, p2 action: 0 disable / 1 enable + + HkSwitchHelper(EventReportingProxyIF *eventProxy); + virtual ~HkSwitchHelper(); + + ReturnValue_t initialize(); + + virtual ReturnValue_t performOperation(uint8_t operationCode = 0); + + ReturnValue_t switchHK(SerializeIF *sids, bool enable); + +protected: + virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step); + virtual void stepFailedReceived(ActionId_t actionId, uint8_t step, + ReturnValue_t returnCode); + virtual void dataReceived(ActionId_t actionId, const uint8_t* data, + uint32_t size); + virtual void completionSuccessfulReceived(ActionId_t actionId); + virtual void completionFailedReceived(ActionId_t actionId, + ReturnValue_t returnCode); + virtual MessageQueueIF* getCommandQueuePtr(); + +private: + CommandActionHelper commandActionHelper; + MessageQueueIF* actionQueue; + EventReportingProxyIF *eventProxy; +}; + +#endif /* FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_ */ diff --git a/datapool/Makefile b/datapool/Makefile deleted file mode 100755 index 97775d60..00000000 --- a/datapool/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash -# -# OPUS makefile -# -# Created on: Mar 04, 2010 -# Author: ziemke -# Author: Claas Ziemke -# Copyright 2010, Claas Ziemke -# - -BASEDIR=../../ -include $(BASEDIR)/options.mk - -OBJ = $(BUILDDIR)/OPUSDataPool.o \ - $(BUILDDIR)/OPUSDataPoolItem.o \ - $(BUILDDIR)/OPUSDataSet.o \ - $(BUILDDIR)/OPUSRegVar.o - -all: $(OBJ) - -$(BUILDDIR)/%.o: %.cpp %.h - $(CPP) $(CFLAGS) $(DEFINES) $(CCOPT) ${INCLUDE} -c $< -o $@ - -clean: - $(RM) *.o *.gcno *.gcda diff --git a/datapool/PIDReader.h b/datapool/PIDReader.h index 452abe40..299cc2fe 100644 --- a/datapool/PIDReader.h +++ b/datapool/PIDReader.h @@ -1,10 +1,3 @@ -/* - * PIDReader.h - * - * Created on: 14.05.2014 - * Author: baetz - */ - #ifndef PIDREADER_H_ #define PIDREADER_H_ #include diff --git a/datapool/PIDReaderList.h b/datapool/PIDReaderList.h index 3eb8fc5d..07d1b8e6 100644 --- a/datapool/PIDReaderList.h +++ b/datapool/PIDReaderList.h @@ -1,10 +1,3 @@ -/* - * PIDReaderList.h - * - * Created on: 15.07.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_DATAPOOL_PIDREADERLIST_H_ #define FRAMEWORK_DATAPOOL_PIDREADERLIST_H_ diff --git a/datapool/PoolEntry.cpp b/datapool/PoolEntry.cpp index bc882ae3..c303e56b 100644 --- a/datapool/PoolEntry.cpp +++ b/datapool/PoolEntry.cpp @@ -1,10 +1,3 @@ -/* - * PoolEntry.cpp - * - * Created on: Oct 25, 2012 - * Author: baetz - */ - #include #include diff --git a/datapool/PoolEntry.h b/datapool/PoolEntry.h index 5277d28b..ce41a991 100644 --- a/datapool/PoolEntry.h +++ b/datapool/PoolEntry.h @@ -3,7 +3,8 @@ #include -#include +#include +#include /** * \brief This is a small helper class that defines a single data pool entry. * diff --git a/datapool/PoolEntryIF.h b/datapool/PoolEntryIF.h index 6ea1c8b7..514e67ef 100644 --- a/datapool/PoolEntryIF.h +++ b/datapool/PoolEntryIF.h @@ -15,6 +15,7 @@ #include + /** * \brief This interface defines the access possibilities to a single data pool entry. * diff --git a/datapool/PoolRawAccess.cpp b/datapool/PoolRawAccess.cpp index d1e35b82..ead7676e 100644 --- a/datapool/PoolRawAccess.cpp +++ b/datapool/PoolRawAccess.cpp @@ -1,18 +1,13 @@ -/* - * PoolRawAccess.cpp - * - * Created on: 29.10.2012 - * Author: baetz - */ - #include #include #include #include +#include + PoolRawAccess::PoolRawAccess(uint32_t set_id, uint8_t setArrayEntry, DataSetIF* data_set, ReadWriteMode_t setReadWriteMode) : - dataPoolId(set_id), arrayEntry(setArrayEntry), valid(false), typeSize( - 0), sizeTillEnd(0), readWriteMode(setReadWriteMode) { + dataPoolId(set_id), arrayEntry(setArrayEntry), valid(false), type(Type::UNKNOWN_TYPE), typeSize( + 0), arraySize(0), sizeTillEnd(0), readWriteMode(setReadWriteMode) { memset(value, 0, sizeof(value)); if (data_set != NULL) { data_set->registerVariable(this); @@ -28,7 +23,9 @@ ReturnValue_t PoolRawAccess::read() { if (read_out != NULL) { valid = read_out->getValid(); if (read_out->getSize() > arrayEntry) { + arraySize = read_out->getSize(); typeSize = read_out->getByteSize() / read_out->getSize(); + type = read_out->getType(); if (typeSize <= sizeof(value)) { uint16_t arrayPosition = arrayEntry * typeSize; sizeTillEnd = read_out->getByteSize() - arrayPosition; @@ -92,10 +89,18 @@ ReturnValue_t PoolRawAccess::getEntryEndianSafe(uint8_t* buffer, return HasReturnvaluesIF::RETURN_OK; } +Type PoolRawAccess::getType() { + return type; +} + uint8_t PoolRawAccess::getSizeOfType() { return typeSize; } +uint8_t PoolRawAccess::getArraySize(){ + return arraySize; +} + uint32_t PoolRawAccess::getDataPoolId() const { return dataPoolId; } diff --git a/datapool/PoolRawAccess.h b/datapool/PoolRawAccess.h index 1cc51c85..3e2bd7ae 100644 --- a/datapool/PoolRawAccess.h +++ b/datapool/PoolRawAccess.h @@ -25,10 +25,18 @@ private: * \brief The valid information as it was stored in the data pool is copied to this attribute. */ uint8_t valid; + /** + * \brief This value contains the type of the data pool entry. + */ + Type type; /** * \brief This value contains the size of the data pool entry in bytes. */ uint8_t typeSize; + /** + * The size of the DP array (single values return 1) + */ + uint8_t arraySize; /** * The size (in bytes) from the selected entry till the end of this DataPool variable. */ @@ -57,7 +65,7 @@ protected: */ ReturnValue_t commit(); public: - static const uint8_t INTERFACE_ID = POOL_RAW_ACCESS_CLASS; + static const uint8_t INTERFACE_ID = CLASS_ID::POOL_RAW_ACCESS_CLASS; static const ReturnValue_t INCORRECT_SIZE = MAKE_RETURN_CODE(0x01); static const ReturnValue_t DATA_POOL_ACCESS_FAILED = MAKE_RETURN_CODE(0x02); uint8_t value[RAW_MAX_SIZE]; @@ -100,10 +108,19 @@ public: */ ReturnValue_t setEntryFromBigEndian(const uint8_t* buffer, uint32_t setSize); + /** + * \brief This operation returns the type of the entry currently stored. + */ + Type getType(); /** * \brief This operation returns the size of the entry currently stored. */ uint8_t getSizeOfType(); + /** + * + * @return the size of the datapool array + */ + uint8_t getArraySize(); /** * \brief This operation returns the data pool id of the variable. */ diff --git a/datapool/PoolVarList.h b/datapool/PoolVarList.h index 1a8bd880..90c9f178 100644 --- a/datapool/PoolVarList.h +++ b/datapool/PoolVarList.h @@ -1,10 +1,3 @@ -/* - * PoolVarList.h - * - * Created on: 06.03.2014 - * Author: baetz - */ - #ifndef POOLVARLIST_H_ #define POOLVARLIST_H_ diff --git a/devicehandlers/AcceptsDeviceResponsesIF.h b/devicehandlers/AcceptsDeviceResponsesIF.h new file mode 100644 index 00000000..0eedae88 --- /dev/null +++ b/devicehandlers/AcceptsDeviceResponsesIF.h @@ -0,0 +1,23 @@ +/** + * @file AcceptsDeviceResponsesIF.h + * @brief This file defines the AcceptsDeviceResponsesIF class. + * @date 15.05.2013 + * @author baetz + */ + +#ifndef ACCEPTSDEVICERESPONSESIF_H_ +#define ACCEPTSDEVICERESPONSESIF_H_ + +#include + +class AcceptsDeviceResponsesIF { +public: + /** + * Default empty virtual destructor. + */ + virtual ~AcceptsDeviceResponsesIF() { +} +virtual MessageQueueId_t getDeviceQueue() = 0; +}; + +#endif /* ACCEPTSDEVICERESPONSESIF_H_ */ diff --git a/devicehandlers/AssemblyBase.cpp b/devicehandlers/AssemblyBase.cpp index ae43e896..c250cf73 100644 --- a/devicehandlers/AssemblyBase.cpp +++ b/devicehandlers/AssemblyBase.cpp @@ -40,11 +40,6 @@ void AssemblyBase::doStartTransition(Mode_t mode, Submode_t submode) { ReturnValue_t result = commandChildren(mode, submode); if (result == NEED_SECOND_STEP) { internalState = STATE_NEED_SECOND_STEP; - } else if (result != RETURN_OK) { - //TODO: Debug - debug << std::hex << getObjectId() - << ": AssemblyBase::commandChildren returned: " << result - << std::dec << std::endl; } } @@ -140,7 +135,6 @@ void AssemblyBase::handleModeTransitionFailed(ReturnValue_t result) { if (targetMode == MODE_OFF) { triggerEvent(CHILD_PROBLEMS, result); internalState = STATE_NONE; - //TODO: Maybe go to ERROR_ON here. Does this cause problems in subsystem? setMode(targetMode, targetSubmode); } else { if (handleChildrenChangedHealth()) { @@ -157,7 +151,7 @@ void AssemblyBase::sendHealthCommand(MessageQueueId_t sendTo, CommandMessage command; HealthMessage::setHealthMessage(&command, HealthMessage::HEALTH_SET, health); - if (commandQueue.sendMessage(sendTo, &command) == RETURN_OK) { + if (commandQueue->sendMessage(sendTo, &command) == RETURN_OK) { commandsOutstanding++; } } diff --git a/devicehandlers/AssemblyBase.h b/devicehandlers/AssemblyBase.h index 131f0818..ee121032 100644 --- a/devicehandlers/AssemblyBase.h +++ b/devicehandlers/AssemblyBase.h @@ -7,7 +7,7 @@ class AssemblyBase: public SubsystemBase { public: - static const uint8_t INTERFACE_ID = ASSEMBLY_BASE; + static const uint8_t INTERFACE_ID = CLASS_ID::ASSEMBLY_BASE; static const ReturnValue_t NEED_SECOND_STEP = MAKE_RETURN_CODE(0x01); static const ReturnValue_t NEED_TO_RECONFIGURE = MAKE_RETURN_CODE(0x02); static const ReturnValue_t MODE_FALLBACK = MAKE_RETURN_CODE(0x03); diff --git a/devicehandlers/ChildHandlerBase.cpp b/devicehandlers/ChildHandlerBase.cpp index c879c597..50a5c07e 100644 --- a/devicehandlers/ChildHandlerBase.cpp +++ b/devicehandlers/ChildHandlerBase.cpp @@ -6,7 +6,7 @@ ChildHandlerBase::ChildHandlerBase(uint32_t ioBoardAddress, object_id_t setObjectId, object_id_t deviceCommunication, uint32_t maxDeviceReplyLen, uint8_t setDeviceSwitch, uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId, - uint32_t parent, FDIRBase* customFdir, uint32_t cmdQueueSize) : + uint32_t parent, FailureIsolationBase* customFdir, uint32_t cmdQueueSize) : DeviceHandlerBase(ioBoardAddress, setObjectId, maxDeviceReplyLen, setDeviceSwitch, deviceCommunication, thermalStatePoolId, thermalRequestPoolId, (customFdir == NULL? &childHandlerFdir : customFdir), cmdQueueSize), parentId( diff --git a/devicehandlers/ChildHandlerBase.h b/devicehandlers/ChildHandlerBase.h index 7b73d559..3879f66f 100644 --- a/devicehandlers/ChildHandlerBase.h +++ b/devicehandlers/ChildHandlerBase.h @@ -10,7 +10,7 @@ public: object_id_t deviceCommunication, uint32_t maxDeviceReplyLen, uint8_t setDeviceSwitch, uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId, uint32_t parent, - FDIRBase* customFdir = NULL, + FailureIsolationBase* customFdir = NULL, uint32_t cmdQueueSize = 20); virtual ~ChildHandlerBase(); diff --git a/devicehandlers/ChildHandlerFDIR.cpp b/devicehandlers/ChildHandlerFDIR.cpp index ece87c19..1bba47fe 100644 --- a/devicehandlers/ChildHandlerFDIR.cpp +++ b/devicehandlers/ChildHandlerFDIR.cpp @@ -1,14 +1,7 @@ -/* - * ChildHandlerFDIR.cpp - * - * Created on: 08.02.2016 - * Author: baetz - */ - #include ChildHandlerFDIR::ChildHandlerFDIR(object_id_t owner, object_id_t faultTreeParent, uint32_t recoveryCount) : - DeviceHandlerFDIR(owner, faultTreeParent) { + DeviceHandlerFailureIsolation(owner, faultTreeParent) { recoveryCounter.setFailureThreshold(recoveryCount); } diff --git a/devicehandlers/ChildHandlerFDIR.h b/devicehandlers/ChildHandlerFDIR.h index 78b1c655..7df9d238 100644 --- a/devicehandlers/ChildHandlerFDIR.h +++ b/devicehandlers/ChildHandlerFDIR.h @@ -1,25 +1,18 @@ -/* - * ChildHandlerFDIR.h - * - * Created on: 08.02.2016 - * Author: baetz - */ - #ifndef FRAMEWORK_DEVICEHANDLERS_CHILDHANDLERFDIR_H_ #define FRAMEWORK_DEVICEHANDLERS_CHILDHANDLERFDIR_H_ -#include +#include /** * Very simple extension to normal FDIR. * Does not have a default fault tree parent and * allows to make the recovery count settable to 0. */ -class ChildHandlerFDIR: public DeviceHandlerFDIR { +class ChildHandlerFDIR: public DeviceHandlerFailureIsolation { public: ChildHandlerFDIR(object_id_t owner, object_id_t faultTreeParent = NO_FAULT_TREE_PARENT, uint32_t recoveryCount = 0); - ~ChildHandlerFDIR(); + virtual ~ChildHandlerFDIR(); protected: static const object_id_t NO_FAULT_TREE_PARENT = 0; }; diff --git a/devicehandlers/DeviceCommunicationIF.h b/devicehandlers/DeviceCommunicationIF.h index 2ff943b8..e0aca573 100644 --- a/devicehandlers/DeviceCommunicationIF.h +++ b/devicehandlers/DeviceCommunicationIF.h @@ -6,7 +6,7 @@ class DeviceCommunicationIF: public HasReturnvaluesIF { public: - static const uint8_t INTERFACE_ID = DEVICE_COMMUNICATION_IF; + static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_COMMUNICATION_IF; static const ReturnValue_t INVALID_COOKIE_TYPE = MAKE_RETURN_CODE(0x01); static const ReturnValue_t NOT_ACTIVE = MAKE_RETURN_CODE(0x02); @@ -39,7 +39,7 @@ public: virtual void close(Cookie *cookie) = 0; - //TODO can data be const? + //SHOULDDO can data be const? virtual ReturnValue_t sendMessage(Cookie *cookie, uint8_t *data, uint32_t len) = 0; diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index cffe8220..2bb9e6c5 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -1,52 +1,58 @@ -/* - * DeviceHandlerBase.cpp - * - * Created on: 30.10.2012 - * Author: mohr - */ - -#include -#include -#include #include #include #include +#include #include #include #include #include -#include -#include #include #include -#include -#include +#include +#include + +object_id_t DeviceHandlerBase::powerSwitcherId = 0; +object_id_t DeviceHandlerBase::rawDataReceiverId = 0; +object_id_t DeviceHandlerBase::defaultFDIRParentId = 0; DeviceHandlerBase::DeviceHandlerBase(uint32_t ioBoardAddress, object_id_t setObjectId, uint32_t maxDeviceReplyLen, uint8_t setDeviceSwitch, object_id_t deviceCommunication, uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId, - FDIRBase* fdirInstance, uint32_t cmdQueueSize) : + FailureIsolationBase* fdirInstance, uint32_t cmdQueueSize) : SystemObject(setObjectId), rawPacket(0), rawPacketLen(0), mode( MODE_OFF), submode(SUBMODE_NONE), pstStep(0), maxDeviceReplyLen( - maxDeviceReplyLen), wiretappingMode(OFF), theOneWhoReceivesRawTraffic( - 0), storedRawData(StorageManagerIF::INVALID_ADDRESS), theOneWhoWantsToReadRawTraffic( - 0), powerSwitcher(NULL), IPCStore(NULL), deviceCommunicationId( - deviceCommunication), communicationInterface(NULL), cookie( - NULL), commandQueue(cmdQueueSize, CommandMessage::MAX_MESSAGE_SIZE), deviceThermalStatePoolId( - thermalStatePoolId), deviceThermalRequestPoolId( + maxDeviceReplyLen), wiretappingMode(OFF), defaultRawReceiver(0), storedRawData( + StorageManagerIF::INVALID_ADDRESS), requestedRawTraffic(0), powerSwitcher( + NULL), IPCStore(NULL), deviceCommunicationId(deviceCommunication), communicationInterface( + NULL), cookie( + NULL), commandQueue(NULL), deviceThermalStatePoolId(thermalStatePoolId), deviceThermalRequestPoolId( thermalRequestPoolId), healthHelper(this, setObjectId), modeHelper( this), parameterHelper(this), childTransitionFailure(RETURN_OK), ignoreMissedRepliesCount( - 0), fdirInstance(fdirInstance), defaultFDIRUsed( - fdirInstance == NULL), switchOffWasReported( - false), cookieInfo(), ioBoardAddress(ioBoardAddress), timeoutStart(0), childTransitionDelay( - 5000), transitionSourceMode(_MODE_POWER_DOWN), transitionSourceSubMode( - SUBMODE_NONE), deviceSwitch(setDeviceSwitch), actionHelper( - this, &commandQueue) { + 0), fdirInstance(fdirInstance), hkSwitcher(this), defaultFDIRUsed( + fdirInstance == NULL), switchOffWasReported(false), executingTask( + NULL), actionHelper(this, commandQueue), cookieInfo(), ioBoardAddress( +//======= +// NULL), IPCStore(NULL), deviceCommunicationId(deviceCommunication), communicationInterface( +// NULL), cookie( +// NULL), commandQueue(cmdQueueSize, CommandMessage::MAX_MESSAGE_SIZE), deviceThermalStatePoolId( +// thermalStatePoolId), deviceThermalRequestPoolId( +// thermalRequestPoolId), healthHelper(this, setObjectId), modeHelper( +// this), parameterHelper(this), childTransitionFailure(RETURN_OK), ignoreMissedRepliesCount( +// 0), fdirInstance(fdirInstance), defaultFDIRUsed( +// fdirInstance == NULL), switchOffWasReported(false), actionHelper( +// this, &commandQueue), cookieInfo(), ioBoardAddress( +//>>>>>>> makefile + ioBoardAddress), timeoutStart(0), childTransitionDelay(5000), transitionSourceMode( + _MODE_POWER_DOWN), transitionSourceSubMode(SUBMODE_NONE), deviceSwitch( + setDeviceSwitch) { + commandQueue = QueueFactory::instance()->createMessageQueue(cmdQueueSize, + CommandMessage::MAX_MESSAGE_SIZE); cookieInfo.state = COOKIE_UNUSED; insertInCommandMap(RAW_COMMAND_ID); if (this->fdirInstance == NULL) { - this->fdirInstance = new DeviceHandlerFDIR(setObjectId); + this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId, + defaultFDIRParentId); } } @@ -55,10 +61,10 @@ DeviceHandlerBase::~DeviceHandlerBase() { if (defaultFDIRUsed) { delete fdirInstance; } - + QueueFactory::instance()->deleteMessageQueue(commandQueue); } -void DeviceHandlerBase::performInPST(uint8_t counter) { +ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { this->pstStep = counter; if (counter == 0) { @@ -68,9 +74,10 @@ void DeviceHandlerBase::performInPST(uint8_t counter) { checkSwitchState(); decrementDeviceReplyMap(); fdirInstance->checkForFailures(); + hkSwitcher.performOperation(); } if (mode == MODE_OFF) { - return; + return RETURN_OK; } switch (getRmapAction()) { case SEND_WRITE: @@ -92,7 +99,7 @@ void DeviceHandlerBase::performInPST(uint8_t counter) { default: break; } - + return RETURN_OK; } void DeviceHandlerBase::decrementDeviceReplyMap() { @@ -118,7 +125,7 @@ void DeviceHandlerBase::readCommandQueue() { } CommandMessage message; - ReturnValue_t result = commandQueue.receiveMessage(&message); + ReturnValue_t result = commandQueue->receiveMessage(&message); if (result != RETURN_OK) { return; } @@ -171,7 +178,7 @@ void DeviceHandlerBase::doStateMachine() { break; } uint32_t currentUptime; - OSAL::getUptime(¤tUptime); + Clock::getUptime(¤tUptime); if (currentUptime - timeoutStart >= childTransitionDelay) { triggerEvent(MODE_TRANSITION_FAILED, childTransitionFailure, 0); setMode(transitionSourceMode, transitionSourceSubMode); @@ -189,7 +196,7 @@ void DeviceHandlerBase::doStateMachine() { break; case _MODE_WAIT_ON: { uint32_t currentUptime; - OSAL::getUptime(¤tUptime); + Clock::getUptime(¤tUptime); if (currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) { triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0); @@ -209,7 +216,7 @@ void DeviceHandlerBase::doStateMachine() { break; case _MODE_WAIT_OFF: { uint32_t currentUptime; - OSAL::getUptime(¤tUptime); + Clock::getUptime(¤tUptime); if (currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) { triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0); @@ -347,6 +354,7 @@ void DeviceHandlerBase::setTransition(Mode_t modeTo, Submode_t submodeTo) { } void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) { + changeHK(mode, submode, false); submode = newSubmode; mode = newMode; modeChanged(); @@ -355,7 +363,7 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) { modeHelper.modeChanged(newMode, newSubmode); announceMode(false); } - OSAL::getUptime(&timeoutStart); + Clock::getUptime(&timeoutStart); if (mode == MODE_OFF) { DataSet mySet; @@ -367,6 +375,7 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) { } mySet.commit(PoolVariableIF::VALID); } + changeHK(mode, submode, true); } void DeviceHandlerBase::setMode(Mode_t newMode) { @@ -378,10 +387,10 @@ void DeviceHandlerBase::replyReturnvalueToCommand(ReturnValue_t status, //This is actually the reply protocol for raw and misc dh commands. if (status == RETURN_OK) { CommandMessage reply(CommandMessage::REPLY_COMMAND_OK, 0, parameter); - commandQueue.reply(&reply); + commandQueue->reply(&reply); } else { CommandMessage reply(CommandMessage::REPLY_REJECTED, status, parameter); - commandQueue.reply(&reply); + commandQueue->reply(&reply); } } @@ -455,8 +464,7 @@ void DeviceHandlerBase::doGetWrite() { ReturnValue_t result = communicationInterface->getSendSuccess(cookie); if (result == RETURN_OK) { if (wiretappingMode == RAW) { - replyRawData(rawPacket, rawPacketLen, - theOneWhoWantsToReadRawTraffic, true); + replyRawData(rawPacket, rawPacketLen, requestedRawTraffic, true); } //We need to distinguish here, because a raw command never expects a reply. (Could be done in eRIRM, but then child implementations need to be careful. result = enableReplyInReplyMap(cookieInfo.pendingCommand); @@ -515,19 +523,11 @@ void DeviceHandlerBase::doGetRead() { return; if (wiretappingMode == RAW) { - replyRawData(receivedData, receivedDataLen, - theOneWhoWantsToReadRawTraffic); + replyRawData(receivedData, receivedDataLen, requestedRawTraffic); } if (mode == MODE_RAW) { - if ((wiretappingMode == RAW) - && (theOneWhoReceivesRawTraffic - == theOneWhoWantsToReadRawTraffic)) { - //The raw packet was already sent by the wiretapping service - } else { - replyRawData(receivedData, receivedDataLen, - theOneWhoReceivesRawTraffic); - } + replyRawReplyIfnotWiretapped(receivedData, receivedDataLen); } else { //The loop may not execute more often than the number of received bytes (worst case). //This approach avoids infinite loops due to buggy scanForReply routines (seen in bug 1077). @@ -537,12 +537,12 @@ void DeviceHandlerBase::doGetRead() { &foundLen); switch (result) { case RETURN_OK: - handleReply(receivedData, foundId); + handleReply(receivedData, foundId, foundLen); break; case APERIODIC_REPLY: { - DataSet dataSet; result = interpretDeviceReply(foundId, receivedData); if (result != RETURN_OK) { + replyRawReplyIfnotWiretapped(receivedData, foundLen); triggerEvent(DEVICE_INTERPRETING_REPLY_FAILED, result, foundId); } @@ -552,6 +552,7 @@ void DeviceHandlerBase::doGetRead() { break; default: //We need to wait for timeout.. don't know what command failed and who sent it. + replyRawReplyIfnotWiretapped(receivedData, foundLen); triggerEvent(DEVICE_READING_REPLY_FAILED, result, foundLen); break; } @@ -613,15 +614,15 @@ ReturnValue_t DeviceHandlerBase::initialize() { } AcceptsDeviceResponsesIF *rawReceiver = objectManager->get< - AcceptsDeviceResponsesIF>(objects::PUS_DEVICE_COMMAND_SERVICE); + AcceptsDeviceResponsesIF>(rawDataReceiverId); if (rawReceiver == NULL) { return RETURN_FAILED; } - theOneWhoReceivesRawTraffic = rawReceiver->getDeviceQueue(); + defaultRawReceiver = rawReceiver->getDeviceQueue(); - powerSwitcher = objectManager->get(objects::PCDU_HANDLER); + powerSwitcher = objectManager->get(powerSwitcherId); if (powerSwitcher == NULL) { return RETURN_FAILED; } @@ -649,6 +650,11 @@ ReturnValue_t DeviceHandlerBase::initialize() { return result; } + result = hkSwitcher.initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + fillCommandAndReplyMap(); //Set temperature target state to NON_OP. @@ -676,12 +682,6 @@ void DeviceHandlerBase::replyRawData(const uint8_t *data, size_t len, return; } - Command_t handlerCommand = DeviceHandlerMessage::REPLY_RAW_REPLY; - - if (isCommand) { - handlerCommand = DeviceHandlerMessage::REPLY_RAW_COMMAND; - } - CommandMessage message; DeviceHandlerMessage::setDeviceHandlerRawReplayMessage(&message, @@ -689,11 +689,11 @@ void DeviceHandlerBase::replyRawData(const uint8_t *data, size_t len, // this->DeviceHandlerCommand = CommandMessage::CMD_NONE; - result = commandQueue.sendMessage(sendTo, &message); + result = commandQueue->sendMessage(sendTo, &message); if (result != RETURN_OK) { IPCStore->deleteData(address); - triggerEvent(MessageQueue::SEND_MSG_FAILED, result, sendTo); + //Silently discard data, this indicates heavy TM traffic which should not be increased by additional events. } } @@ -714,23 +714,22 @@ DeviceHandlerBase::RmapAction_t DeviceHandlerBase::getRmapAction() { return GET_READ; break; default: - break; } return NOTHING; } MessageQueueId_t DeviceHandlerBase::getCommandQueue() const { - return commandQueue.getId(); + return commandQueue->getId(); } void DeviceHandlerBase::handleReply(const uint8_t* receivedData, - DeviceCommandId_t foundId) { + DeviceCommandId_t foundId, uint32_t foundLen) { ReturnValue_t result; - DataSet dataSet; DeviceReplyMap::iterator iter = deviceReplyMap.find(foundId); if (iter == deviceReplyMap.end()) { + replyRawReplyIfnotWiretapped(receivedData, foundLen); triggerEvent(DEVICE_UNKNOWN_REPLY, foundId); return; } @@ -747,12 +746,13 @@ void DeviceHandlerBase::handleReply(const uint8_t* receivedData, result = interpretDeviceReply(foundId, receivedData); if (result != RETURN_OK) { //Report failed interpretation to FDIR. + replyRawReplyIfnotWiretapped(receivedData, foundLen); triggerEvent(DEVICE_INTERPRETING_REPLY_FAILED, result, foundId); } replyToReply(iter, result); } else { //Other completion failure messages are created by timeout. - //Powering down the device might take some time during which periodic replys may still come in. + //Powering down the device might take some time during which periodic replies may still come in. if (mode != _MODE_WAIT_OFF) { triggerEvent(DEVICE_UNREQUESTED_REPLY, foundId); } @@ -899,7 +899,8 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode, mySet.read(); if (thermalRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) { if (!ThermalComponentIF::isOperational(thermalState)) { - triggerEvent(ThermalComponentIF::TEMP_NOT_IN_OP_RANGE, thermalState); + triggerEvent(ThermalComponentIF::TEMP_NOT_IN_OP_RANGE, + thermalState); return NON_OP_TEMPERATURE; } } @@ -1020,6 +1021,20 @@ ReturnValue_t DeviceHandlerBase::acceptExternalDeviceCommands() { return RETURN_OK; } +void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* interface) { + executingTask = interface; +} + +void DeviceHandlerBase::replyRawReplyIfnotWiretapped(const uint8_t* data, + size_t len) { + if ((wiretappingMode == RAW) + && (defaultRawReceiver == requestedRawTraffic)) { + //The raw packet was already sent by the wiretapping service + } else { + replyRawData(data, len, defaultRawReceiver); + } +} + ReturnValue_t DeviceHandlerBase::handleDeviceHandlerMessage( CommandMessage * message) { ReturnValue_t result; @@ -1028,11 +1043,11 @@ ReturnValue_t DeviceHandlerBase::handleDeviceHandlerMessage( switch (DeviceHandlerMessage::getWiretappingMode(message)) { case RAW: wiretappingMode = RAW; - theOneWhoWantsToReadRawTraffic = commandQueue.getLastPartner(); + requestedRawTraffic = commandQueue->getLastPartner(); break; case TM: wiretappingMode = TM; - theOneWhoWantsToReadRawTraffic = commandQueue.getLastPartner(); + requestedRawTraffic = commandQueue->getLastPartner(); break; case OFF: wiretappingMode = OFF; @@ -1091,23 +1106,39 @@ ReturnValue_t DeviceHandlerBase::letChildHandleMessage( } void DeviceHandlerBase::handleDeviceTM(SerializeIF* data, - DeviceCommandId_t replyId, bool neverInDataPool) { + DeviceCommandId_t replyId, bool neverInDataPool, bool forceDirectTm) { DeviceReplyMap::iterator iter = deviceReplyMap.find(replyId); if (iter == deviceReplyMap.end()) { triggerEvent(DEVICE_UNKNOWN_REPLY, replyId); return; } - if (iter->second.command != deviceCommandMap.end()) { + DeviceTmReportingWrapper wrapper(getObjectId(), replyId, data); + if (iter->second.command != deviceCommandMap.end()) {//replies to a command MessageQueueId_t queueId = iter->second.command->second.sendReplyTo; - DeviceTmReportingWrapper wrapper(getObjectId(), replyId, data); + if (queueId != NO_COMMANDER) { + //This may fail, but we'll ignore the fault. actionHelper.reportData(queueId, replyId, data); } //This check should make sure we get any TM but don't get anything doubled. - if (wiretappingMode == TM - && (theOneWhoWantsToReadRawTraffic != queueId)) { - actionHelper.reportData(theOneWhoWantsToReadRawTraffic, - replyId, &wrapper); + if (wiretappingMode == TM && (requestedRawTraffic != queueId)) { + actionHelper.reportData(requestedRawTraffic, replyId, &wrapper); + } else if (forceDirectTm && (defaultRawReceiver != queueId)) { + + // hiding of sender needed so the service will handle it as unexpected Data, no matter what state + //(progress or completed) it is in + actionHelper.reportData(defaultRawReceiver, replyId, &wrapper, + true); + + } + } else { //unrequested/aperiodic replies + if (wiretappingMode == TM) { + actionHelper.reportData(requestedRawTraffic, replyId, &wrapper); + } else if (forceDirectTm) { + // hiding of sender needed so the service will handle it as unexpected Data, no matter what state + //(progress or completed) it is in + actionHelper.reportData(defaultRawReceiver, replyId, &wrapper, + true); } } //Try to cast to DataSet and commit data. @@ -1171,7 +1202,8 @@ void DeviceHandlerBase::buildInternalCommand(void) { result = COMMAND_NOT_SUPPORTED; } else if (iter->second.isExecuting) { debug << std::hex << getObjectId() - << ": DHB::buildInternalCommand: Command " << deviceCommandId << " isExecuting" << std::endl; //so we can track misconfigurations + << ": DHB::buildInternalCommand: Command " + << deviceCommandId << " isExecuting" << std::endl; //so we can track misconfigurations return; //this is an internal command, no need to report a failure here, missed reply will track if a reply is too late, otherwise, it's ok } else { iter->second.sendReplyTo = NO_COMMANDER; @@ -1232,7 +1264,9 @@ ReturnValue_t DeviceHandlerBase::getParameter(uint8_t domainId, } bool DeviceHandlerBase::isTransitionalMode() { - return ((mode & (TRANSITION_MODE_BASE_ACTION_MASK | TRANSITION_MODE_CHILD_ACTION_MASK)) != 0); + return ((mode + & (TRANSITION_MODE_BASE_ACTION_MASK + | TRANSITION_MODE_CHILD_ACTION_MASK)) != 0); } bool DeviceHandlerBase::commandIsExecuting(DeviceCommandId_t commandId) { @@ -1244,3 +1278,6 @@ bool DeviceHandlerBase::commandIsExecuting(DeviceCommandId_t commandId) { } } + +void DeviceHandlerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) { +} diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index f6c33879..78efa657 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -6,9 +6,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -16,7 +14,17 @@ #include #include #include +#include +#include +#include +#include #include +#include +#include + +namespace Factory{ +void setStaticFrameworkObjectIds(); +} class StorageManagerIF; @@ -27,7 +35,7 @@ class StorageManagerIF; * communication with commanding objects. * It inherits SystemObject and thus can be created by the ObjectManagerIF. * - * This class is called by the PollingSequenceTable periodically. Thus, the execution is divided into PST cycles and steps within a cycle. + * This class uses the opcode of ExecutableObjectIF to perform a step-wise execution. * For each step an RMAP action is selected and executed. If data has been received (eg in case of an RMAP Read), the data will be interpreted. * The action for each step can be defined by the child class but as most device handlers share a 4-call (Read-getRead-write-getWrite) structure, * a default implementation is provided. @@ -36,12 +44,13 @@ class StorageManagerIF; */ class DeviceHandlerBase: public DeviceHandlerIF, public HasReturnvaluesIF, - public PollingSequenceExecutableIF, + public ExecutableObjectIF, public SystemObject, public HasModesIF, public HasHealthIF, public HasActionsIF, public ReceivesParameterMessagesIF { + friend void (Factory::setStaticFrameworkObjectIds)(); public: /** * The constructor passes the objectId to the SystemObject(). @@ -54,16 +63,16 @@ public: uint32_t maxDeviceReplyLen, uint8_t setDeviceSwitch, object_id_t deviceCommunication, uint32_t thermalStatePoolId = PoolVariableIF::NO_PARAMETER, - uint32_t thermalRequestPoolId = PoolVariableIF::NO_PARAMETER, FDIRBase* fdirInstance = NULL, uint32_t cmdQueueSize = 20); + uint32_t thermalRequestPoolId = PoolVariableIF::NO_PARAMETER, + FailureIsolationBase* fdirInstance = NULL, uint32_t cmdQueueSize = 20); virtual MessageQueueId_t getCommandQueue(void) const; - virtual void performInPST(uint8_t counter); + virtual ReturnValue_t performOperation(uint8_t counter); virtual ReturnValue_t initialize(); /** - * MUST be called after initialize(), not before! TODO: Is this statement still valid? * * @param parentQueueId */ @@ -81,13 +90,15 @@ public: HealthState getHealth(); ReturnValue_t setHealth(HealthState health); virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, - ParameterWrapper *parameterWrapper, - const ParameterWrapper *newValues, uint16_t startAtIndex); + ParameterWrapper *parameterWrapper, + const ParameterWrapper *newValues, uint16_t startAtIndex); + + void setTaskIF(PeriodicTaskIF* interface); protected: /** * The Returnvalues id of this class, required by HasReturnvaluesIF */ - static const uint8_t INTERFACE_ID = DEVICE_HANDLER_BASE; + static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE; static const ReturnValue_t INVALID_CHANNEL = MAKE_RETURN_CODE(4); static const ReturnValue_t APERIODIC_REPLY = MAKE_RETURN_CODE(5); @@ -106,19 +117,6 @@ protected: static const DeviceCommandId_t NO_COMMAND_ID = -2; static const MessageQueueId_t NO_COMMANDER = 0; - /** - * RMAP Action that will be executed. - * - * This is used by the child class to tell the base class what to do. - */ - enum RmapAction_t { - SEND_WRITE, //!< RMAP send write - GET_WRITE, //!< RMAP get write - SEND_READ, //!< RMAP send read - GET_READ, //!< RMAP get read - NOTHING //!< Do nothing. - }; - /** * Pointer to the raw packet that will be sent. */ @@ -143,7 +141,7 @@ protected: Submode_t submode; /** - * This is the counter value from performInPST(). + * This is the counter value from performOperation(). */ uint8_t pstStep; @@ -163,11 +161,12 @@ protected: } wiretappingMode; /** - * the message queue which commanded raw mode + * A message queue that accepts raw replies * - * This is the one to receive raw replies + * Statically initialized in initialize() to a configurable object. Used when there is no method + * of finding a recipient, ie raw mode and reporting erreonous replies */ - MessageQueueId_t theOneWhoReceivesRawTraffic; + MessageQueueId_t defaultRawReceiver; store_address_t storedRawData; @@ -176,7 +175,7 @@ protected: * * if #isWiretappingActive all raw communication from and to the device will be sent to this queue */ - MessageQueueId_t theOneWhoWantsToReadRawTraffic; + MessageQueueId_t requestedRawTraffic; /** * the object used to set power switches @@ -208,7 +207,7 @@ protected: /** * The MessageQueue used to receive device handler commands and to send replies. */ - MessageQueue commandQueue; + MessageQueueIF* commandQueue; /** * this is the datapool variable with the thermal state of the device @@ -241,12 +240,21 @@ protected: uint32_t ignoreMissedRepliesCount; //!< Counts if communication channel lost a reply, so some missed replys can be ignored. - FDIRBase* fdirInstance; //!< Pointer to the used FDIR instance. If not provided by child, default class is instantiated. + FailureIsolationBase* fdirInstance; //!< Pointer to the used FDIR instance. If not provided by child, default class is instantiated. + + HkSwitchHelper hkSwitcher; bool defaultFDIRUsed; //!< To correctly delete the default instance. bool switchOffWasReported; //!< Indicates if SWITCH_WENT_OFF was already thrown. + static object_id_t powerSwitcherId; //!< Object which switches power on and off. + + static object_id_t rawDataReceiverId; //!< Object which receives RAW data by default. + + static object_id_t defaultFDIRParentId; //!< Object which may be the root cause of an identified fault. + + PeriodicTaskIF* executingTask; /** * Helper function to report a missed reply * @@ -593,6 +601,12 @@ protected: virtual void replyRawData(const uint8_t *data, size_t len, MessageQueueId_t sendTo, bool isCommand = false); + /** + * Calls replyRawData() with #defaultRawReceiver, but checks if wiretapping is active and if so, + * does not send the Data as the wiretapping will have sent it already + */ + void replyRawReplyIfnotWiretapped(const uint8_t *data, size_t len); + /** * Return the switches connected to the device. * @@ -663,6 +677,11 @@ protected: */ virtual void setNormalDatapoolEntriesInvalid() = 0; + /** + * build a list of sids and pass it to the #hkSwitcher + */ + virtual void changeHK(Mode_t mode, Submode_t submode, bool enable); + /** * Children can overwrite this function to suppress checking of the command Queue * @@ -679,7 +698,7 @@ protected: bool isAwaitingReply(); void handleDeviceTM(SerializeIF *dataSet, DeviceCommandId_t commandId, - bool neverInDataPool = false); + bool neverInDataPool = false, bool forceDirectTm = false); virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode); @@ -732,12 +751,6 @@ protected: virtual ReturnValue_t acceptExternalDeviceCommands(); bool commandIsExecuting(DeviceCommandId_t commandId); -private: - - /** - * Information about commands - */ - DeviceCommandMap deviceCommandMap; /** * Information about expected replies @@ -750,6 +763,7 @@ private: uint8_t periodic; //!< if this is !=0, the delayCycles will not be reset to 0 but to maxDelayCycles DeviceCommandMap::iterator command; //!< The command that expects this reply. }; + /** * Definition for the important reply Map. */ @@ -767,6 +781,15 @@ private: */ DeviceReplyMap deviceReplyMap; + /** + * Information about commands + */ + DeviceCommandMap deviceCommandMap; + + ActionHelper actionHelper; + +private: + /** * State a cookie is in. * @@ -837,8 +860,6 @@ private: */ const uint8_t deviceSwitch; - ActionHelper actionHelper; - /** * read the command queue */ @@ -880,8 +901,9 @@ private: * * @param data the found packet * @param id the found id + * @foundLen the length of the packet */ - void handleReply(const uint8_t *data, DeviceCommandId_t id); + void handleReply(const uint8_t *data, DeviceCommandId_t id, uint32_t foundLen); void replyToReply(DeviceReplyMap::iterator iter, ReturnValue_t status); /** diff --git a/devicehandlers/DeviceHandlerFDIR.cpp b/devicehandlers/DeviceHandlerFailureIsolation.cpp similarity index 75% rename from devicehandlers/DeviceHandlerFDIR.cpp rename to devicehandlers/DeviceHandlerFailureIsolation.cpp index c69045fc..65c40219 100644 --- a/devicehandlers/DeviceHandlerFDIR.cpp +++ b/devicehandlers/DeviceHandlerFailureIsolation.cpp @@ -1,20 +1,14 @@ -/* - * DeviceHandlerFDIR.cpp - * - * Created on: 09.09.2015 - * Author: baetz - */ - #include -#include +#include #include +#include #include -#include -#include +#include -//TODO: Mechanisms have no power FDIR.. -DeviceHandlerFDIR::DeviceHandlerFDIR(object_id_t owner, object_id_t parent) : - FDIRBase(owner, parent), strangeReplyCount(MAX_STRANGE_REPLIES, +object_id_t DeviceHandlerFailureIsolation::powerConfirmationId = 0; + +DeviceHandlerFailureIsolation::DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent) : + FailureIsolationBase(owner, parent), strangeReplyCount(MAX_STRANGE_REPLIES, STRANGE_REPLIES_TIME_MS, parameterDomainBase++), missedReplyCount( MAX_MISSED_REPLY_COUNT, MISSED_REPLY_TIME_MS, parameterDomainBase++), recoveryCounter(MAX_REBOOT, @@ -22,25 +16,11 @@ DeviceHandlerFDIR::DeviceHandlerFDIR(object_id_t owner, object_id_t parent) : 0) { } -DeviceHandlerFDIR::~DeviceHandlerFDIR() { +DeviceHandlerFailureIsolation::~DeviceHandlerFailureIsolation() { } -ReturnValue_t DeviceHandlerFDIR::eventReceived(EventMessage* event) { - if (fdirState != NONE) { - //Only wait for those events, ignore all others. - if (event->getParameter1() == HasHealthIF::HEALTHY - && event->getEvent() == HasHealthIF::HEALTH_INFO) { - setFdirState(NONE); - } - if (event->getEvent() == HasModesIF::MODE_INFO - && fdirState != RECOVERY_ONGOING) { - setFdirState(NONE); - } - return RETURN_OK; - } - if (owner->getHealth() == HasHealthIF::FAULTY - || owner->getHealth() == HasHealthIF::PERMANENT_FAULTY) { - //Ignore all events in case device is already faulty. +ReturnValue_t DeviceHandlerFailureIsolation::eventReceived(EventMessage* event) { + if(isFdirInActionOrAreWeFaulty(event)) { return RETURN_OK; } ReturnValue_t result = RETURN_FAILED; @@ -76,13 +56,11 @@ ReturnValue_t DeviceHandlerFDIR::eventReceived(EventMessage* event) { break; case StorageManagerIF::GET_DATA_FAILED: case StorageManagerIF::STORE_DATA_FAILED: - case MessageQueue::SEND_MSG_FAILED: - //Rather strange bugs, occur in RAW mode only. TODO:? By now: Ignore. + //Rather strange bugs, occur in RAW mode only. Ignore. break; case DeviceHandlerIF::INVALID_DEVICE_COMMAND: //Ignore, is bad configuration. We can't do anything in flight. break; - case DeviceHandlerIF::MONITORING_AMBIGUOUS: case HasHealthIF::HEALTH_INFO: case HasModesIF::MODE_INFO: case HasModesIF::CHANGING_MODE: @@ -111,13 +89,17 @@ ReturnValue_t DeviceHandlerFDIR::eventReceived(EventMessage* event) { case ThermalComponentIF::COMPONENT_TEMP_OOL_LOW: case ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH: //Well, the device is not really faulty, but it is required to stay off as long as possible. - //*******ACS***** - case DeviceHandlerIF::MONITORING_LIMIT_EXCEEDED: setFaulty(event->getEvent()); break; case ThermalComponentIF::TEMP_NOT_IN_OP_RANGE: //Ignore, is information only. break; + //*******Default monitoring variables. Are currently not used.***** +// case DeviceHandlerIF::MONITORING_LIMIT_EXCEEDED: +// setFaulty(event->getEvent()); +// break; +// case DeviceHandlerIF::MONITORING_AMBIGUOUS: +// break; default: //We don't know the event, someone else should handle it. return RETURN_FAILED; @@ -125,7 +107,7 @@ ReturnValue_t DeviceHandlerFDIR::eventReceived(EventMessage* event) { return RETURN_OK; } -void DeviceHandlerFDIR::eventConfirmed(EventMessage* event) { +void DeviceHandlerFailureIsolation::eventConfirmed(EventMessage* event) { switch (event->getEvent()) { case DeviceHandlerIF::DEVICE_SENDING_COMMAND_FAILED: case DeviceHandlerIF::DEVICE_REQUESTING_REPLY_FAILED: @@ -143,13 +125,13 @@ void DeviceHandlerFDIR::eventConfirmed(EventMessage* event) { } } -void DeviceHandlerFDIR::decrementFaultCounters() { +void DeviceHandlerFailureIsolation::decrementFaultCounters() { strangeReplyCount.checkForDecrement(); missedReplyCount.checkForDecrement(); recoveryCounter.checkForDecrement(); } -void DeviceHandlerFDIR::handleRecovery(Event reason) { +void DeviceHandlerFailureIsolation::handleRecovery(Event reason) { clearFaultCounters(); if (!recoveryCounter.incrementAndCheck()) { startRecovery(reason); @@ -158,7 +140,7 @@ void DeviceHandlerFDIR::handleRecovery(Event reason) { } } -void DeviceHandlerFDIR::wasParentsFault(EventMessage* event) { +void DeviceHandlerFailureIsolation::wasParentsFault(EventMessage* event) { //We'll better ignore the SWITCH_WENT_OFF event and await a system-wide reset. //This means, no fault message will come through until a MODE_ or HEALTH_INFO message comes through -> Is that ok? //Same issue in TxFailureIsolation! @@ -168,18 +150,18 @@ void DeviceHandlerFDIR::wasParentsFault(EventMessage* event) { // } } -void DeviceHandlerFDIR::clearFaultCounters() { +void DeviceHandlerFailureIsolation::clearFaultCounters() { strangeReplyCount.clear(); missedReplyCount.clear(); } -ReturnValue_t DeviceHandlerFDIR::initialize() { - ReturnValue_t result = FDIRBase::initialize(); +ReturnValue_t DeviceHandlerFailureIsolation::initialize() { + ReturnValue_t result = FailureIsolationBase::initialize(); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } ConfirmsFailuresIF* power = objectManager->get( - objects::PCDU_HANDLER); + powerConfirmationId); if (power == NULL) { return RETURN_FAILED; } @@ -187,31 +169,31 @@ ReturnValue_t DeviceHandlerFDIR::initialize() { return RETURN_OK; } -void DeviceHandlerFDIR::setFdirState(FDIRState state) { - FDIRBase::throwFdirEvent(FDIR_CHANGED_STATE, state, fdirState); +void DeviceHandlerFailureIsolation::setFdirState(FDIRState state) { + FailureIsolationBase::throwFdirEvent(FDIR_CHANGED_STATE, state, fdirState); fdirState = state; } -void DeviceHandlerFDIR::triggerEvent(Event event, uint32_t parameter1, +void DeviceHandlerFailureIsolation::triggerEvent(Event event, uint32_t parameter1, uint32_t parameter2) { //Do not throw error events if fdirState != none. //This will still forward MODE and HEALTH INFO events in any case. if (fdirState == NONE || EVENT::getSeverity(event) == SEVERITY::INFO) { - FDIRBase::triggerEvent(event, parameter1, parameter2); + FailureIsolationBase::triggerEvent(event, parameter1, parameter2); } } -bool DeviceHandlerFDIR::isFdirActionInProgress() { +bool DeviceHandlerFailureIsolation::isFdirActionInProgress() { return (fdirState != NONE); } -void DeviceHandlerFDIR::startRecovery(Event reason) { +void DeviceHandlerFailureIsolation::startRecovery(Event reason) { throwFdirEvent(FDIR_STARTS_RECOVERY, EVENT::getEventId(reason)); setOwnerHealth(HasHealthIF::NEEDS_RECOVERY); setFdirState(RECOVERY_ONGOING); } -ReturnValue_t DeviceHandlerFDIR::getParameter(uint8_t domainId, +ReturnValue_t DeviceHandlerFailureIsolation::getParameter(uint8_t domainId, uint16_t parameterId, ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues, uint16_t startAtIndex) { ReturnValue_t result = strangeReplyCount.getParameter(domainId, parameterId, @@ -232,8 +214,30 @@ ReturnValue_t DeviceHandlerFDIR::getParameter(uint8_t domainId, return INVALID_DOMAIN_ID; } -void DeviceHandlerFDIR::setFaulty(Event reason) { +void DeviceHandlerFailureIsolation::setFaulty(Event reason) { throwFdirEvent(FDIR_TURNS_OFF_DEVICE, EVENT::getEventId(reason)); setOwnerHealth(HasHealthIF::FAULTY); setFdirState(AWAIT_SHUTDOWN); } + +bool DeviceHandlerFailureIsolation::isFdirInActionOrAreWeFaulty( + EventMessage* event) { + if (fdirState != NONE) { + //Only wait for those events, ignore all others. + if (event->getParameter1() == HasHealthIF::HEALTHY + && event->getEvent() == HasHealthIF::HEALTH_INFO) { + setFdirState(NONE); + } + if (event->getEvent() == HasModesIF::MODE_INFO + && fdirState != RECOVERY_ONGOING) { + setFdirState(NONE); + } + return true; + } + if (owner->getHealth() == HasHealthIF::FAULTY + || owner->getHealth() == HasHealthIF::PERMANENT_FAULTY) { + //Ignore all events in case device is already faulty. + return true; + } + return false; +} diff --git a/devicehandlers/DeviceHandlerFDIR.h b/devicehandlers/DeviceHandlerFailureIsolation.h similarity index 54% rename from devicehandlers/DeviceHandlerFDIR.h rename to devicehandlers/DeviceHandlerFailureIsolation.h index 3e33c46a..91f6ef64 100644 --- a/devicehandlers/DeviceHandlerFDIR.h +++ b/devicehandlers/DeviceHandlerFailureIsolation.h @@ -1,27 +1,22 @@ -/* - * DeviceHandlerFDIR.h - * - * Created on: 09.09.2015 - * Author: baetz - */ - -#ifndef FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERFDIR_H_ -#define FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERFDIR_H_ +#ifndef FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERFAILUREISOLATION_H_ +#define FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERFAILUREISOLATION_H_ #include -#include +#include +namespace Factory{ +void setStaticFrameworkObjectIds(); +} -class DeviceHandlerFDIR: public FDIRBase { + +class DeviceHandlerFailureIsolation: public FailureIsolationBase { + friend void (Factory::setStaticFrameworkObjectIds)(); + friend class Heater; public: - DeviceHandlerFDIR(object_id_t owner, object_id_t parent = objects::IO_ASSEMBLY); - ~DeviceHandlerFDIR(); - virtual ReturnValue_t eventReceived(EventMessage* event); - void eventConfirmed(EventMessage* event); - void wasParentsFault(EventMessage* event); - void decrementFaultCounters(); + DeviceHandlerFailureIsolation(object_id_t owner, object_id_t parent); + ~DeviceHandlerFailureIsolation(); ReturnValue_t initialize(); - void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0); - bool isFdirActionInProgress(); + void triggerEvent(Event event, uint32_t parameter1 = 0, + uint32_t parameter2 = 0);bool isFdirActionInProgress(); virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues, uint16_t startAtIndex); @@ -30,25 +25,28 @@ protected: FaultCounter missedReplyCount; FaultCounter recoveryCounter; enum FDIRState { - NONE, - RECOVERY_ONGOING, - DEVICE_MIGHT_BE_OFF, - AWAIT_SHUTDOWN + NONE, RECOVERY_ONGOING, DEVICE_MIGHT_BE_OFF, AWAIT_SHUTDOWN }; FDIRState fdirState; MessageQueueId_t powerConfirmation; - //TODO: Arbitrary numbers! Adjust! + static object_id_t powerConfirmationId; static const uint32_t MAX_REBOOT = 1; static const uint32_t REBOOT_TIME_MS = 180000; static const uint32_t MAX_STRANGE_REPLIES = 10; static const uint32_t STRANGE_REPLIES_TIME_MS = 10000; static const uint32_t MAX_MISSED_REPLY_COUNT = 5; static const uint32_t MISSED_REPLY_TIME_MS = 10000; + virtual ReturnValue_t eventReceived(EventMessage* event); + virtual void eventConfirmed(EventMessage* event); + void wasParentsFault(EventMessage* event); + void decrementFaultCounters(); void handleRecovery(Event reason); virtual void clearFaultCounters(); void setFdirState(FDIRState state); void startRecovery(Event reason); void setFaulty(Event reason); + + bool isFdirInActionOrAreWeFaulty(EventMessage* event); }; -#endif /* FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERFDIR_H_ */ +#endif /* FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERFAILUREISOLATION_H_ */ diff --git a/devicehandlers/DeviceHandlerIF.h b/devicehandlers/DeviceHandlerIF.h index 4922556a..fe0ee8e8 100644 --- a/devicehandlers/DeviceHandlerIF.h +++ b/devicehandlers/DeviceHandlerIF.h @@ -4,8 +4,8 @@ #include #include #include -#include #include +#include /** * This is the Interface used to communicate with a device handler. @@ -52,7 +52,7 @@ public: static const Event MONITORING_LIMIT_EXCEEDED = MAKE_EVENT(9, SEVERITY::LOW); static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, SEVERITY::HIGH); - static const uint8_t INTERFACE_ID = DEVICE_HANDLER_IF; + static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF; static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA0); static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA1); static const ReturnValue_t COMMAND_ALREADY_SENT = MAKE_RETURN_CODE(0xA2); @@ -63,6 +63,7 @@ public: static const ReturnValue_t BUSY = MAKE_RETURN_CODE(0xA7); static const ReturnValue_t NO_REPLY_EXPECTED = MAKE_RETURN_CODE(0xA8); //!< Used to indicate that this is a command-only command. static const ReturnValue_t NON_OP_TEMPERATURE = MAKE_RETURN_CODE(0xA9); + static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xAA); //standard codes used in scan for reply // static const ReturnValue_t TOO_SHORT = MAKE_RETURN_CODE(0xB1); @@ -82,6 +83,19 @@ public: 0xD0); static const ReturnValue_t INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS = MAKE_RETURN_CODE(0xD1); + + /** + * RMAP Action that will be executed. + * + * This is used by the child class to tell the base class what to do. + */ + enum RmapAction_t { + SEND_WRITE,//!< RMAP send write + GET_WRITE, //!< RMAP get write + SEND_READ, //!< RMAP send read + GET_READ, //!< RMAP get read + NOTHING //!< Do nothing. + }; /** * Default Destructor */ diff --git a/devicehandlers/DeviceHandlerMessage.cpp b/devicehandlers/DeviceHandlerMessage.cpp index 30a5c413..fc09c2cd 100644 --- a/devicehandlers/DeviceHandlerMessage.cpp +++ b/devicehandlers/DeviceHandlerMessage.cpp @@ -89,7 +89,7 @@ void DeviceHandlerMessage::clear(CommandMessage* message) { ipcStore->deleteData(getStoreAddress(message)); } } - /* NO BREAK*/ + /* NO BREAK falls through*/ case CMD_SWITCH_IOBOARD: case CMD_WIRETAPPING: message->setCommand(CommandMessage::CMD_NONE); diff --git a/devicehandlers/DeviceHandlerMessage.h b/devicehandlers/DeviceHandlerMessage.h index e521ff97..03399423 100644 --- a/devicehandlers/DeviceHandlerMessage.h +++ b/devicehandlers/DeviceHandlerMessage.h @@ -5,7 +5,7 @@ #include #include #include -//TODO: rework the static constructors to name the type of command they are building, maybe even hide setting the commandID. +//SHOULDDO: rework the static constructors to name the type of command they are building, maybe even hide setting the commandID. /** * This is used to uniquely identify commands that are sent to a device @@ -25,7 +25,7 @@ public: /** * These are the commands that can be sent to a DeviceHandlerBase */ - static const uint8_t MESSAGE_ID = DEVICE_HANDLER_COMMAND_MESSAGE_ID; + static const uint8_t MESSAGE_ID = MESSAGE_TYPE::DEVICE_HANDLER_COMMAND; static const Command_t CMD_RAW = MAKE_COMMAND_ID( 1 ); //!< Sends a raw command, setParameter is a ::store_id_t containing the raw packet to send // static const Command_t CMD_DIRECT = MAKE_COMMAND_ID( 2 ); //!< Sends a direct command, setParameter is a ::DeviceCommandId_t, setParameter2 is a ::store_id_t containing the data needed for the command static const Command_t CMD_SWITCH_IOBOARD = MAKE_COMMAND_ID( 3 ); //!< Requests a IO-Board switch, setParameter() is the IO-Board identifier diff --git a/devicehandlers/FixedSequenceSlot.cpp b/devicehandlers/FixedSequenceSlot.cpp new file mode 100644 index 00000000..29e7ee6a --- /dev/null +++ b/devicehandlers/FixedSequenceSlot.cpp @@ -0,0 +1,21 @@ +/** + * @file PollingSlot.cpp + * @brief This file defines the PollingSlot class. + * @date 19.12.2012 + * @author baetz + */ + +#include +#include +#include + +FixedSequenceSlot::FixedSequenceSlot(object_id_t handlerId, uint32_t setTime, + int8_t setSequenceId, PeriodicTaskIF* executingTask) : + handler(NULL), pollingTimeMs(setTime), opcode(setSequenceId) { + handler = objectManager->get(handlerId); + handler->setTaskIF(executingTask); +} + +FixedSequenceSlot::~FixedSequenceSlot() { +} + diff --git a/devicehandlers/PollingSlot.h b/devicehandlers/FixedSequenceSlot.h similarity index 52% rename from devicehandlers/PollingSlot.h rename to devicehandlers/FixedSequenceSlot.h index 125e9222..5aff0f4f 100644 --- a/devicehandlers/PollingSlot.h +++ b/devicehandlers/FixedSequenceSlot.h @@ -1,44 +1,40 @@ /** - * @file PollingSlot.h + * @file FixedSequenceSlot.h * @brief This file defines the PollingSlot class. * @date 19.12.2012 * @author baetz */ -#ifndef POLLINGSLOT_H_ -#define POLLINGSLOT_H_ +#ifndef FIXEDSEQUENCESLOT_H_ +#define FIXEDSEQUENCESLOT_H_ -#include #include -#include - -class PollingSequence; +#include +class PeriodicTaskIF; /** * \brief This class is the representation of a single polling sequence table entry. * * \details The PollingSlot class is the representation of a single polling sequence table entry. - * It contains three attributes and a debug method to print its content. */ -class PollingSlot { - friend class PollingSequence; - friend class PollingTask; - friend ReturnValue_t pollingSequenceInitFunction(PollingSequence *thisSequence); - friend ReturnValue_t payloadSequenceInitFunction(PollingSequence *thisSequence); -protected: +class FixedSequenceSlot { +public: + FixedSequenceSlot( object_id_t handlerId, uint32_t setTimeMs, int8_t setSequenceId, PeriodicTaskIF* executingTask ); + virtual ~FixedSequenceSlot(); + /** * \brief \c handler identifies which device handler object is executed in this slot. */ - PollingSequenceExecutableIF* handler; + ExecutableObjectIF* handler; /** * \brief This attribute defines when a device handler object is executed. * - * \details The pollingTime attribute identifies the time the handler is executed in clock ticks. It must be + * \details The pollingTime attribute identifies the time the handler is executed in ms. It must be * smaller than the period length of the polling sequence, what is ensured by automated calculation * from a database. */ - Interval_t pollingTime; + uint32_t pollingTimeMs; /** * \brief This value defines the type of device communication. @@ -46,16 +42,7 @@ protected: * \details The state of this value decides what communication routine is called in the PST executable or the device handler object. */ uint8_t opcode; - -public: - PollingSlot( object_id_t handlerId, Interval_t setTime, int8_t setSequenceId ); - virtual ~PollingSlot(); - - /** - * \brief This is a small debug method to print the PollingSlot's content to a debug interface. - */ - void print() const; }; -#endif /* POLLINGSLOT_H_ */ +#endif /* FIXEDSEQUENCESLOT_H_ */ diff --git a/devicehandlers/FixedSlotSequence.cpp b/devicehandlers/FixedSlotSequence.cpp new file mode 100644 index 00000000..88ec5717 --- /dev/null +++ b/devicehandlers/FixedSlotSequence.cpp @@ -0,0 +1,109 @@ +#include +#include + +FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) : + lengthMs(setLengthMs) { + current = slotList.begin(); +} + +FixedSlotSequence::~FixedSlotSequence() { + std::list::iterator slotIt; + //Iterate through slotList and delete all entries. + slotIt = this->slotList.begin(); + while (slotIt != this->slotList.end()) { + delete (*slotIt); + slotIt++; + } +} + +void FixedSlotSequence::executeAndAdvance() { +// (*this->current)->print(); + (*this->current)->handler->performOperation((*this->current)->opcode); +// if (returnValue != RETURN_OK) { +// this->sendErrorMessage( returnValue ); +// } + //Increment the polling Sequence iterator + this->current++; + //Set it to the beginning, if the list's end is reached. + if (this->current == this->slotList.end()) { + this->current = this->slotList.begin(); + } +} + +uint32_t FixedSlotSequence::getIntervalMs() { + uint32_t oldTime; + std::list::iterator it; + it = current; + // Get the pollingTimeMs of the current slot object. + oldTime = (*it)->pollingTimeMs; + // Advance to the next object. + it++; + // Find the next interval which is not 0. + while (it != slotList.end()) { + if (oldTime != (*it)->pollingTimeMs) { + return (*it)->pollingTimeMs - oldTime; + } else { + it++; + } + } + // If the list end is reached (this is definitely an interval != 0), + // the interval is calculated by subtracting the remaining time of the PST + // and adding the start time of the first handler in the list. + it = slotList.begin(); + return lengthMs - oldTime + (*it)->pollingTimeMs; +} + +bool FixedSlotSequence::slotFollowsImmediately() { + uint32_t currentTime = (*current)->pollingTimeMs; + std::list::iterator it; + it = this->current; + // Get the pollingTimeMs of the current slot object. + if (it == slotList.begin()) + return false; + it--; + if ((*it)->pollingTimeMs == currentTime) { + return true; + } else { + return false; + } +} + +uint32_t FixedSlotSequence::getLengthMs() const { + return this->lengthMs; +} + +ReturnValue_t FixedSlotSequence::checkSequence() const { + //Iterate through slotList and check successful creation. Checks if timing is ok (must be ascending) and if all handlers were found. + auto slotIt = slotList.begin(); + uint32_t count = 0; + uint32_t time = 0; + while (slotIt != slotList.end()) { + if ((*slotIt)->handler == NULL) { + error << "FixedSlotSequene::initialize: ObjectId does not exist!" + << std::endl; + count++; + } else if ((*slotIt)->pollingTimeMs < time) { + error << "FixedSlotSequence::initialize: Time: " + << (*slotIt)->pollingTimeMs + << " is smaller than previous with " << time << std::endl; + count++; + } else { + //All ok, print slot. +// (*slotIt)->print(); + } + time = (*slotIt)->pollingTimeMs; + slotIt++; + } + if (count > 0) { + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; +} + +void FixedSlotSequence::addSlot(object_id_t componentId, uint32_t slotTimeMs, + int8_t executionStep, PeriodicTaskIF* executingTask) { + this->slotList.push_back( + new FixedSequenceSlot(componentId, slotTimeMs, executionStep, + executingTask)); + this->current = slotList.begin(); +} diff --git a/devicehandlers/PollingSequence.h b/devicehandlers/FixedSlotSequence.h similarity index 55% rename from devicehandlers/PollingSequence.h rename to devicehandlers/FixedSlotSequence.h index 3f424c07..161b3a34 100644 --- a/devicehandlers/PollingSequence.h +++ b/devicehandlers/FixedSlotSequence.h @@ -1,24 +1,14 @@ -/** - * @file PollingSequence.h - * @brief This file defines the PollingSequence class. - * @date 19.12.2012 - * @author baetz - */ +#ifndef FIXEDSLOTSEQUENCE_H_ +#define FIXEDSLOTSEQUENCE_H_ -#ifndef POLLINGSEQUENCE_H_ -#define POLLINGSEQUENCE_H_ - -#include -#include +#include #include -#include -#include - +#include /** * \brief This class is the representation of a Polling Sequence Table in software. * - * \details The PollingSequence object maintains the dynamic execution of device handler objects. + * \details The FixedSlotSequence object maintains the dynamic execution of device handler objects. * The main idea is to create a list of device handlers, to announce all handlers to the * polling sequence and to maintain a list of polling slot objects. This slot list represents the * Polling Sequence Table in software. Each polling slot contains information to indicate when and @@ -26,10 +16,78 @@ * The sequence is then executed by iterating through this slot list. * Handlers are invoking by calling a certain function stored in the handler list. */ -class PollingSequence : public SystemObject { - friend class PollingTask; - friend ReturnValue_t pollingSequenceInitFunction(PollingSequence *thisSequence); - friend ReturnValue_t payloadSequenceInitFunction(PollingSequence *thisSequence); +class FixedSlotSequence { +public: + + /** + * \brief The constructor of the FixedSlotSequence object. + * + * \details The constructor takes two arguments, the period length and the init function. + * + * \param setLength The period length, expressed in ms. + */ + FixedSlotSequence(uint32_t setLengthMs); + + /** + * \brief The destructor of the FixedSlotSequence object. + * + * \details The destructor frees all allocated memory by iterating through the slotList + * and deleting all allocated resources. + */ + virtual ~FixedSlotSequence(); + + /** + * \brief This is a method to add an PollingSlot object to slotList. + * + * \details Here, a polling slot object is added to the slot list. It is appended + * to the end of the list. The list is currently NOT reordered. + * Afterwards, the iterator current is set to the beginning of the list. + */ + void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId, + PeriodicTaskIF* executingTask); + + /** + * Checks if the current slot shall be executed immediately after the one before. + * This allows to distinguish between grouped and not grouped handlers. + * @return - @c true if the slot has the same polling time as the previous + * - @c false else + */ + bool slotFollowsImmediately(); + + /** + * \brief This method returns the time until the next software component is invoked. + * + * \details This method is vitally important for the operation of the PST. By fetching the polling time + * of the current slot and that of the next one (or the first one, if the list end is reached) + * it calculates and returns the interval in clock ticks within which the handler execution + * shall take place. + */ + uint32_t getIntervalMs(); + + /** + * \brief This method returns the length of this FixedSlotSequence instance. + */ + uint32_t getLengthMs() const; + + /** + * \brief The method to execute the device handler entered in the current OPUSPollingSlot object. + * + * \details Within this method the device handler object to be executed is chosen by looking up the + * handler address of the current slot in the handlerMap. Either the device handler's + * talkToInterface or its listenToInterface method is invoked, depending on the isTalking flag + * of the polling slot. After execution the iterator current is increased or, by reaching the + * end of slotList, reset to the beginning. + */ + void executeAndAdvance(); + + /** + * \brief An iterator that indicates the current polling slot to execute. + * + * \details This is an iterator for slotList and always points to the polling slot which is executed next. + */ + std::list::iterator current; + + ReturnValue_t checkSequence() const; protected: /** @@ -41,109 +99,9 @@ protected: * By iterating through this list the polling sequence is executed. Two entries with identical * polling times are executed immediately one after another. */ - std::list slotList; + std::list slotList; - /** - * \brief An iterator that indicates the current polling slot to execute. - * - * \details This is an iterator for slotList and always points to the polling slot which is executed next. - */ - std::list::iterator current; - - /** - * \brief The period of the Polling Sequence Table in clock ticks. - * - * \details This attribute is set within the constructor, defining the main period length of the - * Polling Sequence Table. The length is expressed in clock ticks. - * - */ - Interval_t length; - - /** - * \brief The init function passed by the ctor - * - * \details This function will be called during initialize() - * - */ - ReturnValue_t (*initFunction)(PollingSequence *thisSequence); - -public: - - /** - * \brief The constructor of the PollingSequence object. - * - * \details The constructor takes two arguments, the period length and the init function. - * - * \param setLength The period length, expressed in clock ticks. - */ - PollingSequence( object_id_t setObjectId, Interval_t setLength, ReturnValue_t (*initFunction)(PollingSequence *thisSequence) ); - - /** - * \brief The destructor of the PollingSequence object. - * - * \details The destructor frees all allocated memory by iterating through - * handlerMap and slotList and deleting all allocated resources. - */ - virtual ~PollingSequence(); - - /** - * \brief This is a method to add an OPUSPollingSlot object to slotList. - * - * \details Here, a polling slot object is added to the slot list. It is appended - * to the end of the list. The list is currently NOT reordered. - * Afterwards, the iterator current is set to the beginning of the list. - * - * \param setSlot This is a pointer to a OPUSPollingSlot object. - */ - void addSlot( PollingSlot* setSlot ); - - /** - * Checks if the current slot shall be executed immediately after the one before. - * This allows to distinguish between grouped and not grouped handlers. - * @return - @c true if the slot has the same polling time as the previous - * - @c false else - */ - bool slotFollowsImmediately(); - - /** - * \brief This method returns the time until the next device handler object is invoked. - * - * \details This method is vitally important for the operation of the PST. By fetching the polling time - * of the current slot and that of the next one (or the first one, if the list end is reached) - * it calculates and returns the interval in clock ticks within which the handler execution - * shall take place. - */ - Interval_t getInterval(); - - /** - * \brief This method returns the length of this PollingSequence instance. - */ - Interval_t getLength(); - - /** - * \brief The method to execute the device handler entered in the current OPUSPollingSlot object. - * - * \details Within this method the device handler object to be executed is chosen by looking up the - * handler address of the current slot in the handlerMap. Either the device handler's - * talkToInterface or its listenToInterface method is invoked, depending on the isTalking flag - * of the polling slot. After execution the iterator current is increased or, by reaching the - * end of slotList, reset to the beginning. - */ - void pollAndAdvance(); - - /** - * \brief This is a method to print debug output. - * - * \details print is a simple debug method to print the whole polling sequence to the debug interface. - * It iterates through slotList and calls all print()} functions of the announced polling slot - * instances. - * - */ - void print(); - - ReturnValue_t initialize(); - //std::string getObjectTypeAsString(); + uint32_t lengthMs; }; - -#endif /* POLLINGSEQUENCE_H_ */ +#endif /* FIXEDSLOTSEQUENCE_H_ */ diff --git a/devicehandlers/HealthDevice.cpp b/devicehandlers/HealthDevice.cpp index dacdcf19..ea0b99ff 100644 --- a/devicehandlers/HealthDevice.cpp +++ b/devicehandlers/HealthDevice.cpp @@ -1,18 +1,20 @@ #include +#include HealthDevice::HealthDevice(object_id_t setObjectId, MessageQueueId_t parentQueue) : SystemObject(setObjectId), lastHealth(HEALTHY), parentQueue( - parentQueue), commandQueue(3, - CommandMessage::COMMAND_MESSAGE_SIZE), healthHelper(this, setObjectId) { + parentQueue), commandQueue(), healthHelper(this, setObjectId) { + commandQueue = QueueFactory::instance()->createMessageQueue(3, CommandMessage::COMMAND_MESSAGE_SIZE); } HealthDevice::~HealthDevice() { + QueueFactory::instance()->deleteMessageQueue(commandQueue); } -ReturnValue_t HealthDevice::performOperation() { +ReturnValue_t HealthDevice::performOperation(uint8_t opCode) { CommandMessage message; - ReturnValue_t result = commandQueue.receiveMessage(&message); + ReturnValue_t result = commandQueue->receiveMessage(&message); if (result == HasReturnvaluesIF::RETURN_OK) { healthHelper.handleHealthCommand(&message); } @@ -32,7 +34,7 @@ ReturnValue_t HealthDevice::initialize() { } MessageQueueId_t HealthDevice::getCommandQueue() const { - return commandQueue.getId(); + return commandQueue->getId(); } void HealthDevice::setParentQueue(MessageQueueId_t parentQueue) { diff --git a/devicehandlers/HealthDevice.h b/devicehandlers/HealthDevice.h index 6b9f5860..ffb9e5bd 100644 --- a/devicehandlers/HealthDevice.h +++ b/devicehandlers/HealthDevice.h @@ -5,6 +5,7 @@ #include #include #include +#include class HealthDevice: public SystemObject, public ExecutableObjectIF, @@ -13,7 +14,7 @@ public: HealthDevice(object_id_t setObjectId, MessageQueueId_t parentQueue); virtual ~HealthDevice(); - ReturnValue_t performOperation(); + ReturnValue_t performOperation(uint8_t opCode); ReturnValue_t initialize(); @@ -31,7 +32,7 @@ protected: HealthState lastHealth; MessageQueueId_t parentQueue; - MessageQueue commandQueue; + MessageQueueIF* commandQueue; public: HealthHelper healthHelper; }; diff --git a/devicehandlers/Makefile b/devicehandlers/Makefile deleted file mode 100755 index 9a2c5bf4..00000000 --- a/devicehandlers/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash -# -# OPUS makefile -# -# Created on: Mar 04, 2010 -# Author: ziemke -# Author: Claas Ziemke -# Copyright 2010, Claas Ziemke -# - -BASEDIR=../../ -include $(BASEDIR)options.mk - -OBJ = $(BUILDDIR)/ChannelResetHandler.o \ - $(BUILDDIR)/RawCommandHandler.o \ - $(BUILDDIR)/RawDataHandler.o \ - $(BUILDDIR)/OPUSPollingSequence.o \ - $(BUILDDIR)/PollingTask.o \ - $(BUILDDIR)/Device.o \ - $(BUILDDIR)/RmapCookie.o \ - -all: $(OBJ) - -$(BUILDDIR)/%.o: %.cpp %.h - $(CPP) $(CFLAGS) $(DEFINES) $(CCOPT) ${INCLUDE} -c $< -o $@ - -clean: - $(RM) *.o *.gcno *.gcda diff --git a/devicehandlers/PollingSequence.cpp b/devicehandlers/PollingSequence.cpp deleted file mode 100644 index 7493bd6a..00000000 --- a/devicehandlers/PollingSequence.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/** - * @file PollingSequence.cpp - * @brief This file defines the PollingSequence class. - * @date 19.12.2012 - * @author baetz - */ - -#include -#include - - -uint32_t PollingSequenceExecutableIF::pollingSequenceLengthMs = 0; -uint32_t PollingSequenceExecutableIF::payloadSequenceLengthMs = 0; - -PollingSequence::PollingSequence(object_id_t setObjectId, Interval_t setLength, ReturnValue_t (*initFunction)(PollingSequence *thisSequence)) : SystemObject( setObjectId ), - initFunction(initFunction){ - this->length = setLength; -// PollingSequenceExecutableIF::pollingSequenceLengthMs = (setLength * 1000) -// / OSAL::getTicksPerSecond(); - current = slotList.begin(); -} - -PollingSequence::~PollingSequence() { - std::list::iterator slotIt; - //Iterate through slotList and delete all entries. - slotIt = this->slotList.begin(); - while (slotIt != this->slotList.end()) { - delete (*slotIt); - slotIt++; - } -} - -void PollingSequence::addSlot(PollingSlot* setSlot) { - //The slot is added to the end of the list. - this->slotList.push_back(setSlot); - this->current = slotList.begin(); -} - -void PollingSequence::pollAndAdvance() { -// (*this->current)->print(); - (*this->current)->handler->performInPST( (*this->current)->opcode ); -// if (returnValue != RETURN_OK) { -// this->sendErrorMessage( returnValue ); -// } - //Increment the polling Sequence iterator - this->current++; - //Set it to the beginning, if the list's end is reached. - if (this->current == this->slotList.end()) { - this->current = this->slotList.begin(); - } -} - -Interval_t PollingSequence::getInterval() { - Interval_t oldTime; - std::list::iterator it; - it = this->current; - // Get the pollingTime of the current slot object. - oldTime = (*it)->pollingTime; - // Advance to the next object. - it++; - // Find the next interval which is not 0. - while ( it != slotList.end() ) { - if ( oldTime != (*it)->pollingTime ) { - return (*it)->pollingTime - oldTime; - } else { - it++; - } - } - // If the list end is reached (this is definitely an interval != 0), - // the interval is calculated by subtracting the remaining time of the PST - // and adding the start time of the first handler in the list. - it = slotList.begin(); - return this->length - oldTime + (*it)->pollingTime; -} - -bool PollingSequence::slotFollowsImmediately() { - Interval_t currentTime = (*current)->pollingTime; - std::list::iterator it; - it = this->current; - // Get the pollingTime of the current slot object. - if ( it == slotList.begin() ) return false; - it--; - if ( (*it)->pollingTime == currentTime ) { - return true; - } else { - return false; - } -} - -Interval_t PollingSequence::getLength() { - return this->length; -} - -void PollingSequence::print() { - debug << "Polling sequence contains:" << std::endl; - - //Iterate through slotList and start all PollingSlot::print() methods. - do { - (*current)->print(); - current++; - } while (current != slotList.end()); - current = slotList.begin(); -} - -//std::string PollingSequence::getObjectTypeAsString() { -// return "PollingSequence"; -//} - -ReturnValue_t PollingSequence::initialize() { - ReturnValue_t result = SystemObject::initialize(); - if (result != HasReturnvaluesIF::RETURN_OK){ - return result; - } - return initFunction(this); -} diff --git a/devicehandlers/PollingSequenceExecutableIF.h b/devicehandlers/PollingSequenceExecutableIF.h deleted file mode 100644 index 7f6db57c..00000000 --- a/devicehandlers/PollingSequenceExecutableIF.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * PollingSequenceExecutableIF.h - * - * Created on: Mar 30, 2012 - * Author: baetz - */ - -#ifndef POLLINGSEQUENCEEXECUTABLE_H_ -#define POLLINGSEQUENCEEXECUTABLE_H_ - -//TODO clean this whole file up - -//TODO maybe define a type to make it look cleaner and use it in the PST -#define SEND_WRITE_CMD 0 -#define GET_WRITE_REPLY 1 -#define SEND_READ_CMD 2 -#define GET_READ_REPLY 3 - - -#include - -class PollingSequenceExecutableIF { -public: - static uint32_t pollingSequenceLengthMs; - static uint32_t payloadSequenceLengthMs; - virtual void performInPST( uint8_t ) = 0; - virtual ~PollingSequenceExecutableIF() { } -}; - -#endif /* POLLINGSEQUENCEEXECUTABLE_H_ */ diff --git a/devicehandlers/PollingSlot.cpp b/devicehandlers/PollingSlot.cpp deleted file mode 100644 index 1d219187..00000000 --- a/devicehandlers/PollingSlot.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @file PollingSlot.cpp - * @brief This file defines the PollingSlot class. - * @date 19.12.2012 - * @author baetz - */ - -#include -#include -#include - -PollingSlot::PollingSlot( object_id_t handlerId, Interval_t setTime, int8_t setSequenceId ) { - //Set all attributes directly on object creation. - this->handler = objectManager->get( handlerId ); - this->pollingTime = setTime; - this->opcode = setSequenceId; -} - -PollingSlot::~PollingSlot() { -} - -void PollingSlot::print() const { - SystemObjectIF * systemObject = dynamic_cast(handler); - object_id_t id = (systemObject == NULL) ? 0xffffffff : systemObject->getObjectId(); - debug << "HandlerID: " << std::hex << id << std::dec << "; Polling Time: " - << this->pollingTime << "; Opcode: " << (uint16_t) this->opcode - << std::endl; -} - diff --git a/devicehandlers/PollingTask.cpp b/devicehandlers/PollingTask.cpp deleted file mode 100644 index e6142205..00000000 --- a/devicehandlers/PollingTask.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/** - * \file OPUSPollingTask.cpp - * - * \brief This file contains the implementation for the OPUSPollingTask class. - * - * \author Bastian Baetz - * - * \date 17.03.2011 - * - */ - -#include -#include - -uint32_t PollingTask::deadlineMissedCount = 0; - -PollingTask::PollingTask( const char *name, TaskPriority_t setPriority, size_t setStack, void (*setDeadlineMissedFunc)(), object_id_t getPst ) : - TaskBase( setPriority, setStack, name ), periodId(0) { - // All additional attributes are applied to the object. - this->deadlineMissedFunc = setDeadlineMissedFunc; - this->pst = objectManager->get( getPst ); -} - -PollingTask::~PollingTask() { - // The PollingSequence destructor is called, if a sequence is announced. - if ( this->pst != NULL ) { - this->pst->~PollingSequence(); - } else { - // There was no memory allocation, so there's nothing to do. - } -} - -TaskReturn_t PollingTask::taskEntryPoint( TaskArgument_t argument ) { - - //The argument is re-interpreted as PollingTask. - PollingTask *originalTask( reinterpret_cast( argument ) ); - if ( originalTask->pst != NULL ) { - //The task's functionality is called. - originalTask->taskFunctionality(); - } else { - - } - 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 << " deadlines." << std::endl; - } -} - -ReturnValue_t PollingTask::startTask() { - this->setRunning( true ); - ReturnValue_t status; - status = OSAL::startTask( &( this->id ), PollingTask::taskEntryPoint, TaskArgument_t( ( void *)this ) ); - if( status != RETURN_OK ) { - //TODO: Call any FDIR routine? - error << "PollingTask::startTask for " << std::hex << this->getId() << std::dec << " failed." << std::endl; - } else { -// debug << "PollingTask::startTask for " << std::hex << this->getId() << std::dec << " successful" << std::endl; - } - return status; -} - -void PollingTask::taskFunctionality() { - ReturnValue_t status = OSAL::TIMEOUT; - Interval_t interval; - // A local iterator for the Polling Sequence Table is created to find the start time for the first entry. - std::list::iterator it; - - it = this->pst->current; - //The start time for the first entry is read. - interval = ( *it )->pollingTime; - //The period is set up and started with the system call. - status = OSAL::setAndStartPeriod( interval, &( this->periodId ) ); - if( status == RETURN_OK ) { - //The task's "infinite" inner loop is entered. - while( this->isRunning ) { - if ( pst->slotFollowsImmediately() ) { - //Do nothing - } else { - //The interval for the next polling slot is selected. - interval = this->pst->getInterval(); - //The period is checked and restarted with the new interval. - //If the deadline was missed, the deadlineMissedFunc is called. - status = OSAL::checkAndRestartPeriod( this->periodId, interval ); - if( status == OSAL::TIMEOUT ) { - if( this->deadlineMissedFunc != NULL ) { - this->deadlineMissedFunc(); - } - } - } - //The device handler for this slot is executed and the next one is chosen. - this->pst->pollAndAdvance(); - } - } else { - error << "PollingTask::setAndStartPeriod failed with status "<< status << std::endl; - } - //Any operating system object for periodic execution is deleted. - debug << "Deleting the PollingTask's period." << std::endl; - OSAL::deletePeriod( &(this->id) ); -} diff --git a/events/Event.cpp b/events/Event.cpp index 55b0a0cd..9ea9f552 100644 --- a/events/Event.cpp +++ b/events/Event.cpp @@ -1,13 +1,3 @@ -/* - * Event.cpp - * - * Created on: 25.08.2015 - * Author: baetz - */ - - - - #include namespace EVENT { EventId_t getEventId(Event event) { diff --git a/events/Event.h b/events/Event.h index 22ef921e..96800f34 100644 --- a/events/Event.h +++ b/events/Event.h @@ -1,14 +1,9 @@ -/* - * Event.h - * - * Created on: 18.08.2015 - * Author: baetz - */ - #ifndef EVENTOBJECT_EVENT_H_ #define EVENTOBJECT_EVENT_H_ #include +#include +//could be move to more suitable location #include typedef uint16_t EventId_t; diff --git a/events/EventManager.cpp b/events/EventManager.cpp index c177ad64..01334bac 100644 --- a/events/EventManager.cpp +++ b/events/EventManager.cpp @@ -1,40 +1,43 @@ -#include -#include - #include #include #include +#include +#include + const uint16_t EventManager::POOL_SIZES[N_POOLS] = { sizeof(EventMatchTree::Node), sizeof(EventIdRangeMatcher), sizeof(ReporterRangeMatcher) }; -//TODO: Rather arbitrary. Adjust! +//If one checks registerListener calls, there are around 40 (to max 50) objects registering for certain events. +//Each listener requires 1 or 2 EventIdMatcher and 1 or 2 ReportRangeMatcher. So a good guess is 75 to a max of 100 pools required for each, which fits well. const uint16_t EventManager::N_ELEMENTS[N_POOLS] = { 240, 120, 120 }; EventManager::EventManager(object_id_t setObjectId) : - SystemObject(setObjectId), eventReportQueue(MAX_EVENTS_PER_CYCLE, - EventMessage::EVENT_MESSAGE_SIZE), mutex(NULL), factoryBackend( + SystemObject(setObjectId), eventReportQueue(NULL), mutex(NULL), factoryBackend( 0, POOL_SIZES, N_ELEMENTS, false, true) { - mutex = new MutexId_t; - OSAL::createMutex(setObjectId + 1, (mutex)); + mutex = MutexFactory::instance()->createMutex(); + eventReportQueue = QueueFactory::instance()->createMessageQueue( + MAX_EVENTS_PER_CYCLE, EventMessage::EVENT_MESSAGE_SIZE); } EventManager::~EventManager() { - OSAL::deleteMutex(mutex); - delete mutex; + QueueFactory::instance()->deleteMessageQueue(eventReportQueue); + MutexFactory::instance()->deleteMutex(mutex); } MessageQueueId_t EventManager::getEventReportQueue() { - return eventReportQueue.getId(); + return eventReportQueue->getId(); } -ReturnValue_t EventManager::performOperation() { +ReturnValue_t EventManager::performOperation(uint8_t opCode) { ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; while (result == HasReturnvaluesIF::RETURN_OK) { EventMessage message; - result = eventReportQueue.receiveMessage(&message); + result = eventReportQueue->receiveMessage(&message); if (result == HasReturnvaluesIF::RETURN_OK) { +#ifdef DEBUG printEvent(&message); +#endif notifyListeners(&message); } } @@ -45,7 +48,7 @@ void EventManager::notifyListeners(EventMessage* message) { lockMutex(); for (auto iter = listenerList.begin(); iter != listenerList.end(); ++iter) { if (iter->second.match(message)) { - eventForwardingSender.sendMessage(iter->first, message, + MessageQueueSenderIF::sendMessage(iter->first, message, message->getSender()); } } @@ -103,21 +106,27 @@ ReturnValue_t EventManager::unsubscribeFromEventRange(MessageQueueId_t listener, return result; } +#ifdef DEBUG + +//forward declaration, should be implemented by mission +const char* translateObject(object_id_t object); +const char * translateEvents(Event event); + void EventManager::printEvent(EventMessage* message) { const char *string = 0; switch (message->getSeverity()) { case SEVERITY::INFO: - string = translateObject(message->getReporter()); - info << "EVENT: "; - if (string != 0) { - info << string; - } else { - info << "0x" << std::hex << message->getReporter() << std::dec; - } - info << " reported " << translateEvents(message->getEvent()) << " (" - << std::dec << message->getEventId() << std::hex << ") P1: 0x" - << message->getParameter1() << " P2: 0x" - << message->getParameter2() << std::dec << std::endl; +// string = translateObject(message->getReporter()); +// info << "EVENT: "; +// if (string != 0) { +// info << string; +// } else { +// info << "0x" << std::hex << message->getReporter() << std::dec; +// } +// info << " reported " << translateEvents(message->getEvent()) << " (" +// << std::dec << message->getEventId() << std::hex << ") P1: 0x" +// << message->getParameter1() << " P2: 0x" +// << message->getParameter2() << std::dec << std::endl; break; default: string = translateObject(message->getReporter()); @@ -135,11 +144,12 @@ void EventManager::printEvent(EventMessage* message) { } } +#endif void EventManager::lockMutex() { - OSAL::lockMutex(this->mutex, OSAL::NO_TIMEOUT); + mutex->lockMutex(MutexIF::NO_TIMEOUT); } void EventManager::unlockMutex() { - OSAL::unlockMutex(this->mutex); + mutex->unlockMutex(); } diff --git a/events/EventManager.h b/events/EventManager.h index 185e15ea..35711b58 100644 --- a/events/EventManager.h +++ b/events/EventManager.h @@ -4,16 +4,17 @@ #include #include #include -#include #include #include +#include +#include #include class EventManager: public EventManagerIF, public ExecutableObjectIF, public SystemObject { public: - static const uint16_t MAX_EVENTS_PER_CYCLE = 150; + static const uint16_t MAX_EVENTS_PER_CYCLE = 80; EventManager(object_id_t setObjectId); virtual ~EventManager(); @@ -32,17 +33,15 @@ public: EventId_t idFrom = 0, EventId_t idTo = 0, bool idInverted = false, object_id_t reporterFrom = 0, object_id_t reporterTo = 0, bool reporterInverted = false); - ReturnValue_t performOperation(); + ReturnValue_t performOperation(uint8_t opCode); protected: - MessageQueue eventReportQueue; - - MessageQueueSender eventForwardingSender; + MessageQueueIF* eventReportQueue; std::map listenerList; - MutexId_t* mutex; + MutexIF* mutex; static const uint8_t N_POOLS = 3; LocalPool factoryBackend; @@ -51,7 +50,9 @@ protected: void notifyListeners(EventMessage *message); +#ifdef DEBUG void printEvent(EventMessage *message); +#endif void lockMutex(); diff --git a/events/EventManagerIF.h b/events/EventManagerIF.h index ac6fb0cb..bc0de432 100644 --- a/events/EventManagerIF.h +++ b/events/EventManagerIF.h @@ -3,13 +3,13 @@ #include #include -#include #include +#include class EventManagerIF { public: - static const uint8_t INTERFACE_ID = EVENT_MANAGER_IF; + static const uint8_t INTERFACE_ID = CLASS_ID::EVENT_MANAGER_IF; static const ReturnValue_t LISTENER_NOT_FOUND = MAKE_RETURN_CODE(1); virtual ~EventManagerIF() { } @@ -44,8 +44,7 @@ public: eventmanagerQueue = eventmanager->getEventReportQueue(); } } - MessageQueueSender sender(eventmanagerQueue); - sender.sendToDefault(message, sentFrom); + MessageQueueSenderIF::sendMessage(eventmanagerQueue, message, sentFrom); } }; diff --git a/events/EventMessage.h b/events/EventMessage.h index ffe3ff64..8e0b6dfd 100644 --- a/events/EventMessage.h +++ b/events/EventMessage.h @@ -15,7 +15,7 @@ public: static const uint8_t CONFIRMATION_REQUEST = 1; //!< Request to parent if event is caused by child or not. static const uint8_t YOUR_FAULT = 2; //!< The fault was caused by child, parent believes it's ok. static const uint8_t MY_FAULT = 3; //!< The fault was caused by the parent, child is ok. - //TODO: Add other messageIDs here if necessary. + //Add other messageIDs here if necessary. static const uint8_t EVENT_MESSAGE_SIZE = HEADER_SIZE + sizeof(Event) + 3 * sizeof(uint32_t); diff --git a/events/EventReportingProxyIF.h b/events/EventReportingProxyIF.h index 9ab783ab..8aca4e26 100644 --- a/events/EventReportingProxyIF.h +++ b/events/EventReportingProxyIF.h @@ -1,10 +1,3 @@ -/* - * EventReportingProxyIF.h - * - * Created on: 19.08.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_EVENTS_EVENTREPORTINGPROXYIF_H_ #define FRAMEWORK_EVENTS_EVENTREPORTINGPROXYIF_H_ diff --git a/events/eventmatching/EventIdRangeMatcher.cpp b/events/eventmatching/EventIdRangeMatcher.cpp index 9a9a802f..ac9156fd 100644 --- a/events/eventmatching/EventIdRangeMatcher.cpp +++ b/events/eventmatching/EventIdRangeMatcher.cpp @@ -1,10 +1,3 @@ -/* - * EventIdRangeMatcher.cpp - * - * Created on: 27.08.2015 - * Author: baetz - */ - #include EventIdRangeMatcher::EventIdRangeMatcher(EventId_t lower, EventId_t upper, diff --git a/events/eventmatching/EventIdRangeMatcher.h b/events/eventmatching/EventIdRangeMatcher.h index ad93de79..57b77cb1 100644 --- a/events/eventmatching/EventIdRangeMatcher.h +++ b/events/eventmatching/EventIdRangeMatcher.h @@ -1,10 +1,3 @@ -/* - * EventIdRangeMatcher.h - * - * Created on: 27.08.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_EVENTS_EVENTMATCHING_EVENTIDRANGEMATCHER_H_ #define FRAMEWORK_EVENTS_EVENTMATCHING_EVENTIDRANGEMATCHER_H_ diff --git a/events/eventmatching/EventMatchTree.cpp b/events/eventmatching/EventMatchTree.cpp index 5360aeca..e1925b8f 100644 --- a/events/eventmatching/EventMatchTree.cpp +++ b/events/eventmatching/EventMatchTree.cpp @@ -1,17 +1,12 @@ -/* - * EventMatchTree.cpp - * - * Created on: 27.08.2015 - * Author: baetz - */ - #include #include #include #include -EventMatchTree::EventMatchTree(StorageManagerIF* storageBackend, bool invertedMatch) : - MatchTree(end(), 1), factory(storageBackend), invertedMatch(invertedMatch) { +EventMatchTree::EventMatchTree(StorageManagerIF* storageBackend, + bool invertedMatch) : + MatchTree(end(), 1), factory(storageBackend), invertedMatch( + invertedMatch) { } EventMatchTree::~EventMatchTree() { @@ -25,9 +20,9 @@ bool EventMatchTree::match(EventMessage* number) { } } -ReturnValue_t EventMatchTree::addMatch(EventId_t idFrom, - EventId_t idTo, bool idInverted, object_id_t reporterFrom, - object_id_t reporterTo, bool reporterInverted) { +ReturnValue_t EventMatchTree::addMatch(EventId_t idFrom, EventId_t idTo, + bool idInverted, object_id_t reporterFrom, object_id_t reporterTo, + bool reporterInverted) { if (idFrom == 0) { //Assuming all events shall be forwarded. idTo = 0; @@ -37,8 +32,8 @@ ReturnValue_t EventMatchTree::addMatch(EventId_t idFrom, idTo = idFrom; } iterator lastTest; - ReturnValue_t result = findOrInsertRangeMatcher( - begin(), idFrom, idTo, idInverted, &lastTest); + ReturnValue_t result = findOrInsertRangeMatcher(begin(), idFrom, idTo, idInverted, &lastTest); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } @@ -54,9 +49,9 @@ ReturnValue_t EventMatchTree::addMatch(EventId_t idFrom, &lastTest); } -ReturnValue_t EventMatchTree::removeMatch(EventId_t idFrom, - EventId_t idTo, bool idInverted, object_id_t reporterFrom, - object_id_t reporterTo, bool reporterInverted) { +ReturnValue_t EventMatchTree::removeMatch(EventId_t idFrom, EventId_t idTo, + bool idInverted, object_id_t reporterFrom, object_id_t reporterTo, + bool reporterInverted) { iterator foundElement; @@ -68,8 +63,8 @@ ReturnValue_t EventMatchTree::removeMatch(EventId_t idFrom, if (idTo == 0) { idTo = idFrom; } - foundElement = findRangeMatcher( - begin(), idFrom, idTo, idInverted); + foundElement = findRangeMatcher(begin(), + idFrom, idTo, idInverted); if (foundElement == end()) { return NO_MATCH; //Can't tell if too detailed or just not found. } @@ -117,6 +112,8 @@ inline ReturnValue_t EventMatchTree::findOrInsertRangeMatcher(iterator start, } Node* newNode = factory.generate(newContent); if (newNode == NULL) { + //Need to make sure partially generated content is deleted, otherwise, that's a leak. + factory.destroy(static_cast(newContent)); return FULL; } *lastTest = insert(attachToBranch, *lastTest, newNode); @@ -145,7 +142,8 @@ EventMatchTree::iterator EventMatchTree::findRangeMatcher(iterator start, } ReturnValue_t EventMatchTree::cleanUpElement(iterator position) { - //TODO: What if first deletion fails? factory.destroy(position.element->value); + //If deletion fails, delete element anyway, nothing we can do. + //SHOULDO: Throw event, or write debug output. return factory.destroy(position.element); } diff --git a/events/eventmatching/EventMatchTree.h b/events/eventmatching/EventMatchTree.h index 696fa505..bd81e3be 100644 --- a/events/eventmatching/EventMatchTree.h +++ b/events/eventmatching/EventMatchTree.h @@ -1,10 +1,3 @@ -/* - * EventMatchTree.h - * - * Created on: 27.08.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_EVENTS_EVENTMATCHING_EVENTMATCHTREE_H_ #define FRAMEWORK_EVENTS_EVENTMATCHING_EVENTMATCHTREE_H_ diff --git a/events/eventmatching/EventRangeMatcherBase.h b/events/eventmatching/EventRangeMatcherBase.h index 5a348ebd..921a5d6a 100644 --- a/events/eventmatching/EventRangeMatcherBase.h +++ b/events/eventmatching/EventRangeMatcherBase.h @@ -1,10 +1,3 @@ -/* - * EventRangeMatcherBase.h - * - * Created on: 27.08.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_EVENTS_EVENTMATCHING_EVENTRANGEMATCHERBASE_H_ #define FRAMEWORK_EVENTS_EVENTMATCHING_EVENTRANGEMATCHERBASE_H_ diff --git a/events/eventmatching/ReporterRangeMatcher.cpp b/events/eventmatching/ReporterRangeMatcher.cpp index b31b5cc3..76b8e788 100644 --- a/events/eventmatching/ReporterRangeMatcher.cpp +++ b/events/eventmatching/ReporterRangeMatcher.cpp @@ -1,10 +1,3 @@ -/* - * ReporterRangeMatcher.cpp - * - * Created on: 27.08.2015 - * Author: baetz - */ - #include ReporterRangeMatcher::ReporterRangeMatcher(object_id_t lower, object_id_t upper, diff --git a/events/eventmatching/ReporterRangeMatcher.h b/events/eventmatching/ReporterRangeMatcher.h index d2c3fcf0..65be2365 100644 --- a/events/eventmatching/ReporterRangeMatcher.h +++ b/events/eventmatching/ReporterRangeMatcher.h @@ -1,10 +1,3 @@ -/* - * ReporterRangeMatcher.h - * - * Created on: 27.08.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_EVENTS_EVENTMATCHING_REPORTERRANGEMATCHER_H_ #define FRAMEWORK_EVENTS_EVENTMATCHING_REPORTERRANGEMATCHER_H_ diff --git a/events/eventmatching/SeverityRangeMatcher.cpp b/events/eventmatching/SeverityRangeMatcher.cpp index a4d9c3e8..98f8d7e1 100644 --- a/events/eventmatching/SeverityRangeMatcher.cpp +++ b/events/eventmatching/SeverityRangeMatcher.cpp @@ -1,10 +1,3 @@ -/* - * SeverityRangeMatcher.cpp - * - * Created on: 27.08.2015 - * Author: baetz - */ - #include #include #include diff --git a/events/eventmatching/SeverityRangeMatcher.h b/events/eventmatching/SeverityRangeMatcher.h index 213fbb1e..ffacff81 100644 --- a/events/eventmatching/SeverityRangeMatcher.h +++ b/events/eventmatching/SeverityRangeMatcher.h @@ -1,10 +1,3 @@ -/* - * SeverityRangeMatcher.h - * - * Created on: 27.08.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_EVENTS_EVENTMATCHING_SEVERITYRANGEMATCHER_H_ #define FRAMEWORK_EVENTS_EVENTMATCHING_SEVERITYRANGEMATCHER_H_ diff --git a/events/fwSubsystemIdRanges.h b/events/fwSubsystemIdRanges.h new file mode 100644 index 00000000..f2308dc0 --- /dev/null +++ b/events/fwSubsystemIdRanges.h @@ -0,0 +1,25 @@ +#ifndef FRAMEWORK_EVENTS_FWSUBSYSTEMIDRANGES_H_ +#define FRAMEWORK_EVENTS_FWSUBSYSTEMIDRANGES_H_ + +namespace SUBSYSTEM_ID { +enum { + OBSW = 26, + CDH = 28, + TCS_1 = 59, + PCDU_1 = 42, + PCDU_2 = 43, + HEATER = 50, + T_SENSORS = 52, + FDIR = 70, + FDIR_1 = 71, + FDIR_2 = 72, + HK = 73, + SYSTEM_MANAGER = 74, + SYSTEM_MANAGER_1 = 75, + SYSTEM_1 = 79, +}; +} + + + +#endif /* FRAMEWORK_EVENTS_FWSUBSYSTEMIDRANGES_H_ */ diff --git a/fdir/ConfirmsFailuresIF.h b/fdir/ConfirmsFailuresIF.h index e9fb4109..99cd212a 100644 --- a/fdir/ConfirmsFailuresIF.h +++ b/fdir/ConfirmsFailuresIF.h @@ -1,19 +1,12 @@ -/* - * ConfirmsFailuresIF.h - * - * Created on: 10.09.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_FDIR_CONFIRMSFAILURESIF_H_ #define FRAMEWORK_FDIR_CONFIRMSFAILURESIF_H_ -#include #include +#include class ConfirmsFailuresIF { public: - static const uint8_t INTERFACE_ID = HANDLES_FAILURES_IF; + static const uint8_t INTERFACE_ID = CLASS_ID::HANDLES_FAILURES_IF; static const ReturnValue_t YOUR_FAULT = MAKE_RETURN_CODE(0); static const ReturnValue_t MY_FAULT = MAKE_RETURN_CODE(1); static const ReturnValue_t CONFIRM_LATER = MAKE_RETURN_CODE(2); diff --git a/fdir/EventCorrelation.cpp b/fdir/EventCorrelation.cpp index c707bed1..32aa3cd3 100644 --- a/fdir/EventCorrelation.cpp +++ b/fdir/EventCorrelation.cpp @@ -1,10 +1,3 @@ -/* - * EventCorrelation.cpp - * - * Created on: 15.10.2015 - * Author: baetz - */ - #include EventCorrelation::EventCorrelation(uint32_t timeout) : diff --git a/fdir/EventCorrelation.h b/fdir/EventCorrelation.h index b40adfc8..0cad6265 100644 --- a/fdir/EventCorrelation.h +++ b/fdir/EventCorrelation.h @@ -1,10 +1,3 @@ -/* - * EventCorrelation.h - * - * Created on: 15.10.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_FDIR_EVENTCORRELATION_H_ #define FRAMEWORK_FDIR_EVENTCORRELATION_H_ diff --git a/fdir/FDIRBase.cpp b/fdir/FailureIsolationBase.cpp similarity index 56% rename from fdir/FDIRBase.cpp rename to fdir/FailureIsolationBase.cpp index bb742254..4b7caac5 100644 --- a/fdir/FDIRBase.cpp +++ b/fdir/FailureIsolationBase.cpp @@ -1,35 +1,32 @@ -/* - * FDIRBase.cpp - * - * Created on: 09.09.2015 - * Author: baetz - */ - #include -#include +#include #include #include +#include #include -FDIRBase::FDIRBase(object_id_t owner, object_id_t parent, uint8_t messageDepth, uint8_t parameterDomainBase) : - eventQueue(messageDepth, EventMessage::EVENT_MESSAGE_SIZE), ownerId( + +FailureIsolationBase::FailureIsolationBase(object_id_t owner, object_id_t parent, uint8_t messageDepth, uint8_t parameterDomainBase) : + eventQueue(NULL), ownerId( owner), owner(NULL), faultTreeParent(parent), parameterDomainBase(parameterDomainBase) { + eventQueue = QueueFactory::instance()->createMessageQueue(messageDepth, EventMessage::EVENT_MESSAGE_SIZE); } -FDIRBase::~FDIRBase() { +FailureIsolationBase::~FailureIsolationBase() { + QueueFactory::instance()->deleteMessageQueue(eventQueue); } -ReturnValue_t FDIRBase::initialize() { +ReturnValue_t FailureIsolationBase::initialize() { EventManagerIF* manager = objectManager->get( objects::EVENT_MANAGER); if (manager == NULL) { return RETURN_FAILED; } - ReturnValue_t result = manager->registerListener(eventQueue.getId()); + ReturnValue_t result = manager->registerListener(eventQueue->getId()); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } if (ownerId != 0) { - result = manager->subscribeToAllEventsFrom(eventQueue.getId(), ownerId); + result = manager->subscribeToAllEventsFrom(eventQueue->getId(), ownerId); if (result != HasReturnvaluesIF::RETURN_OK) { return result; } @@ -44,16 +41,16 @@ ReturnValue_t FDIRBase::initialize() { if (parentIF == NULL) { return RETURN_FAILED; } - eventQueue.setDefaultDestination(parentIF->getEventReceptionQueue()); + eventQueue->setDefaultDestination(parentIF->getEventReceptionQueue()); } return RETURN_OK; } -void FDIRBase::checkForFailures() { +void FailureIsolationBase::checkForFailures() { EventMessage event; - for (ReturnValue_t result = eventQueue.receiveMessage(&event); - result == RETURN_OK; result = eventQueue.receiveMessage(&event)) { - if (event.getSender() == eventQueue.getId()) { + for (ReturnValue_t result = eventQueue->receiveMessage(&event); + result == RETURN_OK; result = eventQueue->receiveMessage(&event)) { + if (event.getSender() == eventQueue->getId()) { //We already got this event, because we sent it. continue; } @@ -81,7 +78,7 @@ void FDIRBase::checkForFailures() { decrementFaultCounters(); } -void FDIRBase::setOwnerHealth(HasHealthIF::HealthState health) { +void FailureIsolationBase::setOwnerHealth(HasHealthIF::HealthState health) { if (owner != NULL) { owner->setHealth(health); } @@ -89,45 +86,45 @@ void FDIRBase::setOwnerHealth(HasHealthIF::HealthState health) { } -MessageQueueId_t FDIRBase::getEventReceptionQueue() { - return eventQueue.getId(); +MessageQueueId_t FailureIsolationBase::getEventReceptionQueue() { + return eventQueue->getId(); } -ReturnValue_t FDIRBase::sendConfirmationRequest(EventMessage* event, +ReturnValue_t FailureIsolationBase::sendConfirmationRequest(EventMessage* event, MessageQueueId_t destination) { event->setMessageId(EventMessage::CONFIRMATION_REQUEST); if (destination != 0) { - return eventQueue.sendMessage(destination, event); + return eventQueue->sendMessage(destination, event); } else if (faultTreeParent != 0) { - return eventQueue.sendToDefault(event); + return eventQueue->sendToDefault(event); } return RETURN_FAILED; } -void FDIRBase::eventConfirmed(EventMessage* event) { +void FailureIsolationBase::eventConfirmed(EventMessage* event) { } -void FDIRBase::wasParentsFault(EventMessage* event) { +void FailureIsolationBase::wasParentsFault(EventMessage* event) { } -void FDIRBase::doConfirmFault(EventMessage* event) { +void FailureIsolationBase::doConfirmFault(EventMessage* event) { ReturnValue_t result = confirmFault(event); if (result == YOUR_FAULT) { event->setMessageId(EventMessage::YOUR_FAULT); - eventQueue.reply(event); + eventQueue->reply(event); } else if (result == MY_FAULT) { event->setMessageId(EventMessage::MY_FAULT); - eventQueue.reply(event); + eventQueue->reply(event); } else { } } -ReturnValue_t FDIRBase::confirmFault(EventMessage* event) { +ReturnValue_t FailureIsolationBase::confirmFault(EventMessage* event) { return YOUR_FAULT; } -void FDIRBase::triggerEvent(Event event, uint32_t parameter1, +void FailureIsolationBase::triggerEvent(Event event, uint32_t parameter1, uint32_t parameter2) { //With this mechanism, all events are disabled for a certain device. //That's not so good for visibility. @@ -135,11 +132,11 @@ void FDIRBase::triggerEvent(Event event, uint32_t parameter1, return; } EventMessage message(event, ownerId, parameter1, parameter2); - EventManagerIF::triggerEvent(&message, eventQueue.getId()); + EventManagerIF::triggerEvent(&message, eventQueue->getId()); eventReceived(&message); } -bool FDIRBase::isFdirDisabledForSeverity(EventSeverity_t severity) { +bool FailureIsolationBase::isFdirDisabledForSeverity(EventSeverity_t severity) { if ((owner != NULL) && (severity != SEVERITY::INFO)) { if (owner->getHealth() == HasHealthIF::EXTERNAL_CONTROL) { //External control disables handling of fault messages. @@ -149,8 +146,8 @@ bool FDIRBase::isFdirDisabledForSeverity(EventSeverity_t severity) { return false; } -void FDIRBase::throwFdirEvent(Event event, uint32_t parameter1, +void FailureIsolationBase::throwFdirEvent(Event event, uint32_t parameter1, uint32_t parameter2) { EventMessage message(event, ownerId, parameter1, parameter2); - EventManagerIF::triggerEvent(&message, eventQueue.getId()); + EventManagerIF::triggerEvent(&message, eventQueue->getId()); } diff --git a/fdir/FDIRBase.h b/fdir/FailureIsolationBase.h similarity index 63% rename from fdir/FDIRBase.h rename to fdir/FailureIsolationBase.h index 54686796..cd582e39 100644 --- a/fdir/FDIRBase.h +++ b/fdir/FailureIsolationBase.h @@ -1,34 +1,32 @@ -/* - * FDIRBase.h - * - * Created on: 09.09.2015 - * Author: baetz - */ - -#ifndef FRAMEWORK_FDIR_FDIRBASE_H_ -#define FRAMEWORK_FDIR_FDIRBASE_H_ +#ifndef FRAMEWORK_FDIR_FAILUREISOLATIONBASE_H_ +#define FRAMEWORK_FDIR_FAILUREISOLATIONBASE_H_ #include #include #include #include -#include #include #include -class FDIRBase: public HasReturnvaluesIF, public ConfirmsFailuresIF, public HasParametersIF { +#include + +class FailureIsolationBase: public HasReturnvaluesIF, + public ConfirmsFailuresIF, + public HasParametersIF { public: static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FDIR_1; static const Event FDIR_CHANGED_STATE = MAKE_EVENT(1, SEVERITY::INFO); //!< FDIR has an internal state, which changed from par2 (oldState) to par1 (newState). static const Event FDIR_STARTS_RECOVERY = MAKE_EVENT(2, SEVERITY::MEDIUM); //!< FDIR tries to restart device. Par1: event that caused recovery. static const Event FDIR_TURNS_OFF_DEVICE = MAKE_EVENT(3, SEVERITY::MEDIUM); //!< FDIR turns off device. Par1: event that caused recovery. - FDIRBase(object_id_t owner, object_id_t parent = 0, uint8_t messageDepth = 10, uint8_t parameterDomainBase = 0xF0); - virtual ~FDIRBase(); + FailureIsolationBase(object_id_t owner, object_id_t parent = 0, + uint8_t messageDepth = 10, uint8_t parameterDomainBase = 0xF0); + virtual ~FailureIsolationBase(); virtual ReturnValue_t initialize(); void checkForFailures(); MessageQueueId_t getEventReceptionQueue(); - virtual void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0); + virtual void triggerEvent(Event event, uint32_t parameter1 = 0, + uint32_t parameter2 = 0); protected: - MessageQueue eventQueue; + MessageQueueIF* eventQueue; object_id_t ownerId; HasHealthIF* owner; object_id_t faultTreeParent; @@ -39,11 +37,13 @@ protected: virtual void wasParentsFault(EventMessage* event); virtual ReturnValue_t confirmFault(EventMessage* event); virtual void decrementFaultCounters() = 0; - ReturnValue_t sendConfirmationRequest(EventMessage* event, MessageQueueId_t destination = 0); - void throwFdirEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0); + ReturnValue_t sendConfirmationRequest(EventMessage* event, + MessageQueueId_t destination = 0); + void throwFdirEvent(Event event, uint32_t parameter1 = 0, + uint32_t parameter2 = 0); private: - void doConfirmFault(EventMessage* event); - bool isFdirDisabledForSeverity(EventSeverity_t severity); + void doConfirmFault(EventMessage* event);bool isFdirDisabledForSeverity( + EventSeverity_t severity); }; -#endif /* FRAMEWORK_FDIR_FDIRBASE_H_ */ +#endif /* FRAMEWORK_FDIR_FAILUREISOLATIONBASE_H_ */ diff --git a/fdir/FaultCounter.cpp b/fdir/FaultCounter.cpp index 671aa6a4..3dc899c2 100644 --- a/fdir/FaultCounter.cpp +++ b/fdir/FaultCounter.cpp @@ -1,10 +1,3 @@ -/* - * FaultCounter.cpp - * - * Created on: 15.09.2015 - * Author: baetz - */ - #include FaultCounter::FaultCounter(uint32_t failureThreshold, uint32_t decrementAfterMs, diff --git a/fdir/FaultCounter.h b/fdir/FaultCounter.h index d63dfa66..ac23853c 100644 --- a/fdir/FaultCounter.h +++ b/fdir/FaultCounter.h @@ -1,10 +1,3 @@ -/* - * FaultCounter.h - * - * Created on: 15.09.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_FDIR_FAULTCOUNTER_H_ #define FRAMEWORK_FDIR_FAULTCOUNTER_H_ diff --git a/framework.mk b/framework.mk new file mode 100644 index 00000000..84ae87b5 --- /dev/null +++ b/framework.mk @@ -0,0 +1,44 @@ +# This file needs FRAMEWORK_PATH set correctly + +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/action/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/container/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/controller/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/coordinates/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datalinklayer/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/datapool/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/devicehandlers/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/events/eventmatching/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/fdir/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/framework.mk/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/globalfunctions/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/globalfunctions/matching/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/globalfunctions/math/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/health/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/internalError/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/ipc/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/memory/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/modes/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/monitoring/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/objectmanager/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/*.cpp) +#TODO should be ifdef'd +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/rtems/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/parameters/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/power/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/returnvalues/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/rmap/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/serialize/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/serviceinterface/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/storagemanager/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/subsystem/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/subsystem/modes/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tasks/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tcdistribution/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/thermal/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/timemanager/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmstorage/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/packetmatcher/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcpacket/pus/*.cpp) +CXXSRC += $(wildcard $(FRAMEWORK_PATH)/tmtcservices/*.cpp) \ No newline at end of file diff --git a/globalfunctions/AsciiConverter.h b/globalfunctions/AsciiConverter.h index 8ba58cb1..acd406da 100644 --- a/globalfunctions/AsciiConverter.h +++ b/globalfunctions/AsciiConverter.h @@ -5,7 +5,7 @@ class AsciiConverter: public HasReturnvaluesIF { public: - static const uint8_t INTERFACE_ID = ASCII_CONVERTER; + static const uint8_t INTERFACE_ID = CLASS_ID::ASCII_CONVERTER; static const ReturnValue_t TOO_LONG_FOR_TARGET_TYPE = MAKE_RETURN_CODE(1); static const ReturnValue_t INVALID_CHARACTERS = MAKE_RETURN_CODE(2); static const ReturnValue_t BUFFER_TOO_SMALL = MAKE_RETURN_CODE(0x3); diff --git a/globalfunctions/Makefile b/globalfunctions/Makefile deleted file mode 100755 index 8e94bbcb..00000000 --- a/globalfunctions/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -# -# OSAL makefile -# -# Created on: Mar 04, 2010 -# Author: ziemke -# Author: Claas Ziemke -# Copyright 2010, Claas Ziemke -# - -BASEDIR=../../ -include $(BASEDIR)options.mk - -OBJ = $(BUILDDIR)/crc_ccitt.o\ - $(BUILDDIR)/conversion.o\ - $(BUILDDIR)/math_custom.o\ - -all: $(OBJ) - -$(BUILDDIR)/%.o: %.cpp %.h - $(CPP) $(CFLAGS) $(DEFINES) $(CCOPT) ${INCLUDE} -c $< -o $@ - -clean: - $(RM) *.o *.gcno *.gcda diff --git a/globalfunctions/constants.h b/globalfunctions/constants.h index ae488a78..2c3b66c1 100644 --- a/globalfunctions/constants.h +++ b/globalfunctions/constants.h @@ -8,7 +8,8 @@ static const double PI = 3.1415926535897932384626433; namespace Earth { static const double OMEGA = 7.2921158553E-5; static const double GRAVITATIONAL_CONSTANT = 3.987095392E14; -static const double MEAN_RADIUS = 6371000; +static const double MEAN_RADIUS = 6371008.8; +static const double STANDARD_GRAVITATIONAL_PARAMETER = 3.9860044189e14; } #endif /* CONSTANTS_H_ */ diff --git a/globalfunctions/conversion.cpp b/globalfunctions/conversion.cpp index 8278e796..8f2f1eb6 100644 --- a/globalfunctions/conversion.cpp +++ b/globalfunctions/conversion.cpp @@ -1,12 +1,11 @@ -/* - * conversion.cpp - * - * Created on: 07.05.2012 - * Author: baetz - */ - #include -//TODO: This shall be optimized (later)! +//TODO REMOVE. Needed because of BYTE_ORDER +#include +#include + + + +//SHOULDDO: This shall be optimized (later)! void convertToByteStream( uint16_t value, uint8_t* buffer, uint32_t* size ) { buffer[0] = (value & 0xFF00) >> 8; buffer[1] = (value & 0x00FF); diff --git a/globalfunctions/conversion.h b/globalfunctions/conversion.h index 33daf94b..0d1ca1a6 100644 --- a/globalfunctions/conversion.h +++ b/globalfunctions/conversion.h @@ -1,15 +1,8 @@ -/* - * conversion.h - * - * Created on: 07.05.2012 - * Author: baetz - */ - #ifndef CONVERSION_H_ #define CONVERSION_H_ -#include +#include void convertToByteStream( uint16_t value, uint8_t* buffer, uint32_t* size ); diff --git a/globalfunctions/crc_ccitt.cpp b/globalfunctions/crc_ccitt.cpp index a894c2d2..2fbebd07 100644 --- a/globalfunctions/crc_ccitt.cpp +++ b/globalfunctions/crc_ccitt.cpp @@ -1,10 +1,3 @@ -/* - * crc.cpp - * - * Created on: 03.04.2012 - * Author: bucher - */ - #include #include diff --git a/globalfunctions/crc_ccitt.h b/globalfunctions/crc_ccitt.h index 85c66a83..6310f184 100644 --- a/globalfunctions/crc_ccitt.h +++ b/globalfunctions/crc_ccitt.h @@ -1,10 +1,3 @@ -/* - * crc.h - * - * Created on: 03.04.2012 - * Author: bucher - */ - #ifndef CRC_CCITT_H_ #define CRC_CCITT_H_ diff --git a/globalfunctions/matching/MatchTree.h b/globalfunctions/matching/MatchTree.h index 6732d317..398cf3f0 100644 --- a/globalfunctions/matching/MatchTree.h +++ b/globalfunctions/matching/MatchTree.h @@ -1,10 +1,3 @@ -/* - * MatchTree.h - * - * Created on: 09.03.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_GLOBALFUNCTIONS_MATCHING_MATCHTREE_H_ #define FRAMEWORK_GLOBALFUNCTIONS_MATCHING_MATCHTREE_H_ @@ -17,11 +10,12 @@ class MatchTree: public SerializeableMatcherIF, public BinaryTree< SerializeableMatcherIF> { public: - static const uint8_t INTERFACE_ID = MATCH_TREE_CLASS; + static const uint8_t INTERFACE_ID = CLASS_ID::MATCH_TREE_CLASS; static const ReturnValue_t TOO_DETAILED_REQUEST = MAKE_RETURN_CODE(1); static const ReturnValue_t TOO_GENERAL_REQUEST = MAKE_RETURN_CODE(2); static const ReturnValue_t NO_MATCH = MAKE_RETURN_CODE(3); static const ReturnValue_t FULL = MAKE_RETURN_CODE(4); + static const ReturnValue_t NEW_NODE_CREATED = MAKE_RETURN_CODE(5); typedef typename BinaryTree>::iterator iterator; typedef BinaryNode> Node; @@ -41,26 +35,14 @@ public: virtual ~MatchTree() { } virtual bool match(T number) { - return matchesTree(number, NULL, NULL); + return matchesTree(number); } - bool matchesTree(T number, iterator* lastTest, uint8_t* hierarchyLevel) { - bool match = false; + bool matchesTree(T number) { iterator iter = this->begin(); - while (iter != this->end()) { - if (lastTest != NULL) { - *lastTest = iter; - } - match = iter->match(number); - if (match) { - iter = iter.left(); - if (hierarchyLevel != NULL) { - (*hierarchyLevel)++; - } - } else { - iter = iter.right(); - } + if (iter == this->end()) { + return false; } - return match; + return matchSubtree(iter, number); } ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, @@ -134,7 +116,7 @@ public: } ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { + bool bigEndian) { return HasReturnvaluesIF::RETURN_OK; } @@ -151,16 +133,22 @@ protected: } } - //TODO: What to do if insertion/deletion fails. Throw event? + //SHOULDDO: What to do if insertion/deletion fails. Throw event? ReturnValue_t removeElementAndAllChildren(iterator position) { - auto children = erase(position); + auto children = this->erase(position); ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; if (children.first != this->end()) { result = removeElementAndAllChildren(children.first); } + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } if (children.second != this->end()) { result = removeElementAndAllChildren(children.second); } + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } //Delete element itself. return cleanUpElement(position); } @@ -173,15 +161,19 @@ protected: ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; if (position.left() != this->end()) { result = removeElementAndAllChildren(position.left()); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } } + if (position.right() != this->end()) { //There's something at the OR branch, reconnect to parent. if (isOnAndBranch(position)) { //Either one hierarchy up AND branch... - insert(AND, position.up(), position.right().element); + this->insert(AND, position.up(), position.right().element); } else { //or on another OR'ed element (or install new root node). - insert(OR, position.up(), position.right().element); + this->insert(OR, position.up(), position.right().element); } } else { if (isOnAndBranch(position)) { @@ -189,7 +181,7 @@ protected: return removeElementAndReconnectChildren(position.up()); } else { //simply delete self. - erase(position); + this->erase(position); } } @@ -201,6 +193,22 @@ protected: return HasReturnvaluesIF::RETURN_OK; } + bool matchSubtree(iterator iter, T number) { + bool isMatch = iter->match(number); + if (isMatch) { + if (iter.left() == this->end()) { + return true; + } + isMatch = matchSubtree(iter.left(), number); + if (isMatch) { + return true; + } + } + if (iter.right() == this->end()) { + return false; + } + return matchSubtree(iter.right(), number); + } private: uint8_t maxDepth; }; diff --git a/globalfunctions/matching/RangeMatcher.h b/globalfunctions/matching/RangeMatcher.h index 1fe6675c..10e07173 100644 --- a/globalfunctions/matching/RangeMatcher.h +++ b/globalfunctions/matching/RangeMatcher.h @@ -21,7 +21,7 @@ public: bool match(T input) { if (inverted) { - return ~doMatch(input); + return !doMatch(input); } else { return doMatch(input); } diff --git a/globalfunctions/matching/SerializeableMatcherIF.h b/globalfunctions/matching/SerializeableMatcherIF.h index 6b3035e9..7b00a1b3 100644 --- a/globalfunctions/matching/SerializeableMatcherIF.h +++ b/globalfunctions/matching/SerializeableMatcherIF.h @@ -1,10 +1,3 @@ -/* - * SerializeableMatcherIF.h - * - * Created on: 09.03.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_GLOBALFUNCTIONS_MATCHING_SERIALIZEABLEMATCHERIF_H_ #define FRAMEWORK_GLOBALFUNCTIONS_MATCHING_SERIALIZEABLEMATCHERIF_H_ diff --git a/globalfunctions/math/MatrixOperations.h b/globalfunctions/math/MatrixOperations.h index e4d82234..66f89c53 100644 --- a/globalfunctions/math/MatrixOperations.h +++ b/globalfunctions/math/MatrixOperations.h @@ -4,15 +4,16 @@ #include #include -template +template class MatrixOperations { public: - virtual ~MatrixOperations() { - } - - //do not use with result == matrix1 or matrix2 //TODO? - static void multiply(const T *matrix1, const T *matrix2, T *result, + //do not use with result == matrix1 or matrix2 + static void multiply(const T1 *matrix1, const T2 *matrix2, T3 *result, uint8_t rows1, uint8_t columns1, uint8_t columns2) { + if ((matrix1 == (T1*)result) || (matrix2 == (T2*)result)){ + //SHOULDDO find an implementation that is tolerant to this + return; + } for (uint8_t resultColumn = 0; resultColumn < columns2; resultColumn++) { for (uint8_t resultRow = 0; resultRow < rows1; resultRow++) { @@ -26,21 +27,89 @@ public: } } - static void transpose(const T *matrix, T *transposed, uint8_t size) { + static void transpose(const T1 *matrix, T2 *transposed, uint8_t size) { uint8_t row, column; transposed[0] = matrix[0]; for (column = 1; column < size; column++) { transposed[column + size * column] = matrix[column + size * column]; for (row = 0; row < column; row++) { - T temp = matrix[column + size * row]; + T1 temp = matrix[column + size * row]; transposed[column + size * row] = matrix[row + size * column]; transposed[row + size * column] = temp; } } } -private: - MatrixOperations(); + // Overload transpose to support non symmetrical matrices + //do not use with transposed == matrix && columns != rows + static void transpose(const T1 *matrix, T2 *transposed, uint8_t rows, uint8_t columns) { + uint8_t row, column; + transposed[0] = matrix[0]; + if (matrix == transposed && columns == rows) + { + transpose(matrix, transposed, rows); + } + else if (matrix == transposed && columns != rows) + { + // not permitted + return; + } + for (column = 0; column < columns; column++) { + for (row = 0; row < rows; row++) { + transposed[row + column * rows] = matrix[column + row * columns]; + } + } + } + + static void add(const T1 *matrix1, const T2 *matrix2, T3 *result, + uint8_t rows, uint8_t columns) + { + for (uint8_t resultColumn = 0; resultColumn < columns; resultColumn++) + { + for (uint8_t resultRow = 0; resultRow < rows; resultRow++) + { + result[resultColumn + columns * resultRow] = matrix1[resultColumn + columns * resultRow]+ + matrix2[resultColumn + columns * resultRow]; + } + } + } + + static void subtract(const T1 *matrix1, const T2 *matrix2, T3 *result, + uint8_t rows, uint8_t columns) + { + for (uint8_t resultColumn = 0; resultColumn < columns; resultColumn++) + { + for (uint8_t resultRow = 0; resultRow < rows; resultRow++) + { + result[resultColumn + columns * resultRow] = matrix1[resultColumn + columns * resultRow]- + matrix2[resultColumn + columns * resultRow]; + } + } + } + + static void addScalar(const T1 *matrix1, const T2 scalar, T3 *result, + uint8_t rows, uint8_t columns) + { + for (uint8_t resultColumn = 0; resultColumn < columns; resultColumn++) + { + for (uint8_t resultRow = 0; resultRow < rows; resultRow++) + { + result[resultColumn + columns * resultRow] = matrix1[resultColumn + columns * resultRow]+scalar; + } + } + } + + static void multiplyScalar(const T1 *matrix1, const T2 scalar, T3 *result, + uint8_t rows, uint8_t columns) + { + for (uint8_t resultColumn = 0; resultColumn < columns; resultColumn++) + { + for (uint8_t resultRow = 0; resultRow < rows; resultRow++) + { + result[resultColumn + columns * resultRow] = matrix1[resultColumn + columns * resultRow]*scalar; + } + } + } }; #endif /* MATRIXOPERATIONS_H_ */ diff --git a/globalfunctions/math/QuaternionOperations.cpp b/globalfunctions/math/QuaternionOperations.cpp index cb06a22e..f8c75149 100644 --- a/globalfunctions/math/QuaternionOperations.cpp +++ b/globalfunctions/math/QuaternionOperations.cpp @@ -1,6 +1,5 @@ -#include +#include "QuaternionOperations.h" #include -#include "VectorOperations.h" #include #include @@ -79,7 +78,7 @@ void QuaternionOperations::fromDcm(const double dcm[][3], double* quaternion, uint8_t maxAIndex = 0; - VectorOperations::maxAbsValue(a, 4, &maxAIndex); + VectorOperations::maxValue(a, 4, &maxAIndex); if (index != 0) { *index = maxAIndex; diff --git a/globalfunctions/math/QuaternionOperations.h b/globalfunctions/math/QuaternionOperations.h index 9b3192aa..0d6fe860 100644 --- a/globalfunctions/math/QuaternionOperations.h +++ b/globalfunctions/math/QuaternionOperations.h @@ -9,8 +9,9 @@ public: static void multiply(const double *q1, const double *q2, double *q); - static void fromDcm(const double dcm[][3],double *quaternion, uint8_t *index = 0); - + static void fromDcm(const double dcm[][3], double *quaternion, + uint8_t *index = 0); + static void toDcm(const double *quaternion, double dcm[][3]); static void toDcm(const double *quaternion, float dcm[][3]); @@ -28,6 +29,51 @@ public: */ static double getAngle(const double *quaternion, bool abs = false); + //multiplies 3d vector with dcm derived from quaternion + template + static void multiplyVector(const double *quaternion, const T *vector, + T * result) { + result[0] = + (2. + * (quaternion[0] * quaternion[0] + + quaternion[3] * quaternion[3]) - 1.) + * vector[0] + + 2. + * (quaternion[0] * quaternion[1] + + quaternion[2] * quaternion[3]) + * vector[1] + + 2. + * (quaternion[0] * quaternion[2] + - quaternion[1] * quaternion[3]) + * vector[2]; + + result[1] = + 2. + * (quaternion[0] * quaternion[1] + - quaternion[2] * quaternion[3]) * vector[0] + + (2. + * (quaternion[1] * quaternion[1] + + quaternion[3] * quaternion[3]) - 1.) + * vector[1] + + 2. + * (quaternion[1] * quaternion[2] + + quaternion[0] * quaternion[3]) + * vector[2]; + + result[2] = + 2. + * (quaternion[0] * quaternion[2] + + quaternion[1] * quaternion[3]) * vector[0] + + 2. + * (quaternion[1] * quaternion[2] + - quaternion[0] * quaternion[3]) + * vector[1] + + (2. + * (quaternion[2] * quaternion[2] + + quaternion[3] * quaternion[3]) - 1.) + * vector[2]; + } + private: QuaternionOperations(); }; diff --git a/globalfunctions/math/VectorOperations.h b/globalfunctions/math/VectorOperations.h index d81bdbfa..f65d2263 100644 --- a/globalfunctions/math/VectorOperations.h +++ b/globalfunctions/math/VectorOperations.h @@ -38,11 +38,11 @@ public: } static void subtract(const T vector1[], const T vector2[], T sum[], - uint8_t size = 3) { - for (; size > 0; size--) { - sum[size - 1] = vector1[size - 1] - vector2[size - 1]; - } + uint8_t size = 3) { + for (; size > 0; size--) { + sum[size - 1] = vector1[size - 1] - vector2[size - 1]; } + } static T norm(const T *vector, uint8_t size) { T result = 0; @@ -76,6 +76,26 @@ public: return max; } + static T maxValue(const T *vector, uint8_t size, uint8_t *index = 0) { + + T max = -1; + + for (; size > 0; size--) { + if (vector[size - 1] > max) { + max = vector[size - 1]; + if (index != 0) { + *index = size - 1; + } + } + } + return max; + } + + + static void copy(const T *in, T *out, uint8_t size) { + mulScalar(in, 1, out, size); + } + private: VectorOperations(); }; diff --git a/globalfunctions/timevalOperations.cpp b/globalfunctions/timevalOperations.cpp index 0ebd8caa..253b6eb7 100644 --- a/globalfunctions/timevalOperations.cpp +++ b/globalfunctions/timevalOperations.cpp @@ -1,8 +1,4 @@ #include -#include -#include - -//TODO test with large numbers timeval& operator+=(timeval& lhs, const timeval& rhs) { int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec; diff --git a/globalfunctions/timevalOperations.h b/globalfunctions/timevalOperations.h index 674220fb..a553e60a 100644 --- a/globalfunctions/timevalOperations.h +++ b/globalfunctions/timevalOperations.h @@ -32,6 +32,14 @@ bool operator<=(const timeval& lhs, const timeval& rhs); bool operator>=(const timeval& lhs, const timeval& rhs); namespace timevalOperations { +/** + * returns the seconds and subseconds stored in the timeval + * as double [s] + * + * + * @param timeval + * @return seconds + */ double toDouble(const timeval timeval); } diff --git a/health/HasHealthIF.h b/health/HasHealthIF.h index 12ed1cb2..dd27fe39 100644 --- a/health/HasHealthIF.h +++ b/health/HasHealthIF.h @@ -2,8 +2,8 @@ #define HASHEALTHIF_H_ #include -#include #include +#include class HasHealthIF { public: @@ -12,7 +12,7 @@ public: HEALTHY = 1, FAULTY = 0, EXTERNAL_CONTROL = 2, NEEDS_RECOVERY = 3, PERMANENT_FAULTY = 4 } HealthState; - static const uint8_t INTERFACE_ID = HAS_HEALTH_IF; + static const uint8_t INTERFACE_ID = CLASS_ID::HAS_HEALTH_IF; static const ReturnValue_t OBJECT_NOT_HEALTHY = MAKE_RETURN_CODE(1); static const ReturnValue_t INVALID_HEALTH_STATE = MAKE_RETURN_CODE(2); @@ -21,9 +21,9 @@ public: static const Event CHILD_CHANGED_HEALTH = MAKE_EVENT(7, SEVERITY::INFO); static const Event CHILD_PROBLEMS = MAKE_EVENT(8, SEVERITY::LOW); static const Event OVERWRITING_HEALTH = MAKE_EVENT(9, SEVERITY::LOW); //!< Assembly overwrites health information of children to keep satellite alive. - static const Event TRYING_RECOVERY = MAKE_EVENT(10, SEVERITY::MEDIUM); - static const Event RECOVERY_STEP = MAKE_EVENT(11, SEVERITY::MEDIUM); - static const Event RECOVERY_DONE = MAKE_EVENT(12, SEVERITY::MEDIUM); + static const Event TRYING_RECOVERY = MAKE_EVENT(10, SEVERITY::MEDIUM); //!< Someone starts a recovery of a component (typically power-cycle). No parameters. + static const Event RECOVERY_STEP = MAKE_EVENT(11, SEVERITY::MEDIUM); //!< Recovery is ongoing. Comes twice during recovery. P1: 0 for the first, 1 for the second event. P2: 0 + static const Event RECOVERY_DONE = MAKE_EVENT(12, SEVERITY::MEDIUM); //!< Recovery was completed. Not necessarily successful. No parameters. virtual ~HasHealthIF() { } diff --git a/health/HealthHelper.cpp b/health/HealthHelper.cpp index e769d2e5..8fc413ed 100644 --- a/health/HealthHelper.cpp +++ b/health/HealthHelper.cpp @@ -1,6 +1,5 @@ -#include #include -#include +#include #include HealthHelper::HealthHelper(HasHealthIF* owner, object_id_t objectId) : healthTable(NULL), eventSender(NULL), objectId(objectId), parentQueue( @@ -67,11 +66,10 @@ void HealthHelper::informParent(HasHealthIF::HealthState health, return; } CommandMessage message; - MessageQueueSender sender(parentQueue); HealthMessage::setHealthMessage(&message, HealthMessage::HEALTH_INFO, health, oldHealth); - if (sender.sendToDefault(&message, owner->getCommandQueue()) - != HasReturnvaluesIF::RETURN_OK) { + if (MessageQueueSenderIF::sendMessage(parentQueue, &message, + owner->getCommandQueue()) != HasReturnvaluesIF::RETURN_OK) { debug << "HealthHelper::informParent: sending health reply failed." << std::endl; } @@ -89,9 +87,8 @@ void HealthHelper::handleSetHealthCommand(CommandMessage* message) { } else { reply.setReplyRejected(result, message->getCommand()); } - MessageQueueSender sender(message->getSender()); - if (sender.sendToDefault(&reply, owner->getCommandQueue()) - != HasReturnvaluesIF::RETURN_OK) { + if (MessageQueueSenderIF::sendMessage(message->getSender(), &reply, + owner->getCommandQueue()) != HasReturnvaluesIF::RETURN_OK) { debug << "HealthHelper::handleHealthCommand: sending health reply failed." << std::endl; diff --git a/health/HealthMessage.cpp b/health/HealthMessage.cpp index 7e33cafb..768dea46 100644 --- a/health/HealthMessage.cpp +++ b/health/HealthMessage.cpp @@ -1,10 +1,3 @@ -/* - * HealthMessage.cpp - * - * Created on: 15.07.2013 - * Author: tod - */ - #include void HealthMessage::setHealthMessage(CommandMessage* message, Command_t command, diff --git a/health/HealthMessage.h b/health/HealthMessage.h index 1cad099e..7fd00904 100644 --- a/health/HealthMessage.h +++ b/health/HealthMessage.h @@ -1,10 +1,3 @@ -/* - * HealthMessage.h - * - * Created on: 15.07.2013 - * Author: tod - */ - #ifndef HEALTHMESSAGE_H_ #define HEALTHMESSAGE_H_ @@ -13,7 +6,7 @@ class HealthMessage { public: - static const uint8_t MESSAGE_ID = HEALTH_COMMAND_MESSAGE_ID; + static const uint8_t MESSAGE_ID = MESSAGE_TYPE::HEALTH_COMMAND; static const Command_t HEALTH_SET = MAKE_COMMAND_ID(1);//REPLY_COMMAND_OK/REPLY_REJECTED static const Command_t HEALTH_ANNOUNCE = MAKE_COMMAND_ID(3); //NO REPLY! static const Command_t HEALTH_INFO = MAKE_COMMAND_ID(5); diff --git a/health/HealthTable.cpp b/health/HealthTable.cpp index a26cb906..a575b282 100644 --- a/health/HealthTable.cpp +++ b/health/HealthTable.cpp @@ -1,17 +1,16 @@ #include #include +#include HealthTable::HealthTable(object_id_t objectid) : SystemObject(objectid) { - mutex = new MutexId_t; - OSAL::createMutex(objectid + 1, mutex); + mutex = MutexFactory::instance()->createMutex();; mapIterator = healthMap.begin(); } HealthTable::~HealthTable() { - OSAL::deleteMutex(mutex); - delete mutex; + MutexFactory::instance()->deleteMutex(mutex); } ReturnValue_t HealthTable::registerObject(object_id_t object, @@ -27,45 +26,45 @@ ReturnValue_t HealthTable::registerObject(object_id_t object, void HealthTable::setHealth(object_id_t object, HasHealthIF::HealthState newState) { - OSAL::lockMutex(mutex, OSAL::NO_TIMEOUT); + mutex->lockMutex(MutexIF::NO_TIMEOUT); HealthMap::iterator iter = healthMap.find(object); if (iter != healthMap.end()) { iter->second = newState; } - OSAL::unlockMutex(mutex); + mutex->unlockMutex(); } HasHealthIF::HealthState HealthTable::getHealth(object_id_t object) { HasHealthIF::HealthState state = HasHealthIF::HEALTHY; - OSAL::lockMutex(mutex, OSAL::NO_TIMEOUT); + mutex->lockMutex(MutexIF::NO_TIMEOUT); HealthMap::iterator iter = healthMap.find(object); if (iter != healthMap.end()) { state = iter->second; } - OSAL::unlockMutex(mutex); + mutex->unlockMutex(); return state; } uint32_t HealthTable::getPrintSize() { - OSAL::lockMutex(mutex, OSAL::NO_TIMEOUT); + mutex->lockMutex(MutexIF::NO_TIMEOUT); uint32_t size = healthMap.size() * 5 + 2; - OSAL::unlockMutex(mutex); + mutex->unlockMutex(); return size; } bool HealthTable::hasHealth(object_id_t object) { bool exits = false; - OSAL::lockMutex(mutex, OSAL::NO_TIMEOUT); + mutex->lockMutex(MutexIF::NO_TIMEOUT); HealthMap::iterator iter = healthMap.find(object); if (iter != healthMap.end()) { exits = true; } - OSAL::unlockMutex(mutex); + mutex->unlockMutex(); return exits; } void HealthTable::printAll(uint8_t* pointer, uint32_t maxSize) { - OSAL::lockMutex(mutex, OSAL::NO_TIMEOUT); + mutex->lockMutex(MutexIF::NO_TIMEOUT); uint32_t size = 0; uint16_t count = healthMap.size(); ReturnValue_t result = SerializeAdapter::serialize(&count, @@ -80,13 +79,13 @@ void HealthTable::printAll(uint8_t* pointer, uint32_t maxSize) { result = SerializeAdapter::serialize(&health, &pointer, &size, maxSize, true); } - OSAL::unlockMutex(mutex); + mutex->unlockMutex(); } ReturnValue_t HealthTable::iterate( std::pair *value, bool reset) { ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - OSAL::lockMutex(mutex, OSAL::NO_TIMEOUT); + mutex->lockMutex(MutexIF::NO_TIMEOUT); if (reset) { mapIterator = healthMap.begin(); } @@ -95,7 +94,7 @@ ReturnValue_t HealthTable::iterate( } *value = *mapIterator; mapIterator++; - OSAL::unlockMutex(mutex); + mutex->unlockMutex(); return result; } diff --git a/health/HealthTable.h b/health/HealthTable.h index 4df0ae9e..32a7eee2 100644 --- a/health/HealthTable.h +++ b/health/HealthTable.h @@ -3,7 +3,7 @@ #include #include -#include +#include #include typedef std::map HealthMap; @@ -24,7 +24,7 @@ public: virtual void printAll(uint8_t *pointer, uint32_t maxSize); protected: - MutexId_t* mutex; + MutexIF* mutex; HealthMap healthMap; HealthMap::iterator mapIterator; diff --git a/health/HealthTableIF.h b/health/HealthTableIF.h index cca41c13..6fdfc2c0 100644 --- a/health/HealthTableIF.h +++ b/health/HealthTableIF.h @@ -1,10 +1,3 @@ -/* - * HealthTabelIF.h - * - * Created on: 15.07.2013 - * Author: tod - */ - #ifndef HEALTHTABLEIF_H_ #define HEALTHTABLEIF_H_ diff --git a/health/ManagesHealthIF.h b/health/ManagesHealthIF.h index 6463e853..ff0c5386 100644 --- a/health/ManagesHealthIF.h +++ b/health/ManagesHealthIF.h @@ -1,10 +1,3 @@ -/* - * ManagesHealthIF.h - * - * Created on: 13.10.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_HEALTH_MANAGESHEALTHIF_H_ #define FRAMEWORK_HEALTH_MANAGESHEALTHIF_H_ @@ -41,11 +34,6 @@ public: return (health == HasHealthIF::PERMANENT_FAULTY); } - virtual bool shouldBeMonitored(object_id_t object) { - HasHealthIF::HealthState health = getHealth(object); - return shouldBeMonitored(health); - } - static bool isFaulty(HasHealthIF::HealthState health) { return ((health == HasHealthIF::FAULTY) || (health == HasHealthIF::PERMANENT_FAULTY) diff --git a/internalError/InternalErrorReporter.cpp b/internalError/InternalErrorReporter.cpp new file mode 100644 index 00000000..9a8ede00 --- /dev/null +++ b/internalError/InternalErrorReporter.cpp @@ -0,0 +1,126 @@ +#include "InternalErrorReporter.h" + +#include +#include +#include + +#include + +InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, + uint32_t queuePoolId, uint32_t tmPoolId, uint32_t storePoolId) : + SystemObject(setObjectId), mutex(NULL), queuePoolId(queuePoolId), tmPoolId( + tmPoolId), storePoolId( + storePoolId), queueHits(0), tmHits(0), storeHits( + 0) { + mutex = MutexFactory::instance()->createMutex(); +} + +InternalErrorReporter::~InternalErrorReporter() { + MutexFactory::instance()->deleteMutex(mutex); +} + +ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) { + + DataSet mySet; + PoolVariable queueHitsInPool(queuePoolId, &mySet, + PoolVariableIF::VAR_READ_WRITE); + PoolVariable tmHitsInPool(tmPoolId, &mySet, + PoolVariableIF::VAR_READ_WRITE); + + PoolVariable storeHitsInPool(storePoolId, &mySet, + PoolVariableIF::VAR_READ_WRITE); + mySet.read(); + + uint32_t newQueueHits = getAndResetQueueHits(); + uint32_t newTmHits = getAndResetTmHits(); + uint32_t newStoreHits = getAndResetStoreHits(); + + queueHitsInPool.value += newQueueHits; + tmHitsInPool.value += newTmHits; + storeHitsInPool.value += newStoreHits; + + mySet.commit(PoolVariableIF::VALID); + + return HasReturnvaluesIF::RETURN_OK; +} + +void InternalErrorReporter::queueMessageNotSent() { + incrementQueueHits(); +} + +void InternalErrorReporter::lostTm() { + incrementTmHits(); +} + +uint32_t InternalErrorReporter::getAndResetQueueHits() { + uint32_t value; + mutex->lockMutex(MutexIF::NO_TIMEOUT); + value = queueHits; + queueHits = 0; + mutex->unlockMutex(); + return value; +} + +uint32_t InternalErrorReporter::getQueueHits() { + uint32_t value; + mutex->lockMutex(MutexIF::NO_TIMEOUT); + value = queueHits; + mutex->unlockMutex(); + return value; +} + +void InternalErrorReporter::incrementQueueHits() { + mutex->lockMutex(MutexIF::NO_TIMEOUT); + queueHits++; + mutex->unlockMutex(); +} + +uint32_t InternalErrorReporter::getAndResetTmHits() { + uint32_t value; + mutex->lockMutex(MutexIF::NO_TIMEOUT); + value = tmHits; + tmHits = 0; + mutex->unlockMutex(); + return value; +} + +uint32_t InternalErrorReporter::getTmHits() { + uint32_t value; + mutex->lockMutex(MutexIF::NO_TIMEOUT); + value = tmHits; + mutex->unlockMutex(); + return value; +} + +void InternalErrorReporter::incrementTmHits() { + mutex->lockMutex(MutexIF::NO_TIMEOUT); + tmHits++; + mutex->unlockMutex(); +} + +void InternalErrorReporter::storeFull() { + incrementStoreHits(); +} + +uint32_t InternalErrorReporter::getAndResetStoreHits() { + uint32_t value; + mutex->lockMutex(MutexIF::NO_TIMEOUT); + value = storeHits; + storeHits = 0; + mutex->unlockMutex(); + return value; +} + +uint32_t InternalErrorReporter::getStoreHits() { + uint32_t value; + mutex->lockMutex(MutexIF::NO_TIMEOUT); + value = storeHits; + mutex->unlockMutex(); + return value; +} + +void InternalErrorReporter::incrementStoreHits() { + mutex->lockMutex(MutexIF::NO_TIMEOUT); + storeHits++; + mutex->unlockMutex(); +} diff --git a/internalError/InternalErrorReporter.h b/internalError/InternalErrorReporter.h new file mode 100644 index 00000000..ed26350e --- /dev/null +++ b/internalError/InternalErrorReporter.h @@ -0,0 +1,51 @@ +#ifndef INTERNALERRORREPORTER_H_ +#define INTERNALERRORREPORTER_H_ + +#include "InternalErrorReporterIF.h" + +#include +#include +#include + +class InternalErrorReporter: public SystemObject, + public ExecutableObjectIF, + public InternalErrorReporterIF { +public: + InternalErrorReporter(object_id_t setObjectId, uint32_t queuePoolId, + uint32_t tmPoolId, uint32_t storePoolId); + virtual ~InternalErrorReporter(); + + virtual ReturnValue_t performOperation(uint8_t opCode); + + virtual void queueMessageNotSent(); + + virtual void lostTm(); + + virtual void storeFull(); + +protected: + MutexIF* mutex; + + uint32_t queuePoolId; + uint32_t tmPoolId; + uint32_t storePoolId; + + uint32_t queueHits; + uint32_t tmHits; + uint32_t storeHits; + + uint32_t getAndResetQueueHits(); + uint32_t getQueueHits(); + void incrementQueueHits(); + + uint32_t getAndResetTmHits(); + uint32_t getTmHits(); + void incrementTmHits(); + + uint32_t getAndResetStoreHits(); + uint32_t getStoreHits(); + void incrementStoreHits(); + +}; + +#endif /* INTERNALERRORREPORTER_H_ */ diff --git a/internalError/InternalErrorReporterIF.h b/internalError/InternalErrorReporterIF.h new file mode 100644 index 00000000..3484c18f --- /dev/null +++ b/internalError/InternalErrorReporterIF.h @@ -0,0 +1,27 @@ +#ifndef INTERNALERRORREPORTERIF_H_ +#define INTERNALERRORREPORTERIF_H_ + +class InternalErrorReporterIF { +public: + virtual ~InternalErrorReporterIF() { + } + + /** + * Thread safe + */ + virtual void queueMessageNotSent() = 0; + + /** + * Thread safe + */ + virtual void lostTm() = 0; + + /** + * Thread safe + */ + virtual void storeFull() = 0; + + +}; + +#endif /* INTERNALERRORREPORTERIF_H_ */ diff --git a/ipc/CommandMessage.cpp b/ipc/CommandMessage.cpp index cd0c82e1..fa41c653 100644 --- a/ipc/CommandMessage.cpp +++ b/ipc/CommandMessage.cpp @@ -13,7 +13,12 @@ #include #include #include -#include +#include + +namespace MESSAGE_TYPE { +void clearMissionMessage(CommandMessage* message); +} + CommandMessage::CommandMessage() { this->messageSize = COMMAND_MESSAGE_SIZE; @@ -62,35 +67,35 @@ void CommandMessage::setParameter2(uint32_t parameter2) { void CommandMessage::clearCommandMessage() { switch((getCommand()>>8) & 0xff){ - case MODE_COMMAND_MESSAGE_ID: + case MESSAGE_TYPE::MODE_COMMAND: ModeMessage::clear(this); break; - case HEALTH_COMMAND_MESSAGE_ID: + case MESSAGE_TYPE::HEALTH_COMMAND: HealthMessage::clear(this); break; - case MODE_SEQUENCE_MESSAGE_ID: + case MESSAGE_TYPE::MODE_SEQUENCE: ModeSequenceMessage::clear(this); break; - case FUNCTION_MESSAGE_ID: + case MESSAGE_TYPE::ACTION: ActionMessage::clear(this); break; - case DEVICE_HANDLER_COMMAND_MESSAGE_ID: + case MESSAGE_TYPE::DEVICE_HANDLER_COMMAND: DeviceHandlerMessage::clear(this); break; - case MEMORY_MESSAGE_ID: + case MESSAGE_TYPE::MEMORY: MemoryMessage::clear(this); break; - case PAYLOAD_HANDLER_MESSAGE_ID: - PayloadHandlerMessage::clear(this); - break; - case LIMIT_MESSAGE_ID: + case MESSAGE_TYPE::MONITORING: MonitoringMessage::clear(this); break; - case TM_STORE_MESSAGE_ID: + case MESSAGE_TYPE::TM_STORE: TmStoreMessage::clear(this); break; + case MESSAGE_TYPE::PARAMETER: + ParameterMessage::clear(this); + break; default: - setCommand(CMD_NONE); + MESSAGE_TYPE::clearMissionMessage(this); break; } } @@ -103,7 +108,9 @@ size_t CommandMessage::getMinimumMessageSize() const { return COMMAND_MESSAGE_SIZE; } -void CommandMessage::setToUnknownCommand(Command_t initialCommand) { +void CommandMessage::setToUnknownCommand() { + Command_t initialCommand = getCommand(); + clearCommandMessage(); setReplyRejected(UNKNOW_COMMAND, initialCommand); } diff --git a/ipc/CommandMessage.h b/ipc/CommandMessage.h index 3cee803a..2d966063 100644 --- a/ipc/CommandMessage.h +++ b/ipc/CommandMessage.h @@ -8,19 +8,9 @@ #ifndef COMMANDMESSAGE_H_ #define COMMANDMESSAGE_H_ -//Remember to add new Message Types to the clear function! -#define MODE_COMMAND_MESSAGE_ID 1 -#define HEALTH_COMMAND_MESSAGE_ID 2 -#define MODE_SEQUENCE_MESSAGE_ID 3 -#define FUNCTION_MESSAGE_ID 4 -#define TM_STORE_MESSAGE_ID 5 -#define TTC_TM_MESSAGE_ID 0x10 -#define DEVICE_HANDLER_COMMAND_MESSAGE_ID 0x44 -#define LIMIT_MESSAGE_ID 0x4C -#define MEMORY_MESSAGE_ID 0x4D -#define PAYLOAD_HANDLER_MESSAGE_ID 0x50 -#define PARAMETER_MESSAGE_ID 0x60 +#include +#include #include @@ -29,11 +19,11 @@ typedef ReturnValue_t Command_t; class CommandMessage : public MessageQueueMessage { public: - static const uint8_t INTERFACE_ID = COMMAND_MESSAGE; + static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_MESSAGE; static const ReturnValue_t UNKNOW_COMMAND = MAKE_RETURN_CODE(0x01); - static const uint8_t MESSAGE_ID = 0; + static const uint8_t MESSAGE_ID = MESSAGE_TYPE::COMMAND; static const Command_t CMD_NONE = MAKE_COMMAND_ID( 0 );//!< Used internally, will be ignored static const Command_t REPLY_COMMAND_OK = MAKE_COMMAND_ID( 3 ); static const Command_t REPLY_REJECTED = MAKE_COMMAND_ID( 0xD1 );//!< Reply indicating that the current command was rejected, par1 should contain the error code @@ -112,6 +102,10 @@ public: * Set the command to CMD_NONE and try to find * the correct class to handle a more detailed * clear. + * Also, calls a mission-specific clearMissionMessage + * function to separate between framework and mission + * messages. Not optimal, may be replaced by totally + * different auto-delete solution (e.g. smart pointers). * */ void clearCommandMessage(); @@ -128,7 +122,7 @@ public: * Sets the command to REPLY_REJECTED with parameter UNKNOWN_COMMAND. * Is needed quite often, so we better code it once only. */ - void setToUnknownCommand(Command_t initialCommand); + void setToUnknownCommand(); void setReplyRejected(ReturnValue_t reason, Command_t initialCommand = CMD_NONE); size_t getMinimumMessageSize() const; }; diff --git a/ipc/FwMessageTypes.h b/ipc/FwMessageTypes.h new file mode 100644 index 00000000..ec1c9aa2 --- /dev/null +++ b/ipc/FwMessageTypes.h @@ -0,0 +1,21 @@ +#ifndef FRAMEWORK_IPC_FWMESSAGETYPES_H_ +#define FRAMEWORK_IPC_FWMESSAGETYPES_H_ + +namespace MESSAGE_TYPE { +//Remember to add new Message Types to the clearCommandMessage function! +enum FW_MESSAGE_TYPE { + COMMAND = 0, + MODE_COMMAND, + HEALTH_COMMAND, + MODE_SEQUENCE, + ACTION, + TM_STORE, + DEVICE_HANDLER_COMMAND, + MONITORING, + MEMORY, + PARAMETER, + FW_MESSAGES_COUNT +}; +} + +#endif /* FRAMEWORK_IPC_FWMESSAGETYPES_H_ */ diff --git a/ipc/Makefile b/ipc/Makefile deleted file mode 100755 index f13a850c..00000000 --- a/ipc/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash -# -# OSAL makefile -# -# Created on: Mar 04, 2010 -# Author: ziemke -# Author: Claas Ziemke -# Copyright 2010, Claas Ziemke -# - -BASEDIR=../../ -include $(BASEDIR)options.mk - -OBJ = $(BUILDDIR)/OPUSMessageQueue.o - -all: $(OBJ) - -$(BUILDDIR)/%.o: %.cpp %.h - $(CPP) $(CFLAGS) $(DEFINES) $(CCOPT) ${INCLUDE} -c $< -o $@ - -clean: - $(RM) *.o *.gcno *.gcda diff --git a/ipc/MessageProxy.cpp b/ipc/MessageProxy.cpp deleted file mode 100644 index 5a5a6f12..00000000 --- a/ipc/MessageProxy.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * MessageProxy.cpp - * - * Created on: 18.03.2015 - * Author: baetz - */ - -#include - -MessageProxy::~MessageProxy() { - -} - -MessageQueueId_t MessageProxy::getReceiver() const { - return receiver; -} - -MessageQueueId_t MessageProxy::getCommandQueue() const { - return commandQueue.getId(); -} - -void MessageProxy::setReceiver(MessageQueueId_t configuredReceiver) { - this->receiver = configuredReceiver; -} - -MessageProxy::MessageProxy(size_t queueDepth, MessageQueueId_t setReceiver) : - receiver(setReceiver), currentRequest(0), commandQueue(queueDepth) { -} - -void MessageProxy::checkCommandQueue() { - CommandMessage message; - MessageQueueId_t senderId; - ReturnValue_t result = commandQueue.receiveMessage(&message, &senderId); - if (result != HasReturnvaluesIF::RETURN_OK) { - return; - } - if (senderId != receiver) { - //It's a command. - if (currentRequest == 0) { - result = commandQueue.sendMessage(receiver, &message); - if (result == HasReturnvaluesIF::RETURN_OK) { - currentRequest = senderId; - } - } else { - result = commandFifo.insert(message); - } - if (result != HasReturnvaluesIF::RETURN_OK) { - message.clear(); - CommandMessage reply; - reply.setReplyRejected(result, message.getCommand()); - commandQueue.reply(&reply); - } - } else { - //It's a reply. - if (currentRequest != 0) { - //Failed forwarding is ignored. - commandQueue.sendMessage(currentRequest, &message); - //This request is finished. - currentRequest = 0; - //Check if there's another request in FIFO: - result = commandFifo.retrieve(&message); - if (result != HasReturnvaluesIF::RETURN_OK) { - //Nothing in FIFO. - return; - } - currentRequest = message.getSender(); - result = commandQueue.sendMessage(receiver, &message); - if (result != HasReturnvaluesIF::RETURN_OK) { - message.clear(); - CommandMessage reply; - reply.setReplyRejected(result, message.getCommand()); - commandQueue.reply(&reply); - currentRequest = 0; - } - } else { - //We don't expect a reply. Ignore. - } - } -} - -void MessageProxy::flush() { - CommandMessage command; - CommandMessage reply; - if (currentRequest != 0) { - commandQueue.sendMessage(currentRequest, &reply); - currentRequest = 0; - } - for (ReturnValue_t result = commandQueue.receiveMessage(&command); - result == HasReturnvaluesIF::RETURN_OK; - result = commandQueue.receiveMessage(&command)) { - reply.setReplyRejected(FLUSHED, command.getCommand()); - commandQueue.reply(&reply); - command.clear(); - } - for (ReturnValue_t result = commandFifo.retrieve(&command); - result == HasReturnvaluesIF::RETURN_OK; - result = commandFifo.retrieve(&command)) { - reply.setReplyRejected(FLUSHED, command.getCommand()); - commandQueue.sendMessage(command.getSender(), &reply); - command.clear(); - } -} diff --git a/ipc/MessageProxy.h b/ipc/MessageProxy.h deleted file mode 100644 index 88cabd0b..00000000 --- a/ipc/MessageProxy.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * MessageProxy.h - * - * Created on: 18.03.2015 - * Author: baetz - */ - -#ifndef FRAMEWORK_IPC_MESSAGEPROXY_H_ -#define FRAMEWORK_IPC_MESSAGEPROXY_H_ - -#include -#include -#include -/** - * Simple "one message forwarding" proxy. - * Could be extended to forwarding to multiple recipients in parallel - * with a small forwarding map. - */ -class MessageProxy { -public: - MessageProxy(size_t queueDepth = DEFAULT_QUEUE_DEPTH, MessageQueueId_t setReceiver = 0); - virtual ~MessageProxy(); - MessageQueueId_t getCommandQueue() const; - MessageQueueId_t getReceiver() const; - void setReceiver(MessageQueueId_t configuredReceiver); - /** - * Checks the commandQueue for commands from other stuff or replies from the Receiver. - * There's the implicit assumption, that we get commands from anywhere, but replies only from the - * #configuredReceiver. - */ - void checkCommandQueue(); - void flush(); - static const uint8_t INTERFACE_ID = MESSAGE_PROXY; - static const ReturnValue_t FLUSHED = MAKE_RETURN_CODE(1); -private: - static const size_t DEFAULT_QUEUE_DEPTH = 5; - MessageQueueId_t receiver; - MessageQueueId_t currentRequest; - MessageQueue commandQueue; - FIFO commandFifo; //!< Required because there might be small bursts of commands coming in parallel. -}; - -#endif /* FRAMEWORK_IPC_MESSAGEPROXY_H_ */ diff --git a/ipc/MessageQueue.cpp b/ipc/MessageQueue.cpp deleted file mode 100644 index 40ed91cb..00000000 --- a/ipc/MessageQueue.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * MessageQueue.cpp - * - * Created on: Oct 2, 2012 - * Author: baetz - */ - -#include -#include -#include - - -MessageQueue::MessageQueue( size_t message_depth, size_t max_message_size ) : - id(0), lastPartner(0) { - Name_t name = ('Q' << 24) + (queueCounter++ << 8); - ReturnValue_t status = OSAL::createMessageQueue(name, message_depth, max_message_size, 0, &(this->id)); - if (status != RETURN_OK) { - error << "MessageQueue::MessageQueue: Creating Queue " << std::hex << name << std::dec << " failed with status:" << (uint32_t)status << std::endl; - this->id = 0; - } else { - //Creating the MQ was successful -// if (id == 0x220100f8) { -// debug << "Queue found! " << std::endl; -// } - } -} - -MessageQueue::~MessageQueue() { - OSAL::deleteMessageQueue(&this->id); -} - -ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, - - MessageQueueMessage* message) { - return this->MessageQueueSender::sendMessage(sendTo, message, this->getId() ); -} - -ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message) { - return this->MessageQueueSender::sendToDefault(message, this->getId() ); -} - -ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) { - if (this->lastPartner != 0) { - return this->MessageQueueSender::sendMessage( this->lastPartner, message, this->getId() ); - } else { - return OSAL::INCORRECT_STATE; - } -} - - -ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message, - MessageQueueId_t* receivedFrom) { - ReturnValue_t status = this->receiveMessage(message); - *receivedFrom = this->lastPartner; - return status; -} - -ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) { - ReturnValue_t status = OSAL::receiveMessage(this->id, message->getBuffer(), message->MAX_MESSAGE_SIZE, - &(message->messageSize), OSAL::NO_WAIT, 1); - if (status == RETURN_OK) { - this->lastPartner = message->getSender(); - //Check size of incoming message. - if ( message->messageSize < message->getMinimumMessageSize() ) { - status = 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); - } - return status; -} - -MessageQueueId_t MessageQueue::getLastPartner() { - return this->lastPartner; -} - -ReturnValue_t MessageQueue::flush(uint32_t* count) { - return OSAL::flushMessageQueue(this->id, count); -} - -MessageQueueId_t MessageQueue::getId() const { - return this->id; -} - -uint16_t MessageQueue::queueCounter = 0; diff --git a/ipc/MessageQueueIF.h b/ipc/MessageQueueIF.h new file mode 100644 index 00000000..f25fde22 --- /dev/null +++ b/ipc/MessageQueueIF.h @@ -0,0 +1,90 @@ +#ifndef FRAMEWORK_IPC_MESSAGEQUEUEIF_H_ +#define FRAMEWORK_IPC_MESSAGEQUEUEIF_H_ + +#include +#include +class MessageQueueIF { +public: + + static const MessageQueueId_t NO_QUEUE = MessageQueueSenderIF::NO_QUEUE; //!< Ugly hack. + + virtual ~MessageQueueIF() {} + /** + * @brief This operation sends a message to the last communication partner. + * @details This operation simplifies answering an incoming message by using the stored + * lastParnter information as destination. If there was no message received yet + * (i.e. lastPartner is zero), an error code is returned. + * @param message A pointer to a previously created message, which is sent. + */ + virtual ReturnValue_t reply( MessageQueueMessage* message ) = 0; + + /** + * @brief This function reads available messages from the message queue and returns the sender. + * @details It works identically to the other receiveMessage call, but in addition returns the + * sender's queue id. + * @param message A pointer to a message in which the received data is stored. + * @param receivedFrom A pointer to a queue id in which the sender's id is stored. + */ + virtual ReturnValue_t receiveMessage(MessageQueueMessage* message, + MessageQueueId_t *receivedFrom) = 0; + + /** + * @brief This function reads available messages from the message queue. + * @details If data is available it is stored in the passed message pointer. The message's + * original content is overwritten and the sendFrom information is stored in the + * lastPartner attribute. Else, the lastPartner information remains untouched, the + * message's content is cleared and the function returns immediately. + * @param message A pointer to a message in which the received data is stored. + */ + virtual ReturnValue_t receiveMessage(MessageQueueMessage* message) = 0; + /** + * Deletes all pending messages in the queue. + * @param count The number of flushed messages. + * @return RETURN_OK on success. + */ + virtual ReturnValue_t flush(uint32_t* count) = 0; + /** + * @brief This method returns the message queue id of the last communication partner. + */ + virtual MessageQueueId_t getLastPartner() const = 0; + /** + * @brief This method returns the message queue id of this class's message queue. + */ + virtual MessageQueueId_t getId() const = 0; + + /** + * \brief With the sendMessage call, a queue message is sent to a receiving queue. + * \details This method takes the message provided, adds the sentFrom information and passes + * it on to the destination provided with an operating system call. The OS's return + * value is returned. + * \param sendTo This parameter specifies the message queue id to send the message to. + * \param message This is a pointer to a previously created message, which is sent. + * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. + * This variable is set to zero by default. + * \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full (if implemented). + */ + virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ) = 0; + + /** + * \brief The sendToDefault method sends a queue message to the default destination. + * \details In all other aspects, it works identical to the sendMessage method. + * \param message This is a pointer to a previously created message, which is sent. + * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. + * This variable is set to zero by default. + */ + virtual ReturnValue_t sendToDefault( MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ) = 0; + /** + * \brief This method is a simple setter for the default destination. + */ + virtual void setDefaultDestination(MessageQueueId_t defaultDestination) = 0; + /** + * \brief This method is a simple getter for the default destination. + */ + virtual MessageQueueId_t getDefaultDestination() const = 0; + + virtual bool isDefaultDestinationSet() const = 0; +}; + + + +#endif /* FRAMEWORK_IPC_MESSAGEQUEUEIF_H_ */ diff --git a/ipc/MessageQueueMessage.cpp b/ipc/MessageQueueMessage.cpp index a0e45baa..2ff264d8 100644 --- a/ipc/MessageQueueMessage.cpp +++ b/ipc/MessageQueueMessage.cpp @@ -1,12 +1,8 @@ -/* - * MessageQueueMessage.cpp - * - * Created on: 22.11.2012 - * Author: baetz - */ #include #include +#include + MessageQueueMessage::MessageQueueMessage() : messageSize(this->HEADER_SIZE) { memset(this->internalBuffer, 0, sizeof(this->internalBuffer)); diff --git a/ipc/MessageQueueMessage.h b/ipc/MessageQueueMessage.h index 9f0c812f..8c4ec947 100644 --- a/ipc/MessageQueueMessage.h +++ b/ipc/MessageQueueMessage.h @@ -1,10 +1,9 @@ #ifndef MESSAGEQUEUEMESSAGE_H_ #define MESSAGEQUEUEMESSAGE_H_ -#include +#include +#include -class MessageQueue; -class MessageQueueSender; /** * \brief This class is the representation and data organizer for interprocess messages. * @@ -20,8 +19,6 @@ class MessageQueueSender; * \ingroup message_queue */ class MessageQueueMessage { - friend class MessageQueue; - friend class MessageQueueSender; public: /** * \brief This constant defines the maximum size of the data content, excluding the header. @@ -44,20 +41,6 @@ private: * \brief This is the internal buffer that contains the actual message data. */ uint8_t internalBuffer[MAX_MESSAGE_SIZE]; -protected: - /** - * \brief This method is used to set the sender's message queue id information prior to - * sending the message. - * \param setId The message queue id that identifies the sending message queue. - */ - void setSender(MessageQueueId_t setId); - /** - * \brief This helper function is used by the MessageQueue class to check the size of an - * incoming message. - * \details The method must be overwritten by child classes if size checks shall be more strict. - * @return The default implementation returns HEADER_SIZE. - */ - virtual size_t getMinimumMessageSize(); public: /** * \brief The size information of each message is stored in this attribute. @@ -117,6 +100,19 @@ public: * \brief This is a debug method that prints the content (till messageSize) to the debug output. */ void print(); + /** + * \brief This method is used to set the sender's message queue id information prior to + * sending the message. + * \param setId The message queue id that identifies the sending message queue. + */ + void setSender(MessageQueueId_t setId); + /** + * \brief This helper function is used by the MessageQueue class to check the size of an + * incoming message. + * \details The method must be overwritten by child classes if size checks shall be more strict. + * @return The default implementation returns HEADER_SIZE. + */ + virtual size_t getMinimumMessageSize(); }; #endif /* MESSAGEQUEUEMESSAGE_H_ */ diff --git a/ipc/MessageQueueSender.cpp b/ipc/MessageQueueSender.cpp deleted file mode 100644 index 854bf135..00000000 --- a/ipc/MessageQueueSender.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - * MessageQueueSender.cpp - * - * Created on: 22.11.2012 - * Author: baetz - */ - -#include -#include -#include - - -MessageQueueSender::MessageQueueSender(MessageQueueId_t set_default_destination) : - default_destination(set_default_destination) { - //Nothing to do in ctor. -} - -void MessageQueueSender::setDefaultDestination( - MessageQueueId_t defaultDestination) { - default_destination = defaultDestination; -} - -MessageQueueSender::~MessageQueueSender() { - //Nothing to do in dtor. -} - -ReturnValue_t MessageQueueSender::sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, MessageQueueId_t sentFrom) { - - message->setSender(sentFrom); - ReturnValue_t result = OSAL::sendMessage(sendTo, message->getBuffer(), - message->messageSize); - if (result != RETURN_OK) { - debug << "MessageQueueSender. Sending message from " << std::hex - << sentFrom << " to " << sendTo << " failed with " << result - << std::endl; - } - return result; -} - -ReturnValue_t MessageQueueSender::sendToDefault(MessageQueueMessage* message, - MessageQueueId_t sentFrom) { - message->setSender(sentFrom); - ReturnValue_t result = OSAL::sendMessage(this->default_destination, - message->getBuffer(), message->messageSize); - if (result != RETURN_OK) { - debug << "MessageQueueSender. Sending message from " << std::hex - << sentFrom << " to " << default_destination << " failed with " - << result << std::endl; - } - return result; -} - -MessageQueueId_t MessageQueueSender::getDefaultDestination() { - return this->default_destination; -} diff --git a/ipc/MessageQueueSender.h b/ipc/MessageQueueSender.h deleted file mode 100644 index 61a7ea55..00000000 --- a/ipc/MessageQueueSender.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef MESSAGEQUEUESENDER_H_ -#define MESSAGEQUEUESENDER_H_ - -#include -#include -#include -#include - -/** - * \defgroup message_queue Message Queues - * This group contains all Message Queue elements, but also the different message - * types sent over these queues. - */ -/** - * \brief This class manages sending of messages to receiving message queues. - * - * \details Message queues are a typical method of interprocess communication. - * They work like post boxes, where all incoming messages are stored in FIFO - * order. This class provides an interface to simplify sending messages to - * receiving queues without the necessity of owing a "post box" itself. It makes - * use of the underlying operating system's message queue features. - * \ingroup message_queue - */ -class MessageQueueSender : public HasReturnvaluesIF { -private: - /** - * \brief This attribute stores a default destination to send messages to. - * \details It is stored to simplify sending to always-the-same receiver. The attribute may - * be set in the constructor or by a setter call to setDefaultDestination. - */ - MessageQueueId_t default_destination; -public: - - static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::OBSW_1; - static const Event SEND_MSG_FAILED = MAKE_EVENT(0, SEVERITY::LOW); - static const MessageQueueId_t NO_QUEUE = 0; - /** - * \brief In the constructor of the class, the default destination may be set. - * \details As the MessageQueueSender class has no receiving queue by itself, no - * operating system call to create a message queue is required. - * \param set_default_destination With this parameter, the default destination is set. - * If no value is provided, it is set to zero. - */ - MessageQueueSender( MessageQueueId_t set_default_destination = NO_QUEUE ); - /** - * \brief As almost nothing is done in the constructor, there's nothing done in the destructor as well. - */ - virtual ~MessageQueueSender(); - /** - * \brief With the sendMessage call, a queue message is sent to a receiving queue. - * \details This method takes the message provided, adds the sentFrom information and passes - * it on to the destination provided with an operating system call. The OS's return - * value is returned. - * \param sendTo This parameter specifies the message queue id to send the message to. - * \param message This is a pointer to a previously created message, which is sent. - * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. - * This variable is set to zero by default. - */ - virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE ); - /** - * \brief The sendToDefault method sends a queue message to the default destination. - * \details In all other aspects, it works identical to the sendMessage method. - * \param message This is a pointer to a previously created message, which is sent. - * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. - * This variable is set to zero by default. - */ - virtual ReturnValue_t sendToDefault( MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE ); - /** - * \brief This method is a simple setter for the default destination. - */ - void setDefaultDestination(MessageQueueId_t defaultDestination); - /** - * \brief This method is a simple getter for the default destination. - */ - MessageQueueId_t getDefaultDestination(); -}; - - -#endif /* MESSAGEQUEUESENDER_H_ */ diff --git a/ipc/MessageQueueSenderIF.h b/ipc/MessageQueueSenderIF.h new file mode 100644 index 00000000..a52f06ce --- /dev/null +++ b/ipc/MessageQueueSenderIF.h @@ -0,0 +1,37 @@ +#ifndef FRAMEWORK_IPC_MESSAGEQUEUESENDERIF_H_ +#define FRAMEWORK_IPC_MESSAGEQUEUESENDERIF_H_ + +#include +class MessageQueueMessage; + + +//TODO: Actually, the definition of this ID to be a uint32_t is not ideal and breaks layering. +//However, it is difficult to keep layering, as the ID is stored in many places and sent around in +//MessageQueueMessage. +//Ideally, one would use the (current) object_id_t only, however, doing a lookup of queueIDs for every +//call does not sound ideal. +//In a first step, I'll circumvent the issue by not touching it, maybe in a second step. +//This also influences Interface design (getCommandQueue) and some other issues.. +typedef uint32_t MessageQueueId_t; + +class MessageQueueSenderIF { +public: + static const MessageQueueId_t NO_QUEUE = 0; + + virtual ~MessageQueueSenderIF() {} + + /** + * Allows sending messages without actually "owing" a message queue. + * Not sure whether this is actually a good idea. + * Must be implemented by a subclass. + */ + static ReturnValue_t sendMessage(MessageQueueId_t sendTo, + MessageQueueMessage* message, MessageQueueId_t sentFrom = + MessageQueueSenderIF::NO_QUEUE); +private: + MessageQueueSenderIF() {} +}; + + + +#endif /* FRAMEWORK_IPC_MESSAGEQUEUESENDERIF_H_ */ diff --git a/ipc/MutexFactory.h b/ipc/MutexFactory.h new file mode 100644 index 00000000..b2e58b6e --- /dev/null +++ b/ipc/MutexFactory.h @@ -0,0 +1,34 @@ +#ifndef FRAMEWORK_IPC_MUTEXFACTORY_H_ +#define FRAMEWORK_IPC_MUTEXFACTORY_H_ + +#include +/** + * Creates Mutex. + * This class is a "singleton" interface, i.e. it provides an + * interface, but also is the base class for a singleton. + */ +class MutexFactory { +public: + virtual ~MutexFactory(); + /** + * Returns the single instance of MutexFactory. + * The implementation of #instance is found in its subclasses. + * Thus, we choose link-time variability of the instance. + */ + static MutexFactory* instance(); + + MutexIF* createMutex(); + + void deleteMutex(MutexIF* mutex); + +private: + /** + * External instantiation is not allowed. + */ + MutexFactory(); + static MutexFactory* factoryInstance; +}; + + + +#endif /* FRAMEWORK_IPC_MUTEXFACTORY_H_ */ diff --git a/ipc/MutexIF.h b/ipc/MutexIF.h new file mode 100644 index 00000000..da7a7c52 --- /dev/null +++ b/ipc/MutexIF.h @@ -0,0 +1,16 @@ +#ifndef FRAMEWORK_IPC_MUTEXIF_H_ +#define FRAMEWORK_IPC_MUTEXIF_H_ + +#include + +class MutexIF { +public: + static const uint32_t NO_TIMEOUT; //!< Needs to be defined in implementation. + virtual ~MutexIF() {} + virtual ReturnValue_t lockMutex(uint32_t timeoutMs) = 0; + virtual ReturnValue_t unlockMutex() = 0; +}; + + + +#endif /* FRAMEWORK_IPC_MUTEXIF_H_ */ diff --git a/ipc/QueueFactory.h b/ipc/QueueFactory.h new file mode 100644 index 00000000..c385b15d --- /dev/null +++ b/ipc/QueueFactory.h @@ -0,0 +1,33 @@ +#ifndef FRAMEWORK_IPC_QUEUEFACTORY_H_ +#define FRAMEWORK_IPC_QUEUEFACTORY_H_ + +#include +#include +/** + * Creates message queues. + * This class is a "singleton" interface, i.e. it provides an + * interface, but also is the base class for a singleton. + */ +class QueueFactory { +public: + virtual ~QueueFactory(); + /** + * Returns the single instance of QueueFactory. + * The implementation of #instance is found in its subclasses. + * Thus, we choose link-time variability of the instance. + */ + static QueueFactory* instance(); + + MessageQueueIF* createMessageQueue(uint32_t message_depth = 3, + uint32_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE); + + void deleteMessageQueue(MessageQueueIF* queue); +private: + /** + * External instantiation is not allowed. + */ + QueueFactory(); + static QueueFactory* factoryInstance; +}; + +#endif /* FRAMEWORK_IPC_QUEUEFACTORY_H_ */ diff --git a/ipc/ReplyMessage.h b/ipc/ReplyMessage.h deleted file mode 100644 index 83c02f8b..00000000 --- a/ipc/ReplyMessage.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @file ReplyMessage.h - * @brief This file defines the ReplyMessage class. - * @date 20.06.2013 - * @author baetz - */ - -#ifndef REPLYMESSAGE_H_ -#define REPLYMESSAGE_H_ - -#include - -class ReplyMessage: public CommandMessage { -public: - static const uint8_t MESSAGE_ID = 1; - static const Command_t REPLY_MODE = MAKE_COMMAND_ID( 3 ); //!< Reply to a @c CMD_MODE or @c CMD_READ_MODE, getParameter contains a DeviceHandlerIF::DeviceHandlerMode_t, getParameter2 the submode - static const Command_t REPLY_TRANSITION_DELAY = MAKE_COMMAND_ID( 4 ); //!< Reply to a @c CMD_MODE, indicates that the transition will take some time, getParameter contains the maximum duration in ms - static const Command_t REPLY_INVALID_MODE = MAKE_COMMAND_ID( 5 ); //!< Reply to a @c CMD_MODE, indicates that the requested DeviceHandlerIF::DeviceHandlerMode_t was invalid - static const Command_t REPLY_CANT_REACH_MODE = MAKE_COMMAND_ID( 6 ); //!< Reply to a @c CMD_MODE, indicates that the requested DeviceHandlerIF::DeviceHandlerMode_t can not be reached from the current mode, getParameter() is the DeviceHandlerIF::DeviceHandlerMode_t, getParameter2() is the submode number - ReplyMessage() : - CommandMessage() { - } - ReplyMessage(Command_t command, uint32_t parameter1, uint32_t parameter2) : - CommandMessage(command, parameter1, parameter2) { - } - virtual ~ReplyMessage() {} -}; - -#endif /* REPLYMESSAGE_H_ */ diff --git a/memory/AcceptsMemoryMessagesIF.h b/memory/AcceptsMemoryMessagesIF.h index 22acab01..2b37f1af 100644 --- a/memory/AcceptsMemoryMessagesIF.h +++ b/memory/AcceptsMemoryMessagesIF.h @@ -8,9 +8,9 @@ #ifndef ACCEPTSMEMORYMESSAGESIF_H_ #define ACCEPTSMEMORYMESSAGESIF_H_ -#include #include #include +#include class AcceptsMemoryMessagesIF : public HasMemoryIF { public: diff --git a/memory/HasMemoryIF.h b/memory/HasMemoryIF.h index 2c80d4f5..cd6e6665 100644 --- a/memory/HasMemoryIF.h +++ b/memory/HasMemoryIF.h @@ -1,10 +1,3 @@ -/* - * HasMemoryIF.h - * - * Created on: 12.07.2013 - * Author: Bastian - */ - #ifndef HASMEMORYIF_H_ #define HASMEMORYIF_H_ @@ -12,7 +5,7 @@ class HasMemoryIF { public: - static const uint8_t INTERFACE_ID = HAS_MEMORY_IF; + static const uint8_t INTERFACE_ID = CLASS_ID::HAS_MEMORY_IF; static const ReturnValue_t DO_IT_MYSELF = MAKE_RETURN_CODE(1); static const ReturnValue_t POINTS_TO_VARIABLE = MAKE_RETURN_CODE(2); static const ReturnValue_t POINTS_TO_MEMORY = MAKE_RETURN_CODE(3); @@ -21,6 +14,7 @@ public: static const ReturnValue_t POINTS_TO_VECTOR_UINT16 = MAKE_RETURN_CODE(6); static const ReturnValue_t POINTS_TO_VECTOR_UINT32 = MAKE_RETURN_CODE(7); static const ReturnValue_t POINTS_TO_VECTOR_FLOAT = MAKE_RETURN_CODE(8); + static const ReturnValue_t DUMP_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA0); static const ReturnValue_t INVALID_SIZE = MAKE_RETURN_CODE(0xE0); static const ReturnValue_t INVALID_ADDRESS = MAKE_RETURN_CODE(0xE1); static const ReturnValue_t INVALID_CONTENT = MAKE_RETURN_CODE(0xE2); diff --git a/memory/LocalMemory.cpp b/memory/LocalMemory.cpp index 1cc3fcda..e82d3ea2 100644 --- a/memory/LocalMemory.cpp +++ b/memory/LocalMemory.cpp @@ -1,29 +1,31 @@ -/* - * LocalMemory.cpp - * - * Created on: 05.11.2013 - * Author: Bastian - */ - +#ifdef LEON #include +#endif + #include #include +#include LocalMemory::LocalMemory(object_id_t setObjectId) : - SystemObject(setObjectId), commandQueue(), memoryHelper(this, - &commandQueue) { + SystemObject(setObjectId), commandQueue(NULL), memoryHelper(this, + commandQueue) { + commandQueue = QueueFactory::instance()->createMessageQueue(); } -ReturnValue_t LocalMemory::performOperation() { +LocalMemory::~LocalMemory() { +QueueFactory::instance()->deleteMessageQueue(commandQueue); +} + +ReturnValue_t LocalMemory::performOperation(uint8_t opCode) { ReturnValue_t handleResult; CommandMessage message; - for (ReturnValue_t result = commandQueue.receiveMessage(&message); + for (ReturnValue_t result = commandQueue->receiveMessage(&message); result == HasReturnvaluesIF::RETURN_OK; - result = commandQueue.receiveMessage(&message)) { + result = commandQueue->receiveMessage(&message)) { handleResult = memoryHelper.handleMemoryCommand(&message); if (handleResult != HasReturnvaluesIF::RETURN_OK) { - message.setToUnknownCommand(message.getCommand()); - commandQueue.reply(&message); + message.setToUnknownCommand(); + commandQueue->reply(&message); } } return HasReturnvaluesIF::RETURN_OK; @@ -54,7 +56,7 @@ ReturnValue_t LocalMemory::initialize() { } MessageQueueId_t LocalMemory::getCommandQueue() const { - return commandQueue.getId(); + return commandQueue->getId(); } ReturnValue_t LocalMemory::checkWriteAccess(uint32_t address, uint32_t size) { @@ -66,14 +68,13 @@ ReturnValue_t LocalMemory::checkWriteAccess(uint32_t address, uint32_t size) { if ((size % 4) != 0) { return INVALID_SIZE; } - +#ifdef LEON if (address < 0x40000000) { HwProm prom(false); if (prom.getPromWriteEnabled() != HwProm::WRITE_ENABLED) { return WRITE_PROTECTED; } } - +#endif return HasReturnvaluesIF::RETURN_OK; } - diff --git a/memory/LocalMemory.h b/memory/LocalMemory.h index 695bb64f..07b30a1c 100644 --- a/memory/LocalMemory.h +++ b/memory/LocalMemory.h @@ -1,32 +1,29 @@ -/* - * LocalMemory.h - * - * Created on: 05.11.2013 - * Author: Bastian - */ - #ifndef LOCALMEMORY_H_ #define LOCALMEMORY_H_ -#include #include #include #include #include +#include #include -class LocalMemory : public AcceptsMemoryMessagesIF, public ExecutableObjectIF, public SystemObject { +class LocalMemory: public AcceptsMemoryMessagesIF, + public ExecutableObjectIF, + public SystemObject { private: - MessageQueue commandQueue; + MessageQueueIF* commandQueue; MemoryHelper memoryHelper; ReturnValue_t checkWriteAccess(uint32_t address, uint32_t size); public: - LocalMemory( object_id_t setObjectId ); - ReturnValue_t performOperation(); + LocalMemory(object_id_t setObjectId); + ~LocalMemory(); + ReturnValue_t performOperation(uint8_t opCode); ReturnValue_t initialize(); MessageQueueId_t getCommandQueue() const; - ReturnValue_t handleMemoryLoad(uint32_t address, const uint8_t* data, uint32_t size, uint8_t** dataPointer); - ReturnValue_t handleMemoryDump(uint32_t address, uint32_t size, uint8_t** dataPointer, uint8_t* dumpTarget); + ReturnValue_t handleMemoryLoad(uint32_t address, const uint8_t* data, + uint32_t size, uint8_t** dataPointer); + ReturnValue_t handleMemoryDump(uint32_t address, uint32_t size, + uint8_t** dataPointer, uint8_t* dumpTarget); }; - #endif /* LOCALMEMORY_H_ */ diff --git a/memory/MemoryHelper.cpp b/memory/MemoryHelper.cpp index e5a5b446..3dfd2b8b 100644 --- a/memory/MemoryHelper.cpp +++ b/memory/MemoryHelper.cpp @@ -1,25 +1,22 @@ -/* - * MemoryHelper.cpp - * - * Created on: 29.10.2013 - * Author: Bastian - */ - #include #include #include #include #include +#include -MemoryHelper::MemoryHelper(HasMemoryIF* workOnThis, MessageQueue* useThisQueue) : +MemoryHelper::MemoryHelper(HasMemoryIF* workOnThis, MessageQueueIF* useThisQueue) : workOnThis(workOnThis), queueToUse(useThisQueue), ipcStore(NULL), ipcAddress(), lastCommand( CommandMessage::CMD_NONE), lastSender(0), reservedSpaceInIPC( - NULL) { + NULL), busy(false) { } ReturnValue_t MemoryHelper::handleMemoryCommand(CommandMessage* message) { lastSender = message->getSender(); lastCommand = message->getCommand(); + if (busy) { + debug << "MemHelper: Busy!" << std::endl; + } switch (lastCommand) { case MemoryMessage::CMD_MEMORY_DUMP: handleMemoryCheckOrDump(message); @@ -47,8 +44,10 @@ ReturnValue_t MemoryHelper::initialize() { void MemoryHelper::completeLoad(ReturnValue_t errorCode, const uint8_t* dataToCopy, const uint32_t size, uint8_t* copyHere) { + busy = false; switch (errorCode) { case HasMemoryIF::DO_IT_MYSELF: + busy = true; return; case HasMemoryIF::POINTS_TO_MEMORY: memcpy(copyHere, dataToCopy, size); @@ -75,10 +74,12 @@ void MemoryHelper::completeLoad(ReturnValue_t errorCode, void MemoryHelper::completeDump(ReturnValue_t errorCode, const uint8_t* dataToCopy, const uint32_t size) { + busy = false; CommandMessage reply; MemoryMessage::setMemoryReplyFailed(&reply, errorCode, lastCommand); switch (errorCode) { case HasMemoryIF::DO_IT_MYSELF: + busy = true; return; case HasReturnvaluesIF::RETURN_OK: case HasMemoryIF::POINTS_TO_MEMORY: @@ -89,6 +90,7 @@ void MemoryHelper::completeDump(ReturnValue_t errorCode, } else { memcpy(reservedSpaceInIPC, dataToCopy, size); } + /* NO BREAK falls through*/ case HasMemoryIF::ACTIVITY_COMPLETED: switch (lastCommand) { case MemoryMessage::CMD_MEMORY_DUMP: { @@ -110,6 +112,13 @@ void MemoryHelper::completeDump(ReturnValue_t errorCode, break; } break; + case HasMemoryIF::DUMP_NOT_SUPPORTED: + if (lastCommand == MemoryMessage::CMD_MEMORY_CHECK){ + MemoryMessage::setMemoryCheckReply(&reply, 0); + MemoryMessage::setCrcReturnValue(&reply,HasMemoryIF::DUMP_NOT_SUPPORTED); + } + ipcStore->deleteData(ipcAddress); + break; default: //Reply is already set to REJECTED. ipcStore->deleteData(ipcAddress); diff --git a/memory/MemoryHelper.h b/memory/MemoryHelper.h index 7797ae98..d62774bf 100644 --- a/memory/MemoryHelper.h +++ b/memory/MemoryHelper.h @@ -1,33 +1,27 @@ -/* - * MemoryHelper.h - * - * Created on: 29.10.2013 - * Author: Bastian - */ - #ifndef MEMORYHELPER_H_ #define MEMORYHELPER_H_ #include -#include #include #include #include +#include class MemoryHelper : public HasReturnvaluesIF { public: - static const uint8_t INTERFACE_ID = MEMORY_HELPER; + static const uint8_t INTERFACE_ID = CLASS_ID::MEMORY_HELPER; static const ReturnValue_t UNKNOWN_CMD = MAKE_RETURN_CODE(0xE0); static const ReturnValue_t INVALID_ADDRESS = MAKE_RETURN_CODE(0xE1); static const ReturnValue_t INVALID_SIZE = MAKE_RETURN_CODE(0xE2); static const ReturnValue_t STATE_MISMATCH = MAKE_RETURN_CODE(0xE3); private: HasMemoryIF* workOnThis; - MessageQueue* queueToUse; + MessageQueueIF* queueToUse; StorageManagerIF* ipcStore; store_address_t ipcAddress; Command_t lastCommand; MessageQueueId_t lastSender; uint8_t* reservedSpaceInIPC; + bool busy; void handleMemoryLoad(CommandMessage* message); void handleMemoryCheckOrDump(CommandMessage* message); public: @@ -36,7 +30,7 @@ public: void completeDump( ReturnValue_t errorCode, const uint8_t* dataToCopy = NULL, const uint32_t size = 0); void swapMatrixCopy( uint8_t *out, const uint8_t *in, uint32_t totalSize, uint8_t datatypeSize); ReturnValue_t initialize(); - MemoryHelper( HasMemoryIF* workOnThis, MessageQueue* useThisQueue ); + MemoryHelper( HasMemoryIF* workOnThis, MessageQueueIF* useThisQueue ); ~MemoryHelper(); }; #endif /* MEMORYHELPER_H_ */ diff --git a/memory/MemoryListAdapter.h b/memory/MemoryListAdapter.h deleted file mode 100644 index 02ed47a7..00000000 --- a/memory/MemoryListAdapter.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * MemoryListAdapter.h - * - * Created on: 21.03.2014 - * Author: baetz - */ - -#ifndef MEMORYLISTADAPTER_H_ -#define MEMORYLISTADAPTER_H_ - -#include -#include - -template -class MemoryListAdapter : public SinglyLinkedList, public HasMemoryIF { -public: - MemoryListAdapter(typename LinkedElement::Iterator start) : SinglyLinkedList(start) { - } - MemoryListAdapter() : SinglyLinkedList() { - } - - ReturnValue_t handleMemoryLoad(uint32_t address, const uint8_t* data, uint32_t size, uint8_t** dataPointer) { - return handleMemoryLoad(SinglyLinkedList::start, address, data, size, dataPointer); - } - - static ReturnValue_t handleMemoryLoad(LinkedElement* element, uint32_t address, const uint8_t* data, uint32_t size, uint8_t** dataPointer) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; - while (!HasMemoryIF::memAccessWasSuccessful(result) && (element != NULL)) { - result = element->value->handleMemoryLoad(address, data, size, dataPointer); - element = element->getNext(); - } - return result; - } - - ReturnValue_t handleMemoryDump(uint32_t address, uint32_t size, uint8_t** dataPointer, uint8_t* dumpTarget ) { - return handleMemoryDump(SinglyLinkedList::start, address, size, dataPointer, dumpTarget); - } - static ReturnValue_t handleMemoryDump(LinkedElement* element, uint32_t address, uint32_t size, uint8_t** dataPointer, uint8_t* dumpTarget ) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; - while (!HasMemoryIF::memAccessWasSuccessful(result) && (element != NULL)) { - result = element->value->handleMemoryDump(address, size, dataPointer, dumpTarget); - element = element->getNext(); - } - return result; - } -}; - - -#endif /* MEMORYLISTADAPTER_H_ */ diff --git a/memory/MemoryMessage.cpp b/memory/MemoryMessage.cpp index a39d3615..c1116e08 100644 --- a/memory/MemoryMessage.cpp +++ b/memory/MemoryMessage.cpp @@ -1,11 +1,3 @@ -/* - * MemoryMessage.cpp - * - * Created on: 17.07.2013 - * Author: Bastian - */ - - #include #include MemoryMessage::MemoryMessage() { @@ -61,10 +53,11 @@ void MemoryMessage::clear(CommandMessage* message) { ipcStore->deleteData(getStoreID(message)); } } - /* NO BREAK*/ + /* NO BREAK falls through*/ case CMD_MEMORY_DUMP: case CMD_MEMORY_CHECK: case REPLY_MEMORY_CHECK: + case END_OF_MEMORY_COPY: message->setCommand(CommandMessage::CMD_NONE); message->setParameter(0); message->setParameter2(0); @@ -87,10 +80,18 @@ ReturnValue_t MemoryMessage::setMemoryCheckReply(CommandMessage* message, return HasReturnvaluesIF::RETURN_OK; } +void MemoryMessage::setCrcReturnValue(CommandMessage* message, ReturnValue_t returnValue){ + message->setParameter(returnValue<<16); +}; + uint16_t MemoryMessage::getCrc(const CommandMessage* message) { return (uint16_t)(message->getParameter()); } +ReturnValue_t MemoryMessage::getCrcReturnValue(const CommandMessage* message){ + return (message->getParameter()>>16); +} + Command_t MemoryMessage::getInitialCommand(const CommandMessage* message) { return message->getParameter2(); } @@ -102,3 +103,11 @@ ReturnValue_t MemoryMessage::setMemoryReplyFailed(CommandMessage* message, message->setParameter2(initialCommand); return HasReturnvaluesIF::RETURN_OK; } + +ReturnValue_t MemoryMessage::setMemoryCopyEnd(CommandMessage* message) { + message->setCommand(END_OF_MEMORY_COPY); + message->setParameter(0); + message->setParameter2(0); + return HasReturnvaluesIF::RETURN_OK; +} + diff --git a/memory/MemoryMessage.h b/memory/MemoryMessage.h index eb4e541d..124fad08 100644 --- a/memory/MemoryMessage.h +++ b/memory/MemoryMessage.h @@ -1,10 +1,3 @@ -/* - * MemoryMessage.h - * - * Created on: 17.07.2013 - * Author: Bastian - */ - #ifndef MEMORYMESSAGE_H_ #define MEMORYMESSAGE_H_ @@ -16,13 +9,14 @@ class MemoryMessage { private: MemoryMessage(); //A private ctor inhibits instantiation public: - static const uint8_t MESSAGE_ID = MEMORY_MESSAGE_ID; + static const uint8_t MESSAGE_ID = MESSAGE_TYPE::MEMORY; static const Command_t CMD_MEMORY_LOAD = MAKE_COMMAND_ID( 0x01 ); static const Command_t CMD_MEMORY_DUMP = MAKE_COMMAND_ID( 0x02 ); static const Command_t CMD_MEMORY_CHECK = MAKE_COMMAND_ID( 0x03 ); static const Command_t REPLY_MEMORY_DUMP = MAKE_COMMAND_ID( 0x10 ); static const Command_t REPLY_MEMORY_CHECK = MAKE_COMMAND_ID( 0x30 ); static const Command_t REPLY_MEMORY_FAILED = MAKE_COMMAND_ID( 0xE0 ); + static const Command_t END_OF_MEMORY_COPY = MAKE_COMMAND_ID(0xF0); static uint32_t getAddress( const CommandMessage* message ); static store_address_t getStoreID( const CommandMessage* message ); @@ -34,7 +28,10 @@ public: static ReturnValue_t setMemoryCheckCommand( CommandMessage* message, uint32_t address, uint32_t length ); static ReturnValue_t setMemoryCheckReply( CommandMessage* message, uint16_t crc ); static ReturnValue_t setMemoryReplyFailed( CommandMessage* message, ReturnValue_t errorCode, Command_t initialCommand ); + static ReturnValue_t setMemoryCopyEnd( CommandMessage* message); + static void setCrcReturnValue(CommandMessage*, ReturnValue_t returnValue); static uint16_t getCrc( const CommandMessage* message ); + static ReturnValue_t getCrcReturnValue(const CommandMessage* message); static Command_t getInitialCommand( const CommandMessage* message ); static void clear(CommandMessage* message); }; diff --git a/memory/MemoryProxyIF.h b/memory/MemoryProxyIF.h index 69db64b8..d325ba4e 100644 --- a/memory/MemoryProxyIF.h +++ b/memory/MemoryProxyIF.h @@ -1,10 +1,3 @@ -/* - * MemoryProxyIF.h - * - * Created on: 18.03.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_MEMORY_MEMORYPROXYIF_H_ #define FRAMEWORK_MEMORY_MEMORYPROXYIF_H_ diff --git a/modes/HasModesIF.h b/modes/HasModesIF.h index 4c9716f5..263b0a87 100644 --- a/modes/HasModesIF.h +++ b/modes/HasModesIF.h @@ -18,7 +18,7 @@ class HasModesIF { friend class ModeHelper; public: - static const uint8_t INTERFACE_ID = HAS_MODES_IF; + static const uint8_t INTERFACE_ID = CLASS_ID::HAS_MODES_IF; static const ReturnValue_t INVALID_MODE = MAKE_RETURN_CODE(0x01); static const ReturnValue_t TRANS_NOT_ALLOWED = MAKE_RETURN_CODE(0x02); static const ReturnValue_t IN_TRANSITION = MAKE_RETURN_CODE(0x03); @@ -40,8 +40,7 @@ public: virtual ~HasModesIF() { } virtual MessageQueueId_t getCommandQueue() const = 0; - virtual void getMode(Mode_t *mode, Submode_t *submode) { - } + virtual void getMode(Mode_t *mode, Submode_t *submode) = 0; protected: virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode) { diff --git a/modes/ModeHelper.cpp b/modes/ModeHelper.cpp index 2b4894b2..7b98bdc6 100644 --- a/modes/ModeHelper.cpp +++ b/modes/ModeHelper.cpp @@ -1,5 +1,6 @@ #include #include +#include ModeHelper::ModeHelper(HasModesIF *owner) : theOneWhoCommandedAMode(0), commandedMode(HasModesIF::MODE_OFF), commandedSubmode( @@ -18,7 +19,7 @@ ReturnValue_t ModeHelper::handleModeCommand(CommandMessage* message) { switch (message->getCommand()) { case ModeMessage::CMD_MODE_COMMAND_FORCED: forced = true; - /*NO BREAK*/ + /* NO BREAK falls through*/ case ModeMessage::CMD_MODE_COMMAND: { mode = ModeMessage::getMode(message); submode = ModeMessage::getSubmode(message); @@ -26,7 +27,7 @@ ReturnValue_t ModeHelper::handleModeCommand(CommandMessage* message) { ReturnValue_t result = owner->checkModeCommand(mode, submode, &timeout); if (result != HasReturnvaluesIF::RETURN_OK) { ModeMessage::cantReachMode(&reply, result); - sender.sendMessage(message->getSender(), &reply, + MessageQueueSenderIF::sendMessage(message->getSender(), &reply, owner->getCommandQueue()); break; } @@ -35,7 +36,7 @@ ReturnValue_t ModeHelper::handleModeCommand(CommandMessage* message) { commandedMode = mode; commandedSubmode = submode; - if ((parentQueueId != MessageQueueSender::NO_QUEUE) + if ((parentQueueId != MessageQueueSenderIF::NO_QUEUE) && (theOneWhoCommandedAMode != parentQueueId)) { owner->setToExternalControl(); } @@ -49,7 +50,7 @@ ReturnValue_t ModeHelper::handleModeCommand(CommandMessage* message) { owner->getMode(&mode, &submode); ModeMessage::setModeMessage(&reply, ModeMessage::REPLY_MODE_REPLY, mode, submode); - sender.sendMessage(message->getSender(), &reply, + MessageQueueSenderIF::sendMessage(message->getSender(), &reply, owner->getCommandQueue()); } break; @@ -73,7 +74,7 @@ ReturnValue_t ModeHelper::initialize(MessageQueueId_t parentQueueId) { void ModeHelper::modeChanged(Mode_t mode, Submode_t submode) { forced = false; CommandMessage reply; - if (theOneWhoCommandedAMode != MessageQueueSender::NO_QUEUE) { + if (theOneWhoCommandedAMode != MessageQueueSenderIF::NO_QUEUE) { if ((mode != commandedMode) || (submode != commandedSubmode)) { ModeMessage::setModeMessage(&reply, ModeMessage::REPLY_WRONG_MODE_REPLY, mode, submode); @@ -81,16 +82,16 @@ void ModeHelper::modeChanged(Mode_t mode, Submode_t submode) { ModeMessage::setModeMessage(&reply, ModeMessage::REPLY_MODE_REPLY, mode, submode); } - sender.sendMessage(theOneWhoCommandedAMode, &reply, + MessageQueueSenderIF::sendMessage(theOneWhoCommandedAMode, &reply, owner->getCommandQueue()); } if (theOneWhoCommandedAMode != parentQueueId - && parentQueueId != MessageQueueSender::NO_QUEUE) { + && parentQueueId != MessageQueueSenderIF::NO_QUEUE) { ModeMessage::setModeMessage(&reply, ModeMessage::REPLY_MODE_INFO, mode, submode); - sender.sendMessage(parentQueueId, &reply, owner->getCommandQueue()); + MessageQueueSenderIF::sendMessage(parentQueueId, &reply, owner->getCommandQueue()); } - theOneWhoCommandedAMode = MessageQueueSender::NO_QUEUE; + theOneWhoCommandedAMode = MessageQueueSenderIF::NO_QUEUE; } void ModeHelper::startTimer(uint32_t timeoutMs) { diff --git a/modes/ModeHelper.h b/modes/ModeHelper.h index 6cff1858..87f6d411 100644 --- a/modes/ModeHelper.h +++ b/modes/ModeHelper.h @@ -1,7 +1,6 @@ #ifndef MODEHELPER_H_ #define MODEHELPER_H_ -#include #include #include #include @@ -43,7 +42,6 @@ protected: MessageQueueId_t parentQueueId; Countdown countdown; - MessageQueueSender sender; bool forced; }; diff --git a/modes/ModeMessage.cpp b/modes/ModeMessage.cpp index fc0f3aca..62fea7e4 100644 --- a/modes/ModeMessage.cpp +++ b/modes/ModeMessage.cpp @@ -1,10 +1,3 @@ -/* - * ModeMessage.cpp - * - * Created on: 12.07.2013 - * Author: tod - */ - #include Mode_t ModeMessage::getMode(const CommandMessage* message) { diff --git a/modes/ModeMessage.h b/modes/ModeMessage.h index c2ebbf24..fad34726 100644 --- a/modes/ModeMessage.h +++ b/modes/ModeMessage.h @@ -17,13 +17,13 @@ class ModeMessage { private: ModeMessage(); public: - static const uint8_t MESSAGE_ID = MODE_COMMAND_MESSAGE_ID; + static const uint8_t MESSAGE_ID = MESSAGE_TYPE::MODE_COMMAND; static const Command_t CMD_MODE_COMMAND = MAKE_COMMAND_ID(0x01);//!> Command to set the specified Mode, replies are: REPLY_MODE_REPLY, REPLY_WRONG_MODE_REPLY, and REPLY_REJECTED; don't add any replies, as this will break the subsystem mode machine!! static const Command_t CMD_MODE_COMMAND_FORCED = MAKE_COMMAND_ID(0xF1);//!> Command to set the specified Mode, regardless of external control flag, replies are: REPLY_MODE_REPLY, REPLY_WRONG_MODE_REPLY, and REPLY_REJECTED; don't add any replies, as this will break the subsystem mode machine!! static const Command_t REPLY_MODE_REPLY = MAKE_COMMAND_ID(0x02);//!> Reply to a CMD_MODE_COMMAND or CMD_MODE_READ static const Command_t REPLY_MODE_INFO = MAKE_COMMAND_ID(0x03); //!> Unrequested info about the current mode (used for composites to inform their container of a changed mode) static const Command_t REPLY_CANT_REACH_MODE = MAKE_COMMAND_ID(0x04); //!> Reply in case a mode command can't be executed. Par1: returnCode, Par2: 0 - //TODO is there a way we can transmit a returnvalue when responding that the mode is wrong, so we can give a nice failure code when commanded by PUS? + //SHOULDDO is there a way we can transmit a returnvalue when responding that the mode is wrong, so we can give a nice failure code when commanded by PUS? static const Command_t REPLY_WRONG_MODE_REPLY = MAKE_COMMAND_ID(0x05);//!> Reply to a CMD_MODE_COMMAND, indicating that a mode was commanded and a transition started but was aborted; the parameters contain the mode that was reached static const Command_t CMD_MODE_READ = MAKE_COMMAND_ID(0x06);//!> Command to read the current mode and reply with a REPLY_MODE_REPLY static const Command_t CMD_MODE_ANNOUNCE = MAKE_COMMAND_ID(0x07);//!> Command to trigger an ModeInfo Event. This command does NOT have a reply. diff --git a/monitoring/AbsLimitMonitor.h b/monitoring/AbsLimitMonitor.h index 88bdcaac..3525ba2c 100644 --- a/monitoring/AbsLimitMonitor.h +++ b/monitoring/AbsLimitMonitor.h @@ -1,4 +1,3 @@ - #ifndef FRAMEWORK_MONITORING_ABSLIMITMONITOR_H_ #define FRAMEWORK_MONITORING_ABSLIMITMONITOR_H_ @@ -15,14 +14,13 @@ public: virtual ~AbsLimitMonitor() { } virtual ReturnValue_t checkSample(T sample, T* crossedLimit) { + *crossedLimit = limit; if (aboveIsViolation) { if ((std::abs(sample) > limit)) { - *crossedLimit = limit; return MonitoringIF::OUT_OF_RANGE; } } else { if ((std::abs(sample) < limit)) { - *crossedLimit = limit; return MonitoringIF::OUT_OF_RANGE; } } diff --git a/monitoring/DeltaCheckMonitor.h b/monitoring/DeltaCheckMonitor.h deleted file mode 100644 index 34f2f338..00000000 --- a/monitoring/DeltaCheckMonitor.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * DeltaCheckMonitor.h - * - * Created on: 21.07.2014 - * Author: baetz - */ - -#ifndef DELTACHECKMONITOR_H_ -#define DELTACHECKMONITOR_H_ - -#include -#include -#include -#include -#include -#include -#include - - - -//TODO: Lots of old, unfixed stuff. Do not use! -template -class DeltaCheckMonitor: public MonitoringIF { -public: - DeltaCheckMonitor(HasMonitorsIF* owner, uint32_t poolId, - T initialMinDelta, T initialMaxDelta, uint8_t arrayPos = 0, - uint8_t initialStrategy = REPORT_ALL, Event eventToTrigger = 0) : - owner(owner), parameter(poolId, NULL, arrayPos), oldValue( - 0), comparisonValueValid(false), minDelta(initialMinDelta), maxDelta( - initialMaxDelta), reportingStrategy(initialStrategy), checkingState( - CHECKING_STATUS_OK), event(eventToTrigger) { - initialMinDelta.setNext(&initialMaxDelta); - } - virtual ~DeltaCheckMonitor() { - - } - ReturnValue_t check() { - DataSet mySet; - mySet.registerVariable(¶meter); - mySet.read(); - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - uint8_t oldState = 0; - if (!parameter.isValid()) { - checkingState = CHECKING_STATUS_INVALID; - comparisonValueValid = false; - result = PARAMETER_INVALID; - } else { - if (!comparisonValueValid) { - oldValue = parameter; - comparisonValueValid = true; - return FIRST_SAMPLE; - } - oldState = checkingState; - if ((parameter.value - oldValue) > maxDelta.entry) { - checkingState = CHECKING_STATUS_ABOVE_HIGH_THRESHOLD; - result = HIGH_LIMIT; - } else if ((parameter.value - oldValue) < minDelta.entry) { - checkingState = CHECKING_STATUS_BELOW_LOW_THRESHOLD; - result = LOW_LIMIT; - } else { - checkingState = CHECKING_STATUS_OK; - } - if (oldState != checkingState) { - reportViolation(oldState); - } - } - if (reportingStrategy == REPORT_NONE) { - checkingState = CHECKING_STATUS_UNSELECTED; - } - return result; - } - ReturnValue_t setLimits(uint8_t type, const uint8_t* data, uint32_t size) { - if (type != getLimitType()) { - return WRONG_TYPE; - } - UpdateLimitMonitorContent content; - int32_t tempSize = size; - const uint8_t* pBuffer = data; - ReturnValue_t result = content.deSerialize(&pBuffer, &tempSize, true); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - minDelta = content.lowValue.entry; - maxDelta = content.highValue.entry; - return HasReturnvaluesIF::RETURN_OK; - } - ReturnValue_t setChecking(uint8_t strategy) { - reportingStrategy = strategy; - return HasReturnvaluesIF::RETURN_OK; - } - uint32_t getPID() { - return parameter.getParameterId(); - } - const uint8_t getLimitType() const { - return LIMIT_TYPE_DELTA_CHECK; - } -private: - HasMonitorsIF* owner; - PIDReader parameter; - T oldValue; - bool comparisonValueValid; - SerializeElement minDelta; - SerializeElement maxDelta; - uint8_t reportingStrategy; - uint8_t checkingState; - EventId_t event; - void reportViolation(uint8_t oldState) { - if ((reportingStrategy & REPORT_REPORTS_ONLY) != 0) { - if (checkingState == CHECKING_STATUS_ABOVE_HIGH_THRESHOLD) { - MonitoringReportContent report(parameter.getParameterId(), - parameter.value, maxDelta.entry, oldState, - checkingState); - LimitViolationReporter::sendLimitViolationReport(&report); - } else { - MonitoringReportContent report(parameter.getParameterId(), - parameter.value, minDelta.entry, oldState, - checkingState); - LimitViolationReporter::sendLimitViolationReport(&report); - }; - } - if ((this->reportingStrategy & REPORT_EVENTS_ONLY) != 0) { - if (checkingState == CHECKING_STATUS_ABOVE_HIGH_THRESHOLD || checkingState == CHECKING_STATUS_BELOW_LOW_THRESHOLD) { - owner->forwardEvent(event, (oldState << 8) + checkingState); - } - } - } -}; - -#endif /* DELTACHECKMONITOR_H_ */ diff --git a/monitoring/HasMonitorsIF.h b/monitoring/HasMonitorsIF.h index d6d39d86..6f1dc1b3 100644 --- a/monitoring/HasMonitorsIF.h +++ b/monitoring/HasMonitorsIF.h @@ -8,8 +8,8 @@ #define HASMONITORSIF_H_ #include -#include #include +#include class HasMonitorsIF { public: diff --git a/monitoring/LimitCheckMonitor.h b/monitoring/LimitCheckMonitor.h deleted file mode 100644 index 1ab78b87..00000000 --- a/monitoring/LimitCheckMonitor.h +++ /dev/null @@ -1,271 +0,0 @@ -/* - * LimitCheckMonitor.h - * - * Created on: 21.07.2014 - * Author: baetz - */ - -#ifndef LIMITCHECKMONITOR_H_ -#define LIMITCHECKMONITOR_H_ - -#include -#include -#include -#include -#include -#include -#include -#include - -template -class LimitCheckMonitor: public MonitoringIF { -public: - struct CheckParameters { - - CheckParameters() : - oldState(HasReturnvaluesIF::RETURN_OK), parameterId( - PoolVariableIF::NO_PARAMETER), sendTransitionreport( - false), sendTransitionEvent(false), lowerTransitionEvent( - 0), upperTransitionEvent(0), reportingObject(0), currentCounter( - 0), maxCounter(0) { - } - - CheckParameters(ReturnValue_t oldState, const uint32_t parameterId, - bool sendTransitionreport, bool sendTransitionEvent, - Event lowerTransitionEvent, Event upperTransitionEvent, - const object_id_t reportingObject, uint16_t maxCounter = 0) : - oldState(oldState), parameterId(parameterId), sendTransitionreport( - sendTransitionreport), sendTransitionEvent( - sendTransitionEvent), lowerTransitionEvent( - lowerTransitionEvent), upperTransitionEvent( - upperTransitionEvent), reportingObject(reportingObject), currentCounter( - 0), maxCounter(maxCounter) { - } - - ReturnValue_t oldState; - const uint32_t parameterId; - bool sendTransitionreport; - bool sendTransitionEvent; - Event lowerTransitionEvent; - Event upperTransitionEvent; - const object_id_t reportingObject; - uint16_t currentCounter; - uint16_t maxCounter; - }; - - LimitCheckMonitor(object_id_t reportAs, uint32_t parameterId, - T initialLower, T initialUpper, bool generateReports = true, - bool throwEvents = false, Event lowerTransitionEvent = 0, - Event upperTransitionEvent = 0, uint16_t confirmationNumber = 0) : - lowerLimit(initialLower), upperLimit(initialUpper), parameters( - UNCHECKED, parameterId, generateReports, throwEvents, - lowerTransitionEvent, upperTransitionEvent, reportAs, - confirmationNumber) { - lowerLimit.setNext(&upperLimit); - } - - virtual ~LimitCheckMonitor() { - } - - virtual ReturnValue_t check() { - DataSet mySet; - PIDReader parameter(parameters.parameterId, &mySet); - mySet.read(); - if (!parameter.isValid()) { - if (parameters.oldState != INVALID) { - MonitoringReportContent report(parameter.getParameterId(), 0, - 0, parameters.oldState, INVALID); - LimitViolationReporter::sendLimitViolationReport(&report); - parameters.oldState = INVALID; - } - } else { - parameters.oldState = doCheck(parameter.value, lowerLimit, - upperLimit, ¶meters); - } - return parameters.oldState; - } - - static ReturnValue_t doCheck(T value, T lowerLimit, T upperLimit, - CheckParameters* checkParameters, ReturnValue_t lowerReturnCode = - BELOW_LOW_LIMIT, ReturnValue_t upperReturnCode = - ABOVE_HIGH_LIMIT) { - return doCheck(value, lowerLimit, upperLimit, checkParameters->oldState, - checkParameters->parameterId, - checkParameters->sendTransitionreport, - checkParameters->sendTransitionEvent, - checkParameters->lowerTransitionEvent, - checkParameters->upperTransitionEvent, - checkParameters->reportingObject, - &checkParameters->currentCounter, checkParameters->maxCounter, - lowerReturnCode, upperReturnCode); - } - - static ReturnValue_t doCheck(T value, T lowerLimit, T upperLimit, - ReturnValue_t oldState, uint32_t parameterId, - bool sendTransitionreport, bool sendTransitionEvent, - Event lowerTransitionEvent, Event upperTransitionEvent, - object_id_t reportingObject, uint16_t *currentCounter = NULL, - uint16_t maxCounter = 0, ReturnValue_t lowerReturnCode = - BELOW_LOW_LIMIT, ReturnValue_t upperReturnCode = - ABOVE_HIGH_LIMIT) { - uint16_t tempCounter = 0; - if (currentCounter == NULL) { - currentCounter = &tempCounter; - maxCounter = 0; - } - - ReturnValue_t currentState = HasReturnvaluesIF::RETURN_OK; - T crossedLimit = 0; - if (value > upperLimit) { - currentState = upperReturnCode; - crossedLimit = upperLimit; - } else if (value < lowerLimit) { - currentState = lowerReturnCode; - crossedLimit = lowerLimit; - } - - if (oldState != currentState) { - //confirmation - *currentCounter += 1; - if (*currentCounter > maxCounter || oldState == UNCHECKED) { - *currentCounter = 0; - // Distinction of 3 cases: up/down/(ok or default) - if (currentState == upperReturnCode) { - if (sendTransitionEvent) { - EventManagerIF::triggerEvent(reportingObject, - upperTransitionEvent, 0, - 0); - } - } else if (currentState == lowerReturnCode) { - if (sendTransitionEvent) { - EventManagerIF::triggerEvent(reportingObject, - lowerTransitionEvent, 0, - 0); - } - } else { - // RETURN_OK or all other cases - if (oldState == lowerReturnCode) { - crossedLimit = lowerLimit; - } else { - crossedLimit = upperLimit; - } - } - - if (sendTransitionreport) { - MonitoringReportContent report(parameterId, value, - crossedLimit, oldState, currentState); - LimitViolationReporter::sendLimitViolationReport(&report); - } else { - currentState = UNSELECTED; - } - } else { - currentState = oldState; - } - } else { - *currentCounter = 0; - } - return currentState; - } - - ReturnValue_t setLimits(uint8_t type, const uint8_t* data, uint32_t size) { - if (type != getLimitType()) { - return WRONG_TYPE; - } - - UpdateLimitMonitorContent content; - - if (size != content.getSerializedSize()) { - return INVALID_SIZE; - } - - int32_t tempSize = size; - const uint8_t* pBuffer = data; - ReturnValue_t result = content.deSerialize(&pBuffer, &tempSize, true); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - setLimits(content.lowValue, content.highValue); - return HasReturnvaluesIF::RETURN_OK; - } - - void setLimits(T lower, T upper) { - lowerLimit = lower; - upperLimit = upper; - } - - ReturnValue_t setChecking(uint8_t strategy) { - if ((strategy & REPORT_EVENTS_ONLY) != 0) { - parameters.sendTransitionEvent = true; - } else { - parameters.sendTransitionEvent = false; - } - if ((strategy & REPORT_REPORTS_ONLY) != 0) { - parameters.sendTransitionreport = true; - } else { - parameters.sendTransitionreport = false; - } - return HasReturnvaluesIF::RETURN_OK; - } - - ReturnValue_t setToUnchecked() { - return setToState(UNCHECKED, ¶meters); - } - - static ReturnValue_t setToUnchecked(CheckParameters* parameters) { - if (parameters->oldState != UNCHECKED) { - MonitoringReportContent report(parameters->parameterId, 0, 0, - parameters->oldState, UNCHECKED); - LimitViolationReporter::sendLimitViolationReport(&report); - parameters->oldState = UNCHECKED; - } - return HasReturnvaluesIF::RETURN_OK; - } - - static ReturnValue_t setToState(ReturnValue_t newState, CheckParameters* parameters) { - if (parameters->oldState != newState) { - MonitoringReportContent report(parameters->parameterId, 0, 0, - parameters->oldState, newState); - LimitViolationReporter::sendLimitViolationReport(&report); - parameters->oldState = newState; - } - return HasReturnvaluesIF::RETURN_OK; - } - - ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { - return SerialLinkedListAdapter::serialize(&lowerLimit, - buffer, size, max_size, bigEndian); - } - - uint32_t getSerializedSize() const { - return SerialLinkedListAdapter::getSerializedSize( - &lowerLimit); - } - - ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { - return SerialLinkedListAdapter::deSerialize(&lowerLimit, - buffer, size, bigEndian); - } - const uint8_t getLimitType() const { - return LIMIT_TYPE_LIMIT_CHECK; - } - const uint32_t getLimitId() const { - return parameters.parameterId; - } - T getLowerLimit() { - return lowerLimit; - } - T getUpperLimit() { - return upperLimit; - } -private: - SerializeElement lowerLimit; - SerializeElement upperLimit; - CheckParameters parameters; -}; - -//TODO: This is for float only, as this is currently the only need. -typedef LinkedElementDecorator, MonitoringIF> LinkedLimitMonitor; - -#endif /* LIMITCHECKMONITOR_H_ */ diff --git a/monitoring/LimitMonitor.h b/monitoring/LimitMonitor.h index e64a7937..45abe48b 100644 --- a/monitoring/LimitMonitor.h +++ b/monitoring/LimitMonitor.h @@ -1,4 +1,3 @@ - #ifndef FRAMEWORK_MONITORING_LIMITMONITOR_H_ #define FRAMEWORK_MONITORING_LIMITMONITOR_H_ @@ -24,6 +23,7 @@ public: virtual ~LimitMonitor() { } virtual ReturnValue_t checkSample(T sample, T* crossedLimit) { + *crossedLimit = 0.0; if (sample > upperLimit) { *crossedLimit = upperLimit; return MonitoringIF::ABOVE_HIGH_LIMIT; @@ -49,7 +49,7 @@ public: parameterWrapper->set(this->lowerLimit); break; case 11: - parameterWrapper->set(this->lowerLimit); + parameterWrapper->set(this->upperLimit); break; default: return this->INVALID_MATRIX_ID; @@ -63,6 +63,15 @@ public: return false; } } + + T getLowerLimit() const { + return lowerLimit; + } + + T getUpperLimit() const { + return upperLimit; + } + protected: void sendTransitionEvent(T currentValue, ReturnValue_t state) { switch (state) { diff --git a/monitoring/LimitViolationReporter.cpp b/monitoring/LimitViolationReporter.cpp index d2dc6845..760e8b93 100644 --- a/monitoring/LimitViolationReporter.cpp +++ b/monitoring/LimitViolationReporter.cpp @@ -33,17 +33,17 @@ ReturnValue_t LimitViolationReporter::sendLimitViolationReport(const SerializeIF } CommandMessage report; MonitoringMessage::setLimitViolationReport(&report, storeId); - return reportQueue.sendToDefault(&report); + return MessageQueueSenderIF::sendMessage(reportQueue, &report); } ReturnValue_t LimitViolationReporter::checkClassLoaded() { - if (reportQueue.getDefaultDestination() == 0) { + if (reportQueue == 0) { ReceivesMonitoringReportsIF* receiver = objectManager->get< - ReceivesMonitoringReportsIF>(objects::PUS_MONITORING_SERVICE); + ReceivesMonitoringReportsIF>(reportingTarget); if (receiver == NULL) { return ObjectManagerIF::NOT_FOUND; } - reportQueue.setDefaultDestination(receiver->getCommandQueue()); + reportQueue = receiver->getCommandQueue(); } if (ipcStore == NULL) { ipcStore = objectManager->get(objects::IPC_STORE); @@ -55,5 +55,6 @@ ReturnValue_t LimitViolationReporter::checkClassLoaded() { } //Lazy initialization. -MessageQueueSender LimitViolationReporter::reportQueue; +MessageQueueId_t LimitViolationReporter::reportQueue = 0; StorageManagerIF* LimitViolationReporter::ipcStore = NULL; +object_id_t LimitViolationReporter::reportingTarget = 0; diff --git a/monitoring/LimitViolationReporter.h b/monitoring/LimitViolationReporter.h index 43d0865c..3a9d04dd 100644 --- a/monitoring/LimitViolationReporter.h +++ b/monitoring/LimitViolationReporter.h @@ -7,16 +7,22 @@ #ifndef LIMITVIOLATIONREPORTER_H_ #define LIMITVIOLATIONREPORTER_H_ -#include #include #include #include +#include + +namespace Factory{ +void setStaticFrameworkObjectIds(); +} class LimitViolationReporter { + friend void (Factory::setStaticFrameworkObjectIds)(); public: static ReturnValue_t sendLimitViolationReport(const SerializeIF* data); private: - static MessageQueueSender reportQueue; + static object_id_t reportingTarget; + static MessageQueueId_t reportQueue; static StorageManagerIF* ipcStore; static ReturnValue_t checkClassLoaded(); LimitViolationReporter(); diff --git a/monitoring/MonitorBase.h b/monitoring/MonitorBase.h index 0bbcbf67..79622645 100644 --- a/monitoring/MonitorBase.h +++ b/monitoring/MonitorBase.h @@ -1,10 +1,3 @@ -/* - * MonitorBase.h - * - * Created on: 25.07.2014 - * Author: baetz - */ - #ifndef MONITORBASE_H_ #define MONITORBASE_H_ @@ -38,7 +31,7 @@ public: //2. If returning from fetch != OK, parameter is invalid. Report (if oldState is != invalidity). if (validity != HasReturnvaluesIF::RETURN_OK) { - monitorStateIs(validity, sample, 0); + this->monitorStateIs(validity, sample, 0); //3. Otherwise, check sample. } else { this->oldState = doCheck(sample); @@ -46,7 +39,7 @@ public: return this->oldState; } virtual ReturnValue_t doCheck(T sample) { - T crossedLimit; + T crossedLimit = 0.0; ReturnValue_t currentState = checkSample(sample, &crossedLimit); return this->monitorStateIs(currentState,sample, crossedLimit); } diff --git a/monitoring/MonitorReporter.h b/monitoring/MonitorReporter.h index d0abc623..6274313f 100644 --- a/monitoring/MonitorReporter.h +++ b/monitoring/MonitorReporter.h @@ -1,4 +1,3 @@ - #ifndef FRAMEWORK_MONITORING_MONITORREPORTER_H_ #define FRAMEWORK_MONITORING_MONITORREPORTER_H_ @@ -12,10 +11,13 @@ template class MonitorReporter: public HasParametersIF { public: + static const uint8_t ENABLED = 1; + static const uint8_t DISABLED = 0; + MonitorReporter(object_id_t reportingId, uint8_t monitorId, uint32_t parameterId, uint16_t confirmationLimit) : monitorId(monitorId), parameterId(parameterId), reportingId( reportingId), oldState(MonitoringIF::UNCHECKED), reportingEnabled( - true), eventEnabled(true), currentCounter(0), confirmationLimit( + ENABLED), eventEnabled(ENABLED), currentCounter(0), confirmationLimit( confirmationLimit) { } @@ -26,12 +28,13 @@ public: T crossedLimit = 0) { if (state != oldState) { if (isConfirmed(state)) { - if (this->eventEnabled) { + if (eventEnabled == ENABLED) { sendTransitionEvent(parameterValue, state); } - if (this->reportingEnabled) { + if (reportingEnabled == ENABLED) { sendTransitionReport(parameterValue, crossedLimit, state); } + oldState = state; } else { //This is to ensure confirmation works. //Needs to be reset to be able to confirm against oldState again next time. @@ -50,13 +53,13 @@ public: return INVALID_DOMAIN_ID; } switch (parameterId) { - case 1: + case 0: parameterWrapper->set(this->confirmationLimit); break; - case 2: + case 1: parameterWrapper->set(this->reportingEnabled); break; - case 3: + case 2: parameterWrapper->set(this->eventEnabled); break; default: @@ -73,15 +76,28 @@ public: object_id_t getReporterId() const { return reportingId; } + + void setEventEnabled(uint8_t eventEnabled) { + this->eventEnabled = eventEnabled; + } + + void setReportingEnabled(uint8_t reportingEnabled) { + this->reportingEnabled = reportingEnabled; + } + + bool isEventEnabled() const { + return (eventEnabled == ENABLED); + } + protected: const uint8_t monitorId; const uint32_t parameterId; object_id_t reportingId; ReturnValue_t oldState; - bool reportingEnabled; + uint8_t reportingEnabled; - bool eventEnabled; + uint8_t eventEnabled; uint16_t currentCounter; uint16_t confirmationLimit; @@ -149,8 +165,8 @@ protected: LimitViolationReporter::sendLimitViolationReport(&report); } ReturnValue_t setToState(ReturnValue_t state) { - if (oldState != state) { - MonitoringReportContent report(parameterId, 0, 0, oldState, + if (oldState != state && reportingEnabled) { + MonitoringReportContent report(parameterId, 0, 0, oldState, state); LimitViolationReporter::sendLimitViolationReport(&report); oldState = state; diff --git a/monitoring/MonitoringHelper.cpp b/monitoring/MonitoringHelper.cpp deleted file mode 100644 index 2e96756f..00000000 --- a/monitoring/MonitoringHelper.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* - * MonitoringHelper.cpp - * - * Created on: 07.07.2014 - * Author: baetz - */ - -#include -#include -#include -#include -#include -#include - -MonitoringHelper::MonitoringHelper(HasMonitorsIF* limitOwner) : - owner(limitOwner), ipcStore(NULL) { -} - -MonitoringHelper::~MonitoringHelper() { - -} - -ReturnValue_t MonitoringHelper::handleMessage(CommandMessage* message) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; - switch (message->getCommand()) { - case MonitoringMessage::CHANGE_REPORTING_STRATEGY: - result = handleReportingStrategyMessage(MonitoringMessage::getReportingStategy(message), - MonitoringMessage::getStoreId(message)); - break; - case MonitoringMessage::UPDATE_PARAMETER_MONITOR: - result = handleUpdateParameterMonitor(MonitoringMessage::getStoreId(message)); - break; - case MonitoringMessage::UPDATE_OBJECT_MONITOR: - result = handleUpdateObjectMonitor(MonitoringMessage::getStoreId(message)); - break; - default: - return HasReturnvaluesIF::RETURN_FAILED; - } - replyReturnValue(message, result); - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t MonitoringHelper::handleReportingStrategyMessage(uint8_t strategy, - store_address_t storeId) { - const uint8_t* data = NULL; - uint32_t size = 0; - ReturnValue_t result = ipcStore->getData(storeId, &data, &size); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - EnableDisableContent content; - int32_t tSize = size; - result = content.deSerialize(&data, &tSize, true); - if (result != HasReturnvaluesIF::RETURN_OK) { - ipcStore->deleteData(storeId); - return result; - } - if (content.funkyList.size == 0) { - result = owner->setCheckingOfParameters(strategy); - } else { - for (EnableDisableContent::EnableDisableList::Iterator iter = content.funkyList.begin(); - iter != content.funkyList.end(); iter++) { - result = owner->setCheckingOfParameters(strategy, true, *iter); - if (result != HasReturnvaluesIF::RETURN_OK) { - //TODO: SW event (as stated in pus) - } - break; - } - result = HasReturnvaluesIF::RETURN_OK; - } - ipcStore->deleteData(storeId); - return result; -} - -ReturnValue_t MonitoringHelper::handleUpdateParameterMonitor(store_address_t storeId) { - const uint8_t* data = NULL; - uint32_t size = 0; - ReturnValue_t result = ipcStore->getData(storeId, &data, &size); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - uint8_t limitType = *data; - data++; - size -= 1; - const uint8_t* pData = data; - int32_t pSize = size; - uint32_t parameterId = 0; - result = SerializeAdapter::deSerialize(¶meterId, &pData, &pSize, - true); - if (result == HasReturnvaluesIF::RETURN_OK) { - result = owner->modifyParameterMonitor(limitType, parameterId, pData, pSize); - } - ipcStore->deleteData(storeId); - return result; -} - -ReturnValue_t MonitoringHelper::handleUpdateObjectMonitor(store_address_t storeId) { - const uint8_t* data = NULL; - uint32_t size = 0; - ReturnValue_t result = ipcStore->getData(storeId, &data, &size); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - object_id_t objectId = 0; - const uint8_t* pData = data; - int32_t tSize = size; - result = SerializeAdapter::deSerialize(&objectId, &pData, &tSize, true); - if (result == HasReturnvaluesIF::RETURN_OK) { - result = owner->modifyObjectMonitor(objectId, pData, tSize); - } - ipcStore->deleteData(storeId); - return result; -} - -void MonitoringHelper::replyReturnValue(CommandMessage* message, ReturnValue_t result) { - CommandMessage reply; - if (result == HasReturnvaluesIF::RETURN_OK) { - reply.setCommand(CommandMessage::REPLY_COMMAND_OK); - } else { - reply.setReplyRejected(result, message->getCommand()); - } - MessageQueueSender sender(message->getSender()); - sender.sendToDefault(&reply, owner->getCommandQueue()); -} - -ReturnValue_t MonitoringHelper::initialize() { - ipcStore = objectManager->get(objects::IPC_STORE); - if (ipcStore != NULL) { - return HasReturnvaluesIF::RETURN_OK; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } -} diff --git a/monitoring/MonitoringHelper.h b/monitoring/MonitoringHelper.h deleted file mode 100644 index 20093ecc..00000000 --- a/monitoring/MonitoringHelper.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * MonitoringHelper.h - * - * Created on: 07.07.2014 - * Author: baetz - */ - -#ifndef MONITORINGHELPER_H_ -#define MONITORINGHELPER_H_ - -#include -#include -#include - -class MonitoringHelper { -public: - MonitoringHelper(HasMonitorsIF* limitOwner); - virtual ~MonitoringHelper(); - ReturnValue_t handleMessage(CommandMessage* message); - ReturnValue_t initialize(); -private: - HasMonitorsIF* owner; - StorageManagerIF* ipcStore; //might be static - ReturnValue_t handleReportingStrategyMessage(uint8_t strategy, store_address_t storeId); - ReturnValue_t handleUpdateParameterMonitor(store_address_t storeId); - ReturnValue_t handleUpdateObjectMonitor(store_address_t storeId); - void replyReturnValue(CommandMessage* message, ReturnValue_t result); -}; - -#endif /* MONITORINGHELPER_H_ */ diff --git a/monitoring/MonitoringIF.h b/monitoring/MonitoringIF.h index b545e97d..d2d62f35 100644 --- a/monitoring/MonitoringIF.h +++ b/monitoring/MonitoringIF.h @@ -7,7 +7,7 @@ class MonitoringIF : public SerializeIF { public: - static const uint8_t VIOLATION_REPORT_MAX_SIZE = 30; + static const uint8_t VIOLATION_REPORT_MAX_SIZE = 32; static const uint8_t LIMIT_TYPE_NO_TYPE = 0xFF; static const uint8_t LIMIT_TYPE_LIMIT_CHECK = 0; static const uint8_t LIMIT_TYPE_DELTA_CHECK = 1; @@ -20,7 +20,7 @@ public: static const Event VALUE_ABOVE_HIGH_LIMIT = MAKE_EVENT(3, SEVERITY::LOW); static const Event VALUE_OUT_OF_RANGE = MAKE_EVENT(4, SEVERITY::LOW); - static const uint8_t INTERFACE_ID = LIMITS_IF; + static const uint8_t INTERFACE_ID = CLASS_ID::LIMITS_IF; static const ReturnValue_t UNCHECKED = MAKE_RETURN_CODE(1); static const ReturnValue_t INVALID = MAKE_RETURN_CODE(2); static const ReturnValue_t UNSELECTED = MAKE_RETURN_CODE(3); @@ -55,8 +55,8 @@ public: virtual ReturnValue_t setLimits( uint8_t type, const uint8_t* data, uint32_t size) = 0; virtual ReturnValue_t setChecking(uint8_t strategy) = 0; virtual ReturnValue_t setToUnchecked() = 0; - virtual const uint8_t getLimitType() const = 0; - virtual const uint32_t getLimitId() const = 0; + virtual uint8_t getLimitType() const = 0; + virtual uint32_t getLimitId() const = 0; // virtual ReturnValue_t setEventReporting(bool active) = 0; virtual ~MonitoringIF() { } diff --git a/monitoring/MonitoringListAdapter.cpp b/monitoring/MonitoringListAdapter.cpp deleted file mode 100644 index 258cbfbd..00000000 --- a/monitoring/MonitoringListAdapter.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * MonitoringListAdapter.cpp - * - * Created on: 09.07.2014 - * Author: baetz - */ - -#include - -ReturnValue_t MonitoringListAdapter::check() { - LinkedElement* element = start; - ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; - bool atLeastOneFailed = false; - while ((element != NULL)) { - result = element->value->check(); - if (result != HasReturnvaluesIF::RETURN_OK) { - atLeastOneFailed = true; - } - element = element->getNext(); - } - return (atLeastOneFailed) ? - (ReturnValue_t) HasReturnvaluesIF::RETURN_FAILED : - (ReturnValue_t) HasReturnvaluesIF::RETURN_OK; -} - -//ReturnValue_t MonitoringListAdapter::serialize(uint8_t** buffer, uint32_t* size, -// const uint32_t max_size, bool bigEndian) const { -// return SerialListAdapter::serialize(start, buffer, size, max_size, bigEndian); -//} -// -//uint32_t MonitoringListAdapter::getSerializedSize() const { -// return SerialListAdapter::getSerializedSize(start); -//} -// -//ReturnValue_t MonitoringListAdapter::deSerialize(const uint8_t** buffer, int32_t* size, -// bool bigEndian) { -// return SerialListAdapter::deSerialize(start, buffer, size, bigEndian); -//} - -ReturnValue_t MonitoringListAdapter::updateMonitor(uint32_t parameterId, - uint8_t limitType, const uint8_t* data, uint32_t size) { - LinkedElement* element = start; - while ((element != NULL)) { - if ((element->value->getLimitId() == parameterId)) { - return element->value->setLimits(limitType, data, size); - } - element = element->getNext(); - } - return MonitoringIF::MONITOR_NOT_FOUND; -} - -ReturnValue_t MonitoringListAdapter::setChecking(uint8_t strategy, uint32_t parameterId) { - LinkedElement* element = start; - while ((element != NULL)) { - if ((element->value->getLimitId() == parameterId)) { - return element->value->setChecking(strategy); - } - element = element->getNext(); - } - return MonitoringIF::MONITOR_NOT_FOUND; -} - -ReturnValue_t MonitoringListAdapter::setChecking(uint8_t strategy) { - LinkedElement* element = start; - ReturnValue_t result = MonitoringIF::MONITOR_NOT_FOUND; - bool atLeastOneUpdated = false; - while ((element != NULL)) { - result = element->value->setChecking(strategy); - if (result == HasReturnvaluesIF::RETURN_OK) { - atLeastOneUpdated = true; - } - element = element->getNext(); - } - result = - (atLeastOneUpdated) ? - (ReturnValue_t) HasReturnvaluesIF::RETURN_OK : - (ReturnValue_t) MonitoringIF::MONITOR_NOT_FOUND; - return result; -} diff --git a/monitoring/MonitoringListAdapter.h b/monitoring/MonitoringListAdapter.h deleted file mode 100644 index e290f4f9..00000000 --- a/monitoring/MonitoringListAdapter.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * MonitoringListAdapter.h - * - * Created on: 09.07.2014 - * Author: baetz - */ - -#ifndef MONITORINGLISTADAPTER_H_ -#define MONITORINGLISTADAPTER_H_ - -#include -#include - -class MonitoringListAdapter : public SerialLinkedListAdapter { -public: - MonitoringListAdapter(LinkedElement* start) : SerialLinkedListAdapter(start) { - } - MonitoringListAdapter() : SerialLinkedListAdapter() { - } - /** - * Checks all elements. - * @return Returns RETURN_FAILED if at least one check failed. - */ - ReturnValue_t check(); - /** - * Iterates the list to update the requested monitor. - * @param parameterId The parameter id to monitor. - * @param limitId The limit id for the given PID. - * @param data contains the new values - * @param size size of the new values - * @return The return code of the monitor if it was found and an update attempt, MONITOR_NOT_FOUND else. - */ - ReturnValue_t updateMonitor( uint32_t parameterId, uint8_t limitType, const uint8_t* data, uint32_t size); - /** - * Iterates the list to set the checking strategies for one monitor. - * @param strategy the reporting strategy. - * @param parameterId The PID. - * @param limitId The limit id for the given PID. - * @return The return code of the monitor if it was found and an update attempt, MONITOR_NOT_FOUND else. - */ -// ReturnValue_t setChecking(uint8_t strategy, uint32_t parameterId, uint32_t limitId); - /** - * Iterates the list to set the checking strategies for all monitors of a given parameter. - * @param strategy the reporting strategy. - * @param parameterId The PID. - * @return RETURN_OK if at least one monitor was updated, MONITOR_NOT_FOUND else. - */ - ReturnValue_t setChecking(uint8_t strategy, uint32_t parameterId); - /** - * Iterates the list to set the checking strategies for all monitors- - * @param strategy the reporting strategy. - * @return RETURN_OK if at least one monitor was updated, MONITOR_NOT_FOUND else. - */ - ReturnValue_t setChecking(uint8_t strategy); -}; - - - -#endif /* MONITORINGLISTADAPTER_H_ */ diff --git a/monitoring/MonitoringMessage.cpp b/monitoring/MonitoringMessage.cpp index e9359fc6..77919bfe 100644 --- a/monitoring/MonitoringMessage.cpp +++ b/monitoring/MonitoringMessage.cpp @@ -4,11 +4,6 @@ MonitoringMessage::~MonitoringMessage() { } -void MonitoringMessage::setAddLimitCommand(CommandMessage* message, - store_address_t storeId) { - setTypicalMessage(message, ADD_MONITOR, storeId); -} - void MonitoringMessage::setLimitViolationReport(CommandMessage* message, store_address_t storeId) { setTypicalMessage(message, LIMIT_VIOLATION_REPORT, storeId); @@ -29,8 +24,6 @@ store_address_t MonitoringMessage::getStoreId(const CommandMessage* message) { void MonitoringMessage::clear(CommandMessage* message) { message->setCommand(CommandMessage::CMD_NONE); switch (message->getCommand()) { - case MonitoringMessage::ADD_MONITOR: - case MonitoringMessage::UPDATE_PARAMETER_MONITOR: case MonitoringMessage::LIMIT_VIOLATION_REPORT: { StorageManagerIF *ipcStore = objectManager->get( objects::IPC_STORE); @@ -43,14 +36,3 @@ void MonitoringMessage::clear(CommandMessage* message) { break; } } - -void MonitoringMessage::setChangeReportingStrategy(CommandMessage* message, - uint8_t strategy, store_address_t storeId) { - message->setCommand(CHANGE_REPORTING_STRATEGY); - message->setParameter(strategy); - message->setParameter2(storeId.raw); -} - -uint8_t MonitoringMessage::getReportingStategy(CommandMessage* message) { - return (message->getParameter() & 0xFF); -} diff --git a/monitoring/MonitoringMessage.h b/monitoring/MonitoringMessage.h index 2e13a66b..d2ff9b4d 100644 --- a/monitoring/MonitoringMessage.h +++ b/monitoring/MonitoringMessage.h @@ -6,23 +6,13 @@ class MonitoringMessage: public CommandMessage { public: - static const uint8_t MESSAGE_ID = LIMIT_MESSAGE_ID; - static const Command_t ADD_MONITOR = MAKE_COMMAND_ID(1); //PID(uint32_t), Data(type, {LIMIT_ID(uint8_t), initialLimits(data, depends)}) - static const Command_t UPDATE_PARAMETER_MONITOR = MAKE_COMMAND_ID(2); //PID(uint32_t), Data{type, n_entries {LIMIT_ID(uint8_t), TYPE(uint8_t) newLimits(data, depends) - static const Command_t UPDATE_OBJECT_MONITOR = MAKE_COMMAND_ID(3); - static const Command_t CHANGE_REPORTING_STRATEGY = MAKE_COMMAND_ID(4); //PID(uint32_t), Data{type, n_entries {LIMIT_ID(uint8_t), TYPE(uint8_t) newLimits(data, depends) - //Optional -// static const Command_t REPORT_LIMIT_DEFINITIONS = MAKE_COMMAND_ID(3); //N_PIDS, PID(uint32_t) -// static const Command_t LIMIT_DEFINITION_REPORT = MAKE_COMMAND_ID(3); //Eventually multiple reports per type or even per definition. + static const uint8_t MESSAGE_ID = MESSAGE_TYPE::MONITORING; //Object id could be useful, but we better manage that on service level (register potential reporters). static const Command_t LIMIT_VIOLATION_REPORT = MAKE_COMMAND_ID(10); virtual ~MonitoringMessage(); - static void setAddLimitCommand(CommandMessage* message, store_address_t storeId); - static void setChangeReportingStrategy(CommandMessage* message, uint8_t strategy, store_address_t storeId); static void setLimitViolationReport(CommandMessage* message, store_address_t storeId); static void clear(CommandMessage* message); static store_address_t getStoreId(const CommandMessage* message); - static uint8_t getReportingStategy(CommandMessage* message); static void setTypicalMessage(CommandMessage* message, Command_t type, store_address_t storeId); }; diff --git a/monitoring/MonitoringMessageContent.h b/monitoring/MonitoringMessageContent.h index 07b0bfb1..e5a7d470 100644 --- a/monitoring/MonitoringMessageContent.h +++ b/monitoring/MonitoringMessageContent.h @@ -11,9 +11,14 @@ #include #include +namespace Factory{ +void setStaticFrameworkObjectIds(); +} + //PID(uint32_t), TYPE, LIMIT_ID, value,limitValue, previous, later, timestamp template class MonitoringReportContent: public SerialLinkedListAdapter { + friend void (Factory::setStaticFrameworkObjectIds)(); public: SerializeElement monitorId; SerializeElement parameterId; @@ -22,7 +27,7 @@ public: SerializeElement oldState; SerializeElement newState; uint8_t rawTimestamp[TimeStamperIF::MISSION_TIMESTAMP_SIZE]; - SerializeElement timestampSerializer; + SerializeElement> timestampSerializer; TimeStamperIF* timeStamper; MonitoringReportContent() : SerialLinkedListAdapter( @@ -35,9 +40,9 @@ public: MonitoringReportContent(uint32_t setPID, T value, T limitValue, ReturnValue_t oldState, ReturnValue_t newState) : SerialLinkedListAdapter( - LinkedElement::Iterator(¶meterId)), parameterId( + LinkedElement::Iterator(¶meterId)), monitorId(0), parameterId( setPID), parameterValue(value), limitValue(limitValue), oldState( - oldState), newState(newState), rawTimestamp( { 0 }), timestampSerializer(rawTimestamp, + oldState), newState(newState), timestampSerializer(rawTimestamp, sizeof(rawTimestamp)), timeStamper(NULL) { setAllNext(); if (checkAndSetStamper()) { @@ -45,6 +50,8 @@ public: } } private: + + static object_id_t timeStamperId; void setAllNext() { parameterId.setNext(¶meterValue); parameterValue.setNext(&limitValue); @@ -54,8 +61,7 @@ private: } bool checkAndSetStamper() { if (timeStamper == NULL) { - //TODO: Adjust name? - timeStamper = objectManager->get( objects::TIME_MANAGER ); + timeStamper = objectManager->get( timeStamperId ); if ( timeStamper == NULL ) { error << "MonitoringReportContent::checkAndSetStamper: Stamper not found!" << std::endl; return false; @@ -64,45 +70,7 @@ private: return true; } }; - -//TODO: Next message would be update_limit message. -//PID(uint32_t), Data{type, n_entries {LIMIT_ID(uint8_t), TYPE(uint8_t) newLimits(data, depends) - template -class UpdateLimitMonitorContent: public SerialLinkedListAdapter { -public: - SerializeElement lowValue; - SerializeElement highValue; - UpdateLimitMonitorContent() : - SerialLinkedListAdapter(&lowValue), lowValue(0), highValue( - 0) { - lowValue.setNext(&highValue); - } -private: -}; - -//Not used at the moment. -//class EnableDisableInner: public SerialLinkedListAdapter { -//public: -// SerializeElement parameterId; -// typedef FixedArrayList LimitIdList; -// SerializeElement limitList; -// EnableDisableInner() : -// SerialLinkedListAdapter(¶meterId) { -// parameterId.setNext(&limitList); -// } -//}; - -class EnableDisableContent { -public: - typedef SerialFixedArrayListAdapter EnableDisableList; - EnableDisableList funkyList; - EnableDisableContent() { - } - ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { - return funkyList.deSerialize(buffer, size, bigEndian); - } -}; +object_id_t MonitoringReportContent::timeStamperId = 0; #endif /* MONITORINGMESSAGECONTENT_H_ */ diff --git a/monitoring/OneParameterMonitorList.h b/monitoring/OneParameterMonitorList.h deleted file mode 100644 index 71792093..00000000 --- a/monitoring/OneParameterMonitorList.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * OneParameterMonitorList.h - * - * Created on: 25.07.2014 - * Author: baetz - */ - -#ifndef ONEPARAMETERMONITORLIST_H_ -#define ONEPARAMETERMONITORLIST_H_ - -#include -#include - -class OneParameterMonitorList: public SinglyLinkedList, - public MonitoringIF { -public: - OneParameterMonitorList(uint32_t setParameterId, - LinkedElement* start) : - SinglyLinkedList(start), parameterId( - setParameterId) { - } - - OneParameterMonitorList() : - SinglyLinkedList(), parameterId(0) { - } - - ReturnValue_t check() { - LinkedElement* element = start; - ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; - bool atLeastOneFailed = false; - while ((element != NULL)) { - result = element->value->check(); - if (result != HasReturnvaluesIF::RETURN_OK) { - atLeastOneFailed = true; - } - element = element->getNext(); - } - return (atLeastOneFailed) ? - (ReturnValue_t) HasReturnvaluesIF::RETURN_FAILED : - (ReturnValue_t) HasReturnvaluesIF::RETURN_OK; - } - - ReturnValue_t setLimits(uint8_t type, const uint8_t* data, uint32_t size) { - uint8_t position = *data; - data++; - size--; - uint8_t currentPosition = 1; - LinkedElement* element = start; - while ((element != NULL)) { - if ((element->value->getLimitType() == type)) { - if (position == currentPosition++) { - return element->value->setLimits(type, data, size); - } - } - element = element->getNext(); - } - return MonitoringIF::MONITOR_NOT_FOUND; - } - - ReturnValue_t setChecking(uint8_t strategy) { - LinkedElement* element = start; - ReturnValue_t result = MonitoringIF::MONITOR_NOT_FOUND; - bool atLeastOneUpdated = false; - while ((element != NULL)) { - result = element->value->setChecking(strategy); - if (result == HasReturnvaluesIF::RETURN_OK) { - atLeastOneUpdated = true; - } - element = element->getNext(); - } - result = - (atLeastOneUpdated) ? - (ReturnValue_t) HasReturnvaluesIF::RETURN_OK : - (ReturnValue_t) MonitoringIF::MONITOR_NOT_FOUND; - return result; - } - - ReturnValue_t setToUnchecked() { - LinkedElement* element = start; - ReturnValue_t result = MonitoringIF::MONITOR_NOT_FOUND; - bool atLeastOneUpdated = false; - while ((element != NULL)) { - result = element->value->setToUnchecked(); - if (result == HasReturnvaluesIF::RETURN_OK) { - atLeastOneUpdated = true; - } - element = element->getNext(); - } - result = - (atLeastOneUpdated) ? - (ReturnValue_t) HasReturnvaluesIF::RETURN_OK : - (ReturnValue_t) MonitoringIF::MONITOR_NOT_FOUND; - return result; - } - - const uint8_t getLimitType() const { - return LIMIT_TYPE_NO_TYPE; - } - const uint32_t getLimitId() const { - return parameterId; - } - - ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { - return SerialLinkedListAdapter::serialize(this->start,buffer,size, max_size,bigEndian); - } - - uint32_t getSerializedSize() const { - return SerialLinkedListAdapter::getSerializedSize(this->start); - } - - ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { - return SerialLinkedListAdapter::deSerialize(this->start, buffer, size, bigEndian); - } -private: - uint32_t parameterId; -}; -#endif /* ONEPARAMETERMONITORLIST_H_ */ diff --git a/monitoring/ReceivesMonitoringReportsIF.h b/monitoring/ReceivesMonitoringReportsIF.h index 568c9007..42c365c1 100644 --- a/monitoring/ReceivesMonitoringReportsIF.h +++ b/monitoring/ReceivesMonitoringReportsIF.h @@ -1,14 +1,7 @@ -/* - * ReceivesMonitoringReportsIF.h - * - * Created on: 07.07.2014 - * Author: baetz - */ - #ifndef RECEIVESMONITORINGREPORTSIF_H_ #define RECEIVESMONITORINGREPORTSIF_H_ -#include +#include class ReceivesMonitoringReportsIF { public: diff --git a/monitoring/TriplexMonitor.h b/monitoring/TriplexMonitor.h new file mode 100644 index 00000000..9a2e69c3 --- /dev/null +++ b/monitoring/TriplexMonitor.h @@ -0,0 +1,155 @@ +#ifndef FRAMEWORK_MONITORING_TRIPLEXMONITOR_H_ +#define FRAMEWORK_MONITORING_TRIPLEXMONITOR_H_ + +#include +#include +#include +#include +#include + + +//SHOULDDO: This is by far not perfect. Could be merged with new Monitor classes. But still, it's over-engineering. +template +class TriplexMonitor : public HasParametersIF { +public: + static const uint8_t INTERFACE_ID = CLASS_ID::TRIPLE_REDUNDACY_CHECK; + static const ReturnValue_t NOT_ENOUGH_SENSORS = MAKE_RETURN_CODE(1); + static const ReturnValue_t LOWEST_VALUE_OOL = MAKE_RETURN_CODE(2); + static const ReturnValue_t HIGHEST_VALUE_OOL = MAKE_RETURN_CODE(3); + static const ReturnValue_t BOTH_VALUES_OOL = MAKE_RETURN_CODE(4); + static const ReturnValue_t DUPLEX_OOL = MAKE_RETURN_CODE(5); + + static const uint8_t THREE = 3; + + TriplexMonitor(const uint32_t parameterIds[3], uint8_t domainId, const T initialLimit, + Event eventTripleCheck, Event eventDualCheck) : + values(parameterIds, &dataSet), limit(initialLimit), eventTripleCheck( + eventTripleCheck), eventDualCheck(eventDualCheck), healthTable( + NULL), domainId(domainId) { + + } + virtual ~TriplexMonitor() { + } + ReturnValue_t check() { + dataSet.read(); + //check health and validity + uint8_t availableIndex[2] = { 0, 0 }; + bool first = true; + uint8_t nAvailable = 0; + for (uint8_t count = 0; count < THREE; count++) { + if (values[count].isValid() && checkObjectHealthState(count)) { + if (first) { + availableIndex[0] = count; + first = false; + } else { + //Might be filled twice, but then it's not needed anyway. + availableIndex[1] = count; + } + nAvailable++; + } + } + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + switch (nAvailable) { + case 3: + result = doTriplexMonitoring(); + break; + case 2: + result = doDuplexMonitoring(availableIndex); + break; + default: + result = NOT_ENOUGH_SENSORS; + break; + } + dataSet.commit(); + return result; + } + ReturnValue_t initialize() { + healthTable = objectManager->get(objects::HEALTH_TABLE); + if (healthTable == NULL) { + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; + } + + ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, + ParameterWrapper *parameterWrapper, + const ParameterWrapper *newValues, uint16_t startAtIndex) { + if (domainId != this->domainId) { + return INVALID_DOMAIN_ID; + } + switch (parameterId) { + case 0: + parameterWrapper->set(limit); + break; + default: + return INVALID_MATRIX_ID; + } + return HasReturnvaluesIF::RETURN_OK; + } + +protected: + DataSet dataSet; + PIDReaderList values; + T limit; + Event eventTripleCheck; + Event eventDualCheck; + HealthTableIF* healthTable; + uint8_t domainId; + ReturnValue_t doTriplexMonitoring() { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + //Find middle value, by ordering indices + uint8_t index[3] = { 0, 1, 2 }; + if (values[index[0]].value > values[index[1]].value) { + std::swap(index[0], index[1]); + } + if (values[index[0]].value > values[index[2]].value) { + std::swap(index[0], index[2]); + } + if (values[index[1]].value > values[index[2]].value) { + std::swap(index[1], index[2]); + } + //Test if smallest value is out-of-limit. + if (values[index[0]] < (values[index[1]] - limit)) { + EventManagerIF::triggerEvent(getRefereneceObject(index[0]), + eventTripleCheck, LOWEST_VALUE_OOL, 0); + result = LOWEST_VALUE_OOL; + } + //Test if largest value is out-of-limit. + if (values[index[2]] > (values[index[1]] + limit)) { + EventManagerIF::triggerEvent(getRefereneceObject(index[2]), + eventTripleCheck, HIGHEST_VALUE_OOL, 0); + if (result == HasReturnvaluesIF::RETURN_OK) { + result = HIGHEST_VALUE_OOL; + } else { + result = BOTH_VALUES_OOL; + } + } + return result; + } + + ReturnValue_t doDuplexMonitoring(uint8_t index[2]) { + T mean = (values[index[0]] + values[index[1]]) / 2; + if (values[index[0]] > values[index[1]]) { + if (values[index[0]] > (mean + limit)) { + EventManagerIF::triggerEvent(getRefereneceObject(index[0]), + eventDualCheck, 0, 0); + EventManagerIF::triggerEvent(getRefereneceObject(index[1]), + eventDualCheck, 0, 0); + return DUPLEX_OOL; + } + } else { + if (values[index[1]] > (mean + limit)) { + EventManagerIF::triggerEvent(getRefereneceObject(index[0]), + eventDualCheck, 0, 0); + EventManagerIF::triggerEvent(getRefereneceObject(index[1]), + eventDualCheck, 0, 0); + return DUPLEX_OOL; + } + } + return HasReturnvaluesIF::RETURN_OK; + } + virtual bool checkObjectHealthState(uint8_t valueIndex) = 0; + virtual object_id_t getRefereneceObject(uint8_t valueIndex) = 0; +}; + +#endif /* FRAMEWORK_MONITORING_TRIPLEXMONITOR_H_ */ diff --git a/monitoring/TwoValueLimitMonitor.h b/monitoring/TwoValueLimitMonitor.h index cc055b77..1e924856 100644 --- a/monitoring/TwoValueLimitMonitor.h +++ b/monitoring/TwoValueLimitMonitor.h @@ -1,4 +1,3 @@ - #ifndef FRAMEWORK_MONITORING_TWOVALUELIMITMONITOR_H_ #define FRAMEWORK_MONITORING_TWOVALUELIMITMONITOR_H_ diff --git a/objectmanager/ObjectManager.cpp b/objectmanager/ObjectManager.cpp index cb505c04..75ca1a60 100644 --- a/objectmanager/ObjectManager.cpp +++ b/objectmanager/ObjectManager.cpp @@ -1,13 +1,3 @@ -/* - * ObjectManager.cpp - * - * Created on: Sep 18, 2012 - * Author: baetz - */ - - - - #include #include #include @@ -37,7 +27,6 @@ ReturnValue_t ObjectManager::insert( object_id_t id, SystemObjectIF* object) { } ReturnValue_t ObjectManager::remove( object_id_t id ) { - std::map::iterator it = this->objectList.find( id ); if ( this->getSystemObject(id) != NULL ) { this->objectList.erase( id ); debug << "ObjectManager::removeObject: Object " << std::hex << (int)id << std::dec << " removed." << std::endl; @@ -67,7 +56,6 @@ ObjectManager::ObjectManager( ) : produceObjects(NULL) { } void ObjectManager::initialize() { - //TODO: Include check if already initialized? this->produceObjects(); ReturnValue_t return_value = RETURN_FAILED; uint32_t error_count = 0; diff --git a/objectmanager/ObjectManager.h b/objectmanager/ObjectManager.h index de22939e..63451071 100644 --- a/objectmanager/ObjectManager.h +++ b/objectmanager/ObjectManager.h @@ -54,7 +54,7 @@ public: /** * @brief In the class's destructor, all objects in the list are deleted. */ - //TODO: Check, if deleting works! + //SHOULDDO: If, for some reason, deleting an ObjectManager instance is required, check if this works. virtual ~ObjectManager( void ); ReturnValue_t insert( object_id_t id, SystemObjectIF* object ); ReturnValue_t remove( object_id_t id ); diff --git a/objectmanager/ObjectManagerIF.h b/objectmanager/ObjectManagerIF.h index 81482ba0..aca24a24 100644 --- a/objectmanager/ObjectManagerIF.h +++ b/objectmanager/ObjectManagerIF.h @@ -8,6 +8,7 @@ #ifndef OBJECTMANAGERIF_H_ #define OBJECTMANAGERIF_H_ +#include #include #include #include @@ -23,7 +24,7 @@ */ class ObjectManagerIF : public HasReturnvaluesIF { public: - static const uint8_t INTERFACE_ID = OBJECT_MANAGER_IF; + static const uint8_t INTERFACE_ID = CLASS_ID::OBJECT_MANAGER_IF; static const ReturnValue_t INSERTION_FAILED = MAKE_RETURN_CODE( 1 ); static const ReturnValue_t NOT_FOUND = MAKE_RETURN_CODE( 2 ); protected: diff --git a/objectmanager/SystemObject.cpp b/objectmanager/SystemObject.cpp index c6495098..85daaa35 100644 --- a/objectmanager/SystemObject.cpp +++ b/objectmanager/SystemObject.cpp @@ -1,10 +1,3 @@ -/* - * SystemObject.cpp - * - * Created on: 07.11.2012 - * Author: mohr - */ - #include #include #include @@ -22,7 +15,7 @@ SystemObject::~SystemObject() { } } -const object_id_t SystemObject::getObjectId() const { +object_id_t SystemObject::getObjectId() const { return objectId; } diff --git a/objectmanager/SystemObject.h b/objectmanager/SystemObject.h index 01f7c327..6a1b35b6 100644 --- a/objectmanager/SystemObject.h +++ b/objectmanager/SystemObject.h @@ -10,8 +10,8 @@ #include #include -#include #include +#include /** * @brief This class automates insertion into the ObjectManager and @@ -51,7 +51,7 @@ public: * @brief On destruction, the object removes itself from the list. */ virtual ~SystemObject(); - const object_id_t getObjectId() const; + object_id_t getObjectId() const; virtual ReturnValue_t initialize(); virtual ReturnValue_t checkObjectConnections(); diff --git a/objectmanager/SystemObjectIF.h b/objectmanager/SystemObjectIF.h index a0c924fc..7540f80f 100644 --- a/objectmanager/SystemObjectIF.h +++ b/objectmanager/SystemObjectIF.h @@ -37,7 +37,7 @@ public: * This is a simple getter to return the object identifier. * @return Returns the object id of this object. */ - virtual const object_id_t getObjectId() const = 0; + virtual object_id_t getObjectId() const = 0; /** * The empty virtual destructor as required for C++ interfaces. */ diff --git a/objectmanager/frameworkObjects.h b/objectmanager/frameworkObjects.h new file mode 100644 index 00000000..c3deafc4 --- /dev/null +++ b/objectmanager/frameworkObjects.h @@ -0,0 +1,21 @@ +#ifndef FRAMEWORK_OBJECTMANAGER_FRAMEWORKOBJECTS_H_ +#define FRAMEWORK_OBJECTMANAGER_FRAMEWORKOBJECTS_H_ + +namespace objects { +enum framework_objects { + //Generic IDs for IPC, modes, health, events + HEALTH_TABLE = 0x53010000, +// MODE_STORE = 0x53010100, + EVENT_MANAGER = 0x53030000, + INTERNAL_ERROR_REPORTER = 0x53040000, + IPC_STORE = 0x534f0300, + //IDs for PUS Packet Communication + TC_STORE = 0x534f0100, + TM_STORE = 0x534f0200, + NO_OBJECT = 0xFFFFFFFF +}; +} + + + +#endif /* FRAMEWORK_OBJECTMANAGER_FRAMEWORKOBJECTS_H_ */ diff --git a/osal/Endiness.h b/osal/Endiness.h new file mode 100644 index 00000000..6e23ce57 --- /dev/null +++ b/osal/Endiness.h @@ -0,0 +1,13 @@ +#ifndef FRAMEWORK_OSAL_ENDINESS_H_ +#define FRAMEWORK_OSAL_ENDINESS_H_ + +//We have to define BYTE_ORDER for that specific OS/Hardware so this must be done somewhere +#ifndef API +#error Please specify Operating System API. Supported: API=RTEMS_API +#elif API == RTEMS_API +#include "rtems/RtemsBasic.h" +#endif + + + +#endif /* FRAMEWORK_OSAL_ENDINESS_H_ */ diff --git a/osal/InternalErrorCodes.h b/osal/InternalErrorCodes.h index 2c4f2d2c..5419fd94 100644 --- a/osal/InternalErrorCodes.h +++ b/osal/InternalErrorCodes.h @@ -5,7 +5,7 @@ class InternalErrorCodes { public: - static const uint8_t INTERFACE_ID = INTERNAL_ERROR_CODES; + static const uint8_t INTERFACE_ID = CLASS_ID::INTERNAL_ERROR_CODES; static const ReturnValue_t NO_CONFIGURATION_TABLE = MAKE_RETURN_CODE(0x01 ); static const ReturnValue_t NO_CPU_TABLE = MAKE_RETURN_CODE(0x02 ); diff --git a/osal/Linux/Clock.cpp b/osal/Linux/Clock.cpp new file mode 100644 index 00000000..d2ce166f --- /dev/null +++ b/osal/Linux/Clock.cpp @@ -0,0 +1,176 @@ +#include +#include +#include + + +#include +#include +#include + +//#include + + +uint32_t Clock::getTicksPerSecond(void){ + //TODO This function returns the ticks per second for thread ticks not clock ticks +// timespec ticks; +// int status = clock_getres(CLOCK_REALTIME,&ticks); +// +// if(status!=0){ +// //TODO errno +// return 0xFFFFFFFF; +// } +// uint32_t resolution = 1e9 / ticks.tv_nsec; + uint32_t resolution = sysconf(_SC_CLK_TCK); + return resolution; +} + +ReturnValue_t Clock::setClock(const TimeOfDay_t* time) { + //TODO timeOfDay conversion + timespec timeUnix; + int status = clock_settime(CLOCK_REALTIME,&timeUnix); + if(status!=0){ + //TODO errno + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::setClock(const timeval* time) { + timespec timeUnix; + timeUnix.tv_sec = time->tv_sec; + timeUnix.tv_nsec = (__syscall_slong_t) time->tv_usec * 1000; + int status = clock_settime(CLOCK_REALTIME,&timeUnix); + if(status!=0){ + //TODO errno + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::getClock_timeval(timeval* time) { + timespec timeUnix; + int status = clock_gettime(CLOCK_REALTIME,&timeUnix); + if(status!=0){ + return HasReturnvaluesIF::RETURN_FAILED; + } + time->tv_sec = timeUnix.tv_sec; + time->tv_usec = timeUnix.tv_nsec / 1000.0; + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::getClock_usecs(uint64_t* time) { + timeval timeVal; + ReturnValue_t result = getClock_timeval(&timeVal); + if(result != HasReturnvaluesIF::RETURN_OK){ + return result; + } + *time = (uint64_t)timeVal.tv_sec*1e6 + timeVal.tv_usec; + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::getUptime(timeval* uptime) { + //TODO This is not posix compatible and delivers only seconds precision + struct sysinfo sysInfo; + int result = sysinfo(&sysInfo); + if(result != 0){ + return HasReturnvaluesIF::RETURN_FAILED; + } + uptime->tv_sec = sysInfo.uptime; + uptime->tv_usec = 0; + + + //Linux specific file read but more precise +// double uptimeSeconds; +// if(std::ifstream("/proc/uptime",std::ios::in) >> uptimeSeconds){ +// uptime->tv_sec = uptimeSeconds; +// uptime->tv_usec = uptimeSeconds *(double) 1e6 - (uptime->tv_sec *1e6); +// } + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) { + timeval uptime; + ReturnValue_t result = getUptime(&uptime); + if(result != HasReturnvaluesIF::RETURN_OK){ + return result; + } + *uptimeMs = uptime.tv_sec * 1e3 + uptime.tv_usec / 1e3; + return HasReturnvaluesIF::RETURN_OK; +} + + + +ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) { + timespec timeUnix; + int status = clock_gettime(CLOCK_REALTIME,&timeUnix); + if(status != 0){ + //TODO errno + return HasReturnvaluesIF::RETURN_FAILED; + } + timespec ticks; + status = clock_getres(CLOCK_REALTIME,&ticks); + if(status!=0){ + //TODO errno + return HasReturnvaluesIF::RETURN_FAILED; + } + uint32_t resolution = 1e9 / ticks.tv_nsec; + + + struct tm* timeInfo; + timeInfo = gmtime(&timeUnix.tv_sec); + time->year = timeInfo->tm_year + 1900; + time->month = timeInfo->tm_mon+1; + time->day = timeInfo->tm_mday; + time->hour = timeInfo->tm_hour; + time->minute = timeInfo->tm_min; + time->second = timeInfo->tm_sec; + time->ticks = (timeUnix.tv_nsec / (double) 1e9) * resolution; + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, + timeval* to) { + + tm fromTm; + //Note: Fails for years before AD + fromTm.tm_year = from->year - 1900; + fromTm.tm_mon = from->month - 1; + fromTm.tm_mday = from->day; + fromTm.tm_hour = from->hour; + fromTm.tm_min = from->minute; + fromTm.tm_sec = from->second; + + timespec ticks; + uint32_t status = clock_getres(CLOCK_REALTIME,&ticks); + if(status!=0){ + //TODO errno + return HasReturnvaluesIF::RETURN_FAILED; + } + uint32_t resolution = 1e9 / ticks.tv_nsec; + + to->tv_sec = mktime(&fromTm); + to->tv_usec = (from->ticks /(double) resolution) * 1e6; + + + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) { + return HasReturnvaluesIF::RETURN_FAILED; +} + +ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) { + return HasReturnvaluesIF::RETURN_FAILED; +} + +ReturnValue_t Clock::setLeapSeconds(const uint16_t leapSeconds_) { + return HasReturnvaluesIF::RETURN_FAILED; +} + +ReturnValue_t Clock::getLeapSeconds(uint16_t* leapSeconds_) { + return HasReturnvaluesIF::RETURN_FAILED; +} diff --git a/osal/OSAL.cpp b/osal/OSAL.cpp deleted file mode 100644 index 6c8507f4..00000000 --- a/osal/OSAL.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/** - * @file OSAL.cpp - * @brief This file defines the OSAL class. - * @date 19.12.2012 - * @author baetz - */ - -#include - -#ifndef API -#error Please specify Operating System API. Supported: API=RTEMS_API -#elif API == RTEMS_API - -#include -//#include - -ReturnValue_t OSAL::convertReturnCode(uint8_t inValue) { - if (inValue == RTEMS_SUCCESSFUL) { - return OSAL::RETURN_OK; - } else { - return MAKE_RETURN_CODE(inValue); - } -} - -Name_t OSAL::buildName(uint8_t c1, uint8_t c2, uint8_t c3, uint8_t c4) { - return rtems_build_name(c1, c2, c3, c4); -} - -Interval_t OSAL::getTicksPerSecond() { - Interval_t ticks_per_second; - (void) rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second); - return ticks_per_second; -} - -ReturnValue_t OSAL::setClock(TimeOfDay_t* time) { - ReturnValue_t status = rtems_clock_set(time); - status = convertReturnCode(status); - return status; -} - -ReturnValue_t OSAL::setClock(timeval* time) { - timespec newTime; - newTime.tv_sec = time->tv_sec; - newTime.tv_nsec = time->tv_usec * TOD_NANOSECONDS_PER_MICROSECOND; - //TODO: Not sure if we need to protect this call somehow (by thread lock or something). - _TOD_Set(&newTime); - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t OSAL::getClock_timeval(timeval* time) { - ReturnValue_t status = rtems_clock_get_tod_timeval(time); - status = convertReturnCode(status); - return status; -} - -ReturnValue_t OSAL::getClock_usecs(uint64_t* time) { - timeval temp_time; - uint8_t returnValue = rtems_clock_get_tod_timeval(&temp_time); - *time = ((uint64_t) temp_time.tv_sec * 1000000) + temp_time.tv_usec; - return OSAL::convertReturnCode(returnValue); -} - -ReturnValue_t OSAL::getDateAndTime(TimeOfDay_t* time) { - ReturnValue_t status = rtems_clock_get_tod(time); - status = convertReturnCode(status); - return status; -} - -ReturnValue_t OSAL::sleepFor(Interval_t ticks) { - ReturnValue_t status = rtems_task_wake_after(ticks); - status = convertReturnCode(status); - return status; -} -ReturnValue_t OSAL::createTask(Name_t name, TaskPriority_t initial_priority, - size_t stack_size, OpusMode_t initial_modes, Attribute_t attribute_set, - TaskId_t* id) { - if (initial_priority >= 0 && initial_priority <= 99) { - ReturnValue_t status = rtems_task_create(name, - (0xFF - 2 * initial_priority), stack_size, initial_modes, - attribute_set, id); - status = convertReturnCode(status); - return status; - } else { - return OSAL::UNSATISFIED; - } -} - -ReturnValue_t OSAL::findTask(Name_t name, TaskId_t* id) { - ReturnValue_t status = rtems_task_ident(name, RTEMS_SEARCH_ALL_NODES, id); - status = convertReturnCode(status); - return status; -} - -ReturnValue_t OSAL::startTask(TaskId_t* id, TaskEntry_t entry_point, - TaskArgument_t argument) { - return rtems_task_start(*id, entry_point, argument); -} - -ReturnValue_t OSAL::deleteTask(TaskId_t* id) { - if (id == RTEMS_SELF) { - return rtems_task_delete(RTEMS_SELF); - } else { - return rtems_task_delete(*id); - } -} - -ReturnValue_t OSAL::setAndStartPeriod(Interval_t period, PeriodId_t *periodId, - Name_t name) { - uint8_t status; - status = rtems_rate_monotonic_create(name, periodId); - if (status == RTEMS_SUCCESSFUL) { - //This is necessary to avoid a call with period = 0, which does not start the period. - status = rtems_rate_monotonic_period(*periodId, period + 1); - } - return OSAL::convertReturnCode(status); -} - -ReturnValue_t OSAL::checkAndRestartPeriod(PeriodId_t periodId, - Interval_t period) { - ReturnValue_t status = rtems_rate_monotonic_period(periodId, period); - status = convertReturnCode(status); - return status; -} - -ReturnValue_t OSAL::deletePeriod(TaskId_t* id) { - rtems_name period_name; - rtems_id period_id; - rtems_object_get_classic_name(*id, &period_name); - period_name = (period_name & 0xFFFFFF00) + 0x50; - rtems_rate_monotonic_ident(period_name, &period_id); - ReturnValue_t status = rtems_rate_monotonic_delete(period_id); - status = convertReturnCode(status); - return status; -} - -ReturnValue_t OSAL::reportPeriodStatistics() { - rtems_rate_monotonic_report_statistics(); - return OSAL::SUCCESSFUL; -} - -ReturnValue_t OSAL::createMessageQueue(Name_t name, uint32_t count, - size_t max_message_size, Attribute_t attribute_set, - MessageQueueId_t* id) { - ReturnValue_t status = rtems_message_queue_create(name, count, - max_message_size, attribute_set, id); - status = convertReturnCode(status); - return status; -} - -ReturnValue_t OSAL::findMessageQueue(Name_t name, MessageQueueId_t* id) { - ReturnValue_t status = rtems_message_queue_ident(name, - RTEMS_SEARCH_ALL_NODES, id); - status = convertReturnCode(status); - return status; -} - -ReturnValue_t OSAL::sendMessage(MessageQueueId_t id, const void* buffer, - size_t size) { - ReturnValue_t status = rtems_message_queue_send(id, buffer, size); - return OSAL::convertReturnCode(status); -} - -ReturnValue_t OSAL::receiveMessage(MessageQueueId_t id, void* buffer, - size_t bufSize, size_t* recSize, Option_t option_set, - Interval_t timeout) { - ReturnValue_t status = rtems_message_queue_receive(id, buffer, recSize, - option_set, timeout); - status = convertReturnCode(status); - return status; -} - -ReturnValue_t OSAL::flushMessageQueue(MessageQueueId_t id, uint32_t* count) { - ReturnValue_t status = rtems_message_queue_flush(id, count); - status = convertReturnCode(status); - return status; -} - -ReturnValue_t OSAL::deleteMessageQueue(MessageQueueId_t* id) { - ReturnValue_t status = rtems_message_queue_delete(*id); - status = convertReturnCode(status); - return status; -} - -ReturnValue_t OSAL::createMutex(Name_t name, MutexId_t* id) { - ReturnValue_t status = rtems_semaphore_create(name, 1, - RTEMS_SIMPLE_BINARY_SEMAPHORE, 0, id); - status = convertReturnCode(status); - return status; -} - -ReturnValue_t OSAL::deleteMutex(MutexId_t* id) { - ReturnValue_t status = rtems_semaphore_delete(*id); - status = convertReturnCode(status); - return status; -} - -ReturnValue_t OSAL::lockMutex(MutexId_t* id, Interval_t timeout) { - ReturnValue_t status = rtems_semaphore_obtain(*id, WAIT, timeout); - status = convertReturnCode(status); - return status; -} - -ReturnValue_t OSAL::getUptime(timeval* uptime) { - timespec time; - ReturnValue_t status = rtems_clock_get_uptime(&time); - uptime->tv_sec = time.tv_sec; - time.tv_nsec = time.tv_nsec / 1000; - uptime->tv_usec = time.tv_nsec; - status = convertReturnCode(status); - return status; -} - -ReturnValue_t OSAL::getUptime(uint32_t* uptimeMs) { - *uptimeMs = rtems_clock_get_ticks_since_boot(); - return RTEMS_SUCCESSFUL; -} - -ReturnValue_t OSAL::unlockMutex(MutexId_t* id) { - ReturnValue_t status = rtems_semaphore_release(*id); - status = convertReturnCode(status); - return status; -} - -ReturnValue_t OSAL::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 - ReturnValue_t status = rtems_interrupt_catch(handler, interrupt + 0x10, - oldHandler); - status = convertReturnCode(status); - return status; -} - -//TODO: Make default values (edge, polarity) settable? -ReturnValue_t OSAL::enableInterrupt(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 RETURN_OK; - } else { - return RETURN_FAILED; - } -} - -ReturnValue_t OSAL::disableInterrupt(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 RETURN_OK; - } else { - return RETURN_FAILED; - } -} - -bool OSAL::isInterruptInProgress() { - return rtems_interrupt_is_in_progress(); -} - -ReturnValue_t OSAL::convertTimeOfDayToTimeval(const TimeOfDay_t* from, - timeval* to) { - //Fails in 2038.. - to->tv_sec = _TOD_To_seconds(from); - to->tv_usec = 0; - return RETURN_OK; -} - -#endif /* API */ diff --git a/osal/OSAL.h b/osal/OSAL.h deleted file mode 100644 index 01ab2c4d..00000000 --- a/osal/OSAL.h +++ /dev/null @@ -1,430 +0,0 @@ -/** - * @file OSAL.h - * @brief This file defines the OSAL class. - * @date 19.12.2012 - * @author baetz - */ - -#ifndef OSAL_H_ -#define OSAL_H_ - -#include - -#define RTEMS_API 1 - -#ifndef API -#error Please specify Operating System API. Supported: API=RTEMS_API -#elif API == RTEMS_API -#include -#include -#include -#include -#include -#include - -//include RMAP - -#define opus_main Init2 -#define opus_main_arguments rtems_task_argument - -//Typedefs for RTEMS: //TODO: these are global, shouldn't they have some prefix? -/** - * A typedef to pass options to RTEMS elements. - */ -typedef rtems_option Option_t; -/** - * A typedef to pass attributes to RTEMS elements. - */ -typedef rtems_attribute Attribute_t; -/** - * A typedef for RTEMS task modes. - */ -typedef rtems_mode OpusMode_t; -/** - * A typedef for time intervals. In clock ticks. - */ -typedef rtems_interval Interval_t; -typedef rtems_time_of_day TimeOfDay_t; -typedef rtems_id TaskId_t; -typedef rtems_id PeriodId_t; -typedef rtems_id MutexId_t; -typedef rtems_id MessageQueueId_t; -typedef rtems_name Name_t; - -typedef rtems_task_argument TaskArgument_t; -typedef rtems_task_entry TaskEntry_t; -typedef rtems_task TaskReturn_t; -typedef rtems_task_priority TaskPriority_t; -typedef rtems_isr_entry IsrHandler_t; -typedef rtems_isr IsrReturn_t; -typedef rtems_vector_number InterruptNumber_t; - -/** - * This class contains encapsulates all System Calls to the Operating System. - * It is currently tailored to the RTEMS Operating system, but should in general - * support different OS. - * For more detailed information on the Operating System calls, please refer to the - * RTEMS documentation at www.rtems.org . - */ -class OSAL: public HasReturnvaluesIF { -private: - /** - * A method to convert an OS-specific return code to the frameworks return value concept. - * @param inValue The return code coming from the OS. - * @return The converted return value. - */ - static ReturnValue_t convertReturnCode(uint8_t inValue); -public: - - static const uint8_t INTERFACE_ID = OPERATING_SYSTEM_ABSTRACTION; - //Interrupts: - static const uint32_t INTERRUPT_MASK_REGISTER_ADDRESS = 0x80000240; - //API Status codes: - static const ReturnValue_t SUCCESSFUL = RTEMS_SUCCESSFUL; - static const ReturnValue_t TASK_EXITTED = - MAKE_RETURN_CODE( RTEMS_TASK_EXITTED ); - static const ReturnValue_t MP_NOT_CONFIGURED = - MAKE_RETURN_CODE( RTEMS_MP_NOT_CONFIGURED ); - static const ReturnValue_t INVALID_NAME = - MAKE_RETURN_CODE( RTEMS_INVALID_NAME ); - static const ReturnValue_t INVALID_ID = MAKE_RETURN_CODE( RTEMS_INVALID_ID ); - static const ReturnValue_t TOO_MANY = MAKE_RETURN_CODE( RTEMS_TOO_MANY ); - static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE( RTEMS_TIMEOUT ); - static const ReturnValue_t OBJECT_WAS_DELETED = - MAKE_RETURN_CODE( RTEMS_OBJECT_WAS_DELETED ); - static const ReturnValue_t INVALID_SIZE = - MAKE_RETURN_CODE( RTEMS_INVALID_SIZE ); - static const ReturnValue_t INVALID_ADDRESS = - MAKE_RETURN_CODE( RTEMS_INVALID_ADDRESS ); - static const ReturnValue_t INVALID_NUMBER = - MAKE_RETURN_CODE( RTEMS_INVALID_NUMBER ); - static const ReturnValue_t NOT_DEFINED = - MAKE_RETURN_CODE( RTEMS_NOT_DEFINED ); - static const ReturnValue_t RESOURCE_IN_USE = - MAKE_RETURN_CODE( RTEMS_RESOURCE_IN_USE ); - static const ReturnValue_t UNSATISFIED = - MAKE_RETURN_CODE( RTEMS_UNSATISFIED ); - static const ReturnValue_t QUEUE_EMPTY = - MAKE_RETURN_CODE( RTEMS_UNSATISFIED ); - static const ReturnValue_t INCORRECT_STATE = - MAKE_RETURN_CODE( RTEMS_INCORRECT_STATE ); - static const ReturnValue_t ALREADY_SUSPENDED = - MAKE_RETURN_CODE( RTEMS_ALREADY_SUSPENDED ); - static const ReturnValue_t ILLEGAL_ON_SELF = - MAKE_RETURN_CODE( RTEMS_ILLEGAL_ON_SELF ); - static const ReturnValue_t ILLEGAL_ON_REMOTE_OBJECT = - MAKE_RETURN_CODE( RTEMS_ILLEGAL_ON_REMOTE_OBJECT ); - static const ReturnValue_t CALLED_FROM_ISR = - MAKE_RETURN_CODE( RTEMS_CALLED_FROM_ISR ); - static const ReturnValue_t INVALID_PRIORITY = - MAKE_RETURN_CODE( RTEMS_INVALID_PRIORITY ); - static const ReturnValue_t INVALID_CLOCK = - MAKE_RETURN_CODE( RTEMS_INVALID_CLOCK ); - static const ReturnValue_t INVALID_NODE = - MAKE_RETURN_CODE( RTEMS_INVALID_NODE ); - static const ReturnValue_t NOT_CONFIGURED = - MAKE_RETURN_CODE( RTEMS_NOT_CONFIGURED ); - static const ReturnValue_t NOT_OWNER_OF_RESOURCE = - MAKE_RETURN_CODE( RTEMS_NOT_OWNER_OF_RESOURCE ); - static const ReturnValue_t NOT_IMPLEMENTED = - MAKE_RETURN_CODE( RTEMS_NOT_IMPLEMENTED ); - static const ReturnValue_t INTERNAL_ERROR = - MAKE_RETURN_CODE( RTEMS_INTERNAL_ERROR ); - static const ReturnValue_t NO_MEMORY = MAKE_RETURN_CODE( RTEMS_NO_MEMORY ); - static const ReturnValue_t IO_ERROR = MAKE_RETURN_CODE( RTEMS_IO_ERROR ); - //API options: - static const Option_t DEFAULT_OPTIONS = RTEMS_DEFAULT_OPTIONS; - static const Option_t WAIT = RTEMS_WAIT; - static const Option_t NO_WAIT = RTEMS_NO_WAIT; - static const Option_t EVENT_ALL = RTEMS_EVENT_ALL; - static const Option_t EVENT_ANY = RTEMS_EVENT_ANY; - //API Attributes: - static const Attribute_t DEFAULT_ATTRIBUTES = RTEMS_DEFAULT_ATTRIBUTES; - static const Attribute_t LOCAL = RTEMS_LOCAL; - static const Attribute_t GLOBAL = RTEMS_GLOBAL; - static const Attribute_t FIFO = RTEMS_FIFO; - static const Attribute_t PRIORITY = RTEMS_PRIORITY; - static const Attribute_t NO_FLOATING_POINT = RTEMS_NO_FLOATING_POINT; - static const Attribute_t FLOATING_POINT = RTEMS_FLOATING_POINT; - //API Modes: - static const OpusMode_t ALL_MODE_MASKS = RTEMS_ALL_MODE_MASKS; - static const OpusMode_t DEFAULT_MODES = RTEMS_DEFAULT_MODES; - static const OpusMode_t CURRENT_MODE = RTEMS_CURRENT_MODE; - static const OpusMode_t PREEMPT = RTEMS_PREEMPT; - static const OpusMode_t NO_PREEMPT = RTEMS_NO_PREEMPT; - static const OpusMode_t NO_TIMESLICE = RTEMS_NO_TIMESLICE; - static const OpusMode_t TIMESLICE = RTEMS_TIMESLICE; - static const OpusMode_t ASR = RTEMS_ASR; - static const OpusMode_t NO_ASR = RTEMS_NO_ASR; - //API Time and Timing - static const Interval_t MILISECOND_WAIT = 1; - static const Interval_t NO_TIMEOUT = RTEMS_NO_TIMEOUT; - static const TaskId_t TASK_MYSELF = RTEMS_SELF; - static const size_t MINIMUM_STACK_SIZE = RTEMS_MINIMUM_STACK_SIZE; - /** - * This is a helper method to build a qualified name out of single characters - * @param c1 The first character - * @param c2 The second character - * @param c3 The third character - * @param c4 The fourth character - * @return A name suitable for use for the Operating System - */ - static Name_t buildName(uint8_t c1, uint8_t c2, uint8_t c3, uint8_t c4); - /** - * This method returns the number of clock ticks per second. - * In RTEMS, this is typically 1000. - * @return The number of ticks. - */ - static Interval_t getTicksPerSecond(void); - /** - * This system call sets the system time. - * To set the time, it uses a TimeOfDay_t struct. - * @param time The struct with the time settings to set. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t setClock(TimeOfDay_t* time); - /** - * This system call sets the system time. - * To set the time, it uses a timeval struct. - * @param time The struct with the time settings to set. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t setClock(timeval* time); - /** - * This system call returns the current system clock in timeval format. - * The timval format has the fields \c tv_sec with seconds and \c tv_usec with - * microseconds since an OS-defined epoch. - * @param time A pointer to a timeval struct where the current time is stored. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t getClock_timeval(timeval* time); - - /** - * Get the time since boot in a timeval struct - * - * @param[out] time A pointer to a timeval struct where the uptime is stored. - * @return\c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t getUptime(timeval* uptime); - - /** - * Get the time since boot in milliseconds - * - * This value can overflow! Still, it can be used to calculate time intervalls - * between two calls up to 49 days by always using uint32_t in the calculation - * - * @param ms uptime in ms - * @return RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t getUptime(uint32_t* uptimeMs); - - /** - * Returns the time in microseconds since an OS-defined epoch. - * The time is returned in a 64 bit unsigned integer. - * @param time A pointer to a 64 bit unisigned integer where the data is stored. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t getClock_usecs(uint64_t* time); - /** - * Returns the time in a TimeOfDay_t struct. - * @param time A pointer to a TimeOfDay_t struct. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t getDateAndTime(TimeOfDay_t* time); - /** - * Converts a time of day struct to POSIX seconds. - * @param time The time of day as input - * @param timeval The corresponding seconds since the epoch. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to); - /** - * Commands the calling task to sleep for a certain number of clock ticks. - * Typically other tasks are executed then. - * @param ticks The number of clock ticks to sleep. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t sleepFor(Interval_t ticks); - - /** - * With this call, a new task is created. - * The task is created (its resources are acquired), but it is not started. - * @param name A name as specified in the OS. - * @param initial_priority The task's priority. Ranging from 0 (lowest) to 99 (highest). - * @param stack_size The stack size reserved for this task. - * @param initial_modes Options for the task's mode (preemptible, time slicing, etc..) - * @param attribute_set Options for the task's attributes (floating point, local/global) - * @param id The OS returns the task id, that uniquely identifies the task. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t createTask(Name_t name, - TaskPriority_t initial_priority, size_t stack_size, - OpusMode_t initial_modes, Attribute_t attribute_set, TaskId_t *id); - /** - * Finds a task with the help of its name. - * @param name Name of the task to find - * @param id The OS returns the task id, that uniquely identifies the task. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t findTask(Name_t name, TaskId_t *id); - /** - * Starts a task. - * The task immediately starts running. - * @param id The task id. - * @param entry_point A pointer to the (static) method that is executed by the task. - * @param argument One argument (a void* pointer) may be passed to the task. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t startTask(TaskId_t *id, TaskEntry_t entry_point, - TaskArgument_t argument); - /** - * With this call, tasks are deleted from the system - * @param id The task id. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t deleteTask(TaskId_t *id); - /** - * Checks if the current executing context is an ISR. - * @return true if handling an interrupt, false else. - */ - static bool isInterruptInProgress(); - /** - * An task is not executed periodically by default. - * This is activated with this call. This is managed internally. - * @param period The task's period in clock ticks. - * @param[out] periodId The newly created period's id - * @param name optional name for the period - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t setAndStartPeriod(Interval_t period, PeriodId_t *periodId, Name_t name = (('P' << 24) + ('e' << 16) + ('r' << 8) + 'd')); - /** - * This call must be made in a periodic task, when activities of one cycle are finished. - * This is managed internally. - * @param periodId Id of the period as returned by setAndStartPeriod() - * @param period The period duration for the next cycle. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t checkAndRestartPeriod(PeriodId_t periodId, Interval_t period); - /** - * This call deletes the period. - * This is managed internally. - * @param id Pointer to the task identifier the period belongs to. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t deletePeriod(TaskId_t *id); - /** - * With this call the period statistics (and therefore the periodic task - * statistics) are printed to the screen. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t reportPeriodStatistics(); - - /** - * With this call, a new message queue is created. - * @param name A qualified name for the message queue. - * @param count Number of messages the queue can store before it rejects new messages. - * @param max_message_size Maximum size of a single message. - * @param attribute_set Attributes for the message queue (fifo/priority, local/global) - * @param id A unique message queue identifier returned by the OS. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t createMessageQueue(Name_t name, uint32_t count, - size_t max_message_size, Attribute_t attribute_set, - MessageQueueId_t *id); - /** - * Returns a message queue id by its name. - * @param name The queue's name. - * @param id A pointer to the queue id to return to. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t findMessageQueue(Name_t name, MessageQueueId_t *id); - /** - * Sends a message to the queue given by id. - * @param id Id of the queue to send to - * @param buffer A pointer to any kind of data to send over the queue. - * @param size Size of the data to send. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t sendMessage(MessageQueueId_t id, const void *buffer, - size_t size); - /** - * Checks, if a message was received by a queue with identifier id. - * @param id The id of the checked task. - * @param buffer Pointer to the buffer to store to. - * @param bufSize Maximum size of the buffer. - * @param recSize The actual message size is returned here. - * @param option_set Specifies, if the task waits for a message (WAIT/ NO_WAIT). - * @param timeout If the task waits, this interval specifies how long (in clock ticks). - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t receiveMessage(MessageQueueId_t id, void *buffer, - size_t bufSize, size_t *recSize, Option_t option_set, - Interval_t timeout); - /** - * Deletes all pending messages in a certain queue. - * @param id Id of the queue to flush - * @param count Number of flushed messages. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t flushMessageQueue( MessageQueueId_t id, uint32_t* count ); - /** - * Deletes a message queue from the system. - * @param id Id of the queue to delete. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t deleteMessageQueue(MessageQueueId_t *id); - - /** - * Creates a new mutual exclusive lock (or semaphore). - * With these locks, concurrent access to system resources (data pool, ...) can be - * controlled. - * @param name A qualified name for the mutex. - * @param id The mutex's id as returned by the OS. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t createMutex(Name_t name, MutexId_t *id); - /** - * Deletes the mutex identified by id. - * @param id Id of the mutex to delete. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t deleteMutex(MutexId_t *id); - /** - * With this call, a task tries to acquire the mutex. - * Must be used in conjunction with unlockMutex. - * @param id Id of the mutex to acquire. - * @param timeout Specifies how long a task waits for the mutex. Default is NO_TIMEOUT. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t lockMutex(MutexId_t *id, Interval_t timeout); - /** - * Releases a mutex. - * Must be used in conjunction with lockMutex. - * @param id Id of the mutex to release. - * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. - */ - static ReturnValue_t unlockMutex(MutexId_t *id); - /** - * 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 ); - /** - * 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 enableInterrupt( 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 disableInterrupt( InterruptNumber_t interrupt ); -}; - -#endif /* API */ -#endif /* OSAL_H_ */ diff --git a/osal/OperatingSystemIF.h b/osal/OperatingSystemIF.h new file mode 100644 index 00000000..7e7948f6 --- /dev/null +++ b/osal/OperatingSystemIF.h @@ -0,0 +1,144 @@ +#ifndef FRAMEWORK_OSAL_OPERATINGSYSTEMIF_H_ +#define FRAMEWORK_OSAL_OPERATINGSYSTEMIF_H_ + +#include + +class OperatingSystemIF { +public: + static const uint8_t INTERFACE_ID = CLASS_ID::OPERATING_SYSTEM_ABSTRACTION; + + //API Status codes, must be implemented by the Operating System (TODO comments based on rtems status.h): + + /** + * This is the status to indicate successful completion. + */ + static const ReturnValue_t SUCCESSFUL = MAKE_RETURN_CODE(0); + /** + * This is the status to indicate that a thread exited. + */ + static const ReturnValue_t TASK_EXITTED = MAKE_RETURN_CODE(1); + /** + * This is the status to indicate multiprocessing is not configured. + */ + static const ReturnValue_t MP_NOT_CONFIGURED = MAKE_RETURN_CODE(2); + /** + * This is the status to indicate that the object name was invalid. + */ + static const ReturnValue_t INVALID_NAME = MAKE_RETURN_CODE(3); + /** + * This is the status to indicate that the object Id was invalid. + */ + static const ReturnValue_t INVALID_ID = MAKE_RETURN_CODE(4); + /** + * This is the status to indicate you have attempted to create too many + * instances of a particular object class. + * + * Used for full messages Queues as well + */ + static const ReturnValue_t TOO_MANY = MAKE_RETURN_CODE(5); + /** + * This is the status to indicate that a blocking directive timed out. + */ + static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE(6); + /** + * This is the status to indicate the the object was deleted + * while the task was blocked waiting. + */ + static const ReturnValue_t OBJECT_WAS_DELETED = MAKE_RETURN_CODE(7); + /** + * This is the status to indicate that the specified size was invalid. + */ + static const ReturnValue_t INVALID_SIZE = MAKE_RETURN_CODE(8); + /** + * This is the status to indicate that the specified address is invalid. + */ + static const ReturnValue_t INVALID_ADDRESS = MAKE_RETURN_CODE(9); + /** + * This is the status to indicate that the specified number was invalid. + */ + static const ReturnValue_t INVALID_NUMBER = MAKE_RETURN_CODE(10); + /** + * This is the status to indicate that the item has not been initialized. + */ + static const ReturnValue_t NOT_DEFINED =MAKE_RETURN_CODE(11); + /** + * This is the status to indicate that the object still has + * resources in use. + */ + static const ReturnValue_t RESOURCE_IN_USE =MAKE_RETURN_CODE(12); + /** + * This is the status to indicate that the request was not satisfied. + */ + static const ReturnValue_t UNSATISFIED =MAKE_RETURN_CODE(13); + /** + * Indicates that a Message Queue is empty (unable to allocate it) + */ + static const ReturnValue_t QUEUE_EMPTY =MAKE_RETURN_CODE(14); + /** + * This is the status to indicate that a thread is in wrong state + * was in the wrong execution state for the requested operation. + */ + static const ReturnValue_t INCORRECT_STATE =MAKE_RETURN_CODE(15); + /** + * This is the status to indicate thread was already suspended. + */ + static const ReturnValue_t ALREADY_SUSPENDED = MAKE_RETURN_CODE(16); + /** + * This is the status to indicate that the operation is illegal + * on calling thread. + */ + static const ReturnValue_t ILLEGAL_ON_SELF =MAKE_RETURN_CODE(17); + /** + * This is the status to indicate illegal for remote object. + */ + static const ReturnValue_t ILLEGAL_ON_REMOTE_OBJECT=MAKE_RETURN_CODE(18); + /** + * This is the status to indicate that the operation should not be + * called from from this excecution environment. + */ + static const ReturnValue_t CALLED_FROM_ISR=MAKE_RETURN_CODE(19); + /** + * This is the status to indicate that an invalid thread priority + * was provided. + */ + static const ReturnValue_t INVALID_PRIORITY=MAKE_RETURN_CODE(20); + /** + * This is the status to indicate that the specified date/time was invalid. + */ + static const ReturnValue_t INVALID_CLOCK=MAKE_RETURN_CODE(21); + /** + * This is the status to indicate that the specified node Id was invalid. + */ + static const ReturnValue_t INVALID_NODE=MAKE_RETURN_CODE(22); + /** + * This is the status to indicate that the directive was not configured. + */ + static const ReturnValue_t NOT_CONFIGURED=MAKE_RETURN_CODE(23); + /** + * This is the status to indicate that the caller is not the + * owner of the resource. + */ + static const ReturnValue_t NOT_OWNER_OF_RESOURCE=MAKE_RETURN_CODE(24); + /** + * This is the status to indicate the the directive or requested + * portion of the directive is not implemented. + */ + static const ReturnValue_t NOT_IMPLEMENTED=MAKE_RETURN_CODE(25); + /** + * This is the status to indicate that an internal RTEMS inconsistency + * was detected. + */ + static const ReturnValue_t INTERNAL_ERROR=MAKE_RETURN_CODE(26); + /** + * This is the status to indicate that the directive attempted to allocate + * memory but was unable to do so. + */ + static const ReturnValue_t NO_MEMORY=MAKE_RETURN_CODE(27); + /** + * This is the status to indicate an driver IO error. + */ + static const ReturnValue_t IO_ERROR=MAKE_RETURN_CODE(28); + + virtual ~OperatingSystemIF() {}; +}; +#endif /* FRAMEWORK_OSAL_OPERATINGSYSTEMIF_H_ */ diff --git a/osal/rtems/Clock.cpp b/osal/rtems/Clock.cpp new file mode 100644 index 00000000..af7ea2ee --- /dev/null +++ b/osal/rtems/Clock.cpp @@ -0,0 +1,145 @@ +#include +#include "RtemsBasic.h" + +uint16_t Clock::leapSeconds = 0; +MutexIF* Clock::timeMutex = NULL; + +uint32_t Clock::getTicksPerSecond(void){ + rtems_interval ticks_per_second; + (void) rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second); + return ticks_per_second; +} + +ReturnValue_t Clock::setClock(const TimeOfDay_t* time) { + //We need to cast to rtems internal time of day type here. Both structs have the same structure + //rtems provides no const guarantee, so we need to cast the const away + //TODO Check if this can be done safely + rtems_time_of_day* timeRtems = reinterpret_cast(const_cast(time)); + rtems_status_code status = rtems_clock_set(timeRtems); + return RtemsBasic::convertReturnCode(status); +} + +ReturnValue_t Clock::setClock(const timeval* time) { + timespec newTime; + newTime.tv_sec = time->tv_sec; + newTime.tv_nsec = time->tv_usec * TOD_NANOSECONDS_PER_MICROSECOND; + //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 + _TOD_Set(&newTime); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::getClock_timeval(timeval* time) { + rtems_status_code status = rtems_clock_get_tod_timeval(time); + return RtemsBasic::convertReturnCode(status); +} + +ReturnValue_t Clock::getUptime(timeval* uptime) { + timespec time; + rtems_status_code status = rtems_clock_get_uptime(&time); + uptime->tv_sec = time.tv_sec; + time.tv_nsec = time.tv_nsec / 1000; + uptime->tv_usec = time.tv_nsec; + return RtemsBasic::convertReturnCode(status); +} + +ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) { + *uptimeMs = rtems_clock_get_ticks_since_boot(); + return RtemsBasic::convertReturnCode(RTEMS_SUCCESSFUL); +} + +ReturnValue_t Clock::getClock_usecs(uint64_t* time) { + timeval temp_time; + rtems_status_code returnValue = rtems_clock_get_tod_timeval(&temp_time); + *time = ((uint64_t) temp_time.tv_sec * 1000000) + temp_time.tv_usec; + return RtemsBasic::convertReturnCode(returnValue); +} + +ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) { + rtems_time_of_day* timeRtems = reinterpret_cast(time); + rtems_status_code status = rtems_clock_get_tod(timeRtems); + return RtemsBasic::convertReturnCode(status); +} + +ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, + timeval* to) { + //Fails in 2038.. + const rtems_time_of_day* timeRtems = reinterpret_cast(from); + to->tv_sec = _TOD_To_seconds(timeRtems); + to->tv_usec = timeRtems->ticks * 1000; + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) { + *JD2000 = (time.tv_sec - 946728000. + time.tv_usec / 1000000.) / 24. + / 3600.; + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) { + //SHOULDDO: works not for dates in the past (might have less leap seconds) + if (timeMutex == NULL) { + return HasReturnvaluesIF::RETURN_FAILED; + } + + uint16_t leapSeconds; + ReturnValue_t result = getLeapSeconds(&leapSeconds); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + timeval leapSeconds_timeval = { 0, 0 }; + leapSeconds_timeval.tv_sec = leapSeconds; + + //initial offset between UTC and TAI + timeval UTCtoTAI1972 = { 10, 0 }; + + timeval TAItoTT = { 32, 184000 }; + + *tt = utc + leapSeconds_timeval + UTCtoTAI1972 + TAItoTT; + + return HasReturnvaluesIF::RETURN_OK; +} + +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; + } + + leapSeconds = leapSeconds_; + + result = timeMutex->unlockMutex(); + return result; +} + +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; + } + + *leapSeconds_ = leapSeconds; + + result = timeMutex->unlockMutex(); + return result; +} + +ReturnValue_t Clock::checkOrCreateClockMutex(){ + if(timeMutex==NULL){ + MutexFactory* mutexFactory = MutexFactory::instance(); + if (mutexFactory == NULL) { + return HasReturnvaluesIF::RETURN_FAILED; + } + timeMutex = mutexFactory->createMutex(); + if (timeMutex == NULL) { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/osal/rtems/InitTask.cpp b/osal/rtems/InitTask.cpp new file mode 100644 index 00000000..fe48e8d9 --- /dev/null +++ b/osal/rtems/InitTask.cpp @@ -0,0 +1,27 @@ +#include "InitTask.h" +#include "RtemsBasic.h" + + + +InitTask::InitTask() { +} + +InitTask::~InitTask() { +} + +void InitTask::deleteTask(){ + rtems_task_delete(RTEMS_SELF); +} + +ReturnValue_t InitTask::startTask() { + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t InitTask::sleepFor(uint32_t ms) { + rtems_status_code status = rtems_task_wake_after(RtemsBasic::convertMsToTicks(ms)); + return RtemsBasic::convertReturnCode(status); +} + +uint32_t InitTask::getPeriodMs() const { + return 0; +} diff --git a/osal/rtems/InitTask.h b/osal/rtems/InitTask.h new file mode 100644 index 00000000..121734e5 --- /dev/null +++ b/osal/rtems/InitTask.h @@ -0,0 +1,28 @@ +#ifndef OS_RTEMS_INITTASK_H_ +#define OS_RTEMS_INITTASK_H_ + +#include + +//TODO move into static function in TaskIF + +/** + * The init task is created automatically by RTEMS. + * As one may need to control it (e.g. suspending it for a while), + * this dummy class provides an implementation of TaskIF to do so. + * Warning: The init task is deleted with this stub, i.e. the destructor + * calls rtems_task_delete(RTEMS_SELF) + */ +class InitTask: public PeriodicTaskIF { +public: + InitTask(); + virtual ~InitTask(); + ReturnValue_t startTask(); + + ReturnValue_t sleepFor(uint32_t ms); + + uint32_t getPeriodMs() const; + + void deleteTask(); +}; + +#endif /* OS_RTEMS_INITTASK_H_ */ diff --git a/osal/InternalErrorCodes.cpp b/osal/rtems/InternalErrorCodes.cpp similarity index 100% rename from osal/InternalErrorCodes.cpp rename to osal/rtems/InternalErrorCodes.cpp diff --git a/osal/rtems/Interrupt.cpp b/osal/rtems/Interrupt.cpp new file mode 100644 index 00000000..b6277499 --- /dev/null +++ b/osal/rtems/Interrupt.cpp @@ -0,0 +1,70 @@ +#include "Interrupt.h" +#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); + return RtemsBasic::convertReturnCode(status); +} + +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 new file mode 100644 index 00000000..c4c21911 --- /dev/null +++ b/osal/rtems/Interrupt.h @@ -0,0 +1,50 @@ +#ifndef OS_RTEMS_INTERRUPT_H_ +#define OS_RTEMS_INTERRUPT_H_ + +#include +#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 new file mode 100644 index 00000000..4f8198dd --- /dev/null +++ b/osal/rtems/MessageQueue.cpp @@ -0,0 +1,116 @@ +#include +#include "MessageQueue.h" +#include "RtemsBasic.h" + +MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size) : + id(0), lastPartner(0), defaultDestination(NO_QUEUE), internalErrorReporter(NULL) { + rtems_name name = ('Q' << 24) + (queueCounter++ << 8); + 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 + << name << std::dec << " failed with status:" + << (uint32_t) status << std::endl; + this->id = 0; + } +} + +MessageQueue::~MessageQueue() { + rtems_message_queue_delete(id); +} + +ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, + MessageQueueMessage* message, bool ignoreFault) { + return sendMessage(sendTo, message, this->getId(), ignoreFault); +} + +ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message) { + return sendToDefault(message, this->getId()); +} + +ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) { + if (this->lastPartner != 0) { + return sendMessage(this->lastPartner, message, this->getId()); + } else { + //TODO: Good returnCode + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message, + MessageQueueId_t* receivedFrom) { + ReturnValue_t status = this->receiveMessage(message); + *receivedFrom = this->lastPartner; + return status; +} + +ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) { + rtems_status_code status = rtems_message_queue_receive(id, + message->getBuffer(), &(message->messageSize), + RTEMS_NO_WAIT, 1); + if (status == RTEMS_SUCCESSFUL) { + this->lastPartner = message->getSender(); + //Check size of incoming message. + if (message->messageSize < 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); + } + return RtemsBasic::convertReturnCode(status); +} + +MessageQueueId_t MessageQueue::getLastPartner() const { + return this->lastPartner; +} + +ReturnValue_t MessageQueue::flush(uint32_t* count) { + rtems_status_code status = rtems_message_queue_flush(id, count); + return RtemsBasic::convertReturnCode(status); +} + +MessageQueueId_t MessageQueue::getId() const { + return this->id; +} + +void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) { + this->defaultDestination = defaultDestination; +} + +ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, + MessageQueueMessage* message, MessageQueueId_t sentFrom, + bool ignoreFault) { + + message->setSender(sentFrom); + rtems_status_code result = rtems_message_queue_send(sendTo, + message->getBuffer(), message->messageSize); + + //TODO: Check if we're in ISR. + if (result != RTEMS_SUCCESSFUL && !ignoreFault) { + if (internalErrorReporter == NULL) { + internalErrorReporter = objectManager->get( + objects::INTERNAL_ERROR_REPORTER); + } + if (internalErrorReporter != NULL) { + internalErrorReporter->queueMessageNotSent(); + } + } + return result; +} + +ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message, + MessageQueueId_t sentFrom, bool ignoreFault) { + return sendMessage(defaultDestination, message, sentFrom, ignoreFault); +} + +MessageQueueId_t MessageQueue::getDefaultDestination() const { + return this->defaultDestination; +} + +bool MessageQueue::isDefaultDestinationSet() const { + return (defaultDestination != NO_QUEUE); +} + +uint16_t MessageQueue::queueCounter = 0; diff --git a/ipc/MessageQueue.h b/osal/rtems/MessageQueue.h similarity index 66% rename from ipc/MessageQueue.h rename to osal/rtems/MessageQueue.h index 6df8cca8..0a8805ef 100644 --- a/ipc/MessageQueue.h +++ b/osal/rtems/MessageQueue.h @@ -10,7 +10,9 @@ #ifndef MESSAGEQUEUE_H_ #define MESSAGEQUEUE_H_ -#include +#include +#include +#include /** * @brief This class manages sending and receiving of message queue messages. @@ -28,23 +30,7 @@ * use of the operating system calls provided. * \ingroup message_queue */ -class MessageQueue : public MessageQueueSender { -private: - /** - * @brief The class stores the queue id it got assigned from the operating system in this attribute. - * If initialization fails, the queue id is set to zero. - */ - MessageQueueId_t id; - /** - * @brief In this attribute, the queue id of the last communication partner is stored - * to allow for replying. - */ - MessageQueueId_t lastPartner; - /** - * @brief The message queue's name -a user specific information for the operating system- is - * generated automatically with the help of this static counter. - */ - static uint16_t queueCounter; +class MessageQueue : public MessageQueueIF { public: /** * @brief The constructor initializes and configures the message queue. @@ -70,8 +56,10 @@ public: * queue id as "sentFrom" parameter. * @param sendTo This parameter specifies the message queue id of the destination message queue. * @param message A pointer to a previously created message, which is sent. + * @param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. */ - ReturnValue_t sendMessage( MessageQueueId_t sendTo, MessageQueueMessage* message ); + ReturnValue_t sendMessage(MessageQueueId_t sendTo, + MessageQueueMessage* message, bool ignoreFault = false ); /** * @brief This operation sends a message to the default destination. * @details As in the sendMessage method, this function uses the sendToDefault call of the @@ -116,12 +104,71 @@ public: /** * @brief This method returns the message queue id of the last communication partner. */ - MessageQueueId_t getLastPartner(); + MessageQueueId_t getLastPartner() const; /** * @brief This method returns the message queue id of this class's message queue. */ MessageQueueId_t getId() const; + /** + * \brief With the sendMessage call, a queue message is sent to a receiving queue. + * \details This method takes the message provided, adds the sentFrom information and passes + * it on to the destination provided with an operating system call. The OS's return + * value is returned. + * \param sendTo This parameter specifies the message queue id to send the message to. + * \param message This is a pointer to a previously created message, which is sent. + * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. + * This variable is set to zero by default. + * \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. + */ + virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ); + /** + * \brief The sendToDefault method sends a queue message to the default destination. + * \details In all other aspects, it works identical to the sendMessage method. + * \param message This is a pointer to a previously created message, which is sent. + * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. + * This variable is set to zero by default. + */ + virtual ReturnValue_t sendToDefault( MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ); + /** + * \brief This method is a simple setter for the default destination. + */ + void setDefaultDestination(MessageQueueId_t defaultDestination); + /** + * \brief This method is a simple getter for the default destination. + */ + MessageQueueId_t getDefaultDestination() const; + bool isDefaultDestinationSet() const; +private: + /** + * @brief The class stores the queue id it got assigned from the operating system in this attribute. + * If initialization fails, the queue id is set to zero. + */ + MessageQueueId_t id; + /** + * @brief In this attribute, the queue id of the last communication partner is stored + * to allow for replying. + */ + MessageQueueId_t lastPartner; + /** + * @brief The message queue's name -a user specific information for the operating system- is + * generated automatically with the help of this static counter. + */ + /** + * \brief This attribute stores a default destination to send messages to. + * \details It is stored to simplify sending to always-the-same receiver. The attribute may + * be set in the constructor or by a setter call to setDefaultDestination. + */ + MessageQueueId_t defaultDestination; + + /** + * \brief This attribute stores a reference to the internal error reporter for reporting full queues. + * \details In the event of a full destination queue, the reporter will be notified. The reference is set + * by lazy loading + */ + InternalErrorReporterIF *internalErrorReporter; + + static uint16_t queueCounter; }; #endif /* MESSAGEQUEUE_H_ */ diff --git a/osal/rtems/MultiObjectTask.cpp b/osal/rtems/MultiObjectTask.cpp new file mode 100644 index 00000000..af853cb3 --- /dev/null +++ b/osal/rtems/MultiObjectTask.cpp @@ -0,0 +1,90 @@ +/** + * @file MultiObjectTask.cpp + * @brief This file defines the MultiObjectTask class. + * @date 30.01.2014 + * @author baetz + */ + +#include +#include +#include "MultiObjectTask.h" + +MultiObjectTask::MultiObjectTask(const char *name, rtems_task_priority setPriority, + size_t setStack, rtems_interval setPeriod, void (*setDeadlineMissedFunc)()) : + TaskBase(setPriority, setStack, name), periodTicks( + RtemsBasic::convertMsToTicks(setPeriod)), periodId(0), deadlineMissedFunc( + setDeadlineMissedFunc) { + rtems_name periodName = (('P' << 24) + ('e' << 16) + ('r' << 8) + 'd'); + rtems_status_code status = rtems_rate_monotonic_create(periodName, + &periodId); + if (status != RTEMS_SUCCESSFUL) { + error << "ObjectTask::period create failed with status " << status + << std::endl; + } +} + +MultiObjectTask::~MultiObjectTask(void) { + //Do not delete objects, we were responsible for ptrs only. + rtems_rate_monotonic_delete(periodId); +} +rtems_task MultiObjectTask::taskEntryPoint(rtems_task_argument argument) { + //The argument is re-interpreted as MultiObjectTask. The Task object is global, so it is found from any place. + MultiObjectTask *originalTask(reinterpret_cast(argument)); + originalTask->taskFunctionality(); +} + +ReturnValue_t MultiObjectTask::startTask() { + rtems_status_code status = rtems_task_start(id, MultiObjectTask::taskEntryPoint, + rtems_task_argument((void *) this)); + if (status != RTEMS_SUCCESSFUL) { + error << "ObjectTask::startTask for " << std::hex << this->getId() + << std::dec << " failed." << std::endl; + } + return RtemsBasic::convertReturnCode(status); +} + +ReturnValue_t MultiObjectTask::sleepFor(uint32_t ms) { + return TaskBase::sleepFor(ms); +} + +void MultiObjectTask::taskFunctionality() { + //The +1 is necessary to avoid a call with period = 0, which does not start the period. + rtems_status_code status = rtems_rate_monotonic_period(periodId, + periodTicks + 1); + if (status != RTEMS_SUCCESSFUL) { + error << "ObjectTask::period start failed with status " << status + << std::endl; + return; + } + //The task's "infinite" inner loop is entered. + while (1) { + for (ObjectList::iterator it = objectList.begin(); + it != objectList.end(); ++it) { + (*it)->performOperation(); + } + status = rtems_rate_monotonic_period(periodId, periodTicks + 1); + if (status == RTEMS_TIMEOUT) { + char nameSpace[8] = { 0 }; + char* ptr = rtems_object_get_name(getId(), sizeof(nameSpace), + nameSpace); + error << "ObjectTask: " << ptr << " Deadline missed." << std::endl; + if (this->deadlineMissedFunc != NULL) { + this->deadlineMissedFunc(); + } + } + } +} + +ReturnValue_t MultiObjectTask::addComponent(object_id_t object) { + ExecutableObjectIF* newObject = objectManager->get( + object); + if (newObject == NULL) { + return HasReturnvaluesIF::RETURN_FAILED; + } + objectList.push_back(newObject); + return HasReturnvaluesIF::RETURN_OK; +} + +uint32_t MultiObjectTask::getPeriodMs() const { + return RtemsBasic::convertTicksToMs(periodTicks); +} diff --git a/tasks/MultiObjectTask.h b/osal/rtems/MultiObjectTask.h similarity index 83% rename from tasks/MultiObjectTask.h rename to osal/rtems/MultiObjectTask.h index d785cefa..64b09c52 100644 --- a/tasks/MultiObjectTask.h +++ b/osal/rtems/MultiObjectTask.h @@ -8,9 +8,13 @@ #define MULTIOBJECTTASK_H_ #include -#include -#include -#include +#include + +#include "TaskBase.h" +#include + +class ExecutableObjectIF; + /** * @brief This class represents a specialized task for periodic activities of multiple objects. * @@ -20,48 +24,7 @@ * * @ingroup task_handling */ -class MultiObjectTask: public TaskBase { -protected: - typedef std::list ObjectList; //!< Typedef for the List of objects. - /** - * @brief This attribute holds a list of objects to be executed. - */ - ObjectList objectList; - /** - * @brief The period of the task. - * @details The period determines the frequency of the task's execution. It is expressed in clock ticks. - */ - Interval_t period; - /** - * @brief id of the associated OS period - */ - PeriodId_t periodId; - /** - * @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, - * then nothing happens on missing the deadline. The deadline is equal to the next execution - * of the periodic task. - */ - void (*deadlineMissedFunc)(void); - /** - * @brief This is the function executed in the new task's context. - * @details It converts the argument back to the thread object type and copies the class instance - * to the task context. The taskFunctionality method is called afterwards. - * @param A pointer to the task object itself is passed as argument. - */ - static TaskReturn_t taskEntryPoint(TaskArgument_t argument); - /** - * @brief The function containing the actual functionality of the task. - * @details The method sets and starts - * the task's period, then enters a loop that is repeated as long as the isRunning - * attribute is true. Within the loop, all performOperation methods of the added - * objects are called. Afterwards the checkAndRestartPeriod system call blocks the task - * until the next period. - * On missing the deadline, the deadlineMissedFunction is executed. - */ - void taskFunctionality(void); - +class MultiObjectTask: public TaskBase, public PeriodicTaskIF { public: /** * @brief Standard constructor of the class. @@ -78,7 +41,7 @@ public: * @param setDeadlineMissedFunc The function pointer to the deadline missed function * that shall be assigned. */ - MultiObjectTask(const char *name, TaskPriority_t setPriority, size_t setStack, Interval_t setPeriod, + MultiObjectTask(const char *name, rtems_task_priority setPriority, size_t setStack, rtems_interval setPeriod, void (*setDeadlineMissedFunc)()); /** * @brief Currently, the executed object's lifetime is not coupled with the task object's @@ -100,14 +63,51 @@ public: * @param object Id of the object to add. * @return RETURN_OK on success, RETURN_FAILED if the object could not be added. */ - ReturnValue_t addObject(object_id_t object); - /** - * Variant to add objects with known location directly. - * @param object Reference to a persistant executable object. - * @return RETURN_OK on success, RETURN_FAILED if the object could not be added. - */ - ReturnValue_t addObject(ExecutableObjectIF* object); + ReturnValue_t addComponent(object_id_t object); + uint32_t getPeriodMs() const; + + ReturnValue_t sleepFor(uint32_t ms); +protected: + typedef std::vector ObjectList; //!< Typedef for the List of objects. + /** + * @brief This attribute holds a list of objects to be executed. + */ + ObjectList objectList; + /** + * @brief The period of the task. + * @details The period determines the frequency of the task's execution. It is expressed in clock ticks. + */ + rtems_interval periodTicks; + /** + * @brief id of the associated OS period + */ + rtems_id periodId; + /** + * @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, + * then nothing happens on missing the deadline. The deadline is equal to the next execution + * of the periodic task. + */ + void (*deadlineMissedFunc)(void); + /** + * @brief This is the function executed in the new task's context. + * @details It converts the argument back to the thread object type and copies the class instance + * to the task context. The taskFunctionality method is called afterwards. + * @param A pointer to the task object itself is passed as argument. + */ + static rtems_task taskEntryPoint(rtems_task_argument argument); + /** + * @brief The function containing the actual functionality of the task. + * @details The method sets and starts + * the task's period, then enters a loop that is repeated as long as the isRunning + * attribute is true. Within the loop, all performOperation methods of the added + * objects are called. Afterwards the checkAndRestartPeriod system call blocks the task + * until the next period. + * On missing the deadline, the deadlineMissedFunction is executed. + */ + void taskFunctionality(void); }; #endif /* MULTIOBJECTTASK_H_ */ diff --git a/osal/rtems/Mutex.cpp b/osal/rtems/Mutex.cpp new file mode 100644 index 00000000..3f559ad1 --- /dev/null +++ b/osal/rtems/Mutex.cpp @@ -0,0 +1,35 @@ +#include "Mutex.h" +#include + +const uint32_t MutexIF::NO_TIMEOUT = RTEMS_NO_TIMEOUT; +uint8_t Mutex::count = 0; + +Mutex::Mutex() : + mutexId(0) { + rtems_name mutexName = ('M' << 24) + ('T' << 16) + ('X' << 8) + count++; + rtems_status_code status = rtems_semaphore_create(mutexName, 1, + RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY, 0, + &mutexId); + if (status != RTEMS_SUCCESSFUL) { + error << "Mutex: creation with name, id " << mutexName << ", " << mutexId + << " failed with " << status << std::endl; + } +} + +Mutex::~Mutex() { + rtems_status_code status = rtems_semaphore_delete(mutexId); + if (status != RTEMS_SUCCESSFUL) { + error << "Mutex: deletion for id " << mutexId + << " failed with " << status << std::endl; + } +} + +ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) { + rtems_status_code status = rtems_semaphore_obtain(mutexId, RTEMS_WAIT, timeoutMs); + return RtemsBasic::convertReturnCode(status); +} + +ReturnValue_t Mutex::unlockMutex() { + rtems_status_code status = rtems_semaphore_release(mutexId); + return RtemsBasic::convertReturnCode(status); +} diff --git a/osal/rtems/Mutex.h b/osal/rtems/Mutex.h new file mode 100644 index 00000000..19b34e7f --- /dev/null +++ b/osal/rtems/Mutex.h @@ -0,0 +1,18 @@ +#ifndef OS_RTEMS_MUTEX_H_ +#define OS_RTEMS_MUTEX_H_ + +#include +#include "RtemsBasic.h" + +class Mutex : public MutexIF { +public: + Mutex(); + ~Mutex(); + ReturnValue_t lockMutex(uint32_t timeoutMs); + ReturnValue_t unlockMutex(); +private: + rtems_id mutexId; + static uint8_t count; +}; + +#endif /* OS_RTEMS_MUTEX_H_ */ diff --git a/osal/rtems/MutexFactory.cpp b/osal/rtems/MutexFactory.cpp new file mode 100644 index 00000000..d7bd16bc --- /dev/null +++ b/osal/rtems/MutexFactory.cpp @@ -0,0 +1,24 @@ +#include +#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() { +} + +MutexFactory::~MutexFactory() { +} + +MutexFactory* MutexFactory::instance() { + return MutexFactory::factoryInstance; +} + +MutexIF* MutexFactory::createMutex() { + return new Mutex(); +} + +void MutexFactory::deleteMutex(MutexIF* mutex) { + delete mutex; +} diff --git a/osal/rtems/PollingTask.cpp b/osal/rtems/PollingTask.cpp new file mode 100644 index 00000000..c2ad74cd --- /dev/null +++ b/osal/rtems/PollingTask.cpp @@ -0,0 +1,106 @@ +#include +#include "PollingTask.h" + +uint32_t PollingTask::deadlineMissedCount = 0; + +PollingTask::PollingTask(const char *name, rtems_task_priority setPriority, + size_t setStack, uint32_t setOverallPeriod, + void (*setDeadlineMissedFunc)()) : + TaskBase(setPriority, setStack, name), periodId(0), pst( + setOverallPeriod) { + // All additional attributes are applied to the object. + this->deadlineMissedFunc = setDeadlineMissedFunc; + rtems_name periodName = (('P' << 24) + ('e' << 16) + ('r' << 8) + 'd'); + rtems_status_code status = rtems_rate_monotonic_create(periodName, + &periodId); + if (status != RTEMS_SUCCESSFUL) { + error << "PollingTask::period create failed with status " << status + << std::endl; + } +} + +PollingTask::~PollingTask() { +} + +rtems_task PollingTask::taskEntryPoint(rtems_task_argument argument) { + + //The argument is re-interpreted as PollingTask. + PollingTask *originalTask(reinterpret_cast(argument)); + //The task's functionality is called. + originalTask->taskFunctionality(); + 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 + << " deadlines." << std::endl; + } +} + +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() + << std::dec << " failed." << std::endl; + } + return RtemsBasic::convertReturnCode(status); +} + +ReturnValue_t PollingTask::addSlot(object_id_t componentId, uint32_t slotTimeMs, + int8_t executionStep) { + pst.addSlot(componentId, slotTimeMs, executionStep, this); + return HasReturnvaluesIF::RETURN_OK; +} + +uint32_t PollingTask::getPeriodMs() const { + return pst.getLengthMs(); +} + +ReturnValue_t PollingTask::checkSequence() const { + return pst.checkSequence(); +} + +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; + + //The start time for the first entry is read. + rtems_interval interval = RtemsBasic::convertMsToTicks( + (*it)->pollingTimeMs); + //The period is set up and started with the system call. + //The +1 is necessary to avoid a call with period = 0, which does not start the period. + rtems_status_code status = rtems_rate_monotonic_period(periodId, + interval + 1); + if (status != RTEMS_SUCCESSFUL) { + error << "PollingTask::period start failed with status " << status + << std::endl; + return; + } + //The task's "infinite" inner loop is entered. + while (1) { + if (pst.slotFollowsImmediately()) { + //Do nothing + } else { + //The interval for the next polling slot is selected. + interval = this->pst.getIntervalMs(); + //The period is checked and restarted with the new interval. + //If the deadline was missed, the deadlineMissedFunc is called. + status = rtems_rate_monotonic_period(periodId, interval); + if (status == RTEMS_TIMEOUT) { + if (this->deadlineMissedFunc != NULL) { + this->deadlineMissedFunc(); + } + } + } + //The device handler for this slot is executed and the next one is chosen. + this->pst.executeAndAdvance(); + } +} + +ReturnValue_t PollingTask::sleepFor(uint32_t ms){ + return TaskBase::sleepFor(ms); +}; diff --git a/devicehandlers/PollingTask.h b/osal/rtems/PollingTask.h similarity index 51% rename from devicehandlers/PollingTask.h rename to osal/rtems/PollingTask.h index 55d71d86..82ec65a2 100644 --- a/devicehandlers/PollingTask.h +++ b/osal/rtems/PollingTask.h @@ -1,49 +1,57 @@ -/** - * @file PollingTask.h - * - * @brief This file contains the definition for the PollingTask class. - * - * @author Claas Ziemke, Bastian Baetz - * - * @date 17.03.2011 - * - * Copyright 2009,2010, Claas Ziemke - * All rights reserved - * - */ #ifndef POLLINGTASK_H_ #define POLLINGTASK_H_ -#include -#include +#include +#include +#include "TaskBase.h" -/** - * - * @brief This class represents a specialized thread to execute polling sequences. - * - * @image latex seq_PST_dynamic.eps "Sequence diagram of polling sequence operation" width=1@textwidth - * @image html seq_PST_dynamic.png "Sequence diagram of polling sequence operation" - * - * @details The Polling Sequence Table is executed in a task of special type, called PollingTask. - * After creation the polling task initializes the PST and starts taskFunctionality. - * An infinite loop is entered within which the iteration through the PST is done by repetitive calls of - * getInterval() and pollAndAdvance(). - * @ingroup task_handling - */ -class PollingTask: public TaskBase { +class PollingTask: public TaskBase, public FixedTimeslotTaskIF { + public: + /** + * @brief The standard constructor of the class. + * + * @details This is the general constructor of the class. In addition to the TaskBase parameters, + * the following variables are passed: + * + * @param (*setDeadlineMissedFunc)() The function pointer to the deadline missed function that shall be assigned. + * + * @param getPst The object id of the completely initialized polling sequence. + */ + PollingTask( const char *name, rtems_task_priority setPriority, size_t setStackSize, uint32_t overallPeriod, void (*setDeadlineMissedFunc)()); + + /** + * @brief The destructor of the class. + * + * @details The destructor frees all heap memory that was allocated on thread initialization for the PST and + * the device handlers. This is done by calling the PST's destructor. + */ + virtual ~PollingTask( void ); + + ReturnValue_t startTask( void ); + /** + * This static function can be used as #deadlineMissedFunc. + * It counts missedDeadlines and prints the number of missed deadlines every 10th time. + */ + static void missedDeadlineCounter(); + /** + * A helper variable to count missed deadlines. + */ + static uint32_t deadlineMissedCount; + + ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep); + + uint32_t getPeriodMs() const; + + ReturnValue_t checkSequence() const; + + ReturnValue_t sleepFor(uint32_t ms); protected: /** * @brief id of the associated OS period */ - PeriodId_t periodId; + rtems_id periodId; - /** - * @brief This attribute is the pointer to the complete polling sequence table object. - * - * @details The most important attribute of the thread object. - * It holds a pointer to the complete polling sequence table object. - */ - PollingSequence* pst; + FixedSlotSequence pst; /** * @brief This attribute holds a function pointer that is executed when a deadline was missed. @@ -56,60 +64,22 @@ protected: /** * @brief This is the entry point in a new polling thread. * - * @details This method, that is the general entry point in the new thread, is here set to generate + * @details This method, that is the generalOSAL::checkAndRestartPeriod( this->periodId, interval ); entry point in the new thread, is here set to generate * and link the Polling Sequence Table to the thread object and start taskFunctionality() * on success. If operation of the task is ended for some reason, * the destructor is called to free allocated memory. */ - static TaskReturn_t taskEntryPoint( TaskArgument_t argument ); + static rtems_task taskEntryPoint( rtems_task_argument argument ); /** * @brief This function holds the main functionality of the thread. * * * @details Holding the main functionality of the task, this method is most important. - * It links the functionalities provided by PollingSequence with the OS's System Calls + * It links the functionalities provided by FixedSlotSequence with the OS's System Calls * to keep the timing of the periods. */ void taskFunctionality( void ); - -public: - /** - * @brief The standard constructor of the class. - * - * @details This is the general constructor of the class. In addition to the TaskBase parameters, - * the following variables are passed: - * - * @param (*setDeadlineMissedFunc)() The function pointer to the deadline missed function that shall be assigned. - * - * @param getPst The object id of the completely initialized polling sequence. - */ - PollingTask( const char *name, TaskPriority_t setPriority, size_t setStack, void (*setDeadlineMissedFunc)(), object_id_t getPst ); - - /** - * @brief The destructor of the class. - * - * @details The destructor frees all heap memory that was allocated on thread initialization for the PST and - * the device handlers. This is done by calling the PST's destructor. - */ - virtual ~PollingTask( void ); - - /** - * @brief The function to actually start a new task. - * - * @details As described in TaskBase this method invokes the operating systems method to start a new task. - * Entry point is taskEntryPoint(). - */ - ReturnValue_t startTask( void ); - /** - * This static function can be used as #deadlineMissedFunc. - * It counts missedDeadlines and prints the number of missed deadlines every 10th time. - */ - static void missedDeadlineCounter(); - /** - * A helper variable to count missed deadlines. - */ - static uint32_t deadlineMissedCount; }; #endif /* POLLINGTASK_H_ */ diff --git a/osal/rtems/QueueFactory.cpp b/osal/rtems/QueueFactory.cpp new file mode 100644 index 00000000..edb4844d --- /dev/null +++ b/osal/rtems/QueueFactory.cpp @@ -0,0 +1,36 @@ +#include +#include "MessageQueue.h" +#include "RtemsBasic.h" + +QueueFactory* QueueFactory::factoryInstance = NULL; + + +ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, + MessageQueueMessage* message, MessageQueueId_t sentFrom) { + message->setSender(sentFrom); + rtems_status_code result = rtems_message_queue_send(sendTo, message->getBuffer(), + message->messageSize); + return RtemsBasic::convertReturnCode(result); +} + +QueueFactory* QueueFactory::instance() { + if (factoryInstance == NULL) { + factoryInstance = new QueueFactory; + } + return factoryInstance; +} + +QueueFactory::QueueFactory() { +} + +QueueFactory::~QueueFactory() { +} + +MessageQueueIF* QueueFactory::createMessageQueue(uint32_t message_depth, + uint32_t max_message_size) { + return new MessageQueue(message_depth, max_message_size); +} + +void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { + delete queue; +} diff --git a/osal/rtems/RtemsBasic.cpp b/osal/rtems/RtemsBasic.cpp new file mode 100644 index 00000000..0f8c538f --- /dev/null +++ b/osal/rtems/RtemsBasic.cpp @@ -0,0 +1,70 @@ +#include "RtemsBasic.h" + + +ReturnValue_t RtemsBasic::convertReturnCode(rtems_status_code inValue) { + if (inValue == RTEMS_SUCCESSFUL) { + return HasReturnvaluesIF::RETURN_OK; + } else { + switch(inValue){ + case RTEMS_SUCCESSFUL: + return OperatingSystemIF::SUCCESSFUL; + case RTEMS_TASK_EXITTED: + return OperatingSystemIF::TASK_EXITTED; + case RTEMS_MP_NOT_CONFIGURED: + return OperatingSystemIF::MP_NOT_CONFIGURED; + case RTEMS_INVALID_NAME: + return OperatingSystemIF::INVALID_NAME; + case RTEMS_INVALID_ID: + return OperatingSystemIF::INVALID_ID; + case RTEMS_TOO_MANY: + return OperatingSystemIF::TOO_MANY; + case RTEMS_TIMEOUT: + return OperatingSystemIF::TIMEOUT; + case RTEMS_OBJECT_WAS_DELETED: + return OperatingSystemIF::OBJECT_WAS_DELETED; + case RTEMS_INVALID_SIZE: + return OperatingSystemIF::INVALID_SIZE; + case RTEMS_INVALID_ADDRESS: + return OperatingSystemIF::INVALID_ADDRESS; + case RTEMS_INVALID_NUMBER: + return OperatingSystemIF::INVALID_NUMBER; + case RTEMS_NOT_DEFINED: + return OperatingSystemIF::NOT_DEFINED; + case RTEMS_RESOURCE_IN_USE: + return OperatingSystemIF::RESOURCE_IN_USE; + //TODO RTEMS_UNSATISFIED is double mapped for FLP so it will only return Queue_empty and not unsatisfied + case RTEMS_UNSATISFIED: + return OperatingSystemIF::QUEUE_EMPTY; + case RTEMS_INCORRECT_STATE: + return OperatingSystemIF::INCORRECT_STATE; + case RTEMS_ALREADY_SUSPENDED: + return OperatingSystemIF::ALREADY_SUSPENDED; + case RTEMS_ILLEGAL_ON_SELF: + return OperatingSystemIF::ILLEGAL_ON_SELF; + case RTEMS_ILLEGAL_ON_REMOTE_OBJECT: + return OperatingSystemIF::ILLEGAL_ON_REMOTE_OBJECT; + case RTEMS_CALLED_FROM_ISR: + return OperatingSystemIF::CALLED_FROM_ISR; + case RTEMS_INVALID_PRIORITY: + return OperatingSystemIF::INVALID_PRIORITY; + case RTEMS_INVALID_CLOCK: + return OperatingSystemIF::INVALID_CLOCK; + case RTEMS_INVALID_NODE: + return OperatingSystemIF::INVALID_NODE; + case RTEMS_NOT_CONFIGURED: + return OperatingSystemIF::NOT_CONFIGURED; + case RTEMS_NOT_OWNER_OF_RESOURCE: + return OperatingSystemIF::NOT_OWNER_OF_RESOURCE; + case RTEMS_NOT_IMPLEMENTED: + return OperatingSystemIF::NOT_IMPLEMENTED; + case RTEMS_INTERNAL_ERROR: + return OperatingSystemIF::INTERNAL_ERROR; + case RTEMS_NO_MEMORY: + return OperatingSystemIF::NO_MEMORY; + case RTEMS_IO_ERROR: + return OperatingSystemIF::IO_ERROR; + default: + return HasReturnvaluesIF::RETURN_FAILED; + } + } +} diff --git a/osal/rtems/RtemsBasic.h b/osal/rtems/RtemsBasic.h new file mode 100644 index 00000000..37b75f6f --- /dev/null +++ b/osal/rtems/RtemsBasic.h @@ -0,0 +1,39 @@ +#ifndef OS_RTEMS_RTEMSBASIC_H_ +#define OS_RTEMS_RTEMSBASIC_H_ + +#include +#include +extern "C" { +#include +} +#include +#include +#include +#include +#include +#include + + +class RtemsBasic: public OperatingSystemIF { +public: + /** + * A method to convert an OS-specific return code to the frameworks return value concept. + * @param inValue The return code coming from the OS. + * @return The converted return value. + */ + static ReturnValue_t convertReturnCode(rtems_status_code inValue); + + static rtems_interval convertMsToTicks(uint32_t msIn) { + rtems_interval ticks_per_second; + rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second); + return (ticks_per_second * msIn) / 1000; + } + + static rtems_interval convertTicksToMs(rtems_interval ticksIn) { + rtems_interval ticks_per_second; + rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticks_per_second); + return (ticksIn * 1000) / ticks_per_second; + } +}; + +#endif /* OS_RTEMS_RTEMSBASIC_H_ */ diff --git a/osal/rtems/TaskBase.cpp b/osal/rtems/TaskBase.cpp new file mode 100644 index 00000000..178e1c12 --- /dev/null +++ b/osal/rtems/TaskBase.cpp @@ -0,0 +1,43 @@ +#include +#include "TaskBase.h" + +const uint64_t PeriodicTaskIF::MINIMUM_STACK_SIZE=RTEMS_MINIMUM_STACK_SIZE; + +TaskBase::TaskBase(rtems_task_priority set_priority, size_t stack_size, + const char *name) { + rtems_name osalName = 0; + for (uint8_t i = 0; i < 4; i++) { + if (name[i] == 0) { + break; + } + osalName += name[i] << (8 * (3 - i)); + } + //The task is created with the operating system's system call. + rtems_status_code status = RTEMS_UNSATISFIED; + if (set_priority >= 0 && set_priority <= 99) { + status = rtems_task_create(osalName, + (0xFF - 2 * set_priority), stack_size, + RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR, + RTEMS_FLOATING_POINT, &id); + } + ReturnValue_t result = RtemsBasic::convertReturnCode(status); + if (result != HasReturnvaluesIF::RETURN_OK) { + error << "TaskBase::TaskBase: createTask with name " << std::hex + << osalName << std::dec << " failed with return code " + << (uint32_t) status << std::endl; + this->id = 0; + } +} + +TaskBase::~TaskBase() { + rtems_task_delete(id); +} + +rtems_id TaskBase::getId() { + return this->id; +} + +ReturnValue_t TaskBase::sleepFor(uint32_t ms) { + rtems_status_code status = rtems_task_wake_after(RtemsBasic::convertMsToTicks(ms)); + return RtemsBasic::convertReturnCode(status); +} diff --git a/osal/rtems/TaskBase.h b/osal/rtems/TaskBase.h new file mode 100644 index 00000000..af081fad --- /dev/null +++ b/osal/rtems/TaskBase.h @@ -0,0 +1,43 @@ +#ifndef TASKBASE_H_ +#define TASKBASE_H_ + +#include "RtemsBasic.h" +#include + +/** + * @brief This is the basic task handling class for rtems. + * + * @details Task creation base class for rtems. + */ +class TaskBase { +protected: + /** + * @brief The class stores the task id it got assigned from the operating system in this attribute. + * If initialization fails, the id is set to zero. + */ + rtems_id id; +public: + /** + * @brief The constructor creates and initializes a task. + * @details This is accomplished by using the operating system call to create a task. The name is + * created automatically with the help od taskCounter. Priority and stack size are + * adjustable, all other attributes are set with default values. + * @param priority Sets the priority of a task. Values range from a low 0 to a high 99. + * @param stack_size The stack size reserved by the operating system for the task. + * @param nam The name of the Task, as a null-terminated String. Currently max 4 chars supported (excluding Null-terminator), rest will be truncated + */ + TaskBase( rtems_task_priority priority, size_t stack_size, const char *name); + /** + * @brief In the destructor, the created task is deleted. + */ + virtual ~TaskBase(); + /** + * @brief This method returns the task id of this class. + */ + rtems_id getId(); + + ReturnValue_t sleepFor(uint32_t ms); +}; + + +#endif /* TASKBASE_H_ */ diff --git a/osal/rtems/TaskFactory.cpp b/osal/rtems/TaskFactory.cpp new file mode 100644 index 00000000..82fb0dc3 --- /dev/null +++ b/osal/rtems/TaskFactory.cpp @@ -0,0 +1,34 @@ +#include +#include "MultiObjectTask.h" +#include "PollingTask.h" +#include "InitTask.h" +#include + +//TODO: Different variant than the lazy loading in QueueFactory. What's better and why? +TaskFactory* TaskFactory::factoryInstance = new TaskFactory(); + +TaskFactory::~TaskFactory() { +} + +TaskFactory* TaskFactory::instance() { + return TaskFactory::factoryInstance; +} + +PeriodicTaskIF* TaskFactory::createPeriodicTask(OSAL::TaskName name_,OSAL::TaskPriority taskPriority_,OSAL::TaskStackSize stackSize_,OSAL::TaskPeriod periodInSeconds_,OSAL::TaskDeadlineMissedFunction deadLineMissedFunction_) { + rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond(); + + return static_cast(new MultiObjectTask(name_,taskPriority_,stackSize_,taskPeriod,deadLineMissedFunction_)); +} + +FixedTimeslotTaskIF* TaskFactory::createFixedTimeslotTask(OSAL::TaskName name_,OSAL::TaskPriority taskPriority_,OSAL::TaskStackSize stackSize_,OSAL::TaskPeriod periodInSeconds_,OSAL::TaskDeadlineMissedFunction deadLineMissedFunction_) { + rtems_interval taskPeriod = periodInSeconds_ * Clock::getTicksPerSecond(); + return static_cast(new PollingTask(name_,taskPriority_,stackSize_,taskPeriod,deadLineMissedFunction_)); +} + +ReturnValue_t TaskFactory::deleteTask(PeriodicTaskIF* task) { + //TODO not implemented + return HasReturnvaluesIF::RETURN_FAILED; +} + +TaskFactory::TaskFactory() { +} diff --git a/parameters/HasParametersIF.h b/parameters/HasParametersIF.h index ad77b879..fbb69445 100644 --- a/parameters/HasParametersIF.h +++ b/parameters/HasParametersIF.h @@ -1,10 +1,3 @@ -/* - * HasParametersIF.h - * - * Created on: 26.11.2015 - * Author: mohr - */ - #ifndef HASPARAMETERSIF_H_ #define HASPARAMETERSIF_H_ @@ -16,26 +9,28 @@ typedef uint32_t ParameterId_t; class HasParametersIF { public: - static const uint8_t INTERFACE_ID = HAS_PARAMETERS_IF; + static const uint8_t INTERFACE_ID = CLASS_ID::HAS_PARAMETERS_IF; static const ReturnValue_t INVALID_MATRIX_ID = MAKE_RETURN_CODE(0x01); static const ReturnValue_t INVALID_DOMAIN_ID = MAKE_RETURN_CODE(0x02); static const ReturnValue_t INVALID_VALUE = MAKE_RETURN_CODE(0x03); + static const ReturnValue_t READ_ONLY = MAKE_RETURN_CODE(0x05); - - - - static uint8_t getDomain(ParameterId_t id){ + static uint8_t getDomain(ParameterId_t id) { return id >> 24; } - static uint16_t getMatrixId(ParameterId_t id){ + static uint16_t getMatrixId(ParameterId_t id) { return id >> 8; } - static uint8_t getIndex(ParameterId_t id){ + static uint8_t getIndex(ParameterId_t id) { return id; } + static uint32_t getFullParameterId(uint8_t domainId, uint16_t parameterId, + uint8_t index) { + return (domainId << 24) + (parameterId << 8) + index; + } virtual ~HasParametersIF() { } diff --git a/parameters/ParameterHelper.cpp b/parameters/ParameterHelper.cpp index f2aebdde..6425ec40 100644 --- a/parameters/ParameterHelper.cpp +++ b/parameters/ParameterHelper.cpp @@ -1,10 +1,3 @@ -/* - * ParameterHelper.cpp - * - * Created on: 28.11.2015 - * Author: mohr - */ - #include #include #include @@ -26,7 +19,7 @@ ReturnValue_t ParameterHelper::handleParameterMessage(CommandMessage *message) { ParameterMessage::getParameterId(message)); uint16_t parameterId = HasParametersIF::getMatrixId( ParameterMessage::getParameterId(message)); - ReturnValue_t result = owner->getParameter(domain, parameterId, + result = owner->getParameter(domain, parameterId, &description, &description, 0); if (result == HasReturnvaluesIF::RETURN_OK) { result = sendParameter(message->getSender(), @@ -45,7 +38,7 @@ ReturnValue_t ParameterHelper::handleParameterMessage(CommandMessage *message) { const uint8_t *storedStream; uint32_t storedStreamSize; - ReturnValue_t result = storage->getData( + result = storage->getData( ParameterMessage::getStoreId(message), &storedStream, &storedStreamSize); if (result != HasReturnvaluesIF::RETURN_OK) { @@ -115,8 +108,7 @@ ReturnValue_t ParameterHelper::sendParameter(MessageQueueId_t to, uint32_t id, ParameterMessage::setParameterDumpReply(&reply, id, address); - MessageQueueSender sender; - sender.sendMessage(to, &reply, ownerQueueId); + MessageQueueSenderIF::sendMessage(to, &reply, ownerQueueId); return HasReturnvaluesIF::RETURN_OK; } @@ -133,6 +125,5 @@ ReturnValue_t ParameterHelper::initialize() { void ParameterHelper::rejectCommand(MessageQueueId_t to, ReturnValue_t reason, Command_t initialCommand) { CommandMessage reply; reply.setReplyRejected(reason, initialCommand); - MessageQueueSender sender; - sender.sendMessage(to, &reply, ownerQueueId); + MessageQueueSenderIF::sendMessage(to, &reply, ownerQueueId); } diff --git a/parameters/ParameterHelper.h b/parameters/ParameterHelper.h index d96a4794..e2fefdba 100644 --- a/parameters/ParameterHelper.h +++ b/parameters/ParameterHelper.h @@ -1,10 +1,3 @@ -/* - * ParameterHelper.h - * - * Created on: 28.11.2015 - * Author: mohr - */ - #ifndef PARAMETERHELPER_H_ #define PARAMETERHELPER_H_ diff --git a/parameters/ParameterMessage.cpp b/parameters/ParameterMessage.cpp index 38dd81a0..1c7d6911 100644 --- a/parameters/ParameterMessage.cpp +++ b/parameters/ParameterMessage.cpp @@ -1,11 +1,5 @@ -/* - * ParameterMessage.cpp - * - * Created on: 28.11.2015 - * Author: mohr - */ - #include +#include ParameterId_t ParameterMessage::getParameterId(const CommandMessage* message) { return message->getParameter(); @@ -36,3 +30,19 @@ void ParameterMessage::setParameterLoadCommand(CommandMessage* message, message->setParameter(id); message->setParameter2(storageID.raw); } + +void ParameterMessage::clear(CommandMessage* message) { + switch (message->getCommand()) { + case CMD_PARAMETER_LOAD: + case REPLY_PARAMETER_DUMP: { + StorageManagerIF *ipcStore = objectManager->get( + objects::IPC_STORE); + if (ipcStore != NULL) { + ipcStore->deleteData(getStoreId(message)); + } + break; + } + default: + break; + } +} diff --git a/parameters/ParameterMessage.h b/parameters/ParameterMessage.h index bf595352..0f286675 100644 --- a/parameters/ParameterMessage.h +++ b/parameters/ParameterMessage.h @@ -1,10 +1,3 @@ -/* - * ParameterMessage.h - * - * Created on: 28.11.2015 - * Author: mohr - */ - #ifndef PARAMETERMESSAGE_H_ #define PARAMETERMESSAGE_H_ @@ -16,7 +9,7 @@ class ParameterMessage { private: ParameterMessage(); public: - static const uint8_t MESSAGE_ID = PARAMETER_MESSAGE_ID; + static const uint8_t MESSAGE_ID = MESSAGE_TYPE::PARAMETER; static const Command_t CMD_PARAMETER_LOAD = MAKE_COMMAND_ID( 0x01 ); static const Command_t CMD_PARAMETER_DUMP = MAKE_COMMAND_ID( 0x02 ); static const Command_t REPLY_PARAMETER_DUMP = MAKE_COMMAND_ID( 0x03 ); @@ -29,6 +22,7 @@ public: ParameterId_t id, store_address_t storageID); static void setParameterLoadCommand(CommandMessage* message, ParameterId_t id, store_address_t storageID); + static void clear(CommandMessage* message); }; diff --git a/parameters/ParameterWrapper.cpp b/parameters/ParameterWrapper.cpp index 3b2f6685..8f661bb3 100644 --- a/parameters/ParameterWrapper.cpp +++ b/parameters/ParameterWrapper.cpp @@ -114,7 +114,7 @@ ReturnValue_t ParameterWrapper::deSerializeData(uint8_t startingRow, const uint8_t *fromAsStream = (const uint8_t *) from; int32_t streamSize = fromRows * fromColumns * sizeof(T); - ReturnValue_t result; + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; for (uint8_t fromRow = 0; fromRow < fromRows; fromRow++) { @@ -219,7 +219,7 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper* from, uint8_t typeSize = type.getSize(); - ReturnValue_t result; + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; //copy data if (from->pointsToStream) { switch (type) { @@ -271,5 +271,5 @@ ReturnValue_t ParameterWrapper::copyFrom(const ParameterWrapper* from, } } - return HasReturnvaluesIF::RETURN_OK; + return result; } diff --git a/parameters/ParameterWrapper.h b/parameters/ParameterWrapper.h index e4c62064..f61786b8 100644 --- a/parameters/ParameterWrapper.h +++ b/parameters/ParameterWrapper.h @@ -1,7 +1,6 @@ #ifndef PARAMETERWRAPPER_H_ #define PARAMETERWRAPPER_H_ -#include #include #include #include @@ -9,8 +8,9 @@ #include class ParameterWrapper: public SerializeIF { + friend class DataPoolParameterWrapper; public: - static const uint8_t INTERFACE_ID = PARAMETER_WRAPPER; + static const uint8_t INTERFACE_ID = CLASS_ID::PARAMETER_WRAPPER; static const ReturnValue_t UNKNOW_DATATYPE = MAKE_RETURN_CODE(0x01); static const ReturnValue_t DATATYPE_MISSMATCH = MAKE_RETURN_CODE(0x02); static const ReturnValue_t READONLY = MAKE_RETURN_CODE(0x03); @@ -46,7 +46,7 @@ public: return DATATYPE_MISSMATCH; } - if ((row > rows) || (column > columns)) { + if ((row >= rows) || (column >= columns)) { return OUT_OF_BOUNDS; } @@ -95,7 +95,7 @@ public: template void setVector(T& member) { - this->set(member, 1, sizeof(member)/sizeof(member[0])); + this->set(member, sizeof(member)/sizeof(member[0]), 1); } template diff --git a/parameters/ReceivesParameterMessagesIF.h b/parameters/ReceivesParameterMessagesIF.h index b76d2967..9bcd226d 100644 --- a/parameters/ReceivesParameterMessagesIF.h +++ b/parameters/ReceivesParameterMessagesIF.h @@ -2,12 +2,13 @@ #define RECEIVESPARAMETERMESSAGESIF_H_ -#include #include +#include class ReceivesParameterMessagesIF : public HasParametersIF { public: + static const uint8_t DOMAIN_ID_BASE = 0; virtual ~ReceivesParameterMessagesIF() { } diff --git a/power/Fuse.cpp b/power/Fuse.cpp new file mode 100644 index 00000000..dd5d3e3f --- /dev/null +++ b/power/Fuse.cpp @@ -0,0 +1,260 @@ +#include +#include +#include +#include +#include +#include + +object_id_t Fuse::powerSwitchId = 0; + +Fuse::Fuse(object_id_t fuseObjectId, uint8_t fuseId, VariableIds ids, + float maxCurrent, uint16_t confirmationCount) : + SystemObject(fuseObjectId), oldFuseState(0), fuseId(fuseId), powerIF( + NULL), currentLimit(fuseObjectId, 1, ids.pidCurrent, confirmationCount, + maxCurrent, FUSE_CURRENT_HIGH), powerMonitor(fuseObjectId, 2, + DataPool::poolIdAndPositionToPid(ids.poolIdPower, 0), + confirmationCount), set(), voltage(ids.pidVoltage, &set), current( + ids.pidCurrent, &set), state(ids.pidState, &set), power( + ids.poolIdPower, &set, PoolVariableIF::VAR_READ_WRITE), commandQueue( + NULL), parameterHelper(this), healthHelper(this, fuseObjectId) { + commandQueue = QueueFactory::instance()->createMessageQueue(); +} + +Fuse::~Fuse() { + QueueFactory::instance()->deleteMessageQueue(commandQueue); +} + +void Fuse::addDevice(PowerComponentIF* switchSet) { + devices.push_back(switchSet); +} + +ReturnValue_t Fuse::initialize() { + ReturnValue_t result = SystemObject::initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = parameterHelper.initialize(); + if (result != RETURN_OK) { + return result; + } + result = healthHelper.initialize(); + if (result != RETURN_OK) { + return result; + } + powerIF = objectManager->get(powerSwitchId); + if (powerIF == NULL) { + return RETURN_FAILED; + } + return RETURN_OK; +} + +void Fuse::calculatePowerLimits(float* low, float* high) { + for (DeviceList::iterator iter = devices.begin(); iter != devices.end(); + iter++) { + if (areSwitchesOfComponentOn(iter)) { + *low += (*iter)->getMin(); + *high += (*iter)->getMax(); + } + } +} + +ReturnValue_t Fuse::check() { + set.read(); + if (!healthHelper.healthTable->isHealthy(getObjectId())) { + setAllMonitorsToUnchecked(); + set.commit(PoolVariableIF::INVALID); + return RETURN_OK; + } + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + checkFuseState(); + calculateFusePower(); + //Check if power is valid and if fuse state is off or invalid. + if (!power.isValid() || (state == 0) || !state.isValid()) { + result = powerMonitor.setToInvalid(); + } else { + float lowLimit = 0.0; + float highLimit = RESIDUAL_POWER; + calculatePowerLimits(&lowLimit, &highLimit); + result = powerMonitor.checkPower(power, lowLimit, highLimit); + if (result == MonitoringIF::BELOW_LOW_LIMIT) { + reportEvents(POWER_BELOW_LOW_LIMIT); + } else if (result == MonitoringIF::ABOVE_HIGH_LIMIT) { + reportEvents(POWER_ABOVE_HIGH_LIMIT); + } + } + set.commit(); + return result; +} + +ReturnValue_t Fuse::serialize(uint8_t** buffer, uint32_t* size, + const uint32_t max_size, bool bigEndian) const { + ReturnValue_t result = RETURN_FAILED; + for (DeviceList::const_iterator iter = devices.begin(); + iter != devices.end(); iter++) { + result = (*iter)->serialize(buffer, size, max_size, bigEndian); + if (result != RETURN_OK) { + return result; + } + } + return RETURN_OK; +} + +uint32_t Fuse::getSerializedSize() const { + uint32_t size = 0; + for (DeviceList::const_iterator iter = devices.begin(); + iter != devices.end(); iter++) { + size += (*iter)->getSerializedSize(); + } + return size; +} + +ReturnValue_t Fuse::deSerialize(const uint8_t** buffer, int32_t* size, +bool bigEndian) { + ReturnValue_t result = RETURN_FAILED; + for (DeviceList::iterator iter = devices.begin(); iter != devices.end(); + iter++) { + result = (*iter)->deSerialize(buffer, size, bigEndian); + if (result != RETURN_OK) { + return result; + } + } + return RETURN_OK; +} + +uint8_t Fuse::getFuseId() const { + return fuseId; +} + +void Fuse::calculateFusePower() { + ReturnValue_t result1 = currentLimit.check(); + if (result1 != HasReturnvaluesIF::RETURN_OK || !(voltage.isValid())) { + power.setValid(PoolVariableIF::INVALID); + return; + } + //Calculate fuse power. + power = current * voltage; + power.setValid(PoolVariableIF::VALID); +} + +ReturnValue_t Fuse::performOperation(uint8_t opCode) { + checkCommandQueue(); + return HasReturnvaluesIF::RETURN_OK; +} + +void Fuse::reportEvents(Event event) { + if (!powerMonitor.isEventEnabled()) { + return; + } + for (DeviceList::iterator iter = devices.begin(); iter != devices.end(); + iter++) { + if (areSwitchesOfComponentOn(iter)) { + EventManagerIF::triggerEvent((*iter)->getDeviceObjectId(), event); + } + } +} + +MessageQueueId_t Fuse::getCommandQueue() const { + return commandQueue->getId(); +} + +void Fuse::setAllMonitorsToUnchecked() { + currentLimit.setToUnchecked(); + powerMonitor.setToUnchecked(); +} + +void Fuse::checkCommandQueue() { + CommandMessage command; + ReturnValue_t result = commandQueue->receiveMessage(&command); + if (result != HasReturnvaluesIF::RETURN_OK) { + return; + } + result = healthHelper.handleHealthCommand(&command); + if (result == HasReturnvaluesIF::RETURN_OK) { + return; + } + result = parameterHelper.handleParameterMessage(&command); + if (result == HasReturnvaluesIF::RETURN_OK) { + return; + } + command.setToUnknownCommand(); + commandQueue->reply(&command); +} + +void Fuse::checkFuseState() { + if (!state.isValid()) { + oldFuseState = 0; + return; + } + if (state == 0) { + if (oldFuseState != 0) { + reportEvents(FUSE_WENT_OFF); + } + } + oldFuseState = state; +} + +float Fuse::getPower() { + if (power.isValid()) { + return power; + } else { + return 0.0; + } +} + +void Fuse::setDataPoolEntriesInvalid() { + set.read(); + set.commit(PoolVariableIF::INVALID); +} + +ReturnValue_t Fuse::getParameter(uint8_t domainId, uint16_t parameterId, + ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues, + uint16_t startAtIndex) { + ReturnValue_t result = currentLimit.getParameter(domainId, parameterId, + parameterWrapper, newValues, startAtIndex); + if (result != INVALID_DOMAIN_ID) { + return result; + } + result = powerMonitor.getParameter(domainId, parameterId, parameterWrapper, + newValues, startAtIndex); + return result; +} + +bool Fuse::areSwitchesOfComponentOn(DeviceList::iterator iter) { + if (powerIF->getSwitchState((*iter)->getSwitchId1()) + != PowerSwitchIF::SWITCH_ON) { + return false; + } + if ((*iter)->hasTwoSwitches()) { + if ((powerIF->getSwitchState((*iter)->getSwitchId2()) + != PowerSwitchIF::SWITCH_ON)) { + return false; + } + } + return true; +} + +bool Fuse::isPowerValid() { + return power.isValid(); +} + +ReturnValue_t Fuse::setHealth(HealthState health) { + healthHelper.setHealth(health); + return RETURN_OK; +} + +HasHealthIF::HealthState Fuse::getHealth() { + return healthHelper.getHealth(); +} + +ReturnValue_t Fuse::PowerMonitor::checkPower(float sample, float lowerLimit, + float upperLimit) { + if (sample > upperLimit) { + return this->monitorStateIs(MonitoringIF::ABOVE_HIGH_LIMIT, sample, + upperLimit); + } else if (sample < lowerLimit) { + return this->monitorStateIs(MonitoringIF::BELOW_LOW_LIMIT, sample, + lowerLimit); + } else { + return this->monitorStateIs(RETURN_OK, sample, 0.0); //Within limits. + } +} diff --git a/power/Fuse.h b/power/Fuse.h new file mode 100644 index 00000000..06b4ae81 --- /dev/null +++ b/power/Fuse.h @@ -0,0 +1,105 @@ +#ifndef FUSE_H_ +#define FUSE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Factory{ +void setStaticFrameworkObjectIds(); +} + +class Fuse: public SystemObject, + public HasHealthIF, + public HasReturnvaluesIF, + public ReceivesParameterMessagesIF { + friend void (Factory::setStaticFrameworkObjectIds)(); +private: + //TODO, modern gcc complains about const + static const float RESIDUAL_POWER = 0.005 * 28.5; //!< This is the upper limit of residual power lost by fuses and switches. Worst case is Fuse and one of two switches on. See PCDU ICD 1.9 p29 bottom +public: + struct VariableIds { + uint32_t pidVoltage; + uint32_t pidCurrent; + uint32_t pidState; + uint32_t poolIdPower; + }; + + static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_1; + static const Event FUSE_CURRENT_HIGH = MAKE_EVENT(1, SEVERITY::LOW); //!< PSS detected that current on a fuse is totally out of bounds. + static const Event FUSE_WENT_OFF = MAKE_EVENT(2, SEVERITY::LOW); //!< PSS detected a fuse that went off. + static const Event POWER_ABOVE_HIGH_LIMIT = MAKE_EVENT(4, SEVERITY::LOW); //!< PSS detected a fuse that violates its limits. + static const Event POWER_BELOW_LOW_LIMIT = MAKE_EVENT(5, SEVERITY::LOW); //!< PSS detected a fuse that violates its limits. + + typedef std::list DeviceList; + Fuse(object_id_t fuseObjectId, uint8_t fuseId, VariableIds ids, + float maxCurrent, uint16_t confirmationCount = 2); + virtual ~Fuse(); + void addDevice(PowerComponentIF* set); + float getPower(); + + bool isPowerValid(); + + ReturnValue_t check(); + uint8_t getFuseId() const; + ReturnValue_t initialize(); + DeviceList devices; + ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, + const uint32_t max_size, bool bigEndian) const; + uint32_t getSerializedSize() const; + ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, + bool bigEndian); + void setAllMonitorsToUnchecked(); + ReturnValue_t performOperation(uint8_t opCode); + MessageQueueId_t getCommandQueue() const; + void setDataPoolEntriesInvalid(); + ReturnValue_t setHealth(HealthState health); + HasHealthIF::HealthState getHealth(); + + ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, + ParameterWrapper *parameterWrapper, + const ParameterWrapper *newValues, uint16_t startAtIndex); + +private: + uint8_t oldFuseState; + uint8_t fuseId; + PowerSwitchIF* powerIF; //could be static in our case. + AbsLimitMonitor currentLimit; + class PowerMonitor: public MonitorReporter { + public: + template + PowerMonitor(Args ... args) : + MonitorReporter(std::forward(args)...) { + } + ReturnValue_t checkPower(float sample, float lowerLimit, + float upperLimit); + void sendTransitionEvent(float currentValue, ReturnValue_t state) { + } + + }; + PowerMonitor powerMonitor; + DataSet set; + PIDReader voltage; + PIDReader current; + PIDReader state; + db_float_t power; + MessageQueueIF* commandQueue; + ParameterHelper parameterHelper; + HealthHelper healthHelper; + static object_id_t powerSwitchId; + void calculatePowerLimits(float* low, float* high); + void calculateFusePower(); + void checkFuseState(); + void reportEvents(Event event); + void checkCommandQueue(); + + bool areSwitchesOfComponentOn(DeviceList::iterator iter); +}; + +#endif /* FUSE_H_ */ diff --git a/power/HasPowerSwitchIF.h b/power/HasPowerSwitchIF.h deleted file mode 100644 index 55a54b47..00000000 --- a/power/HasPowerSwitchIF.h +++ /dev/null @@ -1,20 +0,0 @@ -/** - * @file HasPowerSwitchIF.h - * @brief This file defines the HasPowerSwitchIF class. - * @date 25.02.2014 - * @author baetz - */ -#ifndef HASPOWERSWITCHIF_H_ -#define HASPOWERSWITCHIF_H_ - - -class HasPowerSwitchIF { -public: - virtual ~HasPowerSwitchIF() {} - virtual ReturnValue_t getSwitches(uint8_t *firstSwitch, - uint8_t *secondSwitch) = 0; - virtual void getPowerLimit(float* low, float* high) = 0; -}; - - -#endif /* HASPOWERSWITCHIF_H_ */ diff --git a/power/PowerComponent.cpp b/power/PowerComponent.cpp new file mode 100644 index 00000000..6a87d88b --- /dev/null +++ b/power/PowerComponent.cpp @@ -0,0 +1,86 @@ +/** + * @file PowerComponent.cpp + * @brief This file defines the PowerComponent class. + * @date 28.08.2014 + * @author baetz + */ + +#include + +PowerComponent::PowerComponent() : + deviceObjectId(0), switchId1(0xFF), switchId2(0xFF), doIHaveTwoSwitches( + false), min(0.0), max(0.0), moduleId(0) { +} +PowerComponent::PowerComponent(object_id_t setId, uint8_t moduleId, float min, float max, + uint8_t switchId1, bool twoSwitches, uint8_t switchId2) : + deviceObjectId(setId), switchId1(switchId1), switchId2(switchId2), doIHaveTwoSwitches( + twoSwitches), min(min), max(max), moduleId(moduleId) { +} + +ReturnValue_t PowerComponent::serialize(uint8_t** buffer, uint32_t* size, + const uint32_t max_size, bool bigEndian) const { + ReturnValue_t result = SerializeAdapter::serialize(&min, buffer, + size, max_size, bigEndian); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return SerializeAdapter::serialize(&max, buffer, size, max_size, + bigEndian); +} + +uint32_t PowerComponent::getSerializedSize() const { + return sizeof(min) + sizeof(max); +} + +object_id_t PowerComponent::getDeviceObjectId() { + return deviceObjectId; +} + +uint8_t PowerComponent::getSwitchId1() { + return switchId1; +} + +uint8_t PowerComponent::getSwitchId2() { + return switchId2; +} + +bool PowerComponent::hasTwoSwitches() { + return doIHaveTwoSwitches; +} + +float PowerComponent::getMin() { + return min; +} + +float PowerComponent::getMax() { + return max; +} + +ReturnValue_t PowerComponent::deSerialize(const uint8_t** buffer, int32_t* size, +bool bigEndian) { + ReturnValue_t result = SerializeAdapter::deSerialize(&min, buffer, + size, bigEndian); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return SerializeAdapter::deSerialize(&max, buffer, size, bigEndian); +} + +ReturnValue_t PowerComponent::getParameter(uint8_t domainId, + uint16_t parameterId, ParameterWrapper* parameterWrapper, + const ParameterWrapper* newValues, uint16_t startAtIndex) { + if (domainId != moduleId) { + return INVALID_DOMAIN_ID; + } + switch (parameterId) { + case 0: + parameterWrapper->set<>(min); + break; + case 1: + parameterWrapper->set<>(max); + break; + default: + return INVALID_MATRIX_ID; + } + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/power/PowerComponent.h b/power/PowerComponent.h new file mode 100644 index 00000000..a82fe1d7 --- /dev/null +++ b/power/PowerComponent.h @@ -0,0 +1,48 @@ +#ifndef POWERCOMPONENT_H_ +#define POWERCOMPONENT_H_ + +#include +#include + +class PowerComponent: public PowerComponentIF { +public: + PowerComponent(object_id_t setId, uint8_t moduleId, float min, float max, uint8_t switchId1, + bool twoSwitches = false, uint8_t switchId2 = 0xFF); + + virtual object_id_t getDeviceObjectId(); + + virtual uint8_t getSwitchId1(); + virtual uint8_t getSwitchId2(); + + bool hasTwoSwitches(); + + float getMin(); + float getMax(); + + ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, + const uint32_t max_size, bool bigEndian) const; + + uint32_t getSerializedSize() const; + + ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, + bool bigEndian); + + ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, + ParameterWrapper *parameterWrapper, + const ParameterWrapper *newValues, uint16_t startAtIndex); +private: + const object_id_t deviceObjectId; + const uint8_t switchId1; + const uint8_t switchId2; + + const bool doIHaveTwoSwitches; + + float min; + float max; + + uint8_t moduleId; + + PowerComponent(); +}; + +#endif /* POWERCOMPONENT_H_ */ diff --git a/power/PowerComponentIF.h b/power/PowerComponentIF.h new file mode 100644 index 00000000..f2aa70ae --- /dev/null +++ b/power/PowerComponentIF.h @@ -0,0 +1,24 @@ +#ifndef POWERCOMPONENTIF_H_ +#define POWERCOMPONENTIF_H_ + +#include +#include + +class PowerComponentIF : public SerializeIF, public HasParametersIF { +public: + virtual ~PowerComponentIF() { + + } + + virtual object_id_t getDeviceObjectId()=0; + + virtual uint8_t getSwitchId1()=0; + virtual uint8_t getSwitchId2()=0; + virtual bool hasTwoSwitches()=0; + + virtual float getMin() = 0; + virtual float getMax() = 0; + +}; + +#endif /* POWERCOMPONENTIF_H_ */ diff --git a/power/PowerSensor.cpp b/power/PowerSensor.cpp new file mode 100644 index 00000000..5433acc9 --- /dev/null +++ b/power/PowerSensor.cpp @@ -0,0 +1,128 @@ +#include +#include + +PowerSensor::PowerSensor(object_id_t setId, VariableIds ids, + DefaultLimits limits, SensorEvents events, uint16_t confirmationCount) : + SystemObject(setId), commandQueue(NULL), parameterHelper(this), healthHelper(this, setId), set(), current( + ids.pidCurrent, &set), voltage(ids.pidVoltage, &set), power( + ids.poolIdPower, &set, PoolVariableIF::VAR_WRITE), currentLimit( + setId, MODULE_ID_CURRENT, ids.pidCurrent, confirmationCount, + limits.currentMin, limits.currentMax, events.currentLow, + events.currentHigh), voltageLimit(setId, MODULE_ID_VOLTAGE, + ids.pidVoltage, confirmationCount, limits.voltageMin, + limits.voltageMax, events.voltageLow, events.voltageHigh) { + commandQueue = QueueFactory::instance()->createMessageQueue(); +} + +PowerSensor::~PowerSensor() { + QueueFactory::instance()->deleteMessageQueue(commandQueue); +} + +ReturnValue_t PowerSensor::calculatePower() { + set.read(); + ReturnValue_t result1 = HasReturnvaluesIF::RETURN_FAILED; + ReturnValue_t result2 = HasReturnvaluesIF::RETURN_FAILED; + if (healthHelper.healthTable->isHealthy(getObjectId()) && voltage.isValid() + && current.isValid()) { + result1 = voltageLimit.doCheck(voltage); + result2 = currentLimit.doCheck(current); + } else { + voltageLimit.setToInvalid(); + currentLimit.setToInvalid(); + result1 = OBJECT_NOT_HEALTHY; + } + if (result1 != HasReturnvaluesIF::RETURN_OK + || result2 != HasReturnvaluesIF::RETURN_OK) { + result1 = MonitoringIF::INVALID; + power.setValid(PoolVariableIF::INVALID); + } else { + power.setValid(PoolVariableIF::VALID); + power = current * voltage; + } + set.commit(); + return result1; +} + +ReturnValue_t PowerSensor::performOperation(uint8_t opCode) { + checkCommandQueue(); + return HasReturnvaluesIF::RETURN_OK; +} + +MessageQueueId_t PowerSensor::getCommandQueue() const { + return commandQueue->getId(); +} + +ReturnValue_t PowerSensor::initialize() { + ReturnValue_t result = SystemObject::initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = healthHelper.initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = parameterHelper.initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return result; +} + +void PowerSensor::setAllMonitorsToUnchecked() { + currentLimit.setToUnchecked(); + voltageLimit.setToUnchecked(); +} + +void PowerSensor::checkCommandQueue() { + CommandMessage command; + ReturnValue_t result = commandQueue->receiveMessage(&command); + if (result != HasReturnvaluesIF::RETURN_OK) { + return; + } + result = healthHelper.handleHealthCommand(&command); + if (result == HasReturnvaluesIF::RETURN_OK) { + return; + } + result = parameterHelper.handleParameterMessage(&command); + if (result == HasReturnvaluesIF::RETURN_OK) { + return; + } + command.setToUnknownCommand(); + commandQueue->reply(&command); +} + +void PowerSensor::setDataPoolEntriesInvalid() { + set.read(); + set.commit(PoolVariableIF::INVALID); +} + +float PowerSensor::getPower() { + if (power.isValid()) { + return power.value; + } else { + return 0.0; + } + +} + +ReturnValue_t PowerSensor::setHealth(HealthState health) { + healthHelper.setHealth(health); + return HasReturnvaluesIF::RETURN_OK; +} + +HasHealthIF::HealthState PowerSensor::getHealth() { + return healthHelper.getHealth(); +} + +ReturnValue_t PowerSensor::getParameter(uint8_t domainId, uint16_t parameterId, + ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues, + uint16_t startAtIndex) { + ReturnValue_t result = currentLimit.getParameter(domainId, parameterId, + parameterWrapper, newValues, startAtIndex); + if (result != INVALID_DOMAIN_ID) { + return result; + } + result = voltageLimit.getParameter(domainId, parameterId, parameterWrapper, + newValues, startAtIndex); + return result; +} diff --git a/power/PowerSensor.h b/power/PowerSensor.h new file mode 100644 index 00000000..922560d0 --- /dev/null +++ b/power/PowerSensor.h @@ -0,0 +1,71 @@ +#ifndef POWERSENSOR_H_ +#define POWERSENSOR_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +class PowerController; + +class PowerSensor: public SystemObject, + public ReceivesParameterMessagesIF, + public HasHealthIF { + friend class PowerController; +public: + struct VariableIds { + uint32_t pidCurrent; + uint32_t pidVoltage; + uint32_t poolIdPower; + }; + struct DefaultLimits { + float currentMin; + float currentMax; + float voltageMin; + float voltageMax; + }; + struct SensorEvents { + Event currentLow; + Event currentHigh; + Event voltageLow; + Event voltageHigh; + }; + PowerSensor(object_id_t setId, VariableIds setIds, DefaultLimits limits, + SensorEvents events, uint16_t confirmationCount = 0); + virtual ~PowerSensor(); + ReturnValue_t calculatePower(); + ReturnValue_t performOperation(uint8_t opCode); + void setAllMonitorsToUnchecked(); + MessageQueueId_t getCommandQueue() const; + ReturnValue_t initialize(); + void setDataPoolEntriesInvalid(); + float getPower(); + ReturnValue_t setHealth(HealthState health); + HasHealthIF::HealthState getHealth(); + ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, + ParameterWrapper *parameterWrapper, + const ParameterWrapper *newValues, uint16_t startAtIndex); +private: + MessageQueueIF* commandQueue; + ParameterHelper parameterHelper; + HealthHelper healthHelper; + DataSet set; + //Variables in + PIDReader current; + PIDReader voltage; + //Variables out + db_float_t power; + + static const uint8_t MODULE_ID_CURRENT = 1; + static const uint8_t MODULE_ID_VOLTAGE = 2; + void checkCommandQueue(); +protected: + LimitMonitor currentLimit; + LimitMonitor voltageLimit; +}; + +#endif /* POWERSENSOR_H_ */ diff --git a/power/PowerSwitchIF.h b/power/PowerSwitchIF.h index 884d13a6..1c4c06f7 100644 --- a/power/PowerSwitchIF.h +++ b/power/PowerSwitchIF.h @@ -25,14 +25,14 @@ public: /** * The Returnvalues id of this class, required by HasReturnvaluesIF */ - static const uint8_t INTERFACE_ID = POWER_SWITCH_IF; + static const uint8_t INTERFACE_ID = CLASS_ID::POWER_SWITCH_IF; static const ReturnValue_t SWITCH_ON = MAKE_RETURN_CODE(1); static const ReturnValue_t SWITCH_OFF = MAKE_RETURN_CODE(0); static const ReturnValue_t SWITCH_TIMEOUT = MAKE_RETURN_CODE(2); static const ReturnValue_t FUSE_ON = MAKE_RETURN_CODE(3); static const ReturnValue_t FUSE_OFF = MAKE_RETURN_CODE(4); static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PCDU_2; - static const Event SWITCH_WENT_OFF = MAKE_EVENT(0, SEVERITY::LOW); //!< Someone detected that a switch went off which shouldn't. Severity: Low, Parameter1: switchId1, Parameter2: switchId2 TODO: CHANGED EVENT_ID! + static const Event SWITCH_WENT_OFF = MAKE_EVENT(0, SEVERITY::LOW); //!< Someone detected that a switch went off which shouldn't. Severity: Low, Parameter1: switchId1, Parameter2: switchId2 /** * send a direct command to the Power Unit to enable/disable the specified switch. * diff --git a/power/PowerSwitcher.cpp b/power/PowerSwitcher.cpp index b3110e59..6b06bf73 100644 --- a/power/PowerSwitcher.cpp +++ b/power/PowerSwitcher.cpp @@ -1,10 +1,3 @@ -/* - * PowerSwitcher.cpp - * - * Created on: 21.01.2014 - * Author: baetz - */ - #include #include #include @@ -14,8 +7,8 @@ PowerSwitcher::PowerSwitcher(uint8_t setSwitch1, uint8_t setSwitch2, state(setStartState), firstSwitch(setSwitch1), secondSwitch(setSwitch2), power(NULL) { } -ReturnValue_t PowerSwitcher::initialize() { - power = objectManager->get(objects::PCDU_HANDLER); +ReturnValue_t PowerSwitcher::initialize(object_id_t powerSwitchId) { + power = objectManager->get(powerSwitchId); if (power == NULL) { return HasReturnvaluesIF::RETURN_FAILED; } @@ -47,7 +40,7 @@ void PowerSwitcher::commandSwitches(ReturnValue_t onOff) { switch (result) { case TWO_SWITCHES: power->sendSwitchCommand(secondSwitch, onOff); - /*NO BREAK*/ + /* NO BREAK falls through*/ case ONE_SWITCH: power->sendSwitchCommand(firstSwitch, onOff); break; diff --git a/power/PowerSwitcher.h b/power/PowerSwitcher.h index 115daf7a..5b2789e9 100644 --- a/power/PowerSwitcher.h +++ b/power/PowerSwitcher.h @@ -1,10 +1,3 @@ -/* - * PowerSwitcher.h - * - * Created on: 21.01.2014 - * Author: baetz - */ - #ifndef POWERSWITCHER_H_ #define POWERSWITCHER_H_ #include @@ -20,11 +13,11 @@ public: SWITCH_IS_ON, }; State_t state; - static const uint8_t INTERFACE_ID = POWER_SWITCHER; + static const uint8_t INTERFACE_ID = CLASS_ID::POWER_SWITCHER; static const ReturnValue_t IN_POWER_TRANSITION = MAKE_RETURN_CODE(1); static const ReturnValue_t SWITCH_STATE_MISMATCH = MAKE_RETURN_CODE(2); PowerSwitcher( uint8_t setSwitch1, uint8_t setSwitch2 = NO_SWITCH, State_t setStartState = SWITCH_IS_OFF ); - ReturnValue_t initialize(); + ReturnValue_t initialize(object_id_t powerSwitchId); void turnOn(); void turnOff(); void doStateMachine(); diff --git a/privatepool/PrivatePoolEntry.h b/privatepool/PrivatePoolEntry.h deleted file mode 100644 index 65a4abc6..00000000 --- a/privatepool/PrivatePoolEntry.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * PrivatePoolEntry.h - * - * Created on: 13.03.2014 - * Author: baetz - */ - -#ifndef PRIVATEPOOLENTRY_H_ -#define PRIVATEPOOLENTRY_H_ - -#include -#include -#include -#include -#include - -template -class PrivatePoolEntry: public PrivatePoolIF, public LinkedElement { -public: - PrivatePoolEntry() : LinkedElement(this), - address(0), element(0) { - } - PrivatePoolEntry(uint32_t address, T value) : LinkedElement(this), - address(address), element(value) { - } - - uint32_t address; - - T element; - - operator T() { - return element; - } - - PrivatePoolEntry &operator =(T value) { - element = value; - return *this; - } - ReturnValue_t handleMemoryLoad(uint32_t address, const uint8_t* data, uint32_t size, uint8_t** dataPointer) { - return handleMemoryDump(address, size, dataPointer, NULL); - } - ReturnValue_t handleMemoryDump(uint32_t address, uint32_t size, uint8_t** dataPointer, uint8_t* dumpTarget ) { - if (this->address != address) { - return INVALID_ADDRESS; - } - if (size != sizeof(element)) { - return INVALID_SIZE; - } - *dataPointer = (uint8_t*)&element; - return POINTS_TO_VARIABLE; - } - ReturnValue_t setAddress(uint32_t* setAddress ) { - address = *setAddress; - return HasReturnvaluesIF::RETURN_OK; - } - ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { - return SerializeAdapter::serialize(&element, buffer, size, max_size, bigEndian); - } - - uint32_t getSerializedSize() const { - return SerializeAdapter::getSerializedSize(&element); - } - - ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { - return SerializeAdapter::deSerialize(&element, buffer, size, bigEndian); - - } -}; - -template -class PrivatePoolEntry::Is>::type> : public LinkedElement, public T { -public: - //TODO: Have a look on how std::forward works. - template - PrivatePoolEntry(Args... args) : LinkedElement(this), T(std::forward(args)...) { - - } - virtual ~PrivatePoolEntry() { - - } -}; - -#endif /* PRIVATEPOOLENTRY_H_ */ diff --git a/privatepool/PrivatePoolIF.h b/privatepool/PrivatePoolIF.h deleted file mode 100644 index 7b7e43d2..00000000 --- a/privatepool/PrivatePoolIF.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * PrivatePoolIF.h - * - * Created on: 20.03.2014 - * Author: baetz - */ - -#ifndef PRIVATEPOOLIF_H_ -#define PRIVATEPOOLIF_H_ -#include -#include - -class PrivatePoolIF : public HasMemoryIF, public SerializeIF { -public: - virtual ~PrivatePoolIF() { - - } -}; - - - -#endif /* PRIVATEPOOLIF_H_ */ diff --git a/privatepool/SetAddressListAdapter.h b/privatepool/SetAddressListAdapter.h deleted file mode 100644 index ea85c0f8..00000000 --- a/privatepool/SetAddressListAdapter.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * SetAddressListAdapter.h - * - * Created on: 24.04.2014 - * Author: baetz - */ - -#ifndef SETADDRESSLISTADAPTER_H_ -#define SETADDRESSLISTADAPTER_H_ -#include -#include - -template -class SetAddressListAdapter { -public: - static ReturnValue_t setAddresses(const LinkedElement* element, uint32_t startFrom) { - ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - while ((result == HasReturnvaluesIF::RETURN_OK) && (element != NULL)) { - result = element->value->setAddress(&startFrom); - element = element->getNext(); - startFrom++; - } - return result; - } -}; - - - -#endif /* SETADDRESSLISTADAPTER_H_ */ diff --git a/returnvalues/FwClassIds.h b/returnvalues/FwClassIds.h new file mode 100644 index 00000000..515b0ddb --- /dev/null +++ b/returnvalues/FwClassIds.h @@ -0,0 +1,63 @@ +#ifndef FRAMEWORK_RETURNVALUES_FWCLASSIDS_H_ +#define FRAMEWORK_RETURNVALUES_FWCLASSIDS_H_ + +namespace CLASS_ID { +enum { + OPERATING_SYSTEM_ABSTRACTION = 1, //OS + OBJECT_MANAGER_IF, //OM + DEVICE_HANDLER_BASE, //DHB + RMAP_CHANNEL, //RMP + POWER_SWITCH_IF, //PS + HAS_MEMORY_IF, //PP + DEVICE_STATE_MACHINE_BASE, //DSMB + DATA_SET_CLASS, //DPS + POOL_RAW_ACCESS_CLASS, //DPR + CONTROLLER_BASE, //CTR + SUBSYSTEM_BASE, //SB + MODE_STORE_IF, //MS + SUBSYSTEM, //SS + HAS_MODES_IF, //HM + COMMAND_MESSAGE, //CM + CCSDS_TIME_HELPER_CLASS, //TIM + ARRAY_LIST, //AL + ASSEMBLY_BASE, //AB + MEMORY_HELPER, //MH + SERIALIZE_IF, //SE + FIXED_MAP, //FM + HAS_HEALTH_IF, //HHI + FIFO_CLASS, //FF + MESSAGE_PROXY, //MQP + TRIPLE_REDUNDACY_CHECK, //TRC + TC_PACKET_CHECK, //TCC + PACKET_DISTRIBUTION, //TCD + ACCEPTS_TELECOMMANDS_IF, //PUS + DEVICE_SERVICE_BASE, //DSB + COMMAND_SERVICE_BASE, //CSB + TM_STORE_BACKEND_IF, //TMB + TM_STORE_FRONTEND_IF, //TMF + STORAGE_AND_RETRIEVAL_SERVICE, //SR + MATCH_TREE_CLASS, //MT + EVENT_MANAGER_IF, //EV + HANDLES_FAILURES_IF, //FDI + DEVICE_HANDLER_IF, //DHI + STORAGE_MANAGER_IF, //SM + THERMAL_COMPONENT_IF, //TC + INTERNAL_ERROR_CODES, //IEC + TRAP, //TRP + CCSDS_HANDLER_IF, //CCS + PARAMETER_WRAPPER, //PAW + HAS_PARAMETERS_IF, //HPA + ASCII_CONVERTER, //ASC + POWER_SWITCHER, //POS + LIMITS_IF, //LIM + COMMANDS_ACTIONS_IF, //CF + HAS_ACTIONS_IF, //HF + DEVICE_COMMUNICATION_IF, //DC + BSP, //BSP + TIME_STAMPER_IF, //TSI 52 + FW_CLASS_ID_COUNT //is actually count + 1 ! + +}; +} + +#endif /* FRAMEWORK_RETURNVALUES_FWCLASSIDS_H_ */ diff --git a/returnvalues/HasReturnvaluesIF.h b/returnvalues/HasReturnvaluesIF.h index 1ce13557..5adbca3f 100644 --- a/returnvalues/HasReturnvaluesIF.h +++ b/returnvalues/HasReturnvaluesIF.h @@ -1,94 +1,14 @@ -/* - * HasReturnvaluesIF.h - * - * Created on: 05.11.2012 - * Author: mohr - */ - #ifndef HASRETURNVALUESIF_H_ #define HASRETURNVALUESIF_H_ #include +#include +#include #define MAKE_RETURN_CODE( number ) ((INTERFACE_ID << 8) + (number)) typedef uint16_t ReturnValue_t; -//TODO: make one storageIF containing all possible returnvalues for storing things -//A list of current interface id's. May be an enum. May be put in a separate header file. -#define OPERATING_SYSTEM_ABSTRACTION 0x01 //OS -#define OBJECT_MANAGER_IF 0x02 //OM -#define DEVICE_HANDLER_BASE 0x03 //DHB -#define RMAP_CHANNEL 0x04 //RMP -#define POWER_SWITCH_IF 0x05 //PS -#define HAS_MEMORY_IF 0x06 //PP -#define DEVICE_STATE_MACHINE_BASE 0x07 //DSMB -#define DATA_SET_CLASS 0x08 //DPS -#define POOL_RAW_ACCESS_CLASS 0x09 //DPR -#define CONTROLLER_BASE 0x0A //CTR -#define SUBSYSTEM_BASE 0x0B //SB -#define MODE_STORE_IF 0x0C //MS -#define SUBSYSTEM 0x0D //SS -#define HAS_MODES_IF 0x0E //HM -#define COMMAND_MESSAGE 0x0F //CM -#define CCSDS_TIME_HELPER_CLASS 0x10 //TIM -#define STAR_TRACKER_HANDLER 0x11 //STR -#define ARRAY_LIST 0x12 //AL -#define ASSEMBLY_BASE 0x13 //AB -#define MEMORY_HELPER 0x14 //MH -#define PCDU_HANDLER_CLASS 0x15 //PHC -#define RW_HANDLER_CLASS 0x16 //RWC -#define PLOC_CC_CLASS 0x17 //PCC -#define SERIALIZE_IF 0x18 //SE -#define FIXED_MAP 0x19 //FM -#define HAS_HEALTH_IF 0x1A //HHI -#define FRAME_FINDER_IF 0x1B //FFI -#define TM_VG_GENERATOR_IF 0x1C //VCG -#define FIFO_CLASS 0x1D //FF -#define MESSAGE_PROXY 0x1E //MQP -#define TRIPLE_REDUNDACY_CHECK 0x1F //TRC -#define TC_PACKET_CHECK 0x20 //TCC -#define PACKET_DISTRIBUTION 0x21 //TCD -#define ACCEPTS_TELECOMMANDS_IF 0x22 //PUS -#define DEVICE_SERVICE_BASE 0x23 //DSB -#define FUNCTION_MANAGEMENT_SERVICE 0x24 //FM -#define HOUSEKEEPING_SERVICE 0x25 //HK -#define MEMORY_MANAGEMENT_SERVICE 0x26 //MM -#define COMMAND_SERVICE_BASE 0x27 //CSB -#define OPERATIONS_SCHEDULING_SERVICE 0x28 //SCH -#define TM_STORE_BACKEND_IF 0x29 //TMB -#define TM_STORE_FRONTEND_IF 0x2A //TMF -#define STORAGE_AND_RETRIEVAL_SERVICE 0x2B //SR -#define MATCH_TREE_CLASS 0x2C //MT -#define EVENT_MANAGER_IF 0x2D //EV -#define HANDLES_FAILURES_IF 0x2E //FDI -#define DEVICE_HANDLER_IF 0x2F //DHI -#define STORAGE_MANAGER_IF 0x30 //SM -#define THERMAL_COMPONENT_IF 0x31 //TC -#define THERMAL_CONTROLLER_CLASS 0x33 //TCC -#define FOG_HANDLER_CLASS 0x34 //FHC -#define INTERNAL_ERROR_CODES 0x35 //IEC -#define TRAP 0x36 //TRP -#define PAYLOAD_HANDLING 0x37 //PLH -#define GPS_MONITORING 0x3A //GPSM -#define SUS_MONITORING 0x3B //SUSM -#define MGMMGT_MONITORING 0x3C //MGMT -#define FOG_MONITORING 0x3D //FOGM -#define STR_MONITORING 0x3E //STRM -#define DEPLOYMENT_CONTROLLER_CLASS 0x3F //DPLC -#define CCSDS_HANDLER_IF 0x40 //CCS -#define ACS_CONTROLLER_CLASS 0x41 //ACS -#define SGP4PROPAGATOR_CLASS 0x42 //SGP -#define PARAMETER_WRAPPER 0x43 //PAW -#define HAS_PARAMETERS_IF 0x44 //HPA -#define ASCII_CONVERTER 0x50 //ASC -#define POWER_SWITCHER 0x51 //POS -#define CCSDS_BOARD_HANDLER 0x52 //CBH -#define LIMITS_IF 0x60 //LIM -#define COMMANDS_ACTIONS_IF 0x80 //CF -#define HAS_ACTIONS_IF 0x81 //HF -#define DEVICE_COMMUNICATION_IF 0x90 //DC -#define BSP 0xF0 //BSP diff --git a/rmap/RMAP.cpp b/rmap/RMAP.cpp index 23fe1eae..3f55e88b 100644 --- a/rmap/RMAP.cpp +++ b/rmap/RMAP.cpp @@ -8,8 +8,6 @@ ReturnValue_t RMAP::reset(RMAPCookie* cookie) { return cookie->channel->reset(); } -//TODO Check for channel == NULL -//Done. BB RMAP::RMAP(){ } diff --git a/rmap/RMAP.h b/rmap/RMAP.h index 15d4aa64..195574f8 100644 --- a/rmap/RMAP.h +++ b/rmap/RMAP.h @@ -4,7 +4,7 @@ #include #include -//TODO: clean up includes for RMAP, should be enough to include RMAP.h but right now it's quite chaotic... +//SHOULDTODO: clean up includes for RMAP, should be enough to include RMAP.h but right now it's quite chaotic... /** * API for a Cookie/Channel based RMAP implementation. @@ -36,7 +36,7 @@ */ class RMAP: public HasReturnvaluesIF { public: - static const uint8_t INTERFACE_ID = RMAP_CHANNEL; + static const uint8_t INTERFACE_ID = CLASS_ID::RMAP_CHANNEL; //static const ReturnValue_t COMMAND_OK = MAKE_RETURN_CODE(0x00); static const ReturnValue_t COMMAND_NO_DESCRIPTORS_AVAILABLE = @@ -53,6 +53,7 @@ public: 0xE7); //The specified port is not valid static const ReturnValue_t COMMAND_PORT_IN_USE = MAKE_RETURN_CODE(0xE8);//The specified port is already in use static const ReturnValue_t COMMAND_NO_CHANNEL = MAKE_RETURN_CODE(0xE9);//The cookie to work with has no channel assigned. + static const ReturnValue_t NO_HW_CRC = MAKE_RETURN_CODE(0xEA);//The SpW port does not support HW CRC generation, which is unsupported //return values for both get_write_reply and get_read_reply static const ReturnValue_t REPLY_NO_REPLY = MAKE_RETURN_CODE(0xD0); //no reply was received static const ReturnValue_t REPLY_NOT_SENT = MAKE_RETURN_CODE(0xD1); //command was not sent, implies no reply diff --git a/rmap/RMAPChannelIF.h b/rmap/RMAPChannelIF.h index 17e98ea5..11cf5256 100644 --- a/rmap/RMAPChannelIF.h +++ b/rmap/RMAPChannelIF.h @@ -1,14 +1,8 @@ -/* - * RMAPChannelIF.h - * - * Created on: 31.05.2013 - * Author: tod - */ - #ifndef RMAPCHANNELIF_H_ #define RMAPCHANNELIF_H_ #include +#include class RMAPChannelIF: public RMAP { public: @@ -48,7 +42,7 @@ public: * - @c COMMAND_PORT_OUT_OF_RANGE if the port is invalid */ virtual ReturnValue_t setPort(int8_t port, uint8_t dest_addr, - uint8_t src_addr)=0; + uint8_t src_addr, PeriodicTaskIF* currentTask)=0; /** * Assign a SpaceWire port to the Channel @@ -60,7 +54,7 @@ public: * - @c COMMAND_OK if port was changed * - @c COMMAND_PORT_OUT_OF_RANGE if the port is invalid */ - virtual ReturnValue_t setPort(int8_t port)=0; + virtual ReturnValue_t setPort(int8_t port, PeriodicTaskIF* currentTask)=0; /** * Send an RMAP command diff --git a/rmap/RMAPCookie.cpp b/rmap/RMAPCookie.cpp index 3e857e52..2e9be1b5 100644 --- a/rmap/RMAPCookie.cpp +++ b/rmap/RMAPCookie.cpp @@ -1,15 +1,8 @@ -/* - * RMAPcpp - * - * Created on: 07.11.2012 - * Author: mohr - */ - #include #include #include -//TODO use ctor initialization list + RMAPCookie::RMAPCookie() { this->header.dest_address = 0; this->header.protocol = 0x01; diff --git a/rmap/RMAPCookie.h b/rmap/RMAPCookie.h index 09ac7030..9918d4b4 100644 --- a/rmap/RMAPCookie.h +++ b/rmap/RMAPCookie.h @@ -1,10 +1,3 @@ -/* - * RMAPCookie.h - * - * Created on: 07.11.2012 - * Author: mohr - */ - #ifndef RMAPCOOKIE_H_ #define RMAPCOOKIE_H_ diff --git a/rmap/RmapSPWChannel.cpp b/rmap/RmapSPWChannel.cpp index 9364bd93..d82166d1 100644 --- a/rmap/RmapSPWChannel.cpp +++ b/rmap/RmapSPWChannel.cpp @@ -1,10 +1,3 @@ -/* - * RMAPStack.cpp - * - * Created on: 30.05.2013 - * Author: tod - */ - #include extern "C" { #include @@ -33,18 +26,18 @@ extern "C" { RmapSPWChannel::RmapSPWChannel(object_id_t setObjectId, uint16_t buffersize_words, uint32_t maxPacketSize, int8_t portNr, - uint8_t dest_addr, uint8_t src_addr, + uint8_t dest_addr, uint8_t src_addr, PeriodicTaskIF* currentTask, datapool::opus_variable_id portVariable) : - SystemObject(setObjectId), port(NULL), port_has_crc(0), rx_index(0), max_rx( - 128), tx_index(0), max_tx(64), src_addr(src_addr), dest_addr( - dest_addr), portPoolId(portVariable) { + SystemObject(setObjectId), port(NULL), rx_index(0), max_rx(128), tx_index( + 0), max_tx(64), src_addr(src_addr), dest_addr(dest_addr), portPoolId( + portVariable) { buffer = new uint32_t[buffersize_words]; buffer_pointer = buffer; end_of_buffer = &buffer[buffersize_words]; max_packet_len = maxPacketSize & 0x1FFFFFC; tid = 0; failure_table = new uint16_t[128]; - setPort(portNr, dest_addr, src_addr); + setPort(portNr, dest_addr, src_addr, currentTask); } RmapSPWChannel::~RmapSPWChannel() { @@ -57,8 +50,6 @@ ReturnValue_t RmapSPWChannel::reset() { uint8_t missed, i; uint32_t state; - //printf_sif_rmap("reset channel %i\n", channel_nr); - //check if channel has a port if (port == NULL) { return COMMAND_CHANNEL_DEACTIVATED; @@ -114,7 +105,7 @@ ReturnValue_t RmapSPWChannel::reset() { if (missed == rx_index) { link_down++; } - //TODO: checkme + for (i = rx_index - missed; i > 0; i--) { if (!(failure_table[i - 1] & 1)) { checkRxDescPacket(&(rx_descriptor_table[i - 1]), @@ -166,7 +157,7 @@ ReturnValue_t RmapSPWChannel::isActive() { } ReturnValue_t RmapSPWChannel::setPort(int8_t portNr, uint8_t dest_addr, - uint8_t src_addr) { + uint8_t src_addr, PeriodicTaskIF* currentTask) { SPW_dev *new_port; @@ -175,8 +166,13 @@ ReturnValue_t RmapSPWChannel::setPort(int8_t portNr, uint8_t dest_addr, return COMMAND_PORT_OUT_OF_RANGE; } + //check if crc is enabled + if (portNr != -1) { new_port = SPW_devices.devices[portNr]; + if (!spw_crc_enabled(new_port)) { + return NO_HW_CRC; + } } else { new_port = NULL; } @@ -203,8 +199,6 @@ ReturnValue_t RmapSPWChannel::setPort(int8_t portNr, uint8_t dest_addr, //stop the new port spw_stop(new_port); -//check if crc is enabled - port_has_crc = spw_crc_enabled(new_port); //make sure the new port has the max len set new_port->SPWRXL = max_packet_len; //set the addresses @@ -218,13 +212,13 @@ ReturnValue_t RmapSPWChannel::setPort(int8_t portNr, uint8_t dest_addr, spw_reset_txdesc_table(new_port); //reset the channel spw_start(new_port); - OSAL::sleepFor(10); + currentTask->sleepFor(10); reset(); return RETURN_OK; } -ReturnValue_t RmapSPWChannel::setPort(int8_t port) { - return setPort(port, this->dest_addr, this->src_addr); +ReturnValue_t RmapSPWChannel::setPort(int8_t port, PeriodicTaskIF* currentTask) { + return setPort(port, this->dest_addr, this->src_addr, currentTask); } spw_rx_desc* RmapSPWChannel::findReply(RMAPCookie* cookie) { @@ -232,7 +226,6 @@ spw_rx_desc* RmapSPWChannel::findReply(RMAPCookie* cookie) { uint8_t i; //look downwards -//TODO: checkme for (i = cookie->rxdesc_index; i < 200; i--) { if ((rxdesc = checkRxDesc(cookie, i)) != NULL) { return rxdesc; @@ -334,21 +327,6 @@ ReturnValue_t RmapSPWChannel::sendCommand(RMAPCookie* cookie, buffer_pointer += BYTES2WORDS(RMAP_READ_REPLY_HEADER_LEN + datalen + 1); //+1 for crc } -//calculate crc if not done in hw - if (!port_has_crc) { - cookie->header.header_crc = crc_calculate((uint8_t *) &cookie->header, - RMAP_COMMAND_HEADER_LEN - 1); - headerlen = RMAP_COMMAND_HEADER_LEN; - if (instruction & (1 << RMAP_COMMAND_BIT_WRITE)) { - if (datalen == 0) { - data = &null_crc; - } else { - data[datalen] = crc_calculate(data, datalen); - } - datalen++; - } - } - //configure tx_descriptor tx_descriptor_table[tx_index].word1 = (uint32_t) &cookie->header; if (instruction & (1 << RMAP_COMMAND_BIT_WRITE)) { @@ -357,18 +335,14 @@ ReturnValue_t RmapSPWChannel::sendCommand(RMAPCookie* cookie, tx_descriptor_table[tx_index].word2 = 0; } tx_descriptor_table[tx_index].word3 = (uint32_t) data; - if (port_has_crc) { - if (instruction & (1 << RMAP_COMMAND_BIT_WRITE)) { - tx_descriptor_table[tx_index].word0 = headerlen - | (1 << SPW_DESC_TX_ENABLE) | (1 << SPW_DESC_TX_CRC_DATA) - | (1 << SPW_DESC_TX_CRC_HEADER); - } else { - tx_descriptor_table[tx_index].word0 = headerlen - | (1 << SPW_DESC_TX_ENABLE) | (1 << SPW_DESC_TX_CRC_HEADER); - } + + if (instruction & (1 << RMAP_COMMAND_BIT_WRITE)) { + tx_descriptor_table[tx_index].word0 = headerlen + | (1 << SPW_DESC_TX_ENABLE) | (1 << SPW_DESC_TX_CRC_DATA) + | (1 << SPW_DESC_TX_CRC_HEADER); } else { tx_descriptor_table[tx_index].word0 = headerlen - | (1 << SPW_DESC_TX_ENABLE); + | (1 << SPW_DESC_TX_ENABLE) | (1 << SPW_DESC_TX_CRC_HEADER); } //remember descriptors to find them faster when looking for the reply @@ -404,7 +378,6 @@ ReturnValue_t RmapSPWChannel::getReply(RMAPCookie* cookie, uint8_t** databuffer, //reply_header = (rmap_write_reply_header *) rxdesc->word1; if (databuffer != NULL) { packetlen = (rxdesc->word0 & 0x1FFFFFF); - // printf_sif("Reached critical entry.\n"); *databuffer = ((uint8_t *) rxdesc->word1) + RMAP_READ_REPLY_HEADER_LEN; *len = packetlen - RMAP_READ_REPLY_HEADER_LEN - 1; } @@ -623,7 +596,7 @@ ReturnValue_t RmapSPWChannel::sendCommandBlocking(RMAPCookie *cookie, return REPLY_TIMEOUT; } -//TODO find a better way to inject the Extended address +//SHOULDDO find a better way to inject the Extended address #include ReturnValue_t RmapSPWChannel::open(Cookie **cookie, uint32_t address, uint32_t maxReplyLen) { @@ -647,7 +620,7 @@ ReturnValue_t RmapSPWChannel::reOpen(Cookie* cookie, uint32_t address, rCookie->setCommandMask(0); rCookie->setExtendedAddress(IoBoardExtendedAddresses::DEVICE_BUFFER); rCookie->setMaxReplyLen(maxReplyLen); - return REPLY_OK; + return RETURN_OK; } void RmapSPWChannel::close(Cookie* cookie) { @@ -692,7 +665,6 @@ uint32_t RmapSPWChannel::getParameter(Cookie* cookie) { void RmapSPWChannel::reportFailures(uint16_t failureEntry, uint8_t descriptorNr) { - //TODO: Communicate to Kai, adjust return codes. if (failureEntry & (1 << RMAP_RX_FAIL_CRC)) { triggerEvent(RMAP_PROTOCOL_ERROR, REPLY_INVALID_DATA_CRC, descriptorNr); } @@ -730,13 +702,11 @@ void RmapSPWChannel::reportFailures(uint16_t failureEntry, } if (failureEntry & (1 << RMAP_RX_FAIL_WRONG_REPLY)) { triggerEvent(RMAP_PROTOCOL_ERROR, REPLY_INVALID_KEY, descriptorNr); - ; } } void RmapSPWChannel::reportSpwstr(uint32_t spwstr) { - //TODO: Communicate to Kai. if (spwstr & (1 << SPW_SPWSTR_CE)) { triggerEvent(SPW_ERROR, SPW_CREDIT); } diff --git a/rmap/RmapSPWChannel.h b/rmap/RmapSPWChannel.h index 4ef82472..4f097ac3 100644 --- a/rmap/RmapSPWChannel.h +++ b/rmap/RmapSPWChannel.h @@ -1,10 +1,3 @@ -/* - * RMAPStack.h - * - * Created on: 30.05.2013 - * Author: tod - */ - #ifndef RMAPCHANNEL_H_ #define RMAPCHANNEL_H_ @@ -16,6 +9,7 @@ extern "C" { #include #include #include +#include class RmapSPWChannel: public SystemObject, public RMAPChannelIF, @@ -52,7 +46,7 @@ public: RmapSPWChannel(object_id_t setObjectId, uint16_t buffersize_words, uint32_t maxPacketSize, int8_t portNr, uint8_t dest_addr, - uint8_t src_addr, datapool::opus_variable_id portVariable = + uint8_t src_addr, PeriodicTaskIF* currentTask, datapool::opus_variable_id portVariable = datapool::NO_PARAMETER); virtual ~RmapSPWChannel(); @@ -62,9 +56,9 @@ public: virtual ReturnValue_t isActive(); virtual ReturnValue_t setPort(int8_t port, uint8_t dest_addr, - uint8_t src_addr); + uint8_t src_addr, PeriodicTaskIF* currentTask); - virtual ReturnValue_t setPort(int8_t port); + virtual ReturnValue_t setPort(int8_t port, PeriodicTaskIF* currentTask); virtual ReturnValue_t sendCommand(RMAPCookie *cookie, uint8_t instruction, uint8_t *data, uint32_t datalen); @@ -111,7 +105,7 @@ private: uint16_t *failure_table; uint32_t max_packet_len; uint16_t tid; - uint8_t port_has_crc; +// uint8_t port_has_crc; uint8_t rx_index; //index of the next unused rx descriptor uint8_t max_rx; uint8_t tx_index; //index of the next unused tx descriptor diff --git a/rmap/rmapStructs.h b/rmap/rmapStructs.h index 978e488c..aa609143 100644 --- a/rmap/rmapStructs.h +++ b/rmap/rmapStructs.h @@ -1,16 +1,9 @@ -/* - * rmapStructs.h - * - * Created on: 30.05.2013 - * Author: tod - */ - #ifndef RMAPSTRUCTS_H_ #define RMAPSTRUCTS_H_ #include -//TODO: having the defines within a namespace would be nice. Problem are the defines referencing the previous define, eg RMAP_COMMAND_WRITE +//SHOULDDO: having the defines within a namespace would be nice. Problem are the defines referencing the previous define, eg RMAP_COMMAND_WRITE ////////////////////////////////////////////////////////////////////////////////// // RMAP command bits diff --git a/serialize/EndianSwapper.h b/serialize/EndianSwapper.h index bf883a2a..b46a2852 100644 --- a/serialize/EndianSwapper.h +++ b/serialize/EndianSwapper.h @@ -1,9 +1,9 @@ #ifndef ENDIANSWAPPER_H_ #define ENDIANSWAPPER_H_ -#include //#include //for testing on x86 - +#include +#include class EndianSwapper { private: diff --git a/serialize/SerialArrayListAdapter.h b/serialize/SerialArrayListAdapter.h index 1384775f..2ad77a74 100644 --- a/serialize/SerialArrayListAdapter.h +++ b/serialize/SerialArrayListAdapter.h @@ -57,11 +57,13 @@ public: static ReturnValue_t deSerialize(ArrayList* list, const uint8_t** buffer, int32_t* size, bool bigEndian) { - ReturnValue_t result = SerializeAdapter::deSerialize(&list->size, + count_t tempSize = 0; + ReturnValue_t result = SerializeAdapter::deSerialize(&tempSize, buffer, size, bigEndian); - if (list->size > list->maxSize()) { + if (tempSize > list->maxSize()) { return SerializeIF::TOO_MANY_ELEMENTS; } + list->size = tempSize; count_t i = 0; while ((result == HasReturnvaluesIF::RETURN_OK) && (i < list->size)) { result = SerializeAdapter::deSerialize( diff --git a/serialize/SerialBufferAdapter.cpp b/serialize/SerialBufferAdapter.cpp index da27432f..3ed083bf 100644 --- a/serialize/SerialBufferAdapter.cpp +++ b/serialize/SerialBufferAdapter.cpp @@ -1,23 +1,41 @@ #include #include -SerialBufferAdapter::SerialBufferAdapter(const uint8_t* buffer, - uint32_t bufferLength) : - constBuffer(buffer), buffer(NULL), bufferLength(bufferLength) { + + +template +SerialBufferAdapter::SerialBufferAdapter(const uint8_t* buffer, + T bufferLength, bool serializeLenght) : + serializeLength(serializeLenght), constBuffer(buffer), buffer(NULL), bufferLength( + bufferLength) { } -SerialBufferAdapter::SerialBufferAdapter(uint8_t* buffer, uint32_t bufferLength) : - constBuffer(NULL), buffer(buffer), bufferLength(bufferLength) { +template +SerialBufferAdapter::SerialBufferAdapter(uint8_t* buffer, T bufferLength, + bool serializeLenght) : + serializeLength(serializeLenght), constBuffer(NULL), buffer(buffer), bufferLength( + bufferLength) { } -SerialBufferAdapter::~SerialBufferAdapter() { +template +SerialBufferAdapter::~SerialBufferAdapter() { } -ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, uint32_t* size, +template +ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, uint32_t* size, const uint32_t max_size, bool bigEndian) const { - if (*size + bufferLength > max_size) { + uint32_t serializedLength = bufferLength; + if (serializeLength) { + serializedLength += AutoSerializeAdapter::getSerializedSize( + &bufferLength); + } + if (*size + serializedLength > max_size) { return BUFFER_TOO_SHORT; } else { + if (serializeLength) { + AutoSerializeAdapter::serialize(&bufferLength, buffer, size, + max_size, bigEndian); + } if (this->constBuffer != NULL) { memcpy(*buffer, this->constBuffer, bufferLength); } else if (this->buffer != NULL) { @@ -26,22 +44,39 @@ ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, uint32_t* size, return HasReturnvaluesIF::RETURN_FAILED; } *size += bufferLength; - buffer += bufferLength; + (*buffer) += bufferLength; return HasReturnvaluesIF::RETURN_OK; } } -uint32_t SerialBufferAdapter::getSerializedSize() const { - return bufferLength; +template +uint32_t SerialBufferAdapter::getSerializedSize() const { + if (serializeLength) { + return bufferLength + AutoSerializeAdapter::getSerializedSize(&bufferLength); + } else { + return bufferLength; + } } - -ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, +template +ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, int32_t* size, bool bigEndian) { + //TODO Ignores Endian flag! if (buffer != NULL) { + if(serializeLength){ + T serializedSize = AutoSerializeAdapter::getSerializedSize( + &bufferLength); + if((*size - bufferLength - serializedSize) >= 0){ + *buffer += serializedSize; + *size -= serializedSize; + }else{ + return STREAM_TOO_SHORT; + } + } + //No Else If, go on with buffer if (*size - bufferLength >= 0) { *size -= bufferLength; memcpy(this->buffer, *buffer, bufferLength); - buffer += bufferLength; + (*buffer) += bufferLength; return HasReturnvaluesIF::RETURN_OK; } else { return STREAM_TOO_SHORT; @@ -50,3 +85,10 @@ ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, return HasReturnvaluesIF::RETURN_FAILED; } } + + +//forward Template declaration for linker +template class SerialBufferAdapter; +template class SerialBufferAdapter; +template class SerialBufferAdapter; + diff --git a/serialize/SerialBufferAdapter.h b/serialize/SerialBufferAdapter.h index eb763b24..7817a232 100644 --- a/serialize/SerialBufferAdapter.h +++ b/serialize/SerialBufferAdapter.h @@ -2,11 +2,14 @@ #define SERIALBUFFERADAPTER_H_ #include +#include +template class SerialBufferAdapter: public SerializeIF { public: - SerialBufferAdapter(const uint8_t * buffer, uint32_t bufferLength); - SerialBufferAdapter(uint8_t* buffer, uint32_t bufferLength); + SerialBufferAdapter(const uint8_t * buffer, T bufferLength, bool serializeLenght = false); + SerialBufferAdapter(uint8_t* buffer, T bufferLength, + bool serializeLenght = false); virtual ~SerialBufferAdapter(); @@ -18,9 +21,12 @@ public: virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, bool bigEndian); private: + bool serializeLength; const uint8_t *constBuffer; uint8_t *buffer; - uint32_t bufferLength; + T bufferLength; }; + + #endif /* SERIALBUFFERADAPTER_H_ */ diff --git a/serialize/SerialFixedArrayListAdapter.h b/serialize/SerialFixedArrayListAdapter.h index 14739092..41e2ae7e 100644 --- a/serialize/SerialFixedArrayListAdapter.h +++ b/serialize/SerialFixedArrayListAdapter.h @@ -1,10 +1,3 @@ -/* - * SerialFixedArrayListAdapter.h - * - * Created on: 22.07.2014 - * Author: baetz - */ - #ifndef SERIALFIXEDARRAYLISTADAPTER_H_ #define SERIALFIXEDARRAYLISTADAPTER_H_ diff --git a/serialize/SerializeAdapter.h b/serialize/SerializeAdapter.h index f1fb2709..e64968c7 100644 --- a/serialize/SerializeAdapter.h +++ b/serialize/SerializeAdapter.h @@ -1,10 +1,3 @@ -/* - * SerializeAdapter.h - * - * Created on: 19.03.2014 - * Author: baetz - */ - #ifndef SERIALIZEADAPTER_H_ #define SERIALIZEADAPTER_H_ @@ -104,4 +97,26 @@ public: } }; + +class AutoSerializeAdapter { +public: + template + static ReturnValue_t serialize(const T* object, uint8_t** buffer, + uint32_t* size, const uint32_t max_size, bool bigEndian) { + SerializeAdapter_::Is> adapter; + return adapter.serialize(object, buffer, size, max_size, bigEndian); + } + template + static uint32_t getSerializedSize(const T* object) { + SerializeAdapter_::Is> adapter; + return adapter.getSerializedSize(object); + } + template + static ReturnValue_t deSerialize(T* object, const uint8_t** buffer, + int32_t* size, bool bigEndian) { + SerializeAdapter_::Is> adapter; + return adapter.deSerialize(object, buffer, size, bigEndian); + } +}; + #endif /* SERIALIZEADAPTER_H_ */ diff --git a/serialize/SerializeElement.h b/serialize/SerializeElement.h index 4f0fb1ba..a269bc77 100644 --- a/serialize/SerializeElement.h +++ b/serialize/SerializeElement.h @@ -1,10 +1,3 @@ -/* - * SerializeElement.h - * - * Created on: 24.03.2014 - * Author: baetz - */ - #ifndef SERIALIZEELEMENT_H_ #define SERIALIZEELEMENT_H_ diff --git a/serialize/SerializeIF.h b/serialize/SerializeIF.h index efc12630..5c36279e 100644 --- a/serialize/SerializeIF.h +++ b/serialize/SerializeIF.h @@ -1,10 +1,3 @@ -/* - * SerializeIF.h - * - * Created on: 19.03.2014 - * Author: baetz - */ - #ifndef SERIALIZEIF_H_ #define SERIALIZEIF_H_ @@ -12,7 +5,7 @@ class SerializeIF { public: - static const uint8_t INTERFACE_ID = SERIALIZE_IF; + static const uint8_t INTERFACE_ID = CLASS_ID::SERIALIZE_IF; static const ReturnValue_t BUFFER_TOO_SHORT = MAKE_RETURN_CODE(1); static const ReturnValue_t STREAM_TOO_SHORT = MAKE_RETURN_CODE(2); static const ReturnValue_t TOO_MANY_ELEMENTS = MAKE_RETURN_CODE(3); diff --git a/serviceinterface/Makefile b/serviceinterface/Makefile deleted file mode 100755 index fb0de152..00000000 --- a/serviceinterface/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash -# -# OSAL makefile -# -# Created on: Mar 04, 2010 -# Author: ziemke -# Author: Claas Ziemke -# Copyright 2010, Claas Ziemke -# - -BASEDIR=../../ -include $(BASEDIR)options.mk - -OBJ = $(BUILDDIR)/OPUSLogger.o - -all: $(OBJ) - -$(BUILDDIR)/%.o: %.cpp %.h - $(CPP) $(CFLAGS) $(DEFINES) $(CCOPT) ${INCLUDE} -c $< -o $@ - -clean: - $(RM) *.o *.gcno *.gcda diff --git a/serviceinterface/ServiceInterfaceBuffer.cpp b/serviceinterface/ServiceInterfaceBuffer.cpp index 3e13452a..ceb81c4b 100644 --- a/serviceinterface/ServiceInterfaceBuffer.cpp +++ b/serviceinterface/ServiceInterfaceBuffer.cpp @@ -1,12 +1,9 @@ -/* - * ServiceInterfaceBuffer.cpp - * - * Created on: 06.08.2015 - * Author: baetz - */ - -#include +#include #include +#include + +//TODO Think of something different +#include int ServiceInterfaceBuffer::overflow(int c) { // Handle output @@ -24,8 +21,8 @@ int ServiceInterfaceBuffer::overflow(int c) { int ServiceInterfaceBuffer::sync(void) { if (this->isActive) { - TimeOfDay_t loggerTime; - OSAL::getDateAndTime(&loggerTime); + Clock::TimeOfDay_t loggerTime; + Clock::getDateAndTime(&loggerTime); char preamble[96] = { 0 }; sprintf(preamble, "%s: | %lu:%02lu:%02lu.%03lu | ", this->log_message.c_str(), (unsigned long) loggerTime.hour, @@ -57,16 +54,12 @@ void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { } memcpy(array, begin, length); -#ifdef DEBUG - if (!OSAL::isInterruptInProgress()) { + if (!Interrupt::isInterruptInProgress()) { std::cout << array; } else { //Uncomment the following line if you need ISR debug output. // printk(array); } -#else -#error Non-DEBUG out messages are not implemented. define DEBUG flag! -#endif } #endif //UT699 @@ -95,14 +88,12 @@ void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) { if (udpSocket <= 0) { initSocket(); } -#ifdef DEBUG + if (udpSocket > 0) { sendto(udpSocket, array, length, 0, (sockaddr*) &remoteAddress, sizeof(remoteAddress)); } -#else -#error Non-DEBUG out messages are not implemented. define DEBUG flag! -#endif + } void ServiceInterfaceBuffer::initSocket() { diff --git a/serviceinterface/ServiceInterfaceBuffer.h b/serviceinterface/ServiceInterfaceBuffer.h index 7fa1dd54..1688b115 100644 --- a/serviceinterface/ServiceInterfaceBuffer.h +++ b/serviceinterface/ServiceInterfaceBuffer.h @@ -1,10 +1,3 @@ -/* - * ServiceInterfaceBuffer.h - * - * Created on: 06.08.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_ #define FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_ diff --git a/serviceinterface/ServiceInterfaceStream.cpp b/serviceinterface/ServiceInterfaceStream.cpp index 7d61dabe..c2979f36 100644 --- a/serviceinterface/ServiceInterfaceStream.cpp +++ b/serviceinterface/ServiceInterfaceStream.cpp @@ -1,11 +1,3 @@ -/* - * ServiceInterfaceStream.cpp - * - * Created on: 06.08.2015 - * Author: baetz - */ - - #include void ServiceInterfaceStream::setActive( bool myActive) { diff --git a/serviceinterface/ServiceInterfaceStream.h b/serviceinterface/ServiceInterfaceStream.h index a95a67e5..32bc263e 100644 --- a/serviceinterface/ServiceInterfaceStream.h +++ b/serviceinterface/ServiceInterfaceStream.h @@ -1,10 +1,3 @@ -/* - * ServiceInterfaceStream.h - * - * Created on: 06.08.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_ #define FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACESTREAM_H_ diff --git a/storagemanager/LocalPool.h b/storagemanager/LocalPool.h index 253aa8b6..08cb017f 100644 --- a/storagemanager/LocalPool.h +++ b/storagemanager/LocalPool.h @@ -1,10 +1,3 @@ -/* - * LocalPool.h - * - * Created on: 11.02.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ #define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ @@ -20,9 +13,9 @@ #include #include #include +#include +#include #include -//TODO: Debugging.. remove! -//#include /** * @brief The LocalPool class provides an intermediate data storage with @@ -118,22 +111,6 @@ private: * @return Returns the position of the data in store. */ uint32_t getRawPosition(store_address_t packet_id); - /** - * With this helper method, a free element of \c size is reserved. - * - * @param size The minimum packet size that shall be reserved. - * @return Returns the storage identifier within the storage or - * StorageManagerIF::INVALID_ADDRESS (in raw). - */ - /** - * With this helper method, a free element of \c size is reserved. - * @param size The minimum packet size that shall be reserved. - * @param[out] address Storage ID of the reserved data. - * @return - #RETURN_OK on success, - * - the return codes of #getPoolIndex or #findEmpty otherwise. - */ - ReturnValue_t reserveSpace(const uint32_t size, store_address_t* address); -protected: /** * @brief This is a helper method to find an empty element in a given pool. * @details The method searches size_list for the first empty element, so @@ -143,7 +120,18 @@ protected: * @return - #RETURN_OK on success, * - #DATA_STORAGE_FULL if the store is full */ - virtual ReturnValue_t findEmpty(uint16_t pool_index, uint16_t* element); + ReturnValue_t findEmpty(uint16_t pool_index, uint16_t* element); +protected: + /** + * With this helper method, a free element of \c size is reserved. + * @param size The minimum packet size that shall be reserved. + * @param[out] address Storage ID of the reserved data. + * @return - #RETURN_OK on success, + * - the return codes of #getPoolIndex or #findEmpty otherwise. + */ + virtual ReturnValue_t reserveSpace(const uint32_t size, store_address_t* address, bool ignoreFault); + + InternalErrorReporterIF *internalErrorReporter; public: /** * @brief This is the default constructor for a pool manager instance. @@ -172,10 +160,17 @@ public: */ virtual ~LocalPool(void); ReturnValue_t addData(store_address_t* storageId, const uint8_t * data, - uint32_t size); + uint32_t size, bool ignoreFault = false); + /** + * With this helper method, a free element of \c size is reserved. + * + * @param size The minimum packet size that shall be reserved. + * @return Returns the storage identifier within the storage or + * StorageManagerIF::INVALID_ADDRESS (in raw). + */ ReturnValue_t getFreeElement(store_address_t* storageId, - const uint32_t size, uint8_t** p_data); + const uint32_t size, uint8_t** p_data, bool ignoreFault = false); ReturnValue_t getData(store_address_t packet_id, const uint8_t** packet_ptr, uint32_t* size); ReturnValue_t modifyData(store_address_t packet_id, uint8_t** packet_ptr, @@ -245,11 +240,12 @@ inline uint32_t LocalPool::getRawPosition( template inline ReturnValue_t LocalPool::reserveSpace( - const uint32_t size, store_address_t* address) { + const uint32_t size, store_address_t* address, bool ignoreFault) { ReturnValue_t status = getPoolIndex(size, &address->pool_index); if (status != RETURN_OK) { error << "LocalPool( " << std::hex << getObjectId() << std::dec << " )::reserveSpace: Packet too large." << std::endl; + return status; } status = findEmpty(address->pool_index, &address->packet_index); while (status != RETURN_OK && spillsToHigherPools) { @@ -261,11 +257,17 @@ inline ReturnValue_t LocalPool::reserveSpace( status = findEmpty(address->pool_index, &address->packet_index); } if (status == RETURN_OK) { -// debug << "LocalPool( " << translateObject(getObjectId()) << " )::reserveSpace: Empty position found: Position: Pool: " << address->pool_index << " Index: " << address->packet_index << std::endl; +// if (getObjectId() == objects::IPC_STORE && address->pool_index >= 3) { +// debug << "Reserve: Pool: " << std::dec << address->pool_index << " Index: " << address->packet_index << std::endl; +// } + size_list[address->pool_index][address->packet_index] = size; } else { - error << "LocalPool( " << std::hex << getObjectId() << std::dec - << " )::reserveSpace: Packet store is full." << std::endl; + if (!ignoreFault) { + internalErrorReporter->storeFull(); + } +// error << "LocalPool( " << std::hex << getObjectId() << std::dec +// << " )::reserveSpace: Packet store is full." << std::endl; } return status; } @@ -274,7 +276,7 @@ template inline LocalPool::LocalPool(object_id_t setObjectId, const uint16_t element_sizes[NUMBER_OF_POOLS], const uint16_t n_elements[NUMBER_OF_POOLS], bool registered, bool spillsToHigherPools) : - SystemObject(setObjectId, registered), spillsToHigherPools(spillsToHigherPools) { + SystemObject(setObjectId, registered), spillsToHigherPools(spillsToHigherPools), internalErrorReporter(NULL) { for (uint16_t n = 0; n < NUMBER_OF_POOLS; n++) { this->element_sizes[n] = element_sizes[n]; this->n_elements[n] = n_elements[n]; @@ -295,8 +297,8 @@ inline LocalPool::~LocalPool(void) { template inline ReturnValue_t LocalPool::addData( - store_address_t* storageId, const uint8_t* data, uint32_t size) { - ReturnValue_t status = reserveSpace(size, storageId); + store_address_t* storageId, const uint8_t* data, uint32_t size, bool ignoreFault) { + ReturnValue_t status = reserveSpace(size, storageId, ignoreFault); if (status == RETURN_OK) { write(*storageId, data, size); } @@ -305,8 +307,8 @@ inline ReturnValue_t LocalPool::addData( template inline ReturnValue_t LocalPool::getFreeElement( - store_address_t* storageId, const uint32_t size, uint8_t** p_data) { - ReturnValue_t status = reserveSpace(size, storageId); + store_address_t* storageId, const uint32_t size, uint8_t** p_data, bool ignoreFault) { + ReturnValue_t status = reserveSpace(size, storageId, ignoreFault); if (status == RETURN_OK) { *p_data = &store[storageId->pool_index][getRawPosition(*storageId)]; } else { @@ -328,19 +330,20 @@ template inline ReturnValue_t LocalPool::modifyData(store_address_t packet_id, uint8_t** packet_ptr, uint32_t* size) { ReturnValue_t status = RETURN_FAILED; - if ((packet_id.packet_index < n_elements[packet_id.pool_index]) - && (packet_id.pool_index < NUMBER_OF_POOLS)) { - if (size_list[packet_id.pool_index][packet_id.packet_index] - != STORAGE_FREE) { - uint32_t packet_position = getRawPosition(packet_id); - *packet_ptr = &store[packet_id.pool_index][packet_position]; - *size = size_list[packet_id.pool_index][packet_id.packet_index]; - status = RETURN_OK; - } else { - status = DATA_DOES_NOT_EXIST; - } + if (packet_id.pool_index >= NUMBER_OF_POOLS) { + return ILLEGAL_STORAGE_ID; + } + if ((packet_id.packet_index >= n_elements[packet_id.pool_index])) { + return ILLEGAL_STORAGE_ID; + } + if (size_list[packet_id.pool_index][packet_id.packet_index] + != STORAGE_FREE) { + uint32_t packet_position = getRawPosition(packet_id); + *packet_ptr = &store[packet_id.pool_index][packet_position]; + *size = size_list[packet_id.pool_index][packet_id.packet_index]; + status = RETURN_OK; } else { - status = ILLEGAL_STORAGE_ID; + status = DATA_DOES_NOT_EXIST; } return status; } @@ -348,7 +351,10 @@ inline ReturnValue_t LocalPool::modifyData(store_address_t pack template inline ReturnValue_t LocalPool::deleteData( store_address_t packet_id) { -// debug << "LocalPool( " << translateObject(getObjectId()) << " )::deleteData from store " << packet_id.pool_index << ". id is " << packet_id.packet_index << std::endl; + +// if (getObjectId() == objects::IPC_STORE && packet_id.pool_index >= 3) { +// debug << "Delete: Pool: " << std::dec << packet_id.pool_index << " Index: " << packet_id.packet_index << std::endl; +// } ReturnValue_t status = RETURN_OK; uint32_t page_size = getPageSize(packet_id.pool_index); if ((page_size != 0) @@ -359,7 +365,7 @@ inline ReturnValue_t LocalPool::deleteData( //Set free list size_list[packet_id.pool_index][packet_id.packet_index] = STORAGE_FREE; } else { - //packet_index is too large + //pool_index or packet_index is too large error << "LocalPool:deleteData failed." << std::endl; status = ILLEGAL_STORAGE_ID; } @@ -382,7 +388,7 @@ inline ReturnValue_t LocalPool::deleteData(uint8_t* ptr, //Not sure if new allocates all stores in order. so better be careful. if ((store[n] <= ptr) && (&store[n][n_elements[n]*element_sizes[n]]) > ptr) { localId.pool_index = n; - uint32_t deltaAddress = (uint32_t) ptr - (uint32_t) store[n]; + uint32_t deltaAddress = ptr - store[n]; //Getting any data from the right "block" is ok. This is necessary, as IF's sometimes don't point to the first element of an object. localId.packet_index = deltaAddress / element_sizes[n]; result = deleteData(localId); @@ -404,6 +410,11 @@ inline ReturnValue_t LocalPool::initialize() { if (result != RETURN_OK) { return result; } + internalErrorReporter = objectManager->get(objects::INTERNAL_ERROR_REPORTER); + if (internalErrorReporter == NULL){ + return RETURN_FAILED; + } + //Check if any pool size is large than the maximum allowed. for (uint8_t count = 0; count < NUMBER_OF_POOLS; count++) { if (element_sizes[count] >= STORAGE_FREE) { diff --git a/storagemanager/Makefile b/storagemanager/Makefile deleted file mode 100755 index 9ca946ac..00000000 --- a/storagemanager/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash -# -# OSAL makefile -# -# Created on: Mar 04, 2010 -# Author: ziemke -# Author: Claas Ziemke -# Copyright 2010, Claas Ziemke -# - -BASEDIR=../../ -include $(BASEDIR)options.mk - -OBJ = $(BUILDDIR)/TmTcStorage.o - -all: $(OBJ) - -$(BUILDDIR)/%.o: %.cpp %.h - $(CPP) $(CFLAGS) $(DEFINES) $(CCOPT) ${INCLUDE} -c $< -o $@ - -clean: - $(RM) *.o *.gcno *.gcda diff --git a/storagemanager/PoolManager.h b/storagemanager/PoolManager.h index 9be74049..da22d24b 100644 --- a/storagemanager/PoolManager.h +++ b/storagemanager/PoolManager.h @@ -11,8 +11,9 @@ #define POOLMANAGER_H_ -#include #include +#include +#include /** * @brief The PoolManager class provides an intermediate data storage with @@ -27,12 +28,13 @@ protected: * Overwritten for thread safety. * Locks during execution. */ - ReturnValue_t findEmpty( uint16_t pool_index, uint16_t* element ); + virtual ReturnValue_t reserveSpace(const uint32_t size, store_address_t* address, bool ignoreFault); + /** * \brief The mutex is created in the constructor and makes access mutual exclusive. * \details Locking and unlocking is done during searching for free slots and deleting existing slots. */ - MutexId_t* mutex; + MutexIF* mutex; public: PoolManager( object_id_t setObjectId, const uint16_t element_sizes[NUMBER_OF_POOLS], const uint16_t n_elements[NUMBER_OF_POOLS] ); /** @@ -47,16 +49,15 @@ public: }; template -inline ReturnValue_t PoolManager::findEmpty(uint16_t pool_index, - uint16_t* element) { - ReturnValue_t mutexStatus = OSAL::lockMutex( mutex, OSAL::NO_TIMEOUT ); +inline ReturnValue_t PoolManager::reserveSpace(const uint32_t size, store_address_t* address, bool ignoreFault) { + ReturnValue_t mutexStatus = mutex->lockMutex(MutexIF::NO_TIMEOUT); ReturnValue_t status = this->DATA_STORAGE_FULL; if ( mutexStatus == this->RETURN_OK ) { - status = LocalPool::findEmpty(pool_index, element); + status = LocalPool::reserveSpace(size,address,ignoreFault); } else { - error << "PoolManager::findEmpty: Mutex could not be acquired. Error code: " << status << std::endl; + error << "PoolManager::findEmpty: Mutex could not be acquired. Error code: " << mutexStatus << std::endl; } - mutexStatus = OSAL::unlockMutex( mutex ); + mutexStatus = mutex->lockMutex(MutexIF::NO_TIMEOUT); if (mutexStatus != this->RETURN_OK) { return mutexStatus; } else { @@ -68,31 +69,26 @@ template inline PoolManager::PoolManager(object_id_t setObjectId, const uint16_t element_sizes[NUMBER_OF_POOLS], const uint16_t n_elements[NUMBER_OF_POOLS]) : LocalPool(setObjectId, element_sizes, n_elements, true) { - mutex = new MutexId_t; - ReturnValue_t result = OSAL::createMutex( OSAL::buildName('M','T','X','1'), ( mutex ) ); - if (result != this->RETURN_OK) { - error << "PoolManager( " << std::hex << this->getObjectId() << std::dec << " )::ctor: Creating mutex failed." << std::endl; - } + mutex = MutexFactory::instance()->createMutex(); } template inline PoolManager::~PoolManager(void) { - OSAL::deleteMutex( mutex ); - delete mutex; + MutexFactory::instance()->deleteMutex(mutex); } template inline ReturnValue_t PoolManager::deleteData( store_address_t packet_id) { // debug << "PoolManager( " << translateObject(getObjectId()) << " )::deleteData from store " << packet_id.pool_index << ". id is " << packet_id.packet_index << std::endl; - ReturnValue_t mutexStatus = OSAL::lockMutex( mutex, OSAL::NO_TIMEOUT ); + ReturnValue_t mutexStatus = mutex->lockMutex(MutexIF::NO_TIMEOUT); ReturnValue_t status = this->RETURN_OK; if ( mutexStatus == this->RETURN_OK ) { LocalPool::deleteData(packet_id); } else { error << "PoolManager:deleteData: Mutex could not be acquired. Error code: " << status << std::endl; } - mutexStatus = OSAL::unlockMutex( mutex ); + mutexStatus = mutex->lockMutex(MutexIF::NO_TIMEOUT); if (mutexStatus != this->RETURN_OK) { return mutexStatus; } else { @@ -103,14 +99,14 @@ inline ReturnValue_t PoolManager::deleteData( template inline ReturnValue_t PoolManager::deleteData(uint8_t* buffer, uint32_t size, store_address_t* storeId) { - ReturnValue_t mutexStatus = OSAL::lockMutex( mutex, OSAL::NO_TIMEOUT ); + ReturnValue_t mutexStatus = mutex->lockMutex(MutexIF::NO_TIMEOUT); ReturnValue_t status = this->RETURN_OK; if ( mutexStatus == this->RETURN_OK ) { LocalPool::deleteData(buffer, size, storeId); } else { error << "PoolManager:deleteData: Mutex could not be acquired. Error code: " << status << std::endl; } - mutexStatus = OSAL::unlockMutex( mutex ); + mutexStatus = mutex->lockMutex(MutexIF::NO_TIMEOUT); if (mutexStatus != this->RETURN_OK) { return mutexStatus; } else { diff --git a/storagemanager/StorageManagerIF.h b/storagemanager/StorageManagerIF.h index 40afb093..575e9caa 100644 --- a/storagemanager/StorageManagerIF.h +++ b/storagemanager/StorageManagerIF.h @@ -5,8 +5,6 @@ #include #include -//TODO: Check setting and returning of store sizes. - /** * This union defines the type that identifies where a data packet is stored in the store. * It comprises of a raw part to read it as raw value and a structured part to use it in @@ -67,7 +65,7 @@ union store_address_t { */ class StorageManagerIF : public HasReturnvaluesIF { public: - static const uint8_t INTERFACE_ID = STORAGE_MANAGER_IF; //!< The unique ID for return codes for this interface. + static const uint8_t INTERFACE_ID = CLASS_ID::STORAGE_MANAGER_IF; //!< The unique ID for return codes for this interface. static const ReturnValue_t DATA_TOO_LARGE = MAKE_RETURN_CODE(1); //!< This return code indicates that the data to be stored is too large for the store. static const ReturnValue_t DATA_STORAGE_FULL = MAKE_RETURN_CODE(2); //!< This return code indicates that a data storage is full. static const ReturnValue_t ILLEGAL_STORAGE_ID = MAKE_RETURN_CODE(3); //!< This return code indicates that data was requested with an illegal storage ID. @@ -96,7 +94,7 @@ public: * @li RETURN_FAILED if data could not be added. * storageId is unchanged then. */ - virtual ReturnValue_t addData(store_address_t* storageId, const uint8_t * data, uint32_t size) = 0; + virtual ReturnValue_t addData(store_address_t* storageId, const uint8_t * data, uint32_t size, bool ignoreFault = false) = 0; /** * @brief With deleteData, the storageManager frees the memory region * identified by packet_id. @@ -146,7 +144,7 @@ public: * @li RETURN_FAILED if data could not be added. * storageId is unchanged then. */ - virtual ReturnValue_t getFreeElement(store_address_t* storageId, const uint32_t size, uint8_t** p_data ) = 0; + virtual ReturnValue_t getFreeElement(store_address_t* storageId, const uint32_t size, uint8_t** p_data, bool ignoreFault = false ) = 0; /** * Clears the whole store. * Use with care! diff --git a/subsystem/Subsystem.cpp b/subsystem/Subsystem.cpp index 4905b6aa..e1ec544b 100644 --- a/subsystem/Subsystem.cpp +++ b/subsystem/Subsystem.cpp @@ -1,10 +1,3 @@ -/* - * Subsystem.cpp - * - * Created on: 12.07.2013 - * Author: tod - */ - #include #include #include @@ -20,7 +13,11 @@ Subsystem::Subsystem(object_id_t setObjectId, object_id_t parent, false), uptimeStartTable(0), currentTargetTable(), targetMode( 0), targetSubmode(SUBMODE_NONE), initialMode(0), currentSequenceIterator(), modeTables( maxNumberOfTables), modeSequences(maxNumberOfSequences), IPCStore( - NULL), modeStore(NULL) { + NULL) +#ifdef USE_MODESTORE +,modeStore(NULL) +#endif +{ } @@ -78,7 +75,7 @@ void Subsystem::performChildOperation() { if (isInTransition) { if (commandsOutstanding <= 0) { //all children of the current table were commanded and replied if (currentSequenceIterator.value == NULL) { //we're through with this sequence - if (checkStateAgainstTable(currentTargetTable) == RETURN_OK) { + if (checkStateAgainstTable(currentTargetTable, targetSubmode) == RETURN_OK) { setMode(targetMode, targetSubmode); isInTransition = false; return; @@ -89,19 +86,19 @@ void Subsystem::performChildOperation() { } } if (currentSequenceIterator->checkSuccess()) { - if (checkStateAgainstTable(getCurrentTable()) != RETURN_OK) { + if (checkStateAgainstTable(getCurrentTable(), targetSubmode) != RETURN_OK) { transitionFailed(TABLE_CHECK_FAILED, currentSequenceIterator->getTableId()); return; } } if (currentSequenceIterator->getWaitSeconds() != 0) { - if (uptimeStartTable != 0) { - OSAL::getUptime(&uptimeStartTable); + if (uptimeStartTable == 0) { + Clock::getUptime(&uptimeStartTable); return; } else { uint32_t uptimeNow; - OSAL::getUptime(&uptimeNow); + Clock::getUptime(&uptimeNow); if ((uptimeNow - uptimeStartTable) < (currentSequenceIterator->getWaitSeconds() * 1000)) { return; @@ -111,7 +108,7 @@ void Subsystem::performChildOperation() { uptimeStartTable = 0; //next Table, but only if there is one if ((++currentSequenceIterator).value != NULL) { //we're through with this sequence - executeTable(getCurrentTable()); + executeTable(getCurrentTable(), targetSubmode); } } } else { @@ -120,7 +117,7 @@ void Subsystem::performChildOperation() { childrenChangedHealth = false; startTransition(mode, submode); } else if (childrenChangedMode) { - if (checkStateAgainstTable(currentTargetTable) != RETURN_OK) { + if (checkStateAgainstTable(currentTargetTable, submode) != RETURN_OK) { triggerEvent(CANT_KEEP_MODE, mode, submode); cantKeepMode(); } @@ -315,7 +312,7 @@ ReturnValue_t Subsystem::handleCommandMessage(CommandMessage* message) { CommandMessage reply; ModeSequenceMessage::setModeSequenceMessage(&reply, ModeSequenceMessage::FREE_SEQUENCE_SLOTS, freeSlots); - commandQueue.reply(&reply); + commandQueue->reply(&reply); } break; case ModeSequenceMessage::READ_FREE_TABLE_SLOTS: { @@ -323,7 +320,7 @@ ReturnValue_t Subsystem::handleCommandMessage(CommandMessage* message) { CommandMessage reply; ModeSequenceMessage::setModeSequenceMessage(&reply, ModeSequenceMessage::FREE_TABLE_SLOTS, free); - commandQueue.reply(&reply); + commandQueue->reply(&reply); } break; default: @@ -335,10 +332,10 @@ ReturnValue_t Subsystem::handleCommandMessage(CommandMessage* message) { void Subsystem::replyToCommand(ReturnValue_t status, uint32_t parameter) { if (status == RETURN_OK) { CommandMessage reply(CommandMessage::REPLY_COMMAND_OK, 0, 0); - commandQueue.reply(&reply); + commandQueue->reply(&reply); } else { CommandMessage reply(CommandMessage::REPLY_REJECTED, status, 0); - commandQueue.reply(&reply); + commandQueue->reply(&reply); } } @@ -372,13 +369,20 @@ ReturnValue_t Subsystem::addSequence(ArrayList* sequence, } if (inStore) { +#ifdef USE_MODESTORE result = modeStore->storeArray(sequence, &(modeSequences.find(id)->entries.firstLinkedElement)); if (result != RETURN_OK) { modeSequences.erase(id); } +#else + modeSequences.erase(id); + return RETURN_FAILED; +#endif } + return result; + } ReturnValue_t Subsystem::addTable(ArrayList *table, Mode_t id, @@ -408,11 +412,16 @@ ReturnValue_t Subsystem::addTable(ArrayList *table, Mode_t id, } if (inStore) { +#ifdef USE_MODESTORE result = modeStore->storeArray(table, &(modeTables.find(id)->firstLinkedElement)); if (result != RETURN_OK) { modeTables.erase(id); } +#else + modeTables.erase(id); + return RETURN_FAILED; +#endif } return result; } @@ -433,7 +442,9 @@ ReturnValue_t Subsystem::deleteSequence(Mode_t id) { return ACCESS_DENIED; } +#ifdef USE_MODESTORE modeStore->deleteList(sequenceInfo->entries.firstLinkedElement); +#endif modeSequences.erase(id); return RETURN_OK; } @@ -453,7 +464,10 @@ ReturnValue_t Subsystem::deleteTable(Mode_t id) { if (!pointer->islinked) { return ACCESS_DENIED; } + +#ifdef USE_MODESTORE modeStore->deleteList(pointer->firstLinkedElement); +#endif modeSequences.erase(id); return RETURN_OK; } @@ -466,12 +480,18 @@ ReturnValue_t Subsystem::initialize() { } IPCStore = objectManager->get(objects::IPC_STORE); - modeStore = objectManager->get(objects::MODE_STORE); - - if ((IPCStore == NULL) || (modeStore == NULL)) { + if (IPCStore == NULL) { return RETURN_FAILED; } +#ifdef USE_MODESTORE + modeStore = objectManager->get(objects::MODE_STORE); + + if (modeStore == NULL) { + return RETURN_FAILED; + } +#endif + if ((modeSequences.maxSize() > MAX_NUMBER_OF_TABLES_OR_SEQUENCES) || (modeTables.maxSize() > MAX_NUMBER_OF_TABLES_OR_SEQUENCES)) { return TABLE_OR_SEQUENCE_LENGTH_INVALID; @@ -488,9 +508,10 @@ MessageQueueId_t Subsystem::getSequenceCommandQueue() const { ReturnValue_t Subsystem::checkModeCommand(Mode_t mode, Submode_t submode, uint32_t* msToReachTheMode) { - if (submode != SUBMODE_NONE) { - return INVALID_SUBMODE; - } + //Need to accept all submodes to be able to inherit submodes +// if (submode != SUBMODE_NONE) { +// return INVALID_SUBMODE; +// } if (isInTransition && (mode != getFallbackSequence(targetMode))) { return HasModesIF::IN_TRANSITION; @@ -516,7 +537,7 @@ void Subsystem::startTransition(Mode_t sequence, Submode_t submode) { ++currentSequenceIterator; if (currentSequenceIterator.value != NULL) { - executeTable(getCurrentTable()); + executeTable(getCurrentTable(), targetSubmode); } } @@ -598,7 +619,7 @@ void Subsystem::sendSerializablesAsCommandMessage(Command_t command, } CommandMessage reply; ModeSequenceMessage::setModeSequenceMessage(&reply, command, address); - if (commandQueue.reply(&reply) != RETURN_OK) { + if (commandQueue->reply(&reply) != RETURN_OK) { IPCStore->deleteData(address); } } diff --git a/subsystem/Subsystem.h b/subsystem/Subsystem.h index 5e924a39..ca1020b9 100644 --- a/subsystem/Subsystem.h +++ b/subsystem/Subsystem.h @@ -1,10 +1,3 @@ -/* - * Subsystem.h - * - * Created on: 12.07.2013 - * Author: tod - */ - #ifndef SUBSYSTEM_H_ #define SUBSYSTEM_H_ @@ -18,7 +11,7 @@ class Subsystem: public SubsystemBase, public HasModeSequenceIF { public: - static const uint8_t INTERFACE_ID = SUBSYSTEM; + static const uint8_t INTERFACE_ID = CLASS_ID::SUBSYSTEM; static const ReturnValue_t SEQUENCE_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01); static const ReturnValue_t TABLE_ALREADY_EXISTS = MAKE_RETURN_CODE(0x02); static const ReturnValue_t TABLE_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03); @@ -91,7 +84,7 @@ protected: EntryPointer entries; }; - static const uint8_t MAX_NUMBER_OF_TABLES_OR_SEQUENCES = 60; + static const uint8_t MAX_NUMBER_OF_TABLES_OR_SEQUENCES = 70; static const uint8_t MAX_LENGTH_OF_TABLE_OR_SEQUENCE = 20; @@ -117,7 +110,9 @@ protected: StorageManagerIF *IPCStore; +#ifdef USE_MODESTORE ModeStoreIF *modeStore; +#endif bool existsModeSequence(Mode_t id); diff --git a/subsystem/SubsystemBase.cpp b/subsystem/SubsystemBase.cpp index 03c3d081..42a41335 100644 --- a/subsystem/SubsystemBase.cpp +++ b/subsystem/SubsystemBase.cpp @@ -1,8 +1,19 @@ #include #include #include +#include + +SubsystemBase::SubsystemBase(object_id_t setObjectId, object_id_t parent, + Mode_t initialMode, uint16_t commandQueueDepth) : + SystemObject(setObjectId), mode(initialMode), submode(SUBMODE_NONE), childrenChangedMode( + false), commandsOutstanding(0), commandQueue(NULL), healthHelper(this, + setObjectId), modeHelper(this), parentId(parent) { + QueueFactory::instance()->createMessageQueue(commandQueueDepth, + CommandMessage::MAX_MESSAGE_SIZE); +} SubsystemBase::~SubsystemBase() { + QueueFactory::instance()->deleteMessageQueue(commandQueue); } @@ -38,7 +49,7 @@ ReturnValue_t SubsystemBase::registerChild(object_id_t objectId) { } ReturnValue_t SubsystemBase::checkStateAgainstTable( - HybridIterator tableIter) { + HybridIterator tableIter, Submode_t targetSubmode) { std::map::iterator childIter; @@ -52,14 +63,20 @@ ReturnValue_t SubsystemBase::checkStateAgainstTable( if (childIter->second.mode != tableIter.value->getMode()) { return RETURN_FAILED; } - if (childIter->second.submode != tableIter.value->getSubmode()) { + + Submode_t submodeToCheckAgainst = tableIter.value->getSubmode(); + if (tableIter.value->inheritSubmode()) { + submodeToCheckAgainst = targetSubmode; + } + + if (childIter->second.submode != submodeToCheckAgainst) { return RETURN_FAILED; } } return RETURN_OK; } -void SubsystemBase::executeTable(HybridIterator tableIter) { +void SubsystemBase::executeTable(HybridIterator tableIter, Submode_t targetSubmode) { CommandMessage message; @@ -70,11 +87,17 @@ void SubsystemBase::executeTable(HybridIterator tableIter) { for (; tableIter.value != NULL; ++tableIter) { object_id_t object = tableIter.value->getObject(); if ((iter = childrenMap.find(object)) == childrenMap.end()) { - //illegal table entry - //TODO: software error + //illegal table entry, should only happen due to misconfigured mode table + debug << std::hex << getObjectId() << ": invalid mode table entry" + << std::endl; continue; } + Submode_t submodeToCommand = tableIter.value->getSubmode(); + if (tableIter.value->inheritSubmode()) { + submodeToCommand = targetSubmode; + } + if (healthHelper.healthTable->hasHealth(object)) { if (healthHelper.healthTable->isFaulty(object)) { ModeMessage::setModeMessage(&message, @@ -84,14 +107,12 @@ void SubsystemBase::executeTable(HybridIterator tableIter) { if (modeHelper.isForced()) { ModeMessage::setModeMessage(&message, ModeMessage::CMD_MODE_COMMAND_FORCED, - tableIter.value->getMode(), - tableIter.value->getSubmode()); + tableIter.value->getMode(), submodeToCommand); } else { if (healthHelper.healthTable->isCommandable(object)) { ModeMessage::setModeMessage(&message, ModeMessage::CMD_MODE_COMMAND, - tableIter.value->getMode(), - tableIter.value->getSubmode()); + tableIter.value->getMode(), submodeToCommand); } else { continue; } @@ -99,20 +120,19 @@ void SubsystemBase::executeTable(HybridIterator tableIter) { } } else { ModeMessage::setModeMessage(&message, ModeMessage::CMD_MODE_COMMAND, - tableIter.value->getMode(), tableIter.value->getSubmode()); + tableIter.value->getMode(), submodeToCommand); } - //TODO: This may causes trouble with more than two layers, sys commands subsys off, which is already off, but children are on (external). - // So, they stay on. Might only be an issue if mode is forced, so we do + if ((iter->second.mode == ModeMessage::getMode(&message)) - && (iter->second.submode == ModeMessage::getSubmode(&message)) && !modeHelper.isForced()) { - continue; //don't send redundant mode commands (produces event spam) + && (iter->second.submode == ModeMessage::getSubmode(&message)) + && !modeHelper.isForced()) { + continue; //don't send redundant mode commands (produces event spam), but still command if mode is forced to reach lower levels } - ReturnValue_t result = commandQueue.sendMessage( + ReturnValue_t result = commandQueue->sendMessage( iter->second.commandQueue, &message); - if (result != RETURN_OK) { - //TODO OBSW internal error + if (result == RETURN_OK) { + ++commandsOutstanding; } - ++commandsOutstanding; } } @@ -132,7 +152,7 @@ ReturnValue_t SubsystemBase::updateChildMode(MessageQueueId_t queue, } ReturnValue_t SubsystemBase::updateChildChangedHealth(MessageQueueId_t queue, - bool changedHealth) { +bool changedHealth) { for (auto iter = childrenMap.begin(); iter != childrenMap.end(); iter++) { if (iter->second.commandQueue == queue) { iter->second.healthChanged = changedHealth; @@ -142,15 +162,8 @@ ReturnValue_t SubsystemBase::updateChildChangedHealth(MessageQueueId_t queue, return CHILD_NOT_FOUND; } -SubsystemBase::SubsystemBase(object_id_t setObjectId, object_id_t parent, - Mode_t initialMode, uint16_t commandQueueDepth) : - SystemObject(setObjectId), mode(initialMode), submode(SUBMODE_NONE), childrenChangedMode( - false), commandsOutstanding(0), commandQueue(commandQueueDepth, - CommandMessage::MAX_MESSAGE_SIZE), healthHelper(this, setObjectId), modeHelper(this), parentId(parent) { -} - MessageQueueId_t SubsystemBase::getCommandQueue() const { - return commandQueue.getId(); + return commandQueue->getId(); } ReturnValue_t SubsystemBase::initialize() { @@ -186,7 +199,7 @@ ReturnValue_t SubsystemBase::initialize() { return RETURN_OK; } -ReturnValue_t SubsystemBase::performOperation() { +ReturnValue_t SubsystemBase::performOperation(uint8_t opCode) { childrenChangedMode = false; @@ -217,7 +230,8 @@ ReturnValue_t SubsystemBase::handleModeReply(CommandMessage* message) { for (auto iter = childrenMap.begin(); iter != childrenMap.end(); iter++) { if (iter->second.commandQueue == message->getSender()) { - triggerEvent(MODE_CMD_REJECTED, iter->first, message->getParameter()); + triggerEvent(MODE_CMD_REJECTED, iter->first, + message->getParameter()); } } } @@ -249,13 +263,14 @@ ReturnValue_t SubsystemBase::checkTable( } void SubsystemBase::replyToCommand(CommandMessage* message) { - commandQueue.reply(message); + commandQueue->reply(message); } void SubsystemBase::setMode(Mode_t newMode, Submode_t newSubmode) { modeHelper.modeChanged(newMode, newSubmode); mode = newMode; submode = newSubmode; + modeChanged(); announceMode(false); } @@ -266,7 +281,7 @@ void SubsystemBase::setMode(Mode_t newMode) { void SubsystemBase::commandAllChildren(CommandMessage* message) { std::map::iterator iter; for (iter = childrenMap.begin(); iter != childrenMap.end(); ++iter) { - commandQueue.sendMessage(iter->second.commandQueue, message); + commandQueue->sendMessage(iter->second.commandQueue, message); } } @@ -293,8 +308,8 @@ void SubsystemBase::checkCommandQueue() { ReturnValue_t result; CommandMessage message; - for (result = commandQueue.receiveMessage(&message); result == RETURN_OK; - result = commandQueue.receiveMessage(&message)) { + for (result = commandQueue->receiveMessage(&message); result == RETURN_OK; + result = commandQueue->receiveMessage(&message)) { result = healthHelper.handleHealthCommand(&message); if (result == RETURN_OK) { @@ -314,7 +329,8 @@ void SubsystemBase::checkCommandQueue() { result = handleCommandMessage(&message); if (result != RETURN_OK) { CommandMessage reply; - reply.setReplyRejected(CommandMessage::UNKNOW_COMMAND, message.getCommand()); + reply.setReplyRejected(CommandMessage::UNKNOW_COMMAND, + message.getCommand()); replyToCommand(&reply); } } @@ -334,3 +350,7 @@ ReturnValue_t SubsystemBase::setHealth(HealthState health) { HasHealthIF::HealthState SubsystemBase::getHealth() { return healthHelper.getHealth(); } + +void SubsystemBase::modeChanged() { +} + diff --git a/subsystem/SubsystemBase.h b/subsystem/SubsystemBase.h index e44a9e88..3294c46d 100644 --- a/subsystem/SubsystemBase.h +++ b/subsystem/SubsystemBase.h @@ -4,22 +4,21 @@ #include #include #include -#include #include #include #include #include #include +#include #include - class SubsystemBase: public SystemObject, public HasModesIF, public HasHealthIF, public HasReturnvaluesIF, public ExecutableObjectIF { public: - static const uint8_t INTERFACE_ID = SUBSYSTEM_BASE; + static const uint8_t INTERFACE_ID = CLASS_ID::SUBSYSTEM_BASE; static const ReturnValue_t CHILD_NOT_FOUND = MAKE_RETURN_CODE(0x01); static const ReturnValue_t CHILD_INFO_UPDATED = MAKE_RETURN_CODE(0x02); static const ReturnValue_t CHILD_DOESNT_HAVE_MODES = MAKE_RETURN_CODE(0x03); @@ -37,7 +36,7 @@ public: virtual ReturnValue_t initialize(); - virtual ReturnValue_t performOperation(); + virtual ReturnValue_t performOperation(uint8_t opCode); virtual ReturnValue_t setHealth(HealthState health); @@ -47,8 +46,7 @@ protected: struct ChildInfo { MessageQueueId_t commandQueue; Mode_t mode; - Submode_t submode; - bool healthChanged; + Submode_t submode;bool healthChanged; }; Mode_t mode; @@ -62,7 +60,7 @@ protected: */ int32_t commandsOutstanding; - MessageQueue commandQueue; + MessageQueueIF* commandQueue; HealthHelper healthHelper; @@ -75,15 +73,24 @@ protected: void checkCommandQueue(); + /** + * We need to know the target Submode, as children are able to inherit the submode + */ ReturnValue_t checkStateAgainstTable( - HybridIterator tableIter); + HybridIterator tableIter, Submode_t targetSubmode); - void executeTable(HybridIterator tableIter); + /** + * We need to know the target Submode, as children are able to inherit the submode + * Still, we have a default for all child implementations which do not use submode inheritance + */ + void executeTable(HybridIterator tableIter, + Submode_t targetSubmode = SUBMODE_NONE); ReturnValue_t updateChildMode(MessageQueueId_t queue, Mode_t mode, Submode_t submode); - ReturnValue_t updateChildChangedHealth(MessageQueueId_t queue, bool changedHealth = true); + ReturnValue_t updateChildChangedHealth(MessageQueueId_t queue, + bool changedHealth = true); virtual ReturnValue_t handleModeReply(CommandMessage *message); @@ -111,6 +118,8 @@ protected: virtual void setToExternalControl(); virtual void announceMode(bool recursive); + + virtual void modeChanged(); }; #endif /* SUBSYSTEMBASE_H_ */ diff --git a/subsystem/modes/ModeDefinitions.h b/subsystem/modes/ModeDefinitions.h index 4a122ef2..8e7531f3 100644 --- a/subsystem/modes/ModeDefinitions.h +++ b/subsystem/modes/ModeDefinitions.h @@ -1,10 +1,3 @@ -/* - * ModeTable.h - * - * Created on: 12.07.2013 - * Author: tod - */ - #ifndef MODEDEFINITIONS_H_ #define MODEDEFINITIONS_H_ @@ -15,13 +8,15 @@ class ModeListEntry: public SerializeIF, public LinkedElement { public: ModeListEntry() : - LinkedElement(this), value1(0), value2(0), value3(0) { + LinkedElement(this), value1(0), value2(0), value3(0), value4( + 0) { } uint32_t value1; uint32_t value2; uint8_t value3; + uint8_t value4; virtual ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, const uint32_t max_size, bool bigEndian) const { @@ -43,16 +38,23 @@ public: result = SerializeAdapter::serialize(&value3, buffer, size, max_size, bigEndian); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + result = SerializeAdapter::serialize(&value4, buffer, size, + max_size, bigEndian); + return result; } virtual uint32_t getSerializedSize() const { - return sizeof(value1) + sizeof(value2) + sizeof(value3); + return sizeof(value1) + sizeof(value2) + sizeof(value3) + sizeof(value4); } virtual ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { + bool bigEndian) { ReturnValue_t result; result = SerializeAdapter::deSerialize(&value1, buffer, size, @@ -70,6 +72,12 @@ public: result = SerializeAdapter::deSerialize(&value3, buffer, size, bigEndian); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = SerializeAdapter::deSerialize(&value4, buffer, size, + bigEndian); + return result; } @@ -98,7 +106,6 @@ public: this->value3 = checkSuccess; } - //for Tables object_id_t getObject() const { return value1; @@ -108,7 +115,6 @@ public: this->value1 = object; } - //TODO no cast! Mode_t getMode() const { return value2; } @@ -125,6 +131,18 @@ public: this->value3 = submode; } + bool inheritSubmode() const { + return value4 == 1; + } + + void setInheritSubmode(bool inherit){ + if (inherit){ + value4 = 1; + } else { + value4 = 0; + } + } + bool operator==(ModeListEntry other) { return ((value1 == other.value1) && (value2 == other.value2) && (value3 == other.value3)); diff --git a/subsystem/modes/ModeSequenceMessage.cpp b/subsystem/modes/ModeSequenceMessage.cpp index 6b6f9eb5..31661739 100644 --- a/subsystem/modes/ModeSequenceMessage.cpp +++ b/subsystem/modes/ModeSequenceMessage.cpp @@ -69,7 +69,7 @@ void ModeSequenceMessage::clear(CommandMessage *message) { ipcStore->deleteData(ModeSequenceMessage::getStoreAddress(message)); } } - /*NO BREAK*/ + /* NO BREAK falls through*/ case DELETE_SEQUENCE: case DELETE_TABLE: case READ_SEQUENCE: diff --git a/subsystem/modes/ModeSequenceMessage.h b/subsystem/modes/ModeSequenceMessage.h index f76bbc9a..830cf532 100644 --- a/subsystem/modes/ModeSequenceMessage.h +++ b/subsystem/modes/ModeSequenceMessage.h @@ -7,7 +7,7 @@ class ModeSequenceMessage { public: - static const uint8_t MESSAGE_ID = MODE_SEQUENCE_MESSAGE_ID; + static const uint8_t MESSAGE_ID = MESSAGE_TYPE::MODE_SEQUENCE; static const Command_t ADD_SEQUENCE = MAKE_COMMAND_ID(0x01); static const Command_t ADD_TABLE = MAKE_COMMAND_ID(0x02); diff --git a/subsystem/modes/ModeStore.cpp b/subsystem/modes/ModeStore.cpp index 017b7202..2aa02087 100644 --- a/subsystem/modes/ModeStore.cpp +++ b/subsystem/modes/ModeStore.cpp @@ -1,8 +1,10 @@ #include +#ifdef USE_MODESTORE + ModeStore::ModeStore(object_id_t objectId, uint32_t slots) : SystemObject(objectId), store(slots), emptySlot(store.front()) { - mutex = new MutexId_t; + mutex = MutexFactory::instance()->createMutex();; OSAL::createMutex(objectId + 1, mutex); clear(); } @@ -38,7 +40,7 @@ ReturnValue_t ModeStore::storeArray(ArrayList* sequence, ArrayList::Iterator iter; for (iter = sequence->begin(); iter != sequence->end(); ++iter) { - //TODO: I need to check this in detail. What is the idea? Why does it not work? + //SHOULDDO: I need to check this in detail. What is the idea? Why does it not work? pointer = pointer->getNext()->value; if (pointer == NULL) { deleteListNoLock(*storedFirstEntry); @@ -120,3 +122,5 @@ ReturnValue_t ModeStore::isValidEntry(ModeListEntry* sequence) { } return HasReturnvaluesIF::RETURN_OK; } + +#endif diff --git a/subsystem/modes/ModeStore.h b/subsystem/modes/ModeStore.h index 8295fd8c..cbc45b5a 100644 --- a/subsystem/modes/ModeStore.h +++ b/subsystem/modes/ModeStore.h @@ -1,6 +1,8 @@ #ifndef MODESTORE_H_ #define MODESTORE_H_ +#ifdef USE_MODESTORE + #include #include #include @@ -37,5 +39,7 @@ private: ReturnValue_t isValidEntry(ModeListEntry *sequence); }; +#endif + #endif /* MODESTORE_H_ */ diff --git a/subsystem/modes/ModeStoreIF.h b/subsystem/modes/ModeStoreIF.h index 3d8efbc8..7be7a5a7 100644 --- a/subsystem/modes/ModeStoreIF.h +++ b/subsystem/modes/ModeStoreIF.h @@ -1,6 +1,8 @@ #ifndef MODESTOREIF_H_ #define MODESTOREIF_H_ +#ifdef USE_MODESTORE + #include #include #include @@ -8,7 +10,7 @@ class ModeStoreIF { public: - static const uint8_t INTERFACE_ID = MODE_STORE_IF; + static const uint8_t INTERFACE_ID = CLASS_ID::MODE_STORE_IF; static const ReturnValue_t INVALID_ENTRY = MAKE_RETURN_CODE(0x02); static const ReturnValue_t TOO_MANY_ELEMENTS = MAKE_RETURN_CODE(0x03); static const ReturnValue_t CANT_STORE_EMPTY = MAKE_RETURN_CODE(0x04); @@ -30,4 +32,6 @@ public: virtual uint32_t getFreeSlots() = 0; }; +#endif + #endif /* MODESTOREIF_H_ */ diff --git a/tasks/ExecutableObjectIF.h b/tasks/ExecutableObjectIF.h index 9ad4fa8d..22273259 100644 --- a/tasks/ExecutableObjectIF.h +++ b/tasks/ExecutableObjectIF.h @@ -12,12 +12,13 @@ #define EXECUTABLEOBJECTIF_H_ -#include +#include +class PeriodicTaskIF; /** * @brief The interface provides a method to execute objects within a task. * @details The performOperation method, that is required by the interface is - * executed cyclically within the ObjectTask's context. + * executed cyclically within a task context. */ class ExecutableObjectIF { public: @@ -26,12 +27,14 @@ public: */ virtual ~ExecutableObjectIF() { } /** - * @brief The performOperation method is executed in the ObjectTask context. + * @brief The performOperation method is executed in a task. * @details There are no restrictions for calls within this method, so any * other member of the class can be used. * @return Currently, the return value is ignored. */ - virtual ReturnValue_t performOperation() = 0; + virtual ReturnValue_t performOperation(uint8_t operationCode = 0) = 0; + + virtual void setTaskIF(PeriodicTaskIF* interface) {}; }; #endif /* EXECUTABLEOBJECTIF_H_ */ diff --git a/tasks/FixedTimeslotTaskIF.h b/tasks/FixedTimeslotTaskIF.h new file mode 100644 index 00000000..3a3582fb --- /dev/null +++ b/tasks/FixedTimeslotTaskIF.h @@ -0,0 +1,19 @@ +#ifndef FRAMEWORK_TASKS_FIXEDTIMESLOTTASKIF_H_ +#define FRAMEWORK_TASKS_FIXEDTIMESLOTTASKIF_H_ + +#include +#include + +/** + * Following the same principle as the base class IF. This is the interface for a Fixed timeslot task + */ +class FixedTimeslotTaskIF : public PeriodicTaskIF { +public: + virtual ~FixedTimeslotTaskIF() {} + virtual ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep) = 0; + virtual ReturnValue_t checkSequence() const = 0; +}; + + + +#endif /* FRAMEWORK_TASKS_FIXEDTIMESLOTTASKIF_H_ */ diff --git a/tasks/Makefile b/tasks/Makefile deleted file mode 100755 index bafd59a9..00000000 --- a/tasks/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -# -# OSAL makefile -# -# Created on: Mar 04, 2010 -# Author: ziemke -# Author: Claas Ziemke -# Copyright 2010, Claas Ziemke -# - -BASEDIR=../../ -include $(BASEDIR)options.mk - -OBJ = $(BUILDDIR)/PeriodicTask.o \ - $(BUILDDIR)/ObjectTask.o \ - $(BUILDDIR)/TaskBase.o - -all: $(OBJ) - -$(BUILDDIR)/%.o: %.cpp %.h - $(CPP) $(CFLAGS) $(DEFINES) $(CCOPT) ${INCLUDE} -c $< -o $@ - -clean: - $(RM) *.o *.gcno *.gcda diff --git a/tasks/MultiObjectTask.cpp b/tasks/MultiObjectTask.cpp deleted file mode 100644 index 65fecaab..00000000 --- a/tasks/MultiObjectTask.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @file MultiObjectTask.cpp - * @brief This file defines the MultiObjectTask class. - * @date 30.01.2014 - * @author baetz - */ - -#include -#include - -MultiObjectTask::MultiObjectTask(const char *name, TaskPriority_t setPriority, - size_t setStack, Interval_t setPeriod, void (*setDeadlineMissedFunc)()) : - TaskBase(setPriority, setStack, name), period(setPeriod), periodId(0), deadlineMissedFunc( - setDeadlineMissedFunc) { - -} - -MultiObjectTask::~MultiObjectTask(void) { - //Do not delete objects! -} -TaskReturn_t MultiObjectTask::taskEntryPoint(TaskArgument_t argument) { - //The argument is re-interpreted as ObjectTask. The Task object is global, so it is found from any place. - MultiObjectTask *originalTask(reinterpret_cast(argument)); - originalTask->taskFunctionality(); - debug << "MultiObjectTask " << originalTask->getId() - << " returned from taskFunctionality. Deleting task." << std::endl; -} - -ReturnValue_t MultiObjectTask::startTask() { - this->setRunning( true); - ReturnValue_t status; - status = OSAL::startTask(&(this->id), MultiObjectTask::taskEntryPoint, - TaskArgument_t((void *) this)); - if (status != RETURN_OK) { - //TODO: Call any FDIR routine? - error << "MultiObjectTask::startTask for " << std::hex << this->getId() - << std::dec << " failed." << std::endl; - } else { -// debug << "ObjectTask::startTask for " << std::hex << this->getId() << std::dec << " successful" << std::endl; - } - return status; -} - -void MultiObjectTask::taskFunctionality() { - ReturnValue_t status = OSAL::TIMEOUT; - //The period is set up and started with the system call. - if (objectList.begin() != objectList.end()) { - status = OSAL::setAndStartPeriod(this->period, &(this->periodId)); - if (status == RETURN_OK) { - //The task's "infinite" inner loop is entered. - while (this->isRunning) { - for (ObjectList::iterator it = objectList.begin(); - it != objectList.end(); ++it) { - (*it)->performOperation(); - } - if (OSAL::checkAndRestartPeriod(this->periodId, this->period) - == OSAL::TIMEOUT) { - char nameSpace[8] = { 0 }; - char* ptr = rtems_object_get_name(getId(), - sizeof(nameSpace), nameSpace); - error << "MultiObjectTask: " << ptr << " Deadline missed." - << std::endl; - if (this->deadlineMissedFunc != NULL) { - this->deadlineMissedFunc(); - } - } - } - debug << "MultiObjectTask: Returned from taskFunctionality()-Loop." - << std::endl; - } else { - error << "MultiObjectTask::setAndStartPeriod failed with status " - << status << std::endl; - } - } else { - error << "MultiObjectTask::taskFunctionality. No object assigned." - << std::endl; - } - //Any operating system object for periodic execution is deleted. - debug << "Deleting the ObjectTask's period." << std::endl; - OSAL::deletePeriod(&(this->id)); -} - -ReturnValue_t MultiObjectTask::addObject(object_id_t object) { - ExecutableObjectIF* newObject = objectManager->get( - object); - if (newObject == NULL) { - return RETURN_FAILED; - } - objectList.push_back(newObject); - return RETURN_OK; -} - -ReturnValue_t MultiObjectTask::addObject(ExecutableObjectIF* object) { - if (object == NULL) { - return RETURN_FAILED; - } - objectList.push_back(object); - return RETURN_OK; -} diff --git a/tasks/ObjectTask.cpp b/tasks/ObjectTask.cpp deleted file mode 100644 index 83d28745..00000000 --- a/tasks/ObjectTask.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * ObjectTask.cpp - * - * Created on: 03.02.2012 - * Author: baetz - */ - -#include -#include - -ObjectTask::ObjectTask( const char *name, TaskPriority_t setPriority, size_t setStack, Interval_t setPeriod, void (*setDeadlineMissedFunc)(), ExecutableObjectIF* (*initFunction)() ) : - TaskBase( setPriority, setStack, name ), period(setPeriod), periodId(0), deadlineMissedFunc(setDeadlineMissedFunc) { - // All additional attributes are applied to the object. - this->executingObject = initFunction(); - -} - -ObjectTask::ObjectTask(const char *name, TaskPriority_t setPriority, size_t setStack, - Interval_t setPeriod, void (*setDeadlineMissedFunc)(), - object_id_t object_id) : TaskBase( setPriority, setStack, name ), period(setPeriod), periodId(0), deadlineMissedFunc(setDeadlineMissedFunc) { - this->executingObject = objectManager->get( object_id ); -} - -ObjectTask::~ObjectTask() { -} - -TaskReturn_t ObjectTask::taskEntryPoint( TaskArgument_t argument ) { - //The argument is re-interpreted as ObjectTask. The Task object is global, so it is found from any place. - ObjectTask *originalTask( reinterpret_cast( argument ) ); - originalTask->taskFunctionality(); - debug << "Object task " << originalTask->getId() << " returned from taskFunctionality. Deleting task." << std::endl; - //TODO: destroy the task object? -} - -ReturnValue_t ObjectTask::startTask() { - this->setRunning( true ); - ReturnValue_t status; - status = OSAL::startTask( &( this->id ), ObjectTask::taskEntryPoint, TaskArgument_t( ( void *)this ) ); - if( status != RETURN_OK ) { - //TODO: Call any FDIR routine? - error << "ObjectTask::startTask for " << std::hex << this->getId() << std::dec << " failed." << std::endl; - } else { -// debug << "ObjectTask::startTask for " << std::hex << this->getId() << std::dec << " successful" << std::endl; - } - return status; -} - -void ObjectTask::taskFunctionality() { - ReturnValue_t status = OSAL::TIMEOUT; - //The period is set up and started with the system call. - if ( this->executingObject != NULL ) { - status = OSAL::setAndStartPeriod( this->period, &(this->periodId) ); - if( status == RETURN_OK ) { - //The task's "infinite" inner loop is entered. - while( this->isRunning ) { - - this->executingObject->performOperation(); - - if( OSAL::checkAndRestartPeriod( this->periodId, this->period ) == OSAL::TIMEOUT ) { - char nameSpace[8] = {0}; - char* ptr = rtems_object_get_name(getId(), sizeof(nameSpace), nameSpace); - error << "ObjectTask: " << ptr << " Deadline missed." << std::endl; - if( this->deadlineMissedFunc != NULL ) { - this->deadlineMissedFunc(); - } - } - } - debug << "Returned from taskFunctionality()-Loop." << std::endl; - } else { - error << "ObjectTask::setAndStartPeriod failed with status " << status << std::endl; - } - } else { - error << "ObjectTask::taskFunctionality. Object not found." << std::endl; - } - //Any operating system object for periodic execution is deleted. - debug << "Deleting the ObjectTask's period." << std::endl; - OSAL::deletePeriod( &(this->id) ); -} diff --git a/tasks/ObjectTask.h b/tasks/ObjectTask.h deleted file mode 100644 index eab8d30c..00000000 --- a/tasks/ObjectTask.h +++ /dev/null @@ -1,129 +0,0 @@ - -/** - * @file ObjectTask.h - * - * @brief This file contains the definition for the ObjectTask class. - * - * @author Bastian Baetz - * - * @date 02/03/2012 - * - */ -#ifndef OBJECTTASK_H_ -#define OBJECTTASK_H_ - -#include -#include -#include - -/** - * @brief This class represents a specialized task for periodic activities of objects. - * - * @details For object-oriented embedded systems, simple periodic tasks executing a single function - * are not very useful. An object method, representing some kind of activity to be performed, - * would either be instantiated in each execution, thus loosing all attribute information, or - * must be known globally. To address this issue, the ObjectTask class is used. - * It implements the TaskBase prototype and provides additional means to make use of any - * object that implements the ExecutableObjectIF interface. The required performOperation - * method is then called periodically. Attributes of the executed object are persistent - * during the task's lifetime. - * Functionally, the class works similar to PeriodicTask. - * - * @author Bastian Baetz - * - * @date 02/03/2012 - * - * @ingroup task_handling - */ -class ObjectTask: public TaskBase { -protected: - /** - * @brief This attribute holds a pointer to the object to be executed. - */ - ExecutableObjectIF* executingObject; - /** - * @brief The period of the task. - * @details The period determines the frequency of the task's execution. It is expressed in clock ticks. - */ - Interval_t period; - /** - * @brief id of the associated OS period - */ - PeriodId_t periodId; - /** - * @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, - * then nothing happens on missing the deadline. The deadline is equal to the next execution - * of the periodic task. - */ - void ( *deadlineMissedFunc )( void ); - /** - * @brief This is the function executed in the new task's context. - * @details It converts the argument back to the thread object type and copies the class instance - * to the task context. The taskFunctionality method is called afterwards. - * @param A pointer to the task object itself is passed as argument. - */ - static TaskReturn_t taskEntryPoint( TaskArgument_t argument ); - /** - * @brief The function containing the actual functionality of the task. - * @details The method sets and starts - * the task's period, then enters a loop that is repeated as long as the isRunning - * attribute is true. Within the loop, the object's performFunction method is called, and - * afterwards the checkAndRestartPeriod system call to block the task until the next - * period. On missing the deadline, the deadlineMissedFunction is executed. - */ - void taskFunctionality( void ); - -public: - /** - * @brief The first of the two standard constructors of the class. - * @details This constructor initializes the object to be executed with the aid of an - * initialization function that returns the pointer to the object. - * In the underlying TaskBase class, a new operating system task is created. - * In addition to the TaskBase parameters, the period, the pointer to the - * aforementioned initialization function and an optional "deadline-missed" - * function pointer is passed. - * @param priority Sets the priority of a task. Values range from a low 0 to a high 99. - * @param stack_size The stack size reserved by the operating system for the task. - * @param setPeriod The length of the period with which the task's functionality will be - * executed. It is expressed in clock ticks. - * @param setDeadlineMissedFunc The function pointer to the deadline missed function - * that shall be assigned. - * @param initFunction A pointer to the initialization function that returns the object to be executed. - */ - ObjectTask( const char *name, TaskPriority_t setPriority, size_t setStack, Interval_t setPeriod, void (*setDeadlineMissedFunc)(), ExecutableObjectIF* (*initFunction)() ); - /** - * @brief The second of the two standard constructors of the class. - * @details This constructor initializes the object to be executed with the aid of an - * object id and the global ObjectManager class. - * In the underlying TaskBase class, a new operating system task is created. - * In addition to the TaskBase parameters, the period, the object_id of the - * object to be executed and an optional "deadline-missed" function pointer is passed. - * @param priority Sets the priority of a task. Values range from a low 0 to a high 99. - * @param stack_size The stack size reserved by the operating system for the task. - * @param setPeriod The length of the period with which the task's functionality will be - * executed. It is expressed in clock ticks. - * @param setDeadlineMissedFunc The function pointer to the deadline missed function - * that shall be assigned. - * @param object_id The object id of the object to be executed. - */ - ObjectTask( const char *name, TaskPriority_t setPriority, size_t setStack, Interval_t setPeriod, void (*setDeadlineMissedFunc)(), object_id_t object_id ); - /** - * @brief Currently, the executed object's lifetime is not coupled with the task object's - * lifetime, so the destructor is empty. - */ - virtual ~ObjectTask( void ); - - /** - * @brief The method to start the task. - * @details The method starts the task with the respective system call. - * Entry point is the taskEntryPoint method described below. - * The address of the task object is passed as an argument - * to the system call. - */ - ReturnValue_t startTask( void ); - -}; - -#endif /* OBJECTTASK_H_ */ diff --git a/tasks/PeriodicTask.cpp b/tasks/PeriodicTask.cpp deleted file mode 100644 index dfc31b1e..00000000 --- a/tasks/PeriodicTask.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/** - * \file PeriodicTask.cpp - * - * \brief This file contains the implementation for the PeriodicTask class. - * - * \author Bastian Baetz - * - * \date 21.07.2010 - * - * Copyright 2010, Bastian Baetz - * All rights reserved - * - */ - -//#include -#include -#include - -//TODO: Check if isRunning flag is useful. Shall tasks be restartable? -TaskReturn_t PeriodicTask::taskEntryPoint( TaskArgument_t argument ) { - - //The argument is re-interpreted as PeriodicTask - PeriodicTask *originalTask( reinterpret_cast(argument) ); - originalTask->taskFunctionality(); - debug << "Object task " << originalTask->getId() << " returned from taskFunctionality." << std::endl; - //TODO: destroy the task object? -} - -PeriodicTask::PeriodicTask( const char *name, TaskPriority_t setPriority, size_t setStack, Interval_t setPeriod, - void (*setDeadlineMissedFunc)(), ReturnValue_t ( *setTaskFunction )( TaskBase* ) ) : - TaskBase( setPriority, setStack, name ), period(setPeriod), periodId(0), deadlineMissedFunc(setDeadlineMissedFunc), - taskFunction(setTaskFunction) { -} - -PeriodicTask::~PeriodicTask() { -} - -ReturnValue_t PeriodicTask::startTask() { - debug << "PeriodicTask::startTask. TaskId: " << this->getId() << std::endl; - this->setRunning( true ); - ReturnValue_t status; - status = OSAL::startTask( &( this->id ), PeriodicTask::taskEntryPoint, TaskArgument_t( ( void *)this ) ); - if( status != RETURN_OK ) { - //TODO: Call any FDIR routine? - error << "PeriodicTask::startTask for " << this->getId() << " failed." << std::endl; - } else { - debug << "PeriodicTask::startTask for " << this->getId() << " successful" << std::endl; - } - return status; -} - -void PeriodicTask::taskFunctionality() { - - ReturnValue_t status = RETURN_OK; - - //The period is set up and started with the system call. - status = OSAL::setAndStartPeriod( this->period, &(this->periodId) ); - if( status == RETURN_OK ) { - //The task's "infinite" inner loop is entered. - while( this->isRunning ) { - //If a functionality is announced, it is started. - if( this->taskFunction != NULL ) { - this->taskFunction( this ); - } - //The period is checked and restarted. - //If the deadline was missed, the deadlineMissedFunc is called. - if( OSAL::checkAndRestartPeriod( this->periodId, this->period ) == OSAL::TIMEOUT ) { - error << "PeriodicTask: " << std::hex << this->getId() << " Deadline missed." << std::endl; - if( this->deadlineMissedFunc != NULL ) { - this->deadlineMissedFunc(); - } - } - } - debug << "Returned from taskFunctionality()-Loop." << std::endl; - } else { - error << "PeriodicTask::setAndStartPeriod failed with status " << status << std::endl; - } - //Any operating system object for periodic execution is deleted. - debug << "Deleting the PeriodicThread's period." << std::endl; - OSAL::deletePeriod( &(this->id) ); -} diff --git a/tasks/PeriodicTask.h b/tasks/PeriodicTask.h deleted file mode 100644 index fc36ab04..00000000 --- a/tasks/PeriodicTask.h +++ /dev/null @@ -1,113 +0,0 @@ -/** - * @file PeriodicTask.h - * - * @brief This file contains the definition for the PeriodicTask class. - * - * @author Bastian Baetz - * - * @date 07/21/2010 - * - */ -#ifndef OPUSPERIODICTASK_H_ -#define OPUSPERIODICTASK_H_ - -#include - -/** - * - * @brief This class represents a specialized task for periodic activities. - * - * @details A simple, but very important task type is the periodic task. Each task of this type has - * a certain period assigned. When started, the task's functionality (a simple function) - * is executed. On finishing, the task is blocked for the rest of the period and restarted - * afterwards. A missed deadline is detected and a function to perform necessary failure - * detection may be called. - * - * @author Bastian Baetz - * - * @date 07/21/2010 - * - * @ingroup task_handling - */ -class PeriodicTask: public TaskBase { -protected: - - /** - * @brief The period of the task. - * @details The period determines the frequency of the task's execution. It is expressed in clock ticks. - */ - Interval_t period; - - /** - * @brief id of the associated OS period - */ - PeriodId_t periodId; - - /** - * @brief This is the function executed in the new task's context. - * @details It converts the argument back to the thread object type and copies the class instance - * to the task context. The taskFunctionality method is called afterwards. - * @param A pointer to the task object itself is passed as argument. - */ - static TaskReturn_t taskEntryPoint( TaskArgument_t argument ); - - /** - * @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, - * then nothing happens on missing the deadline. The deadline is equal to the next execution - * of the periodic task. - */ - void ( *deadlineMissedFunc )( void ); - - /** - * @brief The function containing the actual functionality of the task. - * @image latex act_OPUSPeriodicThread.eps "Activity diagram of the PeriodicThread functionality." width=0.6@textwidth - * @image html act_OPUSPeriodicThread.png "Activity diagram of the PeriodicThread functionality." - * @details The figure above shows the functional execution of this method. It sets and starts - * the task's period, then enters a loop that is repeated as long as the isRunning - * attribute is true. Within the loop, the taskFunction is called, and - * afterwards the checkAndRestartPeriod system call to block the task until the next - * period. On missing the deadline, the deadlineMissedFunction is executed. - */ - void taskFunctionality( void ); - /** - * @brief In this attribute the pointer to the function which shall be executed periodically - * is stored. - */ - ReturnValue_t ( *taskFunction )( TaskBase* ); -public: - /** - * @brief The standard constructor of the class. - * @details This is the general constructor of the class. In the underlying TaskBase class, - * a new operating system task is created. In addition to the TaskBase parameters, - * the period, the actual function to be executed and an optional "deadline-missed" - * function pointer is passed. - * @param priority Sets the priority of a task. Values range from a low 0 to a high 99. - * @param stack_size The stack size reserved by the operating system for the task. - * @param setPeriod The length of the period with which the task's functionality will be - * executed. It is expressed in clock ticks. - * @param (*setDeadlineMissedFunc)() The function pointer to the deadline missed function - * that shall be assigned. - * @param ( *setTaskFunction )( TaskBase* ) A pointer to the actual function to be executed. - */ - PeriodicTask( const char *name, TaskPriority_t setPriority, size_t setStack, Interval_t setPeriod, void ( *setDeadlineMissedFunc )(), ReturnValue_t ( *setTaskFunction )( TaskBase* ) ); - - /** - * @brief The destructor of the class. - * @details Similar to the destructor in the parent class, no memory clean-ups are necessary. - * Thus, the destructor is empty. - */ - virtual ~PeriodicTask( void ); - - /** - * @brief The method to start the task. - * @details The method starts the task with the respective system call. - * Entry point is the taskEntryPoint method described below. - * The address of the task object is passed as an argument - * to the system call. - */ - virtual ReturnValue_t startTask( void ); -}; - -#endif /* OPUSPERIODICTASK_H_ */ diff --git a/tasks/PeriodicTaskIF.h b/tasks/PeriodicTaskIF.h new file mode 100644 index 00000000..1415d7f6 --- /dev/null +++ b/tasks/PeriodicTaskIF.h @@ -0,0 +1,31 @@ +#ifndef PERIODICTASKIF_H_ +#define PERIODICTASKIF_H_ + +#include +class ExecutableObjectIF; +/** + * New version of TaskIF + * Follows RAII principles, i.e. there's no create or delete method. + * Minimalistic. +*/ +class PeriodicTaskIF { +public: + static const uint64_t MINIMUM_STACK_SIZE; + /** + * @brief A virtual destructor as it is mandatory for interfaces. + */ + virtual ~PeriodicTaskIF() { } + /** + * @brief With the startTask method, a created task can be started for the first time. + */ + virtual ReturnValue_t startTask() = 0; + + virtual ReturnValue_t addComponent(object_id_t) {return HasReturnvaluesIF::RETURN_FAILED;}; + + virtual ReturnValue_t sleepFor(uint32_t ms) = 0; + + virtual uint32_t getPeriodMs() const = 0; +}; + + +#endif /* PERIODICTASKIF_H_ */ diff --git a/tasks/TaskBase.cpp b/tasks/TaskBase.cpp deleted file mode 100644 index 9279bad1..00000000 --- a/tasks/TaskBase.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * TaskBase.cpp - * - * Created on: Nov 5, 2012 - * Author: baetz - */ - - - - -#include -#include - -TaskBase::TaskBase( TaskPriority_t set_priority, size_t stack_size , const char *name) : isRunning(false) { - Name_t osalName = 0; - for (uint8_t i = 0; i < 4; i++){ - if (name[i] == 0){ - break; - } - osalName += name[i] << (8*(3-i)); - } - //The task is created with the operating system's system call. - ReturnValue_t status = OSAL::createTask( - osalName, set_priority, - stack_size, - OSAL::PREEMPT | OSAL::NO_TIMESLICE | OSAL::NO_ASR, OSAL::FLOATING_POINT, - &( this->id ) - ); - //TODO: Safe system halt or FDIR call on failed task creation? - if( status != RETURN_OK ) { - error << "TaskBase::TaskBase: createTask with name " << std::hex << osalName << std::dec << " failed with return code " << (uint32_t)status << std::endl; - this->id = 0; - } else { -// debug << "TaskBase::TaskBase: createTask successful. Name: " << std::hex << new_name << ", ID: " << this->id << std::dec << std::endl; - } -} - -TaskBase::~TaskBase() { - OSAL::deleteTask( &(this->id) ); -} - -TaskId_t TaskBase::getId() { - return this->id; -} - -void TaskBase::setRunning( bool set ) { - this->isRunning = set; -} - -uint8_t TaskBase::taskCounter = 0; diff --git a/tasks/TaskBase.h b/tasks/TaskBase.h deleted file mode 100644 index 2aa66d07..00000000 --- a/tasks/TaskBase.h +++ /dev/null @@ -1,86 +0,0 @@ -/** - * @file TaskBase.h - * - * @date 11/05/2012 - * @author Bastian Baetz - * - * @brief This file contains the definition of the TaskBase class. - * It is a reviewed and updated version of a file originally created - * by Claas Ziemke in 2010. - */ - -#ifndef TASKBASE_H_ -#define TASKBASE_H_ - - - -#include -#include -#include -/** - * @brief This is the basic task handling class. - * - * @details The virtual parent class contains attributes and methods to perform basic task operations. - * The task is created in the constructor. Next to the main methods to set the functionality - * and start the task, it also contains methods to stop execution safely and to return its - * identifier. - * The whole class was undergoing a major redesign by Bastian Baetz in November 2012 where - * unnecessary attributes were removed and task creation was simplified. Also, the class - * implements the TaskIF now. - * - * @author Claas Ziemke - * - * @date 07/23/2010 - * - * @ingroup task_handling - */ -class TaskBase : public TaskIF, public HasReturnvaluesIF { -protected: - /** - * @brief The task's name -a user specific information for the operating system- is - * generated automatically with the help of this static counter. - */ - static uint8_t taskCounter; - /** - * @brief The class stores the task id it got assigned from the operating system in this attribute. - * If initialization fails, the id is set to zero. - */ - TaskId_t id; - /** - * @brief The isRunning information can be used by child classes to change its operational behavior. - * @details It is not used in the TaskBase class itself, but for example in periodic tasks to leave - * the periodic activity. - */ - bool isRunning; -public: - /** - * @brief The constructor creates and initializes a task. - * @details This is accomplished by using the operating system call to create a task. The name is - * created automatically with the help od taskCounter. Priority and stack size are - * adjustable, all other attributes are set with default values. - * @param priority Sets the priority of a task. Values range from a low 0 to a high 99. - * @param stack_size The stack size reserved by the operating system for the task. - * @param nam The name of the Task, as a null-terminated String. Currently max 4 chars supported (excluding Null-terminator), rest will be truncated - */ - TaskBase( TaskPriority_t priority, size_t stack_size, const char *name); - /** - * @brief In the destructor, the created task is deleted. - */ - virtual ~TaskBase(); - /** - * @brief This abstract method must be implemented by child classes to successfully start a task. - */ - virtual ReturnValue_t startTask() = 0; - /** - * @brief This method returns the task id of this class. - */ - TaskId_t getId(); - /** - * @brief With this method, the task "running" state can be set. - * @details This typically involves leaving any kind of periodic activity. - */ - void setRunning( bool set ); -}; - - -#endif /* TASKBASE_H_ */ diff --git a/tasks/TaskFactory.h b/tasks/TaskFactory.h new file mode 100644 index 00000000..2a1684e6 --- /dev/null +++ b/tasks/TaskFactory.h @@ -0,0 +1,65 @@ +#ifndef FRAMEWORK_TASKS_TASKFACTORY_H_ +#define FRAMEWORK_TASKS_TASKFACTORY_H_ + +#include +#include + + + + +/** + * Singleton Class that produces Tasks. + */ +class TaskFactory{ +public: + virtual ~TaskFactory(); + /** + * Returns the single instance of TaskFactory. + * The implementation of #instance is found in its subclasses. + * Thus, we choose link-time variability of the instance. + */ + static TaskFactory* instance(); + + /** + * Creates a new periodic task and returns the interface pointer. + * @param name_ Name of the task + * @param taskPriority_ Priority of the task + * @param stackSize_ Stack Size of the task + * @param period_ Period of the task + * @param deadLineMissedFunction_ Function to be called if a deadline was missed + * @return PeriodicTaskIF* Pointer to the newly created Task + */ + PeriodicTaskIF* createPeriodicTask(OSAL::TaskName name_,OSAL::TaskPriority taskPriority_,OSAL::TaskStackSize stackSize_,OSAL::TaskPeriod periodInSeconds_,OSAL::TaskDeadlineMissedFunction deadLineMissedFunction_); + + /** + * + * @param name_ Name of the task + * @param taskPriority_ Priority of the task + * @param stackSize_ Stack Size of the task + * @param period_ Period of the task + * @param deadLineMissedFunction_ Function to be called if a deadline was missed + * @return FixedTimeslotTaskIF* Pointer to the newly created Task + */ + FixedTimeslotTaskIF* createFixedTimeslotTask(OSAL::TaskName name_,OSAL::TaskPriority taskPriority_,OSAL::TaskStackSize stackSize_,OSAL::TaskPeriod periodInSeconds_,OSAL::TaskDeadlineMissedFunction deadLineMissedFunction_); + + + /** + * Function to be called to delete a task + * @param task The pointer to the task that shall be deleted + * @return Success of deletion + */ + ReturnValue_t deleteTask(PeriodicTaskIF* task); + +private: + /** + * External instantiation is not allowed. + */ + TaskFactory(); + static TaskFactory* factoryInstance; + + +}; + + + +#endif /* FRAMEWORK_TASKS_TASKFACTORY_H_ */ diff --git a/tasks/TaskIF.h b/tasks/TaskIF.h deleted file mode 100644 index 4b383c5e..00000000 --- a/tasks/TaskIF.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef TASKIF_H_ -#define TASKIF_H_ - -/** - * \defgroup task_handling Task Handling - * This is the group, where all classes associated with Task Handling belong to. - * Task handling is based on the task handling methods which the operating system - * provides (currently RTEMS). - */ - -/** - * @brief This interface provides all basic methods to handle task operations. - * @details To uniformly operate different types of tasks, this interface provides methods to - * start and stop created tasks and to return the operating system's identifier. - * - * @date 11/05/2012 - * @ingroup task_handling - * author Bastian Baetz - */ -class TaskIF { -public: - /** - * @brief A virtual destructor as it is mandatory for interfaces. - */ - virtual ~TaskIF() { } - /** - * @brief With the startTask method, a created task can be started for the first time. - */ - virtual ReturnValue_t startTask() = 0; - /** - * @brief The getId method returns the task's operating system identifier. - */ - virtual TaskId_t getId() = 0; - /** - * @brief With this method, the task "running" state can be set. - * @details This typically involves leaving any kind of periodic activity. - */ - virtual void setRunning( bool set ) = 0; -}; - - -#endif /* TASKIF_H_ */ diff --git a/tasks/Typedef.h b/tasks/Typedef.h new file mode 100644 index 00000000..bbea059a --- /dev/null +++ b/tasks/Typedef.h @@ -0,0 +1,21 @@ +#ifndef FRAMEWORK_TASKS_TYPEDEF_H_ +#define FRAMEWORK_TASKS_TYPEDEF_H_ + + +#ifndef API +#error Please specify Operating System API. Supported: API=RTEMS_API +#elif API == RTEMS_API +#include +namespace OSAL{ + typedef const char* TaskName; + typedef rtems_task_priority TaskPriority; + typedef size_t TaskStackSize; + typedef double TaskPeriod; + typedef void (*TaskDeadlineMissedFunction)(); +}; +#endif + + + + +#endif /* FRAMEWORK_TASKS_TYPEDEF_H_ */ diff --git a/tcdistribution/CCSDSDistributor.cpp b/tcdistribution/CCSDSDistributor.cpp index 952f4fbd..ecd7702e 100644 --- a/tcdistribution/CCSDSDistributor.cpp +++ b/tcdistribution/CCSDSDistributor.cpp @@ -1,16 +1,9 @@ -/* - * CCSDSDistributor.cpp - * - * Created on: 18.06.2012 - * Author: baetz - */ - #include #include #include -CCSDSDistributor::CCSDSDistributor( uint16_t set_default_apid ) : - TcDistributor( objects::CCSDS_PACKET_DISTRIBUTOR ), default_apid( set_default_apid ), tcStore(NULL) { +CCSDSDistributor::CCSDSDistributor( uint16_t setDefaultApid, object_id_t setObjectId ) : + TcDistributor( setObjectId ), default_apid( setDefaultApid ), tcStore(NULL) { } CCSDSDistributor::~CCSDSDistributor() { @@ -21,6 +14,7 @@ iterator_t CCSDSDistributor::selectDestination() { // debug << "CCSDSDistributor::selectDestination received: " << this->currentMessage.getStorageId().pool_index << ", " << this->currentMessage.getStorageId().packet_index << std::endl; const uint8_t* p_packet = NULL; uint32_t size = 0; + //TODO check returncode? this->tcStore->getData( this->currentMessage.getStorageId(), &p_packet, &size ); SpacePacketBase current_packet( p_packet ); // info << "CCSDSDistributor::selectDestination has packet with APID " << std::hex << current_packet.getAPID() << std::dec << std::endl; @@ -35,7 +29,7 @@ iterator_t CCSDSDistributor::selectDestination() { } MessageQueueId_t CCSDSDistributor::getRequestQueue() { - return this->tcQueue.getId(); + return tcQueue->getId(); } ReturnValue_t CCSDSDistributor::registerApplication( diff --git a/tcdistribution/CCSDSDistributor.h b/tcdistribution/CCSDSDistributor.h index 5b22c710..9dce34f2 100644 --- a/tcdistribution/CCSDSDistributor.h +++ b/tcdistribution/CCSDSDistributor.h @@ -1,10 +1,3 @@ -/* - * CCSDSDistributor.h - * - * Created on: 18.06.2012 - * Author: baetz - */ - #ifndef CCSDSDISTRIBUTOR_H_ #define CCSDSDISTRIBUTOR_H_ @@ -48,7 +41,7 @@ public: * \c tcStore is set in the \c initialize method. * @param set_default_apid The default APID, where packets with unknown destination are sent to. */ - CCSDSDistributor( uint16_t set_default_apid = 0x35 ); + CCSDSDistributor( uint16_t setDefaultApid, object_id_t setObjectId ); /** * The destructor is empty. */ diff --git a/tcdistribution/CCSDSDistributorIF.h b/tcdistribution/CCSDSDistributorIF.h index 9843c8a8..dc1263a9 100644 --- a/tcdistribution/CCSDSDistributorIF.h +++ b/tcdistribution/CCSDSDistributorIF.h @@ -1,15 +1,8 @@ -/* - * CCSDSDistributorIF.h - * - * Created on: 21.11.2012 - * Author: baetz - */ - #ifndef CCSDSDISTRIBUTORIF_H_ #define CCSDSDISTRIBUTORIF_H_ -#include #include +#include /** * This is the Interface to a CCSDS Distributor. * On a CCSDS Distributor, Applications (in terms of CCSDS) may register themselves, diff --git a/tcdistribution/Makefile b/tcdistribution/Makefile deleted file mode 100755 index 03c13e75..00000000 --- a/tcdistribution/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -# -# OSAL makefile -# -# Created on: Mar 04, 2010 -# Author: ziemke -# Author: Claas Ziemke -# Copyright 2010, Claas Ziemke -# - -BASEDIR=../../ -include $(BASEDIR)options.mk - -OBJ = $(BUILDDIR)/TcDistributor.o\ - $(BUILDDIR)/CCSDSDistributor.o - -all: $(OBJ) - -$(BUILDDIR)/%.o: %.cpp %.h - $(CPP) $(CFLAGS) $(DEFINES) $(CCOPT) ${INCLUDE} -c $< -o $@ - -clean: - $(RM) *.o *.gcno *.gcda diff --git a/tcdistribution/PUSDistributor.cpp b/tcdistribution/PUSDistributor.cpp index 46f2ab37..ab87c571 100644 --- a/tcdistribution/PUSDistributor.cpp +++ b/tcdistribution/PUSDistributor.cpp @@ -1,20 +1,12 @@ -/* - * PUSDistributor.cpp - * - * Created on: 18.06.2012 - * Author: baetz - */ - - - #include #include #include #include #include -PUSDistributor::PUSDistributor(uint16_t set_apid ) : TcDistributor(objects::PUS_PACKET_DISTRIBUTOR), checker(set_apid), verify_channel(), - current_packet(), tc_status(RETURN_FAILED) { +PUSDistributor::PUSDistributor(uint16_t setApid, object_id_t setObjectId, object_id_t setPacketSource) : + TcDistributor(setObjectId), checker(setApid), verifyChannel(), currentPacket(), tcStatus( + RETURN_FAILED), packetSource(setPacketSource) { } @@ -25,21 +17,22 @@ PUSDistributor::~PUSDistributor() { iterator_t PUSDistributor::selectDestination() { // debug << "PUSDistributor::handlePacket received: " << this->current_packet_id.store_index << ", " << this->current_packet_id.packet_index << std::endl; iterator_t queueMapIt = this->queueMap.end(); - this->current_packet.setStoreAddress( this->currentMessage.getStorageId() ); - if ( current_packet.getWholeData() != NULL ) { - tc_status = checker.checkPacket( ¤t_packet ); + this->currentPacket.setStoreAddress(this->currentMessage.getStorageId()); + if (currentPacket.getWholeData() != NULL) { + tcStatus = checker.checkPacket(¤tPacket); // info << "PUSDistributor::handlePacket: packetCheck returned with " << (int)tc_status << std::endl; - uint32_t queue_id = current_packet.getService(); - queueMapIt = this->queueMap.find( queue_id ); + uint32_t queue_id = currentPacket.getService(); + queueMapIt = this->queueMap.find(queue_id); } else { - tc_status = PACKET_LOST; + tcStatus = PACKET_LOST; } - if ( queueMapIt == this->queueMap.end() ) { - tc_status = DESTINATION_NOT_FOUND; + if (queueMapIt == this->queueMap.end()) { + tcStatus = DESTINATION_NOT_FOUND; } - if ( tc_status != RETURN_OK ) { - debug << "PUSDistributor::handlePacket: error with " << (int)tc_status << std::endl; + if (tcStatus != RETURN_OK) { + debug << "PUSDistributor::handlePacket: error with " << (int) tcStatus + << std::endl; return this->queueMap.end(); } else { return queueMapIt; @@ -47,7 +40,6 @@ iterator_t PUSDistributor::selectDestination() { } - //uint16_t PUSDistributor::createDestination( uint8_t service_id, uint8_t subservice_id ) { // return ( service_id << 8 ) + subservice_id; //} @@ -57,28 +49,31 @@ ReturnValue_t PUSDistributor::registerService(AcceptsTelecommandsIF* service) { bool errorCode = true; uint16_t serviceId = service->getIdentifier(); MessageQueueId_t queue = service->getRequestQueue(); - errorCode = this->queueMap.insert( std::pair( serviceId, queue) ).second; - if( errorCode == false ) { - returnValue = OSAL::RESOURCE_IN_USE; + errorCode = this->queueMap.insert( + std::pair(serviceId, queue)).second; + if (errorCode == false) { + returnValue = OperatingSystemIF::RESOURCE_IN_USE; } return returnValue; } MessageQueueId_t PUSDistributor::getRequestQueue() { - return this->tcQueue.getId(); + return tcQueue->getId(); } ReturnValue_t PUSDistributor::callbackAfterSending(ReturnValue_t queueStatus) { - if ( queueStatus != RETURN_OK ) { - tc_status = queueStatus; + if (queueStatus != RETURN_OK) { + tcStatus = queueStatus; } - if ( tc_status != RETURN_OK ) { - this->verify_channel.sendFailureReport( TC_VERIFY::ACCEPTANCE_FAILURE, ¤t_packet, tc_status ); + if (tcStatus != RETURN_OK) { + this->verifyChannel.sendFailureReport(TC_VERIFY::ACCEPTANCE_FAILURE, + ¤tPacket, tcStatus); //A failed packet is deleted immediately after reporting, otherwise it will block memory. - current_packet.deletePacket(); + currentPacket.deletePacket(); return RETURN_FAILED; } else { - this->verify_channel.sendSuccessReport( TC_VERIFY::ACCEPTANCE_SUCCESS, ¤t_packet ); + this->verifyChannel.sendSuccessReport(TC_VERIFY::ACCEPTANCE_SUCCESS, + ¤tPacket); return RETURN_OK; } } @@ -88,7 +83,8 @@ uint16_t PUSDistributor::getIdentifier() { } ReturnValue_t PUSDistributor::initialize() { - CCSDSDistributorIF* ccsdsDistributor = objectManager->get(objects::CCSDS_PACKET_DISTRIBUTOR); + CCSDSDistributorIF* ccsdsDistributor = + objectManager->get(packetSource); if (ccsdsDistributor == NULL) { return RETURN_FAILED; } else { diff --git a/tcdistribution/PUSDistributor.h b/tcdistribution/PUSDistributor.h index 620f42bd..8d774662 100644 --- a/tcdistribution/PUSDistributor.h +++ b/tcdistribution/PUSDistributor.h @@ -1,10 +1,3 @@ -/* - * PUSDistributor.h - * - * Created on: 18.06.2012 - * Author: baetz - */ - #ifndef PUSDISTRIBUTOR_H_ #define PUSDISTRIBUTOR_H_ @@ -21,7 +14,25 @@ * or failure messages. * \ingroup tc_distribution */ -class PUSDistributor : public TcDistributor, public PUSDistributorIF, public AcceptsTelecommandsIF { +class PUSDistributor: public TcDistributor, + public PUSDistributorIF, + public AcceptsTelecommandsIF { +public: + /** + * The ctor passes \c set_apid to the checker class and calls the TcDistribution ctor with a certain object id. + * @param setApid The APID of this receiving Application. + * @param setObjectId Object ID of the distributor itself + * @param setPacketSource Object ID of the source of TC packets. Must implement CCSDSDistributorIF. + */ + PUSDistributor(uint16_t setApid, object_id_t setObjectId, object_id_t setPacketSource); + /** + * The destructor is empty. + */ + virtual ~PUSDistributor(); + ReturnValue_t registerService(AcceptsTelecommandsIF* service); + MessageQueueId_t getRequestQueue(); + uint16_t getIdentifier(); + ReturnValue_t initialize(); protected: /** * This attribute contains the class, that performs a formal packet check. @@ -30,15 +41,17 @@ protected: /** * With this class, verification messages are sent to the TC Verification service. */ - VerificationReporter verify_channel; + VerificationReporter verifyChannel; /** * The currently handled packet is stored here. */ - TcPacketStored current_packet; + TcPacketStored currentPacket; /** * With this variable, the current check status is stored to generate acceptance messages later. */ - ReturnValue_t tc_status; + ReturnValue_t tcStatus; + + const object_id_t packetSource; /** * This method reads the packet service, checks if such a service is registered and forwards the packet to the destination. * It also initiates the formal packet check and sending of verification messages. @@ -48,24 +61,7 @@ protected: /** * The callback here handles the generation of acceptance success/failure messages. */ - ReturnValue_t callbackAfterSending( ReturnValue_t queueStatus ); -public: - /** - * The ctor passes \c set_apid to the checker class and calls the TcDistribution ctor with a certain object id. - * @param set_apid The APID of this receiving Application. - */ - PUSDistributor( uint16_t set_apid ); - /** - * The destructor is empty. - */ - virtual ~PUSDistributor(); - ReturnValue_t registerService( AcceptsTelecommandsIF* service ); - MessageQueueId_t getRequestQueue(); - uint16_t getIdentifier(); - ReturnValue_t initialize(); + ReturnValue_t callbackAfterSending(ReturnValue_t queueStatus); }; - - - #endif /* PUSDISTRIBUTOR_H_ */ diff --git a/tcdistribution/PUSDistributorIF.h b/tcdistribution/PUSDistributorIF.h index f40e6f9f..bb101137 100644 --- a/tcdistribution/PUSDistributorIF.h +++ b/tcdistribution/PUSDistributorIF.h @@ -1,15 +1,8 @@ -/* - * PUSDistributorIF.h - * - * Created on: 21.11.2012 - * Author: baetz - */ - #ifndef PUSDISTRIBUTORIF_H_ #define PUSDISTRIBUTORIF_H_ -#include #include +#include /** * This interface allows PUS Services to register themselves at a PUS Distributor. * \ingroup tc_distribution diff --git a/tcdistribution/TcDistributor.cpp b/tcdistribution/TcDistributor.cpp index 4c7a67a9..8c4ff16f 100644 --- a/tcdistribution/TcDistributor.cpp +++ b/tcdistribution/TcDistributor.cpp @@ -1,26 +1,26 @@ #include -#include #include #include #include +#include TcDistributor::TcDistributor(object_id_t set_object_id) : - SystemObject(set_object_id), tcQueue(DISTRIBUTER_MAX_PACKETS) { - + SystemObject(set_object_id), tcQueue(NULL) { + tcQueue = QueueFactory::instance()->createMessageQueue(DISTRIBUTER_MAX_PACKETS); } TcDistributor::~TcDistributor() { - //Nothing to do in the destructor, MQ's are destroyed elsewhere. + QueueFactory::instance()->deleteMessageQueue(tcQueue); } -ReturnValue_t TcDistributor::performOperation(void) { +ReturnValue_t TcDistributor::performOperation(uint8_t opCode) { ReturnValue_t status = RETURN_OK; // debug << "TcDistributor: performing Operation." << std::endl; - for (status = tcQueue.receiveMessage(¤tMessage); status == RETURN_OK; - status = tcQueue.receiveMessage(¤tMessage)) { + for (status = tcQueue->receiveMessage(¤tMessage); status == RETURN_OK; + status = tcQueue->receiveMessage(¤tMessage)) { status = handlePacket(); } - if (status == OSAL::QUEUE_EMPTY) { + if (status == OperatingSystemIF::QUEUE_EMPTY) { return RETURN_OK; } else { return status; @@ -32,7 +32,7 @@ ReturnValue_t TcDistributor::handlePacket() { iterator_t queueMapIt = this->selectDestination(); ReturnValue_t returnValue = RETURN_FAILED; if (queueMapIt != this->queueMap.end()) { - returnValue = this->tcQueue.sendMessage(queueMapIt->second, + returnValue = this->tcQueue->sendMessage(queueMapIt->second, &this->currentMessage); } return this->callbackAfterSending(returnValue); diff --git a/tcdistribution/TcDistributor.h b/tcdistribution/TcDistributor.h index 792762ca..fa3a7584 100644 --- a/tcdistribution/TcDistributor.h +++ b/tcdistribution/TcDistributor.h @@ -1,13 +1,13 @@ #ifndef TCDISTRIBUTOR_H_ #define TCDISTRIBUTOR_H_ -#include #include #include -#include +#include #include #include #include #include +#include #include @@ -42,7 +42,7 @@ protected: * This is the receiving queue for incoming Telecommands. * The child classes must make its queue id public. */ - MessageQueue tcQueue; + MessageQueueIF* tcQueue; /** * The last received incoming packet information is stored in this * member. @@ -82,7 +82,7 @@ protected: */ virtual ReturnValue_t callbackAfterSending( ReturnValue_t queueStatus ); public: - static const uint8_t INTERFACE_ID = PACKET_DISTRIBUTION; + static const uint8_t INTERFACE_ID = CLASS_ID::PACKET_DISTRIBUTION; static const ReturnValue_t PACKET_LOST = MAKE_RETURN_CODE( 1 ); static const ReturnValue_t DESTINATION_NOT_FOUND = MAKE_RETURN_CODE( 2 ); /** @@ -105,7 +105,7 @@ public: * with distribution. * @return The error code of the message queue call. */ - ReturnValue_t performOperation(); + ReturnValue_t performOperation(uint8_t opCode); /** * A simple debug print, that prints all distribution information stored in * queueMap. diff --git a/tcdistribution/TcPacketCheck.cpp b/tcdistribution/TcPacketCheck.cpp index e82ee564..b942e6b6 100644 --- a/tcdistribution/TcPacketCheck.cpp +++ b/tcdistribution/TcPacketCheck.cpp @@ -1,11 +1,3 @@ -/* - * TcPacketCheck.cpp - * - * Created on: 19.06.2012 - * Author: baetz - */ - - #include #include #include diff --git a/tcdistribution/TcPacketCheck.h b/tcdistribution/TcPacketCheck.h index b635b949..88810ed7 100644 --- a/tcdistribution/TcPacketCheck.h +++ b/tcdistribution/TcPacketCheck.h @@ -1,10 +1,3 @@ -/* - * TcPacketCheck.h - * - * Created on: 19.06.2012 - * Author: baetz - */ - #ifndef TCPACKETCHECK_H_ #define TCPACKETCHECK_H_ @@ -36,7 +29,7 @@ protected: */ uint16_t apid; public: - static const uint8_t INTERFACE_ID = TC_PACKET_CHECK; + static const uint8_t INTERFACE_ID = CLASS_ID::TC_PACKET_CHECK; static const ReturnValue_t ILLEGAL_APID = MAKE_RETURN_CODE( 0 ); static const ReturnValue_t INCOMPLETE_PACKET = MAKE_RETURN_CODE( 1 ); static const ReturnValue_t INCORRECT_CHECKSUM = MAKE_RETURN_CODE( 2 ); diff --git a/thermal/AbstractTemperatureSensor.cpp b/thermal/AbstractTemperatureSensor.cpp new file mode 100644 index 00000000..be143410 --- /dev/null +++ b/thermal/AbstractTemperatureSensor.cpp @@ -0,0 +1,70 @@ +#include "AbstractTemperatureSensor.h" +#include + +AbstractTemperatureSensor::AbstractTemperatureSensor(object_id_t setObjectid, + ThermalModuleIF *thermalModule) : + SystemObject(setObjectid), commandQueue(NULL), healthHelper(this, + setObjectid), parameterHelper(this) { + if (thermalModule != NULL) { + thermalModule->registerSensor(this); + } + commandQueue = QueueFactory::instance()->createMessageQueue(); +} + +AbstractTemperatureSensor::~AbstractTemperatureSensor() { + QueueFactory::instance()->deleteMessageQueue(commandQueue); +} + +MessageQueueId_t AbstractTemperatureSensor::getCommandQueue() const { + return commandQueue->getId(); +} + +ReturnValue_t AbstractTemperatureSensor::initialize() { + ReturnValue_t result = SystemObject::initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = healthHelper.initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = parameterHelper.initialize(); + return result; +} + +ReturnValue_t AbstractTemperatureSensor::performOperation(uint8_t opCode) { + handleCommandQueue(); + doChildOperation(); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t AbstractTemperatureSensor::performHealthOp() { + handleCommandQueue(); + return HasReturnvaluesIF::RETURN_OK; +} + +void AbstractTemperatureSensor::handleCommandQueue() { + CommandMessage message; + ReturnValue_t result = commandQueue->receiveMessage(&message); + if (result == HasReturnvaluesIF::RETURN_OK) { + result = healthHelper.handleHealthCommand(&message); + if (result == HasReturnvaluesIF::RETURN_OK) { + return; + } + result = parameterHelper.handleParameterMessage(&message); + if (result == HasReturnvaluesIF::RETURN_OK) { + return; + } + message.setToUnknownCommand(); + commandQueue->reply(&message); + } +} + +ReturnValue_t AbstractTemperatureSensor::setHealth(HealthState health) { + healthHelper.setHealth(health); + return HasReturnvaluesIF::RETURN_OK; +} + +HasHealthIF::HealthState AbstractTemperatureSensor::getHealth() { + return healthHelper.getHealth(); +} diff --git a/thermal/AbstractTemperatureSensor.h b/thermal/AbstractTemperatureSensor.h new file mode 100644 index 00000000..d620bd05 --- /dev/null +++ b/thermal/AbstractTemperatureSensor.h @@ -0,0 +1,55 @@ +#ifndef ABSTRACTSENSOR_H_ +#define ABSTRACTSENSOR_H_ + +#include +#include +#include +#include +#include +#include +#include "ThermalModuleIF.h" +#include "tcsDefinitions.h" + +class AbstractTemperatureSensor: public HasHealthIF, + public SystemObject, + public ExecutableObjectIF, + public ReceivesParameterMessagesIF { +public: + + static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::T_SENSORS; + static const Event TEMP_SENSOR_HIGH = MAKE_EVENT(0, SEVERITY::LOW); + static const Event TEMP_SENSOR_LOW = MAKE_EVENT(1, SEVERITY::LOW); + static const Event TEMP_SENSOR_GRADIENT = MAKE_EVENT(2, SEVERITY::LOW); + + //TODO, modern gcc complains about const + static const float ZERO_KELVIN_C = -273.15; + AbstractTemperatureSensor(object_id_t setObjectid, + ThermalModuleIF *thermalModule); + virtual ~AbstractTemperatureSensor(); + + virtual MessageQueueId_t getCommandQueue() const; + + ReturnValue_t initialize(); + + ReturnValue_t performHealthOp(); + + ReturnValue_t performOperation(uint8_t opCode); + + virtual float getTemperature() = 0; + virtual bool isValid() = 0; + + virtual void resetOldState() = 0; + + ReturnValue_t setHealth(HealthState health); + HasHealthIF::HealthState getHealth(); +protected: + MessageQueueIF* commandQueue; + HealthHelper healthHelper; + ParameterHelper parameterHelper; + + virtual void doChildOperation() = 0; + + void handleCommandQueue(); +}; + +#endif /* ABSTRACTSENSOR_H_ */ diff --git a/thermal/CoreComponent.cpp b/thermal/CoreComponent.cpp new file mode 100644 index 00000000..304712ef --- /dev/null +++ b/thermal/CoreComponent.cpp @@ -0,0 +1,257 @@ +#include "CoreComponent.h" + +CoreComponent::CoreComponent(object_id_t reportingObjectId, uint8_t domainId, + uint32_t temperaturePoolId, uint32_t targetStatePoolId, + uint32_t currentStatePoolId, uint32_t requestPoolId, DataSet* dataSet, + AbstractTemperatureSensor* sensor, + AbstractTemperatureSensor* firstRedundantSensor, + AbstractTemperatureSensor* secondRedundantSensor, + ThermalModuleIF* thermalModule, Parameters parameters, + Priority priority, StateRequest initialTargetState) : + sensor(sensor), firstRedundantSensor(firstRedundantSensor), secondRedundantSensor( + secondRedundantSensor), thermalModule(thermalModule), temperature( + temperaturePoolId, dataSet, PoolVariableIF::VAR_WRITE), targetState( + targetStatePoolId, dataSet, PoolVariableIF::VAR_READ), currentState( + currentStatePoolId, dataSet, PoolVariableIF::VAR_WRITE), heaterRequest( + requestPoolId, dataSet, PoolVariableIF::VAR_WRITE), isHeating( + false), isSafeComponent(priority == SAFE), minTemp(999), maxTemp( + AbstractTemperatureSensor::ZERO_KELVIN_C), parameters( + parameters), temperatureMonitor(reportingObjectId, + domainId + 1, + DataPool::poolIdAndPositionToPid(temperaturePoolId, 0), + COMPONENT_TEMP_CONFIRMATION), domainId(domainId) { + if (thermalModule != NULL) { + thermalModule->registerComponent(this, priority); + } + //Set thermal state once, then leave to operator. + DataSet mySet; + PoolVariable writableTargetState(targetStatePoolId, &mySet, + PoolVariableIF::VAR_WRITE); + writableTargetState = initialTargetState; + mySet.commit(PoolVariableIF::VALID); +} + +CoreComponent::~CoreComponent() { +} + +ThermalComponentIF::HeaterRequest CoreComponent::performOperation(uint8_t opCode) { + HeaterRequest request = HEATER_DONT_CARE; + //SHOULDDO: Better pass db_float_t* to getTemperature and set it invalid if invalid. + temperature = getTemperature(); + updateMinMaxTemp(); + if ((temperature != INVALID_TEMPERATURE)) { + temperature.setValid(PoolVariableIF::VALID); + State state = getState(temperature, getParameters(), targetState); + currentState = state; + checkLimits(state); + request = getHeaterRequest(targetState, temperature, getParameters()); + } else { + temperatureMonitor.setToInvalid(); + temperature.setValid(PoolVariableIF::INVALID); + currentState = UNKNOWN; + request = HEATER_DONT_CARE; + } + currentState.setValid(PoolVariableIF::VALID); + heaterRequest = request; + heaterRequest.setValid(PoolVariableIF::VALID); + return request; +} + +void CoreComponent::markStateIgnored() { + currentState = getIgnoredState(currentState); +} + +object_id_t CoreComponent::getObjectId() { + return temperatureMonitor.getReporterId(); +} + +float CoreComponent::getLowerOpLimit() { + return parameters.lowerOpLimit; +} + +ReturnValue_t CoreComponent::setTargetState(int8_t newState) { + DataSet mySet; + PoolVariable writableTargetState(targetState.getDataPoolId(), + &mySet, PoolVariableIF::VAR_READ_WRITE); + mySet.read(); + if ((writableTargetState == STATE_REQUEST_OPERATIONAL) + && (newState != STATE_REQUEST_IGNORE)) { + return HasReturnvaluesIF::RETURN_FAILED; + } + switch (newState) { + case STATE_REQUEST_HEATING: + case STATE_REQUEST_IGNORE: + case STATE_REQUEST_OPERATIONAL: + writableTargetState = newState; + break; + case STATE_REQUEST_NON_OPERATIONAL: + default: + return INVALID_TARGET_STATE; + } + mySet.commit(PoolVariableIF::VALID); + return HasReturnvaluesIF::RETURN_OK; +} + +void CoreComponent::setOutputInvalid() { + temperature = INVALID_TEMPERATURE; + temperature.setValid(PoolVariableIF::INVALID); + currentState.setValid(PoolVariableIF::INVALID); + heaterRequest = HEATER_DONT_CARE; + heaterRequest.setValid(PoolVariableIF::INVALID); + temperatureMonitor.setToUnchecked(); +} + +float CoreComponent::getTemperature() { + if ((sensor != NULL) && (sensor->isValid())) { + return sensor->getTemperature(); + } + + if ((firstRedundantSensor != NULL) && (firstRedundantSensor->isValid())) { + return firstRedundantSensor->getTemperature(); + } + + if ((secondRedundantSensor != NULL) && (secondRedundantSensor->isValid())) { + return secondRedundantSensor->getTemperature(); + } + + if (thermalModule != NULL) { + float temperature = thermalModule->getTemperature(); + if (temperature != ThermalModuleIF::INVALID_TEMPERATURE) { + return temperature; + } else { + return INVALID_TEMPERATURE; + } + } else { + return INVALID_TEMPERATURE; + } +} + +ThermalComponentIF::State CoreComponent::getState(float temperature, + Parameters parameters, int8_t targetState) { + ThermalComponentIF::State state; + + if (temperature < parameters.lowerOpLimit) { + state = NON_OPERATIONAL_LOW; + } else if (temperature < parameters.upperOpLimit) { + state = OPERATIONAL; + } else { + state = NON_OPERATIONAL_HIGH; + } + if (targetState == STATE_REQUEST_IGNORE) { + state = getIgnoredState(state); + } + + return state; +} + +void CoreComponent::checkLimits(ThermalComponentIF::State state) { + //Checks operational limits only. + temperatureMonitor.translateState(state, temperature.value, + getParameters().lowerOpLimit, getParameters().upperOpLimit); + +} + +ThermalComponentIF::HeaterRequest CoreComponent::getHeaterRequest( + int8_t targetState, float temperature, Parameters parameters) { + if (targetState == STATE_REQUEST_IGNORE) { + isHeating = false; + return HEATER_DONT_CARE; + } + + if (temperature > parameters.upperOpLimit - parameters.heaterSwitchoff) { + isHeating = false; + return HEATER_REQUEST_EMERGENCY_OFF; + } + + float opHeaterLimit = parameters.lowerOpLimit + parameters.heaterOn; + + if (isHeating) { + opHeaterLimit += parameters.hysteresis; + } + + if (temperature < opHeaterLimit) { + isHeating = true; + return HEATER_REQUEST_EMERGENCY_ON; + } + isHeating = false; + return HEATER_DONT_CARE; +} + +ThermalComponentIF::State CoreComponent::getIgnoredState(int8_t state) { + switch (state) { + case NON_OPERATIONAL_LOW: + return NON_OPERATIONAL_LOW_IGNORED; + case OPERATIONAL: + return OPERATIONAL_IGNORED; + case NON_OPERATIONAL_HIGH: + return NON_OPERATIONAL_HIGH_IGNORED; + case NON_OPERATIONAL_LOW_IGNORED: + return NON_OPERATIONAL_LOW_IGNORED; + case OPERATIONAL_IGNORED: + return OPERATIONAL_IGNORED; + case NON_OPERATIONAL_HIGH_IGNORED: + return NON_OPERATIONAL_HIGH_IGNORED; + default: + case UNKNOWN: + return UNKNOWN; + } +} + +void CoreComponent::updateMinMaxTemp() { + if (temperature == INVALID_TEMPERATURE) { + return; + } + if (temperature < minTemp) { + minTemp = temperature; + } + if (temperature > maxTemp) { + maxTemp = temperature; + } +} + +uint8_t CoreComponent::getDomainId() const { + return domainId; +} + +CoreComponent::Parameters CoreComponent::getParameters() { + return parameters; +} + +ReturnValue_t CoreComponent::getParameter(uint8_t domainId, + uint16_t parameterId, ParameterWrapper* parameterWrapper, + const ParameterWrapper* newValues, uint16_t startAtIndex) { + ReturnValue_t result = temperatureMonitor.getParameter(domainId, + parameterId, parameterWrapper, newValues, startAtIndex); + if (result != INVALID_DOMAIN_ID) { + return result; + } + if (domainId != this->domainId) { + return INVALID_DOMAIN_ID; + } + switch (parameterId) { + case 0: + parameterWrapper->set(parameters.heaterOn); + break; + case 1: + parameterWrapper->set(parameters.hysteresis); + break; + case 2: + parameterWrapper->set(parameters.heaterSwitchoff); + break; + case 3: + parameterWrapper->set(minTemp); + break; + case 4: + parameterWrapper->set(maxTemp); + break; + case 10: + parameterWrapper->set(parameters.lowerOpLimit); + break; + case 11: + parameterWrapper->set(parameters.upperOpLimit); + break; + default: + return INVALID_MATRIX_ID; + } + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/thermal/CoreComponent.h b/thermal/CoreComponent.h new file mode 100644 index 00000000..f7e7aff8 --- /dev/null +++ b/thermal/CoreComponent.h @@ -0,0 +1,95 @@ +#ifndef MISSION_CONTROLLERS_TCS_CORECOMPONENT_H_ +#define MISSION_CONTROLLERS_TCS_CORECOMPONENT_H_ + +#include +#include +#include +#include +#include +#include + +class CoreComponent: public ThermalComponentIF { +public: + struct Parameters { + float lowerOpLimit; + float upperOpLimit; + float heaterOn; + float hysteresis; + float heaterSwitchoff; + }; + + static const uint16_t COMPONENT_TEMP_CONFIRMATION = 5; + + CoreComponent(object_id_t reportingObjectId, uint8_t domainId, uint32_t temperaturePoolId, + uint32_t targetStatePoolId, uint32_t currentStatePoolId, + uint32_t requestPoolId, DataSet *dataSet, + AbstractTemperatureSensor *sensor, + AbstractTemperatureSensor *firstRedundantSensor, + AbstractTemperatureSensor *secondRedundantSensor, + ThermalModuleIF *thermalModule, Parameters parameters, + Priority priority, StateRequest initialTargetState = + ThermalComponentIF::STATE_REQUEST_OPERATIONAL); + + virtual ~CoreComponent(); + + virtual HeaterRequest performOperation(uint8_t opCode); + + void markStateIgnored(); + + object_id_t getObjectId(); + + uint8_t getDomainId() const; + + virtual float getLowerOpLimit(); + + ReturnValue_t setTargetState(int8_t newState); + + virtual void setOutputInvalid(); + + virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, + ParameterWrapper *parameterWrapper, + const ParameterWrapper *newValues, uint16_t startAtIndex); + +protected: + + AbstractTemperatureSensor *sensor; + AbstractTemperatureSensor *firstRedundantSensor; + AbstractTemperatureSensor *secondRedundantSensor; + ThermalModuleIF *thermalModule; + + db_float_t temperature; + db_int8_t targetState; + db_int8_t currentState; + db_uint8_t heaterRequest; + + bool isHeating; + + bool isSafeComponent; + + float minTemp; + + float maxTemp; + + Parameters parameters; + + ThermalMonitor temperatureMonitor; + + const uint8_t domainId; + + virtual float getTemperature(); + virtual State getState(float temperature, Parameters parameters, + int8_t targetState); + + virtual void checkLimits(State state); + + virtual HeaterRequest getHeaterRequest(int8_t targetState, + float temperature, Parameters parameters); + + virtual State getIgnoredState(int8_t state); + + void updateMinMaxTemp(); + + virtual Parameters getParameters(); +}; + +#endif /* MISSION_CONTROLLERS_TCS_CORECOMPONENT_H_ */ diff --git a/thermal/Heater.cpp b/thermal/Heater.cpp new file mode 100644 index 00000000..29daa15d --- /dev/null +++ b/thermal/Heater.cpp @@ -0,0 +1,350 @@ +#include +#include "Heater.h" + +#include +#include + +Heater::Heater(uint32_t objectId, uint8_t switch0, uint8_t switch1) : + HealthDevice(objectId, 0), internalState(STATE_OFF), powerSwitcher( + NULL), pcduQueueId(0), switch0(switch0), switch1(switch1), wasOn( + false), timedOut(false), reactedToBeingFaulty(false), passive( + false), eventQueue(NULL), heaterOnCountdown(10800000)/*about two orbits*/, parameterHelper( + this), lastAction(CLEAR) { + eventQueue = QueueFactory::instance()->createMessageQueue(); +} + +Heater::~Heater() { + QueueFactory::instance()->deleteMessageQueue(eventQueue); +} + +ReturnValue_t Heater::set() { + passive = false; + //wait for clear before doing anything + if (internalState == STATE_WAIT) { + return HasReturnvaluesIF::RETURN_OK; + } + if (healthHelper.healthTable->isHealthy(getObjectId())) { + doAction(SET); + if ((internalState == STATE_OFF) || (internalState == STATE_PASSIVE)){ + return HasReturnvaluesIF::RETURN_FAILED; + } else { + return HasReturnvaluesIF::RETURN_OK; + } + } else { + if (healthHelper.healthTable->isFaulty(getObjectId())) { + if (!reactedToBeingFaulty) { + reactedToBeingFaulty = true; + doAction(CLEAR); + } + } + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +void Heater::clear(bool passive) { + this->passive = passive; + //Force switching off + if (internalState == STATE_WAIT) { + internalState = STATE_ON; + } + if (healthHelper.healthTable->isHealthy(getObjectId())) { + doAction(CLEAR); + } else if (healthHelper.healthTable->isFaulty(getObjectId())) { + if (!reactedToBeingFaulty) { + reactedToBeingFaulty = true; + doAction(CLEAR); + } + } +} + +void Heater::doAction(Action action) { + //only act if we are not in the right state or in a transition + if (action == SET) { + if ((internalState == STATE_OFF) || (internalState == STATE_PASSIVE) + || (internalState == STATE_EXTERNAL_CONTROL)) { + switchCountdown.setTimeout(powerSwitcher->getSwitchDelayMs()); + internalState = STATE_WAIT_FOR_SWITCHES_ON; + powerSwitcher->sendSwitchCommand(switch0, PowerSwitchIF::SWITCH_ON); + powerSwitcher->sendSwitchCommand(switch1, PowerSwitchIF::SWITCH_ON); + } + } else { //clear + if ((internalState == STATE_ON) || (internalState == STATE_FAULTY) + || (internalState == STATE_EXTERNAL_CONTROL)) { + internalState = STATE_WAIT_FOR_SWITCHES_OFF; + switchCountdown.setTimeout(powerSwitcher->getSwitchDelayMs()); + powerSwitcher->sendSwitchCommand(switch0, + PowerSwitchIF::SWITCH_OFF); + powerSwitcher->sendSwitchCommand(switch1, + PowerSwitchIF::SWITCH_OFF); + } + } +} + +void Heater::setPowerSwitcher(PowerSwitchIF* powerSwitch) { + this->powerSwitcher = powerSwitch; +} + +ReturnValue_t Heater::performOperation(uint8_t opCode) { + handleQueue(); + handleEventQueue(); + + if (!healthHelper.healthTable->isFaulty(getObjectId())) { + reactedToBeingFaulty = false; + } + + switch (internalState) { + case STATE_ON: + if ((powerSwitcher->getSwitchState(switch0) == PowerSwitchIF::SWITCH_OFF) + || (powerSwitcher->getSwitchState(switch1) + == PowerSwitchIF::SWITCH_OFF)) { + //switch went off on its own + //trigger event. FDIR can confirm if it is caused by MniOps and decide on the action + //do not trigger FD events when under external control + if (healthHelper.getHealth() != EXTERNAL_CONTROL) { + triggerEvent(PowerSwitchIF::SWITCH_WENT_OFF); + } else { + internalState = STATE_EXTERNAL_CONTROL; + } + } + break; + case STATE_OFF: + //check if heater is on, ie both switches are on + //if so, just command it to off, to resolve the situation or force a switch stayed on event + //But, only do anything if not already faulty (state off is the stable point for being faulty) + if ((!healthHelper.healthTable->isFaulty(getObjectId())) + && (powerSwitcher->getSwitchState(switch0) + == PowerSwitchIF::SWITCH_ON) + && (powerSwitcher->getSwitchState(switch1) + == PowerSwitchIF::SWITCH_ON)) { + //do not trigger FD events when under external control + if (healthHelper.getHealth() != EXTERNAL_CONTROL) { + internalState = STATE_WAIT_FOR_SWITCHES_OFF; + switchCountdown.setTimeout(powerSwitcher->getSwitchDelayMs()); + powerSwitcher->sendSwitchCommand(switch0, + PowerSwitchIF::SWITCH_OFF); + powerSwitcher->sendSwitchCommand(switch1, + PowerSwitchIF::SWITCH_OFF); + } else { + internalState = STATE_EXTERNAL_CONTROL; + } + } + break; + case STATE_PASSIVE: + break; + case STATE_WAIT_FOR_SWITCHES_ON: + if (switchCountdown.hasTimedOut()) { + if ((powerSwitcher->getSwitchState(switch0) + == PowerSwitchIF::SWITCH_OFF) + || (powerSwitcher->getSwitchState(switch1) + == PowerSwitchIF::SWITCH_OFF)) { + triggerEvent(HEATER_STAYED_OFF); + internalState = STATE_WAIT_FOR_FDIR; //wait before retrying or anything + } else { + triggerEvent(HEATER_ON); + internalState = STATE_ON; + } + } + break; + case STATE_WAIT_FOR_SWITCHES_OFF: + if (switchCountdown.hasTimedOut()) { + //only check for both being on (ie heater still on) + if ((powerSwitcher->getSwitchState(switch0) + == PowerSwitchIF::SWITCH_ON) + && (powerSwitcher->getSwitchState(switch1) + == PowerSwitchIF::SWITCH_ON)) { + if (healthHelper.healthTable->isFaulty(getObjectId())) { + if (passive) { + internalState = STATE_PASSIVE; + } else { + internalState = STATE_OFF; //just accept it + } + triggerEvent(HEATER_ON); //but throw an event to make it more visible + break; + } + triggerEvent(HEATER_STAYED_ON); + internalState = STATE_WAIT_FOR_FDIR; //wait before retrying or anything + } else { + triggerEvent(HEATER_OFF); + if (passive) { + internalState = STATE_PASSIVE; + } else { + internalState = STATE_OFF; + } + } + } + break; + default: + break; + } + + if ((powerSwitcher->getSwitchState(switch0) == PowerSwitchIF::SWITCH_ON) + && (powerSwitcher->getSwitchState(switch1) + == PowerSwitchIF::SWITCH_ON)) { + if (wasOn) { + if (heaterOnCountdown.hasTimedOut()) { + //SHOULDDO this means if a heater fails in single mode, the timeout will start again + //I am not sure if this is a bug, but atm I have no idea how to fix this and think + //it will be ok. whatcouldpossiblygowrong™ + if (!timedOut) { + triggerEvent(HEATER_TIMEOUT); + timedOut = true; + } + } + } else { + wasOn = true; + heaterOnCountdown.resetTimer(); + timedOut = false; + } + } else { + wasOn = false; + } + + return HasReturnvaluesIF::RETURN_OK; +} + +void Heater::setSwitch(uint8_t number, ReturnValue_t state, + uint32_t* uptimeOfSwitching) { + if (powerSwitcher == NULL) { + return; + } + if (powerSwitcher->getSwitchState(number) == state) { + *uptimeOfSwitching = INVALID_UPTIME; + } else { + if ((*uptimeOfSwitching == INVALID_UPTIME)) { + powerSwitcher->sendSwitchCommand(number, state); + Clock::getUptime(uptimeOfSwitching); + } else { + uint32_t currentUptime; + Clock::getUptime(¤tUptime); + if (currentUptime - *uptimeOfSwitching + > powerSwitcher->getSwitchDelayMs()) { + *uptimeOfSwitching = INVALID_UPTIME; + if (healthHelper.healthTable->isHealthy(getObjectId())) { + if (state == PowerSwitchIF::SWITCH_ON) { + triggerEvent(HEATER_STAYED_OFF); + } else { + triggerEvent(HEATER_STAYED_ON); + } + } + //SHOULDDO MiniOps during switch timeout leads to a faulty switch + } + } + } +} + +MessageQueueId_t Heater::getCommandQueue() const { + return commandQueue->getId(); +} + +ReturnValue_t Heater::initialize() { + ReturnValue_t result = SystemObject::initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + EventManagerIF* manager = objectManager->get( + objects::EVENT_MANAGER); + if (manager == NULL) { + return HasReturnvaluesIF::RETURN_FAILED; + } + result = manager->registerListener(eventQueue->getId()); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + ConfirmsFailuresIF* pcdu = objectManager->get( + DeviceHandlerFailureIsolation::powerConfirmationId); + if (pcdu == NULL) { + return HasReturnvaluesIF::RETURN_FAILED; + } + pcduQueueId = pcdu->getEventReceptionQueue(); + + result = manager->subscribeToAllEventsFrom(eventQueue->getId(), + getObjectId()); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + result = parameterHelper.initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + result = healthHelper.initialize(); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + + return HasReturnvaluesIF::RETURN_OK; +} + +void Heater::handleQueue() { + CommandMessage message; + ReturnValue_t result = commandQueue->receiveMessage(&message); + if (result == HasReturnvaluesIF::RETURN_OK) { + result = healthHelper.handleHealthCommand(&message); + if (result == HasReturnvaluesIF::RETURN_OK) { + return; + } + parameterHelper.handleParameterMessage(&message); + } +} + +ReturnValue_t Heater::getParameter(uint8_t domainId, uint16_t parameterId, + ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues, + uint16_t startAtIndex) { + if (domainId != DOMAIN_ID_BASE) { + return INVALID_DOMAIN_ID; + } + switch (parameterId) { + case 0: + parameterWrapper->set(heaterOnCountdown.timeout); + break; + default: + return INVALID_MATRIX_ID; + } + return HasReturnvaluesIF::RETURN_OK; +} + +void Heater::handleEventQueue() { + EventMessage event; + for (ReturnValue_t result = eventQueue->receiveMessage(&event); + result == HasReturnvaluesIF::RETURN_OK; + result = eventQueue->receiveMessage(&event)) { + switch (event.getMessageId()) { + case EventMessage::EVENT_MESSAGE: + switch (event.getEvent()) { + case Fuse::FUSE_WENT_OFF: + case HEATER_STAYED_OFF: + case HEATER_STAYED_ON://Setting it faulty does not help, but we need to reach a stable state and can check for being faulty before throwing this event again. + if (healthHelper.healthTable->isCommandable(getObjectId())) { + healthHelper.setHealth(HasHealthIF::FAULTY); + internalState = STATE_FAULTY; + } + break; + case PowerSwitchIF::SWITCH_WENT_OFF: + internalState = STATE_WAIT; + event.setMessageId(EventMessage::CONFIRMATION_REQUEST); + if (pcduQueueId != 0) { + eventQueue->sendMessage(pcduQueueId, &event); + } else { + healthHelper.setHealth(HasHealthIF::FAULTY); + internalState = STATE_FAULTY; + } + break; + default: + return; + } + break; + case EventMessage::YOUR_FAULT: + healthHelper.setHealth(HasHealthIF::FAULTY); + internalState = STATE_FAULTY; + break; + case EventMessage::MY_FAULT: + //do nothing, we are already in STATE_WAIT and wait for a clear() + break; + default: + return; + } + } +} diff --git a/thermal/Heater.h b/thermal/Heater.h new file mode 100644 index 00000000..41004e03 --- /dev/null +++ b/thermal/Heater.h @@ -0,0 +1,90 @@ +#ifndef FRAMEWORK_THERMAL_HEATER_H_ +#define FRAMEWORK_THERMAL_HEATER_H_ + +#include +#include +#include +#include +#include +#include +//class RedundantHeater; + +class Heater: public HealthDevice, public ReceivesParameterMessagesIF { + friend class RedundantHeater; +public: + + static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::HEATER; + static const Event HEATER_ON = MAKE_EVENT(0, SEVERITY::INFO); + static const Event HEATER_OFF = MAKE_EVENT(1, SEVERITY::INFO); + static const Event HEATER_TIMEOUT = MAKE_EVENT(2, SEVERITY::LOW); + static const Event HEATER_STAYED_ON = MAKE_EVENT(3, SEVERITY::LOW); + static const Event HEATER_STAYED_OFF = MAKE_EVENT(4, SEVERITY::LOW); + + Heater(uint32_t objectId, uint8_t switch0, uint8_t switch1); + virtual ~Heater(); + + ReturnValue_t performOperation(uint8_t opCode); + + ReturnValue_t initialize(); + + ReturnValue_t set(); + void clear(bool passive); + + void setPowerSwitcher(PowerSwitchIF *powerSwitch); + + MessageQueueId_t getCommandQueue() const; + + ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, + ParameterWrapper *parameterWrapper, + const ParameterWrapper *newValues, uint16_t startAtIndex); + +protected: + static const uint32_t INVALID_UPTIME = 0; + + enum InternalState { + STATE_ON, + STATE_OFF, + STATE_PASSIVE, + STATE_WAIT_FOR_SWITCHES_ON, + STATE_WAIT_FOR_SWITCHES_OFF, + STATE_WAIT_FOR_FDIR, //used to avoid doing anything until fdir decided what to do + STATE_FAULTY, + STATE_WAIT, //used when waiting for system to recover from miniops + STATE_EXTERNAL_CONTROL //entered when under external control and a fdir reaction would be triggered. This is useful when leaving external control into an unknown state + //if no fdir reaction is triggered under external control the state is still ok and no need for any special treatment is needed + } internalState; + + PowerSwitchIF *powerSwitcher; + MessageQueueId_t pcduQueueId; + + uint8_t switch0; + uint8_t switch1; + + bool wasOn; + + bool timedOut; + + bool reactedToBeingFaulty; + + bool passive; + + MessageQueueIF* eventQueue; + Countdown heaterOnCountdown; + Countdown switchCountdown; + ParameterHelper parameterHelper; + + enum Action { + SET, CLEAR + } lastAction; + + void doAction(Action action); + + void setSwitch(uint8_t number, ReturnValue_t state, + uint32_t *upTimeOfSwitching); + + void handleQueue(); + + void handleEventQueue(); +}; + +#endif /* FRAMEWORK_THERMAL_HEATER_H_ */ diff --git a/thermal/RedundantHeater.cpp b/thermal/RedundantHeater.cpp new file mode 100644 index 00000000..6463fcc8 --- /dev/null +++ b/thermal/RedundantHeater.cpp @@ -0,0 +1,40 @@ +#include "RedundantHeater.h" + +RedundantHeater::~RedundantHeater() { +} + +RedundantHeater::RedundantHeater(Parameters parameters) : + heater0(parameters.objectIdHeater0, parameters.switch0Heater0, + parameters.switch1Heater0), heater1(parameters.objectIdHeater1, + parameters.switch0Heater1, parameters.switch1Heater1) { +} + +void RedundantHeater::performOperation(uint8_t opCode) { + heater0.performOperation(0); + heater1.performOperation(0); +} + +void RedundantHeater::set(bool on, bool both, bool passive) { + if (on) { + ReturnValue_t result = heater0.set(); + if (result != HasReturnvaluesIF::RETURN_OK || both) { + heater1.set(); + } else { + heater1.clear(passive); + } + } else { + heater0.clear(passive); + heater1.clear(passive); + } + +} + +void RedundantHeater::triggerHeaterEvent(Event event) { + heater0.triggerEvent(event); + heater1.triggerEvent(event); +} + +void RedundantHeater::setPowerSwitcher(PowerSwitchIF* powerSwitch) { + heater0.setPowerSwitcher(powerSwitch); + heater1.setPowerSwitcher(powerSwitch); +} diff --git a/thermal/RedundantHeater.h b/thermal/RedundantHeater.h new file mode 100644 index 00000000..29791a9a --- /dev/null +++ b/thermal/RedundantHeater.h @@ -0,0 +1,51 @@ +#ifndef REDUNDANTHEATER_H_ +#define REDUNDANTHEATER_H_ + +#include + +class RedundantHeater { +public: + + struct Parameters { + Parameters(uint32_t objectIdHeater0, uint32_t objectIdHeater1, + uint8_t switch0Heater0, uint8_t switch1Heater0, + uint8_t switch0Heater1, uint8_t switch1Heater1) : + objectIdHeater0(objectIdHeater0), objectIdHeater1( + objectIdHeater1), switch0Heater0(switch0Heater0), switch1Heater0( + switch1Heater0), switch0Heater1(switch0Heater1), switch1Heater1( + switch1Heater1) { + } + + Parameters() : + objectIdHeater0(0), objectIdHeater1(0), switch0Heater0(0), switch1Heater0( + 0), switch0Heater1(0), switch1Heater1(0) { + } + + uint32_t objectIdHeater0; + uint32_t objectIdHeater1; + uint8_t switch0Heater0; + uint8_t switch1Heater0; + uint8_t switch0Heater1; + uint8_t switch1Heater1; + }; + + RedundantHeater(Parameters parameters); + virtual ~RedundantHeater(); + + void performOperation(uint8_t opCode); + + void triggerHeaterEvent(Event event); + + void set(bool on, bool both, bool passive = false); + + void setPowerSwitcher(PowerSwitchIF *powerSwitch); + +protected: + + Heater heater0; + Heater heater1; + +}; + +#endif /* REDUNDANTHEATER_H_ */ + diff --git a/thermal/TemperatureSensor.h b/thermal/TemperatureSensor.h new file mode 100644 index 00000000..de280d87 --- /dev/null +++ b/thermal/TemperatureSensor.h @@ -0,0 +1,174 @@ +#ifndef TEMPERATURESENSOR_H_ +#define TEMPERATURESENSOR_H_ + +#include +#include "AbstractTemperatureSensor.h" +#include + +template +class TemperatureSensor: public AbstractTemperatureSensor { +public: + struct Parameters { + float a; + float b; + float c; + T lowerLimit; + T upperLimit; + float gradient; + }; + struct UsedParameters { + UsedParameters(Parameters parameters) : + a(parameters.a), b(parameters.b), c(parameters.c), gradient( + parameters.gradient) { + } + float a; + float b; + float c; + float gradient; + }; + + static const uint16_t ADDRESS_A = 0; + static const uint16_t ADDRESS_B = 1; + static const uint16_t ADDRESS_C = 2; + static const uint16_t ADDRESS_GRADIENT = 3; + + static const uint16_t DEFAULT_CONFIRMATION_COUNT = 1; //!< Changed due to issue with later temperature checking even tough the sensor monitor was confirming already (Was 10 before with comment = Correlates to a 10s confirmation time. Chosen rather large, should not be so bad for components and helps survive glitches.) + + static const uint8_t DOMAIN_ID_SENSOR = 1; +private: + void setInvalid() { + outputTemperature = INVALID_TEMPERATURE; + outputTemperature.setValid(false); + uptimeOfOldTemperature.tv_sec = INVALID_UPTIME; + sensorMonitor.setToInvalid(); + } +protected: + static const int32_t INVALID_UPTIME = 0; + + UsedParameters parameters; + + T *inputTemperature; + + PoolVariableIF *poolVariable; + + PoolVariable outputTemperature; + + LimitMonitor sensorMonitor; + + float oldTemperature; + timeval uptimeOfOldTemperature; + + virtual float calculateOutputTemperature(T inputTemperature) { + return parameters.a * inputTemperature * inputTemperature + + parameters.b * inputTemperature + parameters.c; + } + + void doChildOperation() { + if (!poolVariable->isValid() + || !healthHelper.healthTable->isHealthy(getObjectId())) { + setInvalid(); + return; + } + + outputTemperature = calculateOutputTemperature(*inputTemperature); + outputTemperature.setValid(PoolVariableIF::VALID); + + timeval uptime; + Clock::getUptime(&uptime); + + if (uptimeOfOldTemperature.tv_sec != INVALID_UPTIME) { + //In theory, we could use an AbsValueMonitor to monitor the gradient. + //But this would require storing the gradient in DP and quite some overhead. + //The concept of delta limits is a bit strange anyway. + float deltaTime; + float deltaTemp; + + deltaTime = (uptime.tv_sec + uptime.tv_usec / 1000000.) + - (uptimeOfOldTemperature.tv_sec + + uptimeOfOldTemperature.tv_usec / 1000000.); + deltaTemp = oldTemperature - outputTemperature; + if (deltaTemp < 0) { + deltaTemp = -deltaTemp; + } + if (parameters.gradient < deltaTemp / deltaTime) { + triggerEvent(TEMP_SENSOR_GRADIENT); + //Don't set invalid, as we did not recognize it as invalid with full authority, let FDIR handle it + } + } + + //Check is done against raw limits. SHOULDDO: Why? Using °C would be more easy to handle. + sensorMonitor.doCheck(*inputTemperature); + + if (sensorMonitor.isOutOfLimits()) { + uptimeOfOldTemperature.tv_sec = INVALID_UPTIME; + outputTemperature.setValid(PoolVariableIF::INVALID); + outputTemperature = INVALID_TEMPERATURE; + } else { + oldTemperature = outputTemperature; + uptimeOfOldTemperature = uptime; + } + } + +public: + TemperatureSensor(object_id_t setObjectid, + T *inputTemperature, PoolVariableIF *poolVariable, + uint8_t vectorIndex, Parameters parameters, uint32_t datapoolId, + DataSet *outputSet, ThermalModuleIF *thermalModule) : + AbstractTemperatureSensor(setObjectid, thermalModule), parameters( + parameters), inputTemperature(inputTemperature), poolVariable( + poolVariable), outputTemperature(datapoolId, outputSet, + PoolVariableIF::VAR_WRITE), sensorMonitor(setObjectid, + DOMAIN_ID_SENSOR, + DataPool::poolIdAndPositionToPid( + poolVariable->getDataPoolId(), vectorIndex), + DEFAULT_CONFIRMATION_COUNT, parameters.lowerLimit, + parameters.upperLimit, TEMP_SENSOR_LOW, TEMP_SENSOR_HIGH), oldTemperature( + 20), uptimeOfOldTemperature( { INVALID_TEMPERATURE, 0 }) { + + } + + float getTemperature() { + return outputTemperature; + } + + bool isValid() { + return outputTemperature.isValid(); + } + + virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, + ParameterWrapper *parameterWrapper, + const ParameterWrapper *newValues, uint16_t startAtIndex) { + ReturnValue_t result = sensorMonitor.getParameter(domainId, parameterId, + parameterWrapper, newValues, startAtIndex); + if (result != INVALID_DOMAIN_ID) { + return result; + } + if (domainId != this->DOMAIN_ID_BASE) { + return INVALID_DOMAIN_ID; + } + switch (parameterId) { + case ADDRESS_A: + parameterWrapper->set(parameters.a); + break; + case ADDRESS_B: + parameterWrapper->set(parameters.b); + break; + case ADDRESS_C: + parameterWrapper->set(parameters.c); + break; + case ADDRESS_GRADIENT: + parameterWrapper->set(parameters.gradient); + break; + default: + return INVALID_MATRIX_ID; + } + return HasReturnvaluesIF::RETURN_OK; + } + + virtual void resetOldState() { + sensorMonitor.setToUnchecked(); + } + +}; + +#endif /* TEMPERATURESENSOR_H_ */ diff --git a/thermal/ThermalComponent.cpp b/thermal/ThermalComponent.cpp new file mode 100644 index 00000000..bf6f7398 --- /dev/null +++ b/thermal/ThermalComponent.cpp @@ -0,0 +1,170 @@ +#include "ThermalComponent.h" + +ThermalComponent::ThermalComponent(object_id_t reportingObjectId, + uint8_t domainId, uint32_t temperaturePoolId, + uint32_t targetStatePoolId, uint32_t currentStatePoolId, + uint32_t requestPoolId, DataSet* dataSet, + AbstractTemperatureSensor* sensor, + AbstractTemperatureSensor* firstRedundantSensor, + AbstractTemperatureSensor* secondRedundantSensor, + ThermalModuleIF* thermalModule, Parameters parameters, + Priority priority) : + CoreComponent(reportingObjectId, domainId, temperaturePoolId, + targetStatePoolId, currentStatePoolId, requestPoolId, dataSet, + sensor, firstRedundantSensor, secondRedundantSensor, + thermalModule, + { parameters.lowerOpLimit, parameters.upperOpLimit, + parameters.heaterOn, parameters.hysteresis, + parameters.heaterSwitchoff }, priority, + ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL), nopParameters( + { parameters.lowerNopLimit, parameters.upperNopLimit }) { +} + +ThermalComponent::~ThermalComponent() { +} + +ReturnValue_t ThermalComponent::setTargetState(int8_t newState) { + DataSet mySet; + PoolVariable writableTargetState(targetState.getDataPoolId(), + &mySet, PoolVariableIF::VAR_READ_WRITE); + mySet.read(); + if ((writableTargetState == STATE_REQUEST_OPERATIONAL) + && (newState != STATE_REQUEST_IGNORE)) { + return HasReturnvaluesIF::RETURN_FAILED; + } + switch (newState) { + case STATE_REQUEST_NON_OPERATIONAL: + writableTargetState = newState; + mySet.commit(PoolVariableIF::VALID); + return HasReturnvaluesIF::RETURN_OK; + default: + return CoreComponent::setTargetState(newState); + } +} + +ReturnValue_t ThermalComponent::setLimits(const uint8_t* data, uint32_t size) { + if (size != 4 * sizeof(parameters.lowerOpLimit)) { + return MonitoringIF::INVALID_SIZE; + } + int32_t readSize = size; + SerializeAdapter::deSerialize(&nopParameters.lowerNopLimit, &data, + &readSize, true); + SerializeAdapter::deSerialize(¶meters.lowerOpLimit, &data, + &readSize, true); + SerializeAdapter::deSerialize(¶meters.upperOpLimit, &data, + &readSize, true); + SerializeAdapter::deSerialize(&nopParameters.upperNopLimit, &data, + &readSize, true); + return HasReturnvaluesIF::RETURN_OK; +} + +ThermalComponentIF::State ThermalComponent::getState(float temperature, + CoreComponent::Parameters parameters, int8_t targetState) { + if (temperature < nopParameters.lowerNopLimit) { + return OUT_OF_RANGE_LOW; + } else { + State state = CoreComponent::getState(temperature, parameters, + targetState); + if (state != NON_OPERATIONAL_HIGH + && state != NON_OPERATIONAL_HIGH_IGNORED) { + return state; + } + if (temperature > nopParameters.upperNopLimit) { + state = OUT_OF_RANGE_HIGH; + } + if (targetState == STATE_REQUEST_IGNORE) { + state = getIgnoredState(state); + } + return state; + } +} + +void ThermalComponent::checkLimits(ThermalComponentIF::State state) { + if (targetState == STATE_REQUEST_OPERATIONAL || targetState == STATE_REQUEST_IGNORE) { + CoreComponent::checkLimits(state); + return; + } + //If component is not operational, it checks the NOP limits. + temperatureMonitor.translateState(state, temperature.value, + nopParameters.lowerNopLimit, nopParameters.upperNopLimit, false); +} + +ThermalComponentIF::HeaterRequest ThermalComponent::getHeaterRequest( + int8_t targetState, float temperature, + CoreComponent::Parameters parameters) { + if (targetState == STATE_REQUEST_IGNORE) { + isHeating = false; + return HEATER_DONT_CARE; + } + + if (temperature + > nopParameters.upperNopLimit - parameters.heaterSwitchoff) { + isHeating = false; + return HEATER_REQUEST_EMERGENCY_OFF; + } + + float nopHeaterLimit = nopParameters.lowerNopLimit + parameters.heaterOn; + float opHeaterLimit = parameters.lowerOpLimit + parameters.heaterOn; + + if (isHeating) { + nopHeaterLimit += parameters.hysteresis; + opHeaterLimit += parameters.hysteresis; + } + + if (temperature < nopHeaterLimit) { + isHeating = true; + return HEATER_REQUEST_EMERGENCY_ON; + } + + if ((targetState == STATE_REQUEST_OPERATIONAL) + || (targetState == STATE_REQUEST_HEATING)) { + if (temperature < opHeaterLimit) { + isHeating = true; + return HEATER_REQUEST_ON; + } + if (temperature + > parameters.upperOpLimit - parameters.heaterSwitchoff) { + isHeating = false; + return HEATER_REQUEST_OFF; + } + } + + isHeating = false; + return HEATER_DONT_CARE; +} + +ThermalComponentIF::State ThermalComponent::getIgnoredState(int8_t state) { + switch (state) { + case OUT_OF_RANGE_LOW: + return OUT_OF_RANGE_LOW_IGNORED; + case OUT_OF_RANGE_HIGH: + return OUT_OF_RANGE_HIGH_IGNORED; + case OUT_OF_RANGE_LOW_IGNORED: + return OUT_OF_RANGE_LOW_IGNORED; + case OUT_OF_RANGE_HIGH_IGNORED: + return OUT_OF_RANGE_HIGH_IGNORED; + default: + return CoreComponent::getIgnoredState(state); + } +} + +ReturnValue_t ThermalComponent::getParameter(uint8_t domainId, + uint16_t parameterId, ParameterWrapper* parameterWrapper, + const ParameterWrapper* newValues, uint16_t startAtIndex) { + ReturnValue_t result = CoreComponent::getParameter(domainId, parameterId, + parameterWrapper, newValues, startAtIndex); + if (result != INVALID_MATRIX_ID) { + return result; + } + switch (parameterId) { + case 12: + parameterWrapper->set(nopParameters.lowerNopLimit); + break; + case 13: + parameterWrapper->set(nopParameters.upperNopLimit); + break; + default: + return INVALID_MATRIX_ID; + } + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/thermal/ThermalComponent.h b/thermal/ThermalComponent.h new file mode 100644 index 00000000..93243868 --- /dev/null +++ b/thermal/ThermalComponent.h @@ -0,0 +1,53 @@ +#ifndef THERMALCOMPONENT_H_ +#define THERMALCOMPONENT_H_ + +#include "CoreComponent.h" + +class ThermalComponent: public CoreComponent { +public: + struct Parameters { + float lowerNopLimit; + float lowerOpLimit; + float upperOpLimit; + float upperNopLimit; + float heaterOn; + float hysteresis; + float heaterSwitchoff; + }; + struct NopParameters { + float lowerNopLimit; + float upperNopLimit; + }; + ThermalComponent(object_id_t reportingObjectId, uint8_t domainId, uint32_t temperaturePoolId, + uint32_t targetStatePoolId, uint32_t currentStatePoolId, uint32_t requestPoolId, + DataSet *dataSet, AbstractTemperatureSensor *sensor, + AbstractTemperatureSensor *firstRedundantSensor, + AbstractTemperatureSensor *secondRedundantSensor, + ThermalModuleIF *thermalModule, Parameters parameters, + Priority priority); + virtual ~ThermalComponent(); + + ReturnValue_t setTargetState(int8_t newState); + + virtual ReturnValue_t setLimits( const uint8_t* data, uint32_t size); + + virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId, + ParameterWrapper *parameterWrapper, + const ParameterWrapper *newValues, uint16_t startAtIndex); + +protected: + + NopParameters nopParameters; + + State getState(float temperature, CoreComponent::Parameters parameters, + int8_t targetState); + + virtual void checkLimits(State state); + + virtual HeaterRequest getHeaterRequest(int8_t targetState, float temperature, + CoreComponent::Parameters parameters); + + State getIgnoredState(int8_t state); +}; + +#endif /* THERMALCOMPONENT_H_ */ diff --git a/thermal/ThermalComponentIF.h b/thermal/ThermalComponentIF.h new file mode 100644 index 00000000..ad8dbd0a --- /dev/null +++ b/thermal/ThermalComponentIF.h @@ -0,0 +1,114 @@ +#ifndef THERMALCOMPONENTIF_H_ +#define THERMALCOMPONENTIF_H_ + +#include +#include +#include +#include + +class ThermalComponentIF : public HasParametersIF { +public: + + static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::TCS_1; + static const Event COMPONENT_TEMP_LOW = MAKE_EVENT(1, SEVERITY::LOW); + static const Event COMPONENT_TEMP_HIGH = MAKE_EVENT(2, SEVERITY::LOW); + static const Event COMPONENT_TEMP_OOL_LOW = MAKE_EVENT(3, SEVERITY::LOW); + static const Event COMPONENT_TEMP_OOL_HIGH = MAKE_EVENT(4, SEVERITY::LOW); + static const Event TEMP_NOT_IN_OP_RANGE = MAKE_EVENT(5, SEVERITY::LOW); //!< Is thrown when a device should start-up, but the temperature is out of OP range. P1: thermalState of the component, P2: 0 + + static const uint8_t INTERFACE_ID = CLASS_ID::THERMAL_COMPONENT_IF; + static const ReturnValue_t INVALID_TARGET_STATE = MAKE_RETURN_CODE(1); + static const ReturnValue_t ABOVE_OPERATIONAL_LIMIT = MAKE_RETURN_CODE(0xF1); + static const ReturnValue_t BELOW_OPERATIONAL_LIMIT = MAKE_RETURN_CODE(0xF2); + + enum State { + OUT_OF_RANGE_LOW = -2, + NON_OPERATIONAL_LOW = -1, + OPERATIONAL = 0, + NON_OPERATIONAL_HIGH = 1, + OUT_OF_RANGE_HIGH = 2, + OUT_OF_RANGE_LOW_IGNORED = OUT_OF_RANGE_LOW - 10, + NON_OPERATIONAL_LOW_IGNORED = NON_OPERATIONAL_LOW - 10, + OPERATIONAL_IGNORED = OPERATIONAL + 10, + NON_OPERATIONAL_HIGH_IGNORED = NON_OPERATIONAL_HIGH + 10, + OUT_OF_RANGE_HIGH_IGNORED = OUT_OF_RANGE_HIGH + 10, + UNKNOWN = 20 + }; + + enum StateRequest { + STATE_REQUEST_HEATING = 4, + STATE_REQUEST_IGNORE = 3, + STATE_REQUEST_OPERATIONAL = 1, + STATE_REQUEST_NON_OPERATIONAL = 0 + }; + + /** + * The elements are ordered by priority, lowest have highest priority + */ + enum Priority { + SAFE = 0, //!< SAFE + IDLE, //!< IDLE + PAYLOAD, //!< PAYLOAD + NUMBER_OF_PRIORITIES //!< MAX_PRIORITY + }; + + /** + * The elements are ordered by priority, lowest have highest priority + */ + enum HeaterRequest { + HEATER_REQUEST_EMERGENCY_OFF = 0, //!< REQUEST_EMERGENCY_OFF + HEATER_REQUEST_EMERGENCY_ON, //!< REQUEST_EMERGENCY_ON + HEATER_REQUEST_OFF, //!< REQUEST_OFF + HEATER_REQUEST_ON, //!< REQUEST_ON + HEATER_DONT_CARE //!< DONT_CARE + }; + + virtual ~ThermalComponentIF() { + + } + + virtual HeaterRequest performOperation(uint8_t opCode) = 0; + + virtual object_id_t getObjectId() = 0; + + virtual uint8_t getDomainId() const = 0; + + virtual void markStateIgnored() = 0; + + virtual float getLowerOpLimit() = 0; + + virtual ReturnValue_t setTargetState(int8_t state) = 0; + + virtual void setOutputInvalid() = 0; + + static bool isOperational(int8_t state) { + return ((state == OPERATIONAL) || (state == OPERATIONAL_IGNORED)); + } + + static bool isOutOfRange(State state) { + return ((state == OUT_OF_RANGE_HIGH) + || (state == OUT_OF_RANGE_HIGH_IGNORED) + || (state == OUT_OF_RANGE_LOW) + || (state == OUT_OF_RANGE_LOW_IGNORED) || (state == UNKNOWN)); + } + + static bool isNonOperational(State state) { + return !isOutOfRange(state); + } + + static bool isIgnoredState(State state) { + switch (state) { + case OUT_OF_RANGE_LOW_IGNORED: + case OUT_OF_RANGE_HIGH_IGNORED: + case NON_OPERATIONAL_LOW_IGNORED: + case NON_OPERATIONAL_HIGH_IGNORED: + case OPERATIONAL_IGNORED: + case UNKNOWN: + return true; + default: + return false; + } + } +}; + +#endif /* THERMALCOMPONENTIF_H_ */ diff --git a/thermal/ThermalModule.cpp b/thermal/ThermalModule.cpp new file mode 100644 index 00000000..24a4c90d --- /dev/null +++ b/thermal/ThermalModule.cpp @@ -0,0 +1,288 @@ +#include +#include +#include "ThermalModule.h" + +#include "AbstractTemperatureSensor.h" + +ThermalModule::ThermalModule(uint32_t moduleTemperaturePoolId, + uint32_t currentStatePoolId, uint32_t targetStatePoolId, + DataSet *dataSet, Parameters parameters, + RedundantHeater::Parameters heaterParameters) : + oldStrategy(ACTIVE_SINGLE), survivalTargetTemp(0), targetTemp(0), heating( + false), parameters(parameters), moduleTemperature( + moduleTemperaturePoolId, dataSet, PoolVariableIF::VAR_WRITE), currentState( + currentStatePoolId, dataSet, PoolVariableIF::VAR_WRITE), targetState( + targetStatePoolId, dataSet, PoolVariableIF::VAR_READ) { + heater = new RedundantHeater(heaterParameters); +} + +ThermalModule::ThermalModule(uint32_t moduleTemperaturePoolId, DataSet* dataSet) : + oldStrategy(ACTIVE_SINGLE), survivalTargetTemp(0), targetTemp(0), heating( + false), parameters( { 0, 0 }), moduleTemperature( + moduleTemperaturePoolId, dataSet, PoolVariableIF::VAR_WRITE), heater( + NULL), currentState(PoolVariableIF::INVALID, dataSet, + PoolVariableIF::VAR_WRITE), targetState(PoolVariableIF::INVALID, + dataSet, PoolVariableIF::VAR_READ) { +} + +ThermalModule::~ThermalModule() { + delete heater; +} + +void ThermalModule::performOperation(uint8_t opCode) { + if (heater != NULL) { + heater->performOperation(0); + } +} + +void ThermalModule::performMode(Strategy strategy) { + calculateTemperature(); + + bool safeOnly = (strategy == ACTIVE_SURVIVAL); + ThermalComponentIF::HeaterRequest componentHeaterRequest = + letComponentsPerformAndDeciceIfWeNeedToHeat(safeOnly); + + if (heater == NULL) { + informComponentsAboutHeaterState(false, NONE); + return; + } + + bool heating = calculateModuleHeaterRequestAndSetModuleStatus(strategy); + + if (componentHeaterRequest != ThermalComponentIF::HEATER_DONT_CARE) { + //Components overwrite the module request. + heating = ((componentHeaterRequest + == ThermalComponentIF::HEATER_REQUEST_ON) + || (componentHeaterRequest + == ThermalComponentIF::HEATER_REQUEST_EMERGENCY_ON)); + } + + bool dual = (strategy == ACTIVE_DUAL); + + if (strategy == PASSIVE) { + informComponentsAboutHeaterState(false, NONE); + if (oldStrategy != PASSIVE) { + heater->set(false, false, true); + } + } else { + if (safeOnly) { + informComponentsAboutHeaterState(heating, SAFE); + } else { + informComponentsAboutHeaterState(heating, ALL); + } + heater->set(heating, dual); + } + oldStrategy = strategy; +} + +float ThermalModule::getTemperature() { + return moduleTemperature; +} + +void ThermalModule::registerSensor(AbstractTemperatureSensor * sensor) { + sensors.push_back(sensor); +} + +void ThermalModule::registerComponent(ThermalComponentIF* component, + ThermalComponentIF::Priority priority) { + components.push_back(ComponentData( { component, priority, ThermalComponentIF::HEATER_DONT_CARE })); +} + +void ThermalModule::calculateTemperature() { + uint32_t numberOfValidSensors = 0; + moduleTemperature = 0; + std::list::iterator iter = sensors.begin(); + for (; iter != sensors.end(); iter++) { + if ((*iter)->isValid()) { + moduleTemperature = moduleTemperature + (*iter)->getTemperature(); + numberOfValidSensors++; + } + } + if (numberOfValidSensors != 0) { + moduleTemperature = moduleTemperature / numberOfValidSensors; + moduleTemperature.setValid(PoolVariableIF::VALID); + } else { + moduleTemperature = INVALID_TEMPERATURE; + moduleTemperature.setValid(PoolVariableIF::INVALID); + } +} + +ThermalComponentIF* ThermalModule::findComponent(object_id_t objectId) { + std::list::iterator iter = components.begin(); + for (; iter != components.end(); iter++) { + if (iter->component->getObjectId() == objectId) { + return iter->component; + } + } + return NULL; +} + +ThermalComponentIF::HeaterRequest ThermalModule::letComponentsPerformAndDeciceIfWeNeedToHeat( + bool safeOnly) { + ThermalComponentIF::HeaterRequest heaterRequests[ThermalComponentIF::NUMBER_OF_PRIORITIES]; + + survivalTargetTemp = -999; + targetTemp = -999; + + for (uint8_t i = 0; i < ThermalComponentIF::NUMBER_OF_PRIORITIES; i++) { + heaterRequests[i] = ThermalComponentIF::HEATER_DONT_CARE; + } + + std::list::iterator iter = components.begin(); + for (; iter != components.end(); iter++) { + updateTargetTemperatures(iter->component, + iter->priority == ThermalComponentIF::SAFE); + ThermalComponentIF::HeaterRequest request = + iter->component->performOperation(0); + iter->request = request; + if (request != ThermalComponentIF::HEATER_DONT_CARE) { + if (request < heaterRequests[iter->priority]) { + heaterRequests[iter->priority] = request; + } + } + } + + if (!safeOnly) { + for (uint8_t i = ThermalComponentIF::NUMBER_OF_PRIORITIES - 1; i > 0; + i--) { + if (heaterRequests[i - 1] == ThermalComponentIF::HEATER_DONT_CARE) { + heaterRequests[i - 1] = heaterRequests[i]; + } + } + } + return heaterRequests[0]; +} + +void ThermalModule::informComponentsAboutHeaterState(bool heaterIsOn, + Informee whomToInform) { + std::list::iterator iter = components.begin(); + for (; iter != components.end(); iter++) { + switch (whomToInform) { + case ALL: + break; + case SAFE: + if (!(iter->priority == ThermalComponentIF::SAFE)) { + iter->component->markStateIgnored(); + continue; + } + break; + case NONE: + iter->component->markStateIgnored(); + continue; + } + + if (heaterIsOn) { + if ((iter->request + == ThermalComponentIF::HEATER_REQUEST_EMERGENCY_OFF) + || (iter->request == ThermalComponentIF::HEATER_REQUEST_OFF)) { + iter->component->markStateIgnored(); + } + } else { + if ((iter->request + == ThermalComponentIF::HEATER_REQUEST_EMERGENCY_ON) + || (iter->request == ThermalComponentIF::HEATER_REQUEST_ON)) { + iter->component->markStateIgnored(); + } + } + } +} + +void ThermalModule::initialize(PowerSwitchIF* powerSwitch) { + if (heater != NULL) { + heater->setPowerSwitcher(powerSwitch); + } + + std::list::iterator iter = components.begin(); + for (; iter != components.end(); iter++) { + float componentLowerOpLimit = iter->component->getLowerOpLimit(); + if (iter->priority == ThermalComponentIF::SAFE) { + if (componentLowerOpLimit > survivalTargetTemp) { + survivalTargetTemp = componentLowerOpLimit; + } + } else { + if (componentLowerOpLimit > targetTemp) { + targetTemp = componentLowerOpLimit; + } + } + } + if (survivalTargetTemp > targetTemp) { + targetTemp = survivalTargetTemp; + } +} + +bool ThermalModule::calculateModuleHeaterRequestAndSetModuleStatus( + Strategy strategy) { + currentState.setValid(PoolVariableIF::VALID); + if (moduleTemperature == INVALID_TEMPERATURE) { + currentState = UNKNOWN; + return false; + } + + float limit = targetTemp; + bool heaterRequest = false; + if (strategy == ACTIVE_SURVIVAL) { + limit = survivalTargetTemp; + } + + if (moduleTemperature >= limit) { + currentState = OPERATIONAL; + } else { + currentState = NON_OPERATIONAL; + } + + limit += parameters.heaterOn; + + if (heating) { + limit += parameters.hysteresis; + } + + if (targetState == STATE_REQUEST_HEATING) { + if (moduleTemperature < limit) { + heaterRequest = true; + } else { + heaterRequest = false; + } + } + + heating = heaterRequest; + + return heaterRequest; +} + +void ThermalModule::setHeating(bool on) { + DataSet mySet; + PoolVariable writableTargetState(targetState.getDataPoolId(), + &mySet, PoolVariableIF::VAR_WRITE); + if (on) { + writableTargetState = STATE_REQUEST_HEATING; + } else { + writableTargetState = STATE_REQUEST_PASSIVE; + } + mySet.commit(PoolVariableIF::VALID); +} + +void ThermalModule::updateTargetTemperatures(ThermalComponentIF* component, + bool isSafe) { + if (isSafe) { + if (component->getLowerOpLimit() > survivalTargetTemp) { + survivalTargetTemp = component->getLowerOpLimit(); + } + } else { + if (component->getLowerOpLimit() > targetTemp) { + targetTemp = component->getLowerOpLimit(); + } + } +} + +void ThermalModule::setOutputInvalid() { + moduleTemperature = INVALID_TEMPERATURE; + moduleTemperature.setValid(PoolVariableIF::INVALID); + currentState.setValid(PoolVariableIF::INVALID); + std::list::iterator iter = components.begin(); + for (; iter != components.end(); iter++) { + iter->component->setOutputInvalid(); + } + if (heater != NULL) { + heater->set(false,true); + } +} diff --git a/thermal/ThermalModule.h b/thermal/ThermalModule.h new file mode 100644 index 00000000..d8ac7d73 --- /dev/null +++ b/thermal/ThermalModule.h @@ -0,0 +1,92 @@ +#ifndef THERMALMODULE_H_ +#define THERMALMODULE_H_ + +#include +#include +#include +#include +#include "ThermalModuleIF.h" +#include +#include "tcsDefinitions.h" +#include "RedundantHeater.h" +class PowerSwitchIF; + +class ThermalModule: public ThermalModuleIF { + friend class ThermalController; +public: + struct Parameters { + float heaterOn; + float hysteresis; + }; + + ThermalModule(uint32_t moduleTemperaturePoolId, uint32_t currentStatePoolId, + uint32_t targetStatePoolId, DataSet *dataSet, Parameters parameters, + RedundantHeater::Parameters heaterParameters); + + ThermalModule(uint32_t moduleTemperaturePoolId, DataSet *dataSet); + + virtual ~ThermalModule(); + + void performOperation(uint8_t opCode); + + void performMode(Strategy strategy); + + float getTemperature(); + + void registerSensor(AbstractTemperatureSensor *sensor); + + void registerComponent(ThermalComponentIF *component, + ThermalComponentIF::Priority priority); + + ThermalComponentIF *findComponent(object_id_t objectId); + + void initialize(PowerSwitchIF* powerSwitch); + + void setHeating(bool on); + + virtual void setOutputInvalid(); + +protected: + enum Informee { + ALL, SAFE, NONE + }; + + struct ComponentData { + ThermalComponentIF *component; + ThermalComponentIF::Priority priority; + ThermalComponentIF::HeaterRequest request; + }; + + Strategy oldStrategy; + + float survivalTargetTemp; + + float targetTemp; + + bool heating; + + Parameters parameters; + + db_float_t moduleTemperature; + + RedundantHeater *heater; + + db_int8_t currentState; + db_int8_t targetState; + + std::list sensors; + std::list components; + + void calculateTemperature(); + + ThermalComponentIF::HeaterRequest letComponentsPerformAndDeciceIfWeNeedToHeat(bool safeOnly); + + void informComponentsAboutHeaterState(bool heaterIsOn, + Informee whomToInform); + + bool calculateModuleHeaterRequestAndSetModuleStatus(Strategy strategy); + + void updateTargetTemperatures(ThermalComponentIF *component, bool isSafe); +}; + +#endif /* THERMALMODULE_H_ */ diff --git a/thermal/ThermalModuleIF.h b/thermal/ThermalModuleIF.h new file mode 100644 index 00000000..a363aed6 --- /dev/null +++ b/thermal/ThermalModuleIF.h @@ -0,0 +1,46 @@ +#ifndef THERMALMODULEIF_H_ +#define THERMALMODULEIF_H_ + +#include "ThermalComponentIF.h" +class AbstractTemperatureSensor; + +class ThermalModuleIF{ +public: + enum Strategy { + PASSIVE = 0, ACTIVE_SURVIVAL = 1, ACTIVE_SINGLE = 2, ACTIVE_DUAL = 3, + }; + + enum StateRequest { + STATE_REQUEST_HEATING = 1, STATE_REQUEST_PASSIVE = 0 + }; + + enum State { + NON_OPERATIONAL = 0, OPERATIONAL = 1, UNKNOWN = 2 + }; + + //TODO, modern gcc complains about const + static const float INVALID_TEMPERATURE = 999; + + virtual ~ThermalModuleIF() { + + } + + virtual void performOperation(uint8_t opCode) = 0; + + virtual void performMode(Strategy strategy) = 0; + + virtual float getTemperature() = 0; + + virtual void registerSensor(AbstractTemperatureSensor *sensor) = 0; + + virtual void registerComponent(ThermalComponentIF *component, + ThermalComponentIF::Priority priority) = 0; + + virtual ThermalComponentIF *findComponent(object_id_t objectId) = 0; + + virtual void setHeating(bool on) = 0; + + virtual void setOutputInvalid() = 0; +}; + +#endif /* THERMALMODULEIF_H_ */ diff --git a/thermal/ThermalMonitor.cpp b/thermal/ThermalMonitor.cpp new file mode 100644 index 00000000..773fa084 --- /dev/null +++ b/thermal/ThermalMonitor.cpp @@ -0,0 +1,68 @@ +#include +#include +#include +ThermalMonitor::~ThermalMonitor() { +} + +void ThermalMonitor::sendTransitionEvent(float currentValue, + ReturnValue_t state) { + switch (state) { + case MonitoringIF::BELOW_LOW_LIMIT: + EventManagerIF::triggerEvent(reportingId, + ThermalComponentIF::COMPONENT_TEMP_OOL_LOW, state); + break; + case MonitoringIF::ABOVE_HIGH_LIMIT: + EventManagerIF::triggerEvent(reportingId, + ThermalComponentIF::COMPONENT_TEMP_OOL_HIGH, state); + break; + case ThermalComponentIF::BELOW_OPERATIONAL_LIMIT: + EventManagerIF::triggerEvent(reportingId, + ThermalComponentIF::COMPONENT_TEMP_LOW, state); + break; + case ThermalComponentIF::ABOVE_OPERATIONAL_LIMIT: + EventManagerIF::triggerEvent(reportingId, + ThermalComponentIF::COMPONENT_TEMP_HIGH, state); + break; + default: + break; + } +} + +bool ThermalMonitor::isAboveHighLimit() { + if (oldState == ThermalComponentIF::ABOVE_OPERATIONAL_LIMIT) { + return true; + } else { + return false; + } +} + +ReturnValue_t ThermalMonitor::translateState(ThermalComponentIF::State state, float sample, float lowerLimit, + float upperLimit, bool componentIsOperational) { + if (ThermalComponentIF::isIgnoredState(state)) { + setToUnchecked(); + return MonitoringIF::UNCHECKED; + } + switch (state) { + case ThermalComponentIF::OUT_OF_RANGE_LOW: + return monitorStateIs(MonitoringIF::BELOW_LOW_LIMIT, sample, lowerLimit); + case ThermalComponentIF::NON_OPERATIONAL_LOW: + if (componentIsOperational) { + return monitorStateIs(ThermalComponentIF::BELOW_OPERATIONAL_LIMIT, sample, lowerLimit); + } else { + return monitorStateIs(HasReturnvaluesIF::RETURN_OK, sample, 0.0); + } + case ThermalComponentIF::OPERATIONAL: + return monitorStateIs(HasReturnvaluesIF::RETURN_OK, sample, 0.0); + case ThermalComponentIF::NON_OPERATIONAL_HIGH: + if (componentIsOperational) { + return monitorStateIs(ThermalComponentIF::ABOVE_OPERATIONAL_LIMIT, sample, upperLimit); + } else { + return monitorStateIs(HasReturnvaluesIF::RETURN_OK, sample, 0.0); + } + case ThermalComponentIF::OUT_OF_RANGE_HIGH: + return monitorStateIs(MonitoringIF::ABOVE_HIGH_LIMIT, sample, upperLimit); + default: + //Never reached, all states covered. + return HasReturnvaluesIF::RETURN_FAILED; + } +} diff --git a/thermal/ThermalMonitor.h b/thermal/ThermalMonitor.h new file mode 100644 index 00000000..6aca55ab --- /dev/null +++ b/thermal/ThermalMonitor.h @@ -0,0 +1,23 @@ +#ifndef FRAMEWORK_THERMAL_THERMALMONITOR_H_ +#define FRAMEWORK_THERMAL_THERMALMONITOR_H_ + +#include +#include + +class ThermalMonitor: public MonitorReporter { +public: + template + ThermalMonitor(Args ... args) : + MonitorReporter(std::forward(args)...) { + } + ~ThermalMonitor(); + ReturnValue_t translateState(ThermalComponentIF::State state, float sample, + float lowerLimit, float upperLimit, bool componentIsOperational = true); + + bool isAboveHighLimit(); +protected: + virtual void sendTransitionEvent(float currentValue, ReturnValue_t state); + +}; + +#endif /* FRAMEWORK_THERMAL_THERMALMONITOR_H_ */ diff --git a/thermal/tcsDefinitions.h b/thermal/tcsDefinitions.h new file mode 100644 index 00000000..ad258ced --- /dev/null +++ b/thermal/tcsDefinitions.h @@ -0,0 +1,8 @@ +#ifndef TCSDEFINITIONS_H_ +#define TCSDEFINITIONS_H_ + + +static const uint32_t INVALID_TEMPERATURE = 999; + + +#endif /* TCSDEFINITIONS_H_ */ diff --git a/timemanager/CCSDSTime.cpp b/timemanager/CCSDSTime.cpp index 29d68e34..a4eaf555 100644 --- a/timemanager/CCSDSTime.cpp +++ b/timemanager/CCSDSTime.cpp @@ -1,11 +1,3 @@ -/* - * CCSDSTime.cpp - * - * Created on: 22.03.2013 - * Author: tod - */ - -#include #include #include #include @@ -17,7 +9,12 @@ CCSDSTime::~CCSDSTime() { } ReturnValue_t CCSDSTime::convertToCcsds(Ccs_seconds* to, - const TimeOfDay_t* from) { + const Clock::TimeOfDay_t* from) { + ReturnValue_t result = checkTimeOfDay(from); + if (result != RETURN_OK) { + return result; + } + to->pField = (CCS << 4); to->yearMSB = (from->year >> 8); @@ -32,7 +29,12 @@ ReturnValue_t CCSDSTime::convertToCcsds(Ccs_seconds* to, } ReturnValue_t CCSDSTime::convertToCcsds(Ccs_mseconds* to, - const TimeOfDay_t* from) { + const Clock::TimeOfDay_t* from) { + ReturnValue_t result = checkTimeOfDay(from); + if (result != RETURN_OK) { + return result; + } + to->pField = (CCS << 4) + 2; to->yearMSB = (from->year >> 8); @@ -48,7 +50,7 @@ ReturnValue_t CCSDSTime::convertToCcsds(Ccs_mseconds* to, return RETURN_OK; } -ReturnValue_t CCSDSTime::convertFromCcsds(TimeOfDay_t* to, const uint8_t* from, +ReturnValue_t CCSDSTime::convertFromCcsds(Clock::TimeOfDay_t* to, const uint8_t* from, uint32_t length) { ReturnValue_t result; if (length > 0xFF) { @@ -62,12 +64,11 @@ ReturnValue_t CCSDSTime::convertFromCcsds(TimeOfDay_t* to, const uint8_t* from, //Seems to be no ascii, try the other formats uint8_t codeIdentification = (*from >> 4); switch (codeIdentification) { - case CUC_LEVEL1: //CUC_LEVEL2 can not be converted to TimeOfDay (ToD is Level 1) <- Well, if we know the epoch, we can... + case CUC_LEVEL1: //CUC_LEVEL2 can not be converted to TimeOfDay (ToD is Level 1) <- Well, if we know the epoch, we can... <- see bug 1133 return convertFromCUC(to, from, length); case CDS: return convertFromCDS(to, from, length); case CCS: { - //SHOULDDO: Returning the actual found length is the right way to go, but for now, keep it. uint32_t temp = 0; return convertFromCCS(to, from, &temp, length); } @@ -77,12 +78,12 @@ ReturnValue_t CCSDSTime::convertFromCcsds(TimeOfDay_t* to, const uint8_t* from, } } -ReturnValue_t CCSDSTime::convertFromCUC(TimeOfDay_t* to, const uint8_t* from, +ReturnValue_t CCSDSTime::convertFromCUC(Clock::TimeOfDay_t* to, const uint8_t* from, uint8_t length) { return UNSUPPORTED_TIME_FORMAT; } -ReturnValue_t CCSDSTime::convertFromCDS(TimeOfDay_t* to, const uint8_t* from, +ReturnValue_t CCSDSTime::convertFromCDS(Clock::TimeOfDay_t* to, const uint8_t* from, uint8_t length) { timeval time; ReturnValue_t result = convertFromCDS(&time, from, NULL, length); @@ -92,26 +93,30 @@ ReturnValue_t CCSDSTime::convertFromCDS(TimeOfDay_t* to, const uint8_t* from, return convertTimevalToTimeOfDay(to, &time); } -ReturnValue_t CCSDSTime::convertFromCCS(TimeOfDay_t* to, const uint8_t* from, +ReturnValue_t CCSDSTime::convertFromCCS(Clock::TimeOfDay_t* to, const uint8_t* from, uint32_t* foundLength, uint32_t maxLength) { uint8_t subsecondsLength = *from & 0b111; uint32_t totalLength = subsecondsLength + 8; if (maxLength < totalLength) { return LENGTH_MISMATCH; } - //TODO: Check this! - Ccs_mseconds *temp = (Ccs_mseconds *) from; - if (checkCcs((Ccs_seconds *) from) != RETURN_OK) { - return INVALID_TIME_FORMAT; + *foundLength = totalLength; + + ReturnValue_t result = checkCcs(from, maxLength); + + if (result != RETURN_OK) { + return result; } + Ccs_mseconds *temp = (Ccs_mseconds *) from; + to->year = (temp->yearMSB << 8) + temp->yearLSB; to->hour = temp->hour; to->minute = temp->minute; to->second = temp->second; - if (*from & (1 << 3)) { //day of year variation + if (temp->pField & (1 << 3)) { //day of year variation uint16_t tempDay = (temp->month << 8) + temp->day; ReturnValue_t result = convertDaysOfYear(tempDay, to->year, &(temp->month), &(temp->day)); @@ -124,7 +129,6 @@ ReturnValue_t CCSDSTime::convertFromCCS(TimeOfDay_t* to, const uint8_t* from, to->day = temp->day; to->ticks = 0; - *foundLength = sizeof(Ccs_seconds); if (subsecondsLength > 0) { *foundLength += 1; if (temp->secondEminus2 >= 100) { @@ -145,7 +149,7 @@ ReturnValue_t CCSDSTime::convertFromCCS(TimeOfDay_t* to, const uint8_t* from, } -ReturnValue_t CCSDSTime::convertFromASCII(TimeOfDay_t* to, const uint8_t* from, +ReturnValue_t CCSDSTime::convertFromASCII(Clock::TimeOfDay_t* to, const uint8_t* from, uint8_t length) { if (length < 19) { return RETURN_FAILED; @@ -175,8 +179,8 @@ ReturnValue_t CCSDSTime::convertFromASCII(TimeOfDay_t* to, const uint8_t* from, &hour, &minute, &second); if (count == 5) { uint8_t tempDay; - ReturnValue_t result = CCSDSTime::convertDaysOfYear(day, year, - &month, &tempDay); + ReturnValue_t result = CCSDSTime::convertDaysOfYear(day, year, &month, + &tempDay); if (result != RETURN_OK) { return RETURN_FAILED; } @@ -193,29 +197,44 @@ ReturnValue_t CCSDSTime::convertFromASCII(TimeOfDay_t* to, const uint8_t* from, return UNSUPPORTED_TIME_FORMAT; } -ReturnValue_t CCSDSTime::checkCcs(Ccs_seconds* time) { - if (time->pField & (1 << 3)) { //day of year variation - uint16_t day = (time->month << 8) + time->day; +ReturnValue_t CCSDSTime::checkCcs(const uint8_t* time, uint8_t length) { + Ccs_mseconds *time_struct = (Ccs_mseconds *) time; + + uint8_t additionalBytes = time_struct->pField & 0b111; + if ((additionalBytes == 0b111) || (length < (additionalBytes + 8))) { + return INVALID_TIME_FORMAT; + } + + if (time_struct->pField & (1 << 3)) { //day of year variation + uint16_t day = (time_struct->month << 8) + time_struct->day; if (day > 366) { return INVALID_TIME_FORMAT; } } else { - if (time->month > 12) { + if (time_struct->month > 12) { return INVALID_TIME_FORMAT; } - if (time->day > 31) { + if (time_struct->day > 31) { return INVALID_TIME_FORMAT; } } - if (time->hour > 23) { + if (time_struct->hour > 23) { return INVALID_TIME_FORMAT; } - if (time->minute > 59) { + if (time_struct->minute > 59) { return INVALID_TIME_FORMAT; } - if (time->second > 59) { + if (time_struct->second > 59) { return INVALID_TIME_FORMAT; } + + uint8_t *additionalByte = &time_struct->secondEminus2; + + for (; additionalBytes != 0; additionalBytes--) { + if (*additionalByte++ > 99) { + return INVALID_TIME_FORMAT; + } + } return RETURN_OK; } @@ -260,6 +279,10 @@ ReturnValue_t CCSDSTime::convertDaysOfYear(uint16_t dayofYear, uint16_t year, *month += 1; dayofYear -= 31; + if (*month == 8) { + continue; + } + if (dayofYear <= 30) { *day = dayofYear; return RETURN_OK; @@ -270,7 +293,7 @@ ReturnValue_t CCSDSTime::convertDaysOfYear(uint16_t dayofYear, uint16_t year, return INVALID_DAY_OF_YEAR; } -bool CCSDSTime::isLeapYear(uint16_t year) { +bool CCSDSTime::isLeapYear(uint32_t year) { if ((year % 400) == 0) { return true; } @@ -322,11 +345,12 @@ ReturnValue_t CCSDSTime::convertToCcsds(OBT_FLP* to, const timeval* from) { ReturnValue_t CCSDSTime::convertFromCcsds(timeval* to, const uint8_t* from, uint32_t* foundLength, uint32_t maxLength) { - //We don't expect ascii here. + //We don't expect ascii here. SHOULDDO uint8_t codeIdentification = (*from >> 4); switch (codeIdentification) { - case CUC_LEVEL1: - return convertFromCUC(to, from, foundLength, maxLength); + //unsupported, as Leap second correction would have to be applied +// case CUC_LEVEL1: +// return convertFromCUC(to, from, foundLength, maxLength); case CDS: return convertFromCDS(to, from, foundLength, maxLength); case CCS: @@ -335,7 +359,6 @@ ReturnValue_t CCSDSTime::convertFromCcsds(timeval* to, const uint8_t* from, return UNSUPPORTED_TIME_FORMAT; } - } ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, const uint8_t* from, @@ -345,7 +368,8 @@ ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, const uint8_t* from, } uint8_t pField = *from; from++; - ReturnValue_t result = convertFromCUC(to, pField, from, foundLength, maxLength-1 ); + ReturnValue_t result = convertFromCUC(to, pField, from, foundLength, + maxLength - 1); if (result == HasReturnvaluesIF::RETURN_OK) { if (foundLength != NULL) { *foundLength += 1; @@ -354,9 +378,64 @@ ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, const uint8_t* from, return result; } -ReturnValue_t CCSDSTime::convertTimevalToTimeOfDay(TimeOfDay_t* to, +ReturnValue_t CCSDSTime::checkTimeOfDay(const Clock::TimeOfDay_t* time) { + if ((time->month > 12) || (time->month == 0)) { + return INVALID_TIME_FORMAT; + } + + if (time->day == 0) { + return INVALID_TIME_FORMAT; + } + switch (time->month) { + case 2: + if (isLeapYear(time->year)) { + if (time->day > 29) { + return INVALID_TIME_FORMAT; + } + } else { + if (time->day > 28) { + return INVALID_TIME_FORMAT; + } + } + break; + case 4: + case 6: + case 9: + case 11: + if (time->day > 30) { + return INVALID_TIME_FORMAT; + } + break; + default: + if (time->day > 31) { + return INVALID_TIME_FORMAT; + } + break; + } + + if (time->hour > 23) { + return INVALID_TIME_FORMAT; + } + + if (time->minute > 59) { + return INVALID_TIME_FORMAT; + } + + if (time->second > 59) { + return INVALID_TIME_FORMAT; + } + + if (time->ticks > 999) { + return INVALID_TIME_FORMAT; + } + + return RETURN_OK; + +} + +ReturnValue_t CCSDSTime::convertTimevalToTimeOfDay(Clock::TimeOfDay_t* to, timeval* from) { - //TODO: This is rather tricky. Implement only if needed. Also, if so, move to OSAL. +//This is rather tricky. Implement only if needed. Also, if so, move to OSAL. return UNSUPPORTED_TIME_FORMAT; } @@ -364,11 +443,11 @@ ReturnValue_t CCSDSTime::convertFromCDS(timeval* to, const uint8_t* from, uint32_t* foundLength, uint32_t maxLength) { uint8_t pField = *from; from++; - //Check epoch +//Check epoch if (pField & 0b1000) { return NOT_ENOUGH_INFORMATION_FOR_TARGET_FORMAT; } - //Check length +//Check length uint8_t expectedLength = 7; //Including p-Field. bool extendedDays = pField & 0b100; if (extendedDays) { @@ -385,34 +464,36 @@ ReturnValue_t CCSDSTime::convertFromCDS(timeval* to, const uint8_t* from, if (expectedLength > maxLength) { return LENGTH_MISMATCH; } - //Check and count days +//Check and count days uint32_t days = 0; if (extendedDays) { days = (from[0] << 16) + (from[1] << 8) + from[2]; - from +=3; + from += 3; } else { days = (from[0] << 8) + from[1]; - from +=2; + from += 2; } - //Move to POSIX epoch. +//Move to POSIX epoch. if (days <= DAYS_CCSDS_TO_UNIX_EPOCH) { return INVALID_TIME_FORMAT; } days -= DAYS_CCSDS_TO_UNIX_EPOCH; to->tv_sec = days * SECONDS_PER_DAY; - uint32_t msDay = (from[0] << 24) + (from[1] << 16) + (from[2] << 8) + from[3]; - from +=4; + uint32_t msDay = (from[0] << 24) + (from[1] << 16) + (from[2] << 8) + + from[3]; + from += 4; to->tv_sec += (msDay / 1000); - to->tv_usec = (msDay%1000)*1000; - if ((pField & 0b11) == 0b01 ) { + to->tv_usec = (msDay % 1000) * 1000; + if ((pField & 0b11) == 0b01) { uint16_t usecs = (from[0] << 16) + from[1]; from += 2; if (usecs > 999) { return INVALID_TIME_FORMAT; } to->tv_usec += usecs; - } else if ((pField & 0b11) == 0b10 ) { - uint32_t picosecs = (from[0] << 24) + (from[1] << 16) + (from[2] << 8) + from[3]; + } else if ((pField & 0b11) == 0b10) { + uint32_t picosecs = (from[0] << 24) + (from[1] << 16) + (from[2] << 8) + + from[3]; from += 4; if (picosecs > 999999) { return INVALID_TIME_FORMAT; @@ -429,7 +510,7 @@ ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, uint8_t pField, uint32_t subSeconds = 0; uint8_t nCoarse = ((pField & 0b1100) >> 2) + 1; uint8_t nFine = (pField & 0b11); - uint32_t totalLength = nCoarse+nFine; + uint32_t totalLength = nCoarse + nFine; if (foundLength != NULL) { *foundLength = totalLength; } @@ -437,11 +518,11 @@ ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, uint8_t pField, return LENGTH_MISMATCH; } for (int count = 0; count < nCoarse; count++) { - secs += *from << ((nCoarse*8-8)*(1+count)); + secs += *from << ((nCoarse * 8 - 8) * (1 + count)); from++; } for (int count = 0; count < nFine; count++) { - subSeconds += *from << ((nFine*8-8)*(1+count)); + subSeconds += *from << ((nFine * 8 - 8) * (1 + count)); from++; } //Move to POSIX epoch. @@ -450,22 +531,25 @@ ReturnValue_t CCSDSTime::convertFromCUC(timeval* to, uint8_t pField, //CCSDS-Epoch to->tv_sec -= (DAYS_CCSDS_TO_UNIX_EPOCH * SECONDS_PER_DAY); } - to->tv_usec = subsecondsToMicroseconds(subSeconds); + to->tv_usec = subsecondsToMicroseconds(subSeconds); return RETURN_OK; } uint32_t CCSDSTime::subsecondsToMicroseconds(uint16_t subseconds) { - uint64_t temp = (uint64_t)subseconds * 1000000 / (1 << (sizeof(subseconds)*8)); + uint64_t temp = (uint64_t) subseconds * 1000000 + / (1 << (sizeof(subseconds) * 8)); return temp; } ReturnValue_t CCSDSTime::convertFromCCS(timeval* to, const uint8_t* from, uint32_t* foundLength, uint32_t maxLength) { - TimeOfDay_t tempTime; - ReturnValue_t result = convertFromCCS(&tempTime,from, foundLength, maxLength); + Clock::TimeOfDay_t tempTime; + ReturnValue_t result = convertFromCCS(&tempTime, from, foundLength, + maxLength); if (result != RETURN_OK) { return result; } - return OSAL::convertTimeOfDayToTimeval(&tempTime, to); + + return Clock::convertTimeOfDayToTimeval(&tempTime, to); } diff --git a/timemanager/CCSDSTime.h b/timemanager/CCSDSTime.h index 5386a2f8..bb7ad23a 100644 --- a/timemanager/CCSDSTime.h +++ b/timemanager/CCSDSTime.h @@ -1,25 +1,19 @@ -/* - * CCSDSTimeHelper.h - * - * Created on: 22.03.2013 - * Author: tod - */ - #ifndef CCSDSTIME_H_ #define CCSDSTIME_H_ -#include +#include #include #include bool operator<(const timeval& lhs, const timeval& rhs); +bool operator<=(const timeval& lhs, const timeval& rhs); bool operator==(const timeval& lhs, const timeval& rhs); /** * static helper class for CCSDS Time Code Formats * * as described in CCSDS 301.0-B-3 * - * Still work in progress thus TODO finishme + * Still work in progress */ class CCSDSTime: public HasReturnvaluesIF { public: @@ -37,6 +31,7 @@ public: + 2; static const uint8_t P_FIELD_CUC_6B_AGENCY = (CUC_LEVEL2 << 4) + (3 << 2) + 2; + static const uint8_t P_FIELD_CDS_SHORT = (CDS << 4); /** * Struct for CDS day-segmented format. */ @@ -50,7 +45,7 @@ public: uint8_t msDay_ll; }; /** - * Struct for the CCS fromat in day of month variation with seconds resolution + * Struct for the CCS fromat in day of month variation with max resolution */ struct Ccs_seconds { uint8_t pField; @@ -95,7 +90,7 @@ public: } }; - static const uint8_t INTERFACE_ID = CCSDS_TIME_HELPER_CLASS; + static const uint8_t INTERFACE_ID = CLASS_ID::CCSDS_TIME_HELPER_CLASS; static const ReturnValue_t UNSUPPORTED_TIME_FORMAT = MAKE_RETURN_CODE(0); static const ReturnValue_t NOT_ENOUGH_INFORMATION_FOR_TARGET_FORMAT = MAKE_RETURN_CODE(1); @@ -107,15 +102,14 @@ public: /** * convert a TimeofDay struct to ccs with seconds resolution * - * Assumes a valid TimeOfDay. TODO: maybe check it anyway? - * * @param to pointer to a CCS struct * @param from pointer to a TimeOfDay Struct * @return - * - @c RETURN_OK as it assumes a valid TimeOfDay + * - @c RETURN_OK if OK + * - @c INVALID_TIMECODE if not OK */ static ReturnValue_t convertToCcsds(Ccs_seconds *to, - TimeOfDay_t const *from); + Clock::TimeOfDay_t const *from); /** * Converts to CDS format from timeval. @@ -127,23 +121,23 @@ public: static ReturnValue_t convertToCcsds(CDS_short* to, timeval const *from); static ReturnValue_t convertToCcsds(OBT_FLP* to, timeval const *from); + /** * convert a TimeofDay struct to ccs with 10E-3 seconds resolution * - * Assumes a valid TimeOfDay. TODO: maybe check it anyway? - * * The 10E-4 seconds in the CCS Struct are 0 as the TimeOfDay only has ms resolution * * @param to pointer to a CCS struct * @param from pointer to a TimeOfDay Struct * @return - * - @c RETURN_OK as it assumes a valid TimeOfDay + * - @c RETURN_OK if OK + * - @c INVALID_TIMECODE if not OK */ static ReturnValue_t convertToCcsds(Ccs_mseconds *to, - TimeOfDay_t const *from); + Clock::TimeOfDay_t const *from); /** - * TODO: can this be modified to recognize padding? + * SHOULDDO: can this be modified to recognize padding? * Tries to interpret a Level 1 CCSDS time code * * It assumes binary formats contain a valid P Field and recognizes the ASCII format @@ -154,11 +148,11 @@ public: * @param length length of the Time code * @return * - @c RETURN_OK if successful - * - @c UNSUPPORTED_TIME_FORMAT if a (possibly valid) time code is not supported TODO: the missing codes should be implemented... + * - @c UNSUPPORTED_TIME_FORMAT if a (possibly valid) time code is not supported * - @c LENGTH_MISMATCH if the length does not match the P Field * - @c INVALID_TIME_FORMAT if the format or a value is invalid */ - static ReturnValue_t convertFromCcsds(TimeOfDay_t *to, uint8_t const *from, + static ReturnValue_t convertFromCcsds(Clock::TimeOfDay_t *to, uint8_t const *from, uint32_t length); /** @@ -171,7 +165,7 @@ public: static ReturnValue_t convertFromCcsds(timeval *to, uint8_t const *from, uint32_t* foundLength, uint32_t maxLength); - static ReturnValue_t convertFromCUC(TimeOfDay_t *to, uint8_t const *from, + static ReturnValue_t convertFromCUC(Clock::TimeOfDay_t *to, uint8_t const *from, uint8_t length); static ReturnValue_t convertFromCUC(timeval *to, uint8_t const *from, @@ -186,16 +180,16 @@ public: static ReturnValue_t convertFromCCS(timeval *to, uint8_t pField, uint8_t const *from, uint32_t* foundLength, uint32_t maxLength); - static ReturnValue_t convertFromCDS(TimeOfDay_t *to, uint8_t const *from, + static ReturnValue_t convertFromCDS(Clock::TimeOfDay_t *to, uint8_t const *from, uint8_t length); static ReturnValue_t convertFromCDS(timeval *to, uint8_t const *from, uint32_t* foundLength, uint32_t maxLength); - static ReturnValue_t convertFromCCS(TimeOfDay_t *to, uint8_t const *from, + static ReturnValue_t convertFromCCS(Clock::TimeOfDay_t *to, uint8_t const *from, uint32_t* foundLength, uint32_t maxLength); - static ReturnValue_t convertFromASCII(TimeOfDay_t *to, uint8_t const *from, + static ReturnValue_t convertFromASCII(Clock::TimeOfDay_t *to, uint8_t const *from, uint8_t length); static uint32_t subsecondsToMicroseconds(uint16_t subseconds); @@ -203,14 +197,17 @@ private: CCSDSTime(); virtual ~CCSDSTime(); /** - * checks a ccs time struct for validity + * checks a ccs time stream for validity * - * only checks year to second, subseconds must be checked elsewhere + * Stream may be longer than the actual timecode * - * @param time pointer to an Ccs struct (should be cast to Ccs_seconds as subseconds are not checked. Cast is save as subseconds are at the end of the struct) + * @param time pointer to an Ccs stream + * @param length length of stream * @return */ - static ReturnValue_t checkCcs(Ccs_seconds *time); + static ReturnValue_t checkCcs(const uint8_t* time, uint8_t length); + + static ReturnValue_t checkTimeOfDay(const Clock::TimeOfDay_t *time); static const uint32_t SECONDS_PER_DAY = 24 * 60 * 60; static const uint32_t SECONDS_PER_NON_LEAP_YEAR = SECONDS_PER_DAY * 365; @@ -226,8 +223,8 @@ private: static ReturnValue_t convertDaysOfYear(uint16_t dayofYear, uint16_t year, uint8_t *month, uint8_t *day); - static bool isLeapYear(uint16_t year); - static ReturnValue_t convertTimevalToTimeOfDay(TimeOfDay_t* to, + static bool isLeapYear(uint32_t year); + static ReturnValue_t convertTimevalToTimeOfDay(Clock::TimeOfDay_t* to, timeval* from); }; diff --git a/timemanager/Clock.h b/timemanager/Clock.h new file mode 100644 index 00000000..680350c4 --- /dev/null +++ b/timemanager/Clock.h @@ -0,0 +1,145 @@ +#ifndef FRAMEWORK_TIMEMANAGER_CLOCK_H_ +#define FRAMEWORK_TIMEMANAGER_CLOCK_H_ + +#include +#include +#include +#include +#include + + + +class Clock { +public: + typedef struct { + uint32_t year; //!< Year, A.D. + uint32_t month; //!< Month, 1 .. 12. + uint32_t day; //!< Day, 1 .. 31. + uint32_t hour; //!< Hour, 0 .. 23. + uint32_t minute; //!< Minute, 0 .. 59. + uint32_t second; //!< Second, 0 .. 59. + uint32_t ticks; //!< Elapsed ticks between seconds. + } TimeOfDay_t; + + /**static Clock* TimeOfDay_t(); + * This method returns the number of clock ticks per second. + * In RTEMS, this is typically 1000. + * @return The number of ticks. + */ + static uint32_t getTicksPerSecond(void); + /** + * This system call sets the system time. + * To set the time, it uses a TimeOfDay_t struct. + * @param time The struct with the time settings to set. + * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. + */ + static ReturnValue_t setClock(const TimeOfDay_t* time); + /** + * This system call sets the system time. + * To set the time, it uses a timeval struct. + * @param time The struct with the time settings to set. + * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. + */ + static ReturnValue_t setClock(const timeval* time); + /** + * This system call returns the current system clock in timeval format. + * The timval format has the fields \c tv_sec with seconds and \c tv_usec with + * microseconds since an OS-defined epoch. + * @param time A pointer to a timeval struct where the current time is stored. + * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. + */ + static ReturnValue_t getClock_timeval(timeval* time); + + /** + * Get the time since boot in a timeval struct + * + * @param[out] time A pointer to a timeval struct where the uptime is stored. + * @return\c RETURN_OK on success. Otherwise, the OS failure code is returned. + */ + static ReturnValue_t getUptime(timeval* uptime); + + /** + * Get the time since boot in milliseconds + * + * This value can overflow! Still, it can be used to calculate time intervalls + * between two calls up to 49 days by always using uint32_t in the calculation + * + * @param ms uptime in ms + * @return RETURN_OK on success. Otherwise, the OS failure code is returned. + */ + static ReturnValue_t getUptime(uint32_t* uptimeMs); + + /** + * Returns the time in microseconds since an OS-defined epoch. + * The time is returned in a 64 bit unsigned integer. + * @param time A pointer to a 64 bit unisigned integer where the data is stored. + * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. + */ + static ReturnValue_t getClock_usecs(uint64_t* time); + /** + * Returns the time in a TimeOfDay_t struct. + * @param time A pointer to a TimeOfDay_t struct. + * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. + */ + static ReturnValue_t getDateAndTime(TimeOfDay_t* time); + + /** + * Converts a time of day struct to POSIX seconds. + * @param time The time of day as input + * @param timeval The corresponding seconds since the epoch. + * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. + */ + static ReturnValue_t convertTimeOfDayToTimeval(const TimeOfDay_t* from, + timeval* to); + + /** + * Converts a time represented as seconds and subseconds since unix epoch to days since J2000 + * + * @param time seconds since unix epoch + * @param[out] JD2000 days since J2000 + * @return \c RETURN_OK + */ + static ReturnValue_t convertTimevalToJD2000(timeval time, double* JD2000); + + /** + * Calculates and adds the offset between UTC and TT + * + * Depends on the leap seconds to be set correctly. + * + * @param utc timeval, corresponding to UTC time + * @param[out] tt timeval, corresponding to Terrestial Time + * @return \c RETURN_OK on success, \c RETURN_FAILED if leapSeconds are not set + */ + static ReturnValue_t convertUTCToTT(timeval utc, timeval* tt); + + /** + * Set the Leap Seconds since 1972 + * + * @param leapSeconds_ + * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. + */ + static ReturnValue_t setLeapSeconds(const uint16_t leapSeconds_); + + /** + * Get the Leap Seconds since 1972 + * + * Must be set before! + * + * @param[out] leapSeconds_ + * @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. + */ + static ReturnValue_t getLeapSeconds(uint16_t *leapSeconds_); + + /** + * Function to check and create the Mutex for the clock + * @return \c RETURN_OK on success. Otherwise \c RETURN_FAILED if not able to create one + */ + static ReturnValue_t checkOrCreateClockMutex(); + +private: + static MutexIF* timeMutex; + static uint16_t leapSeconds; +}; + + +#endif /* FRAMEWORK_TIMEMANAGER_CLOCK_H_ */ diff --git a/timemanager/Countdown.cpp b/timemanager/Countdown.cpp index 94e1007e..e6565914 100644 --- a/timemanager/Countdown.cpp +++ b/timemanager/Countdown.cpp @@ -15,14 +15,14 @@ Countdown::~Countdown() { } ReturnValue_t Countdown::setTimeout(uint32_t miliseconds) { - ReturnValue_t return_value = OSAL::getUptime( &startTime ); + ReturnValue_t return_value = Clock::getUptime( &startTime ); timeout = miliseconds; return return_value; } bool Countdown::hasTimedOut() const { uint32_t current_time; - OSAL::getUptime( ¤t_time ); + Clock::getUptime( ¤t_time ); if ( uint32_t(current_time - startTime) >= timeout) { return true; } else { @@ -37,3 +37,9 @@ bool Countdown::isBusy() const { ReturnValue_t Countdown::resetTimer() { return setTimeout(timeout); } + +void Countdown::timeOut() { + uint32_t current_time; + Clock::getUptime( ¤t_time ); + startTime= current_time - timeout; +} diff --git a/timemanager/Countdown.h b/timemanager/Countdown.h index 4c9ac43a..57a11f91 100644 --- a/timemanager/Countdown.h +++ b/timemanager/Countdown.h @@ -8,7 +8,7 @@ #ifndef COUNTDOWN_H_ #define COUNTDOWN_H_ -#include +#include class Countdown { private: @@ -24,6 +24,8 @@ public: bool isBusy() const; ReturnValue_t resetTimer(); //!< Use last set timeout value and restart timer. + + void timeOut(); //!< Make hasTimedOut() return true }; #endif /* COUNTDOWN_H_ */ diff --git a/timemanager/ReceivesTimeInfoIF.h b/timemanager/ReceivesTimeInfoIF.h index 813c30b2..14a750c5 100644 --- a/timemanager/ReceivesTimeInfoIF.h +++ b/timemanager/ReceivesTimeInfoIF.h @@ -8,7 +8,6 @@ #ifndef RECEIVESTIMEINFOIF_H_ #define RECEIVESTIMEINFOIF_H_ -#include /** * This is a Interface for classes that receive timing information * with the help of a dedicated message queue. @@ -19,7 +18,7 @@ public: * Returns the id of the queue which receives the timing information. * @return Queue id of the timing queue. */ - virtual MessageQueueId_t getTimeReceptionQueue() = 0; + virtual MessageQueueId_t getTimeReceptionQueue() const = 0; /** * Empty virtual destructor. */ diff --git a/timemanager/TimeMessage.cpp b/timemanager/TimeMessage.cpp index d2fe02b7..bf514317 100644 --- a/timemanager/TimeMessage.cpp +++ b/timemanager/TimeMessage.cpp @@ -8,12 +8,13 @@ #include TimeMessage::TimeMessage() { - this->messageSize += sizeof(timeval); + this->messageSize += sizeof(timeval) + sizeof(uint32_t); } -TimeMessage::TimeMessage(timeval setTime) { +TimeMessage::TimeMessage(timeval setTime, uint32_t CounterValue) { memcpy (this->getData(), &setTime, sizeof(timeval)); - this->messageSize += sizeof(timeval); + this->messageSize += sizeof(timeval) + sizeof(uint32_t); + memcpy (this->getData() + sizeof(timeval), &CounterValue, sizeof(uint32_t)); } TimeMessage::~TimeMessage() { @@ -25,6 +26,12 @@ timeval TimeMessage::getTime() { return temp; } +uint32_t TimeMessage::getCounterValue() { + uint32_t temp; + memcpy ( &temp, this->getData() + sizeof(timeval), sizeof(uint32_t)); + return temp; +} + size_t TimeMessage::getMinimumMessageSize() { return this->MAX_SIZE; } diff --git a/timemanager/TimeMessage.h b/timemanager/TimeMessage.h index 2e7397d5..95685fec 100644 --- a/timemanager/TimeMessage.h +++ b/timemanager/TimeMessage.h @@ -9,12 +9,14 @@ #define TIMEMESSAGE_H_ #include +#include +#include class TimeMessage : public MessageQueueMessage { protected: /** * @brief This call always returns the same fixed size of the message. - * @return Returns HEADER_SIZE + \c sizeof(timeval). + * @return Returns HEADER_SIZE + \c sizeof(timeval) + sizeof(uint32_t). */ size_t getMinimumMessageSize(); public: @@ -22,7 +24,7 @@ public: /** * @ brief the size of a TimeMessage */ - static const uint32_t MAX_SIZE = HEADER_SIZE + sizeof(timeval); + static const uint32_t MAX_SIZE = HEADER_SIZE + sizeof(timeval) + sizeof(uint32_t); /** * @brief In the default constructor, only the message_size is set. @@ -31,9 +33,10 @@ public: /** * @brief With this constructor, the passed time information is directly put * into the message. - * @param setTime The time information to put into the message. + * @param setTime The time information to put into the message. + * @param counterValue The counterValue to put into the message (GPS PPS). */ - TimeMessage( timeval setTime ); + TimeMessage( timeval setTime, uint32_t counterValue = 0 ); /** * @brief The class's destructor is empty. */ @@ -43,6 +46,11 @@ public: * @return Returns the time stored in this packet. */ timeval getTime(); + /** + * @brief This getter returns the CounterValue in uint32_t format. + * @return Returns the CounterValue stored in this packet. + */ + uint32_t getCounterValue(); }; #endif /* TIMEMESSAGE_H_ */ diff --git a/timemanager/TimeStamperIF.h b/timemanager/TimeStamperIF.h index b4f1b121..7ed45371 100644 --- a/timemanager/TimeStamperIF.h +++ b/timemanager/TimeStamperIF.h @@ -1,17 +1,19 @@ -/* - * TimeStamperIF.h - * - * Created on: 31.03.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_TIMEMANAGER_TIMESTAMPERIF_H_ #define FRAMEWORK_TIMEMANAGER_TIMESTAMPERIF_H_ #include +/** + * A class implementing this IF provides facilities to add a time stamp to the + * buffer provided. + * Implementors need to ensure that calling the method is thread-safe, i.e. + * addTimeStamp may be called in parallel from a different context. + */ class TimeStamperIF { public: + static const uint8_t INTERFACE_ID = CLASS_ID::TIME_STAMPER_IF; + static const ReturnValue_t BAD_TIMESTAMP = MAKE_RETURN_CODE(1); + static const uint8_t MISSION_TIMESTAMP_SIZE = 8; //!< This is a mission-specific constant and determines the total size reserved for timestamps. virtual ReturnValue_t addTimeStamp(uint8_t* buffer, const uint8_t maxSize) = 0; virtual ~TimeStamperIF() {} diff --git a/tmstorage/TmStore.cpp b/tmstorage/TmStore.cpp deleted file mode 100644 index e771cba8..00000000 --- a/tmstorage/TmStore.cpp +++ /dev/null @@ -1,704 +0,0 @@ -/* - * TmStore.cpp - * - * Created on: 05.02.2015 - * Author: baetz - */ - -#include -#include -#include -#include -#include -#include - - -TmStore::TmStore(TmStoreFrontendIF* owner, object_id_t memoryObject, - uint32_t storeAddress, uint32_t size, bool overwriteOld, - uint32_t maxDumpPacketsPerCylce, uint32_t maxDumpedBytesPerCylce, - uint32_t updateRemotePtrsMs, uint32_t chunkSize) : - owner(owner), eventProxy(NULL), info(&oldestPacket, &newestPacket), infoSize( - info.getSerializedSize()), ring(storeAddress + infoSize, - size - infoSize, overwriteOld), state(OFF), writeState( - WRITE_IDLE), readState(READ_IDLE), memoryObject(memoryObject), memoryQueue(), ipcStore( - NULL), timer(), pendingDataToWrite(0), maximumAmountToRead(0), storedPacketCounter(0), pendingStoredPackets(0), splitWrite( - false), splitRead(NO_SPLIT), splitReadTotalSize(0), tmBuffer(chunkSize), dumpBuffer( - NULL), pointerAddress(storeAddress), updateRemotePtrsMs( - updateRemotePtrsMs), maxDumpPacketsPerCycle( - maxDumpPacketsPerCylce), maxDumpedBytesPerCycle(maxDumpedBytesPerCylce), tryToSetStoreInfo(false) { - dumpBuffer = new uint8_t[chunkSize]; -} - -TmStore::~TmStore() { - delete[] dumpBuffer; -} - -ReturnValue_t TmStore::performOperation() { - doStateMachine(); - checkMemoryQueue(); - if (localBufferTimer.hasTimedOut() && (state == READY)) { - sendTmBufferToStore(); - localBufferTimer.setTimeout(LOCAL_BUFFER_TIMEOUT_MS); - } - return RETURN_OK; -} - -ReturnValue_t TmStore::storePacket(TmPacketMinimal* tmPacket) { - if (tmPacket->getFullSize() > chunkSize()) { - return TOO_LARGE; - } - ReturnValue_t result = RETURN_FAILED; - if (hasEnoughSpaceFor(tmPacket->getFullSize())) { - localBufferTimer.setTimeout(LOCAL_BUFFER_TIMEOUT_MS); - result = storeOrForwardPacket(tmPacket->getWholeData(), - tmPacket->getFullSize()); - } else { - result = handleFullStore(tmPacket->getWholeData(), - tmPacket->getFullSize()); - } - if (result == RETURN_OK) { - pendingNewestPacket.setContent(tmPacket); - if (!pendingOldestPacket.isValid()) { - pendingOldestPacket.setContent(tmPacket); - } - pendingStoredPackets++; - } - return result; -} - -ReturnValue_t TmStore::fetchPackets(bool useAddress, uint32_t startAtAddress) { - if (!isReady()) { - return NOT_READY; - } - if (ring.isEmpty()) { - return EMPTY; - } - if (readState != READ_IDLE) { - return BUSY; - } - // Never download more than the currently available data. - maximumAmountToRead = ring.availableReadData(); - if (useAddress) { - ring.setRead(startAtAddress, TEMP_READ_PTR); - } else { - ring.setRead(ring.getRead(READ_PTR), TEMP_READ_PTR); - } - ReturnValue_t result = requestChunkOfData(); - if (result != RETURN_OK) { - return result; - } - setReadState(DUMPING_PACKETS); - return RETURN_OK; -} - -ReturnValue_t TmStore::requestStoreInfo() { - CommandMessage message; - MemoryMessage::setMemoryDumpCommand(&message, pointerAddress, infoSize); - ReturnValue_t result = memoryQueue.sendToDefault(&message); - if (result != RETURN_OK) { - return result; - } - return RETURN_OK; -} - -ReturnValue_t TmStore::setStoreInfo() { - store_address_t storeId; - uint8_t* data = NULL; - uint32_t size = 0; - ReturnValue_t result = ipcStore->getFreeElement(&storeId, infoSize, &data); - if (result != RETURN_OK) { - return result; - } - info.setContent(ring.getRead(), ring.getWrite(), storedPacketCounter); - result = info.serialize(&data, &size, infoSize, true); - if (result != RETURN_OK) { - ipcStore->deleteData(storeId); - return result; - } - CommandMessage message; - MemoryMessage::setMemoryLoadCommand(&message, pointerAddress, storeId); - result = memoryQueue.sendToDefault(&message); - if (result != RETURN_OK) { - ipcStore->deleteData(storeId); - return result; - } - return RETURN_OK; -} - -void TmStore::doStateMachine() { - switch (state) { - case OFF: - break; - case STARTUP: { - ReturnValue_t result = requestStoreInfo(); - if (result == RETURN_OK) { - setState(FETCH_STORE_INFORMATION); - setReadState(FETCHING_STORE_INFO); - timer.setTimeout(DEFAULT_TIMEOUT_MS); - } else { - eventProxy->forwardEvent(STORE_INIT_FAILED, result, 0); - setState(OFF); - } - } - break; - case FETCH_STORE_INFORMATION: - if (timer.hasTimedOut()) { - eventProxy->forwardEvent(STORE_INIT_FAILED, TIMEOUT, 1); - setState(OFF); - } - break; - case READY: - if (tryToSetStoreInfo) { - if ((writeState == WRITE_IDLE) && (readState == READ_IDLE)) { - if (setStoreInfo() == RETURN_OK) { - setWriteState(SETTING_STORE_INFO); - } - tryToSetStoreInfo = false; - } - } - break; - default: - //do nothing. - break; - } -} - -void TmStore::checkMemoryQueue() { - CommandMessage message; - for (ReturnValue_t result = memoryQueue.receiveMessage(&message); - result == RETURN_OK; - result = memoryQueue.receiveMessage(&message)) { - switch (message.getCommand()) { - case CommandMessage::REPLY_COMMAND_OK: - handleLoadSuccess(); - break; - case MemoryMessage::REPLY_MEMORY_DUMP: - handleDump(MemoryMessage::getStoreID(&message)); - break; - case MemoryMessage::REPLY_MEMORY_FAILED: - case CommandMessage::REPLY_REJECTED: // REPLY_REJECTED uses the same protocol. - switch (MemoryMessage::getInitialCommand(&message)) { - case MemoryMessage::CMD_MEMORY_LOAD: - handleLoadFailed(MemoryMessage::getErrorCode(&message)); - break; - case MemoryMessage::CMD_MEMORY_DUMP: - handleDumpFailed(MemoryMessage::getErrorCode(&message)); - break; - default: - debug << "TmStore: Unknown InitialCommand: " - << MemoryMessage::getInitialCommand(&message) - << std::endl; - break; - } - break; - default: - eventProxy->forwardEvent(UNEXPECTED_MSG, 0, 0); - break; - } - } -} - -void TmStore::handleLoadSuccess() { - switch (writeState) { - case SETTING_STORE_INFO: - setWriteState(WRITE_IDLE); - break; - case SENDING_PACKETS: - if (splitWrite) { - ReturnValue_t result = sendRemainingTmPiece(); - if (result != RETURN_OK) { - eventProxy->forwardEvent(STORE_SEND_WRITE_FAILED, result, 0); - resetStore(true); - pendingDataToWrite = 0; - } - splitWrite = false; - } else { - ring.writeData(pendingDataToWrite); - pendingDataToWrite = 0; - storedPacketCounter += pendingStoredPackets; - newestPacket.setContent(&pendingNewestPacket); - if (!oldestPacket.isValid()) { - oldestPacket.setContent(&pendingOldestPacket); - } - pendingStoredPackets = 0; - setWriteState(WRITE_IDLE); - tryToSetStoreInfo = true; - } - break; - default: - eventProxy->forwardEvent(UNEXPECTED_MSG, 0, 1); - } -} - -void TmStore::handleDump(store_address_t storeId) { - const uint8_t* buffer = NULL; - uint32_t size = 0; - ReturnValue_t result = ipcStore->getData(storeId, &buffer, &size); - if (result != RETURN_OK) { - return; - } - switch (readState) { - case FETCHING_STORE_INFO: - readStoreInfo(buffer, size); - break; - case DUMPING_PACKETS: - case DELETING_OLD: - case DELETING_MORE: - handleSplitRead(buffer, size); - break; - default: - setReadState(READ_IDLE); - //No break. - case READ_IDLE: - eventProxy->forwardEvent(UNEXPECTED_MSG, 0, 2); - break; - } - ipcStore->deleteData(storeId); -} - -void TmStore::handleSplitRead(const uint8_t* buffer, uint32_t size) { - switch (splitRead) { - case NO_SPLIT: - if (readState == DELETING_OLD || readState == DELETING_MORE) { - deleteOld(buffer, size); - } else { - dumpPackets(buffer, size); - } - break; - case SPLIT_STARTED: - if (size <= chunkSize()) { - ReturnValue_t result = requestRemainingDumpPiece(size); - if (result == RETURN_OK) { - memcpy(dumpBuffer, buffer, size); - splitRead = ONE_RECEIVED; - } else { - eventProxy->forwardEvent(STORE_SEND_READ_FAILED, result, 0); - splitRead = NO_SPLIT; - maximumAmountToRead = 0; - } - } else { - eventProxy->forwardEvent(STORE_SEND_READ_FAILED, TOO_LARGE, 0); - splitRead = NO_SPLIT; - maximumAmountToRead = 0; - } - break; - case ONE_RECEIVED: - memcpy(&dumpBuffer[splitReadTotalSize - size], buffer, size); - if (readState == DELETING_OLD || readState == DELETING_MORE) { - deleteOld(dumpBuffer, splitReadTotalSize); - } else { - dumpPackets(dumpBuffer, splitReadTotalSize); - } - splitRead = NO_SPLIT; - break; - } -} - -void TmStore::handleLoadFailed(ReturnValue_t errorCode) { - eventProxy->forwardEvent(STORE_WRITE_FAILED, errorCode, 0); - setWriteState(WRITE_IDLE); - setState(READY); - splitWrite = false; - pendingDataToWrite = 0; -} - -void TmStore::handleDumpFailed(ReturnValue_t errorCode) { - switch (readState) { - case FETCHING_STORE_INFO: - eventProxy->forwardEvent(STORE_INIT_FAILED, errorCode, 2); - setState(OFF); - break; - case DUMPING_PACKETS: - owner->handleRetrievalFailed(errorCode); - //No break - default: - case READ_IDLE: - case DELETING_OLD: - case DELETING_MORE: - eventProxy->forwardEvent(STORE_READ_FAILED, errorCode, 0); - setState(READY); - break; - } - setReadState(READ_IDLE); - splitRead = NO_SPLIT; - maximumAmountToRead = 0; -} - -void TmStore::readStoreInfo(const uint8_t* buffer, uint32_t size) { - setReadState(READ_IDLE); - if (::Calculate_CRC(buffer, infoSize) != 0) { - eventProxy->forwardEvent(STORE_INIT_EMPTY, 0, 0); - setState(READY); - return; - } - int32_t deSize = size; - ReturnValue_t result = info.deSerialize(&buffer, &deSize, true); - if (result != RETURN_OK) { - //An error here is extremely unlikely. - eventProxy->forwardEvent(STORE_INIT_FAILED, result, 3); - setState(OFF); - return; - } - eventProxy->forwardEvent(STORE_INIT_DONE); - ring.setWrite(info.writeP); - ring.setRead(info.readP); - storedPacketCounter = info.storedPacketCount; - setState(READY); -} - -void TmStore::dumpPackets(const uint8_t* buffer, uint32_t size) { - ReturnValue_t result = RETURN_OK; - uint32_t tempSize = 0; - uint32_t dumpedPacketCounter = 0; - uint32_t dumpedBytesCounter = 0; - while (size >= TmPacketMinimal::MINIMUM_SIZE - && dumpedPacketCounter < maxDumpPacketsPerCycle - && dumpedBytesCounter < maxDumpedBytesPerCycle - && result == RETURN_OK) { - TmPacketMinimal packet(buffer); - tempSize = packet.getFullSize(); - if (tempSize > size) { - if (tempSize > ring.availableReadData(READ_PTR) || tempSize > chunkSize()) { - owner->handleRetrievalFailed(DUMP_ERROR); - eventProxy->forwardEvent(STORE_CONTENT_CORRUPTED, 0, tempSize); - result = DUMP_ERROR; - } - break; - } - size -= tempSize; - buffer += tempSize; - dumpedBytesCounter += tempSize; - if (maximumAmountToRead > tempSize) { - result = owner->packetRetrieved(&packet, - ring.getRead(TEMP_READ_PTR)); - maximumAmountToRead -= tempSize; - } else { - //packet is complete and last. - result = owner->packetRetrieved(&packet, - ring.getRead(TEMP_READ_PTR), true); - maximumAmountToRead = 0; - break; - } - if (result == RETURN_OK) { - ring.readData(tempSize, TEMP_READ_PTR); - dumpedPacketCounter++; - } - } - if (result == RETURN_OK && maximumAmountToRead != 0) { - result = requestChunkOfData(); - if (result != HasReturnvaluesIF::RETURN_OK) { - owner->handleRetrievalFailed(result); - } - } else { - setReadState(READ_IDLE); - } -} - -ReturnValue_t TmStore::sendDataToTmStore(const uint8_t* data, uint32_t size) { - //Unfortunately, cleanup is quite complex. - store_address_t storeId; - ReturnValue_t result = RETURN_FAILED; - if (size > ring.writeTillWrap()) { - //Two-folded write - result = ipcStore->addData(&storeId, data, ring.writeTillWrap()); - if (result != RETURN_OK) { - return result; - } - splitWrite = true; - result = ipcStore->addData(&splitWriteStoreId, - data + ring.writeTillWrap(), size - ring.writeTillWrap()); - if (result != RETURN_OK) { - ipcStore->deleteData(storeId); - } - } else { - //Normal write - splitWrite = false; - result = ipcStore->addData(&storeId, data, size); - } - if (result != RETURN_OK) { - splitWrite = false; - return result; - } - CommandMessage message; - MemoryMessage::setMemoryLoadCommand(&message, ring.getWrite(), storeId); - if ((result = memoryQueue.sendToDefault(&message)) == RETURN_OK) { - setWriteState(SENDING_PACKETS); - pendingDataToWrite = size; - } else { - if (splitWrite) { - ipcStore->deleteData(splitWriteStoreId); - } - splitWrite = false; - ipcStore->deleteData(storeId); - } - return result; -} - -ReturnValue_t TmStore::requestChunkOfData() { - uint32_t readSize = - (maximumAmountToRead > chunkSize()) ? - chunkSize() : maximumAmountToRead; - CommandMessage message; - if (readSize > ring.readTillWrap(TEMP_READ_PTR)) { - //Wrap - splitReadTotalSize = readSize; - splitRead = SPLIT_STARTED; - MemoryMessage::setMemoryDumpCommand(&message, - ring.getRead(TEMP_READ_PTR), ring.readTillWrap(TEMP_READ_PTR)); - } else { - splitRead = NO_SPLIT; - MemoryMessage::setMemoryDumpCommand(&message, - ring.getRead(TEMP_READ_PTR), readSize); - } - ReturnValue_t result = memoryQueue.sendToDefault(&message); - if (result != RETURN_OK) { - splitRead = NO_SPLIT; - maximumAmountToRead = 0; - } - return result; -} - -ReturnValue_t TmStore::initialize() { - AcceptsMemoryMessagesIF* memoryTarget = objectManager->get< - AcceptsMemoryMessagesIF>(memoryObject); - if (memoryTarget == NULL) { - return RETURN_FAILED; - } - memoryQueue.setDefaultDestination(memoryTarget->getCommandQueue()); - ipcStore = objectManager->get(objects::IPC_STORE); - if (ipcStore == NULL) { - return RETURN_FAILED; - } - //assert that Store is larger than local store and potential data on the way. - if (ring.availableWriteSpace(READ_PTR) < (2 * tmBuffer.maxSize())) { - //Ring buffer is too small. - return RETURN_FAILED; - } - //Ugly cast to have the correct link to eventProxy: - eventProxy = dynamic_cast(owner); - if (eventProxy == NULL) { - return RETURN_FAILED; - } - return RETURN_OK; -} - -ReturnValue_t TmStore::initializeStore() { - setState(STARTUP); - eventProxy->forwardEvent(STORE_INITIALIZE, 0, 0); - return RETURN_OK; -} - -bool TmStore::isReady() { - return (state == READY); -} - -ReturnValue_t TmStore::sendRemainingTmPiece() { - if (writeState != SENDING_PACKETS) { - return RETURN_FAILED; - } - CommandMessage message; - MemoryMessage::setMemoryLoadCommand(&message, ring.getStart(), - splitWriteStoreId); - return memoryQueue.sendToDefault(&message); -} - -ReturnValue_t TmStore::requestRemainingDumpPiece(uint32_t firstPartSize) { - CommandMessage message; - MemoryMessage::setMemoryDumpCommand(&message, ring.getStart(), - splitReadTotalSize - firstPartSize); - return memoryQueue.sendToDefault(&message); -} - -uint32_t TmStore::availableData() { - return ring.availableReadData(); -} - -ReturnValue_t TmStore::storeOrForwardPacket(const uint8_t* data, - uint32_t size) { - if (tmBuffer.remaining() >= size) { - memcpy(&tmBuffer[tmBuffer.size], data, size); - tmBuffer.size += size; - return RETURN_OK; - } else { - if (writeState != WRITE_IDLE) { - return BUSY; - } - if (!isReady()) { - return NOT_READY; - } - sendTmBufferToStore(); - memcpy(tmBuffer.front(), data, size); - tmBuffer.size += size; - return RETURN_OK; - } -} - -bool TmStore::hasEnoughSpaceFor(uint32_t size) { - //Correct size configuration is asserted in initialize(). - if ((ring.availableWriteSpace(READ_PTR) - tmBuffer.size - pendingDataToWrite) - > size) { - return true; - } else { - return false; - } -} - -ReturnValue_t TmStore::deleteContent(bool deletePart, uint32_t upToAddress, - uint32_t nDeletedPackets, TmPacketMinimal* newOldestPacket) { - if (deletePart) { - ring.setRead(upToAddress, READ_PTR); - storedPacketCounter -= nDeletedPackets; - if (newOldestPacket != NULL) { - oldestPacket.setContent(newOldestPacket); - } - } else { - resetStore(); - } - tryToSetStoreInfo = true; - return RETURN_OK; -} - -ReturnValue_t TmStore::handleFullStore(const uint8_t* data, uint32_t size) { - if (!isReady()) { - return NOT_READY; - } - if (!ring.overwritesOld()) { - sendTmBufferToStore(); - return FULL; - } - ReturnValue_t result = FULL; - if ((writeState == WRITE_IDLE) && (readState == READ_IDLE)) { - sendTmBufferToStore(); - maximumAmountToRead = chunkSize(); - ring.setRead(ring.getRead(READ_PTR), TEMP_READ_PTR); - result = requestChunkOfData(); - if (result != RETURN_OK) { - return result; - } - setReadState(DELETING_OLD); - //Store data in cleared store. - memcpy(tmBuffer.front(), data, size); - tmBuffer.size += size; - result = RETURN_OK; - } else if (readState == DELETING_OLD) { - //Try to store local as long as possible - if (tmBuffer.remaining() >= size) { - memcpy(&tmBuffer[tmBuffer.size], data, size); - tmBuffer.size += size; - result = RETURN_OK; - } - } - return result; -} - -void TmStore::deleteOld(const uint8_t* buffer, uint32_t size) { - ReturnValue_t result = RETURN_OK; - uint32_t tempSize = 0; - while (size >= TmPacketMinimal::MINIMUM_SIZE && result == RETURN_OK) { - TmPacketMinimal packet(buffer); - tempSize = packet.getFullSize(); - if (readState == DELETING_MORE) { - if (size < (TmPacketMinimal::MINIMUM_SIZE + tempSize)) { - oldestPacket.setContent(&packet); - break; - } - } else { - if (tempSize > size) { - //Don't delete the last packet half in store... - break; - } - } - result = ring.readData(tempSize, READ_PTR); - ring.readData(tempSize, TEMP_READ_PTR); - size -= tempSize; - buffer += tempSize; - storedPacketCounter--; - } - if (readState == DELETING_OLD) { - result = requestChunkOfData(); - if (result != HasReturnvaluesIF::RETURN_OK) { - oldestPacket.reset(); - eventProxy->forwardEvent(STORE_SEND_WRITE_FAILED, result, 1); - setReadState(READ_IDLE); - } else { - setReadState(DELETING_MORE); - } - } else { - setReadState(READ_IDLE); - owner->restDownlinkedPacketCount(); - tryToSetStoreInfo = true; - } -} - -void TmStore::sendTmBufferToStore() { - //No need to send empty data packet. - if (tmBuffer.size > 0) { - ReturnValue_t result = sendDataToTmStore(tmBuffer.front(), tmBuffer.size); - if (result != HasReturnvaluesIF::RETURN_OK) { - eventProxy->forwardEvent(STORE_SEND_WRITE_FAILED, result, 2); - } - tmBuffer.clear(); - } -} - -void TmStore::resetStore(bool resetWrite, bool resetRead) { - ring.clear(); - setState(READY); - storedPacketCounter = 0; - clearPending(); - tmBuffer.clear(); - oldestPacket.reset(); - newestPacket.reset(); - tryToSetStoreInfo = true; - if (resetWrite) { - setWriteState(WRITE_IDLE); - splitWrite = false; - pendingDataToWrite = 0; - } - if (resetRead) { - maximumAmountToRead = 0; - splitRead = NO_SPLIT; - setReadState(READ_IDLE); - } -} - -void TmStore::setState(State state) { -// debug << "TmStore::setState: " << state << std::endl; - this->state = state; -} - -void TmStore::setWriteState(WriteState writeState) { -// debug << "TmStore::setWriteState: " << writeState << std::endl; - this->writeState = writeState; -} - -void TmStore::setReadState(ReadState readState) { -// debug << "TmStore::setReadState: " << readState << std::endl; - this->readState = readState; -} - -float TmStore::getPercentageFilled() const { - return ring.availableReadData(READ_PTR) / float(ring.maxSize()); -} - -uint32_t TmStore::getStoredPacketsCount() const { - return storedPacketCounter; -} - -TmPacketInformation* TmStore::getOldestPacket() { - return &oldestPacket; -} - -TmPacketInformation* TmStore::getYoungestPacket() { - return &newestPacket; -} - -uint32_t TmStore::chunkSize() { - return tmBuffer.maxSize(); -} - -void TmStore::clearPending() { - pendingOldestPacket.reset(); - pendingNewestPacket.reset(); - pendingStoredPackets = 0; -} diff --git a/tmstorage/TmStore.h b/tmstorage/TmStore.h deleted file mode 100644 index b56ad67d..00000000 --- a/tmstorage/TmStore.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * TmStore.h - * - * Created on: 05.02.2015 - * Author: baetz - */ - -#ifndef PLATFORM_TMTCSERVICES_TMSTORE_H_ -#define PLATFORM_TMTCSERVICES_TMSTORE_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class TmStore: public HasReturnvaluesIF, public TmStoreBackendIF { -public: - static const uint32_t DEFAULT_TIMEOUT_MS = 3000; - static const uint32_t UPDATE_REMOTE_PTRS_DEFAULT_MS = 20000; - static const uint32_t MAX_DUMP_PACKETS_PER_CYCLE_DEFAULT = 16; - static const uint32_t MAX_DUMPED_BYTES_PER_CYCLE_DEFAULT = 1024; - TmStore(TmStoreFrontendIF* owner, object_id_t memoryObject, - uint32_t storeAddress, uint32_t size, bool overwriteOld = false, - uint32_t maxDumpPacketsPerCylce = MAX_DUMP_PACKETS_PER_CYCLE_DEFAULT, - uint32_t maxDumpedBytesPerCycle = MAX_DUMPED_BYTES_PER_CYCLE_DEFAULT, - uint32_t updateRemotePtrsMs = UPDATE_REMOTE_PTRS_DEFAULT_MS, - uint32_t chunkSize = CHUNK_SIZE_DEFAULT); - virtual ~TmStore(); - ReturnValue_t performOperation(); - ReturnValue_t storePacket(TmPacketMinimal* tmPacket); - ReturnValue_t fetchPackets(bool useAddress = false, - uint32_t startAtAddress = 0); - uint32_t availableData(); - ReturnValue_t deleteContent(bool deletePart = false, uint32_t upToAddress = - 0, uint32_t nDeletedPackets = 0, TmPacketMinimal* newOldestPacket = - NULL); - ReturnValue_t initialize(); - ReturnValue_t initializeStore(); - bool isReady(); - void resetStore(bool resetWrite = false, bool resetRead = false); - float getPercentageFilled() const; - uint32_t getStoredPacketsCount() const; - TmPacketInformation* getOldestPacket(); - TmPacketInformation* getYoungestPacket(); -private: - TmStoreFrontendIF* owner; - EventReportingProxyIF* eventProxy; - TmPacketInformation pendingOldestPacket; - TmPacketInformation pendingNewestPacket; - TmPacketInformation oldestPacket; - TmPacketInformation newestPacket; - TmStoreInfo info; - const uint32_t infoSize; - RingBufferBase<2> ring; - enum State { - OFF = 0, - STARTUP = 1, - FETCH_STORE_INFORMATION = 2, - STORE_INFORMATION_RECEIVED = 3, - READY = 4 - }; - State state; - enum WriteState { - WRITE_IDLE = 0, SETTING_STORE_INFO = 1, SENDING_PACKETS = 2, - }; - WriteState writeState; - enum ReadState { - READ_IDLE = 0, - DELETING_OLD = 1, - DUMPING_PACKETS = 2, - FETCHING_STORE_INFO = 3, - DELETING_MORE = 4 - }; - ReadState readState; - object_id_t memoryObject; - MessageQueue memoryQueue; - StorageManagerIF* ipcStore; - Countdown timer; - uint32_t pendingDataToWrite; - uint32_t maximumAmountToRead; - uint32_t storedPacketCounter; - uint32_t pendingStoredPackets; - bool splitWrite; - store_address_t splitWriteStoreId; - enum SplitReadState { - NO_SPLIT, SPLIT_STARTED, ONE_RECEIVED - }; - SplitReadState splitRead; - uint32_t splitReadTotalSize; - ArrayList tmBuffer; - uint8_t* dumpBuffer; - const uint32_t pointerAddress; - const uint32_t updateRemotePtrsMs; - const uint32_t maxDumpPacketsPerCycle; - const uint32_t maxDumpedBytesPerCycle; - Countdown localBufferTimer; - bool tryToSetStoreInfo; - static const uint8_t READ_PTR = 0; - static const uint8_t TEMP_READ_PTR = 1; - static const uint32_t LOCAL_BUFFER_TIMEOUT_MS = 5000; - static const uint32_t CHUNK_SIZE_DEFAULT = 2048; - void checkMemoryQueue(); - ReturnValue_t requestStoreInfo(); - ReturnValue_t setStoreInfo(); - void readStoreInfo(const uint8_t* buffer, uint32_t size); - void dumpPackets(const uint8_t* buffer, uint32_t size); - /** - * Deletes old packets to free space in the store for new packets. - * Two chunks of data are requested to definitely delete mored than one - * chunk. Deletion is stopped when the last full packet is found, to - * be able to remember the oldest packet in store. - * @param buffer Data containing the old packets. - * @param size Size of the data chunk. - */ - void deleteOld(const uint8_t* buffer, uint32_t size); - void doStateMachine(); - void handleLoadSuccess(); - void handleDump(store_address_t storeId); - void handleLoadFailed(ReturnValue_t errorCode); - void handleDumpFailed(ReturnValue_t errorCode); - ReturnValue_t sendDataToTmStore(const uint8_t* data, uint32_t size); - ReturnValue_t sendRemainingTmPiece(); - ReturnValue_t requestChunkOfData(); - ReturnValue_t requestRemainingDumpPiece(uint32_t firstPartSize); - ReturnValue_t storeOrForwardPacket(const uint8_t* data, uint32_t size); - ReturnValue_t handleFullStore(const uint8_t* data, uint32_t size); - bool hasEnoughSpaceFor(uint32_t size); - void sendTmBufferToStore(); - void handleSplitRead(const uint8_t* buffer, uint32_t size); - void setState(State state); - void setReadState(ReadState readState); - void setWriteState(WriteState writeState); - uint32_t chunkSize(); - void clearPending(); -}; - -#endif /* PLATFORM_TMTCSERVICES_TMSTORE_H_ */ diff --git a/tmstorage/TmStoreBackendIF.h b/tmstorage/TmStoreBackendIF.h index 8c1c1ef0..162bd766 100644 --- a/tmstorage/TmStoreBackendIF.h +++ b/tmstorage/TmStoreBackendIF.h @@ -1,20 +1,19 @@ -/* - * TmStoreBackendIF.h - * - * Created on: 18.02.2015 - * Author: baetz - */ - #ifndef PLATFORM_TMTCSERVICES_TMSTOREBACKENDIF_H_ #define PLATFORM_TMTCSERVICES_TMSTOREBACKENDIF_H_ #include +#include +#include +#include +#include class TmPacketInformation; class TmPacketMinimal; +class SpacePacketBase; +class ApidSsc; -class TmStoreBackendIF { +class TmStoreBackendIF : public HasParametersIF { public: - static const uint8_t INTERFACE_ID = TM_STORE_BACKEND_IF; + static const uint8_t INTERFACE_ID = CLASS_ID::TM_STORE_BACKEND_IF; static const ReturnValue_t BUSY = MAKE_RETURN_CODE(1); static const ReturnValue_t FULL = MAKE_RETURN_CODE(2); static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(3); @@ -24,35 +23,52 @@ public: static const ReturnValue_t DUMP_ERROR = MAKE_RETURN_CODE(7); static const ReturnValue_t CRC_ERROR = MAKE_RETURN_CODE(8); static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE(9); + static const ReturnValue_t IDLE_PACKET_FOUND = MAKE_RETURN_CODE(10); + static const ReturnValue_t TELECOMMAND_FOUND = MAKE_RETURN_CODE(11); + static const ReturnValue_t NO_PUS_A_TM = MAKE_RETURN_CODE(12); + static const ReturnValue_t TOO_SMALL = MAKE_RETURN_CODE(13); + static const ReturnValue_t BLOCK_NOT_FOUND = MAKE_RETURN_CODE(14); + static const ReturnValue_t INVALID_REQUEST = MAKE_RETURN_CODE(15); static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::MEMORY; static const Event STORE_SEND_WRITE_FAILED = MAKE_EVENT(0, SEVERITY::LOW); //!< Initiating sending data to store failed. Low, par1: returnCode, par2: integer (debug info) static const Event STORE_WRITE_FAILED = MAKE_EVENT(1, SEVERITY::LOW); //!< Data was sent, but writing failed. Low, par1: returnCode, par2: 0 static const Event STORE_SEND_READ_FAILED = MAKE_EVENT(2, SEVERITY::LOW); //!< Initiating reading data from store failed. Low, par1: returnCode, par2: 0 static const Event STORE_READ_FAILED = MAKE_EVENT(3, SEVERITY::LOW); //!< Data was requested, but access failed. Low, par1: returnCode, par2: 0 - static const Event UNEXPECTED_MSG = MAKE_EVENT(4, SEVERITY::INFO); //!< An unexpected TM packet or data message occurred. Info, par1: 0, par2: integer (debug info) + static const Event UNEXPECTED_MSG = MAKE_EVENT(4, SEVERITY::LOW); //!< An unexpected TM packet or data message occurred. Low, par1: 0, par2: integer (debug info) static const Event STORING_FAILED = MAKE_EVENT(5, SEVERITY::LOW); //!< Storing data failed. May simply be a full store. Low, par1: returnCode, par2: integer (sequence count of failed packet). static const Event TM_DUMP_FAILED = MAKE_EVENT(6, SEVERITY::LOW); //!< Dumping retrieved data failed. Low, par1: returnCode, par2: integer (sequence count of failed packet). static const Event STORE_INIT_FAILED = MAKE_EVENT(7, SEVERITY::LOW); //!< Corrupted init data or read error. Low, par1: returnCode, par2: integer (debug info) static const Event STORE_INIT_EMPTY = MAKE_EVENT(8, SEVERITY::INFO); //!< Store was not initialized. Starts empty. Info, parameters both zero. - static const Event STORE_CONTENT_CORRUPTED = MAKE_EVENT(9, SEVERITY::LOW); //!< Data was read out, but it is inconsistent. Low par1: 0, par2: integer (debug info) + static const Event STORE_CONTENT_CORRUPTED = MAKE_EVENT(9, SEVERITY::LOW); //!< Data was read out, but it is inconsistent. Low par1: Memory address of corruption, par2: integer (debug info) static const Event STORE_INITIALIZE = MAKE_EVENT(10, SEVERITY::INFO); //!< Info event indicating the store will be initialized, either at boot or after IOB switch. Info. pars: 0 - static const Event STORE_INIT_DONE = MAKE_EVENT(11, SEVERITY::INFO); //!< Info event indicating the store was successfully initialized, either at boot or after IOB switch. Info. pars: 0 + static const Event INIT_DONE = MAKE_EVENT(11, SEVERITY::INFO); //!< Info event indicating the store was successfully initialized, either at boot or after IOB switch. Info. pars: 0 + static const Event DUMP_FINISHED = MAKE_EVENT(12, SEVERITY::INFO); //!< Info event indicating that dumping finished successfully. par1: Number of dumped packets. par2: APID/SSC (16bits each) + static const Event DELETION_FINISHED = MAKE_EVENT(13, SEVERITY::INFO); //!< Info event indicating that deletion finished successfully. par1: Number of deleted packets. par2: APID/SSC (16bits each) + static const Event DELETION_FAILED = MAKE_EVENT(14, SEVERITY::LOW); //!< Info event indicating that something went wrong during deletion. pars: 0 + static const Event AUTO_CATALOGS_SENDING_FAILED = MAKE_EVENT(15, SEVERITY::INFO);//!< Info that the a auto catalog report failed virtual ~TmStoreBackendIF() {} - virtual ReturnValue_t performOperation() = 0; + virtual ReturnValue_t performOperation(uint8_t opCode) = 0; virtual ReturnValue_t initialize() = 0; virtual ReturnValue_t storePacket(TmPacketMinimal* tmPacket) = 0; - virtual ReturnValue_t fetchPackets(bool useAddress = false, uint32_t startAtAddress = 0) = 0; - virtual ReturnValue_t deleteContent(bool deletePart = false, uint32_t upToAddress = 0, uint32_t nDeletedPackets = 0, TmPacketMinimal* newOldestPacket = NULL) = 0; - virtual ReturnValue_t initializeStore() = 0; - virtual void resetStore(bool resetWrite = false, bool resetRead = false) = 0; + virtual ReturnValue_t setFetchLimitTime(const timeval* loverLimit, const timeval* upperLimit) = 0; + virtual ReturnValue_t setFetchLimitBlocks(uint32_t startAddress, uint32_t endAddress) = 0; + virtual ReturnValue_t fetchPackets(bool fromBegin = false) = 0; + virtual ReturnValue_t initializeStore(object_id_t dumpTarget) = 0; + virtual ReturnValue_t dumpIndex(store_address_t* storeId) = 0; + virtual ReturnValue_t deleteBlocks(uint32_t startAddress, uint32_t endAddress) = 0; + virtual ReturnValue_t deleteTime(const timeval* timeUntil, + uint32_t* deletedPackets) = 0; + virtual void resetStore(bool clearStore, bool resetWrite, bool resetRead) = 0; virtual bool isReady() = 0; virtual uint32_t availableData() = 0; virtual float getPercentageFilled() const = 0; virtual uint32_t getStoredPacketsCount() const = 0; virtual TmPacketInformation* getOldestPacket() = 0; - virtual TmPacketInformation* getYoungestPacket() = 0; + virtual TmPacketInformation* getYoungestPacket() = 0; + virtual float getDataRate() = 0; + }; diff --git a/tmstorage/TmStoreFrontendIF.h b/tmstorage/TmStoreFrontendIF.h index cd0f606a..787c3597 100644 --- a/tmstorage/TmStoreFrontendIF.h +++ b/tmstorage/TmStoreFrontendIF.h @@ -1,27 +1,17 @@ -/* - * TmStoreFrontendIF.h - * - * Created on: 19.02.2015 - * Author: baetz - */ - #ifndef PLATFORM_TMTCSERVICES_TMSTOREFRONTENDIF_H_ #define PLATFORM_TMTCSERVICES_TMSTOREFRONTENDIF_H_ -#include #include +#include +#include class TmPacketMinimal; class SpacePacketBase; class TmStoreBackendIF; class TmStoreFrontendIF { public: - struct ApidSsc { - uint16_t apid; - uint16_t ssc; - }; virtual TmStoreBackendIF* getBackend() const = 0; - virtual ReturnValue_t performOperation() = 0; + virtual ReturnValue_t performOperation(uint8_t opCode) = 0; /** * Callback from the back-end to indicate a certain packet was received. * front-end takes care of discarding/downloading the packet. @@ -31,24 +21,31 @@ public: * @return If more packets shall be fetched, RETURN_OK must be returned. * Any other code stops fetching packets. */ - virtual ReturnValue_t packetRetrieved(TmPacketMinimal* packet, uint32_t address, bool isLastPacket = false) = 0; + virtual ReturnValue_t packetRetrieved(TmPacketMinimal* packet, uint32_t address) = 0; + virtual void noMorePacketsInStore() = 0; virtual void handleRetrievalFailed(ReturnValue_t errorCode, uint32_t parameter1 = 0, uint32_t parameter2 = 0) = 0; /** * To get the queue where commands shall be sent. * @return Id of command queue. */ - virtual MessageQueueId_t getCommandQueue() = 0; + virtual MessageQueueId_t getCommandQueue() const = 0; virtual ReturnValue_t fetchPackets(ApidSsc start, ApidSsc end) = 0; virtual ReturnValue_t deletePackets(ApidSsc upTo) = 0; virtual ReturnValue_t checkPacket(SpacePacketBase* tmPacket) = 0; virtual bool isEnabled() const = 0; virtual void setEnabled(bool enabled) = 0; - virtual void restDownlinkedPacketCount() = 0; - static const uint8_t INTERFACE_ID = TM_STORE_FRONTEND_IF; + virtual void resetDownlinkedPacketCount() = 0; + virtual ReturnValue_t setDumpTarget(object_id_t dumpTarget) = 0; + static const uint8_t INTERFACE_ID = CLASS_ID::TM_STORE_FRONTEND_IF; static const ReturnValue_t BUSY = MAKE_RETURN_CODE(1); static const ReturnValue_t LAST_PACKET_FOUND = MAKE_RETURN_CODE(2); static const ReturnValue_t STOP_FETCH = MAKE_RETURN_CODE(3); static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE(4); + static const ReturnValue_t TM_CHANNEL_FULL = MAKE_RETURN_CODE(5); + static const ReturnValue_t NOT_STORED = MAKE_RETURN_CODE(6); + static const ReturnValue_t ALL_DELETED = MAKE_RETURN_CODE(7); + static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(8); + static const ReturnValue_t NOT_READY = MAKE_RETURN_CODE(9); virtual ~TmStoreFrontendIF() { } }; diff --git a/tmstorage/TmStoreInfo.h b/tmstorage/TmStoreInfo.h deleted file mode 100644 index 5df7d29b..00000000 --- a/tmstorage/TmStoreInfo.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * TmStoreInfo.h - * - * Created on: 19.03.2015 - * Author: baetz - */ - -#ifndef FRAMEWORK_TMSTORAGE_TMSTOREINFO_H_ -#define FRAMEWORK_TMSTORAGE_TMSTOREINFO_H_ - -#include -#include - -class TmStoreInfo: public SerializeIF { -public: - SerializeElement readP; - SerializeElement writeP; - SerializeElement storedPacketCount; - LinkedElement linkedOldestPacket; - LinkedElement linkedYoungestPacket; - SerializeElement crc; - TmStoreInfo(SerializeIF* oldestPacket, SerializeIF* youngestPacket) : - readP(0), writeP(0), linkedOldestPacket(oldestPacket), linkedYoungestPacket( - youngestPacket) { - this->readP.setNext(&this->writeP); - this->writeP.setNext(&this->storedPacketCount); - storedPacketCount.setNext(&linkedOldestPacket); - linkedOldestPacket.setNext(&linkedYoungestPacket); - } - void setContent(uint32_t readP, uint32_t writeP, uint32_t storedPackets) { - this->readP = readP; - this->writeP = writeP; - this->storedPacketCount = storedPackets; - } - ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, - const uint32_t max_size, bool bigEndian) const { - uint8_t* startBuffer = *buffer; - ReturnValue_t result = SerialLinkedListAdapter::serialize( - &readP, buffer, size, max_size, bigEndian); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - uint32_t elementSize = - SerialLinkedListAdapter::getSerializedSize(&readP); - SerializeElement localCrc; - localCrc.entry = ::Calculate_CRC(startBuffer, elementSize); - return localCrc.serialize(buffer, size, max_size, bigEndian); - } - - uint32_t getSerializedSize() const { - return (SerialLinkedListAdapter::getSerializedSize(&readP) - + crc.getSerializedSize()); - } - - ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, - bool bigEndian) { - ReturnValue_t result = - SerialLinkedListAdapter::deSerialize(&readP, - buffer, size, bigEndian); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - return crc.deSerialize(buffer, size, bigEndian); - } -}; - -#endif /* FRAMEWORK_TMSTORAGE_TMSTOREINFO_H_ */ diff --git a/tmstorage/TmStoreManager.cpp b/tmstorage/TmStoreManager.cpp deleted file mode 100644 index 61891fa6..00000000 --- a/tmstorage/TmStoreManager.cpp +++ /dev/null @@ -1,511 +0,0 @@ -/* - * TmStoreManager.cpp - * - * Created on: 18.02.2015 - * Author: baetz - */ - -#include -#include -#include -#include -#include - -TmStoreManager::TmStoreManager(object_id_t objectId, object_id_t setDumpTarget, - uint8_t setVC, uint32_t setTimeoutMs) : - SystemObject(objectId), backend(NULL), tmForwardStore(NULL), dumpTarget( - setDumpTarget), virtualChannel(setVC), fetchState( - NOTHING_FETCHED), addressOfFetchCandidate(0), deletionStarted( - false), lastAddressToDelete(0), pendingPacketsToDelete(0), state(IDLE), storingEnabled( - false), timeoutMs(setTimeoutMs), ipcStore(NULL), downlinkedPacketsCount( - 0), fullEventThrown(false) { -} - -TmStoreManager::~TmStoreManager() { -} - -ReturnValue_t TmStoreManager::initialize() { - ReturnValue_t result = SystemObject::initialize(); - if (result != RETURN_OK) { - return result; - } - AcceptsTelemetryIF* telemetryDestimation = objectManager->get< - AcceptsTelemetryIF>(dumpTarget); - if (telemetryDestimation == NULL) { - return RETURN_FAILED; - } - tmQueue.setDefaultDestination( - telemetryDestimation->getReportReceptionQueue(virtualChannel)); - tmForwardStore = objectManager->get(objects::TM_STORE); - if (tmForwardStore == NULL) { - return RETURN_FAILED; - } - result = backend->initialize(); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - ipcStore = objectManager->get(objects::IPC_STORE); - if (ipcStore == NULL) { - return RETURN_FAILED; - } - return matcher.initialize(); -} - -ReturnValue_t TmStoreManager::fetchPackets(ApidSsc start, ApidSsc end) { - //Check mode, store ids, start fetching. - if (state != IDLE) { - return BUSY; - } - if (start.apid < SpacePacketBase::LIMIT_APID) { - firstPacketToFetch = start; - fetchCandidate.apid = start.apid; - fetchState = NOTHING_FETCHED; - } else { - firstPacketToFetch.apid = SpacePacketBase::LIMIT_APID; - firstPacketToFetch.ssc = 0; - //There's no start defined, so we're in range automatically. - fetchState = IN_RANGE; - } - if (end.apid < SpacePacketBase::LIMIT_APID) { - lastPacketToFetch = end; - } else { - lastPacketToFetch.apid = SpacePacketBase::LIMIT_APID; - lastPacketToFetch.ssc = SpacePacketBase::LIMIT_SEQUENCE_COUNT; - } - //Advanced: start fetching at a certain position - ReturnValue_t result = backend->fetchPackets(); - if (result != RETURN_OK) { - return result; - } - downlinkedPacketsCount = 0; - state = RETRIEVING_PACKETS; - return result; -} - -ReturnValue_t TmStoreManager::performOperation() { - backend->performOperation(); - checkCommandQueue(); - return RETURN_OK; -} - -ReturnValue_t TmStoreManager::packetRetrieved(TmPacketMinimal* packet, - uint32_t address, bool isLastPacket) { - ReturnValue_t result = RETURN_FAILED; - switch (state) { - case DELETING_PACKETS: - result = checkDeletionLimit(packet, address); - break; - case RETRIEVING_PACKETS: - result = checkRetrievalLimit(packet, address); - break; - case GET_OLDEST_PACKET_INFO: { - backend->deleteContent(true, lastAddressToDelete, - pendingPacketsToDelete, packet); - result = LAST_PACKET_FOUND; - } - break; - default: - triggerEvent(TmStoreBackendIF::UNEXPECTED_MSG, 0, packet->getPacketSequenceCount()); - break; - } - switch (result) { - case RETURN_OK: - //We go on. But if lastPacket... - if (isLastPacket) { - //... we'll stop successfully. - replySuccess(); - if (state == DELETING_PACKETS) { - //Store is completely deleted, so we can reset oldest and newest packet. - restDownlinkedPacketCount(); - backend->resetStore(); - } - state = IDLE; - } - break; - case LAST_PACKET_FOUND: - //All ok - replySuccess(); - state = IDLE; - break; - case STOP_FETCH: - //This means, we started a new fetch. Returning STOP_FETCH will stop current scan. Stay in state. - break; - default: - //Some error occurred. - replyFailure(result); - state = IDLE; - break; - } - return result; -} - -ReturnValue_t TmStoreManager::checkRetrievalLimit(TmPacketMinimal* packet, - uint32_t address) { - switch (fetchState) { - case NOTHING_FETCHED: - case BEFORE_RANGE: - if (packet->getAPID() != firstPacketToFetch.apid) { - //Dump all packets of unknown APID. - dumpPacket(packet); - return RETURN_OK; - } - if (packet->getPacketSequenceCount() < firstPacketToFetch.ssc) { - addressOfFetchCandidate = address; - fetchCandidate.ssc = packet->getPacketSequenceCount(); - fetchState = BEFORE_RANGE; - return RETURN_OK; - } else if ((packet->getPacketSequenceCount() == firstPacketToFetch.ssc) - || (fetchState == NOTHING_FETCHED)) { - //We have either found the right packet or one with higher count without having an older packet. So dump. - fetchState = IN_RANGE; - dumpPacket(packet); - if (packet->getPacketSequenceCount() < lastPacketToFetch.ssc) { - return RETURN_OK; - } else { - return LAST_PACKET_FOUND; - } - } else { - //We're in range, but the expected SSC is not in store. So we shall restart from the first older packet. - ReturnValue_t result = backend->fetchPackets(true, - addressOfFetchCandidate); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - fetchState = NOTHING_FETCHED; - firstPacketToFetch = fetchCandidate; - return STOP_FETCH; - } - case IN_RANGE: - dumpPacket(packet); - if ((packet->getAPID() == lastPacketToFetch.apid) - && (packet->getPacketSequenceCount() >= lastPacketToFetch.ssc)) { - return LAST_PACKET_FOUND; - } else { - return RETURN_OK; - } - default: - break; - } - return RETURN_FAILED; -} - -ReturnValue_t TmStoreManager::deletePackets(ApidSsc upTo) { - if (state != IDLE) { - return BUSY; - } - if (upTo.apid >= SpacePacketBase::LIMIT_APID) { - ReturnValue_t result = backend->deleteContent(); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - restDownlinkedPacketCount(); - return result; - } else { - state = DELETING_PACKETS; - restDownlinkedPacketCount(); - lastPacketToDelete = upTo; - deletionStarted = false; - pendingPacketsToDelete = 0; - return backend->fetchPackets(); - } -} - -ReturnValue_t TmStoreManager::checkDeletionLimit(TmPacketMinimal* packet, - uint32_t address) { - uint32_t addressOfLastByte = address + packet->getFullSize(); - if (packet->getAPID() == lastPacketToDelete.apid) { - if (packet->getPacketSequenceCount() < lastPacketToDelete.ssc) { - if (deletionStarted) { - backend->deleteContent(true, lastAddressToDelete, - pendingPacketsToDelete, packet); - pendingPacketsToDelete = 0; - } else { - deletionStarted = true; - } - pendingPacketsToDelete++; - lastAddressToDelete = addressOfLastByte; - return RETURN_OK; - } else if (packet->getPacketSequenceCount() == lastPacketToDelete.ssc) { - lastAddressToDelete = addressOfLastByte; - pendingPacketsToDelete++; - state = GET_OLDEST_PACKET_INFO; - return RETURN_OK; - } else { - return LAST_PACKET_FOUND; - } - } else { - lastAddressToDelete = addressOfLastByte; - pendingPacketsToDelete++; - return RETURN_OK; - } -} - -void TmStoreManager::setBackend(TmStoreBackendIF* backend) { - this->backend = backend; -} - -TmStoreBackendIF* TmStoreManager::getBackend() const { - return backend; -} - -ReturnValue_t TmStoreManager::checkPacket(SpacePacketBase* tmPacket) { - if (!storingEnabled) { - return RETURN_OK; - } - TmPacketMinimal testPacket(tmPacket->getWholeData()); - if (matcher.match(&testPacket)) { - ReturnValue_t result = backend->storePacket(&testPacket); - if (result != HasReturnvaluesIF::RETURN_OK) { - //Generate only one event to avoid full event store loop. - if (!fullEventThrown) { - triggerEvent(TmStoreBackendIF::STORING_FAILED, result, testPacket.getPacketSequenceCount()); - fullEventThrown = true; - } - } else { - fullEventThrown = false; - } - return result; - } else { - return RETURN_OK; - } -} - -void TmStoreManager::dumpPacket(SpacePacketBase* packet) { - store_address_t forwardStoreId; - TmTcMessage message; - ReturnValue_t result = tmForwardStore->addData(&forwardStoreId, - packet->getWholeData(), packet->getFullSize()); - if (result != RETURN_OK) { - triggerEvent(TmStoreBackendIF::TM_DUMP_FAILED, result, packet->getPacketSequenceCount()); - return; - } - message.setStorageId(forwardStoreId); - result = tmQueue.sendToDefault(&message); - if (result != RETURN_OK) { - triggerEvent(TmStoreBackendIF::TM_DUMP_FAILED, result, packet->getPacketSequenceCount()); - tmForwardStore->deleteData(forwardStoreId); - return; - } - downlinkedPacketsCount.entry++; -} - -bool TmStoreManager::isEnabled() const { - return storingEnabled; -} - -void TmStoreManager::setEnabled(bool enabled) { - storingEnabled = enabled; -} - -void TmStoreManager::checkCommandQueue() { - if (state != IDLE) { - if (timer.hasTimedOut()) { - replyFailure(TIMEOUT); - state = IDLE; - } - return; - } - CommandMessage message; - for (ReturnValue_t result = commandQueue.receiveMessage(&message); - result == RETURN_OK; - result = commandQueue.receiveMessage(&message)) { - switch (message.getCommand()) { - case TmStoreMessage::ENABLE_STORING: - setEnabled(TmStoreMessage::getEnableStoring(&message)); - replySuccess(); - break; - case TmStoreMessage::CHANGE_SELECTION_DEFINITION: { - uint32_t errorCount = 0; - result = changeSelectionDefinition( - TmStoreMessage::getAddToSelection(&message), - TmStoreMessage::getStoreId(&message), &errorCount); - if (result != RETURN_OK) { - replyFailure(result, errorCount); - } else { - replySuccess(); - } - break; - } - case TmStoreMessage::DOWNLINK_STORE_CONTENT: - result = fetchPackets(TmStoreMessage::getPacketId1(&message), - TmStoreMessage::getPacketId2(&message)); - if (result != RETURN_OK) { - if (result == TmStoreBackendIF::EMPTY) { - replySuccess(); - } else { - replyFailure(result); - } - } else { - timer.setTimeout(timeoutMs); - } - break; - case TmStoreMessage::DELETE_STORE_CONTENT: - result = deletePackets(TmStoreMessage::getPacketId1(&message)); - if (result == RETURN_OK) { - if (state == IDLE) { - //We're finished - replySuccess(); - } else { - timer.setTimeout(timeoutMs); - } - } else { - replyFailure(result); - } - break; - case TmStoreMessage::REPORT_SELECTION_DEFINITION: - result = sendMatchTree(); - if (result != RETURN_OK) { - replyFailure(result); - } - break; - case TmStoreMessage::REPORT_STORE_CATALOGUE: - result = sendStatistics(); - if (result != RETURN_OK) { - replyFailure(result); - } - break; - default: - replyFailure(CommandMessage::UNKNOW_COMMAND, message.getCommand()); - break; - } - } -} - -void TmStoreManager::replySuccess() { - CommandMessage reply(CommandMessage::REPLY_COMMAND_OK, 0, 0); - commandQueue.reply(&reply); - -} - -MessageQueueId_t TmStoreManager::getCommandQueue() { - return commandQueue.getId(); -} - -void TmStoreManager::replyFailure(ReturnValue_t errorCode, uint32_t parameter) { - CommandMessage reply(CommandMessage::REPLY_REJECTED, errorCode, parameter); - commandQueue.reply(&reply); -} - -ReturnValue_t TmStoreManager::changeSelectionDefinition(bool addSelection, - store_address_t storeId, uint32_t* errorCount) { - const uint8_t* pData; - uint32_t size = 0; - ReturnValue_t result = ipcStore->getData(storeId, &pData, &size); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - int32_t iSize = size; - ChangeSelectionDefinition content; - result = content.deSerialize(&pData, &iSize, true); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - ReturnValue_t totalResult = RETURN_OK; - if (content.serviceList.size == 0) { - return updateMatch(addSelection, content.apid, NO_SERVICE, - NO_SUBSERVICE); - } - for (auto iter = content.serviceList.begin(); - iter != content.serviceList.end(); iter++) { - if (iter->subservices.size == 0) { - result = updateMatch(addSelection, content.apid, - iter->service, NO_SUBSERVICE); - if (result != HasReturnvaluesIF::RETURN_OK) { - totalResult = result; - (*errorCount)++; - } - } else { - for (auto iter2 = iter->subservices.begin(); - iter2 != iter->subservices.end(); iter2++) { - result = updateMatch(addSelection, content.apid, - iter->service, *(iter2.value)); - if (result != HasReturnvaluesIF::RETURN_OK) { - totalResult = result; - (*errorCount)++; - } - } - } - } - return totalResult; -} - -ReturnValue_t TmStoreManager::sendMatchTree() { - store_address_t storeId; - uint8_t* buffer; - uint32_t maxSize = matcher.getSerializedSize(); - ReturnValue_t result = ipcStore->getFreeElement(&storeId, maxSize, &buffer); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - uint32_t size = 0; - result = matcher.serialize(&buffer, &size, maxSize, true); - if (result != HasReturnvaluesIF::RETURN_OK) { - ipcStore->deleteData(storeId); - return result; - } - CommandMessage reply; - TmStoreMessage::setSelectionDefinitionReportMessage(&reply, storeId); - result = commandQueue.reply(&reply); - if (result != RETURN_OK) { - ipcStore->deleteData(storeId); - } - return result; -} - -void TmStoreManager::restDownlinkedPacketCount() { - downlinkedPacketsCount = 0; -} - -ReturnValue_t TmStoreManager::updateMatch(bool addSelection, uint16_t apid, uint8_t serviceType, - uint8_t serviceSubtype) { - return matcher.changeMatch(addSelection, apid, serviceType, serviceSubtype); -} - -void TmStoreManager::handleRetrievalFailed(ReturnValue_t errorCode, - uint32_t parameter1, uint32_t parameter2) { - restDownlinkedPacketCount(); - state = IDLE; - replyFailure(errorCode, parameter1); -} - -ReturnValue_t TmStoreManager::sendStatistics() { - LinkedElement linkedOldestPacket(backend->getOldestPacket()); - LinkedElement linkedYoungestPacket( - backend->getYoungestPacket()); - SerializeElement percentageFilled(backend->getPercentageFilled()); - float pDownlinked = - (backend->getStoredPacketsCount() != 0) ? - (float) downlinkedPacketsCount - / (float) backend->getStoredPacketsCount() : - 0.0; - SerializeElement percentageDownlinked(pDownlinked); - SerializeElement storedPacketsCount( - backend->getStoredPacketsCount()); - linkedOldestPacket.setNext(&linkedYoungestPacket); - linkedYoungestPacket.setNext(&percentageFilled); - percentageFilled.setNext(&percentageDownlinked); - percentageDownlinked.setNext(&storedPacketsCount); - storedPacketsCount.setNext(&downlinkedPacketsCount); - store_address_t storeId; - uint8_t* buffer; - uint32_t maxSize = SerialLinkedListAdapter::getSerializedSize( - &linkedOldestPacket); - ReturnValue_t result = ipcStore->getFreeElement(&storeId, maxSize, &buffer); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - uint32_t size = 0; - result = SerialLinkedListAdapter::serialize( - &linkedOldestPacket, &buffer, &size, maxSize, true); - if (result != HasReturnvaluesIF::RETURN_OK) { - ipcStore->deleteData(storeId); - return result; - } - CommandMessage reply; - TmStoreMessage::setStoreCatalogueReportMessage(&reply, storeId); - result = commandQueue.reply(&reply); - if (result != RETURN_OK) { - ipcStore->deleteData(storeId); - } - return result; -} diff --git a/tmstorage/TmStoreManager.h b/tmstorage/TmStoreManager.h deleted file mode 100644 index 7f1ffd62..00000000 --- a/tmstorage/TmStoreManager.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * TmStoreManager.h - * - * Created on: 18.02.2015 - * Author: baetz - */ - -#ifndef PLATFORM_TMTCSERVICES_TMSTOREMANAGER_H_ -#define PLATFORM_TMTCSERVICES_TMSTOREMANAGER_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class TmStoreManager : public SystemObject, public HasReturnvaluesIF, public TmStoreFrontendIF { -public: - TmStoreManager(object_id_t objectId, object_id_t setDumpTarget, uint8_t setVC, uint32_t setTimeoutMs); - virtual ~TmStoreManager(); - ReturnValue_t fetchPackets(ApidSsc start, ApidSsc end); - ReturnValue_t deletePackets(ApidSsc upTo); - ReturnValue_t checkPacket(SpacePacketBase* tmPacket); - ReturnValue_t performOperation(); - ReturnValue_t initialize(); - ReturnValue_t packetRetrieved(TmPacketMinimal* packet, uint32_t address, bool isLastPacket = false); - void handleRetrievalFailed(ReturnValue_t errorCode, uint32_t parameter1 = 0, uint32_t parameter2 = 0); - bool isEnabled() const; - void setEnabled(bool enabled); - void setBackend(TmStoreBackendIF* backend); - TmStoreBackendIF* getBackend() const; - MessageQueueId_t getCommandQueue(); - ReturnValue_t updateMatch(bool addSelection, uint16_t apid, uint8_t serviceType, uint8_t serviceSubtype); -private: - MessageQueue commandQueue; - TmStoreBackendIF* backend; - StorageManagerIF* tmForwardStore; - MessageQueueSender tmQueue; - const object_id_t dumpTarget; - const uint8_t virtualChannel; - enum FetchState { - NOTHING_FETCHED, - BEFORE_RANGE, - IN_RANGE - }; - FetchState fetchState; - ApidSsc firstPacketToFetch; - ApidSsc lastPacketToFetch; - uint32_t addressOfFetchCandidate; - ApidSsc fetchCandidate; - bool deletionStarted; - ApidSsc lastPacketToDelete; - uint32_t lastAddressToDelete; - uint32_t pendingPacketsToDelete; - TmPacketInformation pendingOldestPacket; - enum State { - IDLE, - DELETING_PACKETS, - RETRIEVING_PACKETS, - GET_OLDEST_PACKET_INFO - }; - State state; - bool storingEnabled; - const uint32_t timeoutMs; - Countdown timer; - PacketMatchTree matcher; - StorageManagerIF* ipcStore; - SerializeElement downlinkedPacketsCount; - bool fullEventThrown; - ReturnValue_t checkRetrievalLimit(TmPacketMinimal* packet, uint32_t address); - ReturnValue_t checkDeletionLimit(TmPacketMinimal* packet, uint32_t address); - void dumpPacket(SpacePacketBase* packet); - void checkCommandQueue(); - void replySuccess(); - void replyFailure(ReturnValue_t errorCode, uint32_t parameter = 0); - ReturnValue_t changeSelectionDefinition(bool addSelection, store_address_t storeId, uint32_t* errorCount); - ReturnValue_t sendMatchTree(); - void restDownlinkedPacketCount(); - ReturnValue_t sendStatistics(); - static const uint8_t NO_SERVICE = 0; - static const uint8_t NO_SUBSERVICE = 0; -}; - -#endif /* PLATFORM_TMTCSERVICES_TMSTOREMANAGER_H_ */ diff --git a/tmstorage/TmStoreMessage.cpp b/tmstorage/TmStoreMessage.cpp index edf37bf8..4509ba91 100644 --- a/tmstorage/TmStoreMessage.cpp +++ b/tmstorage/TmStoreMessage.cpp @@ -1,10 +1,3 @@ -/* - * TmStoreMessage.cpp - * - * Created on: 23.02.2015 - * Author: baetz - */ - #include #include @@ -23,30 +16,30 @@ ReturnValue_t TmStoreMessage::setEnableStoringMessage(CommandMessage* cmd, } ReturnValue_t TmStoreMessage::setDeleteContentMessage(CommandMessage* cmd, - TmStoreFrontendIF::ApidSsc upTo) { + ApidSsc upTo) { cmd->setCommand(DELETE_STORE_CONTENT); cmd->setParameter((upTo.apid<<16) + upTo.ssc); return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t TmStoreMessage::setDownlinkContentMessage(CommandMessage* cmd, - TmStoreFrontendIF::ApidSsc fromPacket, - TmStoreFrontendIF::ApidSsc toPacket) { + ApidSsc fromPacket, + ApidSsc toPacket) { cmd->setCommand(DOWNLINK_STORE_CONTENT); cmd->setParameter((fromPacket.apid<<16) + fromPacket.ssc); cmd->setParameter2((toPacket.apid<<16) + toPacket.ssc); return HasReturnvaluesIF::RETURN_OK; } -TmStoreFrontendIF::ApidSsc TmStoreMessage::getPacketId1(CommandMessage* cmd) { - TmStoreFrontendIF::ApidSsc temp; +ApidSsc TmStoreMessage::getPacketId1(CommandMessage* cmd) { + ApidSsc temp; temp.apid = (cmd->getParameter() >> 16) & 0xFFFF; temp.ssc = cmd->getParameter() & 0xFFFF; return temp; } -TmStoreFrontendIF::ApidSsc TmStoreMessage::getPacketId2(CommandMessage* cmd) { - TmStoreFrontendIF::ApidSsc temp; +ApidSsc TmStoreMessage::getPacketId2(CommandMessage* cmd) { + ApidSsc temp; temp.apid = (cmd->getParameter2() >> 16) & 0xFFFF; temp.ssc = cmd->getParameter2() & 0xFFFF; return temp; @@ -67,13 +60,23 @@ void TmStoreMessage::clear(CommandMessage* cmd) { switch(cmd->getCommand()) { case SELECTION_DEFINITION_REPORT: case STORE_CATALOGUE_REPORT: - case CHANGE_SELECTION_DEFINITION: { + case CHANGE_SELECTION_DEFINITION: + case INDEX_REPORT: + case DELETE_STORE_CONTENT_TIME: + case DOWNLINK_STORE_CONTENT_TIME: { StorageManagerIF *ipcStore = objectManager->get( objects::IPC_STORE); if (ipcStore != NULL) { ipcStore->deleteData(getStoreId(cmd)); } } + /* NO BREAK falls through*/ + case DELETE_STORE_CONTENT_BLOCKS: + case DOWNLINK_STORE_CONTENT_BLOCKS: + case REPORT_INDEX_REQUEST: + cmd->setCommand(UNKNOW_COMMAND); + cmd->setParameter(0); + cmd->setParameter2(0); break; default: break; @@ -108,8 +111,55 @@ ReturnValue_t TmStoreMessage::setReportStoreCatalogueMessage( return HasReturnvaluesIF::RETURN_OK; } -void TmStoreMessage::setStoreCatalogueReportMessage(CommandMessage* cmd, +void TmStoreMessage::setStoreCatalogueReportMessage(CommandMessage* cmd, object_id_t objectId, store_address_t storeId) { cmd->setCommand(STORE_CATALOGUE_REPORT); + cmd->setParameter(objectId); + cmd->setParameter2(storeId.raw); +} + +object_id_t TmStoreMessage::getObjectId(CommandMessage* cmd) { + return cmd->getParameter(); +} + +void TmStoreMessage::setDownlinkContentTimeMessage(CommandMessage* cmd, + store_address_t storeId) { + cmd->setCommand(DOWNLINK_STORE_CONTENT_TIME); + cmd->setParameter2(storeId.raw); +} + +uint32_t TmStoreMessage::getAddressLow(CommandMessage* cmd){ + return cmd->getParameter(); +} +uint32_t TmStoreMessage::getAddressHigh(CommandMessage* cmd){ + return cmd->getParameter2(); +} + +void TmStoreMessage::setDeleteContentTimeMessage(CommandMessage* cmd, + store_address_t storeId) { + cmd->setCommand(DELETE_STORE_CONTENT_TIME); + cmd->setParameter2(storeId.raw); +} + +ReturnValue_t TmStoreMessage::setDeleteBlocksMessage(CommandMessage* cmd, uint32_t addressLow, uint32_t addressHigh){ + cmd->setCommand(DELETE_STORE_CONTENT_BLOCKS); + cmd->setParameter(addressLow); + cmd->setParameter2(addressHigh); + return HasReturnvaluesIF::RETURN_OK; +} +ReturnValue_t TmStoreMessage::setDownlinkBlocksMessage(CommandMessage* cmd, uint32_t addressLow, uint32_t addressHigh){ + cmd->setCommand(DOWNLINK_STORE_CONTENT_BLOCKS); + cmd->setParameter(addressLow); + cmd->setParameter2(addressHigh); + return HasReturnvaluesIF::RETURN_OK; +} +ReturnValue_t TmStoreMessage::setIndexRequestMessage(CommandMessage* cmd){ + cmd->setCommand(REPORT_INDEX_REQUEST); + return HasReturnvaluesIF::RETURN_OK; +} + + +void TmStoreMessage::setIndexReportMessage(CommandMessage* cmd, store_address_t storeId){ + cmd->setCommand(INDEX_REPORT); cmd->setParameter2(storeId.raw); } diff --git a/tmstorage/TmStoreMessage.h b/tmstorage/TmStoreMessage.h index 436895c5..0883063c 100644 --- a/tmstorage/TmStoreMessage.h +++ b/tmstorage/TmStoreMessage.h @@ -1,35 +1,47 @@ -/* - * TmStoreMessage.h - * - * Created on: 23.02.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_TMSTORAGE_TMSTOREMESSAGE_H_ #define FRAMEWORK_TMSTORAGE_TMSTOREMESSAGE_H_ #include #include -#include - +#include +#include class TmStoreMessage: public CommandMessage { public: - static ReturnValue_t setEnableStoringMessage(CommandMessage* cmd, bool setEnabled); - static ReturnValue_t setDeleteContentMessage(CommandMessage* cmd, TmStoreFrontendIF::ApidSsc upTo); - static ReturnValue_t setDownlinkContentMessage(CommandMessage* cmd, TmStoreFrontendIF::ApidSsc fromPacket, TmStoreFrontendIF::ApidSsc toPacket ); - static void setChangeSelectionDefinitionMessage(CommandMessage* cmd, bool addDefinition, store_address_t store_id); - static ReturnValue_t setReportSelectionDefinitionMessage(CommandMessage* cmd); - static void setSelectionDefinitionReportMessage(CommandMessage* cmd, store_address_t storeId); + static ReturnValue_t setEnableStoringMessage(CommandMessage* cmd, + bool setEnabled); + static ReturnValue_t setDeleteContentMessage(CommandMessage* cmd, + ApidSsc upTo); + static ReturnValue_t setDownlinkContentMessage(CommandMessage* cmd, + ApidSsc fromPacket, ApidSsc toPacket); + static void setChangeSelectionDefinitionMessage(CommandMessage* cmd, + bool addDefinition, store_address_t store_id); + static ReturnValue_t setReportSelectionDefinitionMessage( + CommandMessage* cmd); + static void setSelectionDefinitionReportMessage(CommandMessage* cmd, + store_address_t storeId); static ReturnValue_t setReportStoreCatalogueMessage(CommandMessage* cmd); - static void setStoreCatalogueReportMessage(CommandMessage* cmd, store_address_t storeId); + static void setStoreCatalogueReportMessage(CommandMessage* cmd, object_id_t objectId, + store_address_t storeId); + static void setDownlinkContentTimeMessage(CommandMessage* cmd, + store_address_t storeId); + static void setIndexReportMessage(CommandMessage* cmd, store_address_t storeId); + static ReturnValue_t setDeleteBlocksMessage(CommandMessage* cmd, uint32_t addressLow, uint32_t addressHigh); + static ReturnValue_t setDownlinkBlocksMessage(CommandMessage* cmd, uint32_t addressLow, uint32_t addressHigh); + static ReturnValue_t setIndexRequestMessage(CommandMessage* cmd); + static void setDeleteContentTimeMessage(CommandMessage* cmd, + store_address_t storeId); static void clear(CommandMessage* cmd); - static TmStoreFrontendIF::ApidSsc getPacketId1(CommandMessage* cmd); - static TmStoreFrontendIF::ApidSsc getPacketId2(CommandMessage* cmd); + static object_id_t getObjectId(CommandMessage* cmd); + static ApidSsc getPacketId1(CommandMessage* cmd); + static ApidSsc getPacketId2(CommandMessage* cmd); static bool getEnableStoring(CommandMessage* cmd); static bool getAddToSelection(CommandMessage* cmd); + static uint32_t getAddressLow(CommandMessage* cmd); + static uint32_t getAddressHigh(CommandMessage* cmd); + static store_address_t getStoreId(const CommandMessage* cmd); virtual ~TmStoreMessage(); - static const uint8_t MESSAGE_ID = TM_STORE_MESSAGE_ID; + static const uint8_t MESSAGE_ID = MESSAGE_TYPE::TM_STORE; static const Command_t ENABLE_STORING = MAKE_COMMAND_ID(1); static const Command_t DELETE_STORE_CONTENT = MAKE_COMMAND_ID(2); static const Command_t DOWNLINK_STORE_CONTENT = MAKE_COMMAND_ID(3); @@ -38,6 +50,12 @@ public: static const Command_t SELECTION_DEFINITION_REPORT = MAKE_COMMAND_ID(6); static const Command_t REPORT_STORE_CATALOGUE = MAKE_COMMAND_ID(7); static const Command_t STORE_CATALOGUE_REPORT = MAKE_COMMAND_ID(8); + static const Command_t DOWNLINK_STORE_CONTENT_TIME = MAKE_COMMAND_ID(9); + static const Command_t DELETE_STORE_CONTENT_TIME = MAKE_COMMAND_ID(10); + static const Command_t DELETE_STORE_CONTENT_BLOCKS = MAKE_COMMAND_ID(11); + static const Command_t DOWNLINK_STORE_CONTENT_BLOCKS = MAKE_COMMAND_ID(12); + static const Command_t REPORT_INDEX_REQUEST = MAKE_COMMAND_ID(13); + static const Command_t INDEX_REPORT = MAKE_COMMAND_ID(14); private: TmStoreMessage(); }; diff --git a/tmstorage/TmStorePackets.h b/tmstorage/TmStorePackets.h index c89d0762..6eea6f58 100644 --- a/tmstorage/TmStorePackets.h +++ b/tmstorage/TmStorePackets.h @@ -1,17 +1,14 @@ -/* - * TmStorePackets.h - * - * Created on: 11.03.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_TMSTORAGE_TMSTOREPACKETS_H_ #define FRAMEWORK_TMSTORAGE_TMSTOREPACKETS_H_ #include #include #include +#include #include +#include +#include +#include class ServiceSubservice: public SerialLinkedListAdapter { public: @@ -25,6 +22,44 @@ public: } }; +class ApidSsc: public SerializeIF { +public: + ApidSsc() : + apid(SpacePacketBase::LIMIT_APID), ssc(0) { + } + ApidSsc(uint16_t apid, uint16_t ssc) : + apid(apid), ssc(ssc) { + } + uint16_t apid; + uint16_t ssc; + ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, + const uint32_t max_size, bool bigEndian) const { + ReturnValue_t result = SerializeAdapter::serialize(&apid, + buffer, size, max_size, bigEndian); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return SerializeAdapter::serialize(&ssc, buffer, size, + max_size, bigEndian); + + } + + uint32_t getSerializedSize() const { + return sizeof(apid) + sizeof(ssc); + } + + ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, + bool bigEndian) { + ReturnValue_t result = SerializeAdapter::deSerialize(&apid, + buffer, size, bigEndian); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return SerializeAdapter::deSerialize(&ssc, buffer, size, + bigEndian); + } +}; + class ChangeSelectionDefinition: public SerialLinkedListAdapter { public: SerializeElement apid; @@ -37,18 +72,14 @@ public: } }; -class TmPacketInformation: public SerialLinkedListAdapter { +class TmPacketInformation: public SerializeIF { public: - TmPacketInformation(TmPacketMinimal* packet) : - SerialLinkedListAdapter(&apid) { - setAllNext(); + TmPacketInformation(TmPacketMinimal* packet){ setContent(packet); } - TmPacketInformation() : - SerialLinkedListAdapter(&apid), apid( + TmPacketInformation() :apid( SpacePacketBase::LIMIT_APID), sourceSequenceCount(0), serviceType( 0), serviceSubtype(0), subCounter(0) { - setAllNext(); } void reset() { apid = SpacePacketBase::LIMIT_APID; @@ -56,6 +87,7 @@ public: serviceType = 0; serviceSubtype = 0; subCounter = 0; + memset(rawTimestamp, 0, sizeof(rawTimestamp)); } void setContent(TmPacketMinimal* packet) { apid = packet->getAPID(); @@ -63,29 +95,206 @@ public: serviceType = packet->getService(); serviceSubtype = packet->getSubService(); subCounter = packet->getPacketSubcounter(); + memset(rawTimestamp, 0, sizeof(rawTimestamp)); + const uint8_t* pField = NULL; + uint32_t size = 0; + ReturnValue_t result = packet->getPacketTimeRaw(&pField, &size); + if (result != HasReturnvaluesIF::RETURN_OK) { + return; + } + if (*pField == CCSDSTime::P_FIELD_CDS_SHORT + && size <= TimeStamperIF::MISSION_TIMESTAMP_SIZE) { + //Shortcut to avoid converting CDS back and forth. + memcpy(rawTimestamp, pField, size); + return; + } + timeval time = { 0, 0 }; + result = packet->getPacketTime(&time); + if (result != HasReturnvaluesIF::RETURN_OK) { + return; + } + + CCSDSTime::CDS_short cdsFormat; + result = CCSDSTime::convertToCcsds(&cdsFormat, &time); + if (result != HasReturnvaluesIF::RETURN_OK) { + return; + } + memcpy(rawTimestamp, &cdsFormat, sizeof(cdsFormat)); } void setContent(TmPacketInformation* content) { - apid.entry = content->apid.entry; - sourceSequenceCount.entry = content->sourceSequenceCount.entry; - serviceType.entry = content->serviceType.entry; - serviceSubtype.entry = content->serviceSubtype.entry; - subCounter.entry = content->subCounter.entry; + apid = content->apid; + sourceSequenceCount = content->sourceSequenceCount; + serviceType = content->serviceType; + serviceSubtype = content->serviceSubtype; + subCounter = content->subCounter; + memcpy(rawTimestamp, content->rawTimestamp, sizeof(rawTimestamp)); } - bool isValid() { + bool isValid() const { return (apid < SpacePacketBase::LIMIT_APID) ? true : false; } -private: - SerializeElement apid; - SerializeElement sourceSequenceCount; - SerializeElement serviceType; - SerializeElement serviceSubtype; - SerializeElement subCounter; - void setAllNext() { - apid.setNext(&sourceSequenceCount); - sourceSequenceCount.setNext(&serviceType); - serviceType.setNext(&serviceSubtype); - serviceSubtype.setNext(&subCounter); + static void reset(TmPacketInformation* packet){ + packet->reset(); } -}; + static bool isOlderThan(const TmPacketInformation* packet, const timeval* cmpTime){ + if(packet->isValid()){ + timeval packetTime = {0,0}; + uint32_t foundlen = 0; + CCSDSTime::convertFromCcsds(&packetTime,&packet->rawTimestamp[0],&foundlen,sizeof(rawTimestamp)); + if(packetTime <= *cmpTime){ + return true; + } + } + return false; + } + + static bool isNewerThan(const TmPacketInformation* packet, const timeval* cmpTime){ + if(packet->isValid()){ + timeval packetTime = {0,0}; + uint32_t foundlen = 0; + CCSDSTime::convertFromCcsds(&packetTime,&packet->rawTimestamp[0],&foundlen,sizeof(rawTimestamp)); + if(packetTime >= *cmpTime){ + return true; + } + } + return false; + } + + static bool isSmallerSSC(const TmPacketInformation* packet,const ApidSsc* compareSSC){ + if(packet->isValid()){ + if(packet->apid == compareSSC->apid){ + if(packet->sourceSequenceCount <= compareSSC->ssc){ + return true; + } + } + } + return false; + } + + static bool isLargerSSC(const TmPacketInformation* packet,const ApidSsc* compareSSC){ + if(packet->isValid()){ + if(packet->apid == compareSSC->apid){ + if(packet->sourceSequenceCount >= compareSSC->ssc){ + return true; + } + } + } + return false; + } + + uint16_t getApid() const{ + return apid; + } + + uint16_t getSsc() const{ + return sourceSequenceCount; + } + + uint8_t getServiceType() const{ + return serviceType; + } + + uint8_t getServiceSubtype() const{ + return serviceSubtype; + } + + uint8_t getSubCounter() const{ + return subCounter; + } + + timeval getTime() const { + timeval packetTime = {0,0}; + uint32_t foundlen = 0; + CCSDSTime::convertFromCcsds(&packetTime,&this->rawTimestamp[0],&foundlen,sizeof(rawTimestamp)); + return packetTime; + } + + bool operator==(const TmPacketInformation& other) { + //TODO Does not compare Raw Timestamp + return ((apid == other.getApid()) + && (sourceSequenceCount == other.getSsc()) + && (serviceType == other.getServiceType()) && (serviceSubtype = + other.getServiceSubtype())); + } + + + ReturnValue_t serialize(uint8_t** buffer, uint32_t* size, + const uint32_t max_size, bool bigEndian) const { + ReturnValue_t result = AutoSerializeAdapter::serialize(&apid,buffer,size,max_size,bigEndian); + if(result!=HasReturnvaluesIF::RETURN_OK){ + return result; + } + result = AutoSerializeAdapter::serialize(&sourceSequenceCount,buffer,size,max_size,bigEndian); + if(result!=HasReturnvaluesIF::RETURN_OK){ + return result; + } + result = AutoSerializeAdapter::serialize(&serviceType,buffer,size,max_size,bigEndian); + if(result!=HasReturnvaluesIF::RETURN_OK){ + return result; + } + result = AutoSerializeAdapter::serialize(&serviceSubtype,buffer,size,max_size,bigEndian); + if(result!=HasReturnvaluesIF::RETURN_OK){ + return result; + } + result = AutoSerializeAdapter::serialize(&subCounter,buffer,size,max_size,bigEndian); + if(result!=HasReturnvaluesIF::RETURN_OK){ + return result; + } + SerialBufferAdapter adapter(rawTimestamp,sizeof(rawTimestamp)); + return adapter.serialize(buffer,size,max_size,bigEndian); + } + + uint32_t getSerializedSize() const { + uint32_t size = 0; + size += AutoSerializeAdapter::getSerializedSize(&apid); + size += AutoSerializeAdapter::getSerializedSize(&sourceSequenceCount); + size += AutoSerializeAdapter::getSerializedSize(&serviceType); + size += AutoSerializeAdapter::getSerializedSize(&serviceSubtype); + size += AutoSerializeAdapter::getSerializedSize(&subCounter); + SerialBufferAdapter adapter(rawTimestamp,sizeof(rawTimestamp)); + size += adapter.getSerializedSize(); + return size; + + }; + + ReturnValue_t deSerialize(const uint8_t** buffer, int32_t* size, + bool bigEndian) { + ReturnValue_t result = AutoSerializeAdapter::deSerialize(&apid, buffer, + size, bigEndian); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = AutoSerializeAdapter::deSerialize(&sourceSequenceCount, buffer, + size, bigEndian); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = AutoSerializeAdapter::deSerialize(&serviceType, buffer, size, + bigEndian); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = AutoSerializeAdapter::deSerialize(&serviceSubtype, buffer, + size, bigEndian); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = AutoSerializeAdapter::deSerialize(&subCounter, buffer, size, + bigEndian); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + SerialBufferAdapter adapter(rawTimestamp,sizeof(rawTimestamp)); + return adapter.deSerialize(buffer,size,bigEndian); + } + +private: + uint16_t apid; + uint16_t sourceSequenceCount; + uint8_t serviceType; + uint8_t serviceSubtype; + uint8_t subCounter; + uint8_t rawTimestamp[TimeStamperIF::MISSION_TIMESTAMP_SIZE]; + +}; #endif /* FRAMEWORK_TMSTORAGE_TMSTOREPACKETS_H_ */ diff --git a/tmtcpacket/Makefile b/tmtcpacket/Makefile deleted file mode 100755 index 5559931d..00000000 --- a/tmtcpacket/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash -# -# OSAL makefile -# -# Created on: Mar 04, 2010 -# Author: ziemke -# Author: Claas Ziemke -# Copyright 2010, Claas Ziemke -# - -BASEDIR=../../ -include $(BASEDIR)options.mk - -OBJ = $(BUILDDIR)/SpacePacketBase.o \ - $(BUILDDIR)/SpacePacket.o - - -all: $(OBJ) - -$(BUILDDIR)/%.o: %.cpp %.h - $(CPP) $(CFLAGS) $(DEFINES) $(CCOPT) ${INCLUDE} -c $< -o $@ - -clean: - $(RM) *.o *.gcno *.gcda diff --git a/tmtcpacket/SpacePacket.cpp b/tmtcpacket/SpacePacket.cpp index 3479bddf..d9bc08fa 100644 --- a/tmtcpacket/SpacePacket.cpp +++ b/tmtcpacket/SpacePacket.cpp @@ -1,28 +1,16 @@ -/* - * SpacePacket.cpp - * - * Created on: Mar 23, 2012 - * Author: baetz - */ - #include #include #include #include -SpacePacket::SpacePacket( uint16_t set_packet_data_length, uint8_t set_type, uint16_t new_apid, uint16_t set_count ): -SpacePacketBase( (uint8_t*)&this->local_data ) { - //reset everything to zero: - memset(this->local_data.byteStream,0 , sizeof(this->local_data.byteStream) ); - //Primary header: - this->local_data.fields.header.packet_id_h = 0b00000000 + ( (set_type & 0b1) << 4 ); - this->setAPID( new_apid ); - this->local_data.fields.header.sequence_control_h = 0b11000000; - this->setPacketSequenceCount(set_count); - if ( set_packet_data_length <= sizeof(this->local_data.fields.buffer) ) { - this->setPacketDataLength(set_packet_data_length); +SpacePacket::SpacePacket( uint16_t packetDataLength, bool isTelecommand, uint16_t apid, uint16_t sequenceCount ): +SpacePacketBase( (uint8_t*)&this->localData ) { + initSpacePacketHeader(isTelecommand, false, apid, sequenceCount); + this->setPacketSequenceCount(sequenceCount); + if ( packetDataLength <= sizeof(this->localData.fields.buffer) ) { + this->setPacketDataLength(packetDataLength); } else { - this->setPacketDataLength( sizeof(this->local_data.fields.buffer) ); + this->setPacketDataLength( sizeof(this->localData.fields.buffer) ); } } @@ -31,7 +19,7 @@ SpacePacket::~SpacePacket( void ) { bool SpacePacket::addWholeData( const uint8_t* p_Data, uint32_t packet_size ) { if ( packet_size <= sizeof(this->data) ) { - memcpy( &this->local_data.byteStream, p_Data, packet_size ); + memcpy( &this->localData.byteStream, p_Data, packet_size ); return true; } else { return false; diff --git a/tmtcpacket/SpacePacket.h b/tmtcpacket/SpacePacket.h index 4dd0630c..f2d45752 100644 --- a/tmtcpacket/SpacePacket.h +++ b/tmtcpacket/SpacePacket.h @@ -13,21 +13,19 @@ * so the parent's methods are reachable. * @ingroup tmtcpackets */ -class SpacePacket : public SpacePacketBase { - public: - static const uint16_t PACKET_MAX_SIZE = 1024; +class SpacePacket: public SpacePacketBase { +public: + static const uint16_t PACKET_MAX_SIZE = 1024; /** * The constructor initializes the packet and sets all header information * according to the passed parameters. - * @param set_packet_data_length Sets the packet data length field and - * therefore specifies the size of the packet. - * @param set_type Sets the packet type field to either 0 (TM) or 1 (TC). - * @param set_apid Sets the packet's APID field. The default value - * describes an idle packet. - * @param set_sequence_count Sets the packet's Source Sequence Count - * field. + * @param packetDataLength Sets the packet data length field and therefore specifies the size of the packet. + * @param isTelecommand Sets the packet type field to either TC (true) or TM (false). + * @param apid Sets the packet's APID field. The default value describes an idle packet. + * @param sequenceCount ets the packet's Source Sequence Count field. */ - SpacePacket( uint16_t set_packet_data_length, uint8_t set_type = 0, uint16_t set_apid = APID_IDLE_PACKET, uint16_t set_sequence_count = 0 ); + SpacePacket(uint16_t packetDataLength, bool isTelecommand = false, + uint16_t apid = APID_IDLE_PACKET, uint16_t sequenceCount = 0); /** * The class's default destructor. */ @@ -40,7 +38,7 @@ class SpacePacket : public SpacePacketBase { * @return @li \c true if packet_size is smaller than \c MAX_PACKET_SIZE. * @li \c false else. */ - bool addWholeData( const uint8_t* p_data, uint32_t packet_size ); + bool addWholeData(const uint8_t* p_data, uint32_t packet_size); protected: /** * This structure defines the data structure of a Space Packet as local data. @@ -66,7 +64,7 @@ protected: * packed in an union, so the data can be accessed as a byte stream without * a cast. */ - SpacePacketData local_data; + SpacePacketData localData; }; #endif /* SPACEPACKET_H_ */ diff --git a/tmtcpacket/SpacePacketBase.cpp b/tmtcpacket/SpacePacketBase.cpp index c148bcc2..13c062d8 100644 --- a/tmtcpacket/SpacePacketBase.cpp +++ b/tmtcpacket/SpacePacketBase.cpp @@ -1,11 +1,7 @@ -/* - * SpacePacketBase.cpp - * - * Created on: 21.03.2012 - * Author: baetz - */ #include #include +#include + SpacePacketBase::SpacePacketBase( const uint8_t* set_address ) { this->data = (SpacePacketPointer*) set_address; } @@ -18,6 +14,20 @@ uint8_t SpacePacketBase::getPacketVersionNumber( void ) { return (this->data->header.packet_id_h & 0b11100000) >> 5; } +void SpacePacketBase::initSpacePacketHeader(bool isTelecommand, bool hasSecondaryHeader, uint16_t apid, uint16_t sequenceCount) { + //reset header to zero: + memset(data,0, sizeof(this->data->header) ); + //Set TC/TM bit. + data->header.packet_id_h = ((isTelecommand? 1 : 0)) << 4; + //Set secondaryHeader bit + data->header.packet_id_h |= ((hasSecondaryHeader? 1 : 0)) << 3; + this->setAPID( apid ); + //Always initialize as standalone packets. + data->header.sequence_control_h = 0b11000000; + setPacketSequenceCount(sequenceCount); + +} + bool SpacePacketBase::isTelecommand( void ) { return (this->data->header.packet_id_h & 0b00010000) >> 4; } @@ -31,7 +41,7 @@ uint16_t SpacePacketBase::getPacketId() { this->data->header.packet_id_l; } -uint16_t SpacePacketBase::getAPID( void ) { +uint16_t SpacePacketBase::getAPID( void ) const { return ( (this->data->header.packet_id_h & 0b00000111) << 8 ) + this->data->header.packet_id_l; } @@ -51,7 +61,7 @@ uint8_t SpacePacketBase::getSequenceFlags( void ) { return (this->data->header.sequence_control_h & 0b11000000) >> 6 ; } -uint16_t SpacePacketBase::getPacketSequenceCount( void ) { +uint16_t SpacePacketBase::getPacketSequenceCount( void ) const { return ( (this->data->header.sequence_control_h & 0b00111111) << 8 ) + this->data->header.sequence_control_l; } @@ -83,3 +93,11 @@ uint8_t* SpacePacketBase::getWholeData() { void SpacePacketBase::setData( const uint8_t* p_Data ) { this->data = (SpacePacketPointer*)p_Data; } + +uint32_t SpacePacketBase::getApidAndSequenceCount() const { + return (getAPID() << 16) + getPacketSequenceCount(); +} + +uint8_t* SpacePacketBase::getPacketData() { + return &(data->packet_data); +} diff --git a/tmtcpacket/SpacePacketBase.h b/tmtcpacket/SpacePacketBase.h index 5d506a3a..cc68f714 100644 --- a/tmtcpacket/SpacePacketBase.h +++ b/tmtcpacket/SpacePacketBase.h @@ -80,6 +80,8 @@ public: * @return Returns true if the bit is set and false if not. */ bool isTelecommand( void ); + + void initSpacePacketHeader(bool isTelecommand, bool hasSecondaryHeader, uint16_t apid, uint16_t sequenceCount = 0); /** * The CCSDS header provides a secondary header flag (the fifth-highest bit), * which is checked with this method. @@ -97,7 +99,7 @@ public: * id. * @return The CCSDS APID. */ - uint16_t getAPID( void ); + uint16_t getAPID( void ) const; /** * Sets the APID of a packet, which are the lowest 11 bit of the packet * id. @@ -122,7 +124,7 @@ public: * packet sequence control field. * @return The CCSDS sequence count. */ - uint16_t getPacketSequenceCount( void ); + uint16_t getPacketSequenceCount( void ) const; /** * Sets the packet sequence count, which are the lowest 14 bit of the * packet sequence control field. @@ -153,6 +155,8 @@ public: * @return A \c uint8_t pointer to the first byte of the CCSDS primary header. */ virtual uint8_t* getWholeData( void ); + + uint8_t* getPacketData(); /** * With this method, the packet data pointer can be redirected to another * location. @@ -165,6 +169,8 @@ public: */ uint32_t getFullSize(); + uint32_t getApidAndSequenceCount() const; + }; #endif /* SPACEPACKETBASE_H_ */ diff --git a/tmtcpacket/packetmatcher/ApidMatcher.h b/tmtcpacket/packetmatcher/ApidMatcher.h index 9199b7ef..1f194968 100644 --- a/tmtcpacket/packetmatcher/ApidMatcher.h +++ b/tmtcpacket/packetmatcher/ApidMatcher.h @@ -1,10 +1,3 @@ -/* - * ApidMatcher.h - * - * Created on: 09.03.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_TMTCPACKET_PACKETMATCHER_APIDMATCHER_H_ #define FRAMEWORK_TMTCPACKET_PACKETMATCHER_APIDMATCHER_H_ @@ -19,6 +12,9 @@ public: ApidMatcher(uint16_t setApid) : apid(setApid) { } + ApidMatcher(TmPacketMinimal* test) : + apid(test->getAPID()) { + } bool match(TmPacketMinimal* packet) { if (packet->getAPID() == apid) { return true; diff --git a/tmtcpacket/packetmatcher/PacketMatchTree.cpp b/tmtcpacket/packetmatcher/PacketMatchTree.cpp index 859070f2..d8f61ffb 100644 --- a/tmtcpacket/packetmatcher/PacketMatchTree.cpp +++ b/tmtcpacket/packetmatcher/PacketMatchTree.cpp @@ -1,10 +1,3 @@ -/* - * PacketMatchTree.cpp - * - * Created on: 10.03.2015 - * Author: baetz - */ - #include #include #include @@ -31,116 +24,148 @@ PacketMatchTree::~PacketMatchTree() { ReturnValue_t PacketMatchTree::addMatch(uint16_t apid, uint8_t type, uint8_t subtype) { //We assume adding APID is always requested. - uint8_t expectedHierarchy = 0; - if (type != 0) { - expectedHierarchy++; - if (subtype != 0) { - expectedHierarchy++; - } - } TmPacketMinimal::TmPacketMinimalPointer data; data.data_field.service_type = type; data.data_field.service_subtype = subtype; - TmPacketMinimal testPacket((uint8_t*)&data); + TmPacketMinimal testPacket((uint8_t*) &data); testPacket.setAPID(apid); - uint8_t realHierarchy = 0; - iterator lastMatch; - bool isInTree = matchesTree(&testPacket, &lastMatch, &realHierarchy); - if (isInTree) { - //Matches somehow. - //TODO: Are we interested in details? + iterator lastTest; + iterator rollback; + ReturnValue_t result = findOrInsertMatch( + this->begin(), &testPacket, &lastTest); + if (result == NEW_NODE_CREATED) { + rollback = lastTest; + } else if (result != RETURN_OK) { + return result; + } + if (type == 0) { + //Check if lastTest has no children, otherwise, delete them, + //as a more general check is requested. + if (lastTest.left() != this->end()) { + removeElementAndAllChildren(lastTest.left()); + } return RETURN_OK; } - if (expectedHierarchy == realHierarchy) { - //Add another element (of correct type) at the OR branch. - lastMatch = addElement(OR, realHierarchy, lastMatch, &testPacket); - if (lastMatch == this->end()) { - return FULL; + //Type insertion required. + result = findOrInsertMatch( + lastTest.left(), &testPacket, &lastTest); + if (result == NEW_NODE_CREATED) { + if (rollback == this->end()) { + rollback = lastTest; } - } else if (expectedHierarchy > realHierarchy) { - //A certain amount of downward structure does not exist. Add first element as OR, rest as AND. - - lastMatch = addElement(OR, realHierarchy, lastMatch, &testPacket); - if (lastMatch == end()) { - return FULL; + } else if (result != RETURN_OK) { + if (rollback != this->end()) { + removeElementAndAllChildren(rollback); } - iterator firstOfList = lastMatch; - while (lastMatch != end() && realHierarchy < expectedHierarchy) { - realHierarchy++; - lastMatch = addElement(AND, realHierarchy, lastMatch, &testPacket); + return result; + } + if (subtype == 0) { + if (lastTest.left() != this->end()) { + //See above + removeElementAndAllChildren(lastTest.left()); } - if (lastMatch == end()) { - //At least one element could not be inserted. So delete everything. - removeElementAndAllChildren(firstOfList); - return FULL; + return RETURN_OK; + } + //Subtype insertion required. + result = findOrInsertMatch( + lastTest.left(), &testPacket, &lastTest); + if (result == NEW_NODE_CREATED) { + return RETURN_OK; + } else if (result != RETURN_OK) { + if (rollback != this->end()) { + removeElementAndAllChildren(rollback); } - } else { - //Might work like that. - //Too detailed match, delete the last element and all its children. - while (lastMatch.up() != end() && lastMatch.up().left() != lastMatch) { - lastMatch = lastMatch.up(); - } - removeElementAndAllChildren(lastMatch); + return result; } return RETURN_OK; } -ReturnValue_t PacketMatchTree::removeMatch(uint16_t apid, uint8_t type, - uint8_t subtype) { - //We assume APID is always in request. - uint8_t expectedHierarchy = 1; - if (type != 0) { - expectedHierarchy++; - if (subtype != 0) { - expectedHierarchy++; - } - } - TmPacketMinimal::TmPacketMinimalPointer data; - data.data_field.service_type = type; - data.data_field.service_subtype = subtype; - TmPacketMinimal testPacket((uint8_t*)&data); - testPacket.setAPID(apid); - uint8_t realHierarchy = 0; - iterator lastMatch; - bool isInTree = matchesTree(&testPacket, &lastMatch, &realHierarchy); - if (isInTree) { - if (expectedHierarchy == realHierarchy) { - return removeElementAndReconnectChildren(lastMatch); +template +ReturnValue_t PacketMatchTree::findOrInsertMatch(iterator startAt, VALUE_T test, + iterator* lastTest) { + bool attachToBranch = AND; + iterator iter = startAt; + while (iter != this->end()) { + bool isMatch = iter->match(test); + attachToBranch = OR; + *lastTest = iter; + if (isMatch) { + return RETURN_OK; } else { - return TOO_DETAILED_REQUEST; + //Go down OR branch. + iter = iter.right(); } - } else { - //TODO: Maybe refine this a bit. - return NO_MATCH; - } -} - -PacketMatchTree::iterator PacketMatchTree::addElement(bool andBranch, - uint8_t level, PacketMatchTree::iterator position, - TmPacketMinimal* content) { - SerializeableMatcherIF* newContent = NULL; - switch (level) { - case 0: - newContent = factory.generate(content->getAPID()); - break; - case 1: - newContent = factory.generate(content->getService()); - break; - case 2: - newContent = factory.generate( - content->getSubService()); - break; - default: - break; } + //Only reached if nothing was found. + SerializeableMatcherIF* newContent = factory.generate( + test); if (newContent == NULL) { - return end(); + return FULL; } Node* newNode = factory.generate(newContent); if (newNode == NULL) { - return end(); + //Need to make sure partially generated content is deleted, otherwise, that's a leak. + factory.destroy(static_cast(newContent)); + return FULL; } - return insert(andBranch, position, newNode); + *lastTest = insert(attachToBranch, *lastTest, newNode); + if (*lastTest == end()) { + //This actaully never fails, so creating a dedicated returncode seems an overshoot. + return RETURN_FAILED; + } + return NEW_NODE_CREATED; +} + +ReturnValue_t PacketMatchTree::removeMatch(uint16_t apid, uint8_t type, + uint8_t subtype) { + TmPacketMinimal::TmPacketMinimalPointer data; + data.data_field.service_type = type; + data.data_field.service_subtype = subtype; + TmPacketMinimal testPacket((uint8_t*) &data); + testPacket.setAPID(apid); + iterator foundElement = findMatch(begin(), &testPacket); + if (foundElement == this->end()) { + return NO_MATCH; + } + if (type == 0) { + if (foundElement.left() == end()) { + return removeElementAndReconnectChildren(foundElement); + } else { + return TOO_GENERAL_REQUEST; + } + } + //Go down AND branch. Will abort if empty. + foundElement = findMatch(foundElement.left(), &testPacket); + if (foundElement == this->end()) { + return NO_MATCH; + } + if (subtype == 0) { + if (foundElement.left() == end()) { + return removeElementAndReconnectChildren(foundElement); + } else { + return TOO_GENERAL_REQUEST; + } + } + //Again, go down AND branch. + foundElement = findMatch(foundElement.left(), &testPacket); + if (foundElement == end()) { + return NO_MATCH; + } + return removeElementAndReconnectChildren(foundElement); +} + +PacketMatchTree::iterator PacketMatchTree::findMatch(iterator startAt, + TmPacketMinimal* test) { + iterator iter = startAt; + while (iter != end()) { + bool isMatch = iter->match(test); + if (isMatch) { + break; + } else { + iter = iter.right(); //next OR element + } + } + return iter; } ReturnValue_t PacketMatchTree::initialize() { @@ -150,7 +175,7 @@ ReturnValue_t PacketMatchTree::initialize() { const uint16_t PacketMatchTree::POOL_SIZES[N_POOLS] = { sizeof(ServiceMatcher), sizeof(SubServiceMatcher), sizeof(ApidMatcher), sizeof(PacketMatchTree::Node) }; -//TODO: Rather arbitrary. Adjust! +//Maximum number of types and subtypes to filter should be more than sufficient. const uint16_t PacketMatchTree::N_ELEMENTS[N_POOLS] = { 10, 20, 2, 40 }; ReturnValue_t PacketMatchTree::changeMatch(bool addToMatch, uint16_t apid, @@ -163,7 +188,8 @@ ReturnValue_t PacketMatchTree::changeMatch(bool addToMatch, uint16_t apid, } ReturnValue_t PacketMatchTree::cleanUpElement(iterator position) { - //TODO: What if first deletion fails? factory.destroy(position.element->value); + //Go on anyway, there's nothing we can do. + //SHOULDDO: Throw event, or write debug message? return factory.destroy(position.element); } diff --git a/tmtcpacket/packetmatcher/PacketMatchTree.h b/tmtcpacket/packetmatcher/PacketMatchTree.h index 81f1aafe..a6c0c61e 100644 --- a/tmtcpacket/packetmatcher/PacketMatchTree.h +++ b/tmtcpacket/packetmatcher/PacketMatchTree.h @@ -1,10 +1,3 @@ -/* - * PacketMatchTree.h - * - * Created on: 10.03.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_TMTCPACKET_PACKETMATCHER_PACKETMATCHTREE_H_ #define FRAMEWORK_TMTCPACKET_PACKETMATCHER_PACKETMATCHTREE_H_ @@ -34,7 +27,9 @@ private: PlacementFactory factory; static const uint16_t POOL_SIZES[N_POOLS]; static const uint16_t N_ELEMENTS[N_POOLS]; - iterator addElement(bool andBranch, uint8_t level, iterator position, TmPacketMinimal* content); + template + ReturnValue_t findOrInsertMatch(iterator startAt, VALUE_T test, iterator* lastTest); + iterator findMatch(iterator startAt, TmPacketMinimal* test); }; #endif /* FRAMEWORK_TMTCPACKET_PACKETMATCHER_PACKETMATCHTREE_H_ */ diff --git a/tmtcpacket/packetmatcher/ServiceMatcher.h b/tmtcpacket/packetmatcher/ServiceMatcher.h index 90a1d6e1..1a6781b4 100644 --- a/tmtcpacket/packetmatcher/ServiceMatcher.h +++ b/tmtcpacket/packetmatcher/ServiceMatcher.h @@ -1,10 +1,3 @@ -/* - * ServiceMatcher.h - * - * Created on: 09.03.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_TMTCPACKET_PACKETMATCHER_SERVICEMATCHER_H_ #define FRAMEWORK_TMTCPACKET_PACKETMATCHER_SERVICEMATCHER_H_ @@ -19,6 +12,9 @@ public: ServiceMatcher(uint8_t setService) : service(setService) { } + ServiceMatcher(TmPacketMinimal* test) : + service(test->getService()) { + } bool match(TmPacketMinimal* packet) { if (packet->getService() == service) { return true; diff --git a/tmtcpacket/packetmatcher/SubserviceMatcher.h b/tmtcpacket/packetmatcher/SubserviceMatcher.h index 51c00baf..1b589b20 100644 --- a/tmtcpacket/packetmatcher/SubserviceMatcher.h +++ b/tmtcpacket/packetmatcher/SubserviceMatcher.h @@ -1,10 +1,3 @@ -/* - * SubserviceMatcher.h - * - * Created on: 09.03.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_TMTCPACKET_PACKETMATCHER_SUBSERVICEMATCHER_H_ #define FRAMEWORK_TMTCPACKET_PACKETMATCHER_SUBSERVICEMATCHER_H_ @@ -17,6 +10,9 @@ public: SubServiceMatcher(uint8_t subService) : subService(subService) { } + SubServiceMatcher(TmPacketMinimal* test) : + subService(test->getSubService()) { + } bool match(TmPacketMinimal* packet) { if (packet->getSubService() == subService) { return true; diff --git a/tmtcpacket/pus/PacketTimestampInterpreterIF.h b/tmtcpacket/pus/PacketTimestampInterpreterIF.h new file mode 100644 index 00000000..6e19381a --- /dev/null +++ b/tmtcpacket/pus/PacketTimestampInterpreterIF.h @@ -0,0 +1,16 @@ +#ifndef FRAMEWORK_TMTCPACKET_PUS_PACKETTIMESTAMPINTERPRETERIF_H_ +#define FRAMEWORK_TMTCPACKET_PUS_PACKETTIMESTAMPINTERPRETERIF_H_ + +#include +class TmPacketMinimal; + +class PacketTimestampInterpreterIF { +public: + virtual ~PacketTimestampInterpreterIF() {} + virtual ReturnValue_t getPacketTime(TmPacketMinimal* packet, timeval* timestamp) const = 0; + virtual ReturnValue_t getPacketTimeRaw(TmPacketMinimal* packet, const uint8_t** timePtr, uint32_t* size) const = 0; +}; + + + +#endif /* FRAMEWORK_TMTCPACKET_PUS_PACKETTIMESTAMPINTERPRETERIF_H_ */ diff --git a/tmtcpacket/pus/TcPacket.cpp b/tmtcpacket/pus/TcPacket.cpp deleted file mode 100644 index 29f67443..00000000 --- a/tmtcpacket/pus/TcPacket.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - * TcPacket.cpp - * - * Created on: 18.06.2012 - * Author: baetz - */ - -#include -#include -#include -template -TcPacket::TcPacket() : TcPacketBase( (uint8_t*)&this->local_data ) { - memset( &this->local_data, 0, sizeof(this->local_data) ); - //Set all constant elements in header according to ECSS E-70-41A (2003) - //Primary header: - //Set APID to idle packet - this->local_data.primary.packet_id_h = 0b00011000; - this->setAPID( APID_IDLE_PACKET ); - //Set Sequence Flags to "stand-alone packet" - this->local_data.primary.sequence_control_h = 0b11000000; - //Set packet size to size of data field header + CRC - this->setPacketDataLength( sizeof(this->local_data.data_field) + CRC_SIZE ); - - //Data Field Header: - //Set CCSDS_secondary_header_flag to 0, version number to 001 and ack to 0000 - this->local_data.data_field.version_type_ack = 0b00010000; - -} - -template -TcPacket::TcPacket( uint16_t new_apid, uint8_t new_ack, uint8_t new_service, uint8_t new_subservice, uint16_t new_sequence_count) : TcPacketBase( (uint8_t*)&this->local_data ) { - memset( &this->local_data, 0, sizeof(this->local_data) ); - //Set all constant elements in header according to ECSS E-70-41A (2003) - //Primary header: - //Set APID to idle packet - this->local_data.primary.packet_id_h = 0b00011000; - this->setAPID( new_apid ); - //Set Sequence Flags to "stand-alone packet" - this->local_data.primary.sequence_control_h = 0b11000000; - this->setPacketSequenceCount( new_sequence_count ); - this->setPacketDataLength( sizeof(this->local_data.data_field) + CRC_SIZE ); - - //Data Field Header: - //Set CCSDS_secondary_header_flag to 0, version number to 001 and ack to 0000 - this->local_data.data_field.version_type_ack = 0b00010000; - this->local_data.data_field.version_type_ack |= ( new_ack & 0x0F); - this->local_data.data_field.service_type = new_service; - this->local_data.data_field.service_subtype = new_subservice; - this->setErrorControl(); - -} - -template -TcPacket< byte_size >::~TcPacket() { -} - -template -bool TcPacket::addApplicationData( uint8_t* newData, uint32_t amount ) { - if ( amount <= ( sizeof(this->local_data.application_data) - CRC_SIZE ) ) { - memcpy( this->local_data.application_data, newData, amount ); - this->setPacketDataLength( amount + sizeof(this->local_data.data_field) + CRC_SIZE - 1 ); - this->setErrorControl(); - return true; - } else { - return false; - } -} - -template class TcPacket; -template class TcPacket<32>; -template class TcPacket<64>; -template class TcPacket<128>; -template class TcPacket<256>; -template class TcPacket<1024>; diff --git a/tmtcpacket/pus/TcPacket.h b/tmtcpacket/pus/TcPacket.h deleted file mode 100644 index a3cfb757..00000000 --- a/tmtcpacket/pus/TcPacket.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef TCPACKET_H_ -#define TCPACKET_H_ - -#include - -/** - * This constant defines the minimum size of a valid PUS Telecommand Packet. - */ -#define TC_PACKET_MIN_SIZE (sizeof(CCSDSPrimaryHeader) + sizeof(PUSTcDataFieldHeader) + 2) - -/** - * The TcPacket class is a representation of a ECSS PUS Telecommand packet. - - * The template parameter is used to instantiate the class with different - * maximum Application Data sizes (to avoid wasting stack size). - * Telecommand packets are mainly created on ground, which are accessed with - * the TcPacketBase class. However, there are occasions when command packets - * are created on-board, for example when commanding another PUS compatible - * device such as the star trackers. - * These packets can be created with the TcPacket class. - * A pointer to \c local_data is passed to the \c TcPacketBase parent class, - * so the parent's methods are reachable. - * @t_param byte_size The maximum size of the complete packet (including CRC - * and headers) - * @ingroup tmtcpackets - */ -template -class TcPacket : public TcPacketBase { -private: - /** - * This structure defines the data structure of a Telecommand Packet as - * local data. - * - * There's a buffer which corresponds to the Telecommand Application Data - * Field with a maximum size of \c byte_size. - */ - struct TcPacketData { - CCSDSPrimaryHeader primary; - PUSTcDataFieldHeader data_field; - uint8_t application_data[byte_size - sizeof(CCSDSPrimaryHeader) - sizeof(PUSTcDataFieldHeader)]; - }; - /** - * This is the data representation of the class. - */ - TcPacketData local_data; -public: - /** - * This is the default constructor of the class. - * - * It sets all values to default for a CCSDS Idle Packet (i.e. APID is 2047). - */ - TcPacket( void ); - /** - * A constructor which directly sets all relevant header information. - * @param apid Sets the packet's APID field. - * @param ack Set's the packet's Ack field, - * which specifies number and size of verification packets returned - * for this command. - * @param service Sets the packet's Service ID field. - * This specifies the destination service. - * @param subservice Sets the packet's Service Subtype field. - * This specifies the destination sub-service. - * @param sequence_count Sets the packet's Source Sequence Count field. - */ - TcPacket( uint16_t apid, uint8_t ack, uint8_t service, uint8_t subservice, uint16_t sequence_count = 0 ); - /** - * This is the empty default destructor of the class. - */ - ~TcPacket( void ); - /** - * With this call, application data can be added to the Application Data - * buffer. - * The Error Control Field is updated automatically. - * @param data The data to add to the Application Data field. - * @param size The size of the data to add. - * @return @li \c true if \c size is smaller than the Application Data - * buffer. - * @li \c false else. - */ - bool addApplicationData( uint8_t* data, uint32_t size ); -}; - -#endif /* TCPACKET_H_ */ diff --git a/tmtcpacket/pus/TcPacketBase.cpp b/tmtcpacket/pus/TcPacketBase.cpp index 593e5937..630394f8 100644 --- a/tmtcpacket/pus/TcPacketBase.cpp +++ b/tmtcpacket/pus/TcPacketBase.cpp @@ -1,16 +1,11 @@ -/* - * TcPacketBase.cpp - * - * Created on: 18.06.2012 - * Author: baetz - */ - #include #include #include +#include -TcPacketBase::TcPacketBase( const uint8_t* set_data ) : SpacePacketBase( set_data ) { - this->tc_data = (TcPacketPointer*)set_data; +TcPacketBase::TcPacketBase(const uint8_t* set_data) : + SpacePacketBase(set_data) { + tcData = (TcPacketPointer*) set_data; } TcPacketBase::~TcPacketBase() { @@ -18,57 +13,70 @@ TcPacketBase::~TcPacketBase() { } uint8_t TcPacketBase::getService() { - return this->tc_data->data_field.service_type; + return tcData->data_field.service_type; } uint8_t TcPacketBase::getSubService() { - return this->tc_data->data_field.service_subtype; + return tcData->data_field.service_subtype; } uint8_t TcPacketBase::getAcknowledgeFlags() { - return this->tc_data->data_field.version_type_ack & 0b00001111; + return tcData->data_field.version_type_ack & 0b00001111; } const uint8_t* TcPacketBase::getApplicationData() const { - return &this->tc_data->data; + return &tcData->data; } uint16_t TcPacketBase::getApplicationDataSize() { - return this->getPacketDataLength() - sizeof(this->tc_data->data_field) - CRC_SIZE + 1; + return getPacketDataLength() - sizeof(tcData->data_field) - CRC_SIZE + 1; } uint16_t TcPacketBase::getErrorControl() { - uint16_t size = this->getApplicationDataSize() + CRC_SIZE; - uint8_t* p_to_buffer = &this->tc_data->data; - return ( p_to_buffer[size - 2] << 8 ) + p_to_buffer[size - 1]; + uint16_t size = getApplicationDataSize() + CRC_SIZE; + uint8_t* p_to_buffer = &tcData->data; + return (p_to_buffer[size - 2] << 8) + p_to_buffer[size - 1]; } void TcPacketBase::setErrorControl() { - uint32_t full_size = this->getFullSize(); - uint16_t crc = ::Calculate_CRC ( this->getWholeData(), full_size - CRC_SIZE ); - uint32_t size = this->getApplicationDataSize(); - (&tc_data->data)[ size ] = ( crc & 0XFF00) >> 8; // CRCH - (&tc_data->data)[ size + 1 ] = ( crc ) & 0X00FF; // CRCL + uint32_t full_size = getFullSize(); + uint16_t crc = ::Calculate_CRC(getWholeData(), full_size - CRC_SIZE); + uint32_t size = getApplicationDataSize(); + (&tcData->data)[size] = (crc & 0XFF00) >> 8; // CRCH + (&tcData->data)[size + 1] = (crc) & 0X00FF; // CRCL } void TcPacketBase::setData(const uint8_t* p_Data) { - this->SpacePacketBase::setData( p_Data ); - this->tc_data = (TcPacketPointer*)p_Data; + SpacePacketBase::setData(p_Data); + tcData = (TcPacketPointer*) p_Data; } uint8_t TcPacketBase::getSecondaryHeaderFlag() { - return (this->tc_data->data_field.version_type_ack & 0b10000000) >> 7; + return (tcData->data_field.version_type_ack & 0b10000000) >> 7; } uint8_t TcPacketBase::getPusVersionNumber() { - return (this->tc_data->data_field.version_type_ack & 0b01110000) >> 4; + return (tcData->data_field.version_type_ack & 0b01110000) >> 4; } void TcPacketBase::print() { - uint8_t * wholeData = this->getWholeData(); + uint8_t * wholeData = getWholeData(); debug << "TcPacket contains: " << std::endl; - for (uint8_t count = 0; count < this->getFullSize(); ++count ) { - debug << std::hex << (uint16_t)wholeData[count] << " "; + for (uint8_t count = 0; count < getFullSize(); ++count) { + debug << std::hex << (uint16_t) wholeData[count] << " "; } debug << std::dec << std::endl; } + +void TcPacketBase::initializeTcPacket(uint16_t apid, uint16_t sequenceCount, + uint8_t ack, uint8_t service, uint8_t subservice) { + initSpacePacketHeader(true, true, apid, sequenceCount); + memset(&tcData->data_field, 0, sizeof(tcData->data_field)); + setPacketDataLength(sizeof(tcData->data_field) + CRC_SIZE); + //Data Field Header: + //Set CCSDS_secondary_header_flag to 0, version number to 001 and ack to 0000 + tcData->data_field.version_type_ack = 0b00010000; + tcData->data_field.version_type_ack |= (ack & 0x0F); + tcData->data_field.service_type = service; + tcData->data_field.service_subtype = subservice; +} diff --git a/tmtcpacket/pus/TcPacketBase.h b/tmtcpacket/pus/TcPacketBase.h index eaeddcd8..e6e6bdad 100644 --- a/tmtcpacket/pus/TcPacketBase.h +++ b/tmtcpacket/pus/TcPacketBase.h @@ -46,8 +46,9 @@ protected: * * To be hardware-safe, all elements are of byte size. */ - TcPacketPointer* tc_data; + TcPacketPointer* tcData; public: + static const uint16_t TC_PACKET_MIN_SIZE = (sizeof(CCSDSPrimaryHeader) + sizeof(PUSTcDataFieldHeader) + 2); /** * With this constant for the acknowledge field responses on all levels are expected. */ @@ -83,6 +84,22 @@ public: * This is the empty default destructor. */ virtual ~TcPacketBase(); + /** + * Initializes the Tc Packet header. + * @param apid APID used. + * @param service PUS Service + * @param subservice PUS Subservice + * @param packetSubcounter Additional subcounter used. + */ + /** + * Initializes the Tc Packet header. + * @param apid APID used. + * @param sequenceCount Sequence Count in the primary header. + * @param ack Which acknowledeges are expected from the receiver. + * @param service PUS Service + * @param subservice PUS Subservice + */ + void initializeTcPacket(uint16_t apid, uint16_t sequenceCount, uint8_t ack, uint8_t service, uint8_t subservice); /** * This command returns the CCSDS Secondary Header Flag. * It shall always be zero for PUS Packets. This is the diff --git a/tmtcpacket/pus/TcPacketStored.cpp b/tmtcpacket/pus/TcPacketStored.cpp index 67542b79..43da0f7d 100644 --- a/tmtcpacket/pus/TcPacketStored.cpp +++ b/tmtcpacket/pus/TcPacketStored.cpp @@ -1,56 +1,57 @@ - -/* - * TcPacketStored.cpp - * - * Created on: 20.11.2012 - * Author: baetz */ #include #include -#include #include #include -TcPacketStored::TcPacketStored( store_address_t setAddress) : TcPacketBase(NULL), storeAddress(setAddress) { - this->setStoreAddress( this->storeAddress ); +TcPacketStored::TcPacketStored(store_address_t setAddress) : + TcPacketBase(NULL), storeAddress(setAddress) { + this->setStoreAddress(this->storeAddress); } -TcPacketStored::TcPacketStored( uint16_t apid, uint8_t ack, uint8_t service, uint8_t subservice, - uint8_t sequence_count, const uint8_t* data, uint32_t size) : TcPacketBase(NULL) { +TcPacketStored::TcPacketStored(uint16_t apid, uint8_t ack, uint8_t service, + uint8_t subservice, uint8_t sequence_count, const uint8_t* data, + uint32_t size) : + TcPacketBase(NULL) { this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; - if ( this->checkAndSetStore() ) { - TcPacket temp_packet( apid, ack, service, subservice, sequence_count); - uint8_t* p_data = NULL; - ReturnValue_t returnValue = this->store->getFreeElement( &this->storeAddress, (TC_PACKET_MIN_SIZE + size), &p_data ); - if ( returnValue == this->store->RETURN_OK ) { - memcpy(p_data, temp_packet.getWholeData(), temp_packet.getFullSize() ); - this->setData( p_data ); - memcpy( &tc_data->data, data, size ); - this->setPacketDataLength( size + sizeof(PUSTcDataFieldHeader) + CRC_SIZE - 1 ); - this->setErrorControl(); - } + if (!this->checkAndSetStore()) { + return; } + uint8_t* p_data = NULL; + ReturnValue_t returnValue = this->store->getFreeElement(&this->storeAddress, + (TC_PACKET_MIN_SIZE + size), &p_data); + if (returnValue != this->store->RETURN_OK) { + return; + } + this->setData(p_data); + initializeTcPacket(apid, sequence_count, ack, service, subservice); + memcpy(&tcData->data, data, size); + this->setPacketDataLength( + size + sizeof(PUSTcDataFieldHeader) + CRC_SIZE - 1); + this->setErrorControl(); } -TcPacketStored::TcPacketStored() : TcPacketBase(NULL) { +TcPacketStored::TcPacketStored() : + TcPacketBase(NULL) { this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; this->checkAndSetStore(); } -//TODO: return code? -void TcPacketStored::deletePacket() { - this->store->deleteData( this->storeAddress ); +ReturnValue_t TcPacketStored::deletePacket() { + ReturnValue_t result = this->store->deleteData(this->storeAddress); this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; - this->setData( NULL ); + this->setData( NULL); + return result; } bool TcPacketStored::checkAndSetStore() { if (this->store == NULL) { - this->store = objectManager->get( objects::TC_STORE ); - if ( this->store == NULL ) { - error << "TcPacketStored::TcPacketStored: TC Store not found!" << std::endl; + this->store = objectManager->get(objects::TC_STORE); + if (this->store == NULL) { + error << "TcPacketStored::TcPacketStored: TC Store not found!" + << std::endl; return false; } } @@ -62,8 +63,9 @@ void TcPacketStored::setStoreAddress(store_address_t setAddress) { const uint8_t* temp_data = NULL; uint32_t temp_size; ReturnValue_t status = StorageManagerIF::RETURN_FAILED; - if ( this->checkAndSetStore() ) { - status = this->store->getData(this->storeAddress, &temp_data, &temp_size ); + if (this->checkAndSetStore()) { + status = this->store->getData(this->storeAddress, &temp_data, + &temp_size); } if (status == StorageManagerIF::RETURN_OK) { this->setData(temp_data); @@ -80,9 +82,10 @@ store_address_t TcPacketStored::getStoreAddress() { bool TcPacketStored::isSizeCorrect() { const uint8_t* temp_data = NULL; uint32_t temp_size; - ReturnValue_t status = this->store->getData(this->storeAddress, &temp_data, &temp_size ); + ReturnValue_t status = this->store->getData(this->storeAddress, &temp_data, + &temp_size); if (status == StorageManagerIF::RETURN_OK) { - if (this->getFullSize() == temp_size ) { + if (this->getFullSize() == temp_size) { return true; } } @@ -91,11 +94,12 @@ bool TcPacketStored::isSizeCorrect() { StorageManagerIF* TcPacketStored::store = NULL; -TcPacketStored::TcPacketStored(const uint8_t* data, uint32_t size) : TcPacketBase(data) { +TcPacketStored::TcPacketStored(const uint8_t* data, uint32_t size) : + TcPacketBase(data) { if (getFullSize() != size) { return; } - if ( this->checkAndSetStore() ) { + if (this->checkAndSetStore()) { ReturnValue_t status = store->addData(&storeAddress, data, size); if (status != HasReturnvaluesIF::RETURN_OK) { this->setData(NULL); diff --git a/tmtcpacket/pus/TcPacketStored.h b/tmtcpacket/pus/TcPacketStored.h index 58371cbc..c57f0e0f 100644 --- a/tmtcpacket/pus/TcPacketStored.h +++ b/tmtcpacket/pus/TcPacketStored.h @@ -81,8 +81,9 @@ public: /** * With this call, the packet is deleted. * It removes itself from the store and sets its data pointer to NULL. + * @return returncode from deleting the data. */ - void deletePacket(); + ReturnValue_t deletePacket(); /** * With this call, a packet can be linked to another store. This is useful * if the packet is a class member and used for more than one packet. diff --git a/tmtcpacket/pus/TmPacket.cpp b/tmtcpacket/pus/TmPacket.cpp deleted file mode 100644 index 5855ef8a..00000000 --- a/tmtcpacket/pus/TmPacket.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * TmPacket.cpp - * - * Created on: 18.06.2012 - * Author: baetz - */ - -#include -#include -template -TmPacket::TmPacket() : TmPacketBase( (uint8_t*)&this->local_data ) { - memset( &this->local_data, 0, sizeof(this->local_data) ); - //Set all constant elements in header according to ECSS E-70-41A (2003) - //Primary header: - //Set APID to idle packet - local_data.primary.packet_id_h = 0b00001000; - setAPID( APID_IDLE_PACKET ); - //Set Sequence Flags to "stand-alone packet" - local_data.primary.sequence_control_h = 0b11000000; - //Set packet size to size of data field header + CRC - setPacketDataLength( sizeof(this->local_data.data_field) + CRC_SIZE ); - if (checkAndSetStamper()) { - timeStamper->addTimeStamp(local_data.data_field.time, sizeof(local_data.data_field.time)); - } - //Data Field Header: - //Set CCSDS_secondary_header_flag to 0, version number to 001 and ack to 0000 - this->local_data.data_field.version_type_ack = 0b00010000; - -} - -template -TmPacket::TmPacket( uint16_t new_apid, uint8_t new_service, uint8_t new_subservice, uint8_t new_packet_counter ) : TmPacketBase( (uint8_t*)&this->local_data ) { - memset( &this->local_data, 0, sizeof(this->local_data) ); - //Set all constant elements in header according to ECSS E-70-41A (2003) - //Primary header: - //Set APID to idle packet - this->local_data.primary.packet_id_h = 0b00001000; - this->setAPID( new_apid ); - //Set Sequence Flags to "stand-alone packet" - this->local_data.primary.sequence_control_h = 0b11000000; - //Set Data Length to minimum size (Data Field Header + CRC size) - this->setPacketDataLength( sizeof(this->local_data.data_field) + CRC_SIZE ); - - //Data Field Header: - //Set CCSDS_secondary_header_flag to 0, version number to 001 and ack to 0000 - this->local_data.data_field.version_type_ack = 0b00010000; - this->local_data.data_field.service_type = new_service; - this->local_data.data_field.service_subtype = new_subservice; - this->local_data.data_field.subcounter = new_packet_counter; - - if (checkAndSetStamper()) { - timeStamper->addTimeStamp(local_data.data_field.time, sizeof(local_data.data_field.time)); - } - -// this->local_data.data_field.destination = new_destination; - this->setErrorControl(); -} - -template -TmPacket< byte_size >::~TmPacket() { -} - -template -bool TmPacket::addSourceData( uint8_t* newData, uint32_t amount ) { - if ( amount <= ( sizeof(this->local_data.source_data) - CRC_SIZE ) ) { - memcpy( this->local_data.source_data, newData, amount ); - this->setPacketDataLength( amount + sizeof(this->local_data.data_field) + CRC_SIZE - 1 ); - this->setErrorControl(); - return true; - } else { - return false; - } -} - -template class TmPacket; -template class TmPacket<64>; -template class TmPacket<128>; -template class TmPacket<256>; -template class TmPacket<512>; -template class TmPacket<1024>; diff --git a/tmtcpacket/pus/TmPacket.h b/tmtcpacket/pus/TmPacket.h deleted file mode 100644 index b6d7c412..00000000 --- a/tmtcpacket/pus/TmPacket.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef TMPACKET_H_ -#define TMPACKET_H_ - -#include - -/** - * The TmPacket class is a representation of a ECSS PUS Telemetry packet. - - * The template parameter is used to instantiate the class with different - * maximum Application Data sizes (to avoid wasting stack size). Almost every - * on-board service is a source of telemetry packets. These packets are created - * with the TmPacket class, which is instantiated similar to the TcPacket - * class. - * A pointer to \c local_data is passed to the \c TmPacketBase parent class, - * so the parent's methods are reachable. - * @t_param byte_size The maximum size of the complete packet (including CRC - * and headers) - * @ingroup tmtcpackets - */ -template -class TmPacket : public TmPacketBase { -public: - /** - * This is the default constructor of the class. - * - * It sets all values to default for a CCSDS Idle Packet (i.e. APID is 2047). - */ - TmPacket( void ); - /** - * A constructor which directly sets all relevant header information. - * @param apid Sets the packet's APID field. - * @param service Sets the packet's Service ID field. - * This specifies the source service. - * @param subservice Sets the packet's Service Subtype field. - * This specifies the source sub-service. - * @param packet_counter Sets the Packet counter field of this packet. - */ - TmPacket( uint16_t apid, uint8_t service, uint8_t subservice, uint8_t packet_counter = 0 ); - /** - * This is the empty default destructor of the class. - */ - ~TmPacket( void ); - /** - * With this call, application data can be added to the Source Data - * buffer. - * The Error Control Field is updated automatically. - * @param data The data to add to the Source Data field. - * @param size The size of the data to add. - * @return @li \c true if \c size is smaller than the Source Data buffer. - * @li \c false else. - */ - bool addSourceData( uint8_t*, uint32_t ); -private: - /** - * This structure defines the data structure of a Telemetry Packet as - * local data. - * - * There's a buffer which corresponds to the Telemetry Source Data Field - * with a maximum size of \c byte_size. - */ - struct TmPacketData { - CCSDSPrimaryHeader primary; - PUSTmDataFieldHeader data_field; - uint8_t source_data[byte_size - sizeof(CCSDSPrimaryHeader) - sizeof(PUSTmDataFieldHeader)]; - }; - /** - * This is the data representation of the class. - */ - TmPacketData local_data; -}; - -#endif /* TMPACKET_H_ */ diff --git a/tmtcpacket/pus/TmPacketBase.cpp b/tmtcpacket/pus/TmPacketBase.cpp index 3bd18283..9cdb6138 100644 --- a/tmtcpacket/pus/TmPacketBase.cpp +++ b/tmtcpacket/pus/TmPacketBase.cpp @@ -1,17 +1,13 @@ -/* - * TmPacketBase.cpp - * - * Created on: 18.06.2012 - * Author: baetz - */ - #include #include #include #include +#include +#include -TmPacketBase::TmPacketBase( uint8_t* set_data ) : SpacePacketBase( set_data ) { - this->tm_data = (TmPacketPointer*)set_data; +TmPacketBase::TmPacketBase(uint8_t* set_data) : + SpacePacketBase(set_data) { + tm_data = (TmPacketPointer*) set_data; } TmPacketBase::~TmPacketBase() { @@ -19,60 +15,97 @@ TmPacketBase::~TmPacketBase() { } uint8_t TmPacketBase::getService() { - return this->tm_data->data_field.service_type; + return tm_data->data_field.service_type; } uint8_t TmPacketBase::getSubService() { - return this->tm_data->data_field.service_subtype; + return tm_data->data_field.service_subtype; } uint8_t* TmPacketBase::getSourceData() { - return &this->tm_data->data; + return &tm_data->data; } uint16_t TmPacketBase::getSourceDataSize() { - return this->getPacketDataLength() - sizeof(this->tm_data->data_field) - CRC_SIZE + 1; + return getPacketDataLength() - sizeof(tm_data->data_field) + - CRC_SIZE + 1; } uint16_t TmPacketBase::getErrorControl() { - uint32_t size = this->getSourceDataSize() + CRC_SIZE; - uint8_t* p_to_buffer = &this->tm_data->data; - return ( p_to_buffer[size - 2] << 8 ) + p_to_buffer[size - 1]; + uint32_t size = getSourceDataSize() + CRC_SIZE; + uint8_t* p_to_buffer = &tm_data->data; + return (p_to_buffer[size - 2] << 8) + p_to_buffer[size - 1]; } - void TmPacketBase::setErrorControl() { - uint32_t full_size = this->getFullSize(); - uint16_t crc = ::Calculate_CRC ( this->getWholeData(), full_size - CRC_SIZE ); - uint32_t size = this->getSourceDataSize(); - this->getSourceData()[ size ] = ( crc & 0XFF00) >> 8; // CRCH - this->getSourceData()[ size + 1 ] = ( crc ) & 0X00FF; // CRCL + uint32_t full_size = getFullSize(); + uint16_t crc = ::Calculate_CRC(getWholeData(), full_size - CRC_SIZE); + uint32_t size = getSourceDataSize(); + getSourceData()[size] = (crc & 0XFF00) >> 8; // CRCH + getSourceData()[size + 1] = (crc) & 0X00FF; // CRCL } void TmPacketBase::setData(const uint8_t* p_Data) { - this->SpacePacketBase::setData( p_Data ); - this->tm_data = (TmPacketPointer*)p_Data; + SpacePacketBase::setData(p_Data); + tm_data = (TmPacketPointer*) p_Data; } void TmPacketBase::print() { - /*uint8_t * wholeData = this->getWholeData(); - debug << "TmPacket contains: " << std::endl; - for (uint8_t count = 0; count < this->getFullSize(); ++count ) { - debug << std::hex << (uint16_t)wholeData[count] << " "; - } - debug << std::dec << std::endl;*/ + /*uint8_t * wholeData = getWholeData(); + debug << "TmPacket contains: " << std::endl; + for (uint8_t count = 0; count < getFullSize(); ++count ) { + debug << std::hex << (uint16_t)wholeData[count] << " "; + } + debug << std::dec << std::endl;*/ } bool TmPacketBase::checkAndSetStamper() { if (timeStamper == NULL) { - //TODO: Adjust name? - timeStamper = objectManager->get( objects::TIME_MANAGER ); - if ( timeStamper == NULL ) { - error << "TmPacketBase::checkAndSetStamper: Stamper not found!" << std::endl; + timeStamper = objectManager->get(timeStamperId); + if (timeStamper == NULL) { + error << "TmPacketBase::checkAndSetStamper: Stamper not found!" + << std::endl; return false; } } return true; } +ReturnValue_t TmPacketBase::getPacketTime(timeval* timestamp) const { + uint32_t tempSize = 0; + return CCSDSTime::convertFromCcsds(timestamp, tm_data->data_field.time, + &tempSize, sizeof(tm_data->data_field.time)); +} + +uint8_t* TmPacketBase::getPacketTimeRaw() const{ + return tm_data->data_field.time; + +} + +void TmPacketBase::initializeTmPacket(uint16_t apid, uint8_t service, uint8_t subservice, uint8_t packetSubcounter) { + //Set primary header: + initSpacePacketHeader(false, true, apid); + //Set data Field Header: + //First, set to zero. + memset(&tm_data->data_field, 0, sizeof(tm_data->data_field)); + //Set CCSDS_secondary header flag to 0, version number to 001 and ack to 0000 + tm_data->data_field.version_type_ack = 0b00010000; + tm_data->data_field.service_type = service; + tm_data->data_field.service_subtype = subservice; + tm_data->data_field.subcounter = packetSubcounter; + //Timestamp packet + if (checkAndSetStamper()) { + timeStamper->addTimeStamp(tm_data->data_field.time, sizeof(tm_data->data_field.time)); + } +} + +void TmPacketBase::setSourceDataSize(uint16_t size) { + setPacketDataLength(size + sizeof(PUSTmDataFieldHeader) + CRC_SIZE - 1); +} + +uint32_t TmPacketBase::getTimestampSize() const { + return sizeof(tm_data->data_field.time); +} + TimeStamperIF* TmPacketBase::timeStamper = NULL; +object_id_t TmPacketBase::timeStamperId = 0; diff --git a/tmtcpacket/pus/TmPacketBase.h b/tmtcpacket/pus/TmPacketBase.h index beda760f..d03beba5 100644 --- a/tmtcpacket/pus/TmPacketBase.h +++ b/tmtcpacket/pus/TmPacketBase.h @@ -3,6 +3,12 @@ #include #include +#include +#include + +namespace Factory{ +void setStaticFrameworkObjectIds(); +} /** * This struct defines a byte-wise structured PUS TM Data Field Header. @@ -31,8 +37,6 @@ struct TmPacketPointer { uint8_t data; }; -//TODO: add getTime, getSubcounter, getDestionation (if required) - /** * This class is the basic data handler for any ECSS PUS Telemetry packet. * @@ -45,7 +49,14 @@ struct TmPacketPointer { * @ingroup tmtcpackets */ class TmPacketBase : public SpacePacketBase { + friend void (Factory::setStaticFrameworkObjectIds)(); public: + /** + * This constant defines the minimum size of a valid PUS Telemetry Packet. + */ + static const uint32_t TM_PACKET_MIN_SIZE = (sizeof(CCSDSPrimaryHeader) + sizeof(PUSTmDataFieldHeader) + 2); //!< Minimum size of a valid PUS Telemetry Packet. + static const uint32_t MISSION_TM_PACKET_MAX_SIZE = 2048; //!< Maximum size of a TM Packet in this mission. + static const uint8_t VERSION_NUMBER_BYTE_PUS_A = 0b00010000; //!< First byte of secondary header for PUS-A packets. /** * This is the default constructor. * It sets its internal data pointer to the address passed and also @@ -57,6 +68,15 @@ public: * This is the empty default destructor. */ virtual ~TmPacketBase(); + /** + * Initializes the Tm Packet header. + * Does set the timestamp (to now), but not the error control field. + * @param apid APID used. + * @param service PUS Service + * @param subservice PUS Subservice + * @param packetSubcounter Additional subcounter used. + */ + void initializeTmPacket(uint16_t apid, uint8_t service, uint8_t subservice, uint8_t packetSubcounter); /** * This is a getter for the packet's PUS Service ID, which is the second * byte of the Data Field Header. @@ -85,6 +105,12 @@ public: * @return The size of the PUS Source Data (without Error Control field) */ uint16_t getSourceDataSize(); + + /** + * In case data was filled manually (almost never the case). + * @param size Size of source data (without CRC and data filed header!). + */ + void setSourceDataSize(uint16_t size); /** * This getter returns the Error Control Field of the packet. * @@ -115,10 +141,18 @@ public: */ void print(); /** - * This constant defines the minimum size of a valid PUS Telemetry Packet. + * Interprets the "time"-field in the secondary header and returns it in timeval format. + * @return Converted timestamp of packet. */ - static const uint32_t TM_PACKET_MIN_SIZE = (sizeof(CCSDSPrimaryHeader) + sizeof(PUSTmDataFieldHeader) + 2); - static const uint32_t MISSION_TM_PACKET_MAX_SIZE = 2048; //!< Maximum size of a TM Packet in this mission. + ReturnValue_t getPacketTime(timeval* timestamp) const; + /** + * Returns a raw pointer to the beginning of the time field. + * @return Raw pointer to time field. + */ + uint8_t* getPacketTimeRaw() const; + + uint32_t getTimestampSize() const; + protected: /** * A pointer to a structure which defines the data structure of @@ -132,6 +166,8 @@ protected: * It is initialized lazy. */ static TimeStamperIF* timeStamper; + + static object_id_t timeStamperId; //!< The ID to use when looking for a time stamper. /** * Checks if a time stamper is available and tries to set it if not. * @return Returns false if setting failed. diff --git a/tmtcpacket/pus/TmPacketMinimal.cpp b/tmtcpacket/pus/TmPacketMinimal.cpp index 12a9e6e3..9df0fe5d 100644 --- a/tmtcpacket/pus/TmPacketMinimal.cpp +++ b/tmtcpacket/pus/TmPacketMinimal.cpp @@ -1,5 +1,7 @@ - #include +#include +#include +#include TmPacketMinimal::TmPacketMinimal(const uint8_t* set_data) : SpacePacketBase( set_data ) { this->tm_data = (TmPacketMinimalPointer*)set_data; @@ -19,3 +21,25 @@ uint8_t TmPacketMinimal::getSubService() { uint8_t TmPacketMinimal::getPacketSubcounter() { return tm_data->data_field.subcounter; } + +ReturnValue_t TmPacketMinimal::getPacketTime(timeval* timestamp) { + if (timestampInterpreter == NULL) { + return HasReturnvaluesIF::RETURN_FAILED; + } + return timestampInterpreter->getPacketTime(this, timestamp); +} + +ReturnValue_t TmPacketMinimal::getPacketTimeRaw(const uint8_t** timePtr, uint32_t* size) { + if (timestampInterpreter == NULL) { + return HasReturnvaluesIF::RETURN_FAILED; + } + return timestampInterpreter->getPacketTimeRaw(this, timePtr, size); +} + +void TmPacketMinimal::setInterpretTimestampObject(PacketTimestampInterpreterIF* interpreter) { + if (TmPacketMinimal::timestampInterpreter == NULL) { + TmPacketMinimal::timestampInterpreter = interpreter; + } +} + +PacketTimestampInterpreterIF* TmPacketMinimal::timestampInterpreter = NULL; diff --git a/tmtcpacket/pus/TmPacketMinimal.h b/tmtcpacket/pus/TmPacketMinimal.h index be8f1423..7bfe0883 100644 --- a/tmtcpacket/pus/TmPacketMinimal.h +++ b/tmtcpacket/pus/TmPacketMinimal.h @@ -1,16 +1,12 @@ -/* - * TmPacketMinimal.h - * - * Created on: 09.03.2015 - * Author: baetz - */ - #ifndef FRAMEWORK_TMTCPACKET_PUS_TMPACKETMINIMAL_H_ #define FRAMEWORK_TMTCPACKET_PUS_TMPACKETMINIMAL_H_ #include +#include +struct timeval; +class PacketTimestampInterpreterIF; /** * This is a minimal version of a PUS TmPacket without any variable field, or, * in other words with Service Type, Subtype and subcounter only. @@ -54,6 +50,11 @@ public: uint8_t subcounter; }; + ReturnValue_t getPacketTime(timeval* timestamp); + + ReturnValue_t getPacketTimeRaw(const uint8_t** timePtr, uint32_t* size); + + static void setInterpretTimestampObject(PacketTimestampInterpreterIF* interpreter); /** * This struct defines the data structure of a PUS Telecommand Packet when * accessed via a pointer. @@ -64,7 +65,8 @@ public: PUSTmMinimalHeader data_field; uint8_t rest; }; - static const uint16_t MINIMUM_SIZE = sizeof(TmPacketMinimalPointer) -1; + //Must include a checksum and is therefore at least one larger than the above struct. + static const uint16_t MINIMUM_SIZE = sizeof(TmPacketMinimalPointer) +1; protected: /** * A pointer to a structure which defines the data structure of @@ -73,6 +75,8 @@ protected: * To be hardware-safe, all elements are of byte size. */ TmPacketMinimalPointer* tm_data; + + static PacketTimestampInterpreterIF* timestampInterpreter; }; diff --git a/tmtcpacket/pus/TmPacketStored.cpp b/tmtcpacket/pus/TmPacketStored.cpp index a61faa5b..f2c1eb28 100644 --- a/tmtcpacket/pus/TmPacketStored.cpp +++ b/tmtcpacket/pus/TmPacketStored.cpp @@ -1,101 +1,105 @@ -/* - * TmPacketStored.cpp - * - * Created on: 19.11.2012 - * Author: baetz - */ - #include #include -#include #include +#include #include -TmPacketStored::TmPacketStored( store_address_t setAddress ) : TmPacketBase(NULL), storeAddress(setAddress) { - this->setStoreAddress( this->storeAddress ); -} - -TmPacketStored::TmPacketStored( uint16_t apid, uint8_t service, - uint8_t subservice, uint8_t packet_counter, const uint8_t* data, uint32_t size,const uint8_t* headerData, uint32_t headerSize) : TmPacketBase(NULL) { - this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; - if ( this->checkAndSetStore() ) { - TmPacket temp_packet( apid, service, subservice, packet_counter ); - uint8_t* p_data = NULL; - ReturnValue_t returnValue = this->store->getFreeElement( &this->storeAddress, (TmPacketBase::TM_PACKET_MIN_SIZE + size + headerSize), &p_data ); - if ( returnValue == this->store->RETURN_OK ) { - memcpy(p_data, temp_packet.getWholeData(), temp_packet.getFullSize() ); - this->setData( p_data ); - memcpy( this->getSourceData(), headerData, headerSize ); - memcpy( this->getSourceData() + headerSize, data, size ); - this->setPacketDataLength( size + headerSize + sizeof(PUSTmDataFieldHeader) + CRC_SIZE - 1 ); - this->setErrorControl(); - } - } +TmPacketStored::TmPacketStored(store_address_t setAddress) : + TmPacketBase(NULL), storeAddress(setAddress) { + setStoreAddress(storeAddress); } TmPacketStored::TmPacketStored(uint16_t apid, uint8_t service, - uint8_t subservice, uint8_t packet_counter, SerializeIF* content, - SerializeIF* header) : TmPacketBase(NULL) { + uint8_t subservice, uint8_t packetSubcounter, const uint8_t* data, + uint32_t size, const uint8_t* headerData, uint32_t headerSize) : + TmPacketBase(NULL) { storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; - if ( checkAndSetStore() ) { - TmPacket temp_packet( apid, service, subservice, packet_counter ); - uint32_t sourceDataSize = 0; - if (content != NULL) { - sourceDataSize += content->getSerializedSize(); - } - if (header != NULL) { - sourceDataSize += header->getSerializedSize(); - } - uint8_t* p_data = NULL; - ReturnValue_t returnValue = this->store->getFreeElement( &this->storeAddress, (TmPacketBase::TM_PACKET_MIN_SIZE + sourceDataSize), &p_data ); - if ( returnValue == store->RETURN_OK ) { - memcpy(p_data, temp_packet.getWholeData(), temp_packet.getFullSize() ); - this->setData( p_data ); - uint8_t* putDataHere = getSourceData(); - uint32_t size = 0; - if (header != NULL) { - header->serialize(&putDataHere, &size, sourceDataSize, true); - } - if (content != NULL) { - content->serialize(&putDataHere, &size, sourceDataSize, true); - } - this->setPacketDataLength( sourceDataSize + sizeof(PUSTmDataFieldHeader) + CRC_SIZE - 1 ); - this->setErrorControl(); - } + if (!checkAndSetStore()) { + return; } + uint8_t* pData = NULL; + ReturnValue_t returnValue = store->getFreeElement(&storeAddress, + (TmPacketBase::TM_PACKET_MIN_SIZE + size + headerSize), &pData); + + if (returnValue != store->RETURN_OK) { + checkAndReportLostTm(); + return; + } + setData(pData); + initializeTmPacket(apid, service, subservice, packetSubcounter); + memcpy(getSourceData(), headerData, headerSize); + memcpy(getSourceData() + headerSize, data, size); + setPacketDataLength( + size + headerSize + sizeof(PUSTmDataFieldHeader) + CRC_SIZE - 1); +} + +TmPacketStored::TmPacketStored(uint16_t apid, uint8_t service, + uint8_t subservice, uint8_t packetSubcounter, SerializeIF* content, + SerializeIF* header) : + TmPacketBase(NULL) { + storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; + if (!checkAndSetStore()) { + return; + } + uint32_t sourceDataSize = 0; + if (content != NULL) { + sourceDataSize += content->getSerializedSize(); + } + if (header != NULL) { + sourceDataSize += header->getSerializedSize(); + } + uint8_t* p_data = NULL; + ReturnValue_t returnValue = store->getFreeElement(&storeAddress, + (TmPacketBase::TM_PACKET_MIN_SIZE + sourceDataSize), &p_data); + if (returnValue != store->RETURN_OK) { + checkAndReportLostTm(); + } + setData(p_data); + initializeTmPacket(apid, service, subservice, packetSubcounter); + uint8_t* putDataHere = getSourceData(); + uint32_t size = 0; + if (header != NULL) { + header->serialize(&putDataHere, &size, sourceDataSize, true); + } + if (content != NULL) { + content->serialize(&putDataHere, &size, sourceDataSize, true); + } + setPacketDataLength( + sourceDataSize + sizeof(PUSTmDataFieldHeader) + CRC_SIZE - 1); } store_address_t TmPacketStored::getStoreAddress() { - return this->storeAddress; + return storeAddress; } void TmPacketStored::deletePacket() { - this->store->deleteData( this->storeAddress ); - this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; - this->setData( NULL ); + store->deleteData(storeAddress); + storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; + setData(NULL); } void TmPacketStored::setStoreAddress(store_address_t setAddress) { - this->storeAddress = setAddress; + storeAddress = setAddress; const uint8_t* temp_data = NULL; uint32_t temp_size; if (!checkAndSetStore()) { return; } - ReturnValue_t status = this->store->getData(this->storeAddress, &temp_data, &temp_size ); + ReturnValue_t status = store->getData(storeAddress, &temp_data, &temp_size); if (status == StorageManagerIF::RETURN_OK) { - this->setData(temp_data); + setData(temp_data); } else { - this->setData(NULL); - this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; + setData(NULL); + storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; } } bool TmPacketStored::checkAndSetStore() { - if (this->store == NULL) { - this->store = objectManager->get( objects::TM_STORE ); - if ( this->store == NULL ) { - error << "TmPacketStored::TmPacketStored: TM Store not found!" << std::endl; + if (store == NULL) { + store = objectManager->get(objects::TM_STORE); + if (store == NULL) { + error << "TmPacketStored::TmPacketStored: TM Store not found!" + << std::endl; return false; } } @@ -103,3 +107,34 @@ bool TmPacketStored::checkAndSetStore() { } StorageManagerIF* TmPacketStored::store = NULL; +InternalErrorReporterIF* TmPacketStored::internalErrorReporter = NULL; + +ReturnValue_t TmPacketStored::sendPacket(MessageQueueId_t destination, + MessageQueueId_t sentFrom, bool doErrorReporting) { + if (getWholeData() == NULL) { + //SHOULDDO: More decent code. + return HasReturnvaluesIF::RETURN_FAILED; + } + TmTcMessage tmMessage(getStoreAddress()); + ReturnValue_t result = MessageQueueSenderIF::sendMessage(destination, &tmMessage, sentFrom); + if (result != HasReturnvaluesIF::RETURN_OK) { + deletePacket(); + if (doErrorReporting) { + checkAndReportLostTm(); + } + return result; + } + //SHOULDDO: In many cases, some counter is incremented for successfully sent packets. The check is often not done, but just incremented. + return HasReturnvaluesIF::RETURN_OK; + +} + +void TmPacketStored::checkAndReportLostTm() { + if (internalErrorReporter == NULL) { + internalErrorReporter = objectManager->get( + objects::INTERNAL_ERROR_REPORTER); + } + if (internalErrorReporter != NULL) { + internalErrorReporter->lostTm(); + } +} diff --git a/tmtcpacket/pus/TmPacketStored.h b/tmtcpacket/pus/TmPacketStored.h index 05037a22..eaa26ce7 100644 --- a/tmtcpacket/pus/TmPacketStored.h +++ b/tmtcpacket/pus/TmPacketStored.h @@ -4,6 +4,8 @@ #include #include #include +#include +#include /** * This class generates a ECSS PUS Telemetry packet within a given @@ -24,6 +26,9 @@ private: * The default store is objects::TM_STORE. */ static StorageManagerIF* store; + + static InternalErrorReporterIF *internalErrorReporter; + /** * The address where the packet data of the object instance is stored. */ @@ -36,6 +41,8 @@ private: * @li \c false otherwise. */ bool checkAndSetStore(); + + void checkAndReportLostTm(); public: /** * This is a default constructor which does not set the data pointer. @@ -81,6 +88,8 @@ public: * @param setAddress The new packet id to link to. */ void setStoreAddress( store_address_t setAddress ); + + ReturnValue_t sendPacket( MessageQueueId_t destination, MessageQueueId_t sentFrom, bool doErrorReporting = true ); }; diff --git a/tmtcservices/AcceptsTelecommandsIF.h b/tmtcservices/AcceptsTelecommandsIF.h index 236f6695..03a57aae 100644 --- a/tmtcservices/AcceptsTelecommandsIF.h +++ b/tmtcservices/AcceptsTelecommandsIF.h @@ -1,7 +1,7 @@ #ifndef ACCEPTSTELECOMMANDSIF_H_ #define ACCEPTSTELECOMMANDSIF_H_ -#include +#include /** * @brief This interface is implemented by classes that are sinks for @@ -11,7 +11,7 @@ */ class AcceptsTelecommandsIF { public: - static const uint8_t INTERFACE_ID = ACCEPTS_TELECOMMANDS_IF; + static const uint8_t INTERFACE_ID = CLASS_ID::ACCEPTS_TELECOMMANDS_IF; static const ReturnValue_t ACTIVITY_STARTED = MAKE_RETURN_CODE(1); static const ReturnValue_t INVALID_SUBSERVICE = MAKE_RETURN_CODE(2); static const ReturnValue_t ILLEGAL_APPLICATION_DATA = MAKE_RETURN_CODE(3); diff --git a/tmtcservices/AcceptsTelemetryIF.h b/tmtcservices/AcceptsTelemetryIF.h index ee974aae..8c00b5c6 100644 --- a/tmtcservices/AcceptsTelemetryIF.h +++ b/tmtcservices/AcceptsTelemetryIF.h @@ -1,7 +1,7 @@ #ifndef ACCEPTSTELEMETRYIF_H_ #define ACCEPTSTELEMETRYIF_H_ -#include +#include /** * @brief This interface is implemented by classes that are sinks for * Telemetry. diff --git a/tmtcservices/AcceptsVerifyMessageIF.h b/tmtcservices/AcceptsVerifyMessageIF.h index 3a499c3d..fe8bb288 100644 --- a/tmtcservices/AcceptsVerifyMessageIF.h +++ b/tmtcservices/AcceptsVerifyMessageIF.h @@ -1,14 +1,7 @@ -/* - * AcceptsVerifyMessageIF.h - * - * Created on: 23.11.2012 - * Author: baetz - */ - #ifndef ACCEPTSVERIFICATIONMESSAGEIF_H_ #define ACCEPTSVERIFICATIONMESSAGEIF_H_ -#include +#include class AcceptsVerifyMessageIF { public: diff --git a/tmtcservices/CommandingServiceBase.h b/tmtcservices/CommandingServiceBase.h index 825b23fa..ecc8b52f 100644 --- a/tmtcservices/CommandingServiceBase.h +++ b/tmtcservices/CommandingServiceBase.h @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -17,6 +16,9 @@ #include #include #include +#include +#include +#include template class CommandingServiceBase: public SystemObject, @@ -24,7 +26,7 @@ class CommandingServiceBase: public SystemObject, public ExecutableObjectIF, public HasReturnvaluesIF { public: - static const uint8_t INTERFACE_ID = COMMAND_SERVICE_BASE; + static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_SERVICE_BASE; static const ReturnValue_t EXECUTION_COMPLETE = MAKE_RETURN_CODE(1); static const ReturnValue_t NO_STEP_MESSAGE = MAKE_RETURN_CODE(2); static const ReturnValue_t OBJECT_BUSY = MAKE_RETURN_CODE(3); @@ -35,10 +37,11 @@ public: CommandingServiceBase(object_id_t setObjectId, uint16_t apid, uint8_t service, uint8_t numberOfParallelCommands, - uint16_t commandTimeout_seconds, size_t queueDepth = 20); + uint16_t commandTimeout_seconds, object_id_t setPacketSource, + object_id_t setPacketDestination, size_t queueDepth = 20); virtual ~CommandingServiceBase(); - virtual ReturnValue_t performOperation(); + virtual ReturnValue_t performOperation(uint8_t opCode); virtual uint16_t getIdentifier(); @@ -74,9 +77,9 @@ protected: StorageManagerIF *TCStore; - MessageQueue commandQueue; + MessageQueueIF* commandQueue; - MessageQueue requestQueue; + MessageQueueIF* requestQueue; VerificationReporter verificationReporter; @@ -85,12 +88,17 @@ protected: uint32_t failureParameter1; //!< May be set be children to return a more precise failure condition. uint32_t failureParameter2; //!< May be set be children to return a more precise failure condition. - void sendTmPacket(uint8_t subservice, const uint8_t *data, - uint32_t dataLen); + object_id_t packetSource; + + object_id_t packetDestination; + + void sendTmPacket(uint8_t subservice, const uint8_t *data, uint32_t dataLen, + const uint8_t* headerData = NULL, uint32_t headerSize = 0); void sendTmPacket(uint8_t subservice, object_id_t objectId, const uint8_t *data, uint32_t dataLen); - void sendTmPacket(uint8_t subservice, SerializeIF* content); + void sendTmPacket(uint8_t subservice, SerializeIF* content, + SerializeIF* header = NULL); virtual ReturnValue_t isValidSubservice(uint8_t subservice) = 0; virtual ReturnValue_t prepareCommand(CommandMessage *message, @@ -110,6 +118,9 @@ protected: virtual void doPeriodicOperation(); + void checkAndExecuteFifo( + typename FixedMap::Iterator *iter); + private: void handleCommandQueue(); @@ -123,29 +134,32 @@ private: void startExecution(TcPacketStored *storedPacket, typename FixedMap::Iterator *iter); - void checkAndExecuteFifo( - typename FixedMap::Iterator *iter); - void checkTimeout(); }; template CommandingServiceBase::CommandingServiceBase(object_id_t setObjectId, uint16_t apid, uint8_t service, uint8_t numberOfParallelCommands, - uint16_t commandTimeout_seconds, size_t queueDepth) : + uint16_t commandTimeout_seconds, object_id_t setPacketSource, + object_id_t setPacketDestination, size_t queueDepth) : SystemObject(setObjectId), apid(apid), service(service), timeout_seconds( commandTimeout_seconds), tmPacketCounter(0), IPCStore(NULL), TCStore( - NULL), commandQueue(queueDepth), requestQueue(20), commandMap( + NULL), commandQueue(NULL), requestQueue(NULL), commandMap( numberOfParallelCommands), failureParameter1(0), failureParameter2( - 0) { + 0), packetSource(setPacketSource), packetDestination( + setPacketDestination) { + commandQueue = QueueFactory::instance()->createMessageQueue(queueDepth); + requestQueue = QueueFactory::instance()->createMessageQueue(20); //TODO: Funny magic number. } template CommandingServiceBase::~CommandingServiceBase() { + QueueFactory::instance()->deleteMessageQueue(commandQueue); + QueueFactory::instance()->deleteMessageQueue(requestQueue); } template -ReturnValue_t CommandingServiceBase::performOperation() { +ReturnValue_t CommandingServiceBase::performOperation(uint8_t opCode) { handleCommandQueue(); handleRequestQueue(); checkTimeout(); @@ -160,7 +174,7 @@ uint16_t CommandingServiceBase::getIdentifier() { template MessageQueueId_t CommandingServiceBase::getRequestQueue() { - return requestQueue.getId(); + return requestQueue->getId(); } template @@ -171,16 +185,15 @@ ReturnValue_t CommandingServiceBase::initialize() { } AcceptsTelemetryIF* packetForwarding = - objectManager->get( - objects::PUS_PACKET_FORWARDING); + objectManager->get(packetDestination); PUSDistributorIF* distributor = objectManager->get( - objects::PUS_PACKET_DISTRIBUTOR); + packetSource); if ((packetForwarding == NULL) && (distributor == NULL)) { return RETURN_FAILED; } distributor->registerService(this); - requestQueue.setDefaultDestination( + requestQueue->setDefaultDestination( packetForwarding->getReportReceptionQueue()); IPCStore = objectManager->get(objects::IPC_STORE); @@ -200,11 +213,15 @@ void CommandingServiceBase::handleCommandQueue() { CommandMessage reply, nextCommand; ReturnValue_t result, sendResult = RETURN_OK; bool isStep = false; - for (result = commandQueue.receiveMessage(&reply); result == RETURN_OK; - result = commandQueue.receiveMessage(&reply)) { + for (result = commandQueue->receiveMessage(&reply); result == RETURN_OK; + result = commandQueue->receiveMessage(&reply)) { isStep = false; typename FixedMap::CommandInfo>::Iterator iter; + if (reply.getSender() == MessageQueueIF::NO_QUEUE) { + handleUnrequestedReply(&reply); + continue; + } if ((iter = commandMap.find(reply.getSender())) == commandMap.end()) { handleUnrequestedReply(&reply); continue; @@ -218,7 +235,7 @@ void CommandingServiceBase::handleCommandQueue() { case NO_STEP_MESSAGE: iter->command = nextCommand.getCommand(); if (nextCommand.getCommand() != CommandMessage::CMD_NONE) { - sendResult = commandQueue.sendMessage(reply.getSender(), + sendResult = commandQueue->sendMessage(reply.getSender(), &nextCommand); } if (sendResult == RETURN_OK) { @@ -249,8 +266,8 @@ void CommandingServiceBase::handleCommandQueue() { verificationReporter.sendFailureReport( TC_VERIFY::COMPLETION_FAILURE, iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, - iter->tcInfo.tcSequenceControl, sendResult, - 0, failureParameter1, failureParameter2); + iter->tcInfo.tcSequenceControl, sendResult, 0, + failureParameter1, failureParameter2); } failureParameter1 = 0; failureParameter2 = 0; @@ -266,7 +283,8 @@ void CommandingServiceBase::handleCommandQueue() { verificationReporter.sendFailureReport( TC_VERIFY::PROGRESS_FAILURE, iter->tcInfo.ackFlags, iter->tcInfo.tcPacketId, iter->tcInfo.tcSequenceControl, - result, ++iter->step, failureParameter1, failureParameter2); + result, ++iter->step, failureParameter1, + failureParameter2); } else { verificationReporter.sendFailureReport( TC_VERIFY::COMPLETION_FAILURE, iter->tcInfo.ackFlags, @@ -290,8 +308,8 @@ void CommandingServiceBase::handleRequestQueue() { TcPacketStored packet; MessageQueueId_t queue; object_id_t objectId; - for (result = requestQueue.receiveMessage(&message); result == RETURN_OK; - result = requestQueue.receiveMessage(&message)) { + for (result = requestQueue->receiveMessage(&message); result == RETURN_OK; + result = requestQueue->receiveMessage(&message)) { address = message.getStorageId(); packet.setStoreAddress(address); @@ -334,12 +352,14 @@ void CommandingServiceBase::handleRequestQueue() { template void CommandingServiceBase::sendTmPacket(uint8_t subservice, - const uint8_t* data, uint32_t dataLen) { + const uint8_t* data, uint32_t dataLen, const uint8_t* headerData, + uint32_t headerSize) { TmPacketStored tmPacketStored(this->apid, this->service, subservice, - this->tmPacketCounter++, data, dataLen); - TmTcMessage tmMessage(tmPacketStored.getStoreAddress()); - if (requestQueue.sendToDefault(&tmMessage) != RETURN_OK) { - tmPacketStored.deletePacket(); + this->tmPacketCounter, data, dataLen, headerData, headerSize); + ReturnValue_t result = tmPacketStored.sendPacket( + requestQueue->getDefaultDestination(), requestQueue->getId()); + if (result == HasReturnvaluesIF::RETURN_OK) { + this->tmPacketCounter++; } } @@ -352,21 +372,24 @@ void CommandingServiceBase::sendTmPacket(uint8_t subservice, SerializeAdapter::serialize(&objectId, &pBuffer, &size, sizeof(object_id_t), true); TmPacketStored tmPacketStored(this->apid, this->service, subservice, - this->tmPacketCounter++, data, dataLen, buffer, size); - TmTcMessage tmMessage(tmPacketStored.getStoreAddress()); - if (requestQueue.sendToDefault(&tmMessage) != RETURN_OK) { - tmPacketStored.deletePacket(); + this->tmPacketCounter, data, dataLen, buffer, size); + ReturnValue_t result = tmPacketStored.sendPacket( + requestQueue->getDefaultDestination(), requestQueue->getId()); + if (result == HasReturnvaluesIF::RETURN_OK) { + this->tmPacketCounter++; } + } template void CommandingServiceBase::sendTmPacket(uint8_t subservice, - SerializeIF* content) { + SerializeIF* content, SerializeIF* header) { TmPacketStored tmPacketStored(this->apid, this->service, subservice, - this->tmPacketCounter++, content); - TmTcMessage tmMessage(tmPacketStored.getStoreAddress()); - if (requestQueue.sendToDefault(&tmMessage) != RETURN_OK) { - tmPacketStored.deletePacket(); + this->tmPacketCounter, content, header); + ReturnValue_t result = tmPacketStored.sendPacket( + requestQueue->getDefaultDestination(), requestQueue->getId()); + if (result == HasReturnvaluesIF::RETURN_OK) { + this->tmPacketCounter++; } } @@ -386,11 +409,11 @@ void CommandingServiceBase::startExecution( switch (result) { case RETURN_OK: if (message.getCommand() != CommandMessage::CMD_NONE) { - sendResult = commandQueue.sendMessage((*iter).value->first, + sendResult = commandQueue->sendMessage((*iter).value->first, &message); } if (sendResult == RETURN_OK) { - OSAL::getUptime(&(*iter)->uptimeOfStart); + Clock::getUptime(&(*iter)->uptimeOfStart); (*iter)->step = 0; // (*iter)->state = 0; (*iter)->subservice = storedPacket->getSubService(); @@ -409,7 +432,7 @@ void CommandingServiceBase::startExecution( case EXECUTION_COMPLETE: if (message.getCommand() != CommandMessage::CMD_NONE) { //Fire-and-forget command. - sendResult = commandQueue.sendMessage((*iter).value->first, + sendResult = commandQueue->sendMessage((*iter).value->first, &message); } if (sendResult == RETURN_OK) { @@ -470,7 +493,7 @@ inline void CommandingServiceBase::doPeriodicOperation() { template void CommandingServiceBase::checkTimeout() { uint32_t uptime; - OSAL::getUptime(&uptime); + Clock::getUptime(&uptime); typename FixedMap::CommandInfo>::Iterator iter; for (iter = commandMap.begin(); iter != commandMap.end(); ++iter) { diff --git a/tmtcservices/PusServiceBase.cpp b/tmtcservices/PusServiceBase.cpp index 882a7237..b5eca15e 100644 --- a/tmtcservices/PusServiceBase.cpp +++ b/tmtcservices/PusServiceBase.cpp @@ -1,30 +1,28 @@ -/* - * PusServiceBase.cpp - * - * Created on: May 9, 2012 - * Author: baetz - */ #include #include #include #include #include #include +#include -PusServiceBase::PusServiceBase(object_id_t setObjectId, uint16_t set_apid, - uint8_t set_service_id) : - SystemObject(setObjectId), apid(set_apid), serviceId(set_service_id), errorParameter1( - 0), errorParameter2(0), requestQueue(PUS_SERVICE_MAX_RECEPTION) { +object_id_t PusServiceBase::packetSource = 0; +object_id_t PusServiceBase::packetDestination = 0; + +PusServiceBase::PusServiceBase(object_id_t setObjectId, uint16_t setApid, uint8_t setServiceId) : + SystemObject(setObjectId), apid(setApid), serviceId(setServiceId), errorParameter1( + 0), errorParameter2(0), requestQueue(NULL) { + requestQueue = QueueFactory::instance()->createMessageQueue(PUS_SERVICE_MAX_RECEPTION); } PusServiceBase::~PusServiceBase() { - + QueueFactory::instance()->deleteMessageQueue(requestQueue); } -ReturnValue_t PusServiceBase::performOperation() { +ReturnValue_t PusServiceBase::performOperation(uint8_t opCode) { TmTcMessage message; for (uint8_t count = 0; count < PUS_SERVICE_MAX_RECEPTION; count++) { - ReturnValue_t status = this->requestQueue.receiveMessage(&message); + ReturnValue_t status = this->requestQueue->receiveMessage(&message); // debug << "PusServiceBase::performOperation: Receiving from MQ ID: " << std::hex << this->requestQueue.getId() << std::dec << " returned: " << status << std::endl; if (status == RETURN_OK) { this->currentPacket.setStoreAddress(message.getStorageId()); @@ -44,7 +42,7 @@ ReturnValue_t PusServiceBase::performOperation() { this->currentPacket.deletePacket(); errorParameter1 = 0; errorParameter2 = 0; - } else if (status == OSAL::QUEUE_EMPTY) { + } else if (status == OperatingSystemIF::QUEUE_EMPTY) { status = RETURN_OK; // debug << "PusService " << (uint16_t)this->serviceId << ": no new packet." << std::endl; break; @@ -73,7 +71,7 @@ uint16_t PusServiceBase::getIdentifier() { } MessageQueueId_t PusServiceBase::getRequestQueue() { - return this->requestQueue.getId(); + return this->requestQueue->getId(); } ReturnValue_t PusServiceBase::initialize() { @@ -82,18 +80,18 @@ ReturnValue_t PusServiceBase::initialize() { return result; } AcceptsTelemetryIF* dest_service = objectManager->get( - objects::PUS_PACKET_FORWARDING); + packetDestination); PUSDistributorIF* distributor = objectManager->get( - objects::PUS_PACKET_DISTRIBUTOR); + packetSource); if ((dest_service != NULL) && (distributor != NULL)) { - this->requestQueue.setDefaultDestination( + this->requestQueue->setDefaultDestination( dest_service->getReportReceptionQueue()); distributor->registerService(this); return RETURN_OK; } else { error << "PusServiceBase::PusServiceBase: Service " << (uint32_t) this->serviceId << ": Configuration error." - << std::endl; + << " Make sure packetSource and packetDestination are defined correctly" << std::endl; return RETURN_FAILED; } } diff --git a/tmtcservices/PusServiceBase.h b/tmtcservices/PusServiceBase.h index 77ac9f4a..08a29634 100644 --- a/tmtcservices/PusServiceBase.h +++ b/tmtcservices/PusServiceBase.h @@ -1,7 +1,6 @@ #ifndef PUSSERVICEBASE_H_ #define PUSSERVICEBASE_H_ -#include #include #include #include @@ -10,6 +9,12 @@ #include #include #include +#include +#include + +namespace Factory{ +void setStaticFrameworkObjectIds(); +} /** * \defgroup pus_services PUS Service Framework @@ -26,44 +31,7 @@ * \ingroup pus_services */ class PusServiceBase : public ExecutableObjectIF, public AcceptsTelecommandsIF, public SystemObject, public HasReturnvaluesIF { -private: - /** - * This constant sets the maximum number of packets accepted per call. - * Remember that one packet must be completely handled in one #handleRequest call. - */ - static const uint8_t PUS_SERVICE_MAX_RECEPTION = 10; -protected: - /** - * The APID of this instance of the Service. - */ - uint16_t apid; - /** - * The Service Identifier. - */ - uint8_t serviceId; - /** - * One of two error parameters for additional error information. - */ - uint32_t errorParameter1; - /** - * One of two error parameters for additional error information. - */ - uint8_t errorParameter2; - /** - * This is a complete instance of the Telecommand reception queue of the class. - * It is initialized on construction of the class. - */ - MessageQueue requestQueue; - /** - * An instance of the VerificationReporter class, that simplifies sending any kind of - * Verification Message to the TC Verification Service. - */ - VerificationReporter verifyReporter; - /** - * The current Telecommand to be processed. - * It is deleted after handleRequest was executed. - */ - TcPacketStored currentPacket; + friend void (Factory::setStaticFrameworkObjectIds)(); public: /** * The constructor for the class. @@ -72,7 +40,7 @@ public: * @param set_apid The APID the Service is instantiated for. * @param set_service_id The Service Identifier as specified in ECSS PUS. */ - PusServiceBase( object_id_t setObjectId, uint16_t set_apid, uint8_t set_service_id ); + PusServiceBase( object_id_t setObjectId, uint16_t setApid, uint8_t setServiceId); /** * The destructor is empty. */ @@ -103,10 +71,52 @@ public: * @return - \c RETURN_OK if the periodic performService was successfull. * - \c RETURN_FAILED else. */ - ReturnValue_t performOperation(); + ReturnValue_t performOperation(uint8_t opCode); virtual uint16_t getIdentifier(); MessageQueueId_t getRequestQueue(); virtual ReturnValue_t initialize(); +protected: + /** + * The APID of this instance of the Service. + */ + uint16_t apid; + /** + * The Service Identifier. + */ + uint8_t serviceId; + /** + * One of two error parameters for additional error information. + */ + uint32_t errorParameter1; + /** + * One of two error parameters for additional error information. + */ + uint8_t errorParameter2; + /** + * This is a complete instance of the Telecommand reception queue of the class. + * It is initialized on construction of the class. + */ + MessageQueueIF* requestQueue; + /** + * An instance of the VerificationReporter class, that simplifies sending any kind of + * Verification Message to the TC Verification Service. + */ + VerificationReporter verifyReporter; + /** + * The current Telecommand to be processed. + * It is deleted after handleRequest was executed. + */ + TcPacketStored currentPacket; + + static object_id_t packetSource; + + static object_id_t packetDestination; +private: + /** + * This constant sets the maximum number of packets accepted per call. + * Remember that one packet must be completely handled in one #handleRequest call. + */ + static const uint8_t PUS_SERVICE_MAX_RECEPTION = 10; }; #endif /* PUSSERVICEBASE_H_ */ diff --git a/tmtcservices/PusVerificationReport.cpp b/tmtcservices/PusVerificationReport.cpp index 7e479b65..1bc53c2a 100644 --- a/tmtcservices/PusVerificationReport.cpp +++ b/tmtcservices/PusVerificationReport.cpp @@ -1,10 +1,3 @@ -/* - * PusVerificationReport.cpp - * - * Created on: 22.05.2012 - * Author: baetz - */ - #include #include diff --git a/tmtcservices/PusVerificationReport.h b/tmtcservices/PusVerificationReport.h index c48e7d5e..7a173be9 100644 --- a/tmtcservices/PusVerificationReport.h +++ b/tmtcservices/PusVerificationReport.h @@ -1,10 +1,3 @@ -/* - * PusVerificationReport.h - * - * Created on: 22.05.2012 - * Author: baetz - */ - #ifndef PUSVERIFICATIONREPORT_H_ #define PUSVERIFICATIONREPORT_H_ diff --git a/tmtcservices/TmTcMessage.cpp b/tmtcservices/TmTcMessage.cpp index da2c8bd3..d437b41e 100644 --- a/tmtcservices/TmTcMessage.cpp +++ b/tmtcservices/TmTcMessage.cpp @@ -1,4 +1,5 @@ #include +#include TmTcMessage::TmTcMessage() { diff --git a/tmtcservices/VerificationCodes.h b/tmtcservices/VerificationCodes.h index d7f81d0d..e3e89b5a 100644 --- a/tmtcservices/VerificationCodes.h +++ b/tmtcservices/VerificationCodes.h @@ -1,10 +1,3 @@ -/* - * VerificationCodes.h - * - * Created on: Aug 8, 2012 - * Author: baetz - */ - #ifndef VERIFICATIONCODES_H_ #define VERIFICATIONCODES_H_ diff --git a/tmtcservices/VerificationReporter.cpp b/tmtcservices/VerificationReporter.cpp index 4f7f37a0..36abbeb8 100644 --- a/tmtcservices/VerificationReporter.cpp +++ b/tmtcservices/VerificationReporter.cpp @@ -1,17 +1,12 @@ -/* - * VerificationReporter.cpp - * - * Created on: 20.07.2012 - * Author: baetz - */ - #include #include #include #include +object_id_t VerificationReporter::messageReceiver = 0; + VerificationReporter::VerificationReporter() : - acknowledge_queue() { + acknowledgeQueue() { } VerificationReporter::~VerificationReporter() { @@ -20,12 +15,15 @@ VerificationReporter::~VerificationReporter() { void VerificationReporter::sendSuccessReport(uint8_t set_report_id, TcPacketBase* current_packet, uint8_t set_step) { - if (this->acknowledge_queue.getDefaultDestination() == 0) { + if (this->acknowledgeQueue == 0) { this->initialize(); } - PusVerificationMessage message(set_report_id, current_packet->getAcknowledgeFlags(), current_packet->getPacketId(), current_packet->getPacketSequenceControl(), set_step); - ReturnValue_t status = this->acknowledge_queue.sendToDefault(&message); - if (status != OSAL::RETURN_OK) { + PusVerificationMessage message(set_report_id, + current_packet->getAcknowledgeFlags(), + current_packet->getPacketId(), + current_packet->getPacketSequenceControl(), 0, set_step); + ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, &message); + if (status != HasReturnvaluesIF::RETURN_OK) { error << "VerificationReporter::sendSuccessReport: Error writing to queue. Code: " << (uint16_t) status << std::endl; @@ -33,13 +31,15 @@ void VerificationReporter::sendSuccessReport(uint8_t set_report_id, } void VerificationReporter::sendSuccessReport(uint8_t set_report_id, - uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, uint8_t set_step) { - if (this->acknowledge_queue.getDefaultDestination() == 0) { + uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, + uint8_t set_step) { + if (this->acknowledgeQueue == 0) { this->initialize(); } - PusVerificationMessage message(set_report_id, ackFlags, tcPacketId, tcSequenceControl, set_step); - ReturnValue_t status = this->acknowledge_queue.sendToDefault(&message); - if (status != OSAL::RETURN_OK) { + PusVerificationMessage message(set_report_id, ackFlags, tcPacketId, + tcSequenceControl, 0, set_step); + ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, &message); + if (status != HasReturnvaluesIF::RETURN_OK) { error << "VerificationReporter::sendSuccessReport: Error writing to queue. Code: " << (uint16_t) status << std::endl; @@ -49,13 +49,16 @@ void VerificationReporter::sendSuccessReport(uint8_t set_report_id, void VerificationReporter::sendFailureReport(uint8_t report_id, TcPacketBase* current_packet, ReturnValue_t error_code, uint8_t step, uint32_t parameter1, uint32_t parameter2) { - if (this->acknowledge_queue.getDefaultDestination() == 0) { + if (this->acknowledgeQueue == 0) { this->initialize(); } - PusVerificationMessage message(report_id, current_packet->getAcknowledgeFlags(), current_packet->getPacketId(), current_packet->getPacketSequenceControl(), error_code, step, + PusVerificationMessage message(report_id, + current_packet->getAcknowledgeFlags(), + current_packet->getPacketId(), + current_packet->getPacketSequenceControl(), error_code, step, parameter1, parameter2); - ReturnValue_t status = this->acknowledge_queue.sendToDefault(&message); - if (status != OSAL::RETURN_OK) { + ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, &message); + if (status != HasReturnvaluesIF::RETURN_OK) { error << "VerificationReporter::sendFailureReport Error writing to queue. Code: " << (uint16_t) status << std::endl; @@ -63,15 +66,16 @@ void VerificationReporter::sendFailureReport(uint8_t report_id, } void VerificationReporter::sendFailureReport(uint8_t report_id, - uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, ReturnValue_t error_code, uint8_t step, - uint32_t parameter1, uint32_t parameter2) { - if (this->acknowledge_queue.getDefaultDestination() == 0) { + uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, + ReturnValue_t error_code, uint8_t step, uint32_t parameter1, + uint32_t parameter2) { + if (this->acknowledgeQueue == 0) { this->initialize(); } - PusVerificationMessage message(report_id, ackFlags, tcPacketId, tcSequenceControl, error_code, step, - parameter1, parameter2); - ReturnValue_t status = this->acknowledge_queue.sendToDefault(&message); - if (status != OSAL::RETURN_OK) { + PusVerificationMessage message(report_id, ackFlags, tcPacketId, + tcSequenceControl, error_code, step, parameter1, parameter2); + ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, &message); + if (status != HasReturnvaluesIF::RETURN_OK) { error << "VerificationReporter::sendFailureReport Error writing to queue. Code: " << (uint16_t) status << std::endl; @@ -80,10 +84,9 @@ void VerificationReporter::sendFailureReport(uint8_t report_id, void VerificationReporter::initialize() { AcceptsVerifyMessageIF* temp = objectManager->get( - objects::PUS_VERIFICATION_SERVICE); + messageReceiver); if (temp != NULL) { - this->acknowledge_queue.setDefaultDestination( - temp->getVerificationQueue()); + this->acknowledgeQueue = temp->getVerificationQueue(); } else { error << "VerificationReporter::VerificationReporter: Configuration error." diff --git a/tmtcservices/VerificationReporter.h b/tmtcservices/VerificationReporter.h index ee8278d1..370c44c8 100644 --- a/tmtcservices/VerificationReporter.h +++ b/tmtcservices/VerificationReporter.h @@ -1,20 +1,15 @@ -/* - * VerificationReporter.h - * - * Created on: 20.07.2012 - * Author: baetz - */ - #ifndef VERIFICATIONREPORTER_H_ #define VERIFICATIONREPORTER_H_ -#include #include #include +namespace Factory{ +void setStaticFrameworkObjectIds(); +} + class VerificationReporter { -protected: - MessageQueueSender acknowledge_queue; + friend void (Factory::setStaticFrameworkObjectIds)(); public: VerificationReporter(); virtual ~VerificationReporter(); @@ -26,6 +21,11 @@ public: uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, ReturnValue_t error_code = 0, uint8_t step = 0, uint32_t parameter1 = 0, uint32_t parameter2 = 0); void initialize(); +private: + static object_id_t messageReceiver; + MessageQueueId_t acknowledgeQueue; + + }; #endif /* VERIFICATIONREPORTER_H_ */ diff --git a/watchdog/Watchdog.cpp b/watchdog/Watchdog.cpp deleted file mode 100644 index 237fb5f7..00000000 --- a/watchdog/Watchdog.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include - -extern "C" { -#include -} - -#include -#include - -Watchdog::Watchdog(object_id_t objectId, uint32_t interval_us, uint32_t initial_interval_us) : - SystemObject(objectId), commandQueue(3, - WatchdogMessage::WATCHDOG_MESSAGE_SIZE) { - hw_timer_set_reload_value(hw_timer_watchdog, interval_us); - hw_timer_start_(hw_timer_watchdog, initial_interval_us); - hw_timer_watchdog ->control_register |= 8; - - hw_gpio_port ->direction |= (HW_GPIO_DDR_OUT << HW_GPIO_LEON_WD_EN); - hw_gpio_port ->output |= (HW_GPIO_DDR_OUT << HW_GPIO_LEON_WD_EN); -} - -Watchdog::~Watchdog() { -} - -ReturnValue_t Watchdog::performOperation() { - WatchdogMessage message; - ReturnValue_t result = commandQueue.receiveMessage(&message); - if (result != HasReturnvaluesIF::RETURN_OK) { - hw_timer_reload(hw_timer_watchdog ); - } else { - debug << "Watchdog::performOperation: Object 0x" << std::hex - << message.getSender() << std::dec << " requested "; - switch (message.getCommand()) { - case WatchdogMessage::ENABLE: - debug << "watchdog enable" << std::endl; - hw_timer_reload(hw_timer_watchdog ); - hw_timer_start(hw_timer_watchdog ); - break; - case WatchdogMessage::DISABLE: - debug << "watchdog disable" << std::endl; - hw_timer_stop(hw_timer_watchdog ); - break; - case WatchdogMessage::RESET_CPU: - debug << "CPU reset" << std::endl; - hw_timer_start_(hw_timer_watchdog, 10); - break; - } - } - return HasReturnvaluesIF::RETURN_OK; -} - -MessageQueueId_t Watchdog::getCommandQueue() { - return commandQueue.getId(); -} - diff --git a/watchdog/Watchdog.h b/watchdog/Watchdog.h deleted file mode 100644 index 373e1dc5..00000000 --- a/watchdog/Watchdog.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef WATCHDOG_H_ -#define WATCHDOG_H_ - -#include -#include -#include -#include - -class Watchdog: public ExecutableObjectIF, public SystemObject { -public: - Watchdog(object_id_t objectId, uint32_t interval_us, uint32_t initial_interval_us); - virtual ~Watchdog(); - virtual ReturnValue_t performOperation(); - - MessageQueueId_t getCommandQueue(); -protected: - MessageQueue commandQueue; -}; - -#endif /* WATCHDOG_H_ */ diff --git a/watchdog/WatchdogMessage.cpp b/watchdog/WatchdogMessage.cpp deleted file mode 100644 index 7e92e0cb..00000000 --- a/watchdog/WatchdogMessage.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include - -WatchdogMessage::WatchdogMessage() { - messageSize = WATCHDOG_MESSAGE_SIZE; -} - -WatchdogMessage::WatchdogMessage(object_id_t sender, - WatchdogCommand_t command) { - messageSize = WATCHDOG_MESSAGE_SIZE; - setSender(sender); - setCommand(command); -} - -WatchdogMessage::WatchdogCommand_t WatchdogMessage::getCommand() { - WatchdogCommand_t command; - memcpy(&command, getData() + sizeof(object_id_t), - sizeof(WatchdogCommand_t)); - return command; -} - -void WatchdogMessage::setCommand(WatchdogCommand_t command) { - memcpy(getData() + sizeof(object_id_t), &command, - sizeof(WatchdogCommand_t)); -} - -object_id_t WatchdogMessage::getSender() { - object_id_t sender; - memcpy(&sender, getData(), sizeof(object_id_t)); - return sender; -} - -void WatchdogMessage::setSender(object_id_t sender) { - memcpy(getData(), &sender, sizeof(object_id_t)); -} - -WatchdogMessage::~WatchdogMessage() { - -} - -size_t WatchdogMessage::getMinimumMessageSize() { - return WATCHDOG_MESSAGE_SIZE; -} diff --git a/watchdog/WatchdogMessage.h b/watchdog/WatchdogMessage.h deleted file mode 100644 index a08c83fd..00000000 --- a/watchdog/WatchdogMessage.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef WATCHDOGMESSAGE_H_ -#define WATCHDOGMESSAGE_H_ - -#include -#include - -class WatchdogMessage: public MessageQueueMessage { -public: - /** - * Commands that can be sent to the watchdog - */ - enum WatchdogCommand_t{ - ENABLE, //!< Enables the Watchdog (it is enabled by default) - DISABLE,//!< Disables the watchdog - RESET_CPU //!< Causes a reset of the Processor - }; - - static const uint8_t WATCHDOG_MESSAGE_SIZE = HEADER_SIZE + sizeof(object_id_t) + sizeof(WatchdogCommand_t); - - WatchdogMessage(); - WatchdogMessage(object_id_t sender, WatchdogCommand_t command); - virtual ~WatchdogMessage(); - WatchdogCommand_t getCommand(); - void setCommand(WatchdogCommand_t command); - object_id_t getSender(); - void setSender(object_id_t sender); - -protected: - virtual size_t getMinimumMessageSize(); -}; - -#endif /* WATCHDOGMESSAGE_H_ */