updating code from Flying Laptop

This is the framework of Flying Laptop OBSW version A.13.0.
This commit is contained in:
Ulrich Mohr 2018-07-12 16:29:32 +02:00
parent 1d22a6c97e
commit 575f70ba03
395 changed files with 12807 additions and 8404 deletions

202
LICENSE Normal file
View File

@ -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.

21
NOTICE Normal file
View File

@ -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/

View File

@ -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.

View File

@ -1,8 +1,7 @@
#include <framework/action/ActionHelper.h>
#include <framework/action/HasActionsIF.h>
#include <framework/objectmanager/ObjectManagerIF.h>
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;
}

View File

@ -1,25 +1,26 @@
#ifndef ACTIONHELPER_H_
#define ACTIONHELPER_H_
#include <framework/action/ActionMessage.h>
#include <framework/serialize/SerializeIF.h>
#include <framework/ipc/MessageQueueIF.h>
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();

View File

@ -1,4 +1,3 @@
#include <framework/action/ActionMessage.h>
#include <framework/objectmanager/ObjectManagerIF.h>
#include <framework/storagemanager/StorageManagerIF.h>

View File

@ -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);

View File

@ -1,4 +1,3 @@
#include <framework/action/ActionMessage.h>
#include <framework/action/CommandActionHelper.h>
#include <framework/action/CommandsActionsIF.h>

View File

@ -1,13 +1,12 @@
#ifndef COMMANDACTIONHELPER_H_
#define COMMANDACTIONHELPER_H_
#include <framework/action/ActionMessage.h>
#include <framework/ipc/MessageQueue.h>
#include <framework/objectmanager/ObjectManagerIF.h>
#include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/serialize/SerializeIF.h>
#include <framework/storagemanager/StorageManagerIF.h>
#include <framework/ipc/MessageQueueIF.h>
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;

View File

@ -1,10 +1,9 @@
#ifndef COMMANDSACTIONSIF_H_
#define COMMANDSACTIONSIF_H_
#include <framework/action/CommandActionHelper.h>
#include <framework/ipc/MessageQueue.h>
#include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/ipc/MessageQueueIF.h>
/**
* 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;

View File

@ -1,21 +1,14 @@
/*
* HasActionsIF.h
*
* Created on: 20.02.2014
* Author: baetz
*/
#ifndef HASACTIONSIF_H_
#define HASACTIONSIF_H_
#include <framework/action/ActionHelper.h>
#include <framework/action/ActionMessage.h>
#include <framework/action/SimpleActionHelper.h>
#include <framework/ipc/MessageQueue.h>
#include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/ipc/MessageQueueIF.h>
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);

View File

@ -1,8 +1,7 @@
#include <framework/action/HasActionsIF.h>
#include <framework/action/SimpleActionHelper.h>
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() {

View File

@ -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);

View File

@ -17,7 +17,7 @@ template<typename T, typename count_t = uint8_t>
class ArrayList {
template<typename U, typename count> 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<T, count_t>::Iterator& other) {
bool operator==(const typename ArrayList<T, count_t>::Iterator& other) const{
return (value == other.value);
}
//SHOULDDO this should be implemented as non-member
bool operator!=(const typename ArrayList<T, count_t>::Iterator& other) {
bool operator!=(const typename ArrayList<T, count_t>::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<T*>(static_cast<const T*>(*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
*/

View File

@ -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;

View File

@ -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);
};

View File

@ -9,7 +9,7 @@
template<typename key_t, typename T>
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);

View File

@ -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<typename key_t, typename T, typename KEY_COMPARE = std::less<key_t>>
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);

View File

@ -0,0 +1,700 @@
#ifndef FRAMEWORK_CONTAINER_INDEXEDRINGMEMORY_H_
#define FRAMEWORK_CONTAINER_INDEXEDRINGMEMORY_H_
#include <framework/container/ArrayList.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/serialize/SerialArrayListAdapter.h>
#include <framework/globalfunctions/crc_ccitt.h>
#include <cmath>
template<typename T>
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<SerializeIF,T>::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<T>& other){
return ((blockStartAddress == other.getBlockStartAddress()) && (size==other.getSize())) && (indexType == *(other.getIndexType()));
}
private:
uint32_t blockStartAddress;
uint32_t size;
uint32_t storedPackets;
T indexType;
};
template<typename T>
class IndexedRingMemoryArray: public SerializeIF, public ArrayList<Index<T>, 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<Index<T>,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<double>(size)/static_cast<double>(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<T> 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<double>(totalSize) / static_cast<double>(bytesPerBlock));
//allocate memory now
this->entries = new Index<T>[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<T>::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((lastBlockSize<bytesPerBlock) && (this->size > 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<T>::Iterator it = this->begin();it!=this->end();++it){
it->setSize(0);
it->setStoredPackets(0);
(*typeResetFnc)(it->modifyIndexType());
}
}
void resetBlock(typename IndexedRingMemoryArray<T>::Iterator it,void (*typeResetFnc)(T*)){
it->setSize(0);
it->setStoredPackets(0);
(*typeResetFnc)(it->modifyIndexType());
}
/*
* Reading
*/
void setCurrentReadBlock(typename IndexedRingMemoryArray<T>::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<T>::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)<lastBlockToReadSize){
//the block has more data -> 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)<currentReadBlockSizeCached){
//The current Block has more data
currentReadSize += readSize;
return true;
}else{
//The current block is written completely
readNext();
if(currentReadBlockSizeCached==0){
//Next block is empty
typename IndexedRingMemoryArray<T>::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<T>::Iterator getNextNonEmptyBlock() const {
for(typename IndexedRingMemoryArray<T>::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<T>::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<T>::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<T>::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<Index<T> >::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<T> 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<Index<T> >::deSerialize(
&this->entries[i], buffer, size,
bigEndian);
++i;
}
if(result != HasReturnvaluesIF::RETURN_OK){
return result;
}
typename IndexedRingMemoryArray<T>::Iterator cmp(&tempIndex);
for(typename IndexedRingMemoryArray<T>::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<T>::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<T>::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<T>::Iterator it= this->begin();it!=this->end();++it){
filledSize += it->getSize();
}
return (double)filledSize/(double)this->totalSize;
}
typename IndexedRingMemoryArray<T>::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<T>::Iterator getNextWrite() const{
typename IndexedRingMemoryArray<T>::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<T>::Iterator getPreviousBlock(typename IndexedRingMemoryArray<T>::Iterator it) {
if(this->begin() == it){
typename IndexedRingMemoryArray<T>::Iterator next((this->back()));
return next;
}
typename IndexedRingMemoryArray<T>::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<T>::Iterator currentWriteBlock;
typename IndexedRingMemoryArray<T>::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<T>::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_ */

View File

@ -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 <framework/container/SinglyLinkedList.h>
#include <utility>
//TODO: This generates multiple inheritance from non-IF parents.
template<typename T, typename IF_T>
class LinkedElementDecorator : public LinkedElement<IF_T>, public T {
public:
template<typename... Args>
LinkedElementDecorator(Args... args) : LinkedElement<IF_T>(this), T(std::forward<Args>(args)...) {
}
virtual ~LinkedElementDecorator() {
}
};
#endif /* LINKEDELEMENTDECORATOR_H_ */

View File

@ -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<typename T>
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));
}

View File

@ -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];

