diff --git a/action/HasActionsIF.h b/action/HasActionsIF.h index f30fcb45e..4d66ad1f6 100644 --- a/action/HasActionsIF.h +++ b/action/HasActionsIF.h @@ -7,8 +7,10 @@ #include #include /** - * \brief Interface for component which uses actions + * @brief + * Interface for component which uses actions * + * @details * This interface is used to execute actions in the component. Actions, in the sense of this interface, are activities with a well-defined beginning and * end in time. They may adjust sub-states of components, but are not supposed to change * the main mode of operation, which is handled with the HasModesIF described below. @@ -23,6 +25,8 @@ * parameters and immediately start execution of the action. It is, however, not required to * immediately finish execution. Instead, this may be deferred to a later point in time, at * which the component needs to inform the caller about finished or failed execution. + * + * \ingroup interfaces */ class HasActionsIF { public: diff --git a/container/FIFO.h b/container/FIFO.h index 670a50d74..134da9b80 100644 --- a/container/FIFO.h +++ b/container/FIFO.h @@ -21,7 +21,7 @@ public: readIndex(0), writeIndex(0), currentSize(0) { } - bool emtpy() { + bool empty() { return (currentSize == 0); } @@ -45,7 +45,7 @@ public: } ReturnValue_t retrieve(T *value) { - if (emtpy()) { + if (empty()) { return EMPTY; } else { *value = data[readIndex]; diff --git a/container/SimpleRingBuffer.h b/container/SimpleRingBuffer.h index 6d7d67e1d..45cb09277 100644 --- a/container/SimpleRingBuffer.h +++ b/container/SimpleRingBuffer.h @@ -4,12 +4,40 @@ #include #include +/** + * Circular buffer implementation, useful for buffering into data streams. + * Note that the deleteData() has to be called to increment the read pointer + */ class SimpleRingBuffer: public RingBufferBase<> { public: SimpleRingBuffer(uint32_t size, bool overwriteOld); virtual ~SimpleRingBuffer(); + + /** + * Write to circular buffer and increment write pointer by amount + * @param data + * @param amount + * @return + */ ReturnValue_t writeData(const uint8_t* data, uint32_t amount); + + /** + * Read from circular buffer at read pointer + * @param data + * @param amount + * @param readRemaining + * @param trueAmount + * @return + */ ReturnValue_t readData(uint8_t* data, uint32_t amount, bool readRemaining = false, uint32_t* trueAmount = NULL); + + /** + * Delete data starting by incrementing read pointer + * @param amount + * @param deleteRemaining + * @param trueAmount + * @return + */ ReturnValue_t deleteData(uint32_t amount, bool deleteRemaining = false, uint32_t* trueAmount = NULL); private: // static const uint8_t TEMP_READ_PTR = 1; diff --git a/devicehandlers/Cookie.h b/devicehandlers/Cookie.h index 495c8c403..618c901ff 100644 --- a/devicehandlers/Cookie.h +++ b/devicehandlers/Cookie.h @@ -1,6 +1,9 @@ #ifndef COOKIE_H_ #define COOKIE_H_ +/** + * This datatype is used to identify different connection over a single interface (like RMAP or I2C) + */ class Cookie{ public: virtual ~Cookie(){} diff --git a/devicehandlers/DeviceCommunicationIF.h b/devicehandlers/DeviceCommunicationIF.h index e0aca5731..59420861e 100644 --- a/devicehandlers/DeviceCommunicationIF.h +++ b/devicehandlers/DeviceCommunicationIF.h @@ -4,6 +4,22 @@ #include #include +/** + * Documentation: Dissertation Baetz p.138 + * + * This is an interface to decouple device communication from + * the device handler to allow reuse of these components. + * It works with the assumption that received data + * is polled by a component. There are four generic steps of device communication: + * + * 1. Send data to a device + * 2. Get acknowledgement for sending + * 3. Request reading data from a device + * 4. Read received data + * + * To identify different connection over a single interface can return so-called cookies to components. + * + */ class DeviceCommunicationIF: public HasReturnvaluesIF { public: static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_COMMUNICATION_IF; @@ -39,14 +55,31 @@ public: virtual void close(Cookie *cookie) = 0; - //SHOULDDO can data be const? - virtual ReturnValue_t sendMessage(Cookie *cookie, uint8_t *data, + /** + * Called by DHB in the SEND_WRITE doSendWrite(). + * This function is used to send data to the physical device + * by implementing and calling related drivers or wrapper functions. + * @param cookie + * @param data + * @param len + * @return + */ + virtual ReturnValue_t sendMessage(Cookie *cookie,const uint8_t *data, uint32_t len) = 0; virtual ReturnValue_t getSendSuccess(Cookie *cookie) = 0; virtual ReturnValue_t requestReceiveMessage(Cookie *cookie) = 0; + /** + * Called by DHB in the GET_WIRTE doGetRead(). + * This function is used to receive data from the physical device + * by implementing and calling related drivers or wrapper functions. + * @param cookie + * @param data + * @param len + * @return + */ virtual ReturnValue_t readReceivedMessage(Cookie *cookie, uint8_t **buffer, uint32_t *size) = 0; diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index ae9199f2c..09c27c87d 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -16,25 +16,24 @@ object_id_t DeviceHandlerBase::powerSwitcherId = 0; object_id_t DeviceHandlerBase::rawDataReceiverId = 0; object_id_t DeviceHandlerBase::defaultFDIRParentId = 0; -DeviceHandlerBase::DeviceHandlerBase(uint32_t ioBoardAddress, +DeviceHandlerBase::DeviceHandlerBase(uint32_t logicalAddress_, object_id_t setObjectId, uint32_t maxDeviceReplyLen, uint8_t setDeviceSwitch, object_id_t deviceCommunication, uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId, FailureIsolationBase* fdirInstance, uint32_t cmdQueueSize) : - SystemObject(setObjectId), rawPacket(0), rawPacketLen(0), mode( - MODE_OFF), submode(SUBMODE_NONE), pstStep(0), maxDeviceReplyLen( - 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), hkSwitcher(this), defaultFDIRUsed( - fdirInstance == NULL), switchOffWasReported(false),executingTask(NULL), actionHelper(this, NULL), cookieInfo(), ioBoardAddress( - ioBoardAddress), timeoutStart(0), childTransitionDelay(5000), transitionSourceMode( - _MODE_POWER_DOWN), transitionSourceSubMode(SUBMODE_NONE), deviceSwitch( - setDeviceSwitch) { + SystemObject(setObjectId), rawPacket(0), rawPacketLen(0), mode(MODE_OFF), + submode(SUBMODE_NONE), pstStep(0), maxDeviceReplyLen(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), hkSwitcher(this), + defaultFDIRUsed(fdirInstance == NULL), switchOffWasReported(false), + executingTask(NULL), actionHelper(this, NULL), cookieInfo(), logicalAddress(logicalAddress_), + 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; @@ -55,7 +54,6 @@ DeviceHandlerBase::~DeviceHandlerBase() { ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { this->pstStep = counter; - if (counter == 0) { cookieInfo.state = COOKIE_UNUSED; readCommandQueue(); @@ -455,7 +453,7 @@ void DeviceHandlerBase::doGetWrite() { if (wiretappingMode == RAW) { 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. + // 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); } else { //always generate a failure event, so that FDIR knows what's up @@ -476,9 +474,9 @@ void DeviceHandlerBase::doSendRead() { cookieInfo.state = COOKIE_READ_SENT; } else { triggerEvent(DEVICE_REQUESTING_REPLY_FAILED, result); - //We can't inform anyone, because we don't know which command was sent last. - //So, we need to wait for a timeout. - //but I think we can allow to ignore one missedReply. + // We can't inform anyone, because we don't know which command was sent last. + // So, we need to wait for a timeout. + // but I think we can allow to ignore one missedReply. ignoreMissedRepliesCount++; cookieInfo.state = COOKIE_UNUSED; } @@ -591,7 +589,7 @@ ReturnValue_t DeviceHandlerBase::initialize() { return RETURN_FAILED; } - result = communicationInterface->open(&cookie, ioBoardAddress, + result = communicationInterface->open(&cookie, logicalAddress, maxDeviceReplyLen); if (result != RETURN_OK) { return result; @@ -672,7 +670,6 @@ void DeviceHandlerBase::replyRawData(const uint8_t *data, size_t len, } CommandMessage message; - DeviceHandlerMessage::setDeviceHandlerRawReplyMessage(&message, getObjectId(), address, isCommand); @@ -753,7 +750,7 @@ ReturnValue_t DeviceHandlerBase::switchCookieChannel(object_id_t newChannelId) { DeviceCommunicationIF>(newChannelId); if (newCommunication != NULL) { - ReturnValue_t result = newCommunication->reOpen(cookie, ioBoardAddress, + ReturnValue_t result = newCommunication->reOpen(cookie, logicalAddress, maxDeviceReplyLen); if (result != RETURN_OK) { return result; @@ -837,8 +834,9 @@ ReturnValue_t DeviceHandlerBase::getStateOfSwitches(void) { ReturnValue_t result = getSwitches(&switches, &numberOfSwitches); if ((result == RETURN_OK) && (numberOfSwitches != 0)) { while (numberOfSwitches > 0) { - if (powerSwitcher->getSwitchState(switches[numberOfSwitches - 1]) - == PowerSwitchIF::SWITCH_OFF) { + if (powerSwitcher-> getSwitchState(switches[numberOfSwitches - 1]) + == PowerSwitchIF::SWITCH_OFF) + { return PowerSwitchIF::SWITCH_OFF; } numberOfSwitches--; @@ -1020,6 +1018,7 @@ void DeviceHandlerBase::replyRawReplyIfnotWiretapped(const uint8_t* data, } } + ReturnValue_t DeviceHandlerBase::handleDeviceHandlerMessage( CommandMessage * message) { ReturnValue_t result; @@ -1112,8 +1111,7 @@ void DeviceHandlerBase::handleDeviceTM(SerializeIF* data, // 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); + actionHelper.reportData(defaultRawReceiver, replyId, &wrapper, true); } } else { //unrequested/aperiodic replies @@ -1270,3 +1268,10 @@ void DeviceHandlerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) { void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task_){ executingTask = task_; } + +void DeviceHandlerBase::debugInterface(uint8_t positionTracker) { +} + +uint32_t DeviceHandlerBase::getLogicalAddress() { + return logicalAddress; +} diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 756ad530d..4c83b230d 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -33,23 +33,29 @@ class StorageManagerIF; * Contains all devices and the DeviceHandlerBase class. */ + /** * \brief This is the abstract base class for device handlers. * * Documentation: Dissertation Baetz p.138,139, p.141-149 - * SpaceWire Remote Memory Access Protocol (RMAP) * - * It features handling of @link DeviceHandlerIF::Mode_t Modes @endlink, the RMAP communication and the - * communication with commanding objects. + * It features handling of @link DeviceHandlerIF::Mode_t Modes @endlink, communication with + * physical devices, using the @link DeviceCommunicationIF, and communication with commanding objects. + * + * NOTE: RMAP is a legacy standard which is used for FLP. + * RMAP communication is not mandatory for projects implementing the FSFW. + * However, the communication principles are similar to RMAP as there are two write and two send calls involved. + * * It inherits SystemObject and thus can be created by the ObjectManagerIF. * * 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. + * For each step an RMAP action is selected and executed. If data has been received (GET_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 + * (sendRead-getRead-sendWrite-getWrite) structure, a default implementation is provided. * * Device handler instances should extend this class and implement the abstract functions. * Components and drivers can send so called cookies which are used for communication + * and contain information about the communcation (e.g. slave address for I2C or RMAP structs). * * \ingroup devices */ @@ -70,7 +76,7 @@ public: * @param maxDeviceReplyLen the length the RMAP getRead call will be sent with * @param setDeviceSwitch the switch the device is connected to, for devices using two switches, overwrite getSwitches() */ - DeviceHandlerBase(uint32_t ioBoardAddress, object_id_t setObjectId, + DeviceHandlerBase(uint32_t logicalAddress, object_id_t setObjectId, uint32_t maxDeviceReplyLen, uint8_t setDeviceSwitch, object_id_t deviceCommunication, uint32_t thermalStatePoolId = PoolVariableIF::NO_PARAMETER, @@ -81,7 +87,7 @@ public: /** - * This function is a core component and is called periodically. + * This function is the device handler base core component and is called periodically. * General sequence: * If the State is SEND_WRITE: * 1. Set the cookie state to COOKIE_UNUSED and read the command queue @@ -95,13 +101,16 @@ public: * 7. If the device mode is MODE_OFF, return RETURN_OK. Otherwise, perform the Action property * and performs depending on value specified * by input value counter. The child class tells base class what to do by setting this value. - * - SEND_WRITE: Send data or commands to device by calling doSendWrite() - * Calls abstract funtions buildNomalDeviceCommand() - * or buildTransitionDeviceCommand() - * - GET_WRITE: Get ackknowledgement for sending by calling doGetWrite(). + * - SEND_WRITE: Send data or commands to device by calling doSendWrite() which calls + * sendMessage function of #communicationInterface + * and calls buildInternalCommand if the cookie state is COOKIE_UNUSED + * - GET_WRITE: Get ackknowledgement for sending by calling doGetWrite() which calls + * getSendSuccess of #communicationInterface. * Calls abstract functions scanForReply() and interpretDeviceReply(). - * - SEND_READ: Request reading data from device by calling doSendRead() - * - GET_READ: Access requested reading data by calling doGetRead() + * - SEND_READ: Request reading data from device by calling doSendRead() which calls + * requestReceiveMessage of #communcationInterface + * - GET_READ: Access requested reading data by calling doGetRead() which calls + * readReceivedMessage of #communicationInterface * @param counter Specifies which Action to perform * @return RETURN_OK for successful execution */ @@ -143,7 +152,7 @@ protected: 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); + static const ReturnValue_t APERIODIC_REPLY = MAKE_RETURN_CODE(5); //!< This is used to specify for replies from a device which are not replies to requests static const ReturnValue_t IGNORE_REPLY_DATA = MAKE_RETURN_CODE(6); // static const ReturnValue_t ONE_SWITCH = MAKE_RETURN_CODE(8); // static const ReturnValue_t TWO_SWITCHES = MAKE_RETURN_CODE(9); @@ -159,6 +168,8 @@ protected: static const DeviceCommandId_t NO_COMMAND_ID = -2; static const MessageQueueId_t NO_COMMANDER = 0; + + /** * Pointer to the raw packet that will be sent. */ @@ -537,6 +548,18 @@ protected: */ virtual void fillCommandAndReplyMap() = 0; + + /** + * @brief Can be implemented by child handler to + * perform debugging + * @details Example: Calling this in performOperation + * to track values like mode. An optional position tracker can be supplied + * to provide the child handler a way to know where the debugInterface was called + * + * Please delete all debugInterface calls in DHB after debugging is finished ! + */ + virtual void debugInterface(uint8_t positionTracker = 0); + /** * This is a helper method to facilitate inserting entries in the command map. * @param deviceCommand Identifier of the command to add. @@ -600,9 +623,9 @@ protected: * @param[out] foundLen length of the packet found * @return * - @c RETURN_OK a valid packet was found at @c start, @c foundLen is valid - * - @c NO_VALID_REPLY no reply could be found starting at @c start, implies @c foundLen is not valid, base class will call scanForReply() again with ++start - * - @c INVALID_REPLY a packet was found but it is invalid, eg checksum error, implies @c foundLen is valid, can be used to skip some bytes - * - @c TOO_SHORT @c len is too short for any valid packet + * - @c RETURN_FAILED no reply could be found starting at @c start, implies @c foundLen is not valid, base class will call scanForReply() again with ++start + * - @c DeviceHandlerIF::INVALID_DATA a packet was found but it is invalid, eg checksum error, implies @c foundLen is valid, can be used to skip some bytes + * - @c DeviceHandlerIF::LENGTH_MISSMATCH @c len is invalid * - @c APERIODIC_REPLY if a valid reply is received that has not been requested by a command, but should be handled anyway (@see also fillCommandAndCookieMap() ) */ virtual ReturnValue_t scanForReply(const uint8_t *start, uint32_t len, @@ -618,7 +641,6 @@ protected: * * @param id the id found by scanForReply() * @param packet - * @param commander the one who initiated the command, is 0 if not external commanded * @return * - @c RETURN_OK when the reply was interpreted. * - @c RETURN_FAILED when the reply could not be interpreted, eg. logical errors or range violations occurred @@ -671,7 +693,8 @@ protected: struct DeviceCommandInfo { bool isExecuting; //!< Indicates if the command is already executing. - uint8_t expectedReplies; //!< Dynamic value to indicate how many replies are expected. + uint8_t expectedReplies; //!< Dynamic value to indicate how many replies are expected. Inititated with 0. + uint8_t expectedRepliesWhenEnablingReplyMap; //!< Constant value which specifies expected replies when enabling reply map. Inititated in insertInCommandAndReplyMap() MessageQueueId_t sendReplyTo; //!< if this is != NO_COMMANDER, DHB was commanded externally and shall report everything to commander. }; @@ -735,6 +758,11 @@ protected: */ virtual bool dontCheckQueue(); + /** + * Used to retrieve logical address + * @return + */ + virtual uint32_t getLogicalAddress(); Mode_t getBaseMode(Mode_t transitionMode); bool isAwaitingReply(); @@ -747,7 +775,6 @@ protected: virtual void startTransition(Mode_t mode, Submode_t submode); virtual void setToExternalControl(); virtual void announceMode(bool recursive); - virtual ReturnValue_t letChildHandleMessage(CommandMessage *message); /** @@ -829,8 +856,13 @@ protected: DeviceCommandMap deviceCommandMap; ActionHelper actionHelper; + + + private: + + /** * State a cookie is in. * @@ -862,9 +894,9 @@ private: CookieInfo cookieInfo; /** - * cached from ctor for initialize() - */ - const uint32_t ioBoardAddress; + * cached from ctor for initialize() + */ + const uint32_t logicalAddress; /** * Used for timing out mode transitions. @@ -929,6 +961,7 @@ private: * * This is called at the beginning of each cycle. It checks whether a reply has timed out (that means a reply was expected * but not received). + * In case the reply is periodic, the counter is simply set back to a specified value. */ void decrementDeviceReplyMap(void); @@ -1028,6 +1061,8 @@ private: ReturnValue_t switchCookieChannel(object_id_t newChannelId); ReturnValue_t handleDeviceHandlerMessage(CommandMessage *message); + + }; #endif /* DEVICEHANDLERBASE_H_ */ diff --git a/devicehandlers/DeviceHandlerIF.h b/devicehandlers/DeviceHandlerIF.h index fe0ee8e8b..bfa7c7b24 100644 --- a/devicehandlers/DeviceHandlerIF.h +++ b/devicehandlers/DeviceHandlerIF.h @@ -22,7 +22,10 @@ public: * * @details The mode of the device handler must not be confused with the mode the device is in. * The mode of the device itself is transparent to the user but related to the mode of the handler. + * MODE_ON and MODE_OFF are included in hasModesIF.h */ + + // MODE_ON = 0, //!< The device is powered and ready to perform operations. In this mode, no commands are sent by the device handler itself, but direct commands van be commanded and will be interpreted // MODE_OFF = 1, //!< The device is powered off. The only command accepted in this mode is a mode change to on. static const Mode_t MODE_NORMAL = 2; //!< The device is powered on and the device handler periodically sends commands. The commands to be sent are selected by the handler according to the submode. @@ -30,7 +33,7 @@ public: static const Mode_t MODE_ERROR_ON = 4; //!4< The device is shut down but the switch could not be turned off, so the device still is powered. In this mode, only a mode change to @c MODE_OFF can be commanded, which tries to switch off the device again. static const Mode_t _MODE_START_UP = TRANSITION_MODE_CHILD_ACTION_MASK | 5; //!< This is a transitional state which can not be commanded. The device handler performs all commands to get the device in a state ready to perform commands. When this is completed, the mode changes to @c MODE_ON. static const Mode_t _MODE_SHUT_DOWN = TRANSITION_MODE_CHILD_ACTION_MASK | 6; //!< This is a transitional state which can not be commanded. The device handler performs all actions and commands to get the device shut down. When the device is off, the mode changes to @c MODE_OFF. - static const Mode_t _MODE_TO_ON = TRANSITION_MODE_CHILD_ACTION_MASK | HasModesIF::MODE_ON; + static const Mode_t _MODE_TO_ON = TRANSITION_MODE_CHILD_ACTION_MASK | HasModesIF::MODE_ON; //!< It is possible to set the mode to _MODE_TO_ON to use the to on transition if available. static const Mode_t _MODE_TO_RAW = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_RAW; static const Mode_t _MODE_TO_NORMAL = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_NORMAL; static const Mode_t _MODE_POWER_DOWN = TRANSITION_MODE_BASE_ACTION_MASK | 1; //!< This is a transitional state which can not be commanded. The device is shut down and ready to be switched off. After the command to set the switch off has been sent, the mode changes to @c MODE_WAIT_OFF diff --git a/events/EventManager.cpp b/events/EventManager.cpp index 01334bac9..46c537520 100644 --- a/events/EventManager.cpp +++ b/events/EventManager.cpp @@ -137,9 +137,10 @@ void EventManager::printEvent(EventMessage* message) { error << "0x" << std::hex << message->getReporter() << std::dec; } error << " reported " << translateEvents(message->getEvent()) << " (" - << std::dec << message->getEventId() << std::hex << ") P1: 0x" - << message->getParameter1() << " P2: 0x" - << message->getParameter2() << std::dec << std::endl; + << std::dec << message->getEventId() << ") " << std::endl; + + error << std::hex << "P1 Hex: 0x" << message->getParameter1() << ", P1 Dec: " << std::dec << message->getParameter1() << std::endl; + error << std::hex << "P2 Hex: 0x" << message->getParameter2() << ", P2 Dec: " << std::dec << message->getParameter2() << std::endl; break; } diff --git a/fdir/FailureIsolationBase.cpp b/fdir/FailureIsolationBase.cpp index 4b7caac53..c65640c27 100644 --- a/fdir/FailureIsolationBase.cpp +++ b/fdir/FailureIsolationBase.cpp @@ -5,9 +5,10 @@ #include #include -FailureIsolationBase::FailureIsolationBase(object_id_t owner, object_id_t parent, uint8_t messageDepth, uint8_t parameterDomainBase) : - eventQueue(NULL), ownerId( - owner), owner(NULL), faultTreeParent(parent), parameterDomainBase(parameterDomainBase) { +FailureIsolationBase::FailureIsolationBase(object_id_t owner, + object_id_t parent, uint8_t messageDepth, uint8_t parameterDomainBase) : + eventQueue(NULL), ownerId(owner), owner(NULL), + faultTreeParent(parent), parameterDomainBase(parameterDomainBase) { eventQueue = QueueFactory::instance()->createMessageQueue(messageDepth, EventMessage::EVENT_MESSAGE_SIZE); } diff --git a/fdir/FailureIsolationBase.h b/fdir/FailureIsolationBase.h index cd582e399..894f63562 100644 --- a/fdir/FailureIsolationBase.h +++ b/fdir/FailureIsolationBase.h @@ -21,6 +21,10 @@ public: uint8_t messageDepth = 10, uint8_t parameterDomainBase = 0xF0); virtual ~FailureIsolationBase(); virtual ReturnValue_t initialize(); + + /** + * This is called by the DHB in performOperation() + */ void checkForFailures(); MessageQueueId_t getEventReceptionQueue(); virtual void triggerEvent(Event event, uint32_t parameter1 = 0, diff --git a/health/HealthHelper.h b/health/HealthHelper.h index a1ca2c525..24fd0d14a 100644 --- a/health/HealthHelper.h +++ b/health/HealthHelper.h @@ -27,8 +27,8 @@ public: /** * ctor * + * @param owner * @param objectId the object Id to use when communication with the HealthTable - * @param useAsFrom id to use as from id when sending replies, can be set to 0 */ HealthHelper(HasHealthIF* owner, object_id_t objectId); diff --git a/modes/ModeHelper.cpp b/modes/ModeHelper.cpp index 7b98bdc64..d9266c354 100644 --- a/modes/ModeHelper.cpp +++ b/modes/ModeHelper.cpp @@ -1,6 +1,7 @@ #include #include #include +#include ModeHelper::ModeHelper(HasModesIF *owner) : theOneWhoCommandedAMode(0), commandedMode(HasModesIF::MODE_OFF), commandedSubmode( @@ -42,7 +43,6 @@ ReturnValue_t ModeHelper::handleModeCommand(CommandMessage* message) { } countdown.setTimeout(timeout); - owner->startTransition(mode, submode); } break; diff --git a/objectmanager/ObjectManagerIF.h b/objectmanager/ObjectManagerIF.h index aca24a24a..9f58f600c 100644 --- a/objectmanager/ObjectManagerIF.h +++ b/objectmanager/ObjectManagerIF.h @@ -78,6 +78,13 @@ public: virtual void printList() = 0; }; +/** + * Used to retrieve Target Interface Pointers of objects. + * The object has to implement the SystemObject or SystemObjectIF at the very least, + * otherwise NULL will be returned. + * @param id + * @return NULL or pointer to target interface specified by template object + */ template T* ObjectManagerIF::get( object_id_t id ) { SystemObjectIF* temp = this->getSystemObject(id); diff --git a/osal/FreeRTOS/FixedTimeslotTask.cpp b/osal/FreeRTOS/FixedTimeslotTask.cpp index 00fd73d35..5bf09f136 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.cpp +++ b/osal/FreeRTOS/FixedTimeslotTask.cpp @@ -19,8 +19,7 @@ FixedTimeslotTask::~FixedTimeslotTask() { void FixedTimeslotTask::taskEntryPoint(void* argument) { //The argument is re-interpreted as FixedTimeslotTask. The Task object is global, so it is found from any place. - FixedTimeslotTask *originalTask( - reinterpret_cast(argument)); + FixedTimeslotTask *originalTask(reinterpret_cast(argument)); // Task should not start until explicitly requested // in FreeRTOS, tasks start as soon as they are created if the scheduler is running // but not if the scheduler is not running. diff --git a/osal/FreeRTOS/TaskFactory.cpp b/osal/FreeRTOS/TaskFactory.cpp index 7b2f70a3a..753da60f7 100644 --- a/osal/FreeRTOS/TaskFactory.cpp +++ b/osal/FreeRTOS/TaskFactory.cpp @@ -15,6 +15,7 @@ TaskFactory* TaskFactory::instance() { } /*** * Keep in Mind that you need to call before this vTaskStartScheduler()! + * High taskPriority_ number means high priority. */ PeriodicTaskIF* TaskFactory::createPeriodicTask(TaskName name_, TaskPriority taskPriority_, TaskStackSize stackSize_, diff --git a/power/PowerSwitchIF.h b/power/PowerSwitchIF.h index 1c4c06f7f..f25589c4d 100644 --- a/power/PowerSwitchIF.h +++ b/power/PowerSwitchIF.h @@ -11,8 +11,13 @@ #include #include /** - * This interface defines a connection to a device that is capable of turning on and off - * switches of devices identified by a switch ID. + * + * @brief This interface defines a connection to a device that is capable of turning on and off + * switches of devices identified by a switch ID. + * @details The virtual functions of this interface do not allow to make any assignments + * because they can be called asynchronosuly (const ending). + * + * @ingroup interfaces */ class PowerSwitchIF : public HasReturnvaluesIF { public: diff --git a/serialize/SerialBufferAdapter.cpp b/serialize/SerialBufferAdapter.cpp index 3ed083bf5..c5fcfb57e 100644 --- a/serialize/SerialBufferAdapter.cpp +++ b/serialize/SerialBufferAdapter.cpp @@ -5,15 +5,15 @@ template SerialBufferAdapter::SerialBufferAdapter(const uint8_t* buffer, - T bufferLength, bool serializeLenght) : - serializeLength(serializeLenght), constBuffer(buffer), buffer(NULL), bufferLength( + T bufferLength, bool serializeLength) : + serializeLength(serializeLength), constBuffer(buffer), buffer(NULL), bufferLength( bufferLength) { } template SerialBufferAdapter::SerialBufferAdapter(uint8_t* buffer, T bufferLength, - bool serializeLenght) : - serializeLength(serializeLenght), constBuffer(NULL), buffer(buffer), bufferLength( + bool serializeLength) : + serializeLength(serializeLength), constBuffer(NULL), buffer(buffer), bufferLength( bufferLength) { } diff --git a/serialize/SerialBufferAdapter.h b/serialize/SerialBufferAdapter.h index 7cd75d556..7d192bb45 100644 --- a/serialize/SerialBufferAdapter.h +++ b/serialize/SerialBufferAdapter.h @@ -5,6 +5,14 @@ #include /** + * This adapter provides an interface for SerializeIF to serialize or deserialize + * buffers with no length header but a known size. + * + * Additionally, the buffer length can be serialized too and will be put in front of the serialized buffer. + * + * Can be used with SerialLinkedListAdapter by declaring a SerializeElement with + * SerialElement> serialBufferElement + * * \ingroup serialize */ template diff --git a/serialize/SerialFixedArrayListAdapter.h b/serialize/SerialFixedArrayListAdapter.h index 16919b623..821e87104 100644 --- a/serialize/SerialFixedArrayListAdapter.h +++ b/serialize/SerialFixedArrayListAdapter.h @@ -5,6 +5,17 @@ #include /** + * This adapter provides an interface for SerializeIF to serialize and deserialize + * buffers with a header containing the buffer length. + * + * Can be used by SerialLinkedListAdapter. + * + * Buffers with a size header inside that class can be declared with + * SerialFixedArrayListAdapter. + * typeOfMaxData specifies the data type of the buffer header containing the buffer size that follows + * and MAX_BUFFER_LENGTH specifies the maximum allowed value for the buffer size. + * The sequence of objects is defined in the constructor by using the setStart and setNext functions. + * * \ingroup serialize */ template diff --git a/serialize/SerialLinkedListAdapter.h b/serialize/SerialLinkedListAdapter.h index 29952c4a3..08d385eec 100644 --- a/serialize/SerialLinkedListAdapter.h +++ b/serialize/SerialLinkedListAdapter.h @@ -13,7 +13,29 @@ #include //This is where we need the SerializeAdapter! -/** + /** + * An alternative to the AutoSerializeAdapter functions to implement the conversion + * of object data to data streams or vice-versa, using linked lists. + * + * All object members with a datatype are declared as SerializeElement inside the class + * implementing this adapter. + * + * Buffers with a size header inside that class can be declared with + * SerialFixedArrayListAdapter. + * typeOfMaxData specifies the data type of the buffer header containing the buffer size that follows + * and MAX_BUFFER_LENGTH specifies the maximum allowed value for the buffer size. + * Please note that a direct link from a linked element to a SerialFixedArrayListAdapter element is not possible and a + * helper needs to be used by calling .setNext(&linkHelper) + * and initialising the link helper as linkHelper(&SerialFixedArrayListAdapterElement). + * + * For buffers with no size header, declare + * SerializeElement> and initialise the buffer adapter in the constructor. + * + * The sequence of objects is defined in the constructor by using the setStart and setNext functions. + * + * The serialization and deserialization process is done by instantiating the class and + * calling the serialize or deserialize function. + * * \ingroup serialize */ template diff --git a/serialize/SerializeAdapter.h b/serialize/SerializeAdapter.h index fd9e1b6af..a0aab9e98 100644 --- a/serialize/SerializeAdapter.h +++ b/serialize/SerializeAdapter.h @@ -7,7 +7,48 @@ #include #include -/** + /** + * This adapter provides an interface to use the SerializeIF functions + * with arbitrary template objects to facilitate and simplify the serialization of classes + * with different multiple different data types into buffers vice-versa. + * + * Examples: + * A report class is converted into a TM buffer. The report class implements a serialize functions and calls + * the AutoSerializeAdapter::serialize function repeatedly on all object data fields. + * The getSerializedSize function is implemented by calling the + * AutoSerializeAdapter::getSerializedSize function repeatedly on all data fields. + * + * The AutoSerializeAdapter functions can also be used as an alternative to memcpy + * to retrieve data out of a buffer directly into a class variable with data type T while being able to specify endianness. + * The boolean bigEndian specifies the endiness of the data to serialize or deSerialize. + * + * If the target architecture is little endian (ARM), any data types created might + * have the wrong endiness if they are to be used for the FSFW. + * there are three ways to retrieve data out of a buffer to be used in the FSFW to use regular aligned (big endian) data. + * This can also be applied to uint32_t and uint64_t: + * + * 1. Use the AutoSerializeAdapter::deSerialize function with bool bigEndian = true: + * The pointer *buffer will be incremented automatically by the typeSize of data, + * so this function can be called on &buffer without adjusting pointer position + * + * uint16_t data; + * int32_t dataLen = sizeof(data); + * ReturnValue_t result = AutoSerializeAdapter::deSerialize(&data,&buffer,&dataLen,true); + * + * 2. Perform a bitshift operation: + * + * uint16_t data; + * data = buffer[targetByte1] >> 8 | buffer[targetByte2]; + * + * 3. Memcpy can be used when data is little-endian. Otherwise, endian-swapper has to be used. + * + * uint16_t data; + * memcpy(&data,buffer + positionOfTargetByte1,sizeof(data)); + * data = EndianSwapper::swap(data); + * + * When serializing for downlink, the packets are generally serialized assuming big endian data format + * like seen in TmPacketStored.cpp for example. + * * \ingroup serialize */ template diff --git a/serialize/SerializeIF.h b/serialize/SerializeIF.h index 701fbf563..cada1e72a 100644 --- a/serialize/SerializeIF.h +++ b/serialize/SerializeIF.h @@ -9,7 +9,20 @@ */ /** - * Translation of objects into data streams. + * An interface for alle classes which require translation of objects data into data streams and vice-versa. + * + * If the target architecture is little endian (e.g. ARM), any data types created might + * have the wrong endiness if they are to be used for the FSFW. + * There are three ways to retrieve data out of a buffer to be used in the FSFW to use regular aligned (big endian) data. + * This can also be applied to uint32_t and uint64_t: + * + * 1. Use the @c AutoSerializeAdapter::deSerialize function with @c bigEndian = true + * 2. Perform a bitshift operation + * 3. @c memcpy can be used when data is in little-endian format. Otherwise, @c EndianSwapper has to be used in conjuction. + * + * When serializing for downlink, the packets are generally serialized assuming big endian data format + * like seen in TmPacketStored.cpp for example. + * * \ingroup serialize */ class SerializeIF { diff --git a/serviceinterface/ServiceInterfaceBuffer.cpp b/serviceinterface/ServiceInterfaceBuffer.cpp index 58065994a..d5ce60568 100644 --- a/serviceinterface/ServiceInterfaceBuffer.cpp +++ b/serviceinterface/ServiceInterfaceBuffer.cpp @@ -5,6 +5,8 @@ // to be implemented by bsp extern "C" void printChar(const char*); + + int ServiceInterfaceBuffer::overflow(int c) { // Handle output putChars(pbase(), pptr()); @@ -19,16 +21,18 @@ int ServiceInterfaceBuffer::overflow(int c) { return 0; } +// custom stdio.c library for at91sam9g20 chip which does not support unsigned long +// So I cast (unsigned int) on loggerTimes int ServiceInterfaceBuffer::sync(void) { if (this->isActive) { Clock::TimeOfDay_t loggerTime; Clock::getDateAndTime(&loggerTime); char preamble[96] = { 0 }; - sprintf(preamble, "%s: | %lu:%02lu:%02lu.%03lu | ", - this->log_message.c_str(), (unsigned long) loggerTime.hour, - (unsigned long) loggerTime.minute, - (unsigned long) loggerTime.second, - (unsigned long) loggerTime.usecond /1000); + sprintf(preamble, "%s: | %u:%02u:%02u.%03u | ", + this->log_message.c_str(), (unsigned int) loggerTime.hour, + (unsigned int) loggerTime.minute, + (unsigned int) loggerTime.second, + (unsigned int) loggerTime.usecond /1000); // Write log_message and time this->putChars(preamble, preamble + sizeof(preamble)); // Handle output diff --git a/tmtcservices/CommandingServiceBase.h b/tmtcservices/CommandingServiceBase.h index ee59ffe44..8ce25f007 100644 --- a/tmtcservices/CommandingServiceBase.h +++ b/tmtcservices/CommandingServiceBase.h @@ -64,7 +64,7 @@ public: virtual ~CommandingServiceBase(); /*** - * This is the periodic called function + * This is the periodically called function. * Handle request queue for external commands. * Handle command Queue for internal commands. * @param opCode is unused here at the moment @@ -180,20 +180,67 @@ protected: */ void sendTmPacket(uint8_t subservice, SerializeIF* content, SerializeIF* header = NULL); + + /** + * Check the target subservice + * @param subservice + * @return + */ virtual ReturnValue_t isValidSubservice(uint8_t subservice) = 0; + /** + * Once a TC Request is valid, the existence of the destination and its target interface is checked and retrieved. + * The target message queue ID can then be acquired by using the target interface. + * @param subservice + * @param tcData Application Data of TC Packet + * @param tcDataLen + * @param id MessageQueue ID is stored here + * @param objectId + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED + * - @c CSB or implementation specific return codes + */ + virtual ReturnValue_t getMessageQueueAndObject(uint8_t subservice, + const uint8_t *tcData, uint32_t tcDataLen, MessageQueueId_t *id, + object_id_t *objectId) = 0; + + /** + * After the Message Queue and Object ID are determined, + * the command is prepared by using an implementation specific CommandMessage type which is sent to + * the target device. It contains all necessary information for the device to + * execute telecommands. + * @param message + * @param subservice + * @param tcData + * @param tcDataLen + * @param state + * @param objectId + * @return + */ virtual ReturnValue_t prepareCommand(CommandMessage *message, uint8_t subservice, const uint8_t *tcData, uint32_t tcDataLen, uint32_t *state, object_id_t objectId) = 0; + /** + * This function is responsible for the communication between the Command Service Base + * and the respective PUS Commanding Service once the execution has started. + * The PUS Commanding Service receives replies from the target device and forwards them by calling this function. + * There are different translations of these replies to specify how the Command Service proceeds. + * @param reply Command Message which contains information about the command + * @param previousCommand + * @param state + * @param optionalNextCommand + * @param objectId + * @param isStep Flag value to mark steps of command execution + * @return - @c RETURN_OK, @c EXECUTION_COMPLETE or @c NO_STEP_MESSAGE to generate TC verification success + * - @c INVALID_REPLY can handle unrequested replies + * - Anything else triggers a TC verification failure + */ virtual ReturnValue_t handleReply(const CommandMessage *reply, Command_t previousCommand, uint32_t *state, CommandMessage *optionalNextCommand, object_id_t objectId, bool *isStep) = 0; - virtual ReturnValue_t getMessageQueueAndObject(uint8_t subservice, - const uint8_t *tcData, uint32_t tcDataLen, MessageQueueId_t *id, - object_id_t *objectId) = 0; virtual void handleUnrequestedReply(CommandMessage *reply); @@ -209,7 +256,8 @@ private: * It handles replies generated by the devices and relayed by the specific service implementation. * This means that it determines further course of action depending on the return values specified * in the service implementation. - * This includes the generation of TC verification messages: + * This includes the generation of TC verification messages. Note that + * the static framework object ID @c VerificationReporter::messageReceiver needs to be set. * - TM[1,5] Step Successs * - TM[1,6] Step Failure * - TM[1,7] Completion Success diff --git a/tmtcservices/PusServiceBase.h b/tmtcservices/PusServiceBase.h index 782d375ff..4fe13ca91 100644 --- a/tmtcservices/PusServiceBase.h +++ b/tmtcservices/PusServiceBase.h @@ -68,8 +68,8 @@ public: * It checks for new requests, and, if found, calls handleRequest, sends completion verification messages and deletes * the TC requests afterwards. * performService is always executed afterwards. - * @return - \c RETURN_OK if the periodic performService was successful. - * - \c RETURN_FAILED else. + * @return \c RETURN_OK if the periodic performService was successful. + * \c RETURN_FAILED else. */ ReturnValue_t performOperation(uint8_t opCode); virtual uint16_t getIdentifier();