From 64f84d9d9ffbf2d4b357ac72ad24956b8540db07 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 27 Oct 2019 03:21:38 +0100 Subject: [PATCH 1/4] doc for dhb, serializeIF and SerializeAdapter --- devicehandlers/DeviceCommunicationIF.h | 2 +- devicehandlers/DeviceHandlerBase.cpp | 11 ++++++---- devicehandlers/DeviceHandlerBase.h | 11 ++++++---- serialize/SerializeAdapter.h | 28 ++++++++++++++++++++++---- serialize/SerializeIF.h | 14 +++++++++---- tmtcservices/PusServiceBase.h | 4 ++-- 6 files changed, 51 insertions(+), 19 deletions(-) diff --git a/devicehandlers/DeviceCommunicationIF.h b/devicehandlers/DeviceCommunicationIF.h index e0aca573..88f0d124 100644 --- a/devicehandlers/DeviceCommunicationIF.h +++ b/devicehandlers/DeviceCommunicationIF.h @@ -40,7 +40,7 @@ public: virtual void close(Cookie *cookie) = 0; //SHOULDDO can data be const? - virtual ReturnValue_t sendMessage(Cookie *cookie, uint8_t *data, + virtual ReturnValue_t sendMessage(Cookie *cookie,const uint8_t *data, uint32_t len) = 0; virtual ReturnValue_t getSendSuccess(Cookie *cookie) = 0; diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index 4eb9f504..2f16f846 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -11,6 +11,7 @@ #include #include #include +#include object_id_t DeviceHandlerBase::powerSwitcherId = 0; object_id_t DeviceHandlerBase::rawDataReceiverId = 0; @@ -452,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 @@ -473,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; } @@ -1266,3 +1267,5 @@ void DeviceHandlerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) { void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task_){ executingTask = task_; } + + diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 2278e1f5..6abfb675 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -167,7 +167,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); @@ -626,9 +626,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, @@ -954,6 +954,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); @@ -1053,6 +1054,8 @@ private: ReturnValue_t switchCookieChannel(object_id_t newChannelId); ReturnValue_t handleDeviceHandlerMessage(CommandMessage *message); + + }; #endif /* DEVICEHANDLERBASE_H_ */ diff --git a/serialize/SerializeAdapter.h b/serialize/SerializeAdapter.h index 6e2f3e5f..04216c89 100644 --- a/serialize/SerializeAdapter.h +++ b/serialize/SerializeAdapter.h @@ -20,11 +20,31 @@ * * 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. * - * In the SOURCE mission , the target architecture is little endian, - * so any buffers must be deSerialized with bool bigEndian = false if - * the parameters are used in the FSFW. - * When serializing for downlink, the packets are generally serialized into big endian for the network when using a TC/UDP client + * 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: + * + * 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 diff --git a/serialize/SerializeIF.h b/serialize/SerializeIF.h index 14f6995e..d86349ab 100644 --- a/serialize/SerializeIF.h +++ b/serialize/SerializeIF.h @@ -11,10 +11,16 @@ /** * An interface for alle classes which require translation of objects data into data streams and vice-versa. * - * In the SOURCE mission , the target architecture is little endian, - * so any buffers must be deSerialized with bool bigEndian = false if - * the parameters are used in the FSFW. - * When serializing for downlink, the packets are generally serialized into big endian for the network when using a TC/UDP client + * 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 @c AutoSerializeAdapter::deSerialize function with @c bigEndian = true + * 2. Perform a bitshift operation + * 3. @c memcpy can be used when data is little-endian. Otherwise, @c EndianSwapper has to be used. + * + * When serializing for downlink, the packets are generally serialized assuming big endian data format * like seen in TmPacketStored.cpp for example. * * \ingroup serialize diff --git a/tmtcservices/PusServiceBase.h b/tmtcservices/PusServiceBase.h index 782d375f..4fe13ca9 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(); From d79f072851264ec3f9e369f2b2ccbfa7fddd3145 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 27 Oct 2019 13:38:08 +0100 Subject: [PATCH 2/4] Additional documentation for DHB and CSB --- devicehandlers/DeviceHandlerBase.h | 19 ++++++---- tmtcservices/CommandingServiceBase.h | 54 +++++++++++++++++++++++++--- 2 files changed, 62 insertions(+), 11 deletions(-) diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 6abfb675..be488d35 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -33,24 +33,29 @@ class StorageManagerIF; * Contains all devices and the DeviceHandlerBase class. */ -// Robin: We're not really using RMAP, right? Maybe we should adapt class description for that? + /** * \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 */ diff --git a/tmtcservices/CommandingServiceBase.h b/tmtcservices/CommandingServiceBase.h index ee59ffe4..f662072f 100644 --- a/tmtcservices/CommandingServiceBase.h +++ b/tmtcservices/CommandingServiceBase.h @@ -180,20 +180,65 @@ 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 determines how CommandServiceBase proceeds + * @param previousCommand + * @param state + * @param optionalNextCommand + * @param objectId + * @param isStep Flag value to mark steps of command execution + * @return + */ 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 +254,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 From b51536c772c9d058b7c7a4449f8cf8ca107773ec Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 28 Oct 2019 12:48:41 +0100 Subject: [PATCH 3/4] CSB doc correction --- fdir/FailureIsolationBase.h | 4 ++++ tmtcservices/CommandingServiceBase.h | 8 +++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/fdir/FailureIsolationBase.h b/fdir/FailureIsolationBase.h index cd582e39..894f6356 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/tmtcservices/CommandingServiceBase.h b/tmtcservices/CommandingServiceBase.h index f662072f..8ce25f00 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 @@ -226,13 +226,15 @@ protected: * 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 determines how CommandServiceBase 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 + * @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, From 1ee445ce245b0383a3d770b44f971693ff37542f Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Oct 2019 11:17:07 +0100 Subject: [PATCH 4/4] fifo typo --- container/FIFO.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/container/FIFO.h b/container/FIFO.h index 670a50d7..134da9b8 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];