View File

@ -0,0 +1,79 @@
#include <iostream>
#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<sizeof(buffer2); count++) {
buffer2[count] = count;
}
result = buffer.writeData(buffer2, sizeof(buffer2));
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "writeData failed." << endl;
}
result = buffer.writeData(buffer2, sizeof(buffer2));
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "writeData failed." << endl;
}
uint8_t readBuffer[64] = {0};
uint32_t writtenData = 0;
result = buffer.readData(readBuffer, 12, true, &writtenData);
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "readData failed." << endl;
} else {
cout << "Read data: " << writtenData << endl;
for (uint32_t count = 0; count < writtenData; count++) {
cout << hex << (uint16_t)readBuffer[count] << " ";
}
cout << dec << endl;
}
result = buffer.readData(readBuffer, 60, true, &writtenData);
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "readData failed." << endl;
} else {
cout << "Read data: " << writtenData << endl;
for (uint32_t count = 0; count < writtenData; count++) {
cout << hex << (uint16_t)readBuffer[count] << " ";
}
cout << dec << endl;
}
result = buffer.writeData(data, sizeof(data));
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "writeData failed." << endl;
}
result = buffer.readData(readBuffer, 60, true, &writtenData);
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "readData failed." << endl;
} else {
cout << "Read data: " << writtenData << endl;
for (uint32_t count = 0; count < writtenData; count++) {
cout << hex << (uint16_t)readBuffer[count] << " ";
}
cout << dec << endl;
}
result = buffer.writeData(readBuffer, sizeof(readBuffer));
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "writeData failed." << endl;
}
result = buffer.writeData(readBuffer, sizeof(readBuffer)-1);
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "writeData failed." << endl;
} else {
cout << "write done." << endl;
}
}

View File

@ -0,0 +1,68 @@
#include <framework/container/SimpleRingBuffer.h>
#include <string.h>
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;
}

View File

@ -0,0 +1,21 @@
#ifndef FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_
#define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_
#include <framework/container/RingBufferBase.h>
#include <stddef.h>
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_ */

View File

@ -49,7 +49,7 @@ public:
virtual ~LinkedElement(){
}
virtual LinkedElement* const getNext() const {
virtual LinkedElement* getNext() const {
return next;
}

4
contrib/sgp4/LICENSE Normal file
View File

@ -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.

2090
contrib/sgp4/sgp4unit.cpp Normal file

File diff suppressed because it is too large Load Diff

117
contrib/sgp4/sgp4unit.h Normal file
View File

@ -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 <math.h>
#include <stdio.h>
// -------------------------- 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

View File

@ -1,15 +1,20 @@
#include <framework/subsystem/SubsystemBase.h>
#include <framework/controller/ControllerBase.h>
#include <framework/subsystem/SubsystemBase.h>
#include <framework/ipc/QueueFactory.h>
#include <framework/action/HasActionsIF.h>
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) {
}

View File

@ -7,6 +7,8 @@
#include <framework/modes/ModeHelper.h>
#include <framework/objectmanager/SystemObject.h>
#include <framework/tasks/ExecutableObjectIF.h>
#include <framework/datapool/HkSwitchHelper.h>
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_ */

View File

@ -6,36 +6,31 @@
#include <cmath>
//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,24 +60,97 @@ 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);
timeval timeUTC;
if (timeUTCin != NULL) {
timeUTC = *timeUTCin;
} else {
Clock::getClock_timeval(&timeUTC);
}
//value of unix time at J2000TT
static const double J2000TtUnix = 946727935.816;
double Tfi[3][3];
double Tif[3][3];
getTransMatrixECITOECF(timeUTC,Tfi);
//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;
MatrixOperations<double>::transpose(Tfi[0], Tif[0], 3);
//Julean centuries since J2000 //TODO fails for dates before now?
double TTt2000 = (time.tv_sec + time.tv_usec / 1000000. - J2000TtUnix
+ leapSecondsSinceJ2000) / 24. / 3600. / 36525.;
MatrixOperations<double>::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 } };
MatrixOperations<double>::multiply(Trot[0], Tfi[0], Tdotfi[0], 3, 3,
3);
MatrixOperations<double>::transpose(Tdotfi[0], Tdotif[0], 3);
double velocityCorrection[3];
MatrixOperations<double>::multiply(Tdotif[0],
ecfPositionIfCoordinatesAreVelocity, velocityCorrection, 3, 3,
1);
VectorOperations<double>::add(velocityCorrection, eciCoordinates,
eciCoordinates, 3);
}
}
double CoordinateTransformations::getJuleanCenturiesTT(timeval timeUTC) {
timeval timeTT;
Clock::convertUTCToTT(timeUTC, &timeTT);
double jD2000TT;
Clock::convertTimevalToJD2000(timeTT, &jD2000TT);
return jD2000TT / 36525.;
}
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);
}
double Tfi[3][3];
getTransMatrixECITOECF(timeUTC,Tfi);
MatrixOperations<double>::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<double>::multiply(Trot[0], Tfi[0], Tdotfi[0], 3, 3,
3);
double velocityCorrection[3];
MatrixOperations<double>::multiply(Tdotfi[0],
eciPositionIfCoordinatesAreVelocity, velocityCorrection, 3, 3,
1);
VectorOperations<double>::add(ecfCoordinates, velocityCorrection,
ecfCoordinates, 3);
}
};
void CoordinateTransformations::getTransMatrixECITOECF(timeval timeUTC,double Tfi[3][3]){
double TTt2000 = getJuleanCenturiesTT(timeUTC);
//////////////////////////////////////////////////////////
// Calculate Precession Matrix
@ -124,6 +192,7 @@ void CoordinateTransformations::ecfToEci(const double* ecfCoordinates,
- 2.86040071854626E-009 * TTt2000 * TTt2000
+ 8.78967203851589E-009 * TTt2000 * TTt2000 * TTt2000;
double mNutation[3][3];
mNutation[0][0] = cos(deltaPsi);
@ -144,63 +213,15 @@ void CoordinateTransformations::ecfToEci(const double* ecfCoordinates,
//////////////////////////////////////////////////////////
// Calculate Earth rotation matrix
//calculate theta
double mTheta[3][3];
getEarthRotationMatrix(time, mTheta);
double Ttemp[3][3];
getEarthRotationMatrix(timeUTC, mTheta);
//polar motion is neglected
double Tfi[3][3];
double Ttemp[3][3];
double Tif[3][3];
MatrixOperations<double>::multiply(mNutation[0], mPrecession[0], Ttemp[0],
3, 3, 3);
MatrixOperations<double>::multiply(mTheta[0], Ttemp[0], Tfi[0], 3, 3, 3);
MatrixOperations<double>::transpose(Tfi[0], Tif[0], 3);
MatrixOperations<double>::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<double>::multiply(mNutation[0], mPrecession[0],
Ttemp[0], 3, 3, 3);
MatrixOperations<double>::multiply(mTheta[0], Ttemp[0], Ttemp2[0], 3, 3,
3);
MatrixOperations<double>::multiply(Trot[0], Ttemp2[0], Tdotfi[0], 3, 3,
3);
MatrixOperations<double>::transpose(Tdotfi[0], Tdotif[0], 3);
double velocityCorrection[3];
MatrixOperations<double>::multiply(Tdotif[0],
ecfPositionIfCoordinatesAreVelocity, velocityCorrection, 3, 3,
1);
VectorOperations<double>::add(velocityCorrection, eciCoordinates,
eciCoordinates, 3);
}
}
CoordinateTransformations::CoordinateTransformations(uint8_t offset) :
utcGpsOffset(offset) {
}
CoordinateTransformations::~CoordinateTransformations() {
}
void CoordinateTransformations::setUtcGpsOffset(uint8_t offset) {
}
};

View File

@ -1,28 +1,32 @@
#ifndef COORDINATETRANSFORMATIONS_H_
#define COORDINATETRANSFORMATIONS_H_
#include <framework/osal/OSAL.h>
#include <framework/timemanager/Clock.h>
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]);
};

180
coordinates/Jgm3Model.h Normal file
View File

@ -0,0 +1,180 @@
#ifndef FRAMEWORK_COORDINATES_JGM3MODEL_H_
#define FRAMEWORK_COORDINATES_JGM3MODEL_H_
#include <stdint.h>
#include <framework/coordinates/CoordinateTransformations.h>
#include <framework/globalfunctions/math/VectorOperations.h>
#include <framework/globalfunctions/timevalOperations.h>
#include <framework/globalfunctions/constants.h>
#include <memory.h>
template<uint8_t DEGREE,uint8_t ORDER>
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<double>::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<double>(factorialLookupTable[n-m+2]) / static_cast<double>(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<DEGREE;n++)
}//End of uint8_t m=0;m<ORDER;m++
}
void initializeNavOrbit(const double position[3],const double velocity[3], timeval timeUTC){
CoordinateTransformations::positionEcfToEci(position,&y0[0],&timeUTC);
CoordinateTransformations::velocityEcfToEci(velocity,position,&y0[3],&timeUTC);
lastExecutionTime = timeUTC;
}
void acsNavOrbit(timeval timeUTC, const double S[ORDER+1][DEGREE+1],const double C[ORDER+1][DEGREE+1], double outputPos[3],double outputVel[3]){
//RK4 Integration for this timestamp
double deltaT = timevalOperations::toDouble(timeUTC-lastExecutionTime);
double y0dot[6] = {0,0,0,0,0,0};
double yA[6] = {0,0,0,0,0,0};
double yAdot[6] = {0,0,0,0,0,0};
double yB[6] = {0,0,0,0,0,0};
double yBdot[6] = {0,0,0,0,0,0};
double yC[6] = {0,0,0,0,0,0};
double yCdot[6] = {0,0,0,0,0,0};
//Step One
rungeKuttaStep(y0,y0dot,lastExecutionTime,S,C);
//Step Two
VectorOperations<double>::mulScalar(y0dot,deltaT/2,yA,6);
VectorOperations<double>::add(y0,yA,yA,6);
rungeKuttaStep(yA,yAdot,lastExecutionTime,S,C);
//Step Three
VectorOperations<double>::mulScalar(yAdot,deltaT/2,yB,6);
VectorOperations<double>::add(y0,yB,yB,6);
rungeKuttaStep(yB,yBdot,lastExecutionTime,S,C);
//Step Four
VectorOperations<double>::mulScalar(yBdot,deltaT,yC,6);
VectorOperations<double>::add(y0,yC,yC,6);
rungeKuttaStep(yC,yCdot,lastExecutionTime,S,C);
//Calc new State
VectorOperations<double>::mulScalar(yAdot,2,yAdot,6);
VectorOperations<double>::mulScalar(yBdot,2,yBdot,6);
VectorOperations<double>::add(y0dot,yAdot,y0dot,6);
VectorOperations<double>::add(y0dot,yBdot,y0dot,6);
VectorOperations<double>::add(y0dot,yCdot,y0dot,6);
VectorOperations<double>::mulScalar(y0dot,1./6.*deltaT,y0dot,6);
VectorOperations<double>::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_ */

View File

@ -1,14 +1,12 @@
#include <framework/osal/OSAL.h>
#include <framework/coordinates/CoordinateTransformations.h>
#include <framework/coordinates/Sgp4Propagator.h>
#include <framework/globalfunctions/constants.h>
#include <framework/globalfunctions/math/MatrixOperations.h>
#include <framework/globalfunctions/math/VectorOperations.h>
#include <framework/globalfunctions/timevalOperations.h>
#include <framework/osal/OSAL.h>
#include <cstring>
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<double>::multiply(earthRotationMatrix[0], positionTEME,
@ -221,7 +221,7 @@ ReturnValue_t Sgp4Propagator::propagate(double* position, double* velocity,
VectorOperations<double>::subtract(velocity, velocityCorrection, velocity);
if (result != 0) {
return MAKE_RETURN_CODE(result);
return MAKE_RETURN_CODE(result || 0xB0);
} else {
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -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;

View File

@ -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.

View File

@ -1,13 +1,5 @@
/*
* DataLinkLayer.cpp
*
* Created on: 02.03.2012
* Author: baetz
*/
#include <framework/datalinklayer/DataLinkLayer.h>
#include <framework/globalfunctions/crc_ccitt.h>
#include <framework/osal/OSAL.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
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(&currentFrame, 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();

View File

@ -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<uint8_t, VirtualChannelReceptionIF*> 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();
/**

View File

@ -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;

View File

@ -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 );

View File

@ -6,17 +6,19 @@
*/
#include <framework/datalinklayer/MapPacketExtraction.h>
#include <framework/ipc/QueueFactory.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <framework/storagemanager/StorageManagerIF.h>
#include <framework/tmtcpacket/SpacePacketBase.h>
#include <framework/tmtcservices/AcceptsTelecommandsIF.h>
#include <framework/tmtcservices/TmTcMessage.h>
#include <string.h>
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;

View File

@ -9,9 +9,10 @@
#define MAPPACKETEXTRACTION_H_
#include <framework/datalinklayer/MapPacketExtractionIF.h>
#include <framework/ipc/MessageQueueSender.h>
#include <framework/objectmanager/ObjectManagerIF.h>
#include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/ipc/MessageQueueSenderIF.h>
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);

View File

@ -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) {

View File

@ -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 );
/**

View File

@ -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;
/**

View File

@ -0,0 +1,14 @@
#include <framework/datapool/ControllerSet.h>
ControllerSet::ControllerSet() {
}
ControllerSet::~ControllerSet() {
}
void ControllerSet::setInvalid() {
read();
setToDefault();
commit(PoolVariableIF::INVALID);
}

15
datapool/ControllerSet.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef CONTROLLERSET_H_
#define CONTROLLERSET_H_
#include <framework/datapool/DataSet.h>
class ControllerSet :public DataSet {
public:
ControllerSet();
virtual ~ControllerSet();
virtual void setToDefault() = 0;
void setInvalid();
};
#endif /* CONTROLLERSET_H_ */

View File

@ -1,24 +1,16 @@
/*
* DataPool.cpp
*
* Created on: 17.10.2012
* Author: baetz
*/
#include <framework/datapool/DataPool.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <framework/ipc/MutexFactory.h>
DataPool::DataPool( void ( *initFunction )( std::map<uint32_t, PoolEntryIF*>* 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<uint32_t, PoolEntryIF*>::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<uint32_t, PoolEntryIF*>::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;
}
}

View File

@ -13,7 +13,7 @@
#include <framework/datapool/PoolEntry.h>
#include <framework/globalfunctions/Type.h>
#include <framework/osal/OSAL.h>
#include <framework/ipc/MutexIF.h>
#include <map>
/**
@ -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_ */

View File

@ -1,67 +1,126 @@
/*
* DataPoolAdmin.cpp
*
* Created on: 05.12.2013
* Author: baetz
*/
#include <framework/datapool/DataPool.h>
#include <framework/datapool/DataPoolAdmin.h>
#include <framework/datapool/DataSet.h>
#include <framework/datapool/PoolRawAccess.h>
#include <framework/ipc/CommandMessage.h>
#include <framework/ipc/QueueFactory.h>
#include <framework/parameters/ParameterMessage.h>
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<StorageManagerIF>(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);
}

View File

@ -1,35 +1,58 @@
/*
* DataPoolAdmin.h
*
* Created on: 05.12.2013
* Author: baetz
*/
#ifndef DATAPOOLADMIN_H_
#define DATAPOOLADMIN_H_
#include <framework/ipc/MessageQueue.h>
#include <framework/memory/MemoryHelper.h>
#include <framework/action/HasActionsIF.h>
#include <framework/action/SimpleActionHelper.h>
#include <framework/objectmanager/SystemObject.h>
#include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/tasks/ExecutableObjectIF.h>
#include <framework/parameters/ReceivesParameterMessagesIF.h>
#include <framework/datapool/DataPoolParameterWrapper.h>
#include <framework/ipc/MessageQueueIF.h>
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_ */

View File

@ -0,0 +1,181 @@
#include "DataPoolParameterWrapper.h"
//for returncodes
#include <framework/parameters/HasParametersIF.h>
#include <framework/datapool/DataSet.h>
#include <framework/datapool/PoolRawAccess.h>
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<Type>::serialize(&type, buffer, size, max_size,
bigEndian);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter<uint8_t>::serialize(&columns, buffer, size,
max_size, bigEndian);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter<uint8_t>::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<typename T>
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<uint8_t>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::INT8_T:
result = deSerializeData<int8_t>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::UINT16_T:
result = deSerializeData<uint16_t>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::INT16_T:
result = deSerializeData<int16_t>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::UINT32_T:
result = deSerializeData<uint32_t>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::INT32_T:
result = deSerializeData<int32_t>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::FLOAT:
result = deSerializeData<float>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::DOUBLE:
result = deSerializeData<double>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
default:
result = ParameterWrapper::UNKNOW_DATATYPE;
break;
}
} else {
//not supported
return HasReturnvaluesIF::RETURN_FAILED;
}
return result;
}

View File

@ -0,0 +1,38 @@
#ifndef DATAPOOLPARAMETERWRAPPER_H_
#define DATAPOOLPARAMETERWRAPPER_H_
#include <framework/globalfunctions/Type.h>
#include <framework/parameters/ParameterWrapper.h>
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<typename T>
ReturnValue_t deSerializeData(uint8_t startingRow, uint8_t startingColumn,
const void *from, uint8_t fromRows);
};
#endif /* DATAPOOLPARAMETERWRAPPER_H_ */

View File

@ -1,10 +1,3 @@
/*
* DataSet.cpp
*
* Created on: 24.10.2012
* Author: baetz
*/
#include <framework/datapool/DataSet.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
@ -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;

View File

@ -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;

View File

@ -12,9 +12,6 @@
#ifndef DATASETIF_H_
#define DATASETIF_H_
#include <framework/osal/OSAL.h>
class PoolVariableIF;
/**

View File

@ -0,0 +1,75 @@
#include <framework/datapool/HkSwitchHelper.h>
#include <mission/tmtcservices/HKService_03.h>
#include <framework/ipc/QueueFactory.h>
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;
}

44
datapool/HkSwitchHelper.h Normal file
View File

@ -0,0 +1,44 @@
#ifndef FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_
#define FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_
#include <framework/tasks/ExecutableObjectIF.h>
#include <framework/action/CommandsActionsIF.h>
#include <framework/events/EventReportingProxyIF.h>
//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_ */

View File

@ -1,25 +0,0 @@
#!/bin/bash
#
# OPUS makefile
#
# Created on: Mar 04, 2010
# Author: ziemke
# Author: Claas Ziemke
# Copyright 2010, Claas Ziemke <claas.ziemke@gmx.net>
#
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

View File

@ -1,10 +1,3 @@
/*
* PIDReader.h
*
* Created on: 14.05.2014
* Author: baetz
*/
#ifndef PIDREADER_H_
#define PIDREADER_H_
#include <framework/datapool/DataPool.h>

View File

@ -1,10 +1,3 @@
/*
* PIDReaderList.h
*
* Created on: 15.07.2015
* Author: baetz
*/
#ifndef FRAMEWORK_DATAPOOL_PIDREADERLIST_H_
#define FRAMEWORK_DATAPOOL_PIDREADERLIST_H_

View File

@ -1,10 +1,3 @@
/*
* PoolEntry.cpp
*
* Created on: Oct 25, 2012
* Author: baetz
*/
#include <framework/datapool/PoolEntry.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>

View File

@ -3,7 +3,8 @@
#include <framework/datapool/PoolEntryIF.h>
#include <framework/osal/OSAL.h>
#include <stddef.h>
#include <cstring>
/**
* \brief This is a small helper class that defines a single data pool entry.
*

View File

@ -15,6 +15,7 @@
#include <stdint.h>
/**
* \brief This interface defines the access possibilities to a single data pool entry.
*

View File

@ -1,18 +1,13 @@
/*
* PoolRawAccess.cpp
*
* Created on: 29.10.2012
* Author: baetz
*/
#include <framework/datapool/DataPool.h>
#include <framework/datapool/PoolEntryIF.h>
#include <framework/datapool/PoolRawAccess.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <framework/osal/Endiness.h>
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;
}

View File

@ -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.
*/

View File

@ -1,10 +1,3 @@
/*
* PoolVarList.h
*
* Created on: 06.03.2014
* Author: baetz
*/
#ifndef POOLVARLIST_H_
#define POOLVARLIST_H_

View File

@ -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 <framework/ipc/MessageQueueSenderIF.h>
class AcceptsDeviceResponsesIF {
public:
/**
* Default empty virtual destructor.
*/
virtual ~AcceptsDeviceResponsesIF() {
}
virtual MessageQueueId_t getDeviceQueue() = 0;
};
#endif /* ACCEPTSDEVICERESPONSESIF_H_ */

View File

@ -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++;
}
}

View File

@ -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);

View File

@ -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(

View File

@ -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();

View File

@ -1,14 +1,7 @@
/*
* ChildHandlerFDIR.cpp
*
* Created on: 08.02.2016
* Author: baetz
*/
#include <framework/devicehandlers/ChildHandlerFDIR.h>
ChildHandlerFDIR::ChildHandlerFDIR(object_id_t owner, object_id_t faultTreeParent, uint32_t recoveryCount) :
DeviceHandlerFDIR(owner, faultTreeParent) {
DeviceHandlerFailureIsolation(owner, faultTreeParent) {
recoveryCounter.setFailureThreshold(recoveryCount);
}

View File

@ -1,25 +1,18 @@
/*
* ChildHandlerFDIR.h
*
* Created on: 08.02.2016
* Author: baetz
*/
#ifndef FRAMEWORK_DEVICEHANDLERS_CHILDHANDLERFDIR_H_
#define FRAMEWORK_DEVICEHANDLERS_CHILDHANDLERFDIR_H_
#include <framework/devicehandlers/DeviceHandlerFDIR.h>
#include <framework/devicehandlers/DeviceHandlerFailureIsolation.h>
/**
* 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;
};

View File

@ -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;

View File

@ -1,52 +1,58 @@
/*
* DeviceHandlerBase.cpp
*
* Created on: 30.10.2012
* Author: mohr
*/
#include <config/datapool/dataPoolInit.h>
#include <mission/devices/PCDUHandler.h>
#include <config/hardware/IoBoardAddresses.h>
#include <framework/datapool/DataSet.h>
#include <framework/datapool/PoolVariable.h>
#include <framework/datapool/PoolVector.h>
#include <framework/devicehandlers/AcceptsDeviceResponsesIF.h>
#include <framework/devicehandlers/DeviceHandlerBase.h>
#include <framework/devicehandlers/DeviceTmReportingWrapper.h>
#include <framework/globalfunctions/crc_ccitt.h>
#include <framework/objectmanager/ObjectManager.h>
#include <framework/rmap/RMAP.h>
#include <framework/rmap/RMAPChannelIF.h>
#include <framework/storagemanager/StorageManagerIF.h>
#include <framework/subsystem/SubsystemBase.h>
#include <mission/tmtcservices/AcceptsDeviceResponsesIF.h>
#include <mission/controllers/tcs/ThermalComponentIF.h>
#include <framework/thermal/ThermalComponentIF.h>
#include <framework/ipc/QueueFactory.h>
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(&currentUptime);
Clock::getUptime(&currentUptime);
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(&currentUptime);
Clock::getUptime(&currentUptime);
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(&currentUptime);
Clock::getUptime(&currentUptime);
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<PowerSwitchIF>(objects::PCDU_HANDLER);
powerSwitcher = objectManager->get<PowerSwitchIF>(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()) {
MessageQueueId_t queueId = iter->second.command->second.sendReplyTo;
DeviceTmReportingWrapper wrapper(getObjectId(), replyId, data);
if (iter->second.command != deviceCommandMap.end()) {//replies to a command
MessageQueueId_t queueId = iter->second.command->second.sendReplyTo;
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) {
}

View File

@ -6,9 +6,7 @@
#include <framework/datapool/DataSet.h>
#include <framework/datapool/PoolVariableIF.h>
#include <framework/devicehandlers/DeviceCommunicationIF.h>
#include <framework/devicehandlers/DeviceHandlerFDIR.h>
#include <framework/devicehandlers/DeviceHandlerIF.h>
#include <framework/devicehandlers/PollingSequenceExecutableIF.h>
#include <framework/health/HealthHelper.h>
#include <framework/modes/HasModesIF.h>
#include <framework/objectmanager/SystemObject.h>
@ -16,7 +14,17 @@
#include <framework/parameters/ParameterHelper.h>
#include <framework/power/PowerSwitchIF.h>
#include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/tasks/ExecutableObjectIF.h>
#include <framework/devicehandlers/DeviceHandlerFailureIsolation.h>
#include <framework/datapool/HkSwitchHelper.h>
#include <framework/serialize/SerialFixedArrayListAdapter.h>
#include <map>
#include <framework/ipc/MessageQueueIF.h>
#include <framework/tasks/PeriodicTaskIF.h>
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
*/
@ -83,11 +92,13 @@ public:
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
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);
/**

View File

@ -1,20 +1,14 @@
/*
* DeviceHandlerFDIR.cpp
*
* Created on: 09.09.2015
* Author: baetz
*/
#include <framework/devicehandlers/DeviceHandlerBase.h>
#include <framework/devicehandlers/DeviceHandlerFDIR.h>
#include <framework/devicehandlers/DeviceHandlerFailureIsolation.h>
#include <framework/health/HealthTableIF.h>
#include <framework/power/Fuse.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <mission/controllers/power/Fuse.h>
#include <mission/controllers/tcs/ThermalComponentIF.h>
#include <framework/thermal/ThermalComponentIF.h>
//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<ConfirmsFailuresIF>(
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;
}

View File

@ -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 <framework/fdir/FaultCounter.h>
#include <framework/fdir/FDIRBase.h>
#include <framework/fdir/FailureIsolationBase.h>
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_ */

View File

@ -4,8 +4,8 @@
#include <framework/action/HasActionsIF.h>
#include <framework/devicehandlers/DeviceHandlerMessage.h>
#include <framework/events/Event.h>
#include <framework/ipc/MessageQueue.h>
#include <framework/modes/HasModesIF.h>
#include <framework/ipc/MessageQueueSenderIF.h>
/**
* 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
*/

View File

@ -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);

View File

@ -5,7 +5,7 @@
#include <framework/ipc/CommandMessage.h>
#include <framework/objectmanager/SystemObjectIF.h>
#include <framework/storagemanager/StorageManagerIF.h>
//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

View File

@ -0,0 +1,21 @@
/**
* @file PollingSlot.cpp
* @brief This file defines the PollingSlot class.
* @date 19.12.2012
* @author baetz
*/
#include <framework/devicehandlers/FixedSequenceSlot.h>
#include <framework/objectmanager/SystemObjectIF.h>
#include <cstddef>
FixedSequenceSlot::FixedSequenceSlot(object_id_t handlerId, uint32_t setTime,
int8_t setSequenceId, PeriodicTaskIF* executingTask) :
handler(NULL), pollingTimeMs(setTime), opcode(setSequenceId) {
handler = objectManager->get<ExecutableObjectIF>(handlerId);
handler->setTaskIF(executingTask);
}
FixedSequenceSlot::~FixedSequenceSlot() {
}

View File

@ -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 <framework/devicehandlers/PollingSequenceExecutableIF.h>
#include <framework/objectmanager/ObjectManagerIF.h>
#include <framework/osal/OSAL.h>
class PollingSequence;
#include <framework/tasks/ExecutableObjectIF.h>
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_ */

View File

@ -0,0 +1,109 @@
#include <framework/devicehandlers/FixedSlotSequence.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) :
lengthMs(setLengthMs) {
current = slotList.begin();
}
FixedSlotSequence::~FixedSlotSequence() {
std::list<FixedSequenceSlot*>::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<FixedSequenceSlot*>::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<FixedSequenceSlot*>::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();
}

View File

@ -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 <framework/devicehandlers/PollingSequenceExecutableIF.h>
#include <framework/devicehandlers/PollingSlot.h>
#include <framework/devicehandlers/FixedSequenceSlot.h>
#include <framework/objectmanager/SystemObject.h>
#include <framework/osal/OSAL.h>
#include<list>
#include <list>
/**
* \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<FixedSequenceSlot*>::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<PollingSlot*> slotList;
std::list<FixedSequenceSlot*> 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<PollingSlot*>::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_ */

View File

@ -1,18 +1,20 @@
#include <framework/devicehandlers/HealthDevice.h>
#include <framework/ipc/QueueFactory.h>
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) {

View File

@ -5,6 +5,7 @@
#include <framework/health/HealthHelper.h>
#include <framework/objectmanager/SystemObject.h>
#include <framework/tasks/ExecutableObjectIF.h>
#include <framework/ipc/MessageQueueIF.h>
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;
};

View File

@ -1,28 +0,0 @@
#!/bin/bash
#
# OPUS makefile
#
# Created on: Mar 04, 2010
# Author: ziemke
# Author: Claas Ziemke
# Copyright 2010, Claas Ziemke <claas.ziemke@gmx.net>
#
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

View File

@ -1,115 +0,0 @@
/**
* @file PollingSequence.cpp
* @brief This file defines the PollingSequence class.
* @date 19.12.2012
* @author baetz
*/
#include <framework/devicehandlers/PollingSequence.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
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<PollingSlot*>::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<PollingSlot*>::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<PollingSlot*>::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);
}

View File

@ -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 <framework/osal/OSAL.h>
class PollingSequenceExecutableIF {
public:
static uint32_t pollingSequenceLengthMs;
static uint32_t payloadSequenceLengthMs;
virtual void performInPST( uint8_t ) = 0;
virtual ~PollingSequenceExecutableIF() { }
};
#endif /* POLLINGSEQUENCEEXECUTABLE_H_ */

View File

@ -1,29 +0,0 @@
/**
* @file PollingSlot.cpp
* @brief This file defines the PollingSlot class.
* @date 19.12.2012
* @author baetz
*/
#include <framework/devicehandlers/PollingSlot.h>
#include <framework/objectmanager/SystemObjectIF.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
PollingSlot::PollingSlot( object_id_t handlerId, Interval_t setTime, int8_t setSequenceId ) {
//Set all attributes directly on object creation.
this->handler = objectManager->get<PollingSequenceExecutableIF>( handlerId );
this->pollingTime = setTime;
this->opcode = setSequenceId;
}
PollingSlot::~PollingSlot() {
}
void PollingSlot::print() const {
SystemObjectIF * systemObject = dynamic_cast<SystemObjectIF *>(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;
}

View File

@ -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 <framework/devicehandlers/PollingTask.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
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<PollingSequence>( 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<PollingTask*>( 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<PollingSlot*>::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) );
}

View File

@ -1,13 +1,3 @@
/*
* Event.cpp
*
* Created on: 25.08.2015
* Author: baetz
*/
#include <framework/events/Event.h>
namespace EVENT {
EventId_t getEventId(Event event) {

View File

@ -1,14 +1,9 @@
/*
* Event.h
*
* Created on: 18.08.2015
* Author: baetz
*/
#ifndef EVENTOBJECT_EVENT_H_
#define EVENTOBJECT_EVENT_H_
#include <stdint.h>
#include <framework/events/fwSubsystemIdRanges.h>
//could be move to more suitable location
#include <config/tmtc/subsystemIdRanges.h>
typedef uint16_t EventId_t;

View File

@ -1,40 +1,43 @@
#include <config/objects/translateObjects.h>
#include <config/events/translateEvents.h>
#include <framework/events/EventManager.h>
#include <framework/events/EventMessage.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <framework/ipc/QueueFactory.h>
#include <framework/ipc/MutexFactory.h>
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();
}

View File

@ -4,16 +4,17 @@
#include <framework/events/eventmatching/EventMatchTree.h>
#include <framework/events/EventManagerIF.h>
#include <framework/objectmanager/SystemObject.h>
#include <framework/osal/OSAL.h>
#include <framework/storagemanager/LocalPool.h>
#include <framework/tasks/ExecutableObjectIF.h>
#include <framework/ipc/MessageQueueIF.h>
#include <framework/ipc/MutexIF.h>
#include <map>
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<MessageQueueId_t, EventMatchTree> listenerList;
MutexId_t* mutex;
MutexIF* mutex;
static const uint8_t N_POOLS = 3;
LocalPool<N_POOLS> factoryBackend;
@ -51,7 +50,9 @@ protected:
void notifyListeners(EventMessage *message);
#ifdef DEBUG
void printEvent(EventMessage *message);
#endif
void lockMutex();

View File

@ -3,13 +3,13 @@
#include <framework/events/eventmatching/eventmatching.h>
#include <framework/events/EventMessage.h>
#include <framework/ipc/MessageQueue.h>
#include <framework/objectmanager/ObjectManagerIF.h>
#include <framework/ipc/MessageQueueSenderIF.h>
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);
}
};

View File

@ -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);

Some files were not shown because too many files have changed in this diff Show More